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 */
23package jdk.vm.ci.amd64;
24
25import static jdk.vm.ci.code.MemoryBarriers.LOAD_LOAD;
26import static jdk.vm.ci.code.MemoryBarriers.LOAD_STORE;
27import static jdk.vm.ci.code.MemoryBarriers.STORE_STORE;
28import static jdk.vm.ci.code.Register.SPECIAL;
29
30import java.nio.ByteOrder;
31import java.util.EnumSet;
32
33import jdk.vm.ci.code.Architecture;
34import jdk.vm.ci.code.Register;
35import jdk.vm.ci.code.Register.RegisterCategory;
36import jdk.vm.ci.code.RegisterArray;
37import jdk.vm.ci.meta.JavaKind;
38import jdk.vm.ci.meta.PlatformKind;
39
40/**
41 * Represents the AMD64 architecture.
42 */
43public class AMD64 extends Architecture {
44
45    public static final RegisterCategory CPU = new RegisterCategory("CPU");
46
47    // @formatter:off
48
49    // General purpose CPU registers
50    public static final Register rax = new Register(0, 0, "rax", CPU);
51    public static final Register rcx = new Register(1, 1, "rcx", CPU);
52    public static final Register rdx = new Register(2, 2, "rdx", CPU);
53    public static final Register rbx = new Register(3, 3, "rbx", CPU);
54    public static final Register rsp = new Register(4, 4, "rsp", CPU);
55    public static final Register rbp = new Register(5, 5, "rbp", CPU);
56    public static final Register rsi = new Register(6, 6, "rsi", CPU);
57    public static final Register rdi = new Register(7, 7, "rdi", CPU);
58
59    public static final Register r8  = new Register(8,  8,  "r8", CPU);
60    public static final Register r9  = new Register(9,  9,  "r9", CPU);
61    public static final Register r10 = new Register(10, 10, "r10", CPU);
62    public static final Register r11 = new Register(11, 11, "r11", CPU);
63    public static final Register r12 = new Register(12, 12, "r12", CPU);
64    public static final Register r13 = new Register(13, 13, "r13", CPU);
65    public static final Register r14 = new Register(14, 14, "r14", CPU);
66    public static final Register r15 = new Register(15, 15, "r15", CPU);
67
68    public static final Register[] cpuRegisters = {
69        rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi,
70        r8, r9, r10, r11, r12, r13, r14, r15
71    };
72
73    public static final RegisterCategory XMM = new RegisterCategory("XMM");
74
75    // XMM registers
76    public static final Register xmm0 = new Register(16, 0, "xmm0", XMM);
77    public static final Register xmm1 = new Register(17, 1, "xmm1", XMM);
78    public static final Register xmm2 = new Register(18, 2, "xmm2", XMM);
79    public static final Register xmm3 = new Register(19, 3, "xmm3", XMM);
80    public static final Register xmm4 = new Register(20, 4, "xmm4", XMM);
81    public static final Register xmm5 = new Register(21, 5, "xmm5", XMM);
82    public static final Register xmm6 = new Register(22, 6, "xmm6", XMM);
83    public static final Register xmm7 = new Register(23, 7, "xmm7", XMM);
84
85    public static final Register xmm8  = new Register(24,  8, "xmm8",  XMM);
86    public static final Register xmm9  = new Register(25,  9, "xmm9",  XMM);
87    public static final Register xmm10 = new Register(26, 10, "xmm10", XMM);
88    public static final Register xmm11 = new Register(27, 11, "xmm11", XMM);
89    public static final Register xmm12 = new Register(28, 12, "xmm12", XMM);
90    public static final Register xmm13 = new Register(29, 13, "xmm13", XMM);
91    public static final Register xmm14 = new Register(30, 14, "xmm14", XMM);
92    public static final Register xmm15 = new Register(31, 15, "xmm15", XMM);
93
94    public static final Register xmm16 = new Register(32, 16, "xmm16", XMM);
95    public static final Register xmm17 = new Register(33, 17, "xmm17", XMM);
96    public static final Register xmm18 = new Register(34, 18, "xmm18", XMM);
97    public static final Register xmm19 = new Register(35, 19, "xmm19", XMM);
98    public static final Register xmm20 = new Register(36, 20, "xmm20", XMM);
99    public static final Register xmm21 = new Register(37, 21, "xmm21", XMM);
100    public static final Register xmm22 = new Register(38, 22, "xmm22", XMM);
101    public static final Register xmm23 = new Register(39, 23, "xmm23", XMM);
102
103    public static final Register xmm24 = new Register(40, 24, "xmm24", XMM);
104    public static final Register xmm25 = new Register(41, 25, "xmm25", XMM);
105    public static final Register xmm26 = new Register(42, 26, "xmm26", XMM);
106    public static final Register xmm27 = new Register(43, 27, "xmm27", XMM);
107    public static final Register xmm28 = new Register(44, 28, "xmm28", XMM);
108    public static final Register xmm29 = new Register(45, 29, "xmm29", XMM);
109    public static final Register xmm30 = new Register(46, 30, "xmm30", XMM);
110    public static final Register xmm31 = new Register(47, 31, "xmm31", XMM);
111
112    public static final Register[] xmmRegistersSSE = {
113        xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
114        xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
115    };
116
117    public static final Register[] xmmRegistersAVX512 = {
118        xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
119        xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,
120        xmm16, xmm17, xmm18, xmm19, xmm20, xmm21, xmm22, xmm23,
121        xmm24, xmm25, xmm26, xmm27, xmm28, xmm29, xmm30, xmm31
122    };
123
124    public static final RegisterCategory MASK = new RegisterCategory("MASK", false);
125
126    public static final Register k0 = new Register(48, 0, "k0", MASK);
127    public static final Register k1 = new Register(49, 1, "k1", MASK);
128    public static final Register k2 = new Register(50, 2, "k2", MASK);
129    public static final Register k3 = new Register(51, 3, "k3", MASK);
130    public static final Register k4 = new Register(52, 4, "k4", MASK);
131    public static final Register k5 = new Register(53, 5, "k5", MASK);
132    public static final Register k6 = new Register(54, 6, "k6", MASK);
133    public static final Register k7 = new Register(55, 7, "k7", MASK);
134
135    public static final RegisterArray valueRegistersSSE = new RegisterArray(
136        rax,  rcx,  rdx,   rbx,   rsp,   rbp,   rsi,   rdi,
137        r8,   r9,   r10,   r11,   r12,   r13,   r14,   r15,
138        xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
139        xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
140    );
141
142    public static final RegisterArray valueRegistersAVX512 = new RegisterArray(
143        rax,  rcx,  rdx,   rbx,   rsp,   rbp,   rsi,   rdi,
144        r8,   r9,   r10,   r11,   r12,   r13,   r14,   r15,
145        xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
146        xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,
147        xmm16, xmm17, xmm18, xmm19, xmm20, xmm21, xmm22, xmm23,
148        xmm24, xmm25, xmm26, xmm27, xmm28, xmm29, xmm30, xmm31,
149        k0, k1, k2, k3, k4, k5, k6, k7
150    );
151
152    /**
153     * Register used to construct an instruction-relative address.
154     */
155    public static final Register rip = new Register(56, -1, "rip", SPECIAL);
156
157    public static final RegisterArray allRegisters = new RegisterArray(
158        rax,  rcx,  rdx,   rbx,   rsp,   rbp,   rsi,   rdi,
159        r8,   r9,   r10,   r11,   r12,   r13,   r14,   r15,
160        xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
161        xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,
162        xmm16, xmm17, xmm18, xmm19, xmm20, xmm21, xmm22, xmm23,
163        xmm24, xmm25, xmm26, xmm27, xmm28, xmm29, xmm30, xmm31,
164        k0, k1, k2, k3, k4, k5, k6, k7,
165        rip
166    );
167
168    // @formatter:on
169
170    /**
171     * Basic set of CPU features mirroring what is returned from the cpuid instruction. See:
172     * {@code VM_Version::cpuFeatureFlags}.
173     */
174    public enum CPUFeature {
175        CX8,
176        CMOV,
177        FXSR,
178        HT,
179        MMX,
180        AMD_3DNOW_PREFETCH,
181        SSE,
182        SSE2,
183        SSE3,
184        SSSE3,
185        SSE4A,
186        SSE4_1,
187        SSE4_2,
188        POPCNT,
189        LZCNT,
190        TSC,
191        TSCINV,
192        AVX,
193        AVX2,
194        AES,
195        ERMS,
196        CLMUL,
197        BMI1,
198        BMI2,
199        RTM,
200        ADX,
201        AVX512F,
202        AVX512DQ,
203        AVX512PF,
204        AVX512ER,
205        AVX512CD,
206        AVX512BW,
207        AVX512VL,
208        SHA,
209        FMA
210    }
211
212    private final EnumSet<CPUFeature> features;
213
214    /**
215     * Set of flags to control code emission.
216     */
217    public enum Flag {
218        UseCountLeadingZerosInstruction,
219        UseCountTrailingZerosInstruction
220    }
221
222    private final EnumSet<Flag> flags;
223
224    private final AMD64Kind largestKind;
225
226    public AMD64(EnumSet<CPUFeature> features, EnumSet<Flag> flags) {
227        super("AMD64", AMD64Kind.QWORD, ByteOrder.LITTLE_ENDIAN, true, allRegisters, LOAD_LOAD | LOAD_STORE | STORE_STORE, 1, 8);
228        this.features = features;
229        this.flags = flags;
230        assert features.contains(CPUFeature.SSE2) : "minimum config for x64";
231
232        if (features.contains(CPUFeature.AVX512F)) {
233            largestKind = AMD64Kind.V512_QWORD;
234        } else if (features.contains(CPUFeature.AVX)) {
235            largestKind = AMD64Kind.V256_QWORD;
236        } else {
237            largestKind = AMD64Kind.V128_QWORD;
238        }
239    }
240
241    public EnumSet<CPUFeature> getFeatures() {
242        return features;
243    }
244
245    public EnumSet<Flag> getFlags() {
246        return flags;
247    }
248
249    @Override
250    public RegisterArray getAvailableValueRegisters() {
251        if (features.contains(CPUFeature.AVX512F)) {
252            return valueRegistersAVX512;
253        } else {
254            return valueRegistersSSE;
255        }
256    }
257
258    @Override
259    public PlatformKind getPlatformKind(JavaKind javaKind) {
260        switch (javaKind) {
261            case Boolean:
262            case Byte:
263                return AMD64Kind.BYTE;
264            case Short:
265            case Char:
266                return AMD64Kind.WORD;
267            case Int:
268                return AMD64Kind.DWORD;
269            case Long:
270            case Object:
271                return AMD64Kind.QWORD;
272            case Float:
273                return AMD64Kind.SINGLE;
274            case Double:
275                return AMD64Kind.DOUBLE;
276            default:
277                return null;
278        }
279    }
280
281    @Override
282    public boolean canStoreValue(RegisterCategory category, PlatformKind platformKind) {
283        AMD64Kind kind = (AMD64Kind) platformKind;
284        if (kind.isInteger()) {
285            return category.equals(CPU);
286        } else if (kind.isXMM()) {
287            return category.equals(XMM);
288        } else {
289            assert kind.isMask();
290            return category.equals(MASK);
291        }
292    }
293
294    @Override
295    public AMD64Kind getLargestStorableKind(RegisterCategory category) {
296        if (category.equals(CPU)) {
297            return AMD64Kind.QWORD;
298        } else if (category.equals(XMM)) {
299            return largestKind;
300        } else if (category.equals(MASK)) {
301            return AMD64Kind.MASK64;
302        } else {
303            return null;
304        }
305    }
306}
307