Skip to content

Commit

Permalink
Add linux-arm64 support
Browse files Browse the repository at this point in the history
  • Loading branch information
csnewman committed Dec 4, 2024
1 parent af092bf commit e003f0f
Show file tree
Hide file tree
Showing 33 changed files with 1,635 additions and 0 deletions.
5 changes: 5 additions & 0 deletions cgo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//go:build cgo

package goblend

import _ "runtime/cgo"
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/csnewman/goblend

go 1.23
10 changes: 10 additions & 0 deletions goblend.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package goblend

import _ "unsafe"

//go:linkname runtime_cgocall runtime.cgocall
func runtime_cgocall(fn uintptr, arg uintptr) int32

func Call(fn uintptr, arg uintptr) int32 {
return runtime_cgocall(fn, arg)
}
5 changes: 5 additions & 0 deletions nocgo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//go:build !cgo

package goblend

import _ "github.com/csnewman/goblend/runtime"
4 changes: 4 additions & 0 deletions runtime/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
linux-arm64:
zig build-obj -O ReleaseFast -target aarch64-linux-gnu --library c -femit-bin=runtime_linux_arm64.syso \
gcc_libinit.c gcc_stack_unix.c gcc_linux_arm64.c gcc_arm64.S gcc_util.c gcc_setenv.c linux_syscall.c \
gcc_mmap.c gcc_sigaction.c
99 changes: 99 additions & 0 deletions runtime/abi_amd64.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// 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.
//
// These save the frame pointer, so in general, functions that use
// these should have zero frame size to suppress the automatic frame
// pointer, though it's harmless to not do this.

#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

#else
// SysV ABI

#define REGS_HOST_TO_ABI0_STACK (6*8)

// SysV 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.
// Both SysV and Go require DF to be cleared, so that's already clear.
// The SysV and Go frame pointer conventions are compatible.
#define PUSH_REGS_HOST_TO_ABI0() \
ADJSP $(REGS_HOST_TO_ABI0_STACK) \
MOVQ BP, (5*8)(SP) \
LEAQ (5*8)(SP), BP \
MOVQ BX, (0*8)(SP) \
MOVQ R12, (1*8)(SP) \
MOVQ R13, (2*8)(SP) \
MOVQ R14, (3*8)(SP) \
MOVQ R15, (4*8)(SP)

#define POP_REGS_HOST_TO_ABI0() \
MOVQ (0*8)(SP), BX \
MOVQ (1*8)(SP), R12 \
MOVQ (2*8)(SP), R13 \
MOVQ (3*8)(SP), R14 \
MOVQ (4*8)(SP), R15 \
MOVQ (5*8)(SP), BP \
ADJSP $-(REGS_HOST_TO_ABI0_STACK)

#endif
43 changes: 43 additions & 0 deletions runtime/abi_arm64.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// 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.
//
// These macros save and restore the callee-saved registers
// from the stack, but they don't adjust stack pointer, so
// the user should prepare stack space in advance.
// SAVE_R19_TO_R28(offset) saves R19 ~ R28 to the stack space
// of ((offset)+0*8)(RSP) ~ ((offset)+9*8)(RSP).
//
// SAVE_F8_TO_F15(offset) saves F8 ~ F15 to the stack space
// of ((offset)+0*8)(RSP) ~ ((offset)+7*8)(RSP).
//
// R29 is not saved because Go will save and restore it.

#define SAVE_R19_TO_R28(offset) \
STP (R19, R20), ((offset)+0*8)(RSP) \
STP (R21, R22), ((offset)+2*8)(RSP) \
STP (R23, R24), ((offset)+4*8)(RSP) \
STP (R25, R26), ((offset)+6*8)(RSP) \
STP (R27, g), ((offset)+8*8)(RSP)

#define RESTORE_R19_TO_R28(offset) \
LDP ((offset)+0*8)(RSP), (R19, R20) \
LDP ((offset)+2*8)(RSP), (R21, R22) \
LDP ((offset)+4*8)(RSP), (R23, R24) \
LDP ((offset)+6*8)(RSP), (R25, R26) \
LDP ((offset)+8*8)(RSP), (R27, g) /* R28 */

