shithub: riscv

Download patch

ref: a0c756078220916db7aef3538502e1d70d4d6a77
parent: fb1eadf6ed68ddf810551057709debbdbfd7938a
author: Jacob Moody <moody@posixcafe.org>
date: Sun Dec 31 18:58:47 EST 2023

libc: add _callmain to share more initialization code

Before each arch had to implement the _privates array
themselves in assembly, which meant it was quite easy
for them to get out of sync. This cleans this up to be
a single enum and shares this initialization code.

--- a/sys/src/libc/386/argv0.s
+++ b/sys/src/libc/386/argv0.s
@@ -1,4 +1,2 @@
 GLOBL	argv0(SB), $4
 GLOBL	_tos(SB), $4
-GLOBL	_privates(SB), $4
-GLOBL	_nprivates(SB), $4
--- a/sys/src/libc/386/main9.s
+++ b/sys/src/libc/386/main9.s
@@ -1,21 +1,7 @@
-#define NPRIVATES	16
-
-TEXT	_main(SB), 1, $(8+NPRIVATES*4)
+TEXT	_main(SB), 1, $0
 	MOVL	AX, _tos(SB)
-	LEAL	8(SP), AX
-	MOVL	AX, _privates(SB)
-	MOVL	$NPRIVATES, _nprivates(SB)
-	MOVL	inargc-4(FP), AX
-	MOVL	AX, 0(SP)
-	LEAL	inargv+0(FP), AX
-	MOVL	AX, 4(SP)
-	CALL	main(SB)
-
-loop:
-	MOVL	$_exits<>(SB), AX
-	MOVL	AX, 0(SP)
-	CALL	exits(SB)
-	JMP	loop
-
-DATA	_exits<>+0(SB)/4, $"main"
-GLOBL	_exits<>+0(SB), $5
+	MOVL	$main(SB), AX
+	PUSHL	AX
+	PUSHL	$0
+	MOVL	$_callmain(SB), AX
+	JMP*	AX
--- a/sys/src/libc/386/main9p.s
+++ b/sys/src/libc/386/main9p.s
@@ -1,30 +1,11 @@
-#define NPRIVATES	16
-
-TEXT	_mainp(SB), 1, $(8+NPRIVATES*4)
-	/* _tos = arg */
+TEXT	_mainp(SB), 1, $0
 	MOVL	AX, _tos(SB)
-	LEAL	8(SP), AX
-	MOVL	AX, _privates(SB)
-	MOVL	$NPRIVATES, _nprivates(SB)
-	/* _profmain(); */
-	CALL	_profmain(SB)
-	/* _tos->prof.pp = _tos->prof.next; */
-	MOVL	_tos+0(SB),DX
-	MOVL	4(DX),CX
-	MOVL	CX,(DX)
-	/* main(argc, argv); */
-	MOVL	inargc-4(FP), AX
-	MOVL	AX, 0(SP)
-	LEAL	inargv+0(FP), AX
-	MOVL	AX, 4(SP)
-	CALL	main(SB)
-
-loop:
-	MOVL	$_exits<>(SB), AX
-	MOVL	AX, 0(SP)
-	CALL	exits(SB)
+	MOVL	$_profmain(SB), AX
+	PUSHL	AX
+	PUSHL	$0
+	MOVL	$_callmain(SB), AX
+	JMP*	AX
 	MOVL	$_profin(SB), AX	/* force loading of profile */
-	JMP	loop
 
 TEXT	_saveret(SB), 1, $0
 TEXT	_savearg(SB), 1, $0
@@ -34,6 +15,3 @@
 	MOVL	argp+0(FP), AX
 	MOVL	4(AX), AX
 	RET
-
-DATA	_exits<>+0(SB)/4, $"main"
-GLOBL	_exits<>+0(SB), $5
--- a/sys/src/libc/68000/argv0.s
+++ b/sys/src/libc/68000/argv0.s
@@ -1,4 +1,2 @@
 GLOBL	argv0(SB), $4
 GLOBL	_tos(SB), $4
