s390x: reconsider "long displacement" requirement.  We currently
require that the host supports accessing memory using long
displacement. On older machines e.g. z900 that is an expensive
operation, because it is millicoded. It would be a performance win to
relax that requirement.  (VEX side changes.)  See #268620.
(Florian Krohm, britzel@acm.org)



git-svn-id: svn://svn.valgrind.org/vex/trunk@2126 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/priv/host_s390_defs.c b/priv/host_s390_defs.c
index 3e0eaf7..17cc737 100644
--- a/priv/host_s390_defs.c
+++ b/priv/host_s390_defs.c
@@ -265,8 +265,6 @@
 {
    if (fits_unsigned_12bit(offset))
       return s390_amode_b12(offset, s390_hreg_guest_state_pointer());
-   if (fits_signed_20bit(offset))
-      return s390_amode_b20(offset, s390_hreg_guest_state_pointer());
 
    vpanic("invalid guest state offset");
 }
@@ -1142,6 +1140,8 @@
 static UChar *
 s390_emit_AY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "ay", r1, dh2, dl2, x2, b2);
 
@@ -1152,6 +1152,8 @@
 static UChar *
 s390_emit_AG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp || dh2 == 0);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "ag", r1, dh2, dl2, x2, b2);
 
@@ -1162,6 +1164,8 @@
 static UChar *
 s390_emit_AFI(UChar *p, UChar r1, UInt i2)
 {
+   vassert(s390_host_has_eimm);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, INT), "afi", r1, i2);
 
@@ -1172,6 +1176,8 @@
 static UChar *
 s390_emit_AGFI(UChar *p, UChar r1, UInt i2)
 {
+   vassert(s390_host_has_eimm);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, INT), "agfi", r1, i2);
 
@@ -1192,6 +1198,8 @@
 static UChar *
 s390_emit_AHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "ahy", r1, dh2, dl2, x2, b2);
 
@@ -1252,6 +1260,8 @@
 static UChar *
 s390_emit_NY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "ny", r1, dh2, dl2, x2, b2);
 
@@ -1262,6 +1272,8 @@
 static UChar *
 s390_emit_NG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp || dh2 == 0);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "ng", r1, dh2, dl2, x2, b2);
 
@@ -1272,6 +1284,8 @@
 static UChar *
 s390_emit_NIHF(UChar *p, UChar r1, UInt i2)
 {
+   vassert(s390_host_has_eimm);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, UINT), "nihf", r1, i2);
 
@@ -1282,6 +1296,8 @@
 static UChar *
 s390_emit_NILF(UChar *p, UChar r1, UInt i2)
 {
+   vassert(s390_host_has_eimm);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, UINT), "nilf", r1, i2);
 
@@ -1362,6 +1378,8 @@
 static UChar *
 s390_emit_CY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "cy", r1, dh2, dl2, x2, b2);
 
@@ -1372,6 +1390,8 @@
 static UChar *
 s390_emit_CG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp || dh2 == 0);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "cg", r1, dh2, dl2, x2, b2);
 
@@ -1382,6 +1402,8 @@
 static UChar *
 s390_emit_CFI(UChar *p, UChar r1, UInt i2)
 {
+   vassert(s390_host_has_eimm);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, INT), "cfi", r1, i2);
 
@@ -1402,6 +1424,8 @@
 static UChar *
 s390_emit_CSY(UChar *p, UChar r1, UChar r3, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC4(MNM, GPR, GPR, SDXB), "csy", r1, r3, dh2, dl2, 0, b2);
 
@@ -1412,6 +1436,8 @@
 static UChar *
 s390_emit_CSG(UChar *p, UChar r1, UChar r3, 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, GPR, SDXB), "csg", r1, r3, dh2, dl2, 0, b2);
 
@@ -1452,6 +1478,8 @@
 static UChar *
 s390_emit_CLY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "cly", r1, dh2, dl2, x2, b2);
 
