< prev index next >

src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotRegisterConfig.java

Print this page




   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");
< prev index next >