cpu-exec.c: avoid AREG0 use
Make functions take a parameter for CPUState instead of relying on global env. Pass CPUState pointer to TCG prologue, which moves it to AREG0. Thanks to Peter Maydell and Laurent Desnogues for the ARM prologue change. Revert the hacks to avoid AREG0 use on Sparc hosts. Move cpu_has_work() and cpu_pc_from_tb() from exec.h to cpu.h. Compile the file without HELPER_CFLAGS. Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
This commit is contained in:
parent
2b41f10e18
commit
cea5f9a28f
@ -94,7 +94,7 @@ tcg/tcg.o: cpu.h
|
||||
|
||||
# HELPER_CFLAGS is used for all the code compiled with static register
|
||||
# variables
|
||||
%_helper.o cpu-exec.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
|
||||
%_helper.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
|
||||
|
||||
# Note: this is a workaround. The real fix is to avoid compiling
|
||||
# cpu_signal_handler() in user-exec.c.
|
||||
|
74
cpu-exec.c
74
cpu-exec.c
@ -17,17 +17,11 @@
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "exec.h"
|
||||
#include "cpu.h"
|
||||
#include "disas.h"
|
||||
#include "tcg.h"
|
||||
#include "qemu-barrier.h"
|
||||
|
||||
#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
|
||||
// Work around ugly bugs in glibc that mangle global register contents
|
||||
#undef env
|
||||
#define env cpu_single_env
|
||||
#endif
|
||||
|
||||
int tb_invalidated_flag;
|
||||
|
||||
//#define CONFIG_DEBUG_EXEC
|
||||
@ -37,20 +31,18 @@ bool qemu_cpu_has_work(CPUState *env)
|
||||
return cpu_has_work(env);
|
||||
}
|
||||
|
||||
void cpu_loop_exit(CPUState *env1)
|
||||
void cpu_loop_exit(CPUState *env)
|
||||
{
|
||||
env1->current_tb = NULL;
|
||||
longjmp(env1->jmp_env, 1);
|
||||
env->current_tb = NULL;
|
||||
longjmp(env->jmp_env, 1);
|
||||
}
|
||||
|
||||
/* exit the current TB from a signal handler. The host registers are
|
||||
restored in a state compatible with the CPU emulator
|
||||
*/
|
||||
#if defined(CONFIG_SOFTMMU)
|
||||
void cpu_resume_from_signal(CPUState *env1, void *puc)
|
||||
void cpu_resume_from_signal(CPUState *env, void *puc)
|
||||
{
|
||||
env = env1;
|
||||
|
||||
/* XXX: restore cpu registers saved in host registers */
|
||||
|
||||
env->exception_index = -1;
|
||||
@ -60,7 +52,8 @@ void cpu_resume_from_signal(CPUState *env1, void *puc)
|
||||
|
||||
/* Execute the code without caching the generated code. An interpreter
|
||||
could be used if available. */
|
||||
static void cpu_exec_nocache(int max_cycles, TranslationBlock *orig_tb)
|
||||
static void cpu_exec_nocache(CPUState *env, int max_cycles,
|
||||
TranslationBlock *orig_tb)
|
||||
{
|
||||
unsigned long next_tb;
|
||||
TranslationBlock *tb;
|
||||
@ -74,7 +67,7 @@ static void cpu_exec_nocache(int max_cycles, TranslationBlock *orig_tb)
|
||||
max_cycles);
|
||||
env->current_tb = tb;
|
||||
/* execute the generated code */
|
||||
next_tb = tcg_qemu_tb_exec(tb->tc_ptr);
|
||||
next_tb = tcg_qemu_tb_exec(env, tb->tc_ptr);
|
||||
env->current_tb = NULL;
|
||||
|
||||
if ((next_tb & 3) == 2) {
|
||||
@ -86,7 +79,8 @@ static void cpu_exec_nocache(int max_cycles, TranslationBlock *orig_tb)
|
||||
tb_free(tb);
|
||||
}
|
||||
|
||||
static TranslationBlock *tb_find_slow(target_ulong pc,
|
||||
static TranslationBlock *tb_find_slow(CPUState *env,
|
||||
target_ulong pc,
|
||||
target_ulong cs_base,
|
||||
uint64_t flags)
|
||||
{
|
||||
@ -140,7 +134,7 @@ static TranslationBlock *tb_find_slow(target_ulong pc,
|
||||
return tb;
|
||||
}
|
||||
|
||||
static inline TranslationBlock *tb_find_fast(void)
|
||||
static inline TranslationBlock *tb_find_fast(CPUState *env)
|
||||
{
|
||||
TranslationBlock *tb;
|
||||
target_ulong cs_base, pc;
|
||||
@ -153,7 +147,7 @@ static inline TranslationBlock *tb_find_fast(void)
|
||||
tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
|
||||
if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
|
||||
tb->flags != flags)) {
|
||||
tb = tb_find_slow(pc, cs_base, flags);
|
||||
tb = tb_find_slow(env, pc, cs_base, flags);
|
||||
}
|
||||
return tb;
|
||||
}
|
||||
@ -186,31 +180,22 @@ static void cpu_handle_debug_exception(CPUState *env)
|
||||
|
||||
volatile sig_atomic_t exit_request;
|
||||
|
||||
int cpu_exec(CPUState *env1)
|
||||
int cpu_exec(CPUState *env)
|
||||
{
|
||||
volatile host_reg_t saved_env_reg;
|
||||
int ret, interrupt_request;
|
||||
TranslationBlock *tb;
|
||||
uint8_t *tc_ptr;
|
||||
unsigned long next_tb;
|
||||
|
||||
if (env1->halted) {
|
||||
if (!cpu_has_work(env1)) {
|
||||
if (env->halted) {
|
||||
if (!cpu_has_work(env)) {
|
||||
return EXCP_HALTED;
|
||||
}
|
||||
|
||||
env1->halted = 0;
|
||||
env->halted = 0;
|
||||
}
|
||||
|
||||
cpu_single_env = env1;
|
||||
|
||||
/* the access to env below is actually saving the global register's
|
||||
value, so that files not including target-xyz/exec.h are free to
|
||||
use it. */
|
||||
QEMU_BUILD_BUG_ON (sizeof (saved_env_reg) != sizeof (env));
|
||||
saved_env_reg = (host_reg_t) env;
|
||||
barrier();
|
||||
env = env1;
|
||||
cpu_single_env = env;
|
||||
|
||||
if (unlikely(exit_request)) {
|
||||
env->exit_request = 1;
|
||||
@ -246,11 +231,6 @@ int cpu_exec(CPUState *env1)
|
||||
/* prepare setjmp context for exception handling */
|
||||
for(;;) {
|
||||
if (setjmp(env->jmp_env) == 0) {
|
||||
#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
|
||||
#undef env
|
||||
env = cpu_single_env;
|
||||
#define env cpu_single_env
|
||||
#endif
|
||||
/* if an exception is pending, we execute it here */
|
||||
if (env->exception_index >= 0) {
|
||||
if (env->exception_index >= EXCP_INTERRUPT) {
|
||||
@ -336,11 +316,6 @@ int cpu_exec(CPUState *env1)
|
||||
env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
|
||||
intno = cpu_get_pic_interrupt(env);
|
||||
qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
|
||||
#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
|
||||
#undef env
|
||||
env = cpu_single_env;
|
||||
#define env cpu_single_env
|
||||
#endif
|
||||
do_interrupt_x86_hardirq(env, intno, 1);
|
||||
/* ensure that no TB jump will be modified as
|
||||
the program flow was changed */
|
||||
@ -547,7 +522,7 @@ int cpu_exec(CPUState *env1)
|
||||
}
|
||||
#endif /* DEBUG_DISAS || CONFIG_DEBUG_EXEC */
|
||||
spin_lock(&tb_lock);
|
||||
tb = tb_find_fast();
|
||||
tb = tb_find_fast(env);
|
||||
/* Note: we do it here to avoid a gcc bug on Mac OS X when
|
||||
doing it in tb_find_slow */
|
||||
if (tb_invalidated_flag) {
|
||||
@ -579,12 +554,7 @@ int cpu_exec(CPUState *env1)
|
||||
if (likely(!env->exit_request)) {
|
||||
tc_ptr = tb->tc_ptr;
|
||||
/* execute the generated code */
|
||||
#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
|
||||
#undef env
|
||||
env = cpu_single_env;
|
||||
#define env cpu_single_env
|
||||
#endif
|
||||
next_tb = tcg_qemu_tb_exec(tc_ptr);
|
||||
next_tb = tcg_qemu_tb_exec(env, tc_ptr);
|
||||
if ((next_tb & 3) == 2) {
|
||||
/* Instruction counter expired. */
|
||||
int insns_left;
|
||||
@ -605,7 +575,7 @@ int cpu_exec(CPUState *env1)
|
||||
} else {
|
||||
if (insns_left > 0) {
|
||||
/* Execute remaining instructions. */
|
||||
cpu_exec_nocache(insns_left, tb);
|
||||
cpu_exec_nocache(env, insns_left, tb);
|
||||
}
|
||||
env->exception_index = EXCP_INTERRUPT;
|
||||
next_tb = 0;
|
||||
@ -647,10 +617,6 @@ int cpu_exec(CPUState *env1)
|
||||
#error unsupported target CPU
|
||||
#endif
|
||||
|
||||
/* restore global registers */
|
||||
barrier();
|
||||
env = (void *) saved_env_reg;
|
||||
|
||||
/* fail safe : never use cpu_single_env outside cpu_exec() */
|
||||
cpu_single_env = NULL;
|
||||
return ret;
|
||||
|
@ -1846,15 +1846,18 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type,
|
||||
|
||||
static void tcg_target_qemu_prologue(TCGContext *s)
|
||||
{
|
||||
/* There is no need to save r7, it is used to store the address
|
||||
of the env structure and is not modified by GCC. */
|
||||
/* Calling convention requires us to save r4-r11 and lr;
|
||||
* save also r12 to maintain stack 8-alignment.
|
||||
*/
|
||||
|
||||
/* stmdb sp!, { r4 - r6, r8 - r11, lr } */
|
||||
tcg_out32(s, (COND_AL << 28) | 0x092d4f70);
|
||||
/* stmdb sp!, { r4 - r12, lr } */
|
||||
tcg_out32(s, (COND_AL << 28) | 0x092d5ff0);
|
||||
|
||||
tcg_out_bx(s, COND_AL, TCG_REG_R0);
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
|
||||
|
||||
tcg_out_bx(s, COND_AL, tcg_target_call_iarg_regs[1]);
|
||||
tb_ret_addr = s->code_ptr;
|
||||
|
||||
/* ldmia sp!, { r4 - r6, r8 - r11, pc } */
|
||||
tcg_out32(s, (COND_AL << 28) | 0x08bd8f70);
|
||||
/* ldmia sp!, { r4 - r12, pc } */
|
||||
tcg_out32(s, (COND_AL << 28) | 0x08bd9ff0);
|
||||
}
|
||||
|
@ -1596,7 +1596,7 @@ static int tcg_target_callee_save_regs[] = {
|
||||
TCG_REG_R14,
|
||||
TCG_REG_R15,
|
||||
TCG_REG_R16,
|
||||
/* R17 is the global env, so no need to save. */
|
||||
TCG_REG_R17, /* R17 is the global env. */
|
||||
TCG_REG_R18
|
||||
};
|
||||
|
||||
@ -1635,8 +1635,10 @@ static void tcg_target_qemu_prologue(TCGContext *s)
|
||||
}
|
||||
#endif
|
||||
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
|
||||
|
||||
/* Jump to TB, and adjust R18 to be the return address. */
|
||||
tcg_out32(s, INSN_BLE_SR4 | INSN_R2(TCG_REG_R26));
|
||||
tcg_out32(s, INSN_BLE_SR4 | INSN_R2(tcg_target_call_iarg_regs[1]));
|
||||
tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_R18, TCG_REG_R31);
|
||||
|
||||
/* Restore callee saved registers. */
|
||||
|
@ -1901,10 +1901,10 @@ static int tcg_target_callee_save_regs[] = {
|
||||
TCG_REG_RBX,
|
||||
TCG_REG_R12,
|
||||
TCG_REG_R13,
|
||||
/* TCG_REG_R14, */ /* Currently used for the global env. */
|
||||
TCG_REG_R14, /* Currently used for the global env. */
|
||||
TCG_REG_R15,
|
||||
#else
|
||||
/* TCG_REG_EBP, */ /* Currently used for the global env. */
|
||||
TCG_REG_EBP, /* Currently used for the global env. */
|
||||
TCG_REG_EBX,
|
||||
TCG_REG_ESI,
|
||||
TCG_REG_EDI,
|
||||
@ -1933,8 +1933,10 @@ static void tcg_target_qemu_prologue(TCGContext *s)
|
||||
stack_addend = frame_size - push_size;
|
||||
tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
|
||||
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
|
||||
|
||||
/* jmp *tb. */
|
||||
tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, tcg_target_call_iarg_regs[0]);
|
||||
tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, tcg_target_call_iarg_regs[1]);
|
||||
|
||||
/* TB epilogue */
|
||||
tb_ret_addr = s->code_ptr;
|
||||
|
@ -2292,7 +2292,7 @@ static void tcg_target_qemu_prologue(TCGContext *s)
|
||||
tcg_opc_m34(TCG_REG_P0, OPC_ALLOC_M34,
|
||||
TCG_REG_R33, 32, 24, 0),
|
||||
tcg_opc_i21(TCG_REG_P0, OPC_MOV_I21,
|
||||
TCG_REG_B6, TCG_REG_R32, 0),
|
||||
TCG_REG_B6, TCG_REG_R33, 0),
|
||||
tcg_opc_i22(TCG_REG_P0, OPC_MOV_I22,
|
||||
TCG_REG_R32, TCG_REG_B0));
|
||||
|
||||
@ -2308,7 +2308,8 @@ static void tcg_target_qemu_prologue(TCGContext *s)
|
||||
}
|
||||
|
||||
tcg_out_bundle(s, miB,
|
||||
tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
|
||||
tcg_opc_m48(TCG_REG_P0, OPC_MOV_I21,
|
||||
TCG_REG_AREG0, TCG_REG_R32, 0),
|
||||
tcg_opc_a4 (TCG_REG_P0, OPC_ADDS_A4,
|
||||
TCG_REG_R12, -frame_size, TCG_REG_R12),
|
||||
tcg_opc_b4 (TCG_REG_P0, OPC_BR_SPTK_MANY_B4, TCG_REG_B6));
|
||||
|
@ -1452,9 +1452,7 @@ static const TCGTargetOpDef mips_op_defs[] = {
|
||||
};
|
||||
|
||||
static int tcg_target_callee_save_regs[] = {
|
||||
#if 0 /* used for the global env (TCG_AREG0), so no need to save */
|
||||
TCG_REG_S0,
|
||||
#endif
|
||||
TCG_REG_S0, /* used for the global env (TCG_AREG0) */
|
||||
TCG_REG_S1,
|
||||
TCG_REG_S2,
|
||||
TCG_REG_S3,
|
||||
@ -1486,8 +1484,8 @@ static void tcg_target_qemu_prologue(TCGContext *s)
|
||||
}
|
||||
|
||||
/* Call generated code */
|
||||
tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_A0, 0);
|
||||
tcg_out_nop(s);
|
||||
tcg_out_opc_reg(s, OPC_JR, 0, tcg_target_call_iarg_regs[1]), 0);
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
|
||||
tb_ret_addr = s->code_ptr;
|
||||
|
||||
/* TB epilogue */
|
||||
|
@ -160,8 +160,7 @@ static const int tcg_target_callee_save_regs[] = {
|
||||
TCG_REG_R24,
|
||||
TCG_REG_R25,
|
||||
TCG_REG_R26,
|
||||
/* TCG_REG_R27, */ /* currently used for the global env, so no
|
||||
need to save */
|
||||
TCG_REG_R27, /* currently used for the global env */
|
||||
TCG_REG_R28,
|
||||
TCG_REG_R29,
|
||||
TCG_REG_R30,
|
||||
@ -939,7 +938,8 @@ static void tcg_target_qemu_prologue (TCGContext *s)
|
||||
}
|
||||
#endif
|
||||
|
||||
tcg_out32 (s, MTSPR | RS (3) | CTR);
|
||||
tcg_out_mov (s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
|
||||
tcg_out32 (s, MTSPR | RS (tcg_target_call_iarg_regs[1]) | CTR);
|
||||
tcg_out32 (s, BCCTR | BO_ALWAYS);
|
||||
tb_ret_addr = s->code_ptr;
|
||||
|
||||
|
@ -151,8 +151,7 @@ static const int tcg_target_callee_save_regs[] = {
|
||||
TCG_REG_R24,
|
||||
TCG_REG_R25,
|
||||
TCG_REG_R26,
|
||||
/* TCG_REG_R27, */ /* currently used for the global env, so no
|
||||
need to save */
|
||||
TCG_REG_R27, /* currently used for the global env */
|
||||
TCG_REG_R28,
|
||||
TCG_REG_R29,
|
||||
TCG_REG_R30,
|
||||
@ -905,7 +904,8 @@ static void tcg_target_qemu_prologue (TCGContext *s)
|
||||
}
|
||||
#endif
|
||||
|
||||
tcg_out32 (s, MTSPR | RS (3) | CTR);
|
||||
tcg_out_mov (s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
|
||||
tcg_out32 (s, MTSPR | RS (tcg_target_call_iarg_regs[1]) | CTR);
|
||||
tcg_out32 (s, BCCTR | BO_ALWAYS);
|
||||
|
||||
/* Epilogue */
|
||||
|
@ -2306,8 +2306,9 @@ static void tcg_target_qemu_prologue(TCGContext *s)
|
||||
tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
|
||||
}
|
||||
|
||||
/* br %r2 (go to TB) */
|
||||
tcg_out_insn(s, RR, BCR, S390_CC_ALWAYS, TCG_REG_R2);
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
|
||||
/* br %r3 (go to TB) */
|
||||
tcg_out_insn(s, RR, BCR, S390_CC_ALWAYS, tcg_target_call_iarg_regs[1]);
|
||||
|
||||
tb_ret_addr = s->code_ptr;
|
||||
|
||||
|
@ -695,9 +695,9 @@ static void tcg_target_qemu_prologue(TCGContext *s)
|
||||
{
|
||||
tcg_out32(s, SAVE | INSN_RD(TCG_REG_O6) | INSN_RS1(TCG_REG_O6) |
|
||||
INSN_IMM13(-TCG_TARGET_STACK_MINFRAME));
|
||||
tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I0) |
|
||||
tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I1) |
|
||||
INSN_RS2(TCG_REG_G0));
|
||||
tcg_out_nop(s);
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, TCG_REG_I0);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SOFTMMU)
|
||||
|
@ -515,8 +515,9 @@ TCGv_i64 tcg_const_local_i64(int64_t val);
|
||||
|
||||
extern uint8_t code_gen_prologue[];
|
||||
#if defined(_ARCH_PPC) && !defined(_ARCH_PPC64)
|
||||
#define tcg_qemu_tb_exec(tb_ptr) \
|
||||
((long REGPARM __attribute__ ((longcall)) (*)(void *))code_gen_prologue)(tb_ptr)
|
||||
#define tcg_qemu_tb_exec(env, tb_ptr) \
|
||||
((long REGPARM __attribute__ ((longcall)) (*)(void *, void *))code_gen_prologue)(env, tb_ptr)
|
||||
#else
|
||||
#define tcg_qemu_tb_exec(tb_ptr) ((long REGPARM (*)(void *))code_gen_prologue)(tb_ptr)
|
||||
#define tcg_qemu_tb_exec(env, tb_ptr) \
|
||||
((long REGPARM (*)(void *, void *))code_gen_prologue)(env, tb_ptr)
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user