1// Copyright 2015 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 mips64 mips64le
7
8//
9// System calls and other sys.stuff for mips64, Linux
10//
11
12#include "go_asm.h"
13#include "go_tls.h"
14#include "textflag.h"
15
16#define AT_FDCWD -100
17
18#define SYS_exit		5058
19#define SYS_read		5000
20#define SYS_write		5001
21#define SYS_close		5003
22#define SYS_getpid		5038
23#define SYS_kill		5060
24#define SYS_fcntl		5070
25#define SYS_mmap		5009
26#define SYS_munmap		5011
27#define SYS_setitimer		5036
28#define SYS_clone		5055
29#define SYS_nanosleep		5034
30#define SYS_sched_yield		5023
31#define SYS_rt_sigreturn	5211
32#define SYS_rt_sigaction	5013
33#define SYS_rt_sigprocmask	5014
34#define SYS_sigaltstack		5129
35#define SYS_madvise		5027
36#define SYS_mincore		5026
37#define SYS_gettid		5178
38#define SYS_futex		5194
39#define SYS_sched_getaffinity	5196
40#define SYS_exit_group		5205
41#define SYS_epoll_create	5207
42#define SYS_epoll_ctl		5208
43#define SYS_tgkill		5225
44#define SYS_openat		5247
45#define SYS_epoll_pwait		5272
46#define SYS_clock_gettime	5222
47#define SYS_epoll_create1	5285
48#define SYS_brk			5012
49#define SYS_pipe2		5287
50
51TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0-4
52	MOVW	code+0(FP), R4
53	MOVV	$SYS_exit_group, R2
54	SYSCALL
55	RET
56
57// func exitThread(wait *uint32)
58TEXT runtime·exitThread(SB),NOSPLIT|NOFRAME,$0-8
59	MOVV	wait+0(FP), R1
60	// We're done using the stack.
61	MOVW	$0, R2
62	SYNC
63	MOVW	R2, (R1)
64	SYNC
65	MOVW	$0, R4	// exit code
66	MOVV	$SYS_exit, R2
67	SYSCALL
68	JMP	0(PC)
69
70TEXT runtime·open(SB),NOSPLIT|NOFRAME,$0-20
71	// This uses openat instead of open, because Android O blocks open.
72	MOVW	$AT_FDCWD, R4 // AT_FDCWD, so this acts like open
73	MOVV	name+0(FP), R5
74	MOVW	mode+8(FP), R6
75	MOVW	perm+12(FP), R7
76	MOVV	$SYS_openat, R2
77	SYSCALL
78	BEQ	R7, 2(PC)
79	MOVW	$-1, R2
80	MOVW	R2, ret+16(FP)
81	RET
82
83TEXT runtime·closefd(SB),NOSPLIT|NOFRAME,$0-12
84	MOVW	fd+0(FP), R4
85	MOVV	$SYS_close, R2
86	SYSCALL
87	BEQ	R7, 2(PC)
88	MOVW	$-1, R2
89	MOVW	R2, ret+8(FP)
90	RET
91
92TEXT runtime·write1(SB),NOSPLIT|NOFRAME,$0-28
93	MOVV	fd+0(FP), R4
94	MOVV	p+8(FP), R5
95	MOVW	n+16(FP), R6
96	MOVV	$SYS_write, R2
97	SYSCALL
98	BEQ	R7, 2(PC)
99	SUBVU	R2, R0, R2	// caller expects negative errno
100	MOVW	R2, ret+24(FP)
101	RET
102
103TEXT runtime·read(SB),NOSPLIT|NOFRAME,$0-28
104	MOVW	fd+0(FP), R4
105	MOVV	p+8(FP), R5
106	MOVW	n+16(FP), R6
107	MOVV	$SYS_read, R2
108	SYSCALL
109	BEQ	R7, 2(PC)
110	SUBVU	R2, R0, R2	// caller expects negative errno
111	MOVW	R2, ret+24(FP)
112	RET
113
114// func pipe() (r, w int32, errno int32)
115TEXT runtime·pipe(SB),NOSPLIT|NOFRAME,$0-12
116	MOVV	$r+0(FP), R4
117	MOVV	R0, R5
118	MOVV	$SYS_pipe2, R2
119	SYSCALL
120	MOVW	R2, errno+8(FP)
121	RET
122
123// func pipe2(flags int32) (r, w int32, errno int32)
124TEXT runtime·pipe2(SB),NOSPLIT|NOFRAME,$0-20
125	MOVV	$r+8(FP), R4
126	MOVW	flags+0(FP), R5
127	MOVV	$SYS_pipe2, R2
128	SYSCALL
129	MOVW	R2, errno+16(FP)
130	RET
131
132TEXT runtime·usleep(SB),NOSPLIT,$16-4
133	MOVWU	usec+0(FP), R3
134	MOVV	R3, R5
135	MOVW	$1000000, R4
136	DIVVU	R4, R3
137	MOVV	LO, R3
138	MOVV	R3, 8(R29)
139	MOVW	$1000, R4
140	MULVU	R3, R4
141	MOVV	LO, R4
142	SUBVU	R4, R5
143	MOVV	R5, 16(R29)
144
145	// nanosleep(&ts, 0)
146	ADDV	$8, R29, R4
147	MOVW	$0, R5
148	MOVV	$SYS_nanosleep, R2
149	SYSCALL
150	RET
151
152TEXT runtime·gettid(SB),NOSPLIT,$0-4
153	MOVV	$SYS_gettid, R2
154	SYSCALL
155	MOVW	R2, ret+0(FP)
156	RET
157
158TEXT runtime·raise(SB),NOSPLIT|NOFRAME,$0
159	MOVV	$SYS_getpid, R2
160	SYSCALL
161	MOVW	R2, R16
162	MOVV	$SYS_gettid, R2
163	SYSCALL
164	MOVW	R2, R5	// arg 2 tid
165	MOVW	R16, R4	// arg 1 pid
166	MOVW	sig+0(FP), R6	// arg 3
167	MOVV	$SYS_tgkill, R2
168	SYSCALL
169	RET
170
171TEXT runtime·raiseproc(SB),NOSPLIT|NOFRAME,$0
172	MOVV	$SYS_getpid, R2
173	SYSCALL
174	MOVW	R2, R4	// arg 1 pid
175	MOVW	sig+0(FP), R5	// arg 2
176	MOVV	$SYS_kill, R2
177	SYSCALL
178	RET
179
180TEXT ·getpid(SB),NOSPLIT|NOFRAME,$0-8
181	MOVV	$SYS_getpid, R2
182	SYSCALL
183	MOVV	R2, ret+0(FP)
184	RET
185
186TEXT ·tgkill(SB),NOSPLIT|NOFRAME,$0-24
187	MOVV	tgid+0(FP), R4
188	MOVV	tid+8(FP), R5
189	MOVV	sig+16(FP), R6
190	MOVV	$SYS_tgkill, R2
191	SYSCALL
192	RET
193
194TEXT runtime·setitimer(SB),NOSPLIT|NOFRAME,$0-24
195	MOVW	mode+0(FP), R4
196	MOVV	new+8(FP), R5
197	MOVV	old+16(FP), R6
198	MOVV	$SYS_setitimer, R2
199	SYSCALL
200	RET
201
202TEXT runtime·mincore(SB),NOSPLIT|NOFRAME,$0-28
203	MOVV	addr+0(FP), R4
204	MOVV	n+8(FP), R5
205	MOVV	dst+16(FP), R6
206	MOVV	$SYS_mincore, R2
207	SYSCALL
208	SUBVU	R2, R0, R2	// caller expects negative errno
209	MOVW	R2, ret+24(FP)
210	RET
211
212// func walltime1() (sec int64, nsec int32)
213TEXT runtime·walltime1(SB),NOSPLIT,$16
214	MOVV	R29, R16	// R16 is unchanged by C code
215	MOVV	R29, R1
216
217	MOVV	g_m(g), R17	// R17 = m
218
219	// Set vdsoPC and vdsoSP for SIGPROF traceback.
220	MOVV	R31, m_vdsoPC(R17)
221	MOVV	R29, m_vdsoSP(R17)
222
223	MOVV	m_curg(R17), R4
224	MOVV	g, R5
225	BNE	R4, R5, noswitch
226
227	MOVV	m_g0(R17), R4
228	MOVV	(g_sched+gobuf_sp)(R4), R1	// Set SP to g0 stack
229
230noswitch:
231	SUBV	$16, R1
232	AND	$~15, R1	// Align for C code
233	MOVV	R1, R29
234
235	MOVW	$0, R4 // CLOCK_REALTIME
236	MOVV	$0(R29), R5
237
238	MOVV	runtime·vdsoClockgettimeSym(SB), R25
239	BEQ	R25, fallback
240
241	JAL	(R25)
242
243finish:
244	MOVV	0(R29), R3	// sec
245	MOVV	8(R29), R5	// nsec
246
247	MOVV	R16, R29	// restore SP
248	MOVV	R0, m_vdsoSP(R17)	// clear vdsoSP
249
250	MOVV	R3, sec+0(FP)
251	MOVW	R5, nsec+8(FP)
252	RET
253
254fallback:
255	MOVV	$SYS_clock_gettime, R2
256	SYSCALL
257	JMP finish
258
259TEXT runtime·nanotime1(SB),NOSPLIT,$16
260	MOVV	R29, R16	// R16 is unchanged by C code
261	MOVV	R29, R1
262
263	MOVV	g_m(g), R17	// R17 = m
264
265	// Set vdsoPC and vdsoSP for SIGPROF traceback.
266	MOVV	R31, m_vdsoPC(R17)
267	MOVV	R29, m_vdsoSP(R17)
268
269	MOVV	m_curg(R17), R4
270	MOVV	g, R5
271	BNE	R4, R5, noswitch
272
273	MOVV	m_g0(R17), R4
274	MOVV	(g_sched+gobuf_sp)(R4), R1	// Set SP to g0 stack
275
276noswitch:
277	SUBV	$16, R1
278	AND	$~15, R1	// Align for C code
279	MOVV	R1, R29
280
281	MOVW	$1, R4 // CLOCK_MONOTONIC
282	MOVV	$0(R29), R5
283
284	MOVV	runtime·vdsoClockgettimeSym(SB), R25
285	BEQ	R25, fallback
286
287	JAL	(R25)
288
289finish:
290	MOVV	0(R29), R3	// sec
291	MOVV	8(R29), R5	// nsec
292
293	MOVV	R16, R29	// restore SP
294	MOVV	R0, m_vdsoSP(R17)	// clear vdsoSP
295
296	// sec is in R3, nsec in R5
297	// return nsec in R3
298	MOVV	$1000000000, R4
299	MULVU	R4, R3
300	MOVV	LO, R3
301	ADDVU	R5, R3
302	MOVV	R3, ret+0(FP)
303	RET
304
305fallback:
306	MOVV	$SYS_clock_gettime, R2
307	SYSCALL
308	JMP	finish
309
310TEXT runtime·rtsigprocmask(SB),NOSPLIT|NOFRAME,$0-28
311	MOVW	how+0(FP), R4
312	MOVV	new+8(FP), R5
313	MOVV	old+16(FP), R6
314	MOVW	size+24(FP), R7
315	MOVV	$SYS_rt_sigprocmask, R2
316	SYSCALL
317	BEQ	R7, 2(PC)
318	MOVV	R0, 0xf1(R0)	// crash
319	RET
320
321TEXT runtime·rt_sigaction(SB),NOSPLIT|NOFRAME,$0-36
322	MOVV	sig+0(FP), R4
323	MOVV	new+8(FP), R5
324	MOVV	old+16(FP), R6
325	MOVV	size+24(FP), R7
326	MOVV	$SYS_rt_sigaction, R2
327	SYSCALL
328	BEQ	R7, 2(PC)
329	SUBVU	R2, R0, R2	// caller expects negative errno
330	MOVW	R2, ret+32(FP)
331	RET
332
333TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
334	MOVW	sig+8(FP), R4
335	MOVV	info+16(FP), R5
336	MOVV	ctx+24(FP), R6
337	MOVV	fn+0(FP), R25
338	JAL	(R25)
339	RET
340
341TEXT runtime·sigtramp(SB),NOSPLIT,$64
342	// initialize REGSB = PC&0xffffffff00000000
343	BGEZAL	R0, 1(PC)
344	SRLV	$32, R31, RSB
345	SLLV	$32, RSB
346
347	// this might be called in external code context,
348	// where g is not set.
349	MOVB	runtime·iscgo(SB), R1
350	BEQ	R1, 2(PC)
351	JAL	runtime·load_g(SB)
352
353	MOVW	R4, 8(R29)
354	MOVV	R5, 16(R29)
355	MOVV	R6, 24(R29)
356	MOVV	$runtime·sigtrampgo(SB), R1
357	JAL	(R1)
358	RET
359
360TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0
361	JMP	runtime·sigtramp(SB)
362
363TEXT runtime·mmap(SB),NOSPLIT|NOFRAME,$0
364	MOVV	addr+0(FP), R4
365	MOVV	n+8(FP), R5
366	MOVW	prot+16(FP), R6
367	MOVW	flags+20(FP), R7
368	MOVW	fd+24(FP), R8
369	MOVW	off+28(FP), R9
370
371	MOVV	$SYS_mmap, R2
372	SYSCALL
373	BEQ	R7, ok
374	MOVV	$0, p+32(FP)
375	MOVV	R2, err+40(FP)
376	RET
377ok:
378	MOVV	R2, p+32(FP)
379	MOVV	$0, err+40(FP)
380	RET
381
382TEXT runtime·munmap(SB),NOSPLIT|NOFRAME,$0
383	MOVV	addr+0(FP), R4
384	MOVV	n+8(FP), R5
385	MOVV	$SYS_munmap, R2
386	SYSCALL
387	BEQ	R7, 2(PC)
388	MOVV	R0, 0xf3(R0)	// crash
389	RET
390
391TEXT runtime·madvise(SB),NOSPLIT|NOFRAME,$0
392	MOVV	addr+0(FP), R4
393	MOVV	n+8(FP), R5
394	MOVW	flags+16(FP), R6
395	MOVV	$SYS_madvise, R2
396	SYSCALL
397	MOVW	R2, ret+24(FP)
398	RET
399
400// int64 futex(int32 *uaddr, int32 op, int32 val,
401//	struct timespec *timeout, int32 *uaddr2, int32 val2);
402TEXT runtime·futex(SB),NOSPLIT|NOFRAME,$0
403	MOVV	addr+0(FP), R4
404	MOVW	op+8(FP), R5
405	MOVW	val+12(FP), R6
406	MOVV	ts+16(FP), R7
407	MOVV	addr2+24(FP), R8
408	MOVW	val3+32(FP), R9
409	MOVV	$SYS_futex, R2
410	SYSCALL
411	BEQ	R7, 2(PC)
412	SUBVU	R2, R0, R2	// caller expects negative errno
413	MOVW	R2, ret+40(FP)
414	RET
415
416// int64 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));
417TEXT runtime·clone(SB),NOSPLIT|NOFRAME,$0
418	MOVW	flags+0(FP), R4
419	MOVV	stk+8(FP), R5
420
421	// Copy mp, gp, fn off parent stack for use by child.
422	// Careful: Linux system call clobbers ???.
423	MOVV	mp+16(FP), R16
424	MOVV	gp+24(FP), R17
425	MOVV	fn+32(FP), R18
426
427	MOVV	R16, -8(R5)
428	MOVV	R17, -16(R5)
429	MOVV	R18, -24(R5)
430	MOVV	$1234, R16
431	MOVV	R16, -32(R5)
432
433	MOVV	$SYS_clone, R2
434	SYSCALL
435	BEQ	R7, 2(PC)
436	SUBVU	R2, R0, R2	// caller expects negative errno
437
438	// In parent, return.
439	BEQ	R2, 3(PC)
440	MOVW	R2, ret+40(FP)
441	RET
442
443	// In child, on new stack.
444	MOVV	-32(R29), R16
445	MOVV	$1234, R1
446	BEQ	R16, R1, 2(PC)
447	MOVV	R0, 0(R0)
448
449	// Initialize m->procid to Linux tid
450	MOVV	$SYS_gettid, R2
451	SYSCALL
452
453	MOVV	-24(R29), R18		// fn
454	MOVV	-16(R29), R17		// g
455	MOVV	-8(R29), R16		// m
456
457	BEQ	R16, nog
458	BEQ	R17, nog
459
460	MOVV	R2, m_procid(R16)
461
462	// TODO: setup TLS.
463
464	// In child, set up new stack
465	MOVV	R16, g_m(R17)
466	MOVV	R17, g
467	//CALL	runtime·stackcheck(SB)
468
469nog:
470	// Call fn
471	JAL	(R18)
472
473	// It shouldn't return.	 If it does, exit that thread.
474	MOVW	$111, R4
475	MOVV	$SYS_exit, R2
476	SYSCALL
477	JMP	-3(PC)	// keep exiting
478
479TEXT runtime·sigaltstack(SB),NOSPLIT|NOFRAME,$0
480	MOVV	new+0(FP), R4
481	MOVV	old+8(FP), R5
482	MOVV	$SYS_sigaltstack, R2
483	SYSCALL
484	BEQ	R7, 2(PC)
485	MOVV	R0, 0xf1(R0)	// crash
486	RET
487
488TEXT runtime·osyield(SB),NOSPLIT|NOFRAME,$0
489	MOVV	$SYS_sched_yield, R2
490	SYSCALL
491	RET
492
493TEXT runtime·sched_getaffinity(SB),NOSPLIT|NOFRAME,$0
494	MOVV	pid+0(FP), R4
495	MOVV	len+8(FP), R5
496	MOVV	buf+16(FP), R6
497	MOVV	$SYS_sched_getaffinity, R2
498	SYSCALL
499	BEQ	R7, 2(PC)
500	SUBVU	R2, R0, R2	// caller expects negative errno
501	MOVW	R2, ret+24(FP)
502	RET
503
504// int32 runtime·epollcreate(int32 size);
505TEXT runtime·epollcreate(SB),NOSPLIT|NOFRAME,$0
506	MOVW    size+0(FP), R4
507	MOVV	$SYS_epoll_create, R2
508	SYSCALL
509	BEQ	R7, 2(PC)
510	SUBVU	R2, R0, R2	// caller expects negative errno
511	MOVW	R2, ret+8(FP)
512	RET
513
514// int32 runtime·epollcreate1(int32 flags);
515TEXT runtime·epollcreate1(SB),NOSPLIT|NOFRAME,$0
516	MOVW	flags+0(FP), R4
517	MOVV	$SYS_epoll_create1, R2
518	SYSCALL
519	BEQ	R7, 2(PC)
520	SUBVU	R2, R0, R2	// caller expects negative errno
521	MOVW	R2, ret+8(FP)
522	RET
523
524// func epollctl(epfd, op, fd int32, ev *epollEvent) int
525TEXT runtime·epollctl(SB),NOSPLIT|NOFRAME,$0
526	MOVW	epfd+0(FP), R4
527	MOVW	op+4(FP), R5
528	MOVW	fd+8(FP), R6
529	MOVV	ev+16(FP), R7
530	MOVV	$SYS_epoll_ctl, R2
531	SYSCALL
532	SUBVU	R2, R0, R2	// caller expects negative errno
533	MOVW	R2, ret+24(FP)
534	RET
535
536// int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout);
537TEXT runtime·epollwait(SB),NOSPLIT|NOFRAME,$0
538	// This uses pwait instead of wait, because Android O blocks wait.
539	MOVW	epfd+0(FP), R4
540	MOVV	ev+8(FP), R5
541	MOVW	nev+16(FP), R6
542	MOVW	timeout+20(FP), R7
543	MOVV	$0, R8
544	MOVV	$SYS_epoll_pwait, R2
545	SYSCALL
546	BEQ	R7, 2(PC)
547	SUBVU	R2, R0, R2	// caller expects negative errno
548	MOVW	R2, ret+24(FP)
549	RET
550
551// void runtime·closeonexec(int32 fd);
552TEXT runtime·closeonexec(SB),NOSPLIT|NOFRAME,$0
553	MOVW    fd+0(FP), R4  // fd
554	MOVV    $2, R5  // F_SETFD
555	MOVV    $1, R6  // FD_CLOEXEC
556	MOVV	$SYS_fcntl, R2
557	SYSCALL
558	RET
559
560// func runtime·setNonblock(int32 fd)
561TEXT runtime·setNonblock(SB),NOSPLIT|NOFRAME,$0-4
562	MOVW	fd+0(FP), R4 // fd
563	MOVV	$3, R5	// F_GETFL
564	MOVV	$0, R6
565	MOVV	$SYS_fcntl, R2
566	SYSCALL
567	MOVW	$0x80, R6 // O_NONBLOCK
568	OR	R2, R6
569	MOVW	fd+0(FP), R4 // fd
570	MOVV	$4, R5	// F_SETFL
571	MOVV	$SYS_fcntl, R2
572	SYSCALL
573	RET
574
575// func sbrk0() uintptr
576TEXT runtime·sbrk0(SB),NOSPLIT|NOFRAME,$0-8
577	// Implemented as brk(NULL).
578	MOVV	$0, R4
579	MOVV	$SYS_brk, R2
580	SYSCALL
581	MOVV	R2, ret+0(FP)
582	RET
583
584TEXT runtime·access(SB),$0-20
585	MOVV	R0, 2(R0) // unimplemented, only needed for android; declared in stubs_linux.go
586	MOVW	R0, ret+16(FP) // for vet
587	RET
588
589TEXT runtime·connect(SB),$0-28
590	MOVV	R0, 2(R0) // unimplemented, only needed for android; declared in stubs_linux.go
591	MOVW	R0, ret+24(FP) // for vet
592	RET
593
594TEXT runtime·socket(SB),$0-20
595	MOVV	R0, 2(R0) // unimplemented, only needed for android; declared in stubs_linux.go
596	MOVW	R0, ret+16(FP) // for vet
597	RET
598