From: Joel Sing Date: Sun, 15 Feb 2015 15:03:53 +0000 (+1100) Subject: runtime: add support for openbsd/arm X-Git-Tag: go1.5beta1~1588 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=be3133bfda9c71b70d7494588c01a86e437ea920;p=gostls13.git runtime: add support for openbsd/arm Change-Id: I2bc101aa19172e705ee4de5f3c73a8b4bbf4fa6f Reviewed-on: https://go-review.googlesource.com/4912 Reviewed-by: Minux Ma --- diff --git a/src/runtime/defs_openbsd_arm.go b/src/runtime/defs_openbsd_arm.go new file mode 100644 index 0000000000..aab9276f14 --- /dev/null +++ b/src/runtime/defs_openbsd_arm.go @@ -0,0 +1,170 @@ +// created by cgo -cdefs and then converted to Go +// cgo -cdefs defs_openbsd.go + +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_FREE = 0x6 + + _SA_SIGINFO = 0x40 + _SA_RESTART = 0x2 + _SA_ONSTACK = 0x1 + + _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 = 0x1 + _FPE_INTOVF = 0x2 + _FPE_FLTDIV = 0x3 + _FPE_FLTOVF = 0x4 + _FPE_FLTUND = 0x5 + _FPE_FLTRES = 0x6 + _FPE_FLTINV = 0x7 + _FPE_FLTSUB = 0x8 + + _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_ERROR = 0x4000 + _EVFILT_READ = -0x1 + _EVFILT_WRITE = -0x2 +) + +type tforkt struct { + tf_tcb unsafe.Pointer + tf_tid *int32 + tf_stack uintptr +} + +type sigaltstackt struct { + ss_sp uintptr + ss_size uintptr + ss_flags int32 +} + +type sigcontext struct { + __sc_unused int32 + sc_mask int32 + + sc_spsr uint32 + sc_r0 uint32 + sc_r1 uint32 + sc_r2 uint32 + sc_r3 uint32 + sc_r4 uint32 + sc_r5 uint32 + sc_r6 uint32 + sc_r7 uint32 + sc_r8 uint32 + sc_r9 uint32 + sc_r10 uint32 + sc_r11 uint32 + sc_r12 uint32 + sc_usr_sp uint32 + sc_usr_lr uint32 + sc_svc_lr uint32 + sc_pc uint32 +} + +type siginfo struct { + si_signo int32 + si_code int32 + si_errno int32 + _data [116]byte +} + +type stackt struct { + ss_sp uintptr + ss_size uintptr + ss_flags int32 +} + +type timespec struct { + tv_sec int64 + tv_nsec int32 +} + +func (ts *timespec) set_sec(x int64) { + ts.tv_sec = x +} + +func (ts *timespec) set_nsec(x int32) { + ts.tv_nsec = x +} + +type timeval struct { + tv_sec int64 + tv_usec int32 +} + +func (tv *timeval) set_usec(x int32) { + tv.tv_usec = x +} + +type itimerval struct { + it_interval timeval + it_value timeval +} + +type keventt struct { + ident uint32 + filter int16 + flags uint16 + fflags uint32 + data int64 + udata *byte +} diff --git a/src/runtime/os_openbsd_arm.go b/src/runtime/os_openbsd_arm.go new file mode 100644 index 0000000000..be3f330dfb --- /dev/null +++ b/src/runtime/os_openbsd_arm.go @@ -0,0 +1,17 @@ +// 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. + +package runtime + +func checkgoarm() { + // 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_freebsd_arm.s b/src/runtime/rt0_freebsd_arm.s index f31252698e..e1bb13d53a 100644 --- a/src/runtime/rt0_freebsd_arm.s +++ b/src/runtime/rt0_freebsd_arm.s @@ -4,10 +4,8 @@ #include "textflag.h" -// FreeBSD and Linux use the same linkage to main - TEXT _rt0_arm_freebsd(SB),NOSPLIT,$-4 - MOVW (R13), R0 // argc + MOVW (R13), R0 // argc MOVW $4(R13), R1 // argv MOVM.DB.W [R0-R1], (R13) B runtime·rt0_go(SB) @@ -15,4 +13,4 @@ TEXT _rt0_arm_freebsd(SB),NOSPLIT,$-4 TEXT main(SB),NOSPLIT,$-4 MOVM.DB.W [R0-R1], (R13) MOVW $runtime·rt0_go(SB), R4 - B (R4) + B (R4) diff --git a/src/runtime/rt0_netbsd_arm.s b/src/runtime/rt0_netbsd_arm.s index bad66e06cf..2cb1182c06 100644 --- a/src/runtime/rt0_netbsd_arm.s +++ b/src/runtime/rt0_netbsd_arm.s @@ -4,10 +4,8 @@ #include "textflag.h" -// FreeBSD/NetBSD and Linux use the same linkage to main - TEXT _rt0_arm_netbsd(SB),NOSPLIT,$-4 - MOVW (R13), R0 // argc + MOVW (R13), R0 // argc MOVW $4(R13), R1 // argv MOVM.DB.W [R0-R1], (R13) B runtime·rt0_go(SB) diff --git a/src/runtime/rt0_openbsd_arm.s b/src/runtime/rt0_openbsd_arm.s new file mode 100644 index 0000000000..6207e55982 --- /dev/null +++ b/src/runtime/rt0_openbsd_arm.s @@ -0,0 +1,11 @@ +// 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 "textflag.h" + +TEXT _rt0_arm_openbsd(SB),NOSPLIT,$-4 + MOVW (R13), R0 // argc + MOVW $4(R13), R1 // argv + MOVM.DB.W [R0-R1], (R13) + B runtime·rt0_go(SB) diff --git a/src/runtime/signal_openbsd_arm.go b/src/runtime/signal_openbsd_arm.go new file mode 100644 index 0000000000..8ee255c649 --- /dev/null +++ b/src/runtime/signal_openbsd_arm.go @@ -0,0 +1,53 @@ +// 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. + +package runtime + +import "unsafe" + +type sigctxt struct { + info *siginfo + ctxt unsafe.Pointer +} + +func (c *sigctxt) regs() *sigcontext { + return (*sigcontext)(c.ctxt) +} + +func (c *sigctxt) r0() uint32 { return c.regs().sc_r0 } +func (c *sigctxt) r1() uint32 { return c.regs().sc_r1 } +func (c *sigctxt) r2() uint32 { return c.regs().sc_r2 } +func (c *sigctxt) r3() uint32 { return c.regs().sc_r3 } +func (c *sigctxt) r4() uint32 { return c.regs().sc_r4 } +func (c *sigctxt) r5() uint32 { return c.regs().sc_r5 } +func (c *sigctxt) r6() uint32 { return c.regs().sc_r6 } +func (c *sigctxt) r7() uint32 { return c.regs().sc_r7 } +func (c *sigctxt) r8() uint32 { return c.regs().sc_r8 } +func (c *sigctxt) r9() uint32 { return c.regs().sc_r9 } +func (c *sigctxt) r10() uint32 { return c.regs().sc_r10 } +func (c *sigctxt) fp() uint32 { return c.regs().sc_r11 } +func (c *sigctxt) ip() uint32 { return c.regs().sc_r12 } +func (c *sigctxt) sp() uint32 { return c.regs().sc_usr_sp } +func (c *sigctxt) lr() uint32 { return c.regs().sc_usr_lr } +func (c *sigctxt) pc() uint32 { return c.regs().sc_pc } +func (c *sigctxt) cpsr() uint32 { return c.regs().sc_spsr } +func (c *sigctxt) fault() uint32 { return c.sigaddr() } +func (c *sigctxt) trap() uint32 { return 0 } +func (c *sigctxt) error() uint32 { return 0 } +func (c *sigctxt) oldmask() uint32 { return 0 } + +func (c *sigctxt) sigcode() uint32 { return uint32(c.info.si_code) } +func (c *sigctxt) sigaddr() uint32 { + return *(*uint32)(add(unsafe.Pointer(c.info), 12)) +} + +func (c *sigctxt) set_pc(x uint32) { c.regs().sc_pc = x } +func (c *sigctxt) set_sp(x uint32) { c.regs().sc_usr_sp = x } +func (c *sigctxt) set_lr(x uint32) { c.regs().sc_usr_lr = x } +func (c *sigctxt) set_r10(x uint32) { c.regs().sc_r10 = x } + +func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) } +func (c *sigctxt) set_sigaddr(x uint32) { + *(*uint32)(add(unsafe.Pointer(c.info), 12)) = x +} diff --git a/src/runtime/sys_openbsd_arm.s b/src/runtime/sys_openbsd_arm.s new file mode 100644 index 0000000000..bc9dbdd70e --- /dev/null +++ b/src/runtime/sys_openbsd_arm.s @@ -0,0 +1,377 @@ +// Copyright 2009 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, OpenBSD +// /usr/src/sys/kern/syscalls.master for syscall numbers. +// + +#include "go_asm.h" +#include "go_tls.h" +#include "textflag.h" + +#define CLOCK_REALTIME $0 +#define CLOCK_MONOTONIC $3 + +// Exit the entire program (like C exit) +TEXT runtime·exit(SB),NOSPLIT,$-4 + MOVW status+0(FP), R0 // arg 1 - status + MOVW $1, R12 // sys_exit + SWI $0 + MOVW.CS $0, R8 // crash on syscall failure + MOVW.CS R8, (R8) + RET + +TEXT runtime·exit1(SB),NOSPLIT,$-4 + MOVW $0, R0 // arg 1 - notdead + MOVW $302, R12 // sys___threxit + SWI $0 + MOVW.CS $1, R8 // crash on syscall failure + MOVW.CS R8, (R8) + RET + +TEXT runtime·open(SB),NOSPLIT,$-4 + MOVW path+0(FP), R0 // arg 1 - path + MOVW flags+4(FP), R1 // arg 2 - flags + MOVW mode+8(FP), R2 // arg 3 - mode + MOVW $5, R12 // sys_open + SWI $0 + MOVW R0, ret+12(FP) + RET + +TEXT runtime·close(SB),NOSPLIT,$-4 + MOVW path+0(FP), R0 // arg 1 - path + MOVW $6, R12 // sys_close + SWI $0 + MOVW R0, ret+4(FP) + RET + +TEXT runtime·read(SB),NOSPLIT,$-4 + MOVW fd+0(FP), R0 // arg 1 - fd + MOVW buf+4(FP), R1 // arg 2 - buf + MOVW nbyte+8(FP), R2 // arg 3 - nbyte + MOVW $3, R12 // sys_read + SWI $0 + MOVW R0, ret+12(FP) + RET + +TEXT runtime·write(SB),NOSPLIT,$-4 + MOVW fd+0(FP), R0 // arg 1 - fd + MOVW buf+4(FP), R1 // arg 2 - buf + MOVW nbyte+8(FP), R2 // arg 3 - nbyte + MOVW $4, R12 // sys_write + SWI $0 + MOVW R0, ret+12(FP) + RET + +TEXT runtime·usleep(SB),NOSPLIT,$16 + MOVW usec+0(FP), R0 + MOVW R0, R2 + MOVW $1000000, R1 + DIV R1, R0 + MOVW R0, 4(R13) // tv_sec - l32 + MOVW $0, R0 + MOVW R0, 8(R13) // tv_sec - h32 + MOD R1, R2 + MOVW $1000, R1 + MUL R1, R2 + MOVW R2, 12(R13) // tv_nsec + + MOVW $4(R13), R0 // arg 1 - rqtp + MOVW $0, R1 // arg 2 - rmtp + MOVW $91, R12 // sys_nanosleep + SWI $0 + RET + +TEXT runtime·raise(SB),NOSPLIT,$12 + MOVW $0x12B, R12 + SWI $0 // sys_getthrid + // arg 1 - pid, already in R0 + MOVW sig+0(FP), R1 // arg 2 - signum + MOVW $37, R12 // sys_kill + SWI $0 + RET + +TEXT runtime·mmap(SB),NOSPLIT,$16 + MOVW addr+0(FP), R0 // arg 1 - addr + MOVW len+4(FP), R1 // arg 2 - len + MOVW prot+8(FP), R2 // arg 3 - prot + MOVW flags+12(FP), R3 // arg 4 - flags + MOVW fd+16(FP), R4 // arg 5 - fd (on stack) + MOVW R4, 4(R13) + MOVW $0, R5 // arg 6 - pad (on stack) + MOVW R5, 8(R13) + MOVW offset+20(FP), R6 // arg 7 - offset (on stack) + MOVW R6, 12(R13) // lower 32 bits (from Go runtime) + MOVW $0, R7 + MOVW R7, 16(R13) // high 32 bits + ADD $4, R13 + MOVW $197, R12 // sys_mmap + SWI $0 + SUB $4, R13 + MOVW R0, ret+24(FP) + RET + +TEXT runtime·munmap(SB),NOSPLIT,$0 + MOVW addr+0(FP), R0 // arg 1 - addr + MOVW len+4(FP), R1 // arg 2 - len + MOVW $73, R12 // sys_munmap + SWI $0 + MOVW.CS $0, R8 // crash on syscall failure + MOVW.CS R8, (R8) + RET + +TEXT runtime·madvise(SB),NOSPLIT,$0 + MOVW addr+0(FP), R0 // arg 1 - addr + MOVW len+4(FP), R1 // arg 2 - len + MOVW behav+8(FP), R2 // arg 2 - behav + MOVW $75, R12 // sys_madvise + SWI $0 + MOVW.CS $0, R8 // crash on syscall failure + MOVW.CS R8, (R8) + RET + +TEXT runtime·setitimer(SB),NOSPLIT,$0 + MOVW which+0(FP), R0 // arg 1 - which + MOVW value+4(FP), R1 // arg 2 - value + MOVW ovalue+8(FP), R2 // arg 3 - ovalue + MOVW $69, R12 // sys_setitimer + SWI $0 + RET + +// func now() (sec int64, nsec int32) +TEXT time·now(SB), NOSPLIT, $32 + MOVW CLOCK_REALTIME, R0 // arg 1 - clock_id + MOVW $8(R13), R1 // arg 2 - tp + MOVW $87, R12 // sys_clock_gettime + SWI $0 + + MOVW 8(R13), R0 // sec - l32 + MOVW 12(R13), R1 // sec - h32 + MOVW 16(R13), R2 // nsec + + MOVW R0, sec_lo+0(FP) + MOVW R1, sec_hi+4(FP) + MOVW R2, nsec+8(FP) + + RET + +// int64 nanotime(void) so really +// void nanotime(int64 *nsec) +TEXT runtime·nanotime(SB),NOSPLIT,$32 + MOVW CLOCK_MONOTONIC, R0 // arg 1 - clock_id + MOVW $8(R13), R1 // arg 2 - tp + MOVW $87, R12 // sys_clock_gettime + SWI $0 + + MOVW 8(R13), R0 // sec - l32 + MOVW 12(R13), R4 // sec - h32 + MOVW 16(R13), R2 // nsec + + MOVW $1000000000, R3 + MULLU R0, R3, (R1, R0) + MUL R3, R4 + ADD.S R2, R0 + ADC R4, R1 + + MOVW R0, ret_lo+0(FP) + MOVW R1, ret_hi+4(FP) + RET + +TEXT runtime·sigaction(SB),NOSPLIT,$0 + MOVW signum+0(FP), R0 // arg 1 - signum + MOVW nsa+4(FP), R1 // arg 2 - nsa + MOVW osa+8(FP), R2 // arg 3 - osa + MOVW $46, R12 // sys_sigaction + SWI $0 + MOVW.CS $3, R8 // crash on syscall failure + MOVW.CS R8, (R8) + RET + +TEXT runtime·sigprocmask(SB),NOSPLIT,$0 + MOVW how+0(FP), R0 // arg 1 - how + MOVW mask+4(FP), R1 // arg 2 - mask + MOVW $48, R12 // sys_sigprocmask + SWI $0 + MOVW.CS $3, R8 // crash on syscall failure + MOVW.CS R8, (R8) + MOVW R0, ret+8(FP) + RET + +TEXT runtime·sigtramp(SB),NOSPLIT,$24 + // If called from an external code context, g will not be set. + // Save R0, since runtime·load_g will clobber it. + MOVW R0, 4(R13) // signum + MOVB runtime·iscgo(SB), R0 + CMP $0, R0 + BL.NE runtime·load_g(SB) + + CMP $0, g + BNE 4(PC) + // Signal number saved in 4(R13). + MOVW runtime·badsignal(SB), R11 + BL (R11) + RET + + // Save g. + MOVW g, R3 + MOVW g, 20(R13) + + // g = m->signal + MOVW g_m(g), R8 + MOVW m_gsignal(R8), g + + // R0 already saved. + MOVW R1, 8(R13) // info + MOVW R2, 12(R13) // context + MOVW R3, 16(R13) // gp (original g) + + BL runtime·sighandler(SB) + + // Restore g. + MOVW 20(R13), g + RET + +// int32 tfork(void *param, uintptr psize, M *mp, G *gp, void (*fn)(void)); +TEXT runtime·tfork(SB),NOSPLIT,$0 + + // Copy mp, gp and fn off parent stack for use by child. + MOVW mm+8(FP), R4 + MOVW gg+12(FP), R5 + MOVW fn+16(FP), R6 + + MOVW param+0(FP), R0 // arg 1 - param + MOVW psize+4(FP), R1 // arg 2 - psize + MOVW $8, R12 // sys___tfork + SWI $0 + + // Return if syscall failed. + B.CC 4(PC) + RSB $0, R0 + MOVW R0, ret+20(FP) + RET + + // In parent, return. + CMP $0, R0 + BEQ 3(PC) + MOVW R0, ret+20(FP) + RET + + // Initialise m, g. + MOVW R5, g + MOVW R4, g_m(g) + + // Paranoia; check that stack splitting code works. + BL runtime·emptyfunc(SB) + + // Call fn. + BL (R6) + + BL runtime·exit1(SB) + MOVW $2, R8 // crash if reached + MOVW R8, (R8) + RET + +TEXT runtime·sigaltstack(SB),NOSPLIT,$0 + MOVW nss+0(FP), R0 // arg 1 - nss + MOVW oss+4(FP), R1 // arg 2 - oss + MOVW $288, R12 // sys_sigaltstack + SWI $0 + MOVW.CS $0, R8 // crash on syscall failure + MOVW.CS R8, (R8) + RET + +TEXT runtime·osyield(SB),NOSPLIT,$0 + MOVW $298, R12 // sys_sched_yield + SWI $0 + RET + +TEXT runtime·thrsleep(SB),NOSPLIT,$4 + MOVW ident+0(FP), R0 // arg 1 - ident + MOVW clock_id+4(FP), R1 // arg 2 - clock_id + MOVW tp+8(FP), R2 // arg 3 - tp + MOVW lock+12(FP), R3 // arg 4 - lock + MOVW abort+16(FP), R4 // arg 5 - abort (on stack) + MOVW R4, 4(R13) + ADD $4, R13 + MOVW $94, R12 // sys___thrsleep + SWI $0 + SUB $4, R13 + MOVW R0, ret+20(FP) + RET + +TEXT runtime·thrwakeup(SB),NOSPLIT,$0 + MOVW ident+0(FP), R0 // arg 1 - ident + MOVW n+4(FP), R1 // arg 2 - n + MOVW $301, R12 // sys___thrwakeup + SWI $0 + MOVW R0, ret+8(FP) + RET + +TEXT runtime·sysctl(SB),NOSPLIT,$8 + MOVW name+0(FP), R0 // arg 1 - name + MOVW namelen+4(FP), R1 // arg 2 - namelen + MOVW oldp+8(FP), R2 // arg 3 - oldp + MOVW oldlenp+12(FP), R3 // arg 4 - oldlenp + MOVW newp+16(FP), R4 // arg 5 - newp (on stack) + MOVW R4, 4(R13) + MOVW newlen+20(FP), R5 // arg 6 - newlen (on stack) + MOVW R5, 8(R13) + ADD $4, R13 + MOVW $202, R12 // sys___sysctl + SWI $0 + SUB $4, R13 + MOVW.CC $0, R0 + RSB.CS $0, R0 + MOVW R0, ret+24(FP) + RET + +// int32 runtime·kqueue(void); +TEXT runtime·kqueue(SB),NOSPLIT,$0 + MOVW $269, R12 // sys_kqueue + SWI $0 + RSB.CS $0, R0 + MOVW R0, ret+0(FP) + RET + +// int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int nevents, Timespec *timeout); +TEXT runtime·kevent(SB),NOSPLIT,$8 + MOVW fd+0(FP), R0 // arg 1 - fd + MOVW changelist+4(FP), R1 // arg 2 - changelist + MOVW nchanges+8(FP), R2 // arg 3 - nchanges + MOVW eventlist+12(FP), R3 // arg 4 - eventlist + MOVW nevents+16(FP), R4 // arg 5 - nevents (on stack) + MOVW R4, 4(R13) + MOVW timeout+20(FP), R5 // arg 6 - timeout (on stack) + MOVW R5, 8(R13) + ADD $4, R13 + MOVW $72, R12 // sys_kevent + SWI $0 + RSB.CS $0, R0 + SUB $4, R13 + MOVW R0, ret+24(FP) + RET + +// int32 runtime·closeonexec(int32 fd); +TEXT runtime·closeonexec(SB),NOSPLIT,$0 + MOVW fd+0(FP), R0 // arg 1 - fd + MOVW $2, R1 // arg 2 - cmd (F_SETFD) + MOVW $1, R2 // arg 3 - arg (FD_CLOEXEC) + MOVW $92, R12 // sys_fcntl + SWI $0 + RSB.CS $0, R0 + MOVW R0, ret+4(FP) + RET + +TEXT runtime·casp1(SB),NOSPLIT,$0 + //B runtime·armcas(SB) + B runtime·cas(SB) + +TEXT runtime·cas(SB),NOSPLIT,$0 + B runtime·armcas(SB) + +// TODO(jsing): Implement. +TEXT runtime·read_tls_fallback(SB),NOSPLIT,$-4 + MOVW $5, R0 + MOVW R0, (R0) + RET