1// Copyright 2016 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// +build linux 6// +build mips mipsle 7 8// 9// System calls and other sys.stuff for mips, Linux 10// 11 12#include "go_asm.h" 13#include "go_tls.h" 14#include "textflag.h" 15 16#define SYS_exit 4001 17#define SYS_read 4003 18#define SYS_write 4004 19#define SYS_open 4005 20#define SYS_close 4006 21#define SYS_getpid 4020 22#define SYS_kill 4037 23#define SYS_pipe 4042 24#define SYS_brk 4045 25#define SYS_fcntl 4055 26#define SYS_mmap 4090 27#define SYS_munmap 4091 28#define SYS_setitimer 4104 29#define SYS_clone 4120 30#define SYS_sched_yield 4162 31#define SYS_nanosleep 4166 32#define SYS_rt_sigreturn 4193 33#define SYS_rt_sigaction 4194 34#define SYS_rt_sigprocmask 4195 35#define SYS_sigaltstack 4206 36#define SYS_madvise 4218 37#define SYS_mincore 4217 38#define SYS_gettid 4222 39#define SYS_futex 4238 40#define SYS_sched_getaffinity 4240 41#define SYS_exit_group 4246 42#define SYS_epoll_create 4248 43#define SYS_epoll_ctl 4249 44#define SYS_epoll_wait 4250 45#define SYS_clock_gettime 4263 46#define SYS_tgkill 4266 47#define SYS_epoll_create1 4326 48#define SYS_pipe2 4328 49 50TEXT runtime·exit(SB),NOSPLIT,$0-4 51 MOVW code+0(FP), R4 52 MOVW $SYS_exit_group, R2 53 SYSCALL 54 UNDEF 55 RET 56 57// func exitThread(wait *uint32) 58TEXT runtime·exitThread(SB),NOSPLIT,$0-4 59 MOVW wait+0(FP), R1 60 // We're done using the stack. 61 MOVW $0, R2 62 SYNC 63 MOVW R2, (R1) 64 SYNC 65 MOVW $0, R4 // exit code 66 MOVW $SYS_exit, R2 67 SYSCALL 68 UNDEF 69 JMP 0(PC) 70 71TEXT runtime·open(SB),NOSPLIT,$0-16 72 MOVW name+0(FP), R4 73 MOVW mode+4(FP), R5 74 MOVW perm+8(FP), R6 75 MOVW $SYS_open, R2 76 SYSCALL 77 BEQ R7, 2(PC) 78 MOVW $-1, R2 79 MOVW R2, ret+12(FP) 80 RET 81 82TEXT runtime·closefd(SB),NOSPLIT,$0-8 83 MOVW fd+0(FP), R4 84 MOVW $SYS_close, R2 85 SYSCALL 86 BEQ R7, 2(PC) 87 MOVW $-1, R2 88 MOVW R2, ret+4(FP) 89 RET 90 91TEXT runtime·write1(SB),NOSPLIT,$0-16 92 MOVW fd+0(FP), R4 93 MOVW p+4(FP), R5 94 MOVW n+8(FP), R6 95 MOVW $SYS_write, R2 96 SYSCALL 97 BEQ R7, 2(PC) 98 SUBU R2, R0, R2 // caller expects negative errno 99 MOVW R2, ret+12(FP) 100 RET 101 102TEXT runtime·read(SB),NOSPLIT,$0-16 103 MOVW fd+0(FP), R4 104 MOVW p+4(FP), R5 105 MOVW n+8(FP), R6 106 MOVW $SYS_read, R2 107 SYSCALL 108 BEQ R7, 2(PC) 109 SUBU R2, R0, R2 // caller expects negative errno 110 MOVW R2, ret+12(FP) 111 RET 112 113// func pipe() (r, w int32, errno int32) 114TEXT runtime·pipe(SB),NOSPLIT,$0-12 115 MOVW $SYS_pipe, R2 116 SYSCALL 117 BEQ R7, pipeok 118 MOVW $-1, R1 119 MOVW R1, r+0(FP) 120 MOVW R1, w+4(FP) 121 MOVW R2, errno+8(FP) 122 RET 123pipeok: 124 MOVW R2, r+0(FP) 125 MOVW R3, w+4(FP) 126 MOVW R0, errno+8(FP) 127 RET 128 129// func pipe2(flags int32) (r, w int32, errno int32) 130TEXT runtime·pipe2(SB),NOSPLIT,$0-16 131 MOVW $r+4(FP), R4 132 MOVW flags+0(FP), R5 133 MOVW $SYS_pipe2, R2 134 SYSCALL 135 MOVW R2, errno+12(FP) 136 RET 137 138TEXT runtime·usleep(SB),NOSPLIT,$28-4 139 MOVW usec+0(FP), R3 140 MOVW R3, R5 141 MOVW $1000000, R4 142 DIVU R4, R3 143 MOVW LO, R3 144 MOVW R3, 24(R29) 145 MOVW $1000, R4 146 MULU R3, R4 147 MOVW LO, R4 148 SUBU R4, R5 149 MOVW R5, 28(R29) 150 151 // nanosleep(&ts, 0) 152 ADDU $24, R29, R4 153 MOVW $0, R5 154 MOVW $SYS_nanosleep, R2 155 SYSCALL 156 RET 157 158TEXT runtime·gettid(SB),NOSPLIT,$0-4 159 MOVW $SYS_gettid, R2 160 SYSCALL 161 MOVW R2, ret+0(FP) 162 RET 163 164TEXT runtime·raise(SB),NOSPLIT,$0-4 165 MOVW $SYS_getpid, R2 166 SYSCALL 167 MOVW R2, R16 168 MOVW $SYS_gettid, R2 169 SYSCALL 170 MOVW R2, R5 // arg 2 tid 171 MOVW R16, R4 // arg 1 pid 172 MOVW sig+0(FP), R6 // arg 3 173 MOVW $SYS_tgkill, R2 174 SYSCALL 175 RET 176 177TEXT runtime·raiseproc(SB),NOSPLIT,$0 178 MOVW $SYS_getpid, R2 179 SYSCALL 180 MOVW R2, R4 // arg 1 pid 181 MOVW sig+0(FP), R5 // arg 2 182 MOVW $SYS_kill, R2 183 SYSCALL 184 RET 185 186TEXT ·getpid(SB),NOSPLIT,$0-4 187 MOVW $SYS_getpid, R2 188 SYSCALL 189 MOVW R2, ret+0(FP) 190 RET 191 192TEXT ·tgkill(SB),NOSPLIT,$0-12 193 MOVW tgid+0(FP), R4 194 MOVW tid+4(FP), R5 195 MOVW sig+8(FP), R6 196 MOVW $SYS_tgkill, R2 197 SYSCALL 198 RET 199 200TEXT runtime·setitimer(SB),NOSPLIT,$0-12 201 MOVW mode+0(FP), R4 202 MOVW new+4(FP), R5 203 MOVW old+8(FP), R6 204 MOVW $SYS_setitimer, R2 205 SYSCALL 206 RET 207 208TEXT runtime·mincore(SB),NOSPLIT,$0-16 209 MOVW addr+0(FP), R4 210 MOVW n+4(FP), R5 211 MOVW dst+8(FP), R6 212 MOVW $SYS_mincore, R2 213 SYSCALL 214 SUBU R2, R0, R2 // caller expects negative errno 215 MOVW R2, ret+12(FP) 216 RET 217 218// func walltime1() (sec int64, nsec int32) 219TEXT runtime·walltime1(SB),NOSPLIT,$8-12 220 MOVW $0, R4 // CLOCK_REALTIME 221 MOVW $4(R29), R5 222 MOVW $SYS_clock_gettime, R2 223 SYSCALL 224 MOVW 4(R29), R3 // sec 225 MOVW 8(R29), R5 // nsec 226 MOVW $sec+0(FP), R6 227#ifdef GOARCH_mips 228 MOVW R3, 4(R6) 229 MOVW R0, 0(R6) 230#else 231 MOVW R3, 0(R6) 232 MOVW R0, 4(R6) 233#endif 234 MOVW R5, nsec+8(FP) 235 RET 236 237TEXT runtime·nanotime1(SB),NOSPLIT,$8-8 238 MOVW $1, R4 // CLOCK_MONOTONIC 239 MOVW $4(R29), R5 240 MOVW $SYS_clock_gettime, R2 241 SYSCALL 242 MOVW 4(R29), R3 // sec 243 MOVW 8(R29), R5 // nsec 244 // sec is in R3, nsec in R5 245 // return nsec in R3 246 MOVW $1000000000, R4 247 MULU R4, R3 248 MOVW LO, R3 249 ADDU R5, R3 250 SGTU R5, R3, R4 251 MOVW $ret+0(FP), R6 252#ifdef GOARCH_mips 253 MOVW R3, 4(R6) 254#else 255 MOVW R3, 0(R6) 256#endif 257 MOVW HI, R3 258 ADDU R4, R3 259#ifdef GOARCH_mips 260 MOVW R3, 0(R6) 261#else 262 MOVW R3, 4(R6) 263#endif 264 RET 265 266TEXT runtime·rtsigprocmask(SB),NOSPLIT,$0-16 267 MOVW how+0(FP), R4 268 MOVW new+4(FP), R5 269 MOVW old+8(FP), R6 270 MOVW size+12(FP), R7 271 MOVW $SYS_rt_sigprocmask, R2 272 SYSCALL 273 BEQ R7, 2(PC) 274 UNDEF // crash 275 RET 276 277TEXT runtime·rt_sigaction(SB),NOSPLIT,$0-20 278 MOVW sig+0(FP), R4 279 MOVW new+4(FP), R5 280 MOVW old+8(FP), R6 281 MOVW size+12(FP), R7 282 MOVW $SYS_rt_sigaction, R2 283 SYSCALL 284 BEQ R7, 2(PC) 285 SUBU R2, R0, R2 // caller expects negative errno 286 MOVW R2, ret+16(FP) 287 RET 288 289TEXT runtime·sigfwd(SB),NOSPLIT,$0-16 290 MOVW sig+4(FP), R4 291 MOVW info+8(FP), R5 292 MOVW ctx+12(FP), R6 293 MOVW fn+0(FP), R25 294 MOVW R29, R22 295 SUBU $16, R29 296 AND $~7, R29 // shadow space for 4 args aligned to 8 bytes as per O32 ABI 297 JAL (R25) 298 MOVW R22, R29 299 RET 300 301TEXT runtime·sigtramp(SB),NOSPLIT,$12 302 // this might be called in external code context, 303 // where g is not set. 304 MOVB runtime·iscgo(SB), R1 305 BEQ R1, 2(PC) 306 JAL runtime·load_g(SB) 307 308 MOVW R4, 4(R29) 309 MOVW R5, 8(R29) 310 MOVW R6, 12(R29) 311 MOVW $runtime·sigtrampgo(SB), R1 312 JAL (R1) 313 RET 314 315TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0 316 JMP runtime·sigtramp(SB) 317 318TEXT runtime·mmap(SB),NOSPLIT,$20-32 319 MOVW addr+0(FP), R4 320 MOVW n+4(FP), R5 321 MOVW prot+8(FP), R6 322 MOVW flags+12(FP), R7 323 MOVW fd+16(FP), R8 324 MOVW off+20(FP), R9 325 MOVW R8, 16(R29) 326 MOVW R9, 20(R29) 327 328 MOVW $SYS_mmap, R2 329 SYSCALL 330 BEQ R7, ok 331 MOVW $0, p+24(FP) 332 MOVW R2, err+28(FP) 333 RET 334ok: 335 MOVW R2, p+24(FP) 336 MOVW $0, err+28(FP) 337 RET 338 339TEXT runtime·munmap(SB),NOSPLIT,$0-8 340 MOVW addr+0(FP), R4 341 MOVW n+4(FP), R5 342 MOVW $SYS_munmap, R2 343 SYSCALL 344 BEQ R7, 2(PC) 345 UNDEF // crash 346 RET 347 348TEXT runtime·madvise(SB),NOSPLIT,$0-16 349 MOVW addr+0(FP), R4 350 MOVW n+4(FP), R5 351 MOVW flags+8(FP), R6 352 MOVW $SYS_madvise, R2 353 SYSCALL 354 MOVW R2, ret+12(FP) 355 RET 356 357// int32 futex(int32 *uaddr, int32 op, int32 val, struct timespec *timeout, int32 *uaddr2, int32 val2); 358TEXT runtime·futex(SB),NOSPLIT,$20-28 359 MOVW addr+0(FP), R4 360 MOVW op+4(FP), R5 361 MOVW val+8(FP), R6 362 MOVW ts+12(FP), R7 363 364 MOVW addr2+16(FP), R8 365 MOVW val3+20(FP), R9 366 367 MOVW R8, 16(R29) 368 MOVW R9, 20(R29) 369 370 MOVW $SYS_futex, R2 371 SYSCALL 372 BEQ R7, 2(PC) 373 SUBU R2, R0, R2 // caller expects negative errno 374 MOVW R2, ret+24(FP) 375 RET 376 377 378// int32 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void)); 379TEXT runtime·clone(SB),NOSPLIT|NOFRAME,$0-24 380 MOVW flags+0(FP), R4 381 MOVW stk+4(FP), R5 382 MOVW R0, R6 // ptid 383 MOVW R0, R7 // tls 384 385 // O32 syscall handler unconditionally copies arguments 5-8 from stack, 386 // even for syscalls with less than 8 arguments. Reserve 32 bytes of new 387 // stack so that any syscall invoked immediately in the new thread won't fail. 388 ADD $-32, R5 389 390 // Copy mp, gp, fn off parent stack for use by child. 391 MOVW mp+8(FP), R16 392 MOVW gp+12(FP), R17 393 MOVW fn+16(FP), R18 394 395 MOVW $1234, R1 396 397 MOVW R16, 0(R5) 398 MOVW R17, 4(R5) 399 MOVW R18, 8(R5) 400 401 MOVW R1, 12(R5) 402 403 MOVW $SYS_clone, R2 404 SYSCALL 405 BEQ R7, 2(PC) 406 SUBU R2, R0, R2 // caller expects negative errno 407 408 // In parent, return. 409 BEQ R2, 3(PC) 410 MOVW R2, ret+20(FP) 411 RET 412 413 // In child, on new stack. 414 // Check that SP is as we expect 415 NOP R29 // tell vet R29/SP changed - stop checking offsets 416 MOVW 12(R29), R16 417 MOVW $1234, R1 418 BEQ R16, R1, 2(PC) 419 MOVW (R0), R0 420 421 // Initialize m->procid to Linux tid 422 MOVW $SYS_gettid, R2 423 SYSCALL 424 425 MOVW 0(R29), R16 // m 426 MOVW 4(R29), R17 // g 427 MOVW 8(R29), R18 // fn 428 429 BEQ R16, nog 430 BEQ R17, nog 431 432 MOVW R2, m_procid(R16) 433 434 // In child, set up new stack 435 MOVW R16, g_m(R17) 436 MOVW R17, g 437 438// TODO(mips32): doesn't have runtime·stackcheck(SB) 439 440nog: 441 // Call fn 442 ADDU $32, R29 443 JAL (R18) 444 445 // It shouldn't return. If it does, exit that thread. 446 ADDU $-32, R29 447 MOVW $0xf4, R4 448 MOVW $SYS_exit, R2 449 SYSCALL 450 UNDEF 451 452TEXT runtime·sigaltstack(SB),NOSPLIT,$0 453 MOVW new+0(FP), R4 454 MOVW old+4(FP), R5 455 MOVW $SYS_sigaltstack, R2 456 SYSCALL 457 BEQ R7, 2(PC) 458 UNDEF // crash 459 RET 460 461TEXT runtime·osyield(SB),NOSPLIT,$0 462 MOVW $SYS_sched_yield, R2 463 SYSCALL 464 RET 465 466TEXT runtime·sched_getaffinity(SB),NOSPLIT,$0-16 467 MOVW pid+0(FP), R4 468 MOVW len+4(FP), R5 469 MOVW buf+8(FP), R6 470 MOVW $SYS_sched_getaffinity, R2 471 SYSCALL 472 BEQ R7, 2(PC) 473 SUBU R2, R0, R2 // caller expects negative errno 474 MOVW R2, ret+12(FP) 475 RET 476 477// int32 runtime·epollcreate(int32 size); 478TEXT runtime·epollcreate(SB),NOSPLIT,$0-8 479 MOVW size+0(FP), R4 480 MOVW $SYS_epoll_create, R2 481 SYSCALL 482 BEQ R7, 2(PC) 483 SUBU R2, R0, R2 // caller expects negative errno 484 MOVW R2, ret+4(FP) 485 RET 486 487// int32 runtime·epollcreate1(int32 flags); 488TEXT runtime·epollcreate1(SB),NOSPLIT,$0-8 489 MOVW flags+0(FP), R4 490 MOVW $SYS_epoll_create1, R2 491 SYSCALL 492 BEQ R7, 2(PC) 493 SUBU R2, R0, R2 // caller expects negative errno 494 MOVW R2, ret+4(FP) 495 RET 496 497// func epollctl(epfd, op, fd int32, ev *epollEvent) int 498TEXT runtime·epollctl(SB),NOSPLIT,$0-20 499 MOVW epfd+0(FP), R4 500 MOVW op+4(FP), R5 501 MOVW fd+8(FP), R6 502 MOVW ev+12(FP), R7 503 MOVW $SYS_epoll_ctl, R2 504 SYSCALL 505 SUBU R2, R0, R2 // caller expects negative errno 506 MOVW R2, ret+16(FP) 507 RET 508 509// int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout); 510TEXT runtime·epollwait(SB),NOSPLIT,$0-20 511 MOVW epfd+0(FP), R4 512 MOVW ev+4(FP), R5 513 MOVW nev+8(FP), R6 514 MOVW timeout+12(FP), R7 515 MOVW $SYS_epoll_wait, R2 516 SYSCALL 517 BEQ R7, 2(PC) 518 SUBU R2, R0, R2 // caller expects negative errno 519 MOVW R2, ret+16(FP) 520 RET 521 522// void runtime·closeonexec(int32 fd); 523TEXT runtime·closeonexec(SB),NOSPLIT,$0-4 524 MOVW fd+0(FP), R4 // fd 525 MOVW $2, R5 // F_SETFD 526 MOVW $1, R6 // FD_CLOEXEC 527 MOVW $SYS_fcntl, R2 528 SYSCALL 529 RET 530 531// func runtime·setNonblock(int32 fd) 532TEXT runtime·setNonblock(SB),NOSPLIT,$0-4 533 MOVW fd+0(FP), R4 // fd 534 MOVW $3, R5 // F_GETFL 535 MOVW $0, R6 536 MOVW $SYS_fcntl, R2 537 SYSCALL 538 MOVW $0x80, R6 // O_NONBLOCK 539 OR R2, R6 540 MOVW fd+0(FP), R4 // fd 541 MOVW $4, R5 // F_SETFL 542 MOVW $SYS_fcntl, R2 543 SYSCALL 544 RET 545 546// func sbrk0() uintptr 547TEXT runtime·sbrk0(SB),NOSPLIT,$0-4 548 // Implemented as brk(NULL). 549 MOVW $0, R4 550 MOVW $SYS_brk, R2 551 SYSCALL 552 MOVW R2, ret+0(FP) 553 RET 554 555TEXT runtime·access(SB),$0-12 556 BREAK // unimplemented, only needed for android; declared in stubs_linux.go 557 MOVW R0, ret+8(FP) // for vet 558 RET 559 560TEXT runtime·connect(SB),$0-16 561 BREAK // unimplemented, only needed for android; declared in stubs_linux.go 562 MOVW R0, ret+12(FP) // for vet 563 RET 564 565TEXT runtime·socket(SB),$0-16 566 BREAK // unimplemented, only needed for android; declared in stubs_linux.go 567 MOVW R0, ret+12(FP) // for vet 568 RET 569