From: Florian Krohm Date: Mon, 3 Dec 2012 13:32:05 +0000 (+0000) Subject: Use "load on condition" insns, if availably, to implement X-Git-Tag: svn/VALGRIND_3_9_0^2~203 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7056d0425945855df88f8056f1cab7169b613d3b;p=thirdparty%2Fvalgrind.git Use "load on condition" insns, if availably, to implement S390_INSN_COND_MOVE. git-svn-id: svn://svn.valgrind.org/vex/trunk@2578 --- diff --git a/VEX/priv/host_s390_defs.c b/VEX/priv/host_s390_defs.c index 95a1167d5c..28b9cf8c04 100644 --- a/VEX/priv/host_s390_defs.c +++ b/VEX/priv/host_s390_defs.c @@ -3935,6 +3935,43 @@ s390_emit_SDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2) 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 @@ s390_insn_cond_move_emit(UChar *buf, const s390_insn *insn) 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. diff --git a/VEX/priv/host_s390_defs.h b/VEX/priv/host_s390_defs.h index d123f706dc..6d21d08688 100644 --- a/VEX/priv/host_s390_defs.h +++ b/VEX/priv/host_s390_defs.h @@ -694,6 +694,8 @@ extern UInt s390_host_hwcaps; (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 */ diff --git a/VEX/priv/main_main.c b/VEX/priv/main_main.c index 55e99c6cd2..4d98f51070 100644 --- a/VEX/priv/main_main.c +++ b/VEX/priv/main_main.c @@ -1260,7 +1260,7 @@ static const HChar* show_hwcaps_arm ( UInt hwcaps ) 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 @@ static const HChar* show_hwcaps_s390x ( UInt hwcaps ) { "etf3" }, { "stckf" }, { "fpext" }, + { "lscond" }, }; static HChar buf[sizeof facilities + sizeof prefix + 1]; static HChar *p; @@ -1300,6 +1301,8 @@ static const HChar* show_hwcaps_s390x ( UInt hwcaps ) 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) diff --git a/VEX/pub/libvex.h b/VEX/pub/libvex.h index 0167a4ff5f..d5c3483cae 100644 --- a/VEX/pub/libvex.h +++ b/VEX/pub/libvex.h @@ -133,6 +133,7 @@ typedef #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 @@ typedef VEX_HWCAPS_S390X_STFLE | \ VEX_HWCAPS_S390X_STCKF | \ VEX_HWCAPS_S390X_FPEXT | \ + VEX_HWCAPS_S390X_LSCOND| \ VEX_HWCAPS_S390X_ETF3 | \ VEX_HWCAPS_S390X_ETF2)