summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShenghou Ma <minux@golang.org>2014-07-10 15:14:49 -0400
committerShenghou Ma <minux@golang.org>2014-07-10 15:14:49 -0400
commit45f9364cbee013841e7f94eeda48d0d3cf9f2585 (patch)
tree9e3297a91fc9bd1040cc6a3fdefb9b9d097e8cbd /src
parentd6679956474eb5d4bf469c228d697648bc80b8f9 (diff)
downloadgo-45f9364cbee013841e7f94eeda48d0d3cf9f2585.tar.gz
runtime: nacl/arm support.
LGTM=rsc R=rsc, iant, dave CC=golang-codereviews https://codereview.appspot.com/103680046
Diffstat (limited to 'src')
-rw-r--r--src/pkg/runtime/arch_arm.h6
-rw-r--r--src/pkg/runtime/asm_arm.s9
-rw-r--r--src/pkg/runtime/defs_nacl_arm.h70
-rw-r--r--src/pkg/runtime/os_nacl_arm.c24
-rw-r--r--src/pkg/runtime/rt0_nacl_arm.s20
-rw-r--r--src/pkg/runtime/runtime.c10
-rw-r--r--src/pkg/runtime/signal_arm.c2
-rw-r--r--src/pkg/runtime/signal_nacl_arm.h28
-rw-r--r--src/pkg/runtime/sys_nacl_arm.s278
-rw-r--r--src/pkg/runtime/tls_arm.s8
-rw-r--r--src/pkg/runtime/vlop_arm.s43
-rw-r--r--src/pkg/runtime/vlrt_arm.c1
12 files changed, 470 insertions, 29 deletions
diff --git a/src/pkg/runtime/arch_arm.h b/src/pkg/runtime/arch_arm.h
index b9711289f..2a1077e2f 100644
--- a/src/pkg/runtime/arch_arm.h
+++ b/src/pkg/runtime/arch_arm.h
@@ -6,7 +6,11 @@ enum {
thechar = '5',
BigEndian = 0,
CacheLineSize = 32,
- RuntimeGogoBytes = 80,
+ RuntimeGogoBytes = 84,
+#ifdef GOOS_nacl
+ PhysPageSize = 65536,
+#else
PhysPageSize = 4096,
+#endif
PCQuantum = 4
};
diff --git a/src/pkg/runtime/asm_arm.s b/src/pkg/runtime/asm_arm.s
index 6711d5105..36b2577f3 100644
--- a/src/pkg/runtime/asm_arm.s
+++ b/src/pkg/runtime/asm_arm.s
@@ -36,6 +36,7 @@ TEXT _rt0_go(SB),NOSPLIT,$-4
MOVW R13, g_stackbase(g)
BL runtime·emptyfunc(SB) // fault if stack check is wrong
+#ifndef GOOS_nacl
// if there is an _cgo_init, call it.
MOVW _cgo_init(SB), R4
CMP $0, R4
@@ -46,6 +47,7 @@ TEXT _rt0_go(SB),NOSPLIT,$-4
MOVW $setg_gcc<>(SB), R1 // arg 1: setg
MOVW g, R0 // arg 0: G
BL (R4) // will clobber R0-R3
+#endif
nocgo:
// update stackguard after _cgo_init
@@ -90,7 +92,11 @@ GLOBL runtime·main·f(SB),RODATA,$4
TEXT runtime·breakpoint(SB),NOSPLIT,$0-0
// gdb won't skip this breakpoint instruction automatically,
// so you must manually "set $pc+=4" to skip it and continue.
+#ifdef GOOS_nacl
+ WORD $0xe125be7f // BKPT 0x5bef, NACL_INSTR_ARM_BREAKPOINT
+#else
WORD $0xe1200071 // BKPT 0x0001
+#endif
RET
TEXT runtime·asminit(SB),NOSPLIT,$0-0
@@ -139,7 +145,8 @@ TEXT runtime·gogo(SB), NOSPLIT, $-4-4
MOVW R11, gobuf_lr(R1)
MOVW R11, gobuf_ctxt(R1)
CMP R11, R11 // set condition codes for == test, needed by stack split
- MOVW gobuf_pc(R1), PC
+ MOVW gobuf_pc(R1), R11
+ B (R11)
// void mcall(void (*fn)(G*))
// Switch to m->g0's stack, call fn(g).
diff --git a/src/pkg/runtime/defs_nacl_arm.h b/src/pkg/runtime/defs_nacl_arm.h
new file mode 100644
index 000000000..9ce07ccb2
--- /dev/null
+++ b/src/pkg/runtime/defs_nacl_arm.h
@@ -0,0 +1,70 @@
+// 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.
+
+// Created by hand, not machine generated.
+
+enum
+{
+ // These values are referred to in the source code
+ // but really don't matter. Even so, use the standard numbers.
+ SIGSEGV = 11,
+ SIGPROF = 27,
+};
+
+typedef struct Siginfo Siginfo;
+
+// native_client/src/trusted/service_runtime/include/machine/_types.h
+typedef struct Timespec Timespec;
+
+struct Timespec
+{
+ int64 tv_sec;
+ int32 tv_nsec;
+};
+
+// native_client/src/trusted/service_runtime/nacl_exception.h
+// native_client/src/include/nacl/nacl_exception.h
+
+typedef struct ExcContext ExcContext;
+typedef struct ExcPortable ExcPortable;
+typedef struct ExcRegsARM ExcRegsARM;
+
+struct ExcRegsARM
+{
+ uint32 r0;
+ uint32 r1;
+ uint32 r2;
+ uint32 r3;
+ uint32 r4;
+ uint32 r5;
+ uint32 r6;
+ uint32 r7;
+ uint32 r8;
+ uint32 r9; // the value reported here is undefined.
+ uint32 r10;
+ uint32 r11;
+ uint32 r12;
+ uint32 sp; /* r13 */
+ uint32 lr; /* r14 */
+ uint32 pc; /* r15 */
+ uint32 cpsr;
+};
+
+struct ExcContext
+{
+ uint32 size;
+ uint32 portable_context_offset;
+ uint32 portable_context_size;
+ uint32 arch;
+ uint32 regs_size;
+ uint32 reserved[11];
+ ExcRegsARM regs;
+};
+
+struct ExcPortableContext
+{
+ uint32 pc;
+ uint32 sp;
+ uint32 fp;
+};
diff --git a/src/pkg/runtime/os_nacl_arm.c b/src/pkg/runtime/os_nacl_arm.c
new file mode 100644
index 000000000..c94b2c78a
--- /dev/null
+++ b/src/pkg/runtime/os_nacl_arm.c
@@ -0,0 +1,24 @@
+// 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 "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+#include "../../cmd/ld/textflag.h"
+
+void
+runtime·checkgoarm(void)
+{
+ return; // NaCl/ARM only supports ARMv7
+}
+
+#pragma textflag NOSPLIT
+int64
+runtime·cputicks(void)
+{
+ // 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 runtime·nanotime();
+}
diff --git a/src/pkg/runtime/rt0_nacl_arm.s b/src/pkg/runtime/rt0_nacl_arm.s
new file mode 100644
index 000000000..df84d5d02
--- /dev/null
+++ b/src/pkg/runtime/rt0_nacl_arm.s
@@ -0,0 +1,20 @@
+// 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 "../../cmd/ld/textflag.h"
+
+// NaCl entry has:
+// 0(FP) - 0
+// 4(FP) - cleanup function pointer, always 0
+// 8(FP) - envc
+// 12(FP) - argc
+// 16(FP) - argv, then 0, then envv, then 0, then auxv
+TEXT _rt0_arm_nacl(SB),NOSPLIT,$-4
+ MOVW 8(R13), R0
+ MOVW $12(R13), R1
+ MOVM.DB.W [R0-R1], (R13)
+ B main(SB)
+
+TEXT main(SB),NOSPLIT,$0
+ B _rt0_go(SB)
diff --git a/src/pkg/runtime/runtime.c b/src/pkg/runtime/runtime.c
index 26dbbbd3e..ec0df1d17 100644
--- a/src/pkg/runtime/runtime.c
+++ b/src/pkg/runtime/runtime.c
@@ -370,11 +370,6 @@ runtime·timediv(int64 v, int32 div, int32 *rem)
{
int32 res, bit;
- if(v >= (int64)div*0x7fffffffLL) {
- if(rem != nil)
- *rem = 0;
- return 0x7fffffff;
- }
res = 0;
for(bit = 30; bit >= 0; bit--) {
if(v >= ((int64)div<<bit)) {
@@ -382,6 +377,11 @@ runtime·timediv(int64 v, int32 div, int32 *rem)
res += 1<<bit;
}
}
+ if(v >= (int64)div) {
+ if(rem != nil)
+ *rem = 0;
+ return 0x7fffffff;
+ }
if(rem != nil)
*rem = v;
return res;
diff --git a/src/pkg/runtime/signal_arm.c b/src/pkg/runtime/signal_arm.c
index 1e8636846..1f9a2325d 100644
--- a/src/pkg/runtime/signal_arm.c
+++ b/src/pkg/runtime/signal_arm.c
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
diff --git a/src/pkg/runtime/signal_nacl_arm.h b/src/pkg/runtime/signal_nacl_arm.h
new file mode 100644
index 000000000..e5bbb211d
--- /dev/null
+++ b/src/pkg/runtime/signal_nacl_arm.h
@@ -0,0 +1,28 @@
+// 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.
+
+#define SIG_REGS(ctxt) (((ExcContext*)(ctxt))->regs)
+
+#define SIG_R0(info, ctxt) (SIG_REGS(ctxt).r0)
+#define SIG_R1(info, ctxt) (SIG_REGS(ctxt).r1)
+#define SIG_R2(info, ctxt) (SIG_REGS(ctxt).r2)
+#define SIG_R3(info, ctxt) (SIG_REGS(ctxt).r3)
+#define SIG_R4(info, ctxt) (SIG_REGS(ctxt).r4)
+#define SIG_R5(info, ctxt) (SIG_REGS(ctxt).r5)
+#define SIG_R6(info, ctxt) (SIG_REGS(ctxt).r6)
+#define SIG_R7(info, ctxt) (SIG_REGS(ctxt).r7)
+#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).r8)
+#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).r9)
+#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).r10)
+#define SIG_FP(info, ctxt) (SIG_REGS(ctxt).r11)
+#define SIG_IP(info, ctxt) (SIG_REGS(ctxt).r12)
+#define SIG_SP(info, ctxt) (SIG_REGS(ctxt).sp)
+#define SIG_LR(info, ctxt) (SIG_REGS(ctxt).lr)
+#define SIG_PC(info, ctxt) (SIG_REGS(ctxt).pc)
+#define SIG_CPSR(info, ctxt) (SIG_REGS(ctxt).cpsr)
+#define SIG_FAULT(info, ctxt) (~0)
+#define SIG_TRAP(info, ctxt) (~0)
+#define SIG_ERROR(info, ctxt) (~0)
+#define SIG_OLDMASK(info, ctxt) (~0)
+#define SIG_CODE0(info, ctxt) (~0)
diff --git a/src/pkg/runtime/sys_nacl_arm.s b/src/pkg/runtime/sys_nacl_arm.s
new file mode 100644
index 000000000..6a2236850
--- /dev/null
+++ b/src/pkg/runtime/sys_nacl_arm.s
@@ -0,0 +1,278 @@
+// 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 "zasm_GOOS_GOARCH.h"
+#include "../../cmd/ld/textflag.h"
+#include "syscall_nacl.h"
+
+#define NACL_SYSCALL(code) \
+ MOVW $(0x10000 + ((code)<<5)), R8; BL (R8)
+
+#define NACL_SYSJMP(code) \
+ MOVW $(0x10000 + ((code)<<5)), R8; B (R8)
+
+TEXT runtime·exit(SB),NOSPLIT,$0
+ MOVW arg1+0(FP), R0
+ NACL_SYSJMP(SYS_exit)
+
+TEXT runtime·exit1(SB),NOSPLIT,$0
+ MOVW arg1+0(FP), R0
+ NACL_SYSJMP(SYS_thread_exit)
+
+TEXT runtime·open(SB),NOSPLIT,$0
+ MOVW arg1+0(FP), R0
+ MOVW arg2+0(FP), R1
+ MOVW arg3+0(FP), R2
+ NACL_SYSJMP(SYS_open)
+
+TEXT runtime·close(SB),NOSPLIT,$0
+ MOVW arg1+0(FP), R0
+ NACL_SYSJMP(SYS_close)
+
+TEXT runtime·read(SB),NOSPLIT,$0
+ MOVW arg1+0(FP), R0
+ MOVW arg2+4(FP), R1
+ MOVW arg3+8(FP), R2
+ NACL_SYSJMP(SYS_read)
+
+// func naclWrite(fd int, b []byte) int
+TEXT syscall·naclWrite(SB),NOSPLIT,$0
+ MOVW arg1+0(FP), R0
+ MOVW arg2+4(FP), R1
+ MOVW arg3+8(FP), R2
+ NACL_SYSCALL(SYS_write)
+ MOVW R0, ret+16(FP)
+ RET
+
+TEXT runtime·write(SB),NOSPLIT,$0
+ MOVW arg1+0(FP), R0
+ MOVW arg2+4(FP), R1
+ MOVW arg3+8(FP), R2
+ NACL_SYSJMP(SYS_write)
+
+TEXT runtime·nacl_exception_stack(SB),NOSPLIT,$0
+ MOVW arg1+0(FP), R0
+ MOVW arg2+4(FP), R1
+ NACL_SYSJMP(SYS_exception_stack)
+
+TEXT runtime·nacl_exception_handler(SB),NOSPLIT,$0
+ MOVW arg1+0(FP), R0
+ MOVW arg2+4(FP), R1
+ NACL_SYSJMP(SYS_exception_handler)
+
+TEXT runtime·nacl_sem_create(SB),NOSPLIT,$0
+ MOVW arg1+0(FP), R0
+ NACL_SYSJMP(SYS_sem_create)
+
+TEXT runtime·nacl_sem_wait(SB),NOSPLIT,$0
+ MOVW arg1+0(FP), R0
+ NACL_SYSJMP(SYS_sem_wait)
+
+TEXT runtime·nacl_sem_post(SB),NOSPLIT,$0
+ MOVW arg1+0(FP), R0
+ NACL_SYSJMP(SYS_sem_post)
+
+TEXT runtime·nacl_mutex_create(SB),NOSPLIT,$0
+ MOVW arg1+0(FP), R0
+ NACL_SYSJMP(SYS_mutex_create)
+
+TEXT runtime·nacl_mutex_lock(SB),NOSPLIT,$0
+ MOVW arg1+0(FP), R0
+ NACL_SYSJMP(SYS_mutex_lock)
+
+TEXT runtime·nacl_mutex_trylock(SB),NOSPLIT,$0
+ MOVW arg1+0(FP), R0
+ NACL_SYSJMP(SYS_mutex_trylock)
+
+TEXT runtime·nacl_mutex_unlock(SB),NOSPLIT,$0
+ MOVW arg1+0(FP), R0
+ NACL_SYSJMP(SYS_mutex_unlock)
+
+TEXT runtime·nacl_cond_create(SB),NOSPLIT,$0
+ MOVW arg1+0(FP), R0
+ NACL_SYSJMP(SYS_cond_create)
+
+TEXT runtime·nacl_cond_wait(SB),NOSPLIT,$0
+ MOVW arg1+0(FP), R0
+ MOVW arg2+4(FP), R1
+ NACL_SYSJMP(SYS_cond_wait)
+
+TEXT runtime·nacl_cond_signal(SB),NOSPLIT,$0
+ MOVW arg1+0(FP), R0
+ NACL_SYSJMP(SYS_cond_signal)
+
+TEXT runtime·nacl_cond_broadcast(SB),NOSPLIT,$0
+ MOVW arg1+0(FP), R0
+ NACL_SYSJMP(SYS_cond_broadcast)
+
+TEXT runtime·nacl_cond_timed_wait_abs(SB),NOSPLIT,$0
+ MOVW arg1+0(FP), R0
+ MOVW arg2+4(FP), R1
+ MOVW arg3+8(FP), R2
+ NACL_SYSJMP(SYS_cond_timed_wait_abs)
+
+TEXT runtime·nacl_thread_create(SB),NOSPLIT,$0
+ MOVW arg1+0(FP), R0
+ MOVW arg2+4(FP), R1
+ MOVW arg3+8(FP), R2
+ MOVW arg4+12(FP), R3
+ NACL_SYSJMP(SYS_thread_create)
+
+TEXT runtime·mstart_nacl(SB),NOSPLIT,$0
+ MOVW 0(R9), R0 // TLS
+ MOVW -8(R0), R1 // g
+ MOVW -4(R0), R2 // m
+ MOVW R2, g_m(R1)
+ MOVW R1, g
+ B runtime·mstart(SB)
+
+TEXT runtime·nacl_nanosleep(SB),NOSPLIT,$0
+ MOVW arg1+0(FP), R0
+ MOVW arg2+4(FP), R1
+ NACL_SYSJMP(SYS_nanosleep)
+
+TEXT runtime·osyield(SB),NOSPLIT,$0
+ NACL_SYSJMP(SYS_sched_yield)
+
+TEXT runtime·mmap(SB),NOSPLIT,$8
+ MOVW arg1+0(FP), R0
+ MOVW arg2+4(FP), R1
+ MOVW arg3+8(FP), R2
+ MOVW arg4+12(FP), R3
+ MOVW arg5+16(FP), R4
+ // arg6:offset should be passed as a pointer (to int64)
+ MOVW arg6+20(FP), R5
+ MOVW R5, 4(R13)
+ MOVW $0, R6
+ MOVW R6, 8(R13)
+ MOVW $4(R13), R5
+ MOVM.DB.W [R4,R5], (R13) // arg5 and arg6 are passed on stack
+ NACL_SYSCALL(SYS_mmap)
+ MOVM.IA.W (R13), [R4, R5]
+ CMP $-4095, R0
+ RSB.HI $0, R0
+ RET
+
+TEXT time·now(SB),NOSPLIT,$16
+ MOVW $0, R0 // real time clock
+ MOVW $4(R13), R1
+ NACL_SYSCALL(SYS_clock_gettime)
+ MOVW 4(R13), R0 // low 32-bit sec
+ MOVW 8(R13), R1 // high 32-bit sec
+ MOVW 12(R13), R2 // nsec
+ MOVW R0, sec+0(FP)
+ MOVW R1, sec+4(FP)
+ MOVW R2, sec+8(FP)
+ RET
+
+TEXT syscall·now(SB),NOSPLIT,$0
+ B time·now(SB)
+
+TEXT runtime·nacl_clock_gettime(SB),NOSPLIT,$0
+ MOVW arg1+0(FP), R0
+ MOVW arg2+4(FP), R1
+ NACL_SYSJMP(SYS_clock_gettime)
+
+// int64 nanotime(void) so really
+// void nanotime(int64 *nsec)
+TEXT runtime·nanotime(SB),NOSPLIT,$16
+ MOVW $0, R0 // real time clock
+ MOVW $4(R13), R1
+ NACL_SYSCALL(SYS_clock_gettime)
+ MOVW 4(R13), R0 // low 32-bit sec
+ MOVW 8(R13), R1 // high 32-bit sec (ignored for now)
+ MOVW 12(R13), R2 // nsec
+ MOVW $1000000000, R3
+ MULLU R0, R3, (R1, R0)
+ MOVW $0, R4
+ ADD.S R2, R0
+ ADC R4, R1
+ MOVW 0(FP), R2
+ MOVW R0, 0(R2)
+ MOVW R1, 4(R2)
+ RET
+
+TEXT runtime·sigtramp(SB),NOSPLIT,$80
+ // load g from thread context
+ MOVW $ctxt+-4(FP), R0
+ MOVW (16*4+10*4)(R0), g
+
+ // check that g exists
+ CMP $0, g
+ BNE 4(PC)
+ MOVW $runtime·badsignal2(SB), R11
+ BL (R11)
+ RET
+
+ // save g
+ MOVW g, R3
+ MOVW g, 20(R13)
+
+ // g = m->gsignal
+ MOVW g_m(g), R8
+ MOVW m_gsignal(R8), g
+
+ // copy arguments for call to sighandler
+ MOVW $11, R0
+ MOVW R0, 4(R13) // signal
+ MOVW $0, R0
+ MOVW R0, 8(R13) // siginfo
+ MOVW $ctxt+-4(FP), R0
+ MOVW R0, 12(R13) // context
+ MOVW R3, 16(R13) // g
+
+ BL runtime·sighandler(SB)
+
+ // restore g
+ MOVW 20(R13), g
+
+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.
+ MOVW $ctxt+-4(FP), R1
+ ADD $64, R1
+ MOVW (0*4)(R1), R0
+ MOVW (2*4)(R1), R2
+ MOVW (3*4)(R1), R3
+ MOVW (4*4)(R1), R4
+ MOVW (5*4)(R1), R5
+ MOVW (6*4)(R1), R6
+ MOVW (7*4)(R1), R7
+ MOVW (8*4)(R1), R8
+ // cannot write to R9
+ MOVW (10*4)(R1), g
+ MOVW (11*4)(R1), R11
+ MOVW (12*4)(R1), R12
+ MOVW (13*4)(R1), R13
+ MOVW (14*4)(R1), R14
+ MOVW (15*4)(R1), R1
+ B (R1)
+
+nog:
+ MOVW $0, R0
+ RET
+
+TEXT runtime·nacl_sysinfo(SB),NOSPLIT,$16
+ RET
+
+TEXT runtime·casp(SB),NOSPLIT,$0
+ B runtime·cas(SB)
+
+// This is only valid for ARMv6+, however, NaCl/ARM is only defined
+// for ARMv7A anyway.
+// bool armcas(int32 *val, int32 old, int32 new)
+// AtomiBLy:
+// if(*val == old){
+// *val = new;
+// return 1;
+// }else
+// return 0;
+TEXT runtime·cas(SB),NOSPLIT,$0
+ B runtime·armcas(SB)
+
+TEXT runtime·read_tls_fallback(SB),NOSPLIT,$-4
+ WORD $0xe7fedef0 // NACL_INSTR_ARM_ABORT_NOW (UDF #0xEDE0)
diff --git a/src/pkg/runtime/tls_arm.s b/src/pkg/runtime/tls_arm.s
index 040ce7d85..37edfa968 100644
--- a/src/pkg/runtime/tls_arm.s
+++ b/src/pkg/runtime/tls_arm.s
@@ -23,6 +23,10 @@
// NOTE: runtime.gogo assumes that R1 is preserved by this function.
// runtime.mcall assumes this function only clobbers R0 and R11.
TEXT runtime·save_g(SB),NOSPLIT,$0
+#ifdef GOOS_nacl
+ // nothing to do as nacl/arm does not use TLS at all.
+ RET
+#endif
MRC 15, 0, R0, C13, C0, 3 // fetch TLS base pointer
// $runtime.tlsg(SB) is a special linker symbol.
// It is the offset from the TLS base pointer to our
@@ -40,6 +44,10 @@ TEXT runtime·save_g(SB),NOSPLIT,$0
// thread-local memory, for use after calling externally compiled
// ARM code that overwrote those registers.
TEXT runtime·load_g(SB),NOSPLIT,$0
+#ifdef GOOS_nacl
+ // nothing to do as nacl/arm does not use TLS at all.
+ RET
+#endif
MRC 15, 0, R0, C13, C0, 3 // fetch TLS base pointer
// $runtime.tlsg(SB) is a special linker symbol.
// It is the offset from the TLS base pointer to our
diff --git a/src/pkg/runtime/vlop_arm.s b/src/pkg/runtime/vlop_arm.s
index c33640695..02bab3107 100644
--- a/src/pkg/runtime/vlop_arm.s
+++ b/src/pkg/runtime/vlop_arm.s
@@ -108,7 +108,8 @@ TEXT udiv<>(SB),NOSPLIT,$-4
CLZ R(q), R(s) // find normalizing shift
MOVW.S R(q)<<R(s), R(a)
MOVW $fast_udiv_tab<>-64(SB), R(M)
- MOVBU.NE R(a)>>25(R(M)), R(a) // index by most significant 7 bits of divisor
+ ADD.NE R(a)>>25, R(M), R(a) // index by most significant 7 bits of divisor
+ MOVBU.NE (R(a)), R(a)
SUB.S $7, R(s)
RSB $0, R(q), R(M) // M = -q
@@ -181,26 +182,26 @@ udiv_by_0:
MOVW R1, 0(R13) // expected here for traceback
B runtime·panicdivide(SB)
-TEXT fast_udiv_tab<>(SB),NOSPLIT,$-4
- // var tab [64]byte
- // tab[0] = 255; for i := 1; i <= 63; i++ { tab[i] = (1<<14)/(64+i) }
- // laid out here as little-endian uint32s
- WORD $0xf4f8fcff
- WORD $0xe6eaedf0
- WORD $0xdadde0e3
- WORD $0xcfd2d4d7
- WORD $0xc5c7cacc
- WORD $0xbcbec0c3
- WORD $0xb4b6b8ba
- WORD $0xacaeb0b2
- WORD $0xa5a7a8aa
- WORD $0x9fa0a2a3
- WORD $0x999a9c9d
- WORD $0x93949697
- WORD $0x8e8f9092
- WORD $0x898a8c8d
- WORD $0x85868788
- WORD $0x81828384
+// var tab [64]byte
+// tab[0] = 255; for i := 1; i <= 63; i++ { tab[i] = (1<<14)/(64+i) }
+// laid out here as little-endian uint32s
+DATA fast_udiv_tab<>+0x00(SB)/4, $0xf4f8fcff
+DATA fast_udiv_tab<>+0x04(SB)/4, $0xe6eaedf0
+DATA fast_udiv_tab<>+0x08(SB)/4, $0xdadde0e3
+DATA fast_udiv_tab<>+0x0c(SB)/4, $0xcfd2d4d7
+DATA fast_udiv_tab<>+0x10(SB)/4, $0xc5c7cacc
+DATA fast_udiv_tab<>+0x14(SB)/4, $0xbcbec0c3
+DATA fast_udiv_tab<>+0x18(SB)/4, $0xb4b6b8ba
+DATA fast_udiv_tab<>+0x1c(SB)/4, $0xacaeb0b2
+DATA fast_udiv_tab<>+0x20(SB)/4, $0xa5a7a8aa
+DATA fast_udiv_tab<>+0x24(SB)/4, $0x9fa0a2a3
+DATA fast_udiv_tab<>+0x28(SB)/4, $0x999a9c9d
+DATA fast_udiv_tab<>+0x2c(SB)/4, $0x93949697
+DATA fast_udiv_tab<>+0x30(SB)/4, $0x8e8f9092
+DATA fast_udiv_tab<>+0x34(SB)/4, $0x898a8c8d
+DATA fast_udiv_tab<>+0x38(SB)/4, $0x85868788
+DATA fast_udiv_tab<>+0x3c(SB)/4, $0x81828384
+GLOBL fast_udiv_tab<>(SB), RODATA, $64
// The linker will pass numerator in R(TMP), and it also
// expects the result in R(TMP)
diff --git a/src/pkg/runtime/vlrt_arm.c b/src/pkg/runtime/vlrt_arm.c
index 7dd71b40e..016fd7a35 100644
--- a/src/pkg/runtime/vlrt_arm.c
+++ b/src/pkg/runtime/vlrt_arm.c
@@ -506,6 +506,7 @@ _mmv(Vlong *l, Vlong *r)
l->lo = r->lo;
}
+#pragma textflag NOSPLIT
void
_vasop(Vlong *ret, void *lv, void fn(Vlong*, Vlong, Vlong), int type, Vlong rv)
{