Add support for simulating big-endian AArch64 binaries.
authorJim Wilson <jim.wilson@linaro.org>
Thu, 30 Jun 2016 08:10:41 +0000 (09:10 +0100)
committerNick Clifton <nickc@redhat.com>
Thu, 30 Jun 2016 08:10:41 +0000 (09:10 +0100)
* 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
sim/aarch64/cpustate.h
sim/aarch64/simulator.c

index 90e501a00a43f2b9b5cbe6f3c2542cea166bf40d..2d9a9d20eac2295e8b8f7d54a9af043b65e11d09 100644 (file)
@@ -1,3 +1,11 @@
+2016-06-30  Jim Wilson  <jim.wilson@linaro.org>
+
+       * 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  <nickc@redhat.com>
 
        * simulator.c (do_FMLA_by_element): New function.
index 07446a23b2deb7775b751c081f502f012e3b0914..fc0c68bd68386bf579df9dc4e257ab92ddb33b57 100644 (file)
@@ -22,6 +22,7 @@
 #ifndef _CPU_STATE_H
 #define _CPU_STATE_H
 
+#include "config.h"
 #include <sys/types.h>
 #include <stdint.h>
 #include <inttypes.h>
@@ -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
index 88cb03d79a5848b528aa0221721d75691f84a557..7c15e7a50b335484d9453bf9dfb749ec6b1a0669 100644 (file)
@@ -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));