ChangeLog:
authorUlrich Weigand <uweigand@de.ibm.com>
Sat, 19 Jun 2010 17:36:51 +0000 (17:36 +0000)
committerUlrich Weigand <uweigand@de.ibm.com>
Sat, 19 Jun 2010 17:36:51 +0000 (17:36 +0000)
* spu-multiarch.c (spu_xfer_partial): Wrap around local store
limit on local store memory accesses.
* spu-linux-nat.c (spu_xfer_partial): Likewise.
* spu-tdep.c (spu_lslr): Remove.
(spu_pointer_to_address): Do not truncate addresses.
(spu_integer_to_address): Likewise.
(spu_overlay_new_objfile): Use SPU_OVERLAY_LMA.
* spu-tdep.h: Add comments.
(SPUADDR_SPU): Respect SPU_OVERLAY_LMA bit.
(SPU_OVERLAY_LMA): Define.

gdbserver/ChangeLog:

* spu-low.c (spu_read_memory): Wrap around local store limit.
(spu_write_memory): Likewise.

testsuite/ChangeLog:

* gdb.arch/spu-ls.exp: New file.
* gdb.arch/spu-ls.c: Likewise.

gdb/ChangeLog
gdb/gdbserver/ChangeLog
gdb/gdbserver/spu-low.c
gdb/spu-linux-nat.c
gdb/spu-multiarch.c
gdb/spu-tdep.c
gdb/spu-tdep.h
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.arch/spu-ls.c [new file with mode: 0644]
gdb/testsuite/gdb.arch/spu-ls.exp [new file with mode: 0644]

index b8cd0f8..48e6250 100644 (file)
@@ -1,3 +1,16 @@
+2010-06-19  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * spu-multiarch.c (spu_xfer_partial): Wrap around local store
+       limit on local store memory accesses.
+       * spu-linux-nat.c (spu_xfer_partial): Likewise.
+       * spu-tdep.c (spu_lslr): Remove.
+       (spu_pointer_to_address): Do not truncate addresses.
+       (spu_integer_to_address): Likewise.
+       (spu_overlay_new_objfile): Use SPU_OVERLAY_LMA.
+       * spu-tdep.h: Add comments.
+       (SPUADDR_SPU): Respect SPU_OVERLAY_LMA bit.
+       (SPU_OVERLAY_LMA): Define.
+
 2010-06-18  Stan Shebs  <stan@codesourcery.com>
 
        * osdata.c (get_osdata): Warn separately if target does not report
index 6b9f493..06c6343 100644 (file)
@@ -1,3 +1,8 @@
+2010-06-19  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * spu-low.c (spu_read_memory): Wrap around local store limit.
+       (spu_write_memory): Likewise.
+
 2010-06-15  Pedro Alves  <pedro@codesourcery.com>
 
        * linux-x86-low.c (amd64_emit_const, amd64_emit_void_call_2)
index d9ac815..2188d64 100644 (file)
@@ -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;
 }
 
