mirror of
https://github.com/golang/go
synced 2024-11-19 14:34:42 -07:00
72eb46c5a0
Other GOARCHs already handle their callee-saved FP registers, but arm was missing. Without this change, code using Cgo and floating point code might fail in mysterious and hard to debug ways. There are no floating point registers when GOARM=5, so skip the registers when runtime.goarm < 6. darwin/arm doesn't support GOARM=5, so the check is left out of rt0_darwin_arm.s. Fixes #14876 Change-Id: I6bcb90a76df3664d8ba1f33123a74b1eb2c9f8b2 Reviewed-on: https://go-review.googlesource.com/23140 Run-TryBot: Elias Naur <elias.naur@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Minux Ma <minux@golang.org>
170 lines
4.4 KiB
ArmAsm
170 lines
4.4 KiB
ArmAsm
// 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.
|
|
|
|
#include "textflag.h"
|
|
|
|
TEXT _rt0_arm_linux(SB),NOSPLIT,$-4
|
|
MOVW (R13), R0 // argc
|
|
MOVW $4(R13), R1 // argv
|
|
MOVW $_rt0_arm_linux1(SB), R4
|
|
B (R4)
|
|
|
|
// When building with -buildmode=c-shared, this symbol is called when the shared
|
|
// library is loaded.
|
|
TEXT _rt0_arm_linux_lib(SB),NOSPLIT,$104
|
|
// Preserve callee-save registers. Raspberry Pi's dlopen(), for example,
|
|
// actually cares that R11 is preserved.
|
|
MOVW R4, 12(R13)
|
|
MOVW R5, 16(R13)
|
|
MOVW R6, 20(R13)
|
|
MOVW R7, 24(R13)
|
|
MOVW R8, 28(R13)
|
|
MOVW R11, 32(R13)
|
|
|
|
// Skip floating point registers on GOARM < 6.
|
|
MOVB runtime·goarm(SB), R11
|
|
CMP $6, R11
|
|
BLT skipfpsave
|
|
MOVD F8, (32+8*1)(R13)
|
|
MOVD F9, (32+8*2)(R13)
|
|
MOVD F10, (32+8*3)(R13)
|
|
MOVD F11, (32+8*4)(R13)
|
|
MOVD F12, (32+8*5)(R13)
|
|
MOVD F13, (32+8*6)(R13)
|
|
MOVD F14, (32+8*7)(R13)
|
|
MOVD F15, (32+8*8)(R13)
|
|
skipfpsave:
|
|
// Save argc/argv.
|
|
MOVW R0, _rt0_arm_linux_lib_argc<>(SB)
|
|
MOVW R1, _rt0_arm_linux_lib_argv<>(SB)
|
|
|
|
// Synchronous initialization.
|
|
MOVW $runtime·libpreinit(SB), R2
|
|
CALL (R2)
|
|
|
|
// Create a new thread to do the runtime initialization.
|
|
MOVW _cgo_sys_thread_create(SB), R2
|
|
CMP $0, R2
|
|
BEQ nocgo
|
|
MOVW $_rt0_arm_linux_lib_go<>(SB), R0
|
|
MOVW $0, R1
|
|
BL (R2)
|
|
B rr
|
|
nocgo:
|
|
MOVW $0x800000, R0 // stacksize = 8192KB
|
|
MOVW $_rt0_arm_linux_lib_go<>(SB), R1 // fn
|
|
MOVW R0, 4(R13)
|
|
MOVW R1, 8(R13)
|
|
BL runtime·newosproc0(SB)
|
|
rr:
|
|
// Restore callee-save registers and return.
|
|
MOVB runtime·goarm(SB), R11
|
|
CMP $6, R11
|
|
BLT skipfprest
|
|
MOVD (32+8*1)(R13), F8
|
|
MOVD (32+8*2)(R13), F9
|
|
MOVD (32+8*3)(R13), F10
|
|
MOVD (32+8*4)(R13), F11
|
|
MOVD (32+8*5)(R13), F12
|
|
MOVD (32+8*6)(R13), F13
|
|
MOVD (32+8*7)(R13), F14
|
|
MOVD (32+8*8)(R13), F15
|
|
skipfprest:
|
|
MOVW 12(R13), R4
|
|
MOVW 16(R13), R5
|
|
MOVW 20(R13), R6
|
|
MOVW 24(R13), R7
|
|
MOVW 28(R13), R8
|
|
MOVW 32(R13), R11
|
|
RET
|
|
|
|
TEXT _rt0_arm_linux_lib_go<>(SB),NOSPLIT,$8
|
|
MOVW _rt0_arm_linux_lib_argc<>(SB), R0
|
|
MOVW _rt0_arm_linux_lib_argv<>(SB), R1
|
|
MOVW R0, 0(R13)
|
|
MOVW R1, 4(R13)
|
|
B runtime·rt0_go(SB)
|
|
|
|
DATA _rt0_arm_linux_lib_argc<>(SB)/4,$0
|
|
GLOBL _rt0_arm_linux_lib_argc<>(SB),NOPTR,$4
|
|
DATA _rt0_arm_linux_lib_argv<>(SB)/4,$0
|
|
GLOBL _rt0_arm_linux_lib_argv<>(SB),NOPTR,$4
|
|
|
|
TEXT _rt0_arm_linux1(SB),NOSPLIT,$-4
|
|
// We first need to detect the kernel ABI, and warn the user
|
|
// if the system only supports OABI
|
|
// The strategy here is to call some EABI syscall to see if
|
|
// SIGILL is received.
|
|
// To catch SIGILL, we have to first setup sigaction, this is
|
|
// a chicken-and-egg problem, because we can't do syscall if
|
|
// we don't know the kernel ABI... Oh, not really, we can do
|
|
// syscall in Thumb mode.
|
|
|
|
// Save argc and argv
|
|
MOVM.DB.W [R0-R1], (R13)
|
|
|
|
// Thumb mode OABI check disabled because there are some
|
|
// EABI systems that do not support Thumb execution.
|
|
// We can run on them except for this check!
|
|
|
|
// // set up sa_handler
|
|
// MOVW $bad_abi<>(SB), R0 // sa_handler
|
|
// MOVW $0, R1 // sa_flags
|
|
// MOVW $0, R2 // sa_restorer
|
|
// MOVW $0, R3 // sa_mask
|
|
// MOVM.DB.W [R0-R3], (R13)
|
|
// MOVW $4, R0 // SIGILL
|
|
// MOVW R13, R1 // sa
|
|
// SUB $16, R13
|
|
// MOVW R13, R2 // old_sa
|
|
// MOVW $8, R3 // c
|
|
// MOVW $174, R7 // sys_sigaction
|
|
// BL oabi_syscall<>(SB)
|
|
|
|
// do an EABI syscall
|
|
MOVW $20, R7 // sys_getpid
|
|
SWI $0 // this will trigger SIGILL on OABI systems
|
|
|
|
// MOVW $4, R0 // SIGILL
|
|
// MOVW R13, R1 // sa
|
|
// MOVW $0, R2 // old_sa
|
|
// MOVW $8, R3 // c
|
|
// MOVW $174, R7 // sys_sigaction
|
|
// SWI $0 // restore signal handler
|
|
// ADD $32, R13
|
|
|
|
B runtime·rt0_go(SB)
|
|
|
|
TEXT bad_abi<>(SB),NOSPLIT,$-4
|
|
// give diagnosis and exit
|
|
MOVW $2, R0 // stderr
|
|
MOVW $bad_abi_msg(SB), R1 // data
|
|
MOVW $45, R2 // len
|
|
MOVW $4, R7 // sys_write
|
|
BL oabi_syscall<>(SB)
|
|
MOVW $1, R0
|
|
MOVW $1, R7 // sys_exit
|
|
BL oabi_syscall<>(SB)
|
|
B 0(PC)
|
|
|
|
DATA bad_abi_msg+0x00(SB)/8, $"This pro"
|
|
DATA bad_abi_msg+0x08(SB)/8, $"gram can"
|
|
DATA bad_abi_msg+0x10(SB)/8, $" only be"
|
|
DATA bad_abi_msg+0x18(SB)/8, $" run on "
|
|
DATA bad_abi_msg+0x20(SB)/8, $"EABI ker"
|
|
DATA bad_abi_msg+0x28(SB)/4, $"nels"
|
|
DATA bad_abi_msg+0x2c(SB)/1, $0xa
|
|
GLOBL bad_abi_msg(SB), RODATA, $45
|
|
|
|
TEXT oabi_syscall<>(SB),NOSPLIT,$-4
|
|
ADD $1, R15, R4 // R15 is hardware PC
|
|
WORD $0xe12fff14 //BX (R4) // enter thumb mode
|
|
// TODO(minux): only supports little-endian CPUs
|
|
WORD $0x4770df01 // swi $1; bx lr
|
|
|
|
TEXT main(SB),NOSPLIT,$-4
|
|
MOVW $_rt0_arm_linux1(SB), R4
|
|
B (R4)
|
|
|