1 // Copyright 2013 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, NetBSD 6 // /usr/src/sys/kern/syscalls.master for syscall numbers. 7 // 8 9 #include "go_asm.h" 10 #include "go_tls.h" 11 #include "textflag.h" 12 13 // Exit the entire program (like C exit) 14 TEXT runtimeexit(SB),NOSPLIT,$-4 15 MOVW code+0(FP), R0 // arg 1 exit status 16 SWI $0xa00001 17 MOVW.CS $0, R8 // crash on syscall failure 18 MOVW.CS R8, (R8) 19 RET 20 21 // func exitThread(wait *uint32) 22 TEXT runtimeexitThread(SB),NOSPLIT,$0-4 23 MOVW wait+0(FP), R0 24 // We're done using the stack. 25 MOVW $0, R2 26 storeloop: 27 LDREX (R0), R4 // loads R4 28 STREX R2, (R0), R1 // stores R2 29 CMP $0, R1 30 BNE storeloop 31 SWI $0xa00136 // sys__lwp_exit 32 MOVW $1, R8 // crash 33 MOVW R8, (R8) 34 JMP 0(PC) 35 36 TEXT runtimeopen(SB),NOSPLIT,$-8 37 MOVW name+0(FP), R0 38 MOVW mode+4(FP), R1 39 MOVW perm+8(FP), R2 40 SWI $0xa00005 41 MOVW.CS $-1, R0 42 MOVW R0, ret+12(FP) 43 RET 44 45 TEXT runtimeclosefd(SB),NOSPLIT,$-8 46 MOVW fd+0(FP), R0 47 SWI $0xa00006 48 MOVW.CS $-1, R0 49 MOVW R0, ret+4(FP) 50 RET 51 52 TEXT runtimeread(SB),NOSPLIT,$-8 53 MOVW fd+0(FP), R0 54 MOVW p+4(FP), R1 55 MOVW n+8(FP), R2 56 SWI $0xa00003 57 MOVW.CS $-1, R0 58 MOVW R0, ret+12(FP) 59 RET 60 61 TEXT runtimewrite(SB),NOSPLIT,$-4 62 MOVW fd+0(FP), R0 // arg 1 - fd 63 MOVW p+4(FP), R1 // arg 2 - buf 64 MOVW n+8(FP), R2 // arg 3 - nbyte 65 SWI $0xa00004 // sys_write 66 MOVW.CS $-1, R0 67 MOVW R0, ret+12(FP) 68 RET 69 70 // int32 lwp_create(void *context, uintptr flags, void *lwpid) 71 TEXT runtimelwp_create(SB),NOSPLIT,$0 72 MOVW ctxt+0(FP), R0 73 MOVW flags+4(FP), R1 74 MOVW lwpid+8(FP), R2 75 SWI $0xa00135 // sys__lwp_create 76 MOVW R0, ret+12(FP) 77 RET 78 79 TEXT runtimeosyield(SB),NOSPLIT,$0 80 SWI $0xa0015e // sys_sched_yield 81 RET 82 83 TEXT runtimelwp_park(SB),NOSPLIT,$8 84 MOVW clockid+0(FP), R0 // arg 1 - clock_id 85 MOVW flags+4(FP), R1 // arg 2 - flags 86 MOVW ts+8(FP), R2 // arg 3 - ts 87 MOVW unpark+12(FP), R3 // arg 4 - unpark 88 MOVW hint+16(FP), R4 // arg 5 - hint 89 MOVW R4, 4(R13) 90 MOVW unparkhint+20(FP), R5 // arg 6 - unparkhint 91 MOVW R5, 8(R13) 92 SWI $0xa001de // sys__lwp_park 93 MOVW R0, ret+24(FP) 94 RET 95 96 TEXT runtimelwp_unpark(SB),NOSPLIT,$0 97 MOVW lwp+0(FP), R0 // arg 1 - lwp 98 MOVW hint+4(FP), R1 // arg 2 - hint 99 SWI $0xa00141 // sys__lwp_unpark 100 MOVW R0, ret+8(FP) 101 RET 102 103 TEXT runtimelwp_self(SB),NOSPLIT,$0 104 SWI $0xa00137 // sys__lwp_self 105 MOVW R0, ret+0(FP) 106 RET 107 108 TEXT runtimelwp_tramp(SB),NOSPLIT,$0 109 MOVW R0, g_m(R1) 110 MOVW R1, g 111 112 BL runtimeemptyfunc(SB) // fault if stack check is wrong 113 BL (R2) 114 MOVW $2, R8 // crash (not reached) 115 MOVW R8, (R8) 116 RET 117 118 TEXT runtimeusleep(SB),NOSPLIT,$16 119 MOVW usec+0(FP), R0 120 CALL runtimeusplitR0(SB) 121 // 0(R13) is the saved LR, don't use it 122 MOVW R0, 4(R13) // tv_sec.low 123 MOVW $0, R0 124 MOVW R0, 8(R13) // tv_sec.high 125 MOVW $1000, R2 126 MUL R1, R2 127 MOVW R2, 12(R13) // tv_nsec 128 129 MOVW $4(R13), R0 // arg 1 - rqtp 130 MOVW $0, R1 // arg 2 - rmtp 131 SWI $0xa001ae // sys_nanosleep 132 RET 133 134 TEXT runtimeraise(SB),NOSPLIT,$16 135 SWI $0xa00137 // sys__lwp_self, the returned R0 is arg 1 136 MOVW sig+0(FP), R1 // arg 2 - signal 137 SWI $0xa0013e // sys__lwp_kill 138 RET 139 140 TEXT runtimeraiseproc(SB),NOSPLIT,$16 141 SWI $0xa00014 // sys_getpid, the returned R0 is arg 1 142 MOVW sig+0(FP), R1 // arg 2 - signal 143 SWI $0xa00025 // sys_kill 144 RET 145 146 TEXT runtimesetitimer(SB),NOSPLIT,$-4 147 MOVW mode+0(FP), R0 // arg 1 - which 148 MOVW new+4(FP), R1 // arg 2 - itv 149 MOVW old+8(FP), R2 // arg 3 - oitv 150 SWI $0xa001a9 // sys_setitimer 151 RET 152 153 // func walltime() (sec int64, nsec int32) 154 TEXT runtimewalltime(SB), NOSPLIT, $32 155 MOVW $0, R0 // CLOCK_REALTIME 156 MOVW $8(R13), R1 157 SWI $0xa001ab // clock_gettime 158 159 MOVW 8(R13), R0 // sec.low 160 MOVW 12(R13), R1 // sec.high 161 MOVW 16(R13), R2 // nsec 162 163 MOVW R0, sec_lo+0(FP) 164 MOVW R1, sec_hi+4(FP) 165 MOVW R2, nsec+8(FP) 166 RET 167 168 // int64 nanotime(void) so really 169 // void nanotime(int64 *nsec) 170 TEXT runtimenanotime(SB), NOSPLIT, $32 171 MOVW $3, R0 // CLOCK_MONOTONIC 172 MOVW $8(R13), R1 173 SWI $0xa001ab // clock_gettime 174 175 MOVW 8(R13), R0 // sec.low 176 MOVW 12(R13), R4 // sec.high 177 MOVW 16(R13), R2 // nsec 178 179 MOVW $1000000000, R3 180 MULLU R0, R3, (R1, R0) 181 MUL R3, R4 182 ADD.S R2, R0 183 ADC R4, R1 184 185 MOVW R0, ret_lo+0(FP) 186 MOVW R1, ret_hi+4(FP) 187 RET 188 189 TEXT runtimegetcontext(SB),NOSPLIT,$-4 190 MOVW ctxt+0(FP), R0 // arg 1 - context 191 SWI $0xa00133 // sys_getcontext 192 MOVW.CS $0, R8 // crash on syscall failure 193 MOVW.CS R8, (R8) 194 RET 195 196 TEXT runtimesigprocmask(SB),NOSPLIT,$0 197 MOVW how+0(FP), R0 // arg 1 - how 198 MOVW new+4(FP), R1 // arg 2 - set 199 MOVW old+8(FP), R2 // arg 3 - oset 200 SWI $0xa00125 // sys_sigprocmask 201 MOVW.CS $0, R8 // crash on syscall failure 202 MOVW.CS R8, (R8) 203 RET 204 205 TEXT runtimesigreturn_tramp(SB),NOSPLIT,$-4 206 // on entry, SP points to siginfo, we add sizeof(ucontext) 207 // to SP to get a pointer to ucontext. 208 ADD $0x80, R13, R0 // 0x80 == sizeof(UcontextT) 209 SWI $0xa00134 // sys_setcontext 210 // something failed, we have to exit 211 MOVW $0x4242, R0 // magic return number 212 SWI $0xa00001 // sys_exit 213 B -2(PC) // continue exit 214 215 TEXT runtimesigaction(SB),NOSPLIT,$4 216 MOVW sig+0(FP), R0 // arg 1 - signum 217 MOVW new+4(FP), R1 // arg 2 - nsa 218 MOVW old+8(FP), R2 // arg 3 - osa 219 MOVW $runtimesigreturn_tramp(SB), R3 // arg 4 - tramp 220 MOVW $2, R4 // arg 5 - vers 221 MOVW R4, 4(R13) 222 ADD $4, R13 // pass arg 5 on stack 223 SWI $0xa00154 // sys___sigaction_sigtramp 224 SUB $4, R13 225 MOVW.CS $3, R8 // crash on syscall failure 226 MOVW.CS R8, (R8) 227 RET 228 229 TEXT runtimesigfwd(SB),NOSPLIT,$0-16 230 MOVW sig+4(FP), R0 231 MOVW info+8(FP), R1 232 MOVW ctx+12(FP), R2 233 MOVW fn+0(FP), R11 234 MOVW R13, R4 235 SUB $24, R13 236 BIC $0x7, R13 // alignment for ELF ABI 237 BL (R11) 238 MOVW R4, R13 239 RET 240 241 TEXT runtimesigtramp(SB),NOSPLIT,$12 242 // this might be called in external code context, 243 // where g is not set. 244 // first save R0, because runtimeload_g will clobber it 245 MOVW R0, 4(R13) // signum 246 MOVB runtimeiscgo(SB), R0 247 CMP $0, R0 248 BL.NE runtimeload_g(SB) 249 250 MOVW R1, 8(R13) 251 MOVW R2, 12(R13) 252 BL runtimesigtrampgo(SB) 253 RET 254 255 TEXT runtimemmap(SB),NOSPLIT,$12 256 MOVW addr+0(FP), R0 // arg 1 - addr 257 MOVW n+4(FP), R1 // arg 2 - len 258 MOVW prot+8(FP), R2 // arg 3 - prot 259 MOVW flags+12(FP), R3 // arg 4 - flags 260 // arg 5 (fid) and arg6 (offset_lo, offset_hi) are passed on stack 261 // note the C runtime only passes the 32-bit offset_lo to us 262 MOVW fd+16(FP), R4 // arg 5 263 MOVW R4, 4(R13) 264 MOVW off+20(FP), R5 // arg 6 lower 32-bit 265 MOVW R5, 8(R13) 266 MOVW $0, R6 // higher 32-bit for arg 6 267 MOVW R6, 12(R13) 268 ADD $4, R13 // pass arg 5 and arg 6 on stack 269 SWI $0xa000c5 // sys_mmap 270 SUB $4, R13 271 MOVW $0, R1 272 MOVW.CS R0, R1 // if error, move to R1 273 MOVW.CS $0, R0 274 MOVW R0, p+24(FP) 275 MOVW R1, err+28(FP) 276 RET 277 278 TEXT runtimemunmap(SB),NOSPLIT,$0 279 MOVW addr+0(FP), R0 // arg 1 - addr 280 MOVW n+4(FP), R1 // arg 2 - len 281 SWI $0xa00049 // sys_munmap 282 MOVW.CS $0, R8 // crash on syscall failure 283 MOVW.CS R8, (R8) 284 RET 285 286 TEXT runtimemadvise(SB),NOSPLIT,$0 287 MOVW addr+0(FP), R0 // arg 1 - addr 288 MOVW n+4(FP), R1 // arg 2 - len 289 MOVW flags+8(FP), R2 // arg 3 - behav 290 SWI $0xa0004b // sys_madvise 291 // ignore failure - maybe pages are locked 292 RET 293 294 TEXT runtimesigaltstack(SB),NOSPLIT,$-4 295 MOVW new+0(FP), R0 // arg 1 - nss 296 MOVW old+4(FP), R1 // arg 2 - oss 297 SWI $0xa00119 // sys___sigaltstack14 298 MOVW.CS $0, R8 // crash on syscall failure 299 MOVW.CS R8, (R8) 300 RET 301 302 TEXT runtimesysctl(SB),NOSPLIT,$8 303 MOVW mib+0(FP), R0 // arg 1 - name 304 MOVW miblen+4(FP), R1 // arg 2 - namelen 305 MOVW out+8(FP), R2 // arg 3 - oldp 306 MOVW size+12(FP), R3 // arg 4 - oldlenp 307 MOVW dst+16(FP), R4 // arg 5 - newp 308 MOVW R4, 4(R13) 309 MOVW ndst+20(FP), R4 // arg 6 - newlen 310 MOVW R4, 8(R13) 311 ADD $4, R13 // pass arg 5 and 6 on stack 312 SWI $0xa000ca // sys___sysctl 313 SUB $4, R13 314 MOVW R0, ret+24(FP) 315 RET 316 317 // int32 runtimekqueue(void) 318 TEXT runtimekqueue(SB),NOSPLIT,$0 319 SWI $0xa00158 // sys_kqueue 320 RSB.CS $0, R0 321 MOVW R0, ret+0(FP) 322 RET 323 324 // int32 runtimekevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int nevents, Timespec *timeout) 325 TEXT runtimekevent(SB),NOSPLIT,$8 326 MOVW kq+0(FP), R0 // kq 327 MOVW ch+4(FP), R1 // changelist 328 MOVW nch+8(FP), R2 // nchanges 329 MOVW ev+12(FP), R3 // eventlist 330 MOVW nev+16(FP), R4 // nevents 331 MOVW R4, 4(R13) 332 MOVW ts+20(FP), R4 // timeout 333 MOVW R4, 8(R13) 334 ADD $4, R13 // pass arg 5 and 6 on stack 335 SWI $0xa001b3 // sys___kevent50 336 RSB.CS $0, R0 337 SUB $4, R13 338 MOVW R0, ret+24(FP) 339 RET 340 341 // void runtimecloseonexec(int32 fd) 342 TEXT runtimecloseonexec(SB),NOSPLIT,$0 343 MOVW fd+0(FP), R0 // fd 344 MOVW $2, R1 // F_SETFD 345 MOVW $1, R2 // FD_CLOEXEC 346 SWI $0xa0005c // sys_fcntl 347 RET 348 349 // TODO: this is only valid for ARMv7+ 350 TEXT publicationBarrier(SB),NOSPLIT,$-4-0 351 B runtimearmPublicationBarrier(SB) 352 353 TEXT runtimeread_tls_fallback(SB),NOSPLIT,$-4 354 MOVM.WP [R1, R2, R3, R12], (R13) 355 SWI $0x00a0013c // _lwp_getprivate 356 MOVM.IAW (R13), [R1, R2, R3, R12] 357 RET 358