github.com/hikaru7719/go@v0.0.0-20181025140707-c8b2ac68906a/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 reflect·call(SB),NOSPLIT,$0-20
   295  	JMP	·reflectcall(SB)
   296  
   297  TEXT ·reflectcall(SB),NOSPLIT|NOFRAME,$0-20
   298  	MOVW	argsize+12(FP), R1
   299  
   300  	DISPATCH(runtime·call16, 16)
   301  	DISPATCH(runtime·call32, 32)
   302  	DISPATCH(runtime·call64, 64)
   303  	DISPATCH(runtime·call128, 128)
   304  	DISPATCH(runtime·call256, 256)
   305  	DISPATCH(runtime·call512, 512)
   306  	DISPATCH(runtime·call1024, 1024)
   307  	DISPATCH(runtime·call2048, 2048)
   308  	DISPATCH(runtime·call4096, 4096)
   309  	DISPATCH(runtime·call8192, 8192)
   310  	DISPATCH(runtime·call16384, 16384)
   311  	DISPATCH(runtime·call32768, 32768)
   312  	DISPATCH(runtime·call65536, 65536)
   313  	DISPATCH(runtime·call131072, 131072)
   314  	DISPATCH(runtime·call262144, 262144)
   315  	DISPATCH(runtime·call524288, 524288)
   316  	DISPATCH(runtime·call1048576, 1048576)
   317  	DISPATCH(runtime·call2097152, 2097152)
   318  	DISPATCH(runtime·call4194304, 4194304)
   319  	DISPATCH(runtime·call8388608, 8388608)
   320  	DISPATCH(runtime·call16777216, 16777216)
   321  	DISPATCH(runtime·call33554432, 33554432)
   322  	DISPATCH(runtime·call67108864, 67108864)
   323  	DISPATCH(runtime·call134217728, 134217728)
   324  	DISPATCH(runtime·call268435456, 268435456)
   325  	DISPATCH(runtime·call536870912, 536870912)
   326  	DISPATCH(runtime·call1073741824, 1073741824)
   327  	MOVW	$runtime·badreflectcall(SB), R4
   328  	JMP	(R4)
   329  
   330  #define CALLFN(NAME,MAXSIZE)	\
   331  TEXT NAME(SB),WRAPPER,$MAXSIZE-20;	\
   332  	NO_LOCAL_POINTERS;	\
   333  	/* copy arguments to stack */		\
   334  	MOVW	arg+8(FP), R1;	\
   335  	MOVW	argsize+12(FP), R2;	\
   336  	MOVW	R29, R3;	\
   337  	ADDU	$4, R3;	\
   338  	ADDU	R3, R2;	\
   339  	BEQ	R3, R2, 6(PC);	\
   340  	MOVBU	(R1), R4;	\
   341  	ADDU	$1, R1;	\
   342  	MOVBU	R4, (R3);	\
   343  	ADDU	$1, R3;	\
   344  	JMP	-5(PC);	\
   345  	/* call function */			\
   346  	MOVW	f+4(FP), REGCTXT;	\
   347  	MOVW	(REGCTXT), R4;	\
   348  	PCDATA	$PCDATA_StackMapIndex, $0;	\
   349  	JAL	(R4);	\
   350  	/* copy return values back */		\
   351  	MOVW	argtype+0(FP), R5;	\
   352  	MOVW	arg+8(FP), R1;	\
   353  	MOVW	n+12(FP), R2;	\
   354  	MOVW	retoffset+16(FP), R4;	\
   355  	ADDU	$4, R29, R3;	\
   356  	ADDU	R4, R3;	\
   357  	ADDU	R4, R1;	\
   358  	SUBU	R4, R2;	\
   359  	JAL	callRet<>(SB);		\
   360  	RET
   361  
   362  // callRet copies return values back at the end of call*. This is a
   363  // separate function so it can allocate stack space for the arguments
   364  // to reflectcallmove. It does not follow the Go ABI; it expects its
   365  // arguments in registers.
   366  TEXT callRet<>(SB), NOSPLIT, $16-0
   367  	MOVW	R5, 4(R29)
   368  	MOVW	R1, 8(R29)
   369  	MOVW	R3, 12(R29)
   370  	MOVW	R2, 16(R29)
   371  	JAL	runtime·reflectcallmove(SB)
   372  	RET
   373  
   374  CALLFN(·call16, 16)
   375  CALLFN(·call32, 32)
   376  CALLFN(·call64, 64)
   377  CALLFN(·call128, 128)
   378  CALLFN(·call256, 256)
   379  CALLFN(·call512, 512)
   380  CALLFN(·call1024, 1024)
   381  CALLFN(·call2048, 2048)
   382  CALLFN(·call4096, 4096)
   383  CALLFN(·call8192, 8192)
   384  CALLFN(·call16384, 16384)
   385  CALLFN(·call32768, 32768)
   386  CALLFN(·call65536, 65536)
   387  CALLFN(·call131072, 131072)
   388  CALLFN(·call262144, 262144)
   389  CALLFN(·call524288, 524288)
   390  CALLFN(·call1048576, 1048576)
   391  CALLFN(·call2097152, 2097152)
   392  CALLFN(·call4194304, 4194304)
   393  CALLFN(·call8388608, 8388608)
   394  CALLFN(·call16777216, 16777216)
   395  CALLFN(·call33554432, 33554432)
   396  CALLFN(·call67108864, 67108864)
   397  CALLFN(·call134217728, 134217728)
   398  CALLFN(·call268435456, 268435456)
   399  CALLFN(·call536870912, 536870912)
   400  CALLFN(·call1073741824, 1073741824)
   401  
   402  TEXT runtime·procyield(SB),NOSPLIT,$0-4
   403  	RET
   404  
   405  // void jmpdefer(fv, sp);
   406  // called from deferreturn.
   407  // 1. grab stored LR for caller
   408  // 2. sub 8 bytes to get back to JAL deferreturn
   409  // 3. JMP to fn
   410  TEXT runtime·jmpdefer(SB),NOSPLIT,$0-8
   411  	MOVW	0(R29), R31
   412  	ADDU	$-8, R31
   413  
   414  	MOVW	fv+0(FP), REGCTXT
   415  	MOVW	argp+4(FP), R29
   416  	ADDU	$-4, R29
   417  	NOR	R0, R0	// prevent scheduling
   418  	MOVW	0(REGCTXT), R4
   419  	JMP	(R4)
   420  
   421  // Save state of caller into g->sched. Smashes R1.
   422  TEXT gosave<>(SB),NOSPLIT|NOFRAME,$0
   423  	MOVW	R31, (g_sched+gobuf_pc)(g)
   424  	MOVW	R29, (g_sched+gobuf_sp)(g)
   425  	MOVW	R0, (g_sched+gobuf_lr)(g)
   426  	MOVW	R0, (g_sched+gobuf_ret)(g)
   427  	// Assert ctxt is zero. See func save.
   428  	MOVW	(g_sched+gobuf_ctxt)(g), R1
   429  	BEQ	R1, 2(PC)
   430  	JAL	runtime·badctxt(SB)
   431  	RET
   432  
   433  // func asmcgocall(fn, arg unsafe.Pointer) int32
   434  // Call fn(arg) on the scheduler stack,
   435  // aligned appropriately for the gcc ABI.
   436  // See cgocall.go for more details.
   437  TEXT ·asmcgocall(SB),NOSPLIT,$0-12
   438  	MOVW	fn+0(FP), R25
   439  	MOVW	arg+4(FP), R4
   440  
   441  	MOVW	R29, R3	// save original stack pointer
   442  	MOVW	g, R2
   443  
   444  	// Figure out if we need to switch to m->g0 stack.
   445  	// We get called to create new OS threads too, and those
   446  	// come in on the m->g0 stack already.
   447  	MOVW	g_m(g), R5
   448  	MOVW	m_g0(R5), R6
   449  	BEQ	R6, g, g0
   450  
   451  	JAL	gosave<>(SB)
   452  	MOVW	R6, g
   453  	JAL	runtime·save_g(SB)
   454  	MOVW	(g_sched+gobuf_sp)(g), R29
   455  
   456  	// Now on a scheduling stack (a pthread-created stack).
   457  g0:
   458  	// Save room for two of our pointers and O32 frame.
   459  	ADDU	$-24, R29
   460  	AND	$~7, R29	// O32 ABI expects 8-byte aligned stack on function entry
   461  	MOVW	R2, 16(R29)	// save old g on stack
   462  	MOVW	(g_stack+stack_hi)(R2), R2
   463  	SUBU	R3, R2
   464  	MOVW	R2, 20(R29)	// save depth in old g stack (can't just save SP, as stack might be copied during a callback)
   465  	JAL	(R25)
   466  
   467  	// Restore g, stack pointer. R2 is return value.
   468  	MOVW	16(R29), g
   469  	JAL	runtime·save_g(SB)
   470  	MOVW	(g_stack+stack_hi)(g), R5
   471  	MOVW	20(R29), R6
   472  	SUBU	R6, R5
   473  	MOVW	R5, R29
   474  
   475  	MOVW	R2, ret+8(FP)
   476  	RET
   477  
   478  // cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
   479  // Turn the fn into a Go func (by taking its address) and call
   480  // cgocallback_gofunc.
   481  TEXT runtime·cgocallback(SB),NOSPLIT,$16-16
   482  	MOVW	$fn+0(FP), R1
   483  	MOVW	R1, 4(R29)
   484  	MOVW	frame+4(FP), R1
   485  	MOVW	R1, 8(R29)
   486  	MOVW	framesize+8(FP), R1
   487  	MOVW	R1, 12(R29)
   488  	MOVW	ctxt+12(FP), R1
   489  	MOVW	R1, 16(R29)
   490  	MOVW	$runtime·cgocallback_gofunc(SB), R1
   491  	JAL	(R1)
   492  	RET
   493  
   494  // cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize, uintptr ctxt)
   495  // See cgocall.go for more details.
   496  TEXT ·cgocallback_gofunc(SB),NOSPLIT,$8-16
   497  	NO_LOCAL_POINTERS
   498  
   499  	// Load m and g from thread-local storage.
   500  	MOVB	runtime·iscgo(SB), R1
   501  	BEQ	R1, nocgo
   502  	JAL	runtime·load_g(SB)
   503  nocgo:
   504  
   505  	// If g is nil, Go did not create the current thread.
   506  	// Call needm to obtain one for temporary use.
   507  	// In this case, we're running on the thread stack, so there's
   508  	// lots of space, but the linker doesn't know. Hide the call from
   509  	// the linker analysis by using an indirect call.
   510  	BEQ	g, needm
   511  
   512  	MOVW	g_m(g), R3
   513  	MOVW	R3, savedm-4(SP)
   514  	JMP	havem
   515  
   516  needm:
   517  	MOVW	g, savedm-4(SP) // g is zero, so is m.
   518  	MOVW	$runtime·needm(SB), R4
   519  	JAL	(R4)
   520  
   521  	// Set m->sched.sp = SP, so that if a panic happens
   522  	// during the function we are about to execute, it will
   523  	// have a valid SP to run on the g0 stack.
   524  	// The next few lines (after the havem label)
   525  	// will save this SP onto the stack and then write
   526  	// the same SP back to m->sched.sp. That seems redundant,
   527  	// but if an unrecovered panic happens, unwindm will
   528  	// restore the g->sched.sp from the stack location
   529  	// and then systemstack will try to use it. If we don't set it here,
   530  	// that restored SP will be uninitialized (typically 0) and
   531  	// will not be usable.
   532  	MOVW	g_m(g), R3
   533  	MOVW	m_g0(R3), R1
   534  	MOVW	R29, (g_sched+gobuf_sp)(R1)
   535  
   536  havem:
   537  	// Now there's a valid m, and we're running on its m->g0.
   538  	// Save current m->g0->sched.sp on stack and then set it to SP.
   539  	// Save current sp in m->g0->sched.sp in preparation for
   540  	// switch back to m->curg stack.
   541  	// NOTE: unwindm knows that the saved g->sched.sp is at 4(R29) aka savedsp-8(SP).
   542  	MOVW	m_g0(R3), R1
   543  	MOVW	(g_sched+gobuf_sp)(R1), R2
   544  	MOVW	R2, savedsp-8(SP)
   545  	MOVW	R29, (g_sched+gobuf_sp)(R1)
   546  
   547  	// Switch to m->curg stack and call runtime.cgocallbackg.
   548  	// Because we are taking over the execution of m->curg
   549  	// but *not* resuming what had been running, we need to
   550  	// save that information (m->curg->sched) so we can restore it.
   551  	// We can restore m->curg->sched.sp easily, because calling
   552  	// runtime.cgocallbackg leaves SP unchanged upon return.
   553  	// To save m->curg->sched.pc, we push it onto the stack.
   554  	// This has the added benefit that it looks to the traceback
   555  	// routine like cgocallbackg is going to return to that
   556  	// PC (because the frame we allocate below has the same
   557  	// size as cgocallback_gofunc's frame declared above)
   558  	// so that the traceback will seamlessly trace back into
   559  	// the earlier calls.
   560  	//
   561  	// In the new goroutine, -4(SP) is unused (where SP refers to
   562  	// m->curg's SP while we're setting it up, before we've adjusted it).
   563  	MOVW	m_curg(R3), g
   564  	JAL	runtime·save_g(SB)
   565  	MOVW	(g_sched+gobuf_sp)(g), R2 // prepare stack as R2
   566  	MOVW	(g_sched+gobuf_pc)(g), R4
   567  	MOVW	R4, -12(R2)
   568  	MOVW    ctxt+12(FP), R1
   569  	MOVW    R1, -8(R2)
   570  	MOVW	$-12(R2), R29
   571  	JAL	runtime·cgocallbackg(SB)
   572  
   573  	// Restore g->sched (== m->curg->sched) from saved values.
   574  	MOVW	0(R29), R4
   575  	MOVW	R4, (g_sched+gobuf_pc)(g)
   576  	MOVW	$12(R29), R2
   577  	MOVW	R2, (g_sched+gobuf_sp)(g)
   578  
   579  	// Switch back to m->g0's stack and restore m->g0->sched.sp.
   580  	// (Unlike m->curg, the g0 goroutine never uses sched.pc,
   581  	// so we do not have to restore it.)
   582  	MOVW	g_m(g), R3
   583  	MOVW	m_g0(R3), g
   584  	JAL	runtime·save_g(SB)
   585  	MOVW	(g_sched+gobuf_sp)(g), R29
   586  	MOVW	savedsp-8(SP), R2
   587  	MOVW	R2, (g_sched+gobuf_sp)(g)
   588  
   589  	// If the m on entry was nil, we called needm above to borrow an m
   590  	// for the duration of the call. Since the call is over, return it with dropm.
   591  	MOVW	savedm-4(SP), R3
   592  	BNE	R3, droppedm
   593  	MOVW	$runtime·dropm(SB), R4
   594  	JAL	(R4)
   595  droppedm:
   596  
   597  	// Done!
   598  	RET
   599  
   600  // void setg(G*); set g. for use by needm.
   601  // This only happens if iscgo, so jump straight to save_g
   602  TEXT runtime·setg(SB),NOSPLIT,$0-4
   603  	MOVW	gg+0(FP), g
   604  	JAL	runtime·save_g(SB)
   605  	RET
   606  
   607  // void setg_gcc(G*); set g in C TLS.
   608  // Must obey the gcc calling convention.
   609  TEXT setg_gcc<>(SB),NOSPLIT,$0
   610  	MOVW	R4, g
   611  	JAL	runtime·save_g(SB)
   612  	RET
   613  
   614  TEXT runtime·abort(SB),NOSPLIT,$0-0
   615  	UNDEF
   616  
   617  // Not implemented.
   618  TEXT runtime·aeshash(SB),NOSPLIT,$0
   619  	UNDEF
   620  
   621  // Not implemented.
   622  TEXT runtime·aeshash32(SB),NOSPLIT,$0
   623  	UNDEF
   624  
   625  // Not implemented.
   626  TEXT runtime·aeshash64(SB),NOSPLIT,$0
   627  	UNDEF
   628  
   629  // Not implemented.
   630  TEXT runtime·aeshashstr(SB),NOSPLIT,$0
   631  	UNDEF
   632  
   633  TEXT runtime·return0(SB),NOSPLIT,$0
   634  	MOVW	$0, R1
   635  	RET
   636  
   637  // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
   638  // Must obey the gcc calling convention.
   639  TEXT _cgo_topofstack(SB),NOSPLIT|NOFRAME,$0
   640  	// g (R30), R3 and REGTMP (R23) might be clobbered by load_g. R30 and R23
   641  	// are callee-save in the gcc calling convention, so save them.
   642  	MOVW	R23, R8
   643  	MOVW	g, R9
   644  	MOVW	R31, R10 // this call frame does not save LR
   645  
   646  	JAL	runtime·load_g(SB)
   647  	MOVW	g_m(g), R1
   648  	MOVW	m_curg(R1), R1
   649  	MOVW	(g_stack+stack_hi)(R1), R2 // return value in R2
   650  
   651  	MOVW	R8, R23
   652  	MOVW	R9, g
   653  	MOVW	R10, R31
   654  
   655  	RET
   656  
   657  // The top-most function running on a goroutine
   658  // returns to goexit+PCQuantum.
   659  TEXT runtime·goexit(SB),NOSPLIT|NOFRAME,$0-0
   660  	NOR	R0, R0	// NOP
   661  	JAL	runtime·goexit1(SB)	// does not return
   662  	// traceback from goexit1 must hit code range of goexit
   663  	NOR	R0, R0	// NOP
   664  
   665  TEXT ·checkASM(SB),NOSPLIT,$0-1
   666  	MOVW	$1, R1
   667  	MOVB	R1, ret+0(FP)
   668  	RET
   669  
   670  // gcWriteBarrier performs a heap pointer write and informs the GC.
   671  //
   672  // gcWriteBarrier does NOT follow the Go ABI. It takes two arguments:
   673  // - R20 is the destination of the write
   674  // - R21 is the value being written at R20.
   675  // It clobbers R23 (the linker temp register).
   676  // The act of CALLing gcWriteBarrier will clobber R31 (LR).
   677  // It does not clobber any other general-purpose registers,
   678  // but may clobber others (e.g., floating point registers).
   679  TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$104
   680  	// Save the registers clobbered by the fast path.
   681  	MOVW	R1, 100(R29)
   682  	MOVW	R2, 104(R29)
   683  	MOVW	g_m(g), R1
   684  	MOVW	m_p(R1), R1
   685  	MOVW	(p_wbBuf+wbBuf_next)(R1), R2
   686  	// Increment wbBuf.next position.
   687  	ADD	$8, R2
   688  	MOVW	R2, (p_wbBuf+wbBuf_next)(R1)
   689  	MOVW	(p_wbBuf+wbBuf_end)(R1), R1
   690  	MOVW	R1, R23		// R23 is linker temp register
   691  	// Record the write.
   692  	MOVW	R21, -8(R2)	// Record value
   693  	MOVW	(R20), R1	// TODO: This turns bad writes into bad reads.
   694  	MOVW	R1, -4(R2)	// Record *slot
   695  	// Is the buffer full?
   696  	BEQ	R2, R23, flush
   697  ret:
   698  	MOVW	100(R29), R1
   699  	MOVW	104(R29), R2
   700  	// Do the write.
   701  	MOVW	R21, (R20)
   702  	RET
   703  
   704  flush:
   705  	// Save all general purpose registers since these could be
   706  	// clobbered by wbBufFlush and were not saved by the caller.
   707  	MOVW	R20, 4(R29)	// Also first argument to wbBufFlush
   708  	MOVW	R21, 8(R29)	// Also second argument to wbBufFlush
   709  	// R1 already saved
   710  	// R2 already saved
   711  	MOVW	R3, 12(R29)
   712  	MOVW	R4, 16(R29)
   713  	MOVW	R5, 20(R29)
   714  	MOVW	R6, 24(R29)
   715  	MOVW	R7, 28(R29)
   716  	MOVW	R8, 32(R29)
   717  	MOVW	R9, 36(R29)
   718  	MOVW	R10, 40(R29)
   719  	MOVW	R11, 44(R29)
   720  	MOVW	R12, 48(R29)
   721  	MOVW	R13, 52(R29)
   722  	MOVW	R14, 56(R29)
   723  	MOVW	R15, 60(R29)
   724  	MOVW	R16, 64(R29)
   725  	MOVW	R17, 68(R29)
   726  	MOVW	R18, 72(R29)
   727  	MOVW	R19, 76(R29)
   728  	MOVW	R20, 80(R29)
   729  	// R21 already saved
   730  	// R22 already saved.
   731  	MOVW	R22, 84(R29)
   732  	// R23 is tmp register.
   733  	MOVW	R24, 88(R29)
   734  	MOVW	R25, 92(R29)
   735  	// R26 is reserved by kernel.
   736  	// R27 is reserved by kernel.
   737  	MOVW	R28, 96(R29)
   738  	// R29 is SP.
   739  	// R30 is g.
   740  	// R31 is LR, which was saved by the prologue.
   741  
   742  	// This takes arguments R20 and R21.
   743  	CALL	runtime·wbBufFlush(SB)
   744  
   745  	MOVW	4(R29), R20
   746  	MOVW	8(R29), R21
   747  	MOVW	12(R29), R3
   748  	MOVW	16(R29), R4
   749  	MOVW	20(R29), R5
   750  	MOVW	24(R29), R6
   751  	MOVW	28(R29), R7
   752  	MOVW	32(R29), R8
   753  	MOVW	36(R29), R9
   754  	MOVW	40(R29), R10
   755  	MOVW	44(R29), R11
   756  	MOVW	48(R29), R12
   757  	MOVW	52(R29), R13
   758  	MOVW	56(R29), R14
   759  	MOVW	60(R29), R15
   760  	MOVW	64(R29), R16
   761  	MOVW	68(R29), R17
   762  	MOVW	72(R29), R18
   763  	MOVW	76(R29), R19
   764  	MOVW	80(R29), R20
   765  	MOVW	84(R29), R22
   766  	MOVW	88(R29), R24
   767  	MOVW	92(R29), R25
   768  	MOVW	96(R29), R28
   769  	JMP	ret