// 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)