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.internal.jvmci.amd64;
  24 
  25 import static jdk.internal.jvmci.code.MemoryBarriers.*;
  26 import static jdk.internal.jvmci.code.Register.*;
  27 
  28 import java.nio.*;
  29 import java.util.*;
  30 
  31 import jdk.internal.jvmci.code.*;
  32 import jdk.internal.jvmci.code.Register.RegisterCategory;
  33 import jdk.internal.jvmci.meta.*;
  34 
  35 /**
  36  * Represents the AMD64 architecture.
  37  */
  38 public class AMD64 extends Architecture {
  39 
  40     public static final RegisterCategory CPU = new RegisterCategory("CPU");
  41 
  42     // @formatter:off
  43 
  44     // General purpose CPU registers
  45     public static final Register rax = new Register(0, 0, "rax", CPU);
  46     public static final Register rcx = new Register(1, 1, "rcx", CPU);
  47     public static final Register rdx = new Register(2, 2, "rdx", CPU);
  48     public static final Register rbx = new Register(3, 3, "rbx", CPU);
  49     public static final Register rsp = new Register(4, 4, "rsp", CPU);
  50     public static final Register rbp = new Register(5, 5, "rbp", CPU);
  51     public static final Register rsi = new Register(6, 6, "rsi", CPU);
  52     public static final Register rdi = new Register(7, 7, "rdi", CPU);
  53 
  54     public static final Register r8  = new Register(8,  8,  "r8", CPU);
  55     public static final Register r9  = new Register(9,  9,  "r9", CPU);
  56     public static final Register r10 = new Register(10, 10, "r10", CPU);
  57     public static final Register r11 = new Register(11, 11, "r11", CPU);
  58     public static final Register r12 = new Register(12, 12, "r12", CPU);
  59     public static final Register r13 = new Register(13, 13, "r13", CPU);
  60     public static final Register r14 = new Register(14, 14, "r14", CPU);
  61     public static final Register r15 = new Register(15, 15, "r15", CPU);
  62 
  63     public static final Register[] cpuRegisters = {
  64         rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi,
  65         r8, r9, r10, r11, r12, r13, r14, r15
  66     };
  67 
  68     private static final int XMM_REFERENCE_MAP_SHIFT = 2;
  69 
  70     public static final RegisterCategory XMM = new RegisterCategory("XMM", cpuRegisters.length, XMM_REFERENCE_MAP_SHIFT);
  71 
  72     // XMM registers
  73     public static final Register xmm0 = new Register(16, 0, "xmm0", XMM);
  74     public static final Register xmm1 = new Register(17, 1, "xmm1", XMM);
  75     public static final Register xmm2 = new Register(18, 2, "xmm2", XMM);
  76     public static final Register xmm3 = new Register(19, 3, "xmm3", XMM);
  77     public static final Register xmm4 = new Register(20, 4, "xmm4", XMM);
  78     public static final Register xmm5 = new Register(21, 5, "xmm5", XMM);
  79     public static final Register xmm6 = new Register(22, 6, "xmm6", XMM);
  80     public static final Register xmm7 = new Register(23, 7, "xmm7", XMM);
  81 
  82     public static final Register xmm8 =  new Register(24,  8, "xmm8",  XMM);
  83     public static final Register xmm9 =  new Register(25,  9, "xmm9",  XMM);
  84     public static final Register xmm10 = new Register(26, 10, "xmm10", XMM);
  85     public static final Register xmm11 = new Register(27, 11, "xmm11", XMM);
  86     public static final Register xmm12 = new Register(28, 12, "xmm12", XMM);
  87     public static final Register xmm13 = new Register(29, 13, "xmm13", XMM);
  88     public static final Register xmm14 = new Register(30, 14, "xmm14", XMM);
  89     public static final Register xmm15 = new Register(31, 15, "xmm15", XMM);
  90 
  91     public static final Register[] xmmRegisters = {
  92         xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
  93         xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
  94     };
  95 
  96     public static final Register[] cpuxmmRegisters = {
  97         rax,  rcx,  rdx,   rbx,   rsp,   rbp,   rsi,   rdi,
  98         r8,   r9,   r10,   r11,   r12,   r13,   r14,   r15,
  99         xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
 100         xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
 101     };
 102 
 103     /**
 104      * Register used to construct an instruction-relative address.
 105      */
 106     public static final Register rip = new Register(32, -1, "rip", SPECIAL);
 107 
 108     public static final Register[] allRegisters = {
 109         rax,  rcx,  rdx,   rbx,   rsp,   rbp,   rsi,   rdi,
 110         r8,   r9,   r10,   r11,   r12,   r13,   r14,   r15,
 111         xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
 112         xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,
 113         rip
 114     };
 115 
 116     // @formatter:on
 117 
 118     /**
 119      * Basic set of CPU features mirroring what is returned from the cpuid instruction.
 120      */
 121     public static enum CPUFeature {
 122         SSE,
 123         SSE2,
 124         SSE3,
 125         SSE4a,
 126         SSE4_1,
 127         SSE4_2,
 128         SSSE3,
 129         POPCNT,
 130         LZCNT,
 131         AVX,
 132         AVX2,
 133         ERMS,
 134         AMD_3DNOW_PREFETCH,
 135         AES,
 136         BMI1
 137     }
 138 
 139     private final EnumSet<CPUFeature> features;
 140 
 141     /**
 142      * Set of flags to control code emission.
 143      */
 144     public static enum Flag {
 145         UseCountLeadingZerosInstruction,
 146         UseCountTrailingZerosInstruction
 147     }
 148 
 149     private final EnumSet<Flag> flags;
 150 
 151     public AMD64(EnumSet<CPUFeature> features, EnumSet<Flag> flags) {
 152         super("AMD64", JavaKind.Long, ByteOrder.LITTLE_ENDIAN, true, allRegisters, LOAD_STORE | STORE_STORE, 1, cpuRegisters.length + (xmmRegisters.length << XMM_REFERENCE_MAP_SHIFT), 8);
 153         this.features = features;
 154         this.flags = flags;
 155         assert features.contains(CPUFeature.SSE2) : "minimum config for x64";
 156     }
 157 
 158     public EnumSet<CPUFeature> getFeatures() {
 159         return features;
 160     }
 161 
 162     public EnumSet<Flag> getFlags() {
 163         return flags;
 164     }
 165 
 166     @Override
 167     public PlatformKind getPlatformKind(JavaKind javaKind) {
 168         if (javaKind.isObject()) {
 169             return getWordKind();
 170         } else {
 171             return javaKind;
 172         }
 173     }
 174 
 175     @Override
 176     public boolean canStoreValue(RegisterCategory category, PlatformKind platformKind) {
 177         if (!(platformKind instanceof JavaKind)) {
 178             return false;
 179         }
 180 
 181         JavaKind kind = (JavaKind) platformKind;
 182         if (category.equals(CPU)) {
 183             switch (kind) {
 184                 case Boolean:
 185                 case Byte:
 186                 case Char:
 187                 case Short:
 188                 case Int:
 189                 case Long:
 190                     return true;
 191             }
 192         } else if (category.equals(XMM)) {
 193             switch (kind) {
 194                 case Float:
 195                 case Double:
 196                     return true;
 197             }
 198         }
 199 
 200         return false;
 201     }
 202 
 203     @Override
 204     public PlatformKind getLargestStorableKind(RegisterCategory category) {
 205         if (category.equals(CPU)) {
 206             return JavaKind.Long;
 207         } else if (category.equals(XMM)) {
 208             return JavaKind.Double;
 209         } else {
 210             return JavaKind.Illegal;
 211         }
 212     }
 213 }