#define SAVE_F8_TO_F15(offset) \
FSTPD (F8, F9), ((offset)+0*8)(RSP) \
FSTPD (F10, F11), ((offset)+2*8)(RSP) \
FSTPD (F12, F13), ((offset)+4*8)(RSP) \
FSTPD (F14, F15), ((offset)+6*8)(RSP)

#define RESTORE_F8_TO_F15(offset) \
FLDPD ((offset)+0*8)(RSP), (F8, F9) \
FLDPD ((offset)+2*8)(RSP), (F10, F11) \
FLDPD ((offset)+4*8)(RSP), (F12, F13) \
FLDPD ((offset)+6*8)(RSP), (F14, F15)

42 changes: 42 additions & 0 deletions runtime/asm_386.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright 2009 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 "textflag.h"

// Set the x_crosscall2_ptr C function pointer variable point to crosscall2.
// It's such a pointer chain: _crosscall2_ptr -> x_crosscall2_ptr -> crosscall2
// Use a local trampoline, to avoid taking the address of a dynamically exported
// function.
TEXT ·set_crosscall2(SB),NOSPLIT,$0-0
MOVL _crosscall2_ptr(SB), AX
MOVL $crosscall2_trampoline<>(SB), BX
MOVL BX, (AX)
RET

TEXT crosscall2_trampoline<>(SB),NOSPLIT,$0-0
JMP crosscall2(SB)

// Called by C code generated by cmd/cgo.
// func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr)
// Saves C callee-saved registers and calls cgocallback with three arguments.
// fn is the PC of a func(a unsafe.Pointer) function.
TEXT crosscall2(SB),NOSPLIT,$28-16
MOVL BP, 24(SP)
MOVL BX, 20(SP)
MOVL SI, 16(SP)
MOVL DI, 12(SP)

MOVL ctxt+12(FP), AX
MOVL AX, 8(SP)
MOVL a+4(FP), AX
MOVL AX, 4(SP)
MOVL fn+0(FP), AX
MOVL AX, 0(SP)
CALL runtime·cgocallback(SB)

MOVL 12(SP), DI
MOVL 16(SP), SI
MOVL 20(SP), BX
MOVL 24(SP), BP
RET
47 changes: 47 additions & 0 deletions runtime/asm_amd64.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright 2009 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 "textflag.h"
#include "abi_amd64.h"

// Set the x_crosscall2_ptr C function pointer variable point to crosscall2.
// It's such a pointer chain: _crosscall2_ptr -> x_crosscall2_ptr -> crosscall2
// Use a local trampoline, to avoid taking the address of a dynamically exported
// function.
TEXT ·set_crosscall2(SB),NOSPLIT,$0-0
MOVQ _crosscall2_ptr(SB), AX
MOVQ $crosscall2_trampoline<>(SB), BX
MOVQ BX, (AX)
RET

TEXT crosscall2_trampoline<>(SB),NOSPLIT,$0-0
JMP crosscall2(SB)

// Called by C code generated by cmd/cgo.
// func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr)
// Saves C callee-saved registers and calls cgocallback with three arguments.
// fn is the PC of a func(a unsafe.Pointer) function.
// This signature is known to SWIG, so we can't change it.
TEXT crosscall2(SB),NOSPLIT,$0-0
PUSH_REGS_HOST_TO_ABI0()

// Make room for arguments to cgocallback.
ADJSP $0x18
#ifndef GOOS_windows
MOVQ DI, 0x0(SP) /* fn */
MOVQ SI, 0x8(SP) /* arg */
// Skip n in DX.
MOVQ CX, 0x10(SP) /* ctxt */
#else
MOVQ CX, 0x0(SP) /* fn */
MOVQ DX, 0x8(SP) /* arg */
// Skip n in R8.
MOVQ R9, 0x10(SP) /* ctxt */
#endif

CALL runtime·cgocallback(SB)

ADJSP $-0x18
POP_REGS_HOST_TO_ABI0()
RET
69 changes: 69 additions & 0 deletions runtime/asm_arm.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright 2012 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 "textflag.h"

// Set the x_crosscall2_ptr C function pointer variable point to crosscall2.
// It's such a pointer chain: _crosscall2_ptr -> x_crosscall2_ptr -> crosscall2
// Use a local trampoline, to avoid taking the address of a dynamically exported
// function.
TEXT ·set_crosscall2(SB),NOSPLIT,$0-0
MOVW _crosscall2_ptr(SB), R1
MOVW $crosscall2_trampoline<>(SB), R2
MOVW R2, (R1)
RET

