From: Julian Seward Date: Wed, 1 Dec 2004 23:19:36 +0000 (+0000) Subject: x86 host: make a start on SSE code generation. X-Git-Tag: svn/VALGRIND_3_0_1^2~730 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6851682a465292fec67bc2d71b305cc7300652ba;p=thirdparty%2Fvalgrind.git x86 host: make a start on SSE code generation. git-svn-id: svn://svn.valgrind.org/vex/trunk@604 --- diff --git a/VEX/priv/host-generic/reg_alloc2.c b/VEX/priv/host-generic/reg_alloc2.c index f251909548..a346e0fedd 100644 --- a/VEX/priv/host-generic/reg_alloc2.c +++ b/VEX/priv/host-generic/reg_alloc2.c @@ -431,9 +431,11 @@ HInstrArray* doRegisterAllocation ( /* Now consider live ranges. */ switch (reg_usage.mode[j]) { case HRmRead: - if (vreg_info[k].live_after == INVALID_INSTRNO) + if (vreg_info[k].live_after == INVALID_INSTRNO) { + vex_printf("\n\nOFFENDING VREG = %d\n", k); vpanic("doRegisterAllocation: " "first event for vreg is Read"); + } vreg_info[k].dead_before = ii + 1; break; case HRmWrite: @@ -625,20 +627,43 @@ HInstrArray* doRegisterAllocation ( continue; } - /* Need to allocate two 64-bit spill slots for this. */ - if (vreg_info[j].reg_class == HRcVec128) - vpanic("can't deal with spilling 128-bit values (yet)"); + /* The spill slots are 64 bits in size. That means, to spill a + Vec128-class vreg, we'll need to find two adjacent spill + slots to use. */ + + if (vreg_info[j].reg_class != HRcVec128) { + + /* The ordinary case -- just find a single spill slot. */ + + /* Find the lowest-numbered spill slot which is available at + the start point of this interval, and assign the interval + to it. */ + for (k = 0; k < N_SPILL64S; k++) + if (ss_busy_until_before[k] <= vreg_info[j].live_after) + break; + if (k == N_SPILL64S) { + vpanic("LibVEX_N_SPILL_BYTES is too low. " + "Increase and recompile."); + } + ss_busy_until_before[k] = vreg_info[j].dead_before; + + } else { + + /* Find two adjacent free slots in which to spill a 128-bit + vreg. */ + + for (k = 0; k < N_SPILL64S-1; k++) + if (ss_busy_until_before[k] <= vreg_info[j].live_after + && ss_busy_until_before[k+1] <= vreg_info[j].live_after) + break; + if (k == N_SPILL64S-1) { + vpanic("LibVEX_N_SPILL_BYTES is too low. " + "Increase and recompile."); + } + ss_busy_until_before[k+0] = vreg_info[j].dead_before; + ss_busy_until_before[k+1] = vreg_info[j].dead_before; - /* Find the lowest-numbered spill slot which is available at the - start point of this interval, and assign the interval to - it. */ - for (k = 0; k < N_SPILL64S; k++) - if (ss_busy_until_before[k] <= vreg_info[j].live_after) - break; - if (k == N_SPILL64S) { - vpanic("LibVEX_N_SPILL_BYTES is too low. Increase and recompile."); } - ss_busy_until_before[k] = vreg_info[j].dead_before; /* This reflects LibVEX's hard-wired knowledge of the baseBlock layout: the guest state, then an equal sized area following diff --git a/VEX/priv/host-x86/hdefs.c b/VEX/priv/host-x86/hdefs.c index 39a44f2b34..834b638131 100644 --- a/VEX/priv/host-x86/hdefs.c +++ b/VEX/priv/host-x86/hdefs.c @@ -47,7 +47,7 @@ void ppHRegX86 ( HReg reg ) { Int r; - static Char* ireg32_names[8] + static HChar* ireg32_names[8] = { "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi" }; /* Be generic for all virtual regs. */ if (hregIsVirtual(reg)) { @@ -67,8 +67,11 @@ void ppHRegX86 ( HReg reg ) vex_printf("%%fake%d", r); return; case HRcVec128: - vpanic("ppHRegX86: real vector reg"); - default: + r = hregNumber(reg); + vassert(r >= 0 && r < 8); + vex_printf("%%xmm%d", r); + return; + default: vpanic("ppHRegX86"); } } @@ -89,9 +92,19 @@ HReg hregX86_FAKE3 ( void ) { return mkHReg(3, HRcFlt64, False); } HReg hregX86_FAKE4 ( void ) { return mkHReg(4, HRcFlt64, False); } HReg hregX86_FAKE5 ( void ) { return mkHReg(5, HRcFlt64, False); } +HReg hregX86_XMM0 ( void ) { return mkHReg(0, HRcVec128, False); } +HReg hregX86_XMM1 ( void ) { return mkHReg(1, HRcVec128, False); } +HReg hregX86_XMM2 ( void ) { return mkHReg(2, HRcVec128, False); } +HReg hregX86_XMM3 ( void ) { return mkHReg(3, HRcVec128, False); } +HReg hregX86_XMM4 ( void ) { return mkHReg(4, HRcVec128, False); } +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 ) { - *nregs = 12; + *nregs = 20; *arr = LibVEX_Alloc(*nregs * sizeof(HReg)); (*arr)[0] = hregX86_EAX(); (*arr)[1] = hregX86_EBX(); @@ -105,6 +118,14 @@ void getAllocableRegs_X86 ( Int* nregs, HReg** arr ) (*arr)[9] = hregX86_FAKE3(); (*arr)[10] = hregX86_FAKE4(); (*arr)[11] = hregX86_FAKE5(); + (*arr)[12] = hregX86_XMM0(); + (*arr)[13] = hregX86_XMM1(); + (*arr)[14] = hregX86_XMM2(); + (*arr)[15] = hregX86_XMM3(); + (*arr)[16] = hregX86_XMM4(); + (*arr)[17] = hregX86_XMM5(); + (*arr)[18] = hregX86_XMM6(); + (*arr)[19] = hregX86_XMM7(); } @@ -409,7 +430,7 @@ static void mapRegs_X86RM ( HRegRemap* m, X86RM* op ) /* --------- Instructions. --------- */ -Char* showX86ScalarSz ( X86ScalarSz sz ) { +HChar* showX86ScalarSz ( X86ScalarSz sz ) { switch (sz) { case Xss_16: return "w"; case Xss_32: return "l"; @@ -417,7 +438,7 @@ Char* showX86ScalarSz ( X86ScalarSz sz ) { } } -Char* showX86UnaryOp ( X86UnaryOp op ) { +HChar* showX86UnaryOp ( X86UnaryOp op ) { switch (op) { case Xun_NOT: return "not"; case Xun_NEG: return "neg"; @@ -425,7 +446,7 @@ Char* showX86UnaryOp ( X86UnaryOp op ) { } } -Char* showX86AluOp ( X86AluOp op ) { +HChar* showX86AluOp ( X86AluOp op ) { switch (op) { case Xalu_MOV: return "mov"; case Xalu_CMP: return "cmp"; @@ -441,7 +462,7 @@ Char* showX86AluOp ( X86AluOp op ) { } } -Char* showX86ShiftOp ( X86ShiftOp op ) { +HChar* showX86ShiftOp ( X86ShiftOp op ) { switch (op) { case Xsh_SHL: return "shl"; case Xsh_SHR: return "shr"; @@ -452,7 +473,7 @@ Char* showX86ShiftOp ( X86ShiftOp op ) { } } -Char* showX86FpOp ( X86FpOp op ) { +HChar* showX86FpOp ( X86FpOp op ) { switch (op) { case Xfp_ADD: return "add"; case Xfp_SUB: return "sub"; @@ -477,6 +498,20 @@ Char* showX86FpOp ( X86FpOp op ) { } } +HChar* showX86SseOp ( X86SseOp op ) { + switch (op) { + case Xsse_MOV: return "mov(?!)"; + case Xsse_AND: return "add"; + case Xsse_OR: return "or"; + case Xsse_XOR: return "xor"; + case Xsse_ANDN: return "andn"; + case Xsse_ADDF: return "add"; + case Xsse_SUBF: return "sub"; + case Xsse_MULF: return "mul"; + default: vpanic("showX86SseOp"); + } +} + X86Instr* X86Instr_Alu32R ( X86AluOp op, X86RMI* src, HReg dst ) { X86Instr* i = LibVEX_Alloc(sizeof(X86Instr)); i->tag = Xin_Alu32R; @@ -601,8 +636,7 @@ X86Instr* X86Instr_Set32 ( X86CondCode cond, HReg dst ) { i->Xin.Set32.dst = dst; return i; } -X86Instr* X86Instr_Bsfr32 ( Bool isFwds, HReg src, HReg dst ) -{ +X86Instr* X86Instr_Bsfr32 ( Bool isFwds, HReg src, HReg dst ) { X86Instr* i = LibVEX_Alloc(sizeof(X86Instr)); i->tag = Xin_Bsfr32; i->Xin.Bsfr32.isFwds = isFwds; @@ -637,7 +671,8 @@ X86Instr* X86Instr_FpLdSt ( Bool isLoad, UChar sz, HReg reg, X86AMode* addr ) { vassert(sz == 4 || sz == 8); return i; } -X86Instr* X86Instr_FpLdStI ( Bool isLoad, UChar sz, HReg reg, X86AMode* addr ) { +X86Instr* X86Instr_FpLdStI ( Bool isLoad, UChar sz, + HReg reg, X86AMode* addr ) { X86Instr* i = LibVEX_Alloc(sizeof(X86Instr)); i->tag = Xin_FpLdStI; i->Xin.FpLdStI.isLoad = isLoad; @@ -656,22 +691,19 @@ X86Instr* X86Instr_FpCMov ( X86CondCode cond, HReg src, HReg dst ) { vassert(cond != Xcc_ALWAYS); return i; } -X86Instr* X86Instr_FpLdStCW ( Bool isLoad, X86AMode* addr ) -{ +X86Instr* X86Instr_FpLdStCW ( Bool isLoad, X86AMode* addr ) { X86Instr* i = LibVEX_Alloc(sizeof(X86Instr)); i->tag = Xin_FpLdStCW; i->Xin.FpLdStCW.isLoad = isLoad; i->Xin.FpLdStCW.addr = addr; return i; } -X86Instr* X86Instr_FpStSW_AX ( void ) -{ +X86Instr* X86Instr_FpStSW_AX ( void ) { X86Instr* i = LibVEX_Alloc(sizeof(X86Instr)); i->tag = Xin_FpStSW_AX; return i; } -X86Instr* X86Instr_FpCmp ( HReg srcL, HReg srcR, HReg dst ) -{ +X86Instr* X86Instr_FpCmp ( HReg srcL, HReg srcR, HReg dst ) { X86Instr* i = LibVEX_Alloc(sizeof(X86Instr)); i->tag = Xin_FpCmp; i->Xin.FpCmp.srcL = srcL; @@ -680,6 +712,40 @@ X86Instr* X86Instr_FpCmp ( HReg srcL, HReg srcR, HReg dst ) return i; } +X86Instr* X86Instr_SseLdSt ( Bool isLoad, HReg reg, X86AMode* addr ) { + X86Instr* i = LibVEX_Alloc(sizeof(X86Instr)); + i->tag = Xin_SseLdSt; + i->Xin.SseLdSt.isLoad = isLoad; + i->Xin.SseLdSt.reg = reg; + i->Xin.SseLdSt.addr = addr; + return i; +} +X86Instr* X86Instr_Sse128 ( X86SseOp op, HReg src, HReg dst ) { + X86Instr* i = LibVEX_Alloc(sizeof(X86Instr)); + i->tag = Xin_Sse128; + i->Xin.Sse128.op = op; + i->Xin.Sse128.src = src; + i->Xin.Sse128.dst = dst; + vassert(op == Xsse_MOV || op == Xsse_AND || op == Xsse_OR + || op == Xsse_XOR || op == Xsse_ANDN); + return i; +} +X86Instr* X86Instr_Sse32Fx4 ( X86SseOp op, HReg src, HReg dst ) { + X86Instr* i = LibVEX_Alloc(sizeof(X86Instr)); + i->tag = Xin_Sse32Fx4; + i->Xin.Sse32Fx4.op = op; + i->Xin.Sse32Fx4.src = src; + i->Xin.Sse32Fx4.dst = dst; + return i; +} +X86Instr* X86Instr_Sse32FLo ( X86SseOp op, HReg src, HReg dst ) { + X86Instr* i = LibVEX_Alloc(sizeof(X86Instr)); + i->tag = Xin_Sse32FLo; + i->Xin.Sse32FLo.op = op; + i->Xin.Sse32FLo.src = src; + i->Xin.Sse32FLo.dst = dst; + return i; +} void ppX86Instr ( X86Instr* i ) { switch (i->tag) { @@ -856,6 +922,41 @@ void ppX86Instr ( X86Instr* i ) { vex_printf(","); ppHRegX86(i->Xin.FpCmp.dst); break; + case Xin_SseLdSt: + vex_printf("movups "); + if (i->Xin.SseLdSt.isLoad) { + ppX86AMode(i->Xin.SseLdSt.addr); + vex_printf(","); + ppHRegX86(i->Xin.SseLdSt.reg); + } else { + ppHRegX86(i->Xin.SseLdSt.reg); + vex_printf(","); + ppX86AMode(i->Xin.SseLdSt.addr); + } + return; + case Xin_Sse128: + if (i->Xin.Sse128.op == Xsse_MOV) { + vex_printf("mov "); + } else { + vex_printf("p%s ", showX86SseOp(i->Xin.Sse128.op)); + } + ppHRegX86(i->Xin.Sse128.src); + vex_printf(","); + ppHRegX86(i->Xin.Sse128.dst); + return; + case Xin_Sse32Fx4: + vex_printf("%sps ", showX86SseOp(i->Xin.Sse32Fx4.op)); + ppHRegX86(i->Xin.Sse32Fx4.src); + vex_printf(","); + ppHRegX86(i->Xin.Sse32Fx4.dst); + return; + case Xin_Sse32FLo: + vex_printf("%sss ", showX86SseOp(i->Xin.Sse32FLo.op)); + ppHRegX86(i->Xin.Sse32FLo.src); + vex_printf(","); + ppHRegX86(i->Xin.Sse32FLo.dst); + return; + default: vpanic("ppX86Instr"); } @@ -1006,6 +1107,21 @@ void getRegUsage_X86Instr (HRegUsage* u, X86Instr* i) addHRegUse(u, HRmWrite, i->Xin.FpCmp.dst); addHRegUse(u, HRmWrite, hregX86_EAX()); return; + case Xin_SseLdSt: + addRegUsage_X86AMode(u, i->Xin.SseLdSt.addr); + addHRegUse(u, i->Xin.SseLdSt.isLoad ? HRmWrite : HRmRead, + i->Xin.SseLdSt.reg); + return; + case Xin_Sse128: + addHRegUse(u, HRmRead, i->Xin.Sse128.src); + addHRegUse(u, i->Xin.Sse128.op==Xsse_MOV ? HRmWrite : HRmModify, + i->Xin.Sse128.dst); + return; + case Xin_Sse32Fx4: + vassert(i->Xin.Sse32Fx4.op != Xsse_MOV); + addHRegUse(u, HRmRead, i->Xin.Sse32Fx4.src); + addHRegUse(u, HRmModify, i->Xin.Sse32Fx4.dst); + return; default: ppX86Instr(i); vpanic("getRegUsage_X86Instr"); @@ -1107,6 +1223,18 @@ void mapRegs_X86Instr (HRegRemap* m, X86Instr* i) mapReg(m, &i->Xin.FpCmp.srcR); mapReg(m, &i->Xin.FpCmp.dst); return; + case Xin_SseLdSt: + mapReg(m, &i->Xin.SseLdSt.reg); + mapRegs_X86AMode(m, i->Xin.SseLdSt.addr); + break; + case Xin_Sse128: + mapReg(m, &i->Xin.Sse128.src); + mapReg(m, &i->Xin.Sse128.dst); + return; + case Xin_Sse32Fx4: + mapReg(m, &i->Xin.Sse32Fx4.src); + mapReg(m, &i->Xin.Sse32Fx4.dst); + return; default: ppX86Instr(i); vpanic("mapRegs_X86Instr"); @@ -1137,6 +1265,13 @@ Bool isMove_X86Instr ( X86Instr* i, HReg* src, HReg* dst ) *dst = i->Xin.FpUnary.dst; return True; } + if (i->tag == Xin_Sse128) { + if (i->Xin.Sse128.op != Xsse_MOV) + return False; + *src = i->Xin.Sse128.src; + *dst = i->Xin.Sse128.dst; + return True; + } return False; } @@ -1203,6 +1338,16 @@ static UInt fregNo ( HReg r ) return n; } +static UInt vregNo ( HReg r ) +{ + UInt n; + vassert(hregClass(r) == HRcVec128); + vassert(!hregIsVirtual(r)); + n = hregNumber(r); + vassert(n <= 7); + return n; +} + static UChar mkModRegRM ( UChar mod, UChar reg, UChar regmem ) { return ((mod & 3) << 6) | ((reg & 7) << 3) | (regmem & 7); @@ -2117,6 +2262,19 @@ Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i ) p = doAMode_R(p, hregX86_EAX(), i->Xin.FpCmp.dst); goto done; + case Xin_SseLdSt: + *p++ = 0x0F; + *p++ = i->Xin.SseLdSt.isLoad ? 0x10 : 0x11; + p = doAMode_M(p, fake(vregNo(i->Xin.SseLdSt.reg)), i->Xin.SseLdSt.addr); + goto done; + + case Xin_Sse32Fx4: + *p++ = 0x0F; + *p++ = 0x58; + p = doAMode_R(p, fake(vregNo(i->Xin.Sse32Fx4.dst)), + fake(vregNo(i->Xin.Sse32Fx4.src)) ); + goto done; + default: goto bad; } diff --git a/VEX/priv/host-x86/hdefs.h b/VEX/priv/host-x86/hdefs.h index 55f4591358..7aaa6a0613 100644 --- a/VEX/priv/host-x86/hdefs.h +++ b/VEX/priv/host-x86/hdefs.h @@ -61,6 +61,15 @@ 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. --------- */ @@ -237,7 +246,7 @@ typedef } X86ScalarSz; -extern Char* showX86ScalarSz ( X86ScalarSz ); +extern HChar* showX86ScalarSz ( X86ScalarSz ); /* --------- */ @@ -248,7 +257,7 @@ typedef } X86UnaryOp; -extern Char* showX86UnaryOp ( X86UnaryOp ); +extern HChar* showX86UnaryOp ( X86UnaryOp ); /* --------- */ @@ -263,7 +272,7 @@ typedef } X86AluOp; -extern Char* showX86AluOp ( X86AluOp ); +extern HChar* showX86AluOp ( X86AluOp ); /* --------- */ @@ -275,7 +284,7 @@ typedef } X86ShiftOp; -extern Char* showX86ShiftOp ( X86ShiftOp ); +extern HChar* showX86ShiftOp ( X86ShiftOp ); /* --------- */ @@ -291,7 +300,19 @@ typedef } X86FpOp; -extern Char* showX86FpOp ( X86FpOp ); +extern HChar* showX86FpOp ( X86FpOp ); + + +/* --------- */ +typedef + enum { + Xsse_INVALID, + Xsse_MOV, Xsse_AND, Xsse_OR, Xsse_XOR, Xsse_ANDN, + Xsse_ADDF, Xsse_SUBF, Xsse_MULF + } + X86SseOp; + +extern HChar* showX86SseOp ( X86SseOp ); /* --------- */ @@ -313,6 +334,7 @@ typedef Xin_Store, /* store 16/8 bit value in memory */ Xin_Set32, /* convert condition code to 32-bit value */ Xin_Bsfr32, /* 32-bit bsf/bsr */ + Xin_FpUnary, /* FP fake unary op */ Xin_FpBinary, /* FP fake binary op */ Xin_FpLdSt, /* FP fake load/store */ @@ -320,7 +342,15 @@ typedef Xin_FpCMov, /* FP fake floating point (un)conditional move */ Xin_FpLdStCW, /* fldcw / fstcw */ Xin_FpStSW_AX, /* fstsw %ax */ - Xin_FpCmp /* FP compare, generating a C320 value into int reg */ + Xin_FpCmp, /* FP compare, generating a C320 value into int reg */ + + Xin_SseLdSt, /* SSE load/store, no alignment constraints */ + Xin_Sse128, /* SSE binary typeless (and/or/xor/andn) */ + Xin_Sse32Fx4, /* SSE binary, 32Fx4 */ + Xin_Sse32FLo /* SSE binary, 32F in lowest lane only */ + // Xin_Sse64Fx2, /* SSE binary, 64Fx2 */ + // Xin_Sse64FLo, /* SSE binary, 64F in lowest lane only */ + /* Xin_SseUn32Fx4 */ } X86InstrTag; @@ -425,6 +455,7 @@ typedef HReg src; HReg dst; } Bsfr32; + /* X86 Floating point (fake 3-operand, "flat reg file" insns) */ struct { X86FpOp op; @@ -475,6 +506,29 @@ typedef HReg srcR; HReg dst; } FpCmp; + + /* Simplistic SSE[123] */ + struct { + Bool isLoad; + HReg reg; + X86AMode* addr; + } SseLdSt; + struct { + X86SseOp op; /* MOV/AND/OR/XOR/ANDN only */ + HReg src; + HReg dst; + } Sse128; + struct { + X86SseOp op; + HReg src; + HReg dst; + } Sse32Fx4; + struct { + X86SseOp op; + HReg src; + HReg dst; + } Sse32FLo; + } Xin; } X86Instr; @@ -496,6 +550,7 @@ extern X86Instr* X86Instr_LoadEX ( UChar szSmall, Bool syned, extern X86Instr* X86Instr_Store ( UChar sz, HReg src, X86AMode* dst ); extern X86Instr* X86Instr_Set32 ( X86CondCode cond, HReg dst ); extern X86Instr* X86Instr_Bsfr32 ( Bool isFwds, HReg src, HReg dst ); + extern X86Instr* X86Instr_FpUnary ( X86FpOp op, HReg src, HReg dst ); extern X86Instr* X86Instr_FpBinary ( X86FpOp op, HReg srcL, HReg srcR, HReg dst ); extern X86Instr* X86Instr_FpLdSt ( Bool isLoad, UChar sz, HReg reg, X86AMode* ); @@ -505,6 +560,11 @@ extern X86Instr* X86Instr_FpLdStCW ( Bool isLoad, X86AMode* ); extern X86Instr* X86Instr_FpStSW_AX ( void ); extern X86Instr* X86Instr_FpCmp ( HReg srcL, HReg srcR, HReg dst ); +extern X86Instr* X86Instr_SseLdSt ( Bool isLoad, HReg, X86AMode* ); +extern X86Instr* X86Instr_Sse128 ( X86SseOp, HReg, HReg ); +extern X86Instr* X86Instr_Sse32Fx4 ( X86SseOp, HReg, HReg ); +extern X86Instr* X86Instr_Sse32FLo ( X86SseOp, HReg, HReg ); + extern void ppX86Instr ( X86Instr* ); diff --git a/VEX/priv/host-x86/isel.c b/VEX/priv/host-x86/isel.c index dadf5a5c45..52dd2b8224 100644 --- a/VEX/priv/host-x86/isel.c +++ b/VEX/priv/host-x86/isel.c @@ -244,6 +244,13 @@ static HReg newVRegF ( ISelEnv* env ) return reg; } +static HReg newVRegV ( ISelEnv* env ) +{ + HReg reg = mkHReg(env->vreg_ctr, HRcVec128, True/*virtual reg*/); + env->vreg_ctr++; + return reg; +} + /*---------------------------------------------------------*/ /*--- ISEL: Forward declarations ---*/ @@ -252,33 +259,40 @@ static HReg newVRegF ( ISelEnv* env ) /* These are organised as iselXXX and iselXXX_wrk pairs. The iselXXX_wrk do the real work, but are not to be called directly. For each XXX, iselXXX calls its iselXXX_wrk counterpart, then - checks that all returned registers are virtual. + checks that all returned registers are virtual. You should not + call the _wrk version directly. */ +static X86RMI* iselIntExpr_RMI_wrk ( ISelEnv* env, IRExpr* e ); +static X86RMI* iselIntExpr_RMI ( ISelEnv* env, IRExpr* e ); -static X86RMI* iselIntExpr_RMI_wrk ( ISelEnv* env, IRExpr* e ); -static X86RMI* iselIntExpr_RMI ( ISelEnv* env, IRExpr* e ); +static X86RI* iselIntExpr_RI_wrk ( ISelEnv* env, IRExpr* e ); +static X86RI* iselIntExpr_RI ( ISelEnv* env, IRExpr* e ); -static X86RI* iselIntExpr_RI_wrk ( ISelEnv* env, IRExpr* e ); -static X86RI* iselIntExpr_RI ( ISelEnv* env, IRExpr* e ); +static X86RM* iselIntExpr_RM_wrk ( ISelEnv* env, IRExpr* e ); +static X86RM* iselIntExpr_RM ( ISelEnv* env, IRExpr* e ); -static X86RM* iselIntExpr_RM_wrk ( ISelEnv* env, IRExpr* e ); -static X86RM* iselIntExpr_RM ( ISelEnv* env, IRExpr* e ); +static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ); +static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e ); -static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ); -static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e ); +static X86AMode* iselIntExpr_AMode_wrk ( ISelEnv* env, IRExpr* e ); +static X86AMode* iselIntExpr_AMode ( ISelEnv* env, IRExpr* e ); -static X86AMode* iselIntExpr_AMode_wrk ( ISelEnv* env, IRExpr* e ); -static X86AMode* iselIntExpr_AMode ( ISelEnv* env, IRExpr* e ); - -static void iselIntExpr64_wrk ( HReg* rHi, HReg* rLo, - ISelEnv* env, IRExpr* e ); -static void iselIntExpr64 ( HReg* rHi, HReg* rLo, - ISelEnv* env, IRExpr* e ); +static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, + ISelEnv* env, IRExpr* e ); +static void iselInt64Expr ( HReg* rHi, HReg* rLo, + ISelEnv* env, IRExpr* e ); static X86CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e ); static X86CondCode iselCondCode ( ISelEnv* env, IRExpr* e ); -static HReg iselDblExpr ( ISelEnv* env, IRExpr* e ); +static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e ); +static HReg iselDblExpr ( ISelEnv* env, IRExpr* e ); + +static HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e ); +static HReg iselFltExpr ( ISelEnv* env, IRExpr* e ); + +static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e ); +static HReg iselVecExpr ( ISelEnv* env, IRExpr* e ); /*---------------------------------------------------------*/ @@ -296,7 +310,7 @@ static Bool isZero32 ( IRExpr* e ) /* Make a int reg-reg move. */ -static X86Instr* mk_MOVsd_RR ( HReg src, HReg dst ) +static X86Instr* mk_iMOVsd_RR ( HReg src, HReg dst ) { vassert(hregClass(src) == HRcInt32); vassert(hregClass(dst) == HRcInt32); @@ -304,6 +318,16 @@ static X86Instr* mk_MOVsd_RR ( HReg src, HReg dst ) } +/* Make a vector reg-reg move. */ + +static X86Instr* mk_vMOVsd_RR ( HReg src, HReg dst ) +{ + vassert(hregClass(src) == HRcVec128); + vassert(hregClass(dst) == HRcVec128); + return X86Instr_Sse128(Xsse_MOV, src, dst); +} + + /* Given an amode, return one which references 4 bytes further along. */ @@ -335,7 +359,7 @@ static Int pushArg ( ISelEnv* env, IRExpr* arg ) } else if (arg_ty == Ity_I64) { HReg rHi, rLo; - iselIntExpr64(&rHi, &rLo, env, arg); + iselInt64Expr(&rHi, &rLo, env, arg); addInstr(env, X86Instr_Push(X86RMI_Reg(rHi))); addInstr(env, X86Instr_Push(X86RMI_Reg(rLo))); return 2; @@ -510,7 +534,7 @@ void doHelperCall ( ISelEnv* env, for (i = stack_limit-1; i >= 0; i--) { argregX--; vassert(argregX >= 0); - addInstr( env, mk_MOVsd_RR( tmpregs[argregX], argregs[argregX] ) ); + addInstr( env, mk_iMOVsd_RR( tmpregs[argregX], argregs[argregX] ) ); } } else { @@ -531,7 +555,7 @@ void doHelperCall ( ISelEnv* env, /* Not forgetting %ebp if needed. */ if (passBBP) { vassert(argreg == 1); - addInstr(env, mk_MOVsd_RR( hregX86_EBP(), argregs[0])); + addInstr(env, mk_iMOVsd_RR( hregX86_EBP(), argregs[0])); not_done_yet--; } @@ -600,7 +624,7 @@ X86AMode* genGuestArrayOffset ( ISelEnv* env, IRArray* descr, */ tmp = newVRegI(env); roff = iselIntExpr_R(env, off); - addInstr(env, mk_MOVsd_RR(roff, tmp)); + addInstr(env, mk_iMOVsd_RR(roff, tmp)); if (bias != 0) { addInstr(env, X86Instr_Alu32R(Xalu_ADD, X86RMI_Imm(bias), tmp)); @@ -689,7 +713,7 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) if (e->Iex.Binop.op == Iop_Sub32 && isZero32(e->Iex.Binop.arg1)) { HReg dst = newVRegI(env); HReg reg = iselIntExpr_R(env, e->Iex.Binop.arg2); - addInstr(env, mk_MOVsd_RR(reg,dst)); + addInstr(env, mk_iMOVsd_RR(reg,dst)); addInstr(env, X86Instr_Unary32(Xun_NEG,X86RM_Reg(dst))); return dst; } @@ -717,7 +741,7 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) HReg dst = newVRegI(env); HReg reg = iselIntExpr_R(env, e->Iex.Binop.arg1); X86RMI* rmi = iselIntExpr_RMI(env, e->Iex.Binop.arg2); - addInstr(env, mk_MOVsd_RR(reg,dst)); + addInstr(env, mk_iMOVsd_RR(reg,dst)); addInstr(env, X86Instr_Alu32R(aluOp, rmi, dst)); return dst; } @@ -755,7 +779,7 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) /* regL = the value to be shifted */ HReg regL = iselIntExpr_R(env, e->Iex.Binop.arg1); - addInstr(env, mk_MOVsd_RR(regL,dst)); + addInstr(env, mk_iMOVsd_RR(regL,dst)); /* Do any necessary widening for 16/8 bit operands */ switch (e->Iex.Binop.op) { @@ -795,7 +819,7 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) } else { /* General case; we have to force the amount into %cl. */ HReg regR = iselIntExpr_R(env, e->Iex.Binop.arg2); - addInstr(env, mk_MOVsd_RR(regR,hregX86_ECX())); + addInstr(env, mk_iMOVsd_RR(regR,hregX86_ECX())); addInstr(env, X86Instr_Sh32(shOp, 0/* %cl */, X86RM_Reg(dst))); } return dst; @@ -807,8 +831,8 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) HReg lo8 = newVRegI(env); HReg hi8s = iselIntExpr_R(env, e->Iex.Binop.arg1); HReg lo8s = iselIntExpr_R(env, e->Iex.Binop.arg2); - addInstr(env, mk_MOVsd_RR(hi8s, hi8)); - addInstr(env, mk_MOVsd_RR(lo8s, lo8)); + addInstr(env, mk_iMOVsd_RR(hi8s, hi8)); + addInstr(env, mk_iMOVsd_RR(lo8s, lo8)); addInstr(env, X86Instr_Sh32(Xsh_SHL, 8, X86RM_Reg(hi8))); addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(0xFF), lo8)); addInstr(env, X86Instr_Alu32R(Xalu_OR, X86RMI_Reg(lo8), hi8)); @@ -820,8 +844,8 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) HReg lo16 = newVRegI(env); HReg hi16s = iselIntExpr_R(env, e->Iex.Binop.arg1); HReg lo16s = iselIntExpr_R(env, e->Iex.Binop.arg2); - addInstr(env, mk_MOVsd_RR(hi16s, hi16)); - addInstr(env, mk_MOVsd_RR(lo16s, lo16)); + addInstr(env, mk_iMOVsd_RR(hi16s, hi16)); + addInstr(env, mk_iMOVsd_RR(lo16s, lo16)); addInstr(env, X86Instr_Sh32(Xsh_SHL, 16, X86RM_Reg(hi16))); addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(0xFFFF), lo16)); addInstr(env, X86Instr_Alu32R(Xalu_OR, X86RMI_Reg(lo16), hi16)); @@ -841,8 +865,8 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) || e->Iex.Binop.op == Iop_MullS16) ? Xsh_SAR : Xsh_SHR; - addInstr(env, mk_MOVsd_RR(a16s, a16)); - addInstr(env, mk_MOVsd_RR(b16s, b16)); + addInstr(env, mk_iMOVsd_RR(a16s, a16)); + addInstr(env, mk_iMOVsd_RR(b16s, b16)); addInstr(env, X86Instr_Sh32(Xsh_SHL, shift, X86RM_Reg(a16))); addInstr(env, X86Instr_Sh32(Xsh_SHL, shift, X86RM_Reg(b16))); addInstr(env, X86Instr_Sh32(shr_op, shift, X86RM_Reg(a16))); @@ -889,7 +913,7 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) movl %rrm2, 0(%esp) fldcw 0(%esp) */ - addInstr(env, mk_MOVsd_RR(rrm, rrm2)); + addInstr(env, mk_iMOVsd_RR(rrm, rrm2)); addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(3), rrm2)); addInstr(env, X86Instr_Sh32(Xsh_SHL, 10, X86RM_Reg(rrm2))); addInstr(env, X86Instr_Alu32R(Xalu_OR, X86RMI_Imm(0x037F), rrm2)); @@ -937,7 +961,7 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) /* The previous pseudo-insn will have left the FPU's C3210 flags set correctly. So bag them. */ addInstr(env, X86Instr_FpStSW_AX()); - addInstr(env, mk_MOVsd_RR(hregX86_EAX(), dst)); + addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), dst)); addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(0x4700), dst)); return dst; } @@ -954,7 +978,7 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) IRExpr* expr32 = mi.bindee[0]; HReg dst = newVRegI(env); HReg src = iselIntExpr_R(env, expr32); - addInstr(env, mk_MOVsd_RR(src,dst) ); + addInstr(env, mk_iMOVsd_RR(src,dst) ); addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(1), dst)); return dst; @@ -980,7 +1004,7 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) HReg dst = newVRegI(env); HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); UInt mask = e->Iex.Unop.op==Iop_16Uto32 ? 0xFFFF : 0xFF; - addInstr(env, mk_MOVsd_RR(src,dst) ); + addInstr(env, mk_iMOVsd_RR(src,dst) ); addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(mask), dst)); return dst; @@ -991,7 +1015,7 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) HReg dst = newVRegI(env); HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); UInt amt = e->Iex.Unop.op==Iop_16Sto32 ? 16 : 24; - addInstr(env, mk_MOVsd_RR(src,dst) ); + addInstr(env, mk_iMOVsd_RR(src,dst) ); addInstr(env, X86Instr_Sh32(Xsh_SHL, amt, X86RM_Reg(dst))); addInstr(env, X86Instr_Sh32(Xsh_SAR, amt, X86RM_Reg(dst))); return dst; @@ -1001,18 +1025,18 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) case Iop_Not32: { HReg dst = newVRegI(env); HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); - addInstr(env, mk_MOVsd_RR(src,dst) ); + addInstr(env, mk_iMOVsd_RR(src,dst) ); addInstr(env, X86Instr_Unary32(Xun_NOT,X86RM_Reg(dst))); return dst; } case Iop_64HIto32: { HReg rHi, rLo; - iselIntExpr64(&rHi,&rLo, env, e->Iex.Unop.arg); + iselInt64Expr(&rHi,&rLo, env, e->Iex.Unop.arg); return rHi; /* and abandon rLo .. poor wee thing :-) */ } case Iop_64to32: { HReg rHi, rLo; - iselIntExpr64(&rHi,&rLo, env, e->Iex.Unop.arg); + iselInt64Expr(&rHi,&rLo, env, e->Iex.Unop.arg); return rLo; /* similar stupid comment to the above ... */ } case Iop_16HIto8: @@ -1020,7 +1044,7 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) HReg dst = newVRegI(env); HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); Int shift = e->Iex.Unop.op == Iop_16HIto8 ? 8 : 16; - addInstr(env, mk_MOVsd_RR(src,dst) ); + addInstr(env, mk_iMOVsd_RR(src,dst) ); addInstr(env, X86Instr_Sh32(Xsh_SHR, shift, X86RM_Reg(dst))); return dst; } @@ -1125,7 +1149,7 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) /* Marshal args, do the call, clear stack. */ doHelperCall( env, False, NULL, e->Iex.CCall.cee, e->Iex.CCall.args ); - addInstr(env, mk_MOVsd_RR(hregX86_EAX(), dst)); + addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), dst)); return dst; } @@ -1146,7 +1170,7 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) HReg rX = iselIntExpr_R(env, e->Iex.Mux0X.exprX); X86RM* r0 = iselIntExpr_RM(env, e->Iex.Mux0X.expr0); HReg dst = newVRegI(env); - addInstr(env, mk_MOVsd_RR(rX,dst)); + addInstr(env, mk_iMOVsd_RR(rX,dst)); r8 = iselIntExpr_R(env, e->Iex.Mux0X.cond); addInstr(env, X86Instr_Test32(X86RI_Imm(0xFF), X86RM_Reg(r8))); addInstr(env, X86Instr_CMov32(Xcc_Z,r0,dst)); @@ -1454,7 +1478,7 @@ static X86CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e ) HReg r1 = iselIntExpr_R(env, e->Iex.Binop.arg1); X86RMI* rmi2 = iselIntExpr_RMI(env, e->Iex.Binop.arg2); HReg r = newVRegI(env); - addInstr(env, mk_MOVsd_RR(r1,r)); + addInstr(env, mk_iMOVsd_RR(r1,r)); addInstr(env, X86Instr_Alu32R(Xalu_XOR,rmi2,r)); addInstr(env, X86Instr_Alu32R(Xalu_AND,X86RMI_Imm(0xFF),r)); switch (e->Iex.Binop.op) { @@ -1471,7 +1495,7 @@ static X86CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e ) HReg r1 = iselIntExpr_R(env, e->Iex.Binop.arg1); X86RMI* rmi2 = iselIntExpr_RMI(env, e->Iex.Binop.arg2); HReg r = newVRegI(env); - addInstr(env, mk_MOVsd_RR(r1,r)); + addInstr(env, mk_iMOVsd_RR(r1,r)); addInstr(env, X86Instr_Alu32R(Xalu_XOR,rmi2,r)); addInstr(env, X86Instr_Alu32R(Xalu_AND,X86RMI_Imm(0xFFFF),r)); switch (e->Iex.Binop.op) { @@ -1531,11 +1555,11 @@ static X86CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e ) HReg hi1, hi2, lo1, lo2; HReg tHi = newVRegI(env); HReg tLo = newVRegI(env); - iselIntExpr64( &hi1, &lo1, env, e->Iex.Binop.arg1 ); - iselIntExpr64( &hi2, &lo2, env, e->Iex.Binop.arg2 ); - addInstr(env, mk_MOVsd_RR(hi1, tHi)); + iselInt64Expr( &hi1, &lo1, env, e->Iex.Binop.arg1 ); + iselInt64Expr( &hi2, &lo2, env, e->Iex.Binop.arg2 ); + addInstr(env, mk_iMOVsd_RR(hi1, tHi)); addInstr(env, X86Instr_Alu32R(Xalu_XOR,X86RMI_Reg(hi2), tHi)); - addInstr(env, mk_MOVsd_RR(lo1, tLo)); + addInstr(env, mk_iMOVsd_RR(lo1, tLo)); addInstr(env, X86Instr_Alu32R(Xalu_XOR,X86RMI_Reg(lo2), tLo)); addInstr(env, X86Instr_Alu32R(Xalu_OR,X86RMI_Reg(tHi), tLo)); switch (e->Iex.Binop.op) { @@ -1548,7 +1572,7 @@ static X86CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e ) if (e->tag == Iex_Tmp) { HReg r32 = lookupIRTemp(env, e->Iex.Tmp.tmp); HReg dst = newVRegI(env); - addInstr(env, mk_MOVsd_RR(r32,dst)); + addInstr(env, mk_iMOVsd_RR(r32,dst)); addInstr(env, X86Instr_Alu32R(Xalu_AND,X86RMI_Imm(1),dst)); return Xcc_NZ; } @@ -1567,9 +1591,9 @@ static X86CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e ) either real or virtual regs; in any case they must not be changed by subsequent code emitted by the caller. */ -static void iselIntExpr64 ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) +static void iselInt64Expr ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) { - iselIntExpr64_wrk(rHi, rLo, env, e); + iselInt64Expr_wrk(rHi, rLo, env, e); # if 0 vex_printf("\n"); ppIRExpr(e); vex_printf("\n"); # endif @@ -1580,9 +1604,8 @@ static void iselIntExpr64 ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) } /* DO NOT CALL THIS DIRECTLY ! */ -static void iselIntExpr64_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) +static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) { - // MatchInfo mi; vassert(e); vassert(typeOfIRExpr(env->type_env,e) == Ity_I64); @@ -1608,19 +1631,15 @@ static void iselIntExpr64_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) /* 64-bit load */ if (e->tag == Iex_LDle) { - /* It would be better to generate the address into an amode and - then do advance4 to get the hi-half address. */ - HReg tLo, tHi, rA; + HReg tLo, tHi; + X86AMode *am0, *am4; vassert(e->Iex.LDle.ty == Ity_I64); tLo = newVRegI(env); tHi = newVRegI(env); - rA = iselIntExpr_R(env, e->Iex.LDle.addr); - addInstr(env, X86Instr_Alu32R( - Xalu_MOV, - X86RMI_Mem(X86AMode_IR(0, rA)), tLo)); - addInstr(env, X86Instr_Alu32R( - Xalu_MOV, - X86RMI_Mem(X86AMode_IR(4, rA)), tHi)); + am0 = iselIntExpr_AMode(env, e->Iex.LDle.addr); + am4 = advance4(am0); + addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(am0), tLo )); + addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(am4), tHi )); *rHi = tHi; *rLo = tLo; return; @@ -1659,10 +1678,10 @@ static void iselIntExpr64_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) HReg e0Lo, e0Hi, eXLo, eXHi, r8; HReg tLo = newVRegI(env); HReg tHi = newVRegI(env); - iselIntExpr64(&e0Hi, &e0Lo, env, e->Iex.Mux0X.expr0); - iselIntExpr64(&eXHi, &eXLo, env, e->Iex.Mux0X.exprX); - addInstr(env, mk_MOVsd_RR(eXHi, tHi)); - addInstr(env, mk_MOVsd_RR(eXLo, tLo)); + iselInt64Expr(&e0Hi, &e0Lo, env, e->Iex.Mux0X.expr0); + iselInt64Expr(&eXHi, &eXLo, env, e->Iex.Mux0X.exprX); + addInstr(env, mk_iMOVsd_RR(eXHi, tHi)); + addInstr(env, mk_iMOVsd_RR(eXLo, tLo)); r8 = iselIntExpr_R(env, e->Iex.Mux0X.cond); addInstr(env, X86Instr_Test32(X86RI_Imm(0xFF), X86RM_Reg(r8))); /* This assumes the first cmov32 doesn't trash the condition @@ -1685,11 +1704,11 @@ static void iselIntExpr64_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) Bool syned = e->Iex.Binop.op == Iop_MullS32; X86RM* rmLeft = iselIntExpr_RM(env, e->Iex.Binop.arg1); HReg rRight = iselIntExpr_R(env, e->Iex.Binop.arg2); - addInstr(env, mk_MOVsd_RR(rRight, hregX86_EAX())); + addInstr(env, mk_iMOVsd_RR(rRight, hregX86_EAX())); addInstr(env, X86Instr_MulL(syned, Xss_32, rmLeft)); /* Result is now in EDX:EAX. Tell the caller. */ - addInstr(env, mk_MOVsd_RR(hregX86_EDX(), tHi)); - addInstr(env, mk_MOVsd_RR(hregX86_EAX(), tLo)); + addInstr(env, mk_iMOVsd_RR(hregX86_EDX(), tHi)); + addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), tLo)); *rHi = tHi; *rLo = tLo; return; @@ -1706,12 +1725,12 @@ static void iselIntExpr64_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) HReg tHi = newVRegI(env); Bool syned = e->Iex.Binop.op == Iop_DivModS64to32; X86RM* rmRight = iselIntExpr_RM(env, e->Iex.Binop.arg2); - iselIntExpr64(&sHi,&sLo, env, e->Iex.Binop.arg1); - addInstr(env, mk_MOVsd_RR(sHi, hregX86_EDX())); - addInstr(env, mk_MOVsd_RR(sLo, hregX86_EAX())); + iselInt64Expr(&sHi,&sLo, env, e->Iex.Binop.arg1); + addInstr(env, mk_iMOVsd_RR(sHi, hregX86_EDX())); + addInstr(env, mk_iMOVsd_RR(sLo, hregX86_EAX())); addInstr(env, X86Instr_Div(syned, Xss_32, rmRight)); - addInstr(env, mk_MOVsd_RR(hregX86_EDX(), tHi)); - addInstr(env, mk_MOVsd_RR(hregX86_EAX(), tLo)); + addInstr(env, mk_iMOVsd_RR(hregX86_EDX(), tHi)); + addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), tLo)); *rHi = tHi; *rLo = tLo; return; @@ -1728,10 +1747,10 @@ static void iselIntExpr64_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) X86AluOp op = e->Iex.Binop.op==Iop_Or64 ? Xalu_OR : e->Iex.Binop.op==Iop_And64 ? Xalu_AND : Xalu_XOR; - iselIntExpr64(&xHi, &xLo, env, e->Iex.Binop.arg1); - addInstr(env, mk_MOVsd_RR(xHi, tHi)); - addInstr(env, mk_MOVsd_RR(xLo, tLo)); - iselIntExpr64(&yHi, &yLo, env, e->Iex.Binop.arg2); + iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1); + addInstr(env, mk_iMOVsd_RR(xHi, tHi)); + addInstr(env, mk_iMOVsd_RR(xLo, tLo)); + iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2); addInstr(env, X86Instr_Alu32R(op, X86RMI_Reg(yHi), tHi)); addInstr(env, X86Instr_Alu32R(op, X86RMI_Reg(yLo), tLo)); *rHi = tHi; @@ -1753,21 +1772,44 @@ static void iselIntExpr64_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) HReg tLo = newVRegI(env); HReg tHi = newVRegI(env); HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); - addInstr(env, mk_MOVsd_RR(src,tHi)); - addInstr(env, mk_MOVsd_RR(src,tLo)); + addInstr(env, mk_iMOVsd_RR(src,tHi)); + addInstr(env, mk_iMOVsd_RR(src,tLo)); addInstr(env, X86Instr_Sh32(Xsh_SAR, 31, X86RM_Reg(tHi))); *rHi = tHi; *rLo = tLo; return; } + /* 128{HI}to64 */ + if (e->tag == Iex_Unop + && (e->Iex.Unop.op == Iop_128HIto64 + || e->Iex.Unop.op == Iop_128to64)) { + Int off = e->Iex.Unop.op==Iop_128HIto64 ? 8 : 0; + HReg tLo = newVRegI(env); + HReg tHi = newVRegI(env); + HReg vec = iselVecExpr(env, e->Iex.Unop.arg); + X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP()); + X86AMode* espLO = X86AMode_IR(off, hregX86_ESP()); + X86AMode* espHI = X86AMode_IR(off+4, hregX86_ESP()); + addInstr(env, + X86Instr_Alu32R(Xalu_SUB, X86RMI_Imm(16), hregX86_ESP())); + addInstr(env, X86Instr_SseLdSt(False/*store*/, vec, esp0)); + addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(espLO), tLo )); + addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(espHI), tHi )); + addInstr(env, + X86Instr_Alu32R(Xalu_ADD, X86RMI_Imm(16), hregX86_ESP())); + *rHi = tHi; + *rLo = tLo; + return; + } + /* 32Uto64(e) */ if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_32Uto64) { HReg tLo = newVRegI(env); HReg tHi = newVRegI(env); HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); - addInstr(env, mk_MOVsd_RR(src,tLo)); + addInstr(env, mk_iMOVsd_RR(src,tLo)); addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(0), tHi)); *rHi = tHi; *rLo = tLo; @@ -1783,7 +1825,7 @@ static void iselIntExpr64_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) addInstr(env, X86Instr_Set32(cond,tLo)); addInstr(env, X86Instr_Sh32(Xsh_SHL, 31, X86RM_Reg(tLo))); addInstr(env, X86Instr_Sh32(Xsh_SAR, 31, X86RM_Reg(tLo))); - addInstr(env, mk_MOVsd_RR(tLo, tHi)); + addInstr(env, mk_iMOVsd_RR(tLo, tHi)); *rHi = tHi; *rLo = tLo; return; @@ -1795,9 +1837,9 @@ static void iselIntExpr64_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) HReg tLo = newVRegI(env); HReg tHi = newVRegI(env); HReg sHi, sLo; - iselIntExpr64(&sHi, &sLo, env, e->Iex.Unop.arg); - addInstr(env, mk_MOVsd_RR(sHi, tHi)); - addInstr(env, mk_MOVsd_RR(sLo, tLo)); + iselInt64Expr(&sHi, &sLo, env, e->Iex.Unop.arg); + addInstr(env, mk_iMOVsd_RR(sHi, tHi)); + addInstr(env, mk_iMOVsd_RR(sLo, tLo)); addInstr(env, X86Instr_Unary32(Xun_NOT,X86RM_Reg(tHi))); addInstr(env, X86Instr_Unary32(Xun_NOT,X86RM_Reg(tLo))); *rHi = tHi; @@ -1862,10 +1904,10 @@ static void iselIntExpr64_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) tHi = newVRegI(env); tTemp = newVRegI(env); rAmt = iselIntExpr_R(env, e->Iex.Binop.arg2); - iselIntExpr64(&sHi,&sLo, env, e->Iex.Binop.arg1); - addInstr(env, mk_MOVsd_RR(rAmt, hregX86_ECX())); - addInstr(env, mk_MOVsd_RR(sHi, tHi)); - addInstr(env, mk_MOVsd_RR(sLo, tLo)); + iselInt64Expr(&sHi,&sLo, env, e->Iex.Binop.arg1); + addInstr(env, mk_iMOVsd_RR(rAmt, hregX86_ECX())); + addInstr(env, mk_iMOVsd_RR(sHi, tHi)); + addInstr(env, mk_iMOVsd_RR(sLo, tLo)); /* Ok. Now shift amt is in %ecx, and value is in tHi/tLo and those regs are legitimately modifiable. */ addInstr(env, X86Instr_Sh3232(Xsh_SHL, 0/*%cl*/, tLo, tHi)); @@ -1905,10 +1947,10 @@ static void iselIntExpr64_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) tHi = newVRegI(env); tTemp = newVRegI(env); rAmt = iselIntExpr_R(env, e->Iex.Binop.arg2); - iselIntExpr64(&sHi,&sLo, env, e->Iex.Binop.arg1); - addInstr(env, mk_MOVsd_RR(rAmt, hregX86_ECX())); - addInstr(env, mk_MOVsd_RR(sHi, tHi)); - addInstr(env, mk_MOVsd_RR(sLo, tLo)); + iselInt64Expr(&sHi,&sLo, env, e->Iex.Binop.arg1); + addInstr(env, mk_iMOVsd_RR(rAmt, hregX86_ECX())); + addInstr(env, mk_iMOVsd_RR(sHi, tHi)); + addInstr(env, mk_iMOVsd_RR(sLo, tLo)); /* Ok. Now shift amt is in %ecx, and value is in tHi/tLo and those regs are legitimately modifiable. */ addInstr(env, X86Instr_Sh3232(Xsh_SHR, 0/*%cl*/, tHi, tLo)); @@ -1957,7 +1999,7 @@ static void iselIntExpr64_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) movl %rrm2, 0(%esp) fldcw 0(%esp) */ - addInstr(env, mk_MOVsd_RR(rrm, rrm2)); + addInstr(env, mk_iMOVsd_RR(rrm, rrm2)); addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(3), rrm2)); addInstr(env, X86Instr_Sh32(Xsh_SHL, 10, X86RM_Reg(rrm2))); addInstr(env, X86Instr_Alu32R(Xalu_OR, X86RMI_Imm(0x037F), rrm2)); @@ -1998,77 +2040,39 @@ static void iselIntExpr64_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) /* Marshal args, do the call, clear stack. */ doHelperCall( env, False, NULL, e->Iex.CCall.cee, e->Iex.CCall.args ); - addInstr(env, mk_MOVsd_RR(hregX86_EDX(), tHi)); - addInstr(env, mk_MOVsd_RR(hregX86_EAX(), tLo)); + addInstr(env, mk_iMOVsd_RR(hregX86_EDX(), tHi)); + addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), tLo)); *rHi = tHi; *rLo = tLo; return; } -#if 0 - if (e->tag == Iex_GetI) { - /* First off, compute the index expression into an integer reg. - The referenced address will then be 0 + ebp + reg*1, that is, - an X86AMode_IRRS. */ - vassert(e->Iex.GetI.ty == Ity_I64); - HReg tLo = newVRegI(env); - HReg tHi = newVRegI(env); - HReg idx = iselIntExpr_R(env, e->Iex.GetI.ixset); - - /* This (x86) is a little-endian target. The front end will - have laid out the baseblock in accordance with the back-end's - endianness, so this hardwired assumption here that the 64-bit - value is stored little-endian is OK. */ - addInstr(env, X86Instr_Alu32R( - Xalu_MOV, - X86RMI_Mem(X86AMode_IRRS(0, hregX86_EBP(), idx, 0)), - tLo)); - addInstr(env, X86Instr_Alu32R( - Xalu_MOV, - X86RMI_Mem(X86AMode_IRRS(4, hregX86_EBP(), idx, 0)), - tHi)); - *rHi = tHi; - *rLo = tLo; - return; - } -#endif - ppIRExpr(e); - vpanic("iselIntExpr64"); + vpanic("iselInt64Expr"); } - /*---------------------------------------------------------*/ -/*--- ISEL: Floating point expressions (64 bit) ---*/ +/*--- ISEL: Floating point expressions (32 bit) ---*/ /*---------------------------------------------------------*/ -/* Compute a 64-bit floating point value into a register, the identity - of which is returned. As with iselIntExpr_R, the reg may be either - real or virtual; in any case it must not be changed by subsequent - code emitted by the caller. */ - -/* IEEE 754 formats. From http://www.freesoft.org/CIE/RFC/1832/32.htm: - - Type S (1 bit) E (11 bits) F (52 bits) - ---- --------- ----------- ----------- - signalling NaN u 2047 (max) .0uuuuu---u - (with at least - one 1 bit) - quiet NaN u 2047 (max) .1uuuuu---u - - negative infinity 1 2047 (max) .000000---0 - - positive infinity 0 2047 (max) .000000---0 - - negative zero 1 0 .000000---0 - - positive zero 0 0 .000000---0 -*/ +/* Nothing interesting here; really just wrappers for + 64-bit stuff. */ static HReg iselFltExpr ( ISelEnv* env, IRExpr* e ) { - // MatchInfo mi; + HReg r = iselFltExpr_wrk( env, e ); +# if 0 + vex_printf("\n"); ppIRExpr(e); vex_printf("\n"); +# endif + vassert(hregClass(r) == HRcFlt64); /* yes, really Flt64 */ + vassert(hregIsVirtual(r)); + return r; +} + +/* DO NOT CALL THIS DIRECTLY */ +static HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e ) +{ IRType ty = typeOfIRExpr(env->type_env,e); vassert(ty == Ity_F32); @@ -2092,13 +2096,51 @@ static HReg iselFltExpr ( ISelEnv* env, IRExpr* e ) } ppIRExpr(e); - vpanic("iselFltExpr"); + vpanic("iselFltExpr_wrk"); } +/*---------------------------------------------------------*/ +/*--- ISEL: Floating point expressions (64 bit) ---*/ +/*---------------------------------------------------------*/ + +/* Compute a 64-bit floating point value into a register, the identity + of which is returned. As with iselIntExpr_R, the reg may be either + real or virtual; in any case it must not be changed by subsequent + code emitted by the caller. */ + +/* IEEE 754 formats. From http://www.freesoft.org/CIE/RFC/1832/32.htm: + + Type S (1 bit) E (11 bits) F (52 bits) + ---- --------- ----------- ----------- + signalling NaN u 2047 (max) .0uuuuu---u + (with at least + one 1 bit) + quiet NaN u 2047 (max) .1uuuuu---u + + negative infinity 1 2047 (max) .000000---0 + + positive infinity 0 2047 (max) .000000---0 + + negative zero 1 0 .000000---0 + + positive zero 0 0 .000000---0 +*/ + static HReg iselDblExpr ( ISelEnv* env, IRExpr* e ) { - /* MatchInfo mi; */ + HReg r = iselDblExpr_wrk( env, e ); +# if 0 + vex_printf("\n"); ppIRExpr(e); vex_printf("\n"); +# endif + vassert(hregClass(r) == HRcFlt64); + vassert(hregIsVirtual(r)); + return r; +} + +/* DO NOT CALL THIS DIRECTLY */ +static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e ) +{ IRType ty = typeOfIRExpr(env->type_env,e); vassert(e); vassert(ty == Ity_F64); @@ -2143,35 +2185,6 @@ static HReg iselDblExpr ( ISelEnv* env, IRExpr* e ) return res; } -#if 0 - /* special-case: GetI( Add32(Shl32(y,3),const:I32) ):F64 */ - { DECLARE_PATTERN(p_Get_FP_reg); - DEFINE_PATTERN(p_Get_FP_reg, - IRExpr_GetI( - binop(Iop_Add32, binop(Iop_Shl32,bind(0),mkU8(3)), bind(1)), - Ity_F64,56,119 - ) - ); - if (matchIRExpr(&mi, p_Get_FP_reg, e)) { - /* partial match, but we have to ensure bind(1) is a 32-bit - literal. */ - IRExpr* y = mi.bindee[0]; - IRExpr* c = mi.bindee[1]; - if (c->tag == Iex_Const && c->Iex.Const.con->tag == Ico_U32) { - UInt c32 = c->Iex.Const.con->Ico.U32; - HReg res = newVRegF(env); - HReg ry = iselIntExpr_R(env, y); - addInstr(env, - X86Instr_FpLdSt( - True/*load*/, 8, res, - X86AMode_IRRS(c32, hregX86_EBP(), ry, 3)) ); - return res; - } - } - } -#endif - - /* GetI, default case */ if (e->tag == Iex_GetI) { X86AMode* am = genGuestArrayOffset( @@ -2233,7 +2246,7 @@ static HReg iselDblExpr ( ISelEnv* env, IRExpr* e ) movl %rrm2, 0(%esp) fldcw 0(%esp) */ - addInstr(env, mk_MOVsd_RR(rrm, rrm2)); + addInstr(env, mk_iMOVsd_RR(rrm, rrm2)); addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(3), rrm2)); addInstr(env, X86Instr_Sh32(Xsh_SHL, 10, X86RM_Reg(rrm2))); addInstr(env, X86Instr_Alu32R(Xalu_OR, X86RMI_Imm(0x037F), rrm2)); @@ -2256,7 +2269,6 @@ static HReg iselDblExpr ( ISelEnv* env, IRExpr* e ) return dst; } - if (e->tag == Iex_Unop) { X86FpOp fpop = Xfp_INVALID; switch (e->Iex.Unop.op) { @@ -2294,7 +2306,7 @@ static HReg iselDblExpr ( ISelEnv* env, IRExpr* e ) case Iop_I64toF64: { HReg dst = newVRegF(env); HReg rHi,rLo; - iselIntExpr64( &rHi, &rLo, env, e->Iex.Unop.arg); + iselInt64Expr( &rHi, &rLo, env, e->Iex.Unop.arg); addInstr(env, X86Instr_Push(X86RMI_Reg(rHi))); addInstr(env, X86Instr_Push(X86RMI_Reg(rLo))); addInstr(env, X86Instr_FpLdStI( @@ -2310,7 +2322,7 @@ static HReg iselDblExpr ( ISelEnv* env, IRExpr* e ) bit pattern. */ HReg dst = newVRegF(env); HReg rHi, rLo; - iselIntExpr64( &rHi, &rLo, env, e->Iex.Unop.arg); + iselInt64Expr( &rHi, &rLo, env, e->Iex.Unop.arg); addInstr(env, X86Instr_Push(X86RMI_Reg(rHi))); addInstr(env, X86Instr_Push(X86RMI_Reg(rLo))); addInstr(env, X86Instr_FpLdSt( @@ -2345,10 +2357,92 @@ static HReg iselDblExpr ( ISelEnv* env, IRExpr* e ) } ppIRExpr(e); - vpanic("iselDblExpr"); + vpanic("iselDblExpr_wrk"); } +/*---------------------------------------------------------*/ +/*--- ISEL: SIMD (Vector) expressions, 128 bit. ---*/ +/*---------------------------------------------------------*/ + +static HReg iselVecExpr ( ISelEnv* env, IRExpr* e ) +{ + HReg r = iselVecExpr_wrk( env, e ); +# if 0 + vex_printf("\n"); ppIRExpr(e); vex_printf("\n"); +# endif + vassert(hregClass(r) == HRcVec128); + vassert(hregIsVirtual(r)); + return r; +} + + +/* DO NOT CALL THIS DIRECTLY */ +static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e ) +{ + IRType ty = typeOfIRExpr(env->type_env,e); + vassert(e); + vassert(ty == Ity_V128); + + if (e->tag == Iex_Tmp) { + return lookupIRTemp(env, e->Iex.Tmp.tmp); + } + + if (e->tag == Iex_Get) { + HReg dst = newVRegV(env); + addInstr(env, X86Instr_SseLdSt( + True/*load*/, + dst, + X86AMode_IR(e->Iex.Get.offset, hregX86_EBP()) + ) + ); + return dst; + } + + if (e->tag == Iex_Binop) { + switch (e->Iex.Binop.op) { + case Iop_64HLto128: { + HReg r3, r2, r1, r0; + X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP()); + X86AMode* esp4 = advance4(esp0); + X86AMode* esp8 = advance4(esp4); + X86AMode* esp12 = advance4(esp8); + HReg dst = newVRegV(env); + /* do this via the stack (easy, convenient, etc) */ + addInstr(env, + X86Instr_Alu32R(Xalu_SUB, X86RMI_Imm(16), hregX86_ESP())); + /* Do the less significant 64 bits */ + iselInt64Expr(&r1, &r0, env, e->Iex.Binop.arg2); + addInstr(env, X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(r0), esp0)); + addInstr(env, X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(r1), esp4)); + /* Do the more significant 64 bits */ + iselInt64Expr(&r3, &r2, env, e->Iex.Binop.arg1); + addInstr(env, X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(r2), esp8)); + addInstr(env, X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(r3), esp12)); + /* Fetch result back from stack. */ + addInstr(env, X86Instr_SseLdSt(True/*load*/, dst, esp0)); + addInstr(env, + X86Instr_Alu32R(Xalu_ADD, X86RMI_Imm(16), hregX86_ESP())); + return dst; + } + case Iop_Add32Fx4: { + HReg argL = iselVecExpr(env, e->Iex.Binop.arg1); + HReg argR = iselVecExpr(env, e->Iex.Binop.arg2); + HReg dst = newVRegV(env); + addInstr(env, mk_vMOVsd_RR(argL, dst)); + addInstr(env, X86Instr_Sse32Fx4(Xsse_ADDF, argR, dst)); + return dst; + } + default: + break; + } /* switch (e->Iex.Binop.op) */ + + } /* if (e->tag == Iex_Binop) */ + + ppIRExpr(e); + vpanic("iseVecExpr_wrk"); +} + /*---------------------------------------------------------*/ /*--- ISEL: Statements ---*/ @@ -2394,7 +2488,7 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt ) } if (tyd == Ity_I64) { HReg vHi, vLo, rA; - iselIntExpr64(&vHi, &vLo, env, stmt->Ist.STle.data); + iselInt64Expr(&vHi, &vLo, env, stmt->Ist.STle.data); rA = iselIntExpr_R(env, stmt->Ist.STle.addr); addInstr(env, X86Instr_Alu32M( Xalu_MOV, X86RI_Reg(vLo), X86AMode_IR(0, rA))); @@ -2433,11 +2527,17 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt ) HReg vHi, vLo; X86AMode* am = X86AMode_IR(stmt->Ist.Put.offset, hregX86_EBP()); X86AMode* am4 = advance4(am); - iselIntExpr64(&vHi, &vLo, env, stmt->Ist.Put.data); + iselInt64Expr(&vHi, &vLo, env, stmt->Ist.Put.data); addInstr(env, X86Instr_Alu32M( Xalu_MOV, X86RI_Reg(vLo), am )); addInstr(env, X86Instr_Alu32M( Xalu_MOV, X86RI_Reg(vHi), am4 )); return; } + if (ty == Ity_V128) { + HReg vec = iselVecExpr(env, stmt->Ist.Put.data); + X86AMode* am = X86AMode_IR(stmt->Ist.Put.offset, hregX86_EBP()); + addInstr(env, X86Instr_SseLdSt(False/*store*/, vec, am)); + return; + } break; } @@ -2462,7 +2562,7 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt ) if (ty == Ity_I64) { HReg rHi, rLo; X86AMode* am4 = advance4(am); - iselIntExpr64(&rHi, &rLo, env, stmt->Ist.PutI.data); + iselInt64Expr(&rHi, &rLo, env, stmt->Ist.PutI.data); addInstr(env, X86Instr_Alu32M( Xalu_MOV, X86RI_Reg(rLo), am )); addInstr(env, X86Instr_Alu32M( Xalu_MOV, X86RI_Reg(rHi), am4 )); return; @@ -2482,10 +2582,10 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt ) } if (ty == Ity_I64) { HReg rHi, rLo, dstHi, dstLo; - iselIntExpr64(&rHi,&rLo, env, stmt->Ist.Tmp.data); + iselInt64Expr(&rHi,&rLo, env, stmt->Ist.Tmp.data); lookupIRTemp64( &dstHi, &dstLo, env, tmp); - addInstr(env, mk_MOVsd_RR(rHi,dstHi) ); - addInstr(env, mk_MOVsd_RR(rLo,dstLo) ); + addInstr(env, mk_iMOVsd_RR(rHi,dstHi) ); + addInstr(env, mk_iMOVsd_RR(rLo,dstLo) ); return; } if (ty == Ity_I1) { @@ -2506,6 +2606,12 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt ) addInstr(env, X86Instr_FpUnary(Xfp_MOV,src,dst)); return; } + if (ty == Ity_V128) { + HReg dst = lookupIRTemp(env, tmp); + HReg src = iselVecExpr(env, stmt->Ist.Tmp.data); + addInstr(env, mk_vMOVsd_RR(src,dst)); + return; + } break; } @@ -2533,15 +2639,15 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt ) /* The returned value is in %edx:%eax. Park it in the register-pair associated with tmp. */ lookupIRTemp64( &dstHi, &dstLo, env, d->tmp); - addInstr(env, mk_MOVsd_RR(hregX86_EDX(),dstHi) ); - addInstr(env, mk_MOVsd_RR(hregX86_EAX(),dstLo) ); + addInstr(env, mk_iMOVsd_RR(hregX86_EDX(),dstHi) ); + addInstr(env, mk_iMOVsd_RR(hregX86_EAX(),dstLo) ); return; } if (retty == Ity_I32 || retty == Ity_I16 || retty == Ity_I8) { /* The returned value is in %eax. Park it in the register associated with tmp. */ HReg dst = lookupIRTemp(env, d->tmp); - addInstr(env, mk_MOVsd_RR(hregX86_EAX(),dst) ); + addInstr(env, mk_iMOVsd_RR(hregX86_EAX(),dst) ); return; } break; @@ -2621,11 +2727,12 @@ HInstrArray* iselBB_X86 ( IRBB* bb ) 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_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_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"); }