From: Bryce Lanham <blanham@gmail.com>
To: qemu-devel@nongnu.org
Cc: Laurent Vivier <laurent@vivier.eu>
Subject: [Qemu-devel] [PATCH 062/111] m68k: FPU rework (draft)
Date: Wed, 17 Aug 2011 15:47:07 -0500 [thread overview]
Message-ID: <1313614076-28878-63-git-send-email-blanham@gmail.com> (raw)
In-Reply-To: <1313614076-28878-1-git-send-email-blanham@gmail.com>
From: Laurent Vivier <laurent@vivier.eu>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
target-m68k/cpu.h | 53 +++-
target-m68k/helper.c | 345 +++++++++++++++++----
target-m68k/helpers.h | 39 ++-
target-m68k/qregs.def | 3 +-
target-m68k/translate.c | 776 +++++++++++++++++++++++++++++++----------------
tests/m68k/Makefile | 15 +
tests/m68k/fmove.S | 55 ++++
tests/m68k/fmovecr.S | 29 ++
tests/m68k/fmovem.S | 17 +
tests/m68k/trap.i | 5 +
10 files changed, 978 insertions(+), 359 deletions(-)
create mode 100644 tests/m68k/Makefile
create mode 100644 tests/m68k/fmove.S
create mode 100644 tests/m68k/fmovecr.S
create mode 100644 tests/m68k/fmovem.S
create mode 100644 tests/m68k/trap.i
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index e316b1e..2587512 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -60,6 +60,36 @@
#define NB_MMU_MODES 2
+#define TARGET_PHYS_ADDR_SPACE_BITS 32
+#define TARGET_VIRT_ADDR_SPACE_BITS 32
+
+#ifdef CONFIG_USER_ONLY
+/* Linux uses 4k pages. */
+#define TARGET_PAGE_BITS 12
+#else
+/* Smallest TLB entry size is 1k. */
+#define TARGET_PAGE_BITS 10
+#endif
+
+#include "cpu-all.h"
+
+typedef uint32_t CPUM68K_SingleU;
+typedef uint64_t CPUM68K_DoubleU;
+
+typedef struct {
+ uint32_t high;
+ uint64_t low;
+} __attribute__((packed)) CPUM68K_XDoubleU;
+
+typedef struct {
+ uint8_t high[2];
+ uint8_t low[10];
+} __attribute__((packed)) CPUM68K_PDoubleU;
+
+typedef CPU_LDoubleU FPReg;
+#define PRIxFPH PRIx16
+#define PRIxFPL PRIx64
+
typedef struct CPUM68KState {
uint32_t dregs[8];
uint32_t aregs[8];
@@ -76,8 +106,7 @@ typedef struct CPUM68KState {
uint32_t cc_src;
uint32_t cc_x;
- float64 fregs[8];
- float64 fp_result;
+ FPReg fregs[8];
uint32_t fpcr;
uint32_t fpsr;
float_status fp_status;
@@ -90,6 +119,13 @@ typedef struct CPUM68KState {
uint32_t macsr;
uint32_t mac_mask;
+ /* Temporary storage for FPU */
+
+ uint32_t fp0h;
+ uint64_t fp0l;
+ uint32_t fp1h;
+ uint64_t fp1l;
+
/* Temporary storage for DIV helpers. */
uint32_t div1;
uint32_t div2;
@@ -228,17 +264,6 @@ void m68k_cpu_list(FILE *f, fprintf_function cpu_fprintf);
void register_m68k_insns (CPUM68KState *env);
-#ifdef CONFIG_USER_ONLY
-/* Linux uses 4k pages. */
-#define TARGET_PAGE_BITS 12
-#else
-/* Smallest TLB entry size is 1k. */
-#define TARGET_PAGE_BITS 10
-#endif
-
-#define TARGET_PHYS_ADDR_SPACE_BITS 32
-#define TARGET_VIRT_ADDR_SPACE_BITS 32
-
#define cpu_init cpu_m68k_init
#define cpu_exec cpu_m68k_exec
#define cpu_gen_code cpu_m68k_gen_code
@@ -267,8 +292,6 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
}
#endif
-#include "cpu-all.h"
-
static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
target_ulong *cs_base, int *flags)
{
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index 1bb0cef..081e1d9 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -23,6 +23,7 @@
#include "config.h"
#include "cpu.h"
+#include "exec.h"
#include "qemu-common.h"
#include "gdbstub.h"
@@ -115,7 +116,8 @@ void m68k_cpu_list(FILE *f, fprintf_function cpu_fprintf)
static int fpu_gdb_get_reg(CPUState *env, uint8_t *mem_buf, int n)
{
if (n < 8) {
- stfq_p(mem_buf, env->fregs[n]);
+ float_status s;
+ stfq_p(mem_buf, floatx80_to_float64(env->fregs[n].d, &s));
return 8;
}
if (n < 11) {
@@ -129,7 +131,8 @@ static int fpu_gdb_get_reg(CPUState *env, uint8_t *mem_buf, int n)
static int fpu_gdb_set_reg(CPUState *env, uint8_t *mem_buf, int n)
{
if (n < 8) {
- env->fregs[n] = ldfq_p(mem_buf);
+ float_status s;
+ env->fregs[n].d = float64_to_floatx80(ldfq_p(mem_buf), &s);
return 8;
}
if (n < 11) {
@@ -980,125 +983,335 @@ HELPER_ROXL(uint32_t, 32)
/* FPU helpers. */
static const floatx80 fpu_rom[128] = {
- [0x00] = { .high = 0x4000, .low = 0xc90fdaa22168c235ULL }, /* Pi */
-
- [0x0b] = { .high = 0x3ffd, .low = 0x9a209a84fbcff798ULL }, /* Log10(2) */
- [0x0c] = { .high = 0x4000, .low = 0xadf85458a2bb4a9aULL }, /* e */
- [0x0d] = { .high = 0x3fff, .low = 0xb8aa3b295c17f0bcULL }, /* Log2(e) */
- [0x0e] = { .high = 0x3ffd, .low = 0xde5bd8a937287195ULL }, /* Log10(e) */
- [0x0f] = { .high = 0x0000, .low = 0x0000000000000000ULL }, /* Zero */
-
- [0x30] = { .high = 0x3ffe, .low = 0xb17217f7d1cf79acULL }, /* ln(2) */
- [0x31] = { .high = 0x4000, .low = 0x935d8dddaaa8ac17ULL }, /* ln(10) */
- [0x32] = { .high = 0x3fff, .low = 0x8000000000000000ULL }, /* 10^0 */
- [0x33] = { .high = 0x4002, .low = 0xa000000000000000ULL }, /* 10^1 */
- [0x34] = { .high = 0x4005, .low = 0xc800000000000000ULL }, /* 10^2 */
- [0x35] = { .high = 0x400c, .low = 0x9c40000000000000ULL }, /* 10^4 */
- [0x36] = { .high = 0x4019, .low = 0xbebc200000000000ULL }, /* 10^8 */
- [0x37] = { .high = 0x4034, .low = 0x8e1bc9bf04000000ULL }, /* 10^16 */
- [0x38] = { .high = 0x4069, .low = 0x9dc5ada82b70b59eULL }, /* 10^32 */
- [0x39] = { .high = 0x40d3, .low = 0xc2781f49ffcfa6d5ULL }, /* 10^64 */
- [0x3a] = { .high = 0x41a8, .low = 0x93ba47c980e98ce0ULL }, /* 10^128 */
- [0x3b] = { .high = 0x4351, .low = 0xaa7eebfb9df9de8eULL }, /* 10^256 */
- [0x3c] = { .high = 0x46a3, .low = 0xe319a0aea60e91c7ULL }, /* 10^512 */
- [0x3d] = { .high = 0x4d48, .low = 0xc976758681750c17ULL }, /* 10^1024 */
- [0x3e] = { .high = 0x5a92, .low = 0x9e8b3b5dc53d5de5ULL }, /* 10^2048 */
- [0x3f] = { .high = 0x7525, .low = 0xc46052028a20979bULL }, /* 10^4096 */
+ [0x00] = floatx80_pi, /* Pi */
+
+ [0x0b] = { .high = 0x3ffd, .low = 0x9a209a84fbcff798ULL }, /* Log10(2) */
+ [0x0c] = { .high = 0x4000, .low = 0xadf85458a2bb4a9aULL }, /* e */
+ [0x0d] = { .high = 0x3fff, .low = 0xb8aa3b295c17f0bcULL }, /* Log2(e) */
+ [0x0e] = { .high = 0x3ffd, .low = 0xde5bd8a937287195ULL }, /* Log10(e) */
+ [0x0f] = floatx80_zero, /* Zero */
+
+ [0x30] = floatx80_ln2, /* ln(2) */
+ [0x31] = { .high = 0x4000, .low = 0x935d8dddaaa8ac17ULL }, /* ln(10) */
+ [0x32] = floatx80_one, /* 10^0 */
+ [0x33] = { .high = 0x4002, .low = 0xa000000000000000ULL }, /* 10^1 */
+ [0x34] = { .high = 0x4005, .low = 0xc800000000000000ULL }, /* 10^2 */
+ [0x35] = { .high = 0x400c, .low = 0x9c40000000000000ULL }, /* 10^4 */
+ [0x36] = { .high = 0x4019, .low = 0xbebc200000000000ULL }, /* 10^8 */
+ [0x37] = { .high = 0x4034, .low = 0x8e1bc9bf04000000ULL }, /* 10^16 */
+ [0x38] = { .high = 0x4069, .low = 0x9dc5ada82b70b59eULL }, /* 10^32 */
+ [0x39] = { .high = 0x40d3, .low = 0xc2781f49ffcfa6d5ULL }, /* 10^64 */
+ [0x3a] = { .high = 0x41a8, .low = 0x93ba47c980e98ce0ULL }, /* 10^128 */
+ [0x3b] = { .high = 0x4351, .low = 0xaa7eebfb9df9de8eULL }, /* 10^256 */
+ [0x3c] = { .high = 0x46a3, .low = 0xe319a0aea60e91c7ULL }, /* 10^512 */
+ [0x3d] = { .high = 0x4d48, .low = 0xc976758681750c17ULL }, /* 10^1024 */
+ [0x3e] = { .high = 0x5a92, .low = 0x9e8b3b5dc53d5de5ULL }, /* 10^2048 */
+ [0x3f] = { .high = 0x7525, .low = 0xc46052028a20979bULL }, /* 10^4096 */
};
-float64 HELPER(const_f64)(CPUState *env, uint32_t offset)
+void HELPER(const_FP0)(CPUState *env, uint32_t offset)
{
- return floatx80_to_float64(fpu_rom[offset], &env->fp_status);
+ env->fp0h = fpu_rom[offset].high;
+ env->fp0l = fpu_rom[offset].low;
}
-uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val)
+static inline floatx80 FP0_to_floatx80(CPUState *env)
{
- return float64_to_int32(val, &env->fp_status);
+ floatx80 res;
+
+ res.high = env->fp0h;
+ res.low = env->fp0l;
+
+ return res;
}
-float32 HELPER(f64_to_f32)(CPUState *env, float64 val)
+static inline void floatx80_to_FP0(CPUState *env, floatx80 res)
{
- return float64_to_float32(val, &env->fp_status);
+ env->fp0h = res.high;
+ env->fp0l = res.low;
}
-float64 HELPER(i32_to_f64)(CPUState *env, uint32_t val)
+static inline int32_t FP0_to_int32(CPUState *env)
{
- return int32_to_float64(val, &env->fp_status);
+ return env->fp0h;
}
-float64 HELPER(f32_to_f64)(CPUState *env, float32 val)
+static inline void int32_to_FP0(CPUState *env, int32_t val)
{
- return float32_to_float64(val, &env->fp_status);
+ env->fp0h = val;
}
-float64 HELPER(iround_f64)(CPUState *env, float64 val)
+static inline float32 FP0_to_float32(CPUState *env)
{
- return float64_round_to_int(val, &env->fp_status);
+ return *(float32*)&env->fp0h;
}
-float64 HELPER(itrunc_f64)(CPUState *env, float64 val)
+static inline void float32_to_FP0(CPUState *env, float32 val)
{
- return float64_trunc_to_int(val, &env->fp_status);
+
+ env->fp0h = *(uint32_t*)&val;
}
-float64 HELPER(sqrt_f64)(CPUState *env, float64 val)
+static inline float64 FP0_to_float64(CPUState *env)
{
- return float64_sqrt(val, &env->fp_status);
+ return *(float64*)&env->fp0l;
}
-float64 HELPER(abs_f64)(float64 val)
+static inline void float64_to_FP0(CPUState *env, float64 val)
{
- return float64_abs(val);
+ env->fp0l = *(uint64_t*)&val;
}
-float64 HELPER(chs_f64)(float64 val)
+static inline floatx80 FP1_to_floatx80(CPUState *env)
{
- return float64_chs(val);
+ floatx80 res;
+
+ res.high = env->fp1h;
+ res.low = env->fp1l;
+
+ return res;
}
-float64 HELPER(add_f64)(CPUState *env, float64 a, float64 b)
+static inline void restore_precision_mode(CPUState *env)
{
- return float64_add(a, b, &env->fp_status);
+ int rounding_precision;
+
+ rounding_precision = (env->fpcr >> 6) & 0x03;
+
+ switch (rounding_precision) {
+ case 0: /* extended */
+ set_floatx80_rounding_precision(80, &env->fp_status);
+ break;
+ case 1: /* single */
+ set_floatx80_rounding_precision(32, &env->fp_status);
+ break;
+ case 2: /* double */
+ set_floatx80_rounding_precision(64, &env->fp_status);
+ break;
+ case 3: /* reserved */
+ default:
+ break;
+ }
}
-float64 HELPER(sub_f64)(CPUState *env, float64 a, float64 b)
+static inline void restore_rounding_mode(CPUState *env)
{
- return float64_sub(a, b, &env->fp_status);
+ int rounding_mode;
+
+ rounding_mode = (env->fpcr >> 4) & 0x03;
+
+ switch (rounding_mode) {
+ case 0: /* round to nearest */
+ set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
+ break;
+ case 1: /* round to zero */
+ set_float_rounding_mode(float_round_to_zero, &env->fp_status);
+ break;
+ case 2: /* round toward minus infinity */
+ set_float_rounding_mode(float_round_down, &env->fp_status);
+ break;
+ case 3: /* round toward positive infinity */
+ set_float_rounding_mode(float_round_up, &env->fp_status);
+ break;
+ }
}
-float64 HELPER(mul_f64)(CPUState *env, float64 a, float64 b)
+void HELPER(set_fpcr)(CPUState *env, uint32_t val)
{
- return float64_mul(a, b, &env->fp_status);
+ env->fpcr = val & 0xffff;
+
+ restore_precision_mode(env);
+ restore_rounding_mode(env);
}
-float64 HELPER(div_f64)(CPUState *env, float64 a, float64 b)
+void HELPER(exts32_FP0)(CPUState *env)
{
- return float64_div(a, b, &env->fp_status);
+ floatx80 res;
+
+ res = int32_to_floatx80(FP0_to_int32(env), &env->fp_status);
+
+ floatx80_to_FP0(env, res);
}
-float64 HELPER(sub_cmp_f64)(CPUState *env, float64 a, float64 b)
+void HELPER(extf32_FP0)(CPUState *env)
+{
+ floatx80 res;
+
+ res = float32_to_floatx80(FP0_to_float32(env), &env->fp_status);
+
+ floatx80_to_FP0(env, res);
+}
+
+void HELPER(extf64_FP0)(CPUState *env)
+{
+ floatx80 res;
+
+ res = float64_to_floatx80(FP0_to_float64(env), &env->fp_status);
+
+ floatx80_to_FP0(env, res);
+}
+
+void HELPER(extp96_FP0)(CPUState *env)
+{
+}
+
+void HELPER(reds32_FP0)(CPUState *env)
+{
+ floatx80 val;
+ int32_t res;
+
+ val = FP0_to_floatx80(env);
+ res = floatx80_to_int32(val, &env->fp_status);
+
+ int32_to_FP0(env, res);
+}
+
+void HELPER(redf32_FP0)(CPUState *env)
+{
+ floatx80 val;
+ float32 res;
+
+ val = FP0_to_floatx80(env);
+ res = floatx80_to_float32(val, &env->fp_status);
+
+ float32_to_FP0(env, res);
+}
+
+void HELPER(redf64_FP0)(CPUState *env)
+{
+ floatx80 val;
+ float64 res;
+
+ val = FP0_to_floatx80(env);
+ res = floatx80_to_float64(val, &env->fp_status);
+
+ float64_to_FP0(env, res);
+}
+
+void HELPER(redp96_FP0)(CPUState *env)
+{
+}
+
+void HELPER(iround_FP0)(CPUState *env)
+{
+ floatx80 res;
+
+ res = floatx80_round_to_int(FP0_to_floatx80(env), &env->fp_status);
+
+ floatx80_to_FP0(env, res);
+}
+
+void HELPER(itrunc_FP0)(CPUState *env)
+{
+ floatx80 res;
+
+ set_float_rounding_mode(float_round_to_zero, &env->fp_status);
+ res = floatx80_round_to_int(FP0_to_floatx80(env), &env->fp_status);
+ restore_rounding_mode(env);
+
+ floatx80_to_FP0(env, res);
+}
+
+void HELPER(sqrt_FP0)(CPUState *env)
+{
+ floatx80 res;
+
+ res = floatx80_sqrt(FP0_to_floatx80(env), &env->fp_status);
+
+ floatx80_to_FP0(env, res);
+}
+
+void HELPER(abs_FP0)(CPUState *env)
+{
+ floatx80 res;
+
+ res = floatx80_abs(FP0_to_floatx80(env));
+
+ floatx80_to_FP0(env, res);
+}
+
+void HELPER(chs_FP0)(CPUState *env)
+{
+ floatx80 res;
+
+ res = floatx80_chs(FP0_to_floatx80(env));
+
+ floatx80_to_FP0(env, res);
+}
+
+void HELPER(add_FP0_FP1)(CPUState *env)
+{
+ floatx80 res;
+
+ res = floatx80_add(FP0_to_floatx80(env), FP1_to_floatx80(env),
+ &env->fp_status);
+
+ floatx80_to_FP0(env, res);
+}
+
+void HELPER(sub_FP0_FP1)(CPUState *env)
+{
+ floatx80 res;
+
+ res = floatx80_sub(FP0_to_floatx80(env), FP1_to_floatx80(env),
+ &env->fp_status);
+
+ floatx80_to_FP0(env, res);
+}
+
+void HELPER(mul_FP0_FP1)(CPUState *env)
+{
+ floatx80 res;
+
+ res = floatx80_mul(FP0_to_floatx80(env), FP1_to_floatx80(env),
+ &env->fp_status);
+
+ floatx80_to_FP0(env, res);
+}
+
+void HELPER(div_FP0_FP1)(CPUState *env)
+{
+ floatx80 res;
+
+ res = floatx80_div(FP0_to_floatx80(env), FP1_to_floatx80(env),
+ &env->fp_status);
+
+ floatx80_to_FP0(env, res);
+}
+
+void HELPER(fcmp_FP0_FP1)(CPUState *env)
{
/* ??? 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)) {
+ floatx80 res;
+ res = floatx80_sub(FP1_to_floatx80(env), FP0_to_floatx80(env),
+ &env->fp_status);
+ if (floatx80_is_any_nan(res)) {
/* +/-inf compares equal against itself, but sub returns nan. */
- if (!float64_is_quiet_nan(a)
- && !float64_is_quiet_nan(b)) {
- res = float64_zero;
- if (float64_lt_quiet(a, res, &env->fp_status))
- res = float64_chs(res);
+ if (!floatx80_is_any_nan(FP0_to_floatx80(env))
+ && !floatx80_is_any_nan(FP1_to_floatx80(env))) {
+ if (floatx80_lt_quiet(FP1_to_floatx80(env), floatx80_zero,
+ &env->fp_status))
+ res = floatx80_chs(res);
}
}
- return res;
+ floatx80_to_FP0(env, res);
}
-uint32_t HELPER(compare_f64)(CPUState *env, float64 val)
+uint32_t HELPER(compare_FP0)(CPUState *env)
{
- return float64_compare_quiet(val, float64_zero, &env->fp_status);
+ uint32_t res;
+
+ res = float64_compare_quiet(floatx80_to_float64(FP0_to_floatx80(env),
+ &env->fp_status),
+ float64_zero, &env->fp_status);
+ return res;
}
+void HELPER(fmovem)(CPUState *env, uint32_t opsize, uint32_t mode, uint32_t mask)
+{
+ fprintf(stderr, "MISSING HELPER fmovem\n");
+}
/* MAC unit. */
/* FIXME: The MAC unit implementation is a bit of a mess. Some helpers
take values, others take register numbers and manipulate the contents
diff --git a/target-m68k/helpers.h b/target-m68k/helpers.h
index aa835eb..6ddd659 100644
--- a/target-m68k/helpers.h
+++ b/target-m68k/helpers.h
@@ -50,22 +50,29 @@ DEF_HELPER_2(xflag_lt_i32, i32, i32, i32)
DEF_HELPER_2(set_sr, void, env, i32)
DEF_HELPER_3(movec, void, env, i32, i32)
-DEF_HELPER_2(const_f64, f64, env, i32);
-DEF_HELPER_2(f64_to_i32, i32, env, f64)
-DEF_HELPER_2(f64_to_f32, f32, env, f64)
-DEF_HELPER_2(i32_to_f64, f64, env, i32)
-DEF_HELPER_2(f32_to_f64, f64, env, f32)
-DEF_HELPER_2(iround_f64, f64, env, f64)
-DEF_HELPER_2(itrunc_f64, f64, env, f64)
-DEF_HELPER_2(sqrt_f64, f64, env, f64)
-DEF_HELPER_1(abs_f64, f64, f64)
-DEF_HELPER_1(chs_f64, f64, f64)
-DEF_HELPER_3(add_f64, f64, env, f64, f64)
-DEF_HELPER_3(sub_f64, f64, env, f64, f64)
-DEF_HELPER_3(mul_f64, f64, env, f64, f64)
-DEF_HELPER_3(div_f64, f64, env, f64, f64)
-DEF_HELPER_3(sub_cmp_f64, f64, env, f64, f64)
-DEF_HELPER_2(compare_f64, i32, env, f64)
+DEF_HELPER_1(exts32_FP0, void, env)
+DEF_HELPER_1(extf32_FP0, void, env)
+DEF_HELPER_1(extf64_FP0, void, env)
+DEF_HELPER_1(redf32_FP0, void, env)
+DEF_HELPER_1(redf64_FP0, void, env)
+DEF_HELPER_1(extp96_FP0, void, env)
+DEF_HELPER_1(reds32_FP0, void, env)
+DEF_HELPER_1(redp96_FP0, void, env)
+
+DEF_HELPER_4(fmovem, void, env, i32, i32, i32)
+DEF_HELPER_2(set_fpcr, void, env, i32)
+DEF_HELPER_2(const_FP0, void, env, i32)
+DEF_HELPER_1(iround_FP0, void, env)
+DEF_HELPER_1(itrunc_FP0, void, env)
+DEF_HELPER_1(sqrt_FP0, void, env)
+DEF_HELPER_1(abs_FP0, void, env)
+DEF_HELPER_1(chs_FP0, void, env)
+DEF_HELPER_1(add_FP0_FP1, void, env)
+DEF_HELPER_1(sub_FP0_FP1, void, env)
+DEF_HELPER_1(mul_FP0_FP1, void, env)
+DEF_HELPER_1(div_FP0_FP1, void, env)
+DEF_HELPER_1(fcmp_FP0_FP1, void, env)
+DEF_HELPER_1(compare_FP0, i32, env)
DEF_HELPER_3(mac_move, void, env, i32, i32)
DEF_HELPER_3(macmulf, i64, env, i32, i32)
diff --git a/target-m68k/qregs.def b/target-m68k/qregs.def
index 76e0236..13a8e5c 100644
--- a/target-m68k/qregs.def
+++ b/target-m68k/qregs.def
@@ -1,4 +1,5 @@
-DEFF64(FP_RESULT, fp_result)
+DEFF96(FP0, fp0)
+DEFF96(FP1, fp1)
DEFO32(PC, pc)
DEFO32(SR, sr)
DEFO32(CC_OP, cc_op)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index e394c2d..d4a7074 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -25,6 +25,7 @@
#include "config.h"
#include "cpu.h"
+#include "exec.h"
#include "disas.h"
#include "tcg-op.h"
#include "qemu-log.h"
@@ -35,30 +36,26 @@
//#define DEBUG_DISPATCH 1
-/* Fake floating point. */
-#define tcg_gen_mov_f64 tcg_gen_mov_i64
-#define tcg_gen_qemu_ldf64 tcg_gen_qemu_ld64
-#define tcg_gen_qemu_stf64 tcg_gen_qemu_st64
-
#define DEFO32(name, offset) static TCGv QREG_##name;
#define DEFO64(name, offset) static TCGv_i64 QREG_##name;
-#define DEFF64(name, offset) static TCGv_i64 QREG_##name;
+#define DEFF96(name, offset) static TCGv_i32 QREG_##name##H; static TCGv_i64 QREG_##name##L;
#include "qregs.def"
#undef DEFO32
#undef DEFO64
-#undef DEFF64
+#undef DEFF96
static TCGv_ptr cpu_env;
-static char cpu_reg_names[3*8*3 + 5*4];
+static char cpu_reg_names[2*8*3 + 5*4];
static TCGv cpu_dregs[8];
static TCGv cpu_aregs[8];
-static TCGv_i64 cpu_fregs[8];
static TCGv_i64 cpu_macc[4];
+static TCGv QEMU_FPSR;
+static TCGv QEMU_FPCR;
-#define DREG(insn, pos) cpu_dregs[((insn) >> (pos)) & 7]
-#define AREG(insn, pos) cpu_aregs[((insn) >> (pos)) & 7]
-#define FREG(insn, pos) cpu_fregs[((insn) >> (pos)) & 7]
+#define REG(insn, pos) (((insn) >> (pos)) & 7)
+#define DREG(insn, pos) cpu_dregs[REG(insn, pos)]
+#define AREG(insn, pos) cpu_aregs[REG(insn, pos)]
#define MACREG(acc) cpu_macc[acc]
#define QREG_SP cpu_aregs[7]
@@ -76,11 +73,14 @@ void m68k_tcg_init(void)
#define DEFO32(name, offset) QREG_##name = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUState, offset), #name);
#define DEFO64(name, offset) QREG_##name = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUState, offset), #name);
-#define DEFF64(name, offset) DEFO64(name, offset)
+#define DEFF96(name, offset) do { \
+QREG_##name##H = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUState, offset##h), #name); \
+QREG_##name##L = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUState, offset##l), #name); \
+} while (0);
#include "qregs.def"
#undef DEFO32
#undef DEFO64
-#undef DEFF64
+#undef DEFF96
cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
@@ -94,10 +94,6 @@ void m68k_tcg_init(void)
cpu_aregs[i] = tcg_global_mem_new(TCG_AREG0,
offsetof(CPUM68KState, aregs[i]), p);
p += 3;
- sprintf(p, "F%d", i);
- cpu_fregs[i] = tcg_global_mem_new_i64(TCG_AREG0,
- offsetof(CPUM68KState, fregs[i]), p);
- p += 3;
}
for (i = 0; i < 4; i++) {
sprintf(p, "ACC%d", i);
@@ -106,6 +102,11 @@ void m68k_tcg_init(void)
p += 5;
}
+ QEMU_FPSR = tcg_global_mem_new(TCG_AREG0, offsetof(CPUM68KState, fpsr),
+ "FPSR");
+ QEMU_FPCR = tcg_global_mem_new(TCG_AREG0, offsetof(CPUM68KState, fpcr),
+ "FPCR");
+
NULL_QREG = tcg_global_mem_new(TCG_AREG0, -4, "NULL");
store_dummy = tcg_global_mem_new(TCG_AREG0, -8, "NULL");
@@ -150,11 +151,13 @@ typedef struct DisasContext {
static void *gen_throws_exception;
#define gen_last_qop NULL
-#define OS_BYTE 0
-#define OS_WORD 1
-#define OS_LONG 2
-#define OS_SINGLE 4
-#define OS_DOUBLE 5
+#define OS_BYTE 1
+#define OS_WORD 2
+#define OS_LONG 3
+#define OS_SINGLE 4
+#define OS_DOUBLE 5
+#define OS_EXTENDED 6
+#define OS_PACKED 7
typedef void (*disas_proc)(DisasContext *, uint16_t);
@@ -170,6 +173,64 @@ typedef void (*disas_proc)(DisasContext *, uint16_t);
static void disas_##name (DisasContext *s, uint16_t insn)
#endif
+/* Update the CPU env CC_OP state. */
+static inline void gen_flush_cc_op(DisasContext *s)
+{
+ if (s->cc_op != CC_OP_DYNAMIC)
+ tcg_gen_movi_i32(QREG_CC_OP, s->cc_op);
+}
+
+
+/* Generate a jump to an immediate address. */
+static void gen_jmp_im(DisasContext *s, uint32_t dest)
+{
+ gen_flush_cc_op(s);
+ tcg_gen_movi_i32(QREG_PC, dest);
+ s->is_jmp = DISAS_JUMP;
+}
+
+static void gen_exception(DisasContext *s, uint32_t where, int nr)
+{
+ gen_flush_cc_op(s);
+ gen_jmp_im(s, where);
+ gen_helper_raise_exception(tcg_const_i32(nr));
+}
+
+static inline void gen_addr_fault(DisasContext *s)
+{
+ gen_exception(s, s->insn_pc, EXCP_ADDRESS);
+}
+
+static void gen_op_load_fpr_FP0(int freg)
+{
+ tcg_gen_ld16u_i32(QREG_FP0H, cpu_env,
+ offsetof(CPUM68KState, fregs[freg]) +
+ offsetof(FPReg, d.high));
+ tcg_gen_ld_i64(QREG_FP0L, cpu_env,
+ offsetof(CPUM68KState, fregs[freg]) +
+ offsetof(FPReg, d.low));
+}
+
+static void gen_op_store_fpr_FP0(int freg)
+{
+ tcg_gen_st16_i32(QREG_FP0H, cpu_env,
+ offsetof(CPUM68KState, fregs[freg]) +
+ offsetof(FPReg, d.high));
+ tcg_gen_st_i64(QREG_FP0L, cpu_env,
+ offsetof(CPUM68KState, fregs[freg]) +
+ offsetof(FPReg, d.low));
+}
+
+static void gen_op_load_fpr_FP1(int freg)
+{
+ tcg_gen_ld16u_i32(QREG_FP1H, cpu_env,
+ offsetof(CPUM68KState, fregs[freg]) +
+ offsetof(FPReg, d.high));
+ tcg_gen_ld_i64(QREG_FP1L, cpu_env,
+ offsetof(CPUM68KState, fregs[freg]) +
+ offsetof(FPReg, d.low));
+}
+
/* Generate a load from the specified address. Narrow values are
sign extended to full register width. */
static inline TCGv gen_load(DisasContext * s, int opsize, TCGv addr, int sign)
@@ -192,7 +253,6 @@ static inline TCGv gen_load(DisasContext * s, int opsize, TCGv addr, int sign)
tcg_gen_qemu_ld16u(tmp, addr, index);
break;
case OS_LONG:
- case OS_SINGLE:
tcg_gen_qemu_ld32u(tmp, addr, index);
break;
default:
@@ -202,17 +262,6 @@ static inline TCGv gen_load(DisasContext * s, int opsize, TCGv addr, int sign)
return tmp;
}
-static inline TCGv_i64 gen_load64(DisasContext * s, TCGv addr)
-{
- TCGv_i64 tmp;
- int index = IS_USER(s);
- s->is_mem = 1;
- tmp = tcg_temp_new_i64();
- tcg_gen_qemu_ldf64(tmp, addr, index);
- gen_throws_exception = gen_last_qop;
- return tmp;
-}
-
/* Generate a store. */
static inline void gen_store(DisasContext *s, int opsize, TCGv addr, TCGv val)
{
@@ -226,7 +275,6 @@ static inline void gen_store(DisasContext *s, int opsize, TCGv addr, TCGv val)
tcg_gen_qemu_st16(val, addr, index);
break;
case OS_LONG:
- case OS_SINGLE:
tcg_gen_qemu_st32(val, addr, index);
break;
default:
@@ -235,14 +283,6 @@ static inline void gen_store(DisasContext *s, int opsize, TCGv addr, TCGv val)
gen_throws_exception = gen_last_qop;
}
-static inline void gen_store64(DisasContext *s, TCGv addr, TCGv_i64 val)
-{
- int index = IS_USER(s);
- s->is_mem = 1;
- tcg_gen_qemu_stf64(val, addr, index);
- gen_throws_exception = gen_last_qop;
-}
-
typedef enum {
EA_STORE,
EA_LOADU,
@@ -282,10 +322,17 @@ static inline uint32_t read_im16(DisasContext *s)
static inline uint32_t read_im32(DisasContext *s)
{
uint32_t im;
- im = ((uint32_t)lduw_code(s->pc)) << 16;
- s->pc += 2;
- im |= lduw_code(s->pc);
- s->pc += 2;
+ im = read_im16(s) << 16;
+ im |= 0xffff & read_im16(s);
+ return im;
+}
+
+/* Read a 64-bit immediate constant. */
+static inline uint64_t read_im64(DisasContext *s)
+{
+ uint64_t im;
+ im = (uint64_t)read_im32(s) << 32;
+ im |= (uint64_t)read_im32(s);
return im;
}
@@ -414,13 +461,6 @@ static TCGv gen_lea_indexed(DisasContext *s, int opsize, TCGv base)
return add;
}
-/* Update the CPU env CC_OP state. */
-static inline void gen_flush_cc_op(DisasContext *s)
-{
- if (s->cc_op != CC_OP_DYNAMIC)
- tcg_gen_movi_i32(QREG_CC_OP, s->cc_op);
-}
-
/* Evaluate all the CC flags. */
static inline void gen_flush_flags(DisasContext *s)
{
@@ -469,6 +509,8 @@ static inline int opsize_bytes(int opsize)
case OS_LONG: return 4;
case OS_SINGLE: return 4;
case OS_DOUBLE: return 8;
+ case OS_EXTENDED: return 12;
+ case OS_PACKED: return 12;
default:
qemu_assert(0, "bad operand size");
return 0;
@@ -485,6 +527,20 @@ static inline int insn_opsize(int insn, int pos)
}
}
+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: abort();
+ }
+}
+
/* 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)
@@ -534,7 +590,6 @@ static inline TCGv gen_extend(TCGv val, int opsize, int sign)
tcg_gen_ext16u_i32(tmp, val);
break;
case OS_LONG:
- case OS_SINGLE:
tmp = val;
break;
default:
@@ -704,7 +759,6 @@ static TCGv gen_ea(DisasContext *s, uint16_t insn, int opsize, TCGv val,
s->pc += 2;
break;
case OS_LONG:
- case OS_SINGLE:
offset = read_im32(s);
break;
default:
@@ -719,6 +773,294 @@ static TCGv gen_ea(DisasContext *s, uint16_t insn, int opsize, TCGv val,
return NULL_QREG;
}
+static inline void gen_extend_FP0(int opsize)
+{
+ switch (opsize) {
+ case OS_BYTE:
+ tcg_gen_ext8s_i32(QREG_FP0H, QREG_FP0H);
+ gen_helper_exts32_FP0(cpu_env);
+ break;
+ case OS_WORD:
+ tcg_gen_ext16s_i32(QREG_FP0H, QREG_FP0H);
+ gen_helper_exts32_FP0(cpu_env);
+ break;
+ case OS_LONG:
+ gen_helper_exts32_FP0(cpu_env);
+ break;
+ case OS_SINGLE:
+ gen_helper_extf32_FP0(cpu_env);
+ break;
+ case OS_DOUBLE:
+ gen_helper_extf64_FP0(cpu_env);
+ break;
+ case OS_EXTENDED:
+ tcg_gen_shri_i32(QREG_FP0H, QREG_FP0H, 16);
+ break;
+ case OS_PACKED:
+ gen_helper_extp96_FP0(cpu_env);
+ break;
+ default:
+ qemu_assert(0, "FPU: Bad operand size");
+ }
+}
+
+static inline void gen_reduce_FP0(int opsize)
+{
+ switch (opsize) {
+ case OS_BYTE:
+ case OS_WORD:
+ case OS_LONG:
+ gen_helper_reds32_FP0(cpu_env);
+ break;
+ case OS_SINGLE:
+ gen_helper_redf32_FP0(cpu_env);
+ break;
+ case OS_DOUBLE:
+ gen_helper_redf64_FP0(cpu_env);
+ break;
+ case OS_EXTENDED:
+ tcg_gen_shli_i32(QREG_FP0H, QREG_FP0H, 16);
+ break;
+ case OS_PACKED:
+ gen_helper_redp96_FP0(cpu_env);
+ break;
+ default:
+ qemu_assert(0, "FPU: Bad operand size");
+ }
+}
+
+static inline void gen_load_FP0(DisasContext * s, int opsize, TCGv addr)
+{
+ TCGv tmp;
+ int index = IS_USER(s);
+ s->is_mem = 1;
+ switch(opsize) {
+ case OS_BYTE:
+ tcg_gen_qemu_ld8s(QREG_FP0H, addr, index);
+ gen_helper_exts32_FP0(cpu_env);
+ break;
+ case OS_WORD:
+ tcg_gen_qemu_ld16u(QREG_FP0H, addr, index);
+ gen_helper_exts32_FP0(cpu_env);
+ break;
+ case OS_LONG:
+ tcg_gen_qemu_ld32u(QREG_FP0H, addr, index);
+ gen_helper_exts32_FP0(cpu_env);
+ break;
+ case OS_SINGLE:
+ tcg_gen_qemu_ld32u(QREG_FP0H, addr, index);
+ gen_helper_extf32_FP0(cpu_env);
+ break;
+ case OS_DOUBLE:
+ tcg_gen_qemu_ld64(QREG_FP0L, addr, index);
+ gen_helper_extf64_FP0(cpu_env);
+ break;
+ case OS_EXTENDED:
+ tcg_gen_qemu_ld32u(QREG_FP0H, addr, index);
+ tcg_gen_shri_i32(QREG_FP0H, QREG_FP0H, 16);
+ tmp = tcg_temp_new();
+ tcg_gen_addi_i32(tmp, addr, 4);
+ tcg_gen_qemu_ld64(QREG_FP0L, tmp, index);
+ tcg_temp_free(tmp);
+ break;
+ case OS_PACKED:
+ tcg_gen_qemu_ld32u(QREG_FP0H, addr, index);
+ tmp = tcg_temp_new();
+ tcg_gen_addi_i32(tmp, addr, 4);
+ tcg_gen_qemu_ld64(QREG_FP0L, tmp, index);
+ tcg_temp_free(tmp);
+ gen_helper_extp96_FP0(cpu_env);
+ break;
+ default:
+ qemu_assert(0, "Bad operand size");
+ }
+ gen_throws_exception = gen_last_qop;
+}
+
+static inline void gen_store_FP0(DisasContext *s, int opsize, TCGv addr)
+{
+ TCGv tmp;
+ int index = IS_USER(s);
+ s->is_mem = 1;
+ switch(opsize) {
+ case OS_BYTE:
+ gen_helper_reds32_FP0(cpu_env);
+ tcg_gen_qemu_st8(QREG_FP0H, addr, index);
+ break;
+ case OS_WORD:
+ gen_helper_reds32_FP0(cpu_env);
+ tcg_gen_qemu_st16(QREG_FP0H, addr, index);
+ break;
+ case OS_LONG:
+ gen_helper_reds32_FP0(cpu_env);
+ tcg_gen_qemu_st32(QREG_FP0H, addr, index);
+ break;
+ case OS_SINGLE:
+ gen_helper_redf32_FP0(cpu_env);
+ tcg_gen_qemu_st32(QREG_FP0H, addr, index);
+ break;
+ case OS_DOUBLE:
+ gen_helper_redf64_FP0(cpu_env);
+ tcg_gen_qemu_st64(QREG_FP0L, addr, index);
+ break;
+ case OS_EXTENDED:
+ tcg_gen_shli_i32(QREG_FP0H, QREG_FP0H, 16);
+ tcg_gen_qemu_st32(QREG_FP0H, addr, index);
+ tmp = tcg_temp_new();
+ tcg_gen_addi_i32(tmp, addr, 4);
+ tcg_gen_qemu_st64(QREG_FP0L, tmp, index);
+ tcg_temp_free(tmp);
+ break;
+ case OS_PACKED:
+ gen_helper_redp96_FP0(cpu_env);
+ tcg_gen_qemu_st32(QREG_FP0H, addr, index);
+ tmp = tcg_temp_new();
+ tcg_gen_addi_i32(tmp, addr, 4);
+ tcg_gen_qemu_st64(QREG_FP0L, tmp, index);
+ tcg_temp_free(tmp);
+ break;
+ default:
+ qemu_assert(0, "Bad operand size");
+ }
+ gen_throws_exception = gen_last_qop;
+}
+
+static void gen_op_load_ea_FP0(DisasContext *s, uint16_t insn, int opsize)
+{
+ TCGv reg;
+ TCGv addr;
+ uint64_t val;
+
+ switch ((insn >> 3) & 7) {
+ case 0: /* Data register direct. */
+ tcg_gen_mov_i32(QREG_FP0H, DREG(insn, 0));
+ gen_extend_FP0(opsize);
+ break;
+ case 1: /* Address register direct. */
+ gen_addr_fault(s);
+ break;
+ case 2: /* Indirect register */
+ gen_load_FP0(s, opsize, AREG(insn, 0));
+ break;
+ case 3: /* Indirect postincrement. */
+ reg = AREG(insn, 0);
+ gen_load_FP0(s, opsize, reg);
+ tcg_gen_addi_i32(reg, reg, opsize_bytes(opsize));
+ break;
+ case 4: /* Indirect predecrememnt. */
+ addr = gen_lea(s, insn, opsize);
+ gen_load_FP0(s, opsize, addr);
+ tcg_gen_mov_i32(AREG(insn, 0), addr);
+ break;
+ case 5: /* Indirect displacement. */
+ case 6: /* Indirect index + displacement. */
+ addr = gen_lea(s, insn, opsize);
+ gen_load_FP0(s, opsize, addr);
+ break;
+ case 7: /* Other */
+ switch (insn & 7) {
+ case 0: /* Absolute short. */
+ case 1: /* Absolute long. */
+ case 2: /* pc displacement */
+ case 3: /* pc index+displacement. */
+ addr = gen_lea(s, insn, opsize);
+ gen_load_FP0(s, opsize, addr);
+ break;
+ case 4: /* Immediate. */
+ switch (opsize) {
+ case OS_BYTE:
+ val = read_im8(s);
+ tcg_gen_movi_i32(QREG_FP0H, val);
+ break;
+ case OS_WORD:
+ val = read_im16(s);
+ tcg_gen_movi_i32(QREG_FP0H, val);
+ break;
+ case OS_LONG:
+ val = read_im32(s);
+ tcg_gen_movi_i32(QREG_FP0H, val);
+ break;
+ case OS_SINGLE:
+ val = read_im32(s);
+ tcg_gen_movi_i32(QREG_FP0H, val);
+ break;
+ case OS_DOUBLE:
+ val = read_im64(s);
+ tcg_gen_movi_i64(QREG_FP0L, val);
+ break;
+ case OS_EXTENDED:
+ val = read_im32(s);
+ tcg_gen_movi_i32(QREG_FP0H, val);
+ val = read_im64(s);
+ tcg_gen_movi_i64(QREG_FP0L, val);
+ break;
+ case OS_PACKED:
+ val = read_im32(s);
+ tcg_gen_movi_i32(QREG_FP0H, val);
+ val = read_im64(s);
+ tcg_gen_movi_i64(QREG_FP0L, val);
+ break;
+ default:
+ qemu_assert(0, "Bad immediate operand");
+ }
+ gen_extend_FP0(opsize);
+ break;
+ default:
+ qemu_assert(0, "Bad FP addressing mode");
+ }
+ }
+}
+
+static void gen_op_store_ea_FP0(DisasContext *s, uint16_t insn, int opsize)
+{
+ TCGv reg;
+ TCGv addr;
+
+ switch ((insn >> 3) & 7) {
+ case 0: /* Data register direct. */
+ gen_reduce_FP0(opsize);
+ tcg_gen_mov_i32(DREG(insn, 0), QREG_FP0H);
+ break;
+ case 1: /* Address register direct. */
+ gen_addr_fault(s);
+ break;
+ case 2: /* Indirect register */
+ reg = AREG(insn, 0);
+ gen_store_FP0(s, opsize, reg);
+ break;
+ case 3: /* Indirect postincrement. */
+ reg = AREG(insn, 0);
+ gen_store_FP0(s, opsize, reg);
+ tcg_gen_addi_i32(reg, reg, opsize_bytes(opsize));
+ break;
+ case 4: /* Indirect predecrememnt. */
+ addr = gen_lea(s, insn, opsize);
+ gen_store_FP0(s, opsize, addr);
+ tcg_gen_mov_i32(AREG(insn, 0), addr);
+ break;
+ case 5: /* Indirect displacement. */
+ case 6: /* Indirect index + displacement. */
+ addr = gen_lea(s, insn, opsize);
+ gen_store_FP0(s, opsize, addr);
+ break;
+ case 7: /* Other */
+ switch (insn & 7) {
+ case 0: /* Absolute short. */
+ case 1: /* Absolute long. */
+ addr = gen_lea(s, insn, opsize);
+ gen_store_FP0(s, opsize, addr);
+ break;
+ case 2: /* pc displacement */
+ case 3: /* pc index+displacement. */
+ case 4: /* Immediate. */
+ gen_addr_fault(s);
+ break;
+ default:
+ qemu_assert(0, "Bad FP addressing mode");
+ }
+ }
+}
+
/* This generates a conditional branch, clobbering all temporaries. */
static void gen_jmpcc(DisasContext *s, int cond, int l1)
{
@@ -848,14 +1190,6 @@ static void gen_lookup_tb(DisasContext *s)
s->is_jmp = DISAS_UPDATE;
}
-/* Generate a jump to an immediate address. */
-static void gen_jmp_im(DisasContext *s, uint32_t dest)
-{
- gen_flush_cc_op(s);
- tcg_gen_movi_i32(QREG_PC, dest);
- s->is_jmp = DISAS_JUMP;
-}
-
/* Generate a jump to the address in qreg DEST. */
static void gen_jmp(DisasContext *s, TCGv dest)
{
@@ -864,18 +1198,6 @@ static void gen_jmp(DisasContext *s, TCGv dest)
s->is_jmp = DISAS_JUMP;
}
-static void gen_exception(DisasContext *s, uint32_t where, int nr)
-{
- gen_flush_cc_op(s);
- gen_jmp_im(s, where);
- gen_helper_raise_exception(tcg_const_i32(nr));
-}
-
-static inline void gen_addr_fault(DisasContext *s)
-{
- gen_exception(s, s->insn_pc, EXCP_ADDRESS);
-}
-
#define SRC_EA(result, opsize, op_sign, addrp) do { \
result = gen_ea(s, insn, opsize, NULL_QREG, addrp, op_sign ? EA_LOADS : EA_LOADU); \
if (IS_NULL_QREG(result)) { \
@@ -3159,6 +3481,70 @@ DISAS_INSN(trap)
gen_exception(s, s->pc - 2, EXCP_TRAP0 + (insn & 0xf));
}
+static void gen_op_fmovem(DisasContext *s, uint32_t insn, uint32_t ext)
+{
+ int opsize;
+ uint16_t mask;
+ int i;
+ uint32_t mode;
+ int32_t incr;
+ TCGv addr, tmp;
+ int is_load;
+
+ if (m68k_feature(s->env, M68K_FEATURE_FPU))
+ opsize = OS_EXTENDED;
+ else
+ opsize = OS_DOUBLE; // FIXME
+
+ mode = (ext >> 11) & 0x3;
+ if ((mode & 0x1) == 1) {
+ gen_helper_fmovem(cpu_env, tcg_const_i32(opsize),
+ tcg_const_i32(mode), DREG(ext, 0));
+ return;
+ }
+
+ tmp = gen_lea(s, insn, opsize);
+ if (IS_NULL_QREG(tmp)) {
+ gen_addr_fault(s);
+ return;
+ }
+
+ addr = tcg_temp_new();
+ tcg_gen_mov_i32(addr, tmp);
+ is_load = ((ext & 0x2000) == 0);
+ incr = opsize_bytes(opsize);
+ mask = ext & 0x00FF;
+
+ if (!is_load && (mode & 2) == 0) {
+ for (i = 7; i >= 0; i--, mask >>= 1) {
+ if (mask & 1) {
+ gen_op_load_fpr_FP0(i);
+ gen_store_FP0(s, opsize, addr);
+ if (mask != 1)
+ tcg_gen_subi_i32(addr, addr, incr);
+ }
+ }
+ tcg_gen_mov_i32(AREG(insn, 0), addr);
+ } else{
+ for (i = 0; i < 8; i++, mask >>=1) {
+ if (mask & 1) {
+ if (is_load) {
+ gen_load_FP0(s, opsize, addr);
+ gen_op_store_fpr_FP0(i);
+ } else {
+ gen_op_load_fpr_FP0(i);
+ gen_store_FP0(s, opsize, addr);
+ }
+ if (mask != 1 || (insn & 070) == 030)
+ tcg_gen_addi_i32(addr, addr, incr);
+ }
+ }
+ if ((insn & 070) == 030)
+ tcg_gen_mov_i32(AREG(insn, 0), addr);
+ }
+ tcg_temp_free_i32(addr);
+}
+
/* ??? FP exceptions are not implemented. Most exceptions are deferred until
immediately before the next FP instruction is executed. */
DISAS_INSN(fpu)
@@ -3166,14 +3552,10 @@ DISAS_INSN(fpu)
uint16_t ext;
uint8_t rom_offset;
int opmode;
- TCGv_i64 src;
- TCGv_i64 dest;
- TCGv_i64 res;
- TCGv tmp32;
- TCGv reg;
int round;
int set_dest;
int opsize;
+ TCGv val;
ext = read_im16(s);
opmode = ext & 0x7f;
@@ -3186,55 +3568,21 @@ DISAS_INSN(fpu)
if ( insn == 0xf200 && (ext & 0xfc00) == 0x5c00) {
/* fmovecr */
rom_offset = ext & 0x7f;
- dest = FREG(ext, 7);
- gen_helper_const_f64(dest, cpu_env, tcg_const_i32(rom_offset));
+ gen_helper_const_FP0(cpu_env, tcg_const_i32(rom_offset));
+ gen_op_store_fpr_FP0(REG(ext, 7));
return;
}
break;
case 3: /* fmove out */
- src = FREG(ext, 7);
- tmp32 = tcg_temp_new_i32();
- /* fmove */
- /* ??? TODO: Proper behavior on overflow. */
- 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;
- }
- if (opsize == OS_DOUBLE) {
- tmp32 = gen_lea(s, insn, opsize);
- if (IS_NULL_QREG(tmp32)) {
- gen_addr_fault(s);
- return;
- }
- gen_store64(s, tmp32, src);
- if ( ((insn >> 3) & 7) == 3) { /* post-increment */
- reg = AREG(insn, 0);
- tcg_gen_addi_i32(reg, reg, opsize_bytes(opsize));
- }
- } else {
- switch (opsize) {
- case OS_LONG:
- case OS_WORD:
- case OS_BYTE:
- gen_helper_f64_to_i32(tmp32, cpu_env, src);
- break;
- case OS_SINGLE:
- gen_helper_f64_to_f32(tmp32, cpu_env, src);
- break;
- }
- DEST_EA(insn, opsize, tmp32, NULL);
- }
- tcg_temp_free_i32(tmp32);
+ opsize = ext_opsize(ext, 10);
+ gen_op_load_fpr_FP0(REG(ext, 7));
+ gen_op_store_ea_FP0(s, insn, opsize);
return;
case 4: /* fmove to control register. */
switch ((ext >> 10) & 7) {
case 4: /* FPCR */
- /* Not implemented. Ignore writes. */
+ SRC_EA(val, OS_LONG, 0, NULL);
+ gen_helper_set_fpcr(cpu_env, val);
break;
case 1: /* FPIAR */
case 2: /* FPSR */
@@ -3247,187 +3595,95 @@ DISAS_INSN(fpu)
switch ((ext >> 10) & 7) {
case 4: /* FPCR */
/* Not implemented. Always return zero. */
- tmp32 = tcg_const_i32(0);
- break;
+ DEST_EA(insn, OS_LONG, QEMU_FPCR, NULL);
+ return;
case 1: /* FPIAR */
+ cpu_abort(NULL, "Unimplemented: fmove from control FPIAR");
+ goto undef;
case 2: /* FPSR */
+ DEST_EA(insn, OS_LONG, QEMU_FPSR, NULL);
+ return;
default:
cpu_abort(NULL, "Unimplemented: fmove from control %d",
(ext >> 10) & 7);
goto undef;
}
- DEST_EA(insn, OS_LONG, tmp32, NULL);
break;
case 6: /* fmovem */
case 7:
- {
- TCGv addr;
- int incr;
- uint16_t mask;
- int i;
- if ((ext & 0xf00) != 0 || (ext & 0xff) == 0)
- goto undef;
- if ((ext & 0x1000) == 0 && !m68k_feature(s->env, M68K_FEATURE_FPU))
- goto undef;
- if ((insn & 070) == 040)
- tmp32 = AREG(insn, 0);
- else {
- tmp32 = gen_lea(s, insn, OS_LONG);
- if (IS_NULL_QREG(tmp32)) {
- gen_addr_fault(s);
- return;
- }
- }
- addr = tcg_temp_new_i32();
- tcg_gen_mov_i32(addr, tmp32);
- mask = 0x80;
- if (m68k_feature(s->env, M68K_FEATURE_FPU))
- incr = 12;
- else
- incr = 8;
- if ((ext & (1 << 13)) && (insn & 070) == 040) {
- for (i = 0; i < 8; i++) {
- if (ext & mask) {
- s->is_mem = 1;
- dest = FREG(i, 7);
- tcg_gen_subi_i32(addr, addr, incr);
- tcg_gen_mov_i32(AREG(insn, 0), addr);
- tcg_gen_qemu_stf64(dest, addr, IS_USER(s));
- }
- mask >>= 1;
- }
- tcg_temp_free_i32(addr);
- return;
- }
- for (i = 0; i < 8; i++) {
- if (ext & mask) {
- s->is_mem = 1;
- dest = FREG(i, 0);
- if (ext & (1 << 13)) {
- /* store */
- tcg_gen_qemu_stf64(dest, addr, IS_USER(s));
- } else {
- /* load */
- tcg_gen_qemu_ldf64(dest, addr, IS_USER(s));
- }
- if (ext & (mask - 1) || (insn & 070) == 030) {
- tcg_gen_addi_i32(addr, addr, incr);
- if ((insn & 070) == 030)
- tcg_gen_mov_i32(AREG(insn, 0), addr);
- }
- }
- mask >>= 1;
- }
- tcg_temp_free_i32(addr);
- }
+ if ((ext & 0xf00) != 0 || (ext & 0xff) == 0)
+ goto undef;
+ if ((ext & 0x1000) == 0 && !m68k_feature(s->env, M68K_FEATURE_FPU))
+ goto undef;
+ gen_op_fmovem(s, insn, ext);
return;
}
+ opsize = ext_opsize(ext, 10);
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;
- }
- if (opsize == OS_DOUBLE) {
- if ((insn & 0x3f) == 0x3c) {
- src = gen_load64(s, tcg_const_i32(s->pc));
- s->pc += 8;
- } else {
- tmp32 = gen_lea(s, insn, opsize);
- if (IS_NULL_QREG(tmp32)) {
- gen_addr_fault(s);
- return;
- }
- src = gen_load64(s, tmp32);
- if ( ((insn >> 3) & 7) == 3) { /* post-increment */
- reg = AREG(insn, 0);
- tcg_gen_addi_i32(reg, reg, opsize_bytes(opsize));
- }
- }
- } else {
- SRC_EA(tmp32, opsize, 1, NULL);
- src = tcg_temp_new_i64();
- switch (opsize) {
- case OS_LONG:
- case OS_WORD:
- case OS_BYTE:
- gen_helper_i32_to_f64(src, cpu_env, tmp32);
- break;
- case OS_SINGLE:
- gen_helper_f32_to_f64(src, cpu_env, tmp32);
- break;
- }
- }
+ gen_op_load_ea_FP0(s, insn, opsize);
} else {
/* Source register. */
- src = FREG(ext, 10);
+ gen_op_load_fpr_FP0(REG(ext, 10));
}
- dest = FREG(ext, 7);
- res = tcg_temp_new_i64();
- if (opmode != 0x3a)
- tcg_gen_mov_f64(res, dest);
round = 1;
set_dest = 1;
switch (opmode) {
case 0: case 0x40: case 0x44: /* fmove */
- tcg_gen_mov_f64(res, src);
break;
case 1: /* fint */
- gen_helper_iround_f64(res, cpu_env, src);
+ gen_helper_iround_FP0(cpu_env);
round = 0;
break;
case 3: /* fintrz */
- gen_helper_itrunc_f64(res, cpu_env, src);
+ gen_helper_itrunc_FP0(cpu_env);
round = 0;
break;
case 4: case 0x41: case 0x45: /* fsqrt */
- gen_helper_sqrt_f64(res, cpu_env, src);
+ gen_helper_sqrt_FP0(cpu_env);
break;
case 0x18: case 0x58: case 0x5c: /* fabs */
- gen_helper_abs_f64(res, src);
+ gen_helper_abs_FP0(cpu_env);
break;
case 0x1a: case 0x5a: case 0x5e: /* fneg */
- gen_helper_chs_f64(res, src);
+ gen_helper_chs_FP0(cpu_env);
break;
case 0x20: case 0x60: case 0x64: /* fdiv */
- gen_helper_div_f64(res, cpu_env, res, src);
+ gen_op_load_fpr_FP1(REG(ext, 7));
+ gen_helper_div_FP0_FP1(cpu_env);
break;
case 0x22: case 0x62: case 0x66: /* fadd */
- gen_helper_add_f64(res, cpu_env, res, src);
+ gen_op_load_fpr_FP1(REG(ext, 7));
+ gen_helper_add_FP0_FP1(cpu_env);
break;
case 0x23: case 0x63: case 0x67: /* fmul */
- gen_helper_mul_f64(res, cpu_env, res, src);
+ gen_op_load_fpr_FP1(REG(ext, 7));
+ gen_helper_mul_FP0_FP1(cpu_env);
break;
case 0x24: /* fsgldiv */
- gen_helper_div_f64(res, cpu_env, res, src);
+ gen_op_load_fpr_FP1(REG(ext, 7));
+ gen_helper_div_FP0_FP1(cpu_env);
break;
case 0x27: /* fsglmul */
- gen_helper_mul_f64(res, cpu_env, res, src);
+ gen_op_load_fpr_FP1(REG(ext, 7));
+ gen_helper_mul_FP0_FP1(cpu_env);
break;
case 0x28: case 0x68: case 0x6c: /* fsub */
- gen_helper_sub_f64(res, cpu_env, res, src);
+ gen_op_load_fpr_FP1(REG(ext, 7));
+ gen_helper_sub_FP0_FP1(cpu_env);
break;
case 0x38: /* fcmp */
- gen_helper_sub_cmp_f64(res, cpu_env, res, src);
+ gen_op_load_fpr_FP1(REG(ext, 7));
+ gen_helper_fcmp_FP0_FP1(cpu_env);
set_dest = 0;
round = 0;
break;
case 0x3a: /* ftst */
- tcg_gen_mov_f64(res, src);
set_dest = 0;
round = 0;
break;
default:
goto undef;
}
- if (ext & (1 << 14)) {
- tcg_temp_free_i64(src);
- }
if (round) {
if (opmode & 0x40) {
if ((opmode & 0x4) != 0)
@@ -3437,16 +3693,16 @@ DISAS_INSN(fpu)
}
}
if (round) {
+#if 0
TCGv tmp = tcg_temp_new_i32();
gen_helper_f64_to_f32(tmp, cpu_env, res);
gen_helper_f32_to_f64(res, cpu_env, tmp);
tcg_temp_free_i32(tmp);
+#endif
}
- tcg_gen_mov_f64(QREG_FP_RESULT, res);
if (set_dest) {
- tcg_gen_mov_f64(dest, res);
+ gen_op_store_fpr_FP0(REG(ext, 7));
}
- tcg_temp_free_i64(res);
return;
undef:
/* FIXME: Is this right for offset addressing modes? */
@@ -3460,7 +3716,7 @@ static void gen_fjmpcc(DisasContext *s, int cond, int l1)
/* TODO: Raise BSUN exception. */
flag = tcg_temp_new();
- gen_helper_compare_f64(flag, cpu_env, QREG_FP_RESULT);
+ gen_helper_compare_FP0(flag, cpu_env);
/* Jump to l1 if condition is true. */
switch (cond) {
case 0: /* f */
@@ -3484,12 +3740,12 @@ static void gen_fjmpcc(DisasContext *s, int cond, int l1)
tcg_gen_andi_i32(flag, flag, 1);
tcg_gen_brcond_i32(TCG_COND_NE, flag, tcg_const_i32(0), l1);
break;
- case 7: /* or (=2) */
- tcg_gen_brcond_i32(TCG_COND_EQ, flag, tcg_const_i32(2), l1);
- break;
- case 8: /* un (<2) */
+ case 7: /* or (<2) */
tcg_gen_brcond_i32(TCG_COND_LT, flag, tcg_const_i32(2), l1);
break;
+ case 8: /* un (=2) */
+ tcg_gen_brcond_i32(TCG_COND_EQ, flag, tcg_const_i32(2), l1);
+ break;
case 9: /* ueq (=0 or =2) */
tcg_gen_andi_i32(flag, flag, 1);
tcg_gen_brcond_i32(TCG_COND_EQ, flag, tcg_const_i32(0), l1);
@@ -4337,20 +4593,18 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
{
int i;
uint16_t sr;
- CPU_DoubleU u;
for (i = 0; i < 8; i++)
{
- u.d = env->fregs[i];
- cpu_fprintf (f, "D%d = %08x A%d = %08x F%d = %08x%08x (%12g)\n",
+ cpu_fprintf (f, "D%d = %08x A%d = %08x "
+ "F%d = %" PRIxFPH " %" PRIxFPL "\n",
i, env->dregs[i], i, env->aregs[i],
- i, u.l.upper, u.l.lower, *(double *)&u.d);
+ i, env->fregs[i].d.high, env->fregs[i].d.low);
}
cpu_fprintf (f, "PC = %08x ", env->pc);
sr = env->sr;
cpu_fprintf (f, "SR = %04x %c%c%c%c%c ", sr, (sr & 0x10) ? 'X' : '-',
(sr & CCF_N) ? 'N' : '-', (sr & CCF_Z) ? 'Z' : '-',
(sr & CCF_V) ? 'V' : '-', (sr & CCF_C) ? 'C' : '-');
- cpu_fprintf (f, "FPRESULT = %12g\n", *(double *)&env->fp_result);
}
void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
diff --git a/tests/m68k/Makefile b/tests/m68k/Makefile
new file mode 100644
index 0000000..8f09805
--- /dev/null
+++ b/tests/m68k/Makefile
@@ -0,0 +1,15 @@
+TESTS=fmovecr fmove fmovem
+
+all: $(TESTS)
+
+%: %.S
+ m68k-linux-gnu-gcc -m68040 -nostartfiles -nodefaultlibs -nostdlib -o $@ $<
+
+fmovecr: fmovecr.S
+fmove: fmove.S
+fmovem: fmovem.S
+
+.PHONY: clean
+
+clean:
+ rm -f $(TESTS)
diff --git a/tests/m68k/fmove.S b/tests/m68k/fmove.S
new file mode 100644
index 0000000..3f2daba
--- /dev/null
+++ b/tests/m68k/fmove.S
@@ -0,0 +1,55 @@
+ .include "trap.i"
+
+ .data
+tmp: .long 0x88776655
+pi: .long 0x40000000
+ .long 0xc90fdaa2
+ .long 0x2168C235
+
+ .text
+ .globl _start
+_start:
+ lea pi,%a0
+ move.l (%a0), %d0
+ fmove.x (%a0), %fp4
+ # Dn
+
+ move.l #-1, %d3
+ fmove.b %d3, %fp0
+ fmove.w %d3, %fp1
+ fmove.l %d3, %fp2
+ fmove.s %d3, %fp3
+
+ move.l #1, %d1
+ fmove.b %d1, %fp0
+ fmove.w %d1, %fp1
+ fmove.l %d1, %fp2
+ fmove.s %d1, %fp3
+
+ move.l #0x11223344, %d1
+ fmove.b %d1, %fp1
+ fmove.w %d1, %fp2
+ fmove.l %d1, %fp3
+ fmove.s %d1, %fp4
+
+ # (A0)
+
+ lea tmp,%a0
+ fmove.b (%a0), %fp0
+ fmove.w (%a0), %fp1
+ fmove.l (%a0), %fp2
+ fmove.l (%a0), %fp3
+ lea pi,%a0
+ fmove.x (%a0), %fp4
+
+ # immediate values
+
+ fmove.b #0xFF,%fp0
+ fmove.w #0xFABC,%fp1
+ fmove.l #0xFABCDEFA,%fp2
+ fmove.s #0xDEADBEAF,%fp3
+ fmove.d #0xFABCDEFADEADBEAF,%fp4
+ fmove.x #0xFABCDEFADEADBEAF12345678,%fp5
+ fmove.p #0xFABCDEFADEADBEAF12345678,%fp6
+
+ exit 0
diff --git a/tests/m68k/fmovecr.S b/tests/m68k/fmovecr.S
new file mode 100644
index 0000000..c6cd82b
--- /dev/null
+++ b/tests/m68k/fmovecr.S
@@ -0,0 +1,29 @@
+ .include "trap.i"
+
+ .text
+ .globl _start
+_start:
+ fmovecr.x #0x00,%fp0
+ fmovecr.x #0x0B,%fp0
+ fmovecr.x #0x0C,%fp0
+ fmovecr.x #0x0D,%fp0
+ fmovecr.x #0x0E,%fp0
+ fmovecr.x #0x0F,%fp0
+ fmovecr.x #0x30,%fp0
+ fmovecr.x #0x31,%fp0
+ fmovecr.x #0x32,%fp0
+ fmovecr.x #0x33,%fp0
+ fmovecr.x #0x34,%fp0
+ fmovecr.x #0x35,%fp0
+ fmovecr.x #0x36,%fp0
+ fmovecr.x #0x37,%fp0
+ fmovecr.x #0x38,%fp0
+ fmovecr.x #0x39,%fp0
+ fmovecr.x #0x3A,%fp0
+ fmovecr.x #0x3B,%fp0
+ fmovecr.x #0x3c,%fp0
+ fmovecr.x #0x3d,%fp0
+ fmovecr.x #0x3e,%fp0
+ fmovecr.x #0x3f,%fp0
+
+ exit 0
diff --git a/tests/m68k/fmovem.S b/tests/m68k/fmovem.S
new file mode 100644
index 0000000..35da35f
--- /dev/null
+++ b/tests/m68k/fmovem.S
@@ -0,0 +1,17 @@
+ .include "trap.i"
+
+ .data
+pi: .long 0x40000000
+ .long 0xc90fdaa2
+ .long 0x2168C235
+ln2: .long 0x3ffe0000
+ .long 0xb17217f7
+ .long 0xd1cf79ac
+
+ .text
+ .globl _start
+_start:
+ lea pi,%a0
+ fmovem.x (%a0), %fp2-%fp3
+ fmovem.x (%a0)+, %fp0-%fp1
+ exit 0
diff --git a/tests/m68k/trap.i b/tests/m68k/trap.i
new file mode 100644
index 0000000..ce7aa1e
--- /dev/null
+++ b/tests/m68k/trap.i
@@ -0,0 +1,5 @@
+.macro exit value
+ move.l #\value,%d1
+ move.l #1, %d0
+ trap #0
+.endm
--
1.7.2.3
next prev parent reply other threads:[~2011-08-17 20:50 UTC|newest]
Thread overview: 125+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-08-17 20:46 [Qemu-devel] [RFC][PATCH 000/111] QEMU m68k core additions Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 001/111] linux-user: Signals processing is not thread-safe Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 002/111] linux-user: add qemu-wrapper Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 003/111] linux-user: define default cpu model in configure instead of linux-user/main.c Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 004/111] linux-user: specify the cpu model during configure Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 005/111] linux-user,m68k: display default cpu Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 006/111] linux-user: define new environment variables Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 007/111] linux-user: define a script to set binfmt using debian flavored tools Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 008/111] linux-user: define default cpu model in configure instead of linux-user/main.c Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 009/111] m68k: add tcg_gen_debug_insn_start() Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 010/111] m68k: define m680x0 CPUs and features Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 011/111] m68k: add missing accessing modes for some instructions Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 012/111] m68k: add Motorola 680x0 family common instructions Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 013/111] m68k: add Scc instruction with memory operand Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 014/111] m68k: add DBcc instruction Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 015/111] m68k: modify movem instruction to manage word Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 016/111] m68k: add 64bit divide Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 017/111] m68k: add 32bit and 64bit multiply Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 018/111] m68k: add word data size for suba/adda Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 019/111] m68k: add fpu Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 020/111] m68k: add "byte", "word" and memory shift Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 021/111] m68k: add "byte", "word" and memory rotate Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 022/111] m68k: add bitfield_mem, bitfield_reg Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 023/111] m68k: add variable offset/width to bitfield_reg/bitfield_mem Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 024/111] m68k: add cas Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 025/111] " Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 026/111] m68k: define fcntl constants Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 027/111] m68k: add DBcc instruction Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 028/111] m68k: allow fpu to manage double data type Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 029/111] m68k: allow fpu to manage double data type with fmove to <ea> Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 030/111] m68k: add FScc instruction Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 031/111] m68k: add single data type to gen_ea Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 032/111] m68k: add linkl instruction Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 033/111] m68k: Add fmovecr Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 034/111] m68k: correct typo on f64_to_i32() return type Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 035/111] m68k: improve CC_OP_LOGIC Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 036/111] m68k: correct neg condition code flags computation Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 037/111] Correct invalid use of "const void *" with "const uint8_t *" Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 038/111] m68k: add EA support for negx Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 039/111] m68k: add abcd instruction Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 040/111] m68k: add sbcd instruction Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 041/111] mm68k: add nbcd instruction Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 042/111] m68k: set X flag according size of operand Set X flag correctly for addsub, arith_im, addsubq Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 043/111] m68k: on 0 bit shift, don't update X flag Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 044/111] m68k: improve addx instructions Add (byte, word) opsize Add memory access Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 045/111] m68k: improve subx, negx instructions Add (byte, word) opsize Add memory access (subx) Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 046/111] m68k: improve asl/asr evaluate correclty the missing V flag Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 047/111] m68k: use read_imm1() when it is possible Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 048/111] m68k: correct shift side effect for roxrl and roxll Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 049/111] m68k: asl/asr, clear C flag if shift count is 0 Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 050/111] m68k: lsl/lsr, " Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 051/111] m68k: correct divs.w and divu.w Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 052/111] m68k: correct flags with negl Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 053/111] m68k: for bitfield opcodes, correct operands corruption Bryce Lanham
2011-08-17 20:46 ` [Qemu-devel] [PATCH 054/111] m68k: Added ULL to 64 bit integer in helper.c Bryce Lanham
2011-08-17 20:47 ` [Qemu-devel] [PATCH 055/111] m68k: Correct bfclr in register case Bryce Lanham
2011-08-17 20:47 ` [Qemu-devel] [PATCH 056/111] m68k-linux-user: add '--enable-emulop' Bryce Lanham
2011-08-17 20:47 ` [Qemu-devel] [PATCH 057/111] m68k: correctly compute divsl Bryce Lanham
2011-08-17 20:47 ` [Qemu-devel] [PATCH 058/111] m68k: correctly compute divul Bryce Lanham
2011-08-17 20:47 ` [Qemu-devel] [PATCH 059/111] m68k: add m68030 definition Bryce Lanham
2011-08-17 20:47 ` [Qemu-devel] [PATCH 060/111] m68k: remove dead code Bryce Lanham
2011-08-17 20:47 ` [Qemu-devel] [PATCH 061/111] m68k: remove useless file m68k-qreg.h Bryce Lanham
2011-08-17 20:47 ` Bryce Lanham [this message]
2011-08-17 20:47 ` [Qemu-devel] [PATCH 063/111] m68k: some FPU debugging macros Bryce Lanham
2011-08-17 20:47 ` [Qemu-devel] [PATCH 064/111] m68k: more tests Bryce Lanham
2011-08-17 20:47 ` [Qemu-devel] [PATCH 065/111] m68k: correct compute gen_bitfield_cc() Bryce Lanham
2011-08-17 20:47 ` [Qemu-devel] [PATCH 066/111] m68k: add fgetexp Bryce Lanham
2011-08-17 20:47 ` [Qemu-devel] [PATCH 067/111] m68k: add fscale Bryce Lanham
2011-08-17 20:47 ` [Qemu-devel] [PATCH 068/111] m68k: correct addsubq Bryce Lanham
2011-08-17 20:47 ` [Qemu-devel] [PATCH 069/111] m68k: add fetox and flogn Bryce Lanham
2011-08-17 20:47 ` [Qemu-devel] [PATCH 070/111] m68k: initialize FRegs, define pickNaN() Bryce Lanham
2011-08-17 20:47 ` [Qemu-devel] [PATCH 071/111] m68k: correct cmpa comparison datatype Bryce Lanham
2011-08-17 20:47 ` [Qemu-devel] [PATCH 072/111] m68k: add flog10 Bryce Lanham
2011-08-17 20:47 ` [Qemu-devel] [PATCH 073/111] m68k: add cmpm instruction Bryce Lanham
2011-08-17 20:47 ` [Qemu-devel] [PATCH 074/111] m68k: add ftwotox instruction Bryce Lanham
2011-08-17 20:47 ` [Qemu-devel] [PATCH 075/111] m68k: better fpu traces Bryce Lanham
2011-08-17 20:47 ` [Qemu-devel] [PATCH 076/111] m68k: register source operand is always in extended size Bryce Lanham
2011-08-17 20:47 ` [Qemu-devel] [PATCH 077/111] m68k: add facos instruction Bryce Lanham
2011-08-17 20:47 ` [Qemu-devel] [PATCH 078/111] m68k: add ftan instruction Bryce Lanham
2011-08-17 20:47 ` [Qemu-devel] [PATCH 079/111] m68k: add fsin instruction Bryce Lanham
2011-08-17 20:47 ` [Qemu-devel] [PATCH 080/111] m68k: add fcos instruction Bryce Lanham
2011-08-17 20:47 ` [Qemu-devel] [PATCH 081/111] m68k: correct fpcr update Bryce Lanham
2011-08-17 20:47 ` [Qemu-devel] [PATCH 082/111] m68k: add fmod instruction Bryce Lanham
2011-08-17 20:47 ` [Qemu-devel] [PATCH 083/111] m68k: flush flags before negx instruction Bryce Lanham
2011-08-17 20:47 ` [Qemu-devel] [PATCH 084/111] m68k: correct fmovemx FP registers order Bryce Lanham
2011-08-17 20:47 ` [Qemu-devel] [PATCH 085/111] m68k: add fatan instruction Bryce Lanham
2011-08-17 20:47 ` [Qemu-devel] [PATCH 086/111] m68k: correct bfins instruction Bryce Lanham
2011-08-17 20:47 ` [Qemu-devel] [PATCH 087/111] m68k: fcmp correctly compares infinity Bryce Lanham
2011-08-17 22:35 ` [Qemu-devel] [RFC][PATCH 000/111] QEMU m68k core additions Anthony Liguori
2011-08-17 23:30 ` Bryce Lanham
2011-08-17 23:36 ` Peter Maydell
2011-08-18 16:05 ` Michael Roth
2011-08-18 7:02 ` Laurent Vivier
2011-08-18 11:12 ` François Revol
2011-08-18 14:02 ` Laurent Vivier
2011-08-18 19:42 ` Natalia Portillo
2011-08-18 19:57 ` Laurent Vivier
2011-08-18 20:13 ` Natalia Portillo
2011-08-18 20:51 ` Laurent Vivier
2011-08-19 2:14 ` Natalia Portillo
2011-08-19 8:55 ` François Revol
2011-08-19 15:52 ` Natalia Portillo
2011-08-19 16:07 ` Laurent Vivier
2011-08-19 20:08 ` Anthony Liguori
2011-08-20 22:12 ` Rob Landley
2011-08-20 22:12 ` Rob Landley
2011-08-20 22:16 ` Rob Landley
2011-08-20 21:06 ` Rob Landley
2011-08-20 20:57 ` Rob Landley
2011-08-20 21:16 ` Laurent Vivier
2011-08-20 22:28 ` Rob Landley
2011-08-20 22:39 ` Rob Landley
2011-08-20 23:24 ` Rob Landley
2011-08-20 20:55 ` Rob Landley
2011-08-20 23:17 ` Natalia Portillo
2011-08-20 23:42 ` Rob Landley
2011-08-21 0:23 ` Natalia Portillo
2011-08-21 0:50 ` Rob Landley
2011-08-21 2:02 ` Natalia Portillo
2011-08-21 22:14 ` Rob Landley
2011-08-22 2:15 ` Natalia Portillo
2011-08-23 12:30 ` Rob Landley
2011-08-21 10:04 ` Laurent Vivier
2011-08-21 13:11 ` Natalia Portillo
2011-08-21 22:23 ` Rob Landley
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1313614076-28878-63-git-send-email-blanham@gmail.com \
--to=blanham@gmail.com \
--cc=laurent@vivier.eu \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.