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