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