From: Cerion Armour-Brown Date: Fri, 18 Nov 2005 20:57:41 +0000 (+0000) Subject: Cleaned up access to 'special purpose' registers. X-Git-Tag: svn/VALGRIND_3_1_1^2~26 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c83786cdb17afaa05481cff497c511381ebc44b0;p=thirdparty%2Fvalgrind.git Cleaned up access to 'special purpose' registers. Added todo/limitations comments for AltiVec. git-svn-id: svn://svn.valgrind.org/vex/trunk@1465 --- diff --git a/VEX/priv/guest-ppc32/toIR.c b/VEX/priv/guest-ppc32/toIR.c index 49ab2c4a4b..3354c7c5fd 100644 --- a/VEX/priv/guest-ppc32/toIR.c +++ b/VEX/priv/guest-ppc32/toIR.c @@ -44,12 +44,15 @@ without prior written permission. */ -/* TODO 2005 07 15: +/* TODO 18/Nov/05: - Spot rlwini cases which are simply left/right shifts and + Spot rlwimi cases which are simply left/right shifts and emit Shl32/Shr32 accordingly. - Move mtxer/mfxer code into its own function. + Altivec + - datastream insns + - lvxl,stvxl: load/store with 'least recently used' hint + - vexptefp, vlogefp LIMITATIONS: @@ -58,10 +61,20 @@ - Some invalid forms of lswi and lswx are accepted when they should not be. - - All FP exceptions masked in FPSCR - - - FP condition codes not set in FPSCR - + - Floating Point: + - All exceptions disabled in FPSCR + - condition codes not set in FPSCR + - some error in accuracy + + - Altivec floating point: + - vmaddfp, vnmsubfp + Because we're using Java/IEEE mode (FPSCR[NJ]), rather than the + system default of Non-Java mode, we get some small errors + (lowest bit only). + This is because Non-Java mode brutally hacks denormalised results + to zero, whereas we keep maximum accuracy. However, using + Non-Java mode would give us more inaccuracy, as our intermediate + results would then be zeroed, too. */ @@ -263,80 +276,32 @@ static Int ifieldSIMM26 ( UInt instr ) { } -//zz /*------------------------------------------------------------*/ -//zz /*--- Abstract register interface (non-gpr|fpr) --- */ -//zz /*------------------------------------------------------------*/ -//zz -//zz /* Offsets of bitfields within various ppc32 registers */ -//zz #define SHIFT_XER_SO 31 -//zz #define SHIFT_XER_OV 30 -//zz #define SHIFT_XER_CA 29 -//zz #define SHIFT_XER_BC 0 -//zz -//zz #define SHIFT_CR_LT 8 -//zz #define SHIFT_CR_GT 4 -//zz #define SHIFT_CR_EQ 2 -//zz #define SHIFT_CR_SO 1 - -#define SHIFT_FPSCR_RN 0 -#define MASK_FPSCR_RN (3 << SHIFT_FPSCR_RN) - -//zz #define SHIFT_VSCR_NJ 16 -//zz #define SHIFT_VSCR_SAT 0 - +/*------------------------------------------------------------*/ +/*--- Special purpose registers (SPRs) ---*/ +/*--- All non-GPR/FPRs, not only strict SPR's {XER,LR,CTR} ---*/ +/*------------------------------------------------------------*/ -// Special purpose (i.e. non-gpr/fpr) registers typedef enum { PPC32_SPR_CIA, // Current Instruction Address PPC32_SPR_LR, // Link Register PPC32_SPR_CTR, // Count Register -//zz PPC32_SPR_XER, // Summary Overflow -//zz PPC32_SPR_CR, // Condition Register + PPC32_SPR_XER, // Overflow, carry flags, byte count + PPC32_SPR_CR, // Condition Register PPC32_SPR_FPSCR, // Floating Point Status/Control Register PPC32_SPR_VRSAVE, // Vector Save/Restore Register PPC32_SPR_VSCR, // Vector Status and Control Register PPC32_SPR_MAX } PPC32SPR; -//zz /* -//zz Note on FPSCR: Floating Point Status and Control Register -//zz -//zz We're only keeping hold of fp rounding-mode bits, via guest_FPROUND -//zz The rest of the FPSCR is set to 0x0, which corresponds to -//zz 'all exceptions masked' -//zz -//zz FPSCR[29:31] => Exception Summaries -//zz FPSCR[17:28] => Exceptions -//zz FPSCR[16] => FPRF::Class Descriptor -//zz FPSCR[12:15] => FPRF::Condition Code -//zz FPSCR[11] => Unused (0) -//zz FPSCR[8:10] => Exceptions -//zz FPSCR[3:7] => Exception Control -//zz FPSCR[2] => Non-IEEE mode -//zz FPSCR[0:1] => Rounding Mode -//zz -//zz CAB: Perhaps necessary to record writes to FPRF ? -//zz Set by dis_fp_cmp() instrs, also some fp arith/round/conv instrs. -//zz Tested using dis_fp_scr(): e.g fpscr->cr, branch conditional... -//zz */ -//zz -//zz -//zz /* Gets from SPR (non-GPR|FPR) registers */ -//zz static IRExpr* getReg_masked ( PPC32SPR reg, UInt mask ); -static IRExpr* getSPR ( PPC32SPR reg ); -//zz static IRExpr* getReg_field ( PPC32SPR reg, UInt field_idx ); -//zz static IRExpr* getReg_bit ( PPC32SPR reg, UInt bit_idx ); -//zz -//zz /* Puts to SPR (non-GPR|FPR) registers */ -//zz static void putReg_masked ( PPC32SPR reg, IRExpr* src, UInt mask ); -static void putSPR ( PPC32SPR reg, IRExpr* src ); -//zz static void putReg_field ( PPC32SPR reg, IRExpr* src, UInt field_idx ); -//zz static void putReg_bit ( PPC32SPR reg, IRExpr* src, UInt bit_idx ); +#define MASK_FPSCR_RN 0x3 +#define MASK_VSCR_VALID 0x00010001 -/* FP Helpers */ -static void put_emwarn ( IRExpr* e /* :: Ity_I32 */ ); +/*------------------------------------------------------------*/ +/*--- FP Helpers ---*/ +/*------------------------------------------------------------*/ +static void put_emwarn ( IRExpr* e /* :: Ity_I32 */ ); /*------------------------------------------------------------*/ @@ -905,37 +870,6 @@ static Int guestCR0offset ( UInt cr ) case 7: return offsetof(VexGuestPPC32State, guest_CR7_0 ); default: vpanic("guestCR3offset(ppc32)"); } -} - -static void putCR321 ( UInt cr, IRExpr* e ) -{ - vassert(cr < 8); - vassert(typeOfIRExpr(irbb->tyenv, e) == Ity_I8); - stmt( IRStmt_Put(guestCR321offset(cr), e) ); -} - -static void putCR0 ( UInt cr, IRExpr* e ) -{ - vassert(cr < 8); - vassert(typeOfIRExpr(irbb->tyenv, e) == Ity_I8); - stmt( IRStmt_Put(guestCR0offset(cr), e) ); -} - -static IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr ) -{ - vassert(cr < 8); - return IRExpr_Get(guestCR0offset(cr), Ity_I8); -} - -static IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr ) -{ - vassert(cr < 8); - return IRExpr_Get(guestCR321offset(cr), Ity_I8); -} - -static IRExpr* /* :: Ity_I8 */ getXER_SO ( void ) -{ - return IRExpr_Get( OFFB_XER_SO, Ity_I8 ); } // ROTL(src32, rot_amt5) @@ -1004,12 +938,9 @@ static IRExpr* /* :: Ity_I32 */ ea_rA_or_zero ( Int rA ) 0 .. 3 ....................... 28 .. 31 (IBM bit numbering) 31 28 3 0 (normal bit numbering) - Each CR field is 4 bits: - - < > == SO + Each CR field is 4 bits: [<,>,==,SO] - Hence in IBM's notation, BI=0 indicates CR7.SO, BI=1 is CR7.==, - etc. + Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc. Indexing from BI to guest state: @@ -1017,15 +948,42 @@ static IRExpr* /* :: Ity_I32 */ ea_rA_or_zero ( Int rA ) off = BI % 4 this references CR n: + off==0 -> guest_CRn_321 >> 3 + off==1 -> guest_CRn_321 >> 2 + off==2 -> guest_CRn_321 >> 1 off==3 -> guest_CRn_SO - off==2 -> guest_CRn_123 >> 1 - off==1 -> guest_CRn_123 >> 2 - off==0 -> guest_CRn_123 >> 3 Bear in mind the only significant bit in guest_CRn_SO is bit 0 - (normal notation) and in guest_CRn_123 the significant bits are + (normal notation) and in guest_CRn_321 the significant bits are 3, 2 and 1 (normal notation). */ + +static void putCR321 ( UInt cr, IRExpr* e ) +{ + vassert(cr < 8); + vassert(typeOfIRExpr(irbb->tyenv, e) == Ity_I8); + stmt( IRStmt_Put(guestCR321offset(cr), e) ); +} + +static void putCR0 ( UInt cr, IRExpr* e ) +{ + vassert(cr < 8); + vassert(typeOfIRExpr(irbb->tyenv, e) == Ity_I8); + stmt( IRStmt_Put(guestCR0offset(cr), e) ); +} + +static IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr ) +{ + vassert(cr < 8); + return IRExpr_Get(guestCR0offset(cr), Ity_I8); +} + +static IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr ) +{ + vassert(cr < 8); + return IRExpr_Get(guestCR321offset(cr), Ity_I8); +} + /* Fetch the specified CR bit (as per IBM/hardware notation) and return it at the bottom of an I32; the top 31 bits are guaranteed to be zero. */ @@ -1081,7 +1039,6 @@ static void putCRbit ( UInt bi, IRExpr* bit ) } } - /* Fetch the specified CR bit (as per IBM/hardware notation) and return it somewhere in an I32; it does not matter where, but whichever bit it is, all other bits are guaranteed to be zero. In @@ -1109,66 +1066,135 @@ static IRExpr* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi, Int* where ) } } - -/* Synthesise the entire CR into a single word. Expensive. */ - -static IRExpr* /* :: Ity_I32 */ getEntireCR ( void ) -{ -# define FIELD(_n) \ - binop(Iop_Shl32, \ - unop(Iop_8Uto32, \ - binop(Iop_Or8, \ - binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \ - binop(Iop_And8, getCR0(_n), mkU8(1)) \ - ) \ - ), \ - mkU8(4 * (7-(_n))) \ - ) - - return binop(Iop_Or32, - binop(Iop_Or32, - binop(Iop_Or32, FIELD(0), FIELD(1)), - binop(Iop_Or32, FIELD(2), FIELD(3)) - ), - binop(Iop_Or32, - binop(Iop_Or32, FIELD(4), FIELD(5)), - binop(Iop_Or32, FIELD(6), FIELD(7)) - ) - ); -# undef FIELD -} - -static void putCRfields ( IRExpr* w32, UInt mask ) -{ - IRTemp t; - Int cr; - vassert(typeOfIRExpr(irbb->tyenv,w32) == Ity_I32); - vassert(mask < 256); - for (cr = 0; cr < 8; cr++) { - if ((mask & (1 << (7-cr))) == 0) - continue; - t = newTemp(Ity_I32); - assign( t, binop(Iop_Shr32, w32, mkU8(toUChar(4*(7-cr)))) ); - putCR0( cr, unop(Iop_32to8, - binop(Iop_And32, mkexpr(t), mkU32(1))) ); - putCR321( cr, unop(Iop_32to8, - binop(Iop_And32, mkexpr(t), mkU32(7<<1))) ); - } -} - - /* Set the CR0 flags following an arithmetic operation. (Condition Register CR0 Field Definition, PPC32 p60) */ +static IRExpr* getXER_SO ( void ); static void set_CR0 ( IRExpr* result ) { vassert(typeOfIRExpr(irbb->tyenv,result) == Ity_I32); putCR321( 0, unop(Iop_32to8, - binop(Iop_CmpORD32S, result, mkU32(0))) ); + binop(Iop_CmpORD32S, result, mkU32(0))) ); putCR0( 0, getXER_SO() ); } +/* Set the CR6 flags following an AltiVec compare operation. */ +static void set_AV_CR6 ( IRExpr* result, Bool test_all_ones ) +{ + /* CR6[0:3] = {all_ones, 0, all_zeros, 0} + all_ones = (v[0] && v[1] && v[2] && v[3]) + all_zeros = ~(v[0] || v[1] || v[2] || v[3]) + */ + IRTemp v0 = newTemp(Ity_V128); + IRTemp v1 = newTemp(Ity_V128); + IRTemp v2 = newTemp(Ity_V128); + IRTemp v3 = newTemp(Ity_V128); + IRTemp rOnes = newTemp(Ity_I8); + IRTemp rZeros = newTemp(Ity_I8); + + vassert(typeOfIRExpr(irbb->tyenv,result) == Ity_V128); + + assign( v0, result ); + assign( v1, binop(Iop_ShrV128, result, mkU8(32)) ); + assign( v2, binop(Iop_ShrV128, result, mkU8(64)) ); + assign( v3, binop(Iop_ShrV128, result, mkU8(96)) ); + + assign( rZeros, unop(Iop_1Uto8, + binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF), + unop(Iop_Not32, + unop(Iop_V128to32, + binop(Iop_OrV128, + binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)), + binop(Iop_OrV128, mkexpr(v2), mkexpr(v3)))) + ))) ); + + if (test_all_ones) { + assign( rOnes, unop(Iop_1Uto8, + binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF), + unop(Iop_V128to32, + binop(Iop_AndV128, + binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)), + binop(Iop_AndV128, mkexpr(v2), mkexpr(v3)))))) ); + putCR321( 6, binop(Iop_Or8, + binop(Iop_Shl8, mkexpr(rOnes), mkU8(3)), + binop(Iop_Shl8, mkexpr(rZeros), mkU8(1))) ); + } else { + putCR321( 6, binop(Iop_Shl8, mkexpr(rZeros), mkU8(1)) ); + } + putCR0( 6, mkU8(0) ); +} + + + +/*------------------------------------------------------------*/ +/*--- Helpers for XER flags. ---*/ +/*------------------------------------------------------------*/ + +static void putXER_SO ( IRExpr* e ) +{ + vassert(typeOfIRExpr(irbb->tyenv, e) == Ity_I8); + stmt( IRStmt_Put(OFFB_XER_SO, binop(Iop_And8, mkU8(1), e)) ); +} + +static void putXER_OV ( IRExpr* e ) +{ + vassert(typeOfIRExpr(irbb->tyenv, e) == Ity_I8); + stmt( IRStmt_Put(OFFB_XER_OV, binop(Iop_And8, mkU8(1), e)) ); +} + +static void putXER_CA ( IRExpr* e ) +{ + vassert(typeOfIRExpr(irbb->tyenv, e) == Ity_I8); + stmt( IRStmt_Put(OFFB_XER_CA, binop(Iop_And8, mkU8(1), e)) ); +} + +static void putXER_BC ( IRExpr* e ) +{ + vassert(typeOfIRExpr(irbb->tyenv, e) == Ity_I8); + stmt( IRStmt_Put(OFFB_XER_BC, binop(Iop_And8, mkU8(0x7F), e)) ); +} + +static IRExpr* /* :: Ity_I8 */ getXER_SO ( void ) +{ + return IRExpr_Get( OFFB_XER_SO, Ity_I8 ); +} + +static IRExpr* /* :: Ity_I32 */ getXER_SO32 ( void ) +{ + return binop( Iop_And32, unop(Iop_8Uto32, getXER_SO()), mkU32(1) ); +} + +static IRExpr* /* :: Ity_I8 */ getXER_OV ( void ) +{ + return IRExpr_Get( OFFB_XER_OV, Ity_I8 ); +} + +static IRExpr* /* :: Ity_I32 */ getXER_OV32 ( void ) +{ + return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV()), mkU32(1) ); +} + +static IRExpr* /* :: Ity_I32 */ getXER_CA32 ( void ) +{ + return binop( Iop_And32, + unop(Iop_8Uto32, IRExpr_Get( OFFB_XER_CA, Ity_I8 )), + mkU32(1) ); +} + +static IRExpr* /* :: Ity_I8 */ getXER_BC ( void ) +{ + return IRExpr_Get( OFFB_XER_BC, Ity_I8 ); +} + +static IRExpr* /* :: Ity_I32 */ getXER_BC32 ( void ) +{ + return binop( Iop_And32, + unop(Iop_8Uto32, IRExpr_Get( OFFB_XER_BC, Ity_I8 )), + mkU32(0x7F) ); +} + + /* RES is the result of doing OP on ARGL and ARGR. Set %XER.OV and %XER.SO accordingly. */ @@ -1276,11 +1302,7 @@ static void set_XER_OV( UInt op, IRExpr* res, stmt( IRStmt_Put( OFFB_XER_OV, unop(Iop_32to8, xer_ov) ) ); /* Update the summary overflow */ - stmt( IRStmt_Put( - OFFB_XER_SO, - binop(Iop_Or8, IRExpr_Get( OFFB_XER_SO, Ity_I8 ), - IRExpr_Get( OFFB_XER_OV, Ity_I8 ) ) - )); + putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) ); # undef INT32_MIN # undef AND3 @@ -1308,7 +1330,7 @@ static void set_XER_CA( UInt op, /* Incoming oldca is assumed to hold the values 0 or 1 only. This seems reasonable given that it's always generated by - get_XER_CA(), which masks it accordingly. In any case it being + getXER_CA32(), which masks it accordingly. In any case it being 0 or 1 is an invariant of the ppc32 guest state representation; if it has any other value, that invariant has been violated. */ @@ -1410,73 +1432,17 @@ static void set_XER_CA( UInt op, } /* xer_ca MUST denote either 0 or 1, no other value allowed */ - stmt( IRStmt_Put( OFFB_XER_CA, unop(Iop_32to8, xer_ca) ) ); -} - -static IRExpr* /* :: Ity_I32 */ get_XER_CA ( void ) -{ - return binop( Iop_And32, - unop( Iop_8Uto32, - IRExpr_Get(OFFB_XER_CA, Ity_I8) ), - mkU32(1) ); + putXER_CA( unop(Iop_32to8, xer_ca) ); } -/* Set the CR6 flags following an AltiVec compare operation. */ -static void set_AV_CR6 ( IRExpr* result, Bool test_all_ones ) -{ - /* CR6[0:3] = {all_ones, 0, all_zeros, 0} - all_ones = (v[0] && v[1] && v[2] && v[3]) - all_zeros = ~(v[0] || v[1] || v[2] || v[3]) - */ - IRTemp v0 = newTemp(Ity_V128); - IRTemp v1 = newTemp(Ity_V128); - IRTemp v2 = newTemp(Ity_V128); - IRTemp v3 = newTemp(Ity_V128); - IRTemp rOnes = newTemp(Ity_I8); - IRTemp rZeros = newTemp(Ity_I8); - - vassert(typeOfIRExpr(irbb->tyenv,result) == Ity_V128); - - assign( v0, result ); - assign( v1, binop(Iop_ShrV128, result, mkU8(32)) ); - assign( v2, binop(Iop_ShrV128, result, mkU8(64)) ); - assign( v3, binop(Iop_ShrV128, result, mkU8(96)) ); - - assign( rZeros, unop(Iop_1Uto8, - binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF), - unop(Iop_Not32, - unop(Iop_V128to32, - binop(Iop_OrV128, - binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)), - binop(Iop_OrV128, mkexpr(v2), mkexpr(v3)))) - ))) ); - - if (test_all_ones) { - assign( rOnes, unop(Iop_1Uto8, - binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF), - unop(Iop_V128to32, - binop(Iop_AndV128, - binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)), - binop(Iop_AndV128, mkexpr(v2), mkexpr(v3)))))) ); - putCR321( 6, binop(Iop_Or8, - binop(Iop_Shl8, mkexpr(rOnes), mkU8(3)), - binop(Iop_Shl8, mkexpr(rZeros), mkU8(1))) ); - } else { - putCR321( 6, binop(Iop_Shl8, mkexpr(rZeros), mkU8(1)) ); - } - putCR0( 6, mkU8(0) ); -} - - - /*------------------------------------------------------------*/ -/*--- Abstract register interface --- */ +/*--- SPR register interface --- */ /*------------------------------------------------------------*/ /* Get a masked word from the given reg */ -static IRExpr* getReg_masked ( PPC32SPR reg, UInt mask ) +static IRExpr* /* ::Ity_I32 */ getSPR_masked ( PPC32SPR reg, UInt mask ) { IRTemp val = newTemp(Ity_I32); vassert( reg < PPC32_SPR_MAX ); @@ -1499,21 +1465,11 @@ static IRExpr* getReg_masked ( PPC32SPR reg, UInt mask ) } else { assign( val, mkU32(0x0) ); } - break; - } - -//zz case PPC32_SPR_VRSAVE: -//zz assign( val, IRExpr_Get(OFFB_VRSAVE, Ity_I32) ); -//zz break; - - case PPC32_SPR_VSCR: - // All other bits are zero. - mask = mask & 0x00010001; - assign( val, IRExpr_Get(OFFB_VSCR, Ity_I32) ); break; + } default: - vpanic("getReg(ppc32)"); + vpanic("getSPR_masked(ppc32)"); } if (mask != 0xFFFFFFFF) { @@ -1523,60 +1479,96 @@ static IRExpr* getReg_masked ( PPC32SPR reg, UInt mask ) } } -//zz /* Get word from the given reg */ -//zz static IRExpr* getReg ( PPC32SPR reg ) -//zz { -//zz vassert( reg < PPC32_SPR_MAX ); -//zz return getReg_masked( reg, 0xFFFFFFFF ); -//zz } -//zz -//zz /* Get a right-shifted nibble from given reg[field_idx] -//zz returns zero padded word */ -//zz static IRExpr* getReg_field ( PPC32SPR reg, UInt field_idx ) -//zz { -//zz IRExpr* fld; -//zz vassert( field_idx < 8 ); -//zz vassert( reg < PPC32_SPR_MAX ); -//zz -//zz fld = getReg_masked( reg, (0xF << (field_idx*4)) ); -//zz -//zz if (field_idx != 0) { -//zz fld = binop(Iop_Shr32, fld, mkU8(toUChar(field_idx * 4))); -//zz } -//zz return fld; -//zz } -//zz -//zz /* Get a right-shifted bit from given reg[bit_idx] -//zz returns zero padded word */ -//zz static IRExpr* getReg_bit ( PPC32SPR reg, UInt bit_idx ) -//zz { -//zz IRExpr* val; -//zz vassert( bit_idx < 32 ); -//zz vassert( reg < PPC32_SPR_MAX ); -//zz -//zz val = getReg_masked( reg, 1<tyenv,src ) == Ity_I32 ); switch (reg) { -//zz case PPC32_SPR_CIA: -//zz vassert(mask == 0xFFFFFFFF); // Only ever need whole reg -//zz stmt( IRStmt_Put( OFFB_CIA, src ) ); -//zz break; - - case PPC32_SPR_FPSCR: + case PPC32_SPR_FPSCR: { vassert((mask & 0x3) == 0x3 || (mask & 0x3) == 0x0); vassert((mask & 0xF000) == 0xF000 || (mask & 0xF000) == 0x0); /* all masks now refer to valid fields */ @@ -1587,8 +1579,7 @@ static void putReg_masked ( PPC32SPR reg, IRExpr* src, UInt mask ) binop(Iop_And32, src, mkU32(0x3)) )); } - /* - Give EmWarn for attempted writes to: + /* Give EmWarn for attempted writes to: - Exception Controls - Non-IEEE Mode */ @@ -1608,42 +1599,47 @@ static void putReg_masked ( PPC32SPR reg, IRExpr* src, UInt mask ) ); } - /* - Ignore all other writes - */ + /* Ignore all other writes */ break; + } -//zz case PPC32_SPR_VRSAVE: -//zz vassert(mask == 0xFFFFFFFF); // Only ever need whole reg -//zz stmt( IRStmt_Put( OFFB_VRSAVE, src ) ); -//zz break; + default: + vex_printf("putSPR_masked(ppc32): %u", reg); + vpanic("putSPR_masked(ppc32)"); + } +} - case PPC32_SPR_VSCR: - // CAB: There are only 2 valid bits in VSCR - maybe split into two vars... - // ... or perhaps only 1 bit... is non-java mode bit ever set to zero? +/* Write the least significant nibble of src to the specified + REG[FLD] (as per IBM/hardware notation). */ +static void putSPR_field ( PPC32SPR reg, IRExpr* src, UInt fld ) +{ + vassert( typeOfIRExpr(irbb->tyenv,src ) == Ity_I32 ); + vassert( fld < 8 ); + vassert( reg < PPC32_SPR_MAX ); + + UInt shft = 4*(7-fld); + UInt mask = 0xF<tyenv,src ) == Ity_I32 ); -//zz vassert( reg < PPC32_SPR_MAX ); -//zz putReg_masked( reg, src, 0xFFFFFFFF ); -//zz } - static void putSPR ( PPC32SPR reg, IRExpr* src ) { + vassert( reg < PPC32_SPR_MAX ); vassert( typeOfIRExpr(irbb->tyenv,src ) == Ity_I32 ); switch (reg) { case PPC32_SPR_CIA: @@ -1659,56 +1655,23 @@ static void putSPR ( PPC32SPR reg, IRExpr* src ) stmt( IRStmt_Put( OFFB_VRSAVE, src ) ); break; case PPC32_SPR_VSCR: - putReg_masked( reg, src, 0xFFFFFFFF ); + stmt( IRStmt_Put( OFFB_VSCR, + binop(Iop_And32, src, + mkU32(MASK_VSCR_VALID)) ) ); + break; + case PPC32_SPR_XER: + putXER_SO( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(31))) ); + putXER_OV( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(30))) ); + putXER_CA( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(29))) ); + putXER_BC( unop(Iop_32to8, src) ); break; - default: - vpanic("putSPR(ppc32)"); - } -} -static IRExpr* /* :: Ity_I32 */ getSPR ( PPC32SPR reg ) -{ - switch (reg) { - case PPC32_SPR_LR: - return IRExpr_Get( OFFB_LR, Ity_I32 ); - case PPC32_SPR_CTR: - return IRExpr_Get( OFFB_CTR, Ity_I32 ); - case PPC32_SPR_VRSAVE: - return IRExpr_Get( OFFB_VRSAVE, Ity_I32 ); - case PPC32_SPR_VSCR: - return getReg_masked( reg, 0xFFFFFFFF ); default: - vpanic("getSPR(ppc32)"); + vpanic("putSPR(ppc32)"); } } -/* Write least-significant nibble of src to reg[field_idx] */ -static void putReg_field ( PPC32SPR reg, IRExpr* src, UInt field_idx ) -{ - vassert( typeOfIRExpr(irbb->tyenv,src ) == Ity_I32 ); - vassert( field_idx < 8 ); - vassert( reg < PPC32_SPR_MAX ); - - if (field_idx != 0) { - src = binop(Iop_Shl32, src, mkU8(toUChar(field_idx * 4))); - } - putReg_masked( reg, src, (0xF << (field_idx*4)) ); -} - -/* Write least-significant bit of src to reg[bit_idx] */ -static void putReg_bit ( PPC32SPR reg, IRExpr* src, UInt bit_idx ) -{ - vassert( typeOfIRExpr(irbb->tyenv,src ) == Ity_I32 ); - vassert( bit_idx < 32 ); - vassert( reg < PPC32_SPR_MAX ); - - if (bit_idx != 0) { - src = binop(Iop_Shl32, src, mkU8(toUChar(bit_idx))); - } - putReg_masked( reg, src, (1< Just another form of adde - assign( old_xer_ca, get_XER_CA() ); + assign( old_xer_ca, getXER_CA32() ); assign( rD, binop(Iop_Add32, mkexpr(rA), binop(Iop_Add32, mkU32(-1), mkexpr(old_xer_ca)) )); set_XER_CA( PPC32G_FLAG_OP_ADDE, @@ -1881,7 +1844,7 @@ static Bool dis_int_arith ( UInt theInstr ) rD_addr, rA_addr, rB_addr); // rD = rA + (0) + XER[CA] // => Just another form of adde - assign( old_xer_ca, get_XER_CA() ); + assign( old_xer_ca, getXER_CA32() ); assign( rD, binop(Iop_Add32, mkexpr(rA), mkexpr(old_xer_ca)) ); set_XER_CA( PPC32G_FLAG_OP_ADDE, mkexpr(rD), mkexpr(rA), mkU32(0), @@ -2004,7 +1967,7 @@ static Bool dis_int_arith ( UInt theInstr ) flag_OE ? "o" : "", flag_rC ? "." : "", rD_addr, rA_addr, rB_addr); // rD = (log not)rA + rB + XER[CA] - assign( old_xer_ca, get_XER_CA() ); + assign( old_xer_ca, getXER_CA32() ); assign( rD, binop(Iop_Add32, unop(Iop_Not32, mkexpr(rA)), binop(Iop_Add32, mkexpr(rB), mkexpr(old_xer_ca))) ); set_XER_CA( PPC32G_FLAG_OP_SUBFE, @@ -2028,7 +1991,7 @@ static Bool dis_int_arith ( UInt theInstr ) rD_addr, rA_addr); // rD = (log not)rA + (-1) + XER[CA] // => Just another form of subfe - assign( old_xer_ca, get_XER_CA() ); + assign( old_xer_ca, getXER_CA32() ); assign( rD, binop(Iop_Add32, unop(Iop_Not32, mkexpr(rA)), binop(Iop_Add32, mkU32(-1), mkexpr(old_xer_ca))) ); set_XER_CA( PPC32G_FLAG_OP_SUBFE, @@ -2052,7 +2015,7 @@ static Bool dis_int_arith ( UInt theInstr ) rD_addr, rA_addr); // rD = (log not)rA + (0) + XER[CA] // => Just another form of subfe - assign( old_xer_ca, get_XER_CA() ); + assign( old_xer_ca, getXER_CA32() ); assign( rD, binop(Iop_Add32, unop(Iop_Not32, mkexpr(rA)), mkexpr(old_xer_ca)) ); set_XER_CA( PPC32G_FLAG_OP_SUBFE, @@ -2461,10 +2424,10 @@ static Bool dis_int_load ( UInt theInstr ) IRTemp EA_reg = newTemp(Ity_I32); IRTemp rA = newTemp(Ity_I32); IRTemp rB = newTemp(Ity_I32); - + assign( rA, getIReg(rA_addr) ); assign( rB, getIReg(rB_addr) ); - + assign( rA_or_0, ea_rA_or_zero(rA_addr)); assign( EA_imm, binop(Iop_Add32, mkexpr(rA_or_0), mkU32(d_simm16)) ); @@ -2631,7 +2594,7 @@ static Bool dis_int_load ( UInt theInstr ) static Bool dis_int_store ( UInt theInstr ) { /* D-Form, X-Form */ - UChar opc1 = ifieldOPC(theInstr); + UChar opc1 = ifieldOPC(theInstr); UInt rS_addr = ifieldRegDS(theInstr); UInt rA_addr = ifieldRegA(theInstr); Int simm16 = ifieldSIMM16(theInstr); @@ -2776,14 +2739,13 @@ static Bool dis_int_ldst_mult ( UInt theInstr ) UChar rS_addr = rD_addr; UChar rA_addr = ifieldRegA(theInstr); Int d_simm16 = ifieldSIMM16(theInstr); - + UInt reg_idx = 0; UInt offset = 0; IRTemp rA = newTemp(Ity_I32); IRTemp EA = newTemp(Ity_I32); - IRExpr* irx_addr; - + if (rA_addr == 0) { assign( EA, binop(Iop_Add32, mkU32(0), mkU32(d_simm16)) ); } else { @@ -2915,12 +2877,12 @@ static Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere ) UChar NumBytes = rB_addr; UInt opc2 = ifieldOPClo10(theInstr); UChar b0 = ifieldBIT0(theInstr); - + IRTemp t_EA = newTemp(Ity_I32); IRTemp t_nbytes = IRTemp_INVALID; - + *stopHere = False; - + if (opc1 != 0x1F || b0 != 0) { vex_printf("dis_int_ldst_str(PPC32)(opc1)\n"); return False; @@ -2960,8 +2922,7 @@ static Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere ) DIP("lswx r%d,r%d,r%d\n", rD_addr, rA_addr, rB_addr); t_nbytes = newTemp(Ity_I32); assign( t_EA, ea_standard(rA_addr,rB_addr) ); - assign( t_nbytes, unop( Iop_8Uto32, - IRExpr_Get( OFFB_XER_BC, Ity_I8 ))); + assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) ); generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 128, guest_CIA_curr_instr+4 ); *stopHere = True; @@ -2990,8 +2951,7 @@ static Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere ) DIP("stswx r%d,r%d,r%d\n", rS_addr, rA_addr, rB_addr); t_nbytes = newTemp(Ity_I32); assign( t_EA, ea_standard(rA_addr,rB_addr) ); - assign( t_nbytes, unop( Iop_8Uto32, - IRExpr_Get( OFFB_XER_BC, Ity_I8 ))); + assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) ); generate_stsw_sequence( t_nbytes, t_EA, rS_addr, 128, guest_CIA_curr_instr+4 ); *stopHere = True; @@ -3379,7 +3339,7 @@ static Bool dis_memsync ( UInt theInstr ) UChar rB_addr = ifieldRegB(theInstr); UInt opc2 = ifieldOPClo10(theInstr); UChar b0 = ifieldBIT0(theInstr); - + IRTemp EA = newTemp(Ity_I32); IRTemp rS = newTemp(Ity_I32); @@ -3449,9 +3409,7 @@ static Bool dis_memsync ( UInt theInstr ) binop(Iop_CmpNE32, mkexpr(resaddr), mkexpr(EA)), Ijk_Boring, - IRConst_U32(guest_CIA_curr_instr + 4) - ) - ); + IRConst_U32(guest_CIA_curr_instr + 4)) ); /* Success? Do the store */ storeBE( mkexpr(EA), mkexpr(rS) ); @@ -3522,7 +3480,7 @@ static Bool dis_int_shift ( UInt theInstr ) & ~((y << 26) >>s 31) -- make result 0 for y in 32 .. 63 */ - assign(rA, + assign( rA, binop( Iop_And32, binop( Iop_Shl32, @@ -3532,8 +3490,7 @@ static Bool dis_int_shift ( UInt theInstr ) unop( Iop_Not32, binop( Iop_Sar32, binop(Iop_Shl32, mkexpr(rB), mkU8(26)), - mkU8(31)))) - ); + mkU8(31)))) ); break; case 0x318: // sraw (Shift Right Algebraic Word, PPC32 p506) @@ -3559,7 +3516,7 @@ static Bool dis_int_shift ( UInt theInstr ) ); set_XER_CA( PPC32G_FLAG_OP_SRAW, mkexpr(rA), mkexpr(rS), mkexpr(sh_amt32), - get_XER_CA() ); + getXER_CA32() ); break; case 0x338: // srawi (Shift Right Algebraic Word Immediate, PPC32 p507) @@ -3570,7 +3527,7 @@ static Bool dis_int_shift ( UInt theInstr ) assign( rA, binop(Iop_Sar32, mkexpr(rS), mkexpr(sh_amt)) ); set_XER_CA( PPC32G_FLAG_OP_SRAWI, mkexpr(rA), mkexpr(rS), mkU32(sh_imm), - get_XER_CA() ); + getXER_CA32() ); break; case 0x218: // srw (Shift Right Word, PPC32 p508) @@ -3582,7 +3539,7 @@ static Bool dis_int_shift ( UInt theInstr ) & ~((y << 26) >>s 31) -- make result 0 for y in 32 .. 63 */ - assign(rA, + assign( rA, binop( Iop_And32, binop( Iop_Shr32, @@ -3592,8 +3549,7 @@ static Bool dis_int_shift ( UInt theInstr ) unop( Iop_Not32, binop( Iop_Sar32, binop(Iop_Shl32, mkexpr(rB), mkU8(26)), - mkU8(31)))) - ); + mkU8(31)))) ); break; default: @@ -3645,10 +3601,10 @@ static Bool dis_int_ldst_rev ( UInt theInstr ) UChar rB_addr = ifieldRegB(theInstr); UInt opc2 = ifieldOPClo10(theInstr); UChar b0 = ifieldBIT0(theInstr); - - IRTemp EA = newTemp(Ity_I32); - IRTemp w1 = newTemp(Ity_I32); - IRTemp w2 = newTemp(Ity_I32); + + IRTemp EA = newTemp(Ity_I32); + IRTemp w1 = newTemp(Ity_I32); + IRTemp w2 = newTemp(Ity_I32); if (opc1 != 0x1F || b0 != 0) { vex_printf("dis_int_ldst_rev(PPC32)(opc1|b0)\n"); @@ -3724,7 +3680,7 @@ static Bool dis_proc_ctl ( UInt theInstr ) /* XFX-Form */ UChar rS_addr = rD_addr; UInt SPR = b11to20; - UInt TBR = SPR; + UInt TBR = b11to20; UChar b20 = toUChar( IFIELD( theInstr, 20, 1 ) ); UInt CRM = IFIELD( theInstr, 12, 8 ); UChar b11 = toUChar( IFIELD( theInstr, 11, 1 ) ); @@ -3749,52 +3705,20 @@ static Bool dis_proc_ctl ( UInt theInstr ) switch (opc2) { /* X-Form */ case 0x200: { // mcrxr (Move to Condition Register from XER, PPC32 p466) - IRTemp xer_0to3 = newTemp(Ity_I8); if (b21to22 != 0 || b11to20 != 0) { vex_printf("dis_proc_ctl(PPC32)(mcrxr,b21to22|b11to20)\n"); return False; } DIP("mcrxr crf%d\n", crfD); - - /* Compute XER[0-3] (the top 4 bits of XER) into the bottom - 4 bits of xer_0to3. */ - assign( - xer_0to3, - unop(Iop_32to8, - binop( - Iop_Or32, - binop( - Iop_Or32, - binop( Iop_Shl32, - binop( Iop_And32, - unop( Iop_8Uto32, - IRExpr_Get( OFFB_XER_SO, Ity_I8 )), - mkU32(1)), - mkU8(31 -28)), - binop( Iop_Shl32, - binop( Iop_And32, - unop( Iop_8Uto32, - IRExpr_Get( OFFB_XER_OV, Ity_I8 )), - mkU32(1)), - mkU8(30 -28)) - ), - binop( Iop_Shl32, - binop( Iop_And32, - unop( Iop_8Uto32, - IRExpr_Get( OFFB_XER_CA, Ity_I8 )), - mkU32(1)), - mkU8(29 -28)) - ) - ) - ); - - putCR321( crfD, binop(Iop_And8, mkexpr(xer_0to3), mkU8(7<<1)) ); - putCR0 ( crfD, binop(Iop_And8, mkexpr(xer_0to3), mkU8(1)) ); + /* Move XER[0-3] (the top 4 bits of XER) to CR[crfD] */ + putSPR_field( PPC32_SPR_CR, + getSPR_field( PPC32_SPR_XER, 7 ), + crfD ); // Clear XER[0-3] - stmt( IRStmt_Put( OFFB_XER_SO, mkU8(0) ) ); - stmt( IRStmt_Put( OFFB_XER_OV, mkU8(0) ) ); - stmt( IRStmt_Put( OFFB_XER_CA, mkU8(0) ) ); + putXER_SO( mkU8(0) ); + putXER_OV( mkU8(0) ); + putXER_CA( mkU8(0) ); break; } @@ -3804,7 +3728,7 @@ static Bool dis_proc_ctl ( UInt theInstr ) return False; } DIP("mfcr r%d\n", rD_addr); - putIReg( rD_addr, getEntireCR() ); + putIReg( rD_addr, getSPR( PPC32_SPR_CR ) ); break; /* XFX-Form */ @@ -3814,43 +3738,8 @@ static Bool dis_proc_ctl ( UInt theInstr ) case 0x1: DIP("mfxer r%d\n", rD_addr); - /* sheesh [kebab] */ - putIReg( - rD_addr, - binop( - Iop_Or32, - binop( - Iop_Or32, - binop( Iop_Shl32, - binop( Iop_And32, - unop( Iop_8Uto32, - IRExpr_Get( OFFB_XER_SO, Ity_I8 )), - mkU32(1)), - mkU8(31)), - binop( Iop_Shl32, - binop( Iop_And32, - unop( Iop_8Uto32, - IRExpr_Get( OFFB_XER_OV, Ity_I8 )), - mkU32(1)), - mkU8(30)) - ), - binop( - Iop_Or32, - binop( Iop_Shl32, - binop( Iop_And32, - unop( Iop_8Uto32, - IRExpr_Get( OFFB_XER_CA, Ity_I8 )), - mkU32(1)), - mkU8(29)), - binop( Iop_And32, - unop( Iop_8Uto32, - IRExpr_Get( OFFB_XER_BC, Ity_I8 )), - mkU32(0xFF)) - ) - ) - ); + putIReg( rD_addr, getSPR( PPC32_SPR_XER ) ); break; - case 0x8: DIP("mflr r%d\n", rD_addr); putIReg( rD_addr, getSPR( PPC32_SPR_LR ) ); @@ -3878,8 +3767,7 @@ static Bool dis_proc_ctl ( UInt theInstr ) return False; default: - vex_printf("dis_proc_ctl(PPC32)(mfspr,SPR)(0x%x)\n", - SPR); + vex_printf("dis_proc_ctl(PPC32)(mfspr,SPR)(0x%x)\n", SPR); return False; } break; @@ -3912,46 +3800,31 @@ static Bool dis_proc_ctl ( UInt theInstr ) break; } - case 0x090: // mtcrf (Move to Condition Register Fields, PPC32 p477) + case 0x090: { // mtcrf (Move to Condition Register Fields, PPC32 p477) + Int cr; + UChar shft; if (b11 != 0 || b20 != 0) { vex_printf("dis_proc_ctl(PPC32)(mtcrf,b11|b20)\n"); return False; } DIP("mtcrf 0x%x,r%d\n", CRM, rS_addr); - putCRfields ( mkexpr(rS), CRM ); + /* Write to each field specified by CRM */ + for (cr = 0; cr < 8; cr++) { + if ((CRM & (1 << (7-cr))) == 0) + continue; + shft = 4*(7-cr); + putSPR_field( PPC32_SPR_CR, + binop(Iop_Shr32, mkexpr(rS), mkU8(shft)), cr ); + } break; + } case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483) switch (SPR) { // Choose a register... case 0x1: DIP("mtxer r%d\n", rS_addr); - stmt(IRStmt_Put( - OFFB_XER_SO, - unop( Iop_32to8, - binop( Iop_And32, - binop(Iop_Shr32, mkexpr(rS), mkU8(31)), - mkU32(1)) ) - )); - stmt(IRStmt_Put( - OFFB_XER_OV, - unop( Iop_32to8, - binop( Iop_And32, - binop(Iop_Shr32, mkexpr(rS), mkU8(30)), - mkU32(1)) ) - )); - stmt(IRStmt_Put( - OFFB_XER_CA, - unop( Iop_32to8, - binop( Iop_And32, - binop(Iop_Shr32, mkexpr(rS), mkU8(29)), - mkU32(1)) ) - )); - stmt(IRStmt_Put( - OFFB_XER_BC, - unop( Iop_32to8, - binop( Iop_And32, mkexpr(rS), mkU32(0xFF)) ) - )); + putSPR( PPC32_SPR_XER, mkexpr(rS) ); break; case 0x8: DIP("mtlr r%d\n", rS_addr); @@ -3965,23 +3838,9 @@ static Bool dis_proc_ctl ( UInt theInstr ) DIP("mtvrsave r%d\n", rS_addr); putSPR( PPC32_SPR_VRSAVE, mkexpr(rS) ); break; -//zz -//zz case 0x012: case 0x013: case 0x016: -//zz case 0x019: case 0x01A: case 0x01B: -//zz case 0x110: case 0x111: case 0x112: case 0x113: -//zz // case 0x118: // 64bit only -//zz case 0x11A: case 0x11C: case 0x11D: -//zz case 0x210: case 0x211: case 0x212: case 0x213: -//zz case 0x214: case 0x215: case 0x216: case 0x217: -//zz case 0x218: case 0x219: case 0x21A: case 0x21B: -//zz case 0x21C: case 0x21D: case 0x21E: case 0x21F: -//zz case 0x3F5: -//zz vex_printf("dis_proc_ctl(PPC32)(mtspr) - supervisor level op\n"); -//zz return False; default: - vex_printf("dis_proc_ctl(PPC32)(mtspr,SPR)(%u)\n", - SPR); + vex_printf("dis_proc_ctl(PPC32)(mtspr,SPR)(%u)\n", SPR); return False; } break; @@ -4053,16 +3912,14 @@ static Bool dis_cache_manage ( UInt theInstr, IRExpr* irx_addr; UInt i; DIP("dcbz r%d,r%d\n", rA_addr, rB_addr); - assign( EA, - binop( Iop_Add32, - getIReg(rB_addr), - rA_addr==0 ? mkU32(0) : getIReg(rA_addr)) ); + assign( EA, binop( Iop_Add32, + getIReg(rB_addr), + rA_addr==0 ? mkU32(0) : getIReg(rA_addr)) ); /* Round EA down to the start of the containing block. */ - assign( addr, - binop( Iop_And32, - mkexpr(EA), - mkU32( ~(lineszB-1) )) ); + assign( addr, binop( Iop_And32, + mkexpr(EA), + mkU32( ~(lineszB-1) )) ); for (i = 0; i < lineszB / 4; i++) { irx_addr = binop( Iop_Add32, mkexpr(addr), mkU32(i*4) ); @@ -4137,7 +3994,7 @@ static IRExpr* /* :: Ity_I32 */ get_roundingmode ( void ) to -infinity | 11 | 01 */ IRTemp rm_PPC32 = newTemp(Ity_I32); - assign( rm_PPC32, getReg_masked( PPC32_SPR_FPSCR, MASK_FPSCR_RN ) ); + assign( rm_PPC32, getSPR_masked( PPC32_SPR_FPSCR, MASK_FPSCR_RN ) ); // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2) return binop(Iop_Xor32, mkexpr(rm_PPC32), @@ -4293,8 +4150,8 @@ static Bool dis_fp_store ( UInt theInstr ) IRTemp rA_or_0 = newTemp(Ity_I32); assign( frS, getFReg(frS_addr) ); - assign( rA, getIReg(rA_addr) ); - assign( rB, getIReg(rB_addr) ); + assign( rA, getIReg(rA_addr) ); + assign( rB, getIReg(rB_addr) ); assign( rA_or_0, ea_rA_or_zero(rA_addr) ); switch(opc1) { @@ -4776,21 +4633,18 @@ static Bool dis_fp_cmp ( UInt theInstr ) binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))))))) ); - putCR0( crfD, unop( Iop_32to8, - binop(Iop_And32, mkexpr(ccPPC32), mkU32(1))) ); - putCR321( crfD, unop( Iop_32to8, - binop(Iop_And32, mkexpr(ccPPC32), mkU32(7<<1))) ); + putSPR_field( PPC32_SPR_CR, mkexpr(ccPPC32), crfD ); - // CAB: Useful to support writing cc to FPSCR->FPCC ? - // putReg_field( PPC32_SPR_FPSCR, mkexpr(ccPPC32), 3 ); + /* CAB: TODO?: Support writing cc to FPSCR->FPCC ? + putSPR_field( PPC32_SPR_FPSCR, mkexpr(ccPPC32), 4 ); + */ - // Note: Differences between fcmpu and fcmpo are only - // in exception flag settings, which aren't supported anyway... + /* Note: Differences between fcmpu and fcmpo are only in exception + flag settings, which aren't supported anyway. */ switch (opc2) { case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403) DIP("fcmpu crf%d,fr%d,fr%d\n", crfD, frA_addr, frB_addr); break; - case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402) DIP("fcmpo crf%d,fr%d,fr%d\n", crfD, frA_addr, frB_addr); break; @@ -4828,7 +4682,6 @@ static Bool dis_fp_round ( UInt theInstr ) assign( frB, getFReg(frB_addr)); switch (opc2) { - case 0x00C: // frsp (Floating Round to Single, PPC32 p423) DIP("frsp%s fr%d,fr%d\n", flag_rC ? "." : "", frD_addr, frB_addr); assign( frD, roundToSgl( mkexpr(frB) )); @@ -4883,7 +4736,6 @@ static Bool dis_fp_move ( UInt theInstr ) assign( frB, getFReg(frB_addr)); switch (opc2) { - case 0x028: // fneg (Floating Negate, PPC32 p416) DIP("fneg%s fr%d,fr%d\n", flag_rC ? "." : "", frD_addr, frB_addr); assign( frD, unop( Iop_NegF64, mkexpr(frB) )); @@ -4941,7 +4793,7 @@ static Bool dis_fp_scr ( UInt theInstr ) //zz return False; //zz } //zz DIP("mtfsb1%s crb%d \n", flag_rC ? "." : "", crbD); -//zz putReg_bit( PPC32_SPR_FPSCR, mkU32(1), 31-crbD ); +//zz putSPR_masked( PPC32_SPR_FPSCR, mkU32(1<<(31-crbD)), 1<<(31-crbD) ); //zz break; //zz } //zz @@ -4958,8 +4810,8 @@ static Bool dis_fp_scr ( UInt theInstr ) //zz return False; //zz } //zz DIP("mcrfs crf%d,crf%d\n", crfD, crfS); -//zz assign( tmp, getReg_field( PPC32_SPR_FPSCR, 7-crfS ) ); -//zz putReg_field( PPC32_SPR_CR, mkexpr(tmp), 7-crfD ); +//zz assign( tmp, getSPR_field( PPC32_SPR_FPSCR, crfS ) ); +//zz putSPR_field( PPC32_SPR_CR, mkexpr(tmp), crfD ); //zz break; //zz } @@ -4973,7 +4825,7 @@ static Bool dis_fp_scr ( UInt theInstr ) return False; } DIP("mtfsb0%s crb%d\n", flag_rC ? "." : "", crbD); - putReg_bit( PPC32_SPR_FPSCR, mkU32(0), 31-crbD ); + putSPR_masked( PPC32_SPR_FPSCR, mkU32(0), 1<<(31-crbD) ); break; } @@ -4988,7 +4840,7 @@ static Bool dis_fp_scr ( UInt theInstr ) return False; } DIP("mtfsfi%s crf%d,%d\n", flag_rC ? "." : "", crfD, IMM); - putReg_field( PPC32_SPR_FPSCR, mkU32(IMM), 7-crfD ); + putSPR_field( PPC32_SPR_FPSCR, mkU32(IMM), crfD ); break; } @@ -5003,7 +4855,7 @@ static Bool dis_fp_scr ( UInt theInstr ) DIP("mffs%s fr%d\n", flag_rC ? "." : "", frD_addr); putFReg( frD_addr, unop( Iop_ReinterpI64asF64, unop( Iop_32Uto64, - getReg_masked( PPC32_SPR_FPSCR, 0x3 ) ))); + getSPR_masked( PPC32_SPR_FPSCR, 0x3 ) ))); break; } @@ -5031,7 +4883,7 @@ static Bool dis_fp_scr ( UInt theInstr ) mask |= 0xF << (7-i); } } - putReg_masked( PPC32_SPR_FPSCR, mkexpr(rB_32), mask ); + putSPR_masked( PPC32_SPR_FPSCR, mkexpr(rB_32), mask ); break; } @@ -5272,8 +5124,8 @@ static Bool dis_av_store ( UInt theInstr ) UInt opc2 = ifieldOPClo10(theInstr); UChar b0 = ifieldBIT0(theInstr); - IRTemp vS = newTemp(Ity_V128); - IRTemp EA = newTemp(Ity_I32); + IRTemp vS = newTemp(Ity_V128); + IRTemp EA = newTemp(Ity_I32); IRTemp EA_aligned = newTemp(Ity_I32); assign( vS, getVReg(vS_addr));