]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/gdbserver/spu-low.c
Remove pid_to_ptid
[thirdparty/binutils-gdb.git] / gdb / gdbserver / spu-low.c
index a7b7a614894bb6f372d5841bcb09e6f22e9e03ea..8a221a2c6cdc93a46d758b0c37fa749c3596e51a 100644 (file)
@@ -1,5 +1,5 @@
 /* Low level interface to SPUs, for the remote server for GDB.
-   Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2006-2018 Free Software Foundation, Inc.
 
    Contributed by Ulrich Weigand <uweigand@de.ibm.com>.
 
@@ -7,7 +7,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,
    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 "server.h"
 
-#include <sys/wait.h>
-#include <stdio.h>
+#include "gdb_wait.h"
 #include <sys/ptrace.h>
 #include <fcntl.h>
-#include <string.h>
-#include <stdlib.h>
 #include <unistd.h>
-#include <errno.h>
 #include <sys/syscall.h>
+#include "filestuff.h"
+#include "hostio.h"
+#include "nat/fork-inferior.h"
 
 /* Some older glibc versions do not define this.  */
 #ifndef __WNOTHREAD
 #define __WNOTHREAD     0x20000000      /* Don't wait on children of other
-                                          threads in this group */
+                                          threads in this group */
 #endif
 
 #define PTRACE_TYPE_RET long
 #define INSTR_SC       0x44000002
 #define NR_spu_run     0x0116
 
-/* Get current thread ID (Linux task ID).  */
-#define current_tid ((struct inferior_list_entry *)current_inferior)->id
-
 /* These are used in remote-utils.c.  */
 int using_threads = 0;
-int debug_threads = 0;
 
+/* Defined in auto-generated file reg-spu.c.  */
+void init_registers_spu (void);
+extern const struct target_desc *tdesc_spu;
+
+/* Software breakpoint instruction.  */
+static const gdb_byte breakpoint[] = { 0x00, 0x00, 0x3f, 0xff };
 
 /* Fetch PPU register REGNO.  */
 static CORE_ADDR
@@ -67,7 +66,7 @@ fetch_ppc_register (int regno)
 {
   PTRACE_TYPE_RET res;
 
-  int tid = current_tid;
+  int tid = ptid_get_lwp (current_ptid);
 
 #ifndef __powerpc64__
   /* If running as a 32-bit process on a 64-bit system, we attempt
@@ -78,10 +77,10 @@ fetch_ppc_register (int regno)
     char buf[8];
 
     errno = 0;
-    ptrace (PPC_PTRACE_PEEKUSR_3264, tid,
+    ptrace ((PTRACE_TYPE_ARG1) PPC_PTRACE_PEEKUSR_3264, tid,
            (PTRACE_TYPE_ARG3) (regno * 8), buf);
     if (errno == 0)
-      ptrace (PPC_PTRACE_PEEKUSR_3264, tid,
+      ptrace ((PTRACE_TYPE_ARG1) PPC_PTRACE_PEEKUSR_3264, tid,
              (PTRACE_TYPE_ARG3) (regno * 8 + 4), buf + 4);
     if (errno == 0)
       return (CORE_ADDR) *(unsigned long long *)buf;
@@ -90,7 +89,7 @@ fetch_ppc_register (int regno)
 
   errno = 0;
   res = ptrace (PT_READ_U, tid,
-               (PTRACE_TYPE_ARG3) (regno * sizeof (PTRACE_TYPE_RET)), 0);
+               (PTRACE_TYPE_ARG3) (regno * sizeof (PTRACE_TYPE_RET)), 0);
   if (errno != 0)
     {
       char mess[128];
@@ -111,7 +110,8 @@ fetch_ppc_memory_1 (int tid, CORE_ADDR memaddr, PTRACE_TYPE_RET *word)
   if (memaddr >> 32)
     {
       unsigned long long addr_8 = (unsigned long long) memaddr;
-      ptrace (PPC_PTRACE_PEEKTEXT_3264, tid, (PTRACE_TYPE_ARG3) &addr_8, word);
+      ptrace ((PTRACE_TYPE_ARG1) PPC_PTRACE_PEEKTEXT_3264, tid,
+             (PTRACE_TYPE_ARG3) &addr_8, word);
     }
   else
 #endif
@@ -130,7 +130,8 @@ store_ppc_memory_1 (int tid, CORE_ADDR memaddr, PTRACE_TYPE_RET word)
   if (memaddr >> 32)
     {
       unsigned long long addr_8 = (unsigned long long) memaddr;
-      ptrace (PPC_PTRACE_POKEDATA_3264, tid, (PTRACE_TYPE_ARG3) &addr_8, word);
+      ptrace ((PTRACE_TYPE_ARG1) PPC_PTRACE_POKEDATA_3264, tid,
+             (PTRACE_TYPE_ARG3) &addr_8, word);
     }
   else
 #endif
@@ -150,9 +151,9 @@ fetch_ppc_memory (CORE_ADDR memaddr, char *myaddr, int len)
               / sizeof (PTRACE_TYPE_RET));
   PTRACE_TYPE_RET *buffer;
 
-  int tid = current_tid;
+  int tid = ptid_get_lwp (current_ptid);
 
-  buffer = (PTRACE_TYPE_RET *) alloca (count * sizeof (PTRACE_TYPE_RET));
+  buffer = XALLOCAVEC (PTRACE_TYPE_RET, count);
   for (i = 0; i < count; i++, addr += sizeof (PTRACE_TYPE_RET))
     if ((ret = fetch_ppc_memory_1 (tid, addr, &buffer[i])) != 0)
       return ret;
@@ -175,9 +176,9 @@ store_ppc_memory (CORE_ADDR memaddr, char *myaddr, int len)
               / sizeof (PTRACE_TYPE_RET));
   PTRACE_TYPE_RET *buffer;
 
-  int tid = current_tid;
+  int tid = ptid_get_lwp (current_ptid);
 
-  buffer = (PTRACE_TYPE_RET *) alloca (count * sizeof (PTRACE_TYPE_RET));
+  buffer = XALLOCAVEC (PTRACE_TYPE_RET, count);
 
   if (addr != memaddr || len < (int) sizeof (PTRACE_TYPE_RET))
     if ((ret = fetch_ppc_memory_1 (tid, addr, &buffer[0])) != 0)
@@ -190,7 +191,7 @@ store_ppc_memory (CORE_ADDR memaddr, char *myaddr, int len)
       return ret;
 
   memcpy ((char *) buffer + (memaddr & (sizeof (PTRACE_TYPE_RET) - 1)),
-          myaddr, len);
+         myaddr, len);
 
   for (i = 0; i < count; i++, addr += sizeof (PTRACE_TYPE_RET))
     if ((ret = store_ppc_memory_1 (tid, addr, buffer[i])) != 0)
@@ -203,17 +204,17 @@ store_ppc_memory (CORE_ADDR memaddr, char *myaddr, int len)
 /* If the PPU thread is currently stopped on a spu_run system call,
    return to FD and ADDR the file handle and NPC parameter address
    used with the system call.  Return non-zero if successful.  */
-static int 
+static int
 parse_spufs_run (int *fd, CORE_ADDR *addr)
 {
-  char buf[4];
+  unsigned int insn;
   CORE_ADDR pc = fetch_ppc_register (32);  /* nip */
 
   /* Fetch instruction preceding current NIP.  */
-  if (fetch_ppc_memory (pc-4, buf, 4) != 0)
+  if (fetch_ppc_memory (pc-4, (char *) &insn, 4) != 0)
     return 0;
   /* It should be a "sc" instruction.  */
-  if (*(unsigned int *)buf != INSTR_SC)
+  if (insn != INSTR_SC)
     return 0;
   /* System call number should be NR_spu_run.  */
   if (fetch_ppc_register (0) != NR_spu_run)
@@ -240,7 +241,7 @@ spu_proc_xfer_spu (const char *annex, unsigned char *readbuf,
   if (!annex)
     return 0;
 
-  sprintf (buf, "/proc/%ld/fd/%s", current_tid, annex);
+  sprintf (buf, "/proc/%ld/fd/%s", ptid_get_lwp (current_ptid), annex);
   fd = open (buf, writebuf? O_WRONLY : O_RDONLY);
   if (fd <= 0)
     return -1;
@@ -249,7 +250,7 @@ spu_proc_xfer_spu (const char *annex, unsigned char *readbuf,
       && lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset)
     {
       close (fd);
-      return -1;
+      return 0;
     }
 
   if (writebuf)
@@ -261,33 +262,43 @@ spu_proc_xfer_spu (const char *annex, unsigned char *readbuf,
   return ret;
 }
 
+/* Callback to be used when calling fork_inferior, responsible for
+   actually initiating the tracing of the inferior.  */
+
+static void
+spu_ptrace_fun ()
+{
+  if (ptrace (PTRACE_TRACEME, 0, 0, 0) < 0)
+    trace_start_error_with_name ("ptrace");
+  if (setpgid (0, 0) < 0)
+    trace_start_error_with_name ("setpgid");
+}
 
 /* Start an inferior process and returns its pid.
-   ALLARGS is a vector of program-name and args. */
+   PROGRAM is the name of the program to be started, and PROGRAM_ARGS
+   are its arguments.  */
+
 static int
-spu_create_inferior (char *program, char **allargs)
+spu_create_inferior (const char *program,
+                    const std::vector<char *> &program_args)
 {
   int pid;
+  ptid_t ptid;
+  struct process_info *proc;
+  std::string str_program_args = stringify_argv (program_args);
 
-  pid = fork ();
-  if (pid < 0)
-    perror_with_name ("fork");
-
-  if (pid == 0)
-    {
-      ptrace (PTRACE_TRACEME, 0, 0, 0);
-
-      setpgid (0, 0);
+  pid = fork_inferior (program,
+                      str_program_args.c_str (),
+                      get_environ ()->envp (), spu_ptrace_fun,
+                      NULL, NULL, NULL, NULL);
 
-      execv (program, allargs);
+  post_fork_inferior (pid, program);
 
-      fprintf (stderr, "Cannot exec %s: %s.\n", program,
-              strerror (errno));
-      fflush (stderr);
-      _exit (0177);
-    }
+  proc = add_process (pid, 0);
+  proc->tdesc = tdesc_spu;
 
-  add_thread (pid, NULL, pid);
+  ptid = ptid_t (pid, pid, 0);
+  add_thread (ptid, NULL);
   return pid;
 }
 
@@ -295,6 +306,9 @@ spu_create_inferior (char *program, char **allargs)
 int
 spu_attach (unsigned long  pid)
 {
+  ptid_t ptid;
+  struct process_info *proc;
+
   if (ptrace (PTRACE_ATTACH, pid, 0, 0) != 0)
     {
       fprintf (stderr, "Cannot attach to process %ld: %s (%d)\n", pid,
@@ -303,72 +317,114 @@ spu_attach (unsigned long  pid)
       _exit (0177);
     }
 
-  add_thread (pid, NULL, pid);
+  proc = add_process (pid, 1);
+  proc->tdesc = tdesc_spu;
+  ptid = ptid_t (pid, pid, 0);
+  add_thread (ptid, NULL);
   return 0;
 }
 
 /* Kill the inferior process.  */
-static void
-spu_kill (void)
+static int
+spu_kill (int pid)
 {
-  ptrace (PTRACE_KILL, current_tid, 0, 0);
+  int status, ret;
+  struct process_info *process = find_process_pid (pid);
+  if (process == NULL)
+    return -1;
+
+  ptrace (PTRACE_KILL, pid, 0, 0);
+
+  do {
+    ret = waitpid (pid, &status, 0);
+    if (WIFEXITED (status) || WIFSIGNALED (status))
+      break;
+  } while (ret != -1 || errno != ECHILD);
+
+  clear_inferiors ();
+  remove_process (process);
+  return 0;
 }
 
 /* Detach from inferior process.  */
+static int
+spu_detach (int pid)
+{
+  struct process_info *process = find_process_pid (pid);
+  if (process == NULL)
+    return -1;
+
+  ptrace (PTRACE_DETACH, pid, 0, 0);
+
+  clear_inferiors ();
+  remove_process (process);
+  return 0;
+}
+
 static void
-spu_detach (void)
+spu_mourn (struct process_info *process)
 {
-  ptrace (PTRACE_DETACH, current_tid, 0, 0);
+  remove_process (process);
+}
+
+static void
+spu_join (int pid)
+{
+  int status, ret;
+
+  do {
+    ret = waitpid (pid, &status, 0);
+    if (WIFEXITED (status) || WIFSIGNALED (status))
+      break;
+  } while (ret != -1 || errno != ECHILD);
 }
 
 /* Return nonzero if the given thread is still alive.  */
 static int
-spu_thread_alive (unsigned long tid)
+spu_thread_alive (ptid_t ptid)
 {
-  return tid == current_tid;
+  return ptid_equal (ptid, current_ptid);
 }
 
 /* Resume process.  */
 static void
-spu_resume (struct thread_resume *resume_info)
+spu_resume (struct thread_resume *resume_info, size_t n)
 {
-  while (resume_info->thread != -1
-        && resume_info->thread != current_tid)
-    resume_info++;
+  struct thread_info *thr = get_first_thread ();
+  size_t i;
 
-  block_async_io ();
-  enable_async_io ();
+  for (i = 0; i < n; i++)
+    if (ptid_equal (resume_info[i].thread, minus_one_ptid)
+       || ptid_equal (resume_info[i].thread, ptid_of (thr)))
+      break;
 
-  if (resume_info->leave_stopped)
+  if (i == n)
     return;
 
   /* We don't support hardware single-stepping right now, assume
      GDB knows to use software single-stepping.  */
-  if (resume_info->step)
+  if (resume_info[i].kind == resume_step)
     fprintf (stderr, "Hardware single-step not supported.\n");
 
   regcache_invalidate ();
 
   errno = 0;
-  ptrace (PTRACE_CONT, current_tid, 0, resume_info->sig);
+  ptrace (PTRACE_CONT, ptid_get_lwp (ptid_of (thr)), 0, resume_info[i].sig);
   if (errno)
     perror_with_name ("ptrace");
 }
 
 /* Wait for process, returns status.  */
-static unsigned char
-spu_wait (char *status)
+static ptid_t
+spu_wait (ptid_t ptid, struct target_waitstatus *ourstatus, int options)
 {
-  int tid = current_tid;
+  int pid = ptid_get_pid (ptid);
   int w;
   int ret;
 
-  enable_async_io ();
-  unblock_async_io ();
-
   while (1)
     {
-      ret = waitpid (tid, &w, WNOHANG | __WALL | __WNOTHREAD);
+      ret = waitpid (pid, &w, WNOHANG | __WALL | __WNOTHREAD);
 
       if (ret == -1)
        {
@@ -390,65 +446,63 @@ spu_wait (char *status)
 
       while (!parse_spufs_run (&fd, &addr))
        {
-         ptrace (PT_SYSCALL, tid, (PTRACE_TYPE_ARG3) 0, 0);
-         waitpid (tid, NULL, __WALL | __WNOTHREAD);
+         ptrace (PT_SYSCALL, pid, (PTRACE_TYPE_ARG3) 0, 0);
+         waitpid (pid, NULL, __WALL | __WNOTHREAD);
        }
     }
 
-  disable_async_io ();
-
   if (WIFEXITED (w))
     {
       fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w));
-      *status = 'W';
+      ourstatus->kind =  TARGET_WAITKIND_EXITED;
+      ourstatus->value.integer = WEXITSTATUS (w);
       clear_inferiors ();
-      return ((unsigned char) WEXITSTATUS (w));
+      return ptid_t (ret);
     }
   else if (!WIFSTOPPED (w))
     {
       fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w));
-      *status = 'X';
+      ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
+      ourstatus->value.sig = gdb_signal_from_host (WTERMSIG (w));
       clear_inferiors ();
-      return ((unsigned char) WTERMSIG (w));
+      return ptid_t (ret);
     }
 
   /* After attach, we may have received a SIGSTOP.  Do not return this
      as signal to GDB, or else it will try to continue with SIGSTOP ...  */
   if (!server_waiting)
     {
-      *status = 'T';
-      return 0;
+      ourstatus->kind = TARGET_WAITKIND_STOPPED;
+      ourstatus->value.sig = GDB_SIGNAL_0;
+      return ptid_t (ret, ret, 0);
     }
 
-  *status = 'T';
-  return ((unsigned char) WSTOPSIG (w));
+  ourstatus->kind = TARGET_WAITKIND_STOPPED;
+  ourstatus->value.sig = gdb_signal_from_host (WSTOPSIG (w));
+  return ptid_t (ret, ret, 0);
 }
 
 /* Fetch inferior registers.  */
 static void
-spu_fetch_registers (int regno)
+spu_fetch_registers (struct regcache *regcache, int regno)
 {
   int fd;
   CORE_ADDR addr;
 
-  /* ??? Some callers use 0 to mean all registers.  */
-  if (regno == 0)
-    regno = -1;
-
   /* We must be stopped on a spu_run system call.  */
   if (!parse_spufs_run (&fd, &addr))
     return;
 
   /* The ID register holds the spufs file handle.  */
   if (regno == -1 || regno == SPU_ID_REGNUM)
-    supply_register (SPU_ID_REGNUM, (char *)&fd);
+    supply_register (regcache, SPU_ID_REGNUM, (char *)&fd);
 
   /* The NPC register is found at ADDR.  */
   if (regno == -1 || regno == SPU_PC_REGNUM)
     {
       char buf[4];
       if (fetch_ppc_memory (addr, buf, 4) == 0)
-       supply_register (SPU_PC_REGNUM, buf);
+       supply_register (regcache, SPU_PC_REGNUM, buf);
     }
 
   /* The GPRs are found in the "regs" spufs file.  */
@@ -461,13 +515,13 @@ spu_fetch_registers (int regno)
       sprintf (annex, "%d/regs", fd);
       if (spu_proc_xfer_spu (annex, buf, NULL, 0, sizeof buf) == sizeof buf)
        for (i = 0; i < SPU_NUM_CORE_REGS; i++)
-         supply_register (i, buf + i*16);
+         supply_register (regcache, i, buf + i*16);
     }
 }
 
 /* Store inferior registers.  */
 static void
