| | |
| | |
| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | |
| | |
| | |
| | |
| | TEXT _rt0_arm64(SB),NOSPLIT,$0 |
| | MOVD 0(RSP), R0 |
| | ADD $8, RSP, R1 |
| | JMP runtime路rt0_go(SB) |
| |
|
| | |
| | |
| | |
| | TEXT main(SB),NOSPLIT,$0 |
| | JMP runtime路rt0_go(SB) |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | TEXT _rt0_arm64_lib(SB),NOSPLIT,$184 |
| | |
| | SAVE_R19_TO_R28(24) |
| | SAVE_F8_TO_F15(104) |
| |
|
| | |
| | MOVD ZR, g |
| |
|
| | MOVD R0, _rt0_arm64_lib_argc<>(SB) |
| | MOVD R1, _rt0_arm64_lib_argv<>(SB) |
| |
|
| | |
| | MOVD $runtime路libpreinit(SB), R4 |
| | BL (R4) |
| |
|
| | |
| | MOVD _cgo_sys_thread_create(SB), R4 |
| | CBZ R4, nocgo |
| | MOVD $_rt0_arm64_lib_go(SB), R0 |
| | MOVD $0, R1 |
| | SUB $16, RSP |
| | BL (R4) |
| | ADD $16, RSP |
| | B restore |
| |
|
| | nocgo: |
| | MOVD $0x800000, R0 |
| | MOVD $_rt0_arm64_lib_go(SB), R1 |
| | MOVD R0, 8(RSP) |
| | MOVD R1, 16(RSP) |
| | MOVD $runtime路newosproc0(SB),R4 |
| | BL (R4) |
| |
|
| | restore: |
| | |
| | RESTORE_R19_TO_R28(24) |
| | RESTORE_F8_TO_F15(104) |
| | RET |
| |
|
| | TEXT _rt0_arm64_lib_go(SB),NOSPLIT,$0 |
| | MOVD _rt0_arm64_lib_argc<>(SB), R0 |
| | MOVD _rt0_arm64_lib_argv<>(SB), R1 |
| | MOVD $runtime路rt0_go(SB),R4 |
| | B (R4) |
| |
|
| | DATA _rt0_arm64_lib_argc<>(SB)/8, $0 |
| | GLOBL _rt0_arm64_lib_argc<>(SB),NOPTR, $8 |
| | DATA _rt0_arm64_lib_argv<>(SB)/8, $0 |
| | GLOBL _rt0_arm64_lib_argv<>(SB),NOPTR, $8 |
| |
|
| | |
| | DATA no_lse_msg<>+0x00(SB)/64, $"This program can only run on ARM64 processors with LSE support.\n" |
| | GLOBL no_lse_msg<>(SB), RODATA, $64 |
| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| |
|
| | TEXT runtime路rt0_go(SB),NOSPLIT|TOPFRAME,$0 |
| | // SP = stack; R0 = argc; R1 = argv |
| | |
| | SUB $32, RSP |
| | MOVW R0, 8(RSP) // argc |
| | MOVD R1, 16(RSP) // argv |
| | |
| | // This is typically the entry point for Go programs. |
| | // Call stack unwinding must not proceed past this frame. |
| | // Set the frame pointer register to 0 so that frame pointer-based unwinders |
| | // (which don't use debug info for performance reasons) |
| | // won't attempt to unwind past this function. |
| | // See go.dev/issue/63630 |
| | MOVD $0, R29 |
| | |
| | #ifdef TLS_darwin |
| | // Initialize TLS. |
| | MOVD ZR, g // clear g, make sure it's not junk. |
| | SUB $32, RSP |
| | MRS_TPIDR_R0 |
| | AND $~7, R0 |
| | MOVD R0, 16(RSP) // arg2: TLS base |
| | MOVD $runtime路tls_g(SB), R2 |
| | MOVD R2, 8(RSP) // arg1: &tlsg |
| | BL 路tlsinit(SB) |
| | ADD $32, RSP |
| | #endif |
| | |
| | // create istack out of the given (operating system) stack. |
| | // _cgo_init may update stackguard. |
| | MOVD $runtime路g0(SB), g |
| | MOVD RSP, R7 |
| | MOVD $(-64*1024)(R7), R0 |
| | MOVD R0, g_stackguard0(g) |
| | MOVD R0, g_stackguard1(g) |
| | MOVD R0, (g_stack+stack_lo)(g) |
| | MOVD R7, (g_stack+stack_hi)(g) |
| | |
| | // if there is a _cgo_init, call it using the gcc ABI. |
| | MOVD _cgo_init(SB), R12 |
| | CBZ R12, nocgo |
| | |
| | #ifdef GOOS_android |
| | MRS_TPIDR_R0 // load TLS base pointer |
| | MOVD R0, R3 // arg 3: TLS base pointer |
| | MOVD $runtime路tls_g(SB), R2 // arg 2: &tls_g |
| | #else |
| | MOVD $0, R2 // arg 2: not used when using platform's TLS |
| | #endif |
| | MOVD $setg_gcc<>(SB), R1 // arg 1: setg |
| | MOVD g, R0 // arg 0: G |
| | SUB $16, RSP // reserve 16 bytes for sp-8 where fp may be saved. |
| | BL (R12) |
| | ADD $16, RSP |
| | |
| | nocgo: |
| | BL runtime路save_g(SB) |
| | // update stackguard after _cgo_init |
| | MOVD (g_stack+stack_lo)(g), R0 |
| | ADD $const_stackGuard, R0 |
| | MOVD R0, g_stackguard0(g) |
| | MOVD R0, g_stackguard1(g) |
| | |
| | // set the per-goroutine and per-mach "registers" |
| | MOVD $runtime路m0(SB), R0 |
| | |
| | // save m->g0 = g0 |
| | MOVD g, m_g0(R0) |
| | // save m0 to g0->m |
| | MOVD R0, g_m(g) |
| | |
| | BL runtime路check(SB) |
| | |
| | #ifdef GOOS_windows |
| | BL runtime路wintls(SB) |
| | #endif |
| | |
| | // Check that CPU we use for execution supports instructions targeted during compile-time. |
| | #ifdef CHECK_GOARM64_LSE |
| | // Read the ID_AA64ISAR0_EL1 register |
| | MRS ID_AA64ISAR0_EL1, R0 |
| | |
| | // Extract the LSE field (bits [23:20]) |
| | LSR $20, R0, R0 |
| | AND $0xf, R0, R0 |
| | |
| | // LSE support is indicated by a non-zero value |
| | CBZ R0, no_lse |
| | #endif |
| | |
| | MOVW 8(RSP), R0 // copy argc |
| | MOVW R0, -8(RSP) |
| | MOVD 16(RSP), R0 // copy argv |
| | MOVD R0, 0(RSP) |
| | BL runtime路args(SB) |
| | BL runtime路osinit(SB) |
| | BL runtime路schedinit(SB) |
| | |
| | // create a new goroutine to start program |
| | MOVD $runtime路mainPC(SB), R0 // entry |
| | SUB $16, RSP |
| | MOVD R0, 8(RSP) // arg |
| | MOVD $0, 0(RSP) // dummy LR |
| | BL runtime路newproc(SB) |
| | ADD $16, RSP |
| | |
| | // start this M |
| | BL runtime路mstart(SB) |
| | UNDEF |
| | |
| | #ifdef CHECK_GOARM64_LSE |
| | no_lse: |
| | MOVD $1, R0 // stderr |
| | MOVD R0, 8(RSP) |
| | MOVD $no_lse_msg<>(SB), R1 // message address |
| | MOVD R1, 16(RSP) |
| | MOVD $64, R2 // message length |
| | MOVD R2, 24(RSP) |
| | CALL runtime路write(SB) |
| | CALL runtime路exit(SB) |
| | CALL runtime路abort(SB) |
| | RET |
| | #endif |
| | |
| | // Prevent dead-code elimination of debugCallV2 and debugPinnerV1, which are |
| | // intended to be called by debuggers. |
| | MOVD $runtime路debugPinnerV1<ABIInternal>(SB), R0 |
| | MOVD $runtime路debugCallV2<ABIInternal>(SB), R0 |
| | |
| | MOVD $0, R0 |
| | MOVD R0, (R0) // boom |
| | UNDEF |
| | |
| | DATA runtime路mainPC+0(SB)/8,$runtime路main<ABIInternal>(SB) |
| | GLOBL runtime路mainPC(SB),RODATA,$8 |
| | |
| | // Windows ARM64 needs an immediate 0xf000 argument. |
| | // See go.dev/issues/53837. |
| | #define BREAK \ |
| | #ifdef GOOS_windows \ |
| | BRK $0xf000 \ |
| | #else \ |
| | BRK \ |
| | #endif \ |
| | |
| | |
| | TEXT runtime路breakpoint(SB),NOSPLIT|NOFRAME,$0-0 |
| | BREAK |
| | RET |
| |
|
| | TEXT runtime路asminit(SB),NOSPLIT|NOFRAME,$0-0 |
| | RET |
| | |
| | TEXT runtime路mstart(SB),NOSPLIT|TOPFRAME,$0 |
| | |
| | |
| | |
| | |
| | |
| | |
| | MOVD $0, R29 |
| | BL runtime路mstart0(SB) |
| | RET |
| |
|
| | |
| | |
| | |
| |
|
| | |
| | |
| | TEXT runtime路gogo(SB), NOSPLIT|NOFRAME, $0-8 |
| | MOVD buf+0(FP), R5 |
| | MOVD gobuf_g(R5), R6 |
| | MOVD 0(R6), R4 // make sure g != nil |
| | B gogo<>(SB) |
| | |
| | TEXT gogo<>(SB), NOSPLIT|NOFRAME, $0 |
| | MOVD R6, g |
| | BL runtime路save_g(SB) |
| |
|
| | MOVD gobuf_sp(R5), R0 |
| | MOVD R0, RSP |
| | MOVD gobuf_bp(R5), R29 |
| | MOVD gobuf_lr(R5), LR |
| | MOVD gobuf_ctxt(R5), R26 |
| | MOVD $0, gobuf_sp(R5) |
| | MOVD $0, gobuf_bp(R5) |
| | MOVD $0, gobuf_lr(R5) |
| | MOVD $0, gobuf_ctxt(R5) |
| | CMP ZR, ZR |
| | MOVD gobuf_pc(R5), R6 |
| | B (R6) |
| |
|
| | |
| | |
| | |
| | |
| | TEXT runtime路mcall<ABIInternal>(SB), NOSPLIT|NOFRAME, $0-8 |
| | #ifdef GOEXPERIMENT_runtimesecret |
| | MOVW g_secret(g), R26 |
| | CBZ R26, nosecret |
| | // Use R26 as a secondary link register |
| | // We purposefully don't erase it in secretEraseRegistersMcall |
| | MOVD LR, R26 |
| | BL runtime路secretEraseRegistersMcall(SB) |
| | MOVD R26, LR |
| | |
| | nosecret: |
| | #endif |
| | MOVD R0, R26 // context |
| | |
| | // Save caller state in g->sched |
| | MOVD RSP, R0 |
| | MOVD R0, (g_sched+gobuf_sp)(g) |
| | MOVD R29, (g_sched+gobuf_bp)(g) |
| | MOVD LR, (g_sched+gobuf_pc)(g) |
| | MOVD $0, (g_sched+gobuf_lr)(g) |
| | |
| | // Switch to m->g0 & its stack, call fn. |
| | MOVD g, R3 |
| | MOVD g_m(g), R8 |
| | MOVD m_g0(R8), g |
| | BL runtime路save_g(SB) |
| | CMP g, R3 |
| | BNE 2(PC) |
| | B runtime路badmcall(SB) |
| | |
| | MOVD (g_sched+gobuf_sp)(g), R0 |
| | MOVD R0, RSP // sp = m->g0->sched.sp |
| | MOVD $0, R29 // clear frame pointer, as caller may execute on another M |
| | MOVD R3, R0 // arg = g |
| | MOVD $0, -16(RSP) // dummy LR |
| | SUB $16, RSP |
| | MOVD 0(R26), R4 // code pointer |
| | BL (R4) |
| | B runtime路badmcall2(SB) |
| | |
| | // systemstack_switch is a dummy routine that systemstack leaves at the bottom |
| | // of the G stack. We need to distinguish the routine that |
| | // lives at the bottom of the G stack from the one that lives |
| | // at the top of the system stack because the one at the top of |
| | // the system stack terminates the stack walk (see topofstack()). |
| | TEXT runtime路systemstack_switch(SB), NOSPLIT, $0-0 |
| | UNDEF |
| | BL (LR) // make sure this function is not leaf |
| | RET |
| | |
| | // func systemstack(fn func()) |
| | TEXT runtime路systemstack(SB), NOSPLIT, $0-8 |
| | #ifdef GOEXPERIMENT_runtimesecret |
| | MOVW g_secret(g), R3 |
| | CBZ R3, nosecret |
| | BL 路secretEraseRegisters(SB) |
| | |
| | nosecret: |
| | #endif |
| | MOVD fn+0(FP), R3 // R3 = fn |
| | MOVD R3, R26 // context |
| | MOVD g_m(g), R4 // R4 = m |
| | |
| | MOVD m_gsignal(R4), R5 // R5 = gsignal |
| | CMP g, R5 |
| | BEQ noswitch |
| | |
| | MOVD m_g0(R4), R5 // R5 = g0 |
| | CMP g, R5 |
| | BEQ noswitch |
| | |
| | MOVD m_curg(R4), R6 |
| | CMP g, R6 |
| | BEQ switch |
| | |
| | // Bad: g is not gsignal, not g0, not curg. What is it? |
| | // Hide call from linker nosplit analysis. |
| | MOVD $runtime路badsystemstack(SB), R3 |
| | BL (R3) |
| | B runtime路abort(SB) |
| | |
| | switch: |
| | // Switch stacks. |
| | // The original frame pointer is stored in R29, |
| | // which is useful for stack unwinding. |
| | // Save our state in g->sched. Pretend to |
| | // be systemstack_switch if the G stack is scanned. |
| | BL gosave_systemstack_switch<>(SB) |
| | |
| | // switch to g0 |
| | MOVD R5, g |
| | BL runtime路save_g(SB) |
| | MOVD (g_sched+gobuf_sp)(g), R3 |
| | MOVD R3, RSP |
| | |
| | // call target function |
| | MOVD 0(R26), R3 // code pointer |
| | BL (R3) |
| | |
| | // switch back to g |
| | MOVD g_m(g), R3 |
| | MOVD m_curg(R3), g |
| | BL runtime路save_g(SB) |
| | MOVD (g_sched+gobuf_sp)(g), R0 |
| | MOVD R0, RSP |
| | MOVD (g_sched+gobuf_bp)(g), R29 |
| | MOVD $0, (g_sched+gobuf_sp)(g) |
| | MOVD $0, (g_sched+gobuf_bp)(g) |
| | RET |
| | |
| | noswitch: |
| | // already on m stack, just call directly |
| | // Using a tail call here cleans up tracebacks since we won't stop |
| | // at an intermediate systemstack. |
| | MOVD 0(R26), R3 // code pointer |
| | MOVD.P 16(RSP), R30 // restore LR |
| | SUB $8, RSP, R29 // restore FP |
| | B (R3) |
| | |
| | // func switchToCrashStack0(fn func()) |
| | TEXT runtime路switchToCrashStack0<ABIInternal>(SB), NOSPLIT, $0-8 |
| | MOVD R0, R26 // context register |
| | MOVD g_m(g), R1 // curm |
| | |
| | // set g to gcrash |
| | MOVD $runtime路gcrash(SB), g // g = &gcrash |
| | BL runtime路save_g(SB) // clobbers R0 |
| | MOVD R1, g_m(g) // g.m = curm |
| | MOVD g, m_g0(R1) // curm.g0 = g |
| | |
| | // switch to crashstack |
| | MOVD (g_stack+stack_hi)(g), R1 |
| | SUB $(4*8), R1 |
| | MOVD R1, RSP |
| | |
| | // call target function |
| | MOVD 0(R26), R0 |
| | CALL (R0) |
| | |
| | // should never return |
| | CALL runtime路abort(SB) |
| | UNDEF |
| | |
| | /* |
| | * support for morestack |
| | */ |
| | |
| | // Called during function prolog when more stack is needed. |
| | // Caller has already loaded: |
| | // R3 prolog's LR (R30) |
| | // |
| | // The traceback routines see morestack on a g0 as being |
| | // the top of a stack (for example, morestack calling newstack |
| | // calling the scheduler calling newm calling gc), so we must |
| | // record an argument size. For that purpose, it has no arguments. |
| | TEXT runtime路morestack(SB),NOSPLIT|NOFRAME,$0-0 |
| | |
| | MOVD g_m(g), R8 |
| | MOVD m_g0(R8), R4 |
| |
|
| | |
| | |
| | MOVD RSP, R0 |
| | MOVD R0, (g_sched+gobuf_sp)(g) |
| | MOVD R29, (g_sched+gobuf_bp)(g) |
| | MOVD LR, (g_sched+gobuf_pc)(g) |
| | MOVD R3, (g_sched+gobuf_lr)(g) |
| | MOVD R26, (g_sched+gobuf_ctxt)(g) |
| |
|
| | CMP g, R4 |
| | BNE 3(PC) |
| | BL runtime路badmorestackg0(SB) |
| | B runtime路abort(SB) |
| |
|
| | |
| | MOVD m_gsignal(R8), R4 |
| | CMP g, R4 |
| | BNE 3(PC) |
| | BL runtime路badmorestackgsignal(SB) |
| | B runtime路abort(SB) |
| |
|
| | |
| | |
| | MOVD R3, (m_morebuf+gobuf_pc)(R8) |
| | MOVD RSP, R0 |
| | MOVD R0, (m_morebuf+gobuf_sp)(R8) |
| | MOVD g, (m_morebuf+gobuf_g)(R8) |
| |
|
| | |
| | |
| | |
| | MOVW g_secret(g), R4 |
| | CBZ R4, nosecret |
| | BL 路secretEraseRegisters(SB) |
| | MOVD g_m(g), R8 |
| | nosecret: |
| | |
| |
|
| | |
| | MOVD m_g0(R8), g |
| | BL runtime路save_g(SB) |
| | MOVD (g_sched+gobuf_sp)(g), R0 |
| | MOVD R0, RSP |
| | MOVD $0, R29 |
| | MOVD.W $0, -16(RSP) |
| | BL runtime路newstack(SB) |
| |
|
| | |
| | |
| | UNDEF |
| |
|
| | TEXT runtime路morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0 |
| | // Force SPWRITE. This function doesn't actually write SP, |
| | // but it is called with a special calling convention where |
| | // the caller doesn't save LR on stack but passes it as a |
| | // register (R3), and the unwinder currently doesn't understand. |
| | // Make it SPWRITE to stop unwinding. (See issue 54332) |
| | MOVD RSP, RSP |
| | |
| | MOVW $0, R26 |
| | B runtime路morestack(SB) |
| | |
| | // spillArgs stores return values from registers to a *internal/abi.RegArgs in R20. |
| | TEXT 路spillArgs(SB),NOSPLIT,$0-0 |
| | STP (R0, R1), (0*8)(R20) |
| | STP (R2, R3), (2*8)(R20) |
| | STP (R4, R5), (4*8)(R20) |
| | STP (R6, R7), (6*8)(R20) |
| | STP (R8, R9), (8*8)(R20) |
| | STP (R10, R11), (10*8)(R20) |
| | STP (R12, R13), (12*8)(R20) |
| | STP (R14, R15), (14*8)(R20) |
| | FSTPD (F0, F1), (16*8)(R20) |
| | FSTPD (F2, F3), (18*8)(R20) |
| | FSTPD (F4, F5), (20*8)(R20) |
| | FSTPD (F6, F7), (22*8)(R20) |
| | FSTPD (F8, F9), (24*8)(R20) |
| | FSTPD (F10, F11), (26*8)(R20) |
| | FSTPD (F12, F13), (28*8)(R20) |
| | FSTPD (F14, F15), (30*8)(R20) |
| | RET |
| | |
| | // unspillArgs loads args into registers from a *internal/abi.RegArgs in R20. |
| | TEXT 路unspillArgs(SB),NOSPLIT,$0-0 |
| | LDP (0*8)(R20), (R0, R1) |
| | LDP (2*8)(R20), (R2, R3) |
| | LDP (4*8)(R20), (R4, R5) |
| | LDP (6*8)(R20), (R6, R7) |
| | LDP (8*8)(R20), (R8, R9) |
| | LDP (10*8)(R20), (R10, R11) |
| | LDP (12*8)(R20), (R12, R13) |
| | LDP (14*8)(R20), (R14, R15) |
| | FLDPD (16*8)(R20), (F0, F1) |
| | FLDPD (18*8)(R20), (F2, F3) |
| | FLDPD (20*8)(R20), (F4, F5) |
| | FLDPD (22*8)(R20), (F6, F7) |
| | FLDPD (24*8)(R20), (F8, F9) |
| | FLDPD (26*8)(R20), (F10, F11) |
| | FLDPD (28*8)(R20), (F12, F13) |
| | FLDPD (30*8)(R20), (F14, F15) |
| | RET |
| | |
| | // reflectcall: call a function with the given argument list |
| | // func call(stackArgsType *_type, f *FuncVal, stackArgs *byte, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs). |
| | // we don't have variable-sized frames, so we use a small number |
| | // of constant-sized-frame functions to encode a few bits of size in the pc. |
| | // Caution: ugly multiline assembly macros in your future! |
| | |
| | #define DISPATCH(NAME,MAXSIZE) \ |
| | MOVD $MAXSIZE, R27; \ |
| | CMP R27, R16; \ |
| | BGT 3(PC); \ |
| | MOVD $NAME(SB), R27; \ |
| | B (R27) |
| | // Note: can't just "B NAME(SB)" - bad inlining results. |
| | |
| | TEXT 路reflectcall(SB), NOSPLIT|NOFRAME, $0-48 |
| | MOVWU frameSize+32(FP), R16 |
| | DISPATCH(runtime路call16, 16) |
| | DISPATCH(runtime路call32, 32) |
| | DISPATCH(runtime路call64, 64) |
| | DISPATCH(runtime路call128, 128) |
| | DISPATCH(runtime路call256, 256) |
| | DISPATCH(runtime路call512, 512) |
| | DISPATCH(runtime路call1024, 1024) |
| | DISPATCH(runtime路call2048, 2048) |
| | DISPATCH(runtime路call4096, 4096) |
| | DISPATCH(runtime路call8192, 8192) |
| | DISPATCH(runtime路call16384, 16384) |
| | DISPATCH(runtime路call32768, 32768) |
| | DISPATCH(runtime路call65536, 65536) |
| | DISPATCH(runtime路call131072, 131072) |
| | DISPATCH(runtime路call262144, 262144) |
| | DISPATCH(runtime路call524288, 524288) |
| | DISPATCH(runtime路call1048576, 1048576) |
| | DISPATCH(runtime路call2097152, 2097152) |
| | DISPATCH(runtime路call4194304, 4194304) |
| | DISPATCH(runtime路call8388608, 8388608) |
| | DISPATCH(runtime路call16777216, 16777216) |
| | DISPATCH(runtime路call33554432, 33554432) |
| | DISPATCH(runtime路call67108864, 67108864) |
| | DISPATCH(runtime路call134217728, 134217728) |
| | DISPATCH(runtime路call268435456, 268435456) |
| | DISPATCH(runtime路call536870912, 536870912) |
| | DISPATCH(runtime路call1073741824, 1073741824) |
| | MOVD $runtime路badreflectcall(SB), R0 |
| | B (R0) |
| |
|
| | |
| | TEXT NAME(SB), WRAPPER, $MAXSIZE-48 |
| | NO_LOCAL_POINTERS |
| | \ |
| | MOVD stackArgs+16(FP), R3 |
| | MOVWU stackArgsSize+24(FP), R4 |
| | ADD $8, RSP, R5 |
| | BIC $0xf, R4, R6 |
| | CBZ R6, 6(PC) |
| | \ |
| | ADD R6, R5, R6 |
| | \ |
| | LDP.P 16(R3), (R7, R8) |
| | STP.P (R7, R8), 16(R5) |
| | CMP R5, R6 |
| | BNE -3(PC) |
| | AND $0xf, R4, R6 |
| | CBZ R6, 6(PC) |
| | \ |
| | ADD R6, R5, R6 |
| | \ |
| | MOVBU.P 1(R3), R7 |
| | MOVBU.P R7, 1(R5) |
| | CMP R5, R6 |
| | BNE -3(PC) |
| | \ |
| | MOVD regArgs+40(FP), R20 |
| | CALL 路unspillArgs(SB) |
| | \ |
| | MOVD f+8(FP), R26 |
| | MOVD (R26), R20 |
| | PCDATA $PCDATA_StackMapIndex, $0 |
| | BL (R20) |
| | \ |
| | MOVD regArgs+40(FP), R20 |
| | CALL 路spillArgs(SB) |
| | MOVD stackArgsType+0(FP), R7 |
| | MOVD stackArgs+16(FP), R3 |
| | MOVWU stackArgsSize+24(FP), R4 |
| | MOVWU stackRetOffset+28(FP), R6 |
| | ADD $8, RSP, R5 |
| | ADD R6, R5 |
| | ADD R6, R3 |
| | SUB R6, R4 |
| | BL callRet<>(SB) |
| | RET |
| |
|
| | |
| | |
| | |
| | |
| | TEXT callRet<>(SB), NOSPLIT, $48-0 |
| | NO_LOCAL_POINTERS |
| | STP (R7, R3), 8(RSP) |
| | STP (R5, R4), 24(RSP) |
| | MOVD R20, 40(RSP) |
| | BL runtime路reflectcallmove(SB) |
| | RET |
| |
|
| | CALLFN(路call16, 16) |
| | CALLFN(路call32, 32) |
| | CALLFN(路call64, 64) |
| | CALLFN(路call128, 128) |
| | CALLFN(路call256, 256) |
| | CALLFN(路call512, 512) |
| | CALLFN(路call1024, 1024) |
| | CALLFN(路call2048, 2048) |
| | CALLFN(路call4096, 4096) |
| | CALLFN(路call8192, 8192) |
| | CALLFN(路call16384, 16384) |
| | CALLFN(路call32768, 32768) |
| | CALLFN(路call65536, 65536) |
| | CALLFN(路call131072, 131072) |
| | CALLFN(路call262144, 262144) |
| | CALLFN(路call524288, 524288) |
| | CALLFN(路call1048576, 1048576) |
| | CALLFN(路call2097152, 2097152) |
| | CALLFN(路call4194304, 4194304) |
| | CALLFN(路call8388608, 8388608) |
| | CALLFN(路call16777216, 16777216) |
| | CALLFN(路call33554432, 33554432) |
| | CALLFN(路call67108864, 67108864) |
| | CALLFN(路call134217728, 134217728) |
| | CALLFN(路call268435456, 268435456) |
| | CALLFN(路call536870912, 536870912) |
| | CALLFN(路call1073741824, 1073741824) |
| |
|
| | |
| | TEXT runtime路memhash32<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24 |
| | MOVB runtime路useAeshash(SB), R10 |
| | CBZ R10, noaes |
| | MOVD $runtime路aeskeysched+0(SB), R3 |
| | |
| | VEOR V0.B16, V0.B16, V0.B16 |
| | VLD1 (R3), [V2.B16] |
| | VLD1 (R0), V0.S[1] |
| | VMOV R1, V0.S[0] |
| | |
| | AESE V2.B16, V0.B16 |
| | AESMC V0.B16, V0.B16 |
| | AESE V2.B16, V0.B16 |
| | AESMC V0.B16, V0.B16 |
| | AESE V2.B16, V0.B16 |
| | |
| | VMOV V0.D[0], R0 |
| | RET |
| | noaes: |
| | B runtime路memhash32Fallback<ABIInternal>(SB) |
| | |
| | // func memhash64(p unsafe.Pointer, h uintptr) uintptr |
| | TEXT runtime路memhash64<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24 |
| | MOVB runtime路useAeshash(SB), R10 |
| | CBZ R10, noaes |
| | MOVD $runtime路aeskeysched+0(SB), R3 |
| |
|
| | VEOR V0.B16, V0.B16, V0.B16 |
| | VLD1 (R3), [V2.B16] |
| | VLD1 (R0), V0.D[1] |
| | VMOV R1, V0.D[0] |
| |
|
| | AESE V2.B16, V0.B16 |
| | AESMC V0.B16, V0.B16 |
| | AESE V2.B16, V0.B16 |
| | AESMC V0.B16, V0.B16 |
| | AESE V2.B16, V0.B16 |
| |
|
| | VMOV V0.D[0], R0 |
| | RET |
| | noaes: |
| | B runtime路memhash64Fallback<ABIInternal>(SB) |
| |
|
| | |
| | TEXT runtime路memhash<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-32 |
| | MOVB runtime路useAeshash(SB), R10 |
| | CBZ R10, noaes |
| | B aeshashbody<>(SB) |
| | noaes: |
| | B runtime路memhashFallback<ABIInternal>(SB) |
| | |
| | // func strhash(p unsafe.Pointer, h uintptr) uintptr |
| | TEXT runtime路strhash<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24 |
| | MOVB runtime路useAeshash(SB), R10 |
| | CBZ R10, noaes |
| | LDP (R0), (R0, R2) |
| | B aeshashbody<>(SB) |
| | noaes: |
| | B runtime路strhashFallback<ABIInternal>(SB) |
| |
|
| | |
| | |
| | |
| | |
| | TEXT aeshashbody<>(SB),NOSPLIT|NOFRAME,$0 |
| | VEOR V30.B16, V30.B16, V30.B16 |
| | VMOV R1, V30.D[0] |
| | VMOV R2, V30.D[1] // load length into seed |
| | |
| | MOVD $runtime路aeskeysched+0(SB), R4 |
| | VLD1.P 16(R4), [V0.B16] |
| | AESE V30.B16, V0.B16 |
| | AESMC V0.B16, V0.B16 |
| | CMP $16, R2 |
| | BLO aes0to15 |
| | BEQ aes16 |
| | CMP $32, R2 |
| | BLS aes17to32 |
| | CMP $64, R2 |
| | BLS aes33to64 |
| | CMP $128, R2 |
| | BLS aes65to128 |
| | B aes129plus |
| | |
| | aes0to15: |
| | CBZ R2, aes0 |
| | VEOR V2.B16, V2.B16, V2.B16 |
| | TBZ $3, R2, less_than_8 |
| | VLD1.P 8(R0), V2.D[0] |
| | |
| | less_than_8: |
| | TBZ $2, R2, less_than_4 |
| | VLD1.P 4(R0), V2.S[2] |
| | |
| | less_than_4: |
| | TBZ $1, R2, less_than_2 |
| | VLD1.P 2(R0), V2.H[6] |
| | |
| | less_than_2: |
| | TBZ $0, R2, done |
| | VLD1 (R0), V2.B[14] |
| | done: |
| | AESE V0.B16, V2.B16 |
| | AESMC V2.B16, V2.B16 |
| | AESE V0.B16, V2.B16 |
| | AESMC V2.B16, V2.B16 |
| | AESE V0.B16, V2.B16 |
| | AESMC V2.B16, V2.B16 |
| | |
| | VMOV V2.D[0], R0 |
| | RET |
| | |
| | aes0: |
| | VMOV V0.D[0], R0 |
| | RET |
| | |
| | aes16: |
| | VLD1 (R0), [V2.B16] |
| | B done |
| | |
| | aes17to32: |
| | // make second seed |
| | VLD1 (R4), [V1.B16] |
| | AESE V30.B16, V1.B16 |
| | AESMC V1.B16, V1.B16 |
| | SUB $16, R2, R10 |
| | VLD1.P (R0)(R10), [V2.B16] |
| | VLD1 (R0), [V3.B16] |
| | |
| | AESE V0.B16, V2.B16 |
| | AESMC V2.B16, V2.B16 |
| | AESE V1.B16, V3.B16 |
| | AESMC V3.B16, V3.B16 |
| | |
| | AESE V0.B16, V2.B16 |
| | AESMC V2.B16, V2.B16 |
| | AESE V1.B16, V3.B16 |
| | AESMC V3.B16, V3.B16 |
| | |
| | AESE V0.B16, V2.B16 |
| | AESE V1.B16, V3.B16 |
| | |
| | VEOR V3.B16, V2.B16, V2.B16 |
| | |
| | VMOV V2.D[0], R0 |
| | RET |
| | |
| | aes33to64: |
| | VLD1 (R4), [V1.B16, V2.B16, V3.B16] |
| | AESE V30.B16, V1.B16 |
| | AESMC V1.B16, V1.B16 |
| | AESE V30.B16, V2.B16 |
| | AESMC V2.B16, V2.B16 |
| | AESE V30.B16, V3.B16 |
| | AESMC V3.B16, V3.B16 |
| | SUB $32, R2, R10 |
| | |
| | VLD1.P (R0)(R10), [V4.B16, V5.B16] |
| | VLD1 (R0), [V6.B16, V7.B16] |
| | |
| | AESE V0.B16, V4.B16 |
| | AESMC V4.B16, V4.B16 |
| | AESE V1.B16, V5.B16 |
| | AESMC V5.B16, V5.B16 |
| | AESE V2.B16, V6.B16 |
| | AESMC V6.B16, V6.B16 |
| | AESE V3.B16, V7.B16 |
| | AESMC V7.B16, V7.B16 |
| | |
| | AESE V0.B16, V4.B16 |
| | AESMC V4.B16, V4.B16 |
| | AESE V1.B16, V5.B16 |
| | AESMC V5.B16, V5.B16 |
| | AESE V2.B16, V6.B16 |
| | AESMC V6.B16, V6.B16 |
| | AESE V3.B16, V7.B16 |
| | AESMC V7.B16, V7.B16 |
| | |
| | AESE V0.B16, V4.B16 |
| | AESE V1.B16, V5.B16 |
| | AESE V2.B16, V6.B16 |
| | AESE V3.B16, V7.B16 |
| | |
| | VEOR V6.B16, V4.B16, V4.B16 |
| | VEOR V7.B16, V5.B16, V5.B16 |
| | VEOR V5.B16, V4.B16, V4.B16 |
| | |
| | VMOV V4.D[0], R0 |
| | RET |
| | |
| | aes65to128: |
| | VLD1.P 64(R4), [V1.B16, V2.B16, V3.B16, V4.B16] |
| | VLD1 (R4), [V5.B16, V6.B16, V7.B16] |
| | AESE V30.B16, V1.B16 |
| | AESMC V1.B16, V1.B16 |
| | AESE V30.B16, V2.B16 |
| | AESMC V2.B16, V2.B16 |
| | AESE V30.B16, V3.B16 |
| | AESMC V3.B16, V3.B16 |
| | AESE V30.B16, V4.B16 |
| | AESMC V4.B16, V4.B16 |
| | AESE V30.B16, V5.B16 |
| | AESMC V5.B16, V5.B16 |
| | AESE V30.B16, V6.B16 |
| | AESMC V6.B16, V6.B16 |
| | AESE V30.B16, V7.B16 |
| | AESMC V7.B16, V7.B16 |
| | |
| | SUB $64, R2, R10 |
| | VLD1.P (R0)(R10), [V8.B16, V9.B16, V10.B16, V11.B16] |
| | VLD1 (R0), [V12.B16, V13.B16, V14.B16, V15.B16] |
| | AESE V0.B16, V8.B16 |
| | AESMC V8.B16, V8.B16 |
| | AESE V1.B16, V9.B16 |
| | AESMC V9.B16, V9.B16 |
| | AESE V2.B16, V10.B16 |
| | AESMC V10.B16, V10.B16 |
| | AESE V3.B16, V11.B16 |
| | AESMC V11.B16, V11.B16 |
| | AESE V4.B16, V12.B16 |
| | AESMC V12.B16, V12.B16 |
| | AESE V5.B16, V13.B16 |
| | AESMC V13.B16, V13.B16 |
| | AESE V6.B16, V14.B16 |
| | AESMC V14.B16, V14.B16 |
| | AESE V7.B16, V15.B16 |
| | AESMC V15.B16, V15.B16 |
| | |
| | AESE V0.B16, V8.B16 |
| | AESMC V8.B16, V8.B16 |
| | AESE V1.B16, V9.B16 |
| | AESMC V9.B16, V9.B16 |
| | AESE V2.B16, V10.B16 |
| | AESMC V10.B16, V10.B16 |
| | AESE V3.B16, V11.B16 |
| | AESMC V11.B16, V11.B16 |
| | AESE V4.B16, V12.B16 |
| | AESMC V12.B16, V12.B16 |
| | AESE V5.B16, V13.B16 |
| | AESMC V13.B16, V13.B16 |
| | AESE V6.B16, V14.B16 |
| | AESMC V14.B16, V14.B16 |
| | AESE V7.B16, V15.B16 |
| | AESMC V15.B16, V15.B16 |
| | |
| | AESE V0.B16, V8.B16 |
| | AESE V1.B16, V9.B16 |
| | AESE V2.B16, V10.B16 |
| | AESE V3.B16, V11.B16 |
| | AESE V4.B16, V12.B16 |
| | AESE V5.B16, V13.B16 |
| | AESE V6.B16, V14.B16 |
| | AESE V7.B16, V15.B16 |
| | |
| | VEOR V12.B16, V8.B16, V8.B16 |
| | VEOR V13.B16, V9.B16, V9.B16 |
| | VEOR V14.B16, V10.B16, V10.B16 |
| | VEOR V15.B16, V11.B16, V11.B16 |
| | VEOR V10.B16, V8.B16, V8.B16 |
| | VEOR V11.B16, V9.B16, V9.B16 |
| | VEOR V9.B16, V8.B16, V8.B16 |
| | |
| | VMOV V8.D[0], R0 |
| | RET |
| | |
| | aes129plus: |
| | PRFM (R0), PLDL1KEEP |
| | VLD1.P 64(R4), [V1.B16, V2.B16, V3.B16, V4.B16] |
| | VLD1 (R4), [V5.B16, V6.B16, V7.B16] |
| | AESE V30.B16, V1.B16 |
| | AESMC V1.B16, V1.B16 |
| | AESE V30.B16, V2.B16 |
| | AESMC V2.B16, V2.B16 |
| | AESE V30.B16, V3.B16 |
| | AESMC V3.B16, V3.B16 |
| | AESE V30.B16, V4.B16 |
| | AESMC V4.B16, V4.B16 |
| | AESE V30.B16, V5.B16 |
| | AESMC V5.B16, V5.B16 |
| | AESE V30.B16, V6.B16 |
| | AESMC V6.B16, V6.B16 |
| | AESE V30.B16, V7.B16 |
| | AESMC V7.B16, V7.B16 |
| | ADD R0, R2, R10 |
| | SUB $128, R10, R10 |
| | VLD1.P 64(R10), [V8.B16, V9.B16, V10.B16, V11.B16] |
| | VLD1 (R10), [V12.B16, V13.B16, V14.B16, V15.B16] |
| | SUB $1, R2, R2 |
| | LSR $7, R2, R2 |
| | |
| | aesloop: |
| | AESE V8.B16, V0.B16 |
| | AESMC V0.B16, V0.B16 |
| | AESE V9.B16, V1.B16 |
| | AESMC V1.B16, V1.B16 |
| | AESE V10.B16, V2.B16 |
| | AESMC V2.B16, V2.B16 |
| | AESE V11.B16, V3.B16 |
| | AESMC V3.B16, V3.B16 |
| | AESE V12.B16, V4.B16 |
| | AESMC V4.B16, V4.B16 |
| | AESE V13.B16, V5.B16 |
| | AESMC V5.B16, V5.B16 |
| | AESE V14.B16, V6.B16 |
| | AESMC V6.B16, V6.B16 |
| | AESE V15.B16, V7.B16 |
| | AESMC V7.B16, V7.B16 |
| | |
| | VLD1.P 64(R0), [V8.B16, V9.B16, V10.B16, V11.B16] |
| | AESE V8.B16, V0.B16 |
| | AESMC V0.B16, V0.B16 |
| | AESE V9.B16, V1.B16 |
| | AESMC V1.B16, V1.B16 |
| | AESE V10.B16, V2.B16 |
| | AESMC V2.B16, V2.B16 |
| | AESE V11.B16, V3.B16 |
| | AESMC V3.B16, V3.B16 |
| | |
| | VLD1.P 64(R0), [V12.B16, V13.B16, V14.B16, V15.B16] |
| | AESE V12.B16, V4.B16 |
| | AESMC V4.B16, V4.B16 |
| | AESE V13.B16, V5.B16 |
| | AESMC V5.B16, V5.B16 |
| | AESE V14.B16, V6.B16 |
| | AESMC V6.B16, V6.B16 |
| | AESE V15.B16, V7.B16 |
| | AESMC V7.B16, V7.B16 |
| | SUB $1, R2, R2 |
| | CBNZ R2, aesloop |
| | |
| | AESE V8.B16, V0.B16 |
| | AESMC V0.B16, V0.B16 |
| | AESE V9.B16, V1.B16 |
| | AESMC V1.B16, V1.B16 |
| | AESE V10.B16, V2.B16 |
| | AESMC V2.B16, V2.B16 |
| | AESE V11.B16, V3.B16 |
| | AESMC V3.B16, V3.B16 |
| | AESE V12.B16, V4.B16 |
| | AESMC V4.B16, V4.B16 |
| | AESE V13.B16, V5.B16 |
| | AESMC V5.B16, V5.B16 |
| | AESE V14.B16, V6.B16 |
| | AESMC V6.B16, V6.B16 |
| | AESE V15.B16, V7.B16 |
| | AESMC V7.B16, V7.B16 |
| | |
| | AESE V8.B16, V0.B16 |
| | AESMC V0.B16, V0.B16 |
| | AESE V9.B16, V1.B16 |
| | AESMC V1.B16, V1.B16 |
| | AESE V10.B16, V2.B16 |
| | AESMC V2.B16, V2.B16 |
| | AESE V11.B16, V3.B16 |
| | AESMC V3.B16, V3.B16 |
| | AESE V12.B16, V4.B16 |
| | AESMC V4.B16, V4.B16 |
| | AESE V13.B16, V5.B16 |
| | AESMC V5.B16, V5.B16 |
| | AESE V14.B16, V6.B16 |
| | AESMC V6.B16, V6.B16 |
| | AESE V15.B16, V7.B16 |
| | AESMC V7.B16, V7.B16 |
| | |
| | AESE V8.B16, V0.B16 |
| | AESE V9.B16, V1.B16 |
| | AESE V10.B16, V2.B16 |
| | AESE V11.B16, V3.B16 |
| | AESE V12.B16, V4.B16 |
| | AESE V13.B16, V5.B16 |
| | AESE V14.B16, V6.B16 |
| | AESE V15.B16, V7.B16 |
| | |
| | VEOR V0.B16, V1.B16, V0.B16 |
| | VEOR V2.B16, V3.B16, V2.B16 |
| | VEOR V4.B16, V5.B16, V4.B16 |
| | VEOR V6.B16, V7.B16, V6.B16 |
| | VEOR V0.B16, V2.B16, V0.B16 |
| | VEOR V4.B16, V6.B16, V4.B16 |
| | VEOR V4.B16, V0.B16, V0.B16 |
| | |
| | VMOV V0.D[0], R0 |
| | RET |
| | |
| | // The Arm architecture provides a user space accessible counter-timer which |
| | // is incremented at a fixed but machine-specific rate. Software can (spin) |
| | // wait until the counter-timer reaches some desired value. |
| | // |
| | // Armv8.7-A introduced the WFET (FEAT_WFxT) instruction, which allows the |
| | // processor to enter a low power state for a set time, or until an event is |
| | // received. |
| | // |
| | // However, WFET is not used here because it is only available on newer hardware, |
| | // and we aim to maintain compatibility with older Armv8-A platforms that do not |
| | // support this feature. |
| | // |
| | // As a fallback, we can instead use the ISB instruction to decrease processor |
| | // activity and thus power consumption between checks of the counter-timer. |
| | // Note that we do not depend on the latency of the ISB instruction which is |
| | // implementation specific. Actual delay comes from comparing against a fresh |
| | // read of the counter-timer value. |
| | // |
| | // Read more in this Arm blog post: |
| | // https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/multi-threaded-applications-arm |
| | |
| | TEXT runtime路procyieldAsm(SB),NOSPLIT,$0-0 |
| | MOVWU cycles+0(FP), R0 |
| | CBZ R0, done |
| | //Prevent speculation of subsequent counter/timer reads and memory accesses. |
| | ISB $15 |
| | // If the delay is very short, just return. |
| | // Hardcode 18ns as the first ISB delay. |
| | CMP $18, R0 |
| | BLS done |
| | // Adjust for overhead of initial ISB. |
| | SUB $18, R0, R0 |
| | // Convert the delay from nanoseconds to counter/timer ticks. |
| | // Read the counter/timer frequency. |
| | // delay_ticks = (delay * CNTFRQ_EL0) / 1e9 |
| | // With the below simplifications and adjustments, |
| | // we are usually within 2% of the correct value: |
| | // delay_ticks = (delay + delay / 16) * CNTFRQ_EL0 >> 30 |
| | MRS CNTFRQ_EL0, R1 |
| | ADD R0>>4, R0, R0 |
| | MUL R1, R0, R0 |
| | LSR $30, R0, R0 |
| | CBZ R0, done |
| | // start = current counter/timer value |
| | MRS CNTVCT_EL0, R2 |
| | delay: |
| | // Delay using ISB for all ticks. |
| | ISB $15 |
| | // Substract and compare to handle counter roll-over. |
| | // counter_read() - start < delay_ticks |
| | MRS CNTVCT_EL0, R1 |
| | SUB R2, R1, R1 |
| | CMP R0, R1 |
| | BCC delay |
| | done: |
| | RET |
| | |
| | // Save state of caller into g->sched, |
| | // but using fake PC from systemstack_switch. |
| | // Must only be called from functions with no locals ($0) |
| | // or else unwinding from systemstack_switch is incorrect. |
| | // Smashes R0. |
| | TEXT gosave_systemstack_switch<>(SB),NOSPLIT|NOFRAME,$0 |
| | MOVD $runtime路systemstack_switch(SB), R0 |
| | ADD $8, R0 |
| | MOVD R0, (g_sched+gobuf_pc)(g) |
| | MOVD RSP, R0 |
| | MOVD R0, (g_sched+gobuf_sp)(g) |
| | MOVD R29, (g_sched+gobuf_bp)(g) |
| | MOVD $0, (g_sched+gobuf_lr)(g) |
| | |
| | MOVD (g_sched+gobuf_ctxt)(g), R0 |
| | CBZ R0, 2(PC) |
| | CALL runtime路abort(SB) |
| | RET |
| |
|
| | |
| | |
| | |
| | TEXT 路asmcgocall_no_g(SB),NOSPLIT,$0-16 |
| | MOVD fn+0(FP), R1 |
| | MOVD arg+8(FP), R0 |
| | SUB $16, RSP |
| | BL (R1) |
| | ADD $16, RSP |
| | RET |
| |
|
| | |
| | |
| | |
| | |
| | TEXT 路asmcgocall(SB),NOSPLIT,$0-20 |
| | CBZ g, nosave |
| |
|
| | |
| | |
| | |
| | |
| | MOVD g_m(g), R8 |
| | MOVD m_gsignal(R8), R3 |
| | CMP R3, g |
| | BEQ nosave |
| | MOVD m_g0(R8), R3 |
| | CMP R3, g |
| | BEQ nosave |
| |
|
| | |
| | |
| | |
| | MOVW g_secret(g), R5 |
| | CBZ R5, nosecret |
| | BL 路secretEraseRegisters(SB) |
| | |
| | MOVD g_m(g), R3 |
| | MOVD m_g0(R3), R3 |
| |
|
| | nosecret: |
| | |
| | MOVD fn+0(FP), R1 |
| | MOVD arg+8(FP), R0 |
| | MOVD RSP, R2 |
| | MOVD g, R4 |
| |
|
| | |
| | MOVD R0, R9 |
| | BL gosave_systemstack_switch<>(SB) |
| | MOVD R3, g |
| | BL runtime路save_g(SB) |
| | MOVD (g_sched+gobuf_sp)(g), R0 |
| | MOVD R0, RSP |
| | MOVD (g_sched+gobuf_bp)(g), R29 |
| | MOVD R9, R0 |
| |
|
| | |
| | |
| | |
| | MOVD RSP, R13 |
| | SUB $16, R13 |
| | MOVD R13, RSP |
| | MOVD R4, 0(RSP) |
| | MOVD (g_stack+stack_hi)(R4), R4 |
| | SUB R2, R4 |
| | MOVD R4, 8(RSP) |
| | BL (R1) |
| | MOVD R0, R9 |
| |
|
| | |
| | MOVD 0(RSP), g |
| | BL runtime路save_g(SB) |
| | MOVD (g_stack+stack_hi)(g), R5 |
| | MOVD 8(RSP), R6 |
| | SUB R6, R5 |
| | MOVD R9, R0 |
| | MOVD R5, RSP |
| |
|
| | MOVW R0, ret+16(FP) |
| | RET |
| |
|
| | nosave: |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | MOVD fn+0(FP), R1 |
| | MOVD arg+8(FP), R0 |
| | MOVD RSP, R2 |
| | MOVD R2, R13 |
| | SUB $16, R13 |
| | MOVD R13, RSP |
| | MOVD $0, R4 |
| | MOVD R4, 0(RSP) |
| | MOVD R2, 8(RSP) |
| | BL (R1) |
| | |
| | MOVD 8(RSP), R2 |
| | MOVD R2, RSP |
| | MOVD R0, ret+16(FP) |
| | RET |
| |
|
| | |
| | |
| | TEXT 路cgocallback(SB),NOSPLIT,$24-24 |
| | NO_LOCAL_POINTERS |
| |
|
| | |
| | |
| | MOVD fn+0(FP), R1 |
| | CBNZ R1, loadg |
| | |
| | MOVD frame+8(FP), g |
| | B dropm |
| |
|
| | loadg: |
| | |
| | BL runtime路load_g(SB) |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | CBZ g, needm |
| |
|
| | MOVD g_m(g), R8 |
| | MOVD R8, savedm-8(SP) |
| | B havem |
| |
|
| | needm: |
| | MOVD g, savedm-8(SP) |
| | MOVD $runtime路needAndBindM(SB), R0 |
| | BL (R0) |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | MOVD g_m(g), R8 |
| | MOVD m_g0(R8), R3 |
| | MOVD RSP, R0 |
| | MOVD R0, (g_sched+gobuf_sp)(R3) |
| | MOVD R29, (g_sched+gobuf_bp)(R3) |
| |
|
| | havem: |
| | |
| | |
| | |
| | |
| | |
| | |
| | MOVD m_g0(R8), R3 |
| | MOVD (g_sched+gobuf_sp)(R3), R4 |
| | MOVD R4, savedsp-16(SP) |
| | MOVD RSP, R0 |
| | MOVD R0, (g_sched+gobuf_sp)(R3) |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | MOVD m_curg(R8), g |
| | BL runtime路save_g(SB) |
| | MOVD (g_sched+gobuf_sp)(g), R4 |
| | MOVD (g_sched+gobuf_pc)(g), R5 |
| | MOVD R5, -48(R4) |
| | MOVD (g_sched+gobuf_bp)(g), R5 |
| | MOVD R5, -56(R4) |
| | |
| | MOVD fn+0(FP), R1 |
| | MOVD frame+8(FP), R2 |
| | MOVD ctxt+16(FP), R3 |
| | MOVD $-48(R4), R0 |
| | MOVD R0, RSP |
| | MOVD R1, 8(RSP) |
| | MOVD R2, 16(RSP) |
| | MOVD R3, 24(RSP) |
| | MOVD $runtime路cgocallbackg(SB), R0 |
| | CALL (R0) |
| |
|
| | |
| | MOVD 0(RSP), R5 |
| | MOVD R5, (g_sched+gobuf_pc)(g) |
| | MOVD RSP, R4 |
| | ADD $48, R4, R4 |
| | MOVD R4, (g_sched+gobuf_sp)(g) |
| |
|
| | |
| | |
| | |
| | MOVD g_m(g), R8 |
| | MOVD m_g0(R8), g |
| | BL runtime路save_g(SB) |
| | MOVD (g_sched+gobuf_sp)(g), R0 |
| | MOVD R0, RSP |
| | MOVD savedsp-16(SP), R4 |
| | MOVD R4, (g_sched+gobuf_sp)(g) |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | MOVD savedm-8(SP), R6 |
| | CBNZ R6, droppedm |
| |
|
| | |
| | MOVD _cgo_pthread_key_created(SB), R6 |
| | |
| | CBZ R6, dropm |
| | MOVD (R6), R6 |
| | CBNZ R6, droppedm |
| |
|
| | dropm: |
| | MOVD $runtime路dropm(SB), R0 |
| | BL (R0) |
| | droppedm: |
| |
|
| | |
| | RET |
| |
|
| | |
| | |
| | TEXT _cgo_topofstack(SB),NOSPLIT,$24 |
| | |
| | |
| | MOVD R27, savedR27-8(SP) |
| | MOVD g, saveG-16(SP) |
| |
|
| | BL runtime路load_g(SB) |
| | MOVD g_m(g), R0 |
| | MOVD m_curg(R0), R0 |
| | MOVD (g_stack+stack_hi)(R0), R0 |
| |
|
| | MOVD saveG-16(SP), g |
| | MOVD savedR28-8(SP), R27 |
| | RET |
| |
|
| | |
| | TEXT runtime路setg(SB), NOSPLIT, $0-8 |
| | MOVD gg+0(FP), g |
| | |
| | BL runtime路save_g(SB) |
| | RET |
| |
|
| | |
| | TEXT setg_gcc<>(SB),NOSPLIT,$8 |
| | MOVD R0, g |
| | MOVD R27, savedR27-8(SP) |
| | BL runtime路save_g(SB) |
| | MOVD savedR27-8(SP), R27 |
| | RET |
| |
|
| | TEXT runtime路emptyfunc(SB),0,$0-0 |
| | RET |
| |
|
| | TEXT runtime路abort(SB),NOSPLIT|NOFRAME,$0-0 |
| | MOVD ZR, R0 |
| | MOVD (R0), R0 |
| | UNDEF |
| | |
| | // The top-most function running on a goroutine |
| | // returns to goexit+PCQuantum. |
| | TEXT runtime路goexit(SB),NOSPLIT|NOFRAME|TOPFRAME,$0-0 |
| | MOVD R0, R0 // NOP |
| | BL runtime路goexit1(SB) // does not return |
| | |
| | // This is called from .init_array and follows the platform, not Go, ABI. |
| | TEXT runtime路addmoduledata(SB),NOSPLIT,$0-0 |
| | SUB $0x10, RSP |
| | MOVD R27, 8(RSP) // The access to global variables below implicitly uses R27, which is callee-save |
| | MOVD runtime路lastmoduledatap(SB), R1 |
| | MOVD R0, moduledata_next(R1) |
| | MOVD R0, runtime路lastmoduledatap(SB) |
| | MOVD 8(RSP), R27 |
| | ADD $0x10, RSP |
| | RET |
| | |
| | TEXT 路checkASM(SB),NOSPLIT,$0-1 |
| | MOVW $1, R3 |
| | MOVB R3, ret+0(FP) |
| | RET |
| | |
| | // gcWriteBarrier informs the GC about heap pointer writes. |
| | // |
| | // gcWriteBarrier does NOT follow the Go ABI. It accepts the |
| | // number of bytes of buffer needed in R25, and returns a pointer |
| | // to the buffer space in R25. |
| | // It clobbers condition codes. |
| | // It does not clobber any general-purpose registers except R27, |
| | // but may clobber others (e.g., floating point registers) |
| | // The act of CALLing gcWriteBarrier will clobber R30 (LR). |
| | TEXT gcWriteBarrier<>(SB),NOSPLIT,$200 |
| | // Save the registers clobbered by the fast path. |
| | STP (R0, R1), 184(RSP) |
| | retry: |
| | MOVD g_m(g), R0 |
| | MOVD m_p(R0), R0 |
| | MOVD (p_wbBuf+wbBuf_next)(R0), R1 |
| | MOVD (p_wbBuf+wbBuf_end)(R0), R27 |
| | // Increment wbBuf.next position. |
| | ADD R25, R1 |
| | // Is the buffer full? |
| | CMP R27, R1 |
| | BHI flush |
| | // Commit to the larger buffer. |
| | MOVD R1, (p_wbBuf+wbBuf_next)(R0) |
| | // Make return value (the original next position) |
| | SUB R25, R1, R25 |
| | // Restore registers. |
| | LDP 184(RSP), (R0, R1) |
| | RET |
| | |
| | flush: |
| | // Save all general purpose registers since these could be |
| | // clobbered by wbBufFlush and were not saved by the caller. |
| | // R0 and R1 already saved |
| | STP (R2, R3), 1*8(RSP) |
| | STP (R4, R5), 3*8(RSP) |
| | STP (R6, R7), 5*8(RSP) |
| | STP (R8, R9), 7*8(RSP) |
| | STP (R10, R11), 9*8(RSP) |
| | STP (R12, R13), 11*8(RSP) |
| | STP (R14, R15), 13*8(RSP) |
| | // R16, R17 may be clobbered by linker trampoline |
| | // R18 is unused. |
| | STP (R19, R20), 15*8(RSP) |
| | STP (R21, R22), 17*8(RSP) |
| | STP (R23, R24), 19*8(RSP) |
| | STP (R25, R26), 21*8(RSP) |
| | // R27 is temp register. |
| | // R28 is g. |
| | // R29 is frame pointer (unused). |
| | // R30 is LR, which was saved by the prologue. |
| | // R31 is SP. |
| | |
| | CALL runtime路wbBufFlush(SB) |
| | LDP 1*8(RSP), (R2, R3) |
| | LDP 3*8(RSP), (R4, R5) |
| | LDP 5*8(RSP), (R6, R7) |
| | LDP 7*8(RSP), (R8, R9) |
| | LDP 9*8(RSP), (R10, R11) |
| | LDP 11*8(RSP), (R12, R13) |
| | LDP 13*8(RSP), (R14, R15) |
| | LDP 15*8(RSP), (R19, R20) |
| | LDP 17*8(RSP), (R21, R22) |
| | LDP 19*8(RSP), (R23, R24) |
| | LDP 21*8(RSP), (R25, R26) |
| | JMP retry |
| | |
| | TEXT runtime路gcWriteBarrier1<ABIInternal>(SB),NOSPLIT,$0 |
| | MOVD $8, R25 |
| | JMP gcWriteBarrier<>(SB) |
| | TEXT runtime路gcWriteBarrier2<ABIInternal>(SB),NOSPLIT,$0 |
| | MOVD $16, R25 |
| | JMP gcWriteBarrier<>(SB) |
| | TEXT runtime路gcWriteBarrier3<ABIInternal>(SB),NOSPLIT,$0 |
| | MOVD $24, R25 |
| | JMP gcWriteBarrier<>(SB) |
| | TEXT runtime路gcWriteBarrier4<ABIInternal>(SB),NOSPLIT,$0 |
| | MOVD $32, R25 |
| | JMP gcWriteBarrier<>(SB) |
| | TEXT runtime路gcWriteBarrier5<ABIInternal>(SB),NOSPLIT,$0 |
| | MOVD $40, R25 |
| | JMP gcWriteBarrier<>(SB) |
| | TEXT runtime路gcWriteBarrier6<ABIInternal>(SB),NOSPLIT,$0 |
| | MOVD $48, R25 |
| | JMP gcWriteBarrier<>(SB) |
| | TEXT runtime路gcWriteBarrier7<ABIInternal>(SB),NOSPLIT,$0 |
| | MOVD $56, R25 |
| | JMP gcWriteBarrier<>(SB) |
| | TEXT runtime路gcWriteBarrier8<ABIInternal>(SB),NOSPLIT,$0 |
| | MOVD $64, R25 |
| | JMP gcWriteBarrier<>(SB) |
| | |
| | DATA debugCallFrameTooLarge<>+0x00(SB)/20, $"call frame too large" |
| | GLOBL debugCallFrameTooLarge<>(SB), RODATA, $20 // Size duplicated below |
| | |
| | // debugCallV2 is the entry point for debugger-injected function |
| | // calls on running goroutines. It informs the runtime that a |
| | // debug call has been injected and creates a call frame for the |
| | // debugger to fill in. |
| | // |
| | // To inject a function call, a debugger should: |
| | // 1. Check that the goroutine is in state _Grunning and that |
| | // there are at least 288 bytes free on the stack. |
| | // 2. Set SP as SP-16. |
| | // 3. Store the current LR in (SP) (using the SP after step 2). |
| | // 4. Store the current PC in the LR register. |
| | // 5. Write the desired argument frame size at SP-16 |
| | // 6. Save all machine registers (including flags and fpsimd registers) |
| | // so they can be restored later by the debugger. |
| | // 7. Set the PC to debugCallV2 and resume execution. |
| | // |
| | // If the goroutine is in state _Grunnable, then it's not generally |
| | // safe to inject a call because it may return out via other runtime |
| | // operations. Instead, the debugger should unwind the stack to find |
| | // the return to non-runtime code, add a temporary breakpoint there, |
| | // and inject the call once that breakpoint is hit. |
| | // |
| | // If the goroutine is in any other state, it's not safe to inject a call. |
| | // |
| | // This function communicates back to the debugger by setting R20 and |
| | // invoking BRK to raise a breakpoint signal. Note that the signal PC of |
| | // the signal triggered by the BRK instruction is the PC where the signal |
| | // is trapped, not the next PC, so to resume execution, the debugger needs |
| | // to set the signal PC to PC+4. See the comments in the implementation for |
| | // the protocol the debugger is expected to follow. InjectDebugCall in the |
| | // runtime tests demonstrates this protocol. |
| | // |
| | // The debugger must ensure that any pointers passed to the function |
| | // obey escape analysis requirements. Specifically, it must not pass |
| | // a stack pointer to an escaping argument. debugCallV2 cannot check |
| | // this invariant. |
| | // |
| | // This is ABIInternal because Go code injects its PC directly into new |
| | // goroutine stacks. |
| | TEXT runtime路debugCallV2<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-0 |
| | STP (R29, R30), -280(RSP) |
| | SUB $272, RSP, RSP |
| | SUB $8, RSP, R29 |
| | |
| | |
| | |
| | |
| | |
| | STP (R27, g), (30*8)(RSP) |
| | STP (R25, R26), (28*8)(RSP) |
| | STP (R23, R24), (26*8)(RSP) |
| | STP (R21, R22), (24*8)(RSP) |
| | STP (R19, R20), (22*8)(RSP) |
| | STP (R16, R17), (20*8)(RSP) |
| | STP (R14, R15), (18*8)(RSP) |
| | STP (R12, R13), (16*8)(RSP) |
| | STP (R10, R11), (14*8)(RSP) |
| | STP (R8, R9), (12*8)(RSP) |
| | STP (R6, R7), (10*8)(RSP) |
| | STP (R4, R5), (8*8)(RSP) |
| | STP (R2, R3), (6*8)(RSP) |
| | STP (R0, R1), (4*8)(RSP) |
| |
|
| | |
| | MOVD R30, 8(RSP) |
| | CALL runtime路debugCallCheck(SB) |
| | MOVD 16(RSP), R0 |
| | CBZ R0, good |
| |
|
| | |
| | |
| | MOVD R0, 8(RSP) |
| | MOVD 24(RSP), R0 |
| | MOVD R0, 16(RSP) |
| |
|
| | |
| | |
| | MOVD $8, R20 |
| | BREAK |
| | JMP restore |
| |
|
| | good: |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | CMP $MAXSIZE, R0 |
| | BGT 5(PC) |
| | MOVD $NAME(SB), R0 |
| | MOVD R0, 8(RSP) |
| | CALL runtime路debugCallWrap(SB) |
| | JMP restore |
| |
|
| | MOVD 256(RSP), R0 |
| | DEBUG_CALL_DISPATCH(debugCall32<>, 32) |
| | DEBUG_CALL_DISPATCH(debugCall64<>, 64) |
| | DEBUG_CALL_DISPATCH(debugCall128<>, 128) |
| | DEBUG_CALL_DISPATCH(debugCall256<>, 256) |
| | DEBUG_CALL_DISPATCH(debugCall512<>, 512) |
| | DEBUG_CALL_DISPATCH(debugCall1024<>, 1024) |
| | DEBUG_CALL_DISPATCH(debugCall2048<>, 2048) |
| | DEBUG_CALL_DISPATCH(debugCall4096<>, 4096) |
| | DEBUG_CALL_DISPATCH(debugCall8192<>, 8192) |
| | DEBUG_CALL_DISPATCH(debugCall16384<>, 16384) |
| | DEBUG_CALL_DISPATCH(debugCall32768<>, 32768) |
| | DEBUG_CALL_DISPATCH(debugCall65536<>, 65536) |
| | |
| | MOVD $debugCallFrameTooLarge<>(SB), R0 |
| | MOVD R0, 8(RSP) |
| | MOVD $20, R0 |
| | MOVD R0, 16(RSP) |
| | MOVD $8, R20 |
| | BREAK |
| | JMP restore |
| |
|
| | restore: |
| | |
| | |
| | |
| | |
| | MOVD $16, R20 |
| | BREAK |
| | |
| |
|
| | |
| | |
| | LDP (30*8)(RSP), (R27, g) |
| | LDP (28*8)(RSP), (R25, R26) |
| | LDP (26*8)(RSP), (R23, R24) |
| | LDP (24*8)(RSP), (R21, R22) |
| | LDP (22*8)(RSP), (R19, R20) |
| | LDP (20*8)(RSP), (R16, R17) |
| | LDP (18*8)(RSP), (R14, R15) |
| | LDP (16*8)(RSP), (R12, R13) |
| | LDP (14*8)(RSP), (R10, R11) |
| | LDP (12*8)(RSP), (R8, R9) |
| | LDP (10*8)(RSP), (R6, R7) |
| | LDP (8*8)(RSP), (R4, R5) |
| | LDP (6*8)(RSP), (R2, R3) |
| | LDP (4*8)(RSP), (R0, R1) |
| |
|
| | LDP -8(RSP), (R29, R27) |
| | ADD $288, RSP, RSP |
| | MOVD -16(RSP), R30 |
| | JMP (R27) |
| |
|
| | |
| | |
| | |
| | TEXT NAME(SB),WRAPPER,$MAXSIZE-0 |
| | NO_LOCAL_POINTERS |
| | MOVD $0, R20 |
| | BREAK |
| | MOVD $1, R20 |
| | BREAK |
| | RET |
| | DEBUG_CALL_FN(debugCall32<>, 32) |
| | DEBUG_CALL_FN(debugCall64<>, 64) |
| | DEBUG_CALL_FN(debugCall128<>, 128) |
| | DEBUG_CALL_FN(debugCall256<>, 256) |
| | DEBUG_CALL_FN(debugCall512<>, 512) |
| | DEBUG_CALL_FN(debugCall1024<>, 1024) |
| | DEBUG_CALL_FN(debugCall2048<>, 2048) |
| | DEBUG_CALL_FN(debugCall4096<>, 4096) |
| | DEBUG_CALL_FN(debugCall8192<>, 8192) |
| | DEBUG_CALL_FN(debugCall16384<>, 16384) |
| | DEBUG_CALL_FN(debugCall32768<>, 32768) |
| | DEBUG_CALL_FN(debugCall65536<>, 65536) |
| |
|
| | |
| | TEXT runtime路debugCallPanicked(SB),NOSPLIT,$16-16 |
| | |
| | MOVD val_type+0(FP), R0 |
| | MOVD R0, 8(RSP) |
| | MOVD val_data+8(FP), R0 |
| | MOVD R0, 16(RSP) |
| | MOVD $2, R20 |
| | BREAK |
| | RET |
| |
|
| | TEXT runtime路panicBounds<ABIInternal>(SB),NOSPLIT,$144-0 |
| | NO_LOCAL_POINTERS |
| | |
| | |
| | STP (R0, R1), 24(RSP) |
| | STP (R2, R3), 40(RSP) |
| | STP (R4, R5), 56(RSP) |
| | STP (R6, R7), 72(RSP) |
| | STP (R8, R9), 88(RSP) |
| | STP (R10, R11), 104(RSP) |
| | STP (R12, R13), 120(RSP) |
| | STP (R14, R15), 136(RSP) |
| | MOVD LR, R0 |
| | ADD $24, RSP, R1 |
| | CALL runtime路panicBounds64<ABIInternal>(SB) |
| | RET |
| |
|
| | TEXT 路getfp<ABIInternal>(SB),NOSPLIT|NOFRAME,$0 |
| | MOVD R29, R0 |
| | RET |
| | |