...
Run Format

Text file src/runtime/asm_arm.s

Documentation: runtime

     1	// Copyright 2009 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	#include "go_asm.h"
     6	#include "go_tls.h"
     7	#include "funcdata.h"
     8	#include "textflag.h"
     9	
    10	// _rt0_arm is common startup code for most ARM systems when using
    11	// internal linking. This is the entry point for the program from the
    12	// kernel for an ordinary -buildmode=exe program. The stack holds the
    13	// number of arguments and the C-style argv.
    14	TEXT _rt0_arm(SB),NOSPLIT,$-4
    15		MOVW	(R13), R0	// argc
    16		MOVW	$4(R13), R1		// argv
    17		B	runtime·rt0_go(SB)
    18	
    19	// main is common startup code for most ARM systems when using
    20	// external linking. The C startup code will call the symbol "main"
    21	// passing argc and argv in the usual C ABI registers R0 and R1.
    22	TEXT main(SB),NOSPLIT,$-4
    23		B	runtime·rt0_go(SB)
    24	
    25	// _rt0_arm_lib is common startup code for most ARM systems when
    26	// using -buildmode=c-archive or -buildmode=c-shared. The linker will
    27	// arrange to invoke this function as a global constructor (for
    28	// c-archive) or when the shared library is loaded (for c-shared).
    29	// We expect argc and argv to be passed in the usual C ABI registers
    30	// R0 and R1.
    31	TEXT _rt0_arm_lib(SB),NOSPLIT,$104
    32		// Preserve callee-save registers. Raspberry Pi's dlopen(), for example,
    33		// actually cares that R11 is preserved.
    34		MOVW	R4, 12(R13)
    35		MOVW	R5, 16(R13)
    36		MOVW	R6, 20(R13)
    37		MOVW	R7, 24(R13)
    38		MOVW	R8, 28(R13)
    39		MOVW	R11, 32(R13)
    40	
    41		// Skip floating point registers on GOARM < 6.
    42		MOVB    runtime·goarm(SB), R11
    43		CMP	$6, R11
    44		BLT	skipfpsave
    45		MOVD	F8, (32+8*1)(R13)
    46		MOVD	F9, (32+8*2)(R13)
    47		MOVD	F10, (32+8*3)(R13)
    48		MOVD	F11, (32+8*4)(R13)
    49		MOVD	F12, (32+8*5)(R13)
    50		MOVD	F13, (32+8*6)(R13)
    51		MOVD	F14, (32+8*7)(R13)
    52		MOVD	F15, (32+8*8)(R13)
    53	skipfpsave:
    54		// Save argc/argv.
    55		MOVW	R0, _rt0_arm_lib_argc<>(SB)
    56		MOVW	R1, _rt0_arm_lib_argv<>(SB)
    57	
    58		// Synchronous initialization.
    59		CALL	runtime·libpreinit(SB)
    60	
    61		// Create a new thread to do the runtime initialization.
    62		MOVW	_cgo_sys_thread_create(SB), R2
    63		CMP	$0, R2
    64		BEQ	nocgo
    65		MOVW	$_rt0_arm_lib_go<>(SB), R0
    66		MOVW	$0, R1
    67		BL	(R2)
    68		B	rr
    69	nocgo:
    70		MOVW	$0x800000, R0                     // stacksize = 8192KB
    71		MOVW	$_rt0_arm_lib_go<>(SB), R1  // fn
    72		MOVW	R0, 4(R13)
    73		MOVW	R1, 8(R13)
    74		BL	runtime·newosproc0(SB)
    75	rr:
    76		// Restore callee-save registers and return.
    77		MOVB    runtime·goarm(SB), R11
    78		CMP	$6, R11
    79		BLT	skipfprest
    80		MOVD	(32+8*1)(R13), F8
    81		MOVD	(32+8*2)(R13), F9
    82		MOVD	(32+8*3)(R13), F10
    83		MOVD	(32+8*4)(R13), F11
    84		MOVD	(32+8*5)(R13), F12
    85		MOVD	(32+8*6)(R13), F13
    86		MOVD	(32+8*7)(R13), F14
    87		MOVD	(32+8*8)(R13), F15
    88	skipfprest:
    89		MOVW	12(R13), R4
    90		MOVW	16(R13), R5
    91		MOVW	20(R13), R6
    92		MOVW	24(R13), R7
    93		MOVW	28(R13), R8
    94		MOVW	32(R13), R11
    95		RET
    96	
    97	// _rt0_arm_lib_go initializes the Go runtime.
    98	// This is started in a separate thread by _rt0_arm_lib.
    99	TEXT _rt0_arm_lib_go<>(SB),NOSPLIT,$8
   100		MOVW	_rt0_arm_lib_argc<>(SB), R0
   101		MOVW	_rt0_arm_lib_argv<>(SB), R1
   102		B	runtime·rt0_go(SB)
   103	
   104	DATA _rt0_arm_lib_argc<>(SB)/4,$0
   105	GLOBL _rt0_arm_lib_argc<>(SB),NOPTR,$4
   106	DATA _rt0_arm_lib_argv<>(SB)/4,$0
   107	GLOBL _rt0_arm_lib_argv<>(SB),NOPTR,$4
   108	
   109	// using frame size $-4 means do not save LR on stack.
   110	// argc is in R0, argv is in R1.
   111	TEXT runtime·rt0_go(SB),NOSPLIT,$-4
   112		MOVW	$0xcafebabe, R12
   113	
   114		// copy arguments forward on an even stack
   115		// use R13 instead of SP to avoid linker rewriting the offsets
   116		SUB	$64, R13		// plenty of scratch
   117		AND	$~7, R13
   118		MOVW	R0, 60(R13)		// save argc, argv away
   119		MOVW	R1, 64(R13)
   120	
   121		// set up g register
   122		// g is R10
   123		MOVW	$runtime·g0(SB), g
   124		MOVW	$runtime·m0(SB), R8
   125	
   126		// save m->g0 = g0
   127		MOVW	g, m_g0(R8)
   128		// save g->m = m0
   129		MOVW	R8, g_m(g)
   130	
   131		// create istack out of the OS stack
   132		// (1MB of system stack is available on iOS and Android)
   133		MOVW	$(-64*1024+104)(R13), R0
   134		MOVW	R0, g_stackguard0(g)
   135		MOVW	R0, g_stackguard1(g)
   136		MOVW	R0, (g_stack+stack_lo)(g)
   137		MOVW	R13, (g_stack+stack_hi)(g)
   138	
   139		BL	runtime·emptyfunc(SB)	// fault if stack check is wrong
   140	
   141		BL	runtime·_initcgo(SB)	// will clobber R0-R3
   142	
   143		// update stackguard after _cgo_init
   144		MOVW	(g_stack+stack_lo)(g), R0
   145		ADD	$const__StackGuard, R0
   146		MOVW	R0, g_stackguard0(g)
   147		MOVW	R0, g_stackguard1(g)
   148	
   149		BL	runtime·check(SB)
   150	
   151		// saved argc, argv
   152		MOVW	60(R13), R0
   153		MOVW	R0, 4(R13)
   154		MOVW	64(R13), R1
   155		MOVW	R1, 8(R13)
   156		BL	runtime·args(SB)
   157		BL	runtime·checkgoarm(SB)
   158		BL	runtime·osinit(SB)
   159		BL	runtime·schedinit(SB)
   160	
   161		// create a new goroutine to start program
   162		MOVW	$runtime·mainPC(SB), R0
   163		MOVW.W	R0, -4(R13)
   164		MOVW	$8, R0
   165		MOVW.W	R0, -4(R13)
   166		MOVW	$0, R0
   167		MOVW.W	R0, -4(R13)	// push $0 as guard
   168		BL	runtime·newproc(SB)
   169		MOVW	$12(R13), R13	// pop args and LR
   170	
   171		// start this M
   172		BL	runtime·mstart(SB)
   173	
   174		MOVW	$1234, R0
   175		MOVW	$1000, R1
   176		MOVW	R0, (R1)	// fail hard
   177	
   178	DATA	runtime·mainPC+0(SB)/4,$runtime·main(SB)
   179	GLOBL	runtime·mainPC(SB),RODATA,$4
   180	
   181	TEXT runtime·breakpoint(SB),NOSPLIT,$0-0
   182		// gdb won't skip this breakpoint instruction automatically,
   183		// so you must manually "set $pc+=4" to skip it and continue.
   184	#ifdef GOOS_nacl
   185		WORD	$0xe125be7f	// BKPT 0x5bef, NACL_INSTR_ARM_BREAKPOINT
   186	#else
   187	#ifdef GOOS_plan9
   188		WORD	$0xD1200070	// undefined instruction used as armv5 breakpoint in Plan 9
   189	#else
   190		WORD	$0xe7f001f0	// undefined instruction that gdb understands is a software breakpoint
   191	#endif
   192	#endif
   193		RET
   194	
   195	TEXT runtime·asminit(SB),NOSPLIT,$0-0
   196		// disable runfast (flush-to-zero) mode of vfp if runtime.goarm > 5
   197		MOVB	runtime·goarm(SB), R11
   198		CMP	$5, R11
   199		BLE	4(PC)
   200		WORD	$0xeef1ba10	// vmrs r11, fpscr
   201		BIC	$(1<<24), R11
   202		WORD	$0xeee1ba10	// vmsr fpscr, r11
   203		RET
   204	
   205	/*
   206	 *  go-routine
   207	 */
   208	
   209	// void gosave(Gobuf*)
   210	// save state in Gobuf; setjmp
   211	TEXT runtime·gosave(SB),NOSPLIT,$-4-4
   212		MOVW	buf+0(FP), R0
   213		MOVW	R13, gobuf_sp(R0)
   214		MOVW	LR, gobuf_pc(R0)
   215		MOVW	g, gobuf_g(R0)
   216		MOVW	$0, R11
   217		MOVW	R11, gobuf_lr(R0)
   218		MOVW	R11, gobuf_ret(R0)
   219		// Assert ctxt is zero. See func save.
   220		MOVW	gobuf_ctxt(R0), R0
   221		CMP	R0, R11
   222		B.EQ	2(PC)
   223		CALL	runtime·badctxt(SB)
   224		RET
   225	
   226	// void gogo(Gobuf*)
   227	// restore state from Gobuf; longjmp
   228	TEXT runtime·gogo(SB),NOSPLIT,$8-4
   229		MOVW	buf+0(FP), R1
   230		MOVW	gobuf_g(R1), R0
   231		BL	setg<>(SB)
   232	
   233		// NOTE: We updated g above, and we are about to update SP.
   234		// Until LR and PC are also updated, the g/SP/LR/PC quadruple
   235		// are out of sync and must not be used as the basis of a traceback.
   236		// Sigprof skips the traceback when SP is not within g's bounds,
   237		// and when the PC is inside this function, runtime.gogo.
   238		// Since we are about to update SP, until we complete runtime.gogo
   239		// we must not leave this function. In particular, no calls
   240		// after this point: it must be straight-line code until the
   241		// final B instruction.
   242		// See large comment in sigprof for more details.
   243		MOVW	gobuf_sp(R1), R13	// restore SP==R13
   244		MOVW	gobuf_lr(R1), LR
   245		MOVW	gobuf_ret(R1), R0
   246		MOVW	gobuf_ctxt(R1), R7
   247		MOVW	$0, R11
   248		MOVW	R11, gobuf_sp(R1)	// clear to help garbage collector
   249		MOVW	R11, gobuf_ret(R1)
   250		MOVW	R11, gobuf_lr(R1)
   251		MOVW	R11, gobuf_ctxt(R1)
   252		MOVW	gobuf_pc(R1), R11
   253		CMP	R11, R11 // set condition codes for == test, needed by stack split
   254		B	(R11)
   255	
   256	// func mcall(fn func(*g))
   257	// Switch to m->g0's stack, call fn(g).
   258	// Fn must never return. It should gogo(&g->sched)
   259	// to keep running g.
   260	TEXT runtime·mcall(SB),NOSPLIT,$-4-4
   261		// Save caller state in g->sched.
   262		MOVW	R13, (g_sched+gobuf_sp)(g)
   263		MOVW	LR, (g_sched+gobuf_pc)(g)
   264		MOVW	$0, R11
   265		MOVW	R11, (g_sched+gobuf_lr)(g)
   266		MOVW	g, (g_sched+gobuf_g)(g)
   267	
   268		// Switch to m->g0 & its stack, call fn.
   269		MOVW	g, R1
   270		MOVW	g_m(g), R8
   271		MOVW	m_g0(R8), R0
   272		BL	setg<>(SB)
   273		CMP	g, R1
   274		B.NE	2(PC)
   275		B	runtime·badmcall(SB)
   276		MOVB	runtime·iscgo(SB), R11
   277		CMP	$0, R11
   278		BL.NE	runtime·save_g(SB)
   279		MOVW	fn+0(FP), R0
   280		MOVW	(g_sched+gobuf_sp)(g), R13
   281		SUB	$8, R13
   282		MOVW	R1, 4(R13)
   283		MOVW	R0, R7
   284		MOVW	0(R0), R0
   285		BL	(R0)
   286		B	runtime·badmcall2(SB)
   287		RET
   288	
   289	// systemstack_switch is a dummy routine that systemstack leaves at the bottom
   290	// of the G stack. We need to distinguish the routine that
   291	// lives at the bottom of the G stack from the one that lives
   292	// at the top of the system stack because the one at the top of
   293	// the system stack terminates the stack walk (see topofstack()).
   294	TEXT runtime·systemstack_switch(SB),NOSPLIT,$0-0
   295		MOVW	$0, R0
   296		BL	(R0) // clobber lr to ensure push {lr} is kept
   297		RET
   298	
   299	// func systemstack(fn func())
   300	TEXT runtime·systemstack(SB),NOSPLIT,$0-4
   301		MOVW	fn+0(FP), R0	// R0 = fn
   302		MOVW	g_m(g), R1	// R1 = m
   303	
   304		MOVW	m_gsignal(R1), R2	// R2 = gsignal
   305		CMP	g, R2
   306		B.EQ	noswitch
   307	
   308		MOVW	m_g0(R1), R2	// R2 = g0
   309		CMP	g, R2
   310		B.EQ	noswitch
   311	
   312		MOVW	m_curg(R1), R3
   313		CMP	g, R3
   314		B.EQ	switch
   315	
   316		// Bad: g is not gsignal, not g0, not curg. What is it?
   317		// Hide call from linker nosplit analysis.
   318		MOVW	$runtime·badsystemstack(SB), R0
   319		BL	(R0)
   320	
   321	switch:
   322		// save our state in g->sched. Pretend to
   323		// be systemstack_switch if the G stack is scanned.
   324		MOVW	$runtime·systemstack_switch(SB), R3
   325	#ifdef GOOS_nacl
   326		ADD	$4, R3, R3 // get past nacl-insert bic instruction
   327	#endif
   328		ADD	$4, R3, R3 // get past push {lr}
   329		MOVW	R3, (g_sched+gobuf_pc)(g)
   330		MOVW	R13, (g_sched+gobuf_sp)(g)
   331		MOVW	LR, (g_sched+gobuf_lr)(g)
   332		MOVW	g, (g_sched+gobuf_g)(g)
   333	
   334		// switch to g0
   335		MOVW	R0, R5
   336		MOVW	R2, R0
   337		BL	setg<>(SB)
   338		MOVW	R5, R0
   339		MOVW	(g_sched+gobuf_sp)(R2), R3
   340		// make it look like mstart called systemstack on g0, to stop traceback
   341		SUB	$4, R3, R3
   342		MOVW	$runtime·mstart(SB), R4
   343		MOVW	R4, 0(R3)
   344		MOVW	R3, R13
   345	
   346		// call target function
   347		MOVW	R0, R7
   348		MOVW	0(R0), R0
   349		BL	(R0)
   350	
   351		// switch back to g
   352		MOVW	g_m(g), R1
   353		MOVW	m_curg(R1), R0
   354		BL	setg<>(SB)
   355		MOVW	(g_sched+gobuf_sp)(g), R13
   356		MOVW	$0, R3
   357		MOVW	R3, (g_sched+gobuf_sp)(g)
   358		RET
   359	
   360	noswitch:
   361		// Using a tail call here cleans up tracebacks since we won't stop
   362		// at an intermediate systemstack.
   363		MOVW	R0, R7
   364		MOVW	0(R0), R0
   365		MOVW.P	4(R13), R14	// restore LR
   366		B	(R0)
   367	
   368	/*
   369	 * support for morestack
   370	 */
   371	
   372	// Called during function prolog when more stack is needed.
   373	// R1 frame size
   374	// R3 prolog's LR
   375	// NB. we do not save R0 because we've forced 5c to pass all arguments
   376	// on the stack.
   377	// using frame size $-4 means do not save LR on stack.
   378	//
   379	// The traceback routines see morestack on a g0 as being
   380	// the top of a stack (for example, morestack calling newstack
   381	// calling the scheduler calling newm calling gc), so we must
   382	// record an argument size. For that purpose, it has no arguments.
   383	TEXT runtime·morestack(SB),NOSPLIT,$-4-0
   384		// Cannot grow scheduler stack (m->g0).
   385		MOVW	g_m(g), R8
   386		MOVW	m_g0(R8), R4
   387		CMP	g, R4
   388		BNE	3(PC)
   389		BL	runtime·badmorestackg0(SB)
   390		B	runtime·abort(SB)
   391	
   392		// Cannot grow signal stack (m->gsignal).
   393		MOVW	m_gsignal(R8), R4
   394		CMP	g, R4
   395		BNE	3(PC)
   396		BL	runtime·badmorestackgsignal(SB)
   397		B	runtime·abort(SB)
   398	
   399		// Called from f.
   400		// Set g->sched to context in f.
   401		MOVW	R13, (g_sched+gobuf_sp)(g)
   402		MOVW	LR, (g_sched+gobuf_pc)(g)
   403		MOVW	R3, (g_sched+gobuf_lr)(g)
   404		MOVW	R7, (g_sched+gobuf_ctxt)(g)
   405	
   406		// Called from f.
   407		// Set m->morebuf to f's caller.
   408		MOVW	R3, (m_morebuf+gobuf_pc)(R8)	// f's caller's PC
   409		MOVW	R13, (m_morebuf+gobuf_sp)(R8)	// f's caller's SP
   410		MOVW	$4(R13), R3			// f's argument pointer
   411		MOVW	g, (m_morebuf+gobuf_g)(R8)
   412	
   413		// Call newstack on m->g0's stack.
   414		MOVW	m_g0(R8), R0
   415		BL	setg<>(SB)
   416		MOVW	(g_sched+gobuf_sp)(g), R13
   417		MOVW	$0, R0
   418		MOVW.W  R0, -4(R13)	// create a call frame on g0 (saved LR)
   419		BL	runtime·newstack(SB)
   420	
   421		// Not reached, but make sure the return PC from the call to newstack
   422		// is still in this function, and not the beginning of the next.
   423		RET
   424	
   425	TEXT runtime·morestack_noctxt(SB),NOSPLIT,$-4-0
   426		MOVW	$0, R7
   427		B runtime·morestack(SB)
   428	
   429	// reflectcall: call a function with the given argument list
   430	// func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32).
   431	// we don't have variable-sized frames, so we use a small number
   432	// of constant-sized-frame functions to encode a few bits of size in the pc.
   433	// Caution: ugly multiline assembly macros in your future!
   434	
   435	#define DISPATCH(NAME,MAXSIZE)		\
   436		CMP	$MAXSIZE, R0;		\
   437		B.HI	3(PC);			\
   438		MOVW	$NAME(SB), R1;		\
   439		B	(R1)
   440	
   441	TEXT reflect·call(SB), NOSPLIT, $0-0
   442		B	·reflectcall(SB)
   443	
   444	TEXT ·reflectcall(SB),NOSPLIT,$-4-20
   445		MOVW	argsize+12(FP), R0
   446		DISPATCH(runtime·call16, 16)
   447		DISPATCH(runtime·call32, 32)
   448		DISPATCH(runtime·call64, 64)
   449		DISPATCH(runtime·call128, 128)
   450		DISPATCH(runtime·call256, 256)
   451		DISPATCH(runtime·call512, 512)
   452		DISPATCH(runtime·call1024, 1024)
   453		DISPATCH(runtime·call2048, 2048)
   454		DISPATCH(runtime·call4096, 4096)
   455		DISPATCH(runtime·call8192, 8192)
   456		DISPATCH(runtime·call16384, 16384)
   457		DISPATCH(runtime·call32768, 32768)
   458		DISPATCH(runtime·call65536, 65536)
   459		DISPATCH(runtime·call131072, 131072)
   460		DISPATCH(runtime·call262144, 262144)
   461		DISPATCH(runtime·call524288, 524288)
   462		DISPATCH(runtime·call1048576, 1048576)
   463		DISPATCH(runtime·call2097152, 2097152)
   464		DISPATCH(runtime·call4194304, 4194304)
   465		DISPATCH(runtime·call8388608, 8388608)
   466		DISPATCH(runtime·call16777216, 16777216)
   467		DISPATCH(runtime·call33554432, 33554432)
   468		DISPATCH(runtime·call67108864, 67108864)
   469		DISPATCH(runtime·call134217728, 134217728)
   470		DISPATCH(runtime·call268435456, 268435456)
   471		DISPATCH(runtime·call536870912, 536870912)
   472		DISPATCH(runtime·call1073741824, 1073741824)
   473		MOVW	$runtime·badreflectcall(SB), R1
   474		B	(R1)
   475	
   476	#define CALLFN(NAME,MAXSIZE)			\
   477	TEXT NAME(SB), WRAPPER, $MAXSIZE-20;		\
   478		NO_LOCAL_POINTERS;			\
   479		/* copy arguments to stack */		\
   480		MOVW	argptr+8(FP), R0;		\
   481		MOVW	argsize+12(FP), R2;		\
   482		ADD	$4, R13, R1;			\
   483		CMP	$0, R2;				\
   484		B.EQ	5(PC);				\
   485		MOVBU.P	1(R0), R5;			\
   486		MOVBU.P R5, 1(R1);			\
   487		SUB	$1, R2, R2;			\
   488		B	-5(PC);				\
   489		/* call function */			\
   490		MOVW	f+4(FP), R7;			\
   491		MOVW	(R7), R0;			\
   492		PCDATA  $PCDATA_StackMapIndex, $0;	\
   493		BL	(R0);				\
   494		/* copy return values back */		\
   495		MOVW	argtype+0(FP), R4;		\
   496		MOVW	argptr+8(FP), R0;		\
   497		MOVW	argsize+12(FP), R2;		\
   498		MOVW	retoffset+16(FP), R3;		\
   499		ADD	$4, R13, R1;			\
   500		ADD	R3, R1;				\
   501		ADD	R3, R0;				\
   502		SUB	R3, R2;				\
   503		BL	callRet<>(SB);			\
   504		RET
   505	
   506	// callRet copies return values back at the end of call*. This is a
   507	// separate function so it can allocate stack space for the arguments
   508	// to reflectcallmove. It does not follow the Go ABI; it expects its
   509	// arguments in registers.
   510	TEXT callRet<>(SB), NOSPLIT, $16-0
   511		MOVW	R4, 4(R13)
   512		MOVW	R0, 8(R13)
   513		MOVW	R1, 12(R13)
   514		MOVW	R2, 16(R13)
   515		BL	runtime·reflectcallmove(SB)
   516		RET	
   517	
   518	CALLFN(·call16, 16)
   519	CALLFN(·call32, 32)
   520	CALLFN(·call64, 64)
   521	CALLFN(·call128, 128)
   522	CALLFN(·call256, 256)
   523	CALLFN(·call512, 512)
   524	CALLFN(·call1024, 1024)
   525	CALLFN(·call2048, 2048)
   526	CALLFN(·call4096, 4096)
   527	CALLFN(·call8192, 8192)
   528	CALLFN(·call16384, 16384)
   529	CALLFN(·call32768, 32768)
   530	CALLFN(·call65536, 65536)
   531	CALLFN(·call131072, 131072)
   532	CALLFN(·call262144, 262144)
   533	CALLFN(·call524288, 524288)
   534	CALLFN(·call1048576, 1048576)
   535	CALLFN(·call2097152, 2097152)
   536	CALLFN(·call4194304, 4194304)
   537	CALLFN(·call8388608, 8388608)
   538	CALLFN(·call16777216, 16777216)
   539	CALLFN(·call33554432, 33554432)
   540	CALLFN(·call67108864, 67108864)
   541	CALLFN(·call134217728, 134217728)
   542	CALLFN(·call268435456, 268435456)
   543	CALLFN(·call536870912, 536870912)
   544	CALLFN(·call1073741824, 1073741824)
   545	
   546	// void jmpdefer(fn, sp);
   547	// called from deferreturn.
   548	// 1. grab stored LR for caller
   549	// 2. sub 4 bytes to get back to BL deferreturn
   550	// 3. B to fn
   551	// TODO(rsc): Push things on stack and then use pop
   552	// to load all registers simultaneously, so that a profiling
   553	// interrupt can never see mismatched SP/LR/PC.
   554	// (And double-check that pop is atomic in that way.)
   555	TEXT runtime·jmpdefer(SB),NOSPLIT,$0-8
   556		MOVW	0(R13), LR
   557		MOVW	$-4(LR), LR	// BL deferreturn
   558		MOVW	fv+0(FP), R7
   559		MOVW	argp+4(FP), R13
   560		MOVW	$-4(R13), R13	// SP is 4 below argp, due to saved LR
   561		MOVW	0(R7), R1
   562		B	(R1)
   563	
   564	// Save state of caller into g->sched. Smashes R11.
   565	TEXT gosave<>(SB),NOSPLIT,$-4
   566		MOVW	LR, (g_sched+gobuf_pc)(g)
   567		MOVW	R13, (g_sched+gobuf_sp)(g)
   568		MOVW	$0, R11
   569		MOVW	R11, (g_sched+gobuf_lr)(g)
   570		MOVW	R11, (g_sched+gobuf_ret)(g)
   571		MOVW	R11, (g_sched+gobuf_ctxt)(g)
   572		// Assert ctxt is zero. See func save.
   573		MOVW	(g_sched+gobuf_ctxt)(g), R11
   574		CMP	$0, R11
   575		B.EQ	2(PC)
   576		CALL	runtime·badctxt(SB)
   577		RET
   578	
   579	// func asmcgocall(fn, arg unsafe.Pointer) int32
   580	// Call fn(arg) on the scheduler stack,
   581	// aligned appropriately for the gcc ABI.
   582	// See cgocall.go for more details.
   583	TEXT ·asmcgocall(SB),NOSPLIT,$0-12
   584		MOVW	fn+0(FP), R1
   585		MOVW	arg+4(FP), R0
   586	
   587		MOVW	R13, R2
   588		MOVW	g, R4
   589	
   590		// Figure out if we need to switch to m->g0 stack.
   591		// We get called to create new OS threads too, and those
   592		// come in on the m->g0 stack already.
   593		MOVW	g_m(g), R8
   594		MOVW	m_g0(R8), R3
   595		CMP	R3, g
   596		BEQ	g0
   597		BL	gosave<>(SB)
   598		MOVW	R0, R5
   599		MOVW	R3, R0
   600		BL	setg<>(SB)
   601		MOVW	R5, R0
   602		MOVW	(g_sched+gobuf_sp)(g), R13
   603	
   604		// Now on a scheduling stack (a pthread-created stack).
   605	g0:
   606		SUB	$24, R13
   607		BIC	$0x7, R13	// alignment for gcc ABI
   608		MOVW	R4, 20(R13) // save old g
   609		MOVW	(g_stack+stack_hi)(R4), R4
   610		SUB	R2, R4
   611		MOVW	R4, 16(R13)	// save depth in stack (can't just save SP, as stack might be copied during a callback)
   612		BL	(R1)
   613	
   614		// Restore registers, g, stack pointer.
   615		MOVW	R0, R5
   616		MOVW	20(R13), R0
   617		BL	setg<>(SB)
   618		MOVW	(g_stack+stack_hi)(g), R1
   619		MOVW	16(R13), R2
   620		SUB	R2, R1
   621		MOVW	R5, R0
   622		MOVW	R1, R13
   623	
   624		MOVW	R0, ret+8(FP)
   625		RET
   626	
   627	// cgocallback(void (*fn)(void*), void *frame, uintptr framesize, uintptr ctxt)
   628	// Turn the fn into a Go func (by taking its address) and call
   629	// cgocallback_gofunc.
   630	TEXT runtime·cgocallback(SB),NOSPLIT,$16-16
   631		MOVW	$fn+0(FP), R0
   632		MOVW	R0, 4(R13)
   633		MOVW	frame+4(FP), R0
   634		MOVW	R0, 8(R13)
   635		MOVW	framesize+8(FP), R0
   636		MOVW	R0, 12(R13)
   637		MOVW	ctxt+12(FP), R0
   638		MOVW	R0, 16(R13)
   639		MOVW	$runtime·cgocallback_gofunc(SB), R0
   640		BL	(R0)
   641		RET
   642	
   643	// cgocallback_gofunc(void (*fn)(void*), void *frame, uintptr framesize, uintptr ctxt)
   644	// See cgocall.go for more details.
   645	TEXT	·cgocallback_gofunc(SB),NOSPLIT,$8-16
   646		NO_LOCAL_POINTERS
   647		
   648		// Load m and g from thread-local storage.
   649		MOVB	runtime·iscgo(SB), R0
   650		CMP	$0, R0
   651		BL.NE	runtime·load_g(SB)
   652	
   653		// If g is nil, Go did not create the current thread.
   654		// Call needm to obtain one for temporary use.
   655		// In this case, we're running on the thread stack, so there's
   656		// lots of space, but the linker doesn't know. Hide the call from
   657		// the linker analysis by using an indirect call.
   658		CMP	$0, g
   659		B.EQ	needm
   660	
   661		MOVW	g_m(g), R8
   662		MOVW	R8, savedm-4(SP)
   663		B	havem
   664	
   665	needm:
   666		MOVW	g, savedm-4(SP) // g is zero, so is m.
   667		MOVW	$runtime·needm(SB), R0
   668		BL	(R0)
   669	
   670		// Set m->sched.sp = SP, so that if a panic happens
   671		// during the function we are about to execute, it will
   672		// have a valid SP to run on the g0 stack.
   673		// The next few lines (after the havem label)
   674		// will save this SP onto the stack and then write
   675		// the same SP back to m->sched.sp. That seems redundant,
   676		// but if an unrecovered panic happens, unwindm will
   677		// restore the g->sched.sp from the stack location
   678		// and then systemstack will try to use it. If we don't set it here,
   679		// that restored SP will be uninitialized (typically 0) and
   680		// will not be usable.
   681		MOVW	g_m(g), R8
   682		MOVW	m_g0(R8), R3
   683		MOVW	R13, (g_sched+gobuf_sp)(R3)
   684	
   685	havem:
   686		// Now there's a valid m, and we're running on its m->g0.
   687		// Save current m->g0->sched.sp on stack and then set it to SP.
   688		// Save current sp in m->g0->sched.sp in preparation for
   689		// switch back to m->curg stack.
   690		// NOTE: unwindm knows that the saved g->sched.sp is at 4(R13) aka savedsp-8(SP).
   691		MOVW	m_g0(R8), R3
   692		MOVW	(g_sched+gobuf_sp)(R3), R4
   693		MOVW	R4, savedsp-8(SP)
   694		MOVW	R13, (g_sched+gobuf_sp)(R3)
   695	
   696		// Switch to m->curg stack and call runtime.cgocallbackg.
   697		// Because we are taking over the execution of m->curg
   698		// but *not* resuming what had been running, we need to
   699		// save that information (m->curg->sched) so we can restore it.
   700		// We can restore m->curg->sched.sp easily, because calling
   701		// runtime.cgocallbackg leaves SP unchanged upon return.
   702		// To save m->curg->sched.pc, we push it onto the stack.
   703		// This has the added benefit that it looks to the traceback
   704		// routine like cgocallbackg is going to return to that
   705		// PC (because the frame we allocate below has the same
   706		// size as cgocallback_gofunc's frame declared above)
   707		// so that the traceback will seamlessly trace back into
   708		// the earlier calls.
   709		//
   710		// In the new goroutine, -4(SP) is unused (where SP refers to
   711		// m->curg's SP while we're setting it up, before we've adjusted it).
   712		MOVW	m_curg(R8), R0
   713		BL	setg<>(SB)
   714		MOVW	(g_sched+gobuf_sp)(g), R4 // prepare stack as R4
   715		MOVW	(g_sched+gobuf_pc)(g), R5
   716		MOVW	R5, -12(R4)
   717		MOVW	ctxt+12(FP), R0
   718		MOVW	R0, -8(R4)
   719		MOVW	$-12(R4), R13
   720		BL	runtime·cgocallbackg(SB)
   721	
   722		// Restore g->sched (== m->curg->sched) from saved values.
   723		MOVW	0(R13), R5
   724		MOVW	R5, (g_sched+gobuf_pc)(g)
   725		MOVW	$12(R13), R4
   726		MOVW	R4, (g_sched+gobuf_sp)(g)
   727	
   728		// Switch back to m->g0's stack and restore m->g0->sched.sp.
   729		// (Unlike m->curg, the g0 goroutine never uses sched.pc,
   730		// so we do not have to restore it.)
   731		MOVW	g_m(g), R8
   732		MOVW	m_g0(R8), R0
   733		BL	setg<>(SB)
   734		MOVW	(g_sched+gobuf_sp)(g), R13
   735		MOVW	savedsp-8(SP), R4
   736		MOVW	R4, (g_sched+gobuf_sp)(g)
   737	
   738		// If the m on entry was nil, we called needm above to borrow an m
   739		// for the duration of the call. Since the call is over, return it with dropm.
   740		MOVW	savedm-4(SP), R6
   741		CMP	$0, R6
   742		B.NE	3(PC)
   743		MOVW	$runtime·dropm(SB), R0
   744		BL	(R0)
   745	
   746		// Done!
   747		RET
   748	
   749	// void setg(G*); set g. for use by needm.
   750	TEXT runtime·setg(SB),NOSPLIT,$-4-4
   751		MOVW	gg+0(FP), R0
   752		B	setg<>(SB)
   753	
   754	TEXT setg<>(SB),NOSPLIT,$-4-0
   755		MOVW	R0, g
   756	
   757		// Save g to thread-local storage.
   758		MOVB	runtime·iscgo(SB), R0
   759		CMP	$0, R0
   760		B.EQ	2(PC)
   761		B	runtime·save_g(SB)
   762	
   763		MOVW	g, R0
   764		RET
   765	
   766	TEXT runtime·getcallerpc(SB),NOSPLIT,$-4-4
   767		MOVW	0(R13), R0		// LR saved by caller
   768		MOVW	R0, ret+0(FP)
   769		RET
   770	
   771	TEXT runtime·emptyfunc(SB),0,$0-0
   772		RET
   773	
   774	TEXT runtime·abort(SB),NOSPLIT,$-4-0
   775		MOVW	$0, R0
   776		MOVW	(R0), R1
   777	
   778	// armPublicationBarrier is a native store/store barrier for ARMv7+.
   779	// On earlier ARM revisions, armPublicationBarrier is a no-op.
   780	// This will not work on SMP ARMv6 machines, if any are in use.
   781	// To implement publicationBarrier in sys_$GOOS_arm.s using the native
   782	// instructions, use:
   783	//
   784	//	TEXT ·publicationBarrier(SB),NOSPLIT,$-4-0
   785	//		B	runtime·armPublicationBarrier(SB)
   786	//
   787	TEXT runtime·armPublicationBarrier(SB),NOSPLIT,$-4-0
   788		MOVB	runtime·goarm(SB), R11
   789		CMP	$7, R11
   790		BLT	2(PC)
   791		WORD $0xf57ff05e	// DMB ST
   792		RET
   793	
   794	// AES hashing not implemented for ARM
   795	TEXT runtime·aeshash(SB),NOSPLIT,$-4-0
   796		MOVW	$0, R0
   797		MOVW	(R0), R1
   798	TEXT runtime·aeshash32(SB),NOSPLIT,$-4-0
   799		MOVW	$0, R0
   800		MOVW	(R0), R1
   801	TEXT runtime·aeshash64(SB),NOSPLIT,$-4-0
   802		MOVW	$0, R0
   803		MOVW	(R0), R1
   804	TEXT runtime·aeshashstr(SB),NOSPLIT,$-4-0
   805		MOVW	$0, R0
   806		MOVW	(R0), R1
   807	
   808	// memequal(p, q unsafe.Pointer, size uintptr) bool
   809	TEXT runtime·memequal(SB),NOSPLIT,$-4-13
   810		MOVW	a+0(FP), R1
   811		MOVW	b+4(FP), R2
   812		MOVW	size+8(FP), R3
   813		ADD	R1, R3, R6
   814		MOVW	$1, R0
   815		MOVB	R0, ret+12(FP)
   816		CMP	R1, R2
   817		RET.EQ
   818	loop:
   819		CMP	R1, R6
   820		RET.EQ
   821		MOVBU.P	1(R1), R4
   822		MOVBU.P	1(R2), R5
   823		CMP	R4, R5
   824		BEQ	loop
   825	
   826		MOVW	$0, R0
   827		MOVB	R0, ret+12(FP)
   828		RET
   829	
   830	// memequal_varlen(a, b unsafe.Pointer) bool
   831	TEXT runtime·memequal_varlen(SB),NOSPLIT,$16-9
   832		MOVW	a+0(FP), R0
   833		MOVW	b+4(FP), R1
   834		CMP	R0, R1
   835		BEQ	eq
   836		MOVW	4(R7), R2    // compiler stores size at offset 4 in the closure
   837		MOVW	R0, 4(R13)
   838		MOVW	R1, 8(R13)
   839		MOVW	R2, 12(R13)
   840		BL	runtime·memequal(SB)
   841		MOVB	16(R13), R0
   842		MOVB	R0, ret+8(FP)
   843		RET
   844	eq:
   845		MOVW	$1, R0
   846		MOVB	R0, ret+8(FP)
   847		RET
   848	
   849	TEXT runtime·cmpstring(SB),NOSPLIT,$-4-20
   850		MOVW	s1_base+0(FP), R2
   851		MOVW	s1_len+4(FP), R0
   852		MOVW	s2_base+8(FP), R3
   853		MOVW	s2_len+12(FP), R1
   854		ADD	$20, R13, R7
   855		B	runtime·cmpbody(SB)
   856	
   857	TEXT bytes·Compare(SB),NOSPLIT,$-4-28
   858		MOVW	s1+0(FP), R2
   859		MOVW	s1+4(FP), R0
   860		MOVW	s2+12(FP), R3
   861		MOVW	s2+16(FP), R1
   862		ADD	$28, R13, R7
   863		B	runtime·cmpbody(SB)
   864	
   865	// On entry:
   866	// R0 is the length of s1
   867	// R1 is the length of s2
   868	// R2 points to the start of s1
   869	// R3 points to the start of s2
   870	// R7 points to return value (-1/0/1 will be written here)
   871	//
   872	// On exit:
   873	// R4, R5, and R6 are clobbered
   874	TEXT runtime·cmpbody(SB),NOSPLIT,$-4-0
   875		CMP	R2, R3
   876		BEQ	samebytes
   877		CMP 	R0, R1
   878		MOVW 	R0, R6
   879		MOVW.LT	R1, R6	// R6 is min(R0, R1)
   880	
   881		ADD	R2, R6	// R2 is current byte in s1, R6 is last byte in s1 to compare
   882	loop:
   883		CMP	R2, R6
   884		BEQ	samebytes // all compared bytes were the same; compare lengths
   885		MOVBU.P	1(R2), R4
   886		MOVBU.P	1(R3), R5
   887		CMP	R4, R5
   888		BEQ	loop
   889		// bytes differed
   890		MOVW.LT	$1, R0
   891		MOVW.GT	$-1, R0
   892		MOVW	R0, (R7)
   893		RET
   894	samebytes:
   895		CMP	R0, R1
   896		MOVW.LT	$1, R0
   897		MOVW.GT	$-1, R0
   898		MOVW.EQ	$0, R0
   899		MOVW	R0, (R7)
   900		RET
   901	
   902	// TODO: share code with memequal?
   903	TEXT bytes·Equal(SB),NOSPLIT,$0-25
   904		MOVW	a_len+4(FP), R1
   905		MOVW	b_len+16(FP), R3
   906		
   907		CMP	R1, R3		// unequal lengths are not equal
   908		B.NE	notequal
   909	
   910		MOVW	a+0(FP), R0
   911		MOVW	b+12(FP), R2
   912		ADD	R0, R1		// end
   913	
   914	loop:
   915		CMP	R0, R1
   916		B.EQ	equal		// reached the end
   917		MOVBU.P	1(R0), R4
   918		MOVBU.P	1(R2), R5
   919		CMP	R4, R5
   920		B.EQ	loop
   921	
   922	notequal:
   923		MOVW	$0, R0
   924		MOVBU	R0, ret+24(FP)
   925		RET
   926	
   927	equal:
   928		MOVW	$1, R0
   929		MOVBU	R0, ret+24(FP)
   930		RET
   931	
   932	TEXT bytes·IndexByte(SB),NOSPLIT,$0-20
   933		MOVW	s+0(FP), R0
   934		MOVW	s_len+4(FP), R1
   935		MOVBU	c+12(FP), R2	// byte to find
   936		MOVW	R0, R4		// store base for later
   937		ADD	R0, R1		// end
   938	
   939	_loop:
   940		CMP	R0, R1
   941		B.EQ	_notfound
   942		MOVBU.P	1(R0), R3
   943		CMP	R2, R3
   944		B.NE	_loop
   945	
   946		SUB	$1, R0		// R0 will be one beyond the position we want
   947		SUB	R4, R0		// remove base
   948		MOVW    R0, ret+16(FP)
   949		RET
   950	
   951	_notfound:
   952		MOVW	$-1, R0
   953		MOVW	R0, ret+16(FP)
   954		RET
   955	
   956	TEXT strings·IndexByte(SB),NOSPLIT,$0-16
   957		MOVW	s+0(FP), R0
   958		MOVW	s_len+4(FP), R1
   959		MOVBU	c+8(FP), R2	// byte to find
   960		MOVW	R0, R4		// store base for later
   961		ADD	R0, R1		// end
   962	
   963	_sib_loop:
   964		CMP	R0, R1
   965		B.EQ	_sib_notfound
   966		MOVBU.P	1(R0), R3
   967		CMP	R2, R3
   968		B.NE	_sib_loop
   969	
   970		SUB	$1, R0		// R0 will be one beyond the position we want
   971		SUB	R4, R0		// remove base
   972		MOVW	R0, ret+12(FP)
   973		RET
   974	
   975	_sib_notfound:
   976		MOVW	$-1, R0
   977		MOVW	R0, ret+12(FP)
   978		RET
   979	
   980	TEXT runtime·return0(SB),NOSPLIT,$0
   981		MOVW	$0, R0
   982		RET
   983	
   984	TEXT runtime·procyield(SB),NOSPLIT,$-4
   985		MOVW	cycles+0(FP), R1
   986		MOVW	$0, R0
   987	yieldloop:
   988		WORD	$0xe320f001	// YIELD (NOP pre-ARMv6K)
   989		CMP	R0, R1
   990		B.NE	2(PC)
   991		RET
   992		SUB	$1, R1
   993		B yieldloop
   994	
   995	// Called from cgo wrappers, this function returns g->m->curg.stack.hi.
   996	// Must obey the gcc calling convention.
   997	TEXT _cgo_topofstack(SB),NOSPLIT,$8
   998		// R11 and g register are clobbered by load_g. They are
   999		// callee-save in the gcc calling convention, so save them here.
  1000		MOVW	R11, saveR11-4(SP)
  1001		MOVW	g, saveG-8(SP)
  1002		
  1003		BL	runtime·load_g(SB)
  1004		MOVW	g_m(g), R0
  1005		MOVW	m_curg(R0), R0
  1006		MOVW	(g_stack+stack_hi)(R0), R0
  1007		
  1008		MOVW	saveG-8(SP), g
  1009		MOVW	saveR11-4(SP), R11
  1010		RET
  1011	
  1012	// The top-most function running on a goroutine
  1013	// returns to goexit+PCQuantum.
  1014	TEXT runtime·goexit(SB),NOSPLIT,$-4-0
  1015		MOVW	R0, R0	// NOP
  1016		BL	runtime·goexit1(SB)	// does not return
  1017		// traceback from goexit1 must hit code range of goexit
  1018		MOVW	R0, R0	// NOP
  1019	
  1020	// x -> x/1000000, x%1000000, called from Go with args, results on stack.
  1021	TEXT runtime·usplit(SB),NOSPLIT,$0-12
  1022		MOVW	x+0(FP), R0
  1023		CALL	runtime·usplitR0(SB)
  1024		MOVW	R0, q+4(FP)
  1025		MOVW	R1, r+8(FP)
  1026		RET
  1027	
  1028	// R0, R1 = R0/1000000, R0%1000000
  1029	TEXT runtime·usplitR0(SB),NOSPLIT,$0
  1030		// magic multiply to avoid software divide without available m.
  1031		// see output of go tool compile -S for x/1000000.
  1032		MOVW	R0, R3
  1033		MOVW	$1125899907, R1
  1034		MULLU	R1, R0, (R0, R1)
  1035		MOVW	R0>>18, R0
  1036		MOVW	$1000000, R1
  1037		MULU	R0, R1
  1038		SUB	R1, R3, R1
  1039		RET
  1040	
  1041	TEXT runtime·sigreturn(SB),NOSPLIT,$0-0
  1042		RET
  1043	
  1044	#ifndef GOOS_nacl
  1045	// This is called from .init_array and follows the platform, not Go, ABI.
  1046	TEXT runtime·addmoduledata(SB),NOSPLIT,$0-8
  1047		MOVW	R9, saver9-4(SP) // The access to global variables below implicitly uses R9, which is callee-save
  1048		MOVW	R11, saver11-8(SP) // Likewise, R11 is the temp register, but callee-save in C ABI
  1049		MOVW	runtime·lastmoduledatap(SB), R1
  1050		MOVW	R0, moduledata_next(R1)
  1051		MOVW	R0, runtime·lastmoduledatap(SB)
  1052		MOVW	saver11-8(SP), R11
  1053		MOVW	saver9-4(SP), R9
  1054		RET
  1055	#endif
  1056	
  1057	TEXT ·checkASM(SB),NOSPLIT,$0-1
  1058		MOVW	$1, R3
  1059		MOVB	R3, ret+0(FP)
  1060		RET

View as plain text