1efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// Copyright 2014 The Go Authors. All rights reserved.
2efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// Use of this source code is governed by a BSD-style
3efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// license that can be found in the LICENSE file.
4efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen
5efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen#include "go_asm.h"
6efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen#include "go_tls.h"
7efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen#include "funcdata.h"
8efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen#include "textflag.h"
9efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen
10efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// We have to resort to TLS variable to save g(R10).
11efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// One reason is that external code might trigger
12efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// SIGSEGV, and our runtime.sigtramp don't even know we
13efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// are in external code, and will continue to use R10,
14efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// this might as well result in another SIGSEGV.
15efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// Note: both functions will clobber R0 and R11 and
16efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// can be called from 5c ABI code.
17efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen
18efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// On android and darwin, runtime.tls_g is a normal variable.
19efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// TLS offset is computed in x_cgo_inittls.
20efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen#ifdef GOOS_android
21efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen#define TLSG_IS_VARIABLE
22efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen#endif
23efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen#ifdef GOOS_darwin
24efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen#define TLSG_IS_VARIABLE
25efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen#endif
26efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen
27efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// save_g saves the g register into pthread-provided
28efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// thread-local memory, so that we can call externally compiled
29efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// ARM code that will overwrite those registers.
30efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// NOTE: runtime.gogo assumes that R1 is preserved by this function.
31efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen//       runtime.mcall assumes this function only clobbers R0 and R11.
32efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// Returns with g in R0.
33efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan WillemsenTEXT runtime·save_g(SB),NOSPLIT,$-4
34efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen#ifdef GOOS_nacl
35efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	// nothing to do as nacl/arm does not use TLS at all.
36efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	MOVW	g, R0 // preserve R0 across call to setg<>
37efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	RET
38efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen#endif
39efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	// If the host does not support MRC the linker will replace it with
40efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	// a call to runtime.read_tls_fallback which jumps to __kuser_get_tls.
41efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	// The replacement function saves LR in R11 over the call to read_tls_fallback.
42efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	MRC	15, 0, R0, C13, C0, 3 // fetch TLS base pointer
43efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	BIC $3, R0 // Darwin/ARM might return unaligned pointer
44efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	MOVW	runtime·tls_g(SB), R11
45efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	ADD	R11, R0
46efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	MOVW	g, 0(R0)
47efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	MOVW	g, R0 // preserve R0 across call to setg<>
48efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	RET
49efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen
50efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// load_g loads the g register from pthread-provided
51efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// thread-local memory, for use after calling externally compiled
52efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// ARM code that overwrote those registers.
53efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan WillemsenTEXT runtime·load_g(SB),NOSPLIT,$0
54efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen#ifdef GOOS_nacl
55efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	// nothing to do as nacl/arm does not use TLS at all.
56efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	RET
57efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen#endif
58efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	// See save_g
59efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	MRC	15, 0, R0, C13, C0, 3 // fetch TLS base pointer
60efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	BIC $3, R0 // Darwin/ARM might return unaligned pointer
61efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	MOVW	runtime·tls_g(SB), R11
62efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	ADD	R11, R0
63efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	MOVW	0(R0), g
64efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	RET
65efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen
66efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// This is called from rt0_go, which runs on the system stack
67efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// using the initial stack allocated by the OS.
68efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// It calls back into standard C using the BL (R4) below.
69efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// To do that, the stack pointer must be 8-byte-aligned
70efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// on some systems, notably FreeBSD.
71efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// The ARM ABI says the stack pointer must be 8-byte-aligned
72efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// on entry to any function, but only FreeBSD's C library seems to care.
73efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// The caller was 8-byte aligned, but we push an LR.
74efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// Declare a dummy word ($4, not $0) to make sure the
75efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// frame is 8 bytes and stays 8-byte-aligned.
76efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan WillemsenTEXT runtime·_initcgo(SB),NOSPLIT,$4
77efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen#ifndef GOOS_nacl
78efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	// if there is an _cgo_init, call it.
79efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	MOVW	_cgo_init(SB), R4
80efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	CMP	$0, R4
81efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	B.EQ	nocgo
82efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	MRC     15, 0, R0, C13, C0, 3 	// load TLS base pointer
83efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	MOVW 	R0, R3 			// arg 3: TLS base pointer
84efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen#ifdef TLSG_IS_VARIABLE
85efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	MOVW 	$runtime·tls_g(SB), R2 	// arg 2: &tls_g
86efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen#else
87efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen        MOVW	$0, R2			// arg 2: not used when using platform tls
88efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen#endif
89efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	MOVW	$setg_gcc<>(SB), R1 	// arg 1: setg
90efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	MOVW	g, R0 			// arg 0: G
91efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	BL	(R4) // will clobber R0-R3
92efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen#endif
93efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsennocgo:
94efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	RET
95efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen
96efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// void setg_gcc(G*); set g called from gcc.
97efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan WillemsenTEXT setg_gcc<>(SB),NOSPLIT,$0
98efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	MOVW	R0, g
99efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen	B		runtime·save_g(SB)
100efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen
101efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen#ifdef TLSG_IS_VARIABLE
102efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan WillemsenGLOBL runtime·tls_g+0(SB), NOPTR, $4
103efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen#else
104efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan WillemsenGLOBL runtime·tls_g+0(SB), TLSBSS, $4
105efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen#endif
106