1/*
2 * Copyright (c) 2013, 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.sparc;
24
25import static java.nio.ByteOrder.BIG_ENDIAN;
26import static jdk.vm.ci.code.MemoryBarriers.LOAD_LOAD;
27import static jdk.vm.ci.code.MemoryBarriers.LOAD_STORE;
28import static jdk.vm.ci.code.MemoryBarriers.STORE_STORE;
29
30import java.util.Set;
31
32import jdk.vm.ci.code.Architecture;
33import jdk.vm.ci.code.Register;
34import jdk.vm.ci.code.Register.RegisterCategory;
35import jdk.vm.ci.code.RegisterArray;
36import jdk.vm.ci.meta.JavaKind;
37import jdk.vm.ci.meta.PlatformKind;
38
39/**
40 * Represents the SPARC architecture.
41 */
42public class SPARC extends Architecture {
43
44    public static final RegisterCategory CPU = new RegisterCategory("CPU");
45    public static final RegisterCategory FPUs = new RegisterCategory("FPUs");
46    public static final RegisterCategory FPUd = new RegisterCategory("FPUd");
47    public static final RegisterCategory FPUq = new RegisterCategory("FPUq");
48
49    // General purpose registers
50    public static final Register g0 = new Register(0, 0, "g0", CPU);
51    public static final Register g1 = new Register(1, 1, "g1", CPU);
52    public static final Register g2 = new Register(2, 2, "g2", CPU);
53    public static final Register g3 = new Register(3, 3, "g3", CPU);
54    public static final Register g4 = new Register(4, 4, "g4", CPU);
55    public static final Register g5 = new Register(5, 5, "g5", CPU);
56    public static final Register g6 = new Register(6, 6, "g6", CPU);
57    public static final Register g7 = new Register(7, 7, "g7", CPU);
58
59    public static final Register o0 = new Register(8, 8, "o0", CPU);
60    public static final Register o1 = new Register(9, 9, "o1", CPU);
61    public static final Register o2 = new Register(10, 10, "o2", CPU);
62    public static final Register o3 = new Register(11, 11, "o3", CPU);
63    public static final Register o4 = new Register(12, 12, "o4", CPU);
64    public static final Register o5 = new Register(13, 13, "o5", CPU);
65    public static final Register o6 = new Register(14, 14, "o6", CPU);
66    public static final Register o7 = new Register(15, 15, "o7", CPU);
67
68    public static final Register l0 = new Register(16, 16, "l0", CPU);
69    public static final Register l1 = new Register(17, 17, "l1", CPU);
70    public static final Register l2 = new Register(18, 18, "l2", CPU);
71    public static final Register l3 = new Register(19, 19, "l3", CPU);
72    public static final Register l4 = new Register(20, 20, "l4", CPU);
73    public static final Register l5 = new Register(21, 21, "l5", CPU);
74    public static final Register l6 = new Register(22, 22, "l6", CPU);
75    public static final Register l7 = new Register(23, 23, "l7", CPU);
76
77    public static final Register i0 = new Register(24, 24, "i0", CPU);
78    public static final Register i1 = new Register(25, 25, "i1", CPU);
79    public static final Register i2 = new Register(26, 26, "i2", CPU);
80    public static final Register i3 = new Register(27, 27, "i3", CPU);
81    public static final Register i4 = new Register(28, 28, "i4", CPU);
82    public static final Register i5 = new Register(29, 29, "i5", CPU);
83    public static final Register i6 = new Register(30, 30, "i6", CPU);
84    public static final Register i7 = new Register(31, 31, "i7", CPU);
85
86    public static final Register sp = o6;
87    public static final Register fp = i6;
88
89    // Floating point registers
90    public static final Register f0 = new Register(32, 0, "f0", FPUs);
91    public static final Register f1 = new Register(33, 1, "f1", FPUs);
92    public static final Register f2 = new Register(34, 2, "f2", FPUs);
93    public static final Register f3 = new Register(35, 3, "f3", FPUs);
94    public static final Register f4 = new Register(36, 4, "f4", FPUs);
95    public static final Register f5 = new Register(37, 5, "f5", FPUs);
96    public static final Register f6 = new Register(38, 6, "f6", FPUs);
97    public static final Register f7 = new Register(39, 7, "f7", FPUs);
98
99    public static final Register f8 = new Register(40, 8, "f8", FPUs);
100    public static final Register f9 = new Register(41, 9, "f9", FPUs);
101    public static final Register f10 = new Register(42, 10, "f10", FPUs);
102    public static final Register f11 = new Register(43, 11, "f11", FPUs);
103    public static final Register f12 = new Register(44, 12, "f12", FPUs);
104    public static final Register f13 = new Register(45, 13, "f13", FPUs);
105    public static final Register f14 = new Register(46, 14, "f14", FPUs);
106    public static final Register f15 = new Register(47, 15, "f15", FPUs);
107
108    public static final Register f16 = new Register(48, 16, "f16", FPUs);
109    public static final Register f17 = new Register(49, 17, "f17", FPUs);
110    public static final Register f18 = new Register(50, 18, "f18", FPUs);
111    public static final Register f19 = new Register(51, 19, "f19", FPUs);
112    public static final Register f20 = new Register(52, 20, "f20", FPUs);
113    public static final Register f21 = new Register(53, 21, "f21", FPUs);
114    public static final Register f22 = new Register(54, 22, "f22", FPUs);
115    public static final Register f23 = new Register(55, 23, "f23", FPUs);
116
117    public static final Register f24 = new Register(56, 24, "f24", FPUs);
118    public static final Register f25 = new Register(57, 25, "f25", FPUs);
119    public static final Register f26 = new Register(58, 26, "f26", FPUs);
120    public static final Register f27 = new Register(59, 27, "f27", FPUs);
121    public static final Register f28 = new Register(60, 28, "f28", FPUs);
122    public static final Register f29 = new Register(61, 29, "f29", FPUs);
123    public static final Register f30 = new Register(62, 30, "f30", FPUs);
124    public static final Register f31 = new Register(63, 31, "f31", FPUs);
125
126    // Double precision registers
127    public static final Register d0 = new Register(64, getDoubleEncoding(0), "d0", FPUd);
128    public static final Register d2 = new Register(65, getDoubleEncoding(2), "d2", FPUd);
129    public static final Register d4 = new Register(66, getDoubleEncoding(4), "d4", FPUd);
130    public static final Register d6 = new Register(67, getDoubleEncoding(6), "d6", FPUd);
131    public static final Register d8 = new Register(68, getDoubleEncoding(8), "d8", FPUd);
132    public static final Register d10 = new Register(69, getDoubleEncoding(10), "d10", FPUd);
133    public static final Register d12 = new Register(70, getDoubleEncoding(12), "d12", FPUd);
134    public static final Register d14 = new Register(71, getDoubleEncoding(14), "d14", FPUd);
135
136    public static final Register d16 = new Register(72, getDoubleEncoding(16), "d16", FPUd);
137    public static final Register d18 = new Register(73, getDoubleEncoding(18), "d18", FPUd);
138    public static final Register d20 = new Register(74, getDoubleEncoding(20), "d20", FPUd);
139    public static final Register d22 = new Register(75, getDoubleEncoding(22), "d22", FPUd);
140    public static final Register d24 = new Register(76, getDoubleEncoding(24), "d24", FPUd);
141    public static final Register d26 = new Register(77, getDoubleEncoding(26), "d26", FPUd);
142    public static final Register d28 = new Register(78, getDoubleEncoding(28), "d28", FPUd);
143    public static final Register d30 = new Register(79, getDoubleEncoding(28), "d28", FPUd);
144
145    public static final Register d32 = new Register(80, getDoubleEncoding(32), "d32", FPUd);
146    public static final Register d34 = new Register(81, getDoubleEncoding(34), "d34", FPUd);
147    public static final Register d36 = new Register(82, getDoubleEncoding(36), "d36", FPUd);
148    public static final Register d38 = new Register(83, getDoubleEncoding(38), "d38", FPUd);
149    public static final Register d40 = new Register(84, getDoubleEncoding(40), "d40", FPUd);
150    public static final Register d42 = new Register(85, getDoubleEncoding(42), "d42", FPUd);
151    public static final Register d44 = new Register(86, getDoubleEncoding(44), "d44", FPUd);
152    public static final Register d46 = new Register(87, getDoubleEncoding(46), "d46", FPUd);
153
154    public static final Register d48 = new Register(88, getDoubleEncoding(48), "d48", FPUd);
155    public static final Register d50 = new Register(89, getDoubleEncoding(50), "d50", FPUd);
156    public static final Register d52 = new Register(90, getDoubleEncoding(52), "d52", FPUd);
157    public static final Register d54 = new Register(91, getDoubleEncoding(54), "d54", FPUd);
158    public static final Register d56 = new Register(92, getDoubleEncoding(56), "d56", FPUd);
159    public static final Register d58 = new Register(93, getDoubleEncoding(58), "d58", FPUd);
160    public static final Register d60 = new Register(94, getDoubleEncoding(60), "d60", FPUd);
161    public static final Register d62 = new Register(95, getDoubleEncoding(62), "d62", FPUd);
162
163    // Quad precision registers
164    public static final Register q0 = new Register(96, getQuadncoding(0), "q0", FPUq);
165    public static final Register q4 = new Register(97, getQuadncoding(4), "q4", FPUq);
166    public static final Register q8 = new Register(98, getQuadncoding(8), "q8", FPUq);
167    public static final Register q12 = new Register(99, getQuadncoding(12), "q12", FPUq);
168    public static final Register q16 = new Register(100, getQuadncoding(16), "q16", FPUq);
169    public static final Register q20 = new Register(101, getQuadncoding(20), "q20", FPUq);
170    public static final Register q24 = new Register(102, getQuadncoding(24), "q24", FPUq);
171    public static final Register q28 = new Register(103, getQuadncoding(28), "q28", FPUq);
172
173    public static final Register q32 = new Register(104, getQuadncoding(32), "q32", FPUq);
174    public static final Register q36 = new Register(105, getQuadncoding(36), "q36", FPUq);
175    public static final Register q40 = new Register(106, getQuadncoding(40), "q40", FPUq);
176    public static final Register q44 = new Register(107, getQuadncoding(44), "q44", FPUq);
177    public static final Register q48 = new Register(108, getQuadncoding(48), "q48", FPUq);
178    public static final Register q52 = new Register(109, getQuadncoding(52), "q52", FPUq);
179    public static final Register q56 = new Register(110, getQuadncoding(56), "q56", FPUq);
180    public static final Register q60 = new Register(111, getQuadncoding(60), "q60", FPUq);
181
182    // @formatter:off
183    public static final RegisterArray cpuRegisters = new RegisterArray(
184        g0,  g1,  g2,  g3,  g4,  g5,  g6,  g7,
185        o0,  o1,  o2,  o3,  o4,  o5,  o6,  o7,
186        l0,  l1,  l2,  l3,  l4,  l5,  l6,  l7,
187        i0,  i1,  i2,  i3,  i4,  i5,  i6,  i7
188    );
189
190    public static final RegisterArray fpusRegisters = new RegisterArray(
191        f0,  f1,  f2,  f3,  f4,  f5,  f6,  f7,
192        f8,  f9,  f10, f11, f12, f13, f14, f15,
193        f16, f17, f18, f19, f20, f21, f22, f23,
194        f24, f25, f26, f27, f28, f29, f30, f31
195    );
196
197    public static final RegisterArray fpudRegisters = new RegisterArray(
198        d0, d2, d4, d6, d8,  d10, d12, d14,
199        d16, d18, d20, d22, d24, d26, d28, d30,
200        d32, d34, d36, d38, d40, d42, d44, d46,
201        d48, d50, d52, d54, d56, d58, d60, d62
202    );
203
204    public static final RegisterArray fpuqRegisters = new RegisterArray(
205        q0, q4, q8, q12,
206        q16, q20, q24, q28,
207        q32, q36, q40, q44,
208        q48, q52, q56, q60
209    );
210
211    public static final RegisterArray allRegisters = new RegisterArray(
212        g0,  g1,  g2,  g3,  g4,  g5,  g6,  g7,
213        o0,  o1,  o2,  o3,  o4,  o5,  o6,  o7,
214        l0,  l1,  l2,  l3,  l4,  l5,  l6,  l7,
215        i0,  i1,  i2,  i3,  i4,  i5,  i6,  i7,
216
217        f0,  f1,  f2,  f3,  f4,  f5,  f6,  f7,
218        f8,  f9,  f10, f11, f12, f13, f14, f15,
219        f16, f17, f18, f19, f20, f21, f22, f23,
220        f24, f25, f26, f27, f28, f29, f30, f31,
221
222        d0, d2, d4, d6, d8,  d10, d12, d14,
223        d16, d18, d20, d22, d24, d26, d28, d30,
224        d32, d34, d36, d38, d40, d42, d44, d46,
225        d48, d50, d52, d54, d56, d58, d60, d62,
226
227        q0, q4, q8, q12,
228        q16, q20, q24, q28,
229        q32, q36, q40, q44,
230        q48, q52, q56, q60
231    );
232    // @formatter:on
233
234    /**
235     * Stack bias for stack and frame pointer loads.
236     */
237    public static final int STACK_BIAS = 0x7ff;
238
239    /**
240     * Size to keep free for flushing the register-window to stack.
241     */
242    public static final int REGISTER_SAFE_AREA_SIZE = 128;
243
244    public final Set<CPUFeature> features;
245
246    public SPARC(Set<CPUFeature> features) {
247        super("SPARC", SPARCKind.XWORD, BIG_ENDIAN, false, allRegisters, LOAD_LOAD | LOAD_STORE | STORE_STORE, 1, 8);
248        this.features = features;
249    }
250
251    @Override
252    public RegisterArray getAvailableValueRegisters() {
253        return allRegisters;
254    }
255
256    @Override
257    public boolean canStoreValue(RegisterCategory category, PlatformKind kind) {
258        SPARCKind sparcKind = (SPARCKind) kind;
259        switch (sparcKind) {
260            case BYTE:
261            case HWORD:
262            case WORD:
263            case XWORD:
264                return CPU.equals(category);
265            case SINGLE:
266            case V32_BYTE:
267            case V32_HWORD:
268                return FPUs.equals(category);
269            case DOUBLE:
270            case V64_BYTE:
271            case V64_HWORD:
272            case V64_WORD:
273            case V64_SINGLE:
274                return FPUd.equals(category);
275            case QUAD:
276                return FPUq.equals(category);
277            default:
278                return false;
279        }
280    }
281
282    @Override
283    public PlatformKind getLargestStorableKind(RegisterCategory category) {
284        if (category.equals(CPU)) {
285            return SPARCKind.XWORD;
286        } else if (category.equals(FPUd)) {
287            return SPARCKind.DOUBLE;
288        } else if (category.equals(FPUs)) {
289            return SPARCKind.SINGLE;
290        } else if (category.equals(FPUq)) {
291            return SPARCKind.QUAD;
292        } else {
293            throw new IllegalArgumentException("Unknown register category: " + category);
294        }
295    }
296
297    @Override
298    public PlatformKind getPlatformKind(JavaKind javaKind) {
299        switch (javaKind) {
300            case Boolean:
301            case Byte:
302                return SPARCKind.BYTE;
303            case Short:
304            case Char:
305                return SPARCKind.HWORD;
306            case Int:
307                return SPARCKind.WORD;
308            case Long:
309            case Object:
310                return SPARCKind.XWORD;
311            case Float:
312                return SPARCKind.SINGLE;
313            case Double:
314                return SPARCKind.DOUBLE;
315            default:
316                throw new IllegalArgumentException("Unknown JavaKind: " + javaKind);
317        }
318    }
319
320    private static int getDoubleEncoding(int reg) {
321        assert reg < 64 && ((reg & 1) == 0);
322        return (reg & 0x1e) | ((reg & 0x20) >> 5);
323    }
324
325    private static int getQuadncoding(int reg) {
326        assert reg < 64 && ((reg & 1) == 0);
327        return (reg & 0x1c) | ((reg & 0x20) >> 5);
328    }
329
330    public Set<CPUFeature> getFeatures() {
331        return features;
332    }
333
334    public boolean hasFeature(CPUFeature feature) {
335        return features.contains(feature);
336    }
337
338    public enum CPUFeature {
339        // ISA determined properties:
340        ADI,
341        AES,
342        BLK_INIT,
343        CAMELLIA,
344        CBCOND,
345        CRC32C,
346        DES,
347        FMAF,
348        HPC,
349        IMA,
350        KASUMI,
351        MD5,
352        MONT,
353        MPMUL,
354        MWAIT,
355        PAUSE,
356        PAUSE_NSEC,
357        POPC,
358        SHA1,
359        SHA256,
360        SHA512,
361        SPARC5,
362        V9,
363        VAMASK,
364        VIS1,
365        VIS2,
366        VIS3,
367        VIS3B,
368        XMONT,
369        XMPMUL,
370        // Synthesised CPU properties:
371        BLK_ZEROING,
372        FAST_BIS,
373        FAST_CMOVE,
374        FAST_IDIV,
375        FAST_IND_BR,
376        FAST_LD,
377        FAST_RDPC
378    }
379}
380