+++ /dev/null
-// Copyright 2025 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "go_asm.h"
-#include "go_tls.h"
-#include "textflag.h"
-#include "time_windows.h"
-
-TEXT ·StdCall<ABIInternal>(SB),NOSPLIT,$0
- B ·asmstdcall(SB)
-
-TEXT ·asmstdcall(SB),NOSPLIT|NOFRAME,$0
- MOVM.DB.W [R4, R5, R14], (R13) // push {r4, r5, lr}
- MOVW R0, R4 // put fn * in r4
- MOVW R13, R5 // save stack pointer in r5
-
- // SetLastError(0)
- MOVW $0, R0
- MRC 15, 0, R1, C13, C0, 2
- MOVW R0, 0x34(R1)
-
- MOVW 8(R4), R12 // fn->Args
-
- // Do we have more than 4 arguments?
- MOVW 4(R4), R0 // fn->n
- SUB.S $4, R0, R2
- BLE loadregs
-
- // Reserve stack space for remaining args
- SUB R2<<2, R13
- BIC $0x7, R13 // alignment for ABI
-
- // R0: count of arguments
- // R1:
- // R2: loop counter, from 0 to (n-4)
- // R3: scratch
- // R4: pointer to StdCallInfo struct
- // R12: fn->args
- MOVW $0, R2
-stackargs:
- ADD $4, R2, R3 // r3 = args[4 + i]
- MOVW R3<<2(R12), R3
- MOVW R3, R2<<2(R13) // stack[i] = r3
-
- ADD $1, R2 // i++
- SUB $4, R0, R3 // while (i < (n - 4))
- CMP R3, R2
- BLT stackargs
-
-loadregs:
- CMP $3, R0
- MOVW.GT 12(R12), R3
-
- CMP $2, R0
- MOVW.GT 8(R12), R2
-
- CMP $1, R0
- MOVW.GT 4(R12), R1
-
- CMP $0, R0
- MOVW.GT 0(R12), R0
-
- BIC $0x7, R13 // alignment for ABI
- MOVW 0(R4), R12 // branch to fn->fn
- BL (R12)
-
- MOVW R5, R13 // free stack space
- MOVW R0, 12(R4) // save return value to fn->r1
- MOVW R1, 16(R4)
-
- // GetLastError
- MRC 15, 0, R1, C13, C0, 2
- MOVW 0x34(R1), R0
- MOVW R0, 20(R4) // store in fn->err
-
- MOVM.IA.W (R13), [R4, R5, R15]
+++ /dev/null
-// Copyright 2018 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package runtime
-
-import (
- "internal/goarch"
- "unsafe"
-)
-
-// NOTE(rsc): _CONTEXT_CONTROL is actually 0x200001 and should include PC, SP, and LR.
-// However, empirically, LR doesn't come along on Windows 10
-// unless you also set _CONTEXT_INTEGER (0x200002).
-// Without LR, we skip over the next-to-bottom function in profiles
-// when the bottom function is frameless.
-// So we set both here, to make a working _CONTEXT_CONTROL.
-const _CONTEXT_CONTROL = 0x200003
-
-type neon128 struct {
- low uint64
- high int64
-}
-
-type context struct {
- contextflags uint32
- r0 uint32
- r1 uint32
- r2 uint32
- r3 uint32
- r4 uint32
- r5 uint32
- r6 uint32
- r7 uint32
- r8 uint32
- r9 uint32
- r10 uint32
- r11 uint32
- r12 uint32
-
- spr uint32
- lrr uint32
- pc uint32
- cpsr uint32
-
- fpscr uint32
- padding uint32
-
- floatNeon [16]neon128
-
- bvr [8]uint32
- bcr [8]uint32
- wvr [1]uint32
- wcr [1]uint32
- padding2 [2]uint32
-}
-
-func (c *context) ip() uintptr { return uintptr(c.pc) }
-func (c *context) sp() uintptr { return uintptr(c.spr) }
-func (c *context) lr() uintptr { return uintptr(c.lrr) }
-
-func (c *context) set_ip(x uintptr) { c.pc = uint32(x) }
-func (c *context) set_sp(x uintptr) { c.spr = uint32(x) }
-func (c *context) set_lr(x uintptr) { c.lrr = uint32(x) }
-
-// arm does not have frame pointer register.
-func (c *context) set_fp(x uintptr) {}
-
-func (c *context) pushCall(targetPC, resumePC uintptr) {
- // Push LR. The injected call is responsible
- // for restoring LR. gentraceback is aware of
- // this extra slot. See sigctxt.pushCall in
- // signal_arm.go.
- sp := c.sp() - goarch.StackAlign
- c.set_sp(sp)
- *(*uint32)(unsafe.Pointer(sp)) = uint32(c.lr())
- c.set_lr(resumePC)
- c.set_ip(targetPC)
-}
-
-func prepareContextForSigResume(c *context) {
- c.r0 = c.spr
- c.r1 = c.pc
-}
-
-func dumpregs(r *context) {
- print("r0 ", hex(r.r0), "\n")
- print("r1 ", hex(r.r1), "\n")
- print("r2 ", hex(r.r2), "\n")
- print("r3 ", hex(r.r3), "\n")
- print("r4 ", hex(r.r4), "\n")
- print("r5 ", hex(r.r5), "\n")
- print("r6 ", hex(r.r6), "\n")
- print("r7 ", hex(r.r7), "\n")
- print("r8 ", hex(r.r8), "\n")
- print("r9 ", hex(r.r9), "\n")
- print("r10 ", hex(r.r10), "\n")
- print("r11 ", hex(r.r11), "\n")
- print("r12 ", hex(r.r12), "\n")
- print("sp ", hex(r.spr), "\n")
- print("lr ", hex(r.lrr), "\n")
- print("pc ", hex(r.pc), "\n")
- print("cpsr ", hex(r.cpsr), "\n")
-}
-
-func stackcheck() {
- // TODO: not implemented on ARM
-}
-
-type _DISPATCHER_CONTEXT struct {
- controlPc uint32
- imageBase uint32
- functionEntry uintptr
- establisherFrame uint32
- targetIp uint32
- context *context
- languageHandler uintptr
- handlerData uintptr
-}
-
-func (c *_DISPATCHER_CONTEXT) ctx() *context {
- return c.context
-}
+++ /dev/null
-// Copyright 2018 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include "go_asm.h"
-#include "go_tls.h"
-#include "textflag.h"
-#include "time_windows.h"
-
-// Note: For system ABI, R0-R3 are args, R4-R11 are callee-save.
-
-TEXT runtime·getlasterror(SB),NOSPLIT,$0
- MRC 15, 0, R0, C13, C0, 2
- MOVW 0x34(R0), R0
- MOVW R0, ret+0(FP)
- RET
-
-// Called by Windows as a Vectored Exception Handler (VEH).
-// R0 is pointer to struct containing
-// exception record and context pointers.
-// R1 is the kind of sigtramp function.
-// Return value of sigtrampgo is stored in R0.
-TEXT sigtramp<>(SB),NOSPLIT|NOFRAME,$0
- MOVM.DB.W [R4-R11, R14], (R13) // push {r4-r11, lr} (SP-=40)
- SUB $(16), R13 // reserve space for parameters/retval to go call
-
- MOVW R0, R6 // Save param0
- MOVW R1, R7 // Save param1
- BL runtime·load_g(SB) // Clobbers R0
-
- MOVW $0, R4
- MOVW R4, 0(R13) // No saved link register.
- MOVW R6, 4(R13) // Move arg0 into position
- MOVW R7, 8(R13) // Move arg1 into position
- BL runtime·sigtrampgo(SB)
- MOVW 12(R13), R0 // Fetch return value from stack
-
- ADD $(16), R13 // free locals
- MOVM.IA.W (R13), [R4-R11, R14] // pop {r4-r11, lr}
-
- B (R14) // return
-
-// Trampoline to resume execution from exception handler.
-// This is part of the control flow guard workaround.
-// It switches stacks and jumps to the continuation address.
-// R0 and R1 are set above at the end of sigtrampgo
-// in the context that starts executing at sigresume.
-TEXT runtime·sigresume(SB),NOSPLIT|NOFRAME,$0
- // Important: do not smash LR,
- // which is set to a live value when handling
- // a signal by pushing a call to sigpanic onto the stack.
- MOVW R0, R13
- B (R1)
-
-TEXT runtime·exceptiontramp(SB),NOSPLIT|NOFRAME,$0
- MOVW $const_callbackVEH, R1
- B sigtramp<>(SB)
-
-TEXT runtime·firstcontinuetramp(SB),NOSPLIT|NOFRAME,$0
- MOVW $const_callbackFirstVCH, R1
- B sigtramp<>(SB)
-
-TEXT runtime·lastcontinuetramp(SB),NOSPLIT|NOFRAME,$0
- MOVW $const_callbackLastVCH, R1
- B sigtramp<>(SB)
-
-TEXT runtime·callbackasm1(SB),NOSPLIT|NOFRAME,$0
- // On entry, the trampoline in zcallback_windows_arm.s left
- // the callback index in R12 (which is volatile in the C ABI).
-
- // Push callback register arguments r0-r3. We do this first so
- // they're contiguous with stack arguments.
- MOVM.DB.W [R0-R3], (R13)
- // Push C callee-save registers r4-r11 and lr.
- MOVM.DB.W [R4-R11, R14], (R13)
- SUB $(16 + callbackArgs__size), R13 // space for locals
-
- // Create a struct callbackArgs on our stack.
- MOVW R12, (16+callbackArgs_index)(R13) // callback index
- MOVW $(16+callbackArgs__size+4*9)(R13), R0
- MOVW R0, (16+callbackArgs_args)(R13) // address of args vector
- MOVW $0, R0
- MOVW R0, (16+callbackArgs_result)(R13) // result
-
- // Prepare for entry to Go.
- BL runtime·load_g(SB)
-
- // Call cgocallback, which will call callbackWrap(frame).
- MOVW $0, R0
- MOVW R0, 12(R13) // context
- MOVW $16(R13), R1 // R1 = &callbackArgs{...}
- MOVW R1, 8(R13) // frame (address of callbackArgs)
- MOVW $·callbackWrap(SB), R1
- MOVW R1, 4(R13) // PC of function to call
- BL runtime·cgocallback(SB)
-
- // Get callback result.
- MOVW (16+callbackArgs_result)(R13), R0
-
- ADD $(16 + callbackArgs__size), R13 // free locals
- MOVM.IA.W (R13), [R4-R11, R12] // pop {r4-r11, lr=>r12}
- ADD $(4*4), R13 // skip r0-r3
- B (R12) // return
-
-// uint32 tstart_stdcall(M *newm);
-TEXT runtime·tstart_stdcall(SB),NOSPLIT|NOFRAME,$0
- MOVM.DB.W [R4-R11, R14], (R13) // push {r4-r11, lr}
-
- MOVW m_g0(R0), g
- MOVW R0, g_m(g)
- BL runtime·save_g(SB)
-
- // Layout new m scheduler stack on os stack.
- MOVW R13, R0
- MOVW R0, g_stack+stack_hi(g)
- SUB $(64*1024), R0
- MOVW R0, (g_stack+stack_lo)(g)
- MOVW R0, g_stackguard0(g)
- MOVW R0, g_stackguard1(g)
-
- BL runtime·emptyfunc(SB) // fault if stack check is wrong
- BL runtime·mstart(SB)
-
- // Exit the thread.
- MOVW $0, R0
- MOVM.IA.W (R13), [R4-R11, R15] // pop {r4-r11, pc}
-
-TEXT ·publicationBarrier(SB),NOSPLIT|NOFRAME,$0-0
- B runtime·armPublicationBarrier(SB)
-
-// never called (this is a GOARM=7 platform)
-TEXT runtime·read_tls_fallback(SB),NOSPLIT,$0
- MOVW $0xabcd, R0
- MOVW R0, (R0)
- RET
-
-TEXT runtime·nanotime1(SB),NOSPLIT,$0-8
- MOVW $_INTERRUPT_TIME, R3
-loop:
- MOVW time_hi1(R3), R1
- DMB MB_ISH
- MOVW time_lo(R3), R0
- DMB MB_ISH
- MOVW time_hi2(R3), R2
- CMP R1, R2
- BNE loop
-
- // wintime = R1:R0, multiply by 100
- MOVW $100, R2
- MULLU R0, R2, (R4, R3) // R4:R3 = R1:R0 * R2
- MULA R1, R2, R4, R4
-
- // wintime*100 = R4:R3
- MOVW R3, ret_lo+0(FP)
- MOVW R4, ret_hi+4(FP)
- RET
-
-// save_g saves the g register (R10) into thread local memory
-// so that we can call externally compiled
-// ARM code that will overwrite those registers.
-// NOTE: runtime.gogo assumes that R1 is preserved by this function.
-// runtime.mcall assumes this function only clobbers R0 and R11.
-// Returns with g in R0.
-// Save the value in the _TEB->TlsSlots array.
-// Effectively implements TlsSetValue().
-// tls_g stores the TLS slot allocated TlsAlloc().
-TEXT runtime·save_g(SB),NOSPLIT,$0
- MRC 15, 0, R0, C13, C0, 2
- ADD $0xe10, R0
- MOVW $runtime·tls_g(SB), R11
- MOVW (R11), R11
- MOVW g, R11<<2(R0)
- MOVW g, R0 // preserve R0 across call to setg<>
- RET
-
-// load_g loads the g register from thread-local memory,
-// for use after calling externally compiled
-// ARM code that overwrote those registers.
-// Get the value from the _TEB->TlsSlots array.
-// Effectively implements TlsGetValue().
-TEXT runtime·load_g(SB),NOSPLIT,$0
- MRC 15, 0, R0, C13, C0, 2
- ADD $0xe10, R0
- MOVW $runtime·tls_g(SB), g
- MOVW (g), g
- MOVW g<<2(R0), g
- RET
-
-// This is called from rt0_go, which runs on the system stack
-// using the initial stack allocated by the OS.
-// It calls back into standard C using the BL below.
-// To do that, the stack pointer must be 8-byte-aligned.
-TEXT runtime·_initcgo(SB),NOSPLIT|NOFRAME,$0
- MOVM.DB.W [R4, R14], (R13) // push {r4, lr}
-
- // Ensure stack is 8-byte aligned before calling C code
- MOVW R13, R4
- BIC $0x7, R13
-
- // Allocate a TLS slot to hold g across calls to external code
- MOVW $runtime·_TlsAlloc(SB), R0
- MOVW (R0), R0
- BL (R0)
-
- // Assert that slot is less than 64 so we can use _TEB->TlsSlots
- CMP $64, R0
- MOVW $runtime·abort(SB), R1
- BL.GE (R1)
-
- // Save Slot into tls_g
- MOVW $runtime·tls_g(SB), R1
- MOVW R0, (R1)
-
- MOVW R4, R13
- MOVM.IA.W (R13), [R4, R15] // pop {r4, pc}
-
-// Holds the TLS Slot, which was allocated by TlsAlloc()
-GLOBL runtime·tls_g+0(SB), NOPTR, $4
// passed as two words (little endian); and
// structs are pushed on the stack. In
// fastcall, arguments larger than the word
- // size are passed by reference. On arm,
- // 8-byte aligned arguments round up to the
- // next even register and can be split across
- // registers and the stack.
+ // size are passed by reference.
panic("compileCallback: argument size is larger than uintptr")
}
if k := t.Kind(); GOARCH != "386" && (k == abi.Float32 || k == abi.Float64) {
// In fastcall, floating-point arguments in
// the first four positions are passed in
// floating-point registers, which we don't
- // currently spill. arm passes floating-point
- // arguments in VFP registers, which we also
- // don't support.
+ // currently spill.
// So basically we only support 386.
panic("compileCallback: float arguments not supported")
}
// argument word and all supported Windows
// architectures are little endian, so srcStackOffset
// is already pointing to the right place for smaller
- // arguments. The same is true on arm.
+ // arguments.
oldParts := p.parts
if p.tryRegAssignArg(t, 0) {
p.dstStackSize += t.Size_
}
- // cdecl, stdcall, fastcall, and arm pad arguments to word size.
- // TODO(rsc): On arm and arm64 do we need to skip the caller's saved LR?
+ // cdecl, stdcall, and fastcall pad arguments to word size.
+ // TODO(rsc): On arm64 do we need to skip the caller's saved LR?
p.srcStackSize += goarch.PtrSize
}
//
// On 386, if cdecl is true, the returned C function will use the
// cdecl calling convention; otherwise, it will use stdcall. On amd64,
-// it always uses fastcall. On arm, it always uses the ARM convention.
+// it always uses fastcall.
//
//go:linkname compileCallback syscall.compileCallback
func compileCallback(fn eface, cdecl bool) (code uintptr) {
// For fastcall, the trampoline spills register arguments to
// the reserved spill slots below the stack arguments,
// resulting in a layout equivalent to stdcall.
- //
- // For arm, the trampoline stores the register arguments just
- // below the stack arguments, so again we can treat it as one
- // big stack arguments frame.
args unsafe.Pointer
// Below are out-args from callbackWrap
result uintptr