/* ADD/SUB/ADC/SBB/AND/OR/XOR/CMP */
opc = opc_rr = subopc_imm = opc_imma = 0;
switch (i->Xin.Alu32R.op) {
+ case Xalu_ADC: opc = 0x13; opc_rr = 0x11;
+ subopc_imm = 2; opc_imma = 0x15; break;
case Xalu_ADD: opc = 0x03; opc_rr = 0x01;
subopc_imm = 0; opc_imma = 0x05; break;
case Xalu_SUB: opc = 0x2B; opc_rr = 0x29;
*p++ = opc_imma;
p = emit32(p, i->Xin.Alu32R.src->Xrmi.Imm.imm32);
} else
- if (fits8bits(i->Xin.Alu32R.src->Xrmi.Imm.imm32)) {
+ if (fits8bits(i->Xin.Alu32R.src->Xrmi.Imm.imm32)) {
*p++ = 0x83;
p = doAMode_R(p, fake(subopc_imm), i->Xin.Alu32R.dst);
*p++ = 0xFF & i->Xin.Alu32R.src->Xrmi.Imm.imm32;
return;
}
- /* Iop_Or64/And64/Xor64 */
+ /* Or64/And64/Xor64 */
case Iop_Or64:
case Iop_And64:
case Iop_Xor64: {
return;
}
+ /* Add64/Sub64 */
+ case Iop_Add64:
+ case Iop_Sub64: {
+ HReg xLo, xHi, yLo, yHi;
+ HReg tLo = newVRegI(env);
+ HReg tHi = newVRegI(env);
+ 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);
+ if (e->Iex.Binop.op==Iop_Add64) {
+ addInstr(env, X86Instr_Alu32R(Xalu_ADD, X86RMI_Reg(yLo), tLo));
+ addInstr(env, X86Instr_Alu32R(Xalu_ADC, X86RMI_Reg(yHi), tHi));
+ } else {
+ addInstr(env, X86Instr_Alu32R(Xalu_SUB, X86RMI_Reg(yLo), tLo));
+ addInstr(env, X86Instr_Alu32R(Xalu_SBB, X86RMI_Reg(yHi), tHi));
+ }
+ *rHi = tHi;
+ *rLo = tLo;
+ return;
+ }
+
/* 32HLto64(e1,e2) */
case Iop_32HLto64:
*rHi = iselIntExpr_R(env, e->Iex.Binop.arg1);