diff --git a/VEX/priv/guest-ppc32/gdefs.h b/VEX/priv/guest-ppc32/gdefs.h index fc71f2370..5f4887e64 100644 --- a/VEX/priv/guest-ppc32/gdefs.h +++ b/VEX/priv/guest-ppc32/gdefs.h @@ -75,15 +75,11 @@ VexGuestLayout ppc32Guest_layout; /* --- CLEAN HELPERS --- */ // Calculate CR0 flags -extern UChar ppc32g_calculate_cr0_all ( UInt op, UInt word1, UInt xer_so ); -extern UChar ppc32g_calculate_cr0_bit0 ( UInt op, UInt word1, UInt xer_so ); -extern UChar ppc32g_calculate_cr0_bit1 ( UInt op, UInt word1, UInt xer_so ); -extern UChar ppc32g_calculate_cr0_bit2 ( UInt op, UInt word1, UInt xer_so ); -extern UChar ppc32g_calculate_cr0_bit3 ( UInt op, UInt word1, UInt xer_so ); +extern UInt ppc32g_calculate_cr0_all ( UInt op, UInt word1, UInt xer_so ); // Calculate XER flags -extern UChar ppc32g_calculate_xer_ov ( UInt op, UInt res, UInt arg1, UInt arg2, UInt ca ); -extern UChar ppc32g_calculate_xer_ca ( UInt op, UInt res, UInt arg1, UInt arg2, UInt ca ); +extern UInt ppc32g_calculate_xer_ov ( UInt op, UInt res, UInt arg1, UInt arg2, UInt ca ); +extern UInt ppc32g_calculate_xer_ca ( UInt op, UInt res, UInt arg1, UInt arg2, UInt ca ); diff --git a/VEX/priv/guest-ppc32/ghelpers.c b/VEX/priv/guest-ppc32/ghelpers.c index 124357f89..b30f117a4 100644 --- a/VEX/priv/guest-ppc32/ghelpers.c +++ b/VEX/priv/guest-ppc32/ghelpers.c @@ -61,49 +61,28 @@ /* CALLED FROM GENERATED CODE: CLEAN HELPER */ /* Calculates CR0[LT,GT,EQ,SO] flags from the supplied - thunk parameters. */ -UChar ppc32g_calculate_cr0_all ( UInt op, UInt word1, UInt xer_so ) + thunk parameters. + Returns values in high field (correct wrt actual CR) + */ +UInt ppc32g_calculate_cr0_all ( UInt op, UInt word1, UInt xer_so ) { - Int sword1 = (Int)word1; + Int sword1 = (int)word1; if (op) { return (word1 & 0xF0000000); } else { return - (xer_so & 1) - | (((sword1 == 0) ? 1:0) << 1) - | (((sword1 > 0) ? 1:0) << 2) - | (((sword1 < 0) ? 1:0) << 3); + ((xer_so & 1) << 28) + | (((sword1 == 0) ? 1:0) << 29) + | (((sword1 > 0) ? 1:0) << 30) + | (((sword1 < 0) ? 1:0) << 31); } } -UChar ppc32g_calculate_cr0_bit0 ( UInt op, UInt word1, UInt xer_so ) -{ - return (ppc32g_calculate_cr0_all(op,word1,xer_so) >> 0) & 1; -} - -UChar ppc32g_calculate_cr0_bit1 ( UInt op, UInt word1, UInt xer_so ) -{ - return (ppc32g_calculate_cr0_all(op,word1,xer_so) >> 1) & 1; -} - -UChar ppc32g_calculate_cr0_bit2 ( UInt op, UInt word1, UInt xer_so ) -{ - return (ppc32g_calculate_cr0_all(op,word1,xer_so) >> 2) & 1; -} - -UChar ppc32g_calculate_cr0_bit3 ( UInt op, UInt word1, UInt xer_so ) -{ - return (ppc32g_calculate_cr0_all(op,word1,xer_so) >> 3) & 1; -} - - - - // Calculate XER_OV -UChar ppc32g_calculate_xer_ov ( UInt op, UInt res, - UInt arg1, UInt arg2, UInt ov ) +UInt ppc32g_calculate_xer_ov ( UInt op, UInt res, + UInt arg1, UInt arg2, UInt ov ) { ULong ul_tmp=0; @@ -154,8 +133,8 @@ UChar ppc32g_calculate_xer_ov ( UInt op, UInt res, } // Calculate XER_CA -UChar ppc32g_calculate_xer_ca ( UInt op, UInt res, - UInt arg1, UInt arg2, UInt ca ) +UInt ppc32g_calculate_xer_ca ( UInt op, UInt res, + UInt arg1, UInt arg2, UInt ca ) { switch (op) { case PPC32G_FLAG_OP_ADD: // addc, addco, addic diff --git a/VEX/priv/guest-ppc32/toIR.c b/VEX/priv/guest-ppc32/toIR.c index 763c51268..2654fe898 100644 --- a/VEX/priv/guest-ppc32/toIR.c +++ b/VEX/priv/guest-ppc32/toIR.c @@ -639,56 +639,6 @@ static IRExpr* mk_ppc32g_calculate_cr0_all ( void ) return call; } -#if 0 -static IRExpr* mk_ppc32g_calculate_cr0_bit0 ( void ) -{ - IRExpr* call - = mkIRExprCCall( - Ity_I32, - 0/*regparm*/, - "ppc32g_calculate_cr0_bit0", &ppc32g_calculate_cr0_bit0, - get_ppc32g_cr0_args() - ); - return call; -} - -static IRExpr* mk_ppc32g_calculate_cr0_bit1 ( void ) -{ - IRExpr* call - = mkIRExprCCall( - Ity_I32, - 0/*regparm*/, - "ppc32g_calculate_cr0_bit1", &ppc32g_calculate_cr0_bit1, - get_ppc32g_cr0_args() - ); - return call; -} - -static IRExpr* mk_ppc32g_calculate_cr0_bit2 ( void ) -{ - IRExpr* call - = mkIRExprCCall( - Ity_I32, - 0/*regparm*/, - "ppc32g_calculate_cr0_bit2", &ppc32g_calculate_cr0_bit2, - get_ppc32g_cr0_args() - ); - return call; -} - -static IRExpr* mk_ppc32g_calculate_cr0_bit3 ( void ) -{ - IRExpr* call - = mkIRExprCCall( - Ity_I32, - 0/*regparm*/, - "ppc32g_calculate_cr0_bit3", &ppc32g_calculate_cr0_bit3, - get_ppc32g_cr0_args() - ); - return call; -} -#endif - // Calculate XER_OV flag static IRExpr* mk_ppc32g_calculate_xer_ov ( UInt op, IRTemp res, @@ -785,6 +735,7 @@ static void mk_ppc32g_set_xer_ca( UInt op, IRTemp res, flag-setting operation. Hence the various setFlags_* functions. */ +#if 0 /* U-widen 8/16/32 bit int expr to 32. */ static IRExpr* widenUto32 ( IRExpr* e ) { @@ -795,6 +746,7 @@ static IRExpr* widenUto32 ( IRExpr* e ) default: vpanic("widenUto32"); } } +#endif /* Narrow 8/16/32 bit int expr to 8/16/32. Clearly only some of these combinations make sense. */ @@ -816,11 +768,8 @@ static IRExpr* narrowTo ( IRType dst_ty, IRExpr* e ) vpanic("narrowTo(PPC32)"); } - - -/* Set the flags thunk OP, DEP1, DEP2 fields. */ -static -void setFlags_CR0_Result ( IRExpr* result ) +/* Set the flags thunk OP=0, DEP1, DEP2 fields. */ +static void setFlags_CR0_Result ( IRExpr* result ) { vassert(typeOfIRExpr(irbb->tyenv,result) == Ity_I32); @@ -829,20 +778,187 @@ void setFlags_CR0_Result ( IRExpr* result ) stmt( IRStmt_Put( OFFB_CC_DEP2, IRExpr_Get(OFFB_XER_SO, Ity_I8) )); } -/* Set the flags thunk OP, DEP1 fields, write 0 to DEP2. */ -static -void setFlags_CR0_Flags ( IRExpr* flags_cr0 ) +/* Write exactly the given flags to field CR0 + Set the flags thunk OP=1, DEP1 fields, DEP2=0. */ +static void setFlags_CR0_Imm ( IRExpr* flags ) { - vassert(typeOfIRExpr(irbb->tyenv,flags_cr0) == Ity_I32); + vassert(typeOfIRExpr(irbb->tyenv,flags) == Ity_I32); stmt( IRStmt_Put( OFFB_CC_OP, mkU8(1)) ); - stmt( IRStmt_Put( OFFB_CC_DEP1, flags_cr0) ); + stmt( IRStmt_Put( OFFB_CC_DEP1, flags) ); stmt( IRStmt_Put( OFFB_CC_DEP2, mkU8(0)) ); } + + + +/* ------------- Abstract register interface. ------------- */ +/* + Most registers are represented directly in the cpu_state + Others are represented by the thunk +*/ +static IRExpr* getReg_LR ( ) { + return IRExpr_Get(OFFB_LR, Ity_I32); +} +static void putReg_LR ( IRExpr* src ) +{ + vassert( typeOfIRExpr(irbb->tyenv,src ) == Ity_I32 ); + stmt( IRStmt_Put( OFFB_LR, src) ); +} + +static IRExpr* getReg_CTR ( ) { + return IRExpr_Get(OFFB_CTR, Ity_I32); +} +static void putReg_CTR ( IRExpr* src ) +{ + vassert( typeOfIRExpr(irbb->tyenv,src ) == Ity_I32 ); + stmt( IRStmt_Put( OFFB_CTR, src) ); +} + +static IRExpr* getReg_XER_SO ( ) +{ + return unop(Iop_8Uto32, IRExpr_Get(OFFB_XER_SO, Ity_I8)); +} +static void putReg_XER_SO ( IRExpr* src ) +{ + vassert( typeOfIRExpr(irbb->tyenv,src ) == Ity_I1 ); + stmt( IRStmt_Put( OFFB_XER_SO, unop(Iop_1Uto8, src) ) ); +} + +static IRExpr* getReg_XER_OV ( ) +{ + return unop(Iop_8Uto32, IRExpr_Get(OFFB_XER_OV, Ity_I8)); +} +static void putReg_XER_OV ( IRExpr* src ) +{ + vassert( typeOfIRExpr(irbb->tyenv,src ) == Ity_I1 ); + stmt( IRStmt_Put( OFFB_XER_OV, unop(Iop_1Uto8, src) ) ); +} + +static IRExpr* getReg_XER_CA ( ) +{ + return unop(Iop_8Uto32, IRExpr_Get(OFFB_XER_CA, Ity_I8)); +} +static void putReg_XER_CA ( IRExpr* src ) +{ + vassert( typeOfIRExpr(irbb->tyenv,src ) == Ity_I1 ); + stmt( IRStmt_Put( OFFB_XER_CA, unop(Iop_1Uto8, src) ) ); +} + +static IRExpr* getReg_XER_BC ( ) +{ + return unop(Iop_8Uto32, IRExpr_Get(OFFB_XER_BC, Ity_I8)); +} +static void putReg_XER_BC ( IRExpr* src ) +{ + vassert( typeOfIRExpr(irbb->tyenv,src ) == Ity_I8 ); + IRExpr* src_mskd = binop(Iop_And8, src, mkU8(0x7F)); + stmt( IRStmt_Put( OFFB_XER_BC, src_mskd ) ); +} + +static IRExpr* getReg_XER ( ) +{ + IRTemp xer_so = newTemp(Ity_I32); + IRTemp xer_ov = newTemp(Ity_I32); + IRTemp xer_ca = newTemp(Ity_I32); + IRTemp tmp = newTemp(Ity_I32); + + assign( xer_so, binop(Iop_Shl32, getReg_XER_SO(), mkU8(3)) ); + assign( xer_ov, binop(Iop_Shl32, getReg_XER_OV(), mkU8(2)) ); + assign( xer_ca, binop(Iop_Shl32, getReg_XER_CA(), mkU8(1)) ); + assign( tmp, binop(Iop_Shl32, + binop(Iop_Or32, mkexpr(xer_so), + binop(Iop_Or32, mkexpr(xer_ov), mkexpr(xer_ca))), + mkU8(28)) ); + return binop(Iop_Or32, mkexpr(tmp), getReg_XER_BC()); +} +static void putReg_XER ( IRExpr* src ) +{ + vassert( typeOfIRExpr(irbb->tyenv,src ) == Ity_I32 ); + + putReg_XER_SO( unop(Iop_32to1, binop(Iop_Shr32, src, mkU8(31))) ); + putReg_XER_OV( unop(Iop_32to1, binop(Iop_Shr32, src, mkU8(30))) ); + putReg_XER_CA( unop(Iop_32to1, binop(Iop_Shr32, src, mkU8(29))) ); + putReg_XER_BC( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(0))) ); +} + + +static IRExpr* getReg_CR ( ) +{ + IRTemp cr0 = newTemp(Ity_I32); + IRTemp cr1to7 = newTemp(Ity_I32); + IRTemp cr = newTemp(Ity_I32); + + assign( cr0, mk_ppc32g_calculate_cr0_all() ); + assign( cr1to7, IRExpr_Get(OFFB_CR1to7, Ity_I32) ); + assign( cr, binop(Iop_Or32, + binop(Iop_And32, mkexpr(cr1to7), mkU32(-1>>4)), + binop(Iop_Shl32, mkexpr(cr0), mkU8(28))) ); + return mkexpr(cr); +} + +/* Write given flags (least sig. nibble) to given field of CR + If given field is 8, set the whole of CR to flags, dep on mask + Note: For CR0, we're writing to the thunk. +*/ +static void putReg_CR ( UInt field_idx, IRExpr* src, UInt mask ) +{ + vassert( typeOfIRExpr(irbb->tyenv,src ) == Ity_I32 ); + vassert( field_idx <= 8 ); + + UInt bit_idx = field_idx * 4; + + IRTemp cr1to7_old = newTemp(Ity_I32); + IRTemp cr1to7_mskd = newTemp(Ity_I32); + IRTemp src_mskd = newTemp(Ity_I32); + IRTemp src1to7_mskd = newTemp(Ity_I32); + IRTemp tmp = newTemp(Ity_I32); + + if (field_idx == 8) { + // Assign fields of src specified by mask to CR: + // CR = src & mask | CR & ~mask + assign( src_mskd, binop(Iop_And32, src, mkU32(mask)) ); + if (mask & (0xF<<28)) { + setFlags_CR0_Imm( binop(Iop_And32, + mkexpr(src_mskd), mkU32(0xF<<28)) ); + } + assign( src1to7_mskd, binop(Iop_And32, + mkexpr(src_mskd), mkU32(-1>>4)) ); + assign( cr1to7_old, binop(Iop_And32, mkU32(-1>>4), getReg_CR()) ); + assign( cr1to7_mskd, binop(Iop_And32, + mkexpr(cr1to7_old), mkU32(~mask)) ); + stmt( IRStmt_Put( OFFB_CR1to7, binop(Iop_Or32, + mkexpr(src1to7_mskd), + mkexpr(cr1to7_mskd)) )); + } else { + // Assign lowest nibble of src to given field_idx of CR + assign( src_mskd, binop(Iop_And32, src, mkU32(0xF)) ); + assign( tmp, binop(Iop_Shl32, mkexpr(src_mskd), mkU8(bit_idx)) ); + + if (field_idx == 7) { + setFlags_CR0_Imm( mkexpr(tmp) ); + } else { + mask = 0xF << bit_idx; + assign( cr1to7_old, binop(Iop_And32, mkU32(-1>>4), getReg_CR()) ); + assign( cr1to7_mskd, binop(Iop_And32, + mkexpr(cr1to7_old), mkU32(~mask)) ); + stmt( IRStmt_Put( OFFB_CR1to7, binop(Iop_Or32, + mkexpr(tmp), + mkexpr(cr1to7_mskd)) )); + } + } +} + + + + + + + + /*------------------------------------------------------------*/ /*--- Misc Helpers ---*/ /*------------------------------------------------------------*/ @@ -917,6 +1033,7 @@ static Bool dis_int_arith ( UInt theInstr ) // li rD,val == addi rD,0,val // la disp(rA) == addi rD,rA,disp DIP("addi %d,%d,0x%x\n", Rd_addr, Ra_addr, SIMM_16); + if ( Ra_addr == 0 ) { assign( Rd, mkU32(EXTS_SIMM) ); } else { @@ -926,6 +1043,7 @@ static Bool dis_int_arith ( UInt theInstr ) case 0x0D: // addic (Add Immediate Carrying, p381) DIP("addic %d,%d,0x%x\n", Rd_addr, Ra_addr, SIMM_16); + assign( Rd, binop( Iop_Add32, mkexpr(Ra), mkU32(EXTS_SIMM) ) ); assign( tmp, mkU32(EXTS_SIMM) ); mk_ppc32g_set_xer_ca( PPC32G_FLAG_OP_ADD, Rd, Ra, tmp ); @@ -933,6 +1051,7 @@ static Bool dis_int_arith ( UInt theInstr ) case 0x0E: // addic. (Add Immediate Carrying and Record, p382) DIP("addic. %d,%d,0x%x\n", Rd_addr, Ra_addr, SIMM_16); + assign( Rd, binop( Iop_Add32, mkexpr(Ra), mkU32(EXTS_SIMM) ) ); assign( tmp, mkU32(EXTS_SIMM) ); mk_ppc32g_set_xer_ca( PPC32G_FLAG_OP_ADD, Rd, Ra, tmp ); @@ -942,6 +1061,7 @@ static Bool dis_int_arith ( UInt theInstr ) case 0x0F: // addis (Add Immediate Shifted, p383) // lis rD,val == addis rD,0,val DIP("addis %d,%d,0x%x\n", Rd_addr, Ra_addr, SIMM_16); + if ( Ra_addr == 0 ) { assign( Rd, mkU32(EXTS_SIMM << 16) ); } else { @@ -952,12 +1072,14 @@ static Bool dis_int_arith ( UInt theInstr ) case 0x07: // mulli (Multiply Low Immediate, p544) DIP("mulli %d,%d,0x%x\n", Rd_addr, Ra_addr, SIMM_16); + assign( res64, binop(Iop_MullS32, mkexpr(Ra), mkU32(EXTS_SIMM)) ); assign( Rd, unop(Iop_64to32, mkexpr(res64)) ); break; case 0x08: // subfic (Subtract from Immediate Carrying, p613) DIP("subfic %d,%d,0x%x\n", Rd_addr, Ra_addr, SIMM_16); + assign( Rd, binop(Iop_Add32, unop(Iop_Not32, mkexpr(Ra)), mkU32(EXTS_SIMM + 1)) ); assign( tmp, mkU32(EXTS_SIMM) ); @@ -972,6 +1094,7 @@ static Bool dis_int_arith ( UInt theInstr ) DIP("add%s%s %d,%d,%d\n", flag_OE ? "o" : "", flag_Rc ? "." : "", Rd_addr, Ra_addr, Rb_addr); + assign( Rd, binop(Iop_Add32, mkexpr(Ra), mkexpr(Rb)) ); if (flag_Rc) { setFlags_CR0_Result( mkexpr(Rd) ); } if (flag_OE) { @@ -983,7 +1106,9 @@ static Bool dis_int_arith ( UInt theInstr ) DIP("addc%s%s %d,%d,%d\n", flag_OE ? "o" : "", flag_Rc ? "." : "", Rd_addr, Ra_addr, Rb_addr); + assign( Rd, binop(Iop_Add32, mkexpr(Ra), mkexpr(Rb)) ); + if (flag_Rc) { setFlags_CR0_Result( mkexpr(Rd) ); } mk_ppc32g_set_xer_ca( PPC32G_FLAG_OP_ADD, Rd, Ra, Rb ); if (flag_OE) { @@ -995,11 +1120,10 @@ static Bool dis_int_arith ( UInt theInstr ) DIP("adde%s%s %d,%d,%d\n", flag_OE ? "o" : "", flag_Rc ? "." : "", Rd_addr, Ra_addr, Rb_addr); + // rD = rA + rB + XER[CA] - assign( tmp, IRExpr_Get(OFFB_XER_CA, Ity_I32) ); - assign( Rd, binop(Iop_Add32, - binop(Iop_Add32, mkexpr(Ra), mkexpr(Rb)), - mkexpr(tmp)) ); + assign( Rd, binop(Iop_Add32, mkexpr(Ra), + binop(Iop_Add32, getReg_XER_CA(), mkexpr(Rb))) ); if (flag_Rc) { setFlags_CR0_Result( mkexpr(Rd) ); } mk_ppc32g_set_xer_ca( PPC32G_FLAG_OP_ADDE, Rd, Ra, Rb ); @@ -1016,10 +1140,10 @@ static Bool dis_int_arith ( UInt theInstr ) DIP("addme%s%s %d,%d,%d\n", flag_OE ? "o" : "", flag_Rc ? "." : "", Rd_addr, Ra_addr, Rb_addr); + // rD = rA + XER[CA] - 1 - assign( Rd, binop(Iop_Add32, - widenUto32(IRExpr_Get(OFFB_XER_CA, Ity_I8)), - binop(Iop_Sub32, mkexpr(Ra), mkU32(1)) )); + assign( Rd, binop(Iop_Add32, mkexpr(Ra), + binop(Iop_Sub32, getReg_XER_CA(), mkU32(1)) )); if (flag_Rc) { setFlags_CR0_Result( mkexpr(Rd) ); } mk_ppc32g_set_xer_ca( PPC32G_FLAG_OP_ADDME, Rd, Ra, Rb ); @@ -1036,9 +1160,9 @@ static Bool dis_int_arith ( UInt theInstr ) DIP("addze%s%s %d,%d,%d\n", flag_OE ? "o" : "", flag_Rc ? "." : "", Rd_addr, Ra_addr, Rb_addr); + // rD = rA + XER[CA] - assign( Rd, binop(Iop_Add32, mkexpr(Ra), - widenUto32(IRExpr_Get(OFFB_XER_CA, Ity_I8)) )); + assign( Rd, binop(Iop_Add32, mkexpr(Ra), getReg_XER_CA()) ); if (flag_Rc) { setFlags_CR0_Result( mkexpr(Rd) ); } mk_ppc32g_set_xer_ca( PPC32G_FLAG_OP_ADDZE, Rd, Ra, Rb ); @@ -1051,7 +1175,9 @@ static Bool dis_int_arith ( UInt theInstr ) DIP("divw%s%s %d,%d,%d\n", flag_OE ? "o" : "", flag_Rc ? "." : "", Rd_addr, Ra_addr, Rb_addr); + assign( Rd, binop(Iop_DivS32, mkexpr(Ra), mkexpr(Rb)) ); + if (flag_Rc) { setFlags_CR0_Result( mkexpr(Rd) ); } if (flag_OE) { mk_ppc32g_set_xer_ov_so( PPC32G_FLAG_OP_DIVW, Rd, Ra, Rb ); @@ -1066,7 +1192,9 @@ static Bool dis_int_arith ( UInt theInstr ) DIP("divwu%s%s %d,%d,%d\n", flag_OE ? "o" : "", flag_Rc ? "." : "", Rd_addr, Ra_addr, Rb_addr); + assign( Rd, binop(Iop_DivU32, mkexpr(Ra), mkexpr(Rb)) ); + if (flag_Rc) { setFlags_CR0_Result( mkexpr(Rd) ); } if (flag_OE) { mk_ppc32g_set_xer_ov_so( PPC32G_FLAG_OP_DIVWU, Rd, Ra, Rb ); @@ -1081,6 +1209,7 @@ static Bool dis_int_arith ( UInt theInstr ) } DIP("mulhw%s %d,%d,%d\n", flag_Rc ? "." : "", Rd_addr, Ra_addr, Rb_addr); + assign( res64, binop(Iop_MullS32, mkexpr(Ra), mkexpr(Rb)) ); assign( Rd, unop(Iop_64HIto32, mkexpr(res64)) ); if (flag_Rc) { setFlags_CR0_Result( mkexpr(Rd) ); } @@ -1093,6 +1222,7 @@ static Bool dis_int_arith ( UInt theInstr ) } DIP("mulhwu%s %d,%d,%d\n", flag_Rc ? "." : "", Rd_addr, Ra_addr, Rb_addr); + assign( res64, binop(Iop_MullU32, mkexpr(Ra), mkexpr(Rb)) ); assign( Rd, unop(Iop_64HIto32, mkexpr(res64)) ); if (flag_Rc) { setFlags_CR0_Result( mkexpr(Rd) ); } @@ -1102,8 +1232,10 @@ static Bool dis_int_arith ( UInt theInstr ) DIP("mullw%s%s %d,%d,%d\n", flag_OE ? "o" : "", flag_Rc ? "." : "", Rd_addr, Ra_addr, Rb_addr); + assign( res64, binop(Iop_MullU32, mkexpr(Ra), mkexpr(Rb)) ); assign( Rd, unop(Iop_64to32, mkexpr(res64)) ); + if (flag_Rc) { setFlags_CR0_Result( mkexpr(Rd) ); } if (flag_OE) { mk_ppc32g_set_xer_ov_so( PPC32G_FLAG_OP_DIVWU, Rd, Ra, Rb ); @@ -1118,9 +1250,11 @@ static Bool dis_int_arith ( UInt theInstr ) DIP("neg%s%s %d,%d\n", flag_OE ? "o" : "", flag_Rc ? "." : "", Rd_addr, Ra_addr); + // rD = (log not)rA + 1 - assign( Rd, binop(Iop_Add32, mkU32(1), - unop(Iop_Not32, mkexpr(Ra))) ); + assign( Rd, binop(Iop_Add32, unop(Iop_Not32, mkexpr(Ra)), + mkU32(1)) ); + if (flag_OE) { mk_ppc32g_set_xer_ov_so( PPC32G_FLAG_OP_NEG, Rd, Ra, Rb ); } @@ -1131,10 +1265,11 @@ static Bool dis_int_arith ( UInt theInstr ) DIP("subf%s%s %d,%d,%d\n", flag_OE ? "o" : "", flag_Rc ? "." : "", Rd_addr, Ra_addr, Rb_addr); + // rD = (log not)rA + rB + 1 - assign( Rd, binop(Iop_Add32, - unop(Iop_Not32, mkexpr(Ra)), + assign( Rd, binop(Iop_Add32, unop(Iop_Not32, mkexpr(Ra)), binop(Iop_Add32, mkexpr(Rb), mkU32(1))) ); + if (flag_Rc) { setFlags_CR0_Result( mkexpr(Rd) ); } if (flag_OE) { mk_ppc32g_set_xer_ov_so( PPC32G_FLAG_OP_SUBF, Rd, Ra, Rb ); @@ -1145,10 +1280,11 @@ static Bool dis_int_arith ( UInt theInstr ) DIP("subfc%s%s %d,%d,%d\n", flag_OE ? "o" : "", flag_Rc ? "." : "", Rd_addr, Ra_addr, Rb_addr); + // rD = (log not)rA + rB + 1 - assign( Rd, binop(Iop_Add32, - unop(Iop_Not32, mkexpr(Ra)), + assign( Rd, binop(Iop_Add32, unop(Iop_Not32, mkexpr(Ra)), binop(Iop_Add32, mkexpr(Rb), mkU32(1))) ); + if (flag_Rc) { setFlags_CR0_Result( mkexpr(Rd) ); } mk_ppc32g_set_xer_ca( PPC32G_FLAG_OP_SUBFC, Rd, Ra, Rb ); if (flag_OE) { @@ -1160,11 +1296,11 @@ static Bool dis_int_arith ( UInt theInstr ) DIP("subfe%s%s %d,%d,%d\n", flag_OE ? "o" : "", flag_Rc ? "." : "", Rd_addr, Ra_addr, Rb_addr); + // rD = (log not)rA + rB + XER[CA] - assign( Rd, binop(Iop_Add32, - widenUto32(IRExpr_Get(OFFB_XER_CA, Ity_I8)), - binop(Iop_Add32, mkexpr(Rb), - unop(Iop_Not32, mkexpr(Ra)))) ); + assign( Rd, binop(Iop_Add32, unop(Iop_Not32, mkexpr(Ra)), + binop(Iop_Add32, mkexpr(Rb), getReg_XER_CA())) ); + if (flag_Rc) { setFlags_CR0_Result( mkexpr(Rd) ); } mk_ppc32g_set_xer_ca( PPC32G_FLAG_OP_SUBFE, Rd, Ra, Rb ); if (flag_OE) { @@ -1180,11 +1316,11 @@ static Bool dis_int_arith ( UInt theInstr ) DIP("subfme%s%s %d,%d\n", flag_OE ? "o" : "", flag_Rc ? "." : "", Rd_addr, Ra_addr); + // rD = (log not)rA + XER[CA] - 1 - assign( Rd, binop(Iop_Add32, - widenUto32(IRExpr_Get(OFFB_XER_CA, Ity_I8)), - binop(Iop_Add32, mkU32(-1), - unop(Iop_Not32, mkexpr(Ra)))) ); + assign( Rd, binop(Iop_Add32, unop(Iop_Not32, mkexpr(Ra)), + binop(Iop_Add32, getReg_XER_CA(), mkU32(-1))) ); + if (flag_Rc) { setFlags_CR0_Result( mkexpr(Rd) ); } mk_ppc32g_set_xer_ca( PPC32G_FLAG_OP_SUBFME, Rd, Ra, Rb ); if (flag_OE) { @@ -1200,9 +1336,11 @@ static Bool dis_int_arith ( UInt theInstr ) DIP("subfze%s%s %d,%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)), - widenUto32(IRExpr_Get(OFFB_XER_CA, Ity_I8))) ); + getReg_XER_CA()) ); + if (flag_Rc) { setFlags_CR0_Result( mkexpr(Rd) ); } mk_ppc32g_set_xer_ca( PPC32G_FLAG_OP_SUBFZE, Rd, Ra, Rb ); if (flag_OE) { @@ -1246,14 +1384,11 @@ static Bool dis_int_cmp ( UInt theInstr ) UInt EXTS_SIMM = 0; IRTemp Ra = newTemp(Ity_I32); IRTemp Rb = newTemp(Ity_I32); - IRTemp cr_flags = newTemp(Ity_I32); IRTemp tmp = newTemp(Ity_I32); - IRTemp xer_so = newTemp(Ity_I32); IRTemp tst1 = newTemp(Ity_I1); IRTemp tst2 = newTemp(Ity_I1); assign( Ra, getIReg(Ra_addr) ); - assign( xer_so, unop(Iop_8Uto32, IRExpr_Get(OFFB_XER_SO, Ity_I8)) ); if (flag_L==1) { // L==1 invalid for 32 bit. vex_printf("dis_int_cmp(PPC32)(flag_L)\n"); @@ -1268,7 +1403,6 @@ static Bool dis_int_cmp ( UInt theInstr ) switch (opc1) { case 0x0B: // cmpi (Compare Immediate, p398) DIP("cmpi %d,%d,%d,%d\n", crfD, flag_L, Ra_addr, SIMM_16); - EXTS_SIMM = extend_s_16to32(SIMM_16); assign( tst1, binop(Iop_CmpEQ32, mkU32(EXTS_SIMM), mkexpr(Ra)) ); assign( tst2, binop(Iop_CmpLT32S, mkU32(EXTS_SIMM), mkexpr(Ra)) ); @@ -1317,14 +1451,8 @@ static Bool dis_int_cmp ( UInt theInstr ) IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(tst2)), mkU32(8), mkU32(4) ), mkU32(2) )); - assign( cr_flags, binop(Iop_Or32, mkexpr(tmp), mkexpr(xer_so)) ); - if (crfD == 0) { - setFlags_CR0_Flags( binop(Iop_Shl32, mkexpr(cr_flags), mkU8(28)) ); - } else { - stmt( IRStmt_Put( OFFB_CR1to7, binop(Iop_Shl32, mkexpr(cr_flags), - mkU8(crfD * 4)) )); - } + putReg_CR( 7-crfD, binop(Iop_Or32, mkexpr(tmp), getReg_XER_SO()), 0 ); return True; } @@ -1409,6 +1537,7 @@ static Bool dis_int_logic ( UInt theInstr ) return False; } DIP("cntlzw%s %d,%d\n", flag_Rc ? "." : "", Ra_addr, Rs_addr); + // Iop_Clz32 undefined for arg==0, so deal with that case: assign(Ra, IRExpr_Mux0X( unop(Iop_1Uto8, binop(Iop_CmpNE32, @@ -2147,19 +2276,15 @@ static IRExpr* branch_cond_ok( UInt BO, UInt BI ) { IRTemp ok = newTemp(Ity_I1); IRTemp tmp = newTemp(Ity_I1); - IRTemp cr = newTemp(Ity_I32); + IRTemp cr_bi = newTemp(Ity_I32); if (BO >> 4) { assign( ok, mkU1(1) ); } else { - // ok = (CR[BI] == BO[3]) - if (BI < 4) { // Get from guest_CC_OP etc. - assign( cr, mk_ppc32g_calculate_cr0_all() ); - } else { // Get from guest_CR1to7 - assign( cr, IRExpr_Get(OFFB_CR1to7, Ity_I32) ); - } - assign( tmp, binop(Iop_CmpNE32, mkU32(0), - binop(Iop_And32, mkexpr(cr), mkU32(1<<(31-BI)))) ); + // ok = (CR[31-BI] == BO[3]) + assign( cr_bi, binop(Iop_And32, getReg_CR(), mkU32(1<<(31-BI))) ); + assign( tmp, binop(Iop_CmpNE32, mkU32(0), mkexpr(cr_bi)) ); + if ((BO >> 3) & 1) { assign( ok, mkexpr(tmp) ); } else { @@ -2378,9 +2503,6 @@ static Bool dis_memsync ( UInt theInstr ) IRTemp Ra = newTemp(Ity_I32); IRTemp Rb = newTemp(Ity_I32); IRTemp Rs = newTemp(Ity_I32); - IRTemp xer_ov = newTemp(Ity_I32); - IRTemp cr0_flags = newTemp(Ity_I32); - switch (opc1) { /* XL-Form */ @@ -2410,6 +2532,9 @@ static Bool dis_memsync ( UInt theInstr ) return False; case 0x014: // lwarx (Load Word and Reserve Indexed, p500) + /* Note: RESERVE, RESERVE_ADDR not implemented. + stwcx. is assumed to be always successful + */ if (b0 != 0) { vex_printf("dis_int_memsync(PPC32)(lwarx,b0)\n"); return False; @@ -2423,17 +2548,18 @@ static Bool dis_memsync ( UInt theInstr ) assign( EA, binop(Iop_And32, mkexpr(Ra), mkexpr(Rb)) ); } putIReg( Rd_addr, loadBE(Ity_I32, mkexpr(EA)) ); - /* Note: RESERVE, RESERVE_ADDR not implemented. - stwcx. is assumed to be successful - */ break; case 0x096: // stwcx. (Store Word Conditional Indexed, p605) + /* Note: RESERVE, RESERVE_ADDR not implemented. + stwcx. is assumed to be always successful + */ if (b0 != 1) { vex_printf("dis_int_memsync(PPC32)(stwcx.,b0)\n"); return False; } DIP("stwcx. %d,%d,%d\n", Rs_addr, Ra_addr, Rb_addr); + assign( Rb, getIReg(Rb_addr) ); assign( Rs, getIReg(Rs_addr) ); if (Ra_addr == 0) { @@ -2445,13 +2571,7 @@ static Bool dis_memsync ( UInt theInstr ) storeBE( mkexpr(EA), mkexpr(Rs) ); // Set CR0[LT GT EQ S0] = 0b001 || XER[SO] - assign( xer_ov, unop(Iop_8Uto32, IRExpr_Get(OFFB_XER_OV, Ity_I8)) ); - assign( cr0_flags, binop(Iop_And32, mkU32(2), mkexpr(xer_ov)) ); - setFlags_CR0_Flags( binop(Iop_Shl32, mkexpr(cr0_flags), mkU8(28)) ); - - /* Note: RESERVE, RESERVE_ADDR not implemented. - stwcx. is assumed to be successful - */ + putReg_CR( 7, binop(Iop_Or32, mkU32(2), getReg_XER_SO()), 0 ); break; case 0x256: // sync (Synchronize, p616) @@ -2500,7 +2620,6 @@ static Bool dis_int_shift ( UInt theInstr ) IRTemp Rs_out = newTemp(Ity_I32); IRTemp Ra = newTemp(Ity_I32); IRTemp Rb = newTemp(Ity_I32); - IRTemp xer_ca = newTemp(Ity_I8); IRTemp tmp = newTemp(Ity_I32); assign( Rs, getIReg(Rs_addr) ); @@ -2533,8 +2652,7 @@ static Bool dis_int_shift ( UInt theInstr ) // sign_rb = Rb[5] assign( sign_rb, binop(Iop_And32, mkexpr(Rb), mkU32(1<<5)) ); // sign = Rs[31] - assign( sign, binop(Iop_And32, mkU32(1), - binop(Iop_Shr32, mkexpr(Rs), mkU8(31))) ); + assign( sign, binop(Iop_Shr32, mkexpr(Rs), mkU8(31)) ); // sign_ext = sign==0 ? 0 : (sign_rb==0 ? -1 : (-1<<(31-shft_amt))) assign( tmp, IRExpr_Mux0X( unop(Iop_32to8, mkexpr(sign_rb)), mkU32(-1), @@ -2550,11 +2668,11 @@ static Bool dis_int_shift ( UInt theInstr ) putIReg( Ra_addr, mkexpr(Ra) ); // ca = sign & (Rs_out != 0) - assign( xer_ca, binop(Iop_And8, - unop(Iop_32to8, mkexpr(sign)), - unop(Iop_1Uto8, binop(Iop_CmpNE32, mkU32(0), - mkexpr(Rs_out)))) ); - stmt( IRStmt_Put( OFFB_XER_CA, mkexpr(xer_ca) ) ); + putReg_XER_CA( unop(Iop_32to1, + binop(Iop_And32, mkexpr(sign), + unop(Iop_1Uto32, + binop(Iop_CmpNE32, mkU32(0), + mkexpr(Rs_out))))) ); if (flag_Rc) { setFlags_CR0_Result( mkexpr(Ra) ); } break; @@ -2584,11 +2702,11 @@ static Bool dis_int_shift ( UInt theInstr ) putIReg( Ra_addr, mkexpr(Ra) ); // ca = sign & (Rs_out != 0) - assign( xer_ca, binop(Iop_And8, - unop(Iop_32to8, mkexpr(sign)), - unop(Iop_1Uto8, binop(Iop_CmpNE32, mkU32(0), - mkexpr(Rs_out)))) ); - stmt( IRStmt_Put( OFFB_XER_CA, mkexpr(xer_ca) ) ); + putReg_XER_CA( unop(Iop_32to1, + binop(Iop_And32, mkexpr(sign), + unop(Iop_1Uto32, + binop(Iop_CmpNE32, mkU32(0), + mkexpr(Rs_out))))) ); if (flag_Rc) { setFlags_CR0_Result( mkexpr(Ra) ); } break; @@ -2740,21 +2858,10 @@ static Bool dis_proc_ctl ( UInt theInstr ) UChar b0 = (theInstr >> 0) & 1; /* theInstr[0] */ UInt SPR_flipped = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F); - UChar bit_idx = (7-crfD) * 4; UInt mask; UChar i; IRTemp Rs = newTemp(Ity_I32); - IRTemp Rs_masked = newTemp(Ity_I32); - IRTemp cr = newTemp(Ity_I32); - IRTemp cr0 = newTemp(Ity_I32); - IRTemp cr1to7 = newTemp(Ity_I32); - IRTemp xer = newTemp(Ity_I32); - IRTemp xer_so = newTemp(Ity_I32); - IRTemp xer_ov = newTemp(Ity_I32); - IRTemp xer_ca = newTemp(Ity_I32); - IRTemp xer_bc = newTemp(Ity_I32); - assign( Rs, getIReg(Rs_addr) ); if (opc1 != 0x1F || b0 != 0) { @@ -2770,30 +2877,14 @@ static Bool dis_proc_ctl ( UInt theInstr ) return False; } DIP("mcrxr %d\n", crfD); - assign( xer_so, binop(Iop_Shl32, IRExpr_Get(OFFB_XER_SO, Ity_I8), - mkU8(3)) ); - assign( xer_ov, binop(Iop_Shl32, IRExpr_Get(OFFB_XER_OV, Ity_I8), - mkU8(2)) ); - assign( xer_ca, binop(Iop_Shl32, IRExpr_Get(OFFB_XER_CA, Ity_I8), - mkU8(1)) ); - assign( xer, binop(Iop_Or32, mkexpr(xer_so), - binop(Iop_Or32, mkexpr(xer_ov), mkexpr(xer_ca))) ); - if (crfD == 0) { // guest_CC_OP etc. - setFlags_CR0_Flags( binop(Iop_Shl32, mkexpr(xer), mkU8(28)) ); - } else { // guest_CR1to7 - mask = (0xF << bit_idx); - assign( cr1to7, binop(Iop_Or32, - binop(Iop_Shl32, mkexpr(xer), mkU8(bit_idx)), - binop(Iop_And32, mkU32(~mask), - IRExpr_Get(OFFB_CR1to7, Ity_I32))) ); - stmt( IRStmt_Put( OFFB_CR1to7, mkexpr(cr1to7) )); - } + // CR[7-crfD] = XER[0-3] + putReg_CR( 7-crfD, binop(Iop_Shr32, getReg_XER(), mkU8(28)), 0 ); // Clear XER[28 - 31] - stmt( IRStmt_Put( OFFB_XER_OV, mkU8(0) )); - stmt( IRStmt_Put( OFFB_XER_SO, mkU8(0) )); - stmt( IRStmt_Put( OFFB_XER_CA, mkU8(0) )); + putReg_XER_SO( mkU1(0) ); + putReg_XER_OV( mkU1(0) ); + putReg_XER_CA( mkU1(0) ); break; case 0x013: // mfcr (Move from Condition Register, p511) @@ -2802,11 +2893,7 @@ static Bool dis_proc_ctl ( UInt theInstr ) return False; } DIP("mfcr %d\n", Rd_addr); - assign( cr0, mk_ppc32g_calculate_cr0_all() ); - assign( cr1to7, IRExpr_Get(OFFB_CR1to7, Ity_I32) ); - assign( cr, binop(Iop_Or32, mkexpr(cr1to7), - binop(Iop_Shl32, mkexpr(cr0), mkU8(28))) ); - putIReg( Rd_addr, mkexpr(cr) ); + putIReg( Rd_addr, getReg_CR() ); break; /* XFX-Form */ @@ -2815,28 +2902,13 @@ static Bool dis_proc_ctl ( UInt theInstr ) switch (SPR_flipped) { // Choose a register... case 0x1: // XER - assign( xer_so, binop(Iop_Shl32, - IRExpr_Get(OFFB_XER_SO, Ity_I8), - mkU8(31)) ); - assign( xer_ov, binop(Iop_Shl32, - IRExpr_Get(OFFB_XER_OV, Ity_I8), - mkU8(30)) ); - assign( xer_ca, binop(Iop_Shl32, - IRExpr_Get(OFFB_XER_CA, Ity_I8), - mkU8(29)) ); - assign( xer_bc, unop(Iop_8Uto32, IRExpr_Get(OFFB_XER_BC, Ity_I8)) ); - assign( xer, binop(Iop_Or32, - binop(Iop_Or32, - mkexpr(xer_so), mkexpr(xer_ov)), - binop(Iop_Or32, - mkexpr(xer_ca), mkexpr(xer_bc))) ); - putIReg( Rd_addr, mkexpr(xer) ); + putIReg( Rd_addr, getReg_XER() ); break; case 0x8: // LR - putIReg( Rd_addr, IRExpr_Get(OFFB_LR, Ity_I32) ); + putIReg( Rd_addr, getReg_LR() ); break; case 0x9: // CTR - putIReg( Rd_addr, IRExpr_Get(OFFB_CTR, Ity_I32) ); + putIReg( Rd_addr, getReg_CTR() ); break; case 0x012: case 0x013: case 0x016: @@ -2874,19 +2946,7 @@ static Bool dis_proc_ctl ( UInt theInstr ) mask = mask | (0xF << (7-i)*4); } } - assign( Rs_masked, binop(Iop_And32, mkexpr(Rs), mkU32(mask)) ); - - if (CRM & 0x80) { // guest_CC_OP etc. - setFlags_CR0_Flags( binop(Iop_And32, - mkexpr(Rs_masked), mkU32(0xF0000000)) ); - } - // guest_CR1to7... - assign( cr1to7, - binop(Iop_Or32, - binop(Iop_And32, mkexpr(Rs_masked), mkU32(0x0FFFFFFF)), - binop(Iop_And32, IRExpr_Get(OFFB_CR1to7, Ity_I32), - mkU32(~mask))) ); - stmt( IRStmt_Put( OFFB_CR1to7, mkexpr(cr1to7) )); + putReg_CR( 8, binop(Iop_And32, mkexpr(Rs), mkU32(mask)), mask ); break; case 0x1D3: // mtspr (Move to Special-Purpose Register, p530) @@ -2894,28 +2954,13 @@ static Bool dis_proc_ctl ( UInt theInstr ) switch (SPR_flipped) { // Choose a register... case 0x1: // XER - assign( xer, mkexpr(Rs) ); - assign( xer_so, binop(Iop_Shr32, - binop(Iop_And32, mkexpr(xer), mkU32(0x80000000)), - mkU32(31)) ); - assign( xer_ov, binop(Iop_Shr32, - binop(Iop_And32, mkexpr(xer), mkU32(0x40000000)), - mkU32(30)) ); - assign( xer_ca, binop(Iop_Shr32, - binop(Iop_And32, mkexpr(xer), mkU32(0x20000000)), - mkU32(29)) ); - assign( xer_bc, binop(Iop_And32, mkexpr(xer), mkU32(0x0000007F)) ); - - stmt( IRStmt_Put( OFFB_XER_SO, mkexpr(xer_so)) ); - stmt( IRStmt_Put( OFFB_XER_OV, mkexpr(xer_ov)) ); - stmt( IRStmt_Put( OFFB_XER_CA, mkexpr(xer_ca)) ); - stmt( IRStmt_Put( OFFB_XER_BC, mkexpr(xer_bc)) ); + putReg_XER( mkexpr(Rs) ); break; case 0x8: // LR - stmt( IRStmt_Put( OFFB_LR, mkexpr(Rs)) ); + putReg_LR( mkexpr(Rs) ); break; case 0x9: // CTR - stmt( IRStmt_Put( OFFB_CTR, mkexpr(Rs)) ); + putReg_CTR( mkexpr(Rs) ); break; case 0x012: case 0x013: case 0x016: