OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-6.8/] [gdb/] [gdbserver/] [spu-low.c] - Diff between revs 827 and 840

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 827 Rev 840
/* Low level interface to SPUs, for the remote server for GDB.
/* Low level interface to SPUs, for the remote server for GDB.
   Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
   Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
 
 
   Contributed by Ulrich Weigand <uweigand@de.ibm.com>.
   Contributed by Ulrich Weigand <uweigand@de.ibm.com>.
 
 
   This file is part of GDB.
   This file is part of GDB.
 
 
   This program is free software; you can redistribute it and/or modify
   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
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.
   (at your option) any later version.
 
 
   This program is distributed in the hope that it will be useful,
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   GNU General Public License for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
#include "server.h"
#include "server.h"
 
 
#include <sys/wait.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdio.h>
#include <sys/ptrace.h>
#include <sys/ptrace.h>
#include <fcntl.h>
#include <fcntl.h>
#include <string.h>
#include <string.h>
#include <stdlib.h>
#include <stdlib.h>
#include <unistd.h>
#include <unistd.h>
#include <errno.h>
#include <errno.h>
#include <sys/syscall.h>
#include <sys/syscall.h>
 
 
/* Some older glibc versions do not define this.  */
/* Some older glibc versions do not define this.  */
#ifndef __WNOTHREAD
#ifndef __WNOTHREAD
#define __WNOTHREAD     0x20000000      /* Don't wait on children of other
#define __WNOTHREAD     0x20000000      /* Don't wait on children of other
                                           threads in this group */
                                           threads in this group */
#endif
#endif
 
 
#define PTRACE_TYPE_RET long
#define PTRACE_TYPE_RET long
#define PTRACE_TYPE_ARG3 long
#define PTRACE_TYPE_ARG3 long
 
 
/* Number of registers.  */
/* Number of registers.  */
#define SPU_NUM_REGS         130
#define SPU_NUM_REGS         130
#define SPU_NUM_CORE_REGS    128
#define SPU_NUM_CORE_REGS    128
 
 
/* Special registers.  */
/* Special registers.  */
#define SPU_ID_REGNUM        128
#define SPU_ID_REGNUM        128
#define SPU_PC_REGNUM        129
#define SPU_PC_REGNUM        129
 
 
/* PPU side system calls.  */
/* PPU side system calls.  */
#define INSTR_SC        0x44000002
#define INSTR_SC        0x44000002
#define NR_spu_run      0x0116
#define NR_spu_run      0x0116
 
 
/* Get current thread ID (Linux task ID).  */
/* Get current thread ID (Linux task ID).  */
#define current_tid ((struct inferior_list_entry *)current_inferior)->id
#define current_tid ((struct inferior_list_entry *)current_inferior)->id
 
 
/* These are used in remote-utils.c.  */
/* These are used in remote-utils.c.  */
int using_threads = 0;
int using_threads = 0;
 
 
 
 
/* Fetch PPU register REGNO.  */
/* Fetch PPU register REGNO.  */
static CORE_ADDR
static CORE_ADDR
fetch_ppc_register (int regno)
fetch_ppc_register (int regno)
{
{
  PTRACE_TYPE_RET res;
  PTRACE_TYPE_RET res;
 
 
  int tid = current_tid;
  int tid = current_tid;
 
 
#ifndef __powerpc64__
#ifndef __powerpc64__
  /* If running as a 32-bit process on a 64-bit system, we attempt
  /* If running as a 32-bit process on a 64-bit system, we attempt
     to get the full 64-bit register content of the target process.
     to get the full 64-bit register content of the target process.
     If the PPC special ptrace call fails, we're on a 32-bit system;
     If the PPC special ptrace call fails, we're on a 32-bit system;
     just fall through to the regular ptrace call in that case.  */
     just fall through to the regular ptrace call in that case.  */
  {
  {
    char buf[8];
    char buf[8];
 
 
    errno = 0;
    errno = 0;
    ptrace (PPC_PTRACE_PEEKUSR_3264, tid,
    ptrace (PPC_PTRACE_PEEKUSR_3264, tid,
            (PTRACE_TYPE_ARG3) (regno * 8), buf);
            (PTRACE_TYPE_ARG3) (regno * 8), buf);
    if (errno == 0)
    if (errno == 0)
      ptrace (PPC_PTRACE_PEEKUSR_3264, tid,
      ptrace (PPC_PTRACE_PEEKUSR_3264, tid,
              (PTRACE_TYPE_ARG3) (regno * 8 + 4), buf + 4);
              (PTRACE_TYPE_ARG3) (regno * 8 + 4), buf + 4);
    if (errno == 0)
    if (errno == 0)
      return (CORE_ADDR) *(unsigned long long *)buf;
      return (CORE_ADDR) *(unsigned long long *)buf;
  }
  }
#endif
#endif
 
 
  errno = 0;
  errno = 0;
  res = ptrace (PT_READ_U, tid,
  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)
  if (errno != 0)
    {
    {
      char mess[128];
      char mess[128];
      sprintf (mess, "reading PPC register #%d", regno);
      sprintf (mess, "reading PPC register #%d", regno);
      perror_with_name (mess);
      perror_with_name (mess);
    }
    }
 
 
  return (CORE_ADDR) (unsigned long) res;
  return (CORE_ADDR) (unsigned long) res;
}
}
 
 
/* Fetch WORD from PPU memory at (aligned) MEMADDR in thread TID.  */
/* Fetch WORD from PPU memory at (aligned) MEMADDR in thread TID.  */
static int
static int
fetch_ppc_memory_1 (int tid, CORE_ADDR memaddr, PTRACE_TYPE_RET *word)
fetch_ppc_memory_1 (int tid, CORE_ADDR memaddr, PTRACE_TYPE_RET *word)
{
{
  errno = 0;
  errno = 0;
 
 
#ifndef __powerpc64__
#ifndef __powerpc64__
  if (memaddr >> 32)
  if (memaddr >> 32)
    {
    {
      unsigned long long addr_8 = (unsigned long long) memaddr;
      unsigned long long addr_8 = (unsigned long long) memaddr;
      ptrace (PPC_PTRACE_PEEKTEXT_3264, tid, (PTRACE_TYPE_ARG3) &addr_8, word);
      ptrace (PPC_PTRACE_PEEKTEXT_3264, tid, (PTRACE_TYPE_ARG3) &addr_8, word);
    }
    }
  else
  else
#endif
#endif
    *word = ptrace (PT_READ_I, tid, (PTRACE_TYPE_ARG3) (size_t) memaddr, 0);
    *word = ptrace (PT_READ_I, tid, (PTRACE_TYPE_ARG3) (size_t) memaddr, 0);
 
 
  return errno;
  return errno;
}
}
 
 
/* Store WORD into PPU memory at (aligned) MEMADDR in thread TID.  */
/* Store WORD into PPU memory at (aligned) MEMADDR in thread TID.  */
static int
static int
store_ppc_memory_1 (int tid, CORE_ADDR memaddr, PTRACE_TYPE_RET word)
store_ppc_memory_1 (int tid, CORE_ADDR memaddr, PTRACE_TYPE_RET word)
{
{
  errno = 0;
  errno = 0;
 
 
#ifndef __powerpc64__
#ifndef __powerpc64__
  if (memaddr >> 32)
  if (memaddr >> 32)
    {
    {
      unsigned long long addr_8 = (unsigned long long) memaddr;
      unsigned long long addr_8 = (unsigned long long) memaddr;
      ptrace (PPC_PTRACE_POKEDATA_3264, tid, (PTRACE_TYPE_ARG3) &addr_8, word);
      ptrace (PPC_PTRACE_POKEDATA_3264, tid, (PTRACE_TYPE_ARG3) &addr_8, word);
    }
    }
  else
  else
#endif
#endif
    ptrace (PT_WRITE_D, tid, (PTRACE_TYPE_ARG3) (size_t) memaddr, word);
    ptrace (PT_WRITE_D, tid, (PTRACE_TYPE_ARG3) (size_t) memaddr, word);
 
 
  return errno;
  return errno;
}
}
 
 
/* Fetch LEN bytes of PPU memory at MEMADDR to MYADDR.  */
/* Fetch LEN bytes of PPU memory at MEMADDR to MYADDR.  */
static int
static int
fetch_ppc_memory (CORE_ADDR memaddr, char *myaddr, int len)
fetch_ppc_memory (CORE_ADDR memaddr, char *myaddr, int len)
{
{
  int i, ret;
  int i, ret;
 
 
  CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_TYPE_RET);
  CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_TYPE_RET);
  int count = ((((memaddr + len) - addr) + sizeof (PTRACE_TYPE_RET) - 1)
  int count = ((((memaddr + len) - addr) + sizeof (PTRACE_TYPE_RET) - 1)
               / sizeof (PTRACE_TYPE_RET));
               / sizeof (PTRACE_TYPE_RET));
  PTRACE_TYPE_RET *buffer;
  PTRACE_TYPE_RET *buffer;
 
 
  int tid = current_tid;
  int tid = current_tid;
 
 
  buffer = (PTRACE_TYPE_RET *) alloca (count * sizeof (PTRACE_TYPE_RET));
  buffer = (PTRACE_TYPE_RET *) alloca (count * sizeof (PTRACE_TYPE_RET));
  for (i = 0; i < count; i++, addr += sizeof (PTRACE_TYPE_RET))
  for (i = 0; i < count; i++, addr += sizeof (PTRACE_TYPE_RET))
    if ((ret = fetch_ppc_memory_1 (tid, addr, &buffer[i])) != 0)
    if ((ret = fetch_ppc_memory_1 (tid, addr, &buffer[i])) != 0)
      return ret;
      return ret;
 
 
  memcpy (myaddr,
  memcpy (myaddr,
          (char *) buffer + (memaddr & (sizeof (PTRACE_TYPE_RET) - 1)),
          (char *) buffer + (memaddr & (sizeof (PTRACE_TYPE_RET) - 1)),
          len);
          len);
 
 
  return 0;
  return 0;
}
}
 
 
/* Store LEN bytes from MYADDR to PPU memory at MEMADDR.  */
/* Store LEN bytes from MYADDR to PPU memory at MEMADDR.  */
static int
static int
store_ppc_memory (CORE_ADDR memaddr, char *myaddr, int len)
store_ppc_memory (CORE_ADDR memaddr, char *myaddr, int len)
{
{
  int i, ret;
  int i, ret;
 
 
  CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_TYPE_RET);
  CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_TYPE_RET);
  int count = ((((memaddr + len) - addr) + sizeof (PTRACE_TYPE_RET) - 1)
  int count = ((((memaddr + len) - addr) + sizeof (PTRACE_TYPE_RET) - 1)
               / sizeof (PTRACE_TYPE_RET));
               / sizeof (PTRACE_TYPE_RET));
  PTRACE_TYPE_RET *buffer;
  PTRACE_TYPE_RET *buffer;
 
 
  int tid = current_tid;
  int tid = current_tid;
 
 
  buffer = (PTRACE_TYPE_RET *) alloca (count * sizeof (PTRACE_TYPE_RET));
  buffer = (PTRACE_TYPE_RET *) alloca (count * sizeof (PTRACE_TYPE_RET));
 
 
  if (addr != memaddr || len < (int) sizeof (PTRACE_TYPE_RET))
  if (addr != memaddr || len < (int) sizeof (PTRACE_TYPE_RET))
    if ((ret = fetch_ppc_memory_1 (tid, addr, &buffer[0])) != 0)
    if ((ret = fetch_ppc_memory_1 (tid, addr, &buffer[0])) != 0)
      return ret;
      return ret;
 
 
  if (count > 1)
  if (count > 1)
    if ((ret = fetch_ppc_memory_1 (tid, addr + (count - 1)
    if ((ret = fetch_ppc_memory_1 (tid, addr + (count - 1)
                                               * sizeof (PTRACE_TYPE_RET),
                                               * sizeof (PTRACE_TYPE_RET),
                                   &buffer[count - 1])) != 0)
                                   &buffer[count - 1])) != 0)
      return ret;
      return ret;
 
 
  memcpy ((char *) buffer + (memaddr & (sizeof (PTRACE_TYPE_RET) - 1)),
  memcpy ((char *) buffer + (memaddr & (sizeof (PTRACE_TYPE_RET) - 1)),
          myaddr, len);
          myaddr, len);
 
 
  for (i = 0; i < count; i++, addr += sizeof (PTRACE_TYPE_RET))
  for (i = 0; i < count; i++, addr += sizeof (PTRACE_TYPE_RET))
    if ((ret = store_ppc_memory_1 (tid, addr, buffer[i])) != 0)
    if ((ret = store_ppc_memory_1 (tid, addr, buffer[i])) != 0)
      return ret;
      return ret;
 
 
  return 0;
  return 0;
}
}
 
 
 
 
/* If the PPU thread is currently stopped on a spu_run system call,
/* 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
   return to FD and ADDR the file handle and NPC parameter address
   used with the system call.  Return non-zero if successful.  */
   used with the system call.  Return non-zero if successful.  */
static int
static int
parse_spufs_run (int *fd, CORE_ADDR *addr)
parse_spufs_run (int *fd, CORE_ADDR *addr)
{
{
  char buf[4];
  char buf[4];
  CORE_ADDR pc = fetch_ppc_register (32);  /* nip */
  CORE_ADDR pc = fetch_ppc_register (32);  /* nip */
 
 
  /* Fetch instruction preceding current NIP.  */
  /* Fetch instruction preceding current NIP.  */
  if (fetch_ppc_memory (pc-4, buf, 4) != 0)
  if (fetch_ppc_memory (pc-4, buf, 4) != 0)
    return 0;
    return 0;
  /* It should be a "sc" instruction.  */
  /* It should be a "sc" instruction.  */
  if (*(unsigned int *)buf != INSTR_SC)
  if (*(unsigned int *)buf != INSTR_SC)
    return 0;
    return 0;
  /* System call number should be NR_spu_run.  */
  /* System call number should be NR_spu_run.  */
  if (fetch_ppc_register (0) != NR_spu_run)
  if (fetch_ppc_register (0) != NR_spu_run)
    return 0;
    return 0;
 
 
  /* Register 3 contains fd, register 4 the NPC param pointer.  */
  /* Register 3 contains fd, register 4 the NPC param pointer.  */
  *fd = fetch_ppc_register (34);  /* orig_gpr3 */
  *fd = fetch_ppc_register (34);  /* orig_gpr3 */
  *addr = fetch_ppc_register (4);
  *addr = fetch_ppc_register (4);
  return 1;
  return 1;
}
}
 
 
 
 
/* Copy LEN bytes at OFFSET in spufs file ANNEX into/from READBUF or WRITEBUF,
/* Copy LEN bytes at OFFSET in spufs file ANNEX into/from READBUF or WRITEBUF,
   using the /proc file system.  */
   using the /proc file system.  */
static int
static int
spu_proc_xfer_spu (const char *annex, unsigned char *readbuf,
spu_proc_xfer_spu (const char *annex, unsigned char *readbuf,
                   const unsigned char *writebuf,
                   const unsigned char *writebuf,
                   CORE_ADDR offset, int len)
                   CORE_ADDR offset, int len)
{
{
  char buf[128];
  char buf[128];
  int fd = 0;
  int fd = 0;
  int ret = -1;
  int ret = -1;
 
 
  if (!annex)
  if (!annex)
    return 0;
    return 0;
 
 
  sprintf (buf, "/proc/%ld/fd/%s", current_tid, annex);
  sprintf (buf, "/proc/%ld/fd/%s", current_tid, annex);
  fd = open (buf, writebuf? O_WRONLY : O_RDONLY);
  fd = open (buf, writebuf? O_WRONLY : O_RDONLY);
  if (fd <= 0)
  if (fd <= 0)
    return -1;
    return -1;
 
 
  if (offset != 0
  if (offset != 0
      && lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset)
      && lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset)
    {
    {
      close (fd);
      close (fd);
      return 0;
      return 0;
    }
    }
 
 
  if (writebuf)
  if (writebuf)
    ret = write (fd, writebuf, (size_t) len);
    ret = write (fd, writebuf, (size_t) len);
  else if (readbuf)
  else if (readbuf)
    ret = read (fd, readbuf, (size_t) len);
    ret = read (fd, readbuf, (size_t) len);
 
 
  close (fd);
  close (fd);
  return ret;
  return ret;
}
}
 
 
 
 
/* Start an inferior process and returns its pid.
/* Start an inferior process and returns its pid.
   ALLARGS is a vector of program-name and args. */
   ALLARGS is a vector of program-name and args. */
static int
static int
spu_create_inferior (char *program, char **allargs)
spu_create_inferior (char *program, char **allargs)
{
{
  int pid;
  int pid;
 
 
  pid = fork ();
  pid = fork ();
  if (pid < 0)
  if (pid < 0)
    perror_with_name ("fork");
    perror_with_name ("fork");
 
 
  if (pid == 0)
  if (pid == 0)
    {
    {
      ptrace (PTRACE_TRACEME, 0, 0, 0);
      ptrace (PTRACE_TRACEME, 0, 0, 0);
 
 
      setpgid (0, 0);
      setpgid (0, 0);
 
 
      execv (program, allargs);
      execv (program, allargs);
      if (errno == ENOENT)
      if (errno == ENOENT)
        execvp (program, allargs);
        execvp (program, allargs);
 
 
      fprintf (stderr, "Cannot exec %s: %s.\n", program,
      fprintf (stderr, "Cannot exec %s: %s.\n", program,
               strerror (errno));
               strerror (errno));
      fflush (stderr);
      fflush (stderr);
      _exit (0177);
      _exit (0177);
    }
    }
 
 
  add_thread (pid, NULL, pid);
  add_thread (pid, NULL, pid);
  return pid;
  return pid;
}
}
 
 
/* Attach to an inferior process.  */
/* Attach to an inferior process.  */
int
int
spu_attach (unsigned long  pid)
spu_attach (unsigned long  pid)
{
{
  if (ptrace (PTRACE_ATTACH, pid, 0, 0) != 0)
  if (ptrace (PTRACE_ATTACH, pid, 0, 0) != 0)
    {
    {
      fprintf (stderr, "Cannot attach to process %ld: %s (%d)\n", pid,
      fprintf (stderr, "Cannot attach to process %ld: %s (%d)\n", pid,
               strerror (errno), errno);
               strerror (errno), errno);
      fflush (stderr);
      fflush (stderr);
      _exit (0177);
      _exit (0177);
    }
    }
 
 
  add_thread (pid, NULL, pid);
  add_thread (pid, NULL, pid);
  return 0;
  return 0;
}
}
 
 
/* Kill the inferior process.  */
/* Kill the inferior process.  */
static void
static void
spu_kill (void)
spu_kill (void)
{
{
  ptrace (PTRACE_KILL, current_tid, 0, 0);
  ptrace (PTRACE_KILL, current_tid, 0, 0);
}
}
 
 
/* Detach from inferior process.  */
/* Detach from inferior process.  */
static int
static int
spu_detach (void)
spu_detach (void)
{
{
  ptrace (PTRACE_DETACH, current_tid, 0, 0);
  ptrace (PTRACE_DETACH, current_tid, 0, 0);
  return 0;
  return 0;
}
}
 
 
static void
static void
spu_join (void)
spu_join (void)
{
{
  int status, ret;
  int status, ret;
 
 
  do {
  do {
    ret = waitpid (current_tid, &status, 0);
    ret = waitpid (current_tid, &status, 0);
    if (WIFEXITED (status) || WIFSIGNALED (status))
    if (WIFEXITED (status) || WIFSIGNALED (status))
      break;
      break;
  } while (ret != -1 || errno != ECHILD);
  } while (ret != -1 || errno != ECHILD);
}
}
 
 
/* Return nonzero if the given thread is still alive.  */
/* Return nonzero if the given thread is still alive.  */
static int
static int
spu_thread_alive (unsigned long tid)
spu_thread_alive (unsigned long tid)
{
{
  return tid == current_tid;
  return tid == current_tid;
}
}
 
 
/* Resume process.  */
/* Resume process.  */
static void
static void
spu_resume (struct thread_resume *resume_info)
spu_resume (struct thread_resume *resume_info)
{
{
  while (resume_info->thread != -1
  while (resume_info->thread != -1
         && resume_info->thread != current_tid)
         && resume_info->thread != current_tid)
    resume_info++;
    resume_info++;
 
 
  if (resume_info->leave_stopped)
  if (resume_info->leave_stopped)
    return;
    return;
 
 
  /* We don't support hardware single-stepping right now, assume
  /* We don't support hardware single-stepping right now, assume
     GDB knows to use software single-stepping.  */
     GDB knows to use software single-stepping.  */
  if (resume_info->step)
  if (resume_info->step)
    fprintf (stderr, "Hardware single-step not supported.\n");
    fprintf (stderr, "Hardware single-step not supported.\n");
 
 
  regcache_invalidate ();
  regcache_invalidate ();
 
 
  errno = 0;
  errno = 0;
  ptrace (PTRACE_CONT, current_tid, 0, resume_info->sig);
  ptrace (PTRACE_CONT, current_tid, 0, resume_info->sig);
  if (errno)
  if (errno)
    perror_with_name ("ptrace");
    perror_with_name ("ptrace");
}
}
 
 
/* Wait for process, returns status.  */
/* Wait for process, returns status.  */
static unsigned char
static unsigned char
spu_wait (char *status)
spu_wait (char *status)
{
{
  int tid = current_tid;
  int tid = current_tid;
  int w;
  int w;
  int ret;
  int ret;
 
 
  while (1)
  while (1)
    {
    {
      ret = waitpid (tid, &w, WNOHANG | __WALL | __WNOTHREAD);
      ret = waitpid (tid, &w, WNOHANG | __WALL | __WNOTHREAD);
 
 
      if (ret == -1)
      if (ret == -1)
        {
        {
          if (errno != ECHILD)
          if (errno != ECHILD)
            perror_with_name ("waitpid");
            perror_with_name ("waitpid");
        }
        }
      else if (ret > 0)
      else if (ret > 0)
        break;
        break;
 
 
      usleep (1000);
      usleep (1000);
    }
    }
 
 
  /* On the first wait, continue running the inferior until we are
  /* On the first wait, continue running the inferior until we are
     blocked inside an spu_run system call.  */
     blocked inside an spu_run system call.  */
  if (!server_waiting)
  if (!server_waiting)
    {
    {
      int fd;
      int fd;
      CORE_ADDR addr;
      CORE_ADDR addr;
 
 
      while (!parse_spufs_run (&fd, &addr))
      while (!parse_spufs_run (&fd, &addr))
        {
        {
          ptrace (PT_SYSCALL, tid, (PTRACE_TYPE_ARG3) 0, 0);
          ptrace (PT_SYSCALL, tid, (PTRACE_TYPE_ARG3) 0, 0);
          waitpid (tid, NULL, __WALL | __WNOTHREAD);
          waitpid (tid, NULL, __WALL | __WNOTHREAD);
        }
        }
    }
    }
 
 
  if (WIFEXITED (w))
  if (WIFEXITED (w))
    {
    {
      fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w));
      fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w));
      *status = 'W';
      *status = 'W';
      clear_inferiors ();
      clear_inferiors ();
      return ((unsigned char) WEXITSTATUS (w));
      return ((unsigned char) WEXITSTATUS (w));
    }
    }
  else if (!WIFSTOPPED (w))
  else if (!WIFSTOPPED (w))
    {
    {
      fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w));
      fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w));
      *status = 'X';
      *status = 'X';
      clear_inferiors ();
      clear_inferiors ();
      return ((unsigned char) WTERMSIG (w));
      return ((unsigned char) WTERMSIG (w));
    }
    }
 
 
  /* After attach, we may have received a SIGSTOP.  Do not return this
  /* 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 ...  */
     as signal to GDB, or else it will try to continue with SIGSTOP ...  */
  if (!server_waiting)
  if (!server_waiting)
    {
    {
      *status = 'T';
      *status = 'T';
      return 0;
      return 0;
    }
    }
 
 
  *status = 'T';
  *status = 'T';
  return ((unsigned char) WSTOPSIG (w));
  return ((unsigned char) WSTOPSIG (w));
}
}
 
 
/* Fetch inferior registers.  */
/* Fetch inferior registers.  */
static void
static void
spu_fetch_registers (int regno)
spu_fetch_registers (int regno)
{
{
  int fd;
  int fd;
  CORE_ADDR addr;
  CORE_ADDR addr;
 
 
  /* ??? Some callers use 0 to mean all registers.  */
  /* ??? Some callers use 0 to mean all registers.  */
  if (regno == 0)
  if (regno == 0)
    regno = -1;
    regno = -1;
 
 
  /* We must be stopped on a spu_run system call.  */
  /* We must be stopped on a spu_run system call.  */
  if (!parse_spufs_run (&fd, &addr))
  if (!parse_spufs_run (&fd, &addr))
    return;
    return;
 
 
  /* The ID register holds the spufs file handle.  */
  /* The ID register holds the spufs file handle.  */
  if (regno == -1 || regno == SPU_ID_REGNUM)
  if (regno == -1 || regno == SPU_ID_REGNUM)
    supply_register (SPU_ID_REGNUM, (char *)&fd);
    supply_register (SPU_ID_REGNUM, (char *)&fd);
 
 
  /* The NPC register is found at ADDR.  */
  /* The NPC register is found at ADDR.  */
  if (regno == -1 || regno == SPU_PC_REGNUM)
  if (regno == -1 || regno == SPU_PC_REGNUM)
    {
    {
      char buf[4];
      char buf[4];
      if (fetch_ppc_memory (addr, buf, 4) == 0)
      if (fetch_ppc_memory (addr, buf, 4) == 0)
        supply_register (SPU_PC_REGNUM, buf);
        supply_register (SPU_PC_REGNUM, buf);
    }
    }
 
 
  /* The GPRs are found in the "regs" spufs file.  */
  /* The GPRs are found in the "regs" spufs file.  */
  if (regno == -1 || (regno >= 0 && regno < SPU_NUM_CORE_REGS))
  if (regno == -1 || (regno >= 0 && regno < SPU_NUM_CORE_REGS))
    {
    {
      unsigned char buf[16*SPU_NUM_CORE_REGS];
      unsigned char buf[16*SPU_NUM_CORE_REGS];
      char annex[32];
      char annex[32];
      int i;
      int i;
 
 
      sprintf (annex, "%d/regs", fd);
      sprintf (annex, "%d/regs", fd);
      if (spu_proc_xfer_spu (annex, buf, NULL, 0, sizeof buf) == sizeof buf)
      if (spu_proc_xfer_spu (annex, buf, NULL, 0, sizeof buf) == sizeof buf)
        for (i = 0; i < SPU_NUM_CORE_REGS; i++)
        for (i = 0; i < SPU_NUM_CORE_REGS; i++)
          supply_register (i, buf + i*16);
          supply_register (i, buf + i*16);
    }
    }
}
}
 
 
/* Store inferior registers.  */
/* Store inferior registers.  */
static void
static void
spu_store_registers (int regno)
spu_store_registers (int regno)
{
{
  int fd;
  int fd;
  CORE_ADDR addr;
  CORE_ADDR addr;
 
 
  /* ??? Some callers use 0 to mean all registers.  */
  /* ??? Some callers use 0 to mean all registers.  */
  if (regno == 0)
  if (regno == 0)
    regno = -1;
    regno = -1;
 
 
  /* We must be stopped on a spu_run system call.  */
  /* We must be stopped on a spu_run system call.  */
  if (!parse_spufs_run (&fd, &addr))
  if (!parse_spufs_run (&fd, &addr))
    return;
    return;
 
 
  /* The NPC register is found at ADDR.  */
  /* The NPC register is found at ADDR.  */
  if (regno == -1 || regno == SPU_PC_REGNUM)
  if (regno == -1 || regno == SPU_PC_REGNUM)
    {
    {
      char buf[4];
      char buf[4];
      collect_register (SPU_PC_REGNUM, buf);
      collect_register (SPU_PC_REGNUM, buf);
      store_ppc_memory (addr, buf, 4);
      store_ppc_memory (addr, buf, 4);
    }
    }
 
 
  /* The GPRs are found in the "regs" spufs file.  */
  /* The GPRs are found in the "regs" spufs file.  */
  if (regno == -1 || (regno >= 0 && regno < SPU_NUM_CORE_REGS))
  if (regno == -1 || (regno >= 0 && regno < SPU_NUM_CORE_REGS))
    {
    {
      unsigned char buf[16*SPU_NUM_CORE_REGS];
      unsigned char buf[16*SPU_NUM_CORE_REGS];
      char annex[32];
      char annex[32];
      int i;
      int i;
 
 
      for (i = 0; i < SPU_NUM_CORE_REGS; i++)
      for (i = 0; i < SPU_NUM_CORE_REGS; i++)
        collect_register (i, buf + i*16);
        collect_register (i, buf + i*16);
 
 
      sprintf (annex, "%d/regs", fd);
      sprintf (annex, "%d/regs", fd);
      spu_proc_xfer_spu (annex, NULL, buf, 0, sizeof buf);
      spu_proc_xfer_spu (annex, NULL, buf, 0, sizeof buf);
    }
    }
}
}
 
 
/* Copy LEN bytes from inferior's memory starting at MEMADDR
/* Copy LEN bytes from inferior's memory starting at MEMADDR
   to debugger memory starting at MYADDR.  */
   to debugger memory starting at MYADDR.  */
static int
static int
spu_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
spu_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
{
{
  int fd, ret;
  int fd, ret;
  CORE_ADDR addr;
  CORE_ADDR addr;
  char annex[32];
  char annex[32];
 
 
  /* We must be stopped on a spu_run system call.  */
  /* We must be stopped on a spu_run system call.  */
  if (!parse_spufs_run (&fd, &addr))
  if (!parse_spufs_run (&fd, &addr))
    return 0;
    return 0;
 
 
  /* Use the "mem" spufs file to access SPU local store.  */
  /* Use the "mem" spufs file to access SPU local store.  */
  sprintf (annex, "%d/mem", fd);
  sprintf (annex, "%d/mem", fd);
  ret = spu_proc_xfer_spu (annex, myaddr, NULL, memaddr, len);
  ret = spu_proc_xfer_spu (annex, myaddr, NULL, memaddr, len);
  return ret == len ? 0 : EIO;
  return ret == len ? 0 : EIO;
}
}
 
 
/* Copy LEN bytes of data from debugger memory at MYADDR
/* Copy LEN bytes of data from debugger memory at MYADDR
   to inferior's memory at MEMADDR.
   to inferior's memory at MEMADDR.
   On failure (cannot write the inferior)
   On failure (cannot write the inferior)
   returns the value of errno.  */
   returns the value of errno.  */
