github.com/hlts2/go@v0.0.0-20170904000733-812b34efaed8/src/runtime/sys_darwin_arm.s (about) 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 // See http://fxr.watson.org/fxr/source/bsd/kern/syscalls.c?v=xnu-1228 7 // or /usr/include/sys/syscall.h (on a Mac) for system call numbers. 8 9 #include "go_asm.h" 10 #include "go_tls.h" 11 #include "textflag.h" 12 13 // Copied from /usr/include/sys/syscall.h 14 #define SYS_exit 1 15 #define SYS_read 3 16 #define SYS_write 4 17 #define SYS_open 5 18 #define SYS_close 6 19 #define SYS_mmap 197 20 #define SYS_munmap 73 21 #define SYS_madvise 75 22 #define SYS_gettimeofday 116 23 #define SYS_kill 37 24 #define SYS_getpid 20 25 #define SYS___pthread_kill 328 26 #define SYS_pthread_sigmask 329 27 #define SYS_setitimer 83 28 #define SYS___sysctl 202 29 #define SYS_sigaction 46 30 #define SYS_sigreturn 184 31 #define SYS_select 93 32 #define SYS_bsdthread_register 366 33 #define SYS_bsdthread_create 360 34 #define SYS_bsdthread_terminate 361 35 #define SYS_kqueue 362 36 #define SYS_kevent 363 37 #define SYS_fcntl 92 38 39 TEXT notok<>(SB),NOSPLIT,$0 40 MOVW $0, R8 41 MOVW R8, (R8) 42 B 0(PC) 43 44 TEXT runtime·open(SB),NOSPLIT,$0 45 MOVW name+0(FP), R0 46 MOVW mode+4(FP), R1 47 MOVW perm+8(FP), R2 48 MOVW $SYS_open, R12 49 SWI $0x80 50 MOVW.CS $-1, R0 51 MOVW R0, ret+12(FP) 52 RET 53 54 TEXT runtime·closefd(SB),NOSPLIT,$0 55 MOVW fd+0(FP), R0 56 MOVW $SYS_close, R12 57 SWI $0x80 58 MOVW.CS $-1, R0 59 MOVW R0, ret+4(FP) 60 RET 61 62 TEXT runtime·write(SB),NOSPLIT,$0 63 MOVW fd+0(FP), R0 64 MOVW p+4(FP), R1 65 MOVW n+8(FP), R2 66 MOVW $SYS_write, R12 67 SWI $0x80 68 MOVW.CS $-1, R0 69 MOVW R0, ret+12(FP) 70 RET 71 72 TEXT runtime·read(SB),NOSPLIT,$0 73 MOVW fd+0(FP), R0 74 MOVW p+4(FP), R1 75 MOVW n+8(FP), R2 76 MOVW $SYS_read, R12 77 SWI $0x80 78 MOVW.CS $-1, R0 79 MOVW R0, ret+12(FP) 80 RET 81 82 TEXT runtime·exit(SB),NOSPLIT,$-4 83 MOVW code+0(FP), R0 84 MOVW $SYS_exit, R12 85 SWI $0x80 86 MOVW $1234, R0 87 MOVW $1002, R1 88 MOVW R0, (R1) // fail hard 89 90 // Exit this OS thread (like pthread_exit, which eventually 91 // calls __bsdthread_terminate). 92 TEXT runtime·exit1(SB),NOSPLIT,$0 93 MOVW $SYS_bsdthread_terminate, R12 94 SWI $0x80 95 MOVW $1234, R0 96 MOVW $1003, R1 97 MOVW R0, (R1) // fail hard 98 99 TEXT runtime·raise(SB),NOSPLIT,$0 100 // Ideally we'd send the signal to the current thread, 101 // not the whole process, but that's too hard on OS X. 102 JMP runtime·raiseproc(SB) 103 104 TEXT runtime·raiseproc(SB),NOSPLIT,$24 105 MOVW $SYS_getpid, R12 106 SWI $0x80 107 // arg 1 pid already in R0 from getpid 108 MOVW sig+0(FP), R1 // arg 2 - signal 109 MOVW $1, R2 // arg 3 - posix 110 MOVW $SYS_kill, R12 111 SWI $0x80 112 RET 113 114 TEXT runtime·mmap(SB),NOSPLIT,$0 115 MOVW addr+0(FP), R0 116 MOVW n+4(FP), R1 117 MOVW prot+8(FP), R2 118 MOVW flags+12(FP), R3 119 MOVW fd+16(FP), R4 120 MOVW off+20(FP), R5 121 MOVW $0, R6 // off_t is uint64_t 122 MOVW $SYS_mmap, R12 123 SWI $0x80 124 MOVW R0, ret+24(FP) 125 RET 126 127 TEXT runtime·munmap(SB),NOSPLIT,$0 128 MOVW addr+0(FP), R0 129 MOVW n+4(FP), R1 130 MOVW $SYS_munmap, R12 131 SWI $0x80 132 BL.CS notok<>(SB) 133 RET 134 135 TEXT runtime·madvise(SB),NOSPLIT,$0 136 MOVW addr+0(FP), R0 137 MOVW n+4(FP), R1 138 MOVW flags+8(FP), R2 139 MOVW $SYS_madvise, R12 140 SWI $0x80 141 BL.CS notok<>(SB) 142 RET 143 144 TEXT runtime·setitimer(SB),NOSPLIT,$0 145 MOVW mode+0(FP), R0 146 MOVW new+4(FP), R1 147 MOVW old+8(FP), R2 148 MOVW $SYS_setitimer, R12 149 SWI $0x80 150 RET 151 152 TEXT runtime·walltime(SB), 7, $32 153 MOVW $8(R13), R0 // timeval 154 MOVW $0, R1 // zone 155 MOVW $0, R2 // see issue 16570 156 MOVW $SYS_gettimeofday, R12 157 SWI $0x80 // Note: R0 is tv_sec, R1 is tv_usec 158 CMP $0, R0 159 BNE inreg 160 MOVW 8(R13), R0 161 MOVW 12(R13), R1 162 inreg: 163 MOVW R1, R2 // usec 164 MOVW R0, sec_lo+0(FP) 165 MOVW $0, R1 166 MOVW R1, sec_hi+4(FP) 167 MOVW $1000, R3 168 MUL R3, R2 169 MOVW R2, nsec+8(FP) 170 RET 171 172 TEXT runtime·nanotime(SB),NOSPLIT,$32 173 MOVW $8(R13), R0 // timeval 174 MOVW $0, R1 // zone 175 MOVW $0, R2 // see issue 16570 176 MOVW $SYS_gettimeofday, R12 177 SWI $0x80 // Note: R0 is tv_sec, R1 is tv_usec 178 CMP $0, R0 179 BNE inreg 180 MOVW 8(R13), R0 181 MOVW 12(R13), R1 182 inreg: 183 MOVW R1, R2 184 MOVW $1000000000, R3 185 MULLU R0, R3, (R1, R0) 186 MOVW $1000, R3 187 MOVW $0, R4 188 MUL R3, R2 189 ADD.S R2, R0 190 ADC R4, R1 191 192 MOVW R0, ret_lo+0(FP) 193 MOVW R1, ret_hi+4(FP) 194 RET 195 196 TEXT runtime·sigfwd(SB),NOSPLIT,$0-16 197 MOVW sig+4(FP), R0 198 MOVW info+8(FP), R1 199 MOVW ctx+12(FP), R2 200 MOVW fn+0(FP), R11 201 MOVW R13, R4 202 SUB $24, R13 203 BIC $0x7, R13 // alignment for ELF ABI 204 BL (R11) 205 MOVW R4, R13 206 RET 207 208 // Sigtramp's job is to call the actual signal handler. 209 // It is called with the following arguments on the stack: 210 // LR "return address" - ignored 211 // R0 actual handler 212 // R1 siginfo style - ignored 213 // R2 signal number 214 // R3 siginfo 215 // -4(FP) context, beware that 0(FP) is the saved LR 216 TEXT runtime·sigtramp(SB),NOSPLIT,$0 217 // this might be called in external code context, 218 // where g is not set. 219 // first save R0, because runtime·load_g will clobber it 220 MOVM.DB.W [R0], (R13) 221 MOVB runtime·iscgo(SB), R0 222 CMP $0, R0 223 BL.NE runtime·load_g(SB) 224 225 CMP $0, g 226 BNE cont 227 // fake function call stack frame for badsignal 228 // we only need to pass R2 (signal number), but 229 // badsignal will expect R2 at 4(R13), so we also 230 // push R1 onto stack. turns out we do need R1 231 // to do sigreturn. 232 MOVM.DB.W [R1,R2], (R13) 233 MOVW $runtime·badsignal(SB), R11 234 BL (R11) 235 MOVM.IA.W [R1], (R13) // saved infostype 236 ADD $(4+4), R13 // +4: also need to remove the pushed R0. 237 MOVW ucontext-4(FP), R0 // load ucontext 238 B ret 239 240 cont: 241 // Restore R0 242 MOVM.IA.W (R13), [R0] 243 244 // NOTE: some Darwin/ARM kernels always use the main stack to run the 245 // signal handler. We need to switch to gsignal ourselves. 246 MOVW g_m(g), R11 247 MOVW m_gsignal(R11), R5 248 MOVW (g_stack+stack_hi)(R5), R6 249 SUB $28, R6 250 251 // copy arguments for call to sighandler 252 MOVW R2, 4(R6) // signal num 253 MOVW R3, 8(R6) // signal info 254 MOVW g, 16(R6) // old_g 255 MOVW context-4(FP), R4 256 MOVW R4, 12(R6) // context 257 258 // Backup ucontext and infostyle 259 MOVW R4, 20(R6) 260 MOVW R1, 24(R6) 261 262 // switch stack and g 263 MOVW R6, R13 // sigtramp is not re-entrant, so no need to back up R13. 264 MOVW R5, g 265 266 BL (R0) 267 268 // call sigreturn 269 MOVW 20(R13), R0 // saved ucontext 270 MOVW 24(R13), R1 // saved infostyle 271 ret: 272 MOVW $SYS_sigreturn, R12 // sigreturn(ucontext, infostyle) 273 SWI $0x80 274 275 // if sigreturn fails, we can do nothing but exit 276 B runtime·exit(SB) 277 278 TEXT runtime·sigprocmask(SB),NOSPLIT,$0 279 MOVW how+0(FP), R0 280 MOVW new+4(FP), R1 281 MOVW old+8(FP), R2 282 MOVW $SYS_pthread_sigmask, R12 283 SWI $0x80 284 BL.CS notok<>(SB) 285 RET 286 287 TEXT runtime·sigaction(SB),NOSPLIT,$0 288 MOVW mode+0(FP), R0 289 MOVW new+4(FP), R1 290 MOVW old+8(FP), R2 291 MOVW $SYS_sigaction, R12 292 SWI $0x80 293 RET 294 295 TEXT runtime·usleep(SB),NOSPLIT,$12 296 MOVW usec+0(FP), R0 297 CALL runtime·usplitR0(SB) 298 MOVW R0, a-12(SP) 299 MOVW R1, b-8(SP) 300 301 // select(0, 0, 0, 0, &tv) 302 MOVW $0, R0 303 MOVW $0, R1 304 MOVW $0, R2 305 MOVW $0, R3 306 MOVW $a-12(SP), R4 307 MOVW $SYS_select, R12 308 SWI $0x80 309 RET 310 311 TEXT ·publicationBarrier(SB),NOSPLIT,$-4-0 312 B runtime·armPublicationBarrier(SB) 313 314 TEXT runtime·sysctl(SB),NOSPLIT,$0 315 MOVW mib+0(FP), R0 316 MOVW miblen+4(FP), R1 317 MOVW out+8(FP), R2 318 MOVW size+12(FP), R3 319 MOVW dst+16(FP), R4 320 MOVW ndst+20(FP), R5 321 MOVW $SYS___sysctl, R12 // syscall entry 322 SWI $0x80 323 BCC sysctl_ret 324 RSB $0, R0, R0 325 MOVW R0, ret+24(FP) 326 RET 327 sysctl_ret: 328 MOVW $0, R0 329 MOVW R0, ret+24(FP) 330 RET 331 332 // Thread related functions 333 // func bsdthread_create(stk, arg unsafe.Pointer, fn uintptr) int32 334 TEXT runtime·bsdthread_create(SB),NOSPLIT,$0 335 // Set up arguments to bsdthread_create system call. 336 // The ones in quotes pass through to the thread callback 337 // uninterpreted, so we can put whatever we want there. 338 MOVW fn+8(FP), R0 // "func" 339 MOVW arg+4(FP), R1 // "arg" 340 MOVW stk+0(FP), R2 // stack 341 MOVW $0x01000000, R4 // flags = PTHREAD_START_CUSTOM 342 MOVW $0, R5 // paranoia 343 MOVW $SYS_bsdthread_create, R12 344 SWI $0x80 345 BCC create_ret 346 RSB $0, R0, R0 347 MOVW R0, ret+12(FP) 348 RET 349 create_ret: 350 MOVW $0, R0 351 MOVW R0, ret+12(FP) 352 RET 353 354 // The thread that bsdthread_create creates starts executing here, 355 // because we registered this function using bsdthread_register 356 // at startup. 357 // R0 = "pthread" 358 // R1 = mach thread port 359 // R2 = "func" (= fn) 360 // R3 = "arg" (= m) 361 // R4 = stack 362 // R5 = flags (= 0) 363 // XXX: how to deal with R4/SP? ref: Libc-594.9.1/arm/pthreads/thread_start.s 364 TEXT runtime·bsdthread_start(SB),NOSPLIT,$0 365 MOVW R1, m_procid(R3) // thread port is m->procid 366 MOVW m_g0(R3), g 367 MOVW R3, g_m(g) 368 // ARM don't have runtime·stackcheck(SB) 369 // disable runfast mode of vfp 370 EOR R12, R12 371 WORD $0xeee1ca10 // fmxr fpscr, ip 372 BL (R2) // fn 373 BL runtime·exit1(SB) 374 RET 375 376 // int32 bsdthread_register(void) 377 // registers callbacks for threadstart (see bsdthread_create above 378 // and wqthread and pthsize (not used). returns 0 on success. 379 TEXT runtime·bsdthread_register(SB),NOSPLIT,$0 380 MOVW $runtime·bsdthread_start(SB), R0 // threadstart 381 MOVW $0, R1 // wqthread, not used by us 382 MOVW $0, R2 // pthsize, not used by us 383 MOVW $0, R3 // dummy_value [sic] 384 MOVW $0, R4 // targetconc_ptr 385 MOVW $0, R5 // dispatchqueue_offset 386 MOVW $SYS_bsdthread_register, R12 // bsdthread_register 387 SWI $0x80 388 MOVW R0, ret+0(FP) 389 RET 390 391 // uint32 mach_msg_trap(void*, uint32, uint32, uint32, uint32, uint32, uint32) 392 TEXT runtime·mach_msg_trap(SB),NOSPLIT,$0 393 MOVW h+0(FP), R0 394 MOVW op+4(FP), R1 395 MOVW send_size+8(FP), R2 396 MOVW rcv_size+12(FP), R3 397 MOVW rcv_name+16(FP), R4 398 MOVW timeout+20(FP), R5 399 MOVW notify+24(FP), R6 400 MVN $30, R12 401 SWI $0x80 402 MOVW R0, ret+28(FP) 403 RET 404 405 TEXT runtime·mach_task_self(SB),NOSPLIT,$0 406 MVN $27, R12 // task_self_trap 407 SWI $0x80 408 MOVW R0, ret+0(FP) 409 RET 410 411 TEXT runtime·mach_thread_self(SB),NOSPLIT,$0 412 MVN $26, R12 // thread_self_trap 413 SWI $0x80 414 MOVW R0, ret+0(FP) 415 RET 416 417 TEXT runtime·mach_reply_port(SB),NOSPLIT,$0 418 MVN $25, R12 // mach_reply_port 419 SWI $0x80 420 MOVW R0, ret+0(FP) 421 RET 422 423 // Mach provides trap versions of the semaphore ops, 424 // instead of requiring the use of RPC. 425 426 // uint32 mach_semaphore_wait(uint32) 427 TEXT runtime·mach_semaphore_wait(SB),NOSPLIT,$0 428 MOVW sema+0(FP), R0 429 MVN $35, R12 // semaphore_wait_trap 430 SWI $0x80 431 MOVW R0, ret+4(FP) 432 RET 433 434 // uint32 mach_semaphore_timedwait(uint32, uint32, uint32) 435 TEXT runtime·mach_semaphore_timedwait(SB),NOSPLIT,$0 436 MOVW sema+0(FP), R0 437 MOVW sec+4(FP), R1 438 MOVW nsec+8(FP), R2 439 MVN $37, R12 // semaphore_timedwait_trap 440 SWI $0x80 441 MOVW R0, ret+12(FP) 442 RET 443 444 // uint32 mach_semaphore_signal(uint32) 445 TEXT runtime·mach_semaphore_signal(SB),NOSPLIT,$0 446 MOVW sema+0(FP), R0 447 MVN $32, R12 // semaphore_signal_trap 448 SWI $0x80 449 MOVW R0, ret+4(FP) 450 RET 451 452 // uint32 mach_semaphore_signal_all(uint32) 453 TEXT runtime·mach_semaphore_signal_all(SB),NOSPLIT,$0 454 MOVW sema+0(FP), R0 455 MVN $33, R12 // semaphore_signal_all_trap 456 SWI $0x80 457 MOVW R0, ret+4(FP) 458 RET 459 460 // int32 runtime·kqueue(void) 461 TEXT runtime·kqueue(SB),NOSPLIT,$0 462 MOVW $SYS_kqueue, R12 463 SWI $0x80 464 RSB.CS $0, R0, R0 465 MOVW R0, ret+0(FP) 466 RET 467 468 // int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int events, Timespec *timeout) 469 TEXT runtime·kevent(SB),NOSPLIT,$0 470 MOVW $SYS_kevent, R12 471 MOVW kq+0(FP), R0 472 MOVW ch+4(FP), R1 473 MOVW nch+8(FP), R2 474 MOVW ev+12(FP), R3 475 MOVW nev+16(FP), R4 476 MOVW ts+20(FP), R5 477 SWI $0x80 478 RSB.CS $0, R0, R0 479 MOVW R0, ret+24(FP) 480 RET 481 482 // int32 runtime·closeonexec(int32 fd) 483 TEXT runtime·closeonexec(SB),NOSPLIT,$0 484 MOVW $SYS_fcntl, R12 485 MOVW fd+0(FP), R0 486 MOVW $2, R1 // F_SETFD 487 MOVW $1, R2 // FD_CLOEXEC 488 SWI $0x80 489 RET 490 491 // sigaltstack on some darwin/arm version is buggy and will always 492 // run the signal handler on the main stack, so our sigtramp has 493 // to do the stack switch ourselves. 494 TEXT runtime·sigaltstack(SB),NOSPLIT,$0 495 RET