Text file src/pkg/runtime/sys_nacl_386.s
1 // Copyright 2013 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 #include "syscall_nacl.h"
9
10 #define NACL_SYSCALL(code) \
11 MOVL $(0x10000 + ((code)<<5)), AX; CALL AX
12
13 TEXT runtime·exit(SB),NOSPLIT,$4
14 MOVL code+0(FP), AX
15 MOVL AX, 0(SP)
16 NACL_SYSCALL(SYS_exit)
17 JMP 0(PC)
18
19 // func exitThread(wait *uint32)
20 TEXT runtime·exitThread(SB),NOSPLIT,$4-4
21 MOVL wait+0(FP), AX
22 // SYS_thread_exit will clear *wait when the stack is free.
23 MOVL AX, 0(SP)
24 NACL_SYSCALL(SYS_thread_exit)
25 JMP 0(PC)
26
27 TEXT runtime·open(SB),NOSPLIT,$12
28 MOVL name+0(FP), AX
29 MOVL AX, 0(SP)
30 MOVL mode+4(FP), AX
31 MOVL AX, 4(SP)
32 MOVL perm+8(FP), AX
33 MOVL AX, 8(SP)
34 NACL_SYSCALL(SYS_open)
35 MOVL AX, ret+12(FP)
36 RET
37
38 TEXT runtime·closefd(SB),NOSPLIT,$4
39 MOVL fd+0(FP), AX
40 MOVL AX, 0(SP)
41 NACL_SYSCALL(SYS_close)
42 MOVL AX, ret+4(FP)
43 RET
44
45 TEXT runtime·read(SB),NOSPLIT,$12
46 MOVL fd+0(FP), AX
47 MOVL AX, 0(SP)
48 MOVL p+4(FP), AX
49 MOVL AX, 4(SP)
50 MOVL n+8(FP), AX
51 MOVL AX, 8(SP)
52 NACL_SYSCALL(SYS_read)
53 MOVL AX, ret+12(FP)
54 RET
55
56 TEXT syscall·naclWrite(SB), NOSPLIT, $16-16
57 MOVL arg1+0(FP), DI
58 MOVL arg2+4(FP), SI
59 MOVL arg3+8(FP), DX
60 MOVL DI, 0(SP)
61 MOVL SI, 4(SP)
62 MOVL DX, 8(SP)
63 CALL runtime·write(SB)
64 MOVL AX, ret+16(FP)
65 RET
66
67 TEXT runtime·write(SB),NOSPLIT,$12
68 MOVL fd+0(FP), AX
69 MOVL AX, 0(SP)
70 MOVL p+4(FP), AX
71 MOVL AX, 4(SP)
72 MOVL n+8(FP), AX
73 MOVL AX, 8(SP)
74 NACL_SYSCALL(SYS_write)
75 MOVL AX, ret+12(FP)
76 RET
77
78 TEXT runtime·nacl_exception_stack(SB),NOSPLIT,$8
79 MOVL p+0(FP), AX
80 MOVL AX, 0(SP)
81 MOVL size+4(FP), AX
82 MOVL AX, 4(SP)
83 NACL_SYSCALL(SYS_exception_stack)
84 MOVL AX, ret+8(FP)
85 RET
86
87 TEXT runtime·nacl_exception_handler(SB),NOSPLIT,$8
88 MOVL fn+0(FP), AX
89 MOVL AX, 0(SP)
90 MOVL arg+4(FP), AX
91 MOVL AX, 4(SP)
92 NACL_SYSCALL(SYS_exception_handler)
93 MOVL AX, ret+8(FP)
94 RET
95
96 TEXT runtime·nacl_sem_create(SB),NOSPLIT,$4
97 MOVL flag+0(FP), AX
98 MOVL AX, 0(SP)
99 NACL_SYSCALL(SYS_sem_create)
100 MOVL AX, ret+4(FP)
101 RET
102
103 TEXT runtime·nacl_sem_wait(SB),NOSPLIT,$4
104 MOVL sem+0(FP), AX
105 MOVL AX, 0(SP)
106 NACL_SYSCALL(SYS_sem_wait)
107 MOVL AX, ret+4(FP)
108 RET
109
110 TEXT runtime·nacl_sem_post(SB),NOSPLIT,$4
111 MOVL sem+0(FP), AX
112 MOVL AX, 0(SP)
113 NACL_SYSCALL(SYS_sem_post)
114 MOVL AX, ret+4(FP)
115 RET
116
117 TEXT runtime·nacl_mutex_create(SB),NOSPLIT,$4
118 MOVL flag+0(FP), AX
119 MOVL AX, 0(SP)
120 NACL_SYSCALL(SYS_mutex_create)
121 MOVL AX, ret+4(FP)
122 RET
123
124 TEXT runtime·nacl_mutex_lock(SB),NOSPLIT,$4
125 MOVL mutex+0(FP), AX
126 MOVL AX, 0(SP)
127 NACL_SYSCALL(SYS_mutex_lock)
128 MOVL AX, ret+4(FP)
129 RET
130
131 TEXT runtime·nacl_mutex_trylock(SB),NOSPLIT,$4
132 MOVL mutex+0(FP), AX
133 MOVL AX, 0(SP)
134 NACL_SYSCALL(SYS_mutex_trylock)
135 MOVL AX, ret+4(FP)
136 RET
137
138 TEXT runtime·nacl_mutex_unlock(SB),NOSPLIT,$4
139 MOVL mutex+0(FP), AX
140 MOVL AX, 0(SP)
141 NACL_SYSCALL(SYS_mutex_unlock)
142 MOVL AX, ret+4(FP)
143 RET
144
145 TEXT runtime·nacl_cond_create(SB),NOSPLIT,$4
146 MOVL flag+0(FP), AX
147 MOVL AX, 0(SP)
148 NACL_SYSCALL(SYS_cond_create)
149 MOVL AX, ret+4(FP)
150 RET
151
152 TEXT runtime·nacl_cond_wait(SB),NOSPLIT,$8
153 MOVL cond+0(FP), AX
154 MOVL AX, 0(SP)
155 MOVL n+4(FP), AX
156 MOVL AX, 4(SP)
157 NACL_SYSCALL(SYS_cond_wait)
158 MOVL AX, ret+8(FP)
159 RET
160
161 TEXT runtime·nacl_cond_signal(SB),NOSPLIT,$4
162 MOVL cond+0(FP), AX
163 MOVL AX, 0(SP)
164 NACL_SYSCALL(SYS_cond_signal)
165 MOVL AX, ret+4(FP)
166 RET
167
168 TEXT runtime·nacl_cond_broadcast(SB),NOSPLIT,$4
169 MOVL cond+0(FP), AX
170 MOVL AX, 0(SP)
171 NACL_SYSCALL(SYS_cond_broadcast)
172 MOVL AX, ret+4(FP)
173 RET
174
175 TEXT runtime·nacl_cond_timed_wait_abs(SB),NOSPLIT,$12
176 MOVL cond+0(FP), AX
177 MOVL AX, 0(SP)
178 MOVL lock+4(FP), AX
179 MOVL AX, 4(SP)
180 MOVL ts+8(FP), AX
181 MOVL AX, 8(SP)
182 NACL_SYSCALL(SYS_cond_timed_wait_abs)
183 MOVL AX, ret+12(FP)
184 RET
185
186 TEXT runtime·nacl_thread_create(SB),NOSPLIT,$16
187 MOVL fn+0(FP), AX
188 MOVL AX, 0(SP)
189 MOVL stk+4(FP), AX
190 MOVL AX, 4(SP)
191 MOVL tls+8(FP), AX
192 MOVL AX, 8(SP)
193 MOVL xx+12(FP), AX
194 MOVL AX, 12(SP)
195 NACL_SYSCALL(SYS_thread_create)
196 MOVL AX, ret+16(FP)
197 RET
198
199 TEXT runtime·mstart_nacl(SB),NOSPLIT,$0
200 JMP runtime·mstart(SB)
201
202 TEXT runtime·nacl_nanosleep(SB),NOSPLIT,$8
203 MOVL ts+0(FP), AX
204 MOVL AX, 0(SP)
205 MOVL extra+4(FP), AX
206 MOVL AX, 4(SP)
207 NACL_SYSCALL(SYS_nanosleep)
208 MOVL AX, ret+8(FP)
209 RET
210
211 TEXT runtime·osyield(SB),NOSPLIT,$0
212 NACL_SYSCALL(SYS_sched_yield)
213 RET
214
215 TEXT runtime·mmap(SB),NOSPLIT,$32
216 MOVL addr+0(FP), AX
217 MOVL AX, 0(SP)
218 MOVL n+4(FP), AX
219 MOVL AX, 4(SP)
220 MOVL prot+8(FP), AX
221 MOVL AX, 8(SP)
222 MOVL flags+12(FP), AX
223 MOVL AX, 12(SP)
224 MOVL fd+16(FP), AX
225 MOVL AX, 16(SP)
226 MOVL off+20(FP), AX
227 MOVL AX, 24(SP)
228 MOVL $0, 28(SP)
229 LEAL 24(SP), AX
230 MOVL AX, 20(SP)
231 NACL_SYSCALL(SYS_mmap)
232 CMPL AX, $-4095
233 JNA ok
234 NEGL AX
235 MOVL $0, p+24(FP)
236 MOVL AX, err+28(FP)
237 RET
238 ok:
239 MOVL AX, p+24(FP)
240 MOVL $0, err+28(FP)
241 RET
242
243 TEXT runtime·walltime(SB),NOSPLIT,$20
244 MOVL $0, 0(SP) // real time clock
245 LEAL 8(SP), AX
246 MOVL AX, 4(SP) // timespec
247 NACL_SYSCALL(SYS_clock_gettime)
248 MOVL 8(SP), AX // low 32 sec
249 MOVL 12(SP), CX // high 32 sec
250 MOVL 16(SP), BX // nsec
251
252 // sec is in AX, nsec in BX
253 MOVL AX, sec_lo+0(FP)
254 MOVL CX, sec_hi+4(FP)
255 MOVL BX, nsec+8(FP)
256 RET
257
258 TEXT syscall·now(SB),NOSPLIT,$0
259 JMP runtime·walltime(SB)
260
261 TEXT runtime·nanotime(SB),NOSPLIT,$20
262 MOVL $0, 0(SP) // real time clock
263 LEAL 8(SP), AX
264 MOVL AX, 4(SP) // timespec
265 NACL_SYSCALL(SYS_clock_gettime)
266 MOVL 8(SP), AX // low 32 sec
267 MOVL 16(SP), BX // nsec
268
269 // sec is in AX, nsec in BX
270 // convert to DX:AX nsec
271 MOVL $1000000000, CX
272 MULL CX
273 ADDL BX, AX
274 ADCL $0, DX
275
276 MOVL AX, ret_lo+0(FP)
277 MOVL DX, ret_hi+4(FP)
278 RET
279
280 TEXT runtime·setldt(SB),NOSPLIT,$8
281 MOVL base+4(FP), BX
282 ADDL $0x8, BX
283 MOVL BX, 0(SP)
284 NACL_SYSCALL(SYS_tls_init)
285 RET
286
287 TEXT runtime·sigtramp(SB),NOSPLIT,$0
288 get_tls(CX)
289
290 // check that g exists
291 MOVL g(CX), DI
292 CMPL DI, $0
293 JNE 6(PC)
294 MOVL $11, BX
295 MOVL $0, 0(SP)
296 MOVL $runtime·badsignal(SB), AX
297 CALL AX
298 JMP ret
299
300 // save g
301 NOP SP // tell vet SP changed - stop checking offsets
302 MOVL DI, 20(SP)
303
304 // g = m->gsignal
305 MOVL g_m(DI), BX
306 MOVL m_gsignal(BX), BX
307 MOVL BX, g(CX)
308
309 // copy arguments for sighandler
310 MOVL $11, 0(SP) // signal
311 MOVL $0, 4(SP) // siginfo
312 LEAL 8(SP), AX
313 MOVL AX, 8(SP) // context
314 MOVL DI, 12(SP) // g
315
316 CALL runtime·sighandler(SB)
317
318 // restore g
319 get_tls(CX)
320 MOVL 20(SP), BX
321 MOVL BX, g(CX)
322
323 ret:
324 // Enable exceptions again.
325 NACL_SYSCALL(SYS_exception_clear_flag)
326
327 // NaCl has abdicated its traditional operating system responsibility
328 // and declined to implement 'sigreturn'. Instead the only way to return
329 // to the execution of our program is to restore the registers ourselves.
330 // Unfortunately, that is impossible to do with strict fidelity, because
331 // there is no way to do the final update of PC that ends the sequence
332 // without either (1) jumping to a register, in which case the register ends
333 // holding the PC value instead of its intended value or (2) storing the PC
334 // on the stack and using RET, which imposes the requirement that SP is
335 // valid and that is okay to smash the word below it. The second would
336 // normally be the lesser of the two evils, except that on NaCl, the linker
337 // must rewrite RET into "POP reg; AND $~31, reg; JMP reg", so either way
338 // we are going to lose a register as a result of the incoming signal.
339 // Similarly, there is no way to restore EFLAGS; the usual way is to use
340 // POPFL, but NaCl rejects that instruction. We could inspect the bits and
341 // execute a sequence of instructions designed to recreate those flag
342 // settings, but that's a lot of work.
343 //
344 // Thankfully, Go's signal handlers never try to return directly to the
345 // executing code, so all the registers and EFLAGS are dead and can be
346 // smashed. The only registers that matter are the ones that are setting
347 // up for the simulated call that the signal handler has created.
348 // Today those registers are just PC and SP, but in case additional registers
349 // are relevant in the future (for example DX is the Go func context register)
350 // we restore as many registers as possible.
351 //
352 // We smash BP, because that's what the linker smashes during RET.
353 //
354 LEAL 72(SP), BP
355 MOVL 0(BP), AX
356 MOVL 4(BP), CX
357 MOVL 8(BP), DX
358 MOVL 12(BP), BX
359 MOVL 16(BP), SP
360 // 20(BP) is saved BP, never to be seen again
361 MOVL 24(BP), SI
362 MOVL 28(BP), DI
363 // 36(BP) is saved EFLAGS, never to be seen again
364 MOVL 32(BP), BP // saved PC
365 JMP BP
366
367 // func getRandomData([]byte)
368 TEXT runtime·getRandomData(SB),NOSPLIT,$8-12
369 MOVL arg_base+0(FP), AX
370 MOVL AX, 0(SP)
371 MOVL arg_len+4(FP), AX
372 MOVL AX, 4(SP)
373 NACL_SYSCALL(SYS_get_random_bytes)
374 RET
View as plain text