2008-07-12 Pedro Alves <pedro@codesourcery.com>
[deliverable/binutils-gdb.git] / gdb / spu-tdep.c
index 88720846b0b39e2c4cdfd2a862b118633f764588..aaa98797070cdb46126b9b159dd87a4d746923ac 100644 (file)
@@ -1,5 +1,5 @@
 /* SPU target-dependent code for GDB, the GNU debugger.
-   Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
 
    Contributed by Ulrich Weigand <uweigand@de.ibm.com>.
    Based on a port by Sid Manning <sid@us.ibm.com>.
@@ -8,7 +8,7 @@
 
    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 2 of the License, or
+   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,
@@ -17,9 +17,7 @@
    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, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "arch-utils.h"
 
 #include "spu-tdep.h"
 
+
+/* The tdep structure.  */
+struct gdbarch_tdep
+{
+  /* SPU-specific vector type.  */
+  struct type *spu_builtin_type_vec128;
+};
+
+
 /* SPU-specific vector type.  */
-struct type *spu_builtin_type_vec128;
+static struct type *
+spu_builtin_type_vec128 (struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (!tdep->spu_builtin_type_vec128)
+    {
+      struct type *t;
+
+      t = init_composite_type ("__spu_builtin_type_vec128", TYPE_CODE_UNION);
+      append_composite_type_field (t, "uint128", builtin_type_int128);
+      append_composite_type_field (t, "v2_int64",
+                                  init_vector_type (builtin_type_int64, 2));
+      append_composite_type_field (t, "v4_int32",
+                                  init_vector_type (builtin_type_int32, 4));
+      append_composite_type_field (t, "v8_int16",
+                                  init_vector_type (builtin_type_int16, 8));
+      append_composite_type_field (t, "v16_int8",
+                                  init_vector_type (builtin_type_int8, 16));
+      append_composite_type_field (t, "v2_double",
+                                  init_vector_type (builtin_type_double, 2));
+      append_composite_type_field (t, "v4_float",
+                                  init_vector_type (builtin_type_float, 4));
+
+      TYPE_FLAGS (t) |= TYPE_FLAG_VECTOR;
+      TYPE_NAME (t) = "spu_builtin_type_vec128";
+
+      tdep->spu_builtin_type_vec128 = t;
+    }
+
+  return tdep->spu_builtin_type_vec128;
+}
+
 
 /* The list of available "info spu " commands.  */
 static struct cmd_list_element *infospucmdlist = NULL;
@@ -55,7 +94,7 @@ static struct cmd_list_element *infospucmdlist = NULL;
 /* Registers.  */
 
 static const char *
