|
From: <sv...@va...> - 2012-12-03 13:32:19
|
florian 2012-12-03 13:32:05 +0000 (Mon, 03 Dec 2012)
New Revision: 2578
Log:
Use "load on condition" insns, if availably, to implement
S390_INSN_COND_MOVE.
Modified files:
trunk/priv/host_s390_defs.c
trunk/priv/host_s390_defs.h
trunk/priv/main_main.c
trunk/pub/libvex.h
Modified: trunk/pub/libvex.h (+2 -0)
===================================================================
--- trunk/pub/libvex.h 2012-12-02 21:31:15 +00:00 (rev 2577)
+++ trunk/pub/libvex.h 2012-12-03 13:32:05 +00:00 (rev 2578)
@@ -133,6 +133,7 @@
#define VEX_HWCAPS_S390X_ETF3 (1<<13) /* ETF3-enhancement facility */
#define VEX_HWCAPS_S390X_STCKF (1<<14) /* STCKF facility */
#define VEX_HWCAPS_S390X_FPEXT (1<<15) /* Floating point extension facility */
+#define VEX_HWCAPS_S390X_LSCOND (1<<16) /* Conditional load/store facility */
/* Special value representing all available s390x hwcaps */
#define VEX_HWCAPS_S390X_ALL (VEX_HWCAPS_S390X_LDISP | \
@@ -143,6 +144,7 @@
VEX_HWCAPS_S390X_STFLE | \
VEX_HWCAPS_S390X_STCKF | \
VEX_HWCAPS_S390X_FPEXT | \
+ VEX_HWCAPS_S390X_LSCOND| \
VEX_HWCAPS_S390X_ETF3 | \
VEX_HWCAPS_S390X_ETF2)
Modified: trunk/priv/main_main.c (+4 -1)
===================================================================
--- trunk/priv/main_main.c 2012-12-02 21:31:15 +00:00 (rev 2577)
+++ trunk/priv/main_main.c 2012-12-03 13:32:05 +00:00 (rev 2578)
@@ -1260,7 +1260,7 @@
static const HChar* show_hwcaps_s390x ( UInt hwcaps )
{
static const HChar prefix[] = "s390x";
- static const HChar facilities[][6] = {
+ static const HChar facilities[][7] = {
{ "ldisp" },
{ "eimm" },
{ "gie" },
@@ -1271,6 +1271,7 @@
{ "etf3" },
{ "stckf" },
{ "fpext" },
+ { "lscond" },
};
static HChar buf[sizeof facilities + sizeof prefix + 1];
static HChar *p;
@@ -1300,6 +1301,8 @@
p = p + vex_sprintf(p, "-%s", facilities[8]);
if (hwcaps & VEX_HWCAPS_S390X_FPEXT)
p = p + vex_sprintf(p, "-%s", facilities[9]);
+ if (hwcaps & VEX_HWCAPS_S390X_LSCOND)
+ p = p + vex_sprintf(p, "-%s", facilities[10]);
/* If there are no facilities, add "zarch" */
if (hwcaps == 0)
Modified: trunk/priv/host_s390_defs.h (+2 -0)
===================================================================
--- trunk/priv/host_s390_defs.h 2012-12-02 21:31:15 +00:00 (rev 2577)
+++ trunk/priv/host_s390_defs.h 2012-12-03 13:32:05 +00:00 (rev 2578)
@@ -694,6 +694,8 @@
(s390_host_hwcaps & (VEX_HWCAPS_S390X_STCKF))
#define s390_host_has_fpext \
(s390_host_hwcaps & (VEX_HWCAPS_S390X_FPEXT))
+#define s390_host_has_lscond \
+ (s390_host_hwcaps & (VEX_HWCAPS_S390X_LSCOND))
#endif /* ndef __VEX_HOST_S390_DEFS_H */
Modified: trunk/priv/host_s390_defs.c (+90 -0)
===================================================================
--- trunk/priv/host_s390_defs.c 2012-12-02 21:31:15 +00:00 (rev 2577)
+++ trunk/priv/host_s390_defs.c 2012-12-03 13:32:05 +00:00 (rev 2578)
@@ -3935,6 +3935,43 @@
return emit_RRF4(p, 0xb3d30000, r3, m4, r1, r2);
}
+
+static UChar *
+s390_emit_LOCGR(UChar *p, UChar m3, UChar r1, UChar r2)
+{
+ vassert(s390_host_has_lscond);
+ if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
+ s390_disasm(ENC4(MNM, GPR, GPR, UINT), "locgr", r1, r2, m3);
+ }
+
+ return emit_RRF3(p, 0xb9e20000, m3, r1, r2);
+}
+
+
+static UChar *
+s390_emit_LOC(UChar *p, UChar r1, UChar m3, UChar b2, UShort dl2, UChar dh2)
+{
+ vassert(s390_host_has_ldisp || dh2 == 0);
+
+ if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
+ s390_disasm(ENC4(MNM, GPR, UINT, SDXB), "loc", r1, m3, dh2, dl2, 0, b2);
+
+ return emit_RSY(p, 0xeb00000000f2ULL, r1, m3, b2, dl2, dh2);
+}
+
+
+static UChar *
+s390_emit_LOCG(UChar *p, UChar r1, UChar m3, UChar b2, UShort dl2, UChar dh2)
+{
+ vassert(s390_host_has_ldisp || dh2 == 0);
+
+ if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
+ s390_disasm(ENC4(MNM, GPR, UINT, SDXB), "locg", r1, m3, dh2, dl2, 0, b2);
+
+ return emit_RSY(p, 0xeb00000000e2ULL, r1, m3, b2, dl2, dh2);
+}
+
+
/* Provide a symbolic name for register "R0" */
#define R0 0
@@ -7394,8 +7431,61 @@
dst = insn->variant.cond_move.dst;
src = insn->variant.cond_move.src;
+ if (cond == S390_CC_NEVER) return buf;
+
p = buf;
+ if (s390_host_has_lscond) {
+ /* LOCx is not the preferred way to implement an unconditional load. */
+ if (cond != S390_CC_ALWAYS) goto use_branch_insn;
+
+ switch (src.tag) {
+ case S390_OPND_REG:
+ return s390_emit_LOCGR(p, cond, hregNumber(dst),
+ hregNumber(src.variant.reg));
+
+ case S390_OPND_AMODE: {
+ const s390_amode *am = src.variant.am;
+
+ /* We cannot use LOCx for loads less than 4 bytes. In that case
+ load into R0 and then use LOCGR. Do the same if the amode uses
+ an index register. */
+ if (insn->size < 4 ||
+ am->tag == S390_AMODE_BX12 || am->tag == S390_AMODE_BX20) {
+ p = s390_emit_load_mem(p, insn->size, R0, am);
+ p = s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
+ return p;
+ }
+
+ vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20);
+ vassert(insn->size == 4 || insn->size == 8);
+
+ UInt b = hregNumber(am->b);
+ UInt d = am->d;
+
+ if (insn->size == 4) {
+ return s390_emit_LOC(p, hregNumber(dst), cond, b, DISP20(d));
+ }
+ return s390_emit_LOCG(p, hregNumber(dst), cond, b, DISP20(d));
+ }
+
+ case S390_OPND_IMMEDIATE: {
+ ULong value = src.variant.imm;
+
+ /* Load value into R0, then use LOCGR */
+ if (insn->size <= 4) {
+ p = s390_emit_load_32imm(p, R0, value);
+ return s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
+ }
+
+ vassert(insn->size == 8);
+ p = s390_emit_load_64imm(p, R0, value);
+ return s390_emit_LOCGR(p, cond, hregNumber(dst), R0);
+ }
+ }
+ }
+
+use_branch_insn:
/* Branch (if cond fails) over move instrs */
if (cond != S390_CC_ALWAYS) {
/* Don't know how many bytes to jump over yet.
|