diff options
author | Michael Stapelberg <stapelberg@debian.org> | 2013-03-04 21:27:36 +0100 |
---|---|---|
committer | Michael Stapelberg <michael@stapelberg.de> | 2013-03-04 21:27:36 +0100 |
commit | 04b08da9af0c450d645ab7389d1467308cfc2db8 (patch) | |
tree | db247935fa4f2f94408edc3acd5d0d4f997aa0d8 /src/pkg/runtime/asm_arm.s | |
parent | 917c5fb8ec48e22459d77e3849e6d388f93d3260 (diff) | |
download | golang-upstream/1.1_hg20130304.tar.gz |
Imported Upstream version 1.1~hg20130304upstream/1.1_hg20130304
Diffstat (limited to 'src/pkg/runtime/asm_arm.s')
-rw-r--r-- | src/pkg/runtime/asm_arm.s | 265 |
1 files changed, 217 insertions, 48 deletions
diff --git a/src/pkg/runtime/asm_arm.s b/src/pkg/runtime/asm_arm.s index 423fda7a0..45b53541b 100644 --- a/src/pkg/runtime/asm_arm.s +++ b/src/pkg/runtime/asm_arm.s @@ -31,6 +31,13 @@ TEXT _rt0_arm(SB),7,$-4 MOVW R13, g_stackbase(g) BL runtime·emptyfunc(SB) // fault if stack check is wrong + // if there is an _cgo_init, call it. + MOVW _cgo_init(SB), R2 + CMP $0, R2 + MOVW.NE g, R0 // first argument of _cgo_init is g + BL.NE (R2) // will clobber R0-R3 + + BL runtime·checkgoarm(SB) BL runtime·check(SB) // saved argc, argv @@ -43,7 +50,7 @@ TEXT _rt0_arm(SB),7,$-4 BL runtime·schedinit(SB) // create a new goroutine to start program - MOVW $runtime·main(SB), R0 + MOVW $runtime·main·f(SB), R0 MOVW.W R0, -4(R13) MOVW $8, R0 MOVW.W R0, -4(R13) @@ -58,24 +65,25 @@ TEXT _rt0_arm(SB),7,$-4 MOVW $1234, R0 MOVW $1000, R1 MOVW R0, (R1) // fail hard - B runtime·_dep_dummy(SB) // Never reached - -// TODO(kaib): remove these once i actually understand how the linker removes symbols -// pull in dummy dependencies -TEXT runtime·_dep_dummy(SB),7,$0 - BL _div(SB) - BL _divu(SB) - BL _mod(SB) - BL _modu(SB) - BL _modu(SB) - BL _sfloat(SB) + +DATA runtime·main·f+0(SB)/4,$runtime·main(SB) +GLOBL runtime·main·f(SB),8,$4 TEXT runtime·breakpoint(SB),7,$0 - // no breakpoint yet; let program exit + // gdb won't skip this breakpoint instruction automatically, + // so you must manually "set $pc+=4" to skip it and continue. + WORD $0xe1200071 // BKPT 0x0001 RET +GLOBL runtime·goarm(SB), $4 TEXT runtime·asminit(SB),7,$0 - // No per-thread init. + // disable runfast (flush-to-zero) mode of vfp if runtime.goarm > 5 + MOVW runtime·goarm(SB), R11 + CMP $5, R11 + BLE 4(PC) + WORD $0xeef1ba10 // vmrs r11, fpscr + BIC $(1<<24), R11 + WORD $0xeee1ba10 // vmsr fpscr, r11 RET /* @@ -95,26 +103,49 @@ TEXT runtime·gosave(SB), 7, $-4 // restore state from Gobuf; longjmp TEXT runtime·gogo(SB), 7, $-4 MOVW 0(FP), R1 // gobuf - MOVW 4(FP), R0 // return 2nd arg MOVW gobuf_g(R1), g MOVW 0(g), R2 // make sure g != nil + MOVW _cgo_save_gm(SB), R2 + CMP $0, R2 // if in Cgo, we have to save g and m + BL.NE (R2) // this call will clobber R0 + MOVW 4(FP), R0 // return 2nd arg MOVW gobuf_sp(R1), SP // restore SP MOVW gobuf_pc(R1), PC -// void gogocall(Gobuf*, void (*fn)(void)) +// void gogocall(Gobuf*, void (*fn)(void), uintptr r7) // restore state from Gobuf but then call fn. // (call fn, returning to state in Gobuf) // using frame size $-4 means do not save LR on stack. TEXT runtime·gogocall(SB), 7, $-4 - MOVW 0(FP), R0 // gobuf + MOVW 0(FP), R3 // gobuf MOVW 4(FP), R1 // fn - MOVW 8(FP), R2 // fp offset - MOVW gobuf_g(R0), g - MOVW 0(g), R3 // make sure g != nil - MOVW gobuf_sp(R0), SP // restore SP - MOVW gobuf_pc(R0), LR + MOVW gobuf_g(R3), g + MOVW 0(g), R0 // make sure g != nil + MOVW _cgo_save_gm(SB), R0 + CMP $0, R0 // if in Cgo, we have to save g and m + BL.NE (R0) // this call will clobber R0 + MOVW 8(FP), R7 // context + MOVW gobuf_sp(R3), SP // restore SP + MOVW gobuf_pc(R3), LR MOVW R1, PC +// void gogocallfn(Gobuf*, FuncVal*) +// restore state from Gobuf but then call fn. +// (call fn, returning to state in Gobuf) +// using frame size $-4 means do not save LR on stack. +TEXT runtime·gogocallfn(SB), 7, $-4 + MOVW 0(FP), R3 // gobuf + MOVW 4(FP), R1 // fn + MOVW gobuf_g(R3), g + MOVW 0(g), R0 // make sure g != nil + MOVW _cgo_save_gm(SB), R0 + CMP $0, R0 // if in Cgo, we have to save g and m + BL.NE (R0) // this call will clobber R0 + MOVW gobuf_sp(R3), SP // restore SP + MOVW gobuf_pc(R3), LR + MOVW R1, R7 + MOVW 0(R1), PC + // void mcall(void (*fn)(G*)) // Switch to m->g0's stack, call fn(g). // Fn must never return. It should gogo(&g->sched) @@ -157,6 +188,7 @@ TEXT runtime·morestack(SB),7,$-4 BL.EQ runtime·abort(SB) // Save in m. + MOVW R7, m_cret(m) // function context MOVW R1, m_moreframesize(m) MOVW R2, m_moreargsize(m) @@ -228,28 +260,175 @@ TEXT runtime·lessstack(SB), 7, $-4 TEXT runtime·jmpdefer(SB), 7, $0 MOVW 0(SP), LR MOVW $-4(LR), LR // BL deferreturn - MOVW fn+0(FP), R0 + MOVW fn+0(FP), R7 MOVW argp+4(FP), SP MOVW $-4(SP), SP // SP is 4 below argp, due to saved LR - B (R0) + MOVW 0(R7), R1 + B (R1) + +// Dummy function to use in saved gobuf.PC, +// to match SP pointing at a return address. +// The gobuf.PC is unused by the contortions here +// but setting it to return will make the traceback code work. +TEXT return<>(SB),7,$0 + RET +// asmcgocall(void(*fn)(void*), void *arg) +// Call fn(arg) on the scheduler stack, +// aligned appropriately for the gcc ABI. +// See cgocall.c for more details. TEXT runtime·asmcgocall(SB),7,$0 - B runtime·cgounimpl(SB) + MOVW fn+0(FP), R1 + MOVW arg+4(FP), R0 + MOVW R13, R2 + MOVW g, R5 + + // Figure out if we need to switch to m->g0 stack. + // We get called to create new OS threads too, and those + // come in on the m->g0 stack already. + MOVW m_g0(m), R3 + CMP R3, g + BEQ 7(PC) + MOVW R13, (g_sched + gobuf_sp)(g) + MOVW $return<>(SB), R4 + MOVW R4, (g_sched+gobuf_pc)(g) + MOVW g, (g_sched+gobuf_g)(g) + MOVW R3, g + MOVW (g_sched+gobuf_sp)(g), R13 + + // Now on a scheduling stack (a pthread-created stack). + SUB $24, R13 + BIC $0x7, R13 // alignment for gcc ABI + MOVW R5, 20(R13) // save old g + MOVW R2, 16(R13) // save old SP + // R0 already contains the first argument + BL (R1) + + // Restore registers, g, stack pointer. + MOVW 20(R13), g + MOVW 16(R13), R13 + RET -TEXT runtime·cgocallback(SB),7,$0 - B runtime·cgounimpl(SB) +// cgocallback(void (*fn)(void*), void *frame, uintptr framesize) +// Turn the fn into a Go func (by taking its address) and call +// cgocallback_gofunc. +TEXT runtime·cgocallback(SB),7,$12 + MOVW $fn+0(FP), R0 + MOVW R0, 4(R13) + MOVW frame+4(FP), R0 + MOVW R0, 8(R13) + MOVW framesize+8(FP), R0 + MOVW R0, 12(R13) + MOVW $runtime·cgocallback_gofunc(SB), R0 + BL (R0) + RET + +// cgocallback_gofunc(void (*fn)(void*), void *frame, uintptr framesize) +// See cgocall.c for more details. +TEXT runtime·cgocallback_gofunc(SB),7,$16 + // Load m and g from thread-local storage. + MOVW _cgo_load_gm(SB), R0 + CMP $0, R0 + BL.NE (R0) + + // If m is nil, Go did not create the current thread. + // Call needm to obtain one for temporary use. + // In this case, we're running on the thread stack, so there's + // lots of space, but the linker doesn't know. Hide the call from + // the linker analysis by using an indirect call. + MOVW m, savedm-16(SP) + CMP $0, m + B.NE havem + MOVW $runtime·needm(SB), R0 + BL (R0) + +havem: + // Now there's a valid m, and we're running on its m->g0. + // Save current m->g0->sched.sp on stack and then set it to SP. + // Save current sp in m->g0->sched.sp in preparation for + // switch back to m->curg stack. + MOVW fn+0(FP), R0 + MOVW frame+4(FP), R1 + MOVW framesize+8(FP), R2 + + MOVW m_g0(m), R3 + MOVW (g_sched+gobuf_sp)(R3), R4 + MOVW.W R4, -4(R13) + MOVW R13, (g_sched+gobuf_sp)(R3) + + // Switch to m->curg stack and call runtime.cgocallbackg + // with the three arguments. Because we are taking over + // the execution of m->curg but *not* resuming what had + // been running, we need to save that information (m->curg->gobuf) + // so that we can restore it when we're done. + // We can restore m->curg->gobuf.sp easily, because calling + // runtime.cgocallbackg leaves SP unchanged upon return. + // To save m->curg->gobuf.pc, we push it onto the stack. + // This has the added benefit that it looks to the traceback + // routine like cgocallbackg is going to return to that + // PC (because we defined cgocallbackg to have + // a frame size of 16, the same amount that we use below), + // so that the traceback will seamlessly trace back into + // the earlier calls. + + // Save current m->g0->sched.sp on stack and then set it to SP. + MOVW m_curg(m), g + MOVW (g_sched+gobuf_sp)(g), R4 // prepare stack as R4 + + // Push gobuf.pc + MOVW (g_sched+gobuf_pc)(g), R5 + SUB $4, R4 + MOVW R5, 0(R4) + + // Push arguments to cgocallbackg. + // Frame size here must match the frame size above + // to trick traceback routines into doing the right thing. + SUB $16, R4 + MOVW R0, 4(R4) + MOVW R1, 8(R4) + MOVW R2, 12(R4) + + // Switch stack and make the call. + MOVW R4, R13 + BL runtime·cgocallbackg(SB) + + // Restore g->gobuf (== m->curg->gobuf) from saved values. + MOVW 16(R13), R5 + MOVW R5, (g_sched+gobuf_pc)(g) + ADD $(16+4), R13 // SP clobbered! It is ok! + MOVW R13, (g_sched+gobuf_sp)(g) + + // Switch back to m->g0's stack and restore m->g0->sched.sp. + // (Unlike m->curg, the g0 goroutine never uses sched.pc, + // so we do not have to restore it.) + MOVW m_g0(m), g + MOVW (g_sched+gobuf_sp)(g), R13 + // POP R6 + MOVW 0(R13), R6 + ADD $4, R13 + MOVW R6, (g_sched+gobuf_sp)(g) + + // If the m on entry was nil, we called needm above to borrow an m + // for the duration of the call. Since the call is over, return it with dropm. + MOVW savedm-16(SP), R6 + CMP $0, R6 + B.NE 3(PC) + MOVW $runtime·dropm(SB), R0 + BL (R0) + + // Done! + RET + +// void setmg(M*, G*); set m and g. for use by needm. +TEXT runtime·setmg(SB), 7, $-4 + MOVW mm+0(FP), m + MOVW gg+4(FP), g + + // Save m and g to thread-local storage. + MOVW _cgo_save_gm(SB), R0 + CMP $0, R0 + BL.NE (R0) -TEXT runtime·memclr(SB),7,$20 - MOVW 0(FP), R0 - MOVW $0, R1 // c = 0 - MOVW R1, -16(SP) - MOVW 4(FP), R1 // n - MOVW R1, -12(SP) - MOVW m, -8(SP) // Save m and g - MOVW g, -4(SP) - BL runtime·memset(SB) - MOVW -8(SP), m // Restore m and g, memset clobbers them - MOVW -4(SP), g RET TEXT runtime·getcallerpc(SB),7,$-4 @@ -269,16 +448,6 @@ TEXT runtime·getcallersp(SB),7,$-4 TEXT runtime·emptyfunc(SB),0,$0 RET -// int64 runtime·cputicks(), so really -// void runtime·cputicks(int64 *ticks) -// stubbed: return int64(0) -TEXT runtime·cputicks(SB),7,$0 - MOVW 0(FP), R1 - MOVW $0, R0 - MOVW R0, 0(R1) - MOVW R0, 4(R1) - RET - TEXT runtime·abort(SB),7,$-4 MOVW $0, R0 MOVW (R0), R1 |