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