From: Cerion Armour-Brown Date: Fri, 28 Jan 2005 17:52:47 +0000 (+0000) Subject: - Added ops enum for xer ov,ca flag calculation X-Git-Tag: svn/VALGRIND_3_0_1^2~569 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=defb5d0f79b9fd484ea7e4cf5d42acc455755190;p=thirdparty%2Fvalgrind.git - Added ops enum for xer ov,ca flag calculation - Filled out the helper functions for xer_ov,ca - Added some DIPs - Using storeBE(),loadBE instead of LE TODO: Need to set up the IR for this! git-svn-id: svn://svn.valgrind.org/vex/trunk@765 --- diff --git a/VEX/priv/guest-ppc32/gdefs.h b/VEX/priv/guest-ppc32/gdefs.h index 0c324894a8..d0a694bb36 100644 --- a/VEX/priv/guest-ppc32/gdefs.h +++ b/VEX/priv/guest-ppc32/gdefs.h @@ -82,12 +82,33 @@ extern UInt ppc32g_calculate_cr0_bit2 ( UChar op, UInt word1, UInt word2 ); extern UInt ppc32g_calculate_cr0_bit3 ( UChar op, UInt word1, UInt word2 ); // Calculate XER flags -extern UInt ppc32g_calculate_xer_ov ( UInt theInstr, UInt Ra, UInt Rb, UInt Rd, UChar ov ); -extern UInt ppc32g_calculate_xer_ca ( UInt theInstr, UInt Ra, UInt Rb, UInt Rd, UChar ca ); +extern UInt ppc32g_calculate_xer_ov ( UInt op, UInt res, UInt arg1, UInt arg2, UChar ca ); +extern UInt ppc32g_calculate_xer_ca ( UInt op, UInt res, UInt arg1, UInt arg2, UChar ca ); +/* + Handy enumeration for flag calculation helper functions (xer_ca, ov) + */ +enum { + PPC_FLAG_OP_ADD, // addc, addo, addic + PPC_FLAG_OP_ADDE, // adde, addeo + PPC_FLAG_OP_ADDME, // addme, addmeo + PPC_FLAG_OP_ADDZE, // addze, addzeo + PPC_FLAG_OP_DIVW, // divwo + PPC_FLAG_OP_DIVWU, // divwuo + PPC_FLAG_OP_MULLW, // mullwo + PPC_FLAG_OP_NEG, // nego + PPC_FLAG_OP_SUBF, // subfo + PPC_FLAG_OP_SUBFC, // subfc, subfco + PPC_FLAG_OP_SUBFE, // subfe, subfeo + PPC_FLAG_OP_SUBFI, // subfic + PPC_FLAG_OP_SUBFME, // subfme, subfmeo + PPC_FLAG_OP_SUBZE, // subfze, subfzeo + PPC_FLAG_OP_SHR // srawi +}; + /* Defines conditions which we can ask for */ diff --git a/VEX/priv/guest-ppc32/ghelpers.c b/VEX/priv/guest-ppc32/ghelpers.c index f50f72880b..0801273ad8 100644 --- a/VEX/priv/guest-ppc32/ghelpers.c +++ b/VEX/priv/guest-ppc32/ghelpers.c @@ -55,6 +55,7 @@ */ +#define INT32_MIN (-2147483647-1) @@ -65,7 +66,7 @@ UInt ppc32g_calculate_cr0_all ( UChar op, UInt word1, UInt word2 ) { Int sword1 = (Int)word1; if (op) { - return (word1 & 0xF0000000); + return (word1 & 0x0000000F); } else { return ((word2 & 1) << 3) @@ -101,63 +102,92 @@ UInt ppc32g_calculate_cr0_bit3 ( UChar op, UInt word1, UInt word2 ) // 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 } @@ -253,7 +283,7 @@ void LibVEX_GuestPPC32_initialise ( /*OUT*/VexGuestPPC32State* vex_state ) 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; diff --git a/VEX/priv/guest-ppc32/toIR.c b/VEX/priv/guest-ppc32/toIR.c index cb9d7cc367..218b397104 100644 --- a/VEX/priv/guest-ppc32/toIR.c +++ b/VEX/priv/guest-ppc32/toIR.c @@ -130,7 +130,7 @@ static IRBB* irbb; #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) @@ -442,11 +442,13 @@ static void assign ( IRTemp dst, IRExpr* e ) } #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); @@ -495,7 +497,7 @@ static IRExpr* mkU ( IRType ty, UInt i ) #endif #if 0 -static IRExpr* loadLE ( IRType ty, IRExpr* data ) +static IRExpr* loadBE ( IRType ty, IRExpr* data ) { return IRExpr_LDle(ty,data); } @@ -630,12 +632,12 @@ static IRExpr* mk_ppc32g_calculate_cr0_bit3 ( void ) // 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 @@ -649,12 +651,12 @@ static IRExpr* mk_ppc32g_calculate_xer_ov ( UInt theInstr, IRTemp Ra, } // 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 @@ -670,19 +672,21 @@ static IRExpr* mk_ppc32g_calculate_xer_ca ( UInt theInstr, IRTemp Ra, // 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 ) ) ); } @@ -771,15 +775,15 @@ void setFlags_CR0_Flags ( IRTemp flags_cr0 ) */ 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; @@ -805,17 +809,23 @@ static Bool dis_int_arith ( UInt theInstr, UChar form ) } 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) @@ -824,6 +834,8 @@ static Bool dis_int_arith ( UInt theInstr, UChar form ) } 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; @@ -833,14 +845,22 @@ static Bool dis_int_arith ( UInt theInstr, UChar form ) 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) @@ -851,8 +871,12 @@ static Bool dis_int_arith ( UInt theInstr, UChar form ) 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) @@ -861,6 +885,10 @@ static Bool dis_int_arith ( UInt theInstr, UChar form ) // 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) @@ -869,6 +897,10 @@ static Bool dis_int_arith ( UInt theInstr, UChar form ) // 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: @@ -959,14 +991,23 @@ static Bool dis_branch ( theInstr ) } 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)) ); @@ -1170,16 +1211,18 @@ static DisResult disInstr ( /*IN*/ Bool resteerOK, 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; diff --git a/VEX/pub/libvex_guest_ppc32.h b/VEX/pub/libvex_guest_ppc32.h index ae0ba1dd92..ff2a4c7ce0 100644 --- a/VEX/pub/libvex_guest_ppc32.h +++ b/VEX/pub/libvex_guest_ppc32.h @@ -91,7 +91,7 @@ typedef // CR1: Used for FP - don't need yet. // CR2:7: Used for 'compare' instructions (bits 0:8 not used) - UInt guest_CR2_7; + UInt guest_CR2to7; /* XER */ UChar guest_XER_SO; // Summary Overflow