113
113
return IRExpr_Binder(binder);
116
static Bool isZeroU8 ( IRExpr* e )
118
return e->tag == Iex_Const
119
&& e->Iex.Const.con->tag == Ico_U8
120
&& e->Iex.Const.con->Ico.U8 == 0;
123
static Bool isZeroU32 ( IRExpr* e )
125
return e->tag == Iex_Const
126
&& e->Iex.Const.con->tag == Ico_U32
127
&& e->Iex.Const.con->Ico.U32 == 0;
130
static Bool isZeroU64 ( IRExpr* e )
132
return e->tag == Iex_Const
133
&& e->Iex.Const.con->tag == Ico_U64
134
&& e->Iex.Const.con->Ico.U64 == 0ULL;
118
138
/*---------------------------------------------------------*/
815
/* Pattern: Sub32(0,x) */
816
if (e->Iex.Binop.op == Iop_Sub32 && isZeroU32(e->Iex.Binop.arg1)) {
817
HReg dst = newVRegI(env);
818
HReg reg = iselIntExpr_R(env, e->Iex.Binop.arg2);
819
addInstr(env, mk_iMOVsd_RR(reg,dst));
820
addInstr(env, X86Instr_Unary32(Xun_NEG,dst));
796
824
/* Is it an addition or logical style op? */
797
825
switch (e->Iex.Binop.op) {
798
826
case Iop_Add8: case Iop_Add16: case Iop_Add32:
1006
1034
/* --------- UNARY OP --------- */
1007
1035
case Iex_Unop: {
1008
1037
/* 1Uto8(32to1(expr32)) */
1009
DEFINE_PATTERN(p_32to1_then_1Uto8,
1010
unop(Iop_1Uto8,unop(Iop_32to1,bind(0))));
1011
if (matchIRExpr(&mi,p_32to1_then_1Uto8,e)) {
1012
IRExpr* expr32 = mi.bindee[0];
1013
HReg dst = newVRegI(env);
1014
HReg src = iselIntExpr_R(env, expr32);
1015
addInstr(env, mk_iMOVsd_RR(src,dst) );
1016
addInstr(env, X86Instr_Alu32R(Xalu_AND,
1017
X86RMI_Imm(1), dst));
1038
if (e->Iex.Unop.op == Iop_1Uto8) {
1039
DECLARE_PATTERN(p_32to1_then_1Uto8);
1040
DEFINE_PATTERN(p_32to1_then_1Uto8,
1041
unop(Iop_1Uto8,unop(Iop_32to1,bind(0))));
1042
if (matchIRExpr(&mi,p_32to1_then_1Uto8,e)) {
1043
IRExpr* expr32 = mi.bindee[0];
1044
HReg dst = newVRegI(env);
1045
HReg src = iselIntExpr_R(env, expr32);
1046
addInstr(env, mk_iMOVsd_RR(src,dst) );
1047
addInstr(env, X86Instr_Alu32R(Xalu_AND,
1048
X86RMI_Imm(1), dst));
1053
/* 8Uto32(LDle(expr32)) */
1054
if (e->Iex.Unop.op == Iop_8Uto32) {
1055
DECLARE_PATTERN(p_LDle8_then_8Uto32);
1056
DEFINE_PATTERN(p_LDle8_then_8Uto32,
1058
IRExpr_Load(Iend_LE,Ity_I8,bind(0))) );
1059
if (matchIRExpr(&mi,p_LDle8_then_8Uto32,e)) {
1060
HReg dst = newVRegI(env);
1061
X86AMode* amode = iselIntExpr_AMode ( env, mi.bindee[0] );
1062
addInstr(env, X86Instr_LoadEX(1,False,amode,dst));
1067
/* 8Sto32(LDle(expr32)) */
1068
if (e->Iex.Unop.op == Iop_8Sto32) {
1069
DECLARE_PATTERN(p_LDle8_then_8Sto32);
1070
DEFINE_PATTERN(p_LDle8_then_8Sto32,
1072
IRExpr_Load(Iend_LE,Ity_I8,bind(0))) );
1073
if (matchIRExpr(&mi,p_LDle8_then_8Sto32,e)) {
1074
HReg dst = newVRegI(env);
1075
X86AMode* amode = iselIntExpr_AMode ( env, mi.bindee[0] );
1076
addInstr(env, X86Instr_LoadEX(1,True,amode,dst));
1021
1081
/* 16Uto32(LDle(expr32)) */
1082
if (e->Iex.Unop.op == Iop_16Uto32) {
1023
1083
DECLARE_PATTERN(p_LDle16_then_16Uto32);
1024
1084
DEFINE_PATTERN(p_LDle16_then_16Uto32,
1025
1085
unop(Iop_16Uto32,
1095
/* 8Uto32(GET:I8) */
1096
if (e->Iex.Unop.op == Iop_8Uto32) {
1097
if (e->Iex.Unop.arg->tag == Iex_Get) {
1100
vassert(e->Iex.Unop.arg->Iex.Get.ty == Ity_I8);
1101
dst = newVRegI(env);
1102
amode = X86AMode_IR(e->Iex.Unop.arg->Iex.Get.offset,
1104
addInstr(env, X86Instr_LoadEX(1,False,amode,dst));
1109
/* 16to32(GET:I16) */
1110
if (e->Iex.Unop.op == Iop_16Uto32) {
1111
if (e->Iex.Unop.arg->tag == Iex_Get) {
1114
vassert(e->Iex.Unop.arg->Iex.Get.ty == Ity_I16);
1115
dst = newVRegI(env);
1116
amode = X86AMode_IR(e->Iex.Unop.arg->Iex.Get.offset,
1118
addInstr(env, X86Instr_LoadEX(2,False,amode,dst));
1035
1123
switch (e->Iex.Unop.op) {
1036
1124
case Iop_8Uto16:
1037
1125
case Iop_8Uto32:
1122
1210
X86RMI_Reg(tmp), dst));
1214
case Iop_CmpwNEZ32: {
1128
1215
HReg dst = newVRegI(env);
1129
HReg reg = iselIntExpr_R(env, e->Iex.Unop.arg);
1130
addInstr(env, mk_iMOVsd_RR(reg,dst));
1216
HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
1217
addInstr(env, mk_iMOVsd_RR(src,dst));
1131
1218
addInstr(env, X86Instr_Unary32(Xun_NEG,dst));
1219
addInstr(env, X86Instr_Alu32R(Xalu_OR,
1220
X86RMI_Reg(src), dst));
1221
addInstr(env, X86Instr_Sh32(Xsh_SAR, 31, dst));
1227
HReg dst = newVRegI(env);
1228
HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
1229
addInstr(env, mk_iMOVsd_RR(src, dst));
1230
addInstr(env, X86Instr_Unary32(Xun_NEG, dst));
1231
addInstr(env, X86Instr_Alu32R(Xalu_OR, X86RMI_Reg(src), dst));
1246
/* ReinterpF32asI32(e) */
1247
/* Given an IEEE754 single, produce an I32 with the same bit
1248
pattern. Keep stack 8-aligned even though only using 4
1250
case Iop_ReinterpF32asI32: {
1251
HReg rf = iselFltExpr(env, e->Iex.Unop.arg);
1252
HReg dst = newVRegI(env);
1253
X86AMode* zero_esp = X86AMode_IR(0, hregX86_ESP());
1255
set_FPU_rounding_default(env);
1257
sub_from_esp(env, 8);
1258
/* gstF %rf, 0(%esp) */
1260
X86Instr_FpLdSt(False/*store*/, 4, rf, zero_esp));
1261
/* movl 0(%esp), %dst */
1263
X86Instr_Alu32R(Xalu_MOV, X86RMI_Mem(zero_esp), dst));
1146
1269
case Iop_16to8:
1147
1270
case Iop_32to8:
1148
1271
case Iop_32to16:
1225
1348
case Iex_Mux0X: {
1226
1349
if ((ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8)
1227
1350
&& typeOfIRExpr(env->type_env,e->Iex.Mux0X.cond) == Ity_I8) {
1229
HReg rX = iselIntExpr_R(env, e->Iex.Mux0X.exprX);
1230
X86RM* r0 = iselIntExpr_RM(env, e->Iex.Mux0X.expr0);
1231
HReg dst = newVRegI(env);
1352
HReg rX = iselIntExpr_R(env, e->Iex.Mux0X.exprX);
1353
X86RM* r0 = iselIntExpr_RM(env, e->Iex.Mux0X.expr0);
1354
HReg dst = newVRegI(env);
1232
1355
addInstr(env, mk_iMOVsd_RR(rX,dst));
1233
r8 = iselIntExpr_R(env, e->Iex.Mux0X.cond);
1356
r8 = iselIntExpr_RM(env, e->Iex.Mux0X.cond);
1234
1357
addInstr(env, X86Instr_Test32(0xFF, r8));
1235
1358
addInstr(env, X86Instr_CMov32(Xcc_Z,r0,dst));
1292
1415
IRType ty = typeOfIRExpr(env->type_env,e);
1293
1416
vassert(ty == Ity_I32);
1418
/* Add32( Add32(expr1, Shl32(expr2, simm)), imm32 ) */
1419
if (e->tag == Iex_Binop
1420
&& e->Iex.Binop.op == Iop_Add32
1421
&& e->Iex.Binop.arg2->tag == Iex_Const
1422
&& e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U32
1423
&& e->Iex.Binop.arg1->tag == Iex_Binop
1424
&& e->Iex.Binop.arg1->Iex.Binop.op == Iop_Add32
1425
&& e->Iex.Binop.arg1->Iex.Binop.arg2->tag == Iex_Binop
1426
&& e->Iex.Binop.arg1->Iex.Binop.arg2->Iex.Binop.op == Iop_Shl32
1427
&& e->Iex.Binop.arg1
1428
->Iex.Binop.arg2->Iex.Binop.arg2->tag == Iex_Const
1429
&& e->Iex.Binop.arg1
1430
->Iex.Binop.arg2->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8) {
1431
UInt shift = e->Iex.Binop.arg1
1432
->Iex.Binop.arg2->Iex.Binop.arg2->Iex.Const.con->Ico.U8;
1433
UInt imm32 = e->Iex.Binop.arg2->Iex.Const.con->Ico.U32;
1434
if (shift == 1 || shift == 2 || shift == 3) {
1435
HReg r1 = iselIntExpr_R(env, e->Iex.Binop.arg1->Iex.Binop.arg1);
1436
HReg r2 = iselIntExpr_R(env, e->Iex.Binop.arg1
1437
->Iex.Binop.arg2->Iex.Binop.arg1 );
1438
return X86AMode_IRRS(imm32, r1, r2, shift);
1295
1442
/* Add32(expr1, Shl32(expr2, imm)) */
1296
1443
if (e->tag == Iex_Binop
1297
1444
&& e->Iex.Binop.op == Iop_Add32
1494
1641
static X86CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e )
1497
DECLARE_PATTERN(p_32to1);
1498
DECLARE_PATTERN(p_1Uto32_then_32to1);
1499
DECLARE_PATTERN(p_1Sto32_then_32to1);
1502
1646
vassert(typeOfIRExpr(env->type_env,e) == Ity_I1);
1505
if (e->tag == Iex_Tmp) {
1506
HReg r32 = lookupIRTemp(env, e->Iex.Tmp.tmp);
1649
if (e->tag == Iex_RdTmp) {
1650
HReg r32 = lookupIRTemp(env, e->Iex.RdTmp.tmp);
1507
1651
/* Test32 doesn't modify r32; so this is OK. */
1508
addInstr(env, X86Instr_Test32(1,r32));
1652
addInstr(env, X86Instr_Test32(1,X86RM_Reg(r32)));
1530
1674
/* --- patterns rooted at: 32to1 --- */
1532
/* 32to1(1Uto32(e)) ==> e */
1533
DEFINE_PATTERN(p_1Uto32_then_32to1,
1534
unop(Iop_32to1,unop(Iop_1Uto32,bind(0))));
1535
if (matchIRExpr(&mi,p_1Uto32_then_32to1,e)) {
1536
IRExpr* expr1 = mi.bindee[0];
1537
return iselCondCode(env, expr1);
1540
/* 32to1(1Sto32(e)) ==> e */
1541
DEFINE_PATTERN(p_1Sto32_then_32to1,
1542
unop(Iop_32to1,unop(Iop_1Sto32,bind(0))));
1543
if (matchIRExpr(&mi,p_1Sto32_then_32to1,e)) {
1544
IRExpr* expr1 = mi.bindee[0];
1545
return iselCondCode(env, expr1);
1549
DEFINE_PATTERN(p_32to1,
1550
unop(Iop_32to1,bind(0))
1552
if (matchIRExpr(&mi,p_32to1,e)) {
1553
HReg r = iselIntExpr_R(env, mi.bindee[0]);
1554
addInstr(env, X86Instr_Test32(1,r));
1676
if (e->tag == Iex_Unop
1677
&& e->Iex.Unop.op == Iop_32to1) {
1678
X86RM* rm = iselIntExpr_RM(env, e->Iex.Unop.arg);
1679
addInstr(env, X86Instr_Test32(1,rm));
1570
1695
/* CmpNEZ16(x) */
1571
1696
if (e->tag == Iex_Unop
1572
1697
&& e->Iex.Unop.op == Iop_CmpNEZ16) {
1573
HReg r = iselIntExpr_R(env, e->Iex.Unop.arg);
1574
addInstr(env, X86Instr_Test32(0xFFFF,r));
1698
X86RM* rm = iselIntExpr_RM(env, e->Iex.Unop.arg);
1699
addInstr(env, X86Instr_Test32(0xFFFF,rm));
1578
1703
/* --- patterns rooted at: CmpNEZ32 --- */
1580
/* CmpNEZ32(1Sto32(b)) ==> b */
1582
DECLARE_PATTERN(p_CmpNEZ32_1Sto32);
1583
DEFINE_PATTERN(p_CmpNEZ32_1Sto32,
1584
unop(Iop_CmpNEZ32, unop(Iop_1Sto32,bind(0))));
1585
if (matchIRExpr(&mi, p_CmpNEZ32_1Sto32, e)) {
1586
return iselCondCode(env, mi.bindee[0]);
1590
1705
/* CmpNEZ32(And32(x,y)) */
1592
1707
DECLARE_PATTERN(p_CmpNEZ32_And32);
1674
1788
if (e->tag == Iex_Binop
1675
1789
&& (e->Iex.Binop.op == Iop_CmpEQ8
1676
1790
|| e->Iex.Binop.op == Iop_CmpNE8)) {
1677
HReg r1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
1678
X86RMI* rmi2 = iselIntExpr_RMI(env, e->Iex.Binop.arg2);
1679
HReg r = newVRegI(env);
1680
addInstr(env, mk_iMOVsd_RR(r1,r));
1681
addInstr(env, X86Instr_Alu32R(Xalu_XOR,rmi2,r));
1682
addInstr(env, X86Instr_Test32(0xFF,r));
1683
switch (e->Iex.Binop.op) {
1684
case Iop_CmpEQ8: return Xcc_Z;
1685
case Iop_CmpNE8: return Xcc_NZ;
1686
default: vpanic("iselCondCode(x86): CmpXX8");
1791
if (isZeroU8(e->Iex.Binop.arg2)) {
1792
HReg r1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
1793
addInstr(env, X86Instr_Test32(0xFF,X86RM_Reg(r1)));
1794
switch (e->Iex.Binop.op) {
1795
case Iop_CmpEQ8: return Xcc_Z;
1796
case Iop_CmpNE8: return Xcc_NZ;
1797
default: vpanic("iselCondCode(x86): CmpXX8(expr,0:I8)");
1800
HReg r1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
1801
X86RMI* rmi2 = iselIntExpr_RMI(env, e->Iex.Binop.arg2);
1802
HReg r = newVRegI(env);
1803
addInstr(env, mk_iMOVsd_RR(r1,r));
1804
addInstr(env, X86Instr_Alu32R(Xalu_XOR,rmi2,r));
1805
addInstr(env, X86Instr_Test32(0xFF,X86RM_Reg(r)));
1806
switch (e->Iex.Binop.op) {
1807
case Iop_CmpEQ8: return Xcc_Z;
1808
case Iop_CmpNE8: return Xcc_NZ;
1809
default: vpanic("iselCondCode(x86): CmpXX8(expr,expr)");
1980
/* 64-bit Mux0X: Mux0X(g, expr, 0:I64) */
1981
if (e->tag == Iex_Mux0X && isZeroU64(e->Iex.Mux0X.exprX)) {
1984
HReg tLo = newVRegI(env);
1985
HReg tHi = newVRegI(env);
1986
X86AMode* zero_esp = X86AMode_IR(0, hregX86_ESP());
1987
iselInt64Expr(&e0Hi, &e0Lo, env, e->Iex.Mux0X.expr0);
1988
r8 = iselIntExpr_RM(env, e->Iex.Mux0X.cond);
1989
addInstr(env, mk_iMOVsd_RR( e0Hi, tHi ) );
1990
addInstr(env, mk_iMOVsd_RR( e0Lo, tLo ) );
1991
addInstr(env, X86Instr_Push(X86RMI_Imm(0)));
1992
addInstr(env, X86Instr_Test32(0xFF, r8));
1993
addInstr(env, X86Instr_CMov32(Xcc_NZ,X86RM_Mem(zero_esp),tHi));
1994
addInstr(env, X86Instr_CMov32(Xcc_NZ,X86RM_Mem(zero_esp),tLo));
2000
/* 64-bit Mux0X: Mux0X(g, 0:I64, expr) */
2001
if (e->tag == Iex_Mux0X && isZeroU64(e->Iex.Mux0X.expr0)) {
2004
HReg tLo = newVRegI(env);
2005
HReg tHi = newVRegI(env);
2006
X86AMode* zero_esp = X86AMode_IR(0, hregX86_ESP());
2007
iselInt64Expr(&e0Hi, &e0Lo, env, e->Iex.Mux0X.exprX);
2008
r8 = iselIntExpr_RM(env, e->Iex.Mux0X.cond);
2009
addInstr(env, mk_iMOVsd_RR( e0Hi, tHi ) );
2010
addInstr(env, mk_iMOVsd_RR( e0Lo, tLo ) );
2011
addInstr(env, X86Instr_Push(X86RMI_Imm(0)));
2012
addInstr(env, X86Instr_Test32(0xFF, r8));
2013
addInstr(env, X86Instr_CMov32(Xcc_Z,X86RM_Mem(zero_esp),tHi));
2014
addInstr(env, X86Instr_CMov32(Xcc_Z,X86RM_Mem(zero_esp),tLo));
2021
/* 64-bit Mux0X: Mux0X(g, expr, expr) */
1856
2022
if (e->tag == Iex_Mux0X) {
1857
HReg e0Lo, e0Hi, eXLo, eXHi, r8;
2024
HReg e0Lo, e0Hi, eXLo, eXHi;
1858
2025
HReg tLo = newVRegI(env);
1859
2026
HReg tHi = newVRegI(env);
1860
2027
iselInt64Expr(&e0Hi, &e0Lo, env, e->Iex.Mux0X.expr0);
1861
2028
iselInt64Expr(&eXHi, &eXLo, env, e->Iex.Mux0X.exprX);
1862
2029
addInstr(env, mk_iMOVsd_RR(eXHi, tHi));
1863
2030
addInstr(env, mk_iMOVsd_RR(eXLo, tLo));
1864
r8 = iselIntExpr_R(env, e->Iex.Mux0X.cond);
2031
r8 = iselIntExpr_RM(env, e->Iex.Mux0X.cond);
1865
2032
addInstr(env, X86Instr_Test32(0xFF, r8));
1866
2033
/* This assumes the first cmov32 doesn't trash the condition
1867
2034
codes, so they are still available for the second cmov32 */
1928
2095
: e->Iex.Binop.op==Iop_And64 ? Xalu_AND
1930
2097
iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
2098
iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
1931
2099
addInstr(env, mk_iMOVsd_RR(xHi, tHi));
1932
addInstr(env, mk_iMOVsd_RR(xLo, tLo));
1933
iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
1934
2100
addInstr(env, X86Instr_Alu32R(op, X86RMI_Reg(yHi), tHi));
2101
addInstr(env, mk_iMOVsd_RR(xLo, tLo));
1935
2102
addInstr(env, X86Instr_Alu32R(op, X86RMI_Reg(yLo), tLo));
1941
2108
/* Add64/Sub64 */
1942
2109
case Iop_Add64:
2110
if (e->Iex.Binop.arg2->tag == Iex_Const) {
2111
/* special case Add64(e, const) */
2112
ULong w64 = e->Iex.Binop.arg2->Iex.Const.con->Ico.U64;
2113
UInt wHi = toUInt(w64 >> 32);
2114
UInt wLo = toUInt(w64);
2115
HReg tLo = newVRegI(env);
2116
HReg tHi = newVRegI(env);
2118
vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U64);
2119
iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
2120
addInstr(env, mk_iMOVsd_RR(xHi, tHi));
2121
addInstr(env, mk_iMOVsd_RR(xLo, tLo));
2122
addInstr(env, X86Instr_Alu32R(Xalu_ADD, X86RMI_Imm(wLo), tLo));
2123
addInstr(env, X86Instr_Alu32R(Xalu_ADC, X86RMI_Imm(wHi), tHi));
2128
/* else fall through to the generic case */
1943
2129
case Iop_Sub64: {
1944
2130
HReg xLo, xHi, yLo, yHi;
1945
2131
HReg tLo = newVRegI(env);
2000
2186
and those regs are legitimately modifiable. */
2001
2187
addInstr(env, X86Instr_Sh3232(Xsh_SHL, 0/*%cl*/, tLo, tHi));
2002
2188
addInstr(env, X86Instr_Sh32(Xsh_SHL, 0/*%cl*/, tLo));
2003
addInstr(env, X86Instr_Test32(32, hregX86_ECX()));
2189
addInstr(env, X86Instr_Test32(32, X86RM_Reg(hregX86_ECX())));
2004
2190
addInstr(env, X86Instr_CMov32(Xcc_NZ, X86RM_Reg(tLo), tHi));
2005
2191
addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(0), tTemp));
2006
2192
addInstr(env, X86Instr_CMov32(Xcc_NZ, X86RM_Reg(tTemp), tLo));
2042
2228
and those regs are legitimately modifiable. */
2043
2229
addInstr(env, X86Instr_Sh3232(Xsh_SHR, 0/*%cl*/, tHi, tLo));
2044
2230
addInstr(env, X86Instr_Sh32(Xsh_SHR, 0/*%cl*/, tHi));
2045
addInstr(env, X86Instr_Test32(32, hregX86_ECX()));
2231
addInstr(env, X86Instr_Test32(32, X86RM_Reg(hregX86_ECX())));
2046
2232
addInstr(env, X86Instr_CMov32(Xcc_NZ, X86RM_Reg(tHi), tLo));
2047
2233
addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(0), tTemp));
2048
2234
addInstr(env, X86Instr_CMov32(Xcc_NZ, X86RM_Reg(tTemp), tHi));
2345
2543
/* tHi = 0 - yHi - carry */
2346
2544
addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(0), tHi));
2347
2545
addInstr(env, X86Instr_Alu32R(Xalu_SBB, X86RMI_Reg(yHi), tHi));
2546
/* So now we have tHi:tLo = -arg. To finish off, or 'arg'
2547
back in, so as to give the final result
2548
tHi:tLo = arg | -arg. */
2549
addInstr(env, X86Instr_Alu32R(Xalu_OR, X86RMI_Reg(yLo), tLo));
2550
addInstr(env, X86Instr_Alu32R(Xalu_OR, X86RMI_Reg(yHi), tHi));
2556
/* --- patterns rooted at: CmpwNEZ64 --- */
2559
case Iop_CmpwNEZ64: {
2561
DECLARE_PATTERN(p_CmpwNEZ64_Or64);
2562
DEFINE_PATTERN(p_CmpwNEZ64_Or64,
2563
unop(Iop_CmpwNEZ64,binop(Iop_Or64,bind(0),bind(1))));
2564
if (matchIRExpr(&mi, p_CmpwNEZ64_Or64, e)) {
2565
/* CmpwNEZ64(Or64(x,y)) */
2566
HReg xHi,xLo,yHi,yLo;
2567
HReg xBoth = newVRegI(env);
2568
HReg merged = newVRegI(env);
2569
HReg tmp2 = newVRegI(env);
2571
iselInt64Expr(&xHi,&xLo, env, mi.bindee[0]);
2572
addInstr(env, mk_iMOVsd_RR(xHi,xBoth));
2573
addInstr(env, X86Instr_Alu32R(Xalu_OR,
2574
X86RMI_Reg(xLo),xBoth));
2576
iselInt64Expr(&yHi,&yLo, env, mi.bindee[1]);
2577
addInstr(env, mk_iMOVsd_RR(yHi,merged));
2578
addInstr(env, X86Instr_Alu32R(Xalu_OR,
2579
X86RMI_Reg(yLo),merged));
2580
addInstr(env, X86Instr_Alu32R(Xalu_OR,
2581
X86RMI_Reg(xBoth),merged));
2583
/* tmp2 = (merged | -merged) >>s 31 */
2584
addInstr(env, mk_iMOVsd_RR(merged,tmp2));
2585
addInstr(env, X86Instr_Unary32(Xun_NEG,tmp2));
2586
addInstr(env, X86Instr_Alu32R(Xalu_OR,
2587
X86RMI_Reg(merged), tmp2));
2588
addInstr(env, X86Instr_Sh32(Xsh_SAR, 31, tmp2));
2595
HReg tmp1 = newVRegI(env);
2596
HReg tmp2 = newVRegI(env);
2597
/* srcHi:srcLo = arg */
2598
iselInt64Expr(&srcHi, &srcLo, env, e->Iex.Unop.arg);
2599
/* tmp1 = srcHi | srcLo */
2600
addInstr(env, mk_iMOVsd_RR(srcHi,tmp1));
2601
addInstr(env, X86Instr_Alu32R(Xalu_OR,
2602
X86RMI_Reg(srcLo), tmp1));
2603
/* tmp2 = (tmp1 | -tmp1) >>s 31 */
2604
addInstr(env, mk_iMOVsd_RR(tmp1,tmp2));
2605
addInstr(env, X86Instr_Unary32(Xun_NEG,tmp2));
2606
addInstr(env, X86Instr_Alu32R(Xalu_OR,
2607
X86RMI_Reg(tmp1), tmp2));
2608
addInstr(env, X86Instr_Sh32(Xsh_SAR, 31, tmp2));
2353
2615
/* ReinterpF64asI64(e) */
2354
2616
/* Given an IEEE754 double, produce an I64 with the same bit
3330
3591
if (tya != Ity_I32 || end != Iend_LE)
3331
3592
goto stmt_fail;
3333
am = iselIntExpr_AMode(env, stmt->Ist.Store.addr);
3334
3594
if (tyd == Ity_I32) {
3595
X86AMode* am = iselIntExpr_AMode(env, stmt->Ist.Store.addr);
3335
3596
X86RI* ri = iselIntExpr_RI(env, stmt->Ist.Store.data);
3336
3597
addInstr(env, X86Instr_Alu32M(Xalu_MOV,ri,am));
3339
3600
if (tyd == Ity_I8 || tyd == Ity_I16) {
3601
X86AMode* am = iselIntExpr_AMode(env, stmt->Ist.Store.addr);
3340
3602
HReg r = iselIntExpr_R(env, stmt->Ist.Store.data);
3341
3603
addInstr(env, X86Instr_Store( toUChar(tyd==Ity_I8 ? 1 : 2),
3345
3607
if (tyd == Ity_F64) {
3608
X86AMode* am = iselIntExpr_AMode(env, stmt->Ist.Store.addr);
3346
3609
HReg r = iselDblExpr(env, stmt->Ist.Store.data);
3347
3610
addInstr(env, X86Instr_FpLdSt(False/*store*/, 8, r, am));
3350
3613
if (tyd == Ity_F32) {
3614
X86AMode* am = iselIntExpr_AMode(env, stmt->Ist.Store.addr);
3351
3615
HReg r = iselFltExpr(env, stmt->Ist.Store.data);
3352
3616
addInstr(env, X86Instr_FpLdSt(False/*store*/, 4, r, am));
3463
3728
/* --------- TMP --------- */
3465
IRTemp tmp = stmt->Ist.Tmp.tmp;
3730
IRTemp tmp = stmt->Ist.WrTmp.tmp;
3466
3731
IRType ty = typeOfIRTemp(env->type_env, tmp);
3733
/* optimisation: if stmt->Ist.WrTmp.data is Add32(..,..),
3734
compute it into an AMode and then use LEA. This usually
3735
produces fewer instructions, often because (for memcheck
3736
created IR) we get t = address-expression, (t is later used
3737
twice) and so doing this naturally turns address-expression
3738
back into an X86 amode. */
3740
&& stmt->Ist.WrTmp.data->tag == Iex_Binop
3741
&& stmt->Ist.WrTmp.data->Iex.Binop.op == Iop_Add32) {
3742
X86AMode* am = iselIntExpr_AMode(env, stmt->Ist.WrTmp.data);
3743
HReg dst = lookupIRTemp(env, tmp);
3744
if (am->tag == Xam_IR && am->Xam.IR.imm == 0) {
3745
/* Hmm, iselIntExpr_AMode wimped out and just computed the
3746
value into a register. Just emit a normal reg-reg move
3747
so reg-alloc can coalesce it away in the usual way. */
3748
HReg src = am->Xam.IR.reg;
3749
addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Reg(src), dst));
3751
addInstr(env, X86Instr_Lea32(am,dst));
3467
3756
if (ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8) {
3468
X86RMI* rmi = iselIntExpr_RMI(env, stmt->Ist.Tmp.data);
3757
X86RMI* rmi = iselIntExpr_RMI(env, stmt->Ist.WrTmp.data);
3469
3758
HReg dst = lookupIRTemp(env, tmp);
3470
3759
addInstr(env, X86Instr_Alu32R(Xalu_MOV,rmi,dst));
3473
3762
if (ty == Ity_I64) {
3474
3763
HReg rHi, rLo, dstHi, dstLo;
3475
iselInt64Expr(&rHi,&rLo, env, stmt->Ist.Tmp.data);
3764
iselInt64Expr(&rHi,&rLo, env, stmt->Ist.WrTmp.data);
3476
3765
lookupIRTemp64( &dstHi, &dstLo, env, tmp);
3477
3766
addInstr(env, mk_iMOVsd_RR(rHi,dstHi) );
3478
3767
addInstr(env, mk_iMOVsd_RR(rLo,dstLo) );
3481
3770
if (ty == Ity_I1) {
3482
X86CondCode cond = iselCondCode(env, stmt->Ist.Tmp.data);
3771
X86CondCode cond = iselCondCode(env, stmt->Ist.WrTmp.data);
3483
3772
HReg dst = lookupIRTemp(env, tmp);
3484
3773
addInstr(env, X86Instr_Set32(cond, dst));
3487
3776
if (ty == Ity_F64) {
3488
3777
HReg dst = lookupIRTemp(env, tmp);
3489
HReg src = iselDblExpr(env, stmt->Ist.Tmp.data);
3778
HReg src = iselDblExpr(env, stmt->Ist.WrTmp.data);
3490
3779
addInstr(env, X86Instr_FpUnary(Xfp_MOV,src,dst));
3493
3782
if (ty == Ity_F32) {
3494
3783
HReg dst = lookupIRTemp(env, tmp);
3495
HReg src = iselFltExpr(env, stmt->Ist.Tmp.data);
3784
HReg src = iselFltExpr(env, stmt->Ist.WrTmp.data);
3496
3785
addInstr(env, X86Instr_FpUnary(Xfp_MOV,src,dst));
3499
3788
if (ty == Ity_V128) {
3500
3789
HReg dst = lookupIRTemp(env, tmp);
3501
HReg src = iselVecExpr(env, stmt->Ist.Tmp.data);
3790
HReg src = iselVecExpr(env, stmt->Ist.WrTmp.data);
3502
3791
addInstr(env, mk_vMOVsd_RR(src,dst));