From: Julian Seward Date: Tue, 1 Feb 2005 20:30:00 +0000 (+0000) Subject: Get the AMD64 back-end show on the road. X-Git-Tag: svn/VALGRIND_3_0_1^2~524 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e7a93c45b1df3f8cf0a86429752b5285fb22c650;p=thirdparty%2Fvalgrind.git Get the AMD64 back-end show on the road. git-svn-id: svn://svn.valgrind.org/vex/trunk@810 --- diff --git a/VEX/priv/host-amd64/hdefs.c b/VEX/priv/host-amd64/hdefs.c index c261e81444..e47f34abeb 100644 --- a/VEX/priv/host-amd64/hdefs.c +++ b/VEX/priv/host-amd64/hdefs.c @@ -37,15 +37,15 @@ #include "libvex.h" #include "libvex_trc_values.h" -//.. #include "main/vex_util.h" -//.. #include "host-generic/h_generic_regs.h" -//.. #include "host-x86/hdefs.h" -//.. -//.. -//.. /* --------- Registers. --------- */ -//.. -//.. void ppHRegX86 ( HReg reg ) -//.. { +#include "main/vex_util.h" +#include "host-generic/h_generic_regs.h" +#include "host-amd64/hdefs.h" + + +/* --------- Registers. --------- */ + +void ppHRegAMD64 ( HReg reg ) +{ vassert(0); //.. Int r; //.. static HChar* ireg32_names[8] //.. = { "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi" }; @@ -74,8 +74,8 @@ //.. default: //.. vpanic("ppHRegX86"); //.. } -//.. } -//.. +} + //.. HReg hregX86_EAX ( void ) { return mkHReg(0, HRcInt32, False); } //.. HReg hregX86_ECX ( void ) { return mkHReg(1, HRcInt32, False); } //.. HReg hregX86_EDX ( void ) { return mkHReg(2, HRcInt32, False); } @@ -100,10 +100,10 @@ //.. HReg hregX86_XMM5 ( void ) { return mkHReg(5, HRcVec128, False); } //.. HReg hregX86_XMM6 ( void ) { return mkHReg(6, HRcVec128, False); } //.. HReg hregX86_XMM7 ( void ) { return mkHReg(7, HRcVec128, False); } -//.. -//.. -//.. void getAllocableRegs_X86 ( Int* nregs, HReg** arr ) -//.. { + + +void getAllocableRegs_AMD64 ( Int* nregs, HReg** arr ) +{ *nregs= 0; *arr=NULL; //.. *nregs = 20; //.. *arr = LibVEX_Alloc(*nregs * sizeof(HReg)); //.. (*arr)[0] = hregX86_EAX(); @@ -126,9 +126,9 @@ //.. (*arr)[17] = hregX86_XMM5(); //.. (*arr)[18] = hregX86_XMM6(); //.. (*arr)[19] = hregX86_XMM7(); -//.. } -//.. -//.. +} + + //.. /* --------- Condition codes, Intel encoding. --------- */ //.. //.. HChar* showX86CondCode ( X86CondCode cond ) @@ -878,9 +878,10 @@ //.. vassert(order >= 0 && order <= 0xFF); //.. return i; //.. } -//.. -//.. void ppX86Instr ( X86Instr* i ) { -//.. switch (i->tag) { + +void ppAMD64Instr ( AMD64Instr* i ) +{ + switch (i->tag) { //.. case Xin_Alu32R: //.. vex_printf("%sl ", showX86AluOp(i->Xin.Alu32R.op)); //.. ppX86RMI(i->Xin.Alu32R.src); @@ -1128,19 +1129,19 @@ //.. vex_printf(","); //.. ppHRegX86(i->Xin.SseShuf.dst); //.. return; -//.. -//.. default: -//.. vpanic("ppX86Instr"); -//.. } -//.. } -//.. -//.. /* --------- Helpers for register allocation. --------- */ -//.. -//.. void getRegUsage_X86Instr (HRegUsage* u, X86Instr* i) -//.. { -//.. Bool unary; -//.. initHRegUsage(u); -//.. switch (i->tag) { + + default: + vpanic("ppAMD64Instr"); + } +} + +/* --------- Helpers for register allocation. --------- */ + +void getRegUsage_AMD64Instr ( HRegUsage* u, AMD64Instr* i ) +{ + // Bool unary; + initHRegUsage(u); + switch (i->tag) { //.. case Xin_Alu32R: //.. addRegUsage_X86RMI(u, i->Xin.Alu32R.src); //.. if (i->Xin.Alu32R.op == Xalu_MOV) { @@ -1355,21 +1356,21 @@ //.. addHRegUse(u, HRmRead, i->Xin.SseShuf.src); //.. addHRegUse(u, HRmWrite, i->Xin.SseShuf.dst); //.. return; -//.. default: -//.. ppX86Instr(i); -//.. vpanic("getRegUsage_X86Instr"); -//.. } -//.. } + default: + ppAMD64Instr(i); + vpanic("getRegUsage_AMD64Instr"); + } +} //.. //.. /* local helper */ //.. static void mapReg(HRegRemap* m, HReg* r) //.. { //.. *r = lookupHRegRemap(m, *r); //.. } -//.. -//.. void mapRegs_X86Instr (HRegRemap* m, X86Instr* i) -//.. { -//.. switch (i->tag) { + +void mapRegs_AMD64Instr ( HRegRemap* m, AMD64Instr* i ) +{ + switch (i->tag) { //.. case Xin_Alu32R: //.. mapRegs_X86RMI(m, i->Xin.Alu32R.src); //.. mapReg(m, &i->Xin.Alu32R.dst); @@ -1501,18 +1502,18 @@ //.. mapReg(m, &i->Xin.SseShuf.src); //.. mapReg(m, &i->Xin.SseShuf.dst); //.. return; -//.. default: -//.. ppX86Instr(i); -//.. vpanic("mapRegs_X86Instr"); -//.. } -//.. } -//.. -//.. /* Figure out if i represents a reg-reg move, and if so assign the -//.. source and destination to *src and *dst. If in doubt say No. Used -//.. by the register allocator to do move coalescing. -//.. */ -//.. Bool isMove_X86Instr ( X86Instr* i, HReg* src, HReg* dst ) -//.. { + default: + ppAMD64Instr(i); + vpanic("mapRegs_AMD64Instr"); + } +} + +/* Figure out if i represents a reg-reg move, and if so assign the + source and destination to *src and *dst. If in doubt say No. Used + by the register allocator to do move coalescing. +*/ +Bool isMove_AMD64Instr ( AMD64Instr* i, HReg* src, HReg* dst ) +{ //.. /* Moves between integer regs */ //.. if (i->tag == Xin_Alu32R) { //.. if (i->Xin.Alu32R.op != Xalu_MOV) @@ -1538,16 +1539,16 @@ //.. *dst = i->Xin.SseReRg.dst; //.. return True; //.. } -//.. return False; -//.. } -//.. -//.. -//.. /* Generate x86 spill/reload instructions under the direction of the -//.. register allocator. Note it's critical these don't write the -//.. condition codes. */ -//.. -//.. X86Instr* genSpill_X86 ( HReg rreg, Int offsetB ) -//.. { + return False; +} + + +/* Generate amd64 spill/reload instructions under the direction of the + register allocator. Note it's critical these don't write the + condition codes. */ + +AMD64Instr* genSpill_AMD64 ( HReg rreg, Int offsetB ) +{vassert(0); //.. X86AMode* am; //.. vassert(offsetB >= 0); //.. vassert(!hregIsVirtual(rreg)); @@ -1564,10 +1565,10 @@ //.. ppHRegClass(hregClass(rreg)); //.. vpanic("genSpill_X86: unimplemented regclass"); //.. } -//.. } -//.. -//.. X86Instr* genReload_X86 ( HReg rreg, Int offsetB ) -//.. { +} + +AMD64Instr* genReload_AMD64 ( HReg rreg, Int offsetB ) +{vassert(0); //.. X86AMode* am; //.. vassert(offsetB >= 0); //.. vassert(!hregIsVirtual(rreg)); @@ -1583,9 +1584,9 @@ //.. ppHRegClass(hregClass(rreg)); //.. vpanic("genReload_X86: unimplemented regclass"); //.. } -//.. } -//.. -//.. +} + + //.. /* --------- The x86 assembler (bleh.) --------- */ //.. //.. static UInt iregNo ( HReg r ) @@ -1827,17 +1828,17 @@ //.. } //.. return p; //.. } -//.. -//.. /* Emit an instruction into buf and return the number of bytes used. -//.. Note that buf is not the insn's final place, and therefore it is -//.. imperative to emit position-independent code. */ -//.. -//.. Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i ) -//.. { -//.. UInt irno, opc, opc_rr, subopc_imm, opc_imma, opc_cl, opc_imm, subopc; + +/* Emit an instruction into buf and return the number of bytes used. + Note that buf is not the insn's final place, and therefore it is + imperative to emit position-independent code. */ + +Int emit_AMD64Instr ( UChar* buf, Int nbuf, AMD64Instr* i ) +{ + // UInt irno, opc, opc_rr, subopc_imm, opc_imma, opc_cl, opc_imm, subopc; //.. //.. UInt xtra; -//.. UChar* p = &buf[0]; + UChar* p = &buf[0]; //.. UChar* ptmp; //.. vassert(nbuf >= 32); //.. @@ -1847,9 +1848,9 @@ //.. # define fake(_n) mkHReg((_n), HRcInt32, False) //.. //.. /* vex_printf("asm ");ppX86Instr(i); vex_printf("\n"); */ -//.. -//.. switch (i->tag) { -//.. + + switch (i->tag) { + //.. case Xin_Alu32R: //.. /* Deal specially with MOV */ //.. if (i->Xin.Alu32R.op == Xalu_MOV) { @@ -2839,21 +2840,21 @@ //.. *p++ = (UChar)(i->Xin.SseShuf.order); //.. goto done; //.. -//.. default: -//.. goto bad; -//.. } -//.. -//.. bad: -//.. ppX86Instr(i); -//.. vpanic("emit_X86Instr"); -//.. /*NOTREACHED*/ -//.. -//.. done: -//.. vassert(p - &buf[0] <= 32); -//.. return p - &buf[0]; -//.. -//.. # undef fake -//.. } + default: + goto bad; + } + + bad: + ppAMD64Instr(i); + vpanic("emit_AMD64Instr"); + /*NOTREACHED*/ + + // done: + vassert(p - &buf[0] <= 32); + return p - &buf[0]; + +# undef fake +} /*---------------------------------------------------------------*/ /*--- end host-amd64/hdefs.c ---*/ diff --git a/VEX/priv/host-amd64/hdefs.h b/VEX/priv/host-amd64/hdefs.h index 4cfb4ae78d..53cbcb5381 100644 --- a/VEX/priv/host-amd64/hdefs.h +++ b/VEX/priv/host-amd64/hdefs.h @@ -36,206 +36,222 @@ #ifndef __LIBVEX_HOST_AMD64_HDEFS_H #define __LIBVEX_HOST_AMD64_HDEFS_H -//.. -//.. /* --------- Registers. --------- */ -//.. -//.. /* The usual HReg abstraction. There are 8 real int regs, -//.. 6 real float regs, and 0 real vector regs. -//.. */ -//.. -//.. extern void ppHRegX86 ( HReg ); -//.. -//.. extern HReg hregX86_EAX ( void ); -//.. extern HReg hregX86_EBX ( void ); -//.. extern HReg hregX86_ECX ( void ); -//.. extern HReg hregX86_EDX ( void ); -//.. extern HReg hregX86_ESP ( void ); -//.. extern HReg hregX86_EBP ( void ); -//.. extern HReg hregX86_ESI ( void ); -//.. extern HReg hregX86_EDI ( void ); -//.. -//.. extern HReg hregX86_FAKE0 ( void ); -//.. extern HReg hregX86_FAKE1 ( void ); -//.. extern HReg hregX86_FAKE2 ( void ); -//.. extern HReg hregX86_FAKE3 ( void ); -//.. extern HReg hregX86_FAKE4 ( void ); -//.. extern HReg hregX86_FAKE5 ( void ); -//.. -//.. extern HReg hregX86_XMM0 ( void ); -//.. extern HReg hregX86_XMM1 ( void ); -//.. extern HReg hregX86_XMM2 ( void ); -//.. extern HReg hregX86_XMM3 ( void ); -//.. extern HReg hregX86_XMM4 ( void ); -//.. extern HReg hregX86_XMM5 ( void ); -//.. extern HReg hregX86_XMM6 ( void ); -//.. extern HReg hregX86_XMM7 ( void ); -//.. -//.. -//.. /* --------- Condition codes, Intel encoding. --------- */ -//.. -//.. typedef -//.. enum { -//.. Xcc_O = 0, /* overflow */ -//.. Xcc_NO = 1, /* no overflow */ -//.. -//.. Xcc_B = 2, /* below */ -//.. Xcc_NB = 3, /* not below */ -//.. -//.. Xcc_Z = 4, /* zero */ -//.. Xcc_NZ = 5, /* not zero */ -//.. -//.. Xcc_BE = 6, /* below or equal */ -//.. Xcc_NBE = 7, /* not below or equal */ -//.. -//.. Xcc_S = 8, /* negative */ -//.. Xcc_NS = 9, /* not negative */ -//.. -//.. Xcc_P = 10, /* parity even */ -//.. Xcc_NP = 11, /* not parity even */ -//.. -//.. Xcc_L = 12, /* jump less */ -//.. Xcc_NL = 13, /* not less */ -//.. -//.. Xcc_LE = 14, /* less or equal */ -//.. Xcc_NLE = 15, /* not less or equal */ -//.. -//.. Xcc_ALWAYS = 16 /* the usual hack */ -//.. } -//.. X86CondCode; -//.. -//.. extern HChar* showX86CondCode ( X86CondCode ); -//.. -//.. -//.. /* --------- Memory address expressions (amodes). --------- */ -//.. -//.. typedef -//.. enum { -//.. Xam_IR, /* Immediate + Reg */ -//.. Xam_IRRS /* Immediate + Reg1 + (Reg2 << Shift) */ -//.. } -//.. X86AModeTag; -//.. -//.. typedef -//.. struct { -//.. X86AModeTag tag; -//.. union { -//.. struct { -//.. UInt imm; -//.. HReg reg; -//.. } IR; -//.. struct { -//.. UInt imm; -//.. HReg base; -//.. HReg index; -//.. Int shift; /* 0, 1, 2 or 3 only */ -//.. } IRRS; -//.. } Xam; -//.. } -//.. X86AMode; -//.. -//.. extern X86AMode* X86AMode_IR ( UInt, HReg ); -//.. extern X86AMode* X86AMode_IRRS ( UInt, HReg, HReg, Int ); -//.. -//.. extern X86AMode* dopyX86AMode ( X86AMode* ); -//.. -//.. extern void ppX86AMode ( X86AMode* ); -//.. -//.. -//.. /* --------- Operand, which can be reg, immediate or memory. --------- */ -//.. -//.. typedef -//.. enum { -//.. Xrmi_Imm, -//.. Xrmi_Reg, -//.. Xrmi_Mem -//.. } -//.. X86RMITag; -//.. -//.. typedef -//.. struct { -//.. X86RMITag tag; -//.. union { -//.. struct { -//.. UInt imm32; -//.. } Imm; -//.. struct { -//.. HReg reg; -//.. } Reg; -//.. struct { -//.. X86AMode* am; -//.. } Mem; -//.. } -//.. Xrmi; -//.. } -//.. X86RMI; -//.. -//.. extern X86RMI* X86RMI_Imm ( UInt ); -//.. extern X86RMI* X86RMI_Reg ( HReg ); -//.. extern X86RMI* X86RMI_Mem ( X86AMode* ); -//.. -//.. extern void ppX86RMI ( X86RMI* ); -//.. -//.. -//.. /* --------- Operand, which can be reg or immediate only. --------- */ -//.. -//.. typedef -//.. enum { -//.. Xri_Imm, -//.. Xri_Reg -//.. } -//.. X86RITag; -//.. -//.. typedef -//.. struct { -//.. X86RITag tag; -//.. union { -//.. struct { -//.. UInt imm32; -//.. } Imm; -//.. struct { -//.. HReg reg; -//.. } Reg; -//.. } -//.. Xri; -//.. } -//.. X86RI; -//.. -//.. extern X86RI* X86RI_Imm ( UInt ); -//.. extern X86RI* X86RI_Reg ( HReg ); -//.. -//.. extern void ppX86RI ( X86RI* ); -//.. -//.. -//.. /* --------- Operand, which can be reg or memory only. --------- */ -//.. -//.. typedef -//.. enum { -//.. Xrm_Reg, -//.. Xrm_Mem -//.. } -//.. X86RMTag; -//.. -//.. typedef -//.. struct { -//.. X86RMTag tag; -//.. union { -//.. struct { -//.. HReg reg; -//.. } Reg; -//.. struct { -//.. X86AMode* am; -//.. } Mem; -//.. } -//.. Xrm; -//.. } -//.. X86RM; -//.. -//.. extern X86RM* X86RM_Reg ( HReg ); -//.. extern X86RM* X86RM_Mem ( X86AMode* ); -//.. -//.. extern void ppX86RM ( X86RM* ); -//.. -//.. + +/* --------- Registers. --------- */ + +/* The usual HReg abstraction. There are 16 real int regs, 6 real + float regs, and 16 real vector regs. +*/ + +extern void ppHRegAMD64 ( HReg ); + +extern HReg hregAMD64_RAX ( void ); +extern HReg hregAMD64_RBX ( void ); +extern HReg hregAMD64_RCX ( void ); +extern HReg hregAMD64_RDX ( void ); +extern HReg hregAMD64_RSP ( void ); +extern HReg hregAMD64_RBP ( void ); +extern HReg hregAMD64_RSI ( void ); +extern HReg hregAMD64_RDI ( void ); +extern HReg hregAMD64_R8 ( void ); +extern HReg hregAMD64_R9 ( void ); +extern HReg hregAMD64_R10 ( void ); +extern HReg hregAMD64_R11 ( void ); +extern HReg hregAMD64_R12 ( void ); +extern HReg hregAMD64_R13 ( void ); +extern HReg hregAMD64_R14 ( void ); +extern HReg hregAMD64_R15 ( void ); + +extern HReg hregAMD64_FAKE0 ( void ); +extern HReg hregAMD64_FAKE1 ( void ); +extern HReg hregAMD64_FAKE2 ( void ); +extern HReg hregAMD64_FAKE3 ( void ); +extern HReg hregAMD64_FAKE4 ( void ); +extern HReg hregAMD64_FAKE5 ( void ); + +extern HReg hregAMD64_XMM0 ( void ); +extern HReg hregAMD64_XMM1 ( void ); +extern HReg hregAMD64_XMM2 ( void ); +extern HReg hregAMD64_XMM3 ( void ); +extern HReg hregAMD64_XMM4 ( void ); +extern HReg hregAMD64_XMM5 ( void ); +extern HReg hregAMD64_XMM6 ( void ); +extern HReg hregAMD64_XMM7 ( void ); +extern HReg hregAMD64_XMM8 ( void ); +extern HReg hregAMD64_XMM9 ( void ); +extern HReg hregAMD64_XMM10 ( void ); +extern HReg hregAMD64_XMM11 ( void ); +extern HReg hregAMD64_XMM12 ( void ); +extern HReg hregAMD64_XMM13 ( void ); +extern HReg hregAMD64_XMM14 ( void ); +extern HReg hregAMD64_XMM15 ( void ); + + +/* --------- Condition codes, AMD encoding. --------- */ + +typedef + enum { + Acc_O = 0, /* overflow */ + Acc_NO = 1, /* no overflow */ + + Acc_B = 2, /* below */ + Acc_NB = 3, /* not below */ + + Acc_Z = 4, /* zero */ + Acc_NZ = 5, /* not zero */ + + Acc_BE = 6, /* below or equal */ + Acc_NBE = 7, /* not below or equal */ + + Acc_S = 8, /* negative */ + Acc_NS = 9, /* not negative */ + + Acc_P = 10, /* parity even */ + Acc_NP = 11, /* not parity even */ + + Acc_L = 12, /* jump less */ + Acc_NL = 13, /* not less */ + + Acc_LE = 14, /* less or equal */ + Acc_NLE = 15, /* not less or equal */ + + Acc_ALWAYS = 16 /* the usual hack */ + } + AMD64CondCode; + +extern HChar* showAMD64CondCode ( AMD64CondCode ); + + +/* --------- Memory address expressions (amodes). --------- */ + +typedef + enum { + Aam_IR, /* Immediate + Reg */ + Aam_IRRS /* Immediate + Reg1 + (Reg2 << Shift) */ + } + AMD64AModeTag; + +typedef + struct { + AMD64AModeTag tag; + union { + struct { + UInt imm; + HReg reg; + } IR; + struct { + UInt imm; + HReg base; + HReg index; + Int shift; /* 0, 1, 2 or 3 only */ + } IRRS; + } Aam; + } + AMD64AMode; + +extern AMD64AMode* AMD64AMode_IR ( UInt, HReg ); +extern AMD64AMode* AMD64AMode_IRRS ( UInt, HReg, HReg, Int ); + +extern AMD64AMode* dopyAMD64AMode ( AMD64AMode* ); + +extern void ppAMD64AMode ( AMD64AMode* ); + + +/* --------- Operand, which can be reg, immediate or memory. --------- */ + +typedef + enum { + Armi_Imm, + Armi_Reg, + Armi_Mem + } + AMD64RMITag; + +typedef + struct { + AMD64RMITag tag; + union { + struct { + UInt imm32; + } Imm; + struct { + HReg reg; + } Reg; + struct { + AMD64AMode* am; + } Mem; + } + Armi; + } + AMD64RMI; + +extern AMD64RMI* AMD64RMI_Imm ( UInt ); +extern AMD64RMI* AMD64RMI_Reg ( HReg ); +extern AMD64RMI* AMD64RMI_Mem ( AMD64AMode* ); + +extern void ppAMD64RMI ( AMD64RMI* ); + + +/* --------- Operand, which can be reg or immediate only. --------- */ + +typedef + enum { + Ari_Imm, + Ari_Reg + } + AMD64RITag; + +typedef + struct { + AMD64RITag tag; + union { + struct { + UInt imm32; + } Imm; + struct { + HReg reg; + } Reg; + } + Ari; + } + AMD64RI; + +extern AMD64RI* AMD64RI_Imm ( UInt ); +extern AMD64RI* AMD64RI_Reg ( HReg ); + +extern void ppAMD64RI ( AMD64RI* ); + + +/* --------- Operand, which can be reg or memory only. --------- */ + +typedef + enum { + Arm_Reg, + Arm_Mem + } + AMD64RMTag; + +typedef + struct { + AMD64RMTag tag; + union { + struct { + HReg reg; + } Reg; + struct { + AMD64AMode* am; + } Mem; + } + Arm; + } + AMD64RM; + +extern AMD64RM* AMD64RM_Reg ( HReg ); +extern AMD64RM* AMD64RM_Mem ( AMD64AMode* ); + +extern void ppAMD64RM ( AMD64RM* ); + + //.. /* --------- Instructions. --------- */ //.. //.. /* --------- */ @@ -344,13 +360,13 @@ //.. X86SseOp; //.. //.. extern HChar* showX86SseOp ( X86SseOp ); -//.. -//.. -//.. /* --------- */ -//.. typedef -//.. enum { -//.. Xin_Alu32R, /* 32-bit mov/arith/logical, dst=REG */ -//.. Xin_Alu32M, /* 32-bit mov/arith/logical, dst=MEM */ + + +/* --------- */ +typedef + enum { + Ain_Alu64R, /* 64-bit mov/arith/logical, dst=REG */ + Ain_Alu64M, /* 64-bit mov/arith/logical, dst=MEM */ //.. Xin_Sh32, /* 32-bit shift/rotate, dst=REG or MEM */ //.. Xin_Test32, /* 32-bit test (AND, set flags, discard result) */ //.. Xin_Unary32, /* 32-bit not and neg */ @@ -387,14 +403,14 @@ //.. Xin_SseReRg, /* SSE binary general reg-reg, Re, Rg */ //.. Xin_SseCMov, /* SSE conditional move */ //.. Xin_SseShuf /* SSE2 shuffle (pshufd) */ -//.. } -//.. X86InstrTag; -//.. -//.. /* Destinations are on the RIGHT (second operand) */ -//.. -//.. typedef -//.. struct { -//.. X86InstrTag tag; + } + AMD64InstrTag; + +/* Destinations are on the RIGHT (second operand) */ + +typedef + struct { + AMD64InstrTag tag; //.. union { //.. struct { //.. X86AluOp op; @@ -615,9 +631,9 @@ //.. } SseShuf; //.. //.. } Xin; -//.. } -//.. X86Instr; -//.. + } + AMD64Instr; + //.. extern X86Instr* X86Instr_Alu32R ( X86AluOp, X86RMI*, HReg ); //.. extern X86Instr* X86Instr_Alu32M ( X86AluOp, X86RI*, X86AMode* ); //.. extern X86Instr* X86Instr_Unary32 ( X86UnaryOp op, X86RM* dst ); @@ -657,20 +673,20 @@ //.. extern X86Instr* X86Instr_SseReRg ( X86SseOp, HReg, HReg ); //.. extern X86Instr* X86Instr_SseCMov ( X86CondCode, HReg src, HReg dst ); //.. extern X86Instr* X86Instr_SseShuf ( Int order, HReg src, HReg dst ); -//.. -//.. -//.. extern void ppX86Instr ( X86Instr* ); -//.. -//.. /* Some functions that insulate the register allocator from details -//.. of the underlying instruction set. */ -//.. extern void getRegUsage_X86Instr ( HRegUsage*, X86Instr* ); -//.. extern void mapRegs_X86Instr ( HRegRemap*, X86Instr* ); -//.. extern Bool isMove_X86Instr ( X86Instr*, HReg*, HReg* ); -//.. extern Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* ); -//.. extern X86Instr* genSpill_X86 ( HReg rreg, Int offset ); -//.. extern X86Instr* genReload_X86 ( HReg rreg, Int offset ); -//.. extern void getAllocableRegs_X86 ( Int*, HReg** ); -//.. extern HInstrArray* iselBB_X86 ( IRBB*, VexSubArch ); + + +extern void ppAMD64Instr ( AMD64Instr* ); + +/* Some functions that insulate the register allocator from details + of the underlying instruction set. */ +extern void getRegUsage_AMD64Instr ( HRegUsage*, AMD64Instr* ); +extern void mapRegs_AMD64Instr ( HRegRemap*, AMD64Instr* ); +extern Bool isMove_AMD64Instr ( AMD64Instr*, HReg*, HReg* ); +extern Int emit_AMD64Instr ( UChar* buf, Int nbuf, AMD64Instr* ); +extern AMD64Instr* genSpill_AMD64 ( HReg rreg, Int offset ); +extern AMD64Instr* genReload_AMD64 ( HReg rreg, Int offset ); +extern void getAllocableRegs_AMD64 ( Int*, HReg** ); +extern HInstrArray* iselBB_AMD64 ( IRBB*, VexSubArch ); #endif /* ndef __LIBVEX_HOST_AMD64_HDEFS_H */ diff --git a/VEX/priv/host-amd64/isel.c b/VEX/priv/host-amd64/isel.c index 14c3d95ed0..27846991e8 100644 --- a/VEX/priv/host-amd64/isel.c +++ b/VEX/priv/host-amd64/isel.c @@ -38,11 +38,11 @@ #include "libvex.h" //.. #include "ir/irmatch.h" -//.. #include "main/vex_util.h" -//.. #include "main/vex_globals.h" -//.. #include "host-generic/h_generic_regs.h" +#include "main/vex_util.h" +#include "main/vex_globals.h" +#include "host-generic/h_generic_regs.h" //.. #include "host-generic/h_generic_simd64.h" -//.. #include "host-x86/hdefs.h" +#include "host-amd64/hdefs.h" //.. //.. //.. /*---------------------------------------------------------*/ @@ -95,64 +95,59 @@ //.. { //.. return IRExpr_Binder(binder); //.. } -//.. -//.. -//.. -//.. /*---------------------------------------------------------*/ -//.. /*--- ISelEnv ---*/ -//.. /*---------------------------------------------------------*/ -//.. -//.. /* This carries around: -//.. -//.. - A mapping from IRTemp to IRType, giving the type of any IRTemp we -//.. might encounter. This is computed before insn selection starts, -//.. and does not change. -//.. -//.. - A mapping from IRTemp to HReg. This tells the insn selector -//.. which virtual register(s) are associated with each IRTemp -//.. temporary. This is computed before insn selection starts, and -//.. does not change. We expect this mapping to map precisely the -//.. same set of IRTemps as the type mapping does. -//.. -//.. - vregmap holds the primary register for the IRTemp. -//.. - vregmapHI is only used for 64-bit integer-typed -//.. IRTemps. It holds the identity of a second -//.. 32-bit virtual HReg, which holds the high half -//.. of the value. -//.. -//.. - The code array, that is, the insns selected so far. -//.. -//.. - A counter, for generating new virtual registers. -//.. -//.. - The host subarchitecture we are selecting insns for. -//.. This is set at the start and does not change. -//.. -//.. Note, this is all host-independent. */ -//.. -//.. typedef -//.. struct { -//.. IRTypeEnv* type_env; -//.. -//.. HReg* vregmap; -//.. HReg* vregmapHI; -//.. Int n_vregmap; -//.. -//.. HInstrArray* code; -//.. -//.. Int vreg_ctr; -//.. -//.. VexSubArch subarch; -//.. } -//.. ISelEnv; -//.. -//.. -//.. static HReg lookupIRTemp ( ISelEnv* env, IRTemp tmp ) -//.. { -//.. vassert(tmp >= 0); -//.. vassert(tmp < env->n_vregmap); -//.. return env->vregmap[tmp]; -//.. } -//.. + + + +/*---------------------------------------------------------*/ +/*--- ISelEnv ---*/ +/*---------------------------------------------------------*/ + +/* This carries around: + + - A mapping from IRTemp to IRType, giving the type of any IRTemp we + might encounter. This is computed before insn selection starts, + and does not change. + + - A mapping from IRTemp to HReg. This tells the insn selector + which virtual register is associated with each IRTemp + temporary. This is computed before insn selection starts, and + does not change. We expect this mapping to map precisely the + same set of IRTemps as the type mapping does. + + - The code array, that is, the insns selected so far. + + - A counter, for generating new virtual registers. + + - The host subarchitecture we are selecting insns for. + This is set at the start and does not change. + + Note, this is all host-independent. (JRS 20050201: well, kinda + ... not completely. Compare with ISelEnv for X86.) +*/ + +typedef + struct { + IRTypeEnv* type_env; + + HReg* vregmap; + Int n_vregmap; + + HInstrArray* code; + + Int vreg_ctr; + + VexSubArch subarch; + } + ISelEnv; + + +static HReg lookupIRTemp ( ISelEnv* env, IRTemp tmp ) +{ + vassert(tmp >= 0); + vassert(tmp < env->n_vregmap); + return env->vregmap[tmp]; +} + //.. static void lookupIRTemp64 ( HReg* vrHI, HReg* vrLO, ISelEnv* env, IRTemp tmp ) //.. { //.. vassert(tmp >= 0); @@ -3123,22 +3118,22 @@ //.. # undef REQUIRE_SSE1 //.. # undef REQUIRE_SSE2 //.. } -//.. -//.. -//.. /*---------------------------------------------------------*/ -//.. /*--- ISEL: Statements ---*/ -//.. /*---------------------------------------------------------*/ -//.. -//.. static void iselStmt ( ISelEnv* env, IRStmt* stmt ) -//.. { -//.. if (vex_traceflags & VEX_TRACE_VCODE) { -//.. vex_printf("\n-- "); -//.. ppIRStmt(stmt); -//.. vex_printf("\n"); -//.. } -//.. -//.. switch (stmt->tag) { -//.. + + +/*---------------------------------------------------------*/ +/*--- ISEL: Statements ---*/ +/*---------------------------------------------------------*/ + +static void iselStmt ( ISelEnv* env, IRStmt* stmt ) +{ + if (vex_traceflags & VEX_TRACE_VCODE) { + vex_printf("\n-- "); + ppIRStmt(stmt); + vex_printf("\n"); + } + + switch (stmt->tag) { + //.. /* --------- STORE --------- */ //.. case Ist_STle: { //.. X86AMode* am; @@ -3369,20 +3364,20 @@ //.. addInstr(env, X86Instr_Goto(stmt->Ist.Exit.jk, cc, dst)); //.. return; //.. } -//.. -//.. default: break; -//.. } -//.. ppIRStmt(stmt); -//.. vpanic("iselStmt"); -//.. } -//.. -//.. -//.. /*---------------------------------------------------------*/ -//.. /*--- ISEL: Basic block terminators (Nexts) ---*/ -//.. /*---------------------------------------------------------*/ -//.. -//.. static void iselNext ( ISelEnv* env, IRExpr* next, IRJumpKind jk ) -//.. { + + default: break; + } + ppIRStmt(stmt); + vpanic("iselStmt(amd64)"); +} + + +/*---------------------------------------------------------*/ +/*--- ISEL: Basic block terminators (Nexts) ---*/ +/*---------------------------------------------------------*/ + +static void iselNext ( ISelEnv* env, IRExpr* next, IRJumpKind jk ) +{vassert(0); //.. X86RI* ri; //.. if (vex_traceflags & VEX_TRACE_VCODE) { //.. vex_printf("\n-- goto {"); @@ -3393,78 +3388,73 @@ //.. } //.. ri = iselIntExpr_RI(env, next); //.. addInstr(env, X86Instr_Goto(jk, Xcc_ALWAYS,ri)); -//.. } -//.. -//.. -//.. /*---------------------------------------------------------*/ -//.. /*--- Insn selector top-level ---*/ -//.. /*---------------------------------------------------------*/ -//.. -//.. /* Translate an entire BB to x86 code. */ -//.. -//.. HInstrArray* iselBB_X86 ( IRBB* bb, VexSubArch subarch_host ) -//.. { -//.. Int i, j; -//.. HReg hreg, hregHI; -//.. -//.. /* sanity ... */ -//.. vassert(subarch_host == VexSubArchX86_sse0 -//.. || subarch_host == VexSubArchX86_sse1 -//.. || subarch_host == VexSubArchX86_sse2); -//.. -//.. /* Make up an initial environment to use. */ -//.. ISelEnv* env = LibVEX_Alloc(sizeof(ISelEnv)); -//.. env->vreg_ctr = 0; -//.. -//.. /* Set up output code array. */ -//.. env->code = newHInstrArray(); -//.. -//.. /* Copy BB's type env. */ -//.. env->type_env = bb->tyenv; -//.. -//.. /* Make up an IRTemp -> virtual HReg mapping. This doesn't -//.. change as we go along. */ -//.. env->n_vregmap = bb->tyenv->types_used; -//.. env->vregmap = LibVEX_Alloc(env->n_vregmap * sizeof(HReg)); -//.. env->vregmapHI = LibVEX_Alloc(env->n_vregmap * sizeof(HReg)); -//.. -//.. /* and finally ... */ -//.. env->subarch = subarch_host; -//.. -//.. /* For each IR temporary, allocate a suitably-kinded virtual -//.. register. */ -//.. j = 0; -//.. for (i = 0; i < env->n_vregmap; i++) { -//.. hregHI = hreg = INVALID_HREG; -//.. switch (bb->tyenv->types[i]) { -//.. case Ity_I1: -//.. case Ity_I8: -//.. case Ity_I16: -//.. case Ity_I32: hreg = mkHReg(j++, HRcInt32, True); break; -//.. case Ity_I64: hreg = mkHReg(j++, HRcInt32, True); -//.. hregHI = mkHReg(j++, HRcInt32, True); break; -//.. case Ity_F32: -//.. case Ity_F64: hreg = mkHReg(j++, HRcFlt64, True); break; -//.. case Ity_V128: hreg = mkHReg(j++, HRcVec128, True); break; -//.. default: ppIRType(bb->tyenv->types[i]); -//.. vpanic("iselBB: IRTemp type"); -//.. } -//.. env->vregmap[i] = hreg; -//.. env->vregmapHI[i] = hregHI; -//.. } -//.. env->vreg_ctr = j; -//.. -//.. /* Ok, finally we can iterate over the statements. */ -//.. for (i = 0; i < bb->stmts_used; i++) -//.. if (bb->stmts[i]) -//.. iselStmt(env,bb->stmts[i]); -//.. -//.. iselNext(env,bb->next,bb->jumpkind); -//.. -//.. /* record the number of vregs we used. */ -//.. env->code->n_vregs = env->vreg_ctr; -//.. return env->code; -//.. } +} + + +/*---------------------------------------------------------*/ +/*--- Insn selector top-level ---*/ +/*---------------------------------------------------------*/ + +/* Translate an entire BB to amd64 code. */ + +HInstrArray* iselBB_AMD64 ( IRBB* bb, VexSubArch subarch_host ) +{ + Int i, j; + HReg hreg; + + /* sanity ... */ + vassert(subarch_host == VexSubArch_NONE); + + /* Make up an initial environment to use. */ + ISelEnv* env = LibVEX_Alloc(sizeof(ISelEnv)); + env->vreg_ctr = 0; + + /* Set up output code array. */ + env->code = newHInstrArray(); + + /* Copy BB's type env. */ + env->type_env = bb->tyenv; + + /* Make up an IRTemp -> virtual HReg mapping. This doesn't + change as we go along. */ + env->n_vregmap = bb->tyenv->types_used; + env->vregmap = LibVEX_Alloc(env->n_vregmap * sizeof(HReg)); + + /* and finally ... */ + env->subarch = subarch_host; + + /* For each IR temporary, allocate a suitably-kinded virtual + register. */ + j = 0; + for (i = 0; i < env->n_vregmap; i++) { + hreg = INVALID_HREG; + switch (bb->tyenv->types[i]) { + case Ity_I1: + case Ity_I8: + case Ity_I16: + case Ity_I32: + case Ity_I64: hreg = mkHReg(j++, HRcInt64, True); break; + case Ity_F32: + case Ity_F64: hreg = mkHReg(j++, HRcFlt64, True); break; + case Ity_V128: hreg = mkHReg(j++, HRcVec128, True); break; + default: ppIRType(bb->tyenv->types[i]); + vpanic("iselBB(amd64): IRTemp type"); + } + env->vregmap[i] = hreg; + } + env->vreg_ctr = j; + + /* Ok, finally we can iterate over the statements. */ + for (i = 0; i < bb->stmts_used; i++) + if (bb->stmts[i]) + iselStmt(env,bb->stmts[i]); + + iselNext(env,bb->next,bb->jumpkind); + + /* record the number of vregs we used. */ + env->code->n_vregs = env->vreg_ctr; + return env->code; +} /*---------------------------------------------------------------*/ diff --git a/VEX/priv/main/vex_main.c b/VEX/priv/main/vex_main.c index 3c99420f68..01567a0e75 100644 --- a/VEX/priv/main/vex_main.c +++ b/VEX/priv/main/vex_main.c @@ -46,6 +46,7 @@ #include "ir/iropt.h" #include "host-x86/hdefs.h" +#include "host-amd64/hdefs.h" #include "guest-x86/gdefs.h" #include "guest-amd64/gdefs.h" @@ -265,6 +266,23 @@ VexTranslateResult LibVEX_Translate ( || subarch_host == VexSubArchX86_sse2); break; + case VexArchAMD64: + getAllocableRegs_AMD64 ( &n_available_real_regs, + &available_real_regs ); + isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_AMD64Instr; + getRegUsage = (void(*)(HRegUsage*,HInstr*)) getRegUsage_AMD64Instr; + mapRegs = (void(*)(HRegRemap*,HInstr*)) mapRegs_AMD64Instr; + genSpill = (HInstr*(*)(HReg,Int)) genSpill_AMD64; + genReload = (HInstr*(*)(HReg,Int)) genReload_AMD64; + ppInstr = (void(*)(HInstr*)) ppAMD64Instr; + ppReg = (void(*)(HReg)) ppHRegAMD64; + iselBB = iselBB_AMD64; + emit = (Int(*)(UChar*,Int,HInstr*)) emit_AMD64Instr; + host_is_bigendian = False; + host_word_type = Ity_I64; + vassert(subarch_host == VexSubArch_NONE); + break; + default: vpanic("LibVEX_Translate: unsupported target insn set"); } @@ -433,6 +451,8 @@ VexTranslateResult LibVEX_Translate ( vex_printf("\n"); } + if (0) { *host_bytes_used = 0; return VexTransOK; } + if (vex_traceflags & VEX_TRACE_VCODE) vex_printf("\n------------------------" " Instruction selection "