-GLOBL	_privates(SB), $4
-GLOBL	_nprivates(SB), $4
--- a/sys/src/libc/68000/main9.s
+++ b/sys/src/libc/68000/main9.s
@@ -1,18 +1,6 @@
-#define NPRIVATES	16
-
-TEXT	_main(SB), 1, $(16 + NPRIVATES*4)
+TEXT	_main(SB), 1, $0
 	MOVL	$a6base(SB), A6
 	MOVL	R0, _tos(SB)
-	LEA	p-64(SP),A0
-	MOVL	A0,_privates+0(SB)
-	MOVL	$16,R0
-	MOVL	R0,_nprivates+0(SB)
-	PEA	inargv+0(FP)
-	MOVL	inargc-4(FP), TOS
-	BSR	main(SB)
-	PEA	_exits<>+0(SB)
-	BSR	exits(SB)
-	RTS
-
-DATA	_exits<>+0(SB)/4, $"main"
-GLOBL	_exits<>+0(SB), $5
+	PEA	main(SB)
+	MOVL	$0, TOS
+	JMP	_callmain(SB)
--- a/sys/src/libc/68000/main9p.s
+++ b/sys/src/libc/68000/main9p.s
@@ -1,23 +1,10 @@
-#define NPRIVATES	16
-
-TEXT	_mainp(SB), 1, $(16 + NPRIVATES*4)
+TEXT	_mainp(SB), 1, $0
 	MOVL	$a6base(SB), A6
-	MOVL	R0, _tos(SB)		/* return value of sys exec!! */
-	LEA	p-64(SP),A0
-	MOVL	A0,_privates+0(SB)
-	MOVL	$16,R0
-	MOVL	R0,_nprivates+0(SB)
-	BSR	_profmain(SB)
-	MOVL	__prof+4(SB), __prof+0(SB)
-	PEA	inargv+0(FP)
-	MOVL	inargc-4(FP), TOS
-	BSR	main(SB)
-
-loop:
-	PEA	_exits<>+0(SB)
-	BSR	exits(SB)
+	MOVL	R0, _tos(SB)
+	PEA	_profmain(SB)
+	MOVL	$0, TOS
+	JMP	_callmain(SB)
 	LEA	_profin(SB), A0		/* force loading of profile */
-	BRA	loop
 
 TEXT	_saveret(SB), 1, $0
 TEXT	_savearg(SB), 1, $0
@@ -27,6 +14,3 @@
 	MOVL	argp+0(FP), A0
 	MOVL	4(A0), R0
 	RTS
-
-DATA	_exits<>+0(SB)/4, $"main"
-GLOBL	_exits<>+0(SB), $5
--- a/sys/src/libc/68020/argv0.s
+++ b/sys/src/libc/68020/argv0.s
@@ -1,4 +1,2 @@
 GLOBL	argv0(SB), $4
 GLOBL	_tos(SB), $4
-GLOBL	_privates(SB), $4
-GLOBL	_nprivates(SB), $4
--- a/sys/src/libc/68020/main9.s
+++ b/sys/src/libc/68020/main9.s
@@ -1,19 +1,6 @@
-#define NPRIVATES	16
-
-TEXT	_main(SB), 1, $(16 + NPRIVATES*4)
+TEXT	_main(SB), 1, $0
 	MOVL	$a6base(SB), A6
 	MOVL	R0, _tos(SB)
-	LEA	p-64(SP),A0
-	MOVL	A0,_privates+0(SB)
-	MOVL	$16,R0
-	MOVL	R0,_nprivates+0(SB)
-	PEA	inargv+0(FP)
-	MOVL	inargc-4(FP), TOS
-	BSR	main(SB)
-	MOVL	$_exits<>+0(SB), R0
-	MOVL	R0,TOS
-	BSR	exits(SB)
-	RTS
-
-DATA	_exits<>+0(SB)/4, $"main"
-GLOBL	_exits<>+0(SB), $5
+	PEA	main(SB)
+	MOVL	$0, TOS
+	JMP	_callmain(SB)
--- a/sys/src/libc/68020/main9p.s
+++ b/sys/src/libc/68020/main9p.s
@@ -1,24 +1,10 @@
-#define NPRIVATES	16
-
-TEXT	_mainp(SB), 1, $(16 + NPRIVATES*4)
+TEXT	_mainp(SB), 1, $0
 	MOVL	$a6base(SB), A6
