]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
s390x: fpr - gpr transfer facility
authorJulian Seward <jseward@acm.org>
Wed, 27 Apr 2011 11:58:22 +0000 (11:58 +0000)
committerJulian Seward <jseward@acm.org>
Wed, 27 Apr 2011 11:58:22 +0000 (11:58 +0000)
We need to introduce a new hwcap to model the presence of the fpr - gpr
transfer facility. If it is not available, we cannot use the LDGR and LGDR
insns and need to use a trick similar to what ppc does (write/read stack
location).
Fixes #268619 (vex side).
(Florian Krohm, britzel@acm.org)

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

VEX/priv/host_s390_defs.c
VEX/priv/host_s390_defs.h
VEX/priv/main_main.c
VEX/pub/libvex.h

index 17cc7377576445eeca88215cd229b08712a9efee..75245164ffd19dcbffca34e4e68f15e6fbbc44c5 100644 (file)
@@ -2794,7 +2794,8 @@ s390_emit_LFPC(UChar *p, UChar b2, UShort d2)
 static UChar *
 s390_emit_LDGR(UChar *p, UChar r1, UChar r2)
 {
-   /* fixs390: PR 268619 */
+   vassert(s390_host_has_fgx);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, FPR, GPR), "ldgr", r1, r2);
 
@@ -2805,7 +2806,8 @@ s390_emit_LDGR(UChar *p, UChar r1, UChar r2)
 static UChar *
 s390_emit_LGDR(UChar *p, UChar r1, UChar r2)
 {
-   /* fixs390: PR 268619 */
+   vassert(s390_host_has_fgx);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, FPR), "lgdr", r1, r2);
 
@@ -3875,6 +3877,55 @@ s390_emit_CLFIw(UChar *p, UChar r1, UInt i2)
    return s390_emit_CLR(p, r1, R0);
 }
 
+
+static UChar *
+s390_emit_LGDRw(UChar *p, UChar r1, UChar r2)
+{
+   if (s390_host_has_fgx) {
+      return s390_emit_LGDR(p, r1, r2);
+   }
+
+   /* Store the FPR at memory[sp - 8]. This is safe because SP grows towards
+      smaller addresses and is 8-byte aligned. Then load the GPR from that
+      memory location/ */
+   if (s390_host_has_ldisp) {
+      p = s390_emit_STDY(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
+      return s390_emit_LG(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
+   }
+
+   /* No long displacement. Need to adjust SP explicitly as to avoid negative
+      displacements. */
+   p = s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, -8);
+   p = s390_emit_STD(p, r2, R0, S390_REGNO_STACK_POINTER, 0);
+   p = s390_emit_LG(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(0));
+   return s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, 8);
+}
+
+
+static UChar *
+s390_emit_LDGRw(UChar *p, UChar r1, UChar r2)
+{
+   if (s390_host_has_fgx) {
+      return s390_emit_LDGR(p, r1, r2);
+   }
+
+   /* Store the GPR at memory[sp - 8]. This is safe because SP grows towards
+      smaller addresses and is 8-byte aligned. Then load the FPR from that
+      memory location/ */
+   if (s390_host_has_ldisp) {
+      p = s390_emit_STG(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
+      return s390_emit_LDY(p, r1, R0, S390_REGNO_STACK_POINTER, DISP20(-8));
+   }
+
+   /* No long displacement. Need to adjust SP explicitly as to avoid negative
+      displacements. */
+   p = s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, -8);
+   p = s390_emit_STG(p, r2, R0, S390_REGNO_STACK_POINTER, DISP20(0));
+   p = s390_emit_LD(p, r1, R0, S390_REGNO_STACK_POINTER, 0);
+   return s390_emit_AGHI(p, S390_REGNO_STACK_POINTER, 8);
+}
+
+
 /* Split up a 20-bit displacement into its high and low piece
    suitable for passing as function arguments */
 #define DISP20(d) ((d) & 0xFFF), (((d) >> 12) & 0xFF)
