|
From: <sv...@va...> - 2014-06-28 22:11:31
|
Author: sewardj
Date: Sat Jun 28 22:11:16 2014
New Revision: 2894
Log:
arm64: change the representation of FPSR.QC so that it can be
used efficiently to record SIMD saturation, and remove support
for all other bits of FPSR, since we don't model them anyway.
Modified:
trunk/priv/guest_arm64_helpers.c
trunk/priv/guest_arm64_toIR.c
trunk/pub/libvex_guest_arm64.h
Modified: trunk/priv/guest_arm64_helpers.c
==============================================================================
--- trunk/priv/guest_arm64_helpers.c (original)
+++ trunk/priv/guest_arm64_helpers.c Sat Jun 28 22:11:16 2014
@@ -1178,6 +1178,28 @@
}
/* VISIBLE TO LIBVEX CLIENT */
+ULong LibVEX_GuestARM64_get_fpsr ( const VexGuestARM64State* vex_state )
+{
+ UInt w32 = vex_state->guest_QCFLAG[0] | vex_state->guest_QCFLAG[1]
+ | vex_state->guest_QCFLAG[2] | vex_state->guest_QCFLAG[3];
+ ULong fpsr = 0;
+ // QC
+ if (w32 != 0)
+ fpsr |= (1 << 27);
+ return fpsr;
+}
+
+void LibVEX_GuestARM64_set_fpsr ( /*MOD*/VexGuestARM64State* vex_state,
+ ULong fpsr )
+{
+ // QC
+ vex_state->guest_QCFLAG[0] = (UInt)((fpsr >> 27) & 1);
+ vex_state->guest_QCFLAG[1] = 0;
+ vex_state->guest_QCFLAG[2] = 0;
+ vex_state->guest_QCFLAG[3] = 0;
+}
+
+/* VISIBLE TO LIBVEX CLIENT */
void LibVEX_GuestARM64_initialise ( /*OUT*/VexGuestARM64State* vex_state )
{
vex_bzero(vex_state, sizeof(*vex_state));
@@ -1345,7 +1367,7 @@
/* Describe any sections to be regarded by Memcheck as
'always-defined'. */
- .n_alwaysDefd = 10,
+ .n_alwaysDefd = 9,
/* flags thunk: OP is always defd, whereas DEP1 and DEP2
have to be tracked. See detailed comment in gdefs.h on
@@ -1359,8 +1381,7 @@
/* 5 */ ALWAYSDEFD(guest_CMLEN),
/* 6 */ ALWAYSDEFD(guest_NRADDR),
/* 7 */ ALWAYSDEFD(guest_IP_AT_SYSCALL),
- /* 8 */ ALWAYSDEFD(guest_FPCR),
- /* 9 */ ALWAYSDEFD(guest_FPSR)
+ /* 8 */ ALWAYSDEFD(guest_TPIDR_EL0)
}
};
Modified: trunk/priv/guest_arm64_toIR.c
==============================================================================
--- trunk/priv/guest_arm64_toIR.c (original)
+++ trunk/priv/guest_arm64_toIR.c Sat Jun 28 22:11:16 2014
@@ -697,14 +697,7 @@
#define OFFB_Q31 offsetof(VexGuestARM64State,guest_Q31)
#define OFFB_FPCR offsetof(VexGuestARM64State,guest_FPCR)
-#define OFFB_FPSR offsetof(VexGuestARM64State,guest_FPSR)
-//ZZ #define OFFB_TPIDRURO offsetof(VexGuestARMState,guest_TPIDRURO)
-//ZZ #define OFFB_ITSTATE offsetof(VexGuestARMState,guest_ITSTATE)
-//ZZ #define OFFB_QFLAG32 offsetof(VexGuestARMState,guest_QFLAG32)
-//ZZ #define OFFB_GEFLAG0 offsetof(VexGuestARMState,guest_GEFLAG0)
-//ZZ #define OFFB_GEFLAG1 offsetof(VexGuestARMState,guest_GEFLAG1)
-//ZZ #define OFFB_GEFLAG2 offsetof(VexGuestARMState,guest_GEFLAG2)
-//ZZ #define OFFB_GEFLAG3 offsetof(VexGuestARMState,guest_GEFLAG3)
+#define OFFB_QCFLAG offsetof(VexGuestARM64State,guest_QCFLAG)
#define OFFB_CMSTART offsetof(VexGuestARM64State,guest_CMSTART)
#define OFFB_CMLEN offsetof(VexGuestARM64State,guest_CMLEN)
@@ -4879,16 +4872,37 @@
/* Cases for FPSR
0xD51B44 001 Rt MSR fpsr, rT
0xD53B44 001 Rt MSR rT, fpsr
+ The only part of this we model is FPSR.QC. All other bits
+ are ignored when writing to it and RAZ when reading from it.
*/
if ( (INSN(31,0) & 0xFFFFFFE0) == 0xD51B4420 /*MSR*/
|| (INSN(31,0) & 0xFFFFFFE0) == 0xD53B4420 /*MRS*/) {
Bool toSys = INSN(21,21) == 0;
UInt tt = INSN(4,0);
if (toSys) {
- stmt( IRStmt_Put( OFFB_FPSR, getIReg32orZR(tt)) );
+ /* Just deal with FPSR.QC. Make up a V128 value which is
+ zero if Xt[27] is zero and any other value if Xt[27] is
+ nonzero. */
+ IRTemp qc64 = newTemp(Ity_I64);
+ assign(qc64, binop(Iop_And64,
+ binop(Iop_Shr64, getIReg64orZR(tt), mkU8(27)),
+ mkU64(1)));
+ IRExpr* qcV128 = binop(Iop_64HLtoV128, mkexpr(qc64), mkexpr(qc64));
+ stmt( IRStmt_Put( OFFB_QCFLAG, qcV128 ) );
DIP("msr fpsr, %s\n", nameIReg64orZR(tt));
} else {
- putIReg32orZR(tt, IRExpr_Get(OFFB_FPSR, Ity_I32));
+ /* Generate a value which is all zeroes except for bit 27,
+ which must be zero if QCFLAG is all zeroes and one otherwise. */
+ IRTemp qcV128 = newTemp(Ity_V128);
+ assign(qcV128, IRExpr_Get( OFFB_QCFLAG, Ity_V128 ));
+ IRTemp qc64 = newTemp(Ity_I64);
+ assign(qc64, binop(Iop_Or64, unop(Iop_V128HIto64, mkexpr(qcV128)),
+ unop(Iop_V128to64, mkexpr(qcV128))));
+ IRExpr* res = binop(Iop_Shl64,
+ unop(Iop_1Uto64,
+ binop(Iop_CmpNE64, mkexpr(qc64), mkU64(0))),
+ mkU8(27));
+ putIReg64orZR(tt, res);
DIP("mrs %s, fpsr\n", nameIReg64orZR(tt));
}
return True;
@@ -4896,6 +4910,9 @@
/* Cases for NZCV
D51B42 000 Rt MSR nzcv, rT
D53B42 000 Rt MRS rT, nzcv
+ The only parts of NZCV that actually exist are bits 31:28, which
+ are the N Z C and V bits themselves. Hence the flags thunk provides
+ all the state we need.
*/
if ( (INSN(31,0) & 0xFFFFFFE0) == 0xD51B4200 /*MSR*/
|| (INSN(31,0) & 0xFFFFFFE0) == 0xD53B4200 /*MRS*/) {
Modified: trunk/pub/libvex_guest_arm64.h
==============================================================================
--- trunk/pub/libvex_guest_arm64.h (original)
+++ trunk/pub/libvex_guest_arm64.h Sat Jun 28 22:11:16 2014
@@ -123,6 +123,13 @@
U128 guest_Q30;
U128 guest_Q31;
+ /* A 128-bit value which is used to represent the FPSR.QC (sticky
+ saturation) flag, when necessary. If the value stored here
+ is zero, FPSR.QC is currently zero. If it is any other value,
+ FPSR.QC is currently one. We don't currently represent any
+ other bits of FPSR, so this is all that that is for FPSR. */
+ U128 guest_QCFLAG;
+
/* Various pseudo-regs mandated by Vex or Valgrind. */
/* Emulation notes */
UInt guest_EMNOTE;
@@ -152,15 +159,9 @@
note of bits 23 and 22. */
UInt guest_FPCR;
- /* The complete FPSR. As with FPCR, the guest may write and
- read any values here, and the emulation ignores it, with the
- exception of bit 27 (QC, the sticky saturation bit) which
- does get set when required. */
- UInt guest_FPSR;
-
/* Padding to make it have an 16-aligned size */
- UInt pad_end_0;
- ULong pad_end_1;
+ /* UInt pad_end_0; */
+ /* ULong pad_end_1; */
}
VexGuestARM64State;
@@ -182,6 +183,18 @@
ULong LibVEX_GuestARM64_get_nzcv ( /*IN*/
const VexGuestARM64State* vex_state );
+/* Calculate the ARM64 FPSR state from the saved data, in the format
+ 36x0:qc:27x0 */
+extern
+ULong LibVEX_GuestARM64_get_fpsr ( /*IN*/
+ const VexGuestARM64State* vex_state );
+
+/* Set the ARM64 FPSR representation from the given FPSR value. */
+extern
+void LibVEX_GuestARM64_set_fpsr ( /*MOD*/VexGuestARM64State* vex_state,
+ ULong fpsr );
+
+
#endif /* ndef __LIBVEX_PUB_GUEST_ARM64_H */
|