Add common AARCH64 REGNUM defines
[deliverable/binutils-gdb.git] / gdb / gdbserver / linux-aarch64-low.c
index 1241434f08018ee9bc4e16ac04e380fbc578f940..b00d5c502d2be67daf0e7f48025647f191efef3b 100644 (file)
@@ -1,7 +1,7 @@
 /* GNU/Linux/AArch64 specific low level interface, for the remote server for
    GDB.
 
-   Copyright (C) 2009-2015 Free Software Foundation, Inc.
+   Copyright (C) 2009-2017 Free Software Foundation, Inc.
    Contributed by ARM Ltd.
 
    This file is part of GDB.
@@ -38,6 +38,7 @@
 #include <sys/uio.h>
 
 #include "gdb_proc_service.h"
+#include "arch/aarch64.h"
 
 /* Defined in auto-generated files.  */
 void init_registers_aarch64 (void);
@@ -47,18 +48,6 @@ extern const struct target_desc *tdesc_aarch64;
 #include <sys/reg.h>
 #endif
 
-#define AARCH64_X_REGS_NUM 31
-#define AARCH64_V_REGS_NUM 32
-#define AARCH64_X0_REGNO    0
-#define AARCH64_SP_REGNO   31
-#define AARCH64_PC_REGNO   32
-#define AARCH64_CPSR_REGNO 33
-#define AARCH64_V0_REGNO   34
-#define AARCH64_FPSR_REGNO (AARCH64_V0_REGNO + AARCH64_V_REGS_NUM)
-#define AARCH64_FPCR_REGNO (AARCH64_V0_REGNO + AARCH64_V_REGS_NUM + 1)
-
-#define AARCH64_NUM_REGS (AARCH64_V0_REGNO + AARCH64_V_REGS_NUM + 2)
-
 /* Per-process arch-specific data we want to keep.  */
 
 struct arch_process_info
@@ -105,51 +94,52 @@ aarch64_cannot_fetch_register (int regno)
 static void
 aarch64_fill_gregset (struct regcache *regcache, void *buf)
 {
-  struct user_pt_regs *regset = buf;
+  struct user_pt_regs *regset = (struct user_pt_regs *) buf;
   int i;
 
   for (i = 0; i < AARCH64_X_REGS_NUM; i++)
-    collect_register (regcache, AARCH64_X0_REGNO + i, &regset->regs[i]);
-  collect_register (regcache, AARCH64_SP_REGNO, &regset->sp);
-  collect_register (regcache, AARCH64_PC_REGNO, &regset->pc);
-  collect_register (regcache, AARCH64_CPSR_REGNO, &regset->pstate);
+    collect_register (regcache, AARCH64_X0_REGNUM + i, &regset->regs[i]);
+  collect_register (regcache, AARCH64_SP_REGNUM, &regset->sp);
+  collect_register (regcache, AARCH64_PC_REGNUM, &regset->pc);
+  collect_register (regcache, AARCH64_CPSR_REGNUM, &regset->pstate);
 }
 
 static void
 aarch64_store_gregset (struct regcache *regcache, const void *buf)
 {
-  const struct user_pt_regs *regset = buf;
+  const struct user_pt_regs *regset = (const struct user_pt_regs *) buf;
   int i;
 
   for (i = 0; i < AARCH64_X_REGS_NUM; i++)
-    supply_register (regcache, AARCH64_X0_REGNO + i, &regset->regs[i]);
-  supply_register (regcache, AARCH64_SP_REGNO, &regset->sp);
-  supply_register (regcache, AARCH64_PC_REGNO, &regset->pc);
-  supply_register (regcache, AARCH64_CPSR_REGNO, &regset->pstate);
+    supply_register (regcache, AARCH64_X0_REGNUM + i, &regset->regs[i]);
+  supply_register (regcache, AARCH64_SP_REGNUM, &regset->sp);
+  supply_register (regcache, AARCH64_PC_REGNUM, &regset->pc);
+  supply_register (regcache, AARCH64_CPSR_REGNUM, &regset->pstate);
 }
 
 static void
 aarch64_fill_fpregset (struct regcache *regcache, void *buf)
 {
-  struct user_fpsimd_state *regset = buf;
+  struct user_fpsimd_state *regset = (struct user_fpsimd_state *) buf;
   int i;
 
   for (i = 0; i < AARCH64_V_REGS_NUM; i++)
-    collect_register (regcache, AARCH64_V0_REGNO + i, &regset->vregs[i]);
-  collect_register (regcache, AARCH64_FPSR_REGNO, &regset->fpsr);
-  collect_register (regcache, AARCH64_FPCR_REGNO, &regset->fpcr);
+    collect_register (regcache, AARCH64_V0_REGNUM + i, &regset->vregs[i]);
+  collect_register (regcache, AARCH64_FPSR_REGNUM, &regset->fpsr);
+  collect_register (regcache, AARCH64_FPCR_REGNUM, &regset->fpcr);
 }
 
 static void
 aarch64_store_fpregset (struct regcache *regcache, const void *buf)
 {
-  const struct user_fpsimd_state *regset = buf;
+  const struct user_fpsimd_state *regset
+    = (const struct user_fpsimd_state *) buf;
   int i;
 
   for (i = 0; i < AARCH64_V_REGS_NUM; i++)
-    supply_register (regcache, AARCH64_V0_REGNO + i, &regset->vregs[i]);
-  supply_register (regcache, AARCH64_FPSR_REGNO, &regset->fpsr);
-  supply_register (regcache, AARCH64_FPCR_REGNO, &regset->fpcr);
+    supply_register (regcache, AARCH64_V0_REGNUM + i, &regset->vregs[i]);
+  supply_register (regcache, AARCH64_FPSR_REGNUM, &regset->fpsr);
+  supply_register (regcache, AARCH64_FPCR_REGNUM, &regset->fpcr);
 }
 
 /* Enable miscellaneous debugging output.  The name is historical - it
@@ -162,23 +152,9 @@ static CORE_ADDR
 aarch64_get_pc (struct regcache *regcache)
 {
   if (register_size (regcache->tdesc, 0) == 8)
-    {
-      unsigned long pc;
-
-      collect_register_by_name (regcache, "pc", &pc);
-      if (debug_threads)
-       debug_printf ("stop pc is %08lx\n", pc);
-      return pc;
-    }
+    return linux_get_pc_64bit (regcache);
   else
-    {
-      unsigned int pc;
-
-      collect_register_by_name (regcache, "pc", &pc);
-      if (debug_threads)
-       debug_printf ("stop pc is %04x\n", pc);
-      return pc;
-    }
+    return linux_get_pc_32bit (regcache);
 }
 
 /* Implementation of linux_target_ops method "set_pc".  */
