1 /*
   2  * Copyright (c) 2009, 2011, 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 com.oracle.graal.amd64;
  24 
  25 import static com.oracle.graal.api.code.MemoryBarriers.*;
  26 import static com.oracle.graal.api.code.Register.*;
  27 
  28 import java.nio.*;
  29 import java.util.*;
  30 
  31 import com.oracle.graal.api.code.*;
  32 import com.oracle.graal.api.code.Register.RegisterCategory;
  33 import com.oracle.graal.api.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     public AMD64(EnumSet<CPUFeature> features) {
 142         super("AMD64", 8, ByteOrder.LITTLE_ENDIAN, true, allRegisters, LOAD_STORE | STORE_STORE, 1, cpuRegisters.length + (xmmRegisters.length << XMM_REFERENCE_MAP_SHIFT), 8);
 143         this.features = features;
 144         assert features.contains(CPUFeature.SSE2) : "minimum config for x64";
 145     }
 146 
 147     public EnumSet<CPUFeature> getFeatures() {
 148         return features;
 149     }
 150 
 151     @Override
 152     public boolean canStoreValue(RegisterCategory category, PlatformKind platformKind) {
 153         if (!(platformKind instanceof Kind)) {
 154             return false;
 155         }
 156 
 157         Kind kind = (Kind) platformKind;
 158         if (category.equals(CPU)) {
 159             switch (kind) {
 160                 case Boolean:
 161                 case Byte:
 162                 case Char:
 163                 case Short:
 164                 case Int:
 165                 case Long:
 166                 case Object:
 167                     return true;
 168             }
 169         } else if (category.equals(XMM)) {
 170             switch (kind) {
 171                 case Float:
 172                 case Double:
 173                     return true;
 174             }
 175         }
 176 
 177         return false;
 178     }
 179 
 180     @Override
 181     public PlatformKind getLargestStorableKind(RegisterCategory category) {
 182         if (category.equals(CPU)) {
 183             return Kind.Long;
 184         } else if (category.equals(XMM)) {
 185             return Kind.Double;
 186         } else {
 187             return Kind.Illegal;
 188         }
 189     }
 190 }