github.com/sanprasirt/go@v0.0.0-20170607001320-a027466e4b6d/src/runtime/asm_arm.s (about)

     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  	CMP	R0, R1
   945  	B.NE	2(PC)
   946  	RET
   947  	SUB	$1, R1
   948  	B yieldloop
   949  
   950  // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
   951  // Must obey the gcc calling convention.
   952  TEXT _cgo_topofstack(SB),NOSPLIT,$8
   953  	// R11 and g register are clobbered by load_g. They are
   954  	// callee-save in the gcc calling convention, so save them here.
   955  	MOVW	R11, saveR11-4(SP)
   956  	MOVW	g, saveG-8(SP)
   957  	
   958  	BL	runtime·load_g(SB)
   959  	MOVW	g_m(g), R0
   960  	MOVW	m_curg(R0), R0
   961  	MOVW	(g_stack+stack_hi)(R0), R0
   962  	
   963  	MOVW	saveG-8(SP), g
   964  	MOVW	saveR11-4(SP), R11
   965  	RET
   966  
   967  // The top-most function running on a goroutine
   968  // returns to goexit+PCQuantum.
   969  TEXT runtime·goexit(SB),NOSPLIT,$-4-0
   970  	MOVW	R0, R0	// NOP
   971  	BL	runtime·goexit1(SB)	// does not return
   972  	// traceback from goexit1 must hit code range of goexit
   973  	MOVW	R0, R0	// NOP
   974  
   975  TEXT runtime·prefetcht0(SB),NOSPLIT,$0-4
   976  	RET
   977  
   978  TEXT runtime·prefetcht1(SB),NOSPLIT,$0-4
   979  	RET
   980  
   981  TEXT runtime·prefetcht2(SB),NOSPLIT,$0-4
   982  	RET
   983  
   984  TEXT runtime·prefetchnta(SB),NOSPLIT,$0-4
   985  	RET
   986  
   987  // x -> x/1000000, x%1000000, called from Go with args, results on stack.
   988  TEXT runtime·usplit(SB),NOSPLIT,$0-12
   989  	MOVW	x+0(FP), R0
   990  	CALL	runtime·usplitR0(SB)
   991  	MOVW	R0, q+4(FP)
   992  	MOVW	R1, r+8(FP)
   993  	RET
   994  
   995  // R0, R1 = R0/1000000, R0%1000000
   996  TEXT runtime·usplitR0(SB),NOSPLIT,$0
   997  	// magic multiply to avoid software divide without available m.
   998  	// see output of go tool compile -S for x/1000000.
   999  	MOVW	R0, R3
  1000  	MOVW	$1125899907, R1
  1001  	MULLU	R1, R0, (R0, R1)
  1002  	MOVW	R0>>18, R0
  1003  	MOVW	$1000000, R1
  1004  	MULU	R0, R1
  1005  	SUB	R1, R3, R1
  1006  	RET
  1007  
  1008  TEXT runtime·sigreturn(SB),NOSPLIT,$0-0
  1009  	RET
  1010  
  1011  #ifndef GOOS_nacl
  1012  // This is called from .init_array and follows the platform, not Go, ABI.
  1013  TEXT runtime·addmoduledata(SB),NOSPLIT,$0-4
  1014  	MOVW	R9, saver9-4(SP) // The access to global variables below implicitly uses R9, which is callee-save
  1015  	MOVW	runtime·lastmoduledatap(SB), R1
  1016  	MOVW	R0, moduledata_next(R1)
  1017  	MOVW	R0, runtime·lastmoduledatap(SB)
  1018  	MOVW	saver9-4(SP), R9
  1019  	RET
  1020  #endif
  1021  
  1022  TEXT ·checkASM(SB),NOSPLIT,$0-1
  1023  	MOVW	$1, R3
  1024  	MOVB	R3, ret+0(FP)
  1025  	RET