1// Copyright 2018 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5//
6// System calls and other sys.stuff for ppc64, Aix
7//
8
9#include "go_asm.h"
10#include "go_tls.h"
11#include "textflag.h"
12#include "asm_ppc64x.h"
13
14// This function calls a C function with the function descriptor in R12
15TEXT callCfunction<>(SB),	NOSPLIT|NOFRAME,$0
16	MOVD	0(R12), R12
17	MOVD	R2, 40(R1)
18	MOVD	0(R12), R0
19	MOVD	8(R12), R2
20	MOVD	R0, CTR
21	BR	(CTR)
22
23
24// asmsyscall6 calls a library function with a function descriptor
25// stored in libcall_fn and store the results in libcall structure
26// Up to 6 arguments can be passed to this C function
27// Called by runtime.asmcgocall
28// It reserves a stack of 288 bytes for the C function. It must
29// follow AIX convention, thus the first local variable must
30// be stored at the offset 112, after the linker area (48 bytes)
31// and the argument area (64).
32// The AIX convention is described here:
33// https://www.ibm.com/docs/en/aix/7.2?topic=overview-runtime-process-stack
34// NOT USING GO CALLING CONVENTION
35// runtime.asmsyscall6 is a function descriptor to the real asmsyscall6.
36DATA	runtime·asmsyscall6+0(SB)/8, $asmsyscall6<>(SB)
37DATA	runtime·asmsyscall6+8(SB)/8, $TOC(SB)
38DATA	runtime·asmsyscall6+16(SB)/8, $0
39GLOBL	runtime·asmsyscall6(SB), NOPTR, $24
40
41TEXT asmsyscall6<>(SB),NOSPLIT,$256
42	// Save libcall for later
43	MOVD	R3, 112(R1)
44	MOVD	libcall_fn(R3), R12
45	MOVD	libcall_args(R3), R9
46	MOVD	0(R9), R3
47	MOVD	8(R9), R4
48	MOVD	16(R9), R5
49	MOVD	24(R9), R6
50	MOVD	32(R9), R7
51	MOVD	40(R9), R8
52	BL	callCfunction<>(SB)
53
54	// Restore R0 and TOC
55	XOR	R0, R0
56	MOVD	40(R1), R2
57
58	// Store result in libcall
59	MOVD	112(R1), R5
60	MOVD	R3, (libcall_r1)(R5)
61	MOVD	$-1, R6
62	CMP	R6, R3
63	BNE	skiperrno
64
65	// Save errno in libcall
66	BL	runtime·load_g(SB)
67	MOVD	g_m(g), R4
68	MOVD	(m_mOS + mOS_perrno)(R4), R9
69	MOVW	0(R9), R9
70	MOVD	R9, (libcall_err)(R5)
71	RET
72skiperrno:
73	// Reset errno if no error has been returned
74	MOVD	R0, (libcall_err)(R5)
75	RET
76
77
78TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
79	MOVW	sig+8(FP), R3
80	MOVD	info+16(FP), R4
81	MOVD	ctx+24(FP), R5
82	MOVD	fn+0(FP), R12
83	// fn is a function descriptor
84	// R2 must be saved on restore
85	MOVD	0(R12), R0
86	MOVD	R2, 40(R1)
87	MOVD	8(R12), R2
88	MOVD	R0, CTR
89	BL	(CTR)
90	MOVD	40(R1), R2
91	BL	runtime·reginit(SB)
92	RET
93
94
95// runtime.sigtramp is a function descriptor to the real sigtramp.
96DATA	runtime·sigtramp+0(SB)/8, $sigtramp<>(SB)
97DATA	runtime·sigtramp+8(SB)/8, $TOC(SB)
98DATA	runtime·sigtramp+16(SB)/8, $0
99GLOBL	runtime·sigtramp(SB), NOPTR, $24
100
101// This function must not have any frame as we want to control how
102// every registers are used.
103// TODO(aix): Implement SetCgoTraceback handler.
104TEXT sigtramp<>(SB),NOSPLIT|NOFRAME|TOPFRAME,$0
105	MOVD	LR, R0
106	MOVD	R0, 16(R1)
107	// initialize essential registers (just in case)
108	BL	runtime·reginit(SB)
109
110	// Note that we are executing on altsigstack here, so we have
111	// more stack available than NOSPLIT would have us believe.
112	// To defeat the linker, we make our own stack frame with
113	// more space.
114	SUB	$144+FIXED_FRAME, R1
115
116	// Save registers
117	MOVD	R31, 56(R1)
118	MOVD	g, 64(R1)
119	MOVD	R29, 72(R1)
120	MOVD	R14, 80(R1)
121	MOVD	R15, 88(R1)
122
123	BL	runtime·load_g(SB)
124
125	CMP	$0, g
126	BEQ	sigtramp // g == nil
127	MOVD	g_m(g), R6
128	CMP	$0, R6
129	BEQ	sigtramp	// g.m == nil
130
131	// Save m->libcall. We need to do this because we
132	// might get interrupted by a signal in runtime·asmcgocall.
133	MOVD	(m_libcall+libcall_fn)(R6), R7
134	MOVD	R7, 96(R1)
135	MOVD	(m_libcall+libcall_args)(R6), R7
136	MOVD	R7, 104(R1)
137	MOVD	(m_libcall+libcall_n)(R6), R7
138	MOVD	R7, 112(R1)
139	MOVD	(m_libcall+libcall_r1)(R6), R7
140	MOVD	R7, 120(R1)
141	MOVD	(m_libcall+libcall_r2)(R6), R7
142	MOVD	R7, 128(R1)
143
144	// save errno, it might be EINTR; stuff we do here might reset it.
145	MOVD	(m_mOS+mOS_perrno)(R6), R8
146	MOVD	0(R8), R8
147	MOVD	R8, 136(R1)
148
149sigtramp:
150	MOVW	R3, FIXED_FRAME+0(R1)
151	MOVD	R4, FIXED_FRAME+8(R1)
152	MOVD	R5, FIXED_FRAME+16(R1)
153	MOVD	$runtime·sigtrampgo(SB), R12
154	MOVD	R12, CTR
155	BL	(CTR)
156
157	CMP	$0, g
158	BEQ	exit // g == nil
159	MOVD	g_m(g), R6
160	CMP	$0, R6
161	BEQ	exit	// g.m == nil
162
163	// restore libcall
164	MOVD	96(R1), R7
165	MOVD	R7, (m_libcall+libcall_fn)(R6)
166	MOVD	104(R1), R7
167	MOVD	R7, (m_libcall+libcall_args)(R6)
168	MOVD	112(R1), R7
169	MOVD	R7, (m_libcall+libcall_n)(R6)
170	MOVD	120(R1), R7
171	MOVD	R7, (m_libcall+libcall_r1)(R6)
172	MOVD	128(R1), R7
173	MOVD	R7, (m_libcall+libcall_r2)(R6)
174
175	// restore errno
176	MOVD	(m_mOS+mOS_perrno)(R6), R7
177	MOVD	136(R1), R8
178	MOVD	R8, 0(R7)
179
180exit:
181	// restore registers
182	MOVD	56(R1),R31
183	MOVD	64(R1),g
184	MOVD	72(R1),R29
185	MOVD	80(R1), R14
186	MOVD	88(R1), R15
187
188	// Don't use RET because we need to restore R31 !
189	ADD $144+FIXED_FRAME, R1
190	MOVD	16(R1), R0
191	MOVD	R0, LR
192	BR (LR)
193
194// runtime.tstart is a function descriptor to the real tstart.
195DATA	runtime·tstart+0(SB)/8, $tstart<>(SB)
196DATA	runtime·tstart+8(SB)/8, $TOC(SB)
197DATA	runtime·tstart+16(SB)/8, $0
198GLOBL	runtime·tstart(SB), NOPTR, $24
199
200TEXT tstart<>(SB),NOSPLIT,$0
201	XOR	 R0, R0 // reset R0
202
203	// set g
204	MOVD	m_g0(R3), g
205	BL	runtime·save_g(SB)
206	MOVD	R3, g_m(g)
207
208	// Layout new m scheduler stack on os stack.
209	MOVD	R1, R3
210	MOVD	R3, (g_stack+stack_hi)(g)
211	SUB	$(const_threadStackSize), R3		// stack size
212	MOVD	R3, (g_stack+stack_lo)(g)
213	ADD	$const_stackGuard, R3
214	MOVD	R3, g_stackguard0(g)
215	MOVD	R3, g_stackguard1(g)
216
217	BL	runtime·mstart(SB)
218
219	MOVD R0, R3
220	RET
221
222
223#define CSYSCALL()			\
224	MOVD	0(R12), R12		\
225	MOVD	R2, 40(R1)		\
226	MOVD	0(R12), R0		\
227	MOVD	8(R12), R2		\
228	MOVD	R0, CTR			\
229	BL	(CTR)			\
230	MOVD	40(R1), R2		\
231	BL runtime·reginit(SB)
232
233
234// Runs on OS stack, called from runtime·osyield.
235TEXT runtime·osyield1(SB),NOSPLIT,$0
236	MOVD	$libc_sched_yield(SB), R12
237	CSYSCALL()
238	RET
239
240
241// Runs on OS stack, called from runtime·sigprocmask.
242TEXT runtime·sigprocmask1(SB),NOSPLIT,$0-24
243	MOVD	how+0(FP), R3
244	MOVD	new+8(FP), R4
245	MOVD	old+16(FP), R5
246	MOVD	$libpthread_sigthreadmask(SB), R12
247	CSYSCALL()
248	RET
249
250// Runs on OS stack, called from runtime·usleep.
251TEXT runtime·usleep1(SB),NOSPLIT,$0-4
252	MOVW	us+0(FP), R3
253	MOVD	$libc_usleep(SB), R12
254	CSYSCALL()
255	RET
256
257// Runs on OS stack, called from runtime·exit.
258TEXT runtime·exit1(SB),NOSPLIT,$0-4
259	MOVW	code+0(FP), R3
260	MOVD	$libc_exit(SB), R12
261	CSYSCALL()
262	RET
263
264// Runs on OS stack, called from runtime·write1.
265TEXT runtime·write2(SB),NOSPLIT,$0-28
266	MOVD	fd+0(FP), R3
267	MOVD	p+8(FP), R4
268	MOVW	n+16(FP), R5
269	MOVD	$libc_write(SB), R12
270	CSYSCALL()
271	MOVW	R3, ret+24(FP)
272	RET
273
274// Runs on OS stack, called from runtime·pthread_attr_init.
275TEXT runtime·pthread_attr_init1(SB),NOSPLIT,$0-12
276	MOVD	attr+0(FP), R3
277	MOVD	$libpthread_attr_init(SB), R12
278	CSYSCALL()
279	MOVW	R3, ret+8(FP)
280	RET
281
282// Runs on OS stack, called from runtime·pthread_attr_setstacksize.
283TEXT runtime·pthread_attr_setstacksize1(SB),NOSPLIT,$0-20
284	MOVD	attr+0(FP), R3
285	MOVD	size+8(FP), R4
286	MOVD	$libpthread_attr_setstacksize(SB), R12
287	CSYSCALL()
288	MOVW	R3, ret+16(FP)
289	RET
290
291// Runs on OS stack, called from runtime·pthread_setdetachstate.
292TEXT runtime·pthread_attr_setdetachstate1(SB),NOSPLIT,$0-20
293	MOVD	attr+0(FP), R3
294	MOVW	state+8(FP), R4
295	MOVD	$libpthread_attr_setdetachstate(SB), R12
296	CSYSCALL()
297	MOVW	R3, ret+16(FP)
298	RET
299
300// Runs on OS stack, called from runtime·pthread_create.
301TEXT runtime·pthread_create1(SB),NOSPLIT,$0-36
302	MOVD	tid+0(FP), R3
303	MOVD	attr+8(FP), R4
304	MOVD	fn+16(FP), R5
305	MOVD	arg+24(FP), R6
306	MOVD	$libpthread_create(SB), R12
307	CSYSCALL()
308	MOVW	R3, ret+32(FP)
309	RET
310
311// Runs on OS stack, called from runtime·sigaction.
312TEXT runtime·sigaction1(SB),NOSPLIT,$0-24
313	MOVD	sig+0(FP), R3
314	MOVD	new+8(FP), R4
315	MOVD	old+16(FP), R5
316	MOVD	$libc_sigaction(SB), R12
317	CSYSCALL()
318	RET
319