summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@twiddle.net>2012-08-23 15:17:35 -0700
committerRichard Henderson <rth@twiddle.net>2013-01-05 12:18:41 -0800
commit68c8bd93ccb0ee441d62b5b8b8911cf5c38663f8 (patch)
tree923ab3014245e726f464f3e2d71ac3156f32e810
parent24db8412ec58a63556fb51fb157497342f1b08b8 (diff)
downloadqemu-68c8bd93ccb0ee441d62b5b8b8911cf5c38663f8.tar.gz
target-s390: Convert CONVERT TO FIXED
Signed-off-by: Richard Henderson <rth@twiddle.net>
-rw-r--r--target-s390x/fpu_helper.c98
-rw-r--r--target-s390x/helper.h12
-rw-r--r--target-s390x/insn-data.def7
-rw-r--r--target-s390x/translate.c125
4 files changed, 124 insertions, 118 deletions
diff --git a/target-s390x/fpu_helper.c b/target-s390x/fpu_helper.c
index b735c2c384..ff3b435e89 100644
--- a/target-s390x/fpu_helper.c
+++ b/target-s390x/fpu_helper.c
@@ -387,8 +387,9 @@ uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
return float_comp_to_cc(env, cmp);
}
-static void set_round_mode(CPUS390XState *env, int m3)
+static int swap_round_mode(CPUS390XState *env, int m3)
{
+ int ret = env->fpu_status.float_rounding_mode;
switch (m3) {
case 0:
/* current mode */
@@ -412,86 +413,69 @@ static void set_round_mode(CPUS390XState *env, int m3)
set_float_rounding_mode(float_round_down, &env->fpu_status);
break;
}
+ return ret;
}
/* convert 32-bit float to 64-bit int */
-uint32_t HELPER(cgebr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
- uint32_t m3)
+uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
{
- float32 v2 = env->fregs[f2].l.upper;
-
- set_round_mode(env, m3);
- env->regs[r1] = float32_to_int64(v2, &env->fpu_status);
- return set_cc_nz_f32(v2);
+ int hold = swap_round_mode(env, m3);
+ int64_t ret = float32_to_int64(v2, &env->fpu_status);
+ set_float_rounding_mode(hold, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
}
/* convert 64-bit float to 64-bit int */
-uint32_t HELPER(cgdbr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
- uint32_t m3)
+uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
{
- float64 v2 = env->fregs[f2].d;
-
- set_round_mode(env, m3);
- env->regs[r1] = float64_to_int64(v2, &env->fpu_status);
- return set_cc_nz_f64(v2);
+ int hold = swap_round_mode(env, m3);
+ int64_t ret = float64_to_int64(v2, &env->fpu_status);
+ set_float_rounding_mode(hold, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
}
/* convert 128-bit float to 64-bit int */
-uint32_t HELPER(cgxbr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
- uint32_t m3)
+uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
{
- CPU_QuadU v2;
-
- v2.ll.upper = env->fregs[f2].ll;
- v2.ll.lower = env->fregs[f2 + 2].ll;
- set_round_mode(env, m3);
- env->regs[r1] = float128_to_int64(v2.q, &env->fpu_status);
- if (float128_is_any_nan(v2.q)) {
- return 3;
- } else if (float128_is_zero(v2.q)) {
- return 0;
- } else if (float128_is_neg(v2.q)) {
- return 1;
- } else {
- return 2;
- }
+ int hold = swap_round_mode(env, m3);
+ float128 v2 = make_float128(h, l);
+ int64_t ret = float128_to_int64(v2, &env->fpu_status);
+ set_float_rounding_mode(hold, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
}
/* convert 32-bit float to 32-bit int */
-uint32_t HELPER(cfebr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
- uint32_t m3)
+uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
{
- float32 v2 = env->fregs[f2].l.upper;
-
- set_round_mode(env, m3);
- env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
- float32_to_int32(v2, &env->fpu_status);
- return set_cc_nz_f32(v2);
+ int hold = swap_round_mode(env, m3);
+ int32_t ret = float32_to_int32(v2, &env->fpu_status);
+ set_float_rounding_mode(hold, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
}
/* convert 64-bit float to 32-bit int */
-uint32_t HELPER(cfdbr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
- uint32_t m3)
+uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3)
{
- float64 v2 = env->fregs[f2].d;
-
- set_round_mode(env, m3);
- env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
- float64_to_int32(v2, &env->fpu_status);
- return set_cc_nz_f64(v2);
+ int hold = swap_round_mode(env, m3);
+ int32_t ret = float64_to_int32(v2, &env->fpu_status);
+ set_float_rounding_mode(hold, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
}
/* convert 128-bit float to 32-bit int */
-uint32_t HELPER(cfxbr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
- uint32_t m3)
+uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3)
{
- CPU_QuadU v2;
-
- v2.ll.upper = env->fregs[f2].ll;
- v2.ll.lower = env->fregs[f2 + 2].ll;
- env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
- float128_to_int32(v2.q, &env->fpu_status);
- return set_cc_nz_f128(v2.q);
+ int hold = swap_round_mode(env, m3);
+ float128 v2 = make_float128(h, l);
+ int32_t ret = float128_to_int32(v2, &env->fpu_status);
+ set_float_rounding_mode(hold, &env->fpu_status);
+ handle_exceptions(env, GETPC());
+ return ret;
}
/* 32-bit FP multiply and add */
diff --git a/target-s390x/helper.h b/target-s390x/helper.h
index 89a3218e4d..1439b5ed1f 100644
--- a/target-s390x/helper.h
+++ b/target-s390x/helper.h
@@ -59,12 +59,12 @@ DEF_HELPER_3(lexb, i64, env, i64, i64)
DEF_HELPER_FLAGS_3(ceb, TCG_CALL_NO_WG_SE, i32, env, i64, i64)
DEF_HELPER_FLAGS_3(cdb, TCG_CALL_NO_WG_SE, i32, env, i64, i64)
DEF_HELPER_FLAGS_5(cxb, TCG_CALL_NO_WG_SE, i32, env, i64, i64, i64, i64)
-DEF_HELPER_4(cgebr, i32, env, i32, i32, i32)
-DEF_HELPER_4(cgdbr, i32, env, i32, i32, i32)
-DEF_HELPER_4(cgxbr, i32, env, i32, i32, i32)
-DEF_HELPER_4(cfebr, i32, env, i32, i32, i32)
-DEF_HELPER_4(cfdbr, i32, env, i32, i32, i32)
-DEF_HELPER_4(cfxbr, i32, env, i32, i32, i32)
+DEF_HELPER_3(cgeb, i64, env, i64, i32)
+DEF_HELPER_3(cgdb, i64, env, i64, i32)
+DEF_HELPER_4(cgxb, i64, env, i64, i64, i32)
+DEF_HELPER_3(cfeb, i64, env, i64, i32)
+DEF_HELPER_3(cfdb, i64, env, i64, i32)
+DEF_HELPER_4(cfxb, i64, env, i64, i64, i32)
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)
diff --git a/target-s390x/insn-data.def b/target-s390x/insn-data.def
index e6b9a5aa7f..2d88b70474 100644
--- a/target-s390x/insn-data.def
+++ b/target-s390x/insn-data.def
@@ -163,6 +163,13 @@
/* CONVERT TO DECIMAL */
C(0x4e00, CVD, RX_a, Z, r1_o, a2, 0, 0, cvd, 0)
C(0xe326, CVDY, RXY_a, LD, r1_o, a2, 0, 0, cvd, 0)
+/* CONVERT TO FIXED */
+ C(0xb398, CFEBR, RRF_e, Z, 0, e2, new, r1_32, cfeb, 0)
+ C(0xb399, CFDBR, RRF_e, Z, 0, f2_o, new, r1_32, cfdb, 0)
+ C(0xb39a, CFXBR, RRF_e, Z, 0, x2_o, new, r1_32, cfxb, 0)
+ C(0xb3a8, CGEBR, RRF_e, Z, 0, e2, r1, 0, cgeb, 0)
+ C(0xb3a9, CGDBR, RRF_e, Z, 0, f2_o, r1, 0, cgdb, 0)
+ C(0xb3aa, CGXBR, RRF_e, Z, 0, x2_o, r1, 0, cgxb, 0)
/* DIVIDE */
C(0x1d00, DR, RR_a, Z, r1_D32, r2_32s, new_P, r1_P32, divs32, 0)
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index b1bcfd393b..03fae68b10 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -485,6 +485,21 @@ static inline void set_cc_nz_u64(DisasContext *s, TCGv_i64 val)
gen_op_update1_cc_i64(s, CC_OP_NZ, val);
}
+static inline void gen_set_cc_nz_f32(DisasContext *s, TCGv_i64 val)
+{
+ gen_op_update1_cc_i64(s, CC_OP_NZ_F32, val);
+}
+
+static inline void gen_set_cc_nz_f64(DisasContext *s, TCGv_i64 val)
+{
+ gen_op_update1_cc_i64(s, CC_OP_NZ_F64, val);
+}
+
+static inline void gen_set_cc_nz_f128(DisasContext *s, TCGv_i64 vh, TCGv_i64 vl)
+{
+ gen_op_update2_cc_i64(s, CC_OP_NZ_F128, vh, vl);
+}
+
static inline void cmp_32(DisasContext *s, TCGv_i32 v1, TCGv_i32 v2,
enum cc_op cond)
{
@@ -1367,7 +1382,7 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
int r1, int r2)
{
TCGv_i64 tmp;
- TCGv_i32 tmp32_1, tmp32_2, tmp32_3;
+ TCGv_i32 tmp32_1, tmp32_2;
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); \
@@ -1411,30 +1426,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i32(tmp32_2);
break;
- case 0x98: /* CFEBR R1,R2 [RRE] */
- case 0x99: /* CFDBR R1,R2 [RRE] */
- case 0x9a: /* CFXBR R1,R2 [RRE] */
- tmp32_1 = tcg_const_i32(r1);
- tmp32_2 = tcg_const_i32(r2);
- tmp32_3 = tcg_const_i32(m3);
- switch (op) {
- case 0x98:
- gen_helper_cfebr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
- break;
- case 0x99:
- gen_helper_cfdbr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
- break;
- case 0x9a:
- gen_helper_cfxbr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
- break;
- default:
- tcg_abort();
- }
- set_cc_static(s);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- tcg_temp_free_i32(tmp32_3);
- break;
case 0xa4: /* CEGBR R1,R2 [RRE] */
case 0xa5: /* CDGBR R1,R2 [RRE] */
tmp32_1 = tcg_const_i32(r1);
@@ -1459,36 +1450,6 @@ static void disas_b3(CPUS390XState *env, DisasContext *s, int op, int m3,
tcg_temp_free_i32(tmp32_1);
tcg_temp_free_i64(tmp);
break;
- case 0xa8: /* CGEBR R1,R2 [RRE] */
- tmp32_1 = tcg_const_i32(r1);
- tmp32_2 = tcg_const_i32(r2);
- tmp32_3 = tcg_const_i32(m3);
- gen_helper_cgebr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
- set_cc_static(s);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- tcg_temp_free_i32(tmp32_3);
- break;
- case 0xa9: /* CGDBR R1,R2 [RRE] */
- tmp32_1 = tcg_const_i32(r1);
- tmp32_2 = tcg_const_i32(r2);
- tmp32_3 = tcg_const_i32(m3);
- gen_helper_cgdbr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
- set_cc_static(s);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- tcg_temp_free_i32(tmp32_3);
- break;
- case 0xaa: /* CGXBR R1,R2 [RRE] */
- tmp32_1 = tcg_const_i32(r1);
- tmp32_2 = tcg_const_i32(r2);
- tmp32_3 = tcg_const_i32(m3);
- gen_helper_cgxbr(cc_op, cpu_env, tmp32_1, tmp32_2, tmp32_3);
- set_cc_static(s);
- tcg_temp_free_i32(tmp32_1);
- tcg_temp_free_i32(tmp32_2);
- tcg_temp_free_i32(tmp32_3);
- break;
default:
LOG_DISAS("illegal b3 operation 0x%x\n", op);
gen_illegal_opcode(s);
@@ -2129,6 +2090,60 @@ static ExitStatus op_cxb(DisasContext *s, DisasOps *o)
return NO_EXIT;
}
+static ExitStatus op_cfeb(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+ gen_helper_cfeb(o->out, cpu_env, o->in2, m3);
+ tcg_temp_free_i32(m3);
+ gen_set_cc_nz_f32(s, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_cfdb(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+ gen_helper_cfdb(o->out, cpu_env, o->in2, m3);
+ tcg_temp_free_i32(m3);
+ gen_set_cc_nz_f64(s, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_cfxb(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+ gen_helper_cfxb(o->out, cpu_env, o->in1, o->in2, m3);
+ tcg_temp_free_i32(m3);
+ gen_set_cc_nz_f128(s, o->in1, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_cgeb(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+ gen_helper_cgeb(o->out, cpu_env, o->in2, m3);
+ tcg_temp_free_i32(m3);
+ gen_set_cc_nz_f32(s, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_cgdb(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+ gen_helper_cgdb(o->out, cpu_env, o->in2, m3);
+ tcg_temp_free_i32(m3);
+ gen_set_cc_nz_f64(s, o->in2);
+ return NO_EXIT;
+}
+
+static ExitStatus op_cgxb(DisasContext *s, DisasOps *o)
+{
+ TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3));
+ gen_helper_cgxb(o->out, cpu_env, o->in1, o->in2, m3);
+ tcg_temp_free_i32(m3);
+ gen_set_cc_nz_f128(s, o->in1, o->in2);
+ return NO_EXIT;
+}
+
static ExitStatus op_clc(DisasContext *s, DisasOps *o)
{
int l = get_field(s->fields, l1);