-	MOVL	R0, _tos(SB)		/* return value of sys exec!! */
-	LEA	p-64(SP),A0
-	MOVL	A0,_privates+0(SB)
-	MOVL	$16,R0
-	MOVL	R0,_nprivates+0(SB)
-	BSR	_profmain(SB)
-	MOVL	__prof+4(SB), __prof+0(SB)
-	PEA	inargv+0(FP)
-	MOVL	inargc-4(FP), TOS
-	BSR	main(SB)
-
-loop:
-	MOVL	$_exits<>+0(SB), R0
-	MOVL	R0,TOS
-	BSR	exits(SB)
+	MOVL	R0, _tos(SB)
+	PEA	_profmain(SB)
+	MOVL	$0, TOS
+	JMP	_callmain(SB)
 	LEA	_profin(SB), A0		/* force loading of profile */
-	BRA	loop
 
 TEXT	_saveret(SB), 1, $0
 TEXT	_savearg(SB), 1, $0
@@ -28,6 +14,3 @@
 	MOVL	argp+0(FP), A0
 	MOVL	4(A0), R0
 	RTS
-
-DATA	_exits<>+0(SB)/4, $"main"
-GLOBL	_exits<>+0(SB), $5
--- /dev/null
+++ b/sys/src/libc/9sys/callmain.c
@@ -1,0 +1,24 @@
+#include <u.h>
+#include <libc.h>
+
+void **_privates;
+int _nprivates;
+
+enum{
+	NPRIVATES=16,
+};
+
+#pragma profile off
+
+void
+_callmain(void (*main)(int, char**), int argc, char *arg0)
+{
+	void *privates[NPRIVATES];
+
+	_privates = privates;
+	_nprivates = NPRIVATES;
+	main(argc, &arg0);
+	exits("main");
+}
+
+#pragma profile on
--- a/sys/src/libc/9sys/mkfile
+++ b/sys/src/libc/9sys/mkfile
@@ -5,6 +5,7 @@
 	abort.$O\
 	access.$O\
 	announce.$O\
+	callmain.$O\
 	convD2M.$O\
 	convM2D.$O\
 	convM2S.$O\
--- a/sys/src/libc/amd64/argv0.s
+++ b/sys/src/libc/amd64/argv0.s
@@ -1,4 +1,2 @@
 GLOBL	argv0(SB), $8
 GLOBL	_tos(SB), $8
-GLOBL	_privates(SB), $8
-GLOBL	_nprivates(SB), $4
--- a/sys/src/libc/amd64/main9.s
+++ b/sys/src/libc/amd64/main9.s
@@ -1,19 +1,7 @@
-#define NPRIVATES	16
-
-TEXT	_main(SB), 1, $(2*8+NPRIVATES*8)
+TEXT	_main(SB), 1, $0
 	MOVQ	AX, _tos(SB)
-	LEAQ	16(SP), AX
-	MOVQ	AX, _privates(SB)
-	MOVL	$NPRIVATES, _nprivates(SB)
-	MOVL	inargc-8(FP), RARG
-	LEAQ	inargv+0(FP), AX
-	MOVQ	AX, 8(SP)
-	CALL	main(SB)
-
-loop:
-	MOVQ	$_exits<>(SB), RARG
-	CALL	exits(SB)
-	JMP	loop
-
-DATA	_exits<>+0(SB)/4, $"main"
-GLOBL	_exits<>+0(SB), $5
+	MOVQ	$main(SB), RARG
+	PUSHQ	RARG
+	PUSHQ	$0
+	MOVQ	$_callmain(SB), AX
+	JMP*	AX
--- a/sys/src/libc/amd64/main9p.s
+++ b/sys/src/libc/amd64/main9p.s
@@ -1,27 +1,12 @@
-#define NPRIVATES	16
+TEXT	_mainp(SB), 1, $0
+	MOVQ	AX, _tos(SB)
+	MOVQ	$_profmain(SB), RARG
+	PUSHQ	RARG
+	PUSHQ	$0
+	MOVQ	$_callmain(SB), AX
+	JMP*	AX
 
