github.com/lzhfromustc/gofuzz@v0.0.0-20211116160056-151b3108bbd1/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<ABIInternal>(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  #define DISPATCH(NAME, MAXSIZE) \
   292  	Get R0; \
   293  	I64Const $MAXSIZE; \
   294  	I64LeU; \
   295  	If; \
   296  		JMP NAME(SB); \
   297  	End
   298  
   299  TEXT ·reflectcall(SB), NOSPLIT, $0-32
   300  	I64Load fn+8(FP)
   301  	I64Eqz
   302  	If
   303  		CALLNORESUME runtime·sigpanic<ABIInternal>(SB)
   304  	End
   305  
   306  	MOVW argsize+24(FP), R0
   307  
   308  	DISPATCH(runtime·call16, 16)
   309  	DISPATCH(runtime·call32, 32)
   310  	DISPATCH(runtime·call64, 64)
   311  	DISPATCH(runtime·call128, 128)
   312  	DISPATCH(runtime·call256, 256)
   313  	DISPATCH(runtime·call512, 512)
   314  	DISPATCH(runtime·call1024, 1024)
   315  	DISPATCH(runtime·call2048, 2048)
   316  	DISPATCH(runtime·call4096, 4096)
   317  	DISPATCH(runtime·call8192, 8192)
   318  	DISPATCH(runtime·call16384, 16384)
   319  	DISPATCH(runtime·call32768, 32768)
   320  	DISPATCH(runtime·call65536, 65536)
   321  	DISPATCH(runtime·call131072, 131072)
   322  	DISPATCH(runtime·call262144, 262144)
   323  	DISPATCH(runtime·call524288, 524288)
   324  	DISPATCH(runtime·call1048576, 1048576)
   325  	DISPATCH(runtime·call2097152, 2097152)
   326  	DISPATCH(runtime·call4194304, 4194304)
   327  	DISPATCH(runtime·call8388608, 8388608)
   328  	DISPATCH(runtime·call16777216, 16777216)
   329  	DISPATCH(runtime·call33554432, 33554432)
   330  	DISPATCH(runtime·call67108864, 67108864)
   331  	DISPATCH(runtime·call134217728, 134217728)
   332  	DISPATCH(runtime·call268435456, 268435456)
   333  	DISPATCH(runtime·call536870912, 536870912)
   334  	DISPATCH(runtime·call1073741824, 1073741824)
   335  	JMP runtime·badreflectcall(SB)
   336  
   337  #define CALLFN(NAME, MAXSIZE) \
   338  TEXT NAME(SB), WRAPPER, $MAXSIZE-32; \
   339  	NO_LOCAL_POINTERS; \
   340  	MOVW argsize+24(FP), R0; \
   341  	\
   342  	Get R0; \
   343  	I64Eqz; \
   344  	Not; \
   345  	If; \
   346  		Get SP; \
   347  		I64Load argptr+16(FP); \
   348  		I32WrapI64; \
   349  		I64Load argsize+24(FP); \
   350  		I64Const $3; \
   351  		I64ShrU; \
   352  		I32WrapI64; \
   353  		Call runtime·wasmMove(SB); \
   354  	End; \
   355  	\
   356  	MOVD f+8(FP), CTXT; \
   357  	Get CTXT; \
   358  	I32WrapI64; \
   359  	I64Load $0; \
   360  	CALL; \
   361  	\
   362  	I64Load32U retoffset+28(FP); \
   363  	Set R0; \
   364  	\
   365  	MOVD argtype+0(FP), RET0; \
   366  	\
   367  	I64Load argptr+16(FP); \
   368  	Get R0; \
   369  	I64Add; \
   370  	Set RET1; \
   371  	\
   372  	Get SP; \
   373  	I64ExtendI32U; \
   374  	Get R0; \
   375  	I64Add; \
   376  	Set RET2; \
   377  	\
   378  	I64Load32U argsize+24(FP); \
   379  	Get R0; \
   380  	I64Sub; \
   381  	Set RET3; \
   382  	\
   383  	CALL callRet<>(SB); \
   384  	RET
   385  
   386  // callRet copies return values back at the end of call*. This is a
   387  // separate function so it can allocate stack space for the arguments
   388  // to reflectcallmove. It does not follow the Go ABI; it expects its
   389  // arguments in registers.
   390  TEXT callRet<>(SB), NOSPLIT, $32-0
   391  	NO_LOCAL_POINTERS
   392  	MOVD RET0, 0(SP)
   393  	MOVD RET1, 8(SP)
   394  	MOVD RET2, 16(SP)
   395  	MOVD RET3, 24(SP)
   396  	CALL runtime·reflectcallmove(SB)
   397  	RET
   398  
   399  CALLFN(·call16, 16)
   400  CALLFN(·call32, 32)
   401  CALLFN(·call64, 64)
   402  CALLFN(·call128, 128)
   403  CALLFN(·call256, 256)
   404  CALLFN(·call512, 512)
   405  CALLFN(·call1024, 1024)
   406  CALLFN(·call2048, 2048)
   407  CALLFN(·call4096, 4096)
   408  CALLFN(·call8192, 8192)
   409  CALLFN(·call16384, 16384)
   410  CALLFN(·call32768, 32768)
   411  CALLFN(·call65536, 65536)
   412  CALLFN(·call131072, 131072)
   413  CALLFN(·call262144, 262144)
   414  CALLFN(·call524288, 524288)
   415  CALLFN(·call1048576, 1048576)
   416  CALLFN(·call2097152, 2097152)
   417  CALLFN(·call4194304, 4194304)
   418  CALLFN(·call8388608, 8388608)
   419  CALLFN(·call16777216, 16777216)
   420  CALLFN(·call33554432, 33554432)
   421  CALLFN(·call67108864, 67108864)
   422  CALLFN(·call134217728, 134217728)
   423  CALLFN(·call268435456, 268435456)
   424  CALLFN(·call536870912, 536870912)
   425  CALLFN(·call1073741824, 1073741824)
   426  
   427  TEXT runtime·goexit(SB), NOSPLIT, $0-0
   428  	NOP // first PC of goexit is skipped
   429  	CALL runtime·goexit1(SB) // does not return
   430  	UNDEF
   431  
   432  TEXT runtime·cgocallback(SB), NOSPLIT, $0-24
   433  	UNDEF
   434  
   435  // gcWriteBarrier performs a heap pointer write and informs the GC.
   436  //
   437  // gcWriteBarrier does NOT follow the Go ABI. It has two WebAssembly parameters:
   438  // R0: the destination of the write (i64)
   439  // R1: the value being written (i64)
   440  TEXT runtime·gcWriteBarrier(SB), NOSPLIT, $16
   441  	// R3 = g.m
   442  	MOVD g_m(g), R3
   443  	// R4 = p
   444  	MOVD m_p(R3), R4
   445  	// R5 = wbBuf.next
   446  	MOVD p_wbBuf+wbBuf_next(R4), R5
   447  
   448  	// Record value
   449  	MOVD R1, 0(R5)
   450  	// Record *slot
   451  	MOVD (R0), 8(R5)
   452  
   453  	// Increment wbBuf.next
   454  	Get R5
   455  	I64Const $16
   456  	I64Add
   457  	Set R5
   458  	MOVD R5, p_wbBuf+wbBuf_next(R4)
   459  
   460  	Get R5
   461  	I64Load (p_wbBuf+wbBuf_end)(R4)
   462  	I64Eq
   463  	If
   464  		// Flush
   465  		MOVD R0, 0(SP)
   466  		MOVD R1, 8(SP)
   467  		CALLNORESUME runtime·wbBufFlush(SB)
   468  	End
   469  
   470  	// Do the write
   471  	MOVD R1, (R0)
   472  
   473  	RET