1// Copyright 2012 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// System calls and other sys.stuff for ARM, FreeBSD
6// /usr/src/sys/kern/syscalls.master for syscall numbers.
7//
8
9#include "go_asm.h"
10#include "go_tls.h"
11#include "textflag.h"
12
13// for EABI, as we don't support OABI
14#define SYS_BASE 0x0
15
16#define SYS_exit (SYS_BASE + 1)
17#define SYS_read (SYS_BASE + 3)
18#define SYS_write (SYS_BASE + 4)
19#define SYS_open (SYS_BASE + 5)
20#define SYS_close (SYS_BASE + 6)
21#define SYS_getpid (SYS_BASE + 20)
22#define SYS_kill (SYS_BASE + 37)
23#define SYS_sigaltstack (SYS_BASE + 53)
24#define SYS_munmap (SYS_BASE + 73)
25#define SYS_madvise (SYS_BASE + 75)
26#define SYS_setitimer (SYS_BASE + 83)
27#define SYS_fcntl (SYS_BASE + 92)
28#define SYS_getrlimit (SYS_BASE + 194)
29#define SYS___sysctl (SYS_BASE + 202)
30#define SYS_nanosleep (SYS_BASE + 240)
31#define SYS_clock_gettime (SYS_BASE + 232)
32#define SYS_sched_yield (SYS_BASE + 331)
33#define SYS_sigprocmask (SYS_BASE + 340)
34#define SYS_kqueue (SYS_BASE + 362)
35#define SYS_kevent (SYS_BASE + 363)
36#define SYS_sigaction (SYS_BASE + 416)
37#define SYS_thr_exit (SYS_BASE + 431)
38#define SYS_thr_self (SYS_BASE + 432)
39#define SYS_thr_kill (SYS_BASE + 433)
40#define SYS__umtx_op (SYS_BASE + 454)
41#define SYS_thr_new (SYS_BASE + 455)
42#define SYS_mmap (SYS_BASE + 477)
43#define SYS_cpuset_getaffinity (SYS_BASE + 487)
44
45TEXT runtime·sys_umtx_op(SB),NOSPLIT,$0
46	MOVW addr+0(FP), R0
47	MOVW mode+4(FP), R1
48	MOVW val+8(FP), R2
49	MOVW uaddr1+12(FP), R3
50	ADD $20, R13 // arg 5 is passed on stack
51	MOVW $SYS__umtx_op, R7
52	SWI $0
53	SUB $20, R13
54	// BCS error
55	MOVW	R0, ret+20(FP)
56	RET
57
58TEXT runtime·thr_new(SB),NOSPLIT,$0
59	MOVW param+0(FP), R0
60	MOVW size+4(FP), R1
61	MOVW $SYS_thr_new, R7
62	SWI $0
63	RET
64
65TEXT runtime·thr_start(SB),NOSPLIT,$0
66	// set up g
67	MOVW m_g0(R0), g
68	MOVW R0, g_m(g)
69	BL runtime·emptyfunc(SB) // fault if stack check is wrong
70	BL runtime·mstart(SB)
71
72	MOVW $2, R8  // crash (not reached)
73	MOVW R8, (R8)
74	RET
75
76// Exit the entire program (like C exit)
77TEXT runtime·exit(SB),NOSPLIT,$-8
78	MOVW code+0(FP), R0	// arg 1 exit status
79	MOVW $SYS_exit, R7
80	SWI $0
81	MOVW.CS $0, R8 // crash on syscall failure
82	MOVW.CS R8, (R8)
83	RET
84
85// func exitThread(wait *uint32)
86TEXT runtime·exitThread(SB),NOSPLIT,$0-4
87	MOVW	wait+0(FP), R0
88	// We're done using the stack.
89	MOVW	$0, R2
90storeloop:
91	LDREX	(R0), R4          // loads R4
92	STREX	R2, (R0), R1      // stores R2
93	CMP	$0, R1
94	BNE	storeloop
95	MOVW	$0, R0		// arg 1 long *state
96	MOVW	$SYS_thr_exit, R7
97	SWI	$0
98	MOVW.CS	$0, R8 // crash on syscall failure
99	MOVW.CS	R8, (R8)
100	JMP	0(PC)
101
102TEXT runtime·open(SB),NOSPLIT,$-8
103	MOVW name+0(FP), R0	// arg 1 name
104	MOVW mode+4(FP), R1	// arg 2 mode
105	MOVW perm+8(FP), R2	// arg 3 perm
106	MOVW $SYS_open, R7
107	SWI $0
108	MOVW.CS	$-1, R0
109	MOVW	R0, ret+12(FP)
110	RET
111
112TEXT runtime·read(SB),NOSPLIT,$-8
113	MOVW fd+0(FP), R0	// arg 1 fd
114	MOVW p+4(FP), R1	// arg 2 buf
115	MOVW n+8(FP), R2	// arg 3 count
116	MOVW $SYS_read, R7
117	SWI $0
118	MOVW.CS	$-1, R0
119	MOVW	R0, ret+12(FP)
120	RET
121
122TEXT runtime·write(SB),NOSPLIT,$-8
123	MOVW fd+0(FP), R0	// arg 1 fd
124	MOVW p+4(FP), R1	// arg 2 buf
125	MOVW n+8(FP), R2	// arg 3 count
126	MOVW $SYS_write, R7
127	SWI $0
128	MOVW.CS	$-1, R0
129	MOVW	R0, ret+12(FP)
130	RET
131
132TEXT runtime·closefd(SB),NOSPLIT,$-8
133	MOVW fd+0(FP), R0	// arg 1 fd
134	MOVW $SYS_close, R7
135	SWI $0
136	MOVW.CS	$-1, R0
137	MOVW	R0, ret+4(FP)
138	RET
139
140TEXT runtime·getrlimit(SB),NOSPLIT,$-8
141	MOVW kind+0(FP), R0
142	MOVW limit+4(FP), R1
143	MOVW $SYS_getrlimit, R7
144	SWI $0
145	MOVW	R0, ret+8(FP)
146	RET
147
148TEXT runtime·raise(SB),NOSPLIT,$8
149	// thr_self(&4(R13))
150	MOVW $4(R13), R0 // arg 1 &4(R13)
151	MOVW $SYS_thr_self, R7
152	SWI $0
153	// thr_kill(self, SIGPIPE)
154	MOVW 4(R13), R0	// arg 1 id
155	MOVW sig+0(FP), R1	// arg 2 - signal
156	MOVW $SYS_thr_kill, R7
157	SWI $0
158	RET
159
160TEXT runtime·raiseproc(SB),NOSPLIT,$0
161	// getpid
162	MOVW $SYS_getpid, R7
163	SWI $0
164	// kill(self, sig)
165				// arg 1 - pid, now in R0
166	MOVW sig+0(FP), R1	// arg 2 - signal
167	MOVW $SYS_kill, R7
168	SWI $0
169	RET
170
171TEXT runtime·setitimer(SB), NOSPLIT, $-8
172	MOVW mode+0(FP), R0
173	MOVW new+4(FP), R1
174	MOVW old+8(FP), R2
175	MOVW $SYS_setitimer, R7
176	SWI $0
177	RET
178
179// func walltime() (sec int64, nsec int32)
180TEXT runtime·walltime(SB), NOSPLIT, $32
181	MOVW $0, R0 // CLOCK_REALTIME
182	MOVW $8(R13), R1
183	MOVW $SYS_clock_gettime, R7
184	SWI $0
185
186	MOVW 8(R13), R0 // sec.low
187	MOVW 12(R13), R1 // sec.high
188	MOVW 16(R13), R2 // nsec
189
190	MOVW R0, sec_lo+0(FP)
191	MOVW R1, sec_hi+4(FP)
192	MOVW R2, nsec+8(FP)
193	RET
194
195// int64 nanotime(void) so really
196// void nanotime(int64 *nsec)
197TEXT runtime·nanotime(SB), NOSPLIT, $32
198	// We can use CLOCK_MONOTONIC_FAST here when we drop
199	// support for FreeBSD 8-STABLE.
200	MOVW $4, R0 // CLOCK_MONOTONIC
201	MOVW $8(R13), R1
202	MOVW $SYS_clock_gettime, R7
203	SWI $0
204
205	MOVW 8(R13), R0 // sec.low
206	MOVW 12(R13), R4 // sec.high
207	MOVW 16(R13), R2 // nsec
208
209	MOVW $1000000000, R3
210	MULLU R0, R3, (R1, R0)
211	MUL R3, R4
212	ADD.S R2, R0
213	ADC R4, R1
214
215	MOVW R0, ret_lo+0(FP)
216	MOVW R1, ret_hi+4(FP)
217	RET
218
219TEXT runtime·sigaction(SB),NOSPLIT,$-8
220	MOVW sig+0(FP), R0		// arg 1 sig
221	MOVW new+4(FP), R1		// arg 2 act
222	MOVW old+8(FP), R2		// arg 3 oact
223	MOVW $SYS_sigaction, R7
224	SWI $0
225	MOVW.CS $0, R8 // crash on syscall failure
226	MOVW.CS R8, (R8)
227	RET
228
229TEXT runtime·sigtramp(SB),NOSPLIT,$12
230	// this might be called in external code context,
231	// where g is not set.
232	// first save R0, because runtime·load_g will clobber it
233	MOVW	R0, 4(R13) // signum
234	MOVB	runtime·iscgo(SB), R0
235	CMP 	$0, R0
236	BL.NE	runtime·load_g(SB)
237
238	MOVW	R1, 8(R13)
239	MOVW	R2, 12(R13)
240	BL	runtime·sigtrampgo(SB)
241	RET
242
243TEXT runtime·mmap(SB),NOSPLIT,$16
244	MOVW addr+0(FP), R0		// arg 1 addr
245	MOVW n+4(FP), R1		// arg 2 len
246	MOVW prot+8(FP), R2		// arg 3 prot
247	MOVW flags+12(FP), R3		// arg 4 flags
248	// arg 5 (fid) and arg6 (offset_lo, offset_hi) are passed on stack
249	// note the C runtime only passes the 32-bit offset_lo to us
250	MOVW fd+16(FP), R4		// arg 5
251	MOVW R4, 4(R13)
252	MOVW off+20(FP), R5		// arg 6 lower 32-bit
253	// the word at 8(R13) is skipped due to 64-bit argument alignment.
254	MOVW R5, 12(R13)
255	MOVW $0, R6 		// higher 32-bit for arg 6
256	MOVW R6, 16(R13)
257	ADD $4, R13
258	MOVW $SYS_mmap, R7
259	SWI $0
260	SUB $4, R13
261	MOVW $0, R1
262	MOVW.CS R0, R1		// if failed, put in R1
263	MOVW.CS $0, R0
264	MOVW	R0, p+24(FP)
265	MOVW	R1, err+28(FP)
266	RET
267
268TEXT runtime·munmap(SB),NOSPLIT,$0
269	MOVW addr+0(FP), R0		// arg 1 addr
270	MOVW n+4(FP), R1		// arg 2 len
271	MOVW $SYS_munmap, R7
272	SWI $0
273	MOVW.CS $0, R8 // crash on syscall failure
274	MOVW.CS R8, (R8)
275	RET
276
277TEXT runtime·madvise(SB),NOSPLIT,$0
278	MOVW addr+0(FP), R0		// arg 1 addr
279	MOVW n+4(FP), R1		// arg 2 len
280	MOVW flags+8(FP), R2		// arg 3 flags
281	MOVW $SYS_madvise, R7
282	SWI $0
283	// ignore failure - maybe pages are locked
284	RET
285
286TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
287	MOVW new+0(FP), R0
288	MOVW old+4(FP), R1
289	MOVW $SYS_sigaltstack, R7
290	SWI $0
291	MOVW.CS $0, R8 // crash on syscall failure
292	MOVW.CS R8, (R8)
293	RET
294
295TEXT runtime·sigfwd(SB),NOSPLIT,$0-16
296	MOVW	sig+4(FP), R0
297	MOVW	info+8(FP), R1
298	MOVW	ctx+12(FP), R2
299	MOVW	fn+0(FP), R11
300	MOVW	R13, R4
301	SUB	$24, R13
302	BIC	$0x7, R13 // alignment for ELF ABI
303	BL	(R11)
304	MOVW	R4, R13
305	RET
306
307TEXT runtime·usleep(SB),NOSPLIT,$16
308	MOVW usec+0(FP), R0
309	CALL runtime·usplitR0(SB)
310	// 0(R13) is the saved LR, don't use it
311	MOVW R0, 4(R13) // tv_sec.low
312	MOVW $0, R0
313	MOVW R0, 8(R13) // tv_sec.high
314	MOVW $1000, R2
315	MUL R1, R2
316	MOVW R2, 12(R13) // tv_nsec
317
318	MOVW $4(R13), R0 // arg 1 - rqtp
319	MOVW $0, R1      // arg 2 - rmtp
320	MOVW $SYS_nanosleep, R7
321	SWI $0
322	RET
323
324TEXT runtime·sysctl(SB),NOSPLIT,$0
325	MOVW mib+0(FP), R0	// arg 1 - name
326	MOVW miblen+4(FP), R1	// arg 2 - namelen
327	MOVW out+8(FP), R2	// arg 3 - old
328	MOVW size+12(FP), R3	// arg 4 - oldlenp
329	// arg 5 (newp) and arg 6 (newlen) are passed on stack
330	ADD $20, R13
331	MOVW $SYS___sysctl, R7
332	SWI $0
333	SUB.CS $0, R0, R0
334	SUB $20, R13
335	MOVW	R0, ret+24(FP)
336	RET
337
338TEXT runtime·osyield(SB),NOSPLIT,$-4
339	MOVW $SYS_sched_yield, R7
340	SWI $0
341	RET
342
343TEXT runtime·sigprocmask(SB),NOSPLIT,$0
344	MOVW how+0(FP), R0	// arg 1 - how
345	MOVW new+4(FP), R1	// arg 2 - set
346	MOVW old+8(FP), R2	// arg 3 - oset
347	MOVW $SYS_sigprocmask, R7
348	SWI $0
349	MOVW.CS $0, R8 // crash on syscall failure
350	MOVW.CS R8, (R8)
351	RET
352
353// int32 runtime·kqueue(void)
354TEXT runtime·kqueue(SB),NOSPLIT,$0
355	MOVW $SYS_kqueue, R7
356	SWI $0
357	RSB.CS $0, R0
358	MOVW	R0, ret+0(FP)
359	RET
360
361// int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int nevents, Timespec *timeout)
362TEXT runtime·kevent(SB),NOSPLIT,$0
363	MOVW kq+0(FP), R0	// kq
364	MOVW ch+4(FP), R1	// changelist
365	MOVW nch+8(FP), R2	// nchanges
366	MOVW ev+12(FP), R3	// eventlist
367	ADD $20, R13	// pass arg 5 and 6 on stack
368	MOVW $SYS_kevent, R7
369	SWI $0
370	RSB.CS $0, R0
371	SUB $20, R13
372	MOVW	R0, ret+24(FP)
373	RET
374
375// void runtime·closeonexec(int32 fd)
376TEXT runtime·closeonexec(SB),NOSPLIT,$0
377	MOVW fd+0(FP), R0	// fd
378	MOVW $2, R1	// F_SETFD
379	MOVW $1, R2	// FD_CLOEXEC
380	MOVW $SYS_fcntl, R7
381	SWI $0
382	RET
383
384// TODO: this is only valid for ARMv7+
385TEXT ·publicationBarrier(SB),NOSPLIT,$-4-0
386	B	runtime·armPublicationBarrier(SB)
387
388// TODO(minux): this only supports ARMv6K+.
389TEXT runtime·read_tls_fallback(SB),NOSPLIT,$-4
390	WORD $0xee1d0f70 // mrc p15, 0, r0, c13, c0, 3
391	RET
392
393// func cpuset_getaffinity(level int, which int, id int64, size int, mask *byte) int32
394TEXT runtime·cpuset_getaffinity(SB), NOSPLIT, $0-28
395	MOVW	level+0(FP), R0
396	MOVW	which+4(FP), R1
397	MOVW	id_lo+8(FP), R2
398	MOVW	id_hi+12(FP), R3
399	ADD	$20, R13	// Pass size and mask on stack.
400	MOVW	$SYS_cpuset_getaffinity, R7
401	SWI	$0
402	RSB.CS	$0, R0
403	SUB	$20, R13
404	MOVW	R0, ret+24(FP)
405	RET
406