From 097362fd2e01735b25b79c71ba6005cd38f81da0 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 30 Oct 2014 10:45:41 -0400 Subject: [dev.power64] runtime: match argument/return type signedness in power64x assembly Previously, the power64x runtime assembly was sloppy about using sign-extending versus zero-extending moves of arguments and return values. I think all of the cases that actually mattered have been fixed in recent CLs; this CL fixes up the few remaining mismatches. LGTM=rsc R=rsc, dave CC=golang-codereviews https://golang.org/cl/162480043 --- src/runtime/asm_power64x.s | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src/runtime') diff --git a/src/runtime/asm_power64x.s b/src/runtime/asm_power64x.s index f77658032e..b6eac96110 100644 --- a/src/runtime/asm_power64x.s +++ b/src/runtime/asm_power64x.s @@ -299,7 +299,7 @@ TEXT runtime·morestack_noctxt(SB),NOSPLIT,$-8-0 // Note: can't just "BR NAME(SB)" - bad inlining results. TEXT ·reflectcall(SB), NOSPLIT, $-8-24 - MOVW argsize+16(FP), R3 + MOVWZ argsize+16(FP), R3 DISPATCH(runtime·call16, 16) DISPATCH(runtime·call32, 32) DISPATCH(runtime·call64, 64) @@ -336,7 +336,7 @@ TEXT NAME(SB), WRAPPER, $MAXSIZE-24; \ NO_LOCAL_POINTERS; \ /* copy arguments to stack */ \ MOVD argptr+8(FP), R3; \ - MOVW argsize+16(FP), R4; \ + MOVWZ argsize+16(FP), R4; \ MOVD R1, R5; \ ADD $(8-1), R5; \ SUB $1, R3; \ @@ -354,8 +354,8 @@ TEXT NAME(SB), WRAPPER, $MAXSIZE-24; \ BL (CTR); \ /* copy return values back */ \ MOVD argptr+8(FP), R3; \ - MOVW argsize+16(FP), R4; \ - MOVW retoffset+20(FP), R6; \ + MOVWZ argsize+16(FP), R4; \ + MOVWZ retoffset+20(FP), R6; \ MOVD R1, R5; \ ADD R6, R5; \ ADD R6, R3; \ @@ -398,7 +398,7 @@ CALLFN(·call268435456, 268435456) CALLFN(·call536870912, 536870912) CALLFN(·call1073741824, 1073741824) -// bool cas(int32 *val, int32 old, int32 new) +// bool cas(uint32 *val, uint32 old, uint32 new) // Atomically: // if(*val == old){ // *val = new; @@ -407,8 +407,8 @@ CALLFN(·call1073741824, 1073741824) // return 0; TEXT runtime·cas(SB), NOSPLIT, $0-17 MOVD p+0(FP), R3 - MOVW old+8(FP), R4 - MOVW new+12(FP), R5 + MOVWZ old+8(FP), R4 + MOVWZ new+12(FP), R5 cas_again: SYNC LWAR (R3), R6 -- cgit v1.3-5-g45d5 From 36d417c0e380b8ea762812b415796cf4b0af72de Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 30 Oct 2014 11:17:26 -0400 Subject: [dev.power64] runtime: test CAS on large unsigned 32-bit numbers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds a test to runtime·check to ensure CAS of large unsigned 32-bit numbers does not accidentally sign-extend its arguments. LGTM=rsc R=rsc CC=golang-codereviews https://golang.org/cl/162490044 --- src/runtime/runtime.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/runtime') diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index f19f8e4be3..a684142848 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -226,6 +226,12 @@ runtime·check(void) if(z != 4) runtime·throw("cas4"); + z = 0xffffffff; + if(!runtime·cas(&z, 0xffffffff, 0xfffffffe)) + runtime·throw("cas5"); + if(z != 0xfffffffe) + runtime·throw("cas6"); + k = (byte*)0xfedcb123; if(sizeof(void*) == 8) k = (byte*)((uintptr)k<<10); -- cgit v1.3-5-g45d5 From 4cf28a11e3807f2f34785d6d4e6aac0821bac654 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 30 Oct 2014 12:08:21 -0400 Subject: [dev.power64] runtime: fix out-of-date comment in panic LGTM=bradfitz R=rsc, bradfitz CC=golang-codereviews https://golang.org/cl/162500043 --- src/runtime/panic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/runtime') diff --git a/src/runtime/panic.c b/src/runtime/panic.c index 46683b2b0c..b19fdd0e18 100644 --- a/src/runtime/panic.c +++ b/src/runtime/panic.c @@ -69,7 +69,7 @@ runtime·recovery_m(G *gp) // each call to deferproc. // (The pc we're returning to does pop pop // before it tests the return value.) - // On the arm there are 2 saved LRs mixed in too. + // On the arm and power there are 2 saved LRs mixed in too. if(thechar == '5' || thechar == '9') gp->sched.sp = (uintptr)argp - 4*sizeof(uintptr); else -- cgit v1.3-5-g45d5 From 8a09639ae8b02317d990ef8e8c5929baf96659cd Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 30 Oct 2014 15:58:30 -0400 Subject: [dev.power64] runtime: make asm_power64x.s go vet-clean No real problems found. Just lots of argument names that didn't quite match up. LGTM=rsc R=rsc, dave CC=golang-codereviews https://golang.org/cl/169790043 --- src/runtime/asm_power64x.s | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) (limited to 'src/runtime') diff --git a/src/runtime/asm_power64x.s b/src/runtime/asm_power64x.s index b6eac96110..e1f8a84aff 100644 --- a/src/runtime/asm_power64x.s +++ b/src/runtime/asm_power64x.s @@ -86,7 +86,7 @@ TEXT runtime·reginit(SB),NOSPLIT,$-8-0 // void gosave(Gobuf*) // save state in Gobuf; setjmp TEXT runtime·gosave(SB), NOSPLIT, $-8-8 - MOVD gobuf+0(FP), R3 + MOVD buf+0(FP), R3 MOVD R1, gobuf_sp(R3) MOVD LR, R31 MOVD R31, gobuf_pc(R3) @@ -99,7 +99,7 @@ TEXT runtime·gosave(SB), NOSPLIT, $-8-8 // void gogo(Gobuf*) // restore state from Gobuf; longjmp TEXT runtime·gogo(SB), NOSPLIT, $-8-8 - MOVD gobuf+0(FP), R5 + MOVD buf+0(FP), R5 MOVD gobuf_g(R5), g // make sure g is not nil MOVD 0(g), R4 MOVD gobuf_sp(R5), R1 @@ -299,7 +299,7 @@ TEXT runtime·morestack_noctxt(SB),NOSPLIT,$-8-0 // Note: can't just "BR NAME(SB)" - bad inlining results. TEXT ·reflectcall(SB), NOSPLIT, $-8-24 - MOVWZ argsize+16(FP), R3 + MOVWZ n+16(FP), R3 DISPATCH(runtime·call16, 16) DISPATCH(runtime·call32, 32) DISPATCH(runtime·call64, 64) @@ -335,8 +335,8 @@ TEXT ·reflectcall(SB), NOSPLIT, $-8-24 TEXT NAME(SB), WRAPPER, $MAXSIZE-24; \ NO_LOCAL_POINTERS; \ /* copy arguments to stack */ \ - MOVD argptr+8(FP), R3; \ - MOVWZ argsize+16(FP), R4; \ + MOVD arg+8(FP), R3; \ + MOVWZ n+16(FP), R4; \ MOVD R1, R5; \ ADD $(8-1), R5; \ SUB $1, R3; \ @@ -353,8 +353,8 @@ TEXT NAME(SB), WRAPPER, $MAXSIZE-24; \ PCDATA $PCDATA_StackMapIndex, $0; \ BL (CTR); \ /* copy return values back */ \ - MOVD argptr+8(FP), R3; \ - MOVWZ argsize+16(FP), R4; \ + MOVD arg+8(FP), R3; \ + MOVWZ n+16(FP), R4; \ MOVWZ retoffset+20(FP), R6; \ MOVD R1, R5; \ ADD R6, R5; \ @@ -398,7 +398,7 @@ CALLFN(·call268435456, 268435456) CALLFN(·call536870912, 536870912) CALLFN(·call1073741824, 1073741824) -// bool cas(uint32 *val, uint32 old, uint32 new) +// bool cas(uint32 *ptr, uint32 old, uint32 new) // Atomically: // if(*val == old){ // *val = new; @@ -406,7 +406,7 @@ CALLFN(·call1073741824, 1073741824) // } else // return 0; TEXT runtime·cas(SB), NOSPLIT, $0-17 - MOVD p+0(FP), R3 + MOVD ptr+0(FP), R3 MOVWZ old+8(FP), R4 MOVWZ new+12(FP), R5 cas_again: @@ -425,7 +425,7 @@ cas_fail: MOVD $0, R3 BR -5(PC) -// bool runtime·cas64(uint64 *val, uint64 old, uint64 new) +// bool runtime·cas64(uint64 *ptr, uint64 old, uint64 new) // Atomically: // if(*val == *old){ // *val = new; @@ -434,7 +434,7 @@ cas_fail: // return 0; // } TEXT runtime·cas64(SB), NOSPLIT, $0-25 - MOVD p+0(FP), R3 + MOVD ptr+0(FP), R3 MOVD old+8(FP), R4 MOVD new+16(FP), R5 cas64_again: @@ -475,12 +475,12 @@ TEXT runtime·atomicstoreuintptr(SB), NOSPLIT, $0-16 TEXT runtime·casp(SB), NOSPLIT, $0-25 BR runtime·cas64(SB) -// uint32 xadd(uint32 volatile *val, int32 delta) +// uint32 xadd(uint32 volatile *ptr, int32 delta) // Atomically: // *val += delta; // return *val; TEXT runtime·xadd(SB), NOSPLIT, $0-20 - MOVD p+0(FP), R4 + MOVD ptr+0(FP), R4 MOVW delta+8(FP), R5 SYNC LWAR (R4), R3 @@ -493,7 +493,7 @@ TEXT runtime·xadd(SB), NOSPLIT, $0-20 RETURN TEXT runtime·xadd64(SB), NOSPLIT, $0-24 - MOVD p+0(FP), R4 + MOVD ptr+0(FP), R4 MOVD delta+8(FP), R5 SYNC LDAR (R4), R3 @@ -506,7 +506,7 @@ TEXT runtime·xadd64(SB), NOSPLIT, $0-24 RETURN TEXT runtime·xchg(SB), NOSPLIT, $0-20 - MOVD p+0(FP), R4 + MOVD ptr+0(FP), R4 MOVW new+8(FP), R5 SYNC LWAR (R4), R3 @@ -518,7 +518,7 @@ TEXT runtime·xchg(SB), NOSPLIT, $0-20 RETURN TEXT runtime·xchg64(SB), NOSPLIT, $0-24 - MOVD p+0(FP), R4 + MOVD ptr+0(FP), R4 MOVD new+8(FP), R5 SYNC LDAR (R4), R3 @@ -651,7 +651,7 @@ TEXT runtime·setcallerpc(SB),NOSPLIT,$-8-16 RETURN TEXT runtime·getcallersp(SB),NOSPLIT,$0-16 - MOVD sp+0(FP), R3 + MOVD argp+0(FP), R3 SUB $8, R3 MOVD R3, ret+8(FP) RETURN @@ -695,22 +695,23 @@ TEXT runtime·aeshashstr(SB),NOSPLIT,$-8-0 TEXT runtime·memeq(SB),NOSPLIT,$-8-25 MOVD a+0(FP), R3 MOVD b+8(FP), R4 - MOVD count+16(FP), R5 + MOVD size+16(FP), R5 SUB $1, R3 SUB $1, R4 ADD R3, R5, R8 loop: CMP R3, R8 - BNE 4(PC) + BNE test MOVD $1, R3 MOVB R3, ret+24(FP) RETURN +test: MOVBZU 1(R3), R6 MOVBZU 1(R4), R7 CMP R6, R7 BEQ loop - MOVB R0, ret+24(FP) + MOVB $0, ret+24(FP) RETURN // eqstring tests whether two strings are equal. -- cgit v1.3-5-g45d5 From c24156bafe24a82ca4c182f289b1bff121ea72e0 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 30 Oct 2014 16:44:42 -0400 Subject: [dev.power64] runtime: fix a syntax error that slipped in to asm_power64x.s Apparently I had already moved on to fixing another problem when I submitted CL 169790043. LGTM=dave R=rsc, dave CC=golang-codereviews https://golang.org/cl/165210043 --- src/runtime/asm_power64x.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/runtime') diff --git a/src/runtime/asm_power64x.s b/src/runtime/asm_power64x.s index e1f8a84aff..ab2db061c2 100644 --- a/src/runtime/asm_power64x.s +++ b/src/runtime/asm_power64x.s @@ -711,7 +711,7 @@ test: CMP R6, R7 BEQ loop - MOVB $0, ret+24(FP) + MOVB R0, ret+24(FP) RETURN // eqstring tests whether two strings are equal. -- cgit v1.3-5-g45d5 From 6e86003651be7feb6da46360d6c411ff1c29b7f5 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Fri, 31 Oct 2014 11:08:27 -0400 Subject: [dev.power64] 9g: fix under-zeroing in clearfat All three cases of clearfat were wrong on power64x. The cases that handle 1032 bytes and up and 32 bytes and up both use MOVDU (one directly generated in a loop and the other via duffzero), which leaves the pointer register pointing at the *last written* address. The generated code was not accounting for this, so the byte fill loop was re-zeroing the last zeroed dword, rather than the bytes following the last zeroed dword. Fix this by simply adding an additional 8 byte offset to the byte zeroing loop. The case that handled under 32 bytes was also wrong. It didn't update the pointer register at all, so the byte zeroing loop was simply re-zeroing the beginning of region. Again, the fix is to add an offset to the byte zeroing loop to account for this. LGTM=dave, bradfitz R=rsc, dave, bradfitz CC=golang-codereviews https://golang.org/cl/168870043 --- src/cmd/9g/ggen.c | 20 +++++++++----- src/runtime/asm_power64x.s | 2 +- test/clearfat.go | 68 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 8 deletions(-) create mode 100644 test/clearfat.go (limited to 'src/runtime') diff --git a/src/cmd/9g/ggen.c b/src/cmd/9g/ggen.c index c41d8eb414..7d9cf5050d 100644 --- a/src/cmd/9g/ggen.c +++ b/src/cmd/9g/ggen.c @@ -900,7 +900,7 @@ ret: void clearfat(Node *nl) { - uint64 w, c, q, t; + uint64 w, c, q, t, boff; Node dst, end, r0, *f; Prog *p, *pl; @@ -944,6 +944,8 @@ clearfat(Node *nl) patch(gbranch(ABNE, T, 0), pl); regfree(&end); + // The loop leaves R3 on the last zeroed dword + boff = 8; } else if(q >= 4) { p = gins(ASUB, N, &dst); p->from.type = D_CONST; @@ -953,17 +955,21 @@ clearfat(Node *nl) afunclit(&p->to, f); // 4 and 128 = magic constants: see ../../runtime/asm_power64x.s p->to.offset = 4*(128-q); - } else - for(t = 0; t < q; t++) { - p = gins(AMOVD, &r0, &dst); - p->to.type = D_OREG; - p->to.offset = 8*t; + // duffzero leaves R3 on the last zeroed dword + boff = 8; + } else { + for(t = 0; t < q; t++) { + p = gins(AMOVD, &r0, &dst); + p->to.type = D_OREG; + p->to.offset = 8*t; + } + boff = 8*q; } for(t = 0; t < c; t++) { p = gins(AMOVB, &r0, &dst); p->to.type = D_OREG; - p->to.offset = t; + p->to.offset = t+boff; } reg[REGRT1]--; } diff --git a/src/runtime/asm_power64x.s b/src/runtime/asm_power64x.s index ab2db061c2..2ad3e56e94 100644 --- a/src/runtime/asm_power64x.s +++ b/src/runtime/asm_power64x.s @@ -829,7 +829,7 @@ notfound: // in ../../cmd/9g/ggen.c:/^clearfat. // R0: always zero // R3 (aka REGRT1): ptr to memory to be zeroed - 8 -// R3 is updated as a side effect. +// On return, R3 points to the last zeroed dword. TEXT runtime·duffzero(SB), NOSPLIT, $-8-0 MOVDU R0, 8(R3) MOVDU R0, 8(R3) diff --git a/test/clearfat.go b/test/clearfat.go new file mode 100644 index 0000000000..45d539306e --- /dev/null +++ b/test/clearfat.go @@ -0,0 +1,68 @@ +// runoutput + +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Check that {5,6,8,9}g/ggen.c:clearfat is zeroing the entire object. + +package main + +import ( + "bytes" + "fmt" + "strconv" + "strings" +) + +const ntest = 1100 + +func main() { + var decls, calls bytes.Buffer + + for i := 1; i <= ntest; i++ { + s := strconv.Itoa(i) + decls.WriteString(strings.Replace(decl, "$", s, -1)) + calls.WriteString(strings.Replace("poison$()\n\tclearfat$()\n\t", "$", s, -1)) + } + + program = strings.Replace(program, "$DECLS", decls.String(), 1) + program = strings.Replace(program, "$CALLS", calls.String(), 1) + fmt.Print(program) +} + +var program = `package main + +var count int + +$DECLS + +func main() { + $CALLS + if count != 0 { + println("failed", count, "case(s)") + } +} +` + +const decl = ` +func poison$() { + // Grow and poison the stack space that will be used by clearfat$ + var t [2*$]byte + for i := range t { + t[i] = 0xff + } +} + +func clearfat$() { + var t [$]byte + + for _, x := range t { + if x != 0 { +// println("clearfat$: index", i, "expected 0, got", x) + count++ + break + } + } +} +` -- cgit v1.3-5-g45d5 From 40a5b3ecb1578a68b0423b8ef4eaebd5fb4c7869 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Fri, 31 Oct 2014 13:39:36 -0400 Subject: [dev.power64] runtime: fix fastrand1 on power64x fastrand1 depends on testing the high bit of its uint32 state. For efficiency, all of the architectures implement this as a sign bit test. However, on power64, fastrand1 was using a 64-bit sign test on the zero-extended 32-bit state. This always failed, causing fastrand1 to have very short periods and often decay to 0 and get stuck. Fix this by using a 32-bit signed compare instead of a 64-bit compare. This fixes various tests for the randomization of select of map iteration. LGTM=rsc R=rsc, dave CC=golang-codereviews https://golang.org/cl/166990043 --- src/runtime/asm_power64x.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/runtime') diff --git a/src/runtime/asm_power64x.s b/src/runtime/asm_power64x.s index 2ad3e56e94..713cc5f549 100644 --- a/src/runtime/asm_power64x.s +++ b/src/runtime/asm_power64x.s @@ -965,7 +965,7 @@ TEXT runtime·fastrand1(SB), NOSPLIT, $0-4 MOVD g_m(g), R4 MOVWZ m_fastrand(R4), R3 ADD R3, R3 - CMP R3, $0 + CMPW R3, $0 BGE 2(PC) XOR $0x88888eef, R3 MOVW R3, m_fastrand(R4) -- cgit v1.3-5-g45d5 From e1db508ffdcfbb78a73c6df7e3d0a6b0cb6f001a Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Fri, 31 Oct 2014 16:58:12 -0400 Subject: [dev.power64] runtime: fix gcinfo_test on power64x The GC info masks for slices and strings were changed in commit caab29a25f68, but the reference masks used by gcinfo_test for power64x hadn't caught up. Now they're identical to amd64, so this CL fixes this test by combining the reference masks for these platforms. LGTM=rsc R=rsc, dave CC=golang-codereviews https://golang.org/cl/162620044 --- src/runtime/gcinfo_test.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'src/runtime') diff --git a/src/runtime/gcinfo_test.go b/src/runtime/gcinfo_test.go index 7d432983b1..2c6d4d662f 100644 --- a/src/runtime/gcinfo_test.go +++ b/src/runtime/gcinfo_test.go @@ -137,7 +137,7 @@ func infoBigStruct() []byte { BitsScalar, BitsScalar, BitsScalar, BitsScalar, // t int; y uint16; u uint64 BitsPointer, BitsDead, // i string } - case "amd64": + case "amd64", "power64", "power64le": return []byte{ BitsPointer, // q *int BitsScalar, BitsScalar, BitsScalar, // w byte; e [17]byte @@ -153,12 +153,6 @@ func infoBigStruct() []byte { BitsScalar, BitsScalar, BitsDead, BitsScalar, BitsScalar, // t int; y uint16; u uint64 BitsPointer, BitsDead, // i string } - case "power64", "power64le": - return []byte{ - BitsPointer, BitsScalar, BitsScalar, BitsScalar, - BitsMultiWord, BitsSlice, BitsScalar, BitsScalar, - BitsScalar, BitsScalar, BitsMultiWord, BitsString, - } default: panic("unknown arch") } -- cgit v1.3-5-g45d5