static int
static int
spu_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
spu_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
{
{
  int fd, ret;
  int fd, ret;
  CORE_ADDR addr;
  CORE_ADDR addr;
  char annex[32];
  char annex[32];
 
 
  /* We must be stopped on a spu_run system call.  */
  /* We must be stopped on a spu_run system call.  */
  if (!parse_spufs_run (&fd, &addr))
  if (!parse_spufs_run (&fd, &addr))
    return 0;
    return 0;
 
 
  /* Use the "mem" spufs file to access SPU local store.  */
  /* Use the "mem" spufs file to access SPU local store.  */
  sprintf (annex, "%d/mem", fd);
  sprintf (annex, "%d/mem", fd);
  ret = spu_proc_xfer_spu (annex, NULL, myaddr, memaddr, len);
  ret = spu_proc_xfer_spu (annex, NULL, myaddr, memaddr, len);
  return ret == len ? 0 : EIO;
  return ret == len ? 0 : EIO;
}
}
 
 
/* Look up special symbols -- unneded here.  */
/* Look up special symbols -- unneded here.  */
static void
static void
spu_look_up_symbols (void)
spu_look_up_symbols (void)
{
{
}
}
 
 
/* Send signal to inferior.  */
/* Send signal to inferior.  */
static void
static void
spu_request_interrupt (void)
spu_request_interrupt (void)
{
{
  syscall (SYS_tkill, current_tid, SIGINT);
  syscall (SYS_tkill, current_tid, SIGINT);
}
}
 
 
static const char *
static const char *
spu_arch_string (void)
spu_arch_string (void)
{
{
  return "spu";
  return "spu";
}
}
 
 
static struct target_ops spu_target_ops = {
static struct target_ops spu_target_ops = {
  spu_create_inferior,
  spu_create_inferior,
  spu_attach,
  spu_attach,
  spu_kill,
  spu_kill,
  spu_detach,
  spu_detach,
  spu_join,
  spu_join,
  spu_thread_alive,
  spu_thread_alive,
  spu_resume,
  spu_resume,
  spu_wait,
  spu_wait,
  spu_fetch_registers,
  spu_fetch_registers,
  spu_store_registers,
  spu_store_registers,
  spu_read_memory,
  spu_read_memory,
  spu_write_memory,
  spu_write_memory,
  spu_look_up_symbols,
  spu_look_up_symbols,
  spu_request_interrupt,
  spu_request_interrupt,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  spu_arch_string,
  spu_arch_string,
  spu_proc_xfer_spu,
  spu_proc_xfer_spu,
  hostio_last_error_from_errno,
  hostio_last_error_from_errno,
};
};
 
 
void
void
initialize_low (void)
initialize_low (void)
{
{
  static const unsigned char breakpoint[] = { 0x00, 0x00, 0x3f, 0xff };
  static const unsigned char breakpoint[] = { 0x00, 0x00, 0x3f, 0xff };
 
 
  set_target_ops (&spu_target_ops);
  set_target_ops (&spu_target_ops);
  set_breakpoint_data (breakpoint, sizeof breakpoint);
  set_breakpoint_data (breakpoint, sizeof breakpoint);
  init_registers ();
  init_registers ();
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.