diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index 408e42b..2c77fc6 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -621,13 +621,12 @@ uint64_t HELPER(msdb)(CPUS390XState *env, uint64_t f1,
 }
 
 /* test data class 32-bit */
-uint32_t HELPER(tceb)(CPUS390XState *env, uint32_t f1, uint64_t m2)
+uint32_t HELPER(tceb)(uint64_t f1, uint64_t m2)
 {
-    float32 v1 = env->fregs[f1].l.upper;
+    float32 v1 = f1;
     int neg = float32_is_neg(v1);
     uint32_t cc = 0;
 
-    HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __func__, (long)v1, m2, neg);
     if ((float32_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
         (float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
         (float32_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
@@ -637,19 +636,16 @@ uint32_t HELPER(tceb)(CPUS390XState *env, uint32_t f1, uint64_t m2)
         /* assume normalized number */
         cc = 1;
     }
-
     /* FIXME: denormalized? */
     return cc;
 }
 
 /* test data class 64-bit */
-uint32_t HELPER(tcdb)(CPUS390XState *env, uint32_t f1, uint64_t m2)
+uint32_t HELPER(tcdb)(uint64_t v1, uint64_t m2)
 {
-    float64 v1 = env->fregs[f1].d;
     int neg = float64_is_neg(v1);
     uint32_t cc = 0;
 
-    HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __func__, v1, m2, neg);
     if ((float64_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
         (float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
         (float64_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
@@ -664,20 +660,16 @@ uint32_t HELPER(tcdb)(CPUS390XState *env, uint32_t f1, uint64_t m2)
 }
 
 /* test data class 128-bit */
-uint32_t HELPER(tcxb)(CPUS390XState *env, uint32_t f1, uint64_t m2)
+uint32_t HELPER(tcxb)(uint64_t ah, uint64_t al, uint64_t m2)
 {
-    CPU_QuadU v1;
+    float128 v1 = make_float128(ah, al);
+    int neg = float128_is_neg(v1);
     uint32_t cc = 0;
-    int neg;
-
-    v1.ll.upper = env->fregs[f1].ll;
-    v1.ll.lower = env->fregs[f1 + 2].ll;
 
-    neg = float128_is_neg(v1.q);
-    if ((float128_is_zero(v1.q) && (m2 & (1 << (11-neg)))) ||
-        (float128_is_infinity(v1.q) && (m2 & (1 << (5-neg)))) ||
-        (float128_is_any_nan(v1.q) && (m2 & (1 << (3-neg)))) ||
-        (float128_is_signaling_nan(v1.q) && (m2 & (1 << (1-neg))))) {
+    if ((float128_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
+        (float128_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
+        (float128_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
+        (float128_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
         cc = 1;
     } else if (m2 & (1 << (9-neg))) {
         /* assume normalized number */
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 5f31d96..739ad1f 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -89,9 +89,9 @@ DEF_HELPER_4(maeb, i64, env, i64, i64, i64)
 DEF_HELPER_4(madb, i64, env, i64, i64, i64)
 DEF_HELPER_4(mseb, i64, env, i64, i64, i64)
 DEF_HELPER_4(msdb, i64, env, i64, i64, i64)
-DEF_HELPER_FLAGS_3(tceb, TCG_CALL_PURE, i32, env, i32, i64)
-DEF_HELPER_FLAGS_3(tcdb, TCG_CALL_PURE, i32, env, i32, i64)
-DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_PURE, i32, env, i32, i64)
+DEF_HELPER_FLAGS_2(tceb, TCG_CALL_PURE | TCG_CALL_CONST, i32, i64, i64)
+DEF_HELPER_FLAGS_2(tcdb, TCG_CALL_PURE | TCG_CALL_CONST, i32, i64, i64)
+DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_PURE | TCG_CALL_CONST, i32, i64, i64, i64)
 DEF_HELPER_3(flogr, i32, env, i32, i64)
 DEF_HELPER_3(sqdbr, void, env, i32, i32)
 DEF_HELPER_FLAGS_1(cvd, TCG_CALL_PURE|TCG_CALL_CONST, i64, s32)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index 6cecf27..8fba8c7 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -531,6 +531,11 @@
 /* SUPERVISOR CALL */
     C(0x0a00, SVC,     I,     Z,   0, 0, 0, 0, svc, 0)
 
+/* TEST DATA CLASS */
+    C(0xed10, TCEB,    RXE,   Z,   e1, a2, 0, 0, tceb, 0)
+    C(0xed11, TCDB,    RXE,   Z,   f1_o, a2, 0, 0, tcdb, 0)
+    C(0xed12, TCXB,    RXE,   Z,   x1_o, a2, 0, 0, tcxb, 0)
+
 /* TEST UNDER MASK */
     C(0x9100, TM,      SI,    Z,   m1_8u, i2_8u, 0, 0, 0, tm32)
     C(0xeb51, TMY,     SIY,   LD,  m1_8u, i2_8u, 0, 0, 0, tm32)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 75f1ec8..7a329ca 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -985,38 +985,6 @@ static void free_compare(DisasCompare *c)
     }
 }
 
-static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2,
-                     int r1b)
-{
-    TCGv_i32 tmp_r1;
-    TCGv_i64 addr;
-    addr = get_address(s, x2, b2, d2);
-    tmp_r1 = tcg_const_i32(r1);
-    switch (op) {
-    case 0x10: /* TCEB   R1,D2(X2,B2)       [RXE] */
-        potential_page_fault(s);
-        gen_helper_tceb(cc_op, cpu_env, tmp_r1, addr);
-        set_cc_static(s);
-        break;
-    case 0x11: /* TCDB   R1,D2(X2,B2)       [RXE] */
-        potential_page_fault(s);
-        gen_helper_tcdb(cc_op, cpu_env, tmp_r1, addr);
-        set_cc_static(s);
-        break;
-    case 0x12: /* TCXB   R1,D2(X2,B2)       [RXE] */
-        potential_page_fault(s);
-        gen_helper_tcxb(cc_op, cpu_env, tmp_r1, addr);
-        set_cc_static(s);
-        break;
-    default:
-        LOG_DISAS("illegal ed operation 0x%x\n", op);
-        gen_illegal_opcode(s);
-        return;
-    }
-    tcg_temp_free_i32(tmp_r1);
-    tcg_temp_free_i64(addr);
-}
-
 static void disas_b2(DisasContext *s, int op, uint32_t insn)
 {
     TCGv_i64 tmp, tmp2, tmp3;
@@ -1597,7 +1565,7 @@ static void disas_s390_insn(DisasContext *s)
 {
     unsigned char opc;
     uint64_t insn;
-    int op, r1, r2, r3, d2, x2, b2, r1b;
+    int op, r1, r2, r3;
 
     opc = cpu_ldub_code(cpu_single_env, s->pc);
     LOG_DISAS("opc 0x%x\n", opc);
@@ -1623,17 +1591,6 @@ static void disas_s390_insn(DisasContext *s)
         op = (insn >> 16) & 0xff;
         disas_b9(s, op, r1, r2);
         break;
-    case 0xed:
-        insn = ld_code6(s->pc);
-        debug_insn(insn);
-        op = insn & 0xff;
-        r1 = (insn >> 36) & 0xf;
-        x2 = (insn >> 32) & 0xf;
-        b2 = (insn >> 28) & 0xf;
-        d2 = (short)((insn >> 16) & 0xfff);
-        r1b = (insn >> 12) & 0xf;
-        disas_ed(s, op, r1, x2, b2, d2, r1b);
-        break;
     default:
         qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%x\n", opc);
         gen_illegal_opcode(s);
@@ -3146,6 +3103,27 @@ static ExitStatus op_svc(DisasContext *s, DisasOps *o)
     return EXIT_NORETURN;
 }
 
+static ExitStatus op_tceb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_tceb(cc_op, o->in1, o->in2);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
+static ExitStatus op_tcdb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_tcdb(cc_op, o->in1, o->in2);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
+static ExitStatus op_tcxb(DisasContext *s, DisasOps *o)
+{
+    gen_helper_tcxb(cc_op, o->out, o->out2, o->in2);
+    set_cc_static(s);
+    return NO_EXIT;
+}
+
 #ifndef CONFIG_USER_ONLY
 static ExitStatus op_tprot(DisasContext *s, DisasOps *o)
 {
