diff options
Diffstat (limited to 'target/sparc/cpu.c')
-rw-r--r-- | target/sparc/cpu.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c index a65a646..373a335 100644 --- a/target/sparc/cpu.c +++ b/target/sparc/cpu.c @@ -23,10 +23,12 @@ #include "qemu/module.h" #include "qemu/qemu-print.h" #include "exec/exec-all.h" +#include "exec/translation-block.h" #include "hw/qdev-properties.h" #include "qapi/visitor.h" #include "tcg/tcg.h" #include "fpu/softfloat.h" +#include "target/sparc/translate.h" //#define DEBUG_FEATURES @@ -713,6 +715,67 @@ static void sparc_cpu_synchronize_from_tb(CPUState *cs, cpu->env.npc = tb->cs_base; } +void cpu_get_tb_cpu_state(CPUSPARCState *env, vaddr *pc, + uint64_t *cs_base, uint32_t *pflags) +{ + uint32_t flags; + *pc = env->pc; + *cs_base = env->npc; + flags = cpu_mmu_index(env_cpu(env), false); +#ifndef CONFIG_USER_ONLY + if (cpu_supervisor_mode(env)) { + flags |= TB_FLAG_SUPER; + } +#endif +#ifdef TARGET_SPARC64 +#ifndef CONFIG_USER_ONLY + if (cpu_hypervisor_mode(env)) { + flags |= TB_FLAG_HYPER; + } +#endif + if (env->pstate & PS_AM) { + flags |= TB_FLAG_AM_ENABLED; + } + if ((env->pstate & PS_PEF) && (env->fprs & FPRS_FEF)) { + flags |= TB_FLAG_FPU_ENABLED; + } + flags |= env->asi << TB_FLAG_ASI_SHIFT; +#else + if (env->psref) { + flags |= TB_FLAG_FPU_ENABLED; + } +#ifndef CONFIG_USER_ONLY + if (env->fsr_qne) { + flags |= TB_FLAG_FSR_QNE; + } +#endif /* !CONFIG_USER_ONLY */ +#endif /* TARGET_SPARC64 */ + *pflags = flags; +} + +static void sparc_restore_state_to_opc(CPUState *cs, + const TranslationBlock *tb, + const uint64_t *data) +{ + CPUSPARCState *env = cpu_env(cs); + target_ulong pc = data[0]; + target_ulong npc = data[1]; + + env->pc = pc; + if (npc == DYNAMIC_PC) { + /* dynamic NPC: already stored */ + } else if (npc & JUMP_PC) { + /* jump PC: use 'cond' and the jump targets of the translation */ + if (env->cond) { + env->npc = npc & ~3; + } else { + env->npc = pc + 4; + } + } else { + env->npc = npc; + } +} + static bool sparc_cpu_has_work(CPUState *cs) { return (cs->interrupt_request & CPU_INTERRUPT_HARD) && |