...
Run Format

Text file src/runtime/asm_s390x.s

Documentation: runtime

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

View as plain text