github.com/reiver/go@v0.0.0-20150109200633-1d0c7792f172/src/runtime/sys_linux_arm.s (about) 1 // Copyright 2009 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 // 6 // System calls and other sys.stuff for arm, Linux 7 // 8 9 #include "go_asm.h" 10 #include "go_tls.h" 11 #include "textflag.h" 12 13 // for EABI, as we don't support OABI 14 #define SYS_BASE 0x0 15 16 #define SYS_exit (SYS_BASE + 1) 17 #define SYS_read (SYS_BASE + 3) 18 #define SYS_write (SYS_BASE + 4) 19 #define SYS_open (SYS_BASE + 5) 20 #define SYS_close (SYS_BASE + 6) 21 #define SYS_gettimeofday (SYS_BASE + 78) 22 #define SYS_clone (SYS_BASE + 120) 23 #define SYS_rt_sigreturn (SYS_BASE + 173) 24 #define SYS_rt_sigaction (SYS_BASE + 174) 25 #define SYS_rt_sigprocmask (SYS_BASE + 175) 26 #define SYS_sigaltstack (SYS_BASE + 186) 27 #define SYS_mmap2 (SYS_BASE + 192) 28 #define SYS_futex (SYS_BASE + 240) 29 #define SYS_exit_group (SYS_BASE + 248) 30 #define SYS_munmap (SYS_BASE + 91) 31 #define SYS_madvise (SYS_BASE + 220) 32 #define SYS_setitimer (SYS_BASE + 104) 33 #define SYS_mincore (SYS_BASE + 219) 34 #define SYS_gettid (SYS_BASE + 224) 35 #define SYS_tkill (SYS_BASE + 238) 36 #define SYS_sched_yield (SYS_BASE + 158) 37 #define SYS_select (SYS_BASE + 142) // newselect 38 #define SYS_ugetrlimit (SYS_BASE + 191) 39 #define SYS_sched_getaffinity (SYS_BASE + 242) 40 #define SYS_clock_gettime (SYS_BASE + 263) 41 #define SYS_epoll_create (SYS_BASE + 250) 42 #define SYS_epoll_ctl (SYS_BASE + 251) 43 #define SYS_epoll_wait (SYS_BASE + 252) 44 #define SYS_epoll_create1 (SYS_BASE + 357) 45 #define SYS_fcntl (SYS_BASE + 55) 46 47 #define ARM_BASE (SYS_BASE + 0x0f0000) 48 49 TEXT runtime·open(SB),NOSPLIT,$0 50 MOVW 0(FP), R0 51 MOVW 4(FP), R1 52 MOVW 8(FP), R2 53 MOVW $SYS_open, R7 54 SWI $0 55 MOVW R0, ret+12(FP) 56 RET 57 58 TEXT runtime·close(SB),NOSPLIT,$0 59 MOVW 0(FP), R0 60 MOVW $SYS_close, R7 61 SWI $0 62 MOVW R0, ret+4(FP) 63 RET 64 65 TEXT runtime·write(SB),NOSPLIT,$0 66 MOVW 0(FP), R0 67 MOVW 4(FP), R1 68 MOVW 8(FP), R2 69 MOVW $SYS_write, R7 70 SWI $0 71 MOVW R0, ret+12(FP) 72 RET 73 74 TEXT runtime·read(SB),NOSPLIT,$0 75 MOVW 0(FP), R0 76 MOVW 4(FP), R1 77 MOVW 8(FP), R2 78 MOVW $SYS_read, R7 79 SWI $0 80 MOVW R0, ret+12(FP) 81 RET 82 83 TEXT runtime·getrlimit(SB),NOSPLIT,$0 84 MOVW 0(FP), R0 85 MOVW 4(FP), R1 86 MOVW $SYS_ugetrlimit, R7 87 SWI $0 88 MOVW R0, ret+8(FP) 89 RET 90 91 TEXT runtime·exit(SB),NOSPLIT,$-4 92 MOVW 0(FP), R0 93 MOVW $SYS_exit_group, R7 94 SWI $0 95 MOVW $1234, R0 96 MOVW $1002, R1 97 MOVW R0, (R1) // fail hard 98 99 TEXT runtime·exit1(SB),NOSPLIT,$-4 100 MOVW 0(FP), R0 101 MOVW $SYS_exit, R7 102 SWI $0 103 MOVW $1234, R0 104 MOVW $1003, R1 105 MOVW R0, (R1) // fail hard 106 107 TEXT runtime·raise(SB),NOSPLIT,$-4 108 MOVW $SYS_gettid, R7 109 SWI $0 110 // arg 1 tid already in R0 from gettid 111 MOVW sig+0(FP), R1 // arg 2 - signal 112 MOVW $SYS_tkill, R7 113 SWI $0 114 RET 115 116 TEXT runtime·mmap(SB),NOSPLIT,$0 117 MOVW 0(FP), R0 118 MOVW 4(FP), R1 119 MOVW 8(FP), R2 120 MOVW 12(FP), R3 121 MOVW 16(FP), R4 122 MOVW 20(FP), R5 123 MOVW $SYS_mmap2, R7 124 SWI $0 125 MOVW $0xfffff001, R6 126 CMP R6, R0 127 RSB.HI $0, R0 128 MOVW R0, ret+24(FP) 129 RET 130 131 TEXT runtime·munmap(SB),NOSPLIT,$0 132 MOVW 0(FP), R0 133 MOVW 4(FP), R1 134 MOVW $SYS_munmap, R7 135 SWI $0 136 MOVW $0xfffff001, R6 137 CMP R6, R0 138 MOVW.HI $0, R8 // crash on syscall failure 139 MOVW.HI R8, (R8) 140 RET 141 142 TEXT runtime·madvise(SB),NOSPLIT,$0 143 MOVW 0(FP), R0 144 MOVW 4(FP), R1 145 MOVW 8(FP), R2 146 MOVW $SYS_madvise, R7 147 SWI $0 148 // ignore failure - maybe pages are locked 149 RET 150 151 TEXT runtime·setitimer(SB),NOSPLIT,$0 152 MOVW 0(FP), R0 153 MOVW 4(FP), R1 154 MOVW 8(FP), R2 155 MOVW $SYS_setitimer, R7 156 SWI $0 157 RET 158 159 TEXT runtime·mincore(SB),NOSPLIT,$0 160 MOVW 0(FP), R0 161 MOVW 4(FP), R1 162 MOVW 8(FP), R2 163 MOVW $SYS_mincore, R7 164 SWI $0 165 MOVW R0, ret+12(FP) 166 RET 167 168 TEXT time·now(SB), NOSPLIT, $32 169 MOVW $0, R0 // CLOCK_REALTIME 170 MOVW $8(R13), R1 // timespec 171 MOVW $SYS_clock_gettime, R7 172 SWI $0 173 174 MOVW 8(R13), R0 // sec 175 MOVW 12(R13), R2 // nsec 176 177 MOVW R0, 0(FP) 178 MOVW $0, R1 179 MOVW R1, 4(FP) 180 MOVW R2, 8(FP) 181 RET 182 183 // int64 nanotime(void) 184 TEXT runtime·nanotime(SB),NOSPLIT,$32 185 MOVW $1, R0 // CLOCK_MONOTONIC 186 MOVW $8(R13), R1 // timespec 187 MOVW $SYS_clock_gettime, R7 188 SWI $0 189 190 MOVW 8(R13), R0 // sec 191 MOVW 12(R13), R2 // nsec 192 193 MOVW $1000000000, R3 194 MULLU R0, R3, (R1, R0) 195 MOVW $0, R4 196 ADD.S R2, R0 197 ADC R4, R1 198 199 MOVW R0, ret_lo+0(FP) 200 MOVW R1, ret_hi+4(FP) 201 RET 202 203 // int32 futex(int32 *uaddr, int32 op, int32 val, 204 // struct timespec *timeout, int32 *uaddr2, int32 val2); 205 TEXT runtime·futex(SB),NOSPLIT,$0 206 MOVW 4(SP), R0 207 MOVW 8(SP), R1 208 MOVW 12(SP), R2 209 MOVW 16(SP), R3 210 MOVW 20(SP), R4 211 MOVW 24(SP), R5 212 MOVW $SYS_futex, R7 213 SWI $0 214 MOVW R0, ret+24(FP) 215 RET 216 217 218 // int32 clone(int32 flags, void *stack, M *mp, G *gp, void (*fn)(void)); 219 TEXT runtime·clone(SB),NOSPLIT,$0 220 MOVW flags+0(FP), R0 221 MOVW stk+4(FP), R1 222 MOVW $0, R2 // parent tid ptr 223 MOVW $0, R3 // tls_val 224 MOVW $0, R4 // child tid ptr 225 MOVW $0, R5 226 227 // Copy mp, gp, fn off parent stack for use by child. 228 // TODO(kaib): figure out which registers are clobbered by clone and avoid stack copying 229 MOVW $-16(R1), R1 230 MOVW mm+8(FP), R6 231 MOVW R6, 0(R1) 232 MOVW gg+12(FP), R6 233 MOVW R6, 4(R1) 234 MOVW fn+16(FP), R6 235 MOVW R6, 8(R1) 236 MOVW $1234, R6 237 MOVW R6, 12(R1) 238 239 MOVW $SYS_clone, R7 240 SWI $0 241 242 // In parent, return. 243 CMP $0, R0 244 BEQ 3(PC) 245 MOVW R0, ret+20(FP) 246 RET 247 248 // Paranoia: check that SP is as we expect. Use R13 to avoid linker 'fixup' 249 MOVW 12(R13), R0 250 MOVW $1234, R1 251 CMP R0, R1 252 BEQ 2(PC) 253 BL runtime·abort(SB) 254 255 MOVW 4(R13), g 256 MOVW 0(R13), R8 257 MOVW R8, g_m(g) 258 259 // paranoia; check they are not nil 260 MOVW 0(R8), R0 261 MOVW 0(g), R0 262 263 BL runtime·emptyfunc(SB) // fault if stack check is wrong 264 265 // Initialize m->procid to Linux tid 266 MOVW $SYS_gettid, R7 267 SWI $0 268 MOVW g_m(g), R8 269 MOVW R0, m_procid(R8) 270 271 // Call fn 272 MOVW 8(R13), R0 273 MOVW $16(R13), R13 274 BL (R0) 275 276 MOVW $0, R0 277 MOVW R0, 4(R13) 278 BL runtime·exit1(SB) 279 280 // It shouldn't return 281 MOVW $1234, R0 282 MOVW $1005, R1 283 MOVW R0, (R1) 284 285 TEXT runtime·sigaltstack(SB),NOSPLIT,$0 286 MOVW 0(FP), R0 287 MOVW 4(FP), R1 288 MOVW $SYS_sigaltstack, R7 289 SWI $0 290 MOVW $0xfffff001, R6 291 CMP R6, R0 292 MOVW.HI $0, R8 // crash on syscall failure 293 MOVW.HI R8, (R8) 294 RET 295 296 TEXT runtime·sigtramp(SB),NOSPLIT,$24 297 // this might be called in external code context, 298 // where g is not set. 299 // first save R0, because runtime·load_g will clobber it 300 MOVW R0, 4(R13) 301 MOVB runtime·iscgo(SB), R0 302 CMP $0, R0 303 BL.NE runtime·load_g(SB) 304 305 CMP $0, g 306 BNE 4(PC) 307 // signal number is already prepared in 4(R13) 308 MOVW $runtime·badsignal(SB), R11 309 BL (R11) 310 RET 311 312 // save g 313 MOVW g, R3 314 MOVW g, 20(R13) 315 316 // g = m->gsignal 317 MOVW g_m(g), R8 318 MOVW m_gsignal(R8), g 319 320 // copy arguments for call to sighandler 321 // R0 is already saved above 322 MOVW R1, 8(R13) 323 MOVW R2, 12(R13) 324 MOVW R3, 16(R13) 325 326 BL runtime·sighandler(SB) 327 328 // restore g 329 MOVW 20(R13), g 330 331 RET 332 333 TEXT runtime·rtsigprocmask(SB),NOSPLIT,$0 334 MOVW 0(FP), R0 335 MOVW 4(FP), R1 336 MOVW 8(FP), R2 337 MOVW 12(FP), R3 338 MOVW $SYS_rt_sigprocmask, R7 339 SWI $0 340 RET 341 342 TEXT runtime·rt_sigaction(SB),NOSPLIT,$0 343 MOVW 0(FP), R0 344 MOVW 4(FP), R1 345 MOVW 8(FP), R2 346 MOVW 12(FP), R3 347 MOVW $SYS_rt_sigaction, R7 348 SWI $0 349 MOVW R0, ret+16(FP) 350 RET 351 352 TEXT runtime·usleep(SB),NOSPLIT,$12 353 MOVW usec+0(FP), R0 354 MOVW R0, R1 355 MOVW $1000000, R2 356 DIV R2, R0 357 MOD R2, R1 358 MOVW R0, 4(SP) 359 MOVW R1, 8(SP) 360 MOVW $0, R0 361 MOVW $0, R1 362 MOVW $0, R2 363 MOVW $0, R3 364 MOVW $4(SP), R4 365 MOVW $SYS_select, R7 366 SWI $0 367 RET 368 369 // Use kernel version instead of native armcas in asm_arm.s. 370 // See ../sync/atomic/asm_linux_arm.s for details. 371 TEXT cas<>(SB),NOSPLIT,$0 372 MOVW $0xffff0fc0, PC 373 374 TEXT runtime·cas(SB),NOSPLIT,$0 375 MOVW ptr+0(FP), R2 376 MOVW old+4(FP), R0 377 loop: 378 MOVW new+8(FP), R1 379 BL cas<>(SB) 380 BCC check 381 MOVW $1, R0 382 MOVB R0, ret+12(FP) 383 RET 384 check: 385 // Kernel lies; double-check. 386 MOVW ptr+0(FP), R2 387 MOVW old+4(FP), R0 388 MOVW 0(R2), R3 389 CMP R0, R3 390 BEQ loop 391 MOVW $0, R0 392 MOVB R0, ret+12(FP) 393 RET 394 395 TEXT runtime·casp1(SB),NOSPLIT,$0 396 B runtime·cas(SB) 397 398 TEXT runtime·osyield(SB),NOSPLIT,$0 399 MOVW $SYS_sched_yield, R7 400 SWI $0 401 RET 402 403 TEXT runtime·sched_getaffinity(SB),NOSPLIT,$0 404 MOVW 0(FP), R0 405 MOVW 4(FP), R1 406 MOVW 8(FP), R2 407 MOVW $SYS_sched_getaffinity, R7 408 SWI $0 409 MOVW R0, ret+12(FP) 410 RET 411 412 // int32 runtime·epollcreate(int32 size) 413 TEXT runtime·epollcreate(SB),NOSPLIT,$0 414 MOVW 0(FP), R0 415 MOVW $SYS_epoll_create, R7 416 SWI $0 417 MOVW R0, ret+4(FP) 418 RET 419 420 // int32 runtime·epollcreate1(int32 flags) 421 TEXT runtime·epollcreate1(SB),NOSPLIT,$0 422 MOVW 0(FP), R0 423 MOVW $SYS_epoll_create1, R7 424 SWI $0 425 MOVW R0, ret+4(FP) 426 RET 427 428 // func epollctl(epfd, op, fd int32, ev *epollEvent) int 429 TEXT runtime·epollctl(SB),NOSPLIT,$0 430 MOVW epfd+0(FP), R0 431 MOVW op+4(FP), R1 432 MOVW fd+8(FP), R2 433 MOVW ev+12(FP), R3 434 MOVW $SYS_epoll_ctl, R7 435 SWI $0 436 MOVW R0, ret+16(FP) 437 RET 438 439 // int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout) 440 TEXT runtime·epollwait(SB),NOSPLIT,$0 441 MOVW 0(FP), R0 442 MOVW 4(FP), R1 443 MOVW 8(FP), R2 444 MOVW 12(FP), R3 445 MOVW $SYS_epoll_wait, R7 446 SWI $0 447 MOVW R0, ret+16(FP) 448 RET 449 450 // void runtime·closeonexec(int32 fd) 451 TEXT runtime·closeonexec(SB),NOSPLIT,$0 452 MOVW 0(FP), R0 // fd 453 MOVW $2, R1 // F_SETFD 454 MOVW $1, R2 // FD_CLOEXEC 455 MOVW $SYS_fcntl, R7 456 SWI $0 457 RET 458 459 // b __kuser_get_tls @ 0xffff0fe0 460 TEXT runtime·read_tls_fallback(SB),NOSPLIT,$-4 461 MOVW $0xffff0fe0, R0 462 B (R0)