* defs.h (extract_signed_integer, extract_unsigned_integer,
[deliverable/binutils-gdb.git] / gdb / spu-tdep.c
index f749ecebb19e091b037662ecf2b2936a91ef8ce5..e237ebfaafb52e44488601e53ed4b7528ae80c7b 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, 2009 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 "regcache.h"
 #include "reggroups.h"
 #include "floatformat.h"
+#include "observer.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)
+    {
+      const struct builtin_type *bt = builtin_type (gdbarch);
+      struct type *t;
+
+      t = arch_composite_type (gdbarch,
+                              "__spu_builtin_type_vec128", TYPE_CODE_UNION);
+      append_composite_type_field (t, "uint128", bt->builtin_int128);
+      append_composite_type_field (t, "v2_int64",
+                                  init_vector_type (bt->builtin_int64, 2));
+      append_composite_type_field (t, "v4_int32",
+                                  init_vector_type (bt->builtin_int32, 4));
+      append_composite_type_field (t, "v8_int16",
+                                  init_vector_type (bt->builtin_int16, 8));
+      append_composite_type_field (t, "v16_int8",
+                                  init_vector_type (bt->builtin_int8, 16));
+      append_composite_type_field (t, "v2_double",
+                                  init_vector_type (bt->builtin_double, 2));
+      append_composite_type_field (t, "v4_float",
+                                  init_vector_type (bt->builtin_float, 4));
+
+      TYPE_VECTOR (t) = 1;
+      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;
 
 /* Registers.  */
 
 static const char *
-spu_register_name (int reg_nr)
+spu_register_name (struct gdbarch *gdbarch, int reg_nr)
 {
   static char *register_names[] = 
     {
@@ -71,7 +116,7 @@ spu_register_name (int reg_nr)
       "r104", "r105", "r106", "r107", "r108", "r109", "r110", "r111",
       "r112", "r113", "r114", "r115", "r116", "r117", "r118", "r119",
       "r120", "r121", "r122", "r123", "r124", "r125", "r126", "r127",
-      "id", "pc", "sp"
+      "id", "pc", "sp", "fpscr", "srr0", "lslr", "decr", "decr_status"
     };
 
   if (reg_nr < 0)
@@ -86,18 +131,33 @@ 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)
     {
     case SPU_ID_REGNUM:
-      return builtin_type_uint32;
+      return builtin_type (gdbarch)->builtin_uint32;
 
     case SPU_PC_REGNUM:
-      return builtin_type_void_func_ptr;
+      return builtin_type (gdbarch)->builtin_func_ptr;
 
     case SPU_SP_REGNUM:
-      return builtin_type_void_data_ptr;
+      return builtin_type (gdbarch)->builtin_data_ptr;
+
+    case SPU_FPSCR_REGNUM:
+      return builtin_type (gdbarch)->builtin_uint128;
+
+    case SPU_SRR0_REGNUM:
+      return builtin_type (gdbarch)->builtin_uint32;
+
+    case SPU_LSLR_REGNUM:
+      return builtin_type (gdbarch)->builtin_uint32;
+
+    case SPU_DECR_REGNUM:
+      return builtin_type (gdbarch)->builtin_uint32;
+
+    case SPU_DECR_STATUS_REGNUM:
+      return builtin_type (gdbarch)->builtin_uint32;
 
     default:
       internal_error (__FILE__, __LINE__, "invalid regnum");
@@ -106,11 +166,32 @@ spu_register_type (struct gdbarch *gdbarch, int reg_nr)
 
 /* Pseudo registers for preferred slots - stack pointer.  */
 
+static void
+spu_pseudo_register_read_spu (struct regcache *regcache, const char *regname,
+                             gdb_byte *buf)
+{
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  gdb_byte reg[32];
+  char annex[32];
+  ULONGEST id;
+
+  regcache_raw_read_unsigned (regcache, SPU_ID_REGNUM, &id);
+  xsnprintf (annex, sizeof annex, "%d/%s", (int) id, regname);
+  memset (reg, 0, sizeof reg);
+  target_read (&current_target, TARGET_OBJECT_SPU, annex,
+              reg, 0, sizeof reg);
+
+  store_unsigned_integer (buf, 4, byte_order, strtoulst (reg, NULL, 16));
+}
+
 static void
 spu_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
                           int regnum, gdb_byte *buf)
 {
   gdb_byte reg[16];
+  char annex[32];
+  ULONGEST id;
 
   switch (regnum)
     {
@@ -119,16 +200,58 @@ spu_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
       memcpy (buf, reg, 4);
       break;
 
+    case SPU_FPSCR_REGNUM:
+      regcache_raw_read_unsigned (regcache, SPU_ID_REGNUM, &id);
+      xsnprintf (annex, sizeof annex, "%d/fpcr", (int) id);
+      target_read (&current_target, TARGET_OBJECT_SPU, annex, buf, 0, 16);
+      break;
+
+    case SPU_SRR0_REGNUM:
+      spu_pseudo_register_read_spu (regcache, "srr0", buf);
+      break;
+
+    case SPU_LSLR_REGNUM:
+      spu_pseudo_register_read_spu (regcache, "lslr", buf);
+      break;
+
+    case SPU_DECR_REGNUM:
+      spu_pseudo_register_read_spu (regcache, "decr", buf);
+      break;
+
+    case SPU_DECR_STATUS_REGNUM:
+      spu_pseudo_register_read_spu (regcache, "decr_status", buf);
+      break;
+
     default:
       internal_error (__FILE__, __LINE__, _("invalid regnum"));
     }
 }
 
+static void
+spu_pseudo_register_write_spu (struct regcache *regcache, const char *regname,
+                              const gdb_byte *buf)
+{
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  gdb_byte reg[32];
+  char annex[32];
+  ULONGEST id;
+
+  regcache_raw_read_unsigned (regcache, SPU_ID_REGNUM, &id);
+  xsnprintf (annex, sizeof annex, "%d/%s", (int) id, regname);
+  xsnprintf (reg, sizeof reg, "0x%s",
+            phex_nz (extract_unsigned_integer (buf, 4, byte_order), 4));
+  target_write (&current_target, TARGET_OBJECT_SPU, annex,
+               reg, 0, strlen (reg));
+}
+
 static void
 spu_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
                            int regnum, const gdb_byte *buf)
 {
   gdb_byte reg[16];
+  char annex[32];
+  ULONGEST id;
 
   switch (regnum)
     {
@@ -138,6 +261,28 @@ spu_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
       regcache_raw_write (regcache, SPU_RAW_SP_REGNUM, reg);
       break;
 
+    case SPU_FPSCR_REGNUM:
+      regcache_raw_read_unsigned (regcache, SPU_ID_REGNUM, &id);
+      xsnprintf (annex, sizeof annex, "%d/fpcr", (int) id);
+      target_write (&current_target, TARGET_OBJECT_SPU, annex, buf, 0, 16);
+      break;
+
+    case SPU_SRR0_REGNUM:
+      spu_pseudo_register_write_spu (regcache, "srr0", buf);
+      break;
+
+    case SPU_LSLR_REGNUM:
+      spu_pseudo_register_write_spu (regcache, "lslr", buf);
+      break;
+
+    case SPU_DECR_REGNUM:
+      spu_pseudo_register_write_spu (regcache, "decr", buf);
+      break;
+
+    case SPU_DECR_STATUS_REGNUM:
+      spu_pseudo_register_write_spu (regcache, "decr_status", buf);
+      break;
+
     default:
       internal_error (__FILE__, __LINE__, _("invalid regnum"));
     }
@@ -183,6 +328,38 @@ 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 gdbarch *gdbarch,
+                       struct type *type, const gdb_byte *buf)
+{
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  ULONGEST addr
+    = extract_unsigned_integer (buf, TYPE_LENGTH (type), byte_order);
+  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.  */
 
@@ -359,9 +536,11 @@ struct spu_prologue_data
   };
 
 static CORE_ADDR
-spu_analyze_prologue (CORE_ADDR start_pc, CORE_ADDR end_pc,
+spu_analyze_prologue (struct gdbarch *gdbarch,
+                     CORE_ADDR start_pc, CORE_ADDR end_pc,
                       struct spu_prologue_data *data)
 {
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   int found_sp = 0;
   int found_fp = 0;
   int found_lr = 0;
@@ -421,7 +600,7 @@ spu_analyze_prologue (CORE_ADDR start_pc, CORE_ADDR end_pc,
 
       if (target_read_memory (pc, buf, 4))
        break;
-      insn = extract_unsigned_integer (buf, 4);
+      insn = extract_unsigned_integer (buf, 4, byte_order);
 
       /* AI is the typical instruction to set up a stack frame.
          It is also used to initialize the frame pointer.  */
@@ -532,18 +711,19 @@ 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);
+  return spu_analyze_prologue (gdbarch, pc, (CORE_ADDR)-1, &data);
 }
 
 /* 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);
+  spu_analyze_prologue (gdbarch, pc, (CORE_ADDR)-1, &data);
 
   if (data.size != -1 && data.cfa_reg != -1)
     {
@@ -559,6 +739,102 @@ spu_virtual_frame_pointer (CORE_ADDR pc, int *reg, LONGEST *offset)
     }
 }
 
+/* Return true if we are in the function's epilogue, i.e. after the
+   instruction that destroyed the function's stack frame.
+
+   1) scan forward from the point of execution:
+       a) If you find an instruction that modifies the stack pointer
+          or transfers control (except a return), execution is not in
+          an epilogue, return.
+       b) Stop scanning if you find a return instruction or reach the
+          end of the function or reach the hard limit for the size of
+          an epilogue.
+   2) scan backward from the point of execution:
+        a) If you find an instruction that modifies the stack pointer,
+            execution *is* in an epilogue, return.
+        b) Stop scanning if you reach an instruction that transfers
+           control or the beginning of the function or reach the hard
+           limit for the size of an epilogue.  */
+
+static int
+spu_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  CORE_ADDR scan_pc, func_start, func_end, epilogue_start, epilogue_end;
+  bfd_byte buf[4];
+  unsigned int insn;
+  int rt, ra, rb, rc, immed;
+
+  /* Find the search limits based on function boundaries and hard limit.
+     We assume the epilogue can be up to 64 instructions long.  */
+
+  const int spu_max_epilogue_size = 64 * 4;
+
+  if (!find_pc_partial_function (pc, NULL, &func_start, &func_end))
+    return 0;
+
+  if (pc - func_start < spu_max_epilogue_size)
+    epilogue_start = func_start;
+  else
+    epilogue_start = pc - spu_max_epilogue_size;
+
+  if (func_end - pc < spu_max_epilogue_size)
+    epilogue_end = func_end;
+  else
+    epilogue_end = pc + spu_max_epilogue_size;
+
+  /* Scan forward until next 'bi $0'.  */
+
+  for (scan_pc = pc; scan_pc < epilogue_end; scan_pc += 4)
+    {
+      if (target_read_memory (scan_pc, buf, 4))
+       return 0;
+      insn = extract_unsigned_integer (buf, 4, byte_order);
+
+      if (is_branch (insn, &immed, &ra))
+       {
+         if (immed == 0 && ra == SPU_LR_REGNUM)
+           break;
+
+         return 0;
+       }
+
+      if (is_ri10 (insn, op_ai, &rt, &ra, &immed)
+         || is_rr (insn, op_a, &rt, &ra, &rb)
+         || is_ri10 (insn, op_lqd, &rt, &ra, &immed))
+       {
+         if (rt == SPU_RAW_SP_REGNUM)
+           return 0;
+       }
+    }
+
+  if (scan_pc >= epilogue_end)
+    return 0;
+
+  /* Scan backward until adjustment to stack pointer (R1).  */
+
+  for (scan_pc = pc - 4; scan_pc >= epilogue_start; scan_pc -= 4)
+    {
+      if (target_read_memory (scan_pc, buf, 4))
+       return 0;
+      insn = extract_unsigned_integer (buf, 4, byte_order);
+
+      if (is_branch (insn, &immed, &ra))
+       return 0;
+
+      if (is_ri10 (insn, op_ai, &rt, &ra, &immed)
+         || is_rr (insn, op_a, &rt, &ra, &rb)
+         || is_ri10 (insn, op_lqd, &rt, &ra, &immed))
+       {
+         if (rt == SPU_RAW_SP_REGNUM)
+           return 1;
+       }
+    }
+
+  return 0;
+}
+
+
 /* Normal stack frames.  */
 
 struct spu_unwind_cache
@@ -571,43 +847,45 @@ 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 gdbarch *gdbarch = get_frame_arch (this_frame);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   struct spu_unwind_cache *info;
   struct spu_prologue_data data;
+  gdb_byte buf[16];
 
   if (*this_prologue_cache)
     return *this_prologue_cache;
 
   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 (gdbarch, info->func, get_frame_pc (this_frame),
+                         &data);
 
   /* If successful, use prologue analysis data.  */
   if (data.size != -1 && data.cfa_reg != -1)
     {
       CORE_ADDR cfa;
       int i;
-      gdb_byte buf[16];
 
       /* Determine CFA via unwound CFA_REG plus CFA_OFFSET.  */
-      frame_unwind_register (next_frame, data.cfa_reg, buf);
-      cfa = extract_unsigned_integer (buf, 4) + data.cfa_offset;
+      get_frame_register (this_frame, data.cfa_reg, buf);
+      cfa = extract_unsigned_integer (buf, 4, byte_order) + data.cfa_offset;
 
       /* Call-saved register slots.  */
       for (i = 0; i < SPU_NUM_GPRS; i++)
@@ -616,15 +894,6 @@ spu_frame_unwind_cache (struct frame_info *next_frame,
          if (data.reg_offset[i] != -1)
            info->saved_regs[i].addr = cfa - data.reg_offset[i];
 
-      /* The previous PC comes from the link register.  */
-      if (trad_frame_addr_p (info->saved_regs, SPU_LR_REGNUM))
-       info->saved_regs[SPU_PC_REGNUM] = info->saved_regs[SPU_LR_REGNUM];
-      else
-       info->saved_regs[SPU_PC_REGNUM].realreg = SPU_LR_REGNUM;
-
-      /* The previous SP is equal to the CFA.  */
-      trad_frame_set_value (info->saved_regs, SPU_SP_REGNUM, cfa);
-
       /* Frame bases.  */
       info->frame_base = cfa;
       info->local_base = cfa - data.size;
@@ -633,44 +902,64 @@ spu_frame_unwind_cache (struct frame_info *next_frame,
   /* Otherwise, fall back to reading the backchain link.  */
   else
     {
-      CORE_ADDR reg, backchain;
+      CORE_ADDR reg;
+      LONGEST backchain;
+      int status;
 
       /* Get the backchain.  */
-      reg = frame_unwind_register_unsigned (next_frame, SPU_SP_REGNUM);
-      backchain = read_memory_unsigned_integer (reg, 4);
+      reg = get_frame_register_unsigned (this_frame, SPU_SP_REGNUM);
+      status = safe_read_memory_integer (reg, 4, byte_order, &backchain);
 
       /* A zero backchain terminates the frame chain.  Also, sanity
          check against the local store size limit.  */
-      if (backchain != 0 && backchain < SPU_LS_SIZE)
+      if (status && backchain > 0 && backchain < SPU_LS_SIZE)
        {
          /* Assume the link register is saved into its slot.  */
          if (backchain + 16 < SPU_LS_SIZE)
            info->saved_regs[SPU_LR_REGNUM].addr = backchain + 16;
 
-         /* This will also be the previous PC.  */
-         if (trad_frame_addr_p (info->saved_regs, SPU_LR_REGNUM))
-           info->saved_regs[SPU_PC_REGNUM] = info->saved_regs[SPU_LR_REGNUM];
-         else
-           info->saved_regs[SPU_PC_REGNUM].realreg = SPU_LR_REGNUM;
-
-         /* The previous SP will equal the backchain value.  */
-         trad_frame_set_value (info->saved_regs, SPU_SP_REGNUM, backchain);
-
           /* Frame bases.  */
          info->frame_base = backchain;
          info->local_base = reg;
        }
     }
+
+  /* If we didn't find a frame, we cannot determine SP / return address.  */
+  if (info->frame_base == 0)
+    return info;
+
+  /* The previous SP is equal to the CFA.  */
+  trad_frame_set_value (info->saved_regs, SPU_SP_REGNUM, info->frame_base);
+
+  /* Read full contents of the unwound link register in order to
+     be able to determine the return address.  */
+  if (trad_frame_addr_p (info->saved_regs, SPU_LR_REGNUM))
+    target_read_memory (info->saved_regs[SPU_LR_REGNUM].addr, buf, 16);
+  else
+    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,
+     slot 0 contains the address of the overlay manager return stub,
+     slot 1 contains the partition number of the overlay section to
+     be returned to, and slot 2 contains the return address within
+     that section.  Return the latter address in that case.  */
+  if (extract_unsigned_integer (buf + 8, 4, byte_order) != 0)
+    trad_frame_set_value (info->saved_regs, SPU_PC_REGNUM,
+                         extract_unsigned_integer (buf + 8, 4, byte_order));
+  else
+    trad_frame_set_value (info->saved_regs, SPU_PC_REGNUM,
+                         extract_unsigned_integer (buf, 4, byte_order));
  
   return info;
 }
 
 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;
@@ -678,41 +967,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;
 }
 
@@ -726,7 +1007,9 @@ static const struct frame_base spu_frame_base = {
 static CORE_ADDR
 spu_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
 {
-  return frame_unwind_register_unsigned (next_frame, SPU_PC_REGNUM);
+  CORE_ADDR pc = frame_unwind_register_unsigned (next_frame, SPU_PC_REGNUM);
+  /* Mask off interrupt enable bit.  */
+  return pc & -4;
 }
 
 static CORE_ADDR
@@ -735,9 +1018,50 @@ spu_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
   return frame_unwind_register_unsigned (next_frame, SPU_SP_REGNUM);
 }
 
+static CORE_ADDR
+spu_read_pc (struct regcache *regcache)
+{
+  ULONGEST pc;
+  regcache_cooked_read_unsigned (regcache, SPU_PC_REGNUM, &pc);
+  /* Mask off interrupt enable bit.  */
+  return pc & -4;
+}
+
+static void
+spu_write_pc (struct regcache *regcache, CORE_ADDR pc)
+{
+  /* Keep interrupt enabled state unchanged.  */
+  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));
+}
+
 
 /* Function calling convention.  */
 
