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:
Blue Swirl 2011-05-15 16:03:25 +00:00
parent 2b41f10e18
commit cea5f9a28f
12 changed files with 61 additions and 87 deletions

View File

@ -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.

View File

@ -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;

View File

@ -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);
}

View File

@ -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. */

View File

@ -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;

View File

@ -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));

View File

@ -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 */

View File

@ -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;

View File

@ -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 */

View File

@ -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;

View File

@ -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)

View File

@ -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