GDBserver
|
00001 /* Low level interface to SPUs, for the remote server for GDB. 00002 Copyright (C) 2006-2013 Free Software Foundation, Inc. 00003 00004 Contributed by Ulrich Weigand <uweigand@de.ibm.com>. 00005 00006 This file is part of GDB. 00007 00008 This program is free software; you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License as published by 00010 the Free Software Foundation; either version 3 of the License, or 00011 (at your option) any later version. 00012 00013 This program is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 You should have received a copy of the GNU General Public License 00019 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00020 00021 #include "server.h" 00022 00023 #include "gdb_wait.h" 00024 #include <stdio.h> 00025 #include <sys/ptrace.h> 00026 #include <fcntl.h> 00027 #include <string.h> 00028 #include <stdlib.h> 00029 #include <unistd.h> 00030 #include <errno.h> 00031 #include <sys/syscall.h> 00032 #include "filestuff.h" 00033 #include "hostio.h" 00034 00035 /* Some older glibc versions do not define this. */ 00036 #ifndef __WNOTHREAD 00037 #define __WNOTHREAD 0x20000000 /* Don't wait on children of other 00038 threads in this group */ 00039 #endif 00040 00041 #define PTRACE_TYPE_RET long 00042 #define PTRACE_TYPE_ARG3 long 00043 00044 /* Number of registers. */ 00045 #define SPU_NUM_REGS 130 00046 #define SPU_NUM_CORE_REGS 128 00047 00048 /* Special registers. */ 00049 #define SPU_ID_REGNUM 128 00050 #define SPU_PC_REGNUM 129 00051 00052 /* PPU side system calls. */ 00053 #define INSTR_SC 0x44000002 00054 #define NR_spu_run 0x0116 00055 00056 /* These are used in remote-utils.c. */ 00057 int using_threads = 0; 00058 00059 /* Defined in auto-generated file reg-spu.c. */ 00060 void init_registers_spu (void); 00061 extern const struct target_desc *tdesc_spu; 00062 00063 /* Fetch PPU register REGNO. */ 00064 static CORE_ADDR 00065 fetch_ppc_register (int regno) 00066 { 00067 PTRACE_TYPE_RET res; 00068 00069 int tid = ptid_get_lwp (current_ptid); 00070 00071 #ifndef __powerpc64__ 00072 /* If running as a 32-bit process on a 64-bit system, we attempt 00073 to get the full 64-bit register content of the target process. 00074 If the PPC special ptrace call fails, we're on a 32-bit system; 00075 just fall through to the regular ptrace call in that case. */ 00076 { 00077 char buf[8]; 00078 00079 errno = 0; 00080 ptrace (PPC_PTRACE_PEEKUSR_3264, tid, 00081 (PTRACE_TYPE_ARG3) (regno * 8), buf); 00082 if (errno == 0) 00083 ptrace (PPC_PTRACE_PEEKUSR_3264, tid, 00084 (PTRACE_TYPE_ARG3) (regno * 8 + 4), buf + 4); 00085 if (errno == 0) 00086 return (CORE_ADDR) *(unsigned long long *)buf; 00087 } 00088 #endif 00089 00090 errno = 0; 00091 res = ptrace (PT_READ_U, tid, 00092 (PTRACE_TYPE_ARG3) (regno * sizeof (PTRACE_TYPE_RET)), 0); 00093 if (errno != 0) 00094 { 00095 char mess[128]; 00096 sprintf (mess, "reading PPC register #%d", regno); 00097 perror_with_name (mess); 00098 } 00099 00100 return (CORE_ADDR) (unsigned long) res; 00101 } 00102 00103 /* Fetch WORD from PPU memory at (aligned) MEMADDR in thread TID. */ 00104 static int 00105 fetch_ppc_memory_1 (int tid, CORE_ADDR memaddr, PTRACE_TYPE_RET *word) 00106 { 00107 errno = 0; 00108 00109 #ifndef __powerpc64__ 00110 if (memaddr >> 32) 00111 { 00112 unsigned long long addr_8 = (unsigned long long) memaddr; 00113 ptrace (PPC_PTRACE_PEEKTEXT_3264, tid, (PTRACE_TYPE_ARG3) &addr_8, word); 00114 } 00115 else 00116 #endif 00117 *word = ptrace (PT_READ_I, tid, (PTRACE_TYPE_ARG3) (size_t) memaddr, 0); 00118 00119 return errno; 00120 } 00121 00122 /* Store WORD into PPU memory at (aligned) MEMADDR in thread TID. */ 00123 static int 00124 store_ppc_memory_1 (int tid, CORE_ADDR memaddr, PTRACE_TYPE_RET word) 00125 { 00126 errno = 0; 00127 00128 #ifndef __powerpc64__ 00129 if (memaddr >> 32) 00130 { 00131 unsigned long long addr_8 = (unsigned long long) memaddr; 00132 ptrace (PPC_PTRACE_POKEDATA_3264, tid, (PTRACE_TYPE_ARG3) &addr_8, word); 00133 } 00134 else 00135 #endif 00136 ptrace (PT_WRITE_D, tid, (PTRACE_TYPE_ARG3) (size_t) memaddr, word); 00137 00138 return errno; 00139 } 00140 00141 /* Fetch LEN bytes of PPU memory at MEMADDR to MYADDR. */ 00142 static int 00143 fetch_ppc_memory (CORE_ADDR memaddr, char *myaddr, int len) 00144 { 00145 int i, ret; 00146 00147 CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_TYPE_RET); 00148 int count = ((((memaddr + len) - addr) + sizeof (PTRACE_TYPE_RET) - 1) 00149 / sizeof (PTRACE_TYPE_RET)); 00150 PTRACE_TYPE_RET *buffer; 00151 00152 int tid = ptid_get_lwp (current_ptid); 00153 00154 buffer = (PTRACE_TYPE_RET *) alloca (count * sizeof (PTRACE_TYPE_RET)); 00155 for (i = 0; i < count; i++, addr += sizeof (PTRACE_TYPE_RET)) 00156 if ((ret = fetch_ppc_memory_1 (tid, addr, &buffer[i])) != 0) 00157 return ret; 00158 00159 memcpy (myaddr, 00160 (char *) buffer + (memaddr & (sizeof (PTRACE_TYPE_RET) - 1)), 00161 len); 00162 00163 return 0; 00164 } 00165 00166 /* Store LEN bytes from MYADDR to PPU memory at MEMADDR. */ 00167 static int 00168 store_ppc_memory (CORE_ADDR memaddr, char *myaddr, int len) 00169 { 00170 int i, ret; 00171 00172 CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_TYPE_RET); 00173 int count = ((((memaddr + len) - addr) + sizeof (PTRACE_TYPE_RET) - 1) 00174 / sizeof (PTRACE_TYPE_RET)); 00175 PTRACE_TYPE_RET *buffer; 00176 00177 int tid = ptid_get_lwp (current_ptid); 00178 00179 buffer = (PTRACE_TYPE_RET *) alloca (count * sizeof (PTRACE_TYPE_RET)); 00180 00181 if (addr != memaddr || len < (int) sizeof (PTRACE_TYPE_RET)) 00182 if ((ret = fetch_ppc_memory_1 (tid, addr, &buffer[0])) != 0) 00183 return ret; 00184 00185 if (count > 1) 00186 if ((ret = fetch_ppc_memory_1 (tid, addr + (count - 1) 00187 * sizeof (PTRACE_TYPE_RET), 00188 &buffer[count - 1])) != 0) 00189 return ret; 00190 00191 memcpy ((char *) buffer + (memaddr & (sizeof (PTRACE_TYPE_RET) - 1)), 00192 myaddr, len); 00193 00194 for (i = 0; i < count; i++, addr += sizeof (PTRACE_TYPE_RET)) 00195 if ((ret = store_ppc_memory_1 (tid, addr, buffer[i])) != 0) 00196 return ret; 00197 00198 return 0; 00199 } 00200 00201 00202 /* If the PPU thread is currently stopped on a spu_run system call, 00203 return to FD and ADDR the file handle and NPC parameter address 00204 used with the system call. Return non-zero if successful. */ 00205 static int 00206 parse_spufs_run (int *fd, CORE_ADDR *addr) 00207 { 00208 unsigned int insn; 00209 CORE_ADDR pc = fetch_ppc_register (32); /* nip */ 00210 00211 /* Fetch instruction preceding current NIP. */ 00212 if (fetch_ppc_memory (pc-4, (char *) &insn, 4) != 0) 00213 return 0; 00214 /* It should be a "sc" instruction. */ 00215 if (insn != INSTR_SC) 00216 return 0; 00217 /* System call number should be NR_spu_run. */ 00218 if (fetch_ppc_register (0) != NR_spu_run) 00219 return 0; 00220 00221 /* Register 3 contains fd, register 4 the NPC param pointer. */ 00222 *fd = fetch_ppc_register (34); /* orig_gpr3 */ 00223 *addr = fetch_ppc_register (4); 00224 return 1; 00225 } 00226 00227 00228 /* Copy LEN bytes at OFFSET in spufs file ANNEX into/from READBUF or WRITEBUF, 00229 using the /proc file system. */ 00230 static int 00231 spu_proc_xfer_spu (const char *annex, unsigned char *readbuf, 00232 const unsigned char *writebuf, 00233 CORE_ADDR offset, int len) 00234 { 00235 char buf[128]; 00236 int fd = 0; 00237 int ret = -1; 00238 00239 if (!annex) 00240 return 0; 00241 00242 sprintf (buf, "/proc/%ld/fd/%s", ptid_get_lwp (current_ptid), annex); 00243 fd = open (buf, writebuf? O_WRONLY : O_RDONLY); 00244 if (fd <= 0) 00245 return -1; 00246 00247 if (offset != 0 00248 && lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset) 00249 { 00250 close (fd); 00251 return 0; 00252 } 00253 00254 if (writebuf) 00255 ret = write (fd, writebuf, (size_t) len); 00256 else if (readbuf) 00257 ret = read (fd, readbuf, (size_t) len); 00258 00259 close (fd); 00260 return ret; 00261 } 00262 00263 00264 /* Start an inferior process and returns its pid. 00265 ALLARGS is a vector of program-name and args. */ 00266 static int 00267 spu_create_inferior (char *program, char **allargs) 00268 { 00269 int pid; 00270 ptid_t ptid; 00271 struct process_info *proc; 00272 00273 pid = fork (); 00274 if (pid < 0) 00275 perror_with_name ("fork"); 00276 00277 if (pid == 0) 00278 { 00279 close_most_fds (); 00280 ptrace (PTRACE_TRACEME, 0, 0, 0); 00281 00282 setpgid (0, 0); 00283 00284 execv (program, allargs); 00285 if (errno == ENOENT) 00286 execvp (program, allargs); 00287 00288 fprintf (stderr, "Cannot exec %s: %s.\n", program, 00289 strerror (errno)); 00290 fflush (stderr); 00291 _exit (0177); 00292 } 00293 00294 proc = add_process (pid, 0); 00295 proc->tdesc = tdesc_spu; 00296 00297 ptid = ptid_build (pid, pid, 0); 00298 add_thread (ptid, NULL); 00299 return pid; 00300 } 00301 00302 /* Attach to an inferior process. */ 00303 int 00304 spu_attach (unsigned long pid) 00305 { 00306 ptid_t ptid; 00307 struct process_info *proc; 00308 00309 if (ptrace (PTRACE_ATTACH, pid, 0, 0) != 0) 00310 { 00311 fprintf (stderr, "Cannot attach to process %ld: %s (%d)\n", pid, 00312 strerror (errno), errno); 00313 fflush (stderr); 00314 _exit (0177); 00315 } 00316 00317 proc = add_process (pid, 1); 00318 proc->tdesc = tdesc_spu; 00319 ptid = ptid_build (pid, pid, 0); 00320 add_thread (ptid, NULL); 00321 return 0; 00322 } 00323 00324 /* Kill the inferior process. */ 00325 static int 00326 spu_kill (int pid) 00327 { 00328 int status, ret; 00329 struct process_info *process = find_process_pid (pid); 00330 if (process == NULL) 00331 return -1; 00332 00333 ptrace (PTRACE_KILL, pid, 0, 0); 00334 00335 do { 00336 ret = waitpid (pid, &status, 0); 00337 if (WIFEXITED (status) || WIFSIGNALED (status)) 00338 break; 00339 } while (ret != -1 || errno != ECHILD); 00340 00341 clear_inferiors (); 00342 remove_process (process); 00343 return 0; 00344 } 00345 00346 /* Detach from inferior process. */ 00347 static int 00348 spu_detach (int pid) 00349 { 00350 struct process_info *process = find_process_pid (pid); 00351 if (process == NULL) 00352 return -1; 00353 00354 ptrace (PTRACE_DETACH, pid, 0, 0); 00355 00356 clear_inferiors (); 00357 remove_process (process); 00358 return 0; 00359 } 00360 00361 static void 00362 spu_mourn (struct process_info *process) 00363 { 00364 remove_process (process); 00365 } 00366 00367 static void 00368 spu_join (int pid) 00369 { 00370 int status, ret; 00371 00372 do { 00373 ret = waitpid (pid, &status, 0); 00374 if (WIFEXITED (status) || WIFSIGNALED (status)) 00375 break; 00376 } while (ret != -1 || errno != ECHILD); 00377 } 00378 00379 /* Return nonzero if the given thread is still alive. */ 00380 static int 00381 spu_thread_alive (ptid_t ptid) 00382 { 00383 return ptid_equal (ptid, current_ptid); 00384 } 00385 00386 /* Resume process. */ 00387 static void 00388 spu_resume (struct thread_resume *resume_info, size_t n) 00389 { 00390 size_t i; 00391 00392 for (i = 0; i < n; i++) 00393 if (ptid_equal (resume_info[i].thread, minus_one_ptid) 00394 || ptid_equal (resume_info[i].thread, current_ptid)) 00395 break; 00396 00397 if (i == n) 00398 return; 00399 00400 /* We don't support hardware single-stepping right now, assume 00401 GDB knows to use software single-stepping. */ 00402 if (resume_info[i].kind == resume_step) 00403 fprintf (stderr, "Hardware single-step not supported.\n"); 00404 00405 regcache_invalidate (); 00406 00407 errno = 0; 00408 ptrace (PTRACE_CONT, ptid_get_lwp (current_ptid), 0, resume_info[i].sig); 00409 if (errno) 00410 perror_with_name ("ptrace"); 00411 } 00412 00413 /* Wait for process, returns status. */ 00414 static ptid_t 00415 spu_wait (ptid_t ptid, struct target_waitstatus *ourstatus, int options) 00416 { 00417 int pid = ptid_get_pid (ptid); 00418 int w; 00419 int ret; 00420 00421 while (1) 00422 { 00423 ret = waitpid (pid, &w, WNOHANG | __WALL | __WNOTHREAD); 00424 00425 if (ret == -1) 00426 { 00427 if (errno != ECHILD) 00428 perror_with_name ("waitpid"); 00429 } 00430 else if (ret > 0) 00431 break; 00432 00433 usleep (1000); 00434 } 00435 00436 /* On the first wait, continue running the inferior until we are 00437 blocked inside an spu_run system call. */ 00438 if (!server_waiting) 00439 { 00440 int fd; 00441 CORE_ADDR addr; 00442 00443 while (!parse_spufs_run (&fd, &addr)) 00444 { 00445 ptrace (PT_SYSCALL, pid, (PTRACE_TYPE_ARG3) 0, 0); 00446 waitpid (pid, NULL, __WALL | __WNOTHREAD); 00447 } 00448 } 00449 00450 if (WIFEXITED (w)) 00451 { 00452 fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w)); 00453 ourstatus->kind = TARGET_WAITKIND_EXITED; 00454 ourstatus->value.integer = WEXITSTATUS (w); 00455 clear_inferiors (); 00456 return pid_to_ptid (ret); 00457 } 00458 else if (!WIFSTOPPED (w)) 00459 { 00460 fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w)); 00461 ourstatus->kind = TARGET_WAITKIND_SIGNALLED; 00462 ourstatus->value.sig = gdb_signal_from_host (WTERMSIG (w)); 00463 clear_inferiors (); 00464 return pid_to_ptid (ret); 00465 } 00466 00467 /* After attach, we may have received a SIGSTOP. Do not return this 00468 as signal to GDB, or else it will try to continue with SIGSTOP ... */ 00469 if (!server_waiting) 00470 { 00471 ourstatus->kind = TARGET_WAITKIND_STOPPED; 00472 ourstatus->value.sig = GDB_SIGNAL_0; 00473 return ptid_build (ret, ret, 0); 00474 } 00475 00476 ourstatus->kind = TARGET_WAITKIND_STOPPED; 00477 ourstatus->value.sig = gdb_signal_from_host (WSTOPSIG (w)); 00478 return ptid_build (ret, ret, 0); 00479 } 00480 00481 /* Fetch inferior registers. */ 00482 static void 00483 spu_fetch_registers (struct regcache *regcache, int regno) 00484 { 00485 int fd; 00486 CORE_ADDR addr; 00487 00488 /* We must be stopped on a spu_run system call. */ 00489 if (!parse_spufs_run (&fd, &addr)) 00490 return; 00491 00492 /* The ID register holds the spufs file handle. */ 00493 if (regno == -1 || regno == SPU_ID_REGNUM) 00494 supply_register (regcache, SPU_ID_REGNUM, (char *)&fd); 00495 00496 /* The NPC register is found at ADDR. */ 00497 if (regno == -1 || regno == SPU_PC_REGNUM) 00498 { 00499 char buf[4]; 00500 if (fetch_ppc_memory (addr, buf, 4) == 0) 00501 supply_register (regcache, SPU_PC_REGNUM, buf); 00502 } 00503 00504 /* The GPRs are found in the "regs" spufs file. */ 00505 if (regno == -1 || (regno >= 0 && regno < SPU_NUM_CORE_REGS)) 00506 { 00507 unsigned char buf[16*SPU_NUM_CORE_REGS]; 00508 char annex[32]; 00509 int i; 00510 00511 sprintf (annex, "%d/regs", fd); 00512 if (spu_proc_xfer_spu (annex, buf, NULL, 0, sizeof buf) == sizeof buf) 00513 for (i = 0; i < SPU_NUM_CORE_REGS; i++) 00514 supply_register (regcache, i, buf + i*16); 00515 } 00516 } 00517 00518 /* Store inferior registers. */ 00519 static void 00520 spu_store_registers (struct regcache *regcache, int regno) 00521 { 00522 int fd; 00523 CORE_ADDR addr; 00524 00525 /* ??? Some callers use 0 to mean all registers. */ 00526 if (regno == 0) 00527 regno = -1; 00528 00529 /* We must be stopped on a spu_run system call. */ 00530 if (!parse_spufs_run (&fd, &addr)) 00531 return; 00532 00533 /* The NPC register is found at ADDR. */ 00534 if (regno == -1 || regno == SPU_PC_REGNUM) 00535 { 00536 char buf[4]; 00537 collect_register (regcache, SPU_PC_REGNUM, buf); 00538 store_ppc_memory (addr, buf, 4); 00539 } 00540 00541 /* The GPRs are found in the "regs" spufs file. */ 00542 if (regno == -1 || (regno >= 0 && regno < SPU_NUM_CORE_REGS)) 00543 { 00544 unsigned char buf[16*SPU_NUM_CORE_REGS]; 00545 char annex[32]; 00546 int i; 00547 00548 for (i = 0; i < SPU_NUM_CORE_REGS; i++) 00549 collect_register (regcache, i, buf + i*16); 00550 00551 sprintf (annex, "%d/regs", fd); 00552 spu_proc_xfer_spu (annex, NULL, buf, 0, sizeof buf); 00553 } 00554 } 00555 00556 /* Copy LEN bytes from inferior's memory starting at MEMADDR 00557 to debugger memory starting at MYADDR. */ 00558 static int 00559 spu_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len) 00560 { 00561 int fd, ret; 00562 CORE_ADDR addr; 00563 char annex[32], lslr_annex[32], buf[32]; 00564 CORE_ADDR lslr; 00565 00566 /* We must be stopped on a spu_run system call. */ 00567 if (!parse_spufs_run (&fd, &addr)) 00568 return 0; 00569 00570 /* Use the "mem" spufs file to access SPU local store. */ 00571 sprintf (annex, "%d/mem", fd); 00572 ret = spu_proc_xfer_spu (annex, myaddr, NULL, memaddr, len); 00573 if (ret > 0) 00574 return ret == len ? 0 : EIO; 00575 00576 /* SPU local store access wraps the address around at the 00577 local store limit. We emulate this here. To avoid needing 00578 an extra access to retrieve the LSLR, we only do that after 00579 trying the original address first, and getting end-of-file. */ 00580 sprintf (lslr_annex, "%d/lslr", fd); 00581 memset (buf, 0, sizeof buf); 00582 if (spu_proc_xfer_spu (lslr_annex, (unsigned char *)buf, NULL, 00583 0, sizeof buf) <= 0) 00584 return ret; 00585 00586 lslr = strtoul (buf, NULL, 16); 00587 ret = spu_proc_xfer_spu (annex, myaddr, NULL, memaddr & lslr, len); 00588 00589 return ret == len ? 0 : EIO; 00590 } 00591 00592 /* Copy LEN bytes of data from debugger memory at MYADDR 00593 to inferior's memory at MEMADDR. 00594 On failure (cannot write the inferior) 00595 returns the value of errno. */ 00596 static int 00597 spu_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len) 00598 { 00599 int fd, ret; 00600 CORE_ADDR addr; 00601 char annex[32], lslr_annex[32], buf[32]; 00602 CORE_ADDR lslr; 00603 00604 /* We must be stopped on a spu_run system call. */ 00605 if (!parse_spufs_run (&fd, &addr)) 00606 return 0; 00607 00608 /* Use the "mem" spufs file to access SPU local store. */ 00609 sprintf (annex, "%d/mem", fd); 00610 ret = spu_proc_xfer_spu (annex, NULL, myaddr, memaddr, len); 00611 if (ret > 0) 00612 return ret == len ? 0 : EIO; 00613 00614 /* SPU local store access wraps the address around at the 00615 local store limit. We emulate this here. To avoid needing 00616 an extra access to retrieve the LSLR, we only do that after 00617 trying the original address first, and getting end-of-file. */ 00618 sprintf (lslr_annex, "%d/lslr", fd); 00619 memset (buf, 0, sizeof buf); 00620 if (spu_proc_xfer_spu (lslr_annex, (unsigned char *)buf, NULL, 00621 0, sizeof buf) <= 0) 00622 return ret; 00623 00624 lslr = strtoul (buf, NULL, 16); 00625 ret = spu_proc_xfer_spu (annex, NULL, myaddr, memaddr & lslr, len); 00626 00627 return ret == len ? 0 : EIO; 00628 } 00629 00630 /* Look up special symbols -- unneded here. */ 00631 static void 00632 spu_look_up_symbols (void) 00633 { 00634 } 00635 00636 /* Send signal to inferior. */ 00637 static void 00638 spu_request_interrupt (void) 00639 { 00640 syscall (SYS_tkill, ptid_get_lwp (current_ptid), SIGINT); 00641 } 00642 00643 static struct target_ops spu_target_ops = { 00644 spu_create_inferior, 00645 spu_attach, 00646 spu_kill, 00647 spu_detach, 00648 spu_mourn, 00649 spu_join, 00650 spu_thread_alive, 00651 spu_resume, 00652 spu_wait, 00653 spu_fetch_registers, 00654 spu_store_registers, 00655 NULL, /* prepare_to_access_memory */ 00656 NULL, /* done_accessing_memory */ 00657 spu_read_memory, 00658 spu_write_memory, 00659 spu_look_up_symbols, 00660 spu_request_interrupt, 00661 NULL, 00662 NULL, 00663 NULL, 00664 NULL, 00665 NULL, 00666 NULL, 00667 NULL, 00668 spu_proc_xfer_spu, 00669 hostio_last_error_from_errno, 00670 }; 00671 00672 void 00673 initialize_low (void) 00674 { 00675 static const unsigned char breakpoint[] = { 0x00, 0x00, 0x3f, 0xff }; 00676 00677 set_target_ops (&spu_target_ops); 00678 set_breakpoint_data (breakpoint, sizeof breakpoint); 00679 init_registers_spu (); 00680 }