@@ -1462,6 +1490,8 @@
 static UChar *
 s390_emit_CLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp || dh2 == 0);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "clg", r1, dh2, dl2, x2, b2);
 
@@ -1472,6 +1502,8 @@
 static UChar *
 s390_emit_CLFI(UChar *p, UChar r1, UInt i2)
 {
+   vassert(s390_host_has_eimm);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, UINT), "clfi", r1, i2);
 
@@ -1522,6 +1554,8 @@
 static UChar *
 s390_emit_DL(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp || dh2 == 0);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "dl", r1, dh2, dl2, x2, b2);
 
@@ -1532,6 +1566,8 @@
 static UChar *
 s390_emit_DLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp || dh2 == 0);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "dlg", r1, dh2, dl2, x2, b2);
 
@@ -1552,6 +1588,8 @@
 static UChar *
 s390_emit_DSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp || dh2 == 0);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "dsg", r1, dh2, dl2, x2, b2);
 
@@ -1592,6 +1630,8 @@
 static UChar *
 s390_emit_XY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "xy", r1, dh2, dl2, x2, b2);
 
@@ -1602,6 +1642,8 @@
 static UChar *
 s390_emit_XG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp || dh2 == 0);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "xg", r1, dh2, dl2, x2, b2);
 
@@ -1612,6 +1654,8 @@
 static UChar *
 s390_emit_XIHF(UChar *p, UChar r1, UInt i2)
 {
+   vassert(s390_host_has_eimm);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, UINT), "xihf", r1, i2);
 
@@ -1622,6 +1666,8 @@
 static UChar *
 s390_emit_XILF(UChar *p, UChar r1, UInt i2)
 {
+   vassert(s390_host_has_eimm);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, UINT), "xilf", r1, i2);
 
@@ -1632,6 +1678,8 @@
 static UChar *
 s390_emit_FLOGR(UChar *p, UChar r1, UChar r2)
 {
+   vassert(s390_host_has_eimm);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, GPR), "flogr", r1, r2);
 
@@ -1652,6 +1700,8 @@
 static UChar *
 s390_emit_ICY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "icy", r1, dh2, dl2, x2, b2);
 
@@ -1662,6 +1712,8 @@
 static UChar *
 s390_emit_IIHF(UChar *p, UChar r1, UInt i2)
 {
+   vassert(s390_host_has_eimm);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, UINT), "iihf", r1, i2);
 
@@ -1692,6 +1744,8 @@
 static UChar *
 s390_emit_IILF(UChar *p, UChar r1, UInt i2)
 {
+   vassert(s390_host_has_eimm);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, UINT), "iilf", r1, i2);
 
@@ -1772,6 +1826,8 @@
 static UChar *
 s390_emit_LY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "ly", r1, dh2, dl2, x2, b2);
 
@@ -1782,6 +1838,8 @@
 static UChar *
 s390_emit_LG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp || dh2 == 0);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "lg", r1, dh2, dl2, x2, b2);
 
@@ -1792,6 +1850,8 @@
 static UChar *
 s390_emit_LGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp || dh2 == 0);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "lgf", r1, dh2, dl2, x2, b2);
 
@@ -1802,6 +1862,8 @@
 static UChar *
 s390_emit_LGFI(UChar *p, UChar r1, UInt i2)
 {
+   vassert(s390_host_has_eimm);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, INT), "lgfi", r1, i2);
 
@@ -1832,6 +1894,8 @@
 static UChar *
 s390_emit_LT(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_eimm);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "lt", r1, dh2, dl2, x2, b2);
 
@@ -1842,6 +1906,8 @@
 static UChar *
 s390_emit_LTG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_eimm);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "ltg", r1, dh2, dl2, x2, b2);
 
@@ -1852,6 +1918,8 @@
 static UChar *
 s390_emit_LBR(UChar *p, UChar r1, UChar r2)
 {
+   vassert(s390_host_has_eimm);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, GPR), "lbr", r1, r2);
 
