diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2018-05-11 15:41:29 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2018-05-11 15:41:29 +0100 |
commit | c74e62ee3e2dc2955e07d004c71badecb68a84eb (patch) | |
tree | d20da427e30c03e58e7ff560b29b012a6fb31d18 | |
parent | 6d7cde809d915e14728eda0af1c0618eb5710a96 (diff) | |
parent | 5b4f1d2db9fb0e24549054ee58c7a7d8f84ddd6e (diff) |
Merge remote-tracking branch 'remotes/rth/tags/cota-target-pull-request' into staging
* Fix all next_page checks for overflow.
* Convert six targets to the translator loop.
# gpg: Signature made Wed 09 May 2018 18:20:43 BST
# gpg: using RSA key 64DF38E8AF7E215F
# gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>"
# Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A 05C0 64DF 38E8 AF7E 215F
* remotes/rth/tags/cota-target-pull-request: (28 commits)
target/riscv: convert to TranslatorOps
target/riscv: convert to DisasContextBase
target/riscv: convert to DisasJumpType
target/openrisc: convert to TranslatorOps
target/openrisc: convert to DisasContextBase
target/s390x: convert to TranslatorOps
target/s390x: convert to DisasContextBase
target/s390x: convert to DisasJumpType
target/mips: convert to TranslatorOps
target/mips: use *ctx for DisasContext
target/mips: convert to DisasContextBase
target/mips: convert to DisasJumpType
target/mips: use lookup_and_goto_ptr on BS_STOP
target/sparc: convert to TranslatorOps
target/sparc: convert to DisasContextBase
target/sparc: convert to DisasJumpType
target/sh4: convert to TranslatorOps
translator: merge max_insns into DisasContextBase
target/mips: avoid integer overflow in next_page PC check
target/s390x: avoid integer overflow in next_page PC check
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | accel/tcg/translator.c | 21 | ||||
-rw-r--r-- | include/exec/translator.h | 8 | ||||
-rw-r--r-- | target/alpha/translate.c | 6 | ||||
-rw-r--r-- | target/arm/translate-a64.c | 8 | ||||
-rw-r--r-- | target/arm/translate.c | 20 | ||||
-rw-r--r-- | target/arm/translate.h | 2 | ||||
-rw-r--r-- | target/cris/translate.c | 6 | ||||
-rw-r--r-- | target/hppa/translate.c | 7 | ||||
-rw-r--r-- | target/i386/translate.c | 5 | ||||
-rw-r--r-- | target/lm32/translate.c | 6 | ||||
-rw-r--r-- | target/microblaze/translate.c | 6 | ||||
-rw-r--r-- | target/mips/translate.c | 623 | ||||
-rw-r--r-- | target/openrisc/translate.c | 226 | ||||
-rw-r--r-- | target/ppc/translate.c | 5 | ||||
-rw-r--r-- | target/riscv/translate.c | 255 | ||||
-rw-r--r-- | target/s390x/translate.c | 1529 | ||||
-rw-r--r-- | target/sh4/translate.c | 171 | ||||
-rw-r--r-- | target/sparc/translate.c | 207 | ||||
-rw-r--r-- | target/tilegx/translate.c | 4 | ||||
-rw-r--r-- | target/unicore32/translate.c | 6 | ||||
-rw-r--r-- | target/xtensa/translate.c | 9 |
21 files changed, 1546 insertions, 1584 deletions
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c index 23c6602cd9..0f9dca9113 100644 --- a/accel/tcg/translator.c +++ b/accel/tcg/translator.c @@ -34,8 +34,6 @@ void translator_loop_temp_check(DisasContextBase *db) void translator_loop(const TranslatorOps *ops, DisasContextBase *db, CPUState *cpu, TranslationBlock *tb) { - int max_insns; - /* Initialize DisasContext */ db->tb = tb; db->pc_first = tb->pc; @@ -45,18 +43,18 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db, db->singlestep_enabled = cpu->singlestep_enabled; /* Instruction counting */ - max_insns = tb_cflags(db->tb) & CF_COUNT_MASK; - if (max_insns == 0) { - max_insns = CF_COUNT_MASK; + db->max_insns = tb_cflags(db->tb) & CF_COUNT_MASK; + if (db->max_insns == 0) { + db->max_insns = CF_COUNT_MASK; } - if (max_insns > TCG_MAX_INSNS) { - max_insns = TCG_MAX_INSNS; + if (db->max_insns > TCG_MAX_INSNS) { + db->max_insns = TCG_MAX_INSNS; } if (db->singlestep_enabled || singlestep) { - max_insns = 1; + db->max_insns = 1; } - max_insns = ops->init_disas_context(db, cpu, max_insns); + ops->init_disas_context(db, cpu); tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */ /* Reset the temp count so that we can identify leaks */ @@ -95,7 +93,8 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db, update db->pc_next and db->is_jmp to indicate what should be done next -- either exiting this loop or locate the start of the next instruction. */ - if (db->num_insns == max_insns && (tb_cflags(db->tb) & CF_LAST_IO)) { + if (db->num_insns == db->max_insns + && (tb_cflags(db->tb) & CF_LAST_IO)) { /* Accept I/O on the last instruction. */ gen_io_start(); ops->translate_insn(db, cpu); @@ -111,7 +110,7 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db, /* Stop translation if the output buffer is full, or we have executed all of the allowed instructions. */ - if (tcg_op_buf_full() || db->num_insns >= max_insns) { + if (tcg_op_buf_full() || db->num_insns >= db->max_insns) { db->is_jmp = DISAS_TOO_MANY; break; } diff --git a/include/exec/translator.h b/include/exec/translator.h index e2dc2a04ae..71e7b2c347 100644 --- a/include/exec/translator.h +++ b/include/exec/translator.h @@ -58,6 +58,7 @@ typedef enum DisasJumpType { * disassembly). * @is_jmp: What instruction to disassemble next. * @num_insns: Number of translated instructions (including current). + * @max_insns: Maximum number of instructions to be translated in this TB. * @singlestep_enabled: "Hardware" single stepping enabled. * * Architecture-agnostic disassembly context. @@ -67,7 +68,8 @@ typedef struct DisasContextBase { target_ulong pc_first; target_ulong pc_next; DisasJumpType is_jmp; - unsigned int num_insns; + int num_insns; + int max_insns; bool singlestep_enabled; } DisasContextBase; @@ -76,7 +78,6 @@ typedef struct DisasContextBase { * @init_disas_context: * Initialize the target-specific portions of DisasContext struct. * The generic DisasContextBase has already been initialized. - * Return max_insns, modified as necessary by db->tb->flags. * * @tb_start: * Emit any code required before the start of the main loop, @@ -106,8 +107,7 @@ typedef struct DisasContextBase { * Print instruction disassembly to log. */ typedef struct TranslatorOps { - int (*init_disas_context)(DisasContextBase *db, CPUState *cpu, - int max_insns); + void (*init_disas_context)(DisasContextBase *db, CPUState *cpu); void (*tb_start)(DisasContextBase *db, CPUState *cpu); void (*insn_start)(DisasContextBase *db, CPUState *cpu); bool (*breakpoint_check)(DisasContextBase *db, CPUState *cpu, diff --git a/target/alpha/translate.c b/target/alpha/translate.c index 73a1b5e63e..15eca71d49 100644 --- a/target/alpha/translate.c +++ b/target/alpha/translate.c @@ -2919,8 +2919,7 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn) return ret; } -static int alpha_tr_init_disas_context(DisasContextBase *dcbase, - CPUState *cpu, int max_insns) +static void alpha_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu) { DisasContext *ctx = container_of(dcbase, DisasContext, base); CPUAlphaState *env = cpu->env_ptr; @@ -2959,8 +2958,7 @@ static int alpha_tr_init_disas_context(DisasContextBase *dcbase, mask = TARGET_PAGE_MASK; } bound = -(ctx->base.pc_first | mask) / 4; - - return MIN(max_insns, bound); + ctx->base.max_insns = MIN(ctx->base.max_insns, bound); } static void alpha_tr_tb_start(DisasContextBase *db, CPUState *cpu) diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 6d49f30b4a..1e7c150514 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -13224,8 +13224,8 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s) free_tmp_a64(s); } -static int aarch64_tr_init_disas_context(DisasContextBase *dcbase, - CPUState *cpu, int max_insns) +static void aarch64_tr_init_disas_context(DisasContextBase *dcbase, + CPUState *cpu) { DisasContext *dc = container_of(dcbase, DisasContext, base); CPUARMState *env = cpu->env_ptr; @@ -13288,11 +13288,9 @@ static int aarch64_tr_init_disas_context(DisasContextBase *dcbase, if (dc->ss_active) { bound = 1; } - max_insns = MIN(max_insns, bound); + dc->base.max_insns = MIN(dc->base.max_insns, bound); init_tmp_a64_array(dc); - - return max_insns; } static void aarch64_tr_tb_start(DisasContextBase *db, CPUState *cpu) diff --git a/target/arm/translate.c b/target/arm/translate.c index ad208867a7..731cf327a1 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -9930,7 +9930,7 @@ static bool thumb_insn_is_16bit(DisasContext *s, uint32_t insn) return false; } - if ((insn >> 11) == 0x1e && (s->pc < s->next_page_start - 3)) { + if ((insn >> 11) == 0x1e && s->pc - s->page_start < TARGET_PAGE_SIZE - 3) { /* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix, and the suffix * is not on the next page; we merge this into a 32-bit * insn. @@ -12243,8 +12243,7 @@ static bool insn_crosses_page(CPUARMState *env, DisasContext *s) return !thumb_insn_is_16bit(s, insn); } -static int arm_tr_init_disas_context(DisasContextBase *dcbase, - CPUState *cs, int max_insns) +static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) { DisasContext *dc = container_of(dcbase, DisasContext, base); CPUARMState *env = cs->env_ptr; @@ -12301,19 +12300,18 @@ static int arm_tr_init_disas_context(DisasContextBase *dcbase, dc->is_ldex = false; dc->ss_same_el = false; /* Can't be true since EL_d must be AArch64 */ - dc->next_page_start = - (dc->base.pc_first & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; + dc->page_start = dc->base.pc_first & TARGET_PAGE_MASK; /* If architectural single step active, limit to 1. */ if (is_singlestepping(dc)) { - max_insns = 1; + dc->base.max_insns = 1; } /* ARM is a fixed-length ISA. Bound the number of insns to execute to those left on the page. */ if (!dc->thumb) { - int bound = (dc->next_page_start - dc->base.pc_first) / 4; - max_insns = MIN(max_insns, bound); + int bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4; + dc->base.max_insns = MIN(dc->base.max_insns, bound); } cpu_F0s = tcg_temp_new_i32(); @@ -12324,8 +12322,6 @@ static int arm_tr_init_disas_context(DisasContextBase *dcbase, cpu_V1 = cpu_F1d; /* FIXME: cpu_M0 can probably be the same as cpu_V0. */ cpu_M0 = tcg_temp_new_i64(); - - return max_insns; } static void arm_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu) @@ -12584,8 +12580,8 @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) * but isn't very efficient). */ if (dc->base.is_jmp == DISAS_NEXT - && (dc->pc >= dc->next_page_start - || (dc->pc >= dc->next_page_start - 3 + && (dc->pc - dc->page_start >= TARGET_PAGE_SIZE + || (dc->pc - dc->page_start >= TARGET_PAGE_SIZE - 3 && insn_crosses_page(env, dc)))) { dc->base.is_jmp = DISAS_TOO_MANY; } diff --git a/target/arm/translate.h b/target/arm/translate.h index 4428c98e2e..37a1bba056 100644 --- a/target/arm/translate.h +++ b/target/arm/translate.h @@ -9,7 +9,7 @@ typedef struct DisasContext { DisasContextBase base; target_ulong pc; - target_ulong next_page_start; + target_ulong page_start; uint32_t insn; /* Nonzero if this instruction has been conditionally skipped. */ int condjmp; diff --git a/target/cris/translate.c b/target/cris/translate.c index f51a731db9..64b9ec6649 100644 --- a/target/cris/translate.c +++ b/target/cris/translate.c @@ -3091,7 +3091,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) unsigned int insn_len; struct DisasContext ctx; struct DisasContext *dc = &ctx; - uint32_t next_page_start; + uint32_t page_start; target_ulong npc; int num_insns; int max_insns; @@ -3138,7 +3138,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) dc->cpustate_changed = 0; - next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; + page_start = pc_start & TARGET_PAGE_MASK; num_insns = 0; max_insns = tb_cflags(tb) & CF_COUNT_MASK; if (max_insns == 0) { @@ -3234,7 +3234,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) } while (!dc->is_jmp && !dc->cpustate_changed && !tcg_op_buf_full() && !singlestep - && (dc->pc < next_page_start) + && (dc->pc - page_start < TARGET_PAGE_SIZE) && num_insns < max_insns); if (dc->clear_locked_irq) { diff --git a/target/hppa/translate.c b/target/hppa/translate.c index cdc397308b..5320b217de 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -4669,8 +4669,7 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn) return gen_illegal(ctx); } -static int hppa_tr_init_disas_context(DisasContextBase *dcbase, - CPUState *cs, int max_insns) +static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) { DisasContext *ctx = container_of(dcbase, DisasContext, base); int bound; @@ -4700,14 +4699,12 @@ static int hppa_tr_init_disas_context(DisasContextBase *dcbase, /* Bound the number of instructions by those left on the page. */ bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4; - bound = MIN(max_insns, bound); + ctx->base.max_insns = MIN(ctx->base.max_insns, bound); ctx->ntempr = 0; ctx->ntempl = 0; memset(ctx->tempr, 0, sizeof(ctx->tempr)); memset(ctx->templ, 0, sizeof(ctx->templ)); - - return bound; } static void hppa_tr_tb_start(DisasContextBase *dcbase, CPUState *cs) diff --git a/target/i386/translate.c b/target/i386/translate.c index c9ed8dc709..b0f69838f2 100644 --- a/target/i386/translate.c +++ b/target/i386/translate.c @@ -8402,8 +8402,7 @@ void tcg_x86_init(void) } } -static int i386_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu, - int max_insns) +static void i386_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu) { DisasContext *dc = container_of(dcbase, DisasContext, base); CPUX86State *env = cpu->env_ptr; @@ -8470,8 +8469,6 @@ static int i386_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu, cpu_ptr0 = tcg_temp_new_ptr(); cpu_ptr1 = tcg_temp_new_ptr(); cpu_cc_srcT = tcg_temp_local_new(); - - return max_insns; } static void i386_tr_tb_start(DisasContextBase *db, CPUState *cpu) diff --git a/target/lm32/translate.c b/target/lm32/translate.c index 2e1c5e6d01..fdd206a860 100644 --- a/target/lm32/translate.c +++ b/target/lm32/translate.c @@ -1055,7 +1055,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) LM32CPU *cpu = lm32_env_get_cpu(env); struct DisasContext ctx, *dc = &ctx; uint32_t pc_start; - uint32_t next_page_start; + uint32_t page_start; int num_insns; int max_insns; @@ -1075,7 +1075,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) pc_start &= ~3; } - next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; + page_start = pc_start & TARGET_PAGE_MASK; num_insns = 0; max_insns = tb_cflags(tb) & CF_COUNT_MASK; if (max_insns == 0) { @@ -1115,7 +1115,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) && !tcg_op_buf_full() && !cs->singlestep_enabled && !singlestep - && (dc->pc < next_page_start) + && (dc->pc - page_start < TARGET_PAGE_SIZE) && num_insns < max_insns); if (tb_cflags(tb) & CF_LAST_IO) { diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c index 100883e2cc..0872dc9ded 100644 --- a/target/microblaze/translate.c +++ b/target/microblaze/translate.c @@ -1635,7 +1635,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) uint32_t pc_start; struct DisasContext ctx; struct DisasContext *dc = &ctx; - uint32_t next_page_start, org_flags; + uint32_t page_start, org_flags; target_ulong npc; int num_insns; int max_insns; @@ -1661,7 +1661,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) cpu_abort(cs, "Microblaze: unaligned PC=%x\n", pc_start); } - next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; + page_start = pc_start & TARGET_PAGE_MASK; num_insns = 0; max_insns = tb_cflags(tb) & CF_COUNT_MASK; if (max_insns == 0) { @@ -1747,7 +1747,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) } while (!dc->is_jmp && !dc->cpustate_changed && !tcg_op_buf_full() && !singlestep - && (dc->pc < next_page_start) + && (dc->pc - page_start < TARGET_PAGE_SIZE) && num_insns < max_insns); npc = dc->pc; diff --git a/target/mips/translate.c b/target/mips/translate.c index d05ee67e63..9eff842c39 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -36,6 +36,7 @@ #include "target/mips/trace.h" #include "trace-tcg.h" +#include "exec/translator.h" #include "exec/log.h" #define MIPS_DEBUG_DISAS 0 @@ -1429,17 +1430,16 @@ static TCGv_i64 msa_wr_d[64]; } while(0) typedef struct DisasContext { - struct TranslationBlock *tb; - target_ulong pc, saved_pc; + DisasContextBase base; + target_ulong saved_pc; + target_ulong page_start; uint32_t opcode; - int singlestep_enabled; int insn_flags; int32_t CP0_Config1; /* Routine used to access memory */ int mem_idx; TCGMemOp default_tcg_memop_mask; uint32_t hflags, saved_hflags; - int bstate; target_ulong btarget; bool ulri; int kscrexist; @@ -1460,13 +1460,8 @@ typedef struct DisasContext { bool abs2008; } DisasContext; -enum { - BS_NONE = 0, /* We go out of the TB without reaching a branch or an - * exception condition */ - BS_STOP = 1, /* We want to stop translation for any reason */ - BS_BRANCH = 2, /* We reached a branch condition */ - BS_EXCP = 3, /* We reached an exception condition */ -}; +#define DISAS_STOP DISAS_TARGET_0 +#define DISAS_EXIT DISAS_TARGET_1 static const char * const regnames[] = { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3", @@ -1521,8 +1516,9 @@ static const char * const msaregnames[] = { if (MIPS_DEBUG_DISAS) { \ qemu_log_mask(CPU_LOG_TB_IN_ASM, \ TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \ - ctx->pc, ctx->opcode, op, ctx->opcode >> 26, \ - ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \ + ctx->base.pc_next, ctx->opcode, op, \ + ctx->opcode >> 26, ctx->opcode & 0x3F, \ + ((ctx->opcode >> 16) & 0x1F)); \ } \ } while (0) @@ -1598,9 +1594,9 @@ static inline void gen_save_pc(target_ulong pc) static inline void save_cpu_state(DisasContext *ctx, int do_save_pc) { LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags); - if (do_save_pc && ctx->pc != ctx->saved_pc) { - gen_save_pc(ctx->pc); - ctx->saved_pc = ctx->pc; + if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) { + gen_save_pc(ctx->base.pc_next); + ctx->saved_pc = ctx->base.pc_next; } if (ctx->hflags != ctx->saved_hflags) { tcg_gen_movi_i32(hflags, ctx->hflags); @@ -1639,7 +1635,7 @@ static inline void generate_exception_err(DisasContext *ctx, int excp, int err) gen_helper_raise_exception_err(cpu_env, texcp, terr); tcg_temp_free_i32(terr); tcg_temp_free_i32(texcp); - ctx->bstate = BS_EXCP; + ctx->base.is_jmp = DISAS_NORETURN; } static inline void generate_exception(DisasContext *ctx, int excp) @@ -2130,7 +2126,7 @@ static void gen_base_offset_addr (DisasContext *ctx, TCGv addr, static target_ulong pc_relative_pc (DisasContext *ctx) { - target_ulong pc = ctx->pc; + target_ulong pc = ctx->base.pc_next; if (ctx->hflags & MIPS_HFLAG_BMASK) { int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4; @@ -4279,12 +4275,12 @@ static void gen_trap (DisasContext *ctx, uint32_t opc, static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest) { - if (unlikely(ctx->singlestep_enabled)) { + if (unlikely(ctx->base.singlestep_enabled)) { return false; } #ifndef CONFIG_USER_ONLY - return (ctx->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK); + return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK); #else return true; #endif @@ -4295,10 +4291,10 @@ static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) if (use_goto_tb(ctx, dest)) { tcg_gen_goto_tb(n); gen_save_pc(dest); - tcg_gen_exit_tb((uintptr_t)ctx->tb + n); + tcg_gen_exit_tb((uintptr_t)ctx->base.tb + n); } else { gen_save_pc(dest); - if (ctx->singlestep_enabled) { + if (ctx->base.singlestep_enabled) { save_cpu_state(ctx, 0); gen_helper_raise_exception_debug(cpu_env); } @@ -4321,7 +4317,7 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, if (ctx->hflags & MIPS_HFLAG_BMASK) { #ifdef MIPS_DEBUG_DISAS LOG_DISAS("Branch in delay / forbidden slot at PC 0x" - TARGET_FMT_lx "\n", ctx->pc); + TARGET_FMT_lx "\n", ctx->base.pc_next); #endif generate_exception_end(ctx, EXCP_RI); goto out; @@ -4339,7 +4335,7 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, gen_load_gpr(t1, rt); bcond_compute = 1; } - btgt = ctx->pc + insn_bytes + offset; + btgt = ctx->base.pc_next + insn_bytes + offset; break; case OPC_BGEZ: case OPC_BGEZAL: @@ -4358,7 +4354,7 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, gen_load_gpr(t0, rs); bcond_compute = 1; } - btgt = ctx->pc + insn_bytes + offset; + btgt = ctx->base.pc_next + insn_bytes + offset; break; case OPC_BPOSGE32: #if defined(TARGET_MIPS64) @@ -4368,13 +4364,14 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F); #endif bcond_compute = 1; - btgt = ctx->pc + insn_bytes + offset; + btgt = ctx->base.pc_next + insn_bytes + offset; break; case OPC_J: case OPC_JAL: case OPC_JALX: /* Jump to immediate */ - btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset; + btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) | + (uint32_t)offset; break; case OPC_JR: case OPC_JALR: @@ -4420,19 +4417,19 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, /* Handle as an unconditional branch to get correct delay slot checking. */ blink = 31; - btgt = ctx->pc + insn_bytes + delayslot_size; + btgt = ctx->base.pc_next + insn_bytes + delayslot_size; ctx->hflags |= MIPS_HFLAG_B; break; case OPC_BLTZALL: /* 0 < 0 likely */ - tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8); + tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8); /* Skip the instruction in the delay slot */ - ctx->pc += 4; + ctx->base.pc_next += 4; goto out; case OPC_BNEL: /* rx != rx likely */ case OPC_BGTZL: /* 0 > 0 likely */ case OPC_BLTZL: /* 0 < 0 likely */ /* Skip the instruction in the delay slot */ - ctx->pc += 4; + ctx->base.pc_next += 4; goto out; case OPC_J: ctx->hflags |= MIPS_HFLAG_B; @@ -4544,7 +4541,8 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc, int post_delay = insn_bytes + delayslot_size; int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16); - tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit); + tcg_gen_movi_tl(cpu_gpr[blink], + ctx->base.pc_next + post_delay + lowbit); } out: @@ -5326,18 +5324,18 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) switch (sel) { case 0: /* Mark as an IO operation because we read the time. */ - if (tb_cflags(ctx->tb) & CF_USE_ICOUNT) { + if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { gen_io_start(); } gen_helper_mfc0_count(arg, cpu_env); - if (tb_cflags(ctx->tb) & CF_USE_ICOUNT) { + if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { gen_io_end(); } /* Break the TB to be able to take timer interrupts immediately - after reading count. BS_STOP isn't sufficient, we need to ensure - we break completely out of translated code. */ - gen_save_pc(ctx->pc + 4); - ctx->bstate = BS_EXCP; + after reading count. DISAS_STOP isn't sufficient, we need to + ensure we break completely out of translated code. */ + gen_save_pc(ctx->base.pc_next + 4); + ctx->base.is_jmp = DISAS_EXIT; rn = "Count"; break; /* 6,7 are implementation dependent */ @@ -5733,7 +5731,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) if (sel != 0) check_insn(ctx, ISA_MIPS32); - if (tb_cflags(ctx->tb) & CF_USE_ICOUNT) { + if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { gen_io_start(); } @@ -5905,7 +5903,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) check_insn(ctx, ISA_MIPS32R2); gen_helper_mtc0_pagegrain(cpu_env, arg); rn = "PageGrain"; - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; break; case 2: CP0_CHECK(ctx->sc); @@ -5966,7 +5964,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) case 0: check_insn(ctx, ISA_MIPS32R2); gen_helper_mtc0_hwrena(cpu_env, arg); - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; rn = "HWREna"; break; default: @@ -6028,30 +6026,30 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) case 0: save_cpu_state(ctx, 1); gen_helper_mtc0_status(cpu_env, arg); - /* BS_STOP isn't good enough here, hflags may have changed. */ - gen_save_pc(ctx->pc + 4); - ctx->bstate = BS_EXCP; + /* DISAS_STOP isn't good enough here, hflags may have changed. */ + gen_save_pc(ctx->base.pc_next + 4); + ctx->base.is_jmp = DISAS_EXIT; rn = "Status"; break; case 1: check_insn(ctx, ISA_MIPS32R2); gen_helper_mtc0_intctl(cpu_env, arg); /* Stop translation as we may have switched the execution mode */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; rn = "IntCtl"; break; case 2: check_insn(ctx, ISA_MIPS32R2); gen_helper_mtc0_srsctl(cpu_env, arg); /* Stop translation as we may have switched the execution mode */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; rn = "SRSCtl"; break; case 3: check_insn(ctx, ISA_MIPS32R2); gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap)); /* Stop translation as we may have switched the execution mode */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; rn = "SRSMap"; break; default: @@ -6063,11 +6061,11 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) case 0: save_cpu_state(ctx, 1); gen_helper_mtc0_cause(cpu_env, arg); - /* Stop translation as we may have triggered an interrupt. BS_STOP - * isn't sufficient, we need to ensure we break out of translated - * code to check for pending interrupts. */ - gen_save_pc(ctx->pc + 4); - ctx->bstate = BS_EXCP; + /* Stop translation as we may have triggered an interrupt. + * DISAS_STOP isn't sufficient, we need to ensure we break out of + * translated code to check for pending interrupts. */ + gen_save_pc(ctx->base.pc_next + 4); + ctx->base.is_jmp = DISAS_EXIT; rn = "Cause"; break; default: @@ -6105,7 +6103,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_helper_mtc0_config0(cpu_env, arg); rn = "Config"; /* Stop translation as we may have switched the execution mode */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; break; case 1: /* ignored, read only */ @@ -6115,24 +6113,24 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_helper_mtc0_config2(cpu_env, arg); rn = "Config2"; /* Stop translation as we may have switched the execution mode */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; break; case 3: gen_helper_mtc0_config3(cpu_env, arg); rn = "Config3"; /* Stop translation as we may have switched the execution mode */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; break; case 4: gen_helper_mtc0_config4(cpu_env, arg); rn = "Config4"; - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; break; case 5: gen_helper_mtc0_config5(cpu_env, arg); rn = "Config5"; /* Stop translation as we may have switched the execution mode */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; break; /* 6,7 are implementation dependent */ case 6: @@ -6221,35 +6219,35 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) switch (sel) { case 0: gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */ - /* BS_STOP isn't good enough here, hflags may have changed. */ - gen_save_pc(ctx->pc + 4); - ctx->bstate = BS_EXCP; + /* DISAS_STOP isn't good enough here, hflags may have changed. */ + gen_save_pc(ctx->base.pc_next + 4); + ctx->base.is_jmp = DISAS_EXIT; rn = "Debug"; break; case 1: // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */ rn = "TraceControl"; /* Stop translation as we may have switched the execution mode */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; goto cp0_unimplemented; case 2: // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */ rn = "TraceControl2"; /* Stop translation as we may have switched the execution mode */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; goto cp0_unimplemented; case 3: /* Stop translation as we may have switched the execution mode */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */ rn = "UserTraceData"; /* Stop translation as we may have switched the execution mode */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; goto cp0_unimplemented; case 4: // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */ /* Stop translation as we may have switched the execution mode */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; rn = "TraceBPC"; goto cp0_unimplemented; default: @@ -6309,7 +6307,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) switch (sel) { case 0: gen_helper_mtc0_errctl(cpu_env, arg); - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; rn = "ErrCtl"; break; default: @@ -6400,12 +6398,12 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) trace_mips_translate_c0("mtc0", rn, reg, sel); /* For simplicity assume that all writes can cause interrupts. */ - if (tb_cflags(ctx->tb) & CF_USE_ICOUNT) { + if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { gen_io_end(); - /* BS_STOP isn't sufficient, we need to ensure we break out of + /* DISAS_STOP isn't sufficient, we need to ensure we break out of * translated code to check for pending interrupts. */ - gen_save_pc(ctx->pc + 4); - ctx->bstate = BS_EXCP; + gen_save_pc(ctx->base.pc_next + 4); + ctx->base.is_jmp = DISAS_EXIT; } return; @@ -6678,18 +6676,18 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel) switch (sel) { case 0: /* Mark as an IO operation because we read the time. */ - if (tb_cflags(ctx->tb) & CF_USE_ICOUNT) { + if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { gen_io_start(); } gen_helper_mfc0_count(arg, cpu_env); - if (tb_cflags(ctx->tb) & CF_USE_ICOUNT) { + if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { gen_io_end(); } /* Break the TB to be able to take timer interrupts immediately - after reading count. BS_STOP isn't sufficient, we need to ensure - we break completely out of translated code. */ - gen_save_pc(ctx->pc + 4); - ctx->bstate = BS_EXCP; + after reading count. DISAS_STOP isn't sufficient, we need to + ensure we break completely out of translated code. */ + gen_save_pc(ctx->base.pc_next + 4); + ctx->base.is_jmp = DISAS_EXIT; rn = "Count"; break; /* 6,7 are implementation dependent */ @@ -7071,7 +7069,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) if (sel != 0) check_insn(ctx, ISA_MIPS64); - if (tb_cflags(ctx->tb) & CF_USE_ICOUNT) { + if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { gen_io_start(); } @@ -7301,7 +7299,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) case 0: check_insn(ctx, ISA_MIPS32R2); gen_helper_mtc0_hwrena(cpu_env, arg); - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; rn = "HWREna"; break; default: @@ -7337,7 +7335,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) goto cp0_unimplemented; } /* Stop translation as we may have switched the execution mode */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; break; case 10: switch (sel) { @@ -7360,37 +7358,37 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) goto cp0_unimplemented; } /* Stop translation as we may have switched the execution mode */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; break; case 12: switch (sel) { case 0: save_cpu_state(ctx, 1); gen_helper_mtc0_status(cpu_env, arg); - /* BS_STOP isn't good enough here, hflags may have changed. */ - gen_save_pc(ctx->pc + 4); - ctx->bstate = BS_EXCP; + /* DISAS_STOP isn't good enough here, hflags may have changed. */ + gen_save_pc(ctx->base.pc_next + 4); + ctx->base.is_jmp = DISAS_EXIT; rn = "Status"; break; case 1: check_insn(ctx, ISA_MIPS32R2); gen_helper_mtc0_intctl(cpu_env, arg); /* Stop translation as we may have switched the execution mode */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; rn = "IntCtl"; break; case 2: check_insn(ctx, ISA_MIPS32R2); gen_helper_mtc0_srsctl(cpu_env, arg); /* Stop translation as we may have switched the execution mode */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; rn = "SRSCtl"; break; case 3: check_insn(ctx, ISA_MIPS32R2); gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap)); /* Stop translation as we may have switched the execution mode */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; rn = "SRSMap"; break; default: @@ -7402,11 +7400,11 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) case 0: save_cpu_state(ctx, 1); gen_helper_mtc0_cause(cpu_env, arg); - /* Stop translation as we may have triggered an intetrupt. BS_STOP - * isn't sufficient, we need to ensure we break out of translated - * code to check for pending interrupts. */ - gen_save_pc(ctx->pc + 4); - ctx->bstate = BS_EXCP; + /* Stop translation as we may have triggered an interrupt. + * DISAS_STOP isn't sufficient, we need to ensure we break out of + * translated code to check for pending interrupts. */ + gen_save_pc(ctx->base.pc_next + 4); + ctx->base.is_jmp = DISAS_EXIT; rn = "Cause"; break; default: @@ -7444,7 +7442,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_helper_mtc0_config0(cpu_env, arg); rn = "Config"; /* Stop translation as we may have switched the execution mode */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; break; case 1: /* ignored, read only */ @@ -7454,13 +7452,13 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_helper_mtc0_config2(cpu_env, arg); rn = "Config2"; /* Stop translation as we may have switched the execution mode */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; break; case 3: gen_helper_mtc0_config3(cpu_env, arg); rn = "Config3"; /* Stop translation as we may have switched the execution mode */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; break; case 4: /* currently ignored */ @@ -7470,7 +7468,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_helper_mtc0_config5(cpu_env, arg); rn = "Config5"; /* Stop translation as we may have switched the execution mode */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; break; /* 6,7 are implementation dependent */ default: @@ -7549,33 +7547,33 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) switch (sel) { case 0: gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */ - /* BS_STOP isn't good enough here, hflags may have changed. */ - gen_save_pc(ctx->pc + 4); - ctx->bstate = BS_EXCP; + /* DISAS_STOP isn't good enough here, hflags may have changed. */ + gen_save_pc(ctx->base.pc_next + 4); + ctx->base.is_jmp = DISAS_EXIT; rn = "Debug"; break; case 1: // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */ /* Stop translation as we may have switched the execution mode */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; rn = "TraceControl"; goto cp0_unimplemented; case 2: // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */ /* Stop translation as we may have switched the execution mode */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; rn = "TraceControl2"; goto cp0_unimplemented; case 3: // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */ /* Stop translation as we may have switched the execution mode */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; rn = "UserTraceData"; goto cp0_unimplemented; case 4: // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */ /* Stop translation as we may have switched the execution mode */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; rn = "TraceBPC"; goto cp0_unimplemented; default: @@ -7635,7 +7633,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) switch (sel) { case 0: gen_helper_mtc0_errctl(cpu_env, arg); - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; rn = "ErrCtl"; break; default: @@ -7726,12 +7724,12 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) trace_mips_translate_c0("dmtc0", rn, reg, sel); /* For simplicity assume that all writes can cause interrupts. */ - if (tb_cflags(ctx->tb) & CF_USE_ICOUNT) { + if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { gen_io_end(); - /* BS_STOP isn't sufficient, we need to ensure we break out of + /* DISAS_STOP isn't sufficient, we need to ensure we break out of * translated code to check for pending interrupts. */ - gen_save_pc(ctx->pc + 4); - ctx->bstate = BS_EXCP; + gen_save_pc(ctx->base.pc_next + 4); + ctx->base.is_jmp = DISAS_EXIT; } return; @@ -8142,7 +8140,7 @@ static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt, tcg_temp_free_i32(fs_tmp); } /* Stop translation as we may have changed hflags */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; break; /* COP2: Not implemented. */ case 4: @@ -8301,7 +8299,7 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, check_insn(ctx, ISA_MIPS2); gen_helper_eret(cpu_env); } - ctx->bstate = BS_EXCP; + ctx->base.is_jmp = DISAS_EXIT; } break; case OPC_DERET: @@ -8316,7 +8314,7 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, generate_exception_end(ctx, EXCP_RI); } else { gen_helper_deret(cpu_env); - ctx->bstate = BS_EXCP; + ctx->base.is_jmp = DISAS_EXIT; } break; case OPC_WAIT: @@ -8327,11 +8325,11 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, goto die; } /* If we get an exception, we want to restart at next instruction */ - ctx->pc += 4; + ctx->base.pc_next += 4; save_cpu_state(ctx, 1); - ctx->pc -= 4; + ctx->base.pc_next -= 4; gen_helper_wait(cpu_env); - ctx->bstate = BS_EXCP; + ctx->base.is_jmp = DISAS_NORETURN; break; default: die: @@ -8358,7 +8356,7 @@ static void gen_compute_branch1(DisasContext *ctx, uint32_t op, if (cc != 0) check_insn(ctx, ISA_MIPS4 | ISA_MIPS32); - btarget = ctx->pc + 4 + offset; + btarget = ctx->base.pc_next + 4 + offset; switch (op) { case OPC_BC1F: @@ -8461,7 +8459,7 @@ static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op, if (ctx->hflags & MIPS_HFLAG_BMASK) { #ifdef MIPS_DEBUG_DISAS LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx - "\n", ctx->pc); + "\n", ctx->base.pc_next); #endif generate_exception_end(ctx, EXCP_RI); goto out; @@ -8470,7 +8468,7 @@ static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op, gen_load_fpr64(ctx, t0, ft); tcg_gen_andi_i64(t0, t0, 1); - btarget = addr_add(ctx, ctx->pc + 4, offset); + btarget = addr_add(ctx, ctx->base.pc_next + 4, offset); switch (op) { case OPC_BC1EQZ: @@ -8756,7 +8754,7 @@ static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs) tcg_temp_free_i32(fs_tmp); } /* Stop translation as we may have changed hflags */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; break; #if defined(TARGET_MIPS64) case OPC_DMFC1: @@ -10755,19 +10753,19 @@ static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel) gen_store_gpr(t0, rt); break; case 2: - if (tb_cflags(ctx->tb) & CF_USE_ICOUNT) { + if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { gen_io_start(); } gen_helper_rdhwr_cc(t0, cpu_env); - if (tb_cflags(ctx->tb) & CF_USE_ICOUNT) { + if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { gen_io_end(); } gen_store_gpr(t0, rt); /* Break the TB to be able to take timer interrupts immediately - after reading count. BS_STOP isn't sufficient, we need to ensure + after reading count. DISAS_STOP isn't sufficient, we need to ensure we break completely out of translated code. */ - gen_save_pc(ctx->pc + 4); - ctx->bstate = BS_EXCP; + gen_save_pc(ctx->base.pc_next + 4); + ctx->base.is_jmp = DISAS_EXIT; break; case 3: gen_helper_rdhwr_ccres(t0, cpu_env); @@ -10817,7 +10815,7 @@ static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel) static inline void clear_branch_hflags(DisasContext *ctx) { ctx->hflags &= ~MIPS_HFLAG_BMASK; - if (ctx->bstate == BS_NONE) { + if (ctx->base.is_jmp == DISAS_NEXT) { save_cpu_state(ctx, 0); } else { /* it is not safe to save ctx->hflags as hflags may be changed @@ -10832,11 +10830,11 @@ static void gen_branch(DisasContext *ctx, int insn_bytes) int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK; /* Branches completion */ clear_branch_hflags(ctx); - ctx->bstate = BS_BRANCH; + ctx->base.is_jmp = DISAS_NORETURN; /* FIXME: Need to clear can_do_io. */ switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) { case MIPS_HFLAG_FBNSLOT: - gen_goto_tb(ctx, 0, ctx->pc + insn_bytes); + gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes); break; case MIPS_HFLAG_B: /* unconditional branch */ @@ -10855,7 +10853,7 @@ static void gen_branch(DisasContext *ctx, int insn_bytes) TCGLabel *l1 = gen_new_label(); tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1); - gen_goto_tb(ctx, 1, ctx->pc + insn_bytes); + gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes); gen_set_label(l1); gen_goto_tb(ctx, 0, ctx->btarget); } @@ -10878,7 +10876,7 @@ static void gen_branch(DisasContext *ctx, int insn_bytes) } else { tcg_gen_mov_tl(cpu_PC, btarget); } - if (ctx->singlestep_enabled) { + if (ctx->base.singlestep_enabled) { save_cpu_state(ctx, 0); gen_helper_raise_exception_debug(cpu_env); } @@ -10903,7 +10901,7 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc, if (ctx->hflags & MIPS_HFLAG_BMASK) { #ifdef MIPS_DEBUG_DISAS LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx - "\n", ctx->pc); + "\n", ctx->base.pc_next); #endif generate_exception_end(ctx, EXCP_RI); goto out; @@ -10917,10 +10915,10 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc, gen_load_gpr(t0, rs); gen_load_gpr(t1, rt); bcond_compute = 1; - ctx->btarget = addr_add(ctx, ctx->pc + 4, offset); + ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset); if (rs <= rt && rs == 0) { /* OPC_BEQZALC, OPC_BNEZALC */ - tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit); + tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit); } break; case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */ @@ -10928,23 +10926,23 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc, gen_load_gpr(t0, rs); gen_load_gpr(t1, rt); bcond_compute = 1; - ctx->btarget = addr_add(ctx, ctx->pc + 4, offset); + ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset); break; case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */ case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */ if (rs == 0 || rs == rt) { /* OPC_BLEZALC, OPC_BGEZALC */ /* OPC_BGTZALC, OPC_BLTZALC */ - tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit); + tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit); } gen_load_gpr(t0, rs); gen_load_gpr(t1, rt); bcond_compute = 1; - ctx->btarget = addr_add(ctx, ctx->pc + 4, offset); + ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset); break; case OPC_BC: case OPC_BALC: - ctx->btarget = addr_add(ctx, ctx->pc + 4, offset); + ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset); break; case OPC_BEQZC: case OPC_BNEZC: @@ -10952,7 +10950,7 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc, /* OPC_BEQZC, OPC_BNEZC */ gen_load_gpr(t0, rs); bcond_compute = 1; - ctx->btarget = addr_add(ctx, ctx->pc + 4, offset); + ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset); } else { /* OPC_JIC, OPC_JIALC */ TCGv tbase = tcg_temp_new(); @@ -10975,13 +10973,13 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc, /* Uncoditional compact branch */ switch (opc) { case OPC_JIALC: - tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit); + tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit); /* Fallthrough */ case OPC_JIC: ctx->hflags |= MIPS_HFLAG_BR; break; case OPC_BALC: - tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit); + tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit); /* Fallthrough */ case OPC_BC: ctx->hflags |= MIPS_HFLAG_B; @@ -11606,7 +11604,7 @@ static void decode_i64_mips16 (DisasContext *ctx, static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx) { - int extend = cpu_lduw_code(env, ctx->pc + 2); + int extend = cpu_lduw_code(env, ctx->base.pc_next + 2); int op, rx, ry, funct, sa; int16_t imm, offset; @@ -11846,7 +11844,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx) /* No delay slot, so just process as a normal instruction */ break; case M16_OPC_JAL: - offset = cpu_lduw_code(env, ctx->pc + 2); + offset = cpu_lduw_code(env, ctx->base.pc_next + 2); offset = (((ctx->opcode & 0x1f) << 21) | ((ctx->opcode >> 5) & 0x1f) << 16 | offset) << 2; @@ -13574,7 +13572,7 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs) gen_helper_di(t0, cpu_env); gen_store_gpr(t0, rs); /* Stop translation as we may have switched the execution mode */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; tcg_temp_free(t0); } break; @@ -13586,10 +13584,10 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs) save_cpu_state(ctx, 1); gen_helper_ei(t0, cpu_env); gen_store_gpr(t0, rs); - /* BS_STOP isn't sufficient, we need to ensure we break out + /* DISAS_STOP isn't sufficient, we need to ensure we break out of translated code to check for pending interrupts. */ - gen_save_pc(ctx->pc + 4); - ctx->bstate = BS_EXCP; + gen_save_pc(ctx->base.pc_next + 4); + ctx->base.is_jmp = DISAS_EXIT; tcg_temp_free(t0); } break; @@ -13944,7 +13942,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx) uint32_t op, minor, minor2, mips32_op; uint32_t cond, fmt, cc; - insn = cpu_lduw_code(env, ctx->pc + 2); + insn = cpu_lduw_code(env, ctx->base.pc_next + 2); ctx->opcode = (ctx->opcode << 16) | insn; rt = (ctx->opcode >> 21) & 0x1f; @@ -14745,7 +14743,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx) /* SYNCI */ /* Break the TB to be able to sync copied instructions immediately */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; } else { /* TNEI */ mips32_op = OPC_TNEI; @@ -14776,7 +14774,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx) check_insn_opc_removed(ctx, ISA_MIPS32R6); /* Break the TB to be able to sync copied instructions immediately */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; break; case BC2F: case BC2T: @@ -15139,16 +15137,16 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx) /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */ switch ((ctx->opcode >> 16) & 0x1f) { case ADDIUPC_00 ... ADDIUPC_07: - gen_pcrel(ctx, OPC_ADDIUPC, ctx->pc & ~0x3, rt); + gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt); break; case AUIPC: - gen_pcrel(ctx, OPC_AUIPC, ctx->pc, rt); + gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt); break; case ALUIPC: - gen_pcrel(ctx, OPC_ALUIPC, ctx->pc, rt); + gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt); break; case LWPC_08 ... LWPC_0F: - gen_pcrel(ctx, R6_OPC_LWPC, ctx->pc & ~0x3, rt); + gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt); break; default: generate_exception(ctx, EXCP_RI); @@ -15280,8 +15278,8 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx) uint32_t op; /* make sure instructions are on a halfword boundary */ - if (ctx->pc & 0x1) { - env->CP0_BadVAddr = ctx->pc; + if (ctx->base.pc_next & 0x1) { + env->CP0_BadVAddr = ctx->base.pc_next; generate_exception_end(ctx, EXCP_AdEL); return 2; } @@ -18507,7 +18505,7 @@ static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1) break; } - ctx->btarget = ctx->pc + (s16 << 2) + 4; + ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4; ctx->hflags |= MIPS_HFLAG_BC; ctx->hflags |= MIPS_HFLAG_BDS32; @@ -19528,8 +19526,8 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) int16_t imm; /* make sure instructions are on a word boundary */ - if (ctx->pc & 0x3) { - env->CP0_BadVAddr = ctx->pc; + if (ctx->base.pc_next & 0x3) { + env->CP0_BadVAddr = ctx->base.pc_next; generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL); return; } @@ -19540,7 +19538,7 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1); tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK); - gen_goto_tb(ctx, 1, ctx->pc + 4); + gen_goto_tb(ctx, 1, ctx->base.pc_next + 4); gen_set_label(l1); } @@ -19601,7 +19599,7 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) check_insn(ctx, ISA_MIPS32R2); /* Break the TB to be able to sync copied instructions immediately */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; break; case OPC_BPOSGE32: /* MIPS DSP branch */ #if defined(TARGET_MIPS64) @@ -19704,17 +19702,17 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) gen_store_gpr(t0, rt); /* Stop translation as we may have switched the execution mode. */ - ctx->bstate = BS_STOP; + ctx->base.is_jmp = DISAS_STOP; break; case OPC_EI: check_insn(ctx, ISA_MIPS32R2); save_cpu_state(ctx, 1); gen_helper_ei(t0, cpu_env); gen_store_gpr(t0, rt); - /* BS_STOP isn't sufficient, we need to ensure we break out - of translated code to check for pending interrupts. */ - gen_save_pc(ctx->pc + 4); - ctx->bstate = BS_EXCP; + /* DISAS_STOP isn't sufficient, we need to ensure we break + out of translated code to check for pending interrupts */ + gen_save_pc(ctx->base.pc_next + 4); + ctx->base.is_jmp = DISAS_EXIT; break; default: /* Invalid */ MIPS_INVAL("mfmc0"); @@ -20188,7 +20186,7 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) break; case OPC_PCREL: check_insn(ctx, ISA_MIPS32R6); - gen_pcrel(ctx, ctx->opcode, ctx->pc, rs); + gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs); break; default: /* Invalid */ MIPS_INVAL("major opcode"); @@ -20197,183 +20195,186 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) } } -void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) +static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) { + DisasContext *ctx = container_of(dcbase, DisasContext, base); CPUMIPSState *env = cs->env_ptr; - DisasContext ctx; - target_ulong pc_start; - target_ulong next_page_start; - int num_insns; - int max_insns; - int insn_bytes; - int is_slot; - pc_start = tb->pc; - next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; - ctx.pc = pc_start; - ctx.saved_pc = -1; - ctx.singlestep_enabled = cs->singlestep_enabled; - ctx.insn_flags = env->insn_flags; - ctx.CP0_Config1 = env->CP0_Config1; - ctx.tb = tb; - ctx.bstate = BS_NONE; - ctx.btarget = 0; - ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff; - ctx.rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1; - ctx.ie = (env->CP0_Config4 >> CP0C4_IE) & 3; - ctx.bi = (env->CP0_Config3 >> CP0C3_BI) & 1; - ctx.bp = (env->CP0_Config3 >> CP0C3_BP) & 1; - ctx.PAMask = env->PAMask; - ctx.mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1; - ctx.eva = (env->CP0_Config5 >> CP0C5_EVA) & 1; - ctx.sc = (env->CP0_Config3 >> CP0C3_SC) & 1; - ctx.CP0_LLAddr_shift = env->CP0_LLAddr_shift; - ctx.cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1; + ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK; + ctx->saved_pc = -1; + ctx->insn_flags = env->insn_flags; + ctx->CP0_Config1 = env->CP0_Config1; + ctx->btarget = 0; + ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff; + ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1; + ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3; + ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1; + ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1; + ctx->PAMask = env->PAMask; + ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1; + ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1; + ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1; + ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift; + ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1; /* Restore delay slot state from the tb context. */ - ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */ - ctx.ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1; - ctx.ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) || + ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */ + ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1; + ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) || (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)); - ctx.vp = (env->CP0_Config5 >> CP0C5_VP) & 1; - ctx.mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1; - ctx.nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1; - ctx.abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1; - restore_cpu_state(env, &ctx); + ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1; + ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1; + ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1; + ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1; + restore_cpu_state(env, ctx); #ifdef CONFIG_USER_ONLY - ctx.mem_idx = MIPS_HFLAG_UM; + ctx->mem_idx = MIPS_HFLAG_UM; #else - ctx.mem_idx = hflags_mmu_index(ctx.hflags); + ctx->mem_idx = hflags_mmu_index(ctx->hflags); #endif - ctx.default_tcg_memop_mask = (ctx.insn_flags & ISA_MIPS32R6) ? - MO_UNALN : MO_ALIGN; - num_insns = 0; - max_insns = tb_cflags(tb) & CF_COUNT_MASK; - if (max_insns == 0) { - max_insns = CF_COUNT_MASK; - } - if (max_insns > TCG_MAX_INSNS) { - max_insns = TCG_MAX_INSNS; - } + ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ? + MO_UNALN : MO_ALIGN; - LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags); - gen_tb_start(tb); - while (ctx.bstate == BS_NONE) { - tcg_gen_insn_start(ctx.pc, ctx.hflags & MIPS_HFLAG_BMASK, ctx.btarget); - num_insns++; + LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx, + ctx->hflags); +} - if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) { - save_cpu_state(&ctx, 1); - ctx.bstate = BS_BRANCH; - gen_helper_raise_exception_debug(cpu_env); - /* The address covered by the breakpoint must be included in - [tb->pc, tb->pc + tb->size) in order to for it to be - properly cleared -- thus we increment the PC here so that - the logic setting tb->size below does the right thing. */ - ctx.pc += 4; - goto done_generating; - } +static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs) +{ +} - if (num_insns == max_insns && (tb_cflags(tb) & CF_LAST_IO)) { - gen_io_start(); - } +static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) +{ + DisasContext *ctx = container_of(dcbase, DisasContext, base); - is_slot = ctx.hflags & MIPS_HFLAG_BMASK; - if (!(ctx.hflags & MIPS_HFLAG_M16)) { - ctx.opcode = cpu_ldl_code(env, ctx.pc); - insn_bytes = 4; - decode_opc(env, &ctx); - } else if (ctx.insn_flags & ASE_MICROMIPS) { - ctx.opcode = cpu_lduw_code(env, ctx.pc); - insn_bytes = decode_micromips_opc(env, &ctx); - } else if (ctx.insn_flags & ASE_MIPS16) { - ctx.opcode = cpu_lduw_code(env, ctx.pc); - insn_bytes = decode_mips16_opc(env, &ctx); - } else { - generate_exception_end(&ctx, EXCP_RI); - break; - } + tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK, + ctx->btarget); +} - if (ctx.hflags & MIPS_HFLAG_BMASK) { - if (!(ctx.hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 | - MIPS_HFLAG_FBNSLOT))) { - /* force to generate branch as there is neither delay nor - forbidden slot */ - is_slot = 1; - } - if ((ctx.hflags & MIPS_HFLAG_M16) && - (ctx.hflags & MIPS_HFLAG_FBNSLOT)) { - /* Force to generate branch as microMIPS R6 doesn't restrict - branches in the forbidden slot. */ - is_slot = 1; - } - } - if (is_slot) { - gen_branch(&ctx, insn_bytes); - } - ctx.pc += insn_bytes; +static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, + const CPUBreakpoint *bp) +{ + DisasContext *ctx = container_of(dcbase, DisasContext, base); - /* Execute a branch and its delay slot as a single instruction. - This is what GDB expects and is consistent with what the - hardware does (e.g. if a delay slot instruction faults, the - reported PC is the PC of the branch). */ - if (cs->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0) { - break; - } + save_cpu_state(ctx, 1); + ctx->base.is_jmp = DISAS_NORETURN; + gen_helper_raise_exception_debug(cpu_env); + /* The address covered by the breakpoint must be included in + [tb->pc, tb->pc + tb->size) in order to for it to be + properly cleared -- thus we increment the PC here so that + the logic setting tb->size below does the right thing. */ + ctx->base.pc_next += 4; + return true; +} - if (ctx.pc >= next_page_start) { - break; - } +static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) +{ + CPUMIPSState *env = cs->env_ptr; + DisasContext *ctx = container_of(dcbase, DisasContext, base); + int insn_bytes; + int is_slot; - if (tcg_op_buf_full()) { - break; - } + is_slot = ctx->hflags & MIPS_HFLAG_BMASK; + if (!(ctx->hflags & MIPS_HFLAG_M16)) { + ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next); + insn_bytes = 4; + decode_opc(env, ctx); + } else if (ctx->insn_flags & ASE_MICROMIPS) { + ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next); + insn_bytes = decode_micromips_opc(env, ctx); + } else if (ctx->insn_flags & ASE_MIPS16) { + ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next); + insn_bytes = decode_mips16_opc(env, ctx); + } else { + generate_exception_end(ctx, EXCP_RI); + g_assert(ctx->base.is_jmp == DISAS_NORETURN); + return; + } - if (num_insns >= max_insns) - break; + if (ctx->hflags & MIPS_HFLAG_BMASK) { + if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 | + MIPS_HFLAG_FBNSLOT))) { + /* force to generate branch as there is neither delay nor + forbidden slot */ + is_slot = 1; + } + if ((ctx->hflags & MIPS_HFLAG_M16) && + (ctx->hflags & MIPS_HFLAG_FBNSLOT)) { + /* Force to generate branch as microMIPS R6 doesn't restrict + branches in the forbidden slot. */ + is_slot = 1; + } + } + if (is_slot) { + gen_branch(ctx, insn_bytes); + } + ctx->base.pc_next += insn_bytes; - if (singlestep) - break; + if (ctx->base.is_jmp != DISAS_NEXT) { + return; } - if (tb_cflags(tb) & CF_LAST_IO) { - gen_io_end(); + /* Execute a branch and its delay slot as a single instruction. + This is what GDB expects and is consistent with what the + hardware does (e.g. if a delay slot instruction faults, the + reported PC is the PC of the branch). */ + if (ctx->base.singlestep_enabled && + (ctx->hflags & MIPS_HFLAG_BMASK) == 0) { + ctx->base.is_jmp = DISAS_TOO_MANY; } - if (cs->singlestep_enabled && ctx.bstate != BS_BRANCH) { - save_cpu_state(&ctx, ctx.bstate != BS_EXCP); + if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) { + ctx->base.is_jmp = DISAS_TOO_MANY; + } +} + +static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) +{ + DisasContext *ctx = container_of(dcbase, DisasContext, base); + + if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) { + save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT); gen_helper_raise_exception_debug(cpu_env); } else { - switch (ctx.bstate) { - case BS_STOP: - gen_goto_tb(&ctx, 0, ctx.pc); + switch (ctx->base.is_jmp) { + case DISAS_STOP: + gen_save_pc(ctx->base.pc_next); + tcg_gen_lookup_and_goto_ptr(); break; - case BS_NONE: - save_cpu_state(&ctx, 0); - gen_goto_tb(&ctx, 0, ctx.pc); + case DISAS_NEXT: + case DISAS_TOO_MANY: + save_cpu_state(ctx, 0); + gen_goto_tb(ctx, 0, ctx->base.pc_next); break; - case BS_EXCP: + case DISAS_EXIT: tcg_gen_exit_tb(0); break; - case BS_BRANCH: - default: + case DISAS_NORETURN: break; + default: + g_assert_not_reached(); } } -done_generating: - gen_tb_end(tb, num_insns); - - tb->size = ctx.pc - pc_start; - tb->icount = num_insns; - -#ifdef DEBUG_DISAS - LOG_DISAS("\n"); - if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) - && qemu_log_in_addr_range(pc_start)) { - qemu_log_lock(); - qemu_log("IN: %s\n", lookup_symbol(pc_start)); - log_target_disas(cs, pc_start, ctx.pc - pc_start); - qemu_log("\n"); - qemu_log_unlock(); - } -#endif +} + +static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs) +{ + qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first)); + log_target_disas(cs, dcbase->pc_first, dcbase->tb->size); +} + +static const TranslatorOps mips_tr_ops = { + .init_disas_context = mips_tr_init_disas_context, + .tb_start = mips_tr_tb_start, + .insn_start = mips_tr_insn_start, + .breakpoint_check = mips_tr_breakpoint_check, + .translate_insn = mips_tr_translate_insn, + .tb_stop = mips_tr_tb_stop, + .disas_log = mips_tr_disas_log, +}; + +void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) +{ + DisasContext ctx; + + translator_loop(&mips_tr_ops, &ctx.base, cs, tb); } static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf, diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index 2747b24cf0..7cf29cd5b0 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -36,7 +36,8 @@ #include "exec/log.h" #define LOG_DIS(str, ...) \ - qemu_log_mask(CPU_LOG_TB_IN_ASM, "%08x: " str, dc->pc, ## __VA_ARGS__) + qemu_log_mask(CPU_LOG_TB_IN_ASM, "%08x: " str, dc->base.pc_next, \ + ## __VA_ARGS__) /* is_jmp field values */ #define DISAS_JUMP DISAS_TARGET_0 /* only pc was modified dynamically */ @@ -44,13 +45,10 @@ #define DISAS_TB_JUMP DISAS_TARGET_2 /* only pc was modified statically */ typedef struct DisasContext { - TranslationBlock *tb; - target_ulong pc; - uint32_t is_jmp; + DisasContextBase base; uint32_t mem_idx; uint32_t tb_flags; uint32_t delayed_branch; - bool singlestep_enabled; } DisasContext; static TCGv cpu_sr; @@ -126,9 +124,9 @@ static void gen_exception(DisasContext *dc, unsigned int excp) static void gen_illegal_exception(DisasContext *dc) { - tcg_gen_movi_tl(cpu_pc, dc->pc); + tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); gen_exception(dc, EXCP_ILLEGAL); - dc->is_jmp = DISAS_UPDATE; + dc->base.is_jmp = DISAS_NORETURN; } /* not used yet, open it when we need or64. */ @@ -166,12 +164,12 @@ static void check_ov64s(DisasContext *dc) static inline bool use_goto_tb(DisasContext *dc, target_ulong dest) { - if (unlikely(dc->singlestep_enabled)) { + if (unlikely(dc->base.singlestep_enabled)) { return false; } #ifndef CONFIG_USER_ONLY - return (dc->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK); + return (dc->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK); #else return true; #endif @@ -182,10 +180,10 @@ static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest) if (use_goto_tb(dc, dest)) { tcg_gen_movi_tl(cpu_pc, dest); tcg_gen_goto_tb(n); - tcg_gen_exit_tb((uintptr_t)dc->tb + n); + tcg_gen_exit_tb((uintptr_t)dc->base.tb + n); } else { tcg_gen_movi_tl(cpu_pc, dest); - if (dc->singlestep_enabled) { + if (dc->base.singlestep_enabled) { gen_exception(dc, EXCP_DEBUG); } tcg_gen_exit_tb(0); @@ -194,16 +192,16 @@ static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest) static void gen_jump(DisasContext *dc, int32_t n26, uint32_t reg, uint32_t op0) { - target_ulong tmp_pc = dc->pc + n26 * 4; + target_ulong tmp_pc = dc->base.pc_next + n26 * 4; switch (op0) { case 0x00: /* l.j */ tcg_gen_movi_tl(jmp_pc, tmp_pc); break; case 0x01: /* l.jal */ - tcg_gen_movi_tl(cpu_R[9], dc->pc + 8); + tcg_gen_movi_tl(cpu_R[9], dc->base.pc_next + 8); /* Optimize jal being used to load the PC for PIC. */ - if (tmp_pc == dc->pc + 8) { + if (tmp_pc == dc->base.pc_next + 8) { return; } tcg_gen_movi_tl(jmp_pc, tmp_pc); @@ -211,7 +209,7 @@ static void gen_jump(DisasContext *dc, int32_t n26, uint32_t reg, uint32_t op0) case 0x03: /* l.bnf */ case 0x04: /* l.bf */ { - TCGv t_next = tcg_const_tl(dc->pc + 8); + TCGv t_next = tcg_const_tl(dc->base.pc_next + 8); TCGv t_true = tcg_const_tl(tmp_pc); TCGv t_zero = tcg_const_tl(0); @@ -227,7 +225,7 @@ static void gen_jump(DisasContext *dc, int32_t n26, uint32_t reg, uint32_t op0) tcg_gen_mov_tl(jmp_pc, cpu_R[reg]); break; case 0x12: /* l.jalr */ - tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8)); + tcg_gen_movi_tl(cpu_R[9], (dc->base.pc_next + 8)); tcg_gen_mov_tl(jmp_pc, cpu_R[reg]); break; default: @@ -795,7 +793,7 @@ static void dec_misc(DisasContext *dc, uint32_t insn) return; } gen_helper_rfe(cpu_env); - dc->is_jmp = DISAS_UPDATE; + dc->base.is_jmp = DISAS_UPDATE; #endif } break; @@ -1254,15 +1252,16 @@ static void dec_sys(DisasContext *dc, uint32_t insn) switch (op0) { case 0x000: /* l.sys */ LOG_DIS("l.sys %d\n", K16); - tcg_gen_movi_tl(cpu_pc, dc->pc); + tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); gen_exception(dc, EXCP_SYSCALL); - dc->is_jmp = DISAS_UPDATE; + dc->base.is_jmp = DISAS_NORETURN; break; case 0x100: /* l.trap */ LOG_DIS("l.trap %d\n", K16); - tcg_gen_movi_tl(cpu_pc, dc->pc); + tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); gen_exception(dc, EXCP_TRAP); + dc->base.is_jmp = DISAS_NORETURN; break; case 0x300: /* l.csync */ @@ -1479,7 +1478,7 @@ static void disas_openrisc_insn(DisasContext *dc, OpenRISCCPU *cpu) { uint32_t op0; uint32_t insn; - insn = cpu_ldl_code(&cpu->env, dc->pc); + insn = cpu_ldl_code(&cpu->env, dc->base.pc_next); op0 = extract32(insn, 26, 6); switch (op0) { @@ -1521,45 +1520,22 @@ static void disas_openrisc_insn(DisasContext *dc, OpenRISCCPU *cpu) } } -void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) +static void openrisc_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs) { + DisasContext *dc = container_of(dcb, DisasContext, base); CPUOpenRISCState *env = cs->env_ptr; - OpenRISCCPU *cpu = openrisc_env_get_cpu(env); - struct DisasContext ctx, *dc = &ctx; - uint32_t pc_start; - uint32_t next_page_start; - int num_insns; - int max_insns; - - pc_start = tb->pc; - dc->tb = tb; - - dc->is_jmp = DISAS_NEXT; - dc->pc = pc_start; - dc->mem_idx = cpu_mmu_index(&cpu->env, false); - dc->tb_flags = tb->flags; - dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0; - dc->singlestep_enabled = cs->singlestep_enabled; - - next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; - num_insns = 0; - max_insns = tb_cflags(tb) & CF_COUNT_MASK; - - if (max_insns == 0) { - max_insns = CF_COUNT_MASK; - } - if (max_insns > TCG_MAX_INSNS) { - max_insns = TCG_MAX_INSNS; - } + int bound; - if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) - && qemu_log_in_addr_range(pc_start)) { - qemu_log_lock(); - qemu_log("----------------\n"); - qemu_log("IN: %s\n", lookup_symbol(pc_start)); - } + dc->mem_idx = cpu_mmu_index(env, false); + dc->tb_flags = dc->base.tb->flags; + dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0; + bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4; + dc->base.max_insns = MIN(dc->base.max_insns, bound); +} - gen_tb_start(tb); +static void openrisc_tr_tb_start(DisasContextBase *db, CPUState *cs) +{ + DisasContext *dc = container_of(db, DisasContext, base); /* Allow the TCG optimizer to see that R0 == 0, when it's true, which is the common case. */ @@ -1568,92 +1544,110 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) } else { cpu_R[0] = cpu_R0; } +} - do { - tcg_gen_insn_start(dc->pc, (dc->delayed_branch ? 1 : 0) - | (num_insns ? 2 : 0)); - num_insns++; +static void openrisc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) +{ + DisasContext *dc = container_of(dcbase, DisasContext, base); - if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) { - tcg_gen_movi_tl(cpu_pc, dc->pc); - gen_exception(dc, EXCP_DEBUG); - dc->is_jmp = DISAS_UPDATE; - /* The address covered by the breakpoint must be included in - [tb->pc, tb->pc + tb->size) in order to for it to be - properly cleared -- thus we increment the PC here so that - the logic setting tb->size below does the right thing. */ - dc->pc += 4; - break; - } + tcg_gen_insn_start(dc->base.pc_next, (dc->delayed_branch ? 1 : 0) + | (dc->base.num_insns > 1 ? 2 : 0)); +} - if (num_insns == max_insns && (tb_cflags(tb) & CF_LAST_IO)) { - gen_io_start(); - } - disas_openrisc_insn(dc, cpu); - dc->pc = dc->pc + 4; - - /* delay slot */ - if (dc->delayed_branch) { - dc->delayed_branch--; - if (!dc->delayed_branch) { - tcg_gen_mov_tl(cpu_pc, jmp_pc); - tcg_gen_discard_tl(jmp_pc); - dc->is_jmp = DISAS_UPDATE; - break; - } +static bool openrisc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, + const CPUBreakpoint *bp) +{ + DisasContext *dc = container_of(dcbase, DisasContext, base); + + tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); + gen_exception(dc, EXCP_DEBUG); + dc->base.is_jmp = DISAS_NORETURN; + /* The address covered by the breakpoint must be included in + [tb->pc, tb->pc + tb->size) in order to for it to be + properly cleared -- thus we increment the PC here so that + the logic setting tb->size below does the right thing. */ + dc->base.pc_next += 4; + return true; +} + +static void openrisc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) +{ + DisasContext *dc = container_of(dcbase, DisasContext, base); + OpenRISCCPU *cpu = OPENRISC_CPU(cs); + + disas_openrisc_insn(dc, cpu); + dc->base.pc_next += 4; + + /* delay slot */ + if (dc->delayed_branch) { + dc->delayed_branch--; + if (!dc->delayed_branch) { + tcg_gen_mov_tl(cpu_pc, jmp_pc); + tcg_gen_discard_tl(jmp_pc); + dc->base.is_jmp = DISAS_UPDATE; + return; } - } while (!dc->is_jmp - && !tcg_op_buf_full() - && !cs->singlestep_enabled - && !singlestep - && (dc->pc < next_page_start) - && num_insns < max_insns); - - if (tb_cflags(tb) & CF_LAST_IO) { - gen_io_end(); } +} + +static void openrisc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) +{ + DisasContext *dc = container_of(dcbase, DisasContext, base); if ((dc->tb_flags & TB_FLAGS_DFLAG ? 1 : 0) != (dc->delayed_branch != 0)) { tcg_gen_movi_i32(cpu_dflag, dc->delayed_branch != 0); } - tcg_gen_movi_tl(cpu_ppc, dc->pc - 4); - if (dc->is_jmp == DISAS_NEXT) { - dc->is_jmp = DISAS_UPDATE; - tcg_gen_movi_tl(cpu_pc, dc->pc); + tcg_gen_movi_tl(cpu_ppc, dc->base.pc_next - 4); + if (dc->base.is_jmp == DISAS_NEXT) { + dc->base.is_jmp = DISAS_UPDATE; + tcg_gen_movi_tl(cpu_pc, dc->base.pc_next); } - if (unlikely(cs->singlestep_enabled)) { + if (unlikely(dc->base.singlestep_enabled)) { gen_exception(dc, EXCP_DEBUG); } else { - switch (dc->is_jmp) { - case DISAS_NEXT: - gen_goto_tb(dc, 0, dc->pc); + switch (dc->base.is_jmp) { + case DISAS_TOO_MANY: + gen_goto_tb(dc, 0, dc->base.pc_next); break; - default: + case DISAS_NORETURN: case DISAS_JUMP: + case DISAS_TB_JUMP: break; case DISAS_UPDATE: /* indicate that the hash table must be used to find the next TB */ tcg_gen_exit_tb(0); break; - case DISAS_TB_JUMP: - /* nothing more to generate */ - break; + default: + g_assert_not_reached(); } } +} + +static void openrisc_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs) +{ + DisasContext *s = container_of(dcbase, DisasContext, base); - gen_tb_end(tb, num_insns); + qemu_log("IN: %s\n", lookup_symbol(s->base.pc_first)); + log_target_disas(cs, s->base.pc_first, s->base.tb->size); +} - tb->size = dc->pc - pc_start; - tb->icount = num_insns; +static const TranslatorOps openrisc_tr_ops = { + .init_disas_context = openrisc_tr_init_disas_context, + .tb_start = openrisc_tr_tb_start, + .insn_start = openrisc_tr_insn_start, + .breakpoint_check = openrisc_tr_breakpoint_check, + .translate_insn = openrisc_tr_translate_insn, + .tb_stop = openrisc_tr_tb_stop, + .disas_log = openrisc_tr_disas_log, +}; - if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) - && qemu_log_in_addr_range(pc_start)) { - log_target_disas(cs, pc_start, tb->size); - qemu_log("\n"); - qemu_log_unlock(); - } +void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) +{ + DisasContext ctx; + + translator_loop(&openrisc_tr_ops, &ctx.base, cs, tb); } void openrisc_cpu_dump_state(CPUState *cs, FILE *f, diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 2a4140f420..7972e6b410 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -7215,8 +7215,7 @@ void ppc_cpu_dump_statistics(CPUState *cs, FILE*f, #endif } -static int ppc_tr_init_disas_context(DisasContextBase *dcbase, - CPUState *cs, int max_insns) +static void ppc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) { DisasContext *ctx = container_of(dcbase, DisasContext, base); CPUPPCState *env = cs->env_ptr; @@ -7281,7 +7280,7 @@ static int ppc_tr_init_disas_context(DisasContextBase *dcbase, #endif bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4; - return MIN(max_insns, bound); + ctx->base.max_insns = MIN(ctx->base.max_insns, bound); } static void ppc_tr_tb_start(DisasContextBase *db, CPUState *cs) diff --git a/target/riscv/translate.c b/target/riscv/translate.c index c0e6a044d3..1788668c6f 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -26,6 +26,7 @@ #include "exec/helper-proto.h" #include "exec/helper-gen.h" +#include "exec/translator.h" #include "exec/log.h" #include "instmap.h" @@ -39,14 +40,12 @@ static TCGv load_val; #include "exec/gen-icount.h" typedef struct DisasContext { - struct TranslationBlock *tb; - target_ulong pc; - target_ulong next_pc; + DisasContextBase base; + /* pc_succ_insn points to the instruction following base.pc_next */ + target_ulong pc_succ_insn; uint32_t opcode; uint32_t flags; uint32_t mem_idx; - int singlestep_enabled; - int bstate; /* Remember the rounding mode encoded in the previous fp instruction, which we have already installed into env->fp_status. Or -1 for no previous fp instruction. Note that we exit the TB when writing @@ -55,13 +54,6 @@ typedef struct DisasContext { int frm; } DisasContext; -enum { - BS_NONE = 0, /* When seen outside of translation while loop, indicates - need to exit tb due to end of page. */ - BS_STOP = 1, /* Need to exit tb for syscall, sret, etc. */ - BS_BRANCH = 2, /* Need to exit tb for branch, jal, etc. */ -}; - /* convert riscv funct3 to qemu memop for load/store */ static const int tcg_memop_lookup[8] = { [0 ... 7] = -1, @@ -84,21 +76,21 @@ static const int tcg_memop_lookup[8] = { static void generate_exception(DisasContext *ctx, int excp) { - tcg_gen_movi_tl(cpu_pc, ctx->pc); + tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); TCGv_i32 helper_tmp = tcg_const_i32(excp); gen_helper_raise_exception(cpu_env, helper_tmp); tcg_temp_free_i32(helper_tmp); - ctx->bstate = BS_BRANCH; + ctx->base.is_jmp = DISAS_NORETURN; } static void generate_exception_mbadaddr(DisasContext *ctx, int excp) { - tcg_gen_movi_tl(cpu_pc, ctx->pc); + tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); tcg_gen_st_tl(cpu_pc, cpu_env, offsetof(CPURISCVState, badaddr)); TCGv_i32 helper_tmp = tcg_const_i32(excp); gen_helper_raise_exception(cpu_env, helper_tmp); tcg_temp_free_i32(helper_tmp); - ctx->bstate = BS_BRANCH; + ctx->base.is_jmp = DISAS_NORETURN; } static void gen_exception_debug(void) @@ -120,12 +112,12 @@ static void gen_exception_inst_addr_mis(DisasContext *ctx) static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest) { - if (unlikely(ctx->singlestep_enabled)) { + if (unlikely(ctx->base.singlestep_enabled)) { return false; } #ifndef CONFIG_USER_ONLY - return (ctx->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK); + return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK); #else return true; #endif @@ -137,10 +129,10 @@ static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) /* chaining is only allowed when the jump is to the same page */ tcg_gen_goto_tb(n); tcg_gen_movi_tl(cpu_pc, dest); - tcg_gen_exit_tb((uintptr_t)ctx->tb + n); + tcg_gen_exit_tb((uintptr_t)ctx->base.tb + n); } else { tcg_gen_movi_tl(cpu_pc, dest); - if (ctx->singlestep_enabled) { + if (ctx->base.singlestep_enabled) { gen_exception_debug(); } else { tcg_gen_exit_tb(0); @@ -519,7 +511,7 @@ static void gen_jal(CPURISCVState *env, DisasContext *ctx, int rd, target_ulong next_pc; /* check misaligned: */ - next_pc = ctx->pc + imm; + next_pc = ctx->base.pc_next + imm; if (!riscv_has_ext(env, RVC)) { if ((next_pc & 0x3) != 0) { gen_exception_inst_addr_mis(ctx); @@ -527,11 +519,11 @@ static void gen_jal(CPURISCVState *env, DisasContext *ctx, int rd, } } if (rd != 0) { - tcg_gen_movi_tl(cpu_gpr[rd], ctx->next_pc); + tcg_gen_movi_tl(cpu_gpr[rd], ctx->pc_succ_insn); } - gen_goto_tb(ctx, 0, ctx->pc + imm); /* must use this for safety */ - ctx->bstate = BS_BRANCH; + gen_goto_tb(ctx, 0, ctx->base.pc_next + imm); /* must use this for safety */ + ctx->base.is_jmp = DISAS_NORETURN; } static void gen_jalr(CPURISCVState *env, DisasContext *ctx, uint32_t opc, @@ -554,7 +546,7 @@ static void gen_jalr(CPURISCVState *env, DisasContext *ctx, uint32_t opc, } if (rd != 0) { - tcg_gen_movi_tl(cpu_gpr[rd], ctx->next_pc); + tcg_gen_movi_tl(cpu_gpr[rd], ctx->pc_succ_insn); } tcg_gen_exit_tb(0); @@ -562,7 +554,7 @@ static void gen_jalr(CPURISCVState *env, DisasContext *ctx, uint32_t opc, gen_set_label(misaligned); gen_exception_inst_addr_mis(ctx); } - ctx->bstate = BS_BRANCH; + ctx->base.is_jmp = DISAS_NORETURN; break; default: @@ -608,15 +600,15 @@ static void gen_branch(CPURISCVState *env, DisasContext *ctx, uint32_t opc, tcg_temp_free(source1); tcg_temp_free(source2); - gen_goto_tb(ctx, 1, ctx->next_pc); + gen_goto_tb(ctx, 1, ctx->pc_succ_insn); gen_set_label(l); /* branch taken */ - if (!riscv_has_ext(env, RVC) && ((ctx->pc + bimm) & 0x3)) { + if (!riscv_has_ext(env, RVC) && ((ctx->base.pc_next + bimm) & 0x3)) { /* misaligned */ gen_exception_inst_addr_mis(ctx); } else { - gen_goto_tb(ctx, 0, ctx->pc + bimm); + gen_goto_tb(ctx, 0, ctx->base.pc_next + bimm); } - ctx->bstate = BS_BRANCH; + ctx->base.is_jmp = DISAS_NORETURN; } static void gen_load(DisasContext *ctx, uint32_t opc, int rd, int rs1, @@ -842,7 +834,7 @@ static void gen_atomic(DisasContext *ctx, uint32_t opc, if (rl) { tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL); } - if (tb_cflags(ctx->tb) & CF_PARALLEL) { + if (tb_cflags(ctx->base.tb) & CF_PARALLEL) { l1 = gen_new_label(); gen_set_label(l1); } else { @@ -859,7 +851,7 @@ static void gen_atomic(DisasContext *ctx, uint32_t opc, tcg_gen_qemu_ld_tl(dat, src1, ctx->mem_idx, mop); tcg_gen_movcond_tl(cond, src2, dat, src2, dat, src2); - if (tb_cflags(ctx->tb) & CF_PARALLEL) { + if (tb_cflags(ctx->base.tb) & CF_PARALLEL) { /* Parallel context. Make this operation atomic by verifying that the memory didn't change while we computed the result. */ tcg_gen_atomic_cmpxchg_tl(src2, src1, dat, src2, ctx->mem_idx, mop); @@ -1323,7 +1315,7 @@ static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc, rs1_pass = tcg_temp_new(); imm_rs1 = tcg_temp_new(); gen_get_gpr(source1, rs1); - tcg_gen_movi_tl(cpu_pc, ctx->pc); + tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); tcg_gen_movi_tl(rs1_pass, rs1); tcg_gen_movi_tl(csr_store, csr); /* copy into temp reg to feed to helper */ @@ -1344,12 +1336,12 @@ static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc, /* always generates U-level ECALL, fixed in do_interrupt handler */ generate_exception(ctx, RISCV_EXCP_U_ECALL); tcg_gen_exit_tb(0); /* no chaining */ - ctx->bstate = BS_BRANCH; + ctx->base.is_jmp = DISAS_NORETURN; break; case 0x1: /* EBREAK */ generate_exception(ctx, RISCV_EXCP_BREAKPOINT); tcg_gen_exit_tb(0); /* no chaining */ - ctx->bstate = BS_BRANCH; + ctx->base.is_jmp = DISAS_NORETURN; break; #ifndef CONFIG_USER_ONLY case 0x002: /* URET */ @@ -1359,7 +1351,7 @@ static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc, if (riscv_has_ext(env, RVS)) { gen_helper_sret(cpu_pc, cpu_env, cpu_pc); tcg_gen_exit_tb(0); /* no chaining */ - ctx->bstate = BS_BRANCH; + ctx->base.is_jmp = DISAS_NORETURN; } else { gen_exception_illegal(ctx); } @@ -1370,13 +1362,13 @@ static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc, case 0x302: /* MRET */ gen_helper_mret(cpu_pc, cpu_env, cpu_pc); tcg_gen_exit_tb(0); /* no chaining */ - ctx->bstate = BS_BRANCH; + ctx->base.is_jmp = DISAS_NORETURN; break; case 0x7b2: /* DRET */ gen_exception_illegal(ctx); break; case 0x105: /* WFI */ - tcg_gen_movi_tl(cpu_pc, ctx->next_pc); + tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn); gen_helper_wfi(cpu_env); break; case 0x104: /* SFENCE.VM */ @@ -1417,9 +1409,9 @@ static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc, gen_io_end(); gen_set_gpr(rd, dest); /* end tb since we may be changing priv modes, to get mmu_index right */ - tcg_gen_movi_tl(cpu_pc, ctx->next_pc); + tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn); tcg_gen_exit_tb(0); /* no chaining */ - ctx->bstate = BS_BRANCH; + ctx->base.is_jmp = DISAS_NORETURN; break; } tcg_temp_free(source1); @@ -1737,7 +1729,7 @@ static void decode_RV32_64G(CPURISCVState *env, DisasContext *ctx) break; /* NOP */ } tcg_gen_movi_tl(cpu_gpr[rd], (sextract64(ctx->opcode, 12, 20) << 12) + - ctx->pc); + ctx->base.pc_next); break; case OPC_RISC_JAL: imm = GET_JAL_IMM(ctx->opcode); @@ -1810,9 +1802,9 @@ static void decode_RV32_64G(CPURISCVState *env, DisasContext *ctx) if (ctx->opcode & 0x1000) { /* FENCE_I is a no-op in QEMU, * however we need to end the translation block */ - tcg_gen_movi_tl(cpu_pc, ctx->next_pc); + tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn); tcg_gen_exit_tb(0); - ctx->bstate = BS_BRANCH; + ctx->base.is_jmp = DISAS_NORETURN; } else { /* FENCE is a full memory barrier. */ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC); @@ -1836,120 +1828,113 @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx) if (!riscv_has_ext(env, RVC)) { gen_exception_illegal(ctx); } else { - ctx->next_pc = ctx->pc + 2; + ctx->pc_succ_insn = ctx->base.pc_next + 2; decode_RV32_64C(env, ctx); } } else { - ctx->next_pc = ctx->pc + 4; + ctx->pc_succ_insn = ctx->base.pc_next + 4; decode_RV32_64G(env, ctx); } } -void gen_intermediate_code(CPUState *cs, TranslationBlock *tb) +static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) { - CPURISCVState *env = cs->env_ptr; - DisasContext ctx; - target_ulong pc_start; - target_ulong next_page_start; - int num_insns; - int max_insns; - pc_start = tb->pc; - next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; - ctx.pc = pc_start; - - /* once we have GDB, the rest of the translate.c implementation should be - ready for singlestep */ - ctx.singlestep_enabled = cs->singlestep_enabled; - - ctx.tb = tb; - ctx.bstate = BS_NONE; - ctx.flags = tb->flags; - ctx.mem_idx = tb->flags & TB_FLAGS_MMU_MASK; - ctx.frm = -1; /* unknown rounding mode */ - - num_insns = 0; - max_insns = tb->cflags & CF_COUNT_MASK; - if (max_insns == 0) { - max_insns = CF_COUNT_MASK; - } - if (max_insns > TCG_MAX_INSNS) { - max_insns = TCG_MAX_INSNS; - } - gen_tb_start(tb); + DisasContext *ctx = container_of(dcbase, DisasContext, base); - while (ctx.bstate == BS_NONE) { - tcg_gen_insn_start(ctx.pc); - num_insns++; + ctx->pc_succ_insn = ctx->base.pc_first; + ctx->flags = ctx->base.tb->flags; + ctx->mem_idx = ctx->base.tb->flags & TB_FLAGS_MMU_MASK; + ctx->frm = -1; /* unknown rounding mode */ +} - if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) { - tcg_gen_movi_tl(cpu_pc, ctx.pc); - ctx.bstate = BS_BRANCH; - gen_exception_debug(); - /* The address covered by the breakpoint must be included in - [tb->pc, tb->pc + tb->size) in order to for it to be - properly cleared -- thus we increment the PC here so that - the logic setting tb->size below does the right thing. */ - ctx.pc += 4; - goto done_generating; - } +static void riscv_tr_tb_start(DisasContextBase *db, CPUState *cpu) +{ +} - if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { - gen_io_start(); - } +static void riscv_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) +{ + DisasContext *ctx = container_of(dcbase, DisasContext, base); - ctx.opcode = cpu_ldl_code(env, ctx.pc); - decode_opc(env, &ctx); - ctx.pc = ctx.next_pc; + tcg_gen_insn_start(ctx->base.pc_next); +} - if (cs->singlestep_enabled) { - break; - } - if (ctx.pc >= next_page_start) { - break; - } - if (tcg_op_buf_full()) { - break; - } - if (num_insns >= max_insns) { - break; - } - if (singlestep) { - break; - } +static bool riscv_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, + const CPUBreakpoint *bp) +{ + DisasContext *ctx = container_of(dcbase, DisasContext, base); + + tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); + ctx->base.is_jmp = DISAS_NORETURN; + gen_exception_debug(); + /* The address covered by the breakpoint must be included in + [tb->pc, tb->pc + tb->size) in order to for it to be + properly cleared -- thus we increment the PC here so that + the logic setting tb->size below does the right thing. */ + ctx->base.pc_next += 4; + return true; +} + +static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) +{ + DisasContext *ctx = container_of(dcbase, DisasContext, base); + CPURISCVState *env = cpu->env_ptr; + + ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next); + decode_opc(env, ctx); + ctx->base.pc_next = ctx->pc_succ_insn; + + if (ctx->base.is_jmp == DISAS_NEXT) { + target_ulong page_start; + + page_start = ctx->base.pc_first & TARGET_PAGE_MASK; + if (ctx->base.pc_next - page_start >= TARGET_PAGE_SIZE) { + ctx->base.is_jmp = DISAS_TOO_MANY; + } } - if (tb->cflags & CF_LAST_IO) { - gen_io_end(); - } - switch (ctx.bstate) { - case BS_STOP: - gen_goto_tb(&ctx, 0, ctx.pc); - break; - case BS_NONE: /* handle end of page - DO NOT CHAIN. See gen_goto_tb. */ - tcg_gen_movi_tl(cpu_pc, ctx.pc); - if (cs->singlestep_enabled) { +} + +static void riscv_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) +{ + DisasContext *ctx = container_of(dcbase, DisasContext, base); + + switch (ctx->base.is_jmp) { + case DISAS_TOO_MANY: + tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); + if (ctx->base.singlestep_enabled) { gen_exception_debug(); } else { tcg_gen_exit_tb(0); } break; - case BS_BRANCH: /* ops using BS_BRANCH generate own exit seq */ - default: + case DISAS_NORETURN: break; + default: + g_assert_not_reached(); } -done_generating: - gen_tb_end(tb, num_insns); - tb->size = ctx.pc - pc_start; - tb->icount = num_insns; - -#ifdef DEBUG_DISAS - if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) - && qemu_log_in_addr_range(pc_start)) { - qemu_log("IN: %s\n", lookup_symbol(pc_start)); - log_target_disas(cs, pc_start, ctx.pc - pc_start); - qemu_log("\n"); - } -#endif +} + +static void riscv_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu) +{ + qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first)); + log_target_disas(cpu, dcbase->pc_first, dcbase->tb->size); +} + +static const TranslatorOps riscv_tr_ops = { + .init_disas_context = riscv_tr_init_disas_context, + .tb_start = riscv_tr_tb_start, + .insn_start = riscv_tr_insn_start, + .breakpoint_check = riscv_tr_breakpoint_check, + .translate_insn = riscv_tr_translate_insn, + .tb_stop = riscv_tr_tb_stop, + .disas_log = riscv_tr_disas_log, +}; + +void gen_intermediate_code(CPUState *cs, TranslationBlock *tb) +{ + DisasContext ctx; + + translator_loop(&riscv_tr_ops, &ctx.base, cs, tb); } void riscv_translate_init(void) diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 7d39ab350d..82309faa11 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -42,6 +42,7 @@ #include "exec/helper-gen.h" #include "trace-tcg.h" +#include "exec/translator.h" #include "exec/log.h" @@ -51,14 +52,19 @@ typedef struct DisasInsn DisasInsn; typedef struct DisasFields DisasFields; struct DisasContext { - struct TranslationBlock *tb; + DisasContextBase base; const DisasInsn *insn; DisasFields *fields; uint64_t ex_value; - uint64_t pc, next_pc; + /* + * During translate_one(), pc_tmp is used to determine the instruction + * to be executed after base.pc_next - e.g. next sequential instruction + * or a branch target. + */ + uint64_t pc_tmp; uint32_t ilen; enum cc_op cc_op; - bool singlestep_enabled; + bool do_debug; }; /* Information carried about a condition to be evaluated. */ @@ -73,9 +79,6 @@ typedef struct { } u; } DisasCompare; -/* is_jmp field values */ -#define DISAS_EXCP DISAS_TARGET_0 - #ifdef DEBUG_INLINE_BRANCHES static uint64_t inline_branch_hit[CC_OP_MAX]; static uint64_t inline_branch_miss[CC_OP_MAX]; @@ -83,8 +86,8 @@ static uint64_t inline_branch_miss[CC_OP_MAX]; static uint64_t pc_to_link_info(DisasContext *s, uint64_t pc) { - if (!(s->tb->flags & FLAG_MASK_64)) { - if (s->tb->flags & FLAG_MASK_32) { + if (!(s->base.tb->flags & FLAG_MASK_64)) { + if (s->base.tb->flags & FLAG_MASK_32) { return pc | 0x80000000; } } @@ -190,16 +193,16 @@ static void return_low128(TCGv_i64 dest) static void update_psw_addr(DisasContext *s) { /* psw.addr */ - tcg_gen_movi_i64(psw_addr, s->pc); + tcg_gen_movi_i64(psw_addr, s->base.pc_next); } static void per_branch(DisasContext *s, bool to_next) { #ifndef CONFIG_USER_ONLY - tcg_gen_movi_i64(gbea, s->pc); + tcg_gen_movi_i64(gbea, s->base.pc_next); - if (s->tb->flags & FLAG_MASK_PER) { - TCGv_i64 next_pc = to_next ? tcg_const_i64(s->next_pc) : psw_addr; + if (s->base.tb->flags & FLAG_MASK_PER) { + TCGv_i64 next_pc = to_next ? tcg_const_i64(s->pc_tmp) : psw_addr; gen_helper_per_branch(cpu_env, gbea, next_pc); if (to_next) { tcg_temp_free_i64(next_pc); @@ -212,16 +215,16 @@ static void per_branch_cond(DisasContext *s, TCGCond cond, TCGv_i64 arg1, TCGv_i64 arg2) { #ifndef CONFIG_USER_ONLY - if (s->tb->flags & FLAG_MASK_PER) { + if (s->base.tb->flags & FLAG_MASK_PER) { TCGLabel *lab = gen_new_label(); tcg_gen_brcond_i64(tcg_invert_cond(cond), arg1, arg2, lab); - tcg_gen_movi_i64(gbea, s->pc); + tcg_gen_movi_i64(gbea, s->base.pc_next); gen_helper_per_branch(cpu_env, gbea, psw_addr); gen_set_label(lab); } else { - TCGv_i64 pc = tcg_const_i64(s->pc); + TCGv_i64 pc = tcg_const_i64(s->base.pc_next); tcg_gen_movcond_i64(cond, gbea, arg1, arg2, gbea, pc); tcg_temp_free_i64(pc); } @@ -230,7 +233,7 @@ static void per_branch_cond(DisasContext *s, TCGCond cond, static void per_breaking_event(DisasContext *s) { - tcg_gen_movi_i64(gbea, s->pc); + tcg_gen_movi_i64(gbea, s->base.pc_next); } static void update_cc_op(DisasContext *s) @@ -252,11 +255,11 @@ static inline uint64_t ld_code4(CPUS390XState *env, uint64_t pc) static int get_mem_index(DisasContext *s) { - if (!(s->tb->flags & FLAG_MASK_DAT)) { + if (!(s->base.tb->flags & FLAG_MASK_DAT)) { return MMU_REAL_IDX; } - switch (s->tb->flags & FLAG_MASK_ASC) { + switch (s->base.tb->flags & FLAG_MASK_ASC) { case PSW_ASC_PRIMARY >> FLAG_MASK_PSW_SHIFT: return MMU_PRIMARY_IDX; case PSW_ASC_SECONDARY >> FLAG_MASK_PSW_SHIFT: @@ -321,7 +324,7 @@ static inline void gen_trap(DisasContext *s) #ifndef CONFIG_USER_ONLY static void check_privileged(DisasContext *s) { - if (s->tb->flags & FLAG_MASK_PSTATE) { + if (s->base.tb->flags & FLAG_MASK_PSTATE) { gen_program_exception(s, PGM_PRIVILEGED); } } @@ -330,7 +333,7 @@ static void check_privileged(DisasContext *s) static TCGv_i64 get_address(DisasContext *s, int x2, int b2, int d2) { TCGv_i64 tmp = tcg_temp_new_i64(); - bool need_31 = !(s->tb->flags & FLAG_MASK_64); + bool need_31 = !(s->base.tb->flags & FLAG_MASK_64); /* Note that d2 is limited to 20 bits, signed. If we crop negative displacements early we create larger immedate addends. */ @@ -543,9 +546,9 @@ static void gen_op_calc_cc(DisasContext *s) static bool use_exit_tb(DisasContext *s) { - return (s->singlestep_enabled || - (tb_cflags(s->tb) & CF_LAST_IO) || - (s->tb->flags & FLAG_MASK_PER)); + return s->base.singlestep_enabled || + (tb_cflags(s->base.tb) & CF_LAST_IO) || + (s->base.tb->flags & FLAG_MASK_PER); } static bool use_goto_tb(DisasContext *s, uint64_t dest) @@ -554,8 +557,8 @@ static bool use_goto_tb(DisasContext *s, uint64_t dest) return false; } #ifndef CONFIG_USER_ONLY - return (dest & TARGET_PAGE_MASK) == (s->tb->pc & TARGET_PAGE_MASK) || - (dest & TARGET_PAGE_MASK) == (s->pc & TARGET_PAGE_MASK); + return (dest & TARGET_PAGE_MASK) == (s->base.tb->pc & TARGET_PAGE_MASK) || + (dest & TARGET_PAGE_MASK) == (s->base.pc_next & TARGET_PAGE_MASK); #else return true; #endif @@ -1091,26 +1094,24 @@ typedef struct { #define SPEC_r2_f128 16 /* Return values from translate_one, indicating the state of the TB. */ -typedef enum { - /* Continue the TB. */ - NO_EXIT, - /* We have emitted one or more goto_tb. No fixup required. */ - EXIT_GOTO_TB, - /* We are not using a goto_tb (for whatever reason), but have updated - the PC (for whatever reason), so there's no need to do it again on - exiting the TB. */ - EXIT_PC_UPDATED, - /* We have updated the PC and CC values. */ - EXIT_PC_CC_UPDATED, - /* We are exiting the TB, but have neither emitted a goto_tb, nor - updated the PC for the next instruction to be executed. */ - EXIT_PC_STALE, - /* We are exiting the TB to the main loop. */ - EXIT_PC_STALE_NOCHAIN, - /* We are ending the TB with a noreturn function call, e.g. longjmp. - No following code will be executed. */ - EXIT_NORETURN, -} ExitStatus; + +/* We are not using a goto_tb (for whatever reason), but have updated + the PC (for whatever reason), so there's no need to do it again on + exiting the TB. */ +#define DISAS_PC_UPDATED DISAS_TARGET_0 + +/* We have emitted one or more goto_tb. No fixup required. */ +#define DISAS_GOTO_TB DISAS_TARGET_1 + +/* We have updated the PC and CC values. */ +#define DISAS_PC_CC_UPDATED DISAS_TARGET_2 + +/* We are exiting the TB, but have neither emitted a goto_tb, nor + updated the PC for the next instruction to be executed. */ +#define DISAS_PC_STALE DISAS_TARGET_3 + +/* We are exiting the TB to the main loop. */ +#define DISAS_PC_STALE_NOCHAIN DISAS_TARGET_4 struct DisasInsn { unsigned opc:16; @@ -1125,7 +1126,7 @@ struct DisasInsn { void (*help_prep)(DisasContext *, DisasFields *, DisasOps *); void (*help_wout)(DisasContext *, DisasFields *, DisasOps *); void (*help_cout)(DisasContext *, DisasOps *); - ExitStatus (*help_op)(DisasContext *, DisasOps *); + DisasJumpType (*help_op)(DisasContext *, DisasOps *); uint64_t data; }; @@ -1147,43 +1148,43 @@ static void help_l2_shift(DisasContext *s, DisasFields *f, } } -static ExitStatus help_goto_direct(DisasContext *s, uint64_t dest) +static DisasJumpType help_goto_direct(DisasContext *s, uint64_t dest) { - if (dest == s->next_pc) { + if (dest == s->pc_tmp) { per_branch(s, true); - return NO_EXIT; + return DISAS_NEXT; } if (use_goto_tb(s, dest)) { update_cc_op(s); per_breaking_event(s); tcg_gen_goto_tb(0); tcg_gen_movi_i64(psw_addr, dest); - tcg_gen_exit_tb((uintptr_t)s->tb); - return EXIT_GOTO_TB; + tcg_gen_exit_tb((uintptr_t)s->base.tb); + return DISAS_GOTO_TB; } else { tcg_gen_movi_i64(psw_addr, dest); per_branch(s, false); - return EXIT_PC_UPDATED; + return DISAS_PC_UPDATED; } } -static ExitStatus help_branch(DisasContext *s, DisasCompare *c, - bool is_imm, int imm, TCGv_i64 cdest) +static DisasJumpType help_branch(DisasContext *s, DisasCompare *c, + bool is_imm, int imm, TCGv_i64 cdest) { - ExitStatus ret; - uint64_t dest = s->pc + 2 * imm; + DisasJumpType ret; + uint64_t dest = s->base.pc_next + 2 * imm; TCGLabel *lab; /* Take care of the special cases first. */ if (c->cond == TCG_COND_NEVER) { - ret = NO_EXIT; + ret = DISAS_NEXT; goto egress; } if (is_imm) { - if (dest == s->next_pc) { + if (dest == s->pc_tmp) { /* Branch to next. */ per_branch(s, true); - ret = NO_EXIT; + ret = DISAS_NEXT; goto egress; } if (c->cond == TCG_COND_ALWAYS) { @@ -1193,18 +1194,18 @@ static ExitStatus help_branch(DisasContext *s, DisasCompare *c, } else { if (!cdest) { /* E.g. bcr %r0 -> no branch. */ - ret = NO_EXIT; + ret = DISAS_NEXT; goto egress; } if (c->cond == TCG_COND_ALWAYS) { tcg_gen_mov_i64(psw_addr, cdest); per_branch(s, false); - ret = EXIT_PC_UPDATED; + ret = DISAS_PC_UPDATED; goto egress; } } - if (use_goto_tb(s, s->next_pc)) { + if (use_goto_tb(s, s->pc_tmp)) { if (is_imm && use_goto_tb(s, dest)) { /* Both exits can use goto_tb. */ update_cc_op(s); @@ -1218,17 +1219,17 @@ static ExitStatus help_branch(DisasContext *s, DisasCompare *c, /* Branch not taken. */ tcg_gen_goto_tb(0); - tcg_gen_movi_i64(psw_addr, s->next_pc); - tcg_gen_exit_tb((uintptr_t)s->tb + 0); + tcg_gen_movi_i64(psw_addr, s->pc_tmp); + tcg_gen_exit_tb((uintptr_t)s->base.tb + 0); /* Branch taken. */ gen_set_label(lab); per_breaking_event(s); tcg_gen_goto_tb(1); tcg_gen_movi_i64(psw_addr, dest); - tcg_gen_exit_tb((uintptr_t)s->tb + 1); + tcg_gen_exit_tb((uintptr_t)s->base.tb + 1); - ret = EXIT_GOTO_TB; + ret = DISAS_GOTO_TB; } else { /* Fallthru can use goto_tb, but taken branch cannot. */ /* Store taken branch destination before the brcond. This @@ -1248,22 +1249,22 @@ static ExitStatus help_branch(DisasContext *s, DisasCompare *c, /* Branch not taken. */ update_cc_op(s); tcg_gen_goto_tb(0); - tcg_gen_movi_i64(psw_addr, s->next_pc); - tcg_gen_exit_tb((uintptr_t)s->tb + 0); + tcg_gen_movi_i64(psw_addr, s->pc_tmp); + tcg_gen_exit_tb((uintptr_t)s->base.tb + 0); gen_set_label(lab); if (is_imm) { tcg_gen_movi_i64(psw_addr, dest); } per_breaking_event(s); - ret = EXIT_PC_UPDATED; + ret = DISAS_PC_UPDATED; } } else { /* Fallthru cannot use goto_tb. This by itself is vanishingly rare. Most commonly we're single-stepping or some other condition that disables all use of goto_tb. Just update the PC and exit. */ - TCGv_i64 next = tcg_const_i64(s->next_pc); + TCGv_i64 next = tcg_const_i64(s->pc_tmp); if (is_imm) { cdest = tcg_const_i64(dest); } @@ -1290,7 +1291,7 @@ static ExitStatus help_branch(DisasContext *s, DisasCompare *c, } tcg_temp_free_i64(next); - ret = EXIT_PC_UPDATED; + ret = DISAS_PC_UPDATED; } egress: @@ -1302,7 +1303,7 @@ static ExitStatus help_branch(DisasContext *s, DisasCompare *c, /* The operations. These perform the bulk of the work for any insn, usually after the operands have been loaded and output initialized. */ -static ExitStatus op_abs(DisasContext *s, DisasOps *o) +static DisasJumpType op_abs(DisasContext *s, DisasOps *o) { TCGv_i64 z, n; z = tcg_const_i64(0); @@ -1311,35 +1312,35 @@ static ExitStatus op_abs(DisasContext *s, DisasOps *o) tcg_gen_movcond_i64(TCG_COND_LT, o->out, o->in2, z, n, o->in2); tcg_temp_free_i64(n); tcg_temp_free_i64(z); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_absf32(DisasContext *s, DisasOps *o) +static DisasJumpType op_absf32(DisasContext *s, DisasOps *o) { tcg_gen_andi_i64(o->out, o->in2, 0x7fffffffull); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_absf64(DisasContext *s, DisasOps *o) +static DisasJumpType op_absf64(DisasContext *s, DisasOps *o) { tcg_gen_andi_i64(o->out, o->in2, 0x7fffffffffffffffull); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_absf128(DisasContext *s, DisasOps *o) +static DisasJumpType op_absf128(DisasContext *s, DisasOps *o) { tcg_gen_andi_i64(o->out, o->in1, 0x7fffffffffffffffull); tcg_gen_mov_i64(o->out2, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_add(DisasContext *s, DisasOps *o) +static DisasJumpType op_add(DisasContext *s, DisasOps *o) { tcg_gen_add_i64(o->out, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_addc(DisasContext *s, DisasOps *o) +static DisasJumpType op_addc(DisasContext *s, DisasOps *o) { DisasCompare cmp; TCGv_i64 carry; @@ -1363,10 +1364,10 @@ static ExitStatus op_addc(DisasContext *s, DisasOps *o) tcg_gen_add_i64(o->out, o->out, carry); tcg_temp_free_i64(carry); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_asi(DisasContext *s, DisasOps *o) +static DisasJumpType op_asi(DisasContext *s, DisasOps *o) { o->in1 = tcg_temp_new_i64(); @@ -1384,35 +1385,35 @@ static ExitStatus op_asi(DisasContext *s, DisasOps *o) if (!s390_has_feat(S390_FEAT_STFLE_45)) { tcg_gen_qemu_st_tl(o->out, o->addr1, get_mem_index(s), s->insn->data); } - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_aeb(DisasContext *s, DisasOps *o) +static DisasJumpType op_aeb(DisasContext *s, DisasOps *o) { gen_helper_aeb(o->out, cpu_env, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_adb(DisasContext *s, DisasOps *o) +static DisasJumpType op_adb(DisasContext *s, DisasOps *o) { gen_helper_adb(o->out, cpu_env, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_axb(DisasContext *s, DisasOps *o) +static DisasJumpType op_axb(DisasContext *s, DisasOps *o) { gen_helper_axb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2); return_low128(o->out2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_and(DisasContext *s, DisasOps *o) +static DisasJumpType op_and(DisasContext *s, DisasOps *o) { tcg_gen_and_i64(o->out, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_andi(DisasContext *s, DisasOps *o) +static DisasJumpType op_andi(DisasContext *s, DisasOps *o) { int shift = s->insn->data & 0xff; int size = s->insn->data >> 8; @@ -1426,10 +1427,10 @@ static ExitStatus op_andi(DisasContext *s, DisasOps *o) /* Produce the CC from only the bits manipulated. */ tcg_gen_andi_i64(cc_dst, o->out, mask); set_cc_nz_u64(s, cc_dst); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_ni(DisasContext *s, DisasOps *o) +static DisasJumpType op_ni(DisasContext *s, DisasOps *o) { o->in1 = tcg_temp_new_i64(); @@ -1447,28 +1448,28 @@ static ExitStatus op_ni(DisasContext *s, DisasOps *o) if (!s390_has_feat(S390_FEAT_INTERLOCKED_ACCESS_2)) { tcg_gen_qemu_st_tl(o->out, o->addr1, get_mem_index(s), s->insn->data); } - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_bas(DisasContext *s, DisasOps *o) +static DisasJumpType op_bas(DisasContext *s, DisasOps *o) { - tcg_gen_movi_i64(o->out, pc_to_link_info(s, s->next_pc)); + tcg_gen_movi_i64(o->out, pc_to_link_info(s, s->pc_tmp)); if (o->in2) { tcg_gen_mov_i64(psw_addr, o->in2); per_branch(s, false); - return EXIT_PC_UPDATED; + return DISAS_PC_UPDATED; } else { - return NO_EXIT; + return DISAS_NEXT; } } -static ExitStatus op_basi(DisasContext *s, DisasOps *o) +static DisasJumpType op_basi(DisasContext *s, DisasOps *o) { - tcg_gen_movi_i64(o->out, pc_to_link_info(s, s->next_pc)); - return help_goto_direct(s, s->pc + 2 * get_field(s->fields, i2)); + tcg_gen_movi_i64(o->out, pc_to_link_info(s, s->pc_tmp)); + return help_goto_direct(s, s->base.pc_next + 2 * get_field(s->fields, i2)); } -static ExitStatus op_bc(DisasContext *s, DisasOps *o) +static DisasJumpType op_bc(DisasContext *s, DisasOps *o) { int m1 = get_field(s->fields, m1); bool is_imm = have_field(s->fields, i2); @@ -1487,14 +1488,14 @@ static ExitStatus op_bc(DisasContext *s, DisasOps *o) /* FIXME: perform checkpoint-synchronisation */ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC); } - return NO_EXIT; + return DISAS_NEXT; } disas_jcc(s, &c, m1); return help_branch(s, &c, is_imm, imm, o->in2); } -static ExitStatus op_bct32(DisasContext *s, DisasOps *o) +static DisasJumpType op_bct32(DisasContext *s, DisasOps *o) { int r1 = get_field(s->fields, r1); bool is_imm = have_field(s->fields, i2); @@ -1518,7 +1519,7 @@ static ExitStatus op_bct32(DisasContext *s, DisasOps *o) return help_branch(s, &c, is_imm, imm, o->in2); } -static ExitStatus op_bcth(DisasContext *s, DisasOps *o) +static DisasJumpType op_bcth(DisasContext *s, DisasOps *o) { int r1 = get_field(s->fields, r1); int imm = get_field(s->fields, i2); @@ -1542,7 +1543,7 @@ static ExitStatus op_bcth(DisasContext *s, DisasOps *o) return help_branch(s, &c, 1, imm, o->in2); } -static ExitStatus op_bct64(DisasContext *s, DisasOps *o) +static DisasJumpType op_bct64(DisasContext *s, DisasOps *o) { int r1 = get_field(s->fields, r1); bool is_imm = have_field(s->fields, i2); @@ -1561,7 +1562,7 @@ static ExitStatus op_bct64(DisasContext *s, DisasOps *o) return help_branch(s, &c, is_imm, imm, o->in2); } -static ExitStatus op_bx32(DisasContext *s, DisasOps *o) +static DisasJumpType op_bx32(DisasContext *s, DisasOps *o) { int r1 = get_field(s->fields, r1); int r3 = get_field(s->fields, r3); @@ -1587,7 +1588,7 @@ static ExitStatus op_bx32(DisasContext *s, DisasOps *o) return help_branch(s, &c, is_imm, imm, o->in2); } -static ExitStatus op_bx64(DisasContext *s, DisasOps *o) +static DisasJumpType op_bx64(DisasContext *s, DisasOps *o) { int r1 = get_field(s->fields, r1); int r3 = get_field(s->fields, r3); @@ -1613,7 +1614,7 @@ static ExitStatus op_bx64(DisasContext *s, DisasOps *o) return help_branch(s, &c, is_imm, imm, o->in2); } -static ExitStatus op_cj(DisasContext *s, DisasOps *o) +static DisasJumpType op_cj(DisasContext *s, DisasOps *o) { int imm, m3 = get_field(s->fields, m3); bool is_imm; @@ -1639,186 +1640,186 @@ static ExitStatus op_cj(DisasContext *s, DisasOps *o) return help_branch(s, &c, is_imm, imm, o->out); } -static ExitStatus op_ceb(DisasContext *s, DisasOps *o) +static DisasJumpType op_ceb(DisasContext *s, DisasOps *o) { gen_helper_ceb(cc_op, cpu_env, o->in1, o->in2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_cdb(DisasContext *s, DisasOps *o) +static DisasJumpType op_cdb(DisasContext *s, DisasOps *o) { gen_helper_cdb(cc_op, cpu_env, o->in1, o->in2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_cxb(DisasContext *s, DisasOps *o) +static DisasJumpType op_cxb(DisasContext *s, DisasOps *o) { gen_helper_cxb(cc_op, cpu_env, o->out, o->out2, o->in1, o->in2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_cfeb(DisasContext *s, DisasOps *o) +static DisasJumpType op_cfeb(DisasContext *s, DisasOps *o) { TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3)); gen_helper_cfeb(o->out, cpu_env, o->in2, m3); tcg_temp_free_i32(m3); gen_set_cc_nz_f32(s, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_cfdb(DisasContext *s, DisasOps *o) +static DisasJumpType op_cfdb(DisasContext *s, DisasOps *o) { TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3)); gen_helper_cfdb(o->out, cpu_env, o->in2, m3); tcg_temp_free_i32(m3); gen_set_cc_nz_f64(s, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_cfxb(DisasContext *s, DisasOps *o) +static DisasJumpType op_cfxb(DisasContext *s, DisasOps *o) { TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3)); gen_helper_cfxb(o->out, cpu_env, o->in1, o->in2, m3); tcg_temp_free_i32(m3); gen_set_cc_nz_f128(s, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_cgeb(DisasContext *s, DisasOps *o) +static DisasJumpType op_cgeb(DisasContext *s, DisasOps *o) { TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3)); gen_helper_cgeb(o->out, cpu_env, o->in2, m3); tcg_temp_free_i32(m3); gen_set_cc_nz_f32(s, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_cgdb(DisasContext *s, DisasOps *o) +static DisasJumpType op_cgdb(DisasContext *s, DisasOps *o) { TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3)); gen_helper_cgdb(o->out, cpu_env, o->in2, m3); tcg_temp_free_i32(m3); gen_set_cc_nz_f64(s, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_cgxb(DisasContext *s, DisasOps *o) +static DisasJumpType op_cgxb(DisasContext *s, DisasOps *o) { TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3)); gen_helper_cgxb(o->out, cpu_env, o->in1, o->in2, m3); tcg_temp_free_i32(m3); gen_set_cc_nz_f128(s, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_clfeb(DisasContext *s, DisasOps *o) +static DisasJumpType op_clfeb(DisasContext *s, DisasOps *o) { TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3)); gen_helper_clfeb(o->out, cpu_env, o->in2, m3); tcg_temp_free_i32(m3); gen_set_cc_nz_f32(s, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_clfdb(DisasContext *s, DisasOps *o) +static DisasJumpType op_clfdb(DisasContext *s, DisasOps *o) { TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3)); gen_helper_clfdb(o->out, cpu_env, o->in2, m3); tcg_temp_free_i32(m3); gen_set_cc_nz_f64(s, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_clfxb(DisasContext *s, DisasOps *o) +static DisasJumpType op_clfxb(DisasContext *s, DisasOps *o) { TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3)); gen_helper_clfxb(o->out, cpu_env, o->in1, o->in2, m3); tcg_temp_free_i32(m3); gen_set_cc_nz_f128(s, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_clgeb(DisasContext *s, DisasOps *o) +static DisasJumpType op_clgeb(DisasContext *s, DisasOps *o) { TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3)); gen_helper_clgeb(o->out, cpu_env, o->in2, m3); tcg_temp_free_i32(m3); gen_set_cc_nz_f32(s, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_clgdb(DisasContext *s, DisasOps *o) +static DisasJumpType op_clgdb(DisasContext *s, DisasOps *o) { TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3)); gen_helper_clgdb(o->out, cpu_env, o->in2, m3); tcg_temp_free_i32(m3); gen_set_cc_nz_f64(s, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_clgxb(DisasContext *s, DisasOps *o) +static DisasJumpType op_clgxb(DisasContext *s, DisasOps *o) { TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3)); gen_helper_clgxb(o->out, cpu_env, o->in1, o->in2, m3); tcg_temp_free_i32(m3); gen_set_cc_nz_f128(s, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_cegb(DisasContext *s, DisasOps *o) +static DisasJumpType op_cegb(DisasContext *s, DisasOps *o) { TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3)); gen_helper_cegb(o->out, cpu_env, o->in2, m3); tcg_temp_free_i32(m3); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_cdgb(DisasContext *s, DisasOps *o) +static DisasJumpType op_cdgb(DisasContext *s, DisasOps *o) { TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3)); gen_helper_cdgb(o->out, cpu_env, o->in2, m3); tcg_temp_free_i32(m3); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_cxgb(DisasContext *s, DisasOps *o) +static DisasJumpType op_cxgb(DisasContext *s, DisasOps *o) { TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3)); gen_helper_cxgb(o->out, cpu_env, o->in2, m3); tcg_temp_free_i32(m3); return_low128(o->out2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_celgb(DisasContext *s, DisasOps *o) +static DisasJumpType op_celgb(DisasContext *s, DisasOps *o) { TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3)); gen_helper_celgb(o->out, cpu_env, o->in2, m3); tcg_temp_free_i32(m3); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_cdlgb(DisasContext *s, DisasOps *o) +static DisasJumpType op_cdlgb(DisasContext *s, DisasOps *o) { TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3)); gen_helper_cdlgb(o->out, cpu_env, o->in2, m3); tcg_temp_free_i32(m3); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_cxlgb(DisasContext *s, DisasOps *o) +static DisasJumpType op_cxlgb(DisasContext *s, DisasOps *o) { TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3)); gen_helper_cxlgb(o->out, cpu_env, o->in2, m3); tcg_temp_free_i32(m3); return_low128(o->out2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_cksm(DisasContext *s, DisasOps *o) +static DisasJumpType op_cksm(DisasContext *s, DisasOps *o) { int r2 = get_field(s->fields, r2); TCGv_i64 len = tcg_temp_new_i64(); @@ -1831,10 +1832,10 @@ static ExitStatus op_cksm(DisasContext *s, DisasOps *o) tcg_gen_sub_i64(regs[r2 + 1], regs[r2 + 1], len); tcg_temp_free_i64(len); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_clc(DisasContext *s, DisasOps *o) +static DisasJumpType op_clc(DisasContext *s, DisasOps *o) { int l = get_field(s->fields, l1); TCGv_i32 vl; @@ -1861,13 +1862,13 @@ static ExitStatus op_clc(DisasContext *s, DisasOps *o) gen_helper_clc(cc_op, cpu_env, vl, o->addr1, o->in2); tcg_temp_free_i32(vl); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } gen_op_update2_cc_i64(s, CC_OP_LTUGTU_64, cc_src, cc_dst); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_clcl(DisasContext *s, DisasOps *o) +static DisasJumpType op_clcl(DisasContext *s, DisasOps *o) { int r1 = get_field(s->fields, r1); int r2 = get_field(s->fields, r2); @@ -1876,7 +1877,7 @@ static ExitStatus op_clcl(DisasContext *s, DisasOps *o) /* r1 and r2 must be even. */ if (r1 & 1 || r2 & 1) { gen_program_exception(s, PGM_SPECIFICATION); - return EXIT_NORETURN; + return DISAS_NORETURN; } t1 = tcg_const_i32(r1); @@ -1885,10 +1886,10 @@ static ExitStatus op_clcl(DisasContext *s, DisasOps *o) tcg_temp_free_i32(t1); tcg_temp_free_i32(t2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_clcle(DisasContext *s, DisasOps *o) +static DisasJumpType op_clcle(DisasContext *s, DisasOps *o) { int r1 = get_field(s->fields, r1); int r3 = get_field(s->fields, r3); @@ -1897,7 +1898,7 @@ static ExitStatus op_clcle(DisasContext *s, DisasOps *o) /* r1 and r3 must be even. */ if (r1 & 1 || r3 & 1) { gen_program_exception(s, PGM_SPECIFICATION); - return EXIT_NORETURN; + return DISAS_NORETURN; } t1 = tcg_const_i32(r1); @@ -1906,10 +1907,10 @@ static ExitStatus op_clcle(DisasContext *s, DisasOps *o) tcg_temp_free_i32(t1); tcg_temp_free_i32(t3); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_clclu(DisasContext *s, DisasOps *o) +static DisasJumpType op_clclu(DisasContext *s, DisasOps *o) { int r1 = get_field(s->fields, r1); int r3 = get_field(s->fields, r3); @@ -1918,7 +1919,7 @@ static ExitStatus op_clclu(DisasContext *s, DisasOps *o) /* r1 and r3 must be even. */ if (r1 & 1 || r3 & 1) { gen_program_exception(s, PGM_SPECIFICATION); - return EXIT_NORETURN; + return DISAS_NORETURN; } t1 = tcg_const_i32(r1); @@ -1927,10 +1928,10 @@ static ExitStatus op_clclu(DisasContext *s, DisasOps *o) tcg_temp_free_i32(t1); tcg_temp_free_i32(t3); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_clm(DisasContext *s, DisasOps *o) +static DisasJumpType op_clm(DisasContext *s, DisasOps *o) { TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3)); TCGv_i32 t1 = tcg_temp_new_i32(); @@ -1939,28 +1940,28 @@ static ExitStatus op_clm(DisasContext *s, DisasOps *o) set_cc_static(s); tcg_temp_free_i32(t1); tcg_temp_free_i32(m3); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_clst(DisasContext *s, DisasOps *o) +static DisasJumpType op_clst(DisasContext *s, DisasOps *o) { gen_helper_clst(o->in1, cpu_env, regs[0], o->in1, o->in2); set_cc_static(s); return_low128(o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_cps(DisasContext *s, DisasOps *o) +static DisasJumpType op_cps(DisasContext *s, DisasOps *o) { TCGv_i64 t = tcg_temp_new_i64(); tcg_gen_andi_i64(t, o->in1, 0x8000000000000000ull); tcg_gen_andi_i64(o->out, o->in2, 0x7fffffffffffffffull); tcg_gen_or_i64(o->out, o->out, t); tcg_temp_free_i64(t); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_cs(DisasContext *s, DisasOps *o) +static DisasJumpType op_cs(DisasContext *s, DisasOps *o) { int d2 = get_field(s->fields, d2); int b2 = get_field(s->fields, b2); @@ -1982,10 +1983,10 @@ static ExitStatus op_cs(DisasContext *s, DisasOps *o) tcg_temp_free_i64(cc); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_cdsg(DisasContext *s, DisasOps *o) +static DisasJumpType op_cdsg(DisasContext *s, DisasOps *o) { int r1 = get_field(s->fields, r1); int r3 = get_field(s->fields, r3); @@ -1998,7 +1999,7 @@ static ExitStatus op_cdsg(DisasContext *s, DisasOps *o) addr = get_address(s, 0, b2, d2); t_r1 = tcg_const_i32(r1); t_r3 = tcg_const_i32(r3); - if (tb_cflags(s->tb) & CF_PARALLEL) { + if (tb_cflags(s->base.tb) & CF_PARALLEL) { gen_helper_cdsg_parallel(cpu_env, addr, t_r1, t_r3); } else { gen_helper_cdsg(cpu_env, addr, t_r1, t_r3); @@ -2008,15 +2009,15 @@ static ExitStatus op_cdsg(DisasContext *s, DisasOps *o) tcg_temp_free_i32(t_r3); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_csst(DisasContext *s, DisasOps *o) +static DisasJumpType op_csst(DisasContext *s, DisasOps *o) { int r3 = get_field(s->fields, r3); TCGv_i32 t_r3 = tcg_const_i32(r3); - if (tb_cflags(s->tb) & CF_PARALLEL) { + if (tb_cflags(s->base.tb) & CF_PARALLEL) { gen_helper_csst_parallel(cc_op, cpu_env, t_r3, o->in1, o->in2); } else { gen_helper_csst(cc_op, cpu_env, t_r3, o->in1, o->in2); @@ -2024,11 +2025,11 @@ static ExitStatus op_csst(DisasContext *s, DisasOps *o) tcg_temp_free_i32(t_r3); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } #ifndef CONFIG_USER_ONLY -static ExitStatus op_csp(DisasContext *s, DisasOps *o) +static DisasJumpType op_csp(DisasContext *s, DisasOps *o) { TCGMemOp mop = s->insn->data; TCGv_i64 addr, old, cc; @@ -2069,11 +2070,11 @@ static ExitStatus op_csp(DisasContext *s, DisasOps *o) gen_helper_purge(cpu_env); gen_set_label(lab); - return NO_EXIT; + return DISAS_NEXT; } #endif -static ExitStatus op_cvd(DisasContext *s, DisasOps *o) +static DisasJumpType op_cvd(DisasContext *s, DisasOps *o) { TCGv_i64 t1 = tcg_temp_new_i64(); TCGv_i32 t2 = tcg_temp_new_i32(); @@ -2082,10 +2083,10 @@ static ExitStatus op_cvd(DisasContext *s, DisasOps *o) tcg_temp_free_i32(t2); tcg_gen_qemu_st64(t1, o->in2, get_mem_index(s)); tcg_temp_free_i64(t1); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_ct(DisasContext *s, DisasOps *o) +static DisasJumpType op_ct(DisasContext *s, DisasOps *o) { int m3 = get_field(s->fields, m3); TCGLabel *lab = gen_new_label(); @@ -2101,10 +2102,10 @@ static ExitStatus op_ct(DisasContext *s, DisasOps *o) gen_trap(s); gen_set_label(lab); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_cuXX(DisasContext *s, DisasOps *o) +static DisasJumpType op_cuXX(DisasContext *s, DisasOps *o) { int m3 = get_field(s->fields, m3); int r1 = get_field(s->fields, r1); @@ -2114,7 +2115,7 @@ static ExitStatus op_cuXX(DisasContext *s, DisasOps *o) /* R1 and R2 must both be even. */ if ((r1 | r2) & 1) { gen_program_exception(s, PGM_SPECIFICATION); - return EXIT_NORETURN; + return DISAS_NORETURN; } if (!s390_has_feat(S390_FEAT_ETF3_ENH)) { m3 = 0; @@ -2151,11 +2152,11 @@ static ExitStatus op_cuXX(DisasContext *s, DisasOps *o) tcg_temp_free_i32(tr2); tcg_temp_free_i32(chk); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } #ifndef CONFIG_USER_ONLY -static ExitStatus op_diag(DisasContext *s, DisasOps *o) +static DisasJumpType op_diag(DisasContext *s, DisasOps *o) { TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); @@ -2167,78 +2168,78 @@ static ExitStatus op_diag(DisasContext *s, DisasOps *o) tcg_temp_free_i32(func_code); tcg_temp_free_i32(r3); tcg_temp_free_i32(r1); - return NO_EXIT; + return DISAS_NEXT; } #endif -static ExitStatus op_divs32(DisasContext *s, DisasOps *o) +static DisasJumpType op_divs32(DisasContext *s, DisasOps *o) { gen_helper_divs32(o->out2, cpu_env, o->in1, o->in2); return_low128(o->out); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_divu32(DisasContext *s, DisasOps *o) +static DisasJumpType op_divu32(DisasContext *s, DisasOps *o) { gen_helper_divu32(o->out2, cpu_env, o->in1, o->in2); return_low128(o->out); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_divs64(DisasContext *s, DisasOps *o) +static DisasJumpType op_divs64(DisasContext *s, DisasOps *o) { gen_helper_divs64(o->out2, cpu_env, o->in1, o->in2); return_low128(o->out); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_divu64(DisasContext *s, DisasOps *o) +static DisasJumpType op_divu64(DisasContext *s, DisasOps *o) { gen_helper_divu64(o->out2, cpu_env, o->out, o->out2, o->in2); return_low128(o->out); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_deb(DisasContext *s, DisasOps *o) +static DisasJumpType op_deb(DisasContext *s, DisasOps *o) { gen_helper_deb(o->out, cpu_env, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_ddb(DisasContext *s, DisasOps *o) +static DisasJumpType op_ddb(DisasContext *s, DisasOps *o) { gen_helper_ddb(o->out, cpu_env, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_dxb(DisasContext *s, DisasOps *o) +static DisasJumpType op_dxb(DisasContext *s, DisasOps *o) { gen_helper_dxb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2); return_low128(o->out2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_ear(DisasContext *s, DisasOps *o) +static DisasJumpType op_ear(DisasContext *s, DisasOps *o) { int r2 = get_field(s->fields, r2); tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, aregs[r2])); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_ecag(DisasContext *s, DisasOps *o) +static DisasJumpType op_ecag(DisasContext *s, DisasOps *o) { /* No cache information provided. */ tcg_gen_movi_i64(o->out, -1); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_efpc(DisasContext *s, DisasOps *o) +static DisasJumpType op_efpc(DisasContext *s, DisasOps *o) { tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, fpc)); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_epsw(DisasContext *s, DisasOps *o) +static DisasJumpType op_epsw(DisasContext *s, DisasOps *o) { int r1 = get_field(s->fields, r1); int r2 = get_field(s->fields, r2); @@ -2253,10 +2254,10 @@ static ExitStatus op_epsw(DisasContext *s, DisasOps *o) } tcg_temp_free_i64(t); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_ex(DisasContext *s, DisasOps *o) +static DisasJumpType op_ex(DisasContext *s, DisasOps *o) { int r1 = get_field(s->fields, r1); TCGv_i32 ilen; @@ -2265,7 +2266,7 @@ static ExitStatus op_ex(DisasContext *s, DisasOps *o) /* Nested EXECUTE is not allowed. */ if (unlikely(s->ex_value)) { gen_program_exception(s, PGM_EXECUTE); - return EXIT_NORETURN; + return DISAS_NORETURN; } update_psw_addr(s); @@ -2285,35 +2286,35 @@ static ExitStatus op_ex(DisasContext *s, DisasOps *o) tcg_temp_free_i64(v1); } - return EXIT_PC_CC_UPDATED; + return DISAS_PC_CC_UPDATED; } -static ExitStatus op_fieb(DisasContext *s, DisasOps *o) +static DisasJumpType op_fieb(DisasContext *s, DisasOps *o) { TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3)); gen_helper_fieb(o->out, cpu_env, o->in2, m3); tcg_temp_free_i32(m3); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_fidb(DisasContext *s, DisasOps *o) +static DisasJumpType op_fidb(DisasContext *s, DisasOps *o) { TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3)); gen_helper_fidb(o->out, cpu_env, o->in2, m3); tcg_temp_free_i32(m3); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_fixb(DisasContext *s, DisasOps *o) +static DisasJumpType op_fixb(DisasContext *s, DisasOps *o) { TCGv_i32 m3 = tcg_const_i32(get_field(s->fields, m3)); gen_helper_fixb(o->out, cpu_env, o->in1, o->in2, m3); return_low128(o->out2); tcg_temp_free_i32(m3); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_flogr(DisasContext *s, DisasOps *o) +static DisasJumpType op_flogr(DisasContext *s, DisasOps *o) { /* We'll use the original input for cc computation, since we get to compare that against 0, which ought to be better than comparing @@ -2330,10 +2331,10 @@ static ExitStatus op_flogr(DisasContext *s, DisasOps *o) tcg_gen_movi_i64(o->out2, 0x8000000000000000ull); tcg_gen_shr_i64(o->out2, o->out2, o->out); tcg_gen_andc_i64(o->out2, cc_dst, o->out2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_icm(DisasContext *s, DisasOps *o) +static DisasJumpType op_icm(DisasContext *s, DisasOps *o) { int m3 = get_field(s->fields, m3); int pos, len, base = s->insn->data; @@ -2390,18 +2391,18 @@ static ExitStatus op_icm(DisasContext *s, DisasOps *o) tcg_gen_movi_i64(tmp, ccm); gen_op_update2_cc_i64(s, CC_OP_ICM, tmp, o->out); tcg_temp_free_i64(tmp); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_insi(DisasContext *s, DisasOps *o) +static DisasJumpType op_insi(DisasContext *s, DisasOps *o) { int shift = s->insn->data & 0xff; int size = s->insn->data >> 8; tcg_gen_deposit_i64(o->out, o->in1, o->in2, shift, size); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_ipm(DisasContext *s, DisasOps *o) +static DisasJumpType op_ipm(DisasContext *s, DisasOps *o) { TCGv_i64 t1; @@ -2417,11 +2418,11 @@ static ExitStatus op_ipm(DisasContext *s, DisasOps *o) tcg_gen_shli_i64(t1, t1, 28); tcg_gen_or_i64(o->out, o->out, t1); tcg_temp_free_i64(t1); - return NO_EXIT; + return DISAS_NEXT; } #ifndef CONFIG_USER_ONLY -static ExitStatus op_idte(DisasContext *s, DisasOps *o) +static DisasJumpType op_idte(DisasContext *s, DisasOps *o) { TCGv_i32 m4; @@ -2433,10 +2434,10 @@ static ExitStatus op_idte(DisasContext *s, DisasOps *o) } gen_helper_idte(cpu_env, o->in1, o->in2, m4); tcg_temp_free_i32(m4); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_ipte(DisasContext *s, DisasOps *o) +static DisasJumpType op_ipte(DisasContext *s, DisasOps *o) { TCGv_i32 m4; @@ -2448,18 +2449,18 @@ static ExitStatus op_ipte(DisasContext *s, DisasOps *o) } gen_helper_ipte(cpu_env, o->in1, o->in2, m4); tcg_temp_free_i32(m4); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_iske(DisasContext *s, DisasOps *o) +static DisasJumpType op_iske(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_iske(o->out, cpu_env, o->in2); - return NO_EXIT; + return DISAS_NEXT; } #endif -static ExitStatus op_msa(DisasContext *s, DisasOps *o) +static DisasJumpType op_msa(DisasContext *s, DisasOps *o) { int r1 = have_field(s->fields, r1) ? get_field(s->fields, r1) : 0; int r2 = have_field(s->fields, r2) ? get_field(s->fields, r2) : 0; @@ -2470,7 +2471,7 @@ static ExitStatus op_msa(DisasContext *s, DisasOps *o) case S390_FEAT_TYPE_KMCTR: if (r3 & 1 || !r3) { gen_program_exception(s, PGM_SPECIFICATION); - return EXIT_NORETURN; + return DISAS_NORETURN; } /* FALL THROUGH */ case S390_FEAT_TYPE_PPNO: @@ -2480,7 +2481,7 @@ static ExitStatus op_msa(DisasContext *s, DisasOps *o) case S390_FEAT_TYPE_KM: if (r1 & 1 || !r1) { gen_program_exception(s, PGM_SPECIFICATION); - return EXIT_NORETURN; + return DISAS_NORETURN; } /* FALL THROUGH */ case S390_FEAT_TYPE_KMAC: @@ -2488,7 +2489,7 @@ static ExitStatus op_msa(DisasContext *s, DisasOps *o) case S390_FEAT_TYPE_KLMD: if (r2 & 1 || !r2) { gen_program_exception(s, PGM_SPECIFICATION); - return EXIT_NORETURN; + return DISAS_NORETURN; } /* FALL THROUGH */ case S390_FEAT_TYPE_PCKMO: @@ -2508,31 +2509,31 @@ static ExitStatus op_msa(DisasContext *s, DisasOps *o) tcg_temp_free_i32(t_r2); tcg_temp_free_i32(t_r3); tcg_temp_free_i32(type); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_keb(DisasContext *s, DisasOps *o) +static DisasJumpType op_keb(DisasContext *s, DisasOps *o) { gen_helper_keb(cc_op, cpu_env, o->in1, o->in2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_kdb(DisasContext *s, DisasOps *o) +static DisasJumpType op_kdb(DisasContext *s, DisasOps *o) { gen_helper_kdb(cc_op, cpu_env, o->in1, o->in2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_kxb(DisasContext *s, DisasOps *o) +static DisasJumpType op_kxb(DisasContext *s, DisasOps *o) { gen_helper_kxb(cc_op, cpu_env, o->out, o->out2, o->in1, o->in2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_laa(DisasContext *s, DisasOps *o) +static DisasJumpType op_laa(DisasContext *s, DisasOps *o) { /* The real output is indeed the original value in memory; recompute the addition for the computation of CC. */ @@ -2540,10 +2541,10 @@ static ExitStatus op_laa(DisasContext *s, DisasOps *o) s->insn->data | MO_ALIGN); /* However, we need to recompute the addition for setting CC. */ tcg_gen_add_i64(o->out, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_lan(DisasContext *s, DisasOps *o) +static DisasJumpType op_lan(DisasContext *s, DisasOps *o) { /* The real output is indeed the original value in memory; recompute the addition for the computation of CC. */ @@ -2551,10 +2552,10 @@ static ExitStatus op_lan(DisasContext *s, DisasOps *o) s->insn->data | MO_ALIGN); /* However, we need to recompute the operation for setting CC. */ tcg_gen_and_i64(o->out, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_lao(DisasContext *s, DisasOps *o) +static DisasJumpType op_lao(DisasContext *s, DisasOps *o) { /* The real output is indeed the original value in memory; recompute the addition for the computation of CC. */ @@ -2562,10 +2563,10 @@ static ExitStatus op_lao(DisasContext *s, DisasOps *o) s->insn->data | MO_ALIGN); /* However, we need to recompute the operation for setting CC. */ tcg_gen_or_i64(o->out, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_lax(DisasContext *s, DisasOps *o) +static DisasJumpType op_lax(DisasContext *s, DisasOps *o) { /* The real output is indeed the original value in memory; recompute the addition for the computation of CC. */ @@ -2573,96 +2574,96 @@ static ExitStatus op_lax(DisasContext *s, DisasOps *o) s->insn->data | MO_ALIGN); /* However, we need to recompute the operation for setting CC. */ tcg_gen_xor_i64(o->out, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_ldeb(DisasContext *s, DisasOps *o) +static DisasJumpType op_ldeb(DisasContext *s, DisasOps *o) { gen_helper_ldeb(o->out, cpu_env, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_ledb(DisasContext *s, DisasOps *o) +static DisasJumpType op_ledb(DisasContext *s, DisasOps *o) { gen_helper_ledb(o->out, cpu_env, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_ldxb(DisasContext *s, DisasOps *o) +static DisasJumpType op_ldxb(DisasContext *s, DisasOps *o) { gen_helper_ldxb(o->out, cpu_env, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_lexb(DisasContext *s, DisasOps *o) +static DisasJumpType op_lexb(DisasContext *s, DisasOps *o) { gen_helper_lexb(o->out, cpu_env, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_lxdb(DisasContext *s, DisasOps *o) +static DisasJumpType op_lxdb(DisasContext *s, DisasOps *o) { gen_helper_lxdb(o->out, cpu_env, o->in2); return_low128(o->out2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_lxeb(DisasContext *s, DisasOps *o) +static DisasJumpType op_lxeb(DisasContext *s, DisasOps *o) { gen_helper_lxeb(o->out, cpu_env, o->in2); return_low128(o->out2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_llgt(DisasContext *s, DisasOps *o) +static DisasJumpType op_llgt(DisasContext *s, DisasOps *o) { tcg_gen_andi_i64(o->out, o->in2, 0x7fffffff); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_ld8s(DisasContext *s, DisasOps *o) +static DisasJumpType op_ld8s(DisasContext *s, DisasOps *o) { tcg_gen_qemu_ld8s(o->out, o->in2, get_mem_index(s)); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_ld8u(DisasContext *s, DisasOps *o) +static DisasJumpType op_ld8u(DisasContext *s, DisasOps *o) { tcg_gen_qemu_ld8u(o->out, o->in2, get_mem_index(s)); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_ld16s(DisasContext *s, DisasOps *o) +static DisasJumpType op_ld16s(DisasContext *s, DisasOps *o) { tcg_gen_qemu_ld16s(o->out, o->in2, get_mem_index(s)); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_ld16u(DisasContext *s, DisasOps *o) +static DisasJumpType op_ld16u(DisasContext *s, DisasOps *o) { tcg_gen_qemu_ld16u(o->out, o->in2, get_mem_index(s)); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_ld32s(DisasContext *s, DisasOps *o) +static DisasJumpType op_ld32s(DisasContext *s, DisasOps *o) { tcg_gen_qemu_ld32s(o->out, o->in2, get_mem_index(s)); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_ld32u(DisasContext *s, DisasOps *o) +static DisasJumpType op_ld32u(DisasContext *s, DisasOps *o) { tcg_gen_qemu_ld32u(o->out, o->in2, get_mem_index(s)); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_ld64(DisasContext *s, DisasOps *o) +static DisasJumpType op_ld64(DisasContext *s, DisasOps *o) { tcg_gen_qemu_ld64(o->out, o->in2, get_mem_index(s)); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_lat(DisasContext *s, DisasOps *o) +static DisasJumpType op_lat(DisasContext *s, DisasOps *o) { TCGLabel *lab = gen_new_label(); store_reg32_i64(get_field(s->fields, r1), o->in2); @@ -2670,10 +2671,10 @@ static ExitStatus op_lat(DisasContext *s, DisasOps *o) tcg_gen_brcondi_i64(TCG_COND_NE, o->in2, 0, lab); gen_trap(s); gen_set_label(lab); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_lgat(DisasContext *s, DisasOps *o) +static DisasJumpType op_lgat(DisasContext *s, DisasOps *o) { TCGLabel *lab = gen_new_label(); tcg_gen_qemu_ld64(o->out, o->in2, get_mem_index(s)); @@ -2681,10 +2682,10 @@ static ExitStatus op_lgat(DisasContext *s, DisasOps *o) tcg_gen_brcondi_i64(TCG_COND_NE, o->out, 0, lab); gen_trap(s); gen_set_label(lab); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_lfhat(DisasContext *s, DisasOps *o) +static DisasJumpType op_lfhat(DisasContext *s, DisasOps *o) { TCGLabel *lab = gen_new_label(); store_reg32h_i64(get_field(s->fields, r1), o->in2); @@ -2692,10 +2693,10 @@ static ExitStatus op_lfhat(DisasContext *s, DisasOps *o) tcg_gen_brcondi_i64(TCG_COND_NE, o->in2, 0, lab); gen_trap(s); gen_set_label(lab); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_llgfat(DisasContext *s, DisasOps *o) +static DisasJumpType op_llgfat(DisasContext *s, DisasOps *o) { TCGLabel *lab = gen_new_label(); tcg_gen_qemu_ld32u(o->out, o->in2, get_mem_index(s)); @@ -2703,10 +2704,10 @@ static ExitStatus op_llgfat(DisasContext *s, DisasOps *o) tcg_gen_brcondi_i64(TCG_COND_NE, o->out, 0, lab); gen_trap(s); gen_set_label(lab); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_llgtat(DisasContext *s, DisasOps *o) +static DisasJumpType op_llgtat(DisasContext *s, DisasOps *o) { TCGLabel *lab = gen_new_label(); tcg_gen_andi_i64(o->out, o->in2, 0x7fffffff); @@ -2714,10 +2715,10 @@ static ExitStatus op_llgtat(DisasContext *s, DisasOps *o) tcg_gen_brcondi_i64(TCG_COND_NE, o->out, 0, lab); gen_trap(s); gen_set_label(lab); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_loc(DisasContext *s, DisasOps *o) +static DisasJumpType op_loc(DisasContext *s, DisasOps *o) { DisasCompare c; @@ -2744,11 +2745,11 @@ static ExitStatus op_loc(DisasContext *s, DisasOps *o) tcg_temp_free_i64(z); } - return NO_EXIT; + return DISAS_NEXT; } #ifndef CONFIG_USER_ONLY -static ExitStatus op_lctl(DisasContext *s, DisasOps *o) +static DisasJumpType op_lctl(DisasContext *s, DisasOps *o) { TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); @@ -2757,10 +2758,10 @@ static ExitStatus op_lctl(DisasContext *s, DisasOps *o) tcg_temp_free_i32(r1); tcg_temp_free_i32(r3); /* Exit to main loop to reevaluate s390_cpu_exec_interrupt. */ - return EXIT_PC_STALE_NOCHAIN; + return DISAS_PC_STALE_NOCHAIN; } -static ExitStatus op_lctlg(DisasContext *s, DisasOps *o) +static DisasJumpType op_lctlg(DisasContext *s, DisasOps *o) { TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); @@ -2769,26 +2770,26 @@ static ExitStatus op_lctlg(DisasContext *s, DisasOps *o) tcg_temp_free_i32(r1); tcg_temp_free_i32(r3); /* Exit to main loop to reevaluate s390_cpu_exec_interrupt. */ - return EXIT_PC_STALE_NOCHAIN; + return DISAS_PC_STALE_NOCHAIN; } -static ExitStatus op_lra(DisasContext *s, DisasOps *o) +static DisasJumpType op_lra(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_lra(o->out, cpu_env, o->in2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_lpp(DisasContext *s, DisasOps *o) +static DisasJumpType op_lpp(DisasContext *s, DisasOps *o) { check_privileged(s); tcg_gen_st_i64(o->in2, cpu_env, offsetof(CPUS390XState, pp)); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_lpsw(DisasContext *s, DisasOps *o) +static DisasJumpType op_lpsw(DisasContext *s, DisasOps *o) { TCGv_i64 t1, t2; @@ -2805,10 +2806,10 @@ static ExitStatus op_lpsw(DisasContext *s, DisasOps *o) gen_helper_load_psw(cpu_env, t1, t2); tcg_temp_free_i64(t1); tcg_temp_free_i64(t2); - return EXIT_NORETURN; + return DISAS_NORETURN; } -static ExitStatus op_lpswe(DisasContext *s, DisasOps *o) +static DisasJumpType op_lpswe(DisasContext *s, DisasOps *o) { TCGv_i64 t1, t2; @@ -2823,21 +2824,21 @@ static ExitStatus op_lpswe(DisasContext *s, DisasOps *o) gen_helper_load_psw(cpu_env, t1, t2); tcg_temp_free_i64(t1); tcg_temp_free_i64(t2); - return EXIT_NORETURN; + return DISAS_NORETURN; } #endif -static ExitStatus op_lam(DisasContext *s, DisasOps *o) +static DisasJumpType op_lam(DisasContext *s, DisasOps *o) { TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); gen_helper_lam(cpu_env, r1, o->in2, r3); tcg_temp_free_i32(r1); tcg_temp_free_i32(r3); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_lm32(DisasContext *s, DisasOps *o) +static DisasJumpType op_lm32(DisasContext *s, DisasOps *o) { int r1 = get_field(s->fields, r1); int r3 = get_field(s->fields, r3); @@ -2849,7 +2850,7 @@ static ExitStatus op_lm32(DisasContext *s, DisasOps *o) tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s)); store_reg32_i64(r1, t1); tcg_temp_free(t1); - return NO_EXIT; + return DISAS_NEXT; } /* First load the values of the first and last registers to trigger @@ -2865,7 +2866,7 @@ static ExitStatus op_lm32(DisasContext *s, DisasOps *o) if (((r1 + 1) & 15) == r3) { tcg_temp_free(t2); tcg_temp_free(t1); - return NO_EXIT; + return DISAS_NEXT; } /* Then load the remaining registers. Page fault can't occur. */ @@ -2880,10 +2881,10 @@ static ExitStatus op_lm32(DisasContext *s, DisasOps *o) tcg_temp_free(t2); tcg_temp_free(t1); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_lmh(DisasContext *s, DisasOps *o) +static DisasJumpType op_lmh(DisasContext *s, DisasOps *o) { int r1 = get_field(s->fields, r1); int r3 = get_field(s->fields, r3); @@ -2895,7 +2896,7 @@ static ExitStatus op_lmh(DisasContext *s, DisasOps *o) tcg_gen_qemu_ld32u(t1, o->in2, get_mem_index(s)); store_reg32h_i64(r1, t1); tcg_temp_free(t1); - return NO_EXIT; + return DISAS_NEXT; } /* First load the values of the first and last registers to trigger @@ -2911,7 +2912,7 @@ static ExitStatus op_lmh(DisasContext *s, DisasOps *o) if (((r1 + 1) & 15) == r3) { tcg_temp_free(t2); tcg_temp_free(t1); - return NO_EXIT; + return DISAS_NEXT; } /* Then load the remaining registers. Page fault can't occur. */ @@ -2926,10 +2927,10 @@ static ExitStatus op_lmh(DisasContext *s, DisasOps *o) tcg_temp_free(t2); tcg_temp_free(t1); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_lm64(DisasContext *s, DisasOps *o) +static DisasJumpType op_lm64(DisasContext *s, DisasOps *o) { int r1 = get_field(s->fields, r1); int r3 = get_field(s->fields, r3); @@ -2938,7 +2939,7 @@ static ExitStatus op_lm64(DisasContext *s, DisasOps *o) /* Only one register to read. */ if (unlikely(r1 == r3)) { tcg_gen_qemu_ld64(regs[r1], o->in2, get_mem_index(s)); - return NO_EXIT; + return DISAS_NEXT; } /* First load the values of the first and last registers to trigger @@ -2954,7 +2955,7 @@ static ExitStatus op_lm64(DisasContext *s, DisasOps *o) /* Only two registers to read. */ if (((r1 + 1) & 15) == r3) { tcg_temp_free(t1); - return NO_EXIT; + return DISAS_NEXT; } /* Then load the remaining registers. Page fault can't occur. */ @@ -2967,20 +2968,20 @@ static ExitStatus op_lm64(DisasContext *s, DisasOps *o) } tcg_temp_free(t1); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_lpd(DisasContext *s, DisasOps *o) +static DisasJumpType op_lpd(DisasContext *s, DisasOps *o) { TCGv_i64 a1, a2; TCGMemOp mop = s->insn->data; /* In a parallel context, stop the world and single step. */ - if (tb_cflags(s->tb) & CF_PARALLEL) { + if (tb_cflags(s->base.tb) & CF_PARALLEL) { update_psw_addr(s); update_cc_op(s); gen_exception(EXCP_ATOMIC); - return EXIT_NORETURN; + return DISAS_NORETURN; } /* In a serial context, perform the two loads ... */ @@ -2993,52 +2994,52 @@ static ExitStatus op_lpd(DisasContext *s, DisasOps *o) /* ... and indicate that we performed them while interlocked. */ gen_op_movi_cc(s, 0); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_lpq(DisasContext *s, DisasOps *o) +static DisasJumpType op_lpq(DisasContext *s, DisasOps *o) { - if (tb_cflags(s->tb) & CF_PARALLEL) { + if (tb_cflags(s->base.tb) & CF_PARALLEL) { gen_helper_lpq_parallel(o->out, cpu_env, o->in2); } else { gen_helper_lpq(o->out, cpu_env, o->in2); } return_low128(o->out2); - return NO_EXIT; + return DISAS_NEXT; } #ifndef CONFIG_USER_ONLY -static ExitStatus op_lura(DisasContext *s, DisasOps *o) +static DisasJumpType op_lura(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_lura(o->out, cpu_env, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_lurag(DisasContext *s, DisasOps *o) +static DisasJumpType op_lurag(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_lurag(o->out, cpu_env, o->in2); - return NO_EXIT; + return DISAS_NEXT; } #endif -static ExitStatus op_lzrb(DisasContext *s, DisasOps *o) +static DisasJumpType op_lzrb(DisasContext *s, DisasOps *o) { tcg_gen_andi_i64(o->out, o->in2, -256); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_mov2(DisasContext *s, DisasOps *o) +static DisasJumpType op_mov2(DisasContext *s, DisasOps *o) { o->out = o->in2; o->g_out = o->g_in2; o->in2 = NULL; o->g_in2 = false; - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_mov2e(DisasContext *s, DisasOps *o) +static DisasJumpType op_mov2e(DisasContext *s, DisasOps *o) { int b2 = get_field(s->fields, b2); TCGv ar1 = tcg_temp_new_i64(); @@ -3048,7 +3049,7 @@ static ExitStatus op_mov2e(DisasContext *s, DisasOps *o) o->in2 = NULL; o->g_in2 = false; - switch (s->tb->flags & FLAG_MASK_ASC) { + switch (s->base.tb->flags & FLAG_MASK_ASC) { case PSW_ASC_PRIMARY >> FLAG_MASK_PSW_SHIFT: tcg_gen_movi_i64(ar1, 0); break; @@ -3070,10 +3071,10 @@ static ExitStatus op_mov2e(DisasContext *s, DisasOps *o) tcg_gen_st32_i64(ar1, cpu_env, offsetof(CPUS390XState, aregs[1])); tcg_temp_free_i64(ar1); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_movx(DisasContext *s, DisasOps *o) +static DisasJumpType op_movx(DisasContext *s, DisasOps *o) { o->out = o->in1; o->out2 = o->in2; @@ -3082,26 +3083,26 @@ static ExitStatus op_movx(DisasContext *s, DisasOps *o) o->in1 = NULL; o->in2 = NULL; o->g_in1 = o->g_in2 = false; - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_mvc(DisasContext *s, DisasOps *o) +static DisasJumpType op_mvc(DisasContext *s, DisasOps *o) { TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); gen_helper_mvc(cpu_env, l, o->addr1, o->in2); tcg_temp_free_i32(l); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_mvcin(DisasContext *s, DisasOps *o) +static DisasJumpType op_mvcin(DisasContext *s, DisasOps *o) { TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); gen_helper_mvcin(cpu_env, l, o->addr1, o->in2); tcg_temp_free_i32(l); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_mvcl(DisasContext *s, DisasOps *o) +static DisasJumpType op_mvcl(DisasContext *s, DisasOps *o) { int r1 = get_field(s->fields, r1); int r2 = get_field(s->fields, r2); @@ -3110,7 +3111,7 @@ static ExitStatus op_mvcl(DisasContext *s, DisasOps *o) /* r1 and r2 must be even. */ if (r1 & 1 || r2 & 1) { gen_program_exception(s, PGM_SPECIFICATION); - return EXIT_NORETURN; + return DISAS_NORETURN; } t1 = tcg_const_i32(r1); @@ -3119,10 +3120,10 @@ static ExitStatus op_mvcl(DisasContext *s, DisasOps *o) tcg_temp_free_i32(t1); tcg_temp_free_i32(t2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_mvcle(DisasContext *s, DisasOps *o) +static DisasJumpType op_mvcle(DisasContext *s, DisasOps *o) { int r1 = get_field(s->fields, r1); int r3 = get_field(s->fields, r3); @@ -3131,7 +3132,7 @@ static ExitStatus op_mvcle(DisasContext *s, DisasOps *o) /* r1 and r3 must be even. */ if (r1 & 1 || r3 & 1) { gen_program_exception(s, PGM_SPECIFICATION); - return EXIT_NORETURN; + return DISAS_NORETURN; } t1 = tcg_const_i32(r1); @@ -3140,10 +3141,10 @@ static ExitStatus op_mvcle(DisasContext *s, DisasOps *o) tcg_temp_free_i32(t1); tcg_temp_free_i32(t3); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_mvclu(DisasContext *s, DisasOps *o) +static DisasJumpType op_mvclu(DisasContext *s, DisasOps *o) { int r1 = get_field(s->fields, r1); int r3 = get_field(s->fields, r3); @@ -3152,7 +3153,7 @@ static ExitStatus op_mvclu(DisasContext *s, DisasOps *o) /* r1 and r3 must be even. */ if (r1 & 1 || r3 & 1) { gen_program_exception(s, PGM_SPECIFICATION); - return EXIT_NORETURN; + return DISAS_NORETURN; } t1 = tcg_const_i32(r1); @@ -3161,151 +3162,151 @@ static ExitStatus op_mvclu(DisasContext *s, DisasOps *o) tcg_temp_free_i32(t1); tcg_temp_free_i32(t3); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_mvcos(DisasContext *s, DisasOps *o) +static DisasJumpType op_mvcos(DisasContext *s, DisasOps *o) { int r3 = get_field(s->fields, r3); gen_helper_mvcos(cc_op, cpu_env, o->addr1, o->in2, regs[r3]); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } #ifndef CONFIG_USER_ONLY -static ExitStatus op_mvcp(DisasContext *s, DisasOps *o) +static DisasJumpType op_mvcp(DisasContext *s, DisasOps *o) { int r1 = get_field(s->fields, l1); check_privileged(s); gen_helper_mvcp(cc_op, cpu_env, regs[r1], o->addr1, o->in2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_mvcs(DisasContext *s, DisasOps *o) +static DisasJumpType op_mvcs(DisasContext *s, DisasOps *o) { int r1 = get_field(s->fields, l1); check_privileged(s); gen_helper_mvcs(cc_op, cpu_env, regs[r1], o->addr1, o->in2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } #endif -static ExitStatus op_mvn(DisasContext *s, DisasOps *o) +static DisasJumpType op_mvn(DisasContext *s, DisasOps *o) { TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); gen_helper_mvn(cpu_env, l, o->addr1, o->in2); tcg_temp_free_i32(l); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_mvo(DisasContext *s, DisasOps *o) +static DisasJumpType op_mvo(DisasContext *s, DisasOps *o) { TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); gen_helper_mvo(cpu_env, l, o->addr1, o->in2); tcg_temp_free_i32(l); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_mvpg(DisasContext *s, DisasOps *o) +static DisasJumpType op_mvpg(DisasContext *s, DisasOps *o) { gen_helper_mvpg(cc_op, cpu_env, regs[0], o->in1, o->in2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_mvst(DisasContext *s, DisasOps *o) +static DisasJumpType op_mvst(DisasContext *s, DisasOps *o) { gen_helper_mvst(o->in1, cpu_env, regs[0], o->in1, o->in2); set_cc_static(s); return_low128(o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_mvz(DisasContext *s, DisasOps *o) +static DisasJumpType op_mvz(DisasContext *s, DisasOps *o) { TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); gen_helper_mvz(cpu_env, l, o->addr1, o->in2); tcg_temp_free_i32(l); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_mul(DisasContext *s, DisasOps *o) +static DisasJumpType op_mul(DisasContext *s, DisasOps *o) { tcg_gen_mul_i64(o->out, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_mul128(DisasContext *s, DisasOps *o) +static DisasJumpType op_mul128(DisasContext *s, DisasOps *o) { tcg_gen_mulu2_i64(o->out2, o->out, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_meeb(DisasContext *s, DisasOps *o) +static DisasJumpType op_meeb(DisasContext *s, DisasOps *o) { gen_helper_meeb(o->out, cpu_env, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_mdeb(DisasContext *s, DisasOps *o) +static DisasJumpType op_mdeb(DisasContext *s, DisasOps *o) { gen_helper_mdeb(o->out, cpu_env, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_mdb(DisasContext *s, DisasOps *o) +static DisasJumpType op_mdb(DisasContext *s, DisasOps *o) { gen_helper_mdb(o->out, cpu_env, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_mxb(DisasContext *s, DisasOps *o) +static DisasJumpType op_mxb(DisasContext *s, DisasOps *o) { gen_helper_mxb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2); return_low128(o->out2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_mxdb(DisasContext *s, DisasOps *o) +static DisasJumpType op_mxdb(DisasContext *s, DisasOps *o) { gen_helper_mxdb(o->out, cpu_env, o->out, o->out2, o->in2); return_low128(o->out2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_maeb(DisasContext *s, DisasOps *o) +static DisasJumpType op_maeb(DisasContext *s, DisasOps *o) { TCGv_i64 r3 = load_freg32_i64(get_field(s->fields, r3)); gen_helper_maeb(o->out, cpu_env, o->in1, o->in2, r3); tcg_temp_free_i64(r3); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_madb(DisasContext *s, DisasOps *o) +static DisasJumpType op_madb(DisasContext *s, DisasOps *o) { int r3 = get_field(s->fields, r3); gen_helper_madb(o->out, cpu_env, o->in1, o->in2, fregs[r3]); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_mseb(DisasContext *s, DisasOps *o) +static DisasJumpType op_mseb(DisasContext *s, DisasOps *o) { TCGv_i64 r3 = load_freg32_i64(get_field(s->fields, r3)); gen_helper_mseb(o->out, cpu_env, o->in1, o->in2, r3); tcg_temp_free_i64(r3); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_msdb(DisasContext *s, DisasOps *o) +static DisasJumpType op_msdb(DisasContext *s, DisasOps *o) { int r3 = get_field(s->fields, r3); gen_helper_msdb(o->out, cpu_env, o->in1, o->in2, fregs[r3]); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_nabs(DisasContext *s, DisasOps *o) +static DisasJumpType op_nabs(DisasContext *s, DisasOps *o) { TCGv_i64 z, n; z = tcg_const_i64(0); @@ -3314,78 +3315,78 @@ static ExitStatus op_nabs(DisasContext *s, DisasOps *o) tcg_gen_movcond_i64(TCG_COND_GE, o->out, o->in2, z, n, o->in2); tcg_temp_free_i64(n); tcg_temp_free_i64(z); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_nabsf32(DisasContext *s, DisasOps *o) +static DisasJumpType op_nabsf32(DisasContext *s, DisasOps *o) { tcg_gen_ori_i64(o->out, o->in2, 0x80000000ull); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_nabsf64(DisasContext *s, DisasOps *o) +static DisasJumpType op_nabsf64(DisasContext *s, DisasOps *o) { tcg_gen_ori_i64(o->out, o->in2, 0x8000000000000000ull); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_nabsf128(DisasContext *s, DisasOps *o) +static DisasJumpType op_nabsf128(DisasContext *s, DisasOps *o) { tcg_gen_ori_i64(o->out, o->in1, 0x8000000000000000ull); tcg_gen_mov_i64(o->out2, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_nc(DisasContext *s, DisasOps *o) +static DisasJumpType op_nc(DisasContext *s, DisasOps *o) { TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); gen_helper_nc(cc_op, cpu_env, l, o->addr1, o->in2); tcg_temp_free_i32(l); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_neg(DisasContext *s, DisasOps *o) +static DisasJumpType op_neg(DisasContext *s, DisasOps *o) { tcg_gen_neg_i64(o->out, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_negf32(DisasContext *s, DisasOps *o) +static DisasJumpType op_negf32(DisasContext *s, DisasOps *o) { tcg_gen_xori_i64(o->out, o->in2, 0x80000000ull); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_negf64(DisasContext *s, DisasOps *o) +static DisasJumpType op_negf64(DisasContext *s, DisasOps *o) { tcg_gen_xori_i64(o->out, o->in2, 0x8000000000000000ull); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_negf128(DisasContext *s, DisasOps *o) +static DisasJumpType op_negf128(DisasContext *s, DisasOps *o) { tcg_gen_xori_i64(o->out, o->in1, 0x8000000000000000ull); tcg_gen_mov_i64(o->out2, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_oc(DisasContext *s, DisasOps *o) +static DisasJumpType op_oc(DisasContext *s, DisasOps *o) { TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); gen_helper_oc(cc_op, cpu_env, l, o->addr1, o->in2); tcg_temp_free_i32(l); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_or(DisasContext *s, DisasOps *o) +static DisasJumpType op_or(DisasContext *s, DisasOps *o) { tcg_gen_or_i64(o->out, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_ori(DisasContext *s, DisasOps *o) +static DisasJumpType op_ori(DisasContext *s, DisasOps *o) { int shift = s->insn->data & 0xff; int size = s->insn->data >> 8; @@ -3398,10 +3399,10 @@ static ExitStatus op_ori(DisasContext *s, DisasOps *o) /* Produce the CC from only the bits manipulated. */ tcg_gen_andi_i64(cc_dst, o->out, mask); set_cc_nz_u64(s, cc_dst); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_oi(DisasContext *s, DisasOps *o) +static DisasJumpType op_oi(DisasContext *s, DisasOps *o) { o->in1 = tcg_temp_new_i64(); @@ -3419,18 +3420,18 @@ static ExitStatus op_oi(DisasContext *s, DisasOps *o) if (!s390_has_feat(S390_FEAT_INTERLOCKED_ACCESS_2)) { tcg_gen_qemu_st_tl(o->out, o->addr1, get_mem_index(s), s->insn->data); } - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_pack(DisasContext *s, DisasOps *o) +static DisasJumpType op_pack(DisasContext *s, DisasOps *o) { TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); gen_helper_pack(cpu_env, l, o->addr1, o->in2); tcg_temp_free_i32(l); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_pka(DisasContext *s, DisasOps *o) +static DisasJumpType op_pka(DisasContext *s, DisasOps *o) { int l2 = get_field(s->fields, l2) + 1; TCGv_i32 l; @@ -3438,15 +3439,15 @@ static ExitStatus op_pka(DisasContext *s, DisasOps *o) /* The length must not exceed 32 bytes. */ if (l2 > 32) { gen_program_exception(s, PGM_SPECIFICATION); - return EXIT_NORETURN; + return DISAS_NORETURN; } l = tcg_const_i32(l2); gen_helper_pka(cpu_env, o->addr1, o->in2, l); tcg_temp_free_i32(l); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_pku(DisasContext *s, DisasOps *o) +static DisasJumpType op_pku(DisasContext *s, DisasOps *o) { int l2 = get_field(s->fields, l2) + 1; TCGv_i32 l; @@ -3454,30 +3455,30 @@ static ExitStatus op_pku(DisasContext *s, DisasOps *o) /* The length must be even and should not exceed 64 bytes. */ if ((l2 & 1) || (l2 > 64)) { gen_program_exception(s, PGM_SPECIFICATION); - return EXIT_NORETURN; + return DISAS_NORETURN; } l = tcg_const_i32(l2); gen_helper_pku(cpu_env, o->addr1, o->in2, l); tcg_temp_free_i32(l); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_popcnt(DisasContext *s, DisasOps *o) +static DisasJumpType op_popcnt(DisasContext *s, DisasOps *o) { gen_helper_popcnt(o->out, o->in2); - return NO_EXIT; + return DISAS_NEXT; } #ifndef CONFIG_USER_ONLY -static ExitStatus op_ptlb(DisasContext *s, DisasOps *o) +static DisasJumpType op_ptlb(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_ptlb(cpu_env); - return NO_EXIT; + return DISAS_NEXT; } #endif -static ExitStatus op_risbg(DisasContext *s, DisasOps *o) +static DisasJumpType op_risbg(DisasContext *s, DisasOps *o) { int i3 = get_field(s->fields, i3); int i4 = get_field(s->fields, i4); @@ -3535,7 +3536,7 @@ static ExitStatus op_risbg(DisasContext *s, DisasOps *o) /* In some cases we can implement this with extract. */ if (imask == 0 && pos == 0 && len > 0 && len <= rot) { tcg_gen_extract_i64(o->out, o->in2, 64 - rot, len); - return NO_EXIT; + return DISAS_NEXT; } /* In some cases we can implement this with deposit. */ @@ -3564,10 +3565,10 @@ static ExitStatus op_risbg(DisasContext *s, DisasOps *o) tcg_gen_andi_i64(o->out, o->out, imask); tcg_gen_or_i64(o->out, o->out, o->in2); } - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_rosbg(DisasContext *s, DisasOps *o) +static DisasJumpType op_rosbg(DisasContext *s, DisasOps *o) { int i3 = get_field(s->fields, i3); int i4 = get_field(s->fields, i4); @@ -3617,28 +3618,28 @@ static ExitStatus op_rosbg(DisasContext *s, DisasOps *o) /* Set the CC. */ tcg_gen_andi_i64(cc_dst, o->out, mask); set_cc_nz_u64(s, cc_dst); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_rev16(DisasContext *s, DisasOps *o) +static DisasJumpType op_rev16(DisasContext *s, DisasOps *o) { tcg_gen_bswap16_i64(o->out, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_rev32(DisasContext *s, DisasOps *o) +static DisasJumpType op_rev32(DisasContext *s, DisasOps *o) { tcg_gen_bswap32_i64(o->out, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_rev64(DisasContext *s, DisasOps *o) +static DisasJumpType op_rev64(DisasContext *s, DisasOps *o) { tcg_gen_bswap64_i64(o->out, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_rll32(DisasContext *s, DisasOps *o) +static DisasJumpType op_rll32(DisasContext *s, DisasOps *o) { TCGv_i32 t1 = tcg_temp_new_i32(); TCGv_i32 t2 = tcg_temp_new_i32(); @@ -3650,34 +3651,34 @@ static ExitStatus op_rll32(DisasContext *s, DisasOps *o) tcg_temp_free_i32(t1); tcg_temp_free_i32(t2); tcg_temp_free_i32(to); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_rll64(DisasContext *s, DisasOps *o) +static DisasJumpType op_rll64(DisasContext *s, DisasOps *o) { tcg_gen_rotl_i64(o->out, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } #ifndef CONFIG_USER_ONLY -static ExitStatus op_rrbe(DisasContext *s, DisasOps *o) +static DisasJumpType op_rrbe(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_rrbe(cc_op, cpu_env, o->in2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_sacf(DisasContext *s, DisasOps *o) +static DisasJumpType op_sacf(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_sacf(cpu_env, o->in2); /* Addressing mode has changed, so end the block. */ - return EXIT_PC_STALE; + return DISAS_PC_STALE; } #endif -static ExitStatus op_sam(DisasContext *s, DisasOps *o) +static DisasJumpType op_sam(DisasContext *s, DisasOps *o) { int sam = s->insn->data; TCGv_i64 tsam; @@ -3698,75 +3699,75 @@ static ExitStatus op_sam(DisasContext *s, DisasOps *o) /* Bizarre but true, we check the address of the current insn for the specification exception, not the next to be executed. Thus the PoO documents that Bad Things Happen two bytes before the end. */ - if (s->pc & ~mask) { + if (s->base.pc_next & ~mask) { gen_program_exception(s, PGM_SPECIFICATION); - return EXIT_NORETURN; + return DISAS_NORETURN; } - s->next_pc &= mask; + s->pc_tmp &= mask; tsam = tcg_const_i64(sam); tcg_gen_deposit_i64(psw_mask, psw_mask, tsam, 31, 2); tcg_temp_free_i64(tsam); /* Always exit the TB, since we (may have) changed execution mode. */ - return EXIT_PC_STALE; + return DISAS_PC_STALE; } -static ExitStatus op_sar(DisasContext *s, DisasOps *o) +static DisasJumpType op_sar(DisasContext *s, DisasOps *o) { int r1 = get_field(s->fields, r1); tcg_gen_st32_i64(o->in2, cpu_env, offsetof(CPUS390XState, aregs[r1])); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_seb(DisasContext *s, DisasOps *o) +static DisasJumpType op_seb(DisasContext *s, DisasOps *o) { gen_helper_seb(o->out, cpu_env, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_sdb(DisasContext *s, DisasOps *o) +static DisasJumpType op_sdb(DisasContext *s, DisasOps *o) { gen_helper_sdb(o->out, cpu_env, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_sxb(DisasContext *s, DisasOps *o) +static DisasJumpType op_sxb(DisasContext *s, DisasOps *o) { gen_helper_sxb(o->out, cpu_env, o->out, o->out2, o->in1, o->in2); return_low128(o->out2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_sqeb(DisasContext *s, DisasOps *o) +static DisasJumpType op_sqeb(DisasContext *s, DisasOps *o) { gen_helper_sqeb(o->out, cpu_env, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_sqdb(DisasContext *s, DisasOps *o) +static DisasJumpType op_sqdb(DisasContext *s, DisasOps *o) { gen_helper_sqdb(o->out, cpu_env, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_sqxb(DisasContext *s, DisasOps *o) +static DisasJumpType op_sqxb(DisasContext *s, DisasOps *o) { gen_helper_sqxb(o->out, cpu_env, o->in1, o->in2); return_low128(o->out2); - return NO_EXIT; + return DISAS_NEXT; } #ifndef CONFIG_USER_ONLY -static ExitStatus op_servc(DisasContext *s, DisasOps *o) +static DisasJumpType op_servc(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_servc(cc_op, cpu_env, o->in2, o->in1); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_sigp(DisasContext *s, DisasOps *o) +static DisasJumpType op_sigp(DisasContext *s, DisasOps *o) { TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); @@ -3775,11 +3776,11 @@ static ExitStatus op_sigp(DisasContext *s, DisasOps *o) set_cc_static(s); tcg_temp_free_i32(r1); tcg_temp_free_i32(r3); - return NO_EXIT; + return DISAS_NEXT; } #endif -static ExitStatus op_soc(DisasContext *s, DisasOps *o) +static DisasJumpType op_soc(DisasContext *s, DisasOps *o) { DisasCompare c; TCGv_i64 a, h; @@ -3821,10 +3822,10 @@ static ExitStatus op_soc(DisasContext *s, DisasOps *o) tcg_temp_free_i64(a); gen_set_label(lab); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_sla(DisasContext *s, DisasOps *o) +static DisasJumpType op_sla(DisasContext *s, DisasOps *o) { uint64_t sign = 1ull << s->insn->data; enum cc_op cco = s->insn->data == 31 ? CC_OP_SLA_32 : CC_OP_SLA_64; @@ -3835,40 +3836,40 @@ static ExitStatus op_sla(DisasContext *s, DisasOps *o) tcg_gen_andi_i64(o->out, o->out, ~sign); tcg_gen_andi_i64(o->in1, o->in1, sign); tcg_gen_or_i64(o->out, o->out, o->in1); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_sll(DisasContext *s, DisasOps *o) +static DisasJumpType op_sll(DisasContext *s, DisasOps *o) { tcg_gen_shl_i64(o->out, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_sra(DisasContext *s, DisasOps *o) +static DisasJumpType op_sra(DisasContext *s, DisasOps *o) { tcg_gen_sar_i64(o->out, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_srl(DisasContext *s, DisasOps *o) +static DisasJumpType op_srl(DisasContext *s, DisasOps *o) { tcg_gen_shr_i64(o->out, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_sfpc(DisasContext *s, DisasOps *o) +static DisasJumpType op_sfpc(DisasContext *s, DisasOps *o) { gen_helper_sfpc(cpu_env, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_sfas(DisasContext *s, DisasOps *o) +static DisasJumpType op_sfas(DisasContext *s, DisasOps *o) { gen_helper_sfas(cpu_env, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_srnm(DisasContext *s, DisasOps *o) +static DisasJumpType op_srnm(DisasContext *s, DisasOps *o) { int b2 = get_field(s->fields, b2); int d2 = get_field(s->fields, d2); @@ -3905,10 +3906,10 @@ static ExitStatus op_srnm(DisasContext *s, DisasOps *o) /* Then install the new FPC to set the rounding mode in fpu_status. */ gen_helper_sfpc(cpu_env, t2); tcg_temp_free_i64(t2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_spm(DisasContext *s, DisasOps *o) +static DisasJumpType op_spm(DisasContext *s, DisasOps *o) { tcg_gen_extrl_i64_i32(cc_op, o->in1); tcg_gen_extract_i32(cc_op, cc_op, 28, 2); @@ -3916,10 +3917,10 @@ static ExitStatus op_spm(DisasContext *s, DisasOps *o) tcg_gen_shri_i64(o->in1, o->in1, 24); tcg_gen_deposit_i64(psw_mask, psw_mask, o->in1, PSW_SHIFT_MASK_PM, 4); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_ectg(DisasContext *s, DisasOps *o) +static DisasJumpType op_ectg(DisasContext *s, DisasOps *o) { int b1 = get_field(s->fields, b1); int d1 = get_field(s->fields, d1); @@ -3946,49 +3947,49 @@ static ExitStatus op_ectg(DisasContext *s, DisasOps *o) tcg_gen_mov_i64(regs[1], o->in2); tcg_temp_free_i64(tmp); - return NO_EXIT; + return DISAS_NEXT; } #ifndef CONFIG_USER_ONLY -static ExitStatus op_spka(DisasContext *s, DisasOps *o) +static DisasJumpType op_spka(DisasContext *s, DisasOps *o) { check_privileged(s); tcg_gen_shri_i64(o->in2, o->in2, 4); tcg_gen_deposit_i64(psw_mask, psw_mask, o->in2, PSW_SHIFT_KEY, 4); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_sske(DisasContext *s, DisasOps *o) +static DisasJumpType op_sske(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_sske(cpu_env, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_ssm(DisasContext *s, DisasOps *o) +static DisasJumpType op_ssm(DisasContext *s, DisasOps *o) { check_privileged(s); tcg_gen_deposit_i64(psw_mask, psw_mask, o->in2, 56, 8); /* Exit to main loop to reevaluate s390_cpu_exec_interrupt. */ - return EXIT_PC_STALE_NOCHAIN; + return DISAS_PC_STALE_NOCHAIN; } -static ExitStatus op_stap(DisasContext *s, DisasOps *o) +static DisasJumpType op_stap(DisasContext *s, DisasOps *o) { check_privileged(s); tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, core_id)); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_stck(DisasContext *s, DisasOps *o) +static DisasJumpType op_stck(DisasContext *s, DisasOps *o) { gen_helper_stck(o->out, cpu_env); /* ??? We don't implement clock states. */ gen_op_movi_cc(s, 0); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_stcke(DisasContext *s, DisasOps *o) +static DisasJumpType op_stcke(DisasContext *s, DisasOps *o) { TCGv_i64 c1 = tcg_temp_new_i64(); TCGv_i64 c2 = tcg_temp_new_i64(); @@ -4012,31 +4013,31 @@ static ExitStatus op_stcke(DisasContext *s, DisasOps *o) tcg_temp_free_i64(todpr); /* ??? We don't implement clock states. */ gen_op_movi_cc(s, 0); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_sckc(DisasContext *s, DisasOps *o) +static DisasJumpType op_sckc(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_sckc(cpu_env, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_sckpf(DisasContext *s, DisasOps *o) +static DisasJumpType op_sckpf(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_sckpf(cpu_env, regs[0]); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_stckc(DisasContext *s, DisasOps *o) +static DisasJumpType op_stckc(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_stckc(o->out, cpu_env); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_stctg(DisasContext *s, DisasOps *o) +static DisasJumpType op_stctg(DisasContext *s, DisasOps *o) { TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); @@ -4044,10 +4045,10 @@ static ExitStatus op_stctg(DisasContext *s, DisasOps *o) gen_helper_stctg(cpu_env, r1, o->in2, r3); tcg_temp_free_i32(r1); tcg_temp_free_i32(r3); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_stctl(DisasContext *s, DisasOps *o) +static DisasJumpType op_stctl(DisasContext *s, DisasOps *o) { TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); @@ -4055,186 +4056,186 @@ static ExitStatus op_stctl(DisasContext *s, DisasOps *o) gen_helper_stctl(cpu_env, r1, o->in2, r3); tcg_temp_free_i32(r1); tcg_temp_free_i32(r3); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_stidp(DisasContext *s, DisasOps *o) +static DisasJumpType op_stidp(DisasContext *s, DisasOps *o) { check_privileged(s); tcg_gen_ld_i64(o->out, cpu_env, offsetof(CPUS390XState, cpuid)); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_spt(DisasContext *s, DisasOps *o) +static DisasJumpType op_spt(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_spt(cpu_env, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_stfl(DisasContext *s, DisasOps *o) +static DisasJumpType op_stfl(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_stfl(cpu_env); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_stpt(DisasContext *s, DisasOps *o) +static DisasJumpType op_stpt(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_stpt(o->out, cpu_env); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_stsi(DisasContext *s, DisasOps *o) +static DisasJumpType op_stsi(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_stsi(cc_op, cpu_env, o->in2, regs[0], regs[1]); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_spx(DisasContext *s, DisasOps *o) +static DisasJumpType op_spx(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_spx(cpu_env, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_xsch(DisasContext *s, DisasOps *o) +static DisasJumpType op_xsch(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_xsch(cpu_env, regs[1]); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_csch(DisasContext *s, DisasOps *o) +static DisasJumpType op_csch(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_csch(cpu_env, regs[1]); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_hsch(DisasContext *s, DisasOps *o) +static DisasJumpType op_hsch(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_hsch(cpu_env, regs[1]); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_msch(DisasContext *s, DisasOps *o) +static DisasJumpType op_msch(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_msch(cpu_env, regs[1], o->in2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_rchp(DisasContext *s, DisasOps *o) +static DisasJumpType op_rchp(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_rchp(cpu_env, regs[1]); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_rsch(DisasContext *s, DisasOps *o) +static DisasJumpType op_rsch(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_rsch(cpu_env, regs[1]); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_sal(DisasContext *s, DisasOps *o) +static DisasJumpType op_sal(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_sal(cpu_env, regs[1]); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_schm(DisasContext *s, DisasOps *o) +static DisasJumpType op_schm(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_schm(cpu_env, regs[1], regs[2], o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_siga(DisasContext *s, DisasOps *o) +static DisasJumpType op_siga(DisasContext *s, DisasOps *o) { check_privileged(s); /* From KVM code: Not provided, set CC = 3 for subchannel not operational */ gen_op_movi_cc(s, 3); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_stcps(DisasContext *s, DisasOps *o) +static DisasJumpType op_stcps(DisasContext *s, DisasOps *o) { check_privileged(s); /* The instruction is suppressed if not provided. */ - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_ssch(DisasContext *s, DisasOps *o) +static DisasJumpType op_ssch(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_ssch(cpu_env, regs[1], o->in2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_stsch(DisasContext *s, DisasOps *o) +static DisasJumpType op_stsch(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_stsch(cpu_env, regs[1], o->in2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_stcrw(DisasContext *s, DisasOps *o) +static DisasJumpType op_stcrw(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_stcrw(cpu_env, o->in2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_tpi(DisasContext *s, DisasOps *o) +static DisasJumpType op_tpi(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_tpi(cc_op, cpu_env, o->addr1); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_tsch(DisasContext *s, DisasOps *o) +static DisasJumpType op_tsch(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_tsch(cpu_env, regs[1], o->in2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_chsc(DisasContext *s, DisasOps *o) +static DisasJumpType op_chsc(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_chsc(cpu_env, o->in2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_stpx(DisasContext *s, DisasOps *o) +static DisasJumpType op_stpx(DisasContext *s, DisasOps *o) { check_privileged(s); tcg_gen_ld_i64(o->out, cpu_env, offsetof(CPUS390XState, psa)); tcg_gen_andi_i64(o->out, o->out, 0x7fffe000); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_stnosm(DisasContext *s, DisasOps *o) +static DisasJumpType op_stnosm(DisasContext *s, DisasOps *o) { uint64_t i2 = get_field(s->fields, i2); TCGv_i64 t; @@ -4257,66 +4258,66 @@ static ExitStatus op_stnosm(DisasContext *s, DisasOps *o) } /* Exit to main loop to reevaluate s390_cpu_exec_interrupt. */ - return EXIT_PC_STALE_NOCHAIN; + return DISAS_PC_STALE_NOCHAIN; } -static ExitStatus op_stura(DisasContext *s, DisasOps *o) +static DisasJumpType op_stura(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_stura(cpu_env, o->in2, o->in1); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_sturg(DisasContext *s, DisasOps *o) +static DisasJumpType op_sturg(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_sturg(cpu_env, o->in2, o->in1); - return NO_EXIT; + return DISAS_NEXT; } #endif -static ExitStatus op_stfle(DisasContext *s, DisasOps *o) +static DisasJumpType op_stfle(DisasContext *s, DisasOps *o) { gen_helper_stfle(cc_op, cpu_env, o->in2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_st8(DisasContext *s, DisasOps *o) +static DisasJumpType op_st8(DisasContext *s, DisasOps *o) { tcg_gen_qemu_st8(o->in1, o->in2, get_mem_index(s)); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_st16(DisasContext *s, DisasOps *o) +static DisasJumpType op_st16(DisasContext *s, DisasOps *o) { tcg_gen_qemu_st16(o->in1, o->in2, get_mem_index(s)); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_st32(DisasContext *s, DisasOps *o) +static DisasJumpType op_st32(DisasContext *s, DisasOps *o) { tcg_gen_qemu_st32(o->in1, o->in2, get_mem_index(s)); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_st64(DisasContext *s, DisasOps *o) +static DisasJumpType op_st64(DisasContext *s, DisasOps *o) { tcg_gen_qemu_st64(o->in1, o->in2, get_mem_index(s)); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_stam(DisasContext *s, DisasOps *o) +static DisasJumpType op_stam(DisasContext *s, DisasOps *o) { TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); gen_helper_stam(cpu_env, r1, o->in2, r3); tcg_temp_free_i32(r1); tcg_temp_free_i32(r3); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_stcm(DisasContext *s, DisasOps *o) +static DisasJumpType op_stcm(DisasContext *s, DisasOps *o) { int m3 = get_field(s->fields, m3); int pos, base = s->insn->data; @@ -4362,10 +4363,10 @@ static ExitStatus op_stcm(DisasContext *s, DisasOps *o) break; } tcg_temp_free_i64(tmp); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_stm(DisasContext *s, DisasOps *o) +static DisasJumpType op_stm(DisasContext *s, DisasOps *o) { int r1 = get_field(s->fields, r1); int r3 = get_field(s->fields, r3); @@ -4386,10 +4387,10 @@ static ExitStatus op_stm(DisasContext *s, DisasOps *o) } tcg_temp_free_i64(tsize); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_stmh(DisasContext *s, DisasOps *o) +static DisasJumpType op_stmh(DisasContext *s, DisasOps *o) { int r1 = get_field(s->fields, r1); int r3 = get_field(s->fields, r3); @@ -4410,20 +4411,20 @@ static ExitStatus op_stmh(DisasContext *s, DisasOps *o) tcg_temp_free_i64(t); tcg_temp_free_i64(t4); tcg_temp_free_i64(t32); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_stpq(DisasContext *s, DisasOps *o) +static DisasJumpType op_stpq(DisasContext *s, DisasOps *o) { - if (tb_cflags(s->tb) & CF_PARALLEL) { + if (tb_cflags(s->base.tb) & CF_PARALLEL) { gen_helper_stpq_parallel(cpu_env, o->in2, o->out2, o->out); } else { gen_helper_stpq(cpu_env, o->in2, o->out2, o->out); } - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_srst(DisasContext *s, DisasOps *o) +static DisasJumpType op_srst(DisasContext *s, DisasOps *o) { TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2)); @@ -4433,10 +4434,10 @@ static ExitStatus op_srst(DisasContext *s, DisasOps *o) tcg_temp_free_i32(r1); tcg_temp_free_i32(r2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_srstu(DisasContext *s, DisasOps *o) +static DisasJumpType op_srstu(DisasContext *s, DisasOps *o) { TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2)); @@ -4446,16 +4447,16 @@ static ExitStatus op_srstu(DisasContext *s, DisasOps *o) tcg_temp_free_i32(r1); tcg_temp_free_i32(r2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_sub(DisasContext *s, DisasOps *o) +static DisasJumpType op_sub(DisasContext *s, DisasOps *o) { tcg_gen_sub_i64(o->out, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_subb(DisasContext *s, DisasOps *o) +static DisasJumpType op_subb(DisasContext *s, DisasOps *o) { DisasCompare cmp; TCGv_i64 borrow; @@ -4478,10 +4479,10 @@ static ExitStatus op_subb(DisasContext *s, DisasOps *o) tcg_gen_sub_i64(o->out, o->out, borrow); tcg_temp_free_i64(borrow); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_svc(DisasContext *s, DisasOps *o) +static DisasJumpType op_svc(DisasContext *s, DisasOps *o) { TCGv_i32 t; @@ -4497,104 +4498,104 @@ static ExitStatus op_svc(DisasContext *s, DisasOps *o) tcg_temp_free_i32(t); gen_exception(EXCP_SVC); - return EXIT_NORETURN; + return DISAS_NORETURN; } -static ExitStatus op_tam(DisasContext *s, DisasOps *o) +static DisasJumpType op_tam(DisasContext *s, DisasOps *o) { int cc = 0; - cc |= (s->tb->flags & FLAG_MASK_64) ? 2 : 0; - cc |= (s->tb->flags & FLAG_MASK_32) ? 1 : 0; + cc |= (s->base.tb->flags & FLAG_MASK_64) ? 2 : 0; + cc |= (s->base.tb->flags & FLAG_MASK_32) ? 1 : 0; gen_op_movi_cc(s, cc); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_tceb(DisasContext *s, DisasOps *o) +static DisasJumpType op_tceb(DisasContext *s, DisasOps *o) { gen_helper_tceb(cc_op, cpu_env, o->in1, o->in2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_tcdb(DisasContext *s, DisasOps *o) +static DisasJumpType op_tcdb(DisasContext *s, DisasOps *o) { gen_helper_tcdb(cc_op, cpu_env, o->in1, o->in2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_tcxb(DisasContext *s, DisasOps *o) +static DisasJumpType op_tcxb(DisasContext *s, DisasOps *o) { gen_helper_tcxb(cc_op, cpu_env, o->out, o->out2, o->in2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } #ifndef CONFIG_USER_ONLY -static ExitStatus op_testblock(DisasContext *s, DisasOps *o) +static DisasJumpType op_testblock(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_testblock(cc_op, cpu_env, o->in2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_tprot(DisasContext *s, DisasOps *o) +static DisasJumpType op_tprot(DisasContext *s, DisasOps *o) { gen_helper_tprot(cc_op, cpu_env, o->addr1, o->in2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } #endif -static ExitStatus op_tp(DisasContext *s, DisasOps *o) +static DisasJumpType op_tp(DisasContext *s, DisasOps *o) { TCGv_i32 l1 = tcg_const_i32(get_field(s->fields, l1) + 1); gen_helper_tp(cc_op, cpu_env, o->addr1, l1); tcg_temp_free_i32(l1); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_tr(DisasContext *s, DisasOps *o) +static DisasJumpType op_tr(DisasContext *s, DisasOps *o) { TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); gen_helper_tr(cpu_env, l, o->addr1, o->in2); tcg_temp_free_i32(l); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_tre(DisasContext *s, DisasOps *o) +static DisasJumpType op_tre(DisasContext *s, DisasOps *o) { gen_helper_tre(o->out, cpu_env, o->out, o->out2, o->in2); return_low128(o->out2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_trt(DisasContext *s, DisasOps *o) +static DisasJumpType op_trt(DisasContext *s, DisasOps *o) { TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); gen_helper_trt(cc_op, cpu_env, l, o->addr1, o->in2); tcg_temp_free_i32(l); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_trtr(DisasContext *s, DisasOps *o) +static DisasJumpType op_trtr(DisasContext *s, DisasOps *o) { TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); gen_helper_trtr(cc_op, cpu_env, l, o->addr1, o->in2); tcg_temp_free_i32(l); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_trXX(DisasContext *s, DisasOps *o) +static DisasJumpType op_trXX(DisasContext *s, DisasOps *o) { TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2)); @@ -4622,28 +4623,28 @@ static ExitStatus op_trXX(DisasContext *s, DisasOps *o) tcg_temp_free_i32(sizes); tcg_temp_free_i32(tst); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_ts(DisasContext *s, DisasOps *o) +static DisasJumpType op_ts(DisasContext *s, DisasOps *o) { TCGv_i32 t1 = tcg_const_i32(0xff); tcg_gen_atomic_xchg_i32(t1, o->in2, t1, get_mem_index(s), MO_UB); tcg_gen_extract_i32(cc_op, t1, 7, 1); tcg_temp_free_i32(t1); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_unpk(DisasContext *s, DisasOps *o) +static DisasJumpType op_unpk(DisasContext *s, DisasOps *o) { TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1)); gen_helper_unpk(cpu_env, l, o->addr1, o->in2); tcg_temp_free_i32(l); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_unpka(DisasContext *s, DisasOps *o) +static DisasJumpType op_unpka(DisasContext *s, DisasOps *o) { int l1 = get_field(s->fields, l1) + 1; TCGv_i32 l; @@ -4651,16 +4652,16 @@ static ExitStatus op_unpka(DisasContext *s, DisasOps *o) /* The length must not exceed 32 bytes. */ if (l1 > 32) { gen_program_exception(s, PGM_SPECIFICATION); - return EXIT_NORETURN; + return DISAS_NORETURN; } l = tcg_const_i32(l1); gen_helper_unpka(cc_op, cpu_env, o->addr1, l, o->in2); tcg_temp_free_i32(l); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_unpku(DisasContext *s, DisasOps *o) +static DisasJumpType op_unpku(DisasContext *s, DisasOps *o) { int l1 = get_field(s->fields, l1) + 1; TCGv_i32 l; @@ -4668,17 +4669,17 @@ static ExitStatus op_unpku(DisasContext *s, DisasOps *o) /* The length must be even and should not exceed 64 bytes. */ if ((l1 & 1) || (l1 > 64)) { gen_program_exception(s, PGM_SPECIFICATION); - return EXIT_NORETURN; + return DISAS_NORETURN; } l = tcg_const_i32(l1); gen_helper_unpku(cc_op, cpu_env, o->addr1, l, o->in2); tcg_temp_free_i32(l); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_xc(DisasContext *s, DisasOps *o) +static DisasJumpType op_xc(DisasContext *s, DisasOps *o) { int d1 = get_field(s->fields, d1); int d2 = get_field(s->fields, d2); @@ -4719,7 +4720,7 @@ static ExitStatus op_xc(DisasContext *s, DisasOps *o) tcg_gen_qemu_st8(o->in2, o->addr1, get_mem_index(s)); } gen_op_movi_cc(s, 0); - return NO_EXIT; + return DISAS_NEXT; } /* But in general we'll defer to a helper. */ @@ -4728,16 +4729,16 @@ static ExitStatus op_xc(DisasContext *s, DisasOps *o) gen_helper_xc(cc_op, cpu_env, t32, o->addr1, o->in2); tcg_temp_free_i32(t32); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_xor(DisasContext *s, DisasOps *o) +static DisasJumpType op_xor(DisasContext *s, DisasOps *o) { tcg_gen_xor_i64(o->out, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_xori(DisasContext *s, DisasOps *o) +static DisasJumpType op_xori(DisasContext *s, DisasOps *o) { int shift = s->insn->data & 0xff; int size = s->insn->data >> 8; @@ -4750,10 +4751,10 @@ static ExitStatus op_xori(DisasContext *s, DisasOps *o) /* Produce the CC from only the bits manipulated. */ tcg_gen_andi_i64(cc_dst, o->out, mask); set_cc_nz_u64(s, cc_dst); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_xi(DisasContext *s, DisasOps *o) +static DisasJumpType op_xi(DisasContext *s, DisasOps *o) { o->in1 = tcg_temp_new_i64(); @@ -4771,25 +4772,25 @@ static ExitStatus op_xi(DisasContext *s, DisasOps *o) if (!s390_has_feat(S390_FEAT_INTERLOCKED_ACCESS_2)) { tcg_gen_qemu_st_tl(o->out, o->addr1, get_mem_index(s), s->insn->data); } - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_zero(DisasContext *s, DisasOps *o) +static DisasJumpType op_zero(DisasContext *s, DisasOps *o) { o->out = tcg_const_i64(0); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_zero2(DisasContext *s, DisasOps *o) +static DisasJumpType op_zero2(DisasContext *s, DisasOps *o) { o->out = tcg_const_i64(0); o->out2 = o->out; o->g_out2 = true; - return NO_EXIT; + return DISAS_NEXT; } #ifndef CONFIG_USER_ONLY -static ExitStatus op_clp(DisasContext *s, DisasOps *o) +static DisasJumpType op_clp(DisasContext *s, DisasOps *o) { TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2)); @@ -4797,10 +4798,10 @@ static ExitStatus op_clp(DisasContext *s, DisasOps *o) gen_helper_clp(cpu_env, r2); tcg_temp_free_i32(r2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_pcilg(DisasContext *s, DisasOps *o) +static DisasJumpType op_pcilg(DisasContext *s, DisasOps *o) { TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2)); @@ -4810,10 +4811,10 @@ static ExitStatus op_pcilg(DisasContext *s, DisasOps *o) tcg_temp_free_i32(r1); tcg_temp_free_i32(r2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_pcistg(DisasContext *s, DisasOps *o) +static DisasJumpType op_pcistg(DisasContext *s, DisasOps *o) { TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2)); @@ -4823,10 +4824,10 @@ static ExitStatus op_pcistg(DisasContext *s, DisasOps *o) tcg_temp_free_i32(r1); tcg_temp_free_i32(r2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_stpcifc(DisasContext *s, DisasOps *o) +static DisasJumpType op_stpcifc(DisasContext *s, DisasOps *o) { TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 ar = tcg_const_i32(get_field(s->fields, b2)); @@ -4836,17 +4837,17 @@ static ExitStatus op_stpcifc(DisasContext *s, DisasOps *o) tcg_temp_free_i32(ar); tcg_temp_free_i32(r1); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_sic(DisasContext *s, DisasOps *o) +static DisasJumpType op_sic(DisasContext *s, DisasOps *o) { check_privileged(s); gen_helper_sic(cpu_env, o->in1, o->in2); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_rpcit(DisasContext *s, DisasOps *o) +static DisasJumpType op_rpcit(DisasContext *s, DisasOps *o) { TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r2 = tcg_const_i32(get_field(s->fields, r2)); @@ -4856,10 +4857,10 @@ static ExitStatus op_rpcit(DisasContext *s, DisasOps *o) tcg_temp_free_i32(r1); tcg_temp_free_i32(r2); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_pcistb(DisasContext *s, DisasOps *o) +static DisasJumpType op_pcistb(DisasContext *s, DisasOps *o) { TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 r3 = tcg_const_i32(get_field(s->fields, r3)); @@ -4871,10 +4872,10 @@ static ExitStatus op_pcistb(DisasContext *s, DisasOps *o) tcg_temp_free_i32(r1); tcg_temp_free_i32(r3); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } -static ExitStatus op_mpcifc(DisasContext *s, DisasOps *o) +static DisasJumpType op_mpcifc(DisasContext *s, DisasOps *o) { TCGv_i32 r1 = tcg_const_i32(get_field(s->fields, r1)); TCGv_i32 ar = tcg_const_i32(get_field(s->fields, b2)); @@ -4884,7 +4885,7 @@ static ExitStatus op_mpcifc(DisasContext *s, DisasOps *o) tcg_temp_free_i32(ar); tcg_temp_free_i32(r1); set_cc_static(s); - return NO_EXIT; + return DISAS_NEXT; } #endif @@ -5629,7 +5630,7 @@ static void in2_a2(DisasContext *s, DisasFields *f, DisasOps *o) static void in2_ri2(DisasContext *s, DisasFields *f, DisasOps *o) { - o->in2 = tcg_const_i64(s->pc + (int64_t)get_field(f, i2) * 2); + o->in2 = tcg_const_i64(s->base.pc_next + (int64_t)get_field(f, i2) * 2); } #define SPEC_in2_ri2 0 @@ -5930,7 +5931,7 @@ static void extract_field(DisasFields *o, const DisasField *f, uint64_t insn) static const DisasInsn *extract_insn(CPUS390XState *env, DisasContext *s, DisasFields *f) { - uint64_t insn, pc = s->pc; + uint64_t insn, pc = s->base.pc_next; int op, op2, ilen; const DisasInsn *info; @@ -5962,7 +5963,7 @@ static const DisasInsn *extract_insn(CPUS390XState *env, DisasContext *s, g_assert_not_reached(); } } - s->next_pc = s->pc + ilen; + s->pc_tmp = s->base.pc_next + ilen; s->ilen = ilen; /* We can't actually determine the insn format until we've looked up @@ -6028,10 +6029,10 @@ static const DisasInsn *extract_insn(CPUS390XState *env, DisasContext *s, return info; } -static ExitStatus translate_one(CPUS390XState *env, DisasContext *s) +static DisasJumpType translate_one(CPUS390XState *env, DisasContext *s) { const DisasInsn *insn; - ExitStatus ret = NO_EXIT; + DisasJumpType ret = DISAS_NEXT; DisasFields f; DisasOps o; @@ -6043,12 +6044,12 @@ static ExitStatus translate_one(CPUS390XState *env, DisasContext *s) qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%02x%02x\n", f.op, f.op2); gen_illegal_opcode(s); - return EXIT_NORETURN; + return DISAS_NORETURN; } #ifndef CONFIG_USER_ONLY - if (s->tb->flags & FLAG_MASK_PER) { - TCGv_i64 addr = tcg_const_i64(s->pc); + if (s->base.tb->flags & FLAG_MASK_PER) { + TCGv_i64 addr = tcg_const_i64(s->base.pc_next); gen_helper_per_ifetch(cpu_env, addr); tcg_temp_free_i64(addr); } @@ -6090,7 +6091,7 @@ static ExitStatus translate_one(CPUS390XState *env, DisasContext *s) } if (excp) { gen_program_exception(s, excp); - return EXIT_NORETURN; + return DISAS_NORETURN; } } @@ -6142,10 +6143,10 @@ static ExitStatus translate_one(CPUS390XState *env, DisasContext *s) } #ifndef CONFIG_USER_ONLY - if (s->tb->flags & FLAG_MASK_PER) { + if (s->base.tb->flags & FLAG_MASK_PER) { /* An exception might be triggered, save PSW if not already done. */ - if (ret == NO_EXIT || ret == EXIT_PC_STALE) { - tcg_gen_movi_i64(psw_addr, s->next_pc); + if (ret == DISAS_NEXT || ret == DISAS_PC_STALE) { + tcg_gen_movi_i64(psw_addr, s->pc_tmp); } /* Call the helper to check for a possible PER exception. */ @@ -6154,102 +6155,91 @@ static ExitStatus translate_one(CPUS390XState *env, DisasContext *s) #endif /* Advance to the next instruction. */ - s->pc = s->next_pc; + s->base.pc_next = s->pc_tmp; return ret; } -void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) +static void s390x_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) { - CPUS390XState *env = cs->env_ptr; - DisasContext dc; - target_ulong pc_start; - uint64_t next_page_start; - int num_insns, max_insns; - ExitStatus status; - bool do_debug; - - pc_start = tb->pc; + DisasContext *dc = container_of(dcbase, DisasContext, base); /* 31-bit mode */ - if (!(tb->flags & FLAG_MASK_64)) { - pc_start &= 0x7fffffff; + if (!(dc->base.tb->flags & FLAG_MASK_64)) { + dc->base.pc_first &= 0x7fffffff; + dc->base.pc_next = dc->base.pc_first; } - dc.tb = tb; - dc.pc = pc_start; - dc.cc_op = CC_OP_DYNAMIC; - dc.ex_value = tb->cs_base; - do_debug = dc.singlestep_enabled = cs->singlestep_enabled; + dc->cc_op = CC_OP_DYNAMIC; + dc->ex_value = dc->base.tb->cs_base; + dc->do_debug = dc->base.singlestep_enabled; +} - next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; +static void s390x_tr_tb_start(DisasContextBase *db, CPUState *cs) +{ +} - num_insns = 0; - max_insns = tb_cflags(tb) & CF_COUNT_MASK; - if (max_insns == 0) { - max_insns = CF_COUNT_MASK; - } - if (max_insns > TCG_MAX_INSNS) { - max_insns = TCG_MAX_INSNS; - } +static void s390x_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) +{ + DisasContext *dc = container_of(dcbase, DisasContext, base); - gen_tb_start(tb); + tcg_gen_insn_start(dc->base.pc_next, dc->cc_op); +} - do { - tcg_gen_insn_start(dc.pc, dc.cc_op); - num_insns++; +static bool s390x_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, + const CPUBreakpoint *bp) +{ + DisasContext *dc = container_of(dcbase, DisasContext, base); - if (unlikely(cpu_breakpoint_test(cs, dc.pc, BP_ANY))) { - status = EXIT_PC_STALE; - do_debug = true; - /* The address covered by the breakpoint must be included in - [tb->pc, tb->pc + tb->size) in order to for it to be - properly cleared -- thus we increment the PC here so that - the logic setting tb->size below does the right thing. */ - dc.pc += 2; - break; - } + dc->base.is_jmp = DISAS_PC_STALE; + dc->do_debug = true; + /* The address covered by the breakpoint must be included in + [tb->pc, tb->pc + tb->size) in order to for it to be + properly cleared -- thus we increment the PC here so that + the logic setting tb->size does the right thing. */ + dc->base.pc_next += 2; + return true; +} - if (num_insns == max_insns && (tb_cflags(tb) & CF_LAST_IO)) { - gen_io_start(); - } +static void s390x_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) +{ + CPUS390XState *env = cs->env_ptr; + DisasContext *dc = container_of(dcbase, DisasContext, base); - status = translate_one(env, &dc); - - /* If we reach a page boundary, are single stepping, - or exhaust instruction count, stop generation. */ - if (status == NO_EXIT - && (dc.pc >= next_page_start - || tcg_op_buf_full() - || num_insns >= max_insns - || singlestep - || cs->singlestep_enabled - || dc.ex_value)) { - status = EXIT_PC_STALE; - } - } while (status == NO_EXIT); + dc->base.is_jmp = translate_one(env, dc); + if (dc->base.is_jmp == DISAS_NEXT) { + uint64_t page_start; - if (tb_cflags(tb) & CF_LAST_IO) { - gen_io_end(); + page_start = dc->base.pc_first & TARGET_PAGE_MASK; + if (dc->base.pc_next - page_start >= TARGET_PAGE_SIZE || dc->ex_value) { + dc->base.is_jmp = DISAS_TOO_MANY; + } } +} + +static void s390x_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) +{ + DisasContext *dc = container_of(dcbase, DisasContext, base); - switch (status) { - case EXIT_GOTO_TB: - case EXIT_NORETURN: + switch (dc->base.is_jmp) { + case DISAS_GOTO_TB: + case DISAS_NORETURN: break; - case EXIT_PC_STALE: - case EXIT_PC_STALE_NOCHAIN: - update_psw_addr(&dc); + case DISAS_TOO_MANY: + case DISAS_PC_STALE: + case DISAS_PC_STALE_NOCHAIN: + update_psw_addr(dc); /* FALLTHRU */ - case EXIT_PC_UPDATED: + case DISAS_PC_UPDATED: /* Next TB starts off with CC_OP_DYNAMIC, so make sure the cc op type is in env */ - update_cc_op(&dc); + update_cc_op(dc); /* FALLTHRU */ - case EXIT_PC_CC_UPDATED: + case DISAS_PC_CC_UPDATED: /* Exit the TB, either by raising a debug exception or by return. */ - if (do_debug) { + if (dc->do_debug) { gen_exception(EXCP_DEBUG); - } else if (use_exit_tb(&dc) || status == EXIT_PC_STALE_NOCHAIN) { + } else if (use_exit_tb(dc) || + dc->base.is_jmp == DISAS_PC_STALE_NOCHAIN) { tcg_gen_exit_tb(0); } else { tcg_gen_lookup_and_goto_ptr(); @@ -6258,27 +6248,36 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) default: g_assert_not_reached(); } +} - gen_tb_end(tb, num_insns); - - tb->size = dc.pc - pc_start; - tb->icount = num_insns; +static void s390x_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs) +{ + DisasContext *dc = container_of(dcbase, DisasContext, base); -#if defined(S390X_DEBUG_DISAS) - if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) - && qemu_log_in_addr_range(pc_start)) { - qemu_log_lock(); - if (unlikely(dc.ex_value)) { - /* ??? Unfortunately log_target_disas can't use host memory. */ - qemu_log("IN: EXECUTE %016" PRIx64 "\n", dc.ex_value); - } else { - qemu_log("IN: %s\n", lookup_symbol(pc_start)); - log_target_disas(cs, pc_start, dc.pc - pc_start); - qemu_log("\n"); - } - qemu_log_unlock(); + if (unlikely(dc->ex_value)) { + /* ??? Unfortunately log_target_disas can't use host memory. */ + qemu_log("IN: EXECUTE %016" PRIx64, dc->ex_value); + } else { + qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first)); + log_target_disas(cs, dc->base.pc_first, dc->base.tb->size); } -#endif +} + +static const TranslatorOps s390x_tr_ops = { + .init_disas_context = s390x_tr_init_disas_context, + .tb_start = s390x_tr_tb_start, + .insn_start = s390x_tr_insn_start, + .breakpoint_check = s390x_tr_breakpoint_check, + .translate_insn = s390x_tr_translate_insn, + .tb_stop = s390x_tr_tb_stop, + .disas_log = s390x_tr_disas_log, +}; + +void gen_intermediate_code(CPUState *cs, TranslationBlock *tb) +{ + DisasContext dc; + + translator_loop(&s390x_tr_ops, &dc.base, cs, tb); } void restore_state_to_opc(CPUS390XState *env, TranslationBlock *tb, diff --git a/target/sh4/translate.c b/target/sh4/translate.c index 012156b97b..58bdfeb4fb 100644 --- a/target/sh4/translate.c +++ b/target/sh4/translate.c @@ -2258,126 +2258,127 @@ static int decode_gusa(DisasContext *ctx, CPUSH4State *env, int *pmax_insns) } #endif -void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) +static void sh4_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) { + DisasContext *ctx = container_of(dcbase, DisasContext, base); CPUSH4State *env = cs->env_ptr; - DisasContext ctx; - target_ulong pc_start; - int num_insns; - int max_insns; - - pc_start = tb->pc; - ctx.base.pc_next = pc_start; - ctx.tbflags = (uint32_t)tb->flags; - ctx.envflags = tb->flags & TB_FLAG_ENVFLAGS_MASK; - ctx.base.is_jmp = DISAS_NEXT; - ctx.memidx = (ctx.tbflags & (1u << SR_MD)) == 0 ? 1 : 0; + int bound; + + ctx->tbflags = (uint32_t)ctx->base.tb->flags; + ctx->envflags = ctx->base.tb->flags & TB_FLAG_ENVFLAGS_MASK; + ctx->memidx = (ctx->tbflags & (1u << SR_MD)) == 0 ? 1 : 0; /* We don't know if the delayed pc came from a dynamic or static branch, so assume it is a dynamic branch. */ - ctx.delayed_pc = -1; /* use delayed pc from env pointer */ - ctx.base.tb = tb; - ctx.base.singlestep_enabled = cs->singlestep_enabled; - ctx.features = env->features; - ctx.has_movcal = (ctx.tbflags & TB_FLAG_PENDING_MOVCA); - ctx.gbank = ((ctx.tbflags & (1 << SR_MD)) && - (ctx.tbflags & (1 << SR_RB))) * 0x10; - ctx.fbank = ctx.tbflags & FPSCR_FR ? 0x10 : 0; - - max_insns = tb_cflags(tb) & CF_COUNT_MASK; - if (max_insns == 0) { - max_insns = CF_COUNT_MASK; - } - max_insns = MIN(max_insns, TCG_MAX_INSNS); + ctx->delayed_pc = -1; /* use delayed pc from env pointer */ + ctx->features = env->features; + ctx->has_movcal = (ctx->tbflags & TB_FLAG_PENDING_MOVCA); + ctx->gbank = ((ctx->tbflags & (1 << SR_MD)) && + (ctx->tbflags & (1 << SR_RB))) * 0x10; + ctx->fbank = ctx->tbflags & FPSCR_FR ? 0x10 : 0; /* Since the ISA is fixed-width, we can bound by the number of instructions remaining on the page. */ - num_insns = -(ctx.base.pc_next | TARGET_PAGE_MASK) / 2; - max_insns = MIN(max_insns, num_insns); - - /* Single stepping means just that. */ - if (ctx.base.singlestep_enabled || singlestep) { - max_insns = 1; - } - - gen_tb_start(tb); - num_insns = 0; + bound = -(ctx->base.pc_next | TARGET_PAGE_MASK) / 2; + ctx->base.max_insns = MIN(ctx->base.max_insns, bound); +} +static void sh4_tr_tb_start(DisasContextBase *dcbase, CPUState *cs) +{ #ifdef CONFIG_USER_ONLY - if (ctx.tbflags & GUSA_MASK) { - num_insns = decode_gusa(&ctx, env, &max_insns); + DisasContext *ctx = container_of(dcbase, DisasContext, base); + CPUSH4State *env = cs->env_ptr; + + if (ctx->tbflags & GUSA_MASK) { + ctx->base.num_insns = decode_gusa(ctx, env, &ctx->base.max_insns); } #endif +} - while (ctx.base.is_jmp == DISAS_NEXT - && num_insns < max_insns - && !tcg_op_buf_full()) { - tcg_gen_insn_start(ctx.base.pc_next, ctx.envflags); - num_insns++; +static void sh4_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) +{ + DisasContext *ctx = container_of(dcbase, DisasContext, base); - if (unlikely(cpu_breakpoint_test(cs, ctx.base.pc_next, BP_ANY))) { - /* We have hit a breakpoint - make sure PC is up-to-date */ - gen_save_cpu_state(&ctx, true); - gen_helper_debug(cpu_env); - ctx.base.is_jmp = DISAS_NORETURN; - /* The address covered by the breakpoint must be included in - [tb->pc, tb->pc + tb->size) in order to for it to be - properly cleared -- thus we increment the PC here so that - the logic setting tb->size below does the right thing. */ - ctx.base.pc_next += 2; - break; - } + tcg_gen_insn_start(ctx->base.pc_next, ctx->envflags); +} - if (num_insns == max_insns && (tb_cflags(tb) & CF_LAST_IO)) { - gen_io_start(); - } +static bool sh4_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, + const CPUBreakpoint *bp) +{ + DisasContext *ctx = container_of(dcbase, DisasContext, base); - ctx.opcode = cpu_lduw_code(env, ctx.base.pc_next); - decode_opc(&ctx); - ctx.base.pc_next += 2; - } - if (tb_cflags(tb) & CF_LAST_IO) { - gen_io_end(); - } + /* We have hit a breakpoint - make sure PC is up-to-date */ + gen_save_cpu_state(ctx, true); + gen_helper_debug(cpu_env); + ctx->base.is_jmp = DISAS_NORETURN; + /* The address covered by the breakpoint must be included in + [tb->pc, tb->pc + tb->size) in order to for it to be + properly cleared -- thus we increment the PC here so that + the logic setting tb->size below does the right thing. */ + ctx->base.pc_next += 2; + return true; +} + +static void sh4_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) +{ + CPUSH4State *env = cs->env_ptr; + DisasContext *ctx = container_of(dcbase, DisasContext, base); - if (ctx.tbflags & GUSA_EXCLUSIVE) { + ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next); + decode_opc(ctx); + ctx->base.pc_next += 2; +} + +static void sh4_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) +{ + DisasContext *ctx = container_of(dcbase, DisasContext, base); + + if (ctx->tbflags & GUSA_EXCLUSIVE) { /* Ending the region of exclusivity. Clear the bits. */ - ctx.envflags &= ~GUSA_MASK; + ctx->envflags &= ~GUSA_MASK; } - switch (ctx.base.is_jmp) { + switch (ctx->base.is_jmp) { case DISAS_STOP: - gen_save_cpu_state(&ctx, true); - if (ctx.base.singlestep_enabled) { + gen_save_cpu_state(ctx, true); + if (ctx->base.singlestep_enabled) { gen_helper_debug(cpu_env); } else { tcg_gen_exit_tb(0); } break; case DISAS_NEXT: - gen_save_cpu_state(&ctx, false); - gen_goto_tb(&ctx, 0, ctx.base.pc_next); + case DISAS_TOO_MANY: + gen_save_cpu_state(ctx, false); + gen_goto_tb(ctx, 0, ctx->base.pc_next); break; case DISAS_NORETURN: break; default: g_assert_not_reached(); } +} - gen_tb_end(tb, num_insns); +static void sh4_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs) +{ + qemu_log("IN:\n"); /* , lookup_symbol(dcbase->pc_first)); */ + log_target_disas(cs, dcbase->pc_first, dcbase->tb->size); +} - tb->size = ctx.base.pc_next - pc_start; - tb->icount = num_insns; +static const TranslatorOps sh4_tr_ops = { + .init_disas_context = sh4_tr_init_disas_context, + .tb_start = sh4_tr_tb_start, + .insn_start = sh4_tr_insn_start, + .breakpoint_check = sh4_tr_breakpoint_check, + .translate_insn = sh4_tr_translate_insn, + .tb_stop = sh4_tr_tb_stop, + .disas_log = sh4_tr_disas_log, +}; + +void gen_intermediate_code(CPUState *cs, TranslationBlock *tb) +{ + DisasContext ctx; -#ifdef DEBUG_DISAS - if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) - && qemu_log_in_addr_range(pc_start)) { - qemu_log_lock(); - qemu_log("IN:\n"); /* , lookup_symbol(pc_start)); */ - log_target_disas(cs, pc_start, ctx.base.pc_next - pc_start); - qemu_log("\n"); - qemu_log_unlock(); - } -#endif + translator_loop(&sh4_tr_ops, &ctx.base, cs, tb); } void restore_state_to_opc(CPUSH4State *env, TranslationBlock *tb, diff --git a/target/sparc/translate.c b/target/sparc/translate.c index 5aa367a182..40b2eaad39 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -30,6 +30,7 @@ #include "exec/helper-gen.h" #include "trace-tcg.h" +#include "exec/translator.h" #include "exec/log.h" #include "asi.h" @@ -66,14 +67,13 @@ static TCGv_i64 cpu_fpr[TARGET_DPREGS]; #include "exec/gen-icount.h" typedef struct DisasContext { + DisasContextBase base; target_ulong pc; /* current Program Counter: integer or DYNAMIC_PC */ target_ulong npc; /* next PC: integer or DYNAMIC_PC or JUMP_PC */ target_ulong jump_pc[2]; /* used when JUMP_PC pc value is used */ - int is_br; int mem_idx; bool fpu_enabled; bool address_mask_32bit; - bool singlestep; #ifndef CONFIG_USER_ONLY bool supervisor; #ifdef TARGET_SPARC64 @@ -82,7 +82,6 @@ typedef struct DisasContext { #endif uint32_t cc_op; /* current CC operation */ - struct TranslationBlock *tb; sparc_def_t *def; TCGv_i32 t32[3]; TCGv ttl[5]; @@ -341,13 +340,13 @@ static inline TCGv gen_dest_gpr(DisasContext *dc, int reg) static inline bool use_goto_tb(DisasContext *s, target_ulong pc, target_ulong npc) { - if (unlikely(s->singlestep)) { + if (unlikely(s->base.singlestep_enabled || singlestep)) { return false; } #ifndef CONFIG_USER_ONLY - return (pc & TARGET_PAGE_MASK) == (s->tb->pc & TARGET_PAGE_MASK) && - (npc & TARGET_PAGE_MASK) == (s->tb->pc & TARGET_PAGE_MASK); + return (pc & TARGET_PAGE_MASK) == (s->base.tb->pc & TARGET_PAGE_MASK) && + (npc & TARGET_PAGE_MASK) == (s->base.tb->pc & TARGET_PAGE_MASK); #else return true; #endif @@ -361,7 +360,7 @@ static inline void gen_goto_tb(DisasContext *s, int tb_num, tcg_gen_goto_tb(tb_num); tcg_gen_movi_tl(cpu_pc, pc); tcg_gen_movi_tl(cpu_npc, npc); - tcg_gen_exit_tb((uintptr_t)s->tb + tb_num); + tcg_gen_exit_tb((uintptr_t)s->base.tb + tb_num); } else { /* jump to another page: currently not optimized */ tcg_gen_movi_tl(cpu_pc, pc); @@ -995,7 +994,7 @@ static void gen_branch_a(DisasContext *dc, target_ulong pc1) gen_set_label(l1); gen_goto_tb(dc, 1, npc + 4, npc + 8); - dc->is_br = 1; + dc->base.is_jmp = DISAS_NORETURN; } static void gen_branch_n(DisasContext *dc, target_ulong pc1) @@ -1078,7 +1077,7 @@ static void gen_exception(DisasContext *dc, int which) t = tcg_const_i32(which); gen_helper_raise_exception(cpu_env, t); tcg_temp_free_i32(t); - dc->is_br = 1; + dc->base.is_jmp = DISAS_NORETURN; } static void gen_check_align(TCGv addr, int mask) @@ -2441,7 +2440,7 @@ static void gen_ldstub_asi(DisasContext *dc, TCGv dst, TCGv addr, int insn) default: /* ??? In theory, this should be raise DAE_invalid_asi. But the SS-20 roms do ldstuba [%l0] #ASI_M_CTL, %o1. */ - if (tb_cflags(dc->tb) & CF_PARALLEL) { + if (tb_cflags(dc->base.tb) & CF_PARALLEL) { gen_helper_exit_atomic(cpu_env); } else { TCGv_i32 r_asi = tcg_const_i32(da.asi); @@ -3351,7 +3350,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) if (cond == 8) { /* An unconditional trap ends the TB. */ - dc->is_br = 1; + dc->base.is_jmp = DISAS_NORETURN; goto jmp_insn; } else { /* A conditional trap falls through to the next insn. */ @@ -4331,7 +4330,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) save_state(dc); gen_op_next_insn(); tcg_gen_exit_tb(0); - dc->is_br = 1; + dc->base.is_jmp = DISAS_NORETURN; break; case 0x6: /* V9 wrfprs */ tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); @@ -4340,7 +4339,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) save_state(dc); gen_op_next_insn(); tcg_gen_exit_tb(0); - dc->is_br = 1; + dc->base.is_jmp = DISAS_NORETURN; break; case 0xf: /* V9 sir, nop if user */ #if !defined(CONFIG_USER_ONLY) @@ -4468,7 +4467,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) save_state(dc); gen_op_next_insn(); tcg_gen_exit_tb(0); - dc->is_br = 1; + dc->base.is_jmp = DISAS_NORETURN; #endif } break; @@ -4624,7 +4623,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) save_state(dc); gen_op_next_insn(); tcg_gen_exit_tb(0); - dc->is_br = 1; + dc->base.is_jmp = DISAS_NORETURN; break; case 1: // htstate // XXX gen_op_wrhtstate(); @@ -5690,7 +5689,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) } else if (dc->npc == JUMP_PC) { /* we can do a static jump */ gen_branch2(dc, dc->jump_pc[0], dc->jump_pc[1], cpu_cond); - dc->is_br = 1; + dc->base.is_jmp = DISAS_NORETURN; } else { dc->pc = dc->npc; dc->npc = dc->npc + 4; @@ -5738,99 +5737,92 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) } } -void gen_intermediate_code(CPUState *cs, TranslationBlock * tb) +static void sparc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) { + DisasContext *dc = container_of(dcbase, DisasContext, base); CPUSPARCState *env = cs->env_ptr; - target_ulong pc_start, last_pc; - DisasContext dc1, *dc = &dc1; - int num_insns; - int max_insns; - unsigned int insn; + int bound; - memset(dc, 0, sizeof(DisasContext)); - dc->tb = tb; - pc_start = tb->pc; - dc->pc = pc_start; - last_pc = dc->pc; - dc->npc = (target_ulong) tb->cs_base; + dc->pc = dc->base.pc_first; + dc->npc = (target_ulong)dc->base.tb->cs_base; dc->cc_op = CC_OP_DYNAMIC; - dc->mem_idx = tb->flags & TB_FLAG_MMU_MASK; + dc->mem_idx = dc->base.tb->flags & TB_FLAG_MMU_MASK; dc->def = &env->def; - dc->fpu_enabled = tb_fpu_enabled(tb->flags); - dc->address_mask_32bit = tb_am_enabled(tb->flags); - dc->singlestep = (cs->singlestep_enabled || singlestep); + dc->fpu_enabled = tb_fpu_enabled(dc->base.tb->flags); + dc->address_mask_32bit = tb_am_enabled(dc->base.tb->flags); #ifndef CONFIG_USER_ONLY - dc->supervisor = (tb->flags & TB_FLAG_SUPER) != 0; + dc->supervisor = (dc->base.tb->flags & TB_FLAG_SUPER) != 0; #endif #ifdef TARGET_SPARC64 dc->fprs_dirty = 0; - dc->asi = (tb->flags >> TB_FLAG_ASI_SHIFT) & 0xff; + dc->asi = (dc->base.tb->flags >> TB_FLAG_ASI_SHIFT) & 0xff; #ifndef CONFIG_USER_ONLY - dc->hypervisor = (tb->flags & TB_FLAG_HYPER) != 0; + dc->hypervisor = (dc->base.tb->flags & TB_FLAG_HYPER) != 0; #endif #endif + /* + * if we reach a page boundary, we stop generation so that the + * PC of a TT_TFAULT exception is always in the right page + */ + bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4; + dc->base.max_insns = MIN(dc->base.max_insns, bound); +} - num_insns = 0; - max_insns = tb_cflags(tb) & CF_COUNT_MASK; - if (max_insns == 0) { - max_insns = CF_COUNT_MASK; - } - if (max_insns > TCG_MAX_INSNS) { - max_insns = TCG_MAX_INSNS; - } +static void sparc_tr_tb_start(DisasContextBase *db, CPUState *cs) +{ +} - gen_tb_start(tb); - do { - if (dc->npc & JUMP_PC) { - assert(dc->jump_pc[1] == dc->pc + 4); - tcg_gen_insn_start(dc->pc, dc->jump_pc[0] | JUMP_PC); - } else { - tcg_gen_insn_start(dc->pc, dc->npc); - } - num_insns++; - last_pc = dc->pc; +static void sparc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) +{ + DisasContext *dc = container_of(dcbase, DisasContext, base); - if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) { - if (dc->pc != pc_start) { - save_state(dc); - } - gen_helper_debug(cpu_env); - tcg_gen_exit_tb(0); - dc->is_br = 1; - goto exit_gen_loop; - } + if (dc->npc & JUMP_PC) { + assert(dc->jump_pc[1] == dc->pc + 4); + tcg_gen_insn_start(dc->pc, dc->jump_pc[0] | JUMP_PC); + } else { + tcg_gen_insn_start(dc->pc, dc->npc); + } +} - if (num_insns == max_insns && (tb_cflags(tb) & CF_LAST_IO)) { - gen_io_start(); - } +static bool sparc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, + const CPUBreakpoint *bp) +{ + DisasContext *dc = container_of(dcbase, DisasContext, base); - insn = cpu_ldl_code(env, dc->pc); + if (dc->pc != dc->base.pc_first) { + save_state(dc); + } + gen_helper_debug(cpu_env); + tcg_gen_exit_tb(0); + dc->base.is_jmp = DISAS_NORETURN; + /* update pc_next so that the current instruction is included in tb->size */ + dc->base.pc_next += 4; + return true; +} - disas_sparc_insn(dc, insn); +static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) +{ + DisasContext *dc = container_of(dcbase, DisasContext, base); + CPUSPARCState *env = cs->env_ptr; + unsigned int insn; - if (dc->is_br) - break; - /* if the next PC is different, we abort now */ - if (dc->pc != (last_pc + 4)) - break; - /* if we reach a page boundary, we stop generation so that the - PC of a TT_TFAULT exception is always in the right page */ - if ((dc->pc & (TARGET_PAGE_SIZE - 1)) == 0) - break; - /* if single step mode, we generate only one instruction and - generate an exception */ - if (dc->singlestep) { - break; - } - } while (!tcg_op_buf_full() && - (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32) && - num_insns < max_insns); + insn = cpu_ldl_code(env, dc->pc); + dc->base.pc_next += 4; + disas_sparc_insn(dc, insn); - exit_gen_loop: - if (tb_cflags(tb) & CF_LAST_IO) { - gen_io_end(); + if (dc->base.is_jmp == DISAS_NORETURN) { + return; + } + if (dc->pc != dc->base.pc_next) { + dc->base.is_jmp = DISAS_TOO_MANY; } - if (!dc->is_br) { +} + +static void sparc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) +{ + DisasContext *dc = container_of(dcbase, DisasContext, base); + + if (dc->base.is_jmp != DISAS_NORETURN) { if (dc->pc != DYNAMIC_PC && (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) { /* static PC and NPC: we can use direct chaining */ @@ -5843,22 +5835,29 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock * tb) tcg_gen_exit_tb(0); } } - gen_tb_end(tb, num_insns); - - tb->size = last_pc + 4 - pc_start; - tb->icount = num_insns; - -#ifdef DEBUG_DISAS - if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) - && qemu_log_in_addr_range(pc_start)) { - qemu_log_lock(); - qemu_log("--------------\n"); - qemu_log("IN: %s\n", lookup_symbol(pc_start)); - log_target_disas(cs, pc_start, last_pc + 4 - pc_start); - qemu_log("\n"); - qemu_log_unlock(); - } -#endif +} + +static void sparc_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu) +{ + qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first)); + log_target_disas(cpu, dcbase->pc_first, dcbase->tb->size); +} + +static const TranslatorOps sparc_tr_ops = { + .init_disas_context = sparc_tr_init_disas_context, + .tb_start = sparc_tr_tb_start, + .insn_start = sparc_tr_insn_start, + .breakpoint_check = sparc_tr_breakpoint_check, + .translate_insn = sparc_tr_translate_insn, + .tb_stop = sparc_tr_tb_stop, + .disas_log = sparc_tr_disas_log, +}; + +void gen_intermediate_code(CPUState *cs, TranslationBlock *tb) +{ + DisasContext dc = {}; + + translator_loop(&sparc_tr_ops, &dc.base, cs, tb); } void sparc_tcg_init(void) diff --git a/target/tilegx/translate.c b/target/tilegx/translate.c index d63bf5bba3..6c53c5e767 100644 --- a/target/tilegx/translate.c +++ b/target/tilegx/translate.c @@ -2375,7 +2375,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) DisasContext ctx; DisasContext *dc = &ctx; uint64_t pc_start = tb->pc; - uint64_t next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; + uint64_t page_start = pc_start & TARGET_PAGE_MASK; int num_insns = 0; int max_insns = tb_cflags(tb) & CF_COUNT_MASK; @@ -2415,7 +2415,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) } dc->pc += TILEGX_BUNDLE_SIZE_IN_BYTES; if (num_insns >= max_insns - || dc->pc >= next_page_start + || (dc->pc - page_start >= TARGET_PAGE_SIZE) || tcg_op_buf_full()) { /* Ending the TB due to TB size or page boundary. Set PC. */ tcg_gen_movi_tl(cpu_pc, dc->pc); diff --git a/target/unicore32/translate.c b/target/unicore32/translate.c index 5b51f2166d..abe2ea8592 100644 --- a/target/unicore32/translate.c +++ b/target/unicore32/translate.c @@ -1875,7 +1875,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb) CPUUniCore32State *env = cs->env_ptr; DisasContext dc1, *dc = &dc1; target_ulong pc_start; - uint32_t next_page_start; + uint32_t page_start; int num_insns; int max_insns; @@ -1894,7 +1894,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb) cpu_F1s = tcg_temp_new_i32(); cpu_F0d = tcg_temp_new_i64(); cpu_F1d = tcg_temp_new_i64(); - next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; + page_start = pc_start & TARGET_PAGE_MASK; num_insns = 0; max_insns = tb_cflags(tb) & CF_COUNT_MASK; if (max_insns == 0) { @@ -1951,7 +1951,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb) } while (!dc->is_jmp && !tcg_op_buf_full() && !cs->singlestep_enabled && !singlestep && - dc->pc < next_page_start && + dc->pc - page_start < TARGET_PAGE_SIZE && num_insns < max_insns); if (tb_cflags(tb) & CF_LAST_IO) { diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index 4f6d03059f..aad496347d 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -1061,8 +1061,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb) int insn_count = 0; int max_insns = tb_cflags(tb) & CF_COUNT_MASK; uint32_t pc_start = tb->pc; - uint32_t next_page_start = - (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; + uint32_t page_start = pc_start & TARGET_PAGE_MASK; if (max_insns == 0) { max_insns = CF_COUNT_MASK; @@ -1162,9 +1161,9 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb) } } while (dc.is_jmp == DISAS_NEXT && insn_count < max_insns && - dc.pc < next_page_start && - dc.pc + xtensa_insn_len(env, &dc) <= next_page_start && - !tcg_op_buf_full()); + dc.pc - page_start < TARGET_PAGE_SIZE && + dc.pc - page_start + xtensa_insn_len(env, &dc) <= TARGET_PAGE_SIZE + && !tcg_op_buf_full()); done: reset_sar_tracker(&dc); if (dc.icount) { |