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

View as plain text