github.com/ice-blockchain/go/src@v0.0.0-20240403114104-1564d284e521/runtime/asm_arm.s (about) 1 // Copyright 2009 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 // _rt0_arm is common startup code for most ARM systems when using 11 // internal linking. This is the entry point for the program from the 12 // kernel for an ordinary -buildmode=exe program. The stack holds the 13 // number of arguments and the C-style argv. 14 TEXT _rt0_arm(SB),NOSPLIT|NOFRAME,$0 15 MOVW (R13), R0 // argc 16 MOVW $4(R13), R1 // argv 17 B runtime·rt0_go(SB) 18 19 // main is common startup code for most ARM systems when using 20 // external linking. The C startup code will call the symbol "main" 21 // passing argc and argv in the usual C ABI registers R0 and R1. 22 TEXT main(SB),NOSPLIT|NOFRAME,$0 23 B runtime·rt0_go(SB) 24 25 // _rt0_arm_lib is common startup code for most ARM systems when 26 // using -buildmode=c-archive or -buildmode=c-shared. The linker will 27 // arrange to invoke this function as a global constructor (for 28 // c-archive) or when the shared library is loaded (for c-shared). 29 // We expect argc and argv to be passed in the usual C ABI registers 30 // R0 and R1. 31 TEXT _rt0_arm_lib(SB),NOSPLIT,$104 32 // Preserve callee-save registers. Raspberry Pi's dlopen(), for example, 33 // actually cares that R11 is preserved. 34 MOVW R4, 12(R13) 35 MOVW R5, 16(R13) 36 MOVW R6, 20(R13) 37 MOVW R7, 24(R13) 38 MOVW R8, 28(R13) 39 MOVW g, 32(R13) 40 MOVW R11, 36(R13) 41 42 // Skip floating point registers on goarmsoftfp != 0. 43 MOVB runtime·goarmsoftfp(SB), R11 44 CMP $0, R11 45 BNE skipfpsave 46 MOVD F8, (40+8*0)(R13) 47 MOVD F9, (40+8*1)(R13) 48 MOVD F10, (40+8*2)(R13) 49 MOVD F11, (40+8*3)(R13) 50 MOVD F12, (40+8*4)(R13) 51 MOVD F13, (40+8*5)(R13) 52 MOVD F14, (40+8*6)(R13) 53 MOVD F15, (40+8*7)(R13) 54 skipfpsave: 55 // Save argc/argv. 56 MOVW R0, _rt0_arm_lib_argc<>(SB) 57 MOVW R1, _rt0_arm_lib_argv<>(SB) 58 59 MOVW $0, g // Initialize g. 60 61 // Synchronous initialization. 62 CALL runtime·libpreinit(SB) 63 64 // Create a new thread to do the runtime initialization. 65 MOVW _cgo_sys_thread_create(SB), R2 66 CMP $0, R2 67 BEQ nocgo 68 MOVW $_rt0_arm_lib_go<>(SB), R0 69 MOVW $0, R1 70 BL (R2) 71 B rr 72 nocgo: 73 MOVW $0x800000, R0 // stacksize = 8192KB 74 MOVW $_rt0_arm_lib_go<>(SB), R1 // fn 75 MOVW R0, 4(R13) 76 MOVW R1, 8(R13) 77 BL runtime·newosproc0(SB) 78 rr: 79 // Restore callee-save registers and return. 80 MOVB runtime·goarmsoftfp(SB), R11 81 CMP $0, R11 82 BNE skipfprest 83 MOVD (40+8*0)(R13), F8 84 MOVD (40+8*1)(R13), F9 85 MOVD (40+8*2)(R13), F10 86 MOVD (40+8*3)(R13), F11 87 MOVD (40+8*4)(R13), F12 88 MOVD (40+8*5)(R13), F13 89 MOVD (40+8*6)(R13), F14 90 MOVD (40+8*7)(R13), F15 91 skipfprest: 92 MOVW 12(R13), R4 93 MOVW 16(R13), R5 94 MOVW 20(R13), R6 95 MOVW 24(R13), R7 96 MOVW 28(R13), R8 97 MOVW 32(R13), g 98 MOVW 36(R13), R11 99 RET 100 101 // _rt0_arm_lib_go initializes the Go runtime. 102 // This is started in a separate thread by _rt0_arm_lib. 103 TEXT _rt0_arm_lib_go<>(SB),NOSPLIT,$8 104 MOVW _rt0_arm_lib_argc<>(SB), R0 105 MOVW _rt0_arm_lib_argv<>(SB), R1 106 B runtime·rt0_go(SB) 107 108 DATA _rt0_arm_lib_argc<>(SB)/4,$0 109 GLOBL _rt0_arm_lib_argc<>(SB),NOPTR,$4 110 DATA _rt0_arm_lib_argv<>(SB)/4,$0 111 GLOBL _rt0_arm_lib_argv<>(SB),NOPTR,$4 112 113 // using NOFRAME means do not save LR on stack. 114 // argc is in R0, argv is in R1. 115 TEXT runtime·rt0_go(SB),NOSPLIT|NOFRAME|TOPFRAME,$0 116 MOVW $0xcafebabe, R12 117 118 // copy arguments forward on an even stack 119 // use R13 instead of SP to avoid linker rewriting the offsets 120 SUB $64, R13 // plenty of scratch 121 AND $~7, R13 122 MOVW R0, 60(R13) // save argc, argv away 123 MOVW R1, 64(R13) 124 125 // set up g register 126 // g is R10 127 MOVW $runtime·g0(SB), g 128 MOVW $runtime·m0(SB), R8 129 130 // save m->g0 = g0 131 MOVW g, m_g0(R8) 132 // save g->m = m0 133 MOVW R8, g_m(g) 134 135 // create istack out of the OS stack 136 // (1MB of system stack is available on iOS and Android) 137 MOVW $(-64*1024+104)(R13), R0 138 MOVW R0, g_stackguard0(g) 139 MOVW R0, g_stackguard1(g) 140 MOVW R0, (g_stack+stack_lo)(g) 141 MOVW R13, (g_stack+stack_hi)(g) 142 143 BL runtime·emptyfunc(SB) // fault if stack check is wrong 144 145 #ifdef GOOS_openbsd 146 // Save g to TLS so that it is available from signal trampoline. 147 BL runtime·save_g(SB) 148 #endif 149 150 BL runtime·_initcgo(SB) // will clobber R0-R3 151 152 // update stackguard after _cgo_init 153 MOVW (g_stack+stack_lo)(g), R0 154 ADD $const_stackGuard, R0 155 MOVW R0, g_stackguard0(g) 156 MOVW R0, g_stackguard1(g) 157 158 BL runtime·check(SB) 159 160 // saved argc, argv 161 MOVW 60(R13), R0 162 MOVW R0, 4(R13) 163 MOVW 64(R13), R1 164 MOVW R1, 8(R13) 165 BL runtime·args(SB) 166 BL runtime·checkgoarm(SB) 167 BL runtime·osinit(SB) 168 BL runtime·schedinit(SB) 169 170 // create a new goroutine to start program 171 SUB $8, R13 172 MOVW $runtime·mainPC(SB), R0 173 MOVW R0, 4(R13) // arg 1: fn 174 MOVW $0, R0 175 MOVW R0, 0(R13) // dummy LR 176 BL runtime·newproc(SB) 177 ADD $8, R13 // pop args and LR 178 179 // start this M 180 BL runtime·mstart(SB) 181 182 MOVW $1234, R0 183 MOVW $1000, R1 184 MOVW R0, (R1) // fail hard 185 186 DATA runtime·mainPC+0(SB)/4,$runtime·main(SB) 187 GLOBL runtime·mainPC(SB),RODATA,$4 188 189 TEXT runtime·breakpoint(SB),NOSPLIT,$0-0 190 // gdb won't skip this breakpoint instruction automatically, 191 // so you must manually "set $pc+=4" to skip it and continue. 192 #ifdef GOOS_plan9 193 WORD $0xD1200070 // undefined instruction used as armv5 breakpoint in Plan 9 194 #else 195 WORD $0xe7f001f0 // undefined instruction that gdb understands is a software breakpoint 196 #endif 197 RET 198 199 TEXT runtime·asminit(SB),NOSPLIT,$0-0 200 // disable runfast (flush-to-zero) mode of vfp if runtime.goarmsoftfp == 0 201 MOVB runtime·goarmsoftfp(SB), R11 202 CMP $0, R11 203 BNE 4(PC) 204 WORD $0xeef1ba10 // vmrs r11, fpscr 205 BIC $(1<<24), R11 206 WORD $0xeee1ba10 // vmsr fpscr, r11 207 RET 208 209 TEXT runtime·mstart(SB),NOSPLIT|TOPFRAME,$0 210 BL runtime·mstart0(SB) 211 RET // not reached 212 213 /* 214 * go-routine 215 */ 216 217 // void gogo(Gobuf*) 218 // restore state from Gobuf; longjmp 219 TEXT runtime·gogo(SB),NOSPLIT|NOFRAME,$0-4 220 MOVW buf+0(FP), R1 221 MOVW gobuf_g(R1), R0 222 MOVW 0(R0), R2 // make sure g != nil 223 B gogo<>(SB) 224 225 TEXT gogo<>(SB),NOSPLIT|NOFRAME,$0 226 BL setg<>(SB) 227 MOVW gobuf_sp(R1), R13 // restore SP==R13 228 MOVW gobuf_lr(R1), LR 229 MOVW gobuf_ret(R1), R0 230 MOVW gobuf_ctxt(R1), R7 231 MOVW $0, R11 232 MOVW R11, gobuf_sp(R1) // clear to help garbage collector 233 MOVW R11, gobuf_ret(R1) 234 MOVW R11, gobuf_lr(R1) 235 MOVW R11, gobuf_ctxt(R1) 236 MOVW gobuf_pc(R1), R11 237 CMP R11, R11 // set condition codes for == test, needed by stack split 238 B (R11) 239 240 // func mcall(fn func(*g)) 241 // Switch to m->g0's stack, call fn(g). 242 // Fn must never return. It should gogo(&g->sched) 243 // to keep running g. 244 TEXT runtime·mcall(SB),NOSPLIT|NOFRAME,$0-4 245 // Save caller state in g->sched. 246 MOVW R13, (g_sched+gobuf_sp)(g) 247 MOVW LR, (g_sched+gobuf_pc)(g) 248 MOVW $0, R11 249 MOVW R11, (g_sched+gobuf_lr)(g) 250 251 // Switch to m->g0 & its stack, call fn. 252 MOVW g, R1 253 MOVW g_m(g), R8 254 MOVW m_g0(R8), R0 255 BL setg<>(SB) 256 CMP g, R1 257 B.NE 2(PC) 258 B runtime·badmcall(SB) 259 MOVW fn+0(FP), R0 260 MOVW (g_sched+gobuf_sp)(g), R13 261 SUB $8, R13 262 MOVW R1, 4(R13) 263 MOVW R0, R7 264 MOVW 0(R0), R0 265 BL (R0) 266 B runtime·badmcall2(SB) 267 RET 268 269 // systemstack_switch is a dummy routine that systemstack leaves at the bottom 270 // of the G stack. We need to distinguish the routine that 271 // lives at the bottom of the G stack from the one that lives 272 // at the top of the system stack because the one at the top of 273 // the system stack terminates the stack walk (see topofstack()). 274 TEXT runtime·systemstack_switch(SB),NOSPLIT,$0-0 275 MOVW $0, R0 276 BL (R0) // clobber lr to ensure push {lr} is kept 277 RET 278 279 // func systemstack(fn func()) 280 TEXT runtime·systemstack(SB),NOSPLIT,$0-4 281 MOVW fn+0(FP), R0 // R0 = fn 282 MOVW g_m(g), R1 // R1 = m 283 284 MOVW m_gsignal(R1), R2 // R2 = gsignal 285 CMP g, R2 286 B.EQ noswitch 287 288 MOVW m_g0(R1), R2 // R2 = g0 289 CMP g, R2 290 B.EQ noswitch 291 292 MOVW m_curg(R1), R3 293 CMP g, R3 294 B.EQ switch 295 296 // Bad: g is not gsignal, not g0, not curg. What is it? 297 // Hide call from linker nosplit analysis. 298 MOVW $runtime·badsystemstack(SB), R0 299 BL (R0) 300 B runtime·abort(SB) 301 302 switch: 303 // save our state in g->sched. Pretend to 304 // be systemstack_switch if the G stack is scanned. 305 BL gosave_systemstack_switch<>(SB) 306 307 // switch to g0 308 MOVW R0, R5 309 MOVW R2, R0 310 BL setg<>(SB) 311 MOVW R5, R0 312 MOVW (g_sched+gobuf_sp)(R2), R13 313 314 // call target function 315 MOVW R0, R7 316 MOVW 0(R0), R0 317 BL (R0) 318 319 // switch back to g 320 MOVW g_m(g), R1 321 MOVW m_curg(R1), R0 322 BL setg<>(SB) 323 MOVW (g_sched+gobuf_sp)(g), R13 324 MOVW $0, R3 325 MOVW R3, (g_sched+gobuf_sp)(g) 326 RET 327 328 noswitch: 329 // Using a tail call here cleans up tracebacks since we won't stop 330 // at an intermediate systemstack. 331 MOVW R0, R7 332 MOVW 0(R0), R0 333 MOVW.P 4(R13), R14 // restore LR 334 B (R0) 335 336 // func switchToCrashStack0(fn func()) 337 TEXT runtime·switchToCrashStack0(SB), NOSPLIT, $0-4 338 MOVW fn+0(FP), R7 // context register 339 MOVW g_m(g), R1 // curm 340 341 // set g to gcrash 342 MOVW $runtime·gcrash(SB), R0 343 BL setg<>(SB) // g = &gcrash 344 MOVW R1, g_m(g) // g.m = curm 345 MOVW g, m_g0(R1) // curm.g0 = g 346 347 // switch to crashstack 348 MOVW (g_stack+stack_hi)(g), R1 349 SUB $(4*8), R1 350 MOVW R1, R13 351 352 // call target function 353 MOVW 0(R7), R0 354 BL (R0) 355 356 // should never return 357 CALL runtime·abort(SB) 358 UNDEF 359 360 /* 361 * support for morestack 362 */ 363 364 // Called during function prolog when more stack is needed. 365 // R3 prolog's LR 366 // using NOFRAME means do not save LR on stack. 367 // 368 // The traceback routines see morestack on a g0 as being 369 // the top of a stack (for example, morestack calling newstack 370 // calling the scheduler calling newm calling gc), so we must 371 // record an argument size. For that purpose, it has no arguments. 372 TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0 373 // Cannot grow scheduler stack (m->g0). 374 MOVW g_m(g), R8 375 MOVW m_g0(R8), R4 376 377 // Called from f. 378 // Set g->sched to context in f. 379 MOVW R13, (g_sched+gobuf_sp)(g) 380 MOVW LR, (g_sched+gobuf_pc)(g) 381 MOVW R3, (g_sched+gobuf_lr)(g) 382 MOVW R7, (g_sched+gobuf_ctxt)(g) 383 384 CMP g, R4 385 BNE 3(PC) 386 BL runtime·badmorestackg0(SB) 387 B runtime·abort(SB) 388 389 // Cannot grow signal stack (m->gsignal). 390 MOVW m_gsignal(R8), R4 391 CMP g, R4 392 BNE 3(PC) 393 BL runtime·badmorestackgsignal(SB) 394 B runtime·abort(SB) 395 396 // Called from f. 397 // Set m->morebuf to f's caller. 398 MOVW R3, (m_morebuf+gobuf_pc)(R8) // f's caller's PC 399 MOVW R13, (m_morebuf+gobuf_sp)(R8) // f's caller's SP 400 MOVW g, (m_morebuf+gobuf_g)(R8) 401 402 // Call newstack on m->g0's stack. 403 MOVW m_g0(R8), R0 404 BL setg<>(SB) 405 MOVW (g_sched+gobuf_sp)(g), R13 406 MOVW $0, R0 407 MOVW.W R0, -4(R13) // create a call frame on g0 (saved LR) 408 BL runtime·newstack(SB) 409 410 // Not reached, but make sure the return PC from the call to newstack 411 // is still in this function, and not the beginning of the next. 412 RET 413 414 TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0 415 // Force SPWRITE. This function doesn't actually write SP, 416 // but it is called with a special calling convention where 417 // the caller doesn't save LR on stack but passes it as a 418 // register (R3), and the unwinder currently doesn't understand. 419 // Make it SPWRITE to stop unwinding. (See issue 54332) 420 MOVW R13, R13 421 422 MOVW $0, R7 423 B runtime·morestack(SB) 424 425 // reflectcall: call a function with the given argument list 426 // func call(stackArgsType *_type, f *FuncVal, stackArgs *byte, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs). 427 // we don't have variable-sized frames, so we use a small number 428 // of constant-sized-frame functions to encode a few bits of size in the pc. 429 // Caution: ugly multiline assembly macros in your future! 430 431 #define DISPATCH(NAME,MAXSIZE) \ 432 CMP $MAXSIZE, R0; \ 433 B.HI 3(PC); \ 434 MOVW $NAME(SB), R1; \ 435 B (R1) 436 437 TEXT ·reflectcall(SB),NOSPLIT|NOFRAME,$0-28 438 MOVW frameSize+20(FP), R0 439 DISPATCH(runtime·call16, 16) 440 DISPATCH(runtime·call32, 32) 441 DISPATCH(runtime·call64, 64) 442 DISPATCH(runtime·call128, 128) 443 DISPATCH(runtime·call256, 256) 444 DISPATCH(runtime·call512, 512) 445 DISPATCH(runtime·call1024, 1024) 446 DISPATCH(runtime·call2048, 2048) 447 DISPATCH(runtime·call4096, 4096) 448 DISPATCH(runtime·call8192, 8192) 449 DISPATCH(runtime·call16384, 16384) 450 DISPATCH(runtime·call32768, 32768) 451 DISPATCH(runtime·call65536, 65536) 452 DISPATCH(runtime·call131072, 131072) 453 DISPATCH(runtime·call262144, 262144) 454 DISPATCH(runtime·call524288, 524288) 455 DISPATCH(runtime·call1048576, 1048576) 456 DISPATCH(runtime·call2097152, 2097152) 457 DISPATCH(runtime·call4194304, 4194304) 458 DISPATCH(runtime·call8388608, 8388608) 459 DISPATCH(runtime·call16777216, 16777216) 460 DISPATCH(runtime·call33554432, 33554432) 461 DISPATCH(runtime·call67108864, 67108864) 462 DISPATCH(runtime·call134217728, 134217728) 463 DISPATCH(runtime·call268435456, 268435456) 464 DISPATCH(runtime·call536870912, 536870912) 465 DISPATCH(runtime·call1073741824, 1073741824) 466 MOVW $runtime·badreflectcall(SB), R1 467 B (R1) 468 469 #define CALLFN(NAME,MAXSIZE) \ 470 TEXT NAME(SB), WRAPPER, $MAXSIZE-28; \ 471 NO_LOCAL_POINTERS; \ 472 /* copy arguments to stack */ \ 473 MOVW stackArgs+8(FP), R0; \ 474 MOVW stackArgsSize+12(FP), R2; \ 475 ADD $4, R13, R1; \ 476 CMP $0, R2; \ 477 B.EQ 5(PC); \ 478 MOVBU.P 1(R0), R5; \ 479 MOVBU.P R5, 1(R1); \ 480 SUB $1, R2, R2; \ 481 B -5(PC); \ 482 /* call function */ \ 483 MOVW f+4(FP), R7; \ 484 MOVW (R7), R0; \ 485 PCDATA $PCDATA_StackMapIndex, $0; \ 486 BL (R0); \ 487 /* copy return values back */ \ 488 MOVW stackArgsType+0(FP), R4; \ 489 MOVW stackArgs+8(FP), R0; \ 490 MOVW stackArgsSize+12(FP), R2; \ 491 MOVW stackArgsRetOffset+16(FP), R3; \ 492 ADD $4, R13, R1; \ 493 ADD R3, R1; \ 494 ADD R3, R0; \ 495 SUB R3, R2; \ 496 BL callRet<>(SB); \ 497 RET 498 499 // callRet copies return values back at the end of call*. This is a 500 // separate function so it can allocate stack space for the arguments 501 // to reflectcallmove. It does not follow the Go ABI; it expects its 502 // arguments in registers. 503 TEXT callRet<>(SB), NOSPLIT, $20-0 504 MOVW R4, 4(R13) 505 MOVW R0, 8(R13) 506 MOVW R1, 12(R13) 507 MOVW R2, 16(R13) 508 MOVW $0, R7 509 MOVW R7, 20(R13) 510 BL runtime·reflectcallmove(SB) 511 RET 512 513 CALLFN(·call16, 16) 514 CALLFN(·call32, 32) 515 CALLFN(·call64, 64) 516 CALLFN(·call128, 128) 517 CALLFN(·call256, 256) 518 CALLFN(·call512, 512) 519 CALLFN(·call1024, 1024) 520 CALLFN(·call2048, 2048) 521 CALLFN(·call4096, 4096) 522 CALLFN(·call8192, 8192) 523 CALLFN(·call16384, 16384) 524 CALLFN(·call32768, 32768) 525 CALLFN(·call65536, 65536) 526 CALLFN(·call131072, 131072) 527 CALLFN(·call262144, 262144) 528 CALLFN(·call524288, 524288) 529 CALLFN(·call1048576, 1048576) 530 CALLFN(·call2097152, 2097152) 531 CALLFN(·call4194304, 4194304) 532 CALLFN(·call8388608, 8388608) 533 CALLFN(·call16777216, 16777216) 534 CALLFN(·call33554432, 33554432) 535 CALLFN(·call67108864, 67108864) 536 CALLFN(·call134217728, 134217728) 537 CALLFN(·call268435456, 268435456) 538 CALLFN(·call536870912, 536870912) 539 CALLFN(·call1073741824, 1073741824) 540 541 // Save state of caller into g->sched, 542 // but using fake PC from systemstack_switch. 543 // Must only be called from functions with no locals ($0) 544 // or else unwinding from systemstack_switch is incorrect. 545 // Smashes R11. 546 TEXT gosave_systemstack_switch<>(SB),NOSPLIT|NOFRAME,$0 547 MOVW $runtime·systemstack_switch(SB), R11 548 ADD $4, R11 // get past push {lr} 549 MOVW R11, (g_sched+gobuf_pc)(g) 550 MOVW R13, (g_sched+gobuf_sp)(g) 551 MOVW $0, R11 552 MOVW R11, (g_sched+gobuf_lr)(g) 553 MOVW R11, (g_sched+gobuf_ret)(g) 554 // Assert ctxt is zero. See func save. 555 MOVW (g_sched+gobuf_ctxt)(g), R11 556 TST R11, R11 557 B.EQ 2(PC) 558 BL runtime·abort(SB) 559 RET 560 561 // func asmcgocall_no_g(fn, arg unsafe.Pointer) 562 // Call fn(arg) aligned appropriately for the gcc ABI. 563 // Called on a system stack, and there may be no g yet (during needm). 564 TEXT ·asmcgocall_no_g(SB),NOSPLIT,$0-8 565 MOVW fn+0(FP), R1 566 MOVW arg+4(FP), R0 567 MOVW R13, R2 568 SUB $32, R13 569 BIC $0x7, R13 // alignment for gcc ABI 570 MOVW R2, 8(R13) 571 BL (R1) 572 MOVW 8(R13), R2 573 MOVW R2, R13 574 RET 575 576 // func asmcgocall(fn, arg unsafe.Pointer) int32 577 // Call fn(arg) on the scheduler stack, 578 // aligned appropriately for the gcc ABI. 579 // See cgocall.go for more details. 580 TEXT ·asmcgocall(SB),NOSPLIT,$0-12 581 MOVW fn+0(FP), R1 582 MOVW arg+4(FP), R0 583 584 MOVW R13, R2 585 CMP $0, g 586 BEQ nosave 587 MOVW g, R4 588 589 // Figure out if we need to switch to m->g0 stack. 590 // We get called to create new OS threads too, and those 591 // come in on the m->g0 stack already. Or we might already 592 // be on the m->gsignal stack. 593 MOVW g_m(g), R8 594 MOVW m_gsignal(R8), R3 595 CMP R3, g 596 BEQ nosave 597 MOVW m_g0(R8), R3 598 CMP R3, g 599 BEQ nosave 600 BL gosave_systemstack_switch<>(SB) 601 MOVW R0, R5 602 MOVW R3, R0 603 BL setg<>(SB) 604 MOVW R5, R0 605 MOVW (g_sched+gobuf_sp)(g), R13 606 607 // Now on a scheduling stack (a pthread-created stack). 608 SUB $24, R13 609 BIC $0x7, R13 // alignment for gcc ABI 610 MOVW R4, 20(R13) // save old g 611 MOVW (g_stack+stack_hi)(R4), R4 612 SUB R2, R4 613 MOVW R4, 16(R13) // save depth in stack (can't just save SP, as stack might be copied during a callback) 614 BL (R1) 615 616 // Restore registers, g, stack pointer. 617 MOVW R0, R5 618 MOVW 20(R13), R0 619 BL setg<>(SB) 620 MOVW (g_stack+stack_hi)(g), R1 621 MOVW 16(R13), R2 622 SUB R2, R1 623 MOVW R5, R0 624 MOVW R1, R13 625 626 MOVW R0, ret+8(FP) 627 RET 628 629 nosave: 630 // Running on a system stack, perhaps even without a g. 631 // Having no g can happen during thread creation or thread teardown 632 // (see needm/dropm on Solaris, for example). 633 // This code is like the above sequence but without saving/restoring g 634 // and without worrying about the stack moving out from under us 635 // (because we're on a system stack, not a goroutine stack). 636 // The above code could be used directly if already on a system stack, 637 // but then the only path through this code would be a rare case on Solaris. 638 // Using this code for all "already on system stack" calls exercises it more, 639 // which should help keep it correct. 640 SUB $24, R13 641 BIC $0x7, R13 // alignment for gcc ABI 642 // save null g in case someone looks during debugging. 643 MOVW $0, R4 644 MOVW R4, 20(R13) 645 MOVW R2, 16(R13) // Save old stack pointer. 646 BL (R1) 647 // Restore stack pointer. 648 MOVW 16(R13), R2 649 MOVW R2, R13 650 MOVW R0, ret+8(FP) 651 RET 652 653 // cgocallback(fn, frame unsafe.Pointer, ctxt uintptr) 654 // See cgocall.go for more details. 655 TEXT ·cgocallback(SB),NOSPLIT,$12-12 656 NO_LOCAL_POINTERS 657 658 // Skip cgocallbackg, just dropm when fn is nil, and frame is the saved g. 659 // It is used to dropm while thread is exiting. 660 MOVW fn+0(FP), R1 661 CMP $0, R1 662 B.NE loadg 663 // Restore the g from frame. 664 MOVW frame+4(FP), g 665 B dropm 666 667 loadg: 668 // Load m and g from thread-local storage. 669 #ifdef GOOS_openbsd 670 BL runtime·load_g(SB) 671 #else 672 MOVB runtime·iscgo(SB), R0 673 CMP $0, R0 674 BL.NE runtime·load_g(SB) 675 #endif 676 677 // If g is nil, Go did not create the current thread, 678 // or if this thread never called into Go on pthread platforms. 679 // Call needm to obtain one for temporary use. 680 // In this case, we're running on the thread stack, so there's 681 // lots of space, but the linker doesn't know. Hide the call from 682 // the linker analysis by using an indirect call. 683 CMP $0, g 684 B.EQ needm 685 686 MOVW g_m(g), R8 687 MOVW R8, savedm-4(SP) 688 B havem 689 690 needm: 691 MOVW g, savedm-4(SP) // g is zero, so is m. 692 MOVW $runtime·needAndBindM(SB), R0 693 BL (R0) 694 695 // Set m->g0->sched.sp = SP, so that if a panic happens 696 // during the function we are about to execute, it will 697 // have a valid SP to run on the g0 stack. 698 // The next few lines (after the havem label) 699 // will save this SP onto the stack and then write 700 // the same SP back to m->sched.sp. That seems redundant, 701 // but if an unrecovered panic happens, unwindm will 702 // restore the g->sched.sp from the stack location 703 // and then systemstack will try to use it. If we don't set it here, 704 // that restored SP will be uninitialized (typically 0) and 705 // will not be usable. 706 MOVW g_m(g), R8 707 MOVW m_g0(R8), R3 708 MOVW R13, (g_sched+gobuf_sp)(R3) 709 710 havem: 711 // Now there's a valid m, and we're running on its m->g0. 712 // Save current m->g0->sched.sp on stack and then set it to SP. 713 // Save current sp in m->g0->sched.sp in preparation for 714 // switch back to m->curg stack. 715 // NOTE: unwindm knows that the saved g->sched.sp is at 4(R13) aka savedsp-12(SP). 716 MOVW m_g0(R8), R3 717 MOVW (g_sched+gobuf_sp)(R3), R4 718 MOVW R4, savedsp-12(SP) // must match frame size 719 MOVW R13, (g_sched+gobuf_sp)(R3) 720 721 // Switch to m->curg stack and call runtime.cgocallbackg. 722 // Because we are taking over the execution of m->curg 723 // but *not* resuming what had been running, we need to 724 // save that information (m->curg->sched) so we can restore it. 725 // We can restore m->curg->sched.sp easily, because calling 726 // runtime.cgocallbackg leaves SP unchanged upon return. 727 // To save m->curg->sched.pc, we push it onto the curg stack and 728 // open a frame the same size as cgocallback's g0 frame. 729 // Once we switch to the curg stack, the pushed PC will appear 730 // to be the return PC of cgocallback, so that the traceback 731 // will seamlessly trace back into the earlier calls. 732 MOVW m_curg(R8), R0 733 BL setg<>(SB) 734 MOVW (g_sched+gobuf_sp)(g), R4 // prepare stack as R4 735 MOVW (g_sched+gobuf_pc)(g), R5 736 MOVW R5, -(12+4)(R4) // "saved LR"; must match frame size 737 // Gather our arguments into registers. 738 MOVW fn+0(FP), R1 739 MOVW frame+4(FP), R2 740 MOVW ctxt+8(FP), R3 741 MOVW $-(12+4)(R4), R13 // switch stack; must match frame size 742 MOVW R1, 4(R13) 743 MOVW R2, 8(R13) 744 MOVW R3, 12(R13) 745 BL runtime·cgocallbackg(SB) 746 747 // Restore g->sched (== m->curg->sched) from saved values. 748 MOVW 0(R13), R5 749 MOVW R5, (g_sched+gobuf_pc)(g) 750 MOVW $(12+4)(R13), R4 // must match frame size 751 MOVW R4, (g_sched+gobuf_sp)(g) 752 753 // Switch back to m->g0's stack and restore m->g0->sched.sp. 754 // (Unlike m->curg, the g0 goroutine never uses sched.pc, 755 // so we do not have to restore it.) 756 MOVW g_m(g), R8 757 MOVW m_g0(R8), R0 758 BL setg<>(SB) 759 MOVW (g_sched+gobuf_sp)(g), R13 760 MOVW savedsp-12(SP), R4 // must match frame size 761 MOVW R4, (g_sched+gobuf_sp)(g) 762 763 // If the m on entry was nil, we called needm above to borrow an m, 764 // 1. for the duration of the call on non-pthread platforms, 765 // 2. or the duration of the C thread alive on pthread platforms. 766 // If the m on entry wasn't nil, 767 // 1. the thread might be a Go thread, 768 // 2. or it wasn't the first call from a C thread on pthread platforms, 769 // since then we skip dropm to reuse the m in the first call. 770 MOVW savedm-4(SP), R6 771 CMP $0, R6 772 B.NE done 773 774 // Skip dropm to reuse it in the next call, when a pthread key has been created. 775 MOVW _cgo_pthread_key_created(SB), R6 776 // It means cgo is disabled when _cgo_pthread_key_created is a nil pointer, need dropm. 777 CMP $0, R6 778 B.EQ dropm 779 MOVW (R6), R6 780 CMP $0, R6 781 B.NE done 782 783 dropm: 784 MOVW $runtime·dropm(SB), R0 785 BL (R0) 786 787 done: 788 // Done! 789 RET 790 791 // void setg(G*); set g. for use by needm. 792 TEXT runtime·setg(SB),NOSPLIT|NOFRAME,$0-4 793 MOVW gg+0(FP), R0 794 B setg<>(SB) 795 796 TEXT setg<>(SB),NOSPLIT|NOFRAME,$0-0 797 MOVW R0, g 798 799 // Save g to thread-local storage. 800 #ifdef GOOS_windows 801 B runtime·save_g(SB) 802 #else 803 #ifdef GOOS_openbsd 804 B runtime·save_g(SB) 805 #else 806 MOVB runtime·iscgo(SB), R0 807 CMP $0, R0 808 B.EQ 2(PC) 809 B runtime·save_g(SB) 810 811 MOVW g, R0 812 RET 813 #endif 814 #endif 815 816 TEXT runtime·emptyfunc(SB),0,$0-0 817 RET 818 819 TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0 820 MOVW $0, R0 821 MOVW (R0), R1 822 823 // armPublicationBarrier is a native store/store barrier for ARMv7+. 824 // On earlier ARM revisions, armPublicationBarrier is a no-op. 825 // This will not work on SMP ARMv6 machines, if any are in use. 826 // To implement publicationBarrier in sys_$GOOS_arm.s using the native 827 // instructions, use: 828 // 829 // TEXT ·publicationBarrier(SB),NOSPLIT|NOFRAME,$0-0 830 // B runtime·armPublicationBarrier(SB) 831 // 832 TEXT runtime·armPublicationBarrier(SB),NOSPLIT|NOFRAME,$0-0 833 MOVB runtime·goarm(SB), R11 834 CMP $7, R11 835 BLT 2(PC) 836 DMB MB_ST 837 RET 838 839 // AES hashing not implemented for ARM 840 TEXT runtime·memhash(SB),NOSPLIT|NOFRAME,$0-16 841 JMP runtime·memhashFallback(SB) 842 TEXT runtime·strhash(SB),NOSPLIT|NOFRAME,$0-12 843 JMP runtime·strhashFallback(SB) 844 TEXT runtime·memhash32(SB),NOSPLIT|NOFRAME,$0-12 845 JMP runtime·memhash32Fallback(SB) 846 TEXT runtime·memhash64(SB),NOSPLIT|NOFRAME,$0-12 847 JMP runtime·memhash64Fallback(SB) 848 849 TEXT runtime·return0(SB),NOSPLIT,$0 850 MOVW $0, R0 851 RET 852 853 TEXT runtime·procyield(SB),NOSPLIT|NOFRAME,$0 854 MOVW cycles+0(FP), R1 855 MOVW $0, R0 856 yieldloop: 857 WORD $0xe320f001 // YIELD (NOP pre-ARMv6K) 858 CMP R0, R1 859 B.NE 2(PC) 860 RET 861 SUB $1, R1 862 B yieldloop 863 864 // Called from cgo wrappers, this function returns g->m->curg.stack.hi. 865 // Must obey the gcc calling convention. 866 TEXT _cgo_topofstack(SB),NOSPLIT,$8 867 // R11 and g register are clobbered by load_g. They are 868 // callee-save in the gcc calling convention, so save them here. 869 MOVW R11, saveR11-4(SP) 870 MOVW g, saveG-8(SP) 871 872 BL runtime·load_g(SB) 873 MOVW g_m(g), R0 874 MOVW m_curg(R0), R0 875 MOVW (g_stack+stack_hi)(R0), R0 876 877 MOVW saveG-8(SP), g 878 MOVW saveR11-4(SP), R11 879 RET 880 881 // The top-most function running on a goroutine 882 // returns to goexit+PCQuantum. 883 TEXT runtime·goexit(SB),NOSPLIT|NOFRAME|TOPFRAME,$0-0 884 MOVW R0, R0 // NOP 885 BL runtime·goexit1(SB) // does not return 886 // traceback from goexit1 must hit code range of goexit 887 MOVW R0, R0 // NOP 888 889 // x -> x/1000000, x%1000000, called from Go with args, results on stack. 890 TEXT runtime·usplit(SB),NOSPLIT,$0-12 891 MOVW x+0(FP), R0 892 CALL runtime·usplitR0(SB) 893 MOVW R0, q+4(FP) 894 MOVW R1, r+8(FP) 895 RET 896 897 // R0, R1 = R0/1000000, R0%1000000 898 TEXT runtime·usplitR0(SB),NOSPLIT,$0 899 // magic multiply to avoid software divide without available m. 900 // see output of go tool compile -S for x/1000000. 901 MOVW R0, R3 902 MOVW $1125899907, R1 903 MULLU R1, R0, (R0, R1) 904 MOVW R0>>18, R0 905 MOVW $1000000, R1 906 MULU R0, R1 907 SUB R1, R3, R1 908 RET 909 910 // This is called from .init_array and follows the platform, not Go, ABI. 911 TEXT runtime·addmoduledata(SB),NOSPLIT,$0-0 912 MOVW R9, saver9-4(SP) // The access to global variables below implicitly uses R9, which is callee-save 913 MOVW R11, saver11-8(SP) // Likewise, R11 is the temp register, but callee-save in C ABI 914 MOVW runtime·lastmoduledatap(SB), R1 915 MOVW R0, moduledata_next(R1) 916 MOVW R0, runtime·lastmoduledatap(SB) 917 MOVW saver11-8(SP), R11 918 MOVW saver9-4(SP), R9 919 RET 920 921 TEXT ·checkASM(SB),NOSPLIT,$0-1 922 MOVW $1, R3 923 MOVB R3, ret+0(FP) 924 RET 925 926 // gcWriteBarrier informs the GC about heap pointer writes. 927 // 928 // gcWriteBarrier does NOT follow the Go ABI. It accepts the 929 // number of bytes of buffer needed in R8, and returns a pointer 930 // to the buffer space in R8. 931 // It clobbers condition codes. 932 // It does not clobber any other general-purpose registers, 933 // but may clobber others (e.g., floating point registers). 934 // The act of CALLing gcWriteBarrier will clobber R14 (LR). 935 TEXT gcWriteBarrier<>(SB),NOSPLIT|NOFRAME,$0 936 // Save the registers clobbered by the fast path. 937 MOVM.DB.W [R0,R1], (R13) 938 retry: 939 MOVW g_m(g), R0 940 MOVW m_p(R0), R0 941 MOVW (p_wbBuf+wbBuf_next)(R0), R1 942 MOVW (p_wbBuf+wbBuf_end)(R0), R11 943 // Increment wbBuf.next position. 944 ADD R8, R1 945 // Is the buffer full? 946 CMP R11, R1 947 BHI flush 948 // Commit to the larger buffer. 949 MOVW R1, (p_wbBuf+wbBuf_next)(R0) 950 // Make return value (the original next position) 951 SUB R8, R1, R8 952 // Restore registers. 953 MOVM.IA.W (R13), [R0,R1] 954 RET 955 956 flush: 957 // Save all general purpose registers since these could be 958 // clobbered by wbBufFlush and were not saved by the caller. 959 // 960 // R0 and R1 were saved at entry. 961 // R10 is g, so preserved. 962 // R11 is linker temp, so no need to save. 963 // R13 is stack pointer. 964 // R15 is PC. 965 MOVM.DB.W [R2-R9,R12], (R13) 966 // Save R14 (LR) because the fast path above doesn't save it, 967 // but needs it to RET. 968 MOVM.DB.W [R14], (R13) 969 970 CALL runtime·wbBufFlush(SB) 971 972 MOVM.IA.W (R13), [R14] 973 MOVM.IA.W (R13), [R2-R9,R12] 974 JMP retry 975 976 TEXT runtime·gcWriteBarrier1<ABIInternal>(SB),NOSPLIT,$0 977 MOVW $4, R8 978 JMP gcWriteBarrier<>(SB) 979 TEXT runtime·gcWriteBarrier2<ABIInternal>(SB),NOSPLIT,$0 980 MOVW $8, R8 981 JMP gcWriteBarrier<>(SB) 982 TEXT runtime·gcWriteBarrier3<ABIInternal>(SB),NOSPLIT,$0 983 MOVW $12, R8 984 JMP gcWriteBarrier<>(SB) 985 TEXT runtime·gcWriteBarrier4<ABIInternal>(SB),NOSPLIT,$0 986 MOVW $16, R8 987 JMP gcWriteBarrier<>(SB) 988 TEXT runtime·gcWriteBarrier5<ABIInternal>(SB),NOSPLIT,$0 989 MOVW $20, R8 990 JMP gcWriteBarrier<>(SB) 991 TEXT runtime·gcWriteBarrier6<ABIInternal>(SB),NOSPLIT,$0 992 MOVW $24, R8 993 JMP gcWriteBarrier<>(SB) 994 TEXT runtime·gcWriteBarrier7<ABIInternal>(SB),NOSPLIT,$0 995 MOVW $28, R8 996 JMP gcWriteBarrier<>(SB) 997 TEXT runtime·gcWriteBarrier8<ABIInternal>(SB),NOSPLIT,$0 998 MOVW $32, R8 999 JMP gcWriteBarrier<>(SB) 1000 1001 // Note: these functions use a special calling convention to save generated code space. 1002 // Arguments are passed in registers, but the space for those arguments are allocated 1003 // in the caller's stack frame. These stubs write the args into that stack space and 1004 // then tail call to the corresponding runtime handler. 1005 // The tail call makes these stubs disappear in backtraces. 1006 TEXT runtime·panicIndex(SB),NOSPLIT,$0-8 1007 MOVW R0, x+0(FP) 1008 MOVW R1, y+4(FP) 1009 JMP runtime·goPanicIndex(SB) 1010 TEXT runtime·panicIndexU(SB),NOSPLIT,$0-8 1011 MOVW R0, x+0(FP) 1012 MOVW R1, y+4(FP) 1013 JMP runtime·goPanicIndexU(SB) 1014 TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-8 1015 MOVW R1, x+0(FP) 1016 MOVW R2, y+4(FP) 1017 JMP runtime·goPanicSliceAlen(SB) 1018 TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-8 1019 MOVW R1, x+0(FP) 1020 MOVW R2, y+4(FP) 1021 JMP runtime·goPanicSliceAlenU(SB) 1022 TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-8 1023 MOVW R1, x+0(FP) 1024 MOVW R2, y+4(FP) 1025 JMP runtime·goPanicSliceAcap(SB) 1026 TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-8 1027 MOVW R1, x+0(FP) 1028 MOVW R2, y+4(FP) 1029 JMP runtime·goPanicSliceAcapU(SB) 1030 TEXT runtime·panicSliceB(SB),NOSPLIT,$0-8 1031 MOVW R0, x+0(FP) 1032 MOVW R1, y+4(FP) 1033 JMP runtime·goPanicSliceB(SB) 1034 TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-8 1035 MOVW R0, x+0(FP) 1036 MOVW R1, y+4(FP) 1037 JMP runtime·goPanicSliceBU(SB) 1038 TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-8 1039 MOVW R2, x+0(FP) 1040 MOVW R3, y+4(FP) 1041 JMP runtime·goPanicSlice3Alen(SB) 1042 TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-8 1043 MOVW R2, x+0(FP) 1044 MOVW R3, y+4(FP) 1045 JMP runtime·goPanicSlice3AlenU(SB) 1046 TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-8 1047 MOVW R2, x+0(FP) 1048 MOVW R3, y+4(FP) 1049 JMP runtime·goPanicSlice3Acap(SB) 1050 TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-8 1051 MOVW R2, x+0(FP) 1052 MOVW R3, y+4(FP) 1053 JMP runtime·goPanicSlice3AcapU(SB) 1054 TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-8 1055 MOVW R1, x+0(FP) 1056 MOVW R2, y+4(FP) 1057 JMP runtime·goPanicSlice3B(SB) 1058 TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-8 1059 MOVW R1, x+0(FP) 1060 MOVW R2, y+4(FP) 1061 JMP runtime·goPanicSlice3BU(SB) 1062 TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-8 1063 MOVW R0, x+0(FP) 1064 MOVW R1, y+4(FP) 1065 JMP runtime·goPanicSlice3C(SB) 1066 TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-8 1067 MOVW R0, x+0(FP) 1068 MOVW R1, y+4(FP) 1069 JMP runtime·goPanicSlice3CU(SB) 1070 TEXT runtime·panicSliceConvert(SB),NOSPLIT,$0-8 1071 MOVW R2, x+0(FP) 1072 MOVW R3, y+4(FP) 1073 JMP runtime·goPanicSliceConvert(SB) 1074 1075 // Extended versions for 64-bit indexes. 1076 TEXT runtime·panicExtendIndex(SB),NOSPLIT,$0-12 1077 MOVW R4, hi+0(FP) 1078 MOVW R0, lo+4(FP) 1079 MOVW R1, y+8(FP) 1080 JMP runtime·goPanicExtendIndex(SB) 1081 TEXT runtime·panicExtendIndexU(SB),NOSPLIT,$0-12 1082 MOVW R4, hi+0(FP) 1083 MOVW R0, lo+4(FP) 1084 MOVW R1, y+8(FP) 1085 JMP runtime·goPanicExtendIndexU(SB) 1086 TEXT runtime·panicExtendSliceAlen(SB),NOSPLIT,$0-12 1087 MOVW R4, hi+0(FP) 1088 MOVW R1, lo+4(FP) 1089 MOVW R2, y+8(FP) 1090 JMP runtime·goPanicExtendSliceAlen(SB) 1091 TEXT runtime·panicExtendSliceAlenU(SB),NOSPLIT,$0-12 1092 MOVW R4, hi+0(FP) 1093 MOVW R1, lo+4(FP) 1094 MOVW R2, y+8(FP) 1095 JMP runtime·goPanicExtendSliceAlenU(SB) 1096 TEXT runtime·panicExtendSliceAcap(SB),NOSPLIT,$0-12 1097 MOVW R4, hi+0(FP) 1098 MOVW R1, lo+4(FP) 1099 MOVW R2, y+8(FP) 1100 JMP runtime·goPanicExtendSliceAcap(SB) 1101 TEXT runtime·panicExtendSliceAcapU(SB),NOSPLIT,$0-12 1102 MOVW R4, hi+0(FP) 1103 MOVW R1, lo+4(FP) 1104 MOVW R2, y+8(FP) 1105 JMP runtime·goPanicExtendSliceAcapU(SB) 1106 TEXT runtime·panicExtendSliceB(SB),NOSPLIT,$0-12 1107 MOVW R4, hi+0(FP) 1108 MOVW R0, lo+4(FP) 1109 MOVW R1, y+8(FP) 1110 JMP runtime·goPanicExtendSliceB(SB) 1111 TEXT runtime·panicExtendSliceBU(SB),NOSPLIT,$0-12 1112 MOVW R4, hi+0(FP) 1113 MOVW R0, lo+4(FP) 1114 MOVW R1, y+8(FP) 1115 JMP runtime·goPanicExtendSliceBU(SB) 1116 TEXT runtime·panicExtendSlice3Alen(SB),NOSPLIT,$0-12 1117 MOVW R4, hi+0(FP) 1118 MOVW R2, lo+4(FP) 1119 MOVW R3, y+8(FP) 1120 JMP runtime·goPanicExtendSlice3Alen(SB) 1121 TEXT runtime·panicExtendSlice3AlenU(SB),NOSPLIT,$0-12 1122 MOVW R4, hi+0(FP) 1123 MOVW R2, lo+4(FP) 1124 MOVW R3, y+8(FP) 1125 JMP runtime·goPanicExtendSlice3AlenU(SB) 1126 TEXT runtime·panicExtendSlice3Acap(SB),NOSPLIT,$0-12 1127 MOVW R4, hi+0(FP) 1128 MOVW R2, lo+4(FP) 1129 MOVW R3, y+8(FP) 1130 JMP runtime·goPanicExtendSlice3Acap(SB) 1131 TEXT runtime·panicExtendSlice3AcapU(SB),NOSPLIT,$0-12 1132 MOVW R4, hi+0(FP) 1133 MOVW R2, lo+4(FP) 1134 MOVW R3, y+8(FP) 1135 JMP runtime·goPanicExtendSlice3AcapU(SB) 1136 TEXT runtime·panicExtendSlice3B(SB),NOSPLIT,$0-12 1137 MOVW R4, hi+0(FP) 1138 MOVW R1, lo+4(FP) 1139 MOVW R2, y+8(FP) 1140 JMP runtime·goPanicExtendSlice3B(SB) 1141 TEXT runtime·panicExtendSlice3BU(SB),NOSPLIT,$0-12 1142 MOVW R4, hi+0(FP) 1143 MOVW R1, lo+4(FP) 1144 MOVW R2, y+8(FP) 1145 JMP runtime·goPanicExtendSlice3BU(SB) 1146 TEXT runtime·panicExtendSlice3C(SB),NOSPLIT,$0-12 1147 MOVW R4, hi+0(FP) 1148 MOVW R0, lo+4(FP) 1149 MOVW R1, y+8(FP) 1150 JMP runtime·goPanicExtendSlice3C(SB) 1151 TEXT runtime·panicExtendSlice3CU(SB),NOSPLIT,$0-12 1152 MOVW R4, hi+0(FP) 1153 MOVW R0, lo+4(FP) 1154 MOVW R1, y+8(FP) 1155 JMP runtime·goPanicExtendSlice3CU(SB)