GDBARCH_BREAKPOINT_MANIPULATION and SET_GDBARCH_BREAKPOINT_MANIPULATION
[deliverable/binutils-gdb.git] / gdb / aarch64-tdep.c
index 8ce0eaadb627baae6604e2bb9da03e98aaa2c3e7..304d9df7e84b1ba24623397bd2c1038fdea9f65e 100644 (file)
@@ -1,6 +1,6 @@
 /* Common target dependent code for GDB on AArch64 systems.
 
-   Copyright (C) 2009-2015 Free Software Foundation, Inc.
+   Copyright (C) 2009-2016 Free Software Foundation, Inc.
    Contributed by ARM Ltd.
 
    This file is part of GDB.
@@ -60,6 +60,7 @@
 #include "arch/aarch64-insn.h"
 
 #include "opcode/aarch64.h"
+#include <algorithm>
 
 #define submask(x) ((1L << ((x) + 1)) - 1)
 #define bit(obj,st) (((obj) >> (st)) & 1)
@@ -67,7 +68,7 @@
 
 /* Pseudo register base numbers.  */
 #define AARCH64_Q0_REGNUM 0
-#define AARCH64_D0_REGNUM (AARCH64_Q0_REGNUM + 32)
+#define AARCH64_D0_REGNUM (AARCH64_Q0_REGNUM + AARCH64_D_REGISTER_COUNT)
 #define AARCH64_S0_REGNUM (AARCH64_D0_REGNUM + 32)
 #define AARCH64_H0_REGNUM (AARCH64_S0_REGNUM + 32)
 #define AARCH64_B0_REGNUM (AARCH64_H0_REGNUM + 32)
@@ -205,11 +206,12 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
 {
   enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
   int i;
-  pv_t regs[AARCH64_X_REGISTER_COUNT];
+  /* Track X registers and D registers in prologue.  */
+  pv_t regs[AARCH64_X_REGISTER_COUNT + AARCH64_D_REGISTER_COUNT];
   struct pv_area *stack;
   struct cleanup *back_to;
 
-  for (i = 0; i < AARCH64_X_REGISTER_COUNT; i++)
+  for (i = 0; i < AARCH64_X_REGISTER_COUNT + AARCH64_D_REGISTER_COUNT; i++)
     regs[i] = pv_register (i, 0);
   stack = make_pv_area (AARCH64_SP_REGNUM, gdbarch_addr_bit (gdbarch));
   back_to = make_cleanup_free_pv_area (stack);
@@ -299,7 +301,7 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
              if (aarch64_debug)
                {
                  debug_printf ("aarch64: prologue analysis gave up "
-                               "addr=0x%s opcode=0x%x (orr x register)\n",
+                               "addr=%s opcode=0x%x (orr x register)\n",
                                core_addr_to_string_nz (start), insn);
                }
              break;
@@ -322,17 +324,20 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
                         is64 ? 8 : 4, regs[rt]);
        }
       else if ((inst.opcode->iclass == ldstpair_off
-               || inst.opcode->iclass == ldstpair_indexed)
-              && inst.operands[2].addr.preind
+               || (inst.opcode->iclass == ldstpair_indexed
+                   && inst.operands[2].addr.preind))
               && strcmp ("stp", inst.opcode->name) == 0)
        {
-         unsigned rt1 = inst.operands[0].reg.regno;
-         unsigned rt2 = inst.operands[1].reg.regno;
+         /* STP with addressing mode Pre-indexed and Base register.  */
+         unsigned rt1;
+         unsigned rt2;
          unsigned rn = inst.operands[2].addr.base_regno;
          int32_t imm = inst.operands[2].addr.offset.imm;
 
-         gdb_assert (inst.operands[0].type == AARCH64_OPND_Rt);
-         gdb_assert (inst.operands[1].type == AARCH64_OPND_Rt2);
+         gdb_assert (inst.operands[0].type == AARCH64_OPND_Rt
+                     || inst.operands[0].type == AARCH64_OPND_Ft);
+         gdb_assert (inst.operands[1].type == AARCH64_OPND_Rt2
+                     || inst.operands[1].type == AARCH64_OPND_Ft2);
          gdb_assert (inst.operands[2].type == AARCH64_OPND_ADDR_SIMM7);
          gdb_assert (!inst.operands[2].addr.offset.is_reg);
 
@@ -347,6 +352,17 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
                                         pv_add_constant (regs[rn], imm + 8)))
            break;
 
