|
From: <sv...@va...> - 2014-08-07 23:25:46
|
Author: carll
Date: Thu Aug 7 23:25:23 2014
New Revision: 2914
Log:
This commit is for Bugzilla 334834. The Bugzilla contains patch 2 of 3
to add PPC64 LE support. The other two patches can be found in Bugzillas
334384 and 334836.
POWER PC, add the functional Little Endian support, patch 2 VEX part
The IBM POWER processor now supports both Big Endian and Little Endian.
The ABI for Little Endian also changes. Specifically, the function
descriptor is not used, the stack size changed, accessing the TOC
changed. Functions now have a local and a global entry point. Register
r2 contains the TOC for local calls and register r12 contains the TOC
for global calls. This patch makes the functional changes to the
Valgrind tool. The patch makes the changes needed for the
none/tests/ppc32 and none/tests/ppc64 Makefile.am. A number of the
ppc specific tests have Endian dependencies that are not fixed in
this patch. They are fixed in the next patch.
Per Julian's comments renamed coregrind/m_dispatch/dispatch-ppc64-linux.S
to coregrind/m_dispatch/dispatch-ppc64be-linux.S Created new file for LE
coregrind/m_dispatch/dispatch-ppc64le-linux.S. The same was done for
coregrind/m_syswrap/syscall-ppc-linux.S.
Signed-off-by: Carl Love <ca...@us...>
Modified:
trunk/priv/guest_ppc_defs.h
trunk/priv/guest_ppc_helpers.c
trunk/priv/guest_ppc_toIR.c
trunk/priv/host_ppc_defs.c
trunk/priv/host_ppc_isel.c
trunk/priv/main_main.c
Modified: trunk/priv/guest_ppc_defs.h
==============================================================================
--- trunk/priv/guest_ppc_defs.h (original)
+++ trunk/priv/guest_ppc_defs.h Thu Aug 7 23:25:23 2014
@@ -161,7 +161,8 @@
extern void ppc64g_dirtyhelper_LVS ( VexGuestPPC64State* gst,
UInt vD_idx, UInt sh,
- UInt shift_right );
+ UInt shift_right,
+ UInt endness );
#endif /* ndef __VEX_GUEST_PPC_DEFS_H */
Modified: trunk/priv/guest_ppc_helpers.c
==============================================================================
--- trunk/priv/guest_ppc_helpers.c (original)
+++ trunk/priv/guest_ppc_helpers.c Thu Aug 7 23:25:23 2014
@@ -153,10 +153,12 @@
/* CALLED FROM GENERATED CODE */
/* DIRTY HELPER (reads guest state, writes guest mem) */
void ppc64g_dirtyhelper_LVS ( VexGuestPPC64State* gst,
- UInt vD_off, UInt sh, UInt shift_right )
+ UInt vD_off, UInt sh, UInt shift_right,
+ UInt endness )
{
UChar ref[32];
ULong i;
+ Int k;
/* ref[] used to be a static const array, but this doesn't work on
ppc64 because VEX doesn't load the TOC pointer for the call here,
and so we wind up picking up some totally random other data.
@@ -179,10 +181,19 @@
pU128_src = (U128*)&ref[sh];
pU128_dst = (U128*)( ((UChar*)gst) + vD_off );
- (*pU128_dst)[0] = (*pU128_src)[0];
- (*pU128_dst)[1] = (*pU128_src)[1];
- (*pU128_dst)[2] = (*pU128_src)[2];
- (*pU128_dst)[3] = (*pU128_src)[3];
+ if ((0x1 & endness) == 0x0) {
+ /* Little endian */
+ unsigned char *srcp, *dstp;
+ srcp = (unsigned char *)pU128_src;
+ dstp = (unsigned char *)pU128_dst;
+ for (k = 15; k >= 0; k--, srcp++)
+ dstp[k] = *srcp;
+ } else {
+ (*pU128_dst)[0] = (*pU128_src)[0];
+ (*pU128_dst)[1] = (*pU128_src)[1];
+ (*pU128_dst)[2] = (*pU128_src)[2];
+ (*pU128_dst)[3] = (*pU128_src)[3];
+ }
}
Modified: trunk/priv/guest_ppc_toIR.c
==============================================================================
--- trunk/priv/guest_ppc_toIR.c (original)
+++ trunk/priv/guest_ppc_toIR.c Thu Aug 7 23:25:23 2014
@@ -97,7 +97,8 @@
7C210B78 (or 1,1,1) %R3 = client_request ( %R4 )
7C421378 (or 2,2,2) %R3 = guest_NRADDR
- 7C631B78 (or 3,3,3) branch-and-link-to-noredir %R11
+ 7C631B78 (or 3,3,3) branch-and-link-to-noredir %R11 Big endian
+ 7C631B78 (or 3,3,3) branch-and-link-to-noredir %R12 Little endian
7C842378 (or 4,4,4) %R3 = guest_NRADDR_GPR2
7CA52B78 (or 5,5,5) IR injection
@@ -107,7 +108,55 @@
fragments designed for Valgrind to catch.
*/
-
+/* Little Endian notes */
+/*
+ * Vector operations in little Endian mode behave in non-obvious ways at times.
+ * Below is an attempt at explaining this.
+ *
+ * LE/BE vector example
+ * With a vector of unsigned ints declared as follows:
+ * vector unsigned int vec_inA =
+ { 0x11111111, 0x22222222, 0x33333333, 0x44444444 };
+ * The '0x11111111' word is word zero in both LE and BE format. But the
+ * loaded vector register will have word zero on the far left in BE mode and
+ * on the far right in LE mode. The lvx and stvx instructions work naturally
+ * for whatever endianness is in effect. For example, in LE mode, the stvx
+ * stores word zero (far right word) of the vector at the lowest memory
+ * address of the EA; in BE mode, stvx still stores word zero at the lowest
+ * memory address, but with word zero interpreted as the one at the far left
+ * of the register.
+ *
+ * The lxvd2x and stxvd2x instructions are not so well suited for LE mode.
+ * When the compiler generates an lxvd2x instruction to load the
+ * above-declared vector of unsigned integers, it loads the vector as two
+ * double words, but they are in BE word-wise format. To put the vector in
+ * the right order for LE, the compiler also generates an xxswapd after the
+ * load, which puts it in proper LE format. Similarly, the stxvd2x
+ * instruction has a BE bias, storing the vector in BE word-wise format. But
+ * the compiler also generates an xxswapd prior to the store, thus ensuring
+ * the vector is stored in memory in the correct LE order.
+ *
+ * Vector-flavored Iops, such Iop_V128Hito64, reference the hi and lo parts
+ * of a double words and words within a vector. Because of the reverse order
+ * of numbering for LE as described above, the high part refers to word 1 in
+ * LE format. When input data is saved to a guest state vector register
+ * (e.g., via Iop_64HLtoV128), it is first saved to memory and then the
+ * register is loaded via PPCInstr_AvLdSt, which does an lvx instruction.
+ * The saving of the data to memory must be done in proper LE order. For the
+ * inverse operation of extracting data from a vector register (e.g.,
+ * Iop_V128Hito64), the register is first saved (by PPCInstr_AvLdSt resulting
+ * in stvx), and then integer registers are loaded from the memory location
+ * from where the vector register was saved. Again, this must be done in
+ * proper LE order. So for these various vector Iops, we have LE-specific
+ * code in host_ppc_isel.c
+ *
+ * Another unique behavior of vectors in LE mode is with the vector scalar
+ * (VSX) operations that operate on "double word 0" of the source register,
+ * storing the result in "double word 0" of the output vector register. For
+ * these operations, "double word 0" is interpreted as "high half of the
+ * register" (i.e, the part on the left side).
+ *
+ */
/* Translates PPC32/64 code to IR. */
/* References
@@ -143,7 +192,6 @@
#include "guest_generic_bb_to_IR.h"
#include "guest_ppc_defs.h"
-
/*------------------------------------------------------------*/
/*--- Globals ---*/
/*------------------------------------------------------------*/
@@ -503,15 +551,22 @@
return (ULong)((((Long)x) << 32) >> 32);
}
-/* Do a big-endian load of a 32-bit word, regardless of the endianness
+/* Do a proper-endian load of a 32-bit word, regardless of the endianness
of the underlying host. */
-static UInt getUIntBigendianly ( UChar* p )
+static UInt getUIntPPCendianly ( UChar* p )
{
UInt w = 0;
- w = (w << 8) | p[0];
- w = (w << 8) | p[1];
- w = (w << 8) | p[2];
- w = (w << 8) | p[3];
+ if (host_endness == VexEndnessBE) {
+ w = (w << 8) | p[0];
+ w = (w << 8) | p[1];
+ w = (w << 8) | p[2];
+ w = (w << 8) | p[3];
+ } else {
+ w = (w << 8) | p[3];
+ w = (w << 8) | p[2];
+ w = (w << 8) | p[1];
+ w = (w << 8) | p[0];
+ }
return w;
}
@@ -526,11 +581,15 @@
}
/* This generates a normal (non store-conditional) store. */
-static void storeBE ( IRExpr* addr, IRExpr* data )
+static void store ( IRExpr* addr, IRExpr* data )
{
IRType tyA = typeOfIRExpr(irsb->tyenv, addr);
vassert(tyA == Ity_I32 || tyA == Ity_I64);
- stmt( IRStmt_Store(Iend_BE, addr, data) );
+
+ if (host_endness == VexEndnessBE)
+ stmt( IRStmt_Store(Iend_BE, addr, data) );
+ else
+ stmt( IRStmt_Store(Iend_LE, addr, data) );
}
static IRExpr* unop ( IROp op, IRExpr* a )
@@ -586,9 +645,21 @@
}
/* This generates a normal (non load-linked) load. */
-static IRExpr* loadBE ( IRType ty, IRExpr* addr )
+static IRExpr* load ( IRType ty, IRExpr* addr )
{
- return IRExpr_Load(Iend_BE, ty, addr);
+ if (host_endness == VexEndnessBE)
+ return IRExpr_Load(Iend_BE, ty, addr);
+ else
+ return IRExpr_Load(Iend_LE, ty, addr);
+}
+
+static IRStmt* stmt_load ( IRTemp result,
+ IRExpr* addr, IRExpr* storedata )
+{
+ if (host_endness == VexEndnessBE)
+ return IRStmt_LLSC(Iend_BE, result, addr, storedata);
+ else
+ return IRStmt_LLSC(Iend_LE, result, addr, storedata);
}
static IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 )
@@ -1039,7 +1110,6 @@
// jrs: probably not necessary; only matters if we reference sub-parts
// of the ppc registers, but that isn't the case
// later: this might affect Altivec though?
- vassert(host_endness == VexEndnessBE);
switch (archreg) {
case 0: return offsetofPPCGuestState(guest_GPR0);
@@ -1101,40 +1171,78 @@
{
vassert(archreg < 32);
- switch (archreg) {
- case 0: return offsetofPPCGuestState(guest_VSR0);
- case 1: return offsetofPPCGuestState(guest_VSR1);
- case 2: return offsetofPPCGuestState(guest_VSR2);
- case 3: return offsetofPPCGuestState(guest_VSR3);
- case 4: return offsetofPPCGuestState(guest_VSR4);
- case 5: return offsetofPPCGuestState(guest_VSR5);
- case 6: return offsetofPPCGuestState(guest_VSR6);
- case 7: return offsetofPPCGuestState(guest_VSR7);
- case 8: return offsetofPPCGuestState(guest_VSR8);
- case 9: return offsetofPPCGuestState(guest_VSR9);
- case 10: return offsetofPPCGuestState(guest_VSR10);
- case 11: return offsetofPPCGuestState(guest_VSR11);
- case 12: return offsetofPPCGuestState(guest_VSR12);
- case 13: return offsetofPPCGuestState(guest_VSR13);
- case 14: return offsetofPPCGuestState(guest_VSR14);
- case 15: return offsetofPPCGuestState(guest_VSR15);
- case 16: return offsetofPPCGuestState(guest_VSR16);
- case 17: return offsetofPPCGuestState(guest_VSR17);
- case 18: return offsetofPPCGuestState(guest_VSR18);
- case 19: return offsetofPPCGuestState(guest_VSR19);
- case 20: return offsetofPPCGuestState(guest_VSR20);
- case 21: return offsetofPPCGuestState(guest_VSR21);
- case 22: return offsetofPPCGuestState(guest_VSR22);
- case 23: return offsetofPPCGuestState(guest_VSR23);
- case 24: return offsetofPPCGuestState(guest_VSR24);
- case 25: return offsetofPPCGuestState(guest_VSR25);
- case 26: return offsetofPPCGuestState(guest_VSR26);
- case 27: return offsetofPPCGuestState(guest_VSR27);
- case 28: return offsetofPPCGuestState(guest_VSR28);
- case 29: return offsetofPPCGuestState(guest_VSR29);
- case 30: return offsetofPPCGuestState(guest_VSR30);
- case 31: return offsetofPPCGuestState(guest_VSR31);
- default: break;
+ if (host_endness == VexEndnessLE) {
+ switch (archreg) {
+ case 0: return offsetofPPCGuestState(guest_VSR0 + 8);
+ case 1: return offsetofPPCGuestState(guest_VSR1 + 8);
+ case 2: return offsetofPPCGuestState(guest_VSR2 + 8);
+ case 3: return offsetofPPCGuestState(guest_VSR3 + 8);
+ case 4: return offsetofPPCGuestState(guest_VSR4 + 8);
+ case 5: return offsetofPPCGuestState(guest_VSR5 + 8);
+ case 6: return offsetofPPCGuestState(guest_VSR6 + 8);
+ case 7: return offsetofPPCGuestState(guest_VSR7 + 8);
+ case 8: return offsetofPPCGuestState(guest_VSR8 + 8);
+ case 9: return offsetofPPCGuestState(guest_VSR9 + 8);
+ case 10: return offsetofPPCGuestState(guest_VSR10 + 8);
+ case 11: return offsetofPPCGuestState(guest_VSR11 + 8);
+ case 12: return offsetofPPCGuestState(guest_VSR12 + 8);
+ case 13: return offsetofPPCGuestState(guest_VSR13 + 8);
+ case 14: return offsetofPPCGuestState(guest_VSR14 + 8);
+ case 15: return offsetofPPCGuestState(guest_VSR15 + 8);
+ case 16: return offsetofPPCGuestState(guest_VSR16 + 8);
+ case 17: return offsetofPPCGuestState(guest_VSR17 + 8);
+ case 18: return offsetofPPCGuestState(guest_VSR18 + 8);
+ case 19: return offsetofPPCGuestState(guest_VSR19 + 8);
+ case 20: return offsetofPPCGuestState(guest_VSR20 + 8);
+ case 21: return offsetofPPCGuestState(guest_VSR21 + 8);
+ case 22: return offsetofPPCGuestState(guest_VSR22 + 8);
+ case 23: return offsetofPPCGuestState(guest_VSR23 + 8);
+ case 24: return offsetofPPCGuestState(guest_VSR24 + 8);
+ case 25: return offsetofPPCGuestState(guest_VSR25 + 8);
+ case 26: return offsetofPPCGuestState(guest_VSR26 + 8);
+ case 27: return offsetofPPCGuestState(guest_VSR27 + 8);
+ case 28: return offsetofPPCGuestState(guest_VSR28 + 8);
+ case 29: return offsetofPPCGuestState(guest_VSR29 + 8);
+ case 30: return offsetofPPCGuestState(guest_VSR30 + 8);
+ case 31: return offsetofPPCGuestState(guest_VSR31 + 8);
+ default: break;
+ }
+ } else {
+ switch (archreg) {
+ case 0: return offsetofPPCGuestState(guest_VSR0);
+ case 1: return offsetofPPCGuestState(guest_VSR1);
+ case 2: return offsetofPPCGuestState(guest_VSR2);
+ case 3: return offsetofPPCGuestState(guest_VSR3);
+ case 4: return offsetofPPCGuestState(guest_VSR4);
+ case 5: return offsetofPPCGuestState(guest_VSR5);
+ case 6: return offsetofPPCGuestState(guest_VSR6);
+ case 7: return offsetofPPCGuestState(guest_VSR7);
+ case 8: return offsetofPPCGuestState(guest_VSR8);
+ case 9: return offsetofPPCGuestState(guest_VSR9);
+ case 10: return offsetofPPCGuestState(guest_VSR10);
+ case 11: return offsetofPPCGuestState(guest_VSR11);
+ case 12: return offsetofPPCGuestState(guest_VSR12);
+ case 13: return offsetofPPCGuestState(guest_VSR13);
+ case 14: return offsetofPPCGuestState(guest_VSR14);
+ case 15: return offsetofPPCGuestState(guest_VSR15);
+ case 16: return offsetofPPCGuestState(guest_VSR16);
+ case 17: return offsetofPPCGuestState(guest_VSR17);
+ case 18: return offsetofPPCGuestState(guest_VSR18);
+ case 19: return offsetofPPCGuestState(guest_VSR19);
+ case 20: return offsetofPPCGuestState(guest_VSR20);
+ case 21: return offsetofPPCGuestState(guest_VSR21);
+ case 22: return offsetofPPCGuestState(guest_VSR22);
+ case 23: return offsetofPPCGuestState(guest_VSR23);
+ case 24: return offsetofPPCGuestState(guest_VSR24);
+ case 25: return offsetofPPCGuestState(guest_VSR25);
+ case 26: return offsetofPPCGuestState(guest_VSR26);
+ case 27: return offsetofPPCGuestState(guest_VSR27);
+ case 28: return offsetofPPCGuestState(guest_VSR28);
+ case 29: return offsetofPPCGuestState(guest_VSR29);
+ case 30: return offsetofPPCGuestState(guest_VSR30);
+ case 31: return offsetofPPCGuestState(guest_VSR31);
+ default: break;
+ }
}
vpanic("floatGuestRegOffset(ppc)"); /*notreached*/
}
@@ -4758,7 +4866,7 @@
switch (opc1) {
case 0x22: // lbz (Load B & Zero, PPC32 p433)
DIP("lbz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
- val = loadBE(Ity_I8, mkexpr(EA));
+ val = load(Ity_I8, mkexpr(EA));
putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
break;
@@ -4768,14 +4876,14 @@
return False;
}
DIP("lbzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
- val = loadBE(Ity_I8, mkexpr(EA));
+ val = load(Ity_I8, mkexpr(EA));
putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
putIReg( rA_addr, mkexpr(EA) );
break;
case 0x2A: // lha (Load HW Alg, PPC32 p445)
DIP("lha r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
- val = loadBE(Ity_I16, mkexpr(EA));
+ val = load(Ity_I16, mkexpr(EA));
putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
break;
@@ -4785,14 +4893,14 @@
return False;
}
DIP("lhau r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
- val = loadBE(Ity_I16, mkexpr(EA));
+ val = load(Ity_I16, mkexpr(EA));
putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
putIReg( rA_addr, mkexpr(EA) );
break;
case 0x28: // lhz (Load HW & Zero, PPC32 p450)
DIP("lhz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
- val = loadBE(Ity_I16, mkexpr(EA));
+ val = load(Ity_I16, mkexpr(EA));
putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
break;
@@ -4802,14 +4910,14 @@
return False;
}
DIP("lhzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
- val = loadBE(Ity_I16, mkexpr(EA));
+ val = load(Ity_I16, mkexpr(EA));
putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
putIReg( rA_addr, mkexpr(EA) );
break;
case 0x20: // lwz (Load W & Zero, PPC32 p460)
DIP("lwz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
- val = loadBE(Ity_I32, mkexpr(EA));
+ val = load(Ity_I32, mkexpr(EA));
putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
break;
@@ -4819,7 +4927,7 @@
return False;
}
DIP("lwzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
- val = loadBE(Ity_I32, mkexpr(EA));
+ val = load(Ity_I32, mkexpr(EA));
putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
putIReg( rA_addr, mkexpr(EA) );
break;
@@ -4838,14 +4946,14 @@
vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
return False;
}
- val = loadBE(Ity_I8, mkexpr(EA));
+ val = load(Ity_I8, mkexpr(EA));
putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
putIReg( rA_addr, mkexpr(EA) );
break;
case 0x057: // lbzx (Load B & Zero, Indexed, PPC32 p436)
DIP("lbzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
- val = loadBE(Ity_I8, mkexpr(EA));
+ val = load(Ity_I8, mkexpr(EA));
putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
break;
@@ -4855,14 +4963,14 @@
return False;
}
DIP("lhaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
- val = loadBE(Ity_I16, mkexpr(EA));
+ val = load(Ity_I16, mkexpr(EA));
putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
putIReg( rA_addr, mkexpr(EA) );
break;
case 0x157: // lhax (Load HW Alg, Indexed, PPC32 p448)
DIP("lhax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
- val = loadBE(Ity_I16, mkexpr(EA));
+ val = load(Ity_I16, mkexpr(EA));
putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
break;
@@ -4872,14 +4980,14 @@
return False;
}
DIP("lhzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
- val = loadBE(Ity_I16, mkexpr(EA));
+ val = load(Ity_I16, mkexpr(EA));
putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
putIReg( rA_addr, mkexpr(EA) );
break;
case 0x117: // lhzx (Load HW & Zero, Indexed, PPC32 p453)
DIP("lhzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
- val = loadBE(Ity_I16, mkexpr(EA));
+ val = load(Ity_I16, mkexpr(EA));
putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
break;
@@ -4889,14 +4997,14 @@
return False;
}
DIP("lwzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
- val = loadBE(Ity_I32, mkexpr(EA));
+ val = load(Ity_I32, mkexpr(EA));
putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
putIReg( rA_addr, mkexpr(EA) );
break;
case 0x017: // lwzx (Load W & Zero, Indexed, PPC32 p463)
DIP("lwzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
- val = loadBE(Ity_I32, mkexpr(EA));
+ val = load(Ity_I32, mkexpr(EA));
putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
break;
@@ -4908,13 +5016,13 @@
return False;
}
DIP("ldux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
- putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
+ putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
putIReg( rA_addr, mkexpr(EA) );
break;
case 0x015: // ldx (Load DWord, Indexed, PPC64 p476)
DIP("ldx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
- putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
+ putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
break;
case 0x175: // lwaux (Load W Alg, Update Indexed, PPC64 p501)
@@ -4924,14 +5032,14 @@
}
DIP("lwaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
putIReg( rD_addr,
- unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) );
+ unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
putIReg( rA_addr, mkexpr(EA) );
break;
case 0x155: // lwax (Load W Alg, Indexed, PPC64 p502)
DIP("lwax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
putIReg( rD_addr,
- unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) );
+ unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
break;
default:
@@ -4946,7 +5054,7 @@
switch ((b1<<1) | b0) {
case 0x0: // ld (Load DWord, PPC64 p472)
DIP("ld r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
- putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
+ putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
break;
case 0x1: // ldu (Load DWord, Update, PPC64 p474)
@@ -4955,14 +5063,14 @@
return False;
}
DIP("ldu r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
- putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
+ putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
putIReg( rA_addr, mkexpr(EA) );
break;
case 0x2: // lwa (Load Word Alg, PPC64 p499)
DIP("lwa r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
putIReg( rD_addr,
- unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) );
+ unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
break;
default:
@@ -4981,17 +5089,17 @@
*/
// trap if EA misaligned on 16 byte address
if (mode64) {
- assign(high, loadBE(ty, mkexpr( EA ) ) );
- assign(low, loadBE(ty, binop( Iop_Add64,
- mkexpr( EA ),
- mkU64( 8 ) ) ) );
+ assign(high, load(ty, mkexpr( EA ) ) );
+ assign(low, load(ty, binop( Iop_Add64,
+ mkexpr( EA ),
+ mkU64( 8 ) ) ) );
} else {
- assign(high, loadBE(ty, binop( Iop_Add32,
- mkexpr( EA ),
- mkU32( 4 ) ) ) );
- assign(low, loadBE(ty, binop( Iop_Add32,
- mkexpr( EA ),
- mkU32( 12 ) ) ) );
+ assign(high, load(ty, binop( Iop_Add32,
+ mkexpr( EA ),
+ mkU32( 4 ) ) ) );
+ assign(low, load(ty, binop( Iop_Add32,
+ mkexpr( EA ),
+ mkU32( 12 ) ) ) );
}
gen_SIGBUS_if_misaligned( EA, 16 );
putIReg( rD_addr, mkexpr( high) );
@@ -5046,7 +5154,7 @@
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), mkNarrowTo8(ty, mkexpr(rS)) );
+ store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
break;
case 0x27: // stbu (Store B, Update, PPC32 p510)
@@ -5056,12 +5164,12 @@
}
DIP("stbu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
putIReg( rA_addr, mkexpr(EA) );
- storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
+ store( mkexpr(EA), mkNarrowTo8(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), mkNarrowTo16(ty, mkexpr(rS)) );
+ store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
break;
case 0x2D: // sthu (Store HW, Update, PPC32 p524)
@@ -5071,12 +5179,12 @@
}
DIP("sthu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
putIReg( rA_addr, mkexpr(EA) );
- storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
+ store( mkexpr(EA), mkNarrowTo16(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), mkNarrowTo32(ty, mkexpr(rS)) );
+ store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
break;
case 0x25: // stwu (Store W, Update, PPC32 p534)
@@ -5086,7 +5194,7 @@
}
DIP("stwu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
putIReg( rA_addr, mkexpr(EA) );
- storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
+ store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
break;
/* X Form : all these use EA_indexed */
@@ -5104,12 +5212,12 @@
}
DIP("stbux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
putIReg( rA_addr, mkexpr(EA) );
- storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
+ store( mkexpr(EA), mkNarrowTo8(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), mkNarrowTo8(ty, mkexpr(rS)) );
+ store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
break;
case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525)
@@ -5119,12 +5227,12 @@
}
DIP("sthux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
putIReg( rA_addr, mkexpr(EA) );
- storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
+ store( mkexpr(EA), mkNarrowTo16(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), mkNarrowTo16(ty, mkexpr(rS)) );
+ store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
break;
case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535)
@@ -5134,12 +5242,12 @@
}
DIP("stwux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
putIReg( rA_addr, mkexpr(EA) );
- storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
+ store( mkexpr(EA), mkNarrowTo32(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), mkNarrowTo32(ty, mkexpr(rS)) );
+ store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
break;
@@ -5151,12 +5259,12 @@
}
DIP("stdux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
putIReg( rA_addr, mkexpr(EA) );
- storeBE( mkexpr(EA), mkexpr(rS) );
+ store( mkexpr(EA), mkexpr(rS) );
break;
case 0x095: // stdx (Store DWord Indexed, PPC64 p585)
DIP("stdx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
- storeBE( mkexpr(EA), mkexpr(rS) );
+ store( mkexpr(EA), mkexpr(rS) );
break;
default:
@@ -5174,7 +5282,7 @@
return False;
DIP("std r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
- storeBE( mkexpr(EA), mkexpr(rS) );
+ store( mkexpr(EA), mkexpr(rS) );
break;
case 0x1: // stdu (Store DWord, Update, PPC64 p583)
@@ -5183,7 +5291,7 @@
DIP("stdu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
putIReg( rA_addr, mkexpr(EA) );
- storeBE( mkexpr(EA), mkexpr(rS) );
+ store( mkexpr(EA), mkexpr(rS) );
break;
case 0x2: { // stq (Store QuadWord, Update, PPC64 p583)
@@ -5205,9 +5313,9 @@
assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+12 ) );
}
putIReg( rA_addr, mkexpr(EA_hi) );
- storeBE( mkexpr(EA_hi), mkexpr(rS) );
+ store( mkexpr(EA_hi), mkexpr(rS) );
putIReg( rA_addr, mkexpr( EA_lo) );
- storeBE( mkexpr(EA_lo), getIReg( rS_addr+1 ) );
+ store( mkexpr(EA_lo), getIReg( rS_addr+1 ) );
break;
}
default:
@@ -5256,7 +5364,7 @@
DIP("lmw r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
for (r = rD_addr; r <= 31; r++) {
irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off));
- putIReg( r, mkWidenFrom32(ty, loadBE(Ity_I32, irx_addr ),
+ putIReg( r, mkWidenFrom32(ty, load(Ity_I32, irx_addr ),
False) );
ea_off += 4;
}
@@ -5266,7 +5374,7 @@
DIP("stmw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
for (r = rS_addr; r <= 31; r++) {
irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off));
- storeBE( irx_addr, mkNarrowTo32(ty, getIReg(r)) );
+ store( irx_addr, mkNarrowTo32(ty, getIReg(r)) );
ea_off += 4;
}
break;
@@ -5321,8 +5429,9 @@
Iop_Shl32,
unop(
Iop_8Uto32,
- loadBE(Ity_I8,
- binop(mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)))
+ load( Ity_I8,
+ binop( mkSzOp(ty,Iop_Add8),
+ e_EA, mkSzImm(ty,i)))
),
mkU8(toUChar(shift))
)
@@ -5360,12 +5469,12 @@
}
/* *(EA+i) = 32to8(rS >> shift) */
vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
- storeBE(
- binop(mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)),
- unop(Iop_32to8,
- binop(Iop_Shr32,
- mkNarrowTo32(ty, getIReg(rS)),
- mkU8(toUChar(shift))))
+ store(
+ binop( mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)),
+ unop( Iop_32to8,
+ binop( Iop_Shr32,
+ mkNarrowTo32( ty, getIReg(rS) ),
+ mkU8( toUChar(shift) )))
);
shift -= 8;
}
@@ -5404,10 +5513,10 @@
/* Special case hack */
/* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */
putIReg( rD_addr,
- loadBE(Ity_I32, mkexpr(t_EA)) );
+ load(Ity_I32, mkexpr(t_EA)) );
putIReg( (rD_addr+1) % 32,
- loadBE(Ity_I32,
- binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) );
+ load(Ity_I32,
+ binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) );
} else {
t_nbytes = newTemp(Ity_I32);
assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
@@ -5439,10 +5548,10 @@
if (NumBytes == 8 && !mode64) {
/* Special case hack */
/* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */
- storeBE( mkexpr(t_EA),
- getIReg(rD_addr) );
- storeBE( binop(Iop_Add32, mkexpr(t_EA), mkU32(4)),
- getIReg((rD_addr+1) % 32) );
+ store( mkexpr(t_EA),
+ getIReg(rD_addr) );
+ store( binop(Iop_Add32, mkexpr(t_EA), mkU32(4)),
+ getIReg((rD_addr+1) % 32) );
} else {
t_nbytes = newTemp(Ity_I32);
assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
@@ -6143,7 +6252,7 @@
// and actually do the load
res = newTemp(Ity_I32);
- stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) );
+ stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) );
putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(res), False) );
break;
@@ -6169,7 +6278,7 @@
// Do the store, and get success/failure bit into resSC
resSC = newTemp(Ity_I1);
- stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) );
+ stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
// Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure
// Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success
@@ -6236,7 +6345,7 @@
// and actually do the load
res = newTemp(Ity_I64);
- stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) );
+ stmt( stmt_load( res, mkexpr(EA), NULL/*this is a load*/) );
putIReg( rD_addr, mkexpr(res) );
break;
@@ -6262,7 +6371,7 @@
// Do the store, and get success/failure bit into resSC
resSC = newTemp(Ity_I1);
- stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) );
+ stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
// Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure
// Set CR0[LT GT EQ S0] = 0b001 || XER[SO] on success
@@ -6292,18 +6401,18 @@
// and actually do the load
if (mode64) {
- stmt( IRStmt_LLSC( Iend_BE, res_hi,
- mkexpr(EA), NULL/*this is a load*/) );
- stmt( IRStmt_LLSC( Iend_BE, res_lo,
- binop(Iop_Add64, mkexpr(EA), mkU64(8) ),
- NULL/*this is a load*/) );
+ stmt( stmt_load( res_hi,
+ mkexpr(EA), NULL/*this is a load*/) );
+ stmt( stmt_load( res_lo,
+ binop(Iop_Add64, mkexpr(EA), mkU64(8) ),
+ NULL/*this is a load*/) );
} else {
- stmt( IRStmt_LLSC( Iend_BE, res_hi,
- binop( Iop_Add32, mkexpr(EA), mkU32(4) ),
- NULL/*this is a load*/) );
- stmt( IRStmt_LLSC( Iend_BE, res_lo,
- binop( Iop_Add32, mkexpr(EA), mkU32(12) ),
- NULL/*this is a load*/) );
+ stmt( stmt_load( res_hi,
+ binop( Iop_Add32, mkexpr(EA), mkU32(4) ),
+ NULL/*this is a load*/) );
+ stmt( stmt_load( res_lo,
+ binop( Iop_Add32, mkexpr(EA), mkU32(12) ),
+ NULL/*this is a load*/) );
}
putIReg( rD_addr, mkexpr(res_hi) );
putIReg( rD_addr+1, mkexpr(res_lo) );
@@ -6332,14 +6441,14 @@
resSC = newTemp(Ity_I1);
if (mode64) {
- stmt( IRStmt_LLSC( Iend_BE, resSC, mkexpr(EA), mkexpr(rS_hi) ) );
- storeBE(binop( Iop_Add64, mkexpr(EA), mkU64(8) ), mkexpr(rS_lo) );
+ stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_hi) ) );
+ store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ), mkexpr(rS_lo) );
} else {
- stmt( IRStmt_LLSC( Iend_BE, resSC, binop( Iop_Add32,
- mkexpr(EA),
- mkU32(4) ),
- mkexpr(rS_hi) ) );
- storeBE(binop(Iop_Add32, mkexpr(EA), mkU32(12) ), mkexpr(rS_lo) );
+ stmt( stmt_load( resSC, binop( Iop_Add32,
+ mkexpr(EA),
+ mkU32(4) ),
+ mkexpr(rS_hi) ) );
+ store( binop(Iop_Add32, mkexpr(EA), mkU32(12) ), mkexpr(rS_lo) );
}
// Set CR0[LT GT EQ S0] = 0b000 || XER[SO] on failure
@@ -6662,7 +6771,7 @@
case 0x316: // lhbrx (Load Halfword Byte-Reverse Indexed, PPC32 p449)
DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
- assign( w1, unop(Iop_16Uto32, loadBE(Ity_I16, mkexpr(EA))) );
+ assign( w1, unop(Iop_16Uto32, load(Ity_I16, mkexpr(EA))) );
assign( w2, gen_byterev16(w1) );
putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
/* Signed */False) );
@@ -6670,7 +6779,7 @@
case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459)
DIP("lwbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
- assign( w1, loadBE(Ity_I32, mkexpr(EA)) );
+ assign( w1, load(Ity_I32, mkexpr(EA)) );
assign( w2, gen_byterev32(w1) );
putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
/* Signed */False) );
@@ -6682,26 +6791,29 @@
IRTemp w3 = newTemp( Ity_I32 );
IRTemp w4 = newTemp( Ity_I32 );
DIP("ldbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
- assign( w1, loadBE( Ity_I32, mkexpr( EA ) ) );
+ assign( w1, load( Ity_I32, mkexpr( EA ) ) );
assign( w2, gen_byterev32( w1 ) );
nextAddr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
ty == Ity_I64 ? mkU64( 4 ) : mkU32( 4 ) );
- assign( w3, loadBE( Ity_I32, nextAddr ) );
+ assign( w3, load( Ity_I32, nextAddr ) );
assign( w4, gen_byterev32( w3 ) );
- putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w4 ), mkexpr( w2 ) ) );
+ if (host_endness == VexEndnessLE)
+ putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w2 ), mkexpr( w4 ) ) );
+ else
+ putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w4 ), mkexpr( w2 ) ) );
break;
}
case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523)
DIP("sthbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
- storeBE( mkexpr(EA), unop(Iop_32to16, gen_byterev16(w1)) );
+ store( mkexpr(EA), unop(Iop_32to16, gen_byterev16(w1)) );
break;
case 0x296: // stwbrx (Store Word Byte-Reverse Indxd, PPC32 p531)
DIP("stwbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
- storeBE( mkexpr(EA), gen_byterev32(w1) );
+ store( mkexpr(EA), gen_byterev32(w1) );
break;
case 0x294: // stdbrx (Store Doubleword Byte-Reverse Indexed)
@@ -6713,8 +6825,9 @@
DIP("stdbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
assign(lo, unop(Iop_64HIto32, mkexpr(rS)));
assign(hi, unop(Iop_64to32, mkexpr(rS)));
- storeBE( mkexpr( EA ),
- binop( Iop_32HLto64, gen_byterev32( hi ), gen_byterev32( lo ) ) );
+ store( mkexpr( EA ),
+ binop( Iop_32HLto64, gen_byterev32( hi ),
+ gen_byterev32( lo ) ) );
break;
}
@@ -7232,7 +7345,7 @@
for (i = 0; i < clearszB / 8; i++) {
irx_addr = binop( Iop_Add64, mkexpr(addr), mkU64(i*8) );
- storeBE( irx_addr, mkU64(0) );
+ store( irx_addr, mkU64(0) );
}
} else {
/* Round EA down to the start of the containing block. */
@@ -7242,7 +7355,7 @@
for (i = 0; i < clearszB / 4; i++) {
irx_addr = binop( Iop_Add32, mkexpr(addr), mkU32(i*4) );
- storeBE( irx_addr, mkU32(0) );
+ store( irx_addr, mkU32(0) );
}
}
break;
@@ -7462,7 +7575,7 @@
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))) );
+ unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
break;
case 0x31: // lfsu (Load Float Single, Update, PPC32 p442)
@@ -7471,14 +7584,14 @@
DIP("lfsu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
assign( EA, ea_rA_simm(rA_addr, simm16) );
putFReg( frD_addr,
- unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
+ unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
putIReg( rA_addr, mkexpr(EA) );
break;
case 0x32: // lfd (Load Float Double, PPC32 p437)
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)) );
+ putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
break;
case 0x33: // lfdu (Load Float Double, Update, PPC32 p438)
@@ -7486,7 +7599,7 @@
return False;
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)) );
+ putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
putIReg( rA_addr, mkexpr(EA) );
break;
@@ -7501,7 +7614,7 @@
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))) );
+ load(Ity_F32, mkexpr(EA))) );
break;
case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443)
@@ -7510,14 +7623,14 @@
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))) );
+ unop(Iop_F32toF64, load(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)) );
+ putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
break;
case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439)
@@ -7525,14 +7638,14 @@
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)) );
+ putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
putIReg( rA_addr, mkexpr(EA) );
break;
case 0x357: // lfiwax (Load Float As Integer, Indxd, ISA 2.05 p120)
DIP("lfiwax fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
- assign( iLo, loadBE(Ity_I32, mkexpr(EA)) );
+ assign( iLo, load(Ity_I32, mkexpr(EA)) );
assign( iHi, binop(Iop_Sub32,
mkU32(0),
binop(Iop_Shr32, mkexpr(iLo), mkU8(31))) );
@@ -7545,7 +7658,7 @@
IRTemp dw = newTemp( Ity_I64 );
DIP("lfiwzx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
- assign( iLo, loadBE(Ity_I32, mkexpr(EA)) );
+ assign( iLo, load(Ity_I32, mkexpr(EA)) );
assign( dw, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( iLo ) ) );
putFReg( frD_addr, unop( Iop_ReinterpI64asF64, mkexpr( dw ) ) );
break;
@@ -7604,8 +7717,7 @@
/* Use Iop_TruncF64asF32 to truncate and possible denormalise
the value to be stored in the correct way, without any
rounding. */
- storeBE( mkexpr(EA),
- unop(Iop_TruncF64asF32, mkexpr(frS)) );
+ store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) );
break;
case 0x35: // stfsu (Store Float Single, Update, PPC32 p519)
@@ -7614,15 +7726,14 @@
DIP("stfsu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
assign( EA, ea_rA_simm(rA_addr, simm16) );
/* See comment for stfs */
- storeBE( mkexpr(EA),
- unop(Iop_TruncF64asF32, mkexpr(frS)) );
+ store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) );
putIReg( rA_addr, mkexpr(EA) );
break;
case 0x36: // stfd (Store Float Double, PPC32 p513)
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) );
+ store( mkexpr(EA), mkexpr(frS) );
break;
case 0x37: // stfdu (Store Float Double, Update, PPC32 p514)
@@ -7630,7 +7741,7 @@
return False;
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) );
+ store( mkexpr(EA), mkexpr(frS) );
putIReg( rA_addr, mkexpr(EA) );
break;
@@ -7644,8 +7755,8 @@
DIP("stfsx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
/* See note for stfs */
- storeBE( mkexpr(EA),
- unop(Iop_TruncF64asF32, mkexpr(frS)) );
+ store( mkexpr(EA),
+ unop(Iop_TruncF64asF32, mkexpr(frS)) );
break;
case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520)
@@ -7654,15 +7765,14 @@
DIP("stfsux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
/* See note for stfs */
- storeBE( mkexpr(EA),
- unop(Iop_TruncF64asF32, mkexpr(frS)) );
+ store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) );
putIReg( rA_addr, mkexpr(EA) );
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) );
+ store( mkexpr(EA), mkexpr(frS) );
break;
case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515)
@@ -7670,7 +7780,7 @@
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) );
+ store( mkexpr(EA), mkexpr(frS) );
putIReg( rA_addr, mkexpr(EA) );
break;
@@ -7678,8 +7788,8 @@
// NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
DIP("stfiwx 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),
- unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) );
+ store( mkexpr(EA),
+ unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) );
break;
default:
@@ -8865,11 +8975,11 @@
assign( frT_lo, getFReg(frT_lo_addr) );
if (is_load) {
- putFReg( frT_hi_addr, loadBE(Ity_F64, mkexpr(EA_hi)) );
- putFReg( frT_lo_addr, loadBE(Ity_F64, mkexpr(EA_lo)) );
+ putFReg( frT_hi_addr, load(Ity_F64, mkexpr(EA_hi)) );
+ putFReg( frT_lo_addr, load(Ity_F64, mkexpr(EA_lo)) );
} else {
- storeBE( mkexpr(EA_hi), mkexpr(frT_hi) );
- storeBE( mkexpr(EA_lo), mkexpr(frT_lo) );
+ store( mkexpr(EA_hi), mkexpr(frT_hi) );
+ store( mkexpr(EA_lo), mkexpr(frT_lo) );
}
return True;
@@ -14767,6 +14877,7 @@
static Bool
dis_vxs_misc( UInt theInstr, UInt opc2 )
{
+#define VG_PPC_SIGN_MASK 0x7fffffffffffffffULL
/* XX3-Form and XX2-Form */
UChar opc1 = ifieldOPC( theInstr );
UChar XT = ifieldRegXT ( theInstr );
@@ -14793,7 +14904,20 @@
{
/* Move abs val of dw 0 of VSX[XB] to dw 0 of VSX[XT]. */
IRTemp absVal = newTemp(Ity_V128);
- assign(absVal, binop(Iop_ShrV128, binop(Iop_ShlV128, mkexpr(vB), mkU8(1)), mkU8(1)));
+ if (host_endness == VexEndnessLE) {
+ IRTemp hi64 = newTemp(Ity_I64);
+ IRTemp lo64 = newTemp(Ity_I64);
+ assign( hi64, unop( Iop_V128HIto64, mkexpr(vB) ) );
+ assign( lo64, unop( Iop_V128to64, mkexpr(vB) ) );
+ assign( absVal, binop( Iop_64HLtoV128,
+ binop( Iop_And64, mkexpr(hi64),
+ mkU64(VG_PPC_SIGN_MASK) ),
+ mkexpr(lo64) ) );
+ } else {
+ assign(absVal, binop(Iop_ShrV128,
+ binop(Iop_ShlV128, mkexpr(vB),
+ mkU8(1)), mkU8(1)));
+ }
DIP("xsabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
putVSReg(XT, mkexpr(absVal));
break;
@@ -14801,51 +14925,73 @@
case 0x2C0: // xscpsgndp
{
/* Scalar copy sign double-precision */
- IRTemp vecA_signbit = newTemp(Ity_V128);
- IRTemp vecB_no_signbit = newTemp(Ity_V128);
+ IRTemp vecA_signed = newTemp(Ity_I64);
+ IRTemp vecB_unsigned = newTemp(Ity_I64);
IRTemp vec_result = newTemp(Ity_V128);
DIP("xscpsgndp v%d,v%d v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
- assign( vecB_no_signbit, binop( Iop_ShrV128, binop( Iop_ShlV128,
- mkexpr( vB ),
- mkU8( 1 ) ),
- mkU8( 1 ) ) );
- assign( vecA_signbit, binop( Iop_ShlV128, binop( Iop_ShrV128,
- mkexpr( vA ),
- mkU8( 127 ) ),
- mkU8( 127 ) ) );
- assign( vec_result, binop( Iop_OrV128, mkexpr(vecA_signbit), mkexpr( vecB_no_signbit ) ) );
+ assign( vecA_signed, binop( Iop_And64,
+ unop( Iop_V128HIto64,
+ mkexpr(vA)),
+ mkU64(~VG_PPC_SIGN_MASK) ) );
+ assign( vecB_unsigned, binop( Iop_And64,
+ unop( Iop_V128HIto64,
+ mkexpr(vB) ),
+ mkU64(VG_PPC_SIGN_MASK) ) );
+ assign( vec_result, binop( Iop_64HLtoV128,
+ binop( Iop_Or64,
+ mkexpr(vecA_signed),
+ mkexpr(vecB_unsigned) ),
+ mkU64(0x0ULL)));
putVSReg(XT, mkexpr(vec_result));
break;
}
case 0x2D2: // xsnabsdp
{
/* Scalar negative absolute value double-precision */
- IRTemp vec_neg_signbit = newTemp(Ity_V128);
+ IRTemp BHi_signed = newTemp(Ity_I64);
DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
- assign( vec_neg_signbit, unop( Iop_NotV128, binop( Iop_ShrV128,
- mkV128( 0xffff ),
- mkU8( 1 ) ) ) );
- putVSReg(XT, binop(Iop_OrV128, mkexpr(vec_neg_signbit), mkexpr(vB)));
+ assign( BHi_signed, binop( Iop_Or64,
+ unop( Iop_V128HIto64,
+ mkexpr(vB) ),
+ mkU64(~VG_PPC_SIGN_MASK) ) );
+ putVSReg(XT, binop( Iop_64HLtoV128,
+ mkexpr(BHi_signed), mkU64(0x0ULL) ) );
break;
}
case 0x2F2: // xsnegdp
{
/* Scalar negate double-precision */
- IRTemp vecB_no_signbit = newTemp(Ity_V128);
- IRTemp vecB_signbit_comp = newTemp(Ity_V128);
+ IRTemp BHi_signed = newTemp(Ity_I64);
+ IRTemp BHi_unsigned = newTemp(Ity_I64);
+ IRTemp BHi_negated = newTemp(Ity_I64);
+ IRTemp BHi_negated_signbit = newTemp(Ity_I1);
+ IRTemp vec_result = newTemp(Ity_V128);
DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
- assign( vecB_no_signbit, binop( Iop_ShrV128, binop( Iop_ShlV128,
- mkexpr( vB ),
- mkU8( 1 ) ),
- mkU8( 1 ) ) );
- assign( vecB_signbit_comp, binop( Iop_ShlV128,
- unop( Iop_NotV128,
- binop( Iop_ShrV128,
- mkexpr( vB ),
- mkU8( 127 ) ) ),
- mkU8( 127 ) ) );
- putVSReg( XT, binop( Iop_OrV128, mkexpr( vecB_no_signbit ),
- mkexpr( vecB_signbit_comp ) ) );
+ assign( BHi_signed, unop( Iop_V128HIto64, mkexpr(vB) ) );
+ assign( BHi_unsigned, binop( Iop_And64, mkexpr(BHi_signed),
+ mkU64(VG_PPC_SIGN_MASK) ) );
+ assign( BHi_negated_signbit,
+ unop( Iop_Not1,
+ unop( Iop_32to1,
+ binop( Iop_Shr32,
+ unop( Iop_64HIto32,
+ binop( Iop_And64,
+ mkexpr(BHi_signed),
+ mkU64(~VG_PPC_SIGN_MASK) )
+ ),
+ mkU8(31) ) ) ) );
+ assign( BHi_negated,
+ binop( Iop_Or64,
+ binop( Iop_32HLto64,
+ binop( Iop_Shl32,
+ unop( Iop_1Uto32,
+ mkexpr(BHi_negated_signbit) ),
+ mkU8(31) ),
+ mkU32(0) ),
+ mkexpr(BHi_unsigned) ) );
+ assign( vec_result, binop( Iop_64HLtoV128, mkexpr(BHi_negated),
+ mkU64(0x0ULL)));
+ putVSReg( XT, mkexpr(vec_result));
break;
}
case 0x280: // xsmaxdp (VSX Scalar Maximum Double-Precision)
@@ -15070,7 +15216,7 @@
{
IRExpr * exp;
DIP("lxsiwzx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
- exp = unop( Iop_64HIto32, loadBE( Ity_I64, mkexpr( EA ) ) );
+ exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) );
putVSReg( XT, binop( Iop_64HLtoV128,
unop( Iop_32Uto64, exp),
mkU64(0) ) );
@@ -15080,7 +15226,7 @@
{
IRExpr * exp;
DIP("lxsiwax %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
- exp = unop( Iop_64HIto32, loadBE( Ity_I64, mkexpr( EA ) ) );
+ exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) );
putVSReg( XT, binop( Iop_64HLtoV128,
unop( Iop_32Sto64, exp),
mkU64(0) ) );
@@ -15097,8 +15243,7 @@
exp = unop( Iop_ReinterpF64asI64,
unop( Iop_F32toF64,
unop( Iop_ReinterpI32asF32,
- unop( Iop_64HIto32,
- loadBE( Ity_I64, mkexpr( EA ) ) ) ) ) );
+ load( Ity_I32, mkexpr( EA ) ) ) ) );
putVSReg( XT, binop( Iop_64HLtoV128, exp, mkU64( 0 ) ) );
break;
@@ -15107,7 +15252,7 @@
{
IRExpr * exp;
DIP("lxsdx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
- exp = loadBE( Ity_I64, mkexpr( EA ) );
+ exp = load( Ity_I64, mkexpr( EA ) );
// We need to pass an expression of type Ity_V128 with putVSReg, but the load
// we just performed is only a DW. But since the contents of VSR[XT] element 1
// are undefined after this operation, we can just do a splat op.
@@ -15121,10 +15266,10 @@
ULong ea_off = 8;
IRExpr* high_addr;
DIP("lxvd2x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
- high = loadBE( Ity_I64, mkexpr( EA ) );
+ high = load( Ity_I64, mkexpr( EA ) );
high_addr = binop( addOp, mkexpr( EA ), ty == Ity_I64 ? mkU64( ea_off )
: mkU32( ea_off ) );
- low = loadBE( Ity_I64, high_addr );
+ low = load( Ity_I64, high_addr );
putVSReg( XT, binop( Iop_64HLtoV128, high, low ) );
break;
}
@@ -15132,7 +15277,7 @@
{
IRTemp data = newTemp(Ity_I64);
DIP("lxvdsx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
- assign( data, loadBE( Ity_I64, mkexpr( EA ) ) );
+ assign( data, load( Ity_I64, mkexpr( EA ) ) );
putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( data ), mkexpr( data ) ) );
break;
}
@@ -15143,19 +15288,19 @@
IRExpr* irx_addr;
DIP("lxvw4x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
- t3 = loadBE( Ity_I32, mkexpr( EA ) );
+ t3 = load( Ity_I32, mkexpr( EA ) );
ea_off += 4;
irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
- t2 = loadBE( Ity_I32, irx_addr );
+ t2 = load( Ity_I32, irx_addr );
ea_off += 4;
irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
- t1 = loadBE( Ity_I32, irx_addr );
+ t1 = load( Ity_I32, irx_addr );
ea_off += 4;
irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
- t0 = loadBE( Ity_I32, irx_addr );
+ t0 = load( Ity_I32, irx_addr );
putVSReg( XT, binop( Iop_64HLtoV128, binop( Iop_32HLto64, t3, t2 ),
binop( Iop_32HLto64, t1, t0 ) ) );
break;
@@ -15203,7 +15348,7 @@
DIP("stxsiwx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
low32 = unop( Iop_64to32, high64 );
- storeBE( mkexpr( EA ), low32 );
+ store( mkexpr( EA ), low32 );
break;
}
case 0x28C:
@@ -15216,7 +15361,7 @@
assign(val32, unop( Iop_ReinterpF32asI32,
unop( Iop_TruncF64asF32,
mkexpr(high64) ) ) );
- storeBE( mkexpr( EA ), mkexpr( val32 ) );
+ store( mkexpr( EA ), mkexpr( val32 ) );
break;
}
case 0x2CC:
@@ -15224,7 +15369,7 @@
IRExpr * high64;
DIP("stxsdx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
- storeBE( mkexpr( EA ), high64 );
+ store( mkexpr( EA ), high64 );
break;
}
case 0x3CC:
@@ -15233,9 +15378,9 @@
DIP("stxvd2x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
low64 = unop( Iop_V128to64, mkexpr( vS ) );
- storeBE( mkexpr( EA ), high64 );
- storeBE( binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), ty == Ity_I64 ? mkU64( 8 )
- : mkU32( 8 ) ), low64 );
+ store( mkexpr( EA ), high64 );
+ store( binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
+ ty == Ity_I64 ? mkU64( 8 ) : mkU32( 8 ) ), low64 );
break;
}
case 0x38C:
@@ -15251,20 +15396,19 @@
// quad-word aligned. Th...
[truncated message content] |