mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-11 18:33:14 +01:00
Merge wilsonk's x86-64 inline assembly.
This commit is contained in:
@@ -890,7 +890,6 @@ struct AsmStatement : Statement
|
||||
unsigned asmalign; // alignment of this statement
|
||||
unsigned refparam; // !=0 if function parameter is referenced
|
||||
unsigned naked; // !=0 if function is to be naked
|
||||
unsigned regs; // mask of registers modified
|
||||
|
||||
AsmStatement(Loc loc, Token *tokens);
|
||||
Statement *syntaxCopy();
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#include "id.h"
|
||||
|
||||
namespace AsmParserx8632 {
|
||||
|
||||
typedef enum {
|
||||
Reg_Invalid = -1,
|
||||
Reg_EAX = 0,
|
||||
@@ -17,7 +19,6 @@ typedef enum {
|
||||
Reg_ST1, Reg_ST2, Reg_ST3, Reg_ST4, Reg_ST5, Reg_ST6, Reg_ST7,
|
||||
Reg_MM0, Reg_MM1, Reg_MM2, Reg_MM3, Reg_MM4, Reg_MM5, Reg_MM6, Reg_MM7,
|
||||
Reg_XMM0, Reg_XMM1, Reg_XMM2, Reg_XMM3, Reg_XMM4, Reg_XMM5, Reg_XMM6, Reg_XMM7,
|
||||
// will need 64-bit rax,etc. eventually
|
||||
// xmm8-15?
|
||||
Reg_EFLAGS,
|
||||
Reg_CS,
|
||||
@@ -1348,7 +1349,7 @@ struct AsmProcessor
|
||||
// }
|
||||
|
||||
if ( matchOperands(operand_i) ) {
|
||||
AsmCode * asmcode = new AsmCode;
|
||||
AsmCode * asmcode = new AsmCode(N_Regs);
|
||||
|
||||
if (formatInstruction(operand_i, asmcode))
|
||||
stmt->asmcode = (code *) asmcode;
|
||||
@@ -1356,7 +1357,7 @@ struct AsmProcessor
|
||||
}
|
||||
|
||||
void setAsmCode() {
|
||||
AsmCode * asmcode = new AsmCode;
|
||||
AsmCode * asmcode = new AsmCode(N_Regs);
|
||||
asmcode->insnTemplateLen = insnTemplate->offset;
|
||||
asmcode->insnTemplate = (char*) insnTemplate->extractData();
|
||||
stmt->asmcode = (code*) asmcode;
|
||||
@@ -1693,12 +1694,12 @@ struct AsmProcessor
|
||||
switch (opInfo->implicitClobbers & Clb_DXAX_Mask) {
|
||||
case Clb_SizeAX:
|
||||
case Clb_EAX:
|
||||
stmt->regs |= (1<<Reg_EAX);
|
||||
asmcode->regs[Reg_EAX] = true;
|
||||
break;
|
||||
case Clb_SizeDXAX:
|
||||
stmt->regs |= (1<<Reg_EAX);
|
||||
asmcode->regs[Reg_EAX] = true;
|
||||
if (type_char != 'b')
|
||||
stmt->regs |= (1<<Reg_EDX);
|
||||
asmcode->regs[Reg_EDX] = true;
|
||||
break;
|
||||
default:
|
||||
// nothing
|
||||
@@ -1706,13 +1707,13 @@ struct AsmProcessor
|
||||
}
|
||||
|
||||
if (opInfo->implicitClobbers & Clb_DI)
|
||||
stmt->regs |= (1 << Reg_EDI);
|
||||
asmcode->regs[Reg_EDI] = true;
|
||||
if (opInfo->implicitClobbers & Clb_SI)
|
||||
stmt->regs |= (1 << Reg_ESI);
|
||||
asmcode->regs[Reg_ESI] = true;
|
||||
if (opInfo->implicitClobbers & Clb_CX)
|
||||
stmt->regs |= (1 << Reg_ECX);
|
||||
asmcode->regs[Reg_ECX] = true;
|
||||
if (opInfo->implicitClobbers & Clb_SP)
|
||||
stmt->regs |= (1 << Reg_ESP);
|
||||
asmcode->regs[Reg_ESP] = true;
|
||||
if (opInfo->implicitClobbers & Clb_ST)
|
||||
{
|
||||
/* Can't figure out how to tell GCC that an
|
||||
@@ -1720,20 +1721,22 @@ struct AsmProcessor
|
||||
Maybe if the statment had and input or output
|
||||
operand it would work... In any case, clobbering
|
||||
all FP prevents incorrect code generation. */
|
||||
stmt->regs |= (1 << Reg_ST);
|
||||
stmt->regs |= (1 << Reg_ST1);
|
||||
stmt->regs |= (1 << Reg_ST2);
|
||||
stmt->regs |= (1 << Reg_ST3);
|
||||
stmt->regs |= (1 << Reg_ST4);
|
||||
stmt->regs |= (1 << Reg_ST5);
|
||||
stmt->regs |= (1 << Reg_ST6);
|
||||
stmt->regs |= (1 << Reg_ST7);
|
||||
asmcode->regs[Reg_ST] = true;
|
||||
asmcode->regs[Reg_ST1] = true;
|
||||
asmcode->regs[Reg_ST2] = true;
|
||||
asmcode->regs[Reg_ST3] = true;
|
||||
asmcode->regs[Reg_ST4] = true;
|
||||
asmcode->regs[Reg_ST5] = true;
|
||||
asmcode->regs[Reg_ST6] = true;
|
||||
asmcode->regs[Reg_ST7] = true;
|
||||
}
|
||||
if (opInfo->implicitClobbers & Clb_Flags)
|
||||
asmcode->moreRegs |= (1 << (Reg_EFLAGS - 32));
|
||||
if (op == Op_cpuid)
|
||||
stmt->regs |= (1 << Reg_EAX)|
|
||||
(1 << Reg_ECX)|(1 << Reg_EDX);
|
||||
asmcode->regs[Reg_EFLAGS] = true;
|
||||
if (op == Op_cpuid) {
|
||||
asmcode->regs[Reg_EAX] = true;
|
||||
asmcode->regs[Reg_ECX] = true;
|
||||
asmcode->regs[Reg_EDX] = true;
|
||||
}
|
||||
|
||||
insnTemplate->writebyte(' ');
|
||||
for (int i__ = 0; i__ < nOperands; i__++) {
|
||||
@@ -1806,10 +1809,7 @@ struct AsmProcessor
|
||||
if (opInfo->operands[i] & Opr_Dest) {
|
||||
Reg clbr_reg = (Reg) regInfo[operand->reg].baseReg;
|
||||
if (clbr_reg != Reg_Invalid) {
|
||||
if (clbr_reg < 32)
|
||||
stmt->regs |= (1 << clbr_reg);
|
||||
else
|
||||
asmcode->moreRegs |= (1 << (clbr_reg - 32));
|
||||
asmcode->regs[clbr_reg] = true;
|
||||
}
|
||||
}
|
||||
if (opTakesLabel()/*opInfo->takesLabel()*/)
|
||||
@@ -2636,6 +2636,7 @@ struct AsmProcessor
|
||||
#define HOST_WIDE_INT long
|
||||
bool getFrameRelativeValue(LLValue* decl, HOST_WIDE_INT * result)
|
||||
{
|
||||
assert(0);
|
||||
// FIXME
|
||||
// // Using this instead of DECL_RTL for struct args seems like a
|
||||
// // good way to get hit by a truck because it may not agree with
|
||||
@@ -2668,3 +2669,18 @@ bool getFrameRelativeValue(LLValue* decl, HOST_WIDE_INT * result)
|
||||
//
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
struct AsmParser : public AsmParserCommon
|
||||
{
|
||||
virtual void run(Scope* sc, AsmStatement* asmst) {
|
||||
AsmProcessor ap(sc, asmst);
|
||||
ap.run();
|
||||
}
|
||||
|
||||
virtual std::string getRegName(int i) {
|
||||
return regInfo[i].gccName;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
2807
gen/asm-x86-64.h
Normal file
2807
gen/asm-x86-64.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -57,13 +57,13 @@ struct AsmCode {
|
||||
char * insnTemplate;
|
||||
unsigned insnTemplateLen;
|
||||
Array args; // of AsmArg
|
||||
unsigned moreRegs;
|
||||
std::vector<bool> regs;
|
||||
unsigned dollarLabel;
|
||||
int clobbersMemory;
|
||||
AsmCode() {
|
||||
AsmCode(int n_regs) {
|
||||
insnTemplate = NULL;
|
||||
insnTemplateLen = 0;
|
||||
moreRegs = 0;
|
||||
regs.resize(n_regs, false);
|
||||
dollarLabel = 0;
|
||||
clobbersMemory = 0;
|
||||
}
|
||||
@@ -77,7 +77,6 @@ AsmStatement::AsmStatement(Loc loc, Token *tokens) :
|
||||
asmalign = 0;
|
||||
refparam = 0;
|
||||
naked = 0;
|
||||
regs = 0;
|
||||
|
||||
isBranchToLabel = NULL;
|
||||
}
|
||||
@@ -89,7 +88,6 @@ Statement *AsmStatement::syntaxCopy()
|
||||
a_s->asmcode = asmcode;
|
||||
a_s->refparam = refparam;
|
||||
a_s->naked = naked;
|
||||
a_s->regs = a_s->regs;
|
||||
return a_s;
|
||||
}
|
||||
|
||||
@@ -130,15 +128,22 @@ int AsmStatement::comeFrom()
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
struct AsmParserCommon
|
||||
{
|
||||
virtual void run(Scope* sc, AsmStatement* asmst) = 0;
|
||||
virtual std::string getRegName(int i) = 0;
|
||||
};
|
||||
AsmParserCommon* asmparser = NULL;
|
||||
|
||||
#include "d-asm-i386.h"
|
||||
#include "asm-x86-32.h"
|
||||
#include "asm-x86-64.h"
|
||||
|
||||
bool d_have_inline_asm() { return true; }
|
||||
|
||||
Statement *AsmStatement::semantic(Scope *sc)
|
||||
{
|
||||
bool err = false;
|
||||
if (global.params.cpu != ARCHx86)
|
||||
if ((global.params.cpu != ARCHx86) && (global.params.cpu != ARCHx86_64))
|
||||
{
|
||||
error("inline asm is not supported for the \"%s\" architecture", global.params.llvmArch);
|
||||
err = true;
|
||||
@@ -160,8 +165,14 @@ Statement *AsmStatement::semantic(Scope *sc)
|
||||
if (! tokens)
|
||||
return this;
|
||||
|
||||
AsmProcessor ap(sc, this);
|
||||
ap.run();
|
||||
if (!asmparser)
|
||||
if (global.params.cpu == ARCHx86)
|
||||
asmparser = new AsmParserx8632::AsmParser;
|
||||
else if (global.params.cpu == ARCHx86_64)
|
||||
asmparser = new AsmParserx8664::AsmParser;
|
||||
|
||||
asmparser->run(sc, this);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -251,7 +262,7 @@ assert(0);
|
||||
/* if (arg->expr->op == TOKvar)
|
||||
arg_val = ((VarExp *) arg->expr)->var->toSymbol()->Stree;
|
||||
else
|
||||
assert(0);*/
|
||||
assert(0);
|
||||
if ( getFrameRelativeValue(arg_val, & var_frame_offset) ) {
|
||||
// arg_val = irs->integerConstant(var_frame_offset);
|
||||
cns = i_cns;
|
||||
@@ -261,7 +272,7 @@ assert(0);
|
||||
}
|
||||
if (arg->mode != Mode_Input)
|
||||
clobbers_mem = true;
|
||||
break;
|
||||
break;*/
|
||||
case Arg_LocalSize:
|
||||
// FIXME
|
||||
std::cout << "asm fixme Arg_LocalSize" << std::endl;
|
||||
@@ -294,16 +305,11 @@ assert(0);
|
||||
|
||||
// FIXME
|
||||
// if (! irs->func->naked) {
|
||||
for (int i = 0; i < 32; i++) {
|
||||
if (regs & (1 << i)) {
|
||||
assert(asmparser);
|
||||
for (int i = 0; i < code->regs.size(); i++) {
|
||||
if (code->regs[i]) {
|
||||
//clobbers.cons(NULL_TREE, regInfo[i].gccName);
|
||||
clobbers.push_back(regInfo[i].gccName);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 32; i++) {
|
||||
if (code->moreRegs & (1 << (i-32))) {
|
||||
//clobbers.cons(NULL_TREE, regInfo[i].gccName);
|
||||
clobbers.push_back(regInfo[i].gccName);
|
||||
clobbers.push_back(asmparser->getRegName(i));
|
||||
}
|
||||
}
|
||||
if (clobbers_mem)
|
||||
|
||||
@@ -4,7 +4,7 @@ extern(C) int printf(char*, ...);
|
||||
|
||||
void main()
|
||||
{
|
||||
version(D_InlineAsm_X86)
|
||||
version(LLVM_InlineAsm_X86)
|
||||
{
|
||||
int x;
|
||||
asm
|
||||
|
||||
Reference in New Issue
Block a user