+static CORE_ADDR
+spu_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp)
+{
+  return sp & ~15;
+}
+
+static CORE_ADDR
+spu_push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp, CORE_ADDR funaddr,
+                    struct value **args, int nargs, struct type *value_type,
+                    CORE_ADDR *real_pc, CORE_ADDR *bp_addr,
+                    struct regcache *regcache)
+{
+  /* Allocate space sufficient for a breakpoint, keeping the stack aligned.  */
+  sp = (sp - 4) & ~15;
+  /* Store the address of that breakpoint */
+  *bp_addr = sp;
+  /* The call starts at the callee's entry point.  */
+  *real_pc = funaddr;
+
+  return sp;
+}
+
 static int
 spu_scalar_value_p (struct type *type)
 {
@@ -813,6 +1137,8 @@ spu_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                     int nargs, struct value **args, CORE_ADDR sp,
                     int struct_return, CORE_ADDR struct_addr)
 {
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  CORE_ADDR sp_delta;
   int i;
   int regnum = SPU_ARG1_REGNUM;
   int stack_arg = -1;
@@ -820,7 +1146,7 @@ spu_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 
   /* Set the return address.  */
   memset (buf, 0, sizeof buf);
-  store_unsigned_integer (buf, 4, bp_addr);
+  store_unsigned_integer (buf, 4, byte_order, bp_addr);
   regcache_cooked_write (regcache, SPU_LR_REGNUM, buf);
 
   /* If STRUCT_RETURN is true, then the struct return address (in
@@ -829,7 +1155,7 @@ spu_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
   if (struct_return)
     {
       memset (buf, 0, sizeof buf);
-      store_unsigned_integer (buf, 4, struct_addr);
+      store_unsigned_integer (buf, 4, byte_order, struct_addr);
       regcache_cooked_write (regcache, regnum++, buf);
     }
 
@@ -888,24 +1214,36 @@ spu_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
   /* Allocate stack frame header.  */
   sp -= 32;
 
-  /* Finally, update the SP register.  */
-  regcache_cooked_write_unsigned (regcache, SPU_SP_REGNUM, sp);
+  /* Store stack back chain.  */
+  regcache_cooked_read (regcache, SPU_RAW_SP_REGNUM, buf);
+  target_write_memory (sp, buf, 16);
+
+  /* Finally, update all slots of the SP register.  */
+  sp_delta = sp - extract_unsigned_integer (buf, 4, byte_order);
+  for (i = 0; i < 4; i++)
+    {
+      CORE_ADDR sp_slot = extract_unsigned_integer (buf + 4*i, 4, byte_order);
+      store_unsigned_integer (buf + 4*i, 4, byte_order, sp_slot + sp_delta);
+    }
+  regcache_cooked_write (regcache, SPU_RAW_SP_REGNUM, buf);
 
   return sp;
 }
 
 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;
 
