aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2017-06-20 11:14:16 +0100
committerPeter Maydell <peter.maydell@linaro.org>2017-06-20 11:14:16 +0100
commit5135a1056d913186cc44ce78f2f6994ff23838f7 (patch)
tree7448828af74c7d9332cacdc055aae3f0228f3e3b /target
parent5837aaac25e008ddafd1f12ddee78887e386c79d (diff)
parent69e698220f68a17ce9584b068f68ed09e527a6ad (diff)
Merge remote-tracking branch 'remotes/vivier/tags/m68k-for-2.10-pull-request' into staging
# gpg: Signature made Thu 15 Jun 2017 09:16:31 BST # gpg: using RSA key 0xF30C38BD3F2FBE3C # gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" # gpg: aka "Laurent Vivier <laurent@vivier.eu>" # gpg: aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" # Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F 5173 F30C 38BD 3F2F BE3C * remotes/vivier/tags/m68k-for-2.10-pull-request: target-m68k: define ext_opsize target-m68k: move FPU helpers to fpu_helper.c softfloat: define 680x0 specific values target/m68k: fix V flag for CC_OP_SUBx Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target')
-rw-r--r--target/m68k/Makefile.objs2
-rw-r--r--target/m68k/fpu_helper.c112
-rw-r--r--target/m68k/helper.c88
-rw-r--r--target/m68k/translate.c45
4 files changed, 138 insertions, 109 deletions
diff --git a/target/m68k/Makefile.objs b/target/m68k/Makefile.objs
index 02cf616a78..39141ab93d 100644
--- a/target/m68k/Makefile.objs
+++ b/target/m68k/Makefile.objs
@@ -1,3 +1,3 @@
obj-y += m68k-semi.o
-obj-y += translate.o op_helper.o helper.o cpu.o
+obj-y += translate.o op_helper.o helper.o cpu.o fpu_helper.o
obj-y += gdbstub.o
diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
new file mode 100644
index 0000000000..5bf2576c2b
--- /dev/null
+++ b/target/m68k/fpu_helper.c
@@ -0,0 +1,112 @@
+/*
+ * m68k FPU helpers
+ *
+ * Copyright (c) 2006-2007 CodeSourcery
+ * Written by Paul Brook
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "exec/helper-proto.h"
+
+uint32_t HELPER(f64_to_i32)(CPUM68KState *env, float64 val)
+{
+ return float64_to_int32(val, &env->fp_status);
+}
+
+float32 HELPER(f64_to_f32)(CPUM68KState *env, float64 val)
+{
+ return float64_to_float32(val, &env->fp_status);
+}
+
+float64 HELPER(i32_to_f64)(CPUM68KState *env, uint32_t val)
+{
+ return int32_to_float64(val, &env->fp_status);
+}
+
+float64 HELPER(f32_to_f64)(CPUM68KState *env, float32 val)
+{
+ return float32_to_float64(val, &env->fp_status);
+}
+
+float64 HELPER(iround_f64)(CPUM68KState *env, float64 val)
+{
+ return float64_round_to_int(val, &env->fp_status);
+}
+
+float64 HELPER(itrunc_f64)(CPUM68KState *env, float64 val)
+{
+ return float64_trunc_to_int(val, &env->fp_status);
+}
+
+float64 HELPER(sqrt_f64)(CPUM68KState *env, float64 val)
+{
+ return float64_sqrt(val, &env->fp_status);
+}
+
+float64 HELPER(abs_f64)(float64 val)
+{
+ return float64_abs(val);
+}
+
+float64 HELPER(chs_f64)(float64 val)
+{
+ return float64_chs(val);
+}
+
+float64 HELPER(add_f64)(CPUM68KState *env, float64 a, float64 b)
+{
+ return float64_add(a, b, &env->fp_status);
+}
+
+float64 HELPER(sub_f64)(CPUM68KState *env, float64 a, float64 b)
+{
+ return float64_sub(a, b, &env->fp_status);
+}
+
+float64 HELPER(mul_f64)(CPUM68KState *env, float64 a, float64 b)
+{
+ return float64_mul(a, b, &env->fp_status);
+}
+
+float64 HELPER(div_f64)(CPUM68KState *env, float64 a, float64 b)
+{
+ return float64_div(a, b, &env->fp_status);
+}
+
+float64 HELPER(sub_cmp_f64)(CPUM68KState *env, float64 a, float64 b)
+{
+ /* ??? This may incorrectly raise exceptions. */
+ /* ??? Should flush denormals to zero. */
+ float64 res;
+ res = float64_sub(a, b, &env->fp_status);
+ if (float64_is_quiet_nan(res, &env->fp_status)) {
+ /* +/-inf compares equal against itself, but sub returns nan. */
+ if (!float64_is_quiet_nan(a, &env->fp_status)
+ && !float64_is_quiet_nan(b, &env->fp_status)) {
+ res = float64_zero;
+ if (float64_lt_quiet(a, res, &env->fp_status)) {
+ res = float64_chs(res);
+ }
+ }
+ }
+ return res;
+}
+
+uint32_t HELPER(compare_f64)(CPUM68KState *env, float64 val)
+{
+ return float64_compare_quiet(val, float64_zero, &env->fp_status);
+}
diff --git a/target/m68k/helper.c b/target/m68k/helper.c
index f750d3dbaa..5ca9911657 100644
--- a/target/m68k/helper.c
+++ b/target/m68k/helper.c
@@ -284,94 +284,6 @@ void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
m68k_switch_sp(env);
}
-/* FPU helpers. */
-uint32_t HELPER(f64_to_i32)(CPUM68KState *env, float64 val)
-{
- return float64_to_int32(val, &env->fp_status);
-}
-
-float32 HELPER(f64_to_f32)(CPUM68KState *env, float64 val)
-{
- return float64_to_float32(val, &env->fp_status);
-}
-
-float64 HELPER(i32_to_f64)(CPUM68KState *env, uint32_t val)
-{
- return int32_to_float64(val, &env->fp_status);
-}
-
-float64 HELPER(f32_to_f64)(CPUM68KState *env, float32 val)
-{
- return float32_to_float64(val, &env->fp_status);
-}
-
-float64 HELPER(iround_f64)(CPUM68KState *env, float64 val)
-{
- return float64_round_to_int(val, &env->fp_status);
-}
-
-float64 HELPER(itrunc_f64)(CPUM68KState *env, float64 val)
-{
- return float64_trunc_to_int(val, &env->fp_status);
-}
-
-float64 HELPER(sqrt_f64)(CPUM68KState *env, float64 val)
-{
- return float64_sqrt(val, &env->fp_status);
-}
-
-float64 HELPER(abs_f64)(float64 val)
-{
- return float64_abs(val);
-}
-
-float64 HELPER(chs_f64)(float64 val)
-{
- return float64_chs(val);
-}
-
-float64 HELPER(add_f64)(CPUM68KState *env, float64 a, float64 b)
-{
- return float64_add(a, b, &env->fp_status);
-}
-
-float64 HELPER(sub_f64)(CPUM68KState *env, float64 a, float64 b)
-{
- return float64_sub(a, b, &env->fp_status);
-}
-
-float64 HELPER(mul_f64)(CPUM68KState *env, float64 a, float64 b)
-{
- return float64_mul(a, b, &env->fp_status);
-}
-
-float64 HELPER(div_f64)(CPUM68KState *env, float64 a, float64 b)
-{
- return float64_div(a, b, &env->fp_status);
-}
-
-float64 HELPER(sub_cmp_f64)(CPUM68KState *env, float64 a, float64 b)
-{
- /* ??? This may incorrectly raise exceptions. */
- /* ??? Should flush denormals to zero. */
- float64 res;
- res = float64_sub(a, b, &env->fp_status);
- if (float64_is_quiet_nan(res, &env->fp_status)) {
- /* +/-inf compares equal against itself, but sub returns nan. */
- if (!float64_is_quiet_nan(a, &env->fp_status)
- && !float64_is_quiet_nan(b, &env->fp_status)) {
- res = float64_zero;
- if (float64_lt_quiet(a, res, &env->fp_status))
- res = float64_chs(res);
- }
- }
- return res;
-}
-
-uint32_t HELPER(compare_f64)(CPUM68KState *env, float64 val)
-{
- return float64_compare_quiet(val, float64_zero, &env->fp_status);
-}
/* MAC unit. */
/* FIXME: The MAC unit implementation is a bit of a mess. Some helpers
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index ad4d4efb8d..dfecfb6e5f 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -565,7 +565,7 @@ static void gen_flush_flags(DisasContext *s)
t1 = tcg_temp_new();
tcg_gen_add_i32(t0, QREG_CC_N, QREG_CC_V);
gen_ext(t0, t0, s->cc_op - CC_OP_SUBB, 1);
- tcg_gen_xor_i32(t1, QREG_CC_N, QREG_CC_V);
+ tcg_gen_xor_i32(t1, QREG_CC_N, t0);
tcg_gen_xor_i32(QREG_CC_V, QREG_CC_V, t0);
tcg_temp_free(t0);
tcg_gen_and_i32(QREG_CC_V, QREG_CC_V, t1);
@@ -669,6 +669,21 @@ static inline int insn_opsize(int insn)
}
}
+static inline int ext_opsize(int ext, int pos)
+{
+ switch ((ext >> pos) & 7) {
+ case 0: return OS_LONG;
+ case 1: return OS_SINGLE;
+ case 2: return OS_EXTENDED;
+ case 3: return OS_PACKED;
+ case 4: return OS_WORD;
+ case 5: return OS_DOUBLE;
+ case 6: return OS_BYTE;
+ default:
+ g_assert_not_reached();
+ }
+}
+
/* Assign value to a register. If the width is less than the register width
only the low part of the register is set. */
static void gen_partset_reg(int opsize, TCGv reg, TCGv val)
@@ -4111,20 +4126,19 @@ DISAS_INSN(fpu)
tmp32 = tcg_temp_new_i32();
/* fmove */
/* ??? TODO: Proper behavior on overflow. */
- switch ((ext >> 10) & 7) {
- case 0:
- opsize = OS_LONG;
+
+ opsize = ext_opsize(ext, 10);
+ switch (opsize) {
+ case OS_LONG:
gen_helper_f64_to_i32(tmp32, cpu_env, src);
break;
- case 1:
- opsize = OS_SINGLE;
+ case OS_SINGLE:
gen_helper_f64_to_f32(tmp32, cpu_env, src);
break;
- case 4:
- opsize = OS_WORD;
+ case OS_WORD:
gen_helper_f64_to_i32(tmp32, cpu_env, src);
break;
- case 5: /* OS_DOUBLE */
+ case OS_DOUBLE:
tcg_gen_mov_i32(tmp32, AREG(insn, 0));
switch ((insn >> 3) & 7) {
case 2:
@@ -4153,8 +4167,7 @@ DISAS_INSN(fpu)
}
tcg_temp_free_i32(tmp32);
return;
- case 6:
- opsize = OS_BYTE;
+ case OS_BYTE:
gen_helper_f64_to_i32(tmp32, cpu_env, src);
break;
default:
@@ -4227,15 +4240,7 @@ DISAS_INSN(fpu)
}
if (ext & (1 << 14)) {
/* Source effective address. */
- switch ((ext >> 10) & 7) {
- case 0: opsize = OS_LONG; break;
- case 1: opsize = OS_SINGLE; break;
- case 4: opsize = OS_WORD; break;
- case 5: opsize = OS_DOUBLE; break;
- case 6: opsize = OS_BYTE; break;
- default:
- goto undef;
- }
+ opsize = ext_opsize(ext, 10);
if (opsize == OS_DOUBLE) {
tmp32 = tcg_temp_new_i32();
tcg_gen_mov_i32(tmp32, AREG(insn, 0));