| // Copyright 2014 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| #include "go_asm.h" |
| #include "go_tls.h" |
| #include "textflag.h" |
| #include "syscall_nacl.h" |
| |
| #define NACL_SYSCALL(code) \ |
| MOVW $(0x10000 + ((code)<<5)), R8; BL (R8) |
| |
| TEXT runtime·exit(SB),NOSPLIT,$0 |
| MOVW code+0(FP), R0 |
| NACL_SYSCALL(SYS_exit) |
| RET |
| |
| TEXT runtime·exit1(SB),NOSPLIT,$0 |
| MOVW code+0(FP), R0 |
| NACL_SYSCALL(SYS_thread_exit) |
| RET |
| |
| TEXT runtime·open(SB),NOSPLIT,$0 |
| MOVW name+0(FP), R0 |
| MOVW name+0(FP), R1 |
| MOVW name+0(FP), R2 |
| NACL_SYSCALL(SYS_open) |
| MOVW R0, ret+12(FP) |
| RET |
| |
| TEXT runtime·closefd(SB),NOSPLIT,$0 |
| MOVW fd+0(FP), R0 |
| NACL_SYSCALL(SYS_close) |
| MOVW R0, ret+4(FP) |
| RET |
| |
| TEXT runtime·read(SB),NOSPLIT,$0 |
| MOVW fd+0(FP), R0 |
| MOVW p+4(FP), R1 |
| MOVW n+8(FP), R2 |
| NACL_SYSCALL(SYS_read) |
| MOVW R0, ret+12(FP) |
| RET |
| |
| // func naclWrite(fd int, b []byte) int |
| TEXT syscall·naclWrite(SB),NOSPLIT,$0 |
| MOVW arg1+0(FP), R0 |
| MOVW arg2+4(FP), R1 |
| MOVW arg3+8(FP), R2 |
| NACL_SYSCALL(SYS_write) |
| MOVW R0, ret+16(FP) |
| RET |
| |
| TEXT runtime·write(SB),NOSPLIT,$0 |
| MOVW fd+0(FP), R0 |
| MOVW p+4(FP), R1 |
| MOVW n+8(FP), R2 |
| NACL_SYSCALL(SYS_write) |
| MOVW R0, ret+12(FP) |
| RET |
| |
| TEXT runtime·nacl_exception_stack(SB),NOSPLIT,$0 |
| MOVW p+0(FP), R0 |
| MOVW size+4(FP), R1 |
| NACL_SYSCALL(SYS_exception_stack) |
| MOVW R0, ret+8(FP) |
| RET |
| |
| TEXT runtime·nacl_exception_handler(SB),NOSPLIT,$0 |
| MOVW fn+0(FP), R0 |
| MOVW arg+4(FP), R1 |
| NACL_SYSCALL(SYS_exception_handler) |
| MOVW R0, ret+8(FP) |
| RET |
| |
| TEXT runtime·nacl_sem_create(SB),NOSPLIT,$0 |
| MOVW flag+0(FP), R0 |
| NACL_SYSCALL(SYS_sem_create) |
| MOVW R0, ret+4(FP) |
| RET |
| |
| TEXT runtime·nacl_sem_wait(SB),NOSPLIT,$0 |
| MOVW sem+0(FP), R0 |
| NACL_SYSCALL(SYS_sem_wait) |
| MOVW R0, ret+4(FP) |
| RET |
| |
| TEXT runtime·nacl_sem_post(SB),NOSPLIT,$0 |
| MOVW sem+0(FP), R0 |
| NACL_SYSCALL(SYS_sem_post) |
| MOVW R0, ret+4(FP) |
| RET |
| |
| TEXT runtime·nacl_mutex_create(SB),NOSPLIT,$0 |
| MOVW flag+0(FP), R0 |
| NACL_SYSCALL(SYS_mutex_create) |
| MOVW R0, ret+4(FP) |
| RET |
| |
| TEXT runtime·nacl_mutex_lock(SB),NOSPLIT,$0 |
| MOVW mutex+0(FP), R0 |
| NACL_SYSCALL(SYS_mutex_lock) |
| MOVW R0, ret+4(FP) |
| RET |
| |
| TEXT runtime·nacl_mutex_trylock(SB),NOSPLIT,$0 |
| MOVW mutex+0(FP), R0 |
| NACL_SYSCALL(SYS_mutex_trylock) |
| MOVW R0, ret+4(FP) |
| RET |
| |
| TEXT runtime·nacl_mutex_unlock(SB),NOSPLIT,$0 |
| MOVW mutex+0(FP), R0 |
| NACL_SYSCALL(SYS_mutex_unlock) |
| MOVW R0, ret+4(FP) |
| RET |
| |
| TEXT runtime·nacl_cond_create(SB),NOSPLIT,$0 |
| MOVW flag+0(FP), R0 |
| NACL_SYSCALL(SYS_cond_create) |
| MOVW R0, ret+4(FP) |
| RET |
| |
| TEXT runtime·nacl_cond_wait(SB),NOSPLIT,$0 |
| MOVW cond+0(FP), R0 |
| MOVW n+4(FP), R1 |
| NACL_SYSCALL(SYS_cond_wait) |
| MOVW R0, ret+8(FP) |
| RET |
| |
| TEXT runtime·nacl_cond_signal(SB),NOSPLIT,$0 |
| MOVW cond+0(FP), R0 |
| NACL_SYSCALL(SYS_cond_signal) |
| MOVW R0, ret+4(FP) |
| RET |
| |
| TEXT runtime·nacl_cond_broadcast(SB),NOSPLIT,$0 |
| MOVW cond+0(FP), R0 |
| NACL_SYSCALL(SYS_cond_broadcast) |
| MOVW R0, ret+4(FP) |
| RET |
| |
| TEXT runtime·nacl_cond_timed_wait_abs(SB),NOSPLIT,$0 |
| MOVW cond+0(FP), R0 |
| MOVW lock+4(FP), R1 |
| MOVW ts+8(FP), R2 |
| NACL_SYSCALL(SYS_cond_timed_wait_abs) |
| MOVW R0, ret+12(FP) |
| RET |
| |
| TEXT runtime·nacl_thread_create(SB),NOSPLIT,$0 |
| MOVW fn+0(FP), R0 |
| MOVW stk+4(FP), R1 |
| MOVW tls+8(FP), R2 |
| MOVW xx+12(FP), R3 |
| NACL_SYSCALL(SYS_thread_create) |
| MOVW R0, ret+16(FP) |
| RET |
| |
| TEXT runtime·mstart_nacl(SB),NOSPLIT,$0 |
| MOVW 0(R9), R0 // TLS |
| MOVW -8(R0), R1 // g |
| MOVW -4(R0), R2 // m |
| MOVW R2, g_m(R1) |
| MOVW R1, g |
| B runtime·mstart(SB) |
| |
| TEXT runtime·nacl_nanosleep(SB),NOSPLIT,$0 |
| MOVW ts+0(FP), R0 |
| MOVW extra+4(FP), R1 |
| NACL_SYSCALL(SYS_nanosleep) |
| MOVW R0, ret+8(FP) |
| RET |
| |
| TEXT runtime·osyield(SB),NOSPLIT,$0 |
| NACL_SYSCALL(SYS_sched_yield) |
| RET |
| |
| TEXT runtime·mmap(SB),NOSPLIT,$8 |
| MOVW addr+0(FP), R0 |
| MOVW n+4(FP), R1 |
| MOVW prot+8(FP), R2 |
| MOVW flags+12(FP), R3 |
| MOVW fd+16(FP), R4 |
| // arg6:offset should be passed as a pointer (to int64) |
| MOVW off+20(FP), R5 |
| MOVW R5, 4(R13) |
| MOVW $0, R6 |
| MOVW R6, 8(R13) |
| MOVW $4(R13), R5 |
| MOVM.DB.W [R4,R5], (R13) // arg5 and arg6 are passed on stack |
| NACL_SYSCALL(SYS_mmap) |
| MOVM.IA.W (R13), [R4, R5] |
| CMP $-4095, R0 |
| RSB.HI $0, R0 |
| MOVW R0, ret+24(FP) |
| RET |
| |
| TEXT time·now(SB),NOSPLIT,$16 |
| MOVW $0, R0 // real time clock |
| MOVW $4(R13), R1 |
| NACL_SYSCALL(SYS_clock_gettime) |
| MOVW 4(R13), R0 // low 32-bit sec |
| MOVW 8(R13), R1 // high 32-bit sec |
| MOVW 12(R13), R2 // nsec |
| MOVW R0, sec+0(FP) |
| MOVW R1, sec+4(FP) |
| MOVW R2, sec+8(FP) |
| RET |
| |
| TEXT syscall·now(SB),NOSPLIT,$0 |
| B time·now(SB) |
| |
| TEXT runtime·nacl_clock_gettime(SB),NOSPLIT,$0 |
| MOVW arg1+0(FP), R0 |
| MOVW arg2+4(FP), R1 |
| NACL_SYSCALL(SYS_clock_gettime) |
| MOVW R0, ret+8(FP) |
| RET |
| |
| // int64 nanotime(void) so really |
| // void nanotime(int64 *nsec) |
| TEXT runtime·nanotime(SB),NOSPLIT,$16 |
| MOVW $0, R0 // real time clock |
| MOVW $4(R13), R1 |
| NACL_SYSCALL(SYS_clock_gettime) |
| MOVW 4(R13), R0 // low 32-bit sec |
| MOVW 8(R13), R1 // high 32-bit sec (ignored for now) |
| MOVW 12(R13), R2 // nsec |
| MOVW $1000000000, R3 |
| MULLU R0, R3, (R1, R0) |
| MOVW $0, R4 |
| ADD.S R2, R0 |
| ADC R4, R1 |
| MOVW R0, ret_lo+0(FP) |
| MOVW R1, ret_hi+4(FP) |
| RET |
| |
| TEXT runtime·sigtramp(SB),NOSPLIT,$80 |
| // load g from thread context |
| MOVW $ctxt+-4(FP), R0 |
| MOVW (16*4+10*4)(R0), g |
| |
| // check that g exists |
| CMP $0, g |
| BNE 4(PC) |
| MOVW $runtime·badsignal2(SB), R11 |
| BL (R11) |
| RET |
| |
| // save g |
| MOVW g, R3 |
| MOVW g, 20(R13) |
| |
| // g = m->gsignal |
| MOVW g_m(g), R8 |
| MOVW m_gsignal(R8), g |
| |
| // copy arguments for call to sighandler |
| MOVW $11, R0 |
| MOVW R0, 4(R13) // signal |
| MOVW $0, R0 |
| MOVW R0, 8(R13) // siginfo |
| MOVW $ctxt+-4(FP), R0 |
| MOVW R0, 12(R13) // context |
| MOVW R3, 16(R13) // g |
| |
| BL runtime·sighandler(SB) |
| |
| // restore g |
| MOVW 20(R13), g |
| |
| // Enable exceptions again. |
| NACL_SYSCALL(SYS_exception_clear_flag) |
| |
| // Restore registers as best we can. Impossible to do perfectly. |
| // See comment in sys_nacl_386.s for extended rationale. |
| MOVW $ctxt+-4(FP), R1 |
| ADD $64, R1 |
| MOVW (0*4)(R1), R0 |
| MOVW (2*4)(R1), R2 |
| MOVW (3*4)(R1), R3 |
| MOVW (4*4)(R1), R4 |
| MOVW (5*4)(R1), R5 |
| MOVW (6*4)(R1), R6 |
| MOVW (7*4)(R1), R7 |
| MOVW (8*4)(R1), R8 |
| // cannot write to R9 |
| MOVW (10*4)(R1), g |
| MOVW (11*4)(R1), R11 |
| MOVW (12*4)(R1), R12 |
| MOVW (13*4)(R1), R13 |
| MOVW (14*4)(R1), R14 |
| MOVW (15*4)(R1), R1 |
| B (R1) |
| |
| nog: |
| MOVW $0, R0 |
| RET |
| |
| TEXT runtime·nacl_sysinfo(SB),NOSPLIT,$16 |
| RET |
| |
| // func getRandomData([]byte) |
| TEXT runtime·getRandomData(SB),NOSPLIT,$0-12 |
| MOVW buf+0(FP), R0 |
| MOVW len+4(FP), R1 |
| NACL_SYSCALL(SYS_get_random_bytes) |
| RET |
| |
| TEXT runtime·casp1(SB),NOSPLIT,$0 |
| B runtime·cas(SB) |
| |
| // This is only valid for ARMv6+, however, NaCl/ARM is only defined |
| // for ARMv7A anyway. |
| // bool armcas(int32 *val, int32 old, int32 new) |
| // AtomiBLy: |
| // if(*val == old){ |
| // *val = new; |
| // return 1; |
| // }else |
| // return 0; |
| TEXT runtime·cas(SB),NOSPLIT,$0 |
| B runtime·armcas(SB) |
| |
| // Likewise, this is only valid for ARMv7+, but that's okay. |
| TEXT ·publicationBarrier(SB),NOSPLIT,$-4-0 |
| B runtime·armPublicationBarrier(SB) |
| |
| TEXT runtime·read_tls_fallback(SB),NOSPLIT,$-4 |
| WORD $0xe7fedef0 // NACL_INSTR_ARM_ABORT_NOW (UDF #0xEDE0) |