-spu_register_name (int reg_nr)
+spu_register_name (struct gdbarch *gdbarch, int reg_nr)
 {
   static char *register_names[] = 
     {
@@ -90,7 +129,7 @@ static struct type *
 spu_register_type (struct gdbarch *gdbarch, int reg_nr)
 {
   if (reg_nr < SPU_NUM_GPRS)
-    return spu_builtin_type_vec128;
+    return spu_builtin_type_vec128 (gdbarch);
 
   switch (reg_nr)
     {
@@ -283,6 +322,35 @@ spu_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
   return default_register_reggroup_p (gdbarch, regnum, group);
 }
 
+/* Address conversion.  */
+
+static CORE_ADDR
+spu_pointer_to_address (struct type *type, const gdb_byte *buf)
+{
+  ULONGEST addr = extract_unsigned_integer (buf, TYPE_LENGTH (type));
+  ULONGEST lslr = SPU_LS_SIZE - 1; /* Hard-wired LS size.  */
+
+  if (target_has_registers && target_has_stack && target_has_memory)
+    lslr = get_frame_register_unsigned (get_selected_frame (NULL),
+                                       SPU_LSLR_REGNUM);
+
+  return addr & lslr;
+}
+
+static CORE_ADDR
+spu_integer_to_address (struct gdbarch *gdbarch,
+                       struct type *type, const gdb_byte *buf)
+{
+  ULONGEST addr = unpack_long (type, buf);
+  ULONGEST lslr = SPU_LS_SIZE - 1; /* Hard-wired LS size.  */
+
+  if (target_has_registers && target_has_stack && target_has_memory)
+    lslr = get_frame_register_unsigned (get_selected_frame (NULL),
+                                       SPU_LSLR_REGNUM);
+
+  return addr & lslr;
+}
+
 
 /* Decoding SPU instructions.  */
 
@@ -632,7 +700,7 @@ spu_analyze_prologue (CORE_ADDR start_pc, CORE_ADDR end_pc,
 
 /* Return the first instruction after the prologue starting at PC.  */
 static CORE_ADDR
-spu_skip_prologue (CORE_ADDR pc)
+spu_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
   struct spu_prologue_data data;
   return spu_analyze_prologue (pc, (CORE_ADDR)-1, &data);
@@ -640,7 +708,8 @@ spu_skip_prologue (CORE_ADDR pc)
 
 /* Return the frame pointer in use at address PC.  */
 static void
-spu_virtual_frame_pointer (CORE_ADDR pc, int *reg, LONGEST *offset)
+spu_virtual_frame_pointer (struct gdbarch *gdbarch, CORE_ADDR pc,
+                          int *reg, LONGEST *offset)
 {
   struct spu_prologue_data data;
   spu_analyze_prologue (pc, (CORE_ADDR)-1, &data);
@@ -766,7 +835,7 @@ struct spu_unwind_cache
 };
 
 static struct spu_unwind_cache *
-spu_frame_unwind_cache (struct frame_info *next_frame,
+spu_frame_unwind_cache (struct frame_info *this_frame,
                        void **this_prologue_cache)
 {
   struct spu_unwind_cache *info;
@@ -778,20 +847,20 @@ spu_frame_unwind_cache (struct frame_info *next_frame,
 
   info = FRAME_OBSTACK_ZALLOC (struct spu_unwind_cache);
   *this_prologue_cache = info;
-  info->saved_regs = trad_frame_alloc_saved_regs (next_frame);
+  info->saved_regs = trad_frame_alloc_saved_regs (this_frame);
   info->frame_base = 0;
   info->local_base = 0;
 
   /* Find the start of the current function, and analyze its prologue.  */
-  info->func = frame_func_unwind (next_frame, NORMAL_FRAME);
+  info->func = get_frame_func (this_frame);
   if (info->func == 0)
     {
       /* Fall back to using the current PC as frame ID.  */
-      info->func = frame_pc_unwind (next_frame);
+      info->func = get_frame_pc (this_frame);
       data.size = -1;
     }
   else
-    spu_analyze_prologue (info->func, frame_pc_unwind (next_frame), &data);
+    spu_analyze_prologue (info->func, get_frame_pc (this_frame), &data);
 
 
   /* If successful, use prologue analysis data.  */
@@ -801,7 +870,7 @@ spu_frame_unwind_cache (struct frame_info *next_frame,
       int i;
 
       /* Determine CFA via unwound CFA_REG plus CFA_OFFSET.  */
-      frame_unwind_register (next_frame, data.cfa_reg, buf);
+      get_frame_register (this_frame, data.cfa_reg, buf);
       cfa = extract_unsigned_integer (buf, 4) + data.cfa_offset;
 
       /* Call-saved register slots.  */
@@ -822,7 +891,7 @@ spu_frame_unwind_cache (struct frame_info *next_frame,
       CORE_ADDR reg, backchain;
 
       /* Get the backchain.  */
-      reg = frame_unwind_register_unsigned (next_frame, SPU_SP_REGNUM);
+      reg = get_frame_register_unsigned (this_frame, SPU_SP_REGNUM);
       backchain = read_memory_unsigned_integer (reg, 4);
 
       /* A zero backchain terminates the frame chain.  Also, sanity
@@ -847,7 +916,7 @@ spu_frame_unwind_cache (struct frame_info *next_frame,
   if (trad_frame_addr_p (info->saved_regs, SPU_LR_REGNUM))
     target_read_memory (info->saved_regs[SPU_LR_REGNUM].addr, buf, 16);
   else
-    frame_unwind_register (next_frame, SPU_LR_REGNUM, buf);
+    get_frame_register (this_frame, SPU_LR_REGNUM, buf);
 
   /* Normally, the return address is contained in the slot 0 of the
      link register, and slots 1-3 are zero.  For an overlay return,
@@ -866,11 +935,11 @@ spu_frame_unwind_cache (struct frame_info *next_frame,
 }
 
 static void
-spu_frame_this_id (struct frame_info *next_frame,
+spu_frame_this_id (struct frame_info *this_frame,
                   void **this_prologue_cache, struct frame_id *this_id)
 {
   struct spu_unwind_cache *info =
-    spu_frame_unwind_cache (next_frame, this_prologue_cache);
+    spu_frame_unwind_cache (this_frame, this_prologue_cache);
 
   if (info->frame_base == 0)
     return;
@@ -878,41 +947,33 @@ spu_frame_this_id (struct frame_info *next_frame,
   *this_id = frame_id_build (info->frame_base, info->func);
 }
 
-static void
-spu_frame_prev_register (struct frame_info *next_frame,
-                        void **this_prologue_cache,
-                        int regnum, int *optimizedp,
-                        enum lval_type *lvalp, CORE_ADDR * addrp,
-                        int *realnump, gdb_byte *bufferp)
+static struct value *
+spu_frame_prev_register (struct frame_info *this_frame,
+                        void **this_prologue_cache, int regnum)
 {
   struct spu_unwind_cache *info
-    = spu_frame_unwind_cache (next_frame, this_prologue_cache);
+    = spu_frame_unwind_cache (this_frame, this_prologue_cache);
 
   /* Special-case the stack pointer.  */
   if (regnum == SPU_RAW_SP_REGNUM)
     regnum = SPU_SP_REGNUM;
 
-  trad_frame_get_prev_register (next_frame, info->saved_regs, regnum,
-                               optimizedp, lvalp, addrp, realnump, bufferp);
+  return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
 }
 
 static const struct frame_unwind spu_frame_unwind = {
   NORMAL_FRAME,
   spu_frame_this_id,
-  spu_frame_prev_register
+  spu_frame_prev_register,
+  NULL,
+  default_frame_sniffer
 };
 
-const struct frame_unwind *
-spu_frame_sniffer (struct frame_info *next_frame)
-{
-  return &spu_frame_unwind;
-}
-
 static CORE_ADDR
-spu_frame_base_address (struct frame_info *next_frame, void **this_cache)
+spu_frame_base_address (struct frame_info *this_frame, void **this_cache)
 {
   struct spu_unwind_cache *info
-    = spu_frame_unwind_cache (next_frame, this_cache);
+    = spu_frame_unwind_cache (this_frame, this_cache);
   return info->local_base;
 }
 
@@ -938,19 +999,22 @@ spu_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
 }
 
 static CORE_ADDR
-spu_read_pc (ptid_t ptid)
+spu_read_pc (struct regcache *regcache)
 {
-  CORE_ADDR pc = read_register_pid (SPU_PC_REGNUM, ptid);
+  ULONGEST pc;
+  regcache_cooked_read_unsigned (regcache, SPU_PC_REGNUM, &pc);
   /* Mask off interrupt enable bit.  */
   return pc & -4;
 }
 
 static void
-spu_write_pc (CORE_ADDR pc, ptid_t ptid)
+spu_write_pc (struct regcache *regcache, CORE_ADDR pc)
 {
   /* Keep interrupt enabled state unchanged.  */
-  CORE_ADDR old_pc = read_register_pid (SPU_PC_REGNUM, ptid);
-  write_register_pid (SPU_PC_REGNUM, (pc & -4) | (old_pc & 3), ptid);
+  ULONGEST old_pc;
+  regcache_cooked_read_unsigned (regcache, SPU_PC_REGNUM, &old_pc);
+  regcache_cooked_write_unsigned (regcache, SPU_PC_REGNUM,
+                                 (pc & -4) | (old_pc & 3));
 }
 
 
@@ -1123,17 +1187,19 @@ spu_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 }
 
 static struct frame_id
-spu_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
+spu_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
 {
-  return frame_id_build (spu_unwind_sp (gdbarch, next_frame),
-                        spu_unwind_pc (gdbarch, next_frame));
+  CORE_ADDR pc = get_frame_register_unsigned (this_frame, SPU_PC_REGNUM);
+  CORE_ADDR sp = get_frame_register_unsigned (this_frame, SPU_SP_REGNUM);
+  return frame_id_build (sp, pc & -4);
 }
 
 /* Function return value access.  */
 
 static enum return_value_convention
-spu_return_value (struct gdbarch *gdbarch, struct type *type,
-                  struct regcache *regcache, gdb_byte *out, const gdb_byte *in)
+spu_return_value (struct gdbarch *gdbarch, struct type *func_type,
+                 struct type *type, struct regcache *regcache,
+                 gdb_byte *out, const gdb_byte *in)
 {
   enum return_value_convention rvc;
 
@@ -1176,7 +1242,7 @@ spu_return_value (struct gdbarch *gdbarch, struct type *type,
 /* Breakpoints.  */
 
 static const gdb_byte *
-spu_breakpoint_from_pc (CORE_ADDR * pcptr, int *lenptr)
+spu_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR * pcptr, int *lenptr)
 {
   static const gdb_byte breakpoint[] = { 0x00, 0x00, 0x3f, 0xff };
 
@@ -1188,16 +1254,14 @@ spu_breakpoint_from_pc (CORE_ADDR * pcptr, int *lenptr)
 /* Software single-stepping support.  */
 
 int
-spu_software_single_step (struct regcache *regcache)
+spu_software_single_step (struct frame_info *frame)
 {
   CORE_ADDR pc, next_pc;
   unsigned int insn;
   int offset, reg;
   gdb_byte buf[4];
 
-  regcache_cooked_read (regcache, SPU_PC_REGNUM, buf);
-  /* Mask off interrupt enable bit.  */
-  pc = extract_unsigned_integer (buf, 4) & -4;
+  pc = get_frame_pc (frame);
 
   if (target_read_memory (pc, buf, 4))
     return 1;
@@ -1221,7 +1285,7 @@ spu_software_single_step (struct regcache *regcache)
        target += pc;
       else if (reg != -1)
        {
-         regcache_cooked_read_part (regcache, reg, 0, 4, buf);
+         get_frame_register_bytes (frame, reg, 0, 4, buf);
          target += extract_unsigned_integer (buf, 4) & -4;
        }
 
@@ -1435,16 +1499,18 @@ info_spu_event_command (char *args, int from_tty)
 
   xsnprintf (annex, sizeof annex, "%d/event_status", id);
   len = target_read (&current_target, TARGET_OBJECT_SPU, annex,
-                    buf, 0, sizeof buf);
+                    buf, 0, (sizeof (buf) - 1));
   if (len <= 0)
     error (_("Could not read event_status."));
+  buf[len] = '\0';
   event_status = strtoulst (buf, NULL, 16);
  
   xsnprintf (annex, sizeof annex, "%d/event_mask", id);
   len = target_read (&current_target, TARGET_OBJECT_SPU, annex,
-                    buf, 0, sizeof buf);
+                    buf, 0, (sizeof (buf) - 1));
   if (len <= 0)
     error (_("Could not read event_mask."));
+  buf[len] = '\0';
   event_mask = strtoulst (buf, NULL, 16);
  
   chain = make_cleanup_ui_out_tuple_begin_end (uiout, "SPUInfoEvent");
@@ -1495,9 +1561,10 @@ info_spu_signal_command (char *args, int from_tty)
     
   xsnprintf (annex, sizeof annex, "%d/signal1_type", id);
   len = target_read (&current_target, TARGET_OBJECT_SPU, annex,
-                    buf, 0, sizeof buf);
+                    buf, 0, (sizeof (buf) - 1));
   if (len <= 0)
     error (_("Could not read signal1_type."));
+  buf[len] = '\0';
   signal1_type = strtoulst (buf, NULL, 16);
 
   xsnprintf (annex, sizeof annex, "%d/signal2", id);
@@ -1512,9 +1579,10 @@ info_spu_signal_command (char *args, int from_tty)
     
   xsnprintf (annex, sizeof annex, "%d/signal2_type", id);
   len = target_read (&current_target, TARGET_OBJECT_SPU, annex,
-                    buf, 0, sizeof buf);
+                    buf, 0, (sizeof (buf) - 1));
   if (len <= 0)
     error (_("Could not read signal2_type."));
+  buf[len] = '\0';
   signal2_type = strtoulst (buf, NULL, 16);
 
   chain = make_cleanup_ui_out_tuple_begin_end (uiout, "SPUInfoSignal");
@@ -1536,9 +1604,9 @@ info_spu_signal_command (char *args, int from_tty)
        printf_filtered (_("Signal 1 not pending "));
 
       if (signal1_type)
-       printf_filtered (_("(Type Overwrite)\n"));
-      else
        printf_filtered (_("(Type Or)\n"));
+      else
+       printf_filtered (_("(Type Overwrite)\n"));
 
       if (signal2_pending)
        printf_filtered (_("Signal 2 control word 0x%s "), phex (signal2, 4));
@@ -1546,9 +1614,9 @@ info_spu_signal_command (char *args, int from_tty)
        printf_filtered (_("Signal 2 not pending "));
 
       if (signal2_type)
-       printf_filtered (_("(Type Overwrite)\n"));
-      else
        printf_filtered (_("(Type Or)\n"));
+      else
+       printf_filtered (_("(Type Overwrite)\n"));
     }
 
   do_cleanups (chain);
@@ -1919,6 +1987,7 @@ static struct gdbarch *
 spu_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 {
   struct gdbarch *gdbarch;
+  struct gdbarch_tdep *tdep;
 
   /* Find a candidate among the list of pre-declared architectures.  */
   arches = gdbarch_list_lookup_by_info (arches, &info);
@@ -1930,7 +1999,8 @@ spu_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     return NULL;
 
   /* Yes, create a new architecture.  */
-  gdbarch = gdbarch_alloc (&info, NULL);
+  tdep = XCALLOC (1, struct gdbarch_tdep);
+  gdbarch = gdbarch_alloc (&info, tdep);
 
   /* Disassembler.  */
   set_gdbarch_print_insn (gdbarch, print_insn_spu);
@@ -1964,16 +2034,20 @@ spu_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_double_format (gdbarch, floatformats_ieee_double);
   set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double);
 
+  /* Address conversion.  */
+  set_gdbarch_pointer_to_address (gdbarch, spu_pointer_to_address);
+  set_gdbarch_integer_to_address (gdbarch, spu_integer_to_address);
+
   /* Inferior function calls.  */
   set_gdbarch_call_dummy_location (gdbarch, ON_STACK);
   set_gdbarch_frame_align (gdbarch, spu_frame_align);
   set_gdbarch_push_dummy_call (gdbarch, spu_push_dummy_call);
-  set_gdbarch_unwind_dummy_id (gdbarch, spu_unwind_dummy_id);
+  set_gdbarch_dummy_id (gdbarch, spu_dummy_id);
   set_gdbarch_return_value (gdbarch, spu_return_value);
 
   /* Frame handling.  */
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
-  frame_unwind_append_sniffer (gdbarch, spu_frame_sniffer);
+  frame_unwind_append_unwinder (gdbarch, &spu_frame_unwind);
   frame_base_set_default (gdbarch, &spu_frame_base);
   set_gdbarch_unwind_pc (gdbarch, spu_unwind_pc);
   set_gdbarch_unwind_sp (gdbarch, spu_unwind_sp);
@@ -1994,34 +2068,11 @@ spu_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   return gdbarch;
 }
 
-/* Implement a SPU-specific vector type as replacement
-   for __gdb_builtin_type_vec128.  */
-static void
-spu_init_vector_type (void)
-{
-  struct type *type;
-
-  type = init_composite_type ("__spu_builtin_type_vec128", TYPE_CODE_UNION);
-  append_composite_type_field (type, "uint128", builtin_type_int128);
-  append_composite_type_field (type, "v2_int64", builtin_type_v2_int64);
-  append_composite_type_field (type, "v4_int32", builtin_type_v4_int32);
-  append_composite_type_field (type, "v8_int16", builtin_type_v8_int16);
-  append_composite_type_field (type, "v16_int8", builtin_type_v16_int8);
-  append_composite_type_field (type, "v2_double", builtin_type_v2_double);
-  append_composite_type_field (type, "v4_float", builtin_type_v4_float);
-
-  TYPE_FLAGS (type) |= TYPE_FLAG_VECTOR;
-  TYPE_NAME (type) = "spu_builtin_type_vec128";
-  spu_builtin_type_vec128 = type;
-}
-
 void
 _initialize_spu_tdep (void)
 {
   register_gdbarch_init (bfd_arch_spu, spu_gdbarch_init);
 
-  spu_init_vector_type ();
-
   /* Add ourselves to objfile event chain.  */
   observer_attach_new_objfile (spu_overlay_new_objfile);
   spu_overlay_data = register_objfile_data ();
This page took 0.031071 seconds and 4 git commands to generate.