Text file
src/runtime/sys_linux_ppc64x.s
1 // Copyright 2014 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 && (ppc64 || ppc64le)
6
7 //
8 // System calls and other sys.stuff for ppc64, Linux
9 //
10
11 #include "go_asm.h"
12 #include "go_tls.h"
13 #include "textflag.h"
14 #include "asm_ppc64x.h"
15
16 #define SYS_exit 1
17 #define SYS_read 3
18 #define SYS_write 4
19 #define SYS_open 5
20 #define SYS_close 6
21 #define SYS_getpid 20
22 #define SYS_kill 37
23 #define SYS_brk 45
24 #define SYS_fcntl 55
25 #define SYS_mmap 90
26 #define SYS_munmap 91
27 #define SYS_setitimer 104
28 #define SYS_clone 120
29 #define SYS_sched_yield 158
30 #define SYS_nanosleep 162
31 #define SYS_rt_sigreturn 172
32 #define SYS_rt_sigaction 173
33 #define SYS_rt_sigprocmask 174
34 #define SYS_sigaltstack 185
35 #define SYS_madvise 205
36 #define SYS_mincore 206
37 #define SYS_gettid 207
38 #define SYS_futex 221
39 #define SYS_sched_getaffinity 223
40 #define SYS_exit_group 234
41 #define SYS_epoll_create 236
42 #define SYS_epoll_ctl 237
43 #define SYS_epoll_wait 238
44 #define SYS_timer_create 240
45 #define SYS_timer_settime 241
46 #define SYS_timer_delete 244
47 #define SYS_clock_gettime 246
48 #define SYS_tgkill 250
49 #define SYS_epoll_create1 315
50 #define SYS_pipe2 317
51
52 TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0-4
53 MOVW code+0(FP), R3
54 SYSCALL $SYS_exit_group
55 RET
56
57 // func exitThread(wait *atomic.Uint32)
58 TEXT runtime·exitThread(SB),NOSPLIT|NOFRAME,$0-8
59 MOVD wait+0(FP), R1
60 // We're done using the stack.
61 MOVW $0, R2
62 SYNC
63 MOVW R2, (R1)
64 MOVW $0, R3 // exit code
65 SYSCALL $SYS_exit
66 JMP 0(PC)
67
68 TEXT runtime·open(SB),NOSPLIT|NOFRAME,$0-20
69 MOVD name+0(FP), R3
70 MOVW mode+8(FP), R4
71 MOVW perm+12(FP), R5
72 SYSCALL $SYS_open
73 BVC 2(PC)
74 MOVW $-1, R3
75 MOVW R3, ret+16(FP)
76 RET
77
78 TEXT runtime·closefd(SB),NOSPLIT|NOFRAME,$0-12
79 MOVW fd+0(FP), R3
80 SYSCALL $SYS_close
81 BVC 2(PC)
82 MOVW $-1, R3
83 MOVW R3, ret+8(FP)
84 RET
85
86 TEXT runtime·write1(SB),NOSPLIT|NOFRAME,$0-28
87 MOVD fd+0(FP), R3
88 MOVD p+8(FP), R4
89 MOVW n+16(FP), R5
90 SYSCALL $SYS_write
91 BVC 2(PC)
92 NEG R3 // caller expects negative errno
93 MOVW R3, ret+24(FP)
94 RET
95
96 TEXT runtime·read(SB),NOSPLIT|NOFRAME,$0-28
97 MOVW fd+0(FP), R3
98 MOVD p+8(FP), R4
99 MOVW n+16(FP), R5
100 SYSCALL $SYS_read
101 BVC 2(PC)
102 NEG R3 // caller expects negative errno
103 MOVW R3, ret+24(FP)
104 RET
105
106 // func pipe2(flags int32) (r, w int32, errno int32)
107 TEXT runtime·pipe2(SB),NOSPLIT|NOFRAME,$0-20
108 ADD $FIXED_FRAME+8, R1, R3
109 MOVW flags+0(FP), R4
110 SYSCALL $SYS_pipe2
111 MOVW R3, errno+16(FP)
112 RET
113
114 // func usleep(usec uint32)
115 TEXT runtime·usleep(SB),NOSPLIT,$16-4
116 MOVW usec+0(FP), R3
117
118 // Use magic constant 0x8637bd06 and shift right 51
119 // to perform usec/1000000.
120 ORIS $0x8637, R0, R4 // Note, R0 always contains 0 here.
121 OR $0xbd06, R4, R4
122 MULLD R3, R4, R4 // Convert usec to S.
123 SRD $51, R4, R4
124 MOVD R4, 8(R1) // Store to tv_sec
125
126 MOVD $1000000, R5
127 MULLW R4, R5, R5 // Convert tv_sec back into uS
128 SUB R5, R3, R5 // Compute remainder uS.
129 MULLD $1000, R5, R5 // Convert to nsec
130 MOVD R5, 16(R1) // Store to tv_nsec
131
132 // nanosleep(&ts, 0)
133 ADD $8, R1, R3
134 MOVW $0, R4
135 SYSCALL $SYS_nanosleep
136 RET
137
138 TEXT runtime·gettid(SB),NOSPLIT,$0-4
139 SYSCALL $SYS_gettid
140 MOVW R3, ret+0(FP)
141 RET
142
143 TEXT runtime·raise(SB),NOSPLIT|NOFRAME,$0
144 SYSCALL $SYS_getpid
145 MOVW R3, R14
146 SYSCALL $SYS_gettid
147 MOVW R3, R4 // arg 2 tid
148 MOVW R14, R3 // arg 1 pid
149 MOVW sig+0(FP), R5 // arg 3
150 SYSCALL $SYS_tgkill
151 RET
152
153 TEXT runtime·raiseproc(SB),NOSPLIT|NOFRAME,$0
154 SYSCALL $SYS_getpid
155 MOVW R3, R3 // arg 1 pid
156 MOVW sig+0(FP), R4 // arg 2
157 SYSCALL $SYS_kill
158 RET
159
160 TEXT ·getpid(SB),NOSPLIT|NOFRAME,$0-8
161 SYSCALL $SYS_getpid
162 MOVD R3, ret+0(FP)
163 RET
164
165 TEXT ·tgkill(SB),NOSPLIT|NOFRAME,$0-24
166 MOVD tgid+0(FP), R3
167 MOVD tid+8(FP), R4
168 MOVD sig+16(FP), R5
169 SYSCALL $SYS_tgkill
170 RET
171
172 TEXT runtime·setitimer(SB),NOSPLIT|NOFRAME,$0-24
173 MOVW mode+0(FP), R3
174 MOVD new+8(FP), R4
175 MOVD old+16(FP), R5
176 SYSCALL $SYS_setitimer
177 RET
178
179 TEXT runtime·timer_create(SB),NOSPLIT,$0-28
180 MOVW clockid+0(FP), R3
181 MOVD sevp+8(FP), R4
182 MOVD timerid+16(FP), R5
183 SYSCALL $SYS_timer_create
184 MOVW R3, ret+24(FP)
185 RET
186
187 TEXT runtime·timer_settime(SB),NOSPLIT,$0-28
188 MOVW timerid+0(FP), R3
189 MOVW flags+4(FP), R4
190 MOVD new+8(FP), R5
191 MOVD old+16(FP), R6
192 SYSCALL $SYS_timer_settime
193 MOVW R3, ret+24(FP)
194 RET
195
196 TEXT runtime·timer_delete(SB),NOSPLIT,$0-12
197 MOVW timerid+0(FP), R3
198 SYSCALL $SYS_timer_delete
199 MOVW R3, ret+8(FP)
200 RET
201
202 TEXT runtime·mincore(SB),NOSPLIT|NOFRAME,$0-28
203 MOVD addr+0(FP), R3
204 MOVD n+8(FP), R4
205 MOVD dst+16(FP), R5
206 SYSCALL $SYS_mincore
207 NEG R3 // caller expects negative errno
208 MOVW R3, ret+24(FP)
209 RET
210
211 // func walltime() (sec int64, nsec int32)
212 TEXT runtime·walltime(SB),NOSPLIT,$16-12
213 MOVD R1, R15 // R15 is unchanged by C code
214 MOVD g_m(g), R21 // R21 = m
215
216 MOVD $0, R3 // CLOCK_REALTIME
217
218 MOVD runtime·vdsoClockgettimeSym(SB), R12 // Check for VDSO availability
219 CMP R12, R0
220 BEQ fallback
221
222 // Set vdsoPC and vdsoSP for SIGPROF traceback.
223 // Save the old values on stack and restore them on exit,
224 // so this function is reentrant.
225 MOVD m_vdsoPC(R21), R4
226 MOVD m_vdsoSP(R21), R5
227 MOVD R4, 32(R1)
228 MOVD R5, 40(R1)
229
230 MOVD LR, R14
231 MOVD $ret-FIXED_FRAME(FP), R5 // caller's SP
232 MOVD R14, m_vdsoPC(R21)
233 MOVD R5, m_vdsoSP(R21)
234
235 MOVD m_curg(R21), R6
236 CMP g, R6
237 BNE noswitch
238
239 MOVD m_g0(R21), R7
240 MOVD (g_sched+gobuf_sp)(R7), R1 // Set SP to g0 stack
241
242 noswitch:
243 SUB $16, R1 // Space for results
244 RLDICR $0, R1, $59, R1 // Align for C code
245 MOVD R12, CTR
246 MOVD R1, R4
247
248 // Store g on gsignal's stack, so if we receive a signal
249 // during VDSO code we can find the g.
250 // If we don't have a signal stack, we won't receive signal,
251 // so don't bother saving g.
252 // When using cgo, we already saved g on TLS, also don't save
253 // g here.
254 // Also don't save g if we are already on the signal stack.
255 // We won't get a nested signal.
256 MOVBZ runtime·iscgo(SB), R22
257 CMP R22, $0
258 BNE nosaveg
259 MOVD m_gsignal(R21), R22 // g.m.gsignal
260 CMP R22, $0
261 BEQ nosaveg
262
263 CMP g, R22
264 BEQ nosaveg
265 MOVD (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo
266 MOVD g, (R22)
267
268 BL (CTR) // Call from VDSO
269
270 MOVD $0, (R22) // clear g slot, R22 is unchanged by C code
271
272 JMP finish
273
274 nosaveg:
275 BL (CTR) // Call from VDSO
276
277 finish:
278 MOVD $0, R0 // Restore R0
279 MOVD 0(R1), R3 // sec
280 MOVD 8(R1), R5 // nsec
281 MOVD R15, R1 // Restore SP
282
283 // Restore vdsoPC, vdsoSP
284 // We don't worry about being signaled between the two stores.
285 // If we are not in a signal handler, we'll restore vdsoSP to 0,
286 // and no one will care about vdsoPC. If we are in a signal handler,
287 // we cannot receive another signal.
288 MOVD 40(R1), R6
289 MOVD R6, m_vdsoSP(R21)
290 MOVD 32(R1), R6
291 MOVD R6, m_vdsoPC(R21)
292
293 return:
294 MOVD R3, sec+0(FP)
295 MOVW R5, nsec+8(FP)
296 RET
297
298 // Syscall fallback
299 fallback:
300 ADD $32, R1, R4
301 SYSCALL $SYS_clock_gettime
302 MOVD 32(R1), R3
303 MOVD 40(R1), R5
304 JMP return
305
306 TEXT runtime·nanotime1(SB),NOSPLIT,$16-8
307 MOVD $1, R3 // CLOCK_MONOTONIC
308
309 MOVD R1, R15 // R15 is unchanged by C code
310 MOVD g_m(g), R21 // R21 = m
311
312 MOVD runtime·vdsoClockgettimeSym(SB), R12 // Check for VDSO availability
313 CMP R12, R0
314 BEQ fallback
315
316 // Set vdsoPC and vdsoSP for SIGPROF traceback.
317 // Save the old values on stack and restore them on exit,
318 // so this function is reentrant.
319 MOVD m_vdsoPC(R21), R4
320 MOVD m_vdsoSP(R21), R5
321 MOVD R4, 32(R1)
322 MOVD R5, 40(R1)
323
324 MOVD LR, R14 // R14 is unchanged by C code
325 MOVD $ret-FIXED_FRAME(FP), R5 // caller's SP
326 MOVD R14, m_vdsoPC(R21)
327 MOVD R5, m_vdsoSP(R21)
328
329 MOVD m_curg(R21), R6
330 CMP g, R6
331 BNE noswitch
332
333 MOVD m_g0(R21), R7
334 MOVD (g_sched+gobuf_sp)(R7), R1 // Set SP to g0 stack
335
336 noswitch:
337 SUB $16, R1 // Space for results
338 RLDICR $0, R1, $59, R1 // Align for C code
339 MOVD R12, CTR
340 MOVD R1, R4
341
342 // Store g on gsignal's stack, so if we receive a signal
343 // during VDSO code we can find the g.
344 // If we don't have a signal stack, we won't receive signal,
345 // so don't bother saving g.
346 // When using cgo, we already saved g on TLS, also don't save
347 // g here.
348 // Also don't save g if we are already on the signal stack.
349 // We won't get a nested signal.
350 MOVBZ runtime·iscgo(SB), R22
351 CMP R22, $0
352 BNE nosaveg
353 MOVD m_gsignal(R21), R22 // g.m.gsignal
354 CMP R22, $0
355 BEQ nosaveg
356
357 CMP g, R22
358 BEQ nosaveg
359 MOVD (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo
360 MOVD g, (R22)
361
362 BL (CTR) // Call from VDSO
363
364 MOVD $0, (R22) // clear g slot, R22 is unchanged by C code
365
366 JMP finish
367
368 nosaveg:
369 BL (CTR) // Call from VDSO
370
371 finish:
372 MOVD $0, R0 // Restore R0
373 MOVD 0(R1), R3 // sec
374 MOVD 8(R1), R5 // nsec
375 MOVD R15, R1 // Restore SP
376
377 // Restore vdsoPC, vdsoSP
378 // We don't worry about being signaled between the two stores.
379 // If we are not in a signal handler, we'll restore vdsoSP to 0,
380 // and no one will care about vdsoPC. If we are in a signal handler,
381 // we cannot receive another signal.
382 MOVD 40(R1), R6
383 MOVD R6, m_vdsoSP(R21)
384 MOVD 32(R1), R6
385 MOVD R6, m_vdsoPC(R21)
386
387 return:
388 // sec is in R3, nsec in R5
389 // return nsec in R3
390 MOVD $1000000000, R4
391 MULLD R4, R3
392 ADD R5, R3
393 MOVD R3, ret+0(FP)
394 RET
395
396 // Syscall fallback
397 fallback:
398 ADD $32, R1, R4
399 SYSCALL $SYS_clock_gettime
400 MOVD 32(R1), R3
401 MOVD 40(R1), R5
402 JMP return
403
404 TEXT runtime·rtsigprocmask(SB),NOSPLIT|NOFRAME,$0-28
405 MOVW how+0(FP), R3
406 MOVD new+8(FP), R4
407 MOVD old+16(FP), R5
408 MOVW size+24(FP), R6
409 SYSCALL $SYS_rt_sigprocmask
410 BVC 2(PC)
411 MOVD R0, 0xf0(R0) // crash
412 RET
413
414 TEXT runtime·rt_sigaction(SB),NOSPLIT|NOFRAME,$0-36
415 MOVD sig+0(FP), R3
416 MOVD new+8(FP), R4
417 MOVD old+16(FP), R5
418 MOVD size+24(FP), R6
419 SYSCALL $SYS_rt_sigaction
420 BVC 2(PC)
421 NEG R3 // caller expects negative errno
422 MOVW R3, ret+32(FP)
423 RET
424
425 #ifdef GOARCH_ppc64le
426 // Call the function stored in _cgo_sigaction using the GCC calling convention.
427 TEXT runtime·callCgoSigaction(SB),NOSPLIT,$0
428 MOVD sig+0(FP), R3
429 MOVD new+8(FP), R4
430 MOVD old+16(FP), R5
431 MOVD _cgo_sigaction(SB), R12
432 MOVD R12, CTR // R12 should contain the function address
433 MOVD R1, R15 // Save R1
434 MOVD R2, 24(R1) // Save R2
435 SUB $48, R1 // reserve 32 (frame) + 16 bytes for sp-8 where fp may be saved.
436 RLDICR $0, R1, $59, R1 // Align to 16 bytes for C code
437 BL (CTR)
438 XOR R0, R0, R0 // Clear R0 as Go expects
439 MOVD R15, R1 // Restore R1
440 MOVD 24(R1), R2 // Restore R2
441 MOVW R3, ret+24(FP) // Return result
442 RET
443 #endif
444
445 TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
446 MOVW sig+8(FP), R3
447 MOVD info+16(FP), R4
448 MOVD ctx+24(FP), R5
449 MOVD fn+0(FP), R12
450 MOVD R12, CTR
451 BL (CTR)
452 MOVD 24(R1), R2
453 RET
454
455 TEXT runtime·sigreturn(SB),NOSPLIT,$0-0
456 RET
457
458 #ifdef GOARCH_ppc64le
459 // ppc64le doesn't need function descriptors
460 // Save callee-save registers in the case of signal forwarding.
461 // Same as on ARM64 https://golang.org/issue/31827 .
462 TEXT runtime·sigtramp(SB),NOSPLIT|NOFRAME,$0
463 #else
464 // function descriptor for the real sigtramp
465 TEXT runtime·sigtramp(SB),NOSPLIT|NOFRAME,$0
466 DWORD $sigtramp<>(SB)
467 DWORD $0
468 DWORD $0
469 TEXT sigtramp<>(SB),NOSPLIT|NOFRAME|TOPFRAME,$0
470 #endif
471 // Start with standard C stack frame layout and linkage.
472 MOVD LR, R0
473 MOVD R0, 16(R1) // Save LR in caller's frame.
474 MOVW CR, R0 // Save CR in caller's frame
475 MOVD R0, 8(R1)
476 // The stack must be acquired here and not
477 // in the automatic way based on stack size
478 // since that sequence clobbers R31 before it
479 // gets saved.
480 // We are being ultra safe here in saving the
481 // Vregs. The case where they might need to
482 // be saved is very unlikely.
483 MOVDU R1, -544(R1)
484 MOVD R14, 64(R1)
485 MOVD R15, 72(R1)
486 MOVD R16, 80(R1)
487 MOVD R17, 88(R1)
488 MOVD R18, 96(R1)
489 MOVD R19, 104(R1)
490 MOVD R20, 112(R1)
491 MOVD R21, 120(R1)
492 MOVD R22, 128(R1)
493 MOVD R23, 136(R1)
494 MOVD R24, 144(R1)
495 MOVD R25, 152(R1)
496 MOVD R26, 160(R1)
497 MOVD R27, 168(R1)
498 MOVD R28, 176(R1)
499 MOVD R29, 184(R1)
500 MOVD g, 192(R1) // R30
501 MOVD R31, 200(R1)
502 FMOVD F14, 208(R1)
503 FMOVD F15, 216(R1)
504 FMOVD F16, 224(R1)
505 FMOVD F17, 232(R1)
506 FMOVD F18, 240(R1)
507 FMOVD F19, 248(R1)
508 FMOVD F20, 256(R1)
509 FMOVD F21, 264(R1)
510 FMOVD F22, 272(R1)
511 FMOVD F23, 280(R1)
512 FMOVD F24, 288(R1)
513 FMOVD F25, 296(R1)
514 FMOVD F26, 304(R1)
515 FMOVD F27, 312(R1)
516 FMOVD F28, 320(R1)
517 FMOVD F29, 328(R1)
518 FMOVD F30, 336(R1)
519 FMOVD F31, 344(R1)
520 // Save V regs
521 // STXVD2X and LXVD2X used since
522 // we aren't sure of alignment.
523 // Endianness doesn't matter
524 // if we are just loading and
525 // storing values.
526 MOVD $352, R7 // V20
527 STXVD2X VS52, (R7)(R1)
528 ADD $16, R7 // V21 368
529 STXVD2X VS53, (R7)(R1)
530 ADD $16, R7 // V22 384
531 STXVD2X VS54, (R7)(R1)
532 ADD $16, R7 // V23 400
533 STXVD2X VS55, (R7)(R1)
534 ADD $16, R7 // V24 416
535 STXVD2X VS56, (R7)(R1)
536 ADD $16, R7 // V25 432
537 STXVD2X VS57, (R7)(R1)
538 ADD $16, R7 // V26 448
539 STXVD2X VS58, (R7)(R1)
540 ADD $16, R7 // V27 464
541 STXVD2X VS59, (R7)(R1)
542 ADD $16, R7 // V28 480
543 STXVD2X VS60, (R7)(R1)
544 ADD $16, R7 // V29 496
545 STXVD2X VS61, (R7)(R1)
546 ADD $16, R7 // V30 512
547 STXVD2X VS62, (R7)(R1)
548 ADD $16, R7 // V31 528
549 STXVD2X VS63, (R7)(R1)
550
551 // initialize essential registers (just in case)
552 BL runtime·reginit(SB)
553
554 // this might be called in external code context,
555 // where g is not set.
556 MOVBZ runtime·iscgo(SB), R6
557 CMP R6, $0
558 BEQ 2(PC)
559 BL runtime·load_g(SB)
560
561 MOVW R3, FIXED_FRAME+0(R1)
562 MOVD R4, FIXED_FRAME+8(R1)
563 MOVD R5, FIXED_FRAME+16(R1)
564 MOVD $runtime·sigtrampgo(SB), R12
565 MOVD R12, CTR
566 BL (CTR)
567 MOVD 24(R1), R2 // Should this be here? Where is it saved?
568 // Starts at 64; FIXED_FRAME is 32
569 MOVD 64(R1), R14
570 MOVD 72(R1), R15
571 MOVD 80(R1), R16
572 MOVD 88(R1), R17
573 MOVD 96(R1), R18
574 MOVD 104(R1), R19
575 MOVD 112(R1), R20
576 MOVD 120(R1), R21
577 MOVD 128(R1), R22
578 MOVD 136(R1), R23
579 MOVD 144(R1), R24
580 MOVD 152(R1), R25
581 MOVD 160(R1), R26
582 MOVD 168(R1), R27
583 MOVD 176(R1), R28
584 MOVD 184(R1), R29
585 MOVD 192(R1), g // R30
586 MOVD 200(R1), R31
587 FMOVD 208(R1), F14
588 FMOVD 216(R1), F15
589 FMOVD 224(R1), F16
590 FMOVD 232(R1), F17
591 FMOVD 240(R1), F18
592 FMOVD 248(R1), F19
593 FMOVD 256(R1), F20
594 FMOVD 264(R1), F21
595 FMOVD 272(R1), F22
596 FMOVD 280(R1), F23
597 FMOVD 288(R1), F24
598 FMOVD 292(R1), F25
599 FMOVD 300(R1), F26
600 FMOVD 308(R1), F27
601 FMOVD 316(R1), F28
602 FMOVD 328(R1), F29
603 FMOVD 336(R1), F30
604 FMOVD 344(R1), F31
605 MOVD $352, R7
606 LXVD2X (R7)(R1), VS52
607 ADD $16, R7 // 368 V21
608 LXVD2X (R7)(R1), VS53
609 ADD $16, R7 // 384 V22
610 LXVD2X (R7)(R1), VS54
611 ADD $16, R7 // 400 V23
612 LXVD2X (R7)(R1), VS55
613 ADD $16, R7 // 416 V24
614 LXVD2X (R7)(R1), VS56
615 ADD $16, R7 // 432 V25
616 LXVD2X (R7)(R1), VS57
617 ADD $16, R7 // 448 V26
618 LXVD2X (R7)(R1), VS58
619 ADD $16, R8 // 464 V27
620 LXVD2X (R7)(R1), VS59
621 ADD $16, R7 // 480 V28
622 LXVD2X (R7)(R1), VS60
623 ADD $16, R7 // 496 V29
624 LXVD2X (R7)(R1), VS61
625 ADD $16, R7 // 512 V30
626 LXVD2X (R7)(R1), VS62
627 ADD $16, R7 // 528 V31
628 LXVD2X (R7)(R1), VS63
629 ADD $544, R1
630 MOVD 8(R1), R0
631 MOVFL R0, $0xff
632 MOVD 16(R1), R0
633 MOVD R0, LR
634
635 RET
636
637 #ifdef GOARCH_ppc64le
638 // ppc64le doesn't need function descriptors
639 TEXT runtime·cgoSigtramp(SB),NOSPLIT|NOFRAME,$0
640 // The stack unwinder, presumably written in C, may not be able to
641 // handle Go frame correctly. So, this function is NOFRAME, and we
642 // save/restore LR manually.
643 MOVD LR, R10
644
645 // We're coming from C code, initialize essential registers.
646 CALL runtime·reginit(SB)
647
648 // If no traceback function, do usual sigtramp.
649 MOVD runtime·cgoTraceback(SB), R6
650 CMP $0, R6
651 BEQ sigtramp
652
653 // If no traceback support function, which means that
654 // runtime/cgo was not linked in, do usual sigtramp.
655 MOVD _cgo_callers(SB), R6
656 CMP $0, R6
657 BEQ sigtramp
658
659 // Set up g register.
660 CALL runtime·load_g(SB)
661
662 // Figure out if we are currently in a cgo call.
663 // If not, just do usual sigtramp.
664 // compared to ARM64 and others.
665 CMP $0, g
666 BEQ sigtrampnog // g == nil
667 MOVD g_m(g), R6
668 CMP $0, R6
669 BEQ sigtramp // g.m == nil
670 MOVW m_ncgo(R6), R7
671 CMPW $0, R7
672 BEQ sigtramp // g.m.ncgo = 0
673 MOVD m_curg(R6), R7
674 CMP $0, R7
675 BEQ sigtramp // g.m.curg == nil
676 MOVD g_syscallsp(R7), R7
677 CMP $0, R7
678 BEQ sigtramp // g.m.curg.syscallsp == 0
679 MOVD m_cgoCallers(R6), R7 // R7 is the fifth arg in C calling convention.
680 CMP $0, R7
681 BEQ sigtramp // g.m.cgoCallers == nil
682 MOVW m_cgoCallersUse(R6), R8
683 CMPW $0, R8
684 BNE sigtramp // g.m.cgoCallersUse != 0
685
686 // Jump to a function in runtime/cgo.
687 // That function, written in C, will call the user's traceback
688 // function with proper unwind info, and will then call back here.
689 // The first three arguments, and the fifth, are already in registers.
690 // Set the two remaining arguments now.
691 MOVD runtime·cgoTraceback(SB), R6
692 MOVD $runtime·sigtramp(SB), R8
693 MOVD _cgo_callers(SB), R12
694 MOVD R12, CTR
695 MOVD R10, LR // restore LR
696 JMP (CTR)
697
698 sigtramp:
699 MOVD R10, LR // restore LR
700 JMP runtime·sigtramp(SB)
701
702 sigtrampnog:
703 // Signal arrived on a non-Go thread. If this is SIGPROF, get a
704 // stack trace.
705 CMPW R3, $27 // 27 == SIGPROF
706 BNE sigtramp
707
708 // Lock sigprofCallersUse (cas from 0 to 1).
709 MOVW $1, R7
710 MOVD $runtime·sigprofCallersUse(SB), R8
711 SYNC
712 LWAR (R8), R6
713 CMPW $0, R6
714 BNE sigtramp
715 STWCCC R7, (R8)
716 BNE -4(PC)
717 ISYNC
718
719 // Jump to the traceback function in runtime/cgo.
720 // It will call back to sigprofNonGo, which will ignore the
721 // arguments passed in registers.
722 // First three arguments to traceback function are in registers already.
723 MOVD runtime·cgoTraceback(SB), R6
724 MOVD $runtime·sigprofCallers(SB), R7
725 MOVD $runtime·sigprofNonGoWrapper<>(SB), R8
726 MOVD _cgo_callers(SB), R12
727 MOVD R12, CTR
728 MOVD R10, LR // restore LR
729 JMP (CTR)
730 #else
731 // function descriptor for the real sigtramp
732 TEXT runtime·cgoSigtramp(SB),NOSPLIT|NOFRAME,$0
733 DWORD $cgoSigtramp<>(SB)
734 DWORD $0
735 DWORD $0
736 TEXT cgoSigtramp<>(SB),NOSPLIT,$0
737 JMP sigtramp<>(SB)
738 #endif
739
740 TEXT runtime·sigprofNonGoWrapper<>(SB),NOSPLIT,$0
741 // We're coming from C code, set up essential register, then call sigprofNonGo.
742 CALL runtime·reginit(SB)
743 MOVW R3, FIXED_FRAME+0(R1) // sig
744 MOVD R4, FIXED_FRAME+8(R1) // info
745 MOVD R5, FIXED_FRAME+16(R1) // ctx
746 CALL runtime·sigprofNonGo(SB)
747 RET
748
749 TEXT runtime·mmap(SB),NOSPLIT|NOFRAME,$0
750 MOVD addr+0(FP), R3
751 MOVD n+8(FP), R4
752 MOVW prot+16(FP), R5
753 MOVW flags+20(FP), R6
754 MOVW fd+24(FP), R7
755 MOVW off+28(FP), R8
756
757 SYSCALL $SYS_mmap
758 BVC ok
759 MOVD $0, p+32(FP)
760 MOVD R3, err+40(FP)
761 RET
762 ok:
763 MOVD R3, p+32(FP)
764 MOVD $0, err+40(FP)
765 RET
766
767 TEXT runtime·munmap(SB),NOSPLIT|NOFRAME,$0
768 MOVD addr+0(FP), R3
769 MOVD n+8(FP), R4
770 SYSCALL $SYS_munmap
771 BVC 2(PC)
772 MOVD R0, 0xf0(R0)
773 RET
774
775 TEXT runtime·madvise(SB),NOSPLIT|NOFRAME,$0
776 MOVD addr+0(FP), R3
777 MOVD n+8(FP), R4
778 MOVW flags+16(FP), R5
779 SYSCALL $SYS_madvise
780 MOVW R3, ret+24(FP)
781 RET
782
783 // int64 futex(int32 *uaddr, int32 op, int32 val,
784 // struct timespec *timeout, int32 *uaddr2, int32 val2);
785 TEXT runtime·futex(SB),NOSPLIT|NOFRAME,$0
786 MOVD addr+0(FP), R3
787 MOVW op+8(FP), R4
788 MOVW val+12(FP), R5
789 MOVD ts+16(FP), R6
790 MOVD addr2+24(FP), R7
791 MOVW val3+32(FP), R8
792 SYSCALL $SYS_futex
793 BVC 2(PC)
794 NEG R3 // caller expects negative errno
795 MOVW R3, ret+40(FP)
796 RET
797
798 // int64 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));
799 TEXT runtime·clone(SB),NOSPLIT|NOFRAME,$0
800 MOVW flags+0(FP), R3
801 MOVD stk+8(FP), R4
802
803 // Copy mp, gp, fn off parent stack for use by child.
804 // Careful: Linux system call clobbers ???.
805 MOVD mp+16(FP), R7
806 MOVD gp+24(FP), R8
807 MOVD fn+32(FP), R12
808
809 MOVD R7, -8(R4)
810 MOVD R8, -16(R4)
811 MOVD R12, -24(R4)
812 MOVD $1234, R7
813 MOVD R7, -32(R4)
814
815 SYSCALL $SYS_clone
816 BVC 2(PC)
817 NEG R3 // caller expects negative errno
818
819 // In parent, return.
820 CMP R3, $0
821 BEQ 3(PC)
822 MOVW R3, ret+40(FP)
823 RET
824
825 // In child, on new stack.
826 // initialize essential registers
827 BL runtime·reginit(SB)
828 MOVD -32(R1), R7
829 CMP R7, $1234
830 BEQ 2(PC)
831 MOVD R0, 0(R0)
832
833 // Initialize m->procid to Linux tid
834 SYSCALL $SYS_gettid
835
836 MOVD -24(R1), R12 // fn
837 MOVD -16(R1), R8 // g
838 MOVD -8(R1), R7 // m
839
840 CMP R7, $0
841 BEQ nog
842 CMP R8, $0
843 BEQ nog
844
845 MOVD R3, m_procid(R7)
846
847 // TODO: setup TLS.
848
849 // In child, set up new stack
850 MOVD R7, g_m(R8)
851 MOVD R8, g
852 //CALL runtime·stackcheck(SB)
853
854 nog:
855 // Call fn
856 MOVD R12, CTR
857 BL (CTR)
858
859 // It shouldn't return. If it does, exit that thread.
860 MOVW $111, R3
861 SYSCALL $SYS_exit
862 BR -2(PC) // keep exiting
863
864 TEXT runtime·sigaltstack(SB),NOSPLIT|NOFRAME,$0
865 MOVD new+0(FP), R3
866 MOVD old+8(FP), R4
867 SYSCALL $SYS_sigaltstack
868 BVC 2(PC)
869 MOVD R0, 0xf0(R0) // crash
870 RET
871
872 TEXT runtime·osyield(SB),NOSPLIT|NOFRAME,$0
873 SYSCALL $SYS_sched_yield
874 RET
875
876 TEXT runtime·sched_getaffinity(SB),NOSPLIT|NOFRAME,$0
877 MOVD pid+0(FP), R3
878 MOVD len+8(FP), R4
879 MOVD buf+16(FP), R5
880 SYSCALL $SYS_sched_getaffinity
881 BVC 2(PC)
882 NEG R3 // caller expects negative errno
883 MOVW R3, ret+24(FP)
884 RET
885
886 // int32 runtime·epollcreate(int32 size);
887 TEXT runtime·epollcreate(SB),NOSPLIT|NOFRAME,$0
888 MOVW size+0(FP), R3
889 SYSCALL $SYS_epoll_create
890 BVC 2(PC)
891 NEG R3 // caller expects negative errno
892 MOVW R3, ret+8(FP)
893 RET
894
895 // int32 runtime·epollcreate1(int32 flags);
896 TEXT runtime·epollcreate1(SB),NOSPLIT|NOFRAME,$0
897 MOVW flags+0(FP), R3
898 SYSCALL $SYS_epoll_create1
899 BVC 2(PC)
900 NEG R3 // caller expects negative errno
901 MOVW R3, ret+8(FP)
902 RET
903
904 // func epollctl(epfd, op, fd int32, ev *epollEvent) int
905 TEXT runtime·epollctl(SB),NOSPLIT|NOFRAME,$0
906 MOVW epfd+0(FP), R3
907 MOVW op+4(FP), R4
908 MOVW fd+8(FP), R5
909 MOVD ev+16(FP), R6
910 SYSCALL $SYS_epoll_ctl
911 NEG R3 // caller expects negative errno
912 MOVW R3, ret+24(FP)
913 RET
914
915 // int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout);
916 TEXT runtime·epollwait(SB),NOSPLIT|NOFRAME,$0
917 MOVW epfd+0(FP), R3
918 MOVD ev+8(FP), R4
919 MOVW nev+16(FP), R5
920 MOVW timeout+20(FP), R6
921 SYSCALL $SYS_epoll_wait
922 BVC 2(PC)
923 NEG R3 // caller expects negative errno
924 MOVW R3, ret+24(FP)
925 RET
926
927 // void runtime·closeonexec(int32 fd);
928 TEXT runtime·closeonexec(SB),NOSPLIT|NOFRAME,$0
929 MOVW fd+0(FP), R3 // fd
930 MOVD $2, R4 // F_SETFD
931 MOVD $1, R5 // FD_CLOEXEC
932 SYSCALL $SYS_fcntl
933 RET
934
935 // func sbrk0() uintptr
936 TEXT runtime·sbrk0(SB),NOSPLIT|NOFRAME,$0
937 // Implemented as brk(NULL).
938 MOVD $0, R3
939 SYSCALL $SYS_brk
940 MOVD R3, ret+0(FP)
941 RET
942
943 TEXT runtime·access(SB),$0-20
944 MOVD R0, 0(R0) // unimplemented, only needed for android; declared in stubs_linux.go
945 MOVW R0, ret+16(FP) // for vet
946 RET
947
948 TEXT runtime·connect(SB),$0-28
949 MOVD R0, 0(R0) // unimplemented, only needed for android; declared in stubs_linux.go
950 MOVW R0, ret+24(FP) // for vet
951 RET
952
953 TEXT runtime·socket(SB),$0-20
954 MOVD R0, 0(R0) // unimplemented, only needed for android; declared in stubs_linux.go
955 MOVW R0, ret+16(FP) // for vet
956 RET
957
View as plain text