|
From: <sv...@va...> - 2005-11-18 20:57:43
|
Author: cerion
Date: 2005-11-18 20:57:41 +0000 (Fri, 18 Nov 2005)
New Revision: 1465
Log:
Cleaned up access to 'special purpose' registers.
Added todo/limitations comments for AltiVec.
Modified:
trunk/priv/guest-ppc32/toIR.c
Modified: trunk/priv/guest-ppc32/toIR.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/priv/guest-ppc32/toIR.c 2005-11-18 20:45:51 UTC (rev 1464)
+++ trunk/priv/guest-ppc32/toIR.c 2005-11-18 20:57:41 UTC (rev 1465)
@@ -44,12 +44,15 @@
without prior written permission.
*/
=20
-/* TODO 2005 07 15:
+/* TODO 18/Nov/05:
=20
- Spot rlwini cases which are simply left/right shifts and
+ Spot rlwimi cases which are simply left/right shifts and
emit Shl32/Shr32 accordingly.
=20
- Move mtxer/mfxer code into its own function.
+ Altivec
+ - datastream insns
+ - lvxl,stvxl: load/store with 'least recently used' hint
+ - vexptefp, vlogefp
=20
LIMITATIONS:
=20
@@ -58,10 +61,20 @@
- Some invalid forms of lswi and lswx are accepted when they should
not be.
=20
- - All FP exceptions masked in FPSCR
+ - Floating Point:
+ - All exceptions disabled in FPSCR
+ - condition codes not set in FPSCR
+ - some error in accuracy
=20
- - FP condition codes not set in FPSCR
-
+ - 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.
*/
=20
=20
@@ -263,80 +276,32 @@
}
=20
=20
-//zz /*------------------------------------------------------------*/
-//zz /*--- Abstract register interface (non-gpr|fpr) --- */
-//zz /*------------------------------------------------------------*/
-//zz=20
-//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=20
-//zz #define SHIFT_CR_LT 8
-//zz #define SHIFT_CR_GT 4
-//zz #define SHIFT_CR_EQ 2
-//zz #define SHIFT_CR_SO 1
+/*------------------------------------------------------------*/
+/*--- Special purpose registers (SPRs) ---*/
+/*--- All non-GPR/FPRs, not only strict SPR's {XER,LR,CTR} ---*/
+/*------------------------------------------------------------*/
=20
-#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 (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;
=20
-//zz /*
-//zz Note on FPSCR: Floating Point Status and Control Register
-//zz=20
-//zz We're only keeping hold of fp rounding-mode bits, via guest_FPROU=
ND
-//zz The rest of the FPSCR is set to 0x0, which corresponds to
-//zz 'all exceptions masked'
-//zz =20
-//zz FPSCR[29:31] =3D> Exception Summaries
-//zz FPSCR[17:28] =3D> Exceptions
-//zz FPSCR[16] =3D> FPRF::Class Descriptor
-//zz FPSCR[12:15] =3D> FPRF::Condition Code
-//zz FPSCR[11] =3D> Unused (0)
-//zz FPSCR[8:10] =3D> Exceptions
-//zz FPSCR[3:7] =3D> Exception Control
-//zz FPSCR[2] =3D> Non-IEEE mode
-//zz FPSCR[0:1] =3D> Rounding Mode
-//zz=20
-//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=20
-//zz=20
-//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=20
-//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_i=
dx );
-//zz static void putReg_bit ( PPC32SPR reg, IRExpr* src, UInt bit_idx=
);
+#define MASK_FPSCR_RN 0x3
+#define MASK_VSCR_VALID 0x00010001
=20
-/* FP Helpers */
-static void put_emwarn ( IRExpr* e /* :: Ity_I32 */ );
=20
+/*------------------------------------------------------------*/
+/*--- FP Helpers ---*/
+/*------------------------------------------------------------*/
=20
+static void put_emwarn ( IRExpr* e /* :: Ity_I32 */ );
=20
=20
/*------------------------------------------------------------*/
@@ -905,39 +870,8 @@
case 7: return offsetof(VexGuestPPC32State, guest_CR7_0 );
default: vpanic("guestCR3offset(ppc32)");
}
-}=20
-
-static void putCR321 ( UInt cr, IRExpr* e )
-{
- vassert(cr < 8);
- vassert(typeOfIRExpr(irbb->tyenv, e) =3D=3D Ity_I8);
- stmt( IRStmt_Put(guestCR321offset(cr), e) );
}
=20
-static void putCR0 ( UInt cr, IRExpr* e )
-{
- vassert(cr < 8);
- vassert(typeOfIRExpr(irbb->tyenv, e) =3D=3D 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)
static IRExpr* ROTL32 ( IRExpr* src, IRExpr* rot_amt )
{
@@ -1004,28 +938,52 @@
0 .. 3 ....................... 28 .. 31 (IBM bit numbering)
31 28 3 0 (normal bit numbering)
=20
- Each CR field is 4 bits:
+ Each CR field is 4 bits: [<,>,=3D=3D,SO]
=20
- < > =3D=3D SO
+ Hence in IBM's notation, BI=3D0 is CR7[SO], BI=3D1 is CR7[=3D=3D], et=
c.
=20
- Hence in IBM's notation, BI=3D0 indicates CR7.SO, BI=3D1 is CR7.=3D=3D=
,
- etc.
-
Indexing from BI to guest state:
=20
let n =3D BI / 4
off =3D BI % 4
this references CR n:
=20
+ off=3D=3D0 -> guest_CRn_321 >> 3
+ off=3D=3D1 -> guest_CRn_321 >> 2
+ off=3D=3D2 -> guest_CRn_321 >> 1
off=3D=3D3 -> guest_CRn_SO
- off=3D=3D2 -> guest_CRn_123 >> 1
- off=3D=3D1 -> guest_CRn_123 >> 2
- off=3D=3D0 -> guest_CRn_123 >> 3
=20
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) =3D=3D Ity_I8);
+ stmt( IRStmt_Put(guestCR321offset(cr), e) );
+}
+
+static void putCR0 ( UInt cr, IRExpr* e )
+{
+ vassert(cr < 8);
+ vassert(typeOfIRExpr(irbb->tyenv, e) =3D=3D 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 @@
}
}
=20
-
/* 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 @@
}
}
=20
+/* 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) =3D=3D Ity_I32);
+ putCR321( 0, unop(Iop_32to8,
+ binop(Iop_CmpORD32S, result, mkU32(0))) );
+ putCR0( 0, getXER_SO() );
+}
=20
-/* Synthesise the entire CR into a single word. Expensive. */
=20
-static IRExpr* /* :: Ity_I32 */ getEntireCR ( void )
+/* Set the CR6 flags following an AltiVec compare operation. */
+static void set_AV_CR6 ( IRExpr* result, Bool test_all_ones )
{
-# 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))) \
- )
+ /* CR6[0:3] =3D {all_ones, 0, all_zeros, 0}
+ all_ones =3D (v[0] && v[1] && v[2] && v[3])
+ all_zeros =3D ~(v[0] || v[1] || v[2] || v[3])
+ */
+ IRTemp v0 =3D newTemp(Ity_V128);
+ IRTemp v1 =3D newTemp(Ity_V128);
+ IRTemp v2 =3D newTemp(Ity_V128);
+ IRTemp v3 =3D newTemp(Ity_V128);
+ IRTemp rOnes =3D newTemp(Ity_I8);
+ IRTemp rZeros =3D newTemp(Ity_I8);
=20
- 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
+ vassert(typeOfIRExpr(irbb->tyenv,result) =3D=3D 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) );
+}=20
+
+
+
+/*------------------------------------------------------------*/
+/*--- Helpers for XER flags. ---*/
+/*------------------------------------------------------------*/
+
+static void putXER_SO ( IRExpr* e )
+{
+ vassert(typeOfIRExpr(irbb->tyenv, e) =3D=3D Ity_I8);
+ stmt( IRStmt_Put(OFFB_XER_SO, binop(Iop_And8, mkU8(1), e)) );
}
=20
-static void putCRfields ( IRExpr* w32, UInt mask )
+static void putXER_OV ( IRExpr* e )
{
- IRTemp t;
- Int cr;
- vassert(typeOfIRExpr(irbb->tyenv,w32) =3D=3D Ity_I32);
- vassert(mask < 256);
- for (cr =3D 0; cr < 8; cr++) {
- if ((mask & (1 << (7-cr))) =3D=3D 0)
- continue;
- t =3D newTemp(Ity_I32);
- assign( t, binop(Iop_Shr32, w32, mkU8(toUChar(4*(7-cr)))) );
- putCR0( cr, unop(Iop_32to8,=20
- binop(Iop_And32, mkexpr(t), mkU32(1))) );
- putCR321( cr, unop(Iop_32to8,
- binop(Iop_And32, mkexpr(t), mkU32(7<<1))) );
- }
+ vassert(typeOfIRExpr(irbb->tyenv, e) =3D=3D Ity_I8);
+ stmt( IRStmt_Put(OFFB_XER_OV, binop(Iop_And8, mkU8(1), e)) );
}
=20
+static void putXER_CA ( IRExpr* e )
+{
+ vassert(typeOfIRExpr(irbb->tyenv, e) =3D=3D Ity_I8);
+ stmt( IRStmt_Put(OFFB_XER_CA, binop(Iop_And8, mkU8(1), e)) );
+}
=20
-/* Set the CR0 flags following an arithmetic operation.
- (Condition Register CR0 Field Definition, PPC32 p60)
-*/
-static void set_CR0 ( IRExpr* result )
+static void putXER_BC ( IRExpr* e )
{
- vassert(typeOfIRExpr(irbb->tyenv,result) =3D=3D Ity_I32);
- putCR321( 0, unop(Iop_32to8,
- binop(Iop_CmpORD32S, result, mkU32(0))) );
- putCR0( 0, getXER_SO() );
+ vassert(typeOfIRExpr(irbb->tyenv, e) =3D=3D Ity_I8);
+ stmt( IRStmt_Put(OFFB_XER_BC, binop(Iop_And8, mkU8(0x7F), e)) );
}
=20
+static IRExpr* /* :: Ity_I8 */ getXER_SO ( void )
+{
+ return IRExpr_Get( OFFB_XER_SO, Ity_I8 );
+}
=20
+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. */
=20
@@ -1276,11 +1302,7 @@
stmt( IRStmt_Put( OFFB_XER_OV, unop(Iop_32to8, xer_ov) ) );
=20
/* Update the summary overflow */
- stmt( IRStmt_Put(=20
- 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()) );
=20
# undef INT32_MIN
# undef AND3
@@ -1308,7 +1330,7 @@
=20
/* 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. */
=20
@@ -1410,73 +1432,17 @@
}
=20
/* xer_ca MUST denote either 0 or 1, no other value allowed */
- stmt( IRStmt_Put( OFFB_XER_CA, unop(Iop_32to8, xer_ca) ) );
+ putXER_CA( unop(Iop_32to8, xer_ca) );
}
=20
-static IRExpr* /* :: Ity_I32 */ get_XER_CA ( void )
-{
- return binop( Iop_And32,
- unop( Iop_8Uto32,=20
- IRExpr_Get(OFFB_XER_CA, Ity_I8) ),
- mkU32(1) );
-}
=20
=20
-
-/* Set the CR6 flags following an AltiVec compare operation. */
-static void set_AV_CR6 ( IRExpr* result, Bool test_all_ones )
-{
- /* CR6[0:3] =3D {all_ones, 0, all_zeros, 0}
- all_ones =3D (v[0] && v[1] && v[2] && v[3])
- all_zeros =3D ~(v[0] || v[1] || v[2] || v[3])
- */
- IRTemp v0 =3D newTemp(Ity_V128);
- IRTemp v1 =3D newTemp(Ity_V128);
- IRTemp v2 =3D newTemp(Ity_V128);
- IRTemp v3 =3D newTemp(Ity_V128);
- IRTemp rOnes =3D newTemp(Ity_I8);
- IRTemp rZeros =3D newTemp(Ity_I8);
-
- vassert(typeOfIRExpr(irbb->tyenv,result) =3D=3D 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) );
-}=20
-
-
-
/*------------------------------------------------------------*/
-/*--- Abstract register interface --- */
+/*--- SPR register interface --- */
/*------------------------------------------------------------*/
=20
/* 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 =3D newTemp(Ity_I32);
vassert( reg < PPC32_SPR_MAX );
@@ -1499,21 +1465,11 @@
} else {
assign( val, mkU32(0x0) );
}
- break; =20
+ break;
}
=20
-//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 =3D mask & 0x00010001;
- assign( val, IRExpr_Get(OFFB_VSCR, Ity_I32) );
- break;
-
default:
- vpanic("getReg(ppc32)");
+ vpanic("getSPR_masked(ppc32)");
}
=20
if (mask !=3D 0xFFFFFFFF) {
@@ -1523,60 +1479,96 @@
}
}
=20
-//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=20
-//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 =20
-//zz fld =3D getReg_masked( reg, (0xF << (field_idx*4)) );
-//zz =20
-//zz if (field_idx !=3D 0) {
-//zz fld =3D binop(Iop_Shr32, fld, mkU8(toUChar(field_idx * 4)));
-//zz }
-//zz return fld;
-//zz }
-//zz=20
-//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 =20
-//zz val =3D getReg_masked( reg, 1<<bit_idx );
-//zz=20
-//zz if (bit_idx !=3D 0) {
-//zz val =3D binop(Iop_Shr32, val, mkU8(toUChar(bit_idx)));
-//zz }
-//zz return val;
-//zz }
+/* Fetch the specified REG[FLD] nibble (as per IBM/hardware notation)
+ and return it at the bottom of an I32; the top 27 bits are
+ guaranteed to be zero. */
+static IRExpr* /* ::Ity_I32 */ getSPR_field ( PPC32SPR reg, UInt fld )
+{
+ vassert( fld < 8 );
+ vassert( reg < PPC32_SPR_MAX );
+ =20
+ UInt shft =3D 4*(7-fld);
+ UInt mask =3D 0xF<<shft;
=20
+ switch (reg) {
+ case PPC32_SPR_XER:
+ vassert(fld =3D=3D7);
+ return binop(Iop_Or32,
+ binop(Iop_Or32,
+ binop(Iop_Shl32, getXER_SO32(), mkU8(3)),
+ binop(Iop_Shl32, getXER_OV32(), mkU8(2))),
+ binop( Iop_Shl32, getXER_CA32(), mkU8(1)));
+ break;
=20
+ default:
+ if (shft =3D=3D 0)
+ return getSPR_masked( reg, mask );
+ else
+ return binop(Iop_Shr32,
+ getSPR_masked( reg, mask ),
+ mkU8(toUChar( shft )));
+ }
+}
=20
+static IRExpr* /* :: Ity_I32 */ getSPR ( PPC32SPR reg )
+{
+ switch (reg) {
+ case PPC32_SPR_LR:=20
+ return IRExpr_Get( OFFB_LR, Ity_I32 );
+ case PPC32_SPR_CTR:=20
+ return IRExpr_Get( OFFB_CTR, Ity_I32 );
+ case PPC32_SPR_VRSAVE:=20
+ return IRExpr_Get( OFFB_VRSAVE, Ity_I32 );
+ case PPC32_SPR_VSCR:
+ return binop(Iop_And32,
+ IRExpr_Get( OFFB_VSCR, Ity_I32 ),
+ mkU32(MASK_VSCR_VALID));
+ case PPC32_SPR_CR: {
+ /* Synthesise the entire CR into a single word. Expensive. */
+# 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
+ }
+ case PPC32_SPR_XER: {
+ return binop(Iop_Or32,
+ binop(Iop_Or32,
+ binop( Iop_Shl32, getXER_SO32(), mkU8(31)),
+ binop( Iop_Shl32, getXER_OV32(), mkU8(30))),
+ binop(Iop_Or32,
+ binop( Iop_Shl32, getXER_CA32(), mkU8(29)),
+ getXER_BC32()));
+ }
+ default:
+ vpanic("getSPR(ppc32)");
+ }
+}
+
/* Write masked src to the given reg */
-static void putReg_masked ( PPC32SPR reg, IRExpr* src, UInt mask )
+static void putSPR_masked ( PPC32SPR reg, IRExpr* src, UInt mask )
{
vassert( reg < PPC32_SPR_MAX );
vassert( typeOfIRExpr(irbb->tyenv,src ) =3D=3D Ity_I32 );
=20
switch (reg) {
-//zz case PPC32_SPR_CIA:
-//zz vassert(mask =3D=3D 0xFFFFFFFF); // Only ever need whole r=
eg
-//zz stmt( IRStmt_Put( OFFB_CIA, src ) );
-//zz break;
-
- case PPC32_SPR_FPSCR:
+ case PPC32_SPR_FPSCR: {
vassert((mask & 0x3) =3D=3D 0x3 || (mask & 0x3) =3D=3D 0x=
0);
vassert((mask & 0xF000) =3D=3D 0xF000 || (mask & 0xF000) =3D=3D 0x=
0);
/* all masks now refer to valid fields */
@@ -1587,8 +1579,7 @@
binop(Iop_And32, src, mkU32(0x3)) ));
}
=20
- /*
- Give EmWarn for attempted writes to:
+ /* Give EmWarn for attempted writes to:
- Exception Controls
- Non-IEEE Mode
*/
@@ -1608,42 +1599,47 @@
);
}
=20
- /*
- Ignore all other writes
- */
+ /* Ignore all other writes */
break;
+ }
=20
-//zz case PPC32_SPR_VRSAVE:
-//zz vassert(mask =3D=3D 0xFFFFFFFF); // Only ever need whole r=
eg
-//zz stmt( IRStmt_Put( OFFB_VRSAVE, src ) );
-//zz break;
+ default:
+ vex_printf("putSPR_masked(ppc32): %u", reg);
+ vpanic("putSPR_masked(ppc32)");
+ }
+}
=20
- 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 z=
ero?
+/* 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 ) =3D=3D Ity_I32 );
+ vassert( fld < 8 );
+ vassert( reg < PPC32_SPR_MAX );
+ =20
+ UInt shft =3D 4*(7-fld);
+ UInt mask =3D 0xF<<shft;
=20
- // All other bits are 'Reserved'. Ignoring writes to these bits.
- stmt( IRStmt_Put( OFFB_VSCR,
- binop(Iop_Or32,
- binop(Iop_And32, src, mkU32(mask & 0x00010001)),
- getReg_masked( PPC32_SPR_VSCR, (~mask & 0x00010001) ))));
+ switch (reg) {
+ case PPC32_SPR_CR:
+ putCR0 (fld, binop(Iop_And8, mkU8(1 ), unop(Iop_32to8, src)));
+ putCR321(fld, binop(Iop_And8, mkU8(7<<1), unop(Iop_32to8, src)));
break;
=20
default:
- vpanic("putReg(ppc32)");
+ if (shft =3D=3D 0) {
+ putSPR_masked( reg, src, mask );
+ } else {
+ putSPR_masked( reg,
+ binop(Iop_Shl32, src, mkU8(toUChar(shft))),
+ mask );
+ }
}
}
=20
-//zz /* Write src to the given reg */
-//zz static void putReg ( PPC32SPR reg, IRExpr* src )
-//zz {
-//zz vassert( typeOfIRExpr(irbb->tyenv,src ) =3D=3D 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 ) =3D=3D Ity_I32 );
switch (reg) {
case PPC32_SPR_CIA:=20
@@ -1659,57 +1655,24 @@
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)");
}
}
=20
-static IRExpr* /* :: Ity_I32 */ getSPR ( PPC32SPR reg )
-{
- switch (reg) {
- case PPC32_SPR_LR:=20
- return IRExpr_Get( OFFB_LR, Ity_I32 );
- case PPC32_SPR_CTR:=20
- return IRExpr_Get( OFFB_CTR, Ity_I32 );
- case PPC32_SPR_VRSAVE:=20
- return IRExpr_Get( OFFB_VRSAVE, Ity_I32 );
- case PPC32_SPR_VSCR:=20
- return getReg_masked( reg, 0xFFFFFFFF );
- default:
- vpanic("getSPR(ppc32)");
- }
-}
=20
=20
-/* 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 ) =3D=3D Ity_I32 );
- vassert( field_idx < 8 );
- vassert( reg < PPC32_SPR_MAX );
- =20
- if (field_idx !=3D 0) {
- src =3D binop(Iop_Shl32, src, mkU8(toUChar(field_idx * 4)));
- } =20
- 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 ) =3D=3D Ity_I32 );
- vassert( bit_idx < 32 );
- vassert( reg < PPC32_SPR_MAX );
- =20
- if (bit_idx !=3D 0) {
- src =3D binop(Iop_Shl32, src, mkU8(toUChar(bit_idx)));
- } =20
- putReg_masked( reg, src, (1<<bit_idx) );
-}
-
-
/*------------------------------------------------------------*/
/*--- Integer Instruction Translation --- */
/*------------------------------------------------------------*/
@@ -1833,7 +1796,7 @@
flag_OE ? "o" : "", flag_rC ? "." : "",
rD_addr, rA_addr, rB_addr);
// rD =3D rA + rB + XER[CA]
- assign( old_xer_ca, get_XER_CA() );
+ assign( old_xer_ca, getXER_CA32() );
assign( rD, binop(Iop_Add32, mkexpr(rA),
binop(Iop_Add32, mkexpr(rB), mkexpr(old_xer_c=
a))) );
set_XER_CA( PPC32G_FLAG_OP_ADDE,=20
@@ -1857,7 +1820,7 @@
rD_addr, rA_addr, rB_addr);
// rD =3D rA + (-1) + XER[CA]
// =3D> 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 @@
rD_addr, rA_addr, rB_addr);
// rD =3D rA + (0) + XER[CA]
// =3D> 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,=20
mkexpr(rD), mkexpr(rA), mkU32(0),=20
@@ -2004,7 +1967,7 @@
flag_OE ? "o" : "", flag_rC ? "." : "",
rD_addr, rA_addr, rB_addr);
// rD =3D (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_c=
a))) );
set_XER_CA( PPC32G_FLAG_OP_SUBFE,=20
@@ -2028,7 +1991,7 @@
rD_addr, rA_addr);
// rD =3D (log not)rA + (-1) + XER[CA]
// =3D> 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 @@
rD_addr, rA_addr);
// rD =3D (log not)rA + (0) + XER[CA]
// =3D> 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_c=
a)) );
set_XER_CA( PPC32G_FLAG_OP_SUBFE,
@@ -2461,10 +2424,10 @@
IRTemp EA_reg =3D newTemp(Ity_I32);
IRTemp rA =3D newTemp(Ity_I32);
IRTemp rB =3D newTemp(Ity_I32);
- =20
+
assign( rA, getIReg(rA_addr) );
assign( rB, getIReg(rB_addr) );
- =20
+
assign( rA_or_0, ea_rA_or_zero(rA_addr));
=20
assign( EA_imm, binop(Iop_Add32, mkexpr(rA_or_0), mkU32(d_simm16)) );
@@ -2631,7 +2594,7 @@
static Bool dis_int_store ( UInt theInstr )
{
/* D-Form, X-Form */
- UChar opc1 =3D ifieldOPC(theInstr);
+ UChar opc1 =3D ifieldOPC(theInstr);
UInt rS_addr =3D ifieldRegDS(theInstr);
UInt rA_addr =3D ifieldRegA(theInstr);
Int simm16 =3D ifieldSIMM16(theInstr);
@@ -2776,14 +2739,13 @@
UChar rS_addr =3D rD_addr;
UChar rA_addr =3D ifieldRegA(theInstr);
Int d_simm16 =3D ifieldSIMM16(theInstr);
- =20
+
UInt reg_idx =3D 0;
UInt offset =3D 0;
IRTemp rA =3D newTemp(Ity_I32);
IRTemp EA =3D newTemp(Ity_I32);
- =20
IRExpr* irx_addr;
- =20
+
if (rA_addr =3D=3D 0) {
assign( EA, binop(Iop_Add32, mkU32(0), mkU32(d_simm16)) );
} else {
@@ -2915,12 +2877,12 @@
UChar NumBytes =3D rB_addr;
UInt opc2 =3D ifieldOPClo10(theInstr);
UChar b0 =3D ifieldBIT0(theInstr);
- =20
+
IRTemp t_EA =3D newTemp(Ity_I32);
IRTemp t_nbytes =3D IRTemp_INVALID;
- =20
+
*stopHere =3D False;
- =20
+
if (opc1 !=3D 0x1F || b0 !=3D 0) {
vex_printf("dis_int_ldst_str(PPC32)(opc1)\n");
return False;
@@ -2960,8 +2922,7 @@
DIP("lswx r%d,r%d,r%d\n", rD_addr, rA_addr, rB_addr);
t_nbytes =3D newTemp(Ity_I32);
assign( t_EA, ea_standard(rA_addr,rB_addr) );
- assign( t_nbytes, unop( Iop_8Uto32,=20
- IRExpr_Get( OFFB_XER_BC, Ity_I8 )));
+ assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
generate_lsw_sequence( t_nbytes, t_EA, rD_addr,=20
128, guest_CIA_curr_instr+4 );
*stopHere =3D True;
@@ -2990,8 +2951,7 @@
DIP("stswx r%d,r%d,r%d\n", rS_addr, rA_addr, rB_addr);
t_nbytes =3D newTemp(Ity_I32);
assign( t_EA, ea_standard(rA_addr,rB_addr) );
- assign( t_nbytes, unop( Iop_8Uto32,=20
- IRExpr_Get( OFFB_XER_BC, Ity_I8 )));
+ assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
generate_stsw_sequence( t_nbytes, t_EA, rS_addr,=20
128, guest_CIA_curr_instr+4 );
*stopHere =3D True;
@@ -3379,7 +3339,7 @@
UChar rB_addr =3D ifieldRegB(theInstr);
UInt opc2 =3D ifieldOPClo10(theInstr);
UChar b0 =3D ifieldBIT0(theInstr);
- =20
+
IRTemp EA =3D newTemp(Ity_I32);
IRTemp rS =3D newTemp(Ity_I32);
=20
@@ -3449,9 +3409,7 @@
binop(Iop_CmpNE32, mkexpr(resaddr),
mkexpr(EA)),
Ijk_Boring,
- IRConst_U32(guest_CIA_curr_instr + 4)
- )
- );
+ IRConst_U32(guest_CIA_curr_instr + 4)) );
=20
/* Success? Do the store */
storeBE( mkexpr(EA), mkexpr(rS) );
@@ -3522,7 +3480,7 @@
& ~((y << 26) >>s 31) -- make result 0=20
for y in 32 .. 63
*/
- assign(rA,
+ assign( rA,
binop(
Iop_And32,
binop( Iop_Shl32,=20
@@ -3532,8 +3490,7 @@
unop( Iop_Not32,=20
binop( Iop_Sar32,=20
binop(Iop_Shl32, mkexpr(rB), mkU8(26)),=20
- mkU8(31))))
- );
+ mkU8(31)))) );
break;
=20
case 0x318: // sraw (Shift Right Algebraic Word, PPC32 p506)
@@ -3559,7 +3516,7 @@
);
set_XER_CA( PPC32G_FLAG_OP_SRAW,
mkexpr(rA), mkexpr(rS), mkexpr(sh_amt32),
- get_XER_CA() );
+ getXER_CA32() );
break;
=20
case 0x338: // srawi (Shift Right Algebraic Word Immediate, PPC32 =
p507)
@@ -3570,7 +3527,7 @@
assign( rA, binop(Iop_Sar32, mkexpr(rS), mkexpr(sh_amt)) );
set_XER_CA( PPC32G_FLAG_OP_SRAWI,=20
mkexpr(rA), mkexpr(rS), mkU32(sh_imm),=20
- get_XER_CA() );
+ getXER_CA32() );
break;
=20
case 0x218: // srw (Shift Right Word, PPC32 p508)
@@ -3582,7 +3539,7 @@
& ~((y << 26) >>s 31) -- make result 0=20
for y in 32 .. 63
*/
- assign(rA,
+ assign( rA,
binop(
Iop_And32,
binop( Iop_Shr32,=20
@@ -3592,8 +3549,7 @@
unop( Iop_Not32,=20
binop( Iop_Sar32,=20
binop(Iop_Shl32, mkexpr(rB), mkU8(26)),=20
- mkU8(31))))
- );
+ mkU8(31)))) );
break;
=20
default:
@@ -3645,11 +3601,11 @@
UChar rB_addr =3D ifieldRegB(theInstr);
UInt opc2 =3D ifieldOPClo10(theInstr);
UChar b0 =3D ifieldBIT0(theInstr);
- =20
- IRTemp EA =3D newTemp(Ity_I32);
- IRTemp w1 =3D newTemp(Ity_I32);
- IRTemp w2 =3D newTemp(Ity_I32);
=20
+ IRTemp EA =3D newTemp(Ity_I32);
+ IRTemp w1 =3D newTemp(Ity_I32);
+ IRTemp w2 =3D newTemp(Ity_I32);
+
if (opc1 !=3D 0x1F || b0 !=3D 0) {
vex_printf("dis_int_ldst_rev(PPC32)(opc1|b0)\n");
return False;
@@ -3724,7 +3680,7 @@
/* XFX-Form */
UChar rS_addr =3D rD_addr;
UInt SPR =3D b11to20;
- UInt TBR =3D SPR;
+ UInt TBR =3D b11to20;
UChar b20 =3D toUChar( IFIELD( theInstr, 20, 1 ) );
UInt CRM =3D IFIELD( theInstr, 12, 8 );
UChar b11 =3D toUChar( IFIELD( theInstr, 11, 1 ) );
@@ -3749,52 +3705,20 @@
switch (opc2) {
/* X-Form */
case 0x200: { // mcrxr (Move to Condition Register from XER, PPC32 p4=
66)
- IRTemp xer_0to3 =3D newTemp(Ity_I8);
if (b21to22 !=3D 0 || b11to20 !=3D 0) {
vex_printf("dis_proc_ctl(PPC32)(mcrxr,b21to22|b11to20)\n");
return False;
}
DIP("mcrxr crf%d\n", crfD);
+ /* 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 );
=20
- /* Compute XER[0-3] (the top 4 bits of XER) into the bottom
- 4 bits of xer_0to3. */
- assign(=20
- xer_0to3,
- unop(Iop_32to8,
- binop(
- Iop_Or32,
- binop(
- Iop_Or32,
- binop( Iop_Shl32,=20
- binop( Iop_And32,=20
- unop( Iop_8Uto32,=20
- IRExpr_Get( OFFB_XER_SO, Ity_I8 =
)),=20
- mkU32(1)),=20
- mkU8(31 -28)),
- binop( Iop_Shl32,=20
- binop( Iop_And32,=20
- unop( Iop_8Uto32,=20
- IRExpr_Get( OFFB_XER_OV, Ity_I8 =
)),=20
- mkU32(1)),=20
- mkU8(30 -28))
- ),
- binop( Iop_Shl32,=20
- binop( Iop_And32,=20
- unop( Iop_8Uto32,=20
- IRExpr_Get( OFFB_XER_CA, Ity_I8 )),=
=20
- mkU32(1)),=20
- mkU8(29 -28))
- )
- )
- );
-
- putCR321( crfD, binop(Iop_And8, mkexpr(xer_0to3), mkU8(7<<1)) );
- putCR0 ( crfD, binop(Iop_And8, mkexpr(xer_0to3), mkU8(1)) );
-
// 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;
}
=20
@@ -3804,7 +3728,7 @@
return False;
}
DIP("mfcr r%d\n", rD_addr);
- putIReg( rD_addr, getEntireCR() );
+ putIReg( rD_addr, getSPR( PPC32_SPR_CR ) );
break;
=20
/* XFX-Form */
@@ -3814,43 +3738,8 @@
=20
case 0x1:
DIP("mfxer r%d\n", rD_addr);
- /* sheesh [kebab] */
- putIReg(=20
- rD_addr,
- binop(
- Iop_Or32,
- binop(
- Iop_Or32,
- binop( Iop_Shl32,=20
- binop( Iop_And32,=20
- unop( Iop_8Uto32,=20
- IRExpr_Get( OFFB_XER_SO, Ity_I8=
)),=20
- mkU32(1)),=20
- mkU8(31)),
- binop( Iop_Shl32,=20
- binop( Iop_And32,=20
- unop( Iop_8Uto32,=20
- IRExpr_Get( OFFB_XER_OV, Ity_I8=
)),=20
- mkU32(1)),=20
- mkU8(30))
- ),
- binop(
- Iop_Or32,
- binop( Iop_Shl32,=20
- binop( Iop_And32,=20
- unop( Iop_8Uto32,=20
- IRExpr_Get( OFFB_XER_CA, Ity_I8=
)),=20
- mkU32(1)),=20
- mkU8(29)),
- binop( Iop_And32,=20
- unop( Iop_8Uto32,=20
- IRExpr_Get( OFFB_XER_BC, Ity_I8 )),=20
- mkU32(0xFF))
- )
- )
- );
+ putIReg( rD_addr, getSPR( PPC32_SPR_XER ) );=20
break;
-
case 0x8:
DIP("mflr r%d\n", rD_addr);
putIReg( rD_addr, getSPR( PPC32_SPR_LR ) );=20
@@ -3878,8 +3767,7 @@
return False;
=20
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 @@
break;
}
=20
- 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 !=3D 0 || b20 !=3D 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 =3D 0; cr < 8; cr++) {
+ if ((CRM & (1 << (7-cr))) =3D=3D 0)
+ continue;
+ shft =3D 4*(7-cr);
+ putSPR_field( PPC32_SPR_CR,
+ binop(Iop_Shr32, mkexpr(rS), mkU8(shft)), cr );
+ }
break;
+ }
=20
case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483)
=20
switch (SPR) { // Choose a register...
case 0x1:
DIP("mtxer r%d\n", rS_addr);
- stmt(IRStmt_Put(=20
- OFFB_XER_SO,=20
- unop( Iop_32to8,=20
- binop( Iop_And32,=20
- binop(Iop_Shr32, mkexpr(rS), mkU8(31)),=20
- mkU32(1)) )=20
- ));
- stmt(IRStmt_Put(=20
- OFFB_XER_OV,=20
- unop( Iop_32to8,=20
- binop( Iop_And32,=20
- binop(Iop_Shr32, mkexpr(rS), mkU8(30)),=20
- mkU32(1)) )=20
- ));
- stmt(IRStmt_Put(=20
- OFFB_XER_CA,=20
- unop( Iop_32to8,=20
- binop( Iop_And32,=20
- binop(Iop_Shr32, mkexpr(rS), mkU8(29)),=20
- mkU32(1)) )=20
- ));
- stmt(IRStmt_Put(=20
- OFFB_XER_BC,=20
- unop( Iop_32to8,=20
- binop( Iop_And32, mkexpr(rS), mkU32(0xFF)) )
- ));
+ putSPR( PPC32_SPR_XER, mkexpr(rS) );=20
break;
case 0x8:
DIP("mtlr r%d\n", rS_addr);
@@ -3965,23 +3838,9 @@
DIP("mtvrsave r%d\n", rS_addr);
putSPR( PPC32_SPR_VRSAVE, mkexpr(rS) );=20
break;
-//zz=20
-//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;
=20
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 @@
IRExpr* irx_addr;
UInt i;
DIP("dcbz r%d,r%d\n", rA_addr, rB_addr);
- assign( EA,
- binop( Iop_Add32,
- getIReg(rB_addr),=20
- rA_addr=3D=3D0 ? mkU32(0) : getIReg(rA_addr)) );
+ assign( EA, binop( Iop_Add32,
+ getIReg(rB_addr),=20
+ rA_addr=3D=3D0 ? mkU32(0) : getIReg(rA_addr)) )=
;
=20
/* 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) )) );
=20
for (i =3D 0; i < lineszB / 4; i++) {
irx_addr =3D binop( Iop_Add32, mkexpr(addr), mkU32(i*4) );
@@ -4137,7 +3994,7 @@
to -infinity | 11 | 01
*/
IRTemp rm_PPC32 =3D 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 ) );
=20
// rm_IR =3D XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
return binop(Iop_Xor32, mkexpr(rm_PPC32),
@@ -4293,8 +4150,8 @@
IRTemp rA_or_0 =3D newTemp(Ity_I32);
=20
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) );
=20
switch(opc1) {
@@ -4776,21 +4633,18 @@
binop(Iop_Shr32, mkexpr(ccIR), mkU8(6=
)))))))
);
=20
- putCR0( crfD, unop( Iop_32to8,=20
- binop(Iop_And32, mkexpr(ccPPC32), mkU32(1))) );
- putCR321( crfD, unop( Iop_32to8,=20
- binop(Iop_And32, mkexpr(ccPPC32), mkU32(7<<1)))=
);
+ putSPR_field( PPC32_SPR_CR, mkexpr(ccPPC32), crfD );
=20
- // 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 );
+ */
=20
- // 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 @@
assign( frB, getFReg(frB_addr));
=20
switch (opc2) {
-
case 0x00C: // frsp (Floating Round to Single, PPC32 p423)
DIP("frsp%s fr%d,fr%d\n", flag_rC ? "." : "", frD_addr, frB_add=
r);
assign( frD, roundToSgl( mkexpr(frB) ));
@@ -4883,7 +4736,6 @@
assign( frB, getFReg(frB_addr));
=20
switch (opc2) {
-
case 0x028: // fneg (Floating Negate, PPC32 p416)
DIP("fneg%s fr%d,fr%d\n", flag_rC ? "." : "", frD_addr, frB_add=
r);
assign( frD, unop( Iop_NegF64, mkexpr(frB) ));
@@ -4941,7 +4793,7 @@
//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-c=
rbD) );
//zz break;
//zz }
//zz=20
@@ -4958,8 +4810,8 @@
//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 }
=20
@@ -4973,7 +4825,7 @@
return False;
} =20
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;
}
=20
@@ -4988,7 +4840,7 @@
return False;
} =20
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;
}
=20
@@ -5003,7 +4855,7 @@
DIP("mffs%s fr%d\n", flag_rC ? "." : "", frD_addr);
putFReg( frD_addr, unop( Iop_ReinterpI64asF64,
unop( Iop_32Uto64,=20
- getReg_masked( PPC32_SPR_FPSCR, 0x3=
) )));
+ getSPR_masked( PPC32_SPR_FPSCR, 0x3=
) )));
break;
}
=20
@@ -5031,7 +4883,7 @@
mask |=3D 0xF << (7-i);
}
}
- putReg_masked( PPC32_SPR_FPSCR, mkexpr(rB_32), mask );
+ putSPR_masked( PPC32_SPR_FPSCR, mkexpr(rB_32), mask );
break;
}
=20
@@ -5272,8 +5124,8 @@
UInt opc2 =3D ifieldOPClo10(theInstr);
UChar b0 =3D ifieldBIT0(theInstr);
=20
- IRTemp vS =3D newTemp(Ity_V128);
- IRTemp EA =3D newTemp(Ity_I32);
+ IRTemp vS =3D newTemp(Ity_V128);
+ IRTemp EA =3D newTemp(Ity_I32);
IRTemp EA_aligned =3D newTemp(Ity_I32);
=20
assign( vS, getVReg(vS_addr));
|