]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
arm64: change the representation of FPSR.QC so that it can be
authorJulian Seward <jseward@acm.org>
Sat, 28 Jun 2014 22:11:16 +0000 (22:11 +0000)
committerJulian Seward <jseward@acm.org>
Sat, 28 Jun 2014 22:11:16 +0000 (22:11 +0000)
used efficiently to record SIMD saturation, and remove support
for all other bits of FPSR, since we don't model them anyway.

git-svn-id: svn://svn.valgrind.org/vex/trunk@2894

VEX/priv/guest_arm64_helpers.c
VEX/priv/guest_arm64_toIR.c
VEX/pub/libvex_guest_arm64.h

index 3196d424b49c7a778c66335c43cf28319b4197ae..eaa8d6fb84b0f9f5ffdfb5cb57caba671e40821d 100644 (file)
@@ -1177,6 +1177,28 @@ ULong LibVEX_GuestARM64_get_nzcv ( /*IN*/const VexGuestARM64State* vex_state )
    return nzcv;
 }
 
+/* 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 )
 {
@@ -1345,7 +1367,7 @@ VexGuestLayout
 
           /* 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 @@ VexGuestLayout
                  /* 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)
                }
         };
 
index 36934cad2010d677adaf9e226606f57b61b5ed73..166a7276c1d17bb4d4b77161b300214bd9ccb335 100644 (file)
@@ -697,14 +697,7 @@ static IRExpr* narrowFrom64 ( IRType dstTy, IRExpr* e )
 #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 @@ Bool dis_ARM64_branch_etc(/*MB_OUT*/DisResult* dres, UInt insn,
    /* 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 @@ Bool dis_ARM64_branch_etc(/*MB_OUT*/DisResult* dres, UInt insn,
    /* 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*/) {
index 1253c59fad02f3085f51cb4e27aaa60a34a443b6..ac224328835a748b9e22b152c12c77ae658e50da 100644 (file)
@@ -123,6 +123,13 @@ typedef
       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 @@ typedef
          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 @@ extern
 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 */