@@ -948,7 +1286,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 };
 
@@ -959,52 +1297,836 @@ spu_breakpoint_from_pc (CORE_ADDR * pcptr, int *lenptr)
 
 /* Software single-stepping support.  */
 
-void
-spu_software_single_step (enum target_signal signal, int insert_breakpoints_p)
+static int
+spu_software_single_step (struct frame_info *frame)
 {
-  if (insert_breakpoints_p)
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  CORE_ADDR pc, next_pc;
+  unsigned int insn;
+  int offset, reg;
+  gdb_byte buf[4];
+
+  pc = get_frame_pc (frame);
+
+  if (target_read_memory (pc, buf, 4))
+    return 1;
+  insn = extract_unsigned_integer (buf, 4, byte_order);
+
+  /* Next sequential instruction is at PC + 4, except if the current
+     instruction is a PPE-assisted call, in which case it is at PC + 8.
+     Wrap around LS limit to be on the safe side.  */
+  if ((insn & 0xffffff00) == 0x00002100)
+    next_pc = (pc + 8) & (SPU_LS_SIZE - 1);
+  else
+    next_pc = (pc + 4) & (SPU_LS_SIZE - 1);
+
+  insert_single_step_breakpoint (gdbarch, next_pc);
+
+  if (is_branch (insn, &offset, &reg))
     {
-      CORE_ADDR pc, next_pc;
-      unsigned int insn;
-      int offset, reg;
-      gdb_byte buf[4];
+      CORE_ADDR target = offset;
 
-      regcache_cooked_read (current_regcache, SPU_PC_REGNUM, buf);
-      pc = extract_unsigned_integer (buf, 4);
+      if (reg == SPU_PC_REGNUM)
+       target += pc;
+      else if (reg != -1)
+       {
+         get_frame_register_bytes (frame, reg, 0, 4, buf);
+         target += extract_unsigned_integer (buf, 4, byte_order) & -4;
+       }
 
-      if (target_read_memory (pc, buf, 4))
-       return;
-      insn = extract_unsigned_integer (buf, 4);
-
-       /* Next sequential instruction is at PC + 4, except if the current
-         instruction is a PPE-assisted call, in which case it is at PC + 8.
-         Wrap around LS limit to be on the safe side.  */
-      if ((insn & 0xffffff00) == 0x00002100)
-       next_pc = (pc + 8) & (SPU_LS_SIZE - 1) & -4;
+      target = target & (SPU_LS_SIZE - 1);
+      if (target != next_pc)
+       insert_single_step_breakpoint (gdbarch, target);
+    }
+
+  return 1;
+}
+
+
+/* Longjmp support.  */
+
+static int
+spu_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
+{
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  gdb_byte buf[4];
+  CORE_ADDR jb_addr;
+
+  /* Jump buffer is pointed to by the argument register $r3.  */
+  get_frame_register_bytes (frame, SPU_ARG1_REGNUM, 0, 4, buf);
+  jb_addr = extract_unsigned_integer (buf, 4, byte_order);
+  if (target_read_memory (jb_addr, buf, 4))
+    return 0;
+
+  *pc = extract_unsigned_integer (buf, 4, byte_order);
+  return 1;
+}
+
+
+/* Target overlays for the SPU overlay manager.
+
+   See the documentation of simple_overlay_update for how the
+   interface is supposed to work.
+
+   Data structures used by the overlay manager:
+
+   struct ovly_table
+     {
+        u32 vma;
+        u32 size;
+        u32 pos;
+        u32 buf;
+     } _ovly_table[];   -- one entry per overlay section
+
+   struct ovly_buf_table
+     {
+        u32 mapped;
+     } _ovly_buf_table[];  -- one entry per overlay buffer
+
+   _ovly_table should never change.
+
+   Both tables are aligned to a 16-byte boundary, the symbols _ovly_table
+   and _ovly_buf_table are of type STT_OBJECT and their size set to the size
+   of the respective array. buf in _ovly_table is an index into _ovly_buf_table.
+
+   mapped is an index into _ovly_table. Both the mapped and buf indices start
+   from one to reference the first entry in their respective tables.  */
+
+/* Using the per-objfile private data mechanism, we store for each
+   objfile an array of "struct spu_overlay_table" structures, one
+   for each obj_section of the objfile.  This structure holds two
+   fields, MAPPED_PTR and MAPPED_VAL.  If MAPPED_PTR is zero, this
+   is *not* an overlay section.  If it is non-zero, it represents
+   a target address.  The overlay section is mapped iff the target
+   integer at this location equals MAPPED_VAL.  */
+
+static const struct objfile_data *spu_overlay_data;
+
+struct spu_overlay_table
+  {
+    CORE_ADDR mapped_ptr;
+    CORE_ADDR mapped_val;
+  };
+
+/* Retrieve the overlay table for OBJFILE.  If not already cached, read
+   the _ovly_table data structure from the target and initialize the
+   spu_overlay_table data structure from it.  */
+static struct spu_overlay_table *
+spu_get_overlay_table (struct objfile *objfile)
+{
+  enum bfd_endian byte_order = bfd_big_endian (objfile->obfd)?
+                  BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE;
+  struct minimal_symbol *ovly_table_msym, *ovly_buf_table_msym;
+  CORE_ADDR ovly_table_base, ovly_buf_table_base;
+  unsigned ovly_table_size, ovly_buf_table_size;
+  struct spu_overlay_table *tbl;
+  struct obj_section *osect;
+  char *ovly_table;
+  int i;
+
+  tbl = objfile_data (objfile, spu_overlay_data);
+  if (tbl)
+    return tbl;
+
+  ovly_table_msym = lookup_minimal_symbol ("_ovly_table", NULL, objfile);
+  if (!ovly_table_msym)
+    return NULL;
+
+  ovly_buf_table_msym = lookup_minimal_symbol ("_ovly_buf_table", NULL, objfile);
+  if (!ovly_buf_table_msym)
+    return NULL;
+
+  ovly_table_base = SYMBOL_VALUE_ADDRESS (ovly_table_msym);
+  ovly_table_size = MSYMBOL_SIZE (ovly_table_msym);
+
+  ovly_buf_table_base = SYMBOL_VALUE_ADDRESS (ovly_buf_table_msym);
+  ovly_buf_table_size = MSYMBOL_SIZE (ovly_buf_table_msym);
+
+  ovly_table = xmalloc (ovly_table_size);
+  read_memory (ovly_table_base, ovly_table, ovly_table_size);
+
+  tbl = OBSTACK_CALLOC (&objfile->objfile_obstack,
+                       objfile->sections_end - objfile->sections,
+                       struct spu_overlay_table);
+
+  for (i = 0; i < ovly_table_size / 16; i++)
+    {
+      CORE_ADDR vma  = extract_unsigned_integer (ovly_table + 16*i + 0,
+                                                4, byte_order);
+      CORE_ADDR size = extract_unsigned_integer (ovly_table + 16*i + 4,
+                                                4, byte_order);
+      CORE_ADDR pos  = extract_unsigned_integer (ovly_table + 16*i + 8,
+                                                4, byte_order);
+      CORE_ADDR buf  = extract_unsigned_integer (ovly_table + 16*i + 12,
+                                                4, byte_order);
+
+      if (buf == 0 || (buf - 1) * 4 >= ovly_buf_table_size)
+       continue;
+
+      ALL_OBJFILE_OSECTIONS (objfile, osect)
+       if (vma == bfd_section_vma (objfile->obfd, osect->the_bfd_section)
+           && pos == osect->the_bfd_section->filepos)
+         {
+           int ndx = osect - objfile->sections;
+           tbl[ndx].mapped_ptr = ovly_buf_table_base + (buf - 1) * 4;
+           tbl[ndx].mapped_val = i + 1;
+           break;
+         }
+    }
+
+  xfree (ovly_table);
+  set_objfile_data (objfile, spu_overlay_data, tbl);
+  return tbl;
+}
+
+/* Read _ovly_buf_table entry from the target to dermine whether
+   OSECT is currently mapped, and update the mapped state.  */
+static void
+spu_overlay_update_osect (struct obj_section *osect)
+{
+  enum bfd_endian byte_order = bfd_big_endian (osect->objfile->obfd)?
+                  BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE;
+  struct spu_overlay_table *ovly_table;
+  CORE_ADDR val;
+
+  ovly_table = spu_get_overlay_table (osect->objfile);
+  if (!ovly_table)
+    return;
+
+  ovly_table += osect - osect->objfile->sections;
+  if (ovly_table->mapped_ptr == 0)
+    return;
+
+  val = read_memory_unsigned_integer (ovly_table->mapped_ptr, 4, byte_order);
+  osect->ovly_mapped = (val == ovly_table->mapped_val);
+}
+
+/* If OSECT is NULL, then update all sections' mapped state.
+   If OSECT is non-NULL, then update only OSECT's mapped state.  */
+static void
+spu_overlay_update (struct obj_section *osect)
+{
+  /* Just one section.  */
+  if (osect)
+    spu_overlay_update_osect (osect);
+
+  /* All sections.  */
+  else
+    {
+      struct objfile *objfile;
+
+      ALL_OBJSECTIONS (objfile, osect)
+       if (section_is_overlay (osect))
+         spu_overlay_update_osect (osect);
+    }
+}
+
+/* Whenever a new objfile is loaded, read the target's _ovly_table.
+   If there is one, go through all sections and make sure for non-
+   overlay sections LMA equals VMA, while for overlay sections LMA
+   is larger than local store size.  */
+static void
+spu_overlay_new_objfile (struct objfile *objfile)
+{
+  struct spu_overlay_table *ovly_table;
+  struct obj_section *osect;
+
+  /* If we've already touched this file, do nothing.  */
+  if (!objfile || objfile_data (objfile, spu_overlay_data) != NULL)
+    return;
+
+  /* Consider only SPU objfiles.  */
+  if (bfd_get_arch (objfile->obfd) != bfd_arch_spu)
+    return;
+
+  /* Check if this objfile has overlays.  */
+  ovly_table = spu_get_overlay_table (objfile);
+  if (!ovly_table)
+    return;
+
+  /* Now go and fiddle with all the LMAs.  */
+  ALL_OBJFILE_OSECTIONS (objfile, osect)
+    {
+      bfd *obfd = objfile->obfd;
+      asection *bsect = osect->the_bfd_section;
+      int ndx = osect - objfile->sections;
+
+      if (ovly_table[ndx].mapped_ptr == 0)
+       bfd_section_lma (obfd, bsect) = bfd_section_vma (obfd, bsect);
+      else
+       bfd_section_lma (obfd, bsect) = bsect->filepos + SPU_LS_SIZE;
+    }
+}
+
+
+/* "info spu" commands.  */
+
+static void
+info_spu_event_command (char *args, int from_tty)
+{
+  struct frame_info *frame = get_selected_frame (NULL);
+  ULONGEST event_status = 0;
+  ULONGEST event_mask = 0;
+  struct cleanup *chain;
+  gdb_byte buf[100];
+  char annex[32];
+  LONGEST len;
+  int rc, id;
+
+  if (gdbarch_bfd_arch_info (get_frame_arch (frame))->arch != bfd_arch_spu)
+    error (_("\"info spu\" is only supported on the SPU architecture."));
+
+  id = get_frame_register_unsigned (frame, SPU_ID_REGNUM);
+
+  xsnprintf (annex, sizeof annex, "%d/event_status", id);
+  len = target_read (&current_target, TARGET_OBJECT_SPU, annex,
+                    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) - 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");
+
+  if (ui_out_is_mi_like_p (uiout))
+    {
+      ui_out_field_fmt (uiout, "event_status",
+                       "0x%s", phex_nz (event_status, 4));
+      ui_out_field_fmt (uiout, "event_mask",
+                       "0x%s", phex_nz (event_mask, 4));
+    }
+  else
+    {
+      printf_filtered (_("Event Status 0x%s\n"), phex (event_status, 4));
+      printf_filtered (_("Event Mask   0x%s\n"), phex (event_mask, 4));
+    }
+
+  do_cleanups (chain);
+}
+
+static void
+info_spu_signal_command (char *args, int from_tty)
+{
+  struct frame_info *frame = get_selected_frame (NULL);
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  ULONGEST signal1 = 0;
+  ULONGEST signal1_type = 0;
+  int signal1_pending = 0;
+  ULONGEST signal2 = 0;
+  ULONGEST signal2_type = 0;
+  int signal2_pending = 0;
+  struct cleanup *chain;
+  char annex[32];
+  gdb_byte buf[100];
+  LONGEST len;
+  int rc, id;
+
+  if (gdbarch_bfd_arch_info (gdbarch)->arch != bfd_arch_spu)
+    error (_("\"info spu\" is only supported on the SPU architecture."));
+
+  id = get_frame_register_unsigned (frame, SPU_ID_REGNUM);
+
+  xsnprintf (annex, sizeof annex, "%d/signal1", id);
+  len = target_read (&current_target, TARGET_OBJECT_SPU, annex, buf, 0, 4);
+  if (len < 0)
+    error (_("Could not read signal1."));
+  else if (len == 4)
+    {
+      signal1 = extract_unsigned_integer (buf, 4, byte_order);
+      signal1_pending = 1;
+    }
+    
+  xsnprintf (annex, sizeof annex, "%d/signal1_type", id);
+  len = target_read (&current_target, TARGET_OBJECT_SPU, annex,
+                    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);
+  len = target_read (&current_target, TARGET_OBJECT_SPU, annex, buf, 0, 4);
+  if (len < 0)
+    error (_("Could not read signal2."));
+  else if (len == 4)
+    {
+      signal2 = extract_unsigned_integer (buf, 4, byte_order);
+      signal2_pending = 1;
+    }
+    
+  xsnprintf (annex, sizeof annex, "%d/signal2_type", id);
+  len = target_read (&current_target, TARGET_OBJECT_SPU, annex,
+                    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");
+
+  if (ui_out_is_mi_like_p (uiout))
+    {
+      ui_out_field_int (uiout, "signal1_pending", signal1_pending);
+      ui_out_field_fmt (uiout, "signal1", "0x%s", phex_nz (signal1, 4));
+      ui_out_field_int (uiout, "signal1_type", signal1_type);
+      ui_out_field_int (uiout, "signal2_pending", signal2_pending);
+      ui_out_field_fmt (uiout, "signal2", "0x%s", phex_nz (signal2, 4));
+      ui_out_field_int (uiout, "signal2_type", signal2_type);
+    }
+  else
+    {
+      if (signal1_pending)
+       printf_filtered (_("Signal 1 control word 0x%s "), phex (signal1, 4));
+      else
+       printf_filtered (_("Signal 1 not pending "));
+
+      if (signal1_type)
+       printf_filtered (_("(Type Or)\n"));
       else
-       next_pc = (pc + 4) & (SPU_LS_SIZE - 1) & -4;
+       printf_filtered (_("(Type Overwrite)\n"));
 
-      insert_single_step_breakpoint (next_pc);
+      if (signal2_pending)
+       printf_filtered (_("Signal 2 control word 0x%s "), phex (signal2, 4));
+      else
+       printf_filtered (_("Signal 2 not pending "));
+
+      if (signal2_type)
+       printf_filtered (_("(Type Or)\n"));
+      else
+       printf_filtered (_("(Type Overwrite)\n"));
+    }
+
+  do_cleanups (chain);
+}
 
-      if (is_branch (insn, &offset, &reg))
+static void
+info_spu_mailbox_list (gdb_byte *buf, int nr, enum bfd_endian byte_order,
+                      const char *field, const char *msg)
+{
+  struct cleanup *chain;
+  int i;
+
+  if (nr <= 0)
+    return;
+
+  chain = make_cleanup_ui_out_table_begin_end (uiout, 1, nr, "mbox");
+
+  ui_out_table_header (uiout, 32, ui_left, field, msg);
+  ui_out_table_body (uiout);
+
+  for (i = 0; i < nr; i++)
+    {
+      struct cleanup *val_chain;
+      ULONGEST val;
+      val_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "mbox");
+      val = extract_unsigned_integer (buf + 4*i, 4, byte_order);
+      ui_out_field_fmt (uiout, field, "0x%s", phex (val, 4));
+      do_cleanups (val_chain);
+
+      if (!ui_out_is_mi_like_p (uiout))
+       printf_filtered ("\n");
+    }
+
+  do_cleanups (chain);
+}
+
+static void
+info_spu_mailbox_command (char *args, int from_tty)
+{
+  struct frame_info *frame = get_selected_frame (NULL);
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  struct cleanup *chain;
+  char annex[32];
+  gdb_byte buf[1024];
+  LONGEST len;
+  int i, id;
+
+  if (gdbarch_bfd_arch_info (gdbarch)->arch != bfd_arch_spu)
+    error (_("\"info spu\" is only supported on the SPU architecture."));
+
+  id = get_frame_register_unsigned (frame, SPU_ID_REGNUM);
+
+  chain = make_cleanup_ui_out_tuple_begin_end (uiout, "SPUInfoMailbox");
+
+  xsnprintf (annex, sizeof annex, "%d/mbox_info", id);
+  len = target_read (&current_target, TARGET_OBJECT_SPU, annex,
+                    buf, 0, sizeof buf);
+  if (len < 0)
+    error (_("Could not read mbox_info."));
+
+  info_spu_mailbox_list (buf, len / 4, byte_order,
+                        "mbox", "SPU Outbound Mailbox");
+
+  xsnprintf (annex, sizeof annex, "%d/ibox_info", id);
+  len = target_read (&current_target, TARGET_OBJECT_SPU, annex,
+                    buf, 0, sizeof buf);
+  if (len < 0)
+    error (_("Could not read ibox_info."));
+
+  info_spu_mailbox_list (buf, len / 4, byte_order,
+                        "ibox", "SPU Outbound Interrupt Mailbox");
+
+  xsnprintf (annex, sizeof annex, "%d/wbox_info", id);
+  len = target_read (&current_target, TARGET_OBJECT_SPU, annex,
+                    buf, 0, sizeof buf);
+  if (len < 0)
+    error (_("Could not read wbox_info."));
+
+  info_spu_mailbox_list (buf, len / 4, byte_order,
+                        "wbox", "SPU Inbound Mailbox");
+
+  do_cleanups (chain);
+}
+
+static ULONGEST
+spu_mfc_get_bitfield (ULONGEST word, int first, int last)
+{
+  ULONGEST mask = ~(~(ULONGEST)0 << (last - first + 1));
+  return (word >> (63 - last)) & mask;
+}
+
+static void
+info_spu_dma_cmdlist (gdb_byte *buf, int nr, enum bfd_endian byte_order)
+{
+  static char *spu_mfc_opcode[256] =
+    {
+    /* 00 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+             NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    /* 10 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+             NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    /* 20 */ "put", "putb", "putf", NULL, "putl", "putlb", "putlf", NULL,
+             "puts", "putbs", "putfs", NULL, NULL, NULL, NULL, NULL,
+    /* 30 */ "putr", "putrb", "putrf", NULL, "putrl", "putrlb", "putrlf", NULL,
+             NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    /* 40 */ "get", "getb", "getf", NULL, "getl", "getlb", "getlf", NULL,
+             "gets", "getbs", "getfs", NULL, NULL, NULL, NULL, NULL,
+    /* 50 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+             NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    /* 60 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+             NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    /* 70 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+             NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    /* 80 */ "sdcrt", "sdcrtst", NULL, NULL, NULL, NULL, NULL, NULL,
+             NULL, "sdcrz", NULL, NULL, NULL, "sdcrst", NULL, "sdcrf",
+    /* 90 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+             NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    /* a0 */ "sndsig", "sndsigb", "sndsigf", NULL, NULL, NULL, NULL, NULL,
+             NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    /* b0 */ "putlluc", NULL, NULL, NULL, "putllc", NULL, NULL, NULL,
+             "putqlluc", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    /* c0 */ "barrier", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+             "mfceieio", NULL, NULL, NULL, "mfcsync", NULL, NULL, NULL,
+    /* d0 */ "getllar", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+             NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    /* e0 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+             NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    /* f0 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+             NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    };
+
+  int *seq = alloca (nr * sizeof (int));
+  int done = 0;
+  struct cleanup *chain;
+  int i, j;
+
+
+  /* Determine sequence in which to display (valid) entries.  */
+  for (i = 0; i < nr; i++)
+    {
+      /* Search for the first valid entry all of whose
+        dependencies are met.  */
+      for (j = 0; j < nr; j++)
        {
-         CORE_ADDR target = offset;
+          ULONGEST mfc_cq_dw3;
+         ULONGEST dependencies;
 
-         if (reg == SPU_PC_REGNUM)
-           target += pc;
-         else if (reg != -1)
-           {
-             regcache_cooked_read_part (current_regcache, reg, 0, 4, buf);
-             target += extract_unsigned_integer (buf, 4);
-           }
+         if (done & (1 << (nr - 1 - j)))
+           continue;
 
-         target = target & (SPU_LS_SIZE - 1) & -4;
-         if (target != next_pc)
-           insert_single_step_breakpoint (target);
+         mfc_cq_dw3
+           = extract_unsigned_integer (buf + 32*j + 24,8, byte_order);
+         if (!spu_mfc_get_bitfield (mfc_cq_dw3, 16, 16))
+           continue;
+
+         dependencies = spu_mfc_get_bitfield (mfc_cq_dw3, 0, nr - 1);
+         if ((dependencies & done) != dependencies)
+           continue;
+
+         seq[i] = j;
+         done |= 1 << (nr - 1 - j);
+         break;
        }
+
+      if (j == nr)
+       break;
+    }
+
+  nr = i;
+
+
+  chain = make_cleanup_ui_out_table_begin_end (uiout, 10, nr, "dma_cmd");
+
+  ui_out_table_header (uiout, 7, ui_left, "opcode", "Opcode");
+  ui_out_table_header (uiout, 3, ui_left, "tag", "Tag");
+  ui_out_table_header (uiout, 3, ui_left, "tid", "TId");
+  ui_out_table_header (uiout, 3, ui_left, "rid", "RId");
+  ui_out_table_header (uiout, 18, ui_left, "ea", "EA");
+  ui_out_table_header (uiout, 7, ui_left, "lsa", "LSA");
+  ui_out_table_header (uiout, 7, ui_left, "size", "Size");
+  ui_out_table_header (uiout, 7, ui_left, "lstaddr", "LstAddr");
+  ui_out_table_header (uiout, 7, ui_left, "lstsize", "LstSize");
+  ui_out_table_header (uiout, 1, ui_left, "error_p", "E");
+
+  ui_out_table_body (uiout);
+
+  for (i = 0; i < nr; i++)
+    {
+      struct cleanup *cmd_chain;
+      ULONGEST mfc_cq_dw0;
+      ULONGEST mfc_cq_dw1;
+      ULONGEST mfc_cq_dw2;
+      int mfc_cmd_opcode, mfc_cmd_tag, rclass_id, tclass_id;
+      int lsa, size, list_lsa, list_size, mfc_lsa, mfc_size;
+      ULONGEST mfc_ea;
+      int list_valid_p, noop_valid_p, qw_valid_p, ea_valid_p, cmd_error_p;
+
+      /* Decode contents of MFC Command Queue Context Save/Restore Registers.
+        See "Cell Broadband Engine Registers V1.3", section 3.3.2.1.  */
+
+      mfc_cq_dw0
+       = extract_unsigned_integer (buf + 32*seq[i], 8, byte_order);
+      mfc_cq_dw1
+       = extract_unsigned_integer (buf + 32*seq[i] + 8, 8, byte_order);
+      mfc_cq_dw2
+       = extract_unsigned_integer (buf + 32*seq[i] + 16, 8, byte_order);
+
+      list_lsa = spu_mfc_get_bitfield (mfc_cq_dw0, 0, 14);
+      list_size = spu_mfc_get_bitfield (mfc_cq_dw0, 15, 26);
+      mfc_cmd_opcode = spu_mfc_get_bitfield (mfc_cq_dw0, 27, 34);
+      mfc_cmd_tag = spu_mfc_get_bitfield (mfc_cq_dw0, 35, 39);
+      list_valid_p = spu_mfc_get_bitfield (mfc_cq_dw0, 40, 40);
+      rclass_id = spu_mfc_get_bitfield (mfc_cq_dw0, 41, 43);
+      tclass_id = spu_mfc_get_bitfield (mfc_cq_dw0, 44, 46);
+
+      mfc_ea = spu_mfc_get_bitfield (mfc_cq_dw1, 0, 51) << 12
+               | spu_mfc_get_bitfield (mfc_cq_dw2, 25, 36);
+
+      mfc_lsa = spu_mfc_get_bitfield (mfc_cq_dw2, 0, 13);
+      mfc_size = spu_mfc_get_bitfield (mfc_cq_dw2, 14, 24);
+      noop_valid_p = spu_mfc_get_bitfield (mfc_cq_dw2, 37, 37);
+      qw_valid_p = spu_mfc_get_bitfield (mfc_cq_dw2, 38, 38);
+      ea_valid_p = spu_mfc_get_bitfield (mfc_cq_dw2, 39, 39);
+      cmd_error_p = spu_mfc_get_bitfield (mfc_cq_dw2, 40, 40);
+
+      cmd_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "cmd");
+
+      if (spu_mfc_opcode[mfc_cmd_opcode])
+       ui_out_field_string (uiout, "opcode", spu_mfc_opcode[mfc_cmd_opcode]);
+      else
+       ui_out_field_int (uiout, "opcode", mfc_cmd_opcode);
+
+      ui_out_field_int (uiout, "tag", mfc_cmd_tag);
+      ui_out_field_int (uiout, "tid", tclass_id);
+      ui_out_field_int (uiout, "rid", rclass_id);
+
+      if (ea_valid_p)
+       ui_out_field_fmt (uiout, "ea", "0x%s", phex (mfc_ea, 8));
+      else
+       ui_out_field_skip (uiout, "ea");
+
+      ui_out_field_fmt (uiout, "lsa", "0x%05x", mfc_lsa << 4);
+      if (qw_valid_p)
+       ui_out_field_fmt (uiout, "size", "0x%05x", mfc_size << 4);
+      else
+       ui_out_field_fmt (uiout, "size", "0x%05x", mfc_size);
+
+      if (list_valid_p)
+       {
+         ui_out_field_fmt (uiout, "lstaddr", "0x%05x", list_lsa << 3);
+         ui_out_field_fmt (uiout, "lstsize", "0x%05x", list_size << 3);
+       }
+      else
+       {
+         ui_out_field_skip (uiout, "lstaddr");
+         ui_out_field_skip (uiout, "lstsize");
+       }
+
+      if (cmd_error_p)
+       ui_out_field_string (uiout, "error_p", "*");
+      else
+       ui_out_field_skip (uiout, "error_p");
+
+      do_cleanups (cmd_chain);
+
+      if (!ui_out_is_mi_like_p (uiout))
+       printf_filtered ("\n");
+    }
+
+  do_cleanups (chain);
+}
+
+static void
+info_spu_dma_command (char *args, int from_tty)
+{
+  struct frame_info *frame = get_selected_frame (NULL);
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  ULONGEST dma_info_type;
+  ULONGEST dma_info_mask;
+  ULONGEST dma_info_status;
+  ULONGEST dma_info_stall_and_notify;
+  ULONGEST dma_info_atomic_command_status;
+  struct cleanup *chain;
+  char annex[32];
+  gdb_byte buf[1024];
+  LONGEST len;
+  int i, id;
+
+  if (gdbarch_bfd_arch_info (get_frame_arch (frame))->arch != bfd_arch_spu)
+    error (_("\"info spu\" is only supported on the SPU architecture."));
+
+  id = get_frame_register_unsigned (frame, SPU_ID_REGNUM);
+
+  xsnprintf (annex, sizeof annex, "%d/dma_info", id);
+  len = target_read (&current_target, TARGET_OBJECT_SPU, annex,
+                    buf, 0, 40 + 16 * 32);
+  if (len <= 0)
+    error (_("Could not read dma_info."));
+
+  dma_info_type
+    = extract_unsigned_integer (buf, 8, byte_order);
+  dma_info_mask
+    = extract_unsigned_integer (buf + 8, 8, byte_order);
+  dma_info_status
+    = extract_unsigned_integer (buf + 16, 8, byte_order);
+  dma_info_stall_and_notify
+    = extract_unsigned_integer (buf + 24, 8, byte_order);
+  dma_info_atomic_command_status
+    = extract_unsigned_integer (buf + 32, 8, byte_order);
+  
+  chain = make_cleanup_ui_out_tuple_begin_end (uiout, "SPUInfoDMA");
+
+  if (ui_out_is_mi_like_p (uiout))
+    {
+      ui_out_field_fmt (uiout, "dma_info_type", "0x%s",
+                       phex_nz (dma_info_type, 4));
+      ui_out_field_fmt (uiout, "dma_info_mask", "0x%s",
+                       phex_nz (dma_info_mask, 4));
+      ui_out_field_fmt (uiout, "dma_info_status", "0x%s",
+                       phex_nz (dma_info_status, 4));
+      ui_out_field_fmt (uiout, "dma_info_stall_and_notify", "0x%s",
+                       phex_nz (dma_info_stall_and_notify, 4));
+      ui_out_field_fmt (uiout, "dma_info_atomic_command_status", "0x%s",
+                       phex_nz (dma_info_atomic_command_status, 4));
     }
   else
-    remove_single_step_breakpoints ();
+    {
+      const char *query_msg = _("no query pending");
+
+      if (dma_info_type & 4)
+       switch (dma_info_type & 3)
+         {
+           case 1: query_msg = _("'any' query pending"); break;
+           case 2: query_msg = _("'all' query pending"); break;
+           default: query_msg = _("undefined query type"); break;
+         }
+
+      printf_filtered (_("Tag-Group Status  0x%s\n"),
+                      phex (dma_info_status, 4));
+      printf_filtered (_("Tag-Group Mask    0x%s (%s)\n"),
+                      phex (dma_info_mask, 4), query_msg);
+      printf_filtered (_("Stall-and-Notify  0x%s\n"),
+                      phex (dma_info_stall_and_notify, 4));
+      printf_filtered (_("Atomic Cmd Status 0x%s\n"),
+                      phex (dma_info_atomic_command_status, 4));
+      printf_filtered ("\n");
+    }
+
+  info_spu_dma_cmdlist (buf + 40, 16, byte_order);
+  do_cleanups (chain);
+}
+
+static void
+info_spu_proxydma_command (char *args, int from_tty)
+{
+  struct frame_info *frame = get_selected_frame (NULL);
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  ULONGEST dma_info_type;
+  ULONGEST dma_info_mask;
+  ULONGEST dma_info_status;
+  struct cleanup *chain;
+  char annex[32];
+  gdb_byte buf[1024];
+  LONGEST len;
+  int i, id;
+
+  if (gdbarch_bfd_arch_info (gdbarch)->arch != bfd_arch_spu)
+    error (_("\"info spu\" is only supported on the SPU architecture."));
+
+  id = get_frame_register_unsigned (frame, SPU_ID_REGNUM);
+
+  xsnprintf (annex, sizeof annex, "%d/proxydma_info", id);
+  len = target_read (&current_target, TARGET_OBJECT_SPU, annex,
+                    buf, 0, 24 + 8 * 32);
+  if (len <= 0)
+    error (_("Could not read proxydma_info."));
+
+  dma_info_type = extract_unsigned_integer (buf, 8, byte_order);
+  dma_info_mask = extract_unsigned_integer (buf + 8, 8, byte_order);
+  dma_info_status = extract_unsigned_integer (buf + 16, 8, byte_order);
+  
+  chain = make_cleanup_ui_out_tuple_begin_end (uiout, "SPUInfoProxyDMA");
+
+  if (ui_out_is_mi_like_p (uiout))
+    {
+      ui_out_field_fmt (uiout, "proxydma_info_type", "0x%s",
+                       phex_nz (dma_info_type, 4));
+      ui_out_field_fmt (uiout, "proxydma_info_mask", "0x%s",
+                       phex_nz (dma_info_mask, 4));
+      ui_out_field_fmt (uiout, "proxydma_info_status", "0x%s",
+                       phex_nz (dma_info_status, 4));
+    }
+  else
+    {
+      const char *query_msg;
+
+      switch (dma_info_type & 3)
+       {
+       case 0: query_msg = _("no query pending"); break;
+       case 1: query_msg = _("'any' query pending"); break;
+       case 2: query_msg = _("'all' query pending"); break;
+       default: query_msg = _("undefined query type"); break;
+       }
+
+      printf_filtered (_("Tag-Group Status  0x%s\n"),
+                      phex (dma_info_status, 4));
+      printf_filtered (_("Tag-Group Mask    0x%s (%s)\n"),
+                      phex (dma_info_mask, 4), query_msg);
+      printf_filtered ("\n");
+    }
+
+  info_spu_dma_cmdlist (buf + 24, 8, byte_order);
+  do_cleanups (chain);
+}
+
+static void
+info_spu_command (char *args, int from_tty)
+{
+  printf_unfiltered (_("\"info spu\" must be followed by the name of an SPU facility.\n"));
+  help_list (infospucmdlist, "info spu ", -1, gdb_stdout);
 }
 
 
