Commit d1177ed4 authored by Shenghou Ma's avatar Shenghou Ma

runtime: nacl/arm support.

LGTM=rsc
R=rsc, iant, dave
CC=golang-codereviews
https://golang.org/cl/103680046
parent 783bcba8
......@@ -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
};
......@@ -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).
......
// 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;
};
// 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();
}
// 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)
......@@ -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;
......
......@@ -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"
......
// 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)
// 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)
......@@ -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
......
......@@ -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)
......
......@@ -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)
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment