github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/pkg/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 "zasm_GOOS_GOARCH.h" 6 #include "funcdata.h" 7 #include "../../cmd/ld/textflag.h" 8 9 // using frame size $-4 means do not save LR on stack. 10 TEXT _rt0_go(SB),NOSPLIT,$-4 11 MOVW $0xcafebabe, R12 12 13 // copy arguments forward on an even stack 14 // use R13 instead of SP to avoid linker rewriting the offsets 15 MOVW 0(R13), R0 // argc 16 MOVW 4(R13), R1 // argv 17 SUB $64, R13 // plenty of scratch 18 AND $~7, R13 19 MOVW R0, 60(R13) // save argc, argv away 20 MOVW R1, 64(R13) 21 22 // set up m and g registers 23 // g is R10, m is R9 24 MOVW $runtime·g0(SB), g 25 MOVW $runtime·m0(SB), m 26 27 // save m->g0 = g0 28 MOVW g, m_g0(m) 29 30 // create istack out of the OS stack 31 MOVW $(-8192+104)(R13), R0 32 MOVW R0, g_stackguard(g) // (w 104b guard) 33 MOVW R0, g_stackguard0(g) 34 MOVW R13, g_stackbase(g) 35 BL runtime·emptyfunc(SB) // fault if stack check is wrong 36 37 // if there is an _cgo_init, call it. 38 MOVW _cgo_init(SB), R4 39 CMP $0, R4 40 B.EQ nocgo 41 BL runtime·save_gm(SB); 42 MOVW g, R0 // first argument of _cgo_init is g 43 MOVW $setmg_gcc<>(SB), R1 // second argument is address of save_gm 44 BL (R4) // will clobber R0-R3 45 46 nocgo: 47 // update stackguard after _cgo_init 48 MOVW g_stackguard0(g), R0 49 MOVW R0, g_stackguard(g) 50 51 BL runtime·checkgoarm(SB) 52 BL runtime·check(SB) 53 54 // saved argc, argv 55 MOVW 60(R13), R0 56 MOVW R0, 4(R13) 57 MOVW 64(R13), R1 58 MOVW R1, 8(R13) 59 BL runtime·args(SB) 60 BL runtime·osinit(SB) 61 BL runtime·hashinit(SB) 62 BL runtime·schedinit(SB) 63 64 // create a new goroutine to start program 65 MOVW $runtime·main·f(SB), R0 66 MOVW.W R0, -4(R13) 67 MOVW $8, R0 68 MOVW.W R0, -4(R13) 69 MOVW $0, R0 70 MOVW.W R0, -4(R13) // push $0 as guard 71 ARGSIZE(12) 72 BL runtime·newproc(SB) 73 ARGSIZE(-1) 74 MOVW $12(R13), R13 // pop args and LR 75 76 // start this M 77 BL runtime·mstart(SB) 78 79 MOVW $1234, R0 80 MOVW $1000, R1 81 MOVW R0, (R1) // fail hard 82 83 DATA runtime·main·f+0(SB)/4,$runtime·main(SB) 84 GLOBL runtime·main·f(SB),RODATA,$4 85 86 TEXT runtime·breakpoint(SB),NOSPLIT,$0-0 87 // gdb won't skip this breakpoint instruction automatically, 88 // so you must manually "set $pc+=4" to skip it and continue. 89 WORD $0xe1200071 // BKPT 0x0001 90 RET 91 92 GLOBL runtime·goarm(SB), $4 93 94 TEXT runtime·asminit(SB),NOSPLIT,$0-0 95 // disable runfast (flush-to-zero) mode of vfp if runtime.goarm > 5 96 MOVW runtime·goarm(SB), R11 97 CMP $5, R11 98 BLE 4(PC) 99 WORD $0xeef1ba10 // vmrs r11, fpscr 100 BIC $(1<<24), R11 101 WORD $0xeee1ba10 // vmsr fpscr, r11 102 RET 103 104 /* 105 * go-routine 106 */ 107 108 // void gosave(Gobuf*) 109 // save state in Gobuf; setjmp 110 TEXT runtime·gosave(SB), NOSPLIT, $-4-4 111 MOVW 0(FP), R0 // gobuf 112 MOVW SP, gobuf_sp(R0) 113 MOVW LR, gobuf_pc(R0) 114 MOVW g, gobuf_g(R0) 115 MOVW $0, R11 116 MOVW R11, gobuf_lr(R0) 117 MOVW R11, gobuf_ret(R0) 118 MOVW R11, gobuf_ctxt(R0) 119 RET 120 121 // void gogo(Gobuf*) 122 // restore state from Gobuf; longjmp 123 TEXT runtime·gogo(SB), NOSPLIT, $-4-4 124 MOVW 0(FP), R1 // gobuf 125 MOVW gobuf_g(R1), g 126 MOVW 0(g), R2 // make sure g != nil 127 MOVB runtime·iscgo(SB), R2 128 CMP $0, R2 // if in Cgo, we have to save g and m 129 BL.NE runtime·save_gm(SB) // this call will clobber R0 130 MOVW gobuf_sp(R1), SP // restore SP 131 MOVW gobuf_lr(R1), LR 132 MOVW gobuf_ret(R1), R0 133 MOVW gobuf_ctxt(R1), R7 134 MOVW $0, R11 135 MOVW R11, gobuf_sp(R1) // clear to help garbage collector 136 MOVW R11, gobuf_ret(R1) 137 MOVW R11, gobuf_lr(R1) 138 MOVW R11, gobuf_ctxt(R1) 139 CMP R11, R11 // set condition codes for == test, needed by stack split 140 MOVW gobuf_pc(R1), PC 141 142 // void mcall(void (*fn)(G*)) 143 // Switch to m->g0's stack, call fn(g). 144 // Fn must never return. It should gogo(&g->sched) 145 // to keep running g. 146 TEXT runtime·mcall(SB), NOSPLIT, $-4-4 147 MOVW fn+0(FP), R0 148 149 // Save caller state in g->sched. 150 MOVW SP, (g_sched+gobuf_sp)(g) 151 MOVW LR, (g_sched+gobuf_pc)(g) 152 MOVW $0, R11 153 MOVW R11, (g_sched+gobuf_lr)(g) 154 MOVW g, (g_sched+gobuf_g)(g) 155 156 // Switch to m->g0 & its stack, call fn. 157 MOVW g, R1 158 MOVW m_g0(m), g 159 CMP g, R1 160 B.NE 2(PC) 161 B runtime·badmcall(SB) 162 MOVW (g_sched+gobuf_sp)(g), SP 163 SUB $8, SP 164 MOVW R1, 4(SP) 165 BL (R0) 166 B runtime·badmcall2(SB) 167 RET 168 169 /* 170 * support for morestack 171 */ 172 173 // Called during function prolog when more stack is needed. 174 // R1 frame size 175 // R2 arg size 176 // R3 prolog's LR 177 // NB. we do not save R0 because we've forced 5c to pass all arguments 178 // on the stack. 179 // using frame size $-4 means do not save LR on stack. 180 // 181 // The traceback routines see morestack on a g0 as being 182 // the top of a stack (for example, morestack calling newstack 183 // calling the scheduler calling newm calling gc), so we must 184 // record an argument size. For that purpose, it has no arguments. 185 TEXT runtime·morestack(SB),NOSPLIT,$-4-0 186 // Cannot grow scheduler stack (m->g0). 187 MOVW m_g0(m), R4 188 CMP g, R4 189 BL.EQ runtime·abort(SB) 190 191 MOVW R1, m_moreframesize(m) 192 MOVW R2, m_moreargsize(m) 193 194 // Called from f. 195 // Set g->sched to context in f. 196 MOVW R7, (g_sched+gobuf_ctxt)(g) 197 MOVW SP, (g_sched+gobuf_sp)(g) 198 MOVW LR, (g_sched+gobuf_pc)(g) 199 MOVW R3, (g_sched+gobuf_lr)(g) 200 201 // Called from f. 202 // Set m->morebuf to f's caller. 203 MOVW R3, (m_morebuf+gobuf_pc)(m) // f's caller's PC 204 MOVW SP, (m_morebuf+gobuf_sp)(m) // f's caller's SP 205 MOVW $4(SP), R3 // f's argument pointer 206 MOVW R3, m_moreargp(m) 207 MOVW g, (m_morebuf+gobuf_g)(m) 208 209 // Call newstack on m->g0's stack. 210 MOVW m_g0(m), g 211 MOVW (g_sched+gobuf_sp)(g), SP 212 BL runtime·newstack(SB) 213 214 // Not reached, but make sure the return PC from the call to newstack 215 // is still in this function, and not the beginning of the next. 216 RET 217 218 // Called from panic. Mimics morestack, 219 // reuses stack growth code to create a frame 220 // with the desired args running the desired function. 221 // 222 // func call(fn *byte, arg *byte, argsize uint32). 223 TEXT runtime·newstackcall(SB), NOSPLIT, $-4-12 224 // Save our caller's state as the PC and SP to 225 // restore when returning from f. 226 MOVW LR, (m_morebuf+gobuf_pc)(m) // our caller's PC 227 MOVW SP, (m_morebuf+gobuf_sp)(m) // our caller's SP 228 MOVW g, (m_morebuf+gobuf_g)(m) 229 230 // Save our own state as the PC and SP to restore 231 // if this goroutine needs to be restarted. 232 MOVW $runtime·newstackcall(SB), R11 233 MOVW R11, (g_sched+gobuf_pc)(g) 234 MOVW LR, (g_sched+gobuf_lr)(g) 235 MOVW SP, (g_sched+gobuf_sp)(g) 236 237 // Set up morestack arguments to call f on a new stack. 238 // We set f's frame size to 1, as a hint to newstack 239 // that this is a call from runtime·newstackcall. 240 // If it turns out that f needs a larger frame than 241 // the default stack, f's usual stack growth prolog will 242 // allocate a new segment (and recopy the arguments). 243 MOVW 4(SP), R0 // fn 244 MOVW 8(SP), R1 // arg frame 245 MOVW 12(SP), R2 // arg size 246 247 MOVW R0, m_cret(m) // f's PC 248 MOVW R1, m_moreargp(m) // f's argument pointer 249 MOVW R2, m_moreargsize(m) // f's argument size 250 MOVW $1, R3 251 MOVW R3, m_moreframesize(m) // f's frame size 252 253 // Call newstack on m->g0's stack. 254 MOVW m_g0(m), g 255 MOVW (g_sched+gobuf_sp)(g), SP 256 B runtime·newstack(SB) 257 258 // reflect·call: call a function with the given argument list 259 // func call(f *FuncVal, arg *byte, argsize uint32). 260 // we don't have variable-sized frames, so we use a small number 261 // of constant-sized-frame functions to encode a few bits of size in the pc. 262 // Caution: ugly multiline assembly macros in your future! 263 264 #define DISPATCH(NAME,MAXSIZE) \ 265 CMP $MAXSIZE, R0; \ 266 B.HI 3(PC); \ 267 MOVW $runtime·NAME(SB), R1; \ 268 B (R1) 269 270 TEXT reflect·call(SB), NOSPLIT, $-4-12 271 MOVW argsize+8(FP), R0 272 DISPATCH(call16, 16) 273 DISPATCH(call32, 32) 274 DISPATCH(call64, 64) 275 DISPATCH(call128, 128) 276 DISPATCH(call256, 256) 277 DISPATCH(call512, 512) 278 DISPATCH(call1024, 1024) 279 DISPATCH(call2048, 2048) 280 DISPATCH(call4096, 4096) 281 DISPATCH(call8192, 8192) 282 DISPATCH(call16384, 16384) 283 DISPATCH(call32768, 32768) 284 DISPATCH(call65536, 65536) 285 DISPATCH(call131072, 131072) 286 DISPATCH(call262144, 262144) 287 DISPATCH(call524288, 524288) 288 DISPATCH(call1048576, 1048576) 289 DISPATCH(call2097152, 2097152) 290 DISPATCH(call4194304, 4194304) 291 DISPATCH(call8388608, 8388608) 292 DISPATCH(call16777216, 16777216) 293 DISPATCH(call33554432, 33554432) 294 DISPATCH(call67108864, 67108864) 295 DISPATCH(call134217728, 134217728) 296 DISPATCH(call268435456, 268435456) 297 DISPATCH(call536870912, 536870912) 298 DISPATCH(call1073741824, 1073741824) 299 MOVW $runtime·badreflectcall(SB), R1 300 B (R1) 301 302 #define CALLFN(NAME,MAXSIZE) \ 303 TEXT runtime·NAME(SB), 0, $MAXSIZE-12; \ 304 /* copy arguments to stack */ \ 305 MOVW argptr+4(FP), R0; \ 306 MOVW argsize+8(FP), R2; \ 307 ADD $4, SP, R1; \ 308 CMP $0, R2; \ 309 B.EQ 5(PC); \ 310 MOVBU.P 1(R0), R5; \ 311 MOVBU.P R5, 1(R1); \ 312 SUB $1, R2, R2; \ 313 B -5(PC); \ 314 /* call function */ \ 315 MOVW f+0(FP), R7; \ 316 MOVW (R7), R0; \ 317 BL (R0); \ 318 /* copy return values back */ \ 319 MOVW argptr+4(FP), R0; \ 320 MOVW argsize+8(FP), R2; \ 321 ADD $4, SP, R1; \ 322 CMP $0, R2; \ 323 RET.EQ ; \ 324 MOVBU.P 1(R1), R5; \ 325 MOVBU.P R5, 1(R0); \ 326 SUB $1, R2, R2; \ 327 B -5(PC) \ 328 329 CALLFN(call16, 16) 330 CALLFN(call32, 32) 331 CALLFN(call64, 64) 332 CALLFN(call128, 128) 333 CALLFN(call256, 256) 334 CALLFN(call512, 512) 335 CALLFN(call1024, 1024) 336 CALLFN(call2048, 2048) 337 CALLFN(call4096, 4096) 338 CALLFN(call8192, 8192) 339 CALLFN(call16384, 16384) 340 CALLFN(call32768, 32768) 341 CALLFN(call65536, 65536) 342 CALLFN(call131072, 131072) 343 CALLFN(call262144, 262144) 344 CALLFN(call524288, 524288) 345 CALLFN(call1048576, 1048576) 346 CALLFN(call2097152, 2097152) 347 CALLFN(call4194304, 4194304) 348 CALLFN(call8388608, 8388608) 349 CALLFN(call16777216, 16777216) 350 CALLFN(call33554432, 33554432) 351 CALLFN(call67108864, 67108864) 352 CALLFN(call134217728, 134217728) 353 CALLFN(call268435456, 268435456) 354 CALLFN(call536870912, 536870912) 355 CALLFN(call1073741824, 1073741824) 356 357 // Return point when leaving stack. 358 // using frame size $-4 means do not save LR on stack. 359 // 360 // Lessstack can appear in stack traces for the same reason 361 // as morestack; in that context, it has 0 arguments. 362 TEXT runtime·lessstack(SB), NOSPLIT, $-4-0 363 // Save return value in m->cret 364 MOVW R0, m_cret(m) 365 366 // Call oldstack on m->g0's stack. 367 MOVW m_g0(m), g 368 MOVW (g_sched+gobuf_sp)(g), SP 369 BL runtime·oldstack(SB) 370 371 // void jmpdefer(fn, sp); 372 // called from deferreturn. 373 // 1. grab stored LR for caller 374 // 2. sub 4 bytes to get back to BL deferreturn 375 // 3. B to fn 376 TEXT runtime·jmpdefer(SB), NOSPLIT, $0-8 377 MOVW 0(SP), LR 378 MOVW $-4(LR), LR // BL deferreturn 379 MOVW fn+0(FP), R7 380 MOVW argp+4(FP), SP 381 MOVW $-4(SP), SP // SP is 4 below argp, due to saved LR 382 MOVW 0(R7), R1 383 B (R1) 384 385 // Save state of caller into g->sched. Smashes R11. 386 TEXT gosave<>(SB),NOSPLIT,$0 387 MOVW LR, (g_sched+gobuf_pc)(g) 388 MOVW R13, (g_sched+gobuf_sp)(g) 389 MOVW $0, R11 390 MOVW R11, (g_sched+gobuf_lr)(g) 391 MOVW R11, (g_sched+gobuf_ret)(g) 392 MOVW R11, (g_sched+gobuf_ctxt)(g) 393 RET 394 395 // asmcgocall(void(*fn)(void*), void *arg) 396 // Call fn(arg) on the scheduler stack, 397 // aligned appropriately for the gcc ABI. 398 // See cgocall.c for more details. 399 TEXT runtime·asmcgocall(SB),NOSPLIT,$0-8 400 MOVW fn+0(FP), R1 401 MOVW arg+4(FP), R0 402 MOVW R13, R2 403 MOVW g, R5 404 405 // Figure out if we need to switch to m->g0 stack. 406 // We get called to create new OS threads too, and those 407 // come in on the m->g0 stack already. 408 MOVW m_g0(m), R3 409 CMP R3, g 410 BEQ 4(PC) 411 BL gosave<>(SB) 412 MOVW R3, g 413 MOVW (g_sched+gobuf_sp)(g), R13 414 415 // Now on a scheduling stack (a pthread-created stack). 416 SUB $24, R13 417 BIC $0x7, R13 // alignment for gcc ABI 418 MOVW R5, 20(R13) // save old g 419 MOVW R2, 16(R13) // save old SP 420 // R0 already contains the first argument 421 BL (R1) 422 423 // Restore registers, g, stack pointer. 424 MOVW 20(R13), g 425 MOVW 16(R13), R13 426 RET 427 428 // cgocallback(void (*fn)(void*), void *frame, uintptr framesize) 429 // Turn the fn into a Go func (by taking its address) and call 430 // cgocallback_gofunc. 431 TEXT runtime·cgocallback(SB),NOSPLIT,$12-12 432 MOVW $fn+0(FP), R0 433 MOVW R0, 4(R13) 434 MOVW frame+4(FP), R0 435 MOVW R0, 8(R13) 436 MOVW framesize+8(FP), R0 437 MOVW R0, 12(R13) 438 MOVW $runtime·cgocallback_gofunc(SB), R0 439 BL (R0) 440 RET 441 442 // cgocallback_gofunc(void (*fn)(void*), void *frame, uintptr framesize) 443 // See cgocall.c for more details. 444 TEXT runtime·cgocallback_gofunc(SB),NOSPLIT,$8-12 445 // Load m and g from thread-local storage. 446 MOVB runtime·iscgo(SB), R0 447 CMP $0, R0 448 BL.NE runtime·load_gm(SB) 449 450 // If m is nil, Go did not create the current thread. 451 // Call needm to obtain one for temporary use. 452 // In this case, we're running on the thread stack, so there's 453 // lots of space, but the linker doesn't know. Hide the call from 454 // the linker analysis by using an indirect call. 455 MOVW m, savedm-4(SP) 456 CMP $0, m 457 B.NE havem 458 MOVW $runtime·needm(SB), R0 459 BL (R0) 460 461 havem: 462 // Now there's a valid m, and we're running on its m->g0. 463 // Save current m->g0->sched.sp on stack and then set it to SP. 464 // Save current sp in m->g0->sched.sp in preparation for 465 // switch back to m->curg stack. 466 // NOTE: unwindm knows that the saved g->sched.sp is at 4(R13) aka savedsp-8(SP). 467 MOVW m_g0(m), R3 468 MOVW (g_sched+gobuf_sp)(R3), R4 469 MOVW R4, savedsp-8(SP) 470 MOVW R13, (g_sched+gobuf_sp)(R3) 471 472 // Switch to m->curg stack and call runtime.cgocallbackg. 473 // Because we are taking over the execution of m->curg 474 // but *not* resuming what had been running, we need to 475 // save that information (m->curg->sched) so we can restore it. 476 // We can restore m->curg->sched.sp easily, because calling 477 // runtime.cgocallbackg leaves SP unchanged upon return. 478 // To save m->curg->sched.pc, we push it onto the stack. 479 // This has the added benefit that it looks to the traceback 480 // routine like cgocallbackg is going to return to that 481 // PC (because the frame we allocate below has the same 482 // size as cgocallback_gofunc's frame declared above) 483 // so that the traceback will seamlessly trace back into 484 // the earlier calls. 485 // 486 // In the new goroutine, -8(SP) and -4(SP) are unused. 487 MOVW fn+4(FP), R0 488 MOVW frame+8(FP), R1 489 MOVW framesize+12(FP), R2 490 MOVW m_curg(m), g 491 MOVW (g_sched+gobuf_sp)(g), R4 // prepare stack as R4 492 MOVW (g_sched+gobuf_pc)(g), R5 493 MOVW R5, -12(R4) 494 MOVW $-12(R4), R13 495 BL runtime·cgocallbackg(SB) 496 497 // Restore g->sched (== m->curg->sched) from saved values. 498 MOVW 0(R13), R5 499 MOVW R5, (g_sched+gobuf_pc)(g) 500 MOVW $12(R13), R4 501 MOVW R4, (g_sched+gobuf_sp)(g) 502 503 // Switch back to m->g0's stack and restore m->g0->sched.sp. 504 // (Unlike m->curg, the g0 goroutine never uses sched.pc, 505 // so we do not have to restore it.) 506 MOVW m_g0(m), g 507 MOVW (g_sched+gobuf_sp)(g), R13 508 MOVW savedsp-8(SP), R4 509 MOVW R4, (g_sched+gobuf_sp)(g) 510 511 // If the m on entry was nil, we called needm above to borrow an m 512 // for the duration of the call. Since the call is over, return it with dropm. 513 MOVW savedm-4(SP), R6 514 CMP $0, R6 515 B.NE 3(PC) 516 MOVW $runtime·dropm(SB), R0 517 BL (R0) 518 519 // Done! 520 RET 521 522 // void setmg(M*, G*); set m and g. for use by needm. 523 TEXT runtime·setmg(SB), NOSPLIT, $0-8 524 MOVW mm+0(FP), m 525 MOVW gg+4(FP), g 526 527 // Save m and g to thread-local storage. 528 MOVB runtime·iscgo(SB), R0 529 CMP $0, R0 530 BL.NE runtime·save_gm(SB) 531 532 RET 533 534 TEXT runtime·getcallerpc(SB),NOSPLIT,$-4-4 535 MOVW 0(SP), R0 536 RET 537 538 TEXT runtime·setcallerpc(SB),NOSPLIT,$-4-8 539 MOVW x+4(FP), R0 540 MOVW R0, 0(SP) 541 RET 542 543 TEXT runtime·getcallersp(SB),NOSPLIT,$-4-4 544 MOVW 0(FP), R0 545 MOVW $-4(R0), R0 546 RET 547 548 TEXT runtime·emptyfunc(SB),0,$0-0 549 RET 550 551 TEXT runtime·abort(SB),NOSPLIT,$-4-0 552 MOVW $0, R0 553 MOVW (R0), R1 554 555 // bool armcas(int32 *val, int32 old, int32 new) 556 // Atomically: 557 // if(*val == old){ 558 // *val = new; 559 // return 1; 560 // }else 561 // return 0; 562 // 563 // To implement runtime·cas in sys_$GOOS_arm.s 564 // using the native instructions, use: 565 // 566 // TEXT runtime·cas(SB),NOSPLIT,$0 567 // B runtime·armcas(SB) 568 // 569 TEXT runtime·armcas(SB),NOSPLIT,$0-12 570 MOVW valptr+0(FP), R1 571 MOVW old+4(FP), R2 572 MOVW new+8(FP), R3 573 casl: 574 LDREX (R1), R0 575 CMP R0, R2 576 BNE casfail 577 STREX R3, (R1), R0 578 CMP $0, R0 579 BNE casl 580 MOVW $1, R0 581 RET 582 casfail: 583 MOVW $0, R0 584 RET 585 586 TEXT runtime·stackguard(SB),NOSPLIT,$0-8 587 MOVW R13, R1 588 MOVW g_stackguard(g), R2 589 MOVW R1, sp+0(FP) 590 MOVW R2, limit+4(FP) 591 RET 592 593 // AES hashing not implemented for ARM 594 TEXT runtime·aeshash(SB),NOSPLIT,$-4-0 595 MOVW $0, R0 596 MOVW (R0), R1 597 TEXT runtime·aeshash32(SB),NOSPLIT,$-4-0 598 MOVW $0, R0 599 MOVW (R0), R1 600 TEXT runtime·aeshash64(SB),NOSPLIT,$-4-0 601 MOVW $0, R0 602 MOVW (R0), R1 603 TEXT runtime·aeshashstr(SB),NOSPLIT,$-4-0 604 MOVW $0, R0 605 MOVW (R0), R1 606 607 TEXT runtime·memeq(SB),NOSPLIT,$-4-12 608 MOVW a+0(FP), R1 609 MOVW b+4(FP), R2 610 MOVW n+8(FP), R3 611 ADD R1, R3, R6 612 MOVW $1, R0 613 _next: 614 CMP R1, R6 615 RET.EQ 616 MOVBU.P 1(R1), R4 617 MOVBU.P 1(R2), R5 618 CMP R4, R5 619 BEQ _next 620 621 MOVW $0, R0 622 RET 623 624 // We have to resort to TLS variable to save g(R10) and 625 // m(R9). One reason is that external code might trigger 626 // SIGSEGV, and our runtime.sigtramp don't even know we 627 // are in external code, and will continue to use R10/R9, 628 // this might as well result in another SIGSEGV. 629 // Note: all three functions will clobber R0, and the last 630 // two can be called from 5c ABI code. 631 632 // g (R10) at 8(TP), m (R9) at 12(TP) 633 TEXT runtime·save_gm(SB),NOSPLIT,$0 634 MRC 15, 0, R0, C13, C0, 3 // Fetch TLS register 635 MOVW g, 8(R0) 636 MOVW m, 12(R0) 637 RET 638 639 TEXT runtime·load_gm(SB),NOSPLIT,$0 640 MRC 15, 0, R0, C13, C0, 3 // Fetch TLS register 641 MOVW 8(R0), g 642 MOVW 12(R0), m 643 RET 644 645 // void setmg_gcc(M*, G*); set m and g called from gcc. 646 TEXT setmg_gcc<>(SB),NOSPLIT,$0 647 MOVW R0, m 648 MOVW R1, g 649 B runtime·save_gm(SB) 650 651 652 // TODO: share code with memeq? 653 TEXT bytes·Equal(SB),NOSPLIT,$0 654 MOVW a_len+4(FP), R1 655 MOVW b_len+16(FP), R3 656 657 CMP R1, R3 // unequal lengths are not equal 658 B.NE _notequal 659 660 MOVW a+0(FP), R0 661 MOVW b+12(FP), R2 662 ADD R0, R1 // end 663 664 _byteseq_next: 665 CMP R0, R1 666 B.EQ _equal // reached the end 667 MOVBU.P 1(R0), R4 668 MOVBU.P 1(R2), R5 669 CMP R4, R5 670 B.EQ _byteseq_next 671 672 _notequal: 673 MOVW $0, R0 674 MOVBU R0, ret+24(FP) 675 RET 676 677 _equal: 678 MOVW $1, R0 679 MOVBU R0, ret+24(FP) 680 RET 681 682 TEXT bytes·IndexByte(SB),NOSPLIT,$0 683 MOVW s+0(FP), R0 684 MOVW s_len+4(FP), R1 685 MOVBU c+12(FP), R2 // byte to find 686 MOVW R0, R4 // store base for later 687 ADD R0, R1 // end 688 689 _loop: 690 CMP R0, R1 691 B.EQ _notfound 692 MOVBU.P 1(R0), R3 693 CMP R2, R3 694 B.NE _loop 695 696 SUB $1, R0 // R0 will be one beyond the position we want 697 SUB R4, R0 // remove base 698 MOVW R0, ret+16(FP) 699 RET 700 701 _notfound: 702 MOVW $-1, R0 703 MOVW R0, ret+16(FP) 704 RET 705 706 TEXT strings·IndexByte(SB),NOSPLIT,$0 707 MOVW s+0(FP), R0 708 MOVW s_len+4(FP), R1 709 MOVBU c+8(FP), R2 // byte to find 710 MOVW R0, R4 // store base for later 711 ADD R0, R1 // end 712 713 _sib_loop: 714 CMP R0, R1 715 B.EQ _sib_notfound 716 MOVBU.P 1(R0), R3 717 CMP R2, R3 718 B.NE _sib_loop 719 720 SUB $1, R0 // R0 will be one beyond the position we want 721 SUB R4, R0 // remove base 722 MOVW R0, ret+12(FP) 723 RET 724 725 _sib_notfound: 726 MOVW $-1, R0 727 MOVW R0, ret+12(FP) 728 RET