+         rt1 = inst.operands[0].reg.regno;
+         rt2 = inst.operands[1].reg.regno;
+         if (inst.operands[0].type == AARCH64_OPND_Ft)
+           {
+             /* Only bottom 64-bit of each V register (D register) need
+                to be preserved.  */
+             gdb_assert (inst.operands[0].qualifier == AARCH64_OPND_QLF_S_D);
+             rt1 += AARCH64_X_REGISTER_COUNT;
+             rt2 += AARCH64_X_REGISTER_COUNT;
+           }
+
          pv_area_store (stack, pv_add_constant (regs[rn], imm), 8,
                         regs[rt1]);
          pv_area_store (stack, pv_add_constant (regs[rn], imm + 8), 8,
@@ -365,7 +381,7 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
        {
          if (aarch64_debug)
            {
-             debug_printf ("aarch64: prologue analysis gave up addr=0x%s"
+             debug_printf ("aarch64: prologue analysis gave up addr=%s"
                            " opcode=0x%x\n",
                            core_addr_to_string_nz (start), insn);
            }
@@ -406,6 +422,16 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
        cache->saved_regs[i].addr = offset;
     }
 
+  for (i = 0; i < AARCH64_D_REGISTER_COUNT; i++)
+    {
+      int regnum = gdbarch_num_regs (gdbarch);
+      CORE_ADDR offset;
+
+      if (pv_area_find_reg (stack, gdbarch, i + AARCH64_X_REGISTER_COUNT,
+                           &offset))
+       cache->saved_regs[i + regnum + AARCH64_D0_REGNUM].addr = offset;
+    }
+
   do_cleanups (back_to);
   return start;
 }
@@ -415,10 +441,7 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
 static CORE_ADDR
 aarch64_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
-  unsigned long inst;
-  CORE_ADDR skip_pc;
   CORE_ADDR func_addr, limit_pc;
-  struct symtab_and_line sal;
 
   /* See if we can determine the end of the prologue via the symbol
      table.  If so, then return either PC, or the PC after the
@@ -429,7 +452,7 @@ aarch64_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
        = skip_prologue_using_sal (gdbarch, func_addr);
 
       if (post_prologue_pc != 0)
-       return max (pc, post_prologue_pc);
+       return std::max (pc, post_prologue_pc);
     }
 
   /* Can't determine prologue from the symbol table, need to examine
@@ -482,15 +505,12 @@ aarch64_scan_prologue (struct frame_info *this_frame,
          prologue_end = sal.end;
        }
 
-      prologue_end = min (prologue_end, prev_pc);
+      prologue_end = std::min (prologue_end, prev_pc);
       aarch64_analyze_prologue (gdbarch, prologue_start, prologue_end, cache);
     }
   else
     {
       CORE_ADDR frame_loc;
-      LONGEST saved_fp;
-      LONGEST saved_lr;
-      enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
 
       frame_loc = get_frame_register_unsigned (this_frame, AARCH64_FP_REGNUM);
       if (frame_loc == 0)
@@ -612,7 +632,6 @@ static struct value *
 aarch64_prologue_prev_register (struct frame_info *this_frame,
                                void **this_cache, int prev_regnum)
 {
-  struct gdbarch *gdbarch = get_frame_arch (this_frame);
   struct aarch64_prologue_cache *cache
     = aarch64_make_prologue_cache (this_frame, this_cache);
 
@@ -816,7 +835,6 @@ static struct value *
 aarch64_dwarf2_prev_register (struct frame_info *this_frame,
                              void **this_cache, int regnum)
 {
-  struct gdbarch *gdbarch = get_frame_arch (this_frame);
   CORE_ADDR lr;
 
   switch (regnum)
@@ -855,7 +873,8 @@ aarch64_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
 
 typedef struct
 {
-  /* Value to pass on stack.  */
+  /* Value to pass on stack.  It can be NULL if this item is for stack
+     padding.  */
   const gdb_byte *data;
 
   /* Size in bytes of value to pass on stack.  */
@@ -921,11 +940,12 @@ aarch64_type_align (struct type *t)
     }
 }
 
