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