@@ -5051,9 +5102,9 @@ s390_insn_move_emit(UChar *buf, const s390_insn *insn)
          return s390_emit_LDR(buf, dst, src);
    } else {
       if (dst_class == HRcFlt64 && src_class == HRcInt64)
-         return s390_emit_LDGR(buf, dst, src);   /* fixs390: PR 268619 */
+         return s390_emit_LDGRw(buf, dst, src);
       if (dst_class == HRcInt64 && src_class == HRcFlt64)
-         return s390_emit_LGDR(buf, dst, src);   /* fixs390: PR 268619 */
+         return s390_emit_LGDRw(buf, dst, src);
       /* A move between floating point registers and general purpose
          registers of different size should never occur and indicates
          an error elsewhere. */
index e409bd5b37e8bedf3da04a667f0673eec87d4f93..0f3cc91e502878f3d0bedb99ff1d095f0b6c1ff4 100644 (file)
@@ -491,6 +491,8 @@ extern const VexArchInfo *s390_archinfo_host;
                       (s390_archinfo_host->hwcaps & (VEX_HWCAPS_S390X_GIE))
 #define s390_host_has_dfp \
                       (s390_archinfo_host->hwcaps & (VEX_HWCAPS_S390X_DFP))
+#define s390_host_has_fgx \
+                      (s390_archinfo_host->hwcaps & (VEX_HWCAPS_S390X_FGX))
 
 #endif /* ndef __VEX_HOST_S390_DEFS_H */
 
index 12dcbfd60f21e2e0bee27c23f79f196a8cf7d0ed..9d939017cd4c68495473b3181cb959a6eeecd77c 100644 (file)
@@ -933,23 +933,38 @@ static HChar* show_hwcaps_arm ( UInt hwcaps )
 
 static HChar* show_hwcaps_s390x ( UInt hwcaps )
 {
-   const UInt LD = VEX_HWCAPS_S390X_LDISP;
-   const UInt EI = VEX_HWCAPS_S390X_EIMM;
-   const UInt GE = VEX_HWCAPS_S390X_GIE;
-   const UInt DF = VEX_HWCAPS_S390X_DFP;
+   static const HChar prefix[] = "s390x";
+   static const HChar facilities[][6] = {
+     { "ldisp" },
+     { "eimm" },
+     { "gie" },
+     { "dfp" },
+     { "fgx" },
+   };
+   static HChar buf[sizeof facilities + sizeof prefix + 1];
+   static HChar *p;
+
+   if (buf[0] != '\0') return buf;  /* already constructed */
 
    hwcaps = VEX_HWCAPS_S390X(hwcaps);
 
-   if (hwcaps == (LD))          return "s390x-ldisp";
-   if (hwcaps == (LD|EI))       return "s390x-ldisp-eimm";
-   if (hwcaps == (LD|GE))       return "s390x-ldisp-gie";
-   if (hwcaps == (LD|DF))       return "s390x-ldisp-dfp";
-   if (hwcaps == (LD|EI|GE))    return "s390x-ldisp-eimm-gie";
-   if (hwcaps == (LD|EI|DF))    return "s390x-ldisp-eimm-dfp";
-   if (hwcaps == (LD|GE|DF))    return "s390x-ldisp-gie-dfp";
-   if (hwcaps == (LD|EI|GE|DF)) return "s390x-ldisp-eimm-gie-dfp";
-
-   return "s390-zarch";
+   p = buf + vex_sprintf(buf, "%s", prefix);
+   if (hwcaps & VEX_HWCAPS_S390X_LDISP)
+     p = p + vex_sprintf(p, "-%s", facilities[0]);
+   if (hwcaps & VEX_HWCAPS_S390X_EIMM)
+     p = p + vex_sprintf(p, "-%s", facilities[1]);
+   if (hwcaps & VEX_HWCAPS_S390X_GIE)
+     p = p + vex_sprintf(p, "-%s", facilities[2]);
+   if (hwcaps & VEX_HWCAPS_S390X_DFP)
+     p = p + vex_sprintf(p, "-%s", facilities[3]);
+   if (hwcaps & VEX_HWCAPS_S390X_FGX)
+     p = p + vex_sprintf(p, "-%s", facilities[4]);
+
+   /* If there are no facilities, add "zarch" */
+   if (hwcaps == 0)
+     vex_sprintf(p, "-%s", "zarch");
+
+   return buf;
 }
 
 /* ---- */
index 0ca5ef1cacc2dc51fff42259999e07d663237f2a..1e2b386683a5d79ea88e83c668d8efb631c378ac 100644 (file)
@@ -104,7 +104,8 @@ typedef
    [24]    Extended-immediate facility
    [23]    General-instruction-extension facility
    [22]    Decimal floating point facility
-   [0:21]  Currently unused; reserved for future use
+   [21]    FPR-GR transfer facility
+   [0:20]  Currently unused; reserved for future use
 */
 
 /* Model numbers must be assigned in chronological order.
@@ -121,16 +122,18 @@ typedef
 #define VEX_S390X_MODEL_INVALID  9
 #define VEX_S390X_MODEL_MASK     0x3F
 
-#define VEX_HWCAPS_S390X_LDISP (1<<6)  /* Long-displacement facility */
-#define VEX_HWCAPS_S390X_EIMM  (1<<7)  /* Extended-immediate facility */
-#define VEX_HWCAPS_S390X_GIE   (1<<8)  /* General-instruction-extension facility */
-#define VEX_HWCAPS_S390X_DFP   (1<<9)  /* Decimal floating point facility */
+#define VEX_HWCAPS_S390X_LDISP (1<<6)   /* Long-displacement facility */
+#define VEX_HWCAPS_S390X_EIMM  (1<<7)   /* Extended-immediate facility */
+#define VEX_HWCAPS_S390X_GIE   (1<<8)   /* General-instruction-extension facility */
+#define VEX_HWCAPS_S390X_DFP   (1<<9)   /* Decimal floating point facility */
+#define VEX_HWCAPS_S390X_FGX   (1<<10)  /* FPR-GR transfer facility */
 
 /* Special value representing all available s390x hwcaps */
 #define VEX_HWCAPS_S390X_ALL   (VEX_HWCAPS_S390X_LDISP | \
                                 VEX_HWCAPS_S390X_EIMM  | \
                                 VEX_HWCAPS_S390X_GIE   | \
-                                VEX_HWCAPS_S390X_DFP)
+                                VEX_HWCAPS_S390X_DFP   | \
+                                VEX_HWCAPS_S390X_FGX)
 
 #define VEX_HWCAPS_S390X(x)  ((x) & ~VEX_S390X_MODEL_MASK)
 #define VEX_S390X_MODEL(x)   ((x) &  VEX_S390X_MODEL_MASK)