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