001/*
002 * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.
008 *
009 * This code is distributed in the hope that it will be useful, but WITHOUT
010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
011 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
012 * version 2 for more details (a copy is included in the LICENSE file that
013 * accompanied this code).
014 *
015 * You should have received a copy of the GNU General Public License version
016 * 2 along with this work; if not, write to the Free Software Foundation,
017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
018 *
019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
020 * or visit www.oracle.com if you need additional information or have any
021 * questions.
022 */
023package jdk.internal.jvmci.amd64;
024
025import static jdk.internal.jvmci.code.MemoryBarriers.*;
026import static jdk.internal.jvmci.code.Register.*;
027
028import java.nio.*;
029import java.util.*;
030
031import jdk.internal.jvmci.code.*;
032import jdk.internal.jvmci.code.Register.RegisterCategory;
033import jdk.internal.jvmci.meta.*;
034
035/**
036 * Represents the AMD64 architecture.
037 */
038public class AMD64 extends Architecture {
039
040    public static final RegisterCategory CPU = new RegisterCategory("CPU");
041
042    // @formatter:off
043
044    // General purpose CPU registers
045    public static final Register rax = new Register(0, 0, "rax", CPU);
046    public static final Register rcx = new Register(1, 1, "rcx", CPU);
047    public static final Register rdx = new Register(2, 2, "rdx", CPU);
048    public static final Register rbx = new Register(3, 3, "rbx", CPU);
049    public static final Register rsp = new Register(4, 4, "rsp", CPU);
050    public static final Register rbp = new Register(5, 5, "rbp", CPU);
051    public static final Register rsi = new Register(6, 6, "rsi", CPU);
052    public static final Register rdi = new Register(7, 7, "rdi", CPU);
053
054    public static final Register r8  = new Register(8,  8,  "r8", CPU);
055    public static final Register r9  = new Register(9,  9,  "r9", CPU);
056    public static final Register r10 = new Register(10, 10, "r10", CPU);
057    public static final Register r11 = new Register(11, 11, "r11", CPU);
058    public static final Register r12 = new Register(12, 12, "r12", CPU);
059    public static final Register r13 = new Register(13, 13, "r13", CPU);
060    public static final Register r14 = new Register(14, 14, "r14", CPU);
061    public static final Register r15 = new Register(15, 15, "r15", CPU);
062
063    public static final Register[] cpuRegisters = {
064        rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi,
065        r8, r9, r10, r11, r12, r13, r14, r15
066    };
067
068    private static final int XMM_REFERENCE_MAP_SHIFT = 2;
069
070    public static final RegisterCategory XMM = new RegisterCategory("XMM", cpuRegisters.length, XMM_REFERENCE_MAP_SHIFT);
071
072    // XMM registers
073    public static final Register xmm0 = new Register(16, 0, "xmm0", XMM);
074    public static final Register xmm1 = new Register(17, 1, "xmm1", XMM);
075    public static final Register xmm2 = new Register(18, 2, "xmm2", XMM);
076    public static final Register xmm3 = new Register(19, 3, "xmm3", XMM);
077    public static final Register xmm4 = new Register(20, 4, "xmm4", XMM);
078    public static final Register xmm5 = new Register(21, 5, "xmm5", XMM);
079    public static final Register xmm6 = new Register(22, 6, "xmm6", XMM);
080    public static final Register xmm7 = new Register(23, 7, "xmm7", XMM);
081
082    public static final Register xmm8 =  new Register(24,  8, "xmm8",  XMM);
083    public static final Register xmm9 =  new Register(25,  9, "xmm9",  XMM);
084    public static final Register xmm10 = new Register(26, 10, "xmm10", XMM);
085    public static final Register xmm11 = new Register(27, 11, "xmm11", XMM);
086    public static final Register xmm12 = new Register(28, 12, "xmm12", XMM);
087    public static final Register xmm13 = new Register(29, 13, "xmm13", XMM);
088    public static final Register xmm14 = new Register(30, 14, "xmm14", XMM);
089    public static final Register xmm15 = new Register(31, 15, "xmm15", XMM);
090
091    public static final Register[] xmmRegisters = {
092        xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
093        xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
094    };
095
096    public static final Register[] cpuxmmRegisters = {
097        rax,  rcx,  rdx,   rbx,   rsp,   rbp,   rsi,   rdi,
098        r8,   r9,   r10,   r11,   r12,   r13,   r14,   r15,
099        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", 8, 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 boolean canStoreValue(RegisterCategory category, PlatformKind platformKind) {
168        if (!(platformKind instanceof Kind)) {
169            return false;
170        }
171
172        Kind kind = (Kind) platformKind;
173        if (category.equals(CPU)) {
174            switch (kind) {
175                case Boolean:
176                case Byte:
177                case Char:
178                case Short:
179                case Int:
180                case Long:
181                case Object:
182                    return true;
183            }
184        } else if (category.equals(XMM)) {
185            switch (kind) {
186                case Float:
187                case Double:
188                    return true;
189            }
190        }
191
192        return false;
193    }
194
195    @Override
196    public PlatformKind getLargestStorableKind(RegisterCategory category) {
197        if (category.equals(CPU)) {
198            return Kind.Long;
199        } else if (category.equals(XMM)) {
200            return Kind.Double;
201        } else {
202            return Kind.Illegal;
203        }
204    }
205}