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