1// Copyright 2023 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Macros for transitioning from the host ABI to Go ABI
6//
7// On PPC64/ELFv2 targets, the following registers are callee
8// saved when called from C. They must be preserved before
9// calling into Go which does not preserve any of them.
10//
11// R14-R31
12// CR2-4
13// VR20-31
14// F14-F31
15//
16// xcoff(aix) and ELFv1 are similar, but may only require a
17// subset of these.
18//
19// These macros assume a 16 byte aligned stack pointer. This
20// is required by ELFv1, ELFv2, and AIX PPC64.
21
22#define SAVE_GPR_SIZE (18*8)
23#define SAVE_GPR(offset) \
24 MOVD R14, (offset+8*0)(R1) \
25 MOVD R15, (offset+8*1)(R1) \
26 MOVD R16, (offset+8*2)(R1) \
27 MOVD R17, (offset+8*3)(R1) \
28 MOVD R18, (offset+8*4)(R1) \
29 MOVD R19, (offset+8*5)(R1) \
30 MOVD R20, (offset+8*6)(R1) \
31 MOVD R21, (offset+8*7)(R1) \
32 MOVD R22, (offset+8*8)(R1) \
33 MOVD R23, (offset+8*9)(R1) \
34 MOVD R24, (offset+8*10)(R1) \
35 MOVD R25, (offset+8*11)(R1) \
36 MOVD R26, (offset+8*12)(R1) \
37 MOVD R27, (offset+8*13)(R1) \
38 MOVD R28, (offset+8*14)(R1) \
39 MOVD R29, (offset+8*15)(R1) \
40 MOVD g, (offset+8*16)(R1) \
41 MOVD R31, (offset+8*17)(R1)
42
43#define RESTORE_GPR(offset) \
44 MOVD (offset+8*0)(R1), R14 \
45 MOVD (offset+8*1)(R1), R15 \
46 MOVD (offset+8*2)(R1), R16 \
47 MOVD (offset+8*3)(R1), R17 \
48 MOVD (offset+8*4)(R1), R18 \
49 MOVD (offset+8*5)(R1), R19 \
50 MOVD (offset+8*6)(R1), R20 \
51 MOVD (offset+8*7)(R1), R21 \
52 MOVD (offset+8*8)(R1), R22 \
53 MOVD (offset+8*9)(R1), R23 \
54 MOVD (offset+8*10)(R1), R24 \
55 MOVD (offset+8*11)(R1), R25 \
56 MOVD (offset+8*12)(R1), R26 \
57 MOVD (offset+8*13)(R1), R27 \
58 MOVD (offset+8*14)(R1), R28 \
59 MOVD (offset+8*15)(R1), R29 \
60 MOVD (offset+8*16)(R1), g \
61 MOVD (offset+8*17)(R1), R31
62
63#define SAVE_FPR_SIZE (18*8)
64#define SAVE_FPR(offset) \
65 FMOVD F14, (offset+8*0)(R1) \
66 FMOVD F15, (offset+8*1)(R1) \
67 FMOVD F16, (offset+8*2)(R1) \
68 FMOVD F17, (offset+8*3)(R1) \
69 FMOVD F18, (offset+8*4)(R1) \
70 FMOVD F19, (offset+8*5)(R1) \
71 FMOVD F20, (offset+8*6)(R1) \
72 FMOVD F21, (offset+8*7)(R1) \
73 FMOVD F22, (offset+8*8)(R1) \
74 FMOVD F23, (offset+8*9)(R1) \
75 FMOVD F24, (offset+8*10)(R1) \
76 FMOVD F25, (offset+8*11)(R1) \
77 FMOVD F26, (offset+8*12)(R1) \
78 FMOVD F27, (offset+8*13)(R1) \
79 FMOVD F28, (offset+8*14)(R1) \
80 FMOVD F29, (offset+8*15)(R1) \
81 FMOVD F30, (offset+8*16)(R1) \
82 FMOVD F31, (offset+8*17)(R1)
83
84#define RESTORE_FPR(offset) \
85 FMOVD (offset+8*0)(R1), F14 \
86 FMOVD (offset+8*1)(R1), F15 \
87 FMOVD (offset+8*2)(R1), F16 \
88 FMOVD (offset+8*3)(R1), F17 \
89 FMOVD (offset+8*4)(R1), F18 \
90 FMOVD (offset+8*5)(R1), F19 \
91 FMOVD (offset+8*6)(R1), F20 \
92 FMOVD (offset+8*7)(R1), F21 \
93 FMOVD (offset+8*8)(R1), F22 \
94 FMOVD (offset+8*9)(R1), F23 \
95 FMOVD (offset+8*10)(R1), F24 \
96 FMOVD (offset+8*11)(R1), F25 \
97 FMOVD (offset+8*12)(R1), F26 \
98 FMOVD (offset+8*13)(R1), F27 \
99 FMOVD (offset+8*14)(R1), F28 \
100 FMOVD (offset+8*15)(R1), F29 \
101 FMOVD (offset+8*16)(R1), F30 \
102 FMOVD (offset+8*17)(R1), F31
103
104// Save and restore VR20-31 (aka VSR56-63). These
105// macros must point to a 16B aligned offset.
106#define SAVE_VR_SIZE (12*16)
107#define SAVE_VR(offset, rtmp) \
108 MOVD $(offset+16*0), rtmp \
109 STVX V20, (rtmp)(R1) \
110 MOVD $(offset+16*1), rtmp \
111 STVX V21, (rtmp)(R1) \
112 MOVD $(offset+16*2), rtmp \
113 STVX V22, (rtmp)(R1) \
114 MOVD $(offset+16*3), rtmp \
115 STVX V23, (rtmp)(R1) \
116 MOVD $(offset+16*4), rtmp \
117 STVX V24, (rtmp)(R1) \
118 MOVD $(offset+16*5), rtmp \
119 STVX V25, (rtmp)(R1) \
120 MOVD $(offset+16*6), rtmp \
121 STVX V26, (rtmp)(R1) \
122 MOVD $(offset+16*7), rtmp \
123 STVX V27, (rtmp)(R1) \
124 MOVD $(offset+16*8), rtmp \
125 STVX V28, (rtmp)(R1) \
126 MOVD $(offset+16*9), rtmp \
127 STVX V29, (rtmp)(R1) \
128 MOVD $(offset+16*10), rtmp \
129 STVX V30, (rtmp)(R1) \
130 MOVD $(offset+16*11), rtmp \
131 STVX V31, (rtmp)(R1)
132
133#define RESTORE_VR(offset, rtmp) \
134 MOVD $(offset+16*0), rtmp \
135 LVX (rtmp)(R1), V20 \
136 MOVD $(offset+16*1), rtmp \
137 LVX (rtmp)(R1), V21 \
138 MOVD $(offset+16*2), rtmp \
139 LVX (rtmp)(R1), V22 \
140 MOVD $(offset+16*3), rtmp \
141 LVX (rtmp)(R1), V23 \
142 MOVD $(offset+16*4), rtmp \
143 LVX (rtmp)(R1), V24 \
144 MOVD $(offset+16*5), rtmp \
145 LVX (rtmp)(R1), V25 \
146 MOVD $(offset+16*6), rtmp \
147 LVX (rtmp)(R1), V26 \
148 MOVD $(offset+16*7), rtmp \
149 LVX (rtmp)(R1), V27 \
150 MOVD $(offset+16*8), rtmp \
151 LVX (rtmp)(R1), V28 \
152 MOVD $(offset+16*9), rtmp \
153 LVX (rtmp)(R1), V29 \
154 MOVD $(offset+16*10), rtmp \
155 LVX (rtmp)(R1), V30 \
156 MOVD $(offset+16*11), rtmp \
157 LVX (rtmp)(R1), V31
158
159// LR and CR are saved in the caller's frame. The callee must
160// make space for all other callee-save registers.
161#define SAVE_ALL_REG_SIZE (SAVE_GPR_SIZE+SAVE_FPR_SIZE+SAVE_VR_SIZE)
162
163// Stack a frame and save all callee-save registers following the
164// host OS's ABI. Fortunately, this is identical for AIX, ELFv1, and
165// ELFv2. All host ABIs require the stack pointer to maintain 16 byte
166// alignment, and save the callee-save registers in the same places.
167//
168// To restate, R1 is assumed to be aligned when this macro is used.
169// This assumes the caller's frame is compliant with the host ABI.
170// CR and LR are saved into the caller's frame per the host ABI.
171// R0 is initialized to $0 as expected by Go.
172#define STACK_AND_SAVE_HOST_TO_GO_ABI(extra) \
173 MOVD LR, R0 \
174 MOVD R0, 16(R1) \
175 MOVW CR, R0 \
176 MOVD R0, 8(R1) \
177 MOVDU R1, -(extra)-FIXED_FRAME-SAVE_ALL_REG_SIZE(R1) \
178 SAVE_GPR(extra+FIXED_FRAME) \
179 SAVE_FPR(extra+FIXED_FRAME+SAVE_GPR_SIZE) \
180 SAVE_VR(extra+FIXED_FRAME+SAVE_GPR_SIZE+SAVE_FPR_SIZE, R0) \
181 MOVD $0, R0
182
183// This unstacks the frame, restoring all callee-save registers
184// as saved by STACK_AND_SAVE_HOST_TO_GO_ABI.
185//
186// R0 is not guaranteed to contain $0 after this macro.
187#define UNSTACK_AND_RESTORE_GO_TO_HOST_ABI(extra) \
188 RESTORE_GPR(extra+FIXED_FRAME) \
189 RESTORE_FPR(extra+FIXED_FRAME+SAVE_GPR_SIZE) \
190 RESTORE_VR(extra+FIXED_FRAME+SAVE_GPR_SIZE+SAVE_FPR_SIZE, R0) \
191 ADD $(extra+FIXED_FRAME+SAVE_ALL_REG_SIZE), R1 \
192 MOVD 16(R1), R0 \
193 MOVD R0, LR \
194 MOVD 8(R1), R0 \
195 MOVW R0, CR
View as plain text