@@ -187,15 +163,9 @@ static void
 aarch64_set_pc (struct regcache *regcache, CORE_ADDR pc)
 {
   if (register_size (regcache->tdesc, 0) == 8)
-    {
-      unsigned long newpc = pc;
-      supply_register_by_name (regcache, "pc", &newpc);
-    }
+    linux_set_pc_64bit (regcache, pc);
   else
-    {
-      unsigned int newpc = pc;
-      supply_register_by_name (regcache, "pc", &newpc);
-    }
+    linux_set_pc_32bit (regcache, pc);
 }
 
 #define aarch64_breakpoint_len 4
@@ -210,14 +180,19 @@ static const gdb_byte aarch64_breakpoint[] = {0x00, 0x00, 0x20, 0xd4};
 static int
 aarch64_breakpoint_at (CORE_ADDR where)
 {
-  gdb_byte insn[aarch64_breakpoint_len];
+  if (is_64bit_tdesc ())
+    {
+      gdb_byte insn[aarch64_breakpoint_len];
 
-  (*the_target->read_memory) (where, (unsigned char *) &insn,
-                             aarch64_breakpoint_len);
-  if (memcmp (insn, aarch64_breakpoint, aarch64_breakpoint_len) == 0)
-    return 1;
+      (*the_target->read_memory) (where, (unsigned char *) &insn,
+                                 aarch64_breakpoint_len);
+      if (memcmp (insn, aarch64_breakpoint, aarch64_breakpoint_len) == 0)
+       return 1;
 
-  return 0;
+      return 0;
+    }
+  else
+    return arm_breakpoint_at (where);
 }
 
 static void
@@ -259,22 +234,6 @@ aarch64_supports_z_point_type (char z_type)
   switch (z_type)
     {
     case Z_PACKET_SW_BP:
-      {
-       if (!extended_protocol && is_64bit_tdesc ())
-         {
-           /* Only enable Z0 packet in non-multi-arch debugging.  If
-              extended protocol is used, don't enable Z0 packet because
-              GDBserver may attach to 32-bit process.  */
-           return 1;
-         }
-       else
-         {
-           /* Disable Z0 packet so that GDBserver doesn't have to handle
-              different breakpoint instructions (aarch64, arm, thumb etc)
-              in multi-arch debugging.  */
-           return 0;
-         }
-      }
     case Z_PACKET_HW_BP:
     case Z_PACKET_WRITE_WP:
     case Z_PACKET_READ_WP:
@@ -315,9 +274,17 @@ aarch64_insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
        ret = -1;
     }
   else
