diff --git a/VEX/priv/guest-ppc32/gdefs.h b/VEX/priv/guest-ppc32/gdefs.h index 82344524b..f8de81d54 100644 --- a/VEX/priv/guest-ppc32/gdefs.h +++ b/VEX/priv/guest-ppc32/gdefs.h @@ -78,7 +78,7 @@ VexGuestLayout ppc32Guest_layout; extern UInt ppc32g_calculate_cr7_all ( UInt op, UInt val, UInt xer_so ); // Calculate XER flags -extern UInt ppc32g_calculate_xer_ov ( UInt op, UInt res, UInt argL, UInt argR, UInt ca ); +extern UInt ppc32g_calculate_xer_ov ( UInt op, UInt res, UInt argL, UInt argR ); extern UInt ppc32g_calculate_xer_ca ( UInt op, UInt res, UInt argL, UInt argR, UInt ca ); @@ -116,20 +116,16 @@ extern UInt ppc32g_calculate_xer_ca ( UInt op, UInt res, UInt argL, UInt argR, Enumeration for xer_ca/ov calculation helper functions */ enum { - PPC32G_FLAG_OP_ADD=0, // addc, addo, addic - PPC32G_FLAG_OP_ADDE, // adde, addeo - PPC32G_FLAG_OP_ADDME, // addme, addmeo - PPC32G_FLAG_OP_ADDZE, // addze, addzeo + PPC32G_FLAG_OP_ADD=0, // addc[o], addic + PPC32G_FLAG_OP_ADDE, // adde[o], addme[o], addze[o] PPC32G_FLAG_OP_DIVW, // divwo PPC32G_FLAG_OP_DIVWU, // divwuo PPC32G_FLAG_OP_MULLW, // mullwo PPC32G_FLAG_OP_NEG, // nego PPC32G_FLAG_OP_SUBF, // subfo - PPC32G_FLAG_OP_SUBFC, // subfc, subfco - PPC32G_FLAG_OP_SUBFE, // subfe, subfeo + PPC32G_FLAG_OP_SUBFC, // subfc[o] + PPC32G_FLAG_OP_SUBFE, // subfe[o], subfme[o], subfze[o] PPC32G_FLAG_OP_SUBFI, // subfic - PPC32G_FLAG_OP_SUBFME, // subfme, subfmeo - PPC32G_FLAG_OP_SUBFZE, // subfze, subfzeo PPC32G_FLAG_OP_SRAW, // sraw PPC32G_FLAG_OP_SRAWI, // srawi diff --git a/VEX/priv/guest-ppc32/ghelpers.c b/VEX/priv/guest-ppc32/ghelpers.c index a16b809b8..dadf1a1d9 100644 --- a/VEX/priv/guest-ppc32/ghelpers.c +++ b/VEX/priv/guest-ppc32/ghelpers.c @@ -80,23 +80,14 @@ UInt ppc32g_calculate_cr7_all ( UInt op, UInt val, UInt xer_so ) // Calculate XER_OV -UInt ppc32g_calculate_xer_ov ( UInt op, UInt res, - UInt argL, UInt argR, UInt ov ) +UInt ppc32g_calculate_xer_ov ( UInt op, UInt res, UInt argL, UInt argR ) { switch (op) { case PPC32G_FLAG_OP_ADD: // addo, addc - case PPC32G_FLAG_OP_ADDE: // addeo + case PPC32G_FLAG_OP_ADDE: // addeo, addmeo, addzeo return ((argL^argR^-1) & (argL^res) & (1<<31)) ? 1:0; // i.e. ((both_same_sign) & (sign_changed) & (sign_mask)) - case PPC32G_FLAG_OP_ADDME: // addmeo - return ((argL) & (argL ^ res) & (1<<31)) ? 1:0; - // i.e. (neg & (sign_changed) & sign_mask) - - case PPC32G_FLAG_OP_ADDZE: // addzeo - return ((argL^(-1)) & (argL ^ res) & (1<<31)) ? 1:0; - // i.e. (pos & (sign_changed) & sign_mask) - case PPC32G_FLAG_OP_DIVW: // divwo return ((argL == INT32_MIN && argR == -1) || argR == 0) ? 1:0; @@ -117,15 +108,9 @@ UInt ppc32g_calculate_xer_ov ( UInt op, UInt res, case PPC32G_FLAG_OP_SUBF: // subfo case PPC32G_FLAG_OP_SUBFC: // subfco - case PPC32G_FLAG_OP_SUBFE: // subfeo + case PPC32G_FLAG_OP_SUBFE: // subfeo, subfmeo, subfzeo return (((~argL)^argR^(-1)) & ((~argL)^res) & (1<<31)) ? 1:0; - case PPC32G_FLAG_OP_SUBFME: // subfmeo - return ((~argL) & ((~argL)^res) & (1<<31)) ? 1:0; - - case PPC32G_FLAG_OP_SUBFZE: // subfzeo - return (((~argL)^(-1)) & ((~argL)^res) & (1<<31)) ? 1:0; - default: break; } @@ -138,40 +123,32 @@ UInt ppc32g_calculate_xer_ov ( UInt op, UInt res, UInt ppc32g_calculate_xer_ca ( UInt op, UInt res, UInt argL, UInt argR, UInt ca ) { - switch (op) { - case PPC32G_FLAG_OP_ADD: // addc, addco, addic - case PPC32G_FLAG_OP_ADDZE: // addze, addzeo + switch (op) { + case PPC32G_FLAG_OP_ADD: // addc[o], addic return (res < argL) ? 1:0; - case PPC32G_FLAG_OP_ADDE: // adde, addeo + case PPC32G_FLAG_OP_ADDE: // adde[o], addze[o], addme[o] return (res < argL || (ca==1 && res==argL)) ? 1:0; - case PPC32G_FLAG_OP_ADDME: // addme, addmeo - return (argL != 0) ? 1:0; - - case PPC32G_FLAG_OP_SUBFC: // subfc, subfco + case PPC32G_FLAG_OP_SUBFC: // subfc[o] case PPC32G_FLAG_OP_SUBFI: // subfic - case PPC32G_FLAG_OP_SUBFZE: // subfze, subfzeo return (res <= argR) ? 1:0; - case PPC32G_FLAG_OP_SUBFE: // subfe, subfeo + case PPC32G_FLAG_OP_SUBFE: // subfe[o], subfze[o], subfme[o] return ((res < argR) || (ca == 1 && res == argR)) ? 1:0; - case PPC32G_FLAG_OP_SUBFME: // subfme, subfmeo - return (res != -1) ? 1:0; - case PPC32G_FLAG_OP_SRAW: // sraw if ((argR & 0x20) == 0) { // shift <= 31 - // ca = sign && (bits_shifted_out != 0) + // xer_ca = sign && (bits_shifted_out != 0) return (((argL & 0x80000000) && ((argL & (0xFFFFFFFF >> (32-argR))) != 0)) != 0) ? 1:0; } // shift > 31 - // ca = sign && src != 0 + // xer_ca = sign && src != 0 return (((argL & 0x80000000) && (argR != 0)) != 0) ? 1:0; case PPC32G_FLAG_OP_SRAWI: // srawi - // ca = sign && (bits_shifted_out != 0) + // xer_ca = sign && (bits_shifted_out != 0) return (((argL & 0x80000000) && ((argL & (0xFFFFFFFF >> (32-argR))) != 0)) != 0) ? 1:0; diff --git a/VEX/priv/guest-ppc32/toIR.c b/VEX/priv/guest-ppc32/toIR.c index 77400af23..ab4ce4526 100644 --- a/VEX/priv/guest-ppc32/toIR.c +++ b/VEX/priv/guest-ppc32/toIR.c @@ -642,9 +642,7 @@ static IRExpr* mk_ppc32g_calculate_xer_ov ( UInt op, IRExpr* res, vassert(typeOfIRExpr(irbb->tyenv,argL) == Ity_I32); vassert(typeOfIRExpr(irbb->tyenv,argR) == Ity_I32); - args = - mkIRExprVec_5( mkU32(op), res, argL, argR, - getReg_bit( PPC32_SPR_XER, SHIFT_XER_OV ) ); + args = mkIRExprVec_4( mkU32(op), res, argL, argR ); call = mkIRExprCCall( @@ -669,7 +667,8 @@ static IRExpr* mk_ppc32g_calculate_xer_ca ( UInt op, IRExpr* res, vassert(typeOfIRExpr(irbb->tyenv,argR) == Ity_I32); xer_ca = getReg_bit( PPC32_SPR_XER, SHIFT_XER_CA ); - args = mkIRExprVec_5( mkU32(op), res, argL, argR, xer_ca ); + + args = mkIRExprVec_5( mkU32(op), res, argL, argR, xer_ca ); call = mkIRExprCCall( @@ -726,9 +725,9 @@ static void setFlags_XER_CA( UInt op, IRExpr* res, vassert(typeOfIRExpr(irbb->tyenv,res) == Ity_I32); vassert(typeOfIRExpr(irbb->tyenv,argL) == Ity_I32); vassert(typeOfIRExpr(irbb->tyenv,argR) == Ity_I32); - - // => Calculate result immediately - xer_ca = mk_ppc32g_calculate_xer_ca(op, res, argL, argR); + + // Calculate new xer_ca immediately: + xer_ca = mk_ppc32g_calculate_xer_ca(op, res, argL, argR ); putReg_bit( PPC32_SPR_XER, xer_ca, SHIFT_XER_CA ); } @@ -977,41 +976,31 @@ static Bool dis_int_arith ( UInt theInstr ) IRTemp Rd = newTemp(Ity_I32); IRTemp res64 = newTemp(Ity_I64); // multiplies need this. IRTemp xer_ca = newTemp(Ity_I32); - - UInt op = PPC32G_FLAG_OP_NUMBER; - Bool do_ca = False; - Bool do_ov = False; + + UInt flag_op = PPC32G_FLAG_OP_NUMBER; Bool do_rc = False; - IRExpr* argL; - IRExpr* argR; assign( Ra, getIReg(Ra_addr) ); assign( Rb, getIReg(Rb_addr) ); // XO-Form: Rd, Ra, Rb EXTS_SIMM = extend_s_16to32(SIMM_16); // D-Form: Rd, Ra, EXTS(SIMM) - - // ca/ov flag calc params - argL = mkexpr(Ra); - argR = (opc1 == 0x1F) ? mkexpr(Rb) : mkU32(EXTS_SIMM); assign( xer_ca, getReg_bit( PPC32_SPR_XER, SHIFT_XER_CA ) ); - - + switch (opc1) { - /* D-Form */ case 0x0C: // addic (Add Immediate Carrying, PPC32 p351 DIP("addic r%d,r%d,0x%x\n", Rd_addr, Ra_addr, EXTS_SIMM); assign( Rd, binop( Iop_Add32, mkexpr(Ra), mkU32(EXTS_SIMM) ) ); - op = PPC32G_FLAG_OP_ADD; - do_ca = True; + flag_op = PPC32G_FLAG_OP_ADD; + setFlags_XER_CA( flag_op, mkexpr(Rd), mkexpr(Ra), mkU32(EXTS_SIMM) ); break; case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352) DIP("addic. r%d,r%d,0x%x\n", Rd_addr, Ra_addr, EXTS_SIMM); assign( Rd, binop( Iop_Add32, mkexpr(Ra), mkU32(EXTS_SIMM) ) ); - op = PPC32G_FLAG_OP_ADD; - do_ca = True; - do_rc = True; + flag_op = PPC32G_FLAG_OP_ADD; + setFlags_XER_CA( flag_op, mkexpr(Rd), mkexpr(Ra), mkU32(EXTS_SIMM) ); + do_rc = True; // Always record to CR flag_Rc = 1; break; @@ -1046,8 +1035,8 @@ static Bool dis_int_arith ( UInt theInstr ) DIP("subfic r%d,r%d,0x%x\n", Rd_addr, Ra_addr, SIMM_16); // rD = exts_simm - rA assign( Rd, binop(Iop_Sub32, mkU32(EXTS_SIMM), mkexpr(Ra)) ); - op = PPC32G_FLAG_OP_SUBFI; - do_ca = True; + flag_op = PPC32G_FLAG_OP_SUBFI; + setFlags_XER_CA( flag_op, mkexpr(Rd), mkexpr(Ra), mkU32(EXTS_SIMM) ); break; @@ -1061,8 +1050,10 @@ static Bool dis_int_arith ( UInt theInstr ) flag_OE ? "o" : "", flag_Rc ? "." : "", Rd_addr, Ra_addr, Rb_addr); assign( Rd, binop(Iop_Add32, mkexpr(Ra), mkexpr(Rb)) ); - op = PPC32G_FLAG_OP_ADD; - do_ov = True; + if (flag_OE) { + flag_op = PPC32G_FLAG_OP_ADD; + setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) ); + } break; case 0x00A: // addc (Add Carrying, PPC32 p348) @@ -1070,9 +1061,11 @@ static Bool dis_int_arith ( UInt theInstr ) flag_OE ? "o" : "", flag_Rc ? "." : "", Rd_addr, Ra_addr, Rb_addr); assign( Rd, binop(Iop_Add32, mkexpr(Ra), mkexpr(Rb)) ); - op = PPC32G_FLAG_OP_ADD; - do_ca = True; - do_ov = True; + flag_op = PPC32G_FLAG_OP_ADD; + setFlags_XER_CA( flag_op, mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) ); + if (flag_OE) { + setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) ); + } break; case 0x08A: // adde (Add Extended, PPC32 p349) @@ -1082,9 +1075,11 @@ static Bool dis_int_arith ( UInt theInstr ) // rD = rA + rB + XER[CA] assign( Rd, binop(Iop_Add32, mkexpr(Ra), binop(Iop_Add32, mkexpr(Rb), mkexpr(xer_ca))) ); - op = PPC32G_FLAG_OP_ADDE; - do_ca = True; - do_ov = True; + flag_op = PPC32G_FLAG_OP_ADDE; + setFlags_XER_CA( flag_op, mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) ); + if (flag_OE) { + setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) ); + } break; case 0x0EA: // addme (Add to Minus One Extended, PPC32 p354) @@ -1095,12 +1090,15 @@ static Bool dis_int_arith ( UInt theInstr ) DIP("addme%s%s r%d,r%d,r%d\n", flag_OE ? "o" : "", flag_Rc ? "." : "", Rd_addr, Ra_addr, Rb_addr); - // rD = rA + XER[CA] - 1 + // rD = rA + (-1) + XER[CA] + // => Just another form of adde assign( Rd, binop(Iop_Add32, mkexpr(Ra), - binop(Iop_Sub32, mkexpr(xer_ca), mkU32(1)) )); - op = PPC32G_FLAG_OP_ADDME; - do_ca = True; - do_ov = True; + binop(Iop_Add32, mkU32(-1), mkexpr(xer_ca)) )); + flag_op = PPC32G_FLAG_OP_ADDE; + setFlags_XER_CA( flag_op, mkexpr(Rd), mkexpr(Ra), mkU32(-1) ); + if (flag_OE) { + setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkU32(-1) ); + } break; case 0x0CA: // addze (Add to Zero Extended, PPC32 p355) @@ -1111,11 +1109,14 @@ static Bool dis_int_arith ( UInt theInstr ) DIP("addze%s%s r%d,r%d,r%d\n", flag_OE ? "o" : "", flag_Rc ? "." : "", Rd_addr, Ra_addr, Rb_addr); - // rD = rA + XER[CA] + // rD = rA + (0) + XER[CA] + // => Just another form of adde assign( Rd, binop(Iop_Add32, mkexpr(Ra), mkexpr(xer_ca)) ); - op = PPC32G_FLAG_OP_ADDZE; - do_ca = True; - do_ov = True; + flag_op = PPC32G_FLAG_OP_ADDE; + setFlags_XER_CA( flag_op, mkexpr(Rd), mkexpr(Ra), mkU32(0) ); + if (flag_OE) { + setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkU32(0) ); + } break; case 0x1EB: // divw (Divide Word, PPC32 p388) @@ -1123,8 +1124,10 @@ static Bool dis_int_arith ( UInt theInstr ) flag_OE ? "o" : "", flag_Rc ? "." : "", Rd_addr, Ra_addr, Rb_addr); assign( Rd, binop(Iop_DivS32, mkexpr(Ra), mkexpr(Rb)) ); - op = PPC32G_FLAG_OP_DIVW; - do_ov = True; + if (flag_OE) { + flag_op = PPC32G_FLAG_OP_DIVW; + setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) ); + } /* Note: if (0x8000_0000 / -1) or (x / 0) => Rd=undef, if(flag_Rc) CR7=undef, if(flag_OE) XER_OV=1 @@ -1136,8 +1139,10 @@ static Bool dis_int_arith ( UInt theInstr ) flag_OE ? "o" : "", flag_Rc ? "." : "", Rd_addr, Ra_addr, Rb_addr); assign( Rd, binop(Iop_DivU32, mkexpr(Ra), mkexpr(Rb)) ); - op = PPC32G_FLAG_OP_DIVWU; - do_ov = True; + if (flag_OE) { + flag_op = PPC32G_FLAG_OP_DIVWU; + setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) ); + } /* Note: ditto comment divw, for (x / 0) */ break; @@ -1169,8 +1174,10 @@ static Bool dis_int_arith ( UInt theInstr ) Rd_addr, Ra_addr, Rb_addr); assign( res64, binop(Iop_MullU32, mkexpr(Ra), mkexpr(Rb)) ); assign( Rd, unop(Iop_64to32, mkexpr(res64)) ); - op = PPC32G_FLAG_OP_MULLW; - do_ov = True; + if (flag_OE) { + flag_op = PPC32G_FLAG_OP_MULLW; + setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) ); + } break; case 0x068: // neg (Negate, PPC32 p493) @@ -1184,8 +1191,10 @@ static Bool dis_int_arith ( UInt theInstr ) // rD = (log not)rA + 1 assign( Rd, binop(Iop_Add32, unop(Iop_Not32, mkexpr(Ra)), mkU32(1)) ); - op = PPC32G_FLAG_OP_NEG; - do_ov = True; + if (flag_OE) { + flag_op = PPC32G_FLAG_OP_NEG; + setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) ); + } break; case 0x028: // subf (Subtract From, PPC32 p537) @@ -1194,8 +1203,10 @@ static Bool dis_int_arith ( UInt theInstr ) Rd_addr, Ra_addr, Rb_addr); // rD = rB - rA assign( Rd, binop(Iop_Sub32, mkexpr(Rb), mkexpr(Ra)) ); - op = PPC32G_FLAG_OP_SUBF; - do_ov = True; + if (flag_OE) { + flag_op = PPC32G_FLAG_OP_SUBF; + setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) ); + } break; case 0x008: // subfc (Subtract from Carrying, PPC32 p538) @@ -1204,9 +1215,11 @@ static Bool dis_int_arith ( UInt theInstr ) Rd_addr, Ra_addr, Rb_addr); // rD = rB - rA assign( Rd, binop(Iop_Sub32, mkexpr(Rb), mkexpr(Ra)) ); - op = PPC32G_FLAG_OP_SUBFC; - do_ca = True; - do_ov = True; + flag_op = PPC32G_FLAG_OP_SUBFC; + setFlags_XER_CA( flag_op, mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) ); + if (flag_OE) { + setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) ); + } break; case 0x088: // subfe (Subtract from Extended, PPC32 p539) @@ -1216,9 +1229,11 @@ static Bool dis_int_arith ( UInt theInstr ) // rD = (log not)rA + rB + XER[CA] assign( Rd, binop(Iop_Add32, unop(Iop_Not32, mkexpr(Ra)), binop(Iop_Add32, mkexpr(Rb), mkexpr(xer_ca))) ); - op = PPC32G_FLAG_OP_SUBFE; - do_ca = True; - do_ov = True; + flag_op = PPC32G_FLAG_OP_SUBFE; + setFlags_XER_CA( flag_op, mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) ); + if (flag_OE) { + setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) ); + } break; case 0x0E8: // subfme (Subtract from Minus One Extended, PPC32 p541) @@ -1229,12 +1244,15 @@ static Bool dis_int_arith ( UInt theInstr ) DIP("subfme%s%s r%d,r%d\n", flag_OE ? "o" : "", flag_Rc ? "." : "", Rd_addr, Ra_addr); - // rD = (log not)rA + XER[CA] - 1 + // rD = (log not)rA + (-1) + XER[CA] + // => Just another form of subfe assign( Rd, binop(Iop_Add32, unop(Iop_Not32, mkexpr(Ra)), - binop(Iop_Sub32, mkexpr(xer_ca), mkU32(1))) ); - op = PPC32G_FLAG_OP_SUBFME; - do_ca = True; - do_ov = True; + binop(Iop_Add32, mkU32(-1), mkexpr(xer_ca))) ); + flag_op = PPC32G_FLAG_OP_SUBFE; + setFlags_XER_CA( flag_op, mkexpr(Rd), mkexpr(Ra), mkU32(-1) ); + if (flag_OE) { + setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkU32(-1) ); + } break; case 0x0C8: // subfze (Subtract from Zero Extended, PPC32 p542) @@ -1245,12 +1263,14 @@ static Bool dis_int_arith ( UInt theInstr ) DIP("subfze%s%s r%d,r%d\n", flag_OE ? "o" : "", flag_Rc ? "." : "", Rd_addr, Ra_addr); - // rD = (log not)rA + XER[CA] - assign( Rd, binop(Iop_Add32, unop(Iop_Not32, mkexpr(Ra)), - mkexpr(xer_ca)) ); - op = PPC32G_FLAG_OP_SUBFZE; - do_ca = True; - do_ov = True; + // rD = (log not)rA + (0) + XER[CA] + // => Just another form of subfe + assign( Rd, binop(Iop_Add32, unop(Iop_Not32, mkexpr(Ra)), mkexpr(xer_ca)) ); + flag_op = PPC32G_FLAG_OP_SUBFE; + setFlags_XER_CA( flag_op, mkexpr(Rd), mkexpr(Ra), mkU32(0) ); + if (flag_OE) { + setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkU32(0) ); + } break; default: @@ -1264,15 +1284,6 @@ static Bool dis_int_arith ( UInt theInstr ) } putIReg( Rd_addr, mkexpr(Rd) ); - - if (do_ov && flag_OE) { - vassert(op < PPC32G_FLAG_OP_NUMBER); - setFlags_XER_OV_SO( op, mkexpr(Rd), argL, argR ); - } - if (do_ca) { - vassert(op < PPC32G_FLAG_OP_NUMBER); - setFlags_XER_CA( op, mkexpr(Rd), argL, argR ); - } if (do_rc && flag_Rc) { setFlags_CR7( mkexpr(Rd) ); } @@ -1305,8 +1316,8 @@ static Bool dis_int_cmp ( UInt theInstr ) IRTemp cr7 = newTemp(Ity_I32); IRTemp mux1 = newTemp(Ity_I32); IRTemp mux2 = newTemp(Ity_I32); - IRExpr* irx_tst1; - IRExpr* irx_tst2; + IRExpr* irx_cmp_lt; + IRExpr* irx_cmp_eq; assign( Ra, getIReg(Ra_addr) ); @@ -1324,14 +1335,14 @@ static Bool dis_int_cmp ( UInt theInstr ) case 0x0B: // cmpi (Compare Immediate, PPC32 p368) EXTS_SIMM = extend_s_16to32(SIMM_16); DIP("cmpi crf%d,%u,r%d,0x%x\n", crfD, flag_L, Ra_addr, EXTS_SIMM); - irx_tst1 = binop(Iop_CmpLT32S, mkexpr(Ra), mkU32(EXTS_SIMM)); - irx_tst2 = binop(Iop_CmpEQ32, mkexpr(Ra), mkU32(EXTS_SIMM)); + irx_cmp_lt = binop(Iop_CmpLT32S, mkexpr(Ra), mkU32(EXTS_SIMM)); + irx_cmp_eq = binop(Iop_CmpEQ32, mkexpr(Ra), mkU32(EXTS_SIMM)); break; case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370) DIP("cmpli crf%d,%u,r%d,0x%x\n", crfD, flag_L, Ra_addr, UIMM_16); - irx_tst1 = binop(Iop_CmpLT32U, mkexpr(Ra), mkU32(UIMM_16)); - irx_tst2 = binop(Iop_CmpEQ32, mkexpr(Ra), mkU32(UIMM_16)); + irx_cmp_lt = binop(Iop_CmpLT32U, mkexpr(Ra), mkU32(UIMM_16)); + irx_cmp_eq = binop(Iop_CmpEQ32, mkexpr(Ra), mkU32(UIMM_16)); break; /* X Form */ @@ -1341,19 +1352,19 @@ static Bool dis_int_cmp ( UInt theInstr ) return False; } assign( Rb, getIReg(Rb_addr) ); - irx_tst2 = binop(Iop_CmpEQ32, mkexpr(Ra), mkexpr(Rb)); + irx_cmp_eq = binop(Iop_CmpEQ32, mkexpr(Ra), mkexpr(Rb)); switch (opc2) { case 0x000: // cmp (Compare, PPC32 p367) DIP("cmp crf%d,%u,r%d,r%d\n", crfD, flag_L, Ra_addr, Rb_addr); - irx_tst1 = binop(Iop_CmpLT32S, mkexpr(Ra), mkexpr(Rb)); + irx_cmp_lt = binop(Iop_CmpLT32S, mkexpr(Ra), mkexpr(Rb)); break; case 0x020: // cmpl (Compare Logical, PPC32 p369) DIP("cmpl crf%d,%u,r%d,r%d\n", crfD, flag_L, Ra_addr, Rb_addr); - irx_tst1 = binop(Iop_CmpLT32U, mkexpr(Ra), mkexpr(Rb)); + irx_cmp_lt = binop(Iop_CmpLT32U, mkexpr(Ra), mkexpr(Rb)); break; default: @@ -1367,13 +1378,14 @@ static Bool dis_int_cmp ( UInt theInstr ) return False; } - assign( mux1, IRExpr_Mux0X( unop(Iop_1Uto8, irx_tst1), // argL < argR ? - mkU32(SHIFT_CR_GT), // GT (or EQ...) - mkU32(SHIFT_CR_LT) ) ); // LT + irx_cmp_lt = unop(Iop_1Uto8, irx_cmp_lt); + irx_cmp_eq = unop(Iop_1Uto8, irx_cmp_eq); - assign( mux2, IRExpr_Mux0X( unop(Iop_1Uto8, irx_tst2), // argL == argR ? - mkexpr(mux1), // GT|LT - mkU32(SHIFT_CR_EQ) ) ); // EQ + // mux_shift_bit = (argL < argR) ? LT : GT (or EQ...) + assign( mux1, IRExpr_Mux0X( irx_cmp_lt, mkU32(SHIFT_CR_GT), mkU32(SHIFT_CR_LT) )); + + // mux_shift_bit = (argL == argR) ? EQ : GT|LT + assign( mux2, IRExpr_Mux0X( irx_cmp_eq, mkexpr(mux1), mkU32(SHIFT_CR_EQ) )); assign( xer_so, getReg_bit( PPC32_SPR_XER, SHIFT_XER_SO ) ); assign( cr7, binop(Iop_Or32, mkexpr(mux2), mkexpr(xer_so)) ); @@ -1412,41 +1424,41 @@ static Bool dis_int_logic ( UInt theInstr ) case 0x1C: // andi. (AND Immediate, PPC32 p358) DIP("andi. r%d,r%d,0x%x\n", Ra_addr, Rs_addr, UIMM_16); assign( Ra, binop(Iop_And32, mkexpr(Rs), mkU32(UIMM_16)) ); - putIReg( Ra_addr, mkexpr(Ra) ); - do_rc = True; + do_rc = True; // Always record to CR flag_Rc = 1; break; case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359) DIP("andis r%d,r%d,0x%x\n", Ra_addr, Rs_addr, UIMM_16); assign( Ra, binop(Iop_And32, mkexpr(Rs), mkU32(UIMM_16 << 16)) ); - putIReg( Ra_addr, mkexpr(Ra) ); - do_rc = True; + do_rc = True; // Always record to CR flag_Rc = 1; break; case 0x18: // ori (OR Immediate, PPC32 p497) DIP("ori r%d,r%d,0x%x\n", Ra_addr, Rs_addr, UIMM_16); - putIReg( Ra_addr, binop(Iop_Or32, mkexpr(Rs), mkU32(UIMM_16)) ); + assign( Ra, binop(Iop_Or32, mkexpr(Rs), mkU32(UIMM_16)) ); break; case 0x19: // oris (OR Immediate Shifted, PPC32 p498) DIP("oris r%d,r%d,0x%x\n", Ra_addr, Rs_addr, UIMM_16); - putIReg( Ra_addr, binop(Iop_Or32, mkexpr(Rs), mkU32(UIMM_16 << 16)) ); + assign( Ra, binop(Iop_Or32, mkexpr(Rs), mkU32(UIMM_16 << 16)) ); break; case 0x1A: // xori (XOR Immediate, PPC32 p550) DIP("xori r%d,r%d,0x%x\n", Ra_addr, Rs_addr, UIMM_16); - putIReg( Ra_addr, binop(Iop_Xor32, mkexpr(Rs), mkU32(UIMM_16)) ); + assign( Ra, binop(Iop_Xor32, mkexpr(Rs), mkU32(UIMM_16)) ); break; case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551) DIP("xoris r%d,r%d,0x%x\n", Ra_addr, Rs_addr, UIMM_16); - putIReg( Ra_addr, binop(Iop_Xor32, mkexpr(Rs), mkU32(UIMM_16 << 16)) ); + assign( Ra, binop(Iop_Xor32, mkexpr(Rs), mkU32(UIMM_16 << 16)) ); break; /* X Form */ case 0x1F: + do_rc = True; // All below record to CR + switch (opc2) { case 0x01C: // and (AND, PPC32 p356) DIP("and%s r%d,r%d,r%d\n", @@ -1550,16 +1562,14 @@ static Bool dis_int_logic ( UInt theInstr ) vex_printf("dis_int_logic(PPC32)(opc2)\n"); return False; } - - putIReg( Ra_addr, mkexpr(Ra) ); - do_rc = True; break; default: vex_printf("dis_int_logic(PPC32)(opc1)\n"); return False; } - + + putIReg( Ra_addr, mkexpr(Ra) ); if (do_rc && flag_Rc) { setFlags_CR7( mkexpr(Ra) ); } @@ -2629,8 +2639,7 @@ static Bool dis_int_shift ( UInt theInstr ) UInt opc2 = (theInstr >> 1) & 0x3FF; /* theInstr[1:10] */ UChar flag_Rc = toUChar((theInstr >> 0) & 1); /* theInstr[0] */ - UInt op = PPC32G_FLAG_OP_NUMBER; - Bool do_ca = False; + UInt flag_op = PPC32G_FLAG_OP_NUMBER; IRTemp sh_amt = newTemp(Ity_I8); IRTemp sign = newTemp(Ity_I32); @@ -2684,8 +2693,8 @@ static Bool dis_int_shift ( UInt theInstr ) assign( Rs_msk, binop(Iop_And32, mkexpr(Rs_sh), mkexpr(mask)) ); // Ra = Rs_msk | sext assign( Ra, binop(Iop_Or32, mkexpr(Rs_msk), mkexpr(sext)) ); - op = PPC32G_FLAG_OP_SRAW; - do_ca = True; + flag_op = PPC32G_FLAG_OP_SRAW; + setFlags_XER_CA( flag_op, mkexpr(Ra), mkexpr(Rs), mkexpr(Rb) ); break; case 0x338: // srawi (Shift Right Algebraic Word Immediate, PPC32 p507) @@ -2706,8 +2715,8 @@ static Bool dis_int_shift ( UInt theInstr ) unop(Iop_Not32, mkexpr(mask)) )); // Ra = Rs_shift | sext assign( Ra, binop(Iop_Or32, mkexpr(sext), mkexpr(Rs_sh)) ); - op = PPC32G_FLAG_OP_SRAWI; - do_ca = True; + flag_op = PPC32G_FLAG_OP_SRAWI; + setFlags_XER_CA( flag_op, mkexpr(Ra), mkexpr(Rs), mkexpr(Rb) ); break; case 0x218: // srw (Shift Right Word, PPC32 p508) @@ -2732,10 +2741,6 @@ static Bool dis_int_shift ( UInt theInstr ) putIReg( Ra_addr, mkexpr(Ra) ); - if (do_ca) { - vassert(op < PPC32G_FLAG_OP_NUMBER); - setFlags_XER_CA( op, mkexpr(Ra), mkexpr(Rs), mkexpr(Rb) ); - } if (flag_Rc) { setFlags_CR7( mkexpr(Ra) ); }