github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/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 7 // using frame size $-4 means do not save LR on stack. 8 TEXT _rt0_arm(SB),7,$-4 9 MOVW $0xcafebabe, R12 10 11 // copy arguments forward on an even stack 12 // use R13 instead of SP to avoid linker rewriting the offsets 13 MOVW 0(R13), R0 // argc 14 MOVW $4(R13), R1 // argv 15 SUB $64, R13 // plenty of scratch 16 AND $~7, R13 17 MOVW R0, 60(R13) // save argc, argv away 18 MOVW R1, 64(R13) 19 20 // set up m and g registers 21 // g is R10, m is R9 22 MOVW $runtime·g0(SB), g 23 MOVW $runtime·m0(SB), m 24 25 // save m->g0 = g0 26 MOVW g, m_g0(m) 27 28 // create istack out of the OS stack 29 MOVW $(-8192+104)(R13), R0 30 MOVW R0, g_stackguard(g) // (w 104b guard) 31 MOVW R13, g_stackbase(g) 32 BL runtime·emptyfunc(SB) // fault if stack check is wrong 33 34 // if there is an _cgo_init, call it. 35 MOVW _cgo_init(SB), R2 36 CMP $0, R2 37 MOVW.NE g, R0 // first argument of _cgo_init is g 38 BL.NE (R2) // will clobber R0-R3 39 40 BL runtime·checkgoarm(SB) 41 BL runtime·check(SB) 42 43 // saved argc, argv 44 MOVW 60(R13), R0 45 MOVW R0, 4(R13) 46 MOVW 64(R13), R1 47 MOVW R1, 8(R13) 48 BL runtime·args(SB) 49 BL runtime·osinit(SB) 50 BL runtime·hashinit(SB) 51 BL runtime·schedinit(SB) 52 53 // create a new goroutine to start program 54 MOVW $runtime·main·f(SB), R0 55 MOVW.W R0, -4(R13) 56 MOVW $8, R0 57 MOVW.W R0, -4(R13) 58 MOVW $0, R0 59 MOVW.W R0, -4(R13) // push $0 as guard 60 BL runtime·newproc(SB) 61 MOVW $12(R13), R13 // pop args and LR 62 63 // start this M 64 BL runtime·mstart(SB) 65 66 MOVW $1234, R0 67 MOVW $1000, R1 68 MOVW R0, (R1) // fail hard 69 70 DATA runtime·main·f+0(SB)/4,$runtime·main(SB) 71 GLOBL runtime·main·f(SB),8,$4 72 73 TEXT runtime·breakpoint(SB),7,$0 74 // gdb won't skip this breakpoint instruction automatically, 75 // so you must manually "set $pc+=4" to skip it and continue. 76 WORD $0xe1200071 // BKPT 0x0001 77 RET 78 79 GLOBL runtime·goarm(SB), $4 80 TEXT runtime·asminit(SB),7,$0 81 // disable runfast (flush-to-zero) mode of vfp if runtime.goarm > 5 82 MOVW runtime·goarm(SB), R11 83 CMP $5, R11 84 BLE 4(PC) 85 WORD $0xeef1ba10 // vmrs r11, fpscr 86 BIC $(1<<24), R11 87 WORD $0xeee1ba10 // vmsr fpscr, r11 88 RET 89 90 /* 91 * go-routine 92 */ 93 94 // void gosave(Gobuf*) 95 // save state in Gobuf; setjmp 96 TEXT runtime·gosave(SB), 7, $-4 97 MOVW 0(FP), R0 // gobuf 98 MOVW SP, gobuf_sp(R0) 99 MOVW LR, gobuf_pc(R0) 100 MOVW g, gobuf_g(R0) 101 RET 102 103 // void gogo(Gobuf*, uintptr) 104 // restore state from Gobuf; longjmp 105 TEXT runtime·gogo(SB), 7, $-4 106 MOVW 0(FP), R1 // gobuf 107 MOVW gobuf_g(R1), g 108 MOVW 0(g), R2 // make sure g != nil 109 MOVW _cgo_save_gm(SB), R2 110 CMP $0, R2 // if in Cgo, we have to save g and m 111 BL.NE (R2) // this call will clobber R0 112 MOVW 4(FP), R0 // return 2nd arg 113 MOVW gobuf_sp(R1), SP // restore SP 114 MOVW gobuf_pc(R1), PC 115 116 // void gogocall(Gobuf*, void (*fn)(void), uintptr r7) 117 // restore state from Gobuf but then call fn. 118 // (call fn, returning to state in Gobuf) 119 // using frame size $-4 means do not save LR on stack. 120 TEXT runtime·gogocall(SB), 7, $-4 121 MOVW 0(FP), R3 // gobuf 122 MOVW 4(FP), R1 // fn 123 MOVW gobuf_g(R3), g 124 MOVW 0(g), R0 // make sure g != nil 125 MOVW _cgo_save_gm(SB), R0 126 CMP $0, R0 // if in Cgo, we have to save g and m 127 BL.NE (R0) // this call will clobber R0 128 MOVW 8(FP), R7 // context 129 MOVW gobuf_sp(R3), SP // restore SP 130 MOVW gobuf_pc(R3), LR 131 MOVW R1, PC 132 133 // void gogocallfn(Gobuf*, FuncVal*) 134 // restore state from Gobuf but then call fn. 135 // (call fn, returning to state in Gobuf) 136 // using frame size $-4 means do not save LR on stack. 137 TEXT runtime·gogocallfn(SB), 7, $-4 138 MOVW 0(FP), R3 // gobuf 139 MOVW 4(FP), R1 // fn 140 MOVW gobuf_g(R3), g 141 MOVW 0(g), R0 // make sure g != nil 142 MOVW _cgo_save_gm(SB), R0 143 CMP $0, R0 // if in Cgo, we have to save g and m 144 BL.NE (R0) // this call will clobber R0 145 MOVW gobuf_sp(R3), SP // restore SP 146 MOVW gobuf_pc(R3), LR 147 MOVW R1, R7 148 MOVW 0(R1), PC 149 150 // void mcall(void (*fn)(G*)) 151 // Switch to m->g0's stack, call fn(g). 152 // Fn must never return. It should gogo(&g->sched) 153 // to keep running g. 154 TEXT runtime·mcall(SB), 7, $-4 155 MOVW fn+0(FP), R0 156 157 // Save caller state in g->gobuf. 158 MOVW SP, (g_sched+gobuf_sp)(g) 159 MOVW LR, (g_sched+gobuf_pc)(g) 160 MOVW g, (g_sched+gobuf_g)(g) 161 162 // Switch to m->g0 & its stack, call fn. 163 MOVW g, R1 164 MOVW m_g0(m), g 165 CMP g, R1 166 BL.EQ runtime·badmcall(SB) 167 MOVW (g_sched+gobuf_sp)(g), SP 168 SUB $8, SP 169 MOVW R1, 4(SP) 170 BL (R0) 171 BL runtime·badmcall2(SB) 172 RET 173 174 /* 175 * support for morestack 176 */ 177 178 // Called during function prolog when more stack is needed. 179 // R1 frame size 180 // R2 arg size 181 // R3 prolog's LR 182 // NB. we do not save R0 because we've forced 5c to pass all arguments 183 // on the stack. 184 // using frame size $-4 means do not save LR on stack. 185 TEXT runtime·morestack(SB),7,$-4 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 // Save in m. 192 MOVW R7, m_cret(m) // function context 193 MOVW R1, m_moreframesize(m) 194 MOVW R2, m_moreargsize(m) 195 196 // Called from f. 197 // Set m->morebuf to f's caller. 198 MOVW R3, (m_morebuf+gobuf_pc)(m) // f's caller's PC 199 MOVW SP, (m_morebuf+gobuf_sp)(m) // f's caller's SP 200 MOVW $4(SP), R3 // f's argument pointer 201 MOVW R3, m_moreargp(m) 202 MOVW g, (m_morebuf+gobuf_g)(m) 203 204 // Set m->morepc to f's PC. 205 MOVW LR, m_morepc(m) 206 207 // Call newstack on m->g0's stack. 208 MOVW m_g0(m), g 209 MOVW (g_sched+gobuf_sp)(g), SP 210 B runtime·newstack(SB) 211 212 // Called from reflection library. Mimics morestack, 213 // reuses stack growth code to create a frame 214 // with the desired args running the desired function. 215 // 216 // func call(fn *byte, arg *byte, argsize uint32). 217 TEXT reflect·call(SB), 7, $-4 218 // Save our caller's state as the PC and SP to 219 // restore when returning from f. 220 MOVW LR, (m_morebuf+gobuf_pc)(m) // our caller's PC 221 MOVW SP, (m_morebuf+gobuf_sp)(m) // our caller's SP 222 MOVW g, (m_morebuf+gobuf_g)(m) 223 224 // Set up morestack arguments to call f on a new stack. 225 // We set f's frame size to 1, as a hint to newstack 226 // that this is a call from reflect·call. 227 // If it turns out that f needs a larger frame than 228 // the default stack, f's usual stack growth prolog will 229 // allocate a new segment (and recopy the arguments). 230 MOVW 4(SP), R0 // fn 231 MOVW 8(SP), R1 // arg frame 232 MOVW 12(SP), R2 // arg size 233 234 MOVW R0, m_morepc(m) // f's PC 235 MOVW R1, m_moreargp(m) // f's argument pointer 236 MOVW R2, m_moreargsize(m) // f's argument size 237 MOVW $1, R3 238 MOVW R3, m_moreframesize(m) // f's frame size 239 240 // Call newstack on m->g0's stack. 241 MOVW m_g0(m), g 242 MOVW (g_sched+gobuf_sp)(g), SP 243 B runtime·newstack(SB) 244 245 // Return point when leaving stack. 246 // using frame size $-4 means do not save LR on stack. 247 TEXT runtime·lessstack(SB), 7, $-4 248 // Save return value in m->cret 249 MOVW R0, m_cret(m) 250 251 // Call oldstack on m->g0's stack. 252 MOVW m_g0(m), g 253 MOVW (g_sched+gobuf_sp)(g), SP 254 B runtime·oldstack(SB) 255 256 // void jmpdefer(fn, sp); 257 // called from deferreturn. 258 // 1. grab stored LR for caller 259 // 2. sub 4 bytes to get back to BL deferreturn 260 // 3. B to fn 261 TEXT runtime·jmpdefer(SB), 7, $0 262 MOVW 0(SP), LR 263 MOVW $-4(LR), LR // BL deferreturn 264 MOVW fn+0(FP), R7 265 MOVW argp+4(FP), SP 266 MOVW $-4(SP), SP // SP is 4 below argp, due to saved LR 267 MOVW 0(R7), R1 268 B (R1) 269 270 // Dummy function to use in saved gobuf.PC, 271 // to match SP pointing at a return address. 272 // The gobuf.PC is unused by the contortions here 273 // but setting it to return will make the traceback code work. 274 TEXT return<>(SB),7,$0 275 RET 276 277 // asmcgocall(void(*fn)(void*), void *arg) 278 // Call fn(arg) on the scheduler stack, 279 // aligned appropriately for the gcc ABI. 280 // See cgocall.c for more details. 281 TEXT runtime·asmcgocall(SB),7,$0 282 MOVW fn+0(FP), R1 283 MOVW arg+4(FP), R0 284 MOVW R13, R2 285 MOVW g, R5 286 287 // Figure out if we need to switch to m->g0 stack. 288 // We get called to create new OS threads too, and those 289 // come in on the m->g0 stack already. 290 MOVW m_g0(m), R3 291 CMP R3, g 292 BEQ 7(PC) 293 MOVW R13, (g_sched + gobuf_sp)(g) 294 MOVW $return<>(SB), R4 295 MOVW R4, (g_sched+gobuf_pc)(g) 296 MOVW g, (g_sched+gobuf_g)(g) 297 MOVW R3, g 298 MOVW (g_sched+gobuf_sp)(g), R13 299 300 // Now on a scheduling stack (a pthread-created stack). 301 SUB $24, R13 302 BIC $0x7, R13 // alignment for gcc ABI 303 MOVW R5, 20(R13) // save old g 304 MOVW R2, 16(R13) // save old SP 305 // R0 already contains the first argument 306 BL (R1) 307 308 // Restore registers, g, stack pointer. 309 MOVW 20(R13), g 310 MOVW 16(R13), R13 311 RET 312 313 // cgocallback(void (*fn)(void*), void *frame, uintptr framesize) 314 // Turn the fn into a Go func (by taking its address) and call 315 // cgocallback_gofunc. 316 TEXT runtime·cgocallback(SB),7,$12 317 MOVW $fn+0(FP), R0 318 MOVW R0, 4(R13) 319 MOVW frame+4(FP), R0 320 MOVW R0, 8(R13) 321 MOVW framesize+8(FP), R0 322 MOVW R0, 12(R13) 323 MOVW $runtime·cgocallback_gofunc(SB), R0 324 BL (R0) 325 RET 326 327 // cgocallback_gofunc(void (*fn)(void*), void *frame, uintptr framesize) 328 // See cgocall.c for more details. 329 TEXT runtime·cgocallback_gofunc(SB),7,$12 330 // Load m and g from thread-local storage. 331 MOVW _cgo_load_gm(SB), R0 332 CMP $0, R0 333 BL.NE (R0) 334 335 // If m is nil, Go did not create the current thread. 336 // Call needm to obtain one for temporary use. 337 // In this case, we're running on the thread stack, so there's 338 // lots of space, but the linker doesn't know. Hide the call from 339 // the linker analysis by using an indirect call. 340 MOVW m, savedm-12(SP) 341 CMP $0, m 342 B.NE havem 343 MOVW $runtime·needm(SB), R0 344 BL (R0) 345 346 havem: 347 // Now there's a valid m, and we're running on its m->g0. 348 // Save current m->g0->sched.sp on stack and then set it to SP. 349 // Save current sp in m->g0->sched.sp in preparation for 350 // switch back to m->curg stack. 351 MOVW m_g0(m), R3 352 MOVW (g_sched+gobuf_sp)(R3), R4 353 MOVW.W R4, -4(R13) 354 MOVW R13, (g_sched+gobuf_sp)(R3) 355 356 // Switch to m->curg stack and call runtime.cgocallbackg 357 // with the three arguments. Because we are taking over 358 // the execution of m->curg but *not* resuming what had 359 // been running, we need to save that information (m->curg->gobuf) 360 // so that we can restore it when we're done. 361 // We can restore m->curg->gobuf.sp easily, because calling 362 // runtime.cgocallbackg leaves SP unchanged upon return. 363 // To save m->curg->gobuf.pc, we push it onto the stack. 364 // This has the added benefit that it looks to the traceback 365 // routine like cgocallbackg is going to return to that 366 // PC (because we defined cgocallbackg to have 367 // a frame size of 12, the same amount that we use below), 368 // so that the traceback will seamlessly trace back into 369 // the earlier calls. 370 MOVW fn+4(FP), R0 371 MOVW frame+8(FP), R1 372 MOVW framesize+12(FP), R2 373 374 MOVW m_curg(m), g 375 MOVW (g_sched+gobuf_sp)(g), R4 // prepare stack as R4 376 377 // Push gobuf.pc 378 MOVW (g_sched+gobuf_pc)(g), R5 379 MOVW.W R5, -16(R4) 380 381 // Push arguments to cgocallbackg. 382 // Frame size here must match the frame size above 383 // to trick traceback routines into doing the right thing. 384 MOVW R0, 4(R4) 385 MOVW R1, 8(R4) 386 MOVW R2, 12(R4) 387 388 // Switch stack and make the call. 389 MOVW R4, R13 390 BL runtime·cgocallbackg(SB) 391 392 // Restore g->gobuf (== m->curg->gobuf) from saved values. 393 MOVW 0(R13), R5 394 MOVW R5, (g_sched+gobuf_pc)(g) 395 ADD $(12+4), R13, R4 396 MOVW R4, (g_sched+gobuf_sp)(g) 397 398 // Switch back to m->g0's stack and restore m->g0->sched.sp. 399 // (Unlike m->curg, the g0 goroutine never uses sched.pc, 400 // so we do not have to restore it.) 401 MOVW m_g0(m), g 402 MOVW (g_sched+gobuf_sp)(g), R13 403 // POP R6 404 MOVW 0(R13), R6 405 ADD $4, R13 406 MOVW R6, (g_sched+gobuf_sp)(g) 407 408 // If the m on entry was nil, we called needm above to borrow an m 409 // for the duration of the call. Since the call is over, return it with dropm. 410 MOVW savedm-12(SP), R6 411 CMP $0, R6 412 B.NE 3(PC) 413 MOVW $runtime·dropm(SB), R0 414 BL (R0) 415 416 // Done! 417 RET 418 419 // void setmg(M*, G*); set m and g. for use by needm. 420 TEXT runtime·setmg(SB), 7, $0 421 MOVW mm+0(FP), m 422 MOVW gg+4(FP), g 423 424 // Save m and g to thread-local storage. 425 MOVW _cgo_save_gm(SB), R0 426 CMP $0, R0 427 BL.NE (R0) 428 429 RET 430 431 TEXT runtime·getcallerpc(SB),7,$-4 432 MOVW 0(SP), R0 433 RET 434 435 TEXT runtime·setcallerpc(SB),7,$-4 436 MOVW x+4(FP), R0 437 MOVW R0, 0(SP) 438 RET 439 440 TEXT runtime·getcallersp(SB),7,$-4 441 MOVW 0(FP), R0 442 MOVW $-4(R0), R0 443 RET 444 445 TEXT runtime·emptyfunc(SB),0,$0 446 RET 447 448 TEXT runtime·abort(SB),7,$-4 449 MOVW $0, R0 450 MOVW (R0), R1 451 452 // bool armcas(int32 *val, int32 old, int32 new) 453 // Atomically: 454 // if(*val == old){ 455 // *val = new; 456 // return 1; 457 // }else 458 // return 0; 459 // 460 // To implement runtime·cas in sys_$GOOS_arm.s 461 // using the native instructions, use: 462 // 463 // TEXT runtime·cas(SB),7,$0 464 // B runtime·armcas(SB) 465 // 466 TEXT runtime·armcas(SB),7,$0 467 MOVW valptr+0(FP), R1 468 MOVW old+4(FP), R2 469 MOVW new+8(FP), R3 470 casl: 471 LDREX (R1), R0 472 CMP R0, R2 473 BNE casfail 474 STREX R3, (R1), R0 475 CMP $0, R0 476 BNE casl 477 MOVW $1, R0 478 RET 479 casfail: 480 MOVW $0, R0 481 RET 482 483 TEXT runtime·stackguard(SB),7,$0 484 MOVW R13, R1 485 MOVW g_stackguard(g), R2 486 MOVW R1, sp+0(FP) 487 MOVW R2, limit+4(FP) 488 RET 489 490 // AES hashing not implemented for ARM 491 TEXT runtime·aeshash(SB),7,$-4 492 MOVW $0, R0 493 MOVW (R0), R1 494 TEXT runtime·aeshash32(SB),7,$-4 495 MOVW $0, R0 496 MOVW (R0), R1 497 TEXT runtime·aeshash64(SB),7,$-4 498 MOVW $0, R0 499 MOVW (R0), R1 500 TEXT runtime·aeshashstr(SB),7,$-4 501 MOVW $0, R0 502 MOVW (R0), R1 503 504 TEXT runtime·memeq(SB),7,$-4 505 MOVW a+0(FP), R1 506 MOVW b+4(FP), R2 507 MOVW n+8(FP), R3 508 ADD R1, R3, R6 509 MOVW $1, R0 510 _next: 511 CMP R1, R6 512 RET.EQ 513 MOVBU.P 1(R1), R4 514 MOVBU.P 1(R2), R5 515 CMP R4, R5 516 BEQ _next 517 518 MOVW $0, R0 519 RET