1// Copyright 2016 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 linux
6// +build mips mipsle
7
8//
9// System calls and other sys.stuff for mips, Linux
10//
11
12#include "go_asm.h"
13#include "go_tls.h"
14#include "textflag.h"
15
16#define SYS_exit		        4001
17#define SYS_read		        4003
18#define SYS_write		        4004
19#define SYS_open		        4005
20#define SYS_close		        4006
21#define SYS_getpid		        4020
22#define SYS_kill		        4037
23#define SYS_fcntl		        4055
24#define SYS_gettimeofday	    4078
25#define SYS_mmap		        4090
26#define SYS_munmap		        4091
27#define SYS_setitimer		    4104
28#define SYS_clone		        4120
29#define SYS_newselect		    4142
30#define SYS_sched_yield		    4162
31#define SYS_rt_sigreturn	    4193
32#define SYS_rt_sigaction	    4194
33#define SYS_rt_sigprocmask		4195
34#define SYS_sigaltstack		    4206
35#define SYS_getrlimit		    4076
36#define SYS_madvise		        4218
37#define SYS_mincore		        4217
38#define SYS_gettid		        4222
39#define SYS_tkill		        4236
40#define SYS_futex		        4238
41#define SYS_sched_getaffinity	4240
42#define SYS_exit_group		    4246
43#define SYS_epoll_create	    4248
44#define SYS_epoll_ctl		    4249
45#define SYS_epoll_wait		    4250
46#define SYS_clock_gettime	    4263
47#define SYS_epoll_create1	    4326
48
49TEXT runtime·exit(SB),NOSPLIT,$0-4
50	MOVW	code+0(FP), R4
51	MOVW	$SYS_exit_group, R2
52	SYSCALL
53	UNDEF
54	RET
55
56TEXT runtime·exit1(SB),NOSPLIT,$0-4
57	MOVW	code+0(FP), R4
58	MOVW	$SYS_exit, R2
59	SYSCALL
60	UNDEF
61	RET
62
63TEXT runtime·open(SB),NOSPLIT,$0-16
64	MOVW	name+0(FP), R4
65	MOVW	mode+4(FP), R5
66	MOVW	perm+8(FP), R6
67	MOVW	$SYS_open, R2
68	SYSCALL
69	BEQ	R7, 2(PC)
70	MOVW	$-1, R2
71	MOVW	R2, ret+12(FP)
72	RET
73
74TEXT runtime·closefd(SB),NOSPLIT,$0-8
75	MOVW	fd+0(FP), R4
76	MOVW	$SYS_close, R2
77	SYSCALL
78	BEQ	R7, 2(PC)
79	MOVW	$-1, R2
80	MOVW	R2, ret+4(FP)
81	RET
82
83TEXT runtime·write(SB),NOSPLIT,$0-16
84	MOVW	fd+0(FP), R4
85	MOVW	p+4(FP), R5
86	MOVW	n+8(FP), R6
87	MOVW	$SYS_write, R2
88	SYSCALL
89	BEQ	R7, 2(PC)
90	MOVW	$-1, R2
91	MOVW	R2, ret+12(FP)
92	RET
93
94TEXT runtime·read(SB),NOSPLIT,$0-16
95	MOVW	fd+0(FP), R4
96	MOVW	p+4(FP), R5
97	MOVW	n+8(FP), R6
98	MOVW	$SYS_read, R2
99	SYSCALL
100	BEQ	R7, 2(PC)
101	MOVW	$-1, R2
102	MOVW	R2, ret+12(FP)
103	RET
104
105TEXT runtime·getrlimit(SB),NOSPLIT,$0-12
106	MOVW	kind+0(FP), R4
107	MOVW	limit+4(FP), R5
108	MOVW	$SYS_getrlimit, R2
109	SYSCALL
110	MOVW	R2, ret+8(FP)
111	RET
112
113TEXT runtime·usleep(SB),NOSPLIT,$28-4
114	MOVW	usec+0(FP), R3
115	MOVW	R3, R5
116	MOVW	$1000000, R4
117	DIVU	R4, R3
118	MOVW	LO, R3
119	MOVW	R3, 24(R29)
120	MULU	R3, R4
121	MOVW	LO, R4
122	SUBU	R4, R5
123	MOVW	R5, 28(R29)
124
125	// select(0, 0, 0, 0, &tv)
126	MOVW	$0, R4
127	MOVW	$0, R5
128	MOVW	$0, R6
129	MOVW	$0, R7
130	ADDU	$24, R29, R8
131	MOVW	R8, 16(R29)
132	MOVW	$SYS_newselect, R2
133	SYSCALL
134	RET
135
136TEXT runtime·gettid(SB),NOSPLIT,$0-4
137	MOVW	$SYS_gettid, R2
138	SYSCALL
139	MOVW	R2, ret+0(FP)
140	RET
141
142TEXT runtime·raise(SB),NOSPLIT,$0-4
143	MOVW	$SYS_gettid, R2
144	SYSCALL
145	MOVW	R2, R4	// arg 1 tid
146	MOVW	sig+0(FP), R5	// arg 2
147	MOVW	$SYS_tkill, R2
148	SYSCALL
149	RET
150
151TEXT runtime·raiseproc(SB),NOSPLIT,$0
152	MOVW	$SYS_getpid, R2
153	SYSCALL
154	MOVW	R2, R4	// arg 1 pid
155	MOVW	sig+0(FP), R5	// arg 2
156	MOVW	$SYS_kill, R2
157	SYSCALL
158	RET
159
160TEXT runtime·setitimer(SB),NOSPLIT,$0-12
161	MOVW	mode+0(FP), R4
162	MOVW	new+4(FP), R5
163	MOVW	old+8(FP), R6
164	MOVW	$SYS_setitimer, R2
165	SYSCALL
166	RET
167
168TEXT runtime·mincore(SB),NOSPLIT,$0-16
169	MOVW	addr+0(FP), R4
170	MOVW	n+4(FP), R5
171	MOVW	dst+8(FP), R6
172	MOVW	$SYS_mincore, R2
173	SYSCALL
174	SUBU	R2, R0, R2	// caller expects negative errno
175	MOVW	R2, ret+12(FP)
176	RET
177
178// func now() (sec int64, nsec int32)
179TEXT time·now(SB),NOSPLIT,$8-12
180	MOVW	$0, R4	// CLOCK_REALTIME
181	MOVW	$4(R29), R5
182	MOVW	$SYS_clock_gettime, R2
183	SYSCALL
184	MOVW	4(R29), R3	// sec
185	MOVW	8(R29), R5	// nsec
186#ifdef GOARCH_mips
187	MOVW	R3, sec_lo+4(FP)
188	MOVW	R0, sec_hi+0(FP)
189#else
190	MOVW	R3, sec_lo+0(FP)
191	MOVW	R0, sec_hi+4(FP)
192#endif
193	MOVW	R5, nsec+8(FP)
194	RET
195
196TEXT runtime·nanotime(SB),NOSPLIT,$8-8
197	MOVW	$1, R4	// CLOCK_MONOTONIC
198	MOVW	$4(R29), R5
199	MOVW	$SYS_clock_gettime, R2
200	SYSCALL
201	MOVW	4(R29), R3	// sec
202	MOVW	8(R29), R5	// nsec
203	// sec is in R3, nsec in R5
204	// return nsec in R3
205	MOVW	$1000000000, R4
206	MULU	R4, R3
207	MOVW	LO, R3
208	ADDU	R5, R3
209	SGTU	R5, R3, R4
210#ifdef GOARCH_mips
211	MOVW	R3, ret_lo+4(FP)
212#else
213	MOVW	R3, ret_lo+0(FP)
214#endif
215	MOVW	HI, R3
216	ADDU	R4, R3
217#ifdef GOARCH_mips
218	MOVW	R3, ret_hi+0(FP)
219#else
220	MOVW	R3, ret_hi+4(FP)
221#endif
222	RET
223
224TEXT runtime·rtsigprocmask(SB),NOSPLIT,$0-16
225	MOVW	how+0(FP), R4
226	MOVW	new+4(FP), R5
227	MOVW	old+8(FP), R6
228	MOVW	size+12(FP), R7
229	MOVW	$SYS_rt_sigprocmask, R2
230	SYSCALL
231	BEQ	R7, 2(PC)
232	UNDEF	// crash
233	RET
234
235TEXT runtime·rt_sigaction(SB),NOSPLIT,$0-20
236	MOVW	sig+0(FP), R4
237	MOVW	new+4(FP), R5
238	MOVW	old+8(FP), R6
239	MOVW	size+12(FP), R7
240	MOVW	$SYS_rt_sigaction, R2
241	SYSCALL
242	MOVW	R2, ret+16(FP)
243	RET
244
245TEXT runtime·sigfwd(SB),NOSPLIT,$0-16
246	MOVW	sig+4(FP), R4
247	MOVW	info+8(FP), R5
248	MOVW	ctx+12(FP), R6
249	MOVW	fn+0(FP), R25
250	MOVW	R29, R22
251	SUBU	$16, R29
252	AND	$~7, R29	// shadow space for 4 args aligned to 8 bytes as per O32 ABI
253	JAL	(R25)
254	MOVW	R22, R29
255	RET
256
257TEXT runtime·sigtramp(SB),NOSPLIT,$12
258	// this might be called in external code context,
259	// where g is not set.
260	MOVB	runtime·iscgo(SB), R1
261	BEQ	R1, 2(PC)
262	JAL	runtime·load_g(SB)
263
264	MOVW	R4, 4(R29)
265	MOVW	R5, 8(R29)
266	MOVW	R6, 12(R29)
267	MOVW	$runtime·sigtrampgo(SB), R1
268	JAL	(R1)
269	RET
270
271TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0
272	JMP	runtime·sigtramp(SB)
273
274TEXT runtime·mmap(SB),NOSPLIT,$20-28
275	MOVW	addr+0(FP), R4
276	MOVW	n+4(FP), R5
277	MOVW	prot+8(FP), R6
278	MOVW	flags+12(FP), R7
279	MOVW	fd+16(FP), R8
280	MOVW	off+20(FP), R9
281	MOVW	R8, 16(R29)
282	MOVW	R9, 20(R29)
283
284	MOVW	$SYS_mmap, R2
285	SYSCALL
286	MOVW	R2, ret+24(FP)
287	RET
288
289TEXT runtime·munmap(SB),NOSPLIT,$0-8
290	MOVW	addr+0(FP), R4
291	MOVW	n+4(FP), R5
292	MOVW	$SYS_munmap, R2
293	SYSCALL
294	BEQ	R7, 2(PC)
295	UNDEF	// crash
296	RET
297
298TEXT runtime·madvise(SB),NOSPLIT,$0-12
299	MOVW	addr+0(FP), R4
300	MOVW	n+4(FP), R5
301	MOVW	flags+8(FP), R6
302	MOVW	$SYS_madvise, R2
303	SYSCALL
304	// ignore failure - maybe pages are locked
305	RET
306
307// int32 futex(int32 *uaddr, int32 op, int32 val, struct timespec *timeout, int32 *uaddr2, int32 val2);
308TEXT runtime·futex(SB),NOSPLIT,$20-28
309	MOVW	addr+0(FP), R4
310	MOVW	op+4(FP), R5
311	MOVW	val+8(FP), R6
312	MOVW	ts+12(FP), R7
313
314	MOVW	addr2+16(FP), R8
315	MOVW	val3+20(FP), R9
316
317	MOVW	R8, 16(R29)
318	MOVW	R9, 20(R29)
319
320	MOVW	$SYS_futex, R2
321	SYSCALL
322	MOVW	R2, ret+24(FP)
323	RET
324
325
326// int32 clone(int32 flags, void *stk, M *mm, G *gg, void (*fn)(void));
327TEXT runtime·clone(SB),NOSPLIT,$-4-24
328	MOVW	flags+0(FP), R4
329	MOVW	stk+4(FP), R5
330	MOVW	R0, R6	// ptid
331	MOVW	R0, R7	// tls
332
333	// O32 syscall handler unconditionally copies arguments 5-8 from stack,
334	// even for syscalls with less than 8 arguments. Reserve 32 bytes of new
335	// stack so that any syscall invoked immediately in the new thread won't fail.
336	ADD	$-32, R5
337
338	// Copy mm, gg, fn off parent stack for use by child.
339	MOVW	mm+8(FP), R16
340	MOVW	gg+12(FP), R17
341	MOVW	fn+16(FP), R18
342
343	MOVW	$1234, R1
344
345	MOVW	R16, 0(R5)
346	MOVW	R17, 4(R5)
347	MOVW	R18, 8(R5)
348
349	MOVW	R1, 12(R5)
350
351	MOVW	$SYS_clone, R2
352	SYSCALL
353
354	// In parent, return.
355	BEQ	R2, 5(PC)
356	SUBU	R2, R0, R3
357	CMOVN	R7, R3, R2
358	MOVW	R2, ret+20(FP)
359	RET
360
361	// In child, on new stack.
362	// Check that SP is as we expect
363	MOVW	12(R29), R16
364	MOVW	$1234, R1
365	BEQ	R16, R1, 2(PC)
366	MOVW	(R0), R0
367
368	// Initialize m->procid to Linux tid
369	MOVW	$SYS_gettid, R2
370	SYSCALL
371
372	MOVW	0(R29), R16	// m
373	MOVW	4(R29), R17	// g
374	MOVW	8(R29), R18	// fn
375
376	BEQ	R16, nog
377	BEQ	R17, nog
378
379	MOVW	R2, m_procid(R16)
380
381	// In child, set up new stack
382	MOVW	R16, g_m(R17)
383	MOVW	R17, g
384
385// TODO(mips32): doesn't have runtime·stackcheck(SB)
386
387nog:
388	// Call fn
389	ADDU	$32, R29
390	JAL	(R18)
391
392	// It shouldn't return.	 If it does, exit that thread.
393	ADDU	$-32, R29
394	MOVW	$0xf4, R4
395	MOVW	$SYS_exit, R2
396	SYSCALL
397	UNDEF
398
399TEXT runtime·sigaltstack(SB),NOSPLIT,$0
400	MOVW	new+0(FP), R4
401	MOVW	old+4(FP), R5
402	MOVW	$SYS_sigaltstack, R2
403	SYSCALL
404	BEQ	R7, 2(PC)
405	UNDEF	// crash
406	RET
407
408TEXT runtime·osyield(SB),NOSPLIT,$0
409	MOVW	$SYS_sched_yield, R2
410	SYSCALL
411	RET
412
413TEXT runtime·sched_getaffinity(SB),NOSPLIT,$0-16
414	MOVW	pid+0(FP), R4
415	MOVW	len+4(FP), R5
416	MOVW	buf+8(FP), R6
417	MOVW	$SYS_sched_getaffinity, R2
418	SYSCALL
419	MOVW	R2, ret+12(FP)
420	RET
421
422// int32 runtime·epollcreate(int32 size);
423TEXT runtime·epollcreate(SB),NOSPLIT,$0-8
424	MOVW	size+0(FP), R4
425	MOVW	$SYS_epoll_create, R2
426	SYSCALL
427	MOVW	R2, ret+4(FP)
428	RET
429
430// int32 runtime·epollcreate1(int32 flags);
431TEXT runtime·epollcreate1(SB),NOSPLIT,$0-8
432	MOVW	flags+0(FP), R4
433	MOVW	$SYS_epoll_create1, R2
434	SYSCALL
435	MOVW	R2, ret+4(FP)
436	RET
437
438// func epollctl(epfd, op, fd int32, ev *epollEvent) int
439TEXT runtime·epollctl(SB),NOSPLIT,$0-20
440	MOVW	epfd+0(FP), R4
441	MOVW	op+4(FP), R5
442	MOVW	fd+8(FP), R6
443	MOVW	ev+12(FP), R7
444	MOVW	$SYS_epoll_ctl, R2
445	SYSCALL
446	MOVW	R2, ret+16(FP)
447	RET
448
449// int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout);
450TEXT runtime·epollwait(SB),NOSPLIT,$0-20
451	MOVW	epfd+0(FP), R4
452	MOVW	ev+4(FP), R5
453	MOVW	nev+8(FP), R6
454	MOVW	timeout+12(FP), R7
455	MOVW	$SYS_epoll_wait, R2
456	SYSCALL
457	MOVW	R2, ret+16(FP)
458	RET
459
460// void runtime·closeonexec(int32 fd);
461TEXT runtime·closeonexec(SB),NOSPLIT,$0-4
462	MOVW	fd+0(FP), R4	// fd
463	MOVW	$2, R5	// F_SETFD
464	MOVW	$1, R6	// FD_CLOEXEC
465	MOVW	$SYS_fcntl, R2
466	SYSCALL
467	RET
468