ARM BE8 support.
authorStan Shebs <shebs@codesourcery.com>
Mon, 11 Aug 2008 19:00:25 +0000 (19:00 +0000)
committerStan Shebs <shebs@codesourcery.com>
Mon, 11 Aug 2008 19:00:25 +0000 (19:00 +0000)
* disasm.c (gdb_disassemble_info): Set endian_code.
* gdbarch.sh (gdbarch_info): New field byte_order_for_code.
* gdbarch.h, gdbarch.c: Regenerate.
* arch-utils.c (initialize_current_architecture): Set the
default byte_order_for_code.
(gdbarch_info_init): Ditto.
(gdbarch_info_fill): Ditto.
* arm-tdep.c (SWAP_INT, SWAP_SHORT): New macros.
(thumb_analyze_prologue): Swap halfword if code endianness is
different from general endianness.
(arm_skip_prologue): Similarly.
(arm_scan_prologue): Ditto.
(thumb_get_next_pc): Ditto.
(arm_get_next_pc): Ditto.
(arm_gdbarch_init): Set byte_order_for_code from BE8 flag,
choose correct endianness for breakpoints.

gdb/ChangeLog
gdb/arch-utils.c
gdb/arm-tdep.c
gdb/disasm.c
gdb/gdbarch.c
gdb/gdbarch.h
gdb/gdbarch.sh

index 73f6d2e137be6921ac4ca90ccf60698c85850570..fbe50881beaae2ede9cc8268bc132459259c2283 100644 (file)
@@ -1,3 +1,23 @@
+2008-08-11  Stan Shebs  <stan@codesourcery.com>
+
+       ARM BE8 support.
+       * disasm.c (gdb_disassemble_info): Set endian_code.
+       * gdbarch.sh (gdbarch_info): New field byte_order_for_code.
+       * gdbarch.h, gdbarch.c: Regenerate.
+       * arch-utils.c (initialize_current_architecture): Set the
+       default byte_order_for_code.
+       (gdbarch_info_init): Ditto.
+       (gdbarch_info_fill): Ditto.
+       * arm-tdep.c (SWAP_INT, SWAP_SHORT): New macros.
+       (thumb_analyze_prologue): Swap halfword if code endianness is
+       different from general endianness.
+       (arm_skip_prologue): Similarly.
+       (arm_scan_prologue): Ditto.
+       (thumb_get_next_pc): Ditto.
+       (arm_get_next_pc): Ditto.
+       (arm_gdbarch_init): Set byte_order_for_code from BE8 flag,
+       choose correct endianness for breakpoints.
+
 2008-08-10  Pedro Alves  <pedro@codesourcery.com>
 
        * bsd-kvm.c: Include "gdbthread.h".
index 259d1e3a5f4f345ef90ca07451b879f3c85fa2b6..a2fd7b65661352547cbb4e66b4de3b3161788c4b 100644 (file)
@@ -629,6 +629,7 @@ initialize_current_architecture (void)
     }
 
   info.byte_order = default_byte_order;