-TEXT _mainp(SB), 1, $(2*8+NPRIVATES*8)
-	MOVQ	AX, _tos(SB)		/* _tos = arg */
-	LEAQ	16(SP), AX
-	MOVQ	AX, _privates(SB)
-	MOVL	$NPRIVATES, _nprivates(SB)
-
-	CALL	_profmain(SB)		/* _profmain(); */
-
-	MOVQ	_tos+0(SB), DX		/* _tos->prof.pp = _tos->prof.next; */
-	MOVQ	8(DX), CX
-	MOVQ	CX, (DX)
-
-	MOVL	inargc-8(FP), RARG	/* main(argc, argv); */
-	LEAQ	inargv+0(FP), AX
-	MOVQ	AX, 8(SP)
-	CALL	main(SB)
-
-loop:
-	MOVQ	$_exits<>(SB), RARG
-	CALL	exits(SB)
 	MOVQ	$_profin(SB), AX	/* force loading of profile */
-	JMP	loop
 
 TEXT	_savearg(SB), 1, $0
 	MOVQ	RARG, AX
@@ -33,6 +18,3 @@
 TEXT	_callpc(SB), 1, $0
 	MOVQ	8(RARG), AX
 	RET
-
-DATA	_exits<>+0(SB)/4, $"main"
-GLOBL	_exits<>+0(SB), $5
--- a/sys/src/libc/arm/argv0.s
+++ b/sys/src/libc/arm/argv0.s
@@ -1,4 +1,2 @@
 GLOBL	argv0(SB), $4
 GLOBL	_tos(SB), $4
-GLOBL	_privates(SB), $4
-GLOBL	_nprivates(SB), $4
--- a/sys/src/libc/arm/main9.s
+++ b/sys/src/libc/arm/main9.s
@@ -1,29 +1,15 @@
-#define NPRIVATES	16
-
 arg=0
 sp=13
 sb=12
+lr=14
 
-TEXT	_main(SB), 1, $(16 + NPRIVATES*4)
+TEXT	_main(SB), 1, $0
+	SUB	$8, R(sp)
 	MOVW	$setR12(SB), R(sb)
 	MOVW	R(arg), _tos(SB)
 
-	MOVW	$p-64(SP), R1
-	MOVW	R1, _privates(SB)
-	MOVW	$NPRIVATES, R1
-	MOVW	R1, _nprivates(SB)
+	MOVW	$main(SB), R(arg)
+	MOVW	$0, R(lr)
+	B	_callmain(SB)
 
-	MOVW	$inargv+0(FP), R(arg)
-	MOVW	R(arg), 8(R(sp))
-	MOVW	inargc-4(FP), R(arg)
-	MOVW	R(arg), 4(R(sp))
-	BL	main(SB)
-loop:
-	MOVW	$_exitstr<>(SB), R(arg)
-	MOVW	R(arg), 4(R(sp))
-	BL	exits(SB)
-	BL	_div(SB)
-	B	loop
-
-DATA	_exitstr<>+0(SB)/4, $"main"
-GLOBL	_exitstr<>+0(SB), $5
+	BL	_div(SB)	/* force loading of div */
--- a/sys/src/libc/arm/main9p.s
+++ b/sys/src/libc/arm/main9p.s
@@ -1,35 +1,19 @@
-#define NPRIVATES	16
-
 arg=0
 sp=13
 sb=12
+lr=14
 