-    ret =
-      aarch64_handle_breakpoint (targ_type, addr, len, 1 /* is_insert */,
-                                state);
+    {
+      if (len == 3)
+       {
+         /* LEN is 3 means the breakpoint is set on a 32-bit thumb
+            instruction.   Set it to 2 to correctly encode length bit
+            mask in hardware/watchpoint control register.  */
+         len = 2;
+       }
+      ret = aarch64_handle_breakpoint (targ_type, addr, len,
+                                      1 /* is_insert */, state);
+    }
 
   if (show_debug_regs)
     aarch64_show_debug_reg_state (state, "insert_point", addr, len,
@@ -353,9 +320,17 @@ aarch64_remove_point (enum raw_bkpt_type type, CORE_ADDR addr,
       aarch64_handle_watchpoint (targ_type, addr, len, 0 /* is_insert */,
                                 state);
   else
-    ret =
-      aarch64_handle_breakpoint (targ_type, addr, len, 0 /* is_insert */,
-                                state);
+    {
+      if (len == 3)
+       {
+         /* LEN is 3 means the breakpoint is set on a 32-bit thumb
+            instruction.   Set it to 2 to correctly encode length bit
+            mask in hardware/watchpoint control register.  */
+         len = 2;
+       }
+      ret = aarch64_handle_breakpoint (targ_type, addr, len,
+                                      0 /* is_insert */,  state);
+    }
 
   if (show_debug_regs)
     aarch64_show_debug_reg_state (state, "remove_point", addr, len,
@@ -415,7 +390,7 @@ aarch64_stopped_by_watchpoint (void)
 /* Fetch the thread-local storage pointer for libthread_db.  */
 
 ps_err_e
-ps_get_thread_area (const struct ps_prochandle *ph,
+ps_get_thread_area (struct ps_prochandle *ph,
                    lwpid_t lwpid, int idx, void **base)
 {
   return aarch64_ps_get_thread_area (ph, lwpid, idx, base,
@@ -425,7 +400,7 @@ ps_get_thread_area (const struct ps_prochandle *ph,
 /* Implementation of linux_target_ops method "siginfo_fixup".  */
 
 static int
-aarch64_linux_siginfo_fixup (siginfo_t *native, void *inf, int direction)
+aarch64_linux_siginfo_fixup (siginfo_t *native, gdb_byte *inf, int direction)
 {
   /* Is the inferior 32-bit?  If so, then fixup the siginfo object.  */
   if (!is_64bit_tdesc ())
@@ -443,7 +418,7 @@ aarch64_linux_siginfo_fixup (siginfo_t *native, void *inf, int direction)
   return 0;
 }
 
-/* Implementation of linux_target_ops method "linux_new_process".  */
+/* Implementation of linux_target_ops method "new_process".  */
 
 static struct arch_process_info *
 aarch64_linux_new_process (void)
@@ -455,6 +430,14 @@ aarch64_linux_new_process (void)
   return info;
 }
 
+/* Implementation of linux_target_ops method "delete_process".  */
+
+static void
+aarch64_linux_delete_process (struct arch_process_info *info)
+{
+  xfree (info);
+}
+
 /* Implementation of linux_target_ops method "linux_new_fork".  */
 
 static void
@@ -523,7 +506,7 @@ static struct regset_info aarch64_regsets[] =
     sizeof (struct user_fpsimd_state), FP_REGS,
     aarch64_fill_fpregset, aarch64_store_fpregset
   },
-  { 0, 0, 0, -1, -1, NULL, NULL }
+  NULL_REGSET
 };
 
 static struct regsets_info aarch64_regsets_info =
@@ -584,91 +567,23 @@ aarch64_get_thread_area (int lwpid, CORE_ADDR *addrp)
   return 0;
 }
 
-/* List of opcodes that we need for building the jump pad and relocating
-   an instruction.  */
-
-enum aarch64_opcodes
-{
-  /* B              0001 01ii iiii iiii iiii iiii iiii iiii */
-  /* BL             1001 01ii iiii iiii iiii iiii iiii iiii */
-  /* B.COND         0101 0100 iiii iiii iiii iiii iii0 cccc */
-  /* CBZ            s011 0100 iiii iiii iiii iiii iiir rrrr */
-  /* CBNZ           s011 0101 iiii iiii iiii iiii iiir rrrr */
-  /* TBZ            b011 0110 bbbb biii iiii iiii iiir rrrr */
-  /* TBNZ           b011 0111 bbbb biii iiii iiii iiir rrrr */
-  B               = 0x14000000,
-  BL              = 0x80000000 | B,
-  BCOND           = 0x40000000 | B,
-  CBZ             = 0x20000000 | B,
-  CBNZ            = 0x21000000 | B,
-  TBZ             = 0x36000000 | B,
-  TBNZ            = 0x37000000 | B,
-  /* BLR            1101 0110 0011 1111 0000 00rr rrr0 0000 */
-  BLR             = 0xd63f0000,
-  /* RET            1101 0110 0101 1111 0000 00rr rrr0 0000 */
-  RET             = 0xd65f0000,
-  /* STP            s010 100o o0ii iiii irrr rrrr rrrr rrrr */
-  /* LDP            s010 100o o1ii iiii irrr rrrr rrrr rrrr */
-  /* STP (SIMD&VFP) ss10 110o o0ii iiii irrr rrrr rrrr rrrr */
-  /* LDP (SIMD&VFP) ss10 110o o1ii iiii irrr rrrr rrrr rrrr */
-  STP             = 0x28000000,
-  LDP             = 0x28400000,
-  STP_SIMD_VFP    = 0x04000000 | STP,
-  LDP_SIMD_VFP    = 0x04000000 | LDP,
-  /* STR            ss11 100o 00xi iiii iiii xxrr rrrr rrrr */
-  /* LDR            ss11 100o 01xi iiii iiii xxrr rrrr rrrr */
-  /* LDRSW          1011 100o 10xi iiii iiii xxrr rrrr rrrr */
-  STR             = 0x38000000,
-  LDR             = 0x00400000 | STR,
-  LDRSW           = 0x80800000 | STR,
-  /* LDAXR          ss00 1000 0101 1111 1111 11rr rrrr rrrr */
-  LDAXR           = 0x085ffc00,
-  /* STXR           ss00 1000 000r rrrr 0111 11rr rrrr rrrr */
-  STXR            = 0x08007c00,
-  /* STLR           ss00 1000 1001 1111 1111 11rr rrrr rrrr */
-  STLR            = 0x089ffc00,
-  /* MOV            s101 0010 1xxi iiii iiii iiii iiir rrrr */
-  /* MOVK           s111 0010 1xxi iiii iiii iiii iiir rrrr */
-  MOV             = 0x52800000,
-  MOVK            = 0x20000000 | MOV,
-  /* ADD            s00o ooo1 xxxx xxxx xxxx xxxx xxxx xxxx */
-  /* SUB            s10o ooo1 xxxx xxxx xxxx xxxx xxxx xxxx */
-  /* SUBS           s11o ooo1 xxxx xxxx xxxx xxxx xxxx xxxx */
-  ADD             = 0x01000000,
-  SUB             = 0x40000000 | ADD,
-  SUBS            = 0x20000000 | SUB,
-  /* AND            s000 1010 xx0x xxxx xxxx xxxx xxxx xxxx */
-  /* ORR            s010 1010 xx0x xxxx xxxx xxxx xxxx xxxx */
-  /* ORN            s010 1010 xx1x xxxx xxxx xxxx xxxx xxxx */
-  /* EOR            s100 1010 xx0x xxxx xxxx xxxx xxxx xxxx */
-  AND             = 0x0a000000,
-  ORR             = 0x20000000 | AND,
-  ORN             = 0x00200000 | ORR,
-  EOR             = 0x40000000 | AND,
-  /* LSLV           s001 1010 110r rrrr 0010 00rr rrrr rrrr */
-  /* LSRV           s001 1010 110r rrrr 0010 01rr rrrr rrrr */
-  /* ASRV           s001 1010 110r rrrr 0010 10rr rrrr rrrr */
-  LSLV             = 0x1ac02000,
-  LSRV             = 0x00000400 | LSLV,
-  ASRV             = 0x00000800 | LSLV,
-  /* SBFM           s001 0011 0nii iiii iiii iirr rrrr rrrr */
-  SBFM            = 0x13000000,
-  /* UBFM           s101 0011 0nii iiii iiii iirr rrrr rrrr */
-  UBFM            = 0x40000000 | SBFM,
-  /* CSINC          s001 1010 100r rrrr cccc 01rr rrrr rrrr */
-  CSINC           = 0x9a800400,
-  /* MUL            s001 1011 000r rrrr 0111 11rr rrrr rrrr */
-  MUL             = 0x1b007c00,
-  /* MSR (register) 1101 0101 0001 oooo oooo oooo ooor rrrr */
-  /* MRS            1101 0101 0011 oooo oooo oooo ooor rrrr */
-  MSR             = 0xd5100000,
-  MRS             = 0x00200000 | MSR,
-  /* HINT           1101 0101 0000 0011 0010 oooo ooo1 1111 */
-  HINT            = 0xd503201f,
-  SEVL            = (5 << 5) | HINT,
-  WFE             = (2 << 5) | HINT,
-  NOP             = (0 << 5) | HINT,
-};
+/* Implementation of linux_target_ops method "get_syscall_trapinfo".  */
+
+static void
+aarch64_get_syscall_trapinfo (struct regcache *regcache, int *sysno)
+{
+  int use_64bit = register_size (regcache->tdesc, 0) == 8;
+
+  if (use_64bit)
+    {
+      long l_sysno;
+
+      collect_register_by_name (regcache, "x8", &l_sysno);
+      *sysno = (int) l_sysno;
+    }
+  else
+    collect_register_by_name (regcache, "r7", sysno);
+}
 
 /* List of condition codes that we need.  */
 
@@ -683,14 +598,10 @@ enum aarch64_condition_codes
   LE = 0xd,
 };
 
-/* Representation of a general purpose register of the form xN or wN.
-
-   This type is used by emitting functions that take registers as operands.  */
-
-struct aarch64_register
+enum aarch64_operand_type
 {
-  unsigned num;
-  int is64;
+  OPERAND_IMMEDIATE,
+  OPERAND_REGISTER,
 };
 
 /* Representation of an operand.  At this time, it only supports register
@@ -699,11 +610,8 @@ struct aarch64_register
 struct aarch64_operand
 {
   /* Type of the operand.  */
-  enum
-    {
-      OPERAND_IMMEDIATE,
-      OPERAND_REGISTER,
-    } type;
+  enum aarch64_operand_type type;
+
   /* Value of the operand according to the type.  */
   union
     {
@@ -779,28 +687,6 @@ immediate_operand (uint32_t imm)
   return operand;
 }
 
-/* Representation of a memory operand, used for load and store
-   instructions.
-
-   The types correspond to the following variants:
-
-   MEMORY_OPERAND_OFFSET:    LDR rt, [rn, #offset]
-   MEMORY_OPERAND_PREINDEX:  LDR rt, [rn, #index]!
-   MEMORY_OPERAND_POSTINDEX: LDR rt, [rn], #index  */
-
-struct aarch64_memory_operand
-{
-  /* Type of the operand.  */
-  enum
-    {
-      MEMORY_OPERAND_OFFSET,
-      MEMORY_OPERAND_PREINDEX,
-      MEMORY_OPERAND_POSTINDEX,
-    } type;
-  /* Index from the base register.  */
-  int32_t index;
-};
-
 /* Helper function to create an offset memory operand.
 
    For example:
@@ -852,108 +738,6 @@ enum aarch64_system_control_registers
   TPIDR_EL0 = (0x1 << 14) | (0x3 << 11) | (0xd << 7) | (0x0 << 3) | 0x2
 };
 
-/* Helper macro to mask and shift a value into a bitfield.  */
-
-#define ENCODE(val, size, offset) \
-  ((uint32_t) ((val & ((1ULL << size) - 1)) << offset))
-
-/* Write a 32-bit unsigned integer INSN info *BUF.  Return the number of
-   instructions written (aka. 1).  */
-
-static int
-emit_insn (uint32_t *buf, uint32_t insn)
-{
-  *buf = insn;
-  return 1;
-}
-
-/* Write a B or BL instruction into *BUF.
-
-     B  #offset
-     BL #offset
-
-   IS_BL specifies if the link register should be updated.
-   OFFSET is the immediate offset from the current PC.  It is
-   byte-addressed but should be 4 bytes aligned.  It has a limited range of
-   +/- 128MB (26 bits << 2).  */
-
-static int
-emit_b (uint32_t *buf, int is_bl, int32_t offset)
-{
-  uint32_t imm26 = ENCODE (offset >> 2, 26, 0);
-
-  if (is_bl)
-    return emit_insn (buf, BL | imm26);
-  else
-    return emit_insn (buf, B | imm26);
-}
-
-/* Write a BCOND instruction into *BUF.
-
-     B.COND #offset
-
-   COND specifies the condition field.
-   OFFSET is the immediate offset from the current PC.  It is
-   byte-addressed but should be 4 bytes aligned.  It has a limited range of
-   +/- 1MB (19 bits << 2).  */
-
-static int
-emit_bcond (uint32_t *buf, unsigned cond, int32_t offset)
-{
-  return emit_insn (buf, BCOND | ENCODE (offset >> 2, 19, 5)
-                   | ENCODE (cond, 4, 0));
-}
-
-/* Write a CBZ or CBNZ instruction into *BUF.
-
-     CBZ  rt, #offset
-     CBNZ rt, #offset
-
-   IS_CBNZ distinguishes between CBZ and CBNZ instructions.
-   RN is the register to test.
-   OFFSET is the immediate offset from the current PC.  It is
-   byte-addressed but should be 4 bytes aligned.  It has a limited range of
-   +/- 1MB (19 bits << 2).  */
-
-static int
-emit_cb (uint32_t *buf, int is_cbnz, struct aarch64_register rt,
-        int32_t offset)
-{
-  uint32_t imm19 = ENCODE (offset >> 2, 19, 5);
-  uint32_t sf = ENCODE (rt.is64, 1, 31);
-
-  if (is_cbnz)
-    return emit_insn (buf, CBNZ | sf | imm19 | ENCODE (rt.num, 5, 0));
-  else
-    return emit_insn (buf, CBZ | sf | imm19 | ENCODE (rt.num, 5, 0));
-}
-
-/* Write a TBZ or TBNZ instruction into *BUF.
-
-     TBZ  rt, #bit, #offset
-     TBNZ rt, #bit, #offset
-
-   IS_TBNZ distinguishes between TBZ and TBNZ instructions.
-   RT is the register to test.
-   BIT is the index of the bit to test in register RT.
-   OFFSET is the immediate offset from the current PC.  It is
-   byte-addressed but should be 4 bytes aligned.  It has a limited range of
-   +/- 32KB (14 bits << 2).  */
-
-static int
-emit_tb (uint32_t *buf, int is_tbnz, unsigned bit,
-        struct aarch64_register rt, int32_t offset)
-{
-  uint32_t imm14 = ENCODE (offset >> 2, 14, 5);
-  uint32_t b40 = ENCODE (bit, 5, 19);
-  uint32_t b5 = ENCODE (bit >> 5, 1, 31);
-
-  if (is_tbnz)
-    return emit_insn (buf, TBNZ | b5 | b40 | imm14 | ENCODE (rt.num, 5, 0));
-  else
-    return emit_insn (buf, TBZ | b5 | b40 | imm14 | ENCODE (rt.num, 5, 0));
-}
-
 /* Write a BLR instruction into *BUF.
 
      BLR rn
@@ -963,7 +747,7 @@ emit_tb (uint32_t *buf, int is_tbnz, unsigned bit,
 static int
 emit_blr (uint32_t *buf, struct aarch64_register rn)
 {
-  return emit_insn (buf, BLR | ENCODE (rn.num, 5, 5));
+  return aarch64_emit_insn (buf, BLR | ENCODE (rn.num, 5, 5));
 }
 
 /* Write a RET instruction into *BUF.
@@ -975,7 +759,7 @@ emit_blr (uint32_t *buf, struct aarch64_register rn)
 static int
 emit_ret (uint32_t *buf, struct aarch64_register rn)
 {
-  return emit_insn (buf, RET | ENCODE (rn.num, 5, 5));
+  return aarch64_emit_insn (buf, RET | ENCODE (rn.num, 5, 5));
 }
 
 static int
@@ -1018,10 +802,10 @@ emit_load_store_pair (uint32_t *buf, enum aarch64_opcodes opcode,
       return 0;
     }
 
-  return emit_insn (buf, opcode | opc | pre_index | write_back
-                   | ENCODE (operand.index >> 3, 7, 15)
-                   | ENCODE (rt2.num, 5, 10)
-                   | ENCODE (rn.num, 5, 5) | ENCODE (rt.num, 5, 0));
+  return aarch64_emit_insn (buf, opcode | opc | pre_index | write_back
+                           | ENCODE (operand.index >> 3, 7, 15)
+                           | ENCODE (rt2.num, 5, 10)
+                           | ENCODE (rn.num, 5, 5) | ENCODE (rt.num, 5, 0));
 }
 
 /* Write a STP instruction into *BUF.
@@ -1078,9 +862,10 @@ emit_ldp_q_offset (uint32_t *buf, unsigned rt, unsigned rt2,
   uint32_t opc = ENCODE (2, 2, 30);
   uint32_t pre_index = ENCODE (1, 1, 24);
 
-  return emit_insn (buf, LDP_SIMD_VFP | opc | pre_index
-                   | ENCODE (offset >> 4, 7, 15) | ENCODE (rt2, 5, 10)
-                   | ENCODE (rn.num, 5, 5) | ENCODE (rt, 5, 0));
+  return aarch64_emit_insn (buf, LDP_SIMD_VFP | opc | pre_index
+                           | ENCODE (offset >> 4, 7, 15)
+                           | ENCODE (rt2, 5, 10)
+                           | ENCODE (rn.num, 5, 5) | ENCODE (rt, 5, 0));
 }
 
 /* Write a STP (SIMD&VFP) instruction using Q registers into *BUF.
@@ -1099,71 +884,10 @@ emit_stp_q_offset (uint32_t *buf, unsigned rt, unsigned rt2,
   uint32_t opc = ENCODE (2, 2, 30);
   uint32_t pre_index = ENCODE (1, 1, 24);
 
-  return emit_insn (buf, STP_SIMD_VFP | opc | pre_index
-                   | ENCODE (offset >> 4, 7, 15) | ENCODE (rt2, 5, 10)
-                   | ENCODE (rn.num, 5, 5) | ENCODE (rt, 5, 0));
-}
-
-/* Helper function emitting a load or store instruction.  */
-
-static int
-emit_load_store (uint32_t *buf, uint32_t size, enum aarch64_opcodes opcode,
-                struct aarch64_register rt, struct aarch64_register rn,
-                struct aarch64_memory_operand operand)
-{
-  uint32_t op;
-
-  switch (operand.type)
-    {
-    case MEMORY_OPERAND_OFFSET:
-      {
-       op = ENCODE (1, 1, 24);
-
-       return emit_insn (buf, opcode | ENCODE (size, 2, 30) | op
-                         | ENCODE (operand.index >> 3, 12, 10)
-                         | ENCODE (rn.num, 5, 5) | ENCODE (rt.num, 5, 0));
-      }
-    case MEMORY_OPERAND_POSTINDEX:
-      {
-       uint32_t post_index = ENCODE (1, 2, 10);
-
-       op = ENCODE (0, 1, 24);
-
-       return emit_insn (buf, opcode | ENCODE (size, 2, 30) | op
-                         | post_index | ENCODE (operand.index, 9, 12)
-                         | ENCODE (rn.num, 5, 5) | ENCODE (rt.num, 5, 0));
-      }
-    case MEMORY_OPERAND_PREINDEX:
-      {
-       uint32_t pre_index = ENCODE (3, 2, 10);
-
-       op = ENCODE (0, 1, 24);
-
-       return emit_insn (buf, opcode | ENCODE (size, 2, 30) | op
-                         | pre_index | ENCODE (operand.index, 9, 12)
-                         | ENCODE (rn.num, 5, 5) | ENCODE (rt.num, 5, 0));
-      }
-    default:
-      return 0;
-    }
-}
-
-/* Write a LDR instruction into *BUF.
-
-     LDR rt, [rn, #offset]
-     LDR rt, [rn, #index]!
-     LDR rt, [rn], #index
-
-   RT is the register to store.
-   RN is the base address register.
-   OFFSET is the immediate to add to the base address.  It is limited to
-   0 .. 32760 range (12 bits << 3).  */
-
-static int
-emit_ldr (uint32_t *buf, struct aarch64_register rt,
-         struct aarch64_register rn, struct aarch64_memory_operand operand)
-{
-  return emit_load_store (buf, rt.is64 ? 3 : 2, LDR, rt, rn, operand);
+  return aarch64_emit_insn (buf, STP_SIMD_VFP | opc | pre_index
+                           | ENCODE (offset >> 4, 7, 15)
+                           | ENCODE (rt2, 5, 10)
+                           | ENCODE (rn.num, 5, 5) | ENCODE (rt, 5, 0));
 }
 
 /* Write a LDRH instruction into *BUF.
@@ -1182,7 +906,7 @@ emit_ldrh (uint32_t *buf, struct aarch64_register rt,
           struct aarch64_register rn,
           struct aarch64_memory_operand operand)
 {
-  return emit_load_store (buf, 1, LDR, rt, rn, operand);
+  return aarch64_emit_load_store (buf, 1, LDR, rt, rn, operand);
 }
 
 /* Write a LDRB instruction into *BUF.
@@ -1201,27 +925,10 @@ emit_ldrb (uint32_t *buf, struct aarch64_register rt,
           struct aarch64_register rn,
           struct aarch64_memory_operand operand)
 {
-  return emit_load_store (buf, 0, LDR, rt, rn, operand);
+  return aarch64_emit_load_store (buf, 0, LDR, rt, rn, operand);
 }
 
-/* Write a LDRSW instruction into *BUF.  The register size is 64-bit.
-
-     LDRSW xt, [rn, #offset]
-     LDRSW xt, [rn, #index]!
-     LDRSW xt, [rn], #index
-
-   RT is the register to store.
-   RN is the base address register.
-   OFFSET is the immediate to add to the base address.  It is limited to
-   0 .. 16380 range (12 bits << 2).  */
 
-static int
-emit_ldrsw (uint32_t *buf, struct aarch64_register rt,
-                  struct aarch64_register rn,
-                  struct aarch64_memory_operand operand)
-{
-  return emit_load_store (buf, 3, LDRSW, rt, rn, operand);
-}
 
 /* Write a STR instruction into *BUF.
 
@@ -1239,7 +946,7 @@ emit_str (uint32_t *buf, struct aarch64_register rt,
          struct aarch64_register rn,
          struct aarch64_memory_operand operand)
 {
-  return emit_load_store (buf, rt.is64 ? 3 : 2, STR, rt, rn, operand);
+  return aarch64_emit_load_store (buf, rt.is64 ? 3 : 2, STR, rt, rn, operand);
 }
 
 /* Helper function emitting an exclusive load or store instruction.  */
@@ -1252,9 +959,9 @@ emit_load_store_exclusive (uint32_t *buf, uint32_t size,
                           struct aarch64_register rt2,
                           struct aarch64_register rn)
 {
-  return emit_insn (buf, opcode | ENCODE (size, 2, 30)
-                   | ENCODE (rs.num, 5, 16) | ENCODE (rt2.num, 5, 10)
-                   | ENCODE (rn.num, 5, 5) | ENCODE (rt.num, 5, 0));
+  return aarch64_emit_insn (buf, opcode | ENCODE (size, 2, 30)
+                           | ENCODE (rs.num, 5, 16) | ENCODE (rt2.num, 5, 10)
+                           | ENCODE (rn.num, 5, 5) | ENCODE (rt.num, 5, 0));
 }
 
 /* Write a LAXR instruction into *BUF.
@@ -1306,15 +1013,15 @@ emit_stlr (uint32_t *buf, struct aarch64_register rt,
 /* Helper function for data processing instructions with register sources.  */
 
 static int
-emit_data_processing_reg (uint32_t *buf, enum aarch64_opcodes opcode,
+emit_data_processing_reg (uint32_t *buf, uint32_t opcode,
                          struct aarch64_register rd,
                          struct aarch64_register rn,
                          struct aarch64_register rm)
 {
   uint32_t size = ENCODE (rd.is64, 1, 31);
 
-  return emit_insn (buf, opcode | size | ENCODE (rm.num, 5, 16)
-                   | ENCODE (rn.num, 5, 5) | ENCODE (rd.num, 5, 0));
+  return aarch64_emit_insn (buf, opcode | size | ENCODE (rm.num, 5, 16)
+                           | ENCODE (rn.num, 5, 5) | ENCODE (rd.num, 5, 0));
 }
 
 /* Helper function for data processing instructions taking either a register
@@ -1335,9 +1042,10 @@ emit_data_processing (uint32_t *buf, enum aarch64_opcodes opcode,
       /* xxx1 000x xxxx xxxx xxxx xxxx xxxx xxxx */
       operand_opcode = ENCODE (8, 4, 25);
 
-      return emit_insn (buf, opcode | operand_opcode | size
-                       | ENCODE (operand.imm, 12, 10)
-                       | ENCODE (rn.num, 5, 5) | ENCODE (rd.num, 5, 0));
+      return aarch64_emit_insn (buf, opcode | operand_opcode | size
+                               | ENCODE (operand.imm, 12, 10)
+                               | ENCODE (rn.num, 5, 5)
+                               | ENCODE (rd.num, 5, 0));
     }
   else
     {
@@ -1410,9 +1118,9 @@ emit_mov (uint32_t *buf, struct aarch64_register rd,
       /* Do not shift the immediate.  */
       uint32_t shift = ENCODE (0, 2, 21);
 
-      return emit_insn (buf, MOV | size | shift
-                       | ENCODE (operand.imm, 16, 5)
-                       | ENCODE (rd.num, 5, 0));
+      return aarch64_emit_insn (buf, MOV | size | shift
+                               | ENCODE (operand.imm, 16, 5)
+                               | ENCODE (rd.num, 5, 0));
     }
   else
     return emit_add (buf, rd, operand.reg, immediate_operand (0));
@@ -1432,8 +1140,8 @@ emit_movk (uint32_t *buf, struct aarch64_register rd, uint32_t imm,
 {
   uint32_t size = ENCODE (rd.is64, 1, 31);
 
-  return emit_insn (buf, MOVK | size | ENCODE (shift, 2, 21) |
-                   ENCODE (imm, 16, 5) | ENCODE (rd.num, 5, 0));
+  return aarch64_emit_insn (buf, MOVK | size | ENCODE (shift, 2, 21) |
+                           ENCODE (imm, 16, 5) | ENCODE (rd.num, 5, 0));
 }
 
 /* Write instructions into *BUF in order to move ADDR into a register.
@@ -1641,8 +1349,8 @@ static int
 emit_mrs (uint32_t *buf, struct aarch64_register rt,
          enum aarch64_system_control_registers system_reg)
 {
-  return emit_insn (buf, MRS | ENCODE (system_reg, 15, 5)
-                   | ENCODE (rt.num, 5, 0));
+  return aarch64_emit_insn (buf, MRS | ENCODE (system_reg, 15, 5)
+                           | ENCODE (rt.num, 5, 0));
 }
 
 /* Write a MSR instruction into *BUF.  The register size is 64-bit.
@@ -1656,8 +1364,8 @@ static int
 emit_msr (uint32_t *buf, enum aarch64_system_control_registers system_reg,
          struct aarch64_register rt)
 {
-  return emit_insn (buf, MSR | ENCODE (system_reg, 15, 5)
-                   | ENCODE (rt.num, 5, 0));
+  return aarch64_emit_insn (buf, MSR | ENCODE (system_reg, 15, 5)
+                           | ENCODE (rt.num, 5, 0));
 }
 
 /* Write a SEVL instruction into *BUF.
@@ -1667,7 +1375,7 @@ emit_msr (uint32_t *buf, enum aarch64_system_control_registers system_reg,
 static int
 emit_sevl (uint32_t *buf)
 {
-  return emit_insn (buf, SEVL);
+  return aarch64_emit_insn (buf, SEVL);
 }
 
 /* Write a WFE instruction into *BUF.
@@ -1677,7 +1385,7 @@ emit_sevl (uint32_t *buf)
 static int
 emit_wfe (uint32_t *buf)
 {
-  return emit_insn (buf, WFE);
+  return aarch64_emit_insn (buf, WFE);
 }
 
 /* Write a SBFM instruction into *BUF.
@@ -1699,9 +1407,9 @@ emit_sbfm (uint32_t *buf, struct aarch64_register rd,
   uint32_t size = ENCODE (rd.is64, 1, 31);
   uint32_t n = ENCODE (rd.is64, 1, 22);
 
-  return emit_insn (buf, SBFM | size | n | ENCODE (immr, 6, 16)
-                   | ENCODE (imms, 6, 10) | ENCODE (rn.num, 5, 5)
-                   | ENCODE (rd.num, 5, 0));
+  return aarch64_emit_insn (buf, SBFM | size | n | ENCODE (immr, 6, 16)
+                           | ENCODE (imms, 6, 10) | ENCODE (rn.num, 5, 5)
+                           | ENCODE (rd.num, 5, 0));
 }
 
 /* Write a SBFX instruction into *BUF.
@@ -1744,9 +1452,9 @@ emit_ubfm (uint32_t *buf, struct aarch64_register rd,
   uint32_t size = ENCODE (rd.is64, 1, 31);
   uint32_t n = ENCODE (rd.is64, 1, 22);
 
-  return emit_insn (buf, UBFM | size | n | ENCODE (immr, 6, 16)
-                   | ENCODE (imms, 6, 10) | ENCODE (rn.num, 5, 5)
-                   | ENCODE (rd.num, 5, 0));
+  return aarch64_emit_insn (buf, UBFM | size | n | ENCODE (immr, 6, 16)
+                           | ENCODE (imms, 6, 10) | ENCODE (rn.num, 5, 5)
+                           | ENCODE (rd.num, 5, 0));
 }
 
 /* Write a UBFX instruction into *BUF.
@@ -1788,9 +1496,9 @@ emit_csinc (uint32_t *buf, struct aarch64_register rd,
 {
   uint32_t size = ENCODE (rd.is64, 1, 31);
 
-  return emit_insn (buf, CSINC | size | ENCODE (rm.num, 5, 16)
-                   | ENCODE (cond, 4, 12) | ENCODE (rn.num, 5, 5)
-                   | ENCODE (rd.num, 5, 0));
+  return aarch64_emit_insn (buf, CSINC | size | ENCODE (rm.num, 5, 16)
+                           | ENCODE (cond, 4, 12) | ENCODE (rn.num, 5, 5)
+                           | ENCODE (rd.num, 5, 0));
 }
 
 /* Write a CSET instruction into *BUF.
@@ -1816,14 +1524,6 @@ emit_cset (uint32_t *buf, struct aarch64_register rd, unsigned cond)
   return emit_csinc (buf, rd, xzr, xzr, cond ^ 0x1);
 }
 
-/* Write a NOP instruction into *BUF.  */
-
-static int
-emit_nop (uint32_t *buf)
-{
-  return emit_insn (buf, NOP);
-}
-
 /* Write LEN instructions from BUF into the inferior memory at *TO.
 
    Note instructions are always little endian on AArch64, unlike data.  */
@@ -1833,7 +1533,7 @@ append_insns (CORE_ADDR *to, size_t len, const uint32_t *buf)
 {
   size_t byte_len = len * sizeof (uint32_t);
 #if (__BYTE_ORDER == __BIG_ENDIAN)
-  uint32_t *le_buf = xmalloc (byte_len);
+  uint32_t *le_buf = (uint32_t *) xmalloc (byte_len);
   size_t i;
 
   for (i = 0; i < len; i++)
@@ -1849,17 +1549,6 @@ append_insns (CORE_ADDR *to, size_t len, const uint32_t *buf)
   *to += byte_len;
 }
 
-/* Helper function.  Return 1 if VAL can be encoded in BITS bits.  */
-
-static int
-can_encode_int32 (int32_t val, unsigned bits)
-{
-  /* This must be an arithemic shift.  */
-  int32_t rest = val >> bits;
-
-  return rest == 0 || rest == -1;
-}
-
 /* Sub-class of struct aarch64_insn_data, store information of
    instruction relocation for fast tracepoint.  Visitor can
    relocate an instruction from BASE.INSN_ADDR to NEW_ADDR and save
@@ -1883,7 +1572,7 @@ aarch64_ftrace_insn_reloc_b (const int is_bl, const int32_t offset,
 {
   struct aarch64_insn_relocation_data *insn_reloc
     = (struct aarch64_insn_relocation_data *) data;
-  int32_t new_offset
+  int64_t new_offset
     = insn_reloc->base.insn_addr - insn_reloc->new_addr + offset;
 
   if (can_encode_int32 (new_offset, 28))
@@ -1898,7 +1587,7 @@ aarch64_ftrace_insn_reloc_b_cond (const unsigned cond, const int32_t offset,
 {
   struct aarch64_insn_relocation_data *insn_reloc
     = (struct aarch64_insn_relocation_data *) data;
-  int32_t new_offset
+  int64_t new_offset
     = insn_reloc->base.insn_addr - insn_reloc->new_addr + offset;
 
   if (can_encode_int32 (new_offset, 21))
@@ -1935,7 +1624,7 @@ aarch64_ftrace_insn_reloc_cb (const int32_t offset, const int is_cbnz,
 {
   struct aarch64_insn_relocation_data *insn_reloc
     = (struct aarch64_insn_relocation_data *) data;
-  int32_t new_offset
+  int64_t new_offset
     = insn_reloc->base.insn_addr - insn_reloc->new_addr + offset;
 
   if (can_encode_int32 (new_offset, 21))
@@ -1972,7 +1661,7 @@ aarch64_ftrace_insn_reloc_tb (const int32_t offset, int is_tbnz,
 {
   struct aarch64_insn_relocation_data *insn_reloc
     = (struct aarch64_insn_relocation_data *) data;
-  int32_t new_offset
+  int64_t new_offset
     = insn_reloc->base.insn_addr - insn_reloc->new_addr + offset;
 
   if (can_encode_int32 (new_offset, 16))
@@ -2074,7 +1763,7 @@ aarch64_ftrace_insn_reloc_others (const uint32_t insn,
 
   /* The instruction is not PC relative.  Just re-emit it at the new
      location.  */
-  insn_reloc->insn_ptr += emit_insn (insn_reloc->insn_ptr, insn);
+  insn_reloc->insn_ptr += aarch64_emit_insn (insn_reloc->insn_ptr, insn);
 }
 
 static const struct aarch64_insn_visitor visitor =
@@ -2108,7 +1797,7 @@ aarch64_install_fast_tracepoint_jump_pad (CORE_ADDR tpoint,
 {
   uint32_t buf[256];
   uint32_t *p = buf;
-  int32_t offset;
+  int64_t offset;
   int i;
   uint32_t insn;
   CORE_ADDR buildaddr = *jump_entry;
@@ -2445,7 +2134,7 @@ aarch64_install_fast_tracepoint_jump_pad (CORE_ADDR tpoint,
     {
       sprintf (err,
               "E.Jump back from jump pad too far from tracepoint "
-              "(offset 0x%" PRIx32 " cannot be encoded in 28 bits).",
+              "(offset 0x%" PRIx64 " cannot be encoded in 28 bits).",
               offset);
       return 1;
     }
@@ -2459,7 +2148,7 @@ aarch64_install_fast_tracepoint_jump_pad (CORE_ADDR tpoint,
     {
       sprintf (err,
               "E.Jump pad too far from tracepoint "
-              "(offset 0x%" PRIx32 " cannot be encoded in 28 bits).",
+              "(offset 0x%" PRIx64 " cannot be encoded in 28 bits).",
               offset);
       return 1;
     }
@@ -2584,7 +2273,7 @@ aarch64_emit_add (void)
   uint32_t *p = buf;
 
   p += emit_pop (p, x1);
-  p += emit_add (p, x0, x0, register_operand (x1));
+  p += emit_add (p, x0, x1, register_operand (x0));
 
   emit_ops_insns (buf, p - buf);
 }
@@ -2598,7 +2287,7 @@ aarch64_emit_sub (void)
   uint32_t *p = buf;
 
   p += emit_pop (p, x1);
-  p += emit_sub (p, x0, x0, register_operand (x1));
+  p += emit_sub (p, x0, x1, register_operand (x0));
 
   emit_ops_insns (buf, p - buf);
 }
@@ -3230,6 +2919,51 @@ aarch64_supports_range_stepping (void)
   return 1;
 }
 
+/* Implementation of linux_target_ops method "sw_breakpoint_from_kind".  */
+
+static const gdb_byte *
+aarch64_sw_breakpoint_from_kind (int kind, int *size)
+{
+  if (is_64bit_tdesc ())
+    {
+      *size = aarch64_breakpoint_len;
+      return aarch64_breakpoint;
+    }
+  else
+    return arm_sw_breakpoint_from_kind (kind, size);
+}
+
+/* Implementation of linux_target_ops method "breakpoint_kind_from_pc".  */
+
+static int
+aarch64_breakpoint_kind_from_pc (CORE_ADDR *pcptr)
+{
+  if (is_64bit_tdesc ())
+    return aarch64_breakpoint_len;
+  else
+    return arm_breakpoint_kind_from_pc (pcptr);
+}
+
+/* Implementation of the linux_target_ops method
+   "breakpoint_kind_from_current_state".  */
+
+static int
+aarch64_breakpoint_kind_from_current_state (CORE_ADDR *pcptr)
+{
+  if (is_64bit_tdesc ())
+    return aarch64_breakpoint_len;
+  else
+    return arm_breakpoint_kind_from_current_state (pcptr);
+}
+
+/* Support for hardware single step.  */
+
+static int
+aarch64_supports_hardware_single_step (void)
+{
+  return 1;
+}
+
 struct linux_target_ops the_low_target =
 {
   aarch64_arch_setup,
@@ -3239,9 +2973,9 @@ struct linux_target_ops the_low_target =
   NULL, /* fetch_register */
   aarch64_get_pc,
   aarch64_set_pc,
-  (const unsigned char *) &aarch64_breakpoint,
-  aarch64_breakpoint_len,
-  NULL, /* breakpoint_reinsert_addr */
+  aarch64_breakpoint_kind_from_pc,
+  aarch64_sw_breakpoint_from_kind,
+  NULL, /* get_next_pcs */
   0,    /* decr_pc_after_break */
   aarch64_breakpoint_at,
   aarch64_supports_z_point_type,
@@ -3253,7 +2987,9 @@ struct linux_target_ops the_low_target =
   NULL, /* supply_ptrace_register */
   aarch64_linux_siginfo_fixup,
   aarch64_linux_new_process,
+  aarch64_linux_delete_process,
   aarch64_linux_new_thread,
+  aarch64_linux_delete_thread,
   aarch64_linux_new_fork,
   aarch64_linux_prepare_to_resume,
   NULL, /* process_qsupported */
@@ -3263,6 +2999,9 @@ struct linux_target_ops the_low_target =
   aarch64_emit_ops,
   aarch64_get_min_fast_tracepoint_insn_len,
   aarch64_supports_range_stepping,
+  aarch64_breakpoint_kind_from_current_state,
+  aarch64_supports_hardware_single_step,
+  aarch64_get_syscall_trapinfo,
 };
 
 void
This page took 0.039603 seconds and 4 git commands to generate.