@@ -1862,6 +1930,8 @@
 static UChar *
 s390_emit_LGBR(UChar *p, UChar r1, UChar r2)
 {
+   vassert(s390_host_has_eimm);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, GPR), "lgbr", r1, r2);
 
@@ -1872,6 +1942,8 @@
 static UChar *
 s390_emit_LB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "lb", r1, dh2, dl2, x2, b2);
 
@@ -1882,6 +1954,8 @@
 static UChar *
 s390_emit_LGB(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "lgb", r1, dh2, dl2, x2, b2);
 
@@ -1912,6 +1986,8 @@
 static UChar *
 s390_emit_LHR(UChar *p, UChar r1, UChar r2)
 {
+   vassert(s390_host_has_eimm);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, GPR), "lhr", r1, r2);
 
@@ -1922,6 +1998,8 @@
 static UChar *
 s390_emit_LGHR(UChar *p, UChar r1, UChar r2)
 {
+   vassert(s390_host_has_eimm);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, GPR), "lghr", r1, r2);
 
@@ -1942,6 +2020,8 @@
 static UChar *
 s390_emit_LHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "lhy", r1, dh2, dl2, x2, b2);
 
@@ -1952,6 +2032,8 @@
 static UChar *
 s390_emit_LGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp || dh2 == 0);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "lgh", r1, dh2, dl2, x2, b2);
 
@@ -1992,6 +2074,8 @@
 static UChar *
 s390_emit_LLGF(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp || dh2 == 0);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "llgf", r1, dh2, dl2, x2, b2);
 
@@ -2002,6 +2086,8 @@
 static UChar *
 s390_emit_LLCR(UChar *p, UChar r1, UChar r2)
 {
+   vassert(s390_host_has_eimm);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, GPR), "llcr", r1, r2);
 
@@ -2012,6 +2098,8 @@
 static UChar *
 s390_emit_LLGCR(UChar *p, UChar r1, UChar r2)
 {
+   vassert(s390_host_has_eimm);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, GPR), "llgcr", r1, r2);
 
@@ -2022,6 +2110,8 @@
 static UChar *
 s390_emit_LLC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_eimm);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "llc", r1, dh2, dl2, x2, b2);
 
@@ -2032,6 +2122,8 @@
 static UChar *
 s390_emit_LLGC(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp || dh2 == 0);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "llgc", r1, dh2, dl2, x2, b2);
 
@@ -2042,6 +2134,8 @@
 static UChar *
 s390_emit_LLHR(UChar *p, UChar r1, UChar r2)
 {
+   vassert(s390_host_has_eimm);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, GPR), "llhr", r1, r2);
 
@@ -2052,6 +2146,8 @@
 static UChar *
 s390_emit_LLGHR(UChar *p, UChar r1, UChar r2)
 {
+   vassert(s390_host_has_eimm);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, GPR), "llghr", r1, r2);
 
@@ -2062,6 +2158,8 @@
 static UChar *
 s390_emit_LLH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_eimm);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "llh", r1, dh2, dl2, x2, b2);
 
@@ -2072,6 +2170,8 @@
 static UChar *
 s390_emit_LLGH(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp || dh2 == 0);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "llgh", r1, dh2, dl2, x2, b2);
 
@@ -2082,6 +2182,8 @@
 static UChar *
 s390_emit_LLILF(UChar *p, UChar r1, UInt i2)
 {
+   vassert(s390_host_has_eimm);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, UINT), "llilf", r1, i2);
 
@@ -2132,6 +2234,8 @@
 static UChar *
 s390_emit_MFY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_gie);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "mfy", r1, dh2, dl2, x2, b2);
 
@@ -2152,6 +2256,8 @@
 static UChar *
 s390_emit_MHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_gie);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "mhy", r1, dh2, dl2, x2, b2);
 
@@ -2192,6 +2298,8 @@
 static UChar *
 s390_emit_ML(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp || dh2 == 0);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "ml", r1, dh2, dl2, x2, b2);
 
