detached fa49e74

purego: support 32 arguments on 64bit (#431)

Closes #425
commit
fa49e74b0075772005ad4360f34107c6ff90fb50
author
Travis Cline · · 2026-04-30 03:18 UTC
committer
GitHub · · 2026-04-30 03:18 UTC
parent
56b2dd8
signature
GPG UnverifiedB5690EEEBB952194 The key is unknown
refs
tag: v0.11.0-alpha.2
31 files · +992 -580
A cdecl.go +11 -0
@@ -0,0 +1,11 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2026 The Ebitengine Authors
3+
4+package purego
5+
6+// CDecl marks a function as being called using the __cdecl calling convention as defined in
7+// the [MSDocs] when passed to NewCallback. It must be the first argument to the function.
8+// This is only useful on 386 Windows, but it is safe to use on other platforms.
9+//
10+// [MSDocs]: https://learn.microsoft.com/en-us/cpp/cpp/cdecl?view=msvc-170
11+type CDecl struct{}
@@ -0,0 +1,11 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2026 The Ebitengine Authors
3+
4+package purego
5+
6+// CDecl marks a function as being called using the __cdecl calling convention as defined in
7+// the [MSDocs] when passed to NewCallback. It must be the first argument to the function.
8+// This is only useful on 386 Windows, but it is safe to use on other platforms.
9+//
10+// [MSDocs]: https://learn.microsoft.com/en-us/cpp/cpp/cdecl?view=msvc-170
11+type CDecl struct{}
M func.go +25 -23
@@ -23,7 +23,7 @@ const (
2323 )
2424
2525 var thePool = sync.Pool{New: func() any {
26- return new(syscall15Args)
26+ return new(syscallArgs)
2727 }}
2828
2929 // RegisterLibFunc is a wrapper around RegisterFunc that uses the C function returned from Dlsym(handle, name).
@@ -141,6 +141,7 @@ func RegisterFunc(fptr any, cfn uintptr) {
141141 // to avoid crashing with too many arguments
142142 var ints int
143143 var floats int
144+ floatArgRegs := numOfFloatRegisters()
144145 var stack int
145146 for i := 0; i < ty.NumIn(); i++ {
146147 arg := ty.In(i)
@@ -167,7 +168,7 @@ func RegisterFunc(fptr any, cfn uintptr) {
167168 stack++
168169 }
169170 case reflect.Float32, reflect.Float64:
170- if floats < numOfFloatRegisters() {
171+ if floats < floatArgRegs {
171172 floats++
172173 } else {
173174 stack++
@@ -202,10 +203,15 @@ func RegisterFunc(fptr any, cfn uintptr) {
202203 }
203204 }
204205
205- sizeOfStack := maxArgs - numOfIntegerRegisters()
206- // On Darwin ARM64, use byte-based validation since arguments pack efficiently.
207- // See https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms
208- if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" {
206+ argsLimit := maxArgs
207+ sizeOfStack := argsLimit - numOfIntegerRegisters()
208+ if runtime.GOOS == "windows" {
209+ if ints+floats+stack > argsLimit {
210+ panic("purego: too many stack arguments")
211+ }
212+ } else if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" {
213+ // On Darwin ARM64, use byte-based validation since arguments pack efficiently.
214+ // See https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms
209215 stackBytes := estimateStackBytes(ty)
210216 maxStackBytes := sizeOfStack * 8
211217 if stackBytes > maxStackBytes {
@@ -224,6 +230,7 @@ func RegisterFunc(fptr any, cfn uintptr) {
224230 // since numOfFloatRegisters() is a function call, not a constant.
225231 // maxArgs is always greater than or equal to numOfFloatRegisters() so this is safe.
226232 var floats [maxArgs]uintptr
233+ floatArgRegs := numOfFloatRegisters()
227234 var numInts int
228235 var numFloats int
229236 var numStack int
@@ -243,7 +250,7 @@ func RegisterFunc(fptr any, cfn uintptr) {
243250 }
244251 }
245252 addFloat = func(x uintptr) {
246- if numFloats < numOfFloatRegisters() {
253+ if numFloats < floatArgRegs {
247254 floats[numFloats] = x
248255 numFloats++
249256 } else {
@@ -257,6 +264,9 @@ func RegisterFunc(fptr any, cfn uintptr) {
257264 // This is in contrast to how macOS and Linux pass arguments which
258265 // tries to use as many registers as possible in the calling convention.
259266 addStack = func(x uintptr) {
267+ if numStack >= maxArgs {
268+ panic("purego: too many stack arguments")
269+ }
260270 sysargs[numStack] = x
261271 numStack++
262272 }
@@ -310,24 +320,16 @@ func RegisterFunc(fptr any, cfn uintptr) {
310320 keepAlive = addValue(v, keepAlive, addInt, addFloat, addStack, &numInts, &numFloats, &numStack)
311321 }
312322
313- syscall := thePool.Get().(*syscall15Args)
314- defer thePool.Put(syscall)
315-
316- if runtime.GOARCH == "loong64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "riscv64" || runtime.GOARCH == "s390x" {
317- syscall.Set(cfn, sysargs[:], floats[:], 0)
318- runtime_cgocall(syscall15XABI0, unsafe.Pointer(syscall))
319- } else if runtime.GOARCH == "arm64" || runtime.GOOS != "windows" {
320- // Use the normal arm64 calling convention even on Windows
321- syscall.Set(cfn, sysargs[:], floats[:], arm64_r8)
322- runtime_cgocall(syscall15XABI0, unsafe.Pointer(syscall))
323- } else {
324- *syscall = syscall15Args{}
325- // This is a fallback for Windows amd64, 386, and arm. Note this may not support floats
326- syscall.a1, syscall.a2, _ = syscall_syscall15X(cfn, sysargs[0], sysargs[1], sysargs[2], sysargs[3], sysargs[4],
327- sysargs[5], sysargs[6], sysargs[7], sysargs[8], sysargs[9], sysargs[10], sysargs[11],
328- sysargs[12], sysargs[13], sysargs[14])
323+ var syscall *syscallArgs
324+ if runtime.GOOS == "windows" && runtime.GOARCH != "arm64" {
325+ // Windows amd64, 386, and arm use syscall.SyscallN.
326+ syscall = thePool.Get().(*syscallArgs)
327+ syscall.a1, syscall.a2, _ = syscall_syscallN(cfn, sysargs[:numStack]...)
329328 syscall.f1 = syscall.a2 // on amd64 a2 stores the float return. On 32bit platforms floats aren't support
329+ } else {
330+ syscall = syscall_SyscallN(cfn, sysargs[:], floats[:], arm64_r8)
330331 }
332+ defer thePool.Put(syscall)
331333 if ty.NumOut() == 0 {
332334 return nil
333335 }
@@ -23,7 +23,7 @@ const (
23 )23 )
24 24
25 var thePool = sync.Pool{New: func() any {25 var thePool = sync.Pool{New: func() any {
26- return new(syscall15Args)26+ return new(syscallArgs)
27 }}27 }}
28 28
29 // RegisterLibFunc is a wrapper around RegisterFunc that uses the C function returned from Dlsym(handle, name).29 // RegisterLibFunc is a wrapper around RegisterFunc that uses the C function returned from Dlsym(handle, name).
@@ -141,6 +141,7 @@ func RegisterFunc(fptr any, cfn uintptr) {
141 // to avoid crashing with too many arguments141 // to avoid crashing with too many arguments
142 var ints int142 var ints int
143 var floats int143 var floats int
144+ floatArgRegs := numOfFloatRegisters()
144 var stack int145 var stack int
145 for i := 0; i < ty.NumIn(); i++ {146 for i := 0; i < ty.NumIn(); i++ {
146 arg := ty.In(i)147 arg := ty.In(i)
@@ -167,7 +168,7 @@ func RegisterFunc(fptr any, cfn uintptr) {
167 stack++168 stack++
168 }169 }
169 case reflect.Float32, reflect.Float64:170 case reflect.Float32, reflect.Float64:
170- if floats < numOfFloatRegisters() {171+ if floats < floatArgRegs {
171 floats++172 floats++
172 } else {173 } else {
173 stack++174 stack++
@@ -202,10 +203,15 @@ func RegisterFunc(fptr any, cfn uintptr) {
202 }203 }
203 }204 }
204 205
205- sizeOfStack := maxArgs - numOfIntegerRegisters()206+ argsLimit := maxArgs
206- // On Darwin ARM64, use byte-based validation since arguments pack efficiently.207+ sizeOfStack := argsLimit - numOfIntegerRegisters()
207- // See https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms208+ if runtime.GOOS == "windows" {
208- if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" {209+ if ints+floats+stack > argsLimit {
210+ panic("purego: too many stack arguments")
211+ }
212+ } else if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" {
213+ // On Darwin ARM64, use byte-based validation since arguments pack efficiently.
214+ // See https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms
209 stackBytes := estimateStackBytes(ty)215 stackBytes := estimateStackBytes(ty)
210 maxStackBytes := sizeOfStack * 8216 maxStackBytes := sizeOfStack * 8
211 if stackBytes > maxStackBytes {217 if stackBytes > maxStackBytes {
@@ -224,6 +230,7 @@ func RegisterFunc(fptr any, cfn uintptr) {
224 // since numOfFloatRegisters() is a function call, not a constant.230 // since numOfFloatRegisters() is a function call, not a constant.
225 // maxArgs is always greater than or equal to numOfFloatRegisters() so this is safe.231 // maxArgs is always greater than or equal to numOfFloatRegisters() so this is safe.
226 var floats [maxArgs]uintptr232 var floats [maxArgs]uintptr
233+ floatArgRegs := numOfFloatRegisters()
227 var numInts int234 var numInts int
228 var numFloats int235 var numFloats int
229 var numStack int236 var numStack int
@@ -243,7 +250,7 @@ func RegisterFunc(fptr any, cfn uintptr) {
243 }250 }
244 }251 }
245 addFloat = func(x uintptr) {252 addFloat = func(x uintptr) {
246- if numFloats < numOfFloatRegisters() {253+ if numFloats < floatArgRegs {
247 floats[numFloats] = x254 floats[numFloats] = x
248 numFloats++255 numFloats++
249 } else {256 } else {
@@ -257,6 +264,9 @@ func RegisterFunc(fptr any, cfn uintptr) {
257 // This is in contrast to how macOS and Linux pass arguments which264 // This is in contrast to how macOS and Linux pass arguments which
258 // tries to use as many registers as possible in the calling convention.265 // tries to use as many registers as possible in the calling convention.
259 addStack = func(x uintptr) {266 addStack = func(x uintptr) {
267+ if numStack >= maxArgs {
268+ panic("purego: too many stack arguments")
269+ }
260 sysargs[numStack] = x270 sysargs[numStack] = x
261 numStack++271 numStack++
262 }272 }
@@ -310,24 +320,16 @@ func RegisterFunc(fptr any, cfn uintptr) {
310 keepAlive = addValue(v, keepAlive, addInt, addFloat, addStack, &numInts, &numFloats, &numStack)320 keepAlive = addValue(v, keepAlive, addInt, addFloat, addStack, &numInts, &numFloats, &numStack)
311 }321 }
312 322
313- syscall := thePool.Get().(*syscall15Args)323+ var syscall *syscallArgs
314- defer thePool.Put(syscall)324+ if runtime.GOOS == "windows" && runtime.GOARCH != "arm64" {
315-325+ // Windows amd64, 386, and arm use syscall.SyscallN.
316- if runtime.GOARCH == "loong64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "riscv64" || runtime.GOARCH == "s390x" {326+ syscall = thePool.Get().(*syscallArgs)
317- syscall.Set(cfn, sysargs[:], floats[:], 0)327+ syscall.a1, syscall.a2, _ = syscall_syscallN(cfn, sysargs[:numStack]...)
318- runtime_cgocall(syscall15XABI0, unsafe.Pointer(syscall))
319- } else if runtime.GOARCH == "arm64" || runtime.GOOS != "windows" {
320- // Use the normal arm64 calling convention even on Windows
321- syscall.Set(cfn, sysargs[:], floats[:], arm64_r8)
322- runtime_cgocall(syscall15XABI0, unsafe.Pointer(syscall))
323- } else {
324- *syscall = syscall15Args{}
325- // This is a fallback for Windows amd64, 386, and arm. Note this may not support floats
326- syscall.a1, syscall.a2, _ = syscall_syscall15X(cfn, sysargs[0], sysargs[1], sysargs[2], sysargs[3], sysargs[4],
327- sysargs[5], sysargs[6], sysargs[7], sysargs[8], sysargs[9], sysargs[10], sysargs[11],
328- sysargs[12], sysargs[13], sysargs[14])
329 syscall.f1 = syscall.a2 // on amd64 a2 stores the float return. On 32bit platforms floats aren't support328 syscall.f1 = syscall.a2 // on amd64 a2 stores the float return. On 32bit platforms floats aren't support
329+ } else {
330+ syscall = syscall_SyscallN(cfn, sysargs[:], floats[:], arm64_r8)
330 }331 }
332+ defer thePool.Put(syscall)
331 if ty.NumOut() == 0 {333 if ty.NumOut() == 0 {
332 return nil334 return nil
333 }335 }
M func_test.go +161 -26
@@ -373,8 +373,8 @@ func TestABI_ArgumentPassing(t *testing.T) {
373373
374374 for _, tt := range tests {
375375 t.Run(tt.name, func(t *testing.T) {
376- if tt.name == "20_int32" && (runtime.GOOS != "darwin" || runtime.GOARCH != "arm64") {
377- t.Skip("20 int32 arguments only supported on Darwin ARM64 with smart stack checking")
376+ if tt.name == "20_int32" && runtime.GOARCH == "ppc64le" {
377+ t.Skip("ppc64le retains the 15-argument limit")
378378 }
379379 if tt.name == "10_float32" && (runtime.GOARCH == "loong64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "riscv64" || runtime.GOARCH == "s390x") {
380380 t.Skip("float32 stack arguments not yet supported on this platform")
@@ -394,39 +394,174 @@ func TestABI_ArgumentPassing(t *testing.T) {
394394 }
395395 })
396396 }
397-}
398397
399-func TestABI_TooManyArguments(t *testing.T) {
400- if runtime.GOOS != "darwin" || runtime.GOARCH != "arm64" {
401- t.Skip("This test is specific to Darwin ARM64")
402- }
398+ t.Run("20_uintptr", func(t *testing.T) {
399+ if runtime.GOARCH == "ppc64le" {
400+ t.Skip("ppc64le retains the 15-argument limit")
401+ }
402+ var fn func(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) uintptr
403+ purego.RegisterLibFunc(&fn, lib, "stack_20_uintptr")
404+ got := fn(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)
405+ const want = uintptr(210)
406+ if got != want {
407+ t.Fatalf("stack_20_uintptr: got %d, want %d", got, want)
408+ }
409+ })
403410
404- libFileName := filepath.Join(t.TempDir(), "abitest.so")
405- if err := buildSharedLib("CC", libFileName, filepath.Join("testdata", "abitest", "abi_test.c")); err != nil {
406- t.Fatal(err)
407- }
408- lib, err := load.OpenLibrary(libFileName)
409- if err != nil {
410- t.Fatalf("Failed to open library %q: %v", libFileName, err)
411- }
412- t.Cleanup(func() {
413- if err := load.CloseLibrary(lib); err != nil {
414- t.Errorf("Failed to close library: %v", err)
411+ t.Run("32_uintptr", func(t *testing.T) {
412+ if runtime.GOARCH == "ppc64le" {
413+ t.Skip("ppc64le retains the 15-argument limit")
414+ }
415+ var fn func(
416+ uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr,
417+ uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr,
418+ uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr,
419+ uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr,
420+ ) uintptr
421+ purego.RegisterLibFunc(&fn, lib, "stack_32_uintptr")
422+ got := fn(
423+ 1, 2, 3, 4, 5, 6, 7, 8,
424+ 9, 10, 11, 12, 13, 14, 15, 16,
425+ 17, 18, 19, 20, 21, 22, 23, 24,
426+ 25, 26, 27, 28, 29, 30, 31, 32,
427+ )
428+ const want = uintptr(528)
429+ if got != want {
430+ t.Fatalf("stack_32_uintptr: got %d, want %d", got, want)
431+ }
432+ })
433+
434+ t.Run("syscalln_20_uintptr", func(t *testing.T) {
435+ if runtime.GOARCH == "ppc64le" {
436+ t.Skip("ppc64le retains the 15-argument limit")
437+ }
438+ fn, err := load.OpenSymbol(lib, "stack_20_uintptr")
439+ if err != nil {
440+ t.Fatalf("OpenSymbol(stack_20_uintptr) failed: %v", err)
441+ }
442+ got, _, _ := purego.SyscallN(fn,
443+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
444+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
445+ )
446+ const want = uintptr(210)
447+ if got != want {
448+ t.Fatalf("stack_20_uintptr SyscallN: got %d, want %d", got, want)
449+ }
450+ })
451+
452+ t.Run("syscalln_32_uintptr", func(t *testing.T) {
453+ if runtime.GOARCH == "ppc64le" {
454+ t.Skip("ppc64le retains the 15-argument limit")
455+ }
456+ fn, err := load.OpenSymbol(lib, "stack_32_uintptr")
457+ if err != nil {
458+ t.Fatalf("OpenSymbol(stack_32_uintptr) failed: %v", err)
459+ }
460+ got, _, _ := purego.SyscallN(fn,
461+ 1, 2, 3, 4, 5, 6, 7, 8,
462+ 9, 10, 11, 12, 13, 14, 15, 16,
463+ 17, 18, 19, 20, 21, 22, 23, 24,
464+ 25, 26, 27, 28, 29, 30, 31, 32,
465+ )
466+ const want = uintptr(528)
467+ if got != want {
468+ t.Fatalf("stack_32_uintptr SyscallN: got %d, want %d", got, want)
469+ }
470+ })
471+
472+ t.Run("32_mixed_int_float", func(t *testing.T) {
473+ if unsafe.Sizeof(uintptr(0)) == 4 {
474+ t.Skip("requires 64-bit uintptr slots")
475+ }
476+ if runtime.GOARCH == "ppc64le" {
477+ t.Skip("mixed int/float stack arguments are not yet supported on ppc64le")
478+ }
479+
480+ var fn func(
481+ uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr,
482+ uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr,
483+ float64, float64, float64, float64, float64, float64, float64, float64,
484+ float64, float64, float64, float64, float64, float64, float64, float64,
485+ ) float64
486+ purego.RegisterLibFunc(&fn, lib, "stack_32_mixed_int_float")
487+ got := fn(
488+ 1, 2, 3, 4, 5, 6, 7, 8,
489+ 9, 10, 11, 12, 13, 14, 15, 16,
490+ 1, 2, 3, 4, 5, 6, 7, 8,
491+ 9, 10, 11, 12, 13, 14, 15, 16,
492+ )
493+ const want = 5168.0
494+ if got != want {
495+ t.Fatalf("stack_32_mixed_int_float: got %f, want %f", got, want)
415496 }
416497 })
498+}
417499
418- // Test that 35 int64 arguments (27 slots needed) exceeds the limit
419- t.Run("35_int64_exceeds_limit", func(t *testing.T) {
500+func TestABI_TooManyArguments(t *testing.T) {
501+ mustPanic := func(t *testing.T, want string, f func()) {
502+ t.Helper()
420503 defer func() {
421- if r := recover(); r != nil {
422- t.Logf("Got expected panic: %v", r)
423- } else {
424- t.Errorf("Expected panic but didn't get one")
504+ r := recover()
505+ if r == nil {
506+ t.Fatalf("expected panic %q, got none", want)
507+ }
508+ got := fmt.Sprint(r)
509+ if got != want {
510+ t.Fatalf("panic mismatch:\n got: %q\n want: %q", got, want)
425511 }
426512 }()
513+ f()
514+ }
515+
516+ // 33 int64 parameters exceeds maxArgs=32.
517+ t.Run("registerfunc_33_int64_exceeds_limit", func(t *testing.T) {
518+ mustPanic(t, "purego: too many stack arguments", func() {
519+ var fn func(
520+ int64, int64, int64, int64, int64, int64, int64, int64,
521+ int64, int64, int64, int64, int64, int64, int64, int64,
522+ int64, int64, int64, int64, int64, int64, int64, int64,
523+ int64, int64, int64, int64, int64, int64, int64, int64,
524+ int64,
525+ )
526+ purego.RegisterFunc(&fn, 1)
527+ })
528+ })
427529
428- var fn func(*byte, uintptr, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64)
429- purego.RegisterLibFunc(&fn, lib, "stack_35_int64_exceeds")
530+ t.Run("registerfunc_16_int64_exceeds_ppc64le_limit", func(t *testing.T) {
531+ if runtime.GOARCH != "ppc64le" {
532+ t.Skip("ppc64le retains the 15-argument limit")
533+ }
534+ mustPanic(t, "purego: too many stack arguments", func() {
535+ var fn func(
536+ int64, int64, int64, int64, int64, int64, int64, int64,
537+ int64, int64, int64, int64, int64, int64, int64, int64,
538+ )
539+ purego.RegisterFunc(&fn, 1)
540+ })
541+ })
542+
543+ t.Run("syscalln_33_uintptr_exceeds_limit", func(t *testing.T) {
544+ mustPanic(t, "purego: too many arguments to SyscallN", func() {
545+ purego.SyscallN(1,
546+ 1, 2, 3, 4, 5, 6, 7, 8,
547+ 9, 10, 11, 12, 13, 14, 15, 16,
548+ 17, 18, 19, 20, 21, 22, 23, 24,
549+ 25, 26, 27, 28, 29, 30, 31, 32,
550+ 33,
551+ )
552+ })
553+ })
554+
555+ t.Run("syscalln_16_uintptr_exceeds_ppc64le_limit", func(t *testing.T) {
556+ if runtime.GOARCH != "ppc64le" {
557+ t.Skip("ppc64le retains the 15-argument limit")
558+ }
559+ mustPanic(t, "purego: too many arguments to SyscallN", func() {
560+ purego.SyscallN(1,
561+ 1, 2, 3, 4, 5, 6, 7, 8,
562+ 9, 10, 11, 12, 13, 14, 15, 16,
563+ )
564+ })
430565 })
431566 }
432567
@@ -373,8 +373,8 @@ func TestABI_ArgumentPassing(t *testing.T) {
373 373
374 for _, tt := range tests {374 for _, tt := range tests {
375 t.Run(tt.name, func(t *testing.T) {375 t.Run(tt.name, func(t *testing.T) {
376- if tt.name == "20_int32" && (runtime.GOOS != "darwin" || runtime.GOARCH != "arm64") {376+ if tt.name == "20_int32" && runtime.GOARCH == "ppc64le" {
377- t.Skip("20 int32 arguments only supported on Darwin ARM64 with smart stack checking")377+ t.Skip("ppc64le retains the 15-argument limit")
378 }378 }
379 if tt.name == "10_float32" && (runtime.GOARCH == "loong64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "riscv64" || runtime.GOARCH == "s390x") {379 if tt.name == "10_float32" && (runtime.GOARCH == "loong64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "riscv64" || runtime.GOARCH == "s390x") {
380 t.Skip("float32 stack arguments not yet supported on this platform")380 t.Skip("float32 stack arguments not yet supported on this platform")
@@ -394,39 +394,174 @@ func TestABI_ArgumentPassing(t *testing.T) {
394 }394 }
395 })395 })
396 }396 }
397-}
398 397
399-func TestABI_TooManyArguments(t *testing.T) {398+ t.Run("20_uintptr", func(t *testing.T) {
400- if runtime.GOOS != "darwin" || runtime.GOARCH != "arm64" {399+ if runtime.GOARCH == "ppc64le" {
401- t.Skip("This test is specific to Darwin ARM64")400+ t.Skip("ppc64le retains the 15-argument limit")
402- }401+ }
402+ var fn func(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) uintptr
403+ purego.RegisterLibFunc(&fn, lib, "stack_20_uintptr")
404+ got := fn(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)
405+ const want = uintptr(210)
406+ if got != want {
407+ t.Fatalf("stack_20_uintptr: got %d, want %d", got, want)
408+ }
409+ })
403 410
404- libFileName := filepath.Join(t.TempDir(), "abitest.so")411+ t.Run("32_uintptr", func(t *testing.T) {
405- if err := buildSharedLib("CC", libFileName, filepath.Join("testdata", "abitest", "abi_test.c")); err != nil {412+ if runtime.GOARCH == "ppc64le" {
406- t.Fatal(err)413+ t.Skip("ppc64le retains the 15-argument limit")
407- }414+ }
408- lib, err := load.OpenLibrary(libFileName)415+ var fn func(
409- if err != nil {416+ uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr,
410- t.Fatalf("Failed to open library %q: %v", libFileName, err)417+ uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr,
411- }418+ uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr,
412- t.Cleanup(func() {419+ uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr,
413- if err := load.CloseLibrary(lib); err != nil {420+ ) uintptr
414- t.Errorf("Failed to close library: %v", err)421+ purego.RegisterLibFunc(&fn, lib, "stack_32_uintptr")
422+ got := fn(
423+ 1, 2, 3, 4, 5, 6, 7, 8,
424+ 9, 10, 11, 12, 13, 14, 15, 16,
425+ 17, 18, 19, 20, 21, 22, 23, 24,
426+ 25, 26, 27, 28, 29, 30, 31, 32,
427+ )
428+ const want = uintptr(528)
429+ if got != want {
430+ t.Fatalf("stack_32_uintptr: got %d, want %d", got, want)
431+ }
432+ })
433+
434+ t.Run("syscalln_20_uintptr", func(t *testing.T) {
435+ if runtime.GOARCH == "ppc64le" {
436+ t.Skip("ppc64le retains the 15-argument limit")
437+ }
438+ fn, err := load.OpenSymbol(lib, "stack_20_uintptr")
439+ if err != nil {
440+ t.Fatalf("OpenSymbol(stack_20_uintptr) failed: %v", err)
441+ }
442+ got, _, _ := purego.SyscallN(fn,
443+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
444+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
445+ )
446+ const want = uintptr(210)
447+ if got != want {
448+ t.Fatalf("stack_20_uintptr SyscallN: got %d, want %d", got, want)
449+ }
450+ })
451+
452+ t.Run("syscalln_32_uintptr", func(t *testing.T) {
453+ if runtime.GOARCH == "ppc64le" {
454+ t.Skip("ppc64le retains the 15-argument limit")
455+ }
456+ fn, err := load.OpenSymbol(lib, "stack_32_uintptr")
457+ if err != nil {
458+ t.Fatalf("OpenSymbol(stack_32_uintptr) failed: %v", err)
459+ }
460+ got, _, _ := purego.SyscallN(fn,
461+ 1, 2, 3, 4, 5, 6, 7, 8,
462+ 9, 10, 11, 12, 13, 14, 15, 16,
463+ 17, 18, 19, 20, 21, 22, 23, 24,
464+ 25, 26, 27, 28, 29, 30, 31, 32,
465+ )
466+ const want = uintptr(528)
467+ if got != want {
468+ t.Fatalf("stack_32_uintptr SyscallN: got %d, want %d", got, want)
469+ }
470+ })
471+
472+ t.Run("32_mixed_int_float", func(t *testing.T) {
473+ if unsafe.Sizeof(uintptr(0)) == 4 {
474+ t.Skip("requires 64-bit uintptr slots")
475+ }
476+ if runtime.GOARCH == "ppc64le" {
477+ t.Skip("mixed int/float stack arguments are not yet supported on ppc64le")
478+ }
479+
480+ var fn func(
481+ uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr,
482+ uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr,
483+ float64, float64, float64, float64, float64, float64, float64, float64,
484+ float64, float64, float64, float64, float64, float64, float64, float64,
485+ ) float64
486+ purego.RegisterLibFunc(&fn, lib, "stack_32_mixed_int_float")
487+ got := fn(
488+ 1, 2, 3, 4, 5, 6, 7, 8,
489+ 9, 10, 11, 12, 13, 14, 15, 16,
490+ 1, 2, 3, 4, 5, 6, 7, 8,
491+ 9, 10, 11, 12, 13, 14, 15, 16,
492+ )
493+ const want = 5168.0
494+ if got != want {
495+ t.Fatalf("stack_32_mixed_int_float: got %f, want %f", got, want)
415 }496 }
416 })497 })
498+}
417 499
418- // Test that 35 int64 arguments (27 slots needed) exceeds the limit500+func TestABI_TooManyArguments(t *testing.T) {
419- t.Run("35_int64_exceeds_limit", func(t *testing.T) {501+ mustPanic := func(t *testing.T, want string, f func()) {
502+ t.Helper()
420 defer func() {503 defer func() {
421- if r := recover(); r != nil {504+ r := recover()
422- t.Logf("Got expected panic: %v", r)505+ if r == nil {
423- } else {506+ t.Fatalf("expected panic %q, got none", want)
424- t.Errorf("Expected panic but didn't get one")507+ }
508+ got := fmt.Sprint(r)
509+ if got != want {
510+ t.Fatalf("panic mismatch:\n got: %q\n want: %q", got, want)
425 }511 }
426 }()512 }()
513+ f()
514+ }
515+
516+ // 33 int64 parameters exceeds maxArgs=32.
517+ t.Run("registerfunc_33_int64_exceeds_limit", func(t *testing.T) {
518+ mustPanic(t, "purego: too many stack arguments", func() {
519+ var fn func(
520+ int64, int64, int64, int64, int64, int64, int64, int64,
521+ int64, int64, int64, int64, int64, int64, int64, int64,
522+ int64, int64, int64, int64, int64, int64, int64, int64,
523+ int64, int64, int64, int64, int64, int64, int64, int64,
524+ int64,
525+ )
526+ purego.RegisterFunc(&fn, 1)
527+ })
528+ })
427 529
428- var fn func(*byte, uintptr, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64, int64)530+ t.Run("registerfunc_16_int64_exceeds_ppc64le_limit", func(t *testing.T) {
429- purego.RegisterLibFunc(&fn, lib, "stack_35_int64_exceeds")531+ if runtime.GOARCH != "ppc64le" {
532+ t.Skip("ppc64le retains the 15-argument limit")
533+ }
534+ mustPanic(t, "purego: too many stack arguments", func() {
535+ var fn func(
536+ int64, int64, int64, int64, int64, int64, int64, int64,
537+ int64, int64, int64, int64, int64, int64, int64, int64,
538+ )
539+ purego.RegisterFunc(&fn, 1)
540+ })
541+ })
542+
543+ t.Run("syscalln_33_uintptr_exceeds_limit", func(t *testing.T) {
544+ mustPanic(t, "purego: too many arguments to SyscallN", func() {
545+ purego.SyscallN(1,
546+ 1, 2, 3, 4, 5, 6, 7, 8,
547+ 9, 10, 11, 12, 13, 14, 15, 16,
548+ 17, 18, 19, 20, 21, 22, 23, 24,
549+ 25, 26, 27, 28, 29, 30, 31, 32,
550+ 33,
551+ )
552+ })
553+ })
554+
555+ t.Run("syscalln_16_uintptr_exceeds_ppc64le_limit", func(t *testing.T) {
556+ if runtime.GOARCH != "ppc64le" {
557+ t.Skip("ppc64le retains the 15-argument limit")
558+ }
559+ mustPanic(t, "purego: too many arguments to SyscallN", func() {
560+ purego.SyscallN(1,
561+ 1, 2, 3, 4, 5, 6, 7, 8,
562+ 9, 10, 11, 12, 13, 14, 15, 16,
563+ )
564+ })
430 })565 })
431 }566 }
432 567
M internal/cgo/syscall_cgo_unix.go +16 -22
@@ -16,40 +16,34 @@ package cgo
1616 #include <errno.h>
1717 #include <assert.h>
1818
19-typedef struct syscall15Args {
19+typedef struct syscallArgs {
2020 uintptr_t fn;
2121 uintptr_t a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15;
22+ uintptr_t a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32;
2223 uintptr_t f1, f2, f3, f4, f5, f6, f7, f8;
23- uintptr_t err;
24-} syscall15Args;
24+ uintptr_t arm64_r8;
25+} syscallArgs;
2526
26-void syscall15(struct syscall15Args *args) {
27+void syscall15(struct syscallArgs *args) {
2728 assert((args->f1|args->f2|args->f3|args->f4|args->f5|args->f6|args->f7|args->f8) == 0);
2829 uintptr_t (*func_name)(uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6,
2930 uintptr_t a7, uintptr_t a8, uintptr_t a9, uintptr_t a10, uintptr_t a11, uintptr_t a12,
30- uintptr_t a13, uintptr_t a14, uintptr_t a15);
31+ uintptr_t a13, uintptr_t a14, uintptr_t a15, uintptr_t a16, uintptr_t a17, uintptr_t a18,
32+ uintptr_t a19, uintptr_t a20, uintptr_t a21, uintptr_t a22, uintptr_t a23, uintptr_t a24,
33+ uintptr_t a25, uintptr_t a26, uintptr_t a27, uintptr_t a28, uintptr_t a29, uintptr_t a30,
34+ uintptr_t a31, uintptr_t a32);
3135 *(void**)(&func_name) = (void*)(args->fn);
32- uintptr_t r1 = func_name(args->a1,args->a2,args->a3,args->a4,args->a5,args->a6,args->a7,args->a8,args->a9,
33- args->a10,args->a11,args->a12,args->a13,args->a14,args->a15);
36+ uintptr_t r1 = func_name(args->a1,args->a2,args->a3,args->a4,args->a5,args->a6,args->a7,args->a8,args->a9,
37+ args->a10,args->a11,args->a12,args->a13,args->a14,args->a15,args->a16,args->a17,args->a18,
38+ args->a19,args->a20,args->a21,args->a22,args->a23,args->a24,args->a25,args->a26,args->a27,
39+ args->a28,args->a29,args->a30,args->a31,args->a32);
3440 args->a1 = r1;
35- args->err = errno;
41+ args->a3 = errno;
3642 }
3743
3844 */
3945 import "C"
4046 import "unsafe"
4147
42-// assign purego.syscall15XABI0 to the C version of this function.
43-var Syscall15XABI0 = unsafe.Pointer(C.syscall15)
44-
45-//go:nosplit
46-func Syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2, err uintptr) {
47- args := C.syscall15Args{
48- C.uintptr_t(fn), C.uintptr_t(a1), C.uintptr_t(a2), C.uintptr_t(a3),
49- C.uintptr_t(a4), C.uintptr_t(a5), C.uintptr_t(a6),
50- C.uintptr_t(a7), C.uintptr_t(a8), C.uintptr_t(a9), C.uintptr_t(a10), C.uintptr_t(a11), C.uintptr_t(a12),
51- C.uintptr_t(a13), C.uintptr_t(a14), C.uintptr_t(a15), 0, 0, 0, 0, 0, 0, 0, 0, 0,
52- }
53- C.syscall15(&args)
54- return uintptr(args.a1), 0, uintptr(args.err)
55-}
48+// assign purego.syscallXABI0 to the C version of this function.
49+var SyscallXABI0 = unsafe.Pointer(C.syscall15)
@@ -16,40 +16,34 @@ package cgo
16 #include <errno.h>16 #include <errno.h>
17 #include <assert.h>17 #include <assert.h>
18 18
19-typedef struct syscall15Args {19+typedef struct syscallArgs {
20 uintptr_t fn;20 uintptr_t fn;
21 uintptr_t a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15;21 uintptr_t a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15;
22+ uintptr_t a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32;
22 uintptr_t f1, f2, f3, f4, f5, f6, f7, f8;23 uintptr_t f1, f2, f3, f4, f5, f6, f7, f8;
23- uintptr_t err;24+ uintptr_t arm64_r8;
24-} syscall15Args;25+} syscallArgs;
25 26
26-void syscall15(struct syscall15Args *args) {27+void syscall15(struct syscallArgs *args) {
27 assert((args->f1|args->f2|args->f3|args->f4|args->f5|args->f6|args->f7|args->f8) == 0);28 assert((args->f1|args->f2|args->f3|args->f4|args->f5|args->f6|args->f7|args->f8) == 0);
28 uintptr_t (*func_name)(uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6,29 uintptr_t (*func_name)(uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6,
29 uintptr_t a7, uintptr_t a8, uintptr_t a9, uintptr_t a10, uintptr_t a11, uintptr_t a12,30 uintptr_t a7, uintptr_t a8, uintptr_t a9, uintptr_t a10, uintptr_t a11, uintptr_t a12,
30- uintptr_t a13, uintptr_t a14, uintptr_t a15);31+ uintptr_t a13, uintptr_t a14, uintptr_t a15, uintptr_t a16, uintptr_t a17, uintptr_t a18,
32+ uintptr_t a19, uintptr_t a20, uintptr_t a21, uintptr_t a22, uintptr_t a23, uintptr_t a24,
33+ uintptr_t a25, uintptr_t a26, uintptr_t a27, uintptr_t a28, uintptr_t a29, uintptr_t a30,
34+ uintptr_t a31, uintptr_t a32);
31 *(void**)(&func_name) = (void*)(args->fn);35 *(void**)(&func_name) = (void*)(args->fn);
32- uintptr_t r1 = func_name(args->a1,args->a2,args->a3,args->a4,args->a5,args->a6,args->a7,args->a8,args->a9,36+ uintptr_t r1 = func_name(args->a1,args->a2,args->a3,args->a4,args->a5,args->a6,args->a7,args->a8,args->a9,
33- args->a10,args->a11,args->a12,args->a13,args->a14,args->a15);37+ args->a10,args->a11,args->a12,args->a13,args->a14,args->a15,args->a16,args->a17,args->a18,
38+ args->a19,args->a20,args->a21,args->a22,args->a23,args->a24,args->a25,args->a26,args->a27,
39+ args->a28,args->a29,args->a30,args->a31,args->a32);
34 args->a1 = r1;40 args->a1 = r1;
35- args->err = errno;41+ args->a3 = errno;
36 }42 }
37 43
38 */44 */
39 import "C"45 import "C"
40 import "unsafe"46 import "unsafe"
41 47
42-// assign purego.syscall15XABI0 to the C version of this function.48+// assign purego.syscallXABI0 to the C version of this function.
43-var Syscall15XABI0 = unsafe.Pointer(C.syscall15)49+var SyscallXABI0 = unsafe.Pointer(C.syscall15)
44-
45-//go:nosplit
46-func Syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2, err uintptr) {
47- args := C.syscall15Args{
48- C.uintptr_t(fn), C.uintptr_t(a1), C.uintptr_t(a2), C.uintptr_t(a3),
49- C.uintptr_t(a4), C.uintptr_t(a5), C.uintptr_t(a6),
50- C.uintptr_t(a7), C.uintptr_t(a8), C.uintptr_t(a9), C.uintptr_t(a10), C.uintptr_t(a11), C.uintptr_t(a12),
51- C.uintptr_t(a13), C.uintptr_t(a14), C.uintptr_t(a15), 0, 0, 0, 0, 0, 0, 0, 0, 0,
52- }
53- C.syscall15(&args)
54- return uintptr(args.a1), 0, uintptr(args.err)
55-}
M struct_386.go +1 -1
@@ -12,7 +12,7 @@ func addStruct(v reflect.Value, numInts, numFloats, numStack *int, addInt, addFl
1212 panic("purego: struct arguments are not supported")
1313 }
1414
15-func getStruct(outType reflect.Type, syscall syscall15Args) (v reflect.Value) {
15+func getStruct(outType reflect.Type, syscall syscallArgs) (v reflect.Value) {
1616 panic("purego: struct returns are not supported")
1717 }
1818
@@ -12,7 +12,7 @@ func addStruct(v reflect.Value, numInts, numFloats, numStack *int, addInt, addFl
12 panic("purego: struct arguments are not supported")12 panic("purego: struct arguments are not supported")
13 }13 }
14 14
15-func getStruct(outType reflect.Type, syscall syscall15Args) (v reflect.Value) {15+func getStruct(outType reflect.Type, syscall syscallArgs) (v reflect.Value) {
16 panic("purego: struct returns are not supported")16 panic("purego: struct returns are not supported")
17 }17 }
18 18
M struct_amd64.go +1 -1
@@ -10,7 +10,7 @@ import (
1010 "unsafe"
1111 )
1212
13-func getStruct(outType reflect.Type, syscall syscall15Args) (v reflect.Value) {
13+func getStruct(outType reflect.Type, syscall syscallArgs) (v reflect.Value) {
1414 outSize := outType.Size()
1515 switch {
1616 case outSize == 0:
@@ -10,7 +10,7 @@ import (
10 "unsafe"10 "unsafe"
11 )11 )
12 12
13-func getStruct(outType reflect.Type, syscall syscall15Args) (v reflect.Value) {13+func getStruct(outType reflect.Type, syscall syscallArgs) (v reflect.Value) {
14 outSize := outType.Size()14 outSize := outType.Size()
15 switch {15 switch {
16 case outSize == 0:16 case outSize == 0:
M struct_arm.go +1 -1
@@ -28,7 +28,7 @@ func addStruct(v reflect.Value, numInts, numFloats, numStack *int, addInt, addFl
2828 return keepAlive
2929 }
3030
31-func getStruct(outType reflect.Type, syscall syscall15Args) (v reflect.Value) {
31+func getStruct(outType reflect.Type, syscall syscallArgs) (v reflect.Value) {
3232 outSize := outType.Size()
3333 if outSize == 0 {
3434 return reflect.New(outType).Elem()
@@ -28,7 +28,7 @@ func addStruct(v reflect.Value, numInts, numFloats, numStack *int, addInt, addFl
28 return keepAlive28 return keepAlive
29 }29 }
30 30
31-func getStruct(outType reflect.Type, syscall syscall15Args) (v reflect.Value) {31+func getStruct(outType reflect.Type, syscall syscallArgs) (v reflect.Value) {
32 outSize := outType.Size()32 outSize := outType.Size()
33 if outSize == 0 {33 if outSize == 0 {
34 return reflect.New(outType).Elem()34 return reflect.New(outType).Elem()
M struct_arm64.go +1 -1
@@ -14,7 +14,7 @@ import (
1414 "github.com/ebitengine/purego/internal/strings"
1515 )
1616
17-func getStruct(outType reflect.Type, syscall syscall15Args) (v reflect.Value) {
17+func getStruct(outType reflect.Type, syscall syscallArgs) (v reflect.Value) {
1818 outSize := outType.Size()
1919 switch {
2020 case outSize == 0:
@@ -14,7 +14,7 @@ import (
14 "github.com/ebitengine/purego/internal/strings"14 "github.com/ebitengine/purego/internal/strings"
15 )15 )
16 16
17-func getStruct(outType reflect.Type, syscall syscall15Args) (v reflect.Value) {17+func getStruct(outType reflect.Type, syscall syscallArgs) (v reflect.Value) {
18 outSize := outType.Size()18 outSize := outType.Size()
19 switch {19 switch {
20 case outSize == 0:20 case outSize == 0:
M struct_loong64.go +1 -1
@@ -9,7 +9,7 @@ import (
99 "unsafe"
1010 )
1111
12-func getStruct(outType reflect.Type, syscall syscall15Args) (v reflect.Value) {
12+func getStruct(outType reflect.Type, syscall syscallArgs) (v reflect.Value) {
1313 outSize := outType.Size()
1414 switch {
1515 case outSize == 0:
@@ -9,7 +9,7 @@ import (
9 "unsafe"9 "unsafe"
10 )10 )
11 11
12-func getStruct(outType reflect.Type, syscall syscall15Args) (v reflect.Value) {12+func getStruct(outType reflect.Type, syscall syscallArgs) (v reflect.Value) {
13 outSize := outType.Size()13 outSize := outType.Size()
14 switch {14 switch {
15 case outSize == 0:15 case outSize == 0:
M struct_ppc64le.go +1 -1
@@ -8,7 +8,7 @@ import (
88 "unsafe"
99 )
1010
11-func getStruct(outType reflect.Type, syscall syscall15Args) reflect.Value {
11+func getStruct(outType reflect.Type, syscall syscallArgs) reflect.Value {
1212 outSize := outType.Size()
1313
1414 switch {
@@ -8,7 +8,7 @@ import (
8 "unsafe"8 "unsafe"
9 )9 )
10 10
11-func getStruct(outType reflect.Type, syscall syscall15Args) reflect.Value {11+func getStruct(outType reflect.Type, syscall syscallArgs) reflect.Value {
12 outSize := outType.Size()12 outSize := outType.Size()
13 13
14 switch {14 switch {
M struct_riscv64.go +1 -1
@@ -8,7 +8,7 @@ import (
88 "unsafe"
99 )
1010
11-func getStruct(outType reflect.Type, syscall syscall15Args) reflect.Value {
11+func getStruct(outType reflect.Type, syscall syscallArgs) reflect.Value {
1212 outSize := outType.Size()
1313
1414 switch {
@@ -8,7 +8,7 @@ import (
8 "unsafe"8 "unsafe"
9 )9 )
10 10
11-func getStruct(outType reflect.Type, syscall syscall15Args) reflect.Value {11+func getStruct(outType reflect.Type, syscall syscallArgs) reflect.Value {
12 outSize := outType.Size()12 outSize := outType.Size()
13 13
14 switch {14 switch {
M struct_s390x.go +1 -1
@@ -8,7 +8,7 @@ import (
88 "unsafe"
99 )
1010
11-func getStruct(outType reflect.Type, syscall syscall15Args) reflect.Value {
11+func getStruct(outType reflect.Type, syscall syscallArgs) reflect.Value {
1212 outSize := outType.Size()
1313
1414 switch {
@@ -8,7 +8,7 @@ import (
8 "unsafe"8 "unsafe"
9 )9 )
10 10
11-func getStruct(outType reflect.Type, syscall syscall15Args) reflect.Value {11+func getStruct(outType reflect.Type, syscall syscallArgs) reflect.Value {
12 outSize := outType.Size()12 outSize := outType.Size()
13 13
14 switch {14 switch {
M sys_386.s +43 -43
@@ -10,8 +10,8 @@
1010 #define STACK_SIZE 160
1111 #define PTR_ADDRESS (STACK_SIZE - 4)
1212
13-// syscall15X calls a function in libc on behalf of the syscall package.
14-// syscall15X takes a pointer to a struct like:
13+// syscallX calls a function in libc on behalf of the syscall package.
14+// syscallX takes a pointer to a struct like:
1515 // struct {
1616 // fn uintptr
1717 // a1 uintptr
@@ -22,18 +22,18 @@
2222 // f16 uintptr
2323 // arm64_r8 uintptr
2424 // }
25-// syscall15X must be called on the g0 stack with the
25+// syscallX must be called on the g0 stack with the
2626 // C calling convention (use libcCall).
2727 //
2828 // On i386 System V ABI, all arguments are passed on the stack.
2929 // Return value is in EAX (and EDX for 64-bit values).
30-GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $4
31-DATA ·syscall15XABI0(SB)/4, $syscall15X(SB)
32-TEXT syscall15X(SB), NOSPLIT|NOFRAME, $0-0
30+GLOBL ·syscallXABI0(SB), NOPTR|RODATA, $4
31+DATA ·syscallXABI0(SB)/4, $syscallX(SB)
32+TEXT syscallX(SB), NOSPLIT|NOFRAME, $0-0
3333 // Called via C calling convention: argument pointer at 4(SP)
3434 // NOT via Go calling convention
3535 // On i386, the first argument is at 4(SP) after CALL pushes return address
36- MOVL 4(SP), AX // get pointer to syscall15Args
36+ MOVL 4(SP), AX // get pointer to syscallArgs
3737
3838 // Save callee-saved registers
3939 PUSHL BP
@@ -50,75 +50,75 @@ TEXT syscall15X(SB), NOSPLIT|NOFRAME, $0-0
5050 MOVL BX, PTR_ADDRESS(SP) // save args pointer
5151
5252 // Load function pointer
53- MOVL syscall15Args_fn(BX), AX
53+ MOVL syscallArgs_fn(BX), AX
5454 MOVL AX, (PTR_ADDRESS-4)(SP) // save fn pointer
5555
5656 // Push all integer arguments onto the stack (a1-a32)
5757 // i386 SysV ABI: arguments pushed right-to-left, but we're
5858 // setting up the stack from low to high addresses
59- MOVL syscall15Args_a1(BX), AX
59+ MOVL syscallArgs_a1(BX), AX
6060 MOVL AX, 0(SP)
61- MOVL syscall15Args_a2(BX), AX
61+ MOVL syscallArgs_a2(BX), AX
6262 MOVL AX, 4(SP)
63- MOVL syscall15Args_a3(BX), AX
63+ MOVL syscallArgs_a3(BX), AX
6464 MOVL AX, 8(SP)
65- MOVL syscall15Args_a4(BX), AX
65+ MOVL syscallArgs_a4(BX), AX
6666 MOVL AX, 12(SP)
67- MOVL syscall15Args_a5(BX), AX
67+ MOVL syscallArgs_a5(BX), AX
6868 MOVL AX, 16(SP)
69- MOVL syscall15Args_a6(BX), AX
69+ MOVL syscallArgs_a6(BX), AX
7070 MOVL AX, 20(SP)
71- MOVL syscall15Args_a7(BX), AX
71+ MOVL syscallArgs_a7(BX), AX
7272 MOVL AX, 24(SP)
73- MOVL syscall15Args_a8(BX), AX
73+ MOVL syscallArgs_a8(BX), AX
7474 MOVL AX, 28(SP)
75- MOVL syscall15Args_a9(BX), AX
75+ MOVL syscallArgs_a9(BX), AX
7676 MOVL AX, 32(SP)
77- MOVL syscall15Args_a10(BX), AX
77+ MOVL syscallArgs_a10(BX), AX
7878 MOVL AX, 36(SP)
79- MOVL syscall15Args_a11(BX), AX
79+ MOVL syscallArgs_a11(BX), AX
8080 MOVL AX, 40(SP)
81- MOVL syscall15Args_a12(BX), AX
81+ MOVL syscallArgs_a12(BX), AX
8282 MOVL AX, 44(SP)
83- MOVL syscall15Args_a13(BX), AX
83+ MOVL syscallArgs_a13(BX), AX
8484 MOVL AX, 48(SP)
85- MOVL syscall15Args_a14(BX), AX
85+ MOVL syscallArgs_a14(BX), AX
8686 MOVL AX, 52(SP)
87- MOVL syscall15Args_a15(BX), AX
87+ MOVL syscallArgs_a15(BX), AX
8888 MOVL AX, 56(SP)
89- MOVL syscall15Args_a16(BX), AX
89+ MOVL syscallArgs_a16(BX), AX
9090 MOVL AX, 60(SP)
91- MOVL syscall15Args_a17(BX), AX
91+ MOVL syscallArgs_a17(BX), AX
9292 MOVL AX, 64(SP)
93- MOVL syscall15Args_a18(BX), AX
93+ MOVL syscallArgs_a18(BX), AX
9494 MOVL AX, 68(SP)
95- MOVL syscall15Args_a19(BX), AX
95+ MOVL syscallArgs_a19(BX), AX
9696 MOVL AX, 72(SP)
97- MOVL syscall15Args_a20(BX), AX
97+ MOVL syscallArgs_a20(BX), AX
9898 MOVL AX, 76(SP)
99- MOVL syscall15Args_a21(BX), AX
99+ MOVL syscallArgs_a21(BX), AX
100100 MOVL AX, 80(SP)
101- MOVL syscall15Args_a22(BX), AX
101+ MOVL syscallArgs_a22(BX), AX
102102 MOVL AX, 84(SP)
103- MOVL syscall15Args_a23(BX), AX
103+ MOVL syscallArgs_a23(BX), AX
104104 MOVL AX, 88(SP)
105- MOVL syscall15Args_a24(BX), AX
105+ MOVL syscallArgs_a24(BX), AX
106106 MOVL AX, 92(SP)
107- MOVL syscall15Args_a25(BX), AX
107+ MOVL syscallArgs_a25(BX), AX
108108 MOVL AX, 96(SP)
109- MOVL syscall15Args_a26(BX), AX
109+ MOVL syscallArgs_a26(BX), AX
110110 MOVL AX, 100(SP)
111- MOVL syscall15Args_a27(BX), AX
111+ MOVL syscallArgs_a27(BX), AX
112112 MOVL AX, 104(SP)
113- MOVL syscall15Args_a28(BX), AX
113+ MOVL syscallArgs_a28(BX), AX
114114 MOVL AX, 108(SP)
115- MOVL syscall15Args_a29(BX), AX
115+ MOVL syscallArgs_a29(BX), AX
116116 MOVL AX, 112(SP)
117- MOVL syscall15Args_a30(BX), AX
117+ MOVL syscallArgs_a30(BX), AX
118118 MOVL AX, 116(SP)
119- MOVL syscall15Args_a31(BX), AX
119+ MOVL syscallArgs_a31(BX), AX
120120 MOVL AX, 120(SP)
121- MOVL syscall15Args_a32(BX), AX
121+ MOVL syscallArgs_a32(BX), AX
122122 MOVL AX, 124(SP)
123123
124124 // Call the C function
@@ -127,13 +127,13 @@ TEXT syscall15X(SB), NOSPLIT|NOFRAME, $0-0
127127
128128 // Get args pointer back and save results
129129 MOVL PTR_ADDRESS(SP), BX
130- MOVL AX, syscall15Args_a1(BX) // return value r1
131- MOVL DX, syscall15Args_a2(BX) // return value r2 (for 64-bit returns)
130+ MOVL AX, syscallArgs_a1(BX) // return value r1
131+ MOVL DX, syscallArgs_a2(BX) // return value r2 (for 64-bit returns)
132132
133133 // Save x87 FPU return value (ST0) to f1 field
134134 // On i386 System V ABI, float/double returns are in ST(0)
135135 // We save as float64 (8 bytes) to preserve precision
136- FMOVDP F0, syscall15Args_f1(BX)
136+ FMOVDP F0, syscallArgs_f1(BX)
137137
138138 // Clean up stack
139139 ADDL $STACK_SIZE, SP
@@ -10,8 +10,8 @@
10 #define STACK_SIZE 16010 #define STACK_SIZE 160
11 #define PTR_ADDRESS (STACK_SIZE - 4)11 #define PTR_ADDRESS (STACK_SIZE - 4)
12 12
13-// syscall15X calls a function in libc on behalf of the syscall package.13+// syscallX calls a function in libc on behalf of the syscall package.
14-// syscall15X takes a pointer to a struct like:14+// syscallX takes a pointer to a struct like:
15 // struct {15 // struct {
16 // fn uintptr16 // fn uintptr
17 // a1 uintptr17 // a1 uintptr
@@ -22,18 +22,18 @@
22 // f16 uintptr22 // f16 uintptr
23 // arm64_r8 uintptr23 // arm64_r8 uintptr
24 // }24 // }
25-// syscall15X must be called on the g0 stack with the25+// syscallX must be called on the g0 stack with the
26 // C calling convention (use libcCall).26 // C calling convention (use libcCall).
27 //27 //
28 // On i386 System V ABI, all arguments are passed on the stack.28 // On i386 System V ABI, all arguments are passed on the stack.
29 // Return value is in EAX (and EDX for 64-bit values).29 // Return value is in EAX (and EDX for 64-bit values).
30-GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $430+GLOBL ·syscallXABI0(SB), NOPTR|RODATA, $4
31-DATA ·syscall15XABI0(SB)/4, $syscall15X(SB)31+DATA ·syscallXABI0(SB)/4, $syscallX(SB)
32-TEXT syscall15X(SB), NOSPLIT|NOFRAME, $0-032+TEXT syscallX(SB), NOSPLIT|NOFRAME, $0-0
33 // Called via C calling convention: argument pointer at 4(SP)33 // Called via C calling convention: argument pointer at 4(SP)
34 // NOT via Go calling convention34 // NOT via Go calling convention
35 // On i386, the first argument is at 4(SP) after CALL pushes return address35 // On i386, the first argument is at 4(SP) after CALL pushes return address
36- MOVL 4(SP), AX // get pointer to syscall15Args36+ MOVL 4(SP), AX // get pointer to syscallArgs
37 37
38 // Save callee-saved registers38 // Save callee-saved registers
39 PUSHL BP39 PUSHL BP
@@ -50,75 +50,75 @@ TEXT syscall15X(SB), NOSPLIT|NOFRAME, $0-0
50 MOVL BX, PTR_ADDRESS(SP) // save args pointer50 MOVL BX, PTR_ADDRESS(SP) // save args pointer
51 51
52 // Load function pointer52 // Load function pointer
53- MOVL syscall15Args_fn(BX), AX53+ MOVL syscallArgs_fn(BX), AX
54 MOVL AX, (PTR_ADDRESS-4)(SP) // save fn pointer54 MOVL AX, (PTR_ADDRESS-4)(SP) // save fn pointer
55 55
56 // Push all integer arguments onto the stack (a1-a32)56 // Push all integer arguments onto the stack (a1-a32)
57 // i386 SysV ABI: arguments pushed right-to-left, but we're57 // i386 SysV ABI: arguments pushed right-to-left, but we're
58 // setting up the stack from low to high addresses58 // setting up the stack from low to high addresses
59- MOVL syscall15Args_a1(BX), AX59+ MOVL syscallArgs_a1(BX), AX
60 MOVL AX, 0(SP)60 MOVL AX, 0(SP)
61- MOVL syscall15Args_a2(BX), AX61+ MOVL syscallArgs_a2(BX), AX
62 MOVL AX, 4(SP)62 MOVL AX, 4(SP)
63- MOVL syscall15Args_a3(BX), AX63+ MOVL syscallArgs_a3(BX), AX
64 MOVL AX, 8(SP)64 MOVL AX, 8(SP)
65- MOVL syscall15Args_a4(BX), AX65+ MOVL syscallArgs_a4(BX), AX
66 MOVL AX, 12(SP)66 MOVL AX, 12(SP)
67- MOVL syscall15Args_a5(BX), AX67+ MOVL syscallArgs_a5(BX), AX
68 MOVL AX, 16(SP)68 MOVL AX, 16(SP)
69- MOVL syscall15Args_a6(BX), AX69+ MOVL syscallArgs_a6(BX), AX
70 MOVL AX, 20(SP)70 MOVL AX, 20(SP)
71- MOVL syscall15Args_a7(BX), AX71+ MOVL syscallArgs_a7(BX), AX
72 MOVL AX, 24(SP)72 MOVL AX, 24(SP)
73- MOVL syscall15Args_a8(BX), AX73+ MOVL syscallArgs_a8(BX), AX
74 MOVL AX, 28(SP)74 MOVL AX, 28(SP)
75- MOVL syscall15Args_a9(BX), AX75+ MOVL syscallArgs_a9(BX), AX
76 MOVL AX, 32(SP)76 MOVL AX, 32(SP)
77- MOVL syscall15Args_a10(BX), AX77+ MOVL syscallArgs_a10(BX), AX
78 MOVL AX, 36(SP)78 MOVL AX, 36(SP)
79- MOVL syscall15Args_a11(BX), AX79+ MOVL syscallArgs_a11(BX), AX
80 MOVL AX, 40(SP)80 MOVL AX, 40(SP)
81- MOVL syscall15Args_a12(BX), AX81+ MOVL syscallArgs_a12(BX), AX
82 MOVL AX, 44(SP)82 MOVL AX, 44(SP)
83- MOVL syscall15Args_a13(BX), AX83+ MOVL syscallArgs_a13(BX), AX
84 MOVL AX, 48(SP)84 MOVL AX, 48(SP)
85- MOVL syscall15Args_a14(BX), AX85+ MOVL syscallArgs_a14(BX), AX
86 MOVL AX, 52(SP)86 MOVL AX, 52(SP)
87- MOVL syscall15Args_a15(BX), AX87+ MOVL syscallArgs_a15(BX), AX
88 MOVL AX, 56(SP)88 MOVL AX, 56(SP)
89- MOVL syscall15Args_a16(BX), AX89+ MOVL syscallArgs_a16(BX), AX
90 MOVL AX, 60(SP)90 MOVL AX, 60(SP)
91- MOVL syscall15Args_a17(BX), AX91+ MOVL syscallArgs_a17(BX), AX
92 MOVL AX, 64(SP)92 MOVL AX, 64(SP)
93- MOVL syscall15Args_a18(BX), AX93+ MOVL syscallArgs_a18(BX), AX
94 MOVL AX, 68(SP)94 MOVL AX, 68(SP)
95- MOVL syscall15Args_a19(BX), AX95+ MOVL syscallArgs_a19(BX), AX
96 MOVL AX, 72(SP)96 MOVL AX, 72(SP)
97- MOVL syscall15Args_a20(BX), AX97+ MOVL syscallArgs_a20(BX), AX
98 MOVL AX, 76(SP)98 MOVL AX, 76(SP)
99- MOVL syscall15Args_a21(BX), AX99+ MOVL syscallArgs_a21(BX), AX
100 MOVL AX, 80(SP)100 MOVL AX, 80(SP)
101- MOVL syscall15Args_a22(BX), AX101+ MOVL syscallArgs_a22(BX), AX
102 MOVL AX, 84(SP)102 MOVL AX, 84(SP)
103- MOVL syscall15Args_a23(BX), AX103+ MOVL syscallArgs_a23(BX), AX
104 MOVL AX, 88(SP)104 MOVL AX, 88(SP)
105- MOVL syscall15Args_a24(BX), AX105+ MOVL syscallArgs_a24(BX), AX
106 MOVL AX, 92(SP)106 MOVL AX, 92(SP)
107- MOVL syscall15Args_a25(BX), AX107+ MOVL syscallArgs_a25(BX), AX
108 MOVL AX, 96(SP)108 MOVL AX, 96(SP)
109- MOVL syscall15Args_a26(BX), AX109+ MOVL syscallArgs_a26(BX), AX
110 MOVL AX, 100(SP)110 MOVL AX, 100(SP)
111- MOVL syscall15Args_a27(BX), AX111+ MOVL syscallArgs_a27(BX), AX
112 MOVL AX, 104(SP)112 MOVL AX, 104(SP)
113- MOVL syscall15Args_a28(BX), AX113+ MOVL syscallArgs_a28(BX), AX
114 MOVL AX, 108(SP)114 MOVL AX, 108(SP)
115- MOVL syscall15Args_a29(BX), AX115+ MOVL syscallArgs_a29(BX), AX
116 MOVL AX, 112(SP)116 MOVL AX, 112(SP)
117- MOVL syscall15Args_a30(BX), AX117+ MOVL syscallArgs_a30(BX), AX
118 MOVL AX, 116(SP)118 MOVL AX, 116(SP)
119- MOVL syscall15Args_a31(BX), AX119+ MOVL syscallArgs_a31(BX), AX
120 MOVL AX, 120(SP)120 MOVL AX, 120(SP)
121- MOVL syscall15Args_a32(BX), AX121+ MOVL syscallArgs_a32(BX), AX
122 MOVL AX, 124(SP)122 MOVL AX, 124(SP)
123 123
124 // Call the C function124 // Call the C function
@@ -127,13 +127,13 @@ TEXT syscall15X(SB), NOSPLIT|NOFRAME, $0-0
127 127
128 // Get args pointer back and save results128 // Get args pointer back and save results
129 MOVL PTR_ADDRESS(SP), BX129 MOVL PTR_ADDRESS(SP), BX
130- MOVL AX, syscall15Args_a1(BX) // return value r1130+ MOVL AX, syscallArgs_a1(BX) // return value r1
131- MOVL DX, syscall15Args_a2(BX) // return value r2 (for 64-bit returns)131+ MOVL DX, syscallArgs_a2(BX) // return value r2 (for 64-bit returns)
132 132
133 // Save x87 FPU return value (ST0) to f1 field133 // Save x87 FPU return value (ST0) to f1 field
134 // On i386 System V ABI, float/double returns are in ST(0)134 // On i386 System V ABI, float/double returns are in ST(0)
135 // We save as float64 (8 bytes) to preserve precision135 // We save as float64 (8 bytes) to preserve precision
136- FMOVDP F0, syscall15Args_f1(BX)136+ FMOVDP F0, syscallArgs_f1(BX)
137 137
138 // Clean up stack138 // Clean up stack
139 ADDL $STACK_SIZE, SP139 ADDL $STACK_SIZE, SP
M sys_amd64.s +71 -37
@@ -8,11 +8,11 @@
88 #include "go_asm.h"
99 #include "funcdata.h"
1010
11-#define STACK_SIZE 80
11+#define STACK_SIZE 224
1212 #define PTR_ADDRESS (STACK_SIZE - 8)
1313
14-// syscall15X calls a function in libc on behalf of the syscall package.
15-// syscall15X takes a pointer to a struct like:
14+// syscallX calls a function in libc on behalf of the syscall package.
15+// syscallX takes a pointer to a struct like:
1616 // struct {
1717 // fn uintptr
1818 // a1 uintptr
@@ -34,65 +34,99 @@
3434 // r2 uintptr
3535 // err uintptr
3636 // }
37-// syscall15X must be called on the g0 stack with the
37+// syscallX must be called on the g0 stack with the
3838 // C calling convention (use libcCall).
39-GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $8
40-DATA ·syscall15XABI0(SB)/8, $syscall15X(SB)
41-TEXT syscall15X(SB), NOSPLIT, $STACK_SIZE
39+GLOBL ·syscallXABI0(SB), NOPTR|RODATA, $8
40+DATA ·syscallXABI0(SB)/8, $syscallX(SB)
41+TEXT syscallX(SB), NOSPLIT, $STACK_SIZE
4242 MOVQ DI, PTR_ADDRESS(SP) // save the pointer
4343 MOVQ DI, R11
4444
45- MOVQ syscall15Args_f1(R11), X0 // f1
46- MOVQ syscall15Args_f2(R11), X1 // f2
47- MOVQ syscall15Args_f3(R11), X2 // f3
48- MOVQ syscall15Args_f4(R11), X3 // f4
49- MOVQ syscall15Args_f5(R11), X4 // f5
50- MOVQ syscall15Args_f6(R11), X5 // f6
51- MOVQ syscall15Args_f7(R11), X6 // f7
52- MOVQ syscall15Args_f8(R11), X7 // f8
53-
54- MOVQ syscall15Args_a1(R11), DI // a1
55- MOVQ syscall15Args_a2(R11), SI // a2
56- MOVQ syscall15Args_a3(R11), DX // a3
57- MOVQ syscall15Args_a4(R11), CX // a4
58- MOVQ syscall15Args_a5(R11), R8 // a5
59- MOVQ syscall15Args_a6(R11), R9 // a6
45+ MOVQ syscallArgs_f1(R11), X0 // f1
46+ MOVQ syscallArgs_f2(R11), X1 // f2
47+ MOVQ syscallArgs_f3(R11), X2 // f3
48+ MOVQ syscallArgs_f4(R11), X3 // f4
49+ MOVQ syscallArgs_f5(R11), X4 // f5
50+ MOVQ syscallArgs_f6(R11), X5 // f6
51+ MOVQ syscallArgs_f7(R11), X6 // f7
52+ MOVQ syscallArgs_f8(R11), X7 // f8
53+
54+ MOVQ syscallArgs_a1(R11), DI // a1
55+ MOVQ syscallArgs_a2(R11), SI // a2
56+ MOVQ syscallArgs_a3(R11), DX // a3
57+ MOVQ syscallArgs_a4(R11), CX // a4
58+ MOVQ syscallArgs_a5(R11), R8 // a5
59+ MOVQ syscallArgs_a6(R11), R9 // a6
6060
6161 // push the remaining parameters onto the stack
62- MOVQ syscall15Args_a7(R11), R12
62+ MOVQ syscallArgs_a7(R11), R12
6363 MOVQ R12, 0(SP) // push a7
64- MOVQ syscall15Args_a8(R11), R12
64+ MOVQ syscallArgs_a8(R11), R12
6565 MOVQ R12, 8(SP) // push a8
66- MOVQ syscall15Args_a9(R11), R12
66+ MOVQ syscallArgs_a9(R11), R12
6767 MOVQ R12, 16(SP) // push a9
68- MOVQ syscall15Args_a10(R11), R12
68+ MOVQ syscallArgs_a10(R11), R12
6969 MOVQ R12, 24(SP) // push a10
70- MOVQ syscall15Args_a11(R11), R12
70+ MOVQ syscallArgs_a11(R11), R12
7171 MOVQ R12, 32(SP) // push a11
72- MOVQ syscall15Args_a12(R11), R12
72+ MOVQ syscallArgs_a12(R11), R12
7373 MOVQ R12, 40(SP) // push a12
74- MOVQ syscall15Args_a13(R11), R12
74+ MOVQ syscallArgs_a13(R11), R12
7575 MOVQ R12, 48(SP) // push a13
76- MOVQ syscall15Args_a14(R11), R12
76+ MOVQ syscallArgs_a14(R11), R12
7777 MOVQ R12, 56(SP) // push a14
78- MOVQ syscall15Args_a15(R11), R12
78+ MOVQ syscallArgs_a15(R11), R12
7979 MOVQ R12, 64(SP) // push a15
80+ MOVQ syscallArgs_a16(R11), R12
81+ MOVQ R12, 72(SP) // push a16
82+ MOVQ syscallArgs_a17(R11), R12
83+ MOVQ R12, 80(SP) // push a17
84+ MOVQ syscallArgs_a18(R11), R12
85+ MOVQ R12, 88(SP) // push a18
86+ MOVQ syscallArgs_a19(R11), R12
87+ MOVQ R12, 96(SP) // push a19
88+ MOVQ syscallArgs_a20(R11), R12
89+ MOVQ R12, 104(SP) // push a20
90+ MOVQ syscallArgs_a21(R11), R12
91+ MOVQ R12, 112(SP) // push a21
92+ MOVQ syscallArgs_a22(R11), R12
93+ MOVQ R12, 120(SP) // push a22
94+ MOVQ syscallArgs_a23(R11), R12
95+ MOVQ R12, 128(SP) // push a23
96+ MOVQ syscallArgs_a24(R11), R12
97+ MOVQ R12, 136(SP) // push a24
98+ MOVQ syscallArgs_a25(R11), R12
99+ MOVQ R12, 144(SP) // push a25
100+ MOVQ syscallArgs_a26(R11), R12
101+ MOVQ R12, 152(SP) // push a26
102+ MOVQ syscallArgs_a27(R11), R12
103+ MOVQ R12, 160(SP) // push a27
104+ MOVQ syscallArgs_a28(R11), R12
105+ MOVQ R12, 168(SP) // push a28
106+ MOVQ syscallArgs_a29(R11), R12
107+ MOVQ R12, 176(SP) // push a29
108+ MOVQ syscallArgs_a30(R11), R12
109+ MOVQ R12, 184(SP) // push a30
110+ MOVQ syscallArgs_a31(R11), R12
111+ MOVQ R12, 192(SP) // push a31
112+ MOVQ syscallArgs_a32(R11), R12
113+ MOVQ R12, 200(SP) // push a32
80114 XORL AX, AX // vararg: say "no float args"
81115
82- MOVQ syscall15Args_fn(R11), R10 // fn
116+ MOVQ syscallArgs_fn(R11), R10 // fn
83117 CALL R10
84118
85119 MOVQ PTR_ADDRESS(SP), DI // get the pointer back
86- MOVQ AX, syscall15Args_a1(DI) // r1
87- MOVQ DX, syscall15Args_a2(DI) // r2
88- MOVQ X0, syscall15Args_f1(DI) // f1
89- MOVQ X1, syscall15Args_f2(DI) // f2
120+ MOVQ AX, syscallArgs_a1(DI) // r1
121+ MOVQ DX, syscallArgs_a2(DI) // r2
122+ MOVQ X0, syscallArgs_f1(DI) // f1
123+ MOVQ X1, syscallArgs_f2(DI) // f2
90124
91125 #ifdef GOOS_darwin
92126 CALL purego_error(SB)
93127 MOVQ PTR_ADDRESS(SP), DI // reload (DI clobbered by call)
94128 MOVQ (AX), AX
95- MOVQ AX, syscall15Args_a3(DI) // save errno
129+ MOVQ AX, syscallArgs_a3(DI) // save errno
96130 #endif
97131
98132 XORL AX, AX // no error (it's ignored anyway)
@@ -8,11 +8,11 @@
8 #include "go_asm.h"8 #include "go_asm.h"
9 #include "funcdata.h"9 #include "funcdata.h"
10 10
11-#define STACK_SIZE 8011+#define STACK_SIZE 224
12 #define PTR_ADDRESS (STACK_SIZE - 8)12 #define PTR_ADDRESS (STACK_SIZE - 8)
13 13
14-// syscall15X calls a function in libc on behalf of the syscall package.14+// syscallX calls a function in libc on behalf of the syscall package.
15-// syscall15X takes a pointer to a struct like:15+// syscallX takes a pointer to a struct like:
16 // struct {16 // struct {
17 // fn uintptr17 // fn uintptr
18 // a1 uintptr18 // a1 uintptr
@@ -34,65 +34,99 @@
34 // r2 uintptr34 // r2 uintptr
35 // err uintptr35 // err uintptr
36 // }36 // }
37-// syscall15X must be called on the g0 stack with the37+// syscallX must be called on the g0 stack with the
38 // C calling convention (use libcCall).38 // C calling convention (use libcCall).
39-GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $839+GLOBL ·syscallXABI0(SB), NOPTR|RODATA, $8
40-DATA ·syscall15XABI0(SB)/8, $syscall15X(SB)40+DATA ·syscallXABI0(SB)/8, $syscallX(SB)
41-TEXT syscall15X(SB), NOSPLIT, $STACK_SIZE41+TEXT syscallX(SB), NOSPLIT, $STACK_SIZE
42 MOVQ DI, PTR_ADDRESS(SP) // save the pointer42 MOVQ DI, PTR_ADDRESS(SP) // save the pointer
43 MOVQ DI, R1143 MOVQ DI, R11
44 44
45- MOVQ syscall15Args_f1(R11), X0 // f145+ MOVQ syscallArgs_f1(R11), X0 // f1
46- MOVQ syscall15Args_f2(R11), X1 // f246+ MOVQ syscallArgs_f2(R11), X1 // f2
47- MOVQ syscall15Args_f3(R11), X2 // f347+ MOVQ syscallArgs_f3(R11), X2 // f3
48- MOVQ syscall15Args_f4(R11), X3 // f448+ MOVQ syscallArgs_f4(R11), X3 // f4
49- MOVQ syscall15Args_f5(R11), X4 // f549+ MOVQ syscallArgs_f5(R11), X4 // f5
50- MOVQ syscall15Args_f6(R11), X5 // f650+ MOVQ syscallArgs_f6(R11), X5 // f6
51- MOVQ syscall15Args_f7(R11), X6 // f751+ MOVQ syscallArgs_f7(R11), X6 // f7
52- MOVQ syscall15Args_f8(R11), X7 // f852+ MOVQ syscallArgs_f8(R11), X7 // f8
53-53+
54- MOVQ syscall15Args_a1(R11), DI // a154+ MOVQ syscallArgs_a1(R11), DI // a1
55- MOVQ syscall15Args_a2(R11), SI // a255+ MOVQ syscallArgs_a2(R11), SI // a2
56- MOVQ syscall15Args_a3(R11), DX // a356+ MOVQ syscallArgs_a3(R11), DX // a3
57- MOVQ syscall15Args_a4(R11), CX // a457+ MOVQ syscallArgs_a4(R11), CX // a4
58- MOVQ syscall15Args_a5(R11), R8 // a558+ MOVQ syscallArgs_a5(R11), R8 // a5
59- MOVQ syscall15Args_a6(R11), R9 // a659+ MOVQ syscallArgs_a6(R11), R9 // a6
60 60
61 // push the remaining parameters onto the stack61 // push the remaining parameters onto the stack
62- MOVQ syscall15Args_a7(R11), R1262+ MOVQ syscallArgs_a7(R11), R12
63 MOVQ R12, 0(SP) // push a763 MOVQ R12, 0(SP) // push a7
64- MOVQ syscall15Args_a8(R11), R1264+ MOVQ syscallArgs_a8(R11), R12
65 MOVQ R12, 8(SP) // push a865 MOVQ R12, 8(SP) // push a8
66- MOVQ syscall15Args_a9(R11), R1266+ MOVQ syscallArgs_a9(R11), R12
67 MOVQ R12, 16(SP) // push a967 MOVQ R12, 16(SP) // push a9
68- MOVQ syscall15Args_a10(R11), R1268+ MOVQ syscallArgs_a10(R11), R12
69 MOVQ R12, 24(SP) // push a1069 MOVQ R12, 24(SP) // push a10
70- MOVQ syscall15Args_a11(R11), R1270+ MOVQ syscallArgs_a11(R11), R12
71 MOVQ R12, 32(SP) // push a1171 MOVQ R12, 32(SP) // push a11
72- MOVQ syscall15Args_a12(R11), R1272+ MOVQ syscallArgs_a12(R11), R12
73 MOVQ R12, 40(SP) // push a1273 MOVQ R12, 40(SP) // push a12
74- MOVQ syscall15Args_a13(R11), R1274+ MOVQ syscallArgs_a13(R11), R12
75 MOVQ R12, 48(SP) // push a1375 MOVQ R12, 48(SP) // push a13
76- MOVQ syscall15Args_a14(R11), R1276+ MOVQ syscallArgs_a14(R11), R12
77 MOVQ R12, 56(SP) // push a1477 MOVQ R12, 56(SP) // push a14
78- MOVQ syscall15Args_a15(R11), R1278+ MOVQ syscallArgs_a15(R11), R12
79 MOVQ R12, 64(SP) // push a1579 MOVQ R12, 64(SP) // push a15
80+ MOVQ syscallArgs_a16(R11), R12
81+ MOVQ R12, 72(SP) // push a16
82+ MOVQ syscallArgs_a17(R11), R12
83+ MOVQ R12, 80(SP) // push a17
84+ MOVQ syscallArgs_a18(R11), R12
85+ MOVQ R12, 88(SP) // push a18
86+ MOVQ syscallArgs_a19(R11), R12
87+ MOVQ R12, 96(SP) // push a19
88+ MOVQ syscallArgs_a20(R11), R12
89+ MOVQ R12, 104(SP) // push a20
90+ MOVQ syscallArgs_a21(R11), R12
91+ MOVQ R12, 112(SP) // push a21
92+ MOVQ syscallArgs_a22(R11), R12
93+ MOVQ R12, 120(SP) // push a22
94+ MOVQ syscallArgs_a23(R11), R12
95+ MOVQ R12, 128(SP) // push a23
96+ MOVQ syscallArgs_a24(R11), R12
97+ MOVQ R12, 136(SP) // push a24
98+ MOVQ syscallArgs_a25(R11), R12
99+ MOVQ R12, 144(SP) // push a25
100+ MOVQ syscallArgs_a26(R11), R12
101+ MOVQ R12, 152(SP) // push a26
102+ MOVQ syscallArgs_a27(R11), R12
103+ MOVQ R12, 160(SP) // push a27
104+ MOVQ syscallArgs_a28(R11), R12
105+ MOVQ R12, 168(SP) // push a28
106+ MOVQ syscallArgs_a29(R11), R12
107+ MOVQ R12, 176(SP) // push a29
108+ MOVQ syscallArgs_a30(R11), R12
109+ MOVQ R12, 184(SP) // push a30
110+ MOVQ syscallArgs_a31(R11), R12
111+ MOVQ R12, 192(SP) // push a31
112+ MOVQ syscallArgs_a32(R11), R12
113+ MOVQ R12, 200(SP) // push a32
80 XORL AX, AX // vararg: say "no float args"114 XORL AX, AX // vararg: say "no float args"
81 115
82- MOVQ syscall15Args_fn(R11), R10 // fn116+ MOVQ syscallArgs_fn(R11), R10 // fn
83 CALL R10117 CALL R10
84 118
85 MOVQ PTR_ADDRESS(SP), DI // get the pointer back119 MOVQ PTR_ADDRESS(SP), DI // get the pointer back
86- MOVQ AX, syscall15Args_a1(DI) // r1120+ MOVQ AX, syscallArgs_a1(DI) // r1
87- MOVQ DX, syscall15Args_a2(DI) // r2121+ MOVQ DX, syscallArgs_a2(DI) // r2
88- MOVQ X0, syscall15Args_f1(DI) // f1122+ MOVQ X0, syscallArgs_f1(DI) // f1
89- MOVQ X1, syscall15Args_f2(DI) // f2123+ MOVQ X1, syscallArgs_f2(DI) // f2
90 124
91 #ifdef GOOS_darwin125 #ifdef GOOS_darwin
92 CALL purego_error(SB)126 CALL purego_error(SB)
93 MOVQ PTR_ADDRESS(SP), DI // reload (DI clobbered by call)127 MOVQ PTR_ADDRESS(SP), DI // reload (DI clobbered by call)
94 MOVQ (AX), AX128 MOVQ (AX), AX
95- MOVQ AX, syscall15Args_a3(DI) // save errno129+ MOVQ AX, syscallArgs_a3(DI) // save errno
96 #endif130 #endif
97 131
98 XORL AX, AX // no error (it's ignored anyway)132 XORL AX, AX // no error (it's ignored anyway)
M sys_arm.s +54 -54
@@ -10,8 +10,8 @@
1010 #define STACK_SIZE 128
1111 #define PTR_ADDRESS (STACK_SIZE - 4)
1212
13-// syscall15X calls a function in libc on behalf of the syscall package.
14-// syscall15X takes a pointer to a struct like:
13+// syscallX calls a function in libc on behalf of the syscall package.
14+// syscallX takes a pointer to a struct like:
1515 // struct {
1616 // fn uintptr
1717 // a1 uintptr
@@ -22,12 +22,12 @@
2222 // f16 uintptr
2323 // arm64_r8 uintptr
2424 // }
25-// syscall15X must be called on the g0 stack with the
25+// syscallX must be called on the g0 stack with the
2626 // C calling convention (use libcCall).
27-GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $4
28-DATA ·syscall15XABI0(SB)/4, $syscall15X(SB)
29-TEXT syscall15X(SB), NOSPLIT|NOFRAME, $0-0
30- // Called via C calling convention: R0 = pointer to syscall15Args
27+GLOBL ·syscallXABI0(SB), NOPTR|RODATA, $4
28+DATA ·syscallXABI0(SB)/4, $syscallX(SB)
29+TEXT syscallX(SB), NOSPLIT|NOFRAME, $0-0
30+ // Called via C calling convention: R0 = pointer to syscallArgs
3131 // NOT via Go calling convention
3232 // Save link register and callee-saved registers first
3333 MOVW.W R14, -4(R13) // save LR (decrement and store)
@@ -38,82 +38,82 @@ TEXT syscall15X(SB), NOSPLIT|NOFRAME, $0-0
3838 MOVW R8, PTR_ADDRESS(R13)
3939
4040 // Load function pointer first (before anything can corrupt R8)
41- MOVW syscall15Args_fn(R8), R5
41+ MOVW syscallArgs_fn(R8), R5
4242 MOVW R5, (PTR_ADDRESS-4)(R13) // save fn at offset 56
4343
4444 // Load floating point arguments
4545 // Each float64 spans 2 uintptr slots (8 bytes) on ARM32, so we skip by 2
46- MOVD syscall15Args_f1(R8), F0 // f1+f2 -> D0
47- MOVD syscall15Args_f3(R8), F1 // f3+f4 -> D1
48- MOVD syscall15Args_f5(R8), F2 // f5+f6 -> D2
49- MOVD syscall15Args_f7(R8), F3 // f7+f8 -> D3
50- MOVD syscall15Args_f9(R8), F4 // f9+f10 -> D4
51- MOVD syscall15Args_f11(R8), F5 // f11+f12 -> D5
52- MOVD syscall15Args_f13(R8), F6 // f13+f14 -> D6
53- MOVD syscall15Args_f15(R8), F7 // f15+f16 -> D7
46+ MOVD syscallArgs_f1(R8), F0 // f1+f2 -> D0
47+ MOVD syscallArgs_f3(R8), F1 // f3+f4 -> D1
48+ MOVD syscallArgs_f5(R8), F2 // f5+f6 -> D2
49+ MOVD syscallArgs_f7(R8), F3 // f7+f8 -> D3
50+ MOVD syscallArgs_f9(R8), F4 // f9+f10 -> D4
51+ MOVD syscallArgs_f11(R8), F5 // f11+f12 -> D5
52+ MOVD syscallArgs_f13(R8), F6 // f13+f14 -> D6
53+ MOVD syscallArgs_f15(R8), F7 // f15+f16 -> D7
5454
5555 // Load integer arguments into registers (R0-R3 for ARM EABI)
56- MOVW syscall15Args_a1(R8), R0 // a1
57- MOVW syscall15Args_a2(R8), R1 // a2
58- MOVW syscall15Args_a3(R8), R2 // a3
59- MOVW syscall15Args_a4(R8), R3 // a4
56+ MOVW syscallArgs_a1(R8), R0 // a1
57+ MOVW syscallArgs_a2(R8), R1 // a2
58+ MOVW syscallArgs_a3(R8), R2 // a3
59+ MOVW syscallArgs_a4(R8), R3 // a4
6060
6161 // push a5-a32 onto stack
62- MOVW syscall15Args_a5(R8), R4
62+ MOVW syscallArgs_a5(R8), R4
6363 MOVW R4, 0(R13)
64- MOVW syscall15Args_a6(R8), R4
64+ MOVW syscallArgs_a6(R8), R4
6565 MOVW R4, 4(R13)
66- MOVW syscall15Args_a7(R8), R4
66+ MOVW syscallArgs_a7(R8), R4
6767 MOVW R4, 8(R13)
68- MOVW syscall15Args_a8(R8), R4
68+ MOVW syscallArgs_a8(R8), R4
6969 MOVW R4, 12(R13)
70- MOVW syscall15Args_a9(R8), R4
70+ MOVW syscallArgs_a9(R8), R4
7171 MOVW R4, 16(R13)
72- MOVW syscall15Args_a10(R8), R4
72+ MOVW syscallArgs_a10(R8), R4
7373 MOVW R4, 20(R13)
74- MOVW syscall15Args_a11(R8), R4
74+ MOVW syscallArgs_a11(R8), R4
7575 MOVW R4, 24(R13)
76- MOVW syscall15Args_a12(R8), R4
76+ MOVW syscallArgs_a12(R8), R4
7777 MOVW R4, 28(R13)
78- MOVW syscall15Args_a13(R8), R4
78+ MOVW syscallArgs_a13(R8), R4
7979 MOVW R4, 32(R13)
80- MOVW syscall15Args_a14(R8), R4
80+ MOVW syscallArgs_a14(R8), R4
8181 MOVW R4, 36(R13)
82- MOVW syscall15Args_a15(R8), R4
82+ MOVW syscallArgs_a15(R8), R4
8383 MOVW R4, 40(R13)
84- MOVW syscall15Args_a16(R8), R4
84+ MOVW syscallArgs_a16(R8), R4
8585 MOVW R4, 44(R13)
86- MOVW syscall15Args_a17(R8), R4
86+ MOVW syscallArgs_a17(R8), R4
8787 MOVW R4, 48(R13)
88- MOVW syscall15Args_a18(R8), R4
88+ MOVW syscallArgs_a18(R8), R4
8989 MOVW R4, 52(R13)
90- MOVW syscall15Args_a19(R8), R4
90+ MOVW syscallArgs_a19(R8), R4
9191 MOVW R4, 56(R13)
92- MOVW syscall15Args_a20(R8), R4
92+ MOVW syscallArgs_a20(R8), R4
9393 MOVW R4, 60(R13)
94- MOVW syscall15Args_a21(R8), R4
94+ MOVW syscallArgs_a21(R8), R4
9595 MOVW R4, 64(R13)
96- MOVW syscall15Args_a22(R8), R4
96+ MOVW syscallArgs_a22(R8), R4
9797 MOVW R4, 68(R13)
98- MOVW syscall15Args_a23(R8), R4
98+ MOVW syscallArgs_a23(R8), R4
9999 MOVW R4, 72(R13)
100- MOVW syscall15Args_a24(R8), R4
100+ MOVW syscallArgs_a24(R8), R4
101101 MOVW R4, 76(R13)
102- MOVW syscall15Args_a25(R8), R4
102+ MOVW syscallArgs_a25(R8), R4
103103 MOVW R4, 80(R13)
104- MOVW syscall15Args_a26(R8), R4
104+ MOVW syscallArgs_a26(R8), R4
105105 MOVW R4, 84(R13)
106- MOVW syscall15Args_a27(R8), R4
106+ MOVW syscallArgs_a27(R8), R4
107107 MOVW R4, 88(R13)
108- MOVW syscall15Args_a28(R8), R4
108+ MOVW syscallArgs_a28(R8), R4
109109 MOVW R4, 92(R13)
110- MOVW syscall15Args_a29(R8), R4
110+ MOVW syscallArgs_a29(R8), R4
111111 MOVW R4, 96(R13)
112- MOVW syscall15Args_a30(R8), R4
112+ MOVW syscallArgs_a30(R8), R4
113113 MOVW R4, 100(R13)
114- MOVW syscall15Args_a31(R8), R4
114+ MOVW syscallArgs_a31(R8), R4
115115 MOVW R4, 104(R13)
116- MOVW syscall15Args_a32(R8), R4
116+ MOVW syscallArgs_a32(R8), R4
117117 MOVW R4, 108(R13)
118118
119119 // Load saved function pointer and call
@@ -128,14 +128,14 @@ TEXT syscall15X(SB), NOSPLIT|NOFRAME, $0-0
128128 ADD $STACK_SIZE, R13
129129
130130 // save R0, R1
131- MOVW R0, syscall15Args_a1(R8)
132- MOVW R1, syscall15Args_a2(R8)
131+ MOVW R0, syscallArgs_a1(R8)
132+ MOVW R1, syscallArgs_a2(R8)
133133
134134 // save f0-f3 (each float64 spans 2 uintptr slots on ARM32)
135- MOVD F0, syscall15Args_f1(R8)
136- MOVD F1, syscall15Args_f3(R8)
137- MOVD F2, syscall15Args_f5(R8)
138- MOVD F3, syscall15Args_f7(R8)
135+ MOVD F0, syscallArgs_f1(R8)
136+ MOVD F1, syscallArgs_f3(R8)
137+ MOVD F2, syscallArgs_f5(R8)
138+ MOVD F3, syscallArgs_f7(R8)
139139
140140 // Restore callee-saved registers and return
141141 MOVM.IA.W (R13), [R4, R5, R6, R7, R8, R9, R11]
@@ -10,8 +10,8 @@
10 #define STACK_SIZE 12810 #define STACK_SIZE 128
11 #define PTR_ADDRESS (STACK_SIZE - 4)11 #define PTR_ADDRESS (STACK_SIZE - 4)
12 12
13-// syscall15X calls a function in libc on behalf of the syscall package.13+// syscallX calls a function in libc on behalf of the syscall package.
14-// syscall15X takes a pointer to a struct like:14+// syscallX takes a pointer to a struct like:
15 // struct {15 // struct {
16 // fn uintptr16 // fn uintptr
17 // a1 uintptr17 // a1 uintptr
@@ -22,12 +22,12 @@
22 // f16 uintptr22 // f16 uintptr
23 // arm64_r8 uintptr23 // arm64_r8 uintptr
24 // }24 // }
25-// syscall15X must be called on the g0 stack with the25+// syscallX must be called on the g0 stack with the
26 // C calling convention (use libcCall).26 // C calling convention (use libcCall).
27-GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $427+GLOBL ·syscallXABI0(SB), NOPTR|RODATA, $4
28-DATA ·syscall15XABI0(SB)/4, $syscall15X(SB)28+DATA ·syscallXABI0(SB)/4, $syscallX(SB)
29-TEXT syscall15X(SB), NOSPLIT|NOFRAME, $0-029+TEXT syscallX(SB), NOSPLIT|NOFRAME, $0-0
30- // Called via C calling convention: R0 = pointer to syscall15Args30+ // Called via C calling convention: R0 = pointer to syscallArgs
31 // NOT via Go calling convention31 // NOT via Go calling convention
32 // Save link register and callee-saved registers first32 // Save link register and callee-saved registers first
33 MOVW.W R14, -4(R13) // save LR (decrement and store)33 MOVW.W R14, -4(R13) // save LR (decrement and store)
@@ -38,82 +38,82 @@ TEXT syscall15X(SB), NOSPLIT|NOFRAME, $0-0
38 MOVW R8, PTR_ADDRESS(R13)38 MOVW R8, PTR_ADDRESS(R13)
39 39
40 // Load function pointer first (before anything can corrupt R8)40 // Load function pointer first (before anything can corrupt R8)
41- MOVW syscall15Args_fn(R8), R541+ MOVW syscallArgs_fn(R8), R5
42 MOVW R5, (PTR_ADDRESS-4)(R13) // save fn at offset 5642 MOVW R5, (PTR_ADDRESS-4)(R13) // save fn at offset 56
43 43
44 // Load floating point arguments44 // Load floating point arguments
45 // Each float64 spans 2 uintptr slots (8 bytes) on ARM32, so we skip by 245 // Each float64 spans 2 uintptr slots (8 bytes) on ARM32, so we skip by 2
46- MOVD syscall15Args_f1(R8), F0 // f1+f2 -> D046+ MOVD syscallArgs_f1(R8), F0 // f1+f2 -> D0
47- MOVD syscall15Args_f3(R8), F1 // f3+f4 -> D147+ MOVD syscallArgs_f3(R8), F1 // f3+f4 -> D1
48- MOVD syscall15Args_f5(R8), F2 // f5+f6 -> D248+ MOVD syscallArgs_f5(R8), F2 // f5+f6 -> D2
49- MOVD syscall15Args_f7(R8), F3 // f7+f8 -> D349+ MOVD syscallArgs_f7(R8), F3 // f7+f8 -> D3
50- MOVD syscall15Args_f9(R8), F4 // f9+f10 -> D450+ MOVD syscallArgs_f9(R8), F4 // f9+f10 -> D4
51- MOVD syscall15Args_f11(R8), F5 // f11+f12 -> D551+ MOVD syscallArgs_f11(R8), F5 // f11+f12 -> D5
52- MOVD syscall15Args_f13(R8), F6 // f13+f14 -> D652+ MOVD syscallArgs_f13(R8), F6 // f13+f14 -> D6
53- MOVD syscall15Args_f15(R8), F7 // f15+f16 -> D753+ MOVD syscallArgs_f15(R8), F7 // f15+f16 -> D7
54 54
55 // Load integer arguments into registers (R0-R3 for ARM EABI)55 // Load integer arguments into registers (R0-R3 for ARM EABI)
56- MOVW syscall15Args_a1(R8), R0 // a156+ MOVW syscallArgs_a1(R8), R0 // a1
57- MOVW syscall15Args_a2(R8), R1 // a257+ MOVW syscallArgs_a2(R8), R1 // a2
58- MOVW syscall15Args_a3(R8), R2 // a358+ MOVW syscallArgs_a3(R8), R2 // a3
59- MOVW syscall15Args_a4(R8), R3 // a459+ MOVW syscallArgs_a4(R8), R3 // a4
60 60
61 // push a5-a32 onto stack61 // push a5-a32 onto stack
62- MOVW syscall15Args_a5(R8), R462+ MOVW syscallArgs_a5(R8), R4
63 MOVW R4, 0(R13)63 MOVW R4, 0(R13)
64- MOVW syscall15Args_a6(R8), R464+ MOVW syscallArgs_a6(R8), R4
65 MOVW R4, 4(R13)65 MOVW R4, 4(R13)
66- MOVW syscall15Args_a7(R8), R466+ MOVW syscallArgs_a7(R8), R4
67 MOVW R4, 8(R13)67 MOVW R4, 8(R13)
68- MOVW syscall15Args_a8(R8), R468+ MOVW syscallArgs_a8(R8), R4
69 MOVW R4, 12(R13)69 MOVW R4, 12(R13)
70- MOVW syscall15Args_a9(R8), R470+ MOVW syscallArgs_a9(R8), R4
71 MOVW R4, 16(R13)71 MOVW R4, 16(R13)
72- MOVW syscall15Args_a10(R8), R472+ MOVW syscallArgs_a10(R8), R4
73 MOVW R4, 20(R13)73 MOVW R4, 20(R13)
74- MOVW syscall15Args_a11(R8), R474+ MOVW syscallArgs_a11(R8), R4
75 MOVW R4, 24(R13)75 MOVW R4, 24(R13)
76- MOVW syscall15Args_a12(R8), R476+ MOVW syscallArgs_a12(R8), R4
77 MOVW R4, 28(R13)77 MOVW R4, 28(R13)
78- MOVW syscall15Args_a13(R8), R478+ MOVW syscallArgs_a13(R8), R4
79 MOVW R4, 32(R13)79 MOVW R4, 32(R13)
80- MOVW syscall15Args_a14(R8), R480+ MOVW syscallArgs_a14(R8), R4
81 MOVW R4, 36(R13)81 MOVW R4, 36(R13)
82- MOVW syscall15Args_a15(R8), R482+ MOVW syscallArgs_a15(R8), R4
83 MOVW R4, 40(R13)83 MOVW R4, 40(R13)
84- MOVW syscall15Args_a16(R8), R484+ MOVW syscallArgs_a16(R8), R4
85 MOVW R4, 44(R13)85 MOVW R4, 44(R13)
86- MOVW syscall15Args_a17(R8), R486+ MOVW syscallArgs_a17(R8), R4
87 MOVW R4, 48(R13)87 MOVW R4, 48(R13)
88- MOVW syscall15Args_a18(R8), R488+ MOVW syscallArgs_a18(R8), R4
89 MOVW R4, 52(R13)89 MOVW R4, 52(R13)
90- MOVW syscall15Args_a19(R8), R490+ MOVW syscallArgs_a19(R8), R4
91 MOVW R4, 56(R13)91 MOVW R4, 56(R13)
92- MOVW syscall15Args_a20(R8), R492+ MOVW syscallArgs_a20(R8), R4
93 MOVW R4, 60(R13)93 MOVW R4, 60(R13)
94- MOVW syscall15Args_a21(R8), R494+ MOVW syscallArgs_a21(R8), R4
95 MOVW R4, 64(R13)95 MOVW R4, 64(R13)
96- MOVW syscall15Args_a22(R8), R496+ MOVW syscallArgs_a22(R8), R4
97 MOVW R4, 68(R13)97 MOVW R4, 68(R13)
98- MOVW syscall15Args_a23(R8), R498+ MOVW syscallArgs_a23(R8), R4
99 MOVW R4, 72(R13)99 MOVW R4, 72(R13)
100- MOVW syscall15Args_a24(R8), R4100+ MOVW syscallArgs_a24(R8), R4
101 MOVW R4, 76(R13)101 MOVW R4, 76(R13)
102- MOVW syscall15Args_a25(R8), R4102+ MOVW syscallArgs_a25(R8), R4
103 MOVW R4, 80(R13)103 MOVW R4, 80(R13)
104- MOVW syscall15Args_a26(R8), R4104+ MOVW syscallArgs_a26(R8), R4
105 MOVW R4, 84(R13)105 MOVW R4, 84(R13)
106- MOVW syscall15Args_a27(R8), R4106+ MOVW syscallArgs_a27(R8), R4
107 MOVW R4, 88(R13)107 MOVW R4, 88(R13)
108- MOVW syscall15Args_a28(R8), R4108+ MOVW syscallArgs_a28(R8), R4
109 MOVW R4, 92(R13)109 MOVW R4, 92(R13)
110- MOVW syscall15Args_a29(R8), R4110+ MOVW syscallArgs_a29(R8), R4
111 MOVW R4, 96(R13)111 MOVW R4, 96(R13)
112- MOVW syscall15Args_a30(R8), R4112+ MOVW syscallArgs_a30(R8), R4
113 MOVW R4, 100(R13)113 MOVW R4, 100(R13)
114- MOVW syscall15Args_a31(R8), R4114+ MOVW syscallArgs_a31(R8), R4
115 MOVW R4, 104(R13)115 MOVW R4, 104(R13)
116- MOVW syscall15Args_a32(R8), R4116+ MOVW syscallArgs_a32(R8), R4
117 MOVW R4, 108(R13)117 MOVW R4, 108(R13)
118 118
119 // Load saved function pointer and call119 // Load saved function pointer and call
@@ -128,14 +128,14 @@ TEXT syscall15X(SB), NOSPLIT|NOFRAME, $0-0
128 ADD $STACK_SIZE, R13128 ADD $STACK_SIZE, R13
129 129
130 // save R0, R1130 // save R0, R1
131- MOVW R0, syscall15Args_a1(R8)131+ MOVW R0, syscallArgs_a1(R8)
132- MOVW R1, syscall15Args_a2(R8)132+ MOVW R1, syscallArgs_a2(R8)
133 133
134 // save f0-f3 (each float64 spans 2 uintptr slots on ARM32)134 // save f0-f3 (each float64 spans 2 uintptr slots on ARM32)
135- MOVD F0, syscall15Args_f1(R8)135+ MOVD F0, syscallArgs_f1(R8)
136- MOVD F1, syscall15Args_f3(R8)136+ MOVD F1, syscallArgs_f3(R8)
137- MOVD F2, syscall15Args_f5(R8)137+ MOVD F2, syscallArgs_f5(R8)
138- MOVD F3, syscall15Args_f7(R8)138+ MOVD F3, syscallArgs_f7(R8)
139 139
140 // Restore callee-saved registers and return140 // Restore callee-saved registers and return
141 MOVM.IA.W (R13), [R4, R5, R6, R7, R8, R9, R11]141 MOVM.IA.W (R13), [R4, R5, R6, R7, R8, R9, R11]
M sys_arm64.s +73 -39
@@ -7,11 +7,11 @@
77 #include "go_asm.h"
88 #include "funcdata.h"
99
10-#define STACK_SIZE 64
10+#define STACK_SIZE 208
1111 #define PTR_ADDRESS (STACK_SIZE - 8)
1212
13-// syscall15X calls a function in libc on behalf of the syscall package.
14-// syscall15X takes a pointer to a struct like:
13+// syscallX calls a function in libc on behalf of the syscall package.
14+// syscallX takes a pointer to a struct like:
1515 // struct {
1616 // fn uintptr
1717 // a1 uintptr
@@ -33,66 +33,100 @@
3333 // r2 uintptr
3434 // err uintptr
3535 // }
36-// syscall15X must be called on the g0 stack with the
36+// syscallX must be called on the g0 stack with the
3737 // C calling convention (use libcCall).
38-GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $8
39-DATA ·syscall15XABI0(SB)/8, $syscall15X(SB)
40-TEXT syscall15X(SB), NOSPLIT, $0
38+GLOBL ·syscallXABI0(SB), NOPTR|RODATA, $8
39+DATA ·syscallXABI0(SB)/8, $syscallX(SB)
40+TEXT syscallX(SB), NOSPLIT, $0
4141 SUB $STACK_SIZE, RSP // push structure pointer
4242 MOVD R0, PTR_ADDRESS(RSP)
4343 MOVD R0, R9
4444
45- FMOVD syscall15Args_f1(R9), F0 // f1
46- FMOVD syscall15Args_f2(R9), F1 // f2
47- FMOVD syscall15Args_f3(R9), F2 // f3
48- FMOVD syscall15Args_f4(R9), F3 // f4
49- FMOVD syscall15Args_f5(R9), F4 // f5
50- FMOVD syscall15Args_f6(R9), F5 // f6
51- FMOVD syscall15Args_f7(R9), F6 // f7
52- FMOVD syscall15Args_f8(R9), F7 // f8
45+ FMOVD syscallArgs_f1(R9), F0 // f1
46+ FMOVD syscallArgs_f2(R9), F1 // f2
47+ FMOVD syscallArgs_f3(R9), F2 // f3
48+ FMOVD syscallArgs_f4(R9), F3 // f4
49+ FMOVD syscallArgs_f5(R9), F4 // f5
50+ FMOVD syscallArgs_f6(R9), F5 // f6
51+ FMOVD syscallArgs_f7(R9), F6 // f7
52+ FMOVD syscallArgs_f8(R9), F7 // f8
5353
54- MOVD syscall15Args_a1(R9), R0 // a1
55- MOVD syscall15Args_a2(R9), R1 // a2
56- MOVD syscall15Args_a3(R9), R2 // a3
57- MOVD syscall15Args_a4(R9), R3 // a4
58- MOVD syscall15Args_a5(R9), R4 // a5
59- MOVD syscall15Args_a6(R9), R5 // a6
60- MOVD syscall15Args_a7(R9), R6 // a7
61- MOVD syscall15Args_a8(R9), R7 // a8
62- MOVD syscall15Args_arm64_r8(R9), R8 // r8
54+ MOVD syscallArgs_a1(R9), R0 // a1
55+ MOVD syscallArgs_a2(R9), R1 // a2
56+ MOVD syscallArgs_a3(R9), R2 // a3
57+ MOVD syscallArgs_a4(R9), R3 // a4
58+ MOVD syscallArgs_a5(R9), R4 // a5
59+ MOVD syscallArgs_a6(R9), R5 // a6
60+ MOVD syscallArgs_a7(R9), R6 // a7
61+ MOVD syscallArgs_a8(R9), R7 // a8
62+ MOVD syscallArgs_arm64_r8(R9), R8 // r8
6363
64- MOVD syscall15Args_a9(R9), R10
64+ MOVD syscallArgs_a9(R9), R10
6565 MOVD R10, 0(RSP) // push a9 onto stack
66- MOVD syscall15Args_a10(R9), R10
66+ MOVD syscallArgs_a10(R9), R10
6767 MOVD R10, 8(RSP) // push a10 onto stack
68- MOVD syscall15Args_a11(R9), R10
68+ MOVD syscallArgs_a11(R9), R10
6969 MOVD R10, 16(RSP) // push a11 onto stack
70- MOVD syscall15Args_a12(R9), R10
70+ MOVD syscallArgs_a12(R9), R10
7171 MOVD R10, 24(RSP) // push a12 onto stack
72- MOVD syscall15Args_a13(R9), R10
72+ MOVD syscallArgs_a13(R9), R10
7373 MOVD R10, 32(RSP) // push a13 onto stack
74- MOVD syscall15Args_a14(R9), R10
74+ MOVD syscallArgs_a14(R9), R10
7575 MOVD R10, 40(RSP) // push a14 onto stack
76- MOVD syscall15Args_a15(R9), R10
76+ MOVD syscallArgs_a15(R9), R10
7777 MOVD R10, 48(RSP) // push a15 onto stack
78+ MOVD syscallArgs_a16(R9), R10
79+ MOVD R10, 56(RSP) // push a16 onto stack
80+ MOVD syscallArgs_a17(R9), R10
81+ MOVD R10, 64(RSP) // push a17 onto stack
82+ MOVD syscallArgs_a18(R9), R10
83+ MOVD R10, 72(RSP) // push a18 onto stack
84+ MOVD syscallArgs_a19(R9), R10
85+ MOVD R10, 80(RSP) // push a19 onto stack
86+ MOVD syscallArgs_a20(R9), R10
87+ MOVD R10, 88(RSP) // push a20 onto stack
88+ MOVD syscallArgs_a21(R9), R10
89+ MOVD R10, 96(RSP) // push a21 onto stack
90+ MOVD syscallArgs_a22(R9), R10
91+ MOVD R10, 104(RSP) // push a22 onto stack
92+ MOVD syscallArgs_a23(R9), R10
93+ MOVD R10, 112(RSP) // push a23 onto stack
94+ MOVD syscallArgs_a24(R9), R10
95+ MOVD R10, 120(RSP) // push a24 onto stack
96+ MOVD syscallArgs_a25(R9), R10
97+ MOVD R10, 128(RSP) // push a25 onto stack
98+ MOVD syscallArgs_a26(R9), R10
99+ MOVD R10, 136(RSP) // push a26 onto stack
100+ MOVD syscallArgs_a27(R9), R10
101+ MOVD R10, 144(RSP) // push a27 onto stack
102+ MOVD syscallArgs_a28(R9), R10
103+ MOVD R10, 152(RSP) // push a28 onto stack
104+ MOVD syscallArgs_a29(R9), R10
105+ MOVD R10, 160(RSP) // push a29 onto stack
106+ MOVD syscallArgs_a30(R9), R10
107+ MOVD R10, 168(RSP) // push a30 onto stack
108+ MOVD syscallArgs_a31(R9), R10
109+ MOVD R10, 176(RSP) // push a31 onto stack
110+ MOVD syscallArgs_a32(R9), R10
111+ MOVD R10, 184(RSP) // push a32 onto stack
78112
79- MOVD syscall15Args_fn(R9), R10 // fn
113+ MOVD syscallArgs_fn(R9), R10 // fn
80114 BL (R10)
81115
82116 MOVD PTR_ADDRESS(RSP), R2 // pop structure pointer
83117 ADD $STACK_SIZE, RSP
84118
85- MOVD R0, syscall15Args_a1(R2) // save r1
86- MOVD R1, syscall15Args_a2(R2) // save r3
87- FMOVD F0, syscall15Args_f1(R2) // save f0
88- FMOVD F1, syscall15Args_f2(R2) // save f1
89- FMOVD F2, syscall15Args_f3(R2) // save f2
90- FMOVD F3, syscall15Args_f4(R2) // save f3
119+ MOVD R0, syscallArgs_a1(R2) // save r1
120+ MOVD R1, syscallArgs_a2(R2) // save r3
121+ FMOVD F0, syscallArgs_f1(R2) // save f0
122+ FMOVD F1, syscallArgs_f2(R2) // save f1
123+ FMOVD F2, syscallArgs_f3(R2) // save f2
124+ FMOVD F3, syscallArgs_f4(R2) // save f3
91125
92126 #ifdef GOOS_darwin
93127 BL purego_error(SB)
94128 MOVD (R0), R0
95- MOVD R0, syscall15Args_a3(R2) // save errno
129+ MOVD R0, syscallArgs_a3(R2) // save errno
96130
97131 #endif
98132 RET
@@ -7,11 +7,11 @@
7 #include "go_asm.h"7 #include "go_asm.h"
8 #include "funcdata.h"8 #include "funcdata.h"
9 9
10-#define STACK_SIZE 6410+#define STACK_SIZE 208
11 #define PTR_ADDRESS (STACK_SIZE - 8)11 #define PTR_ADDRESS (STACK_SIZE - 8)
12 12
13-// syscall15X calls a function in libc on behalf of the syscall package.13+// syscallX calls a function in libc on behalf of the syscall package.
14-// syscall15X takes a pointer to a struct like:14+// syscallX takes a pointer to a struct like:
15 // struct {15 // struct {
16 // fn uintptr16 // fn uintptr
17 // a1 uintptr17 // a1 uintptr
@@ -33,66 +33,100 @@
33 // r2 uintptr33 // r2 uintptr
34 // err uintptr34 // err uintptr
35 // }35 // }
36-// syscall15X must be called on the g0 stack with the36+// syscallX must be called on the g0 stack with the
37 // C calling convention (use libcCall).37 // C calling convention (use libcCall).
38-GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $838+GLOBL ·syscallXABI0(SB), NOPTR|RODATA, $8
39-DATA ·syscall15XABI0(SB)/8, $syscall15X(SB)39+DATA ·syscallXABI0(SB)/8, $syscallX(SB)
40-TEXT syscall15X(SB), NOSPLIT, $040+TEXT syscallX(SB), NOSPLIT, $0
41 SUB $STACK_SIZE, RSP // push structure pointer41 SUB $STACK_SIZE, RSP // push structure pointer
42 MOVD R0, PTR_ADDRESS(RSP)42 MOVD R0, PTR_ADDRESS(RSP)
43 MOVD R0, R943 MOVD R0, R9
44 44
45- FMOVD syscall15Args_f1(R9), F0 // f145+ FMOVD syscallArgs_f1(R9), F0 // f1
46- FMOVD syscall15Args_f2(R9), F1 // f246+ FMOVD syscallArgs_f2(R9), F1 // f2
47- FMOVD syscall15Args_f3(R9), F2 // f347+ FMOVD syscallArgs_f3(R9), F2 // f3
48- FMOVD syscall15Args_f4(R9), F3 // f448+ FMOVD syscallArgs_f4(R9), F3 // f4
49- FMOVD syscall15Args_f5(R9), F4 // f549+ FMOVD syscallArgs_f5(R9), F4 // f5
50- FMOVD syscall15Args_f6(R9), F5 // f650+ FMOVD syscallArgs_f6(R9), F5 // f6
51- FMOVD syscall15Args_f7(R9), F6 // f751+ FMOVD syscallArgs_f7(R9), F6 // f7
52- FMOVD syscall15Args_f8(R9), F7 // f852+ FMOVD syscallArgs_f8(R9), F7 // f8
53 53
54- MOVD syscall15Args_a1(R9), R0 // a154+ MOVD syscallArgs_a1(R9), R0 // a1
55- MOVD syscall15Args_a2(R9), R1 // a255+ MOVD syscallArgs_a2(R9), R1 // a2
56- MOVD syscall15Args_a3(R9), R2 // a356+ MOVD syscallArgs_a3(R9), R2 // a3
57- MOVD syscall15Args_a4(R9), R3 // a457+ MOVD syscallArgs_a4(R9), R3 // a4
58- MOVD syscall15Args_a5(R9), R4 // a558+ MOVD syscallArgs_a5(R9), R4 // a5
59- MOVD syscall15Args_a6(R9), R5 // a659+ MOVD syscallArgs_a6(R9), R5 // a6
60- MOVD syscall15Args_a7(R9), R6 // a760+ MOVD syscallArgs_a7(R9), R6 // a7
61- MOVD syscall15Args_a8(R9), R7 // a861+ MOVD syscallArgs_a8(R9), R7 // a8
62- MOVD syscall15Args_arm64_r8(R9), R8 // r862+ MOVD syscallArgs_arm64_r8(R9), R8 // r8
63 63
64- MOVD syscall15Args_a9(R9), R1064+ MOVD syscallArgs_a9(R9), R10
65 MOVD R10, 0(RSP) // push a9 onto stack65 MOVD R10, 0(RSP) // push a9 onto stack
66- MOVD syscall15Args_a10(R9), R1066+ MOVD syscallArgs_a10(R9), R10
67 MOVD R10, 8(RSP) // push a10 onto stack67 MOVD R10, 8(RSP) // push a10 onto stack
68- MOVD syscall15Args_a11(R9), R1068+ MOVD syscallArgs_a11(R9), R10
69 MOVD R10, 16(RSP) // push a11 onto stack69 MOVD R10, 16(RSP) // push a11 onto stack
70- MOVD syscall15Args_a12(R9), R1070+ MOVD syscallArgs_a12(R9), R10
71 MOVD R10, 24(RSP) // push a12 onto stack71 MOVD R10, 24(RSP) // push a12 onto stack
72- MOVD syscall15Args_a13(R9), R1072+ MOVD syscallArgs_a13(R9), R10
73 MOVD R10, 32(RSP) // push a13 onto stack73 MOVD R10, 32(RSP) // push a13 onto stack
74- MOVD syscall15Args_a14(R9), R1074+ MOVD syscallArgs_a14(R9), R10
75 MOVD R10, 40(RSP) // push a14 onto stack75 MOVD R10, 40(RSP) // push a14 onto stack
76- MOVD syscall15Args_a15(R9), R1076+ MOVD syscallArgs_a15(R9), R10
77 MOVD R10, 48(RSP) // push a15 onto stack77 MOVD R10, 48(RSP) // push a15 onto stack
78+ MOVD syscallArgs_a16(R9), R10
79+ MOVD R10, 56(RSP) // push a16 onto stack
80+ MOVD syscallArgs_a17(R9), R10
81+ MOVD R10, 64(RSP) // push a17 onto stack
82+ MOVD syscallArgs_a18(R9), R10
83+ MOVD R10, 72(RSP) // push a18 onto stack
84+ MOVD syscallArgs_a19(R9), R10
85+ MOVD R10, 80(RSP) // push a19 onto stack
86+ MOVD syscallArgs_a20(R9), R10
87+ MOVD R10, 88(RSP) // push a20 onto stack
88+ MOVD syscallArgs_a21(R9), R10
89+ MOVD R10, 96(RSP) // push a21 onto stack
90+ MOVD syscallArgs_a22(R9), R10
91+ MOVD R10, 104(RSP) // push a22 onto stack
92+ MOVD syscallArgs_a23(R9), R10
93+ MOVD R10, 112(RSP) // push a23 onto stack
94+ MOVD syscallArgs_a24(R9), R10
95+ MOVD R10, 120(RSP) // push a24 onto stack
96+ MOVD syscallArgs_a25(R9), R10
97+ MOVD R10, 128(RSP) // push a25 onto stack
98+ MOVD syscallArgs_a26(R9), R10
99+ MOVD R10, 136(RSP) // push a26 onto stack
100+ MOVD syscallArgs_a27(R9), R10
101+ MOVD R10, 144(RSP) // push a27 onto stack
102+ MOVD syscallArgs_a28(R9), R10
103+ MOVD R10, 152(RSP) // push a28 onto stack
104+ MOVD syscallArgs_a29(R9), R10
105+ MOVD R10, 160(RSP) // push a29 onto stack
106+ MOVD syscallArgs_a30(R9), R10
107+ MOVD R10, 168(RSP) // push a30 onto stack
108+ MOVD syscallArgs_a31(R9), R10
109+ MOVD R10, 176(RSP) // push a31 onto stack
110+ MOVD syscallArgs_a32(R9), R10
111+ MOVD R10, 184(RSP) // push a32 onto stack
78 112
79- MOVD syscall15Args_fn(R9), R10 // fn113+ MOVD syscallArgs_fn(R9), R10 // fn
80 BL (R10)114 BL (R10)
81 115
82 MOVD PTR_ADDRESS(RSP), R2 // pop structure pointer116 MOVD PTR_ADDRESS(RSP), R2 // pop structure pointer
83 ADD $STACK_SIZE, RSP117 ADD $STACK_SIZE, RSP
84 118
85- MOVD R0, syscall15Args_a1(R2) // save r1119+ MOVD R0, syscallArgs_a1(R2) // save r1
86- MOVD R1, syscall15Args_a2(R2) // save r3120+ MOVD R1, syscallArgs_a2(R2) // save r3
87- FMOVD F0, syscall15Args_f1(R2) // save f0121+ FMOVD F0, syscallArgs_f1(R2) // save f0
88- FMOVD F1, syscall15Args_f2(R2) // save f1122+ FMOVD F1, syscallArgs_f2(R2) // save f1
89- FMOVD F2, syscall15Args_f3(R2) // save f2123+ FMOVD F2, syscallArgs_f3(R2) // save f2
90- FMOVD F3, syscall15Args_f4(R2) // save f3124+ FMOVD F3, syscallArgs_f4(R2) // save f3
91 125
92 #ifdef GOOS_darwin126 #ifdef GOOS_darwin
93 BL purego_error(SB)127 BL purego_error(SB)
94 MOVD (R0), R0128 MOVD (R0), R0
95- MOVD R0, syscall15Args_a3(R2) // save errno129+ MOVD R0, syscallArgs_a3(R2) // save errno
96 130
97 #endif131 #endif
98 RET132 RET
M sys_loong64.s +71 -37
@@ -7,11 +7,11 @@
77 #include "go_asm.h"
88 #include "funcdata.h"
99
10-#define STACK_SIZE 64
10+#define STACK_SIZE 208
1111 #define PTR_ADDRESS (STACK_SIZE - 8)
1212
13-// syscall15X calls a function in libc on behalf of the syscall package.
14-// syscall15X takes a pointer to a struct like:
13+// syscallX calls a function in libc on behalf of the syscall package.
14+// syscallX takes a pointer to a struct like:
1515 // struct {
1616 // fn uintptr
1717 // a1 uintptr
@@ -33,51 +33,85 @@
3333 // r2 uintptr
3434 // err uintptr
3535 // }
36-// syscall15X must be called on the g0 stack with the
36+// syscallX must be called on the g0 stack with the
3737 // C calling convention (use libcCall).
38-GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $8
39-DATA ·syscall15XABI0(SB)/8, $syscall15X(SB)
40-TEXT syscall15X(SB), NOSPLIT, $0
38+GLOBL ·syscallXABI0(SB), NOPTR|RODATA, $8
39+DATA ·syscallXABI0(SB)/8, $syscallX(SB)
40+TEXT syscallX(SB), NOSPLIT, $0
4141 // push structure pointer
4242 SUBV $STACK_SIZE, R3
4343 MOVV R4, PTR_ADDRESS(R3)
4444 MOVV R4, R13
4545
46- MOVD syscall15Args_f1(R13), F0 // f1
47- MOVD syscall15Args_f2(R13), F1 // f2
48- MOVD syscall15Args_f3(R13), F2 // f3
49- MOVD syscall15Args_f4(R13), F3 // f4
50- MOVD syscall15Args_f5(R13), F4 // f5
51- MOVD syscall15Args_f6(R13), F5 // f6
52- MOVD syscall15Args_f7(R13), F6 // f7
53- MOVD syscall15Args_f8(R13), F7 // f8
46+ MOVD syscallArgs_f1(R13), F0 // f1
47+ MOVD syscallArgs_f2(R13), F1 // f2
48+ MOVD syscallArgs_f3(R13), F2 // f3
49+ MOVD syscallArgs_f4(R13), F3 // f4
50+ MOVD syscallArgs_f5(R13), F4 // f5
51+ MOVD syscallArgs_f6(R13), F5 // f6
52+ MOVD syscallArgs_f7(R13), F6 // f7
53+ MOVD syscallArgs_f8(R13), F7 // f8
5454
55- MOVV syscall15Args_a1(R13), R4 // a1
56- MOVV syscall15Args_a2(R13), R5 // a2
57- MOVV syscall15Args_a3(R13), R6 // a3
58- MOVV syscall15Args_a4(R13), R7 // a4
59- MOVV syscall15Args_a5(R13), R8 // a5
60- MOVV syscall15Args_a6(R13), R9 // a6
61- MOVV syscall15Args_a7(R13), R10 // a7
62- MOVV syscall15Args_a8(R13), R11 // a8
55+ MOVV syscallArgs_a1(R13), R4 // a1
56+ MOVV syscallArgs_a2(R13), R5 // a2
57+ MOVV syscallArgs_a3(R13), R6 // a3
58+ MOVV syscallArgs_a4(R13), R7 // a4
59+ MOVV syscallArgs_a5(R13), R8 // a5
60+ MOVV syscallArgs_a6(R13), R9 // a6
61+ MOVV syscallArgs_a7(R13), R10 // a7
62+ MOVV syscallArgs_a8(R13), R11 // a8
6363
6464 // push a9-a15 onto stack
65- MOVV syscall15Args_a9(R13), R12
65+ MOVV syscallArgs_a9(R13), R12
6666 MOVV R12, 0(R3)
67- MOVV syscall15Args_a10(R13), R12
67+ MOVV syscallArgs_a10(R13), R12
6868 MOVV R12, 8(R3)
69- MOVV syscall15Args_a11(R13), R12
69+ MOVV syscallArgs_a11(R13), R12
7070 MOVV R12, 16(R3)
71- MOVV syscall15Args_a12(R13), R12
71+ MOVV syscallArgs_a12(R13), R12
7272 MOVV R12, 24(R3)
73- MOVV syscall15Args_a13(R13), R12
73+ MOVV syscallArgs_a13(R13), R12
7474 MOVV R12, 32(R3)
75- MOVV syscall15Args_a14(R13), R12
75+ MOVV syscallArgs_a14(R13), R12
7676 MOVV R12, 40(R3)
77- MOVV syscall15Args_a15(R13), R12
77+ MOVV syscallArgs_a15(R13), R12
7878 MOVV R12, 48(R3)
79+ MOVV syscallArgs_a16(R13), R12
80+ MOVV R12, 56(R3)
81+ MOVV syscallArgs_a17(R13), R12
82+ MOVV R12, 64(R3)
83+ MOVV syscallArgs_a18(R13), R12
84+ MOVV R12, 72(R3)
85+ MOVV syscallArgs_a19(R13), R12
86+ MOVV R12, 80(R3)
87+ MOVV syscallArgs_a20(R13), R12
88+ MOVV R12, 88(R3)
89+ MOVV syscallArgs_a21(R13), R12
90+ MOVV R12, 96(R3)
91+ MOVV syscallArgs_a22(R13), R12
92+ MOVV R12, 104(R3)
93+ MOVV syscallArgs_a23(R13), R12
94+ MOVV R12, 112(R3)
95+ MOVV syscallArgs_a24(R13), R12
96+ MOVV R12, 120(R3)
97+ MOVV syscallArgs_a25(R13), R12
98+ MOVV R12, 128(R3)
99+ MOVV syscallArgs_a26(R13), R12
100+ MOVV R12, 136(R3)
101+ MOVV syscallArgs_a27(R13), R12
102+ MOVV R12, 144(R3)
103+ MOVV syscallArgs_a28(R13), R12
104+ MOVV R12, 152(R3)
105+ MOVV syscallArgs_a29(R13), R12
106+ MOVV R12, 160(R3)
107+ MOVV syscallArgs_a30(R13), R12
108+ MOVV R12, 168(R3)
109+ MOVV syscallArgs_a31(R13), R12
110+ MOVV R12, 176(R3)
111+ MOVV syscallArgs_a32(R13), R12
112+ MOVV R12, 184(R3)
79113
80- MOVV syscall15Args_fn(R13), R12
114+ MOVV syscallArgs_fn(R13), R12
81115 JAL (R12)
82116
83117 // pop structure pointer
@@ -85,12 +119,12 @@ TEXT syscall15X(SB), NOSPLIT, $0
85119 ADDV $STACK_SIZE, R3
86120
87121 // save R4, R5
88- MOVV R4, syscall15Args_a1(R13)
89- MOVV R5, syscall15Args_a2(R13)
122+ MOVV R4, syscallArgs_a1(R13)
123+ MOVV R5, syscallArgs_a2(R13)
90124
91125 // save f0-f3
92- MOVD F0, syscall15Args_f1(R13)
93- MOVD F1, syscall15Args_f2(R13)
94- MOVD F2, syscall15Args_f3(R13)
95- MOVD F3, syscall15Args_f4(R13)
126+ MOVD F0, syscallArgs_f1(R13)
127+ MOVD F1, syscallArgs_f2(R13)
128+ MOVD F2, syscallArgs_f3(R13)
129+ MOVD F3, syscallArgs_f4(R13)
96130 RET
@@ -7,11 +7,11 @@
7 #include "go_asm.h"7 #include "go_asm.h"
8 #include "funcdata.h"8 #include "funcdata.h"
9 9
10-#define STACK_SIZE 6410+#define STACK_SIZE 208
11 #define PTR_ADDRESS (STACK_SIZE - 8)11 #define PTR_ADDRESS (STACK_SIZE - 8)
12 12
13-// syscall15X calls a function in libc on behalf of the syscall package.13+// syscallX calls a function in libc on behalf of the syscall package.
14-// syscall15X takes a pointer to a struct like:14+// syscallX takes a pointer to a struct like:
15 // struct {15 // struct {
16 // fn uintptr16 // fn uintptr
17 // a1 uintptr17 // a1 uintptr
@@ -33,51 +33,85 @@
33 // r2 uintptr33 // r2 uintptr
34 // err uintptr34 // err uintptr
35 // }35 // }
36-// syscall15X must be called on the g0 stack with the36+// syscallX must be called on the g0 stack with the
37 // C calling convention (use libcCall).37 // C calling convention (use libcCall).
38-GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $838+GLOBL ·syscallXABI0(SB), NOPTR|RODATA, $8
39-DATA ·syscall15XABI0(SB)/8, $syscall15X(SB)39+DATA ·syscallXABI0(SB)/8, $syscallX(SB)
40-TEXT syscall15X(SB), NOSPLIT, $040+TEXT syscallX(SB), NOSPLIT, $0
41 // push structure pointer41 // push structure pointer
42 SUBV $STACK_SIZE, R342 SUBV $STACK_SIZE, R3
43 MOVV R4, PTR_ADDRESS(R3)43 MOVV R4, PTR_ADDRESS(R3)
44 MOVV R4, R1344 MOVV R4, R13
45 45
46- MOVD syscall15Args_f1(R13), F0 // f146+ MOVD syscallArgs_f1(R13), F0 // f1
47- MOVD syscall15Args_f2(R13), F1 // f247+ MOVD syscallArgs_f2(R13), F1 // f2
48- MOVD syscall15Args_f3(R13), F2 // f348+ MOVD syscallArgs_f3(R13), F2 // f3
49- MOVD syscall15Args_f4(R13), F3 // f449+ MOVD syscallArgs_f4(R13), F3 // f4
50- MOVD syscall15Args_f5(R13), F4 // f550+ MOVD syscallArgs_f5(R13), F4 // f5
51- MOVD syscall15Args_f6(R13), F5 // f651+ MOVD syscallArgs_f6(R13), F5 // f6
52- MOVD syscall15Args_f7(R13), F6 // f752+ MOVD syscallArgs_f7(R13), F6 // f7
53- MOVD syscall15Args_f8(R13), F7 // f853+ MOVD syscallArgs_f8(R13), F7 // f8
54 54
55- MOVV syscall15Args_a1(R13), R4 // a155+ MOVV syscallArgs_a1(R13), R4 // a1
56- MOVV syscall15Args_a2(R13), R5 // a256+ MOVV syscallArgs_a2(R13), R5 // a2
57- MOVV syscall15Args_a3(R13), R6 // a357+ MOVV syscallArgs_a3(R13), R6 // a3
58- MOVV syscall15Args_a4(R13), R7 // a458+ MOVV syscallArgs_a4(R13), R7 // a4
59- MOVV syscall15Args_a5(R13), R8 // a559+ MOVV syscallArgs_a5(R13), R8 // a5
60- MOVV syscall15Args_a6(R13), R9 // a660+ MOVV syscallArgs_a6(R13), R9 // a6
61- MOVV syscall15Args_a7(R13), R10 // a761+ MOVV syscallArgs_a7(R13), R10 // a7
62- MOVV syscall15Args_a8(R13), R11 // a862+ MOVV syscallArgs_a8(R13), R11 // a8
63 63
64 // push a9-a15 onto stack64 // push a9-a15 onto stack
65- MOVV syscall15Args_a9(R13), R1265+ MOVV syscallArgs_a9(R13), R12
66 MOVV R12, 0(R3)66 MOVV R12, 0(R3)
67- MOVV syscall15Args_a10(R13), R1267+ MOVV syscallArgs_a10(R13), R12
68 MOVV R12, 8(R3)68 MOVV R12, 8(R3)
69- MOVV syscall15Args_a11(R13), R1269+ MOVV syscallArgs_a11(R13), R12
70 MOVV R12, 16(R3)70 MOVV R12, 16(R3)
71- MOVV syscall15Args_a12(R13), R1271+ MOVV syscallArgs_a12(R13), R12
72 MOVV R12, 24(R3)72 MOVV R12, 24(R3)
73- MOVV syscall15Args_a13(R13), R1273+ MOVV syscallArgs_a13(R13), R12
74 MOVV R12, 32(R3)74 MOVV R12, 32(R3)
75- MOVV syscall15Args_a14(R13), R1275+ MOVV syscallArgs_a14(R13), R12
76 MOVV R12, 40(R3)76 MOVV R12, 40(R3)
77- MOVV syscall15Args_a15(R13), R1277+ MOVV syscallArgs_a15(R13), R12
78 MOVV R12, 48(R3)78 MOVV R12, 48(R3)
79+ MOVV syscallArgs_a16(R13), R12
80+ MOVV R12, 56(R3)
81+ MOVV syscallArgs_a17(R13), R12
82+ MOVV R12, 64(R3)
83+ MOVV syscallArgs_a18(R13), R12
84+ MOVV R12, 72(R3)
85+ MOVV syscallArgs_a19(R13), R12
86+ MOVV R12, 80(R3)
87+ MOVV syscallArgs_a20(R13), R12
88+ MOVV R12, 88(R3)
89+ MOVV syscallArgs_a21(R13), R12
90+ MOVV R12, 96(R3)
91+ MOVV syscallArgs_a22(R13), R12
92+ MOVV R12, 104(R3)
93+ MOVV syscallArgs_a23(R13), R12
94+ MOVV R12, 112(R3)
95+ MOVV syscallArgs_a24(R13), R12
96+ MOVV R12, 120(R3)
97+ MOVV syscallArgs_a25(R13), R12
98+ MOVV R12, 128(R3)
99+ MOVV syscallArgs_a26(R13), R12
100+ MOVV R12, 136(R3)
101+ MOVV syscallArgs_a27(R13), R12
102+ MOVV R12, 144(R3)
103+ MOVV syscallArgs_a28(R13), R12
104+ MOVV R12, 152(R3)
105+ MOVV syscallArgs_a29(R13), R12
106+ MOVV R12, 160(R3)
107+ MOVV syscallArgs_a30(R13), R12
108+ MOVV R12, 168(R3)
109+ MOVV syscallArgs_a31(R13), R12
110+ MOVV R12, 176(R3)
111+ MOVV syscallArgs_a32(R13), R12
112+ MOVV R12, 184(R3)
79 113
80- MOVV syscall15Args_fn(R13), R12114+ MOVV syscallArgs_fn(R13), R12
81 JAL (R12)115 JAL (R12)
82 116
83 // pop structure pointer117 // pop structure pointer
@@ -85,12 +119,12 @@ TEXT syscall15X(SB), NOSPLIT, $0
85 ADDV $STACK_SIZE, R3119 ADDV $STACK_SIZE, R3
86 120
87 // save R4, R5121 // save R4, R5
88- MOVV R4, syscall15Args_a1(R13)122+ MOVV R4, syscallArgs_a1(R13)
89- MOVV R5, syscall15Args_a2(R13)123+ MOVV R5, syscallArgs_a2(R13)
90 124
91 // save f0-f3125 // save f0-f3
92- MOVD F0, syscall15Args_f1(R13)126+ MOVD F0, syscallArgs_f1(R13)
93- MOVD F1, syscall15Args_f2(R13)127+ MOVD F1, syscallArgs_f2(R13)
94- MOVD F2, syscall15Args_f3(R13)128+ MOVD F2, syscallArgs_f3(R13)
95- MOVD F3, syscall15Args_f4(R13)129+ MOVD F3, syscallArgs_f4(R13)
96 RET130 RET
M sys_ppc64le.s +34 -34
@@ -35,10 +35,10 @@
3535 #define TOC_SAVE 160
3636 #define ARGP_SAVE 168
3737
38-GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $8
39-DATA ·syscall15XABI0(SB)/8, $syscall15X(SB)
38+GLOBL ·syscallXABI0(SB), NOPTR|RODATA, $8
39+DATA ·syscallXABI0(SB)/8, $syscallX(SB)
4040
41-TEXT syscall15X(SB), NOSPLIT, $0
41+TEXT syscallX(SB), NOSPLIT, $0
4242 // Prologue: create stack frame
4343 // R3 contains the args pointer on entry
4444 MOVD R1, R12 // save old SP
@@ -51,49 +51,49 @@ TEXT syscall15X(SB), NOSPLIT, $0
5151 // Save args pointer (in R3)
5252 MOVD R3, ARGP_SAVE(R1)
5353
54- // R11 := args pointer (syscall15Args*)
54+ // R11 := args pointer (syscallArgs*)
5555 MOVD R3, R11
5656
5757 // Load float args into F1-F8
58- FMOVD syscall15Args_f1(R11), F1
59- FMOVD syscall15Args_f2(R11), F2
60- FMOVD syscall15Args_f3(R11), F3
61- FMOVD syscall15Args_f4(R11), F4
62- FMOVD syscall15Args_f5(R11), F5
63- FMOVD syscall15Args_f6(R11), F6
64- FMOVD syscall15Args_f7(R11), F7
65- FMOVD syscall15Args_f8(R11), F8
58+ FMOVD syscallArgs_f1(R11), F1
59+ FMOVD syscallArgs_f2(R11), F2
60+ FMOVD syscallArgs_f3(R11), F3
61+ FMOVD syscallArgs_f4(R11), F4
62+ FMOVD syscallArgs_f5(R11), F5
63+ FMOVD syscallArgs_f6(R11), F6
64+ FMOVD syscallArgs_f7(R11), F7
65+ FMOVD syscallArgs_f8(R11), F8
6666
6767 // Load integer args into R3-R10
68- MOVD syscall15Args_a1(R11), R3
69- MOVD syscall15Args_a2(R11), R4
70- MOVD syscall15Args_a3(R11), R5
71- MOVD syscall15Args_a4(R11), R6
72- MOVD syscall15Args_a5(R11), R7
73- MOVD syscall15Args_a6(R11), R8
74- MOVD syscall15Args_a7(R11), R9
75- MOVD syscall15Args_a8(R11), R10
68+ MOVD syscallArgs_a1(R11), R3
69+ MOVD syscallArgs_a2(R11), R4
70+ MOVD syscallArgs_a3(R11), R5
71+ MOVD syscallArgs_a4(R11), R6
72+ MOVD syscallArgs_a5(R11), R7
73+ MOVD syscallArgs_a6(R11), R8
74+ MOVD syscallArgs_a7(R11), R9
75+ MOVD syscallArgs_a8(R11), R10
7676
7777 // Spill a9-a15 onto the stack (stack parameters start at 96(R1))
7878 // Per ELFv2: parameter save area is 32-95, stack args start at 96
7979 MOVD ARGP_SAVE(R1), R11 // reload args pointer
80- MOVD syscall15Args_a9(R11), R12
80+ MOVD syscallArgs_a9(R11), R12
8181 MOVD R12, 96(R1) // a9 at 96(R1)
82- MOVD syscall15Args_a10(R11), R12
82+ MOVD syscallArgs_a10(R11), R12
8383 MOVD R12, 104(R1) // a10 at 104(R1)
84- MOVD syscall15Args_a11(R11), R12
84+ MOVD syscallArgs_a11(R11), R12
8585 MOVD R12, 112(R1) // a11 at 112(R1)
86- MOVD syscall15Args_a12(R11), R12
86+ MOVD syscallArgs_a12(R11), R12
8787 MOVD R12, 120(R1) // a12 at 120(R1)
88- MOVD syscall15Args_a13(R11), R12
88+ MOVD syscallArgs_a13(R11), R12
8989 MOVD R12, 128(R1) // a13 at 128(R1)
90- MOVD syscall15Args_a14(R11), R12
90+ MOVD syscallArgs_a14(R11), R12
9191 MOVD R12, 136(R1) // a14 at 136(R1)
92- MOVD syscall15Args_a15(R11), R12
92+ MOVD syscallArgs_a15(R11), R12
9393 MOVD R12, 144(R1) // a15 at 144(R1)
9494
9595 // Call function: load fn and call
96- MOVD syscall15Args_fn(R11), R12
96+ MOVD syscallArgs_fn(R11), R12
9797 MOVD R12, CTR
9898 BL (CTR)
9999
@@ -104,14 +104,14 @@ TEXT syscall15X(SB), NOSPLIT, $0
104104 MOVD ARGP_SAVE(R1), R11
105105
106106 // Store integer results back (R3, R4)
107- MOVD R3, syscall15Args_a1(R11)
108- MOVD R4, syscall15Args_a2(R11)
107+ MOVD R3, syscallArgs_a1(R11)
108+ MOVD R4, syscallArgs_a2(R11)
109109
110110 // Store float return values (F1-F4)
111- FMOVD F1, syscall15Args_f1(R11)
112- FMOVD F2, syscall15Args_f2(R11)
113- FMOVD F3, syscall15Args_f3(R11)
114- FMOVD F4, syscall15Args_f4(R11)
111+ FMOVD F1, syscallArgs_f1(R11)
112+ FMOVD F2, syscallArgs_f2(R11)
113+ FMOVD F3, syscallArgs_f3(R11)
114+ FMOVD F4, syscallArgs_f4(R11)
115115
116116 // Epilogue: restore and return
117117 MOVD LR_SAVE(R1), R12
@@ -35,10 +35,10 @@
35 #define TOC_SAVE 16035 #define TOC_SAVE 160
36 #define ARGP_SAVE 16836 #define ARGP_SAVE 168
37 37
38-GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $838+GLOBL ·syscallXABI0(SB), NOPTR|RODATA, $8
39-DATA ·syscall15XABI0(SB)/8, $syscall15X(SB)39+DATA ·syscallXABI0(SB)/8, $syscallX(SB)
40 40
41-TEXT syscall15X(SB), NOSPLIT, $041+TEXT syscallX(SB), NOSPLIT, $0
42 // Prologue: create stack frame42 // Prologue: create stack frame
43 // R3 contains the args pointer on entry43 // R3 contains the args pointer on entry
44 MOVD R1, R12 // save old SP44 MOVD R1, R12 // save old SP
@@ -51,49 +51,49 @@ TEXT syscall15X(SB), NOSPLIT, $0
51 // Save args pointer (in R3)51 // Save args pointer (in R3)
52 MOVD R3, ARGP_SAVE(R1)52 MOVD R3, ARGP_SAVE(R1)
53 53
54- // R11 := args pointer (syscall15Args*)54+ // R11 := args pointer (syscallArgs*)
55 MOVD R3, R1155 MOVD R3, R11
56 56
57 // Load float args into F1-F857 // Load float args into F1-F8
58- FMOVD syscall15Args_f1(R11), F158+ FMOVD syscallArgs_f1(R11), F1
59- FMOVD syscall15Args_f2(R11), F259+ FMOVD syscallArgs_f2(R11), F2
60- FMOVD syscall15Args_f3(R11), F360+ FMOVD syscallArgs_f3(R11), F3
61- FMOVD syscall15Args_f4(R11), F461+ FMOVD syscallArgs_f4(R11), F4
62- FMOVD syscall15Args_f5(R11), F562+ FMOVD syscallArgs_f5(R11), F5
63- FMOVD syscall15Args_f6(R11), F663+ FMOVD syscallArgs_f6(R11), F6
64- FMOVD syscall15Args_f7(R11), F764+ FMOVD syscallArgs_f7(R11), F7
65- FMOVD syscall15Args_f8(R11), F865+ FMOVD syscallArgs_f8(R11), F8
66 66
67 // Load integer args into R3-R1067 // Load integer args into R3-R10
68- MOVD syscall15Args_a1(R11), R368+ MOVD syscallArgs_a1(R11), R3
69- MOVD syscall15Args_a2(R11), R469+ MOVD syscallArgs_a2(R11), R4
70- MOVD syscall15Args_a3(R11), R570+ MOVD syscallArgs_a3(R11), R5
71- MOVD syscall15Args_a4(R11), R671+ MOVD syscallArgs_a4(R11), R6
72- MOVD syscall15Args_a5(R11), R772+ MOVD syscallArgs_a5(R11), R7
73- MOVD syscall15Args_a6(R11), R873+ MOVD syscallArgs_a6(R11), R8
74- MOVD syscall15Args_a7(R11), R974+ MOVD syscallArgs_a7(R11), R9
75- MOVD syscall15Args_a8(R11), R1075+ MOVD syscallArgs_a8(R11), R10
76 76
77 // Spill a9-a15 onto the stack (stack parameters start at 96(R1))77 // Spill a9-a15 onto the stack (stack parameters start at 96(R1))
78 // Per ELFv2: parameter save area is 32-95, stack args start at 9678 // Per ELFv2: parameter save area is 32-95, stack args start at 96
79 MOVD ARGP_SAVE(R1), R11 // reload args pointer79 MOVD ARGP_SAVE(R1), R11 // reload args pointer
80- MOVD syscall15Args_a9(R11), R1280+ MOVD syscallArgs_a9(R11), R12
81 MOVD R12, 96(R1) // a9 at 96(R1)81 MOVD R12, 96(R1) // a9 at 96(R1)
82- MOVD syscall15Args_a10(R11), R1282+ MOVD syscallArgs_a10(R11), R12
83 MOVD R12, 104(R1) // a10 at 104(R1)83 MOVD R12, 104(R1) // a10 at 104(R1)
84- MOVD syscall15Args_a11(R11), R1284+ MOVD syscallArgs_a11(R11), R12
85 MOVD R12, 112(R1) // a11 at 112(R1)85 MOVD R12, 112(R1) // a11 at 112(R1)
86- MOVD syscall15Args_a12(R11), R1286+ MOVD syscallArgs_a12(R11), R12
87 MOVD R12, 120(R1) // a12 at 120(R1)87 MOVD R12, 120(R1) // a12 at 120(R1)
88- MOVD syscall15Args_a13(R11), R1288+ MOVD syscallArgs_a13(R11), R12
89 MOVD R12, 128(R1) // a13 at 128(R1)89 MOVD R12, 128(R1) // a13 at 128(R1)
90- MOVD syscall15Args_a14(R11), R1290+ MOVD syscallArgs_a14(R11), R12
91 MOVD R12, 136(R1) // a14 at 136(R1)91 MOVD R12, 136(R1) // a14 at 136(R1)
92- MOVD syscall15Args_a15(R11), R1292+ MOVD syscallArgs_a15(R11), R12
93 MOVD R12, 144(R1) // a15 at 144(R1)93 MOVD R12, 144(R1) // a15 at 144(R1)
94 94
95 // Call function: load fn and call95 // Call function: load fn and call
96- MOVD syscall15Args_fn(R11), R1296+ MOVD syscallArgs_fn(R11), R12
97 MOVD R12, CTR97 MOVD R12, CTR
98 BL (CTR)98 BL (CTR)
99 99
@@ -104,14 +104,14 @@ TEXT syscall15X(SB), NOSPLIT, $0
104 MOVD ARGP_SAVE(R1), R11104 MOVD ARGP_SAVE(R1), R11
105 105
106 // Store integer results back (R3, R4)106 // Store integer results back (R3, R4)
107- MOVD R3, syscall15Args_a1(R11)107+ MOVD R3, syscallArgs_a1(R11)
108- MOVD R4, syscall15Args_a2(R11)108+ MOVD R4, syscallArgs_a2(R11)
109 109
110 // Store float return values (F1-F4)110 // Store float return values (F1-F4)
111- FMOVD F1, syscall15Args_f1(R11)111+ FMOVD F1, syscallArgs_f1(R11)
112- FMOVD F2, syscall15Args_f2(R11)112+ FMOVD F2, syscallArgs_f2(R11)
113- FMOVD F3, syscall15Args_f3(R11)113+ FMOVD F3, syscallArgs_f3(R11)
114- FMOVD F4, syscall15Args_f4(R11)114+ FMOVD F4, syscallArgs_f4(R11)
115 115
116 // Epilogue: restore and return116 // Epilogue: restore and return
117 MOVD LR_SAVE(R1), R12117 MOVD LR_SAVE(R1), R12
M sys_riscv64.s +83 -50
@@ -8,22 +8,21 @@
88 #include "funcdata.h"
99
1010 // Stack usage:
11-// 0(SP) - 56(SP): stack args a9-a15 (7 * 8 bytes = 56)
12-// 56(SP) - 64(SP): saved RA (x1)
13-// 64(SP) - 72(SP): saved X9 (s1)
14-// 72(SP) - 80(SP): saved X18 (s2)
15-// 80(SP) - 88(SP): saved args pointer (original X10)
16-// 88(SP) - 96(SP): padding
17-#define STACK_SIZE 96
18-#define SAVE_RA 56
19-#define SAVE_X9 64
20-#define SAVE_X18 72
21-#define SAVE_ARGP 80
22-
23-GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $8
24-DATA ·syscall15XABI0(SB)/8, $syscall15X(SB)
25-
26-TEXT syscall15X(SB), NOSPLIT, $0
11+// 0(SP) - 192(SP): stack args a9-a32 (24 * 8 bytes)
12+// 192(SP) - 200(SP): saved RA (x1)
13+// 200(SP) - 208(SP): saved X9 (s1)
14+// 208(SP) - 216(SP): saved X18 (s2)
15+// 216(SP) - 224(SP): saved args pointer (original X10)
16+#define STACK_SIZE 224
17+#define SAVE_RA 192
18+#define SAVE_X9 200
19+#define SAVE_X18 208
20+#define SAVE_ARGP 216
21+
22+GLOBL ·syscallXABI0(SB), NOPTR|RODATA, $8
23+DATA ·syscallXABI0(SB)/8, $syscallX(SB)
24+
25+TEXT syscallX(SB), NOSPLIT, $0
2726 // Allocate stack frame (keeps 16-byte alignment)
2827 SUB $STACK_SIZE, SP
2928
@@ -35,62 +34,96 @@ TEXT syscall15X(SB), NOSPLIT, $0
3534 // Save original args pointer (in a0/X10)
3635 MOV X10, SAVE_ARGP(SP)
3736
38- // X9 := args pointer (syscall15Args*)
37+ // X9 := args pointer (syscallArgs*)
3938 MOV X10, X9
4039
4140 // Load float args into fa0-fa7 (F10-F17)
42- MOVD syscall15Args_f1(X9), F10
43- MOVD syscall15Args_f2(X9), F11
44- MOVD syscall15Args_f3(X9), F12
45- MOVD syscall15Args_f4(X9), F13
46- MOVD syscall15Args_f5(X9), F14
47- MOVD syscall15Args_f6(X9), F15
48- MOVD syscall15Args_f7(X9), F16
49- MOVD syscall15Args_f8(X9), F17
41+ MOVD syscallArgs_f1(X9), F10
42+ MOVD syscallArgs_f2(X9), F11
43+ MOVD syscallArgs_f3(X9), F12
44+ MOVD syscallArgs_f4(X9), F13
45+ MOVD syscallArgs_f5(X9), F14
46+ MOVD syscallArgs_f6(X9), F15
47+ MOVD syscallArgs_f7(X9), F16
48+ MOVD syscallArgs_f8(X9), F17
5049
5150 // Load integer args into a0-a7 (X10-X17)
52- MOV syscall15Args_a1(X9), X10
53- MOV syscall15Args_a2(X9), X11
54- MOV syscall15Args_a3(X9), X12
55- MOV syscall15Args_a4(X9), X13
56- MOV syscall15Args_a5(X9), X14
57- MOV syscall15Args_a6(X9), X15
58- MOV syscall15Args_a7(X9), X16
59- MOV syscall15Args_a8(X9), X17
60-
61- // Spill a9-a15 onto the stack (C ABI)
62- MOV syscall15Args_a9(X9), X18
51+ MOV syscallArgs_a1(X9), X10
52+ MOV syscallArgs_a2(X9), X11
53+ MOV syscallArgs_a3(X9), X12
54+ MOV syscallArgs_a4(X9), X13
55+ MOV syscallArgs_a5(X9), X14
56+ MOV syscallArgs_a6(X9), X15
57+ MOV syscallArgs_a7(X9), X16
58+ MOV syscallArgs_a8(X9), X17
59+
60+ // Spill a9-a32 onto the stack (C ABI)
61+ MOV syscallArgs_a9(X9), X18
6362 MOV X18, 0(SP)
64- MOV syscall15Args_a10(X9), X18
63+ MOV syscallArgs_a10(X9), X18
6564 MOV X18, 8(SP)
66- MOV syscall15Args_a11(X9), X18
65+ MOV syscallArgs_a11(X9), X18
6766 MOV X18, 16(SP)
68- MOV syscall15Args_a12(X9), X18
67+ MOV syscallArgs_a12(X9), X18
6968 MOV X18, 24(SP)
70- MOV syscall15Args_a13(X9), X18
69+ MOV syscallArgs_a13(X9), X18
7170 MOV X18, 32(SP)
72- MOV syscall15Args_a14(X9), X18
71+ MOV syscallArgs_a14(X9), X18
7372 MOV X18, 40(SP)
74- MOV syscall15Args_a15(X9), X18
73+ MOV syscallArgs_a15(X9), X18
7574 MOV X18, 48(SP)
75+ MOV syscallArgs_a16(X9), X18
76+ MOV X18, 56(SP)
77+ MOV syscallArgs_a17(X9), X18
78+ MOV X18, 64(SP)
79+ MOV syscallArgs_a18(X9), X18
80+ MOV X18, 72(SP)
81+ MOV syscallArgs_a19(X9), X18
82+ MOV X18, 80(SP)
83+ MOV syscallArgs_a20(X9), X18
84+ MOV X18, 88(SP)
85+ MOV syscallArgs_a21(X9), X18
86+ MOV X18, 96(SP)
87+ MOV syscallArgs_a22(X9), X18
88+ MOV X18, 104(SP)
89+ MOV syscallArgs_a23(X9), X18
90+ MOV X18, 112(SP)
91+ MOV syscallArgs_a24(X9), X18
92+ MOV X18, 120(SP)
93+ MOV syscallArgs_a25(X9), X18
94+ MOV X18, 128(SP)
95+ MOV syscallArgs_a26(X9), X18
96+ MOV X18, 136(SP)
97+ MOV syscallArgs_a27(X9), X18
98+ MOV X18, 144(SP)
99+ MOV syscallArgs_a28(X9), X18
100+ MOV X18, 152(SP)
101+ MOV syscallArgs_a29(X9), X18
102+ MOV X18, 160(SP)
103+ MOV syscallArgs_a30(X9), X18
104+ MOV X18, 168(SP)
105+ MOV syscallArgs_a31(X9), X18
106+ MOV X18, 176(SP)
107+ MOV syscallArgs_a32(X9), X18
108+ MOV X18, 184(SP)
76109
77110 // Call fn
78111 // IMPORTANT: preserve RA across this call (we saved it above)
79- MOV syscall15Args_fn(X9), X18
112+ MOV syscallArgs_fn(X9), X18
80113 CALL X18
81114
82- // Restore args pointer (syscall15Args*) for storing results
115+ // Restore args pointer (syscallArgs*) for storing results
83116 MOV SAVE_ARGP(SP), X9
84117
85118 // Store results back
86- MOV X10, syscall15Args_a1(X9)
87- MOV X11, syscall15Args_a2(X9)
119+ MOV X10, syscallArgs_a1(X9)
120+ MOV X11, syscallArgs_a2(X9)
88121
89122 // Store back float return regs if used by your ABI contract
90- MOVD F10, syscall15Args_f1(X9)
91- MOVD F11, syscall15Args_f2(X9)
92- MOVD F12, syscall15Args_f3(X9)
93- MOVD F13, syscall15Args_f4(X9)
123+ MOVD F10, syscallArgs_f1(X9)
124+ MOVD F11, syscallArgs_f2(X9)
125+ MOVD F12, syscallArgs_f3(X9)
126+ MOVD F13, syscallArgs_f4(X9)
94127
95128 // Restore callee-saved regs and return address
96129 MOV SAVE_X18(SP), X18
@@ -8,22 +8,21 @@
8 #include "funcdata.h"8 #include "funcdata.h"
9 9
10 // Stack usage:10 // Stack usage:
11-// 0(SP) - 56(SP): stack args a9-a15 (7 * 8 bytes = 56)11+// 0(SP) - 192(SP): stack args a9-a32 (24 * 8 bytes)
12-// 56(SP) - 64(SP): saved RA (x1)12+// 192(SP) - 200(SP): saved RA (x1)
13-// 64(SP) - 72(SP): saved X9 (s1)13+// 200(SP) - 208(SP): saved X9 (s1)
14-// 72(SP) - 80(SP): saved X18 (s2)14+// 208(SP) - 216(SP): saved X18 (s2)
15-// 80(SP) - 88(SP): saved args pointer (original X10)15+// 216(SP) - 224(SP): saved args pointer (original X10)
16-// 88(SP) - 96(SP): padding16+#define STACK_SIZE 224
17-#define STACK_SIZE 9617+#define SAVE_RA 192
18-#define SAVE_RA 5618+#define SAVE_X9 200
19-#define SAVE_X9 6419+#define SAVE_X18 208
20-#define SAVE_X18 7220+#define SAVE_ARGP 216
21-#define SAVE_ARGP 8021+
22-22+GLOBL ·syscallXABI0(SB), NOPTR|RODATA, $8
23-GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $823+DATA ·syscallXABI0(SB)/8, $syscallX(SB)
24-DATA ·syscall15XABI0(SB)/8, $syscall15X(SB)24+
25-25+TEXT syscallX(SB), NOSPLIT, $0
26-TEXT syscall15X(SB), NOSPLIT, $0
27 // Allocate stack frame (keeps 16-byte alignment)26 // Allocate stack frame (keeps 16-byte alignment)
28 SUB $STACK_SIZE, SP27 SUB $STACK_SIZE, SP
29 28
@@ -35,62 +34,96 @@ TEXT syscall15X(SB), NOSPLIT, $0
35 // Save original args pointer (in a0/X10)34 // Save original args pointer (in a0/X10)
36 MOV X10, SAVE_ARGP(SP)35 MOV X10, SAVE_ARGP(SP)
37 36
38- // X9 := args pointer (syscall15Args*)37+ // X9 := args pointer (syscallArgs*)
39 MOV X10, X938 MOV X10, X9
40 39
41 // Load float args into fa0-fa7 (F10-F17)40 // Load float args into fa0-fa7 (F10-F17)
42- MOVD syscall15Args_f1(X9), F1041+ MOVD syscallArgs_f1(X9), F10
43- MOVD syscall15Args_f2(X9), F1142+ MOVD syscallArgs_f2(X9), F11
44- MOVD syscall15Args_f3(X9), F1243+ MOVD syscallArgs_f3(X9), F12
45- MOVD syscall15Args_f4(X9), F1344+ MOVD syscallArgs_f4(X9), F13
46- MOVD syscall15Args_f5(X9), F1445+ MOVD syscallArgs_f5(X9), F14
47- MOVD syscall15Args_f6(X9), F1546+ MOVD syscallArgs_f6(X9), F15
48- MOVD syscall15Args_f7(X9), F1647+ MOVD syscallArgs_f7(X9), F16
49- MOVD syscall15Args_f8(X9), F1748+ MOVD syscallArgs_f8(X9), F17
50 49
51 // Load integer args into a0-a7 (X10-X17)50 // Load integer args into a0-a7 (X10-X17)
52- MOV syscall15Args_a1(X9), X1051+ MOV syscallArgs_a1(X9), X10
53- MOV syscall15Args_a2(X9), X1152+ MOV syscallArgs_a2(X9), X11
54- MOV syscall15Args_a3(X9), X1253+ MOV syscallArgs_a3(X9), X12
55- MOV syscall15Args_a4(X9), X1354+ MOV syscallArgs_a4(X9), X13
56- MOV syscall15Args_a5(X9), X1455+ MOV syscallArgs_a5(X9), X14
57- MOV syscall15Args_a6(X9), X1556+ MOV syscallArgs_a6(X9), X15
58- MOV syscall15Args_a7(X9), X1657+ MOV syscallArgs_a7(X9), X16
59- MOV syscall15Args_a8(X9), X1758+ MOV syscallArgs_a8(X9), X17
60-59+
61- // Spill a9-a15 onto the stack (C ABI)60+ // Spill a9-a32 onto the stack (C ABI)
62- MOV syscall15Args_a9(X9), X1861+ MOV syscallArgs_a9(X9), X18
63 MOV X18, 0(SP)62 MOV X18, 0(SP)
64- MOV syscall15Args_a10(X9), X1863+ MOV syscallArgs_a10(X9), X18
65 MOV X18, 8(SP)64 MOV X18, 8(SP)
66- MOV syscall15Args_a11(X9), X1865+ MOV syscallArgs_a11(X9), X18
67 MOV X18, 16(SP)66 MOV X18, 16(SP)
68- MOV syscall15Args_a12(X9), X1867+ MOV syscallArgs_a12(X9), X18
69 MOV X18, 24(SP)68 MOV X18, 24(SP)
70- MOV syscall15Args_a13(X9), X1869+ MOV syscallArgs_a13(X9), X18
71 MOV X18, 32(SP)70 MOV X18, 32(SP)
72- MOV syscall15Args_a14(X9), X1871+ MOV syscallArgs_a14(X9), X18
73 MOV X18, 40(SP)72 MOV X18, 40(SP)
74- MOV syscall15Args_a15(X9), X1873+ MOV syscallArgs_a15(X9), X18
75 MOV X18, 48(SP)74 MOV X18, 48(SP)
75+ MOV syscallArgs_a16(X9), X18
76+ MOV X18, 56(SP)
77+ MOV syscallArgs_a17(X9), X18
78+ MOV X18, 64(SP)
79+ MOV syscallArgs_a18(X9), X18
80+ MOV X18, 72(SP)
81+ MOV syscallArgs_a19(X9), X18
82+ MOV X18, 80(SP)
83+ MOV syscallArgs_a20(X9), X18
84+ MOV X18, 88(SP)
85+ MOV syscallArgs_a21(X9), X18
86+ MOV X18, 96(SP)
87+ MOV syscallArgs_a22(X9), X18
88+ MOV X18, 104(SP)
89+ MOV syscallArgs_a23(X9), X18
90+ MOV X18, 112(SP)
91+ MOV syscallArgs_a24(X9), X18
92+ MOV X18, 120(SP)
93+ MOV syscallArgs_a25(X9), X18
94+ MOV X18, 128(SP)
95+ MOV syscallArgs_a26(X9), X18
96+ MOV X18, 136(SP)
97+ MOV syscallArgs_a27(X9), X18
98+ MOV X18, 144(SP)
99+ MOV syscallArgs_a28(X9), X18
100+ MOV X18, 152(SP)
101+ MOV syscallArgs_a29(X9), X18
102+ MOV X18, 160(SP)
103+ MOV syscallArgs_a30(X9), X18
104+ MOV X18, 168(SP)
105+ MOV syscallArgs_a31(X9), X18
106+ MOV X18, 176(SP)
107+ MOV syscallArgs_a32(X9), X18
108+ MOV X18, 184(SP)
76 109
77 // Call fn110 // Call fn
78 // IMPORTANT: preserve RA across this call (we saved it above)111 // IMPORTANT: preserve RA across this call (we saved it above)
79- MOV syscall15Args_fn(X9), X18112+ MOV syscallArgs_fn(X9), X18
80 CALL X18113 CALL X18
81 114
82- // Restore args pointer (syscall15Args*) for storing results115+ // Restore args pointer (syscallArgs*) for storing results
83 MOV SAVE_ARGP(SP), X9116 MOV SAVE_ARGP(SP), X9
84 117
85 // Store results back118 // Store results back
86- MOV X10, syscall15Args_a1(X9)119+ MOV X10, syscallArgs_a1(X9)
87- MOV X11, syscall15Args_a2(X9)120+ MOV X11, syscallArgs_a2(X9)
88 121
89 // Store back float return regs if used by your ABI contract122 // Store back float return regs if used by your ABI contract
90- MOVD F10, syscall15Args_f1(X9)123+ MOVD F10, syscallArgs_f1(X9)
91- MOVD F11, syscall15Args_f2(X9)124+ MOVD F11, syscallArgs_f2(X9)
92- MOVD F12, syscall15Args_f3(X9)125+ MOVD F12, syscallArgs_f3(X9)
93- MOVD F13, syscall15Args_f4(X9)126+ MOVD F13, syscallArgs_f4(X9)
94 127
95 // Restore callee-saved regs and return address128 // Restore callee-saved regs and return address
96 MOV SAVE_X18(SP), X18129 MOV SAVE_X18(SP), X18
M sys_s390x.s +69 -36
@@ -24,19 +24,18 @@
2424 //
2525 // We need space for:
2626 // - 160 bytes standard frame (with register save area)
27-// - Stack args a6-a15 (10 * 8 = 80 bytes)
27+// - Stack args a6-a32 (27 * 8 = 216 bytes)
2828 // - Saved args pointer (8 bytes)
29-// - Padding for alignment
30-// Total: 264 bytes (rounded to 8-byte alignment)
29+// Total: 384 bytes
3130
32-#define STACK_SIZE 264
31+#define STACK_SIZE 384
3332 #define STACK_ARGS 160
34-#define ARGP_SAVE 248
33+#define ARGP_SAVE 376
3534
36-GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $8
37-DATA ·syscall15XABI0(SB)/8, $syscall15X(SB)
35+GLOBL ·syscallXABI0(SB), NOPTR|RODATA, $8
36+DATA ·syscallXABI0(SB)/8, $syscallX(SB)
3837
39-TEXT syscall15X(SB), NOSPLIT, $0
38+TEXT syscallX(SB), NOSPLIT, $0
4039 // On entry, R2 contains the args pointer
4140 // Save callee-saved registers in caller's frame (per ABI)
4241 STMG R6, R15, 48(R15)
@@ -49,61 +48,95 @@ TEXT syscall15X(SB), NOSPLIT, $0
4948 // Save args pointer
5049 MOVD R2, ARGP_SAVE(R15)
5150
52- // R9 := args pointer (syscall15Args*)
51+ // R9 := args pointer (syscallArgs*)
5352 MOVD R2, R9
5453
5554 // Load float args into F0, F2, F4, F6 (s390x uses even-numbered FPRs)
56- FMOVD syscall15Args_f1(R9), F0
57- FMOVD syscall15Args_f2(R9), F2
58- FMOVD syscall15Args_f3(R9), F4
59- FMOVD syscall15Args_f4(R9), F6
55+ FMOVD syscallArgs_f1(R9), F0
56+ FMOVD syscallArgs_f2(R9), F2
57+ FMOVD syscallArgs_f3(R9), F4
58+ FMOVD syscallArgs_f4(R9), F6
6059
6160 // Load integer args into R2-R6 (5 registers)
62- MOVD syscall15Args_a1(R9), R2
63- MOVD syscall15Args_a2(R9), R3
64- MOVD syscall15Args_a3(R9), R4
65- MOVD syscall15Args_a4(R9), R5
66- MOVD syscall15Args_a5(R9), R6
61+ MOVD syscallArgs_a1(R9), R2
62+ MOVD syscallArgs_a2(R9), R3
63+ MOVD syscallArgs_a3(R9), R4
64+ MOVD syscallArgs_a4(R9), R5
65+ MOVD syscallArgs_a5(R9), R6
6766
68- // Spill remaining args (a6-a15) onto the stack at 160(R15)
67+ // Spill remaining args (a6-a32) onto the stack at 160(R15)
6968 MOVD ARGP_SAVE(R15), R9 // reload args pointer
70- MOVD syscall15Args_a6(R9), R1
69+ MOVD syscallArgs_a6(R9), R1
7170 MOVD R1, (STACK_ARGS+0*8)(R15)
72- MOVD syscall15Args_a7(R9), R1
71+ MOVD syscallArgs_a7(R9), R1
7372 MOVD R1, (STACK_ARGS+1*8)(R15)
74- MOVD syscall15Args_a8(R9), R1
73+ MOVD syscallArgs_a8(R9), R1
7574 MOVD R1, (STACK_ARGS+2*8)(R15)
76- MOVD syscall15Args_a9(R9), R1
75+ MOVD syscallArgs_a9(R9), R1
7776 MOVD R1, (STACK_ARGS+3*8)(R15)
78- MOVD syscall15Args_a10(R9), R1
77+ MOVD syscallArgs_a10(R9), R1
7978 MOVD R1, (STACK_ARGS+4*8)(R15)
80- MOVD syscall15Args_a11(R9), R1
79+ MOVD syscallArgs_a11(R9), R1
8180 MOVD R1, (STACK_ARGS+5*8)(R15)
82- MOVD syscall15Args_a12(R9), R1
81+ MOVD syscallArgs_a12(R9), R1
8382 MOVD R1, (STACK_ARGS+6*8)(R15)
84- MOVD syscall15Args_a13(R9), R1
83+ MOVD syscallArgs_a13(R9), R1
8584 MOVD R1, (STACK_ARGS+7*8)(R15)
86- MOVD syscall15Args_a14(R9), R1
85+ MOVD syscallArgs_a14(R9), R1
8786 MOVD R1, (STACK_ARGS+8*8)(R15)
88- MOVD syscall15Args_a15(R9), R1
87+ MOVD syscallArgs_a15(R9), R1
8988 MOVD R1, (STACK_ARGS+9*8)(R15)
89+ MOVD syscallArgs_a16(R9), R1
90+ MOVD R1, (STACK_ARGS+10*8)(R15)
91+ MOVD syscallArgs_a17(R9), R1
92+ MOVD R1, (STACK_ARGS+11*8)(R15)
93+ MOVD syscallArgs_a18(R9), R1
94+ MOVD R1, (STACK_ARGS+12*8)(R15)
95+ MOVD syscallArgs_a19(R9), R1
96+ MOVD R1, (STACK_ARGS+13*8)(R15)
97+ MOVD syscallArgs_a20(R9), R1
98+ MOVD R1, (STACK_ARGS+14*8)(R15)
99+ MOVD syscallArgs_a21(R9), R1
100+ MOVD R1, (STACK_ARGS+15*8)(R15)
101+ MOVD syscallArgs_a22(R9), R1
102+ MOVD R1, (STACK_ARGS+16*8)(R15)
103+ MOVD syscallArgs_a23(R9), R1
104+ MOVD R1, (STACK_ARGS+17*8)(R15)
105+ MOVD syscallArgs_a24(R9), R1
106+ MOVD R1, (STACK_ARGS+18*8)(R15)
107+ MOVD syscallArgs_a25(R9), R1
108+ MOVD R1, (STACK_ARGS+19*8)(R15)
109+ MOVD syscallArgs_a26(R9), R1
110+ MOVD R1, (STACK_ARGS+20*8)(R15)
111+ MOVD syscallArgs_a27(R9), R1
112+ MOVD R1, (STACK_ARGS+21*8)(R15)
113+ MOVD syscallArgs_a28(R9), R1
114+ MOVD R1, (STACK_ARGS+22*8)(R15)
115+ MOVD syscallArgs_a29(R9), R1
116+ MOVD R1, (STACK_ARGS+23*8)(R15)
117+ MOVD syscallArgs_a30(R9), R1
118+ MOVD R1, (STACK_ARGS+24*8)(R15)
119+ MOVD syscallArgs_a31(R9), R1
120+ MOVD R1, (STACK_ARGS+25*8)(R15)
121+ MOVD syscallArgs_a32(R9), R1
122+ MOVD R1, (STACK_ARGS+26*8)(R15)
90123
91124 // Call function
92- MOVD syscall15Args_fn(R9), R1
125+ MOVD syscallArgs_fn(R9), R1
93126 BL (R1)
94127
95128 // Restore args pointer for storing results
96129 MOVD ARGP_SAVE(R15), R9
97130
98131 // Store integer results back (R2, R3)
99- MOVD R2, syscall15Args_a1(R9)
100- MOVD R3, syscall15Args_a2(R9)
132+ MOVD R2, syscallArgs_a1(R9)
133+ MOVD R3, syscallArgs_a2(R9)
101134
102135 // Store float return values (F0, F2, F4, F6)
103- FMOVD F0, syscall15Args_f1(R9)
104- FMOVD F2, syscall15Args_f2(R9)
105- FMOVD F4, syscall15Args_f3(R9)
106- FMOVD F6, syscall15Args_f4(R9)
136+ FMOVD F0, syscallArgs_f1(R9)
137+ FMOVD F2, syscallArgs_f2(R9)
138+ FMOVD F4, syscallArgs_f3(R9)
139+ FMOVD F6, syscallArgs_f4(R9)
107140
108141 // Deallocate stack frame
109142 ADD $STACK_SIZE, R15
@@ -24,19 +24,18 @@
24 //24 //
25 // We need space for:25 // We need space for:
26 // - 160 bytes standard frame (with register save area)26 // - 160 bytes standard frame (with register save area)
27-// - Stack args a6-a15 (10 * 8 = 80 bytes)27+// - Stack args a6-a32 (27 * 8 = 216 bytes)
28 // - Saved args pointer (8 bytes)28 // - Saved args pointer (8 bytes)
29-// - Padding for alignment29+// Total: 384 bytes
30-// Total: 264 bytes (rounded to 8-byte alignment)
31 30
32-#define STACK_SIZE 26431+#define STACK_SIZE 384
33 #define STACK_ARGS 16032 #define STACK_ARGS 160
34-#define ARGP_SAVE 24833+#define ARGP_SAVE 376
35 34
36-GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $835+GLOBL ·syscallXABI0(SB), NOPTR|RODATA, $8
37-DATA ·syscall15XABI0(SB)/8, $syscall15X(SB)36+DATA ·syscallXABI0(SB)/8, $syscallX(SB)
38 37
39-TEXT syscall15X(SB), NOSPLIT, $038+TEXT syscallX(SB), NOSPLIT, $0
40 // On entry, R2 contains the args pointer39 // On entry, R2 contains the args pointer
41 // Save callee-saved registers in caller's frame (per ABI)40 // Save callee-saved registers in caller's frame (per ABI)
42 STMG R6, R15, 48(R15)41 STMG R6, R15, 48(R15)
@@ -49,61 +48,95 @@ TEXT syscall15X(SB), NOSPLIT, $0
49 // Save args pointer48 // Save args pointer
50 MOVD R2, ARGP_SAVE(R15)49 MOVD R2, ARGP_SAVE(R15)
51 50
52- // R9 := args pointer (syscall15Args*)51+ // R9 := args pointer (syscallArgs*)
53 MOVD R2, R952 MOVD R2, R9
54 53
55 // Load float args into F0, F2, F4, F6 (s390x uses even-numbered FPRs)54 // Load float args into F0, F2, F4, F6 (s390x uses even-numbered FPRs)
56- FMOVD syscall15Args_f1(R9), F055+ FMOVD syscallArgs_f1(R9), F0
57- FMOVD syscall15Args_f2(R9), F256+ FMOVD syscallArgs_f2(R9), F2
58- FMOVD syscall15Args_f3(R9), F457+ FMOVD syscallArgs_f3(R9), F4
59- FMOVD syscall15Args_f4(R9), F658+ FMOVD syscallArgs_f4(R9), F6
60 59
61 // Load integer args into R2-R6 (5 registers)60 // Load integer args into R2-R6 (5 registers)
62- MOVD syscall15Args_a1(R9), R261+ MOVD syscallArgs_a1(R9), R2
63- MOVD syscall15Args_a2(R9), R362+ MOVD syscallArgs_a2(R9), R3
64- MOVD syscall15Args_a3(R9), R463+ MOVD syscallArgs_a3(R9), R4
65- MOVD syscall15Args_a4(R9), R564+ MOVD syscallArgs_a4(R9), R5
66- MOVD syscall15Args_a5(R9), R665+ MOVD syscallArgs_a5(R9), R6
67 66
68- // Spill remaining args (a6-a15) onto the stack at 160(R15)67+ // Spill remaining args (a6-a32) onto the stack at 160(R15)
69 MOVD ARGP_SAVE(R15), R9 // reload args pointer68 MOVD ARGP_SAVE(R15), R9 // reload args pointer
70- MOVD syscall15Args_a6(R9), R169+ MOVD syscallArgs_a6(R9), R1
71 MOVD R1, (STACK_ARGS+0*8)(R15)70 MOVD R1, (STACK_ARGS+0*8)(R15)
72- MOVD syscall15Args_a7(R9), R171+ MOVD syscallArgs_a7(R9), R1
73 MOVD R1, (STACK_ARGS+1*8)(R15)72 MOVD R1, (STACK_ARGS+1*8)(R15)
74- MOVD syscall15Args_a8(R9), R173+ MOVD syscallArgs_a8(R9), R1
75 MOVD R1, (STACK_ARGS+2*8)(R15)74 MOVD R1, (STACK_ARGS+2*8)(R15)
76- MOVD syscall15Args_a9(R9), R175+ MOVD syscallArgs_a9(R9), R1
77 MOVD R1, (STACK_ARGS+3*8)(R15)76 MOVD R1, (STACK_ARGS+3*8)(R15)
78- MOVD syscall15Args_a10(R9), R177+ MOVD syscallArgs_a10(R9), R1
79 MOVD R1, (STACK_ARGS+4*8)(R15)78 MOVD R1, (STACK_ARGS+4*8)(R15)
80- MOVD syscall15Args_a11(R9), R179+ MOVD syscallArgs_a11(R9), R1
81 MOVD R1, (STACK_ARGS+5*8)(R15)80 MOVD R1, (STACK_ARGS+5*8)(R15)
82- MOVD syscall15Args_a12(R9), R181+ MOVD syscallArgs_a12(R9), R1
83 MOVD R1, (STACK_ARGS+6*8)(R15)82 MOVD R1, (STACK_ARGS+6*8)(R15)
84- MOVD syscall15Args_a13(R9), R183+ MOVD syscallArgs_a13(R9), R1
85 MOVD R1, (STACK_ARGS+7*8)(R15)84 MOVD R1, (STACK_ARGS+7*8)(R15)
86- MOVD syscall15Args_a14(R9), R185+ MOVD syscallArgs_a14(R9), R1
87 MOVD R1, (STACK_ARGS+8*8)(R15)86 MOVD R1, (STACK_ARGS+8*8)(R15)
88- MOVD syscall15Args_a15(R9), R187+ MOVD syscallArgs_a15(R9), R1
89 MOVD R1, (STACK_ARGS+9*8)(R15)88 MOVD R1, (STACK_ARGS+9*8)(R15)
89+ MOVD syscallArgs_a16(R9), R1
90+ MOVD R1, (STACK_ARGS+10*8)(R15)
91+ MOVD syscallArgs_a17(R9), R1
92+ MOVD R1, (STACK_ARGS+11*8)(R15)
93+ MOVD syscallArgs_a18(R9), R1
94+ MOVD R1, (STACK_ARGS+12*8)(R15)
95+ MOVD syscallArgs_a19(R9), R1
96+ MOVD R1, (STACK_ARGS+13*8)(R15)
97+ MOVD syscallArgs_a20(R9), R1
98+ MOVD R1, (STACK_ARGS+14*8)(R15)
99+ MOVD syscallArgs_a21(R9), R1
100+ MOVD R1, (STACK_ARGS+15*8)(R15)
101+ MOVD syscallArgs_a22(R9), R1
102+ MOVD R1, (STACK_ARGS+16*8)(R15)
103+ MOVD syscallArgs_a23(R9), R1
104+ MOVD R1, (STACK_ARGS+17*8)(R15)
105+ MOVD syscallArgs_a24(R9), R1
106+ MOVD R1, (STACK_ARGS+18*8)(R15)
107+ MOVD syscallArgs_a25(R9), R1
108+ MOVD R1, (STACK_ARGS+19*8)(R15)
109+ MOVD syscallArgs_a26(R9), R1
110+ MOVD R1, (STACK_ARGS+20*8)(R15)
111+ MOVD syscallArgs_a27(R9), R1
112+ MOVD R1, (STACK_ARGS+21*8)(R15)
113+ MOVD syscallArgs_a28(R9), R1
114+ MOVD R1, (STACK_ARGS+22*8)(R15)
115+ MOVD syscallArgs_a29(R9), R1
116+ MOVD R1, (STACK_ARGS+23*8)(R15)
117+ MOVD syscallArgs_a30(R9), R1
118+ MOVD R1, (STACK_ARGS+24*8)(R15)
119+ MOVD syscallArgs_a31(R9), R1
120+ MOVD R1, (STACK_ARGS+25*8)(R15)
121+ MOVD syscallArgs_a32(R9), R1
122+ MOVD R1, (STACK_ARGS+26*8)(R15)
90 123
91 // Call function124 // Call function
92- MOVD syscall15Args_fn(R9), R1125+ MOVD syscallArgs_fn(R9), R1
93 BL (R1)126 BL (R1)
94 127
95 // Restore args pointer for storing results128 // Restore args pointer for storing results
96 MOVD ARGP_SAVE(R15), R9129 MOVD ARGP_SAVE(R15), R9
97 130
98 // Store integer results back (R2, R3)131 // Store integer results back (R2, R3)
99- MOVD R2, syscall15Args_a1(R9)132+ MOVD R2, syscallArgs_a1(R9)
100- MOVD R3, syscall15Args_a2(R9)133+ MOVD R3, syscallArgs_a2(R9)
101 134
102 // Store float return values (F0, F2, F4, F6)135 // Store float return values (F0, F2, F4, F6)
103- FMOVD F0, syscall15Args_f1(R9)136+ FMOVD F0, syscallArgs_f1(R9)
104- FMOVD F2, syscall15Args_f2(R9)137+ FMOVD F2, syscallArgs_f2(R9)
105- FMOVD F4, syscall15Args_f3(R9)138+ FMOVD F4, syscallArgs_f3(R9)
106- FMOVD F6, syscall15Args_f4(R9)139+ FMOVD F6, syscallArgs_f4(R9)
107 140
108 // Deallocate stack frame141 // Deallocate stack frame
109 ADD $STACK_SIZE, R15142 ADD $STACK_SIZE, R15
M syscall.go +40 -39
@@ -1,53 +1,44 @@
11 // SPDX-License-Identifier: Apache-2.0
22 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
33
4-//go:build !386 && !arm && (darwin || freebsd || linux || netbsd || windows)
4+//go:build !386 && !arm && !ppc64le && (darwin || freebsd || linux || netbsd || windows)
55
66 package purego
77
8-// CDecl marks a function as being called using the __cdecl calling convention as defined in
9-// the [MSDocs] when passed to NewCallback. It must be the first argument to the function.
10-// This is only useful on 386 Windows, but it is safe to use on other platforms.
11-//
12-// [MSDocs]: https://learn.microsoft.com/en-us/cpp/cpp/cdecl?view=msvc-170
13-type CDecl struct{}
8+import (
9+ "runtime"
10+ "unsafe"
11+)
1412
1513 const (
16- maxArgs = 15
14+ maxArgs = 32
1715 )
1816
19-type syscall15Args struct {
20- fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr
21- f1, f2, f3, f4, f5, f6, f7, f8 uintptr
22- arm64_r8 uintptr
17+type syscallArgs struct {
18+ fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr
19+ a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32 uintptr
20+ f1, f2, f3, f4, f5, f6, f7, f8 uintptr
21+ arm64_r8 uintptr
2322 }
2423
25-func (s *syscall15Args) Set(fn uintptr, ints []uintptr, floats []uintptr, r8 uintptr) {
26- s.fn = fn
27- s.a1 = ints[0]
28- s.a2 = ints[1]
29- s.a3 = ints[2]
30- s.a4 = ints[3]
31- s.a5 = ints[4]
32- s.a6 = ints[5]
33- s.a7 = ints[6]
34- s.a8 = ints[7]
35- s.a9 = ints[8]
36- s.a10 = ints[9]
37- s.a11 = ints[10]
38- s.a12 = ints[11]
39- s.a13 = ints[12]
40- s.a14 = ints[13]
41- s.a15 = ints[14]
42- s.f1 = floats[0]
43- s.f2 = floats[1]
44- s.f3 = floats[2]
45- s.f4 = floats[3]
46- s.f5 = floats[4]
47- s.f6 = floats[5]
48- s.f7 = floats[6]
49- s.f8 = floats[7]
50- s.arm64_r8 = r8
24+func syscall_SyscallN(fn uintptr, sysargs []uintptr, floats []uintptr, r8 uintptr) *syscallArgs {
25+ s := thePool.Get().(*syscallArgs)
26+ *s = syscallArgs{
27+ fn: fn,
28+ a1: sysargs[0], a2: sysargs[1], a3: sysargs[2], a4: sysargs[3],
29+ a5: sysargs[4], a6: sysargs[5], a7: sysargs[6], a8: sysargs[7],
30+ a9: sysargs[8], a10: sysargs[9], a11: sysargs[10], a12: sysargs[11],
31+ a13: sysargs[12], a14: sysargs[13], a15: sysargs[14], a16: sysargs[15],
32+ a17: sysargs[16], a18: sysargs[17], a19: sysargs[18], a20: sysargs[19],
33+ a21: sysargs[20], a22: sysargs[21], a23: sysargs[22], a24: sysargs[23],
34+ a25: sysargs[24], a26: sysargs[25], a27: sysargs[26], a28: sysargs[27],
35+ a29: sysargs[28], a30: sysargs[29], a31: sysargs[30], a32: sysargs[31],
36+ f1: floats[0], f2: floats[1], f3: floats[2], f4: floats[3],
37+ f5: floats[4], f6: floats[5], f7: floats[6], f8: floats[7],
38+ arm64_r8: r8,
39+ }
40+ runtime_cgocall(syscallXABI0, unsafe.Pointer(s))
41+ return s
5142 }
5243
5344 // SyscallN takes fn, a C function pointer and a list of arguments as uintptr.
@@ -76,8 +67,18 @@ func SyscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) {
7667 if len(args) > maxArgs {
7768 panic("purego: too many arguments to SyscallN")
7869 }
70+
71+ // Windows uses syscall.SyscallN in syscall_windows.go.
72+ if runtime.GOOS == "windows" {
73+ return syscall_syscallN(fn, args...)
74+ }
75+
7976 // add padding so there is no out-of-bounds slicing
8077 var tmp [maxArgs]uintptr
8178 copy(tmp[:], args)
82- return syscall_syscall15X(fn, tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8], tmp[9], tmp[10], tmp[11], tmp[12], tmp[13], tmp[14])
79+ var floats [maxArgs]uintptr
80+ copy(floats[:], tmp[:])
81+ s := syscall_SyscallN(fn, tmp[:], floats[:], 0)
82+ defer thePool.Put(s)
83+ return s.a1, s.a2, s.a3
8384 }
@@ -1,53 +1,44 @@
1 // SPDX-License-Identifier: Apache-2.01 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors2 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3 3
4-//go:build !386 && !arm && (darwin || freebsd || linux || netbsd || windows)4+//go:build !386 && !arm && !ppc64le && (darwin || freebsd || linux || netbsd || windows)
5 5
6 package purego6 package purego
7 7
8-// CDecl marks a function as being called using the __cdecl calling convention as defined in8+import (
9-// the [MSDocs] when passed to NewCallback. It must be the first argument to the function.9+ "runtime"
10-// This is only useful on 386 Windows, but it is safe to use on other platforms.10+ "unsafe"
11-//11+)
12-// [MSDocs]: https://learn.microsoft.com/en-us/cpp/cpp/cdecl?view=msvc-170
13-type CDecl struct{}
14 12
15 const (13 const (
16- maxArgs = 1514+ maxArgs = 32
17 )15 )
18 16
19-type syscall15Args struct {17+type syscallArgs struct {
20- fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr18+ fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr
21- f1, f2, f3, f4, f5, f6, f7, f8 uintptr19+ a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32 uintptr
22- arm64_r8 uintptr20+ f1, f2, f3, f4, f5, f6, f7, f8 uintptr
21+ arm64_r8 uintptr
23 }22 }
24 23
25-func (s *syscall15Args) Set(fn uintptr, ints []uintptr, floats []uintptr, r8 uintptr) {24+func syscall_SyscallN(fn uintptr, sysargs []uintptr, floats []uintptr, r8 uintptr) *syscallArgs {
26- s.fn = fn25+ s := thePool.Get().(*syscallArgs)
27- s.a1 = ints[0]26+ *s = syscallArgs{
28- s.a2 = ints[1]27+ fn: fn,
29- s.a3 = ints[2]28+ a1: sysargs[0], a2: sysargs[1], a3: sysargs[2], a4: sysargs[3],
30- s.a4 = ints[3]29+ a5: sysargs[4], a6: sysargs[5], a7: sysargs[6], a8: sysargs[7],
31- s.a5 = ints[4]30+ a9: sysargs[8], a10: sysargs[9], a11: sysargs[10], a12: sysargs[11],
32- s.a6 = ints[5]31+ a13: sysargs[12], a14: sysargs[13], a15: sysargs[14], a16: sysargs[15],
33- s.a7 = ints[6]32+ a17: sysargs[16], a18: sysargs[17], a19: sysargs[18], a20: sysargs[19],
34- s.a8 = ints[7]33+ a21: sysargs[20], a22: sysargs[21], a23: sysargs[22], a24: sysargs[23],
35- s.a9 = ints[8]34+ a25: sysargs[24], a26: sysargs[25], a27: sysargs[26], a28: sysargs[27],
36- s.a10 = ints[9]35+ a29: sysargs[28], a30: sysargs[29], a31: sysargs[30], a32: sysargs[31],
37- s.a11 = ints[10]36+ f1: floats[0], f2: floats[1], f3: floats[2], f4: floats[3],
38- s.a12 = ints[11]37+ f5: floats[4], f6: floats[5], f7: floats[6], f8: floats[7],
39- s.a13 = ints[12]38+ arm64_r8: r8,
40- s.a14 = ints[13]39+ }
41- s.a15 = ints[14]40+ runtime_cgocall(syscallXABI0, unsafe.Pointer(s))
42- s.f1 = floats[0]41+ return s
43- s.f2 = floats[1]
44- s.f3 = floats[2]
45- s.f4 = floats[3]
46- s.f5 = floats[4]
47- s.f6 = floats[5]
48- s.f7 = floats[6]
49- s.f8 = floats[7]
50- s.arm64_r8 = r8
51 }42 }
52 43
53 // SyscallN takes fn, a C function pointer and a list of arguments as uintptr.44 // SyscallN takes fn, a C function pointer and a list of arguments as uintptr.
@@ -76,8 +67,18 @@ func SyscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) {
76 if len(args) > maxArgs {67 if len(args) > maxArgs {
77 panic("purego: too many arguments to SyscallN")68 panic("purego: too many arguments to SyscallN")
78 }69 }
70+
71+ // Windows uses syscall.SyscallN in syscall_windows.go.
72+ if runtime.GOOS == "windows" {
73+ return syscall_syscallN(fn, args...)
74+ }
75+
79 // add padding so there is no out-of-bounds slicing76 // add padding so there is no out-of-bounds slicing
80 var tmp [maxArgs]uintptr77 var tmp [maxArgs]uintptr
81 copy(tmp[:], args)78 copy(tmp[:], args)
82- return syscall_syscall15X(fn, tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8], tmp[9], tmp[10], tmp[11], tmp[12], tmp[13], tmp[14])79+ var floats [maxArgs]uintptr
80+ copy(floats[:], tmp[:])
81+ s := syscall_SyscallN(fn, tmp[:], floats[:], 0)
82+ defer thePool.Put(s)
83+ return s.a1, s.a2, s.a3
83 }84 }
M syscall_32bit.go +37 -60
@@ -5,75 +5,42 @@
55
66 package purego
77
8-// CDecl marks a function as being called using the __cdecl calling convention as defined in
9-// the [MSDocs] when passed to NewCallback. It must be the first argument to the function.
10-// This is only useful on 386 Windows, but it is safe to use on other platforms.
11-//
12-// [MSDocs]: https://learn.microsoft.com/en-us/cpp/cpp/cdecl?view=msvc-170
13-type CDecl struct{}
8+import (
9+ "runtime"
10+ "unsafe"
11+)
1412
1513 const (
1614 maxArgs = 32
1715 )
1816
19-type syscall15Args struct {
17+type syscallArgs struct {
2018 fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr
2119 a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32 uintptr
2220 f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16 uintptr
2321 arm64_r8 uintptr
2422 }
2523
26-func (s *syscall15Args) Set(fn uintptr, ints []uintptr, floats []uintptr, r8 uintptr) {
27- s.fn = fn
28- s.a1 = ints[0]
29- s.a2 = ints[1]
30- s.a3 = ints[2]
31- s.a4 = ints[3]
32- s.a5 = ints[4]
33- s.a6 = ints[5]
34- s.a7 = ints[6]
35- s.a8 = ints[7]
36- s.a9 = ints[8]
37- s.a10 = ints[9]
38- s.a11 = ints[10]
39- s.a12 = ints[11]
40- s.a13 = ints[12]
41- s.a14 = ints[13]
42- s.a15 = ints[14]
43- s.a16 = ints[15]
44- s.a17 = ints[16]
45- s.a18 = ints[17]
46- s.a19 = ints[18]
47- s.a20 = ints[19]
48- s.a21 = ints[20]
49- s.a22 = ints[21]
50- s.a23 = ints[22]
51- s.a24 = ints[23]
52- s.a25 = ints[24]
53- s.a26 = ints[25]
54- s.a27 = ints[26]
55- s.a28 = ints[27]
56- s.a29 = ints[28]
57- s.a30 = ints[29]
58- s.a31 = ints[30]
59- s.a32 = ints[31]
60- s.f1 = floats[0]
61- s.f2 = floats[1]
62- s.f3 = floats[2]
63- s.f4 = floats[3]
64- s.f5 = floats[4]
65- s.f6 = floats[5]
66- s.f7 = floats[6]
67- s.f8 = floats[7]
68- s.f9 = floats[8]
69- s.f10 = floats[9]
70- s.f11 = floats[10]
71- s.f12 = floats[11]
72- s.f13 = floats[12]
73- s.f14 = floats[13]
74- s.f15 = floats[14]
75- s.f16 = floats[15]
76- s.arm64_r8 = r8
24+func syscall_SyscallN(fn uintptr, sysargs []uintptr, floats []uintptr, r8 uintptr) *syscallArgs {
25+ s := thePool.Get().(*syscallArgs)
26+ *s = syscallArgs{
27+ fn: fn,
28+ a1: sysargs[0], a2: sysargs[1], a3: sysargs[2], a4: sysargs[3],
29+ a5: sysargs[4], a6: sysargs[5], a7: sysargs[6], a8: sysargs[7],
30+ a9: sysargs[8], a10: sysargs[9], a11: sysargs[10], a12: sysargs[11],
31+ a13: sysargs[12], a14: sysargs[13], a15: sysargs[14], a16: sysargs[15],
32+ a17: sysargs[16], a18: sysargs[17], a19: sysargs[18], a20: sysargs[19],
33+ a21: sysargs[20], a22: sysargs[21], a23: sysargs[22], a24: sysargs[23],
34+ a25: sysargs[24], a26: sysargs[25], a27: sysargs[26], a28: sysargs[27],
35+ a29: sysargs[28], a30: sysargs[29], a31: sysargs[30], a32: sysargs[31],
36+ f1: floats[0], f2: floats[1], f3: floats[2], f4: floats[3],
37+ f5: floats[4], f6: floats[5], f7: floats[6], f8: floats[7],
38+ f9: floats[8], f10: floats[9], f11: floats[10], f12: floats[11],
39+ f13: floats[12], f14: floats[13], f15: floats[14], f16: floats[15],
40+ arm64_r8: r8,
41+ }
42+ runtime_cgocall(syscallXABI0, unsafe.Pointer(s))
43+ return s
7744 }
7845
7946 // SyscallN takes fn, a C function pointer and a list of arguments as uintptr.
@@ -102,8 +69,18 @@ func SyscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) {
10269 if len(args) > maxArgs {
10370 panic("purego: too many arguments to SyscallN")
10471 }
105- // add padding so there is no out-of-bounds slicing
72+
73+ // Windows uses syscall.SyscallN in syscall_windows.go.
74+ if runtime.GOOS == "windows" {
75+ return syscall_syscallN(fn, args...)
76+ }
77+
78+ // Add padding so there is no out-of-bounds slicing.
10679 var tmp [maxArgs]uintptr
10780 copy(tmp[:], args)
108- return syscall_syscall15X(fn, tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8], tmp[9], tmp[10], tmp[11], tmp[12], tmp[13], tmp[14])
81+ var floats [16]uintptr
82+ copy(floats[:], tmp[:16])
83+ s := syscall_SyscallN(fn, tmp[:], floats[:], 0)
84+ defer thePool.Put(s)
85+ return s.a1, s.a2, s.a3
10986 }
@@ -5,75 +5,42 @@
5 5
6 package purego6 package purego
7 7
8-// CDecl marks a function as being called using the __cdecl calling convention as defined in8+import (
9-// the [MSDocs] when passed to NewCallback. It must be the first argument to the function.9+ "runtime"
10-// This is only useful on 386 Windows, but it is safe to use on other platforms.10+ "unsafe"
11-//11+)
12-// [MSDocs]: https://learn.microsoft.com/en-us/cpp/cpp/cdecl?view=msvc-170
13-type CDecl struct{}
14 12
15 const (13 const (
16 maxArgs = 3214 maxArgs = 32
17 )15 )
18 16
19-type syscall15Args struct {17+type syscallArgs struct {
20 fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr18 fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr
21 a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32 uintptr19 a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32 uintptr
22 f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16 uintptr20 f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16 uintptr
23 arm64_r8 uintptr21 arm64_r8 uintptr
24 }22 }
25 23
26-func (s *syscall15Args) Set(fn uintptr, ints []uintptr, floats []uintptr, r8 uintptr) {24+func syscall_SyscallN(fn uintptr, sysargs []uintptr, floats []uintptr, r8 uintptr) *syscallArgs {
27- s.fn = fn25+ s := thePool.Get().(*syscallArgs)
28- s.a1 = ints[0]26+ *s = syscallArgs{
29- s.a2 = ints[1]27+ fn: fn,
30- s.a3 = ints[2]28+ a1: sysargs[0], a2: sysargs[1], a3: sysargs[2], a4: sysargs[3],
31- s.a4 = ints[3]29+ a5: sysargs[4], a6: sysargs[5], a7: sysargs[6], a8: sysargs[7],
32- s.a5 = ints[4]30+ a9: sysargs[8], a10: sysargs[9], a11: sysargs[10], a12: sysargs[11],
33- s.a6 = ints[5]31+ a13: sysargs[12], a14: sysargs[13], a15: sysargs[14], a16: sysargs[15],
34- s.a7 = ints[6]32+ a17: sysargs[16], a18: sysargs[17], a19: sysargs[18], a20: sysargs[19],
35- s.a8 = ints[7]33+ a21: sysargs[20], a22: sysargs[21], a23: sysargs[22], a24: sysargs[23],
36- s.a9 = ints[8]34+ a25: sysargs[24], a26: sysargs[25], a27: sysargs[26], a28: sysargs[27],
37- s.a10 = ints[9]35+ a29: sysargs[28], a30: sysargs[29], a31: sysargs[30], a32: sysargs[31],
38- s.a11 = ints[10]36+ f1: floats[0], f2: floats[1], f3: floats[2], f4: floats[3],
39- s.a12 = ints[11]37+ f5: floats[4], f6: floats[5], f7: floats[6], f8: floats[7],
40- s.a13 = ints[12]38+ f9: floats[8], f10: floats[9], f11: floats[10], f12: floats[11],
41- s.a14 = ints[13]39+ f13: floats[12], f14: floats[13], f15: floats[14], f16: floats[15],
42- s.a15 = ints[14]40+ arm64_r8: r8,
43- s.a16 = ints[15]41+ }
44- s.a17 = ints[16]42+ runtime_cgocall(syscallXABI0, unsafe.Pointer(s))
45- s.a18 = ints[17]43+ return s
46- s.a19 = ints[18]
47- s.a20 = ints[19]
48- s.a21 = ints[20]
49- s.a22 = ints[21]
50- s.a23 = ints[22]
51- s.a24 = ints[23]
52- s.a25 = ints[24]
53- s.a26 = ints[25]
54- s.a27 = ints[26]
55- s.a28 = ints[27]
56- s.a29 = ints[28]
57- s.a30 = ints[29]
58- s.a31 = ints[30]
59- s.a32 = ints[31]
60- s.f1 = floats[0]
61- s.f2 = floats[1]
62- s.f3 = floats[2]
63- s.f4 = floats[3]
64- s.f5 = floats[4]
65- s.f6 = floats[5]
66- s.f7 = floats[6]
67- s.f8 = floats[7]
68- s.f9 = floats[8]
69- s.f10 = floats[9]
70- s.f11 = floats[10]
71- s.f12 = floats[11]
72- s.f13 = floats[12]
73- s.f14 = floats[13]
74- s.f15 = floats[14]
75- s.f16 = floats[15]
76- s.arm64_r8 = r8
77 }44 }
78 45
79 // SyscallN takes fn, a C function pointer and a list of arguments as uintptr.46 // SyscallN takes fn, a C function pointer and a list of arguments as uintptr.
@@ -102,8 +69,18 @@ func SyscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) {
102 if len(args) > maxArgs {69 if len(args) > maxArgs {
103 panic("purego: too many arguments to SyscallN")70 panic("purego: too many arguments to SyscallN")
104 }71 }
105- // add padding so there is no out-of-bounds slicing72+
73+ // Windows uses syscall.SyscallN in syscall_windows.go.
74+ if runtime.GOOS == "windows" {
75+ return syscall_syscallN(fn, args...)
76+ }
77+
78+ // Add padding so there is no out-of-bounds slicing.
106 var tmp [maxArgs]uintptr79 var tmp [maxArgs]uintptr
107 copy(tmp[:], args)80 copy(tmp[:], args)
108- return syscall_syscall15X(fn, tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8], tmp[9], tmp[10], tmp[11], tmp[12], tmp[13], tmp[14])81+ var floats [16]uintptr
82+ copy(floats[:], tmp[:16])
83+ s := syscall_SyscallN(fn, tmp[:], floats[:], 0)
84+ defer thePool.Put(s)
85+ return s.a1, s.a2, s.a3
109 }86 }
M syscall_cgo_linux.go +1 -6
@@ -9,12 +9,7 @@ import (
99 "github.com/ebitengine/purego/internal/cgo"
1010 )
1111
12-var syscall15XABI0 = uintptr(cgo.Syscall15XABI0)
13-
14-//go:nosplit
15-func syscall_syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2, err uintptr) {
16- return cgo.Syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15)
17-}
12+var syscallXABI0 = uintptr(cgo.SyscallXABI0)
1813
1914 func NewCallback(_ any) uintptr {
2015 panic("purego: NewCallback on Linux is only supported on 386/amd64/arm64/arm/loong64/ppc64le/riscv64/s390x")
@@ -9,12 +9,7 @@ import (
9 "github.com/ebitengine/purego/internal/cgo"9 "github.com/ebitengine/purego/internal/cgo"
10 )10 )
11 11
12-var syscall15XABI0 = uintptr(cgo.Syscall15XABI0)12+var syscallXABI0 = uintptr(cgo.SyscallXABI0)
13-
14-//go:nosplit
15-func syscall_syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2, err uintptr) {
16- return cgo.Syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15)
17-}
18 13
19 func NewCallback(_ any) uintptr {14 func NewCallback(_ any) uintptr {
20 panic("purego: NewCallback on Linux is only supported on 386/amd64/arm64/arm/loong64/ppc64le/riscv64/s390x")15 panic("purego: NewCallback on Linux is only supported on 386/amd64/arm64/arm/loong64/ppc64le/riscv64/s390x")
M syscall_notstackargs.go +4 -0
@@ -35,3 +35,7 @@ type callbackArgs struct {
3535 func (c *callbackArgs) stackFrame() unsafe.Pointer {
3636 return nil
3737 }
38+
39+func (c *callbackArgs) intFrame() unsafe.Pointer {
40+ return nil
41+}
@@ -35,3 +35,7 @@ type callbackArgs struct {
35 func (c *callbackArgs) stackFrame() unsafe.Pointer {35 func (c *callbackArgs) stackFrame() unsafe.Pointer {
36 return nil36 return nil
37 }37 }
38+
39+func (c *callbackArgs) intFrame() unsafe.Pointer {
40+ return nil
41+}
A syscall_ppc64le.go +72 -0
@@ -0,0 +1,72 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3+
4+//go:build linux
5+
6+package purego
7+
8+import (
9+ "unsafe"
10+)
11+
12+const (
13+ maxArgs = 15
14+)
15+
16+type syscallArgs struct {
17+ fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr
18+ f1, f2, f3, f4, f5, f6, f7, f8 uintptr
19+ arm64_r8 uintptr
20+}
21+
22+func syscall_SyscallN(fn uintptr, sysargs []uintptr, floats []uintptr, r8 uintptr) *syscallArgs {
23+ s := thePool.Get().(*syscallArgs)
24+ *s = syscallArgs{
25+ fn: fn,
26+ a1: sysargs[0], a2: sysargs[1], a3: sysargs[2], a4: sysargs[3],
27+ a5: sysargs[4], a6: sysargs[5], a7: sysargs[6], a8: sysargs[7],
28+ a9: sysargs[8], a10: sysargs[9], a11: sysargs[10], a12: sysargs[11],
29+ a13: sysargs[12], a14: sysargs[13], a15: sysargs[14],
30+ f1: floats[0], f2: floats[1], f3: floats[2], f4: floats[3],
31+ f5: floats[4], f6: floats[5], f7: floats[6], f8: floats[7],
32+ arm64_r8: r8,
33+ }
34+ runtime_cgocall(syscallXABI0, unsafe.Pointer(s))
35+ return s
36+}
37+
38+// SyscallN takes fn, a C function pointer and a list of arguments as uintptr.
39+// There is an internal maximum number of arguments that SyscallN can take. It panics
40+// when the maximum is exceeded. It returns the result and the libc error code if there is one.
41+//
42+// In order to call this function properly make sure to follow all the rules specified in [unsafe.Pointer]
43+// especially point 4.
44+//
45+// NOTE: SyscallN does not properly call functions that have both integer and float parameters.
46+// See discussion comment https://github.com/ebiten/purego/pull/1#issuecomment-1128057607
47+// for an explanation of why that is.
48+//
49+// On amd64, if there are more than 8 floats the 9th and so on will be placed incorrectly on the
50+// stack.
51+//
52+// The pragma go:nosplit is not needed at this function declaration because it uses go:uintptrescapes
53+// which forces all the objects that the uintptrs point to onto the heap where a stack split won't affect
54+// their memory location.
55+//
56+//go:uintptrescapes
57+func SyscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) {
58+ if fn == 0 {
59+ panic("purego: fn is nil")
60+ }
61+ if len(args) > maxArgs {
62+ panic("purego: too many arguments to SyscallN")
63+ }
64+
65+ var tmp [maxArgs]uintptr
66+ copy(tmp[:], args)
67+ var floats [maxArgs]uintptr
68+ copy(floats[:], tmp[:])
69+ s := syscall_SyscallN(fn, tmp[:], floats[:], 0)
70+ defer thePool.Put(s)
71+ return s.a1, s.a2, s.a3
72+}
@@ -0,0 +1,72 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
3+
4+//go:build linux
5+
6+package purego
7+
8+import (
9+ "unsafe"
10+)
11+
12+const (
13+ maxArgs = 15
14+)
15+
16+type syscallArgs struct {
17+ fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr
18+ f1, f2, f3, f4, f5, f6, f7, f8 uintptr
19+ arm64_r8 uintptr
20+}
21+
22+func syscall_SyscallN(fn uintptr, sysargs []uintptr, floats []uintptr, r8 uintptr) *syscallArgs {
23+ s := thePool.Get().(*syscallArgs)
24+ *s = syscallArgs{
25+ fn: fn,
26+ a1: sysargs[0], a2: sysargs[1], a3: sysargs[2], a4: sysargs[3],
27+ a5: sysargs[4], a6: sysargs[5], a7: sysargs[6], a8: sysargs[7],
28+ a9: sysargs[8], a10: sysargs[9], a11: sysargs[10], a12: sysargs[11],
29+ a13: sysargs[12], a14: sysargs[13], a15: sysargs[14],
30+ f1: floats[0], f2: floats[1], f3: floats[2], f4: floats[3],
31+ f5: floats[4], f6: floats[5], f7: floats[6], f8: floats[7],
32+ arm64_r8: r8,
33+ }
34+ runtime_cgocall(syscallXABI0, unsafe.Pointer(s))
35+ return s
36+}
37+
38+// SyscallN takes fn, a C function pointer and a list of arguments as uintptr.
39+// There is an internal maximum number of arguments that SyscallN can take. It panics
40+// when the maximum is exceeded. It returns the result and the libc error code if there is one.
41+//
42+// In order to call this function properly make sure to follow all the rules specified in [unsafe.Pointer]
43+// especially point 4.
44+//
45+// NOTE: SyscallN does not properly call functions that have both integer and float parameters.
46+// See discussion comment https://github.com/ebiten/purego/pull/1#issuecomment-1128057607
47+// for an explanation of why that is.
48+//
49+// On amd64, if there are more than 8 floats the 9th and so on will be placed incorrectly on the
50+// stack.
51+//
52+// The pragma go:nosplit is not needed at this function declaration because it uses go:uintptrescapes
53+// which forces all the objects that the uintptrs point to onto the heap where a stack split won't affect
54+// their memory location.
55+//
56+//go:uintptrescapes
57+func SyscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) {
58+ if fn == 0 {
59+ panic("purego: fn is nil")
60+ }
61+ if len(args) > maxArgs {
62+ panic("purego: too many arguments to SyscallN")
63+ }
64+
65+ var tmp [maxArgs]uintptr
66+ copy(tmp[:], args)
67+ var floats [maxArgs]uintptr
68+ copy(floats[:], tmp[:])
69+ s := syscall_SyscallN(fn, tmp[:], floats[:], 0)
70+ defer thePool.Put(s)
71+ return s.a1, s.a2, s.a3
72+}
D syscall_stackargs.go +0 -42
@@ -1,42 +0,0 @@
1-// SPDX-License-Identifier: Apache-2.0
2-// SPDX-FileCopyrightText: 2026 The Ebitengine Authors
3-
4-//go:build ppc64le || s390x
5-
6-package purego
7-
8-import "unsafe"
9-
10-// callbackArgs is the argument block passed from the assembly trampoline
11-// to callbackWrap when C code calls a Go callback registered with NewCallback.
12-// The assembly fills in the fields before calling callbackWrap, which uses
13-// them to determine which Go function to invoke and where to read its
14-// arguments from, and writes the return value back into result.
15-//
16-// callbackArgs is only used on Unix. On Windows, callbacks are handled by
17-// the runtime's own callback mechanism, so this type is compiled but unused,
18-// serving only as a stub to satisfy cross-platform compilation.
19-type callbackArgs struct {
20- index uintptr
21- // args points to the argument block.
22- //
23- // The structure of the arguments goes
24- // float registers followed by the
25- // integer registers followed by the stack.
26- //
27- // This variable is treated as a contiguous
28- // block of memory containing all of the arguments
29- // for this callback.
30- args unsafe.Pointer
31- // Below are out-args from callbackWrap
32- result [1]uintptr
33- // stackArgs points to stack-passed arguments for architectures where
34- // they can't be made contiguous with register args (e.g., ppc64le).
35- // On other architectures, this is nil and stack args are read from
36- // the end of the args block.
37- stackArgs unsafe.Pointer
38-}
39-
40-func (c *callbackArgs) stackFrame() unsafe.Pointer {
41- return c.stackArgs
42-}
@@ -1,42 +0,0 @@
1-// SPDX-License-Identifier: Apache-2.0
2-// SPDX-FileCopyrightText: 2026 The Ebitengine Authors
3-
4-//go:build ppc64le || s390x
5-
6-package purego
7-
8-import "unsafe"
9-
10-// callbackArgs is the argument block passed from the assembly trampoline
11-// to callbackWrap when C code calls a Go callback registered with NewCallback.
12-// The assembly fills in the fields before calling callbackWrap, which uses
13-// them to determine which Go function to invoke and where to read its
14-// arguments from, and writes the return value back into result.
15-//
16-// callbackArgs is only used on Unix. On Windows, callbacks are handled by
17-// the runtime's own callback mechanism, so this type is compiled but unused,
18-// serving only as a stub to satisfy cross-platform compilation.
19-type callbackArgs struct {
20- index uintptr
21- // args points to the argument block.
22- //
23- // The structure of the arguments goes
24- // float registers followed by the
25- // integer registers followed by the stack.
26- //
27- // This variable is treated as a contiguous
28- // block of memory containing all of the arguments
29- // for this callback.
30- args unsafe.Pointer
31- // Below are out-args from callbackWrap
32- result [1]uintptr
33- // stackArgs points to stack-passed arguments for architectures where
34- // they can't be made contiguous with register args (e.g., ppc64le).
35- // On other architectures, this is nil and stack args are read from
36- // the end of the args block.
37- stackArgs unsafe.Pointer
38-}
39-
40-func (c *callbackArgs) stackFrame() unsafe.Pointer {
41- return c.stackArgs
42-}
A syscall_stackargs_ppc64le.go +30 -0
@@ -0,0 +1,30 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2026 The Ebitengine Authors
3+
4+package purego
5+
6+import "unsafe"
7+
8+// callbackArgs is the argument block passed from the assembly trampoline
9+// to callbackWrap when C code calls a Go callback registered with NewCallback.
10+type callbackArgs struct {
11+ index uintptr
12+ // args points to the argument block.
13+ //
14+ // The structure of the arguments goes
15+ // float registers followed by the
16+ // integer registers.
17+ args unsafe.Pointer
18+ // Below are out-args from callbackWrap.
19+ result [1]uintptr
20+ // stackArgs points to stack-passed arguments.
21+ stackArgs unsafe.Pointer
22+}
23+
24+func (c *callbackArgs) stackFrame() unsafe.Pointer {
25+ return c.stackArgs
26+}
27+
28+func (c *callbackArgs) intFrame() unsafe.Pointer {
29+ return nil
30+}
@@ -0,0 +1,30 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2026 The Ebitengine Authors
3+
4+package purego
5+
6+import "unsafe"
7+
8+// callbackArgs is the argument block passed from the assembly trampoline
9+// to callbackWrap when C code calls a Go callback registered with NewCallback.
10+type callbackArgs struct {
11+ index uintptr
12+ // args points to the argument block.
13+ //
14+ // The structure of the arguments goes
15+ // float registers followed by the
16+ // integer registers.
17+ args unsafe.Pointer
18+ // Below are out-args from callbackWrap.
19+ result [1]uintptr
20+ // stackArgs points to stack-passed arguments.
21+ stackArgs unsafe.Pointer
22+}
23+
24+func (c *callbackArgs) stackFrame() unsafe.Pointer {
25+ return c.stackArgs
26+}
27+
28+func (c *callbackArgs) intFrame() unsafe.Pointer {
29+ return nil
30+}
A syscall_stackargs_s390x.go +30 -0
@@ -0,0 +1,30 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2026 The Ebitengine Authors
3+
4+package purego
5+
6+import "unsafe"
7+
8+// callbackArgs is the argument block passed from the assembly trampoline
9+// to callbackWrap when C code calls a Go callback registered with NewCallback.
10+type callbackArgs struct {
11+ index uintptr
12+ // args points to the argument block.
13+ //
14+ // The structure of the arguments goes
15+ // float registers followed by the
16+ // integer registers followed by the stack.
17+ args unsafe.Pointer
18+ // Below are out-args from callbackWrap.
19+ result [1]uintptr
20+ // stackArgs points to stack-passed arguments.
21+ stackArgs unsafe.Pointer
22+}
23+
24+func (c *callbackArgs) stackFrame() unsafe.Pointer {
25+ return c.stackArgs
26+}
27+
28+func (c *callbackArgs) intFrame() unsafe.Pointer {
29+ return nil
30+}
@@ -0,0 +1,30 @@
1+// SPDX-License-Identifier: Apache-2.0
2+// SPDX-FileCopyrightText: 2026 The Ebitengine Authors
3+
4+package purego
5+
6+import "unsafe"
7+
8+// callbackArgs is the argument block passed from the assembly trampoline
9+// to callbackWrap when C code calls a Go callback registered with NewCallback.
10+type callbackArgs struct {
11+ index uintptr
12+ // args points to the argument block.
13+ //
14+ // The structure of the arguments goes
15+ // float registers followed by the
16+ // integer registers followed by the stack.
17+ args unsafe.Pointer
18+ // Below are out-args from callbackWrap.
19+ result [1]uintptr
20+ // stackArgs points to stack-passed arguments.
21+ stackArgs unsafe.Pointer
22+}
23+
24+func (c *callbackArgs) stackFrame() unsafe.Pointer {
25+ return c.stackArgs
26+}
27+
28+func (c *callbackArgs) intFrame() unsafe.Pointer {
29+ return nil
30+}
M syscall_unix.go +18 -21
@@ -13,21 +13,10 @@ import (
1313 "unsafe"
1414 )
1515
16-var syscall15XABI0 uintptr
16+var syscallXABI0 uintptr
1717
18-func syscall_syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2, err uintptr) {
19- args := thePool.Get().(*syscall15Args)
20- defer thePool.Put(args)
21-
22- *args = syscall15Args{
23- fn: fn,
24- a1: a1, a2: a2, a3: a3, a4: a4, a5: a5, a6: a6, a7: a7, a8: a8,
25- a9: a9, a10: a10, a11: a11, a12: a12, a13: a13, a14: a14, a15: a15,
26- f1: a1, f2: a2, f3: a3, f4: a4, f5: a5, f6: a6, f7: a7, f8: a8,
27- }
28-
29- runtime_cgocall(syscall15XABI0, unsafe.Pointer(args))
30- return args.a1, args.a2, args.a3
18+func syscall_syscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) {
19+ panic("purego: syscall_syscallN is only supported on windows")
3120 }
3221
3322 // NewCallback converts a Go function to a function pointer conforming to the C calling convention.
@@ -136,10 +125,14 @@ func callbackWrap(a *callbackArgs) {
136125 // stackFrame points to stack-passed arguments. On most architectures this is
137126 // contiguous with frame (after register args), but on ppc64le it's separate.
138127 var stackFrame *[callbackMaxFrame]uintptr
128+ var intFrame *[callbackMaxFrame]uintptr
139129 if sf := a.stackFrame(); sf != nil {
140130 // Only ppc64le uses separate stackArgs pointer due to NOSPLIT constraints
141131 stackFrame = (*[callbackMaxFrame]uintptr)(sf)
142132 }
133+ if intf := a.intFrame(); intf != nil {
134+ intFrame = (*[callbackMaxFrame]uintptr)(intf)
135+ }
143136 // floatsN and intsN track the number of register slots used, not argument count.
144137 // This distinction matters on ARM32 where float64 uses 2 slots (32-bit registers).
145138 var floatsN int
@@ -147,7 +140,7 @@ func callbackWrap(a *callbackArgs) {
147140 // On amd64/loong64/ppc64le/riscv64/s390x, when returning a struct larger than
148141 // maxRegAllocStructSize, the caller passes a hidden pointer in the first integer
149142 // register. Skip it to avoid misreading it as the first function argument.
150- if (runtime.GOARCH == "amd64" || runtime.GOARCH == "loong64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "riscv64" || runtime.GOARCH == "s390x") &&
143+ if (runtime.GOARCH == "amd64" || runtime.GOARCH == "loong64" || runtime.GOARCH == "riscv64" || runtime.GOARCH == "s390x") &&
151144 fnType.NumOut() == 1 && fnType.Out(0).Kind() == reflect.Struct &&
152145 fnType.Out(0).Size() > maxRegAllocStructSize {
153146 intsN = 1
@@ -227,13 +220,17 @@ func callbackWrap(a *callbackArgs) {
227220 stackSlot += slots
228221 }
229222 } else {
230- // the integers begin after the floats in frame
231- pos := intsN + numOfFloatRegisters()
232- if runtime.GOARCH == "s390x" {
233- // s390x big-endian: sub-8-byte values are right-justified in GPR slot
234- args[i] = callbackArgFromSlotBigEndian(unsafe.Pointer(&frame[pos]), inType)
223+ if intFrame != nil {
224+ args[i] = reflect.NewAt(inType, unsafe.Pointer(&intFrame[intsN])).Elem()
235225 } else {
236- args[i] = reflect.NewAt(inType, unsafe.Pointer(&frame[pos])).Elem()
226+ // the integers begin after the floats in frame
227+ pos := intsN + numOfFloatRegisters()
228+ if runtime.GOARCH == "s390x" {
229+ // s390x big-endian: sub-8-byte values are right-justified in GPR slot
230+ args[i] = callbackArgFromSlotBigEndian(unsafe.Pointer(&frame[pos]), inType)
231+ } else {
232+ args[i] = reflect.NewAt(inType, unsafe.Pointer(&frame[pos])).Elem()
233+ }
237234 }
238235 }
239236 intsN += slots
@@ -13,21 +13,10 @@ import (
13 "unsafe"13 "unsafe"
14 )14 )
15 15
16-var syscall15XABI0 uintptr16+var syscallXABI0 uintptr
17 17
18-func syscall_syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2, err uintptr) {18+func syscall_syscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) {
19- args := thePool.Get().(*syscall15Args)19+ panic("purego: syscall_syscallN is only supported on windows")
20- defer thePool.Put(args)
21-
22- *args = syscall15Args{
23- fn: fn,
24- a1: a1, a2: a2, a3: a3, a4: a4, a5: a5, a6: a6, a7: a7, a8: a8,
25- a9: a9, a10: a10, a11: a11, a12: a12, a13: a13, a14: a14, a15: a15,
26- f1: a1, f2: a2, f3: a3, f4: a4, f5: a5, f6: a6, f7: a7, f8: a8,
27- }
28-
29- runtime_cgocall(syscall15XABI0, unsafe.Pointer(args))
30- return args.a1, args.a2, args.a3
31 }20 }
32 21
33 // NewCallback converts a Go function to a function pointer conforming to the C calling convention.22 // NewCallback converts a Go function to a function pointer conforming to the C calling convention.
@@ -136,10 +125,14 @@ func callbackWrap(a *callbackArgs) {
136 // stackFrame points to stack-passed arguments. On most architectures this is125 // stackFrame points to stack-passed arguments. On most architectures this is
137 // contiguous with frame (after register args), but on ppc64le it's separate.126 // contiguous with frame (after register args), but on ppc64le it's separate.
138 var stackFrame *[callbackMaxFrame]uintptr127 var stackFrame *[callbackMaxFrame]uintptr
128+ var intFrame *[callbackMaxFrame]uintptr
139 if sf := a.stackFrame(); sf != nil {129 if sf := a.stackFrame(); sf != nil {
140 // Only ppc64le uses separate stackArgs pointer due to NOSPLIT constraints130 // Only ppc64le uses separate stackArgs pointer due to NOSPLIT constraints
141 stackFrame = (*[callbackMaxFrame]uintptr)(sf)131 stackFrame = (*[callbackMaxFrame]uintptr)(sf)
142 }132 }
133+ if intf := a.intFrame(); intf != nil {
134+ intFrame = (*[callbackMaxFrame]uintptr)(intf)
135+ }
143 // floatsN and intsN track the number of register slots used, not argument count.136 // floatsN and intsN track the number of register slots used, not argument count.
144 // This distinction matters on ARM32 where float64 uses 2 slots (32-bit registers).137 // This distinction matters on ARM32 where float64 uses 2 slots (32-bit registers).
145 var floatsN int138 var floatsN int
@@ -147,7 +140,7 @@ func callbackWrap(a *callbackArgs) {
147 // On amd64/loong64/ppc64le/riscv64/s390x, when returning a struct larger than140 // On amd64/loong64/ppc64le/riscv64/s390x, when returning a struct larger than
148 // maxRegAllocStructSize, the caller passes a hidden pointer in the first integer141 // maxRegAllocStructSize, the caller passes a hidden pointer in the first integer
149 // register. Skip it to avoid misreading it as the first function argument.142 // register. Skip it to avoid misreading it as the first function argument.
150- if (runtime.GOARCH == "amd64" || runtime.GOARCH == "loong64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "riscv64" || runtime.GOARCH == "s390x") &&143+ if (runtime.GOARCH == "amd64" || runtime.GOARCH == "loong64" || runtime.GOARCH == "riscv64" || runtime.GOARCH == "s390x") &&
151 fnType.NumOut() == 1 && fnType.Out(0).Kind() == reflect.Struct &&144 fnType.NumOut() == 1 && fnType.Out(0).Kind() == reflect.Struct &&
152 fnType.Out(0).Size() > maxRegAllocStructSize {145 fnType.Out(0).Size() > maxRegAllocStructSize {
153 intsN = 1146 intsN = 1
@@ -227,13 +220,17 @@ func callbackWrap(a *callbackArgs) {
227 stackSlot += slots220 stackSlot += slots
228 }221 }
229 } else {222 } else {
230- // the integers begin after the floats in frame223+ if intFrame != nil {
231- pos := intsN + numOfFloatRegisters()224+ args[i] = reflect.NewAt(inType, unsafe.Pointer(&intFrame[intsN])).Elem()
232- if runtime.GOARCH == "s390x" {
233- // s390x big-endian: sub-8-byte values are right-justified in GPR slot
234- args[i] = callbackArgFromSlotBigEndian(unsafe.Pointer(&frame[pos]), inType)
235 } else {225 } else {
236- args[i] = reflect.NewAt(inType, unsafe.Pointer(&frame[pos])).Elem()226+ // the integers begin after the floats in frame
227+ pos := intsN + numOfFloatRegisters()
228+ if runtime.GOARCH == "s390x" {
229+ // s390x big-endian: sub-8-byte values are right-justified in GPR slot
230+ args[i] = callbackArgFromSlotBigEndian(unsafe.Pointer(&frame[pos]), inType)
231+ } else {
232+ args[i] = reflect.NewAt(inType, unsafe.Pointer(&frame[pos])).Elem()
233+ }
237 }234 }
238 }235 }
239 intsN += slots236 intsN += slots
M syscall_windows.go +3 -3
@@ -9,10 +9,10 @@ import (
99 "unsafe"
1010 )
1111
12-var syscall15XABI0 uintptr
12+var syscallXABI0 uintptr
1313
14-func syscall_syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2, err uintptr) {
15- r1, r2, errno := syscall.Syscall15(fn, 15, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15)
14+func syscall_syscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) {
15+ r1, r2, errno := syscall.SyscallN(fn, args...)
1616 return r1, r2, uintptr(errno)
1717 }
1818
@@ -9,10 +9,10 @@ import (
9 "unsafe"9 "unsafe"
10 )10 )
11 11
12-var syscall15XABI0 uintptr12+var syscallXABI0 uintptr
13 13
14-func syscall_syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2, err uintptr) {14+func syscall_syscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) {
15- r1, r2, errno := syscall.Syscall15(fn, 15, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15)15+ r1, r2, errno := syscall.SyscallN(fn, args...)
16 return r1, r2, uintptr(errno)16 return r1, r2, uintptr(errno)
17 }17 }
18 18
M testdata/abitest/abi_test.c +38 -0
@@ -129,3 +129,41 @@ void stack_25_int64_exceeds(char *buf, size_t bufsize, int64_t a1, int64_t a2, i
129129 snprintf(buf, bufsize, "%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64,
130130 a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25);
131131 }
132+
133+uintptr_t stack_20_uintptr(
134+ uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5,
135+ uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9, uintptr_t a10,
136+ uintptr_t a11, uintptr_t a12, uintptr_t a13, uintptr_t a14, uintptr_t a15,
137+ uintptr_t a16, uintptr_t a17, uintptr_t a18, uintptr_t a19, uintptr_t a20
138+) {
139+ return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 +
140+ a11 + a12 + a13 + a14 + a15 + a16 + a17 + a18 + a19 + a20;
141+}
142+
143+uintptr_t stack_32_uintptr(
144+ uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8,
145+ uintptr_t a9, uintptr_t a10, uintptr_t a11, uintptr_t a12, uintptr_t a13, uintptr_t a14, uintptr_t a15, uintptr_t a16,
146+ uintptr_t a17, uintptr_t a18, uintptr_t a19, uintptr_t a20, uintptr_t a21, uintptr_t a22, uintptr_t a23, uintptr_t a24,
147+ uintptr_t a25, uintptr_t a26, uintptr_t a27, uintptr_t a28, uintptr_t a29, uintptr_t a30, uintptr_t a31, uintptr_t a32
148+) {
149+ return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 +
150+ a9 + a10 + a11 + a12 + a13 + a14 + a15 + a16 +
151+ a17 + a18 + a19 + a20 + a21 + a22 + a23 + a24 +
152+ a25 + a26 + a27 + a28 + a29 + a30 + a31 + a32;
153+}
154+
155+double stack_32_mixed_int_float(
156+ uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8,
157+ uintptr_t a9, uintptr_t a10, uintptr_t a11, uintptr_t a12, uintptr_t a13, uintptr_t a14, uintptr_t a15, uintptr_t a16,
158+ double f1, double f2, double f3, double f4, double f5, double f6, double f7, double f8,
159+ double f9, double f10, double f11, double f12, double f13, double f14, double f15, double f16
160+) {
161+ return (double)a1 * 1 + (double)a2 * 2 + (double)a3 * 3 + (double)a4 * 4 +
162+ (double)a5 * 5 + (double)a6 * 6 + (double)a7 * 7 + (double)a8 * 8 +
163+ (double)a9 * 9 + (double)a10 * 10 + (double)a11 * 11 + (double)a12 * 12 +
164+ (double)a13 * 13 + (double)a14 * 14 + (double)a15 * 15 + (double)a16 * 16 +
165+ f1 * 17 + f2 * 18 + f3 * 19 + f4 * 20 +
166+ f5 * 21 + f6 * 22 + f7 * 23 + f8 * 24 +
167+ f9 * 25 + f10 * 26 + f11 * 27 + f12 * 28 +
168+ f13 * 29 + f14 * 30 + f15 * 31 + f16 * 32;
169+}
@@ -129,3 +129,41 @@ void stack_25_int64_exceeds(char *buf, size_t bufsize, int64_t a1, int64_t a2, i
129 snprintf(buf, bufsize, "%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64,129 snprintf(buf, bufsize, "%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64,
130 a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25);130 a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25);
131 }131 }
132+
133+uintptr_t stack_20_uintptr(
134+ uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5,
135+ uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9, uintptr_t a10,
136+ uintptr_t a11, uintptr_t a12, uintptr_t a13, uintptr_t a14, uintptr_t a15,
137+ uintptr_t a16, uintptr_t a17, uintptr_t a18, uintptr_t a19, uintptr_t a20
138+) {
139+ return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 +
140+ a11 + a12 + a13 + a14 + a15 + a16 + a17 + a18 + a19 + a20;
141+}
142+
143+uintptr_t stack_32_uintptr(
144+ uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8,
145+ uintptr_t a9, uintptr_t a10, uintptr_t a11, uintptr_t a12, uintptr_t a13, uintptr_t a14, uintptr_t a15, uintptr_t a16,
146+ uintptr_t a17, uintptr_t a18, uintptr_t a19, uintptr_t a20, uintptr_t a21, uintptr_t a22, uintptr_t a23, uintptr_t a24,
147+ uintptr_t a25, uintptr_t a26, uintptr_t a27, uintptr_t a28, uintptr_t a29, uintptr_t a30, uintptr_t a31, uintptr_t a32
148+) {
149+ return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 +
150+ a9 + a10 + a11 + a12 + a13 + a14 + a15 + a16 +
151+ a17 + a18 + a19 + a20 + a21 + a22 + a23 + a24 +
152+ a25 + a26 + a27 + a28 + a29 + a30 + a31 + a32;
153+}
154+
155+double stack_32_mixed_int_float(
156+ uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8,
157+ uintptr_t a9, uintptr_t a10, uintptr_t a11, uintptr_t a12, uintptr_t a13, uintptr_t a14, uintptr_t a15, uintptr_t a16,
158+ double f1, double f2, double f3, double f4, double f5, double f6, double f7, double f8,
159+ double f9, double f10, double f11, double f12, double f13, double f14, double f15, double f16
160+) {
161+ return (double)a1 * 1 + (double)a2 * 2 + (double)a3 * 3 + (double)a4 * 4 +
162+ (double)a5 * 5 + (double)a6 * 6 + (double)a7 * 7 + (double)a8 * 8 +
163+ (double)a9 * 9 + (double)a10 * 10 + (double)a11 * 11 + (double)a12 * 12 +
164+ (double)a13 * 13 + (double)a14 * 14 + (double)a15 * 15 + (double)a16 * 16 +
165+ f1 * 17 + f2 * 18 + f3 * 19 + f4 * 20 +
166+ f5 * 21 + f6 * 22 + f7 * 23 + f8 * 24 +
167+ f9 * 25 + f10 * 26 + f11 * 27 + f12 * 28 +
168+ f13 * 29 + f14 * 30 + f15 * 31 + f16 * 32;
169+}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 102

↑↓ moveenter openesc close