...

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.
    16TEXT _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
    50nocgo:
    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
    58restore:
    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.
    76TEXT _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
    82DATA _rt0_s390x_lib_argc<>(SB)/8, $0
    83GLOBL _rt0_s390x_lib_argc<>(SB), NOPTR, $8
    84DATA _rt0_s90x_lib_argv<>(SB)/8, $0
    85GLOBL _rt0_s390x_lib_argv<>(SB), NOPTR, $8
    86
    87TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$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
   126nocgo:
   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·checkS390xCPU(SB)
   146	BL	runtime·osinit(SB)
   147	BL	runtime·schedinit(SB)
   148
   149	// create a new goroutine to start program
   150	MOVD	$runtime·mainPC(SB), R2		// entry
   151	SUB     $16, R15
   152	MOVD 	R2, 8(R15)
   153	MOVD 	$0, 0(R15)
   154	BL	runtime·newproc(SB)
   155	ADD	$16, R15
   156
   157	// start this M
   158	BL	runtime·mstart(SB)
   159
   160	MOVD	$0, 1(R0)
   161	RET
   162
   163DATA	runtime·mainPC+0(SB)/8,$runtime·main(SB)
   164GLOBL	runtime·mainPC(SB),RODATA,$8
   165
   166TEXT runtime·breakpoint(SB),NOSPLIT|NOFRAME,$0-0
   167	BRRK
   168	RET
   169
   170TEXT runtime·asminit(SB),NOSPLIT|NOFRAME,$0-0
   171	RET
   172
   173TEXT runtime·mstart(SB),NOSPLIT|TOPFRAME,$0
   174	CALL	runtime·mstart0(SB)
   175	RET // not reached
   176
   177/*
   178 *  go-routine
   179 */
   180
   181// void gogo(Gobuf*)
   182// restore state from Gobuf; longjmp
   183TEXT runtime·gogo(SB), NOSPLIT|NOFRAME, $0-8
   184	MOVD	buf+0(FP), R5
   185	MOVD	gobuf_g(R5), R6
   186	MOVD	0(R6), R7	// make sure g != nil
   187	BR	gogo<>(SB)
   188
   189TEXT gogo<>(SB), NOSPLIT|NOFRAME, $0
   190	MOVD	R6, g
   191	BL	runtime·save_g(SB)
   192
   193	MOVD	0(g), R4
   194	MOVD	gobuf_sp(R5), R15
   195	MOVD	gobuf_lr(R5), LR
   196	MOVD	gobuf_ret(R5), R3
   197	MOVD	gobuf_ctxt(R5), R12
   198	MOVD	$0, gobuf_sp(R5)
   199	MOVD	$0, gobuf_ret(R5)
   200	MOVD	$0, gobuf_lr(R5)
   201	MOVD	$0, gobuf_ctxt(R5)
   202	CMP	R0, R0 // set condition codes for == test, needed by stack split
   203	MOVD	gobuf_pc(R5), R6
   204	BR	(R6)
   205
   206// void mcall(fn func(*g))
   207// Switch to m->g0's stack, call fn(g).
   208// Fn must never return.  It should gogo(&g->sched)
   209// to keep running g.
   210TEXT runtime·mcall(SB), NOSPLIT, $-8-8
   211	// Save caller state in g->sched
   212	MOVD	R15, (g_sched+gobuf_sp)(g)
   213	MOVD	LR, (g_sched+gobuf_pc)(g)
   214	MOVD	$0, (g_sched+gobuf_lr)(g)
   215
   216	// Switch to m->g0 & its stack, call fn.
   217	MOVD	g, R3
   218	MOVD	g_m(g), R8
   219	MOVD	m_g0(R8), g
   220	BL	runtime·save_g(SB)
   221	CMP	g, R3
   222	BNE	2(PC)
   223	BR	runtime·badmcall(SB)
   224	MOVD	fn+0(FP), R12			// context
   225	MOVD	0(R12), R4			// code pointer
   226	MOVD	(g_sched+gobuf_sp)(g), R15	// sp = m->g0->sched.sp
   227	SUB	$16, R15
   228	MOVD	R3, 8(R15)
   229	MOVD	$0, 0(R15)
   230	BL	(R4)
   231	BR	runtime·badmcall2(SB)
   232
   233// systemstack_switch is a dummy routine that systemstack leaves at the bottom
   234// of the G stack.  We need to distinguish the routine that
   235// lives at the bottom of the G stack from the one that lives
   236// at the top of the system stack because the one at the top of
   237// the system stack terminates the stack walk (see topofstack()).
   238TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
   239	UNDEF
   240	BL	(LR)	// make sure this function is not leaf
   241	RET
   242
   243// func systemstack(fn func())
   244TEXT runtime·systemstack(SB), NOSPLIT, $0-8
   245	MOVD	fn+0(FP), R3	// R3 = fn
   246	MOVD	R3, R12		// context
   247	MOVD	g_m(g), R4	// R4 = m
   248
   249	MOVD	m_gsignal(R4), R5	// R5 = gsignal
   250	CMPBEQ	g, R5, noswitch
   251
   252	MOVD	m_g0(R4), R5	// R5 = g0
   253	CMPBEQ	g, R5, noswitch
   254
   255	MOVD	m_curg(R4), R6
   256	CMPBEQ	g, R6, switch
   257
   258	// Bad: g is not gsignal, not g0, not curg. What is it?
   259	// Hide call from linker nosplit analysis.
   260	MOVD	$runtime·badsystemstack(SB), R3
   261	BL	(R3)
   262	BL	runtime·abort(SB)
   263
   264switch:
   265	// save our state in g->sched.  Pretend to
   266	// be systemstack_switch if the G stack is scanned.
   267	BL	gosave_systemstack_switch<>(SB)
   268
   269	// switch to g0
   270	MOVD	R5, g
   271	BL	runtime·save_g(SB)
   272	MOVD	(g_sched+gobuf_sp)(g), R15
   273
   274	// call target function
   275	MOVD	0(R12), R3	// code pointer
   276	BL	(R3)
   277
   278	// switch back to g
   279	MOVD	g_m(g), R3
   280	MOVD	m_curg(R3), g
   281	BL	runtime·save_g(SB)
   282	MOVD	(g_sched+gobuf_sp)(g), R15
   283	MOVD	$0, (g_sched+gobuf_sp)(g)
   284	RET
   285
   286noswitch:
   287	// already on m stack, just call directly
   288	// Using a tail call here cleans up tracebacks since we won't stop
   289	// at an intermediate systemstack.
   290	MOVD	0(R12), R3	// code pointer
   291	MOVD	0(R15), LR	// restore LR
   292	ADD	$8, R15
   293	BR	(R3)
   294
   295// func switchToCrashStack0(fn func())
   296TEXT runtime·switchToCrashStack0<ABIInternal>(SB), NOSPLIT, $0-8
   297	MOVD	fn+0(FP), R12	// context
   298	MOVD	g_m(g), R4	// curm
   299
   300	// set g to gcrash
   301	MOVD	$runtime·gcrash(SB), g	// g = &gcrash
   302	BL	runtime·save_g(SB)
   303	MOVD	R4, g_m(g)	// g.m = curm
   304	MOVD	g, m_g0(R4)	// curm.g0 = g
   305
   306	// switch to crashstack
   307	MOVD	(g_stack+stack_hi)(g), R4
   308	ADD	$(-4*8), R4, R15
   309
   310	// call target function
   311	MOVD	0(R12), R3	// code pointer
   312	BL	(R3)
   313
   314	// should never return
   315	BL	runtime·abort(SB)
   316	UNDEF
   317
   318/*
   319 * support for morestack
   320 */
   321
   322// Called during function prolog when more stack is needed.
   323// Caller has already loaded:
   324// R3: framesize, R4: argsize, R5: LR
   325//
   326// The traceback routines see morestack on a g0 as being
   327// the top of a stack (for example, morestack calling newstack
   328// calling the scheduler calling newm calling gc), so we must
   329// record an argument size. For that purpose, it has no arguments.
   330TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
   331	// Called from f.
   332	// Set g->sched to context in f.
   333	MOVD	R15, (g_sched+gobuf_sp)(g)
   334	MOVD	LR, R8
   335	MOVD	R8, (g_sched+gobuf_pc)(g)
   336	MOVD	R5, (g_sched+gobuf_lr)(g)
   337	MOVD	R12, (g_sched+gobuf_ctxt)(g)
   338
   339	// Cannot grow scheduler stack (m->g0).
   340	MOVD	g_m(g), R7
   341	MOVD	m_g0(R7), R8
   342	CMPBNE	g, R8, 3(PC)
   343	BL	runtime·badmorestackg0(SB)
   344	BL	runtime·abort(SB)
   345
   346	// Cannot grow signal stack (m->gsignal).
   347	MOVD	m_gsignal(R7), R8
   348	CMP	g, R8
   349	BNE	3(PC)
   350	BL	runtime·badmorestackgsignal(SB)
   351	BL	runtime·abort(SB)
   352
   353	// Called from f.
   354	// Set m->morebuf to f's caller.
   355	MOVD	R5, (m_morebuf+gobuf_pc)(R7)	// f's caller's PC
   356	MOVD	R15, (m_morebuf+gobuf_sp)(R7)	// f's caller's SP
   357	MOVD	g, (m_morebuf+gobuf_g)(R7)
   358
   359	// Call newstack on m->g0's stack.
   360	MOVD	m_g0(R7), g
   361	BL	runtime·save_g(SB)
   362	MOVD	(g_sched+gobuf_sp)(g), R15
   363	// Create a stack frame on g0 to call newstack.
   364	MOVD	$0, -8(R15)	// Zero saved LR in frame
   365	SUB	$8, R15
   366	BL	runtime·newstack(SB)
   367
   368	// Not reached, but make sure the return PC from the call to newstack
   369	// is still in this function, and not the beginning of the next.
   370	UNDEF
   371
   372TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0
   373	// Force SPWRITE. This function doesn't actually write SP,
   374	// but it is called with a special calling convention where
   375	// the caller doesn't save LR on stack but passes it as a
   376	// register (R5), and the unwinder currently doesn't understand.
   377	// Make it SPWRITE to stop unwinding. (See issue 54332)
   378	MOVD	R15, R15
   379
   380	MOVD	$0, R12
   381	BR	runtime·morestack(SB)
   382
   383// reflectcall: call a function with the given argument list
   384// func call(stackArgsType *_type, f *FuncVal, stackArgs *byte, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs).
   385// we don't have variable-sized frames, so we use a small number
   386// of constant-sized-frame functions to encode a few bits of size in the pc.
   387// Caution: ugly multiline assembly macros in your future!
   388
   389#define DISPATCH(NAME,MAXSIZE)		\
   390	MOVD	$MAXSIZE, R4;		\
   391	CMP	R3, R4;		\
   392	BGT	3(PC);			\
   393	MOVD	$NAME(SB), R5;	\
   394	BR	(R5)
   395// Note: can't just "BR NAME(SB)" - bad inlining results.
   396
   397TEXT ·reflectcall(SB), NOSPLIT, $-8-48
   398	MOVWZ	frameSize+32(FP), R3
   399	DISPATCH(runtime·call16, 16)
   400	DISPATCH(runtime·call32, 32)
   401	DISPATCH(runtime·call64, 64)
   402	DISPATCH(runtime·call128, 128)
   403	DISPATCH(runtime·call256, 256)
   404	DISPATCH(runtime·call512, 512)
   405	DISPATCH(runtime·call1024, 1024)
   406	DISPATCH(runtime·call2048, 2048)
   407	DISPATCH(runtime·call4096, 4096)
   408	DISPATCH(runtime·call8192, 8192)
   409	DISPATCH(runtime·call16384, 16384)
   410	DISPATCH(runtime·call32768, 32768)
   411	DISPATCH(runtime·call65536, 65536)
   412	DISPATCH(runtime·call131072, 131072)
   413	DISPATCH(runtime·call262144, 262144)
   414	DISPATCH(runtime·call524288, 524288)
   415	DISPATCH(runtime·call1048576, 1048576)
   416	DISPATCH(runtime·call2097152, 2097152)
   417	DISPATCH(runtime·call4194304, 4194304)
   418	DISPATCH(runtime·call8388608, 8388608)
   419	DISPATCH(runtime·call16777216, 16777216)
   420	DISPATCH(runtime·call33554432, 33554432)
   421	DISPATCH(runtime·call67108864, 67108864)
   422	DISPATCH(runtime·call134217728, 134217728)
   423	DISPATCH(runtime·call268435456, 268435456)
   424	DISPATCH(runtime·call536870912, 536870912)
   425	DISPATCH(runtime·call1073741824, 1073741824)
   426	MOVD	$runtime·badreflectcall(SB), R5
   427	BR	(R5)
   428
   429#define CALLFN(NAME,MAXSIZE)			\
   430TEXT NAME(SB), WRAPPER, $MAXSIZE-48;		\
   431	NO_LOCAL_POINTERS;			\
   432	/* copy arguments to stack */		\
   433	MOVD	stackArgs+16(FP), R4;			\
   434	MOVWZ	stackArgsSize+24(FP), R5;		\
   435	MOVD	$stack-MAXSIZE(SP), R6;		\
   436loopArgs: /* copy 256 bytes at a time */	\
   437	CMP	R5, $256;			\
   438	BLT	tailArgs;			\
   439	SUB	$256, R5;			\
   440	MVC	$256, 0(R4), 0(R6);		\
   441	MOVD	$256(R4), R4;			\
   442	MOVD	$256(R6), R6;			\
   443	BR	loopArgs;			\
   444tailArgs: /* copy remaining bytes */		\
   445	CMP	R5, $0;				\
   446	BEQ	callFunction;			\
   447	SUB	$1, R5;				\
   448	EXRL	$callfnMVC<>(SB), R5;		\
   449callFunction:					\
   450	MOVD	f+8(FP), R12;			\
   451	MOVD	(R12), R8;			\
   452	PCDATA  $PCDATA_StackMapIndex, $0;	\
   453	BL	(R8);				\
   454	/* copy return values back */		\
   455	MOVD	stackArgsType+0(FP), R7;		\
   456	MOVD	stackArgs+16(FP), R6;			\
   457	MOVWZ	stackArgsSize+24(FP), R5;			\
   458	MOVD	$stack-MAXSIZE(SP), R4;		\
   459	MOVWZ	stackRetOffset+28(FP), R1;		\
   460	ADD	R1, R4;				\
   461	ADD	R1, R6;				\
   462	SUB	R1, R5;				\
   463	BL	callRet<>(SB);			\
   464	RET
   465
   466// callRet copies return values back at the end of call*. This is a
   467// separate function so it can allocate stack space for the arguments
   468// to reflectcallmove. It does not follow the Go ABI; it expects its
   469// arguments in registers.
   470TEXT callRet<>(SB), NOSPLIT, $40-0
   471	MOVD	R7, 8(R15)
   472	MOVD	R6, 16(R15)
   473	MOVD	R4, 24(R15)
   474	MOVD	R5, 32(R15)
   475	MOVD	$0, 40(R15)
   476	BL	runtime·reflectcallmove(SB)
   477	RET
   478
   479CALLFN(·call16, 16)
   480CALLFN(·call32, 32)
   481CALLFN(·call64, 64)
   482CALLFN(·call128, 128)
   483CALLFN(·call256, 256)
   484CALLFN(·call512, 512)
   485CALLFN(·call1024, 1024)
   486CALLFN(·call2048, 2048)
   487CALLFN(·call4096, 4096)
   488CALLFN(·call8192, 8192)
   489CALLFN(·call16384, 16384)
   490CALLFN(·call32768, 32768)
   491CALLFN(·call65536, 65536)
   492CALLFN(·call131072, 131072)
   493CALLFN(·call262144, 262144)
   494CALLFN(·call524288, 524288)
   495CALLFN(·call1048576, 1048576)
   496CALLFN(·call2097152, 2097152)
   497CALLFN(·call4194304, 4194304)
   498CALLFN(·call8388608, 8388608)
   499CALLFN(·call16777216, 16777216)
   500CALLFN(·call33554432, 33554432)
   501CALLFN(·call67108864, 67108864)
   502CALLFN(·call134217728, 134217728)
   503CALLFN(·call268435456, 268435456)
   504CALLFN(·call536870912, 536870912)
   505CALLFN(·call1073741824, 1073741824)
   506
   507// Not a function: target for EXRL (execute relative long) instruction.
   508TEXT callfnMVC<>(SB),NOSPLIT|NOFRAME,$0-0
   509	MVC	$1, 0(R4), 0(R6)
   510
   511TEXT runtime·procyield(SB),NOSPLIT,$0-0
   512	RET
   513
   514// Save state of caller into g->sched,
   515// but using fake PC from systemstack_switch.
   516// Must only be called from functions with no locals ($0)
   517// or else unwinding from systemstack_switch is incorrect.
   518// Smashes R1.
   519TEXT gosave_systemstack_switch<>(SB),NOSPLIT|NOFRAME,$0
   520	MOVD	$runtime·systemstack_switch(SB), R1
   521	ADD	$16, R1	// get past prologue
   522	MOVD	R1, (g_sched+gobuf_pc)(g)
   523	MOVD	R15, (g_sched+gobuf_sp)(g)
   524	MOVD	$0, (g_sched+gobuf_lr)(g)
   525	MOVD	$0, (g_sched+gobuf_ret)(g)
   526	// Assert ctxt is zero. See func save.
   527	MOVD	(g_sched+gobuf_ctxt)(g), R1
   528	CMPBEQ	R1, $0, 2(PC)
   529	BL	runtime·abort(SB)
   530	RET
   531
   532// func asmcgocall(fn, arg unsafe.Pointer) int32
   533// Call fn(arg) on the scheduler stack,
   534// aligned appropriately for the gcc ABI.
   535// See cgocall.go for more details.
   536TEXT ·asmcgocall(SB),NOSPLIT,$0-20
   537	// R2 = argc; R3 = argv; R11 = temp; R13 = g; R15 = stack pointer
   538	// C TLS base pointer in AR0:AR1
   539	MOVD	fn+0(FP), R3
   540	MOVD	arg+8(FP), R4
   541
   542	MOVD	R15, R2		// save original stack pointer
   543	MOVD	g, R5
   544
   545	// Figure out if we need to switch to m->g0 stack.
   546	// We get called to create new OS threads too, and those
   547	// come in on the m->g0 stack already. Or we might already
   548	// be on the m->gsignal stack.
   549	MOVD	g_m(g), R6
   550	MOVD	m_gsignal(R6), R7
   551	CMPBEQ	R7, g, g0
   552	MOVD	m_g0(R6), R7
   553	CMPBEQ	R7, g, g0
   554	BL	gosave_systemstack_switch<>(SB)
   555	MOVD	R7, g
   556	BL	runtime·save_g(SB)
   557	MOVD	(g_sched+gobuf_sp)(g), R15
   558
   559	// Now on a scheduling stack (a pthread-created stack).
   560g0:
   561	// Save room for two of our pointers, plus 160 bytes of callee
   562	// save area that lives on the caller stack.
   563	SUB	$176, R15
   564	MOVD	$~7, R6
   565	AND	R6, R15                 // 8-byte alignment for gcc ABI
   566	MOVD	R5, 168(R15)             // save old g on stack
   567	MOVD	(g_stack+stack_hi)(R5), R5
   568	SUB	R2, R5
   569	MOVD	R5, 160(R15)             // save depth in old g stack (can't just save SP, as stack might be copied during a callback)
   570	MOVD	$0, 0(R15)              // clear back chain pointer (TODO can we give it real back trace information?)
   571	MOVD	R4, R2                  // arg in R2
   572	BL	R3                      // can clobber: R0-R5, R14, F0-F3, F5, F7-F15
   573
   574	XOR	R0, R0                  // set R0 back to 0.
   575	// Restore g, stack pointer.
   576	MOVD	168(R15), g
   577	BL	runtime·save_g(SB)
   578	MOVD	(g_stack+stack_hi)(g), R5
   579	MOVD	160(R15), R6
   580	SUB	R6, R5
   581	MOVD	R5, R15
   582
   583	MOVW	R2, ret+16(FP)
   584	RET
   585
   586// cgocallback(fn, frame unsafe.Pointer, ctxt uintptr)
   587// See cgocall.go for more details.
   588TEXT ·cgocallback(SB),NOSPLIT,$24-24
   589	NO_LOCAL_POINTERS
   590
   591	// Skip cgocallbackg, just dropm when fn is nil, and frame is the saved g.
   592	// It is used to dropm while thread is exiting.
   593	MOVD	fn+0(FP), R1
   594	CMPBNE	R1, $0, loadg
   595	// Restore the g from frame.
   596	MOVD	frame+8(FP), g
   597	BR	dropm
   598
   599loadg:
   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
   605nocgo:
   606	// If g is nil, Go did not create the current thread,
   607	// or if this thread never called into Go on pthread platforms.
   608	// Call needm to obtain one for temporary use.
   609	// In this case, we're running on the thread stack, so there's
   610	// lots of space, but the linker doesn't know. Hide the call from
   611	// the linker analysis by using an indirect call.
   612	CMPBEQ	g, $0, needm
   613
   614	MOVD	g_m(g), R8
   615	MOVD	R8, savedm-8(SP)
   616	BR	havem
   617
   618needm:
   619	MOVD	g, savedm-8(SP) // g is zero, so is m.
   620	MOVD	$runtime·needAndBindM(SB), R3
   621	BL	(R3)
   622
   623	// Set m->sched.sp = SP, so that if a panic happens
   624	// during the function we are about to execute, it will
   625	// have a valid SP to run on the g0 stack.
   626	// The next few lines (after the havem label)
   627	// will save this SP onto the stack and then write
   628	// the same SP back to m->sched.sp. That seems redundant,
   629	// but if an unrecovered panic happens, unwindm will
   630	// restore the g->sched.sp from the stack location
   631	// and then systemstack will try to use it. If we don't set it here,
   632	// that restored SP will be uninitialized (typically 0) and
   633	// will not be usable.
   634	MOVD	g_m(g), R8
   635	MOVD	m_g0(R8), R3
   636	MOVD	R15, (g_sched+gobuf_sp)(R3)
   637
   638havem:
   639	// Now there's a valid m, and we're running on its m->g0.
   640	// Save current m->g0->sched.sp on stack and then set it to SP.
   641	// Save current sp in m->g0->sched.sp in preparation for
   642	// switch back to m->curg stack.
   643	// NOTE: unwindm knows that the saved g->sched.sp is at 8(R1) aka savedsp-16(SP).
   644	MOVD	m_g0(R8), R3
   645	MOVD	(g_sched+gobuf_sp)(R3), R4
   646	MOVD	R4, savedsp-24(SP)	// must match frame size
   647	MOVD	R15, (g_sched+gobuf_sp)(R3)
   648
   649	// Switch to m->curg stack and call runtime.cgocallbackg.
   650	// Because we are taking over the execution of m->curg
   651	// but *not* resuming what had been running, we need to
   652	// save that information (m->curg->sched) so we can restore it.
   653	// We can restore m->curg->sched.sp easily, because calling
   654	// runtime.cgocallbackg leaves SP unchanged upon return.
   655	// To save m->curg->sched.pc, we push it onto the curg stack and
   656	// open a frame the same size as cgocallback's g0 frame.
   657	// Once we switch to the curg stack, the pushed PC will appear
   658	// to be the return PC of cgocallback, so that the traceback
   659	// will seamlessly trace back into the earlier calls.
   660	MOVD	m_curg(R8), g
   661	BL	runtime·save_g(SB)
   662	MOVD	(g_sched+gobuf_sp)(g), R4 // prepare stack as R4
   663	MOVD	(g_sched+gobuf_pc)(g), R5
   664	MOVD	R5, -(24+8)(R4)	// "saved LR"; must match frame size
   665	// Gather our arguments into registers.
   666	MOVD	fn+0(FP), R1
   667	MOVD	frame+8(FP), R2
   668	MOVD	ctxt+16(FP), R3
   669	MOVD	$-(24+8)(R4), R15	// switch stack; must match frame size
   670	MOVD	R1, 8(R15)
   671	MOVD	R2, 16(R15)
   672	MOVD	R3, 24(R15)
   673	BL	runtime·cgocallbackg(SB)
   674
   675	// Restore g->sched (== m->curg->sched) from saved values.
   676	MOVD	0(R15), R5
   677	MOVD	R5, (g_sched+gobuf_pc)(g)
   678	MOVD	$(24+8)(R15), R4	// must match frame size
   679	MOVD	R4, (g_sched+gobuf_sp)(g)
   680
   681	// Switch back to m->g0's stack and restore m->g0->sched.sp.
   682	// (Unlike m->curg, the g0 goroutine never uses sched.pc,
   683	// so we do not have to restore it.)
   684	MOVD	g_m(g), R8
   685	MOVD	m_g0(R8), g
   686	BL	runtime·save_g(SB)
   687	MOVD	(g_sched+gobuf_sp)(g), R15
   688	MOVD	savedsp-24(SP), R4	// must match frame size
   689	MOVD	R4, (g_sched+gobuf_sp)(g)
   690
   691	// If the m on entry was nil, we called needm above to borrow an m,
   692	// 1. for the duration of the call on non-pthread platforms,
   693	// 2. or the duration of the C thread alive on pthread platforms.
   694	// If the m on entry wasn't nil,
   695	// 1. the thread might be a Go thread,
   696	// 2. or it wasn't the first call from a C thread on pthread platforms,
   697	//    since then we skip dropm to reuse the m in the first call.
   698	MOVD	savedm-8(SP), R6
   699	CMPBNE	R6, $0, droppedm
   700
   701	// Skip dropm to reuse it in the next call, when a pthread key has been created.
   702	MOVD	_cgo_pthread_key_created(SB), R6
   703	// It means cgo is disabled when _cgo_pthread_key_created is a nil pointer, need dropm.
   704	CMPBEQ	R6, $0, dropm
   705	MOVD	(R6), R6
   706	CMPBNE	R6, $0, droppedm
   707
   708dropm:
   709	MOVD	$runtime·dropm(SB), R3
   710	BL	(R3)
   711droppedm:
   712
   713	// Done!
   714	RET
   715
   716// void setg(G*); set g. for use by needm.
   717TEXT runtime·setg(SB), NOSPLIT, $0-8
   718	MOVD	gg+0(FP), g
   719	// This only happens if iscgo, so jump straight to save_g
   720	BL	runtime·save_g(SB)
   721	RET
   722
   723// void setg_gcc(G*); set g in C TLS.
   724// Must obey the gcc calling convention.
   725TEXT setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0
   726	// The standard prologue clobbers LR (R14), which is callee-save in
   727	// the C ABI, so we have to use NOFRAME and save LR ourselves.
   728	MOVD	LR, R1
   729	// Also save g, R10, and R11 since they're callee-save in C ABI
   730	MOVD	R10, R3
   731	MOVD	g, R4
   732	MOVD	R11, R5
   733
   734	MOVD	R2, g
   735	BL	runtime·save_g(SB)
   736
   737	MOVD	R5, R11
   738	MOVD	R4, g
   739	MOVD	R3, R10
   740	MOVD	R1, LR
   741	RET
   742
   743TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0
   744	MOVW	(R0), R0
   745	UNDEF
   746
   747// int64 runtime·cputicks(void)
   748TEXT runtime·cputicks(SB),NOSPLIT,$0-8
   749	// The TOD clock on s390 counts from the year 1900 in ~250ps intervals.
   750	// This means that since about 1972 the msb has been set, making the
   751	// result of a call to STORE CLOCK (stck) a negative number.
   752	// We clear the msb to make it positive.
   753	STCK	ret+0(FP)      // serialises before and after call
   754	MOVD	ret+0(FP), R3  // R3 will wrap to 0 in the year 2043
   755	SLD	$1, R3
   756	SRD	$1, R3
   757	MOVD	R3, ret+0(FP)
   758	RET
   759
   760// AES hashing not implemented for s390x
   761TEXT runtime·memhash(SB),NOSPLIT|NOFRAME,$0-32
   762	JMP	runtime·memhashFallback(SB)
   763TEXT runtime·strhash(SB),NOSPLIT|NOFRAME,$0-24
   764	JMP	runtime·strhashFallback(SB)
   765TEXT runtime·memhash32(SB),NOSPLIT|NOFRAME,$0-24
   766	JMP	runtime·memhash32Fallback(SB)
   767TEXT runtime·memhash64(SB),NOSPLIT|NOFRAME,$0-24
   768	JMP	runtime·memhash64Fallback(SB)
   769
   770TEXT runtime·return0(SB), NOSPLIT, $0
   771	MOVW	$0, R3
   772	RET
   773
   774// Called from cgo wrappers, this function returns g->m->curg.stack.hi.
   775// Must obey the gcc calling convention.
   776TEXT _cgo_topofstack(SB),NOSPLIT|NOFRAME,$0
   777	// g (R13), R10, R11 and LR (R14) are callee-save in the C ABI, so save them
   778	MOVD	g, R1
   779	MOVD	R10, R3
   780	MOVD	LR, R4
   781	MOVD	R11, R5
   782
   783	BL	runtime·load_g(SB)	// clobbers g (R13), R10, R11
   784	MOVD	g_m(g), R2
   785	MOVD	m_curg(R2), R2
   786	MOVD	(g_stack+stack_hi)(R2), R2
   787
   788	MOVD	R1, g
   789	MOVD	R3, R10
   790	MOVD	R4, LR
   791	MOVD	R5, R11
   792	RET
   793
   794// The top-most function running on a goroutine
   795// returns to goexit+PCQuantum.
   796TEXT runtime·goexit(SB),NOSPLIT|NOFRAME|TOPFRAME,$0-0
   797	BYTE $0x07; BYTE $0x00; // 2-byte nop
   798	BL	runtime·goexit1(SB)	// does not return
   799	// traceback from goexit1 must hit code range of goexit
   800	BYTE $0x07; BYTE $0x00; // 2-byte nop
   801
   802TEXT ·publicationBarrier(SB),NOSPLIT|NOFRAME,$0-0
   803	// Stores are already ordered on s390x, so this is just a
   804	// compile barrier.
   805	RET
   806
   807// This is called from .init_array and follows the platform, not Go, ABI.
   808// We are overly conservative. We could only save the registers we use.
   809// However, since this function is only called once per loaded module
   810// performance is unimportant.
   811TEXT runtime·addmoduledata(SB),NOSPLIT|NOFRAME,$0-0
   812	// Save R6-R15 in the register save area of the calling function.
   813	// Don't bother saving F8-F15 as we aren't doing any calls.
   814	STMG	R6, R15, 48(R15)
   815
   816	// append the argument (passed in R2, as per the ELF ABI) to the
   817	// moduledata linked list.
   818	MOVD	runtime·lastmoduledatap(SB), R1
   819	MOVD	R2, moduledata_next(R1)
   820	MOVD	R2, runtime·lastmoduledatap(SB)
   821
   822	// Restore R6-R15.
   823	LMG	48(R15), R6, R15
   824	RET
   825
   826TEXT ·checkASM(SB),NOSPLIT,$0-1
   827	MOVB	$1, ret+0(FP)
   828	RET
   829
   830// gcWriteBarrier informs the GC about heap pointer writes.
   831//
   832// gcWriteBarrier does NOT follow the Go ABI. It accepts the
   833// number of bytes of buffer needed in R9, and returns a pointer
   834// to the buffer space in R9.
   835// It clobbers R10 (the temp register) and R1 (used by PLT stub).
   836// It does not clobber any other general-purpose registers,
   837// but may clobber others (e.g., floating point registers).
   838TEXT gcWriteBarrier<>(SB),NOSPLIT,$96
   839	// Save the registers clobbered by the fast path.
   840	MOVD	R4, 96(R15)
   841retry:
   842	MOVD	g_m(g), R1
   843	MOVD	m_p(R1), R1
   844	// Increment wbBuf.next position.
   845	MOVD	R9, R4
   846	ADD	(p_wbBuf+wbBuf_next)(R1), R4
   847	// Is the buffer full?
   848	MOVD	(p_wbBuf+wbBuf_end)(R1), R10
   849	CMPUBGT	R4, R10, flush
   850	// Commit to the larger buffer.
   851	MOVD	R4, (p_wbBuf+wbBuf_next)(R1)
   852	// Make return value (the original next position)
   853	SUB	R9, R4, R9
   854	// Restore registers.
   855	MOVD	96(R15), R4
   856	RET
   857
   858flush:
   859	// Save all general purpose registers since these could be
   860	// clobbered by wbBufFlush and were not saved by the caller.
   861	STMG	R2, R3, 8(R15)
   862	MOVD	R0, 24(R15)
   863	// R1 already saved.
   864	// R4 already saved.
   865	STMG	R5, R12, 32(R15) // save R5 - R12
   866	// R13 is g.
   867	// R14 is LR.
   868	// R15 is SP.
   869
   870	CALL	runtime·wbBufFlush(SB)
   871
   872	LMG	8(R15), R2, R3   // restore R2 - R3
   873	MOVD	24(R15), R0      // restore R0
   874	LMG	32(R15), R5, R12 // restore R5 - R12
   875	JMP	retry
   876
   877TEXT runtime·gcWriteBarrier1<ABIInternal>(SB),NOSPLIT,$0
   878	MOVD	$8, R9
   879	JMP	gcWriteBarrier<>(SB)
   880TEXT runtime·gcWriteBarrier2<ABIInternal>(SB),NOSPLIT,$0
   881	MOVD	$16, R9
   882	JMP	gcWriteBarrier<>(SB)
   883TEXT runtime·gcWriteBarrier3<ABIInternal>(SB),NOSPLIT,$0
   884	MOVD	$24, R9
   885	JMP	gcWriteBarrier<>(SB)
   886TEXT runtime·gcWriteBarrier4<ABIInternal>(SB),NOSPLIT,$0
   887	MOVD	$32, R9
   888	JMP	gcWriteBarrier<>(SB)
   889TEXT runtime·gcWriteBarrier5<ABIInternal>(SB),NOSPLIT,$0
   890	MOVD	$40, R9
   891	JMP	gcWriteBarrier<>(SB)
   892TEXT runtime·gcWriteBarrier6<ABIInternal>(SB),NOSPLIT,$0
   893	MOVD	$48, R9
   894	JMP	gcWriteBarrier<>(SB)
   895TEXT runtime·gcWriteBarrier7<ABIInternal>(SB),NOSPLIT,$0
   896	MOVD	$56, R9
   897	JMP	gcWriteBarrier<>(SB)
   898TEXT runtime·gcWriteBarrier8<ABIInternal>(SB),NOSPLIT,$0
   899	MOVD	$64, R9
   900	JMP	gcWriteBarrier<>(SB)
   901
   902// Note: these functions use a special calling convention to save generated code space.
   903// Arguments are passed in registers, but the space for those arguments are allocated
   904// in the caller's stack frame. These stubs write the args into that stack space and
   905// then tail call to the corresponding runtime handler.
   906// The tail call makes these stubs disappear in backtraces.
   907TEXT runtime·panicIndex(SB),NOSPLIT,$0-16
   908	MOVD	R0, x+0(FP)
   909	MOVD	R1, y+8(FP)
   910	JMP	runtime·goPanicIndex(SB)
   911TEXT runtime·panicIndexU(SB),NOSPLIT,$0-16
   912	MOVD	R0, x+0(FP)
   913	MOVD	R1, y+8(FP)
   914	JMP	runtime·goPanicIndexU(SB)
   915TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-16
   916	MOVD	R1, x+0(FP)
   917	MOVD	R2, y+8(FP)
   918	JMP	runtime·goPanicSliceAlen(SB)
   919TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-16
   920	MOVD	R1, x+0(FP)
   921	MOVD	R2, y+8(FP)
   922	JMP	runtime·goPanicSliceAlenU(SB)
   923TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-16
   924	MOVD	R1, x+0(FP)
   925	MOVD	R2, y+8(FP)
   926	JMP	runtime·goPanicSliceAcap(SB)
   927TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-16
   928	MOVD	R1, x+0(FP)
   929	MOVD	R2, y+8(FP)
   930	JMP	runtime·goPanicSliceAcapU(SB)
   931TEXT runtime·panicSliceB(SB),NOSPLIT,$0-16
   932	MOVD	R0, x+0(FP)
   933	MOVD	R1, y+8(FP)
   934	JMP	runtime·goPanicSliceB(SB)
   935TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-16
   936	MOVD	R0, x+0(FP)
   937	MOVD	R1, y+8(FP)
   938	JMP	runtime·goPanicSliceBU(SB)
   939TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-16
   940	MOVD	R2, x+0(FP)
   941	MOVD	R3, y+8(FP)
   942	JMP	runtime·goPanicSlice3Alen(SB)
   943TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-16
   944	MOVD	R2, x+0(FP)
   945	MOVD	R3, y+8(FP)
   946	JMP	runtime·goPanicSlice3AlenU(SB)
   947TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-16
   948	MOVD	R2, x+0(FP)
   949	MOVD	R3, y+8(FP)
   950	JMP	runtime·goPanicSlice3Acap(SB)
   951TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-16
   952	MOVD	R2, x+0(FP)
   953	MOVD	R3, y+8(FP)
   954	JMP	runtime·goPanicSlice3AcapU(SB)
   955TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-16
   956	MOVD	R1, x+0(FP)
   957	MOVD	R2, y+8(FP)
   958	JMP	runtime·goPanicSlice3B(SB)
   959TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-16
   960	MOVD	R1, x+0(FP)
   961	MOVD	R2, y+8(FP)
   962	JMP	runtime·goPanicSlice3BU(SB)
   963TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-16
   964	MOVD	R0, x+0(FP)
   965	MOVD	R1, y+8(FP)
   966	JMP	runtime·goPanicSlice3C(SB)
   967TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-16
   968	MOVD	R0, x+0(FP)
   969	MOVD	R1, y+8(FP)
   970	JMP	runtime·goPanicSlice3CU(SB)
   971TEXT runtime·panicSliceConvert(SB),NOSPLIT,$0-16
   972	MOVD	R2, x+0(FP)
   973	MOVD	R3, y+8(FP)
   974	JMP	runtime·goPanicSliceConvert(SB)

View as plain text