-TEXT	_mainp(SB), 1, $(16 + NPRIVATES*4)
+TEXT	_mainp(SB), 1, $0
+	SUB	$8, R(sp)
 	MOVW	$setR12(SB), R(sb)
 	MOVW	R(arg), _tos(SB)
 
-	MOVW	$p-64(SP), R1
-	MOVW	R1, _privates(SB)
-	MOVW	$NPRIVATES, R1
-	MOVW	R1, _nprivates(SB)
+	MOVW	$_profmain(SB), R(arg)
+	MOVW	$0, R(lr)
+	B	_callmain(SB)
 
-	BL	_profmain(SB)
-	MOVW	_tos(SB), R1
-	MOVW	4(R1), R0
-	MOVW	R0, 0(R1)
-
-	MOVW	$inargv+0(FP), R(arg)
-	MOVW	R(arg), 8(R(sp))
-	MOVW	inargc-4(FP), R(arg)
-	MOVW	R(arg), 4(R(sp))
-	BL	main(SB)
-loop:
-	MOVW	$_exitstr<>(SB), R(arg)
-	MOVW	R(arg), 4(R(sp))
-	BL	exits(SB)
 	MOVW	$_div(SB), R(arg)	/* force loading of div */
 	MOVW	$_profin(SB), R(arg)	/* force loading of profile */
-	B	loop
 
 TEXT	_saveret(SB), 1, $0
 TEXT	_savearg(SB), 1, $0
@@ -38,6 +22,3 @@
 TEXT	_callpc(SB), 1, $-4
 	MOVW	0(R13), R(arg)
 	RET
-
-DATA	_exitstr<>+0(SB)/4, $"main"
-GLOBL	_exitstr<>+0(SB), $5
--- a/sys/src/libc/arm64/argv0.s
+++ b/sys/src/libc/arm64/argv0.s
@@ -1,4 +1,2 @@
 GLOBL	argv0(SB), $8
 GLOBL	_tos(SB), $8
-GLOBL	_privates(SB), $8
-GLOBL	_nprivates(SB), $4
--- a/sys/src/libc/arm64/main9.s
+++ b/sys/src/libc/arm64/main9.s
@@ -1,25 +1,9 @@
-#define NPRIVATES	16
-
-TEXT	_main(SB), 1, $(16 + NPRIVATES*8)
+TEXT	_main(SB), 1, $0
+	SUB	$16, SP
 	MOV	$setSB(SB), R28
 	MOV	R0, _tos(SB)
 
-	ADD	$32, RSP, R1
-	MOV	R1, _privates(SB)
-	MOVW	$NPRIVATES, R2
-	MOVW	R2, _nprivates(SB)
+	MOV	$main(SB), R0
 
-	MOV	$inargv+0(FP), R1
-	MOV	R1, 16(RSP)
-
-	MOVW	inargc-8(FP), R0
-	MOV	R0, 8(RSP)
-
-	BL	main(SB)
-loop:
-	MOV	$_exitstr<>(SB), R0
-	BL	exits(SB)
-	B	loop
-
-DATA	_exitstr<>+0(SB)/4, $"main"
-GLOBL	_exitstr<>+0(SB), $5
+	MOV	$0, R30
+	B	_callmain(SB)
--- a/sys/src/libc/arm64/main9p.s
+++ b/sys/src/libc/arm64/main9p.s
@@ -1,32 +1,14 @@
-#define NPRIVATES	16
-
-TEXT	_mainp(SB), 1, $(16 + NPRIVATES*8)
+TEXT	_mainp(SB), 1, $0
+	SUB	$16, SP
 	MOV	$setSB(SB), R28
 	MOV	R0, _tos(SB)
 
-	ADD	$32, RSP, R1
-	MOV	R1, _privates(SB)
-	MOVW	$NPRIVATES, R2
-	MOVW	R2, _nprivates(SB)
+	MOV	$_profmain(SB), R0
 
-	BL	_profmain(SB)
+	MOV	$0, R30
+	B	_callmain(SB)
 
-	MOV	_tos(SB), R0	/* _tos->prof.pp = _tos->prof.next; */
-	MOV	8(R0), R1
-	MOV	R1, 0(R0)
-
-	MOV	$inargv+0(FP), R1
-	MOV	R1, 16(RSP)
-
-	MOVW	inargc-8(FP), R0
-	MOV	R0, 8(RSP)
-
-	BL	main(SB)
-loop:
-	MOV	$_exitstr<>(SB), R0
-	BL	exits(SB)
 	MOV	$_profin(SB), R0
-	B	loop
 
 TEXT	_callpc(SB), 1, $-4
 	MOV	0(SP), R0
@@ -33,6 +15,3 @@
 TEXT	_saveret(SB), 1, $-4
 TEXT	_savearg(SB), 1, $-4
 	RETURN
-
-DATA	_exitstr<>+0(SB)/4, $"main"
-GLOBL	_exitstr<>+0(SB), $5
--- a/sys/src/libc/mips/argv0.s
+++ b/sys/src/libc/mips/argv0.s
@@ -1,4 +1,2 @@
 GLOBL	argv0(SB), $4
 GLOBL	_tos(SB), $4
-GLOBL	_privates(SB), $4
-GLOBL	_nprivates(SB), $4
--- a/sys/src/libc/mips/main9.s
+++ b/sys/src/libc/mips/main9.s
@@ -1,25 +1,8 @@
-#define NPRIVATES	16
-
-TEXT	_main(SB), 1, $(16 + NPRIVATES*4)
-
+TEXT	_main(SB), 1, $0
+	ADD	$-8, R29
 	MOVW	$setR30(SB), R30
 	MOVW	R1, _tos(SB)
 
-	MOVW	$p-64(SP), R1
-	MOVW	R1, _privates(SB)
-	MOVW	$NPRIVATES, R1
-	MOVW	R1, _nprivates(SB)
-
-	MOVW	inargc-4(FP), R1
-	MOVW	$inargv+0(FP), R2
-	MOVW	R1, 4(R29)
-	MOVW	R2, 8(R29)
-	JAL	main(SB)
-loop:
-	MOVW	$_exitstr<>(SB), R1
-	MOVW	R1, 4(R29)
-	JAL	exits(SB)
-	JMP	loop
-
-DATA	_exitstr<>+0(SB)/4, $"main"
-GLOBL	_exitstr<>+0(SB), $5
+	MOVW	$main(SB), R1
+	MOVW	$0, R31
+	JMP	_callmain(SB)
--- a/sys/src/libc/mips/main9p.s
+++ b/sys/src/libc/mips/main9p.s
@@ -1,29 +1,12 @@
-#define NPRIVATES	16
-
-TEXT	_mainp(SB), 1, $(16 + NPRIVATES*4)
-
+TEXT	_mainp(SB), 1, $0
+	ADD	$-8, R29
 	MOVW	$setR30(SB), R30
 	MOVW	R1, _tos(SB)
 
-	MOVW	$p-64(SP), R1
-	MOVW	R1, _privates(SB)
-	MOVW	$NPRIVATES, R1
-	MOVW	R1, _nprivates(SB)
-
-	JAL	_profmain(SB)
-	MOVW	__prof+4(SB), R1
-	MOVW	R1, __prof+0(SB)
-	MOVW	inargc-4(FP), R1
-	MOVW	$inargv+0(FP), R2
-	MOVW	R1, 4(R29)
-	MOVW	R2, 8(R29)
-	JAL	main(SB)
-loop:
-	MOVW	$exits<>(SB), R1
-	MOVW	R1, 4(R29)
-	JAL	exits(SB)
+	MOVW	$_profmain(SB), R1
+	MOVW	$0, R31
+	JMP	_callmain(SB)
 	MOVW	$_profin(SB), R0	/* force loading of profile */
-	JMP	loop
 
 TEXT	_saveret(SB), 1, $0
 TEXT	_savearg(SB), 1, $0
@@ -32,6 +15,3 @@
 TEXT	_callpc(SB), 1, $0
 	MOVW	argp-4(FP), R1
 	RET
-
-DATA	exits<>+0(SB)/4, $"main"
-GLOBL	exits<>+0(SB), $5
--- a/sys/src/libc/port/profile.c
+++ b/sys/src/libc/port/profile.c
@@ -235,7 +235,7 @@
 }
 
 void
-_profmain(void)
+_profmain(int argc, char **argv)
 {
 	char ename[50];
 	int n, f;
@@ -274,6 +274,9 @@
 	_tos->prof.pid = _tos->pid;
 	atexit(_profdump);
 	_tos->clock = 1;
+	_tos->prof.pp = _tos->prof.next;
+	extern void main(int, char**);
+	main(argc, argv);
 }
 
 void prof(void (*fn)(void*), void *arg, int entries, int what)
--- a/sys/src/libc/power/argv0.s
+++ b/sys/src/libc/power/argv0.s
@@ -1,4 +1,2 @@
 GLOBL	argv0(SB), $4
 GLOBL	_tos(SB), $4
-GLOBL	_privates(SB), $4
-GLOBL	_nprivates(SB), $4
--- a/sys/src/libc/power/main9.s
+++ b/sys/src/libc/power/main9.s
@@ -1,25 +1,10 @@
-#define NPRIVATES	16
-
-TEXT	_main(SB), 1, $(16 + NPRIVATES*4)
-
+TEXT	_main(SB), 1, $0
+	SUB	$8, R1
 	MOVW	$setSB(SB), R2
 	MOVW	R3, _tos(SB)
 
-	MOVW	$p-64(SP), R4
-	MOVW	R4, _privates+0(SB)
-	MOVW	$16, R4
-	MOVW	R4, _nprivates+0(SB)
-
-	MOVW	inargc-4(FP), R3
-	MOVW	$inargv+0(FP), R4
-	MOVW	R3, 4(R1)
-	MOVW	R4, 8(R1)
-	BL	main(SB)
-loop:
-	MOVW	$_exitstr<>(SB), R3
-	MOVW	R3, 4(R1)
-	BL	exits(SB)
-	BR	loop
-
-DATA	_exitstr<>+0(SB)/4, $"main"
-GLOBL	_exitstr<>+0(SB), $5
+	MOVW	$main(SB), R3
+	MOVW	R0, LR
+	MOVW	$_callmain(SB), R4
+	MOVW	R4, CTR
+	BR	(CTR)
--- a/sys/src/libc/power/main9p.s
+++ b/sys/src/libc/power/main9p.s
@@ -1,31 +1,14 @@
-#define NPRIVATES	16
-
-TEXT	_mainp(SB), 1, $(16 + NPRIVATES*4)
-
+TEXT	_mainp(SB), 1, $0
+	SUB	$8, R1
 	MOVW	$setSB(SB), R2
 	MOVW	R3, _tos(SB)
 
-	MOVW	$p-64(SP), R4
-	MOVW	R4, _privates+0(SB)
-	MOVW	$16, R4
-	MOVW	R4, _nprivates+0(SB)
+	MOVW	$_profmain(SB), R3
+	MOVW	R0, LR
+	MOVW	$_callmain(SB), R4
+	MOVW	R4, CTR
+	BR	(CTR)
 
-	BL	_profmain(SB)
-	MOVW	_tos(SB), R3
-	MOVW	4(R3), R4
-	MOVW	R4, 0(R3)
-	MOVW	inargc-4(FP), R3
-	MOVW	$inargv+0(FP), R4
-	MOVW	R3, 4(R1)
-	MOVW	R4, 8(R1)
-	BL		main(SB)
-loop:
-	MOVW	$exits<>(SB), R3
-	MOVW	R3, 4(R1)
-	BL	exits(SB)
-	MOVW	$_profin(SB), R3	/* force loading of profile */
-	BR	loop
-
 TEXT	_saveret(SB), 1, $0
 TEXT	_savearg(SB), 1, $0
 	RETURN