@@ -1014,6 +2136,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);
@@ -1025,7 +2148,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);
@@ -1035,6 +2159,8 @@ spu_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_num_pseudo_regs (gdbarch, SPU_NUM_PSEUDO_REGS);
   set_gdbarch_sp_regnum (gdbarch, SPU_SP_REGNUM);
   set_gdbarch_pc_regnum (gdbarch, SPU_PC_REGNUM);
+  set_gdbarch_read_pc (gdbarch, spu_read_pc);
+  set_gdbarch_write_pc (gdbarch, spu_write_pc);
   set_gdbarch_register_name (gdbarch, spu_register_name);
   set_gdbarch_register_type (gdbarch, spu_register_type);
   set_gdbarch_pseudo_register_read (gdbarch, spu_pseudo_register_read);
@@ -1057,55 +2183,74 @@ 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_frame_red_zone_size (gdbarch, 2000);
+  set_gdbarch_push_dummy_code (gdbarch, spu_push_dummy_code);
   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);
   set_gdbarch_virtual_frame_pointer (gdbarch, spu_virtual_frame_pointer);
   set_gdbarch_frame_args_skip (gdbarch, 0);
   set_gdbarch_skip_prologue (gdbarch, spu_skip_prologue);
+  set_gdbarch_in_function_epilogue_p (gdbarch, spu_in_function_epilogue_p);
 
   /* Breakpoints.  */
   set_gdbarch_decr_pc_after_break (gdbarch, 4);
   set_gdbarch_breakpoint_from_pc (gdbarch, spu_breakpoint_from_pc);
   set_gdbarch_cannot_step_breakpoint (gdbarch, 1);
   set_gdbarch_software_single_step (gdbarch, spu_software_single_step);
