mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-06 09:13:55 -06:00
TCG variable type checking.
Signed-off-by: Paul Brook <paul@codesourcery.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5729 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
30913bae9a
commit
a7812ae412
37 changed files with 6201 additions and 5766 deletions
|
@ -1,138 +1,54 @@
|
|||
#ifndef DEF_HELPER
|
||||
#define DEF_HELPER(name, ret, args) ret glue(helper_,name) args;
|
||||
#endif
|
||||
#include "def-helper.h"
|
||||
|
||||
#ifdef GEN_HELPER
|
||||
#define DEF_HELPER_0_0(name, ret, args) \
|
||||
DEF_HELPER(name, ret, args) \
|
||||
static inline void gen_helper_##name(void) \
|
||||
{ \
|
||||
tcg_gen_helper_0_0(helper_##name); \
|
||||
}
|
||||
#define DEF_HELPER_0_1(name, ret, args) \
|
||||
DEF_HELPER(name, ret, args) \
|
||||
static inline void gen_helper_##name(TCGv arg1) \
|
||||
{ \
|
||||
tcg_gen_helper_0_1(helper_##name, arg1); \
|
||||
}
|
||||
#define DEF_HELPER_0_2(name, ret, args) \
|
||||
DEF_HELPER(name, ret, args) \
|
||||
static inline void gen_helper_##name(TCGv arg1, TCGv arg2) \
|
||||
{ \
|
||||
tcg_gen_helper_0_2(helper_##name, arg1, arg2); \
|
||||
}
|
||||
#define DEF_HELPER_0_3(name, ret, args) \
|
||||
DEF_HELPER(name, ret, args) \
|
||||
static inline void gen_helper_##name( \
|
||||
TCGv arg1, TCGv arg2, TCGv arg3) \
|
||||
{ \
|
||||
tcg_gen_helper_0_3(helper_##name, arg1, arg2, arg3); \
|
||||
}
|
||||
#define DEF_HELPER_1_0(name, ret, args) \
|
||||
DEF_HELPER(name, ret, args) \
|
||||
static inline void gen_helper_##name(TCGv ret) \
|
||||
{ \
|
||||
tcg_gen_helper_1_0(helper_##name, ret); \
|
||||
}
|
||||
#define DEF_HELPER_1_1(name, ret, args) \
|
||||
DEF_HELPER(name, ret, args) \
|
||||
static inline void gen_helper_##name(TCGv ret, TCGv arg1) \
|
||||
{ \
|
||||
tcg_gen_helper_1_1(helper_##name, ret, arg1); \
|
||||
}
|
||||
#define DEF_HELPER_1_2(name, ret, args) \
|
||||
DEF_HELPER(name, ret, args) \
|
||||
static inline void gen_helper_##name(TCGv ret, TCGv arg1, TCGv arg2) \
|
||||
{ \
|
||||
tcg_gen_helper_1_2(helper_##name, ret, arg1, arg2); \
|
||||
}
|
||||
#define DEF_HELPER_1_3(name, ret, args) \
|
||||
DEF_HELPER(name, ret, args) \
|
||||
static inline void gen_helper_##name(TCGv ret, \
|
||||
TCGv arg1, TCGv arg2, TCGv arg3) \
|
||||
{ \
|
||||
tcg_gen_helper_1_3(helper_##name, ret, arg1, arg2, arg3); \
|
||||
}
|
||||
#define DEF_HELPER_1_4(name, ret, args) \
|
||||
DEF_HELPER(name, ret, args) \
|
||||
static inline void gen_helper_##name(TCGv ret, \
|
||||
TCGv arg1, TCGv arg2, TCGv arg3, TCGv arg4) \
|
||||
{ \
|
||||
tcg_gen_helper_1_4(helper_##name, ret, arg1, arg2, arg3, arg4); \
|
||||
}
|
||||
#else /* !GEN_HELPER */
|
||||
#define DEF_HELPER_0_0 DEF_HELPER
|
||||
#define DEF_HELPER_0_1 DEF_HELPER
|
||||
#define DEF_HELPER_0_2 DEF_HELPER
|
||||
#define DEF_HELPER_0_3 DEF_HELPER
|
||||
#define DEF_HELPER_1_0 DEF_HELPER
|
||||
#define DEF_HELPER_1_1 DEF_HELPER
|
||||
#define DEF_HELPER_1_2 DEF_HELPER
|
||||
#define DEF_HELPER_1_3 DEF_HELPER
|
||||
#define DEF_HELPER_1_4 DEF_HELPER
|
||||
#define HELPER(x) glue(helper_,x)
|
||||
#endif
|
||||
DEF_HELPER_1(bitrev, i32, i32)
|
||||
DEF_HELPER_1(ff1, i32, i32)
|
||||
DEF_HELPER_2(sats, i32, i32, i32)
|
||||
DEF_HELPER_2(divu, void, env, i32)
|
||||
DEF_HELPER_2(divs, void, env, i32)
|
||||
DEF_HELPER_3(addx_cc, i32, env, i32, i32)
|
||||
DEF_HELPER_3(subx_cc, i32, env, i32, i32)
|
||||
DEF_HELPER_3(shl_cc, i32, env, i32, i32)
|
||||
DEF_HELPER_3(shr_cc, i32, env, i32, i32)
|
||||
DEF_HELPER_3(sar_cc, i32, env, i32, i32)
|
||||
DEF_HELPER_2(xflag_lt, i32, i32, i32)
|
||||
DEF_HELPER_2(set_sr, void, env, i32)
|
||||
DEF_HELPER_3(movec, void, env, i32, i32)
|
||||
|
||||
DEF_HELPER_1_1(bitrev, uint32_t, (uint32_t))
|
||||
DEF_HELPER_1_1(ff1, uint32_t, (uint32_t))
|
||||
DEF_HELPER_1_2(sats, uint32_t, (uint32_t, uint32_t))
|
||||
DEF_HELPER_0_2(divu, void, (CPUState *, uint32_t))
|
||||
DEF_HELPER_0_2(divs, void, (CPUState *, uint32_t))
|
||||
DEF_HELPER_1_3(addx_cc, uint32_t, (CPUState *, uint32_t, uint32_t))
|
||||
DEF_HELPER_1_3(subx_cc, uint32_t, (CPUState *, uint32_t, uint32_t))
|
||||
DEF_HELPER_1_3(shl_cc, uint32_t, (CPUState *, uint32_t, uint32_t))
|
||||
DEF_HELPER_1_3(shr_cc, uint32_t, (CPUState *, uint32_t, uint32_t))
|
||||
DEF_HELPER_1_3(sar_cc, uint32_t, (CPUState *, uint32_t, uint32_t))
|
||||
DEF_HELPER_1_2(xflag_lt, uint32_t, (uint32_t, uint32_t))
|
||||
DEF_HELPER_0_2(set_sr, void, (CPUState *, uint32_t))
|
||||
DEF_HELPER_0_3(movec, void, (CPUState *, uint32_t, uint32_t))
|
||||
DEF_HELPER_2(f64_to_i32, f32, 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_2(f64_to_i32, float32, (CPUState *, float64))
|
||||
DEF_HELPER_1_2(f64_to_f32, float32, (CPUState *, float64))
|
||||
DEF_HELPER_1_2(i32_to_f64, float64, (CPUState *, uint32_t))
|
||||
DEF_HELPER_1_2(f32_to_f64, float64, (CPUState *, float32))
|
||||
DEF_HELPER_1_2(iround_f64, float64, (CPUState *, float64))
|
||||
DEF_HELPER_1_2(itrunc_f64, float64, (CPUState *, float64))
|
||||
DEF_HELPER_1_2(sqrt_f64, float64, (CPUState *, float64))
|
||||
DEF_HELPER_1_1(abs_f64, float64, (float64))
|
||||
DEF_HELPER_1_1(chs_f64, float64, (float64))
|
||||
DEF_HELPER_1_3(add_f64, float64, (CPUState *, float64, float64))
|
||||
DEF_HELPER_1_3(sub_f64, float64, (CPUState *, float64, float64))
|
||||
DEF_HELPER_1_3(mul_f64, float64, (CPUState *, float64, float64))
|
||||
DEF_HELPER_1_3(div_f64, float64, (CPUState *, float64, float64))
|
||||
DEF_HELPER_1_3(sub_cmp_f64, float64, (CPUState *, float64, float64))
|
||||
DEF_HELPER_1_2(compare_f64, uint32_t, (CPUState *, float64))
|
||||
DEF_HELPER_3(mac_move, void, env, i32, i32)
|
||||
DEF_HELPER_3(macmulf, i64, env, i32, i32)
|
||||
DEF_HELPER_3(macmuls, i64, env, i32, i32)
|
||||
DEF_HELPER_3(macmulu, i64, env, i32, i32)
|
||||
DEF_HELPER_2(macsats, void, env, i32)
|
||||
DEF_HELPER_2(macsatu, void, env, i32)
|
||||
DEF_HELPER_2(macsatf, void, env, i32)
|
||||
DEF_HELPER_2(mac_set_flags, void, env, i32)
|
||||
DEF_HELPER_2(set_macsr, void, env, i32)
|
||||
DEF_HELPER_2(get_macf, i32, env, i64)
|
||||
DEF_HELPER_1(get_macs, i32, i64)
|
||||
DEF_HELPER_1(get_macu, i32, i64)
|
||||
DEF_HELPER_2(get_mac_extf, i32, env, i32)
|
||||
DEF_HELPER_2(get_mac_exti, i32, env, i32)
|
||||
DEF_HELPER_3(set_mac_extf, void, env, i32, i32)
|
||||
DEF_HELPER_3(set_mac_exts, void, env, i32, i32)
|
||||
DEF_HELPER_3(set_mac_extu, void, env, i32, i32)
|
||||
|
||||
DEF_HELPER_0_3(mac_move, void, (CPUState *, uint32_t, uint32_t))
|
||||
DEF_HELPER_1_3(macmulf, uint64_t, (CPUState *, uint32_t, uint32_t))
|
||||
DEF_HELPER_1_3(macmuls, uint64_t, (CPUState *, uint32_t, uint32_t))
|
||||
DEF_HELPER_1_3(macmulu, uint64_t, (CPUState *, uint32_t, uint32_t))
|
||||
DEF_HELPER_0_2(macsats, void, (CPUState *, uint32_t))
|
||||
DEF_HELPER_0_2(macsatu, void, (CPUState *, uint32_t))
|
||||
DEF_HELPER_0_2(macsatf, void, (CPUState *, uint32_t))
|
||||
DEF_HELPER_0_2(mac_set_flags, void, (CPUState *, uint32_t))
|
||||
DEF_HELPER_0_2(set_macsr, void, (CPUState *, uint32_t))
|
||||
DEF_HELPER_1_2(get_macf, uint32_t, (CPUState *, uint64_t))
|
||||
DEF_HELPER_1_1(get_macs, uint32_t, (uint64_t))
|
||||
DEF_HELPER_1_1(get_macu, uint32_t, (uint64_t))
|
||||
DEF_HELPER_1_2(get_mac_extf, uint32_t, (CPUState *, uint32_t))
|
||||
DEF_HELPER_1_2(get_mac_exti, uint32_t, (CPUState *, uint32_t))
|
||||
DEF_HELPER_0_3(set_mac_extf, void, (CPUState *, uint32_t, uint32_t))
|
||||
DEF_HELPER_0_3(set_mac_exts, void, (CPUState *, uint32_t, uint32_t))
|
||||
DEF_HELPER_0_3(set_mac_extu, void, (CPUState *, uint32_t, uint32_t))
|
||||
DEF_HELPER_2(flush_flags, void, env, i32)
|
||||
DEF_HELPER_1(raise_exception, void, i32)
|
||||
|
||||
DEF_HELPER_0_2(flush_flags, void, (CPUState *, uint32_t))
|
||||
DEF_HELPER_0_1(raise_exception, void, (uint32_t))
|
||||
|
||||
#undef DEF_HELPER
|
||||
#undef DEF_HELPER_0_0
|
||||
#undef DEF_HELPER_0_1
|
||||
#undef DEF_HELPER_0_2
|
||||
#undef DEF_HELPER_0_3
|
||||
#undef DEF_HELPER_1_0
|
||||
#undef DEF_HELPER_1_1
|
||||
#undef DEF_HELPER_1_2
|
||||
#undef DEF_HELPER_1_3
|
||||
#undef DEF_HELPER_1_4
|
||||
#undef GEN_HELPER
|
||||
#undef DEF_HELPER
|
||||
#include "def-helper.h"
|
||||
|
|
|
@ -32,37 +32,32 @@
|
|||
#include "tcg-op.h"
|
||||
#include "qemu-log.h"
|
||||
|
||||
#include "helpers.h"
|
||||
#define GEN_HELPER 1
|
||||
#include "helpers.h"
|
||||
|
||||
//#define DEBUG_DISPATCH 1
|
||||
|
||||
/* Fake floating point. */
|
||||
#define TCG_TYPE_F32 TCG_TYPE_I32
|
||||
#define TCG_TYPE_F64 TCG_TYPE_I64
|
||||
#define tcg_gen_mov_f64 tcg_gen_mov_i64
|
||||
#define tcg_gen_qemu_ldf32 tcg_gen_qemu_ld32u
|
||||
#define tcg_gen_qemu_ldf64 tcg_gen_qemu_ld64
|
||||
#define tcg_gen_qemu_stf32 tcg_gen_qemu_st32
|
||||
#define tcg_gen_qemu_stf64 tcg_gen_qemu_st64
|
||||
#define gen_helper_pack_32_f32 tcg_gen_mov_i32
|
||||
#define gen_helper_pack_f32_32 tcg_gen_mov_i32
|
||||
|
||||
#define DEFO32(name, offset) static TCGv QREG_##name;
|
||||
#define DEFO64(name, offset) static TCGv QREG_##name;
|
||||
#define DEFF64(name, offset) static TCGv QREG_##name;
|
||||
#define DEFO64(name, offset) static TCGv_i64 QREG_##name;
|
||||
#define DEFF64(name, offset) static TCGv_i64 QREG_##name;
|
||||
#include "qregs.def"
|
||||
#undef DEFO32
|
||||
#undef DEFO64
|
||||
#undef DEFF64
|
||||
|
||||
static TCGv cpu_env;
|
||||
static TCGv_ptr cpu_env;
|
||||
|
||||
static char cpu_reg_names[3*8*3 + 5*4];
|
||||
static TCGv cpu_dregs[8];
|
||||
static TCGv cpu_aregs[8];
|
||||
static TCGv cpu_fregs[8];
|
||||
static TCGv cpu_macc[4];
|
||||
static TCGv_i64 cpu_fregs[8];
|
||||
static TCGv_i64 cpu_macc[4];
|
||||
|
||||
#define DREG(insn, pos) cpu_dregs[((insn) >> (pos)) & 7]
|
||||
#define AREG(insn, pos) cpu_aregs[((insn) >> (pos)) & 7]
|
||||
|
@ -71,7 +66,7 @@ static TCGv cpu_macc[4];
|
|||
#define QREG_SP cpu_aregs[7]
|
||||
|
||||
static TCGv NULL_QREG;
|
||||
#define IS_NULL_QREG(t) (GET_TCGV(t) == GET_TCGV(NULL_QREG))
|
||||
#define IS_NULL_QREG(t) (TCGV_EQUAL(t, NULL_QREG))
|
||||
/* Used to distinguish stores from bad addressing modes. */
|
||||
static TCGv store_dummy;
|
||||
|
||||
|
@ -82,43 +77,42 @@ void m68k_tcg_init(void)
|
|||
char *p;
|
||||
int i;
|
||||
|
||||
#define DEFO32(name, offset) QREG_##name = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0, offsetof(CPUState, offset), #name);
|
||||
#define DEFO64(name, offset) QREG_##name = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0, offsetof(CPUState, offset), #name);
|
||||
#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)
|
||||
#include "qregs.def"
|
||||
#undef DEFO32
|
||||
#undef DEFO64
|
||||
#undef DEFF64
|
||||
|
||||
cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
|
||||
cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
|
||||
|
||||
p = cpu_reg_names;
|
||||
for (i = 0; i < 8; i++) {
|
||||
sprintf(p, "D%d", i);
|
||||
cpu_dregs[i] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
|
||||
cpu_dregs[i] = tcg_global_mem_new(TCG_AREG0,
|
||||
offsetof(CPUM68KState, dregs[i]), p);
|
||||
p += 3;
|
||||
sprintf(p, "A%d", i);
|
||||
cpu_aregs[i] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
|
||||
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(TCG_TYPE_F64, TCG_AREG0,
|
||||
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);
|
||||
cpu_macc[i] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
|
||||
cpu_macc[i] = tcg_global_mem_new_i64(TCG_AREG0,
|
||||
offsetof(CPUM68KState, macc[i]), p);
|
||||
p += 5;
|
||||
}
|
||||
|
||||
NULL_QREG = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0, -4, "NULL");
|
||||
store_dummy = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0, -8, "NULL");
|
||||
NULL_QREG = tcg_global_mem_new(TCG_AREG0, -4, "NULL");
|
||||
store_dummy = tcg_global_mem_new(TCG_AREG0, -8, "NULL");
|
||||
|
||||
#define DEF_HELPER(name, ret, args) \
|
||||
tcg_register_helper(HELPER(name), #name);
|
||||
#define GEN_HELPER 2
|
||||
#include "helpers.h"
|
||||
}
|
||||
|
||||
|
@ -142,7 +136,8 @@ typedef struct DisasContext {
|
|||
struct TranslationBlock *tb;
|
||||
int singlestep_enabled;
|
||||
int is_mem;
|
||||
TCGv mactmp;
|
||||
TCGv_i64 mactmp;
|
||||
int done_mac;
|
||||
} DisasContext;
|
||||
|
||||
#define DISAS_JUMP_NEXT 4
|
||||
|
@ -181,15 +176,6 @@ typedef void (*disas_proc)(DisasContext *, uint16_t);
|
|||
/* FIXME: Remove this. */
|
||||
#define gen_im32(val) tcg_const_i32(val)
|
||||
|
||||
#define QMODE_I32 TCG_TYPE_I32
|
||||
#define QMODE_I64 TCG_TYPE_I64
|
||||
#define QMODE_F32 TCG_TYPE_F32
|
||||
#define QMODE_F64 TCG_TYPE_F64
|
||||
static inline TCGv gen_new_qreg(int mode)
|
||||
{
|
||||
return tcg_temp_new(mode);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
|
@ -197,32 +183,23 @@ static inline TCGv gen_load(DisasContext * s, int opsize, TCGv addr, int sign)
|
|||
TCGv tmp;
|
||||
int index = IS_USER(s);
|
||||
s->is_mem = 1;
|
||||
tmp = tcg_temp_new_i32();
|
||||
switch(opsize) {
|
||||
case OS_BYTE:
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
if (sign)
|
||||
tcg_gen_qemu_ld8s(tmp, addr, index);
|
||||
else
|
||||
tcg_gen_qemu_ld8u(tmp, addr, index);
|
||||
break;
|
||||
case OS_WORD:
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
if (sign)
|
||||
tcg_gen_qemu_ld16s(tmp, addr, index);
|
||||
else
|
||||
tcg_gen_qemu_ld16u(tmp, addr, index);
|
||||
break;
|
||||
case OS_LONG:
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tcg_gen_qemu_ld32u(tmp, addr, index);
|
||||
break;
|
||||
case OS_SINGLE:
|
||||
tmp = gen_new_qreg(QMODE_F32);
|
||||
tcg_gen_qemu_ldf32(tmp, addr, index);
|
||||
break;
|
||||
case OS_DOUBLE:
|
||||
tmp = gen_new_qreg(QMODE_F64);
|
||||
tcg_gen_qemu_ldf64(tmp, addr, index);
|
||||
tcg_gen_qemu_ld32u(tmp, addr, index);
|
||||
break;
|
||||
default:
|
||||
qemu_assert(0, "bad load size");
|
||||
|
@ -231,6 +208,17 @@ 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)
|
||||
{
|
||||
|
@ -244,13 +232,8 @@ static inline void gen_store(DisasContext *s, int opsize, TCGv addr, TCGv val)
|
|||
tcg_gen_qemu_st16(val, addr, index);
|
||||
break;
|
||||
case OS_LONG:
|
||||
tcg_gen_qemu_st32(val, addr, index);
|
||||
break;
|
||||
case OS_SINGLE:
|
||||
tcg_gen_qemu_stf32(val, addr, index);
|
||||
break;
|
||||
case OS_DOUBLE:
|
||||
tcg_gen_qemu_stf64(val, addr, index);
|
||||
tcg_gen_qemu_st32(val, addr, index);
|
||||
break;
|
||||
default:
|
||||
qemu_assert(0, "bad store size");
|
||||
|
@ -258,6 +241,14 @@ 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,
|
||||
|
@ -340,7 +331,7 @@ static TCGv gen_lea_indexed(DisasContext *s, int opsize, TCGv base)
|
|||
} else {
|
||||
bd = 0;
|
||||
}
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
if ((ext & 0x44) == 0) {
|
||||
/* pre-index */
|
||||
add = gen_addr_index(ext, tmp);
|
||||
|
@ -396,7 +387,7 @@ static TCGv gen_lea_indexed(DisasContext *s, int opsize, TCGv base)
|
|||
}
|
||||
} else {
|
||||
/* brief extension word format */
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
add = gen_addr_index(ext, tmp);
|
||||
if (!IS_NULL_QREG(base)) {
|
||||
tcg_gen_add_i32(tmp, add, base);
|
||||
|
@ -461,21 +452,19 @@ static void gen_partset_reg(int opsize, TCGv reg, TCGv val)
|
|||
switch (opsize) {
|
||||
case OS_BYTE:
|
||||
tcg_gen_andi_i32(reg, reg, 0xffffff00);
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
tcg_gen_ext8u_i32(tmp, val);
|
||||
tcg_gen_or_i32(reg, reg, tmp);
|
||||
break;
|
||||
case OS_WORD:
|
||||
tcg_gen_andi_i32(reg, reg, 0xffff0000);
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
tcg_gen_ext16u_i32(tmp, val);
|
||||
tcg_gen_or_i32(reg, reg, tmp);
|
||||
break;
|
||||
case OS_LONG:
|
||||
tcg_gen_mov_i32(reg, val);
|
||||
break;
|
||||
case OS_SINGLE:
|
||||
gen_helper_pack_32_f32(reg, val);
|
||||
tcg_gen_mov_i32(reg, val);
|
||||
break;
|
||||
default:
|
||||
qemu_assert(0, "Bad operand size");
|
||||
|
@ -490,25 +479,22 @@ static inline TCGv gen_extend(TCGv val, int opsize, int sign)
|
|||
|
||||
switch (opsize) {
|
||||
case OS_BYTE:
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
if (sign)
|
||||
tcg_gen_ext8s_i32(tmp, val);
|
||||
else
|
||||
tcg_gen_ext8u_i32(tmp, val);
|
||||
break;
|
||||
case OS_WORD:
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
if (sign)
|
||||
tcg_gen_ext16s_i32(tmp, val);
|
||||
else
|
||||
tcg_gen_ext16u_i32(tmp, val);
|
||||
break;
|
||||
case OS_LONG:
|
||||
tmp = val;
|
||||
break;
|
||||
case OS_SINGLE:
|
||||
tmp = gen_new_qreg(QMODE_F32);
|
||||
gen_helper_pack_f32_32(tmp, val);
|
||||
tmp = val;
|
||||
break;
|
||||
default:
|
||||
qemu_assert(0, "Bad operand size");
|
||||
|
@ -534,12 +520,12 @@ static TCGv gen_lea(DisasContext *s, uint16_t insn, int opsize)
|
|||
return AREG(insn, 0);
|
||||
case 4: /* Indirect predecrememnt. */
|
||||
reg = AREG(insn, 0);
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
tcg_gen_subi_i32(tmp, reg, opsize_bytes(opsize));
|
||||
return tmp;
|
||||
case 5: /* Indirect displacement. */
|
||||
reg = AREG(insn, 0);
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
ext = lduw_code(s->pc);
|
||||
s->pc += 2;
|
||||
tcg_gen_addi_i32(tmp, reg, (int16_t)ext);
|
||||
|
@ -557,7 +543,7 @@ static TCGv gen_lea(DisasContext *s, uint16_t insn, int opsize)
|
|||
offset = read_im32(s);
|
||||
return gen_im32(offset);
|
||||
case 2: /* pc displacement */
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
offset = s->pc;
|
||||
offset += ldsw_code(s->pc);
|
||||
s->pc += 2;
|
||||
|
@ -708,57 +694,57 @@ static void gen_jmpcc(DisasContext *s, int cond, int l1)
|
|||
case 1: /* F */
|
||||
break;
|
||||
case 2: /* HI (!C && !Z) */
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_C | CCF_Z);
|
||||
tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
|
||||
break;
|
||||
case 3: /* LS (C || Z) */
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_C | CCF_Z);
|
||||
tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
|
||||
break;
|
||||
case 4: /* CC (!C) */
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_C);
|
||||
tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
|
||||
break;
|
||||
case 5: /* CS (C) */
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_C);
|
||||
tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
|
||||
break;
|
||||
case 6: /* NE (!Z) */
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_Z);
|
||||
tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
|
||||
break;
|
||||
case 7: /* EQ (Z) */
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_Z);
|
||||
tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
|
||||
break;
|
||||
case 8: /* VC (!V) */
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_V);
|
||||
tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
|
||||
break;
|
||||
case 9: /* VS (V) */
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_V);
|
||||
tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
|
||||
break;
|
||||
case 10: /* PL (!N) */
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_N);
|
||||
tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
|
||||
break;
|
||||
case 11: /* MI (N) */
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_N);
|
||||
tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
|
||||
break;
|
||||
case 12: /* GE (!(N ^ V)) */
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
assert(CCF_V == (CCF_N >> 2));
|
||||
tcg_gen_shri_i32(tmp, QREG_CC_DEST, 2);
|
||||
tcg_gen_xor_i32(tmp, tmp, QREG_CC_DEST);
|
||||
|
@ -766,7 +752,7 @@ static void gen_jmpcc(DisasContext *s, int cond, int l1)
|
|||
tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
|
||||
break;
|
||||
case 13: /* LT (N ^ V) */
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
assert(CCF_V == (CCF_N >> 2));
|
||||
tcg_gen_shri_i32(tmp, QREG_CC_DEST, 2);
|
||||
tcg_gen_xor_i32(tmp, tmp, QREG_CC_DEST);
|
||||
|
@ -774,7 +760,7 @@ static void gen_jmpcc(DisasContext *s, int cond, int l1)
|
|||
tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
|
||||
break;
|
||||
case 14: /* GT (!(Z || (N ^ V))) */
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
assert(CCF_V == (CCF_N >> 2));
|
||||
tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_N);
|
||||
tcg_gen_shri_i32(tmp, tmp, 2);
|
||||
|
@ -783,7 +769,7 @@ static void gen_jmpcc(DisasContext *s, int cond, int l1)
|
|||
tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
|
||||
break;
|
||||
case 15: /* LE (Z || (N ^ V)) */
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
assert(CCF_V == (CCF_N >> 2));
|
||||
tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_N);
|
||||
tcg_gen_shri_i32(tmp, tmp, 2);
|
||||
|
@ -912,7 +898,7 @@ DISAS_INSN(mulw)
|
|||
|
||||
sign = (insn & 0x100) != 0;
|
||||
reg = DREG(insn, 9);
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
if (sign)
|
||||
tcg_gen_ext16s_i32(tmp, reg);
|
||||
else
|
||||
|
@ -946,8 +932,8 @@ DISAS_INSN(divw)
|
|||
gen_helper_divu(cpu_env, tcg_const_i32(1));
|
||||
}
|
||||
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
src = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
src = tcg_temp_new();
|
||||
tcg_gen_ext16u_i32(tmp, QREG_DIV1);
|
||||
tcg_gen_shli_i32(src, QREG_DIV2, 16);
|
||||
tcg_gen_or_i32(reg, tmp, src);
|
||||
|
@ -998,7 +984,7 @@ DISAS_INSN(addsub)
|
|||
|
||||
add = (insn & 0x4000) != 0;
|
||||
reg = DREG(insn, 9);
|
||||
dest = gen_new_qreg(QMODE_I32);
|
||||
dest = tcg_temp_new();
|
||||
if (insn & 0x100) {
|
||||
SRC_EA(tmp, OS_LONG, 0, &addr);
|
||||
src = reg;
|
||||
|
@ -1049,16 +1035,16 @@ DISAS_INSN(bitop_reg)
|
|||
op = (insn >> 6) & 3;
|
||||
SRC_EA(src1, opsize, 0, op ? &addr: NULL);
|
||||
src2 = DREG(insn, 9);
|
||||
dest = gen_new_qreg(QMODE_I32);
|
||||
dest = tcg_temp_new();
|
||||
|
||||
gen_flush_flags(s);
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
if (opsize == OS_BYTE)
|
||||
tcg_gen_andi_i32(tmp, src2, 7);
|
||||
else
|
||||
tcg_gen_andi_i32(tmp, src2, 31);
|
||||
src2 = tmp;
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
tcg_gen_shr_i32(tmp, src1, src2);
|
||||
tcg_gen_andi_i32(tmp, tmp, 1);
|
||||
tcg_gen_shli_i32(tmp, tmp, 2);
|
||||
|
@ -1098,7 +1084,7 @@ static void gen_push(DisasContext *s, TCGv val)
|
|||
{
|
||||
TCGv tmp;
|
||||
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
tcg_gen_subi_i32(tmp, QREG_SP, 4);
|
||||
gen_store(s, OS_LONG, tmp, val);
|
||||
tcg_gen_mov_i32(QREG_SP, tmp);
|
||||
|
@ -1120,7 +1106,7 @@ DISAS_INSN(movem)
|
|||
gen_addr_fault(s);
|
||||
return;
|
||||
}
|
||||
addr = gen_new_qreg(QMODE_I32);
|
||||
addr = tcg_temp_new();
|
||||
tcg_gen_mov_i32(addr, tmp);
|
||||
is_load = ((insn & 0x0400) != 0);
|
||||
for (i = 0; i < 16; i++, mask >>= 1) {
|
||||
|
@ -1173,7 +1159,7 @@ DISAS_INSN(bitop_im)
|
|||
bitnum &= 31;
|
||||
mask = 1 << bitnum;
|
||||
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
assert (CCF_Z == (1 << 2));
|
||||
if (bitnum > 2)
|
||||
tcg_gen_shri_i32(tmp, src1, bitnum - 2);
|
||||
|
@ -1214,7 +1200,7 @@ DISAS_INSN(arith_im)
|
|||
op = (insn >> 9) & 7;
|
||||
SRC_EA(src1, OS_LONG, 0, (op == 6) ? NULL : &addr);
|
||||
im = read_im32(s);
|
||||
dest = gen_new_qreg(QMODE_I32);
|
||||
dest = tcg_temp_new();
|
||||
switch (op) {
|
||||
case 0: /* ori */
|
||||
tcg_gen_ori_i32(dest, src1, im);
|
||||
|
@ -1350,7 +1336,7 @@ static TCGv gen_get_ccr(DisasContext *s)
|
|||
TCGv dest;
|
||||
|
||||
gen_flush_flags(s);
|
||||
dest = gen_new_qreg(QMODE_I32);
|
||||
dest = tcg_temp_new();
|
||||
tcg_gen_shli_i32(dest, QREG_CC_X, 4);
|
||||
tcg_gen_or_i32(dest, dest, QREG_CC_DEST);
|
||||
return dest;
|
||||
|
@ -1372,7 +1358,7 @@ DISAS_INSN(neg)
|
|||
TCGv src1;
|
||||
|
||||
reg = DREG(insn, 0);
|
||||
src1 = gen_new_qreg(QMODE_I32);
|
||||
src1 = tcg_temp_new();
|
||||
tcg_gen_mov_i32(src1, reg);
|
||||
tcg_gen_neg_i32(reg, src1);
|
||||
s->cc_op = CC_OP_SUB;
|
||||
|
@ -1398,7 +1384,7 @@ static void gen_set_sr(DisasContext *s, uint16_t insn, int ccr_only)
|
|||
s->cc_op = CC_OP_FLAGS;
|
||||
if ((insn & 0x38) == 0)
|
||||
{
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
reg = DREG(insn, 0);
|
||||
tcg_gen_andi_i32(QREG_CC_DEST, reg, 0xf);
|
||||
tcg_gen_shri_i32(tmp, reg, 4);
|
||||
|
@ -1438,8 +1424,8 @@ DISAS_INSN(swap)
|
|||
TCGv src2;
|
||||
TCGv reg;
|
||||
|
||||
src1 = gen_new_qreg(QMODE_I32);
|
||||
src2 = gen_new_qreg(QMODE_I32);
|
||||
src1 = tcg_temp_new();
|
||||
src2 = tcg_temp_new();
|
||||
reg = DREG(insn, 0);
|
||||
tcg_gen_shli_i32(src1, reg, 16);
|
||||
tcg_gen_shri_i32(src2, reg, 16);
|
||||
|
@ -1467,7 +1453,7 @@ DISAS_INSN(ext)
|
|||
|
||||
reg = DREG(insn, 0);
|
||||
op = (insn >> 6) & 7;
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
if (op == 3)
|
||||
tcg_gen_ext16s_i32(tmp, reg);
|
||||
else
|
||||
|
@ -1518,7 +1504,7 @@ DISAS_INSN(tas)
|
|||
TCGv src1;
|
||||
TCGv addr;
|
||||
|
||||
dest = gen_new_qreg(QMODE_I32);
|
||||
dest = tcg_temp_new();
|
||||
SRC_EA(src1, OS_BYTE, 1, &addr);
|
||||
gen_logic_cc(s, src1);
|
||||
tcg_gen_ori_i32(dest, src1, 0x80);
|
||||
|
@ -1542,7 +1528,7 @@ DISAS_INSN(mull)
|
|||
}
|
||||
reg = DREG(ext, 12);
|
||||
SRC_EA(src1, OS_LONG, 0, NULL);
|
||||
dest = gen_new_qreg(QMODE_I32);
|
||||
dest = tcg_temp_new();
|
||||
tcg_gen_mul_i32(dest, src1, reg);
|
||||
tcg_gen_mov_i32(reg, dest);
|
||||
/* Unlike m68k, coldfire always clears the overflow bit. */
|
||||
|
@ -1558,7 +1544,7 @@ DISAS_INSN(link)
|
|||
offset = ldsw_code(s->pc);
|
||||
s->pc += 2;
|
||||
reg = AREG(insn, 0);
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
tcg_gen_subi_i32(tmp, QREG_SP, 4);
|
||||
gen_store(s, OS_LONG, tmp, reg);
|
||||
if ((insn & 7) != 7)
|
||||
|
@ -1572,7 +1558,7 @@ DISAS_INSN(unlk)
|
|||
TCGv reg;
|
||||
TCGv tmp;
|
||||
|
||||
src = gen_new_qreg(QMODE_I32);
|
||||
src = tcg_temp_new();
|
||||
reg = AREG(insn, 0);
|
||||
tcg_gen_mov_i32(src, reg);
|
||||
tmp = gen_load(s, OS_LONG, src, 0);
|
||||
|
@ -1623,7 +1609,7 @@ DISAS_INSN(addsubq)
|
|||
val = (insn >> 9) & 7;
|
||||
if (val == 0)
|
||||
val = 8;
|
||||
dest = gen_new_qreg(QMODE_I32);
|
||||
dest = tcg_temp_new();
|
||||
tcg_gen_mov_i32(dest, src1);
|
||||
if ((insn & 0x38) == 0x08) {
|
||||
/* Don't update condition codes if the destination is an
|
||||
|
@ -1732,7 +1718,7 @@ DISAS_INSN(or)
|
|||
TCGv addr;
|
||||
|
||||
reg = DREG(insn, 9);
|
||||
dest = gen_new_qreg(QMODE_I32);
|
||||
dest = tcg_temp_new();
|
||||
if (insn & 0x100) {
|
||||
SRC_EA(src, OS_LONG, 0, &addr);
|
||||
tcg_gen_or_i32(dest, src, reg);
|
||||
|
@ -1806,7 +1792,7 @@ DISAS_INSN(cmp)
|
|||
}
|
||||
SRC_EA(src, opsize, 1, NULL);
|
||||
reg = DREG(insn, 9);
|
||||
dest = gen_new_qreg(QMODE_I32);
|
||||
dest = tcg_temp_new();
|
||||
tcg_gen_sub_i32(dest, reg, src);
|
||||
gen_update_cc_add(dest, src);
|
||||
}
|
||||
|
@ -1825,7 +1811,7 @@ DISAS_INSN(cmpa)
|
|||
}
|
||||
SRC_EA(src, opsize, 1, NULL);
|
||||
reg = AREG(insn, 9);
|
||||
dest = gen_new_qreg(QMODE_I32);
|
||||
dest = tcg_temp_new();
|
||||
tcg_gen_sub_i32(dest, reg, src);
|
||||
gen_update_cc_add(dest, src);
|
||||
s->cc_op = CC_OP_SUB;
|
||||
|
@ -1840,7 +1826,7 @@ DISAS_INSN(eor)
|
|||
|
||||
SRC_EA(src, OS_LONG, 0, &addr);
|
||||
reg = DREG(insn, 9);
|
||||
dest = gen_new_qreg(QMODE_I32);
|
||||
dest = tcg_temp_new();
|
||||
tcg_gen_xor_i32(dest, src, reg);
|
||||
gen_logic_cc(s, dest);
|
||||
DEST_EA(insn, OS_LONG, dest, &addr);
|
||||
|
@ -1854,7 +1840,7 @@ DISAS_INSN(and)
|
|||
TCGv addr;
|
||||
|
||||
reg = DREG(insn, 9);
|
||||
dest = gen_new_qreg(QMODE_I32);
|
||||
dest = tcg_temp_new();
|
||||
if (insn & 0x100) {
|
||||
SRC_EA(src, OS_LONG, 0, &addr);
|
||||
tcg_gen_and_i32(dest, src, reg);
|
||||
|
@ -1949,7 +1935,7 @@ static TCGv gen_get_sr(DisasContext *s)
|
|||
TCGv sr;
|
||||
|
||||
ccr = gen_get_ccr(s);
|
||||
sr = gen_new_qreg(QMODE_I32);
|
||||
sr = tcg_temp_new();
|
||||
tcg_gen_andi_i32(sr, QREG_SR, 0xffe0);
|
||||
tcg_gen_or_i32(sr, sr, ccr);
|
||||
return sr;
|
||||
|
@ -2117,11 +2103,14 @@ DISAS_INSN(trap)
|
|||
DISAS_INSN(fpu)
|
||||
{
|
||||
uint16_t ext;
|
||||
int32_t offset;
|
||||
int opmode;
|
||||
TCGv src;
|
||||
TCGv dest;
|
||||
TCGv res;
|
||||
TCGv_i64 src;
|
||||
TCGv_i64 dest;
|
||||
TCGv_i64 res;
|
||||
TCGv tmp32;
|
||||
int round;
|
||||
int set_dest;
|
||||
int opsize;
|
||||
|
||||
ext = lduw_code(s->pc);
|
||||
|
@ -2134,37 +2123,59 @@ DISAS_INSN(fpu)
|
|||
goto undef;
|
||||
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;
|
||||
res = gen_new_qreg(QMODE_I32);
|
||||
gen_helper_f64_to_i32(res, cpu_env, src);
|
||||
gen_helper_f64_to_i32(tmp32, cpu_env, src);
|
||||
break;
|
||||
case 1:
|
||||
opsize = OS_SINGLE;
|
||||
res = gen_new_qreg(QMODE_F32);
|
||||
gen_helper_f64_to_f32(res, cpu_env, src);
|
||||
gen_helper_f64_to_f32(tmp32, cpu_env, src);
|
||||
break;
|
||||
case 4:
|
||||
opsize = OS_WORD;
|
||||
res = gen_new_qreg(QMODE_I32);
|
||||
gen_helper_f64_to_i32(res, cpu_env, src);
|
||||
break;
|
||||
case 5:
|
||||
opsize = OS_DOUBLE;
|
||||
res = src;
|
||||
gen_helper_f64_to_i32(tmp32, cpu_env, src);
|
||||
break;
|
||||
case 5: /* OS_DOUBLE */
|
||||
tcg_gen_mov_i32(tmp32, AREG(insn, 0));
|
||||
switch (insn >> 3) {
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
tcg_gen_addi_i32(tmp32, tmp32, -8);
|
||||
break;
|
||||
case 5:
|
||||
offset = ldsw_code(s->pc);
|
||||
s->pc += 2;
|
||||
tcg_gen_addi_i32(tmp32, tmp32, offset);
|
||||
break;
|
||||
default:
|
||||
goto undef;
|
||||
}
|
||||
gen_store64(s, tmp32, src);
|
||||
switch (insn >> 3) {
|
||||
case 3:
|
||||
tcg_gen_addi_i32(tmp32, tmp32, 8);
|
||||
tcg_gen_mov_i32(AREG(insn, 0), tmp32);
|
||||
break;
|
||||
case 4:
|
||||
tcg_gen_mov_i32(AREG(insn, 0), tmp32);
|
||||
break;
|
||||
}
|
||||
tcg_temp_free_i32(tmp32);
|
||||
return;
|
||||
case 6:
|
||||
opsize = OS_BYTE;
|
||||
res = gen_new_qreg(QMODE_I32);
|
||||
gen_helper_f64_to_i32(res, cpu_env, src);
|
||||
gen_helper_f64_to_i32(tmp32, cpu_env, src);
|
||||
break;
|
||||
default:
|
||||
goto undef;
|
||||
}
|
||||
DEST_EA(insn, opsize, res, NULL);
|
||||
DEST_EA(insn, opsize, tmp32, NULL);
|
||||
tcg_temp_free_i32(tmp32);
|
||||
return;
|
||||
case 4: /* fmove to control register. */
|
||||
switch ((ext >> 10) & 7) {
|
||||
|
@ -2182,7 +2193,7 @@ DISAS_INSN(fpu)
|
|||
switch ((ext >> 10) & 7) {
|
||||
case 4: /* FPCR */
|
||||
/* Not implemented. Always return zero. */
|
||||
res = gen_im32(0);
|
||||
tmp32 = gen_im32(0);
|
||||
break;
|
||||
case 1: /* FPIAR */
|
||||
case 2: /* FPSR */
|
||||
|
@ -2191,7 +2202,7 @@ DISAS_INSN(fpu)
|
|||
(ext >> 10) & 7);
|
||||
goto undef;
|
||||
}
|
||||
DEST_EA(insn, OS_LONG, res, NULL);
|
||||
DEST_EA(insn, OS_LONG, tmp32, NULL);
|
||||
break;
|
||||
case 6: /* fmovem */
|
||||
case 7:
|
||||
|
@ -2201,13 +2212,13 @@ DISAS_INSN(fpu)
|
|||
int i;
|
||||
if ((ext & 0x1f00) != 0x1000 || (ext & 0xff) == 0)
|
||||
goto undef;
|
||||
src = gen_lea(s, insn, OS_LONG);
|
||||
if (IS_NULL_QREG(src)) {
|
||||
tmp32 = gen_lea(s, insn, OS_LONG);
|
||||
if (IS_NULL_QREG(tmp32)) {
|
||||
gen_addr_fault(s);
|
||||
return;
|
||||
}
|
||||
addr = gen_new_qreg(QMODE_I32);
|
||||
tcg_gen_mov_i32(addr, src);
|
||||
addr = tcg_temp_new_i32();
|
||||
tcg_gen_mov_i32(addr, tmp32);
|
||||
mask = 0x80;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (ext & mask) {
|
||||
|
@ -2225,12 +2236,11 @@ DISAS_INSN(fpu)
|
|||
}
|
||||
mask >>= 1;
|
||||
}
|
||||
tcg_temp_free_i32(tmp32);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (ext & (1 << 14)) {
|
||||
TCGv tmp;
|
||||
|
||||
/* Source effective address. */
|
||||
switch ((ext >> 10) & 7) {
|
||||
case 0: opsize = OS_LONG; break;
|
||||
|
@ -2241,19 +2251,51 @@ DISAS_INSN(fpu)
|
|||
default:
|
||||
goto undef;
|
||||
}
|
||||
SRC_EA(tmp, opsize, 1, NULL);
|
||||
if (opsize == OS_DOUBLE) {
|
||||
src = tmp;
|
||||
tmp32 = tcg_temp_new_i32();
|
||||
tcg_gen_mov_i32(tmp32, AREG(insn, 0));
|
||||
switch (insn >> 3) {
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
tcg_gen_addi_i32(tmp32, tmp32, -8);
|
||||
break;
|
||||
case 5:
|
||||
offset = ldsw_code(s->pc);
|
||||
s->pc += 2;
|
||||
tcg_gen_addi_i32(tmp32, tmp32, offset);
|
||||
break;
|
||||
case 7:
|
||||
offset = ldsw_code(s->pc);
|
||||
offset += s->pc - 2;
|
||||
s->pc += 2;
|
||||
tcg_gen_addi_i32(tmp32, tmp32, offset);
|
||||
break;
|
||||
default:
|
||||
goto undef;
|
||||
}
|
||||
src = gen_load64(s, tmp32);
|
||||
switch (insn >> 3) {
|
||||
case 3:
|
||||
tcg_gen_addi_i32(tmp32, tmp32, 8);
|
||||
tcg_gen_mov_i32(AREG(insn, 0), tmp32);
|
||||
break;
|
||||
case 4:
|
||||
tcg_gen_mov_i32(AREG(insn, 0), tmp32);
|
||||
break;
|
||||
}
|
||||
tcg_temp_free_i32(tmp32);
|
||||
} else {
|
||||
src = gen_new_qreg(QMODE_F64);
|
||||
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, tmp);
|
||||
gen_helper_i32_to_f64(src, cpu_env, tmp32);
|
||||
break;
|
||||
case OS_SINGLE:
|
||||
gen_helper_f32_to_f64(src, cpu_env, tmp);
|
||||
gen_helper_f32_to_f64(src, cpu_env, tmp32);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2262,10 +2304,11 @@ DISAS_INSN(fpu)
|
|||
src = FREG(ext, 10);
|
||||
}
|
||||
dest = FREG(ext, 7);
|
||||
res = gen_new_qreg(QMODE_F64);
|
||||
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);
|
||||
|
@ -2301,17 +2344,20 @@ DISAS_INSN(fpu)
|
|||
break;
|
||||
case 0x38: /* fcmp */
|
||||
gen_helper_sub_cmp_f64(res, cpu_env, res, src);
|
||||
dest = NULL_QREG;
|
||||
set_dest = 0;
|
||||
round = 0;
|
||||
break;
|
||||
case 0x3a: /* ftst */
|
||||
tcg_gen_mov_f64(res, src);
|
||||
dest = NULL_QREG;
|
||||
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)
|
||||
|
@ -2321,18 +2367,19 @@ DISAS_INSN(fpu)
|
|||
}
|
||||
}
|
||||
if (round) {
|
||||
TCGv tmp;
|
||||
|
||||
tmp = gen_new_qreg(QMODE_F32);
|
||||
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);
|
||||
}
|
||||
tcg_gen_mov_f64(QREG_FP_RESULT, res);
|
||||
if (!IS_NULL_QREG(dest)) {
|
||||
if (set_dest) {
|
||||
tcg_gen_mov_f64(dest, res);
|
||||
}
|
||||
tcg_temp_free_i64(res);
|
||||
return;
|
||||
undef:
|
||||
/* FIXME: Is this right for offset addressing modes? */
|
||||
s->pc -= 2;
|
||||
disas_undef_fpu(s, insn);
|
||||
}
|
||||
|
@ -2354,7 +2401,7 @@ DISAS_INSN(fbcc)
|
|||
|
||||
l1 = gen_new_label();
|
||||
/* TODO: Raise BSUN exception. */
|
||||
flag = gen_new_qreg(QMODE_I32);
|
||||
flag = tcg_temp_new();
|
||||
gen_helper_compare_f64(flag, cpu_env, QREG_FP_RESULT);
|
||||
/* Jump to l1 if condition is true. */
|
||||
switch (insn & 0xf) {
|
||||
|
@ -2427,7 +2474,7 @@ DISAS_INSN(fsave)
|
|||
|
||||
static inline TCGv gen_mac_extract_word(DisasContext *s, TCGv val, int upper)
|
||||
{
|
||||
TCGv tmp = gen_new_qreg(QMODE_I32);
|
||||
TCGv tmp = tcg_temp_new();
|
||||
if (s->env->macsr & MACSR_FI) {
|
||||
if (upper)
|
||||
tcg_gen_andi_i32(tmp, val, 0xffff0000);
|
||||
|
@ -2465,8 +2512,10 @@ DISAS_INSN(mac)
|
|||
int dual;
|
||||
TCGv saved_flags;
|
||||
|
||||
if (IS_NULL_QREG(s->mactmp))
|
||||
s->mactmp = tcg_temp_new(TCG_TYPE_I64);
|
||||
if (!s->done_mac) {
|
||||
s->mactmp = tcg_temp_new_i64();
|
||||
s->done_mac = 1;
|
||||
}
|
||||
|
||||
ext = lduw_code(s->pc);
|
||||
s->pc += 2;
|
||||
|
@ -2480,7 +2529,7 @@ DISAS_INSN(mac)
|
|||
if (insn & 0x30) {
|
||||
/* MAC with load. */
|
||||
tmp = gen_lea(s, insn, OS_LONG);
|
||||
addr = gen_new_qreg(QMODE_I32);
|
||||
addr = tcg_temp_new();
|
||||
tcg_gen_and_i32(addr, tmp, QREG_MAC_MASK);
|
||||
/* Load the value now to ensure correct exception behavior.
|
||||
Perform writeback after reading the MAC inputs. */
|
||||
|
@ -2502,7 +2551,7 @@ DISAS_INSN(mac)
|
|||
if ((s->env->macsr & MACSR_OMC) != 0 && !dual) {
|
||||
/* Skip the multiply if we know we will ignore it. */
|
||||
l1 = gen_new_label();
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
tcg_gen_andi_i32(tmp, QREG_MACSR, 1 << (acc + 8));
|
||||
gen_op_jmp_nz32(tmp, l1);
|
||||
}
|
||||
|
@ -2532,7 +2581,7 @@ DISAS_INSN(mac)
|
|||
|
||||
if (dual) {
|
||||
/* Save the overflow flag from the multiply. */
|
||||
saved_flags = gen_new_qreg(QMODE_I32);
|
||||
saved_flags = tcg_temp_new();
|
||||
tcg_gen_mov_i32(saved_flags, QREG_MACSR);
|
||||
} else {
|
||||
saved_flags = NULL_QREG;
|
||||
|
@ -2543,7 +2592,7 @@ DISAS_INSN(mac)
|
|||
if ((s->env->macsr & MACSR_OMC) != 0 && dual) {
|
||||
/* Skip the accumulate if the value is already saturated. */
|
||||
l1 = gen_new_label();
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
gen_op_and32(tmp, QREG_MACSR, gen_im32(MACSR_PAV0 << acc));
|
||||
gen_op_jmp_nz32(tmp, l1);
|
||||
}
|
||||
|
@ -2577,7 +2626,7 @@ DISAS_INSN(mac)
|
|||
if ((s->env->macsr & MACSR_OMC) != 0) {
|
||||
/* Skip the accumulate if the value is already saturated. */
|
||||
l1 = gen_new_label();
|
||||
tmp = gen_new_qreg(QMODE_I32);
|
||||
tmp = tcg_temp_new();
|
||||
gen_op_and32(tmp, QREG_MACSR, gen_im32(MACSR_PAV0 << acc));
|
||||
gen_op_jmp_nz32(tmp, l1);
|
||||
}
|
||||
|
@ -2619,14 +2668,14 @@ DISAS_INSN(mac)
|
|||
DISAS_INSN(from_mac)
|
||||
{
|
||||
TCGv rx;
|
||||
TCGv acc;
|
||||
TCGv_i64 acc;
|
||||
int accnum;
|
||||
|
||||
rx = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
|
||||
accnum = (insn >> 9) & 3;
|
||||
acc = MACREG(accnum);
|
||||
if (s->env->macsr & MACSR_FI) {
|
||||
gen_helper_get_macf(cpu_env, rx, acc);
|
||||
gen_helper_get_macf(rx, cpu_env, acc);
|
||||
} else if ((s->env->macsr & MACSR_OMC) == 0) {
|
||||
tcg_gen_trunc_i64_i32(rx, acc);
|
||||
} else if (s->env->macsr & MACSR_SU) {
|
||||
|
@ -2688,7 +2737,7 @@ DISAS_INSN(macsr_to_ccr)
|
|||
|
||||
DISAS_INSN(to_mac)
|
||||
{
|
||||
TCGv acc;
|
||||
TCGv_i64 acc;
|
||||
TCGv val;
|
||||
int accnum;
|
||||
accnum = (insn >> 9) & 3;
|
||||
|
@ -2938,7 +2987,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
|
|||
dc->fpcr = env->fpcr;
|
||||
dc->user = (env->sr & SR_S) == 0;
|
||||
dc->is_mem = 0;
|
||||
dc->mactmp = NULL_QREG;
|
||||
dc->done_mac = 0;
|
||||
lj = -1;
|
||||
num_insns = 0;
|
||||
max_insns = tb->cflags & CF_COUNT_MASK;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue