aboutsummaryrefslogtreecommitdiff
path: root/target-m68k/translate.c
diff options
context:
space:
mode:
authorpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>2008-11-17 14:43:54 +0000
committerpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>2008-11-17 14:43:54 +0000
commita7812ae412311d7d47f8aa85656faadac9d64b56 (patch)
treebae5e0d6fe19739e5e6d1cdc75d84312bf175257 /target-m68k/translate.c
parent30913bae9a2cf92b5a87363ec1c7d0ad1f82cdcc (diff)
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
Diffstat (limited to 'target-m68k/translate.c')
-rw-r--r--target-m68k/translate.c363
1 files changed, 206 insertions, 157 deletions
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index df3a418ae8..07f0640c03 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -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;