diff options
Diffstat (limited to 'libgo/runtime/go-memclr.c')
-rw-r--r-- | libgo/runtime/go-memclr.c | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/libgo/runtime/go-memclr.c b/libgo/runtime/go-memclr.c index b5d4975..53b8117 100644 --- a/libgo/runtime/go-memclr.c +++ b/libgo/runtime/go-memclr.c @@ -13,5 +13,48 @@ void memclrNoHeapPointers(void *, uintptr) void memclrNoHeapPointers (void *p1, uintptr len) { - __builtin_memset (p1, 0, len); + +#if !defined(__PPC64__) + __builtin_memset(p1, 0, len); +#else + int64 rem,drem,i; + uint64 offset; + volatile uint64 *vp; + + if (len == 0) { + return; + } + rem = len; + + offset = (uint64)p1 % 8; + // This memset is OK since it can't contain + // an 8 byte aligned pointer. + if ((rem < 8) || (offset > 0 && offset+rem <= 16)) { + __builtin_memset(p1, 0, rem); + return; + } + // Move initial bytes to get to 8 byte boundary + if (offset > 0) { + __builtin_memset(p1, 0, 8-offset); + p1 = (void*)((char*)p1+8-offset); + rem -= 8-offset; + } + + // If at least 8 bytes left, clear + drem = rem>>3; + + vp = (volatile uint64*)(p1); + // Without the use of volatile here, the compiler + // might convert the loop into a memset. + for (i=0; i<drem; i++) { + *vp = 0; + vp++; + rem -= 8; + } + p1 = (void*)((char*)p1 + 8*drem); + // Clear any remaining + if (rem > 0) { + __builtin_memset (p1, 0, rem); + } +#endif } |