@@ -2202,6 +2310,8 @@
 static UChar *
 s390_emit_MLG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp || dh2 == 0);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "mlg", r1, dh2, dl2, x2, b2);
 
@@ -2242,6 +2352,8 @@
 static UChar *
 s390_emit_MSY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "msy", r1, dh2, dl2, x2, b2);
 
@@ -2252,6 +2364,8 @@
 static UChar *
 s390_emit_MSG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp || dh2 == 0);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "msg", r1, dh2, dl2, x2, b2);
 
@@ -2262,6 +2376,8 @@
 static UChar *
 s390_emit_MSFI(UChar *p, UChar r1, UInt i2)
 {
+   vassert(s390_host_has_gie);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, INT), "msfi", r1, i2);
 
@@ -2272,6 +2388,8 @@
 static UChar *
 s390_emit_MSGFI(UChar *p, UChar r1, UInt i2)
 {
+   vassert(s390_host_has_gie);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, INT), "msgfi", r1, i2);
 
@@ -2312,6 +2430,8 @@
 static UChar *
 s390_emit_OY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "oy", r1, dh2, dl2, x2, b2);
 
@@ -2322,6 +2442,8 @@
 static UChar *
 s390_emit_OG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp || dh2 == 0);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "og", r1, dh2, dl2, x2, b2);
 
@@ -2332,6 +2454,8 @@
 static UChar *
 s390_emit_OIHF(UChar *p, UChar r1, UInt i2)
 {
+   vassert(s390_host_has_eimm);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, UINT), "oihf", r1, i2);
 
@@ -2342,6 +2466,8 @@
 static UChar *
 s390_emit_OILF(UChar *p, UChar r1, UInt i2)
 {
+   vassert(s390_host_has_eimm);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, UINT), "oilf", r1, i2);
 
@@ -2372,6 +2498,8 @@
 static UChar *
 s390_emit_SLLG(UChar *p, UChar r1, UChar r3, 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, GPR, SDXB), "sllg", r1, r3, dh2, dl2, 0, b2);
 
@@ -2392,6 +2520,8 @@
 static UChar *
 s390_emit_SRAG(UChar *p, UChar r1, UChar r3, 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, GPR, SDXB), "srag", r1, r3, dh2, dl2, 0, b2);
 
@@ -2412,6 +2542,8 @@
 static UChar *
 s390_emit_SRLG(UChar *p, UChar r1, UChar r3, 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, GPR, SDXB), "srlg", r1, r3, dh2, dl2, 0, b2);
 
@@ -2432,6 +2564,8 @@
 static UChar *
 s390_emit_STY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "sty", r1, dh2, dl2, x2, b2);
 
@@ -2442,6 +2576,8 @@
 static UChar *
 s390_emit_STG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp || dh2 == 0);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "stg", r1, dh2, dl2, x2, b2);
 
@@ -2462,6 +2598,8 @@
 static UChar *
 s390_emit_STCY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "stcy", r1, dh2, dl2, x2, b2);
 
@@ -2482,6 +2620,8 @@
 static UChar *
 s390_emit_STHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "sthy", r1, dh2, dl2, x2, b2);
 
@@ -2522,6 +2662,8 @@
 static UChar *
 s390_emit_SY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "sy", r1, dh2, dl2, x2, b2);
 
@@ -2532,6 +2674,8 @@
 static UChar *
 s390_emit_SG(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp || dh2 == 0);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "sg", r1, dh2, dl2, x2, b2);
 
@@ -2552,6 +2696,8 @@
 static UChar *
 s390_emit_SHY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, SDXB), "shy", r1, dh2, dl2, x2, b2);
 
@@ -2562,6 +2708,8 @@
 static UChar *
 s390_emit_SLFI(UChar *p, UChar r1, UInt i2)
 {
+   vassert(s390_host_has_eimm);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, UINT), "slfi", r1, i2);
 
