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