-spu_store_registers (int regno)
+spu_store_registers (struct regcache *regcache, int regno)
 {
   int fd;
   CORE_ADDR addr;
@@ -484,7 +538,7 @@ spu_store_registers (int regno)
   if (regno == -1 || regno == SPU_PC_REGNUM)
     {
       char buf[4];
-      collect_register (SPU_PC_REGNUM, buf);
+      collect_register (regcache, SPU_PC_REGNUM, buf);
       store_ppc_memory (addr, buf, 4);
     }
 
@@ -496,7 +550,7 @@ spu_store_registers (int regno)
       int i;
 
       for (i = 0; i < SPU_NUM_CORE_REGS; i++)
-       collect_register (i, buf + i*16);
+       collect_register (regcache, i, buf + i*16);
 
       sprintf (annex, "%d/regs", fd);
       spu_proc_xfer_spu (annex, NULL, buf, 0, sizeof buf);
@@ -510,7 +564,8 @@ spu_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
 {
   int fd, ret;
   CORE_ADDR addr;
-  char annex[32];
+  char annex[32], lslr_annex[32], buf[32];
+  CORE_ADDR lslr;
 
   /* We must be stopped on a spu_run system call.  */
   if (!parse_spufs_run (&fd, &addr))
@@ -519,6 +574,22 @@ spu_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
   /* Use the "mem" spufs file to access SPU local store.  */
   sprintf (annex, "%d/mem", fd);
   ret = spu_proc_xfer_spu (annex, myaddr, NULL, memaddr, len);
+  if (ret > 0)
+    return ret == len ? 0 : EIO;
+
+  /* SPU local store access wraps the address around at the
+     local store limit.  We emulate this here.  To avoid needing
+     an extra access to retrieve the LSLR, we only do that after
+     trying the original address first, and getting end-of-file.  */
+  sprintf (lslr_annex, "%d/lslr", fd);
+  memset (buf, 0, sizeof buf);
+  if (spu_proc_xfer_spu (lslr_annex, (unsigned char *)buf, NULL,
+                        0, sizeof buf) <= 0)
+    return ret;
+
+  lslr = strtoul (buf, NULL, 16);
+  ret = spu_proc_xfer_spu (annex, myaddr, NULL, memaddr & lslr, len);
+
   return ret == len ? 0 : EIO;
 }
 
@@ -531,7 +602,8 @@ spu_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
 {
   int fd, ret;
   CORE_ADDR addr;
-  char annex[32];
+  char annex[32], lslr_annex[32], buf[32];
+  CORE_ADDR lslr;
 
   /* We must be stopped on a spu_run system call.  */
   if (!parse_spufs_run (&fd, &addr))
@@ -540,6 +612,22 @@ spu_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
   /* Use the "mem" spufs file to access SPU local store.  */
   sprintf (annex, "%d/mem", fd);
   ret = spu_proc_xfer_spu (annex, NULL, myaddr, memaddr, len);
+  if (ret > 0)
+    return ret == len ? 0 : EIO;
+
+  /* SPU local store access wraps the address around at the
+     local store limit.  We emulate this here.  To avoid needing
+     an extra access to retrieve the LSLR, we only do that after
+     trying the original address first, and getting end-of-file.  */
+  sprintf (lslr_annex, "%d/lslr", fd);
+  memset (buf, 0, sizeof buf);
+  if (spu_proc_xfer_spu (lslr_annex, (unsigned char *)buf, NULL,
+                        0, sizeof buf) <= 0)
+    return ret;
+
+  lslr = strtoul (buf, NULL, 16);
+  ret = spu_proc_xfer_spu (annex, NULL, myaddr, memaddr & lslr, len);
+
   return ret == len ? 0 : EIO;
 }
 
@@ -551,35 +639,100 @@ spu_look_up_symbols (void)
 
 /* Send signal to inferior.  */
 static void
-spu_send_signal (int signo)
+spu_request_interrupt (void)
+{
+  struct thread_info *thr = get_first_thread ();
+
+  syscall (SYS_tkill, lwpid_of (thr), SIGINT);
+}
+
+/* Implementation of the target_ops method "sw_breakpoint_from_kind".  */
+
+static const gdb_byte *
+spu_sw_breakpoint_from_kind (int kind, int *size)
 {
-  syscall (SYS_tkill, current_tid, signo);
+  *size = sizeof breakpoint;
+  return breakpoint;
 }
 
-\f
 static struct target_ops spu_target_ops = {
   spu_create_inferior,
+  NULL,  /* post_create_inferior */
   spu_attach,
   spu_kill,
   spu_detach,
+  spu_mourn,
+  spu_join,
   spu_thread_alive,
   spu_resume,
   spu_wait,
   spu_fetch_registers,
   spu_store_registers,
+  NULL, /* prepare_to_access_memory */
+  NULL, /* done_accessing_memory */
   spu_read_memory,
   spu_write_memory,
   spu_look_up_symbols,
-  spu_send_signal,
+  spu_request_interrupt,
   NULL,
+  NULL,  /* supports_z_point_type */
+  NULL,
+  NULL,
+  NULL, /* stopped_by_sw_breakpoint */
+  NULL, /* supports_stopped_by_sw_breakpoint */
+  NULL, /* stopped_by_hw_breakpoint */
+  NULL, /* supports_stopped_by_hw_breakpoint */
+  NULL, /* supports_hardware_single_step */
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  spu_proc_xfer_spu,
+  hostio_last_error_from_errno,
+  NULL, /* qxfer_osdata */
+  NULL, /* qxfer_siginfo */
+  NULL, /* supports_non_stop */
+  NULL, /* async */
+  NULL, /* start_non_stop */
+  NULL, /* supports_multi_process */
+  NULL, /* supports_fork_events */
+  NULL, /* supports_vfork_events */
+  NULL, /* supports_exec_events */
+  NULL, /* handle_new_gdb_connection */
+  NULL, /* handle_monitor_command */
+  NULL, /* core_of_thread */
+  NULL, /* read_loadmap */
+  NULL, /* process_qsupported */
+  NULL, /* supports_tracepoints */
+  NULL, /* read_pc */
+  NULL, /* write_pc */
+  NULL, /* thread_stopped */
+  NULL, /* get_tib_address */
+  NULL, /* pause_all */
+  NULL, /* unpause_all */
+  NULL, /* stabilize_threads */
+  NULL, /* install_fast_tracepoint_jump_pad */
+  NULL, /* emit_ops */
+  NULL, /* supports_disable_randomization */
+  NULL, /* get_min_fast_tracepoint_insn_len */
+  NULL, /* qxfer_libraries_svr4 */
+  NULL, /* support_agent */
+  NULL, /* enable_btrace */
+  NULL, /* disable_btrace */
+  NULL, /* read_btrace */
+  NULL, /* read_btrace_conf */
+  NULL, /* supports_range_stepping */
+  NULL, /* pid_to_exec_file */
+  NULL, /* multifs_open */
+  NULL, /* multifs_unlink */
+  NULL, /* multifs_readlink */
+  NULL, /* breakpoint_kind_from_pc */
+  spu_sw_breakpoint_from_kind,
 };
 
 void
 initialize_low (void)
 {
-  static const unsigned char breakpoint[] = { 0x00, 0x00, 0x3f, 0xff };
-
   set_target_ops (&spu_target_ops);
-  set_breakpoint_data (breakpoint, sizeof breakpoint);
-  init_registers ();
+  init_registers_spu ();
 }