From c7be441465094e5ffce2f4205ea887676965d0be Mon Sep 17 00:00:00 2001 From: Jim Wilson Date: Thu, 30 Jun 2016 09:10:41 +0100 Subject: [PATCH] Add support for simulating big-endian AArch64 binaries. * cpustate.h: Include config.h. (union GRegisterValue): Add WORDS_BIGENDIAN check. For big endian code use anonymous structs to align members. * simulator.c (aarch64_step): Use sim_core_read_buffer and endian_le2h_4 to read instruction from pc. --- sim/aarch64/ChangeLog | 8 ++++++++ sim/aarch64/cpustate.h | 25 +++++++++++++++++-------- sim/aarch64/simulator.c | 6 +++++- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/sim/aarch64/ChangeLog b/sim/aarch64/ChangeLog index 90e501a00a..2d9a9d20ea 100644 --- a/sim/aarch64/ChangeLog +++ b/sim/aarch64/ChangeLog @@ -1,3 +1,11 @@ +2016-06-30 Jim Wilson + + * cpustate.h: Include config.h. + (union GRegisterValue): Add WORDS_BIGENDIAN check. For big endian code + use anonymous structs to align members. + * simulator.c (aarch64_step): Use sim_core_read_buffer and + endian_le2h_4 to read instruction from pc. + 2016-05-06 Nick Clifton * simulator.c (do_FMLA_by_element): New function. diff --git a/sim/aarch64/cpustate.h b/sim/aarch64/cpustate.h index 07446a23b2..fc0c68bd68 100644 --- a/sim/aarch64/cpustate.h +++ b/sim/aarch64/cpustate.h @@ -22,6 +22,7 @@ #ifndef _CPU_STATE_H #define _CPU_STATE_H +#include "config.h" #include #include #include @@ -123,16 +124,14 @@ typedef enum VReg } VReg; /* All the different integer bit patterns for the components of a - general register are overlaid here using a union so as to allow all - reading and writing of the desired bits. - - N.B. the ARM spec says that when you write a 32 bit register you - are supposed to write the low 32 bits and zero the high 32 - bits. But we don't actually have to care about this because Java - will only ever consume the 32 bits value as a 64 bit quantity after - an explicit extend. */ + general register are overlaid here using a union so as to allow + all reading and writing of the desired bits. Note that we have + to take care when emulating a big-endian AArch64 as we are + running on a little endian host. */ + typedef union GRegisterValue { +#if !WORDS_BIGENDIAN int8_t s8; int16_t s16; int32_t s32; @@ -141,6 +140,16 @@ typedef union GRegisterValue uint16_t u16; uint32_t u32; uint64_t u64; +#else + struct { int64_t :56; int8_t s8; }; + struct { int64_t :48; int16_t s16; }; + struct { int64_t :32; int32_t s32; }; + int64_t s64; + struct { uint64_t :56; uint8_t u8; }; + struct { uint64_t :48; uint16_t u16; }; + struct { uint64_t :32; uint32_t u32; }; + uint64_t u64; +#endif } GRegister; /* Float registers provide for storage of a single, double or quad diff --git a/sim/aarch64/simulator.c b/sim/aarch64/simulator.c index 88cb03d79a..7c15e7a50b 100644 --- a/sim/aarch64/simulator.c +++ b/sim/aarch64/simulator.c @@ -14083,7 +14083,11 @@ aarch64_step (sim_cpu *cpu) return FALSE; aarch64_set_next_PC (cpu, pc + 4); - aarch64_get_instr (cpu) = aarch64_get_mem_u32 (cpu, pc); + + /* Code is always little-endian. */ + sim_core_read_buffer (CPU_STATE (cpu), cpu, read_map, + & aarch64_get_instr (cpu), pc, 4); + aarch64_get_instr (cpu) = endian_le2h_4 (aarch64_get_instr (cpu)); TRACE_INSN (cpu, " pc = %" PRIx64 " instr = %08x", pc, aarch64_get_instr (cpu)); -- 2.34.1