@@ -19,35 +19,71 @@ import (
1919
2020var templateArchTrampolines = template .Must (template .New ("arch_trampolines" ).Funcs (funcs ).Parse (
2121 `// Code generated by 'go generate' with gen.go. DO NOT EDIT.
22-
22+
2323// SPDX-License-Identifier: Apache-2.0
2424// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
25-
25+
2626//go:build {{.Tag}}
27-
27+
2828#include "textflag.h"
2929#include "go_asm.h"
30-
30+
3131// these trampolines map the gcc ABI to Go ABI and then calls into the Go equivalent functions.
3232{{ range .Symbols }}
33- TEXT {{.Name}}_trampoline(SB), NOSPLIT, ${{argCount .Args | mul $.Arch.WordSize}}
34- {{- range $i, $arg := .Args }}
35- {{- if $arg.Name }}
33+ {{- if $.Arch.StackBased }}
34+ {{- if eq .ArgsCount 0 }}
35+ TEXT _x_cgo_{{.Name}}_trampoline(SB), NOSPLIT, $0-0
36+ CALL ·x_cgo_{{.Name}}(SB)
37+ RET
38+ {{- else }}
39+ TEXT _x_cgo_{{.Name}}_trampoline(SB), NOSPLIT, ${{mul .ArgsCount $.Arch.WordSize}}-0
40+ {{- if eq $.Arch.Name "arm" }}
41+ {{- range $i := .ArgsCount }}
42+ {{- $dstOffset := add 4 (mul $i $.Arch.WordSize) }}
43+ {{$.Arch.MOV}} R{{$i}}, {{$dstOffset}}(R13)
44+ {{- end }}
45+ {{$.Arch.MOV}} ·_cgo_{{.Name}}_call(SB), {{$.Arch.VolatileReg}}
46+ {{$.Arch.MOV}} ({{$.Arch.VolatileReg}}), {{$.Arch.VolatileReg}}
47+ {{- if $.Arch.CallNeedsParens }}
48+ CALL ({{$.Arch.VolatileReg}})
49+ {{- else }}
50+ CALL {{$.Arch.VolatileReg}}
51+ {{- end }}
52+ RET
53+ {{- else }}
54+ {{- $frameSize := mul .ArgsCount $.Arch.WordSize }}
55+ {{- $retAddrSize := $.Arch.WordSize }}
56+ {{- range $i := .ArgsCount }}
57+ {{- $srcOffset := add $frameSize $retAddrSize }}
58+ {{- $srcOffset = add $srcOffset (mul $i $.Arch.WordSize) }}
59+ {{- $dstOffset := mul $i $.Arch.WordSize }}
60+ {{$.Arch.MOV}} {{$srcOffset}}(SP), AX
61+ {{$.Arch.MOV}} AX, {{$dstOffset}}(SP)
62+ {{- end }}
63+ {{$.Arch.MOV}} ·_cgo_{{.Name}}_call(SB), {{$.Arch.VolatileReg}}
64+ {{$.Arch.MOV}} ({{$.Arch.VolatileReg}}), {{$.Arch.VolatileReg}}
65+ CALL {{$.Arch.VolatileReg}}
66+ RET
67+ {{- end }}
68+ {{- end }}
69+ {{- else }}
70+ TEXT _x_cgo_{{.Name}}_trampoline(SB), NOSPLIT, ${{mul .ArgsCount $.Arch.WordSize}}
71+ {{- range $i := .ArgsCount }}
3672 {{- $src := index $.Arch.C.IntRegArgs $i }}
3773 {{- $dst := index $.Arch.GoABI0.IntRegArgs $i }}
3874 {{- if ne $src $dst }}
39- {{$.Arch.MOV}} {{$src}}, {{$dst}}
75+ {{$.Arch.MOV}} {{$src}}, {{$dst}}
4076 {{- end }}
4177{{- end }}
42- {{- end }}
43- {{$.Arch.MOV}} ·{{.Name}}_call(SB), {{$.Arch.VolatileReg}}
44- {{$.Arch.MOV}} ({{$.Arch.VolatileReg}}), {{$.Arch.VolatileReg}}
45- {{- if eq $.Arch.Name "loong64" }}
46- CALL ({{$.Arch.VolatileReg}})
78+ {{$.Arch.MOV}} ·_cgo_{{.Name}}_call(SB), {{$.Arch.VolatileReg}}
79+ {{$.Arch.MOV}} ({{$.Arch.VolatileReg}}), {{$.Arch.VolatileReg}}
80+ {{- if $.Arch.CallNeedsParens }}
81+ CALL ({{$.Arch.VolatileReg}})
4782{{- else }}
48- CALL {{$.Arch.VolatileReg}}
83+ CALL {{$.Arch.VolatileReg}}
84+ {{- end }}
85+ RET
4986{{- end }}
50- RET
5187{{ end }}` ))
5288
5389var templateSymbols = template .Must (template .New ("symbols" ).Funcs (funcs ).Parse (
@@ -147,19 +183,16 @@ import (
147183)
148184
149185{{ range .Symbols }}
150- {{- $cgoName := getCgoName .Name }}
151- {{- if $cgoName }}
152- //go:linkname {{.Name}}_trampoline {{.Name}}_trampoline
153- //go:linkname {{$cgoName}} {{$cgoName}}
154- var {{.Name}}_trampoline byte
155- var {{$cgoName}} = &{{.Name}}_trampoline
156- {{- end }}
186+ //go:linkname _x_cgo_{{.Name}}_trampoline _x_cgo_{{.Name}}_trampoline
187+ //go:linkname _cgo_{{.Name}} {{if .Package}}{{.Package}}.{{end}}_cgo_{{.Name}}
188+ var _x_cgo_{{.Name}}_trampoline byte
189+ var _cgo_{{.Name}} = &_x_cgo_{{.Name}}_trampoline
157190{{- end }}
158191
159192var (
160193 threadentry_call = threadentry
161194{{- range .Symbols }}
162- {{.Name}}_call = {{.Name}}
195+ _cgo_ {{.Name}}_call = x_cgo_ {{.Name}}
163196{{- end }}
164197)
165198` ))
@@ -205,35 +238,10 @@ var (
205238)
206239
207240var funcs = map [string ]any {
208- "hasPrefix" : strings .HasPrefix ,
209- "imports" : imports ,
210- "argCount" : argCount ,
211- "mul" : func (a , b int ) int { return a * b },
212- "getCgoName" : getCgoName ,
213- }
214-
215- func getCgoName (name string ) string {
216- switch name {
217- case "x_cgo_init" :
218- return "_cgo_init"
219- case "x_cgo_thread_start" :
220- return "_cgo_thread_start"
221- case "x_cgo_notify_runtime_init_done" :
222- return "_cgo_notify_runtime_init_done"
223- case "x_cgo_bindm" :
224- return "_cgo_bindm"
225- }
226- return ""
227- }
228-
229- func argCount (args [5 ]Arg ) int {
230- count := 0
231- for _ , arg := range args {
232- if arg .Name != "" {
233- count ++
234- }
235- }
236- return count
241+ "hasPrefix" : strings .HasPrefix ,
242+ "imports" : imports ,
243+ "mul" : func (a , b int ) int { return a * b },
244+ "add" : func (a , b int ) int { return a + b },
237245}
238246
239247var GOOSes = []string {"darwin" , "freebsd" , "linux" , "netbsd" }
@@ -382,73 +390,97 @@ func run() error {
382390 return err
383391 }
384392 }
385- if err := execute (templateCallbacks , "zcallbacks.go" , struct { Symbols []Symbol }{Symbols : archTrampolines }); err != nil {
393+ if err := execute (templateCallbacks , "zcallbacks.go" , struct { Symbols []AsmGoSymbol }{Symbols : asmGoSymbols }); err != nil {
386394 return err
387395 }
388396 return nil
389397}
390398
391399type Arch struct {
392- Name string // as in runtime.GOARCH
393- GoABIInternal ABI // if empty, same as GoABI0
394- GoABI0 ABI
395- C ABI
396- WordSize int // 4 on 32-bit systems, 8 on 64-bit systems
397- MOV string // MOV instruction, e.g., "MOVL" or "MOVQ"
398- VolatileReg string // Scratch register for intermediate values
400+ Name string // as in runtime.GOARCH
401+ GoABI0 ABI
402+ C ABI
403+ WordSize int // 4 on 32-bit systems, 8 on 64-bit systems
404+ MOV string // MOV instruction, e.g., "MOVL" or "MOVQ"
405+ VolatileReg string // Scratch register for intermediate values
406+ CallNeedsParens bool
407+ StackBased bool // true if using stack-based calling convention (e.g., 386)
399408}
400409
401410type ABI struct {
402411 IntRegArgs [5 ]string // Name of integer argument registers in order. If empty, stack-based calling convention is used.
403412 OutRegArg string // Name of the register for the single return value. If empty, stack-based calling convention is used.
404413}
405414
415+ // AsmGoSymbols are symbols that called from Go Assembly.
416+ type AsmGoSymbol struct {
417+ Name string
418+ ArgsCount int
419+ Package string
420+ }
421+
406422var (
407423 archs = []Arch {
408424 {
409- Name : "amd64" ,
410- WordSize : 8 ,
411- GoABIInternal : ABI {IntRegArgs : [5 ]string {"AX" , "BX" , "CX" , "DX" , "SI" }, OutRegArg : "AX" },
412- GoABI0 : ABI {IntRegArgs : [5 ]string {"AX" , "BX" , "CX" , "DX" , "SI" }, OutRegArg : "AX" },
413- C : ABI {IntRegArgs : [5 ]string {"DI" , "SI" , "DX" , "CX" , "R8" }, OutRegArg : "AX" },
414- MOV : "MOVQ" ,
415- VolatileReg : "R11" ,
425+ Name : "386" ,
426+ WordSize : 4 ,
427+ GoABI0 : ABI {}, // stack-based calling convention
428+ C : ABI {}, // stack-based calling convention
429+ MOV : "MOVL" ,
430+ VolatileReg : "CX" ,
431+ StackBased : true ,
432+ },
433+ {
434+ Name : "amd64" ,
435+ WordSize : 8 ,
436+ GoABI0 : ABI {IntRegArgs : [5 ]string {"AX" , "BX" , "CX" , "DX" , "SI" }, OutRegArg : "AX" },
437+ C : ABI {IntRegArgs : [5 ]string {"DI" , "SI" , "DX" , "CX" , "R8" }, OutRegArg : "AX" },
438+ MOV : "MOVQ" ,
439+ VolatileReg : "R11" ,
440+ },
441+ {
442+ Name : "arm" ,
443+ WordSize : 4 ,
444+ GoABI0 : ABI {}, // stack-based calling convention
445+ C : ABI {}, // stack-based calling convention
446+ MOV : "MOVW" ,
447+ VolatileReg : "R12" ,
448+ StackBased : true ,
449+ CallNeedsParens : true ,
416450 },
417451 {
418- Name : "arm64" ,
419- WordSize : 8 ,
420- GoABIInternal : ABI {IntRegArgs : [5 ]string {"R0" , "R1" , "R2" , "R3" , "R4" }, OutRegArg : "R0" },
421- GoABI0 : ABI {IntRegArgs : [5 ]string {"R0" , "R1" , "R2" , "R3" , "R4" }, OutRegArg : "R0" },
422- C : ABI {IntRegArgs : [5 ]string {"R0" , "R1" , "R2" , "R3" , "R4" }, OutRegArg : "R0" },
423- MOV : "MOVD" ,
424- VolatileReg : "R9" ,
452+ Name : "arm64" ,
453+ WordSize : 8 ,
454+ GoABI0 : ABI {IntRegArgs : [5 ]string {"R0" , "R1" , "R2" , "R3" , "R4" }, OutRegArg : "R0" },
455+ C : ABI {IntRegArgs : [5 ]string {"R0" , "R1" , "R2" , "R3" , "R4" }, OutRegArg : "R0" },
456+ MOV : "MOVD" ,
457+ VolatileReg : "R9" ,
425458 },
426459 {
427- Name : "loong64" ,
428- WordSize : 8 ,
429- GoABIInternal : ABI {IntRegArgs : [5 ]string {"R4" , "R5" , "R6" , "R7" , "R8" }, OutRegArg : "R4" },
430- GoABI0 : ABI {IntRegArgs : [5 ]string {"R4" , "R5" , "R6" , "R7" , "R8" }, OutRegArg : "R4" },
431- C : ABI { IntRegArgs : [ 5 ] string { "R4" , "R5" , "R6" , "R7" , "R8" }, OutRegArg : "R4" } ,
432- MOV : "MOVV " ,
433- VolatileReg : "R23" ,
460+ Name : "loong64" ,
461+ WordSize : 8 ,
462+ GoABI0 : ABI {IntRegArgs : [5 ]string {"R4" , "R5" , "R6" , "R7" , "R8" }, OutRegArg : "R4" },
463+ C : ABI {IntRegArgs : [5 ]string {"R4" , "R5" , "R6" , "R7" , "R8" }, OutRegArg : "R4" },
464+ MOV : "MOVV" ,
465+ VolatileReg : "R23 " ,
466+ CallNeedsParens : true ,
434467 },
435468 {
436- Name : "riscv64" ,
437- WordSize : 8 ,
438- GoABIInternal : ABI {IntRegArgs : [5 ]string {"X10" , "X11" , "X12" , "X13" , "X14" }, OutRegArg : "X10" },
439- GoABI0 : ABI {IntRegArgs : [5 ]string {"X10" , "X11" , "X12" , "X13" , "X14" }, OutRegArg : "X10" },
440- C : ABI {IntRegArgs : [5 ]string {"X10" , "X11" , "X12" , "X13" , "X14" }, OutRegArg : "X10" },
441- MOV : "MOV" ,
442- VolatileReg : "X5" ,
469+ Name : "riscv64" ,
470+ WordSize : 8 ,
471+ GoABI0 : ABI {IntRegArgs : [5 ]string {"X10" , "X11" , "X12" , "X13" , "X14" }, OutRegArg : "X10" },
472+ C : ABI {IntRegArgs : [5 ]string {"X10" , "X11" , "X12" , "X13" , "X14" }, OutRegArg : "X10" },
473+ MOV : "MOV " ,
474+ VolatileReg : "X5" ,
443475 },
444476 }
445- archTrampolines = []Symbol {
446- {"x_cgo_init " , [ 5 ] Arg {{ "G" , "*g" }, { "setg" , "uintptr" }}, "" , nil },
447- {"x_cgo_thread_start " , [ 5 ] Arg {{ "ts" , "*ThreadStart" }}, "" , nil },
448- {"x_cgo_setenv " , [ 5 ] Arg {{ "arg" , "*uintptr" }}, "" , nil },
449- {"x_cgo_unsetenv " , [ 5 ] Arg {{ "arg" , "*uintptr" }}, "" , nil },
450- {"x_cgo_notify_runtime_init_done " , [ 5 ] Arg {} , "" , nil },
451- {"x_cgo_bindm " , [ 5 ] Arg {{ "g" , "unsafe.Pointer" }}, "" , nil },
477+ asmGoSymbols = []AsmGoSymbol {
478+ {"init " , 2 , "" },
479+ {"thread_start " , 1 , "" },
480+ {"setenv " , 1 , "runtime" },
481+ {"unsetenv " , 1 , "runtime" },
482+ {"notify_runtime_init_done " , 0 , "" },
483+ {"bindm " , 0 , "" },
452484 }
453485)
454486
@@ -459,6 +491,8 @@ func writeArchTrampolines(arch Arch) error {
459491 gooses = []string {"darwin" , "freebsd" , "linux" }
460492 case "loong64" , "riscv64" :
461493 gooses = []string {"linux" }
494+ case "386" :
495+ gooses = []string {"freebsd" , "linux" }
462496 default :
463497 gooses = GOOSes
464498 }
@@ -468,11 +502,11 @@ func writeArchTrampolines(arch Arch) error {
468502 }
469503 data := struct {
470504 Tag string
471- Symbols []Symbol
505+ Symbols []AsmGoSymbol
472506 Arch Arch
473507 }{
474508 Tag : tag ,
475- Symbols : archTrampolines ,
509+ Symbols : asmGoSymbols ,
476510 Arch : arch ,
477511 }
478512 return execute (templateArchTrampolines , fmt .Sprintf ("ztrampolines_%s.s" , arch .Name ), data )
0 commit comments