@@ -2612,6 +2760,8 @@
 static UChar *
 s390_emit_LEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, FPR, SDXB), "ley", r1, dh2, dl2, x2, b2);
 
@@ -2622,6 +2772,8 @@
 static UChar *
 s390_emit_LDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, FPR, SDXB), "ldy", r1, dh2, dl2, x2, b2);
 
@@ -2642,6 +2794,7 @@
 static UChar *
 s390_emit_LDGR(UChar *p, UChar r1, UChar r2)
 {
+   /* fixs390: PR 268619 */
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, FPR, GPR), "ldgr", r1, r2);
 
@@ -2652,6 +2805,7 @@
 static UChar *
 s390_emit_LGDR(UChar *p, UChar r1, UChar r2)
 {
+   /* fixs390: PR 268619 */
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, GPR, FPR), "lgdr", r1, r2);
 
@@ -2712,6 +2866,8 @@
 static UChar *
 s390_emit_STEY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, FPR, SDXB), "stey", r1, dh2, dl2, x2, b2);
 
@@ -2722,6 +2878,8 @@
 static UChar *
 s390_emit_STDY(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
 {
+   vassert(s390_host_has_ldisp);
+
    if (unlikely(vex_traceflags & VEX_TRACE_ASM))
       s390_disasm(ENC3(MNM, FPR, SDXB), "stdy", r1, dh2, dl2, x2, b2);
 
@@ -3423,6 +3581,22 @@
 }
 
 
+/* r1[32:63] = sign_extend(mem[op2addr][0:7]) */
+static UChar *
+s390_emit_LBw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
+{
+   vassert(s390_host_has_ldisp || dh2 == 0);
+
+   if (s390_host_has_ldisp) {
+      return s390_emit_LB(p, r1, x2, b2, dl2, dh2);
+   }
+
+   p = s390_emit_IC(p, r1, x2, b2, dl2);    /* r1[56:63] = mem[op2addr][0:7] */
+   p = s390_emit_SLL(p, r1, R0, 24);        /* r1 = r1 << 24  */
+   return s390_emit_SRA(p, r1, R0, 24);     /* r1 = r1 >>a 24 */
+}
+
+
 /*  r1[32:63] = sign_extend(r2[56:63]) */
 static UChar *
 s390_emit_LBRw(UChar *p, UChar r1, UChar r2)
@@ -3437,6 +3611,22 @@
 }
 
 
+/* r1[0:63] = sign_extend(mem[op2addr][0:7]) */
+static UChar *
+s390_emit_LGBw(UChar *p, UChar r1, UChar x2, UChar b2, UShort dl2, UChar dh2)
+{
+   vassert(s390_host_has_ldisp || dh2 == 0);
+
+   if (s390_host_has_ldisp) {
+      return s390_emit_LGB(p, r1, x2, b2, dl2, dh2);
+   }
+
+   p = s390_emit_IC(p, r1, x2, b2, dl2);             /* r1[56:63] = mem[op2addr][0:7] */
+   p = s390_emit_SLLG(p, r1, r1, R0, DISP20(56));    /* r1 = r1 << 56  */
+   return s390_emit_SRAG(p, r1, r1, R0, DISP20(56)); /* r1 = r1 >>a 56 */
+}
+
+
 /*  r1[0:63] = sign_extend(r2[56:63]) */
 static UChar *
 s390_emit_LGBRw(UChar *p, UChar r1, UChar r2)
