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 
 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 
 241     public EnumSet<CPUFeature> getFeatures() {
 242         return features;
 243     }
 244 
 245     public EnumSet<Flag> getFlags() {
 246         return flags;
 247     }
 248 
 249     @Override
 250     public RegisterArray getAvailableValueRegisters() {
 251         if (features.contains(CPUFeature.AVX512F)) {
 252             return valueRegistersAVX512;
 253         } else {
 254             return valueRegistersSSE;
 255         }
 256     }
 257 
 258     @Override
 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
 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
 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 }