1 /*
   2  * Copyright (c) 2009, 2015, 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 jdk.vm.ci.aarch64;
  24 
  25 import static jdk.vm.ci.code.MemoryBarriers.*;
  26 import static jdk.vm.ci.code.Register.*;
  27 
  28 import java.nio.*;
  29 import java.util.*;
  30 
  31 import jdk.vm.ci.code.*;
  32 import jdk.vm.ci.code.Register.RegisterCategory;
  33 import jdk.vm.ci.meta.*;
  34 
  35 /**
  36  * Represents the AARCH64 architecture.
  37  */
  38 public class AArch64 extends Architecture {
  39 
  40     public static final RegisterCategory CPU = new RegisterCategory("CPU");
  41 
  42     // @formatter:off
  43 
  44     // General purpose CPU registers
  45     public static final Register r0 = new Register(0, 0, "r0", CPU);
  46     public static final Register r1 = new Register(0, 0, "r1", CPU);
  47     public static final Register r2 = new Register(0, 0, "r2", CPU);
  48     public static final Register r3 = new Register(0, 0, "r3", CPU);
  49     public static final Register r4 = new Register(0, 0, "r4", CPU);
  50     public static final Register r5 = new Register(0, 0, "r5", CPU);
  51     public static final Register r6 = new Register(0, 0, "r6", CPU);
  52     public static final Register r7 = new Register(0, 0, "r7", CPU);
  53     public static final Register r8 = new Register(0, 0, "r8", CPU);
  54     public static final Register r9 = new Register(0, 0, "r9", CPU);
  55     public static final Register r10 = new Register(0, 0, "r10", CPU);
  56     public static final Register r11 = new Register(0, 0, "r11", CPU);
  57     public static final Register r12 = new Register(0, 0, "r12", CPU);
  58     public static final Register r13 = new Register(0, 0, "r13", CPU);
  59     public static final Register r14 = new Register(0, 0, "r14", CPU);
  60     public static final Register r15 = new Register(0, 0, "r15", CPU);
  61     public static final Register r16 = new Register(0, 0, "r16", CPU);
  62     public static final Register r17 = new Register(0, 0, "r17", CPU);
  63     public static final Register r18 = new Register(0, 0, "r18", CPU);
  64     public static final Register r19 = new Register(0, 0, "r19", CPU);
  65     public static final Register r20 = new Register(0, 0, "r20", CPU);
  66     public static final Register r21 = new Register(0, 0, "r21", CPU);
  67     public static final Register r22 = new Register(0, 0, "r22", CPU);
  68     public static final Register r23 = new Register(0, 0, "r23", CPU);
  69     public static final Register r24 = new Register(0, 0, "r24", CPU);
  70     public static final Register r25 = new Register(0, 0, "r25", CPU);
  71     public static final Register r26 = new Register(0, 0, "r26", CPU);
  72     public static final Register r27 = new Register(0, 0, "r27", CPU);
  73     public static final Register rheapbase = new Register(0, 0, "rheapbase", CPU);
  74     public static final Register rthread = new Register(0, 0, "rthread", CPU);
  75     public static final Register fp = new Register(0, 0, "rfp", CPU);
  76     public static final Register lr = new Register(0, 0, "rlr", CPU);
  77     public static final Register sp = new Register(0, 0, "rsp", CPU);
  78 
  79     public static final Register[] cpuRegisters = {
  80         r0, r1, r2, r3, r4, r5, r6, r7, r8, r9,
  81         r10, r11, r12, r13, r14, r15, r16, r17, r18, r19,
  82         r20, r21, r22, r23, r24, r25, r26, r27,
  83         rheapbase, rthread, fp, lr, sp,
  84     };
  85 
  86     private static final int SIMD_REFERENCE_MAP_SHIFT = 2;
  87 
  88     public static final RegisterCategory SIMD = new RegisterCategory("SIMD", cpuRegisters.length, SIMD_REFERENCE_MAP_SHIFT);
  89 
  90     // Simd registers
  91     public static final Register v0 = new Register(0, 0, "v0", SIMD);
  92     public static final Register v1 = new Register(0, 0, "v1", SIMD);
  93     public static final Register v2 = new Register(0, 0, "v2", SIMD);
  94     public static final Register v3 = new Register(0, 0, "v3", SIMD);
  95     public static final Register v4 = new Register(0, 0, "v4", SIMD);
  96     public static final Register v5 = new Register(0, 0, "v5", SIMD);
  97     public static final Register v6 = new Register(0, 0, "v6", SIMD);
  98     public static final Register v7 = new Register(0, 0, "v7", SIMD);
  99     public static final Register v8 = new Register(0, 0, "v8", SIMD);
 100     public static final Register v9 = new Register(0, 0, "v9", SIMD);
 101     public static final Register v10 = new Register(0, 0, "v10", SIMD);
 102     public static final Register v11 = new Register(0, 0, "v11", SIMD);
 103     public static final Register v12 = new Register(0, 0, "v12", SIMD);
 104     public static final Register v13 = new Register(0, 0, "v13", SIMD);
 105     public static final Register v14 = new Register(0, 0, "v14", SIMD);
 106     public static final Register v15 = new Register(0, 0, "v15", SIMD);
 107     public static final Register v16 = new Register(0, 0, "v16", SIMD);
 108     public static final Register v17 = new Register(0, 0, "v17", SIMD);
 109     public static final Register v18 = new Register(0, 0, "v18", SIMD);
 110     public static final Register v19 = new Register(0, 0, "v19", SIMD);
 111     public static final Register v20 = new Register(0, 0, "v20", SIMD);
 112     public static final Register v21 = new Register(0, 0, "v21", SIMD);
 113     public static final Register v22 = new Register(0, 0, "v22", SIMD);
 114     public static final Register v23 = new Register(0, 0, "v23", SIMD);
 115     public static final Register v24 = new Register(0, 0, "v24", SIMD);
 116     public static final Register v25 = new Register(0, 0, "v25", SIMD);
 117     public static final Register v26 = new Register(0, 0, "v26", SIMD);
 118     public static final Register v27 = new Register(0, 0, "v27", SIMD);
 119     public static final Register v28 = new Register(0, 0, "v28", SIMD);
 120     public static final Register v29 = new Register(0, 0, "v29", SIMD);
 121     public static final Register v30 = new Register(0, 0, "v30", SIMD);
 122     public static final Register v31 = new Register(0, 0, "v31", SIMD);
 123 
 124     public static final Register[] simdRegisters = {
 125         v0, v1, v2, v3, v4, v5, v6, v7, v8, v9,
 126         v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
 127         v20, v21, v22, v23, v24, v25, v26, v27, v28, v29,
 128         v30, v31
 129     };
 130 
 131     public static final Register[] allRegisters = {
 132         r0, r1, r2, r3, r4, r5, r6, r7, r8, r9,
 133         r10, r11, r12, r13, r14, r15, r16, r17, r18, r19,
 134         r20, r21, r22, r23, r24, r25, r26, r27,
 135         rheapbase, rthread, fp, lr, sp,
 136 
 137         v0, v1, v2, v3, v4, v5, v6, v7, v8, v9,
 138         v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
 139         v20, v21, v22, v23, v24, v25, v26, v27, v28, v29,
 140         v30, v31
 141     };
 142 
 143     // @formatter:on
 144 
 145     /**
 146      * Basic set of CPU features mirroring what is returned from the cpuid instruction. See:
 147      * {@code VM_Version::cpuFeatureFlags}.
 148      */
 149     public static enum CPUFeature {
 150         FP,
 151         ASIMD,
 152         EVTSTRM,
 153         AES,
 154         PMULL,
 155         SHA1,
 156         SHA2,
 157         CRC32,
 158         A53MAC,
 159         DMB_ATOMICS
 160     }
 161 
 162     private final EnumSet<CPUFeature> features;
 163 
 164     /**
 165      * Set of flags to control code emission.
 166      */
 167     public static enum Flag {
 168         UseBarriersForVolatile,
 169         UseCRC32,
 170         UseNeon
 171     }
 172 
 173     private final EnumSet<Flag> flags;
 174 
 175     public AArch64(EnumSet<CPUFeature> features, EnumSet<Flag> flags) {
 176         super("aarch64", JavaKind.Long, ByteOrder.LITTLE_ENDIAN,
 177               /*unalignedMemoryAccess*/true, allRegisters,
 178               /*implicitMemoryBarriers*/0, /*nativeCallDisplacementOffset*/0,
 179               cpuRegisters.length + (simdRegisters.length << SIMD_REFERENCE_MAP_SHIFT),
 180               /*returnAddressSize*/0);
 181         this.features = features;
 182         this.flags = flags;
 183         assert features.contains(CPUFeature.FP) : "minimum config for aarch64";
 184     }
 185 
 186     public EnumSet<CPUFeature> getFeatures() {
 187         return features;
 188     }
 189 
 190     public EnumSet<Flag> getFlags() {
 191         return flags;
 192     }
 193 
 194     @Override
 195     public PlatformKind getPlatformKind(JavaKind javaKind) {
 196         if (javaKind.isObject()) {
 197             return getWordKind();
 198         } else {
 199             return javaKind;
 200         }
 201     }
 202 
 203     @Override
 204     public boolean canStoreValue(RegisterCategory category, PlatformKind platformKind) {
 205         if (!(platformKind instanceof JavaKind)) {
 206             return false;
 207         }
 208 
 209         JavaKind kind = (JavaKind) platformKind;
 210         if (category.equals(CPU)) {
 211             switch (kind) {
 212                 case Boolean:
 213                 case Byte:
 214                 case Char:
 215                 case Short:
 216                 case Int:
 217                 case Long:
 218                     return true;
 219             }
 220         } else if (category.equals(SIMD)) {
 221             switch (kind) {
 222                 case Float:
 223                 case Double:
 224                     return true;
 225             }
 226         }
 227 
 228         return false;
 229     }
 230 
 231     @Override
 232     public PlatformKind getLargestStorableKind(RegisterCategory category) {
 233         if (category.equals(CPU)) {
 234             return JavaKind.Long;
 235         } else if (category.equals(SIMD)) {
 236             return JavaKind.Double;
 237         } else {
 238             return JavaKind.Illegal;
 239         }
 240     }
 241 }