github.com/likebike/go--@v0.0.0-20190911215757-0bd925d16e96/go/src/runtime/asm_s390x.s (about)

     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  
   270  switch:
   271  	// save our state in g->sched.  Pretend to
   272  	// be systemstack_switch if the G stack is scanned.
   273  	MOVD	$runtime·systemstack_switch(SB), R6
   274  	ADD	$16, R6	// get past prologue
   275  	MOVD	R6, (g_sched+gobuf_pc)(g)
   276  	MOVD	R15, (g_sched+gobuf_sp)(g)
   277  	MOVD	$0, (g_sched+gobuf_lr)(g)
   278  	MOVD	g, (g_sched+gobuf_g)(g)
   279  
   280  	// switch to g0
   281  	MOVD	R5, g
   282  	BL	runtime·save_g(SB)
   283  	MOVD	(g_sched+gobuf_sp)(g), R3
   284  	// make it look like mstart called systemstack on g0, to stop traceback
   285  	SUB	$8, R3
   286  	MOVD	$runtime·mstart(SB), R4
   287  	MOVD	R4, 0(R3)
   288  	MOVD	R3, R15
   289  
   290  	// call target function
   291  	MOVD	0(R12), R3	// code pointer
   292  	BL	(R3)
   293  
   294  	// switch back to g
   295  	MOVD	g_m(g), R3
   296  	MOVD	m_curg(R3), g
   297  	BL	runtime·save_g(SB)
   298  	MOVD	(g_sched+gobuf_sp)(g), R15
   299  	MOVD	$0, (g_sched+gobuf_sp)(g)
   300  	RET
   301  
   302  noswitch:
   303  	// already on m stack, just call directly
   304  	// Using a tail call here cleans up tracebacks since we won't stop
   305  	// at an intermediate systemstack.
   306  	MOVD	0(R12), R3	// code pointer
   307  	MOVD	0(R15), LR	// restore LR
   308  	ADD	$8, R15
   309  	BR	(R3)
   310  
   311  /*
   312   * support for morestack
   313   */
   314  
   315  // Called during function prolog when more stack is needed.
   316  // Caller has already loaded:
   317  // R3: framesize, R4: argsize, R5: LR
   318  //
   319  // The traceback routines see morestack on a g0 as being
   320  // the top of a stack (for example, morestack calling newstack
   321  // calling the scheduler calling newm calling gc), so we must
   322  // record an argument size. For that purpose, it has no arguments.
   323  TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
   324  	// Cannot grow scheduler stack (m->g0).
   325  	MOVD	g_m(g), R7
   326  	MOVD	m_g0(R7), R8
   327  	CMPBNE	g, R8, 3(PC)
   328  	BL	runtime·badmorestackg0(SB)
   329  	BL	runtime·abort(SB)
   330  
   331  	// Cannot grow signal stack (m->gsignal).
   332  	MOVD	m_gsignal(R7), R8
   333  	CMP	g, R8
   334  	BNE	3(PC)
   335  	BL	runtime·badmorestackgsignal(SB)
   336  	BL	runtime·abort(SB)
   337  
   338  	// Called from f.
   339  	// Set g->sched to context in f.
   340  	MOVD	R15, (g_sched+gobuf_sp)(g)
   341  	MOVD	LR, R8
   342  	MOVD	R8, (g_sched+gobuf_pc)(g)
   343  	MOVD	R5, (g_sched+gobuf_lr)(g)
   344  	MOVD	R12, (g_sched+gobuf_ctxt)(g)
   345  
   346  	// Called from f.
   347  	// Set m->morebuf to f's caller.
   348  	MOVD	R5, (m_morebuf+gobuf_pc)(R7)	// f's caller's PC
   349  	MOVD	R15, (m_morebuf+gobuf_sp)(R7)	// f's caller's SP
   350  	MOVD	g, (m_morebuf+gobuf_g)(R7)
   351  
   352  	// Call newstack on m->g0's stack.
   353  	MOVD	m_g0(R7), g
   354  	BL	runtime·save_g(SB)
   355  	MOVD	(g_sched+gobuf_sp)(g), R15
   356  	// Create a stack frame on g0 to call newstack.
   357  	MOVD	$0, -8(R15)	// Zero saved LR in frame
   358  	SUB	$8, R15
   359  	BL	runtime·newstack(SB)
   360  
   361  	// Not reached, but make sure the return PC from the call to newstack
   362  	// is still in this function, and not the beginning of the next.
   363  	UNDEF
   364  
   365  TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0
   366  	MOVD	$0, R12
   367  	BR	runtime·morestack(SB)
   368  
   369  // reflectcall: call a function with the given argument list
   370  // func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32).
   371  // we don't have variable-sized frames, so we use a small number
   372  // of constant-sized-frame functions to encode a few bits of size in the pc.
   373  // Caution: ugly multiline assembly macros in your future!
   374  
   375  #define DISPATCH(NAME,MAXSIZE)		\
   376  	MOVD	$MAXSIZE, R4;		\
   377  	CMP	R3, R4;		\
   378  	BGT	3(PC);			\
   379  	MOVD	$NAME(SB), R5;	\
   380  	BR	(R5)
   381  // Note: can't just "BR NAME(SB)" - bad inlining results.
   382  
   383  TEXT reflect·call(SB), NOSPLIT, $0-0
   384  	BR	·reflectcall(SB)
   385  
   386  TEXT ·reflectcall(SB), NOSPLIT, $-8-32
   387  	MOVWZ argsize+24(FP), R3
   388  	DISPATCH(runtime·call32, 32)
   389  	DISPATCH(runtime·call64, 64)
   390  	DISPATCH(runtime·call128, 128)
   391  	DISPATCH(runtime·call256, 256)
   392  	DISPATCH(runtime·call512, 512)
   393  	DISPATCH(runtime·call1024, 1024)
   394  	DISPATCH(runtime·call2048, 2048)
   395  	DISPATCH(runtime·call4096, 4096)
   396  	DISPATCH(runtime·call8192, 8192)
   397  	DISPATCH(runtime·call16384, 16384)
   398  	DISPATCH(runtime·call32768, 32768)
   399  	DISPATCH(runtime·call65536, 65536)
   400  	DISPATCH(runtime·call131072, 131072)
   401  	DISPATCH(runtime·call262144, 262144)
   402  	DISPATCH(runtime·call524288, 524288)
   403  	DISPATCH(runtime·call1048576, 1048576)
   404  	DISPATCH(runtime·call2097152, 2097152)
   405  	DISPATCH(runtime·call4194304, 4194304)
   406  	DISPATCH(runtime·call8388608, 8388608)
   407  	DISPATCH(runtime·call16777216, 16777216)
   408  	DISPATCH(runtime·call33554432, 33554432)
   409  	DISPATCH(runtime·call67108864, 67108864)
   410  	DISPATCH(runtime·call134217728, 134217728)
   411  	DISPATCH(runtime·call268435456, 268435456)
   412  	DISPATCH(runtime·call536870912, 536870912)
   413  	DISPATCH(runtime·call1073741824, 1073741824)
   414  	MOVD	$runtime·badreflectcall(SB), R5
   415  	BR	(R5)
   416  
   417  #define CALLFN(NAME,MAXSIZE)			\
   418  TEXT NAME(SB), WRAPPER, $MAXSIZE-24;		\
   419  	NO_LOCAL_POINTERS;			\
   420  	/* copy arguments to stack */		\
   421  	MOVD	arg+16(FP), R4;			\
   422  	MOVWZ	argsize+24(FP), R5;		\
   423  	MOVD	$stack-MAXSIZE(SP), R6;		\
   424  loopArgs: /* copy 256 bytes at a time */	\
   425  	CMP	R5, $256;			\
   426  	BLT	tailArgs;			\
   427  	SUB	$256, R5;			\
   428  	MVC	$256, 0(R4), 0(R6);		\
   429  	MOVD	$256(R4), R4;			\
   430  	MOVD	$256(R6), R6;			\
   431  	BR	loopArgs;			\
   432  tailArgs: /* copy remaining bytes */		\
   433  	CMP	R5, $0;				\
   434  	BEQ	callFunction;			\
   435  	SUB	$1, R5;				\
   436  	EXRL	$callfnMVC<>(SB), R5;		\
   437  callFunction:					\
   438  	MOVD	f+8(FP), R12;			\
   439  	MOVD	(R12), R8;			\
   440  	PCDATA  $PCDATA_StackMapIndex, $0;	\
   441  	BL	(R8);				\
   442  	/* copy return values back */		\
   443  	MOVD	argtype+0(FP), R7;		\
   444  	MOVD	arg+16(FP), R6;			\
   445  	MOVWZ	n+24(FP), R5;			\
   446  	MOVD	$stack-MAXSIZE(SP), R4;		\
   447  	MOVWZ	retoffset+28(FP), R1;		\
   448  	ADD	R1, R4;				\
   449  	ADD	R1, R6;				\
   450  	SUB	R1, R5;				\
   451  	BL	callRet<>(SB);			\
   452  	RET
   453  
   454  // callRet copies return values back at the end of call*. This is a
   455  // separate function so it can allocate stack space for the arguments
   456  // to reflectcallmove. It does not follow the Go ABI; it expects its
   457  // arguments in registers.
   458  TEXT callRet<>(SB), NOSPLIT, $32-0
   459  	MOVD	R7, 8(R15)
   460  	MOVD	R6, 16(R15)
   461  	MOVD	R4, 24(R15)
   462  	MOVD	R5, 32(R15)
   463  	BL	runtime·reflectcallmove(SB)
   464  	RET
   465  
   466  CALLFN(·call32, 32)
   467  CALLFN(·call64, 64)
   468  CALLFN(·call128, 128)
   469  CALLFN(·call256, 256)
   470  CALLFN(·call512, 512)
   471  CALLFN(·call1024, 1024)
   472  CALLFN(·call2048, 2048)
   473  CALLFN(·call4096, 4096)
   474  CALLFN(·call8192, 8192)
   475  CALLFN(·call16384, 16384)
   476  CALLFN(·call32768, 32768)
   477  CALLFN(·call65536, 65536)
   478  CALLFN(·call131072, 131072)
   479  CALLFN(·call262144, 262144)
   480  CALLFN(·call524288, 524288)
   481  CALLFN(·call1048576, 1048576)
   482  CALLFN(·call2097152, 2097152)
   483  CALLFN(·call4194304, 4194304)
   484  CALLFN(·call8388608, 8388608)
   485  CALLFN(·call16777216, 16777216)
   486  CALLFN(·call33554432, 33554432)
   487  CALLFN(·call67108864, 67108864)
   488  CALLFN(·call134217728, 134217728)
   489  CALLFN(·call268435456, 268435456)
   490  CALLFN(·call536870912, 536870912)
   491  CALLFN(·call1073741824, 1073741824)
   492  
   493  // Not a function: target for EXRL (execute relative long) instruction.
   494  TEXT callfnMVC<>(SB),NOSPLIT|NOFRAME,$0-0
   495  	MVC	$1, 0(R4), 0(R6)
   496  
   497  TEXT runtime·procyield(SB),NOSPLIT,$0-0
   498  	RET
   499  
   500  // void jmpdefer(fv, sp);
   501  // called from deferreturn.
   502  // 1. grab stored LR for caller
   503  // 2. sub 6 bytes to get back to BL deferreturn (size of BRASL instruction)
   504  // 3. BR to fn
   505  TEXT runtime·jmpdefer(SB),NOSPLIT|NOFRAME,$0-16
   506  	MOVD	0(R15), R1
   507  	SUB	$6, R1, LR
   508  
   509  	MOVD	fv+0(FP), R12
   510  	MOVD	argp+8(FP), R15
   511  	SUB	$8, R15
   512  	MOVD	0(R12), R3
   513  	BR	(R3)
   514  
   515  // Save state of caller into g->sched. Smashes R1.
   516  TEXT gosave<>(SB),NOSPLIT|NOFRAME,$0
   517  	MOVD	LR, (g_sched+gobuf_pc)(g)
   518  	MOVD	R15, (g_sched+gobuf_sp)(g)
   519  	MOVD	$0, (g_sched+gobuf_lr)(g)
   520  	MOVD	$0, (g_sched+gobuf_ret)(g)
   521  	// Assert ctxt is zero. See func save.
   522  	MOVD	(g_sched+gobuf_ctxt)(g), R1
   523  	CMPBEQ	R1, $0, 2(PC)
   524  	BL	runtime·badctxt(SB)
   525  	RET
   526  
   527  // func asmcgocall(fn, arg unsafe.Pointer) int32
   528  // Call fn(arg) on the scheduler stack,
   529  // aligned appropriately for the gcc ABI.
   530  // See cgocall.go for more details.
   531  TEXT ·asmcgocall(SB),NOSPLIT,$0-20
   532  	// R2 = argc; R3 = argv; R11 = temp; R13 = g; R15 = stack pointer
   533  	// C TLS base pointer in AR0:AR1
   534  	MOVD	fn+0(FP), R3
   535  	MOVD	arg+8(FP), R4
   536  
   537  	MOVD	R15, R2		// save original stack pointer
   538  	MOVD	g, R5
   539  
   540  	// Figure out if we need to switch to m->g0 stack.
   541  	// We get called to create new OS threads too, and those
   542  	// come in on the m->g0 stack already.
   543  	MOVD	g_m(g), R6
   544  	MOVD	m_g0(R6), R6
   545  	CMPBEQ	R6, g, g0
   546  	BL	gosave<>(SB)
   547  	MOVD	R6, g
   548  	BL	runtime·save_g(SB)
   549  	MOVD	(g_sched+gobuf_sp)(g), R15
   550  
   551  	// Now on a scheduling stack (a pthread-created stack).
   552  g0:
   553  	// Save room for two of our pointers, plus 160 bytes of callee
   554  	// save area that lives on the caller stack.
   555  	SUB	$176, R15
   556  	MOVD	$~7, R6
   557  	AND	R6, R15                 // 8-byte alignment for gcc ABI
   558  	MOVD	R5, 168(R15)             // save old g on stack
   559  	MOVD	(g_stack+stack_hi)(R5), R5
   560  	SUB	R2, R5
   561  	MOVD	R5, 160(R15)             // save depth in old g stack (can't just save SP, as stack might be copied during a callback)
   562  	MOVD	$0, 0(R15)              // clear back chain pointer (TODO can we give it real back trace information?)
   563  	MOVD	R4, R2                  // arg in R2
   564  	BL	R3                      // can clobber: R0-R5, R14, F0-F3, F5, F7-F15
   565  
   566  	XOR	R0, R0                  // set R0 back to 0.
   567  	// Restore g, stack pointer.
   568  	MOVD	168(R15), g
   569  	BL	runtime·save_g(SB)
   570  	MOVD	(g_stack+stack_hi)(g), R5
   571  	MOVD	160(R15), R6
   572  	SUB	R6, R5
   573  	MOVD	R5, R15
   574  
   575  	MOVW	R2, ret+16(FP)
   576  	RET
   577  
   578  // cgocallback(void (*fn)(void*), void *frame, uintptr framesize, uintptr ctxt)
   579  // Turn the fn into a Go func (by taking its address) and call
   580  // cgocallback_gofunc.
   581  TEXT runtime·cgocallback(SB),NOSPLIT,$32-32
   582  	MOVD	$fn+0(FP), R3
   583  	MOVD	R3, 8(R15)
   584  	MOVD	frame+8(FP), R3
   585  	MOVD	R3, 16(R15)
   586  	MOVD	framesize+16(FP), R3
   587  	MOVD	R3, 24(R15)
   588  	MOVD	ctxt+24(FP), R3
   589  	MOVD	R3, 32(R15)
   590  	MOVD	$runtime·cgocallback_gofunc(SB), R3
   591  	BL	(R3)
   592  	RET
   593  
   594  // cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize, uintptr ctxt)
   595  // See cgocall.go for more details.
   596  TEXT ·cgocallback_gofunc(SB),NOSPLIT,$16-32
   597  	NO_LOCAL_POINTERS
   598  
   599  	// Load m and g from thread-local storage.
   600  	MOVB	runtime·iscgo(SB), R3
   601  	CMPBEQ	R3, $0, nocgo
   602  	BL	runtime·load_g(SB)
   603  
   604  nocgo:
   605  	// If g is nil, Go did not create the current thread.
   606  	// Call needm to obtain one for temporary use.
   607  	// In this case, we're running on the thread stack, so there's
   608  	// lots of space, but the linker doesn't know. Hide the call from
   609  	// the linker analysis by using an indirect call.
   610  	CMPBEQ	g, $0, needm
   611  
   612  	MOVD	g_m(g), R8
   613  	MOVD	R8, savedm-8(SP)
   614  	BR	havem
   615  
   616  needm:
   617  	MOVD	g, savedm-8(SP) // g is zero, so is m.
   618  	MOVD	$runtime·needm(SB), R3
   619  	BL	(R3)
   620  
   621  	// Set m->sched.sp = SP, so that if a panic happens
   622  	// during the function we are about to execute, it will
   623  	// have a valid SP to run on the g0 stack.
   624  	// The next few lines (after the havem label)
   625  	// will save this SP onto the stack and then write
   626  	// the same SP back to m->sched.sp. That seems redundant,
   627  	// but if an unrecovered panic happens, unwindm will
   628  	// restore the g->sched.sp from the stack location
   629  	// and then systemstack will try to use it. If we don't set it here,
   630  	// that restored SP will be uninitialized (typically 0) and
   631  	// will not be usable.
   632  	MOVD	g_m(g), R8
   633  	MOVD	m_g0(R8), R3
   634  	MOVD	R15, (g_sched+gobuf_sp)(R3)
   635  
   636  havem:
   637  	// Now there's a valid m, and we're running on its m->g0.
   638  	// Save current m->g0->sched.sp on stack and then set it to SP.
   639  	// Save current sp in m->g0->sched.sp in preparation for
   640  	// switch back to m->curg stack.
   641  	// NOTE: unwindm knows that the saved g->sched.sp is at 8(R1) aka savedsp-16(SP).
   642  	MOVD	m_g0(R8), R3
   643  	MOVD	(g_sched+gobuf_sp)(R3), R4
   644  	MOVD	R4, savedsp-16(SP)
   645  	MOVD	R15, (g_sched+gobuf_sp)(R3)
   646  
   647  	// Switch to m->curg stack and call runtime.cgocallbackg.
   648  	// Because we are taking over the execution of m->curg
   649  	// but *not* resuming what had been running, we need to
   650  	// save that information (m->curg->sched) so we can restore it.
   651  	// We can restore m->curg->sched.sp easily, because calling
   652  	// runtime.cgocallbackg leaves SP unchanged upon return.
   653  	// To save m->curg->sched.pc, we push it onto the stack.
   654  	// This has the added benefit that it looks to the traceback
   655  	// routine like cgocallbackg is going to return to that
   656  	// PC (because the frame we allocate below has the same
   657  	// size as cgocallback_gofunc's frame declared above)
   658  	// so that the traceback will seamlessly trace back into
   659  	// the earlier calls.
   660  	//
   661  	// In the new goroutine, -8(SP) is unused (where SP refers to
   662  	// m->curg's SP while we're setting it up, before we've adjusted it).
   663  	MOVD	m_curg(R8), g
   664  	BL	runtime·save_g(SB)
   665  	MOVD	(g_sched+gobuf_sp)(g), R4 // prepare stack as R4
   666  	MOVD	(g_sched+gobuf_pc)(g), R5
   667  	MOVD	R5, -24(R4)
   668  	MOVD	ctxt+24(FP), R5
   669  	MOVD	R5, -16(R4)
   670  	MOVD	$-24(R4), R15
   671  	BL	runtime·cgocallbackg(SB)
   672  
   673  	// Restore g->sched (== m->curg->sched) from saved values.
   674  	MOVD	0(R15), R5
   675  	MOVD	R5, (g_sched+gobuf_pc)(g)
   676  	MOVD	$24(R15), R4
   677  	MOVD	R4, (g_sched+gobuf_sp)(g)
   678  
   679  	// Switch back to m->g0's stack and restore m->g0->sched.sp.
   680  	// (Unlike m->curg, the g0 goroutine never uses sched.pc,
   681  	// so we do not have to restore it.)
   682  	MOVD	g_m(g), R8
   683  	MOVD	m_g0(R8), g
   684  	BL	runtime·save_g(SB)
   685  	MOVD	(g_sched+gobuf_sp)(g), R15
   686  	MOVD	savedsp-16(SP), R4
   687  	MOVD	R4, (g_sched+gobuf_sp)(g)
   688  
   689  	// If the m on entry was nil, we called needm above to borrow an m
   690  	// for the duration of the call. Since the call is over, return it with dropm.
   691  	MOVD	savedm-8(SP), R6
   692  	CMPBNE	R6, $0, droppedm
   693  	MOVD	$runtime·dropm(SB), R3
   694  	BL	(R3)
   695  droppedm:
   696  
   697  	// Done!
   698  	RET
   699  
   700  // void setg(G*); set g. for use by needm.
   701  TEXT runtime·setg(SB), NOSPLIT, $0-8
   702  	MOVD	gg+0(FP), g
   703  	// This only happens if iscgo, so jump straight to save_g
   704  	BL	runtime·save_g(SB)
   705  	RET
   706  
   707  // void setg_gcc(G*); set g in C TLS.
   708  // Must obey the gcc calling convention.
   709  TEXT setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0
   710  	// The standard prologue clobbers LR (R14), which is callee-save in
   711  	// the C ABI, so we have to use NOFRAME and save LR ourselves.
   712  	MOVD	LR, R1
   713  	// Also save g, R10, and R11 since they're callee-save in C ABI
   714  	MOVD	R10, R3
   715  	MOVD	g, R4
   716  	MOVD	R11, R5
   717  
   718  	MOVD	R2, g
   719  	BL	runtime·save_g(SB)
   720  
   721  	MOVD	R5, R11
   722  	MOVD	R4, g
   723  	MOVD	R3, R10
   724  	MOVD	R1, LR
   725  	RET
   726  
   727  TEXT runtime·getcallerpc(SB),NOSPLIT|NOFRAME,$0-8
   728  	MOVD	0(R15), R3		// LR saved by caller
   729  	MOVD	R3, ret+0(FP)
   730  	RET
   731  
   732  TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0
   733  	MOVW	(R0), R0
   734  	UNDEF
   735  
   736  // int64 runtime·cputicks(void)
   737  TEXT runtime·cputicks(SB),NOSPLIT,$0-8
   738  	// The TOD clock on s390 counts from the year 1900 in ~250ps intervals.
   739  	// This means that since about 1972 the msb has been set, making the
   740  	// result of a call to STORE CLOCK (stck) a negative number.
   741  	// We clear the msb to make it positive.
   742  	STCK	ret+0(FP)      // serialises before and after call
   743  	MOVD	ret+0(FP), R3  // R3 will wrap to 0 in the year 2043
   744  	SLD	$1, R3
   745  	SRD	$1, R3
   746  	MOVD	R3, ret+0(FP)
   747  	RET
   748  
   749  // AES hashing not implemented for s390x
   750  TEXT runtime·aeshash(SB),NOSPLIT|NOFRAME,$0-0
   751  	MOVW	(R0), R15
   752  TEXT runtime·aeshash32(SB),NOSPLIT|NOFRAME,$0-0
   753  	MOVW	(R0), R15
   754  TEXT runtime·aeshash64(SB),NOSPLIT|NOFRAME,$0-0
   755  	MOVW	(R0), R15
   756  TEXT runtime·aeshashstr(SB),NOSPLIT|NOFRAME,$0-0
   757  	MOVW	(R0), R15
   758  
   759  // memequal(a, b unsafe.Pointer, size uintptr) bool
   760  TEXT runtime·memequal(SB),NOSPLIT|NOFRAME,$0-25
   761  	MOVD	a+0(FP), R3
   762  	MOVD	b+8(FP), R5
   763  	MOVD	size+16(FP), R6
   764  	LA	ret+24(FP), R7
   765  	BR	runtime·memeqbody(SB)
   766  
   767  // memequal_varlen(a, b unsafe.Pointer) bool
   768  TEXT runtime·memequal_varlen(SB),NOSPLIT|NOFRAME,$0-17
   769  	MOVD	a+0(FP), R3
   770  	MOVD	b+8(FP), R5
   771  	MOVD	8(R12), R6    // compiler stores size at offset 8 in the closure
   772  	LA	ret+16(FP), R7
   773  	BR	runtime·memeqbody(SB)
   774  
   775  TEXT bytes·Equal(SB),NOSPLIT|NOFRAME,$0-49
   776  	MOVD	a_len+8(FP), R2
   777  	MOVD	b_len+32(FP), R6
   778  	MOVD	a+0(FP), R3
   779  	MOVD	b+24(FP), R5
   780  	LA	ret+48(FP), R7
   781  	CMPBNE	R2, R6, notequal
   782  	BR	runtime·memeqbody(SB)
   783  notequal:
   784  	MOVB	$0, ret+48(FP)
   785  	RET
   786  
   787  // input:
   788  //   R3 = a
   789  //   R5 = b
   790  //   R6 = len
   791  //   R7 = address of output byte (stores 0 or 1 here)
   792  //   a and b have the same length
   793  TEXT runtime·memeqbody(SB),NOSPLIT|NOFRAME,$0-0
   794  	CMPBEQ	R3, R5, equal
   795  loop:
   796  	CMPBEQ	R6, $0, equal
   797  	CMPBLT	R6, $32, tiny
   798  	CMP	R6, $256
   799  	BLT	tail
   800  	CLC	$256, 0(R3), 0(R5)
   801  	BNE	notequal
   802  	SUB	$256, R6
   803  	LA	256(R3), R3
   804  	LA	256(R5), R5
   805  	BR	loop
   806  tail:
   807  	SUB	$1, R6, R8
   808  	EXRL	$runtime·memeqbodyclc(SB), R8
   809  	BEQ	equal
   810  notequal:
   811  	MOVB	$0, 0(R7)
   812  	RET
   813  equal:
   814  	MOVB	$1, 0(R7)
   815  	RET
   816  tiny:
   817  	MOVD	$0, R2
   818  	CMPBLT	R6, $16, lt16
   819  	MOVD	0(R3), R8
   820  	MOVD	0(R5), R9
   821  	CMPBNE	R8, R9, notequal
   822  	MOVD	8(R3), R8
   823  	MOVD	8(R5), R9
   824  	CMPBNE	R8, R9, notequal
   825  	LA	16(R2), R2
   826  	SUB	$16, R6
   827  lt16:
   828  	CMPBLT	R6, $8, lt8
   829  	MOVD	0(R3)(R2*1), R8
   830  	MOVD	0(R5)(R2*1), R9
   831  	CMPBNE	R8, R9, notequal
   832  	LA	8(R2), R2
   833  	SUB	$8, R6
   834  lt8:
   835  	CMPBLT	R6, $4, lt4
   836  	MOVWZ	0(R3)(R2*1), R8
   837  	MOVWZ	0(R5)(R2*1), R9
   838  	CMPBNE	R8, R9, notequal
   839  	LA	4(R2), R2
   840  	SUB	$4, R6
   841  lt4:
   842  #define CHECK(n) \
   843  	CMPBEQ	R6, $n, equal \
   844  	MOVB	n(R3)(R2*1), R8 \
   845  	MOVB	n(R5)(R2*1), R9 \
   846  	CMPBNE	R8, R9, notequal
   847  	CHECK(0)
   848  	CHECK(1)
   849  	CHECK(2)
   850  	CHECK(3)
   851  	BR	equal
   852  
   853  TEXT runtime·memeqbodyclc(SB),NOSPLIT|NOFRAME,$0-0
   854  	CLC	$1, 0(R3), 0(R5)
   855  	RET
   856  
   857  TEXT bytes·IndexByte(SB),NOSPLIT|NOFRAME,$0-40
   858  	MOVD	s+0(FP), R3     // s => R3
   859  	MOVD	s_len+8(FP), R4 // s_len => R4
   860  	MOVBZ	c+24(FP), R5    // c => R5
   861  	MOVD	$ret+32(FP), R2 // &ret => R9
   862  	BR	runtime·indexbytebody(SB)
   863  
   864  TEXT strings·IndexByte(SB),NOSPLIT|NOFRAME,$0-32
   865  	MOVD	s+0(FP), R3     // s => R3
   866  	MOVD	s_len+8(FP), R4 // s_len => R4
   867  	MOVBZ	c+16(FP), R5    // c => R5
   868  	MOVD	$ret+24(FP), R2 // &ret => R9
   869  	BR	runtime·indexbytebody(SB)
   870  
   871  // input:
   872  // R3: s
   873  // R4: s_len
   874  // R5: c -- byte sought
   875  // R2: &ret -- address to put index into
   876  TEXT runtime·indexbytebody(SB),NOSPLIT|NOFRAME,$0
   877  	CMPBEQ	R4, $0, notfound
   878  	MOVD	R3, R6          // store base for later
   879  	ADD	R3, R4, R8      // the address after the end of the string
   880  	//if the length is small, use loop; otherwise, use vector or srst search
   881  	CMPBGE	R4, $16, large
   882  
   883  residual:
   884  	CMPBEQ	R3, R8, notfound
   885  	MOVBZ	0(R3), R7
   886  	LA	1(R3), R3
   887  	CMPBNE	R7, R5, residual
   888  
   889  found:
   890  	SUB	R6, R3
   891  	SUB	$1, R3
   892  	MOVD	R3, 0(R2)
   893  	RET
   894  
   895  notfound:
   896  	MOVD	$-1, 0(R2)
   897  	RET
   898  
   899  large:
   900  	MOVBZ	·cpu+facilities_hasVX(SB), R1
   901  	CMPBNE	R1, $0, vectorimpl
   902  
   903  srstimpl:                       // no vector facility
   904  	MOVBZ	R5, R0          // c needs to be in R0, leave until last minute as currently R0 is expected to be 0
   905  srstloop:
   906  	WORD	$0xB25E0083     // srst %r8, %r3 (search the range [R3, R8))
   907  	BVS	srstloop        // interrupted - continue
   908  	BGT	notfoundr0
   909  foundr0:
   910  	XOR	R0, R0          // reset R0
   911  	SUB	R6, R8          // remove base
   912  	MOVD	R8, 0(R2)
   913  	RET
   914  notfoundr0:
   915  	XOR	R0, R0          // reset R0
   916  	MOVD	$-1, 0(R2)
   917  	RET
   918  
   919  vectorimpl:
   920  	//if the address is not 16byte aligned, use loop for the header
   921  	MOVD	R3, R8
   922  	AND	$15, R8
   923  	CMPBGT	R8, $0, notaligned
   924  
   925  aligned:
   926  	ADD	R6, R4, R8
   927  	MOVD	R8, R7
   928  	AND	$-16, R7
   929  	// replicate c across V17
   930  	VLVGB	$0, R5, V19
   931  	VREPB	$0, V19, V17
   932  
   933  vectorloop:
   934  	CMPBGE	R3, R7, residual
   935  	VL	0(R3), V16    // load string to be searched into V16
   936  	ADD	$16, R3
   937  	VFEEBS	V16, V17, V18 // search V17 in V16 and set conditional code accordingly
   938  	BVS	vectorloop
   939  
   940  	// when vector search found c in the string
   941  	VLGVB	$7, V18, R7   // load 7th element of V18 containing index into R7
   942  	SUB	$16, R3
   943  	SUB	R6, R3
   944  	ADD	R3, R7
   945  	MOVD	R7, 0(R2)
   946  	RET
   947  
   948  notaligned:
   949  	MOVD	R3, R8
   950  	AND	$-16, R8
   951  	ADD     $16, R8
   952  notalignedloop:
   953  	CMPBEQ	R3, R8, aligned
   954  	MOVBZ	0(R3), R7
   955  	LA	1(R3), R3
   956  	CMPBNE	R7, R5, notalignedloop
   957  	BR	found
   958  
   959  TEXT runtime·return0(SB), NOSPLIT, $0
   960  	MOVW	$0, R3
   961  	RET
   962  
   963  // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
   964  // Must obey the gcc calling convention.
   965  TEXT _cgo_topofstack(SB),NOSPLIT|NOFRAME,$0
   966  	// g (R13), R10, R11 and LR (R14) are callee-save in the C ABI, so save them
   967  	MOVD	g, R1
   968  	MOVD	R10, R3
   969  	MOVD	LR, R4
   970  	MOVD	R11, R5
   971  
   972  	BL	runtime·load_g(SB)	// clobbers g (R13), R10, R11
   973  	MOVD	g_m(g), R2
   974  	MOVD	m_curg(R2), R2
   975  	MOVD	(g_stack+stack_hi)(R2), R2
   976  
   977  	MOVD	R1, g
   978  	MOVD	R3, R10
   979  	MOVD	R4, LR
   980  	MOVD	R5, R11
   981  	RET
   982  
   983  // The top-most function running on a goroutine
   984  // returns to goexit+PCQuantum.
   985  TEXT runtime·goexit(SB),NOSPLIT|NOFRAME,$0-0
   986  	BYTE $0x07; BYTE $0x00; // 2-byte nop
   987  	BL	runtime·goexit1(SB)	// does not return
   988  	// traceback from goexit1 must hit code range of goexit
   989  	BYTE $0x07; BYTE $0x00; // 2-byte nop
   990  
   991  TEXT runtime·sigreturn(SB),NOSPLIT,$0-0
   992  	RET
   993  
   994  TEXT ·publicationBarrier(SB),NOSPLIT|NOFRAME,$0-0
   995          // Stores are already ordered on s390x, so this is just a
   996          // compile barrier.
   997  	RET
   998  
   999  TEXT runtime·cmpstring(SB),NOSPLIT|NOFRAME,$0-40
  1000  	MOVD	s1_base+0(FP), R3
  1001  	MOVD	s1_len+8(FP), R4
  1002  	MOVD	s2_base+16(FP), R5
  1003  	MOVD	s2_len+24(FP), R6
  1004  	LA	ret+32(FP), R7
  1005  	BR	runtime·cmpbody(SB)
  1006  
  1007  TEXT bytes·Compare(SB),NOSPLIT|NOFRAME,$0-56
  1008  	MOVD	s1+0(FP), R3
  1009  	MOVD	s1+8(FP), R4
  1010  	MOVD	s2+24(FP), R5
  1011  	MOVD	s2+32(FP), R6
  1012  	LA	res+48(FP), R7
  1013  	BR	runtime·cmpbody(SB)
  1014  
  1015  // input:
  1016  //   R3 = a
  1017  //   R4 = alen
  1018  //   R5 = b
  1019  //   R6 = blen
  1020  //   R7 = address of output word (stores -1/0/1 here)
  1021  TEXT runtime·cmpbody(SB),NOSPLIT|NOFRAME,$0-0
  1022  	CMPBEQ	R3, R5, cmplengths
  1023  	MOVD	R4, R8
  1024  	CMPBLE	R4, R6, amin
  1025  	MOVD	R6, R8
  1026  amin:
  1027  	CMPBEQ	R8, $0, cmplengths
  1028  	CMP	R8, $256
  1029  	BLE	tail
  1030  loop:
  1031  	CLC	$256, 0(R3), 0(R5)
  1032  	BGT	gt
  1033  	BLT	lt
  1034  	SUB	$256, R8
  1035  	CMP	R8, $256
  1036  	BGT	loop
  1037  tail:
  1038  	SUB	$1, R8
  1039  	EXRL	$runtime·cmpbodyclc(SB), R8
  1040  	BGT	gt
  1041  	BLT	lt
  1042  cmplengths:
  1043  	CMP	R4, R6
  1044  	BEQ	eq
  1045  	BLT	lt
  1046  gt:
  1047  	MOVD	$1, 0(R7)
  1048  	RET
  1049  lt:
  1050  	MOVD	$-1, 0(R7)
  1051  	RET
  1052  eq:
  1053  	MOVD	$0, 0(R7)
  1054  	RET
  1055  
  1056  TEXT runtime·cmpbodyclc(SB),NOSPLIT|NOFRAME,$0-0
  1057  	CLC	$1, 0(R3), 0(R5)
  1058  	RET
  1059  
  1060  // func supportsVX() bool
  1061  TEXT strings·supportsVX(SB),NOSPLIT,$0-1
  1062  	MOVBZ	runtime·cpu+facilities_hasVX(SB), R0
  1063  	MOVB	R0, ret+0(FP)
  1064  	RET
  1065  
  1066  // func supportsVX() bool
  1067  TEXT bytes·supportsVX(SB),NOSPLIT,$0-1
  1068  	MOVBZ	runtime·cpu+facilities_hasVX(SB), R0
  1069  	MOVB	R0, ret+0(FP)
  1070  	RET
  1071  
  1072  // func indexShortStr(s, sep string) int
  1073  // Caller must confirm availability of vx facility before calling.
  1074  TEXT strings·indexShortStr(SB),NOSPLIT|NOFRAME,$0-40
  1075  	LMG	s+0(FP), R1, R2   // R1=&s[0],   R2=len(s)
  1076  	LMG	sep+16(FP), R3, R4 // R3=&sep[0], R4=len(sep)
  1077  	MOVD	$ret+32(FP), R5
  1078  	BR	runtime·indexShortStr(SB)
  1079  
  1080  // func indexShortStr(s, sep []byte) int
  1081  // Caller must confirm availability of vx facility before calling.
  1082  TEXT bytes·indexShortStr(SB),NOSPLIT|NOFRAME,$0-56
  1083  	LMG	s+0(FP), R1, R2    // R1=&s[0],   R2=len(s)
  1084  	LMG	sep+24(FP), R3, R4 // R3=&sep[0], R4=len(sep)
  1085  	MOVD	$ret+48(FP), R5
  1086  	BR	runtime·indexShortStr(SB)
  1087  
  1088  // s: string we are searching
  1089  // sep: string to search for
  1090  // R1=&s[0], R2=len(s)
  1091  // R3=&sep[0], R4=len(sep)
  1092  // R5=&ret (int)
  1093  // Caller must confirm availability of vx facility before calling.
  1094  TEXT runtime·indexShortStr(SB),NOSPLIT|NOFRAME,$0
  1095  	CMPBGT	R4, R2, notfound
  1096  	ADD	R1, R2
  1097  	SUB	R4, R2 // R2=&s[len(s)-len(sep)] (last valid index)
  1098  	CMPBEQ	R4, $0, notfound
  1099  	SUB	$1, R4 // R4=len(sep)-1 for use as VLL index
  1100  	VLL	R4, (R3), V0 // contains first 16 bytes of sep
  1101  	MOVD	R1, R7
  1102  index2plus:
  1103  	CMPBNE	R4, $1, index3plus
  1104  	MOVD	$15(R7), R9
  1105  	CMPBGE	R9, R2, index2to16
  1106  	VGBM	$0xaaaa, V31       // 0xff00ff00ff00ff00...
  1107  	VONE	V16
  1108  	VREPH	$0, V0, V1
  1109  	CMPBGE	R9, R2, index2to16
  1110  index2loop:
  1111  	VL	0(R7), V2          // 16 bytes, even indices
  1112  	VL	1(R7), V4          // 16 bytes, odd indices
  1113  	VCEQH	V1, V2, V5         // compare even indices
  1114  	VCEQH	V1, V4, V6         // compare odd indices
  1115  	VSEL	V5, V6, V31, V7    // merge even and odd indices
  1116  	VFEEBS	V16, V7, V17       // find leftmost index, set condition to 1 if found
  1117  	BLT	foundV17
  1118  	MOVD	$16(R7), R7        // R7+=16
  1119  	ADD	$15, R7, R9
  1120  	CMPBLE	R9, R2, index2loop // continue if (R7+15) <= R2 (last index to search)
  1121  	CMPBLE	R7, R2, index2to16
  1122  	BR	notfound
  1123  
  1124  index3plus:
  1125  	CMPBNE	R4, $2, index4plus
  1126  	ADD	$15, R7, R9
  1127  	CMPBGE	R9, R2, index2to16
  1128  	MOVD	$1, R0
  1129  	VGBM	$0xaaaa, V31       // 0xff00ff00ff00ff00...
  1130  	VONE	V16
  1131  	VREPH	$0, V0, V1
  1132  	VREPB	$2, V0, V8
  1133  index3loop:
  1134  	VL	(R7), V2           // load 16-bytes into V2
  1135  	VLL	R0, 16(R7), V3     // load 2-bytes into V3
  1136  	VSLDB	$1, V2, V3, V4     // V4=(V2:V3)<<1
  1137  	VSLDB	$2, V2, V3, V9     // V9=(V2:V3)<<2
  1138  	VCEQH	V1, V2, V5         // compare 2-byte even indices
  1139  	VCEQH	V1, V4, V6         // compare 2-byte odd indices
  1140  	VCEQB	V8, V9, V10        // compare last bytes
  1141  	VSEL	V5, V6, V31, V7    // merge even and odd indices
  1142  	VN	V7, V10, V7        // AND indices with last byte
  1143  	VFEEBS	V16, V7, V17       // find leftmost index, set condition to 1 if found
  1144  	BLT	foundV17
  1145  	MOVD	$16(R7), R7        // R7+=16
  1146  	ADD	$15, R7, R9
  1147  	CMPBLE	R9, R2, index3loop // continue if (R7+15) <= R2 (last index to search)
  1148  	CMPBLE	R7, R2, index2to16
  1149  	BR	notfound
  1150  
  1151  index4plus:
  1152  	CMPBNE	R4, $3, index5plus
  1153  	ADD	$15, R7, R9
  1154  	CMPBGE	R9, R2, index2to16
  1155  	MOVD	$2, R0
  1156  	VGBM	$0x8888, V29       // 0xff000000ff000000...
  1157  	VGBM	$0x2222, V30       // 0x0000ff000000ff00...
  1158  	VGBM	$0xcccc, V31       // 0xffff0000ffff0000...
  1159  	VONE	V16
  1160  	VREPF	$0, V0, V1
  1161  index4loop:
  1162  	VL	(R7), V2           // load 16-bytes into V2
  1163  	VLL	R0, 16(R7), V3     // load 3-bytes into V3
  1164  	VSLDB	$1, V2, V3, V4     // V4=(V2:V3)<<1
  1165  	VSLDB	$2, V2, V3, V9     // V9=(V2:V3)<<1
  1166  	VSLDB	$3, V2, V3, V10    // V10=(V2:V3)<<1
  1167  	VCEQF	V1, V2, V5         // compare index 0, 4, ...
  1168  	VCEQF	V1, V4, V6         // compare index 1, 5, ...
  1169  	VCEQF	V1, V9, V11        // compare index 2, 6, ...
  1170  	VCEQF	V1, V10, V12       // compare index 3, 7, ...
  1171  	VSEL	V5, V6, V29, V13   // merge index 0, 1, 4, 5, ...
  1172  	VSEL	V11, V12, V30, V14 // merge index 2, 3, 6, 7, ...
  1173  	VSEL	V13, V14, V31, V7  // final merge
  1174  	VFEEBS	V16, V7, V17       // find leftmost index, set condition to 1 if found
  1175  	BLT	foundV17
  1176  	MOVD	$16(R7), R7        // R7+=16
  1177  	ADD	$15, R7, R9
  1178  	CMPBLE	R9, R2, index4loop // continue if (R7+15) <= R2 (last index to search)
  1179  	CMPBLE	R7, R2, index2to16
  1180  	BR	notfound
  1181  
  1182  index5plus:
  1183  	CMPBGT	R4, $15, index17plus
  1184  index2to16:
  1185  	CMPBGT	R7, R2, notfound
  1186  	MOVD	$1(R7), R8
  1187  	CMPBGT	R8, R2, index2to16tail
  1188  index2to16loop:
  1189  	// unrolled 2x
  1190  	VLL	R4, (R7), V1
  1191  	VLL	R4, 1(R7), V2
  1192  	VCEQGS	V0, V1, V3
  1193  	BEQ	found
  1194  	MOVD	$1(R7), R7
  1195  	VCEQGS	V0, V2, V4
  1196  	BEQ	found
  1197  	MOVD	$1(R7), R7
  1198  	CMPBLT	R7, R2, index2to16loop
  1199  	CMPBGT	R7, R2, notfound
  1200  index2to16tail:
  1201  	VLL	R4, (R7), V1
  1202  	VCEQGS	V0, V1, V2
  1203  	BEQ	found
  1204  	BR	notfound
  1205  
  1206  index17plus:
  1207  	CMPBGT	R4, $31, index33plus
  1208  	SUB	$16, R4, R0
  1209  	VLL	R0, 16(R3), V1
  1210  	VONE	V7
  1211  index17to32loop:
  1212  	VL	(R7), V2
  1213  	VLL	R0, 16(R7), V3
  1214  	VCEQG	V0, V2, V4
  1215  	VCEQG	V1, V3, V5
  1216  	VN	V4, V5, V6
  1217  	VCEQGS	V6, V7, V8
  1218  	BEQ	found
  1219  	MOVD	$1(R7), R7
  1220  	CMPBLE  R7, R2, index17to32loop
  1221  	BR	notfound
  1222  
  1223  index33plus:
  1224  	CMPBGT	R4, $47, index49plus
  1225  	SUB	$32, R4, R0
  1226  	VL	16(R3), V1
  1227  	VLL	R0, 32(R3), V2
  1228  	VONE	V11
  1229  index33to48loop:
  1230  	VL	(R7), V3
  1231  	VL	16(R7), V4
  1232  	VLL	R0, 32(R7), V5
  1233  	VCEQG	V0, V3, V6
  1234  	VCEQG	V1, V4, V7
  1235  	VCEQG	V2, V5, V8
  1236  	VN	V6, V7, V9
  1237  	VN	V8, V9, V10
  1238  	VCEQGS	V10, V11, V12
  1239  	BEQ	found
  1240  	MOVD	$1(R7), R7
  1241  	CMPBLE  R7, R2, index33to48loop
  1242  	BR	notfound
  1243  
  1244  index49plus:
  1245  	CMPBGT	R4, $63, index65plus
  1246  	SUB	$48, R4, R0
  1247  	VL	16(R3), V1
  1248  	VL	32(R3), V2
  1249  	VLL	R0, 48(R3), V3
  1250  	VONE	V15
  1251  index49to64loop:
  1252  	VL	(R7), V4
  1253  	VL	16(R7), V5
  1254  	VL	32(R7), V6
  1255  	VLL	R0, 48(R7), V7
  1256  	VCEQG	V0, V4, V8
  1257  	VCEQG	V1, V5, V9
  1258  	VCEQG	V2, V6, V10
  1259  	VCEQG	V3, V7, V11
  1260  	VN	V8, V9, V12
  1261  	VN	V10, V11, V13
  1262  	VN	V12, V13, V14
  1263  	VCEQGS	V14, V15, V16
  1264  	BEQ	found
  1265  	MOVD	$1(R7), R7
  1266  	CMPBLE  R7, R2, index49to64loop
  1267  notfound:
  1268  	MOVD	$-1, (R5)
  1269  	RET
  1270  
  1271  index65plus:
  1272  	// not implemented
  1273  	MOVD	$0, (R0)
  1274  	RET
  1275  
  1276  foundV17: // index is in doubleword V17[0]
  1277  	VLGVG	$0, V17, R8
  1278  	ADD	R8, R7
  1279  found:
  1280  	SUB	R1, R7
  1281  	MOVD	R7, (R5)
  1282  	RET
  1283  
  1284  // This is called from .init_array and follows the platform, not Go, ABI.
  1285  // We are overly conservative. We could only save the registers we use.
  1286  // However, since this function is only called once per loaded module
  1287  // performance is unimportant.
  1288  TEXT runtime·addmoduledata(SB),NOSPLIT|NOFRAME,$0-0
  1289  	// Save R6-R15 in the register save area of the calling function.
  1290  	// Don't bother saving F8-F15 as we aren't doing any calls.
  1291  	STMG	R6, R15, 48(R15)
  1292  
  1293  	// append the argument (passed in R2, as per the ELF ABI) to the
  1294  	// moduledata linked list.
  1295  	MOVD	runtime·lastmoduledatap(SB), R1
  1296  	MOVD	R2, moduledata_next(R1)
  1297  	MOVD	R2, runtime·lastmoduledatap(SB)
  1298  
  1299  	// Restore R6-R15.
  1300  	LMG	48(R15), R6, R15
  1301  	RET
  1302  
  1303  TEXT ·checkASM(SB),NOSPLIT,$0-1
  1304  	MOVB	$1, ret+0(FP)
  1305  	RET