github.com/aloncn/graphics-go@v0.0.1/src/runtime/asm_ppc64x.s (about)

     1  // Copyright 2014 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 ppc64 ppc64le
     6  
     7  #include "go_asm.h"
     8  #include "go_tls.h"
     9  #include "funcdata.h"
    10  #include "textflag.h"
    11  #include "asm_ppc64x.h"
    12  
    13  TEXT runtime·rt0_go(SB),NOSPLIT,$0
    14  	// R1 = stack; R3 = argc; R4 = argv; R13 = C TLS base pointer
    15  
    16  	// initialize essential registers
    17  	BL	runtime·reginit(SB)
    18  
    19  	SUB	$(FIXED_FRAME+16), R1
    20  	MOVD	R2, 24(R1)		// stash the TOC pointer away again now we've created a new frame
    21  	MOVW	R3, FIXED_FRAME+0(R1)	// argc
    22  	MOVD	R4, FIXED_FRAME+8(R1)	// argv
    23  
    24  	// create istack out of the given (operating system) stack.
    25  	// _cgo_init may update stackguard.
    26  	MOVD	$runtime·g0(SB), g
    27  	MOVD	$(-64*1024), R31
    28  	ADD	R31, R1, R3
    29  	MOVD	R3, g_stackguard0(g)
    30  	MOVD	R3, g_stackguard1(g)
    31  	MOVD	R3, (g_stack+stack_lo)(g)
    32  	MOVD	R1, (g_stack+stack_hi)(g)
    33  
    34  	// if there is a _cgo_init, call it using the gcc ABI.
    35  	MOVD	_cgo_init(SB), R12
    36  	CMP	R0, R12
    37  	BEQ	nocgo
    38  	MOVD	R12, CTR		// r12 = "global function entry point"
    39  	MOVD	R13, R5			// arg 2: TLS base pointer
    40  	MOVD	$setg_gcc<>(SB), R4 	// arg 1: setg
    41  	MOVD	g, R3			// arg 0: G
    42  	// C functions expect 32 bytes of space on caller stack frame
    43  	// and a 16-byte aligned R1
    44  	MOVD	R1, R14			// save current stack
    45  	SUB	$32, R1			// reserve 32 bytes
    46  	RLDCR	$0, R1, $~15, R1	// 16-byte align
    47  	BL	(CTR)			// may clobber R0, R3-R12
    48  	MOVD	R14, R1			// restore stack
    49  	MOVD	24(R1), R2
    50  	XOR	R0, R0			// fix R0
    51  
    52  nocgo:
    53  	// update stackguard after _cgo_init
    54  	MOVD	(g_stack+stack_lo)(g), R3
    55  	ADD	$const__StackGuard, R3
    56  	MOVD	R3, g_stackguard0(g)
    57  	MOVD	R3, g_stackguard1(g)
    58  
    59  	// set the per-goroutine and per-mach "registers"
    60  	MOVD	$runtime·m0(SB), R3
    61  
    62  	// save m->g0 = g0
    63  	MOVD	g, m_g0(R3)
    64  	// save m0 to g0->m
    65  	MOVD	R3, g_m(g)
    66  
    67  	BL	runtime·check(SB)
    68  
    69  	// args are already prepared
    70  	BL	runtime·args(SB)
    71  	BL	runtime·osinit(SB)
    72  	BL	runtime·schedinit(SB)
    73  
    74  	// create a new goroutine to start program
    75  	MOVD	$runtime·mainPC(SB), R3		// entry
    76  	MOVDU	R3, -8(R1)
    77  	MOVDU	R0, -8(R1)
    78  	MOVDU	R0, -8(R1)
    79  	MOVDU	R0, -8(R1)
    80  	MOVDU	R0, -8(R1)
    81  	MOVDU	R0, -8(R1)
    82  	BL	runtime·newproc(SB)
    83  	ADD	$(16+FIXED_FRAME), R1
    84  
    85  	// start this M
    86  	BL	runtime·mstart(SB)
    87  
    88  	MOVD	R0, 1(R0)
    89  	RET
    90  
    91  DATA	runtime·mainPC+0(SB)/8,$runtime·main(SB)
    92  GLOBL	runtime·mainPC(SB),RODATA,$8
    93  
    94  TEXT runtime·breakpoint(SB),NOSPLIT|NOFRAME,$0-0
    95  	MOVD	R0, 2(R0) // TODO: TD
    96  	RET
    97  
    98  TEXT runtime·asminit(SB),NOSPLIT|NOFRAME,$0-0
    99  	RET
   100  
   101  TEXT _cgo_reginit(SB),NOSPLIT|NOFRAME,$0-0
   102  	// crosscall_ppc64 and crosscall2 need to reginit, but can't
   103  	// get at the 'runtime.reginit' symbol.
   104  	BR	runtime·reginit(SB)
   105  
   106  TEXT runtime·reginit(SB),NOSPLIT|NOFRAME,$0-0
   107  	// set R0 to zero, it's expected by the toolchain
   108  	XOR R0, R0
   109  	// initialize essential FP registers
   110  	FMOVD	$4503601774854144.0, F27
   111  	FMOVD	$0.5, F29
   112  	FSUB	F29, F29, F28
   113  	FADD	F29, F29, F30
   114  	FADD	F30, F30, F31
   115  	RET
   116  
   117  /*
   118   *  go-routine
   119   */
   120  
   121  // void gosave(Gobuf*)
   122  // save state in Gobuf; setjmp
   123  TEXT runtime·gosave(SB), NOSPLIT|NOFRAME, $0-8
   124  	MOVD	buf+0(FP), R3
   125  	MOVD	R1, gobuf_sp(R3)
   126  	MOVD	LR, R31
   127  	MOVD	R31, gobuf_pc(R3)
   128  	MOVD	g, gobuf_g(R3)
   129  	MOVD	R0, gobuf_lr(R3)
   130  	MOVD	R0, gobuf_ret(R3)
   131  	MOVD	R0, gobuf_ctxt(R3)
   132  	RET
   133  
   134  // void gogo(Gobuf*)
   135  // restore state from Gobuf; longjmp
   136  TEXT runtime·gogo(SB), NOSPLIT|NOFRAME, $0-8
   137  	MOVD	buf+0(FP), R5
   138  	MOVD	gobuf_g(R5), g	// make sure g is not nil
   139  	BL	runtime·save_g(SB)
   140  
   141  	MOVD	0(g), R4
   142  	MOVD	gobuf_sp(R5), R1
   143  	MOVD	gobuf_lr(R5), R31
   144  	MOVD	R31, LR
   145  	MOVD	gobuf_ret(R5), R3
   146  	MOVD	gobuf_ctxt(R5), R11
   147  	MOVD	R0, gobuf_sp(R5)
   148  	MOVD	R0, gobuf_ret(R5)
   149  	MOVD	R0, gobuf_lr(R5)
   150  	MOVD	R0, gobuf_ctxt(R5)
   151  	CMP	R0, R0 // set condition codes for == test, needed by stack split
   152  	MOVD	gobuf_pc(R5), R12
   153  	MOVD	R12, CTR
   154  	BR	(CTR)
   155  
   156  // void mcall(fn func(*g))
   157  // Switch to m->g0's stack, call fn(g).
   158  // Fn must never return.  It should gogo(&g->sched)
   159  // to keep running g.
   160  TEXT runtime·mcall(SB), NOSPLIT|NOFRAME, $0-8
   161  	// Save caller state in g->sched
   162  	MOVD	R1, (g_sched+gobuf_sp)(g)
   163  	MOVD	LR, R31
   164  	MOVD	R31, (g_sched+gobuf_pc)(g)
   165  	MOVD	R0, (g_sched+gobuf_lr)(g)
   166  	MOVD	g, (g_sched+gobuf_g)(g)
   167  
   168  	// Switch to m->g0 & its stack, call fn.
   169  	MOVD	g, R3
   170  	MOVD	g_m(g), R8
   171  	MOVD	m_g0(R8), g
   172  	BL	runtime·save_g(SB)
   173  	CMP	g, R3
   174  	BNE	2(PC)
   175  	BR	runtime·badmcall(SB)
   176  	MOVD	fn+0(FP), R11			// context
   177  	MOVD	0(R11), R12			// code pointer
   178  	MOVD	R12, CTR
   179  	MOVD	(g_sched+gobuf_sp)(g), R1	// sp = m->g0->sched.sp
   180  	MOVDU	R3, -8(R1)
   181  	MOVDU	R0, -8(R1)
   182  	MOVDU	R0, -8(R1)
   183  	MOVDU	R0, -8(R1)
   184  	MOVDU	R0, -8(R1)
   185  	BL	(CTR)
   186  	MOVD	24(R1), R2
   187  	BR	runtime·badmcall2(SB)
   188  
   189  // systemstack_switch is a dummy routine that systemstack leaves at the bottom
   190  // of the G stack.  We need to distinguish the routine that
   191  // lives at the bottom of the G stack from the one that lives
   192  // at the top of the system stack because the one at the top of
   193  // the system stack terminates the stack walk (see topofstack()).
   194  TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
   195  	// We have several undefs here so that 16 bytes past
   196  	// $runtime·systemstack_switch lies within them whether or not the
   197          // instructions that derive r2 from r12 are there.
   198  	UNDEF
   199  	UNDEF
   200  	UNDEF
   201  	BL	(LR)	// make sure this function is not leaf
   202  	RET
   203  
   204  // func systemstack(fn func())
   205  TEXT runtime·systemstack(SB), NOSPLIT, $0-8
   206  	MOVD	fn+0(FP), R3	// R3 = fn
   207  	MOVD	R3, R11		// context
   208  	MOVD	g_m(g), R4	// R4 = m
   209  
   210  	MOVD	m_gsignal(R4), R5	// R5 = gsignal
   211  	CMP	g, R5
   212  	BEQ	noswitch
   213  
   214  	MOVD	m_g0(R4), R5	// R5 = g0
   215  	CMP	g, R5
   216  	BEQ	noswitch
   217  
   218  	MOVD	m_curg(R4), R6
   219  	CMP	g, R6
   220  	BEQ	switch
   221  
   222  	// Bad: g is not gsignal, not g0, not curg. What is it?
   223  	// Hide call from linker nosplit analysis.
   224  	MOVD	$runtime·badsystemstack(SB), R12
   225  	MOVD	R12, CTR
   226  	BL	(CTR)
   227  
   228  switch:
   229  	// save our state in g->sched.  Pretend to
   230  	// be systemstack_switch if the G stack is scanned.
   231  	MOVD	$runtime·systemstack_switch(SB), R6
   232  	ADD     $16, R6 // get past prologue (including r2-setting instructions when they're there)
   233  	MOVD	R6, (g_sched+gobuf_pc)(g)
   234  	MOVD	R1, (g_sched+gobuf_sp)(g)
   235  	MOVD	R0, (g_sched+gobuf_lr)(g)
   236  	MOVD	g, (g_sched+gobuf_g)(g)
   237  
   238  	// switch to g0
   239  	MOVD	R5, g
   240  	BL	runtime·save_g(SB)
   241  	MOVD	(g_sched+gobuf_sp)(g), R3
   242  	// make it look like mstart called systemstack on g0, to stop traceback
   243  	SUB	$FIXED_FRAME, R3
   244  	MOVD	$runtime·mstart(SB), R4
   245  	MOVD	R4, 0(R3)
   246  	MOVD	R3, R1
   247  
   248  	// call target function
   249  	MOVD	0(R11), R12	// code pointer
   250  	MOVD	R12, CTR
   251  	BL	(CTR)
   252  
   253  	// restore TOC pointer. It seems unlikely that we will use systemstack
   254  	// to call a function defined in another module, but the results of
   255  	// doing so would be so confusing that it's worth doing this.
   256  	MOVD	g_m(g), R3
   257  	MOVD	m_curg(R3), g
   258  	MOVD	(g_sched+gobuf_sp)(g), R3
   259  	MOVD	24(R3), R2
   260  	// switch back to g
   261  	MOVD	g_m(g), R3
   262  	MOVD	m_curg(R3), g
   263  	BL	runtime·save_g(SB)
   264  	MOVD	(g_sched+gobuf_sp)(g), R1
   265  	MOVD	R0, (g_sched+gobuf_sp)(g)
   266  	RET
   267  
   268  noswitch:
   269  	// already on m stack, just call directly
   270  	MOVD	0(R11), R12	// code pointer
   271  	MOVD	R12, CTR
   272  	BL	(CTR)
   273  	MOVD	24(R1), R2
   274  	RET
   275  
   276  /*
   277   * support for morestack
   278   */
   279  
   280  // Called during function prolog when more stack is needed.
   281  // Caller has already loaded:
   282  // R3: framesize, R4: argsize, R5: LR
   283  //
   284  // The traceback routines see morestack on a g0 as being
   285  // the top of a stack (for example, morestack calling newstack
   286  // calling the scheduler calling newm calling gc), so we must
   287  // record an argument size. For that purpose, it has no arguments.
   288  TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
   289  	// Cannot grow scheduler stack (m->g0).
   290  	MOVD	g_m(g), R7
   291  	MOVD	m_g0(R7), R8
   292  	CMP	g, R8
   293  	BNE	2(PC)
   294  	BL	runtime·abort(SB)
   295  
   296  	// Cannot grow signal stack (m->gsignal).
   297  	MOVD	m_gsignal(R7), R8
   298  	CMP	g, R8
   299  	BNE	2(PC)
   300  	BL	runtime·abort(SB)
   301  
   302  	// Called from f.
   303  	// Set g->sched to context in f.
   304  	MOVD	R11, (g_sched+gobuf_ctxt)(g)
   305  	MOVD	R1, (g_sched+gobuf_sp)(g)
   306  	MOVD	LR, R8
   307  	MOVD	R8, (g_sched+gobuf_pc)(g)
   308  	MOVD	R5, (g_sched+gobuf_lr)(g)
   309  
   310  	// Called from f.
   311  	// Set m->morebuf to f's caller.
   312  	MOVD	R5, (m_morebuf+gobuf_pc)(R7)	// f's caller's PC
   313  	MOVD	R1, (m_morebuf+gobuf_sp)(R7)	// f's caller's SP
   314  	MOVD	g, (m_morebuf+gobuf_g)(R7)
   315  
   316  	// Call newstack on m->g0's stack.
   317  	MOVD	m_g0(R7), g
   318  	BL	runtime·save_g(SB)
   319  	MOVD	(g_sched+gobuf_sp)(g), R1
   320  	BL	runtime·newstack(SB)
   321  
   322  	// Not reached, but make sure the return PC from the call to newstack
   323  	// is still in this function, and not the beginning of the next.
   324  	UNDEF
   325  
   326  TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0
   327  	MOVD	R0, R11
   328  	BR	runtime·morestack(SB)
   329  
   330  TEXT runtime·stackBarrier(SB),NOSPLIT,$0
   331  	// We came here via a RET to an overwritten LR.
   332  	// R3 may be live. Other registers are available.
   333  
   334  	// Get the original return PC, g.stkbar[g.stkbarPos].savedLRVal.
   335  	MOVD	(g_stkbar+slice_array)(g), R4
   336  	MOVD	g_stkbarPos(g), R5
   337  	MOVD	$stkbar__size, R6
   338  	MULLD	R5, R6
   339  	ADD	R4, R6
   340  	MOVD	stkbar_savedLRVal(R6), R6
   341  	// Record that this stack barrier was hit.
   342  	ADD	$1, R5
   343  	MOVD	R5, g_stkbarPos(g)
   344  	// Jump to the original return PC.
   345  	MOVD	R6, CTR
   346  	BR	(CTR)
   347  
   348  // reflectcall: call a function with the given argument list
   349  // func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32).
   350  // we don't have variable-sized frames, so we use a small number
   351  // of constant-sized-frame functions to encode a few bits of size in the pc.
   352  // Caution: ugly multiline assembly macros in your future!
   353  
   354  #define DISPATCH(NAME,MAXSIZE)		\
   355  	MOVD	$MAXSIZE, R31;		\
   356  	CMP	R3, R31;		\
   357  	BGT	4(PC);			\
   358  	MOVD	$NAME(SB), R12;		\
   359  	MOVD	R12, CTR;		\
   360  	BR	(CTR)
   361  // Note: can't just "BR NAME(SB)" - bad inlining results.
   362  
   363  TEXT reflect·call(SB), NOSPLIT, $0-0
   364  	BR	·reflectcall(SB)
   365  
   366  TEXT ·reflectcall(SB), NOSPLIT|NOFRAME, $0-32
   367  	MOVWZ argsize+24(FP), R3
   368  	// NOTE(rsc): No call16, because CALLFN needs four words
   369  	// of argument space to invoke callwritebarrier.
   370  	DISPATCH(runtime·call32, 32)
   371  	DISPATCH(runtime·call64, 64)
   372  	DISPATCH(runtime·call128, 128)
   373  	DISPATCH(runtime·call256, 256)
   374  	DISPATCH(runtime·call512, 512)
   375  	DISPATCH(runtime·call1024, 1024)
   376  	DISPATCH(runtime·call2048, 2048)
   377  	DISPATCH(runtime·call4096, 4096)
   378  	DISPATCH(runtime·call8192, 8192)
   379  	DISPATCH(runtime·call16384, 16384)
   380  	DISPATCH(runtime·call32768, 32768)
   381  	DISPATCH(runtime·call65536, 65536)
   382  	DISPATCH(runtime·call131072, 131072)
   383  	DISPATCH(runtime·call262144, 262144)
   384  	DISPATCH(runtime·call524288, 524288)
   385  	DISPATCH(runtime·call1048576, 1048576)
   386  	DISPATCH(runtime·call2097152, 2097152)
   387  	DISPATCH(runtime·call4194304, 4194304)
   388  	DISPATCH(runtime·call8388608, 8388608)
   389  	DISPATCH(runtime·call16777216, 16777216)
   390  	DISPATCH(runtime·call33554432, 33554432)
   391  	DISPATCH(runtime·call67108864, 67108864)
   392  	DISPATCH(runtime·call134217728, 134217728)
   393  	DISPATCH(runtime·call268435456, 268435456)
   394  	DISPATCH(runtime·call536870912, 536870912)
   395  	DISPATCH(runtime·call1073741824, 1073741824)
   396  	MOVD	$runtime·badreflectcall(SB), R12
   397  	MOVD	R12, CTR
   398  	BR	(CTR)
   399  
   400  #define CALLFN(NAME,MAXSIZE)			\
   401  TEXT NAME(SB), WRAPPER, $MAXSIZE-24;		\
   402  	NO_LOCAL_POINTERS;			\
   403  	/* copy arguments to stack */		\
   404  	MOVD	arg+16(FP), R3;			\
   405  	MOVWZ	argsize+24(FP), R4;			\
   406  	MOVD	R1, R5;				\
   407  	ADD	$(FIXED_FRAME-1), R5;			\
   408  	SUB	$1, R3;				\
   409  	ADD	R5, R4;				\
   410  	CMP	R5, R4;				\
   411  	BEQ	4(PC);				\
   412  	MOVBZU	1(R3), R6;			\
   413  	MOVBZU	R6, 1(R5);			\
   414  	BR	-4(PC);				\
   415  	/* call function */			\
   416  	MOVD	f+8(FP), R11;			\
   417  	MOVD	(R11), R12;			\
   418  	MOVD	R12, CTR;			\
   419  	PCDATA  $PCDATA_StackMapIndex, $0;	\
   420  	BL	(CTR);				\
   421  	MOVD	24(R1), R2;			\
   422  	/* copy return values back */		\
   423  	MOVD	arg+16(FP), R3;			\
   424  	MOVWZ	n+24(FP), R4;			\
   425  	MOVWZ	retoffset+28(FP), R6;		\
   426  	MOVD	R1, R5;				\
   427  	ADD	R6, R5; 			\
   428  	ADD	R6, R3;				\
   429  	SUB	R6, R4;				\
   430  	ADD	$(FIXED_FRAME-1), R5;			\
   431  	SUB	$1, R3;				\
   432  	ADD	R5, R4;				\
   433  loop:						\
   434  	CMP	R5, R4;				\
   435  	BEQ	end;				\
   436  	MOVBZU	1(R5), R6;			\
   437  	MOVBZU	R6, 1(R3);			\
   438  	BR	loop;				\
   439  end:						\
   440  	/* execute write barrier updates */	\
   441  	MOVD	argtype+0(FP), R7;		\
   442  	MOVD	arg+16(FP), R3;			\
   443  	MOVWZ	n+24(FP), R4;			\
   444  	MOVWZ	retoffset+28(FP), R6;		\
   445  	MOVD	R7, FIXED_FRAME+0(R1);			\
   446  	MOVD	R3, FIXED_FRAME+8(R1);			\
   447  	MOVD	R4, FIXED_FRAME+16(R1);			\
   448  	MOVD	R6, FIXED_FRAME+24(R1);			\
   449  	BL	runtime·callwritebarrier(SB);	\
   450  	RET
   451  
   452  CALLFN(·call32, 32)
   453  CALLFN(·call64, 64)
   454  CALLFN(·call128, 128)
   455  CALLFN(·call256, 256)
   456  CALLFN(·call512, 512)
   457  CALLFN(·call1024, 1024)
   458  CALLFN(·call2048, 2048)
   459  CALLFN(·call4096, 4096)
   460  CALLFN(·call8192, 8192)
   461  CALLFN(·call16384, 16384)
   462  CALLFN(·call32768, 32768)
   463  CALLFN(·call65536, 65536)
   464  CALLFN(·call131072, 131072)
   465  CALLFN(·call262144, 262144)
   466  CALLFN(·call524288, 524288)
   467  CALLFN(·call1048576, 1048576)
   468  CALLFN(·call2097152, 2097152)
   469  CALLFN(·call4194304, 4194304)
   470  CALLFN(·call8388608, 8388608)
   471  CALLFN(·call16777216, 16777216)
   472  CALLFN(·call33554432, 33554432)
   473  CALLFN(·call67108864, 67108864)
   474  CALLFN(·call134217728, 134217728)
   475  CALLFN(·call268435456, 268435456)
   476  CALLFN(·call536870912, 536870912)
   477  CALLFN(·call1073741824, 1073741824)
   478  
   479  TEXT runtime·procyield(SB),NOSPLIT,$0-0
   480  	RET
   481  
   482  // void jmpdefer(fv, sp);
   483  // called from deferreturn.
   484  // 1. grab stored LR for caller
   485  // 2. sub 8 bytes to get back to either nop or toc reload before deferreturn
   486  // 3. BR to fn
   487  // When dynamically linking Go, it is not sufficient to rewind to the BL
   488  // deferreturn -- we might be jumping between modules and so we need to reset
   489  // the TOC pointer in r2. To do this, codegen inserts MOVD 24(R1), R2 *before*
   490  // the BL deferreturn and jmpdefer rewinds to that.
   491  TEXT runtime·jmpdefer(SB), NOSPLIT|NOFRAME, $0-16
   492  	MOVD	0(R1), R31
   493  	SUB     $8, R31
   494  	MOVD	R31, LR
   495  
   496  	MOVD	fv+0(FP), R11
   497  	MOVD	argp+8(FP), R1
   498  	SUB	$FIXED_FRAME, R1
   499  	MOVD	0(R11), R12
   500  	MOVD	R12, CTR
   501  	BR	(CTR)
   502  
   503  // Save state of caller into g->sched. Smashes R31.
   504  TEXT gosave<>(SB),NOSPLIT|NOFRAME,$0
   505  	MOVD	LR, R31
   506  	MOVD	R31, (g_sched+gobuf_pc)(g)
   507  	MOVD	R1, (g_sched+gobuf_sp)(g)
   508  	MOVD	R0, (g_sched+gobuf_lr)(g)
   509  	MOVD	R0, (g_sched+gobuf_ret)(g)
   510  	MOVD	R0, (g_sched+gobuf_ctxt)(g)
   511  	RET
   512  
   513  // func asmcgocall(fn, arg unsafe.Pointer) int32
   514  // Call fn(arg) on the scheduler stack,
   515  // aligned appropriately for the gcc ABI.
   516  // See cgocall.go for more details.
   517  TEXT ·asmcgocall(SB),NOSPLIT,$0-20
   518  	MOVD	fn+0(FP), R3
   519  	MOVD	arg+8(FP), R4
   520  
   521  	MOVD	R1, R7		// save original stack pointer
   522  	MOVD	g, R5
   523  
   524  	// Figure out if we need to switch to m->g0 stack.
   525  	// We get called to create new OS threads too, and those
   526  	// come in on the m->g0 stack already.
   527  	MOVD	g_m(g), R6
   528  	MOVD	m_g0(R6), R6
   529  	CMP	R6, g
   530  	BEQ	g0
   531  	BL	gosave<>(SB)
   532  	MOVD	R6, g
   533  	BL	runtime·save_g(SB)
   534  	MOVD	(g_sched+gobuf_sp)(g), R1
   535  
   536  	// Now on a scheduling stack (a pthread-created stack).
   537  g0:
   538  	// Save room for two of our pointers, plus 32 bytes of callee
   539  	// save area that lives on the caller stack.
   540  	SUB	$48, R1
   541  	RLDCR	$0, R1, $~15, R1	// 16-byte alignment for gcc ABI
   542  	MOVD	R5, 40(R1)	// save old g on stack
   543  	MOVD	(g_stack+stack_hi)(R5), R5
   544  	SUB	R7, R5
   545  	MOVD	R5, 32(R1)	// save depth in old g stack (can't just save SP, as stack might be copied during a callback)
   546  	MOVD	R0, 0(R1)	// clear back chain pointer (TODO can we give it real back trace information?)
   547  	// This is a "global call", so put the global entry point in r12
   548  	MOVD	R3, R12
   549  	MOVD	R12, CTR
   550  	MOVD	R4, R3		// arg in r3
   551  	BL	(CTR)
   552  
   553  	// C code can clobber R0, so set it back to 0.  F27-F31 are
   554  	// callee save, so we don't need to recover those.
   555  	XOR	R0, R0
   556  	// Restore g, stack pointer, toc pointer.
   557  	// R3 is errno, so don't touch it
   558  	MOVD	40(R1), g
   559  	MOVD    (g_stack+stack_hi)(g), R5
   560  	MOVD    32(R1), R6
   561  	SUB     R6, R5
   562  	MOVD    24(R5), R2
   563  	BL	runtime·save_g(SB)
   564  	MOVD	(g_stack+stack_hi)(g), R5
   565  	MOVD	32(R1), R6
   566  	SUB	R6, R5
   567  	MOVD	R5, R1
   568  
   569  	MOVW	R3, ret+16(FP)
   570  	RET
   571  
   572  // cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
   573  // Turn the fn into a Go func (by taking its address) and call
   574  // cgocallback_gofunc.
   575  TEXT runtime·cgocallback(SB),NOSPLIT,$24-24
   576  	MOVD	$fn+0(FP), R3
   577  	MOVD	R3, FIXED_FRAME+0(R1)
   578  	MOVD	frame+8(FP), R3
   579  	MOVD	R3, FIXED_FRAME+8(R1)
   580  	MOVD	framesize+16(FP), R3
   581  	MOVD	R3, FIXED_FRAME+16(R1)
   582  	MOVD	$runtime·cgocallback_gofunc(SB), R12
   583  	MOVD	R12, CTR
   584  	BL	(CTR)
   585  	RET
   586  
   587  // cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize)
   588  // See cgocall.go for more details.
   589  TEXT ·cgocallback_gofunc(SB),NOSPLIT,$16-24
   590  	NO_LOCAL_POINTERS
   591  
   592  	// Load m and g from thread-local storage.
   593  	MOVB	runtime·iscgo(SB), R3
   594  	CMP	R3, $0
   595  	BEQ	nocgo
   596  	BL	runtime·load_g(SB)
   597  nocgo:
   598  
   599  	// If g is nil, Go did not create the current thread.
   600  	// Call needm to obtain one for temporary use.
   601  	// In this case, we're running on the thread stack, so there's
   602  	// lots of space, but the linker doesn't know. Hide the call from
   603  	// the linker analysis by using an indirect call.
   604  	CMP	g, $0
   605  	BEQ	needm
   606  
   607  	MOVD	g_m(g), R8
   608  	MOVD	R8, savedm-8(SP)
   609  	BR	havem
   610  
   611  needm:
   612  	MOVD	g, savedm-8(SP) // g is zero, so is m.
   613  	MOVD	$runtime·needm(SB), R12
   614  	MOVD	R12, CTR
   615  	BL	(CTR)
   616  
   617  	// Set m->sched.sp = SP, so that if a panic happens
   618  	// during the function we are about to execute, it will
   619  	// have a valid SP to run on the g0 stack.
   620  	// The next few lines (after the havem label)
   621  	// will save this SP onto the stack and then write
   622  	// the same SP back to m->sched.sp. That seems redundant,
   623  	// but if an unrecovered panic happens, unwindm will
   624  	// restore the g->sched.sp from the stack location
   625  	// and then systemstack will try to use it. If we don't set it here,
   626  	// that restored SP will be uninitialized (typically 0) and
   627  	// will not be usable.
   628  	MOVD	g_m(g), R8
   629  	MOVD	m_g0(R8), R3
   630  	MOVD	R1, (g_sched+gobuf_sp)(R3)
   631  
   632  havem:
   633  	// Now there's a valid m, and we're running on its m->g0.
   634  	// Save current m->g0->sched.sp on stack and then set it to SP.
   635  	// Save current sp in m->g0->sched.sp in preparation for
   636  	// switch back to m->curg stack.
   637  	// NOTE: unwindm knows that the saved g->sched.sp is at 8(R1) aka savedsp-16(SP).
   638  	MOVD	m_g0(R8), R3
   639  	MOVD	(g_sched+gobuf_sp)(R3), R4
   640  	MOVD	R4, savedsp-16(SP)
   641  	MOVD	R1, (g_sched+gobuf_sp)(R3)
   642  
   643  	// Switch to m->curg stack and call runtime.cgocallbackg.
   644  	// Because we are taking over the execution of m->curg
   645  	// but *not* resuming what had been running, we need to
   646  	// save that information (m->curg->sched) so we can restore it.
   647  	// We can restore m->curg->sched.sp easily, because calling
   648  	// runtime.cgocallbackg leaves SP unchanged upon return.
   649  	// To save m->curg->sched.pc, we push it onto the stack.
   650  	// This has the added benefit that it looks to the traceback
   651  	// routine like cgocallbackg is going to return to that
   652  	// PC (because the frame we allocate below has the same
   653  	// size as cgocallback_gofunc's frame declared above)
   654  	// so that the traceback will seamlessly trace back into
   655  	// the earlier calls.
   656  	//
   657  	// In the new goroutine, -16(SP) and -8(SP) are unused.
   658  	MOVD	m_curg(R8), g
   659  	BL	runtime·save_g(SB)
   660  	MOVD	(g_sched+gobuf_sp)(g), R4 // prepare stack as R4
   661  	MOVD	(g_sched+gobuf_pc)(g), R5
   662  	MOVD	R5, -(FIXED_FRAME+16)(R4)
   663  	MOVD	$-(FIXED_FRAME+16)(R4), R1
   664  	BL	runtime·cgocallbackg(SB)
   665  
   666  	// Restore g->sched (== m->curg->sched) from saved values.
   667  	MOVD	0(R1), R5
   668  	MOVD	R5, (g_sched+gobuf_pc)(g)
   669  	MOVD	$(FIXED_FRAME+16)(R1), R4
   670  	MOVD	R4, (g_sched+gobuf_sp)(g)
   671  
   672  	// Switch back to m->g0's stack and restore m->g0->sched.sp.
   673  	// (Unlike m->curg, the g0 goroutine never uses sched.pc,
   674  	// so we do not have to restore it.)
   675  	MOVD	g_m(g), R8
   676  	MOVD	m_g0(R8), g
   677  	BL	runtime·save_g(SB)
   678  	MOVD	(g_sched+gobuf_sp)(g), R1
   679  	MOVD	savedsp-16(SP), R4
   680  	MOVD	R4, (g_sched+gobuf_sp)(g)
   681  
   682  	// If the m on entry was nil, we called needm above to borrow an m
   683  	// for the duration of the call. Since the call is over, return it with dropm.
   684  	MOVD	savedm-8(SP), R6
   685  	CMP	R6, $0
   686  	BNE	droppedm
   687  	MOVD	$runtime·dropm(SB), R12
   688  	MOVD	R12, CTR
   689  	BL	(CTR)
   690  droppedm:
   691  
   692  	// Done!
   693  	RET
   694  
   695  // void setg(G*); set g. for use by needm.
   696  TEXT runtime·setg(SB), NOSPLIT, $0-8
   697  	MOVD	gg+0(FP), g
   698  	// This only happens if iscgo, so jump straight to save_g
   699  	BL	runtime·save_g(SB)
   700  	RET
   701  
   702  // void setg_gcc(G*); set g in C TLS.
   703  // Must obey the gcc calling convention.
   704  TEXT setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0
   705  	// The standard prologue clobbers R31, which is callee-save in
   706  	// the C ABI, so we have to use $-8-0 and save LR ourselves.
   707  	MOVD	LR, R4
   708  	// Also save g and R31, since they're callee-save in C ABI
   709  	MOVD	R31, R5
   710  	MOVD	g, R6
   711  
   712  	MOVD	R3, g
   713  	BL	runtime·save_g(SB)
   714  
   715  	MOVD	R6, g
   716  	MOVD	R5, R31
   717  	MOVD	R4, LR
   718  	RET
   719  
   720  TEXT runtime·getcallerpc(SB),NOSPLIT,$8-16
   721  	MOVD	FIXED_FRAME+8(R1), R3		// LR saved by caller
   722  	MOVD	runtime·stackBarrierPC(SB), R4
   723  	CMP	R3, R4
   724  	BNE	nobar
   725  	// Get original return PC.
   726  	BL	runtime·nextBarrierPC(SB)
   727  	MOVD	FIXED_FRAME+0(R1), R3
   728  nobar:
   729  	MOVD	R3, ret+8(FP)
   730  	RET
   731  
   732  TEXT runtime·setcallerpc(SB),NOSPLIT,$8-16
   733  	MOVD	pc+8(FP), R3
   734  	MOVD	FIXED_FRAME+8(R1), R4
   735  	MOVD	runtime·stackBarrierPC(SB), R5
   736  	CMP	R4, R5
   737  	BEQ	setbar
   738  	MOVD	R3, FIXED_FRAME+8(R1)		// set LR in caller
   739  	RET
   740  setbar:
   741  	// Set the stack barrier return PC.
   742  	MOVD	R3, FIXED_FRAME+0(R1)
   743  	BL	runtime·setNextBarrierPC(SB)
   744  	RET
   745  
   746  TEXT runtime·getcallersp(SB),NOSPLIT,$0-16
   747  	MOVD	argp+0(FP), R3
   748  	SUB	$FIXED_FRAME, R3
   749  	MOVD	R3, ret+8(FP)
   750  	RET
   751  
   752  TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0
   753  	MOVW	(R0), R0
   754  	UNDEF
   755  
   756  #define	TBRL	268
   757  #define	TBRU	269		/* Time base Upper/Lower */
   758  
   759  // int64 runtime·cputicks(void)
   760  TEXT runtime·cputicks(SB),NOSPLIT,$0-8
   761  	MOVW	SPR(TBRU), R4
   762  	MOVW	SPR(TBRL), R3
   763  	MOVW	SPR(TBRU), R5
   764  	CMPW	R4, R5
   765  	BNE	-4(PC)
   766  	SLD	$32, R5
   767  	OR	R5, R3
   768  	MOVD	R3, ret+0(FP)
   769  	RET
   770  
   771  // memhash_varlen(p unsafe.Pointer, h seed) uintptr
   772  // redirects to memhash(p, h, size) using the size
   773  // stored in the closure.
   774  TEXT runtime·memhash_varlen(SB),NOSPLIT,$40-24
   775  	GO_ARGS
   776  	NO_LOCAL_POINTERS
   777  	MOVD	p+0(FP), R3
   778  	MOVD	h+8(FP), R4
   779  	MOVD	8(R11), R5
   780  	MOVD	R3, FIXED_FRAME+0(R1)
   781  	MOVD	R4, FIXED_FRAME+8(R1)
   782  	MOVD	R5, FIXED_FRAME+16(R1)
   783  	BL	runtime·memhash(SB)
   784  	MOVD	FIXED_FRAME+24(R1), R3
   785  	MOVD	R3, ret+16(FP)
   786  	RET
   787  
   788  // AES hashing not implemented for ppc64
   789  TEXT runtime·aeshash(SB),NOSPLIT|NOFRAME,$0-0
   790  	MOVW	(R0), R1
   791  TEXT runtime·aeshash32(SB),NOSPLIT|NOFRAME,$0-0
   792  	MOVW	(R0), R1
   793  TEXT runtime·aeshash64(SB),NOSPLIT|NOFRAME,$0-0
   794  	MOVW	(R0), R1
   795  TEXT runtime·aeshashstr(SB),NOSPLIT|NOFRAME,$0-0
   796  	MOVW	(R0), R1
   797  
   798  TEXT runtime·memeq(SB),NOSPLIT|NOFRAME,$0-25
   799  	MOVD	a+0(FP), R3
   800  	MOVD	b+8(FP), R4
   801  	MOVD	size+16(FP), R5
   802  	SUB	$1, R3
   803  	SUB	$1, R4
   804  	ADD	R3, R5, R8
   805  loop:
   806  	CMP	R3, R8
   807  	BNE	test
   808  	MOVD	$1, R3
   809  	MOVB	R3, ret+24(FP)
   810  	RET
   811  test:
   812  	MOVBZU	1(R3), R6
   813  	MOVBZU	1(R4), R7
   814  	CMP	R6, R7
   815  	BEQ	loop
   816  
   817  	MOVB	R0, ret+24(FP)
   818  	RET
   819  
   820  // memequal_varlen(a, b unsafe.Pointer) bool
   821  TEXT runtime·memequal_varlen(SB),NOSPLIT,$40-17
   822  	MOVD	a+0(FP), R3
   823  	MOVD	b+8(FP), R4
   824  	CMP	R3, R4
   825  	BEQ	eq
   826  	MOVD	8(R11), R5    // compiler stores size at offset 8 in the closure
   827  	MOVD	R3, FIXED_FRAME+0(R1)
   828  	MOVD	R4, FIXED_FRAME+8(R1)
   829  	MOVD	R5, FIXED_FRAME+16(R1)
   830  	BL	runtime·memeq(SB)
   831  	MOVBZ	FIXED_FRAME+24(R1), R3
   832  	MOVB	R3, ret+16(FP)
   833  	RET
   834  eq:
   835  	MOVD	$1, R3
   836  	MOVB	R3, ret+16(FP)
   837  	RET
   838  
   839  // eqstring tests whether two strings are equal.
   840  // The compiler guarantees that strings passed
   841  // to eqstring have equal length.
   842  // See runtime_test.go:eqstring_generic for
   843  // equivalent Go code.
   844  TEXT runtime·eqstring(SB),NOSPLIT,$0-33
   845  	MOVD	s1str+0(FP), R3
   846  	MOVD	s2str+16(FP), R4
   847  	MOVD	$1, R5
   848  	MOVB	R5, ret+32(FP)
   849  	CMP	R3, R4
   850  	BNE	2(PC)
   851  	RET
   852  	MOVD	s1len+8(FP), R5
   853  	SUB	$1, R3
   854  	SUB	$1, R4
   855  	ADD	R3, R5, R8
   856  loop:
   857  	CMP	R3, R8
   858  	BNE	2(PC)
   859  	RET
   860  	MOVBZU	1(R3), R6
   861  	MOVBZU	1(R4), R7
   862  	CMP	R6, R7
   863  	BEQ	loop
   864  	MOVB	R0, ret+32(FP)
   865  	RET
   866  
   867  // TODO: share code with memeq?
   868  TEXT bytes·Equal(SB),NOSPLIT,$0-49
   869  	MOVD	a_len+8(FP), R3
   870  	MOVD	b_len+32(FP), R4
   871  
   872  	CMP	R3, R4		// unequal lengths are not equal
   873  	BNE	noteq
   874  
   875  	MOVD	a+0(FP), R5
   876  	MOVD	b+24(FP), R6
   877  	SUB	$1, R5
   878  	SUB	$1, R6
   879  	ADD	R5, R3		// end-1
   880  
   881  loop:
   882  	CMP	R5, R3
   883  	BEQ	equal		// reached the end
   884  	MOVBZU	1(R5), R4
   885  	MOVBZU	1(R6), R7
   886  	CMP	R4, R7
   887  	BEQ	loop
   888  
   889  noteq:
   890  	MOVBZ	R0, ret+48(FP)
   891  	RET
   892  
   893  equal:
   894  	MOVD	$1, R3
   895  	MOVBZ	R3, ret+48(FP)
   896  	RET
   897  
   898  TEXT bytes·IndexByte(SB),NOSPLIT,$0-40
   899  	MOVD	s+0(FP), R3
   900  	MOVD	s_len+8(FP), R4
   901  	MOVBZ	c+24(FP), R5	// byte to find
   902  	MOVD	R3, R6		// store base for later
   903  	SUB	$1, R3
   904  	ADD	R3, R4		// end-1
   905  
   906  loop:
   907  	CMP	R3, R4
   908  	BEQ	notfound
   909  	MOVBZU	1(R3), R7
   910  	CMP	R7, R5
   911  	BNE	loop
   912  
   913  	SUB	R6, R3		// remove base
   914  	MOVD	R3, ret+32(FP)
   915  	RET
   916  
   917  notfound:
   918  	MOVD	$-1, R3
   919  	MOVD	R3, ret+32(FP)
   920  	RET
   921  
   922  TEXT strings·IndexByte(SB),NOSPLIT,$0-32
   923  	MOVD	p+0(FP), R3
   924  	MOVD	b_len+8(FP), R4
   925  	MOVBZ	c+16(FP), R5	// byte to find
   926  	MOVD	R3, R6		// store base for later
   927  	SUB	$1, R3
   928  	ADD	R3, R4		// end-1
   929  
   930  loop:
   931  	CMP	R3, R4
   932  	BEQ	notfound
   933  	MOVBZU	1(R3), R7
   934  	CMP	R7, R5
   935  	BNE	loop
   936  
   937  	SUB	R6, R3		// remove base
   938  	MOVD	R3, ret+24(FP)
   939  	RET
   940  
   941  notfound:
   942  	MOVD	$-1, R3
   943  	MOVD	R3, ret+24(FP)
   944  	RET
   945  
   946  TEXT runtime·cmpstring(SB),NOSPLIT|NOFRAME,$0-40
   947  	MOVD	s1_base+0(FP), R5
   948  	MOVD	s1_len+8(FP), R3
   949  	MOVD	s2_base+16(FP), R6
   950  	MOVD	s2_len+24(FP), R4
   951  	MOVD	$ret+32(FP), R7
   952  	BR	runtime·cmpbody<>(SB)
   953  
   954  TEXT bytes·Compare(SB),NOSPLIT|NOFRAME,$0-56
   955  	MOVD	s1+0(FP), R5
   956  	MOVD	s1+8(FP), R3
   957  	MOVD	s2+24(FP), R6
   958  	MOVD	s2+32(FP), R4
   959  	MOVD	$ret+48(FP), R7
   960  	BR	runtime·cmpbody<>(SB)
   961  
   962  // On entry:
   963  // R3 is the length of s1
   964  // R4 is the length of s2
   965  // R5 points to the start of s1
   966  // R6 points to the start of s2
   967  // R7 points to return value (-1/0/1 will be written here)
   968  //
   969  // On exit:
   970  // R5, R6, R8, R9 and R10 are clobbered
   971  TEXT runtime·cmpbody<>(SB),NOSPLIT|NOFRAME,$0-0
   972  	CMP	R5, R6
   973  	BEQ	samebytes // same starting pointers; compare lengths
   974  	SUB	$1, R5
   975  	SUB	$1, R6
   976  	MOVD	R4, R8
   977  	CMP	R3, R4
   978  	BGE	2(PC)
   979  	MOVD	R3, R8	// R8 is min(R3, R4)
   980  	ADD	R5, R8	// R5 is current byte in s1, R8 is last byte in s1 to compare
   981  loop:
   982  	CMP	R5, R8
   983  	BEQ	samebytes // all compared bytes were the same; compare lengths
   984  	MOVBZU	1(R5), R9
   985  	MOVBZU	1(R6), R10
   986  	CMP	R9, R10
   987  	BEQ	loop
   988  	// bytes differed
   989  	MOVD	$1, R4
   990  	BGT	2(PC)
   991  	NEG	R4
   992  	MOVD	R4, (R7)
   993  	RET
   994  samebytes:
   995  	MOVD	$1, R8
   996  	CMP	R3, R4
   997  	BNE	3(PC)
   998  	MOVD	R0, (R7)
   999  	RET
  1000  	BGT	2(PC)
  1001  	NEG	R8
  1002  	MOVD	R8, (R7)
  1003  	RET
  1004  
  1005  TEXT runtime·fastrand1(SB), NOSPLIT, $0-4
  1006  	MOVD	g_m(g), R4
  1007  	MOVWZ	m_fastrand(R4), R3
  1008  	ADD	R3, R3
  1009  	CMPW	R3, $0
  1010  	BGE	2(PC)
  1011  	XOR	$0x88888eef, R3
  1012  	MOVW	R3, m_fastrand(R4)
  1013  	MOVW	R3, ret+0(FP)
  1014  	RET
  1015  
  1016  TEXT runtime·return0(SB), NOSPLIT, $0
  1017  	MOVW	$0, R3
  1018  	RET
  1019  
  1020  // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
  1021  // Must obey the gcc calling convention.
  1022  TEXT _cgo_topofstack(SB),NOSPLIT|NOFRAME,$0
  1023  	// g (R30) and R31 are callee-save in the C ABI, so save them
  1024  	MOVD	g, R4
  1025  	MOVD	R31, R5
  1026  	MOVD	LR, R6
  1027  
  1028  	BL	runtime·load_g(SB)	// clobbers g (R30), R31
  1029  	MOVD	g_m(g), R3
  1030  	MOVD	m_curg(R3), R3
  1031  	MOVD	(g_stack+stack_hi)(R3), R3
  1032  
  1033  	MOVD	R4, g
  1034  	MOVD	R5, R31
  1035  	MOVD	R6, LR
  1036  	RET
  1037  
  1038  // The top-most function running on a goroutine
  1039  // returns to goexit+PCQuantum.
  1040  //
  1041  // When dynamically linking Go, it can be returned to from a function
  1042  // implemented in a different module and so needs to reload the TOC pointer
  1043  // from the stack (although this function declares that it does not set up x-a
  1044  // frame, newproc1 does in fact allocate one for goexit and saves the TOC
  1045  // pointer in the correct place).
  1046  // goexit+_PCQuantum is halfway through the usual global entry point prologue
  1047  // that derives r2 from r12 which is a bit silly, but not harmful.
  1048  TEXT runtime·goexit(SB),NOSPLIT|NOFRAME,$0-0
  1049  	MOVD	24(R1), R2
  1050  	BL	runtime·goexit1(SB)	// does not return
  1051  	// traceback from goexit1 must hit code range of goexit
  1052  	MOVD	R0, R0	// NOP
  1053  
  1054  TEXT runtime·prefetcht0(SB),NOSPLIT,$0-8
  1055  	RET
  1056  
  1057  TEXT runtime·prefetcht1(SB),NOSPLIT,$0-8
  1058  	RET
  1059  
  1060  TEXT runtime·prefetcht2(SB),NOSPLIT,$0-8
  1061  	RET
  1062  
  1063  TEXT runtime·prefetchnta(SB),NOSPLIT,$0-8
  1064  	RET
  1065  
  1066  TEXT runtime·sigreturn(SB),NOSPLIT,$0-8
  1067          RET
  1068  
  1069  // prepGoExitFrame saves the current TOC pointer (i.e. the TOC pointer for the
  1070  // module containing runtime) to the frame that goexit will execute in when
  1071  // the goroutine exits. It's implemented in assembly mainly because that's the
  1072  // easiest way to get access to R2.
  1073  TEXT runtime·prepGoExitFrame(SB),NOSPLIT,$0-8
  1074        MOVD    sp+0(FP), R3
  1075        MOVD    R2, 24(R3)
  1076        RET
  1077  
  1078  TEXT runtime·addmoduledata(SB),NOSPLIT|NOFRAME,$0-0
  1079  	ADD	$-8, R1
  1080  	MOVD	R31, 0(R1)
  1081  	MOVD	runtime·lastmoduledatap(SB), R4
  1082  	MOVD	R3, moduledata_next(R4)
  1083  	MOVD	R3, runtime·lastmoduledatap(SB)
  1084  	MOVD	0(R1), R31
  1085  	ADD	$8, R1
  1086  	RET
  1087  
  1088  TEXT ·checkASM(SB),NOSPLIT,$0-1
  1089  	MOVW	$1, R3
  1090  	MOVB	R3, ret+0(FP)
  1091  	RET