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