mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-04-28 18:36:29 +00:00
target: [tcg] Use a generic enum for DISAS_ values
Used later. An enum makes expected values explicit and bounds the value space of switches. Backports commit 77fc6f5e28667634916f114ae04c6029cd7b9c45 from qemu
This commit is contained in:
parent
4a5b1aec34
commit
3a196c62ae
|
@ -35,36 +35,6 @@ typedef abi_ulong tb_page_addr_t;
|
||||||
typedef ram_addr_t tb_page_addr_t;
|
typedef ram_addr_t tb_page_addr_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* DisasContext is_jmp field values
|
|
||||||
*
|
|
||||||
* is_jmp starts as DISAS_NEXT. The translator will keep processing
|
|
||||||
* instructions until an exit condition is reached. If we reach the
|
|
||||||
* exit condition and is_jmp is still DISAS_NEXT (because of some
|
|
||||||
* other condition) we simply "jump" to the next address.
|
|
||||||
* The remaining exit cases are:
|
|
||||||
*
|
|
||||||
* DISAS_JUMP - Only the PC was modified dynamically (e.g computed)
|
|
||||||
* DISAS_TB_JUMP - Only the PC was modified statically (e.g. branch)
|
|
||||||
*
|
|
||||||
* In these cases as long as the PC is updated we can chain to the
|
|
||||||
* next TB either by exiting the loop or looking up the next TB via
|
|
||||||
* the loookup helper.
|
|
||||||
*
|
|
||||||
* DISAS_UPDATE - CPU State was modified dynamically
|
|
||||||
*
|
|
||||||
* This covers any other CPU state which necessities us exiting the
|
|
||||||
* TCG code to the main run-loop. Typically this includes anything
|
|
||||||
* that might change the interrupt state.
|
|
||||||
*
|
|
||||||
* Individual translators may define additional exit cases to deal
|
|
||||||
* with per-target special conditions.
|
|
||||||
*/
|
|
||||||
#define DISAS_NEXT 0 /* next instruction can be analyzed */
|
|
||||||
#define DISAS_JUMP 1 /* only pc was modified dynamically */
|
|
||||||
#define DISAS_TB_JUMP 2 /* only pc was modified statically */
|
|
||||||
#define DISAS_UPDATE 3 /* cpu state was modified dynamically */
|
|
||||||
#define DISAS_NORETURN 4 /* the tb has already been exited */
|
|
||||||
|
|
||||||
#include "qemu/log.h"
|
#include "qemu/log.h"
|
||||||
|
|
||||||
void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb);
|
void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb);
|
||||||
|
|
40
qemu/include/exec/translator.h
Normal file
40
qemu/include/exec/translator.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Generic intermediate code generation.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016-2017 Lluís Vilanova <vilanova@ac.upc.edu>
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||||
|
* See the COPYING file in the top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EXEC__TRANSLATOR_H
|
||||||
|
#define EXEC__TRANSLATOR_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DisasJumpType:
|
||||||
|
* @DISAS_NEXT: Next instruction in program order.
|
||||||
|
* @DISAS_TOO_MANY: Too many instructions translated.
|
||||||
|
* @DISAS_NORETURN: Following code is dead.
|
||||||
|
* @DISAS_TARGET_*: Start of target-specific conditions.
|
||||||
|
*
|
||||||
|
* What instruction to disassemble next.
|
||||||
|
*/
|
||||||
|
typedef enum DisasJumpType {
|
||||||
|
DISAS_NEXT,
|
||||||
|
DISAS_TOO_MANY,
|
||||||
|
DISAS_NORETURN,
|
||||||
|
DISAS_TARGET_0,
|
||||||
|
DISAS_TARGET_1,
|
||||||
|
DISAS_TARGET_2,
|
||||||
|
DISAS_TARGET_3,
|
||||||
|
DISAS_TARGET_4,
|
||||||
|
DISAS_TARGET_5,
|
||||||
|
DISAS_TARGET_6,
|
||||||
|
DISAS_TARGET_7,
|
||||||
|
DISAS_TARGET_8,
|
||||||
|
DISAS_TARGET_9,
|
||||||
|
DISAS_TARGET_10,
|
||||||
|
DISAS_TARGET_11,
|
||||||
|
} DisasJumpType;
|
||||||
|
|
||||||
|
#endif /* EXEC__TRANSLATOR_H */
|
|
@ -4283,7 +4283,7 @@ static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
|
||||||
gen_set_pc_im(s, dest);
|
gen_set_pc_im(s, dest);
|
||||||
gen_goto_ptr(s);
|
gen_goto_ptr(s);
|
||||||
}
|
}
|
||||||
s->is_jmp = DISAS_TB_JUMP;
|
s->is_jmp = DISAS_NORETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void gen_jmp(DisasContext *s, uint32_t dest)
|
static inline void gen_jmp(DisasContext *s, uint32_t dest)
|
||||||
|
@ -4295,7 +4295,6 @@ static inline void gen_jmp(DisasContext *s, uint32_t dest)
|
||||||
gen_bx_im(s, dest);
|
gen_bx_im(s, dest);
|
||||||
} else {
|
} else {
|
||||||
gen_goto_tb(s, 0, dest);
|
gen_goto_tb(s, 0, dest);
|
||||||
s->is_jmp = DISAS_TB_JUMP;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef TARGET_ARM_TRANSLATE_H
|
#ifndef TARGET_ARM_TRANSLATE_H
|
||||||
#define TARGET_ARM_TRANSLATE_H
|
#define TARGET_ARM_TRANSLATE_H
|
||||||
|
|
||||||
|
#include "exec/translator.h"
|
||||||
|
|
||||||
/* internal defines */
|
/* internal defines */
|
||||||
typedef struct DisasContext {
|
typedef struct DisasContext {
|
||||||
target_ulong pc;
|
target_ulong pc;
|
||||||
|
@ -119,28 +121,31 @@ static void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* target-specific extra values for is_jmp */
|
/* target-specific extra values for is_jmp */
|
||||||
|
/* is_jmp field values */
|
||||||
|
#define DISAS_JUMP DISAS_TARGET_0 /* only pc was modified dynamically */
|
||||||
|
#define DISAS_UPDATE DISAS_TARGET_1 /* cpu state was modified dynamically */
|
||||||
/* These instructions trap after executing, so the A32/T32 decoder must
|
/* These instructions trap after executing, so the A32/T32 decoder must
|
||||||
* defer them until after the conditional execution state has been updated.
|
* defer them until after the conditional execution state has been updated.
|
||||||
* WFI also needs special handling when single-stepping.
|
* WFI also needs special handling when single-stepping.
|
||||||
*/
|
*/
|
||||||
#define DISAS_WFI 5
|
#define DISAS_WFI DISAS_TARGET_2
|
||||||
#define DISAS_SWI 6
|
#define DISAS_SWI DISAS_TARGET_3
|
||||||
/* WFE */
|
/* WFE */
|
||||||
#define DISAS_WFE 7
|
#define DISAS_WFE DISAS_TARGET_4
|
||||||
#define DISAS_HVC 8
|
#define DISAS_HVC DISAS_TARGET_5
|
||||||
#define DISAS_SMC 9
|
#define DISAS_SMC DISAS_TARGET_6
|
||||||
#define DISAS_YIELD 10
|
#define DISAS_YIELD DISAS_TARGET_7
|
||||||
/* M profile branch which might be an exception return (and so needs
|
/* M profile branch which might be an exception return (and so needs
|
||||||
* custom end-of-TB code)
|
* custom end-of-TB code)
|
||||||
*/
|
*/
|
||||||
#define DISAS_BX_EXCRET 11
|
#define DISAS_BX_EXCRET DISAS_TARGET_8
|
||||||
/* For instructions which want an immediate exit to the main loop,
|
/* For instructions which want an immediate exit to the main loop,
|
||||||
* as opposed to attempting to use lookup_and_goto_ptr. Unlike
|
* as opposed to attempting to use lookup_and_goto_ptr. Unlike
|
||||||
* DISAS_UPDATE this doesn't write the PC on exiting the translation
|
* DISAS_UPDATE this doesn't write the PC on exiting the translation
|
||||||
* loop so you need to ensure something (gen_a64_set_pc_im or runtime
|
* loop so you need to ensure something (gen_a64_set_pc_im or runtime
|
||||||
* helper) has done so before we reach return from cpu_tb_exec.
|
* helper) has done so before we reach return from cpu_tb_exec.
|
||||||
*/
|
*/
|
||||||
#define DISAS_EXIT 12
|
#define DISAS_EXIT DISAS_TARGET_9
|
||||||
|
|
||||||
#ifdef TARGET_AARCH64
|
#ifdef TARGET_AARCH64
|
||||||
void a64_translate_init(struct uc_struct *uc);
|
void a64_translate_init(struct uc_struct *uc);
|
||||||
|
|
|
@ -25,13 +25,13 @@
|
||||||
#include "exec/exec-all.h"
|
#include "exec/exec-all.h"
|
||||||
#include "tcg-op.h"
|
#include "tcg-op.h"
|
||||||
#include "exec/cpu_ldst.h"
|
#include "exec/cpu_ldst.h"
|
||||||
|
#include "exec/translator.h"
|
||||||
|
|
||||||
#include "exec/helper-proto.h"
|
#include "exec/helper-proto.h"
|
||||||
#include "exec/helper-gen.h"
|
#include "exec/helper-gen.h"
|
||||||
|
|
||||||
#include "uc_priv.h"
|
#include "uc_priv.h"
|
||||||
|
|
||||||
#define DISAS_TOO_MANY 5
|
|
||||||
|
|
||||||
#define PREFIX_REPZ 0x01
|
#define PREFIX_REPZ 0x01
|
||||||
#define PREFIX_REPNZ 0x02
|
#define PREFIX_REPNZ 0x02
|
||||||
#define PREFIX_LOCK 0x04
|
#define PREFIX_LOCK 0x04
|
||||||
|
@ -5045,7 +5045,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
|
||||||
gen_update_cc_op(s);
|
gen_update_cc_op(s);
|
||||||
gen_jmp_im(s, pc_start - s->cs_base);
|
gen_jmp_im(s, pc_start - s->cs_base);
|
||||||
gen_helper_hlt(tcg_ctx, cpu_env, tcg_const_i32(tcg_ctx, s->pc - pc_start));
|
gen_helper_hlt(tcg_ctx, cpu_env, tcg_const_i32(tcg_ctx, s->pc - pc_start));
|
||||||
s->is_jmp = DISAS_TB_JUMP;
|
s->is_jmp = DISAS_NORETURN;
|
||||||
return s->pc;
|
return s->pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9245,7 +9245,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
|
||||||
gen_tb_start(tcg_ctx);
|
gen_tb_start(tcg_ctx);
|
||||||
gen_jmp_im(dc, tb->pc - tb->cs_base);
|
gen_jmp_im(dc, tb->pc - tb->cs_base);
|
||||||
gen_helper_hlt(tcg_ctx, tcg_ctx->cpu_env, tcg_const_i32(tcg_ctx, 0));
|
gen_helper_hlt(tcg_ctx, tcg_ctx->cpu_env, tcg_const_i32(tcg_ctx, 0));
|
||||||
dc->is_jmp = DISAS_TB_JUMP;
|
dc->is_jmp = DISAS_NORETURN;
|
||||||
goto done_generating;
|
goto done_generating;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "tcg-op.h"
|
#include "tcg-op.h"
|
||||||
#include "qemu/log.h"
|
#include "qemu/log.h"
|
||||||
#include "exec/cpu_ldst.h"
|
#include "exec/cpu_ldst.h"
|
||||||
|
#include "exec/translator.h"
|
||||||
|
|
||||||
#include "exec/helper-proto.h"
|
#include "exec/helper-proto.h"
|
||||||
#include "exec/helper-gen.h"
|
#include "exec/helper-gen.h"
|
||||||
|
@ -158,7 +159,11 @@ static void do_writebacks(DisasContext *s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DISAS_JUMP_NEXT 4
|
/* is_jmp field values */
|
||||||
|
#define DISAS_JUMP DISAS_TARGET_0 /* only pc was modified dynamically */
|
||||||
|
#define DISAS_UPDATE DISAS_TARGET_1 /* cpu state was modified dynamically */
|
||||||
|
#define DISAS_TB_JUMP DISAS_TARGET_2 /* only pc was modified statically */
|
||||||
|
#define DISAS_JUMP_NEXT DISAS_TARGET_3
|
||||||
|
|
||||||
#if defined(CONFIG_USER_ONLY)
|
#if defined(CONFIG_USER_ONLY)
|
||||||
#define IS_USER(s) 1
|
#define IS_USER(s) 1
|
||||||
|
|
Loading…
Reference in a new issue