golang.org/toolchain@v0.0.1-go1.9rc2.windows-amd64/src/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 // using frame size $-4 means do not save LR on stack. 11 TEXT runtime·rt0_go(SB),NOSPLIT,$-4 12 MOVW $0xcafebabe, R12 13 14 // copy arguments forward on an even stack 15 // use R13 instead of SP to avoid linker rewriting the offsets 16 MOVW 0(R13), R0 // argc 17 MOVW 4(R13), R1 // argv 18 SUB $64, R13 // plenty of scratch 19 AND $~7, R13 20 MOVW R0, 60(R13) // save argc, argv away 21 MOVW R1, 64(R13) 22 23 // set up g register 24 // g is R10 25 MOVW $runtime·g0(SB), g 26 MOVW $runtime·m0(SB), R8 27 28 // save m->g0 = g0 29 MOVW g, m_g0(R8) 30 // save g->m = m0 31 MOVW R8, g_m(g) 32 33 // create istack out of the OS stack 34 // (1MB of system stack is available on iOS and Android) 35 MOVW $(-64*1024+104)(R13), R0 36 MOVW R0, g_stackguard0(g) 37 MOVW R0, g_stackguard1(g) 38 MOVW R0, (g_stack+stack_lo)(g) 39 MOVW R13, (g_stack+stack_hi)(g) 40 41 BL runtime·emptyfunc(SB) // fault if stack check is wrong 42 43 BL runtime·_initcgo(SB) // will clobber R0-R3 44 45 // update stackguard after _cgo_init 46 MOVW (g_stack+stack_lo)(g), R0 47 ADD $const__StackGuard, R0 48 MOVW R0, g_stackguard0(g) 49 MOVW R0, g_stackguard1(g) 50 51 BL runtime·check(SB) 52 53 // saved argc, argv 54 MOVW 60(R13), R0 55 MOVW R0, 4(R13) 56 MOVW 64(R13), R1 57 MOVW R1, 8(R13) 58 BL runtime·args(SB) 59 BL runtime·checkgoarm(SB) 60 BL runtime·osinit(SB) 61 BL runtime·schedinit(SB) 62 63 // create a new goroutine to start program 64 MOVW $runtime·mainPC(SB), R0 65 MOVW.W R0, -4(R13) 66 MOVW $8, R0 67 MOVW.W R0, -4(R13) 68 MOVW $0, R0 69 MOVW.W R0, -4(R13) // push $0 as guard 70 BL runtime·newproc(SB) 71 MOVW $12(R13), R13 // pop args and LR 72 73 // start this M 74 BL runtime·mstart(SB) 75 76 MOVW $1234, R0 77 MOVW $1000, R1 78 MOVW R0, (R1) // fail hard 79 80 DATA runtime·mainPC+0(SB)/4,$runtime·main(SB) 81 GLOBL runtime·mainPC(SB),RODATA,$4 82 83 TEXT runtime·breakpoint(SB),NOSPLIT,$0-0 84 // gdb won't skip this breakpoint instruction automatically, 85 // so you must manually "set $pc+=4" to skip it and continue. 86 #ifdef GOOS_nacl 87 WORD $0xe125be7f // BKPT 0x5bef, NACL_INSTR_ARM_BREAKPOINT 88 #else 89 #ifdef GOOS_plan9 90 WORD $0xD1200070 // undefined instruction used as armv5 breakpoint in Plan 9 91 #else 92 WORD $0xe7f001f0 // undefined instruction that gdb understands is a software breakpoint 93 #endif 94 #endif 95 RET 96 97 TEXT runtime·asminit(SB),NOSPLIT,$0-0 98 // disable runfast (flush-to-zero) mode of vfp if runtime.goarm > 5 99 MOVB runtime·goarm(SB), R11 100 CMP $5, R11 101 BLE 4(PC) 102 WORD $0xeef1ba10 // vmrs r11, fpscr 103 BIC $(1<<24), R11 104 WORD $0xeee1ba10 // vmsr fpscr, r11 105 RET 106 107 /* 108 * go-routine 109 */ 110 111 // void gosave(Gobuf*) 112 // save state in Gobuf; setjmp 113 TEXT runtime·gosave(SB),NOSPLIT,$-4-4 114 MOVW buf+0(FP), R0 115 MOVW R13, gobuf_sp(R0) 116 MOVW LR, gobuf_pc(R0) 117 MOVW g, gobuf_g(R0) 118 MOVW $0, R11 119 MOVW R11, gobuf_lr(R0) 120 MOVW R11, gobuf_ret(R0) 121 // Assert ctxt is zero. See func save. 122 MOVW gobuf_ctxt(R0), R0 123 CMP R0, R11 124 B.EQ 2(PC) 125 CALL runtime·badctxt(SB) 126 RET 127 128 // void gogo(Gobuf*) 129 // restore state from Gobuf; longjmp 130 TEXT runtime·gogo(SB),NOSPLIT,$8-4 131 MOVW buf+0(FP), R1 132 133 // If ctxt is not nil, invoke deletion barrier before overwriting. 134 MOVW gobuf_ctxt(R1), R0 135 CMP $0, R0 136 B.EQ nilctxt 137 MOVW $gobuf_ctxt(R1), R0 138 MOVW R0, 4(R13) 139 MOVW $0, R0 140 MOVW R0, 8(R13) 141 BL runtime·writebarrierptr_prewrite(SB) 142 MOVW buf+0(FP), R1 143 144 nilctxt: 145 MOVW gobuf_g(R1), R0 146 BL setg<>(SB) 147 148 // NOTE: We updated g above, and we are about to update SP. 149 // Until LR and PC are also updated, the g/SP/LR/PC quadruple 150 // are out of sync and must not be used as the basis of a traceback. 151 // Sigprof skips the traceback when SP is not within g's bounds, 152 // and when the PC is inside this function, runtime.gogo. 153 // Since we are about to update SP, until we complete runtime.gogo 154 // we must not leave this function. In particular, no calls 155 // after this point: it must be straight-line code until the 156 // final B instruction. 157 // See large comment in sigprof for more details. 158 MOVW gobuf_sp(R1), R13 // restore SP==R13 159 MOVW gobuf_lr(R1), LR 160 MOVW gobuf_ret(R1), R0 161 MOVW gobuf_ctxt(R1), R7 162 MOVW $0, R11 163 MOVW R11, gobuf_sp(R1) // clear to help garbage collector 164 MOVW R11, gobuf_ret(R1) 165 MOVW R11, gobuf_lr(R1) 166 MOVW R11, gobuf_ctxt(R1) 167 MOVW gobuf_pc(R1), R11 168 CMP R11, R11 // set condition codes for == test, needed by stack split 169 B (R11) 170 171 // func mcall(fn func(*g)) 172 // Switch to m->g0's stack, call fn(g). 173 // Fn must never return. It should gogo(&g->sched) 174 // to keep running g. 175 TEXT runtime·mcall(SB),NOSPLIT,$-4-4 176 // Save caller state in g->sched. 177 MOVW R13, (g_sched+gobuf_sp)(g) 178 MOVW LR, (g_sched+gobuf_pc)(g) 179 MOVW $0, R11 180 MOVW R11, (g_sched+gobuf_lr)(g) 181 MOVW g, (g_sched+gobuf_g)(g) 182 183 // Switch to m->g0 & its stack, call fn. 184 MOVW g, R1 185 MOVW g_m(g), R8 186 MOVW m_g0(R8), R0 187 BL setg<>(SB) 188 CMP g, R1 189 B.NE 2(PC) 190 B runtime·badmcall(SB) 191 MOVB runtime·iscgo(SB), R11 192 CMP $0, R11 193 BL.NE runtime·save_g(SB) 194 MOVW fn+0(FP), R0 195 MOVW (g_sched+gobuf_sp)(g), R13 196 SUB $8, R13 197 MOVW R1, 4(R13) 198 MOVW R0, R7 199 MOVW 0(R0), R0 200 BL (R0) 201 B runtime·badmcall2(SB) 202 RET 203 204 // systemstack_switch is a dummy routine that systemstack leaves at the bottom 205 // of the G stack. We need to distinguish the routine that 206 // lives at the bottom of the G stack from the one that lives 207 // at the top of the system stack because the one at the top of 208 // the system stack terminates the stack walk (see topofstack()). 209 TEXT runtime·systemstack_switch(SB),NOSPLIT,$0-0 210 MOVW $0, R0 211 BL (R0) // clobber lr to ensure push {lr} is kept 212 RET 213 214 // func systemstack(fn func()) 215 TEXT runtime·systemstack(SB),NOSPLIT,$0-4 216 MOVW fn+0(FP), R0 // R0 = fn 217 MOVW g_m(g), R1 // R1 = m 218 219 MOVW m_gsignal(R1), R2 // R2 = gsignal 220 CMP g, R2 221 B.EQ noswitch 222 223 MOVW m_g0(R1), R2 // R2 = g0 224 CMP g, R2 225 B.EQ noswitch 226 227 MOVW m_curg(R1), R3 228 CMP g, R3 229 B.EQ switch 230 231 // Bad: g is not gsignal, not g0, not curg. What is it? 232 // Hide call from linker nosplit analysis. 233 MOVW $runtime·badsystemstack(SB), R0 234 BL (R0) 235 236 switch: 237 // save our state in g->sched. Pretend to 238 // be systemstack_switch if the G stack is scanned. 239 MOVW $runtime·systemstack_switch(SB), R3 240 #ifdef GOOS_nacl 241 ADD $4, R3, R3 // get past nacl-insert bic instruction 242 #endif 243 ADD $4, R3, R3 // get past push {lr} 244 MOVW R3, (g_sched+gobuf_pc)(g) 245 MOVW R13, (g_sched+gobuf_sp)(g) 246 MOVW LR, (g_sched+gobuf_lr)(g) 247 MOVW g, (g_sched+gobuf_g)(g) 248 249 // switch to g0 250 MOVW R0, R5 251 MOVW R2, R0 252 BL setg<>(SB) 253 MOVW R5, R0 254 MOVW (g_sched+gobuf_sp)(R2), R3 255 // make it look like mstart called systemstack on g0, to stop traceback 256 SUB $4, R3, R3 257 MOVW $runtime·mstart(SB), R4 258 MOVW R4, 0(R3) 259 MOVW R3, R13 260 261 // call target function 262 MOVW R0, R7 263 MOVW 0(R0), R0 264 BL (R0) 265 266 // switch back to g 267 MOVW g_m(g), R1 268 MOVW m_curg(R1), R0 269 BL setg<>(SB) 270 MOVW (g_sched+gobuf_sp)(g), R13 271 MOVW $0, R3 272 MOVW R3, (g_sched+gobuf_sp)(g) 273 RET 274 275 noswitch: 276 MOVW R0, R7 277 MOVW 0(R0), R0 278 BL (R0) 279 RET 280 281 /* 282 * support for morestack 283 */ 284 285 // Called during function prolog when more stack is needed. 286 // R1 frame size 287 // R3 prolog's LR 288 // NB. we do not save R0 because we've forced 5c to pass all arguments 289 // on the stack. 290 // using frame size $-4 means do not save LR on stack. 291 // 292 // The traceback routines see morestack on a g0 as being 293 // the top of a stack (for example, morestack calling newstack 294 // calling the scheduler calling newm calling gc), so we must 295 // record an argument size. For that purpose, it has no arguments. 296 TEXT runtime·morestack(SB),NOSPLIT,$-4-0 297 // Cannot grow scheduler stack (m->g0). 298 MOVW g_m(g), R8 299 MOVW m_g0(R8), R4 300 CMP g, R4 301 BNE 3(PC) 302 BL runtime·badmorestackg0(SB) 303 B runtime·abort(SB) 304 305 // Cannot grow signal stack (m->gsignal). 306 MOVW m_gsignal(R8), R4 307 CMP g, R4 308 BNE 3(PC) 309 BL runtime·badmorestackgsignal(SB) 310 B runtime·abort(SB) 311 312 // Called from f. 313 // Set g->sched to context in f. 314 MOVW R13, (g_sched+gobuf_sp)(g) 315 MOVW LR, (g_sched+gobuf_pc)(g) 316 MOVW R3, (g_sched+gobuf_lr)(g) 317 // newstack will fill gobuf.ctxt. 318 319 // Called from f. 320 // Set m->morebuf to f's caller. 321 MOVW R3, (m_morebuf+gobuf_pc)(R8) // f's caller's PC 322 MOVW R13, (m_morebuf+gobuf_sp)(R8) // f's caller's SP 323 MOVW $4(R13), R3 // f's argument pointer 324 MOVW g, (m_morebuf+gobuf_g)(R8) 325 326 // Call newstack on m->g0's stack. 327 MOVW m_g0(R8), R0 328 BL setg<>(SB) 329 MOVW (g_sched+gobuf_sp)(g), R13 330 MOVW $0, R0 331 MOVW.W R0, -8(R13) // create a call frame on g0 332 MOVW R7, 4(R13) // ctxt argument 333 BL runtime·newstack(SB) 334 335 // Not reached, but make sure the return PC from the call to newstack 336 // is still in this function, and not the beginning of the next. 337 RET 338 339 TEXT runtime·morestack_noctxt(SB),NOSPLIT,$-4-0 340 MOVW $0, R7 341 B runtime·morestack(SB) 342 343 // reflectcall: call a function with the given argument list 344 // func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32). 345 // we don't have variable-sized frames, so we use a small number 346 // of constant-sized-frame functions to encode a few bits of size in the pc. 347 // Caution: ugly multiline assembly macros in your future! 348 349 #define DISPATCH(NAME,MAXSIZE) \ 350 CMP $MAXSIZE, R0; \ 351 B.HI 3(PC); \ 352 MOVW $NAME(SB), R1; \ 353 B (R1) 354 355 TEXT reflect·call(SB), NOSPLIT, $0-0 356 B ·reflectcall(SB) 357 358 TEXT ·reflectcall(SB),NOSPLIT,$-4-20 359 MOVW argsize+12(FP), R0 360 DISPATCH(runtime·call16, 16) 361 DISPATCH(runtime·call32, 32) 362 DISPATCH(runtime·call64, 64) 363 DISPATCH(runtime·call128, 128) 364 DISPATCH(runtime·call256, 256) 365 DISPATCH(runtime·call512, 512) 366 DISPATCH(runtime·call1024, 1024) 367 DISPATCH(runtime·call2048, 2048) 368 DISPATCH(runtime·call4096, 4096) 369 DISPATCH(runtime·call8192, 8192) 370 DISPATCH(runtime·call16384, 16384) 371 DISPATCH(runtime·call32768, 32768) 372 DISPATCH(runtime·call65536, 65536) 373 DISPATCH(runtime·call131072, 131072) 374 DISPATCH(runtime·call262144, 262144) 375 DISPATCH(runtime·call524288, 524288) 376 DISPATCH(runtime·call1048576, 1048576) 377 DISPATCH(runtime·call2097152, 2097152) 378 DISPATCH(runtime·call4194304, 4194304) 379 DISPATCH(runtime·call8388608, 8388608) 380 DISPATCH(runtime·call16777216, 16777216) 381 DISPATCH(runtime·call33554432, 33554432) 382 DISPATCH(runtime·call67108864, 67108864) 383 DISPATCH(runtime·call134217728, 134217728) 384 DISPATCH(runtime·call268435456, 268435456) 385 DISPATCH(runtime·call536870912, 536870912) 386 DISPATCH(runtime·call1073741824, 1073741824) 387 MOVW $runtime·badreflectcall(SB), R1 388 B (R1) 389 390 #define CALLFN(NAME,MAXSIZE) \ 391 TEXT NAME(SB), WRAPPER, $MAXSIZE-20; \ 392 NO_LOCAL_POINTERS; \ 393 /* copy arguments to stack */ \ 394 MOVW argptr+8(FP), R0; \ 395 MOVW argsize+12(FP), R2; \ 396 ADD $4, R13, R1; \ 397 CMP $0, R2; \ 398 B.EQ 5(PC); \ 399 MOVBU.P 1(R0), R5; \ 400 MOVBU.P R5, 1(R1); \ 401 SUB $1, R2, R2; \ 402 B -5(PC); \ 403 /* call function */ \ 404 MOVW f+4(FP), R7; \ 405 MOVW (R7), R0; \ 406 PCDATA $PCDATA_StackMapIndex, $0; \ 407 BL (R0); \ 408 /* copy return values back */ \ 409 MOVW argtype+0(FP), R4; \ 410 MOVW argptr+8(FP), R0; \ 411 MOVW argsize+12(FP), R2; \ 412 MOVW retoffset+16(FP), R3; \ 413 ADD $4, R13, R1; \ 414 ADD R3, R1; \ 415 ADD R3, R0; \ 416 SUB R3, R2; \ 417 BL callRet<>(SB); \ 418 RET 419 420 // callRet copies return values back at the end of call*. This is a 421 // separate function so it can allocate stack space for the arguments 422 // to reflectcallmove. It does not follow the Go ABI; it expects its 423 // arguments in registers. 424 TEXT callRet<>(SB), NOSPLIT, $16-0 425 MOVW R4, 4(R13) 426 MOVW R0, 8(R13) 427 MOVW R1, 12(R13) 428 MOVW R2, 16(R13) 429 BL runtime·reflectcallmove(SB) 430 RET 431 432 CALLFN(·call16, 16) 433 CALLFN(·call32, 32) 434 CALLFN(·call64, 64) 435 CALLFN(·call128, 128) 436 CALLFN(·call256, 256) 437 CALLFN(·call512, 512) 438 CALLFN(·call1024, 1024) 439 CALLFN(·call2048, 2048) 440 CALLFN(·call4096, 4096) 441 CALLFN(·call8192, 8192) 442 CALLFN(·call16384, 16384) 443 CALLFN(·call32768, 32768) 444 CALLFN(·call65536, 65536) 445 CALLFN(·call131072, 131072) 446 CALLFN(·call262144, 262144) 447 CALLFN(·call524288, 524288) 448 CALLFN(·call1048576, 1048576) 449 CALLFN(·call2097152, 2097152) 450 CALLFN(·call4194304, 4194304) 451 CALLFN(·call8388608, 8388608) 452 CALLFN(·call16777216, 16777216) 453 CALLFN(·call33554432, 33554432) 454 CALLFN(·call67108864, 67108864) 455 CALLFN(·call134217728, 134217728) 456 CALLFN(·call268435456, 268435456) 457 CALLFN(·call536870912, 536870912) 458 CALLFN(·call1073741824, 1073741824) 459 460 // void jmpdefer(fn, sp); 461 // called from deferreturn. 462 // 1. grab stored LR for caller 463 // 2. sub 4 bytes to get back to BL deferreturn 464 // 3. B to fn 465 // TODO(rsc): Push things on stack and then use pop 466 // to load all registers simultaneously, so that a profiling 467 // interrupt can never see mismatched SP/LR/PC. 468 // (And double-check that pop is atomic in that way.) 469 TEXT runtime·jmpdefer(SB),NOSPLIT,$0-8 470 MOVW 0(R13), LR 471 MOVW $-4(LR), LR // BL deferreturn 472 MOVW fv+0(FP), R7 473 MOVW argp+4(FP), R13 474 MOVW $-4(R13), R13 // SP is 4 below argp, due to saved LR 475 MOVW 0(R7), R1 476 B (R1) 477 478 // Save state of caller into g->sched. Smashes R11. 479 TEXT gosave<>(SB),NOSPLIT,$-4 480 MOVW LR, (g_sched+gobuf_pc)(g) 481 MOVW R13, (g_sched+gobuf_sp)(g) 482 MOVW $0, R11 483 MOVW R11, (g_sched+gobuf_lr)(g) 484 MOVW R11, (g_sched+gobuf_ret)(g) 485 MOVW R11, (g_sched+gobuf_ctxt)(g) 486 // Assert ctxt is zero. See func save. 487 MOVW (g_sched+gobuf_ctxt)(g), R11 488 CMP $0, R11 489 B.EQ 2(PC) 490 CALL runtime·badctxt(SB) 491 RET 492 493 // func asmcgocall(fn, arg unsafe.Pointer) int32 494 // Call fn(arg) on the scheduler stack, 495 // aligned appropriately for the gcc ABI. 496 // See cgocall.go for more details. 497 TEXT ·asmcgocall(SB),NOSPLIT,$0-12 498 MOVW fn+0(FP), R1 499 MOVW arg+4(FP), R0 500 501 MOVW R13, R2 502 MOVW g, R4 503 504 // Figure out if we need to switch to m->g0 stack. 505 // We get called to create new OS threads too, and those 506 // come in on the m->g0 stack already. 507 MOVW g_m(g), R8 508 MOVW m_g0(R8), R3 509 CMP R3, g 510 BEQ g0 511 BL gosave<>(SB) 512 MOVW R0, R5 513 MOVW R3, R0 514 BL setg<>(SB) 515 MOVW R5, R0 516 MOVW (g_sched+gobuf_sp)(g), R13 517 518 // Now on a scheduling stack (a pthread-created stack). 519 g0: 520 SUB $24, R13 521 BIC $0x7, R13 // alignment for gcc ABI 522 MOVW R4, 20(R13) // save old g 523 MOVW (g_stack+stack_hi)(R4), R4 524 SUB R2, R4 525 MOVW R4, 16(R13) // save depth in stack (can't just save SP, as stack might be copied during a callback) 526 BL (R1) 527 528 // Restore registers, g, stack pointer. 529 MOVW R0, R5 530 MOVW 20(R13), R0 531 BL setg<>(SB) 532 MOVW (g_stack+stack_hi)(g), R1 533 MOVW 16(R13), R2 534 SUB R2, R1 535 MOVW R5, R0 536 MOVW R1, R13 537 538 MOVW R0, ret+8(FP) 539 RET 540 541 // cgocallback(void (*fn)(void*), void *frame, uintptr framesize, uintptr ctxt) 542 // Turn the fn into a Go func (by taking its address) and call 543 // cgocallback_gofunc. 544 TEXT runtime·cgocallback(SB),NOSPLIT,$16-16 545 MOVW $fn+0(FP), R0 546 MOVW R0, 4(R13) 547 MOVW frame+4(FP), R0 548 MOVW R0, 8(R13) 549 MOVW framesize+8(FP), R0 550 MOVW R0, 12(R13) 551 MOVW ctxt+12(FP), R0 552 MOVW R0, 16(R13) 553 MOVW $runtime·cgocallback_gofunc(SB), R0 554 BL (R0) 555 RET 556 557 // cgocallback_gofunc(void (*fn)(void*), void *frame, uintptr framesize, uintptr ctxt) 558 // See cgocall.go for more details. 559 TEXT ·cgocallback_gofunc(SB),NOSPLIT,$8-16 560 NO_LOCAL_POINTERS 561 562 // Load m and g from thread-local storage. 563 MOVB runtime·iscgo(SB), R0 564 CMP $0, R0 565 BL.NE runtime·load_g(SB) 566 567 // If g is nil, Go did not create the current thread. 568 // Call needm to obtain one for temporary use. 569 // In this case, we're running on the thread stack, so there's 570 // lots of space, but the linker doesn't know. Hide the call from 571 // the linker analysis by using an indirect call. 572 CMP $0, g 573 B.EQ needm 574 575 MOVW g_m(g), R8 576 MOVW R8, savedm-4(SP) 577 B havem 578 579 needm: 580 MOVW g, savedm-4(SP) // g is zero, so is m. 581 MOVW $runtime·needm(SB), R0 582 BL (R0) 583 584 // Set m->sched.sp = SP, so that if a panic happens 585 // during the function we are about to execute, it will 586 // have a valid SP to run on the g0 stack. 587 // The next few lines (after the havem label) 588 // will save this SP onto the stack and then write 589 // the same SP back to m->sched.sp. That seems redundant, 590 // but if an unrecovered panic happens, unwindm will 591 // restore the g->sched.sp from the stack location 592 // and then systemstack will try to use it. If we don't set it here, 593 // that restored SP will be uninitialized (typically 0) and 594 // will not be usable. 595 MOVW g_m(g), R8 596 MOVW m_g0(R8), R3 597 MOVW R13, (g_sched+gobuf_sp)(R3) 598 599 havem: 600 // Now there's a valid m, and we're running on its m->g0. 601 // Save current m->g0->sched.sp on stack and then set it to SP. 602 // Save current sp in m->g0->sched.sp in preparation for 603 // switch back to m->curg stack. 604 // NOTE: unwindm knows that the saved g->sched.sp is at 4(R13) aka savedsp-8(SP). 605 MOVW m_g0(R8), R3 606 MOVW (g_sched+gobuf_sp)(R3), R4 607 MOVW R4, savedsp-8(SP) 608 MOVW R13, (g_sched+gobuf_sp)(R3) 609 610 // Switch to m->curg stack and call runtime.cgocallbackg. 611 // Because we are taking over the execution of m->curg 612 // but *not* resuming what had been running, we need to 613 // save that information (m->curg->sched) so we can restore it. 614 // We can restore m->curg->sched.sp easily, because calling 615 // runtime.cgocallbackg leaves SP unchanged upon return. 616 // To save m->curg->sched.pc, we push it onto the stack. 617 // This has the added benefit that it looks to the traceback 618 // routine like cgocallbackg is going to return to that 619 // PC (because the frame we allocate below has the same 620 // size as cgocallback_gofunc's frame declared above) 621 // so that the traceback will seamlessly trace back into 622 // the earlier calls. 623 // 624 // In the new goroutine, -4(SP) is unused (where SP refers to 625 // m->curg's SP while we're setting it up, before we've adjusted it). 626 MOVW m_curg(R8), R0 627 BL setg<>(SB) 628 MOVW (g_sched+gobuf_sp)(g), R4 // prepare stack as R4 629 MOVW (g_sched+gobuf_pc)(g), R5 630 MOVW R5, -12(R4) 631 MOVW ctxt+12(FP), R0 632 MOVW R0, -8(R4) 633 MOVW $-12(R4), R13 634 BL runtime·cgocallbackg(SB) 635 636 // Restore g->sched (== m->curg->sched) from saved values. 637 MOVW 0(R13), R5 638 MOVW R5, (g_sched+gobuf_pc)(g) 639 MOVW $12(R13), R4 640 MOVW R4, (g_sched+gobuf_sp)(g) 641 642 // Switch back to m->g0's stack and restore m->g0->sched.sp. 643 // (Unlike m->curg, the g0 goroutine never uses sched.pc, 644 // so we do not have to restore it.) 645 MOVW g_m(g), R8 646 MOVW m_g0(R8), R0 647 BL setg<>(SB) 648 MOVW (g_sched+gobuf_sp)(g), R13 649 MOVW savedsp-8(SP), R4 650 MOVW R4, (g_sched+gobuf_sp)(g) 651 652 // If the m on entry was nil, we called needm above to borrow an m 653 // for the duration of the call. Since the call is over, return it with dropm. 654 MOVW savedm-4(SP), R6 655 CMP $0, R6 656 B.NE 3(PC) 657 MOVW $runtime·dropm(SB), R0 658 BL (R0) 659 660 // Done! 661 RET 662 663 // void setg(G*); set g. for use by needm. 664 TEXT runtime·setg(SB),NOSPLIT,$-4-4 665 MOVW gg+0(FP), R0 666 B setg<>(SB) 667 668 TEXT setg<>(SB),NOSPLIT,$-4-0 669 MOVW R0, g 670 671 // Save g to thread-local storage. 672 MOVB runtime·iscgo(SB), R0 673 CMP $0, R0 674 B.EQ 2(PC) 675 B runtime·save_g(SB) 676 677 MOVW g, R0 678 RET 679 680 TEXT runtime·getcallerpc(SB),NOSPLIT,$4-8 681 MOVW 8(R13), R0 // LR saved by caller 682 MOVW R0, ret+4(FP) 683 RET 684 685 TEXT runtime·emptyfunc(SB),0,$0-0 686 RET 687 688 TEXT runtime·abort(SB),NOSPLIT,$-4-0 689 MOVW $0, R0 690 MOVW (R0), R1 691 692 // armPublicationBarrier is a native store/store barrier for ARMv7+. 693 // On earlier ARM revisions, armPublicationBarrier is a no-op. 694 // This will not work on SMP ARMv6 machines, if any are in use. 695 // To implement publicationBarrier in sys_$GOOS_arm.s using the native 696 // instructions, use: 697 // 698 // TEXT ·publicationBarrier(SB),NOSPLIT,$-4-0 699 // B runtime·armPublicationBarrier(SB) 700 // 701 TEXT runtime·armPublicationBarrier(SB),NOSPLIT,$-4-0 702 MOVB runtime·goarm(SB), R11 703 CMP $7, R11 704 BLT 2(PC) 705 WORD $0xf57ff05e // DMB ST 706 RET 707 708 // AES hashing not implemented for ARM 709 TEXT runtime·aeshash(SB),NOSPLIT,$-4-0 710 MOVW $0, R0 711 MOVW (R0), R1 712 TEXT runtime·aeshash32(SB),NOSPLIT,$-4-0 713 MOVW $0, R0 714 MOVW (R0), R1 715 TEXT runtime·aeshash64(SB),NOSPLIT,$-4-0 716 MOVW $0, R0 717 MOVW (R0), R1 718 TEXT runtime·aeshashstr(SB),NOSPLIT,$-4-0 719 MOVW $0, R0 720 MOVW (R0), R1 721 722 // memhash_varlen(p unsafe.Pointer, h seed) uintptr 723 // redirects to memhash(p, h, size) using the size 724 // stored in the closure. 725 TEXT runtime·memhash_varlen(SB),NOSPLIT,$16-12 726 GO_ARGS 727 NO_LOCAL_POINTERS 728 MOVW p+0(FP), R0 729 MOVW h+4(FP), R1 730 MOVW 4(R7), R2 731 MOVW R0, 4(R13) 732 MOVW R1, 8(R13) 733 MOVW R2, 12(R13) 734 BL runtime·memhash(SB) 735 MOVW 16(R13), R0 736 MOVW R0, ret+8(FP) 737 RET 738 739 // memequal(p, q unsafe.Pointer, size uintptr) bool 740 TEXT runtime·memequal(SB),NOSPLIT,$-4-13 741 MOVW a+0(FP), R1 742 MOVW b+4(FP), R2 743 MOVW size+8(FP), R3 744 ADD R1, R3, R6 745 MOVW $1, R0 746 MOVB R0, ret+12(FP) 747 CMP R1, R2 748 RET.EQ 749 loop: 750 CMP R1, R6 751 RET.EQ 752 MOVBU.P 1(R1), R4 753 MOVBU.P 1(R2), R5 754 CMP R4, R5 755 BEQ loop 756 757 MOVW $0, R0 758 MOVB R0, ret+12(FP) 759 RET 760 761 // memequal_varlen(a, b unsafe.Pointer) bool 762 TEXT runtime·memequal_varlen(SB),NOSPLIT,$16-9 763 MOVW a+0(FP), R0 764 MOVW b+4(FP), R1 765 CMP R0, R1 766 BEQ eq 767 MOVW 4(R7), R2 // compiler stores size at offset 4 in the closure 768 MOVW R0, 4(R13) 769 MOVW R1, 8(R13) 770 MOVW R2, 12(R13) 771 BL runtime·memequal(SB) 772 MOVB 16(R13), R0 773 MOVB R0, ret+8(FP) 774 RET 775 eq: 776 MOVW $1, R0 777 MOVB R0, ret+8(FP) 778 RET 779 780 TEXT runtime·cmpstring(SB),NOSPLIT,$-4-20 781 MOVW s1_base+0(FP), R2 782 MOVW s1_len+4(FP), R0 783 MOVW s2_base+8(FP), R3 784 MOVW s2_len+12(FP), R1 785 ADD $20, R13, R7 786 B runtime·cmpbody(SB) 787 788 TEXT bytes·Compare(SB),NOSPLIT,$-4-28 789 MOVW s1+0(FP), R2 790 MOVW s1+4(FP), R0 791 MOVW s2+12(FP), R3 792 MOVW s2+16(FP), R1 793 ADD $28, R13, R7 794 B runtime·cmpbody(SB) 795 796 // On entry: 797 // R0 is the length of s1 798 // R1 is the length of s2 799 // R2 points to the start of s1 800 // R3 points to the start of s2 801 // R7 points to return value (-1/0/1 will be written here) 802 // 803 // On exit: 804 // R4, R5, and R6 are clobbered 805 TEXT runtime·cmpbody(SB),NOSPLIT,$-4-0 806 CMP R2, R3 807 BEQ samebytes 808 CMP R0, R1 809 MOVW R0, R6 810 MOVW.LT R1, R6 // R6 is min(R0, R1) 811 812 ADD R2, R6 // R2 is current byte in s1, R6 is last byte in s1 to compare 813 loop: 814 CMP R2, R6 815 BEQ samebytes // all compared bytes were the same; compare lengths 816 MOVBU.P 1(R2), R4 817 MOVBU.P 1(R3), R5 818 CMP R4, R5 819 BEQ loop 820 // bytes differed 821 MOVW.LT $1, R0 822 MOVW.GT $-1, R0 823 MOVW R0, (R7) 824 RET 825 samebytes: 826 CMP R0, R1 827 MOVW.LT $1, R0 828 MOVW.GT $-1, R0 829 MOVW.EQ $0, R0 830 MOVW R0, (R7) 831 RET 832 833 // eqstring tests whether two strings are equal. 834 // The compiler guarantees that strings passed 835 // to eqstring have equal length. 836 // See runtime_test.go:eqstring_generic for 837 // equivalent Go code. 838 TEXT runtime·eqstring(SB),NOSPLIT,$-4-17 839 MOVW s1_base+0(FP), R2 840 MOVW s2_base+8(FP), R3 841 MOVW $1, R8 842 MOVB R8, ret+16(FP) 843 CMP R2, R3 844 RET.EQ 845 MOVW s1_len+4(FP), R0 846 ADD R2, R0, R6 847 loop: 848 CMP R2, R6 849 RET.EQ 850 MOVBU.P 1(R2), R4 851 MOVBU.P 1(R3), R5 852 CMP R4, R5 853 BEQ loop 854 MOVW $0, R8 855 MOVB R8, ret+16(FP) 856 RET 857 858 // TODO: share code with memequal? 859 TEXT bytes·Equal(SB),NOSPLIT,$0-25 860 MOVW a_len+4(FP), R1 861 MOVW b_len+16(FP), R3 862 863 CMP R1, R3 // unequal lengths are not equal 864 B.NE notequal 865 866 MOVW a+0(FP), R0 867 MOVW b+12(FP), R2 868 ADD R0, R1 // end 869 870 loop: 871 CMP R0, R1 872 B.EQ equal // reached the end 873 MOVBU.P 1(R0), R4 874 MOVBU.P 1(R2), R5 875 CMP R4, R5 876 B.EQ loop 877 878 notequal: 879 MOVW $0, R0 880 MOVBU R0, ret+24(FP) 881 RET 882 883 equal: 884 MOVW $1, R0 885 MOVBU R0, ret+24(FP) 886 RET 887 888 TEXT bytes·IndexByte(SB),NOSPLIT,$0-20 889 MOVW s+0(FP), R0 890 MOVW s_len+4(FP), R1 891 MOVBU c+12(FP), R2 // byte to find 892 MOVW R0, R4 // store base for later 893 ADD R0, R1 // end 894 895 _loop: 896 CMP R0, R1 897 B.EQ _notfound 898 MOVBU.P 1(R0), R3 899 CMP R2, R3 900 B.NE _loop 901 902 SUB $1, R0 // R0 will be one beyond the position we want 903 SUB R4, R0 // remove base 904 MOVW R0, ret+16(FP) 905 RET 906 907 _notfound: 908 MOVW $-1, R0 909 MOVW R0, ret+16(FP) 910 RET 911 912 TEXT strings·IndexByte(SB),NOSPLIT,$0-16 913 MOVW s+0(FP), R0 914 MOVW s_len+4(FP), R1 915 MOVBU c+8(FP), R2 // byte to find 916 MOVW R0, R4 // store base for later 917 ADD R0, R1 // end 918 919 _sib_loop: 920 CMP R0, R1 921 B.EQ _sib_notfound 922 MOVBU.P 1(R0), R3 923 CMP R2, R3 924 B.NE _sib_loop 925 926 SUB $1, R0 // R0 will be one beyond the position we want 927 SUB R4, R0 // remove base 928 MOVW R0, ret+12(FP) 929 RET 930 931 _sib_notfound: 932 MOVW $-1, R0 933 MOVW R0, ret+12(FP) 934 RET 935 936 TEXT runtime·return0(SB),NOSPLIT,$0 937 MOVW $0, R0 938 RET 939 940 TEXT runtime·procyield(SB),NOSPLIT,$-4 941 MOVW cycles+0(FP), R1 942 MOVW $0, R0 943 yieldloop: 944 WORD $0xe320f001 // YIELD (NOP pre-ARMv6K) 945 CMP R0, R1 946 B.NE 2(PC) 947 RET 948 SUB $1, R1 949 B yieldloop 950 951 // Called from cgo wrappers, this function returns g->m->curg.stack.hi. 952 // Must obey the gcc calling convention. 953 TEXT _cgo_topofstack(SB),NOSPLIT,$8 954 // R11 and g register are clobbered by load_g. They are 955 // callee-save in the gcc calling convention, so save them here. 956 MOVW R11, saveR11-4(SP) 957 MOVW g, saveG-8(SP) 958 959 BL runtime·load_g(SB) 960 MOVW g_m(g), R0 961 MOVW m_curg(R0), R0 962 MOVW (g_stack+stack_hi)(R0), R0 963 964 MOVW saveG-8(SP), g 965 MOVW saveR11-4(SP), R11 966 RET 967 968 // The top-most function running on a goroutine 969 // returns to goexit+PCQuantum. 970 TEXT runtime·goexit(SB),NOSPLIT,$-4-0 971 MOVW R0, R0 // NOP 972 BL runtime·goexit1(SB) // does not return 973 // traceback from goexit1 must hit code range of goexit 974 MOVW R0, R0 // NOP 975 976 TEXT runtime·prefetcht0(SB),NOSPLIT,$0-4 977 RET 978 979 TEXT runtime·prefetcht1(SB),NOSPLIT,$0-4 980 RET 981 982 TEXT runtime·prefetcht2(SB),NOSPLIT,$0-4 983 RET 984 985 TEXT runtime·prefetchnta(SB),NOSPLIT,$0-4 986 RET 987 988 // x -> x/1000000, x%1000000, called from Go with args, results on stack. 989 TEXT runtime·usplit(SB),NOSPLIT,$0-12 990 MOVW x+0(FP), R0 991 CALL runtime·usplitR0(SB) 992 MOVW R0, q+4(FP) 993 MOVW R1, r+8(FP) 994 RET 995 996 // R0, R1 = R0/1000000, R0%1000000 997 TEXT runtime·usplitR0(SB),NOSPLIT,$0 998 // magic multiply to avoid software divide without available m. 999 // see output of go tool compile -S for x/1000000. 1000 MOVW R0, R3 1001 MOVW $1125899907, R1 1002 MULLU R1, R0, (R0, R1) 1003 MOVW R0>>18, R0 1004 MOVW $1000000, R1 1005 MULU R0, R1 1006 SUB R1, R3, R1 1007 RET 1008 1009 TEXT runtime·sigreturn(SB),NOSPLIT,$0-0 1010 RET 1011 1012 #ifndef GOOS_nacl 1013 // This is called from .init_array and follows the platform, not Go, ABI. 1014 TEXT runtime·addmoduledata(SB),NOSPLIT,$0-8 1015 MOVW R9, saver9-4(SP) // The access to global variables below implicitly uses R9, which is callee-save 1016 MOVW R11, saver11-8(SP) // Likewise, R11 is the temp register, but callee-save in C ABI 1017 MOVW runtime·lastmoduledatap(SB), R1 1018 MOVW R0, moduledata_next(R1) 1019 MOVW R0, runtime·lastmoduledatap(SB) 1020 MOVW saver11-8(SP), R11 1021 MOVW saver9-4(SP), R9 1022 RET 1023 #endif 1024 1025 TEXT ·checkASM(SB),NOSPLIT,$0-1 1026 MOVW $1, R3 1027 MOVB R3, ret+0(FP) 1028 RET