[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 24/30] target-arm: implement BE32 mode in system emul
From: |
Peter Maydell |
Subject: |
[Qemu-devel] [PULL 24/30] target-arm: implement BE32 mode in system emulation |
Date: |
Fri, 4 Mar 2016 11:41:47 +0000 |
From: Paolo Bonzini <address@hidden>
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 <address@hidden>
[PC changes:
* rebased against master (Jan 2016)
]
Reviewed-by: Peter Maydell <address@hidden>
Signed-off-by: Peter Crosthwaite <address@hidden>
Signed-off-by: Peter Maydell <address@hidden>
---
target-arm/cpu.h | 5 ++-
target-arm/translate.c | 86 +++++++++++++++++++++++++++++++++++++++++---------
2 files changed, 73 insertions(+), 18 deletions(-)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 279c91f..066ff67 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -2033,9 +2033,8 @@ static inline bool bswap_code(bool sctlr_b)
#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.
+ /* All code access in ARM is little endian, and there are no loaders
+ * doing swaps that need to be reversed
*/
return 0;
#endif
diff --git a/target-arm/translate.c b/target-arm/translate.c
index c23ddb3..25db09e 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -911,6 +911,12 @@ static inline void store_reg_from_load(DisasContext *s,
int reg, TCGv_i32 var)
}
}
+#ifdef CONFIG_USER_ONLY
+#define IS_USER_ONLY 1
+#else
+#define IS_USER_ONLY 0
+#endif
+
/* Abstractions of "generate code to do a guest load/store for
* AArch32", where a vaddr is always 32 bits (and is zero
* extended if we're a 64 bit core) and data is also
@@ -920,19 +926,35 @@ 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) \
+#define DO_GEN_LD(SUFF, OPC, BE32_XOR) \
static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, \
TCGv_i32 addr, int index) \
{ \
TCGMemOp opc = (OPC) | s->be_data; \
+ /* Not needed for user-mode BE32, where we use MO_BE instead. */ \
+ if (!IS_USER_ONLY && s->sctlr_b && BE32_XOR) { \
+ TCGv addr_be = tcg_temp_new(); \
+ tcg_gen_xori_i32(addr_be, addr, BE32_XOR); \
+ tcg_gen_qemu_ld_i32(val, addr_be, index, opc); \
+ tcg_temp_free(addr_be); \
+ return; \
+ } \
tcg_gen_qemu_ld_i32(val, addr, index, opc); \
}
-#define DO_GEN_ST(SUFF, OPC) \
+#define DO_GEN_ST(SUFF, OPC, BE32_XOR) \
static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, \
TCGv_i32 addr, int index) \
{ \
TCGMemOp opc = (OPC) | s->be_data; \
+ /* Not needed for user-mode BE32, where we use MO_BE instead. */ \
+ if (!IS_USER_ONLY && s->sctlr_b && BE32_XOR) { \
+ TCGv addr_be = tcg_temp_new(); \
+ tcg_gen_xori_i32(addr_be, addr, BE32_XOR); \
+ tcg_gen_qemu_st_i32(val, addr_be, index, opc); \
+ tcg_temp_free(addr_be); \
+ return; \
+ } \
tcg_gen_qemu_st_i32(val, addr, index, opc); \
}
@@ -941,35 +963,55 @@ static inline void gen_aa32_ld64(DisasContext *s,
TCGv_i64 val,
{
TCGMemOp opc = MO_Q | s->be_data;
tcg_gen_qemu_ld_i64(val, addr, index, opc);
+ /* Not needed for user-mode BE32, where we use MO_BE instead. */
+ if (!IS_USER_ONLY && s->sctlr_b) {
+ tcg_gen_rotri_i64(val, val, 32);
+ }
}
static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
TCGv_i32 addr, int index)
{
TCGMemOp opc = MO_Q | s->be_data;
+ /* Not needed for user-mode BE32, where we use MO_BE instead. */
+ if (!IS_USER_ONLY && s->sctlr_b) {
+ TCGv_i64 tmp = tcg_temp_new_i64();
+ tcg_gen_rotri_i64(tmp, val, 32);
+ tcg_gen_qemu_st_i64(tmp, addr, index, opc);
+ tcg_temp_free_i64(tmp);
+ return;
+ }
tcg_gen_qemu_st_i64(val, addr, index, opc);
}
#else
-#define DO_GEN_LD(SUFF, OPC) \
+#define DO_GEN_LD(SUFF, OPC, BE32_XOR) \
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); \
+ /* Not needed for user-mode BE32, where we use MO_BE instead. */ \
+ if (!IS_USER_ONLY && s->sctlr_b && BE32_XOR) { \
+ tcg_gen_xori_i64(addr64, addr64, BE32_XOR); \
+ } \
tcg_gen_qemu_ld_i32(val, addr64, index, opc); \
tcg_temp_free(addr64); \
}
-#define DO_GEN_ST(SUFF, OPC) \
+#define DO_GEN_ST(SUFF, OPC, BE32_XOR) \
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); \
+ /* Not needed for user-mode BE32, where we use MO_BE instead. */ \
+ if (!IS_USER_ONLY && s->sctlr_b && BE32_XOR) { \
+ tcg_gen_xori_i64(addr64, addr64, BE32_XOR); \
+ } \
tcg_gen_qemu_st_i32(val, addr64, index, opc); \
tcg_temp_free(addr64); \
}
@@ -981,6 +1023,11 @@ static inline void gen_aa32_ld64(DisasContext *s,
TCGv_i64 val,
TCGv addr64 = tcg_temp_new();
tcg_gen_extu_i32_i64(addr64, addr);
tcg_gen_qemu_ld_i64(val, addr64, index, opc);
+
+ /* Not needed for user-mode BE32, where we use MO_BE instead. */
+ if (!IS_USER_ONLY && s->sctlr_b) {
+ tcg_gen_rotri_i64(val, val, 32);
+ }
tcg_temp_free(addr64);
}
@@ -990,23 +1037,32 @@ static inline void gen_aa32_st64(DisasContext *s,
TCGv_i64 val,
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, opc);
+
+ /* Not needed for user-mode BE32, where we use MO_BE instead. */
+ if (!IS_USER_ONLY && s->sctlr_b) {
+ TCGv tmp = tcg_temp_new();
+ tcg_gen_rotri_i64(tmp, val, 32);
+ tcg_gen_qemu_st_i64(tmp, addr64, index, opc);
+ tcg_temp_free(tmp);
+ } else {
+ tcg_gen_qemu_st_i64(val, addr64, index, opc);
+ }
tcg_temp_free(addr64);
}
#endif
-DO_GEN_LD(8s, MO_SB)
-DO_GEN_LD(8u, MO_UB)
-DO_GEN_LD(16s, MO_SW)
-DO_GEN_LD(16u, MO_UW)
-DO_GEN_LD(32u, MO_UL)
+DO_GEN_LD(8s, MO_SB, 3)
+DO_GEN_LD(8u, MO_UB, 3)
+DO_GEN_LD(16s, MO_SW, 2)
+DO_GEN_LD(16u, MO_UW, 2)
+DO_GEN_LD(32u, MO_UL, 0)
/* 'a' variants include an alignment check */
-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_UW)
-DO_GEN_ST(32, MO_UL)
+DO_GEN_LD(16ua, MO_UW | MO_ALIGN, 2)
+DO_GEN_LD(32ua, MO_UL | MO_ALIGN, 0)
+DO_GEN_ST(8, MO_UB, 3)
+DO_GEN_ST(16, MO_UW, 2)
+DO_GEN_ST(32, MO_UL, 0)
static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
{
--
1.9.1
- [Qemu-devel] [PULL 28/30] arm: boot: Support big-endian elfs, (continued)
- [Qemu-devel] [PULL 28/30] arm: boot: Support big-endian elfs, Peter Maydell, 2016/03/04
- [Qemu-devel] [PULL 05/30] hw/arm/virt: Provide a secure-only RAM if booting in Secure mode, Peter Maydell, 2016/03/04
- [Qemu-devel] [PULL 18/30] target-arm: implement SCTLR.EE, Peter Maydell, 2016/03/04
- [Qemu-devel] [PULL 23/30] target-arm: implement setend, Peter Maydell, 2016/03/04
- [Qemu-devel] [PULL 26/30] loader: load_elf(): Add doc comment, Peter Maydell, 2016/03/04
- [Qemu-devel] [PULL 09/30] hw/arm/virt: Assume EL3 boot rom will handle PSCI if one is provided, Peter Maydell, 2016/03/04
- [Qemu-devel] [PULL 11/30] linux-user: arm: fix coding style for some linux-user signal functions, Peter Maydell, 2016/03/04
- [Qemu-devel] [PULL 13/30] target-arm: implement SCTLR.B, drop bswap_code, Peter Maydell, 2016/03/04
- [Qemu-devel] [PULL 21/30] target-arm: a64: Add endianness support, Peter Maydell, 2016/03/04
- [Qemu-devel] [PULL 25/30] loader: add API to load elf header, Peter Maydell, 2016/03/04
- [Qemu-devel] [PULL 24/30] target-arm: implement BE32 mode in system emulation,
Peter Maydell <=
- [Qemu-devel] [PULL 30/30] target-arm: Only trap SRS from S-EL1 if specified mode is MON, Peter Maydell, 2016/03/04
- [Qemu-devel] [PULL 29/30] hw/intc/arm_gic.c: Implement GICv2 GICC_DIR, Peter Maydell, 2016/03/04
- [Qemu-devel] [PULL 27/30] loader: Add data swap option to load-elf, Peter Maydell, 2016/03/04
- [Qemu-devel] [PULL 20/30] target-arm: introduce disas flag for endianness, Peter Maydell, 2016/03/04
- Re: [Qemu-devel] [PULL 00/30] target-arm queue, Peter Maydell, 2016/03/04