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