First pass at VEX support of ppc64.
git-svn-id: svn://svn.valgrind.org/vex/trunk@1475 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/Makefile b/Makefile
index b7dd71e..d47403a 100644
--- a/Makefile
+++ b/Makefile
@@ -130,6 +130,12 @@
if [ ! -f TAG_ppc32_linux ] ; then rm -f $(LIB_OBJS) TAG_* libvex.a ; fi
touch TAG_ppc32_linux
+libvex_ppc64_linux.a: TAG_ppc64_linux libvex.a
+ mv -f libvex.a libvex_ppc64_linux.a
+TAG_ppc64_linux:
+ if [ ! -f TAG_ppc64_linux ] ; then rm -f $(LIB_OBJS) TAG_* libvex.a ; fi
+ touch TAG_ppc64_linux
+
# This doesn't get rid of priv/main/vex_svnversion.h, because
# that can't be regenerated in the final Valgrind tarball, and
diff --git a/auxprogs/genoffsets.c b/auxprogs/genoffsets.c
index 9e56f5e..9d220bd 100644
--- a/auxprogs/genoffsets.c
+++ b/auxprogs/genoffsets.c
@@ -52,6 +52,7 @@
#include "../pub/libvex_guest_x86.h"
#include "../pub/libvex_guest_amd64.h"
#include "../pub/libvex_guest_ppc32.h"
+#include "../pub/libvex_guest_ppc64.h"
Int main ( void )
{
@@ -168,5 +169,35 @@
printf("\n");
+ // ppc64
+ printf("#define OFFSET_ppc64_GPR0 %3d\n",
+ offsetof(VexGuestPPC64State,guest_GPR0));
+
+ printf("#define OFFSET_ppc64_GPR3 %3d\n",
+ offsetof(VexGuestPPC64State,guest_GPR3));
+
+ printf("#define OFFSET_ppc64_GPR4 %3d\n",
+ offsetof(VexGuestPPC64State,guest_GPR4));
+
+ printf("#define OFFSET_ppc64_GPR5 %3d\n",
+ offsetof(VexGuestPPC64State,guest_GPR5));
+
+ printf("#define OFFSET_ppc64_GPR6 %3d\n",
+ offsetof(VexGuestPPC64State,guest_GPR6));
+
+ printf("#define OFFSET_ppc64_GPR7 %3d\n",
+ offsetof(VexGuestPPC64State,guest_GPR7));
+
+ printf("#define OFFSET_ppc64_GPR8 %3d\n",
+ offsetof(VexGuestPPC64State,guest_GPR8));
+
+ printf("#define OFFSET_ppc64_CIA %3d\n",
+ offsetof(VexGuestPPC64State,guest_CIA));
+
+ printf("#define OFFSET_ppc64_CR0_0 %3d\n",
+ offsetof(VexGuestPPC64State,guest_CR0_0));
+
+ printf("\n");
+
return 0;
}
diff --git a/priv/guest-ppc32/ghelpers.c b/priv/guest-ppc32/ghelpers.c
index 7a40b3c..2cf0b1b 100644
--- a/priv/guest-ppc32/ghelpers.c
+++ b/priv/guest-ppc32/ghelpers.c
@@ -47,6 +47,7 @@
#include "libvex_basictypes.h"
#include "libvex_emwarn.h"
#include "libvex_guest_ppc32.h"
+#include "libvex_guest_ppc64.h"
#include "libvex_ir.h"
#include "libvex.h"
@@ -55,11 +56,10 @@
#include "guest-ppc32/gdefs.h"
-/* This file contains helper functions for ppc32 guest code.
- Calls to these functions are generated by the back end.
- These calls are of course in the host machine code and
- this file will be compiled to host machine code, so that
- all makes sense.
+/* This file contains helper functions for ppc32 and ppc64 guest code.
+ Calls to these functions are generated by the back end. These
+ calls are of course in the host machine code and this file will be
+ compiled to host machine code, so that all makes sense.
Only change the signatures of these helper functions very
carefully. If you change the signature here, you'll have to change
@@ -163,6 +163,27 @@
/* VISIBLE TO LIBVEX CLIENT */
+/* Note: %CR is 32 bits even for ppc64 */
+UInt LibVEX_GuestPPC64_get_CR ( /*IN*/VexGuestPPC64State* vex_state )
+{
+# define FIELD(_n) \
+ ( ( (UInt) \
+ ( (vex_state->guest_CR##_n##_321 & (7<<1)) \
+ | (vex_state->guest_CR##_n##_0 & 1) \
+ ) \
+ ) \
+ << (4 * (7-(_n))) \
+ )
+
+ return
+ FIELD(0) | FIELD(1) | FIELD(2) | FIELD(3)
+ | FIELD(4) | FIELD(5) | FIELD(6) | FIELD(7);
+
+# undef FIELD
+}
+
+
+/* VISIBLE TO LIBVEX CLIENT */
void LibVEX_GuestPPC32_put_CR ( UInt cr_native,
/*OUT*/VexGuestPPC32State* vex_state )
{
@@ -189,6 +210,33 @@
/* VISIBLE TO LIBVEX CLIENT */
+/* Note: %CR is 32 bits even for ppc64 */
+void LibVEX_GuestPPC64_put_CR ( UInt cr_native,
+ /*OUT*/VexGuestPPC64State* vex_state )
+{
+ UInt t;
+
+# define FIELD(_n) \
+ do { \
+ t = cr_native >> (4*(7-(_n))); \
+ vex_state->guest_CR##_n##_0 = toUChar(t & 1); \
+ vex_state->guest_CR##_n##_321 = toUChar(t & (7<<1)); \
+ } while (0)
+
+ FIELD(0);
+ FIELD(1);
+ FIELD(2);
+ FIELD(3);
+ FIELD(4);
+ FIELD(5);
+ FIELD(6);
+ FIELD(7);
+
+# undef FIELD
+}
+
+
+/* VISIBLE TO LIBVEX CLIENT */
UInt LibVEX_GuestPPC32_get_XER ( /*IN*/VexGuestPPC32State* vex_state )
{
UInt w = 0;
@@ -201,6 +249,19 @@
/* VISIBLE TO LIBVEX CLIENT */
+/* Note: %XER is 32 bits even for ppc64 */
+UInt LibVEX_GuestPPC64_get_XER ( /*IN*/VexGuestPPC64State* vex_state )
+{
+ UInt w = 0;
+ w |= ( ((UInt)vex_state->guest_XER_BC) & 0xFF );
+ w |= ( (((UInt)vex_state->guest_XER_SO) & 0x1) << 31 );
+ w |= ( (((UInt)vex_state->guest_XER_OV) & 0x1) << 30 );
+ w |= ( (((UInt)vex_state->guest_XER_CA) & 0x1) << 29 );
+ return w;
+}
+
+
+/* VISIBLE TO LIBVEX CLIENT */
void LibVEX_GuestPPC32_put_XER ( UInt xer_native,
/*OUT*/VexGuestPPC32State* vex_state )
{
@@ -359,6 +420,154 @@
}
+/* VISIBLE TO LIBVEX CLIENT */
+void LibVEX_GuestPPC64_initialise ( /*OUT*/VexGuestPPC64State* vex_state )
+{
+ vex_state->guest_GPR0 = 0;
+ vex_state->guest_GPR1 = 0;
+ vex_state->guest_GPR2 = 0;
+ vex_state->guest_GPR3 = 0;
+ vex_state->guest_GPR4 = 0;
+ vex_state->guest_GPR5 = 0;
+ vex_state->guest_GPR6 = 0;
+ vex_state->guest_GPR7 = 0;
+ vex_state->guest_GPR8 = 0;
+ vex_state->guest_GPR9 = 0;
+ vex_state->guest_GPR10 = 0;
+ vex_state->guest_GPR11 = 0;
+ vex_state->guest_GPR12 = 0;
+ vex_state->guest_GPR13 = 0;
+ vex_state->guest_GPR14 = 0;
+ vex_state->guest_GPR15 = 0;
+ vex_state->guest_GPR16 = 0;
+ vex_state->guest_GPR17 = 0;
+ vex_state->guest_GPR18 = 0;
+ vex_state->guest_GPR19 = 0;
+ vex_state->guest_GPR20 = 0;
+ vex_state->guest_GPR21 = 0;
+ vex_state->guest_GPR22 = 0;
+ vex_state->guest_GPR23 = 0;
+ vex_state->guest_GPR24 = 0;
+ vex_state->guest_GPR25 = 0;
+ vex_state->guest_GPR26 = 0;
+ vex_state->guest_GPR27 = 0;
+ vex_state->guest_GPR28 = 0;
+ vex_state->guest_GPR29 = 0;
+ vex_state->guest_GPR30 = 0;
+ vex_state->guest_GPR31 = 0;
+
+ vex_state->guest_FPR0 = 0;
+ vex_state->guest_FPR1 = 0;
+ vex_state->guest_FPR2 = 0;
+ vex_state->guest_FPR3 = 0;
+ vex_state->guest_FPR4 = 0;
+ vex_state->guest_FPR5 = 0;
+ vex_state->guest_FPR6 = 0;
+ vex_state->guest_FPR7 = 0;
+ vex_state->guest_FPR8 = 0;
+ vex_state->guest_FPR9 = 0;
+ vex_state->guest_FPR10 = 0;
+ vex_state->guest_FPR11 = 0;
+ vex_state->guest_FPR12 = 0;
+ vex_state->guest_FPR13 = 0;
+ vex_state->guest_FPR14 = 0;
+ vex_state->guest_FPR15 = 0;
+ vex_state->guest_FPR16 = 0;
+ vex_state->guest_FPR17 = 0;
+ vex_state->guest_FPR18 = 0;
+ vex_state->guest_FPR19 = 0;
+ vex_state->guest_FPR20 = 0;
+ vex_state->guest_FPR21 = 0;
+ vex_state->guest_FPR22 = 0;
+ vex_state->guest_FPR23 = 0;
+ vex_state->guest_FPR24 = 0;
+ vex_state->guest_FPR25 = 0;
+ vex_state->guest_FPR26 = 0;
+ vex_state->guest_FPR27 = 0;
+ vex_state->guest_FPR28 = 0;
+ vex_state->guest_FPR29 = 0;
+ vex_state->guest_FPR30 = 0;
+ vex_state->guest_FPR31 = 0;
+
+ /* Initialise the vector state. */
+# define VECZERO(_vr) _vr[0]=_vr[1]=_vr[2]=_vr[3] = 0;
+
+ VECZERO(vex_state->guest_VR0 );
+ VECZERO(vex_state->guest_VR1 );
+ VECZERO(vex_state->guest_VR2 );
+ VECZERO(vex_state->guest_VR3 );
+ VECZERO(vex_state->guest_VR4 );
+ VECZERO(vex_state->guest_VR5 );
+ VECZERO(vex_state->guest_VR6 );
+ VECZERO(vex_state->guest_VR7 );
+ VECZERO(vex_state->guest_VR8 );
+ VECZERO(vex_state->guest_VR9 );
+ VECZERO(vex_state->guest_VR10);
+ VECZERO(vex_state->guest_VR11);
+ VECZERO(vex_state->guest_VR12);
+ VECZERO(vex_state->guest_VR13);
+ VECZERO(vex_state->guest_VR14);
+ VECZERO(vex_state->guest_VR15);
+ VECZERO(vex_state->guest_VR16);
+ VECZERO(vex_state->guest_VR17);
+ VECZERO(vex_state->guest_VR18);
+ VECZERO(vex_state->guest_VR19);
+ VECZERO(vex_state->guest_VR20);
+ VECZERO(vex_state->guest_VR21);
+ VECZERO(vex_state->guest_VR22);
+ VECZERO(vex_state->guest_VR23);
+ VECZERO(vex_state->guest_VR24);
+ VECZERO(vex_state->guest_VR25);
+ VECZERO(vex_state->guest_VR26);
+ VECZERO(vex_state->guest_VR27);
+ VECZERO(vex_state->guest_VR28);
+ VECZERO(vex_state->guest_VR29);
+ VECZERO(vex_state->guest_VR30);
+ VECZERO(vex_state->guest_VR31);
+
+# undef VECZERO
+
+ vex_state->guest_CIA = 0;
+ vex_state->guest_LR = 0;
+ vex_state->guest_CTR = 0;
+
+ vex_state->guest_XER_SO = 0;
+ vex_state->guest_XER_OV = 0;
+ vex_state->guest_XER_CA = 0;
+ vex_state->guest_XER_BC = 0;
+
+ vex_state->guest_CR0_321 = 0;
+ vex_state->guest_CR0_0 = 0;
+ vex_state->guest_CR1_321 = 0;
+ vex_state->guest_CR1_0 = 0;
+ vex_state->guest_CR2_321 = 0;
+ vex_state->guest_CR2_0 = 0;
+ vex_state->guest_CR3_321 = 0;
+ vex_state->guest_CR3_0 = 0;
+ vex_state->guest_CR4_321 = 0;
+ vex_state->guest_CR4_0 = 0;
+ vex_state->guest_CR5_321 = 0;
+ vex_state->guest_CR5_0 = 0;
+ vex_state->guest_CR6_321 = 0;
+ vex_state->guest_CR6_0 = 0;
+ vex_state->guest_CR7_321 = 0;
+ vex_state->guest_CR7_0 = 0;
+
+ vex_state->guest_FPROUND = (UInt)PPC32rm_NEAREST;
+
+ vex_state->guest_VRSAVE = 0;
+
+ vex_state->guest_VSCR = 0x0; // Non-Java mode = 0
+
+ vex_state->guest_EMWARN = EmWarn_NONE;
+
+ vex_state->guest_TISTART = 0;
+ vex_state->guest_TILEN = 0;
+
+ vex_state->guest_RESVN = 0;
+}
+
+
/*-----------------------------------------------------------*/
/*--- Describing the ppc32 guest state, for the benefit ---*/
/*--- of iropt and instrumenters. ---*/
diff --git a/priv/guest-ppc32/toIR.c b/priv/guest-ppc32/toIR.c
index f601f7c..f84a768 100644
--- a/priv/guest-ppc32/toIR.c
+++ b/priv/guest-ppc32/toIR.c
@@ -78,34 +78,34 @@
*/
-/* Translates PPC32 code to IR. */
+/* Translates PPC32 & PPC64 code to IR. */
/* References
#define PPC32
"PowerPC Microprocessor Family:
- The Programming Environments for 32-Bit Microprocessors"
+ The Programming Environments Manual for 32-Bit Microprocessors"
02/21/2000
http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF778525699600719DF2
+#define PPC64
+ "PowerPC Microprocessor Family:
+ Programming Environments Manual for 64-Bit Microprocessors"
+ 06/10/2003
+ http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/F7E732FF811F783187256FDD004D3797
+
#define AV
"PowerPC Microprocessor Family:
AltiVec(TM) Technology Programming Environments Manual"
07/10/2003
http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/FBFA164F824370F987256D6A006F424D
-
- Other refs:
- "PowerPC Microprocessor Family:
- Programming Environments Manual for 64 and 32-Bit Microprocessors
- Version 2.0"
- 06/10/2003
- http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/F6153E213FDD912E87256D49006C6541
*/
#include "libvex_basictypes.h"
#include "libvex_ir.h"
#include "libvex.h"
#include "libvex_guest_ppc32.h"
+#include "libvex_guest_ppc64.h"
#include "main/vex_util.h"
#include "main/vex_globals.h"
@@ -129,21 +129,24 @@
static UChar* guest_code;
/* The guest address corresponding to guest_code[0]. */
-static Addr32 guest_CIA_bbstart;
+static Addr64 guest_CIA_bbstart;
/* The guest address for the instruction currently being
translated. */
-static Addr32 guest_CIA_curr_instr;
+static Addr64 guest_CIA_curr_instr;
/* The IRBB* into which we're generating code. */
static IRBB* irbb;
+/* Is our guest binary 32 or 64bit? */
+static Bool mode64;
+
/*------------------------------------------------------------*/
/*--- Debugging output ---*/
/*------------------------------------------------------------*/
-#define PPC32_TOIR_DEBUG 0
+#define PPC_TOIR_DEBUG 0
#define DIP(format, args...) \
if (vex_traceflags & VEX_TRACE_FE) \
@@ -153,11 +156,11 @@
if (vex_traceflags & VEX_TRACE_FE) \
vex_sprintf(buf, format, ## args)
-#if PPC32_TOIR_DEBUG
-static void vex_printf_binary( UInt x, UInt len, Bool spaces )
+#if PPC_TOIR_DEBUG
+static void vex_printf_binary( ULong x, UInt len, Bool spaces )
{
UInt i;
- vassert(len > 0 && len <= 32);
+ vassert(len > 0 && len <= 64);
for (i=len; i>0; i--) {
vex_printf("%d", ((x & (1<<(len-1))) != 0) );
@@ -171,29 +174,52 @@
/*------------------------------------------------------------*/
-/*--- Offsets of various parts of the ppc32 guest state. ---*/
+/*--- Offsets of various parts of the ppc32/64 guest state ---*/
/*------------------------------------------------------------*/
-#define OFFB_CIA offsetof(VexGuestPPC32State,guest_CIA)
-#define OFFB_LR offsetof(VexGuestPPC32State,guest_LR)
-#define OFFB_CTR offsetof(VexGuestPPC32State,guest_CTR)
+// 64-bit offsets
+#define OFFB64_CIA offsetof(VexGuestPPC64State,guest_CIA)
+#define OFFB64_LR offsetof(VexGuestPPC64State,guest_LR)
+#define OFFB64_CTR offsetof(VexGuestPPC64State,guest_CTR)
-#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)
+#define OFFB64_XER_SO offsetof(VexGuestPPC64State,guest_XER_SO)
+#define OFFB64_XER_OV offsetof(VexGuestPPC64State,guest_XER_OV)
+#define OFFB64_XER_CA offsetof(VexGuestPPC64State,guest_XER_CA)
+#define OFFB64_XER_BC offsetof(VexGuestPPC64State,guest_XER_BC)
-#define OFFB_FPROUND offsetof(VexGuestPPC32State,guest_FPROUND)
+#define OFFB64_FPROUND offsetof(VexGuestPPC64State,guest_FPROUND)
-#define OFFB_VRSAVE offsetof(VexGuestPPC32State,guest_VRSAVE)
-#define OFFB_VSCR offsetof(VexGuestPPC32State,guest_VSCR)
+#define OFFB64_VRSAVE offsetof(VexGuestPPC64State,guest_VRSAVE)
+#define OFFB64_VSCR offsetof(VexGuestPPC64State,guest_VSCR)
-#define OFFB_EMWARN offsetof(VexGuestPPC32State,guest_EMWARN)
+#define OFFB64_EMWARN offsetof(VexGuestPPC64State,guest_EMWARN)
-#define OFFB_TISTART offsetof(VexGuestPPC32State,guest_TISTART)
-#define OFFB_TILEN offsetof(VexGuestPPC32State,guest_TILEN)
+#define OFFB64_TISTART offsetof(VexGuestPPC64State,guest_TISTART)
+#define OFFB64_TILEN offsetof(VexGuestPPC64State,guest_TILEN)
-#define OFFB_RESVN offsetof(VexGuestPPC32State,guest_RESVN)
+#define OFFB64_RESVN offsetof(VexGuestPPC64State,guest_RESVN)
+
+// 32-bit offsets
+#define OFFB32_CIA offsetof(VexGuestPPC32State,guest_CIA)
+#define OFFB32_LR offsetof(VexGuestPPC32State,guest_LR)
+#define OFFB32_CTR offsetof(VexGuestPPC32State,guest_CTR)
+
+#define OFFB32_XER_SO offsetof(VexGuestPPC32State,guest_XER_SO)
+#define OFFB32_XER_OV offsetof(VexGuestPPC32State,guest_XER_OV)
+#define OFFB32_XER_CA offsetof(VexGuestPPC32State,guest_XER_CA)
+#define OFFB32_XER_BC offsetof(VexGuestPPC32State,guest_XER_BC)
+
+#define OFFB32_FPROUND offsetof(VexGuestPPC32State,guest_FPROUND)
+
+#define OFFB32_VRSAVE offsetof(VexGuestPPC32State,guest_VRSAVE)
+#define OFFB32_VSCR offsetof(VexGuestPPC32State,guest_VSCR)
+
+#define OFFB32_EMWARN offsetof(VexGuestPPC32State,guest_EMWARN)
+
+#define OFFB32_TISTART offsetof(VexGuestPPC32State,guest_TISTART)
+#define OFFB32_TILEN offsetof(VexGuestPPC32State,guest_TILEN)
+
+#define OFFB32_RESVN offsetof(VexGuestPPC32State,guest_RESVN)
/*------------------------------------------------------------*/
@@ -263,35 +289,31 @@
return instr & 0xFFFF;
}
-/* Extract bottom half, instr[15:0], and sign extent to 32 bits */
-static Int ifieldSIMM16 ( UInt instr ) {
- Int i = instr & 0xFFFF;
- return (i << 16) >> 16;
-}
-
-/* Extract bottom 26 bits, instr[25:0], and sign extent to 32 bits */
-static Int ifieldSIMM26 ( UInt instr ) {
- Int i = instr & 0x3FFFFFF;
- return (i << 6) >> 6;
+/* Extract unsigned bottom 26 bits, instr[25:0] */
+static UInt ifieldUIMM26 ( UInt instr ) {
+ return instr & 0x3FFFFFF;
}
/*------------------------------------------------------------*/
-/*--- Special purpose registers (SPRs) ---*/
-/*--- All non-GPR/FPRs, not only strict SPR's {XER,LR,CTR} ---*/
+/*--- Guest-state identifiers ---*/
/*------------------------------------------------------------*/
typedef enum {
- PPC32_SPR_CIA, // Current Instruction Address
- PPC32_SPR_LR, // Link Register
- PPC32_SPR_CTR, // Count 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;
+ PPC_GST_CIA, // Current Instruction Address
+ PPC_GST_LR, // Link Register
+ PPC_GST_CTR, // Count Register
+ PPC_GST_XER, // Overflow, carry flags, byte count
+ PPC_GST_CR, // Condition Register
+ PPC_GST_FPSCR, // Floating Point Status/Control Register
+ PPC_GST_VRSAVE, // Vector Save/Restore Register
+ PPC_GST_VSCR, // Vector Status and Control Register
+ PPC_GST_EMWARN, // Emulation warnings
+ PPC_GST_TISTART,// For icbi: start of area to invalidate
+ PPC_GST_TILEN, // For icbi: length of area to invalidate
+ PPC_GST_RESVN, // For lwarx/stwcx.
+ PPC_GST_MAX
+} PPC_GST;
#define MASK_FPSCR_RN 0x3
#define MASK_VSCR_VALID 0x00010001
@@ -301,8 +323,6 @@
/*--- FP Helpers ---*/
/*------------------------------------------------------------*/
-static void put_emwarn ( IRExpr* e /* :: Ity_I32 */ );
-
/* Produce the 32-bit pattern corresponding to the supplied
float. */
static UInt float_to_bits ( Float f )
@@ -320,8 +340,12 @@
/*--- Misc Helpers ---*/
/*------------------------------------------------------------*/
-static UInt MASK( UInt begin, UInt end )
+/* Generate mask with 1's from 'begin' through 'end' (0=lsb),
+ wrapping if begin > end. */
+static UInt MASK32( UInt begin, UInt end )
{
+ vassert(begin < 32);
+ vassert(end < 32);
UInt m1 = ((UInt)(-1)) << begin;
UInt m2 = ((UInt)(-1)) << (end + 1);
UInt mask = m1 ^ m2;
@@ -329,10 +353,23 @@
return mask;
}
+static ULong MASK64( UInt begin, UInt end )
+{
+ vassert(begin < 64);
+ vassert(end < 64);
+ ULong m1 = ((ULong)(-1)) << begin;
+ ULong m2 = ((ULong)(-1)) << (end + 1);
+ ULong mask = m1 ^ m2;
+ if (begin > end) mask = ~mask; // wrap mask
+ return mask;
+}
+
+static Addr64 nextInsnAddr() { return guest_CIA_curr_instr + 4; }
+
/*------------------------------------------------------------*/
/*--- Helper bits and pieces for deconstructing the ---*/
-/*--- ppc32 insn stream. ---*/
+/*--- ppc32/64 insn stream. ---*/
/*------------------------------------------------------------*/
/* Add a statement to the list held by "irbb". */
@@ -365,6 +402,28 @@
return (UInt)((((Int)x) << 16) >> 16);
}
+#if 0
+static UInt extend_s_26to32 ( UInt x )
+{
+ return (UInt)((((Int)x) << 6) >> 6);
+}
+#endif
+
+static ULong extend_s_16to64 ( UInt x )
+{
+ return (ULong)((((Long)x) << 48) >> 48);
+}
+
+static ULong extend_s_26to64 ( UInt x )
+{
+ return (ULong)((((Long)x) << 38) >> 38);
+}
+
+static ULong extend_s_32to64 ( UInt x )
+{
+ return (ULong)((((Long)x) << 32) >> 32);
+}
+
/* Do a big-endian load of a 32-bit word, regardless of the endianness
of the underlying host. */
static UInt getUIntBigendianly ( UChar* p )
@@ -389,7 +448,8 @@
static void storeBE ( IRExpr* addr, IRExpr* data )
{
- vassert(typeOfIRExpr(irbb->tyenv, addr) == Ity_I32);
+ vassert(typeOfIRExpr(irbb->tyenv, addr) == Ity_I32 ||
+ typeOfIRExpr(irbb->tyenv, addr) == Ity_I64);
stmt( IRStmt_Store(Iend_BE,addr,data) );
}
@@ -677,6 +737,117 @@
binop(Iop_ShrV128, expr_vA, mkU8(16)), \
binop(Iop_ShrV128, expr_vB, mkU8(16)))
+/* */
+static IRExpr* /* :: Ity_I64 */ mkExtendLoS32 ( IRExpr* src )
+{
+ vassert(typeOfIRExpr(irbb->tyenv, src) == Ity_I64);
+ return unop(Iop_32Sto64, unop(Iop_64to32, src));
+}
+
+static IROp mkSizedOp ( IRType ty, IROp op8 )
+{
+ Int adj;
+ vassert(ty == Ity_I8 || ty == Ity_I16 ||
+ ty == Ity_I32 || ty == Ity_I64);
+ vassert(op8 == Iop_Add8 || op8 == Iop_Sub8 || op8 == Iop_Mul8 ||
+ op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8 ||
+ op8 == Iop_Shl8 || op8 == Iop_Shr8 || op8 == Iop_Sar8 ||
+ op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 ||
+ op8 == Iop_Not8 || op8 == Iop_Neg8 );
+ adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : (ty==Ity_I32 ? 2 : 3));
+ return adj + op8;
+}
+
+/* Make sure we get valid 32 and 64bit addresses
+ CAB: do we ever get -ve addresses/offsets?
+*/
+static Addr64 mkSizedAddr ( IRType ty, Addr64 addr )
+{
+ vassert(ty == Ity_I32 || ty == Ity_I64);
+ return ( ty == Ity_I64 ?
+ (Addr64)addr :
+ (Addr64)extend_s_32to64( toUInt(addr) ) );
+}
+
+/* sz, ULong -> IRExpr */
+static IRExpr* mkSizedImm ( IRType ty, ULong imm64 )
+{
+ vassert(ty == Ity_I32 || ty == Ity_I64);
+ return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt)imm64);
+}
+
+/* sz, ULong -> IRConst */
+static IRConst* mkSizedConst ( IRType ty, ULong imm64 )
+{
+ vassert(ty == Ity_I32 || ty == Ity_I64);
+ return ( ty == Ity_I64 ?
+ IRConst_U64(imm64) :
+ IRConst_U32((UInt)imm64) );
+}
+
+/* Sign extend imm16 -> IRExpr* */
+static IRExpr* mkSizedExtendS16 ( IRType ty, UInt imm16 )
+{
+ vassert(ty == Ity_I32 || ty == Ity_I64);
+ return ( ty == Ity_I64 ?
+ mkU64(extend_s_16to64(imm16)) :
+ mkU32(extend_s_16to32(imm16)) );
+}
+
+/* Sign extend imm32 -> IRExpr* */
+static IRExpr* mkSizedExtendS32 ( IRType ty, UInt imm32 )
+{
+ vassert(ty == Ity_I32 || ty == Ity_I64);
+ return ( ty == Ity_I64 ?
+ mkU64(extend_s_32to64(imm32)) :
+ mkU32(imm32) );
+}
+
+/* IR narrows I32/I64 -> I8/I16/I32 */
+static IRExpr* mkSizedNarrow8 ( IRType ty, IRExpr* src )
+{
+ vassert(ty == Ity_I32 || ty == Ity_I64);
+ return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src);
+}
+
+static IRExpr* mkSizedNarrow16 ( IRType ty, IRExpr* src )
+{
+ vassert(ty == Ity_I32 || ty == Ity_I64);
+ return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src);
+}
+
+static IRExpr* mkSizedNarrow32 ( IRType ty, IRExpr* src )
+{
+ vassert(ty == Ity_I32 || ty == Ity_I64);
+ return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
+}
+
+/* Signed/Unsigned IR widens I8/I16/I32 -> I32/I64 */
+static IRExpr* mkSizedWiden8 ( IRType ty, IRExpr* src, Bool sined )
+{
+ vassert(ty == Ity_I32 || ty == Ity_I64);
+ IROp op;
+ if (sined) op = (ty==Ity_I32) ? Iop_8Sto32 : Iop_8Sto64;
+ else op = (ty==Ity_I32) ? Iop_8Uto32 : Iop_8Uto64;
+ return unop(op, src);
+}
+
+static IRExpr* mkSizedWiden16 ( IRType ty, IRExpr* src, Bool sined )
+{
+ vassert(ty == Ity_I32 || ty == Ity_I64);
+ IROp op;
+ if (sined) op = (ty==Ity_I32) ? Iop_16Sto32 : Iop_16Sto64;
+ else op = (ty==Ity_I32) ? Iop_16Uto32 : Iop_16Uto64;
+ return unop(op, src);
+}
+
+static IRExpr* mkSizedWiden32 ( IRType ty, IRExpr* src, Bool sined )
+{
+ vassert(ty == Ity_I32 || ty == Ity_I64);
+ if (ty == Ity_I32)
+ return src;
+ return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src);
+}
static Int integerGuestRegOffset ( UInt archreg )
@@ -688,7 +859,44 @@
// later: this might affect Altivec though?
vassert(host_is_bigendian);
- switch (archreg) {
+ if (mode64) {
+ switch (archreg) {
+ case 0: return offsetof(VexGuestPPC64State, guest_GPR0);
+ case 1: return offsetof(VexGuestPPC64State, guest_GPR1);
+ case 2: return offsetof(VexGuestPPC64State, guest_GPR2);
+ case 3: return offsetof(VexGuestPPC64State, guest_GPR3);
+ case 4: return offsetof(VexGuestPPC64State, guest_GPR4);
+ case 5: return offsetof(VexGuestPPC64State, guest_GPR5);
+ case 6: return offsetof(VexGuestPPC64State, guest_GPR6);
+ case 7: return offsetof(VexGuestPPC64State, guest_GPR7);
+ case 8: return offsetof(VexGuestPPC64State, guest_GPR8);
+ case 9: return offsetof(VexGuestPPC64State, guest_GPR9);
+ case 10: return offsetof(VexGuestPPC64State, guest_GPR10);
+ case 11: return offsetof(VexGuestPPC64State, guest_GPR11);
+ case 12: return offsetof(VexGuestPPC64State, guest_GPR12);
+ case 13: return offsetof(VexGuestPPC64State, guest_GPR13);
+ case 14: return offsetof(VexGuestPPC64State, guest_GPR14);
+ case 15: return offsetof(VexGuestPPC64State, guest_GPR15);
+ case 16: return offsetof(VexGuestPPC64State, guest_GPR16);
+ case 17: return offsetof(VexGuestPPC64State, guest_GPR17);
+ case 18: return offsetof(VexGuestPPC64State, guest_GPR18);
+ case 19: return offsetof(VexGuestPPC64State, guest_GPR19);
+ case 20: return offsetof(VexGuestPPC64State, guest_GPR20);
+ case 21: return offsetof(VexGuestPPC64State, guest_GPR21);
+ case 22: return offsetof(VexGuestPPC64State, guest_GPR22);
+ case 23: return offsetof(VexGuestPPC64State, guest_GPR23);
+ case 24: return offsetof(VexGuestPPC64State, guest_GPR24);
+ case 25: return offsetof(VexGuestPPC64State, guest_GPR25);
+ case 26: return offsetof(VexGuestPPC64State, guest_GPR26);
+ case 27: return offsetof(VexGuestPPC64State, guest_GPR27);
+ case 28: return offsetof(VexGuestPPC64State, guest_GPR28);
+ case 29: return offsetof(VexGuestPPC64State, guest_GPR29);
+ case 30: return offsetof(VexGuestPPC64State, guest_GPR30);
+ case 31: return offsetof(VexGuestPPC64State, guest_GPR31);
+ default: break;
+ }
+ } else {
+ switch (archreg) {
case 0: return offsetof(VexGuestPPC32State, guest_GPR0);
case 1: return offsetof(VexGuestPPC32State, guest_GPR1);
case 2: return offsetof(VexGuestPPC32State, guest_GPR2);
@@ -722,21 +930,24 @@
case 30: return offsetof(VexGuestPPC32State, guest_GPR30);
case 31: return offsetof(VexGuestPPC32State, guest_GPR31);
default: break;
+ }
}
vpanic("integerGuestRegOffset(ppc32,be)"); /*notreached*/
}
static IRExpr* getIReg ( UInt archreg )
{
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
vassert(archreg < 32);
- return IRExpr_Get( integerGuestRegOffset(archreg), Ity_I32 );
+ return IRExpr_Get( integerGuestRegOffset(archreg), ty );
}
/* Ditto, but write to a reg instead. */
static void putIReg ( UInt archreg, IRExpr* e )
{
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
vassert(archreg < 32);
- vassert(typeOfIRExpr(irbb->tyenv, e) == Ity_I32);
+ vassert(typeOfIRExpr(irbb->tyenv, e) == ty );
stmt( IRStmt_Put(integerGuestRegOffset(archreg), e) );
}
@@ -745,7 +956,44 @@
{
vassert(archreg < 32);
- switch (archreg) {
+ if (mode64) {
+ switch (archreg) {
+ case 0: return offsetof(VexGuestPPC64State, guest_FPR0);
+ case 1: return offsetof(VexGuestPPC64State, guest_FPR1);
+ case 2: return offsetof(VexGuestPPC64State, guest_FPR2);
+ case 3: return offsetof(VexGuestPPC64State, guest_FPR3);
+ case 4: return offsetof(VexGuestPPC64State, guest_FPR4);
+ case 5: return offsetof(VexGuestPPC64State, guest_FPR5);
+ case 6: return offsetof(VexGuestPPC64State, guest_FPR6);
+ case 7: return offsetof(VexGuestPPC64State, guest_FPR7);
+ case 8: return offsetof(VexGuestPPC64State, guest_FPR8);
+ case 9: return offsetof(VexGuestPPC64State, guest_FPR9);
+ case 10: return offsetof(VexGuestPPC64State, guest_FPR10);
+ case 11: return offsetof(VexGuestPPC64State, guest_FPR11);
+ case 12: return offsetof(VexGuestPPC64State, guest_FPR12);
+ case 13: return offsetof(VexGuestPPC64State, guest_FPR13);
+ case 14: return offsetof(VexGuestPPC64State, guest_FPR14);
+ case 15: return offsetof(VexGuestPPC64State, guest_FPR15);
+ case 16: return offsetof(VexGuestPPC64State, guest_FPR16);
+ case 17: return offsetof(VexGuestPPC64State, guest_FPR17);
+ case 18: return offsetof(VexGuestPPC64State, guest_FPR18);
+ case 19: return offsetof(VexGuestPPC64State, guest_FPR19);
+ case 20: return offsetof(VexGuestPPC64State, guest_FPR20);
+ case 21: return offsetof(VexGuestPPC64State, guest_FPR21);
+ case 22: return offsetof(VexGuestPPC64State, guest_FPR22);
+ case 23: return offsetof(VexGuestPPC64State, guest_FPR23);
+ case 24: return offsetof(VexGuestPPC64State, guest_FPR24);
+ case 25: return offsetof(VexGuestPPC64State, guest_FPR25);
+ case 26: return offsetof(VexGuestPPC64State, guest_FPR26);
+ case 27: return offsetof(VexGuestPPC64State, guest_FPR27);
+ case 28: return offsetof(VexGuestPPC64State, guest_FPR28);
+ case 29: return offsetof(VexGuestPPC64State, guest_FPR29);
+ case 30: return offsetof(VexGuestPPC64State, guest_FPR30);
+ case 31: return offsetof(VexGuestPPC64State, guest_FPR31);
+ default: break;
+ }
+ } else {
+ switch (archreg) {
case 0: return offsetof(VexGuestPPC32State, guest_FPR0);
case 1: return offsetof(VexGuestPPC32State, guest_FPR1);
case 2: return offsetof(VexGuestPPC32State, guest_FPR2);
@@ -779,6 +1027,7 @@
case 30: return offsetof(VexGuestPPC32State, guest_FPR30);
case 31: return offsetof(VexGuestPPC32State, guest_FPR31);
default: break;
+ }
}
vpanic("floatGuestRegOffset(ppc32)"); /*notreached*/
}
@@ -802,7 +1051,44 @@
{
vassert(archreg < 32);
- switch (archreg) {
+ if (mode64) {
+ switch (archreg) {
+ case 0: return offsetof(VexGuestPPC64State, guest_VR0);
+ case 1: return offsetof(VexGuestPPC64State, guest_VR1);
+ case 2: return offsetof(VexGuestPPC64State, guest_VR2);
+ case 3: return offsetof(VexGuestPPC64State, guest_VR3);
+ case 4: return offsetof(VexGuestPPC64State, guest_VR4);
+ case 5: return offsetof(VexGuestPPC64State, guest_VR5);
+ case 6: return offsetof(VexGuestPPC64State, guest_VR6);
+ case 7: return offsetof(VexGuestPPC64State, guest_VR7);
+ case 8: return offsetof(VexGuestPPC64State, guest_VR8);
+ case 9: return offsetof(VexGuestPPC64State, guest_VR9);
+ case 10: return offsetof(VexGuestPPC64State, guest_VR10);
+ case 11: return offsetof(VexGuestPPC64State, guest_VR11);
+ case 12: return offsetof(VexGuestPPC64State, guest_VR12);
+ case 13: return offsetof(VexGuestPPC64State, guest_VR13);
+ case 14: return offsetof(VexGuestPPC64State, guest_VR14);
+ case 15: return offsetof(VexGuestPPC64State, guest_VR15);
+ case 16: return offsetof(VexGuestPPC64State, guest_VR16);
+ case 17: return offsetof(VexGuestPPC64State, guest_VR17);
+ case 18: return offsetof(VexGuestPPC64State, guest_VR18);
+ case 19: return offsetof(VexGuestPPC64State, guest_VR19);
+ case 20: return offsetof(VexGuestPPC64State, guest_VR20);
+ case 21: return offsetof(VexGuestPPC64State, guest_VR21);
+ case 22: return offsetof(VexGuestPPC64State, guest_VR22);
+ case 23: return offsetof(VexGuestPPC64State, guest_VR23);
+ case 24: return offsetof(VexGuestPPC64State, guest_VR24);
+ case 25: return offsetof(VexGuestPPC64State, guest_VR25);
+ case 26: return offsetof(VexGuestPPC64State, guest_VR26);
+ case 27: return offsetof(VexGuestPPC64State, guest_VR27);
+ case 28: return offsetof(VexGuestPPC64State, guest_VR28);
+ case 29: return offsetof(VexGuestPPC64State, guest_VR29);
+ case 30: return offsetof(VexGuestPPC64State, guest_VR30);
+ case 31: return offsetof(VexGuestPPC64State, guest_VR31);
+ default: break;
+ }
+ } else {
+ switch (archreg) {
case 0: return offsetof(VexGuestPPC32State, guest_VR0);
case 1: return offsetof(VexGuestPPC32State, guest_VR1);
case 2: return offsetof(VexGuestPPC32State, guest_VR2);
@@ -836,6 +1122,7 @@
case 30: return offsetof(VexGuestPPC32State, guest_VR30);
case 31: return offsetof(VexGuestPPC32State, guest_VR31);
default: break;
+ }
}
vpanic("vextorGuestRegOffset(ppc32)"); /*notreached*/
}
@@ -856,7 +1143,20 @@
static Int guestCR321offset ( UInt cr )
{
- switch (cr) {
+ if (mode64) {
+ switch (cr) {
+ case 0: return offsetof(VexGuestPPC64State, guest_CR0_321 );
+ case 1: return offsetof(VexGuestPPC64State, guest_CR1_321 );
+ case 2: return offsetof(VexGuestPPC64State, guest_CR2_321 );
+ case 3: return offsetof(VexGuestPPC64State, guest_CR3_321 );
+ case 4: return offsetof(VexGuestPPC64State, guest_CR4_321 );
+ case 5: return offsetof(VexGuestPPC64State, guest_CR5_321 );
+ case 6: return offsetof(VexGuestPPC64State, guest_CR6_321 );
+ case 7: return offsetof(VexGuestPPC64State, guest_CR7_321 );
+ default: vpanic("guestCR321offset(ppc32)");
+ }
+ } else {
+ switch (cr) {
case 0: return offsetof(VexGuestPPC32State, guest_CR0_321 );
case 1: return offsetof(VexGuestPPC32State, guest_CR1_321 );
case 2: return offsetof(VexGuestPPC32State, guest_CR2_321 );
@@ -866,12 +1166,26 @@
case 6: return offsetof(VexGuestPPC32State, guest_CR6_321 );
case 7: return offsetof(VexGuestPPC32State, guest_CR7_321 );
default: vpanic("guestCR321offset(ppc32)");
+ }
}
}
static Int guestCR0offset ( UInt cr )
{
- switch (cr) {
+ if (mode64) {
+ switch (cr) {
+ case 0: return offsetof(VexGuestPPC64State, guest_CR0_0 );
+ case 1: return offsetof(VexGuestPPC64State, guest_CR1_0 );
+ case 2: return offsetof(VexGuestPPC64State, guest_CR2_0 );
+ case 3: return offsetof(VexGuestPPC64State, guest_CR3_0 );
+ case 4: return offsetof(VexGuestPPC64State, guest_CR4_0 );
+ case 5: return offsetof(VexGuestPPC64State, guest_CR5_0 );
+ case 6: return offsetof(VexGuestPPC64State, guest_CR6_0 );
+ case 7: return offsetof(VexGuestPPC64State, guest_CR7_0 );
+ default: vpanic("guestCR3offset(ppc32)");
+ }
+ } else {
+ switch (cr) {
case 0: return offsetof(VexGuestPPC32State, guest_CR0_0 );
case 1: return offsetof(VexGuestPPC32State, guest_CR1_0 );
case 2: return offsetof(VexGuestPPC32State, guest_CR2_0 );
@@ -881,60 +1195,134 @@
case 6: return offsetof(VexGuestPPC32State, guest_CR6_0 );
case 7: return offsetof(VexGuestPPC32State, guest_CR7_0 );
default: vpanic("guestCR3offset(ppc32)");
+ }
}
}
-// ROTL(src32, rot_amt5)
-static IRExpr* ROTL32 ( IRExpr* src, IRExpr* rot_amt )
+// ROTL(src32/64, rot_amt5)
+static IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src,
+ IRExpr* rot_amt )
{
- IRExpr* masked;
- vassert(typeOfIRExpr(irbb->tyenv,src) == Ity_I32);
- vassert(typeOfIRExpr(irbb->tyenv,rot_amt) == Ity_I32);
+ IRExpr *mask, *rot;
+ vassert(typeOfIRExpr(irbb->tyenv,rot_amt) == Ity_I8);
- masked
- = unop(Iop_32to8, binop(Iop_And32, rot_amt, mkU32(31)));
-
- // (src << rot_amt) | (src >> (32-rot_amt))
+ if (mode64) {
+ vassert(typeOfIRExpr(irbb->tyenv,src) == Ity_I64);
+ // rot = (src << rot_amt) | (src >> (64-rot_amt))
+ mask = binop(Iop_And8, rot_amt, mkU8(63));
+ rot = binop(Iop_Or64,
+ binop(Iop_Shl64, src, mask),
+ binop(Iop_Shr64, src, binop(Iop_Sub8, mkU8(64), mask)));
+ } else {
+ vassert(typeOfIRExpr(irbb->tyenv,src) == Ity_I32);
+ // rot = (src << rot_amt) | (src >> (32-rot_amt))
+ mask = binop(Iop_And8, rot_amt, mkU8(31));
+ rot = binop(Iop_Or32,
+ binop(Iop_Shl32, src, mask),
+ binop(Iop_Shr32, src, binop(Iop_Sub8, mkU8(32), mask)));
+ }
/* Note: the MuxOX is not merely an optimisation; it's needed
because otherwise the Shr32 is a shift by the word size when
- masked denotes zero. For rotates by immediates, a lot of
+ mask denotes zero. For rotates by immediates, a lot of
this junk gets folded out. */
- return
- IRExpr_Mux0X(
- masked,
- /* zero rotate. */
- src,
- /* non-zero rotate */
- binop( Iop_Or32,
- binop(Iop_Shl32, src, masked),
- binop(Iop_Shr32, src, binop(Iop_Sub8, mkU8(32), masked))
- )
- );
+ return IRExpr_Mux0X( mask, /* zero rotate */ src,
+ /* non-zero rotate */ rot );
}
-/* Do the standard effective address calculation: (rA|0) + rB. */
-static IRExpr* /* :: Ity_I32 */ ea_standard ( Int rA, Int rB )
+#if 0
+/* ROTL32_64(src64, rot_amt5)
+ Weirdo 32bit rotl on ppc64:
+ rot32 = ROTL(src_lo32,y);
+ return (rot32|rot32);
+*/
+static IRExpr* /* :: Ity_I64 */ ROTL32_64 ( IRExpr* src64,
+ IRExpr* rot_amt )
{
- vassert(rA >= 0 && rA < 32);
- vassert(rB >= 0 && rB < 32);
- if (rA == 0) {
- return getIReg(rB);
- } else {
- return binop(Iop_Add32, getIReg(rA), getIReg(rB));
- }
+ IRExpr *mask, *rot32;
+ vassert(mode64); // used only in 64bit mode
+ vassert(typeOfIRExpr(irbb->tyenv,src64) == Ity_I64);
+ vassert(typeOfIRExpr(irbb->tyenv,rot_amt) == Ity_I8);
+
+ mask = binop(Iop_And8, rot_amt, mkU8(31));
+ rot32 = ROTL( unop(Iop_64to32, src64), rot_amt );
+
+ return binop(Iop_Or64,
+ binop(Iop_Shl64, unop(Iop_32Uto64, rot32), mkU8(32)),
+ unop(Iop_32Uto64, rot32));
+}
+#endif
+
+
+/* Standard effective address calc: (rA + rB) */
+static IRExpr* ea_rA_idxd ( UInt rA, UInt rB )
+{
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
+ vassert(rA < 32);
+ vassert(rB < 32);
+ return binop(mkSizedOp(ty, Iop_Add8), getIReg(rA), getIReg(rB));
}
-/* Do the effective address calculation: (rA|0). */
-static IRExpr* /* :: Ity_I32 */ ea_rA_or_zero ( Int rA )
+/* Standard effective address calc: (rA + simm) */
+static IRExpr* ea_rA_simm ( UInt rA, UInt simm16 )
{
- vassert(rA >= 0 && rA < 32);
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
+ vassert(rA < 32);
+ return binop(mkSizedOp(ty, Iop_Add8), getIReg(rA),
+ mkSizedExtendS16(ty, simm16));
+}
+
+/* Standard effective address calc: (rA|0) */
+static IRExpr* ea_rAor0 ( UInt rA )
+{
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
+ vassert(rA < 32);
if (rA == 0) {
- return mkU32(0);
+ return mkSizedImm(ty, 0);
} else {
return getIReg(rA);
}
}
+/* Standard effective address calc: (rA|0) + rB */
+static IRExpr* ea_rAor0_idxd ( UInt rA, UInt rB )
+{
+ vassert(rA < 32);
+ vassert(rB < 32);
+ return (rA == 0) ? getIReg(rB) : ea_rA_idxd( rA, rB );
+}
+
+/* Standard effective address calc: (rA|0) + simm16 */
+static IRExpr* ea_rAor0_simm ( UInt rA, UInt simm16 )
+{
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
+ vassert(rA < 32);
+ if (rA == 0) {
+ return mkSizedExtendS16(ty, simm16);
+ } else {
+ return ea_rA_simm( rA, simm16 );
+ }
+}
+
+
+/* Align effective address */
+static IRExpr* addr_align( IRExpr* addr, UChar align )
+{
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
+ Long mask;
+ switch (align) {
+ case 2: mask = ((Long)-1) << 1; break; // half-word aligned
+ case 4: mask = ((Long)-1) << 2; break; // word aligned
+ case 16: mask = ((Long)-1) << 4; break; // quad-word aligned
+ default:
+ vex_printf("addr_align: align = %u\n", align);
+ vpanic("addr_align(ppc32)");
+ }
+
+ vassert(typeOfIRExpr(irbb->tyenv,addr) == ty);
+ return binop( mkSizedOp(ty, Iop_And8), addr,
+ mkSizedImm(ty, mask) );
+}
+
/*------------------------------------------------------------*/
/*--- Helpers for condition codes. ---*/
@@ -1084,9 +1472,17 @@
static IRExpr* getXER_SO ( void );
static void set_CR0 ( IRExpr* result )
{
- vassert(typeOfIRExpr(irbb->tyenv,result) == Ity_I32);
- putCR321( 0, unop(Iop_32to8,
- binop(Iop_CmpORD32S, result, mkU32(0))) );
+ vassert(typeOfIRExpr(irbb->tyenv,result) == Ity_I32 ||
+ typeOfIRExpr(irbb->tyenv,result) == Ity_I64);
+ if (mode64) {
+#if 0 // CAB: TODO
+ putCR321( 0, unop(Iop_64to8,
+ binop(Iop_Cmp
+#endif
+ } else {
+ putCR321( 0, unop(Iop_32to8,
+ binop(Iop_CmpORD32S, result, mkU32(0))) );
+ }
putCR0( 0, getXER_SO() );
}
@@ -1146,30 +1542,35 @@
static void putXER_SO ( IRExpr* e )
{
vassert(typeOfIRExpr(irbb->tyenv, e) == Ity_I8);
- stmt( IRStmt_Put(OFFB_XER_SO, binop(Iop_And8, mkU8(1), e)) );
+ IRExpr* so = binop(Iop_And8, mkU8(1), e);
+ stmt( IRStmt_Put( (mode64 ? OFFB64_XER_SO : OFFB32_XER_SO), so) );
}
static void putXER_OV ( IRExpr* e )
{
vassert(typeOfIRExpr(irbb->tyenv, e) == Ity_I8);
- stmt( IRStmt_Put(OFFB_XER_OV, binop(Iop_And8, mkU8(1), e)) );
+ IRExpr* ov = binop(Iop_And8, mkU8(1), e);
+ stmt( IRStmt_Put( (mode64 ? OFFB64_XER_OV : OFFB32_XER_OV), ov) );
}
static void putXER_CA ( IRExpr* e )
{
vassert(typeOfIRExpr(irbb->tyenv, e) == Ity_I8);
- stmt( IRStmt_Put(OFFB_XER_CA, binop(Iop_And8, mkU8(1), e)) );
+ IRExpr* ca = binop(Iop_And8, mkU8(1), e);
+ stmt( IRStmt_Put( (mode64 ? OFFB64_XER_CA : OFFB32_XER_CA), ca) );
}
static void putXER_BC ( IRExpr* e )
{
vassert(typeOfIRExpr(irbb->tyenv, e) == Ity_I8);
- stmt( IRStmt_Put(OFFB_XER_BC, binop(Iop_And8, mkU8(0x7F), e)) );
+ IRExpr* bc = binop(Iop_And8, mkU8(0x7F), e);
+ stmt( IRStmt_Put( (mode64 ? OFFB64_XER_BC : OFFB32_XER_BC), bc) );
}
static IRExpr* /* :: Ity_I8 */ getXER_SO ( void )
{
- return IRExpr_Get( OFFB_XER_SO, Ity_I8 );
+ return mode64 ? IRExpr_Get( OFFB64_XER_SO, Ity_I8 ) :
+ IRExpr_Get( OFFB32_XER_SO, Ity_I8 );
}
static IRExpr* /* :: Ity_I32 */ getXER_SO32 ( void )
@@ -1179,7 +1580,8 @@
static IRExpr* /* :: Ity_I8 */ getXER_OV ( void )
{
- return IRExpr_Get( OFFB_XER_OV, Ity_I8 );
+ return mode64 ? IRExpr_Get( OFFB64_XER_OV, Ity_I8 ) :
+ IRExpr_Get( OFFB32_XER_OV, Ity_I8 );
}
static IRExpr* /* :: Ity_I32 */ getXER_OV32 ( void )
@@ -1189,34 +1591,35 @@
static IRExpr* /* :: Ity_I32 */ getXER_CA32 ( void )
{
- return binop( Iop_And32,
- unop(Iop_8Uto32, IRExpr_Get( OFFB_XER_CA, Ity_I8 )),
- mkU32(1) );
+ IRExpr* ca = mode64 ? IRExpr_Get( OFFB64_XER_CA, Ity_I8 ) :
+ IRExpr_Get( OFFB32_XER_CA, Ity_I8 );
+ return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) );
}
static IRExpr* /* :: Ity_I8 */ getXER_BC ( void )
{
- return IRExpr_Get( OFFB_XER_BC, Ity_I8 );
+ return mode64 ? IRExpr_Get( OFFB64_XER_BC, Ity_I8 ) :
+ IRExpr_Get( OFFB32_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) );
+ IRExpr* bc = mode64 ? IRExpr_Get( OFFB64_XER_BC, Ity_I8 ) :
+ IRExpr_Get( OFFB32_XER_BC, Ity_I8 );
+ return binop( Iop_And32, unop(Iop_8Uto32, bc), mkU32(0x7F) );
}
/* 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 )
+static void set_XER_OV_32( UInt op, IRExpr* res,
+ IRExpr* argL, IRExpr* argR )
{
IRTemp t64;
IRExpr* xer_ov;
vassert(op < PPC32G_FLAG_OP_NUMBER);
- vassert(typeOfIRExpr(irbb->tyenv,res) == Ity_I32);
+ vassert(typeOfIRExpr(irbb->tyenv,res) == Ity_I32);
vassert(typeOfIRExpr(irbb->tyenv,argL) == Ity_I32);
vassert(typeOfIRExpr(irbb->tyenv,argR) == Ity_I32);
@@ -1235,83 +1638,82 @@
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
- = AND3( XOR3(argL,argR,mkU32(-1)),
- XOR2(argL,res),
- mkU32(INT32_MIN) );
- /* xer_ov can only be 0 or 1<<31 */
- xer_ov
- = binop(Iop_Shr32, xer_ov, mkU8(31) );
- break;
-
- case /* 2 */ PPC32G_FLAG_OP_DIVW:
- /* (argL == INT32_MIN && argR == -1) || argR == 0 */
- xer_ov
- = mkOR1(
- mkAND1(
- binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)),
- binop(Iop_CmpEQ32, argR, mkU32(-1))
- ),
- binop(Iop_CmpEQ32, argR, mkU32(0) )
- );
- xer_ov
- = unop(Iop_1Uto32, xer_ov);
- break;
-
- case /* 3 */ PPC32G_FLAG_OP_DIVWU:
- /* argR == 0 */
- xer_ov
- = 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 != sign extension of sLo */
- t64 = newTemp(Ity_I64);
- assign( t64, binop(Iop_MullS32, argL, argR) );
- xer_ov
- = binop( Iop_CmpNE32,
- unop(Iop_64HIto32, mkexpr(t64)),
- binop( Iop_Sar32,
- unop(Iop_64to32, mkexpr(t64)),
- mkU8(31))
- );
- xer_ov
- = unop(Iop_1Uto32, xer_ov);
- break;
-
- case /* 5 */ PPC32G_FLAG_OP_NEG:
- /* argL == INT32_MIN */
- xer_ov
- = unop( Iop_1Uto32,
- 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
- = 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
- = binop(Iop_Shr32, xer_ov, mkU8(31) );
- break;
-
- default:
- vex_printf("set_XER_OV: op = %u\n", op);
- vpanic("set_XER_OV(ppc32)");
+ 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
+ = AND3( XOR3(argL,argR,mkU32(-1)),
+ XOR2(argL,res),
+ mkU32(INT32_MIN) );
+ /* xer_ov can only be 0 or 1<<31 */
+ xer_ov
+ = binop(Iop_Shr32, xer_ov, mkU8(31) );
+ break;
+
+ case /* 2 */ PPC32G_FLAG_OP_DIVW:
+ /* (argL == INT32_MIN && argR == -1) || argR == 0 */
+ xer_ov
+ = mkOR1(
+ mkAND1(
+ binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)),
+ binop(Iop_CmpEQ32, argR, mkU32(-1))
+ ),
+ binop(Iop_CmpEQ32, argR, mkU32(0) )
+ );
+ xer_ov
+ = unop(Iop_1Uto32, xer_ov);
+ break;
+
+ case /* 3 */ PPC32G_FLAG_OP_DIVWU:
+ /* argR == 0 */
+ xer_ov
+ = 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 != sign extension of sLo */
+ t64 = newTemp(Ity_I64);
+ assign( t64, binop(Iop_MullS32, argL, argR) );
+ xer_ov
+ = binop( Iop_CmpNE32,
+ unop(Iop_64HIto32, mkexpr(t64)),
+ binop( Iop_Sar32,
+ unop(Iop_64to32, mkexpr(t64)),
+ mkU8(31))
+ );
+ xer_ov
+ = unop(Iop_1Uto32, xer_ov);
+ break;
+
+ case /* 5 */ PPC32G_FLAG_OP_NEG:
+ /* argL == INT32_MIN */
+ xer_ov
+ = unop( Iop_1Uto32,
+ 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
+ = 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
+ = binop(Iop_Shr32, xer_ov, mkU8(31) );
+ break;
+
+ default:
+ vex_printf("set_XER_OV: op = %u\n", op);
+ vpanic("set_XER_OV(ppc32)");
}
-
+
/* xer_ov MUST denote either 0 or 1, no other value allowed */
- stmt( IRStmt_Put( OFFB_XER_OV, unop(Iop_32to8, xer_ov) ) );
+ putXER_OV( unop(Iop_32to8, xer_ov) );
/* Update the summary overflow */
putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
@@ -1323,15 +1725,133 @@
# undef NOT
}
+static void set_XER_OV_64( UInt op, IRExpr* res,
+ IRExpr* argL, IRExpr* argR )
+{
+ IRExpr* xer_ov;
+ vassert(op < PPC32G_FLAG_OP_NUMBER);
+ vassert(typeOfIRExpr(irbb->tyenv,res) == Ity_I64);
+ vassert(typeOfIRExpr(irbb->tyenv,argL) == Ity_I64);
+ vassert(typeOfIRExpr(irbb->tyenv,argR) == Ity_I64);
+
+# define INT64_MIN 0x8000000000000000
+
+# define XOR2(_aa,_bb) \
+ binop(Iop_Xor64,(_aa),(_bb))
+
+# define XOR3(_cc,_dd,_ee) \
+ binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee))
+
+# define AND3(_ff,_gg,_hh) \
+ binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh))
+
+#define NOT(_jj) \
+ unop(Iop_Not64, (_jj))
+
+ switch (op) {
+
+ case /* 0 */ PPC32G_FLAG_OP_ADD:
+ case /* 1 */ PPC32G_FLAG_OP_ADDE:
+ /* (argL^argR^-1) & (argL^res) & (1<<63) ? 1:0 */
+ // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
+ xer_ov
+ = AND3( XOR3(argL,argR,mkU64(-1)),
+ XOR2(argL,res),
+ mkU64(INT64_MIN) );
+ /* xer_ov can only be 0 or 1<<63 */
+ xer_ov
+ = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
+ break;
+
+ case /* 2 */ PPC32G_FLAG_OP_DIVW:
+ /* (argL == INT64_MIN && argR == -1) || argR == 0 */
+ xer_ov
+ = mkOR1(
+ mkAND1(
+ binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)),
+ binop(Iop_CmpEQ64, argR, mkU64(-1))
+ ),
+ binop(Iop_CmpEQ64, argR, mkU64(0) )
+ );
+ break;
+
+ case /* 3 */ PPC32G_FLAG_OP_DIVWU:
+ /* argR == 0 */
+ xer_ov
+ = binop(Iop_CmpEQ64, argR, mkU64(0));
+ break;
+
+ case /* 4 */ PPC32G_FLAG_OP_MULLW: {
+ /* OV true if result can't be represented in 64 bits
+ i.e sHi != sign extension of sLo */
+ IRTemp t128 = newTemp(Ity_I128);
+ assign( t128, binop(Iop_MullS64, argL, argR) );
+ xer_ov
+ = binop( Iop_CmpNE64,
+ unop(Iop_128HIto64, mkexpr(t128)),
+ binop( Iop_Sar64,
+ unop(Iop_128to64, mkexpr(t128)),
+ mkU8(63)) );
+ break;
+ }
+
+ case /* 5 */ PPC32G_FLAG_OP_NEG:
+ /* argL == INT64_MIN */
+ xer_ov
+ = binop(Iop_CmpEQ64, argL, mkU64(INT64_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<<63) ?1:0; */
+ xer_ov
+ = AND3( XOR3(NOT(argL),argR,mkU64(-1)),
+ XOR2(NOT(argL),res),
+ mkU64(INT64_MIN) );
+ /* xer_ov can only be 0 or 1<<63 */
+ xer_ov
+ = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
+ break;
+
+ default:
+ vex_printf("set_XER_OV: op = %u\n", op);
+ vpanic("set_XER_OV(ppc32)");
+ }
+
+ /* xer_ov MUST denote either 0 or 1, no other value allowed */
+ putXER_OV( unop(Iop_1Uto8, xer_ov) );
+
+ /* Update the summary overflow */
+ putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
+
+# undef INT64_MIN
+# undef AND3
+# undef XOR3
+# undef XOR2
+# undef NOT
+}
+
+static void set_XER_OV ( IRType ty, UInt op, IRExpr* res,
+ IRExpr* argL, IRExpr* argR )
+{
+ if (ty == Ity_I32)
+ set_XER_OV_32( op, res, argL, argR );
+ else
+ set_XER_OV_64( op, res, argL, argR );
+}
+
+
+
/* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA
value being OLDCA. Set %XER.CA accordingly. */
-static void set_XER_CA( UInt op,
- IRExpr* res,
- IRExpr* argL,
- IRExpr* argR,
- IRExpr* oldca )
+static void set_XER_CA_32( UInt op,
+ IRExpr* res,
+ IRExpr* argL,
+ IRExpr* argR,
+ IRExpr* oldca )
{
IRExpr* xer_ca;
vassert(op < PPC32G_FLAG_OP_NUMBER);
@@ -1348,196 +1868,264 @@
switch (op) {
- case /* 0 */ PPC32G_FLAG_OP_ADD:
- /* res <u argL */
- xer_ca
- = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL));
- break;
-
- case /* 1 */ PPC32G_FLAG_OP_ADDE:
- /* res <u argL || (old_ca==1 && res==argL) */
- xer_ca
- = mkOR1(
- binop(Iop_CmpLT32U, res, argL),
- mkAND1(
- binop(Iop_CmpEQ32, oldca, mkU32(1)),
- binop(Iop_CmpEQ32, res, argL)
- )
+ case /* 0 */ PPC32G_FLAG_OP_ADD:
+ /* res <u argL */
+ xer_ca
+ = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL));
+ break;
+
+ case /* 1 */ PPC32G_FLAG_OP_ADDE:
+ /* res <u argL || (old_ca==1 && res==argL) */
+ xer_ca
+ = mkOR1(
+ binop(Iop_CmpLT32U, res, argL),
+ mkAND1(
+ binop(Iop_CmpEQ32, oldca, mkU32(1)),
+ binop(Iop_CmpEQ32, res, argL)
+ )
+ );
+ xer_ca
+ = unop(Iop_1Uto32, xer_ca);
+ break;
+
+ case /* 8 */ PPC32G_FLAG_OP_SUBFE:
+ /* res <u argR || (old_ca==1 && res==argR) */
+ xer_ca
+ = mkOR1(
+ binop(Iop_CmpLT32U, res, argR),
+ mkAND1(
+ binop(Iop_CmpEQ32, oldca, mkU32(1)),
+ binop(Iop_CmpEQ32, res, argR)
+ )
+ );
+ xer_ca
+ = unop(Iop_1Uto32, xer_ca);
+ break;
+
+ case /* 7 */ PPC32G_FLAG_OP_SUBFC:
+ case /* 9 */ PPC32G_FLAG_OP_SUBFI:
+ /* res <=u argR */
+ xer_ca
+ = 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 <= 31, behave like SRAWI; else XER.CA is the sign
+ bit of argL. */
+ /* This term valid for shift amount < 32 only */
+ xer_ca
+ = 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
- = unop(Iop_1Uto32, xer_ca);
- break;
+ xer_ca
+ = 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 /* 8 */ PPC32G_FLAG_OP_SUBFE:
- /* res <u argR || (old_ca==1 && res==argR) */
- xer_ca
- = mkOR1(
- binop(Iop_CmpLT32U, res, argR),
- mkAND1(
- binop(Iop_CmpEQ32, oldca, mkU32(1)),
- binop(Iop_CmpEQ32, res, argR)
- )
+ case /* 11 */ PPC32G_FLAG_OP_SRAWI:
+ /* xer_ca is 1 iff src was negative and bits_shifted_out !=
+ 0. Since the shift amount is known to be in the range
+ 0 .. 31 inclusive the following seems viable:
+ xer.ca == 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
+ = 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
- = unop(Iop_1Uto32, xer_ca);
- break;
-
- case /* 7 */ PPC32G_FLAG_OP_SUBFC:
- case /* 9 */ PPC32G_FLAG_OP_SUBFI:
- /* res <=u argR */
- xer_ca
- = 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 <= 31, behave like SRAWI; else XER.CA is the sign
- bit of argL. */
- /* This term valid for shift amount < 32 only */
- xer_ca
- = 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
- = 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 !=
- 0. Since the shift amount is known to be in the range
- 0 .. 31 inclusive the following seems viable:
- xer.ca == 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
- = 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
- = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)));
- break;
-
- default:
- vex_printf("set_XER_CA: op = %u\n", op);
- vpanic("set_XER_CA(ppc32)");
+ xer_ca
+ = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)));
+ break;
+
+ default:
+ vex_printf("set_XER_CA: op = %u\n", op);
+ vpanic("set_XER_CA(ppc32)");
}
/* xer_ca MUST denote either 0 or 1, no other value allowed */
putXER_CA( unop(Iop_32to8, xer_ca) );
}
-
-
-/*------------------------------------------------------------*/
-/*--- SPR register interface --- */
-/*------------------------------------------------------------*/
-
-/* Get a masked word from the given reg */
-static IRExpr* /* ::Ity_I32 */ getSPR_masked ( PPC32SPR reg, UInt mask )
+static void set_XER_CA_64( UInt op,
+ IRExpr* res,
+ IRExpr* argL,
+ IRExpr* argR,
+ IRExpr* oldca )
{
- IRTemp val = newTemp(Ity_I32);
- vassert( reg < PPC32_SPR_MAX );
-
- switch (reg) {
+ IRExpr* xer_ca;
+ vassert(op < PPC32G_FLAG_OP_NUMBER);
+ vassert(typeOfIRExpr(irbb->tyenv,res) == Ity_I64);
+ vassert(typeOfIRExpr(irbb->tyenv,argL) == Ity_I64);
+ vassert(typeOfIRExpr(irbb->tyenv,argR) == Ity_I64);
+ vassert(typeOfIRExpr(irbb->tyenv,oldca) == Ity_I64);
- case PPC32_SPR_FPSCR: {
- vassert((mask & 0x3) == 0x3 || (mask & 0x3) == 0x0);
- vassert((mask & 0xF000) == 0xF000 || (mask & 0xF000) == 0x0);
- /* all masks now refer to valid fields */
+ /* Incoming oldca is assumed to hold the values 0 or 1 only. This
+ seems reasonable given that it's always generated by
+ 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. */
+
+ switch (op) {
+
+ case /* 0 */ PPC32G_FLAG_OP_ADD:
+ /* res <u argL */
+ xer_ca
+ = binop(Iop_CmpLT64U, res, argL);
+ break;
- /* Vex-generated code expects to run with the FPSCR set as follows:
- all exceptions masked, round-to-nearest.
- This corresponds to a FPSCR value of 0x0. */
-
- /* We're only keeping track of the rounding mode,
- so if the mask isn't asking for this, just return 0x0 */
- if (mask & 0x3) {
- assign( val, IRExpr_Get(OFFB_FPROUND, Ity_I32) );
- } else {
- assign( val, mkU32(0x0) );
- }
+ case /* 1 */ PPC32G_FLAG_OP_ADDE:
+ /* res <u argL || (old_ca==1 && res==argL) */
+ xer_ca
+ = mkOR1(
+ binop(Iop_CmpLT64U, res, argL),
+ mkAND1(
+ binop(Iop_CmpEQ64, oldca, mkU32(1)),
+ binop(Iop_CmpEQ64, res, argL)
+ )
+ );
break;
+
+ case /* 8 */ PPC32G_FLAG_OP_SUBFE:
+ /* res <u argR || (old_ca==1 && res==argR) */
+ xer_ca
+ = mkOR1(
+ binop(Iop_CmpLT64U, res, argR),
+ mkAND1(
+ binop(Iop_CmpEQ64, oldca, mkU64(1)),
+ binop(Iop_CmpEQ64, res, argR)
+ )
+ );
+ break;
+
+ case /* 7 */ PPC32G_FLAG_OP_SUBFC:
+ case /* 9 */ PPC32G_FLAG_OP_SUBFI:
+ /* res <=u argR */
+ xer_ca
+ = binop(Iop_CmpLE64U, res, argR);
+ break;
+
+
+#if 0 // CAB: TODO
+
+ case /* 10 */ PPC32G_FLAG_OP_SRAW:
+ /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
+ If it is <= 31, behave like SRAWI; else XER.CA is the sign
+ bit of argL. */
+ /* This term valid for shift amount < 32 only */
+ xer_ca
+ = 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
+ = IRExpr_Mux0X(
+ /* shift amt > 31 ? */
+ unop(Iop_1Uto8, binop(Iop_CmpLT32U, mkU32(31), argR)),
+ /* no -- be like srawi */
+ binop(Iop_CmpNE32, xer_ca, mkU32(0)),
+ /* yes -- get sign bit of argL */
+ unop(Iop_32to1, 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 !=
+ 0. Since the shift amount is known to be in the range
+ 0 .. 31 inclusive the following seems viable:
+ xer.ca == 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
+ = 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
+ = binop(Iop_CmpNE32, xer_ca, mkU32(0));
+ break;
+#endif
+
+ default:
+ vex_printf("set_XER_CA: op = %u\n", op);
+ vpanic("set_XER_CA(ppc32)");
}
- default:
- vpanic("getSPR_masked(ppc32)");
- }
-
- if (mask != 0xFFFFFFFF) {
- return binop(Iop_And32, mkexpr(val), mkU32(mask));
- } else {
- return mkexpr(val);
- }
+ /* xer_ca MUST denote either 0 or 1, no other value allowed */
+ putXER_CA( unop(Iop_1Uto8, xer_ca) );
}
-/* 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 )
+static void set_XER_CA( UInt op,
+ IRExpr* res,
+ IRExpr* argL,
+ IRExpr* argR,
+ IRExpr* oldca )
{
- UInt shft, mask;
-
- vassert( fld < 8 );
- vassert( reg < PPC32_SPR_MAX );
-
- shft = 4*(7-fld);
- mask = 0xF<<shft;
-
- switch (reg) {
- case PPC32_SPR_XER:
- vassert(fld ==7);
- 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;
-
- default:
- if (shft == 0)
- return getSPR_masked( reg, mask );
- else
- return binop(Iop_Shr32,
- getSPR_masked( reg, mask ),
- mkU8(toUChar( shft )));
- }
+ if (typeOfIRExpr(irbb->tyenv,res) == Ity_I32)
+ set_XER_CA_32( op, res, argL, argR, oldca );
+ else
+ set_XER_CA_64( op, res, argL, argR, oldca );
}
-static IRExpr* /* :: Ity_I32 */ getSPR ( PPC32SPR reg )
+
+
+/*------------------------------------------------------------*/
+/*--- Read/write to guest-state --- */
+/*------------------------------------------------------------*/
+
+static IRExpr* /* :: Ity_I32 */ getGST ( PPC_GST reg )
{
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
switch (reg) {
- case PPC32_SPR_LR:
- return IRExpr_Get( OFFB_LR, Ity_I32 );
- case PPC32_SPR_CTR:
- return IRExpr_Get( OFFB_CTR, Ity_I32 );
- case PPC32_SPR_VRSAVE:
- return IRExpr_Get( OFFB_VRSAVE, Ity_I32 );
- case PPC32_SPR_VSCR:
- return binop(Iop_And32,
- IRExpr_Get( OFFB_VSCR, Ity_I32 ),
- mkU32(MASK_VSCR_VALID));
- case PPC32_SPR_CR: {
+ case PPC_GST_LR:
+ return IRExpr_Get((mode64 ? OFFB64_LR : OFFB32_LR), ty);
+
+ case PPC_GST_CTR:
+ return IRExpr_Get((mode64 ? OFFB64_CTR : OFFB32_CTR), ty);
+
+ case PPC_GST_VRSAVE:
+ return
+ IRExpr_Get((mode64 ? OFFB64_VRSAVE : OFFB32_VRSAVE), Ity_I32);
+
+ case PPC_GST_VSCR:
+ return
+ binop(Iop_And32,
+ IRExpr_Get((mode64 ? OFFB64_VSCR : OFFB32_VSCR),Ity_I32),
+ mkU32(MASK_VSCR_VALID));
+
+ case PPC_GST_CR: {
/* Synthesise the entire CR into a single word. Expensive. */
# define FIELD(_n) \
binop(Iop_Shl32, \
@@ -1561,7 +2149,8 @@
);
# undef FIELD
}
- case PPC32_SPR_XER: {
+
+ case PPC_GST_XER:
return binop(Iop_Or32,
binop(Iop_Or32,
binop( Iop_Shl32, getXER_SO32(), mkU8(31)),
@@ -1569,27 +2158,164 @@
binop(Iop_Or32,
binop( Iop_Shl32, getXER_CA32(), mkU8(29)),
getXER_BC32()));
- }
+
+ case PPC_GST_RESVN:
+ return IRExpr_Get((mode64 ? OFFB64_RESVN : OFFB32_RESVN), ty);
+
default:
- vpanic("getSPR(ppc32)");
+ vpanic("getGST(ppc32)");
+ }
+}
+
+/* Get a masked word from the given reg */
+static IRExpr* /* ::Ity_I32 */ getGST_masked ( PPC_GST reg, UInt mask )
+{
+ IRTemp val = newTemp(Ity_I32);
+ vassert( reg < PPC_GST_MAX );
+
+ switch (reg) {
+
+ case PPC_GST_FPSCR: {
+ vassert((mask & 0x3) == 0x3 || (mask & 0x3) == 0x0);
+ vassert((mask & 0xF000) == 0xF000 || (mask & 0xF000) == 0x0);
+ /* all masks now refer to valid fields */
+
+ /* Vex-generated code expects to run with the FPSCR set as follows:
+ all exceptions masked, round-to-nearest.
+ This corresponds to a FPSCR value of 0x0. */
+
+ /* We're only keeping track of the rounding mode,
+ so if the mask isn't asking for this, just return 0x0 */
+ if (mask & 0x3) {
+ assign( val, IRExpr_Get((mode64 ? OFFB64_FPROUND :
+ OFFB32_FPROUND), Ity_I32) );
+ } else {
+ assign( val, mkU32(0x0) );
+ }
+ break;
+ }
+
+ default:
+ vpanic("getGST_masked(ppc32)");
+ }
+
+ if (mask != 0xFFFFFFFF) {
+ return binop(Iop_And32, mkexpr(val), mkU32(mask));
+ } else {
+ return mkexpr(val);
+ }
+}
+
+/* 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 */ getGST_field ( PPC_GST reg, UInt fld )
+{
+ UInt shft, mask;
+
+ vassert( fld < 8 );
+ vassert( reg < PPC_GST_MAX );
+
+ shft = 4*(7-fld);
+ mask = 0xF<<shft;
+
+ switch (reg) {
+ case PPC_GST_XER:
+ vassert(fld ==7);
+ 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;
+
+ default:
+ if (shft == 0)
+ return getGST_masked( reg, mask );
+ else
+ return binop(Iop_Shr32,
+ getGST_masked( reg, mask ),
+ mkU8(toUChar( shft )));
+ }
+}
+
+static void putGST ( PPC_GST reg, IRExpr* src )
+{
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
+ vassert( reg < PPC_GST_MAX );
+ switch (reg) {
+ case PPC_GST_CIA:
+ vassert( typeOfIRExpr(irbb->tyenv,src ) == ty );
+ stmt( IRStmt_Put( (mode64 ? OFFB64_CIA : OFFB32_CIA), src ) );
+ break;
+ case PPC_GST_LR:
+ vassert( typeOfIRExpr(irbb->tyenv,src ) == ty );
+ stmt( IRStmt_Put( (mode64 ? OFFB64_LR : OFFB32_LR), src ) );
+ break;
+ case PPC_GST_CTR:
+ vassert( typeOfIRExpr(irbb->tyenv,src ) == ty );
+ stmt( IRStmt_Put( (mode64 ? OFFB64_CTR : OFFB32_CTR), src ) );
+ break;
+ case PPC_GST_VRSAVE:
+ vassert( typeOfIRExpr(irbb->tyenv,src ) == Ity_I32 );
+ stmt( IRStmt_Put((mode64 ? OFFB64_VRSAVE :OFFB32_VRSAVE),src));
+ break;
+ case PPC_GST_VSCR:
+ vassert( typeOfIRExpr(irbb->tyenv,src ) == Ity_I32 );
+ stmt( IRStmt_Put( (mode64 ? OFFB64_VSCR : OFFB32_VSCR),
+ binop(Iop_And32, src,
+ mkU32(MASK_VSCR_VALID)) ) );
+ break;
+ case PPC_GST_XER:
+ vassert( typeOfIRExpr(irbb->tyenv,src ) == Ity_I32 );
+ 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;
+
+ case PPC_GST_EMWARN:
+ vassert(typeOfIRExpr(irbb->tyenv,src) == Ity_I32);
+ stmt( IRStmt_Put((mode64 ? OFFB64_EMWARN : OFFB32_EMWARN),src) );
+ break;
+
+ case PPC_GST_TISTART:
+ vassert( typeOfIRExpr(irbb->tyenv,src ) == ty );
+ stmt( IRStmt_Put((mode64 ? OFFB64_TISTART :
+ OFFB32_TISTART), src) );
+ break;
+
+ case PPC_GST_TILEN:
+ vassert( typeOfIRExpr(irbb->tyenv,src ) == ty );
+ stmt( IRStmt_Put((mode64 ? OFFB64_TILEN : OFFB32_TILEN), src) );
+ break;
+
+ case PPC_GST_RESVN:
+ vassert( typeOfIRExpr(irbb->tyenv,src ) == ty );
+ stmt( IRStmt_Put((mode64 ? OFFB64_RESVN : OFFB32_RESVN), src) );
+ break;
+
+ default:
+ vpanic("putGST(ppc32)");
}
}
/* Write masked src to the given reg */
-static void putSPR_masked ( PPC32SPR reg, IRExpr* src, UInt mask )
+static void putGST_masked ( PPC_GST reg, IRExpr* src, UInt mask )
{
- vassert( reg < PPC32_SPR_MAX );
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
+ vassert( reg < PPC_GST_MAX );
vassert( typeOfIRExpr(irbb->tyenv,src ) == Ity_I32 );
switch (reg) {
- case PPC32_SPR_FPSCR: {
+ case PPC_GST_FPSCR: {
vassert((mask & 0x3) == 0x3 || (mask & 0x3) == 0x0);
vassert((mask & 0xF000) == 0xF000 || (mask & 0xF000) == 0x0);
/* all masks now refer to valid fields */
/* Allow writes to Rounding Mode */
if (mask & 0x3) {
- stmt( IRStmt_Put( OFFB_FPROUND,
+ stmt( IRStmt_Put( (mode64 ? OFFB64_FPROUND : OFFB32_FPROUND),
binop(Iop_And32, src, mkU32(0x3)) ));
}
@@ -1603,14 +2329,12 @@
/* If any of the src::exception_control bits are actually set,
side-exit to the next insn, reporting the warning,
so that Valgrind's dispatcher sees the warning. */
- put_emwarn( mkU32(ew) );
+ putGST( PPC_GST_EMWARN, mkU32(ew) );
stmt(
IRStmt_Exit(
binop(Iop_CmpNE32, mkU32(ew), mkU32(EmWarn_NONE)),
Ijk_EmWarn,
- IRConst_U32(guest_CIA_curr_instr + 4)
- )
- );
+ mkSizedConst( ty, nextInsnAddr()) ));
}
/* Ignore all other writes */
@@ -1618,75 +2342,41 @@
}
default:
- vex_printf("putSPR_masked(ppc32): %u", reg);
- vpanic("putSPR_masked(ppc32)");
+ vex_printf("putGST_masked(ppc32): %u", reg);
+ vpanic("putGST_masked(ppc32)");
}
}
/* 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 )
+static void putGST_field ( PPC_GST reg, IRExpr* src, UInt fld )
{
UInt shft, mask;
vassert( typeOfIRExpr(irbb->tyenv,src ) == Ity_I32 );
vassert( fld < 8 );
- vassert( reg < PPC32_SPR_MAX );
+ vassert( reg < PPC_GST_MAX );
shft = 4*(7-fld);
mask = 0xF<<shft;
switch (reg) {
- case PPC32_SPR_CR:
+ case PPC_GST_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;
default:
if (shft == 0) {
- putSPR_masked( reg, src, mask );
+ putGST_masked( reg, src, mask );
} else {
- putSPR_masked( reg,
+ putGST_masked( reg,
binop(Iop_Shl32, src, mkU8(toUChar(shft))),
mask );
}
}
}
-static void putSPR ( PPC32SPR reg, IRExpr* src )
-{
- vassert( reg < PPC32_SPR_MAX );
- vassert( typeOfIRExpr(irbb->tyenv,src ) == Ity_I32 );
- switch (reg) {
- case PPC32_SPR_CIA:
- stmt( IRStmt_Put( OFFB_CIA, src ) );
- break;
- case PPC32_SPR_LR:
- stmt( IRStmt_Put( OFFB_LR, src ) );
- break;
- case PPC32_SPR_CTR:
- stmt( IRStmt_Put( OFFB_CTR, src ) );
- break;
- case PPC32_SPR_VRSAVE:
- stmt( IRStmt_Put( OFFB_VRSAVE, src ) );
- break;
- case PPC32_SPR_VSCR:
- 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)");
- }
-}
-
/*------------------------------------------------------------*/
@@ -1702,16 +2392,17 @@
UChar opc1 = ifieldOPC(theInstr);
UChar rD_addr = ifieldRegDS(theInstr);
UChar rA_addr = ifieldRegA(theInstr);
- Int simm16 = ifieldSIMM16(theInstr);
+ UInt uimm16 = ifieldUIMM16(theInstr);
UChar rB_addr = ifieldRegB(theInstr);
UChar flag_OE = ifieldBIT10(theInstr);
UInt opc2 = ifieldOPClo9(theInstr);
UChar flag_rC = ifieldBIT0(theInstr);
- IRTemp rA = newTemp(Ity_I32);
- IRTemp rB = newTemp(Ity_I32);
- IRTemp rD = newTemp(Ity_I32);
- IRTemp res64 = newTemp(Ity_I64); // multiplies need this.
+ Long simm16 = extend_s_16to64(uimm16);
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
+ IRTemp rA = newTemp(ty);
+ IRTemp rB = newTemp(ty);
+ IRTemp rD = newTemp(ty);
Bool do_rc = False;
@@ -1721,19 +2412,21 @@
switch (opc1) {
/* D-Form */
case 0x0C: // addic (Add Immediate Carrying, PPC32 p351
- DIP("addic r%d,r%d,%d\n", rD_addr, rA_addr, simm16);
- assign( rD, binop( Iop_Add32, mkexpr(rA), mkU32(simm16) ) );
+ DIP("addic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
+ assign( rD, binop( mkSizedOp(ty, Iop_Add8), mkexpr(rA),
+ mkSizedExtendS16(ty, uimm16) ) );
set_XER_CA( PPC32G_FLAG_OP_ADD,
- mkexpr(rD), mkexpr(rA), mkU32(simm16),
- mkU32(0)/*old xer.ca, which is ignored*/ );
+ mkexpr(rD), mkexpr(rA), mkSizedExtendS16(ty, uimm16),
+ mkSizedImm(ty, 0)/*old xer.ca, which is ignored*/ );
break;
case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352)
- DIP("addic. r%d,r%d,%d\n", rD_addr, rA_addr, simm16);
- assign( rD, binop( Iop_Add32, mkexpr(rA), mkU32(simm16) ) );
+ DIP("addic. r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
+ assign( rD, binop( mkSizedOp(ty, Iop_Add8), mkexpr(rA),
+ mkSizedExtendS16(ty, uimm16) ) );
set_XER_CA( PPC32G_FLAG_OP_ADD,
- mkexpr(rD), mkexpr(rA), mkU32(simm16),
- mkU32(0)/*old xer.ca, which is ignored*/ );
+ mkexpr(rD), mkexpr(rA), mkSizedExtendS16(ty, uimm16),
+ mkSizedImm(ty, 0)/*old xer.ca, which is ignored*/ );
do_rc = True; // Always record to CR
flag_rC = 1;
break;
@@ -1742,38 +2435,48 @@
// li rD,val == addi rD,0,val
// la disp(rA) == addi rD,rA,disp
if ( rA_addr == 0 ) {
- DIP("li r%d,%d\n", rD_addr, simm16);
- assign( rD, mkU32(simm16) );
+ DIP("li r%u,%d\n", rD_addr, (Int)simm16);
+ assign( rD, mkSizedExtendS16(ty, uimm16) );
} else {
- DIP("addi r%d,r%d,%d\n", rD_addr, rA_addr, simm16);
- assign( rD, binop( Iop_Add32, mkexpr(rA), mkU32(simm16) ) );
+ DIP("addi r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
+ assign( rD, binop( mkSizedOp(ty, Iop_Add8), mkexpr(rA),
+ mkSizedExtendS16(ty, uimm16) ) );
}
break;
case 0x0F: // addis (Add Immediate Shifted, PPC32 p353)
// lis rD,val == addis rD,0,val
if ( rA_addr == 0 ) {
- DIP("lis r%d,%d\n", rD_addr, simm16);
- assign( rD, mkU32(simm16 << 16) );
+ DIP("lis r%u,%d\n", rD_addr, (Int)simm16);
+ assign( rD, mkSizedExtendS32(ty, uimm16 << 16) );
} else {
- DIP("addis r%d,r%d,0x%x\n", rD_addr, rA_addr, simm16);
- assign( rD, binop(Iop_Add32, mkexpr(rA), mkU32(simm16 << 16)) );
+ DIP("addis r%u,r%u,0x%x\n", rD_addr, rA_addr, (Int)simm16);
+ assign( rD, binop( mkSizedOp(ty, Iop_Add8), mkexpr(rA),
+ mkSizedExtendS32(ty, uimm16 << 16) ) );
}
break;
case 0x07: // mulli (Multiply Low Immediate, PPC32 p490)
- DIP("mulli r%d,r%d,%d\n", rD_addr, rA_addr, simm16);
- assign( res64, binop(Iop_MullS32, mkexpr(rA), mkU32(simm16)) );
- assign( rD, unop(Iop_64to32, mkexpr(res64)) );
+ DIP("mulli r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
+ if (mode64)
+ assign( rD, unop(Iop_128to64,
+ binop(Iop_MullS64, mkexpr(rA),
+ mkSizedExtendS16(ty, uimm16))) );
+ else
+ assign( rD, unop(Iop_64to32,
+ binop(Iop_MullS32, mkexpr(rA),
+ mkSizedExtendS16(ty, uimm16))) );
break;
case 0x08: // subfic (Subtract from Immediate Carrying, PPC32 p540)
- DIP("subfic r%d,r%d,%d\n", rD_addr, rA_addr, simm16);
+ DIP("subfic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
// rD = simm16 - rA
- assign( rD, binop(Iop_Sub32, mkU32(simm16), mkexpr(rA)) );
+ assign( rD, binop( mkSizedOp(ty, Iop_Sub8),
+ mkSizedExtendS16(ty, uimm16),
+ mkexpr(rA)) );
set_XER_CA( PPC32G_FLAG_OP_SUBFI,
- mkexpr(rD), mkexpr(rA), mkU32(simm16),
- mkU32(0)/*old xer.ca, which is ignored*/ );
+ mkexpr(rD), mkexpr(rA), mkSizedExtendS16(ty, uimm16),
+ mkSizedImm(ty, 0)/*old xer.ca, which is ignored*/ );
break;
/* XO-Form */
@@ -1782,105 +2485,136 @@
switch (opc2) {
case 0x10A: // add (Add, PPC32 p347)
- DIP("add%s%s r%d,r%d,r%d\n",
+ DIP("add%s%s r%u,r%u,r%u\n",
flag_OE ? "o" : "", flag_rC ? "." : "",
rD_addr, rA_addr, rB_addr);
- assign( rD, binop(Iop_Add32, mkexpr(rA), mkexpr(rB)) );
+ assign( rD, binop( mkSizedOp(ty, Iop_Add8),
+ mkexpr(rA), mkexpr(rB) ) );
if (flag_OE) {
- set_XER_OV( PPC32G_FLAG_OP_ADD,
+ set_XER_OV( ty, PPC32G_FLAG_OP_ADD,
mkexpr(rD), mkexpr(rA), mkexpr(rB) );
}
break;
case 0x00A: // addc (Add Carrying, PPC32 p348)
- DIP("addc%s%s r%d,r%d,r%d\n",
+ DIP("addc%s%s r%u,r%u,r%u\n",
flag_OE ? "o" : "", flag_rC ? "." : "",
rD_addr, rA_addr, rB_addr);
- assign( rD, binop(Iop_Add32, mkexpr(rA), mkexpr(rB)) );
+ assign( rD, binop( mkSizedOp(ty, Iop_Add8),
+ mkexpr(rA), mkexpr(rB)) );
set_XER_CA( PPC32G_FLAG_OP_ADD,
mkexpr(rD), mkexpr(rA), mkexpr(rB),
- mkU32(0)/*old xer.ca, which is ignored*/ );
+ mkSizedImm(ty, 0)/*old xer.ca, which is ignored*/ );
if (flag_OE) {
- set_XER_OV( PPC32G_FLAG_OP_ADD,
+ set_XER_OV( ty, PPC32G_FLAG_OP_ADD,
mkexpr(rD), mkexpr(rA), mkexpr(rB) );
}
break;
case 0x08A: { // adde (Add Extended, PPC32 p349)
- IRTemp old_xer_ca = newTemp(Ity_I32);
- DIP("adde%s%s r%d,r%d,r%d\n",
+ IRExpr* old_xer_ca;
+ DIP("adde%s%s r%u,r%u,r%u\n",
flag_OE ? "o" : "", flag_rC ? "." : "",
rD_addr, rA_addr, rB_addr);
// rD = rA + rB + XER[CA]
- assign( old_xer_ca, getXER_CA32() );
- assign( rD, binop(Iop_Add32, mkexpr(rA),
- binop(Iop_Add32, mkexpr(rB), mkexpr(old_xer_ca))) );
+ old_xer_ca = getXER_CA32();
+ if (mode64) old_xer_ca = unop(Iop_32Uto64, old_xer_ca);
+ assign( rD, binop( mkSizedOp(ty, Iop_Add8), mkexpr(rA),
+ binop( mkSizedOp(ty, Iop_Add8),
+ mkexpr(rB), old_xer_ca)) );
set_XER_CA( PPC32G_FLAG_OP_ADDE,
mkexpr(rD), mkexpr(rA), mkexpr(rB),
- mkexpr(old_xer_ca) );
+ old_xer_ca );
if (flag_OE) {
- set_XER_OV( PPC32G_FLAG_OP_ADDE,
+ set_XER_OV( ty, PPC32G_FLAG_OP_ADDE,
mkexpr(rD), mkexpr(rA), mkexpr(rB) );
}
break;
}
case 0x0EA: { // addme (Add to Minus One Extended, PPC32 p354)
- IRTemp old_xer_ca = newTemp(Ity_I32);
+ IRExpr *old_xer_ca, *min_one;
if (rB_addr != 0) {
vex_printf("dis_int_arith(PPC32)(addme,rB_addr)\n");
return False;
}
- DIP("addme%s%s r%d,r%d,r%d\n",
+ DIP("addme%s%s r%u,r%u,r%u\n",
flag_OE ? "o" : "", flag_rC ? "." : "",
rD_addr, rA_addr, rB_addr);
// rD = rA + (-1) + XER[CA]
// => Just another form of adde
- assign( old_xer_ca, getXER_CA32() );
- assign( rD, binop(Iop_Add32, mkexpr(rA),
- binop(Iop_Add32, mkU32(-1), mkexpr(old_xer_ca)) ));
+ old_xer_ca = getXER_CA32();
+ if (mode64) old_xer_ca = unop(Iop_32Uto64, old_xer_ca);
+ min_one = mkSizedImm(ty, (Long)-1);
+ assign( rD, binop( mkSizedOp(ty, Iop_Add8), mkexpr(rA),
+ binop( mkSizedOp(ty, Iop_Add8),
+ min_one, old_xer_ca) ));
set_XER_CA( PPC32G_FLAG_OP_ADDE,
- mkexpr(rD), mkexpr(rA), mkU32(-1),
- mkexpr(old_xer_ca) );
+ mkexpr(rD), mkexpr(rA), min_one,
+ old_xer_ca );
if (flag_OE) {
- set_XER_OV( PPC32G_FLAG_OP_ADDE,
- mkexpr(rD), mkexpr(rA), mkU32(-1) );
+ set_XER_OV( ty, PPC32G_FLAG_OP_ADDE,
+ mkexpr(rD), mkexpr(rA), min_one );
}
break;
}
case 0x0CA: { // addze (Add to Zero Extended, PPC32 p355)
- IRTemp old_xer_ca = newTemp(Ity_I32);
+ IRExpr* old_xer_ca;
if (rB_addr != 0) {
vex_printf("dis_int_arith(PPC32)(addze,rB_addr)\n");
return False;
}
- DIP("addze%s%s r%d,r%d,r%d\n",
+ DIP("addze%s%s r%u,r%u,r%u\n",
flag_OE ? "o" : "", flag_rC ? "." : "",
rD_addr, rA_addr, rB_addr);
// rD = rA + (0) + XER[CA]
// => Just another form of adde
- assign( old_xer_ca, getXER_CA32() );
- assign( rD, binop(Iop_Add32, mkexpr(rA), mkexpr(old_xer_ca)) );
+ old_xer_ca = getXER_CA32();
+ if (mode64) old_xer_ca = unop(Iop_32Uto64, old_xer_ca);
+ assign( rD, binop( mkSizedOp(ty, Iop_Add8),
+ mkexpr(rA), old_xer_ca) );
set_XER_CA( PPC32G_FLAG_OP_ADDE,
- mkexpr(rD), mkexpr(rA), mkU32(0),
- mkexpr(old_xer_ca) );
+ mkexpr(rD), mkexpr(rA), mkSizedImm(ty, 0),
+ old_xer_ca );
if (flag_OE) {
- set_XER_OV( PPC32G_FLAG_OP_ADDE,
- mkexpr(rD), mkexpr(rA), mkU32(0) );
+ set_XER_OV( ty, PPC32G_FLAG_OP_ADDE,
+ mkexpr(rD), mkexpr(rA), mkSizedImm(ty, 0) );
}
break;
}
case 0x1EB: // divw (Divide Word, PPC32 p388)
- DIP("divw%s%s r%d,r%d,r%d\n",
+ DIP("divw%s%s r%u,r%u,r%u\n",
flag_OE ? "o" : "", flag_rC ? "." : "",
rD_addr, rA_addr, rB_addr);
- assign( rD, binop(Iop_DivS32, mkexpr(rA), mkexpr(rB)) );
- if (flag_OE) {
- set_XER_OV( PPC32G_FLAG_OP_DIVW,
- mkexpr(rD), mkexpr(rA), mkexpr(rB) );
+ if (mode64) {
+#if 0
+// CAB: TODO
+ IRExpr* dividend = unop(Iop_32Sto64,
+ unop(Iop_64to32, mkexpr(rA)));
+ IRExpr* divisor = unop(Iop_32Sto64,
+ unop(Iop_64to32, mkexpr(rB)));
+ assign( rD, binop(Iop_DivS64, dividend, divisor) );
+#endif
+ IRExpr* dividend = unop(Iop_64to32, mkexpr(rA));
+ IRExpr* divisor = unop(Iop_64to32, mkexpr(rB));
+ assign( rD, binop(Iop_DivS32, dividend, divisor) );
+
+ if (flag_OE) {
+ // CAB: swap rA for dividend, rB for divisor?
+ // zero top half of rD ?
+ set_XER_OV( ty, PPC32G_FLAG_OP_DIVW,
+ mkexpr(rD), mkexpr(rA), mkexpr(rB) );
+ }
+ } else {
+ assign( rD, binop(Iop_DivS32, mkexpr(rA), mkexpr(rB)) );
+ if (flag_OE) {
+ set_XER_OV( ty, PPC32G_FLAG_OP_DIVW,
+ mkexpr(rD), mkexpr(rA), mkexpr(rB) );
+ }
}
+
/* Note:
if (0x8000_0000 / -1) or (x / 0)
=> rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
@@ -1888,13 +2622,34 @@
break;
case 0x1CB: // divwu (Divide Word Unsigned, PPC32 p389)
- DIP("divwu%s%s r%d,r%d,r%d\n",
+ DIP("divwu%s%s r%u,r%u,r%u\n",
flag_OE ? "o" : "", flag_rC ? "." : "",
rD_addr, rA_addr, rB_addr);
- assign( rD, binop(Iop_DivU32, mkexpr(rA), mkexpr(rB)) );
- if (flag_OE) {
- set_XER_OV( PPC32G_FLAG_OP_DIVWU,
- mkexpr(rD), mkexpr(rA), mkexpr(rB) );
+ if (mode64) {
+#if 0
+// CAB: TODO
+ IRExpr* dividend = unop(Iop_32Sto64,
+ unop(Iop_64to32, mkexpr(rA)));
+ IRExpr* divisor = unop(Iop_32Sto64,
+ unop(Iop_64to32, mkexpr(rB)));
+ assign( rD, binop(Iop_DivU64, dividend, divisor) );
+#endif
+ IRExpr* dividend = unop(Iop_64to32, mkexpr(rA));
+ IRExpr* divisor = unop(Iop_64to32, mkexpr(rB));
+ assign( rD, binop(Iop_DivU32, dividend, divisor) );
+
+ if (flag_OE) {
+ // CAB: swap rA for dividend, rB for divisor?
+ // zero top half of rD ?
+ set_XER_OV( ty, PPC32G_FLAG_OP_DIVWU,
+ mkexpr(rD), mkexpr(rA), mkexpr(rB) );
+ }
+ }else {
+ assign( rD, binop(Iop_DivU32, mkexpr(rA), mkexpr(rB)) );
+ if (flag_OE) {
+ set_XER_OV( ty, PPC32G_FLAG_OP_DIVWU,
+ mkexpr(rD), mkexpr(rA), mkexpr(rB) );
+ }
}
/* Note: ditto comment divw, for (x / 0) */
break;
@@ -1904,10 +2659,16 @@
vex_printf("dis_int_arith(PPC32)(mulhw,flag_OE)\n");
return False;
}
- DIP("mulhw%s r%d,r%d,r%d\n", flag_rC ? "." : "",
+ DIP("mulhw%s r%u,r%u,r%u\n", flag_rC ? "." : "",
rD_addr, rA_addr, rB_addr);
- assign( res64, binop(Iop_MullS32, mkexpr(rA), mkexpr(rB)) );
- assign( rD, unop(Iop_64HIto32, mkexpr(res64)) );
+ if (mode64)
+ assign( rD, unop(Iop_128HIto64,
+ binop(Iop_MullS64,
+ mkexpr(rA), mkexpr(rB))) );
+ else
+ assign( rD, unop(Iop_64HIto32,
+ binop(Iop_MullS32,
+ mkexpr(rA), mkexpr(rB))) );
break;
case 0x00B: // mulhwu (Multiply High Word Unsigned, PPC32 p489)
@@ -1915,20 +2676,32 @@
vex_printf("dis_int_arith(PPC32)(mulhwu,flag_OE)\n");
return False;
}
- DIP("mulhwu%s r%d,r%d,r%d\n", flag_rC ? "." : "",
+ DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC ? "." : "",
rD_addr, rA_addr, rB_addr);
- assign( res64, binop(Iop_MullU32, mkexpr(rA), mkexpr(rB)) );
- assign( rD, unop(Iop_64HIto32, mkexpr(res64)) );
+ if (mode64)
+ assign( rD, unop(Iop_128HIto64,
+ binop(Iop_MullU64,
+ mkexpr(rA), mkexpr(rB))) );
+ else
+ assign( rD, unop(Iop_64HIto32,
+ binop(Iop_MullU32,
+ mkexpr(rA), mkexpr(rB))) );
break;
case 0x0EB: // mullw (Multiply Low Word, PPC32 p491)
- DIP("mullw%s%s r%d,r%d,r%d\n",
+ DIP("mullw%s%s r%u,r%u,r%u\n",
flag_OE ? "o" : "", flag_rC ? "." : "",
rD_addr, rA_addr, rB_addr);
- assign( res64, binop(Iop_MullU32, mkexpr(rA), mkexpr(rB)) );
- assign( rD, unop(Iop_64to32, mkexpr(res64)) );
+ if (mode64)
+ assign( rD, unop(Iop_128to64,
+ binop(Iop_MullU64,
+ mkexpr(rA), mkexpr(rB))) );
+ else
+ assign( rD, unop(Iop_64to32,
+ binop(Iop_MullU32,
+ mkexpr(rA), mkexpr(rB))) );
if (flag_OE) {
- set_XER_OV( PPC32G_FLAG_OP_MULLW,
+ set_XER_OV( ty, PPC32G_FLAG_OP_MULLW,
mkexpr(rD), mkexpr(rA), mkexpr(rB) );
}
break;
@@ -1938,108 +2711,120 @@
vex_printf("dis_int_arith(PPC32)(neg,rB_addr)\n");
return False;
}
- DIP("neg%s%s r%d,r%d\n",
+ DIP("neg%s%s r%u,r%u\n",
flag_OE ? "o" : "", flag_rC ? "." : "",
rD_addr, rA_addr);
- // rD = (log not)rA + 1
- assign( rD, binop(Iop_Add32,
- unop(Iop_Not32, mkexpr(rA)), mkU32(1)) );
+ // rD = (~rA) + 1
+ assign( rD, binop( mkSizedOp(ty, Iop_Add8),
+ unop( mkSizedOp(ty, Iop_Not8), mkexpr(rA) ),
+ mkSizedImm(ty, 1)) );
if (flag_OE) {
- set_XER_OV( PPC32G_FLAG_OP_NEG,
+ set_XER_OV( ty, PPC32G_FLAG_OP_NEG,
mkexpr(rD), mkexpr(rA), mkexpr(rB) );
}
break;
case 0x028: // subf (Subtract From, PPC32 p537)
- DIP("subf%s%s r%d,r%d,r%d\n",
+ DIP("subf%s%s r%u,r%u,r%u\n",
flag_OE ? "o" : "", flag_rC ? "." : "",
rD_addr, rA_addr, rB_addr);
// rD = rB - rA
- assign( rD, binop(Iop_Sub32, mkexpr(rB), mkexpr(rA)) );
+ assign( rD, binop( mkSizedOp(ty, Iop_Sub8),
+ mkexpr(rB), mkexpr(rA)) );
if (flag_OE) {
- set_XER_OV( PPC32G_FLAG_OP_SUBF,
+ set_XER_OV( ty, PPC32G_FLAG_OP_SUBF,
mkexpr(rD), mkexpr(rA), mkexpr(rB) );
}
break;
case 0x008: // subfc (Subtract from Carrying, PPC32 p538)
- DIP("subfc%s%s r%d,r%d,r%d\n",
+ DIP("subfc%s%s r%u,r%u,r%u\n",
flag_OE ? "o" : "", flag_rC ? "." : "",
rD_addr, rA_addr, rB_addr);
// rD = rB - rA
- assign( rD, binop(Iop_Sub32, mkexpr(rB), mkexpr(rA)) );
+ assign( rD, binop( mkSizedOp(ty, Iop_Sub8),
+ mkexpr(rB), mkexpr(rA)) );
set_XER_CA( PPC32G_FLAG_OP_SUBFC,
mkexpr(rD), mkexpr(rA), mkexpr(rB),
- mkU32(0)/*old xer.ca, which is ignored*/ );
+ mkSizedImm(ty, 0)/*old xer.ca, which is ignored*/ );
if (flag_OE) {
- set_XER_OV( PPC32G_FLAG_OP_SUBFC,
+ set_XER_OV( ty, PPC32G_FLAG_OP_SUBFC,
mkexpr(rD), mkexpr(rA), mkexpr(rB) );
}
break;
case 0x088: {// subfe (Subtract from Extended, PPC32 p539)
- IRTemp old_xer_ca = newTemp(Ity_I32);
- DIP("subfe%s%s r%d,r%d,r%d\n",
+ IRExpr* old_xer_ca;
+ DIP("subfe%s%s r%u,r%u,r%u\n",
flag_OE ? "o" : "", flag_rC ? "." : "",
rD_addr, rA_addr, rB_addr);
// rD = (log not)rA + rB + XER[CA]
- assign( old_xer_ca, getXER_CA32() );
- assign( rD, binop(Iop_Add32, unop(Iop_Not32, mkexpr(rA)),
- binop(Iop_Add32, mkexpr(rB), mkexpr(old_xer_ca))) );
+ old_xer_ca = getXER_CA32();
+ if (mode64) old_xer_ca = unop(Iop_32Uto64, old_xer_ca);
+ assign( rD, binop( mkSizedOp(ty, Iop_Add8),
+ unop( mkSizedOp(ty, Iop_Not8), mkexpr(rA)),
+ binop( mkSizedOp(ty, Iop_Add8),
+ mkexpr(rB), old_xer_ca)) );
set_XER_CA( PPC32G_FLAG_OP_SUBFE,
mkexpr(rD), mkexpr(rA), mkexpr(rB),
- mkexpr(old_xer_ca) );
+ old_xer_ca );
if (flag_OE) {
- set_XER_OV( PPC32G_FLAG_OP_SUBFE,
+ set_XER_OV( ty, PPC32G_FLAG_OP_SUBFE,
mkexpr(rD), mkexpr(rA), mkexpr(rB) );
}
break;
}
case 0x0E8: { // subfme (Subtract from Minus One Extended, PPC32 p541)
- IRTemp old_xer_ca = newTemp(Ity_I32);
+ IRExpr *old_xer_ca, *min_one;
if (rB_addr != 0) {
vex_printf("dis_int_arith(PPC32)(subfme,rB_addr)\n");
return False;
}
- DIP("subfme%s%s r%d,r%d\n",
+ DIP("subfme%s%s r%u,r%u\n",
flag_OE ? "o" : "", flag_rC ? "." : "",
rD_addr, rA_addr);
// rD = (log not)rA + (-1) + XER[CA]
// => Just another form of subfe
- 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))) );
+ old_xer_ca = getXER_CA32();
+ if (mode64) old_xer_ca = unop(Iop_32Uto64, old_xer_ca);
+ min_one = mkSizedImm(ty, (Long)-1);
+ assign( rD, binop( mkSizedOp(ty, Iop_Add8),
+ unop( mkSizedOp(ty, Iop_Not8), mkexpr(rA)),
+ binop( mkSizedOp(ty, Iop_Add8),
+ min_one, old_xer_ca)) );
set_XER_CA( PPC32G_FLAG_OP_SUBFE,
- mkexpr(rD), mkexpr(rA), mkU32(-1),
- mkexpr(old_xer_ca) );
+ mkexpr(rD), mkexpr(rA), min_one,
+ old_xer_ca );
if (flag_OE) {
- set_XER_OV( PPC32G_FLAG_OP_SUBFE,
- mkexpr(rD), mkexpr(rA), mkU32(-1) );
+ set_XER_OV( ty, PPC32G_FLAG_OP_SUBFE,
+ mkexpr(rD), mkexpr(rA), min_one );
}
break;
}
case 0x0C8: { // subfze (Subtract from Zero Extended, PPC32 p542)
- IRTemp old_xer_ca = newTemp(Ity_I32);
+ IRExpr* old_xer_ca;
if (rB_addr != 0) {
vex_printf("dis_int_arith(PPC32)(subfze,rB_addr)\n");
return False;
}
- DIP("subfze%s%s r%d,r%d\n",
+ DIP("subfze%s%s r%u,r%u\n",
flag_OE ? "o" : "", flag_rC ? "." : "",
rD_addr, rA_addr);
// rD = (log not)rA + (0) + XER[CA]
// => Just another form of subfe
- assign( old_xer_ca, getXER_CA32() );
- assign( rD, binop(Iop_Add32,
- unop(Iop_Not32, mkexpr(rA)), mkexpr(old_xer_ca)) );
+ old_xer_ca = getXER_CA32();
+ if (mode64) old_xer_ca = unop(Iop_32Uto64, old_xer_ca);
+ assign( rD, binop( mkSizedOp(ty, Iop_Add8),
+ unop( mkSizedOp(ty, Iop_Not8),
+ mkexpr(rA)), old_xer_ca) );
set_XER_CA( PPC32G_FLAG_OP_SUBFE,
- mkexpr(rD), mkexpr(rA), mkU32(0),
- mkexpr(old_xer_ca) );
+ mkexpr(rD), mkexpr(rA), mkSizedImm(ty, 0),
+ old_xer_ca );
if (flag_OE) {
- set_XER_OV( PPC32G_FLAG_OP_SUBFE,
- mkexpr(rD), mkexpr(rA), mkU32(0) );
+ set_XER_OV( ty, PPC32G_FLAG_OP_SUBFE,
+ mkexpr(rD), mkexpr(rA), mkSizedImm(ty, 0) );
}
break;
}
@@ -2075,18 +2860,20 @@
UChar b22 = toUChar( IFIELD( theInstr, 22, 1 ) );
UChar flag_L = toUChar( IFIELD( theInstr, 21, 1 ) );
UChar rA_addr = ifieldRegA(theInstr);
- UInt UIMM_16 = ifieldUIMM16(theInstr);
+ UInt uimm16 = ifieldUIMM16(theInstr);
UChar rB_addr = ifieldRegB(theInstr);
UInt opc2 = ifieldOPClo10(theInstr);
UChar b0 = ifieldBIT0(theInstr);
- Int EXTS_SIMM = extend_s_16to32(UIMM_16);
- IRTemp rA = newTemp(Ity_I32);
- IRTemp rB = newTemp(Ity_I32);
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
+ IRTemp rA = newTemp(ty);
+ IRTemp rB = newTemp(ty);
- assign( rA, getIReg(rA_addr) );
+ assign(rA, getIReg(rA_addr));
+ IRExpr* a = mkexpr(rA);
+ IRExpr* b;
- if (flag_L==1) { // L==1 invalid for 32 bit.
+ if (!mode64 && flag_L==1) { // L==1 invalid for 32 bit.
vex_printf("dis_int_cmp(PPC32)(flag_L)\n");
return False;
}
@@ -2097,21 +2884,32 @@
}
switch (opc1) {
- case 0x0B: // cmpi (Compare Immediate, PPC32 p368)
- DIP("cmp cr%d,r%d,%d\n", crfD, rA_addr, EXTS_SIMM);
- putCR321( crfD, unop(Iop_32to8,
- binop(Iop_CmpORD32S, mkexpr(rA),
- mkU32(EXTS_SIMM))) );
- putCR0( crfD, getXER_SO() );
- break;
-
- case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370)
- DIP("cmpli cr%d,r%d,0x%x\n", crfD, rA_addr, UIMM_16);
- putCR321( crfD, unop(Iop_32to8,
- binop(Iop_CmpORD32U, mkexpr(rA),
- mkU32(UIMM_16))) );
- putCR0( crfD, getXER_SO() );
- break;
+ case 0x0B: // cmpi (Compare Immediate, PPC32 p368)
+ DIP("cmpi cr%u,%u,r%u,%d\n", crfD, flag_L, rA_addr,
+ (Int)extend_s_16to32(uimm16));
+ b = mkSizedExtendS16( ty, uimm16 );
+ if (mode64) {
+ if (flag_L == 0) a = mkExtendLoS32( mkexpr(rA) );
+// CAB TODO: new Iop_CmpORD64S
+// putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
+ } else {
+ putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32S, a, b)));
+ }
+ putCR0( crfD, getXER_SO() );
+ break;
+
+ case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370)
+ DIP("cmpli cr%u,%u,r%u,0x%x\n", crfD, flag_L, rA_addr, uimm16);
+ b = mkSizedExtendS16( ty, uimm16 );
+ if (mode64) {
+ if (flag_L == 0) a = mkExtendLoS32( mkexpr(rA) );
+// CAB TODO: new Iop_CmpORD64U
+// putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
+ } else {
+ putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
+ }
+ putCR0( crfD, getXER_SO() );
+ break;
/* X Form */
case 0x1F:
@@ -2119,29 +2917,46 @@
vex_printf("dis_int_cmp(PPC32)(0x1F,b0)\n");
return False;
}
- assign( rB, getIReg(rB_addr) );
+ assign(rB, getIReg(rB_addr));
+ b = mkexpr(rB);
+ if (flag_L == 0) {
+ a = mkExtendLoS32( mkexpr(rA) );
+ b = mkExtendLoS32( mkexpr(rB) );
+ }
switch (opc2) {
- case 0x000: // cmp (Compare, PPC32 p367)
- DIP("cmp cr%d,r%d,r%d\n", crfD, rA_addr, rB_addr);
+ case 0x000: // cmp (Compare, PPC32 p367)
+ DIP("cmp cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
+ if (mode64) {
+// CAB TODO: new Iop_CmpORD64S
+// putCR321( crfD, unop(Iop_64to8,
+// binop(Iop_CmpORD64S, a, b)) );
+ } else {
putCR321( crfD, unop(Iop_32to8,
- binop(Iop_CmpORD32S, mkexpr(rA), mkexpr(rB))) );
- putCR0( crfD, getXER_SO() );
- break;
+ binop(Iop_CmpORD32S, a, b)) );
+ }
+ putCR0( crfD, getXER_SO() );
+ break;
- case 0x020: // cmpl (Compare Logical, PPC32 p369)
- DIP("cmpl cr%d,r%d,r%d\n", crfD, rA_addr, rB_addr);
+ case 0x020: // cmpl (Compare Logical, PPC32 p369)
+ DIP("cmpl cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
+ if (mode64) {
+// CAB TODO: new Iop_CmpORD64S
+// putCR321( crfD, unop(Iop_64to8,
+// binop(Iop_CmpORD64U, a, b)) );
+ } else {
putCR321( crfD, unop(Iop_32to8,
- binop(Iop_CmpORD32U, mkexpr(rA), mkexpr(rB))) );
- putCR0( crfD, getXER_SO() );
- break;
+ binop(Iop_CmpORD32U, a, b)) );
+ }
+ putCR0( crfD, getXER_SO() );
+ break;
- default:
- vex_printf("dis_int_cmp(PPC32)(opc2)\n");
- return False;
+ default:
+ vex_printf("dis_int_cmp(PPC32)(opc2)\n");
+ return False;
}
break;
-
+
default:
vex_printf("dis_int_cmp(PPC32)(opc1)\n");
return False;
@@ -2160,54 +2975,60 @@
UChar opc1 = ifieldOPC(theInstr);
UChar rS_addr = ifieldRegDS(theInstr);
UChar rA_addr = ifieldRegA(theInstr);
- UInt UIMM_16 = ifieldUIMM16(theInstr);
+ UInt uimm16 = ifieldUIMM16(theInstr);
UChar rB_addr = ifieldRegB(theInstr);
UInt opc2 = ifieldOPClo10(theInstr);
UChar flag_rC = ifieldBIT0(theInstr);
- Bool do_rc = False;
-
- IRTemp rS = newTemp(Ity_I32);
- IRTemp rA = newTemp(Ity_I32);
- IRTemp rB = newTemp(Ity_I32);
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
+ IRTemp rS = newTemp(ty);
+ IRTemp rA = newTemp(ty);
+ IRTemp rB = newTemp(ty);
IRExpr* irx;
-
+ Bool do_rc = False;
+
assign( rS, getIReg(rS_addr) );
assign( rB, getIReg(rB_addr) );
switch (opc1) {
case 0x1C: // andi. (AND Immediate, PPC32 p358)
- DIP("andi. r%d,r%d,0x%x\n", rA_addr, rS_addr, UIMM_16);
- assign( rA, binop(Iop_And32, mkexpr(rS), mkU32(UIMM_16)) );
+ DIP("andi. r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
+ assign( rA, binop( mkSizedOp(ty, Iop_And8), mkexpr(rS),
+ mkSizedExtendS16(ty, uimm16)) );
do_rc = True; // Always record to CR
flag_rC = 1;
break;
case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359)
- DIP("andis r%d,r%d,0x%x\n", rA_addr, rS_addr, UIMM_16);
- assign( rA, binop(Iop_And32, mkexpr(rS), mkU32(UIMM_16 << 16)) );
+ DIP("andis r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
+ assign( rA, binop( mkSizedOp(ty, Iop_And8), mkexpr(rS),
+ mkSizedExtendS32(ty, uimm16 << 16)) );
do_rc = True; // Always record to CR
flag_rC = 1;
break;
case 0x18: // ori (OR Immediate, PPC32 p497)
- DIP("ori r%d,r%d,0x%x\n", rA_addr, rS_addr, UIMM_16);
- assign( rA, binop(Iop_Or32, mkexpr(rS), mkU32(UIMM_16)) );
+ DIP("ori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
+ assign( rA, binop( mkSizedOp(ty, Iop_Or8), mkexpr(rS),
+ mkSizedExtendS16(ty, uimm16)) );
break;
case 0x19: // oris (OR Immediate Shifted, PPC32 p498)
- DIP("oris r%d,r%d,0x%x\n", rA_addr, rS_addr, UIMM_16);
- assign( rA, binop(Iop_Or32, mkexpr(rS), mkU32(UIMM_16 << 16)) );
+ DIP("oris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
+ assign( rA, binop( mkSizedOp(ty, Iop_Or8), mkexpr(rS),
+ mkSizedExtendS32(ty, uimm16 << 16)) );
break;
case 0x1A: // xori (XOR Immediate, PPC32 p550)
- DIP("xori r%d,r%d,0x%x\n", rA_addr, rS_addr, UIMM_16);
- assign( rA, binop(Iop_Xor32, mkexpr(rS), mkU32(UIMM_16)) );
+ DIP("xori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
+ assign( rA, binop( mkSizedOp(ty, Iop_Xor8), mkexpr(rS),
+ mkSizedExtendS16(ty, uimm16)) );
break;
case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551)
- DIP("xoris r%d,r%d,0x%x\n", rA_addr, rS_addr, UIMM_16);
- assign( rA, binop(Iop_Xor32, mkexpr(rS), mkU32(UIMM_16 << 16)) );
+ DIP("xoris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
+ assign( rA, binop( mkSizedOp(ty, Iop_Xor8), mkexpr(rS),
+ mkSizedExtendS32(ty, uimm16 << 16)) );
break;
/* X Form */
@@ -2215,40 +3036,48 @@
do_rc = True; // All below record to CR
switch (opc2) {
- case 0x01C: // and (AND, PPC32 p356)
- DIP("and%s r%d,r%d,r%d\n",
- flag_rC ? "." : "", rA_addr, rS_addr, rB_addr);
- assign(rA, binop(Iop_And32, mkexpr(rS), mkexpr(rB)));
- break;
-
- case 0x03C: // andc (AND with Complement, PPC32 p357)
- DIP("andc%s r%d,r%d,r%d\n",
- flag_rC ? "." : "", rA_addr, rS_addr, rB_addr);
- assign(rA, binop(Iop_And32, mkexpr(rS),
- unop(Iop_Not32, mkexpr(rB))));
- break;
-
- case 0x01A: // cntlzw (Count Leading Zeros Word, PPC32 p371)
- if (rB_addr!=0) {
- vex_printf("dis_int_logic(PPC32)(cntlzw,rB_addr)\n");
- return False;
- }
- DIP("cntlzw%s r%d,r%d\n",
- flag_rC ? "." : "", rA_addr, rS_addr);
-
- // Iop_Clz32 undefined for arg==0, so deal with that case:
- irx = binop(Iop_CmpNE32, mkexpr(rS), mkU32(0));
- assign(rA, IRExpr_Mux0X( unop(Iop_1Uto8, irx),
- mkU32(32),
- unop(Iop_Clz32, mkexpr(rS)) ));
- // alternatively: assign(rA, verbose_Clz32(rS));
- break;
-
- case 0x11C: // eqv (Equivalent, PPC32 p396)
- DIP("eqv%s r%d,r%d,r%d\n",
+ case 0x01C: // and (AND, PPC32 p356)
+ DIP("and%s r%u,r%u,r%u\n",
flag_rC ? "." : "", rA_addr, rS_addr, rB_addr);
- assign( rA, unop(Iop_Not32, binop(Iop_Xor32,
- mkexpr(rS), mkexpr(rB))) );
+ assign(rA, binop( mkSizedOp(ty, Iop_And8),
+ mkexpr(rS), mkexpr(rB)));
+ break;
+
+ case 0x03C: // andc (AND with Complement, PPC32 p357)
+ DIP("andc%s r%u,r%u,r%u\n",
+ flag_rC ? "." : "", rA_addr, rS_addr, rB_addr);
+ assign(rA, binop( mkSizedOp(ty, Iop_And8), mkexpr(rS),
+ unop( mkSizedOp(ty, Iop_Not8),
+ mkexpr(rB))));
+ break;
+
+ case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371)
+ IRExpr* lo32;
+ if (rB_addr!=0) {
+ vex_printf("dis_int_logic(PPC32)(cntlzw,rB_addr)\n");
+ return False;
+ }
+ DIP("cntlzw%s r%u,r%u\n",
+ flag_rC ? "." : "", rA_addr, rS_addr);
+
+ // mode64: count in low word only
+ lo32 = mode64 ? unop(Iop_64to32, mkexpr(rS)) : mkexpr(rS);
+
+ // Iop_Clz32 undefined for arg==0, so deal with that case:
+ irx = binop(Iop_CmpNE32, lo32, mkU32(0));
+ assign(rA, IRExpr_Mux0X( unop(Iop_1Uto8, irx),
+ mkU32(32),
+ unop(Iop_Clz32, lo32) ));
+ // TODO: alternatively: assign(rA, verbose_Clz32(rS));
+ break;
+ }
+
+ case 0x11C: // eqv (Equivalent, PPC32 p396)
+ DIP("eqv%s r%u,r%u,r%u\n",
+ flag_rC ? "." : "", rA_addr, rS_addr, rB_addr);
+ assign( rA, unop( mkSizedOp(ty, Iop_Not8),
+ binop( mkSizedOp(ty, Iop_Xor8),
+ mkexpr(rS), mkexpr(rB))) );
break;
case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397
@@ -2256,9 +3085,12 @@
vex_printf("dis_int_logic(PPC32)(extsb,rB_addr)\n");
return False;
}
- DIP("extsb%s r%d,r%d\n",
+ DIP("extsb%s r%u,r%u\n",
flag_rC ? "." : "", rA_addr, rS_addr);
- assign( rA, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rS))) );
+ if (mode64)
+ assign( rA, unop(Iop_8Sto64, unop(Iop_64to8, mkexpr(rS))) );
+ else
+ assign( rA, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rS))) );
break;
case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398)
@@ -2266,47 +3098,54 @@
vex_printf("dis_int_logic(PPC32)(extsh,rB_addr)\n");
return False;
}
- DIP("extsh%s r%d,r%d\n",
+ DIP("extsh%s r%u,r%u\n",
flag_rC ? "." : "", rA_addr, rS_addr);
- assign( rA, unop(Iop_16Sto32, unop(Iop_32to16, mkexpr(rS))) );
+ if (mode64)
+ assign( rA, unop(Iop_16Sto64, unop(Iop_64to16, mkexpr(rS))) );
+ else
+ assign( rA, unop(Iop_16Sto32, unop(Iop_32to16, mkexpr(rS))) );
break;
case 0x1DC: // nand (NAND, PPC32 p492)
- DIP("nand%s r%d,r%d,r%d\n",
+ DIP("nand%s r%u,r%u,r%u\n",
flag_rC ? "." : "", rA_addr, rS_addr, rB_addr);
- assign( rA, unop(Iop_Not32,
- binop(Iop_And32, mkexpr(rS), mkexpr(rB))) );
+ assign( rA, unop( mkSizedOp(ty, Iop_Not8),
+ binop( mkSizedOp(ty, Iop_And8),
+ mkexpr(rS), mkexpr(rB))) );
break;
case 0x07C: // nor (NOR, PPC32 p494)
- DIP("nor%s r%d,r%d,r%d\n",
+ DIP("nor%s r%u,r%u,r%u\n",
flag_rC ? "." : "", rA_addr, rS_addr, rB_addr);
- assign( rA, unop(Iop_Not32,
- binop(Iop_Or32, mkexpr(rS), mkexpr(rB))) );
+ assign( rA, unop( mkSizedOp(ty, Iop_Not8),
+ binop( mkSizedOp(ty, Iop_Or8),
+ mkexpr(rS), mkexpr(rB))) );
break;
case 0x1BC: // or (OR, PPC32 p495)
if ((!flag_rC) && rS_addr == rB_addr) {
- DIP("mr r%d,r%d\n", rA_addr, rS_addr);
+ DIP("mr r%u,r%u\n", rA_addr, rS_addr);
assign( rA, mkexpr(rS) );
} else {
- DIP("or%s r%d,r%d,r%d\n",
+ DIP("or%s r%u,r%u,r%u\n",
flag_rC ? "." : "", rA_addr, rS_addr, rB_addr);
- assign( rA, binop(Iop_Or32, mkexpr(rS), mkexpr(rB)) );
+ assign( rA, binop( mkSizedOp(ty, Iop_Or8),
+ mkexpr(rS), mkexpr(rB)) );
}
break;
case 0x19C: // orc (OR with Complement, PPC32 p496)
- DIP("orc%s r%d,r%d,r%d\n",
+ DIP("orc%s r%u,r%u,r%u\n",
flag_rC ? "." : "", rA_addr, rS_addr, rB_addr);
- assign( rA, binop(Iop_Or32, mkexpr(rS),
- unop(Iop_Not32, mkexpr(rB))) );
+ assign( rA, binop( mkSizedOp(ty, Iop_Or8), mkexpr(rS),
+ unop(mkSizedOp(ty, Iop_Not8), mkexpr(rB))));
break;
case 0x13C: // xor (XOR, PPC32 p549)
- DIP("xor%s r%d,r%d,r%d\n",
+ DIP("xor%s r%u,r%u,r%u\n",
flag_rC ? "." : "", rA_addr, rS_addr, rB_addr);
- assign( rA, binop(Iop_Xor32, mkexpr(rS), mkexpr(rB)) );
+ assign( rA, binop( mkSizedOp(ty, Iop_Xor8),
+ mkexpr(rS), mkexpr(rB)) );
break;
default:
@@ -2336,75 +3175,123 @@
static Bool dis_int_rot ( UInt theInstr )
{
/* M-Form */
- UChar opc1 = ifieldOPC(theInstr);
- UChar rS_addr = ifieldRegDS(theInstr);
- UChar rA_addr = ifieldRegA(theInstr);
- UChar rB_addr = ifieldRegB(theInstr);
- UChar sh_imm = rB_addr;
- UChar MaskBegin = toUChar( IFIELD( theInstr, 6, 5 ) );
- UChar MaskEnd = toUChar( IFIELD( theInstr, 1, 5 ) );
- UChar flag_rC = ifieldBIT0(theInstr);
+ UChar opc1 = ifieldOPC(theInstr);
+ UChar rS_addr = ifieldRegDS(theInstr);
+ UChar rA_addr = ifieldRegA(theInstr);
+ UChar rB_addr = ifieldRegB(theInstr);
+ UChar sh_imm = rB_addr;
+ UChar MaskBeg = toUChar( IFIELD( theInstr, 6, 5 ) );
+ UChar MaskEnd = toUChar( IFIELD( theInstr, 1, 5 ) );
+ UChar flag_rC = ifieldBIT0(theInstr);
- UInt mask = MASK(31-MaskEnd, 31-MaskBegin);
- IRTemp rS = newTemp(Ity_I32);
- IRTemp rA = newTemp(Ity_I32);
- IRTemp rB = newTemp(Ity_I32);
-
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
+ IRTemp rS = newTemp(ty);
+ IRTemp rA = newTemp(ty);
+ IRTemp rB = newTemp(ty);
+ IRExpr *r;
+
assign( rS, getIReg(rS_addr) );
assign( rB, getIReg(rB_addr) );
-
+
switch (opc1) {
- case 0x14:
+ case 0x14: {
// rlwimi (Rotate Left Word Immediate then Mask Insert, PPC32 p500)
- DIP("rlwimi%s r%d,r%d,%d,%d,%d\n", flag_rC ? "." : "",
- rA_addr, rS_addr, sh_imm, MaskBegin, MaskEnd);
- // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask);
- assign( rA, binop(Iop_Or32,
- binop(Iop_And32, mkU32(mask),
- ROTL32(mkexpr(rS), mkU32(sh_imm))),
- binop(Iop_And32, getIReg(rA_addr), mkU32(~mask))) );
- break;
-
- case 0x15:
- // rlwinm (Rotate Left Word Immediate then AND with Mask, PPC32 p501)
- vassert(MaskBegin < 32);
- vassert(MaskEnd < 32);
- vassert(sh_imm < 32);
-
- if (MaskBegin == 0 && sh_imm+MaskEnd == 31) {
- /* Special-case the ,n,0,31-n form as that is just n-bit
- shift left (PPC32 p501) */
- DIP("slwi%s r%d,r%d,%d\n", flag_rC ? "." : "",
- rA_addr, rS_addr, sh_imm);
- assign( rA, binop(Iop_Shl32, mkexpr(rS), mkU8(sh_imm)) );
- }
- else
- if (MaskEnd == 31 && sh_imm+MaskBegin == 32) {
- /* Special-case the ,32-n,n,31 form as that is just n-bit
- unsigned shift right (PPC32 p501) */
- DIP("srwi%s r%d,r%d,%d\n", flag_rC ? "." : "",
- rA_addr, rS_addr, sh_imm);
- assign( rA, binop(Iop_Shr32, mkexpr(rS), mkU8(MaskBegin)) );
+ DIP("rlwimi%s r%u,r%u,%d,%d,%d\n", flag_rC ? "." : "",
+ rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
+ if (mode64) {
+ // tmp32 = (ROTL(rS_Lo32, Imm)
+ // rA = ((tmp32 || tmp32) & mask64) | (rA & ~mask64)
+ ULong mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
+ r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
+ r = unop(Iop_32Uto64, r);
+ r = binop(Iop_Or64, r, binop(Iop_Shl64, r, mkU8(32)));
+ assign( rA,
+ binop(Iop_Or64,
+ binop(Iop_And64, r, mkU32(mask64)),
+ binop(Iop_And64, getIReg(rA_addr), mkU32(~mask64))) );
}
else {
- /* General case. */
- DIP("rlwinm%s r%d,r%d,%d,%d,%d\n", flag_rC ? "." : "",
- rA_addr, rS_addr, sh_imm, MaskBegin, MaskEnd);
- // rA = ROTL(rS, Imm) & mask
- assign( rA, binop(Iop_And32, ROTL32(mkexpr(rS), mkU32(sh_imm)),
- mkU32(mask)) );
+ // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask);
+ UInt mask = MASK32(31-MaskEnd, 31-MaskBeg);
+ r = ROTL(mkexpr(rS), mkU8(sh_imm));
+ assign( rA,
+ binop(Iop_Or32,
+ binop(Iop_And32, r, mkU32(mask) ),
+ binop(Iop_And32, getIReg(rA_addr), mkU32(~mask))) );
}
break;
+ }
- case 0x17:
- // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503
- DIP("rlwnm%s r%d,r%d,r%d,%d,%d\n", flag_rC ? "." : "",
- rA_addr, rS_addr, rB_addr, MaskBegin, MaskEnd);
- // rA = ROTL(rS, rB[0-4]) & mask
- // note, ROTL32 does the masking, so we don't do it here
- assign( rA, binop(Iop_And32, ROTL32(mkexpr(rS), mkexpr(rB)),
- mkU32(mask)) );
+ case 0x15: {
+ // rlwinm (Rotate Left Word Immediate then AND with Mask, PPC32 p501)
+ vassert(MaskBeg < 32);
+ vassert(MaskEnd < 32);
+ vassert(sh_imm < 32);
+
+ if (mode64) {
+ ULong mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
+ DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? "." : "",
+ rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
+ // tmp32 = (ROTL(rS_Lo32, Imm)
+ // rA = ((tmp32 || tmp32) & mask64)
+ r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
+ r = unop(Iop_32Uto64, r);
+ r = binop(Iop_Or64, r, binop(Iop_Shl64, r, mkU8(32)));
+ assign( rA, binop(Iop_And64, r, mkU32(mask64)) );
+ }
+ else {
+ if (MaskBeg == 0 && sh_imm+MaskEnd == 31) {
+ /* Special-case the ,n,0,31-n form as that is just n-bit
+ shift left (PPC32 p501) */
+ DIP("slwi%s r%u,r%u,%d\n", flag_rC ? "." : "",
+ rA_addr, rS_addr, sh_imm);
+ assign( rA, binop(Iop_Shl32, mkexpr(rS), mkU8(sh_imm)) );
+ }
+ else
+ if (MaskEnd == 31 && sh_imm+MaskBeg == 32) {
+ /* Special-case the ,32-n,n,31 form as that is just n-bit
+ unsigned shift right (PPC32 p501) */
+ DIP("srwi%s r%u,r%u,%d\n", flag_rC ? "." : "",
+ rA_addr, rS_addr, sh_imm);
+ assign( rA, binop(Iop_Shr32, mkexpr(rS), mkU8(MaskBeg)) );
+ }
+ else {
+ /* General case. */
+ UInt mask = MASK32(31-MaskEnd, 31-MaskBeg);
+ DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? "." : "",
+ rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
+ // rA = ROTL(rS, Imm) & mask
+ assign( rA, binop(Iop_And32, ROTL(mkexpr(rS), mkU8(sh_imm)),
+ mkU32(mask)) );
+ }
+ }
break;
+ }
+
+ case 0x17: {
+ // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503
+ DIP("rlwnm%s r%u,r%u,r%u,%d,%d\n", flag_rC ? "." : "",
+ rA_addr, rS_addr, rB_addr, MaskBeg, MaskEnd);
+ if (mode64) {
+ ULong mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
+ // tmp32 = (ROTL(rS_Lo32, rB[0-4])
+ // rA = ((tmp32 || tmp32) & mask64)
+ // note, ROTL does the masking, so we don't do it here
+ r = ROTL( unop(Iop_64to32, mkexpr(rS)),
+ unop(Iop_32to8, mkexpr(rB)) );
+ r = unop(Iop_32Uto64, r);
+ r = binop(Iop_Or64, r, binop(Iop_Shl64, r, mkU8(32)));
+ assign( rA, binop(Iop_And64, r, mkU32(mask64)) );
+ } else {
+ UInt mask = MASK32(31-MaskEnd, 31-MaskBeg);
+ // rA = ROTL(rS, rB[0-4]) & mask
+ // note, ROTL does the masking, so we don't do it here
+ assign( rA, binop(Iop_And32,
+ ROTL(mkexpr(rS), unop(Iop_32to8, mkexpr(rB))),
+ mkU32(mask)) );
+ }
+ break;
+ }
default:
vex_printf("dis_int_rot(PPC32)(opc1)\n");
@@ -2420,7 +3307,6 @@
}
-
/*
Integer Load Instructions
*/
@@ -2430,29 +3316,32 @@
UChar opc1 = ifieldOPC(theInstr);
UChar rD_addr = ifieldRegDS(theInstr);
UChar rA_addr = ifieldRegA(theInstr);
- Int d_simm16 = ifieldSIMM16(theInstr);
+ UInt uimm16 = ifieldUIMM16(theInstr);
UChar rB_addr = ifieldRegB(theInstr);
UInt opc2 = ifieldOPClo10(theInstr);
UChar b0 = ifieldBIT0(theInstr);
- IRTemp rA_or_0 = newTemp(Ity_I32);
- IRTemp EA_imm = newTemp(Ity_I32);
- IRTemp EA_reg = newTemp(Ity_I32);
- IRTemp rA = newTemp(Ity_I32);
- IRTemp rB = newTemp(Ity_I32);
+ Int simm16 = extend_s_16to32(uimm16);
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
+ IRTemp rA = newTemp(ty);
+ IRTemp rB = newTemp(ty);
+ IRTemp EA = newTemp(ty);
+ IRExpr* val;
assign( rA, getIReg(rA_addr) );
assign( rB, getIReg(rB_addr) );
- assign( rA_or_0, ea_rA_or_zero(rA_addr));
+ if (opc1 != 0x1F) {
+ assign( EA, ea_rAor0_simm( rA_addr, simm16 ) );
+ } else {
+ assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
+ }
- assign( EA_imm, binop(Iop_Add32, mkexpr(rA_or_0), mkU32(d_simm16)) );
-
switch (opc1) {
case 0x22: // lbz (Load B & Zero, PPC32 p433)
- DIP("lbz r%d,%d(r%d)\n", rD_addr, d_simm16, rA_addr);
- putIReg( rD_addr, unop(Iop_8Uto32,
- loadBE(Ity_I8, mkexpr(EA_imm))) );
+ DIP("lbz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
+ val = loadBE(Ity_I8, mkexpr(EA));
+ putIReg( rD_addr, mkSizedWiden8(ty, val, False) );
break;
case 0x23: // lbzu (Load B & Zero with Update, PPC32 p434)
@@ -2460,16 +3349,16 @@
vex_printf("dis_int_load(PPC32)(lbzu,rA_addr|rD_addr)\n");
return False;
}
- DIP("lbzu r%d,%d(r%d)\n", rD_addr, d_simm16, rA_addr);
- putIReg( rD_addr, unop(Iop_8Uto32,
- loadBE(Ity_I8, mkexpr(EA_imm))) );
- putIReg( rA_addr, mkexpr(EA_imm) );
+ DIP("lbzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
+ val = loadBE(Ity_I8, mkexpr(EA));
+ putIReg( rD_addr, mkSizedWiden8(ty, val, False) );
+ putIReg( rA_addr, mkexpr(EA) );
break;
case 0x2A: // lha (Load HW Algebraic, PPC32 p445)
- DIP("lha r%d,%d(r%d)\n", rD_addr, d_simm16, rA_addr);
- putIReg( rD_addr, unop(Iop_16Sto32,
- loadBE(Ity_I16, mkexpr(EA_imm))) );
+ DIP("lha r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
+ val = loadBE(Ity_I16, mkexpr(EA));
+ putIReg( rD_addr, mkSizedWiden16(ty, val, True) );
break;
case 0x2B: // lhau (Load HW Algebraic with Update, PPC32 p446)
@@ -2477,16 +3366,16 @@
vex_printf("dis_int_load(PPC32)(lhau,rA_addr|rD_addr)\n");
return False;
}
- DIP("lhau r%d,%d(r%d)\n", rD_addr, d_simm16, rA_addr);
- putIReg( rD_addr, unop(Iop_16Sto32,
- loadBE(Ity_I16, mkexpr(EA_imm))) );
- putIReg( rA_addr, mkexpr(EA_imm) );
+ DIP("lhau r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
+ val = loadBE(Ity_I16, mkexpr(EA));
+ putIReg( rD_addr, mkSizedWiden16(ty, val, True) );
+ putIReg( rA_addr, mkexpr(EA) );
break;
case 0x28: // lhz (Load HW & Zero, PPC32 p450)
- DIP("lhz r%d,%d(r%d)\n", rD_addr, d_simm16, rA_addr);
- putIReg( rD_addr, unop(Iop_16Uto32,
- loadBE(Ity_I16, mkexpr(EA_imm))) );
+ DIP("lhz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
+ val = loadBE(Ity_I16, mkexpr(EA));
+ putIReg( rD_addr, mkSizedWiden16(ty, val, False) );
break;
case 0x29: // lhzu (Load HW & and Zero with Update, PPC32 p451)
@@ -2494,15 +3383,16 @@
vex_printf("dis_int_load(PPC32)(lhzu,rA_addr|rD_addr)\n");
return False;
}
- DIP("lhzu r%d,%d(r%d)\n", rD_addr, d_simm16, rA_addr);
- putIReg( rD_addr, unop(Iop_16Uto32,
- loadBE(Ity_I16, mkexpr(EA_imm))) );
- putIReg( rA_addr, mkexpr(EA_imm) );
+ DIP("lhzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
+ val = loadBE(Ity_I16, mkexpr(EA));
+ putIReg( rD_addr, mkSizedWiden16(ty, val, False) );
+ putIReg( rA_addr, mkexpr(EA) );
break;
case 0x20: // lwz (Load W & Zero, PPC32 p460)
- DIP("lwz r%d,%d(r%d)\n", rD_addr, d_simm16, rA_addr);
- putIReg( rD_addr, loadBE(Ity_I32, mkexpr(EA_imm)) );
+ DIP("lwz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
+ val = loadBE(Ity_I32, mkexpr(EA));
+ putIReg( rD_addr, mkSizedWiden32(ty, val, False) );
break;
case 0x21: // lwzu (Load W & Zero with Update, PPC32 p461))
@@ -2510,9 +3400,10 @@
vex_printf("dis_int_load(PPC32)(lwzu,rA_addr|rD_addr)\n");
return False;
}
- DIP("lwzu r%d,%d(r%d)\n", rD_addr, d_simm16, rA_addr);
- putIReg( rD_addr, loadBE(Ity_I32, mkexpr(EA_imm)) );
- putIReg( rA_addr, mkexpr(EA_imm) );
+ DIP("lwzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
+ val = loadBE(Ity_I32, mkexpr(EA));
+ putIReg( rD_addr, mkSizedWiden32(ty, val, False) );
+ putIReg( rA_addr, mkexpr(EA) );
break;
/* X Form */
@@ -2521,24 +3412,23 @@
vex_printf("dis_int_load(PPC32)(Ox1F,b0)\n");
return False;
}
- assign( EA_reg, binop(Iop_Add32, mkexpr(rA_or_0), mkexpr(rB)) );
switch (opc2) {
case 0x077: // lbzux (Load B & Zero with Update Indexed, PPC32 p435)
- DIP("lbzux r%d,r%d,r%d\n", rD_addr, rA_addr, rB_addr);
+ DIP("lbzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
if (rA_addr == 0 || rA_addr == rD_addr) {
vex_printf("dis_int_load(PPC32)(lwzux,rA_addr|rD_addr)\n");
return False;
}
- putIReg( rD_addr, unop(Iop_8Uto32,
- loadBE(Ity_I8, mkexpr(EA_reg))) );
- putIReg( rA_addr, mkexpr(EA_reg) );
+ val = loadBE(Ity_I8, mkexpr(EA));
+ putIReg( rD_addr, mkSizedWiden8(ty, val, False) );
+ putIReg( rA_addr, mkexpr(EA) );
break;
case 0x057: // lbzx (Load B & Zero Indexed, PPC32 p436)
- DIP("lbzx r%d,r%d,r%d\n", rD_addr, rA_addr, rB_addr);
- putIReg( rD_addr, unop(Iop_8Uto32,
- loadBE(Ity_I8, mkexpr(EA_reg))) );
+ DIP("lbzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
+ val = loadBE(Ity_I8, mkexpr(EA));
+ putIReg( rD_addr, mkSizedWiden8(ty, val, False) );
break;
case 0x177: // lhaux (Load HW Algebraic with Update Indexed, PPC32 p447)
@@ -2546,16 +3436,16 @@
vex_printf("dis_int_load(PPC32)(lhaux,rA_addr|rD_addr)\n");
return False;
}
- DIP("lhaux r%d,r%d,r%d\n", rD_addr, rA_addr, rB_addr);
- putIReg( rD_addr, unop(Iop_16Sto32,
- loadBE(Ity_I16, mkexpr(EA_reg))) );
- putIReg( rA_addr, mkexpr(EA_reg) );
+ DIP("lhaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
+ val = loadBE(Ity_I16, mkexpr(EA));
+ putIReg( rD_addr, mkSizedWiden16(ty, val, True) );
+ putIReg( rA_addr, mkexpr(EA) );
break;
case 0x157: // lhax (Load HW Algebraic Indexed, PPC32 p448)
- DIP("lhax r%d,r%d,r%d\n", rD_addr, rA_addr, rB_addr);
- putIReg( rD_addr, unop(Iop_16Sto32,
- loadBE(Ity_I16, mkexpr(EA_reg))) );
+ DIP("lhax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
+ val = loadBE(Ity_I16, mkexpr(EA));
+ putIReg( rD_addr, mkSizedWiden16(ty, val, True) );
break;
case 0x137: // lhzux (Load HW & Zero with Update Indexed, PPC32 p452)
@@ -2563,16 +3453,16 @@
vex_printf("dis_int_load(PPC32)(lhzux,rA_addr|rD_addr)\n");
return False;
}
- DIP("lhzux r%d,r%d,r%d\n", rD_addr, rA_addr, rB_addr);
- putIReg( rD_addr, unop(Iop_16Uto32,
- loadBE(Ity_I16, mkexpr(EA_reg))) );
- putIReg( rA_addr, mkexpr(EA_reg) );
+ DIP("lhzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
+ val = loadBE(Ity_I16, mkexpr(EA));
+ putIReg( rD_addr, mkSizedWiden16(ty, val, False) );
+ putIReg( rA_addr, mkexpr(EA) );
break;
case 0x117: // lhzx (Load HW & Zero Indexed, PPC32 p453)
- DIP("lhzx r%d,r%d,r%d\n", rD_addr, rA_addr, rB_addr);
- putIReg( rD_addr, unop(Iop_16Uto32,
- loadBE(Ity_I16, mkexpr(EA_reg))) );
+ DIP("lhzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
+ val = loadBE(Ity_I16, mkexpr(EA));
+ putIReg( rD_addr, mkSizedWiden16(ty, val, False) );
break;
case 0x037: // lwzux (Load W & Zero with Update Indexed, PPC32 p462)
@@ -2580,14 +3470,16 @@
vex_printf("dis_int_load(PPC32)(lwzux,rA_addr|rD_addr)\n");
return False;
}
- DIP("lwzux r%d,r%d,r%d\n", rD_addr, rA_addr, rB_addr);
- putIReg( rD_addr, loadBE(Ity_I32, mkexpr(EA_reg)) );
- putIReg( rA_addr, mkexpr(EA_reg) );
+ DIP("lwzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
+ val = loadBE(Ity_I32, mkexpr(EA));
+ putIReg( rD_addr, mkSizedWiden32(ty, val, False) );
+ putIReg( rA_addr, mkexpr(EA) );
break;
case 0x017: // lwzx (Load W & Zero Indexed, PPC32 p463)
- DIP("lwzx r%d,r%d,r%d\n", rD_addr, rA_addr, rB_addr);
- putIReg( rD_addr, loadBE(Ity_I32, mkexpr(EA_reg)) );
+ DIP("lwzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
+ val = loadBE(Ity_I32, mkexpr(EA));
+ putIReg( rD_addr, mkSizedWiden32(ty, val, False) );
break;
default:
@@ -2613,27 +3505,30 @@
UChar opc1 = ifieldOPC(theInstr);
UInt rS_addr = ifieldRegDS(theInstr);
UInt rA_addr = ifieldRegA(theInstr);
- Int simm16 = ifieldSIMM16(theInstr);
+ UInt uimm16 = ifieldUIMM16(theInstr);
UInt rB_addr = ifieldRegB(theInstr);
UInt opc2 = ifieldOPClo10(theInstr);
UChar b0 = ifieldBIT0(theInstr);
- IRTemp rA_or_0 = newTemp(Ity_I32);
- IRTemp rB = newTemp(Ity_I32);
- IRTemp rS = newTemp(Ity_I32);
- IRTemp EA_imm = newTemp(Ity_I32);
- IRTemp EA_reg = newTemp(Ity_I32);
+ Int simm16 = extend_s_16to32(uimm16);
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
+ IRTemp rS = newTemp(ty);
+ IRTemp rB = newTemp(ty);
+ IRTemp EA = newTemp(ty);
assign( rB, getIReg(rB_addr) );
assign( rS, getIReg(rS_addr) );
- assign( rA_or_0, ea_rA_or_zero(rA_addr) );
- assign( EA_imm, binop(Iop_Add32, mkexpr(rA_or_0), mkU32(simm16)) );
-
+ if (opc1 != 0x1F) {
+ assign( EA, ea_rAor0_simm( rA_addr, simm16 ) );
+ } else {
+ assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
+ }
+
switch (opc1) {
case 0x26: // stb (Store B, PPC32 p509)
DIP("stb r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
- storeBE( mkexpr(EA_imm), unop(Iop_32to8, mkexpr(rS)) );
+ storeBE( mkexpr(EA), mkSizedNarrow8(ty, mkexpr(rS)) );
break;
case 0x27: // stbu (Store B with Update, PPC32 p510)
@@ -2642,13 +3537,13 @@
return False;
}
DIP("stbu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
- putIReg( rA_addr, mkexpr(EA_imm) );
- storeBE( mkexpr(EA_imm), unop(Iop_32to8, mkexpr(rS)) );
+ putIReg( rA_addr, mkexpr(EA) );
+ storeBE( mkexpr(EA), mkSizedNarrow8(ty, mkexpr(rS)) );
break;
case 0x2C: // sth (Store HW, PPC32 p522)
DIP("sth r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
- storeBE( mkexpr(EA_imm), unop(Iop_32to16, mkexpr(rS)) );
+ storeBE( mkexpr(EA), mkSizedNarrow16(ty, mkexpr(rS)) );
break;
case 0x2D: // sthu (Store HW with Update, PPC32 p524)
@@ -2657,13 +3552,13 @@
return False;
}
DIP("sthu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
- putIReg( rA_addr, mkexpr(EA_imm) );
- storeBE( mkexpr(EA_imm), unop(Iop_32to16, mkexpr(rS)) );
+ putIReg( rA_addr, mkexpr(EA) );
+ storeBE( mkexpr(EA), mkSizedNarrow16(ty, mkexpr(rS)) );
break;
case 0x24: // stw (Store W, PPC32 p530)
DIP("stw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
- storeBE( mkexpr(EA_imm), mkexpr(rS) );
+ storeBE( mkexpr(EA), mkSizedNarrow32(ty, mkexpr(rS)) );
break;
case 0x25: // stwu (Store W with Update, PPC32 p534)
@@ -2672,8 +3567,8 @@
return False;
}
DIP("stwu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
- putIReg( rA_addr, mkexpr(EA_imm) );
- storeBE( mkexpr(EA_imm), mkexpr(rS) );
+ putIReg( rA_addr, mkexpr(EA) );
+ storeBE( mkexpr(EA), mkSizedNarrow32(ty, mkexpr(rS)) );
break;
/* X Form */
@@ -2682,7 +3577,6 @@
vex_printf("dis_int_store(PPC32)(0x1F,b0)\n");
return False;
}
- assign( EA_reg, binop(Iop_Add32, mkexpr(rA_or_0), mkexpr(rB)) );
switch (opc2) {
case 0x0F7: // stbux (Store B with Update Indexed, PPC32 p511)
@@ -2691,13 +3585,13 @@
return False;
}
DIP("stbux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
- putIReg( rA_addr, mkexpr(EA_reg) );
- storeBE( mkexpr(EA_reg), unop(Iop_32to8, mkexpr(rS)) );
+ putIReg( rA_addr, mkexpr(EA) );
+ storeBE( mkexpr(EA), mkSizedNarrow8(ty, mkexpr(rS)) );
break;
case 0x0D7: // stbx (Store B Indexed, PPC32 p512)
DIP("stbx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
- storeBE( mkexpr(EA_reg), unop(Iop_32to8, mkexpr(rS)) );
+ storeBE( mkexpr(EA), mkSizedNarrow8(ty, mkexpr(rS)) );
break;
case 0x1B7: // sthux (Store HW with Update Indexed, PPC32 p525)
@@ -2706,13 +3600,13 @@
return False;
}
DIP("sthux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
- putIReg( rA_addr, mkexpr(EA_reg) );
- storeBE( mkexpr(EA_reg), unop(Iop_32to16, mkexpr(rS)) );
+ putIReg( rA_addr, mkexpr(EA) );
+ storeBE( mkexpr(EA), mkSizedNarrow16(ty, mkexpr(rS)) );
break;
case 0x197: // sthx (Store HW Indexed, PPC32 p526)
DIP("sthx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
- storeBE( mkexpr(EA_reg), unop(Iop_32to16, mkexpr(rS)) );
+ storeBE( mkexpr(EA), mkSizedNarrow16(ty, mkexpr(rS)) );
break;
case 0x0B7: // stwux (Store W with Update Indexed, PPC32 p535)
@@ -2721,13 +3615,13 @@
return False;
}
DIP("stwux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
- putIReg( rA_addr, mkexpr(EA_reg) );
- storeBE( mkexpr(EA_reg), mkexpr(rS) );
+ putIReg( rA_addr, mkexpr(EA) );
+ storeBE( mkexpr(EA), mkSizedNarrow32(ty, mkexpr(rS)) );
break;
case 0x097: // stwx (Store W Indexed, PPC32 p536)
DIP("stwx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
- storeBE( mkexpr(EA_reg), mkexpr(rS) );
+ storeBE( mkexpr(EA), mkSizedNarrow32(ty, mkexpr(rS)) );
break;
default:
@@ -2746,6 +3640,7 @@
/*
Integer Load/Store Multiple Instructions
+ TODO: 64bit
*/
static Bool dis_int_ldst_mult ( UInt theInstr )
{
@@ -2754,47 +3649,43 @@
UChar rD_addr = ifieldRegDS(theInstr);
UChar rS_addr = rD_addr;
UChar rA_addr = ifieldRegA(theInstr);
- Int d_simm16 = ifieldSIMM16(theInstr);
+ Int uimm16 = ifieldUIMM16(theInstr);
- UInt reg_idx = 0;
- UInt offset = 0;
- IRTemp rA = newTemp(Ity_I32);
- IRTemp EA = newTemp(Ity_I32);
+ Int simm16 = extend_s_16to32(uimm16);
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
+ IRTemp EA = newTemp(ty);
+ UInt r = 0;
+ UInt ea_off = 0;
IRExpr* irx_addr;
- if (rA_addr == 0) {
- assign( EA, binop(Iop_Add32, mkU32(0), mkU32(d_simm16)) );
- } else {
- assign( rA, getIReg(rA_addr) );
- assign( EA, binop(Iop_Add32, mkexpr(rA), mkU32(d_simm16)) );
- }
-
+ assign( EA, ea_rAor0_simm( rA_addr, simm16 ) );
+
switch (opc1) {
- case 0x2E: // lmw (Load Multiple Word, PPC32 p454)
- if (rA_addr >= rD_addr) {
- vex_printf("dis_int_ldst_mult(PPC32)(lmw,rA_addr)\n");
- return False;
- }
- DIP("lmw r%d,%d(r%d)\n", rD_addr, d_simm16, rA_addr);
- for (reg_idx = rD_addr; reg_idx <= 31; reg_idx++) {
- irx_addr = binop(Iop_Add32, mkexpr(EA), mkU32(offset));
- putIReg( reg_idx, loadBE(Ity_I32, irx_addr ) );
- offset += 4;
- }
- break;
-
- case 0x2F: // stmw (Store Multiple Word, PPC32 p527)
- DIP("stmw r%d,%d(r%d)\n", rS_addr, d_simm16, rA_addr);
- for (reg_idx = rS_addr; reg_idx <= 31; reg_idx++) {
- irx_addr = binop(Iop_Add32, mkexpr(EA), mkU32(offset));
- storeBE( irx_addr, getIReg(reg_idx) );
- offset += 4;
- }
- break;
-
- default:
- vex_printf("dis_int_ldst_mult(PPC32)(opc1)\n");
+ case 0x2E: // lmw (Load Multiple Word, PPC32 p454)
+ if (rA_addr >= rD_addr) {
+ vex_printf("dis_int_ldst_mult(PPC32)(lmw,rA_addr)\n");
return False;
+ }
+ DIP("lmw r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
+ for (r = rD_addr; r <= 31; r++) {
+ irx_addr = binop(Iop_Add32, mkexpr(EA), mkU32(ea_off));
+ putIReg( r, mkSizedWiden32(ty, loadBE(Ity_I32, irx_addr ), False) );
+ ea_off += 4;
+ }
+ break;
+
+ case 0x2F: // stmw (Store Multiple Word, PPC32 p527)
+ DIP("stmw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
+ for (r = rS_addr; r <= 31; r++) {
+ irx_addr = binop(Iop_Add32, mkexpr(EA), mkU32(ea_off));
+ storeBE( irx_addr, mkSizedNarrow32(ty, getIReg(r)) );
+ ea_off += 4;
+ }
+ break;
+
+ default:
+ vex_printf("dis_int_ldst_mult(PPC32)(opc1)\n");
+ return False;
}
return True;
}
@@ -2808,22 +3699,21 @@
void generate_lsw_sequence ( IRTemp tNBytes, // # bytes, :: Ity_I32
IRTemp EA, // EA
Int rD, // first dst register
- Int maxBytes, // 32 or 128
- Addr32 NIA ) // where next?
+ Int maxBytes ) // 32 or 128
{
Int i, shift = 24;
IRExpr* e_nbytes = mkexpr(tNBytes);
- IRExpr* e_EA = mkexpr(EA);
+ IRExpr* e_EA = mkexpr(EA);
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
vassert(rD >= 0 && rD < 32);
rD--; if (rD < 0) rD = 31;
for (i = 0; i < maxBytes; i++) {
-
/* if (nBytes < (i+1)) goto NIA; */
stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
Ijk_Boring,
- IRConst_U32(NIA)) );
+ mkSizedConst( ty, nextInsnAddr()) ));
/* when crossing into a new dest register, set it to zero. */
if ((i % 4) == 0) {
rD++; if (rD == 32) rD = 0;
@@ -2850,12 +3740,12 @@
void generate_stsw_sequence ( IRTemp tNBytes, // # bytes, :: Ity_I32
IRTemp EA, // EA
Int rS, // first src register
- Int maxBytes, // 32 or 128
- Addr32 NIA ) // where next?
+ Int maxBytes ) // 32 or 128
{
Int i, shift = 24;
IRExpr* e_nbytes = mkexpr(tNBytes);
- IRExpr* e_EA = mkexpr(EA);
+ IRExpr* e_EA = mkexpr(EA);
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
vassert(rS >= 0 && rS < 32);
rS--; if (rS < 0) rS = 31;
@@ -2864,7 +3754,7 @@
/* if (nBytes < (i+1)) goto NIA; */
stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
Ijk_Boring,
- IRConst_U32(NIA)) );
+ mkSizedConst( ty, nextInsnAddr() ) ));
/* check for crossing into a new src register. */
if ((i % 4) == 0) {
rS++; if (rS == 32) rS = 0;
@@ -2881,7 +3771,7 @@
}
}
-
+// TODO: 64bit
static Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere )
{
/* X-Form */
@@ -2894,7 +3784,8 @@
UInt opc2 = ifieldOPClo10(theInstr);
UChar b0 = ifieldBIT0(theInstr);
- IRTemp t_EA = newTemp(Ity_I32);
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
+ IRTemp t_EA = newTemp(ty);
IRTemp t_nbytes = IRTemp_INVALID;
*stopHere = False;
@@ -2908,20 +3799,20 @@
case 0x255: // lswi (Load String Word Immediate, PPC32 p455)
/* NB: does not reject the case where RA is in the range of
registers to be loaded. It should. */
- DIP("lswi r%d,r%d,%d\n", rD_addr, rA_addr, NumBytes);
- assign( t_EA, ea_rA_or_zero(rA_addr) );
- if (NumBytes == 8) {
+ DIP("lswi r%u,r%u,%d\n", rD_addr, rA_addr, NumBytes);
+ assign( t_EA, ea_rAor0(rA_addr) );
+ if (!mode64 && NumBytes == 8) {
/* Special case hack */
/* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */
putIReg( rD_addr,
loadBE(Ity_I32, mkexpr(t_EA)) );
putIReg( (rD_addr+1) % 32,
- loadBE(Ity_I32, binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) );
+ loadBE(Ity_I32,
+ binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) );
} else {
t_nbytes = newTemp(Ity_I32);
assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
- generate_lsw_sequence( t_nbytes, t_EA, rD_addr,
- 32, guest_CIA_curr_instr+4 );
+ generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
*stopHere = True;
}
return True;
@@ -2935,18 +3826,17 @@
return False;
if (rD_addr == 0 && rA_addr == 0)
return False;
- DIP("lswx r%d,r%d,r%d\n", rD_addr, rA_addr, rB_addr);
+ DIP("lswx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
t_nbytes = newTemp(Ity_I32);
- assign( t_EA, ea_standard(rA_addr,rB_addr) );
+ assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
- generate_lsw_sequence( t_nbytes, t_EA, rD_addr,
- 128, guest_CIA_curr_instr+4 );
+ generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 128 );
*stopHere = True;
return True;
case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528)
- DIP("stswi r%d,r%d,%d\n", rS_addr, rA_addr, NumBytes);
- assign( t_EA, ea_rA_or_zero(rA_addr) );
+ DIP("stswi r%u,r%u,%d\n", rS_addr, rA_addr, NumBytes);
+ assign( t_EA, ea_rAor0(rA_addr) );
if (NumBytes == 8) {
/* Special case hack */
/* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */
@@ -2957,19 +3847,17 @@
} else {
t_nbytes = newTemp(Ity_I32);
assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
- generate_stsw_sequence( t_nbytes, t_EA, rD_addr,
- 32, guest_CIA_curr_instr+4 );
+ generate_stsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
*stopHere = True;
}
return True;
case 0x295: // stswx (Store String Word Indexed, PPC32 p529)
- DIP("stswx r%d,r%d,r%d\n", rS_addr, rA_addr, rB_addr);
+ DIP("stswx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
t_nbytes = newTemp(Ity_I32);
- assign( t_EA, ea_standard(rA_addr,rB_addr) );
+ assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
- generate_stsw_sequence( t_nbytes, t_EA, rS_addr,
- 128, guest_CIA_curr_instr+4 );
+ generate_stsw_sequence( t_nbytes, t_EA, rS_addr, 128 );
*stopHere = True;
return True;
@@ -2993,19 +3881,22 @@
*/
static IRExpr* /* :: Ity_I32 */ branch_ctr_ok( UInt BO )
{
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
IRTemp ok = newTemp(Ity_I32);
if ((BO >> 2) & 1) {
assign( ok, mkU32(0xFFFFFFFF) );
} else {
if ((BO >> 1) & 1) {
- assign( ok, unop( Iop_1Sto32,
- binop( Iop_CmpEQ32,
- getSPR( PPC32_SPR_CTR ), mkU32(0))) );
+ assign( ok, unop( Iop_1Sto32,
+ binop( mkSizedOp(ty, Iop_CmpEQ8),
+ getGST( PPC_GST_CTR ),
+ mkSizedImm(ty, 0))) );
} else {
assign( ok, unop( Iop_1Sto32,
- binop( Iop_CmpNE32,
- getSPR( PPC32_SPR_CTR ), mkU32(0))) );
+ binop( mkSizedOp(ty, Iop_CmpNE8),
+ getGST( PPC_GST_CTR ),
+ mkSizedImm(ty, 0))) );
}
}
return mkexpr(ok);
@@ -3052,27 +3943,29 @@
/*OUT*/DisResult* dres,
Bool (*resteerOkFn)(Addr64) )
{
- UChar opc1 = ifieldOPC(theInstr);
- UChar BO = ifieldRegDS(theInstr);
- UChar BI = ifieldRegA(theInstr);
- Int BD_s16 = ifieldSIMM16(theInstr) & 0xFFFFFFFC; /* mask off */
- UChar b11to15 = ifieldRegB(theInstr);
- UInt opc2 = ifieldOPClo10(theInstr);
- Int LI_s26 = ifieldSIMM26(theInstr) & 0xFFFFFFFC; /* mask off */
- UChar flag_AA = ifieldBIT1(theInstr);
- UChar flag_LK = ifieldBIT0(theInstr);
-
- Addr32 nia = 0;
-
- IRTemp ir_nia = newTemp(Ity_I32);
- IRTemp do_branch = newTemp(Ity_I32);
- IRTemp ctr_ok = newTemp(Ity_I32);
- IRTemp cond_ok = newTemp(Ity_I32);
-
+ UChar opc1 = ifieldOPC(theInstr);
+ UChar BO = ifieldRegDS(theInstr);
+ UChar BI = ifieldRegA(theInstr);
+ UInt BD_u16 = ifieldUIMM16(theInstr) & 0xFFFFFFFC; /* mask off */
+ UChar b11to15 = ifieldRegB(theInstr);
+ UInt opc2 = ifieldOPClo10(theInstr);
+ UInt LI_u26 = ifieldUIMM26(theInstr) & 0xFFFFFFFC; /* mask off */
+ UChar flag_AA = ifieldBIT1(theInstr);
+ UChar flag_LK = ifieldBIT0(theInstr);
+
+ Addr64 tgt = 0;
+ Int BD = extend_s_16to32(BD_u16);
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
+ IRTemp do_branch = newTemp(ty);
+ IRTemp ctr_ok = newTemp(ty);
+ IRTemp cond_ok = newTemp(ty);
+ IRExpr* e_nia = mkSizedImm(ty, nextInsnAddr());
+ IRConst* c_nia = mkSizedConst( ty, nextInsnAddr() );
+
/* Hack to pass through code that just wants to read the PC */
if (theInstr == 0x429F0005) {
DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO, BI);
- putSPR( PPC32_SPR_LR, mkU32(guest_CIA_curr_instr + 4) );
+ putGST( PPC_GST_LR, e_nia );
return True;
}
@@ -3082,32 +3975,39 @@
switch (opc1) {
case 0x12: // b (Branch, PPC32 p360)
if (flag_AA) {
- nia = (UInt)LI_s26;
+ tgt = mkSizedAddr( ty, extend_s_16to64(LI_u26) );
} else {
- nia = (UInt)((Int)guest_CIA_curr_instr + LI_s26);
+ tgt = mkSizedAddr( ty, guest_CIA_curr_instr +
+ (Long)extend_s_26to64(LI_u26) );
}
- DIP("b%s%s 0x%x\n", flag_LK ? "l" : "", flag_AA ? "a" : "", nia);
-
- if (flag_LK) {
- putSPR( PPC32_SPR_LR, mkU32(guest_CIA_curr_instr + 4) );
+ if (mode64) {
+ DIP("b%s%s 0x%llx\n",
+ flag_LK ? "l" : "", flag_AA ? "a" : "", tgt);
+ } else {
+ DIP("b%s%s 0x%x\n",
+ flag_LK ? "l" : "", flag_AA ? "a" : "", (Addr32)tgt);
}
- if (resteerOkFn((Addr64)nia)) {
- dres->whatNext = Dis_Resteer;
- dres->continueAt = (Addr64)nia;
+ if (flag_LK)
+ putGST( PPC_GST_LR, e_nia );
+
+ if (resteerOkFn(tgt)) {
+ dres->whatNext = Dis_Resteer;
+ dres->continueAt = tgt;
} else {
irbb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring;
- irbb->next = mkU32(nia);
+ irbb->next = mkSizedImm(ty, tgt);
}
break;
case 0x10: // bc (Branch Conditional, PPC32 p361)
DIP("bc%s%s 0x%x, 0x%x, 0x%x\n",
- flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD_s16);
+ flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD);
if (!(BO & 0x4)) {
- putSPR( PPC32_SPR_CTR,
- binop(Iop_Sub32, getSPR( PPC32_SPR_CTR ), mkU32(1)) );
+ putGST( PPC_GST_CTR,
+ binop(mkSizedOp(ty, Iop_Sub8),
+ getGST( PPC_GST_CTR ), mkSizedImm(ty, 1)) );
}
/* This is a bit subtle. ctr_ok is either all 0s or all 1s.
@@ -3121,20 +4021,21 @@
binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
if (flag_AA) {
- nia = (UInt)BD_s16;
+ tgt = mkSizedAddr(ty, extend_s_16to64(BD_u16));
} else {
- nia = (UInt)((Int)guest_CIA_curr_instr + BD_s16);
+ tgt = mkSizedAddr(ty, guest_CIA_curr_instr +
+ (Long)extend_s_16to64(BD_u16));
}
- if (flag_LK) {
- putSPR( PPC32_SPR_LR, mkU32(guest_CIA_curr_instr + 4) );
- }
+ if (flag_LK)
+ putGST( PPC_GST_LR, e_nia );
- stmt( IRStmt_Exit( binop(Iop_CmpNE32, mkexpr(do_branch), mkU32(0)),
- flag_LK ? Ijk_Call : Ijk_Boring,
- IRConst_U32(nia) ));
+ stmt( IRStmt_Exit(
+ binop(Iop_CmpNE32, mkexpr(do_branch), mkU32(0)),
+ flag_LK ? Ijk_Call : Ijk_Boring,
+ mkSizedConst(ty, tgt) ) );
irbb->jumpkind = Ijk_Boring;
- irbb->next = mkU32(guest_CIA_curr_instr + 4);
+ irbb->next = e_nia;
break;
case 0x13:
@@ -3152,23 +4053,17 @@
DIP("bcctr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
assign( cond_ok, branch_cond_ok( BO, BI ) );
-
- assign( ir_nia,
- binop(Iop_And32, mkU32(0xFFFFFFFC),
- getSPR( PPC32_SPR_CTR ) ));
-
- if (flag_LK) {
- putSPR( PPC32_SPR_LR, mkU32(guest_CIA_curr_instr + 4) );
- }
+
+ if (flag_LK)
+ putGST( PPC_GST_LR, e_nia );
stmt( IRStmt_Exit(
binop(Iop_CmpEQ32, mkexpr(cond_ok), mkU32(0)),
Ijk_Boring,
- IRConst_U32(guest_CIA_curr_instr + 4)
- ));
+ c_nia ));
irbb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring;
- irbb->next = mkexpr(ir_nia);
+ irbb->next = addr_align( getGST( PPC_GST_CTR ), 4 );
break;
case 0x010: // bclr (Branch Cond. to Link Register, PPC32 p365)
@@ -3180,8 +4075,10 @@
}
if (!(BO & 0x4)) {
- putSPR( PPC32_SPR_CTR,
- binop(Iop_Sub32, getSPR( PPC32_SPR_CTR ), mkU32(1)) );
+ putGST( PPC_GST_CTR,
+ binop(mkSizedOp(ty, Iop_Sub8),
+ getGST( PPC_GST_CTR ),
+ mkSizedImm(ty, 1)) );
}
/* See comments above for 'bc' about this */
@@ -3190,24 +4087,19 @@
assign( do_branch,
binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
- assign( ir_nia, binop(Iop_And32,
- getSPR( PPC32_SPR_LR ),
- mkU32(0xFFFFFFFC)) );
- if (flag_LK) {
- putSPR( PPC32_SPR_LR, mkU32(guest_CIA_curr_instr + 4) );
- }
+ if (flag_LK)
+ putGST( PPC_GST_LR, e_nia );
stmt( IRStmt_Exit(
binop(Iop_CmpEQ32, mkexpr(do_branch), mkU32(0)),
Ijk_Boring,
- IRConst_U32(guest_CIA_curr_instr + 4)
- ));
+ c_nia ));
/* blrl is pretty strange; it's like a return that sets the
return address of its caller to the insn following this
one. Mark it as a return. */
irbb->jumpkind = Ijk_Ret; /* was flag_LK ? Ijk_Call : Ijk_Ret; */
- irbb->next = mkexpr(ir_nia);
+ irbb->next = addr_align( getGST( PPC_GST_LR ), 4 );
break;
default:
@@ -3241,9 +4133,10 @@
UInt opc2 = ifieldOPClo10(theInstr);
UChar b0 = ifieldBIT0(theInstr);
- IRTemp crbD = newTemp(Ity_I32);
- IRTemp crbA = newTemp(Ity_I32);
- IRTemp crbB = newTemp(Ity_I32);
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
+ IRTemp crbD = newTemp(ty);
+ IRTemp crbA = newTemp(ty);
+ IRTemp crbB = newTemp(ty);
if (opc1 != 19 || b0 != 0) {
vex_printf("dis_cond_logic(PPC32)(opc1)\n");
@@ -3256,7 +4149,7 @@
vex_printf("dis_cond_logic(PPC32)(crbD|crbA|crbB != 0)\n");
return False;
}
- DIP("mcrf cr%d,cr%d\n", crfD_addr, crfS_addr);
+ DIP("mcrf cr%u,cr%u\n", crfD_addr, crfS_addr);
putCR0( crfD_addr, getCR0( crfS_addr) );
putCR321( crfD_addr, getCR321(crfS_addr) );
} else {
@@ -3322,8 +4215,10 @@
*/
static Bool dis_syslink ( UInt theInstr, DisResult* dres )
{
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
+
if (theInstr != 0x44000002) {
- vex_printf("dis_int_syslink(PPC32)(theInstr)\n");
+ vex_printf("dis_syslink(PPC32)(theInstr)\n");
return False;
}
@@ -3333,9 +4228,9 @@
/* It's important that all ArchRegs carry their up-to-date value
at this point. So we declare an end-of-block here, which
forces any TempRegs caching ArchRegs to be flushed. */
- irbb->next = mkU32( guest_CIA_curr_instr + 4 );
+ irbb->next = mkSizedImm( ty, nextInsnAddr() );
irbb->jumpkind = Ijk_Sys_syscall;
-
+
dres->whatNext = Dis_StopHere;
return True;
}
@@ -3347,27 +4242,30 @@
static Bool dis_memsync ( UInt theInstr )
{
/* X-Form, XL-Form */
- UChar opc1 = ifieldOPC(theInstr);
- UInt b11to25 = IFIELD(theInstr, 11, 15);
- UChar rD_addr = ifieldRegDS(theInstr);
- UChar rS_addr = rD_addr;
- UChar rA_addr = ifieldRegA(theInstr);
- UChar rB_addr = ifieldRegB(theInstr);
- UInt opc2 = ifieldOPClo10(theInstr);
- UChar b0 = ifieldBIT0(theInstr);
+ UChar opc1 = ifieldOPC(theInstr);
+ UInt b11to25 = IFIELD(theInstr, 11, 15);
+ UChar rD_addr = ifieldRegDS(theInstr);
+ UChar rS_addr = rD_addr;
+ UChar rA_addr = ifieldRegA(theInstr);
+ UChar rB_addr = ifieldRegB(theInstr);
+ UInt opc2 = ifieldOPClo10(theInstr);
+ UChar b0 = ifieldBIT0(theInstr);
- IRTemp EA = newTemp(Ity_I32);
- IRTemp rS = newTemp(Ity_I32);
-
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
+ IRTemp EA = newTemp(ty);
+ IRTemp rS = newTemp(ty);
+
+ assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
+
switch (opc1) {
/* XL-Form */
case 0x13: // isync (Instruction Synchronize, PPC32 p432)
if (opc2 != 0x096) {
- vex_printf("dis_int_memsync(PPC32)(0x13,opc2)\n");
+ vex_printf("dis_memsync(PPC32)(0x13,opc2)\n");
return False;
}
if (b11to25 != 0 || b0 != 0) {
- vex_printf("dis_int_memsync(PPC32)(0x13,b11to25|b0)\n");
+ vex_printf("dis_memsync(PPC32)(0x13,b11to25|b0)\n");
return False;
}
DIP("isync\n");
@@ -3379,7 +4277,7 @@
switch (opc2) {
case 0x356: // eieio (Enforce In-Order Execution of I/O, PPC32 p394)
if (b11to25 != 0 || b0 != 0) {
- vex_printf("dis_int_memsync(PPC32)(eiei0,b11to25|b0)\n");
+ vex_printf("dis_memsync(PPC32)(eiei0,b11to25|b0)\n");
return False;
}
DIP("eieio\n");
@@ -3389,26 +4287,24 @@
case 0x014: // lwarx (Load Word and Reserve Indexed, PPC32 p458)
if (b0 != 0) {
- vex_printf("dis_int_memsync(PPC32)(lwarx,b0)\n");
+ vex_printf("dis_memsync(PPC32)(lwarx,b0)\n");
return False;
}
- DIP("lwarx r%d,r%d,r%d\n", rD_addr, rA_addr, rB_addr);
- assign( EA, ea_standard(rA_addr, rB_addr) );
- putIReg( rD_addr, loadBE(Ity_I32, mkexpr(EA)) );
+ DIP("lwarx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
+ putIReg( rD_addr, mkSizedWiden32(ty, loadBE(Ity_I32, mkexpr(EA)), False) );
/* Take a reservation */
- stmt( IRStmt_Put( OFFB_RESVN, mkexpr(EA) ));
+ putGST( PPC_GST_RESVN, mkexpr(EA) );
break;
case 0x096: {
// stwcx. (Store Word Conditional Indexed, PPC32 p532)
IRTemp resaddr = newTemp(Ity_I32);
if (b0 != 1) {
- vex_printf("dis_int_memsync(PPC32)(stwcx.,b0)\n");
+ vex_printf("dis_memsync(PPC32)(stwcx.,b0)\n");
return False;
}
- DIP("stwcx. r%d,r%d,r%d\n", rS_addr, rA_addr, rB_addr);
+ DIP("stwcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
assign( rS, getIReg(rS_addr) );
- assign( EA, ea_standard(rA_addr, rB_addr) );
/* First set up as if the reservation failed */
// Set CR0[LT GT EQ S0] = 0b000 || XER[SO]
@@ -3417,15 +4313,20 @@
/* Get the reservation address into a temporary, then
clear it. */
- assign( resaddr, IRExpr_Get(OFFB_RESVN, Ity_I32) );
- stmt( IRStmt_Put( OFFB_RESVN, mkU32(0) ));
+ assign( resaddr, getGST(PPC_GST_RESVN) );
+ putGST( PPC_GST_RESVN, mkSizedImm(ty, 0) );
/* Skip the rest if the reservation really did fail. */
stmt( IRStmt_Exit(
- binop(Iop_CmpNE32, mkexpr(resaddr),
- mkexpr(EA)),
+ ( mode64 ?
+ binop(Iop_CmpNE64, mkexpr(resaddr), mkexpr(EA)) :
+ binop(Iop_CmpNE32, mkexpr(resaddr), mkexpr(EA)) ),
Ijk_Boring,
- IRConst_U32(guest_CIA_curr_instr + 4)) );
+ mkSizedConst( ty, nextInsnAddr()) ));
+
+ /* Note for mode64:
+ If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
+ whether rS is stored is dependent on that value. */
/* Success? Do the store */
storeBE( mkexpr(EA), mkexpr(rS) );
@@ -3437,7 +4338,7 @@
case 0x256: // sync (Synchronize, PPC32 p543)
if (b11to25 != 0 || b0 != 0) {
- vex_printf("dis_int_memsync(PPC32)(sync,b11to25|b0)\n");
+ vex_printf("dis_memsync(PPC32)(sync,b11to25|b0)\n");
return False;
}
DIP("sync\n");
@@ -3447,13 +4348,13 @@
break;
default:
- vex_printf("dis_int_memsync(PPC32)(opc2)\n");
+ vex_printf("dis_memsync(PPC32)(opc2)\n");
return False;
}
break;
default:
- vex_printf("dis_int_memsync(PPC32)(opc1)\n");
+ vex_printf("dis_memsync(PPC32)(opc1)\n");
return False;
}
return True;
@@ -3475,20 +4376,22 @@
UInt opc2 = ifieldOPClo10(theInstr);
UChar flag_rC = ifieldBIT0(theInstr);
- IRTemp sh_amt = newTemp(Ity_I8);
- IRTemp rS = newTemp(Ity_I32);
- IRTemp rA = newTemp(Ity_I32);
- IRTemp rB = newTemp(Ity_I32);
- IRTemp sh_amt32 = newTemp(Ity_I32);
- IRTemp outofrange = newTemp(Ity_I8);
-
- assign( rS, getIReg(rS_addr) );
- assign( rB, getIReg(rB_addr) );
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
+ IRTemp rA = newTemp(ty);
+ IRTemp outofrange = newTemp(Ity_I8);
+ IRTemp sh_amt = newTemp(Ity_I8);
+ IRTemp sh_amt32 = newTemp(Ity_I32);
+ IRTemp rS_lo32 = newTemp(Ity_I32);
+ IRTemp rB_lo32 = newTemp(Ity_I32);
+ IRExpr* e_tmp;
+
+ assign( rS_lo32, mkSizedNarrow32(ty, getIReg(rS_addr)) );
+ assign( rB_lo32, mkSizedNarrow32(ty, getIReg(rB_addr)) );
if (opc1 == 0x1F) {
switch (opc2) {
- case 0x018: // slw (Shift Left Word, PPC32 p505)
- DIP("slw%s r%d,r%d,r%d\n", flag_rC ? "." : "",
+ case 0x018: { // slw (Shift Left Word, PPC32 p505)
+ DIP("slw%s r%u,r%u,r%u\n", flag_rC ? "." : "",
rA_addr, rS_addr, rB_addr);
/* rA = rS << rB */
/* ppc32 semantics are:
@@ -3496,58 +4399,63 @@
& ~((y << 26) >>s 31) -- make result 0
for y in 32 .. 63
*/
- assign( rA,
- binop(
- Iop_And32,
- binop( Iop_Shl32,
- mkexpr(rS),
- unop( Iop_32to8,
- binop(Iop_And32, mkexpr(rB), mkU32(31)))),
- unop( Iop_Not32,
- binop( Iop_Sar32,
- binop(Iop_Shl32, mkexpr(rB), mkU8(26)),
- mkU8(31)))) );
+ e_tmp =
+ binop( Iop_And32,
+ binop( Iop_Shl32,
+ mkexpr(rS_lo32),
+ unop( Iop_32to8,
+ binop(Iop_And32,
+ mkexpr(rB_lo32), mkU32(31)))),
+ unop( Iop_Not32,
+ binop( Iop_Sar32,
+ binop(Iop_Shl32, mkexpr(rB_lo32), mkU8(26)),
+ mkU8(31))) );
+ assign( rA, mkSizedWiden32(ty, e_tmp, /* Signed */False) );
break;
-
+ }
+
case 0x318: // sraw (Shift Right Algebraic Word, PPC32 p506)
- DIP("sraw%s r%d,r%d,r%d\n", flag_rC ? "." : "",
+ 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:
amt = rB & 63
rA = Sar32( rS, amt > 31 ? 31 : amt )
XER.CA = amt > 31 ? sign-of-rS : (computation as per srawi)
*/
- assign( sh_amt32, binop(Iop_And32, mkU32(0x3F), mkexpr(rB)) );
+ assign( sh_amt32, binop(Iop_And32, mkU32(0x3F), mkexpr(rB_lo32)) );
assign( outofrange,
unop( Iop_1Uto8,
binop(Iop_CmpLT32U, mkU32(31), mkexpr(sh_amt32)) ));
- assign( rA,
- binop( Iop_Sar32,
- mkexpr(rS),
+ e_tmp = binop( Iop_Sar32,
+ mkexpr(rS_lo32),
unop( Iop_32to8,
IRExpr_Mux0X( mkexpr(outofrange),
mkexpr(sh_amt32),
- mkU32(31)) ))
- );
+ mkU32(31)) ) );
+ assign( rA, mkSizedWiden32(ty, e_tmp, /* Signed */True) );
+#if 0
set_XER_CA( PPC32G_FLAG_OP_SRAW,
mkexpr(rA), mkexpr(rS), mkexpr(sh_amt32),
getXER_CA32() );
+#endif
break;
case 0x338: // srawi (Shift Right Algebraic Word Immediate, PPC32 p507)
- DIP("srawi%s r%d,r%d,%d\n", flag_rC ? "." : "",
+ DIP("srawi%s r%u,r%u,%d\n", flag_rC ? "." : "",
rA_addr, rS_addr, sh_imm);
vassert(sh_imm < 32);
assign( sh_amt, mkU8(sh_imm) );
- assign( rA, binop(Iop_Sar32, mkexpr(rS), mkexpr(sh_amt)) );
+ e_tmp = binop(Iop_Sar32, mkexpr(rS_lo32), mkexpr(sh_amt));
+ assign( rA, mkSizedWiden32(ty, e_tmp, /* Signed */True) );
+#if 0
set_XER_CA( PPC32G_FLAG_OP_SRAWI,
mkexpr(rA), mkexpr(rS), mkU32(sh_imm),
getXER_CA32() );
+#endif
break;
case 0x218: // srw (Shift Right Word, PPC32 p508)
- DIP("srw%s r%d,r%d,r%d\n", flag_rC ? "." : "",
+ DIP("srw%s r%u,r%u,r%u\n", flag_rC ? "." : "",
rA_addr, rS_addr, rB_addr);
/* rA = rS >>u rB */
/* ppc32 semantics are:
@@ -3555,17 +4463,18 @@
& ~((y << 26) >>s 31) -- make result 0
for y in 32 .. 63
*/
- assign( rA,
+ e_tmp =
binop(
Iop_And32,
binop( Iop_Shr32,
- mkexpr(rS),
+ mkexpr(rS_lo32),
unop( Iop_32to8,
- binop(Iop_And32, mkexpr(rB), mkU32(31)))),
+ binop(Iop_And32, mkexpr(rB_lo32), mkU32(31)))),
unop( Iop_Not32,
binop( Iop_Sar32,
- binop(Iop_Shl32, mkexpr(rB), mkU8(26)),
- mkU8(31)))) );
+ binop(Iop_Shl32, mkexpr(rB_lo32), mkU8(26)),
+ mkU8(31))));
+ assign( rA, mkSizedWiden32(ty, e_tmp, /* Signed */False) );
break;
default:
@@ -3618,7 +4527,8 @@
UInt opc2 = ifieldOPClo10(theInstr);
UChar b0 = ifieldBIT0(theInstr);
- IRTemp EA = newTemp(Ity_I32);
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
+ IRTemp EA = newTemp(ty);
IRTemp w1 = newTemp(Ity_I32);
IRTemp w2 = newTemp(Ity_I32);
@@ -3627,13 +4537,13 @@
return False;
}
- assign( EA, ea_standard(rA_addr, rB_addr) );
+ assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
switch (opc2) {
//zz case 0x316: // lhbrx (Load Half Word Byte-Reverse Indexed, PPC32 p449)
//zz vassert(0);
//zz
-//zz DIP("lhbrx r%d,r%d,r%d\n", rD_addr, rA_addr, rB_addr);
+//zz DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
//zz assign( byte0, loadBE(Ity_I8, mkexpr(EA)) );
//zz assign( byte1, loadBE(Ity_I8, binop(Iop_Add32, mkexpr(EA),mkU32(1))) );
//zz assign( rD, binop(Iop_Or32,
@@ -3643,16 +4553,16 @@
//zz break;
case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459)
- DIP("lwbrx r%d,r%d,r%d\n", rD_addr, rA_addr, rB_addr);
+ DIP("lwbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
assign( w1, loadBE(Ity_I32, mkexpr(EA)) );
assign( w2, gen_byterev32(w1) );
- putIReg( rD_addr, mkexpr(w2));
+ putIReg( rD_addr, mkSizedWiden32(ty, mkexpr(w2), /* Signed */False) );
break;
//zz case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523)
//zz vassert(0);
//zz
-//zz DIP("sthbrx r%d,r%d,r%d\n", rS_addr, rA_addr, rB_addr);
+//zz DIP("sthbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
//zz assign( rS, getIReg(rS_addr) );
//zz assign( byte0, binop(Iop_And32, mkexpr(rS), mkU32(0x00FF)) );
//zz assign( byte1, binop(Iop_And32, mkexpr(rS), mkU32(0xFF00)) );
@@ -3666,8 +4576,8 @@
//zz break;
case 0x296: // stwbrx (Store Word Byte-Reverse Indexed, PPC32 p531)
- DIP("stwbrx r%d,r%d,r%d\n", rS_addr, rA_addr, rB_addr);
- assign( w1, getIReg(rS_addr) );
+ DIP("stwbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
+ assign( w1, mkSizedNarrow32(ty, getIReg(rS_addr)) );
storeBE( mkexpr(EA), gen_byterev32(w1) );
break;
@@ -3704,16 +4614,13 @@
UInt opc2 = ifieldOPClo10(theInstr);
UChar b0 = ifieldBIT0(theInstr);
- IRTemp rS;
+ IRTemp rS = newTemp(Ity_I32);
+ assign( rS, getIReg(rS_addr) );
/* Reorder SPR field as per PPC32 p470 */
SPR = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F);
-
/* Reorder TBR field as per PPC32 p475 */
TBR = ((TBR & 31) << 5) | ((TBR >> 5) & 31);
-
- rS = newTemp(Ity_I32);
- assign( rS, getIReg(rS_addr) );
if (opc1 != 0x1F || b0 != 0) {
vex_printf("dis_proc_ctl(PPC32)(opc1|b0)\n");
@@ -3729,8 +4636,8 @@
}
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 ),
+ putGST_field( PPC_GST_CR,
+ getGST_field( PPC_GST_XER, 7 ),
crfD );
// Clear XER[0-3]
@@ -3745,48 +4652,34 @@
vex_printf("dis_proc_ctl(PPC32)(mfcr,b11to20)\n");
return False;
}
- DIP("mfcr r%d\n", rD_addr);
- putIReg( rD_addr, getSPR( PPC32_SPR_CR ) );
+ DIP("mfcr r%u\n", rD_addr);
+ putIReg( rD_addr, getGST( PPC_GST_CR ) );
break;
/* XFX-Form */
case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470)
switch (SPR) { // Choose a register...
-
- case 0x1:
- DIP("mfxer r%d\n", rD_addr);
- putIReg( rD_addr, getSPR( PPC32_SPR_XER ) );
- break;
- case 0x8:
- DIP("mflr r%d\n", rD_addr);
- putIReg( rD_addr, getSPR( PPC32_SPR_LR ) );
- break;
- case 0x9:
- DIP("mfctr r%d\n", rD_addr);
- putIReg( rD_addr, getSPR( PPC32_SPR_CTR ) );
- break;
- case 0x100:
- DIP("mfvrsave r%d\n", rD_addr);
- putIReg( rD_addr, getSPR( PPC32_SPR_VRSAVE ) );
- break;
-
- case 0x012: case 0x013: case 0x016:
- case 0x019: case 0x01A: case 0x01B:
- case 0x110: case 0x111: case 0x112: case 0x113:
- // case 0x118: // 64bit only
- case 0x11A: case 0x11F:
- case 0x210: case 0x211: case 0x212: case 0x213:
- case 0x214: case 0x215: case 0x216: case 0x217:
- case 0x218: case 0x219: case 0x21A: case 0x21B:
- case 0x21C: case 0x21D: case 0x21E: case 0x21F:
- case 0x3F5:
- vex_printf("dis_proc_ctl(PPC32)(mfspr) - supervisor level op\n");
- return False;
-
- default:
- vex_printf("dis_proc_ctl(PPC32)(mfspr,SPR)(0x%x)\n", SPR);
- return False;
+ case 0x1:
+ DIP("mfxer r%u\n", rD_addr);
+ putIReg( rD_addr, getGST( PPC_GST_XER ) );
+ break;
+ case 0x8:
+ DIP("mflr r%u\n", rD_addr);
+ putIReg( rD_addr, getGST( PPC_GST_LR ) );
+ break;
+ case 0x9:
+ DIP("mfctr r%u\n", rD_addr);
+ putIReg( rD_addr, getGST( PPC_GST_CTR ) );
+ break;
+ case 0x100:
+ DIP("mfvrsave r%u\n", rD_addr);
+ putIReg( rD_addr, getGST( PPC_GST_VRSAVE ) );
+ break;
+
+ default:
+ vex_printf("dis_proc_ctl(PPC32)(mfspr,SPR)(0x%x)\n", SPR);
+ return False;
}
break;
@@ -3804,16 +4697,16 @@
stmt( IRStmt_Dirty(d) );
switch (TBR) {
- case 269:
- putIReg( rD_addr, unop(Iop_64HIto32, mkexpr(val)) );
- DIP("mftbu r%d", rD_addr);
- break;
- case 268:
- putIReg( rD_addr, unop(Iop_64to32, mkexpr(val)) );
- DIP("mftb r%d", rD_addr);
- break;
- default:
- return False; /* illegal instruction */
+ case 269:
+ putIReg( rD_addr, unop(Iop_64HIto32, mkexpr(val)) );
+ DIP("mftbu r%u", rD_addr);
+ break;
+ case 268:
+ putIReg( rD_addr, unop(Iop_64to32, mkexpr(val)) );
+ DIP("mftb r%u", rD_addr);
+ break;
+ default:
+ return False; /* illegal instruction */
}
break;
}
@@ -3825,13 +4718,13 @@
vex_printf("dis_proc_ctl(PPC32)(mtcrf,b11|b20)\n");
return False;
}
- DIP("mtcrf 0x%x,r%d\n", CRM, rS_addr);
+ DIP("mtcrf 0x%x,r%u\n", CRM, rS_addr);
/* Write to each field specified by CRM */
for (cr = 0; cr < 8; cr++) {
if ((CRM & (1 << (7-cr))) == 0)
continue;
shft = 4*(7-cr);
- putSPR_field( PPC32_SPR_CR,
+ putGST_field( PPC_GST_CR,
binop(Iop_Shr32, mkexpr(rS), mkU8(shft)), cr );
}
break;
@@ -3840,26 +4733,26 @@
case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483)
switch (SPR) { // Choose a register...
- case 0x1:
- DIP("mtxer r%d\n", rS_addr);
- putSPR( PPC32_SPR_XER, mkexpr(rS) );
- break;
- case 0x8:
- DIP("mtlr r%d\n", rS_addr);
- putSPR( PPC32_SPR_LR, mkexpr(rS) );
- break;
- case 0x9:
- DIP("mtctr r%d\n", rS_addr);
- putSPR( PPC32_SPR_CTR, mkexpr(rS) );
- break;
- case 0x100:
- DIP("mtvrsave r%d\n", rS_addr);
- putSPR( PPC32_SPR_VRSAVE, mkexpr(rS) );
- break;
-
- default:
- vex_printf("dis_proc_ctl(PPC32)(mtspr,SPR)(%u)\n", SPR);
- return False;
+ case 0x1:
+ DIP("mtxer r%u\n", rS_addr);
+ putGST( PPC_GST_XER, mkexpr(rS) );
+ break;
+ case 0x8:
+ DIP("mtlr r%u\n", rS_addr);
+ putGST( PPC_GST_LR, mkexpr(rS) );
+ break;
+ case 0x9:
+ DIP("mtctr r%u\n", rS_addr);
+ putGST( PPC_GST_CTR, mkexpr(rS) );
+ break;
+ case 0x100:
+ DIP("mtvrsave r%u\n", rS_addr);
+ putGST( PPC_GST_VRSAVE, mkexpr(rS) );
+ break;
+
+ default:
+ vex_printf("dis_proc_ctl(PPC32)(mtspr,SPR)(%u)\n", SPR);
+ return False;
}
break;
@@ -3885,7 +4778,9 @@
UChar rB_addr = ifieldRegB(theInstr);
UInt opc2 = ifieldOPClo10(theInstr);
UChar b0 = ifieldBIT0(theInstr);
- Int lineszB = guest_archinfo->ppc32_cache_line_szB;
+ UInt lineszB = guest_archinfo->ppc32_cache_line_szB;
+
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
if (opc1 != 0x1F || b21to25 != 0 || b0 != 0) {
vex_printf("dis_cache_manage(PPC32)(opc1|b21to25|b0)\n");
@@ -3898,28 +4793,28 @@
switch (opc2) {
//zz case 0x2F6: // dcba (Data Cache Block Allocate, PPC32 p380)
//zz vassert(0); /* AWAITING TEST CASE */
-//zz DIP("dcba r%d,r%d\n", rA_addr, rB_addr);
+//zz DIP("dcba r%u,r%u\n", rA_addr, rB_addr);
//zz if (0) vex_printf("vex ppc32->IR: kludged dcba\n");
//zz break;
case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382)
- DIP("dcbf r%d,r%d\n", rA_addr, rB_addr);
+ DIP("dcbf r%u,r%u\n", rA_addr, rB_addr);
/* nop as far as vex is concerned */
if (0) vex_printf("vex ppc32->IR: kludged dcbf\n");
break;
case 0x036: // dcbst (Data Cache Block Store, PPC32 p384)
- DIP("dcbst r%d,r%d\n", rA_addr, rB_addr);
+ DIP("dcbst r%u,r%u\n", rA_addr, rB_addr);
/* nop as far as vex is concerned */
break;
case 0x116: // dcbt (Data Cache Block Touch, PPC32 p385)
- DIP("dcbt r%d,r%d\n", rA_addr, rB_addr);
+ DIP("dcbt r%u,r%u\n", rA_addr, rB_addr);
/* nop as far as vex is concerned */
break;
case 0x0F6: // dcbtst (Data Cache Block Touch for Store, PPC32 p386)
- DIP("dcbtst r%d,r%d\n", rA_addr, rB_addr);
+ DIP("dcbtst r%u,r%u\n", rA_addr, rB_addr);
/* nop as far as vex is concerned */
break;
@@ -3929,10 +4824,8 @@
IRTemp addr = newTemp(Ity_I32);
IRExpr* irx_addr;
UInt i;
- DIP("dcbz r%d,r%d\n", rA_addr, rB_addr);
- assign( EA, binop( Iop_Add32,
- getIReg(rB_addr),
- rA_addr==0 ? mkU32(0) : getIReg(rA_addr)) );
+ DIP("dcbz r%u,r%u\n", rA_addr, rB_addr);
+ assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
/* Round EA down to the start of the containing block. */
assign( addr, binop( Iop_And32,
@@ -3950,28 +4843,23 @@
// icbi (Instruction Cache Block Invalidate, PPC32 p431)
/* Invalidate all translations containing code from the cache
block at (rA|0) + rB. */
- IRTemp addr = newTemp(Ity_I32);
- DIP("icbi r%d,r%d\n", rA_addr, rB_addr);
-
- assign( addr,
- binop( Iop_Add32,
- getIReg(rB_addr),
- rA_addr==0 ? mkU32(0) : getIReg(rA_addr)) );
+ IRTemp EA = newTemp(ty);
+ IRTemp addr = newTemp(ty);
+ DIP("icbi r%u,r%u\n", rA_addr, rB_addr);
+ assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
/* Round addr down to the start of the containing block. */
- stmt( IRStmt_Put(
- OFFB_TISTART,
- binop( Iop_And32,
- mkexpr(addr),
- mkU32( ~(lineszB-1) ))) );
-
- stmt( IRStmt_Put(OFFB_TILEN, mkU32(lineszB) ) );
+ assign( addr, binop( mkSizedOp(ty, Iop_And8),
+ mkexpr(EA),
+ mkSizedImm(ty, ~(((ULong)lineszB)-1) )) );
+ putGST( PPC_GST_TISTART, mkexpr(addr) );
+ putGST( PPC_GST_TILEN, mkSizedImm(ty, lineszB) );
/* be paranoid ... */
stmt( IRStmt_MFence() );
irbb->jumpkind = Ijk_TInval;
- irbb->next = mkU32(guest_CIA_curr_instr + 4);
+ irbb->next = mkSizedImm(ty, nextInsnAddr());
dres->whatNext = Dis_StopHere;
break;
}
@@ -3988,14 +4876,6 @@
/*--- Floating Point Helpers ---*/
/*------------------------------------------------------------*/
-/* --- Set the emulation-warning pseudo-register. --- */
-
-static void put_emwarn ( IRExpr* e /* :: Ity_I32 */ )
-{
- vassert(typeOfIRExpr(irbb->tyenv,e) == Ity_I32);
- stmt( IRStmt_Put( OFFB_EMWARN, e ) );
-}
-
/* --------- Synthesise a 2-bit FPU rounding mode. --------- */
/* Produces a value in 0 .. 3, which is encoded as per the type
IRRoundingMode. PPC32RoundingMode encoding is different to
@@ -4012,7 +4892,7 @@
to -infinity | 11 | 01
*/
IRTemp rm_PPC32 = newTemp(Ity_I32);
- assign( rm_PPC32, getSPR_masked( PPC32_SPR_FPSCR, MASK_FPSCR_RN ) );
+ assign( rm_PPC32, getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ) );
// rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
return binop(Iop_Xor32, mkexpr(rm_PPC32),
@@ -4044,21 +4924,28 @@
UChar rB_addr = ifieldRegB(theInstr);
UInt opc2 = ifieldOPClo10(theInstr);
UChar b0 = ifieldBIT0(theInstr);
- Int d_simm16 = ifieldSIMM16(theInstr);
+ Int uimm16 = ifieldUIMM16(theInstr);
- IRTemp EA = newTemp(Ity_I32);
- IRTemp rA = newTemp(Ity_I32);
- IRTemp rB = newTemp(Ity_I32);
- IRTemp rA_or_0 = newTemp(Ity_I32);
+ Int simm16 = extend_s_16to32(uimm16);
+ IRTemp EA, rA, rB;
+ if (mode64) {
+ EA = newTemp(Ity_I64);
+ rA = newTemp(Ity_I64);
+ rB = newTemp(Ity_I64);
+ } else {
+ EA = newTemp(Ity_I32);
+ rA = newTemp(Ity_I32);
+ rB = newTemp(Ity_I32);
+ }
assign( rA, getIReg(rA_addr) );
assign( rB, getIReg(rB_addr) );
- assign( rA_or_0, ea_rA_or_zero(rA_addr) );
+
switch(opc1) {
case 0x30: // lfs (Load Float Single, PPC32 p441)
- DIP("lfs fr%d,%d(r%d)\n", frD_addr, d_simm16, rA_addr);
- assign( EA, binop(Iop_Add32, mkU32(d_simm16), mkexpr(rA_or_0)) );
+ DIP("lfs fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
+ assign( EA, ea_rAor0_simm(rA_addr, simm16) );
putFReg( frD_addr, unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
break;
@@ -4067,15 +4954,15 @@
//zz vex_printf("dis_fp_load(PPC32)(instr,lfsu)\n");
//zz return False;
//zz }
-//zz DIP("lfsu fr%d,%d(r%d)\n", frD_addr, d_simm16, rA_addr);
-//zz assign( EA, binop(Iop_Add32, mkU32(d_simm16), mkexpr(rA)) );
+//zz DIP("lfsu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
+//zz assign( EA, ea_rAor0_simm(rA_addr, simm16) );
//zz putFReg( frD_addr, unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
//zz putIReg( rA_addr, mkexpr(EA) );
//zz break;
case 0x32: // lfd (Load Float Double, PPC32 p437)
- DIP("lfd fr%d,%d(r%d)\n", frD_addr, d_simm16, rA_addr);
- assign( EA, binop(Iop_Add32, mkU32(d_simm16), mkexpr(rA_or_0)) );
+ DIP("lfd fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
+ assign( EA, ea_rAor0_simm(rA_addr, simm16) );
putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
break;
@@ -4084,8 +4971,8 @@
vex_printf("dis_fp_load(PPC32)(instr,lfdu)\n");
return False;
}
- DIP("lfdu fr%d,%d(r%d)\n", frD_addr, d_simm16, rA_addr);
- assign( EA, binop(Iop_Add32, mkU32(d_simm16), mkexpr(rA)) );
+ DIP("lfdu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
+ assign( EA, ea_rA_simm(rA_addr, simm16) );
putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
putIReg( rA_addr, mkexpr(EA) );
break;
@@ -4097,44 +4984,44 @@
}
switch(opc2) {
- case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444)
- DIP("lfsx fr%d,r%d,r%d\n", frD_addr, rA_addr, rB_addr);
- assign( EA, binop(Iop_Add32, mkexpr(rB), mkexpr(rA_or_0)) );
- putFReg( frD_addr, unop( Iop_F32toF64,
- loadBE(Ity_F32, mkexpr(EA))) );
- break;
-
- case 0x237: // lfsux (Load Float Single with Update Indexed, PPC32 p443)
- if (rA_addr == 0) {
- vex_printf("dis_fp_load(PPC32)(instr,lfsux)\n");
- return False;
- }
- DIP("lfsux fr%d,r%d,r%d\n", frD_addr, rA_addr, rB_addr);
- assign( EA, binop(Iop_Add32, mkexpr(rB), mkexpr(rA)) );
- putFReg( frD_addr, unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
- putIReg( rA_addr, mkexpr(EA) );
- break;
-
- case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440)
- DIP("lfdx fr%d,r%d,r%d\n", frD_addr, rA_addr, rB_addr);
- assign( EA, binop(Iop_Add32, mkexpr(rB), mkexpr(rA_or_0)) );
- putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
- break;
-
- case 0x277: // lfdux (Load Float Double with Update Indexed, PPC32 p439)
- if (rA_addr == 0) {
- vex_printf("dis_fp_load(PPC32)(instr,lfdux)\n");
- return False;
- }
- DIP("lfdux fr%d,r%d,r%d\n", frD_addr, rA_addr, rB_addr);
- assign( EA, binop(Iop_Add32, mkexpr(rB), mkexpr(rA)) );
- putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
- putIReg( rA_addr, mkexpr(EA) );
- break;
-
- default:
- vex_printf("dis_fp_load(PPC32)(opc2)\n");
+ case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444)
+ DIP("lfsx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
+ assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
+ putFReg( frD_addr, unop( Iop_F32toF64,
+ loadBE(Ity_F32, mkexpr(EA))) );
+ break;
+
+ case 0x237: // lfsux (Load Float Single with Update Indexed, PPC32 p443)
+ if (rA_addr == 0) {
+ vex_printf("dis_fp_load(PPC32)(instr,lfsux)\n");
return False;
+ }
+ DIP("lfsux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
+ assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
+ putFReg( frD_addr, unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
+ putIReg( rA_addr, mkexpr(EA) );
+ break;
+
+ case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440)
+ DIP("lfdx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
+ assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
+ putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
+ break;
+
+ case 0x277: // lfdux (Load Float Double with Update Indexed, PPC32 p439)
+ if (rA_addr == 0) {
+ vex_printf("dis_fp_load(PPC32)(instr,lfdux)\n");
+ return False;
+ }
+ DIP("lfdux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
+ assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
+ putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
+ putIReg( rA_addr, mkexpr(EA) );
+ break;
+
+ default:
+ vex_printf("dis_fp_load(PPC32)(opc2)\n");
+ return False;
}
break;
@@ -4159,24 +5046,30 @@
UChar rB_addr = ifieldRegB(theInstr);
UInt opc2 = ifieldOPClo10(theInstr);
UChar b0 = ifieldBIT0(theInstr);
- Int d_simm16 = ifieldSIMM16(theInstr);
+ Int uimm16 = ifieldUIMM16(theInstr);
- IRTemp EA = newTemp(Ity_I32);
+ Int simm16 = extend_s_16to32(uimm16);
IRTemp frS = newTemp(Ity_F64);
- IRTemp rA = newTemp(Ity_I32);
- IRTemp rB = newTemp(Ity_I32);
- IRTemp rA_or_0 = newTemp(Ity_I32);
+ IRTemp EA, rA, rB;
+ if (mode64) {
+ EA = newTemp(Ity_I64);
+ rA = newTemp(Ity_I64);
+ rB = newTemp(Ity_I64);
+ } else {
+ EA = newTemp(Ity_I32);
+ rA = newTemp(Ity_I32);
+ rB = newTemp(Ity_I32);
+ }
assign( frS, getFReg(frS_addr) );
assign( rA, getIReg(rA_addr) );
assign( rB, getIReg(rB_addr) );
- assign( rA_or_0, ea_rA_or_zero(rA_addr) );
switch(opc1) {
case 0x34: // stfs (Store Float Single, PPC32 p518)
- DIP("stfs fr%d,%d(r%d)\n", frS_addr, d_simm16, rA_addr);
- assign( EA, binop(Iop_Add32, mkU32(d_simm16), mkexpr(rA_or_0)) );
+ DIP("stfs fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
+ assign( EA, ea_rAor0_simm(rA_addr, simm16) );
storeBE( mkexpr(EA),
binop(Iop_F64toF32, get_roundingmode(), mkexpr(frS)) );
break;
@@ -4186,16 +5079,16 @@
//zz vex_printf("dis_fp_store(PPC32)(instr,stfsu)\n");
//zz return False;
//zz }
-//zz DIP("stfsu fr%d,%d(r%d)\n", frS_addr, d_simm16, rA_addr);
-//zz assign( EA, binop(Iop_Add32, mkU32(d_simm16), mkexpr(rA)) );
+//zz DIP("stfsu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
+//zz assign( EA, ea_rA_simm(rA_addr, simm16) );
//zz storeBE( mkexpr(EA),
//zz binop(Iop_F64toF32, get_roundingmode(), mkexpr(frS)) );
//zz putIReg( rA_addr, mkexpr(EA) );
//zz break;
case 0x36: // stfd (Store Float Double, PPC32 p513)
- DIP("stfd fr%d,%d(r%d)\n", frS_addr, d_simm16, rA_addr);
- assign( EA, binop(Iop_Add32, mkU32(d_simm16), mkexpr(rA_or_0)) );
+ DIP("stfd fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
+ assign( EA, ea_rAor0_simm(rA_addr, simm16) );
storeBE( mkexpr(EA), mkexpr(frS) );
break;
@@ -4204,8 +5097,8 @@
vex_printf("dis_fp_store(PPC32)(instr,stfdu)\n");
return False;
}
- DIP("stfdu fr%d,%d(r%d)\n", frS_addr, d_simm16, rA_addr);
- assign( EA, binop(Iop_Add32, mkU32(d_simm16), mkexpr(rA)) );
+ DIP("stfdu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
+ assign( EA, ea_rA_simm(rA_addr, simm16) );
storeBE( mkexpr(EA), mkexpr(frS) );
putIReg( rA_addr, mkexpr(EA) );
break;
@@ -4217,52 +5110,52 @@
}
switch(opc2) {
- case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521)
- DIP("stfsx fr%d,r%d,r%d\n", frS_addr, rA_addr, rB_addr);
- assign( EA, binop(Iop_Add32, mkexpr(rB), mkexpr(rA_or_0)) );
- storeBE( mkexpr(EA),
- binop(Iop_F64toF32, get_roundingmode(), mkexpr(frS)) );
- break;
-
+ case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521)
+ DIP("stfsx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
+ assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
+ storeBE( mkexpr(EA),
+ binop(Iop_F64toF32, get_roundingmode(), mkexpr(frS)) );
+ break;
+
//zz case 0x2B7: // stfsux (Store Float Single with Update Indexed, PPC32 p520)
//zz if (rA_addr == 0) {
//zz vex_printf("dis_fp_store(PPC32)(instr,stfsux)\n");
//zz return False;
//zz }
-//zz DIP("stfsux fr%d,r%d,r%d\n", frS_addr, rA_addr, rB_addr);
-//zz assign( EA, binop(Iop_Add32, mkexpr(rB), mkexpr(rA)) );
+//zz DIP("stfsux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
+//zz assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
//zz storeBE( mkexpr(EA),
//zz binop(Iop_F64toF32, get_roundingmode(), mkexpr(frS)) );
//zz putIReg( rA_addr, mkexpr(EA) );
//zz break;
- case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516)
- DIP("stfdx fr%d,r%d,r%d\n", frS_addr, rA_addr, rB_addr);
- assign( EA, binop(Iop_Add32, mkexpr(rB), mkexpr(rA_or_0)) );
- storeBE( mkexpr(EA), mkexpr(frS) );
- break;
+ case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516)
+ DIP("stfdx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
+ assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
+ storeBE( mkexpr(EA), mkexpr(frS) );
+ break;
- case 0x2F7: // stfdux (Store Float Double with Update Indexed, PPC32 p515)
- if (rA_addr == 0) {
- vex_printf("dis_fp_store(PPC32)(instr,stfdux)\n");
- return False;
- }
- DIP("stfdux fr%d,r%d,r%d\n", frS_addr, rA_addr, rB_addr);
- assign( EA, binop(Iop_Add32, mkexpr(rB), mkexpr(rA)) );
- storeBE( mkexpr(EA), mkexpr(frS) );
- putIReg( rA_addr, mkexpr(EA) );
- break;
+ case 0x2F7: // stfdux (Store Float Double with Update Indexed, PPC32 p515)
+ if (rA_addr == 0) {
+ vex_printf("dis_fp_store(PPC32)(instr,stfdux)\n");
+ return False;
+ }
+ DIP("stfdux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
+ assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
+ storeBE( mkexpr(EA), mkexpr(frS) );
+ putIReg( rA_addr, mkexpr(EA) );
+ break;
//zz case 0x3D7: // stfiwx (Store Float as Int, Indexed, PPC32 p517)
-//zz DIP("stfiwx fr%d,r%d,r%d\n", frS_addr, rA_addr, rB_addr);
-//zz assign( EA, binop(Iop_Add32, mkexpr(rB), mkexpr(rA_or_0)) );
+//zz DIP("stfiwx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
+//zz assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
//zz storeBE( mkexpr(EA),
//zz unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) );
//zz break;
- default:
- vex_printf("dis_fp_store(PPC32)(opc2)\n");
- return False;
+ default:
+ vex_printf("dis_fp_store(PPC32)(opc2)\n");
+ return False;
}
break;
@@ -4307,7 +5200,7 @@
vex_printf("dis_fp_arith(PPC32)(instr,fdivs)\n");
return False;
}
- DIP("fdivs%s fr%d,fr%d,fr%d\n", flag_rC ? "." : "",
+ DIP("fdivs%s fr%u,fr%u,fr%u\n", flag_rC ? "." : "",
frD_addr, frA_addr, frB_addr);
assign( frD, roundToSgl( binop(Iop_DivF64, mkexpr(frA), mkexpr(frB)) ));
break;
@@ -4317,7 +5210,7 @@
vex_printf("dis_fp_arith(PPC32)(instr,fsubs)\n");
return False;
}
- DIP("fsubs%s fr%d,fr%d,fr%d\n", flag_rC ? "." : "",
+ DIP("fsubs%s fr%u,fr%u,fr%u\n", flag_rC ? "." : "",
frD_addr, frA_addr, frB_addr);
assign( frD, roundToSgl(
binop(Iop_SubF64, mkexpr(frA), mkexpr(frB)) ));
@@ -4328,7 +5221,7 @@
vex_printf("dis_fp_arith(PPC32)(instr,fadds)\n");
return False;
}
- DIP("fadds%s fr%d,fr%d,fr%d\n", flag_rC ? "." : "",
+ DIP("fadds%s fr%u,fr%u,fr%u\n", flag_rC ? "." : "",
frD_addr, frA_addr, frB_addr);
assign( frD, roundToSgl(
binop(Iop_AddF64, mkexpr(frA), mkexpr(frB)) ));
@@ -4339,7 +5232,7 @@
//zz vex_printf("dis_fp_arith(PPC32)(instr,fsqrts)\n");
//zz return False;
//zz }
-//zz DIP("fsqrts%s fr%d,fr%d\n", flag_rC ? "." : "",
+//zz DIP("fsqrts%s fr%u,fr%u\n", flag_rC ? "." : "",
//zz frD_addr, frB_addr);
//zz assign( frD, roundToSgl( unop(Iop_SqrtF64, mkexpr(frB)) ));
//zz break;
@@ -4349,7 +5242,7 @@
//zz vex_printf("dis_fp_arith(PPC32)(instr,fres)\n");
//zz return False;
//zz }
-//zz DIP("fres%s fr%d,fr%d\n", flag_rC ? "." : "",
+//zz DIP("fres%s fr%u,fr%u\n", flag_rC ? "." : "",
//zz frD_addr, frB_addr);
//zz DIP(" => not implemented\n");
//zz // CAB: Can we use one of the 128 bit SIMD Iop_Recip32F ops?
@@ -4360,7 +5253,7 @@
vex_printf("dis_fp_arith(PPC32)(instr,fmuls)\n");
return False;
}
- DIP("fmuls%s fr%d,fr%d,fr%d\n", flag_rC ? "." : "",
+ DIP("fmuls%s fr%u,fr%u,fr%u\n", flag_rC ? "." : "",
frD_addr, frA_addr, frC_addr);
assign( frD, roundToSgl( binop(Iop_MulF64, mkexpr(frA), mkexpr(frC)) ));
break;
@@ -4378,7 +5271,7 @@
vex_printf("dis_fp_arith(PPC32)(instr,fdiv)\n");
return False;
}
- DIP("fdiv%s fr%d,fr%d,fr%d\n", flag_rC ? "." : "",
+ DIP("fdiv%s fr%u,fr%u,fr%u\n", flag_rC ? "." : "",
frD_addr, frA_addr, frB_addr);
assign( frD, binop( Iop_DivF64, mkexpr(frA), mkexpr(frB) ) );
break;
@@ -4388,7 +5281,7 @@
vex_printf("dis_fp_arith(PPC32)(instr,fsub)\n");
return False;
}
- DIP("fsub%s fr%d,fr%d,fr%d\n", flag_rC ? "." : "",
+ DIP("fsub%s fr%u,fr%u,fr%u\n", flag_rC ? "." : "",
frD_addr, frA_addr, frB_addr);
assign( frD, binop( Iop_SubF64, mkexpr(frA), mkexpr(frB) ) );
break;
@@ -4398,7 +5291,7 @@
vex_printf("dis_fp_arith(PPC32)(instr,fadd)\n");
return False;
}
- DIP("fadd%s fr%d,fr%d,fr%d\n", flag_rC ? "." : "",
+ DIP("fadd%s fr%u,fr%u,fr%u\n", flag_rC ? "." : "",
frD_addr, frA_addr, frB_addr);
assign( frD, binop( Iop_AddF64, mkexpr(frA), mkexpr(frB) ) );
break;
@@ -4408,7 +5301,7 @@
//zz vex_printf("dis_fp_arith(PPC32)(instr,fsqrt)\n");
//zz return False;
//zz }
-//zz DIP("fsqrt%s fr%d,fr%d\n", flag_rC ? "." : "",
+//zz DIP("fsqrt%s fr%u,fr%u\n", flag_rC ? "." : "",
//zz frD_addr, frB_addr);
//zz assign( frD, unop( Iop_SqrtF64, mkexpr(frB) ) );
//zz break;
@@ -4417,7 +5310,7 @@
IRTemp cc = newTemp(Ity_I32);
IRTemp cc_b0 = newTemp(Ity_I32);
- DIP("fsel%s fr%d,fr%d,fr%d,fr%d\n", flag_rC ? "." : "",
+ DIP("fsel%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? "." : "",
frD_addr, frA_addr, frC_addr, frB_addr);
// cc: UN == 0x41, LT == 0x01, GT == 0x00, EQ == 0x40
@@ -4441,7 +5334,7 @@
vex_printf("dis_fp_arith(PPC32)(instr,fmul)\n");
return False;
}
- DIP("fmul%s fr%d,fr%d,fr%d\n", flag_rC ? "." : "",
+ DIP("fmul%s fr%u,fr%u,fr%u\n", flag_rC ? "." : "",
frD_addr, frA_addr, frC_addr);
assign( frD, binop( Iop_MulF64, mkexpr(frA), mkexpr(frC) ) );
break;
@@ -4451,7 +5344,7 @@
//zz vex_printf("dis_fp_arith(PPC32)(instr,frsqrte)\n");
//zz return False;
//zz }
-//zz DIP("frsqrte%s fr%d,fr%d\n", flag_rC ? "." : "",
+//zz DIP("frsqrte%s fr%u,fr%u\n", flag_rC ? "." : "",
//zz frD_addr, frB_addr);
//zz DIP(" => not implemented\n");
//zz // CAB: Iop_SqrtF64, then one of the 128 bit SIMD Iop_Recip32F ops?
@@ -4501,7 +5394,7 @@
case 0x3B:
switch (opc2) {
case 0x1C: // fmsubs (Floating Mult-Subtr Single, PPC32 p412)
- DIP("fmsubs%s fr%d,fr%d,fr%d,fr%d\n", flag_rC ? "." : "",
+ DIP("fmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? "." : "",
frD_addr, frA_addr, frC_addr, frB_addr);
assign( frD, roundToSgl(
binop( Iop_SubF64,
@@ -4510,7 +5403,7 @@
break;
case 0x1D: // fmadds (Floating Mult-Add Single, PPC32 p409)
- DIP("fmadds%s fr%d,fr%d,fr%d,fr%d\n", flag_rC ? "." : "",
+ DIP("fmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? "." : "",
frD_addr, frA_addr, frC_addr, frB_addr);
assign( frD, roundToSgl(
binop( Iop_AddF64,
@@ -4519,7 +5412,7 @@
break;
case 0x1E: // fnmsubs (Float Neg Mult-Subtr Single, PPC32 p420)
- DIP("fnmsubs%s fr%d,fr%d,fr%d,fr%d\n", flag_rC ? "." : "",
+ DIP("fnmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? "." : "",
frD_addr, frA_addr, frC_addr, frB_addr);
assign( frD, roundToSgl(
unop(Iop_NegF64,
@@ -4529,7 +5422,7 @@
break;
case 0x1F: // fnmadds (Floating Negative Multiply-Add Single, PPC32 p418)
- DIP("fnmadds%s fr%d,fr%d,fr%d,fr%d\n", flag_rC ? "." : "",
+ DIP("fnmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? "." : "",
frD_addr, frA_addr, frC_addr, frB_addr);
assign( frD, roundToSgl(
unop(Iop_NegF64,
@@ -4547,7 +5440,7 @@
case 0x3F:
switch (opc2) {
case 0x1C: // fmsub (Float Mult-Subtr (Double Precision), PPC32 p411)
- DIP("fmsub%s fr%d,fr%d,fr%d,fr%d\n", flag_rC ? "." : "",
+ DIP("fmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? "." : "",
frD_addr, frA_addr, frC_addr, frB_addr);
assign( frD, binop( Iop_SubF64,
binop( Iop_MulF64, mkexpr(frA), mkexpr(frC) ),
@@ -4555,7 +5448,7 @@
break;
case 0x1D: // fmadd (Float Mult-Add (Double Precision), PPC32 p408)
- DIP("fmadd%s fr%d,fr%d,fr%d,fr%d\n", flag_rC ? "." : "",
+ DIP("fmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? "." : "",
frD_addr, frA_addr, frC_addr, frB_addr);
assign( frD, binop( Iop_AddF64,
binop( Iop_MulF64, mkexpr(frA), mkexpr(frC) ),
@@ -4563,7 +5456,7 @@
break;
case 0x1E: // fnmsub (Float Neg Mult-Subtr (Double Precision), PPC32 p419)
- DIP("fnmsub%s fr%d,fr%d,fr%d,fr%d\n", flag_rC ? "." : "",
+ DIP("fnmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? "." : "",
frD_addr, frA_addr, frC_addr, frB_addr);
assign( frD, unop( Iop_NegF64,
binop( Iop_SubF64,
@@ -4572,7 +5465,7 @@
break;
case 0x1F: // fnmadd (Float Neg Mult-Add (Double Precision), PPC32 p417)
- DIP("fnmadd%s fr%d,fr%d,fr%d,fr%d\n", flag_rC ? "." : "",
+ DIP("fnmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? "." : "",
frD_addr, frA_addr, frC_addr, frB_addr);
assign( frD, unop( Iop_NegF64,
binop( Iop_AddF64,
@@ -4651,24 +5544,24 @@
binop(Iop_Shr32, mkexpr(ccIR), mkU8(6)))))))
);
- putSPR_field( PPC32_SPR_CR, mkexpr(ccPPC32), crfD );
+ putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
/* CAB: TODO?: Support writing cc to FPSCR->FPCC ?
- putSPR_field( PPC32_SPR_FPSCR, mkexpr(ccPPC32), 4 );
+ putGST_field( PPC_GST_FPSCR, mkexpr(ccPPC32), 4 );
*/
/* 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;
- default:
- vex_printf("dis_fp_cmp(PPC32)(opc2)\n");
- return False;
+ case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403)
+ DIP("fcmpu crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
+ break;
+ case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402)
+ DIP("fcmpo crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
+ break;
+ default:
+ vex_printf("dis_fp_cmp(PPC32)(opc2)\n");
+ return False;
}
return True;
}
@@ -4700,28 +5593,28 @@
assign( frB, getFReg(frB_addr));
switch (opc2) {
- case 0x00C: // frsp (Floating Round to Single, PPC32 p423)
- DIP("frsp%s fr%d,fr%d\n", flag_rC ? "." : "", frD_addr, frB_addr);
- assign( frD, roundToSgl( mkexpr(frB) ));
- break;
-
- case 0x00E: // fctiw (Floating Conv to Int, PPC32 p404)
- DIP("fctiw%s fr%d,fr%d\n", flag_rC ? "." : "", frD_addr, frB_addr);
- assign( r_tmp, binop(Iop_F64toI32, get_roundingmode(), mkexpr(frB)) );
- assign( frD, unop( Iop_ReinterpI64asF64,
- unop( Iop_32Uto64, mkexpr(r_tmp))));
- break;
-
- case 0x00F: // fctiwz (Floating Conv to Int, Round to Zero, PPC32 p405)
- DIP("fctiwz%s fr%d,fr%d\n", flag_rC ? "." : "", frD_addr, frB_addr);
- assign( r_tmp, binop(Iop_F64toI32, mkU32(0x3), mkexpr(frB)) );
- assign( frD, unop( Iop_ReinterpI64asF64,
- unop( Iop_32Uto64, mkexpr(r_tmp))));
- break;
-
- default:
- vex_printf("dis_fp_round(PPC32)(opc2)\n");
- return False;
+ case 0x00C: // frsp (Floating Round to Single, PPC32 p423)
+ DIP("frsp%s fr%u,fr%u\n", flag_rC ? "." : "", frD_addr, frB_addr);
+ assign( frD, roundToSgl( mkexpr(frB) ));
+ break;
+
+ case 0x00E: // fctiw (Floating 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( frD, unop( Iop_ReinterpI64asF64,
+ unop( Iop_32Uto64, mkexpr(r_tmp))));
+ break;
+
+ case 0x00F: // fctiwz (Floating 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( frD, unop( Iop_ReinterpI64asF64,
+ unop( Iop_32Uto64, mkexpr(r_tmp))));
+ break;
+
+ default:
+ vex_printf("dis_fp_round(PPC32)(opc2)\n");
+ return False;
}
putFReg( frD_addr, mkexpr(frD) );
@@ -4754,29 +5647,29 @@
assign( frB, getFReg(frB_addr));
switch (opc2) {
- case 0x028: // fneg (Floating Negate, PPC32 p416)
- DIP("fneg%s fr%d,fr%d\n", flag_rC ? "." : "", frD_addr, frB_addr);
- assign( frD, unop( Iop_NegF64, mkexpr(frB) ));
- break;
-
- case 0x048: // fmr (Floating Move Register, PPC32 p410)
- DIP("fmr%s fr%d,fr%d\n", flag_rC ? "." : "", frD_addr, frB_addr);
- assign( frD, mkexpr(frB) );
- break;
-
- case 0x088: // fnabs (Floating Negative Absolute Value, PPC32 p415)
- DIP("fnabs%s fr%d,fr%d\n", flag_rC ? "." : "", frD_addr, frB_addr);
- assign( frD, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr(frB) )));
- break;
-
- case 0x108: // fabs (Floating Absolute Value, PPC32 p399)
- DIP("fabs%s fr%d,fr%d\n", flag_rC ? "." : "", frD_addr, frB_addr);
- assign( frD, unop( Iop_AbsF64, mkexpr(frB) ));
- break;
-
- default:
- vex_printf("dis_fp_move(PPC32)(opc2)\n");
- return False;
+ case 0x028: // fneg (Floating Negate, PPC32 p416)
+ DIP("fneg%s fr%u,fr%u\n", flag_rC ? "." : "", frD_addr, frB_addr);
+ assign( frD, unop( Iop_NegF64, mkexpr(frB) ));
+ break;
+
+ case 0x048: // fmr (Floating Move Register, PPC32 p410)
+ DIP("fmr%s fr%u,fr%u\n", flag_rC ? "." : "", frD_addr, frB_addr);
+ assign( frD, mkexpr(frB) );
+ break;
+
+ case 0x088: // fnabs (Floating Negative Absolute Value, PPC32 p415)
+ DIP("fnabs%s fr%u,fr%u\n", flag_rC ? "." : "", frD_addr, frB_addr);
+ assign( frD, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr(frB) )));
+ break;
+
+ case 0x108: // fabs (Floating Absolute Value, PPC32 p399)
+ DIP("fabs%s fr%u,fr%u\n", flag_rC ? "." : "", frD_addr, frB_addr);
+ assign( frD, unop( Iop_AbsF64, mkexpr(frB) ));
+ break;
+
+ default:
+ vex_printf("dis_fp_move(PPC32)(opc2)\n");
+ return False;
}
putFReg( frD_addr, mkexpr(frD) );
@@ -4811,7 +5704,7 @@
//zz return False;
//zz }
//zz DIP("mtfsb1%s crb%d \n", flag_rC ? "." : "", crbD);
-//zz putSPR_masked( PPC32_SPR_FPSCR, mkU32(1<<(31-crbD)), 1<<(31-crbD) );
+//zz putGST_masked( PPC_GST_FPSCR, mkU32(1<<(31-crbD)), 1<<(31-crbD) );
//zz break;
//zz }
//zz
@@ -4828,8 +5721,8 @@
//zz return False;
//zz }
//zz DIP("mcrfs crf%d,crf%d\n", crfD, crfS);
-//zz assign( tmp, getSPR_field( PPC32_SPR_FPSCR, crfS ) );
-//zz putSPR_field( PPC32_SPR_CR, mkexpr(tmp), crfD );
+//zz assign( tmp, getGST_field( PPC_GST_FPSCR, crfS ) );
+//zz putGST_field( PPC_GST_CR, mkexpr(tmp), crfD );
//zz break;
//zz }
@@ -4843,7 +5736,7 @@
return False;
}
DIP("mtfsb0%s crb%d\n", flag_rC ? "." : "", crbD);
- putSPR_masked( PPC32_SPR_FPSCR, mkU32(0), 1<<(31-crbD) );
+ putGST_masked( PPC_GST_FPSCR, mkU32(0), 1<<(31-crbD) );
break;
}
@@ -4858,7 +5751,7 @@
return False;
}
DIP("mtfsfi%s crf%d,%d\n", flag_rC ? "." : "", crfD, IMM);
- putSPR_field( PPC32_SPR_FPSCR, mkU32(IMM), crfD );
+ putGST_field( PPC_GST_FPSCR, mkU32(IMM), crfD );
break;
}
@@ -4870,10 +5763,10 @@
vex_printf("dis_fp_scr(PPC32)(instr,mffs)\n");
return False;
}
- DIP("mffs%s fr%d\n", flag_rC ? "." : "", frD_addr);
+ DIP("mffs%s fr%u\n", flag_rC ? "." : "", frD_addr);
putFReg( frD_addr, unop( Iop_ReinterpI64asF64,
unop( Iop_32Uto64,
- getSPR_masked( PPC32_SPR_FPSCR, 0x3 ) )));
+ getGST_masked( PPC_GST_FPSCR, 0x3 ) )));
break;
}
@@ -4890,7 +5783,7 @@
vex_printf("dis_fp_scr(PPC32)(instr,mtfsf)\n");
return False;
}
- DIP("mtfsf%s %d,fr%d\n", flag_rC ? "." : "", FM, frB_addr);
+ DIP("mtfsf%s %d,fr%u\n", flag_rC ? "." : "", FM, frB_addr);
assign( frB, getFReg(frB_addr));
assign( rB_32, unop( Iop_64to32,
unop( Iop_ReinterpF64asI64, mkexpr(frB) )));
@@ -4901,7 +5794,7 @@
mask |= 0xF << (7-i);
}
}
- putSPR_masked( PPC32_SPR_FPSCR, mkexpr(rB_32), mask );
+ putGST_masked( PPC_GST_FPSCR, mkexpr(rB_32), mask );
break;
}
@@ -4941,12 +5834,12 @@
switch (opc2) {
case 0x156: // dst (Data Stream Touch, AV p115)
- DIP("dst%s r%d,r%d,%d\n", flag_T ? "t" : "", rA_addr, rB_addr, STRM);
+ DIP("dst%s r%u,r%u,%d\n", flag_T ? "t" : "", rA_addr, rB_addr, STRM);
DIP(" => not implemented\n");
return False;
case 0x176: // dstst (Data Stream Touch for Store, AV p117)
- DIP("dstst%s r%d,r%d,%d\n", flag_T ? "t" : "", rA_addr, rB_addr, STRM);
+ DIP("dstst%s r%u,r%u,%d\n", flag_T ? "t" : "", rA_addr, rB_addr, STRM);
DIP(" => not implemented\n");
return False;
@@ -4995,7 +5888,7 @@
return False;
}
DIP("mfvscr v%d\n", vD_addr);
- putVReg( vD_addr, unop(Iop_32UtoV128, getSPR( PPC32_SPR_VSCR )) );
+ putVReg( vD_addr, unop(Iop_32UtoV128, getGST( PPC_GST_VSCR )) );
break;
case 0x644: { // mtvscr (Move to VSCR, AV p130)
@@ -5006,7 +5899,7 @@
}
DIP("mtvscr v%d\n", vB_addr);
assign( vB, getVReg(vB_addr));
- putSPR( PPC32_SPR_VSCR, unop(Iop_V128to32, mkexpr(vB)) );
+ putGST( PPC_GST_VSCR, unop(Iop_V128to32, mkexpr(vB)) );
break;
}
default:
@@ -5029,15 +5922,22 @@
UInt opc2 = ifieldOPClo10(theInstr);
UChar b0 = ifieldBIT0(theInstr);
- IRTemp EA = newTemp(Ity_I32);
- IRTemp EA_aligned = newTemp(Ity_I32);
-
if (opc1 != 0x1F || b0 != 0) {
vex_printf("dis_av_load(PPC32)(instr)\n");
return False;
}
- assign( EA, ea_standard(rA_addr, rB_addr) );
+ IRTemp EA, addr_align16;
+ if (mode64) {
+ EA = newTemp(Ity_I64);
+ addr_align16 = newTemp(Ity_I64);
+ } else {
+ EA = newTemp(Ity_I32);
+ addr_align16 = newTemp(Ity_I32);
+ }
+
+ assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
+ assign( addr_align16, addr_align( mkexpr(EA), 16 ) );
switch (opc2) {
@@ -5052,7 +5952,7 @@
"ppc32g_dirtyhelper_LVS",
&ppc32g_dirtyhelper_LVS,
args );
- DIP("lvsl v%d,r%d,r%d\n", vD_addr, rA_addr, rB_addr);
+ DIP("lvsl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
/* declare guest state effects */
d->needsBBP = True;
d->nFxState = 1;
@@ -5075,7 +5975,7 @@
"ppc32g_dirtyhelper_LVS",
&ppc32g_dirtyhelper_LVS,
args );
- DIP("lvsr v%d,r%d,r%d\n", vD_addr, rA_addr, rB_addr);
+ DIP("lvsr v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
/* declare guest state effects */
d->needsBBP = True;
d->nFxState = 1;
@@ -5088,37 +5988,33 @@
break;
}
case 0x007: // lvebx (Load Vector Element Byte Indexed, AV p119)
- DIP("lvebx v%d,r%d,r%d\n", vD_addr, rA_addr, rB_addr);
+ DIP("lvebx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
/* loads addressed byte into vector[EA[0:3]
since all other destination bytes are undefined,
can simply load entire vector from 16-aligned EA */
- assign( EA_aligned, binop( Iop_And32, mkexpr(EA), mkU32(0xFFFFFFF0) ));
- putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_aligned)) );
+ putVReg( vD_addr, loadBE(Ity_V128, mkexpr(addr_align16)) );
break;
case 0x027: // lvehx (Load Vector Element Half Word Indexed, AV p121)
- DIP("lvehx v%d,r%d,r%d\n", vD_addr, rA_addr, rB_addr);
+ DIP("lvehx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
/* see note for lvebx */
- assign( EA_aligned, binop( Iop_And32, mkexpr(EA), mkU32(0xFFFFFFF0) ));
- putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_aligned)) );
+ putVReg( vD_addr, loadBE(Ity_V128, mkexpr(addr_align16)) );
break;
case 0x047: // lvewx (Load Vector Element Word Indexed, AV p122)
- DIP("lvewx v%d,r%d,r%d\n", vD_addr, rA_addr, rB_addr);
+ DIP("lvewx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
/* see note for lvebx */
- assign( EA_aligned, binop( Iop_And32, mkexpr(EA), mkU32(0xFFFFFFF0) ));
- putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_aligned)) );
+ putVReg( vD_addr, loadBE(Ity_V128, mkexpr(addr_align16)) );
break;
case 0x067: // lvx (Load Vector Indexed, AV p127)
- DIP("lvx v%d,r%d,r%d\n", vD_addr, rA_addr, rB_addr);
- assign( EA_aligned, binop( Iop_And32, mkexpr(EA), mkU32(0xFFFFFFF0) ));
- putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_aligned)) );
+ DIP("lvx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
+ putVReg( vD_addr, loadBE(Ity_V128, mkexpr(addr_align16)) );
break;
case 0x167: // lvxl (Load Vector Indexed LRU, AV p128)
// XXX: lvxl gives explicit control over cache block replacement
- DIP("lvxl v%d,r%d,r%d\n", vD_addr, rA_addr, rB_addr);
+ DIP("lvxl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
DIP(" => not implemented\n");
return False;
@@ -5142,23 +6038,29 @@
UInt opc2 = ifieldOPClo10(theInstr);
UChar b0 = ifieldBIT0(theInstr);
- IRTemp vS = newTemp(Ity_V128);
- IRTemp EA = newTemp(Ity_I32);
- IRTemp EA_aligned = newTemp(Ity_I32);
-
- assign( vS, getVReg(vS_addr));
- assign( EA, ea_standard(rA_addr, rB_addr) );
+ IRTemp vS = newTemp(Ity_V128);
+ IRTemp EA, addr_aligned;
+ if (mode64) {
+ EA = newTemp(Ity_I64);
+ addr_aligned = newTemp(Ity_I64);
+ } else {
+ EA = newTemp(Ity_I32);
+ addr_aligned = newTemp(Ity_I32);
+ }
if (opc1 != 0x1F || b0 != 0) {
vex_printf("dis_av_store(PPC32)(instr)\n");
return False;
}
+ assign( vS, getVReg(vS_addr));
+ assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
+
switch (opc2) {
case 0x087: { // stvebx (Store Vector Byte Indexed, AV p131)
IRTemp eb = newTemp(Ity_I8);
IRTemp idx = newTemp(Ity_I8);
- DIP("stvebx v%d,r%d,r%d\n", vS_addr, rA_addr, rB_addr);
+ DIP("stvebx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
assign( eb, binop(Iop_And8, mkU8(0xF),
unop(Iop_32to8, mkexpr(EA) )) );
assign( idx, binop(Iop_Shl8, binop(Iop_Sub8, mkU8(15), mkexpr(eb)),
@@ -5171,13 +6073,13 @@
case 0x0A7: { // stvehx (Store Vector Half Word Indexed, AV p132)
IRTemp eb = newTemp(Ity_I8);
IRTemp idx = newTemp(Ity_I8);
- DIP("stvehx v%d,r%d,r%d\n", vS_addr, rA_addr, rB_addr);
- assign( EA_aligned, binop( Iop_And32, mkexpr(EA), mkU32(0xFFFFFFFE) ));
+ DIP("stvehx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
+ assign( addr_aligned, addr_align( mkexpr(EA), 2 ) );
assign( eb, binop(Iop_And8, mkU8(0xF),
- unop(Iop_32to8, mkexpr(EA_aligned) )) );
+ unop(Iop_32to8, mkexpr(addr_aligned) )) );
assign( idx, binop(Iop_Shl8, binop(Iop_Sub8, mkU8(14), mkexpr(eb)),
mkU8(3)) );
- storeBE( mkexpr(EA_aligned),
+ storeBE( mkexpr(addr_aligned),
unop(Iop_32to16, unop(Iop_V128to32,
binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
break;
@@ -5185,32 +6087,30 @@
case 0x0C7: { // stvewx (Store Vector Word Indexed, AV p133)
IRTemp eb = newTemp(Ity_I8);
IRTemp idx = newTemp(Ity_I8);
- DIP("stvewx v%d,r%d,r%d\n", vS_addr, rA_addr, rB_addr);
- assign( EA_aligned, binop( Iop_And32, mkexpr(EA), mkU32(0xFFFFFFFC) ));
+ DIP("stvewx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
+ assign( addr_aligned, addr_align( mkexpr(EA), 4 ) );
assign( eb, binop(Iop_And8, mkU8(0xF),
- unop(Iop_32to8, mkexpr(EA_aligned) )) );
+ unop(Iop_32to8, mkexpr(addr_aligned) )) );
assign( idx, binop(Iop_Shl8, binop(Iop_Sub8, mkU8(12), mkexpr(eb)),
mkU8(3)) );
- storeBE( mkexpr(EA_aligned),
+ storeBE( mkexpr(addr_aligned),
unop(Iop_V128to32,
binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx))) );
break;
}
case 0x0E7: // stvx (Store Vector Indexed, AV p134)
- DIP("stvx v%d,r%d,r%d\n", vS_addr, rA_addr, rB_addr);
- assign( EA_aligned, binop( Iop_And32, mkexpr(EA), mkU32(0xFFFFFFF0) ));
- storeBE( mkexpr(EA_aligned), mkexpr(vS) );
+ DIP("stvx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
+ storeBE( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
break;
case 0x1E7: // stvxl (Store Vector Indexed LRU, AV p135)
// XXX: stvxl can give explicit control over cache block replacement
- DIP("stvxl v%d,r%d,r%d\n", vS_addr, rA_addr, rB_addr);
+ DIP("stvxl v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
DIP(" => not implemented\n");
return False;
-// EA_aligned = EA & 0xFFFF_FFF0;
-// STORE(vS, 16, EA);
+// STORE(vS, 16, addr_align( mkexpr(EA), 16 ));
default:
vex_printf("dis_av_store(PPC32)(opc2)\n");
@@ -6942,6 +7842,7 @@
UInt opc2;
DisResult dres;
UInt theInstr;
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
/* What insn variants are we supporting today? */
Bool allow_FP = archinfo->subarch == VexSubArchPPC32_FI
@@ -6950,7 +7851,7 @@
Bool allow_VMX = archinfo->subarch == VexSubArchPPC32_VFI;
/* The running delta */
- Int delta = (Int)delta64;
+ Long delta = (Long)mkSizedAddr(ty, (ULong)delta64);
/* Set result defaults. */
dres.whatNext = Dis_Continue;
@@ -6962,11 +7863,15 @@
and have done. */
theInstr = getUIntBigendianly( (UChar*)(&guest_code[delta]) );
- DIP("\t0x%x: ", guest_CIA_curr_instr);
+ if (mode64) {
+ DIP("\t0x%llx: ", guest_CIA_curr_instr);
+ } else {
+ DIP("\t0x%x: ", (Addr32)guest_CIA_curr_instr);
+ }
/* We may be asked to update the guest CIA before going further. */
if (put_IP)
- putSPR( PPC32_SPR_CIA, mkU32(guest_CIA_curr_instr) );
+ putGST( PPC_GST_CIA, mkSizedImm(ty, guest_CIA_curr_instr) );
/* Spot the client-request magic sequence. */
// Essentially a v. unlikely sequence of noops that we can catch
@@ -6976,7 +7881,7 @@
/* Spot this:
0x7C03D808 tw 0,3,27 => trap word if (0) => nop
0x5400E800 rlwinm 0,0,29,0,0 => r0 = rotl(r0,29)
- 0x54001800 rlwinm 0,0,3,0,0 => r0 = rotl(r0,3)
+ 0x54001800 rlwinm 0,0, 3,0,0 => r0 = rotl(r0, 3)
0x54006800 rlwinm 0,0,13,0,0 => r0 = rotl(r0,13)
0x54009800 rlwinm 0,0,19,0,0 => r0 = rotl(r0,19)
0x60000000 nop
@@ -6991,7 +7896,7 @@
dres.len = 24;
delta += 24;
- irbb->next = mkU32(guest_CIA_bbstart+delta);
+ irbb->next = mkSizedImm( ty, guest_CIA_bbstart + delta );
irbb->jumpkind = Ijk_ClientReq;
dres.whatNext = Dis_StopHere;
goto decode_success;
@@ -7078,20 +7983,20 @@
opc2 = IFIELD(theInstr, 1, 5);
switch (opc2) {
- /* Floating Point Arith Instructions */
- case 0x12: case 0x14: case 0x15: // fdivs, fsubs, fadds
- case 0x16: case 0x18: case 0x19: // fsqrts, fres, fmuls
- if (dis_fp_arith(theInstr)) goto decode_success;
- goto decode_failure;
-
- /* Floating Point Mult-Add Instructions */
- case 0x1C: case 0x1D: case 0x1E: // fmsubs, fmadds, fnmsubs
- case 0x1F: // fnmadds
- if (dis_fp_multadd(theInstr)) goto decode_success;
- goto decode_failure;
-
- default:
- goto decode_failure;
+ /* Floating Point Arith Instructions */
+ case 0x12: case 0x14: case 0x15: // fdivs, fsubs, fadds
+ case 0x16: case 0x18: case 0x19: // fsqrts, fres, fmuls
+ if (dis_fp_arith(theInstr)) goto decode_success;
+ goto decode_failure;
+
+ /* Floating Point Mult-Add Instructions */
+ case 0x1C: case 0x1D: case 0x1E: // fmsubs, fmadds, fnmsubs
+ case 0x1F: // fnmadds
+ if (dis_fp_multadd(theInstr)) goto decode_success;
+ goto decode_failure;
+
+ default:
+ goto decode_failure;
}
break;
@@ -7102,82 +8007,82 @@
opc2 = IFIELD(theInstr, 1, 5);
switch (opc2) {
- /* Floating Point Arith Instructions */
- case 0x12: case 0x14: case 0x15: // fdiv, fsub, fadd
- case 0x16: case 0x17: case 0x19: // fsqrt, fsel, fmul
- case 0x1A: // frsqrte
- if (dis_fp_arith(theInstr)) goto decode_success;
- goto decode_failure;
-
- /* Floating Point Mult-Add Instructions */
- case 0x1C: case 0x1D: case 0x1E: // fmsub, fmadd, fnmsub
- case 0x1F: // fnmadd
- if (dis_fp_multadd(theInstr)) goto decode_success;
- goto decode_failure;
+ /* Floating Point Arith Instructions */
+ case 0x12: case 0x14: case 0x15: // fdiv, fsub, fadd
+ case 0x16: case 0x17: case 0x19: // fsqrt, fsel, fmul
+ case 0x1A: // frsqrte
+ if (dis_fp_arith(theInstr)) goto decode_success;
+ goto decode_failure;
- default:
- break; // Fall through
+ /* Floating Point Mult-Add Instructions */
+ case 0x1C: case 0x1D: case 0x1E: // fmsub, fmadd, fnmsub
+ case 0x1F: // fnmadd
+ if (dis_fp_multadd(theInstr)) goto decode_success;
+ goto decode_failure;
+
+ default:
+ break; // Fall through
}
opc2 = IFIELD(theInstr, 1, 10);
switch (opc2) {
- /* Floating Point Compare Instructions */
- case 0x000: // fcmpu
- case 0x020: // fcmpo
- if (dis_fp_cmp(theInstr)) goto decode_success;
- goto decode_failure;
+ /* Floating Point Compare Instructions */
+ case 0x000: // fcmpu
+ case 0x020: // fcmpo
+ if (dis_fp_cmp(theInstr)) goto decode_success;
+ goto decode_failure;
- /* Floating Point Rounding/Conversion Instructions */
- case 0x00C: // frsp
- case 0x00E: // fctiw
- case 0x00F: // fctiwz
- if (dis_fp_round(theInstr)) goto decode_success;
- goto decode_failure;
+ /* Floating Point Rounding/Conversion Instructions */
+ case 0x00C: // frsp
+ case 0x00E: // fctiw
+ case 0x00F: // fctiwz
+ if (dis_fp_round(theInstr)) goto decode_success;
+ goto decode_failure;
+
+ /* Floating Point Move Instructions */
+ case 0x028: // fneg
+ case 0x048: // fmr
+ case 0x088: // fnabs
+ case 0x108: // fabs
+ if (dis_fp_move( theInstr )) goto decode_success;
+ goto decode_failure;
- /* Floating Point Move Instructions */
- case 0x028: // fneg
- case 0x048: // fmr
- case 0x088: // fnabs
- case 0x108: // fabs
- if (dis_fp_move( theInstr )) goto decode_success;
- goto decode_failure;
-
-//zz /* Floating Point Status/Control Register Instructions */
+ /* Floating Point Status/Control Register Instructions */
//zz case 0x026: // mtfsb1
//zz case 0x040: // mcrfs
- case 0x046: // mtfsb0
- case 0x086: // mtfsfi
- case 0x247: // mffs
- case 0x2C7: // mtfsf
- if (dis_fp_scr( theInstr )) goto decode_success;
- goto decode_failure;
- default:
- goto decode_failure;
+ case 0x046: // mtfsb0
+ case 0x086: // mtfsfi
+ case 0x247: // mffs
+ case 0x2C7: // mtfsf
+ if (dis_fp_scr( theInstr )) goto decode_success;
+ goto decode_failure;
+ default:
+ goto decode_failure;
}
break;
-
+
case 0x13:
switch (opc2) {
- /* Condition Register Logical Instructions */
- case 0x101: case 0x081: case 0x121: // crand, crandc, creqv
- case 0x0E1: case 0x021: case 0x1C1: // crnand, crnor, cror
- case 0x1A1: case 0x0C1: case 0x000: // crorc, crxor, mcrf
- if (dis_cond_logic( theInstr )) goto decode_success;
- goto decode_failure;
-
- /* Branch Instructions */
- case 0x210: case 0x010: // bcctr, bclr
- if (dis_branch(theInstr, &dres, resteerOkFn)) goto decode_success;
- goto decode_failure;
-
- /* Memory Synchronization Instructions */
- case 0x096: // isync
- if (dis_memsync( theInstr )) goto decode_success;
- goto decode_failure;
+ /* Condition Register Logical Instructions */
+ case 0x101: case 0x081: case 0x121: // crand, crandc, creqv
+ case 0x0E1: case 0x021: case 0x1C1: // crnand, crnor, cror
+ case 0x1A1: case 0x0C1: case 0x000: // crorc, crxor, mcrf
+ if (dis_cond_logic( theInstr )) goto decode_success;
+ goto decode_failure;
- default:
- goto decode_failure;
+ /* Branch Instructions */
+ case 0x210: case 0x010: // bcctr, bclr
+ if (dis_branch(theInstr, &dres, resteerOkFn)) goto decode_success;
+ goto decode_failure;
+
+ /* Memory Synchronization Instructions */
+ case 0x096: // isync
+ if (dis_memsync( theInstr )) goto decode_success;
+ goto decode_failure;
+
+ default:
+ goto decode_failure;
}
break;
@@ -7188,17 +8093,17 @@
opc2 = IFIELD(theInstr, 1, 9);
switch (opc2) {
- /* Integer Arithmetic Instructions */
- case 0x10A: case 0x00A: case 0x08A: // add, addc, adde
- case 0x0EA: case 0x0CA: case 0x1EB: // addme, addze, divw
- case 0x1CB: case 0x04B: case 0x00B: // divwu, mulhw, mulhwu
- case 0x0EB: case 0x068: case 0x028: // mullw, neg, subf
- case 0x008: case 0x088: case 0x0E8: // subfc, subfe, subfme
- case 0x0C8: // subfze
- if (dis_int_arith( theInstr )) goto decode_success;
- goto decode_failure;
- default:
- break; // Fall through...
+ /* Integer Arithmetic Instructions */
+ case 0x10A: case 0x00A: case 0x08A: // add, addc, adde
+ case 0x0EA: case 0x0CA: case 0x1EB: // addme, addze, divw
+ case 0x1CB: case 0x04B: case 0x00B: // divwu, mulhw, mulhwu
+ case 0x0EB: case 0x068: case 0x028: // mullw, neg, subf
+ case 0x008: case 0x088: case 0x0E8: // subfc, subfe, subfme
+ case 0x0C8: // subfze
+ if (dis_int_arith( theInstr )) goto decode_success;
+ goto decode_failure;
+ default:
+ break; // Fall through...
}
/* All remaining opcodes use full 10 bits. */
@@ -7250,9 +8155,9 @@
Bool ok = dis_int_ldst_str( theInstr, &stopHere );
if (!ok) goto decode_failure;
if (stopHere) {
- irbb->next = mkU32(guest_CIA_curr_instr+4);
+ irbb->next = mkSizedImm(ty, nextInsnAddr());
irbb->jumpkind = Ijk_Boring;
- dres.whatNext = Dis_StopHere;
+ dres.whatNext = Dis_StopHere;
}
goto decode_success;
}
@@ -7488,7 +8393,7 @@
vex_printf(" primary %d(0x%x), secondary %u(0x%x)\n",
opc1, opc1, opc2, opc2);
-#if PPC32_TOIR_DEBUG
+#if PPC_TOIR_DEBUG
vex_printf("disInstr(ppc32): instr: ");
vex_printf_binary( theInstr, 32, True );
vex_printf("\n");
@@ -7508,11 +8413,11 @@
CIA should be up-to-date since it made so at the start of each
insn, but nevertheless be paranoid and update it again right
now. */
- putSPR( PPC32_SPR_CIA, mkU32(guest_CIA_curr_instr) );
- irbb->next = mkU32(guest_CIA_curr_instr);
+ putGST( PPC_GST_CIA, mkSizedImm(ty, guest_CIA_curr_instr) );
+ irbb->next = mkSizedImm(ty, guest_CIA_curr_instr);
irbb->jumpkind = Ijk_NoDecode;
- dres.whatNext = Dis_StopHere;
- dres.len = 0;
+ dres.whatNext = Dis_StopHere;
+ dres.len = 0;
return dres;
} /* switch (opc) for the main (primary) opcode switch. */
@@ -7546,13 +8451,15 @@
Bool host_bigendian_IN )
{
DisResult dres;
+ IRType ty = mode64 ? Ity_I64 : Ity_I32;
/* Set globals (see top of this file) */
guest_code = guest_code_IN;
irbb = irbb_IN;
host_is_bigendian = host_bigendian_IN;
- guest_CIA_curr_instr = (Addr32)guest_IP;
- guest_CIA_bbstart = (Addr32)toUInt(guest_IP - delta);
+
+ guest_CIA_curr_instr = mkSizedAddr(ty, guest_IP);
+ guest_CIA_bbstart = mkSizedAddr(ty, guest_IP - delta);
dres = disInstr_PPC32_WRK ( put_IP, resteerOkFn,
delta, archinfo );
diff --git a/pub/libvex.h b/pub/libvex.h
index 5541dbd..e5f605e 100644
--- a/pub/libvex.h
+++ b/pub/libvex.h
@@ -66,7 +66,8 @@
VexArchX86,
VexArchAMD64,
VexArchARM,
- VexArchPPC32
+ VexArchPPC32,
+ VexArchPPC64
}
VexArch;
@@ -80,7 +81,9 @@
VexSubArchARM_v4, /* ARM version 4 */
VexSubArchPPC32_I, /* 32-bit PowerPC, no FP, no Altivec */
VexSubArchPPC32_FI, /* 32-bit PowerPC, with FP but no Altivec */
- VexSubArchPPC32_VFI /* 32-bit PowerPC, with FP and Altivec */
+ VexSubArchPPC32_VFI, /* 32-bit PowerPC, with FP and Altivec */
+ VexSubArchPPC64_FI, /* 64-bit PowerPC, with FP but no Altivec */
+ VexSubArchPPC64_VFI /* 64-bit PowerPC, with FP and Altivec */
}
VexSubArch;
@@ -98,7 +101,7 @@
struct {
/* This is the only mandatory field. */
VexSubArch subarch;
- /* PPC32 only: size of cache line */
+ /* PPC32/PPC64 only: size of cache line */
Int ppc32_cache_line_szB;
}
VexArchInfo;
diff --git a/pub/libvex_basictypes.h b/pub/libvex_basictypes.h
index c831477..465262e 100644
--- a/pub/libvex_basictypes.h
+++ b/pub/libvex_basictypes.h
@@ -139,8 +139,9 @@
# define VEX_HOST_WORDSIZE 8
#elif defined(__i386__)
# define VEX_HOST_WORDSIZE 4
-#elif defined (__powerpc__)
- /* need to distinguish ppc32 from ppc64 */
+#elif defined(__powerpc__) && defined(__powerpc64__)
+# define VEX_HOST_WORDSIZE 8
+#elif defined(__powerpc__) && !defined(__powerpc64__)
# define VEX_HOST_WORDSIZE 4
#else
# error "Vex: Fatal: Can't establish the host architecture"