diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 3c3a8f7..02e9cc0 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -173,6 +173,13 @@
     C(0xb914, LGFR,    RRE,   Z,   0, r2_32s, 0, r1, mov2, 0)
     C(0xe304, LG,      RXY_a, Z,   0, a2, r1, 0, ld64, 0)
     C(0xe314, LGF,     RXY_a, Z,   0, a2, r1, 0, ld32s, 0)
+    C(0x2800, LDR,     RR_a,  Z,   0, f2_o, 0, f1, mov2, 0)
+    C(0x6800, LD,      RX_a,  Z,   0, m2_64, 0, f1, mov2, 0)
+    C(0xed65, LDY,     RXY_a, LD,  0, m2_64, 0, f1, mov2, 0)
+    C(0x3800, LER,     RR_a,  Z,   0, e2, 0, cond_e1e2, mov2, 0)
+    C(0x7800, LE,      RX_a,  Z,   0, m2_32u, 0, e1, mov2, 0)
+    C(0xed64, LEY,     RXY_a, LD,  0, m2_32u, 0, e1, mov2, 0)
+    C(0xb365, LXR,     RRE,   Z,   0, x2_o, 0, x1, movx, 0)
 /* LOAD IMMEDIATE */
     C(0xc001, LGFI,    RIL_a, EI,  0, i2, 0, r1, mov2, 0)
 /* LOAD RELATIVE LONG */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 0752c67..c36ad44 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -222,6 +222,13 @@ static inline TCGv_i32 load_freg32(int reg)
     return r;
 }
 
+static inline TCGv_i64 load_freg32_i64(int reg)
+{
+    TCGv_i64 r = tcg_temp_new_i64();
+    tcg_gen_shri_i64(r, fregs[reg], 32);
+    return r;
+}
+
 static inline TCGv_i32 load_reg32(int reg)
 {
     TCGv_i32 r = tcg_temp_new_i32();
@@ -291,6 +298,11 @@ static inline void store_freg32(int reg, TCGv_i32 v)
 #endif
 }
 
+static inline void store_freg32_i64(int reg, TCGv_i64 v)
+{
+    tcg_gen_deposit_i64(fregs[reg], fregs[reg], v, 32, 32);
+}
+
 static inline void return_low128(TCGv_i64 dest)
 {
     tcg_gen_ld_i64(dest, cpu_env, offsetof(CPUS390XState, retxl));
@@ -2364,20 +2376,6 @@ static void disas_s390_insn(DisasContext *s)
     LOG_DISAS("opc 0x%x\n", opc);
 
     switch (opc) {
-    case 0x28: /* LDR    R1,R2               [RR] */
-        insn = ld_code2(s->pc);
-        decode_rr(s, insn, &r1, &r2);
-        tmp = load_freg(r2);
-        store_freg(r1, tmp);
-        tcg_temp_free_i64(tmp);
-        break;
-    case 0x38: /* LER    R1,R2               [RR] */
-        insn = ld_code2(s->pc);
-        decode_rr(s, insn, &r1, &r2);
-        tmp32_1 = load_freg32(r2);
-        store_freg32(r1, tmp32_1);
-        tcg_temp_free_i32(tmp32_1);
-        break;
     case 0x43: /* IC     R1,D2(X2,B2)     [RX] */
         insn = ld_code4(s->pc);
         tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -2420,15 +2418,6 @@ static void disas_s390_insn(DisasContext *s)
         tcg_temp_free_i64(tmp);
         tcg_temp_free_i64(tmp2);
         break;
-    case 0x68: /* LD    R1,D2(X2,B2)        [RX] */
-        insn = ld_code4(s->pc);
-        tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
-        tmp2 = tcg_temp_new_i64();
-        tcg_gen_qemu_ld64(tmp2, tmp, get_mem_index(s));
-        store_freg(r1, tmp2);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        break;
     case 0x70: /* STE R1,D2(X2,B2) [RX] */
         insn = ld_code4(s->pc);
         tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
@@ -2440,18 +2429,6 @@ static void disas_s390_insn(DisasContext *s)
         tcg_temp_free_i64(tmp2);
         tcg_temp_free_i32(tmp32_1);
         break;
-    case 0x78: /* LE     R1,D2(X2,B2)        [RX] */
-        insn = ld_code4(s->pc);
-        tmp = decode_rx(s, insn, &r1, &x2, &b2, &d2);
-        tmp2 = tcg_temp_new_i64();
-        tmp32_1 = tcg_temp_new_i32();
-        tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s));
-        tcg_gen_trunc_i64_i32(tmp32_1, tmp2);
-        store_freg32(r1, tmp32_1);
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i32(tmp32_1);
-        break;
 #ifndef CONFIG_USER_ONLY
     case 0x80: /* SSM      D2(B2)       [S] */
         /* Set System Mask */
@@ -3543,6 +3520,18 @@ static ExitStatus op_mov2(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_movx(DisasContext *s, DisasOps *o)
+{
+    o->out = o->in1;
+    o->out2 = o->in2;
+    o->g_out = o->g_in1;
+    o->g_out2 = o->g_in2;
+    TCGV_UNUSED_I64(o->in1);
+    TCGV_UNUSED_I64(o->in2);
+    o->g_in1 = o->g_in2 = false;
+    return NO_EXIT;
+}
+
 static ExitStatus op_mvcl(DisasContext *s, DisasOps *o)
 {
     TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1));
@@ -3902,6 +3891,23 @@ static void wout_r1_D32(DisasContext *s, DisasFields *f, DisasOps *o)
     store_reg32_i64(r1, o->out);
 }
 
+static void wout_e1(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    store_freg32_i64(get_field(f, r1), o->out);
+}
+
+static void wout_f1(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    store_freg(get_field(f, r1), o->out);
+}
+
+static void wout_x1(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    int f1 = get_field(s->fields, r1);
+    store_freg(f1, o->out);
+    store_freg((f1 + 2) & 15, o->out2);
+}
+
 static void wout_cond_r1r2_32(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     if (get_field(f, r1) != get_field(f, r2)) {
@@ -3909,6 +3915,13 @@ static void wout_cond_r1r2_32(DisasContext *s, DisasFields *f, DisasOps *o)
     }
 }
 
+static void wout_cond_e1e2(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    if (get_field(f, r1) != get_field(f, r2)) {
+        store_freg32_i64(get_field(f, r1), o->out);
+    }
+}
+
 static void wout_m1_32(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     tcg_gen_qemu_st32(o->out, o->addr1, get_mem_index(s));
@@ -4084,6 +4097,25 @@ static void in2_r2_32u(DisasContext *s, DisasFields *f, DisasOps *o)
     tcg_gen_ext32u_i64(o->in2, regs[get_field(f, r2)]);
 }
 
+static void in2_e2(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in2 = load_freg32_i64(get_field(f, r2));
+}
+
+static void in2_f2_o(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    o->in2 = fregs[get_field(f, r2)];
+    o->g_in2 = true;
+}
+
+static void in2_x2_o(DisasContext *s, DisasFields *f, DisasOps *o)
+{
+    int f2 = get_field(f, r2);
+    o->in1 = fregs[f2];
+    o->in2 = fregs[(f2 + 2) & 15];
+    o->g_in1 = o->g_in2 = true;
+}
+
 static void in2_a2(DisasContext *s, DisasFields *f, DisasOps *o)
 {
     int x2 = have_field(f, x2) ? get_field(f, x2) : 0;
