|  | // Copyright 2015 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" | 
|  |  | 
|  | // from ../syscall/zsysnum_plan9.go | 
|  |  | 
|  | #define SYS_SYSR1       0 | 
|  | #define SYS_BIND        2 | 
|  | #define SYS_CHDIR       3 | 
|  | #define SYS_CLOSE       4 | 
|  | #define SYS_DUP         5 | 
|  | #define SYS_ALARM       6 | 
|  | #define SYS_EXEC        7 | 
|  | #define SYS_EXITS       8 | 
|  | #define SYS_FAUTH       10 | 
|  | #define SYS_SEGBRK      12 | 
|  | #define SYS_OPEN        14 | 
|  | #define SYS_OSEEK       16 | 
|  | #define SYS_SLEEP       17 | 
|  | #define SYS_RFORK       19 | 
|  | #define SYS_PIPE        21 | 
|  | #define SYS_CREATE      22 | 
|  | #define SYS_FD2PATH     23 | 
|  | #define SYS_BRK_        24 | 
|  | #define SYS_REMOVE      25 | 
|  | #define SYS_NOTIFY      28 | 
|  | #define SYS_NOTED       29 | 
|  | #define SYS_SEGATTACH   30 | 
|  | #define SYS_SEGDETACH   31 | 
|  | #define SYS_SEGFREE     32 | 
|  | #define SYS_SEGFLUSH    33 | 
|  | #define SYS_RENDEZVOUS  34 | 
|  | #define SYS_UNMOUNT     35 | 
|  | #define SYS_SEMACQUIRE  37 | 
|  | #define SYS_SEMRELEASE  38 | 
|  | #define SYS_SEEK        39 | 
|  | #define SYS_FVERSION    40 | 
|  | #define SYS_ERRSTR      41 | 
|  | #define SYS_STAT        42 | 
|  | #define SYS_FSTAT       43 | 
|  | #define SYS_WSTAT       44 | 
|  | #define SYS_FWSTAT      45 | 
|  | #define SYS_MOUNT       46 | 
|  | #define SYS_AWAIT       47 | 
|  | #define SYS_PREAD       50 | 
|  | #define SYS_PWRITE      51 | 
|  | #define SYS_TSEMACQUIRE 52 | 
|  | #define SYS_NSEC        53 | 
|  |  | 
|  | //func open(name *byte, mode, perm int32) int32 | 
|  | TEXT runtime·open(SB),NOSPLIT,$0-16 | 
|  | MOVW    $SYS_OPEN, R0 | 
|  | SWI	$0 | 
|  | MOVW	R0, ret+12(FP) | 
|  | RET | 
|  |  | 
|  | //func pread(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32 | 
|  | TEXT runtime·pread(SB),NOSPLIT,$0-24 | 
|  | MOVW    $SYS_PREAD, R0 | 
|  | SWI	$0 | 
|  | MOVW	R0, ret+20(FP) | 
|  | RET | 
|  |  | 
|  | //func pwrite(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32 | 
|  | TEXT runtime·pwrite(SB),NOSPLIT,$0-24 | 
|  | MOVW    $SYS_PWRITE, R0 | 
|  | SWI	$0 | 
|  | MOVW	R0, ret+20(FP) | 
|  | RET | 
|  |  | 
|  | //func seek(fd int32, offset int64, whence int32) int64 | 
|  | TEXT runtime·seek(SB),NOSPLIT,$0-24 | 
|  | MOVW	$ret_lo+16(FP), R0 | 
|  | MOVW	0(R13), R1 | 
|  | MOVW	R0, 0(R13) | 
|  | MOVW.W	R1, -4(R13) | 
|  | MOVW	$SYS_SEEK, R0 | 
|  | SWI	$0 | 
|  | MOVW.W	R1, 4(R13) | 
|  | CMP	$-1, R0 | 
|  | MOVW.EQ	R0, ret_lo+16(FP) | 
|  | MOVW.EQ	R0, ret_hi+20(FP) | 
|  | RET | 
|  |  | 
|  | //func closefd(fd int32) int32 | 
|  | TEXT runtime·closefd(SB),NOSPLIT,$0-8 | 
|  | MOVW	$SYS_CLOSE, R0 | 
|  | SWI	$0 | 
|  | MOVW	R0, ret+4(FP) | 
|  | RET | 
|  |  | 
|  | //func exits(msg *byte) | 
|  | TEXT runtime·exits(SB),NOSPLIT,$0-4 | 
|  | MOVW    $SYS_EXITS, R0 | 
|  | SWI	$0 | 
|  | RET | 
|  |  | 
|  | //func brk_(addr unsafe.Pointer) int32 | 
|  | TEXT runtime·brk_(SB),NOSPLIT,$0-8 | 
|  | MOVW    $SYS_BRK_, R0 | 
|  | SWI	$0 | 
|  | MOVW	R0, ret+4(FP) | 
|  | RET | 
|  |  | 
|  | //func sleep(ms int32) int32 | 
|  | TEXT runtime·sleep(SB),NOSPLIT,$0-8 | 
|  | MOVW    $SYS_SLEEP, R0 | 
|  | SWI	$0 | 
|  | MOVW	R0, ret+4(FP) | 
|  | RET | 
|  |  | 
|  | //func plan9_semacquire(addr *uint32, block int32) int32 | 
|  | TEXT runtime·plan9_semacquire(SB),NOSPLIT,$0-12 | 
|  | MOVW	$SYS_SEMACQUIRE, R0 | 
|  | SWI	$0 | 
|  | MOVW	R0, ret+8(FP) | 
|  | RET | 
|  |  | 
|  | //func plan9_tsemacquire(addr *uint32, ms int32) int32 | 
|  | TEXT runtime·plan9_tsemacquire(SB),NOSPLIT,$0-12 | 
|  | MOVW	$SYS_TSEMACQUIRE, R0 | 
|  | SWI	$0 | 
|  | MOVW	R0, ret+8(FP) | 
|  | RET | 
|  |  | 
|  | //func nsec(*int64) int64 | 
|  | TEXT runtime·nsec(SB),NOSPLIT|NOFRAME,$0-12 | 
|  | MOVW	$SYS_NSEC, R0 | 
|  | SWI	$0 | 
|  | MOVW	arg+0(FP), R1 | 
|  | MOVW	0(R1), R0 | 
|  | MOVW	R0, ret_lo+4(FP) | 
|  | MOVW	4(R1), R0 | 
|  | MOVW	R0, ret_hi+8(FP) | 
|  | RET | 
|  |  | 
|  | // func walltime1() (sec int64, nsec int32) | 
|  | TEXT runtime·walltime1(SB),NOSPLIT,$12-12 | 
|  | // use nsec system call to get current time in nanoseconds | 
|  | MOVW	$sysnsec_lo-8(SP), R0	// destination addr | 
|  | MOVW	R0,res-12(SP) | 
|  | MOVW	$SYS_NSEC, R0 | 
|  | SWI	$0 | 
|  | MOVW	sysnsec_lo-8(SP), R1	// R1:R2 = nsec | 
|  | MOVW	sysnsec_hi-4(SP), R2 | 
|  |  | 
|  | // multiply nanoseconds by reciprocal of 10**9 (scaled by 2**61) | 
|  | // to get seconds (96 bit scaled result) | 
|  | MOVW	$0x89705f41, R3		// 2**61 * 10**-9 | 
|  | MULLU	R1,R3,(R6,R5)		// R5:R6:R7 = R1:R2 * R3 | 
|  | MOVW	$0,R7 | 
|  | MULALU	R2,R3,(R7,R6) | 
|  |  | 
|  | // unscale by discarding low 32 bits, shifting the rest by 29 | 
|  | MOVW	R6>>29,R6		// R6:R7 = (R5:R6:R7 >> 61) | 
|  | ORR	R7<<3,R6 | 
|  | MOVW	R7>>29,R7 | 
|  |  | 
|  | // subtract (10**9 * sec) from nsec to get nanosecond remainder | 
|  | MOVW	$1000000000, R5		// 10**9 | 
|  | MULLU	R6,R5,(R9,R8)		// R8:R9 = R6:R7 * R5 | 
|  | MULA	R7,R5,R9,R9 | 
|  | SUB.S	R8,R1			// R1:R2 -= R8:R9 | 
|  | SBC	R9,R2 | 
|  |  | 
|  | // because reciprocal was a truncated repeating fraction, quotient | 
|  | // may be slightly too small -- adjust to make remainder < 10**9 | 
|  | CMP	R5,R1			// if remainder > 10**9 | 
|  | SUB.HS	R5,R1			//    remainder -= 10**9 | 
|  | ADD.HS	$1,R6			//    sec += 1 | 
|  |  | 
|  | MOVW	R6,sec_lo+0(FP) | 
|  | MOVW	R7,sec_hi+4(FP) | 
|  | MOVW	R1,nsec+8(FP) | 
|  | RET | 
|  |  | 
|  | //func notify(fn unsafe.Pointer) int32 | 
|  | TEXT runtime·notify(SB),NOSPLIT,$0-8 | 
|  | MOVW	$SYS_NOTIFY, R0 | 
|  | SWI	$0 | 
|  | MOVW	R0, ret+4(FP) | 
|  | RET | 
|  |  | 
|  | //func noted(mode int32) int32 | 
|  | TEXT runtime·noted(SB),NOSPLIT,$0-8 | 
|  | MOVW	$SYS_NOTED, R0 | 
|  | SWI	$0 | 
|  | MOVW	R0, ret+4(FP) | 
|  | RET | 
|  |  | 
|  | //func plan9_semrelease(addr *uint32, count int32) int32 | 
|  | TEXT runtime·plan9_semrelease(SB),NOSPLIT,$0-12 | 
|  | MOVW	$SYS_SEMRELEASE, R0 | 
|  | SWI	$0 | 
|  | MOVW	R0, ret+8(FP) | 
|  | RET | 
|  |  | 
|  | //func rfork(flags int32) int32 | 
|  | TEXT runtime·rfork(SB),NOSPLIT,$0-8 | 
|  | MOVW	$SYS_RFORK, R0 | 
|  | SWI	$0 | 
|  | MOVW	R0, ret+4(FP) | 
|  | RET | 
|  |  | 
|  | //func tstart_plan9(newm *m) | 
|  | TEXT runtime·tstart_plan9(SB),NOSPLIT,$4-4 | 
|  | MOVW	newm+0(FP), R1 | 
|  | MOVW	m_g0(R1), g | 
|  |  | 
|  | // Layout new m scheduler stack on os stack. | 
|  | MOVW	R13, R0 | 
|  | MOVW	R0, g_stack+stack_hi(g) | 
|  | SUB	$(64*1024), R0 | 
|  | MOVW	R0, (g_stack+stack_lo)(g) | 
|  | MOVW	R0, g_stackguard0(g) | 
|  | MOVW	R0, g_stackguard1(g) | 
|  |  | 
|  | // Initialize procid from TOS struct. | 
|  | MOVW	_tos(SB), R0 | 
|  | MOVW	48(R0), R0 | 
|  | MOVW	R0, m_procid(R1)	// save pid as m->procid | 
|  |  | 
|  | BL	runtime·mstart(SB) | 
|  |  | 
|  | // Exit the thread. | 
|  | MOVW	$0, R0 | 
|  | MOVW	R0, 4(R13) | 
|  | CALL	runtime·exits(SB) | 
|  | JMP	0(PC) | 
|  |  | 
|  | //func sigtramp(ureg, note unsafe.Pointer) | 
|  | TEXT runtime·sigtramp(SB),NOSPLIT,$0-8 | 
|  | // check that g and m exist | 
|  | CMP	$0, g | 
|  | BEQ	4(PC) | 
|  | MOVW	g_m(g), R0 | 
|  | CMP 	$0, R0 | 
|  | BNE	2(PC) | 
|  | BL	runtime·badsignal2(SB)	// will exit | 
|  |  | 
|  | // save args | 
|  | MOVW	ureg+0(FP), R1 | 
|  | MOVW	note+4(FP), R2 | 
|  |  | 
|  | // change stack | 
|  | MOVW	m_gsignal(R0), R3 | 
|  | MOVW	(g_stack+stack_hi)(R3), R13 | 
|  |  | 
|  | // make room for args, retval and g | 
|  | SUB	$24, R13 | 
|  |  | 
|  | // save g | 
|  | MOVW	g, R3 | 
|  | MOVW	R3, 20(R13) | 
|  |  | 
|  | // g = m->gsignal | 
|  | MOVW	m_gsignal(R0), g | 
|  |  | 
|  | // load args and call sighandler | 
|  | ADD	$4,R13,R5 | 
|  | MOVM.IA	[R1-R3], (R5) | 
|  | BL	runtime·sighandler(SB) | 
|  | MOVW	16(R13), R0			// retval | 
|  |  | 
|  | // restore g | 
|  | MOVW	20(R13), g | 
|  |  | 
|  | // call noted(R0) | 
|  | MOVW	R0, 4(R13) | 
|  | BL	runtime·noted(SB) | 
|  | RET | 
|  |  | 
|  | //func sigpanictramp() | 
|  | TEXT  runtime·sigpanictramp(SB),NOSPLIT,$0-0 | 
|  | MOVW.W	R0, -4(R13) | 
|  | B	runtime·sigpanic(SB) | 
|  |  | 
|  | //func setfpmasks() | 
|  | // Only used by the 64-bit runtime. | 
|  | TEXT runtime·setfpmasks(SB),NOSPLIT,$0 | 
|  | RET | 
|  |  | 
|  | #define ERRMAX 128	/* from os_plan9.h */ | 
|  |  | 
|  | // func errstr() string | 
|  | // Only used by package syscall. | 
|  | // Grab error string due to a syscall made | 
|  | // in entersyscall mode, without going | 
|  | // through the allocator (issue 4994). | 
|  | // See ../syscall/asm_plan9_arm.s:/·Syscall/ | 
|  | TEXT runtime·errstr(SB),NOSPLIT,$0-8 | 
|  | MOVW	g_m(g), R0 | 
|  | MOVW	(m_mOS+mOS_errstr)(R0), R1 | 
|  | MOVW	R1, ret_base+0(FP) | 
|  | MOVW	$ERRMAX, R2 | 
|  | MOVW	R2, ret_len+4(FP) | 
|  | MOVW    $SYS_ERRSTR, R0 | 
|  | SWI	$0 | 
|  | MOVW	R1, R2 | 
|  | MOVBU	0(R2), R0 | 
|  | CMP	$0, R0 | 
|  | BEQ	3(PC) | 
|  | ADD	$1, R2 | 
|  | B	-4(PC) | 
|  | SUB	R1, R2 | 
|  | MOVW	R2, ret_len+4(FP) | 
|  | RET | 
|  |  | 
|  | TEXT ·publicationBarrier(SB),NOSPLIT|NOFRAME,$0-0 | 
|  | B	runtime·armPublicationBarrier(SB) | 
|  |  | 
|  | // never called (cgo not supported) | 
|  | TEXT runtime·read_tls_fallback(SB),NOSPLIT|NOFRAME,$0 | 
|  | MOVW	$0, R0 | 
|  | MOVW	R0, (R0) | 
|  | RET |