]> git.proxmox.com Git - qemu.git/commitdiff
target-s390: Implement LOAD/SET FP AND SIGNAL
authorRichard Henderson <rth@twiddle.net>
Tue, 11 Sep 2012 00:23:13 +0000 (17:23 -0700)
committerRichard Henderson <rth@twiddle.net>
Sat, 5 Jan 2013 20:18:45 +0000 (12:18 -0800)
Signed-off-by: Richard Henderson <rth@twiddle.net>
target-s390x/fpu_helper.c
target-s390x/helper.h
target-s390x/insn-data.def
target-s390x/translate.c

index b6e5040ff5711d29a78eb4b55aac6735cca4e837..94375b6a63e5c931abfbaff231123dc92ce3201f 100644 (file)
@@ -674,19 +674,40 @@ uint64_t HELPER(sqxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
     return RET128(ret);
 }
 
+static const int fpc_to_rnd[4] = {
+    float_round_nearest_even,
+    float_round_to_zero,
+    float_round_up,
+    float_round_down
+};
+
 /* 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);
+    set_float_rounding_mode(fpc_to_rnd[fpc & 3], &env->fpu_status);
+}
+
+/* set fpc and signal */
+void HELPER(sfas)(CPUS390XState *env, uint64_t val)
+{
+    uint32_t signalling = env->fpc;
+    uint32_t source = val;
+    uint32_t s390_exc;
+
+    /* The contents of the source operand are placed in the FPC register;
+       then the flags in the FPC register are set to the logical OR of the
+       signalling flags and the source flags.  */
+    env->fpc = source | (signalling & 0x00ff0000);
+    set_float_rounding_mode(fpc_to_rnd[source & 3], &env->fpu_status);
+
+    /* If any signalling flag is 1 and the corresponding source mask
+       is also 1, a simulated-iee-exception trap occurs.  */
+    s390_exc = (signalling >> 16) & (source >> 24);
+    if (s390_exc) {
+        ieee_exception(env, s390_exc | 3, GETPC());
+    }
 }
index 23d23d5b3aa4617040987e22fa83ca3b4c904af2..b7376339cdb2e4c23fdfb1b9afc0fb4a585d0e5d 100644 (file)
@@ -87,6 +87,7 @@ DEF_HELPER_4(tr, void, env, i32, i64, i64)
 DEF_HELPER_4(cksm, i64, env, i64, i64, i64)
 DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_NO_RWG_SE, i32, env, i32, i64, i64, i64)
 DEF_HELPER_FLAGS_2(sfpc, TCG_CALL_NO_RWG, void, env, i64)
+DEF_HELPER_FLAGS_2(sfas, TCG_CALL_NO_WG, void, env, i64)
 DEF_HELPER_FLAGS_1(popcnt, TCG_CALL_NO_RWG_SE, i64, i64)
 
 #ifndef CONFIG_USER_ONLY
index 79341a4b41e14696478c7ec56acb31129c5bb27e..e9159848281cd60536cccf0f2f63ecbc1caef4c1 100644 (file)
 
 /* LOAD FPC */
     C(0xb29d, LFPC,    S,     Z,   0, m2_32u, 0, 0, sfpc, 0)
+/* LOAD FPC AND SIGNAL */
+    C(0xb2bd, LFAS,    S,     IEEEE_SIM, 0, m2_32u, 0, 0, sfas, 0)
 
 /* LOAD LENGTHENED */
     C(0xb304, LDEBR,   RRE,   Z,   0, e2, f1, 0, ldeb, 0)
     C(0xb24e, SAR,     RRE,   Z,   0, r2_o, 0, 0, sar, 0)
 /* SET FPC */
     C(0xb384, SFPC,    RRE,   Z,   0, r1_o, 0, 0, sfpc, 0)
+/* SET FPC AND SIGNAL */
+    C(0xb385, SFASR,   RRE,   IEEEE_SIM, 0, r1_o, 0, 0, sfas, 0)
 /* SET BFP ROUNDING MODE */
     C(0xb299, SRNM,    S,     Z,   0, 0, 0, 0, srnm, 0)
     C(0xb2b8, SRNMB,   S,     FPE, 0, 0, 0, 0, srnm, 0)
index c4d9fffa21fe9d88599f1d85b98ed3d194bd70db..34b9cdf127d8ef1f3d8439cd0ab33add6aef3b2b 100644 (file)
@@ -2921,6 +2921,12 @@ static ExitStatus op_sfpc(DisasContext *s, DisasOps *o)
     return NO_EXIT;
 }
 
+static ExitStatus op_sfas(DisasContext *s, DisasOps *o)
+{
+    gen_helper_sfas(cpu_env, o->in2);
+    return NO_EXIT;
+}
+
 static ExitStatus op_srnm(DisasContext *s, DisasOps *o)
 {
     int b2 = get_field(s->fields, b2);