diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index b6cc45b..4f5a29f 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -578,3 +578,20 @@ uint64_t HELPER(sqxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
     handle_exceptions(env, GETPC());
     return RET128(ret);
 }
+
+/* set fpc */
+void HELPER(sfpc)(CPUS390XState *env, uint64_t fpc)
+{
+    static const int rnd[4] = {
+        float_round_nearest_even,
+        float_round_to_zero,
+        float_round_up,
+        float_round_down
+    };
+
+    /* Install everything in the main FPC.  */
+    env->fpc = fpc;
+
+    /* Install the rounding mode in the shadow fpu_status.  */
+    set_float_rounding_mode(rnd[fpc & 3], &env->fpu_status);
+}
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 0ba0342..29f1565 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -120,6 +120,7 @@ DEF_HELPER_FLAGS_1(ptlb, TCG_CALL_CONST, void, env)
 DEF_HELPER_2(lra, i64, env, i64)
 DEF_HELPER_3(stura, void, env, i64, i32)
 DEF_HELPER_3(cksm, void, env, i32, i32)
+DEF_HELPER_FLAGS_2(sfpc, TCG_CALL_CONST, void, env, i64)
 
 DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_PURE|TCG_CALL_CONST,
                    i32, env, i32, i64, i64, i64)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index f08a37e..652c7ad 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -351,6 +351,9 @@
     C(0xb375, LZDR,    RRE,   Z,   0, 0, 0, f1, zero, 0)
     C(0xb376, LZXR,    RRE,   Z,   0, 0, 0, x1, zero2, 0)
 
+/* LOAD FPC */
+    C(0xb29d, LFPC,    S,     Z,   0, m2_32u, 0, 0, sfpc, 0)
+
 /* LOAD LENGTHENED */
     C(0xb304, LDEBR,   RRE,   Z,   0, e2, f1, 0, ldeb, 0)
     C(0xb305, LXDBR,   RRE,   Z,   0, f2_o, x1, 0, lxdb, 0)
@@ -455,6 +458,9 @@
     C(0xeb1d, RLL,     RSY_a, Z,   r3_o, sh32, new, r1_32, rll32, 0)
     C(0xeb1c, RLLG,    RSY_a, Z,   r3_o, sh64, r1, 0, rll64, 0)
 
+/* SET FPC */
+    C(0xb384, SFPC,    RRE,   Z,   0, r1_o, 0, 0, sfpc, 0)
+
 /* SHIFT LEFT SINGLE */
     D(0x8b00, SLA,     RS_a,  Z,   r1, sh32, new, r1_32, sla, 0, 31)
     D(0xebdd, SLAK,    RSY_a, DO,  r3, sh32, new, r1_32, sla, 0, 31)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index f07bed1..4fbade5 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1334,18 +1334,6 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
         tcg_temp_free_i32(tmp32_1);
         tcg_temp_free_i32(tmp32_2);
         break;
-    case 0x9d: /* LFPC      D2(B2)   [S] */
-        decode_rs(s, insn, &r1, &r3, &b2, &d2);
-        tmp = get_address(s, 0, 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);
-        tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
-        tcg_temp_free_i64(tmp);
-        tcg_temp_free_i64(tmp2);
-        tcg_temp_free_i32(tmp32_1);
-        break;
     case 0xb1: /* STFL     D2(B2)     [S] */
         /* Store Facility List (CPU features) at 200 */
         check_privileged(s);
@@ -1391,46 +1379,11 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn)
     }
 }
 
-static void disas_b3(DisasContext *s, int op, int m3, int r1, int r2)
-{
-    TCGv_i32 tmp32_1;
-    LOG_DISAS("disas_b3: op 0x%x m3 0x%x r1 %d r2 %d\n", op, m3, r1, r2);
-#define FP_HELPER(i) \
-    tmp32_1 = tcg_const_i32(r1); \
-    tmp32_2 = tcg_const_i32(r2); \
-    gen_helper_ ## i(cpu_env, tmp32_1, tmp32_2); \
-    tcg_temp_free_i32(tmp32_1); \
-    tcg_temp_free_i32(tmp32_2);
-
-#define FP_HELPER_CC(i) \
-    tmp32_1 = tcg_const_i32(r1); \
-    tmp32_2 = tcg_const_i32(r2); \
-    gen_helper_ ## i(cc_op, cpu_env, tmp32_1, tmp32_2); \
-    set_cc_static(s); \
-    tcg_temp_free_i32(tmp32_1); \
-    tcg_temp_free_i32(tmp32_2);
-
-    switch (op) {
-    case 0x84: /* SFPC        R1                [RRE] */
-        tmp32_1 = load_reg32(r1);
-        tcg_gen_st_i32(tmp32_1, cpu_env, offsetof(CPUS390XState, fpc));
-        tcg_temp_free_i32(tmp32_1);
-        break;
-    default:
-        LOG_DISAS("illegal b3 operation 0x%x\n", op);
-        gen_illegal_opcode(s);
-        break;
-    }
-
-#undef FP_HELPER_CC
-#undef FP_HELPER
-}
-
 static void disas_s390_insn(DisasContext *s)
 {
     unsigned char opc;
     uint64_t insn;
-    int op, r1, r2, r3;
+    int op;
 
     opc = cpu_ldub_code(cpu_single_env, s->pc);
     LOG_DISAS("opc 0x%x\n", opc);
@@ -1441,14 +1394,6 @@ static void disas_s390_insn(DisasContext *s)
         op = (insn >> 16) & 0xff;
         disas_b2(s, op, insn);
         break;
-    case 0xb3:
-        insn = ld_code4(s->pc);
-        op = (insn >> 16) & 0xff;
-        r3 = (insn >> 12) & 0xf; /* aka m3 */
-        r1 = (insn >> 4) & 0xf;
-        r2 = insn & 0xf;
-        disas_b3(s, op, r3, r1, r2);
-        break;
     default:
         qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%x\n", opc);
         gen_illegal_opcode(s);
@@ -2919,6 +2864,12 @@ static ExitStatus op_srl(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_sfpc(DisasContext *s, DisasOps *o)
+{
+    gen_helper_sfpc(cpu_env, o->in2);
+    return NO_EXIT;
+}
+
 #ifndef CONFIG_USER_ONLY
 static ExitStatus op_ssm(DisasContext *s, DisasOps *o)
 {
