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