enum
{
- HasLinkRegister = (thechar == '5'),
+ HasLinkRegister = (thechar == '5' || thechar == '9'),
};
// TODO: Record enough information in new object files to
static int
callsize(void)
{
- if(thechar == '5')
+ if(HasLinkRegister)
return 0;
return RegSize;
}
Chain ch;
LSym *s;
- if(thechar == '9')
- return;
-
morestack = linklookup(ctxt, "runtime.morestack", 0);
newstack = linklookup(ctxt, "runtime.newstack", 0);
continue;
if(s->nosplit) {
- ctxt->cursym = s;
- ch.sym = s;
- stkcheck(&ch, 0);
- }
+ ctxt->cursym = s;
+ ch.sym = s;
+ stkcheck(&ch, 0);
+ }
}
for(s = ctxt->textp; s != nil; s = s->next) {
if(!s->nosplit) {
- ctxt->cursym = s;
- ch.sym = s;
- stkcheck(&ch, 0);
+ ctxt->cursym = s;
+ ch.sym = s;
+ stkcheck(&ch, 0);
+ }
}
}
-}
static int
stkcheck(Chain *up, int depth)
// function at top of safe zone once.
if(limit == StackLimit-callsize()) {
if(s->stkcheck)
- return 0;
+ return 0;
s->stkcheck = 1;
}
// to StackLimit beyond the frame size.
if(strncmp(r->sym->name, "runtime.morestack", 17) == 0) {
limit = StackLimit + s->locals;
- if(thechar == '5')
- limit += 4; // saved LR
+ if(HasLinkRegister)
+ limit += RegSize;
}
break;
break;
}
}
- }
+ }
return 0;
}
else
print("\t%d\tguaranteed after split check in %s\n", ch->limit, name);
} else {
- stkprint(ch->up, ch->limit + (!HasLinkRegister)*PtrSize);
+ stkprint(ch->up, ch->limit + (!HasLinkRegister)*RegSize);
if(!HasLinkRegister)
print("\t%d\ton entry to %s\n", ch->limit, name);
}
runtime·futex(addr, FUTEX_WAIT, val, nil, nil, 0);
return;
}
- // NOTE: tv_nsec is int64 on amd64, so this assumes a little-endian system.
+
+ // It's difficult to live within the no-split stack limits here.
+ // On ARM and 386, a 64-bit divide invokes a general software routine
+ // that needs more stack than we can afford. So we use timediv instead.
+ // But on real 64-bit systems, where words are larger but the stack limit
+ // is not, even timediv is too heavy, and we really need to use just an
+ // ordinary machine instruction.
+ // Sorry for the #ifdef.
+ // For what it's worth, the #ifdef eliminated an implicit little-endian assumption.
+#ifdef _64BIT
+ ts.tv_sec = ns / 1000000000LL;
+ ts.tv_nsec = ns % 1000000000LL;
+#else
ts.tv_nsec = 0;
ts.tv_sec = runtime·timediv(ns, 1000000000LL, (int32*)&ts.tv_nsec);
+#endif
runtime·futex(addr, FUTEX_WAIT, val, &ts, nil, 0);
}
return s
}
-//go:nosplit
func concatstring2(a [2]string) string {
return concatstrings(a[:])
}
-//go:nosplit
func concatstring3(a [3]string) string {
return concatstrings(a[:])
}
-//go:nosplit
func concatstring4(a [4]string) string {
return concatstrings(a[:])
}
-//go:nosplit
func concatstring5(a [5]string) string {
return concatstrings(a[:])
}
# Calling a nosplit function from a nosplit function requires
# having room for the saved caller PC and the called frame.
# Because ARM doesn't save LR in the leaf, it gets an extra 4 bytes.
+# Because Power64 doesn't save LR in the leaf, it gets an extra 8 bytes.
main 112 nosplit call f; f 0 nosplit
-main 116 nosplit call f; f 0 nosplit; REJECT amd64
+main 116 nosplit call f; f 0 nosplit
main 120 nosplit call f; f 0 nosplit; REJECT amd64
main 124 nosplit call f; f 0 nosplit; REJECT amd64 386
main 128 nosplit call f; f 0 nosplit; REJECT
# Calling a splitting function from a nosplit function requires
# having room for the saved caller PC of the call but also the
-# saved caller PC for the call to morestack. Again the ARM works
-# in less space.
+# saved caller PC for the call to morestack.
+# Again the ARM and Power64 work in less space.
main 104 nosplit call f; f 0 call f
main 108 nosplit call f; f 0 call f
main 112 nosplit call f; f 0 call f; REJECT amd64
switch goarch {
case "power64", "power64le":
ptrSize = 8
- fmt.Fprintf(&buf, "#define CALL BL\n#define REGISTER (R0)\n#define RET RETURN\n")
+ fmt.Fprintf(&buf, "#define CALL BL\n#define REGISTER (CTR)\n#define RET RETURN\n")
case "arm":
fmt.Fprintf(&buf, "#define CALL BL\n#define REGISTER (R0)\n")
case "amd64":