mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2024-12-23 16:15:36 +00:00
target-arm: implement SCTLR.B, drop bswap_code
bswap_code is a CPU property of sorts ("is the iside endianness the opposite way round to TARGET_WORDS_BIGENDIAN?") but it is not the actual CPU state involved here which is SCTLR.B (set for BE32 binaries, clear for BE8). Replace bswap_code with SCTLR.B, and pass that to arm_ld*_code. The next patches will make data fetches honor both SCTLR.B and CPSR.E appropriately. Backports commit f9fd40ebe4f55e0048e002925b8d65e66d56e7a7 from qemu
This commit is contained in:
parent
64a9bec68a
commit
ec15ee10d0
|
@ -25,10 +25,10 @@
|
|||
|
||||
/* Load an instruction and return it in the standard little-endian order */
|
||||
static inline uint32_t arm_ldl_code(CPUARMState *env, target_ulong addr,
|
||||
bool do_swap)
|
||||
bool sctlr_b)
|
||||
{
|
||||
uint32_t insn = cpu_ldl_code(env, addr);
|
||||
if (do_swap) {
|
||||
if (bswap_code(sctlr_b)) {
|
||||
return bswap32(insn);
|
||||
}
|
||||
return insn;
|
||||
|
@ -36,10 +36,10 @@ static inline uint32_t arm_ldl_code(CPUARMState *env, target_ulong addr,
|
|||
|
||||
/* Ditto, for a halfword (Thumb) instruction */
|
||||
static inline uint16_t arm_lduw_code(CPUARMState *env, target_ulong addr,
|
||||
bool do_swap)
|
||||
bool sctlr_b)
|
||||
{
|
||||
uint16_t insn = cpu_lduw_code(env, addr);
|
||||
if (do_swap) {
|
||||
if (bswap_code(sctlr_b)) {
|
||||
return bswap16(insn);
|
||||
}
|
||||
return insn;
|
||||
|
|
|
@ -481,9 +481,6 @@ typedef struct CPUARMState {
|
|||
uint32_t cregs[16];
|
||||
} iwmmxt;
|
||||
|
||||
/* For mixed endian mode. */
|
||||
bool bswap_code;
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
/* For usermode syscall translation. */
|
||||
int eabi;
|
||||
|
@ -1951,8 +1948,8 @@ static inline bool arm_singlestep_active(CPUARMState *env)
|
|||
#define ARM_TBFLAG_VFPEN_MASK (1 << ARM_TBFLAG_VFPEN_SHIFT)
|
||||
#define ARM_TBFLAG_CONDEXEC_SHIFT 8
|
||||
#define ARM_TBFLAG_CONDEXEC_MASK (0xff << ARM_TBFLAG_CONDEXEC_SHIFT)
|
||||
#define ARM_TBFLAG_BSWAP_CODE_SHIFT 16
|
||||
#define ARM_TBFLAG_BSWAP_CODE_MASK (1 << ARM_TBFLAG_BSWAP_CODE_SHIFT)
|
||||
#define ARM_TBFLAG_SCTLR_B_SHIFT 16
|
||||
#define ARM_TBFLAG_SCTLR_B_MASK (1 << ARM_TBFLAG_SCTLR_B_SHIFT)
|
||||
/* We store the bottom two bits of the CPAR as TB flags and handle
|
||||
* checks on the other bits at runtime
|
||||
*/
|
||||
|
@ -1988,13 +1985,34 @@ static inline bool arm_singlestep_active(CPUARMState *env)
|
|||
(((F) & ARM_TBFLAG_VFPEN_MASK) >> ARM_TBFLAG_VFPEN_SHIFT)
|
||||
#define ARM_TBFLAG_CONDEXEC(F) \
|
||||
(((F) & ARM_TBFLAG_CONDEXEC_MASK) >> ARM_TBFLAG_CONDEXEC_SHIFT)
|
||||
#define ARM_TBFLAG_BSWAP_CODE(F) \
|
||||
(((F) & ARM_TBFLAG_BSWAP_CODE_MASK) >> ARM_TBFLAG_BSWAP_CODE_SHIFT)
|
||||
#define ARM_TBFLAG_SCTLR_B(F) \
|
||||
(((F) & ARM_TBFLAG_SCTLR_B_MASK) >> ARM_TBFLAG_SCTLR_B_SHIFT)
|
||||
#define ARM_TBFLAG_XSCALE_CPAR(F) \
|
||||
(((F) & ARM_TBFLAG_XSCALE_CPAR_MASK) >> ARM_TBFLAG_XSCALE_CPAR_SHIFT)
|
||||
#define ARM_TBFLAG_NS(F) \
|
||||
(((F) & ARM_TBFLAG_NS_MASK) >> ARM_TBFLAG_NS_SHIFT)
|
||||
|
||||
static inline bool bswap_code(bool sctlr_b)
|
||||
{
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
/* BE8 (SCTLR.B = 0, TARGET_WORDS_BIGENDIAN = 1) is mixed endian.
|
||||
* The invalid combination SCTLR.B=1/CPSR.E=1/TARGET_WORDS_BIGENDIAN=0
|
||||
* would also end up as a mixed-endian mode with BE code, LE data.
|
||||
*/
|
||||
return
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
1 ^
|
||||
#endif
|
||||
sctlr_b;
|
||||
#else
|
||||
/* We do not implement BE32 mode for system-mode emulation, but
|
||||
* anyway it would always do little-endian accesses with
|
||||
* TARGET_WORDS_BIGENDIAN = 0.
|
||||
*/
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Return the exception level to which FP-disabled exceptions should
|
||||
* be taken, or 0 if FP is enabled.
|
||||
*/
|
||||
|
@ -2060,6 +2078,19 @@ static inline int fp_exception_el(CPUARMState *env)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline bool arm_sctlr_b(CPUARMState *env)
|
||||
{
|
||||
return
|
||||
/* We need not implement SCTLR.ITD in user-mode emulation, so
|
||||
* let linux-user ignore the fact that it conflicts with SCTLR_B.
|
||||
* This lets people run BE32 binaries with "-cpu any".
|
||||
*/
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
!arm_feature(env, ARM_FEATURE_V7) &&
|
||||
#endif
|
||||
(env->cp15.sctlr_el[1] & SCTLR_B) != 0;
|
||||
}
|
||||
|
||||
static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
|
||||
target_ulong *cs_base, int *flags)
|
||||
{
|
||||
|
@ -2072,7 +2103,7 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
|
|||
| (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
|
||||
| (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
|
||||
| (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT)
|
||||
| (env->bswap_code << ARM_TBFLAG_BSWAP_CODE_SHIFT);
|
||||
| (arm_sctlr_b(env) << ARM_TBFLAG_SCTLR_B_SHIFT);
|
||||
if (!(access_secure_reg(env))) {
|
||||
*flags |= ARM_TBFLAG_NS_MASK;
|
||||
}
|
||||
|
|
|
@ -5094,7 +5094,7 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
|
|||
#if 0
|
||||
if (semihosting_enabled) {
|
||||
int nr;
|
||||
nr = arm_lduw_code(env, env->regs[15], env->bswap_code) & 0xff;
|
||||
nr = arm_lduw_code(env, env->regs[15], arm_sctlr_b(env)) & 0xff;
|
||||
if (nr == 0xab) {
|
||||
env->regs[15] += 2;
|
||||
qemu_log_mask(CPU_LOG_INT,
|
||||
|
@ -5640,13 +5640,13 @@ static inline bool check_for_semihosting(CPUState *cs)
|
|||
case EXCP_SWI:
|
||||
/* Check for semihosting interrupt. */
|
||||
if (env->thumb) {
|
||||
imm = arm_lduw_code(env, env->regs[15] - 2, env->bswap_code)
|
||||
imm = arm_lduw_code(env, env->regs[15] - 2, arm_sctlr_b(env))
|
||||
& 0xff;
|
||||
if (imm == 0xab) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
imm = arm_ldl_code(env, env->regs[15] - 4, env->bswap_code)
|
||||
imm = arm_ldl_code(env, env->regs[15] - 4, arm_sctlr_b(env))
|
||||
& 0xffffff;
|
||||
if (imm == 0x123456) {
|
||||
break;
|
||||
|
@ -5656,7 +5656,7 @@ static inline bool check_for_semihosting(CPUState *cs)
|
|||
case EXCP_BKPT:
|
||||
/* See if this is a semihosting syscall. */
|
||||
if (env->thumb) {
|
||||
imm = arm_lduw_code(env, env->regs[15], env->bswap_code)
|
||||
imm = arm_lduw_code(env, env->regs[15], arm_sctlr_b(env))
|
||||
& 0xff;
|
||||
if (imm == 0xab) {
|
||||
env->regs[15] += 2;
|
||||
|
|
|
@ -11175,7 +11175,7 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s)
|
|||
return;
|
||||
}
|
||||
|
||||
insn = arm_ldl_code(env, s->pc, s->bswap_code);
|
||||
insn = arm_ldl_code(env, s->pc, s->sctlr_b);
|
||||
s->insn = insn;
|
||||
s->pc += 4;
|
||||
|
||||
|
@ -11250,11 +11250,7 @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
|
|||
dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
|
||||
!arm_el_is_aa64(env, 3);
|
||||
dc->thumb = 0;
|
||||
#if defined(TARGET_WORDS_BIGENDIAN)
|
||||
dc->bswap_code = 1;
|
||||
#else
|
||||
dc->bswap_code = 0;
|
||||
#endif
|
||||
dc->sctlr_b = 0;
|
||||
dc->condexec_mask = 0;
|
||||
dc->condexec_cond = 0;
|
||||
dc->mmu_idx = ARM_TBFLAG_MMUIDX(tb->flags);
|
||||
|
|
|
@ -7909,7 +7909,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) // qq
|
|||
if ((insn & 0x0ffffdff) == 0x01010000) {
|
||||
ARCH(6);
|
||||
/* setend */
|
||||
if (((insn >> 9) & 1) != s->bswap_code) {
|
||||
if (((insn >> 9) & 1) != bswap_code(s->sctlr_b)) {
|
||||
/* Dynamic endianness switching not implemented. */
|
||||
qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
|
||||
goto illegal_op;
|
||||
|
@ -9427,7 +9427,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
|
|||
/* Fall through to 32-bit decode. */
|
||||
}
|
||||
|
||||
insn = arm_lduw_code(env, s->pc, s->bswap_code);
|
||||
insn = arm_lduw_code(env, s->pc, s->sctlr_b);
|
||||
s->pc += 2;
|
||||
insn |= (uint32_t)insn_hw1 << 16;
|
||||
|
||||
|
@ -10677,7 +10677,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) // qq
|
|||
}
|
||||
}
|
||||
|
||||
insn = arm_lduw_code(env, s->pc, s->bswap_code);
|
||||
insn = arm_lduw_code(env, s->pc, s->sctlr_b);
|
||||
|
||||
// Unicorn: trace this instruction on request
|
||||
if (HOOK_EXISTS_BOUNDED(s->uc, UC_HOOK_CODE, s->pc)) {
|
||||
|
@ -11268,7 +11268,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) // qq
|
|||
case 2:
|
||||
/* setend */
|
||||
ARCH(6);
|
||||
if (((insn >> 3) & 1) != s->bswap_code) {
|
||||
if (((insn >> 3) & 1) != bswap_code(s->sctlr_b)) {
|
||||
/* Dynamic endianness switching not implemented. */
|
||||
qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
|
||||
goto illegal_op;
|
||||
|
@ -11423,7 +11423,7 @@ static bool insn_crosses_page(CPUARMState *env, DisasContext *s)
|
|||
}
|
||||
|
||||
/* This must be a Thumb insn */
|
||||
insn = arm_lduw_code(env, s->pc, s->bswap_code);
|
||||
insn = arm_lduw_code(env, s->pc, s->sctlr_b);
|
||||
|
||||
if ((insn >> 11) >= 0x1d) {
|
||||
/* Top five bits 0b11101 / 0b11110 / 0b11111 : this is the
|
||||
|
@ -11481,7 +11481,7 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
|
|||
dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
|
||||
!arm_el_is_aa64(env, 3);
|
||||
dc->thumb = ARM_TBFLAG_THUMB(tb->flags); // qq
|
||||
dc->bswap_code = ARM_TBFLAG_BSWAP_CODE(tb->flags);
|
||||
dc->sctlr_b = ARM_TBFLAG_SCTLR_B(tb->flags);
|
||||
dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
|
||||
dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
|
||||
dc->mmu_idx = ARM_TBFLAG_MMUIDX(tb->flags);
|
||||
|
@ -11687,7 +11687,7 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
|
|||
// imitate WFI instruction to halt emulation
|
||||
dc->is_jmp = DISAS_WFI;
|
||||
} else {
|
||||
insn = arm_ldl_code(env, dc->pc, dc->bswap_code);
|
||||
insn = arm_ldl_code(env, dc->pc, dc->sctlr_b);
|
||||
dc->pc += 4;
|
||||
disas_arm_insn(dc, insn);
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ typedef struct DisasContext {
|
|||
struct TranslationBlock *tb;
|
||||
int singlestep_enabled;
|
||||
int thumb;
|
||||
int bswap_code;
|
||||
int sctlr_b;
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
int user;
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue