}
if autoffset != deltasp {
- ctxt.Diag("unbalanced PUSH/POP")
+ ctxt.Diag("%s: unbalanced PUSH/POP", cursym)
}
if autoffset != 0 {
--- /dev/null
+// Copyright 2021 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.
+
+// Macros for transitioning from the host ABI to Go ABI0.
+//
+// TODO(austin): Define these for ELF platforms as well.
+
+#ifdef GOOS_windows
+
+// REGS_HOST_TO_ABI0_STACK is the stack bytes used by
+// PUSH_REGS_HOST_TO_ABI0.
+#define REGS_HOST_TO_ABI0_STACK (28*8 + 8)
+
+// PUSH_REGS_HOST_TO_ABI0 prepares for transitioning from
+// the host ABI to Go ABI0 code. It saves all registers that are
+// callee-save in the host ABI and caller-save in Go ABI0 and prepares
+// for entry to Go.
+//
+// Save DI SI BP BX R12 R13 R14 R15 X6-X15 registers and the DF flag.
+// Clear the DF flag for the Go ABI.
+// MXCSR matches the Go ABI, so we don't have to set that,
+// and Go doesn't modify it, so we don't have to save it.
+#define PUSH_REGS_HOST_TO_ABI0() \
+ PUSHFQ \
+ CLD \
+ ADJSP $(REGS_HOST_TO_ABI0_STACK - 8) \
+ MOVQ DI, (0*0)(SP) \
+ MOVQ SI, (1*8)(SP) \
+ MOVQ BP, (2*8)(SP) \
+ MOVQ BX, (3*8)(SP) \
+ MOVQ R12, (4*8)(SP) \
+ MOVQ R13, (5*8)(SP) \
+ MOVQ R14, (6*8)(SP) \
+ MOVQ R15, (7*8)(SP) \
+ MOVUPS X6, (8*8)(SP) \
+ MOVUPS X7, (10*8)(SP) \
+ MOVUPS X8, (12*8)(SP) \
+ MOVUPS X9, (14*8)(SP) \
+ MOVUPS X10, (16*8)(SP) \
+ MOVUPS X11, (18*8)(SP) \
+ MOVUPS X12, (20*8)(SP) \
+ MOVUPS X13, (22*8)(SP) \
+ MOVUPS X14, (24*8)(SP) \
+ MOVUPS X15, (26*8)(SP)
+
+#define POP_REGS_HOST_TO_ABI0() \
+ MOVQ (0*0)(SP), DI \
+ MOVQ (1*8)(SP), SI \
+ MOVQ (2*8)(SP), BP \
+ MOVQ (3*8)(SP), BX \
+ MOVQ (4*8)(SP), R12 \
+ MOVQ (5*8)(SP), R13 \
+ MOVQ (6*8)(SP), R14 \
+ MOVQ (7*8)(SP), R15 \
+ MOVUPS (8*8)(SP), X6 \
+ MOVUPS (10*8)(SP), X7 \
+ MOVUPS (12*8)(SP), X8 \
+ MOVUPS (14*8)(SP), X9 \
+ MOVUPS (16*8)(SP), X10 \
+ MOVUPS (18*8)(SP), X11 \
+ MOVUPS (20*8)(SP), X12 \
+ MOVUPS (22*8)(SP), X13 \
+ MOVUPS (24*8)(SP), X14 \
+ MOVUPS (26*8)(SP), X15 \
+ ADJSP $-(REGS_HOST_TO_ABI0_STACK - 8) \
+ POPFQ
+
+#endif
// license that can be found in the LICENSE file.
#include "textflag.h"
+#include "abi_amd64.h"
// Called by C code generated by cmd/cgo.
// func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr)
// This signature is known to SWIG, so we can't change it.
#ifndef GOOS_windows
TEXT crosscall2(SB),NOSPLIT,$0x50-0 /* keeps stack pointer 32-byte aligned */
-#else
-TEXT crosscall2(SB),NOSPLIT,$0x110-0 /* also need to save xmm6 - xmm15 */
-#endif
MOVQ BX, 0x18(SP)
MOVQ R12, 0x28(SP)
MOVQ R13, 0x30(SP)
MOVQ R14, 0x38(SP)
MOVQ R15, 0x40(SP)
-#ifdef GOOS_windows
- // Win64 save RBX, RBP, RDI, RSI, RSP, R12, R13, R14, R15 and XMM6 -- XMM15.
- MOVQ DI, 0x48(SP)
- MOVQ SI, 0x50(SP)
- MOVUPS X6, 0x60(SP)
- MOVUPS X7, 0x70(SP)
- MOVUPS X8, 0x80(SP)
- MOVUPS X9, 0x90(SP)
- MOVUPS X10, 0xa0(SP)
- MOVUPS X11, 0xb0(SP)
- MOVUPS X12, 0xc0(SP)
- MOVUPS X13, 0xd0(SP)
- MOVUPS X14, 0xe0(SP)
- MOVUPS X15, 0xf0(SP)
-
- MOVQ CX, 0x0(SP) /* fn */
- MOVQ DX, 0x8(SP) /* arg */
- // Skip n in R8.
- MOVQ R9, 0x10(SP) /* ctxt */
-
- CALL runtime·cgocallback(SB)
-
- MOVQ 0x48(SP), DI
- MOVQ 0x50(SP), SI
- MOVUPS 0x60(SP), X6
- MOVUPS 0x70(SP), X7
- MOVUPS 0x80(SP), X8
- MOVUPS 0x90(SP), X9
- MOVUPS 0xa0(SP), X10
- MOVUPS 0xb0(SP), X11
- MOVUPS 0xc0(SP), X12
- MOVUPS 0xd0(SP), X13
- MOVUPS 0xe0(SP), X14
- MOVUPS 0xf0(SP), X15
-#else
MOVQ DI, 0x0(SP) /* fn */
MOVQ SI, 0x8(SP) /* arg */
// Skip n in DX.
MOVQ CX, 0x10(SP) /* ctxt */
CALL runtime·cgocallback(SB)
-#endif
MOVQ 0x18(SP), BX
MOVQ 0x28(SP), R12
MOVQ 0x40(SP), R15
RET
+
+#else
+TEXT crosscall2(SB),NOSPLIT,$0-0
+ PUSH_REGS_HOST_TO_ABI0()
+
+ // Make room for arguments to cgocallback.
+ ADJSP $0x18
+ MOVQ CX, 0x0(SP) /* fn */
+ MOVQ DX, 0x8(SP) /* arg */
+ // Skip n in R8.
+ MOVQ R9, 0x10(SP) /* ctxt */
+
+ CALL runtime·cgocallback(SB)
+
+ ADJSP $-0x18
+ POP_REGS_HOST_TO_ABI0()
+ RET
+#endif
#include "go_asm.h"
#include "go_tls.h"
#include "textflag.h"
+#include "cgo/abi_amd64.h"
// maxargs should be divisible by 2, as Windows stack
// must be kept 16-byte aligned on syscall entry.
TEXT sigtramp<>(SB),NOSPLIT|NOFRAME,$0-0
// CX: PEXCEPTION_POINTERS ExceptionInfo
- // DI SI BP BX R12 R13 R14 R15 registers and DF flag are preserved
- // as required by windows callback convention.
- PUSHFQ
- SUBQ $112, SP
- MOVQ DI, 80(SP)
- MOVQ SI, 72(SP)
- MOVQ BP, 64(SP)
- MOVQ BX, 56(SP)
- MOVQ R12, 48(SP)
- MOVQ R13, 40(SP)
- MOVQ R14, 32(SP)
- MOVQ R15, 88(SP)
+ // Switch from the host ABI to the Go ABI.
+ PUSH_REGS_HOST_TO_ABI0()
+ // Make stack space for the rest of the function.
+ ADJSP $48
MOVQ AX, R15 // save handler address
CALL runtime·badsignal2(SB)
// save g and SP in case of stack switch
- MOVQ DX, 96(SP) // g
- MOVQ SP, 104(SP)
+ MOVQ DX, 32(SP) // g
+ MOVQ SP, 40(SP)
// do we need to switch to the g0 stack?
MOVQ g_m(DX), BX
MOVQ (g_sched+gobuf_sp)(BX), DI
// make room for sighandler arguments
// and re-save old SP for restoring later.
- // (note that the 104(DI) here must match the 104(SP) above.)
- SUBQ $120, DI
- MOVQ SP, 104(DI)
+ // Adjust g0 stack by the space we're using and
+ // save SP at the same place on the g0 stack.
+ // The 32(DI) here must match the 32(SP) above.
+ SUBQ $(REGS_HOST_TO_ABI0_STACK + 48), DI
+ MOVQ SP, 40(DI)
MOVQ DI, SP
g0:
// switch back to original stack and g
// no-op if we never left.
- MOVQ 104(SP), SP
- MOVQ 96(SP), DX
+ MOVQ 40(SP), SP
+ MOVQ 32(SP), DX
get_tls(BP)
MOVQ DX, g(BP)
done:
- // restore registers as required for windows callback
- MOVQ 88(SP), R15
- MOVQ 32(SP), R14
- MOVQ 40(SP), R13
- MOVQ 48(SP), R12
- MOVQ 56(SP), BX
- MOVQ 64(SP), BP
- MOVQ 72(SP), SI
- MOVQ 80(SP), DI
- ADDQ $112, SP
- POPFQ
+ ADJSP $-48
+ POP_REGS_HOST_TO_ABI0()
RET
DIVL CX
SUBQ $1, AX // subtract 1 because return PC is to the next slot
- // DI SI BP BX R12 R13 R14 R15 registers and DF flag are preserved
- // as required by windows callback convention.
- PUSHFQ
- SUBQ $64, SP
- MOVQ DI, 56(SP)
- MOVQ SI, 48(SP)
- MOVQ BP, 40(SP)
- MOVQ BX, 32(SP)
- MOVQ R12, 24(SP)
- MOVQ R13, 16(SP)
- MOVQ R14, 8(SP)
- MOVQ R15, 0(SP)
-
- // Go ABI requires DF flag to be cleared.
- CLD
+ // Switch from the host ABI to the Go ABI.
+ PUSH_REGS_HOST_TO_ABI0()
// Create a struct callbackArgs on our stack to be passed as
// the "frame" to cgocallback and on to callbackWrap.
MOVQ (24+callbackArgs_result)(SP), AX
ADDQ $(24+callbackArgs__size), SP
- // restore registers as required for windows callback
- MOVQ 0(SP), R15
- MOVQ 8(SP), R14
- MOVQ 16(SP), R13
- MOVQ 24(SP), R12
- MOVQ 32(SP), BX
- MOVQ 40(SP), BP
- MOVQ 48(SP), SI
- MOVQ 56(SP), DI
- ADDQ $64, SP
- POPFQ
+ POP_REGS_HOST_TO_ABI0()
// The return value was placed in AX above.
RET
// uint32 tstart_stdcall(M *newm);
TEXT runtime·tstart_stdcall<ABIInternal>(SB),NOSPLIT,$0
+ // Switch from the host ABI to the Go ABI.
+ PUSH_REGS_HOST_TO_ABI0()
+
// CX contains first arg newm
MOVQ m_g0(CX), DX // g
MOVQ CX, g_m(DX)
MOVQ DX, g(SI)
- // Someday the convention will be D is always cleared.
- CLD
-
CALL runtime·stackcheck(SB) // clobbers AX,CX
CALL runtime·mstart(SB)
+ POP_REGS_HOST_TO_ABI0()
+
XORL AX, AX // return 0 == success
RET