* [Qemu-devel] [PATCH v2 01/18] linux-user: arm: fix coding style for some linux-user signal functions
2016-03-02 6:56 [Qemu-devel] [PATCH v2 00/18] ARM big-endian and setend support Peter Crosthwaite
@ 2016-03-02 6:56 ` Peter Crosthwaite
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 02/18] linux-user: arm: pass env to get_user_code_* Peter Crosthwaite
` (17 subsequent siblings)
18 siblings, 0 replies; 24+ messages in thread
From: Peter Crosthwaite @ 2016-03-02 6:56 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, Peter Crosthwaite, sw, Andrew.Baumann,
alistair.francis, sridhar_kulk, qemu-arm, pbonzini, piotr.krol
From: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
---
TEST result: 0 (log@ logs/qemu-armeb-BE32-)
TEST result: 0 (log@ logs/qemu-armeb-BE8-)
TEST result: 0 (log@ logs/qemu-arm-LE-)
TEST result: 0 (log@ logs/qemu-system-arm-LE-)
linux-user/signal.c | 110 ++++++++++++++++++++++++++--------------------------
1 file changed, 56 insertions(+), 54 deletions(-)
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 962111c..96e86c0 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1536,82 +1536,84 @@ static void
setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
CPUARMState *env, abi_ulong mask)
{
- __put_user(env->regs[0], &sc->arm_r0);
- __put_user(env->regs[1], &sc->arm_r1);
- __put_user(env->regs[2], &sc->arm_r2);
- __put_user(env->regs[3], &sc->arm_r3);
- __put_user(env->regs[4], &sc->arm_r4);
- __put_user(env->regs[5], &sc->arm_r5);
- __put_user(env->regs[6], &sc->arm_r6);
- __put_user(env->regs[7], &sc->arm_r7);
- __put_user(env->regs[8], &sc->arm_r8);
- __put_user(env->regs[9], &sc->arm_r9);
- __put_user(env->regs[10], &sc->arm_r10);
- __put_user(env->regs[11], &sc->arm_fp);
- __put_user(env->regs[12], &sc->arm_ip);
- __put_user(env->regs[13], &sc->arm_sp);
- __put_user(env->regs[14], &sc->arm_lr);
- __put_user(env->regs[15], &sc->arm_pc);
+ __put_user(env->regs[0], &sc->arm_r0);
+ __put_user(env->regs[1], &sc->arm_r1);
+ __put_user(env->regs[2], &sc->arm_r2);
+ __put_user(env->regs[3], &sc->arm_r3);
+ __put_user(env->regs[4], &sc->arm_r4);
+ __put_user(env->regs[5], &sc->arm_r5);
+ __put_user(env->regs[6], &sc->arm_r6);
+ __put_user(env->regs[7], &sc->arm_r7);
+ __put_user(env->regs[8], &sc->arm_r8);
+ __put_user(env->regs[9], &sc->arm_r9);
+ __put_user(env->regs[10], &sc->arm_r10);
+ __put_user(env->regs[11], &sc->arm_fp);
+ __put_user(env->regs[12], &sc->arm_ip);
+ __put_user(env->regs[13], &sc->arm_sp);
+ __put_user(env->regs[14], &sc->arm_lr);
+ __put_user(env->regs[15], &sc->arm_pc);
#ifdef TARGET_CONFIG_CPU_32
- __put_user(cpsr_read(env), &sc->arm_cpsr);
+ __put_user(cpsr_read(env), &sc->arm_cpsr);
#endif
- __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
- __put_user(/* current->thread.error_code */ 0, &sc->error_code);
- __put_user(/* current->thread.address */ 0, &sc->fault_address);
- __put_user(mask, &sc->oldmask);
+ __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
+ __put_user(/* current->thread.error_code */ 0, &sc->error_code);
+ __put_user(/* current->thread.address */ 0, &sc->fault_address);
+ __put_user(mask, &sc->oldmask);
}
static inline abi_ulong
get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
{
- unsigned long sp = regs->regs[13];
+ unsigned long sp = regs->regs[13];
- /*
- * This is the X/Open sanctioned signal stack switching.
- */
- if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp))
- sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
- /*
- * ATPCS B01 mandates 8-byte alignment
- */
- return (sp - framesize) & ~7;
+ /*
+ * This is the X/Open sanctioned signal stack switching.
+ */
+ if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
+ sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
+ }
+ /*
+ * ATPCS B01 mandates 8-byte alignment
+ */
+ return (sp - framesize) & ~7;
}
static void
setup_return(CPUARMState *env, struct target_sigaction *ka,
abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
{
- abi_ulong handler = ka->_sa_handler;
- abi_ulong retcode;
- int thumb = handler & 1;
- uint32_t cpsr = cpsr_read(env);
+ abi_ulong handler = ka->_sa_handler;
+ abi_ulong retcode;
+ int thumb = handler & 1;
+ uint32_t cpsr = cpsr_read(env);
- cpsr &= ~CPSR_IT;
- if (thumb) {
- cpsr |= CPSR_T;
- } else {
- cpsr &= ~CPSR_T;
- }
+ cpsr &= ~CPSR_IT;
+ if (thumb) {
+ cpsr |= CPSR_T;
+ } else {
+ cpsr &= ~CPSR_T;
+ }
- if (ka->sa_flags & TARGET_SA_RESTORER) {
- retcode = ka->sa_restorer;
- } else {
- unsigned int idx = thumb;
+ if (ka->sa_flags & TARGET_SA_RESTORER) {
+ retcode = ka->sa_restorer;
+ } else {
+ unsigned int idx = thumb;
- if (ka->sa_flags & TARGET_SA_SIGINFO)
- idx += 2;
+ if (ka->sa_flags & TARGET_SA_SIGINFO) {
+ idx += 2;
+ }
__put_user(retcodes[idx], rc);
- retcode = rc_addr + thumb;
- }
+ retcode = rc_addr + thumb;
+ }
- env->regs[0] = usig;
- env->regs[13] = frame_addr;
- env->regs[14] = retcode;
- env->regs[15] = handler & (thumb ? ~1 : ~3);
- cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);
+ env->regs[0] = usig;
+ env->regs[13] = frame_addr;
+ env->regs[14] = retcode;
+ env->regs[15] = handler & (thumb ? ~1 : ~3);
+ cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);
}
static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
--
1.9.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH v2 02/18] linux-user: arm: pass env to get_user_code_*
2016-03-02 6:56 [Qemu-devel] [PATCH v2 00/18] ARM big-endian and setend support Peter Crosthwaite
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 01/18] linux-user: arm: fix coding style for some linux-user signal functions Peter Crosthwaite
@ 2016-03-02 6:56 ` Peter Crosthwaite
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 03/18] target-arm: implement SCTLR.B, drop bswap_code Peter Crosthwaite
` (16 subsequent siblings)
18 siblings, 0 replies; 24+ messages in thread
From: Peter Crosthwaite @ 2016-03-02 6:56 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, Peter Crosthwaite, sw, Andrew.Baumann,
alistair.francis, sridhar_kulk, qemu-arm, pbonzini, piotr.krol
From: Paolo Bonzini <pbonzini@redhat.com>
This matches the idiom used by get_user_data_* later in the series,
and will help when bswap_code will be replaced by SCTLR.B.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
---
TEST result: 0 (log@ logs/qemu-armeb-BE32-)
TEST result: 0 (log@ logs/qemu-armeb-BE8-)
TEST result: 0 (log@ logs/qemu-arm-LE-)
TEST result: 0 (log@ logs/qemu-system-arm-LE-)
linux-user/main.c | 20 +++++++++-----------
1 file changed, 9 insertions(+), 11 deletions(-)
diff --git a/linux-user/main.c b/linux-user/main.c
index 700724e..bcb9f66 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -435,17 +435,17 @@ void cpu_loop(CPUX86State *env)
#ifdef TARGET_ARM
-#define get_user_code_u32(x, gaddr, doswap) \
+#define get_user_code_u32(x, gaddr, env) \
({ abi_long __r = get_user_u32((x), (gaddr)); \
- if (!__r && (doswap)) { \
+ if (!__r && (env)->bswap_code) { \
(x) = bswap32(x); \
} \
__r; \
})
-#define get_user_code_u16(x, gaddr, doswap) \
+#define get_user_code_u16(x, gaddr, env) \
({ abi_long __r = get_user_u16((x), (gaddr)); \
- if (!__r && (doswap)) { \
+ if (!__r && (env)->bswap_code) { \
(x) = bswap16(x); \
} \
__r; \
@@ -692,7 +692,7 @@ void cpu_loop(CPUARMState *env)
/* we handle the FPU emulation here, as Linux */
/* we get the opcode */
/* FIXME - what to do if get_user() fails? */
- get_user_code_u32(opcode, env->regs[15], env->bswap_code);
+ get_user_code_u32(opcode, env->regs[15], env);
rc = EmulateAll(opcode, &ts->fpa, env);
if (rc == 0) { /* illegal instruction */
@@ -762,25 +762,23 @@ void cpu_loop(CPUARMState *env)
if (trapnr == EXCP_BKPT) {
if (env->thumb) {
/* FIXME - what to do if get_user() fails? */
- get_user_code_u16(insn, env->regs[15], env->bswap_code);
+ get_user_code_u16(insn, env->regs[15], env);
n = insn & 0xff;
env->regs[15] += 2;
} else {
/* FIXME - what to do if get_user() fails? */
- get_user_code_u32(insn, env->regs[15], env->bswap_code);
+ get_user_code_u32(insn, env->regs[15], env);
n = (insn & 0xf) | ((insn >> 4) & 0xff0);
env->regs[15] += 4;
}
} else {
if (env->thumb) {
/* FIXME - what to do if get_user() fails? */
- get_user_code_u16(insn, env->regs[15] - 2,
- env->bswap_code);
+ get_user_code_u16(insn, env->regs[15] - 2, env);
n = insn & 0xff;
} else {
/* FIXME - what to do if get_user() fails? */
- get_user_code_u32(insn, env->regs[15] - 4,
- env->bswap_code);
+ get_user_code_u32(insn, env->regs[15] - 4, env);
n = insn & 0xffffff;
}
}
--
1.9.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH v2 03/18] target-arm: implement SCTLR.B, drop bswap_code
2016-03-02 6:56 [Qemu-devel] [PATCH v2 00/18] ARM big-endian and setend support Peter Crosthwaite
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 01/18] linux-user: arm: fix coding style for some linux-user signal functions Peter Crosthwaite
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 02/18] linux-user: arm: pass env to get_user_code_* Peter Crosthwaite
@ 2016-03-02 6:56 ` Peter Crosthwaite
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 04/18] target-arm: cpu: Move cpu_is_big_endian to header Peter Crosthwaite
` (15 subsequent siblings)
18 siblings, 0 replies; 24+ messages in thread
From: Peter Crosthwaite @ 2016-03-02 6:56 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, Peter Crosthwaite, sw, Andrew.Baumann,
alistair.francis, sridhar_kulk, qemu-arm, pbonzini, piotr.krol
From: Paolo Bonzini <pbonzini@redhat.com>
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.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[PC changes:
* rebased on master (Jan 2016)
* s/TARGET_USER_ONLY/CONFIG_USER_ONLY
* Use bswap_code() for disas_set_info() instead of raw sctlr_b
]
Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
---
TEST result: 0 (log@ logs/qemu-armeb-BE32-)
TEST result: 0 (log@ logs/qemu-armeb-BE8-)
TEST result: 0 (log@ logs/qemu-arm-LE-)
TEST result: 0 (log@ logs/qemu-system-arm-LE-)
Changed since v1:
Re-added BE32 support
linux-user/main.c | 10 +++++++---
target-arm/arm_ldst.h | 8 ++++----
target-arm/cpu.c | 2 +-
target-arm/cpu.h | 47 ++++++++++++++++++++++++++++++++++++++--------
target-arm/helper.c | 8 ++++----
target-arm/translate-a64.c | 6 +++---
target-arm/translate.c | 16 ++++++++--------
target-arm/translate.h | 2 +-
8 files changed, 67 insertions(+), 32 deletions(-)
diff --git a/linux-user/main.c b/linux-user/main.c
index bcb9f66..fe2a8dd 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -437,7 +437,7 @@ void cpu_loop(CPUX86State *env)
#define get_user_code_u32(x, gaddr, env) \
({ abi_long __r = get_user_u32((x), (gaddr)); \
- if (!__r && (env)->bswap_code) { \
+ if (!__r && bswap_code(arm_sctlr_b(env))) { \
(x) = bswap32(x); \
} \
__r; \
@@ -445,7 +445,7 @@ void cpu_loop(CPUX86State *env)
#define get_user_code_u16(x, gaddr, env) \
({ abi_long __r = get_user_u16((x), (gaddr)); \
- if (!__r && (env)->bswap_code) { \
+ if (!__r && bswap_code(arm_sctlr_b(env))) { \
(x) = bswap16(x); \
} \
__r; \
@@ -4449,11 +4449,15 @@ int main(int argc, char **argv, char **envp)
for(i = 0; i < 16; i++) {
env->regs[i] = regs->uregs[i];
}
+#ifdef TARGET_WORDS_BIGENDIAN
/* Enable BE8. */
if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4
&& (info->elf_flags & EF_ARM_BE8)) {
- env->bswap_code = 1;
+ /* nothing for now, CPSR.E not emulated yet */
+ } else {
+ env->cp15.sctlr_el[1] |= SCTLR_B;
}
+#endif
}
#elif defined(TARGET_UNICORE32)
{
diff --git a/target-arm/arm_ldst.h b/target-arm/arm_ldst.h
index b1ece01..35c2c43 100644
--- a/target-arm/arm_ldst.h
+++ b/target-arm/arm_ldst.h
@@ -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;
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index e95b030..001fccf 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -427,7 +427,7 @@ static void arm_disas_set_info(CPUState *cpu, disassemble_info *info)
} else {
info->print_insn = print_insn_arm;
}
- if (env->bswap_code) {
+ if (bswap_code(arm_sctlr_b(env))) {
#ifdef TARGET_WORDS_BIGENDIAN
info->endian = BFD_ENDIAN_LITTLE;
#else
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 744f052..61b8b03 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -478,9 +478,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;
@@ -1898,6 +1895,19 @@ static inline bool arm_singlestep_active(CPUARMState *env)
&& arm_generate_debug_exceptions(env);
}
+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;
+}
+
#include "exec/cpu-all.h"
/* Bit usage in the TB flags field: bit 31 indicates whether we are
@@ -1928,8 +1938,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
*/
@@ -1965,13 +1975,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.
*/
@@ -2049,7 +2080,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;
}
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 18c8296..32e66c8 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -5841,7 +5841,7 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
case EXCP_BKPT:
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,
@@ -6379,13 +6379,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;
@@ -6395,7 +6395,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;
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 7f65aea..f6dd44b 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -10966,7 +10966,7 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s)
{
uint32_t insn;
- 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;
@@ -11031,7 +11031,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;
- dc->bswap_code = 0;
+ dc->sctlr_b = 0;
dc->condexec_mask = 0;
dc->condexec_cond = 0;
dc->mmu_idx = ARM_TBFLAG_MMUIDX(tb->flags);
@@ -11217,7 +11217,7 @@ done_generating:
qemu_log("----------------\n");
qemu_log("IN: %s\n", lookup_symbol(pc_start));
log_target_disas(cs, pc_start, dc->pc - pc_start,
- 4 | (dc->bswap_code << 1));
+ 4 | (bswap_code(dc->sctlr_b) ? 2 : 0));
qemu_log("\n");
}
#endif
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 413f7de..ee04085 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -7770,7 +7770,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
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;
@@ -9286,7 +9286,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;
@@ -10528,7 +10528,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
}
}
- insn = arm_lduw_code(env, s->pc, s->bswap_code);
+ insn = arm_lduw_code(env, s->pc, s->sctlr_b);
s->pc += 2;
switch (insn >> 12) {
@@ -11099,7 +11099,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
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;
@@ -11253,7 +11253,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
@@ -11307,7 +11307,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);
- 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);
@@ -11487,7 +11487,7 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
}
}
} else {
- unsigned int insn = arm_ldl_code(env, dc->pc, dc->bswap_code);
+ unsigned int insn = arm_ldl_code(env, dc->pc, dc->sctlr_b);
dc->pc += 4;
disas_arm_insn(dc, insn);
}
@@ -11644,7 +11644,7 @@ done_generating:
qemu_log("----------------\n");
qemu_log("IN: %s\n", lookup_symbol(pc_start));
log_target_disas(cs, pc_start, dc->pc - pc_start,
- dc->thumb | (dc->bswap_code << 1));
+ dc->thumb | (dc->sctlr_b << 1));
qemu_log("\n");
}
#endif
diff --git a/target-arm/translate.h b/target-arm/translate.h
index 53ef971..0bdc68c 100644
--- a/target-arm/translate.h
+++ b/target-arm/translate.h
@@ -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
--
1.9.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH v2 04/18] target-arm: cpu: Move cpu_is_big_endian to header
2016-03-02 6:56 [Qemu-devel] [PATCH v2 00/18] ARM big-endian and setend support Peter Crosthwaite
` (2 preceding siblings ...)
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 03/18] target-arm: implement SCTLR.B, drop bswap_code Peter Crosthwaite
@ 2016-03-02 6:56 ` Peter Crosthwaite
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 05/18] arm: cpu: handle BE32 user-mode as BE Peter Crosthwaite
` (14 subsequent siblings)
18 siblings, 0 replies; 24+ messages in thread
From: Peter Crosthwaite @ 2016-03-02 6:56 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, Peter Crosthwaite, sw, Andrew.Baumann,
alistair.francis, sridhar_kulk, qemu-arm, pbonzini, piotr.krol
From: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
There is a CPU data endianness test that is used to drive the
virtio_big_endian test.
Move this up to the header so it can be more generally used for endian
tests. The KVM specific cpu_syncronize_state call is left behind in the
virtio specific function.
Rename it arm_cpu-data_is_big_endian() to more accurately capture that
this is for data accesses only.
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
TEST result: 0 (log@ logs/qemu-armeb-BE32-)
TEST result: 0 (log@ logs/qemu-armeb-BE8-)
TEST result: 0 (log@ logs/qemu-arm-LE-)
TEST result: 0 (log@ logs/qemu-system-arm-LE-)
Changed since v1:
rename to arm_cpu_data_is_big_endian (PMM review)
inline function to suppress compile warning.
target-arm/cpu.c | 19 +++----------------
target-arm/cpu.h | 19 +++++++++++++++++++
2 files changed, 22 insertions(+), 16 deletions(-)
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 001fccf..352d9f8 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -369,26 +369,13 @@ static void arm_cpu_kvm_set_irq(void *opaque, int irq, int level)
#endif
}
-static bool arm_cpu_is_big_endian(CPUState *cs)
+static bool arm_cpu_virtio_is_big_endian(CPUState *cs)
{
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;
- int cur_el;
cpu_synchronize_state(cs);
-
- /* In 32bit guest endianness is determined by looking at CPSR's E bit */
- if (!is_a64(env)) {
- return (env->uncached_cpsr & CPSR_E) ? 1 : 0;
- }
-
- cur_el = arm_current_el(env);
-
- if (cur_el == 0) {
- return (env->cp15.sctlr_el[1] & SCTLR_E0E) != 0;
- }
-
- return (env->cp15.sctlr_el[cur_el] & SCTLR_EE) != 0;
+ return arm_cpu_data_is_big_endian(env);
}
#endif
@@ -1476,7 +1463,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
cc->get_phys_page_attrs_debug = arm_cpu_get_phys_page_attrs_debug;
cc->asidx_from_attrs = arm_asidx_from_attrs;
cc->vmsd = &vmstate_arm_cpu;
- cc->virtio_is_big_endian = arm_cpu_is_big_endian;
+ cc->virtio_is_big_endian = arm_cpu_virtio_is_big_endian;
cc->write_elf64_note = arm_cpu_write_elf64_note;
cc->write_elf32_note = arm_cpu_write_elf32_note;
#endif
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 61b8b03..75e5ea0 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1908,6 +1908,25 @@ static inline bool arm_sctlr_b(CPUARMState *env)
(env->cp15.sctlr_el[1] & SCTLR_B) != 0;
}
+/* Return true if the processor is in big-endian mode. */
+static inline bool arm_cpu_data_is_big_endian(CPUARMState *env)
+{
+ int cur_el;
+
+ /* In 32bit endianness is determined by looking at CPSR's E bit */
+ if (!is_a64(env)) {
+ return (env->uncached_cpsr & CPSR_E) ? 1 : 0;
+ }
+
+ cur_el = arm_current_el(env);
+
+ if (cur_el == 0) {
+ return (env->cp15.sctlr_el[1] & SCTLR_E0E) != 0;
+ }
+
+ return (env->cp15.sctlr_el[cur_el] & SCTLR_EE) != 0;
+}
+
#include "exec/cpu-all.h"
/* Bit usage in the TB flags field: bit 31 indicates whether we are
--
1.9.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH v2 05/18] arm: cpu: handle BE32 user-mode as BE
2016-03-02 6:56 [Qemu-devel] [PATCH v2 00/18] ARM big-endian and setend support Peter Crosthwaite
` (3 preceding siblings ...)
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 04/18] target-arm: cpu: Move cpu_is_big_endian to header Peter Crosthwaite
@ 2016-03-02 6:56 ` Peter Crosthwaite
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 06/18] linux-user: arm: set CPSR.E/SCTLR.E0E correctly for BE mode Peter Crosthwaite
` (13 subsequent siblings)
18 siblings, 0 replies; 24+ messages in thread
From: Peter Crosthwaite @ 2016-03-02 6:56 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, Peter Crosthwaite, sw, Andrew.Baumann,
alistair.francis, sridhar_kulk, qemu-arm, pbonzini, piotr.krol
>From a system emulation point of view, BE32 is best modelled as little
endian with address manipulations on subword accesses (to give the
illusion of BE). But user-mode cannot tell the difference and is
already implemented as straight BE. So handle the difference in the
endianess query, where USER mode is BE and system is not.
Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
---
Changed since v1:
Rewrote commit subject and message formerly:
arm: linux-user: don't set CPSR.E in BE32 mode
target-arm/cpu.h | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 75e5ea0..ab0ea92 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1915,7 +1915,22 @@ static inline bool arm_cpu_data_is_big_endian(CPUARMState *env)
/* In 32bit endianness is determined by looking at CPSR's E bit */
if (!is_a64(env)) {
- return (env->uncached_cpsr & CPSR_E) ? 1 : 0;
+ return
+#ifdef CONFIG_USER_ONLY
+ /* In system mode, BE32 is modelled in line with the
+ * architecture (as word-invariant big-endianness), where loads
+ * and stores are done little endian but from addresses which
+ * are adjusted by XORing with the appropriate constant. So the
+ * endianness to use for the raw data access is not affected by
+ * SCTLR.B.
+ * In user mode, however, we model BE32 as byte-invariant
+ * big-endianness (because user-only code cannot tell the
+ * difference), and so we need to use a data access endianness
+ * that depends on SCTLR.B.
+ */
+ arm_sctlr_b(env) ||
+#endif
+ ((env->uncached_cpsr & CPSR_E) ? 1 : 0);
}
cur_el = arm_current_el(env);
--
1.9.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH v2 06/18] linux-user: arm: set CPSR.E/SCTLR.E0E correctly for BE mode
2016-03-02 6:56 [Qemu-devel] [PATCH v2 00/18] ARM big-endian and setend support Peter Crosthwaite
` (4 preceding siblings ...)
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 05/18] arm: cpu: handle BE32 user-mode as BE Peter Crosthwaite
@ 2016-03-02 6:56 ` Peter Crosthwaite
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 07/18] linux-user: arm: handle CPSR.E correctly in strex emulation Peter Crosthwaite
` (12 subsequent siblings)
18 siblings, 0 replies; 24+ messages in thread
From: Peter Crosthwaite @ 2016-03-02 6:56 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, Peter Crosthwaite, sw, Andrew.Baumann,
alistair.francis, sridhar_kulk, qemu-arm, pbonzini, piotr.krol
From: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
If doing big-endian linux-user mode, set both the CPSR.E and SCTLR.E0E
bits. This sets big-endian mode for data accesses.
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
TEST result: 0 (log@ logs/qemu-armeb-BE32-)
TEST result: 0 (log@ logs/qemu-armeb-BE8-)
TEST result: 0 (log@ logs/qemu-arm-LE-)
TEST result: 0 (log@ logs/qemu-system-arm-LE-)
changed since v1:
Removed claim of AA64 support from commit message
linux-user/main.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/linux-user/main.c b/linux-user/main.c
index fe2a8dd..510b3b7 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -4453,7 +4453,8 @@ int main(int argc, char **argv, char **envp)
/* Enable BE8. */
if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4
&& (info->elf_flags & EF_ARM_BE8)) {
- /* nothing for now, CPSR.E not emulated yet */
+ env->uncached_cpsr |= CPSR_E;
+ env->cp15.sctlr_el[1] |= SCTLR_E0E;
} else {
env->cp15.sctlr_el[1] |= SCTLR_B;
}
--
1.9.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH v2 07/18] linux-user: arm: handle CPSR.E correctly in strex emulation
2016-03-02 6:56 [Qemu-devel] [PATCH v2 00/18] ARM big-endian and setend support Peter Crosthwaite
` (5 preceding siblings ...)
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 06/18] linux-user: arm: set CPSR.E/SCTLR.E0E correctly for BE mode Peter Crosthwaite
@ 2016-03-02 6:56 ` Peter Crosthwaite
2016-03-03 15:09 ` Peter Maydell
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 08/18] target-arm: implement SCTLR.EE Peter Crosthwaite
` (11 subsequent siblings)
18 siblings, 1 reply; 24+ messages in thread
From: Peter Crosthwaite @ 2016-03-02 6:56 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, Peter Crosthwaite, sw, Andrew.Baumann,
alistair.francis, sridhar_kulk, qemu-arm, pbonzini, piotr.krol
From: Paolo Bonzini <pbonzini@redhat.com>
Now that CPSR.E is set correctly, prepare for when setend will be able
to change it; bswap data in and out of strex manually by comparing
SCTLR.B, CPSR.E and TARGET_WORDS_BIGENDIAN (we do not have the luxury
of using TCGMemOps).
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[ PC changes:
* Moved SCTLR/CPSR logic to arm_cpu_data_is_big_endian
]
Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
---
Changed since v1:
Removed SCTLR logic from bwap_data()
linux-user/main.c | 50 +++++++++++++++++++++++++++++++++++++++++++-------
target-arm/cpu.h | 11 +++++++++++
2 files changed, 54 insertions(+), 7 deletions(-)
diff --git a/linux-user/main.c b/linux-user/main.c
index 510b3b7..2b1e755 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -451,6 +451,38 @@ void cpu_loop(CPUX86State *env)
__r; \
})
+#define get_user_data_u32(x, gaddr, env) \
+ ({ abi_long __r = get_user_u32((x), (gaddr)); \
+ if (!__r && arm_cpu_bswap_data(env)) { \
+ (x) = bswap32(x); \
+ } \
+ __r; \
+ })
+
+#define get_user_data_u16(x, gaddr, env) \
+ ({ abi_long __r = get_user_u16((x), (gaddr)); \
+ if (!__r && arm_cpu_bswap_data(env)) { \
+ (x) = bswap16(x); \
+ } \
+ __r; \
+ })
+
+#define put_user_data_u32(x, gaddr, env) \
+ ({ typeof(x) __x = (x); \
+ if (arm_cpu_bswap_data(env)) { \
+ __x = bswap32(__x); \
+ } \
+ put_user_u32(__x, (gaddr)); \
+ })
+
+#define put_user_data_u16(x, gaddr, env) \
+ ({ typeof(x) __x = (x); \
+ if (arm_cpu_bswap_data(env)) { \
+ __x = bswap16(__x); \
+ } \
+ put_user_u16(__x, (gaddr)); \
+ })
+
#ifdef TARGET_ABI32
/* Commpage handling -- there is no commpage for AArch64 */
@@ -610,11 +642,11 @@ static int do_strex(CPUARMState *env)
segv = get_user_u8(val, addr);
break;
case 1:
- segv = get_user_u16(val, addr);
+ segv = get_user_data_u16(val, addr, env);
break;
case 2:
case 3:
- segv = get_user_u32(val, addr);
+ segv = get_user_data_u32(val, addr, env);
break;
default:
abort();
@@ -625,12 +657,16 @@ static int do_strex(CPUARMState *env)
}
if (size == 3) {
uint32_t valhi;
- segv = get_user_u32(valhi, addr + 4);
+ segv = get_user_data_u32(valhi, addr + 4, env);
if (segv) {
env->exception.vaddress = addr + 4;
goto done;
}
- val = deposit64(val, 32, 32, valhi);
+ if (arm_cpu_bswap_data(env)) {
+ val = deposit64((uint64_t)valhi, 32, 32, val);
+ } else {
+ val = deposit64(val, 32, 32, valhi);
+ }
}
if (val != env->exclusive_val) {
goto fail;
@@ -642,11 +678,11 @@ static int do_strex(CPUARMState *env)
segv = put_user_u8(val, addr);
break;
case 1:
- segv = put_user_u16(val, addr);
+ segv = put_user_data_u16(val, addr, env);
break;
case 2:
case 3:
- segv = put_user_u32(val, addr);
+ segv = put_user_data_u32(val, addr, env);
break;
}
if (segv) {
@@ -655,7 +691,7 @@ static int do_strex(CPUARMState *env)
}
if (size == 3) {
val = env->regs[(env->exclusive_info >> 12) & 0xf];
- segv = put_user_u32(val, addr + 4);
+ segv = put_user_data_u32(val, addr + 4, env);
if (segv) {
env->exception.vaddress = addr + 4;
goto done;
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index ab0ea92..cbf171c 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -2102,6 +2102,17 @@ static inline int fp_exception_el(CPUARMState *env)
return 0;
}
+#ifdef CONFIG_USER_ONLY
+static inline bool arm_cpu_bswap_data(CPUARMState *env)
+{
+ return
+#ifdef TARGET_WORDS_BIGENDIAN
+ 1 ^
+#endif
+ arm_cpu_data_is_big_endian(env);
+}
+#endif
+
static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
target_ulong *cs_base, int *flags)
{
--
1.9.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [Qemu-devel] [PATCH v2 07/18] linux-user: arm: handle CPSR.E correctly in strex emulation
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 07/18] linux-user: arm: handle CPSR.E correctly in strex emulation Peter Crosthwaite
@ 2016-03-03 15:09 ` Peter Maydell
0 siblings, 0 replies; 24+ messages in thread
From: Peter Maydell @ 2016-03-03 15:09 UTC (permalink / raw)
To: Peter Crosthwaite
Cc: Peter Crosthwaite, Stefan Weil, QEMU Developers, Andrew Baumann,
Alistair Francis, sridhar kulkarni, qemu-arm, Paolo Bonzini,
Piotr Król
On 2 March 2016 at 06:56, Peter Crosthwaite <crosthwaitepeter@gmail.com> wrote:
> From: Paolo Bonzini <pbonzini@redhat.com>
> @@ -610,11 +642,11 @@ static int do_strex(CPUARMState *env)
> segv = get_user_u8(val, addr);
> break;
> case 1:
> - segv = get_user_u16(val, addr);
> + segv = get_user_data_u16(val, addr, env);
> break;
> case 2:
> case 3:
> - segv = get_user_u32(val, addr);
> + segv = get_user_data_u32(val, addr, env);
> break;
> default:
> abort();
> @@ -625,12 +657,16 @@ static int do_strex(CPUARMState *env)
> }
> if (size == 3) {
> uint32_t valhi;
> - segv = get_user_u32(valhi, addr + 4);
> + segv = get_user_data_u32(valhi, addr + 4, env);
> if (segv) {
> env->exception.vaddress = addr + 4;
> goto done;
> }
> - val = deposit64(val, 32, 32, valhi);
> + if (arm_cpu_bswap_data(env)) {
> + val = deposit64((uint64_t)valhi, 32, 32, val);
> + } else {
> + val = deposit64(val, 32, 32, valhi);
> + }
> }
> if (val != env->exclusive_val) {
> goto fail;
> @@ -642,11 +678,11 @@ static int do_strex(CPUARMState *env)
> segv = put_user_u8(val, addr);
> break;
> case 1:
> - segv = put_user_u16(val, addr);
> + segv = put_user_data_u16(val, addr, env);
> break;
> case 2:
> case 3:
> - segv = put_user_u32(val, addr);
> + segv = put_user_data_u32(val, addr, env);
> break;
> }
> if (segv) {
> @@ -655,7 +691,7 @@ static int do_strex(CPUARMState *env)
> }
> if (size == 3) {
> val = env->regs[(env->exclusive_info >> 12) & 0xf];
> - segv = put_user_u32(val, addr + 4);
> + segv = put_user_data_u32(val, addr + 4, env);
> if (segv) {
> env->exception.vaddress = addr + 4;
> goto done;
This confused me for a bit because it doesn't swap the two
halves of a 64-bit word on the 'store new value' codepath,
but it is correct -- for STREXD for AArch32 the first word
in memory is Rt and the second is Rt2, regardless of
endianness.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
thanks
-- PMM
^ permalink raw reply [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH v2 08/18] target-arm: implement SCTLR.EE
2016-03-02 6:56 [Qemu-devel] [PATCH v2 00/18] ARM big-endian and setend support Peter Crosthwaite
` (6 preceding siblings ...)
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 07/18] linux-user: arm: handle CPSR.E correctly in strex emulation Peter Crosthwaite
@ 2016-03-02 6:56 ` Peter Crosthwaite
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 09/18] target-arm: pass DisasContext to gen_aa32_ld*/st* Peter Crosthwaite
` (10 subsequent siblings)
18 siblings, 0 replies; 24+ messages in thread
From: Peter Crosthwaite @ 2016-03-02 6:56 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, Peter Crosthwaite, sw, Andrew.Baumann,
alistair.francis, sridhar_kulk, qemu-arm, pbonzini, piotr.krol
From: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Implement SCTLR.EE bit which controls data endianess for exceptions
and page table translations. SCTLR.EE is mirrored to the CPSR.E bit
on exception entry.
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
target-arm/helper.c | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 32e66c8..c79c7b9 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -6234,6 +6234,11 @@ static void arm_cpu_do_interrupt_aarch32(CPUState *cs)
env->condexec_bits = 0;
/* Switch to the new mode, and to the correct instruction set. */
env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
+ /* Set new mode endianness */
+ env->uncached_cpsr &= ~CPSR_E;
+ if (env->cp15.sctlr_el[arm_current_el(env)] & SCTLR_EE) {
+ env->uncached_cpsr |= ~CPSR_E;
+ }
env->daif |= mask;
/* this is a lie, as the was no c1_sys on V4T/V5, but who cares
* and we should just guard the thumb mode on V4 */
@@ -6520,6 +6525,12 @@ static inline bool regime_translation_disabled(CPUARMState *env,
return (regime_sctlr(env, mmu_idx) & SCTLR_M) == 0;
}
+static inline bool regime_translation_big_endian(CPUARMState *env,
+ ARMMMUIdx mmu_idx)
+{
+ return (regime_sctlr(env, mmu_idx) & SCTLR_EE) != 0;
+}
+
/* Return the TCR controlling this translation regime */
static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
{
@@ -6842,7 +6853,11 @@ static uint32_t arm_ldl_ptw(CPUState *cs, hwaddr addr, bool is_secure,
if (fi->s1ptw) {
return 0;
}
- return address_space_ldl(as, addr, attrs, NULL);
+ if (regime_translation_big_endian(env, mmu_idx)) {
+ return address_space_ldl_be(as, addr, attrs, NULL);
+ } else {
+ return address_space_ldl_le(as, addr, attrs, NULL);
+ }
}
static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, bool is_secure,
@@ -6860,7 +6875,11 @@ static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, bool is_secure,
if (fi->s1ptw) {
return 0;
}
- return address_space_ldq(as, addr, attrs, NULL);
+ if (regime_translation_big_endian(env, mmu_idx)) {
+ return address_space_ldq_be(as, addr, attrs, NULL);
+ } else {
+ return address_space_ldq_le(as, addr, attrs, NULL);
+ }
}
static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
--
1.9.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH v2 09/18] target-arm: pass DisasContext to gen_aa32_ld*/st*
2016-03-02 6:56 [Qemu-devel] [PATCH v2 00/18] ARM big-endian and setend support Peter Crosthwaite
` (7 preceding siblings ...)
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 08/18] target-arm: implement SCTLR.EE Peter Crosthwaite
@ 2016-03-02 6:56 ` Peter Crosthwaite
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 10/18] target-arm: introduce disas flag for endianness Peter Crosthwaite
` (9 subsequent siblings)
18 siblings, 0 replies; 24+ messages in thread
From: Peter Crosthwaite @ 2016-03-02 6:56 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, Peter Crosthwaite, sw, Andrew.Baumann,
alistair.francis, sridhar_kulk, qemu-arm, pbonzini, piotr.krol
From: Paolo Bonzini <pbonzini@redhat.com>
We'll need the DisasContext in the next patch to retrieve the
desired endianness, so pass it as a whole to gen_aa32_ld*/st*.
Unfortunately we cannot let those functions call get_mem_index,
because of user-mode load/store instructions.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[ PC changes:
* Fix long lines
]
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
---
target-arm/translate.c | 270 ++++++++++++++++++++++++++-----------------------
1 file changed, 142 insertions(+), 128 deletions(-)
diff --git a/target-arm/translate.c b/target-arm/translate.c
index ee04085..2028908 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -921,23 +921,27 @@ static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var)
#if TARGET_LONG_BITS == 32
#define DO_GEN_LD(SUFF, OPC) \
-static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
+static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, \
+ TCGv_i32 addr, int index) \
{ \
tcg_gen_qemu_ld_i32(val, addr, index, (OPC)); \
}
#define DO_GEN_ST(SUFF, OPC) \
-static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
+static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, \
+ TCGv_i32 addr, int index) \
{ \
tcg_gen_qemu_st_i32(val, addr, index, (OPC)); \
}
-static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 addr, int index)
+static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
+ TCGv_i32 addr, int index)
{
tcg_gen_qemu_ld_i64(val, addr, index, MO_TEQ);
}
-static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 addr, int index)
+static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
+ TCGv_i32 addr, int index)
{
tcg_gen_qemu_st_i64(val, addr, index, MO_TEQ);
}
@@ -945,7 +949,8 @@ static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 addr, int index)
#else
#define DO_GEN_LD(SUFF, OPC) \
-static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
+static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, \
+ TCGv_i32 addr, int index) \
{ \
TCGv addr64 = tcg_temp_new(); \
tcg_gen_extu_i32_i64(addr64, addr); \
@@ -954,7 +959,8 @@ static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
}
#define DO_GEN_ST(SUFF, OPC) \
-static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
+static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, \
+ TCGv_i32 addr, int index) \
{ \
TCGv addr64 = tcg_temp_new(); \
tcg_gen_extu_i32_i64(addr64, addr); \
@@ -962,7 +968,8 @@ static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
tcg_temp_free(addr64); \
}
-static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 addr, int index)
+static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
+ TCGv_i32 addr, int index)
{
TCGv addr64 = tcg_temp_new();
tcg_gen_extu_i32_i64(addr64, addr);
@@ -970,7 +977,8 @@ static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 addr, int index)
tcg_temp_free(addr64);
}
-static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 addr, int index)
+static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
+ TCGv_i32 addr, int index)
{
TCGv addr64 = tcg_temp_new();
tcg_gen_extu_i32_i64(addr64, addr);
@@ -1285,18 +1293,18 @@ VFP_GEN_FIX(ulto, )
static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv_i32 addr)
{
if (dp) {
- gen_aa32_ld64(cpu_F0d, addr, get_mem_index(s));
+ gen_aa32_ld64(s, cpu_F0d, addr, get_mem_index(s));
} else {
- gen_aa32_ld32u(cpu_F0s, addr, get_mem_index(s));
+ gen_aa32_ld32u(s, cpu_F0s, addr, get_mem_index(s));
}
}
static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr)
{
if (dp) {
- gen_aa32_st64(cpu_F0d, addr, get_mem_index(s));
+ gen_aa32_st64(s, cpu_F0d, addr, get_mem_index(s));
} else {
- gen_aa32_st32(cpu_F0s, addr, get_mem_index(s));
+ gen_aa32_st32(s, cpu_F0s, addr, get_mem_index(s));
}
}
@@ -1632,24 +1640,24 @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
if (insn & ARM_CP_RW_BIT) {
if ((insn >> 28) == 0xf) { /* WLDRW wCx */
tmp = tcg_temp_new_i32();
- gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
iwmmxt_store_creg(wrd, tmp);
} else {
i = 1;
if (insn & (1 << 8)) {
if (insn & (1 << 22)) { /* WLDRD */
- gen_aa32_ld64(cpu_M0, addr, get_mem_index(s));
+ gen_aa32_ld64(s, cpu_M0, addr, get_mem_index(s));
i = 0;
} else { /* WLDRW wRd */
tmp = tcg_temp_new_i32();
- gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
}
} else {
tmp = tcg_temp_new_i32();
if (insn & (1 << 22)) { /* WLDRH */
- gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
} else { /* WLDRB */
- gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
}
}
if (i) {
@@ -1661,24 +1669,24 @@ static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
} else {
if ((insn >> 28) == 0xf) { /* WSTRW wCx */
tmp = iwmmxt_load_creg(wrd);
- gen_aa32_st32(tmp, addr, get_mem_index(s));
+ gen_aa32_st32(s, tmp, addr, get_mem_index(s));
} else {
gen_op_iwmmxt_movq_M0_wRn(wrd);
tmp = tcg_temp_new_i32();
if (insn & (1 << 8)) {
if (insn & (1 << 22)) { /* WSTRD */
- gen_aa32_st64(cpu_M0, addr, get_mem_index(s));
+ gen_aa32_st64(s, cpu_M0, addr, get_mem_index(s));
} else { /* WSTRW wRd */
tcg_gen_extrl_i64_i32(tmp, cpu_M0);
- gen_aa32_st32(tmp, addr, get_mem_index(s));
+ gen_aa32_st32(s, tmp, addr, get_mem_index(s));
}
} else {
if (insn & (1 << 22)) { /* WSTRH */
tcg_gen_extrl_i64_i32(tmp, cpu_M0);
- gen_aa32_st16(tmp, addr, get_mem_index(s));
+ gen_aa32_st16(s, tmp, addr, get_mem_index(s));
} else { /* WSTRB */
tcg_gen_extrl_i64_i32(tmp, cpu_M0);
- gen_aa32_st8(tmp, addr, get_mem_index(s));
+ gen_aa32_st8(s, tmp, addr, get_mem_index(s));
}
}
}
@@ -2743,15 +2751,15 @@ static TCGv_i32 gen_load_and_replicate(DisasContext *s, TCGv_i32 addr, int size)
TCGv_i32 tmp = tcg_temp_new_i32();
switch (size) {
case 0:
- gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
gen_neon_dup_u8(tmp, 0);
break;
case 1:
- gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
gen_neon_dup_low16(tmp);
break;
case 2:
- gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
break;
default: /* Avoid compiler warnings. */
abort();
@@ -4449,11 +4457,11 @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
if (size == 3) {
tmp64 = tcg_temp_new_i64();
if (load) {
- gen_aa32_ld64(tmp64, addr, get_mem_index(s));
+ gen_aa32_ld64(s, tmp64, addr, get_mem_index(s));
neon_store_reg64(tmp64, rd);
} else {
neon_load_reg64(tmp64, rd);
- gen_aa32_st64(tmp64, addr, get_mem_index(s));
+ gen_aa32_st64(s, tmp64, addr, get_mem_index(s));
}
tcg_temp_free_i64(tmp64);
tcg_gen_addi_i32(addr, addr, stride);
@@ -4462,21 +4470,21 @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
if (size == 2) {
if (load) {
tmp = tcg_temp_new_i32();
- gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
neon_store_reg(rd, pass, tmp);
} else {
tmp = neon_load_reg(rd, pass);
- gen_aa32_st32(tmp, addr, get_mem_index(s));
+ gen_aa32_st32(s, tmp, addr, get_mem_index(s));
tcg_temp_free_i32(tmp);
}
tcg_gen_addi_i32(addr, addr, stride);
} else if (size == 1) {
if (load) {
tmp = tcg_temp_new_i32();
- gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
tcg_gen_addi_i32(addr, addr, stride);
tmp2 = tcg_temp_new_i32();
- gen_aa32_ld16u(tmp2, addr, get_mem_index(s));
+ gen_aa32_ld16u(s, tmp2, addr, get_mem_index(s));
tcg_gen_addi_i32(addr, addr, stride);
tcg_gen_shli_i32(tmp2, tmp2, 16);
tcg_gen_or_i32(tmp, tmp, tmp2);
@@ -4486,10 +4494,10 @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
tmp = neon_load_reg(rd, pass);
tmp2 = tcg_temp_new_i32();
tcg_gen_shri_i32(tmp2, tmp, 16);
- gen_aa32_st16(tmp, addr, get_mem_index(s));
+ gen_aa32_st16(s, tmp, addr, get_mem_index(s));
tcg_temp_free_i32(tmp);
tcg_gen_addi_i32(addr, addr, stride);
- gen_aa32_st16(tmp2, addr, get_mem_index(s));
+ gen_aa32_st16(s, tmp2, addr, get_mem_index(s));
tcg_temp_free_i32(tmp2);
tcg_gen_addi_i32(addr, addr, stride);
}
@@ -4498,7 +4506,7 @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
TCGV_UNUSED_I32(tmp2);
for (n = 0; n < 4; n++) {
tmp = tcg_temp_new_i32();
- gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
tcg_gen_addi_i32(addr, addr, stride);
if (n == 0) {
tmp2 = tmp;
@@ -4518,7 +4526,7 @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
} else {
tcg_gen_shri_i32(tmp, tmp2, n * 8);
}
- gen_aa32_st8(tmp, addr, get_mem_index(s));
+ gen_aa32_st8(s, tmp, addr, get_mem_index(s));
tcg_temp_free_i32(tmp);
tcg_gen_addi_i32(addr, addr, stride);
}
@@ -4642,13 +4650,13 @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
tmp = tcg_temp_new_i32();
switch (size) {
case 0:
- gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
break;
case 1:
- gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
break;
case 2:
- gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
break;
default: /* Avoid compiler warnings. */
abort();
@@ -4666,13 +4674,13 @@ static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
tcg_gen_shri_i32(tmp, tmp, shift);
switch (size) {
case 0:
- gen_aa32_st8(tmp, addr, get_mem_index(s));
+ gen_aa32_st8(s, tmp, addr, get_mem_index(s));
break;
case 1:
- gen_aa32_st16(tmp, addr, get_mem_index(s));
+ gen_aa32_st16(s, tmp, addr, get_mem_index(s));
break;
case 2:
- gen_aa32_st32(tmp, addr, get_mem_index(s));
+ gen_aa32_st32(s, tmp, addr, get_mem_index(s));
break;
}
tcg_temp_free_i32(tmp);
@@ -7435,14 +7443,14 @@ static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
switch (size) {
case 0:
- gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
break;
case 1:
- gen_aa32_ld16ua(tmp, addr, get_mem_index(s));
+ gen_aa32_ld16ua(s, tmp, addr, get_mem_index(s));
break;
case 2:
case 3:
- gen_aa32_ld32ua(tmp, addr, get_mem_index(s));
+ gen_aa32_ld32ua(s, tmp, addr, get_mem_index(s));
break;
default:
abort();
@@ -7453,7 +7461,7 @@ static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
TCGv_i32 tmp3 = tcg_temp_new_i32();
tcg_gen_addi_i32(tmp2, addr, 4);
- gen_aa32_ld32u(tmp3, tmp2, get_mem_index(s));
+ gen_aa32_ld32u(s, tmp3, tmp2, get_mem_index(s));
tcg_temp_free_i32(tmp2);
tcg_gen_concat_i32_i64(cpu_exclusive_val, tmp, tmp3);
store_reg(s, rt2, tmp3);
@@ -7504,14 +7512,14 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
tmp = tcg_temp_new_i32();
switch (size) {
case 0:
- gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
break;
case 1:
- gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
break;
case 2:
case 3:
- gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
break;
default:
abort();
@@ -7522,7 +7530,7 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
TCGv_i32 tmp2 = tcg_temp_new_i32();
TCGv_i32 tmp3 = tcg_temp_new_i32();
tcg_gen_addi_i32(tmp2, addr, 4);
- gen_aa32_ld32u(tmp3, tmp2, get_mem_index(s));
+ gen_aa32_ld32u(s, tmp3, tmp2, get_mem_index(s));
tcg_temp_free_i32(tmp2);
tcg_gen_concat_i32_i64(val64, tmp, tmp3);
tcg_temp_free_i32(tmp3);
@@ -7537,14 +7545,14 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
tmp = load_reg(s, rt);
switch (size) {
case 0:
- gen_aa32_st8(tmp, addr, get_mem_index(s));
+ gen_aa32_st8(s, tmp, addr, get_mem_index(s));
break;
case 1:
- gen_aa32_st16(tmp, addr, get_mem_index(s));
+ gen_aa32_st16(s, tmp, addr, get_mem_index(s));
break;
case 2:
case 3:
- gen_aa32_st32(tmp, addr, get_mem_index(s));
+ gen_aa32_st32(s, tmp, addr, get_mem_index(s));
break;
default:
abort();
@@ -7553,7 +7561,7 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
if (size == 3) {
tcg_gen_addi_i32(addr, addr, 4);
tmp = load_reg(s, rt2);
- gen_aa32_st32(tmp, addr, get_mem_index(s));
+ gen_aa32_st32(s, tmp, addr, get_mem_index(s));
tcg_temp_free_i32(tmp);
}
tcg_gen_movi_i32(cpu_R[rd], 0);
@@ -7659,11 +7667,11 @@ static void gen_srs(DisasContext *s,
}
tcg_gen_addi_i32(addr, addr, offset);
tmp = load_reg(s, 14);
- gen_aa32_st32(tmp, addr, get_mem_index(s));
+ gen_aa32_st32(s, tmp, addr, get_mem_index(s));
tcg_temp_free_i32(tmp);
tmp = load_cpu_field(spsr);
tcg_gen_addi_i32(addr, addr, 4);
- gen_aa32_st32(tmp, addr, get_mem_index(s));
+ gen_aa32_st32(s, tmp, addr, get_mem_index(s));
tcg_temp_free_i32(tmp);
if (writeback) {
switch (amode) {
@@ -7822,10 +7830,10 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
tcg_gen_addi_i32(addr, addr, offset);
/* Load PC into tmp and CPSR into tmp2. */
tmp = tcg_temp_new_i32();
- gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
tcg_gen_addi_i32(addr, addr, 4);
tmp2 = tcg_temp_new_i32();
- gen_aa32_ld32u(tmp2, addr, get_mem_index(s));
+ gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
if (insn & (1 << 21)) {
/* Base writeback. */
switch (i) {
@@ -8441,13 +8449,16 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
tmp = tcg_temp_new_i32();
switch (op1) {
case 0: /* lda */
- gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld32u(s, tmp, addr,
+ get_mem_index(s));
break;
case 2: /* ldab */
- gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld8u(s, tmp, addr,
+ get_mem_index(s));
break;
case 3: /* ldah */
- gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld16u(s, tmp, addr,
+ get_mem_index(s));
break;
default:
abort();
@@ -8458,13 +8469,16 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
tmp = load_reg(s, rm);
switch (op1) {
case 0: /* stl */
- gen_aa32_st32(tmp, addr, get_mem_index(s));
+ gen_aa32_st32(s, tmp, addr,
+ get_mem_index(s));
break;
case 2: /* stlb */
- gen_aa32_st8(tmp, addr, get_mem_index(s));
+ gen_aa32_st8(s, tmp, addr,
+ get_mem_index(s));
break;
case 3: /* stlh */
- gen_aa32_st16(tmp, addr, get_mem_index(s));
+ gen_aa32_st16(s, tmp, addr,
+ get_mem_index(s));
break;
default:
abort();
@@ -8519,11 +8533,11 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
tmp = load_reg(s, rm);
tmp2 = tcg_temp_new_i32();
if (insn & (1 << 22)) {
- gen_aa32_ld8u(tmp2, addr, get_mem_index(s));
- gen_aa32_st8(tmp, addr, get_mem_index(s));
+ gen_aa32_ld8u(s, tmp2, addr, get_mem_index(s));
+ gen_aa32_st8(s, tmp, addr, get_mem_index(s));
} else {
- gen_aa32_ld32u(tmp2, addr, get_mem_index(s));
- gen_aa32_st32(tmp, addr, get_mem_index(s));
+ gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
+ gen_aa32_st32(s, tmp, addr, get_mem_index(s));
}
tcg_temp_free_i32(tmp);
tcg_temp_free_i32(addr);
@@ -8558,20 +8572,20 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
if (!load) {
/* store */
tmp = load_reg(s, rd);
- gen_aa32_st32(tmp, addr, get_mem_index(s));
+ gen_aa32_st32(s, tmp, addr, get_mem_index(s));
tcg_temp_free_i32(tmp);
tcg_gen_addi_i32(addr, addr, 4);
tmp = load_reg(s, rd + 1);
- gen_aa32_st32(tmp, addr, get_mem_index(s));
+ gen_aa32_st32(s, tmp, addr, get_mem_index(s));
tcg_temp_free_i32(tmp);
} else {
/* load */
tmp = tcg_temp_new_i32();
- gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
store_reg(s, rd, tmp);
tcg_gen_addi_i32(addr, addr, 4);
tmp = tcg_temp_new_i32();
- gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
rd++;
}
address_offset = -4;
@@ -8580,20 +8594,20 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
tmp = tcg_temp_new_i32();
switch (sh) {
case 1:
- gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
break;
case 2:
- gen_aa32_ld8s(tmp, addr, get_mem_index(s));
+ gen_aa32_ld8s(s, tmp, addr, get_mem_index(s));
break;
default:
case 3:
- gen_aa32_ld16s(tmp, addr, get_mem_index(s));
+ gen_aa32_ld16s(s, tmp, addr, get_mem_index(s));
break;
}
} else {
/* store */
tmp = load_reg(s, rd);
- gen_aa32_st16(tmp, addr, get_mem_index(s));
+ gen_aa32_st16(s, tmp, addr, get_mem_index(s));
tcg_temp_free_i32(tmp);
}
/* Perform base writeback before the loaded value to
@@ -8946,17 +8960,17 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
/* load */
tmp = tcg_temp_new_i32();
if (insn & (1 << 22)) {
- gen_aa32_ld8u(tmp, tmp2, i);
+ gen_aa32_ld8u(s, tmp, tmp2, i);
} else {
- gen_aa32_ld32u(tmp, tmp2, i);
+ gen_aa32_ld32u(s, tmp, tmp2, i);
}
} else {
/* store */
tmp = load_reg(s, rd);
if (insn & (1 << 22)) {
- gen_aa32_st8(tmp, tmp2, i);
+ gen_aa32_st8(s, tmp, tmp2, i);
} else {
- gen_aa32_st32(tmp, tmp2, i);
+ gen_aa32_st32(s, tmp, tmp2, i);
}
tcg_temp_free_i32(tmp);
}
@@ -9029,7 +9043,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
if (is_load) {
/* load */
tmp = tcg_temp_new_i32();
- gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
if (user) {
tmp2 = tcg_const_i32(i);
gen_helper_set_user_reg(cpu_env, tmp2, tmp);
@@ -9056,7 +9070,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
} else {
tmp = load_reg(s, i);
}
- gen_aa32_st32(tmp, addr, get_mem_index(s));
+ gen_aa32_st32(s, tmp, addr, get_mem_index(s));
tcg_temp_free_i32(tmp);
}
j++;
@@ -9323,20 +9337,20 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
if (insn & (1 << 20)) {
/* ldrd */
tmp = tcg_temp_new_i32();
- gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
store_reg(s, rs, tmp);
tcg_gen_addi_i32(addr, addr, 4);
tmp = tcg_temp_new_i32();
- gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
store_reg(s, rd, tmp);
} else {
/* strd */
tmp = load_reg(s, rs);
- gen_aa32_st32(tmp, addr, get_mem_index(s));
+ gen_aa32_st32(s, tmp, addr, get_mem_index(s));
tcg_temp_free_i32(tmp);
tcg_gen_addi_i32(addr, addr, 4);
tmp = load_reg(s, rd);
- gen_aa32_st32(tmp, addr, get_mem_index(s));
+ gen_aa32_st32(s, tmp, addr, get_mem_index(s));
tcg_temp_free_i32(tmp);
}
if (insn & (1 << 21)) {
@@ -9374,11 +9388,11 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
tcg_gen_add_i32(addr, addr, tmp);
tcg_temp_free_i32(tmp);
tmp = tcg_temp_new_i32();
- gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
} else { /* tbb */
tcg_temp_free_i32(tmp);
tmp = tcg_temp_new_i32();
- gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
}
tcg_temp_free_i32(addr);
tcg_gen_shli_i32(tmp, tmp, 1);
@@ -9415,13 +9429,13 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
tmp = tcg_temp_new_i32();
switch (op) {
case 0: /* ldab */
- gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
break;
case 1: /* ldah */
- gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
break;
case 2: /* lda */
- gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
break;
default:
abort();
@@ -9431,13 +9445,13 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
tmp = load_reg(s, rs);
switch (op) {
case 0: /* stlb */
- gen_aa32_st8(tmp, addr, get_mem_index(s));
+ gen_aa32_st8(s, tmp, addr, get_mem_index(s));
break;
case 1: /* stlh */
- gen_aa32_st16(tmp, addr, get_mem_index(s));
+ gen_aa32_st16(s, tmp, addr, get_mem_index(s));
break;
case 2: /* stl */
- gen_aa32_st32(tmp, addr, get_mem_index(s));
+ gen_aa32_st32(s, tmp, addr, get_mem_index(s));
break;
default:
abort();
@@ -9465,10 +9479,10 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
tcg_gen_addi_i32(addr, addr, -8);
/* Load PC into tmp and CPSR into tmp2. */
tmp = tcg_temp_new_i32();
- gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
tcg_gen_addi_i32(addr, addr, 4);
tmp2 = tcg_temp_new_i32();
- gen_aa32_ld32u(tmp2, addr, get_mem_index(s));
+ gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
if (insn & (1 << 21)) {
/* Base writeback. */
if (insn & (1 << 24)) {
@@ -9507,7 +9521,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
if (insn & (1 << 20)) {
/* Load. */
tmp = tcg_temp_new_i32();
- gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
if (i == 15) {
gen_bx(s, tmp);
} else if (i == rn) {
@@ -9519,7 +9533,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
} else {
/* Store. */
tmp = load_reg(s, i);
- gen_aa32_st32(tmp, addr, get_mem_index(s));
+ gen_aa32_st32(s, tmp, addr, get_mem_index(s));
tcg_temp_free_i32(tmp);
}
tcg_gen_addi_i32(addr, addr, 4);
@@ -10449,19 +10463,19 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
tmp = tcg_temp_new_i32();
switch (op) {
case 0:
- gen_aa32_ld8u(tmp, addr, memidx);
+ gen_aa32_ld8u(s, tmp, addr, memidx);
break;
case 4:
- gen_aa32_ld8s(tmp, addr, memidx);
+ gen_aa32_ld8s(s, tmp, addr, memidx);
break;
case 1:
- gen_aa32_ld16u(tmp, addr, memidx);
+ gen_aa32_ld16u(s, tmp, addr, memidx);
break;
case 5:
- gen_aa32_ld16s(tmp, addr, memidx);
+ gen_aa32_ld16s(s, tmp, addr, memidx);
break;
case 2:
- gen_aa32_ld32u(tmp, addr, memidx);
+ gen_aa32_ld32u(s, tmp, addr, memidx);
break;
default:
tcg_temp_free_i32(tmp);
@@ -10478,13 +10492,13 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
tmp = load_reg(s, rs);
switch (op) {
case 0:
- gen_aa32_st8(tmp, addr, memidx);
+ gen_aa32_st8(s, tmp, addr, memidx);
break;
case 1:
- gen_aa32_st16(tmp, addr, memidx);
+ gen_aa32_st16(s, tmp, addr, memidx);
break;
case 2:
- gen_aa32_st32(tmp, addr, memidx);
+ gen_aa32_st32(s, tmp, addr, memidx);
break;
default:
tcg_temp_free_i32(tmp);
@@ -10621,7 +10635,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
addr = tcg_temp_new_i32();
tcg_gen_movi_i32(addr, val);
tmp = tcg_temp_new_i32();
- gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
tcg_temp_free_i32(addr);
store_reg(s, rd, tmp);
break;
@@ -10824,28 +10838,28 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
switch (op) {
case 0: /* str */
- gen_aa32_st32(tmp, addr, get_mem_index(s));
+ gen_aa32_st32(s, tmp, addr, get_mem_index(s));
break;
case 1: /* strh */
- gen_aa32_st16(tmp, addr, get_mem_index(s));
+ gen_aa32_st16(s, tmp, addr, get_mem_index(s));
break;
case 2: /* strb */
- gen_aa32_st8(tmp, addr, get_mem_index(s));
+ gen_aa32_st8(s, tmp, addr, get_mem_index(s));
break;
case 3: /* ldrsb */
- gen_aa32_ld8s(tmp, addr, get_mem_index(s));
+ gen_aa32_ld8s(s, tmp, addr, get_mem_index(s));
break;
case 4: /* ldr */
- gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
break;
case 5: /* ldrh */
- gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
break;
case 6: /* ldrb */
- gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
break;
case 7: /* ldrsh */
- gen_aa32_ld16s(tmp, addr, get_mem_index(s));
+ gen_aa32_ld16s(s, tmp, addr, get_mem_index(s));
break;
}
if (op >= 3) { /* load */
@@ -10867,12 +10881,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
if (insn & (1 << 11)) {
/* load */
tmp = tcg_temp_new_i32();
- gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
store_reg(s, rd, tmp);
} else {
/* store */
tmp = load_reg(s, rd);
- gen_aa32_st32(tmp, addr, get_mem_index(s));
+ gen_aa32_st32(s, tmp, addr, get_mem_index(s));
tcg_temp_free_i32(tmp);
}
tcg_temp_free_i32(addr);
@@ -10889,12 +10903,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
if (insn & (1 << 11)) {
/* load */
tmp = tcg_temp_new_i32();
- gen_aa32_ld8u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
store_reg(s, rd, tmp);
} else {
/* store */
tmp = load_reg(s, rd);
- gen_aa32_st8(tmp, addr, get_mem_index(s));
+ gen_aa32_st8(s, tmp, addr, get_mem_index(s));
tcg_temp_free_i32(tmp);
}
tcg_temp_free_i32(addr);
@@ -10911,12 +10925,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
if (insn & (1 << 11)) {
/* load */
tmp = tcg_temp_new_i32();
- gen_aa32_ld16u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
store_reg(s, rd, tmp);
} else {
/* store */
tmp = load_reg(s, rd);
- gen_aa32_st16(tmp, addr, get_mem_index(s));
+ gen_aa32_st16(s, tmp, addr, get_mem_index(s));
tcg_temp_free_i32(tmp);
}
tcg_temp_free_i32(addr);
@@ -10932,12 +10946,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
if (insn & (1 << 11)) {
/* load */
tmp = tcg_temp_new_i32();
- gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
store_reg(s, rd, tmp);
} else {
/* store */
tmp = load_reg(s, rd);
- gen_aa32_st32(tmp, addr, get_mem_index(s));
+ gen_aa32_st32(s, tmp, addr, get_mem_index(s));
tcg_temp_free_i32(tmp);
}
tcg_temp_free_i32(addr);
@@ -11005,12 +11019,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
if (insn & (1 << 11)) {
/* pop */
tmp = tcg_temp_new_i32();
- gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
store_reg(s, i, tmp);
} else {
/* push */
tmp = load_reg(s, i);
- gen_aa32_st32(tmp, addr, get_mem_index(s));
+ gen_aa32_st32(s, tmp, addr, get_mem_index(s));
tcg_temp_free_i32(tmp);
}
/* advance to the next address. */
@@ -11022,13 +11036,13 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
if (insn & (1 << 11)) {
/* pop pc */
tmp = tcg_temp_new_i32();
- gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
/* don't set the pc until the rest of the instruction
has completed */
} else {
/* push lr */
tmp = load_reg(s, 14);
- gen_aa32_st32(tmp, addr, get_mem_index(s));
+ gen_aa32_st32(s, tmp, addr, get_mem_index(s));
tcg_temp_free_i32(tmp);
}
tcg_gen_addi_i32(addr, addr, 4);
@@ -11158,7 +11172,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
if (insn & (1 << 11)) {
/* load */
tmp = tcg_temp_new_i32();
- gen_aa32_ld32u(tmp, addr, get_mem_index(s));
+ gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
if (i == rn) {
loaded_var = tmp;
} else {
@@ -11167,7 +11181,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
} else {
/* store */
tmp = load_reg(s, i);
- gen_aa32_st32(tmp, addr, get_mem_index(s));
+ gen_aa32_st32(s, tmp, addr, get_mem_index(s));
tcg_temp_free_i32(tmp);
}
/* advance to the next address */
--
1.9.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH v2 10/18] target-arm: introduce disas flag for endianness
2016-03-02 6:56 [Qemu-devel] [PATCH v2 00/18] ARM big-endian and setend support Peter Crosthwaite
` (8 preceding siblings ...)
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 09/18] target-arm: pass DisasContext to gen_aa32_ld*/st* Peter Crosthwaite
@ 2016-03-02 6:56 ` Peter Crosthwaite
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 11/18] target-arm: a64: Add endianness support Peter Crosthwaite
` (8 subsequent siblings)
18 siblings, 0 replies; 24+ messages in thread
From: Peter Crosthwaite @ 2016-03-02 6:56 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, Peter Crosthwaite, sw, Andrew.Baumann,
alistair.francis, sridhar_kulk, qemu-arm, pbonzini, piotr.krol
From: Paolo Bonzini <pbonzini@redhat.com>
Introduce a disas flag for setting the CPU data endianness. This allows
control of the endianness from the CPU state rather than hard-coding it
to TARGET_WORDS_BIGENDIAN.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[ PC changes:
* Split off as new patch from original:
"target-arm: introduce tbflag for CPSR.E"
* Wrote commit message from scratch
]
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
Changed since v1:
rename mo_endianness to be_data
target-arm/translate-a64.c | 1 +
target-arm/translate.c | 39 ++++++++++++++++++++++++---------------
target-arm/translate.h | 1 +
3 files changed, 26 insertions(+), 15 deletions(-)
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index f6dd44b..88b95ab 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -11032,6 +11032,7 @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
!arm_el_is_aa64(env, 3);
dc->thumb = 0;
dc->sctlr_b = 0;
+ dc->be_data = MO_TE;
dc->condexec_mask = 0;
dc->condexec_cond = 0;
dc->mmu_idx = ARM_TBFLAG_MMUIDX(tb->flags);
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 2028908..88f24cb 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -924,26 +924,30 @@ static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var)
static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, \
TCGv_i32 addr, int index) \
{ \
- tcg_gen_qemu_ld_i32(val, addr, index, (OPC)); \
+ TCGMemOp opc = (OPC) | s->be_data; \
+ tcg_gen_qemu_ld_i32(val, addr, index, opc); \
}
#define DO_GEN_ST(SUFF, OPC) \
static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, \
TCGv_i32 addr, int index) \
{ \
- tcg_gen_qemu_st_i32(val, addr, index, (OPC)); \
+ TCGMemOp opc = (OPC) | s->be_data; \
+ tcg_gen_qemu_st_i32(val, addr, index, opc); \
}
static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
TCGv_i32 addr, int index)
{
- tcg_gen_qemu_ld_i64(val, addr, index, MO_TEQ);
+ TCGMemOp opc = MO_Q | s->be_data;
+ tcg_gen_qemu_ld_i64(val, addr, index, opc);
}
static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
TCGv_i32 addr, int index)
{
- tcg_gen_qemu_st_i64(val, addr, index, MO_TEQ);
+ TCGMemOp opc = MO_Q | s->be_data;
+ tcg_gen_qemu_st_i64(val, addr, index, opc);
}
#else
@@ -952,9 +956,10 @@ static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, \
TCGv_i32 addr, int index) \
{ \
+ TCGMemOp opc = (OPC) | s->be_data; \
TCGv addr64 = tcg_temp_new(); \
tcg_gen_extu_i32_i64(addr64, addr); \
- tcg_gen_qemu_ld_i32(val, addr64, index, OPC); \
+ tcg_gen_qemu_ld_i32(val, addr64, index, opc); \
tcg_temp_free(addr64); \
}
@@ -962,27 +967,30 @@ static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, \
static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, \
TCGv_i32 addr, int index) \
{ \
+ TCGMemOp opc = (OPC) | s->be_data; \
TCGv addr64 = tcg_temp_new(); \
tcg_gen_extu_i32_i64(addr64, addr); \
- tcg_gen_qemu_st_i32(val, addr64, index, OPC); \
+ tcg_gen_qemu_st_i32(val, addr64, index, opc); \
tcg_temp_free(addr64); \
}
static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
TCGv_i32 addr, int index)
{
+ TCGMemOp opc = MO_Q | s->be_data;
TCGv addr64 = tcg_temp_new();
tcg_gen_extu_i32_i64(addr64, addr);
- tcg_gen_qemu_ld_i64(val, addr64, index, MO_TEQ);
+ tcg_gen_qemu_ld_i64(val, addr64, index, opc);
tcg_temp_free(addr64);
}
static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
TCGv_i32 addr, int index)
{
+ TCGMemOp opc = MO_Q | s->be_data;
TCGv addr64 = tcg_temp_new();
tcg_gen_extu_i32_i64(addr64, addr);
- tcg_gen_qemu_st_i64(val, addr64, index, MO_TEQ);
+ tcg_gen_qemu_st_i64(val, addr64, index, opc);
tcg_temp_free(addr64);
}
@@ -990,15 +998,15 @@ static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
DO_GEN_LD(8s, MO_SB)
DO_GEN_LD(8u, MO_UB)
-DO_GEN_LD(16s, MO_TESW)
-DO_GEN_LD(16u, MO_TEUW)
-DO_GEN_LD(32u, MO_TEUL)
+DO_GEN_LD(16s, MO_SW)
+DO_GEN_LD(16u, MO_UW)
+DO_GEN_LD(32u, MO_UL)
/* 'a' variants include an alignment check */
-DO_GEN_LD(16ua, MO_TEUW | MO_ALIGN)
-DO_GEN_LD(32ua, MO_TEUL | MO_ALIGN)
+DO_GEN_LD(16ua, MO_UW | MO_ALIGN)
+DO_GEN_LD(32ua, MO_UL | MO_ALIGN)
DO_GEN_ST(8, MO_UB)
-DO_GEN_ST(16, MO_TEUW)
-DO_GEN_ST(32, MO_TEUL)
+DO_GEN_ST(16, MO_UW)
+DO_GEN_ST(32, MO_UL)
static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
{
@@ -11322,6 +11330,7 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
!arm_el_is_aa64(env, 3);
dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
dc->sctlr_b = ARM_TBFLAG_SCTLR_B(tb->flags);
+ dc->be_data = MO_TE;
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);
diff --git a/target-arm/translate.h b/target-arm/translate.h
index 0bdc68c..36bc996 100644
--- a/target-arm/translate.h
+++ b/target-arm/translate.h
@@ -17,6 +17,7 @@ typedef struct DisasContext {
int singlestep_enabled;
int thumb;
int sctlr_b;
+ TCGMemOp be_data;
#if !defined(CONFIG_USER_ONLY)
int user;
#endif
--
1.9.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH v2 11/18] target-arm: a64: Add endianness support
2016-03-02 6:56 [Qemu-devel] [PATCH v2 00/18] ARM big-endian and setend support Peter Crosthwaite
` (9 preceding siblings ...)
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 10/18] target-arm: introduce disas flag for endianness Peter Crosthwaite
@ 2016-03-02 6:56 ` Peter Crosthwaite
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 12/18] target-arm: introduce tbflag for endianness Peter Crosthwaite
` (7 subsequent siblings)
18 siblings, 0 replies; 24+ messages in thread
From: Peter Crosthwaite @ 2016-03-02 6:56 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, Peter Crosthwaite, sw, Andrew.Baumann,
alistair.francis, sridhar_kulk, qemu-arm, pbonzini, piotr.krol
From: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Set the dc->mo_endianness flag for AA64 and use it in all ldst ops.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
target-arm/translate-a64.c | 49 ++++++++++++++++++++++++++++------------------
1 file changed, 30 insertions(+), 19 deletions(-)
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 88b95ab..539e6d9 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -723,7 +723,7 @@ static void do_gpr_st_memidx(DisasContext *s, TCGv_i64 source,
TCGv_i64 tcg_addr, int size, int memidx)
{
g_assert(size <= 3);
- tcg_gen_qemu_st_i64(source, tcg_addr, memidx, MO_TE + size);
+ tcg_gen_qemu_st_i64(source, tcg_addr, memidx, s->be_data + size);
}
static void do_gpr_st(DisasContext *s, TCGv_i64 source,
@@ -738,7 +738,7 @@ static void do_gpr_st(DisasContext *s, TCGv_i64 source,
static void do_gpr_ld_memidx(DisasContext *s, TCGv_i64 dest, TCGv_i64 tcg_addr,
int size, bool is_signed, bool extend, int memidx)
{
- TCGMemOp memop = MO_TE + size;
+ TCGMemOp memop = s->be_data + size;
g_assert(size <= 3);
@@ -770,13 +770,18 @@ static void do_fp_st(DisasContext *s, int srcidx, TCGv_i64 tcg_addr, int size)
TCGv_i64 tmp = tcg_temp_new_i64();
tcg_gen_ld_i64(tmp, cpu_env, fp_reg_offset(s, srcidx, MO_64));
if (size < 4) {
- tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s), MO_TE + size);
+ tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s),
+ s->be_data + size);
} else {
+ bool be = s->be_data == MO_BE;
TCGv_i64 tcg_hiaddr = tcg_temp_new_i64();
- tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s), MO_TEQ);
+
+ tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
+ tcg_gen_qemu_st_i64(tmp, be ? tcg_hiaddr : tcg_addr, get_mem_index(s),
+ s->be_data | MO_Q);
tcg_gen_ld_i64(tmp, cpu_env, fp_reg_hi_offset(s, srcidx));
- tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
- tcg_gen_qemu_st_i64(tmp, tcg_hiaddr, get_mem_index(s), MO_TEQ);
+ tcg_gen_qemu_st_i64(tmp, be ? tcg_addr : tcg_hiaddr, get_mem_index(s),
+ s->be_data | MO_Q);
tcg_temp_free_i64(tcg_hiaddr);
}
@@ -793,17 +798,21 @@ static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size)
TCGv_i64 tmphi;
if (size < 4) {
- TCGMemOp memop = MO_TE + size;
+ TCGMemOp memop = s->be_data + size;
tmphi = tcg_const_i64(0);
tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), memop);
} else {
+ bool be = s->be_data == MO_BE;
TCGv_i64 tcg_hiaddr;
+
tmphi = tcg_temp_new_i64();
tcg_hiaddr = tcg_temp_new_i64();
- tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), MO_TEQ);
tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
- tcg_gen_qemu_ld_i64(tmphi, tcg_hiaddr, get_mem_index(s), MO_TEQ);
+ tcg_gen_qemu_ld_i64(tmplo, be ? tcg_hiaddr : tcg_addr, get_mem_index(s),
+ s->be_data | MO_Q);
+ tcg_gen_qemu_ld_i64(tmphi, be ? tcg_addr : tcg_hiaddr, get_mem_index(s),
+ s->be_data | MO_Q);
tcg_temp_free_i64(tcg_hiaddr);
}
@@ -942,7 +951,7 @@ static void clear_vec_high(DisasContext *s, int rd)
static void do_vec_st(DisasContext *s, int srcidx, int element,
TCGv_i64 tcg_addr, int size)
{
- TCGMemOp memop = MO_TE + size;
+ TCGMemOp memop = s->be_data + size;
TCGv_i64 tcg_tmp = tcg_temp_new_i64();
read_vec_element(s, tcg_tmp, srcidx, element, size);
@@ -955,7 +964,7 @@ static void do_vec_st(DisasContext *s, int srcidx, int element,
static void do_vec_ld(DisasContext *s, int destidx, int element,
TCGv_i64 tcg_addr, int size)
{
- TCGMemOp memop = MO_TE + size;
+ TCGMemOp memop = s->be_data + size;
TCGv_i64 tcg_tmp = tcg_temp_new_i64();
tcg_gen_qemu_ld_i64(tcg_tmp, tcg_addr, get_mem_index(s), memop);
@@ -1702,7 +1711,7 @@ static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
TCGv_i64 addr, int size, bool is_pair)
{
TCGv_i64 tmp = tcg_temp_new_i64();
- TCGMemOp memop = MO_TE + size;
+ TCGMemOp memop = s->be_data + size;
g_assert(size <= 3);
tcg_gen_qemu_ld_i64(tmp, addr, get_mem_index(s), memop);
@@ -1764,7 +1773,7 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label);
tmp = tcg_temp_new_i64();
- tcg_gen_qemu_ld_i64(tmp, addr, get_mem_index(s), MO_TE + size);
+ tcg_gen_qemu_ld_i64(tmp, addr, get_mem_index(s), s->be_data + size);
tcg_gen_brcond_i64(TCG_COND_NE, tmp, cpu_exclusive_val, fail_label);
tcg_temp_free_i64(tmp);
@@ -1773,7 +1782,8 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
TCGv_i64 tmphi = tcg_temp_new_i64();
tcg_gen_addi_i64(addrhi, addr, 1 << size);
- tcg_gen_qemu_ld_i64(tmphi, addrhi, get_mem_index(s), MO_TE + size);
+ tcg_gen_qemu_ld_i64(tmphi, addrhi, get_mem_index(s),
+ s->be_data + size);
tcg_gen_brcond_i64(TCG_COND_NE, tmphi, cpu_exclusive_high, fail_label);
tcg_temp_free_i64(tmphi);
@@ -1781,13 +1791,14 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
}
/* We seem to still have the exclusive monitor, so do the store */
- tcg_gen_qemu_st_i64(cpu_reg(s, rt), addr, get_mem_index(s), MO_TE + size);
+ tcg_gen_qemu_st_i64(cpu_reg(s, rt), addr, get_mem_index(s),
+ s->be_data + size);
if (is_pair) {
TCGv_i64 addrhi = tcg_temp_new_i64();
tcg_gen_addi_i64(addrhi, addr, 1 << size);
tcg_gen_qemu_st_i64(cpu_reg(s, rt2), addrhi,
- get_mem_index(s), MO_TE + size);
+ get_mem_index(s), s->be_data + size);
tcg_temp_free_i64(addrhi);
}
@@ -2602,7 +2613,7 @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
TCGv_i64 tcg_tmp = tcg_temp_new_i64();
tcg_gen_qemu_ld_i64(tcg_tmp, tcg_addr,
- get_mem_index(s), MO_TE + scale);
+ get_mem_index(s), s->be_data + scale);
switch (scale) {
case 0:
mulconst = 0x0101010101010101ULL;
@@ -2632,9 +2643,9 @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
} else {
/* Load/store one element per register */
if (is_load) {
- do_vec_ld(s, rt, index, tcg_addr, MO_TE + scale);
+ do_vec_ld(s, rt, index, tcg_addr, s->be_data + scale);
} else {
- do_vec_st(s, rt, index, tcg_addr, MO_TE + scale);
+ do_vec_st(s, rt, index, tcg_addr, s->be_data + scale);
}
}
tcg_gen_addi_i64(tcg_addr, tcg_addr, ebytes);
--
1.9.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH v2 12/18] target-arm: introduce tbflag for endianness
2016-03-02 6:56 [Qemu-devel] [PATCH v2 00/18] ARM big-endian and setend support Peter Crosthwaite
` (10 preceding siblings ...)
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 11/18] target-arm: a64: Add endianness support Peter Crosthwaite
@ 2016-03-02 6:56 ` Peter Crosthwaite
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 13/18] target-arm: implement setend Peter Crosthwaite
` (6 subsequent siblings)
18 siblings, 0 replies; 24+ messages in thread
From: Peter Crosthwaite @ 2016-03-02 6:56 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, Peter Crosthwaite, sw, Andrew.Baumann,
alistair.francis, sridhar_kulk, qemu-arm, pbonzini, piotr.krol
From: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Introduce a tbflags for endianness, set based upon the CPUs current
endianness. This in turn propagates through to the disas endianness
flag.
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
changed since v1:
s/MOE/BE_DATA (PMM review)
target-arm/cpu.h | 7 +++++++
target-arm/translate-a64.c | 2 +-
target-arm/translate.c | 2 +-
3 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index cbf171c..279c91f 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1985,6 +1985,8 @@ static inline bool arm_cpu_data_is_big_endian(CPUARMState *env)
*/
#define ARM_TBFLAG_NS_SHIFT 19
#define ARM_TBFLAG_NS_MASK (1 << ARM_TBFLAG_NS_SHIFT)
+#define ARM_TBFLAG_BE_DATA_SHIFT 20
+#define ARM_TBFLAG_BE_DATA_MASK (1 << ARM_TBFLAG_BE_DATA_SHIFT)
/* Bit usage when in AArch64 state: currently we have no A64 specific bits */
@@ -2015,6 +2017,8 @@ static inline bool arm_cpu_data_is_big_endian(CPUARMState *env)
(((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)
+#define ARM_TBFLAG_BE_DATA(F) \
+ (((F) & ARM_TBFLAG_BE_DATA_MASK) >> ARM_TBFLAG_BE_DATA_SHIFT)
static inline bool bswap_code(bool sctlr_b)
{
@@ -2157,6 +2161,9 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
}
}
}
+ if (arm_cpu_data_is_big_endian(env)) {
+ *flags |= ARM_TBFLAG_BE_DATA_MASK;
+ }
*flags |= fp_exception_el(env) << ARM_TBFLAG_FPEXC_EL_SHIFT;
*cs_base = 0;
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 539e6d9..f0c73df 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -11043,7 +11043,7 @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
!arm_el_is_aa64(env, 3);
dc->thumb = 0;
dc->sctlr_b = 0;
- dc->be_data = MO_TE;
+ dc->be_data = ARM_TBFLAG_BE_DATA(tb->flags) ? MO_BE : MO_LE;
dc->condexec_mask = 0;
dc->condexec_cond = 0;
dc->mmu_idx = ARM_TBFLAG_MMUIDX(tb->flags);
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 88f24cb..fe0be00 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -11330,7 +11330,7 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
!arm_el_is_aa64(env, 3);
dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
dc->sctlr_b = ARM_TBFLAG_SCTLR_B(tb->flags);
- dc->be_data = MO_TE;
+ dc->be_data = ARM_TBFLAG_BE_DATA(tb->flags) ? MO_BE : MO_LE;
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);
--
1.9.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH v2 13/18] target-arm: implement setend
2016-03-02 6:56 [Qemu-devel] [PATCH v2 00/18] ARM big-endian and setend support Peter Crosthwaite
` (11 preceding siblings ...)
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 12/18] target-arm: introduce tbflag for endianness Peter Crosthwaite
@ 2016-03-02 6:56 ` Peter Crosthwaite
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 15/18] loader: add API to load elf header Peter Crosthwaite
` (5 subsequent siblings)
18 siblings, 0 replies; 24+ messages in thread
From: Peter Crosthwaite @ 2016-03-02 6:56 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, Peter Crosthwaite, sw, Andrew.Baumann,
alistair.francis, sridhar_kulk, qemu-arm, pbonzini, piotr.krol
From: Paolo Bonzini <pbonzini@redhat.com>
Since this is not a high-performance path, just use a helper to
flip the E bit and force a lookup in the hash table since the
flags have changed.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
---
target-arm/helper.h | 1 +
target-arm/op_helper.c | 5 +++++
target-arm/translate.c | 14 ++++++--------
3 files changed, 12 insertions(+), 8 deletions(-)
diff --git a/target-arm/helper.h b/target-arm/helper.h
index ea13202..e3d09d9 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -48,6 +48,7 @@ DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
i32, i32, i32, i32)
DEF_HELPER_2(exception_internal, void, env, i32)
DEF_HELPER_4(exception_with_syndrome, void, env, i32, i32, i32)
+DEF_HELPER_1(setend, void, env)
DEF_HELPER_1(wfi, void, env)
DEF_HELPER_1(wfe, void, env)
DEF_HELPER_1(yield, void, env)
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 4881e34..92fde0a 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -296,6 +296,11 @@ uint32_t HELPER(usat16)(CPUARMState *env, uint32_t x, uint32_t shift)
return res;
}
+void HELPER(setend)(CPUARMState *env)
+{
+ env->uncached_cpsr ^= CPSR_E;
+}
+
/* Function checks whether WFx (WFI/WFE) instructions are set up to be trapped.
* The function returns the target EL (1-3) if the instruction is to be trapped;
* otherwise it returns 0 indicating it is not trapped.
diff --git a/target-arm/translate.c b/target-arm/translate.c
index fe0be00..d0f13e2 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -7786,10 +7786,9 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
if ((insn & 0x0ffffdff) == 0x01010000) {
ARCH(6);
/* setend */
- 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;
+ if (((insn >> 9) & 1) != !!(s->be_data == MO_BE)) {
+ gen_helper_setend(cpu_env);
+ s->is_jmp = DISAS_UPDATE;
}
return;
} else if ((insn & 0x0fffff00) == 0x057ff000) {
@@ -11121,10 +11120,9 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
case 2:
/* setend */
ARCH(6);
- 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;
+ if (((insn >> 3) & 1) != !!(s->be_data == MO_BE)) {
+ gen_helper_setend(cpu_env);
+ s->is_jmp = DISAS_UPDATE;
}
break;
case 3:
--
1.9.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH v2 15/18] loader: add API to load elf header
2016-03-02 6:56 [Qemu-devel] [PATCH v2 00/18] ARM big-endian and setend support Peter Crosthwaite
` (12 preceding siblings ...)
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 13/18] target-arm: implement setend Peter Crosthwaite
@ 2016-03-02 6:56 ` Peter Crosthwaite
2016-03-03 15:24 ` Peter Maydell
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 16/18] loader: load_elf(): Add doc comment Peter Crosthwaite
` (4 subsequent siblings)
18 siblings, 1 reply; 24+ messages in thread
From: Peter Crosthwaite @ 2016-03-02 6:56 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, Peter Crosthwaite, sw, Andrew.Baumann,
alistair.francis, sridhar_kulk, qemu-arm, pbonzini, piotr.krol
Add an API to load an elf header header from a file. Populates a
buffer with the header contents, as well as a boolean for whether the
elf is 64b or not. Both arguments are optional.
Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
---
Changed since v1 (PMM review):
Add filname to error messages
Remove unneeded lseek()
Add doc comment
hw/core/loader.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++
include/hw/loader.h | 13 +++++++++++++
2 files changed, 68 insertions(+)
diff --git a/hw/core/loader.c b/hw/core/loader.c
index 3a57415..7d5e3a9 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -332,6 +332,61 @@ const char *load_elf_strerror(int error)
}
}
+void load_elf_hdr(const char *filename, void *hdr, bool *is64, Error **errp)
+{
+ int fd;
+ uint8_t e_ident_local[EI_NIDENT];
+ uint8_t *e_ident;
+ size_t hdr_size, off;
+ bool is64l;
+
+ if (!hdr) {
+ hdr = e_ident_local;
+ }
+ e_ident = hdr;
+
+ fd = open(filename, O_RDONLY | O_BINARY);
+ if (fd < 0) {
+ error_setg_errno(errp, errno, "Failed to open file: %s", filename);
+ return;
+ }
+ if (read(fd, hdr, EI_NIDENT) != EI_NIDENT) {
+ error_setg_errno(errp, errno, "Failed to read file: %s", filename);
+ goto fail;
+ }
+ if (e_ident[0] != ELFMAG0 ||
+ e_ident[1] != ELFMAG1 ||
+ e_ident[2] != ELFMAG2 ||
+ e_ident[3] != ELFMAG3) {
+ error_setg(errp, "Bad ELF magic");
+ goto fail;
+ }
+
+ is64l = e_ident[EI_CLASS] == ELFCLASS64;
+ hdr_size = is64l ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr);
+ if (is64) {
+ *is64 = is64l;
+ }
+
+ off = EI_NIDENT;
+ while (hdr != e_ident_local && off < hdr_size) {
+ size_t br = read(fd, hdr + off, hdr_size - off);
+ switch (br) {
+ case 0:
+ error_setg(errp, "File too short: %s", filename);
+ goto fail;
+ case -1:
+ error_setg_errno(errp, errno, "Failed to read file: %s",
+ filename);
+ goto fail;
+ }
+ off += br;
+ }
+
+fail:
+ close(fd);
+}
+
/* return < 0 if error, otherwise the number of bytes loaded in memory */
int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
diff --git a/include/hw/loader.h b/include/hw/loader.h
index f7b43ab..a626c9b 100644
--- a/include/hw/loader.h
+++ b/include/hw/loader.h
@@ -36,6 +36,19 @@ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
uint64_t *highaddr, int big_endian, int elf_machine,
int clear_lsb);
+
+/** load_elf_hdr:
+ * @filename: Path of ELF file
+ * @hdr: Buffer to populate with header data. Header data will not be
+ * filled if set to NULL.
+ * @is64: Set to true if the ELF is 64bit. Ignored if set to NULL
+ * @errp: Populated with an error in failure cases
+ *
+ * Inspect as ELF file's header. Read its full header contents into a
+ * buffer and/or determine if the ELF is 64bit.
+ */
+void load_elf_hdr(const char *filename, void *hdr, bool *is64, Error **errp);
+
int load_aout(const char *filename, hwaddr addr, int max_sz,
int bswap_needed, hwaddr target_page_size);
int load_uimage(const char *filename, hwaddr *ep,
--
1.9.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [Qemu-devel] [PATCH v2 15/18] loader: add API to load elf header
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 15/18] loader: add API to load elf header Peter Crosthwaite
@ 2016-03-03 15:24 ` Peter Maydell
0 siblings, 0 replies; 24+ messages in thread
From: Peter Maydell @ 2016-03-03 15:24 UTC (permalink / raw)
To: Peter Crosthwaite
Cc: Peter Crosthwaite, Stefan Weil, QEMU Developers, Andrew Baumann,
Alistair Francis, sridhar kulkarni, qemu-arm, Paolo Bonzini,
Piotr Król
On 2 March 2016 at 06:56, Peter Crosthwaite <crosthwaitepeter@gmail.com> wrote:
> Add an API to load an elf header header from a file. Populates a
> buffer with the header contents, as well as a boolean for whether the
> elf is 64b or not. Both arguments are optional.
>
> Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
> ---
> Changed since v1 (PMM review):
> Add filname to error messages
> Remove unneeded lseek()
> Add doc comment
> +/** load_elf_hdr:
> + * @filename: Path of ELF file
> + * @hdr: Buffer to populate with header data. Header data will not be
> + * filled if set to NULL.
> + * @is64: Set to true if the ELF is 64bit. Ignored if set to NULL
> + * @errp: Populated with an error in failure cases
> + *
> + * Inspect as ELF file's header. Read its full header contents into a
"an".
> + * buffer and/or determine if the ELF is 64bit.
> + */
Otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
thanks
-- PMM
^ permalink raw reply [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH v2 16/18] loader: load_elf(): Add doc comment
2016-03-02 6:56 [Qemu-devel] [PATCH v2 00/18] ARM big-endian and setend support Peter Crosthwaite
` (13 preceding siblings ...)
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 15/18] loader: add API to load elf header Peter Crosthwaite
@ 2016-03-02 6:56 ` Peter Crosthwaite
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 17/18] loader: Add data swap option to load-elf Peter Crosthwaite
` (3 subsequent siblings)
18 siblings, 0 replies; 24+ messages in thread
From: Peter Crosthwaite @ 2016-03-02 6:56 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, Peter Crosthwaite, sw, Andrew.Baumann,
alistair.francis, sridhar_kulk, qemu-arm, pbonzini, piotr.krol
Document the usage of load_elf() for clarity on current features.
Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
---
include/hw/loader.h | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/include/hw/loader.h b/include/hw/loader.h
index a626c9b..264ef89 100644
--- a/include/hw/loader.h
+++ b/include/hw/loader.h
@@ -32,6 +32,29 @@ int load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz);
#define ELF_LOAD_WRONG_ARCH -3
#define ELF_LOAD_WRONG_ENDIAN -4
const char *load_elf_strerror(int error);
+
+/** load_elf:
+ * @filename: Path of ELF file
+ * @translate_fn: optional function to translate load addresses
+ * @translate_opaque: opaque data passed to @translate_fn
+ * @pentry: Populated with program entry point. Ignored if NULL.
+ * @lowaddr: Populated with lowest loaded address. Ignored if NULL.
+ * @highaddr: Populated with highest loaded address. Ignored if NULL.
+ * @bigendian: Expected ELF endianness. 0 for LE otherwise BE
+ * @elf_machine: Expected ELF machine type
+ * @clear_lsb: Set to mask off LSB of addresses (Some architectures use
+ * this for non-address data)
+ *
+ * Load an ELF file's contents to the emulated system's address space.
+ * Clients may optionally specify a callback to perform address
+ * translations. @pentry, @lowaddr and @highaddr are optional pointers
+ * which will be populated with various load information. @bigendian and
+ * @elf_machine give the expected endianness and machine for the ELF the
+ * load will fail if the target ELF does not match. Some architectures
+ * have some architecture-specific behaviours that come into effect when
+ * their particular values for @elf_machine are set.
+ */
+
int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
uint64_t *highaddr, int big_endian, int elf_machine,
--
1.9.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH v2 17/18] loader: Add data swap option to load-elf
2016-03-02 6:56 [Qemu-devel] [PATCH v2 00/18] ARM big-endian and setend support Peter Crosthwaite
` (14 preceding siblings ...)
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 16/18] loader: load_elf(): Add doc comment Peter Crosthwaite
@ 2016-03-02 6:56 ` Peter Crosthwaite
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 18/18] arm: boot: Support big-endian elfs Peter Crosthwaite
` (2 subsequent siblings)
18 siblings, 0 replies; 24+ messages in thread
From: Peter Crosthwaite @ 2016-03-02 6:56 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, Peter Crosthwaite, sw, Andrew.Baumann,
alistair.francis, sridhar_kulk, qemu-arm, pbonzini, piotr.krol
Some CPUs are of an opposite data-endianness to other components in the
system. Sometimes elfs have the data sections layed out with this CPU
data-endianness accounting for when loaded via the CPU, so byte swaps
(relative to other system components) will occur.
The leading example, is ARM's BE32 mode, which is is basically LE with
address manipulation on half-word and byte accesses to access the
hw/byte reversed address. This means that word data is invariant
across LE and BE32. This also means that instructions are still LE.
The expectation is that the elf will be loaded via the CPU in this
endianness scheme, which means the data in the elf is reversed at
compile time.
As QEMU loads via the system memory directly, rather than the CPU, we
need a mechanism to reverse elf data endianness to implement this
possibility.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
---
changed since v1:
Added doc comment (PMM review)
Commit message typos
hw/alpha/dp264.c | 4 ++--
hw/arm/armv7m.c | 2 +-
hw/arm/boot.c | 2 +-
hw/core/loader.c | 9 ++++++---
hw/cris/boot.c | 2 +-
hw/i386/multiboot.c | 3 ++-
hw/lm32/lm32_boards.c | 4 ++--
hw/lm32/milkymist.c | 2 +-
hw/m68k/an5206.c | 2 +-
hw/m68k/dummy_m68k.c | 2 +-
hw/m68k/mcf5208.c | 2 +-
hw/microblaze/boot.c | 4 ++--
hw/mips/mips_fulong2e.c | 2 +-
hw/mips/mips_malta.c | 2 +-
hw/mips/mips_mipssim.c | 2 +-
hw/mips/mips_r4k.c | 2 +-
hw/moxie/moxiesim.c | 3 ++-
hw/openrisc/openrisc_sim.c | 3 ++-
hw/pci-host/prep.c | 2 +-
hw/ppc/e500.c | 2 +-
hw/ppc/mac_newworld.c | 5 +++--
hw/ppc/mac_oldworld.c | 5 +++--
hw/ppc/ppc440_bamboo.c | 3 ++-
hw/ppc/spapr.c | 6 ++++--
hw/ppc/virtex_ml507.c | 3 ++-
hw/s390x/ipl.c | 4 ++--
hw/sparc/leon3.c | 2 +-
hw/sparc/sun4m.c | 4 ++--
hw/sparc64/sun4u.c | 4 ++--
hw/tricore/tricore_testboard.c | 2 +-
hw/xtensa/sim.c | 4 ++--
hw/xtensa/xtfpga.c | 2 +-
include/hw/elf_ops.h | 22 +++++++++++++++++++++-
include/hw/loader.h | 5 ++++-
34 files changed, 81 insertions(+), 46 deletions(-)
diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c
index 992d1b2..7c5989b 100644
--- a/hw/alpha/dp264.c
+++ b/hw/alpha/dp264.c
@@ -111,7 +111,7 @@ static void clipper_init(MachineState *machine)
}
size = load_elf(palcode_filename, cpu_alpha_superpage_to_phys,
NULL, &palcode_entry, &palcode_low, &palcode_high,
- 0, EM_ALPHA, 0);
+ 0, EM_ALPHA, 0, 0);
if (size < 0) {
error_report("could not load palcode '%s'", palcode_filename);
exit(1);
@@ -131,7 +131,7 @@ static void clipper_init(MachineState *machine)
size = load_elf(kernel_filename, cpu_alpha_superpage_to_phys,
NULL, &kernel_entry, &kernel_low, &kernel_high,
- 0, EM_ALPHA, 0);
+ 0, EM_ALPHA, 0, 0);
if (size < 0) {
error_report("could not load kernel '%s'", kernel_filename);
exit(1);
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
index f3973f7..ed7d97f 100644
--- a/hw/arm/armv7m.c
+++ b/hw/arm/armv7m.c
@@ -211,7 +211,7 @@ DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
if (kernel_filename) {
image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
- NULL, big_endian, EM_ARM, 1);
+ NULL, big_endian, EM_ARM, 1, 0);
if (image_size < 0) {
image_size = load_image_targphys(kernel_filename, 0, mem_size);
lowaddr = 0;
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 0a56d34c..17400be 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -755,7 +755,7 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
/* Assume that raw images are linux kernels, and ELF images are not. */
kernel_size = load_elf(info->kernel_filename, NULL, NULL, &elf_entry,
&elf_low_addr, &elf_high_addr, big_endian,
- elf_machine, 1);
+ elf_machine, 1, 0);
if (kernel_size > 0 && have_dtb(info)) {
/* If there is still some room left at the base of RAM, try and put
* the DTB there like we do for images loaded with -bios or -pflash.
diff --git a/hw/core/loader.c b/hw/core/loader.c
index 7d5e3a9..79877ec 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -390,7 +390,8 @@ fail:
/* return < 0 if error, otherwise the number of bytes loaded in memory */
int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
- uint64_t *highaddr, int big_endian, int elf_machine, int clear_lsb)
+ uint64_t *highaddr, int big_endian, int elf_machine,
+ int clear_lsb, int data_swab)
{
int fd, data_order, target_data_order, must_swab, ret = ELF_LOAD_FAILED;
uint8_t e_ident[EI_NIDENT];
@@ -429,10 +430,12 @@ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
lseek(fd, 0, SEEK_SET);
if (e_ident[EI_CLASS] == ELFCLASS64) {
ret = load_elf64(filename, fd, translate_fn, translate_opaque, must_swab,
- pentry, lowaddr, highaddr, elf_machine, clear_lsb);
+ pentry, lowaddr, highaddr, elf_machine, clear_lsb,
+ data_swab);
} else {
ret = load_elf32(filename, fd, translate_fn, translate_opaque, must_swab,
- pentry, lowaddr, highaddr, elf_machine, clear_lsb);
+ pentry, lowaddr, highaddr, elf_machine, clear_lsb,
+ data_swab);
}
fail:
diff --git a/hw/cris/boot.c b/hw/cris/boot.c
index 6608160..42485a4 100644
--- a/hw/cris/boot.c
+++ b/hw/cris/boot.c
@@ -73,7 +73,7 @@ void cris_load_image(CRISCPU *cpu, struct cris_load_info *li)
/* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis
devboard SDK. */
image_size = load_elf(li->image_filename, translate_kernel_address, NULL,
- &entry, NULL, &high, 0, EM_CRIS, 0);
+ &entry, NULL, &high, 0, EM_CRIS, 0, 0);
li->entry = entry;
if (image_size < 0) {
/* Takes a kimage from the axis devboard SDK. */
diff --git a/hw/i386/multiboot.c b/hw/i386/multiboot.c
index c4d7d83..9e164e6 100644
--- a/hw/i386/multiboot.c
+++ b/hw/i386/multiboot.c
@@ -196,7 +196,8 @@ int load_multiboot(FWCfgState *fw_cfg,
}
kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
- &elf_low, &elf_high, 0, I386_ELF_MACHINE, 0);
+ &elf_low, &elf_high, 0, I386_ELF_MACHINE,
+ 0, 0);
if (kernel_size < 0) {
fprintf(stderr, "Error while loading elf kernel\n");
exit(1);
diff --git a/hw/lm32/lm32_boards.c b/hw/lm32/lm32_boards.c
index efa6f91..c5a848b 100644
--- a/hw/lm32/lm32_boards.c
+++ b/hw/lm32/lm32_boards.c
@@ -143,7 +143,7 @@ static void lm32_evr_init(MachineState *machine)
int kernel_size;
kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
- 1, EM_LATTICEMICO32, 0);
+ 1, EM_LATTICEMICO32, 0, 0);
reset_info->bootstrap_pc = entry;
if (kernel_size < 0) {
@@ -245,7 +245,7 @@ static void lm32_uclinux_init(MachineState *machine)
int kernel_size;
kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
- 1, EM_LATTICEMICO32, 0);
+ 1, EM_LATTICEMICO32, 0, 0);
reset_info->bootstrap_pc = entry;
if (kernel_size < 0) {
diff --git a/hw/lm32/milkymist.c b/hw/lm32/milkymist.c
index 5a37b4a..f71492e 100644
--- a/hw/lm32/milkymist.c
+++ b/hw/lm32/milkymist.c
@@ -177,7 +177,7 @@ milkymist_init(MachineState *machine)
/* Boots a kernel elf binary. */
kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
- 1, EM_LATTICEMICO32, 0);
+ 1, EM_LATTICEMICO32, 0, 0);
reset_info->bootstrap_pc = entry;
if (kernel_size < 0) {
diff --git a/hw/m68k/an5206.c b/hw/m68k/an5206.c
index d87b945..85f7277 100644
--- a/hw/m68k/an5206.c
+++ b/hw/m68k/an5206.c
@@ -73,7 +73,7 @@ static void an5206_init(MachineState *machine)
}
kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
- NULL, NULL, 1, EM_68K, 0);
+ NULL, NULL, 1, EM_68K, 0, 0);
entry = elf_entry;
if (kernel_size < 0) {
kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,
diff --git a/hw/m68k/dummy_m68k.c b/hw/m68k/dummy_m68k.c
index a213bcf..3c2174b 100644
--- a/hw/m68k/dummy_m68k.c
+++ b/hw/m68k/dummy_m68k.c
@@ -50,7 +50,7 @@ static void dummy_m68k_init(MachineState *machine)
/* Load kernel. */
if (kernel_filename) {
kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
- NULL, NULL, 1, EM_68K, 0);
+ NULL, NULL, 1, EM_68K, 0, 0);
entry = elf_entry;
if (kernel_size < 0) {
kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,
diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c
index 9597e86..4f49d34 100644
--- a/hw/m68k/mcf5208.c
+++ b/hw/m68k/mcf5208.c
@@ -276,7 +276,7 @@ static void mcf5208evb_init(MachineState *machine)
}
kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
- NULL, NULL, 1, EM_68K, 0);
+ NULL, NULL, 1, EM_68K, 0, 0);
entry = elf_entry;
if (kernel_size < 0) {
kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,
diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c
index 26cc378..c24014a 100644
--- a/hw/microblaze/boot.c
+++ b/hw/microblaze/boot.c
@@ -142,12 +142,12 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
/* Boots a kernel elf binary. */
kernel_size = load_elf(kernel_filename, NULL, NULL,
&entry, &low, &high,
- big_endian, EM_MICROBLAZE, 0);
+ big_endian, EM_MICROBLAZE, 0, 0);
base32 = entry;
if (base32 == 0xc0000000) {
kernel_size = load_elf(kernel_filename, translate_kernel_address,
NULL, &entry, NULL, NULL,
- big_endian, EM_MICROBLAZE, 0);
+ big_endian, EM_MICROBLAZE, 0, 0);
}
/* Always boot into physical ram. */
boot_info.bootstrap_pc = (uint32_t)entry;
diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c
index 184c404..4e5581b 100644
--- a/hw/mips/mips_fulong2e.c
+++ b/hw/mips/mips_fulong2e.c
@@ -117,7 +117,7 @@ static int64_t load_kernel (CPUMIPSState *env)
if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
(uint64_t *)&kernel_entry, (uint64_t *)&kernel_low,
- (uint64_t *)&kernel_high, 0, EM_MIPS, 1) < 0) {
+ (uint64_t *)&kernel_high, 0, EM_MIPS, 1, 0) < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
loaderparams.kernel_filename);
exit(1);
diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index c04aa2b..f5173c4 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -796,7 +796,7 @@ static int64_t load_kernel (void)
if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
(uint64_t *)&kernel_entry, NULL, (uint64_t *)&kernel_high,
- big_endian, EM_MIPS, 1) < 0) {
+ big_endian, EM_MIPS, 1, 0) < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
loaderparams.kernel_filename);
exit(1);
diff --git a/hw/mips/mips_mipssim.c b/hw/mips/mips_mipssim.c
index 8951ae9..1ecff44 100644
--- a/hw/mips/mips_mipssim.c
+++ b/hw/mips/mips_mipssim.c
@@ -70,7 +70,7 @@ static int64_t load_kernel(void)
kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
NULL, (uint64_t *)&entry, NULL,
(uint64_t *)&kernel_high, big_endian,
- EM_MIPS, 1);
+ EM_MIPS, 1, 0);
if (kernel_size >= 0) {
if ((entry & ~0x7fffffffULL) == 0x80000000)
entry = (int32_t)entry;
diff --git a/hw/mips/mips_r4k.c b/hw/mips/mips_r4k.c
index b6625ae..724b1e9 100644
--- a/hw/mips/mips_r4k.c
+++ b/hw/mips/mips_r4k.c
@@ -88,7 +88,7 @@ static int64_t load_kernel(void)
kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
NULL, (uint64_t *)&entry, NULL,
(uint64_t *)&kernel_high, big_endian,
- EM_MIPS, 1);
+ EM_MIPS, 1, 0);
if (kernel_size >= 0) {
if ((entry & ~0x7fffffffULL) == 0x80000000)
entry = (int32_t)entry;
diff --git a/hw/moxie/moxiesim.c b/hw/moxie/moxiesim.c
index 9191ae9..d88c942 100644
--- a/hw/moxie/moxiesim.c
+++ b/hw/moxie/moxiesim.c
@@ -54,7 +54,8 @@ static void load_kernel(MoxieCPU *cpu, LoaderParams *loader_params)
ram_addr_t initrd_offset;
kernel_size = load_elf(loader_params->kernel_filename, NULL, NULL,
- &entry, &kernel_low, &kernel_high, 1, EM_MOXIE, 0);
+ &entry, &kernel_low, &kernel_high, 1, EM_MOXIE,
+ 0, 0);
if (kernel_size <= 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c
index 25c637a..46418c3 100644
--- a/hw/openrisc/openrisc_sim.c
+++ b/hw/openrisc/openrisc_sim.c
@@ -69,7 +69,8 @@ static void cpu_openrisc_load_kernel(ram_addr_t ram_size,
if (kernel_filename && !qtest_enabled()) {
kernel_size = load_elf(kernel_filename, NULL, NULL,
- &elf_entry, NULL, NULL, 1, EM_OPENRISC, 1);
+ &elf_entry, NULL, NULL, 1, EM_OPENRISC,
+ 1, 0);
entry = elf_entry;
if (kernel_size < 0) {
kernel_size = load_uimage(kernel_filename,
diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c
index 5dc550f..49cdaab 100644
--- a/hw/pci-host/prep.c
+++ b/hw/pci-host/prep.c
@@ -313,7 +313,7 @@ static void raven_realize(PCIDevice *d, Error **errp)
if (filename) {
if (s->elf_machine != EM_NONE) {
bios_size = load_elf(filename, NULL, NULL, NULL,
- NULL, NULL, 1, s->elf_machine, 0);
+ NULL, NULL, 1, s->elf_machine, 0, 0);
}
if (bios_size < 0) {
bios_size = get_image_size(filename);
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index bd84e9a..09154fa 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -1017,7 +1017,7 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
bios_size = load_elf(filename, NULL, NULL, &bios_entry, &loadaddr, NULL,
- 1, PPC_ELF_MACHINE, 0);
+ 1, PPC_ELF_MACHINE, 0, 0);
if (bios_size < 0) {
/*
* Hrm. No ELF image? Try a uImage, maybe someone is giving us an
diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
index f95086b..f0a36b3 100644
--- a/hw/ppc/mac_newworld.c
+++ b/hw/ppc/mac_newworld.c
@@ -221,7 +221,7 @@ static void ppc_core99_init(MachineState *machine)
/* Load OpenBIOS (ELF) */
if (filename) {
bios_size = load_elf(filename, NULL, NULL, NULL,
- NULL, NULL, 1, PPC_ELF_MACHINE, 0);
+ NULL, NULL, 1, PPC_ELF_MACHINE, 0, 0);
g_free(filename);
} else {
@@ -244,7 +244,8 @@ static void ppc_core99_init(MachineState *machine)
kernel_base = KERNEL_LOAD_ADDR;
kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
- NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE, 0);
+ NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE,
+ 0, 0);
if (kernel_size < 0)
kernel_size = load_aout(kernel_filename, kernel_base,
ram_size - kernel_base, bswap_needed,
diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index 8984398..d952713 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -149,7 +149,7 @@ static void ppc_heathrow_init(MachineState *machine)
/* Load OpenBIOS (ELF) */
if (filename) {
bios_size = load_elf(filename, 0, NULL, NULL, NULL, NULL,
- 1, PPC_ELF_MACHINE, 0);
+ 1, PPC_ELF_MACHINE, 0, 0);
g_free(filename);
} else {
bios_size = -1;
@@ -170,7 +170,8 @@ static void ppc_heathrow_init(MachineState *machine)
#endif
kernel_base = KERNEL_LOAD_ADDR;
kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
- NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE, 0);
+ NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE,
+ 0, 0);
if (kernel_size < 0)
kernel_size = load_aout(kernel_filename, kernel_base,
ram_size - kernel_base, bswap_needed,
diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
index e535a9f..5c535b1 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -256,7 +256,8 @@ static void bamboo_init(MachineState *machine)
NULL, NULL);
if (success < 0) {
success = load_elf(kernel_filename, NULL, NULL, &elf_entry,
- &elf_lowaddr, NULL, 1, PPC_ELF_MACHINE, 0);
+ &elf_lowaddr, NULL, 1, PPC_ELF_MACHINE,
+ 0, 0);
entry = elf_entry;
loadaddr = elf_lowaddr;
}
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index c119f55..0f42a8e 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1942,11 +1942,13 @@ static void ppc_spapr_init(MachineState *machine)
uint64_t lowaddr = 0;
kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
- NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE, 0);
+ NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE,
+ 0, 0);
if (kernel_size == ELF_LOAD_WRONG_ENDIAN) {
kernel_size = load_elf(kernel_filename,
translate_kernel_address, NULL,
- NULL, &lowaddr, NULL, 0, PPC_ELF_MACHINE, 0);
+ NULL, &lowaddr, NULL, 0, PPC_ELF_MACHINE,
+ 0, 0);
kernel_le = kernel_size > 0;
}
if (kernel_size < 0) {
diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c
index a902c88..b807a08 100644
--- a/hw/ppc/virtex_ml507.c
+++ b/hw/ppc/virtex_ml507.c
@@ -258,7 +258,8 @@ static void virtex_init(MachineState *machine)
/* Boots a kernel elf binary. */
kernel_size = load_elf(kernel_filename, NULL, NULL,
- &entry, &low, &high, 1, PPC_ELF_MACHINE, 0);
+ &entry, &low, &high, 1, PPC_ELF_MACHINE,
+ 0, 0);
boot_info.bootstrap_pc = entry & 0x00ffffff;
if (kernel_size < 0) {
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index c9cf7cc..41ff002 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -101,7 +101,7 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp)
bios_size = load_elf(bios_filename, bios_translate_addr, &fwbase,
&ipl->bios_start_addr, NULL, NULL, 1,
- EM_S390, 0);
+ EM_S390, 0, 0);
if (bios_size > 0) {
/* Adjust ELF start address to final location */
ipl->bios_start_addr += fwbase;
@@ -124,7 +124,7 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp)
if (ipl->kernel) {
kernel_size = load_elf(ipl->kernel, NULL, NULL, &pentry, NULL,
- NULL, 1, EM_S390, 0);
+ NULL, 1, EM_S390, 0, 0);
if (kernel_size < 0) {
kernel_size = load_image_targphys(ipl->kernel, 0, ram_size);
}
diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c
index 07c5c85..c579f5b 100644
--- a/hw/sparc/leon3.c
+++ b/hw/sparc/leon3.c
@@ -194,7 +194,7 @@ static void leon3_generic_hw_init(MachineState *machine)
uint64_t entry;
kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
- 1 /* big endian */, EM_SPARC, 0);
+ 1 /* big endian */, EM_SPARC, 0, 0);
if (kernel_size < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
kernel_filename);
diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
index 20dc341..eebef37 100644
--- a/hw/sparc/sun4m.c
+++ b/hw/sparc/sun4m.c
@@ -279,7 +279,7 @@ static unsigned long sun4m_load_kernel(const char *kernel_filename,
bswap_needed = 0;
#endif
kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
- NULL, NULL, NULL, 1, EM_SPARC, 0);
+ NULL, NULL, NULL, 1, EM_SPARC, 0, 0);
if (kernel_size < 0)
kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
RAM_size - KERNEL_LOAD_ADDR, bswap_needed,
@@ -723,7 +723,7 @@ static void prom_init(hwaddr addr, const char *bios_name)
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
if (filename) {
ret = load_elf(filename, translate_prom_address, &addr, NULL,
- NULL, NULL, 1, EM_SPARC, 0);
+ NULL, NULL, 1, EM_SPARC, 0, 0);
if (ret < 0 || ret > PROM_SIZE_MAX) {
ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
}
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index add1e75..0a6f453 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -187,7 +187,7 @@ static uint64_t sun4u_load_kernel(const char *kernel_filename,
bswap_needed = 0;
#endif
kernel_size = load_elf(kernel_filename, NULL, NULL, kernel_entry,
- kernel_addr, &kernel_top, 1, EM_SPARCV9, 0);
+ kernel_addr, &kernel_top, 1, EM_SPARCV9, 0, 0);
if (kernel_size < 0) {
*kernel_addr = KERNEL_LOAD_ADDR;
*kernel_entry = KERNEL_LOAD_ADDR;
@@ -633,7 +633,7 @@ static void prom_init(hwaddr addr, const char *bios_name)
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
if (filename) {
ret = load_elf(filename, translate_prom_address, &addr,
- NULL, NULL, NULL, 1, EM_SPARCV9, 0);
+ NULL, NULL, NULL, 1, EM_SPARCV9, 0, 0);
if (ret < 0 || ret > PROM_SIZE_MAX) {
ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
}
diff --git a/hw/tricore/tricore_testboard.c b/hw/tricore/tricore_testboard.c
index 9392571..3cadb65 100644
--- a/hw/tricore/tricore_testboard.c
+++ b/hw/tricore/tricore_testboard.c
@@ -45,7 +45,7 @@ static void tricore_load_kernel(CPUTriCoreState *env)
kernel_size = load_elf(tricoretb_binfo.kernel_filename, NULL,
NULL, (uint64_t *)&entry, NULL,
NULL, 0,
- EM_TRICORE, 1);
+ EM_TRICORE, 1, 0);
if (kernel_size <= 0) {
error_report("qemu: no kernel file '%s'",
tricoretb_binfo.kernel_filename);
diff --git a/hw/xtensa/sim.c b/hw/xtensa/sim.c
index 3a5060b..23050e8 100644
--- a/hw/xtensa/sim.c
+++ b/hw/xtensa/sim.c
@@ -94,10 +94,10 @@ static void xtensa_sim_init(MachineState *machine)
uint64_t elf_lowaddr;
#ifdef TARGET_WORDS_BIGENDIAN
int success = load_elf(kernel_filename, translate_phys_addr, cpu,
- &elf_entry, &elf_lowaddr, NULL, 1, EM_XTENSA, 0);
+ &elf_entry, &elf_lowaddr, NULL, 1, EM_XTENSA, 0, 0);
#else
int success = load_elf(kernel_filename, translate_phys_addr, cpu,
- &elf_entry, &elf_lowaddr, NULL, 0, EM_XTENSA, 0);
+ &elf_entry, &elf_lowaddr, NULL, 0, EM_XTENSA, 0, 0);
#endif
if (success > 0) {
env->pc = elf_entry;
diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c
index fe7684d..ed09b9d 100644
--- a/hw/xtensa/xtfpga.c
+++ b/hw/xtensa/xtfpga.c
@@ -355,7 +355,7 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine)
uint64_t elf_entry;
uint64_t elf_lowaddr;
int success = load_elf(kernel_filename, translate_phys_addr, cpu,
- &elf_entry, &elf_lowaddr, NULL, be, EM_XTENSA, 0);
+ &elf_entry, &elf_lowaddr, NULL, be, EM_XTENSA, 0, 0);
if (success > 0) {
entry_point = elf_entry;
} else {
diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h
index 0010c44..f510e7e 100644
--- a/include/hw/elf_ops.h
+++ b/include/hw/elf_ops.h
@@ -263,7 +263,7 @@ static int glue(load_elf, SZ)(const char *name, int fd,
void *translate_opaque,
int must_swab, uint64_t *pentry,
uint64_t *lowaddr, uint64_t *highaddr,
- int elf_machine, int clear_lsb)
+ int elf_machine, int clear_lsb, int data_swab)
{
struct elfhdr ehdr;
struct elf_phdr *phdr = NULL, *ph;
@@ -366,6 +366,26 @@ static int glue(load_elf, SZ)(const char *name, int fd,
addr = ph->p_paddr;
}
+ if (data_swab) {
+ int j;
+ for (j = 0; j < file_size; j += (1 << data_swab)) {
+ uint8_t *dp = data + j;
+ switch (data_swab) {
+ case (1):
+ *(uint16_t *)dp = bswap16(*(uint16_t *)dp);
+ break;
+ case (2):
+ *(uint32_t *)dp = bswap32(*(uint32_t *)dp);
+ break;
+ case (3):
+ *(uint64_t *)dp = bswap64(*(uint64_t *)dp);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ }
+ }
+
/* the entry pointer in the ELF header is a virtual
* address, if the text segments paddr and vaddr differ
* we need to adjust the entry */
diff --git a/include/hw/loader.h b/include/hw/loader.h
index 264ef89..d68e222 100644
--- a/include/hw/loader.h
+++ b/include/hw/loader.h
@@ -44,6 +44,9 @@ const char *load_elf_strerror(int error);
* @elf_machine: Expected ELF machine type
* @clear_lsb: Set to mask off LSB of addresses (Some architectures use
* this for non-address data)
+ * @data_swab: Set to order of byte swapping for data. 0 for no swap, 1
+ * for swapping bytes within halfwords, 2 for bytes within
+ * words and 3 for within doublewords.
*
* Load an ELF file's contents to the emulated system's address space.
* Clients may optionally specify a callback to perform address
@@ -58,7 +61,7 @@ const char *load_elf_strerror(int error);
int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
uint64_t *highaddr, int big_endian, int elf_machine,
- int clear_lsb);
+ int clear_lsb, int data_swab);
/** load_elf_hdr:
* @filename: Path of ELF file
--
1.9.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [Qemu-devel] [PATCH v2 18/18] arm: boot: Support big-endian elfs
2016-03-02 6:56 [Qemu-devel] [PATCH v2 00/18] ARM big-endian and setend support Peter Crosthwaite
` (15 preceding siblings ...)
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 17/18] loader: Add data swap option to load-elf Peter Crosthwaite
@ 2016-03-02 6:56 ` Peter Crosthwaite
2016-03-03 15:23 ` Peter Maydell
2016-03-03 15:25 ` [Qemu-devel] [PATCH v2 00/18] ARM big-endian and setend support Peter Maydell
[not found] ` <130944d3702e4184b48ff43096aabfeb24f0bdf3.1456901522.git.crosthwaite.peter@gmail.com>
18 siblings, 1 reply; 24+ messages in thread
From: Peter Crosthwaite @ 2016-03-02 6:56 UTC (permalink / raw)
To: qemu-devel
Cc: peter.maydell, Peter Crosthwaite, sw, Andrew.Baumann,
alistair.francis, sridhar_kulk, qemu-arm, pbonzini, piotr.krol
Support ARM big-endian ELF files in system-mode emulation. When loading
an elf, determine the endianness mode expected by the elf, and set the
relevant CPU state accordingly.
With this, big-endian modes are now fully supported via system-mode LE,
so there is no need to restrict the elf loading to the TARGET
endianness so the ifdeffery on TARGET_WORDS_BIGENDIAN goes away.
Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
---
Changed since v1:
Factor out elf manipulation logic into static helper (PMM review)
hw/arm/boot.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++------
include/hw/arm/arm.h | 9 +++++
2 files changed, 92 insertions(+), 10 deletions(-)
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 17400be..13aad42 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -518,9 +518,34 @@ static void do_cpu_reset(void *opaque)
cpu_reset(cs);
if (info) {
if (!info->is_linux) {
+ int i;
/* Jump to the entry point. */
uint64_t entry = info->entry;
+ switch (info->endianness) {
+ case ARM_ENDIANNESS_LE:
+ env->cp15.sctlr_el[1] &= ~SCTLR_E0E;
+ for (i = 1; i < 4; ++i) {
+ env->cp15.sctlr_el[i] &= ~SCTLR_EE;
+ }
+ env->uncached_cpsr &= ~CPSR_E;
+ break;
+ case ARM_ENDIANNESS_BE8:
+ env->cp15.sctlr_el[1] |= SCTLR_E0E;
+ for (i = 1; i < 4; ++i) {
+ env->cp15.sctlr_el[i] |= SCTLR_EE;
+ }
+ env->uncached_cpsr |= CPSR_E;
+ break;
+ case ARM_ENDIANNESS_BE32:
+ env->cp15.sctlr_el[1] |= SCTLR_B;
+ break;
+ case ARM_ENDIANNESS_UNKNOWN:
+ break; /* Board's decision */
+ default:
+ g_assert_not_reached();
+ }
+
if (!env->aarch64) {
env->thumb = info->entry & 1;
entry &= 0xfffffffe;
@@ -638,6 +663,62 @@ static int do_arm_linux_init(Object *obj, void *opaque)
return 0;
}
+static uint64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry,
+ uint64_t *lowaddr, uint64_t *highaddr,
+ int elf_machine)
+{
+ bool elf_is64;
+ union {
+ Elf32_Ehdr h32;
+ Elf64_Ehdr h64;
+ } elf_header;
+ int data_swab = 0;
+ bool big_endian;
+ uint64_t ret = -1;
+ Error *err = NULL;
+
+
+ load_elf_hdr(info->kernel_filename, &elf_header, &elf_is64, &err);
+ if (err) {
+ return ret;
+ }
+
+ if (elf_is64) {
+ big_endian = elf_header.h64.e_ident[EI_DATA] == ELFDATA2MSB;
+ info->endianness = big_endian ? ARM_ENDIANNESS_BE8
+ : ARM_ENDIANNESS_LE;
+ } else {
+ big_endian = elf_header.h32.e_ident[EI_DATA] == ELFDATA2MSB;
+ if (big_endian) {
+ if (bswap32(elf_header.h32.e_flags) & EF_ARM_BE8) {
+ info->endianness = ARM_ENDIANNESS_BE8;
+ } else {
+ info->endianness = ARM_ENDIANNESS_BE32;
+ /* In BE32, the CPU has a different view of the per-byte
+ * address map than the rest of the system. BE32 elfs are
+ * organised such that they can be programmed through the
+ * CPUs per-word byte-reversed view of the world. QEMU
+ * however loads elfs independently of the CPU. So tell
+ * the elf loader to byte reverse the data for us.
+ */
+ data_swab = 2;
+ }
+ } else {
+ info->endianness = ARM_ENDIANNESS_LE;
+ }
+ }
+
+ ret = load_elf(info->kernel_filename, NULL, NULL,
+ pentry, lowaddr, highaddr, big_endian, elf_machine,
+ 1, data_swab);
+ if (ret <= 0) {
+ /* The header loaded but the image didn't */
+ exit(1);
+ }
+
+ return ret;
+}
+
static void arm_load_kernel_notify(Notifier *notifier, void *data)
{
CPUState *cs;
@@ -647,7 +728,6 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
uint64_t elf_entry, elf_low_addr, elf_high_addr;
int elf_machine;
hwaddr entry, kernel_load_offset;
- int big_endian;
static const ARMInsnFixup *primary_loader;
ArmLoadKernelNotifier *n = DO_UPCAST(ArmLoadKernelNotifier,
notifier, notifier);
@@ -733,12 +813,6 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
if (info->nb_cpus == 0)
info->nb_cpus = 1;
-#ifdef TARGET_WORDS_BIGENDIAN
- big_endian = 1;
-#else
- big_endian = 0;
-#endif
-
/* We want to put the initrd far enough into RAM that when the
* kernel is uncompressed it will not clobber the initrd. However
* on boards without much RAM we must ensure that we still leave
@@ -753,9 +827,8 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
MIN(info->ram_size / 2, 128 * 1024 * 1024);
/* Assume that raw images are linux kernels, and ELF images are not. */
- kernel_size = load_elf(info->kernel_filename, NULL, NULL, &elf_entry,
- &elf_low_addr, &elf_high_addr, big_endian,
- elf_machine, 1, 0);
+ kernel_size = arm_load_elf(info, &elf_entry, &elf_low_addr,
+ &elf_high_addr, elf_machine);
if (kernel_size > 0 && have_dtb(info)) {
/* If there is still some room left at the base of RAM, try and put
* the DTB there like we do for images loaded with -bios or -pflash.
diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h
index 52ecf4a..b2517f9 100644
--- a/include/hw/arm/arm.h
+++ b/include/hw/arm/arm.h
@@ -16,6 +16,13 @@
#include "qemu/notify.h"
#include "cpu.h"
+typedef enum {
+ ARM_ENDIANNESS_UNKNOWN = 0,
+ ARM_ENDIANNESS_LE,
+ ARM_ENDIANNESS_BE8,
+ ARM_ENDIANNESS_BE32,
+} arm_endianness;
+
/* armv7m.c */
DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
const char *kernel_filename, const char *cpu_model);
@@ -103,6 +110,8 @@ struct arm_boot_info {
* changing to non-secure state if implementing a non-secure boot
*/
bool secure_board_setup;
+
+ arm_endianness endianness;
};
/**
--
1.9.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [Qemu-devel] [PATCH v2 18/18] arm: boot: Support big-endian elfs
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 18/18] arm: boot: Support big-endian elfs Peter Crosthwaite
@ 2016-03-03 15:23 ` Peter Maydell
0 siblings, 0 replies; 24+ messages in thread
From: Peter Maydell @ 2016-03-03 15:23 UTC (permalink / raw)
To: Peter Crosthwaite
Cc: Peter Crosthwaite, Stefan Weil, QEMU Developers, Andrew Baumann,
Alistair Francis, sridhar kulkarni, qemu-arm, Paolo Bonzini,
Piotr Król
On 2 March 2016 at 06:56, Peter Crosthwaite <crosthwaitepeter@gmail.com> wrote:
> Support ARM big-endian ELF files in system-mode emulation. When loading
> an elf, determine the endianness mode expected by the elf, and set the
> relevant CPU state accordingly.
>
> With this, big-endian modes are now fully supported via system-mode LE,
> so there is no need to restrict the elf loading to the TARGET
> endianness so the ifdeffery on TARGET_WORDS_BIGENDIAN goes away.
>
> Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
> ---
> + /* In BE32, the CPU has a different view of the per-byte
> + * address map than the rest of the system. BE32 elfs are
> + * organised such that they can be programmed through the
> + * CPUs per-word byte-reversed view of the world. QEMU
"CPU's".
> + * however loads elfs independently of the CPU. So tell
> + * the elf loader to byte reverse the data for us.
> + */
Otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
thanks
-- PMM
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [Qemu-devel] [PATCH v2 00/18] ARM big-endian and setend support
2016-03-02 6:56 [Qemu-devel] [PATCH v2 00/18] ARM big-endian and setend support Peter Crosthwaite
` (16 preceding siblings ...)
2016-03-02 6:56 ` [Qemu-devel] [PATCH v2 18/18] arm: boot: Support big-endian elfs Peter Crosthwaite
@ 2016-03-03 15:25 ` Peter Maydell
2016-03-03 15:40 ` Paolo Bonzini
[not found] ` <130944d3702e4184b48ff43096aabfeb24f0bdf3.1456901522.git.crosthwaite.peter@gmail.com>
18 siblings, 1 reply; 24+ messages in thread
From: Peter Maydell @ 2016-03-03 15:25 UTC (permalink / raw)
To: Peter Crosthwaite
Cc: Peter Crosthwaite, Stefan Weil, QEMU Developers, Andrew Baumann,
Alistair Francis, sridhar kulkarni, qemu-arm, Paolo Bonzini,
Piotr Król
On 2 March 2016 at 06:56, Peter Crosthwaite <crosthwaitepeter@gmail.com> wrote:
> Hi All,
>
> This patch series adds system-mode big-endian support for ARM. It also
> implements the setend instruction, and loading of BE binaries even in
> LE emulation mode.
>
> Based on Paolo's original work.
>
> I have tested all of LE, BE8 and BE32 in both linux-user mode (for
> regressions) and system mode (BE8 and BE32 are new here).
> My test application is here, the README gives some example command
> lines you can run:
>
> https://github.com/pcrost/arm-be-test
>
> Regards,
> Peter
>
> Changed since v1:
> Addressed PMM review
> Added doc comments to new/changed loader.h APIs
Thanks for the respin. For the remaining patches:
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Since there were only a couple of comment typos I'm planning to
apply this series to target-arm.next (and send a pullreq tomorrow
I expect).
thanks
-- PMM
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [Qemu-devel] [PATCH v2 00/18] ARM big-endian and setend support
2016-03-03 15:25 ` [Qemu-devel] [PATCH v2 00/18] ARM big-endian and setend support Peter Maydell
@ 2016-03-03 15:40 ` Paolo Bonzini
0 siblings, 0 replies; 24+ messages in thread
From: Paolo Bonzini @ 2016-03-03 15:40 UTC (permalink / raw)
To: Peter Maydell, Peter Crosthwaite
Cc: Peter Crosthwaite, Stefan Weil, QEMU Developers, Andrew Baumann,
Alistair Francis, sridhar kulkarni, qemu-arm, Piotr Król
On 03/03/2016 16:25, Peter Maydell wrote:
> On 2 March 2016 at 06:56, Peter Crosthwaite <crosthwaitepeter@gmail.com> wrote:
>> Hi All,
>>
>> This patch series adds system-mode big-endian support for ARM. It also
>> implements the setend instruction, and loading of BE binaries even in
>> LE emulation mode.
>>
>> Based on Paolo's original work.
>>
>> I have tested all of LE, BE8 and BE32 in both linux-user mode (for
>> regressions) and system mode (BE8 and BE32 are new here).
>> My test application is here, the README gives some example command
>> lines you can run:
>>
>> https://github.com/pcrost/arm-be-test
>>
>> Regards,
>> Peter
>>
>> Changed since v1:
>> Addressed PMM review
>> Added doc comments to new/changed loader.h APIs
>
> Thanks for the respin. For the remaining patches:
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
>
> Since there were only a couple of comment typos I'm planning to
> apply this series to target-arm.next (and send a pullreq tomorrow
> I expect).
Yay, thanks Peter (both of you)!
Paolo
^ permalink raw reply [flat|nested] 24+ messages in thread
[parent not found: <130944d3702e4184b48ff43096aabfeb24f0bdf3.1456901522.git.crosthwaite.peter@gmail.com>]
* Re: [Qemu-devel] [PATCH v2 14/18] target-arm: implement BE32 mode in system emulation
[not found] ` <130944d3702e4184b48ff43096aabfeb24f0bdf3.1456901522.git.crosthwaite.peter@gmail.com>
@ 2016-03-03 15:27 ` Peter Maydell
0 siblings, 0 replies; 24+ messages in thread
From: Peter Maydell @ 2016-03-03 15:27 UTC (permalink / raw)
To: Peter Crosthwaite
Cc: Peter Crosthwaite, Stefan Weil, QEMU Developers, Andrew Baumann,
Alistair Francis, sridhar kulkarni, qemu-arm, Paolo Bonzini,
Piotr Król
On 2 March 2016 at 06:56, Peter Crosthwaite <crosthwaitepeter@gmail.com> wrote:
> From: Paolo Bonzini <pbonzini@redhat.com>
>
> System emulation only has a little-endian target; BE32 mode
> is implemented by adjusting the low bits of the address
> for every byte and halfword load and store. 64-bit accesses
> flip the low and high words.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> [PC changes:
> * rebased against master (Jan 2016)
> ]
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
> ---
> fix ld/st copy-paste error (PMM review)
This mail didn't make it to qemu-devel for some reason...
(maybe the spam filters caught it ? :-( )
-- PMM
^ permalink raw reply [flat|nested] 24+ messages in thread