github.com/primecitizens/pcz/std@v0.2.1/core/reflect/call_arm64.s (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright 2023 The Prime Citizens 3 // 4 // Copyright 2018 The Go Authors. All rights reserved. 5 // Use of this source code is governed by a BSD-style 6 // license that can be found in the LICENSE file. 7 8 //go:build pcz && arm64 9 10 #include "textflag.h" 11 #include "funcdata.h" // for NO_LOCAL_POINTERS 12 13 // spillArgs stores return values from registers to a *internal/abi.RegArgs in R20. 14 TEXT ·spillArgs(SB),NOSPLIT,$0-0 15 STP (R0, R1), (0*8)(R20) 16 STP (R2, R3), (2*8)(R20) 17 STP (R4, R5), (4*8)(R20) 18 STP (R6, R7), (6*8)(R20) 19 STP (R8, R9), (8*8)(R20) 20 STP (R10, R11), (10*8)(R20) 21 STP (R12, R13), (12*8)(R20) 22 STP (R14, R15), (14*8)(R20) 23 FSTPD (F0, F1), (16*8)(R20) 24 FSTPD (F2, F3), (18*8)(R20) 25 FSTPD (F4, F5), (20*8)(R20) 26 FSTPD (F6, F7), (22*8)(R20) 27 FSTPD (F8, F9), (24*8)(R20) 28 FSTPD (F10, F11), (26*8)(R20) 29 FSTPD (F12, F13), (28*8)(R20) 30 FSTPD (F14, F15), (30*8)(R20) 31 RET 32 33 // unspillArgs loads args into registers from a *internal/abi.RegArgs in R20. 34 TEXT ·unspillArgs(SB),NOSPLIT,$0-0 35 LDP (0*8)(R20), (R0, R1) 36 LDP (2*8)(R20), (R2, R3) 37 LDP (4*8)(R20), (R4, R5) 38 LDP (6*8)(R20), (R6, R7) 39 LDP (8*8)(R20), (R8, R9) 40 LDP (10*8)(R20), (R10, R11) 41 LDP (12*8)(R20), (R12, R13) 42 LDP (14*8)(R20), (R14, R15) 43 FLDPD (16*8)(R20), (F0, F1) 44 FLDPD (18*8)(R20), (F2, F3) 45 FLDPD (20*8)(R20), (F4, F5) 46 FLDPD (22*8)(R20), (F6, F7) 47 FLDPD (24*8)(R20), (F8, F9) 48 FLDPD (26*8)(R20), (F10, F11) 49 FLDPD (28*8)(R20), (F12, F13) 50 FLDPD (30*8)(R20), (F14, F15) 51 RET 52 53 // reflectcall: call a function with the given argument list 54 // func call(stackArgsType *_type, f *FuncVal, stackArgs *byte, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs). 55 // we don't have variable-sized frames, so we use a small number 56 // of constant-sized-frame functions to encode a few bits of size in the pc. 57 // Caution: ugly multiline assembly macros in your future! 58 59 #define DISPATCH(NAME,MAXSIZE) \ 60 MOVD $MAXSIZE, R27; \ 61 CMP R27, R16; \ 62 BGT 3(PC); \ 63 MOVD $NAME(SB), R27; \ 64 B (R27) 65 // Note: can't just "B NAME(SB)" - bad inlining results. 66 67 TEXT ·Call(SB), NOSPLIT|NOFRAME, $0-48 68 MOVWU frameSize+32(FP), R16 69 DISPATCH(·call16, 16) 70 DISPATCH(·call32, 32) 71 DISPATCH(·call64, 64) 72 DISPATCH(·call128, 128) 73 DISPATCH(·call256, 256) 74 DISPATCH(·call512, 512) 75 DISPATCH(·call1024, 1024) 76 DISPATCH(·call2048, 2048) 77 DISPATCH(·call4096, 4096) 78 DISPATCH(·call8192, 8192) 79 DISPATCH(·call16384, 16384) 80 DISPATCH(·call32768, 32768) 81 DISPATCH(·call65536, 65536) 82 DISPATCH(·call131072, 131072) 83 DISPATCH(·call262144, 262144) 84 DISPATCH(·call524288, 524288) 85 DISPATCH(·call1048576, 1048576) 86 DISPATCH(·call2097152, 2097152) 87 DISPATCH(·call4194304, 4194304) 88 DISPATCH(·call8388608, 8388608) 89 DISPATCH(·call16777216, 16777216) 90 DISPATCH(·call33554432, 33554432) 91 DISPATCH(·call67108864, 67108864) 92 DISPATCH(·call134217728, 134217728) 93 DISPATCH(·call268435456, 268435456) 94 DISPATCH(·call536870912, 536870912) 95 DISPATCH(·call1073741824, 1073741824) 96 MOVD $·badreflectcall(SB), R0 97 B (R0) 98 99 #define CALLFN(NAME,MAXSIZE) \ 100 TEXT NAME(SB), WRAPPER, $MAXSIZE-48; \ 101 NO_LOCAL_POINTERS; \ 102 /* copy arguments to stack */ \ 103 MOVD stackArgs+16(FP), R3; \ 104 MOVWU stackArgsSize+24(FP), R4; \ 105 ADD $8, RSP, R5; \ 106 BIC $0xf, R4, R6; \ 107 CBZ R6, 6(PC); \ 108 /* if R6=(argsize&~15) != 0 */ \ 109 ADD R6, R5, R6; \ 110 /* copy 16 bytes a time */ \ 111 LDP.P 16(R3), (R7, R8); \ 112 STP.P (R7, R8), 16(R5); \ 113 CMP R5, R6; \ 114 BNE -3(PC); \ 115 AND $0xf, R4, R6; \ 116 CBZ R6, 6(PC); \ 117 /* if R6=(argsize&15) != 0 */ \ 118 ADD R6, R5, R6; \ 119 /* copy 1 byte a time for the rest */ \ 120 MOVBU.P 1(R3), R7; \ 121 MOVBU.P R7, 1(R5); \ 122 CMP R5, R6; \ 123 BNE -3(PC); \ 124 /* set up argument registers */ \ 125 MOVD regArgs+40(FP), R20; \ 126 CALL ·unspillArgs(SB); \ 127 /* call function */ \ 128 MOVD f+8(FP), R26; \ 129 MOVD (R26), R20; \ 130 PCDATA $PCDATA_StackMapIndex, $0; \ 131 BL (R20); \ 132 /* copy return values back */ \ 133 MOVD regArgs+40(FP), R20; \ 134 CALL ·spillArgs(SB); \ 135 MOVD stackArgsType+0(FP), R7; \ 136 MOVD stackArgs+16(FP), R3; \ 137 MOVWU stackArgsSize+24(FP), R4; \ 138 MOVWU stackRetOffset+28(FP), R6; \ 139 ADD $8, RSP, R5; \ 140 ADD R6, R5; \ 141 ADD R6, R3; \ 142 SUB R6, R4; \ 143 BL callRet<>(SB); \ 144 RET 145 146 // callRet copies return values back at the end of call*. This is a 147 // separate function so it can allocate stack space for the arguments 148 // to reflectcallmove. It does not follow the Go ABI; it expects its 149 // arguments in registers. 150 TEXT callRet<>(SB), NOSPLIT, $48-0 151 NO_LOCAL_POINTERS 152 STP (R7, R3), 8(RSP) 153 STP (R5, R4), 24(RSP) 154 MOVD R20, 40(RSP) 155 BL ·reflectcallmove(SB) 156 RET 157 158 CALLFN(·call16, 16) 159 CALLFN(·call32, 32) 160 CALLFN(·call64, 64) 161 CALLFN(·call128, 128) 162 CALLFN(·call256, 256) 163 CALLFN(·call512, 512) 164 CALLFN(·call1024, 1024) 165 CALLFN(·call2048, 2048) 166 CALLFN(·call4096, 4096) 167 CALLFN(·call8192, 8192) 168 CALLFN(·call16384, 16384) 169 CALLFN(·call32768, 32768) 170 CALLFN(·call65536, 65536) 171 CALLFN(·call131072, 131072) 172 CALLFN(·call262144, 262144) 173 CALLFN(·call524288, 524288) 174 CALLFN(·call1048576, 1048576) 175 CALLFN(·call2097152, 2097152) 176 CALLFN(·call4194304, 4194304) 177 CALLFN(·call8388608, 8388608) 178 CALLFN(·call16777216, 16777216) 179 CALLFN(·call33554432, 33554432) 180 CALLFN(·call67108864, 67108864) 181 CALLFN(·call134217728, 134217728) 182 CALLFN(·call268435456, 268435456) 183 CALLFN(·call536870912, 536870912) 184 CALLFN(·call1073741824, 1073741824)