aboutsummaryrefslogtreecommitdiff
path: root/src/internal/abi/abi.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/internal/abi/abi.go')
-rw-r--r--src/internal/abi/abi.go45
1 files changed, 44 insertions, 1 deletions
diff --git a/src/internal/abi/abi.go b/src/internal/abi/abi.go
index aaff9cece3..eadff248d9 100644
--- a/src/internal/abi/abi.go
+++ b/src/internal/abi/abi.go
@@ -4,7 +4,10 @@
package abi
-import "unsafe"
+import (
+ "internal/goarch"
+ "unsafe"
+)
// RegArgs is a struct that has space for each argument
// and return value register on the current architecture.
@@ -33,6 +36,46 @@ type RegArgs struct {
ReturnIsPtr IntArgRegBitmap
}
+// IntRegArgAddr returns a pointer inside of r.Ints[reg] that is appropriately
+// offset for an argument of size argSize.
+//
+// argSize must be non-zero, fit in a register, and a power-of-two.
+//
+// This method is a helper for dealing with the endianness of different CPU
+// architectures, since sub-word-sized arguments in big endian architectures
+// need to be "aligned" to the upper edge of the register to be interpreted
+// by the CPU correctly.
+func (r *RegArgs) IntRegArgAddr(reg int, argSize uintptr) unsafe.Pointer {
+ if argSize > goarch.PtrSize || argSize == 0 || argSize&(argSize-1) != 0 {
+ panic("invalid argSize")
+ }
+ offset := uintptr(0)
+ if goarch.BigEndian {
+ offset = goarch.PtrSize - argSize
+ }
+ return unsafe.Pointer(uintptr(unsafe.Pointer(&r.Ints[reg])) + offset)
+}
+
+// FloatRegArgAddr returns a pointer inside of r.Floats[reg] that is appropriately
+// offset for an argument of size argSize.
+//
+// argSize must be non-zero, fit in a register, and a power-of-two.
+//
+// This method is a helper for dealing with the endianness of different CPU
+// architectures, since sub-word-sized arguments in big endian architectures
+// need to be "aligned" to the upper edge of the register to be interpreted
+// by the CPU correctly.
+func (r *RegArgs) FloatRegArgAddr(reg int, argSize uintptr) unsafe.Pointer {
+ if argSize > EffectiveFloatRegSize || argSize == 0 || argSize&(argSize-1) != 0 {
+ panic("invalid argSize")
+ }
+ offset := uintptr(0)
+ if goarch.BigEndian {
+ offset = EffectiveFloatRegSize - argSize
+ }
+ return unsafe.Pointer(uintptr(unsafe.Pointer(&r.Floats[reg])) + offset)
+}
+
// IntArgRegBitmap is a bitmap large enough to hold one bit per
// integer argument/return register.
type IntArgRegBitmap [(IntArgRegs + 7) / 8]uint8