1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
|
// Copyright 2013 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 "zasm_GOOS_GOARCH.h"
#include "textflag.h"
#include "syscall_nacl.h"
#define NACL_SYSCALL(code) \
MOVL $(0x10000 + ((code)<<5)), AX; CALL AX
TEXT runtime·settls(SB),NOSPLIT,$0
MOVL DI, TLS // really BP
RET
TEXT runtime·exit(SB),NOSPLIT,$0
MOVL code+0(FP), DI
NACL_SYSCALL(SYS_exit)
RET
TEXT runtime·exit1(SB),NOSPLIT,$0
MOVL code+0(FP), DI
NACL_SYSCALL(SYS_thread_exit)
RET
TEXT runtime·open(SB),NOSPLIT,$0
MOVL name+0(FP), DI
MOVL mode+4(FP), SI
MOVL perm+8(FP), DX
NACL_SYSCALL(SYS_open)
MOVL AX, ret+16(FP)
RET
TEXT runtime·close(SB),NOSPLIT,$0
MOVL fd+0(FP), DI
NACL_SYSCALL(SYS_close)
MOVL AX, ret+8(FP)
RET
TEXT runtime·read(SB),NOSPLIT,$0
MOVL fd+0(FP), DI
MOVL p+4(FP), SI
MOVL n+8(FP), DX
NACL_SYSCALL(SYS_read)
MOVL AX, ret+16(FP)
RET
TEXT syscall·naclWrite(SB), NOSPLIT, $24-20
MOVL arg1+0(FP), DI
MOVL arg2+4(FP), SI
MOVL arg3+8(FP), DX
MOVL DI, 0(SP)
MOVL SI, 4(SP)
MOVL DX, 8(SP)
CALL runtime·write(SB)
MOVL 16(SP), AX
MOVL AX, ret+16(FP)
RET
TEXT runtime·write(SB),NOSPLIT,$16-20
// If using fake time and writing to stdout or stderr,
// emit playback header before actual data.
MOVQ runtime·timens(SB), AX
CMPQ AX, $0
JEQ write
MOVL fd+0(FP), DI
CMPL DI, $1
JEQ playback
CMPL DI, $2
JEQ playback
write:
// Ordinary write.
MOVL fd+0(FP), DI
MOVL p+4(FP), SI
MOVL n+8(FP), DX
NACL_SYSCALL(SYS_write)
MOVL AX, ret+16(FP)
RET
// Write with playback header.
// First, lock to avoid interleaving writes.
playback:
MOVL $1, BX
XCHGL runtime·writelock(SB), BX
CMPL BX, $0
JNE playback
// Playback header: 0 0 P B <8-byte time> <4-byte data length>
MOVL $(('B'<<24) | ('P'<<16)), 0(SP)
BSWAPQ AX
MOVQ AX, 4(SP)
MOVL n+8(FP), DX
BSWAPL DX
MOVL DX, 12(SP)
MOVL $1, DI // standard output
MOVL SP, SI
MOVL $16, DX
NACL_SYSCALL(SYS_write)
// Write actual data.
MOVL $1, DI // standard output
MOVL p+4(FP), SI
MOVL n+8(FP), DX
NACL_SYSCALL(SYS_write)
// Unlock.
MOVL $0, runtime·writelock(SB)
MOVL AX, ret+16(FP)
RET
TEXT runtime·nacl_exception_stack(SB),NOSPLIT,$0
MOVL p+0(FP), DI
MOVL size+4(FP), SI
NACL_SYSCALL(SYS_exception_stack)
MOVL AX, ret+8(FP)
RET
TEXT runtime·nacl_exception_handler(SB),NOSPLIT,$0
MOVL fn+0(FP), DI
MOVL arg+4(FP), SI
NACL_SYSCALL(SYS_exception_handler)
MOVL AX, ret+8(FP)
RET
TEXT runtime·nacl_sem_create(SB),NOSPLIT,$0
MOVL flag+0(FP), DI
NACL_SYSCALL(SYS_sem_create)
MOVL AX, ret+8(FP)
RET
TEXT runtime·nacl_sem_wait(SB),NOSPLIT,$0
MOVL sem+0(FP), DI
NACL_SYSCALL(SYS_sem_wait)
MOVL AX, ret+8(FP)
RET
TEXT runtime·nacl_sem_post(SB),NOSPLIT,$0
MOVL sem+0(FP), DI
NACL_SYSCALL(SYS_sem_post)
MOVL AX, ret+8(FP)
RET
TEXT runtime·nacl_mutex_create(SB),NOSPLIT,$0
MOVL flag+0(FP), DI
NACL_SYSCALL(SYS_mutex_create)
MOVL AX, ret+8(FP)
RET
TEXT runtime·nacl_mutex_lock(SB),NOSPLIT,$0
MOVL mutex+0(FP), DI
NACL_SYSCALL(SYS_mutex_lock)
MOVL AX, ret+8(FP)
RET
TEXT runtime·nacl_mutex_trylock(SB),NOSPLIT,$0
MOVL mutex+0(FP), DI
NACL_SYSCALL(SYS_mutex_trylock)
MOVL AX, ret+8(FP)
RET
TEXT runtime·nacl_mutex_unlock(SB),NOSPLIT,$0
MOVL mutex+0(FP), DI
NACL_SYSCALL(SYS_mutex_unlock)
MOVL AX, ret+8(FP)
RET
TEXT runtime·nacl_cond_create(SB),NOSPLIT,$0
MOVL flag+0(FP), DI
NACL_SYSCALL(SYS_cond_create)
MOVL AX, ret+8(FP)
RET
TEXT runtime·nacl_cond_wait(SB),NOSPLIT,$0
MOVL cond+0(FP), DI
MOVL n+4(FP), SI
NACL_SYSCALL(SYS_cond_wait)
MOVL AX, ret+8(FP)
RET
TEXT runtime·nacl_cond_signal(SB),NOSPLIT,$0
MOVL cond+0(FP), DI
NACL_SYSCALL(SYS_cond_signal)
MOVL AX, ret+8(FP)
RET
TEXT runtime·nacl_cond_broadcast(SB),NOSPLIT,$0
MOVL cond+0(FP), DI
NACL_SYSCALL(SYS_cond_broadcast)
MOVL AX, ret+8(FP)
RET
TEXT runtime·nacl_cond_timed_wait_abs(SB),NOSPLIT,$0
MOVL cond+0(FP), DI
MOVL lock+4(FP), SI
MOVL ts+8(FP), DX
NACL_SYSCALL(SYS_cond_timed_wait_abs)
MOVL AX, ret+16(FP)
RET
TEXT runtime·nacl_thread_create(SB),NOSPLIT,$0
MOVL fn+0(FP), DI
MOVL stk+4(FP), SI
MOVL tls+8(FP), DX
MOVL xx+12(FP), CX
NACL_SYSCALL(SYS_thread_create)
MOVL AX, ret+16(FP)
RET
TEXT runtime·mstart_nacl(SB),NOSPLIT,$0
NACL_SYSCALL(SYS_tls_get)
SUBL $8, AX
MOVL AX, TLS
JMP runtime·mstart(SB)
TEXT runtime·nacl_nanosleep(SB),NOSPLIT,$0
MOVL ts+0(FP), DI
MOVL extra+4(FP), SI
NACL_SYSCALL(SYS_nanosleep)
MOVL AX, ret+8(FP)
RET
TEXT runtime·osyield(SB),NOSPLIT,$0
NACL_SYSCALL(SYS_sched_yield)
RET
TEXT runtime·mmap(SB),NOSPLIT,$8
MOVL addr+0(FP), DI
MOVL n+4(FP), SI
MOVL prot+8(FP), DX
MOVL flags+12(FP), CX
MOVL fd+16(FP), R8
MOVL off+20(FP), AX
MOVQ AX, 0(SP)
MOVL SP, R9
NACL_SYSCALL(SYS_mmap)
CMPL AX, $-4095
JNA 2(PC)
NEGL AX
MOVL AX, ret+24(FP)
RET
TEXT time·now(SB),NOSPLIT,$16
MOVQ runtime·timens(SB), AX
CMPQ AX, $0
JEQ realtime
MOVQ $0, DX
MOVQ $1000000000, CX
DIVQ CX
MOVQ AX, sec+0(FP)
MOVL DX, nsec+8(FP)
RET
realtime:
MOVL $0, DI // real time clock
LEAL 0(SP), AX
MOVL AX, SI // timespec
NACL_SYSCALL(SYS_clock_gettime)
MOVL 0(SP), AX // low 32 sec
MOVL 4(SP), CX // high 32 sec
MOVL 8(SP), BX // nsec
// sec is in AX, nsec in BX
MOVL AX, sec+0(FP)
MOVL CX, sec+4(FP)
MOVL BX, nsec+8(FP)
RET
TEXT syscall·now(SB),NOSPLIT,$0
JMP time·now(SB)
TEXT runtime·nacl_clock_gettime(SB),NOSPLIT,$0
MOVL arg1+0(FP), DI
MOVL arg2+4(FP), SI
NACL_SYSCALL(SYS_clock_gettime)
MOVL AX, ret+8(FP)
RET
TEXT runtime·nanotime(SB),NOSPLIT,$16
MOVQ runtime·timens(SB), AX
CMPQ AX, $0
JEQ 3(PC)
MOVQ AX, ret+0(FP)
RET
MOVL $0, DI // real time clock
LEAL 0(SP), AX
MOVL AX, SI // timespec
NACL_SYSCALL(SYS_clock_gettime)
MOVQ 0(SP), AX // sec
MOVL 8(SP), DX // nsec
// sec is in AX, nsec in DX
// return nsec in AX
IMULQ $1000000000, AX
ADDQ DX, AX
MOVQ AX, ret+0(FP)
RET
TEXT runtime·sigtramp(SB),NOSPLIT,$80
// restore TLS register at time of execution,
// in case it's been smashed.
// the TLS register is really BP, but for consistency
// with non-NaCl systems it is referred to here as TLS.
// NOTE: Cannot use SYS_tls_get here (like we do in mstart_nacl),
// because the main thread never calls tls_set.
LEAL ctxt+0(FP), AX
MOVL (16*4+5*8)(AX), AX
MOVL AX, TLS
// check that g exists
get_tls(CX)
MOVL g(CX), DI
CMPL DI, $0
JEQ nog
// save g
MOVL DI, 20(SP)
// g = m->gsignal
MOVL g_m(DI), BX
MOVL m_gsignal(BX), BX
MOVL BX, g(CX)
//JMP debughandler
// copy arguments for sighandler
MOVL $11, 0(SP) // signal
MOVL $0, 4(SP) // siginfo
LEAL ctxt+0(FP), AX
MOVL AX, 8(SP) // context
MOVL DI, 12(SP) // g
CALL runtime·sighandler(SB)
// restore g
get_tls(CX)
MOVL 20(SP), BX
MOVL BX, g(CX)
sigtramp_ret:
// 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.
LEAL ctxt+0(FP), SI
ADDL $64, SI
MOVQ 0(SI), AX
MOVQ 8(SI), CX
MOVQ 16(SI), DX
MOVQ 24(SI), BX
MOVL 32(SI), SP // MOVL for SP sandboxing
// 40(SI) is saved BP aka TLS, already restored above
// 48(SI) is saved SI, never to be seen again
MOVQ 56(SI), DI
MOVQ 64(SI), R8
MOVQ 72(SI), R9
MOVQ 80(SI), R10
MOVQ 88(SI), R11
MOVQ 96(SI), R12
MOVQ 104(SI), R13
MOVQ 112(SI), R14
// 120(SI) is R15, which is owned by Native Client and must not be modified
MOVQ 128(SI), SI // saved PC
// 136(SI) is saved EFLAGS, never to be seen again
JMP SI
debughandler:
// print basic information
LEAL ctxt+0(FP), DI
MOVL $runtime·sigtrampf(SB), AX
MOVL AX, 0(SP)
MOVQ (16*4+16*8)(DI), BX // rip
MOVQ BX, 8(SP)
MOVQ (16*4+0*8)(DI), BX // rax
MOVQ BX, 16(SP)
MOVQ (16*4+1*8)(DI), BX // rcx
MOVQ BX, 24(SP)
MOVQ (16*4+2*8)(DI), BX // rdx
MOVQ BX, 32(SP)
MOVQ (16*4+3*8)(DI), BX // rbx
MOVQ BX, 40(SP)
MOVQ (16*4+7*8)(DI), BX // rdi
MOVQ BX, 48(SP)
MOVQ (16*4+15*8)(DI), BX // r15
MOVQ BX, 56(SP)
MOVQ (16*4+4*8)(DI), BX // rsp
MOVQ 0(BX), BX
MOVQ BX, 64(SP)
CALL runtime·printf(SB)
LEAL ctxt+0(FP), DI
MOVQ (16*4+16*8)(DI), BX // rip
MOVL BX, 0(SP)
MOVQ (16*4+4*8)(DI), BX // rsp
MOVL BX, 4(SP)
MOVL $0, 8(SP) // lr
get_tls(CX)
MOVL g(CX), BX
MOVL BX, 12(SP) // gp
CALL runtime·traceback(SB)
notls:
MOVL 0, AX
RET
nog:
MOVL 0, AX
RET
// cannot do real signal handling yet, because gsignal has not been allocated.
MOVL $1, DI; NACL_SYSCALL(SYS_exit)
TEXT runtime·nacl_sysinfo(SB),NOSPLIT,$16
/*
MOVL di+0(FP), DI
LEAL 12(DI), BX
MOVL 8(DI), AX
ADDL 4(DI), AX
ADDL $2, AX
LEAL (BX)(AX*4), BX
MOVL BX, runtime·nacl_irt_query(SB)
auxloop:
MOVL 0(BX), DX
CMPL DX, $0
JNE 2(PC)
RET
CMPL DX, $32
JEQ auxfound
ADDL $8, BX
JMP auxloop
auxfound:
MOVL 4(BX), BX
MOVL BX, runtime·nacl_irt_query(SB)
LEAL runtime·nacl_irt_basic_v0_1_str(SB), DI
LEAL runtime·nacl_irt_basic_v0_1(SB), SI
MOVL runtime·nacl_irt_basic_v0_1_size(SB), DX
MOVL runtime·nacl_irt_query(SB), BX
CALL BX
LEAL runtime·nacl_irt_memory_v0_3_str(SB), DI
LEAL runtime·nacl_irt_memory_v0_3(SB), SI
MOVL runtime·nacl_irt_memory_v0_3_size(SB), DX
MOVL runtime·nacl_irt_query(SB), BX
CALL BX
LEAL runtime·nacl_irt_thread_v0_1_str(SB), DI
LEAL runtime·nacl_irt_thread_v0_1(SB), SI
MOVL runtime·nacl_irt_thread_v0_1_size(SB), DX
MOVL runtime·nacl_irt_query(SB), BX
CALL BX
// TODO: Once we have a NaCl SDK with futex syscall support,
// try switching to futex syscalls and here load the
// nacl-irt-futex-0.1 table.
*/
RET
|