aboutsummaryrefslogtreecommitdiff
path: root/libgloss/spu/sbrk.c
diff options
context:
space:
mode:
authorBen Elliston <bje@gnu.org>2007-03-01 23:08:21 +0000
committerBen Elliston <bje@gnu.org>2007-03-01 23:08:21 +0000
commit538b71077d1f936bbe1700b1db94c700fcff344a (patch)
treeb86f2cbee0162c9311f182e02a6f9b64a416fa7a /libgloss/spu/sbrk.c
parente943a1a37ee4febeb856c39d03e6d38692f6a3e6 (diff)
downloadnewlib-538b71077d1f936bbe1700b1db94c700fcff344a.zip
newlib-538b71077d1f936bbe1700b1db94c700fcff344a.tar.gz
newlib-538b71077d1f936bbe1700b1db94c700fcff344a.tar.bz2
* spu/sbrk.c (sbrk): Adjust the stack pointer vector correctly so
that GCC runtime stack checking works. Handle the backchain, too.
Diffstat (limited to 'libgloss/spu/sbrk.c')
-rw-r--r--libgloss/spu/sbrk.c36
1 files changed, 28 insertions, 8 deletions
diff --git a/libgloss/spu/sbrk.c b/libgloss/spu/sbrk.c
index c95a7e8..b0528c3 100644
--- a/libgloss/spu/sbrk.c
+++ b/libgloss/spu/sbrk.c
@@ -32,6 +32,7 @@ Author: Andreas Neukoetter (ti95neuk@de.ibm.com)
#include <sys/types.h>
#include <errno.h>
+#include <spu_intrinsics.h>
extern int errno;
@@ -44,20 +45,39 @@ sbrk (ptrdiff_t increment)
{
static caddr_t heap_ptr = NULL;
caddr_t base;
+ vector unsigned int sp_reg, sp_delta;
+ vector unsigned int *sp_ptr;
+ /* The stack pointer register. */
+ volatile register vector unsigned int sp_r1 __asm__("1");
+
if (heap_ptr == NULL)
- {
- heap_ptr = (caddr_t) & _end;
- }
+ heap_ptr = (caddr_t) & _end;
+
if (((RAMSIZE - STACKSIZE) - (int) heap_ptr) >= increment)
{
- base = heap_ptr;
- heap_ptr += increment;
- return (base);
+ base = heap_ptr;
+ heap_ptr += increment;
+
+ sp_delta = (vector unsigned int) spu_insert (increment, spu_splats (0), 1);
+
+ /* Subtract sp_delta from the SP limit (word 1). */
+ sp_r1 = spu_sub (sp_r1, sp_delta);
+
+ /* Fix-up backchain. */
+ sp_ptr = (vector unsigned int *) spu_extract (sp_r1, 0);
+ do
+ {
+ sp_reg = *sp_ptr;
+ *sp_ptr = (vector unsigned int) spu_sub (sp_reg, sp_delta);
+ }
+ while ((sp_ptr = (vector unsigned int *) spu_extract (sp_reg, 0)));
+
+ return (base);
}
else
{
- errno = ENOMEM;
- return ((void *) -1);
+ errno = ENOMEM;
+ return ((void *) -1);
}
}