purego: support float arguments in RegisterFunc (#69)
This commit adds proper float support into RegisterFunc. It puts the first 8 in registers and the 9th onto the stack. It also checks beforehand that there aren't too many arguments.
- commit
- c9e35fa8a6a11df664933e8d7ce2451ecee3e4f0
- author
- TotallyGamerJet · · 2022-11-15 11:51 UTC
- committer
- GitHub · · 2022-11-15 11:51 UTC
- parent
- c99251d
- signature
- GPG Unverified
4AEE18F83AFDEB23The key is unknown
4 files · +128 -45
M func_darwin.go +87 -10
| @@ -68,6 +68,40 @@ func RegisterFunc(fptr interface{}, cfn uintptr) { | |||
| 68 | 68 | if ty.NumOut() > 1 { | |
| 69 | 69 | panic("purego: function can only return zero or one values") | |
| 70 | 70 | } | |
| 71 | + | if cfn == 0 { | |
| 72 | + | panic("purego: cfn is nil") | |
| 73 | + | } | |
| 74 | + | { | |
| 75 | + | // this code checks how many registers and stack this function will use | |
| 76 | + | // to avoid crashing with too many arguments | |
| 77 | + | var ints int | |
| 78 | + | var floats int | |
| 79 | + | var stack int | |
| 80 | + | for i := 0; i < ty.NumIn(); i++ { | |
| 81 | + | arg := ty.In(i) | |
| 82 | + | switch arg.Kind() { | |
| 83 | + | case reflect.String, reflect.Uintptr, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, | |
| 84 | + | reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Ptr, reflect.UnsafePointer, reflect.Slice, | |
| 85 | + | reflect.Func, reflect.Bool: | |
| 86 | + | if ints < numOfIntegerRegisters() { | |
| 87 | + | ints++ | |
| 88 | + | } else { | |
| 89 | + | stack++ | |
| 90 | + | } | |
| 91 | + | case reflect.Float32, reflect.Float64: | |
| 92 | + | if floats < 8 { | |
| 93 | + | floats++ | |
| 94 | + | } else { | |
| 95 | + | stack++ | |
| 96 | + | } | |
| 97 | + | default: | |
| 98 | + | panic("purego: unsupported kind " + arg.Kind().String()) | |
| 99 | + | } | |
| 100 | + | } | |
| 101 | + | if ints+stack > maxArgs || floats+stack > maxArgs { | |
| 102 | + | panic("purego: too many arguments") | |
| 103 | + | } | |
| 104 | + | } | |
| 71 | 105 | v := reflect.MakeFunc(ty, func(args []reflect.Value) (results []reflect.Value) { | |
| 72 | 106 | if len(args) > 0 { | |
| 73 | 107 | if variadic, ok := args[len(args)-1].Interface().([]interface{}); ok { | |
| @@ -81,37 +115,69 @@ func RegisterFunc(fptr interface{}, cfn uintptr) { | |||
| 81 | 115 | args = tmp | |
| 82 | 116 | } | |
| 83 | 117 | } | |
| 84 | - | var sysargs = make([]uintptr, len(args)) | |
| 118 | + | var sysargs [maxArgs]uintptr | |
| 119 | + | var stack = sysargs[numOfIntegerRegisters():] | |
| 120 | + | var floats [8]float64 | |
| 121 | + | var numInts int | |
| 122 | + | var numFloats int | |
| 123 | + | var numStack int | |
| 124 | + | addStack := func(x uintptr) { | |
| 125 | + | stack[numStack] = x | |
| 126 | + | numStack++ | |
| 127 | + | } | |
| 128 | + | addInt := func(x uintptr) { | |
| 129 | + | if numInts >= numOfIntegerRegisters() { | |
| 130 | + | addStack(x) | |
| 131 | + | } else { | |
| 132 | + | sysargs[numInts] = x | |
| 133 | + | numInts++ | |
| 134 | + | } | |
| 135 | + | } | |
| 85 | 136 | var keepAlive []interface{} | |
| 86 | 137 | defer func() { | |
| 87 | 138 | runtime.KeepAlive(keepAlive) | |
| 88 | 139 | }() | |
| 89 | - | for i, v := range args { | |
| 140 | + | for _, v := range args { | |
| 90 | 141 | switch v.Kind() { | |
| 91 | 142 | case reflect.String: | |
| 92 | 143 | ptr := strings.CString(v.String()) | |
| 93 | 144 | keepAlive = append(keepAlive, ptr) | |
| 94 | - | sysargs[i] = uintptr(unsafe.Pointer(ptr)) | |
| 145 | + | addInt(uintptr(unsafe.Pointer(ptr))) | |
| 95 | 146 | case reflect.Uintptr, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | |
| 96 | - | sysargs[i] = uintptr(v.Uint()) | |
| 147 | + | addInt(uintptr(v.Uint())) | |
| 97 | 148 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | |
| 98 | - | sysargs[i] = uintptr(v.Int()) | |
| 149 | + | addInt(uintptr(v.Int())) | |
| 99 | 150 | case reflect.Ptr, reflect.UnsafePointer, reflect.Slice: | |
| 100 | 151 | keepAlive = append(keepAlive, v.Pointer()) | |
| 101 | - | sysargs[i] = v.Pointer() | |
| 152 | + | addInt(v.Pointer()) | |
| 102 | 153 | case reflect.Func: | |
| 103 | - | sysargs[i] = NewCallback(v.Interface()) | |
| 154 | + | addInt(NewCallback(v.Interface())) | |
| 104 | 155 | case reflect.Bool: | |
| 105 | 156 | if v.Bool() { | |
| 106 | - | sysargs[i] = 1 | |
| 157 | + | addInt(1) | |
| 158 | + | } else { | |
| 159 | + | addInt(0) | |
| 160 | + | } | |
| 161 | + | case reflect.Float32, reflect.Float64: | |
| 162 | + | if numFloats < len(floats) { | |
| 163 | + | floats[numFloats] = v.Float() | |
| 164 | + | numFloats++ | |
| 107 | 165 | } else { | |
| 108 | - | sysargs[i] = 0 | |
| 166 | + | addStack(uintptr(math.Float64bits(v.Float()))) | |
| 109 | 167 | } | |
| 110 | 168 | default: | |
| 111 | 169 | panic("purego: unsupported kind: " + v.Kind().String()) | |
| 112 | 170 | } | |
| 113 | 171 | } | |
| 114 | - | r1, r2, _ := SyscallN(cfn, sysargs...) //TODO: handle float32/64 and struct types | |
| 172 | + | // TODO: support structs | |
| 173 | + | syscall := syscall9Args{ | |
| 174 | + | cfn, | |
| 175 | + | sysargs[0], sysargs[1], sysargs[2], sysargs[3], sysargs[4], sysargs[5], sysargs[6], sysargs[7], sysargs[8], | |
| 176 | + | floats[0], floats[1], floats[2], floats[3], floats[4], floats[5], floats[6], floats[7], | |
| 177 | + | 0, 0, 0} | |
| 178 | + | runtime_cgocall(syscall9XABI0, unsafe.Pointer(&syscall)) | |
| 179 | + | r1, r2 := syscall.r1, syscall.r2 | |
| 180 | + | ||
| 115 | 181 | if ty.NumOut() == 0 { | |
| 116 | 182 | return nil | |
| 117 | 183 | } | |
| @@ -146,3 +212,14 @@ func RegisterFunc(fptr interface{}, cfn uintptr) { | |||
| 146 | 212 | }) | |
| 147 | 213 | fn.Set(v) | |
| 148 | 214 | } | |
| 215 | + | ||
| 216 | + | func numOfIntegerRegisters() int { | |
| 217 | + | switch runtime.GOARCH { | |
| 218 | + | case "arm64": | |
| 219 | + | return 8 | |
| 220 | + | case "amd64": | |
| 221 | + | return 6 | |
| 222 | + | default: | |
| 223 | + | panic("purego: unknown GOARCH (" + runtime.GOARCH + ")") | |
| 224 | + | } | |
| 225 | + | } | |
| @@ -68,6 +68,40 @@ func RegisterFunc(fptr interface{}, cfn uintptr) { | |||||
| 68 | if ty.NumOut() > 1 { | 68 | if ty.NumOut() > 1 { | ||
| 69 | panic("purego: function can only return zero or one values") | 69 | panic("purego: function can only return zero or one values") | ||
| 70 | } | 70 | } | ||
| 71 | + | if cfn == 0 { | |||
| 72 | + | panic("purego: cfn is nil") | |||
| 73 | + | } | |||
| 74 | + | { | |||
| 75 | + | // this code checks how many registers and stack this function will use | |||
| 76 | + | // to avoid crashing with too many arguments | |||
| 77 | + | var ints int | |||
| 78 | + | var floats int | |||
| 79 | + | var stack int | |||
| 80 | + | for i := 0; i < ty.NumIn(); i++ { | |||
| 81 | + | arg := ty.In(i) | |||
| 82 | + | switch arg.Kind() { | |||
| 83 | + | case reflect.String, reflect.Uintptr, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, | |||
| 84 | + | reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Ptr, reflect.UnsafePointer, reflect.Slice, | |||
| 85 | + | reflect.Func, reflect.Bool: | |||
| 86 | + | if ints < numOfIntegerRegisters() { | |||
| 87 | + | ints++ | |||
| 88 | + | } else { | |||
| 89 | + | stack++ | |||
| 90 | + | } | |||
| 91 | + | case reflect.Float32, reflect.Float64: | |||
| 92 | + | if floats < 8 { | |||
| 93 | + | floats++ | |||
| 94 | + | } else { | |||
| 95 | + | stack++ | |||
| 96 | + | } | |||
| 97 | + | default: | |||
| 98 | + | panic("purego: unsupported kind " + arg.Kind().String()) | |||
| 99 | + | } | |||
| 100 | + | } | |||
| 101 | + | if ints+stack > maxArgs || floats+stack > maxArgs { | |||
| 102 | + | panic("purego: too many arguments") | |||
| 103 | + | } | |||
| 104 | + | } | |||
| 71 | v := reflect.MakeFunc(ty, func(args []reflect.Value) (results []reflect.Value) { | 105 | v := reflect.MakeFunc(ty, func(args []reflect.Value) (results []reflect.Value) { | ||
| 72 | if len(args) > 0 { | 106 | if len(args) > 0 { | ||
| 73 | if variadic, ok := args[len(args)-1].Interface().([]interface{}); ok { | 107 | if variadic, ok := args[len(args)-1].Interface().([]interface{}); ok { | ||
| @@ -81,37 +115,69 @@ func RegisterFunc(fptr interface{}, cfn uintptr) { | |||||
| 81 | args = tmp | 115 | args = tmp | ||
| 82 | } | 116 | } | ||
| 83 | } | 117 | } | ||
| 84 | - | var sysargs = make([]uintptr, len(args)) | 118 | + | var sysargs [maxArgs]uintptr |
| 119 | + | var stack = sysargs[numOfIntegerRegisters():] | |||
| 120 | + | var floats [8]float64 | |||
| 121 | + | var numInts int | |||
| 122 | + | var numFloats int | |||
| 123 | + | var numStack int | |||
| 124 | + | addStack := func(x uintptr) { | |||
| 125 | + | stack[numStack] = x | |||
| 126 | + | numStack++ | |||
| 127 | + | } | |||
| 128 | + | addInt := func(x uintptr) { | |||
| 129 | + | if numInts >= numOfIntegerRegisters() { | |||
| 130 | + | addStack(x) | |||
| 131 | + | } else { | |||
| 132 | + | sysargs[numInts] = x | |||
| 133 | + | numInts++ | |||
| 134 | + | } | |||
| 135 | + | } | |||
| 85 | var keepAlive []interface{} | 136 | var keepAlive []interface{} | ||
| 86 | defer func() { | 137 | defer func() { | ||
| 87 | runtime.KeepAlive(keepAlive) | 138 | runtime.KeepAlive(keepAlive) | ||
| 88 | }() | 139 | }() | ||
| 89 | - | for i, v := range args { | 140 | + | for _, v := range args { |
| 90 | switch v.Kind() { | 141 | switch v.Kind() { | ||
| 91 | case reflect.String: | 142 | case reflect.String: | ||
| 92 | ptr := strings.CString(v.String()) | 143 | ptr := strings.CString(v.String()) | ||
| 93 | keepAlive = append(keepAlive, ptr) | 144 | keepAlive = append(keepAlive, ptr) | ||
| 94 | - | sysargs[i] = uintptr(unsafe.Pointer(ptr)) | 145 | + | addInt(uintptr(unsafe.Pointer(ptr))) |
| 95 | case reflect.Uintptr, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | 146 | case reflect.Uintptr, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | ||
| 96 | - | sysargs[i] = uintptr(v.Uint()) | 147 | + | addInt(uintptr(v.Uint())) |
| 97 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | 148 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | ||
| 98 | - | sysargs[i] = uintptr(v.Int()) | 149 | + | addInt(uintptr(v.Int())) |
| 99 | case reflect.Ptr, reflect.UnsafePointer, reflect.Slice: | 150 | case reflect.Ptr, reflect.UnsafePointer, reflect.Slice: | ||
| 100 | keepAlive = append(keepAlive, v.Pointer()) | 151 | keepAlive = append(keepAlive, v.Pointer()) | ||
| 101 | - | sysargs[i] = v.Pointer() | 152 | + | addInt(v.Pointer()) |
| 102 | case reflect.Func: | 153 | case reflect.Func: | ||
| 103 | - | sysargs[i] = NewCallback(v.Interface()) | 154 | + | addInt(NewCallback(v.Interface())) |
| 104 | case reflect.Bool: | 155 | case reflect.Bool: | ||
| 105 | if v.Bool() { | 156 | if v.Bool() { | ||
| 106 | - | sysargs[i] = 1 | 157 | + | addInt(1) |
| 158 | + | } else { | |||
| 159 | + | addInt(0) | |||
| 160 | + | } | |||
| 161 | + | case reflect.Float32, reflect.Float64: | |||
| 162 | + | if numFloats < len(floats) { | |||
| 163 | + | floats[numFloats] = v.Float() | |||
| 164 | + | numFloats++ | |||
| 107 | } else { | 165 | } else { | ||
| 108 | - | sysargs[i] = 0 | 166 | + | addStack(uintptr(math.Float64bits(v.Float()))) |
| 109 | } | 167 | } | ||
| 110 | default: | 168 | default: | ||
| 111 | panic("purego: unsupported kind: " + v.Kind().String()) | 169 | panic("purego: unsupported kind: " + v.Kind().String()) | ||
| 112 | } | 170 | } | ||
| 113 | } | 171 | } | ||
| 114 | - | r1, r2, _ := SyscallN(cfn, sysargs...) //TODO: handle float32/64 and struct types | 172 | + | // TODO: support structs |
| 173 | + | syscall := syscall9Args{ | |||
| 174 | + | cfn, | |||
| 175 | + | sysargs[0], sysargs[1], sysargs[2], sysargs[3], sysargs[4], sysargs[5], sysargs[6], sysargs[7], sysargs[8], | |||
| 176 | + | floats[0], floats[1], floats[2], floats[3], floats[4], floats[5], floats[6], floats[7], | |||
| 177 | + | 0, 0, 0} | |||
| 178 | + | runtime_cgocall(syscall9XABI0, unsafe.Pointer(&syscall)) | |||
| 179 | + | r1, r2 := syscall.r1, syscall.r2 | |||
| 180 | + | ||||
| 115 | if ty.NumOut() == 0 { | 181 | if ty.NumOut() == 0 { | ||
| 116 | return nil | 182 | return nil | ||
| 117 | } | 183 | } | ||
| @@ -146,3 +212,14 @@ func RegisterFunc(fptr interface{}, cfn uintptr) { | |||||
| 146 | }) | 212 | }) | ||
| 147 | fn.Set(v) | 213 | fn.Set(v) | ||
| 148 | } | 214 | } | ||
| 215 | + | ||||
| 216 | + | func numOfIntegerRegisters() int { | |||
| 217 | + | switch runtime.GOARCH { | |||
| 218 | + | case "arm64": | |||
| 219 | + | return 8 | |||
| 220 | + | case "amd64": | |||
| 221 | + | return 6 | |||
| 222 | + | default: | |||
| 223 | + | panic("purego: unknown GOARCH (" + runtime.GOARCH + ")") | |||
| 224 | + | } | |||
| 225 | + | } | |||
M sys_darwin_amd64.s +21 -22
| @@ -31,28 +31,27 @@ TEXT syscall9X(SB), NOSPLIT, $0 | |||
| 31 | 31 | PUSHQ BP | |
| 32 | 32 | MOVQ SP, BP | |
| 33 | 33 | SUBQ $32, SP | |
| 34 | - | MOVQ DI, 24(BP) // save the pointer | |
| 35 | - | MOVQ syscall9Args_fn(DI), R10 // fn | |
| 36 | - | MOVQ syscall9Args_a2(DI), SI // a2 | |
| 37 | - | MOVQ syscall9Args_a3(DI), DX // a3 | |
| 38 | - | MOVQ syscall9Args_a4(DI), CX // a4 | |
| 39 | - | MOVQ syscall9Args_a5(DI), R8 // a5 | |
| 40 | - | MOVQ syscall9Args_a6(DI), R9 // a6 | |
| 41 | - | MOVQ syscall9Args_a7(DI), R11 // a7 | |
| 42 | - | MOVQ syscall9Args_a8(DI), R12 // a8 | |
| 43 | - | MOVQ syscall9Args_a9(DI), R13 // a9 | |
| 44 | - | MOVQ syscall9Args_a1(DI), DI // a1 | |
| 45 | - | ||
| 46 | - | // these may be float arguments | |
| 47 | - | // so we put them also where C expects floats | |
| 48 | - | MOVQ DI, X0 // a1 | |
| 49 | - | MOVQ SI, X1 // a2 | |
| 50 | - | MOVQ DX, X2 // a3 | |
| 51 | - | MOVQ CX, X3 // a4 | |
| 52 | - | MOVQ R8, X4 // a5 | |
| 53 | - | MOVQ R9, X5 // a6 | |
| 54 | - | MOVQ R11, X6 // a7 | |
| 55 | - | MOVQ R12, X7 // a8 | |
| 34 | + | MOVQ DI, 24(BP) // save the pointer | |
| 35 | + | ||
| 36 | + | MOVQ syscall9Args_f1(DI), X0 // f1 | |
| 37 | + | MOVQ syscall9Args_f2(DI), X1 // f2 | |
| 38 | + | MOVQ syscall9Args_f3(DI), X2 // f3 | |
| 39 | + | MOVQ syscall9Args_f4(DI), X3 // f4 | |
| 40 | + | MOVQ syscall9Args_f5(DI), X4 // f5 | |
| 41 | + | MOVQ syscall9Args_f6(DI), X5 // f6 | |
| 42 | + | MOVQ syscall9Args_f7(DI), X6 // f7 | |
| 43 | + | MOVQ syscall9Args_f8(DI), X7 // f8 | |
| 44 | + | ||
| 45 | + | MOVQ syscall9Args_fn(DI), R10 // fn | |
| 46 | + | MOVQ syscall9Args_a2(DI), SI // a2 | |
| 47 | + | MOVQ syscall9Args_a3(DI), DX // a3 | |
| 48 | + | MOVQ syscall9Args_a4(DI), CX // a4 | |
| 49 | + | MOVQ syscall9Args_a5(DI), R8 // a5 | |
| 50 | + | MOVQ syscall9Args_a6(DI), R9 // a6 | |
| 51 | + | MOVQ syscall9Args_a7(DI), R11 // a7 | |
| 52 | + | MOVQ syscall9Args_a8(DI), R12 // a8 | |
| 53 | + | MOVQ syscall9Args_a9(DI), R13 // a9 | |
| 54 | + | MOVQ syscall9Args_a1(DI), DI // a1 | |
| 56 | 55 | ||
| 57 | 56 | // push the remaining paramters onto the stack | |
| 58 | 57 | MOVQ R11, 0(SP) // push a7 | |
| @@ -31,28 +31,27 @@ TEXT syscall9X(SB), NOSPLIT, $0 | |||||
| 31 | PUSHQ BP | 31 | PUSHQ BP | ||
| 32 | MOVQ SP, BP | 32 | MOVQ SP, BP | ||
| 33 | SUBQ $32, SP | 33 | SUBQ $32, SP | ||
| 34 | - | MOVQ DI, 24(BP) // save the pointer | 34 | + | MOVQ DI, 24(BP) // save the pointer |
| 35 | - | MOVQ syscall9Args_fn(DI), R10 // fn | 35 | + | |
| 36 | - | MOVQ syscall9Args_a2(DI), SI // a2 | 36 | + | MOVQ syscall9Args_f1(DI), X0 // f1 |
| 37 | - | MOVQ syscall9Args_a3(DI), DX // a3 | 37 | + | MOVQ syscall9Args_f2(DI), X1 // f2 |
| 38 | - | MOVQ syscall9Args_a4(DI), CX // a4 | 38 | + | MOVQ syscall9Args_f3(DI), X2 // f3 |
| 39 | - | MOVQ syscall9Args_a5(DI), R8 // a5 | 39 | + | MOVQ syscall9Args_f4(DI), X3 // f4 |
| 40 | - | MOVQ syscall9Args_a6(DI), R9 // a6 | 40 | + | MOVQ syscall9Args_f5(DI), X4 // f5 |
| 41 | - | MOVQ syscall9Args_a7(DI), R11 // a7 | 41 | + | MOVQ syscall9Args_f6(DI), X5 // f6 |
| 42 | - | MOVQ syscall9Args_a8(DI), R12 // a8 | 42 | + | MOVQ syscall9Args_f7(DI), X6 // f7 |
| 43 | - | MOVQ syscall9Args_a9(DI), R13 // a9 | 43 | + | MOVQ syscall9Args_f8(DI), X7 // f8 |
| 44 | - | MOVQ syscall9Args_a1(DI), DI // a1 | 44 | + | |
| 45 | - | 45 | + | MOVQ syscall9Args_fn(DI), R10 // fn | |
| 46 | - | // these may be float arguments | 46 | + | MOVQ syscall9Args_a2(DI), SI // a2 |
| 47 | - | // so we put them also where C expects floats | 47 | + | MOVQ syscall9Args_a3(DI), DX // a3 |
| 48 | - | MOVQ DI, X0 // a1 | 48 | + | MOVQ syscall9Args_a4(DI), CX // a4 |
| 49 | - | MOVQ SI, X1 // a2 | 49 | + | MOVQ syscall9Args_a5(DI), R8 // a5 |
| 50 | - | MOVQ DX, X2 // a3 | 50 | + | MOVQ syscall9Args_a6(DI), R9 // a6 |
| 51 | - | MOVQ CX, X3 // a4 | 51 | + | MOVQ syscall9Args_a7(DI), R11 // a7 |
| 52 | - | MOVQ R8, X4 // a5 | 52 | + | MOVQ syscall9Args_a8(DI), R12 // a8 |
| 53 | - | MOVQ R9, X5 // a6 | 53 | + | MOVQ syscall9Args_a9(DI), R13 // a9 |
| 54 | - | MOVQ R11, X6 // a7 | 54 | + | MOVQ syscall9Args_a1(DI), DI // a1 |
| 55 | - | MOVQ R12, X7 // a8 | |||
| 56 | 55 | ||||
| 57 | // push the remaining paramters onto the stack | 56 | // push the remaining paramters onto the stack | ||
| 58 | MOVQ R11, 0(SP) // push a7 | 57 | MOVQ R11, 0(SP) // push a7 | ||
M sys_darwin_arm64.s +9 -11
| @@ -31,6 +31,15 @@ TEXT syscall9X(SB), NOSPLIT, $0 | |||
| 31 | 31 | SUB $16, RSP // push structure pointer | |
| 32 | 32 | MOVD R0, 8(RSP) | |
| 33 | 33 | ||
| 34 | + | FMOVD syscall9Args_f1(R0), F0 // f1 | |
| 35 | + | FMOVD syscall9Args_f2(R0), F1 // f2 | |
| 36 | + | FMOVD syscall9Args_f3(R0), F2 // f3 | |
| 37 | + | FMOVD syscall9Args_f4(R0), F3 // f4 | |
| 38 | + | FMOVD syscall9Args_f5(R0), F4 // f5 | |
| 39 | + | FMOVD syscall9Args_f6(R0), F5 // f6 | |
| 40 | + | FMOVD syscall9Args_f7(R0), F6 // f7 | |
| 41 | + | FMOVD syscall9Args_f8(R0), F7 // f8 | |
| 42 | + | ||
| 34 | 43 | MOVD syscall9Args_fn(R0), R12 // fn | |
| 35 | 44 | MOVD syscall9Args_a2(R0), R1 // a2 | |
| 36 | 45 | MOVD syscall9Args_a3(R0), R2 // a3 | |
| @@ -42,17 +51,6 @@ TEXT syscall9X(SB), NOSPLIT, $0 | |||
| 42 | 51 | MOVD syscall9Args_a9(R0), R8 // a9 | |
| 43 | 52 | MOVD syscall9Args_a1(R0), R0 // a1 | |
| 44 | 53 | ||
| 45 | - | // these may be float arguments | |
| 46 | - | // so we put them also where C expects floats | |
| 47 | - | FMOVD R0, F0 // a1 | |
| 48 | - | FMOVD R1, F1 // a2 | |
| 49 | - | FMOVD R2, F2 // a3 | |
| 50 | - | FMOVD R3, F3 // a4 | |
| 51 | - | FMOVD R4, F4 // a5 | |
| 52 | - | FMOVD R5, F5 // a6 | |
| 53 | - | FMOVD R6, F6 // a7 | |
| 54 | - | FMOVD R7, F7 // a8 | |
| 55 | - | ||
| 56 | 54 | MOVD R8, (RSP) // push a9 onto stack | |
| 57 | 55 | ||
| 58 | 56 | BL (R12) | |
| @@ -31,6 +31,15 @@ TEXT syscall9X(SB), NOSPLIT, $0 | |||||
| 31 | SUB $16, RSP // push structure pointer | 31 | SUB $16, RSP // push structure pointer | ||
| 32 | MOVD R0, 8(RSP) | 32 | MOVD R0, 8(RSP) | ||
| 33 | 33 | ||||
| 34 | + | FMOVD syscall9Args_f1(R0), F0 // f1 | |||
| 35 | + | FMOVD syscall9Args_f2(R0), F1 // f2 | |||
| 36 | + | FMOVD syscall9Args_f3(R0), F2 // f3 | |||
| 37 | + | FMOVD syscall9Args_f4(R0), F3 // f4 | |||
| 38 | + | FMOVD syscall9Args_f5(R0), F4 // f5 | |||
| 39 | + | FMOVD syscall9Args_f6(R0), F5 // f6 | |||
| 40 | + | FMOVD syscall9Args_f7(R0), F6 // f7 | |||
| 41 | + | FMOVD syscall9Args_f8(R0), F7 // f8 | |||
| 42 | + | ||||
| 34 | MOVD syscall9Args_fn(R0), R12 // fn | 43 | MOVD syscall9Args_fn(R0), R12 // fn | ||
| 35 | MOVD syscall9Args_a2(R0), R1 // a2 | 44 | MOVD syscall9Args_a2(R0), R1 // a2 | ||
| 36 | MOVD syscall9Args_a3(R0), R2 // a3 | 45 | MOVD syscall9Args_a3(R0), R2 // a3 | ||
| @@ -42,17 +51,6 @@ TEXT syscall9X(SB), NOSPLIT, $0 | |||||
| 42 | MOVD syscall9Args_a9(R0), R8 // a9 | 51 | MOVD syscall9Args_a9(R0), R8 // a9 | ||
| 43 | MOVD syscall9Args_a1(R0), R0 // a1 | 52 | MOVD syscall9Args_a1(R0), R0 // a1 | ||
| 44 | 53 | ||||
| 45 | - | // these may be float arguments | |||
| 46 | - | // so we put them also where C expects floats | |||
| 47 | - | FMOVD R0, F0 // a1 | |||
| 48 | - | FMOVD R1, F1 // a2 | |||
| 49 | - | FMOVD R2, F2 // a3 | |||
| 50 | - | FMOVD R3, F3 // a4 | |||
| 51 | - | FMOVD R4, F4 // a5 | |||
| 52 | - | FMOVD R5, F5 // a6 | |||
| 53 | - | FMOVD R6, F6 // a7 | |||
| 54 | - | FMOVD R7, F7 // a8 | |||
| 55 | - | ||||
| 56 | MOVD R8, (RSP) // push a9 onto stack | 54 | MOVD R8, (RSP) // push a9 onto stack | ||
| 57 | 55 | ||||
| 58 | BL (R12) | 56 | BL (R12) | ||
M syscall_darwin.go +11 -2
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | package purego | |
| 5 | 5 | ||
| 6 | 6 | import ( | |
| 7 | + | "math" | |
| 7 | 8 | "reflect" | |
| 8 | 9 | "runtime" | |
| 9 | 10 | "sync" | |
| @@ -12,11 +13,19 @@ import ( | |||
| 12 | 13 | ||
| 13 | 14 | var syscall9XABI0 uintptr | |
| 14 | 15 | ||
| 15 | - | type syscall9Args struct{ fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2, err uintptr } | |
| 16 | + | type syscall9Args struct { | |
| 17 | + | fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr | |
| 18 | + | f1, f2, f3, f4, f5, f6, f7, f8 float64 | |
| 19 | + | r1, r2, err uintptr | |
| 20 | + | } | |
| 16 | 21 | ||
| 17 | 22 | //go:nosplit | |
| 18 | 23 | func syscall_syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) { | |
| 19 | - | args := syscall9Args{fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2, err} | |
| 24 | + | args := syscall9Args{fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, | |
| 25 | + | math.Float64frombits(uint64(a1)), math.Float64frombits(uint64(a2)), math.Float64frombits(uint64(a3)), | |
| 26 | + | math.Float64frombits(uint64(a4)), math.Float64frombits(uint64(a5)), math.Float64frombits(uint64(a6)), | |
| 27 | + | math.Float64frombits(uint64(a7)), math.Float64frombits(uint64(a8)), | |
| 28 | + | r1, r2, err} | |
| 20 | 29 | runtime_cgocall(syscall9XABI0, unsafe.Pointer(&args)) | |
| 21 | 30 | return args.r1, args.r2, args.err | |
| 22 | 31 | } | |
| @@ -4,6 +4,7 @@ | |||||
| 4 | package purego | 4 | package purego | ||
| 5 | 5 | ||||
| 6 | import ( | 6 | import ( | ||
| 7 | + | "math" | |||
| 7 | "reflect" | 8 | "reflect" | ||
| 8 | "runtime" | 9 | "runtime" | ||
| 9 | "sync" | 10 | "sync" | ||
| @@ -12,11 +13,19 @@ import ( | |||||
| 12 | 13 | ||||
| 13 | var syscall9XABI0 uintptr | 14 | var syscall9XABI0 uintptr | ||
| 14 | 15 | ||||
| 15 | - | type syscall9Args struct{ fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2, err uintptr } | 16 | + | type syscall9Args struct { |
| 17 | + | fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr | |||
| 18 | + | f1, f2, f3, f4, f5, f6, f7, f8 float64 | |||
| 19 | + | r1, r2, err uintptr | |||
| 20 | + | } | |||
| 16 | 21 | ||||
| 17 | //go:nosplit | 22 | //go:nosplit | ||
| 18 | func syscall_syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) { | 23 | func syscall_syscall9X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) { | ||
| 19 | - | args := syscall9Args{fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, r1, r2, err} | 24 | + | args := syscall9Args{fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, |
| 25 | + | math.Float64frombits(uint64(a1)), math.Float64frombits(uint64(a2)), math.Float64frombits(uint64(a3)), | |||
| 26 | + | math.Float64frombits(uint64(a4)), math.Float64frombits(uint64(a5)), math.Float64frombits(uint64(a6)), | |||
| 27 | + | math.Float64frombits(uint64(a7)), math.Float64frombits(uint64(a8)), | |||
| 28 | + | r1, r2, err} | |||
| 20 | runtime_cgocall(syscall9XABI0, unsafe.Pointer(&args)) | 29 | runtime_cgocall(syscall9XABI0, unsafe.Pointer(&args)) | ||
| 21 | return args.r1, args.r2, args.err | 30 | return args.r1, args.r2, args.err | ||
| 22 | } | 31 | } | ||