|
From: <sv...@va...> - 2005-07-21 14:48:48
|
Author: sewardj
Date: 2005-07-21 15:48:31 +0100 (Thu, 21 Jul 2005)
New Revision: 1285
Log:
Do all ppc32 flag calculations in-line, partly for performance reasons
and partly to try and avoid confusing memcheck so much.
Modified:
trunk/priv/guest-ppc32/gdefs.h
trunk/priv/guest-ppc32/toIR.c
trunk/priv/host-ppc32/isel.c
Modified: trunk/priv/guest-ppc32/gdefs.h
=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/gdefs.h 2005-07-21 10:07:13 UTC (rev 1284)
+++ trunk/priv/guest-ppc32/gdefs.h 2005-07-21 14:48:31 UTC (rev 1285)
@@ -111,19 +111,18 @@
Enumeration for xer_ca/ov calculation helper functions
*/
enum {
- PPC32G_FLAG_OP_ADD=3D0, // addc[o], addic
- PPC32G_FLAG_OP_ADDE, // adde[o], addme[o], addze[o]
- PPC32G_FLAG_OP_DIVW, // divwo
- PPC32G_FLAG_OP_DIVWU, // divwuo
- PPC32G_FLAG_OP_MULLW, // mullwo
- PPC32G_FLAG_OP_NEG, // nego
- PPC32G_FLAG_OP_SUBF, // subfo
- PPC32G_FLAG_OP_SUBFC, // subfc[o]
- PPC32G_FLAG_OP_SUBFE, // subfe[o], subfme[o], subfze[o]
- PPC32G_FLAG_OP_SUBFI, // subfic
- PPC32G_FLAG_OP_SRAW, // sraw
- PPC32G_FLAG_OP_SRAWI, // srawi
- =20
+ /* 0 */ PPC32G_FLAG_OP_ADD=3D0, // addc[o], addic
+ /* 1 */ PPC32G_FLAG_OP_ADDE, // adde[o], addme[o], addze[o]
+ /* 2 */ PPC32G_FLAG_OP_DIVW, // divwo
+ /* 3 */ PPC32G_FLAG_OP_DIVWU, // divwuo
+ /* 4 */ PPC32G_FLAG_OP_MULLW, // mullwo
+ /* 5 */ PPC32G_FLAG_OP_NEG, // nego
+ /* 6 */ PPC32G_FLAG_OP_SUBF, // subfo
+ /* 7 */ PPC32G_FLAG_OP_SUBFC, // subfc[o]
+ /* 8 */ PPC32G_FLAG_OP_SUBFE, // subfe[o], subfme[o], subfze[o]
+ /* 9 */ PPC32G_FLAG_OP_SUBFI, // subfic
+ /* 10 */ PPC32G_FLAG_OP_SRAW, // sraw
+ /* 11 */ PPC32G_FLAG_OP_SRAWI, // srawi
PPC32G_FLAG_OP_NUMBER
};
=20
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-07-21 10:07:13 UTC (rev 1284)
+++ trunk/priv/guest-ppc32/toIR.c 2005-07-21 14:48:31 UTC (rev 1285)
@@ -127,7 +127,9 @@
#define OFFB_CTR offsetof(VexGuestPPC32State,guest_CTR)
=20
#define OFFB_XER_SO offsetof(VexGuestPPC32State,guest_XER_SO)
+#define OFFB_XER_OV offsetof(VexGuestPPC32State,guest_XER_OV)
#define OFFB_XER_CA offsetof(VexGuestPPC32State,guest_XER_CA)
+#define OFFB_XER_BC offsetof(VexGuestPPC32State,guest_XER_BC)
=20
#define OFFB_FPROUND offsetof(VexGuestPPC32State,guest_FPROUND)
=20
@@ -392,7 +394,24 @@
return IRExpr_Load(Iend_BE,ty,data);
}
=20
+static IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 )
+{
+ vassert(typeOfIRExpr(irbb->tyenv, arg1) =3D=3D Ity_I1);
+ vassert(typeOfIRExpr(irbb->tyenv, arg2) =3D=3D Ity_I1);
+ return
+ unop(Iop_32to1, binop(Iop_Or32, unop(Iop_1Uto32, arg1),=20
+ unop(Iop_1Uto32, arg2)));
+}
=20
+static IRExpr* mkAND1 ( IRExpr* arg1, IRExpr* arg2 )
+{
+ vassert(typeOfIRExpr(irbb->tyenv, arg1) =3D=3D Ity_I1);
+ vassert(typeOfIRExpr(irbb->tyenv, arg2) =3D=3D Ity_I1);
+ return
+ unop(Iop_32to1, binop(Iop_And32, unop(Iop_1Uto32, arg1),=20
+ unop(Iop_1Uto32, arg2)));
+}
+
static Int integerGuestRegOffset ( UInt archreg )
{
vassert(archreg < 32);
@@ -898,7 +917,7 @@
/* Set the CR0 flags following an arithmetic operation.
(Condition Register CR0 Field Definition, PPC32 p60)
*/
-static void setFlags_CR0 ( IRExpr* result )
+static void set_CR0 ( IRExpr* result )
{
vassert(typeOfIRExpr(irbb->tyenv,result) =3D=3D Ity_I32);
putCR321( 0, unop(Iop_32to8,
@@ -906,22 +925,128 @@
putCR0( 0, getXER_SO() );
}
=20
-//zz static void setFlags_XER_OV_SO( UInt op, IRExpr* res,
-//zz IRExpr* argL, IRExpr* argR )
-//zz {
-//zz IRExpr* xer_ov;
-//zz vassert(op < PPC32G_FLAG_OP_NUMBER);
-//zz vassert(typeOfIRExpr(irbb->tyenv,res) =3D=3D Ity_I32);
-//zz vassert(typeOfIRExpr(irbb->tyenv,argL) =3D=3D Ity_I32);
-//zz vassert(typeOfIRExpr(irbb->tyenv,argR) =3D=3D Ity_I32);
-//zz=20
-//zz // =3D> Calculate result immediately
-//zz xer_ov =3D mk_ppc32g_calculate_xer_ov(op, res, argL, argR);
-//zz=20
-//zz putReg_bit( PPC32_SPR_XER, xer_ov, SHIFT_XER_OV );
-//zz putReg_bit( PPC32_SPR_XER, xer_ov, SHIFT_XER_SO );
-//zz }
=20
+/* RES is the result of doing OP on ARGL and ARGR. Set %XER.OV and
+ %XER.SO accordingly. */
+
+static void set_XER_OV( UInt op, IRExpr* res,
+ IRExpr* argL, IRExpr* argR )
+{
+ IRTemp t64;
+ IRExpr* xer_ov;
+ vassert(op < PPC32G_FLAG_OP_NUMBER);
+ vassert(typeOfIRExpr(irbb->tyenv,res) =3D=3D Ity_I32);
+ vassert(typeOfIRExpr(irbb->tyenv,argL) =3D=3D Ity_I32);
+ vassert(typeOfIRExpr(irbb->tyenv,argR) =3D=3D Ity_I32);
+
+# define INT32_MIN 0x80000000
+
+# define XOR2(_aa,_bb) \
+ binop(Iop_Xor32,(_aa),(_bb))
+
+# define XOR3(_cc,_dd,_ee) \
+ binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee))
+
+# define AND3(_ff,_gg,_hh) \
+ binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh))
+
+#define NOT(_jj) \
+ unop(Iop_Not32, (_jj))
+
+ switch (op) {
+
+ case /* 0 */ PPC32G_FLAG_OP_ADD:
+ case /* 1 */ PPC32G_FLAG_OP_ADDE:
+ /* (argL^argR^-1) & (argL^res) & (1<<31) ?1:0 */
+ // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
+ xer_ov=20
+ =3D AND3( XOR3(argL,argR,mkU32(-1)),
+ XOR2(argL,res),
+ mkU32(INT32_MIN) );
+ /* xer_ov can only be 0 or 1<<31 */
+ xer_ov=20
+ =3D binop(Iop_Shr32, xer_ov, mkU8(31) );
+ break;
+
+ case /* 2 */ PPC32G_FLAG_OP_DIVW:
+ /* (argL =3D=3D INT32_MIN && argR =3D=3D -1) || argR =3D=3D 0 *=
/
+ xer_ov
+ =3D mkOR1(
+ mkAND1(=20
+ binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)),
+ binop(Iop_CmpEQ32, argR, mkU32(-1))=20
+ ),
+ binop(Iop_CmpEQ32, argR, mkU32(0) )=20
+ );
+ xer_ov=20
+ =3D unop(Iop_1Uto32, xer_ov);
+ break;
+
+ case /* 3 */ PPC32G_FLAG_OP_DIVWU:
+ /* argR =3D=3D 0 */
+ xer_ov=20
+ =3D unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0)));
+ break;
+
+ case /* 4 */ PPC32G_FLAG_OP_MULLW:
+ /* OV true if result can't be represented in 32 bits
+ i.e sHi !=3D sign extension of sLo */
+ t64 =3D newTemp(Ity_I64);
+ assign( t64, binop(Iop_MullU32, argL, argR) );
+ xer_ov=20
+ =3D binop( Iop_CmpNE32,
+ unop(Iop_64HIto32, mkexpr(t64)),
+ binop( Iop_Sar32,=20
+ unop(Iop_64to32, mkexpr(t64)),=20
+ mkU8(31))
+ );
+ xer_ov
+ =3D unop(Iop_1Uto32, xer_ov);
+ break;
+
+ case /* 5 */ PPC32G_FLAG_OP_NEG:
+ /* argL =3D=3D INT32_MIN */
+ xer_ov
+ =3D unop( Iop_1Uto32,=20
+ binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) );
+ break;
+
+ case /* 6 */ PPC32G_FLAG_OP_SUBF:
+ case /* 7 */ PPC32G_FLAG_OP_SUBFC:
+ case /* 8 */ PPC32G_FLAG_OP_SUBFE:
+ /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */
+ xer_ov=20
+ =3D AND3( XOR3(NOT(argL),argR,mkU32(-1)),
+ XOR2(NOT(argL),res),
+ mkU32(INT32_MIN) );
+ /* xer_ov can only be 0 or 1<<31 */
+ xer_ov=20
+ =3D binop(Iop_Shr32, xer_ov, mkU8(31) );
+ break;
+
+ default:=20
+ vex_printf("set_XER_OV: op =3D %d\n", op);
+ vpanic("set_XER_OV(ppc32)");
+ }
+=20
+ /* xer_ov MUST denote either 0 or 1, no other value allowed */
+ stmt( IRStmt_Put( OFFB_XER_OV, unop(Iop_32to8, xer_ov) ) );
+
+ /* 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 ) )
+ ));
+
+# undef INT32_MIN
+# undef AND3
+# undef XOR3
+# undef XOR2
+# undef NOT
+}
+
+
/* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA
value being OLDCA. Set %XER.CA accordingly. */
=20
@@ -938,13 +1063,111 @@
vassert(typeOfIRExpr(irbb->tyenv,argR) =3D=3D Ity_I32);
vassert(typeOfIRExpr(irbb->tyenv,oldca) =3D=3D Ity_I32);
=20
- // Use a helper to calculate xer_ca. Assumes that the
- // helper returns either 1 or 0, which is true because
- // mk_ppc32g_calculate_xer_ca masks the value appropriately.
- xer_ca =3D mk_ppc32g_calculate_xer_ca(op, res, argL, argR, oldca );
- xer_ca =3D unop(Iop_32to8, xer_ca);
+ /* 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
+ 0 or 1 is an invariant of the ppc32 guest state representation;
+ if it has any other value, that invariant has been violated. */
=20
- stmt( IRStmt_Put( OFFB_XER_CA, xer_ca ) );
+ switch (op) {
+
+ case /* 0 */ PPC32G_FLAG_OP_ADD:
+ /* res <u argL */
+ xer_ca
+ =3D unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL));
+ break;
+
+ case /* 1 */ PPC32G_FLAG_OP_ADDE:
+ /* res <u argL || (old_ca=3D=3D1 && res=3D=3DargL) */
+ xer_ca=20
+ =3D mkOR1(=20
+ binop(Iop_CmpLT32U, res, argL),
+ mkAND1(=20
+ binop(Iop_CmpEQ32, oldca, mkU32(1)),
+ binop(Iop_CmpEQ32, res, argL)=20
+ )=20
+ );
+ xer_ca=20
+ =3D unop(Iop_1Uto32, xer_ca);
+ break;
+
+ case /* 8 */ PPC32G_FLAG_OP_SUBFE:
+ /* res <u argR || (old_ca=3D=3D1 && res=3D=3DargR) */
+ xer_ca=20
+ =3D mkOR1(=20
+ binop(Iop_CmpLT32U, res, argR),
+ mkAND1(=20
+ binop(Iop_CmpEQ32, oldca, mkU32(1)),
+ binop(Iop_CmpEQ32, res, argR)=20
+ )=20
+ );
+ xer_ca=20
+ =3D unop(Iop_1Uto32, xer_ca);
+ break;
+
+ case /* 7 */ PPC32G_FLAG_OP_SUBFC:
+ case /* 9 */ PPC32G_FLAG_OP_SUBFI:
+ /* res <=3Du argR */
+ xer_ca
+ =3D unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR));
+ break;
+
+ case /* 10 */ PPC32G_FLAG_OP_SRAW:
+ /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
+ If it is <=3D 31, behave like SRAWI; else XER.CA is the sign
+ bit of argL. */
+ /* This term valid for shift amount < 32 only */
+ xer_ca
+ =3D binop(
+ Iop_And32,
+ binop(Iop_Sar32, argL, mkU8(31)),
+ binop( Iop_And32,
+ argL,
+ binop( Iop_Sub32,
+ binop(Iop_Shl32, mkU32(1), unop(Iop_32to8=
,argR)),
+ mkU32(1) )
+ )
+ );
+ xer_ca=20
+ =3D IRExpr_Mux0X(
+ /* shift amt > 31 ? */
+ unop(Iop_1Uto8, binop(Iop_CmpLT32U, mkU32(31), argR)),
+ /* no -- be like srawi */
+ unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))),
+ /* yes -- get sign bit of argL */
+ binop(Iop_Shr32, argL, mkU8(31))
+ );
+ break;
+
+ case /* 11 */ PPC32G_FLAG_OP_SRAWI:
+ /* xer_ca is 1 iff src was negative and bits_shifted_out !=3D=20
+ 0. Since the shift amount is known to be in the range
+ 0 .. 31 inclusive the following seems viable:
+ xer.ca =3D=3D 1 iff the following is nonzero:
+ (argL >>s 31) -- either all 0s or all 1s
+ & (argL & (1<<argR)-1) -- the stuff shifted out */
+ xer_ca
+ =3D binop(
+ Iop_And32,
+ binop(Iop_Sar32, argL, mkU8(31)),
+ binop( Iop_And32,
+ argL,
+ binop( Iop_Sub32,
+ binop(Iop_Shl32, mkU32(1), unop(Iop_32to8=
,argR)),
+ mkU32(1) )
+ )
+ );
+ xer_ca=20
+ =3D unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)));
+ break;
+
+ default:=20
+ vex_printf("set_XER_CA: op =3D %d\n", op);
+ vpanic("set_XER_CA(ppc32)");
+ }
+
+ /* xer_ca MUST denote either 0 or 1, no other value allowed */
+ stmt( IRStmt_Put( OFFB_XER_CA, unop(Iop_32to8, xer_ca) ) );
}
=20
static IRExpr* /* :: Ity_I32 */ get_XER_CA ( void )
@@ -1374,9 +1597,8 @@
Rd_addr, Ra_addr, Rb_addr);
assign( Rd, binop(Iop_Add32, mkexpr(Ra), mkexpr(Rb)) );
if (flag_OE) {
-vassert(0);
-// flag_op =3D PPC32G_FLAG_OP_ADD;
-// setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkexp=
r(Rb) );
+ set_XER_OV( PPC32G_FLAG_OP_ADD,
+ mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) );
}
break;
=20
@@ -1389,8 +1611,8 @@
mkexpr(Rd), mkexpr(Ra), mkexpr(Rb),
mkU32(0)/*old xer.ca, which is ignored*/ );
if (flag_OE) {
-vassert(0);
-// setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkexp=
r(Rb) );
+ set_XER_OV( PPC32G_FLAG_OP_ADD,=20
+ mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) );
}
break;
=20
@@ -1407,8 +1629,8 @@
mkexpr(Rd), mkexpr(Ra), mkexpr(Rb),
mkexpr(old_xer_ca) );
if (flag_OE) {
-vassert(0);
-// setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkexp=
r(Rb) );
+ set_XER_OV( PPC32G_FLAG_OP_ADDE,=20
+ mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) );
}
break;
}
@@ -1431,8 +1653,8 @@
mkexpr(Rd), mkexpr(Ra), mkU32(-1),
mkexpr(old_xer_ca) );
if (flag_OE) {
-vassert(0);
-// setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkU32=
(-1) );
+ set_XER_OV( PPC32G_FLAG_OP_ADDE,=20
+ mkexpr(Rd), mkexpr(Ra), mkU32(-1) );
}
break;
}
@@ -1454,8 +1676,8 @@
mkexpr(Rd), mkexpr(Ra), mkU32(0),=20
mkexpr(old_xer_ca) );
if (flag_OE) {
-vassert(0);
-// setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkU32=
(0) );
+ set_XER_OV( PPC32G_FLAG_OP_ADDE,=20
+ mkexpr(Rd), mkexpr(Ra), mkU32(0) );
}
break;
}
@@ -1466,9 +1688,8 @@
Rd_addr, Ra_addr, Rb_addr);
assign( Rd, binop(Iop_DivS32, mkexpr(Ra), mkexpr(Rb)) );
if (flag_OE) {
-vassert(0);
-// flag_op =3D PPC32G_FLAG_OP_DIVW;
-// setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkexp=
r(Rb) );
+ set_XER_OV( PPC32G_FLAG_OP_DIVW,=20
+ mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) );
}
/* Note:
if (0x8000_0000 / -1) or (x / 0)
@@ -1482,9 +1703,8 @@
Rd_addr, Ra_addr, Rb_addr);
assign( Rd, binop(Iop_DivU32, mkexpr(Ra), mkexpr(Rb)) );
if (flag_OE) {
-vassert(0);
-// flag_op =3D PPC32G_FLAG_OP_DIVWU;
-// setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkexp=
r(Rb) );
+ set_XER_OV( PPC32G_FLAG_OP_DIVWU,=20
+ mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) );
}
/* Note: ditto comment divw, for (x / 0) */
break;
@@ -1518,9 +1738,8 @@
assign( res64, binop(Iop_MullU32, mkexpr(Ra), mkexpr(Rb)) );
assign( Rd, unop(Iop_64to32, mkexpr(res64)) );
if (flag_OE) {
- vassert(0);
- // flag_op =3D PPC32G_FLAG_OP_MULLW;
- // setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkex=
pr(Rb) );
+ set_XER_OV( PPC32G_FLAG_OP_MULLW,=20
+ mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) );
}
break;
=20
@@ -1536,9 +1755,8 @@
assign( Rd, binop(Iop_Add32,
unop(Iop_Not32, mkexpr(Ra)), mkU32(1)) );
if (flag_OE) {
-vassert(0);
-// flag_op =3D PPC32G_FLAG_OP_NEG;
-// setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkexp=
r(Rb) );
+ set_XER_OV( PPC32G_FLAG_OP_NEG,=20
+ mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) );
}
break;
=20
@@ -1549,9 +1767,8 @@
// rD =3D rB - rA
assign( Rd, binop(Iop_Sub32, mkexpr(Rb), mkexpr(Ra)) );
if (flag_OE) {
-vassert(0);
-// flag_op =3D PPC32G_FLAG_OP_SUBF;
-// setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkexp=
r(Rb) );
+ set_XER_OV( PPC32G_FLAG_OP_SUBF,=20
+ mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) );
}
break;
=20
@@ -1565,8 +1782,8 @@
mkexpr(Rd), mkexpr(Ra), mkexpr(Rb),
mkU32(0)/*old xer.ca, which is ignored*/ );
if (flag_OE) {
-vassert(0);
-// setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkexp=
r(Rb) );
+ set_XER_OV( PPC32G_FLAG_OP_SUBFC,=20
+ mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) );
}
break;
=20
@@ -1583,31 +1800,36 @@
mkexpr(Rd), mkexpr(Ra), mkexpr(Rb),=20
mkexpr(old_xer_ca) );
if (flag_OE) {
- vassert(0);
-// setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkexp=
r(Rb) );
+ set_XER_OV( PPC32G_FLAG_OP_SUBFE,=20
+ mkexpr(Rd), mkexpr(Ra), mkexpr(Rb) );
}
break;
}
=20
-//zz case 0x0E8: // subfme (Subtract from Minus One Extended, =
PPC32 p541)
-//zz if (Rb_addr !=3D 0) {
-//zz vex_printf("dis_int_arith(PPC32)(subfme,Rb_addr)\n");
-//zz return False;
-//zz }
-//zz DIP("subfme%s%s r%d,r%d\n",
-//zz flag_OE ? "o" : "", flag_Rc ? "." : "",
-//zz Rd_addr, Ra_addr);
-//zz // rD =3D (log not)rA + (-1) + XER[CA]
-//zz // =3D> Just another form of subfe
-//zz assign( Rd, binop(Iop_Add32, unop(Iop_Not32, mkexpr(Ra)),
-//zz binop(Iop_Add32, mkU32(-1), mkexpr(xer_c=
a))) );
-//zz flag_op =3D PPC32G_FLAG_OP_SUBFE;
-//zz setFlags_XER_CA( flag_op, mkexpr(Rd), mkexpr(Ra), mkU32(-1=
) );
-//zz if (flag_OE) {
-//zz setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mk=
U32(-1) );
-//zz }
-//zz break;
- =20
+ case 0x0E8: { // subfme (Subtract from Minus One Extended, PPC=
32 p541)
+ IRTemp old_xer_ca =3D newTemp(Ity_I32);
+ if (Rb_addr !=3D 0) {
+ vex_printf("dis_int_arith(PPC32)(subfme,Rb_addr)\n");
+ return False;
+ }
+ DIP("subfme%s%s r%d,r%d\n",
+ flag_OE ? "o" : "", flag_Rc ? "." : "",
+ 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( 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,
+ mkexpr(Rd), mkexpr(Ra), mkU32(-1),
+ mkexpr(old_xer_ca) );
+ if (flag_OE) {
+ set_XER_OV( PPC32G_FLAG_OP_SUBFE,=20
+ mkexpr(Rd), mkexpr(Ra), mkU32(-1) );
+ }
+ break;
+ }
+
case 0x0C8: { // subfze (Subtract from Zero Extended, PPC32 p5=
42)
IRTemp old_xer_ca =3D newTemp(Ity_I32);
if (Rb_addr !=3D 0) {
@@ -1626,8 +1848,8 @@
mkexpr(Rd), mkexpr(Ra), mkU32(0),=20
mkexpr(old_xer_ca) );
if (flag_OE) {
-vassert(0);
-// setFlags_XER_OV_SO( flag_op, mkexpr(Rd), mkexpr(Ra), mkU32=
(0) );
+ set_XER_OV( PPC32G_FLAG_OP_SUBFE,
+ mkexpr(Rd), mkexpr(Ra), mkU32(0) );
}
break;
}
@@ -1644,7 +1866,7 @@
=20
putIReg( Rd_addr, mkexpr(Rd) );
if (do_rc && flag_Rc) {
- setFlags_CR0( mkexpr(Rd) );
+ set_CR0( mkexpr(Rd) );
}
return True;
}
@@ -1858,12 +2080,12 @@
unop(Iop_Clz32, mkexpr(Rs)) ));
break;
=20
-//zz case 0x11C: // eqv (Equivalent, PPC32 p396)
-//zz DIP("eqv%s r%d,r%d,r%d\n",
-//zz flag_Rc ? "." : "", Ra_addr, Rs_addr, Rb_addr);
-//zz assign( Ra, unop(Iop_Not32, binop(Iop_Xor32,
-//zz mkexpr(Rs), mkexpr(Rb)))=
);
-//zz break;
+ case 0x11C: // eqv (Equivalent, PPC32 p396)
+ DIP("eqv%s r%d,r%d,r%d\n",
+ flag_Rc ? "." : "", Ra_addr, Rs_addr, Rb_addr);
+ assign( Ra, unop(Iop_Not32, binop(Iop_Xor32,
+ mkexpr(Rs), mkexpr(Rb))) );
+ break;
=20
case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397
if (Rb_addr!=3D0) {
@@ -1936,7 +2158,7 @@
=20
putIReg( Ra_addr, mkexpr(Ra) );
if (do_rc && flag_Rc) {
- setFlags_CR0( mkexpr(Ra) );
+ set_CR0( mkexpr(Ra) );
}
return True;
}
@@ -2003,7 +2225,7 @@
=20
putIReg( Ra_addr, mkexpr(Ra) );
if (flag_Rc) {
- setFlags_CR0( mkexpr(Ra) );
+ set_CR0( mkexpr(Ra) );
}
return True;
}
@@ -3112,6 +3334,8 @@
IRTemp Ra =3D newTemp(Ity_I32);
IRTemp Rb =3D newTemp(Ity_I32);
IRTemp mask =3D newTemp(Ity_I32);
+ IRTemp sh_amt32 =3D newTemp(Ity_I32);
+ IRTemp outofrange =3D newTemp(Ity_I8);
=20
assign( Rs, getIReg(Rs_addr) );
assign( Rb, getIReg(Rb_addr) );
@@ -3133,53 +3357,37 @@
DIP("sraw%s r%d,r%d,r%d\n", flag_Rc ? "." : "",
Ra_addr, Rs_addr, Rb_addr);
=20
- assign( sh_amt, binop(Iop_And8, mkU8(0x1F),
- unop(Iop_32to8, mkexpr(Rb))) );
- // Rs_shift =3D Rs >> sh_amt
- assign( Rs_sh, binop(Iop_Shr32, mkexpr(Rs), mkexpr(sh_amt)) );
- // rb_b5 =3D Rb[5]
- assign( rb_b5, binop(Iop_And32, mkexpr(Rb), mkU32(1<<5)) );
- // sign =3D Rs[31]
- assign( sign, binop(Iop_Shr32, mkexpr(Rs), mkU8(31)) );
- // mask =3D rb_b5=3D=3D0 ? (-1 >> sh_amt) : 0
- assign( mask,
- IRExpr_Mux0X( unop(Iop_32to8, mkexpr(rb_b5)),
- binop(Iop_Shr32, mkU32(-1), mkexpr(sh_amt=
)),
- mkU32(0) ));
- // sign_ext =3D sign=3D=3D0 ? 0 : ~mask
- assign( sext, IRExpr_Mux0X( unop(Iop_32to8, mkexpr(sign)),
- mkU32(0),
- unop(Iop_Not32, mkexpr(mask)) ));
- // Rs_msk =3D (Rs_sh & mask)
- assign( Rs_msk, binop(Iop_And32, mkexpr(Rs_sh), mkexpr(mask)) )=
;
- // Ra =3D Rs_msk | sext
- assign( Ra, binop(Iop_Or32, mkexpr(Rs_msk), mkexpr(sext)) );
- flag_op =3D PPC32G_FLAG_OP_SRAW;
- set_XER_CA( flag_op, mkexpr(Ra), mkexpr(Rs), mkexpr(Rb),
- mkU32(0)/*old xer.ca, which is ignored*/ )=
;
+ /* JRS: my reading of the (poorly worded) PPC32 doc p506 is:
+ amt =3D Rb & 63
+ Ra =3D Sar32( Rs, amt > 31 ? 31 : amt )
+ XER.CA =3D amt > 31 ? sign-of-Rs : (computation as per sr=
awi)
+ */
+ assign( sh_amt32, binop(Iop_And32, mkU32(0x3F), mkexpr(Rb)) );
+ assign( outofrange,
+ unop( Iop_1Uto8,=20
+ binop(Iop_CmpLT32U, mkU32(31), mkexpr(sh_amt32)) =
));
+ assign( Ra,
+ binop( Iop_Sar32,=20
+ mkexpr(Rs),=20
+ unop( Iop_32to8,=20
+ IRExpr_Mux0X( mkexpr(outofrange),=20
+ mkexpr(sh_amt32),=20
+ mkU32(31)) ))
+ );
+ set_XER_CA( PPC32G_FLAG_OP_SRAW,
+ mkexpr(Ra), mkexpr(Rs), mkexpr(sh_amt32),
+ get_XER_CA() );
break;
=20
case 0x338: // srawi (Shift Right Algebraic Word Immediate, PPC32 =
p507)
DIP("srawi%s r%d,r%d,%d\n", flag_Rc ? "." : "",
Ra_addr, Rs_addr, sh_imm);
- =20
+ vassert(sh_imm < 32);
assign( sh_amt, mkU8(sh_imm) );
- // Rs_shift =3D Rs >> sh_amt
- assign( Rs_sh, binop(Iop_Shr32, mkexpr(Rs), mkexpr(sh_amt)) );
- // sign =3D Rs[31]
- assign( sign, binop(Iop_And32, mkU32(1),
- binop(Iop_Shr32, mkexpr(Rs), mkU8(31))) );
- // mask =3D (-1 >> sh_amt)
- assign( mask, binop(Iop_Shr32, mkU32(-1), mkexpr(sh_amt)) );
- // sign_ext =3D sign=3D=3D0 ? 0 : ~mask
- assign( sext, IRExpr_Mux0X( unop(Iop_32to8, mkexpr(sign)),
- mkU32(0),
- unop(Iop_Not32, mkexpr(mask)) ));
- // Ra =3D Rs_shift | sext
- assign( Ra, binop(Iop_Or32, mkexpr(sext), mkexpr(Rs_sh)) );
- flag_op =3D PPC32G_FLAG_OP_SRAWI;
- set_XER_CA( flag_op, mkexpr(Ra), mkexpr(Rs), mkU32(sh_imm),=20
- mkU32(0)/*old xer.ca, which is ignored*/ )=
;
+ 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() );
break;
=20
case 0x218: // srw (Shift Right Word, PPC32 p508)
@@ -3205,8 +3413,7 @@
putIReg( Ra_addr, mkexpr(Ra) );
=20
if (flag_Rc) {
-vassert(0);
- // setFlags_CR7( mkexpr(Ra) );
+ set_CR0( mkexpr(Ra) );
}
return True;
}
@@ -3391,7 +3598,46 @@
case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470)
=20
switch (SPR_flipped) { // Choose a register...
-//zz case 0x1: putIReg( Rd_addr, getReg( PPC32_SPR_XER ) ); b=
reak;
+
+ 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))
+ )
+ )
+ );
+ break;
+
case 0x8:
DIP("mflr r%d\n", Rd_addr);
putIReg( Rd_addr, getSPR( PPC32_SPR_LR ) );=20
@@ -3443,7 +3689,35 @@
case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483)
=20
switch (SPR_flipped) { // Choose a register...
-//zz case 0x1: putReg( PPC32_SPR_XER, mkexpr(Rs) ); break;
+ case 0x1:
+ DIP("mtxer r%d\n", Rs_addr);
+ IRStmt_Put(=20
+ OFFB_XER_SO,=20
+ unop( Iop_32to8,=20
+ binop( Iop_And32,=20
+ binop(Iop_Shr32, mkexpr(Rs_addr), mkU8(31)),=
=20
+ mkU32(1)) )=20
+ );
+ IRStmt_Put(=20
+ OFFB_XER_OV,=20
+ unop( Iop_32to8,=20
+ binop( Iop_And32,=20
+ binop(Iop_Shr32, mkexpr(Rs_addr), mkU8(30)),=
=20
+ mkU32(1)) )=20
+ );
+ IRStmt_Put(=20
+ OFFB_XER_CA,=20
+ unop( Iop_32to8,=20
+ binop( Iop_And32,=20
+ binop(Iop_Shr32, mkexpr(Rs_addr), mkU8(29)),=
=20
+ mkU32(1)) )=20
+ );
+ IRStmt_Put(=20
+ OFFB_XER_BC,=20
+ unop( Iop_32to8,=20
+ binop( Iop_And32, mkexpr(Rs_addr), mkU32(0xFF)) )
+ );
+ break;
case 0x8:
DIP("mtlr r%d\n", Rs_addr);
putSPR( PPC32_SPR_LR, mkexpr(Rs) );=20
@@ -3515,13 +3789,13 @@
//zz DIP("dcba r%d,r%d\n", Ra_addr, Rb_addr);
//zz if (0) vex_printf("vex ppc32->IR: kludged dcba\n");
//zz break;
-//zz =20
-//zz case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382)
-//zz vassert(0); /* AWAITING TEST CASE */
-//zz DIP("dcbf r%d,r%d\n", Ra_addr, Rb_addr);
-//zz if (0) vex_printf("vex ppc32->IR: kludged dcbf\n");
-//zz break;
=20
+ case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382)
+ DIP("dcbf r%d,r%d\n", Ra_addr, Rb_addr);
+ /* nop as far as vex is concerned */
+ if (0) vex_printf("vex ppc32->IR: kludged dcbf\n");
+ break;
+ =20
case 0x036: // dcbst (Data Cache Block Store, PPC32 p384)
DIP("dcbst r%d,r%d\n", Ra_addr, Rb_addr);
/* nop as far as vex is concerned */
Modified: trunk/priv/host-ppc32/isel.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/host-ppc32/isel.c 2005-07-21 10:07:13 UTC (rev 1284)
+++ trunk/priv/host-ppc32/isel.c 2005-07-21 14:48:31 UTC (rev 1285)
@@ -1537,7 +1537,8 @@
// Make a compare that will always be true:
HReg r_zero =3D newVRegI(env);
addInstr(env, PPC32Instr_LI32(r_zero, 0));
- addInstr(env, PPC32Instr_Cmp32(False/*unsigned*/, /*cr*/7, r_zero,=
PPC32RH_Reg(r_zero)));
+ addInstr(env, PPC32Instr_Cmp32(False/*unsigned*/, /*cr*/7,=20
+ r_zero, PPC32RH_Reg(r_zero)));
return mk_PPCCondCode( Pct_TRUE, Pcf_7EQ );
}
=20
@@ -1567,6 +1568,19 @@
//.. return iselCondCode(env, expr1);
//.. }
=20
+ /* 32to1 */
+ if (e->tag =3D=3D Iex_Unop && e->Iex.Unop.op =3D=3D Iop_32to1) {
+ HReg src =3D iselIntExpr_R(env, e->Iex.Unop.arg);
+ HReg tmp =3D newVRegI(env);
+ /* could do better, probably -- andi. */
+ addInstr(env, PPC32Instr_Alu32(
+ Palu_AND, tmp, src, PPC32RH_Imm(False,1)));
+ addInstr(env, PPC32Instr_Cmp32(
+ False/*unsigned*/, 7/*cr*/,=20
+ tmp, PPC32RH_Imm(False,1)));
+ return mk_PPCCondCode( Pct_TRUE, Pcf_7EQ );
+ }
+
/* --- patterns rooted at: CmpNEZ8 --- */
=20
/* CmpNEZ8(x) */
@@ -1576,7 +1590,8 @@
HReg r_32 =3D iselIntExpr_R(env, e->Iex.Unop.arg);
HReg r_l =3D newVRegI(env);
addInstr(env, PPC32Instr_Alu32(Palu_AND, r_l, r_32, PPC32RH_Imm(Fa=
lse,0xFF)));
- addInstr(env, PPC32Instr_Cmp32(False/*unsigned*/, 7, r_l, PPC32RH_=
Imm(False,0)));
+ addInstr(env, PPC32Instr_Cmp32(False/*unsigned*/, 7/*cr*/,=20
+r_l, PPC32RH_Imm(False,0)));
return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
}
=20
@@ -1661,9 +1676,9 @@
case Iop_CmpEQ32: return mk_PPCCondCode( Pct_TRUE, Pcf_7EQ );
case Iop_CmpNE32: return mk_PPCCondCode( Pct_FALSE, Pcf_7EQ );
// case Iop_CmpLT32S: return mk_PPCCondCode( Pct_TRUE, Pcf_LT );
-// case Iop_CmpLT32U: return mk_PPCCondCode( Pct_TRUE, Pcf_LT );
+ case Iop_CmpLT32U: return mk_PPCCondCode( Pct_TRUE, Pcf_7LT );
// case Iop_CmpLE32S: return mk_PPCCondCode( Pct_FALSE, Pcf_GT );
-// case Iop_CmpLE32U: return mk_PPCCondCode( Pct_FALSE, Pcf_GT );
+ case Iop_CmpLE32U: return mk_PPCCondCode( Pct_FALSE, Pcf_7GT );
default: vpanic("iselCondCode(ppc32): CmpXX32");
}
}
|