github.com/c12o16h1/go/src@v0.0.0-20200114212001-5a151c0f00ed/runtime/asm_wasm.s (about)

     1  // Copyright 2018 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  TEXT runtime·rt0_go(SB), NOSPLIT|NOFRAME, $0
    11  	// save m->g0 = g0
    12  	MOVD $runtime·g0(SB), runtime·m0+m_g0(SB)
    13  	// save m0 to g0->m
    14  	MOVD $runtime·m0(SB), runtime·g0+g_m(SB)
    15  	// set g to g0
    16  	MOVD $runtime·g0(SB), g
    17  	CALLNORESUME runtime·check(SB)
    18  	CALLNORESUME runtime·args(SB)
    19  	CALLNORESUME runtime·osinit(SB)
    20  	CALLNORESUME runtime·schedinit(SB)
    21  	MOVD $0, 0(SP)
    22  	MOVD $runtime·mainPC(SB), 8(SP)
    23  	CALLNORESUME runtime·newproc(SB)
    24  	CALL runtime·mstart(SB) // WebAssembly stack will unwind when switching to another goroutine
    25  	UNDEF
    26  
    27  DATA  runtime·mainPC+0(SB)/8,$runtime·main(SB)
    28  GLOBL runtime·mainPC(SB),RODATA,$8
    29  
    30  // func checkASM() bool
    31  TEXT ·checkASM(SB), NOSPLIT, $0-1
    32  	MOVB $1, ret+0(FP)
    33  	RET
    34  
    35  TEXT runtime·gogo(SB), NOSPLIT, $0-8
    36  	MOVD buf+0(FP), R0
    37  	MOVD gobuf_g(R0), g
    38  	MOVD gobuf_sp(R0), SP
    39  
    40  	// Put target PC at -8(SP), wasm_pc_f_loop will pick it up
    41  	Get SP
    42  	I32Const $8
    43  	I32Sub
    44  	I64Load gobuf_pc(R0)
    45  	I64Store $0
    46  
    47  	MOVD gobuf_ret(R0), RET0
    48  	MOVD gobuf_ctxt(R0), CTXT
    49  	// clear to help garbage collector
    50  	MOVD $0, gobuf_sp(R0)
    51  	MOVD $0, gobuf_ret(R0)
    52  	MOVD $0, gobuf_ctxt(R0)
    53  
    54  	I32Const $1
    55  	Return
    56  
    57  // func mcall(fn func(*g))
    58  // Switch to m->g0's stack, call fn(g).
    59  // Fn must never return. It should gogo(&g->sched)
    60  // to keep running g.
    61  TEXT runtime·mcall(SB), NOSPLIT, $0-8
    62  	// CTXT = fn
    63  	MOVD fn+0(FP), CTXT
    64  	// R1 = g.m
    65  	MOVD g_m(g), R1
    66  	// R2 = g0
    67  	MOVD m_g0(R1), R2
    68  
    69  	// save state in g->sched
    70  	MOVD 0(SP), g_sched+gobuf_pc(g)     // caller's PC
    71  	MOVD $fn+0(FP), g_sched+gobuf_sp(g) // caller's SP
    72  	MOVD g, g_sched+gobuf_g(g)
    73  
    74  	// if g == g0 call badmcall
    75  	Get g
    76  	Get R2
    77  	I64Eq
    78  	If
    79  		JMP runtime·badmcall(SB)
    80  	End
    81  
    82  	// switch to g0's stack
    83  	I64Load (g_sched+gobuf_sp)(R2)
    84  	I64Const $8
    85  	I64Sub
    86  	I32WrapI64
    87  	Set SP
    88  
    89  	// set arg to current g
    90  	MOVD g, 0(SP)
    91  
    92  	// switch to g0
    93  	MOVD R2, g
    94  
    95  	// call fn
    96  	Get CTXT
    97  	I32WrapI64
    98  	I64Load $0
    99  	CALL
   100  
   101  	Get SP
   102  	I32Const $8
   103  	I32Add
   104  	Set SP
   105  
   106  	JMP runtime·badmcall2(SB)
   107  
   108  // func systemstack(fn func())
   109  TEXT runtime·systemstack(SB), NOSPLIT, $0-8
   110  	// R0 = fn
   111  	MOVD fn+0(FP), R0
   112  	// R1 = g.m
   113  	MOVD g_m(g), R1
   114  	// R2 = g0
   115  	MOVD m_g0(R1), R2
   116  
   117  	// if g == g0
   118  	Get g
   119  	Get R2
   120  	I64Eq
   121  	If
   122  		// no switch:
   123  		MOVD R0, CTXT
   124  
   125  		Get CTXT
   126  		I32WrapI64
   127  		I64Load $0
   128  		JMP
   129  	End
   130  
   131  	// if g != m.curg
   132  	Get g
   133  	I64Load m_curg(R1)
   134  	I64Ne
   135  	If
   136  		CALLNORESUME runtime·badsystemstack(SB)
   137  	End
   138  
   139  	// switch:
   140  
   141  	// save state in g->sched. Pretend to
   142  	// be systemstack_switch if the G stack is scanned.
   143  	MOVD $runtime·systemstack_switch(SB), g_sched+gobuf_pc(g)
   144  
   145  	MOVD SP, g_sched+gobuf_sp(g)
   146  	MOVD g, g_sched+gobuf_g(g)
   147  
   148  	// switch to g0
   149  	MOVD R2, g
   150  
   151  	// make it look like mstart called systemstack on g0, to stop traceback
   152  	I64Load (g_sched+gobuf_sp)(R2)
   153  	I64Const $8
   154  	I64Sub
   155  	Set R3
   156  
   157  	MOVD $runtime·mstart(SB), 0(R3)
   158  	MOVD R3, SP
   159  
   160  	// call fn
   161  	MOVD R0, CTXT
   162  
   163  	Get CTXT
   164  	I32WrapI64
   165  	I64Load $0
   166  	CALL
   167  
   168  	// switch back to g
   169  	MOVD g_m(g), R1
   170  	MOVD m_curg(R1), R2
   171  	MOVD R2, g
   172  	MOVD g_sched+gobuf_sp(R2), SP
   173  	MOVD $0, g_sched+gobuf_sp(R2)
   174  	RET
   175  
   176  TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
   177  	RET
   178  
   179  // AES hashing not implemented for wasm
   180  TEXT runtime·memhash(SB),NOSPLIT|NOFRAME,$0-32
   181  	JMP	runtime·memhashFallback(SB)
   182  TEXT runtime·strhash(SB),NOSPLIT|NOFRAME,$0-24
   183  	JMP	runtime·strhashFallback(SB)
   184  TEXT runtime·memhash32(SB),NOSPLIT|NOFRAME,$0-24
   185  	JMP	runtime·memhash32Fallback(SB)
   186  TEXT runtime·memhash64(SB),NOSPLIT|NOFRAME,$0-24
   187  	JMP	runtime·memhash64Fallback(SB)
   188  
   189  TEXT runtime·return0(SB), NOSPLIT, $0-0
   190  	MOVD $0, RET0
   191  	RET
   192  
   193  TEXT runtime·jmpdefer(SB), NOSPLIT, $0-16
   194  	MOVD fv+0(FP), CTXT
   195  
   196  	Get CTXT
   197  	I64Eqz
   198  	If
   199  		CALLNORESUME runtime·sigpanic(SB)
   200  	End
   201  
   202  	// caller sp after CALL
   203  	I64Load argp+8(FP)
   204  	I64Const $8
   205  	I64Sub
   206  	I32WrapI64
   207  	Set SP
   208  
   209  	// decrease PC_B by 1 to CALL again
   210  	Get SP
   211  	I32Load16U (SP)
   212  	I32Const $1
   213  	I32Sub
   214  	I32Store16 $0
   215  
   216  	// but first run the deferred function
   217  	Get CTXT
   218  	I32WrapI64
   219  	I64Load $0
   220  	JMP
   221  
   222  TEXT runtime·asminit(SB), NOSPLIT, $0-0
   223  	// No per-thread init.
   224  	RET
   225  
   226  TEXT ·publicationBarrier(SB), NOSPLIT, $0-0
   227  	RET
   228  
   229  TEXT runtime·procyield(SB), NOSPLIT, $0-0 // FIXME
   230  	RET
   231  
   232  TEXT runtime·breakpoint(SB), NOSPLIT, $0-0
   233  	UNDEF
   234  
   235  // Called during function prolog when more stack is needed.
   236  //
   237  // The traceback routines see morestack on a g0 as being
   238  // the top of a stack (for example, morestack calling newstack
   239  // calling the scheduler calling newm calling gc), so we must
   240  // record an argument size. For that purpose, it has no arguments.
   241  TEXT runtime·morestack(SB), NOSPLIT, $0-0
   242  	// R1 = g.m
   243  	MOVD g_m(g), R1
   244  
   245  	// R2 = g0
   246  	MOVD m_g0(R1), R2
   247  
   248  	// Cannot grow scheduler stack (m->g0).
   249  	Get g
   250  	Get R1
   251  	I64Eq
   252  	If
   253  		CALLNORESUME runtime·badmorestackg0(SB)
   254  	End
   255  
   256  	// Cannot grow signal stack (m->gsignal).
   257  	Get g
   258  	I64Load m_gsignal(R1)
   259  	I64Eq
   260  	If
   261  		CALLNORESUME runtime·badmorestackgsignal(SB)
   262  	End
   263  
   264  	// Called from f.
   265  	// Set m->morebuf to f's caller.
   266  	NOP	SP	// tell vet SP changed - stop checking offsets
   267  	MOVD 8(SP), m_morebuf+gobuf_pc(R1)
   268  	MOVD $16(SP), m_morebuf+gobuf_sp(R1) // f's caller's SP
   269  	MOVD g, m_morebuf+gobuf_g(R1)
   270  
   271  	// Set g->sched to context in f.
   272  	MOVD 0(SP), g_sched+gobuf_pc(g)
   273  	MOVD g, g_sched+gobuf_g(g)
   274  	MOVD $8(SP), g_sched+gobuf_sp(g) // f's SP
   275  	MOVD CTXT, g_sched+gobuf_ctxt(g)
   276  
   277  	// Call newstack on m->g0's stack.
   278  	MOVD R2, g
   279  	MOVD g_sched+gobuf_sp(R2), SP
   280  	CALL runtime·newstack(SB)
   281  	UNDEF // crash if newstack returns
   282  
   283  // morestack but not preserving ctxt.
   284  TEXT runtime·morestack_noctxt(SB),NOSPLIT,$0
   285  	MOVD $0, CTXT
   286  	JMP runtime·morestack(SB)
   287  
   288  TEXT ·asmcgocall(SB), NOSPLIT, $0-0
   289  	UNDEF
   290  
   291  TEXT ·cgocallback_gofunc(SB), NOSPLIT, $16-32
   292  	UNDEF
   293  
   294  #define DISPATCH(NAME, MAXSIZE) \
   295  	Get R0; \
   296  	I64Const $MAXSIZE; \
   297  	I64LeU; \
   298  	If; \
   299  		JMP NAME(SB); \
   300  	End
   301  
   302  TEXT ·reflectcall(SB), NOSPLIT, $0-32
   303  	I64Load fn+8(FP)
   304  	I64Eqz
   305  	If
   306  		CALLNORESUME runtime·sigpanic(SB)
   307  	End
   308  
   309  	MOVW argsize+24(FP), R0
   310  
   311  	DISPATCH(runtime·call32, 32)
   312  	DISPATCH(runtime·call64, 64)
   313  	DISPATCH(runtime·call128, 128)
   314  	DISPATCH(runtime·call256, 256)
   315  	DISPATCH(runtime·call512, 512)
   316  	DISPATCH(runtime·call1024, 1024)
   317  	DISPATCH(runtime·call2048, 2048)
   318  	DISPATCH(runtime·call4096, 4096)
   319  	DISPATCH(runtime·call8192, 8192)
   320  	DISPATCH(runtime·call16384, 16384)
   321  	DISPATCH(runtime·call32768, 32768)
   322  	DISPATCH(runtime·call65536, 65536)
   323  	DISPATCH(runtime·call131072, 131072)
   324  	DISPATCH(runtime·call262144, 262144)
   325  	DISPATCH(runtime·call524288, 524288)
   326  	DISPATCH(runtime·call1048576, 1048576)
   327  	DISPATCH(runtime·call2097152, 2097152)
   328  	DISPATCH(runtime·call4194304, 4194304)
   329  	DISPATCH(runtime·call8388608, 8388608)
   330  	DISPATCH(runtime·call16777216, 16777216)
   331  	DISPATCH(runtime·call33554432, 33554432)
   332  	DISPATCH(runtime·call67108864, 67108864)
   333  	DISPATCH(runtime·call134217728, 134217728)
   334  	DISPATCH(runtime·call268435456, 268435456)
   335  	DISPATCH(runtime·call536870912, 536870912)
   336  	DISPATCH(runtime·call1073741824, 1073741824)
   337  	JMP runtime·badreflectcall(SB)
   338  
   339  #define CALLFN(NAME, MAXSIZE) \
   340  TEXT NAME(SB), WRAPPER, $MAXSIZE-32; \
   341  	NO_LOCAL_POINTERS; \
   342  	MOVW argsize+24(FP), R0; \
   343  	\
   344  	Get R0; \
   345  	I64Eqz; \
   346  	Not; \
   347  	If; \
   348  		Get SP; \
   349  		I64Load argptr+16(FP); \
   350  		I32WrapI64; \
   351  		I64Load argsize+24(FP); \
   352  		I64Const $3; \
   353  		I64ShrU; \
   354  		I32WrapI64; \
   355  		Call runtime·wasmMove(SB); \
   356  	End; \
   357  	\
   358  	MOVD f+8(FP), CTXT; \
   359  	Get CTXT; \
   360  	I32WrapI64; \
   361  	I64Load $0; \
   362  	CALL; \
   363  	\
   364  	I64Load32U retoffset+28(FP); \
   365  	Set R0; \
   366  	\
   367  	MOVD argtype+0(FP), RET0; \
   368  	\
   369  	I64Load argptr+16(FP); \
   370  	Get R0; \
   371  	I64Add; \
   372  	Set RET1; \
   373  	\
   374  	Get SP; \
   375  	I64ExtendI32U; \
   376  	Get R0; \
   377  	I64Add; \
   378  	Set RET2; \
   379  	\
   380  	I64Load32U argsize+24(FP); \
   381  	Get R0; \
   382  	I64Sub; \
   383  	Set RET3; \
   384  	\
   385  	CALL callRet<>(SB); \
   386  	RET
   387  
   388  // callRet copies return values back at the end of call*. This is a
   389  // separate function so it can allocate stack space for the arguments
   390  // to reflectcallmove. It does not follow the Go ABI; it expects its
   391  // arguments in registers.
   392  TEXT callRet<>(SB), NOSPLIT, $32-0
   393  	NO_LOCAL_POINTERS
   394  	MOVD RET0, 0(SP)
   395  	MOVD RET1, 8(SP)
   396  	MOVD RET2, 16(SP)
   397  	MOVD RET3, 24(SP)
   398  	CALL runtime·reflectcallmove(SB)
   399  	RET
   400  
   401  CALLFN(·call32, 32)
   402  CALLFN(·call64, 64)
   403  CALLFN(·call128, 128)
   404  CALLFN(·call256, 256)
   405  CALLFN(·call512, 512)
   406  CALLFN(·call1024, 1024)
   407  CALLFN(·call2048, 2048)
   408  CALLFN(·call4096, 4096)
   409  CALLFN(·call8192, 8192)
   410  CALLFN(·call16384, 16384)
   411  CALLFN(·call32768, 32768)
   412  CALLFN(·call65536, 65536)
   413  CALLFN(·call131072, 131072)
   414  CALLFN(·call262144, 262144)
   415  CALLFN(·call524288, 524288)
   416  CALLFN(·call1048576, 1048576)
   417  CALLFN(·call2097152, 2097152)
   418  CALLFN(·call4194304, 4194304)
   419  CALLFN(·call8388608, 8388608)
   420  CALLFN(·call16777216, 16777216)
   421  CALLFN(·call33554432, 33554432)
   422  CALLFN(·call67108864, 67108864)
   423  CALLFN(·call134217728, 134217728)
   424  CALLFN(·call268435456, 268435456)
   425  CALLFN(·call536870912, 536870912)
   426  CALLFN(·call1073741824, 1073741824)
   427  
   428  TEXT runtime·goexit(SB), NOSPLIT, $0-0
   429  	NOP // first PC of goexit is skipped
   430  	CALL runtime·goexit1(SB) // does not return
   431  	UNDEF
   432  
   433  TEXT runtime·cgocallback(SB), NOSPLIT, $32-32
   434  	UNDEF
   435  
   436  // gcWriteBarrier performs a heap pointer write and informs the GC.
   437  //
   438  // gcWriteBarrier does NOT follow the Go ABI. It has two WebAssembly parameters:
   439  // R0: the destination of the write (i64)
   440  // R1: the value being written (i64)
   441  TEXT runtime·gcWriteBarrier(SB), NOSPLIT, $16
   442  	// R3 = g.m
   443  	MOVD g_m(g), R3
   444  	// R4 = p
   445  	MOVD m_p(R3), R4
   446  	// R5 = wbBuf.next
   447  	MOVD p_wbBuf+wbBuf_next(R4), R5
   448  
   449  	// Record value
   450  	MOVD R1, 0(R5)
   451  	// Record *slot
   452  	MOVD (R0), 8(R5)
   453  
   454  	// Increment wbBuf.next
   455  	Get R5
   456  	I64Const $16
   457  	I64Add
   458  	Set R5
   459  	MOVD R5, p_wbBuf+wbBuf_next(R4)
   460  
   461  	Get R5
   462  	I64Load (p_wbBuf+wbBuf_end)(R4)
   463  	I64Eq
   464  	If
   465  		// Flush
   466  		MOVD R0, 0(SP)
   467  		MOVD R1, 8(SP)
   468  		CALLNORESUME runtime·wbBufFlush(SB)
   469  	End
   470  
   471  	// Do the write
   472  	MOVD R1, (R0)
   473  
   474  	RET