*/
+#define INT32_MIN (-2147483647-1)
{
Int sword1 = (Int)word1;
if (op) {
- return (word1 & 0xF0000000);
+ return (word1 & 0x0000000F);
} else {
return
((word2 & 1) << 3)
// Calculate XER_OV
-UInt ppc32g_calculate_xer_ov ( UInt theInstr, UInt Ra, UInt Rb, UInt Rd, UChar ov )
+UInt ppc32g_calculate_xer_ov ( UInt op, UInt res,
+ UInt arg1, UInt arg2, UChar ov )
{
- UChar opc1 = (theInstr >> 26) & 0x3F; /* opcode1: theInstr[0:5] */
- UInt opc2 = (theInstr >> 1) & 0x1FF; /* opcode2: theInstr[22:30] */
+ ULong ul_tmp=0;
- switch (opc1) {
- case 0x1F:
- switch (opc2) {
- case 0x10A: // addo
- // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
- return ((Ra^Rb^-1) & (Ra^Rd) & (1<<31)) ? 1:0;
+ switch (op) {
+ case PPC_FLAG_OP_ADD: // addo, addc
+ case PPC_FLAG_OP_ADDE: // addeo
+ return ((arg1^arg2^-1) & (arg1^res) & (1<<31)) ? 1:0;
+ // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
- case 0x00A: // addc
- return ((Ra^Rb^-1) & (Ra^Rd) & (1<<31)) ? 1:0;
+ case PPC_FLAG_OP_ADDME: // addmeo
+ return ((arg1) & (arg1 ^ res) & (1<<31)) ? 1:0;
+ // i.e. (neg & (sign_changed) & sign_mask)
- case 0x08A: // addeo
- return ((Ra^Rb^-1) & (Ra^Rd) & (1<<31)) ? 1:0;
+ case PPC_FLAG_OP_ADDZE: // addzeo
+ return ((arg1^(-1)) & (arg1 ^ res) & (1<<31)) ? 1:0;
+ // i.e. (pos & (sign_changed) & sign_mask)
- default:
- break;
- }
+ case PPC_FLAG_OP_DIVW: // divwo
+ return ((arg1 == INT32_MIN && arg2 == -1) || arg2 == 0) ? 1:0;
+
+ case PPC_FLAG_OP_DIVWU: // divwuo
+ return (arg2 == 0) ? 1:0;
+
+ case PPC_FLAG_OP_MULLW: // mullwo
+ ul_tmp = (ULong)arg1 * (ULong)arg2;
+ return (res != res) ? 1:0;
+
+ case PPC_FLAG_OP_NEG: // nego
+ return (arg1 == 0x80000000) ? 1:0;
+
+ case PPC_FLAG_OP_SUBF: // subfo
+ case PPC_FLAG_OP_SUBFC: // subfco
+ case PPC_FLAG_OP_SUBFE: // subfeo
+ return (((~arg1)^arg2^(-1)) & ((~arg1)^res) & (1<<31)) ? 1:0;
+
+ case PPC_FLAG_OP_SUBFME: // subfmeo
+ return ((~arg1) & ((~arg1)^res) & (1<<31)) ? 1:0;
+
+ case PPC_FLAG_OP_SUBZE: // subfzeo
+ return (((~arg1)^(-1)) & ((~arg1)^res) & (1<<31)) ? 1:0;
default:
break;
}
- return 0;
+ vpanic("ppc32g_calculate_xer_ov(ppc32)");
+ return 0; // notreached
}
// Calculate XER_CA
-UInt ppc32g_calculate_xer_ca ( UInt theInstr, UInt Ra, UInt Rb, UInt Rd, UChar ca )
+UInt ppc32g_calculate_xer_ca ( UInt op, UInt res,
+ UInt arg1, UInt arg2, UChar ca )
{
- UChar opc1 = (theInstr >> 26) & 0x3F; /* opcode1: theInstr[0:5] */
- UInt opc2 = (theInstr >> 1) & 0x1FF; /* opcode2: theInstr[22:30] */
+ switch (op) {
+ case PPC_FLAG_OP_ADD: // addc, addco, addic
+ case PPC_FLAG_OP_ADDZE: // addze, addzeo
+ return (res < arg1) ? 1:0;
- switch (opc1) {
- case 0x0D: // addic
- case 0x0E: // addic.
- return (Rd < Ra) ? 1:0;
+ case PPC_FLAG_OP_ADDE: // adde, addeo
+ return (res < arg1 || (ca==1 && res==arg1)) ? 1:0;
- case 0x1F:
- switch (opc2) {
- case 0x00A: // addc
- return (Rd < Ra) ? 1:0;
+ case PPC_FLAG_OP_ADDME: // addme, addmeo
+ return (arg1 != 0) ? 1:0;
- case 0x08A: // adde
- return (Rd < Ra || (ca==1 && Rd==Ra)) ? 1:0;
+ case PPC_FLAG_OP_SUBFC: // subfc, subfco
+ case PPC_FLAG_OP_SUBFI: // subfic
+ case PPC_FLAG_OP_SUBZE: // subfze, subfzeo
+ return (res <= arg2) ? 1:0;
- default:
- break;
- }
+ case PPC_FLAG_OP_SUBFE: // subfe, subfeo
+ return ((res < arg2) || (ca == 1 && res == arg2)) ? 1:0;
+ case PPC_FLAG_OP_SUBFME: // subfme, subfmeo
+ return (res != -1) ? 1:0;
+
+ case PPC_FLAG_OP_SHR: // srawi
+ // res = arg1 >> arg2
+ return (arg1 < 0 && (arg1 & arg2) != 0) ? 1:0;
+
default:
break;
}
-
- return 0;
+ vpanic("ppc32g_calculate_xer_ov(ppc32)");
+ return 0; // notreached
}
vex_state->guest_CC_DEP1 = 0;
vex_state->guest_CC_DEP2 = 0;
- vex_state->guest_CR2_7 = 0;
+ vex_state->guest_CR2to7 = 0;
vex_state->guest_XER_SO = 0;
vex_state->guest_XER_OV = 0;
#define OFFB_CC_DEP1 offsetof(VexGuestPPC32State,guest_CC_DEP1)
#define OFFB_CC_DEP2 offsetof(VexGuestPPC32State,guest_CC_DEP2)
-#define OFFB_CR2_7 offsetof(VexGuestPPC32State,guest_CR2_7)
+#define OFFB_CR2to7 offsetof(VexGuestPPC32State,guest_CR2to7)
#define OFFB_XER_SO offsetof(VexGuestPPC32State,guest_XER_SO)
#define OFFB_XER_OV offsetof(VexGuestPPC32State,guest_XER_OV)
}
#if 0
-static void storeLE ( IRExpr* addr, IRExpr* data )
+static void storeBE ( IRExpr* addr, IRExpr* data )
{
stmt( IRStmt_STle(addr,data) );
}
+#endif
+#if 0
static IRExpr* unop ( IROp op, IRExpr* a )
{
return IRExpr_Unop(op, a);
#endif
#if 0
-static IRExpr* loadLE ( IRType ty, IRExpr* data )
+static IRExpr* loadBE ( IRType ty, IRExpr* data )
{
return IRExpr_LDle(ty,data);
}
// Calculate XER_OV flag
-static IRExpr* mk_ppc32g_calculate_xer_ov ( UInt theInstr, IRTemp Ra,
- IRTemp Rb, IRTemp Rd )
+static IRExpr* mk_ppc32g_calculate_xer_ov ( UInt op, IRTemp res,
+ IRTemp arg1, IRTemp arg2 )
{
IRExpr** args =
mkIRExprVec_5(
- mkU32(theInstr), mkexpr(Ra), mkexpr(Rb), mkexpr(Rd),
+ mkU32(op), mkexpr(res), mkexpr(arg1), mkexpr(arg2),
IRExpr_Get(OFFB_XER_OV, Ity_I8) );
IRExpr* call
}
// Calculate XER_CA flag
-static IRExpr* mk_ppc32g_calculate_xer_ca ( UInt theInstr, IRTemp Ra,
- IRTemp Rb, IRTemp Rd )
+static IRExpr* mk_ppc32g_calculate_xer_ca ( UInt op, IRTemp res,
+ IRTemp arg1, IRTemp arg2 )
{
IRExpr** args =
mkIRExprVec_5(
- mkU32(theInstr), mkexpr(Ra), mkexpr(Rb), mkexpr(Rd),
+ mkU32(op), mkexpr(res), mkexpr(arg1), mkexpr(arg2),
IRExpr_Get(OFFB_XER_CA, Ity_I8) );
IRExpr* call
// Helper to set XER_OV,SO flags
-static void mk_ppc32g_set_xer_ov_so( UInt theInstr, IRTemp Ra, IRTemp Rb, IRTemp Rd )
+static void mk_ppc32g_set_xer_ov_so( UInt op, IRTemp res,
+ IRTemp arg1, IRTemp arg2 )
{
IRTemp ir_tmp = newTemp(Ity_I32);
- assign( ir_tmp, mk_ppc32g_calculate_xer_ov( theInstr, Ra, Rb, Rd ) );
+ assign( ir_tmp, mk_ppc32g_calculate_xer_ov( op, res, arg1, arg2 ) );
stmt( IRStmt_Put( OFFB_XER_OV, mkexpr(ir_tmp) ));
stmt( IRStmt_Put( OFFB_XER_SO, mkexpr(ir_tmp) ));
}
// Helper to set XER_CA flag
-static void mk_ppc32g_set_xer_ca( UInt theInstr, IRTemp Ra, IRTemp Rb, IRTemp Rd )
+static void mk_ppc32g_set_xer_ca( UInt op, IRTemp res,
+ IRTemp arg1, IRTemp arg2 )
{
- stmt( IRStmt_Put( OFFB_XER_CA,
- mk_ppc32g_calculate_xer_ca( theInstr, Ra, Rb, Rd ) ) );
+ stmt( IRStmt_Put( OFFB_XER_CA,
+ mk_ppc32g_calculate_xer_ca( op, res, arg1, arg2 ) ) );
}
*/
static Bool dis_int_arith ( UInt theInstr, UChar form )
{
- UChar opc1 = (theInstr) & 0x3F; /* opcode1: theInstr[0:5] */
- UChar Rd_addr = (theInstr >> 6 ) & 0x1F; /* reg D: theInstr[6:10] */
- UChar Ra_addr = (theInstr >> 11) & 0x1F; /* reg A: theInstr[11:15] */
- UInt SIMM_16 = (theInstr >> 16) & 0xFFFF; /* SIMM: theInstr[16:31] */
+ UChar opc1 = (theInstr) & 0x3F; /* theInstr[0:5] */
+ UChar Rd_addr = (theInstr >> 6 ) & 0x1F; /* theInstr[6:10] */
+ UChar Ra_addr = (theInstr >> 11) & 0x1F; /* theInstr[11:15] */
+ UInt SIMM_16 = (theInstr >> 16) & 0xFFFF; /* theInstr[16:31] */
- UChar Rb_addr = (theInstr >> 16) & 0x1F; /* reg B: theInstr[16:20] */
- UChar flag_OE = (theInstr >> 21) & 1; /* OE: theInstr[21] */
- UInt opc2 = (theInstr >> 22) & 0x1FF; /* opcode2: theInstr[22:30] */
- UChar flag_Rc = (theInstr >> 31) & 1; /* Rc: theInstr[31] */
+ UChar Rb_addr = (theInstr >> 16) & 0x1F; /* theInstr[16:20] */
+ UChar flag_OE = (theInstr >> 21) & 1; /* theInstr[21] */
+ UInt opc2 = (theInstr >> 22) & 0x1FF; /* theInstr[22:30] */
+ UChar flag_Rc = (theInstr >> 31) & 1; /* theInstr[31] */
UInt EXTS_SIMM = 0;
} else {
assign( Rd, binop( Iop_Add32, mkexpr(Ra), mkU32(EXTS_SIMM) ) );
}
+
+ DIP("addi %i,%i,0x%x\n", Rd_addr, Ra_addr, SIMM_16);
break;
case 0x0D: // addic (Add Immediate Carrying)
assign( Rd, binop( Iop_Add32, mkexpr(Ra), mkU32(EXTS_SIMM) ) );
- mk_ppc32g_set_xer_ca( theInstr, Ra, Rb, Rd );
+ mk_ppc32g_set_xer_ca( PPC_FLAG_OP_ADD, Rd, Ra, Rb );
+
+ DIP("addic %i,%i,0x%x\n", Rd_addr, Ra_addr, SIMM_16);
break;
case 0x0E: // addic. (Add Immediate Carrying and Record)
assign( Rd, binop( Iop_Add32, mkexpr(Ra), mkU32(EXTS_SIMM) ) );
- mk_ppc32g_set_xer_ca( theInstr, Ra, Rb, Rd );
+ mk_ppc32g_set_xer_ca( PPC_FLAG_OP_ADD, Rd, Ra, Rb );
setFlags_CR0_Result( Rd );
+
+ DIP("addic. %i,%i,0x%x\n", Rd_addr, Ra_addr, SIMM_16);
break;
case 0x0F: // addis (Add Immediate Shifted)
} else {
assign( Rd, binop( Iop_Add32, mkexpr(Ra), mkU32(EXTS_SIMM << 16) ) );
}
+
+ DIP("addis %i,%i,0x%x\n", Rd_addr, Ra_addr, SIMM_16);
break;
case 0x10A: // add (Add)
assign( Rd, binop(Iop_Add32, mkexpr(Ra), mkexpr(Rb)) );
if (flag_Rc) { setFlags_CR0_Result( Rd ); }
- if (flag_OE) { mk_ppc32g_set_xer_ov_so( theInstr, Ra, Rb, Rd ); }
+ if (flag_OE) { mk_ppc32g_set_xer_ov_so( PPC_FLAG_OP_ADD, Rd, Ra, Rb ); }
+
+ DIP("add%s%s %i,%i,%i\n",
+ flag_OE ? "o" : "", flag_Rc ? "." : "",
+ Rd_addr, Ra_addr, Rb_addr);
break;
case 0x00A: // addc (Add Carrying)
assign( Rd, binop(Iop_Add32, mkexpr(Ra), mkexpr(Rb)) );
if (flag_Rc) { setFlags_CR0_Result( Rd ); }
- mk_ppc32g_set_xer_ca( theInstr, Ra, Rb, Rd );
- if (flag_OE) { mk_ppc32g_set_xer_ov_so( theInstr, Ra, Rb, Rd ); }
+ mk_ppc32g_set_xer_ca( PPC_FLAG_OP_ADD, Rd, Ra, Rb );
+ if (flag_OE) { mk_ppc32g_set_xer_ov_so( PPC_FLAG_OP_ADD, Rd, Ra, Rb ); }
+
+ DIP("addc%s%s %i,%i,%i\n",
+ flag_OE ? "o" : "", flag_Rc ? "." : "",
+ Rd_addr, Ra_addr, Rb_addr);
break;
case 0x08A: // adde (Add Extended)
mkexpr(tmp)) );
if (flag_Rc) { setFlags_CR0_Result( Rd ); }
- mk_ppc32g_set_xer_ca( theInstr, Ra, Rb, Rd );
- if (flag_OE) { mk_ppc32g_set_xer_ov_so( theInstr, Ra, Rb, Rd ); }
+ mk_ppc32g_set_xer_ca( PPC_FLAG_OP_ADDE, Rd, Ra, Rb );
+ if (flag_OE) { mk_ppc32g_set_xer_ov_so( PPC_FLAG_OP_ADDE, Rd, Ra, Rb ); }
+
+ DIP("adde%s%s %i,%i,%i\n",
+ flag_OE ? "o" : "", flag_Rc ? "." : "",
+ Rd_addr, Ra_addr, Rb_addr);
break;
case 0x0EA: // addme (Add to Minus One Extended)
// if (Rc=1) { set guest_result }
// set XER[CA]
// if (OE=1) { XER[SO,OV] }
+
+ DIP("addme%s%s %i,%i,%i\n",
+ flag_OE ? "o" : "", flag_Rc ? "." : "",
+ Rd_addr, Ra_addr, Rb_addr);
return False;
case 0x0CA: // addze (Add to Zero Extended)
// if (Rc=1) { set guest_result }
// set XER[CA]
// if (OE=1) { XER[SO,OV] }
+
+ DIP("addze%s%s %i,%i,%i\n",
+ flag_OE ? "o" : "", flag_Rc ? "." : "",
+ Rd_addr, Ra_addr, Rb_addr);
return False;
default:
} else {
assign( cr_bi, binop(Iop_And32, mkU32(1),
binop(Iop_Shr32,
- IRExpr_Get(OFFB_CR2_7, Ity_I32),
+ IRExpr_Get(OFFB_CR2to7, Ity_I32),
mkU32(BI))) );
}
assign( cond_ok, binop( Iop_Or32, mkexpr(BO & 1),
binop( Iop_CmpEQ8, mkexpr(cr_bi),
mkU32((BO>>1)&1) )));
- // CAB: umm... querying guest state to set irbb->... how to do this?
+
+ // CAB: This is getting silly - Maybe use a helper function?
+
+/*
+ stmt( IRStmt_Exit( mk_x86g_calculate_condition(condPos),
+ Ijk_Boring,
+ IRConst_U32(d32_false) ) );
+ irbb->next = mkU32(d32_true);
+ irbb->jumpkind = Ijk_Boring;
+*/
/*
assign( tmp, binop(Iop_And32, mkexpr(ctr_ok), mkexpr(cond_ok)) );
case 0x1F:
+
+ opc2 = (theInstr >> 22) & 0x1FF; /* opcode2: [22:30] */
switch (opc2) {
/*
Integer Arithmetic Instructions
*/
- case 0x10A: case 0x30A: // add
- case 0x00A: case 0x20A: // addc
- case 0x08A: case 0x28A: // adde
- case 0x0EA: case 0x2EA: // addme
- case 0x0CA: case 0x2CA: // addze
+ case 0x10A: // add
+ case 0x00A: // addc
+ case 0x08A: // adde
+ case 0x0EA: // addme
+ case 0x0CA: // addze
if (dis_int_arith(theInstr, 1)) break;
goto decode_failure;