Move instruction decoding into new arch/ directory
authorPierre Langlois <pierre.langlois@arm.com>
Mon, 21 Sep 2015 14:01:04 +0000 (15:01 +0100)
committerYao Qi <yao.qi@linaro.org>
Mon, 21 Sep 2015 14:01:04 +0000 (15:01 +0100)
This patch moves the following functions into the arch/ common
directory, in new files arch/aarch64-insn.{h,c}.  They are prefixed with
'aarch64_':

 - aarch64_decode_adrp
 - aarch64_decode_b
 - aarch64_decode_cb
 - aarch64_decode_tb

We will need them to implement fast tracepoints in GDBserver.

For consistency, this patch also adds the 'aarch64_' prefix to static
decoding functions that do not need to be shared right now.

V2:
 make sure the formatting issues propagated
 fix `gdbserver/configure.srv'.

gdb/ChangeLog:

* Makefile.in (ALL_64_TARGET_OBS): Add aarch64-insn.o.
(HFILES_NO_SRCDIR): Add arch/aarch64-insn.h.
(aarch64-insn.o): New rule.
* configure.tgt (aarch64*-*-elf): Add aarch64-insn.o.
(aarch64*-*-linux*): Likewise.
* arch/aarch64-insn.c: New file.
* arch/aarch64-insn.h: New file.
* aarch64-tdep.c: Include arch/aarch64-insn.h.
(aarch64_debug): Move to arch/aarch64-insn.c.  Declare in
arch/aarch64-insn.h.
(decode_add_sub_imm): Rename to ...
(aarch64_decode_add_sub_imm): ... this.
(decode_adrp): Rename to ...
(aarch64_decode_adrp): ... this.  Move to arch/aarch64-insn.c.
Declare in arch/aarch64-insn.h.
(decode_b): Rename to ...
(aarch64_decode_b): ... this.  Move to arch/aarch64-insn.c.
Declare in arch/aarch64-insn.h.
(decode_bcond): Rename to ...
(aarch64_decode_bcond): ... this.  Move to arch/aarch64-insn.c.
Declare in arch/aarch64-insn.h.
(decode_br): Rename to ...
(aarch64_decode_br): ... this.
(decode_cb): Rename to ...
(aarch64_decode_cb): ... this.  Move to arch/aarch64-insn.c.
Declare in arch/aarch64-insn.h.
(decode_eret): Rename to ...
(aarch64_decode_eret): ... this.
(decode_movz): Rename to ...
(aarch64_decode_movz): ... this.
(decode_orr_shifted_register_x): Rename to ...
(aarch64_decode_orr_shifted_register_x): ... this.
(decode_ret): Rename to ...
(aarch64_decode_ret): ... this.
(decode_stp_offset): Rename to ...
(aarch64_decode_stp_offset): ... this.
(decode_stp_offset_wb): Rename to ...
(aarch64_decode_stp_offset_wb): ... this.
(decode_stur): Rename to ...
(aarch64_decode_stur): ... this.
(decode_tb): Rename to ...
(aarch64_decode_tb): ... this.  Move to arch/aarch64-insn.c.
Declare in arch/aarch64-insn.h.
(aarch64_analyze_prologue): Adjust calls to renamed functions.

gdb/gdbserver/ChangeLog:

* Makefile.in (aarch64-insn.o): New rule.
* configure.srv (aarch64*-*-linux*): Add aarch64-insn.o.

gdb/ChangeLog
gdb/Makefile.in
gdb/aarch64-tdep.c
gdb/arch/aarch64-insn.c [new file with mode: 0644]
gdb/arch/aarch64-insn.h [new file with mode: 0644]
gdb/configure.tgt
gdb/gdbserver/ChangeLog
gdb/gdbserver/Makefile.in
gdb/gdbserver/configure.srv

index fe56b75..7d8feeb 100644 (file)
@@ -1,3 +1,50 @@
+2015-09-21  Pierre Langlois  <pierre.langlois@arm.com>
+
+       * Makefile.in (ALL_64_TARGET_OBS): Add aarch64-insn.o.
+       (HFILES_NO_SRCDIR): Add arch/aarch64-insn.h.
+       (aarch64-insn.o): New rule.
+       * configure.tgt (aarch64*-*-elf): Add aarch64-insn.o.
+       (aarch64*-*-linux*): Likewise.
+       * arch/aarch64-insn.c: New file.
+       * arch/aarch64-insn.h: New file.
+       * aarch64-tdep.c: Include arch/aarch64-insn.h.
+       (aarch64_debug): Move to arch/aarch64-insn.c.  Declare in
+       arch/aarch64-insn.h.
+       (decode_add_sub_imm): Rename to ...
+       (aarch64_decode_add_sub_imm): ... this.
+       (decode_adrp): Rename to ...
+       (aarch64_decode_adrp): ... this.  Move to arch/aarch64-insn.c.
+       Declare in arch/aarch64-insn.h.
+       (decode_b): Rename to ...
+       (aarch64_decode_b): ... this.  Move to arch/aarch64-insn.c.
+       Declare in arch/aarch64-insn.h.
+       (decode_bcond): Rename to ...
+       (aarch64_decode_bcond): ... this.  Move to arch/aarch64-insn.c.
+       Declare in arch/aarch64-insn.h.
+       (decode_br): Rename to ...
+       (aarch64_decode_br): ... this.
+       (decode_cb): Rename to ...
+       (aarch64_decode_cb): ... this.  Move to arch/aarch64-insn.c.
+       Declare in arch/aarch64-insn.h.
+       (decode_eret): Rename to ...
+       (aarch64_decode_eret): ... this.
+       (decode_movz): Rename to ...
+       (aarch64_decode_movz): ... this.
+       (decode_orr_shifted_register_x): Rename to ...
+       (aarch64_decode_orr_shifted_register_x): ... this.
+       (decode_ret): Rename to ...
+       (aarch64_decode_ret): ... this.
+       (decode_stp_offset): Rename to ...
+       (aarch64_decode_stp_offset): ... this.
+       (decode_stp_offset_wb): Rename to ...
+       (aarch64_decode_stp_offset_wb): ... this.
+       (decode_stur): Rename to ...
+       (aarch64_decode_stur): ... this.
+       (decode_tb): Rename to ...
+       (aarch64_decode_tb): ... this.  Move to arch/aarch64-insn.c.
+       Declare in arch/aarch64-insn.h.
+       (aarch64_analyze_prologue): Adjust calls to renamed functions.
+
 2015-09-20  Doug Evans  <xdje42@gmail.com>
 
        * dwarf2read.c (add_partial_symbol): Remove outdated comments.
index 5659116..d5ca2ee 100644 (file)
@@ -644,7 +644,7 @@ TARGET_OBS = @TARGET_OBS@
 # All target-dependent objects files that require 64-bit CORE_ADDR
 # (used with --enable-targets=all --enable-64-bit-bfd).
 ALL_64_TARGET_OBS = \
-       aarch64-tdep.o aarch64-linux-tdep.o aarch64-newlib-tdep.o \
+       aarch64-tdep.o aarch64-linux-tdep.o aarch64-newlib-tdep.o aarch64-insn.o \
        alphabsd-tdep.o alphafbsd-tdep.o alpha-linux-tdep.o alpha-mdebug-tdep.o \
        alphanbsd-tdep.o alphaobsd-tdep.o alpha-tdep.o \
        amd64fbsd-tdep.o amd64-darwin-tdep.o amd64-dicos-tdep.o \
@@ -986,7 +986,7 @@ common/common-debug.h common/cleanups.h common/gdb_setjmp.h \
 common/common-exceptions.h target/target.h common/symbol.h \
 common/common-regcache.h fbsd-tdep.h nat/linux-personality.h \
 common/fileio.h nat/x86-linux.h nat/x86-linux-dregs.h \
-nat/linux-namespaces.h arch/arm.h common/gdb_sys_time.h
+nat/linux-namespaces.h arch/arm.h common/gdb_sys_time.h arch/aarch64-insn.h
 
 # Header files that already have srcdir in them, or which are in objdir.
 
@@ -2336,6 +2336,15 @@ aarch64-linux.o: ${srcdir}/nat/aarch64-linux.c
        $(COMPILE) $(srcdir)/nat/aarch64-linux.c
        $(POSTCOMPILE)
 
+# gdb/arch/ dependencies
+#
+# Need to explicitly specify the compile rule as make will do nothing
+# or try to compile the object file into the sub-directory.
+
+aarch64-insn.o: ${srcdir}/arch/aarch64-insn.c
+       $(COMPILE) $(srcdir)/arch/aarch64-insn.c
+       $(POSTCOMPILE)
+
 #
 # gdb/tui/ dependencies
 #
index 9a4eda2..92e2404 100644 (file)
@@ -57,6 +57,8 @@
 
 #include "features/aarch64.c"
 
+#include "arch/aarch64-insn.h"
+
 /* Pseudo register base numbers.  */
 #define AARCH64_Q0_REGNUM 0
 #define AARCH64_D0_REGNUM (AARCH64_Q0_REGNUM + 32)
@@ -179,9 +181,6 @@ struct aarch64_prologue_cache
   struct trad_frame_saved_reg *saved_regs;
 };
 
-/* Toggle this file's internal debugging dump.  */
-static int aarch64_debug;
-
 static void
 show_aarch64_debug (struct ui_file *file, int from_tty,
                     struct cmd_list_element *c, const char *value)
@@ -231,8 +230,8 @@ decode_masked_match (uint32_t insn, uint32_t mask, uint32_t pattern)
 
    Return 1 if the opcodes matches and is decoded, otherwise 0.  */
 static int
-decode_add_sub_imm (CORE_ADDR addr, uint32_t insn, unsigned *rd, unsigned *rn,
-                   int32_t *imm)
+aarch64_decode_add_sub_imm (CORE_ADDR addr, uint32_t insn, unsigned *rd,
+                           unsigned *rn, int32_t *imm)
 {
   if ((insn & 0x9f000000) == 0x91000000)
     {
@@ -271,94 +270,6 @@ decode_add_sub_imm (CORE_ADDR addr, uint32_t insn, unsigned *rd, unsigned *rn,
   return 0;
 }
 
-/* Decode an opcode if it represents an ADRP instruction.
-
-   ADDR specifies the address of the opcode.
-   INSN specifies the opcode to test.
-   RD receives the 'rd' field from the decoded instruction.
-
-   Return 1 if the opcodes matches and is decoded, otherwise 0.  */
-
-static int
-decode_adrp (CORE_ADDR addr, uint32_t insn, unsigned *rd)
-{
-  if (decode_masked_match (insn, 0x9f000000, 0x90000000))
-    {
-      *rd = (insn >> 0) & 0x1f;
-
-      if (aarch64_debug)
-       {
-         debug_printf ("decode: 0x%s 0x%x adrp x%u, #?\n",
-                       core_addr_to_string_nz (addr), insn, *rd);
-       }
-      return 1;
-    }
-  return 0;
-}
-
-/* Decode an opcode if it represents an branch immediate or branch
-   and link immediate instruction.
-
-   ADDR specifies the address of the opcode.
-   INSN specifies the opcode to test.
-   IS_BL receives the 'op' bit from the decoded instruction.
-   OFFSET receives the immediate offset from the decoded instruction.
-
-   Return 1 if the opcodes matches and is decoded, otherwise 0.  */
-
-static int
-decode_b (CORE_ADDR addr, uint32_t insn, int *is_bl, int32_t *offset)
-{
-  /* b  0001 01ii iiii iiii iiii iiii iiii iiii */
-  /* bl 1001 01ii iiii iiii iiii iiii iiii iiii */
-  if (decode_masked_match (insn, 0x7c000000, 0x14000000))
-    {
-      *is_bl = (insn >> 31) & 0x1;
-      *offset = extract_signed_bitfield (insn, 26, 0) << 2;
-
-      if (aarch64_debug)
-       {
-         debug_printf ("decode: 0x%s 0x%x %s 0x%s\n",
-                       core_addr_to_string_nz (addr), insn,
-                       *is_bl ? "bl" : "b",
-                       core_addr_to_string_nz (addr + *offset));
-       }
-
-      return 1;
-    }
-  return 0;
-}
-
-/* Decode an opcode if it represents a conditional branch instruction.
-
-   ADDR specifies the address of the opcode.
-   INSN specifies the opcode to test.
-   COND receives the branch condition field from the decoded
-   instruction.
-   OFFSET receives the immediate offset from the decoded instruction.
-
-   Return 1 if the opcodes matches and is decoded, otherwise 0.  */
-
-static int
-decode_bcond (CORE_ADDR addr, uint32_t insn, unsigned *cond, int32_t *offset)
-{
-  /* b.cond  0101 0100 iiii iiii iiii iiii iii0 cccc */
-  if (decode_masked_match (insn, 0xff000010, 0x54000000))
-    {
-      *cond = (insn >> 0) & 0xf;
-      *offset = extract_signed_bitfield (insn, 19, 5) << 2;
-
-      if (aarch64_debug)
-       {
-         debug_printf ("decode: 0x%s 0x%x b<%u> 0x%s\n",
-                       core_addr_to_string_nz (addr), insn, *cond,
-                       core_addr_to_string_nz (addr + *offset));
-       }
-      return 1;
-    }
-  return 0;
-}
-
 /* Decode an opcode if it represents a branch via register instruction.
 
    ADDR specifies the address of the opcode.
@@ -369,7 +280,8 @@ decode_bcond (CORE_ADDR addr, uint32_t insn, unsigned *cond, int32_t *offset)
    Return 1 if the opcodes matches and is decoded, otherwise 0.  */
 
 static int
-decode_br (CORE_ADDR addr, uint32_t insn, int *is_blr, unsigned *rn)
+aarch64_decode_br (CORE_ADDR addr, uint32_t insn, int *is_blr,
+                  unsigned *rn)
 {
   /*         8   4   0   6   2   8   4   0 */
   /* blr  110101100011111100000000000rrrrr */
@@ -391,42 +303,6 @@ decode_br (CORE_ADDR addr, uint32_t insn, int *is_blr, unsigned *rn)
   return 0;
 }
 
-/* Decode an opcode if it represents a CBZ or CBNZ instruction.
-
-   ADDR specifies the address of the opcode.
-   INSN specifies the opcode to test.
-   IS64 receives the 'sf' field from the decoded instruction.
-   IS_CBNZ receives the 'op' field from the decoded instruction.
-   RN receives the 'rn' field from the decoded instruction.
-   OFFSET receives the 'imm19' field from the decoded instruction.
-
-   Return 1 if the opcodes matches and is decoded, otherwise 0.  */
-
-static int
-decode_cb (CORE_ADDR addr, uint32_t insn, int *is64, int *is_cbnz,
-          unsigned *rn, int32_t *offset)
-{
-  /* cbz  T011 010o iiii iiii iiii iiii iiir rrrr */
-  /* cbnz T011 010o iiii iiii iiii iiii iiir rrrr */
-  if (decode_masked_match (insn, 0x7e000000, 0x34000000))
-    {
-      *rn = (insn >> 0) & 0x1f;
-      *is64 = (insn >> 31) & 0x1;
-      *is_cbnz = (insn >> 24) & 0x1;
-      *offset = extract_signed_bitfield (insn, 19, 5) << 2;
-
-      if (aarch64_debug)
-       {
-         debug_printf ("decode: 0x%s 0x%x %s 0x%s\n",
-                       core_addr_to_string_nz (addr), insn,
-                       *is_cbnz ? "cbnz" : "cbz",
-                       core_addr_to_string_nz (addr + *offset));
-       }
-      return 1;
-    }
-  return 0;
-}
-
 /* Decode an opcode if it represents a ERET instruction.
 
    ADDR specifies the address of the opcode.
@@ -435,7 +311,7 @@ decode_cb (CORE_ADDR addr, uint32_t insn, int *is64, int *is_cbnz,
    Return 1 if the opcodes matches and is decoded, otherwise 0.  */
 
 static int
-decode_eret (CORE_ADDR addr, uint32_t insn)
+aarch64_decode_eret (CORE_ADDR addr, uint32_t insn)
 {
   /* eret 1101 0110 1001 1111 0000 0011 1110 0000 */
   if (insn == 0xd69f03e0)
@@ -459,7 +335,7 @@ decode_eret (CORE_ADDR addr, uint32_t insn)
    Return 1 if the opcodes matches and is decoded, otherwise 0.  */
 
 static int
-decode_movz (CORE_ADDR addr, uint32_t insn, unsigned *rd)
+aarch64_decode_movz (CORE_ADDR addr, uint32_t insn, unsigned *rd)
 {
   if (decode_masked_match (insn, 0xff800000, 0x52800000))
     {
@@ -488,9 +364,9 @@ decode_movz (CORE_ADDR addr, uint32_t insn, unsigned *rd)
    Return 1 if the opcodes matches and is decoded, otherwise 0.  */
 
 static int
-decode_orr_shifted_register_x (CORE_ADDR addr,
-                              uint32_t insn, unsigned *rd, unsigned *rn,
-                              unsigned *rm, int32_t *imm)
+aarch64_decode_orr_shifted_register_x (CORE_ADDR addr, uint32_t insn,
+                                      unsigned *rd, unsigned *rn,
+                                      unsigned *rm, int32_t *imm)
 {
   if (decode_masked_match (insn, 0xff200000, 0xaa000000))
     {
@@ -519,7 +395,7 @@ decode_orr_shifted_register_x (CORE_ADDR addr,
    Return 1 if the opcodes matches and is decoded, otherwise 0.  */
 
 static int
-decode_ret (CORE_ADDR addr, uint32_t insn, unsigned *rn)
+aarch64_decode_ret (CORE_ADDR addr, uint32_t insn, unsigned *rn)
 {
   if (decode_masked_match (insn, 0xfffffc1f, 0xd65f0000))
     {
@@ -547,9 +423,8 @@ decode_ret (CORE_ADDR addr, uint32_t insn, unsigned *rn)
    Return 1 if the opcodes matches and is decoded, otherwise 0.  */
 
 static int
-decode_stp_offset (CORE_ADDR addr,
-                  uint32_t insn,
-                  unsigned *rt1, unsigned *rt2, unsigned *rn, int32_t *imm)
+aarch64_decode_stp_offset (CORE_ADDR addr, uint32_t insn, unsigned *rt1,
+                          unsigned *rt2, unsigned *rn, int32_t *imm)
 {
   if (decode_masked_match (insn, 0xffc00000, 0xa9000000))
     {
@@ -583,10 +458,8 @@ decode_stp_offset (CORE_ADDR addr,
    Return 1 if the opcodes matches and is decoded, otherwise 0.  */
 
 static int
-decode_stp_offset_wb (CORE_ADDR addr,
-                     uint32_t insn,
-                     unsigned *rt1, unsigned *rt2, unsigned *rn,
-                     int32_t *imm)
+aarch64_decode_stp_offset_wb (CORE_ADDR addr, uint32_t insn, unsigned *rt1,
+                             unsigned *rt2, unsigned *rn, int32_t *imm)
 {
   if (decode_masked_match (insn, 0xffc00000, 0xa9800000))
     {
@@ -620,8 +493,8 @@ decode_stp_offset_wb (CORE_ADDR addr,
    Return 1 if the opcodes matches and is decoded, otherwise 0.  */
 
 static int
-decode_stur (CORE_ADDR addr, uint32_t insn, int *is64, unsigned *rt,
-            unsigned *rn, int32_t *imm)
+aarch64_decode_stur (CORE_ADDR addr, uint32_t insn, int *is64,
+                    unsigned *rt, unsigned *rn, int32_t *imm)
 {
   if (decode_masked_match (insn, 0xbfe00c00, 0xb8000000))
     {
@@ -641,42 +514,6 @@ decode_stur (CORE_ADDR addr, uint32_t insn, int *is64, unsigned *rt,
   return 0;
 }
 
-/* Decode an opcode if it represents a TBZ or TBNZ instruction.
-
-   ADDR specifies the address of the opcode.
-   INSN specifies the opcode to test.
-   IS_TBNZ receives the 'op' field from the decoded instruction.
-   BIT receives the bit position field from the decoded instruction.
-   RT receives 'rt' field from the decoded instruction.
-   IMM receives 'imm' field from the decoded instruction.
-
-   Return 1 if the opcodes matches and is decoded, otherwise 0.  */
-
-static int
-decode_tb (CORE_ADDR addr, uint32_t insn, int *is_tbnz, unsigned *bit,
-          unsigned *rt, int32_t *imm)
-{
-  /* tbz  b011 0110 bbbb biii iiii iiii iiir rrrr */
-  /* tbnz B011 0111 bbbb biii iiii iiii iiir rrrr */
-  if (decode_masked_match (insn, 0x7e000000, 0x36000000))
-    {
-      *rt = (insn >> 0) & 0x1f;
-      *is_tbnz = (insn >> 24) & 0x1;
-      *bit = ((insn >> (31 - 4)) & 0x20) | ((insn >> 19) & 0x1f);
-      *imm = extract_signed_bitfield (insn, 14, 5) << 2;
-
-      if (aarch64_debug)
-       {
-         debug_printf ("decode: 0x%s 0x%x %s x%u, #%u, 0x%s\n",
-                       core_addr_to_string_nz (addr), insn,
-                       *is_tbnz ? "tbnz" : "tbz", *rt, *bit,
-                       core_addr_to_string_nz (addr + *imm));
-       }
-      return 1;
-    }
-  return 0;
-}
-
 /* Analyze a prologue, looking for a recognizable stack frame
    and frame pointer.  Scan until we encounter a store that could
    clobber the stack frame unexpectedly, or an unknown instruction.  */
@@ -718,39 +555,40 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
 
       insn = read_memory_unsigned_integer (start, 4, byte_order_for_code);
 
-      if (decode_add_sub_imm (start, insn, &rd, &rn, &imm))
+      if (aarch64_decode_add_sub_imm (start, insn, &rd, &rn, &imm))
        regs[rd] = pv_add_constant (regs[rn], imm);
-      else if (decode_adrp (start, insn, &rd))
+      else if (aarch64_decode_adrp (start, insn, &rd))
        regs[rd] = pv_unknown ();
-      else if (decode_b (start, insn, &is_link, &offset))
+      else if (aarch64_decode_b (start, insn, &is_link, &offset))
        {
          /* Stop analysis on branch.  */
          break;
        }
-      else if (decode_bcond (start, insn, &cond, &offset))
+      else if (aarch64_decode_bcond (start, insn, &cond, &offset))
        {
          /* Stop analysis on branch.  */
          break;
        }
-      else if (decode_br (start, insn, &is_link, &rn))
+      else if (aarch64_decode_br (start, insn, &is_link, &rn))
        {
          /* Stop analysis on branch.  */
          break;
        }
-      else if (decode_cb (start, insn, &is64, &is_cbnz, &rn, &offset))
+      else if (aarch64_decode_cb (start, insn, &is64, &is_cbnz, &rn,
+                                 &offset))
        {
          /* Stop analysis on branch.  */
          break;
        }
-      else if (decode_eret (start, insn))
+      else if (aarch64_decode_eret (start, insn))
        {
          /* Stop analysis on branch.  */
          break;
        }
-      else if (decode_movz (start, insn, &rd))
+      else if (aarch64_decode_movz (start, insn, &rd))
        regs[rd] = pv_unknown ();
-      else
-       if (decode_orr_shifted_register_x (start, insn, &rd, &rn, &rm, &imm))
+      else if (aarch64_decode_orr_shifted_register_x (start, insn, &rd,
+                                                     &rn, &rm, &imm))
        {
          if (imm == 0 && rn == 31)
            regs[rd] = regs[rm];
@@ -765,17 +603,18 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
              break;
            }
        }
-      else if (decode_ret (start, insn, &rn))
+      else if (aarch64_decode_ret (start, insn, &rn))
        {
          /* Stop analysis on branch.  */
          break;
        }
-      else if (decode_stur (start, insn, &is64, &rt, &rn, &offset))
+      else if (aarch64_decode_stur (start, insn, &is64, &rt, &rn, &offset))
        {
          pv_area_store (stack, pv_add_constant (regs[rn], offset),
                         is64 ? 8 : 4, regs[rt]);
        }
-      else if (decode_stp_offset (start, insn, &rt1, &rt2, &rn, &imm))
+      else if (aarch64_decode_stp_offset (start, insn, &rt1, &rt2, &rn,
+                                         &imm))
        {
          /* If recording this store would invalidate the store area
             (perhaps because rn is not known) then we should abandon
@@ -793,7 +632,8 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
          pv_area_store (stack, pv_add_constant (regs[rn], imm + 8), 8,
                         regs[rt2]);
        }
-      else if (decode_stp_offset_wb (start, insn, &rt1, &rt2, &rn, &imm))
+      else if (aarch64_decode_stp_offset_wb (start, insn, &rt1, &rt2, &rn,
+                                            &imm))
        {
          /* If recording this store would invalidate the store area
             (perhaps because rn is not known) then we should abandon
@@ -812,7 +652,8 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
                         regs[rt2]);
          regs[rn] = pv_add_constant (regs[rn], imm);
        }
-      else if (decode_tb (start, insn, &is_tbnz, &bit, &rn, &offset))
+      else if (aarch64_decode_tb (start, insn, &is_tbnz, &bit, &rn,
+                                 &offset))
        {
          /* Stop analysis on branch.  */
          break;
@@ -2663,7 +2504,7 @@ aarch64_software_single_step (struct frame_info *frame)
                                           byte_order_for_code);
 
       /* Check if the instruction is a conditional branch.  */
-      if (decode_bcond (loc, insn, &cond, &offset))
+      if (aarch64_decode_bcond (loc, insn, &cond, &offset))
        {
          if (bc_insn_count >= 1)
            return 0;
diff --git a/gdb/arch/aarch64-insn.c b/gdb/arch/aarch64-insn.c
new file mode 100644 (file)
index 0000000..3a289a2
--- /dev/null
@@ -0,0 +1,218 @@
+/* Copyright (C) 2009-2015 Free Software Foundation, Inc.
+   Contributed by ARM Ltd.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "common-defs.h"
+#include "aarch64-insn.h"
+
+/* Toggle this file's internal debugging dump.  */
+int aarch64_debug = 0;
+
+/* Extract a signed value from a bit field within an instruction
+   encoding.
+
+   INSN is the instruction opcode.
+
+   WIDTH specifies the width of the bit field to extract (in bits).
+
+   OFFSET specifies the least significant bit of the field where bits
+   are numbered zero counting from least to most significant.  */
+
+static int32_t
+extract_signed_bitfield (uint32_t insn, unsigned width, unsigned offset)
+{
+  unsigned shift_l = sizeof (int32_t) * 8 - (offset + width);
+  unsigned shift_r = sizeof (int32_t) * 8 - width;
+
+  return ((int32_t) insn << shift_l) >> shift_r;
+}
+
+/* Determine if specified bits within an instruction opcode matches a
+   specific pattern.
+
+   INSN is the instruction opcode.
+
+   MASK specifies the bits within the opcode that are to be tested
+   agsinst for a match with PATTERN.  */
+
+static int
+decode_masked_match (uint32_t insn, uint32_t mask, uint32_t pattern)
+{
+  return (insn & mask) == pattern;
+}
+
+/* Decode an opcode if it represents an ADRP instruction.
+
+   ADDR specifies the address of the opcode.
+   INSN specifies the opcode to test.
+   RD receives the 'rd' field from the decoded instruction.
+
+   Return 1 if the opcodes matches and is decoded, otherwise 0.  */
+
+int
+aarch64_decode_adrp (CORE_ADDR addr, uint32_t insn, unsigned *rd)
+{
+  if (decode_masked_match (insn, 0x9f000000, 0x90000000))
+    {
+      *rd = (insn >> 0) & 0x1f;
+
+      if (aarch64_debug)
+       {
+         debug_printf ("decode: 0x%s 0x%x adrp x%u, #?\n",
+                       core_addr_to_string_nz (addr), insn, *rd);
+       }
+      return 1;
+    }
+  return 0;
+}
+
+/* Decode an opcode if it represents an branch immediate or branch
+   and link immediate instruction.
+
+   ADDR specifies the address of the opcode.
+   INSN specifies the opcode to test.
+   IS_BL receives the 'op' bit from the decoded instruction.
+   OFFSET receives the immediate offset from the decoded instruction.
+
+   Return 1 if the opcodes matches and is decoded, otherwise 0.  */
+
+int
+aarch64_decode_b (CORE_ADDR addr, uint32_t insn, int *is_bl,
+                 int32_t *offset)
+{
+  /* b  0001 01ii iiii iiii iiii iiii iiii iiii */
+  /* bl 1001 01ii iiii iiii iiii iiii iiii iiii */
+  if (decode_masked_match (insn, 0x7c000000, 0x14000000))
+    {
+      *is_bl = (insn >> 31) & 0x1;
+      *offset = extract_signed_bitfield (insn, 26, 0) << 2;
+
+      if (aarch64_debug)
+       {
+         debug_printf ("decode: 0x%s 0x%x %s 0x%s\n",
+                       core_addr_to_string_nz (addr), insn,
+                       *is_bl ? "bl" : "b",
+                       core_addr_to_string_nz (addr + *offset));
+       }
+
+      return 1;
+    }
+  return 0;
+}
+
+/* Decode an opcode if it represents a conditional branch instruction.
+
+   ADDR specifies the address of the opcode.
+   INSN specifies the opcode to test.
+   COND receives the branch condition field from the decoded
+   instruction.
+   OFFSET receives the immediate offset from the decoded instruction.
+
+   Return 1 if the opcodes matches and is decoded, otherwise 0.  */
+
+int
+aarch64_decode_bcond (CORE_ADDR addr, uint32_t insn, unsigned *cond,
+                     int32_t *offset)
+{
+  /* b.cond  0101 0100 iiii iiii iiii iiii iii0 cccc */
+  if (decode_masked_match (insn, 0xff000010, 0x54000000))
+    {
+      *cond = (insn >> 0) & 0xf;
+      *offset = extract_signed_bitfield (insn, 19, 5) << 2;
+
+      if (aarch64_debug)
+       {
+         debug_printf ("decode: 0x%s 0x%x b<%u> 0x%s\n",
+                       core_addr_to_string_nz (addr), insn, *cond,
+                       core_addr_to_string_nz (addr + *offset));
+       }
+      return 1;
+    }
+  return 0;
+}
+
+/* Decode an opcode if it represents a CBZ or CBNZ instruction.
+
+   ADDR specifies the address of the opcode.
+   INSN specifies the opcode to test.
+   IS64 receives the 'sf' field from the decoded instruction.
+   IS_CBNZ receives the 'op' field from the decoded instruction.
+   RN receives the 'rn' field from the decoded instruction.
+   OFFSET receives the 'imm19' field from the decoded instruction.
+
+   Return 1 if the opcodes matches and is decoded, otherwise 0.  */
+
+int
+aarch64_decode_cb (CORE_ADDR addr, uint32_t insn, int *is64, int *is_cbnz,
+                  unsigned *rn, int32_t *offset)
+{
+  /* cbz  T011 010o iiii iiii iiii iiii iiir rrrr */
+  /* cbnz T011 010o iiii iiii iiii iiii iiir rrrr */
+  if (decode_masked_match (insn, 0x7e000000, 0x34000000))
+    {
+      *rn = (insn >> 0) & 0x1f;
+      *is64 = (insn >> 31) & 0x1;
+      *is_cbnz = (insn >> 24) & 0x1;
+      *offset = extract_signed_bitfield (insn, 19, 5) << 2;
+
+      if (aarch64_debug)
+       {
+         debug_printf ("decode: 0x%s 0x%x %s 0x%s\n",
+                       core_addr_to_string_nz (addr), insn,
+                       *is_cbnz ? "cbnz" : "cbz",
+                       core_addr_to_string_nz (addr + *offset));
+       }
+      return 1;
+    }
+  return 0;
+}
+
+/* Decode an opcode if it represents a TBZ or TBNZ instruction.
+
+   ADDR specifies the address of the opcode.
+   INSN specifies the opcode to test.
+   IS_TBNZ receives the 'op' field from the decoded instruction.
+   BIT receives the bit position field from the decoded instruction.
+   RT receives 'rt' field from the decoded instruction.
+   IMM receives 'imm' field from the decoded instruction.
+
+   Return 1 if the opcodes matches and is decoded, otherwise 0.  */
+
+int
+aarch64_decode_tb (CORE_ADDR addr, uint32_t insn, int *is_tbnz,
+                  unsigned *bit, unsigned *rt, int32_t *imm)
+{
+  /* tbz  b011 0110 bbbb biii iiii iiii iiir rrrr */
+  /* tbnz B011 0111 bbbb biii iiii iiii iiir rrrr */
+  if (decode_masked_match (insn, 0x7e000000, 0x36000000))
+    {
+      *rt = (insn >> 0) & 0x1f;
+      *is_tbnz = (insn >> 24) & 0x1;
+      *bit = ((insn >> (31 - 4)) & 0x20) | ((insn >> 19) & 0x1f);
+      *imm = extract_signed_bitfield (insn, 14, 5) << 2;
+
+      if (aarch64_debug)
+       {
+         debug_printf ("decode: 0x%s 0x%x %s x%u, #%u, 0x%s\n",
+                       core_addr_to_string_nz (addr), insn,
+                       *is_tbnz ? "tbnz" : "tbz", *rt, *bit,
+                       core_addr_to_string_nz (addr + *imm));
+       }
+      return 1;
+    }
+  return 0;
+}
diff --git a/gdb/arch/aarch64-insn.h b/gdb/arch/aarch64-insn.h
new file mode 100644 (file)
index 0000000..7775a34
--- /dev/null
@@ -0,0 +1,38 @@
+/* Copyright (C) 2009-2015 Free Software Foundation, Inc.
+   Contributed by ARM Ltd.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef AARCH64_INSN_H
+#define AARCH64_INSN_H 1
+
+extern int aarch64_debug;
+
+int aarch64_decode_adrp (CORE_ADDR addr, uint32_t insn, unsigned *rd);
+
+int aarch64_decode_b (CORE_ADDR addr, uint32_t insn, int *is_bl,
+                     int32_t *offset);
+
+int aarch64_decode_bcond (CORE_ADDR addr, uint32_t insn, unsigned *cond,
+                         int32_t *offset);
+
+int aarch64_decode_cb (CORE_ADDR addr, uint32_t insn, int *is64,
+                      int *is_cbnz, unsigned *rn, int32_t *offset);
+
+int aarch64_decode_tb (CORE_ADDR addr, uint32_t insn, int *is_tbnz,
+                      unsigned *bit, unsigned *rt, int32_t *imm);
+
+#endif
index c42b4df..33d4cfc 100644 (file)
@@ -38,12 +38,12 @@ esac
 case "${targ}" in
 aarch64*-*-elf)
        # Target: AArch64 embedded system
-       gdb_target_obs="aarch64-tdep.o aarch64-newlib-tdep.o"
+       gdb_target_obs="aarch64-tdep.o aarch64-newlib-tdep.o aarch64-insn.o"
        ;;
 
 aarch64*-*-linux*)
        # Target: AArch64 linux
-       gdb_target_obs="aarch64-tdep.o aarch64-linux-tdep.o \
+       gdb_target_obs="aarch64-tdep.o aarch64-linux-tdep.o aarch64-insn.o \
                        arm-tdep.o arm-linux-tdep.o \
                        glibc-tdep.o linux-tdep.o solib-svr4.o \
                        symfile-mem.o linux-record.o"
index 16b02ca..83a7848 100644 (file)
@@ -1,3 +1,8 @@
+2015-09-21  Pierre Langlois  <pierre.langlois@arm.com>
+
+       * Makefile.in (aarch64-insn.o): New rule.
+       * configure.srv (aarch64*-*-linux*): Add aarch64-insn.o.
+
 2015-09-21  Yao Qi  <yao.qi@linaro.org>
 
        * ax.c [!IN_PROCESS_AGENT] (gdb_agent_op_sizes): Define it.
index b715a32..d096663 100644 (file)
@@ -625,6 +625,12 @@ linux-namespaces.o: ../nat/linux-namespaces.c
        $(COMPILE) $<
        $(POSTCOMPILE)
 
+# Architecture specific object files rules from ../arch
+
+aarch64-insn.o: ../arch/aarch64-insn.c
+       $(COMPILE) $<
+       $(POSTCOMPILE)
+
 aarch64.c : $(srcdir)/../regformats/aarch64.dat $(regdat_sh)
        $(SHELL) $(regdat_sh) $(srcdir)/../regformats/aarch64.dat aarch64.c
 reg-arm.c : $(srcdir)/../regformats/reg-arm.dat $(regdat_sh)
index aa232f8..a62df83 100644 (file)
@@ -53,6 +53,7 @@ case "${target}" in
                        srv_tgtobj="linux-aarch64-low.o aarch64-linux-hw-point.o"
                        srv_tgtobj="$srv_tgtobj linux-aarch32-low.o"
                        srv_tgtobj="$srv_tgtobj aarch64-linux.o"
+                       srv_tgtobj="$srv_tgtobj aarch64-insn.o"
                        srv_tgtobj="${srv_tgtobj} $srv_linux_obj"
                        srv_xmlfiles="aarch64.xml"
                        srv_xmlfiles="${srv_xmlfiles} aarch64-core.xml"