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