1 /* 2 * Copyright (c) 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 java.nio.ByteOrder; 26 import java.util.EnumSet; 27 28 import jdk.vm.ci.code.Architecture; 29 import jdk.vm.ci.code.Register; 30 import jdk.vm.ci.code.Register.RegisterCategory; 31 import jdk.vm.ci.code.RegisterArray; 32 import jdk.vm.ci.meta.JavaKind; 33 import jdk.vm.ci.meta.PlatformKind; 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 // General purpose CPU registers 43 public static final Register r0 = new Register(0, 0, "r0", CPU); 44 public static final Register r1 = new Register(1, 1, "r1", CPU); 45 public static final Register r2 = new Register(2, 2, "r2", CPU); 46 public static final Register r3 = new Register(3, 3, "r3", CPU); 47 public static final Register r4 = new Register(4, 4, "r4", CPU); 48 public static final Register r5 = new Register(5, 5, "r5", CPU); 49 public static final Register r6 = new Register(6, 6, "r6", CPU); 50 public static final Register r7 = new Register(7, 7, "r7", CPU); 51 public static final Register r8 = new Register(8, 8, "r8", CPU); 52 public static final Register r9 = new Register(9, 9, "r9", CPU); 53 public static final Register r10 = new Register(10, 10, "r10", CPU); 54 public static final Register r11 = new Register(11, 11, "r11", CPU); 55 public static final Register r12 = new Register(12, 12, "r12", CPU); 56 public static final Register r13 = new Register(13, 13, "r13", CPU); 57 public static final Register r14 = new Register(14, 14, "r14", CPU); 58 public static final Register r15 = new Register(15, 15, "r15", CPU); 59 public static final Register r16 = new Register(16, 16, "r16", CPU); 60 public static final Register r17 = new Register(17, 17, "r17", CPU); 61 public static final Register r18 = new Register(18, 18, "r18", CPU); 62 public static final Register r19 = new Register(19, 19, "r19", CPU); 63 public static final Register r20 = new Register(20, 20, "r20", CPU); 64 public static final Register r21 = new Register(21, 21, "r21", CPU); 65 public static final Register r22 = new Register(22, 22, "r22", CPU); 66 public static final Register r23 = new Register(23, 23, "r23", CPU); 67 public static final Register r24 = new Register(24, 24, "r24", CPU); 68 public static final Register r25 = new Register(25, 25, "r25", CPU); 69 public static final Register r26 = new Register(26, 26, "r26", CPU); 70 public static final Register r27 = new Register(27, 27, "r27", CPU); 71 public static final Register r28 = new Register(28, 28, "r28", CPU); 72 public static final Register r29 = new Register(29, 29, "r29", CPU); 73 public static final Register r30 = new Register(30, 30, "r30", CPU); 74 75 /* 76 * r31 is not a general purpose register, but represents either the stackpointer or the 77 * zero/discard register depending on the instruction. So we represent those two uses as two 78 * different registers. The register numbers are kept in sync with register_aarch64.hpp and have 79 * to be sequential, hence we also need a general r31 register here, which is never used. 80 */ 81 public static final Register r31 = new Register(31, 31, "r31", CPU); 82 public static final Register zr = new Register(32, 31, "zr", CPU); 83 public static final Register sp = new Register(33, 31, "sp", CPU); 84 85 public static final Register lr = r30; 86 87 // Used by runtime code: cannot be compiler-allocated. 88 public static final Register rscratch1 = r8; 89 public static final Register rscratch2 = r9; 90 91 // @formatter:off 92 public static final RegisterArray cpuRegisters = new RegisterArray( 93 r0, r1, r2, r3, r4, r5, r6, r7, 94 r8, r9, r10, r11, r12, r13, r14, r15, 95 r16, r17, r18, r19, r20, r21, r22, r23, 96 r24, r25, r26, r27, r28, r29, r30, r31, 97 zr, sp 98 ); 99 // @formatter:on 100 101 public static final RegisterCategory SIMD = new RegisterCategory("SIMD"); 102 103 // Simd registers 104 public static final Register v0 = new Register(34, 0, "v0", SIMD); 105 public static final Register v1 = new Register(35, 1, "v1", SIMD); 106 public static final Register v2 = new Register(36, 2, "v2", SIMD); 107 public static final Register v3 = new Register(37, 3, "v3", SIMD); 108 public static final Register v4 = new Register(38, 4, "v4", SIMD); 109 public static final Register v5 = new Register(39, 5, "v5", SIMD); 110 public static final Register v6 = new Register(40, 6, "v6", SIMD); 111 public static final Register v7 = new Register(41, 7, "v7", SIMD); 112 public static final Register v8 = new Register(42, 8, "v8", SIMD); 113 public static final Register v9 = new Register(43, 9, "v9", SIMD); 114 public static final Register v10 = new Register(44, 10, "v10", SIMD); 115 public static final Register v11 = new Register(45, 11, "v11", SIMD); 116 public static final Register v12 = new Register(46, 12, "v12", SIMD); 117 public static final Register v13 = new Register(47, 13, "v13", SIMD); 118 public static final Register v14 = new Register(48, 14, "v14", SIMD); 119 public static final Register v15 = new Register(49, 15, "v15", SIMD); 120 public static final Register v16 = new Register(50, 16, "v16", SIMD); 121 public static final Register v17 = new Register(51, 17, "v17", SIMD); 122 public static final Register v18 = new Register(52, 18, "v18", SIMD); 123 public static final Register v19 = new Register(53, 19, "v19", SIMD); 124 public static final Register v20 = new Register(54, 20, "v20", SIMD); 125 public static final Register v21 = new Register(55, 21, "v21", SIMD); 126 public static final Register v22 = new Register(56, 22, "v22", SIMD); 127 public static final Register v23 = new Register(57, 23, "v23", SIMD); 128 public static final Register v24 = new Register(58, 24, "v24", SIMD); 129 public static final Register v25 = new Register(59, 25, "v25", SIMD); 130 public static final Register v26 = new Register(60, 26, "v26", SIMD); 131 public static final Register v27 = new Register(61, 27, "v27", SIMD); 132 public static final Register v28 = new Register(62, 28, "v28", SIMD); 133 public static final Register v29 = new Register(63, 29, "v29", SIMD); 134 public static final Register v30 = new Register(64, 30, "v30", SIMD); 135 public static final Register v31 = new Register(65, 31, "v31", SIMD); 136 137 // @formatter:off 138 public static final RegisterArray simdRegisters = new RegisterArray( 139 v0, v1, v2, v3, v4, v5, v6, v7, 140 v8, v9, v10, v11, v12, v13, v14, v15, 141 v16, v17, v18, v19, v20, v21, v22, v23, 142 v24, v25, v26, v27, v28, v29, v30, v31 143 ); 144 // @formatter:on 145 146 // @formatter:off 147 public static final RegisterArray allRegisters = new RegisterArray( 148 r0, r1, r2, r3, r4, r5, r6, r7, 149 r8, r9, r10, r11, r12, r13, r14, r15, 150 r16, r17, r18, r19, r20, r21, r22, r23, 151 r24, r25, r26, r27, r28, r29, r30, r31, 152 zr, sp, 153 154 v0, v1, v2, v3, v4, v5, v6, v7, 155 v8, v9, v10, v11, v12, v13, v14, v15, 156 v16, v17, v18, v19, v20, v21, v22, v23, 157 v24, v25, v26, v27, v28, v29, v30, v31 158 ); 159 // @formatter:on 160 161 /** 162 * Basic set of CPU features mirroring what is returned from the cpuid instruction. See: 163 * {@code VM_Version::cpuFeatureFlags}. 164 */ 165 public enum CPUFeature { 166 FP, 167 ASIMD, 168 EVTSTRM, 169 AES, 170 PMULL, 171 SHA1, 172 SHA2, 173 CRC32, 174 LSE, 175 STXR_PREFETCH, 176 A53MAC, 177 DMB_ATOMICS 178 } 179 180 private final EnumSet<CPUFeature> features; 181 182 /** 183 * Set of flags to control code emission. 184 */ 185 public enum Flag { 186 UseBarriersForVolatile, 187 UseCRC32, 188 UseNeon, 189 UseSIMDForMemoryOps, 190 AvoidUnalignedAccesses, 191 UseLSE, 192 UseBlockZeroing 193 } 194 195 private final EnumSet<Flag> flags; 196 197 public AArch64(EnumSet<CPUFeature> features, EnumSet<Flag> flags) { 198 super("aarch64", AArch64Kind.QWORD, ByteOrder.LITTLE_ENDIAN, true, allRegisters, 0, 0, 0); 199 this.features = features; 200 this.flags = flags; 201 } 202 203 public EnumSet<CPUFeature> getFeatures() { 204 return features; 205 } 206 207 public EnumSet<Flag> getFlags() { 208 return flags; 209 } 210 211 @Override 212 public PlatformKind getPlatformKind(JavaKind javaKind) { 213 switch (javaKind) { 214 case Boolean: 215 case Byte: 216 return AArch64Kind.BYTE; 217 case Short: 218 case Char: 219 return AArch64Kind.WORD; 220 case Int: 221 return AArch64Kind.DWORD; 222 case Long: 223 case Object: 224 return AArch64Kind.QWORD; 225 case Float: 226 return AArch64Kind.SINGLE; 227 case Double: 228 return AArch64Kind.DOUBLE; 229 default: 230 return null; 231 } 232 } 233 234 @Override 235 public boolean canStoreValue(RegisterCategory category, PlatformKind platformKind) { 236 AArch64Kind kind = (AArch64Kind) platformKind; 237 if (kind.isInteger()) { 238 return category.equals(CPU); 239 } else if (kind.isSIMD()) { 240 return category.equals(SIMD); 241 } 242 return false; 243 } 244 245 @Override 246 public AArch64Kind getLargestStorableKind(RegisterCategory category) { 247 if (category.equals(CPU)) { 248 return AArch64Kind.QWORD; 249 } else if (category.equals(SIMD)) { 250 return AArch64Kind.V128_QWORD; 251 } else { 252 return null; 253 } 254 } 255 }