github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/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  
     7  // using frame size $-4 means do not save LR on stack.
     8  TEXT _rt0_arm(SB),7,$-4
     9  	MOVW	$0xcafebabe, R12
    10  
    11  	// copy arguments forward on an even stack
    12  	// use R13 instead of SP to avoid linker rewriting the offsets
    13  	MOVW	0(R13), R0		// argc
    14  	MOVW	$4(R13), R1		// argv
    15  	SUB	$64, R13		// plenty of scratch
    16  	AND	$~7, R13
    17  	MOVW	R0, 60(R13)		// save argc, argv away
    18  	MOVW	R1, 64(R13)
    19  
    20  	// set up m and g registers
    21  	// g is R10, m is R9
    22  	MOVW	$runtime·g0(SB), g
    23  	MOVW	$runtime·m0(SB), m
    24  
    25  	// save m->g0 = g0
    26  	MOVW	g, m_g0(m)
    27  
    28  	// create istack out of the OS stack
    29  	MOVW	$(-8192+104)(R13), R0
    30  	MOVW	R0, g_stackguard(g)	// (w 104b guard)
    31  	MOVW	R13, g_stackbase(g)
    32  	BL	runtime·emptyfunc(SB)	// fault if stack check is wrong
    33  
    34  	// if there is an _cgo_init, call it.
    35  	MOVW	_cgo_init(SB), R2
    36  	CMP	$0, R2
    37  	MOVW.NE	g, R0 // first argument of _cgo_init is g
    38  	BL.NE	(R2) // will clobber R0-R3
    39  
    40  	BL	runtime·checkgoarm(SB)
    41  	BL	runtime·check(SB)
    42  
    43  	// saved argc, argv
    44  	MOVW	60(R13), R0
    45  	MOVW	R0, 4(R13)
    46  	MOVW	64(R13), R1
    47  	MOVW	R1, 8(R13)
    48  	BL	runtime·args(SB)
    49  	BL	runtime·osinit(SB)
    50  	BL	runtime·hashinit(SB)
    51  	BL	runtime·schedinit(SB)
    52  
    53  	// create a new goroutine to start program
    54  	MOVW	$runtime·main·f(SB), R0
    55  	MOVW.W	R0, -4(R13)
    56  	MOVW	$8, R0
    57  	MOVW.W	R0, -4(R13)
    58  	MOVW	$0, R0
    59  	MOVW.W	R0, -4(R13)	// push $0 as guard
    60  	BL	runtime·newproc(SB)
    61  	MOVW	$12(R13), R13	// pop args and LR
    62  
    63  	// start this M
    64  	BL	runtime·mstart(SB)
    65  
    66  	MOVW	$1234, R0
    67  	MOVW	$1000, R1
    68  	MOVW	R0, (R1)	// fail hard
    69  
    70  DATA	runtime·main·f+0(SB)/4,$runtime·main(SB)
    71  GLOBL	runtime·main·f(SB),8,$4
    72  
    73  TEXT runtime·breakpoint(SB),7,$0
    74  	// gdb won't skip this breakpoint instruction automatically,
    75  	// so you must manually "set $pc+=4" to skip it and continue.
    76  	WORD    $0xe1200071 // BKPT 0x0001
    77  	RET
    78  
    79  GLOBL runtime·goarm(SB), $4
    80  TEXT runtime·asminit(SB),7,$0
    81  	// disable runfast (flush-to-zero) mode of vfp if runtime.goarm > 5
    82  	MOVW runtime·goarm(SB), R11
    83  	CMP $5, R11
    84  	BLE 4(PC)
    85  	WORD $0xeef1ba10	// vmrs r11, fpscr
    86  	BIC $(1<<24), R11
    87  	WORD $0xeee1ba10	// vmsr fpscr, r11
    88  	RET
    89  
    90  /*
    91   *  go-routine
    92   */
    93  
    94  // void gosave(Gobuf*)
    95  // save state in Gobuf; setjmp
    96  TEXT runtime·gosave(SB), 7, $-4
    97  	MOVW	0(FP), R0		// gobuf
    98  	MOVW	SP, gobuf_sp(R0)
    99  	MOVW	LR, gobuf_pc(R0)
   100  	MOVW	g, gobuf_g(R0)
   101  	RET
   102  
   103  // void gogo(Gobuf*, uintptr)
   104  // restore state from Gobuf; longjmp
   105  TEXT runtime·gogo(SB), 7, $-4
   106  	MOVW	0(FP), R1		// gobuf
   107  	MOVW	gobuf_g(R1), g
   108  	MOVW	0(g), R2		// make sure g != nil
   109  	MOVW	_cgo_save_gm(SB), R2
   110  	CMP 	$0, R2 // if in Cgo, we have to save g and m
   111  	BL.NE	(R2) // this call will clobber R0
   112  	MOVW	4(FP), R0		// return 2nd arg
   113  	MOVW	gobuf_sp(R1), SP	// restore SP
   114  	MOVW	gobuf_pc(R1), PC
   115  
   116  // void gogocall(Gobuf*, void (*fn)(void), uintptr r7)
   117  // restore state from Gobuf but then call fn.
   118  // (call fn, returning to state in Gobuf)
   119  // using frame size $-4 means do not save LR on stack.
   120  TEXT runtime·gogocall(SB), 7, $-4
   121  	MOVW	0(FP), R3		// gobuf
   122  	MOVW	4(FP), R1		// fn
   123  	MOVW	gobuf_g(R3), g
   124  	MOVW	0(g), R0		// make sure g != nil
   125  	MOVW	_cgo_save_gm(SB), R0
   126  	CMP 	$0, R0 // if in Cgo, we have to save g and m
   127  	BL.NE	(R0) // this call will clobber R0
   128  	MOVW	8(FP), R7	// context
   129  	MOVW	gobuf_sp(R3), SP	// restore SP
   130  	MOVW	gobuf_pc(R3), LR
   131  	MOVW	R1, PC
   132  
   133  // void gogocallfn(Gobuf*, FuncVal*)
   134  // restore state from Gobuf but then call fn.
   135  // (call fn, returning to state in Gobuf)
   136  // using frame size $-4 means do not save LR on stack.
   137  TEXT runtime·gogocallfn(SB), 7, $-4
   138  	MOVW	0(FP), R3		// gobuf
   139  	MOVW	4(FP), R1		// fn
   140  	MOVW	gobuf_g(R3), g
   141  	MOVW	0(g), R0		// make sure g != nil
   142  	MOVW	_cgo_save_gm(SB), R0
   143  	CMP 	$0, R0 // if in Cgo, we have to save g and m
   144  	BL.NE	(R0) // this call will clobber R0
   145  	MOVW	gobuf_sp(R3), SP	// restore SP
   146  	MOVW	gobuf_pc(R3), LR
   147  	MOVW	R1, R7
   148  	MOVW	0(R1), PC
   149  
   150  // void mcall(void (*fn)(G*))
   151  // Switch to m->g0's stack, call fn(g).
   152  // Fn must never return.  It should gogo(&g->sched)
   153  // to keep running g.
   154  TEXT runtime·mcall(SB), 7, $-4
   155  	MOVW	fn+0(FP), R0
   156  
   157  	// Save caller state in g->gobuf.
   158  	MOVW	SP, (g_sched+gobuf_sp)(g)
   159  	MOVW	LR, (g_sched+gobuf_pc)(g)
   160  	MOVW	g, (g_sched+gobuf_g)(g)
   161  
   162  	// Switch to m->g0 & its stack, call fn.
   163  	MOVW	g, R1
   164  	MOVW	m_g0(m), g
   165  	CMP	g, R1
   166  	BL.EQ	runtime·badmcall(SB)
   167  	MOVW	(g_sched+gobuf_sp)(g), SP
   168  	SUB	$8, SP
   169  	MOVW	R1, 4(SP)
   170  	BL	(R0)
   171  	BL	runtime·badmcall2(SB)
   172  	RET
   173  
   174  /*
   175   * support for morestack
   176   */
   177  
   178  // Called during function prolog when more stack is needed.
   179  // R1 frame size
   180  // R2 arg size
   181  // R3 prolog's LR
   182  // NB. we do not save R0 because we've forced 5c to pass all arguments
   183  // on the stack.
   184  // using frame size $-4 means do not save LR on stack.
   185  TEXT runtime·morestack(SB),7,$-4
   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  	// Save in m.
   192  	MOVW	R7, m_cret(m) // function context
   193  	MOVW	R1, m_moreframesize(m)
   194  	MOVW	R2, m_moreargsize(m)
   195  
   196  	// Called from f.
   197  	// Set m->morebuf to f's caller.
   198  	MOVW	R3, (m_morebuf+gobuf_pc)(m)	// f's caller's PC
   199  	MOVW	SP, (m_morebuf+gobuf_sp)(m)	// f's caller's SP
   200  	MOVW	$4(SP), R3			// f's argument pointer
   201  	MOVW	R3, m_moreargp(m)	
   202  	MOVW	g, (m_morebuf+gobuf_g)(m)
   203  
   204  	// Set m->morepc to f's PC.
   205  	MOVW	LR, m_morepc(m)
   206  
   207  	// Call newstack on m->g0's stack.
   208  	MOVW	m_g0(m), g
   209  	MOVW	(g_sched+gobuf_sp)(g), SP
   210  	B	runtime·newstack(SB)
   211  
   212  // Called from reflection library.  Mimics morestack,
   213  // reuses stack growth code to create a frame
   214  // with the desired args running the desired function.
   215  //
   216  // func call(fn *byte, arg *byte, argsize uint32).
   217  TEXT reflect·call(SB), 7, $-4
   218  	// Save our caller's state as the PC and SP to
   219  	// restore when returning from f.
   220  	MOVW	LR, (m_morebuf+gobuf_pc)(m)	// our caller's PC
   221  	MOVW	SP, (m_morebuf+gobuf_sp)(m)	// our caller's SP
   222  	MOVW	g,  (m_morebuf+gobuf_g)(m)
   223  
   224  	// Set up morestack arguments to call f on a new stack.
   225  	// We set f's frame size to 1, as a hint to newstack
   226  	// that this is a call from reflect·call.
   227  	// If it turns out that f needs a larger frame than
   228  	// the default stack, f's usual stack growth prolog will
   229  	// allocate a new segment (and recopy the arguments).
   230  	MOVW	4(SP), R0			// fn
   231  	MOVW	8(SP), R1			// arg frame
   232  	MOVW	12(SP), R2			// arg size
   233  
   234  	MOVW	R0, m_morepc(m)			// f's PC
   235  	MOVW	R1, m_moreargp(m)		// f's argument pointer
   236  	MOVW	R2, m_moreargsize(m)		// f's argument size
   237  	MOVW	$1, R3
   238  	MOVW	R3, m_moreframesize(m)		// f's frame size
   239  
   240  	// Call newstack on m->g0's stack.
   241  	MOVW	m_g0(m), g
   242  	MOVW	(g_sched+gobuf_sp)(g), SP
   243  	B	runtime·newstack(SB)
   244  
   245  // Return point when leaving stack.
   246  // using frame size $-4 means do not save LR on stack.
   247  TEXT runtime·lessstack(SB), 7, $-4
   248  	// Save return value in m->cret
   249  	MOVW	R0, m_cret(m)
   250  
   251  	// Call oldstack on m->g0's stack.
   252  	MOVW	m_g0(m), g
   253  	MOVW	(g_sched+gobuf_sp)(g), SP
   254  	B	runtime·oldstack(SB)
   255  
   256  // void jmpdefer(fn, sp);
   257  // called from deferreturn.
   258  // 1. grab stored LR for caller
   259  // 2. sub 4 bytes to get back to BL deferreturn
   260  // 3. B to fn
   261  TEXT runtime·jmpdefer(SB), 7, $0
   262  	MOVW	0(SP), LR
   263  	MOVW	$-4(LR), LR	// BL deferreturn
   264  	MOVW	fn+0(FP), R7
   265  	MOVW	argp+4(FP), SP
   266  	MOVW	$-4(SP), SP	// SP is 4 below argp, due to saved LR
   267  	MOVW	0(R7), R1
   268  	B	(R1)
   269  
   270  // Dummy function to use in saved gobuf.PC,
   271  // to match SP pointing at a return address.
   272  // The gobuf.PC is unused by the contortions here
   273  // but setting it to return will make the traceback code work.
   274  TEXT return<>(SB),7,$0
   275  	RET
   276  
   277  // asmcgocall(void(*fn)(void*), void *arg)
   278  // Call fn(arg) on the scheduler stack,
   279  // aligned appropriately for the gcc ABI.
   280  // See cgocall.c for more details.
   281  TEXT	runtime·asmcgocall(SB),7,$0
   282  	MOVW	fn+0(FP), R1
   283  	MOVW	arg+4(FP), R0
   284  	MOVW	R13, R2
   285  	MOVW	g, R5
   286  
   287  	// Figure out if we need to switch to m->g0 stack.
   288  	// We get called to create new OS threads too, and those
   289  	// come in on the m->g0 stack already.
   290  	MOVW	m_g0(m), R3
   291  	CMP	R3, g
   292  	BEQ	7(PC)
   293  	MOVW	R13, (g_sched + gobuf_sp)(g)
   294  	MOVW	$return<>(SB), R4
   295  	MOVW	R4, (g_sched+gobuf_pc)(g)
   296  	MOVW	g, (g_sched+gobuf_g)(g)
   297  	MOVW	R3, g
   298  	MOVW	(g_sched+gobuf_sp)(g), R13
   299  
   300  	// Now on a scheduling stack (a pthread-created stack).
   301  	SUB	$24, R13
   302  	BIC	$0x7, R13	// alignment for gcc ABI
   303  	MOVW	R5, 20(R13) // save old g
   304  	MOVW	R2, 16(R13)	// save old SP
   305  	// R0 already contains the first argument
   306  	BL	(R1)
   307  
   308  	// Restore registers, g, stack pointer.
   309  	MOVW	20(R13), g
   310  	MOVW	16(R13), R13
   311  	RET
   312  
   313  // cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
   314  // Turn the fn into a Go func (by taking its address) and call
   315  // cgocallback_gofunc.
   316  TEXT runtime·cgocallback(SB),7,$12
   317  	MOVW	$fn+0(FP), R0
   318  	MOVW	R0, 4(R13)
   319  	MOVW	frame+4(FP), R0
   320  	MOVW	R0, 8(R13)
   321  	MOVW	framesize+8(FP), R0
   322  	MOVW	R0, 12(R13)
   323  	MOVW	$runtime·cgocallback_gofunc(SB), R0
   324  	BL	(R0)
   325  	RET
   326  
   327  // cgocallback_gofunc(void (*fn)(void*), void *frame, uintptr framesize)
   328  // See cgocall.c for more details.
   329  TEXT	runtime·cgocallback_gofunc(SB),7,$12
   330  	// Load m and g from thread-local storage.
   331  	MOVW	_cgo_load_gm(SB), R0
   332  	CMP	$0, R0
   333  	BL.NE	(R0)
   334  
   335  	// If m is nil, Go did not create the current thread.
   336  	// Call needm to obtain one for temporary use.
   337  	// In this case, we're running on the thread stack, so there's
   338  	// lots of space, but the linker doesn't know. Hide the call from
   339  	// the linker analysis by using an indirect call.
   340  	MOVW	m, savedm-12(SP)
   341  	CMP	$0, m
   342  	B.NE havem
   343  	MOVW	$runtime·needm(SB), R0
   344  	BL	(R0)
   345  
   346  havem:
   347  	// Now there's a valid m, and we're running on its m->g0.
   348  	// Save current m->g0->sched.sp on stack and then set it to SP.
   349  	// Save current sp in m->g0->sched.sp in preparation for
   350  	// switch back to m->curg stack.
   351  	MOVW	m_g0(m), R3
   352  	MOVW	(g_sched+gobuf_sp)(R3), R4
   353  	MOVW.W	R4, -4(R13)
   354  	MOVW	R13, (g_sched+gobuf_sp)(R3)
   355  
   356  	// Switch to m->curg stack and call runtime.cgocallbackg
   357  	// with the three arguments.  Because we are taking over
   358  	// the execution of m->curg but *not* resuming what had
   359  	// been running, we need to save that information (m->curg->gobuf)
   360  	// so that we can restore it when we're done. 
   361  	// We can restore m->curg->gobuf.sp easily, because calling
   362  	// runtime.cgocallbackg leaves SP unchanged upon return.
   363  	// To save m->curg->gobuf.pc, we push it onto the stack.
   364  	// This has the added benefit that it looks to the traceback
   365  	// routine like cgocallbackg is going to return to that
   366  	// PC (because we defined cgocallbackg to have
   367  	// a frame size of 12, the same amount that we use below),
   368  	// so that the traceback will seamlessly trace back into
   369  	// the earlier calls.
   370  	MOVW	fn+4(FP), R0
   371  	MOVW	frame+8(FP), R1
   372  	MOVW	framesize+12(FP), R2
   373  
   374  	MOVW	m_curg(m), g
   375  	MOVW	(g_sched+gobuf_sp)(g), R4 // prepare stack as R4
   376  
   377  	// Push gobuf.pc
   378  	MOVW	(g_sched+gobuf_pc)(g), R5
   379  	MOVW.W	R5, -16(R4)
   380  
   381  	// Push arguments to cgocallbackg.
   382  	// Frame size here must match the frame size above
   383  	// to trick traceback routines into doing the right thing.
   384  	MOVW	R0, 4(R4)
   385  	MOVW	R1, 8(R4)
   386  	MOVW	R2, 12(R4)
   387  	
   388  	// Switch stack and make the call.
   389  	MOVW	R4, R13
   390  	BL	runtime·cgocallbackg(SB)
   391  
   392  	// Restore g->gobuf (== m->curg->gobuf) from saved values.
   393  	MOVW	0(R13), R5
   394  	MOVW	R5, (g_sched+gobuf_pc)(g)
   395  	ADD	$(12+4), R13, R4
   396  	MOVW	R4, (g_sched+gobuf_sp)(g)
   397  
   398  	// Switch back to m->g0's stack and restore m->g0->sched.sp.
   399  	// (Unlike m->curg, the g0 goroutine never uses sched.pc,
   400  	// so we do not have to restore it.)
   401  	MOVW	m_g0(m), g
   402  	MOVW	(g_sched+gobuf_sp)(g), R13
   403  	// POP R6
   404  	MOVW	0(R13), R6
   405  	ADD	$4, R13
   406  	MOVW	R6, (g_sched+gobuf_sp)(g)
   407  
   408  	// If the m on entry was nil, we called needm above to borrow an m
   409  	// for the duration of the call. Since the call is over, return it with dropm.
   410  	MOVW	savedm-12(SP), R6
   411  	CMP	$0, R6
   412  	B.NE	3(PC)
   413  	MOVW	$runtime·dropm(SB), R0
   414  	BL	(R0)
   415  
   416  	// Done!
   417  	RET
   418  
   419  // void setmg(M*, G*); set m and g. for use by needm.
   420  TEXT runtime·setmg(SB), 7, $0
   421  	MOVW	mm+0(FP), m
   422  	MOVW	gg+4(FP), g
   423  
   424  	// Save m and g to thread-local storage.
   425  	MOVW	_cgo_save_gm(SB), R0
   426  	CMP	$0, R0
   427  	BL.NE	(R0)
   428  
   429  	RET
   430  
   431  TEXT runtime·getcallerpc(SB),7,$-4
   432  	MOVW	0(SP), R0
   433  	RET
   434  
   435  TEXT runtime·setcallerpc(SB),7,$-4
   436  	MOVW	x+4(FP), R0
   437  	MOVW	R0, 0(SP)
   438  	RET
   439  
   440  TEXT runtime·getcallersp(SB),7,$-4
   441  	MOVW	0(FP), R0
   442  	MOVW	$-4(R0), R0
   443  	RET
   444  
   445  TEXT runtime·emptyfunc(SB),0,$0
   446  	RET
   447  
   448  TEXT runtime·abort(SB),7,$-4
   449  	MOVW	$0, R0
   450  	MOVW	(R0), R1
   451  
   452  // bool armcas(int32 *val, int32 old, int32 new)
   453  // Atomically:
   454  //	if(*val == old){
   455  //		*val = new;
   456  //		return 1;
   457  //	}else
   458  //		return 0;
   459  //
   460  // To implement runtime·cas in sys_$GOOS_arm.s
   461  // using the native instructions, use:
   462  //
   463  //	TEXT runtime·cas(SB),7,$0
   464  //		B	runtime·armcas(SB)
   465  //
   466  TEXT runtime·armcas(SB),7,$0
   467  	MOVW	valptr+0(FP), R1
   468  	MOVW	old+4(FP), R2
   469  	MOVW	new+8(FP), R3
   470  casl:
   471  	LDREX	(R1), R0
   472  	CMP		R0, R2
   473  	BNE		casfail
   474  	STREX	R3, (R1), R0
   475  	CMP		$0, R0
   476  	BNE		casl
   477  	MOVW	$1, R0
   478  	RET
   479  casfail:
   480  	MOVW	$0, R0
   481  	RET
   482  
   483  TEXT runtime·stackguard(SB),7,$0
   484  	MOVW	R13, R1
   485  	MOVW	g_stackguard(g), R2
   486  	MOVW	R1, sp+0(FP)
   487  	MOVW	R2, limit+4(FP)
   488  	RET
   489  
   490  // AES hashing not implemented for ARM
   491  TEXT runtime·aeshash(SB),7,$-4
   492  	MOVW	$0, R0
   493  	MOVW	(R0), R1
   494  TEXT runtime·aeshash32(SB),7,$-4
   495  	MOVW	$0, R0
   496  	MOVW	(R0), R1
   497  TEXT runtime·aeshash64(SB),7,$-4
   498  	MOVW	$0, R0
   499  	MOVW	(R0), R1
   500  TEXT runtime·aeshashstr(SB),7,$-4
   501  	MOVW	$0, R0
   502  	MOVW	(R0), R1
   503  
   504  TEXT runtime·memeq(SB),7,$-4
   505  	MOVW	a+0(FP), R1
   506  	MOVW	b+4(FP), R2
   507  	MOVW	n+8(FP), R3
   508  	ADD	R1, R3, R6
   509  	MOVW	$1, R0
   510  _next:
   511  	CMP	R1, R6
   512  	RET.EQ
   513  	MOVBU.P	1(R1), R4
   514  	MOVBU.P	1(R2), R5
   515  	CMP	R4, R5
   516  	BEQ	_next
   517  
   518  	MOVW	$0, R0
   519  	RET