github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/pkg/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 "zasm_GOOS_GOARCH.h"
     6  #include "funcdata.h"
     7  #include "../../cmd/ld/textflag.h"
     8  
     9  // using frame size $-4 means do not save LR on stack.
    10  TEXT _rt0_go(SB),NOSPLIT,$-4
    11  	MOVW	$0xcafebabe, R12
    12  
    13  	// copy arguments forward on an even stack
    14  	// use R13 instead of SP to avoid linker rewriting the offsets
    15  	MOVW	0(R13), R0		// argc
    16  	MOVW	4(R13), R1		// argv
    17  	SUB	$64, R13		// plenty of scratch
    18  	AND	$~7, R13
    19  	MOVW	R0, 60(R13)		// save argc, argv away
    20  	MOVW	R1, 64(R13)
    21  
    22  	// set up m and g registers
    23  	// g is R10, m is R9
    24  	MOVW	$runtime·g0(SB), g
    25  	MOVW	$runtime·m0(SB), m
    26  
    27  	// save m->g0 = g0
    28  	MOVW	g, m_g0(m)
    29  
    30  	// create istack out of the OS stack
    31  	MOVW	$(-8192+104)(R13), R0
    32  	MOVW	R0, g_stackguard(g)	// (w 104b guard)
    33  	MOVW	R0, g_stackguard0(g)
    34  	MOVW	R13, g_stackbase(g)
    35  	BL	runtime·emptyfunc(SB)	// fault if stack check is wrong
    36  
    37  	// if there is an _cgo_init, call it.
    38  	MOVW	_cgo_init(SB), R4
    39  	CMP	$0, R4
    40  	B.EQ	nocgo
    41  	BL		runtime·save_gm(SB);
    42  	MOVW	g, R0 // first argument of _cgo_init is g
    43  	MOVW	$setmg_gcc<>(SB), R1 // second argument is address of save_gm
    44  	BL		(R4) // will clobber R0-R3
    45  
    46  nocgo:
    47  	// update stackguard after _cgo_init
    48  	MOVW	g_stackguard0(g), R0
    49  	MOVW	R0, g_stackguard(g)
    50  
    51  	BL	runtime·checkgoarm(SB)
    52  	BL	runtime·check(SB)
    53  
    54  	// saved argc, argv
    55  	MOVW	60(R13), R0
    56  	MOVW	R0, 4(R13)
    57  	MOVW	64(R13), R1
    58  	MOVW	R1, 8(R13)
    59  	BL	runtime·args(SB)
    60  	BL	runtime·osinit(SB)
    61  	BL	runtime·hashinit(SB)
    62  	BL	runtime·schedinit(SB)
    63  
    64  	// create a new goroutine to start program
    65  	MOVW	$runtime·main·f(SB), R0
    66  	MOVW.W	R0, -4(R13)
    67  	MOVW	$8, R0
    68  	MOVW.W	R0, -4(R13)
    69  	MOVW	$0, R0
    70  	MOVW.W	R0, -4(R13)	// push $0 as guard
    71  	ARGSIZE(12)
    72  	BL	runtime·newproc(SB)
    73  	ARGSIZE(-1)
    74  	MOVW	$12(R13), R13	// pop args and LR
    75  
    76  	// start this M
    77  	BL	runtime·mstart(SB)
    78  
    79  	MOVW	$1234, R0
    80  	MOVW	$1000, R1
    81  	MOVW	R0, (R1)	// fail hard
    82  
    83  DATA	runtime·main·f+0(SB)/4,$runtime·main(SB)
    84  GLOBL	runtime·main·f(SB),RODATA,$4
    85  
    86  TEXT runtime·breakpoint(SB),NOSPLIT,$0-0
    87  	// gdb won't skip this breakpoint instruction automatically,
    88  	// so you must manually "set $pc+=4" to skip it and continue.
    89  	WORD	$0xe1200071	// BKPT 0x0001
    90  	RET
    91  
    92  GLOBL runtime·goarm(SB), $4
    93  
    94  TEXT runtime·asminit(SB),NOSPLIT,$0-0
    95  	// disable runfast (flush-to-zero) mode of vfp if runtime.goarm > 5
    96  	MOVW	runtime·goarm(SB), R11
    97  	CMP	$5, R11
    98  	BLE	4(PC)
    99  	WORD	$0xeef1ba10	// vmrs r11, fpscr
   100  	BIC	$(1<<24), R11
   101  	WORD	$0xeee1ba10	// vmsr fpscr, r11
   102  	RET
   103  
   104  /*
   105   *  go-routine
   106   */
   107  
   108  // void gosave(Gobuf*)
   109  // save state in Gobuf; setjmp
   110  TEXT runtime·gosave(SB), NOSPLIT, $-4-4
   111  	MOVW	0(FP), R0		// gobuf
   112  	MOVW	SP, gobuf_sp(R0)
   113  	MOVW	LR, gobuf_pc(R0)
   114  	MOVW	g, gobuf_g(R0)
   115  	MOVW	$0, R11
   116  	MOVW	R11, gobuf_lr(R0)
   117  	MOVW	R11, gobuf_ret(R0)
   118  	MOVW	R11, gobuf_ctxt(R0)
   119  	RET
   120  
   121  // void gogo(Gobuf*)
   122  // restore state from Gobuf; longjmp
   123  TEXT runtime·gogo(SB), NOSPLIT, $-4-4
   124  	MOVW	0(FP), R1		// gobuf
   125  	MOVW	gobuf_g(R1), g
   126  	MOVW	0(g), R2		// make sure g != nil
   127  	MOVB	runtime·iscgo(SB), R2
   128  	CMP 	$0, R2 // if in Cgo, we have to save g and m
   129  	BL.NE	runtime·save_gm(SB) // this call will clobber R0
   130  	MOVW	gobuf_sp(R1), SP	// restore SP
   131  	MOVW	gobuf_lr(R1), LR
   132  	MOVW	gobuf_ret(R1), R0
   133  	MOVW	gobuf_ctxt(R1), R7
   134  	MOVW	$0, R11
   135  	MOVW	R11, gobuf_sp(R1)	// clear to help garbage collector
   136  	MOVW	R11, gobuf_ret(R1)
   137  	MOVW	R11, gobuf_lr(R1)
   138  	MOVW	R11, gobuf_ctxt(R1)
   139  	CMP	R11, R11 // set condition codes for == test, needed by stack split
   140  	MOVW	gobuf_pc(R1), PC
   141  
   142  // void mcall(void (*fn)(G*))
   143  // Switch to m->g0's stack, call fn(g).
   144  // Fn must never return.  It should gogo(&g->sched)
   145  // to keep running g.
   146  TEXT runtime·mcall(SB), NOSPLIT, $-4-4
   147  	MOVW	fn+0(FP), R0
   148  
   149  	// Save caller state in g->sched.
   150  	MOVW	SP, (g_sched+gobuf_sp)(g)
   151  	MOVW	LR, (g_sched+gobuf_pc)(g)
   152  	MOVW	$0, R11
   153  	MOVW	R11, (g_sched+gobuf_lr)(g)
   154  	MOVW	g, (g_sched+gobuf_g)(g)
   155  
   156  	// Switch to m->g0 & its stack, call fn.
   157  	MOVW	g, R1
   158  	MOVW	m_g0(m), g
   159  	CMP	g, R1
   160  	B.NE	2(PC)
   161  	B	runtime·badmcall(SB)
   162  	MOVW	(g_sched+gobuf_sp)(g), SP
   163  	SUB	$8, SP
   164  	MOVW	R1, 4(SP)
   165  	BL	(R0)
   166  	B	runtime·badmcall2(SB)
   167  	RET
   168  
   169  /*
   170   * support for morestack
   171   */
   172  
   173  // Called during function prolog when more stack is needed.
   174  // R1 frame size
   175  // R2 arg size
   176  // R3 prolog's LR
   177  // NB. we do not save R0 because we've forced 5c to pass all arguments
   178  // on the stack.
   179  // using frame size $-4 means do not save LR on stack.
   180  //
   181  // The traceback routines see morestack on a g0 as being
   182  // the top of a stack (for example, morestack calling newstack
   183  // calling the scheduler calling newm calling gc), so we must
   184  // record an argument size. For that purpose, it has no arguments.
   185  TEXT runtime·morestack(SB),NOSPLIT,$-4-0
   186  	// Cannot grow scheduler stack (m->g0).
   187  	MOVW	m_g0(m), R4
   188  	CMP	g, R4
   189  	BL.EQ	runtime·abort(SB)
   190  
   191  	MOVW	R1, m_moreframesize(m)
   192  	MOVW	R2, m_moreargsize(m)
   193  
   194  	// Called from f.
   195  	// Set g->sched to context in f.
   196  	MOVW	R7, (g_sched+gobuf_ctxt)(g)
   197  	MOVW	SP, (g_sched+gobuf_sp)(g)
   198  	MOVW	LR, (g_sched+gobuf_pc)(g)
   199  	MOVW	R3, (g_sched+gobuf_lr)(g)
   200  
   201  	// Called from f.
   202  	// Set m->morebuf to f's caller.
   203  	MOVW	R3, (m_morebuf+gobuf_pc)(m)	// f's caller's PC
   204  	MOVW	SP, (m_morebuf+gobuf_sp)(m)	// f's caller's SP
   205  	MOVW	$4(SP), R3			// f's argument pointer
   206  	MOVW	R3, m_moreargp(m)	
   207  	MOVW	g, (m_morebuf+gobuf_g)(m)
   208  
   209  	// Call newstack on m->g0's stack.
   210  	MOVW	m_g0(m), g
   211  	MOVW	(g_sched+gobuf_sp)(g), SP
   212  	BL	runtime·newstack(SB)
   213  
   214  	// Not reached, but make sure the return PC from the call to newstack
   215  	// is still in this function, and not the beginning of the next.
   216  	RET
   217  
   218  // Called from panic.  Mimics morestack,
   219  // reuses stack growth code to create a frame
   220  // with the desired args running the desired function.
   221  //
   222  // func call(fn *byte, arg *byte, argsize uint32).
   223  TEXT runtime·newstackcall(SB), NOSPLIT, $-4-12
   224  	// Save our caller's state as the PC and SP to
   225  	// restore when returning from f.
   226  	MOVW	LR, (m_morebuf+gobuf_pc)(m)	// our caller's PC
   227  	MOVW	SP, (m_morebuf+gobuf_sp)(m)	// our caller's SP
   228  	MOVW	g,  (m_morebuf+gobuf_g)(m)
   229  
   230  	// Save our own state as the PC and SP to restore
   231  	// if this goroutine needs to be restarted.
   232  	MOVW	$runtime·newstackcall(SB), R11
   233  	MOVW	R11, (g_sched+gobuf_pc)(g)
   234  	MOVW	LR, (g_sched+gobuf_lr)(g)
   235  	MOVW	SP, (g_sched+gobuf_sp)(g)
   236  
   237  	// Set up morestack arguments to call f on a new stack.
   238  	// We set f's frame size to 1, as a hint to newstack
   239  	// that this is a call from runtime·newstackcall.
   240  	// If it turns out that f needs a larger frame than
   241  	// the default stack, f's usual stack growth prolog will
   242  	// allocate a new segment (and recopy the arguments).
   243  	MOVW	4(SP), R0			// fn
   244  	MOVW	8(SP), R1			// arg frame
   245  	MOVW	12(SP), R2			// arg size
   246  
   247  	MOVW	R0, m_cret(m)			// f's PC
   248  	MOVW	R1, m_moreargp(m)		// f's argument pointer
   249  	MOVW	R2, m_moreargsize(m)		// f's argument size
   250  	MOVW	$1, R3
   251  	MOVW	R3, m_moreframesize(m)		// f's frame size
   252  
   253  	// Call newstack on m->g0's stack.
   254  	MOVW	m_g0(m), g
   255  	MOVW	(g_sched+gobuf_sp)(g), SP
   256  	B	runtime·newstack(SB)
   257  
   258  // reflect·call: call a function with the given argument list
   259  // func call(f *FuncVal, arg *byte, argsize uint32).
   260  // we don't have variable-sized frames, so we use a small number
   261  // of constant-sized-frame functions to encode a few bits of size in the pc.
   262  // Caution: ugly multiline assembly macros in your future!
   263  
   264  #define DISPATCH(NAME,MAXSIZE)		\
   265  	CMP	$MAXSIZE, R0;		\
   266  	B.HI	3(PC);			\
   267  	MOVW	$runtime·NAME(SB), R1;	\
   268  	B	(R1)
   269  
   270  TEXT reflect·call(SB), NOSPLIT, $-4-12
   271  	MOVW	argsize+8(FP), R0
   272  	DISPATCH(call16, 16)
   273  	DISPATCH(call32, 32)
   274  	DISPATCH(call64, 64)
   275  	DISPATCH(call128, 128)
   276  	DISPATCH(call256, 256)
   277  	DISPATCH(call512, 512)
   278  	DISPATCH(call1024, 1024)
   279  	DISPATCH(call2048, 2048)
   280  	DISPATCH(call4096, 4096)
   281  	DISPATCH(call8192, 8192)
   282  	DISPATCH(call16384, 16384)
   283  	DISPATCH(call32768, 32768)
   284  	DISPATCH(call65536, 65536)
   285  	DISPATCH(call131072, 131072)
   286  	DISPATCH(call262144, 262144)
   287  	DISPATCH(call524288, 524288)
   288  	DISPATCH(call1048576, 1048576)
   289  	DISPATCH(call2097152, 2097152)
   290  	DISPATCH(call4194304, 4194304)
   291  	DISPATCH(call8388608, 8388608)
   292  	DISPATCH(call16777216, 16777216)
   293  	DISPATCH(call33554432, 33554432)
   294  	DISPATCH(call67108864, 67108864)
   295  	DISPATCH(call134217728, 134217728)
   296  	DISPATCH(call268435456, 268435456)
   297  	DISPATCH(call536870912, 536870912)
   298  	DISPATCH(call1073741824, 1073741824)
   299  	MOVW	$runtime·badreflectcall(SB), R1
   300  	B	(R1)
   301  
   302  #define CALLFN(NAME,MAXSIZE)			\
   303  TEXT runtime·NAME(SB), 0, $MAXSIZE-12;		\
   304  	/* copy arguments to stack */		\
   305  	MOVW	argptr+4(FP), R0;		\
   306  	MOVW	argsize+8(FP), R2;		\
   307  	ADD	$4, SP, R1;			\
   308  	CMP	$0, R2;				\
   309  	B.EQ	5(PC);				\
   310  	MOVBU.P	1(R0), R5;			\
   311  	MOVBU.P R5, 1(R1);			\
   312  	SUB	$1, R2, R2;			\
   313  	B	-5(PC);				\
   314  	/* call function */			\
   315  	MOVW	f+0(FP), R7;			\
   316  	MOVW	(R7), R0;			\
   317  	BL	(R0);				\
   318  	/* copy return values back */		\
   319  	MOVW	argptr+4(FP), R0;		\
   320  	MOVW	argsize+8(FP), R2;		\
   321  	ADD	$4, SP, R1;			\
   322  	CMP	$0, R2;				\
   323  	RET.EQ	;				\
   324  	MOVBU.P	1(R1), R5;			\
   325  	MOVBU.P R5, 1(R0);			\
   326  	SUB	$1, R2, R2;			\
   327  	B	-5(PC)				\
   328  
   329  CALLFN(call16, 16)
   330  CALLFN(call32, 32)
   331  CALLFN(call64, 64)
   332  CALLFN(call128, 128)
   333  CALLFN(call256, 256)
   334  CALLFN(call512, 512)
   335  CALLFN(call1024, 1024)
   336  CALLFN(call2048, 2048)
   337  CALLFN(call4096, 4096)
   338  CALLFN(call8192, 8192)
   339  CALLFN(call16384, 16384)
   340  CALLFN(call32768, 32768)
   341  CALLFN(call65536, 65536)
   342  CALLFN(call131072, 131072)
   343  CALLFN(call262144, 262144)
   344  CALLFN(call524288, 524288)
   345  CALLFN(call1048576, 1048576)
   346  CALLFN(call2097152, 2097152)
   347  CALLFN(call4194304, 4194304)
   348  CALLFN(call8388608, 8388608)
   349  CALLFN(call16777216, 16777216)
   350  CALLFN(call33554432, 33554432)
   351  CALLFN(call67108864, 67108864)
   352  CALLFN(call134217728, 134217728)
   353  CALLFN(call268435456, 268435456)
   354  CALLFN(call536870912, 536870912)
   355  CALLFN(call1073741824, 1073741824)
   356  
   357  // Return point when leaving stack.
   358  // using frame size $-4 means do not save LR on stack.
   359  //
   360  // Lessstack can appear in stack traces for the same reason
   361  // as morestack; in that context, it has 0 arguments.
   362  TEXT runtime·lessstack(SB), NOSPLIT, $-4-0
   363  	// Save return value in m->cret
   364  	MOVW	R0, m_cret(m)
   365  
   366  	// Call oldstack on m->g0's stack.
   367  	MOVW	m_g0(m), g
   368  	MOVW	(g_sched+gobuf_sp)(g), SP
   369  	BL	runtime·oldstack(SB)
   370  
   371  // void jmpdefer(fn, sp);
   372  // called from deferreturn.
   373  // 1. grab stored LR for caller
   374  // 2. sub 4 bytes to get back to BL deferreturn
   375  // 3. B to fn
   376  TEXT runtime·jmpdefer(SB), NOSPLIT, $0-8
   377  	MOVW	0(SP), LR
   378  	MOVW	$-4(LR), LR	// BL deferreturn
   379  	MOVW	fn+0(FP), R7
   380  	MOVW	argp+4(FP), SP
   381  	MOVW	$-4(SP), SP	// SP is 4 below argp, due to saved LR
   382  	MOVW	0(R7), R1
   383  	B	(R1)
   384  
   385  // Save state of caller into g->sched. Smashes R11.
   386  TEXT gosave<>(SB),NOSPLIT,$0
   387  	MOVW	LR, (g_sched+gobuf_pc)(g)
   388  	MOVW	R13, (g_sched+gobuf_sp)(g)
   389  	MOVW	$0, R11
   390  	MOVW	R11, (g_sched+gobuf_lr)(g)
   391  	MOVW	R11, (g_sched+gobuf_ret)(g)
   392  	MOVW	R11, (g_sched+gobuf_ctxt)(g)
   393  	RET
   394  
   395  // asmcgocall(void(*fn)(void*), void *arg)
   396  // Call fn(arg) on the scheduler stack,
   397  // aligned appropriately for the gcc ABI.
   398  // See cgocall.c for more details.
   399  TEXT	runtime·asmcgocall(SB),NOSPLIT,$0-8
   400  	MOVW	fn+0(FP), R1
   401  	MOVW	arg+4(FP), R0
   402  	MOVW	R13, R2
   403  	MOVW	g, R5
   404  
   405  	// Figure out if we need to switch to m->g0 stack.
   406  	// We get called to create new OS threads too, and those
   407  	// come in on the m->g0 stack already.
   408  	MOVW	m_g0(m), R3
   409  	CMP	R3, g
   410  	BEQ	4(PC)
   411  	BL	gosave<>(SB)
   412  	MOVW	R3, g
   413  	MOVW	(g_sched+gobuf_sp)(g), R13
   414  
   415  	// Now on a scheduling stack (a pthread-created stack).
   416  	SUB	$24, R13
   417  	BIC	$0x7, R13	// alignment for gcc ABI
   418  	MOVW	R5, 20(R13) // save old g
   419  	MOVW	R2, 16(R13)	// save old SP
   420  	// R0 already contains the first argument
   421  	BL	(R1)
   422  
   423  	// Restore registers, g, stack pointer.
   424  	MOVW	20(R13), g
   425  	MOVW	16(R13), R13
   426  	RET
   427  
   428  // cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
   429  // Turn the fn into a Go func (by taking its address) and call
   430  // cgocallback_gofunc.
   431  TEXT runtime·cgocallback(SB),NOSPLIT,$12-12
   432  	MOVW	$fn+0(FP), R0
   433  	MOVW	R0, 4(R13)
   434  	MOVW	frame+4(FP), R0
   435  	MOVW	R0, 8(R13)
   436  	MOVW	framesize+8(FP), R0
   437  	MOVW	R0, 12(R13)
   438  	MOVW	$runtime·cgocallback_gofunc(SB), R0
   439  	BL	(R0)
   440  	RET
   441  
   442  // cgocallback_gofunc(void (*fn)(void*), void *frame, uintptr framesize)
   443  // See cgocall.c for more details.
   444  TEXT	runtime·cgocallback_gofunc(SB),NOSPLIT,$8-12
   445  	// Load m and g from thread-local storage.
   446  	MOVB	runtime·iscgo(SB), R0
   447  	CMP	$0, R0
   448  	BL.NE	runtime·load_gm(SB)
   449  
   450  	// If m is nil, Go did not create the current thread.
   451  	// Call needm to obtain one for temporary use.
   452  	// In this case, we're running on the thread stack, so there's
   453  	// lots of space, but the linker doesn't know. Hide the call from
   454  	// the linker analysis by using an indirect call.
   455  	MOVW	m, savedm-4(SP)
   456  	CMP	$0, m
   457  	B.NE	havem
   458  	MOVW	$runtime·needm(SB), R0
   459  	BL	(R0)
   460  
   461  havem:
   462  	// Now there's a valid m, and we're running on its m->g0.
   463  	// Save current m->g0->sched.sp on stack and then set it to SP.
   464  	// Save current sp in m->g0->sched.sp in preparation for
   465  	// switch back to m->curg stack.
   466  	// NOTE: unwindm knows that the saved g->sched.sp is at 4(R13) aka savedsp-8(SP).
   467  	MOVW	m_g0(m), R3
   468  	MOVW	(g_sched+gobuf_sp)(R3), R4
   469  	MOVW	R4, savedsp-8(SP)
   470  	MOVW	R13, (g_sched+gobuf_sp)(R3)
   471  
   472  	// Switch to m->curg stack and call runtime.cgocallbackg.
   473  	// Because we are taking over the execution of m->curg
   474  	// but *not* resuming what had been running, we need to
   475  	// save that information (m->curg->sched) so we can restore it.
   476  	// We can restore m->curg->sched.sp easily, because calling
   477  	// runtime.cgocallbackg leaves SP unchanged upon return.
   478  	// To save m->curg->sched.pc, we push it onto the stack.
   479  	// This has the added benefit that it looks to the traceback
   480  	// routine like cgocallbackg is going to return to that
   481  	// PC (because the frame we allocate below has the same
   482  	// size as cgocallback_gofunc's frame declared above)
   483  	// so that the traceback will seamlessly trace back into
   484  	// the earlier calls.
   485  	//
   486  	// In the new goroutine, -8(SP) and -4(SP) are unused.
   487  	MOVW	fn+4(FP), R0
   488  	MOVW	frame+8(FP), R1
   489  	MOVW	framesize+12(FP), R2
   490  	MOVW	m_curg(m), g
   491  	MOVW	(g_sched+gobuf_sp)(g), R4 // prepare stack as R4
   492  	MOVW	(g_sched+gobuf_pc)(g), R5
   493  	MOVW	R5, -12(R4)
   494  	MOVW	$-12(R4), R13
   495  	BL	runtime·cgocallbackg(SB)
   496  
   497  	// Restore g->sched (== m->curg->sched) from saved values.
   498  	MOVW	0(R13), R5
   499  	MOVW	R5, (g_sched+gobuf_pc)(g)
   500  	MOVW	$12(R13), R4
   501  	MOVW	R4, (g_sched+gobuf_sp)(g)
   502  
   503  	// Switch back to m->g0's stack and restore m->g0->sched.sp.
   504  	// (Unlike m->curg, the g0 goroutine never uses sched.pc,
   505  	// so we do not have to restore it.)
   506  	MOVW	m_g0(m), g
   507  	MOVW	(g_sched+gobuf_sp)(g), R13
   508  	MOVW	savedsp-8(SP), R4
   509  	MOVW	R4, (g_sched+gobuf_sp)(g)
   510  
   511  	// If the m on entry was nil, we called needm above to borrow an m
   512  	// for the duration of the call. Since the call is over, return it with dropm.
   513  	MOVW	savedm-4(SP), R6
   514  	CMP	$0, R6
   515  	B.NE	3(PC)
   516  	MOVW	$runtime·dropm(SB), R0
   517  	BL	(R0)
   518  
   519  	// Done!
   520  	RET
   521  
   522  // void setmg(M*, G*); set m and g. for use by needm.
   523  TEXT runtime·setmg(SB), NOSPLIT, $0-8
   524  	MOVW	mm+0(FP), m
   525  	MOVW	gg+4(FP), g
   526  
   527  	// Save m and g to thread-local storage.
   528  	MOVB	runtime·iscgo(SB), R0
   529  	CMP	$0, R0
   530  	BL.NE	runtime·save_gm(SB)
   531  
   532  	RET
   533  
   534  TEXT runtime·getcallerpc(SB),NOSPLIT,$-4-4
   535  	MOVW	0(SP), R0
   536  	RET
   537  
   538  TEXT runtime·setcallerpc(SB),NOSPLIT,$-4-8
   539  	MOVW	x+4(FP), R0
   540  	MOVW	R0, 0(SP)
   541  	RET
   542  
   543  TEXT runtime·getcallersp(SB),NOSPLIT,$-4-4
   544  	MOVW	0(FP), R0
   545  	MOVW	$-4(R0), R0
   546  	RET
   547  
   548  TEXT runtime·emptyfunc(SB),0,$0-0
   549  	RET
   550  
   551  TEXT runtime·abort(SB),NOSPLIT,$-4-0
   552  	MOVW	$0, R0
   553  	MOVW	(R0), R1
   554  
   555  // bool armcas(int32 *val, int32 old, int32 new)
   556  // Atomically:
   557  //	if(*val == old){
   558  //		*val = new;
   559  //		return 1;
   560  //	}else
   561  //		return 0;
   562  //
   563  // To implement runtime·cas in sys_$GOOS_arm.s
   564  // using the native instructions, use:
   565  //
   566  //	TEXT runtime·cas(SB),NOSPLIT,$0
   567  //		B	runtime·armcas(SB)
   568  //
   569  TEXT runtime·armcas(SB),NOSPLIT,$0-12
   570  	MOVW	valptr+0(FP), R1
   571  	MOVW	old+4(FP), R2
   572  	MOVW	new+8(FP), R3
   573  casl:
   574  	LDREX	(R1), R0
   575  	CMP	R0, R2
   576  	BNE	casfail
   577  	STREX	R3, (R1), R0
   578  	CMP	$0, R0
   579  	BNE	casl
   580  	MOVW	$1, R0
   581  	RET
   582  casfail:
   583  	MOVW	$0, R0
   584  	RET
   585  
   586  TEXT runtime·stackguard(SB),NOSPLIT,$0-8
   587  	MOVW	R13, R1
   588  	MOVW	g_stackguard(g), R2
   589  	MOVW	R1, sp+0(FP)
   590  	MOVW	R2, limit+4(FP)
   591  	RET
   592  
   593  // AES hashing not implemented for ARM
   594  TEXT runtime·aeshash(SB),NOSPLIT,$-4-0
   595  	MOVW	$0, R0
   596  	MOVW	(R0), R1
   597  TEXT runtime·aeshash32(SB),NOSPLIT,$-4-0
   598  	MOVW	$0, R0
   599  	MOVW	(R0), R1
   600  TEXT runtime·aeshash64(SB),NOSPLIT,$-4-0
   601  	MOVW	$0, R0
   602  	MOVW	(R0), R1
   603  TEXT runtime·aeshashstr(SB),NOSPLIT,$-4-0
   604  	MOVW	$0, R0
   605  	MOVW	(R0), R1
   606  
   607  TEXT runtime·memeq(SB),NOSPLIT,$-4-12
   608  	MOVW	a+0(FP), R1
   609  	MOVW	b+4(FP), R2
   610  	MOVW	n+8(FP), R3
   611  	ADD	R1, R3, R6
   612  	MOVW	$1, R0
   613  _next:
   614  	CMP	R1, R6
   615  	RET.EQ
   616  	MOVBU.P	1(R1), R4
   617  	MOVBU.P	1(R2), R5
   618  	CMP	R4, R5
   619  	BEQ	_next
   620  
   621  	MOVW	$0, R0
   622  	RET
   623  
   624  // We have to resort to TLS variable to save g(R10) and
   625  // m(R9). One reason is that external code might trigger
   626  // SIGSEGV, and our runtime.sigtramp don't even know we
   627  // are in external code, and will continue to use R10/R9,
   628  // this might as well result in another SIGSEGV.
   629  // Note: all three functions will clobber R0, and the last
   630  // two can be called from 5c ABI code.
   631  
   632  // g (R10) at 8(TP), m (R9) at 12(TP)
   633  TEXT runtime·save_gm(SB),NOSPLIT,$0
   634  	MRC		15, 0, R0, C13, C0, 3 // Fetch TLS register
   635  	MOVW	g, 8(R0)
   636  	MOVW	m, 12(R0)
   637  	RET
   638  
   639  TEXT runtime·load_gm(SB),NOSPLIT,$0
   640  	MRC		15, 0, R0, C13, C0, 3 // Fetch TLS register
   641  	MOVW	8(R0), g
   642  	MOVW	12(R0), m
   643  	RET
   644  
   645  // void setmg_gcc(M*, G*); set m and g called from gcc.
   646  TEXT setmg_gcc<>(SB),NOSPLIT,$0
   647  	MOVW	R0, m
   648  	MOVW	R1, g
   649  	B		runtime·save_gm(SB)
   650  
   651  
   652  // TODO: share code with memeq?
   653  TEXT bytes·Equal(SB),NOSPLIT,$0
   654  	MOVW	a_len+4(FP), R1
   655  	MOVW	b_len+16(FP), R3
   656  	
   657  	CMP	R1, R3		// unequal lengths are not equal
   658  	B.NE	_notequal
   659  
   660  	MOVW	a+0(FP), R0
   661  	MOVW	b+12(FP), R2
   662  	ADD	R0, R1		// end
   663  
   664  _byteseq_next:
   665  	CMP	R0, R1
   666  	B.EQ	_equal		// reached the end
   667  	MOVBU.P	1(R0), R4
   668  	MOVBU.P	1(R2), R5
   669  	CMP	R4, R5
   670  	B.EQ	_byteseq_next
   671  
   672  _notequal:
   673  	MOVW	$0, R0
   674  	MOVBU	R0, ret+24(FP)
   675  	RET
   676  
   677  _equal:
   678  	MOVW	$1, R0
   679  	MOVBU	R0, ret+24(FP)
   680  	RET
   681  
   682  TEXT bytes·IndexByte(SB),NOSPLIT,$0
   683  	MOVW	s+0(FP), R0
   684  	MOVW	s_len+4(FP), R1
   685  	MOVBU	c+12(FP), R2	// byte to find
   686  	MOVW	R0, R4		// store base for later
   687  	ADD	R0, R1		// end 
   688  
   689  _loop:
   690  	CMP	R0, R1
   691  	B.EQ	_notfound
   692  	MOVBU.P	1(R0), R3
   693  	CMP	R2, R3
   694  	B.NE	_loop
   695  
   696  	SUB	$1, R0		// R0 will be one beyond the position we want
   697  	SUB	R4, R0		// remove base
   698  	MOVW    R0, ret+16(FP) 
   699  	RET
   700  
   701  _notfound:
   702  	MOVW	$-1, R0
   703  	MOVW	R0, ret+16(FP)
   704  	RET
   705  
   706  TEXT strings·IndexByte(SB),NOSPLIT,$0
   707  	MOVW	s+0(FP), R0
   708  	MOVW	s_len+4(FP), R1
   709  	MOVBU	c+8(FP), R2	// byte to find
   710  	MOVW	R0, R4		// store base for later
   711  	ADD	R0, R1		// end 
   712  
   713  _sib_loop:
   714  	CMP	R0, R1
   715  	B.EQ	_sib_notfound
   716  	MOVBU.P	1(R0), R3
   717  	CMP	R2, R3
   718  	B.NE	_sib_loop
   719  
   720  	SUB	$1, R0		// R0 will be one beyond the position we want
   721  	SUB	R4, R0		// remove base
   722  	MOVW	R0, ret+12(FP) 
   723  	RET
   724  
   725  _sib_notfound:
   726  	MOVW	$-1, R0
   727  	MOVW	R0, ret+12(FP)
   728  	RET