+  set_gdbarch_get_longjmp_target (gdbarch, spu_get_longjmp_target);
+
+  /* Overlays.  */
+  set_gdbarch_overlay_update (gdbarch, spu_overlay_update);
 
   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;
-}
+/* Provide a prototype to silence -Wmissing-prototypes.  */
+extern initialize_file_ftype _initialize_spu_tdep;
 
 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 ();
+
+  /* Add root prefix command for all "info spu" commands.  */
+  add_prefix_cmd ("spu", class_info, info_spu_command,
+                 _("Various SPU specific commands."),
+                 &infospucmdlist, "info spu ", 0, &infolist);
+
+  /* Add various "info spu" commands.  */
+  add_cmd ("event", class_info, info_spu_event_command,
+          _("Display SPU event facility status.\n"),
+          &infospucmdlist);
+  add_cmd ("signal", class_info, info_spu_signal_command,
+          _("Display SPU signal notification facility status.\n"),
+          &infospucmdlist);
+  add_cmd ("mailbox", class_info, info_spu_mailbox_command,
+          _("Display SPU mailbox facility status.\n"),
+          &infospucmdlist);
+  add_cmd ("dma", class_info, info_spu_dma_command,
+          _("Display MFC DMA status.\n"),
+          &infospucmdlist);
+  add_cmd ("proxydma", class_info, info_spu_proxydma_command,
+          _("Display MFC Proxy-DMA status.\n"),
+          &infospucmdlist);
 }
This page took 0.046199 seconds and 4 git commands to generate.