+  info.byte_order_for_code = info.byte_order;
 
   if (! gdbarch_update_p (info))
     internal_error (__FILE__, __LINE__,
@@ -667,6 +668,7 @@ gdbarch_info_init (struct gdbarch_info *info)
 {
   memset (info, 0, sizeof (struct gdbarch_info));
   info->byte_order = BFD_ENDIAN_UNKNOWN;
+  info->byte_order_for_code = info->byte_order;
   info->osabi = GDB_OSABI_UNINITIALIZED;
 }
 
@@ -708,6 +710,7 @@ gdbarch_info_fill (struct gdbarch_info *info)
   /* From the default.  */
   if (info->byte_order == BFD_ENDIAN_UNKNOWN)
     info->byte_order = default_byte_order;
+  info->byte_order_for_code = info->byte_order;
 
   /* "(gdb) set osabi ...".  Handled by gdbarch_lookup_osabi.  */
   if (info->osabi == GDB_OSABI_UNINITIALIZED)
index fd732a87e4510a0be2a26189f45a364c41aa656b..66add047d4b21fc2bb6a9b9bca22d5cf74fa22e4 100644 (file)
@@ -69,6 +69,19 @@ static int arm_debug;
 #define MSYMBOL_IS_SPECIAL(msym)                               \
        (((long) MSYMBOL_INFO (msym) & 0x80000000) != 0)
 
+/* Macros for swapping shorts and ints. In the unlikely case that anybody else needs these,
+   move to a general header. (A better solution might be to define memory read routines that
+   know whether they are reading code or data.)  */
+
+#define SWAP_SHORT(x) \
+  ((((x) & 0xff00) >> 8) | (((x) & 0x00ff) << 8));
+
+#define SWAP_INT(x) \
+  (  ((x & 0xff000000) >> 24) \
+   | ((x & 0x00ff0000) >> 8)  \
+   | ((x & 0x0000ff00) << 8)  \
+   | ((x & 0x000000ff) << 24))
+
 /* Per-objfile data used for mapping symbols.  */
 static const struct objfile_data *arm_objfile_data_key;
 
@@ -391,6 +404,9 @@ thumb_analyze_prologue (struct gdbarch *gdbarch,
 
       insn = read_memory_unsigned_integer (start, 2);
 
+      if (gdbarch_byte_order_for_code (gdbarch) != gdbarch_byte_order (gdbarch))
+       insn = SWAP_SHORT (insn);
+
       if ((insn & 0xfe00) == 0xb400)           /* push { rlist } */
        {
          int regno;
@@ -559,6 +575,9 @@ arm_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
     {
       inst = read_memory_unsigned_integer (skip_pc, 4);
 
+      if (gdbarch_byte_order_for_code (gdbarch) != gdbarch_byte_order (gdbarch))
+       inst = SWAP_INT (inst);
+
       /* "mov ip, sp" is no longer a required part of the prologue.  */
       if (inst == 0xe1a0c00d)                  /* mov ip, sp */
        continue;
@@ -855,6 +874,9 @@ arm_scan_prologue (struct frame_info *this_frame,
     {
       unsigned int insn = read_memory_unsigned_integer (current_pc, 4);
 
+      if (gdbarch_byte_order_for_code (gdbarch) != gdbarch_byte_order (gdbarch))
+       insn = SWAP_INT (insn);
+
       if (insn == 0xe1a0c00d)          /* mov ip, sp */
        {
          regs[ARM_IP_REGNUM] = regs[ARM_SP_REGNUM];
@@ -1812,6 +1834,9 @@ thumb_get_next_pc (struct frame_info *frame, CORE_ADDR pc)
   CORE_ADDR nextpc = pc + 2;           /* default is next instruction */
   unsigned long offset;
 
+  if (gdbarch_byte_order_for_code (gdbarch) != gdbarch_byte_order (gdbarch))
+    inst1 = SWAP_SHORT (inst1);
+
   if ((inst1 & 0xff00) == 0xbd00)      /* pop {rlist, pc} */
     {
       CORE_ADDR sp;
@@ -1839,6 +1864,8 @@ thumb_get_next_pc (struct frame_info *frame, CORE_ADDR pc)
   else if ((inst1 & 0xf800) == 0xf000) /* long branch with link, and blx */
     {
       unsigned short inst2 = read_memory_unsigned_integer (pc + 2, 2);
+      if (gdbarch_byte_order_for_code (gdbarch) != gdbarch_byte_order (gdbarch))
+       inst2 = SWAP_SHORT (inst2);
       offset = (sbits (inst1, 0, 10) << 12) + (bits (inst2, 0, 10) << 1);
       nextpc = pc_val + offset;
       /* For BLX make sure to clear the low bits.  */
@@ -1874,6 +1901,10 @@ arm_get_next_pc (struct frame_info *frame, CORE_ADDR pc)
 
   pc_val = (unsigned long) pc;
   this_instr = read_memory_unsigned_integer (pc, 4);
+
+  if (gdbarch_byte_order_for_code (gdbarch) != gdbarch_byte_order (gdbarch))
+    this_instr = SWAP_INT (this_instr);
+
   status = get_frame_register_unsigned (frame, ARM_PS_REGNUM);
   nextpc = (CORE_ADDR) (pc_val + 4);   /* Default case */
 
@@ -3150,6 +3181,10 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
                  break;
                }
            }
+
+         if (e_flags & EF_ARM_BE8)
+           info.byte_order_for_code = BFD_ENDIAN_LITTLE;
+
          break;
 
        default:
@@ -3192,7 +3227,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->have_fpa_registers = have_fpa_registers;
 
   /* Breakpoints.  */
-  switch (info.byte_order)
+  switch (info.byte_order_for_code)
     {
     case BFD_ENDIAN_BIG:
       tdep->arm_breakpoint = arm_default_arm_be_breakpoint;
index 64c0cbc5a7c721b57e3bf5f0ada5de5dfea4ac6b..f9ff9b1c4853e146416482f14d7a211315c3924b 100644 (file)
@@ -343,6 +343,7 @@ gdb_disassemble_info (struct gdbarch *gdbarch, struct ui_file *file)
   di.arch = gdbarch_bfd_arch_info (gdbarch)->arch;
   di.mach = gdbarch_bfd_arch_info (gdbarch)->mach;
   di.endian = gdbarch_byte_order (gdbarch);
+  di.endian_code = gdbarch_byte_order_for_code (gdbarch);
   disassemble_init_for_target (&di);
   return di;
 }
index 6b173c2b80c96dca543e8390433099e5341cb26c..504cb774f1c1fcea76075640c80345d8b8e44ac7 100644 (file)
@@ -90,6 +90,7 @@ struct gdbarch
   /* basic architectural information */
   const struct bfd_arch_info * bfd_arch_info;
   int byte_order;
+  int byte_order_for_code;
   enum gdb_osabi osabi;
   const struct target_desc * target_desc;
 
@@ -254,6 +255,7 @@ struct gdbarch startup_gdbarch =
   /* basic architecture information */
   &bfd_default_arch_struct,  /* bfd_arch_info */
   BFD_ENDIAN_BIG,  /* byte_order */
+  BFD_ENDIAN_BIG,  /* byte_order_for_code */
   GDB_OSABI_UNKNOWN,  /* osabi */
   0,  /* target_desc */
   /* target specific vector and its dump routine */
@@ -398,6 +400,7 @@ gdbarch_alloc (const struct gdbarch_info *info,
 
   gdbarch->bfd_arch_info = info->bfd_arch_info;
   gdbarch->byte_order = info->byte_order;
+  gdbarch->byte_order_for_code = info->byte_order_for_code;
   gdbarch->osabi = info->osabi;
   gdbarch->target_desc = info->target_desc;
 
@@ -692,6 +695,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
   fprintf_unfiltered (file,
                       "gdbarch_dump: byte_order = %s\n",
                       paddr_d (gdbarch->byte_order));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: byte_order_for_code = %s\n",
+                      paddr_d (gdbarch->byte_order_for_code));
   fprintf_unfiltered (file,
                       "gdbarch_dump: call_dummy_location = %s\n",
                       paddr_d (gdbarch->call_dummy_location));
@@ -1122,6 +1128,15 @@ gdbarch_byte_order (struct gdbarch *gdbarch)
   return gdbarch->byte_order;
 }
 
+int
+gdbarch_byte_order_for_code (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_byte_order_for_code called\n");
+  return gdbarch->byte_order_for_code;
+}
+
 enum gdb_osabi
 gdbarch_osabi (struct gdbarch *gdbarch)
 {
index 870b79b73d233afdb81fe94e2992a8d1b68f7b18..24d8c6bbc6844ca7743348a20f8776fe49c46bd8 100644 (file)
@@ -64,6 +64,9 @@ extern const struct bfd_arch_info * gdbarch_bfd_arch_info (struct gdbarch *gdbar
 extern int gdbarch_byte_order (struct gdbarch *gdbarch);
 /* set_gdbarch_byte_order() - not applicable - pre-initialized. */
 
+extern int gdbarch_byte_order_for_code (struct gdbarch *gdbarch);
+/* set_gdbarch_byte_order_for_code() - not applicable - pre-initialized. */
+
 extern enum gdb_osabi gdbarch_osabi (struct gdbarch *gdbarch);
 /* set_gdbarch_osabi() - not applicable - pre-initialized. */
 
@@ -885,6 +888,8 @@ struct gdbarch_info
   /* Use default: BFD_ENDIAN_UNKNOWN (NB: is not ZERO).  */
   int byte_order;
 
+  int byte_order_for_code;
+
   /* Use default: NULL (ZERO). */
   bfd *abfd;
 
index af7aea437b8818c6c96d2aeb15e7da1de50605b7..a9fcd80015a5b1c594a2fc8b1e323c8c256fafee 100755 (executable)
@@ -339,6 +339,7 @@ function_list ()
 i:const struct bfd_arch_info *:bfd_arch_info:::&bfd_default_arch_struct::::gdbarch_bfd_arch_info (gdbarch)->printable_name
 #
 i:int:byte_order:::BFD_ENDIAN_BIG
+i:int:byte_order_for_code:::BFD_ENDIAN_BIG
 #
 i:enum gdb_osabi:osabi:::GDB_OSABI_UNKNOWN
 #
@@ -962,6 +963,8 @@ struct gdbarch_info
   /* Use default: BFD_ENDIAN_UNKNOWN (NB: is not ZERO).  */
   int byte_order;
 
+  int byte_order_for_code;
+
   /* Use default: NULL (ZERO). */
   bfd *abfd;