Skip gdb.mi/list-thread-groups-available.exp if no xml support
[deliverable/binutils-gdb.git] / gdb / xtensa-tdep.c
index 3a3badab1970642a91a92f0cc5680aa4b6c0fc07..0b0ec2e41621135108d656051161d85d4d68c173 100644 (file)
@@ -1,6 +1,6 @@
 /* Target-dependent code for the Xtensa port of GDB, the GNU debugger.
 
-   Copyright (C) 2003-2016 Free Software Foundation, Inc.
+   Copyright (C) 2003-2017 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -29,7 +29,6 @@
 #include "dis-asm.h"
 #include "inferior.h"
 #include "osabi.h"
-#include "floatformat.h"
 #include "regcache.h"
 #include "reggroups.h"
 #include "regset.h"
@@ -52,6 +51,7 @@
 #include "xtensa-isa.h"
 #include "xtensa-tdep.h"
 #include "xtensa-config.h"
+#include <algorithm>
 
 
 static unsigned int xtensa_debug_level = 0;
@@ -119,6 +119,9 @@ static unsigned int xtensa_debug_level = 0;
 #define PS_WOE                 (1<<18)
 #define PS_EXC                 (1<<4)
 
+/* Big enough to hold the size of the largest register in bytes.  */
+#define XTENSA_MAX_REGISTER_SIZE       64
+
 static int
 windowing_enabled (struct gdbarch *gdbarch, unsigned int ps)
 {
@@ -227,7 +230,7 @@ extract_call_winsize (struct gdbarch *gdbarch, CORE_ADDR pc)
 
 /* Find register by name.  */
 static int
-xtensa_find_register_by_name (struct gdbarch *gdbarch, char *name)
+xtensa_find_register_by_name (struct gdbarch *gdbarch, const char *name)
 {
   int i;
 
@@ -369,7 +372,7 @@ static void
 xtensa_register_write_masked (struct regcache *regcache,
                              xtensa_register_t *reg, const gdb_byte *buffer)
 {
-  unsigned int value[(MAX_REGISTER_SIZE + 3) / 4];
+  unsigned int value[(XTENSA_MAX_REGISTER_SIZE + 3) / 4];
   const xtensa_mask_t *mask = reg->mask;
 
   int shift = 0;               /* Shift for next mask (mod 32).  */
@@ -385,7 +388,7 @@ xtensa_register_write_masked (struct regcache *regcache,
   DEBUGTRACE ("xtensa_register_write_masked ()\n");
 
   /* Copy the masked register to host byte-order.  */
-  if (gdbarch_byte_order (get_regcache_arch (regcache)) == BFD_ENDIAN_BIG)
+  if (gdbarch_byte_order (regcache->arch ()) == BFD_ENDIAN_BIG)
     for (i = 0; i < bytesize; i++)
       {
        mem >>= 8;
@@ -453,7 +456,7 @@ static enum register_status
 xtensa_register_read_masked (struct regcache *regcache,
                             xtensa_register_t *reg, gdb_byte *buffer)
 {
-  unsigned int value[(MAX_REGISTER_SIZE + 3) / 4];
+  unsigned int value[(XTENSA_MAX_REGISTER_SIZE + 3) / 4];
   const xtensa_mask_t *mask = reg->mask;
 
   int shift = 0;
@@ -519,7 +522,7 @@ xtensa_register_read_masked (struct regcache *regcache,
   ptr = value;
   mem = *ptr;
 
-  if (gdbarch_byte_order (get_regcache_arch (regcache)) == BFD_ENDIAN_BIG)
+  if (gdbarch_byte_order (regcache->arch ()) == BFD_ENDIAN_BIG)
     for (i = 0; i < bytesize; i++)
       {
        if ((i & 3) == 0)
@@ -558,16 +561,15 @@ xtensa_pseudo_register_read (struct gdbarch *gdbarch,
       && (regnum >= gdbarch_tdep (gdbarch)->a0_base)
       && (regnum <= gdbarch_tdep (gdbarch)->a0_base + 15))
     {
-      gdb_byte *buf = (gdb_byte *) alloca (MAX_REGISTER_SIZE);
+      ULONGEST value;
       enum register_status status;
 
-      status = regcache_raw_read (regcache,
-                                 gdbarch_tdep (gdbarch)->wb_regnum,
-                                 buf);
+      status = regcache_raw_read_unsigned (regcache,
+                                          gdbarch_tdep (gdbarch)->wb_regnum,
+                                          &value);
       if (status != REG_VALID)
        return status;
-      regnum = arreg_number (gdbarch, regnum,
-                            extract_unsigned_integer (buf, 4, byte_order));
+      regnum = arreg_number (gdbarch, regnum, value);
     }
 
   /* We can always read non-pseudo registers.  */
@@ -577,7 +579,8 @@ xtensa_pseudo_register_read (struct gdbarch *gdbarch,
   /* We have to find out how to deal with priveleged registers.
      Let's treat them as pseudo-registers, but we cannot read/write them.  */
      
-  else if (regnum < gdbarch_tdep (gdbarch)->a0_base)
+  else if (gdbarch_tdep (gdbarch)->call_abi == CallAbiCall0Only
+          || regnum < gdbarch_tdep (gdbarch)->a0_base)
     {
       buffer[0] = (gdb_byte)0;
       buffer[1] = (gdb_byte)0;
@@ -654,12 +657,10 @@ xtensa_pseudo_register_write (struct gdbarch *gdbarch,
       && (regnum >= gdbarch_tdep (gdbarch)->a0_base)
       && (regnum <= gdbarch_tdep (gdbarch)->a0_base + 15))
     {
-      gdb_byte *buf = (gdb_byte *) alloca (MAX_REGISTER_SIZE);
-
-      regcache_raw_read (regcache,
-                        gdbarch_tdep (gdbarch)->wb_regnum, buf);
-      regnum = arreg_number (gdbarch, regnum,
-                            extract_unsigned_integer (buf, 4, byte_order));
+      ULONGEST value;
+      regcache_raw_read_unsigned (regcache,
+                                 gdbarch_tdep (gdbarch)->wb_regnum, &value);
+      regnum = arreg_number (gdbarch, regnum, value);
     }
 
   /* We can always write 'core' registers.
@@ -738,17 +739,13 @@ static void
 xtensa_init_reggroups (void)
 {
   int i;
-  char cpname[] = "cp0";
 
   xtensa_ar_reggroup = reggroup_new ("ar", USER_REGGROUP);
   xtensa_user_reggroup = reggroup_new ("user", USER_REGGROUP);
   xtensa_vectra_reggroup = reggroup_new ("vectra", USER_REGGROUP);
 
   for (i = 0; i < XTENSA_MAX_COPROCESSOR; i++)
-    {
-      cpname[2] = '0' + i;
-      xtensa_cp[i] = reggroup_new (cpname, USER_REGGROUP);
-    }
+    xtensa_cp[i] = reggroup_new (xstrprintf ("cp%d", i), USER_REGGROUP);
 }
 
 static void
@@ -850,7 +847,7 @@ xtensa_supply_gregset (const struct regset *regset,
                       size_t len)
 {
   const xtensa_elf_gregset_t *regs = (const xtensa_elf_gregset_t *) gregs;
-  struct gdbarch *gdbarch = get_regcache_arch (rc);
+  struct gdbarch *gdbarch = rc->arch ();
   int i;
 
   DEBUGTRACE ("xtensa_supply_gregset (..., regnum==%d, ...)\n", regnum);
@@ -941,7 +938,6 @@ typedef struct xtensa_windowed_frame_cache
 
 #define C0_MAXOPDS  3  /* Maximum number of operands for prologue
                           analysis.  */
-#define C0_NREGS   16  /* Number of A-registers to track.  */
 #define C0_CLESV   12  /* Callee-saved registers are here and up.  */
 #define C0_SP      1   /* Register used as SP.  */
 #define C0_FP     15   /* Register used as FP.  */
@@ -1150,8 +1146,6 @@ xtensa_scan_prologue (struct gdbarch *gdbarch, CORE_ADDR current_pc)
   if (start_addr == 0)
     return fp_regnum;
 
-  if (!xtensa_default_isa)
-    xtensa_default_isa = xtensa_isa_init (0, 0);
   isa = xtensa_default_isa;
   gdb_assert (XTENSA_ISA_BSZ >= xtensa_isa_maxlength (isa));
   ins = xtensa_insnbuf_alloc (isa);
@@ -1563,7 +1557,7 @@ xtensa_extract_return_value (struct type *type,
                             struct regcache *regcache,
                             void *dst)
 {
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch *gdbarch = regcache->arch ();
   bfd_byte *valbuf = (bfd_byte *) dst;
   int len = TYPE_LENGTH (type);
   ULONGEST pc, wb;
@@ -1619,7 +1613,7 @@ xtensa_store_return_value (struct type *type,
                           struct regcache *regcache,
                           const void *dst)
 {
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch *gdbarch = regcache->arch ();
   const bfd_byte *valbuf = (const bfd_byte *) dst;
   unsigned int areg;
   ULONGEST pc, wb;
@@ -1958,6 +1952,16 @@ xtensa_push_dummy_call (struct gdbarch *gdbarch,
   return sp + SP_ALIGNMENT;
 }
 
+/* Implement the breakpoint_kind_from_pc gdbarch method.  */
+
+static int
+xtensa_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
+{
+  if (gdbarch_tdep (gdbarch)->isa_use_density_instructions)
+    return 2;
+  else
+    return 4;
+}
 
 /* Return a breakpoint for the current location of PC.  We always use
    the density version if we have density instructions (regardless of the
@@ -1968,42 +1972,33 @@ xtensa_push_dummy_call (struct gdbarch *gdbarch,
 #define DENSITY_BIG_BREAKPOINT { 0xd2, 0x0f }
 #define DENSITY_LITTLE_BREAKPOINT { 0x2d, 0xf0 }
 
-static const unsigned char *
-xtensa_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
-                          int *lenptr)
-{
-  static unsigned char big_breakpoint[] = BIG_BREAKPOINT;
-  static unsigned char little_breakpoint[] = LITTLE_BREAKPOINT;
-  static unsigned char density_big_breakpoint[] = DENSITY_BIG_BREAKPOINT;
-  static unsigned char density_little_breakpoint[] = DENSITY_LITTLE_BREAKPOINT;
+/* Implement the sw_breakpoint_from_kind gdbarch method.  */
 
-  DEBUGTRACE ("xtensa_breakpoint_from_pc (pc = 0x%08x)\n", (int) *pcptr);
+static const gdb_byte *
+xtensa_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
+{
+  *size = kind;
 
-  if (gdbarch_tdep (gdbarch)->isa_use_density_instructions)
+  if (kind == 4)
     {
+      static unsigned char big_breakpoint[] = BIG_BREAKPOINT;
+      static unsigned char little_breakpoint[] = LITTLE_BREAKPOINT;
+
       if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
-       {
-         *lenptr = sizeof (density_big_breakpoint);
-         return density_big_breakpoint;
-       }
+       return big_breakpoint;
       else
-       {
-         *lenptr = sizeof (density_little_breakpoint);
-         return density_little_breakpoint;
-       }
+       return little_breakpoint;
     }
   else
     {
+      static unsigned char density_big_breakpoint[] = DENSITY_BIG_BREAKPOINT;
+      static unsigned char density_little_breakpoint[]
+       = DENSITY_LITTLE_BREAKPOINT;
+
       if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
-       {
-         *lenptr = sizeof (big_breakpoint);
-         return big_breakpoint;
-       }
+       return density_big_breakpoint;
       else
-       {
-         *lenptr = sizeof (little_breakpoint);
-         return little_breakpoint;
-       }
+       return density_little_breakpoint;
     }
 }
 
@@ -2399,7 +2394,7 @@ call0_analyze_prologue (struct gdbarch *gdbarch,
      arg was not supplied to avoid probing beyond the end of valid memory.
      If memory is full of garbage that classifies as c0opc_uninteresting.
      If this fails (eg. if no symbols) pc ends up 0 as it was.
-     Intialize the Call0 frame and register tracking info.
+     Initialize the Call0 frame and register tracking info.
      Assume it's Call0 until an 'entry' instruction is encountered.
      Assume we may be in the prologue until we hit a flow control instr.  */
 
@@ -2417,16 +2412,14 @@ call0_analyze_prologue (struct gdbarch *gdbarch,
   if (pc == 0)
     {
       find_pc_partial_function (start, 0, NULL, &end_pc);
-      body_pc = min (end_pc, body_pc);
+      body_pc = std::min (end_pc, body_pc);
     }
   else
-    body_pc = min (pc, body_pc);
+    body_pc = std::min (pc, body_pc);
 
   cache->call0 = 1;
   rtmp = (xtensa_c0reg_t*) alloca(nregs * sizeof(xtensa_c0reg_t));
 
-  if (!xtensa_default_isa)
-    xtensa_default_isa = xtensa_isa_init (0, 0);
   isa = xtensa_default_isa;
   gdb_assert (XTENSA_ISA_BSZ >= xtensa_isa_maxlength (isa));
   ins = xtensa_insnbuf_alloc (isa);
@@ -2796,7 +2789,6 @@ execute_code (struct gdbarch *gdbarch, CORE_ADDR current_pc, CORE_ADDR wb)
   int ilen, islots, is;
   xtensa_opcode opc;
   int insn_num = 0;
-  int fail = 0;
   void (*func) (struct gdbarch *, int, int, int, CORE_ADDR);
 
   uint32_t at, as, offset;
@@ -3062,48 +3054,38 @@ xtensa_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
 static void
 xtensa_verify_config (struct gdbarch *gdbarch)
 {
-  struct ui_file *log;
-  struct cleanup *cleanups;
-  struct gdbarch_tdep *tdep;
-  long length;
-  char *buf;
-
-  tdep = gdbarch_tdep (gdbarch);
-  log = mem_fileopen ();
-  cleanups = make_cleanup_ui_file_delete (log);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  string_file log;
 
   /* Verify that we got a reasonable number of AREGS.  */
   if ((tdep->num_aregs & -tdep->num_aregs) != tdep->num_aregs)
-    fprintf_unfiltered (log, _("\
+    log.printf (_("\
 \n\tnum_aregs: Number of AR registers (%d) is not a power of two!"),
-                       tdep->num_aregs);
+               tdep->num_aregs);
 
   /* Verify that certain registers exist.  */
 
   if (tdep->pc_regnum == -1)
-    fprintf_unfiltered (log, _("\n\tpc_regnum: No PC register"));
+    log.printf (_("\n\tpc_regnum: No PC register"));
   if (tdep->isa_use_exceptions && tdep->ps_regnum == -1)
-    fprintf_unfiltered (log, _("\n\tps_regnum: No PS register"));
+    log.printf (_("\n\tps_regnum: No PS register"));
 
   if (tdep->isa_use_windowed_registers)
     {
       if (tdep->wb_regnum == -1)
-       fprintf_unfiltered (log, _("\n\twb_regnum: No WB register"));
+       log.printf (_("\n\twb_regnum: No WB register"));
       if (tdep->ws_regnum == -1)
-       fprintf_unfiltered (log, _("\n\tws_regnum: No WS register"));
+       log.printf (_("\n\tws_regnum: No WS register"));
       if (tdep->ar_base == -1)
-       fprintf_unfiltered (log, _("\n\tar_base: No AR registers"));
+       log.printf (_("\n\tar_base: No AR registers"));
     }
 
   if (tdep->a0_base == -1)
-    fprintf_unfiltered (log, _("\n\ta0_base: No Ax registers"));
+    log.printf (_("\n\ta0_base: No Ax registers"));
 
-  buf = ui_file_xstrdup (log, &length);
-  make_cleanup (xfree, buf);
-  if (length > 0)
+  if (!log.empty ())
     internal_error (__FILE__, __LINE__,
-                   _("the following are invalid: %s"), buf);
-  do_cleanups (cleanups);
+                   _("the following are invalid: %s"), log.c_str ());
 }
 
 
@@ -3120,6 +3102,8 @@ xtensa_derive_tdep (struct gdbarch_tdep *tdep)
 
 /* Special registers 0..255 (core).  */
 #define XTENSA_DBREGN_SREG(n)  (0x0200+(n))
+/* User registers 0..255.  */
+#define XTENSA_DBREGN_UREG(n)  (0x0300+(n))
 
   for (rmap = tdep->regmap, n = 0; rmap->target_number != -1; n++, rmap++)
     {
@@ -3151,6 +3135,8 @@ xtensa_derive_tdep (struct gdbarch_tdep *tdep)
        tdep->litbase_regnum = n;
       else if (rmap->target_number == XTENSA_DBREGN_SREG(230))
        tdep->ps_regnum = n;
+      else if (rmap->target_number == XTENSA_DBREGN_UREG(231))
+       tdep->threadptr_regnum = n;
 #if 0
       else if (rmap->target_number == XTENSA_DBREGN_SREG(226))
        tdep->interrupt_regnum = n;
@@ -3192,10 +3178,12 @@ xtensa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 {
   struct gdbarch_tdep *tdep;
   struct gdbarch *gdbarch;
-  struct xtensa_abi_handler *abi_handler;
 
   DEBUGTRACE ("gdbarch_init()\n");
 
+  if (!xtensa_default_isa)
+    xtensa_default_isa = xtensa_isa_init (0, 0);
+
   /* We have to set the byte order before we call gdbarch_alloc.  */
   info.byte_order = XCHAL_HAVE_BE ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE;
 
@@ -3207,6 +3195,9 @@ xtensa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   xtensa_verify_config (gdbarch);
   xtensa_session_once_reported = 0;
 
+  set_gdbarch_wchar_bit (gdbarch, 2 * TARGET_CHAR_BIT);
+  set_gdbarch_wchar_signed (gdbarch, 0);
+
   /* Pseudo-Register read/write.  */
   set_gdbarch_pseudo_register_read (gdbarch, xtensa_pseudo_register_read);
   set_gdbarch_pseudo_register_write (gdbarch, xtensa_pseudo_register_write);
@@ -3240,7 +3231,10 @@ xtensa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
 
   /* Set breakpoints.  */
-  set_gdbarch_breakpoint_from_pc (gdbarch, xtensa_breakpoint_from_pc);
+  set_gdbarch_breakpoint_kind_from_pc (gdbarch,
+                                      xtensa_breakpoint_kind_from_pc);
+  set_gdbarch_sw_breakpoint_from_kind (gdbarch,
+                                      xtensa_sw_breakpoint_from_kind);
 
   /* After breakpoint instruction or illegal instruction, pc still
      points at break instruction, so don't decrement.  */
@@ -3260,8 +3254,6 @@ xtensa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   frame_unwind_append_unwinder (gdbarch, &xtensa_unwind);
   dwarf2_append_unwinders (gdbarch);
 
-  set_gdbarch_print_insn (gdbarch, print_insn_xtensa);
-
   set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
 
   xtensa_add_reggroups (gdbarch);
@@ -3285,14 +3277,9 @@ xtensa_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
   error (_("xtensa_dump_tdep(): not implemented"));
 }
 
-/* Provide a prototype to silence -Wmissing-prototypes.  */
-extern initialize_file_ftype _initialize_xtensa_tdep;
-
 void
 _initialize_xtensa_tdep (void)
 {
-  struct cmd_list_element *c;
-
   gdbarch_register (bfd_arch_xtensa, xtensa_gdbarch_init, xtensa_dump_tdep);
   xtensa_init_reggroups ();
 
This page took 0.047419 seconds and 4 git commands to generate.