| // 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 | 
 |  | 
 | // func exitThread(wait *uint32) | 
 | TEXT runtime·exitThread(SB),NOSPLIT,$4-4 | 
 | 	MOVW wait+0(FP), R0 | 
 | 	// SYS_thread_exit will clear *wait when the stack is free. | 
 | 	NACL_SYSCALL(SYS_thread_exit) | 
 | 	JMP 0(PC) | 
 |  | 
 | 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 | 
 | 	MOVW	$0, R1 | 
 | 	RSB.HI	$0, R0 | 
 | 	MOVW.HI	R0, R1		// if error, put in R1 | 
 | 	MOVW.HI	$0, R0 | 
 | 	MOVW	R0, p+24(FP) | 
 | 	MOVW	R1, err+28(FP) | 
 | 	RET | 
 |  | 
 | TEXT runtime·walltime(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_lo+0(FP) | 
 | 	MOVW	R1, sec_hi+4(FP) | 
 | 	MOVW	R2, nsec+8(FP) | 
 | 	RET | 
 |  | 
 | TEXT syscall·now(SB),NOSPLIT,$0 | 
 | 	B runtime·walltime(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 arg_base+0(FP), R0 | 
 | 	MOVW arg_len+4(FP), R1 | 
 | 	NACL_SYSCALL(SYS_get_random_bytes) | 
 | 	RET | 
 |  | 
 | // Likewise, this is only valid for ARMv7+, but that's okay. | 
 | TEXT ·publicationBarrier(SB),NOSPLIT|NOFRAME,$0-0 | 
 | 	B	runtime·armPublicationBarrier(SB) | 
 |  | 
 | TEXT runtime·read_tls_fallback(SB),NOSPLIT|NOFRAME,$0 | 
 | 	WORD $0xe7fedef0 // NACL_INSTR_ARM_ABORT_NOW (UDF #0xEDE0) |