Merge wilsonk's x86-64 inline assembly.

This commit is contained in:
Christian Kamm
2008-11-08 22:29:19 +01:00
parent d41bcb5312
commit bc80a83666
5 changed files with 2876 additions and 48 deletions

View File

@@ -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();

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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)

View File

@@ -4,7 +4,7 @@ extern(C) int printf(char*, ...);
void main()
{
version(D_InlineAsm_X86)
version(LLVM_InlineAsm_X86)
{
int x;
asm