aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--target/m68k/translate.c125
1 files changed, 66 insertions, 59 deletions
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index b33b3c6..ecb89e4 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -281,10 +281,10 @@ static inline void gen_addr_fault(DisasContext *s)
/* 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)
+static inline TCGv gen_load(DisasContext *s, int opsize, TCGv addr,
+ int sign, int index)
{
TCGv tmp;
- int index = IS_USER(s);
tmp = tcg_temp_new_i32();
switch(opsize) {
case OS_BYTE:
@@ -309,9 +309,9 @@ static inline TCGv gen_load(DisasContext * s, int opsize, TCGv addr, int sign)
}
/* Generate a store. */
-static inline void gen_store(DisasContext *s, int opsize, TCGv addr, TCGv val)
+static inline void gen_store(DisasContext *s, int opsize, TCGv addr, TCGv val,
+ int index)
{
- int index = IS_USER(s);
switch(opsize) {
case OS_BYTE:
tcg_gen_qemu_st8(val, addr, index);
@@ -336,13 +336,13 @@ typedef enum {
/* Generate an unsigned load if VAL is 0 a signed load if val is -1,
otherwise generate a store. */
static TCGv gen_ldst(DisasContext *s, int opsize, TCGv addr, TCGv val,
- ea_what what)
+ ea_what what, int index)
{
if (what == EA_STORE) {
- gen_store(s, opsize, addr, val);
+ gen_store(s, opsize, addr, val, index);
return store_dummy;
} else {
- return gen_load(s, opsize, addr, what == EA_LOADS);
+ return gen_load(s, opsize, addr, what == EA_LOADS, index);
}
}
@@ -464,7 +464,7 @@ static TCGv gen_lea_indexed(CPUM68KState *env, DisasContext *s, TCGv base)
}
if ((ext & 3) != 0) {
/* memory indirect */
- base = gen_load(s, OS_LONG, add, 0);
+ base = gen_load(s, OS_LONG, add, 0, IS_USER(s));
if ((ext & 0x44) == 4) {
add = gen_addr_index(s, ext, tmp);
tcg_gen_add_i32(tmp, add, base);
@@ -793,7 +793,8 @@ static TCGv gen_lea(CPUM68KState *env, DisasContext *s, uint16_t insn,
a write otherwise it is a read (0 == sign extend, -1 == zero extend).
ADDRP is non-null for readwrite operands. */
static TCGv gen_ea_mode(CPUM68KState *env, DisasContext *s, int mode, int reg0,
- int opsize, TCGv val, TCGv *addrp, ea_what what)
+ int opsize, TCGv val, TCGv *addrp, ea_what what,
+ int index)
{
TCGv reg, tmp, result;
int32_t offset;
@@ -817,10 +818,10 @@ static TCGv gen_ea_mode(CPUM68KState *env, DisasContext *s, int mode, int reg0,
}
case 2: /* Indirect register */
reg = get_areg(s, reg0);
- return gen_ldst(s, opsize, reg, val, what);
+ return gen_ldst(s, opsize, reg, val, what, index);
case 3: /* Indirect postincrement. */
reg = get_areg(s, reg0);
- result = gen_ldst(s, opsize, reg, val, what);
+ result = gen_ldst(s, opsize, reg, val, what, index);
if (what == EA_STORE || !addrp) {
TCGv tmp = tcg_temp_new();
if (reg0 == 7 && opsize == OS_BYTE &&
@@ -844,7 +845,7 @@ static TCGv gen_ea_mode(CPUM68KState *env, DisasContext *s, int mode, int reg0,
*addrp = tmp;
}
}
- result = gen_ldst(s, opsize, tmp, val, what);
+ result = gen_ldst(s, opsize, tmp, val, what, index);
if (what == EA_STORE || !addrp) {
delay_set_areg(s, reg0, tmp, false);
}
@@ -863,7 +864,7 @@ static TCGv gen_ea_mode(CPUM68KState *env, DisasContext *s, int mode, int reg0,
*addrp = tmp;
}
}
- return gen_ldst(s, opsize, tmp, val, what);
+ return gen_ldst(s, opsize, tmp, val, what, index);
case 7: /* Other */
switch (reg0) {
case 0: /* Absolute short. */
@@ -904,11 +905,11 @@ static TCGv gen_ea_mode(CPUM68KState *env, DisasContext *s, int mode, int reg0,
}
static TCGv gen_ea(CPUM68KState *env, DisasContext *s, uint16_t insn,
- int opsize, TCGv val, TCGv *addrp, ea_what what)
+ int opsize, TCGv val, TCGv *addrp, ea_what what, int index)
{
int mode = extract32(insn, 3, 3);
int reg0 = REG(insn, 0);
- return gen_ea_mode(env, s, mode, reg0, opsize, val, addrp, what);
+ return gen_ea_mode(env, s, mode, reg0, opsize, val, addrp, what, index);
}
static TCGv_ptr gen_fp_ptr(int freg)
@@ -941,11 +942,11 @@ static void gen_fp_move(TCGv_ptr dest, TCGv_ptr src)
tcg_temp_free_i64(t64);
}
-static void gen_load_fp(DisasContext *s, int opsize, TCGv addr, TCGv_ptr fp)
+static void gen_load_fp(DisasContext *s, int opsize, TCGv addr, TCGv_ptr fp,
+ int index)
{
TCGv tmp;
TCGv_i64 t64;
- int index = IS_USER(s);
t64 = tcg_temp_new_i64();
tmp = tcg_temp_new();
@@ -995,11 +996,11 @@ static void gen_load_fp(DisasContext *s, int opsize, TCGv addr, TCGv_ptr fp)
tcg_temp_free_i64(t64);
}
-static void gen_store_fp(DisasContext *s, int opsize, TCGv addr, TCGv_ptr fp)
+static void gen_store_fp(DisasContext *s, int opsize, TCGv addr, TCGv_ptr fp,
+ int index)
{
TCGv tmp;
TCGv_i64 t64;
- int index = IS_USER(s);
t64 = tcg_temp_new_i64();
tmp = tcg_temp_new();
@@ -1050,17 +1051,18 @@ static void gen_store_fp(DisasContext *s, int opsize, TCGv addr, TCGv_ptr fp)
}
static void gen_ldst_fp(DisasContext *s, int opsize, TCGv addr,
- TCGv_ptr fp, ea_what what)
+ TCGv_ptr fp, ea_what what, int index)
{
if (what == EA_STORE) {
- gen_store_fp(s, opsize, addr, fp);
+ gen_store_fp(s, opsize, addr, fp, index);
} else {
- gen_load_fp(s, opsize, addr, fp);
+ gen_load_fp(s, opsize, addr, fp, index);
}
}
static int gen_ea_mode_fp(CPUM68KState *env, DisasContext *s, int mode,
- int reg0, int opsize, TCGv_ptr fp, ea_what what)
+ int reg0, int opsize, TCGv_ptr fp, ea_what what,
+ int index)
{
TCGv reg, addr, tmp;
TCGv_i64 t64;
@@ -1108,11 +1110,11 @@ static int gen_ea_mode_fp(CPUM68KState *env, DisasContext *s, int mode,
return -1;
case 2: /* Indirect register */
addr = get_areg(s, reg0);
- gen_ldst_fp(s, opsize, addr, fp, what);
+ gen_ldst_fp(s, opsize, addr, fp, what, index);
return 0;
case 3: /* Indirect postincrement. */
addr = cpu_aregs[reg0];
- gen_ldst_fp(s, opsize, addr, fp, what);
+ gen_ldst_fp(s, opsize, addr, fp, what, index);
tcg_gen_addi_i32(addr, addr, opsize_bytes(opsize));
return 0;
case 4: /* Indirect predecrememnt. */
@@ -1120,7 +1122,7 @@ static int gen_ea_mode_fp(CPUM68KState *env, DisasContext *s, int mode,
if (IS_NULL_QREG(addr)) {
return -1;
}
- gen_ldst_fp(s, opsize, addr, fp, what);
+ gen_ldst_fp(s, opsize, addr, fp, what, index);
tcg_gen_mov_i32(cpu_aregs[reg0], addr);
return 0;
case 5: /* Indirect displacement. */
@@ -1130,7 +1132,7 @@ static int gen_ea_mode_fp(CPUM68KState *env, DisasContext *s, int mode,
if (IS_NULL_QREG(addr)) {
return -1;
}
- gen_ldst_fp(s, opsize, addr, fp, what);
+ gen_ldst_fp(s, opsize, addr, fp, what, index);
return 0;
case 7: /* Other */
switch (reg0) {
@@ -1199,11 +1201,11 @@ static int gen_ea_mode_fp(CPUM68KState *env, DisasContext *s, int mode,
}
static int gen_ea_fp(CPUM68KState *env, DisasContext *s, uint16_t insn,
- int opsize, TCGv_ptr fp, ea_what what)
+ int opsize, TCGv_ptr fp, ea_what what, int index)
{
int mode = extract32(insn, 3, 3);
int reg0 = REG(insn, 0);
- return gen_ea_mode_fp(env, s, mode, reg0, opsize, fp, what);
+ return gen_ea_mode_fp(env, s, mode, reg0, opsize, fp, what, index);
}
typedef struct {
@@ -1423,7 +1425,7 @@ static void gen_lookup_tb(DisasContext *s)
#define SRC_EA(env, result, opsize, op_sign, addrp) do { \
result = gen_ea(env, s, insn, opsize, NULL_QREG, addrp, \
- op_sign ? EA_LOADS : EA_LOADU); \
+ op_sign ? EA_LOADS : EA_LOADU, IS_USER(s)); \
if (IS_NULL_QREG(result)) { \
gen_addr_fault(s); \
return; \
@@ -1431,7 +1433,8 @@ static void gen_lookup_tb(DisasContext *s)
} while (0)
#define DEST_EA(env, insn, opsize, val, addrp) do { \
- TCGv ea_result = gen_ea(env, s, insn, opsize, val, addrp, EA_STORE); \
+ TCGv ea_result = gen_ea(env, s, insn, opsize, val, addrp, \
+ EA_STORE, IS_USER(s)); \
if (IS_NULL_QREG(ea_result)) { \
gen_addr_fault(s); \
return; \
@@ -1768,13 +1771,14 @@ DISAS_INSN(abcd_mem)
/* Indirect pre-decrement load (mode 4) */
src = gen_ea_mode(env, s, 4, REG(insn, 0), OS_BYTE,
- NULL_QREG, NULL, EA_LOADU);
+ NULL_QREG, NULL, EA_LOADU, IS_USER(s));
dest = gen_ea_mode(env, s, 4, REG(insn, 9), OS_BYTE,
- NULL_QREG, &addr, EA_LOADU);
+ NULL_QREG, &addr, EA_LOADU, IS_USER(s));
bcd_add(dest, src);
- gen_ea_mode(env, s, 4, REG(insn, 9), OS_BYTE, dest, &addr, EA_STORE);
+ gen_ea_mode(env, s, 4, REG(insn, 9), OS_BYTE, dest, &addr,
+ EA_STORE, IS_USER(s));
bcd_flags(dest);
}
@@ -1804,13 +1808,14 @@ DISAS_INSN(sbcd_mem)
/* Indirect pre-decrement load (mode 4) */
src = gen_ea_mode(env, s, 4, REG(insn, 0), OS_BYTE,
- NULL_QREG, NULL, EA_LOADU);
+ NULL_QREG, NULL, EA_LOADU, IS_USER(s));
dest = gen_ea_mode(env, s, 4, REG(insn, 9), OS_BYTE,
- NULL_QREG, &addr, EA_LOADU);
+ NULL_QREG, &addr, EA_LOADU, IS_USER(s));
bcd_sub(dest, src);
- gen_ea_mode(env, s, 4, REG(insn, 9), OS_BYTE, dest, &addr, EA_STORE);
+ gen_ea_mode(env, s, 4, REG(insn, 9), OS_BYTE, dest, &addr,
+ EA_STORE, IS_USER(s));
bcd_flags(dest);
}
@@ -1947,7 +1952,7 @@ static void gen_push(DisasContext *s, TCGv val)
tmp = tcg_temp_new();
tcg_gen_subi_i32(tmp, QREG_SP, 4);
- gen_store(s, OS_LONG, tmp, val);
+ gen_store(s, OS_LONG, tmp, val, IS_USER(s));
tcg_gen_mov_i32(QREG_SP, tmp);
tcg_temp_free(tmp);
}
@@ -2016,7 +2021,7 @@ DISAS_INSN(movem)
/* memory to register */
for (i = 0; i < 16; i++) {
if (mask & (1 << i)) {
- r[i] = gen_load(s, opsize, addr, 1);
+ r[i] = gen_load(s, opsize, addr, 1, IS_USER(s));
tcg_gen_add_i32(addr, addr, incr);
}
}
@@ -2048,10 +2053,10 @@ DISAS_INSN(movem)
*/
tmp = tcg_temp_new();
tcg_gen_sub_i32(tmp, cpu_aregs[reg0], incr);
- gen_store(s, opsize, addr, tmp);
+ gen_store(s, opsize, addr, tmp, IS_USER(s));
tcg_temp_free(tmp);
} else {
- gen_store(s, opsize, addr, mreg(i));
+ gen_store(s, opsize, addr, mreg(i), IS_USER(s));
}
}
}
@@ -2059,7 +2064,7 @@ DISAS_INSN(movem)
} else {
for (i = 0; i < 16; i++) {
if (mask & (1 << i)) {
- gen_store(s, opsize, addr, mreg(i));
+ gen_store(s, opsize, addr, mreg(i), IS_USER(s));
tcg_gen_add_i32(addr, addr, incr);
}
}
@@ -2779,7 +2784,7 @@ static void gen_link(DisasContext *s, uint16_t insn, int32_t offset)
reg = AREG(insn, 0);
tmp = tcg_temp_new();
tcg_gen_subi_i32(tmp, QREG_SP, 4);
- gen_store(s, OS_LONG, tmp, reg);
+ gen_store(s, OS_LONG, tmp, reg, IS_USER(s));
if ((insn & 7) != 7) {
tcg_gen_mov_i32(reg, tmp);
}
@@ -2812,7 +2817,7 @@ DISAS_INSN(unlk)
src = tcg_temp_new();
reg = AREG(insn, 0);
tcg_gen_mov_i32(src, reg);
- tmp = gen_load(s, OS_LONG, src, 0);
+ tmp = gen_load(s, OS_LONG, src, 0, IS_USER(s));
tcg_gen_mov_i32(reg, tmp);
tcg_gen_addi_i32(QREG_SP, src, 4);
tcg_temp_free(src);
@@ -2839,7 +2844,7 @@ DISAS_INSN(rtd)
TCGv tmp;
int16_t offset = read_im16(env, s);
- tmp = gen_load(s, OS_LONG, QREG_SP, 0);
+ tmp = gen_load(s, OS_LONG, QREG_SP, 0, IS_USER(s));
tcg_gen_addi_i32(QREG_SP, QREG_SP, offset + 4);
gen_jmp(s, tmp);
}
@@ -2848,7 +2853,7 @@ DISAS_INSN(rts)
{
TCGv tmp;
- tmp = gen_load(s, OS_LONG, QREG_SP, 0);
+ tmp = gen_load(s, OS_LONG, QREG_SP, 0, IS_USER(s));
tcg_gen_addi_i32(QREG_SP, QREG_SP, 4);
gen_jmp(s, tmp);
}
@@ -3084,15 +3089,15 @@ DISAS_INSN(subx_mem)
addr_src = AREG(insn, 0);
tcg_gen_subi_i32(addr_src, addr_src, opsize);
- src = gen_load(s, opsize, addr_src, 1);
+ src = gen_load(s, opsize, addr_src, 1, IS_USER(s));
addr_dest = AREG(insn, 9);
tcg_gen_subi_i32(addr_dest, addr_dest, opsize);
- dest = gen_load(s, opsize, addr_dest, 1);
+ dest = gen_load(s, opsize, addr_dest, 1, IS_USER(s));
gen_subx(s, src, dest, opsize);
- gen_store(s, opsize, addr_dest, QREG_CC_N);
+ gen_store(s, opsize, addr_dest, QREG_CC_N, IS_USER(s));
}
DISAS_INSN(mov3q)
@@ -3144,10 +3149,10 @@ DISAS_INSN(cmpm)
/* Post-increment load (mode 3) from Ay. */
src = gen_ea_mode(env, s, 3, REG(insn, 0), opsize,
- NULL_QREG, NULL, EA_LOADS);
+ NULL_QREG, NULL, EA_LOADS, IS_USER(s));
/* Post-increment load (mode 3) from Ax. */
dst = gen_ea_mode(env, s, 3, REG(insn, 9), opsize,
- NULL_QREG, NULL, EA_LOADS);
+ NULL_QREG, NULL, EA_LOADS, IS_USER(s));
gen_update_cc_cmp(s, dst, src, opsize);
}
@@ -3290,15 +3295,15 @@ DISAS_INSN(addx_mem)
addr_src = AREG(insn, 0);
tcg_gen_subi_i32(addr_src, addr_src, opsize_bytes(opsize));
- src = gen_load(s, opsize, addr_src, 1);
+ src = gen_load(s, opsize, addr_src, 1, IS_USER(s));
addr_dest = AREG(insn, 9);
tcg_gen_subi_i32(addr_dest, addr_dest, opsize_bytes(opsize));
- dest = gen_load(s, opsize, addr_dest, 1);
+ dest = gen_load(s, opsize, addr_dest, 1, IS_USER(s));
gen_addx(s, src, dest, opsize);
- gen_store(s, opsize, addr_dest, QREG_CC_N);
+ gen_store(s, opsize, addr_dest, QREG_CC_N, IS_USER(s));
}
static inline void shift_im(DisasContext *s, uint16_t insn, int opsize)
@@ -4328,9 +4333,9 @@ DISAS_INSN(chk2)
addr2 = tcg_temp_new();
tcg_gen_addi_i32(addr2, addr1, opsize_bytes(opsize));
- bound1 = gen_load(s, opsize, addr1, 1);
+ bound1 = gen_load(s, opsize, addr1, 1, IS_USER(s));
tcg_temp_free(addr1);
- bound2 = gen_load(s, opsize, addr2, 1);
+ bound2 = gen_load(s, opsize, addr2, 1, IS_USER(s));
tcg_temp_free(addr2);
reg = tcg_temp_new();
@@ -4843,7 +4848,8 @@ DISAS_INSN(fpu)
case 3: /* fmove out */
cpu_src = gen_fp_ptr(REG(ext, 7));
opsize = ext_opsize(ext, 10);
- if (gen_ea_fp(env, s, insn, opsize, cpu_src, EA_STORE) == -1) {
+ if (gen_ea_fp(env, s, insn, opsize, cpu_src,
+ EA_STORE, IS_USER(s)) == -1) {
gen_addr_fault(s);
}
gen_helper_ftst(cpu_env, cpu_src);
@@ -4865,7 +4871,8 @@ DISAS_INSN(fpu)
/* Source effective address. */
opsize = ext_opsize(ext, 10);
cpu_src = gen_fp_result_ptr();
- if (gen_ea_fp(env, s, insn, opsize, cpu_src, EA_LOADS) == -1) {
+ if (gen_ea_fp(env, s, insn, opsize, cpu_src,
+ EA_LOADS, IS_USER(s)) == -1) {
gen_addr_fault(s);
return;
}
@@ -5264,7 +5271,7 @@ DISAS_INSN(mac)
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. */
- loadval = gen_load(s, OS_LONG, addr, 0);
+ loadval = gen_load(s, OS_LONG, addr, 0, IS_USER(s));
acc ^= 1;
rx = (ext & 0x8000) ? AREG(ext, 12) : DREG(insn, 12);