-/* Return 1 if *TY is a homogeneous floating-point aggregate as
-   defined in the AAPCS64 ABI document; otherwise return 0.  */
+/* Return 1 if *TY is a homogeneous floating-point aggregate or
+   homogeneous short-vector aggregate as defined in the AAPCS64 ABI
+   document; otherwise return 0.  */
 
 static int
-is_hfa (struct type *ty)
+is_hfa_or_hva (struct type *ty)
 {
   switch (TYPE_CODE (ty))
     {
@@ -936,7 +956,10 @@ is_hfa (struct type *ty)
        if (TYPE_VECTOR (ty))
          return 0;
 
-       if (TYPE_CODE (target_ty) == TYPE_CODE_FLT && TYPE_LENGTH (ty) <= 4)
+       if (TYPE_LENGTH (ty) <= 4 /* HFA or HVA has at most 4 members.  */
+           && (TYPE_CODE (target_ty) == TYPE_CODE_FLT /* HFA */
+               || (TYPE_CODE (target_ty) == TYPE_CODE_ARRAY /* HVA */
+                   && TYPE_VECTOR (target_ty))))
          return 1;
        break;
       }
@@ -944,12 +967,15 @@ is_hfa (struct type *ty)
     case TYPE_CODE_UNION:
     case TYPE_CODE_STRUCT:
       {
+       /* HFA or HVA has at most four members.  */
        if (TYPE_NFIELDS (ty) > 0 && TYPE_NFIELDS (ty) <= 4)
          {
            struct type *member0_type;
 
            member0_type = check_typedef (TYPE_FIELD_TYPE (ty, 0));
-           if (TYPE_CODE (member0_type) == TYPE_CODE_FLT)
+           if (TYPE_CODE (member0_type) == TYPE_CODE_FLT
+               || (TYPE_CODE (member0_type) == TYPE_CODE_ARRAY
+                   && TYPE_VECTOR (member0_type)))
              {
                int i;
 
@@ -1053,7 +1079,6 @@ pass_in_v (struct gdbarch *gdbarch,
 {
   if (info->nsrn < 8)
     {
-      enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
       int regnum = AARCH64_V0_REGNUM + info->nsrn;
       gdb_byte reg[V_REGISTER_SIZE];
 
@@ -1117,7 +1142,7 @@ pass_on_stack (struct aarch64_call_info *info, struct type *type,
       int pad = align - (info->nsaa & (align - 1));
 
       item.len = pad;
-      item.data = buf;
+      item.data = NULL;
 
       VEC_safe_push (stack_item_t, info->si, &item);
       info->nsaa += pad;
@@ -1173,10 +1198,7 @@ aarch64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                         struct value **args, CORE_ADDR sp, int struct_return,
                         CORE_ADDR struct_addr)
 {
-  int nstack = 0;
   int argnum;
-  int x_argreg;
-  int v_argreg;
   struct aarch64_call_info info;
   struct type *func_type;
   struct type *return_type;
@@ -1304,7 +1326,7 @@ aarch64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
        case TYPE_CODE_STRUCT:
        case TYPE_CODE_ARRAY:
        case TYPE_CODE_UNION:
-         if (is_hfa (arg_type))
+         if (is_hfa_or_hva (arg_type))
            {
              int elements = TYPE_NFIELDS (arg_type);
 
@@ -1375,7 +1397,8 @@ aarch64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
       stack_item_t *si = VEC_last (stack_item_t, info.si);
 
       sp -= si->len;
-      write_memory (sp, si->data, si->len);
+      if (si->data != NULL)
+       write_memory (sp, si->data, si->len);
       VEC_pop (stack_item_t, info.si);
     }
 
@@ -1569,17 +1592,7 @@ aarch64_gdb_print_insn (bfd_vma memaddr, disassemble_info *info)
    1101.0100.0010.0000.0000.0000.0000.0000 = 0xd4200000.  */
 static const gdb_byte aarch64_default_breakpoint[] = {0x00, 0x00, 0x20, 0xd4};
 
-/* Implement the "breakpoint_from_pc" gdbarch method.  */
-
-static const gdb_byte *
-aarch64_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
-                           int *lenptr)
-{
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-
-  *lenptr = sizeof (aarch64_default_breakpoint);
-  return aarch64_default_breakpoint;
-}
+GDBARCH_BREAKPOINT_MANIPULATION (aarch64, aarch64_default_breakpoint)
 
 /* Extract from an array REGS containing the (raw) register state a
    function return value of type TYPE, and copy that, in virtual
@@ -1640,7 +1653,7 @@ aarch64_extract_return_value (struct type *type, struct regcache *regs,
       memcpy (valbuf, buf, len);
       valbuf += len;
     }
-  else if (is_hfa (type))
+  else if (is_hfa_or_hva (type))
     {
       int elements = TYPE_NFIELDS (type);
       struct type *member_type = check_typedef (TYPE_FIELD_TYPE (type, 0));
@@ -1654,7 +1667,7 @@ aarch64_extract_return_value (struct type *type, struct regcache *regs,
 
          if (aarch64_debug)
            {
-             debug_printf ("read HFA return value element %d from %s\n",
+             debug_printf ("read HFA or HVA return value element %d from %s\n",
                            i + 1,
                            gdbarch_register_name (gdbarch, regno));
            }
@@ -1700,19 +1713,12 @@ aarch64_extract_return_value (struct type *type, struct regcache *regs,
 static int
 aarch64_return_in_memory (struct gdbarch *gdbarch, struct type *type)
 {
-  int nRc;
-  enum type_code code;
-
   type = check_typedef (type);
 
-  /* In the AArch64 ABI, "integer" like aggregate types are returned
-     in registers.  For an aggregate type to be integer like, its size
-     must be less than or equal to 4 * X_REGISTER_SIZE.  */
-
-  if (is_hfa (type))
+  if (is_hfa_or_hva (type))
     {
-      /* PCS B.5 If the argument is a Named HFA, then the argument is
-         used unmodified.  */
+      /* v0-v7 are used to return values and one register is allocated
+        for one member.  However, HFA or HVA has at most four members.  */
       return 0;
     }
 
@@ -1778,7 +1784,7 @@ aarch64_store_return_value (struct type *type, struct regcache *regs,
            }
        }
     }
-  else if (is_hfa (type))
+  else if (is_hfa_or_hva (type))
     {
       int elements = TYPE_NFIELDS (type);
       struct type *member_type = check_typedef (TYPE_FIELD_TYPE (type, 0));
@@ -1792,7 +1798,7 @@ aarch64_store_return_value (struct type *type, struct regcache *regs,
 
          if (aarch64_debug)
            {
-             debug_printf ("write HFA return value element %d to %s\n",
+             debug_printf ("write HFA or HVA return value element %d to %s\n",
                            i + 1,
                            gdbarch_register_name (gdbarch, regno));
            }
@@ -1838,7 +1844,6 @@ aarch64_return_value (struct gdbarch *gdbarch, struct value *func_value,
                      struct type *valtype, struct regcache *regcache,
                      gdb_byte *readbuf, const gdb_byte *writebuf)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   if (TYPE_CODE (valtype) == TYPE_CODE_STRUCT
       || TYPE_CODE (valtype) == TYPE_CODE_UNION
@@ -2335,7 +2340,7 @@ aarch64_displaced_step_b (const int is_bl, const int32_t offset,
 {
   struct aarch64_displaced_step_data *dsd
     = (struct aarch64_displaced_step_data *) data;
-  int32_t new_offset = data->insn_addr - dsd->new_addr + offset;
+  int64_t new_offset = data->insn_addr - dsd->new_addr + offset;
 
   if (can_encode_int32 (new_offset, 28))
     {
@@ -2369,7 +2374,6 @@ aarch64_displaced_step_b_cond (const unsigned cond, const int32_t offset,
 {
   struct aarch64_displaced_step_data *dsd
     = (struct aarch64_displaced_step_data *) data;
-  int32_t new_offset = data->insn_addr - dsd->new_addr + offset;
 
   /* GDB has to fix up PC after displaced step this instruction
      differently according to the condition is true or false.  Instead
@@ -2408,7 +2412,6 @@ aarch64_displaced_step_cb (const int32_t offset, const int is_cbnz,
 {
   struct aarch64_displaced_step_data *dsd
     = (struct aarch64_displaced_step_data *) data;
-  int32_t new_offset = data->insn_addr - dsd->new_addr + offset;
 
   /* The offset is out of range for a compare and branch
      instruction.  We can use the following instructions instead:
@@ -2433,7 +2436,6 @@ aarch64_displaced_step_tb (const int32_t offset, int is_tbnz,
 {
   struct aarch64_displaced_step_data *dsd
     = (struct aarch64_displaced_step_data *) data;
-  int32_t new_offset = data->insn_addr - dsd->new_addr + offset;
 
   /* The offset is out of range for a test bit and branch
      instruction We can use the following instructions instead:
@@ -2657,7 +2659,6 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   struct tdesc_arch_data *tdesc_data = NULL;
   const struct target_desc *tdesc = info.target_desc;
   int i;
-  int have_fpa_registers = 1;
   int valid_p = 1;
   const struct tdesc_feature *feature;
   int num_regs = 0;
@@ -2753,7 +2754,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
 
   /* Breakpoint manipulation.  */
-  set_gdbarch_breakpoint_from_pc (gdbarch, aarch64_breakpoint_from_pc);
+  SET_GDBARCH_BREAKPOINT_MANIPULATION (aarch64);
   set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
   set_gdbarch_software_single_step (gdbarch, aarch64_software_single_step);
 
@@ -2998,11 +2999,10 @@ aarch64_record_data_proc_reg (insn_decode_record *aarch64_insn_r)
 static unsigned int
 aarch64_record_data_proc_imm (insn_decode_record *aarch64_insn_r)
 {
-  uint8_t reg_rd, insn_bit28, insn_bit23, insn_bits24_27, setflags;
+  uint8_t reg_rd, insn_bit23, insn_bits24_27, setflags;
   uint32_t record_buf[4];
 
   reg_rd = bits (aarch64_insn_r->aarch64_insn, 0, 4);
-  insn_bit28 = bit (aarch64_insn_r->aarch64_insn, 28);
   insn_bit23 = bit (aarch64_insn_r->aarch64_insn, 23);
   insn_bits24_27 = bits (aarch64_insn_r->aarch64_insn, 24, 27);
 
@@ -3187,15 +3187,17 @@ aarch64_record_asimd_load_store (insn_decode_record *aarch64_insn_r)
       else
         {
           for (sindex = 0; sindex < selem; sindex++)
-            if (bit (aarch64_insn_r->aarch64_insn, 22))
-              record_buf[reg_index++] = reg_rt + AARCH64_V0_REGNUM;
-            else
-              {
-                record_buf_mem[mem_index++] = esize / 8;
-                record_buf_mem[mem_index++] = address + addr_offset;
-              }
-            addr_offset = addr_offset + (esize / 8);
-            reg_rt = (reg_rt + 1) % 32;
+           {
+             if (bit (aarch64_insn_r->aarch64_insn, 22))
+               record_buf[reg_index++] = reg_rt + AARCH64_V0_REGNUM;
+             else
+               {
+                 record_buf_mem[mem_index++] = esize / 8;
+                 record_buf_mem[mem_index++] = address + addr_offset;
+               }
+             addr_offset = addr_offset + (esize / 8);
+             reg_rt = (reg_rt + 1) % 32;
+           }
         }
     }
   /* Load/store multiple structure.  */
@@ -3467,7 +3469,8 @@ aarch64_record_load_store (insn_decode_record *aarch64_insn_r)
 
       if (!ld_flag)
         {
-          uint64_t reg_rm_val;
+          ULONGEST reg_rm_val;
+
           regcache_raw_read_unsigned (aarch64_insn_r->regcache,
                      bits (aarch64_insn_r->aarch64_insn, 16, 20), &reg_rm_val);
           if (bit (aarch64_insn_r->aarch64_insn, 12))
@@ -3754,7 +3757,6 @@ aarch64_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
   uint32_t rec_no = 0;
   uint8_t insn_size = 4;
   uint32_t ret = 0;
-  ULONGEST t_bit = 0, insn_id = 0;
   gdb_byte buf[insn_size];
   insn_decode_record aarch64_record;
 
This page took 0.035493 seconds and 4 git commands to generate.