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