1 /* 2 * Copyright (c) 2009, 2021, 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.amd64; 24 25 import static jdk.vm.ci.code.MemoryBarriers.LOAD_LOAD; 26 import static jdk.vm.ci.code.MemoryBarriers.LOAD_STORE; 27 import static jdk.vm.ci.code.MemoryBarriers.STORE_STORE; 28 import static jdk.vm.ci.code.Register.SPECIAL; 29 30 import java.nio.ByteOrder; 31 import java.util.EnumSet; 32 33 import jdk.vm.ci.code.Architecture; 34 import jdk.vm.ci.code.CPUFeatureName; 35 import jdk.vm.ci.code.Register; 36 import jdk.vm.ci.code.Register.RegisterCategory; 37 import jdk.vm.ci.code.RegisterArray; 38 import jdk.vm.ci.meta.JavaKind; 39 import jdk.vm.ci.meta.PlatformKind; 40 41 /** 42 * Represents the AMD64 architecture. 43 */ 44 public class AMD64 extends Architecture { 45 46 public static final RegisterCategory CPU = new RegisterCategory("CPU"); 47 48 // @formatter:off 49 50 // General purpose CPU registers 51 public static final Register rax = new Register(0, 0, "rax", CPU); 52 public static final Register rcx = new Register(1, 1, "rcx", CPU); 53 public static final Register rdx = new Register(2, 2, "rdx", CPU); 54 public static final Register rbx = new Register(3, 3, "rbx", CPU); 55 public static final Register rsp = new Register(4, 4, "rsp", CPU); 56 public static final Register rbp = new Register(5, 5, "rbp", CPU); 57 public static final Register rsi = new Register(6, 6, "rsi", CPU); 58 public static final Register rdi = new Register(7, 7, "rdi", CPU); 59 60 public static final Register r8 = new Register(8, 8, "r8", CPU); 61 public static final Register r9 = new Register(9, 9, "r9", CPU); 62 public static final Register r10 = new Register(10, 10, "r10", CPU); 63 public static final Register r11 = new Register(11, 11, "r11", CPU); 64 public static final Register r12 = new Register(12, 12, "r12", CPU); 65 public static final Register r13 = new Register(13, 13, "r13", CPU); 66 public static final Register r14 = new Register(14, 14, "r14", CPU); 67 public static final Register r15 = new Register(15, 15, "r15", CPU); 68 69 public static final Register[] cpuRegisters = { 70 rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, 71 r8, r9, r10, r11, r12, r13, r14, r15 72 }; 73 74 public static final RegisterCategory XMM = new RegisterCategory("XMM"); 75 76 // XMM registers 77 public static final Register xmm0 = new Register(16, 0, "xmm0", XMM); 78 public static final Register xmm1 = new Register(17, 1, "xmm1", XMM); 79 public static final Register xmm2 = new Register(18, 2, "xmm2", XMM); 80 public static final Register xmm3 = new Register(19, 3, "xmm3", XMM); 81 public static final Register xmm4 = new Register(20, 4, "xmm4", XMM); 82 public static final Register xmm5 = new Register(21, 5, "xmm5", XMM); 83 public static final Register xmm6 = new Register(22, 6, "xmm6", XMM); 84 public static final Register xmm7 = new Register(23, 7, "xmm7", XMM); 85 86 public static final Register xmm8 = new Register(24, 8, "xmm8", XMM); 87 public static final Register xmm9 = new Register(25, 9, "xmm9", XMM); 88 public static final Register xmm10 = new Register(26, 10, "xmm10", XMM); 89 public static final Register xmm11 = new Register(27, 11, "xmm11", XMM); 90 public static final Register xmm12 = new Register(28, 12, "xmm12", XMM); 91 public static final Register xmm13 = new Register(29, 13, "xmm13", XMM); 92 public static final Register xmm14 = new Register(30, 14, "xmm14", XMM); 93 public static final Register xmm15 = new Register(31, 15, "xmm15", XMM); 94 95 public static final Register xmm16 = new Register(32, 16, "xmm16", XMM); 96 public static final Register xmm17 = new Register(33, 17, "xmm17", XMM); 97 public static final Register xmm18 = new Register(34, 18, "xmm18", XMM); 98 public static final Register xmm19 = new Register(35, 19, "xmm19", XMM); 99 public static final Register xmm20 = new Register(36, 20, "xmm20", XMM); 100 public static final Register xmm21 = new Register(37, 21, "xmm21", XMM); 101 public static final Register xmm22 = new Register(38, 22, "xmm22", XMM); 102 public static final Register xmm23 = new Register(39, 23, "xmm23", XMM); 103 104 public static final Register xmm24 = new Register(40, 24, "xmm24", XMM); 105 public static final Register xmm25 = new Register(41, 25, "xmm25", XMM); 106 public static final Register xmm26 = new Register(42, 26, "xmm26", XMM); 107 public static final Register xmm27 = new Register(43, 27, "xmm27", XMM); 108 public static final Register xmm28 = new Register(44, 28, "xmm28", XMM); 109 public static final Register xmm29 = new Register(45, 29, "xmm29", XMM); 110 public static final Register xmm30 = new Register(46, 30, "xmm30", XMM); 111 public static final Register xmm31 = new Register(47, 31, "xmm31", XMM); 112 113 public static final Register[] xmmRegistersSSE = { 114 xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, 115 xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 116 }; 117 118 public static final Register[] xmmRegistersAVX512 = { 119 xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, 120 xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, 121 xmm16, xmm17, xmm18, xmm19, xmm20, xmm21, xmm22, xmm23, 122 xmm24, xmm25, xmm26, xmm27, xmm28, xmm29, xmm30, xmm31 123 }; 124 125 public static final RegisterCategory MASK = new RegisterCategory("MASK", false); 126 127 public static final Register k0 = new Register(48, 0, "k0", MASK); 128 public static final Register k1 = new Register(49, 1, "k1", MASK); 129 public static final Register k2 = new Register(50, 2, "k2", MASK); 130 public static final Register k3 = new Register(51, 3, "k3", MASK); 131 public static final Register k4 = new Register(52, 4, "k4", MASK); 132 public static final Register k5 = new Register(53, 5, "k5", MASK); 133 public static final Register k6 = new Register(54, 6, "k6", MASK); 134 public static final Register k7 = new Register(55, 7, "k7", MASK); 135 136 public static final RegisterArray valueRegistersSSE = new RegisterArray( 137 rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, 138 r8, r9, r10, r11, r12, r13, r14, r15, 139 xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, 140 xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 141 ); 142 143 public static final RegisterArray valueRegistersAVX512 = new RegisterArray( 144 rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, 145 r8, r9, r10, r11, r12, r13, r14, r15, 146 xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, 147 xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, 148 xmm16, xmm17, xmm18, xmm19, xmm20, xmm21, xmm22, xmm23, 149 xmm24, xmm25, xmm26, xmm27, xmm28, xmm29, xmm30, xmm31, 150 k0, k1, k2, k3, k4, k5, k6, k7 151 ); 152 153 /** 154 * Register used to construct an instruction-relative address. 155 */ 156 public static final Register rip = new Register(56, -1, "rip", SPECIAL); 157 158 public static final RegisterArray allRegisters = new RegisterArray( 159 rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, 160 r8, r9, r10, r11, r12, r13, r14, r15, 161 xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, 162 xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, 163 xmm16, xmm17, xmm18, xmm19, xmm20, xmm21, xmm22, xmm23, 164 xmm24, xmm25, xmm26, xmm27, xmm28, xmm29, xmm30, xmm31, 165 k0, k1, k2, k3, k4, k5, k6, k7, 166 rip 167 ); 168 169 // @formatter:on 170 171 /** 172 * Basic set of CPU features mirroring what is returned from the cpuid instruction. See: 173 * {@code VM_Version::cpuFeatureFlags}. 174 */ 175 public enum CPUFeature implements CPUFeatureName { 176 CX8, 177 CMOV, 178 FXSR, 179 HT, 180 MMX, 181 AMD_3DNOW_PREFETCH, 182 SSE, 183 SSE2, 184 SSE3, 185 SSSE3, 186 SSE4A, 187 SSE4_1, 188 SSE4_2, 189 POPCNT, 190 LZCNT, 191 TSC, 192 TSCINV, 193 TSCINV_BIT, 194 AVX, 195 AVX2, 196 AES, 197 ERMS, 198 CLMUL, 199 BMI1, 200 BMI2, 201 RTM, 202 ADX, 203 AVX512F, 204 AVX512DQ, 205 AVX512PF, 206 AVX512ER, 207 AVX512CD, 208 AVX512BW, 209 AVX512VL, 210 SHA, 211 FMA, 212 VZEROUPPER, 213 AVX512_VPOPCNTDQ, 214 AVX512_VPCLMULQDQ, 215 AVX512_VAES, 216 AVX512_VNNI, 217 FLUSH, 218 FLUSHOPT, 219 CLWB, 220 AVX512_VBMI2, 221 AVX512_VBMI, 222 HV, 223 } 224 225 private final EnumSet<CPUFeature> features; 226 227 /** 228 * Set of flags to control code emission. 229 */ 230 public enum Flag { 231 UseCountLeadingZerosInstruction, 232 UseCountTrailingZerosInstruction 233 } 234 235 private final EnumSet<Flag> flags; 236 237 private final AMD64Kind largestKind; 238 AMD64(EnumSet<CPUFeature> features, EnumSet<Flag> flags)239 public AMD64(EnumSet<CPUFeature> features, EnumSet<Flag> flags) { 240 super("AMD64", AMD64Kind.QWORD, ByteOrder.LITTLE_ENDIAN, true, allRegisters, LOAD_LOAD | LOAD_STORE | STORE_STORE, 1, 8); 241 this.features = features; 242 this.flags = flags; 243 assert features.contains(CPUFeature.SSE2) : "minimum config for x64"; 244 245 if (features.contains(CPUFeature.AVX512F)) { 246 largestKind = AMD64Kind.V512_QWORD; 247 } else if (features.contains(CPUFeature.AVX)) { 248 largestKind = AMD64Kind.V256_QWORD; 249 } else { 250 largestKind = AMD64Kind.V128_QWORD; 251 } 252 } 253 254 @Override getFeatures()255 public EnumSet<CPUFeature> getFeatures() { 256 return features; 257 } 258 getFlags()259 public EnumSet<Flag> getFlags() { 260 return flags; 261 } 262 263 @Override getAvailableValueRegisters()264 public RegisterArray getAvailableValueRegisters() { 265 if (features.contains(CPUFeature.AVX512F)) { 266 return valueRegistersAVX512; 267 } else { 268 return valueRegistersSSE; 269 } 270 } 271 272 @Override getPlatformKind(JavaKind javaKind)273 public PlatformKind getPlatformKind(JavaKind javaKind) { 274 switch (javaKind) { 275 case Boolean: 276 case Byte: 277 return AMD64Kind.BYTE; 278 case Short: 279 case Char: 280 return AMD64Kind.WORD; 281 case Int: 282 return AMD64Kind.DWORD; 283 case Long: 284 case Object: 285 return AMD64Kind.QWORD; 286 case Float: 287 return AMD64Kind.SINGLE; 288 case Double: 289 return AMD64Kind.DOUBLE; 290 default: 291 return null; 292 } 293 } 294 295 @Override canStoreValue(RegisterCategory category, PlatformKind platformKind)296 public boolean canStoreValue(RegisterCategory category, PlatformKind platformKind) { 297 AMD64Kind kind = (AMD64Kind) platformKind; 298 if (kind.isInteger()) { 299 return category.equals(CPU); 300 } else if (kind.isXMM()) { 301 return category.equals(XMM); 302 } else { 303 assert kind.isMask(); 304 return category.equals(MASK); 305 } 306 } 307 308 @Override getLargestStorableKind(RegisterCategory category)309 public AMD64Kind getLargestStorableKind(RegisterCategory category) { 310 if (category.equals(CPU)) { 311 return AMD64Kind.QWORD; 312 } else if (category.equals(XMM)) { 313 return largestKind; 314 } else if (category.equals(MASK)) { 315 return AMD64Kind.MASK64; 316 } else { 317 return null; 318 } 319 } 320 } 321