|
From: <sv...@va...> - 2005-12-22 14:32:41
|
Author: cerion
Date: 2005-12-22 14:32:35 +0000 (Thu, 22 Dec 2005)
New Revision: 1503
Log:
Implemented almost all of the remaining 64bit-mode insns.
Currently:
Not yet implemented: td(i)
Implemented, not tested: ldarx, stdcx.
All common-mode int & fp insns in 64bit-mode tested.
Altivec insns in 64bit-mode still to be tested.
Modified:
trunk/priv/guest-ppc32/toIR.c
trunk/priv/host-ppc32/hdefs.c
trunk/priv/host-ppc32/hdefs.h
trunk/priv/host-ppc32/isel.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-12-22 03:01:17 UTC (rev 1502)
+++ trunk/priv/guest-ppc32/toIR.c 2005-12-22 14:32:35 UTC (rev 1503)
@@ -1216,7 +1216,7 @@
}
}
=20
-// ROTL(src32/64, rot_amt5)
+// ROTL(src32/64, rot_amt5/6)
static IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src,
IRExpr* rot_amt )
{
@@ -2086,8 +2086,6 @@
=20
=20
case /* 12 */ PPC32G_FLAG_OP_SRAD:
- vassert(0); // AWAITING TEST CASE
-
/* The shift amount is guaranteed to be in 0 .. 63 inclusive.
If it is <=3D 63, behave like SRADI; else XER.CA is the sign
bit of argL. */
@@ -2108,8 +2106,8 @@
=3D IRExpr_Mux0X(
/* shift amt > 63 ? */
unop(Iop_1Uto8, binop(Iop_CmpLT64U, mkU64(63), argR)),
- /* no -- be like srawi */
- unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))),
+ /* no -- be like sradi */
+ unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))),
/* yes -- get sign bit of argL */
unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63)))
);
@@ -2900,14 +2898,12 @@
}
DIP("mulhd%s r%u,r%u,r%u\n", flag_rC ? "." : "",
rD_addr, rA_addr, rB_addr);
- DIP(" =3D> not implemented\n");
- return False;
- /*
assign( rD, unop(Iop_128HIto64,=20
- binop(Iop_MullU64,
+ binop(Iop_MullS64,
mkexpr(rA), mkexpr(rB))) );
- */
=20
+ break;
+
case 0x9: // mulhdu (Multiply High Double Word Unsigned, PPC64 p=
540)
if (flag_OE !=3D 0) {
vex_printf("dis_int_arith(PPC32)(mulhdu,flagOE)\n");
@@ -2915,13 +2911,10 @@
}
DIP("mulhdu%s r%u,r%u,r%u\n", flag_rC ? "." : "",
rD_addr, rA_addr, rB_addr);
- DIP(" =3D> not implemented\n");
- return False;
- /*
- assign( rD, unop(Iop_128HIto64,=20
- binop(Iop_MullU64,
- mkexpr(rA), mkexpr(rB))) );
- */
+ assign( rD, unop(Iop_128HIto64,=20
+ binop(Iop_MullU64,
+ mkexpr(rA), mkexpr(rB))) );
+ break;
=20
case 0xE9: // mulld (Multiply Low Double Word, PPC64 p543)
DIP("mulld%s%s r%u,r%u,r%u\n",
@@ -2938,21 +2931,14 @@
DIP("divd%s%s r%u,r%u,r%u\n",
flag_OE ? "o" : "", flag_rC ? "." : "",
rD_addr, rA_addr, rB_addr);
- DIP(" =3D> not implemented\n");
- return False;
- /*
- assign( rD, binop(Iop_DivS64, mkexpr(rA), mkexpr(rB)) );
- if (flag_OE) {
- set_XER_OV( ty, PPC32G_FLAG_OP_DIVW,=20
- mkexpr(rD), mkexpr(rA), mkexpr(rB) );
- }
-
- if invalid divide (rA=3D=3D0x8000_0000_0000_0000 && rB=3D=3D-=
1, OR rB=3D=3D0)
- rD undefined, CR[LT,GT,EQ] undefined
- flag_OE ? XER: set OV
- */
+ assign( rD, binop(Iop_DivS64, mkexpr(rA), mkexpr(rB)) );
+ if (flag_OE) {
+ set_XER_OV( ty, PPC32G_FLAG_OP_DIVW,=20
+ mkexpr(rD), mkexpr(rA), mkexpr(rB) );
+ }
+ break;
/* Note:
- if (0x8000_0000 / -1) or (x / 0)
+ if (0x8000_0000_0000_0000 / -1) or (x / 0)
=3D> rD=3Dundef, if(flag_rC) CR7=3Dundef, if(flag_OE) XER_OV=
=3D1
=3D> But _no_ exception raised. */
=20
@@ -2960,19 +2946,12 @@
DIP("divdu%s%s r%u,r%u,r%u\n",
flag_OE ? "o" : "", flag_rC ? "." : "",
rD_addr, rA_addr, rB_addr);
- DIP(" =3D> not implemented\n");
- return False;
- /*
- assign( rD, binop(Iop_DivU64, mkexpr(rA), mkexpr(rB)) );
- if (flag_OE) {
- set_XER_OV( PPC32G_FLAG_OP_DIVWU,=20
- mkexpr(rD), mkexpr(rA), mkexpr(rB) );
- }
-
- if invalid divide (rB=3D=3D0)
- rD undefined, CR[LT,GT,EQ] undefined
- flag_OE ? XER: set OV
- */
+ assign( rD, binop(Iop_DivU64, mkexpr(rA), mkexpr(rB)) );
+ if (flag_OE) {
+ set_XER_OV( ty, PPC32G_FLAG_OP_DIVWU,=20
+ mkexpr(rD), mkexpr(rA), mkexpr(rB) );
+ }
+ break;
/* Note: ditto comment divd, for (x / 0) */
=20
default:
@@ -3301,15 +3280,12 @@
return False;
}
DIP("cntlzd%s r%u,r%u\n", flag_rC ? "." : "", rA_addr, rS_addr)=
;
- DIP(" =3D> not implemented\n");
- return False;
- /*
- // Iop_Clz64 undefined for arg=3D=3D0, so deal with that case=
:
- irx =3D binop(Iop_CmpNE64, mkexpr(rS), mkU64(0));
- assign(rA, IRExpr_Mux0X( unop(Iop_1Uto8, irx),
- mkU64(64),
- unop(Iop_Clz64, mkexpr(rS)) ));
- */
+ // Iop_Clz64 undefined for arg=3D=3D0, so deal with that case:
+ irx =3D binop(Iop_CmpNE64, mkexpr(rS), mkU64(0));
+ assign(rA, IRExpr_Mux0X( unop(Iop_1Uto8, irx),
+ mkU64(64),
+ unop(Iop_Clz64, mkexpr(rS)) ));
+ break;
=20
default:
vex_printf("dis_int_logic(PPC32)(opc2)\n");
@@ -3473,28 +3449,26 @@
vassert( sh_imm < 64 );
=20
switch (opc2) {
- case 0x4:
- /*
- n =3D lowest 6bits of rB
- r =3D ROTL64(rS,n)
- */
+ case 0x4: {
+ /* r =3D ROTL64( rS, rB_lo6) */
+ r =3D ROTL( mkexpr(rS), unop(Iop_64to8, mkexpr(rB)) );
+
if (b1 =3D=3D 0) { // rldcl (Rotate Left DW then Clear Left, PP=
C64 p555)
DIP("rldcl%s r%u,r%u,r%u,%u\n", flag_rC ? "." : "",
rA_addr, rS_addr, rB_addr, msk_imm);
- r =3D ROTL(mkexpr(rS), mkU8(sh_imm));
+ // note, ROTL does the masking, so we don't do it here
mask64 =3D MASK64(0, 63-msk_imm);
assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
break;
} else { // rldcr (Rotate Left DW then Clear Right, PPC64=
p556)
DIP("rldcr%s r%u,r%u,r%u,%u\n", flag_rC ? "." : "",
rA_addr, rS_addr, rB_addr, msk_imm);
- r =3D ROTL(mkexpr(rS), mkU8(sh_imm));
mask64 =3D MASK64(63-msk_imm, 63);
assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
break;
}
break;
-
+ }
case 0x2: // rldic (Rotate Left DW Imm then Clear, PPC64 p557)
DIP("rldic%s r%u,r%u,%u,%u\n", flag_rC ? "." : "",
rA_addr, rS_addr, sh_imm, msk_imm);
@@ -3528,16 +3502,18 @@
break;
// later: deal with special case: (msk_imm =3D=3D sh_imm) =3D> =
SHL(sh_imm)
=20
- case 0x3: // rldimi (Rotate Left DW Imm then Mask Insert, PPC64 p5=
60)
+ case 0x3: { // rldimi (Rotate Left DW Imm then Mask Insert, PPC64 =
p560)
+ IRTemp rA_orig =3D newTemp(ty);
DIP("rldimi%s r%u,r%u,%u,%u\n", flag_rC ? "." : "",
rA_addr, rS_addr, sh_imm, msk_imm);
r =3D ROTL(mkexpr(rS), mkU8(sh_imm));
mask64 =3D MASK64(sh_imm, 63-msk_imm);
+ assign( rA_orig, getIReg(rA_addr) );
assign( rA, binop(Iop_Or64,
binop(Iop_And64, mkU64(mask64), r),
- binop(Iop_And64, mkU64(~mask64), mkexpr(rA)))=
);
+ binop(Iop_And64, mkU64(~mask64), mkexpr(rA_or=
ig))) );
break;
- =20
+ }
default:
vex_printf("dis_int_rot(PPC32)(opc2)\n");
return False;
@@ -4600,6 +4576,12 @@
=20
/*
Memory Synchronization Instructions
+
+ Note on Reservations:
+ We rely on the assumption that V will in fact only allow one thread at
+ once to run. In effect, a thread can make a reservation, but we don't
+ check any stores it does. Instead, the reservation is cancelled when
+ the scheduler switches to another thread (run_thread_for_a_while()).
*/
static Bool dis_memsync ( UInt theInstr )
{
@@ -4717,50 +4699,43 @@
return False;
}
DIP("ldarx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
- DIP(" =3D> not implemented\n");
- return False;
- /*
- assign( EA, ea_standard(rA_addr, rB_addr) );
- putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
- // Take a reservation
- stmt( IRStmt_Put( OFFB_RESVN, mkexpr(EA) )); =20
- */
- =20
- case 0x0D6: // stdcx. (Store DW Condition Indexed, PPC64 p581)
+ putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
+ // Take a reservation
+ putGST( PPC_GST_RESVN, mkexpr(EA) );
+ break;
+ =20
+ case 0x0D6: { // stdcx. (Store DW Condition Indexed, PPC64 p581)
+ IRTemp resaddr =3D newTemp(ty);
if (b0 !=3D 1) {
vex_printf("dis_memsync(PPC32)(stdcx.,b0)\n");
return False;
}
DIP("stdcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
- DIP(" =3D> not implemented\n");
- return False;
- /*
- assign( rS, getIReg(rS_addr) );
- assign( EA, ea_standard(rA_addr, rB_addr) );
+ assign( rS, getIReg(rS_addr) );
=20
- // First set up as if the reservation failed
- // Set CR0[LT GT EQ S0] =3D 0b000 || XER[SO]
- putCR321(0, mkU8(0<<1));
- putCR0(0, getXER_SO());
+ // First set up as if the reservation failed
+ // Set CR0[LT GT EQ S0] =3D 0b000 || XER[SO]
+ putCR321(0, mkU8(0<<1));
+ putCR0(0, getXER_SO());
=20
- // Get the reservation address into a temporary, then clear i=
t.
- assign( resaddr, IRExpr_Get(OFFB_RESVN, Ity_I64) );
- stmt( IRStmt_Put( OFFB_RESVN, mkU64(0) ));
+ // Get the reservation address into a temporary, then clear it.
+ assign( resaddr, getGST(PPC_GST_RESVN) );
+ putGST( PPC_GST_RESVN, mkSzImm(ty, 0) );
=20
- // Skip the rest if the reservation really did fail.
- stmt( IRStmt_Exit(
- binop(Iop_CmpNE64, mkexpr(resaddr),
- mkexpr(EA)),
- Ijk_Boring,
- IRConst_U32(guest_CIA_curr_instr + 4)) );
+ // Skip the rest if the reservation really did fail.
+ stmt( IRStmt_Exit( binop(Iop_CmpNE64, mkexpr(resaddr),
+ mkexpr(EA)),
+ Ijk_Boring,
+ IRConst_U64(nextInsnAddr())) );
=20
- // Success? Do the store
- storeBE( mkexpr(EA), mkexpr(rS) );
+ // Success? Do the store
+ storeBE( mkexpr(EA), mkexpr(rS) );
=20
- // Set CR0[LT GT EQ S0] =3D 0b001 || XER[SO]
- putCR321(0, mkU8(1<<1));
- */
- =20
+ // Set CR0[LT GT EQ S0] =3D 0b001 || XER[SO]
+ putCR321(0, mkU8(1<<1));
+ break;
+ }
+
default:
vex_printf("dis_memsync(PPC32)(opc2)\n");
return False;
@@ -4793,15 +4768,17 @@
=20
IRType ty =3D mode64 ? Ity_I64 : Ity_I32;
IRTemp rA =3D newTemp(ty);
+ IRTemp rS =3D newTemp(ty);
+ IRTemp rB =3D newTemp(ty);
IRTemp outofrange =3D newTemp(Ity_I8);
-// IRTemp sh_amt =3D newTemp(Ity_I8);
- IRTemp sh_amt32 =3D newTemp(Ity_I32);
IRTemp rS_lo32 =3D newTemp(Ity_I32);
IRTemp rB_lo32 =3D newTemp(Ity_I32);
IRExpr* e_tmp;
=20
- assign( rS_lo32, mkSzNarrow32(ty, getIReg(rS_addr)) );
- assign( rB_lo32, mkSzNarrow32(ty, getIReg(rB_addr)) );
+ assign( rS, getIReg(rS_addr) );
+ assign( rB, getIReg(rB_addr) );
+ assign( rS_lo32, mkSzNarrow32(ty, mkexpr(rS)) );
+ assign( rB_lo32, mkSzNarrow32(ty, mkexpr(rB)) );
=20
if (opc1 =3D=3D 0x1F) {
switch (opc2) {
@@ -4829,7 +4806,8 @@
break;
}
=20
- case 0x318: // sraw (Shift Right Algebraic Word, PPC32 p506)
+ case 0x318: { // sraw (Shift Right Algebraic Word, PPC32 p506)
+ IRTemp sh_amt =3D newTemp(Ity_I32);
DIP("sraw%s r%u,r%u,r%u\n", flag_rC ? "." : "",
rA_addr, rS_addr, rB_addr);
/* JRS: my reading of the (poorly worded) PPC32 doc p506 is:
@@ -4837,24 +4815,25 @@
rA =3D Sar32( rS, amt > 31 ? 31 : amt )
XER.CA =3D amt > 31 ? sign-of-rS : (computation as per srawi=
)
*/
- assign( sh_amt32, binop(Iop_And32, mkU32(0x3F), mkexpr(rB_lo32)=
) );
+ assign( sh_amt, binop(Iop_And32, mkU32(0x3F), mkexpr(rB_lo32)) =
);
assign( outofrange,
unop( Iop_1Uto8,=20
- binop(Iop_CmpLT32U, mkU32(31), mkexpr(sh_amt32)) =
));
+ binop(Iop_CmpLT32U, mkU32(31), mkexpr(sh_amt)) ))=
;
e_tmp =3D binop( Iop_Sar32,=20
mkexpr(rS_lo32),=20
unop( Iop_32to8,=20
IRExpr_Mux0X( mkexpr(outofrange),=20
- mkexpr(sh_amt32),=20
+ mkexpr(sh_amt),=20
mkU32(31)) ) );
assign( rA, mkSzWiden32(ty, e_tmp, /* Signed */True) );
=20
set_XER_CA( ty, PPC32G_FLAG_OP_SRAW,
mkexpr(rA),
mkSzWiden32(ty, mkexpr(rS_lo32), True),
- mkSzWiden32(ty, mkexpr(sh_amt32), True ),
+ mkSzWiden32(ty, mkexpr(sh_amt), True ),
mkSzWiden32(ty, getXER_CA32(), True) );
break;
+ }
=20
case 0x338: // srawi (Shift Right Algebraic Word Immediate, PPC32 =
p507)
DIP("srawi%s r%u,r%u,%d\n", flag_rC ? "." : "",
@@ -4903,14 +4882,11 @@
case 0x01B: // sld (Shift Left DW, PPC64 p568)
DIP("sld%s r%u,r%u,r%u\n", flag_rC ? "." : "", rA_addr, rS_addr=
, rB_addr);
/* rA =3D rS << rB */
- /* ppc32 semantics are:=20
+ /* ppc64 semantics are:=20
slw(x,y) =3D (x << (y & 63)) -- primary result
& ~((y << 57) >>s 63) -- make result 0=20
for y in 64 ..=20
*/
- DIP(" =3D> not implemented\n");
- return False;
- /*
assign( rA,
binop(
Iop_And64,
@@ -4922,34 +4898,33 @@
binop( Iop_Sar64,
binop(Iop_Shl64, mkexpr(rB), mkU8(57)),=20
mkU8(63)))) );
- */
+ break;
=20
- case 0x31A: // srad (Shift Right Algebraic DW, PPC64 p570)
+ case 0x31A: { // srad (Shift Right Algebraic DW, PPC64 p570)
+ IRTemp sh_amt =3D newTemp(Ity_I64);
DIP("srad%s r%u,r%u,r%u\n", flag_rC ? "." : "", rA_addr, rS_add=
r, rB_addr);
/* amt =3D rB & 127
rA =3D Sar64( rS, amt > 63 ? 63 : amt )
XER.CA =3D amt > 63 ? sign-of-rS : (computation as per srawi=
)
*/
- DIP(" =3D> not implemented\n");
- return False;
- /*
- assign( sh_amt64, binop(Iop_And64, mkU64(0x7F), mkexpr(rB)) );
+ assign( sh_amt, binop(Iop_And64, mkU64(0x7F), mkexpr(rB)) );
assign( outofrange,
unop( Iop_1Uto8,=20
- binop(Iop_CmpLT64U, mkU64(63), mkexpr(sh_amt64)) =
));
+ binop(Iop_CmpLT64U, mkU64(63), mkexpr(sh_amt)) ))=
;
assign( rA,
binop( Iop_Sar64,=20
mkexpr(rS),=20
unop( Iop_64to8,=20
IRExpr_Mux0X( mkexpr(outofrange),=20
- mkexpr(sh_amt64),=20
- mkU32(63)) ))
+ mkexpr(sh_amt),=20
+ mkU64(63)) ))
);
- set_XER_CA( PPC32G_FLAG_OP_SRAD,
- mkexpr(rA), mkexpr(rS), mkexpr(sh_amt64),
- getXER_CA32() );
- */
- =20
+ set_XER_CA( ty, PPC32G_FLAG_OP_SRAD,
+ mkexpr(rA), mkexpr(rS), mkexpr(sh_amt),
+ mkSzWiden32(ty, getXER_CA32(), /* Signed */False) )=
;
+ break;
+ }
+
case 0x33A: case 0x33B: // sradi (Shift Right Algebraic DW Imm, PP=
C64 p571)
sh_imm |=3D b1<<5;
vassert(sh_imm < 64);
@@ -4965,15 +4940,12 @@
=20
case 0x21B: // srd (Shift Right DW, PPC64 p574)
DIP("srd%s r%u,r%u,r%u\n", flag_rC ? "." : "", rA_addr, rS_addr=
, rB_addr);
- DIP(" =3D> not implemented\n");
- return False;
/* rA =3D rS >>u rB */
- /* ppc32 semantics are:=20
+ /* ppc semantics are:=20
srw(x,y) =3D (x >>u (y & 63)) -- primary result
& ~((y << 57) >>s 63) -- make result 0=20
for y in 64 .. 127
*/
- /*
assign( rA,
binop(
Iop_And64,
@@ -4985,7 +4957,7 @@
binop( Iop_Sar64,=20
binop(Iop_Shl64, mkexpr(rB), mkU8(57)),=20
mkU8(63)))) );
- */
+ break;
=20
default:
vex_printf("dis_int_shift(PPC32)(opc2)\n");
@@ -6113,7 +6085,8 @@
=20
IRTemp frD =3D newTemp(Ity_F64);
IRTemp frB =3D newTemp(Ity_F64);
- IRTemp r_tmp =3D newTemp(Ity_I32);
+ IRTemp r_tmp32 =3D newTemp(Ity_I32);
+ IRTemp r_tmp64 =3D newTemp(Ity_I64);
=20
if (opc1 !=3D 0x3F || b16to20 !=3D 0) {
vex_printf("dis_fp_round(PPC32)(instr)\n");
@@ -6130,47 +6103,37 @@
=20
case 0x00E: // fctiw (Float Conv to Int, PPC32 p404)
DIP("fctiw%s fr%u,fr%u\n", flag_rC ? "." : "", frD_addr, frB_addr)=
;
- assign( r_tmp, binop(Iop_F64toI32, get_roundingmode(), mkexpr(frB)=
) );
+ assign( r_tmp32, binop(Iop_F64toI32, get_roundingmode(), mkexpr(fr=
B)) );
assign( frD, unop( Iop_ReinterpI64asF64,
- unop( Iop_32Uto64, mkexpr(r_tmp))));
+ unop( Iop_32Uto64, mkexpr(r_tmp32))));
break;
=20
case 0x00F: // fctiwz (Float Conv to Int, Round to Zero, PPC32 p405)
DIP("fctiwz%s fr%u,fr%u\n", flag_rC ? "." : "", frD_addr, frB_addr=
);
- assign( r_tmp, binop(Iop_F64toI32, mkU32(0x3), mkexpr(frB)) );
+ assign( r_tmp32, binop(Iop_F64toI32, mkU32(0x3), mkexpr(frB)) );
assign( frD, unop( Iop_ReinterpI64asF64,
- unop( Iop_32Uto64, mkexpr(r_tmp))));
+ unop( Iop_32Uto64, mkexpr(r_tmp32))));
break;
=20
=20
/* 64bit FP conversions */
case 0x32E: // fctid (Float Conv to Int DW, PPC64 p437)
DIP("fctid%s fr%u,fr%u\n", flag_rC ? "." : "", frD_addr, frB_addr)=
;
- DIP(" =3D> not implemented\n");
- return False;
- /*
- assign( r_tmp, binop(Iop_F64toI64, get_roundingmode(), mkexpr(fr=
B)) );
- assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp)) );
- */
+ assign( r_tmp64, binop(Iop_F64toI64, get_roundingmode(), mkexpr(fr=
B)) );
+ assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
+ break;
=20
case 0x32F: // fctidz (Float Conv to Int DW, Round to Zero, PPC64 p43=
7)
DIP("fctidz%s fr%u,fr%u\n", flag_rC ? "." : "", frD_addr, frB_addr=
);
- DIP(" =3D> not implemented\n");
- return False;
- /*
- assign( r_tmp, binop(Iop_F64toI64, mkU32(0x3), mkexpr(frB)) );
- assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp)) );
- */
+ assign( r_tmp64, binop(Iop_F64toI64, mkU32(0x3), mkexpr(frB)) );
+ assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
+ break;
=20
case 0x34E: // fcfid (Float Conv from Int DW, PPC64 p434)
DIP("fcfid%s fr%u,fr%u\n", flag_rC ? "." : "", frD_addr, frB_addr)=
;
- DIP(" =3D> not implemented\n");
- return False;
- /*
- ?
- assign( r_tmp, unop( Iop_ReinterpF64asI64, mkexpr(rD)) );
- assign( frD, binop(Iop_I64toF64, get_roundingmode(), mkexpr(frB)=
) );
- */
+ assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
+ assign( frD, binop(Iop_I64toF64, get_roundingmode(), mkexpr(r_tmp6=
4)) );
+ break;
=20
default:
vex_printf("dis_fp_round(PPC32)(opc2)\n");
@@ -8722,7 +8685,7 @@
goto decode_failure;
=20
/* 64bit Integer Logical Instructions */
- case 0x3DA: case 0x03A: // extsw, cntlzw
+ case 0x3DA: case 0x03A: // extsw, cntlzd
if (!mode64) goto decode_failure;
if (dis_int_logic( theInstr )) goto decode_success;
goto decode_failure;
@@ -8735,7 +8698,7 @@
=20
/* 64bit Integer Shift Instructions */
case 0x01B: case 0x31A: // sld, srad
- case 0x33A: case 0x33B: // sradi_a, sradi_b
+ case 0x33A: case 0x33B: // sradi
case 0x21B: // srd
if (!mode64) goto decode_failure;
if (dis_int_shift( theInstr )) goto decode_success;
Modified: trunk/priv/host-ppc32/hdefs.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/hdefs.c 2005-12-22 03:01:17 UTC (rev 1502)
+++ trunk/priv/host-ppc32/hdefs.c 2005-12-22 14:32:35 UTC (rev 1503)
@@ -568,7 +568,8 @@
switch (op) {
case Pun_NOT: return "not";
case Pun_NEG: return "neg";
- case Pun_CLZ: return "cntlzw";
+ case Pun_CLZ32: return "cntlzw";
+ case Pun_CLZ64: return "cntlzd";
default: vpanic("showPPC32UnaryOp");
}
}
@@ -909,6 +910,20 @@
i->Pin.FpF64toI32.src =3D src;
return i;
}
+PPC32Instr* PPC32Instr_FpF64toI64 ( HReg dst, HReg src ) {
+ PPC32Instr* i =3D LibVEX_Alloc(sizeof(PPC32Instr));
+ i->tag =3D Pin_FpF64toI64;
+ i->Pin.FpF64toI64.dst =3D dst;
+ i->Pin.FpF64toI64.src =3D src;
+ return i;
+}
+PPC32Instr* PPC32Instr_FpI64toF64 ( HReg dst, HReg src ) {
+ PPC32Instr* i =3D LibVEX_Alloc(sizeof(PPC32Instr));
+ i->tag =3D Pin_FpI64toF64;
+ i->Pin.FpI64toF64.dst =3D dst;
+ i->Pin.FpI64toF64.src =3D src;
+ return i;
+}
PPC32Instr* PPC32Instr_FpCMov ( PPC32CondCode cond, HReg dst, HReg src )=
{
PPC32Instr* i =3D LibVEX_Alloc(sizeof(PPC32Instr));
i->tag =3D Pin_FpCMov;
@@ -1396,6 +1411,23 @@
ppHRegPPC32(i->Pin.FpF64toI32.dst);
vex_printf(",%%r0,%%r1");
return;
+ case Pin_FpF64toI64:
+ vex_printf("fctid %%fr7,");
+ ppHRegPPC32(i->Pin.FpF64toI64.src);
+ vex_printf("; stfdx %%fr7,%%r0,%%r1");
+ vex_printf("; ldx ");
+ ppHRegPPC32(i->Pin.FpF64toI64.dst);
+ vex_printf(",%%r0,%%r1");
+ return;
+ case Pin_FpI64toF64:
+ vex_printf("stdx ");
+ ppHRegPPC32(i->Pin.FpI64toF64.src);
+ vex_printf(",%%r0,%%r1");
+ vex_printf("; lfdx %%fr7,%%r0,%%r1");
+ vex_printf("; fcfid ");
+ ppHRegPPC32(i->Pin.FpI64toF64.dst);
+ vex_printf(",%%r7");
+ return;
case Pin_FpCMov:
vex_printf("fpcmov (%s) ", showPPC32CondCode(i->Pin.FpCMov.cond));
ppHRegPPC32(i->Pin.FpCMov.dst);
@@ -1731,6 +1763,16 @@
addHRegUse(u, HRmWrite, hregPPC32_FPR7());
addHRegUse(u, HRmRead, i->Pin.FpF64toI32.src);
return;
+ case Pin_FpF64toI64:
+ addHRegUse(u, HRmWrite, i->Pin.FpF64toI64.dst);
+ addHRegUse(u, HRmWrite, hregPPC32_FPR7());
+ addHRegUse(u, HRmRead, i->Pin.FpF64toI64.src);
+ return;
+ case Pin_FpI64toF64:
+ addHRegUse(u, HRmWrite, i->Pin.FpI64toF64.dst);
+ addHRegUse(u, HRmWrite, hregPPC32_FPR7());
+ addHRegUse(u, HRmRead, i->Pin.FpI64toF64.src);
+ return;
case Pin_FpCMov:
addHRegUse(u, HRmModify, i->Pin.FpCMov.dst);
addHRegUse(u, HRmRead, i->Pin.FpCMov.src);
@@ -1925,6 +1967,14 @@
mapReg(m, &i->Pin.FpF64toI32.dst);
mapReg(m, &i->Pin.FpF64toI32.src);
return;
+ case Pin_FpF64toI64:
+ mapReg(m, &i->Pin.FpF64toI64.dst);
+ mapReg(m, &i->Pin.FpF64toI64.src);
+ return;
+ case Pin_FpI64toF64:
+ mapReg(m, &i->Pin.FpI64toF64.dst);
+ mapReg(m, &i->Pin.FpI64toF64.src);
+ return;
case Pin_FpCMov:
mapReg(m, &i->Pin.FpCMov.dst);
mapReg(m, &i->Pin.FpCMov.src);
@@ -2728,9 +2778,12 @@
case Pun_NEG: // neg r_dst,r_src
p =3D mkFormXO(p, 31, r_dst, r_src, 0, 0, 104, 0);
break;
- case Pun_CLZ: // cntlzw r_dst, r_src
+ case Pun_CLZ32: // cntlzw r_dst, r_src
p =3D mkFormX(p, 31, r_src, r_dst, 0, 26, 0);
break;
+ case Pun_CLZ64: // cntlzd r_dst, r_src
+ p =3D mkFormX(p, 31, r_src, r_dst, 0, 58, 0);
+ break;
default: goto bad;
}
goto done;
@@ -3147,6 +3200,44 @@
goto done;
}
=20
+ case Pin_FpF64toI64: {
+ UInt r_dst =3D iregNo(i->Pin.FpF64toI64.dst, mode64);
+ UInt fr_src =3D fregNo(i->Pin.FpF64toI64.src);
+ UChar fr_tmp =3D 7; // Temp freg
+ PPC32AMode* am_addr;
+
+ // fctid (conv f64 to i64), PPC64 p437
+ p =3D mkFormX(p, 63, fr_tmp, 0, fr_src, 814, 0);
+
+ am_addr =3D PPC32AMode_RR( StackFramePtr(mode64),
+ hregPPC_GPR0(mode64) );
+
+ // stfdx (store fp64), PPC64 p589
+ p =3D doAMode_RR(p, 31, 727, fr_tmp, am_addr, mode64);
+
+ // ldx (load int64), PPC64 p476
+ p =3D doAMode_RR(p, 31, 21, r_dst, am_addr, mode64);
+ goto done;
+ }
+
+ case Pin_FpI64toF64: {
+ UInt r_src =3D iregNo(i->Pin.FpI64toF64.src, mode64);
+ UInt fr_dst =3D fregNo(i->Pin.FpI64toF64.dst);
+ UChar fr_tmp =3D 7; // Temp freg
+ PPC32AMode* am_addr =3D PPC32AMode_RR( StackFramePtr(mode64),
+ hregPPC_GPR0(mode64) );
+
+ // stdx r_src,r0,r1
+ p =3D doAMode_RR(p, 31, 149, r_src, am_addr, mode64);
+
+ // lfdx fr7,r0,r1
+ p =3D doAMode_RR(p, 31, 599, fr_tmp, am_addr, mode64);
+
+ // fcfid (conv i64 to f64), PPC64 p434
+ p =3D mkFormX(p, 63, fr_dst, 0, fr_tmp, 846, 0);
+ goto done;
+ }
+
case Pin_FpCMov: {
UInt fr_dst =3D fregNo(i->Pin.FpCMov.dst);
UInt fr_src =3D fregNo(i->Pin.FpCMov.src);
Modified: trunk/priv/host-ppc32/hdefs.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/host-ppc32/hdefs.h 2005-12-22 03:01:17 UTC (rev 1502)
+++ trunk/priv/host-ppc32/hdefs.h 2005-12-22 14:32:35 UTC (rev 1503)
@@ -326,7 +326,8 @@
enum {
Pun_NEG,
Pun_NOT,
- Pun_CLZ
+ Pun_CLZ32,
+ Pun_CLZ64
}
PPC32UnaryOp;
=20
@@ -460,6 +461,8 @@
Pin_FpLdSt, /* FP load/store */
Pin_FpF64toF32, /* FP round IEEE754 double to IEEE754 single */
Pin_FpF64toI32, /* FP round IEEE754 double to 32-bit integer */
+ Pin_FpF64toI64, /* FP round IEEE754 double to 32-bit integer */
+ Pin_FpI64toF64, /* FP round IEEE754 64-bit integer to double */
Pin_FpCMov, /* FP floating point conditional move */
Pin_FpLdFPSCR, /* mtfsf */
Pin_FpCmp, /* FP compare, generating value into int reg */
@@ -645,6 +648,17 @@
HReg src;
HReg dst;
} FpF64toI32;
+ /* Ditto to 64-bit integer type. */
+ struct {
+ HReg src;
+ HReg dst;
+ } FpF64toI64;
+ /* By observing the current FPU rounding mode, reinterpret src =
from
+ a 64-bit integer to double type, and round into dst. */
+ struct {
+ HReg src;
+ HReg dst;
+ } FpI64toF64;
/* Mov src to dst on the given condition, which may not
be the bogus Xcc_ALWAYS. */
struct {
@@ -781,6 +795,8 @@
extern PPC32Instr* PPC32Instr_FpLdSt ( Bool isLoad, UChar sz, HReg, =
PPC32AMode* );
extern PPC32Instr* PPC32Instr_FpF64toF32 ( HReg dst, HReg src );
extern PPC32Instr* PPC32Instr_FpF64toI32 ( HReg dst, HReg src );
+extern PPC32Instr* PPC32Instr_FpF64toI64 ( HReg dst, HReg src );
+extern PPC32Instr* PPC32Instr_FpI64toF64 ( HReg dst, HReg src );
extern PPC32Instr* PPC32Instr_FpCMov ( PPC32CondCode, HReg dst, HReg=
src );
extern PPC32Instr* PPC32Instr_FpLdFPSCR ( HReg src );
extern PPC32Instr* PPC32Instr_FpCmp ( HReg dst, HReg srcL, HReg src=
R );
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-12-22 03:01:17 UTC (rev 1502)
+++ trunk/priv/host-ppc32/isel.c 2005-12-22 14:32:35 UTC (rev 1503)
@@ -786,13 +786,10 @@
static
void set_FPU_rounding_mode ( ISelEnv* env, IRExpr* mode )
{
- HReg fr_src =3D newVRegF(env);
+ HReg fr_src =3D newVRegF(env);
HReg r_src;
=20
- if (mode64)
- vassert(typeOfIRExpr(env->type_env,mode) =3D=3D Ity_I64);
- else
- vassert(typeOfIRExpr(env->type_env,mode) =3D=3D Ity_I32);
+ vassert(typeOfIRExpr(env->type_env,mode) =3D=3D Ity_I32);
=20
/* Only supporting the rounding-mode bits - the rest of FPSCR is 0x0
- so we can set the whole register at once (faster)
@@ -1324,7 +1321,22 @@
return r_dst;
}
=20
+ if (e->Iex.Binop.op =3D=3D Iop_F64toI64) {
+ HReg fr_src =3D iselDblExpr(env, e->Iex.Binop.arg2);
+ HReg r_dst =3D newVRegI(env); =20
+ /* Set host rounding mode */
+ set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
=20
+ sub_from_sp( env, 16 );
+ addInstr(env, PPC32Instr_FpF64toI64(r_dst, fr_src));
+ add_to_sp( env, 16 );
+
+ /* Restore default FPU rounding. */
+ set_FPU_rounding_default( env );
+ return r_dst;
+ }
+
+
//.. /* C3210 flags following FPU partial remainder (fprem), both
//.. IEEE compliant (PREM1) and non-IEEE compliant (PREM). */
//.. if (e->Iex.Binop.op =3D=3D Iop_PRemC3210F64
@@ -1538,19 +1550,14 @@
r_dst, r_dst, PPC32RH_Imm(False,3=
1)));
return r_dst;
}
-
-//.. case Iop_Ctz32: {
-//.. /* Count trailing zeroes, implemented by x86 'bsfl' */
-//.. HReg dst =3D newVRegI32(env);
-//.. HReg src =3D iselIntExpr_R(env, e->Iex.Unop.arg);
-//.. addInstr(env, X86Instr_Bsfr32(True,src,dst));
-//.. return dst;
-//.. }
- case Iop_Clz32: {
+ case Iop_Clz32:
+ case Iop_Clz64: {
+ PPC32UnaryOp op_clz =3D
+ (e->Iex.Unop.op =3D=3D Iop_Clz32) ? Pun_CLZ32 : Pun_CLZ64;
/* Count leading zeroes. */
HReg r_dst =3D newVRegI(env);
HReg r_src =3D iselIntExpr_R(env, e->Iex.Unop.arg);
- addInstr(env, PPC32Instr_Unary(Pun_CLZ,r_dst,r_src));
+ addInstr(env, PPC32Instr_Unary(op_clz,r_dst,r_src));
return r_dst;
}
case Iop_Neg8:
@@ -1590,6 +1597,27 @@
/* These are no-ops. */
return iselIntExpr_R(env, e->Iex.Unop.arg);
=20
+ /* ReinterpF64asI64(e) */
+ /* Given an IEEE754 double, produce an I64 with the same bit
+ pattern. */
+ case Iop_ReinterpF64asI64: {
+ PPC32AMode *am_addr;
+ HReg fr_src =3D iselDblExpr(env, e->Iex.Unop.arg);
+ HReg r_dst =3D newVRegI(env);
+ vassert(mode64);
+
+ sub_from_sp( env, 16 ); // Move SP down 16 bytes
+ am_addr =3D PPC32AMode_IR(0, StackFramePtr(mode64));
+
+ // store as F64
+ addInstr(env, PPC32Instr_FpLdSt( False/*store*/, 8, fr_src, am_=
addr ));
+ // load as Ity_I64
+ addInstr(env, PPC32Instr_Load( 8, False, r_dst, am_addr, mode64=
));
+
+ add_to_sp( env, 16 ); // Reset SP
+ return r_dst;
+ }
+
default:=20
break;
}
@@ -3159,18 +3187,16 @@
else
vpanic("iselDblExpr(ppc32): const");
=20
- if (mode64) {
- HReg r_src =3D newVRegI(env);
- vassert(0);
- // AWAITING TEST CASE
- addInstr(env, PPC32Instr_LI(r_src, u.u64, mode64));
- return mk_LoadR64toFPR( env, r_src ); // 1*I64 -> F64
- } else { // mode32
+ if (!mode64) {
HReg r_srcHi =3D newVRegI(env);
HReg r_srcLo =3D newVRegI(env);
addInstr(env, PPC32Instr_LI(r_srcHi, u.u32x2[1], mode64));
addInstr(env, PPC32Instr_LI(r_srcLo, u.u32x2[0], mode64));
return mk_LoadRR32toFPR( env, r_srcHi, r_srcLo );
+ } else { // mode64
+ HReg r_src =3D newVRegI(env);
+ addInstr(env, PPC32Instr_LI(r_src, u.u64, mode64));
+ return mk_LoadR64toFPR( env, r_src ); // 1*I64 -> F64
}
}
=20
@@ -3217,6 +3243,23 @@
addInstr(env, PPC32Instr_FpBinary(fpop, r_dst, r_srcL, r_srcR))=
;
return r_dst;
}
+
+ if (e->Iex.Binop.op =3D=3D Iop_I64toF64) {
+ HReg fr_dst =3D newVRegF(env);
+ HReg r_src =3D iselIntExpr_R(env, e->Iex.Binop.arg2);
+ vassert(mode64);
+
+ /* Set host rounding mode */
+ set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
+
+ sub_from_sp( env, 16 );
+ addInstr(env, PPC32Instr_FpI64toF64(fr_dst, r_src));
+ add_to_sp( env, 16 );
+
+ /* Restore default FPU rounding. */
+ set_FPU_rounding_default( env );
+ return fr_dst;
+ }
}
=20
//.. if (e->tag =3D=3D Iex_Binop && e->Iex.Binop.op =3D=3D Iop_RoundF=
64) {
@@ -3299,6 +3342,7 @@
//.. add_to_esp(env, 4);
//.. return dst;
//.. }
+
case Iop_ReinterpI64asF64: {
/* Given an I64, produce an IEEE754 double with the same
bit pattern. */
@@ -3307,8 +3351,8 @@
iselInt64Expr( &r_srcHi, &r_srcLo, env, e->Iex.Unop.arg);
return mk_LoadRR32toFPR( env, r_srcHi, r_srcLo );
} else {
- // TODO
- vassert(0);
+ HReg r_src =3D iselIntExpr_R(env, e->Iex.Unop.arg);
+ return mk_LoadR64toFPR( env, r_src );
}
}
case Iop_F32toF64: {
|