@@ -33,6 +16,3 @@
 TEXT	_callpc(SB), 1, $0
 	MOVW	argp-4(FP), R3
 	RETURN
-
-DATA	exits<>+0(SB)/4, $"main"
-GLOBL	exits<>+0(SB), $5
--- a/sys/src/libc/sparc/argv0.s
+++ b/sys/src/libc/sparc/argv0.s
@@ -1,4 +1,2 @@
 GLOBL	argv0(SB), $4
 GLOBL	_tos(SB), $4
-GLOBL	_privates(SB), $4
-GLOBL	_nprivates(SB), $4
--- a/sys/src/libc/sparc/main9.s
+++ b/sys/src/libc/sparc/main9.s
@@ -1,14 +1,8 @@
-#define NPRIVATES	16
-
-TEXT	_main(SB), 1, $(16 + NPRIVATES*4)
-
+TEXT	_main(SB), 1, $0
+	SUB	$8, R1
 	MOVW	$setSB(SB), R2
 	MOVW	R7, _tos(SB)
 
-	MOVW	$p-64(SP),R7
-	MOVW	R7,_privates+0(SB)
-	MOVW	$16,R7
-	MOVW	R7,_nprivates+0(SB)
 /*
 	MOVW	_fpsr+0(SB), FSR
 	FMOVD	$0.5, F26
@@ -16,16 +10,9 @@
 	FADDD	F26, F26, F28
 	FADDD	F28, F28, F30
 */
-	MOVW	inargc-4(FP), R7
-	MOVW	$inargv+0(FP), R8
-	MOVW	R8, 8(R1)
-	JMPL	main(SB)
 
-loop:
-	MOVW	$_exits<>(SB), R7
-	JMPL	exits(SB)
+	MOVW	$main(SB), R7
+	MOVW	$_callmain(SB), R24
+	MOVW	$0, R15
+	JMP	(R24)
 	MOVW	$_mul(SB), R8	/* force loading of muldiv */
-	JMP	loop
-
-DATA	_exits<>+0(SB)/5, $"main"
-GLOBL	_exits<>+0(SB), $5
--- a/sys/src/libc/sparc/main9p.s
+++ b/sys/src/libc/sparc/main9p.s
@@ -1,14 +1,8 @@
-#define NPRIVATES	16
-
-TEXT	_mainp(SB), 1, $(16 + NPRIVATES*4)
-
+TEXT	_mainp(SB), 1, $0
+	SUB	$8, R1
 	MOVW	$setSB(SB), R2
 	MOVW	R7, _tos(SB)
 
-	MOVW	$p-64(SP),R7
-	MOVW	R7,_privates+0(SB)
-	MOVW	$16,R7
-	MOVW	R7,_nprivates+0(SB)
 /*
 	MOVW	_fpsr+0(SB), FSR
 	FMOVD	$0.5, F26
@@ -17,21 +11,12 @@
 	FADDD	F28, F28, F30
 */
 
-	JMPL	_profmain(SB)
-	MOVW	__prof+4(SB), R7
-	MOVW	R7, __prof+0(SB)
-
-	MOVW	inargc-4(FP), R7
-	MOVW	$inargv+0(FP), R8
-	MOVW	R8, 8(R1)
-	JMPL	main(SB)
-
-loop:
-	MOVW	$_exits<>(SB), R7
-	JMPL	exits(SB)
+	MOVW	$_profmain(SB), R7
+	MOVW	$_callmain(SB), R24
+	MOVW	$0, R15
+	JMP	(R24)
 	MOVW	$_mul(SB), R8		/* force loading of muldiv */
 	MOVW	$_profin(SB), R9	/* force loading of profile */
-	JMP	loop
 
 TEXT	_saveret(SB), 1, $0
 TEXT	_savearg(SB), 1, $0
@@ -40,6 +25,3 @@
 TEXT	_callpc(SB), 1, $0
 	MOVW	argp-4(FP), R7
 	RETURN
-
-DATA	_exits<>+0(SB)/4, $"main"
-GLOBL	_exits<>+0(SB), $5