Patchwork [088/147] target-s390: Convert LFPC, SFPC

login
register
mail settings
Submitter Richard Henderson
Date Sept. 28, 2012, 12:22 a.m.
Message ID <1348791729-26480-1-git-send-email-rth@twiddle.net>
Download mbox | patch
Permalink /patch/187610/
State New
Headers show

Comments

Richard Henderson - Sept. 28, 2012, 12:22 a.m.
Note that we were failing to set the rounding mode in fpu_status.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-s390x/fpu_helper.c  | 17 ++++++++++++
 target-s390x/helper.h      |  1 +
 target-s390x/insn-data.def |  6 +++++
 target-s390x/translate.c   | 64 +++++-----------------------------------------
 4 files changed, 31 insertions(+), 57 deletions(-)

Patch

diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index 82505eb..e40e531 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -577,3 +577,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 be37f8a..e8300ec 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -77,6 +77,7 @@  DEF_HELPER_FLAGS_1(cvd, TCG_CALL_PURE|TCG_CALL_CONST, i64, s32)
 DEF_HELPER_4(unpk, void, env, i32, i64, i64)
 DEF_HELPER_4(tr, void, env, i32, i64, i64)
 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 771baaf..b319beb 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 e65b752..9f8fcb5 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -1337,18 +1337,6 @@  static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
         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);
@@ -1394,47 +1382,11 @@  static void disas_b2(CPUS390XState *env, DisasContext *s, int op,
     }
 }
 
-static void disas_b3(CPUS390XState *env, 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(CPUS390XState *env, DisasContext *s)
 {
     unsigned char opc;
     uint64_t insn;
-    int op, r1, r2, r3;
+    int op;
 
     opc = cpu_ldub_code(env, s->pc);
     LOG_DISAS("opc 0x%x\n", opc);
@@ -1445,14 +1397,6 @@  static void disas_s390_insn(CPUS390XState *env, DisasContext *s)
         op = (insn >> 16) & 0xff;
         disas_b2(env, s, op, insn);
         break;
-    case 0xb3:
-        insn = ld_code4(env, s->pc);
-        op = (insn >> 16) & 0xff;
-        r3 = (insn >> 12) & 0xf; /* aka m3 */
-        r1 = (insn >> 4) & 0xf;
-        r2 = insn & 0xf;
-        disas_b3(env, s, op, r3, r1, r2);
-        break;
     default:
         qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%x\n", opc);
         gen_illegal_opcode(s);
@@ -2981,6 +2925,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)
 {