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     }
 137 
 138     private final EnumSet<CPUFeature> features;
 139 
 140     public AMD64(EnumSet<CPUFeature> features) {
 141         super("AMD64", 8, ByteOrder.LITTLE_ENDIAN, true, allRegisters, LOAD_STORE | STORE_STORE, 1, cpuRegisters.length + (xmmRegisters.length << XMM_REFERENCE_MAP_SHIFT), 8);
 142         this.features = features;
 143         assert features.contains(CPUFeature.SSE2) : "minimum config for x64";
 144     }
 145 
 146     public EnumSet<CPUFeature> getFeatures() {
 147         return features;
 148     }
 149 
 150     @Override
 151     public boolean canStoreValue(RegisterCategory category, PlatformKind platformKind) {
 152         if (!(platformKind instanceof Kind)) {
 153             return false;
 154         }
 155 
 156         Kind kind = (Kind) platformKind;
 157         if (category.equals(CPU)) {
 158             switch (kind) {
 159                 case Boolean:
 160                 case Byte:
 161                 case Char:
 162                 case Short:
 163                 case Int:
 164                 case Long:
 165                 case Object:
 166                     return true;
 167             }
 168         } else if (category.equals(XMM)) {
 169             switch (kind) {
 170                 case Float:
 171                 case Double:
 172                     return true;
 173             }
 174         }
 175 
 176         return false;
 177     }
 178 
 179     @Override
 180     public PlatformKind getLargestStorableKind(RegisterCategory category) {
 181         if (category.equals(CPU)) {
 182             return Kind.Long;
 183         } else if (category.equals(XMM)) {
 184             return Kind.Double;
 185         } else {
 186             return Kind.Illegal;
 187         }
 188     }
 189 }