]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: nacl/arm support.
authorShenghou Ma <minux@golang.org>
Thu, 10 Jul 2014 19:14:49 +0000 (15:14 -0400)
committerShenghou Ma <minux@golang.org>
Thu, 10 Jul 2014 19:14:49 +0000 (15:14 -0400)
LGTM=rsc
R=rsc, iant, dave
CC=golang-codereviews
https://golang.org/cl/103680046

12 files changed:
src/pkg/runtime/arch_arm.h
src/pkg/runtime/asm_arm.s
src/pkg/runtime/defs_nacl_arm.h [new file with mode: 0644]
src/pkg/runtime/os_nacl_arm.c [new file with mode: 0644]
src/pkg/runtime/rt0_nacl_arm.s [new file with mode: 0644]
src/pkg/runtime/runtime.c
src/pkg/runtime/signal_arm.c
src/pkg/runtime/signal_nacl_arm.h [new file with mode: 0644]
src/pkg/runtime/sys_nacl_arm.s [new file with mode: 0644]
src/pkg/runtime/tls_arm.s
src/pkg/runtime/vlop_arm.s
src/pkg/runtime/vlrt_arm.c

index b9711289f4fab26326ae7f77a1d723473e200153..2a1077e2fc19aa383089719480877c163a1a8aee 100644 (file)
@@ -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
 };
index 6711d5105be3813818985b262be3e31b0b5917d7..36b2577f30c64033a0205b39b64cc3889b5affb7 100644 (file)
@@ -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 (file)
index 0000000..9ce07cc
--- /dev/null
@@ -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 (file)
index 0000000..c94b2c7
--- /dev/null
@@ -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 (file)
index 0000000..df84d5d
--- /dev/null
@@ -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)
index 26dbbbd3e22a1c9b207207a5e9a87c524ffad25d..ec0df1d1708c60383d83d544a808aa83f62be77c 100644 (file)
@@ -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;
index 1e8636846daa77b7a44632f9b73be00a1595cee5..1f9a2325d18403b852362455ca980abe9127d880 100644 (file)
@@ -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 (file)
index 0000000..e5bbb21
--- /dev/null
@@ -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 (file)
index 0000000..6a22368
--- /dev/null
@@ -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)
index 040ce7d8562b967c4e40ea225fc4028a33df18e6..37edfa968e2fc2fee872189171fb909df7738f93 100644 (file)
 // 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
index c33640695c6121b515900cae702edd093e6f60c2..02bab3107e52e01f14babc557fade00251382452 100644 (file)
@@ -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)
index 7dd71b40e3895f334910fc26a1fb2524929dd3f4..016fd7a35714e5c5bf74722ef4b7236319675a15 100644 (file)
@@ -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)
 {