aboutsummaryrefslogtreecommitdiff
path: root/gdb/gdbserver/spu-low.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/gdbserver/spu-low.c')
-rw-r--r--gdb/gdbserver/spu-low.c38
1 files changed, 36 insertions, 2 deletions
diff --git a/gdb/gdbserver/spu-low.c b/gdb/gdbserver/spu-low.c
index d9ac815..2188d64 100644
--- a/gdb/gdbserver/spu-low.c
+++ b/gdb/gdbserver/spu-low.c
@@ -561,7 +561,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))
@@ -570,6 +571,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;
}
@@ -582,7 +599,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))
@@ -591,6 +609,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;
}