@@ -4861,9 +5051,9 @@
          return s390_emit_LDR(buf, dst, src);
    } else {
       if (dst_class == HRcFlt64 && src_class == HRcInt64)
-         return s390_emit_LDGR(buf, dst, src);
+         return s390_emit_LDGR(buf, dst, src);   /* fixs390: PR 268619 */
       if (dst_class == HRcInt64 && src_class == HRcFlt64)
-         return s390_emit_LGDR(buf, dst, src);
+         return s390_emit_LGDR(buf, dst, src);   /* fixs390: PR 268619 */
       /* A move between floating point registers and general purpose
          registers of different size should never occur and indicates
          an error elsewhere. */
@@ -4968,6 +5158,8 @@
 
       /* Shift operands are special here as there are no opcodes that
          allow a memory operand. So we first load the 2nd operand to R0. */
+
+      /* fixs390: NO. Using R0 as the base will ignore the register contents. */
       if (insn->variant.alu.tag == S390_ALU_LSH ||
           insn->variant.alu.tag == S390_ALU_RSH ||
           insn->variant.alu.tag == S390_ALU_RSHA) {
@@ -5245,6 +5437,11 @@
             buf = s390_emit_load_64imm(buf, R0, value);
             return s390_emit_XGR(buf, dst, R0);
 
+            /* No special considerations for long displacement here. Only the six
+               least significant bits of VALUE will be taken; all other bits are
+               ignored. So the DH2 bits are irrelevant and do not influence the
+               shift operation, independent of whether long-displacement is available
+               or not. */
          case S390_ALU_LSH:  return s390_emit_SLLG(buf, dst, dst, 0, DISP20(value));
          case S390_ALU_RSH:  return s390_emit_SRLG(buf, dst, dst, 0, DISP20(value));
          case S390_ALU_RSHA: return s390_emit_SRAG(buf, dst, dst, 0, DISP20(value));
@@ -5328,15 +5525,14 @@
       case 1:
          if (insn->size == 4 || insn->size == 2) {
             if (sign_extend)
-               return s390_emit_LB(buf, r1, x, b, DISP20(d));
+               return s390_emit_LBw(buf, r1, x, b, DISP20(d));
             else
                return s390_emit_LLCw(buf, r1, x, b, DISP20(d));
          }
          if (insn->size == 8) {
             if (sign_extend)
-               return s390_emit_LGB(buf, r1, x, b, DISP20(d));
+               return s390_emit_LGBw(buf, r1, x, b, DISP20(d));
             else
-               /* No wrapper required. Opcode exists as RXE and RXY */
                return s390_emit_LLGC(buf, r1, x, b, DISP20(d));
          }
          goto fail;
@@ -5358,7 +5554,6 @@
             goto fail;
          }
          if (insn->size == 8) {  /* 16 --> 64 */
-            /* No wrappers required. Opcodes exist as RXE and RXY */
             if (sign_extend)
                return s390_emit_LGH(buf, r1, x, b, DISP20(d));
             else
@@ -5368,7 +5563,6 @@
 
       case 4:
          if (insn->size == 8) {  /* 32 --> 64 */
-            /* No wrappers required. Opcodes exist as RXE and RXY */
             if (sign_extend)
                return s390_emit_LGF(buf, r1, x, b, DISP20(d));
             else
diff --git a/priv/host_s390_defs.h b/priv/host_s390_defs.h
index 9781258..e409bd5 100644
--- a/priv/host_s390_defs.h
+++ b/priv/host_s390_defs.h
@@ -483,6 +483,8 @@
 extern const VexArchInfo *s390_archinfo_host;
 
 /* Convenience macros to test installed facilities */
+#define s390_host_has_ldisp \
+                      (s390_archinfo_host->hwcaps & (VEX_HWCAPS_S390X_LDISP))
 #define s390_host_has_eimm \
                       (s390_archinfo_host->hwcaps & (VEX_HWCAPS_S390X_EIMM))
 #define s390_host_has_gie \
diff --git a/priv/host_s390_isel.c b/priv/host_s390_isel.c
index 80e5759..beb03b3 100644
--- a/priv/host_s390_isel.c
+++ b/priv/host_s390_isel.c
@@ -227,7 +227,9 @@
          if (ulong_fits_unsigned_12bit(value)) {
             return s390_amode_b12((Int)value, s390_isel_int_expr(env, arg1));
          }
-         if (ulong_fits_signed_20bit(value)) {
+         /* If long-displacement is not available, do not construct B20 or
+            BX20 amodes because code generation cannot handle them. */
+         if (s390_host_has_ldisp && ulong_fits_signed_20bit(value)) {
             return s390_amode_b20((Int)value, s390_isel_int_expr(env, arg1));
          }
       }
@@ -2350,9 +2352,8 @@
    /* KLUDGE: export archinfo_host. */
    s390_archinfo_host = archinfo_host;
 
-
    /* Do some sanity checks */
-   vassert((hwcaps_host & ~(VEX_HWCAPS_S390X_ALL)) == 0);
+   vassert((VEX_HWCAPS_S390X(hwcaps_host) & ~(VEX_HWCAPS_S390X_ALL)) == 0);
 
    /* Make up an initial environment to use. */
    env = LibVEX_Alloc(sizeof(ISelEnv));
diff --git a/priv/main_main.c b/priv/main_main.c
index 4a4d2c9..989bb6c 100644
--- a/priv/main_main.c
+++ b/priv/main_main.c
@@ -934,6 +934,8 @@
    const UInt GE = VEX_HWCAPS_S390X_GIE;
    const UInt DF = VEX_HWCAPS_S390X_DFP;
 
+   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";
@@ -943,7 +945,7 @@
    if (hwcaps == (LD|GE|DF))    return "s390x-ldisp-gie-dfp";
    if (hwcaps == (LD|EI|GE|DF)) return "s390x-ldisp-eimm-gie-dfp";
 
-   return NULL;
+   return "s390-zarch";
 }
 
 /* ---- */
diff --git a/pub/libvex.h b/pub/libvex.h
index 84a55a8..e7f94e1 100644
--- a/pub/libvex.h
+++ b/pub/libvex.h
@@ -94,18 +94,45 @@
 #define VEX_HWCAPS_PPC64_GX    (1<<14) /* Graphics extns
                                           (fres,frsqrte,fsel,stfiwx) */
 
-/* s390x: baseline capability is z/Architecture with long displacement */
-#define VEX_HWCAPS_S390X_LDISP (1<<13)  /* Long-displacement facility */
-#define VEX_HWCAPS_S390X_EIMM  (1<<14)  /* Extended-immediate facility */
-#define VEX_HWCAPS_S390X_GIE   (1<<15)  /* General-instruction-extension
-                                           facility */
-#define VEX_HWCAPS_S390X_DFP   (1<<16)  /* Decimal floating point facility */
+/* s390x: Hardware capability encoding
+
+   Bits    Information
+   [26:31] Machine model
+   [25]    Long displacement facility
+   [24]    Extended-immediate facility
+   [23]    General-instruction-extension facility
+   [22]    Decimal floating point facility
+   [0:21]  Currently unused; reserved for future use
+*/
+
+/* Model numbers must be assigned in chronological order.
+   They are used as array index. */
+#define VEX_S390X_MODEL_Z900     0
+#define VEX_S390X_MODEL_Z800     1
+#define VEX_S390X_MODEL_Z990     2
+#define VEX_S390X_MODEL_Z890     3
+#define VEX_S390X_MODEL_Z9_EC    4
+#define VEX_S390X_MODEL_Z9_BC    5
+#define VEX_S390X_MODEL_Z10_EC   6
+#define VEX_S390X_MODEL_Z10_BC   7
+#define VEX_S390X_MODEL_Z196     8
+#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 */
+
 /* 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)
 
+#define VEX_HWCAPS_S390X(x)  ((x) & ~VEX_S390X_MODEL_MASK)
+#define VEX_S390X_MODEL(x)   ((x) &  VEX_S390X_MODEL_MASK)
+
 /* arm: baseline capability is ARMv4 */
 /* Bits 5:0 - architecture level (e.g. 5 for v5, 6 for v6 etc) */
 #define VEX_HWCAPS_ARM_VFP    (1<<6)  /* VFP extension */