|
From: <sv...@va...> - 2015-01-17 19:28:38
|
Author: sewardj
Date: Sat Jan 17 19:28:29 2015
New Revision: 3067
Log:
Code generation improvements for amd64 NCode:
* add and use AMD64AMode_IRS
* use testq instead of andq for misaligned-or-hi check
* use movzwq instead of mov and and-w-0xFFFF
* use short form immediates for loading address of helper fns
Modified:
branches/NCODE/priv/host_amd64_defs.c
branches/NCODE/priv/host_amd64_defs.h
branches/NCODE/priv/host_amd64_isel.c
Modified: branches/NCODE/priv/host_amd64_defs.c
==============================================================================
--- branches/NCODE/priv/host_amd64_defs.c (original)
+++ branches/NCODE/priv/host_amd64_defs.c Sat Jan 17 19:28:29 2015
@@ -82,7 +82,8 @@
Int r;
static const HChar* ireg32_names[16]
= { "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
- "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d" };
+ "%r8d", "%r9d", "%r10d", "%r11d",
+ "%r12d", "%r13d", "%r14d", "%r15d" };
/* Be generic for all virtual regs. */
if (hregIsVirtual(reg)) {
ppHReg(reg);
@@ -101,6 +102,31 @@
}
}
+static void ppHRegAMD64_lo16 ( HReg reg )
+{
+ Int r;
+ static const HChar* ireg16_names[16]
+ = { "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di",
+ "%r8w", "%r9w", "%r10w", "%r11w",
+ "%r12w", "%r13w", "%r14w", "%r15w" };
+ /* Be generic for all virtual regs. */
+ if (hregIsVirtual(reg)) {
+ ppHReg(reg);
+ vex_printf("w");
+ return;
+ }
+ /* But specific for real regs. */
+ switch (hregClass(reg)) {
+ case HRcInt64:
+ r = hregNumber(reg);
+ vassert(r >= 0 && r < 16);
+ vex_printf("%s", ireg16_names[r]);
+ return;
+ default:
+ vpanic("ppHRegAMD64_lo16: invalid regclass");
+ }
+}
+
void getAllocableRegs_AMD64 ( Int* nregs, HReg** arr )
{
#if 0
@@ -178,6 +204,15 @@
am->Aam.IR.reg = reg;
return am;
}
+AMD64AMode* AMD64AMode_IRS ( UInt imm32, HReg reg, Int shift ) {
+ AMD64AMode* am = LibVEX_Alloc(sizeof(AMD64AMode));
+ am->tag = Aam_IRS;
+ am->Aam.IRS.imm = imm32;
+ am->Aam.IRS.reg = reg;
+ am->Aam.IRS.shift = shift;
+ vassert(shift >= 0 && shift <= 3);
+ return am;
+}
AMD64AMode* AMD64AMode_IRRS ( UInt imm32, HReg base, HReg indEx, Int shift ) {
AMD64AMode* am = LibVEX_Alloc(sizeof(AMD64AMode));
am->tag = Aam_IRRS;
@@ -199,6 +234,11 @@
ppHRegAMD64(am->Aam.IR.reg);
vex_printf(")");
return;
+ case Aam_IRS:
+ vex_printf("0x%x(,", am->Aam.IRS.imm);
+ ppHRegAMD64(am->Aam.IRS.reg);
+ vex_printf(",%d)", 1 << am->Aam.IRS.shift);
+ return;
case Aam_IRRS:
vex_printf("0x%x(", am->Aam.IRRS.imm);
ppHRegAMD64(am->Aam.IRRS.base);
@@ -216,6 +256,9 @@
case Aam_IR:
addHRegUse(u, HRmRead, am->Aam.IR.reg);
return;
+ case Aam_IRS:
+ addHRegUse(u, HRmRead, am->Aam.IRS.reg);
+ return;
case Aam_IRRS:
addHRegUse(u, HRmRead, am->Aam.IRRS.base);
addHRegUse(u, HRmRead, am->Aam.IRRS.index);
@@ -230,6 +273,9 @@
case Aam_IR:
am->Aam.IR.reg = lookupHRegRemap(m, am->Aam.IR.reg);
return;
+ case Aam_IRS:
+ am->Aam.IRS.reg = lookupHRegRemap(m, am->Aam.IRS.reg);
+ return;
case Aam_IRRS:
am->Aam.IRRS.base = lookupHRegRemap(m, am->Aam.IRRS.base);
am->Aam.IRRS.index = lookupHRegRemap(m, am->Aam.IRRS.index);
@@ -722,6 +768,14 @@
i->Ain.MovxLQ.dst = dst;
return i;
}
+AMD64Instr* AMD64Instr_MovxWQ ( Bool syned, HReg src, HReg dst ) {
+ AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
+ i->tag = Ain_MovxWQ;
+ i->Ain.MovxWQ.syned = syned;
+ i->Ain.MovxWQ.src = src;
+ i->Ain.MovxWQ.dst = dst;
+ return i;
+}
AMD64Instr* AMD64Instr_LoadEX ( UChar szSmall, Bool syned,
AMD64AMode* src, HReg dst ) {
AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
@@ -1000,6 +1054,13 @@
i->tag = Ain_NC_CallR11;
return i;
}
+AMD64Instr* AMD64Instr_NC_TestQ ( HReg src, HReg dst ) {
+ AMD64Instr* i = LibVEX_Alloc(sizeof(AMD64Instr));
+ i->tag = Ain_NC_TestQ;
+ i->Ain.NC_TestQ.src = src;
+ i->Ain.NC_TestQ.dst = dst;
+ return i;
+}
void ppAMD64Instr ( const AMD64Instr* i, Bool mode64 )
{
@@ -1118,6 +1179,12 @@
vex_printf(",");
ppHRegAMD64(i->Ain.MovxLQ.dst);
return;
+ case Ain_MovxWQ:
+ vex_printf("mov%cwq ", i->Ain.MovxWQ.syned ? 's' : 'z');
+ ppHRegAMD64_lo16(i->Ain.MovxWQ.src);
+ vex_printf(",");
+ ppHRegAMD64(i->Ain.MovxWQ.dst);
+ return;
case Ain_LoadEX:
if (i->Ain.LoadEX.szSmall==4 && !i->Ain.LoadEX.syned) {
vex_printf("movl ");
@@ -1342,6 +1409,13 @@
vex_printf("call* %%r11");
return;
}
+ case Ain_NC_TestQ: {
+ vex_printf("testq ");
+ ppHRegAMD64(i->Ain.NC_TestQ.src);
+ vex_printf(",");
+ ppHRegAMD64(i->Ain.NC_TestQ.dst);
+ return;
+ }
default:
vpanic("ppAMD64Instr");
}
@@ -1489,6 +1563,10 @@
addHRegUse(u, HRmRead, i->Ain.MovxLQ.src);
addHRegUse(u, HRmWrite, i->Ain.MovxLQ.dst);
return;
+ case Ain_MovxWQ:
+ addHRegUse(u, HRmRead, i->Ain.MovxWQ.src);
+ addHRegUse(u, HRmWrite, i->Ain.MovxWQ.dst);
+ return;
case Ain_LoadEX:
addRegUsage_AMD64AMode(u, i->Ain.LoadEX.src);
addHRegUse(u, HRmWrite, i->Ain.LoadEX.dst);
@@ -1739,6 +1817,10 @@
mapReg(m, &i->Ain.MovxLQ.src);
mapReg(m, &i->Ain.MovxLQ.dst);
return;
+ case Ain_MovxWQ:
+ mapReg(m, &i->Ain.MovxWQ.src);
+ mapReg(m, &i->Ain.MovxWQ.dst);
+ return;
case Ain_LoadEX:
mapRegs_AMD64AMode(m, i->Ain.LoadEX.src);
mapReg(m, &i->Ain.LoadEX.dst);
@@ -2098,6 +2180,12 @@
greg, d32(base,index,scale)
| index != RSP
= 10 greg 100, scale index base, d32
+
+ -----------------------------------------------
+
+ greg, d32(,index,scale)
+ | index != RSP
+ = 00 greg 100, scale index 101, d32
*/
static void doAMode_M ( /*MOD*/AssemblyBuffer* ab, HReg greg, AMD64AMode* am )
{
@@ -2168,6 +2256,17 @@
vpanic("doAMode_M: can't emit amode IRRS");
/*NOTREACHED*/
}
+ if (am->tag == Aam_IRS) {
+ if (! sameHReg(am->Aam.IRS.reg, hregAMD64_RSP())) {
+ PUT(ab, mkModRegRM(0, iregBits210(greg), 4));
+ PUT(ab, mkSIB(am->Aam.IRS.shift, iregBits210(am->Aam.IRS.reg), 5));
+ emit32(ab, am->Aam.IRS.imm);
+ return;
+ }
+ ppAMD64AMode(am);
+ vpanic("doAMode_M: can't emit amode IRRS");
+ /*NOTREACHED*/
+ }
vpanic("doAMode_M: unknown amode");
/*NOTREACHED*/
}
@@ -2191,19 +2290,30 @@
/* Make up a REX byte, with W=1 (size=64), for a (greg,amode) pair. */
static UChar rexAMode_M ( HReg greg, AMD64AMode* am )
{
- if (am->tag == Aam_IR) {
- UChar W = 1; /* we want 64-bit mode */
- UChar R = iregBit3(greg);
- UChar X = 0; /* not relevant */
- UChar B = iregBit3(am->Aam.IR.reg);
- return toUChar(0x40 + ((W << 3) | (R << 2) | (X << 1) | (B << 0)));
- }
- if (am->tag == Aam_IRRS) {
- UChar W = 1; /* we want 64-bit mode */
- UChar R = iregBit3(greg);
- UChar X = iregBit3(am->Aam.IRRS.index);
- UChar B = iregBit3(am->Aam.IRRS.base);
- return toUChar(0x40 + ((W << 3) | (R << 2) | (X << 1) | (B << 0)));
+ switch (am->tag) {
+ case Aam_IR: {
+ UChar W = 1; /* we want 64-bit mode */
+ UChar R = iregBit3(greg);
+ UChar X = 0; /* not relevant */
+ UChar B = iregBit3(am->Aam.IR.reg);
+ return toUChar(0x40 + ((W << 3) | (R << 2) | (X << 1) | (B << 0)));
+ }
+ case Aam_IRS: {
+ UChar W = 1; /* we want 64-bit mode */
+ UChar R = iregBit3(greg);
+ UChar X = iregBit3(am->Aam.IRS.reg);
+ UChar B = 0; /* there is no base register -- base is a constant. */
+ return toUChar(0x40 + ((W << 3) | (R << 2) | (X << 1) | (B << 0)));
+ }
+ case Aam_IRRS: {
+ UChar W = 1; /* we want 64-bit mode */
+ UChar R = iregBit3(greg);
+ UChar X = iregBit3(am->Aam.IRRS.index);
+ UChar B = iregBit3(am->Aam.IRRS.base);
+ return toUChar(0x40 + ((W << 3) | (R << 2) | (X << 1) | (B << 0)));
+ }
+ default:
+ break;
}
vassert(0);
return 0; /*NOTREACHED*/
@@ -2339,7 +2449,7 @@
switch (i->tag) {
case Ain_Imm64:
- if (i->Ain.Imm64.imm64 <= 0xFFFFFULL) {
+ if (i->Ain.Imm64.imm64 <= /*0xFFFFFULL*/ 0x39000000ULL) {
/* Use the short form (load into 32 bit reg, + default
widening rule) for constants under 1 million. We could
use this form for the range 0 to 0x7FFFFFFF inclusive, but
@@ -2984,6 +3094,14 @@
}
goto done;
+ case Ain_MovxWQ:
+ /* Need REX.W = 1 here, but rexAMode_R does that for us. */
+ PUT(ab, rexAMode_R(i->Ain.MovxWQ.dst, i->Ain.MovxWQ.src));
+ PUT(ab, 0x0F);
+ PUT(ab, i->Ain.MovxWQ.syned ? 0xBF : 0xB7);
+ doAMode_R(ab, i->Ain.MovxWQ.dst, i->Ain.MovxWQ.src);
+ goto done;
+
case Ain_LoadEX:
if (i->Ain.LoadEX.szSmall == 1 && !i->Ain.LoadEX.syned) {
/* movzbq */
@@ -3600,6 +3718,15 @@
goto done;
}
+ case Ain_NC_TestQ: {
+ HReg greg = i->Ain.NC_TestQ.src;
+ HReg ereg = i->Ain.NC_TestQ.dst;
+ PUT(ab, rexAMode_R(greg, ereg));
+ PUT(ab, 0x85);
+ doAMode_R(ab, greg, ereg);
+ goto done;
+ }
+
default:
goto bad;
}
@@ -4118,11 +4245,16 @@
HReg dstR = mapNReg(nregMap, ni->Nin.AluWri.dst);
HReg srcLR = mapNReg(nregMap, ni->Nin.AluWri.srcL);
HWord imm = ni->Nin.AluWri.srcR;
- if (how == Nalu_AND && fitsIn32Bits((ULong)imm)) {
- if (!sameHReg(srcLR, dstR)) {
- HI( mk_iMOVsd_RR(srcLR, dstR) );
- }
- HI( AMD64Instr_Alu64R(Aalu_AND, AMD64RMI_Imm(imm), dstR) );
+ // Verified correct, but currently unused
+ //if (how == Nalu_AND && fitsIn32Bits((ULong)imm)) {
+ // if (!sameHReg(srcLR, dstR)) {
+ // HI( mk_iMOVsd_RR(srcLR, dstR) );
+ // }
+ // HI( AMD64Instr_Alu64R(Aalu_AND, AMD64RMI_Imm(imm), dstR) );
+ // break;
+ //}
+ if (how == Nalu_AND && imm == 0xFFFFULL) {
+ HI( AMD64Instr_MovxWQ(False/*!syned*/, srcLR, dstR) );
break;
}
goto unhandled;
@@ -4134,7 +4266,7 @@
if (ni->Nin.SetFlagsWri.how == Nsf_TEST) {
HReg r11 = hregAMD64_R11();
HI( AMD64Instr_Imm64((ULong)imm, r11) );
- HI( AMD64Instr_Alu64R(Aalu_AND, AMD64RMI_Reg(reg), r11) );
+ HI( AMD64Instr_NC_TestQ(r11, reg) );
break;
}
if (ni->Nin.SetFlagsWri.how == Nsf_CMP && fitsIn32Bits((ULong)imm)) {
@@ -4163,9 +4295,7 @@
HReg indexR = mapNReg(nregMap, addr->Nea.IRS.index);
UChar shift = addr->Nea.IRS.shift;
if (szB == 8 && shift <= 3) {
- HReg r11 = hregAMD64_R11();
- AMD64AMode* am = AMD64AMode_IRRS((UInt)imm, r11, indexR, shift);
- HI( AMD64Instr_Imm64(0, r11) );
+ AMD64AMode* am = AMD64AMode_IRS((UInt)imm, indexR, shift);
HI( AMD64Instr_Alu64R(Aalu_MOV, AMD64RMI_Mem(am), dstR) );
break;
}
Modified: branches/NCODE/priv/host_amd64_defs.h
==============================================================================
--- branches/NCODE/priv/host_amd64_defs.h (original)
+++ branches/NCODE/priv/host_amd64_defs.h Sat Jan 17 19:28:29 2015
@@ -175,6 +175,7 @@
typedef
enum {
Aam_IR, /* Immediate + Reg */
+ Aam_IRS, /* Immediate + (Reg << Shift) */
Aam_IRRS /* Immediate + Reg1 + (Reg2 << Shift) */
}
AMD64AModeTag;
@@ -189,6 +190,11 @@
} IR;
struct {
UInt imm;
+ HReg reg;
+ Int shift; /* 0, 1, 2 or 3 only */
+ } IRS;
+ struct {
+ UInt imm;
HReg base;
HReg index;
Int shift; /* 0, 1, 2 or 3 only */
@@ -198,10 +204,9 @@
AMD64AMode;
extern AMD64AMode* AMD64AMode_IR ( UInt, HReg );
+extern AMD64AMode* AMD64AMode_IRS ( UInt, HReg, Int );
extern AMD64AMode* AMD64AMode_IRRS ( UInt, HReg, HReg, Int );
-extern AMD64AMode* dopyAMD64AMode ( AMD64AMode* );
-
extern void ppAMD64AMode ( AMD64AMode* );
@@ -417,7 +422,8 @@
Ain_XIndir, /* indirect transfer to GA */
Ain_XAssisted, /* assisted transfer to GA */
Ain_CMov64, /* conditional move */
- Ain_MovxLQ, /* reg-reg move, zx-ing/sx-ing top half */
+ Ain_MovxLQ, /* reg-reg move, zx-ing/sx-ing top 32 bits */
+ Ain_MovxWQ, /* reg-reg move, zx-ing/sx-ing top 48 bits */
Ain_LoadEX, /* mov{s,z}{b,w,l}q from mem to reg */
Ain_Store, /* store 32/16/8 bit value in memory */
Ain_Set64, /* convert condition code to 64-bit value */
@@ -456,7 +462,8 @@
// The following for NCode only
Ain_NC_Jmp32, /* cond. br. w/ 32-bit offset, 0F 8x xx xx xx xx */
/* or cond==Acc_ALWAYS, giving, E9 xx xx xx xx */
- Ain_NC_CallR11 /* Literally "call *%r11" */
+ Ain_NC_CallR11, /* Literally "call *%r11" */
+ Ain_NC_TestQ /* testq reg, reg */
}
AMD64InstrTag;
@@ -559,12 +566,18 @@
AMD64RM* src;
HReg dst;
} CMov64;
- /* reg-reg move, sx-ing/zx-ing top half */
+ /* reg-reg move, sx-ing/zx-ing top 32 bits */
struct {
Bool syned;
HReg src;
HReg dst;
} MovxLQ;
+ /* reg-reg move, sx-ing/zx-ing top 32 bits */
+ struct {
+ Bool syned;
+ HReg src;
+ HReg dst;
+ } MovxWQ;
/* Sign/Zero extending loads. Dst size is always 64 bits. */
struct {
UChar szSmall; /* only 1, 2 or 4 */
@@ -758,6 +771,15 @@
struct {
/* Literally "call *%r11" */
} NC_CallR11;
+ struct {
+ /* testq reg, reg. The src and dst characterisation is
+ somewhat spurious considering that the registers can be
+ swapped without affecting the result, and that there is
+ no result. */
+ HReg src;
+ HReg dst;
+ }
+ NC_TestQ;
} Ain;
}
AMD64Instr;
@@ -782,6 +804,7 @@
AMD64CondCode cond, IRJumpKind jk );
extern AMD64Instr* AMD64Instr_CMov64 ( AMD64CondCode, AMD64RM* src, HReg dst );
extern AMD64Instr* AMD64Instr_MovxLQ ( Bool syned, HReg src, HReg dst );
+extern AMD64Instr* AMD64Instr_MovxWQ ( Bool syned, HReg src, HReg dst );
extern AMD64Instr* AMD64Instr_LoadEX ( UChar szSmall, Bool syned,
AMD64AMode* src, HReg dst );
extern AMD64Instr* AMD64Instr_Store ( UChar sz, HReg src, AMD64AMode* dst );
@@ -819,6 +842,7 @@
HReg* regsA, HReg* regsS );
extern AMD64Instr* AMD64Instr_NC_Jmp32 ( AMD64CondCode cc );
extern AMD64Instr* AMD64Instr_NC_CallR11 ( void );
+extern AMD64Instr* AMD64Instr_NC_TestQ ( HReg src, HReg dst );
extern void ppAMD64Instr ( const AMD64Instr*, Bool );
Modified: branches/NCODE/priv/host_amd64_isel.c
==============================================================================
--- branches/NCODE/priv/host_amd64_isel.c (original)
+++ branches/NCODE/priv/host_amd64_isel.c Sat Jan 17 19:28:29 2015
@@ -266,6 +266,10 @@
toBool( hregClass(am->Aam.IR.reg) == HRcInt64
&& (hregIsVirtual(am->Aam.IR.reg)
|| sameHReg(am->Aam.IR.reg, hregAMD64_RBP())) );
+ case Aam_IRS:
+ return
+ toBool( hregClass(am->Aam.IRS.reg) == HRcInt64
+ && hregIsVirtual(am->Aam.IRS.reg) );
case Aam_IRRS:
return
toBool( hregClass(am->Aam.IRRS.base) == HRcInt64
@@ -1036,8 +1040,7 @@
Aalu_AND, AMD64RMI_Imm(0xFF), dst));
break;
case Iop_Shr16:
- addInstr(env, AMD64Instr_Alu64R(
- Aalu_AND, AMD64RMI_Imm(0xFFFF), dst));
+ addInstr(env, AMD64Instr_MovxWQ(False, dst, dst));
break;
case Iop_Shr32:
addInstr(env, AMD64Instr_MovxLQ(False, dst, dst));
@@ -1047,8 +1050,7 @@
addInstr(env, AMD64Instr_Sh64(Ash_SAR, 56, dst));
break;
case Iop_Sar16:
- addInstr(env, AMD64Instr_Sh64(Ash_SHL, 48, dst));
- addInstr(env, AMD64Instr_Sh64(Ash_SAR, 48, dst));
+ addInstr(env, AMD64Instr_MovxWQ(True, dst, dst));
break;
case Iop_Sar32:
addInstr(env, AMD64Instr_MovxLQ(True, dst, dst));
@@ -1467,32 +1469,36 @@
}
case Iop_8Uto16:
case Iop_8Uto32:
- case Iop_8Uto64:
- case Iop_16Uto64:
- case Iop_16Uto32: {
- HReg dst = newVRegI(env);
- HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
- Bool srcIs16 = toBool( e->Iex.Unop.op==Iop_16Uto32
- || e->Iex.Unop.op==Iop_16Uto64 );
- UInt mask = srcIs16 ? 0xFFFF : 0xFF;
+ case Iop_8Uto64: {
+ HReg dst = newVRegI(env);
+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
addInstr(env, mk_iMOVsd_RR(src,dst) );
addInstr(env, AMD64Instr_Alu64R(Aalu_AND,
- AMD64RMI_Imm(mask), dst));
+ AMD64RMI_Imm(0xFF), dst));
+ return dst;
+ }
+ case Iop_16Uto64:
+ case Iop_16Uto32: {
+ HReg dst = newVRegI(env);
+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
+ addInstr(env, AMD64Instr_MovxWQ(False/*!syned*/, src, dst));
return dst;
}
case Iop_8Sto16:
- case Iop_8Sto64:
case Iop_8Sto32:
+ case Iop_8Sto64: {
+ HReg dst = newVRegI(env);
+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
+ addInstr(env, mk_iMOVsd_RR(src,dst) );
+ addInstr(env, AMD64Instr_Sh64(Ash_SHL, 56, dst));
+ addInstr(env, AMD64Instr_Sh64(Ash_SAR, 56, dst));
+ return dst;
+ }
case Iop_16Sto32:
case Iop_16Sto64: {
- HReg dst = newVRegI(env);
- HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
- Bool srcIs16 = toBool( e->Iex.Unop.op==Iop_16Sto32
- || e->Iex.Unop.op==Iop_16Sto64 );
- UInt amt = srcIs16 ? 48 : 56;
- addInstr(env, mk_iMOVsd_RR(src,dst) );
- addInstr(env, AMD64Instr_Sh64(Ash_SHL, amt, dst));
- addInstr(env, AMD64Instr_Sh64(Ash_SAR, amt, dst));
+ HReg dst = newVRegI(env);
+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
+ addInstr(env, AMD64Instr_MovxWQ(True/*syned*/, src, dst));
return dst;
}
case Iop_Not8:
@@ -1991,9 +1997,19 @@
&& e->Iex.Binop.arg2->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8) {
UInt shift = e->Iex.Binop.arg2->Iex.Binop.arg2->Iex.Const.con->Ico.U8;
if (shift == 1 || shift == 2 || shift == 3) {
- HReg r1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
- HReg r2 = iselIntExpr_R(env, e->Iex.Binop.arg2->Iex.Binop.arg1 );
- return AMD64AMode_IRRS(0, r1, r2, shift);
+ IRExpr* expr1 = e->Iex.Binop.arg1;
+ IRExpr* expr2 = e->Iex.Binop.arg2->Iex.Binop.arg1;
+ if (expr1->tag == Iex_Const
+ && expr1->Iex.Const.con->tag == Ico_U64/*must always be true*/
+ && fitsIn32Bits(expr1->Iex.Const.con->Ico.U64)) {
+ HReg r2 = iselIntExpr_R(env, expr2);
+ return AMD64AMode_IRS(toUInt(expr1->Iex.Const.con->Ico.U64),
+ r2, shift);
+ } else {
+ HReg r1 = iselIntExpr_R(env, expr1);
+ HReg r2 = iselIntExpr_R(env, expr2);
+ return AMD64AMode_IRRS(0, r1, r2, shift);
+ }
}
}
|