1// Copyright 2015 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#include "go_asm.h"
6#include "go_tls.h"
7#include "textflag.h"
8
9// from ../syscall/zsysnum_plan9.go
10
11#define SYS_SYSR1       0
12#define SYS_BIND        2
13#define SYS_CHDIR       3
14#define SYS_CLOSE       4
15#define SYS_DUP         5
16#define SYS_ALARM       6
17#define SYS_EXEC        7
18#define SYS_EXITS       8
19#define SYS_FAUTH       10
20#define SYS_SEGBRK      12
21#define SYS_OPEN        14
22#define SYS_OSEEK       16
23#define SYS_SLEEP       17
24#define SYS_RFORK       19
25#define SYS_PIPE        21
26#define SYS_CREATE      22
27#define SYS_FD2PATH     23
28#define SYS_BRK_        24
29#define SYS_REMOVE      25
30#define SYS_NOTIFY      28
31#define SYS_NOTED       29
32#define SYS_SEGATTACH   30
33#define SYS_SEGDETACH   31
34#define SYS_SEGFREE     32
35#define SYS_SEGFLUSH    33
36#define SYS_RENDEZVOUS  34
37#define SYS_UNMOUNT     35
38#define SYS_SEMACQUIRE  37
39#define SYS_SEMRELEASE  38
40#define SYS_SEEK        39
41#define SYS_FVERSION    40
42#define SYS_ERRSTR      41
43#define SYS_STAT        42
44#define SYS_FSTAT       43
45#define SYS_WSTAT       44
46#define SYS_FWSTAT      45
47#define SYS_MOUNT       46
48#define SYS_AWAIT       47
49#define SYS_PREAD       50
50#define SYS_PWRITE      51
51#define SYS_TSEMACQUIRE 52
52#define SYS_NSEC        53
53
54//func open(name *byte, mode, perm int32) int32
55TEXT runtime·open(SB),NOSPLIT,$0-16
56	MOVW    $SYS_OPEN, R0
57	SWI	$0
58	MOVW	R0, ret+12(FP)
59	RET
60
61//func pread(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32
62TEXT runtime·pread(SB),NOSPLIT,$0-24
63	MOVW    $SYS_PREAD, R0
64	SWI	$0
65	MOVW	R0, ret+20(FP)
66	RET
67
68//func pwrite(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32
69TEXT runtime·pwrite(SB),NOSPLIT,$0-24
70	MOVW    $SYS_PWRITE, R0
71	SWI	$0
72	MOVW	R0, ret+20(FP)
73	RET
74
75//func seek(fd int32, offset int64, whence int32) int64
76TEXT runtime·seek(SB),NOSPLIT,$0-24
77	MOVW	$ret_lo+16(FP), R0
78	MOVW	0(R13), R1
79	MOVW	R0, 0(R13)
80	MOVW.W	R1, -4(R13)
81	MOVW	$SYS_SEEK, R0
82	SWI	$0
83	MOVW.W	R1, 4(R13)
84	CMP	$-1, R0
85	MOVW.EQ	R0, ret_lo+16(FP)
86	MOVW.EQ	R0, ret_hi+20(FP)
87	RET
88
89//func closefd(fd int32) int32
90TEXT runtime·closefd(SB),NOSPLIT,$0-8
91	MOVW	$SYS_CLOSE, R0
92	SWI	$0
93	MOVW	R0, ret+4(FP)
94	RET
95
96//func exits(msg *byte)
97TEXT runtime·exits(SB),NOSPLIT,$0-4
98	MOVW    $SYS_EXITS, R0
99	SWI	$0
100	RET
101
102//func brk_(addr unsafe.Pointer) int32
103TEXT runtime·brk_(SB),NOSPLIT,$0-8
104	MOVW    $SYS_BRK_, R0
105	SWI	$0
106	MOVW	R0, ret+4(FP)
107	RET
108
109//func sleep(ms int32) int32
110TEXT runtime·sleep(SB),NOSPLIT,$0-8
111	MOVW    $SYS_SLEEP, R0
112	SWI	$0
113	MOVW	R0, ret+4(FP)
114	RET
115
116//func plan9_semacquire(addr *uint32, block int32) int32
117TEXT runtime·plan9_semacquire(SB),NOSPLIT,$0-12
118	MOVW	$SYS_SEMACQUIRE, R0
119	SWI	$0
120	MOVW	R0, ret+8(FP)
121	RET
122
123//func plan9_tsemacquire(addr *uint32, ms int32) int32
124TEXT runtime·plan9_tsemacquire(SB),NOSPLIT,$0-12
125	MOVW	$SYS_TSEMACQUIRE, R0
126	SWI	$0
127	MOVW	R0, ret+8(FP)
128	RET
129
130//func nsec(*int64) int64
131TEXT runtime·nsec(SB),NOSPLIT|NOFRAME,$0-12
132	MOVW	$SYS_NSEC, R0
133	SWI	$0
134	MOVW	arg+0(FP), R1
135	MOVW	0(R1), R0
136	MOVW	R0, ret_lo+4(FP)
137	MOVW	4(R1), R0
138	MOVW	R0, ret_hi+8(FP)
139	RET
140
141// func walltime1() (sec int64, nsec int32)
142TEXT runtime·walltime1(SB),NOSPLIT,$12-12
143	// use nsec system call to get current time in nanoseconds
144	MOVW	$sysnsec_lo-8(SP), R0	// destination addr
145	MOVW	R0,res-12(SP)
146	MOVW	$SYS_NSEC, R0
147	SWI	$0
148	MOVW	sysnsec_lo-8(SP), R1	// R1:R2 = nsec
149	MOVW	sysnsec_hi-4(SP), R2
150
151	// multiply nanoseconds by reciprocal of 10**9 (scaled by 2**61)
152	// to get seconds (96 bit scaled result)
153	MOVW	$0x89705f41, R3		// 2**61 * 10**-9
154	MULLU	R1,R3,(R6,R5)		// R5:R6:R7 = R1:R2 * R3
155	MOVW	$0,R7
156	MULALU	R2,R3,(R7,R6)
157
158	// unscale by discarding low 32 bits, shifting the rest by 29
159	MOVW	R6>>29,R6		// R6:R7 = (R5:R6:R7 >> 61)
160	ORR	R7<<3,R6
161	MOVW	R7>>29,R7
162
163	// subtract (10**9 * sec) from nsec to get nanosecond remainder
164	MOVW	$1000000000, R5		// 10**9
165	MULLU	R6,R5,(R9,R8)		// R8:R9 = R6:R7 * R5
166	MULA	R7,R5,R9,R9
167	SUB.S	R8,R1			// R1:R2 -= R8:R9
168	SBC	R9,R2
169
170	// because reciprocal was a truncated repeating fraction, quotient
171	// may be slightly too small -- adjust to make remainder < 10**9
172	CMP	R5,R1			// if remainder > 10**9
173	SUB.HS	R5,R1			//    remainder -= 10**9
174	ADD.HS	$1,R6			//    sec += 1
175
176	MOVW	R6,sec_lo+0(FP)
177	MOVW	R7,sec_hi+4(FP)
178	MOVW	R1,nsec+8(FP)
179	RET
180
181//func notify(fn unsafe.Pointer) int32
182TEXT runtime·notify(SB),NOSPLIT,$0-8
183	MOVW	$SYS_NOTIFY, R0
184	SWI	$0
185	MOVW	R0, ret+4(FP)
186	RET
187
188//func noted(mode int32) int32
189TEXT runtime·noted(SB),NOSPLIT,$0-8
190	MOVW	$SYS_NOTED, R0
191	SWI	$0
192	MOVW	R0, ret+4(FP)
193	RET
194
195//func plan9_semrelease(addr *uint32, count int32) int32
196TEXT runtime·plan9_semrelease(SB),NOSPLIT,$0-12
197	MOVW	$SYS_SEMRELEASE, R0
198	SWI	$0
199	MOVW	R0, ret+8(FP)
200	RET
201
202//func rfork(flags int32) int32
203TEXT runtime·rfork(SB),NOSPLIT,$0-8
204	MOVW	$SYS_RFORK, R0
205	SWI	$0
206	MOVW	R0, ret+4(FP)
207	RET
208
209//func tstart_plan9(newm *m)
210TEXT runtime·tstart_plan9(SB),NOSPLIT,$4-4
211	MOVW	newm+0(FP), R1
212	MOVW	m_g0(R1), g
213
214	// Layout new m scheduler stack on os stack.
215	MOVW	R13, R0
216	MOVW	R0, g_stack+stack_hi(g)
217	SUB	$(64*1024), R0
218	MOVW	R0, (g_stack+stack_lo)(g)
219	MOVW	R0, g_stackguard0(g)
220	MOVW	R0, g_stackguard1(g)
221
222	// Initialize procid from TOS struct.
223	MOVW	_tos(SB), R0
224	MOVW	48(R0), R0
225	MOVW	R0, m_procid(R1)	// save pid as m->procid
226
227	BL	runtime·mstart(SB)
228
229	// Exit the thread.
230	MOVW	$0, R0
231	MOVW	R0, 4(R13)
232	CALL	runtime·exits(SB)
233	JMP	0(PC)
234
235//func sigtramp(ureg, note unsafe.Pointer)
236TEXT runtime·sigtramp(SB),NOSPLIT,$0-8
237	// check that g and m exist
238	CMP	$0, g
239	BEQ	4(PC)
240	MOVW	g_m(g), R0
241	CMP 	$0, R0
242	BNE	2(PC)
243	BL	runtime·badsignal2(SB)	// will exit
244
245	// save args
246	MOVW	ureg+0(FP), R1
247	MOVW	note+4(FP), R2
248
249	// change stack
250	MOVW	m_gsignal(R0), R3
251	MOVW	(g_stack+stack_hi)(R3), R13
252
253	// make room for args, retval and g
254	SUB	$24, R13
255
256	// save g
257	MOVW	g, R3
258	MOVW	R3, 20(R13)
259
260	// g = m->gsignal
261	MOVW	m_gsignal(R0), g
262
263	// load args and call sighandler
264	ADD	$4,R13,R5
265	MOVM.IA	[R1-R3], (R5)
266	BL	runtime·sighandler(SB)
267	MOVW	16(R13), R0			// retval
268
269	// restore g
270	MOVW	20(R13), g
271
272	// call noted(R0)
273	MOVW	R0, 4(R13)
274	BL	runtime·noted(SB)
275	RET
276
277//func sigpanictramp()
278TEXT  runtime·sigpanictramp(SB),NOSPLIT,$0-0
279	MOVW.W	R0, -4(R13)
280	B	runtime·sigpanic(SB)
281
282//func setfpmasks()
283// Only used by the 64-bit runtime.
284TEXT runtime·setfpmasks(SB),NOSPLIT,$0
285	RET
286
287#define ERRMAX 128	/* from os_plan9.h */
288
289// func errstr() string
290// Only used by package syscall.
291// Grab error string due to a syscall made
292// in entersyscall mode, without going
293// through the allocator (issue 4994).
294// See ../syscall/asm_plan9_arm.s:/·Syscall/
295TEXT runtime·errstr(SB),NOSPLIT,$0-8
296	MOVW	g_m(g), R0
297	MOVW	(m_mOS+mOS_errstr)(R0), R1
298	MOVW	R1, ret_base+0(FP)
299	MOVW	$ERRMAX, R2
300	MOVW	R2, ret_len+4(FP)
301	MOVW    $SYS_ERRSTR, R0
302	SWI	$0
303	MOVW	R1, R2
304	MOVBU	0(R2), R0
305	CMP	$0, R0
306	BEQ	3(PC)
307	ADD	$1, R2
308	B	-4(PC)
309	SUB	R1, R2
310	MOVW	R2, ret_len+4(FP)
311	RET
312
313TEXT ·publicationBarrier(SB),NOSPLIT|NOFRAME,$0-0
314	B	runtime·armPublicationBarrier(SB)
315
316// never called (cgo not supported)
317TEXT runtime·read_tls_fallback(SB),NOSPLIT|NOFRAME,$0
318	MOVW	$0, R0
319	MOVW	R0, (R0)
320	RET
321