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 }