mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-12 14:20:04 +00:00
Fixed xer_ca flag calc for subfze,
Cleaned up ghelpers.c: calc_xer_ca, calc_xer_ov Cleaned up toIR.c dis_int_arith, dis_int_cmp, dis_int_logic, dis_int_shift git-svn-id: svn://svn.valgrind.org/vex/trunk@1040
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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) );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user