comparison graal/com.oracle.jvmci.hotspot.sparc/src/com/oracle/jvmci/hotspot/sparc/SPARCHotSpotRegisterConfig.java @ 21674:e0b5d4fcd929

moved HotSpotTargetDescription and [AMD64|SPARC]HotSpotRegisterConfig into JVMCI namespace (JBS:GRAAL-53)
author Doug Simon <doug.simon@oracle.com>
date Tue, 02 Jun 2015 23:29:27 +0200
parents graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java@5024c80224c7
children
comparison
equal deleted inserted replaced
21673:5024c80224c7 21674:e0b5d4fcd929
1 /*
2 * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23 package com.oracle.jvmci.hotspot.sparc;
24
25 import com.oracle.jvmci.code.Architecture;
26 import com.oracle.jvmci.code.TargetDescription;
27 import com.oracle.jvmci.code.CallingConvention;
28 import com.oracle.jvmci.code.CalleeSaveLayout;
29 import com.oracle.jvmci.code.RegisterAttributes;
30 import com.oracle.jvmci.code.StackSlot;
31 import com.oracle.jvmci.code.RegisterConfig;
32 import com.oracle.jvmci.code.Register;
33 import com.oracle.jvmci.meta.Kind;
34 import com.oracle.jvmci.meta.JavaType;
35 import com.oracle.jvmci.meta.PlatformKind;
36 import com.oracle.jvmci.meta.Value;
37 import com.oracle.jvmci.meta.AllocatableValue;
38 import com.oracle.jvmci.sparc.*;
39
40 import static com.oracle.jvmci.sparc.SPARC.*;
41
42 import java.util.*;
43
44 import com.oracle.jvmci.code.CallingConvention.Type;
45 import com.oracle.jvmci.common.*;
46 import com.oracle.jvmci.hotspot.*;
47
48 public class SPARCHotSpotRegisterConfig implements RegisterConfig {
49
50 private final Architecture architecture;
51
52 private final Register[] allocatable;
53
54 private final RegisterAttributes[] attributesMap;
55
56 @Override
57 public Register[] getAllocatableRegisters() {
58 return allocatable.clone();
59 }
60
61 public Register[] filterAllocatableRegisters(PlatformKind kind, Register[] registers) {
62 ArrayList<Register> list = new ArrayList<>();
63 for (Register reg : registers) {
64 if (architecture.canStoreValue(reg.getRegisterCategory(), kind)) {
65 // Special treatment for double precision
66 // TODO: This is wasteful it uses only half of the registers as float.
67 if (kind == Kind.Double) {
68 if (reg.name.startsWith("d")) {
69 list.add(reg);
70 }
71 } else if (kind == Kind.Float) {
72 if (reg.name.startsWith("f")) {
73 list.add(reg);
74 }
75 } else {
76 list.add(reg);
77 }
78 }
79 }
80
81 Register[] ret = list.toArray(new Register[list.size()]);
82 return ret;
83 }
84
85 @Override
86 public RegisterAttributes[] getAttributesMap() {
87 return attributesMap.clone();
88 }
89
90 private final Register[] cpuCallerParameterRegisters = {o0, o1, o2, o3, o4, o5};
91 private final Register[] cpuCalleeParameterRegisters = {i0, i1, i2, i3, i4, i5};
92
93 private final Register[] fpuParameterRegisters = {f0, f1, f2, f3, f4, f5, f6, f7};
94 private final Register[] fpuDoubleParameterRegisters = {d0, null, d2, null, d4, null, d6, null};
95 // @formatter:off
96 private final Register[] callerSaveRegisters =
97 {g1, g2, g3, g4, g5, g6, g7,
98 o0, o1, o2, o3, o4, o5, o7,
99 f0, f1, f2, f3, f4, f5, f6, f7,
100 f8, f9, f10, f11, f12, f13, f14, f15,
101 f16, f17, f18, f19, f20, f21, f22, f23,
102 f24, f25, f26, f27, f28, f29, f30, f31,
103 d32, d34, d36, d38, d40, d42, d44, d46,
104 d48, d50, d52, d54, d56, d58, d60, d62};
105 // @formatter:on
106
107 /**
108 * Registers saved by the callee. This lists all L and I registers which are saved in the
109 * register window.
110 */
111 private final Register[] calleeSaveRegisters = {l0, l1, l2, l3, l4, l5, l6, l7, i0, i1, i2, i3, i4, i5, i6, i7};
112
113 private final CalleeSaveLayout csl;
114
115 private static Register[] initAllocatable(boolean reserveForHeapBase) {
116 Register[] registers = null;
117 if (reserveForHeapBase) {
118 // @formatter:off
119 registers = new Register[]{
120 // TODO this is not complete
121 // o7 cannot be used as register because it is always overwritten on call
122 // and the current register handler would ignore this fact if the called
123 // method still does not modify registers, in fact o7 is modified by the Call instruction
124 // There would be some extra handlin necessary to be able to handle the o7 properly for local usage
125 o0, o1, o2, o3, o4, o5, /*o6, o7,*/
126 l0, l1, l2, l3, l4, l5, l6, l7,
127 i0, i1, i2, i3, i4, i5, /*i6,*/ /*i7,*/
128 //f0, f1, f2, f3, f4, f5, f6, f7,
129 f8, f9, f10, f11, f12, f13, f14, f15,
130 f16, f17, f18, f19, f20, f21, f22, f23,
131 f24, f25, f26, f27, f28, f29, f30, f31,
132 d32, d34, d36, d38, d40, d42, d44, d46,
133 d48, d50, d52, d54, d56, d58, d60, d62
134 };
135 // @formatter:on
136 } else {
137 // @formatter:off
138 registers = new Register[]{
139 // TODO this is not complete
140 o0, o1, o2, o3, o4, o5, /*o6, o7,*/
141 l0, l1, l2, l3, l4, l5, l6, l7,
142 i0, i1, i2, i3, i4, i5, /*i6,*/ /*i7,*/
143 // f0, f1, f2, f3, f4, f5, f6, f7
144 f8, f9, f10, f11, f12, f13, f14, f15,
145 f16, f17, f18, f19, f20, f21, f22, f23,
146 f24, f25, f26, f27, f28, f29, f30, f31,
147 d32, d34, d36, d38, d40, d42, d44, d46,
148 d48, d50, d52, d54, d56, d58, d60, d62
149 };
150 // @formatter:on
151 }
152
153 return registers;
154 }
155
156 public SPARCHotSpotRegisterConfig(TargetDescription target, HotSpotVMConfig config) {
157 this(target, initAllocatable(config.useCompressedOops));
158 }
159
160 public SPARCHotSpotRegisterConfig(TargetDescription target, Register[] allocatable) {
161 this.architecture = target.arch;
162
163 csl = new CalleeSaveLayout(target, -1, -1, target.arch.getWordSize(), calleeSaveRegisters);
164 this.allocatable = allocatable.clone();
165 attributesMap = RegisterAttributes.createMap(this, SPARC.allRegisters);
166 }
167
168 @Override
169 public Register[] getCallerSaveRegisters() {
170 return callerSaveRegisters;
171 }
172
173 @Override
174 public boolean areAllAllocatableRegistersCallerSaved() {
175 return false;
176 }
177
178 @Override
179 public Register getRegisterForRole(int index) {
180 throw new UnsupportedOperationException();
181 }
182
183 @Override
184 public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, TargetDescription target, boolean stackOnly) {
185 if (type == Type.JavaCall || type == Type.NativeCall) {
186 return callingConvention(cpuCallerParameterRegisters, returnType, parameterTypes, type, target, stackOnly);
187 }
188 if (type == Type.JavaCallee) {
189 return callingConvention(cpuCalleeParameterRegisters, returnType, parameterTypes, type, target, stackOnly);
190 }
191 throw JVMCIError.shouldNotReachHere();
192 }
193
194 public Register[] getCallingConventionRegisters(Type type, Kind kind) {
195 if (architecture.canStoreValue(FPUs, kind) || architecture.canStoreValue(FPUd, kind)) {
196 return fpuParameterRegisters;
197 }
198 assert architecture.canStoreValue(CPU, kind);
199 return type == Type.JavaCallee ? cpuCalleeParameterRegisters : cpuCallerParameterRegisters;
200 }
201
202 private CallingConvention callingConvention(Register[] generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, Type type, TargetDescription target, boolean stackOnly) {
203 AllocatableValue[] locations = new AllocatableValue[parameterTypes.length];
204
205 int currentGeneral = 0;
206 int currentFloating = 0;
207 int currentStackOffset = 0;
208
209 for (int i = 0; i < parameterTypes.length; i++) {
210 final Kind kind = parameterTypes[i].getKind();
211
212 switch (kind) {
213 case Byte:
214 case Boolean:
215 case Short:
216 case Char:
217 case Int:
218 case Long:
219 case Object:
220 if (!stackOnly && currentGeneral < generalParameterRegisters.length) {
221 Register register = generalParameterRegisters[currentGeneral++];
222 locations[i] = register.asValue(target.getLIRKind(kind));
223 }
224 break;
225 case Double:
226 if (!stackOnly && currentFloating < fpuParameterRegisters.length) {
227 if (currentFloating % 2 != 0) {
228 // Make register number even to be a double reg
229 currentFloating++;
230 }
231 Register register = fpuDoubleParameterRegisters[currentFloating];
232 currentFloating += 2; // Only every second is a double register
233 locations[i] = register.asValue(target.getLIRKind(kind));
234 }
235 break;
236 case Float:
237 if (!stackOnly && currentFloating < fpuParameterRegisters.length) {
238 Register register = fpuParameterRegisters[currentFloating++];
239 locations[i] = register.asValue(target.getLIRKind(kind));
240 }
241 break;
242 default:
243 throw JVMCIError.shouldNotReachHere();
244 }
245
246 if (locations[i] == null) {
247 // Stack slot is always aligned to its size in bytes but minimum wordsize
248 int typeSize = SPARC.spillSlotSize(target, kind);
249 currentStackOffset = roundUp(currentStackOffset, typeSize);
250 locations[i] = StackSlot.get(target.getLIRKind(kind.getStackKind()), currentStackOffset, !type.out);
251 currentStackOffset += typeSize;
252 }
253 }
254
255 Kind returnKind = returnType == null ? Kind.Void : returnType.getKind();
256 AllocatableValue returnLocation = returnKind == Kind.Void ? Value.ILLEGAL : getReturnRegister(returnKind, type).asValue(target.getLIRKind(returnKind.getStackKind()));
257 return new CallingConvention(currentStackOffset, returnLocation, locations);
258 }
259
260 private static int roundUp(int number, int mod) {
261 return ((number + mod - 1) / mod) * mod;
262 }
263
264 @Override
265 public Register getReturnRegister(Kind kind) {
266 return getReturnRegister(kind, Type.JavaCallee);
267 }
268
269 private static Register getReturnRegister(Kind kind, Type type) {
270 switch (kind) {
271 case Boolean:
272 case Byte:
273 case Char:
274 case Short:
275 case Int:
276 case Long:
277 case Object:
278 return type == Type.JavaCallee ? i0 : o0;
279 case Float:
280 return f0;
281 case Double:
282 return d0;
283 case Void:
284 case Illegal:
285 return null;
286 default:
287 throw new UnsupportedOperationException("no return register for type " + kind);
288 }
289 }
290
291 @Override
292 public Register getFrameRegister() {
293 return sp;
294 }
295
296 public CalleeSaveLayout getCalleeSaveLayout() {
297 return csl;
298 }
299
300 @Override
301 public String toString() {
302 return String.format("Allocatable: " + Arrays.toString(getAllocatableRegisters()) + "%n" + "CallerSave: " + Arrays.toString(getCallerSaveRegisters()) + "%n");
303 }
304 }