48 import static jdk.vm.ci.sparc.SPARC.i5;
49 import static jdk.vm.ci.sparc.SPARC.i6;
50 import static jdk.vm.ci.sparc.SPARC.i7;
51 import static jdk.vm.ci.sparc.SPARC.l0;
52 import static jdk.vm.ci.sparc.SPARC.l1;
53 import static jdk.vm.ci.sparc.SPARC.l2;
54 import static jdk.vm.ci.sparc.SPARC.l3;
55 import static jdk.vm.ci.sparc.SPARC.l4;
56 import static jdk.vm.ci.sparc.SPARC.l5;
57 import static jdk.vm.ci.sparc.SPARC.l6;
58 import static jdk.vm.ci.sparc.SPARC.l7;
59 import static jdk.vm.ci.sparc.SPARC.o0;
60 import static jdk.vm.ci.sparc.SPARC.o1;
61 import static jdk.vm.ci.sparc.SPARC.o2;
62 import static jdk.vm.ci.sparc.SPARC.o3;
63 import static jdk.vm.ci.sparc.SPARC.o4;
64 import static jdk.vm.ci.sparc.SPARC.o5;
65 import static jdk.vm.ci.sparc.SPARC.sp;
66
67 import java.util.ArrayList;
68 import java.util.Arrays;
69 import java.util.Collections;
70 import java.util.HashSet;
71 import java.util.List;
72
73 import jdk.vm.ci.code.Architecture;
74 import jdk.vm.ci.code.CallingConvention;
75 import jdk.vm.ci.code.CallingConvention.Type;
76 import jdk.vm.ci.code.Register;
77 import jdk.vm.ci.code.RegisterAttributes;
78 import jdk.vm.ci.code.RegisterConfig;
79 import jdk.vm.ci.code.StackSlot;
80 import jdk.vm.ci.code.TargetDescription;
81 import jdk.vm.ci.code.ValueKindFactory;
82 import jdk.vm.ci.common.JVMCIError;
83 import jdk.vm.ci.hotspot.HotSpotCallingConventionType;
84 import jdk.vm.ci.meta.AllocatableValue;
85 import jdk.vm.ci.meta.JavaKind;
86 import jdk.vm.ci.meta.JavaType;
87 import jdk.vm.ci.meta.PlatformKind;
88 import jdk.vm.ci.meta.ValueKind;
89 import jdk.vm.ci.sparc.SPARC;
90
91 public class SPARCHotSpotRegisterConfig implements RegisterConfig {
92
93 private final TargetDescription target;
94
95 private final Register[] allocatable;
96
97 private final RegisterAttributes[] attributesMap;
98
99 /**
100 * Does native code (C++ code) spill arguments in registers to the parent frame?
101 */
102 private final boolean addNativeRegisterArgumentSlots;
103
104 @Override
105 public Register[] getAllocatableRegisters() {
106 return allocatable.clone();
107 }
108
109 @Override
110 public Register[] filterAllocatableRegisters(PlatformKind kind, Register[] registers) {
111 ArrayList<Register> list = new ArrayList<>();
112 for (Register reg : registers) {
113 if (target.arch.canStoreValue(reg.getRegisterCategory(), kind)) {
114 list.add(reg);
115 }
116 }
117 Register[] ret = list.toArray(new Register[list.size()]);
118 return ret;
119 }
120
121 @Override
122 public RegisterAttributes[] getAttributesMap() {
123 return attributesMap.clone();
124 }
125
126 private final Register[] cpuCallerParameterRegisters = {o0, o1, o2, o3, o4, o5};
127 private final Register[] cpuCalleeParameterRegisters = {i0, i1, i2, i3, i4, i5};
128
129 private final Register[] fpuFloatParameterRegisters = {f0, f1, f2, f3, f4, f5, f6, f7};
130 private final Register[] fpuDoubleParameterRegisters = {d0, null, d2, null, d4, null, d6, null};
131
132 // @formatter:off
133 private final Register[] callerSaveRegisters;
134
135 /**
136 * This lists all L and I registers which are saved in the register window.
137 */
138 private final Register[] windowSaveRegisters = {
139 l0, l1, l2, l3, l4, l5, l6, l7,
140 i0, i1, i2, i3, i4, i5, i6, i7};
141 // @formatter:on
142
143 private static final Register[] reservedRegisters = {sp, g0, g2};
144
145 private static Register[] initAllocatable(Architecture arch, boolean reserveForHeapBase) {
146 Register[] allRegisters = arch.getAvailableValueRegisters();
147 Register[] registers = new Register[allRegisters.length - reservedRegisters.length - (reserveForHeapBase ? 1 : 0)];
148 List<Register> reservedRegistersList = Arrays.asList(reservedRegisters);
149
150 int idx = 0;
151 for (Register reg : allRegisters) {
152 if (reservedRegistersList.contains(reg)) {
153 // skip reserved registers
154 continue;
155 }
156 if (reserveForHeapBase && reg.equals(g6)) {
157 // skip heap base register
158 continue;
159 }
160
161 registers[idx++] = reg;
162 }
163
164 assert idx == registers.length;
165 return registers;
166 }
167
168 public SPARCHotSpotRegisterConfig(TargetDescription target, boolean useCompressedOops) {
169 this(target, initAllocatable(target.arch, useCompressedOops));
170 }
171
172 public SPARCHotSpotRegisterConfig(TargetDescription target, Register[] allocatable) {
173 this.target = target;
174 this.allocatable = allocatable.clone();
175 this.addNativeRegisterArgumentSlots = false;
176 HashSet<Register> callerSaveSet = new HashSet<>();
177 Collections.addAll(callerSaveSet, target.arch.getAvailableValueRegisters());
178 for (Register cs : windowSaveRegisters) {
179 callerSaveSet.remove(cs);
180 }
181 this.callerSaveRegisters = callerSaveSet.toArray(new Register[callerSaveSet.size()]);
182 attributesMap = RegisterAttributes.createMap(this, SPARC.allRegisters);
183 }
184
185 @Override
186 public Register[] getCallerSaveRegisters() {
187 return callerSaveRegisters;
188 }
189
190 @Override
191 public Register[] getCalleeSaveRegisters() {
192 return null;
193 }
194
195 @Override
196 public boolean areAllAllocatableRegistersCallerSaved() {
197 return false;
198 }
199
200 @Override
201 public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, ValueKindFactory<?> valueKindFactory) {
202 HotSpotCallingConventionType hotspotType = (HotSpotCallingConventionType) type;
203 if (type == HotSpotCallingConventionType.JavaCall || type == HotSpotCallingConventionType.NativeCall) {
204 return callingConvention(cpuCallerParameterRegisters, returnType, parameterTypes, hotspotType, valueKindFactory);
205 }
206 if (type == HotSpotCallingConventionType.JavaCallee) {
207 return callingConvention(cpuCalleeParameterRegisters, returnType, parameterTypes, hotspotType, valueKindFactory);
208 }
209 throw JVMCIError.shouldNotReachHere();
210 }
211
212 @Override
213 public Register[] getCallingConventionRegisters(Type type, JavaKind kind) {
214 HotSpotCallingConventionType hotspotType = (HotSpotCallingConventionType) type;
215 switch (kind) {
216 case Boolean:
217 case Byte:
218 case Short:
219 case Char:
220 case Int:
221 case Long:
222 case Object:
223 return hotspotType == HotSpotCallingConventionType.JavaCallee ? cpuCalleeParameterRegisters : cpuCallerParameterRegisters;
224 case Double:
225 case Float:
226 return fpuFloatParameterRegisters;
227 default:
228 throw JVMCIError.shouldNotReachHere("Unknown JavaKind " + kind);
229 }
230 }
231
232 private CallingConvention callingConvention(Register[] generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, HotSpotCallingConventionType type,
233 ValueKindFactory<?> valueKindFactory) {
234 AllocatableValue[] locations = new AllocatableValue[parameterTypes.length];
235
236 int currentGeneral = 0;
237 int currentFloating = 0;
238 int currentStackOffset = 0;
239
240 for (int i = 0; i < parameterTypes.length; i++) {
241 final JavaKind kind = parameterTypes[i].getJavaKind().getStackKind();
242
243 switch (kind) {
244 case Byte:
245 case Boolean:
246 case Short:
247 case Char:
248 case Int:
249 case Long:
250 case Object:
251 if (currentGeneral < generalParameterRegisters.length) {
252 Register register = generalParameterRegisters[currentGeneral++];
253 locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
254 }
255 break;
256 case Double:
257 if (currentFloating < fpuFloatParameterRegisters.length) {
258 if (currentFloating % 2 != 0) {
259 // Make register number even to be a double reg
260 currentFloating++;
261 }
262 Register register = fpuDoubleParameterRegisters[currentFloating];
263 currentFloating += 2; // Only every second is a double register
264 locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
265 }
266 break;
267 case Float:
268 if (currentFloating < fpuFloatParameterRegisters.length) {
269 Register register = fpuFloatParameterRegisters[currentFloating++];
270 locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
271 }
272 break;
273 default:
274 throw JVMCIError.shouldNotReachHere();
275 }
276
277 if (locations[i] == null) {
278 ValueKind<?> valueKind = valueKindFactory.getValueKind(kind);
279 // Stack slot is always aligned to its size in bytes but minimum wordsize
280 int typeSize = valueKind.getPlatformKind().getSizeInBytes();
281 currentStackOffset = roundUp(currentStackOffset, typeSize);
282 int slotOffset = currentStackOffset + REGISTER_SAFE_AREA_SIZE;
283 locations[i] = StackSlot.get(valueKind, slotOffset, !type.out);
284 currentStackOffset += typeSize;
285 }
286 }
287
288 JavaKind returnKind = returnType == null ? Void : returnType.getJavaKind();
289 AllocatableValue returnLocation = returnKind == Void ? ILLEGAL : getReturnRegister(returnKind, type).asValue(valueKindFactory.getValueKind(returnKind.getStackKind()));
290
291 int outArgSpillArea;
292 if (type == HotSpotCallingConventionType.NativeCall && addNativeRegisterArgumentSlots) {
293 // Space for native callee which may spill our outgoing arguments
294 outArgSpillArea = Math.min(locations.length, generalParameterRegisters.length) * target.wordSize;
295 } else {
296 outArgSpillArea = 0;
297 }
298 return new CallingConvention(currentStackOffset + outArgSpillArea, returnLocation, locations);
299 }
300
301 private static int roundUp(int number, int mod) {
302 return ((number + mod - 1) / mod) * mod;
303 }
304
305 @Override
306 public Register getReturnRegister(JavaKind kind) {
307 return getReturnRegister(kind, HotSpotCallingConventionType.JavaCallee);
308 }
309
310 private static Register getReturnRegister(JavaKind kind, HotSpotCallingConventionType type) {
311 switch (kind) {
312 case Boolean:
313 case Byte:
314 case Char:
319 return type == HotSpotCallingConventionType.JavaCallee ? i0 : o0;
320 case Float:
321 return f0;
322 case Double:
323 return d0;
324 case Void:
325 case Illegal:
326 return null;
327 default:
328 throw new UnsupportedOperationException("no return register for type " + kind);
329 }
330 }
331
332 @Override
333 public Register getFrameRegister() {
334 return sp;
335 }
336
337 @Override
338 public String toString() {
339 return String.format("Allocatable: " + Arrays.toString(getAllocatableRegisters()) + "%n" + "CallerSave: " + Arrays.toString(getCallerSaveRegisters()) + "%n");
340 }
341 }
|
48 import static jdk.vm.ci.sparc.SPARC.i5;
49 import static jdk.vm.ci.sparc.SPARC.i6;
50 import static jdk.vm.ci.sparc.SPARC.i7;
51 import static jdk.vm.ci.sparc.SPARC.l0;
52 import static jdk.vm.ci.sparc.SPARC.l1;
53 import static jdk.vm.ci.sparc.SPARC.l2;
54 import static jdk.vm.ci.sparc.SPARC.l3;
55 import static jdk.vm.ci.sparc.SPARC.l4;
56 import static jdk.vm.ci.sparc.SPARC.l5;
57 import static jdk.vm.ci.sparc.SPARC.l6;
58 import static jdk.vm.ci.sparc.SPARC.l7;
59 import static jdk.vm.ci.sparc.SPARC.o0;
60 import static jdk.vm.ci.sparc.SPARC.o1;
61 import static jdk.vm.ci.sparc.SPARC.o2;
62 import static jdk.vm.ci.sparc.SPARC.o3;
63 import static jdk.vm.ci.sparc.SPARC.o4;
64 import static jdk.vm.ci.sparc.SPARC.o5;
65 import static jdk.vm.ci.sparc.SPARC.sp;
66
67 import java.util.ArrayList;
68 import java.util.HashSet;
69 import java.util.List;
70
71 import jdk.vm.ci.code.Architecture;
72 import jdk.vm.ci.code.CallingConvention;
73 import jdk.vm.ci.code.CallingConvention.Type;
74 import jdk.vm.ci.code.Register;
75 import jdk.vm.ci.code.RegisterArray;
76 import jdk.vm.ci.code.RegisterAttributes;
77 import jdk.vm.ci.code.RegisterConfig;
78 import jdk.vm.ci.code.StackSlot;
79 import jdk.vm.ci.code.TargetDescription;
80 import jdk.vm.ci.code.ValueKindFactory;
81 import jdk.vm.ci.common.JVMCIError;
82 import jdk.vm.ci.hotspot.HotSpotCallingConventionType;
83 import jdk.vm.ci.meta.AllocatableValue;
84 import jdk.vm.ci.meta.JavaKind;
85 import jdk.vm.ci.meta.JavaType;
86 import jdk.vm.ci.meta.PlatformKind;
87 import jdk.vm.ci.meta.ValueKind;
88 import jdk.vm.ci.sparc.SPARC;
89
90 public class SPARCHotSpotRegisterConfig implements RegisterConfig {
91
92 private final TargetDescription target;
93
94 private final RegisterArray allocatable;
95
96 private final RegisterAttributes[] attributesMap;
97
98 /**
99 * Does native code (C++ code) spill arguments in registers to the parent frame?
100 */
101 private final boolean addNativeRegisterArgumentSlots;
102
103 @Override
104 public RegisterArray getAllocatableRegisters() {
105 return allocatable;
106 }
107
108 @Override
109 public RegisterArray filterAllocatableRegisters(PlatformKind kind, RegisterArray registers) {
110 ArrayList<Register> list = new ArrayList<>();
111 for (Register reg : registers) {
112 if (target.arch.canStoreValue(reg.getRegisterCategory(), kind)) {
113 list.add(reg);
114 }
115 }
116 return new RegisterArray(list);
117 }
118
119 @Override
120 public RegisterAttributes[] getAttributesMap() {
121 return attributesMap.clone();
122 }
123
124 private final RegisterArray cpuCallerParameterRegisters = new RegisterArray(o0, o1, o2, o3, o4, o5);
125 private final RegisterArray cpuCalleeParameterRegisters = new RegisterArray(i0, i1, i2, i3, i4, i5);
126
127 private final RegisterArray fpuFloatParameterRegisters = new RegisterArray(f0, f1, f2, f3, f4, f5, f6, f7);
128 private final RegisterArray fpuDoubleParameterRegisters = new RegisterArray(d0, null, d2, null, d4, null, d6, null);
129
130 // @formatter:off
131 private final RegisterArray callerSaveRegisters;
132
133 /**
134 * This lists all L and I registers which are saved in the register window.
135 */
136 private final RegisterArray windowSaveRegisters = new RegisterArray(
137 l0, l1, l2, l3, l4, l5, l6, l7,
138 i0, i1, i2, i3, i4, i5, i6, i7);
139 // @formatter:on
140
141 private static final RegisterArray reservedRegisters = new RegisterArray(sp, g0, g2);
142
143 private static RegisterArray initAllocatable(Architecture arch, boolean reserveForHeapBase) {
144 RegisterArray allRegisters = arch.getAvailableValueRegisters();
145 Register[] registers = new Register[allRegisters.size() - reservedRegisters.size() - (reserveForHeapBase ? 1 : 0)];
146 List<Register> reservedRegistersList = reservedRegisters.asList();
147
148 int idx = 0;
149 for (Register reg : allRegisters) {
150 if (reservedRegistersList.contains(reg)) {
151 // skip reserved registers
152 continue;
153 }
154 if (reserveForHeapBase && reg.equals(g6)) {
155 // skip heap base register
156 continue;
157 }
158
159 registers[idx++] = reg;
160 }
161
162 assert idx == registers.length;
163 return new RegisterArray(registers);
164 }
165
166 public SPARCHotSpotRegisterConfig(TargetDescription target, boolean useCompressedOops) {
167 this(target, initAllocatable(target.arch, useCompressedOops));
168 }
169
170 public SPARCHotSpotRegisterConfig(TargetDescription target, RegisterArray allocatable) {
171 this.target = target;
172 this.allocatable = allocatable;
173 this.addNativeRegisterArgumentSlots = false;
174 HashSet<Register> callerSaveSet = new HashSet<>(target.arch.getAvailableValueRegisters().asList());
175 for (Register cs : windowSaveRegisters) {
176 callerSaveSet.remove(cs);
177 }
178 this.callerSaveRegisters = new RegisterArray(callerSaveSet);
179 attributesMap = RegisterAttributes.createMap(this, SPARC.allRegisters);
180 }
181
182 @Override
183 public RegisterArray getCallerSaveRegisters() {
184 return callerSaveRegisters;
185 }
186
187 @Override
188 public RegisterArray getCalleeSaveRegisters() {
189 return null;
190 }
191
192 @Override
193 public boolean areAllAllocatableRegistersCallerSaved() {
194 return false;
195 }
196
197 @Override
198 public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, ValueKindFactory<?> valueKindFactory) {
199 HotSpotCallingConventionType hotspotType = (HotSpotCallingConventionType) type;
200 if (type == HotSpotCallingConventionType.JavaCall || type == HotSpotCallingConventionType.NativeCall) {
201 return callingConvention(cpuCallerParameterRegisters, returnType, parameterTypes, hotspotType, valueKindFactory);
202 }
203 if (type == HotSpotCallingConventionType.JavaCallee) {
204 return callingConvention(cpuCalleeParameterRegisters, returnType, parameterTypes, hotspotType, valueKindFactory);
205 }
206 throw JVMCIError.shouldNotReachHere();
207 }
208
209 @Override
210 public RegisterArray getCallingConventionRegisters(Type type, JavaKind kind) {
211 HotSpotCallingConventionType hotspotType = (HotSpotCallingConventionType) type;
212 switch (kind) {
213 case Boolean:
214 case Byte:
215 case Short:
216 case Char:
217 case Int:
218 case Long:
219 case Object:
220 return hotspotType == HotSpotCallingConventionType.JavaCallee ? cpuCalleeParameterRegisters : cpuCallerParameterRegisters;
221 case Double:
222 case Float:
223 return fpuFloatParameterRegisters;
224 default:
225 throw JVMCIError.shouldNotReachHere("Unknown JavaKind " + kind);
226 }
227 }
228
229 private CallingConvention callingConvention(RegisterArray generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, HotSpotCallingConventionType type,
230 ValueKindFactory<?> valueKindFactory) {
231 AllocatableValue[] locations = new AllocatableValue[parameterTypes.length];
232
233 int currentGeneral = 0;
234 int currentFloating = 0;
235 int currentStackOffset = 0;
236
237 for (int i = 0; i < parameterTypes.length; i++) {
238 final JavaKind kind = parameterTypes[i].getJavaKind().getStackKind();
239
240 switch (kind) {
241 case Byte:
242 case Boolean:
243 case Short:
244 case Char:
245 case Int:
246 case Long:
247 case Object:
248 if (currentGeneral < generalParameterRegisters.size()) {
249 Register register = generalParameterRegisters.get(currentGeneral++);
250 locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
251 }
252 break;
253 case Double:
254 if (currentFloating < fpuFloatParameterRegisters.size()) {
255 if (currentFloating % 2 != 0) {
256 // Make register number even to be a double reg
257 currentFloating++;
258 }
259 Register register = fpuDoubleParameterRegisters.get(currentFloating);
260 currentFloating += 2; // Only every second is a double register
261 locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
262 }
263 break;
264 case Float:
265 if (currentFloating < fpuFloatParameterRegisters.size()) {
266 Register register = fpuFloatParameterRegisters.get(currentFloating++);
267 locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
268 }
269 break;
270 default:
271 throw JVMCIError.shouldNotReachHere();
272 }
273
274 if (locations[i] == null) {
275 ValueKind<?> valueKind = valueKindFactory.getValueKind(kind);
276 // Stack slot is always aligned to its size in bytes but minimum wordsize
277 int typeSize = valueKind.getPlatformKind().getSizeInBytes();
278 currentStackOffset = roundUp(currentStackOffset, typeSize);
279 int slotOffset = currentStackOffset + REGISTER_SAFE_AREA_SIZE;
280 locations[i] = StackSlot.get(valueKind, slotOffset, !type.out);
281 currentStackOffset += typeSize;
282 }
283 }
284
285 JavaKind returnKind = returnType == null ? Void : returnType.getJavaKind();
286 AllocatableValue returnLocation = returnKind == Void ? ILLEGAL : getReturnRegister(returnKind, type).asValue(valueKindFactory.getValueKind(returnKind.getStackKind()));
287
288 int outArgSpillArea;
289 if (type == HotSpotCallingConventionType.NativeCall && addNativeRegisterArgumentSlots) {
290 // Space for native callee which may spill our outgoing arguments
291 outArgSpillArea = Math.min(locations.length, generalParameterRegisters.size()) * target.wordSize;
292 } else {
293 outArgSpillArea = 0;
294 }
295 return new CallingConvention(currentStackOffset + outArgSpillArea, returnLocation, locations);
296 }
297
298 private static int roundUp(int number, int mod) {
299 return ((number + mod - 1) / mod) * mod;
300 }
301
302 @Override
303 public Register getReturnRegister(JavaKind kind) {
304 return getReturnRegister(kind, HotSpotCallingConventionType.JavaCallee);
305 }
306
307 private static Register getReturnRegister(JavaKind kind, HotSpotCallingConventionType type) {
308 switch (kind) {
309 case Boolean:
310 case Byte:
311 case Char:
316 return type == HotSpotCallingConventionType.JavaCallee ? i0 : o0;
317 case Float:
318 return f0;
319 case Double:
320 return d0;
321 case Void:
322 case Illegal:
323 return null;
324 default:
325 throw new UnsupportedOperationException("no return register for type " + kind);
326 }
327 }
328
329 @Override
330 public Register getFrameRegister() {
331 return sp;
332 }
333
334 @Override
335 public String toString() {
336 return String.format("Allocatable: " + getAllocatableRegisters() + "%n" + "CallerSave: " + getCallerSaveRegisters() + "%n");
337 }
338 }
|