summaryrefslogtreecommitdiff
path: root/src/pkg/runtime/sys_nacl_amd64p32.s
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/runtime/sys_nacl_amd64p32.s')
-rw-r--r--src/pkg/runtime/sys_nacl_amd64p32.s413
1 files changed, 413 insertions, 0 deletions
diff --git a/src/pkg/runtime/sys_nacl_amd64p32.s b/src/pkg/runtime/sys_nacl_amd64p32.s
new file mode 100644
index 000000000..43c172372
--- /dev/null
+++ b/src/pkg/runtime/sys_nacl_amd64p32.s
@@ -0,0 +1,413 @@
+// 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 "../../cmd/ld/textflag.h"
+#include "syscall_nacl.h"
+
+#define NACL_SYSCALL(code) \
+ MOVL $(0x10000 + ((code)<<5)), AX; CALL AX
+
+#define NACL_SYSJMP(code) \
+ MOVL $(0x10000 + ((code)<<5)), AX; JMP AX
+
+TEXT runtime·settls(SB),NOSPLIT,$0
+ MOVL DI, TLS // really BP
+ RET
+
+TEXT runtime·exit(SB),NOSPLIT,$0
+ MOVL arg1+0(FP), DI
+ NACL_SYSJMP(SYS_exit)
+
+TEXT runtime·exit1(SB),NOSPLIT,$0
+ MOVL arg1+0(FP), DI
+ NACL_SYSJMP(SYS_thread_exit)
+
+TEXT runtime·open(SB),NOSPLIT,$0
+ MOVL arg1+0(FP), DI
+ MOVL arg2+4(FP), SI
+ MOVL arg3+8(FP), DX
+ NACL_SYSJMP(SYS_open)
+
+TEXT runtime·close(SB),NOSPLIT,$0
+ MOVL arg1+0(FP), DI
+ NACL_SYSJMP(SYS_close)
+
+TEXT runtime·read(SB),NOSPLIT,$0
+ MOVL arg1+0(FP), DI
+ MOVL arg2+4(FP), SI
+ MOVL arg3+8(FP), DX
+ NACL_SYSJMP(SYS_read)
+
+TEXT syscall·naclWrite(SB), NOSPLIT, $16-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 AX, ret+16(FP)
+ RET
+
+TEXT runtime·write(SB),NOSPLIT,$16-12
+ // 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 arg1+0(FP), DI
+ CMPL DI, $1
+ JEQ playback
+ CMPL DI, $2
+ JEQ playback
+
+write:
+ // Ordinary write.
+ MOVL arg1+0(FP), DI
+ MOVL arg2+4(FP), SI
+ MOVL arg3+8(FP), DX
+ NACL_SYSCALL(SYS_write)
+ 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 arg3+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 arg2+4(FP), SI
+ MOVL arg3+8(FP), DX
+ NACL_SYSCALL(SYS_write)
+
+ // Unlock.
+ MOVL $0, runtime·writelock(SB)
+
+ RET
+
+TEXT runtime·nacl_exception_stack(SB),NOSPLIT,$0
+ MOVL arg1+0(FP), DI
+ MOVL arg2+4(FP), SI
+ NACL_SYSJMP(SYS_exception_stack)
+
+TEXT runtime·nacl_exception_handler(SB),NOSPLIT,$0
+ MOVL arg1+0(FP), DI
+ MOVL arg2+4(FP), SI
+ NACL_SYSJMP(SYS_exception_handler)
+
+TEXT runtime·nacl_sem_create(SB),NOSPLIT,$0
+ MOVL arg1+0(FP), DI
+ NACL_SYSJMP(SYS_sem_create)
+
+TEXT runtime·nacl_sem_wait(SB),NOSPLIT,$0
+ MOVL arg1+0(FP), DI
+ NACL_SYSJMP(SYS_sem_wait)
+
+TEXT runtime·nacl_sem_post(SB),NOSPLIT,$0
+ MOVL arg1+0(FP), DI
+ NACL_SYSJMP(SYS_sem_post)
+
+TEXT runtime·nacl_mutex_create(SB),NOSPLIT,$0
+ MOVL arg1+0(FP), DI
+ NACL_SYSJMP(SYS_mutex_create)
+
+TEXT runtime·nacl_mutex_lock(SB),NOSPLIT,$0
+ MOVL arg1+0(FP), DI
+ NACL_SYSJMP(SYS_mutex_lock)
+
+TEXT runtime·nacl_mutex_trylock(SB),NOSPLIT,$0
+ MOVL arg1+0(FP), DI
+ NACL_SYSJMP(SYS_mutex_trylock)
+
+TEXT runtime·nacl_mutex_unlock(SB),NOSPLIT,$0
+ MOVL arg1+0(FP), DI
+ NACL_SYSJMP(SYS_mutex_unlock)
+
+TEXT runtime·nacl_cond_create(SB),NOSPLIT,$0
+ MOVL arg1+0(FP), DI
+ NACL_SYSJMP(SYS_cond_create)
+
+TEXT runtime·nacl_cond_wait(SB),NOSPLIT,$0
+ MOVL arg1+0(FP), DI
+ MOVL arg2+4(FP), SI
+ NACL_SYSJMP(SYS_cond_wait)
+
+TEXT runtime·nacl_cond_signal(SB),NOSPLIT,$0
+ MOVL arg1+0(FP), DI
+ NACL_SYSJMP(SYS_cond_signal)
+
+TEXT runtime·nacl_cond_broadcast(SB),NOSPLIT,$0
+ MOVL arg1+0(FP), DI
+ NACL_SYSJMP(SYS_cond_broadcast)
+
+TEXT runtime·nacl_cond_timed_wait_abs(SB),NOSPLIT,$0
+ MOVL arg1+0(FP), DI
+ MOVL arg2+4(FP), SI
+ MOVL arg3+8(FP), DX
+ NACL_SYSJMP(SYS_cond_timed_wait_abs)
+
+TEXT runtime·nacl_thread_create(SB),NOSPLIT,$0
+ MOVL arg1+0(FP), DI
+ MOVL arg2+4(FP), SI
+ MOVL arg3+8(FP), DX
+ MOVL arg4+12(FP), CX
+ NACL_SYSJMP(SYS_thread_create)
+
+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 arg1+0(FP), DI
+ MOVL arg2+4(FP), SI
+ NACL_SYSJMP(SYS_nanosleep)
+
+TEXT runtime·osyield(SB),NOSPLIT,$0
+ NACL_SYSJMP(SYS_sched_yield)
+
+TEXT runtime·mmap(SB),NOSPLIT,$8
+ MOVL arg1+0(FP), DI
+ MOVL arg2+4(FP), SI
+ MOVL arg3+8(FP), DX
+ MOVL arg4+12(FP), CX
+ MOVL arg5+16(FP), R8
+ MOVL arg6+20(FP), AX
+ MOVQ AX, 0(SP)
+ MOVL SP, R9
+ NACL_SYSCALL(SYS_mmap)
+ CMPL AX, $-4095
+ JNA 2(PC)
+ NEGL AX
+ 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_SYSJMP(SYS_clock_gettime)
+
+TEXT runtime·nanotime(SB),NOSPLIT,$16
+ MOVQ runtime·timens(SB), AX
+ CMPQ AX, $0
+ JEQ 2(PC)
+ 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
+ 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 m exists
+ get_tls(CX)
+ MOVL m(CX), BX
+
+ CMPL BX, $0
+ JEQ nom
+
+ // save g
+ MOVL g(CX), DI
+ MOVL DI, 20(SP)
+
+ // g = m->gsignal
+ 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
+
+nom:
+ 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