github.com/zxy12/go_duplicate_112_new@v0.0.0-20200807091221-747231827200/src/runtime/asm_mipsx.s (about)

     1  // Copyright 2016 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  // +build mips mipsle
     6  
     7  #include "go_asm.h"
     8  #include "go_tls.h"
     9  #include "funcdata.h"
    10  #include "textflag.h"
    11  
    12  #define	REGCTXT	R22
    13  
    14  TEXT runtime·rt0_go(SB),NOSPLIT,$0
    15  	// R29 = stack; R4 = argc; R5 = argv
    16  
    17  	ADDU	$-12, R29
    18  	MOVW	R4, 4(R29)	// argc
    19  	MOVW	R5, 8(R29)	// argv
    20  
    21  	// create istack out of the given (operating system) stack.
    22  	// _cgo_init may update stackguard.
    23  	MOVW	$runtime·g0(SB), g
    24  	MOVW	$(-64*1024), R23
    25  	ADD	R23, R29, R1
    26  	MOVW	R1, g_stackguard0(g)
    27  	MOVW	R1, g_stackguard1(g)
    28  	MOVW	R1, (g_stack+stack_lo)(g)
    29  	MOVW	R29, (g_stack+stack_hi)(g)
    30  
    31  	// if there is a _cgo_init, call it using the gcc ABI.
    32  	MOVW	_cgo_init(SB), R25
    33  	BEQ	R25, nocgo
    34  	ADDU	$-16, R29
    35  	MOVW	R0, R7	// arg 3: not used
    36  	MOVW	R0, R6	// arg 2: not used
    37  	MOVW	$setg_gcc<>(SB), R5	// arg 1: setg
    38  	MOVW	g, R4	// arg 0: G
    39  	JAL	(R25)
    40  	ADDU	$16, R29
    41  
    42  nocgo:
    43  	// update stackguard after _cgo_init
    44  	MOVW	(g_stack+stack_lo)(g), R1
    45  	ADD	$const__StackGuard, R1
    46  	MOVW	R1, g_stackguard0(g)
    47  	MOVW	R1, g_stackguard1(g)
    48  
    49  	// set the per-goroutine and per-mach "registers"
    50  	MOVW	$runtime·m0(SB), R1
    51  
    52  	// save m->g0 = g0
    53  	MOVW	g, m_g0(R1)
    54  	// save m0 to g0->m
    55  	MOVW	R1, g_m(g)
    56  
    57  	JAL	runtime·check(SB)
    58  
    59  	// args are already prepared
    60  	JAL	runtime·args(SB)
    61  	JAL	runtime·osinit(SB)
    62  	JAL	runtime·schedinit(SB)
    63  
    64  	// create a new goroutine to start program
    65  	MOVW	$runtime·mainPC(SB), R1	// entry
    66  	ADDU	$-12, R29
    67  	MOVW	R1, 8(R29)
    68  	MOVW	R0, 4(R29)
    69  	MOVW	R0, 0(R29)
    70  	JAL	runtime·newproc(SB)
    71  	ADDU	$12, R29
    72  
    73  	// start this M
    74  	JAL	runtime·mstart(SB)
    75  
    76  	UNDEF
    77  	RET
    78  
    79  DATA	runtime·mainPC+0(SB)/4,$runtime·main(SB)
    80  GLOBL	runtime·mainPC(SB),RODATA,$4
    81  
    82  TEXT runtime·breakpoint(SB),NOSPLIT,$0-0
    83  	BREAK
    84  	RET
    85  
    86  TEXT runtime·asminit(SB),NOSPLIT,$0-0
    87  	RET
    88  
    89  /*
    90   *  go-routine
    91   */
    92  
    93  // void gosave(Gobuf*)
    94  // save state in Gobuf; setjmp
    95  TEXT runtime·gosave(SB),NOSPLIT|NOFRAME,$0-4
    96  	MOVW	buf+0(FP), R1
    97  	MOVW	R29, gobuf_sp(R1)
    98  	MOVW	R31, gobuf_pc(R1)
    99  	MOVW	g, gobuf_g(R1)
   100  	MOVW	R0, gobuf_lr(R1)
   101  	MOVW	R0, gobuf_ret(R1)
   102  	// Assert ctxt is zero. See func save.
   103  	MOVW	gobuf_ctxt(R1), R1
   104  	BEQ	R1, 2(PC)
   105  	JAL	runtime·badctxt(SB)
   106  	RET
   107  
   108  // void gogo(Gobuf*)
   109  // restore state from Gobuf; longjmp
   110  TEXT runtime·gogo(SB),NOSPLIT,$8-4
   111  	MOVW	buf+0(FP), R3
   112  	MOVW	gobuf_g(R3), g	// make sure g is not nil
   113  	JAL	runtime·save_g(SB)
   114  
   115  	MOVW	0(g), R2
   116  	MOVW	gobuf_sp(R3), R29
   117  	MOVW	gobuf_lr(R3), R31
   118  	MOVW	gobuf_ret(R3), R1
   119  	MOVW	gobuf_ctxt(R3), REGCTXT
   120  	MOVW	R0, gobuf_sp(R3)
   121  	MOVW	R0, gobuf_ret(R3)
   122  	MOVW	R0, gobuf_lr(R3)
   123  	MOVW	R0, gobuf_ctxt(R3)
   124  	MOVW	gobuf_pc(R3), R4
   125  	JMP	(R4)
   126  
   127  // void mcall(fn func(*g))
   128  // Switch to m->g0's stack, call fn(g).
   129  // Fn must never return. It should gogo(&g->sched)
   130  // to keep running g.
   131  TEXT runtime·mcall(SB),NOSPLIT|NOFRAME,$0-4
   132  	// Save caller state in g->sched
   133  	MOVW	R29, (g_sched+gobuf_sp)(g)
   134  	MOVW	R31, (g_sched+gobuf_pc)(g)
   135  	MOVW	R0, (g_sched+gobuf_lr)(g)
   136  	MOVW	g, (g_sched+gobuf_g)(g)
   137  
   138  	// Switch to m->g0 & its stack, call fn.
   139  	MOVW	g, R1
   140  	MOVW	g_m(g), R3
   141  	MOVW	m_g0(R3), g
   142  	JAL	runtime·save_g(SB)
   143  	BNE	g, R1, 2(PC)
   144  	JMP	runtime·badmcall(SB)
   145  	MOVW	fn+0(FP), REGCTXT	// context
   146  	MOVW	0(REGCTXT), R4	// code pointer
   147  	MOVW	(g_sched+gobuf_sp)(g), R29	// sp = m->g0->sched.sp
   148  	ADDU	$-8, R29	// make room for 1 arg and fake LR
   149  	MOVW	R1, 4(R29)
   150  	MOVW	R0, 0(R29)
   151  	JAL	(R4)
   152  	JMP	runtime·badmcall2(SB)
   153  
   154  // systemstack_switch is a dummy routine that systemstack leaves at the bottom
   155  // of the G stack.  We need to distinguish the routine that
   156  // lives at the bottom of the G stack from the one that lives
   157  // at the top of the system stack because the one at the top of
   158  // the system stack terminates the stack walk (see topofstack()).
   159  TEXT runtime·systemstack_switch(SB),NOSPLIT,$0-0
   160  	UNDEF
   161  	JAL	(R31)	// make sure this function is not leaf
   162  	RET
   163  
   164  // func systemstack(fn func())
   165  TEXT runtime·systemstack(SB),NOSPLIT,$0-4
   166  	MOVW	fn+0(FP), R1	// R1 = fn
   167  	MOVW	R1, REGCTXT	// context
   168  	MOVW	g_m(g), R2	// R2 = m
   169  
   170  	MOVW	m_gsignal(R2), R3	// R3 = gsignal
   171  	BEQ	g, R3, noswitch
   172  
   173  	MOVW	m_g0(R2), R3	// R3 = g0
   174  	BEQ	g, R3, noswitch
   175  
   176  	MOVW	m_curg(R2), R4
   177  	BEQ	g, R4, switch
   178  
   179  	// Bad: g is not gsignal, not g0, not curg. What is it?
   180  	// Hide call from linker nosplit analysis.
   181  	MOVW	$runtime·badsystemstack(SB), R4
   182  	JAL	(R4)
   183  	JAL	runtime·abort(SB)
   184  
   185  switch:
   186  	// save our state in g->sched.  Pretend to
   187  	// be systemstack_switch if the G stack is scanned.
   188  	MOVW	$runtime·systemstack_switch(SB), R4
   189  	ADDU	$8, R4	// get past prologue
   190  	MOVW	R4, (g_sched+gobuf_pc)(g)
   191  	MOVW	R29, (g_sched+gobuf_sp)(g)
   192  	MOVW	R0, (g_sched+gobuf_lr)(g)
   193  	MOVW	g, (g_sched+gobuf_g)(g)
   194  
   195  	// switch to g0
   196  	MOVW	R3, g
   197  	JAL	runtime·save_g(SB)
   198  	MOVW	(g_sched+gobuf_sp)(g), R1
   199  	// make it look like mstart called systemstack on g0, to stop traceback
   200  	ADDU	$-4, R1
   201  	MOVW	$runtime·mstart(SB), R2
   202  	MOVW	R2, 0(R1)
   203  	MOVW	R1, R29
   204  
   205  	// call target function
   206  	MOVW	0(REGCTXT), R4	// code pointer
   207  	JAL	(R4)
   208  
   209  	// switch back to g
   210  	MOVW	g_m(g), R1
   211  	MOVW	m_curg(R1), g
   212  	JAL	runtime·save_g(SB)
   213  	MOVW	(g_sched+gobuf_sp)(g), R29
   214  	MOVW	R0, (g_sched+gobuf_sp)(g)
   215  	RET
   216  
   217  noswitch:
   218  	// already on m stack, just call directly
   219  	// Using a tail call here cleans up tracebacks since we won't stop
   220  	// at an intermediate systemstack.
   221  	MOVW	0(REGCTXT), R4	// code pointer
   222  	MOVW	0(R29), R31	// restore LR
   223  	ADD	$4, R29
   224  	JMP	(R4)
   225  
   226  /*
   227   * support for morestack
   228   */
   229  
   230  // Called during function prolog when more stack is needed.
   231  // Caller has already loaded:
   232  // R1: framesize, R2: argsize, R3: LR
   233  //
   234  // The traceback routines see morestack on a g0 as being
   235  // the top of a stack (for example, morestack calling newstack
   236  // calling the scheduler calling newm calling gc), so we must
   237  // record an argument size. For that purpose, it has no arguments.
   238  TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
   239  	// Cannot grow scheduler stack (m->g0).
   240  	MOVW	g_m(g), R7
   241  	MOVW	m_g0(R7), R8
   242  	BNE	g, R8, 3(PC)
   243  	JAL	runtime·badmorestackg0(SB)
   244  	JAL	runtime·abort(SB)
   245  
   246  	// Cannot grow signal stack (m->gsignal).
   247  	MOVW	m_gsignal(R7), R8
   248  	BNE	g, R8, 3(PC)
   249  	JAL	runtime·badmorestackgsignal(SB)
   250  	JAL	runtime·abort(SB)
   251  
   252  	// Called from f.
   253  	// Set g->sched to context in f.
   254  	MOVW	R29, (g_sched+gobuf_sp)(g)
   255  	MOVW	R31, (g_sched+gobuf_pc)(g)
   256  	MOVW	R3, (g_sched+gobuf_lr)(g)
   257  	MOVW	REGCTXT, (g_sched+gobuf_ctxt)(g)
   258  
   259  	// Called from f.
   260  	// Set m->morebuf to f's caller.
   261  	MOVW	R3, (m_morebuf+gobuf_pc)(R7)	// f's caller's PC
   262  	MOVW	R29, (m_morebuf+gobuf_sp)(R7)	// f's caller's SP
   263  	MOVW	g, (m_morebuf+gobuf_g)(R7)
   264  
   265  	// Call newstack on m->g0's stack.
   266  	MOVW	m_g0(R7), g
   267  	JAL	runtime·save_g(SB)
   268  	MOVW	(g_sched+gobuf_sp)(g), R29
   269  	// Create a stack frame on g0 to call newstack.
   270  	MOVW	R0, -4(R29)	// Zero saved LR in frame
   271  	ADDU	$-4, R29
   272  	JAL	runtime·newstack(SB)
   273  
   274  	// Not reached, but make sure the return PC from the call to newstack
   275  	// is still in this function, and not the beginning of the next.
   276  	UNDEF
   277  
   278  TEXT runtime·morestack_noctxt(SB),NOSPLIT,$0-0
   279  	MOVW	R0, REGCTXT
   280  	JMP	runtime·morestack(SB)
   281  
   282  // reflectcall: call a function with the given argument list
   283  // func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32).
   284  // we don't have variable-sized frames, so we use a small number
   285  // of constant-sized-frame functions to encode a few bits of size in the pc.
   286  
   287  #define DISPATCH(NAME,MAXSIZE)	\
   288  	MOVW	$MAXSIZE, R23;	\
   289  	SGTU	R1, R23, R23;	\
   290  	BNE	R23, 3(PC);	\
   291  	MOVW	$NAME(SB), R4;	\
   292  	JMP	(R4)
   293  
   294  TEXT ·reflectcall(SB),NOSPLIT|NOFRAME,$0-20
   295  	MOVW	argsize+12(FP), R1
   296  
   297  	DISPATCH(runtime·call16, 16)
   298  	DISPATCH(runtime·call32, 32)
   299  	DISPATCH(runtime·call64, 64)
   300  	DISPATCH(runtime·call128, 128)
   301  	DISPATCH(runtime·call256, 256)
   302  	DISPATCH(runtime·call512, 512)
   303  	DISPATCH(runtime·call1024, 1024)
   304  	DISPATCH(runtime·call2048, 2048)
   305  	DISPATCH(runtime·call4096, 4096)
   306  	DISPATCH(runtime·call8192, 8192)
   307  	DISPATCH(runtime·call16384, 16384)
   308  	DISPATCH(runtime·call32768, 32768)
   309  	DISPATCH(runtime·call65536, 65536)
   310  	DISPATCH(runtime·call131072, 131072)
   311  	DISPATCH(runtime·call262144, 262144)
   312  	DISPATCH(runtime·call524288, 524288)
   313  	DISPATCH(runtime·call1048576, 1048576)
   314  	DISPATCH(runtime·call2097152, 2097152)
   315  	DISPATCH(runtime·call4194304, 4194304)
   316  	DISPATCH(runtime·call8388608, 8388608)
   317  	DISPATCH(runtime·call16777216, 16777216)
   318  	DISPATCH(runtime·call33554432, 33554432)
   319  	DISPATCH(runtime·call67108864, 67108864)
   320  	DISPATCH(runtime·call134217728, 134217728)
   321  	DISPATCH(runtime·call268435456, 268435456)
   322  	DISPATCH(runtime·call536870912, 536870912)
   323  	DISPATCH(runtime·call1073741824, 1073741824)
   324  	MOVW	$runtime·badreflectcall(SB), R4
   325  	JMP	(R4)
   326  
   327  #define CALLFN(NAME,MAXSIZE)	\
   328  TEXT NAME(SB),WRAPPER,$MAXSIZE-20;	\
   329  	NO_LOCAL_POINTERS;	\
   330  	/* copy arguments to stack */		\
   331  	MOVW	arg+8(FP), R1;	\
   332  	MOVW	argsize+12(FP), R2;	\
   333  	MOVW	R29, R3;	\
   334  	ADDU	$4, R3;	\
   335  	ADDU	R3, R2;	\
   336  	BEQ	R3, R2, 6(PC);	\
   337  	MOVBU	(R1), R4;	\
   338  	ADDU	$1, R1;	\
   339  	MOVBU	R4, (R3);	\
   340  	ADDU	$1, R3;	\
   341  	JMP	-5(PC);	\
   342  	/* call function */			\
   343  	MOVW	f+4(FP), REGCTXT;	\
   344  	MOVW	(REGCTXT), R4;	\
   345  	PCDATA	$PCDATA_StackMapIndex, $0;	\
   346  	JAL	(R4);	\
   347  	/* copy return values back */		\
   348  	MOVW	argtype+0(FP), R5;	\
   349  	MOVW	arg+8(FP), R1;	\
   350  	MOVW	n+12(FP), R2;	\
   351  	MOVW	retoffset+16(FP), R4;	\
   352  	ADDU	$4, R29, R3;	\
   353  	ADDU	R4, R3;	\
   354  	ADDU	R4, R1;	\
   355  	SUBU	R4, R2;	\
   356  	JAL	callRet<>(SB);		\
   357  	RET
   358  
   359  // callRet copies return values back at the end of call*. This is a
   360  // separate function so it can allocate stack space for the arguments
   361  // to reflectcallmove. It does not follow the Go ABI; it expects its
   362  // arguments in registers.
   363  TEXT callRet<>(SB), NOSPLIT, $16-0
   364  	MOVW	R5, 4(R29)
   365  	MOVW	R1, 8(R29)
   366  	MOVW	R3, 12(R29)
   367  	MOVW	R2, 16(R29)
   368  	JAL	runtime·reflectcallmove(SB)
   369  	RET
   370  
   371  CALLFN(·call16, 16)
   372  CALLFN(·call32, 32)
   373  CALLFN(·call64, 64)
   374  CALLFN(·call128, 128)
   375  CALLFN(·call256, 256)
   376  CALLFN(·call512, 512)
   377  CALLFN(·call1024, 1024)
   378  CALLFN(·call2048, 2048)
   379  CALLFN(·call4096, 4096)
   380  CALLFN(·call8192, 8192)
   381  CALLFN(·call16384, 16384)
   382  CALLFN(·call32768, 32768)
   383  CALLFN(·call65536, 65536)
   384  CALLFN(·call131072, 131072)
   385  CALLFN(·call262144, 262144)
   386  CALLFN(·call524288, 524288)
   387  CALLFN(·call1048576, 1048576)
   388  CALLFN(·call2097152, 2097152)
   389  CALLFN(·call4194304, 4194304)
   390  CALLFN(·call8388608, 8388608)
   391  CALLFN(·call16777216, 16777216)
   392  CALLFN(·call33554432, 33554432)
   393  CALLFN(·call67108864, 67108864)
   394  CALLFN(·call134217728, 134217728)
   395  CALLFN(·call268435456, 268435456)
   396  CALLFN(·call536870912, 536870912)
   397  CALLFN(·call1073741824, 1073741824)
   398  
   399  TEXT runtime·procyield(SB),NOSPLIT,$0-4
   400  	RET
   401  
   402  // void jmpdefer(fv, sp);
   403  // called from deferreturn.
   404  // 1. grab stored LR for caller
   405  // 2. sub 8 bytes to get back to JAL deferreturn
   406  // 3. JMP to fn
   407  TEXT runtime·jmpdefer(SB),NOSPLIT,$0-8
   408  	MOVW	0(R29), R31
   409  	ADDU	$-8, R31
   410  
   411  	MOVW	fv+0(FP), REGCTXT
   412  	MOVW	argp+4(FP), R29
   413  	ADDU	$-4, R29
   414  	NOR	R0, R0	// prevent scheduling
   415  	MOVW	0(REGCTXT), R4
   416  	JMP	(R4)
   417  
   418  // Save state of caller into g->sched. Smashes R1.
   419  TEXT gosave<>(SB),NOSPLIT|NOFRAME,$0
   420  	MOVW	R31, (g_sched+gobuf_pc)(g)
   421  	MOVW	R29, (g_sched+gobuf_sp)(g)
   422  	MOVW	R0, (g_sched+gobuf_lr)(g)
   423  	MOVW	R0, (g_sched+gobuf_ret)(g)
   424  	// Assert ctxt is zero. See func save.
   425  	MOVW	(g_sched+gobuf_ctxt)(g), R1
   426  	BEQ	R1, 2(PC)
   427  	JAL	runtime·badctxt(SB)
   428  	RET
   429  
   430  // func asmcgocall(fn, arg unsafe.Pointer) int32
   431  // Call fn(arg) on the scheduler stack,
   432  // aligned appropriately for the gcc ABI.
   433  // See cgocall.go for more details.
   434  TEXT ·asmcgocall(SB),NOSPLIT,$0-12
   435  	MOVW	fn+0(FP), R25
   436  	MOVW	arg+4(FP), R4
   437  
   438  	MOVW	R29, R3	// save original stack pointer
   439  	MOVW	g, R2
   440  
   441  	// Figure out if we need to switch to m->g0 stack.
   442  	// We get called to create new OS threads too, and those
   443  	// come in on the m->g0 stack already.
   444  	MOVW	g_m(g), R5
   445  	MOVW	m_g0(R5), R6
   446  	BEQ	R6, g, g0
   447  
   448  	JAL	gosave<>(SB)
   449  	MOVW	R6, g
   450  	JAL	runtime·save_g(SB)
   451  	MOVW	(g_sched+gobuf_sp)(g), R29
   452  
   453  	// Now on a scheduling stack (a pthread-created stack).
   454  g0:
   455  	// Save room for two of our pointers and O32 frame.
   456  	ADDU	$-24, R29
   457  	AND	$~7, R29	// O32 ABI expects 8-byte aligned stack on function entry
   458  	MOVW	R2, 16(R29)	// save old g on stack
   459  	MOVW	(g_stack+stack_hi)(R2), R2
   460  	SUBU	R3, R2
   461  	MOVW	R2, 20(R29)	// save depth in old g stack (can't just save SP, as stack might be copied during a callback)
   462  	JAL	(R25)
   463  
   464  	// Restore g, stack pointer. R2 is return value.
   465  	MOVW	16(R29), g
   466  	JAL	runtime·save_g(SB)
   467  	MOVW	(g_stack+stack_hi)(g), R5
   468  	MOVW	20(R29), R6
   469  	SUBU	R6, R5
   470  	MOVW	R5, R29
   471  
   472  	MOVW	R2, ret+8(FP)
   473  	RET
   474  
   475  // cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
   476  // Turn the fn into a Go func (by taking its address) and call
   477  // cgocallback_gofunc.
   478  TEXT runtime·cgocallback(SB),NOSPLIT,$16-16
   479  	MOVW	$fn+0(FP), R1
   480  	MOVW	R1, 4(R29)
   481  	MOVW	frame+4(FP), R1
   482  	MOVW	R1, 8(R29)
   483  	MOVW	framesize+8(FP), R1
   484  	MOVW	R1, 12(R29)
   485  	MOVW	ctxt+12(FP), R1
   486  	MOVW	R1, 16(R29)
   487  	MOVW	$runtime·cgocallback_gofunc(SB), R1
   488  	JAL	(R1)
   489  	RET
   490  
   491  // cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize, uintptr ctxt)
   492  // See cgocall.go for more details.
   493  TEXT ·cgocallback_gofunc(SB),NOSPLIT,$8-16
   494  	NO_LOCAL_POINTERS
   495  
   496  	// Load m and g from thread-local storage.
   497  	MOVB	runtime·iscgo(SB), R1
   498  	BEQ	R1, nocgo
   499  	JAL	runtime·load_g(SB)
   500  nocgo:
   501  
   502  	// If g is nil, Go did not create the current thread.
   503  	// Call needm to obtain one for temporary use.
   504  	// In this case, we're running on the thread stack, so there's
   505  	// lots of space, but the linker doesn't know. Hide the call from
   506  	// the linker analysis by using an indirect call.
   507  	BEQ	g, needm
   508  
   509  	MOVW	g_m(g), R3
   510  	MOVW	R3, savedm-4(SP)
   511  	JMP	havem
   512  
   513  needm:
   514  	MOVW	g, savedm-4(SP) // g is zero, so is m.
   515  	MOVW	$runtime·needm(SB), R4
   516  	JAL	(R4)
   517  
   518  	// Set m->sched.sp = SP, so that if a panic happens
   519  	// during the function we are about to execute, it will
   520  	// have a valid SP to run on the g0 stack.
   521  	// The next few lines (after the havem label)
   522  	// will save this SP onto the stack and then write
   523  	// the same SP back to m->sched.sp. That seems redundant,
   524  	// but if an unrecovered panic happens, unwindm will
   525  	// restore the g->sched.sp from the stack location
   526  	// and then systemstack will try to use it. If we don't set it here,
   527  	// that restored SP will be uninitialized (typically 0) and
   528  	// will not be usable.
   529  	MOVW	g_m(g), R3
   530  	MOVW	m_g0(R3), R1
   531  	MOVW	R29, (g_sched+gobuf_sp)(R1)
   532  
   533  havem:
   534  	// Now there's a valid m, and we're running on its m->g0.
   535  	// Save current m->g0->sched.sp on stack and then set it to SP.
   536  	// Save current sp in m->g0->sched.sp in preparation for
   537  	// switch back to m->curg stack.
   538  	// NOTE: unwindm knows that the saved g->sched.sp is at 4(R29) aka savedsp-8(SP).
   539  	MOVW	m_g0(R3), R1
   540  	MOVW	(g_sched+gobuf_sp)(R1), R2
   541  	MOVW	R2, savedsp-8(SP)
   542  	MOVW	R29, (g_sched+gobuf_sp)(R1)
   543  
   544  	// Switch to m->curg stack and call runtime.cgocallbackg.
   545  	// Because we are taking over the execution of m->curg
   546  	// but *not* resuming what had been running, we need to
   547  	// save that information (m->curg->sched) so we can restore it.
   548  	// We can restore m->curg->sched.sp easily, because calling
   549  	// runtime.cgocallbackg leaves SP unchanged upon return.
   550  	// To save m->curg->sched.pc, we push it onto the stack.
   551  	// This has the added benefit that it looks to the traceback
   552  	// routine like cgocallbackg is going to return to that
   553  	// PC (because the frame we allocate below has the same
   554  	// size as cgocallback_gofunc's frame declared above)
   555  	// so that the traceback will seamlessly trace back into
   556  	// the earlier calls.
   557  	//
   558  	// In the new goroutine, -4(SP) is unused (where SP refers to
   559  	// m->curg's SP while we're setting it up, before we've adjusted it).
   560  	MOVW	m_curg(R3), g
   561  	JAL	runtime·save_g(SB)
   562  	MOVW	(g_sched+gobuf_sp)(g), R2 // prepare stack as R2
   563  	MOVW	(g_sched+gobuf_pc)(g), R4
   564  	MOVW	R4, -12(R2)
   565  	MOVW    ctxt+12(FP), R1
   566  	MOVW    R1, -8(R2)
   567  	MOVW	$-12(R2), R29
   568  	JAL	runtime·cgocallbackg(SB)
   569  
   570  	// Restore g->sched (== m->curg->sched) from saved values.
   571  	MOVW	0(R29), R4
   572  	MOVW	R4, (g_sched+gobuf_pc)(g)
   573  	MOVW	$12(R29), R2
   574  	MOVW	R2, (g_sched+gobuf_sp)(g)
   575  
   576  	// Switch back to m->g0's stack and restore m->g0->sched.sp.
   577  	// (Unlike m->curg, the g0 goroutine never uses sched.pc,
   578  	// so we do not have to restore it.)
   579  	MOVW	g_m(g), R3
   580  	MOVW	m_g0(R3), g
   581  	JAL	runtime·save_g(SB)
   582  	MOVW	(g_sched+gobuf_sp)(g), R29
   583  	MOVW	savedsp-8(SP), R2
   584  	MOVW	R2, (g_sched+gobuf_sp)(g)
   585  
   586  	// If the m on entry was nil, we called needm above to borrow an m
   587  	// for the duration of the call. Since the call is over, return it with dropm.
   588  	MOVW	savedm-4(SP), R3
   589  	BNE	R3, droppedm
   590  	MOVW	$runtime·dropm(SB), R4
   591  	JAL	(R4)
   592  droppedm:
   593  
   594  	// Done!
   595  	RET
   596  
   597  // void setg(G*); set g. for use by needm.
   598  // This only happens if iscgo, so jump straight to save_g
   599  TEXT runtime·setg(SB),NOSPLIT,$0-4
   600  	MOVW	gg+0(FP), g
   601  	JAL	runtime·save_g(SB)
   602  	RET
   603  
   604  // void setg_gcc(G*); set g in C TLS.
   605  // Must obey the gcc calling convention.
   606  TEXT setg_gcc<>(SB),NOSPLIT,$0
   607  	MOVW	R4, g
   608  	JAL	runtime·save_g(SB)
   609  	RET
   610  
   611  TEXT runtime·abort(SB),NOSPLIT,$0-0
   612  	UNDEF
   613  
   614  // Not implemented.
   615  TEXT runtime·aeshash(SB),NOSPLIT,$0
   616  	UNDEF
   617  
   618  // Not implemented.
   619  TEXT runtime·aeshash32(SB),NOSPLIT,$0
   620  	UNDEF
   621  
   622  // Not implemented.
   623  TEXT runtime·aeshash64(SB),NOSPLIT,$0
   624  	UNDEF
   625  
   626  // Not implemented.
   627  TEXT runtime·aeshashstr(SB),NOSPLIT,$0
   628  	UNDEF
   629  
   630  TEXT runtime·return0(SB),NOSPLIT,$0
   631  	MOVW	$0, R1
   632  	RET
   633  
   634  // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
   635  // Must obey the gcc calling convention.
   636  TEXT _cgo_topofstack(SB),NOSPLIT|NOFRAME,$0
   637  	// g (R30), R3 and REGTMP (R23) might be clobbered by load_g. R30 and R23
   638  	// are callee-save in the gcc calling convention, so save them.
   639  	MOVW	R23, R8
   640  	MOVW	g, R9
   641  	MOVW	R31, R10 // this call frame does not save LR
   642  
   643  	JAL	runtime·load_g(SB)
   644  	MOVW	g_m(g), R1
   645  	MOVW	m_curg(R1), R1
   646  	MOVW	(g_stack+stack_hi)(R1), R2 // return value in R2
   647  
   648  	MOVW	R8, R23
   649  	MOVW	R9, g
   650  	MOVW	R10, R31
   651  
   652  	RET
   653  
   654  // The top-most function running on a goroutine
   655  // returns to goexit+PCQuantum.
   656  TEXT runtime·goexit(SB),NOSPLIT|NOFRAME,$0-0
   657  	NOR	R0, R0	// NOP
   658  	JAL	runtime·goexit1(SB)	// does not return
   659  	// traceback from goexit1 must hit code range of goexit
   660  	NOR	R0, R0	// NOP
   661  
   662  TEXT ·checkASM(SB),NOSPLIT,$0-1
   663  	MOVW	$1, R1
   664  	MOVB	R1, ret+0(FP)
   665  	RET
   666  
   667  // gcWriteBarrier performs a heap pointer write and informs the GC.
   668  //
   669  // gcWriteBarrier does NOT follow the Go ABI. It takes two arguments:
   670  // - R20 is the destination of the write
   671  // - R21 is the value being written at R20.
   672  // It clobbers R23 (the linker temp register).
   673  // The act of CALLing gcWriteBarrier will clobber R31 (LR).
   674  // It does not clobber any other general-purpose registers,
   675  // but may clobber others (e.g., floating point registers).
   676  TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$104
   677  	// Save the registers clobbered by the fast path.
   678  	MOVW	R1, 100(R29)
   679  	MOVW	R2, 104(R29)
   680  	MOVW	g_m(g), R1
   681  	MOVW	m_p(R1), R1
   682  	MOVW	(p_wbBuf+wbBuf_next)(R1), R2
   683  	// Increment wbBuf.next position.
   684  	ADD	$8, R2
   685  	MOVW	R2, (p_wbBuf+wbBuf_next)(R1)
   686  	MOVW	(p_wbBuf+wbBuf_end)(R1), R1
   687  	MOVW	R1, R23		// R23 is linker temp register
   688  	// Record the write.
   689  	MOVW	R21, -8(R2)	// Record value
   690  	MOVW	(R20), R1	// TODO: This turns bad writes into bad reads.
   691  	MOVW	R1, -4(R2)	// Record *slot
   692  	// Is the buffer full?
   693  	BEQ	R2, R23, flush
   694  ret:
   695  	MOVW	100(R29), R1
   696  	MOVW	104(R29), R2
   697  	// Do the write.
   698  	MOVW	R21, (R20)
   699  	RET
   700  
   701  flush:
   702  	// Save all general purpose registers since these could be
   703  	// clobbered by wbBufFlush and were not saved by the caller.
   704  	MOVW	R20, 4(R29)	// Also first argument to wbBufFlush
   705  	MOVW	R21, 8(R29)	// Also second argument to wbBufFlush
   706  	// R1 already saved
   707  	// R2 already saved
   708  	MOVW	R3, 12(R29)
   709  	MOVW	R4, 16(R29)
   710  	MOVW	R5, 20(R29)
   711  	MOVW	R6, 24(R29)
   712  	MOVW	R7, 28(R29)
   713  	MOVW	R8, 32(R29)
   714  	MOVW	R9, 36(R29)
   715  	MOVW	R10, 40(R29)
   716  	MOVW	R11, 44(R29)
   717  	MOVW	R12, 48(R29)
   718  	MOVW	R13, 52(R29)
   719  	MOVW	R14, 56(R29)
   720  	MOVW	R15, 60(R29)
   721  	MOVW	R16, 64(R29)
   722  	MOVW	R17, 68(R29)
   723  	MOVW	R18, 72(R29)
   724  	MOVW	R19, 76(R29)
   725  	MOVW	R20, 80(R29)
   726  	// R21 already saved
   727  	// R22 already saved.
   728  	MOVW	R22, 84(R29)
   729  	// R23 is tmp register.
   730  	MOVW	R24, 88(R29)
   731  	MOVW	R25, 92(R29)
   732  	// R26 is reserved by kernel.
   733  	// R27 is reserved by kernel.
   734  	MOVW	R28, 96(R29)
   735  	// R29 is SP.
   736  	// R30 is g.
   737  	// R31 is LR, which was saved by the prologue.
   738  
   739  	// This takes arguments R20 and R21.
   740  	CALL	runtime·wbBufFlush(SB)
   741  
   742  	MOVW	4(R29), R20
   743  	MOVW	8(R29), R21
   744  	MOVW	12(R29), R3
   745  	MOVW	16(R29), R4
   746  	MOVW	20(R29), R5
   747  	MOVW	24(R29), R6
   748  	MOVW	28(R29), R7
   749  	MOVW	32(R29), R8
   750  	MOVW	36(R29), R9
   751  	MOVW	40(R29), R10
   752  	MOVW	44(R29), R11
   753  	MOVW	48(R29), R12
   754  	MOVW	52(R29), R13
   755  	MOVW	56(R29), R14
   756  	MOVW	60(R29), R15
   757  	MOVW	64(R29), R16
   758  	MOVW	68(R29), R17
   759  	MOVW	72(R29), R18
   760  	MOVW	76(R29), R19
   761  	MOVW	80(R29), R20
   762  	MOVW	84(R29), R22
   763  	MOVW	88(R29), R24
   764  	MOVW	92(R29), R25
   765  	MOVW	96(R29), R28
   766  	JMP	ret