diff options
Diffstat (limited to 'target/m68k/translate.c')
-rw-r--r-- | target/m68k/translate.c | 56 |
1 files changed, 43 insertions, 13 deletions
diff --git a/target/m68k/translate.c b/target/m68k/translate.c index 1c2ff56305..6beaf9ed66 100644 --- a/target/m68k/translate.c +++ b/target/m68k/translate.c @@ -123,8 +123,34 @@ typedef struct DisasContext { int done_mac; int writeback_mask; TCGv writeback[8]; +#define MAX_TO_RELEASE 8 + int release_count; + TCGv release[MAX_TO_RELEASE]; } DisasContext; +static void init_release_array(DisasContext *s) +{ +#ifdef CONFIG_DEBUG_TCG + memset(s->release, 0, sizeof(s->release)); +#endif + s->release_count = 0; +} + +static void do_release(DisasContext *s) +{ + int i; + for (i = 0; i < s->release_count; i++) { + tcg_temp_free(s->release[i]); + } + init_release_array(s); +} + +static TCGv mark_to_release(DisasContext *s, TCGv tmp) +{ + g_assert(s->release_count < MAX_TO_RELEASE); + return s->release[s->release_count++] = tmp; +} + static TCGv get_areg(DisasContext *s, unsigned regno) { if (s->writeback_mask & (1 << regno)) { @@ -347,7 +373,8 @@ static TCGv gen_ldst(DisasContext *s, int opsize, TCGv addr, TCGv val, gen_store(s, opsize, addr, val, index); return store_dummy; } else { - return gen_load(s, opsize, addr, what == EA_LOADS, index); + return mark_to_release(s, gen_load(s, opsize, addr, + what == EA_LOADS, index)); } } @@ -439,7 +466,7 @@ static TCGv gen_lea_indexed(CPUM68KState *env, DisasContext *s, TCGv base) } else { bd = 0; } - tmp = tcg_temp_new(); + tmp = mark_to_release(s, tcg_temp_new()); if ((ext & 0x44) == 0) { /* pre-index */ add = gen_addr_index(s, ext, tmp); @@ -449,7 +476,7 @@ static TCGv gen_lea_indexed(CPUM68KState *env, DisasContext *s, TCGv base) if ((ext & 0x80) == 0) { /* base not suppressed */ if (IS_NULL_QREG(base)) { - base = tcg_const_i32(offset + bd); + base = mark_to_release(s, tcg_const_i32(offset + bd)); bd = 0; } if (!IS_NULL_QREG(add)) { @@ -465,11 +492,11 @@ static TCGv gen_lea_indexed(CPUM68KState *env, DisasContext *s, TCGv base) add = tmp; } } else { - add = tcg_const_i32(bd); + add = mark_to_release(s, tcg_const_i32(bd)); } if ((ext & 3) != 0) { /* memory indirect */ - base = gen_load(s, OS_LONG, add, 0, IS_USER(s)); + base = mark_to_release(s, 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); @@ -494,7 +521,7 @@ static TCGv gen_lea_indexed(CPUM68KState *env, DisasContext *s, TCGv base) } } else { /* brief extension word format */ - tmp = tcg_temp_new(); + tmp = mark_to_release(s, tcg_temp_new()); add = gen_addr_index(s, ext, tmp); if (!IS_NULL_QREG(base)) { tcg_gen_add_i32(tmp, add, base); @@ -624,7 +651,7 @@ static inline TCGv gen_extend(DisasContext *s, TCGv val, int opsize, int sign) if (opsize == OS_LONG) { tmp = val; } else { - tmp = tcg_temp_new(); + tmp = mark_to_release(s, tcg_temp_new()); gen_ext(tmp, val, opsize, sign); } @@ -746,7 +773,7 @@ static TCGv gen_lea_mode(CPUM68KState *env, DisasContext *s, return NULL_QREG; } reg = get_areg(s, reg0); - tmp = tcg_temp_new(); + tmp = mark_to_release(s, tcg_temp_new()); if (reg0 == 7 && opsize == OS_BYTE && m68k_feature(s->env, M68K_FEATURE_M68000)) { tcg_gen_subi_i32(tmp, reg, 2); @@ -756,7 +783,7 @@ static TCGv gen_lea_mode(CPUM68KState *env, DisasContext *s, return tmp; case 5: /* Indirect displacement. */ reg = get_areg(s, reg0); - tmp = tcg_temp_new(); + tmp = mark_to_release(s, tcg_temp_new()); ext = read_im16(env, s); tcg_gen_addi_i32(tmp, reg, (int16_t)ext); return tmp; @@ -767,14 +794,14 @@ static TCGv gen_lea_mode(CPUM68KState *env, DisasContext *s, switch (reg0) { case 0: /* Absolute short. */ offset = (int16_t)read_im16(env, s); - return tcg_const_i32(offset); + return mark_to_release(s, tcg_const_i32(offset)); case 1: /* Absolute long. */ offset = read_im32(env, s); - return tcg_const_i32(offset); + return mark_to_release(s, tcg_const_i32(offset)); case 2: /* pc displacement */ offset = s->pc; offset += (int16_t)read_im16(env, s); - return tcg_const_i32(offset); + return mark_to_release(s, tcg_const_i32(offset)); case 3: /* pc index+displacement. */ return gen_lea_indexed(env, s, NULL_QREG); case 4: /* Immediate. */ @@ -900,7 +927,7 @@ static TCGv gen_ea_mode(CPUM68KState *env, DisasContext *s, int mode, int reg0, default: g_assert_not_reached(); } - return tcg_const_i32(offset); + return mark_to_release(s, tcg_const_i32(offset)); default: return NULL_QREG; } @@ -6033,6 +6060,7 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s) uint16_t insn = read_im16(env, s); opcode_table[insn](env, s, insn); do_writebacks(s); + do_release(s); } /* generate intermediate code for basic block 'tb'. */ @@ -6067,6 +6095,8 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb) max_insns = TCG_MAX_INSNS; } + init_release_array(dc); + gen_tb_start(tb); do { pc_offset = dc->pc - pc_start; |