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