Make aarch64_decode_adrp handle both ADR and ADRP instructions
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)
We will need to decode both ADR and ADRP instructions in GDBserver.
This patch makes common code handle both cases, even if GDB only needs
to decode the ADRP instruction.

gdb/ChangeLog:

* aarch64-tdep.c (aarch64_analyze_prologue): New is_adrp
variable.  Call aarch64_decode_adr instead of
aarch64_decode_adrp.
* arch/aarch64-insn.h (aarch64_decode_adrp): Delete.
(aarch64_decode_adr): New function declaration.
* arch/aarch64-insn.c (aarch64_decode_adrp): Delete.
(aarch64_decode_adr): New function, factored out from
aarch64_decode_adrp to decode both adr and adrp instructions.

gdb/ChangeLog
gdb/aarch64-tdep.c
gdb/arch/aarch64-insn.c
gdb/arch/aarch64-insn.h

index 7d8feeb0ce5644d44ed33f8659d795c8fbade7d9..935daf17c681780257d622da705f5500502e7fa0 100644 (file)
@@ -1,3 +1,14 @@
+2015-09-21  Pierre Langlois  <pierre.langlois@arm.com>
+
+       * aarch64-tdep.c (aarch64_analyze_prologue): New is_adrp
+       variable.  Call aarch64_decode_adr instead of
+       aarch64_decode_adrp.
+       * arch/aarch64-insn.h (aarch64_decode_adrp): Delete.
+       (aarch64_decode_adr): New function declaration.
+       * arch/aarch64-insn.c (aarch64_decode_adrp): Delete.
+       (aarch64_decode_adr): New function, factored out from
+       aarch64_decode_adrp to decode both adr and adrp instructions.
+
 2015-09-21  Pierre Langlois  <pierre.langlois@arm.com>
 
        * Makefile.in (ALL_64_TARGET_OBS): Add aarch64-insn.o.
index 92e24047bb4874b2c052db14f154a0afae052dee..da61e546db9d54ccec386ff3dbf9d6cdd5b90ec9 100644 (file)
@@ -551,13 +551,15 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
       int is_cbnz;
       int is_tbnz;
       unsigned bit;
+      int is_adrp;
       int32_t offset;
 
       insn = read_memory_unsigned_integer (start, 4, byte_order_for_code);
 
       if (aarch64_decode_add_sub_imm (start, insn, &rd, &rn, &imm))
        regs[rd] = pv_add_constant (regs[rn], imm);
-      else if (aarch64_decode_adrp (start, insn, &rd))
+      else if (aarch64_decode_adr (start, insn, &is_adrp, &rd, &offset)
+              && is_adrp)
        regs[rd] = pv_unknown ();
       else if (aarch64_decode_b (start, insn, &is_link, &offset))
        {
index 3a289a26da811b7c0fdf385db3ad2883e69ec801..13d0013d6e971b728191c29a1a0668f89e5dc855 100644 (file)
@@ -55,25 +55,44 @@ 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.
+/* Decode an opcode if it represents an ADR or ADRP instruction.
 
    ADDR specifies the address of the opcode.
    INSN specifies the opcode to test.
+   IS_ADRP receives the 'op' field from the decoded instruction.
    RD receives the 'rd' field from the decoded instruction.
+   OFFSET receives the 'immhi:immlo' 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)
+aarch64_decode_adr (CORE_ADDR addr, uint32_t insn, int *is_adrp,
+                   unsigned *rd, int32_t *offset)
 {
-  if (decode_masked_match (insn, 0x9f000000, 0x90000000))
+  /* adr  0ii1 0000 iiii iiii iiii iiii iiir rrrr */
+  /* adrp 1ii1 0000 iiii iiii iiii iiii iiir rrrr */
+  if (decode_masked_match (insn, 0x1f000000, 0x10000000))
     {
+      uint32_t immlo = (insn >> 29) & 0x3;
+      int32_t immhi = extract_signed_bitfield (insn, 19, 5) << 2;
+
+      *is_adrp = (insn >> 31) & 0x1;
       *rd = (insn >> 0) & 0x1f;
 
+      if (*is_adrp)
+       {
+         /* The ADRP instruction has an offset with a -/+ 4GB range,
+            encoded as (immhi:immlo * 4096).  */
+         *offset = (immhi | immlo) * 4096;
+       }
+      else
+       *offset = (immhi | immlo);
+
       if (aarch64_debug)
        {
-         debug_printf ("decode: 0x%s 0x%x adrp x%u, #?\n",
-                       core_addr_to_string_nz (addr), insn, *rd);
+         debug_printf ("decode: 0x%s 0x%x %s x%u, #?\n",
+                       core_addr_to_string_nz (addr), insn,
+                       *is_adrp ?  "adrp" : "adr", *rd);
        }
       return 1;
     }
index 7775a34e829990efbc334d11b15d20a9b039cf01..2facb44aea8445331d97b075f5b31b8bab589f1d 100644 (file)
@@ -21,7 +21,8 @@
 
 extern int aarch64_debug;
 
-int aarch64_decode_adrp (CORE_ADDR addr, uint32_t insn, unsigned *rd);
+int aarch64_decode_adr (CORE_ADDR addr, uint32_t insn, int *is_adrp,
+                       unsigned *rd, int32_t *offset);
 
 int aarch64_decode_b (CORE_ADDR addr, uint32_t insn, int *is_bl,
                      int32_t *offset);
This page took 0.043222 seconds and 4 git commands to generate.