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 jdk.vm.ci.hotspot.sparc; 24 25 import static jdk.vm.ci.sparc.SPARC.*; 26 27 import java.util.*; 28 29 import jdk.vm.ci.code.*; 30 import jdk.vm.ci.code.CallingConvention.*; 31 import jdk.vm.ci.common.*; 32 import jdk.vm.ci.hotspot.*; 33 import jdk.vm.ci.meta.*; 34 import jdk.vm.ci.sparc.*; 35 36 public class SPARCHotSpotRegisterConfig implements RegisterConfig { 37 38 private final Architecture architecture; 39 40 private final Register[] allocatable; 41 42 private final RegisterAttributes[] attributesMap; 43 44 @Override 45 public Register[] getAllocatableRegisters() { 46 return allocatable.clone(); 47 } 48 49 public Register[] filterAllocatableRegisters(PlatformKind kind, Register[] registers) { 50 ArrayList<Register> list = new ArrayList<>(); 51 for (Register reg : registers) { 52 if (architecture.canStoreValue(reg.getRegisterCategory(), kind)) { 53 // Special treatment for double precision 54 // TODO: This is wasteful it uses only half of the registers as float. 55 if (kind == JavaKind.Double) { 56 if (reg.getRegisterCategory().equals(FPUd)) { 57 list.add(reg); 58 } 59 } else if (kind == JavaKind.Float) { 60 if (reg.getRegisterCategory().equals(FPUs)) { 61 list.add(reg); 62 } 63 } else { 64 list.add(reg); 65 } 66 } 67 } 68 69 Register[] ret = list.toArray(new Register[list.size()]); 70 return ret; 71 } 72 73 @Override 74 public RegisterAttributes[] getAttributesMap() { 75 return attributesMap.clone(); 76 } 77 78 private final Register[] cpuCallerParameterRegisters = {o0, o1, o2, o3, o4, o5}; 79 private final Register[] cpuCalleeParameterRegisters = {i0, i1, i2, i3, i4, i5}; 80 81 private final Register[] fpuParameterRegisters = {f0, f1, f2, f3, f4, f5, f6, f7}; 82 private final Register[] fpuDoubleParameterRegisters = {d0, null, d2, null, d4, null, d6, null}; 83 // @formatter:off 84 private final Register[] callerSaveRegisters = 85 {g1, g2, g3, g4, g5, g6, g7, 86 o0, o1, o2, o3, o4, o5, o7, 87 f0, f1, f2, f3, f4, f5, f6, f7, 88 f8, f9, f10, f11, f12, f13, f14, f15, 89 f16, f17, f18, f19, f20, f21, f22, f23, 90 f24, f25, f26, f27, f28, f29, f30, f31, 91 d32, d34, d36, d38, d40, d42, d44, d46, 92 d48, d50, d52, d54, d56, d58, d60, d62}; 93 // @formatter:on 94 95 /** 96 * Registers saved by the callee. This lists all L and I registers which are saved in the 97 * register window. 98 */ 99 private final Register[] calleeSaveRegisters = {l0, l1, l2, l3, l4, l5, l6, l7, i0, i1, i2, i3, i4, i5, i6, i7}; 100 101 private static Register[] initAllocatable(boolean reserveForHeapBase) { 102 Register[] registers = null; 103 if (reserveForHeapBase) { 104 // @formatter:off 105 registers = new Register[]{ 106 // TODO this is not complete 107 // o7 cannot be used as register because it is always overwritten on call 108 // and the current register handler would ignore this fact if the called 109 // method still does not modify registers, in fact o7 is modified by the Call instruction 110 // There would be some extra handlin necessary to be able to handle the o7 properly for local usage 111 g1, g4, g5, 112 o0, o1, o2, o3, o4, o5, /*o6,o7,*/ 113 l0, l1, l2, l3, l4, l5, l6, l7, 114 i0, i1, i2, i3, i4, i5, /*i6,*/ /*i7,*/ 115 //f0, f1, f2, f3, f4, f5, f6, f7, 116 f8, f9, f10, f11, f12, f13, f14, f15, 117 f16, f17, f18, f19, f20, f21, f22, f23, 118 f24, f25, f26, f27, f28, f29, f30, f31, 119 d32, d34, d36, d38, d40, d42, d44, d46, 120 d48, d50, d52, d54, d56, d58, d60, d62 121 }; 122 // @formatter:on 123 } else { 124 // @formatter:off 125 registers = new Register[]{ 126 // TODO this is not complete 127 g1, g4, g5, 128 o0, o1, o2, o3, o4, o5, /*o6, o7,*/ 129 l0, l1, l2, l3, l4, l5, l6, l7, 130 i0, i1, i2, i3, i4, i5, /*i6,*/ /*i7,*/ 131 // f0, f1, f2, f3, f4, f5, f6, f7 132 f8, f9, f10, f11, f12, f13, f14, f15, 133 f16, f17, f18, f19, f20, f21, f22, f23, 134 f24, f25, f26, f27, f28, f29, f30, f31, 135 d32, d34, d36, d38, d40, d42, d44, d46, 136 d48, d50, d52, d54, d56, d58, d60, d62 137 }; 138 // @formatter:on 139 } 140 141 return registers; 142 } 143 144 public SPARCHotSpotRegisterConfig(TargetDescription target, HotSpotVMConfig config) { 145 this(target, initAllocatable(config.useCompressedOops)); 146 } 147 148 public SPARCHotSpotRegisterConfig(TargetDescription target, Register[] allocatable) { 149 this.architecture = target.arch; 150 this.allocatable = allocatable.clone(); 151 attributesMap = RegisterAttributes.createMap(this, SPARC.allRegisters); 152 } 153 154 @Override 155 public Register[] getCallerSaveRegisters() { 156 return callerSaveRegisters; 157 } 158 159 public Register[] getCalleeSaveRegisters() { 160 return calleeSaveRegisters; 161 } 162 163 @Override 164 public boolean areAllAllocatableRegistersCallerSaved() { 165 return false; 166 } 167 168 @Override 169 public Register getRegisterForRole(int index) { 170 throw new UnsupportedOperationException(); 171 } 172 173 @Override 174 public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, TargetDescription target, boolean stackOnly) { 175 if (type == Type.JavaCall || type == Type.NativeCall) { 176 return callingConvention(cpuCallerParameterRegisters, returnType, parameterTypes, type, target, stackOnly); 177 } 178 if (type == Type.JavaCallee) { 179 return callingConvention(cpuCalleeParameterRegisters, returnType, parameterTypes, type, target, stackOnly); 180 } 181 throw JVMCIError.shouldNotReachHere(); 182 } 183 184 public Register[] getCallingConventionRegisters(Type type, JavaKind kind) { 185 if (architecture.canStoreValue(FPUs, kind) || architecture.canStoreValue(FPUd, kind)) { 186 return fpuParameterRegisters; 187 } 188 assert architecture.canStoreValue(CPU, kind); 189 return type == Type.JavaCallee ? cpuCalleeParameterRegisters : cpuCallerParameterRegisters; 190 } 191 192 private CallingConvention callingConvention(Register[] generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, Type type, TargetDescription target, boolean stackOnly) { 193 AllocatableValue[] locations = new AllocatableValue[parameterTypes.length]; 194 195 int currentGeneral = 0; 196 int currentFloating = 0; 197 int currentStackOffset = 0; 198 199 for (int i = 0; i < parameterTypes.length; i++) { 200 final JavaKind kind = parameterTypes[i].getJavaKind().getStackKind(); 201 202 switch (kind) { 203 case Byte: 204 case Boolean: 205 case Short: 206 case Char: 207 case Int: 208 case Long: 209 case Object: 210 if (!stackOnly && currentGeneral < generalParameterRegisters.length) { 211 Register register = generalParameterRegisters[currentGeneral++]; 212 locations[i] = register.asValue(target.getLIRKind(kind)); 213 } 214 break; 215 case Double: 216 if (!stackOnly && currentFloating < fpuParameterRegisters.length) { 217 if (currentFloating % 2 != 0) { 218 // Make register number even to be a double reg 219 currentFloating++; 220 } 221 Register register = fpuDoubleParameterRegisters[currentFloating]; 222 currentFloating += 2; // Only every second is a double register 223 locations[i] = register.asValue(target.getLIRKind(kind)); 224 } 225 break; 226 case Float: 227 if (!stackOnly && currentFloating < fpuParameterRegisters.length) { 228 Register register = fpuParameterRegisters[currentFloating++]; 229 locations[i] = register.asValue(target.getLIRKind(kind)); 230 } 231 break; 232 default: 233 throw JVMCIError.shouldNotReachHere(); 234 } 235 236 if (locations[i] == null) { 237 // Stack slot is always aligned to its size in bytes but minimum wordsize 238 int typeSize = SPARC.spillSlotSize(target, kind); 239 currentStackOffset = roundUp(currentStackOffset, typeSize); 240 int slotOffset = currentStackOffset + SPARC.REGISTER_SAFE_AREA_SIZE; 241 locations[i] = StackSlot.get(target.getLIRKind(kind.getStackKind()), slotOffset, !type.out); 242 currentStackOffset += typeSize; 243 } 244 } 245 246 JavaKind returnKind = returnType == null ? JavaKind.Void : returnType.getJavaKind(); 247 AllocatableValue returnLocation = returnKind == JavaKind.Void ? Value.ILLEGAL : getReturnRegister(returnKind, type).asValue(target.getLIRKind(returnKind.getStackKind())); 248 // Space where callee may spill outgoing parameters o0...o5 249 int lowerOutgoingSpace = Math.min(locations.length, 6) * target.wordSize; 250 return new CallingConvention(currentStackOffset + lowerOutgoingSpace, returnLocation, locations); 251 } 252 253 private static int roundUp(int number, int mod) { 254 return ((number + mod - 1) / mod) * mod; 255 } 256 257 @Override 258 public Register getReturnRegister(JavaKind kind) { 259 return getReturnRegister(kind, Type.JavaCallee); 260 } 261 262 private static Register getReturnRegister(JavaKind kind, Type type) { 263 switch (kind) { 264 case Boolean: 265 case Byte: 266 case Char: 267 case Short: 268 case Int: 269 case Long: 270 case Object: 271 return type == Type.JavaCallee ? i0 : o0; 272 case Float: 273 return f0; 274 case Double: 275 return d0; 276 case Void: 277 case Illegal: 278 return null; 279 default: 280 throw new UnsupportedOperationException("no return register for type " + kind); 281 } 282 } 283 284 @Override 285 public Register getFrameRegister() { 286 return sp; 287 } 288 289 @Override 290 public String toString() { 291 return String.format("Allocatable: " + Arrays.toString(getAllocatableRegisters()) + "%n" + "CallerSave: " + Arrays.toString(getCallerSaveRegisters()) + "%n"); | 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 jdk.vm.ci.hotspot.sparc; 24 25 import static jdk.vm.ci.code.CallingConvention.Type.JavaCall; 26 import static jdk.vm.ci.code.CallingConvention.Type.JavaCallee; 27 import static jdk.vm.ci.code.CallingConvention.Type.NativeCall; 28 import static jdk.vm.ci.meta.JavaKind.Void; 29 import static jdk.vm.ci.meta.Value.ILLEGAL; 30 import static jdk.vm.ci.sparc.SPARC.REGISTER_SAFE_AREA_SIZE; 31 import static jdk.vm.ci.sparc.SPARC.d0; 32 import static jdk.vm.ci.sparc.SPARC.d2; 33 import static jdk.vm.ci.sparc.SPARC.d4; 34 import static jdk.vm.ci.sparc.SPARC.d6; 35 import static jdk.vm.ci.sparc.SPARC.f0; 36 import static jdk.vm.ci.sparc.SPARC.f1; 37 import static jdk.vm.ci.sparc.SPARC.f2; 38 import static jdk.vm.ci.sparc.SPARC.f3; 39 import static jdk.vm.ci.sparc.SPARC.f4; 40 import static jdk.vm.ci.sparc.SPARC.f5; 41 import static jdk.vm.ci.sparc.SPARC.f6; 42 import static jdk.vm.ci.sparc.SPARC.f7; 43 import static jdk.vm.ci.sparc.SPARC.g0; 44 import static jdk.vm.ci.sparc.SPARC.g2; 45 import static jdk.vm.ci.sparc.SPARC.g6; 46 import static jdk.vm.ci.sparc.SPARC.i0; 47 import static jdk.vm.ci.sparc.SPARC.i1; 48 import static jdk.vm.ci.sparc.SPARC.i2; 49 import static jdk.vm.ci.sparc.SPARC.i3; 50 import static jdk.vm.ci.sparc.SPARC.i4; 51 import static jdk.vm.ci.sparc.SPARC.i5; 52 import static jdk.vm.ci.sparc.SPARC.i6; 53 import static jdk.vm.ci.sparc.SPARC.i7; 54 import static jdk.vm.ci.sparc.SPARC.l0; 55 import static jdk.vm.ci.sparc.SPARC.l1; 56 import static jdk.vm.ci.sparc.SPARC.l2; 57 import static jdk.vm.ci.sparc.SPARC.l3; 58 import static jdk.vm.ci.sparc.SPARC.l4; 59 import static jdk.vm.ci.sparc.SPARC.l5; 60 import static jdk.vm.ci.sparc.SPARC.l6; 61 import static jdk.vm.ci.sparc.SPARC.l7; 62 import static jdk.vm.ci.sparc.SPARC.o0; 63 import static jdk.vm.ci.sparc.SPARC.o1; 64 import static jdk.vm.ci.sparc.SPARC.o2; 65 import static jdk.vm.ci.sparc.SPARC.o3; 66 import static jdk.vm.ci.sparc.SPARC.o4; 67 import static jdk.vm.ci.sparc.SPARC.o5; 68 import static jdk.vm.ci.sparc.SPARC.sp; 69 70 import java.util.ArrayList; 71 import java.util.Arrays; 72 import java.util.Collections; 73 import java.util.HashSet; 74 75 import jdk.vm.ci.code.Architecture; 76 import jdk.vm.ci.code.CallingConvention; 77 import jdk.vm.ci.code.CallingConvention.Type; 78 import jdk.vm.ci.code.Register; 79 import jdk.vm.ci.code.RegisterAttributes; 80 import jdk.vm.ci.code.RegisterConfig; 81 import jdk.vm.ci.code.StackSlot; 82 import jdk.vm.ci.code.TargetDescription; 83 import jdk.vm.ci.common.JVMCIError; 84 import jdk.vm.ci.hotspot.HotSpotVMConfig; 85 import jdk.vm.ci.meta.AllocatableValue; 86 import jdk.vm.ci.meta.JavaKind; 87 import jdk.vm.ci.meta.JavaType; 88 import jdk.vm.ci.meta.LIRKind; 89 import jdk.vm.ci.meta.PlatformKind; 90 import jdk.vm.ci.sparc.SPARC; 91 92 public class SPARCHotSpotRegisterConfig implements RegisterConfig { 93 94 private final Architecture architecture; 95 96 private final Register[] allocatable; 97 98 private final RegisterAttributes[] attributesMap; 99 100 /** 101 * Does native code (C++ code) spill arguments in registers to the parent frame? 102 */ 103 private final boolean addNativeRegisterArgumentSlots; 104 105 @Override 106 public Register[] getAllocatableRegisters() { 107 return allocatable.clone(); 108 } 109 110 public Register[] filterAllocatableRegisters(PlatformKind kind, Register[] registers) { 111 ArrayList<Register> list = new ArrayList<>(); 112 for (Register reg : registers) { 113 if (architecture.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 * Registers saved by the callee. This lists all L and I registers which are saved in the 137 * register window. 138 */ 139 private final Register[] calleeSaveRegisters = { 140 l0, l1, l2, l3, l4, l5, l6, l7, 141 i0, i1, i2, i3, i4, i5, i6, i7}; 142 // @formatter:on 143 144 private static Register[] initAllocatable(Architecture arch, boolean reserveForHeapBase) { 145 Register[] allRegisters = arch.getAvailableValueRegisters(); 146 Register[] registers = new Register[allRegisters.length - (reserveForHeapBase ? 4 : 3)]; 147 148 int idx = 0; 149 for (Register reg : allRegisters) { 150 if (reg.equals(sp) || reg.equals(g2) || reg.equals(g0)) { 151 // skip g0, stack pointer and thread register 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 registers; 164 } 165 166 public SPARCHotSpotRegisterConfig(Architecture arch, HotSpotVMConfig config) { 167 this(arch, initAllocatable(arch, config.useCompressedOops), config); 168 } 169 170 public SPARCHotSpotRegisterConfig(Architecture arch, Register[] allocatable, HotSpotVMConfig config) { 171 this.architecture = arch; 172 this.allocatable = allocatable.clone(); 173 this.addNativeRegisterArgumentSlots = config.linuxOs; 174 HashSet<Register> callerSaveSet = new HashSet<>(); 175 Collections.addAll(callerSaveSet, arch.getAvailableValueRegisters()); 176 for (Register cs : calleeSaveRegisters) { 177 callerSaveSet.remove(cs); 178 } 179 this.callerSaveRegisters = callerSaveSet.toArray(new Register[callerSaveSet.size()]); 180 attributesMap = RegisterAttributes.createMap(this, SPARC.allRegisters); 181 } 182 183 @Override 184 public Register[] getCallerSaveRegisters() { 185 return callerSaveRegisters; 186 } 187 188 public Register[] getCalleeSaveRegisters() { 189 return calleeSaveRegisters; 190 } 191 192 @Override 193 public boolean areAllAllocatableRegistersCallerSaved() { 194 return false; 195 } 196 197 @Override 198 public Register getRegisterForRole(int index) { 199 throw new UnsupportedOperationException(); 200 } 201 202 @Override 203 public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, TargetDescription target, boolean stackOnly) { 204 if (type == JavaCall || type == NativeCall) { 205 return callingConvention(cpuCallerParameterRegisters, returnType, parameterTypes, type, target, stackOnly); 206 } 207 if (type == JavaCallee) { 208 return callingConvention(cpuCalleeParameterRegisters, returnType, parameterTypes, type, target, stackOnly); 209 } 210 throw JVMCIError.shouldNotReachHere(); 211 } 212 213 public Register[] getCallingConventionRegisters(Type type, JavaKind kind) { 214 switch (kind) { 215 case Boolean: 216 case Byte: 217 case Short: 218 case Char: 219 case Int: 220 case Long: 221 case Object: 222 return type == Type.JavaCallee ? cpuCalleeParameterRegisters : cpuCallerParameterRegisters; 223 case Double: 224 case Float: 225 return fpuFloatParameterRegisters; 226 default: 227 throw JVMCIError.shouldNotReachHere("Unknown JavaKind " + kind); 228 } 229 } 230 231 private CallingConvention callingConvention(Register[] generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, Type type, TargetDescription target, boolean stackOnly) { 232 AllocatableValue[] locations = new AllocatableValue[parameterTypes.length]; 233 234 int currentGeneral = 0; 235 int currentFloating = 0; 236 int currentStackOffset = 0; 237 238 for (int i = 0; i < parameterTypes.length; i++) { 239 final JavaKind kind = parameterTypes[i].getJavaKind().getStackKind(); 240 241 switch (kind) { 242 case Byte: 243 case Boolean: 244 case Short: 245 case Char: 246 case Int: 247 case Long: 248 case Object: 249 if (!stackOnly && currentGeneral < generalParameterRegisters.length) { 250 Register register = generalParameterRegisters[currentGeneral++]; 251 locations[i] = register.asValue(target.getLIRKind(kind)); 252 } 253 break; 254 case Double: 255 if (!stackOnly && currentFloating < fpuFloatParameterRegisters.length) { 256 if (currentFloating % 2 != 0) { 257 // Make register number even to be a double reg 258 currentFloating++; 259 } 260 Register register = fpuDoubleParameterRegisters[currentFloating]; 261 currentFloating += 2; // Only every second is a double register 262 locations[i] = register.asValue(target.getLIRKind(kind)); 263 } 264 break; 265 case Float: 266 if (!stackOnly && currentFloating < fpuFloatParameterRegisters.length) { 267 Register register = fpuFloatParameterRegisters[currentFloating++]; 268 locations[i] = register.asValue(target.getLIRKind(kind)); 269 } 270 break; 271 default: 272 throw JVMCIError.shouldNotReachHere(); 273 } 274 275 if (locations[i] == null) { 276 LIRKind lirKind = target.getLIRKind(kind); 277 // Stack slot is always aligned to its size in bytes but minimum wordsize 278 int typeSize = lirKind.getPlatformKind().getSizeInBytes(); 279 currentStackOffset = roundUp(currentStackOffset, typeSize); 280 int slotOffset = currentStackOffset + REGISTER_SAFE_AREA_SIZE; 281 locations[i] = StackSlot.get(lirKind, slotOffset, !type.out); 282 currentStackOffset += typeSize; 283 } 284 } 285 286 JavaKind returnKind = returnType == null ? Void : returnType.getJavaKind(); 287 AllocatableValue returnLocation = returnKind == Void ? ILLEGAL : getReturnRegister(returnKind, type).asValue(target.getLIRKind(returnKind.getStackKind())); 288 289 int outArgSpillArea; 290 if (type == NativeCall && addNativeRegisterArgumentSlots) { 291 // Space for native callee which may spill our outgoing arguments 292 outArgSpillArea = Math.min(locations.length, generalParameterRegisters.length) * target.wordSize; 293 } else { 294 outArgSpillArea = 0; 295 } 296 return new CallingConvention(currentStackOffset + outArgSpillArea, returnLocation, locations); 297 } 298 299 private static int roundUp(int number, int mod) { 300 return ((number + mod - 1) / mod) * mod; 301 } 302 303 @Override 304 public Register getReturnRegister(JavaKind kind) { 305 return getReturnRegister(kind, JavaCallee); 306 } 307 308 private static Register getReturnRegister(JavaKind kind, Type type) { 309 switch (kind) { 310 case Boolean: 311 case Byte: 312 case Char: 313 case Short: 314 case Int: 315 case Long: 316 case Object: 317 return type == JavaCallee ? i0 : o0; 318 case Float: 319 return f0; 320 case Double: 321 return d0; 322 case Void: 323 case Illegal: 324 return null; 325 default: 326 throw new UnsupportedOperationException("no return register for type " + kind); 327 } 328 } 329 330 @Override 331 public Register getFrameRegister() { 332 return sp; 333 } 334 335 @Override 336 public String toString() { 337 return String.format("Allocatable: " + Arrays.toString(getAllocatableRegisters()) + "%n" + "CallerSave: " + Arrays.toString(getCallerSaveRegisters()) + "%n"); |