TEXT crosscall2_trampoline<>(SB),NOSPLIT,$0-0
JMP crosscall2(SB)

// Called by C code generated by cmd/cgo.
// func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr)
// Saves C callee-saved registers and calls cgocallback with three arguments.
// fn is the PC of a func(a unsafe.Pointer) function.
TEXT crosscall2(SB),NOSPLIT|NOFRAME,$0
SUB $(8*9), R13 // Reserve space for the floating point registers.
// The C arguments arrive in R0, R1, R2, and R3. We want to
// pass R0, R1, and R3 to Go, so we push those on the stack.
// Also, save C callee-save registers R4-R12.
MOVM.WP [R0, R1, R3, R4, R5, R6, R7, R8, R9, g, R11, R12], (R13)
// Finally, save the link register R14. This also puts the
// arguments we pushed for cgocallback where they need to be,
// starting at 4(R13).
MOVW.W R14, -4(R13)

// Skip floating point registers if goarmsoftfp!=0.
MOVB runtime·goarmsoftfp(SB), R11
CMP $0, R11
BNE skipfpsave
MOVD F8, (13*4+8*1)(R13)
MOVD F9, (13*4+8*2)(R13)
MOVD F10, (13*4+8*3)(R13)
MOVD F11, (13*4+8*4)(R13)
MOVD F12, (13*4+8*5)(R13)
MOVD F13, (13*4+8*6)(R13)
MOVD F14, (13*4+8*7)(R13)
MOVD F15, (13*4+8*8)(R13)

skipfpsave:
BL runtime·load_g(SB)
// We set up the arguments to cgocallback when saving registers above.
BL runtime·cgocallback(SB)

MOVB runtime·goarmsoftfp(SB), R11
CMP $0, R11
BNE skipfprest
MOVD (13*4+8*1)(R13), F8
MOVD (13*4+8*2)(R13), F9
MOVD (13*4+8*3)(R13), F10
MOVD (13*4+8*4)(R13), F11
MOVD (13*4+8*5)(R13), F12
MOVD (13*4+8*6)(R13), F13
MOVD (13*4+8*7)(R13), F14
MOVD (13*4+8*8)(R13), F15

skipfprest:
MOVW.P 4(R13), R14
MOVM.IAW (R13), [R0, R1, R3, R4, R5, R6, R7, R8, R9, g, R11, R12]
ADD $(8*9), R13
MOVW R14, R15
50 changes: 50 additions & 0 deletions runtime/asm_arm64.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright 2015 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 "textflag.h"
#include "abi_arm64.h"

// Set the x_crosscall2_ptr C function pointer variable point to crosscall2.
// It's such a pointer chain: _crosscall2_ptr -> x_crosscall2_ptr -> crosscall2
// Use a local trampoline, to avoid taking the address of a dynamically exported
// function.
TEXT ·set_crosscall2(SB),NOSPLIT,$0-0
MOVD _crosscall2_ptr(SB), R1
MOVD $crosscall2_trampoline<>(SB), R2
MOVD R2, (R1)
RET

TEXT crosscall2_trampoline<>(SB),NOSPLIT,$0-0
JMP crosscall2(SB)

// Called by C code generated by cmd/cgo.
// func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr)
// Saves C callee-saved registers and calls cgocallback with three arguments.
// fn is the PC of a func(a unsafe.Pointer) function.
TEXT crosscall2(SB),NOSPLIT|NOFRAME,$0
/*
* We still need to save all callee save register as before, and then
* push 3 args for fn (R0, R1, R3), skipping R2.
* Also note that at procedure entry in gc world, 8(RSP) will be the
* first arg.
*/
SUB $(8*24), RSP
STP (R0, R1), (8*1)(RSP)
MOVD R3, (8*3)(RSP)

SAVE_R19_TO_R28(8*4)
SAVE_F8_TO_F15(8*14)
STP (R29, R30), (8*22)(RSP)


// Initialize Go ABI environment
BL runtime·load_g(SB)
BL runtime·cgocallback(SB)

RESTORE_R19_TO_R28(8*4)
RESTORE_F8_TO_F15(8*14)
LDP (8*22)(RSP), (R29, R30)

ADD $(8*24), RSP
RET
Loading

0 comments on commit e003f0f

Please sign in to comment.