]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: darwin/arm support
authorShenghou Ma <minux@golang.org>
Fri, 26 Dec 2014 06:07:10 +0000 (01:07 -0500)
committerMinux Ma <minux@golang.org>
Fri, 6 Feb 2015 05:48:56 +0000 (05:48 +0000)
Change-Id: I63110daad2d62ae72ab1f33a40464d76e6205627
Reviewed-on: https://go-review.googlesource.com/2121
Reviewed-by: David Crawshaw <crawshaw@golang.org>
src/runtime/defs_darwin_arm.go [new file with mode: 0644]
src/runtime/os_darwin_arm.go [new file with mode: 0644]
src/runtime/rt0_darwin_arm.s [new file with mode: 0644]
src/runtime/signal_darwin_arm.go [new file with mode: 0644]
src/runtime/stack.h
src/runtime/stack2.go
src/runtime/sys_darwin_arm.s [new file with mode: 0644]
src/runtime/tls_arm.s

diff --git a/src/runtime/defs_darwin_arm.go b/src/runtime/defs_darwin_arm.go
new file mode 100644 (file)
index 0000000..92bab50
--- /dev/null
@@ -0,0 +1,245 @@
+// Note: cgo can't handle some Darwin/ARM structures, so this file can't
+// be auto generated by cgo yet.
+// Created based on output of `cgo -cdefs defs_darwin.go` and Darwin/ARM
+// specific header (mainly mcontext and ucontext related stuff)
+
+package runtime
+
+import "unsafe"
+
+const (
+       _EINTR  = 0x4
+       _EFAULT = 0xe
+
+       _PROT_NONE  = 0x0
+       _PROT_READ  = 0x1
+       _PROT_WRITE = 0x2
+       _PROT_EXEC  = 0x4
+
+       _MAP_ANON    = 0x1000
+       _MAP_PRIVATE = 0x2
+       _MAP_FIXED   = 0x10
+
+       _MADV_DONTNEED = 0x4
+       _MADV_FREE     = 0x5
+
+       _MACH_MSG_TYPE_MOVE_RECEIVE   = 0x10
+       _MACH_MSG_TYPE_MOVE_SEND      = 0x11
+       _MACH_MSG_TYPE_MOVE_SEND_ONCE = 0x12
+       _MACH_MSG_TYPE_COPY_SEND      = 0x13
+       _MACH_MSG_TYPE_MAKE_SEND      = 0x14
+       _MACH_MSG_TYPE_MAKE_SEND_ONCE = 0x15
+       _MACH_MSG_TYPE_COPY_RECEIVE   = 0x16
+
+       _MACH_MSG_PORT_DESCRIPTOR         = 0x0
+       _MACH_MSG_OOL_DESCRIPTOR          = 0x1
+       _MACH_MSG_OOL_PORTS_DESCRIPTOR    = 0x2
+       _MACH_MSG_OOL_VOLATILE_DESCRIPTOR = 0x3
+
+       _MACH_MSGH_BITS_COMPLEX = 0x80000000
+
+       _MACH_SEND_MSG  = 0x1
+       _MACH_RCV_MSG   = 0x2
+       _MACH_RCV_LARGE = 0x4
+
+       _MACH_SEND_TIMEOUT   = 0x10
+       _MACH_SEND_INTERRUPT = 0x40
+       _MACH_SEND_ALWAYS    = 0x10000
+       _MACH_SEND_TRAILER   = 0x20000
+       _MACH_RCV_TIMEOUT    = 0x100
+       _MACH_RCV_NOTIFY     = 0x200
+       _MACH_RCV_INTERRUPT  = 0x400
+       _MACH_RCV_OVERWRITE  = 0x1000
+
+       _NDR_PROTOCOL_2_0      = 0x0
+       _NDR_INT_BIG_ENDIAN    = 0x0
+       _NDR_INT_LITTLE_ENDIAN = 0x1
+       _NDR_FLOAT_IEEE        = 0x0
+       _NDR_CHAR_ASCII        = 0x0
+
+       _SA_SIGINFO   = 0x40
+       _SA_RESTART   = 0x2
+       _SA_ONSTACK   = 0x1
+       _SA_USERTRAMP = 0x100
+       _SA_64REGSET  = 0x200
+
+       _SIGHUP    = 0x1
+       _SIGINT    = 0x2
+       _SIGQUIT   = 0x3
+       _SIGILL    = 0x4
+       _SIGTRAP   = 0x5
+       _SIGABRT   = 0x6
+       _SIGEMT    = 0x7
+       _SIGFPE    = 0x8
+       _SIGKILL   = 0x9
+       _SIGBUS    = 0xa
+       _SIGSEGV   = 0xb
+       _SIGSYS    = 0xc
+       _SIGPIPE   = 0xd
+       _SIGALRM   = 0xe
+       _SIGTERM   = 0xf
+       _SIGURG    = 0x10
+       _SIGSTOP   = 0x11
+       _SIGTSTP   = 0x12
+       _SIGCONT   = 0x13
+       _SIGCHLD   = 0x14
+       _SIGTTIN   = 0x15
+       _SIGTTOU   = 0x16
+       _SIGIO     = 0x17
+       _SIGXCPU   = 0x18
+       _SIGXFSZ   = 0x19
+       _SIGVTALRM = 0x1a
+       _SIGPROF   = 0x1b
+       _SIGWINCH  = 0x1c
+       _SIGINFO   = 0x1d
+       _SIGUSR1   = 0x1e
+       _SIGUSR2   = 0x1f
+
+       _FPE_INTDIV = 0x7
+       _FPE_INTOVF = 0x8
+       _FPE_FLTDIV = 0x1
+       _FPE_FLTOVF = 0x2
+       _FPE_FLTUND = 0x3
+       _FPE_FLTRES = 0x4
+       _FPE_FLTINV = 0x5
+       _FPE_FLTSUB = 0x6
+
+       _BUS_ADRALN = 0x1
+       _BUS_ADRERR = 0x2
+       _BUS_OBJERR = 0x3
+
+       _SEGV_MAPERR = 0x1
+       _SEGV_ACCERR = 0x2
+
+       _ITIMER_REAL    = 0x0
+       _ITIMER_VIRTUAL = 0x1
+       _ITIMER_PROF    = 0x2
+
+       _EV_ADD       = 0x1
+       _EV_DELETE    = 0x2
+       _EV_CLEAR     = 0x20
+       _EV_RECEIPT   = 0x40
+       _EV_ERROR     = 0x4000
+       _EVFILT_READ  = -0x1
+       _EVFILT_WRITE = -0x2
+)
+
+type machbody struct {
+       msgh_descriptor_count uint32
+}
+
+type machheader struct {
+       msgh_bits        uint32
+       msgh_size        uint32
+       msgh_remote_port uint32
+       msgh_local_port  uint32
+       msgh_reserved    uint32
+       msgh_id          int32
+}
+
+type machndr struct {
+       mig_vers     uint8
+       if_vers      uint8
+       reserved1    uint8
+       mig_encoding uint8
+       int_rep      uint8
+       char_rep     uint8
+       float_rep    uint8
+       reserved2    uint8
+}
+
+type machport struct {
+       name        uint32
+       pad1        uint32
+       pad2        uint16
+       disposition uint8
+       _type       uint8
+}
+
+type stackt struct {
+       ss_sp    *byte
+       ss_size  uintptr
+       ss_flags int32
+}
+
+type sigactiont struct {
+       __sigaction_u [4]byte
+       sa_tramp      unsafe.Pointer
+       sa_mask       uint32
+       sa_flags      int32
+}
+
+type siginfo struct {
+       si_signo  int32
+       si_errno  int32
+       si_code   int32
+       si_pid    int32
+       si_uid    uint32
+       si_status int32
+       si_addr   *byte
+       si_value  [4]byte
+       si_band   int32
+       __pad     [7]uint32
+}
+
+type timeval struct {
+       tv_sec  int32
+       tv_usec int32
+}
+
+func (tv *timeval) set_usec(x int32) {
+       tv.tv_usec = x
+}
+
+type itimerval struct {
+       it_interval timeval
+       it_value    timeval
+}
+
+type timespec struct {
+       tv_sec  int32
+       tv_nsec int32
+}
+
+type floatstate32 struct {
+       r     [32]uint32
+       fpscr uint32
+}
+
+type regs32 struct {
+       r    [13]uint32 // r0 to r12
+       sp   uint32     // r13
+       lr   uint32     // r14
+       pc   uint32     // r15
+       cpsr uint32
+}
+
+type exceptionstate32 struct {
+       trapno     uint32 // NOTE: on 386, the trapno field is split into trapno and cpu
+       err        uint32
+       faultvaddr uint32
+}
+
+type mcontext32 struct {
+       es exceptionstate32
+       ss regs32
+       fs floatstate32
+}
+
+type ucontext struct {
+       uc_onstack  int32
+       uc_sigmask  uint32
+       uc_stack    stackt
+       uc_link     *ucontext
+       uc_mcsize   uint32
+       uc_mcontext *mcontext32
+}
+
+type keventt struct {
+       ident  uint32
+       filter int16
+       flags  uint16
+       fflags uint32
+       data   int32
+       udata  *byte
+}
diff --git a/src/runtime/os_darwin_arm.go b/src/runtime/os_darwin_arm.go
new file mode 100644 (file)
index 0000000..d3336c0
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2014 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.
+
+package runtime
+
+func checkgoarm() {
+       return // TODO(minux)
+}
+
+//go:nosplit
+func cputicks() int64 {
+       // Currently cputicks() is used in blocking profiler and to seed runtime·fastrand1().
+       // runtime·nanotime() is a poor approximation of CPU ticks that is enough for the profiler.
+       // TODO: need more entropy to better seed fastrand1.
+       return nanotime()
+}
diff --git a/src/runtime/rt0_darwin_arm.s b/src/runtime/rt0_darwin_arm.s
new file mode 100644 (file)
index 0000000..4d31e3a
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2014 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 "textflag.h"
+
+TEXT _rt0_arm_darwin(SB),7,$-4
+       // prepare arguments for main (_rt0_go)
+       MOVW    (R13), R0       // argc
+       MOVW    $4(R13), R1             // argv
+       MOVW    $main(SB), R4
+       B               (R4)
+
+TEXT main(SB),NOSPLIT,$-8
+       // save argc and argv onto stack
+       MOVM.DB.W [R0-R1], (R13)
+       MOVW    $runtime·rt0_go(SB), R4
+       B               (R4)
diff --git a/src/runtime/signal_darwin_arm.go b/src/runtime/signal_darwin_arm.go
new file mode 100644 (file)
index 0000000..1441a65
--- /dev/null
@@ -0,0 +1,44 @@
+// Copyright 2014 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.
+
+package runtime
+
+import "unsafe"
+
+type sigctxt struct {
+       info *siginfo
+       ctxt unsafe.Pointer
+}
+
+func (c *sigctxt) regs() *regs32   { return &(*ucontext)(c.ctxt).uc_mcontext.ss }
+func (c *sigctxt) r0() uint32      { return c.regs().r[0] }
+func (c *sigctxt) r1() uint32      { return c.regs().r[1] }
+func (c *sigctxt) r2() uint32      { return c.regs().r[2] }
+func (c *sigctxt) r3() uint32      { return c.regs().r[3] }
+func (c *sigctxt) r4() uint32      { return c.regs().r[4] }
+func (c *sigctxt) r5() uint32      { return c.regs().r[5] }
+func (c *sigctxt) r6() uint32      { return c.regs().r[6] }
+func (c *sigctxt) r7() uint32      { return c.regs().r[7] }
+func (c *sigctxt) r8() uint32      { return c.regs().r[8] }
+func (c *sigctxt) r9() uint32      { return c.regs().r[9] }
+func (c *sigctxt) r10() uint32     { return c.regs().r[10] }
+func (c *sigctxt) fp() uint32      { return c.regs().r[11] }
+func (c *sigctxt) ip() uint32      { return c.regs().r[12] }
+func (c *sigctxt) sp() uint32      { return c.regs().sp }
+func (c *sigctxt) lr() uint32      { return c.regs().lr }
+func (c *sigctxt) pc() uint32      { return c.regs().pc }
+func (c *sigctxt) cpsr() uint32    { return c.regs().cpsr }
+func (c *sigctxt) fault() uint32   { return uint32(uintptr(unsafe.Pointer(c.info.si_addr))) }
+func (c *sigctxt) sigcode() uint32 { return uint32(c.info.si_code) }
+func (c *sigctxt) trap() uint32    { return 0 }
+func (c *sigctxt) error() uint32   { return 0 }
+func (c *sigctxt) oldmask() uint32 { return 0 }
+
+func (c *sigctxt) set_pc(x uint32)  { c.regs().pc = x }
+func (c *sigctxt) set_sp(x uint32)  { c.regs().sp = x }
+func (c *sigctxt) set_lr(x uint32)  { c.regs().lr = x }
+func (c *sigctxt) set_r10(x uint32) { c.regs().r[10] = x }
+
+func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) }
+func (c *sigctxt) set_sigaddr(x uint32) { c.info.si_addr = (*byte)(unsafe.Pointer(uintptr(x))) }
index b790e70103317922823468f31ff11ca1684885fd..88c7e02f40f764f3f7041ed36032c366a3a81871 100644 (file)
@@ -7,14 +7,22 @@
 
 enum {
 #ifdef GOOS_windows
-#define StackSystem (512*sizeof(uintptr))
-#else
+#define STACKSYSTEM (512 * sizeof(uintptr))
+#endif // GOOS_windows
 #ifdef GOOS_plan9
-#define StackSystem (512)
-#else
-       StackSystem = 0,
-#endif // Plan 9
-#endif // Windows
+#define STACKSYSTEM    512
+#endif // GOOS_plan9
+#ifdef GOOS_darwin
+#ifdef GOARCH_arm
+#define STACKSYSTEM 1024
+#endif // GOARCH_arm
+#endif // GOOS_darwin
+
+#ifndef STACKSYSTEM
+#define STACKSYSTEM 0
+#endif
+
+       StackSystem = STACKSYSTEM,
 
        StackBig = 4096,
        StackGuard = 640 + StackSystem,
index 8a78b1ad966cec6df683424748e855dbd64c4ed5..07a7d38f0c1a56fdac53a87e38cf98e5950d072a 100644 (file)
@@ -57,9 +57,9 @@ functions to make sure that this limit cannot be violated.
 const (
        // StackSystem is a number of additional bytes to add
        // to each stack below the usual guard area for OS-specific
-       // purposes like signal handling. Used on Windows and on
-       // Plan 9 because they do not use a separate stack.
-       _StackSystem = goos_windows*512*ptrSize + goos_plan9*512
+       // purposes like signal handling. Used on Windows, Plan 9,
+       // and Darwin/ARM because they do not use a separate stack.
+       _StackSystem = goos_windows*512*ptrSize + goos_plan9*512 + goos_darwin*goarch_arm*1024
 
        // The minimum size of stack used by Go code
        _StackMin = 2048
diff --git a/src/runtime/sys_darwin_arm.s b/src/runtime/sys_darwin_arm.s
new file mode 100644 (file)
index 0000000..e1b2b66
--- /dev/null
@@ -0,0 +1,481 @@
+// Copyright 2014 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.
+
+// System calls and other sys.stuff for ARM, Darwin
+// See http://fxr.watson.org/fxr/source/bsd/kern/syscalls.c?v=xnu-1228
+// or /usr/include/sys/syscall.h (on a Mac) for system call numbers.
+
+#include "go_asm.h"
+#include "go_tls.h"
+#include "textflag.h"
+
+// Copied from /usr/include/sys/syscall.h
+#define        SYS_exit           1
+#define        SYS_read           3
+#define        SYS_write          4
+#define        SYS_open           5
+#define        SYS_close          6
+#define        SYS_mmap           197
+#define        SYS_munmap         73
+#define        SYS_madvise        75
+#define        SYS_mincore        78
+#define        SYS_gettimeofday   116
+#define        SYS_kill           37
+#define        SYS_getpid         20
+#define        SYS___pthread_kill 328
+#define        SYS_setitimer      83
+#define        SYS___sysctl       202
+#define        SYS_sigprocmask    48
+#define        SYS_sigaction      46
+#define        SYS_sigreturn      184
+#define        SYS_select         93
+#define        SYS_bsdthread_register 366
+#define        SYS_bsdthread_create 360
+#define        SYS_bsdthread_terminate 361
+#define        SYS_kqueue         362
+#define        SYS_kevent         363
+#define        SYS_fcntl          92
+
+TEXT notok<>(SB),NOSPLIT,$0
+       MOVW    $0, R8
+       MOVW    R8, (R8)
+       B               0(PC)
+
+TEXT runtime·open(SB),NOSPLIT,$0
+       MOVW    name+0(FP), R0
+       MOVW    mode+4(FP), R1
+       MOVW    perm+8(FP), R2
+       MOVW    $SYS_open, R12
+       SWI     $0x80
+       MOVW    R0, ret+12(FP)
+       RET
+
+TEXT runtime·close(SB),NOSPLIT,$0
+       MOVW    fd+0(FP), R0
+       MOVW    $SYS_close, R12
+       SWI     $0x80
+       MOVW    R0, ret+4(FP)
+       RET
+
+TEXT runtime·write(SB),NOSPLIT,$0
+       MOVW    fd+0(FP), R0
+       MOVW    p+4(FP), R1
+       MOVW    n+8(FP), R2
+       MOVW    $SYS_write, R12
+       SWI     $0x80
+       MOVW    R0, ret+12(FP)
+       RET
+
+TEXT runtime·read(SB),NOSPLIT,$0
+       MOVW    fd+0(FP), R0
+       MOVW    p+4(FP), R1
+       MOVW    n+8(FP), R2
+       MOVW    $SYS_read, R12
+       SWI     $0x80
+       MOVW    R0, ret+12(FP)
+       RET
+
+TEXT runtime·exit(SB),NOSPLIT,$-4
+       MOVW    0(FP), R0
+       MOVW    $SYS_exit, R12
+       SWI     $0x80
+       MOVW    $1234, R0
+       MOVW    $1002, R1
+       MOVW    R0, (R1)        // fail hard
+
+// Exit this OS thread (like pthread_exit, which eventually
+// calls __bsdthread_terminate).
+TEXT runtime·exit1(SB),NOSPLIT,$0
+       MOVW    $SYS_bsdthread_terminate, R12
+       SWI     $0x80
+       MOVW    $1234, R0
+       MOVW    $1003, R1
+       MOVW    R0, (R1)        // fail hard
+
+TEXT runtime·raise(SB),NOSPLIT,$24
+       MOVW    $SYS_getpid, R12
+       SWI     $0x80
+       // arg 1 pid already in R0 from getpid
+       MOVW    sig+0(FP), R1   // arg 2 - signal
+       MOVW    $1, R2  // arg 3 - posix
+       MOVW    $SYS_kill, R12
+       SWI $0x80
+       RET
+
+TEXT runtime·mmap(SB),NOSPLIT,$0
+       MOVW    addr+0(FP), R0
+       MOVW    n+4(FP), R1
+       MOVW    prot+8(FP), R2
+       MOVW    flags+12(FP), R3
+       MOVW    fd+16(FP), R4
+       MOVW    off+20(FP), R5
+       MOVW    $0, R6 // off_t is uint64_t
+       MOVW    $SYS_mmap, R12
+       SWI     $0x80
+       MOVW    R0, ret+24(FP)
+       RET
+
+TEXT runtime·munmap(SB),NOSPLIT,$0
+       MOVW    0(FP), R0
+       MOVW    4(FP), R1
+       MOVW    $SYS_munmap, R12
+       SWI     $0x80
+       BL.CS   notok<>(SB)
+       RET
+
+TEXT runtime·madvise(SB),NOSPLIT,$0
+       MOVW    0(FP), R0
+       MOVW    4(FP), R1
+       MOVW    8(FP), R2
+       MOVW    $SYS_madvise, R12
+       SWI     $0x80
+       BL.CS   notok<>(SB)
+       RET
+
+TEXT runtime·setitimer(SB),NOSPLIT,$0
+       MOVW    0(FP), R0
+       MOVW    4(FP), R1
+       MOVW    8(FP), R2
+       MOVW    $SYS_setitimer, R12
+       SWI     $0x80
+       RET
+
+TEXT runtime·mincore(SB),NOSPLIT,$0
+       MOVW    0(FP), R0
+       MOVW    4(FP), R1
+       MOVW    8(FP), R2
+       MOVW    $SYS_mincore, R12
+       SWI     $0x80
+       RET
+
+TEXT time·now(SB), 7, $32
+       MOVW    $8(R13), R0  // timeval
+       MOVW    $0, R1  // zone
+       MOVW    $SYS_gettimeofday, R12
+       SWI     $0x80 // Note: R0 is tv_sec, R1 is tv_usec
+
+       MOVW    R1, R2  // usec
+
+       MOVW    R0, 0(FP)
+       MOVW    $0, R1
+       MOVW    R1, 4(FP)
+       MOVW    $1000, R3
+       MUL     R3, R2
+       MOVW    R2, 8(FP)
+       RET
+
+TEXT runtime·nanotime(SB),NOSPLIT,$32
+       MOVW    $8(R13), R0  // timeval
+       MOVW    $0, R1  // zone
+       MOVW    $SYS_gettimeofday, R12
+       SWI     $0x80 // Note: R0 is tv_sec, R1 is tv_usec
+
+       MOVW    R1, R2
+       MOVW    $1000000000, R3
+       MULLU   R0, R3, (R1, R0)
+       MOVW    $1000, R3
+       MOVW    $0, R4
+       MUL     R3, R2
+       ADD.S   R2, R0
+       ADC     R4, R1
+
+       MOVW    R0, 0(FP)
+       MOVW    R1, 4(FP)
+       RET
+
+// Sigtramp's job is to call the actual signal handler.
+// It is called with the following arguments on the stack:
+//      LR     "return address" - ignored
+//      R0     actual handler
+//      R1     siginfo style - ignored
+//      R2     signal number
+//      R3     siginfo
+//      -4(FP) context, beware that 0(FP) is the saved LR
+TEXT runtime·sigtramp(SB),NOSPLIT,$0
+       // this might be called in external code context,
+       // where g is not set.
+       // first save R0, because runtime·load_g will clobber it
+       MOVM.DB.W [R0], (R13)
+       MOVB    runtime·iscgo(SB), R0
+       CMP     $0, R0
+       BL.NE   runtime·load_g(SB)
+
+       CMP     $0, g
+       BNE     cont
+       // fake function call stack frame for badsignal
+       // we only need to pass R2 (signal number), but
+       // badsignal will expect R2 at 4(R13), so we also
+       // push R1 onto stack. turns out we do need R1
+       // to do sigreturn.
+       MOVM.DB.W [R1,R2], (R13)
+       MOVW    $runtime·badsignal(SB), R11
+       BL      (R11)
+       MOVM.IA.W [R1], (R13) // saved infostype
+       ADD             $(4+4), R13 // +4: also need to remove the pushed R0.
+       MOVW    -4(FP), R0 // load ucontext
+       B       ret
+
+cont:
+       // Restore R0
+       MOVM.IA.W (R13), [R0]
+
+       // NOTE: some Darwin/ARM kernels always use the main stack to run the
+       // signal handler. We need to switch to gsignal ourselves.
+       MOVW    g_m(g), R11
+       MOVW    m_gsignal(R11), R5
+       MOVW    (g_stack+stack_hi)(R5), R6
+       SUB             $28, R6
+
+       // copy arguments for call to sighandler
+       MOVW    R2, 4(R6) // signal num
+       MOVW    R3, 8(R6) // signal info
+       MOVW    g, 16(R6) // old_g
+       MOVW    -4(FP), R4
+       MOVW    R4, 12(R6) // context
+
+       // Backup ucontext and infostyle
+       MOVW    R4, 20(R6)
+       MOVW    R1, 24(R6)
+
+       // switch stack and g
+       MOVW    R6, R13 // sigtramp can not re-entrant, so no need to back up R13.
+       MOVW    R5, g
+
+       BL      (R0)
+
+       // call sigreturn
+       MOVW    20(R13), R0     // saved ucontext
+       MOVW    24(R13), R1     // saved infostyle
+ret:
+       MOVW    $SYS_sigreturn, R12 // sigreturn(ucontext, infostyle)
+       SWI     $0x80
+
+       // if sigreturn fails, we can do nothing but exit
+       B       runtime·exit(SB)
+
+TEXT runtime·sigprocmask(SB),NOSPLIT,$0
+       MOVW    0(FP), R0
+       MOVW    4(FP), R1
+       MOVW    8(FP), R2
+       MOVW    $SYS_sigprocmask, R12
+       SWI     $0x80
+       BL.CS   notok<>(SB)
+       RET
+
+TEXT runtime·sigaction(SB),NOSPLIT,$0
+       MOVW    0(FP), R0
+       MOVW    4(FP), R1
+       MOVW    8(FP), R2
+       MOVW    $SYS_sigaction, R12
+       SWI     $0x80
+       RET
+
+TEXT runtime·usleep(SB),NOSPLIT,$12
+       MOVW    usec+0(FP), R0
+       MOVW    R0, R1
+       MOVW    $1000000, R2
+       DIV     R2, R0
+       MOD     R2, R1
+       MOVW    R0, -12(SP)
+       MOVW    R1, -8(SP)
+
+       // select(0, 0, 0, 0, &tv)
+       MOVW    $0, R0
+       MOVW    $0, R1
+       MOVW    $0, R2
+       MOVW    $0, R3
+       MOVW    $-12(SP), R4
+       MOVW    $SYS_select, R12
+       SWI     $0x80
+       RET
+
+TEXT runtime·cas(SB),NOSPLIT,$0
+       B       runtime·armcas(SB)
+
+TEXT runtime·casp1(SB),NOSPLIT,$0
+       B       runtime·cas(SB)
+
+TEXT runtime·sysctl(SB),NOSPLIT,$0
+       MOVW    0(FP), R0
+       MOVW    4(FP), R1
+       MOVW    8(FP), R2
+       MOVW    12(FP), R3
+       MOVW    16(FP), R4
+       MOVW    20(FP), R5
+       MOVW    $SYS___sysctl, R12 // syscall entry
+       SWI     $0x80
+       BCC     sysctl_ret
+       RSB     $0, R0, R0
+       MOVW    R0, ret+24(FP)
+       RET
+sysctl_ret:
+       MOVW    $0, R0
+       MOVW    R0, ret+24(FP)
+       RET
+
+// Thread related functions
+// void bsdthread_create(void *stk, M *m, G *g, void (*fn)(void))
+TEXT runtime·bsdthread_create(SB),NOSPLIT,$0
+       // Set up arguments to bsdthread_create system call.
+       // The ones in quotes pass through to the thread callback
+       // uninterpreted, so we can put whatever we want there.
+       MOVW    fn+12(FP), R0   // "func"
+       MOVW    mm+4(FP), R1 // "arg"
+       MOVW    stk+0(FP), R2 // stack
+       MOVW    gg+8(FP), R3 // "pthread"
+       MOVW    $0x01000000, R4 // flags = PTHREAD_START_CUSTOM
+       MOVW    $0, R5  // paranoia
+       MOVW    $SYS_bsdthread_create, R12
+       SWI     $0x80
+       BCC             create_ret
+       RSB     $0, R0, R0
+       MOVW    R0, ret+16(FP)
+       RET
+create_ret:
+       MOVW    $0, R0
+       MOVW    R0, ret+16(FP)
+       RET
+
+// The thread that bsdthread_create creates starts executing here,
+// because we registered this function using bsdthread_register
+// at startup.
+//     R0 = "pthread"
+//     R1 = mach thread port
+//     R2 = "func" (= fn)
+//     R3 = "arg" (= m)
+//     R4 = stack
+//     R5 = flags (= 0)
+// XXX: how to deal with R4/SP? ref: Libc-594.9.1/arm/pthreads/thread_start.s
+TEXT runtime·bsdthread_start(SB),NOSPLIT,$0
+       MOVW    R1, m_procid(R3) // thread port is m->procid
+       MOVW    m_g0(R3), g
+       MOVW    R3, g_m(g)
+       // ARM don't have runtime·stackcheck(SB)
+       // disable runfast mode of vfp
+       EOR     R12, R12
+       WORD    $0xeee1ca10 // fmxr     fpscr, ip
+       BL      (R2) // fn
+       BL      runtime·exit1(SB)
+       RET
+
+// int32 bsdthread_register(void)
+// registers callbacks for threadstart (see bsdthread_create above
+// and wqthread and pthsize (not used).  returns 0 on success.
+TEXT runtime·bsdthread_register(SB),NOSPLIT,$0
+       MOVW    $runtime·bsdthread_start(SB), R0       // threadstart
+       MOVW    $0, R1  // wqthread, not used by us
+       MOVW    $0, R2  // pthsize, not used by us
+       MOVW    $0, R3  // dummy_value [sic]
+       MOVW    $0, R4  // targetconc_ptr
+       MOVW    $0, R5  // dispatchqueue_offset
+       MOVW    $SYS_bsdthread_register, R12    // bsdthread_register
+       SWI     $0x80
+       MOVW    R0, ret+0(FP)
+       RET
+
+// uint32 mach_msg_trap(void*, uint32, uint32, uint32, uint32, uint32, uint32)
+TEXT runtime·mach_msg_trap(SB),NOSPLIT,$0
+       MOVW    0(FP), R0
+       MOVW    4(FP), R1
+       MOVW    8(FP), R2
+       MOVW    12(FP), R3
+       MOVW    16(FP), R4
+       MOVW    20(FP), R5
+       MOVW    24(FP), R6
+       MVN     $30, R12
+       SWI     $0x80
+       MOVW    R0, 28(FP)
+       RET
+
+TEXT runtime·mach_task_self(SB),NOSPLIT,$0
+       MVN     $27, R12 // task_self_trap
+       SWI     $0x80
+       MOVW    R0, 0(FP)
+       RET
+
+TEXT runtime·mach_thread_self(SB),NOSPLIT,$0
+       MVN     $26, R12 // thread_self_trap
+       SWI     $0x80
+       MOVW    R0, 0(FP)
+       RET
+
+TEXT runtime·mach_reply_port(SB),NOSPLIT,$0
+       MVN     $25, R12        // mach_reply_port
+       SWI     $0x80
+       MOVW    R0, 0(FP)
+       RET
+
+// Mach provides trap versions of the semaphore ops,
+// instead of requiring the use of RPC.
+
+// uint32 mach_semaphore_wait(uint32)
+TEXT runtime·mach_semaphore_wait(SB),NOSPLIT,$0
+       MOVW    0(FP), R0
+       MVN     $35, R12        // semaphore_wait_trap
+       SWI     $0x80
+       MOVW    R0, ret+4(FP)
+       RET
+
+// uint32 mach_semaphore_timedwait(uint32, uint32, uint32)
+TEXT runtime·mach_semaphore_timedwait(SB),NOSPLIT,$0
+       MOVW    0(FP), R0
+       MOVW    4(FP), R1
+       MOVW    8(FP), R2
+       MVN     $37, R12        // semaphore_timedwait_trap
+       SWI     $0x80
+       MOVW    R0, ret+12(FP)
+       RET
+
+// uint32 mach_semaphore_signal(uint32)
+TEXT runtime·mach_semaphore_signal(SB),NOSPLIT,$0
+       MOVW    0(FP), R0
+       MVN     $32, R12        // semaphore_signal_trap
+       SWI     $0x80
+       MOVW    R0, ret+4(FP)
+       RET
+
+// uint32 mach_semaphore_signal_all(uint32)
+TEXT runtime·mach_semaphore_signal_all(SB),NOSPLIT,$0
+       MOVW    0(FP), R0
+       MVN     $33, R12        // semaphore_signal_all_trap
+       SWI     $0x80
+       MOVW    R0, ret+4(FP)
+       RET
+
+// int32 runtime·kqueue(void)
+TEXT runtime·kqueue(SB),NOSPLIT,$0
+       MOVW    $SYS_kqueue, R12
+       SWI     $0x80
+       RSB.CS  $0, R0, R0
+       MOVW    R0, ret+0(FP)
+       RET
+
+// int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int events, Timespec *timeout)
+TEXT runtime·kevent(SB),NOSPLIT,$0
+       MOVW    $SYS_kevent, R12
+       MOVW    kq+0(FP), R0
+       MOVW    changelist+4(FP), R1
+       MOVW    nchanges+8(FP), R2
+       MOVW    eventlist+12(FP), R3
+       MOVW    nevents+16(FP), R4
+       MOVW    timeout+20(FP), R5
+       SWI     $0x80
+       RSB.CS  $0, R0, R0
+       MOVW    R0, ret+24(FP)
+       RET
+
+// int32 runtime·closeonexec(int32 fd)
+TEXT runtime·closeonexec(SB),NOSPLIT,$0
+       MOVW    $SYS_fcntl, R12
+       MOVW    0(FP), R0
+       MOVW    $2, R1  // F_SETFD
+       MOVW    $1, R2  // FD_CLOEXEC
+       SWI     $0x80
+       RET
+
+// sigaltstack on some darwin/arm version is buggy and will always
+// run the signal handler on the main stack, so our sigtramp has
+// to do the stack switch ourselves.
+TEXT runtime·sigaltstack(SB),NOSPLIT,$0
+       RET
index 4b01d12c460a0450181b34e51bd285e781e0c38e..2dbab722b072519fa2a6955181f902e1a47482a3 100644 (file)
 // Note: both functions will clobber R0 and R11 and
 // can be called from 5c ABI code.
 
-// On android, runtime.tlsg is a normal variable.
+// On android and darwin, runtime.tlsg is a normal variable.
 // TLS offset is computed in x_cgo_inittls.
 #ifdef GOOS_android
 #define TLSG_IS_VARIABLE
 #endif
+#ifdef GOOS_darwin
+#define TLSG_IS_VARIABLE
+#endif
 
 // save_g saves the g register into pthread-provided
 // thread-local memory, so that we can call externally compiled
@@ -37,6 +40,7 @@ TEXT runtime·save_g(SB),NOSPLIT,$-4
        // a call to runtime.read_tls_fallback which jumps to __kuser_get_tls.
        // The replacement function saves LR in R11 over the call to read_tls_fallback.
        MRC     15, 0, R0, C13, C0, 3 // fetch TLS base pointer
+       BIC $3, R0 // Darwin/ARM might return unaligned pointer
        // $runtime.tlsg(SB) is a special linker symbol.
        // It is the offset from the TLS base pointer to our
        // thread-local storage for g.
@@ -60,6 +64,7 @@ TEXT runtime·load_g(SB),NOSPLIT,$0
 #endif
        // See save_g
        MRC     15, 0, R0, C13, C0, 3 // fetch TLS base pointer
+       BIC $3, R0 // Darwin/ARM might return unaligned pointer
        // $runtime.tlsg(SB) is a special linker symbol.
        // It is the offset from the TLS base pointer to our
        // thread-local storage for g.