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)) {
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");
}
}
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();
(*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();
}
/* --------- Instructions. --------- */
-Char* showX86ScalarSz ( X86ScalarSz sz ) {
+HChar* showX86ScalarSz ( X86ScalarSz sz ) {
switch (sz) {
case Xss_16: return "w";
case Xss_32: return "l";
}
}
-Char* showX86UnaryOp ( X86UnaryOp op ) {
+HChar* showX86UnaryOp ( X86UnaryOp op ) {
switch (op) {
case Xun_NOT: return "not";
case Xun_NEG: return "neg";
}
}
-Char* showX86AluOp ( X86AluOp op ) {
+HChar* showX86AluOp ( X86AluOp op ) {
switch (op) {
case Xalu_MOV: return "mov";
case Xalu_CMP: return "cmp";
}
}
-Char* showX86ShiftOp ( X86ShiftOp op ) {
+HChar* showX86ShiftOp ( X86ShiftOp op ) {
switch (op) {
case Xsh_SHL: return "shl";
case Xsh_SHR: return "shr";
}
}
-Char* showX86FpOp ( X86FpOp op ) {
+HChar* showX86FpOp ( X86FpOp op ) {
switch (op) {
case Xfp_ADD: return "add";
case Xfp_SUB: return "sub";
}
}
+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;
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;
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;
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;
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) {
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");
}
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");
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");
*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;
}
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);
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;
}
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 ---*/
/* 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 );
/*---------------------------------------------------------*/
/* 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);
}
+/* 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. */
} 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;
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 {
/* 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--;
}
*/
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));
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;
}
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;
}
/* 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) {
} 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;
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));
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));
|| 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)));
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));
/* 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;
}
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;
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;
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;
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:
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;
}
/* 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;
}
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));
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) {
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) {
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) {
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;
}
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
}
/* 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);
/* 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;
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
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;
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;
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;
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;
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;
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;
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));
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));
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));
/* 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);
}
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);
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(
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));
return dst;
}
-
if (e->tag == Iex_Unop) {
X86FpOp fpop = Xfp_INVALID;
switch (e->Iex.Unop.op) {
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(
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(
}
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 ---*/
}
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)));
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;
}
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;
}
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) {
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;
}
/* 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;
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");
}