index 7c9e2c5..5adfe4b 100644 (file)
@@ -562,7 +562,10 @@ spu_xfer_partial (struct target_ops *ops,
     {
       int fd;
       ULONGEST addr;
-      char mem_annex[32];
+      char mem_annex[32], lslr_annex[32];
+      gdb_byte buf[32];
+      ULONGEST lslr;
+      LONGEST ret;
 
       /* We must be stopped on a spu_run system call.  */
       if (!parse_spufs_run (&fd, &addr))
@@ -570,7 +573,22 @@ spu_xfer_partial (struct target_ops *ops,
 
       /* Use the "mem" spufs file to access SPU local store.  */
       xsnprintf (mem_annex, sizeof mem_annex, "%d/mem", fd);
-      return spu_proc_xfer_spu (mem_annex, readbuf, writebuf, offset, len);
+      ret = spu_proc_xfer_spu (mem_annex, readbuf, writebuf, offset, len);
+      if (ret > 0)
+       return ret;
+
+      /* 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.  */
+      xsnprintf (lslr_annex, sizeof lslr_annex, "%d/lslr", fd);
+      memset (buf, 0, sizeof buf);
+      if (spu_proc_xfer_spu (lslr_annex, buf, NULL, 0, sizeof buf) <= 0)
+       return ret;
+
+      lslr = strtoulst (buf, NULL, 16);
+      return spu_proc_xfer_spu (mem_annex, readbuf, writebuf,
+                               offset & lslr, len);
     }
 
   return -1;
index d072032..450aa42 100644 (file)
@@ -259,14 +259,35 @@ spu_xfer_partial (struct target_ops *ops, enum target_object object,
     {
       int fd = SPUADDR_SPU (offset);
       CORE_ADDR addr = SPUADDR_ADDR (offset);
-      char mem_annex[32];
+      char mem_annex[32], lslr_annex[32];
+      gdb_byte buf[32];
+      ULONGEST lslr;
+      LONGEST ret;
 
-      if (fd >= 0 && addr < SPU_LS_SIZE)
+      if (fd >= 0)
        {
          xsnprintf (mem_annex, sizeof mem_annex, "%d/mem", fd);
+         ret = ops_beneath->to_xfer_partial (ops_beneath, TARGET_OBJECT_SPU,
+                                             mem_annex, readbuf, writebuf,
+                                             addr, len);
+         if (ret > 0)
+           return ret;
+
+         /* 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.  */
+         xsnprintf (lslr_annex, sizeof lslr_annex, "%d/lslr", fd);
+         memset (buf, 0, sizeof buf);
+         if (ops_beneath->to_xfer_partial (ops_beneath, TARGET_OBJECT_SPU,
+                                           lslr_annex, buf, NULL,
+                                           0, sizeof buf) <= 0)
+           return ret;
+
+         lslr = strtoulst (buf, NULL, 16);
          return ops_beneath->to_xfer_partial (ops_beneath, TARGET_OBJECT_SPU,
                                               mem_annex, readbuf, writebuf,
-                                              addr, len);
+                                              addr & lslr, len);
        }
     }
 
index ae64841..072ae8c 100644 (file)
@@ -364,23 +364,6 @@ spu_gdbarch_id (struct gdbarch *gdbarch)
   return id;
 }
 
-static ULONGEST
-spu_lslr (int id)
-{
-  gdb_byte buf[32];
-  char annex[32];
-
-  if (id == -1)
-    return SPU_LS_SIZE - 1;
-
-  xsnprintf (annex, sizeof annex, "%d/lslr", id);
-  memset (buf, 0, sizeof buf);
-  target_read (&current_target, TARGET_OBJECT_SPU, annex,
-              buf, 0, sizeof buf);
-
-  return strtoulst (buf, NULL, 16);
-}
-
 static int
 spu_address_class_type_flags (int byte_size, int dwarf2_addr_class)
 {
@@ -426,7 +409,6 @@ spu_pointer_to_address (struct gdbarch *gdbarch,
                        struct type *type, const gdb_byte *buf)
 {
   int id = spu_gdbarch_id (gdbarch);
-  ULONGEST lslr = spu_lslr (id);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   ULONGEST addr
     = extract_unsigned_integer (buf, TYPE_LENGTH (type), byte_order);
@@ -435,7 +417,7 @@ spu_pointer_to_address (struct gdbarch *gdbarch,
   if (TYPE_ADDRESS_CLASS_1 (type))
     return addr;
 
-  return addr? SPUADDR (id, addr & lslr) : 0;
+  return addr? SPUADDR (id, addr) : 0;
 }
 
 static CORE_ADDR
@@ -443,10 +425,9 @@ spu_integer_to_address (struct gdbarch *gdbarch,
                        struct type *type, const gdb_byte *buf)
 {
   int id = spu_gdbarch_id (gdbarch);
-  ULONGEST lslr = spu_lslr (id);
   ULONGEST addr = unpack_long (type, buf);
 
-  return SPUADDR (id, addr & lslr);
+  return SPUADDR (id, addr);
 }
 
 
@@ -1777,7 +1758,7 @@ spu_overlay_update (struct obj_section *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.  */
+   is larger than SPU_OVERLAY_LMA.  */
 static void
 spu_overlay_new_objfile (struct objfile *objfile)
 {
@@ -1807,7 +1788,7 @@ spu_overlay_new_objfile (struct objfile *objfile)
       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;
+       bfd_section_lma (obfd, bsect) = SPU_OVERLAY_LMA + bsect->filepos;
     }
 }
 
index 9e70db9..4b83f74 100644 (file)
@@ -50,14 +50,71 @@ enum spu_regnum
 /* Local store.  */
 #define SPU_LS_SIZE          0x40000
 
-/* Address conversions.  */
+/* Address conversions.
+
+   In a combined PPU/SPU debugging session, we have to consider multiple
+   address spaces: the PPU 32- or 64-bit address space, and the 32-bit
+   local store address space for each SPU context.  As it is currently
+   not yet possible to use the program_space / address_space mechanism
+   to represent this, we encode all those addresses into one single
+   64-bit address for the whole process.  For SPU programs using overlays,
+   this address space must also include separate ranges reserved for the
+   LMA of overlay sections.
+
+
+   The following combinations are supported for combined debugging:
+
+   PPU address (this relies on the fact that PPC 64-bit user space
+   addresses can never have the highest-most bit set):
+
+      +-+---------------------------------+
+      |0|              ADDR [63]          |
+      +-+---------------------------------+
+
+   SPU address for SPU context with id SPU (this assumes that SPU
+   IDs, which are file descriptors, are never larger than 2^30):
+
+      +-+-+--------------+----------------+
+      |1|0|    SPU [30]  |    ADDR [32]   |
+      +-+-+--------------+----------------+
+
+   SPU overlay section LMA for SPU context with id SPU:
+
+      +-+-+--------------+----------------+
+      |1|1|    SPU [30]  |    ADDR [32]   |
+      +-+-+--------------+----------------+
+
+
+   In SPU stand-alone debugging mode (using spu-linux-nat.c),
+   the following combinations are supported:
+
+   SPU address:
+
+      +-+-+--------------+----------------+
+      |0|0|     0        |    ADDR [32]   |
+      +-+-+--------------+----------------+
+
+   SPU overlay section LMA:
+
+      +-+-+--------------+----------------+
+      |0|1|     0        |    ADDR [32]   |
+      +-+-+--------------+----------------+
+
+
+   The following macros allow manipulation of addresses in the
+   above formats.  */
+
 #define SPUADDR(spu, addr) \
   ((spu) != -1? (ULONGEST)1 << 63 | (ULONGEST)(spu) << 32 | (addr) : (addr))
+
 #define SPUADDR_SPU(addr) \
   (((addr) & (ULONGEST)1 << 63) \
-   ? (int) ((ULONGEST)(addr) >> 32 & 0x7fffffff) \
+   ? (int) ((ULONGEST)(addr) >> 32 & 0x3fffffff) \
    : -1)
+
 #define SPUADDR_ADDR(addr) \
   (((addr) & (ULONGEST)1 << 63)? (ULONGEST)(addr) & 0xffffffff : (addr))
 
+#define SPU_OVERLAY_LMA ((ULONGEST)1 << 62)
+
 #endif
index 3b61976..ca54ab7 100644 (file)
@@ -1,3 +1,8 @@
+2010-06-19  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
+
+       * gdb.arch/spu-ls.exp: New file.
+       * gdb.arch/spu-ls.c: Likewise.
+
 2010-06-18  Stan Shebs  <stan@codesourcery.com>
 
        * gdb.threads/thread-specific.exp: Add tests of $_thread.
diff --git a/gdb/testsuite/gdb.arch/spu-ls.c b/gdb/testsuite/gdb.arch/spu-ls.c
new file mode 100644 (file)
index 0000000..4cb651f
--- /dev/null
@@ -0,0 +1,31 @@
+/* Copyright 2010 Free Software Foundation, Inc.
+
+   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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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, see <http://www.gnu.org/licenses/>.
+
+   This file is part of the gdb testsuite.
+
+   Contributed by Ulrich Weigand <uweigand@de.ibm.com>.
+   Tests for SPU local-store access.  */
+
+char *ptr = (char *)0x12345678;
+
+char array[256];
+
+int
+main (unsigned long long speid, unsigned long long argp, 
+      unsigned long long envp)
+{
+  return 0;
+}
+
diff --git a/gdb/testsuite/gdb.arch/spu-ls.exp b/gdb/testsuite/gdb.arch/spu-ls.exp
new file mode 100644 (file)
index 0000000..967d057
--- /dev/null
@@ -0,0 +1,54 @@
+# Copyright 2010 Free Software Foundation, Inc.
+#
+# 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 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# 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, see <http://www.gnu.org/licenses/>.
+#
+# This file is part of the gdb testsuite.
+#
+# Contributed by Ulrich Weigand  <uweigand@de.ibm.com>.
+# Tests for SPU local-store access.
+
+if { ![istarget "spu-*-elf"] } then {
+  verbose "Skipping SPU-only testcase"
+  return
+}
+
+set testfile "spu-ls"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+set sources ${srcdir}/${subdir}/${srcfile}
+
+if { [gdb_compile $sources ${binfile} executable { debug }] != "" } {
+  return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if ![runto_main] then {
+  fail "Can't run to main"
+  return 0
+}
+
+gdb_test "print ptr" " = 0x12345678 \".*\"" "print ptr"
+gdb_test_no_output "set ptr = array + \$lslr + 1" "set ptr = array + \$lslr + 1"
+gdb_test_no_output "set array\[0\] = 1" "set array\[0\] = 1"
+gdb_test "print *ptr" " = 1 '\\\\001'" "print *ptr"
+gdb_test_no_output "set *ptr = 2" "set *ptr = 2"
+gdb_test "print array\[0\]" " = 2 '\\\\002'" "print array\[0\]"
+
+gdb_exit
+
+return 0