Text file src/runtime/sys_darwin_arm.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 // System calls and other sys.stuff for ARM, Darwin
6 // System calls are implemented in libSystem, this file contains
7 // trampolines that convert from Go to C calling convention.
8
9 #include "go_asm.h"
10 #include "go_tls.h"
11 #include "textflag.h"
12
13 TEXT notok<>(SB),NOSPLIT,$0
14 MOVW $0, R8
15 MOVW R8, (R8)
16 B 0(PC)
17
18 TEXT runtime·open_trampoline(SB),NOSPLIT,$0
19 MOVW 4(R0), R1 // arg 2 mode
20 MOVW 8(R0), R2 // arg 3 perm
21 MOVW 0(R0), R0 // arg 1 name
22 BL libc_open(SB)
23 RET
24
25 TEXT runtime·close_trampoline(SB),NOSPLIT,$0
26 MOVW 0(R0), R0 // arg 1 fd
27 BL libc_close(SB)
28 RET
29
30 TEXT runtime·write_trampoline(SB),NOSPLIT,$0
31 MOVW 4(R0), R1 // arg 2 buf
32 MOVW 8(R0), R2 // arg 3 count
33 MOVW 0(R0), R0 // arg 1 fd
34 BL libc_write(SB)
35 RET
36
37 TEXT runtime·read_trampoline(SB),NOSPLIT,$0
38 MOVW 4(R0), R1 // arg 2 buf
39 MOVW 8(R0), R2 // arg 3 count
40 MOVW 0(R0), R0 // arg 1 fd
41 BL libc_read(SB)
42 RET
43
44 TEXT runtime·pipe_trampoline(SB),NOSPLIT,$0
45 BL libc_pipe(SB) // pointer already in R0
46 CMP $0, R0
47 BEQ 3(PC)
48 BL libc_error(SB) // return negative errno value
49 RSB $0, R0, R0
50 RET
51
52 TEXT runtime·exit_trampoline(SB),NOSPLIT|NOFRAME,$0
53 MOVW 0(R0), R0 // arg 0 code
54 BL libc_exit(SB)
55 MOVW $1234, R0
56 MOVW $1002, R1
57 MOVW R0, (R1) // fail hard
58
59 TEXT runtime·raiseproc_trampoline(SB),NOSPLIT,$0
60 MOVW 0(R0), R8 // signal
61 BL libc_getpid(SB)
62 // arg 1 pid already in R0 from getpid
63 MOVW R8, R1 // arg 2 signal
64 BL libc_kill(SB)
65 RET
66
67 TEXT runtime·mmap_trampoline(SB),NOSPLIT,$0
68 MOVW R0, R8
69 MOVW 0(R8), R0 // arg 1 addr
70 MOVW 4(R8), R1 // arg 2 len
71 MOVW 8(R8), R2 // arg 3 prot
72 MOVW 12(R8), R3 // arg 4 flags
73 MOVW 16(R8), R4 // arg 5 fid
74 MOVW 20(R8), R5 // arg 6 offset
75 MOVW $0, R6 // off_t is uint64_t
76 // Only R0-R3 are used for arguments, the rest
77 // go on the stack.
78 MOVM.DB.W [R4-R6], (R13)
79 BL libc_mmap(SB)
80 ADD $12, R13
81 MOVW $0, R1
82 MOVW $-1, R2
83 CMP R0, R2
84 BNE ok
85 BL libc_error(SB)
86 MOVW (R0), R1
87 MOVW $0, R0
88 ok:
89 MOVW R0, 24(R8) // ret 1 addr
90 MOVW R1, 28(R8) // ret 2 err
91 RET
92
93 TEXT runtime·munmap_trampoline(SB),NOSPLIT,$0
94 MOVW 4(R0), R1 // arg 2 len
95 MOVW 0(R0), R0 // arg 1 addr
96 BL libc_munmap(SB)
97 MOVW $-1, R2
98 CMP R0, R2
99 BL.EQ notok<>(SB)
100 RET
101
102 TEXT runtime·madvise_trampoline(SB),NOSPLIT,$0
103 MOVW 4(R0), R1 // arg 2 len
104 MOVW 8(R0), R2 // arg 3 advice
105 MOVW 0(R0), R0 // arg 1 addr
106 BL libc_madvise(SB)
107 MOVW $-1, R2
108 CMP R0, R2
109 BL.EQ notok<>(SB)
110 RET
111
112 TEXT runtime·setitimer_trampoline(SB),NOSPLIT,$0
113 MOVW 4(R0), R1 // arg 2 new
114 MOVW 8(R0), R2 // arg 3 old
115 MOVW 0(R0), R0 // arg 1 which
116 BL libc_setitimer(SB)
117 RET
118
119 TEXT runtime·walltime_trampoline(SB),NOSPLIT,$0
120 // R0 already has *timeval
121 MOVW $0, R1 // no timezone needed
122 BL libc_gettimeofday(SB)
123 RET
124
125 GLOBL timebase<>(SB),NOPTR,$(machTimebaseInfo__size)
126
127 TEXT runtime·nanotime_trampoline(SB),NOSPLIT,$0
128 MOVW R0, R8
129 BL libc_mach_absolute_time(SB)
130 MOVW R0, 0(R8)
131 MOVW R1, 4(R8)
132 MOVW timebase<>+machTimebaseInfo_numer(SB), R6
133 MOVW $timebase<>+machTimebaseInfo_denom(SB), R5
134 MOVW (R5), R7
135 DMB MB_ISH // memory barrier for atomic read
136 CMP $0, R7
137 BNE initialized
138
139 SUB $(machTimebaseInfo__size+7)/8*8, R13
140 MOVW R13, R0
141 BL libc_mach_timebase_info(SB)
142 MOVW machTimebaseInfo_numer(R13), R6
143 MOVW machTimebaseInfo_denom(R13), R7
144 ADD $(machTimebaseInfo__size+7)/8*8, R13
145
146 MOVW R6, timebase<>+machTimebaseInfo_numer(SB)
147 MOVW $timebase<>+machTimebaseInfo_denom(SB), R5
148 DMB MB_ISH // memory barrier for atomic write
149 MOVW R7, (R5)
150 DMB MB_ISH
151
152 initialized:
153 MOVW R6, 8(R8)
154 MOVW R7, 12(R8)
155 RET
156
157 TEXT runtime·sigfwd(SB),NOSPLIT,$0-16
158 MOVW sig+4(FP), R0
159 MOVW info+8(FP), R1
160 MOVW ctx+12(FP), R2
161 MOVW fn+0(FP), R11
162 MOVW R13, R4
163 SUB $24, R13
164 BIC $0x7, R13 // alignment for ELF ABI
165 BL (R11)
166 MOVW R4, R13
167 RET
168
169 TEXT runtime·sigtramp(SB),NOSPLIT,$0
170 // Reserve space for callee-save registers and arguments.
171 SUB $40, R13
172
173 MOVW R4, 16(R13)
174 MOVW R5, 20(R13)
175 MOVW R6, 24(R13)
176 MOVW R7, 28(R13)
177 MOVW R8, 32(R13)
178 MOVW R11, 36(R13)
179
180 // Save arguments.
181 MOVW R0, 4(R13) // sig
182 MOVW R1, 8(R13) // info
183 MOVW R2, 12(R13) // ctx
184
185 // this might be called in external code context,
186 // where g is not set.
187 MOVB runtime·iscgo(SB), R0
188 CMP $0, R0
189 BL.NE runtime·load_g(SB)
190
191 MOVW R13, R6
192 CMP $0, g
193 BEQ nog
194
195 // iOS always use the main stack to run the signal handler.
196 // We need to switch to gsignal ourselves.
197 MOVW g_m(g), R11
198 MOVW m_gsignal(R11), R5
199 MOVW (g_stack+stack_hi)(R5), R6
200
201 nog:
202 // Restore arguments.
203 MOVW 4(R13), R0
204 MOVW 8(R13), R1
205 MOVW 12(R13), R2
206
207 // Reserve space for args and the stack pointer on the
208 // gsignal stack.
209 SUB $24, R6
210 // Save stack pointer.
211 MOVW R13, R4
212 MOVW R4, 16(R6)
213 // Switch to gsignal stack.
214 MOVW R6, R13
215
216 // Call sigtrampgo
217 MOVW R0, 4(R13)
218 MOVW R1, 8(R13)
219 MOVW R2, 12(R13)
220 BL runtime·sigtrampgo(SB)
221
222 // Switch to old stack.
223 MOVW 16(R13), R5
224 MOVW R5, R13
225
226 // Restore callee-save registers.
227 MOVW 16(R13), R4
228 MOVW 20(R13), R5
229 MOVW 24(R13), R6
230 MOVW 28(R13), R7
231 MOVW 32(R13), R8
232 MOVW 36(R13), R11
233
234 ADD $40, R13
235
236 RET
237
238 TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0
239 JMP runtime·sigtramp(SB)
240
241 TEXT runtime·sigprocmask_trampoline(SB),NOSPLIT,$0
242 MOVW 4(R0), R1 // arg 2 new
243 MOVW 8(R0), R2 // arg 3 old
244 MOVW 0(R0), R0 // arg 1 how
245 BL libc_pthread_sigmask(SB)
246 CMP $0, R0
247 BL.NE notok<>(SB)
248 RET
249
250 TEXT runtime·sigaction_trampoline(SB),NOSPLIT,$0
251 MOVW 4(R0), R1 // arg 2 new
252 MOVW 8(R0), R2 // arg 3 old
253 MOVW 0(R0), R0 // arg 1 how
254 BL libc_sigaction(SB)
255 RET
256
257 TEXT runtime·usleep_trampoline(SB),NOSPLIT,$0
258 MOVW 0(R0), R0 // arg 1 usec
259 BL libc_usleep(SB)
260 RET
261
262 TEXT ·publicationBarrier(SB),NOSPLIT|NOFRAME,$0-0
263 B runtime·armPublicationBarrier(SB)
264
265 TEXT runtime·sysctl_trampoline(SB),NOSPLIT,$0
266 MOVW 4(R0), R1 // arg 2 miblen
267 MOVW 8(R0), R2 // arg 3 out
268 MOVW 12(R0), R3 // arg 4 size
269 MOVW 16(R0), R4 // arg 5 dst
270 MOVW 20(R0), R5 // arg 6 ndst
271 MOVW 0(R0), R0 // arg 1 mib
272 // Only R0-R3 are used for arguments, the rest
273 // go on the stack.
274 MOVM.DB.W [R4-R5], (R13)
275 BL libc_sysctl(SB)
276 ADD $(2*4), R13
277 RET
278
279 TEXT runtime·kqueue_trampoline(SB),NOSPLIT,$0
280 BL libc_kqueue(SB)
281 RET
282
283 // int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int events, Timespec *timeout)
284 TEXT runtime·kevent_trampoline(SB),NOSPLIT,$0
285 MOVW 4(R0), R1 // arg 2 keventss
286 MOVW 8(R0), R2 // arg 3 nch
287 MOVW 12(R0), R3 // arg 4 ev
288 MOVW 16(R0), R4 // arg 5 nev
289 MOVW 20(R0), R5 // arg 6 ts
290 MOVW 0(R0), R0 // arg 1 kq
291 // Only R0-R3 are used for arguments, the rest
292 // go on the stack.
293 MOVM.DB.W [R4-R5], (R13)
294 BL libc_kevent(SB)
295 ADD $(2*4), R13
296 MOVW $-1, R2
297 CMP R0, R2
298 BNE ok
299 BL libc_error(SB)
300 MOVW (R0), R0 // errno
301 RSB $0, R0, R0 // caller wants it as a negative error code
302 ok:
303 RET
304
305 TEXT runtime·fcntl_trampoline(SB),NOSPLIT,$0
306 MOVW 4(R0), R1 // arg 2 cmd
307 MOVW 8(R0), R2 // arg 3 arg
308 MOVW 0(R0), R0 // arg 1 fd
309 BL libc_fcntl(SB)
310 RET
311
312 // sigaltstack is not supported on iOS, so our sigtramp has
313 // to do the stack switch ourselves.
314 TEXT runtime·sigaltstack_trampoline(SB),NOSPLIT,$0
315 MOVW $43, R0
316 BL libc_exit(SB)
317 RET
318
319 // Thread related functions
320 // Note: On darwin/arm, the runtime always use runtime/cgo to
321 // create threads, so all thread related functions will just exit with a
322 // unique status.
323
324 TEXT runtime·mstart_stub(SB),NOSPLIT,$0
325 MOVW $44, R0
326 BL libc_exit(SB)
327 RET
328
329 TEXT runtime·pthread_attr_init_trampoline(SB),NOSPLIT,$0
330 MOVW $45, R0
331 BL libc_exit(SB)
332 RET
333
334 TEXT runtime·pthread_attr_getstacksize_trampoline(SB),NOSPLIT,$0
335 MOVW $46, R0
336 BL libc_exit(SB)
337 RET
338
339 TEXT runtime·pthread_attr_setdetachstate_trampoline(SB),NOSPLIT,$0
340 MOVW $47, R0
341 BL libc_exit(SB)
342 RET
343
344 TEXT runtime·pthread_create_trampoline(SB),NOSPLIT,$0
345 MOVW $48, R0
346 BL libc_exit(SB)
347 RET
348
349 TEXT runtime·raise_trampoline(SB),NOSPLIT,$0
350 MOVW 0(R0), R0 // arg 1 sig
351 BL libc_raise(SB)
352 RET
353
354 TEXT runtime·pthread_mutex_init_trampoline(SB),NOSPLIT,$0
355 MOVW 4(R0), R1 // arg 2 attr
356 MOVW 0(R0), R0 // arg 1 mutex
357 BL libc_pthread_mutex_init(SB)
358 RET
359
360 TEXT runtime·pthread_mutex_lock_trampoline(SB),NOSPLIT,$0
361 MOVW 0(R0), R0 // arg 1 mutex
362 BL libc_pthread_mutex_lock(SB)
363 RET
364
365 TEXT runtime·pthread_mutex_unlock_trampoline(SB),NOSPLIT,$0
366 MOVW 0(R0), R0 // arg 1 mutex
367 BL libc_pthread_mutex_unlock(SB)
368 RET
369
370 TEXT runtime·pthread_cond_init_trampoline(SB),NOSPLIT,$0
371 MOVW 4(R0), R1 // arg 2 attr
372 MOVW 0(R0), R0 // arg 1 cond
373 BL libc_pthread_cond_init(SB)
374 RET
375
376 TEXT runtime·pthread_cond_wait_trampoline(SB),NOSPLIT,$0
377 MOVW 4(R0), R1 // arg 2 mutex
378 MOVW 0(R0), R0 // arg 1 cond
379 BL libc_pthread_cond_wait(SB)
380 RET
381
382 TEXT runtime·pthread_cond_timedwait_relative_np_trampoline(SB),NOSPLIT,$0
383 MOVW 4(R0), R1 // arg 2 mutex
384 MOVW 8(R0), R2 // arg 3 timeout
385 MOVW 0(R0), R0 // arg 1 cond
386 BL libc_pthread_cond_timedwait_relative_np(SB)
387 RET
388
389 TEXT runtime·pthread_cond_signal_trampoline(SB),NOSPLIT,$0
390 MOVW 0(R0), R0 // arg 1 cond
391 BL libc_pthread_cond_signal(SB)
392 RET
393
394 // syscall calls a function in libc on behalf of the syscall package.
395 // syscall takes a pointer to a struct like:
396 // struct {
397 // fn uintptr
398 // a1 uintptr
399 // a2 uintptr
400 // a3 uintptr
401 // r1 uintptr
402 // r2 uintptr
403 // err uintptr
404 // }
405 // syscall must be called on the g0 stack with the
406 // C calling convention (use libcCall).
407 TEXT runtime·syscall(SB),NOSPLIT,$0
408 MOVW.W R0, -4(R13) // push structure pointer
409 MOVW 0(R0), R12 // fn
410 MOVW 8(R0), R1 // a2
411 MOVW 12(R0), R2 // a3
412 MOVW 4(R0), R0 // a1
413 BL (R12)
414 MOVW.P 4(R13), R2 // pop structure pointer
415 MOVW R0, 16(R2) // save r1
416 MOVW R1, 20(R2) // save r2
417 MOVW $-1, R3
418 CMP R0, R3
419 BNE ok
420 MOVW.W R2, -4(R13) // push structure pointer
421 BL libc_error(SB)
422 MOVW (R0), R0
423 MOVW.P 4(R13), R2 // pop structure pointer
424 MOVW R0, 24(R2) // save err
425 ok:
426 RET
427
428 // syscallPtr is like syscall except the libc function reports an
429 // error by returning NULL and setting errno.
430 TEXT runtime·syscallPtr(SB),NOSPLIT,$0
431 MOVW.W R0, -4(R13) // push structure pointer
432 MOVW 0(R0), R12 // fn
433 MOVW 8(R0), R1 // a2
434 MOVW 12(R0), R2 // a3
435 MOVW 4(R0), R0 // a1
436 BL (R12)
437 MOVW.P 4(R13), R2 // pop structure pointer
438 MOVW R0, 16(R2) // save r1
439 MOVW R1, 20(R2) // save r2
440 MOVW $0, R3
441 CMP R0, R3
442 BNE ok
443 MOVW.W R2, -4(R13) // push structure pointer
444 BL libc_error(SB)
445 MOVW (R0), R0
446 MOVW.P 4(R13), R2 // pop structure pointer
447 MOVW R0, 24(R2) // save err
448 ok:
449 RET
450
451 // syscall6 calls a function in libc on behalf of the syscall package.
452 // syscall6 takes a pointer to a struct like:
453 // struct {
454 // fn uintptr
455 // a1 uintptr
456 // a2 uintptr
457 // a3 uintptr
458 // a4 uintptr
459 // a5 uintptr
460 // a6 uintptr
461 // r1 uintptr
462 // r2 uintptr
463 // err uintptr
464 // }
465 // syscall6 must be called on the g0 stack with the
466 // C calling convention (use libcCall).
467 TEXT runtime·syscall6(SB),NOSPLIT,$0
468 MOVW.W R0, -4(R13) // push structure pointer
469 MOVW 0(R0), R12 // fn
470 MOVW 24(R0), R1 // a6
471 MOVW.W R1, -4(R13)
472 MOVW 20(R0), R1 // a5
473 MOVW.W R1, -4(R13)
474 MOVW 8(R0), R1 // a2
475 MOVW 12(R0), R2 // a3
476 MOVW 16(R0), R3 // a4
477 MOVW 4(R0), R0 // a1
478 BL (R12)
479 ADD $8, R13
480 MOVW.P 4(R13), R2 // pop structure pointer
481 MOVW R0, 28(R2) // save r1
482 MOVW R1, 32(R2) // save r2
483 MOVW $-1, R3
484 CMP R0, R3
485 BNE ok
486 MOVW.W R2, -4(R13) // push structure pointer
487 BL libc_error(SB)
488 MOVW (R0), R0
489 MOVW.P 4(R13), R2 // pop structure pointer
490 MOVW R0, 36(R2) // save err
491 ok:
492 RET
493
494 // syscall6X calls a function in libc on behalf of the syscall package.
495 // syscall6X takes a pointer to a struct like:
496 // struct {
497 // fn uintptr
498 // a1 uintptr
499 // a2 uintptr
500 // a3 uintptr
501 // a4 uintptr
502 // a5 uintptr
503 // a6 uintptr
504 // r1 uintptr
505 // r2 uintptr
506 // err uintptr
507 // }
508 // syscall6X must be called on the g0 stack with the
509 // C calling convention (use libcCall).
510 TEXT runtime·syscall6X(SB),NOSPLIT,$0
511 MOVW.W R0, -4(R13) // push structure pointer
512 MOVW 0(R0), R12 // fn
513 MOVW 24(R0), R1 // a6
514 MOVW.W R1, -4(R13)
515 MOVW 20(R0), R1 // a5
516 MOVW.W R1, -4(R13)
517 MOVW 8(R0), R1 // a2
518 MOVW 12(R0), R2 // a3
519 MOVW 16(R0), R3 // a4
520 MOVW 4(R0), R0 // a1
521 BL (R12)
522 ADD $8, R13
523 MOVW.P 4(R13), R2 // pop structure pointer
524 MOVW R0, 28(R2) // save r1
525 MOVW R1, 32(R2) // save r2
526 MOVW $-1, R3
527 CMP R0, R3
528 BNE ok
529 CMP R1, R3
530 BNE ok
531 MOVW.W R2, -4(R13) // push structure pointer
532 BL libc_error(SB)
533 MOVW (R0), R0
534 MOVW.P 4(R13), R2 // pop structure pointer
535 MOVW R0, 36(R2) // save err
536 ok:
537 RET
538
539 // syscall9 calls a function in libc on behalf of the syscall package.
540 // syscall9 takes a pointer to a struct like:
541 // struct {
542 // fn uintptr
543 // a1 uintptr
544 // a2 uintptr
545 // a3 uintptr
546 // a4 uintptr
547 // a5 uintptr
548 // a6 uintptr
549 // a7 uintptr
550 // a8 uintptr
551 // a9 uintptr
552 // r1 uintptr
553 // r2 uintptr
554 // err uintptr
555 // }
556 // syscall9 must be called on the g0 stack with the
557 // C calling convention (use libcCall).
558 TEXT runtime·syscall9(SB),NOSPLIT,$0
559 MOVW.W R0, -4(R13) // push structure pointer
560 MOVW 0(R0), R12 // fn
561 MOVW 36(R0), R1 // a9
562 MOVW.W R1, -4(R13)
563 MOVW 32(R0), R1 // a8
564 MOVW.W R1, -4(R13)
565 MOVW 28(R0), R1 // a7
566 MOVW.W R1, -4(R13)
567 MOVW 24(R0), R1 // a6
568 MOVW.W R1, -4(R13)
569 MOVW 20(R0), R1 // a5
570 MOVW.W R1, -4(R13)
571 MOVW 8(R0), R1 // a2
572 MOVW 12(R0), R2 // a3
573 MOVW 16(R0), R3 // a4
574 MOVW 4(R0), R0 // a1
575 BL (R12)
576 ADD $20, R13
577 MOVW.P 4(R13), R2 // pop structure pointer
578 MOVW R0, 40(R2) // save r1
579 MOVW R1, 44(R2) // save r2
580 MOVW $-1, R3
581 CMP R0, R3
582 BNE ok
583 MOVW.W R2, -4(R13) // push structure pointer
584 BL libc_error(SB)
585 MOVW (R0), R0
586 MOVW.P 4(R13), R2 // pop structure pointer
587 MOVW R0, 48(R2) // save err
588 ok:
589 RET
View as plain text