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