1 /*
2  * Copyright (c) 2009, 2019, 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 
24 
25 package org.graalvm.compiler.asm.sparc;
26 
27 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.CC.Icc;
28 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag.Always;
29 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Add;
30 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Addc;
31 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Addcc;
32 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.And;
33 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Andcc;
34 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Andn;
35 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Andncc;
36 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Casa;
37 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Casxa;
38 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Flushw;
39 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Fpop1;
40 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Fpop2;
41 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Impdep1;
42 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Jmpl;
43 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Lddf;
44 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Ldf;
45 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Ldsb;
46 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Ldsh;
47 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Ldsw;
48 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Ldub;
49 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Lduh;
50 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Lduw;
51 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Lduwa;
52 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Ldx;
53 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Ldxa;
54 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Membar;
55 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Movcc;
56 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Mulx;
57 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Or;
58 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Popc;
59 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Prefetch;
60 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Rd;
61 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Restore;
62 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Save;
63 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Sdivx;
64 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Sll;
65 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Sllx;
66 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Sra;
67 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Srax;
68 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Srl;
69 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Srlx;
70 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Stb;
71 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Stdf;
72 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Stf;
73 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Sth;
74 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Stw;
75 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Stx;
76 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Stxa;
77 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Sub;
78 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Subcc;
79 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Udivx;
80 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Wr;
81 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Xnor;
82 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Xor;
83 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Xorcc;
84 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fabsd;
85 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fabss;
86 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Faddd;
87 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fadds;
88 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fdivd;
89 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fdivs;
90 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fdtoi;
91 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fdtos;
92 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fdtox;
93 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fitod;
94 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fitos;
95 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fmovd;
96 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fmovs;
97 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fmuld;
98 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fmuls;
99 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fnegd;
100 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fnegs;
101 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fpadd32;
102 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fsmuld;
103 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fsqrtd;
104 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fsqrts;
105 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fsrc2d;
106 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fsrc2s;
107 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fstod;
108 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fstoi;
109 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fstox;
110 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fsubd;
111 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fsubs;
112 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fxtod;
113 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fxtos;
114 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fzerod;
115 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fzeros;
116 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Movdtox;
117 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Movstosw;
118 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Movwtos;
119 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Movxtod;
120 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.UMulxhi;
121 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Ops.ArithOp;
122 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Ops.LdstOp;
123 import static java.lang.String.format;
124 import static jdk.vm.ci.sparc.SPARC.CPU;
125 import static jdk.vm.ci.sparc.SPARC.FPUd;
126 import static jdk.vm.ci.sparc.SPARC.FPUs;
127 import static jdk.vm.ci.sparc.SPARC.g0;
128 import static jdk.vm.ci.sparc.SPARC.g2;
129 import static jdk.vm.ci.sparc.SPARC.g5;
130 import static jdk.vm.ci.sparc.SPARC.g7;
131 import static jdk.vm.ci.sparc.SPARC.o7;
132 
133 import java.util.ArrayList;
134 import java.util.HashMap;
135 import java.util.List;
136 import java.util.Map;
137 
138 import org.graalvm.compiler.asm.Assembler;
139 import org.graalvm.compiler.asm.BranchTargetOutOfBoundsException;
140 import org.graalvm.compiler.asm.Label;
141 import org.graalvm.compiler.core.common.NumUtil;
142 import org.graalvm.compiler.debug.GraalError;
143 
144 import jdk.vm.ci.code.Register;
145 import jdk.vm.ci.code.TargetDescription;
146 import jdk.vm.ci.meta.JavaConstant;
147 import jdk.vm.ci.meta.PlatformKind;
148 import jdk.vm.ci.sparc.SPARC;
149 import jdk.vm.ci.sparc.SPARC.CPUFeature;
150 import jdk.vm.ci.sparc.SPARCKind;
151 
152 /**
153  * This class implements an assembler that can encode most SPARC instructions.
154  */
155 public abstract class SPARCAssembler extends Assembler {
156 
157     /**
158      * Constructs an assembler for the SPARC architecture.
159      */
SPARCAssembler(TargetDescription target)160     public SPARCAssembler(TargetDescription target) {
161         super(target);
162     }
163 
164     /**
165      * Size of an SPARC assembler instruction in Bytes.
166      */
167     public static final int INSTRUCTION_SIZE = 4;
168 
169     /**
170      * Size in bytes which are cleared by stxa %g0, [%rd] ASI_ST_BLKINIT_PRIMARY.
171      */
172     public static final int BLOCK_ZERO_LENGTH = 64;
173 
174     public static final int CCR_ICC_SHIFT = 0;
175     public static final int CCR_XCC_SHIFT = 4;
176     public static final int CCR_V_SHIFT = 1;
177 
178     public static final int MEMBAR_LOAD_LOAD = 1;
179     public static final int MEMBAR_STORE_LOAD = 2;
180     public static final int MEMBAR_LOAD_STORE = 3;
181     public static final int MEMBAR_STORE_STORE = 4;
182 
183     private static final Ops[] OPS;
184     private static final Op2s[] OP2S;
185     private static final Op3s[][] OP3S;
186 
187     private ArrayList<Integer> delaySlotOptimizationPoints = new ArrayList<>(5);
188 
189     static {
190         Ops[] ops = Ops.values();
191         OPS = new Ops[ops.length];
192         for (Ops op : ops) {
193             OPS[op.value] = op;
194         }
195         Op2s[] op2s = Op2s.values();
196         OP2S = new Op2s[op2s.length];
197         for (Op2s op2 : op2s) {
198             OP2S[op2.value] = op2;
199         }
200         OP3S = new Op3s[2][64];
201         for (Op3s op3 : Op3s.values()) {
202             if (op3.value >= 1 << 6) {
203                 throw new RuntimeException("Error " + op3 + " " + op3.value);
204             }
205             OP3S[op3.op.value & 1][op3.value] = op3;
206         }
207     }
208 
209     public enum Ops {
210         // @formatter:off
211         BranchOp(0b00),
212         CallOp(0b01),
213         ArithOp(0b10),
214         LdstOp(0b11);
215         // @formatter:on
216 
217         private final int value;
218 
Ops(int value)219         Ops(int value) {
220             this.value = value;
221         }
222 
getValue()223         public int getValue() {
224             return value;
225         }
226 
appliesTo(int instructionWord)227         public boolean appliesTo(int instructionWord) {
228             int opShift = 30;
229             return (instructionWord >>> opShift) == value;
230         }
231     }
232 
233     public enum Op2s {
234         // Checkstyle: stop
235         // @formatter:off
236         Illtrap(0b000),
237         Bpr    (0b011),
238         Fb     (0b110),
239         Fbp    (0b101),
240         Br     (0b010),
241         Bp     (0b001),
242         Cb     (0b111),
243         Sethi  (0b100);
244         // @formatter:on
245         // Checkstyle: resume
246 
247         private final int value;
248 
Op2s(int value)249         Op2s(int value) {
250             this.value = value;
251         }
252 
getValue()253         public int getValue() {
254             return value;
255         }
256 
byValue(int value)257         public static Op2s byValue(int value) {
258             return OP2S[value];
259         }
260     }
261 
262     private static final int COMMUTATIVE = 1;
263     private static final int BINARY = 2;
264     private static final int UNARY = 4;
265     private static final int VOID_IN = 8;
266 
267     public enum Op3s {
268         // Checkstyle: stop
269         // @formatter:off
270         Add(0x00, "add", ArithOp, BINARY | COMMUTATIVE),
271         And(0x01, "and", ArithOp, BINARY | COMMUTATIVE),
272         Or(0x02, "or", ArithOp, BINARY | COMMUTATIVE),
273         Xor(0x03, "xor", ArithOp, BINARY | COMMUTATIVE),
274         Sub(0x04, "sub", ArithOp, BINARY),
275         Andn(0x05, "andn", ArithOp, BINARY | COMMUTATIVE),
276         Orn(0x06, "orn", ArithOp, BINARY | COMMUTATIVE),
277         Xnor(0x07, "xnor", ArithOp, BINARY | COMMUTATIVE),
278         Addc(0x08, "addc", ArithOp, BINARY | COMMUTATIVE),
279         Mulx(0x09, "mulx", ArithOp, BINARY | COMMUTATIVE),
280         Umul(0x0A, "umul", ArithOp, BINARY | COMMUTATIVE),
281         Smul(0x0B, "smul", ArithOp, BINARY | COMMUTATIVE),
282         Subc(0x0C, "subc", ArithOp, BINARY),
283         Udivx(0x0D, "udivx", ArithOp, BINARY),
284         Udiv(0x0E, "udiv", ArithOp, BINARY),
285         Sdiv(0x0F, "sdiv", ArithOp, BINARY),
286 
287         Addcc(0x10, "addcc", ArithOp, BINARY | COMMUTATIVE),
288         Andcc(0x11, "andcc", ArithOp, BINARY | COMMUTATIVE),
289         Orcc(0x12, "orcc", ArithOp, BINARY | COMMUTATIVE),
290         Xorcc(0x13, "xorcc", ArithOp, BINARY | COMMUTATIVE),
291         Subcc(0x14, "subcc", ArithOp, BINARY),
292         Andncc(0x15, "andncc", ArithOp, BINARY | COMMUTATIVE),
293         Orncc(0x16, "orncc", ArithOp, BINARY | COMMUTATIVE),
294         Xnorcc(0x17, "xnorcc", ArithOp, BINARY | COMMUTATIVE),
295         Addccc(0x18, "addccc", ArithOp, BINARY | COMMUTATIVE),
296 
297         Umulcc(0x1A, "umulcc", ArithOp, BINARY | COMMUTATIVE),
298         Smulcc(0x1B, "smulcc", ArithOp, BINARY | COMMUTATIVE),
299         Subccc(0x1C, "subccc", ArithOp, BINARY),
300         Udivcc(0x1E, "udivcc", ArithOp, BINARY),
301         Sdivcc(0x1F, "sdivcc", ArithOp, BINARY),
302 
303         Mulscc(0x24, "mulscc", ArithOp, BINARY | COMMUTATIVE),
304         Sll(0x25, "sll", ArithOp, BINARY),
305         Sllx(0x25, "sllx", ArithOp, BINARY),
306         Srl(0x26, "srl", ArithOp, BINARY),
307         Srlx(0x26, "srlx", ArithOp, BINARY),
308         Sra(0x27, "srax", ArithOp, BINARY),
309         Srax(0x27, "srax", ArithOp, BINARY),
310         Membar(0x28, "membar", ArithOp),
311 
312         Flushw(0x2B, "flushw", ArithOp),
313         Movcc(0x2C, "movcc", ArithOp),
314         Sdivx(0x2D, "sdivx", ArithOp, BINARY),
315         Popc(0x2E, "popc", ArithOp, UNARY),
316         Movr(0x2F, "movr", ArithOp, BINARY),
317 
318         Fpop1(0b11_0100, "fpop1", ArithOp),
319         Fpop2(0b11_0101, "fpop2", ArithOp),
320         Impdep1(0b11_0110, "impdep1", ArithOp),
321         Impdep2(0b11_0111, "impdep2", ArithOp),
322         Jmpl(0x38, "jmpl", ArithOp),
323         Rett(0x39, "rett", ArithOp),
324         Trap(0x3a, "trap", ArithOp),
325         Flush(0x3b, "flush", ArithOp),
326         Save(0x3c, "save", ArithOp),
327         Restore(0x3d, "restore", ArithOp),
328         Retry(0x3e, "retry", ArithOp),
329 
330 
331         Casa(0b111100, "casa", LdstOp),
332         Casxa(0b111110, "casxa", LdstOp),
333         Prefetch(0b101101, "prefetch", LdstOp),
334         Prefetcha(0b111101, "prefetcha", LdstOp),
335 
336         Lduw  (0b00_0000, "lduw", LdstOp),
337         Ldub  (0b00_0001, "ldub", LdstOp),
338         Lduh  (0b00_0010, "lduh", LdstOp),
339         Stw   (0b00_0100, "stw", LdstOp),
340         Stb   (0b00_0101, "stb", LdstOp),
341         Sth   (0b00_0110, "sth", LdstOp),
342         Ldsw  (0b00_1000, "ldsw", LdstOp),
343         Ldsb  (0b00_1001, "ldsb", LdstOp),
344         Ldsh  (0b00_1010, "ldsh", LdstOp),
345         Ldx   (0b00_1011, "ldx", LdstOp),
346         Stx   (0b00_1110, "stx", LdstOp),
347 
348         Ldf   (0b10_0000, "ldf", LdstOp),
349         Ldfsr (0b10_0001, "ldfsr", LdstOp),
350         Ldaf  (0b10_0010, "ldaf", LdstOp),
351         Lddf  (0b10_0011, "lddf", LdstOp),
352         Stf   (0b10_0100, "stf", LdstOp),
353         Stfsr (0b10_0101, "stfsr", LdstOp),
354         Staf  (0b10_0110, "staf", LdstOp),
355         Stdf  (0b10_0111, "stdf", LdstOp),
356 
357         Stba  (0b01_0101, "stba", LdstOp),
358         Stha  (0b01_0110, "stha", LdstOp),
359         Stwa  (0b01_0100, "stwa", LdstOp),
360         Stxa  (0b01_1110, "stxa", LdstOp),
361 
362         Ldsba  (0b01_1001, "ldsba", LdstOp),
363         Ldsha  (0b01_1010, "ldsha", LdstOp),
364         Ldswa  (0b01_1000, "ldswa", LdstOp),
365         Lduba  (0b01_0001, "lduba", LdstOp),
366         Lduha  (0b01_0010, "lduha", LdstOp),
367         Lduwa (0b01_0000, "lduwa", LdstOp),
368 
369         Ldxa  (0b01_1011, "ldxa", LdstOp),
370 
371         Rd    (0b10_1000, "rd", ArithOp),
372         Wr    (0b11_0000, "wr", ArithOp),
373 
374         Tcc(0b11_1010, "tcc", ArithOp);
375 
376         // @formatter:on
377         // Checkstyle: resume
378 
379         private final int value;
380         private final String operator;
381         private final Ops op;
382         private final int flags;
383 
Op3s(int value, String name, Ops op)384         Op3s(int value, String name, Ops op) {
385             this(value, name, op, 0);
386         }
387 
Op3s(int value, String name, Ops op, int flags)388         Op3s(int value, String name, Ops op, int flags) {
389             this.value = value;
390             this.operator = name;
391             this.op = op;
392             this.flags = flags;
393         }
394 
getValue()395         public int getValue() {
396             return value;
397         }
398 
getOperator()399         public String getOperator() {
400             return operator;
401         }
402 
throwsException()403         public boolean throwsException() {
404             if (op == LdstOp) {
405                 return true;
406             }
407             switch (this) {
408                 case Udiv:
409                 case Udivx:
410                 case Sdiv:
411                 case Sdivx:
412                 case Udivcc:
413                 case Sdivcc:
414                     return true;
415                 default:
416                     return false;
417             }
418         }
419 
isBinary()420         public boolean isBinary() {
421             return (flags & BINARY) != 0;
422         }
423 
isUnary()424         public boolean isUnary() {
425             return (flags & UNARY) != 0;
426         }
427 
isCommutative()428         public boolean isCommutative() {
429             return (flags & COMMUTATIVE) != 0;
430         }
431     }
432 
433     public enum Opfs {
434         // @formatter:off
435 
436         Fmovs(0b0_0000_0001, "fmovs", Fpop1, UNARY),
437         Fmovd(0b0_0000_0010, "fmovd", Fpop1, UNARY),
438         Fmovq(0b0_0000_0011, "fmovq", Fpop1, UNARY),
439         Fnegs(0x05, "fnegs", Fpop1, UNARY),
440         Fnegd(0x06, "fnegd", Fpop1, UNARY),
441         Fnegq(0x07, "fnegq", Fpop1, UNARY),
442         Fabss(0x09, "fabss", Fpop1, UNARY),
443         Fabsd(0x0A, "fabsd", Fpop1, UNARY),
444         Fabsq(0x0B, "fabsq", Fpop1, UNARY),
445 
446         // start VIS1
447         Fpadd32(0x52, "fpadd32", Impdep1, BINARY | COMMUTATIVE),
448         Fzerod(0x60, "fzerod", Impdep1, VOID_IN),
449         Fzeros(0x61, "fzeros", Impdep1, VOID_IN),
450         Fsrc2d(0x78, "fsrc2d", Impdep1, UNARY),
451         Fsrc2s(0x79, "fsrc2s", Impdep1, UNARY),
452         // end VIS1
453 
454         // start VIS3
455         Movdtox(0x110, "movdtox", Impdep1, UNARY),
456         Movstouw(0x111, "movstouw", Impdep1, UNARY),
457         Movstosw(0x113, "movstosw", Impdep1, UNARY),
458         Movxtod(0x118, "movxtod", Impdep1, UNARY),
459         Movwtos(0b1_0001_1001, "movwtos", Impdep1, UNARY),
460         UMulxhi(0b0_0001_0110, "umulxhi", Impdep1, BINARY | COMMUTATIVE),
461         // end VIS3
462 
463         Fadds(0x41, "fadds", Fpop1, BINARY | COMMUTATIVE),
464         Faddd(0x42, "faddd", Fpop1, BINARY | COMMUTATIVE),
465         Fsubs(0x45, "fsubs", Fpop1, BINARY),
466         Fsubd(0x46, "fsubd", Fpop1, BINARY),
467         Fmuls(0x49, "fmuls", Fpop1, BINARY | COMMUTATIVE),
468         Fmuld(0x4A, "fmuld", Fpop1, BINARY | COMMUTATIVE),
469         Fdivs(0x4D, "fdivs", Fpop1, BINARY),
470         Fdivd(0x4E, "fdivd", Fpop1, BINARY),
471 
472         Fsqrts(0x29, "fsqrts", Fpop1, UNARY),
473         Fsqrtd(0x2A, "fsqrtd", Fpop1, UNARY),
474 
475         Fsmuld(0x69, "fsmuld", Fpop1, BINARY | COMMUTATIVE),
476 
477         Fstoi(0xD1, "fstoi", Fpop1, UNARY),
478         Fdtoi(0xD2, "fdtoi", Fpop1, UNARY),
479         Fstox(0x81, "fstox", Fpop1, UNARY),
480         Fdtox(0x82, "fdtox", Fpop1, UNARY),
481         Fxtos(0x84, "fxtos", Fpop1, UNARY),
482         Fxtod(0x88, "fxtod", Fpop1, UNARY),
483         Fitos(0xC4, "fitos", Fpop1, UNARY),
484         Fdtos(0xC6, "fdtos", Fpop1, UNARY),
485         Fitod(0xC8, "fitod", Fpop1, UNARY),
486         Fstod(0xC9, "fstod", Fpop1, UNARY),
487 
488 
489         Fcmps(0x51, "fcmps", Fpop2, BINARY),
490         Fcmpd(0x52, "fcmpd", Fpop2, BINARY);
491 
492         // @formatter:on
493 
494         private final int value;
495         private final String operator;
496         private final Op3s op3;
497         private final int flags;
498 
Opfs(int value, String op, Op3s op3, int flags)499         Opfs(int value, String op, Op3s op3, int flags) {
500             this.value = value;
501             this.operator = op;
502             this.op3 = op3;
503             this.flags = flags;
504         }
505 
getValue()506         public int getValue() {
507             return value;
508         }
509 
getOperator()510         public String getOperator() {
511             return operator;
512         }
513 
isBinary()514         public boolean isBinary() {
515             return (flags & BINARY) != 0;
516         }
517 
isUnary()518         public boolean isUnary() {
519             return (flags & UNARY) != 0;
520         }
521 
isCommutative()522         public boolean isCommutative() {
523             return (flags & COMMUTATIVE) != 0;
524         }
525     }
526 
527     public enum OpfLow {
528         Fmovscc(0b00_0001, "fmovscc", Fpop2),
529         Fmovdcc(0b00_0010, "fmovdcc", Fpop2);
530 
531         private final int value;
532         private final String operator;
533         private final Op3s op3;
534 
OpfLow(int value, String op, Op3s op3)535         OpfLow(int value, String op, Op3s op3) {
536             this.value = value;
537             this.operator = op;
538             this.op3 = op3;
539         }
540 
541         @Override
toString()542         public String toString() {
543             return operator;
544         }
545     }
546 
547     public enum Annul {
548         ANNUL(1),
549         NOT_ANNUL(0);
550         public final int flag;
551 
Annul(int flag)552         Annul(int flag) {
553             this.flag = flag;
554         }
555     }
556 
557     public enum BranchPredict {
558         PREDICT_TAKEN(1),
559         PREDICT_NOT_TAKEN(0);
560         public final int flag;
561 
BranchPredict(int flag)562         BranchPredict(int flag) {
563             this.flag = flag;
564         }
565     }
566 
567     public enum MembarMask {
568         // @formatter:off
569 
570         StoreStore(1 << 3, "storestore"),
571         LoadStore(1 << 2, "loadstore"),
572         StoreLoad(1 << 1, "storeload"),
573         LoadLoad(1 << 0, "loadload"),
574         Sync(1 << 6, "sync"),
575         MemIssue(1 << 5, "memissue"),
576         LookAside(1 << 4, "lookaside");
577 
578         // @formatter:on
579 
580         private final int value;
581         private final String operator;
582 
MembarMask(int value, String op)583         MembarMask(int value, String op) {
584             this.value = value;
585             this.operator = op;
586         }
587 
getValue()588         public int getValue() {
589             return value | 0x2000;
590         }
591 
getOperator()592         public String getOperator() {
593             return operator;
594         }
595     }
596 
597     /**
598      * Condition Codes to use for instruction.
599      */
600     public enum CC {
601         // @formatter:off
602         /**
603          * Condition is considered as 32bit operation condition.
604          */
605         Icc(0b00, "icc", false),
606         /**
607          * Condition is considered as 64bit operation condition.
608          */
609         Xcc(0b10, "xcc", false),
610         Fcc0(0b00, "fcc0", true),
611         Fcc1(0b01, "fcc1", true),
612         Fcc2(0b10, "fcc2", true),
613         Fcc3(0b11, "fcc3", true);
614 
615         // @formatter:on
616 
617         private final int value;
618         private final String operator;
619         private boolean isFloat;
620 
CC(int value, String op, boolean isFloat)621         CC(int value, String op, boolean isFloat) {
622             this.value = value;
623             this.operator = op;
624             this.isFloat = isFloat;
625         }
626 
getValue()627         public int getValue() {
628             return value;
629         }
630 
getOpfCCValue()631         public int getOpfCCValue() {
632             /*
633              * In the opf_cc encoding for FMOVcc, the third bit is set to indicate icc/xcc.
634              */
635             return (isFloat ? value : (value | 0x4));
636         }
637 
getOperator()638         public String getOperator() {
639             return operator;
640         }
641 
forKind(PlatformKind kind)642         public static CC forKind(PlatformKind kind) {
643             if (kind.equals(SPARCKind.XWORD)) {
644                 return Xcc;
645             } else if (kind.equals(SPARCKind.WORD)) {
646                 return Icc;
647             } else if (kind.equals(SPARCKind.SINGLE) || kind.equals(SPARCKind.DOUBLE)) {
648                 return Fcc0;
649             } else {
650                 throw new IllegalArgumentException("Unknown kind: " + kind);
651             }
652         }
653     }
654 
655     public enum ConditionFlag {
656         // @formatter:off
657 
658         // for FBfcc & FBPfcc instruction
659         F_Never(0, "f_never"),
660         F_NotEqual(1, "f_notEqual"),
661         F_LessOrGreater(2, "f_lessOrGreater"),
662         F_UnorderedOrLess(3, "f_unorderedOrLess"),
663         F_Less(4, "f_less"),
664         F_UnorderedOrGreater(5, "f_unorderedOrGreater"),
665         F_Greater(6, "f_greater"),
666         F_Unordered(7, "f_unordered"),
667         F_Always(8, "f_always"),
668         F_Equal(9, "f_equal"),
669         F_UnorderedOrEqual(10, "f_unorderedOrEqual"),
670         F_GreaterOrEqual(11, "f_greaterOrEqual"),
671         F_UnorderedGreaterOrEqual(12, "f_unorderedGreaterOrEqual"),
672         F_LessOrEqual(13, "f_lessOrEqual"),
673         F_UnorderedOrLessOrEqual(14, "f_unorderedOrLessOrEqual"),
674         F_Ordered(15, "f_ordered"),
675 
676         // for integers
677         Never(0, "never"),
678         Equal(1, "equal", true),
679         Zero(1, "zero"),
680         LessEqual(2, "lessEqual", true),
681         Less(3, "less", true),
682         LessEqualUnsigned(4, "lessEqualUnsigned", true),
683         LessUnsigned(5, "lessUnsigned", true),
684         CarrySet(5, "carrySet"),
685         Negative(6, "negative", true),
686         OverflowSet(7, "overflowSet", true),
687         Always(8, "always"),
688         NotEqual(9, "notEqual", true),
689         NotZero(9, "notZero"),
690         Greater(10, "greater", true),
691         GreaterEqual(11, "greaterEqual", true),
692         GreaterUnsigned(12, "greaterUnsigned", true),
693         GreaterEqualUnsigned(13, "greaterEqualUnsigned", true),
694         CarryClear(13, "carryClear"),
695         Positive(14, "positive", true),
696         OverflowClear(15, "overflowClear", true);
697 
698         // @formatter:on
699 
700         private final int value;
701         private final String operator;
702         private boolean forCBcond = false;
703 
ConditionFlag(int value, String op)704         ConditionFlag(int value, String op) {
705             this(value, op, false);
706         }
707 
ConditionFlag(int value, String op, boolean cbcond)708         ConditionFlag(int value, String op, boolean cbcond) {
709             this.value = value;
710             this.operator = op;
711             this.forCBcond = cbcond;
712         }
713 
isCBCond()714         public boolean isCBCond() {
715             return forCBcond;
716         }
717 
getValue()718         public int getValue() {
719             return value;
720         }
721 
getOperator()722         public String getOperator() {
723             return operator;
724         }
725 
negate()726         public ConditionFlag negate() {
727             //@formatter:off
728             switch (this) {
729                 case F_Never                  : return F_Always;
730                 case F_Always                 : return F_Never;
731                 case F_NotEqual               : return F_Equal;
732                 case F_Equal                  : return F_NotEqual;
733                 case F_LessOrGreater          : return F_UnorderedOrEqual;
734                 case F_UnorderedOrEqual       : return F_LessOrGreater;
735                 case F_Less                   : return F_UnorderedGreaterOrEqual;
736                 case F_UnorderedGreaterOrEqual: return F_Less;
737                 case F_LessOrEqual            : return F_UnorderedOrGreater;
738                 case F_UnorderedOrGreater     : return F_LessOrEqual;
739                 case F_Greater                : return F_UnorderedOrLessOrEqual;
740                 case F_UnorderedOrLessOrEqual : return F_Greater;
741                 case F_GreaterOrEqual         : return F_UnorderedOrLess;
742                 case F_UnorderedOrLess        : return F_GreaterOrEqual;
743                 case F_Unordered              : return F_Ordered;
744                 case F_Ordered                : return F_Unordered;
745                 case Never                    : return Always;
746                 case Always                   : return Never;
747                 case Equal                    : return NotEqual;
748                 case NotEqual                 : return Equal;
749                 case Zero                     : return NotZero;
750                 case NotZero                  : return Zero;
751                 case LessEqual                : return Greater;
752                 case Greater                  : return LessEqual;
753                 case Less                     : return GreaterEqual;
754                 case GreaterEqual             : return Less;
755                 case LessEqualUnsigned        : return GreaterUnsigned;
756                 case GreaterUnsigned          : return LessEqualUnsigned;
757                 case LessUnsigned             : return GreaterEqualUnsigned;
758                 case GreaterEqualUnsigned     : return LessUnsigned;
759                 case CarrySet                 : return CarryClear;
760                 case CarryClear               : return CarrySet;
761                 case Negative                 : return Positive;
762                 case Positive                 : return Negative;
763                 case OverflowSet              : return OverflowClear;
764                 case OverflowClear            : return OverflowSet;
765                 default:
766                     throw new InternalError();
767             }
768             //@formatter:on
769         }
770 
mirror()771         public ConditionFlag mirror() {
772             switch (this) {
773             //@formatter:off
774                 case F_Less                   : return F_Greater;
775                 case F_Greater                : return F_Less;
776                 case F_LessOrEqual            : return F_GreaterOrEqual;
777                 case F_UnorderedGreaterOrEqual: return F_UnorderedOrLessOrEqual;
778                 case F_UnorderedOrGreater     : return F_UnorderedOrLess;
779                 case F_UnorderedOrLessOrEqual : return F_UnorderedGreaterOrEqual;
780                 case F_GreaterOrEqual         : return F_LessOrEqual;
781                 case F_UnorderedOrLess        : return F_UnorderedOrGreater;
782                 case LessEqual                : return GreaterEqual;
783                 case Greater                  : return Less;
784                 case Less                     : return Greater;
785                 case GreaterEqual             : return LessEqual;
786                 case LessEqualUnsigned        : return GreaterEqualUnsigned;
787                 case GreaterUnsigned          : return LessUnsigned;
788                 case LessUnsigned             : return GreaterUnsigned;
789                 case GreaterEqualUnsigned     : return LessEqualUnsigned;
790                 default:
791                     return this;
792                 //@formatter:on
793             }
794         }
795 
796     }
797 
798     public enum RCondition {
799         // @formatter:off
800 
801         Rc_z(0b001, "rc_z"),
802         Rc_lez(0b010, "rc_lez"),
803         Rc_lz(0b011, "rc_lz"),
804         Rc_nz(0b101, "rc_nz"),
805         Rc_gz(0b110, "rc_gz"),
806         Rc_gez(0b111, "rc_gez"),
807         Rc_last(Rc_gez.getValue(), "rc_last");
808 
809         // @formatter:on
810 
811         private final int value;
812         private final String operator;
813 
RCondition(int value, String op)814         RCondition(int value, String op) {
815             this.value = value;
816             this.operator = op;
817         }
818 
getValue()819         public int getValue() {
820             return value;
821         }
822 
getOperator()823         public String getOperator() {
824             return operator;
825         }
826     }
827 
828     /**
829      * Represents the <b>Address Space Identifier</b> defined in the SPARC architecture.
830      */
831     public enum Asi {
832         // @formatter:off
833 
834         INVALID(-1),
835         ASI_PRIMARY(0x80),
836         ASI_PRIMARY_NOFAULT(0x82),
837         ASI_PRIMARY_LITTLE(0x88),
838         // Block initializing store
839         ASI_ST_BLKINIT_PRIMARY(0xE2),
840         // Most-Recently-Used (MRU) BIS variant
841         ASI_ST_BLKINIT_MRU_PRIMARY(0xF2);
842 
843         // @formatter:on
844 
845         private final int value;
846 
Asi(int value)847         Asi(int value) {
848             this.value = value;
849         }
850 
getValue()851         public int getValue() {
852             return value;
853         }
854 
isValid()855         public boolean isValid() {
856             return value != INVALID.getValue();
857         }
858     }
859 
860     public enum Fcn {
861         SeveralWritesAndPossiblyReads(2),
862         SeveralReadsWeak(0),
863         OneRead(1),
864         OneWrite(3),
865         Page(4),
866         NearestUnifiedCache(17),
867         SeveralReadsStrong(20),
868         OneReadStrong(21),
869         SeveralWritesAndPossiblyReadsStrong(22),
870         OneWriteStrong(23);
871 
872         private final int value;
873 
Fcn(int value)874         Fcn(int value) {
875             this.value = value;
876         }
877 
getValue()878         public int getValue() {
879             return value;
880         }
881     }
882 
883     /**
884      * Specifies various bit fields used in SPARC instructions.
885      */
886     @SuppressWarnings("unused")
887     public abstract static class BitSpec {
888         private static final BitSpec op = new ContinousBitSpec(31, 30, "op");
889         private static final BitSpec op2 = new ContinousBitSpec(24, 22, "op2");
890         private static final BitSpec op3 = new ContinousBitSpec(24, 19, "op3");
891         private static final BitSpec opf = new ContinousBitSpec(13, 5, "opf");
892         private static final BitSpec opfLow = new ContinousBitSpec(10, 5, "opfLow");
893         private static final BitSpec opfCC = new ContinousBitSpec(13, 11, "opfCC");
894         private static final BitSpec opfCond = new ContinousBitSpec(17, 14, "opfCond");
895         private static final BitSpec rd = new ContinousBitSpec(29, 25, "rd");
896         private static final BitSpec rs1 = new ContinousBitSpec(18, 14, "rs1");
897         private static final BitSpec rs2 = new ContinousBitSpec(4, 0, "rs2");
898         private static final BitSpec simm13 = new ContinousBitSpec(12, 0, true, "simm13");
899         private static final BitSpec shcnt32 = new ContinousBitSpec(4, 0, "shcnt32");
900         private static final BitSpec shcnt64 = new ContinousBitSpec(5, 0, "shcnt64");
901         private static final BitSpec imm22 = new ContinousBitSpec(21, 0, "imm22");
902         private static final BitSpec immAsi = new ContinousBitSpec(12, 5, "immASI");
903         private static final BitSpec i = new ContinousBitSpec(13, 13, "i");
904         private static final BitSpec disp19 = new ContinousBitSpec(18, 0, true, "disp19");
905         private static final BitSpec disp22 = new ContinousBitSpec(21, 0, true, "disp22");
906         private static final BitSpec disp30 = new ContinousBitSpec(29, 0, true, "disp30");
907         private static final BitSpec a = new ContinousBitSpec(29, 29, "a");
908         private static final BitSpec p = new ContinousBitSpec(19, 19, "p");
909         private static final BitSpec x = new ContinousBitSpec(12, 12, "x");
910         private static final BitSpec cond = new ContinousBitSpec(28, 25, "cond");
911         private static final BitSpec rcond = new ContinousBitSpec(27, 25, "rcond");
912         private static final BitSpec cc = new ContinousBitSpec(21, 20, "cc");
913         private static final BitSpec fcc = new ContinousBitSpec(26, 25, "cc");
914         private static final BitSpec d16lo = new ContinousBitSpec(13, 0, "d16lo");
915         private static final BitSpec d16hi = new ContinousBitSpec(21, 20, true, "d16hi");
916         private static final BitSpec d16 = new CompositeBitSpec(d16hi, d16lo);
917         // Movcc
918         private static final BitSpec movccLo = new ContinousBitSpec(12, 11, "cc_lo");
919         private static final BitSpec movccHi = new ContinousBitSpec(18, 18, "cc_hi");
920         private static final BitSpec movccCond = new ContinousBitSpec(17, 14, "cond");
921         private static final BitSpec simm11 = new ContinousBitSpec(10, 0, true, "simm11");
922 
923         // CBCond
924         private static final BitSpec cLo = new ContinousBitSpec(27, 25, "cLo");
925         private static final BitSpec cHi = new ContinousBitSpec(29, 29, "cHi");
926         private static final BitSpec c = new CompositeBitSpec(cHi, cLo);
927         private static final BitSpec cbcond = new ContinousBitSpec(28, 28, "cbcond");
928         private static final BitSpec cc2 = new ContinousBitSpec(21, 21, "cc2");
929         private static final BitSpec d10Lo = new ContinousBitSpec(12, 5, "d10Lo");
930         private static final BitSpec d10Hi = new ContinousBitSpec(20, 19, true, "d10Hi");
931         private static final BitSpec d10 = new CompositeBitSpec(d10Hi, d10Lo);
932         private static final BitSpec simm5 = new ContinousBitSpec(4, 0, true, "simm5");
933 
934         protected final boolean signExtend;
935 
BitSpec(boolean signExtend)936         public BitSpec(boolean signExtend) {
937             super();
938             this.signExtend = signExtend;
939         }
940 
isSignExtend()941         public final boolean isSignExtend() {
942             return signExtend;
943         }
944 
setBits(int word, int value)945         public abstract int setBits(int word, int value);
946 
getBits(int word)947         public abstract int getBits(int word);
948 
getWidth()949         public abstract int getWidth();
950 
valueFits(int value)951         public abstract boolean valueFits(int value);
952     }
953 
954     public static final class ContinousBitSpec extends BitSpec {
955         private final int hiBit;
956         private final int lowBit;
957         private final int width;
958         private final int mask;
959         private final String name;
960 
ContinousBitSpec(int hiBit, int lowBit, String name)961         public ContinousBitSpec(int hiBit, int lowBit, String name) {
962             this(hiBit, lowBit, false, name);
963         }
964 
ContinousBitSpec(int hiBit, int lowBit, boolean signExt, String name)965         public ContinousBitSpec(int hiBit, int lowBit, boolean signExt, String name) {
966             super(signExt);
967             this.hiBit = hiBit;
968             this.lowBit = lowBit;
969             this.width = hiBit - lowBit + 1;
970             mask = ((1 << width) - 1) << lowBit;
971             this.name = name;
972         }
973 
974         @Override
setBits(int word, int value)975         public int setBits(int word, int value) {
976             assert valueFits(value) : String.format("Value 0x%x for field %s does not fit.", value, this);
977             return (word & ~mask) | ((value << lowBit) & mask);
978         }
979 
980         @Override
getBits(int word)981         public int getBits(int word) {
982             if (signExtend) {
983                 return ((word & mask) << (31 - hiBit)) >> (32 - width);
984             } else {
985                 return (word & mask) >>> lowBit;
986             }
987         }
988 
989         @Override
getWidth()990         public int getWidth() {
991             return width;
992         }
993 
994         @Override
toString()995         public String toString() {
996             return String.format("%s [%d:%d]", name, hiBit, lowBit);
997         }
998 
999         @Override
valueFits(int value)1000         public boolean valueFits(int value) {
1001             if (signExtend) {
1002                 return isSimm(value, getWidth());
1003             } else {
1004                 return isImm(value, getWidth());
1005             }
1006         }
1007     }
1008 
1009     public static final class CompositeBitSpec extends BitSpec {
1010         private final BitSpec left;
1011         private final int leftWidth;
1012         private final BitSpec right;
1013         private final int rightWidth;
1014         private final int width;
1015 
CompositeBitSpec(BitSpec left, BitSpec right)1016         public CompositeBitSpec(BitSpec left, BitSpec right) {
1017             super(left.isSignExtend());
1018             assert !right.isSignExtend() : String.format("Right field %s must not be sign extended", right);
1019             this.left = left;
1020             this.leftWidth = left.getWidth();
1021             this.right = right;
1022             this.rightWidth = right.getWidth();
1023             this.width = leftWidth + rightWidth;
1024         }
1025 
1026         @Override
getBits(int word)1027         public int getBits(int word) {
1028             int l = left.getBits(word);
1029             int r = right.getBits(word);
1030             return (l << rightWidth) | r;
1031         }
1032 
1033         @Override
setBits(int word, int value)1034         public int setBits(int word, int value) {
1035             int l = leftBits(value);
1036             int r = rightBits(value);
1037             return left.setBits(right.setBits(word, r), l);
1038         }
1039 
leftBits(int value)1040         private int leftBits(int value) {
1041             return getBits(value, width - 1, rightWidth, signExtend);
1042         }
1043 
rightBits(int value)1044         private int rightBits(int value) {
1045             return getBits(value, rightWidth - 1, 0, false);
1046         }
1047 
1048         @Override
getWidth()1049         public int getWidth() {
1050             return width;
1051         }
1052 
1053         @Override
toString()1054         public String toString() {
1055             return String.format("CompositeBitSpec[%s, %s]", left, right);
1056         }
1057 
1058         @Override
valueFits(int value)1059         public boolean valueFits(int value) {
1060             int l = leftBits(value);
1061             int r = rightBits(value);
1062             return left.valueFits(l) && right.valueFits(r);
1063         }
1064 
getBits(int inst, int hiBit, int lowBit, boolean signExtended)1065         private static int getBits(int inst, int hiBit, int lowBit, boolean signExtended) {
1066             int shifted = inst >> lowBit;
1067             if (signExtended) {
1068                 return shifted;
1069             } else {
1070                 return shifted & ((1 << (hiBit - lowBit + 1)) - 1);
1071             }
1072         }
1073     }
1074 
1075     public static class BitKey {
1076         private final BitSpec spec;
1077         private final int value;
1078 
BitKey(BitSpec spec, int value)1079         public BitKey(BitSpec spec, int value) {
1080             super();
1081             this.spec = spec;
1082             this.value = value;
1083         }
1084 
1085         @Override
toString()1086         public String toString() {
1087             return String.format("BitKey %s=%s", spec, value);
1088         }
1089     }
1090 
1091     /**
1092      * Represents a prefix tree of {@link BitSpec} objects to find the most accurate SPARCOp.
1093      */
1094     public static final class BitKeyIndex {
1095         private final BitSpec spec;
1096         private final Map<Integer, BitKeyIndex> nodes;
1097         private SPARCOp op;
1098 
BitKeyIndex(SPARCOp op)1099         public BitKeyIndex(SPARCOp op) {
1100             assert op != null;
1101             this.op = op;
1102             this.nodes = null;
1103             this.spec = null;
1104         }
1105 
BitKeyIndex(BitSpec spec)1106         public BitKeyIndex(BitSpec spec) {
1107             assert spec != null;
1108             this.op = null;
1109             this.nodes = new HashMap<>(4);
1110             this.spec = spec;
1111         }
1112 
1113         /**
1114          * Adds operation to the index.
1115          *
1116          * @param keys Ordered by the importance
1117          * @param operation Operation represented by this list of keys
1118          */
addOp(List<BitKey[]> keys, SPARCOp operation)1119         private void addOp(List<BitKey[]> keys, SPARCOp operation) {
1120             assert keys.size() > 0;
1121             BitKey[] firstKeys = keys.get(0);
1122             for (BitKey first : firstKeys) {
1123                 assert first.spec.equals(spec) : first.spec + " " + spec;
1124                 BitKeyIndex node;
1125                 if (keys.size() == 1) {
1126                     if (nodes.containsKey(first.value)) {
1127                         node = nodes.get(first.value);
1128                         assert node.op == null : node + " " + keys;
1129                         node.op = operation;
1130                     } else {
1131                         assert !nodes.containsKey(first.value) : "Index must be unique. Existing key: " + nodes.get(first.value);
1132                         node = new BitKeyIndex(operation);
1133                     }
1134                 } else {
1135                     node = nodes.get(first.value);
1136                     BitKey[] next = keys.get(1);
1137                     if (node == null) {
1138                         for (int i = 1; i < next.length; i++) {
1139                             assert next[i - 1].spec.equals(next[i].spec) : "All spec on this node must equal";
1140                         }
1141                         node = new BitKeyIndex(next[0].spec);
1142                     }
1143                     node.addOp(keys.subList(1, keys.size()), operation);
1144                 }
1145                 nodes.put(first.value, node);
1146             }
1147         }
1148 
1149         /**
1150          * Finds the best matching {@link SPARCOp} for this instruction.
1151          */
find(int inst)1152         public SPARCOp find(int inst) {
1153             if (nodes != null) {
1154                 int key = spec.getBits(inst);
1155                 BitKeyIndex sub = nodes.get(key);
1156                 if (sub == null) {
1157                     if (op != null) {
1158                         return op;
1159                     } else {
1160                         throw new RuntimeException(String.format("%s 0x%x, 0x%x %s", spec, inst, key, nodes));
1161                     }
1162                 }
1163                 return sub.find(inst);
1164             } else {
1165                 return this.op;
1166             }
1167         }
1168 
1169         @Override
toString()1170         public String toString() {
1171             return this.op == null ? this.spec + ": " + this.nodes : this.op.toString();
1172         }
1173     }
1174 
1175     public static final Bpcc BPCC = new Bpcc(Op2s.Bp);
1176     public static final Bpcc FBPCC = new Bpcc(Op2s.Fbp);
1177     public static final CBCond CBCOND = new CBCond();
1178     public static final Bpr BPR = new Bpr();
1179     public static final Br BR = new Br();
1180     public static final Sethi SETHI = new Sethi();
1181     public static final FMOVcc FMOVSCC = new FMOVcc(OpfLow.Fmovscc);
1182     public static final FMOVcc FMOVDCC = new FMOVcc(OpfLow.Fmovdcc);
1183     public static final MOVicc MOVICC = new MOVicc();
1184     public static final OpfOp OPF = new OpfOp();
1185     public static final Op3Op OP3 = new Op3Op();
1186     public static final SPARCOp LDST = new SPARCOp(Ops.LdstOp);
1187     public static final SPARCOp BRANCH = new SPARCOp(Ops.BranchOp);
1188     public static final SPARCOp CALL = new SPARCOp(Ops.CallOp);
1189     private static final BitKeyIndex INDEX = new BitKeyIndex(BitSpec.op);
1190 
1191     static {
1192         for (SPARCOp op : SPARCOp.OPS) {
op.getKeys()1193             INDEX.addOp(op.getKeys(), op);
1194         }
1195     }
1196 
getSPARCOp(int inst)1197     public static SPARCOp getSPARCOp(int inst) {
1198         return INDEX.find(inst);
1199     }
1200 
1201     /**
1202      * Represents a class of SPARC instruction and gives methods to modify its fields.
1203      */
1204     public static class SPARCOp {
1205         private final Ops op;
1206         private final BitKey opKey;
1207         private List<BitKey[]> keyFields;
1208         private static final List<SPARCOp> OPS = new ArrayList<>();
1209 
SPARCOp(Ops op)1210         public SPARCOp(Ops op) {
1211             super();
1212             this.op = op;
1213             this.opKey = new BitKey(BitSpec.op, op.value);
1214             OPS.add(this);
1215         }
1216 
setBits(int word)1217         protected int setBits(int word) {
1218             return BitSpec.op.setBits(word, op.value);
1219         }
1220 
match(int inst)1221         public boolean match(int inst) {
1222             for (BitKey[] keys : keyFields) {
1223                 for (BitKey k : keys) {
1224                     if (k.spec.getBits(inst) != k.value) {
1225                         return false;
1226                     }
1227                 }
1228             }
1229             return true;
1230         }
1231 
getKeys()1232         protected List<BitKey[]> getKeys() {
1233             if (keyFields == null) {
1234                 keyFields = new ArrayList<>(4);
1235                 keyFields.add(new BitKey[]{opKey});
1236             }
1237             return keyFields;
1238         }
1239 
getOp(int inst)1240         public Ops getOp(int inst) {
1241             return SPARCAssembler.OPS[BitSpec.op.getBits(inst)];
1242         }
1243 
1244         @Override
toString()1245         public String toString() {
1246             String name = getClass().getName();
1247             name = name.substring(name.lastIndexOf(".") + 1);
1248             return name + "[op: " + op + "]";
1249         }
1250     }
1251 
1252     /**
1253      * Base class for control transfer operations; provides access to the disp field.
1254      */
1255     public abstract static class ControlTransferOp extends SPARCOp {
1256         private final Op2s op2;
1257         private final boolean delaySlot;
1258         private final BitSpec disp;
1259         private final BitKey[] op2Key;
1260 
ControlTransferOp(Ops op, Op2s op2, boolean delaySlot, BitSpec disp)1261         private ControlTransferOp(Ops op, Op2s op2, boolean delaySlot, BitSpec disp) {
1262             super(op);
1263             this.op2 = op2;
1264             this.delaySlot = delaySlot;
1265             this.disp = disp;
1266             this.op2Key = new BitKey[]{new BitKey(BitSpec.op2, op2.value)};
1267         }
1268 
hasDelaySlot()1269         public boolean hasDelaySlot() {
1270             return delaySlot;
1271         }
1272 
1273         @Override
setBits(int word)1274         protected int setBits(int word) {
1275             return BitSpec.op2.setBits(super.setBits(word), op2.value);
1276         }
1277 
setDisp(int inst, SPARCMacroAssembler masm, Label lab)1278         protected int setDisp(int inst, SPARCMacroAssembler masm, Label lab) {
1279             if (lab.isBound()) {
1280                 int d = (lab.position() - masm.position()) / 4;
1281                 return setDisp(inst, d);
1282             } else {
1283                 masm.patchUnbound(lab);
1284                 return inst;
1285             }
1286         }
1287 
setDisp(int inst, int d)1288         public int setDisp(int inst, int d) {
1289             assert this.match(inst);
1290             if (!isValidDisp(d)) {
1291                 throw new BranchTargetOutOfBoundsException(true, "Too large displacement 0x%x in field %s in instruction %s", d, this.disp, this);
1292             }
1293             return this.disp.setBits(inst, d);
1294         }
1295 
isValidDisp(int d)1296         public boolean isValidDisp(int d) {
1297             return this.disp.valueFits(d);
1298         }
1299 
setAnnul(int inst, boolean a)1300         public int setAnnul(int inst, boolean a) {
1301             return BitSpec.a.setBits(inst, a ? 1 : 0);
1302         }
1303 
1304         @Override
getKeys()1305         protected List<BitKey[]> getKeys() {
1306             List<BitKey[]> keys = super.getKeys();
1307             keys.add(op2Key);
1308             return keys;
1309         }
1310 
getDisp(int inst)1311         public int getDisp(int inst) {
1312             return this.disp.getBits(inst);
1313         }
1314 
isAnnulable(int inst)1315         public abstract boolean isAnnulable(int inst);
1316 
isConditional(int inst)1317         public abstract boolean isConditional(int inst);
1318     }
1319 
1320     public static final class Bpcc extends ControlTransferOp {
Bpcc(Op2s op2)1321         public Bpcc(Op2s op2) {
1322             super(Ops.BranchOp, op2, true, BitSpec.disp19);
1323         }
1324 
emit(SPARCMacroAssembler masm, CC cc, ConditionFlag cf, Annul annul, BranchPredict p, Label lab)1325         public void emit(SPARCMacroAssembler masm, CC cc, ConditionFlag cf, Annul annul, BranchPredict p, Label lab) {
1326             int inst = setBits(0);
1327             inst = BitSpec.a.setBits(inst, annul.flag);
1328             inst = BitSpec.cond.setBits(inst, cf.value);
1329             inst = BitSpec.cc.setBits(inst, cc.value);
1330             inst = BitSpec.p.setBits(inst, p.flag);
1331             masm.insertNopAfterCBCond();
1332             masm.emitInt(setDisp(inst, masm, lab));
1333         }
1334 
1335         @Override
isAnnulable(int inst)1336         public boolean isAnnulable(int inst) {
1337             return isConditional(inst);
1338         }
1339 
1340         @Override
isConditional(int inst)1341         public boolean isConditional(int inst) {
1342             int cond = BitSpec.cond.getBits(inst);
1343             return cond != ConditionFlag.Always.value && cond != ConditionFlag.Never.value;
1344         }
1345     }
1346 
1347     public static final class Br extends ControlTransferOp {
Br()1348         public Br() {
1349             super(Ops.BranchOp, Op2s.Br, true, BitSpec.disp22);
1350         }
1351 
1352         @Override
isAnnulable(int inst)1353         public boolean isAnnulable(int inst) {
1354             return isConditional(inst);
1355         }
1356 
1357         @Override
isConditional(int inst)1358         public boolean isConditional(int inst) {
1359             int cond = BitSpec.cond.getBits(inst);
1360             return cond != ConditionFlag.Always.value && cond != ConditionFlag.Never.value;
1361         }
1362 
emit(SPARCMacroAssembler masm, ConditionFlag cond, Annul a, Label lab)1363         public void emit(SPARCMacroAssembler masm, ConditionFlag cond, Annul a, Label lab) {
1364             int inst = setBits(0);
1365             inst = BitSpec.cond.setBits(inst, cond.value);
1366             inst = BitSpec.a.setBits(inst, a.flag);
1367             masm.insertNopAfterCBCond();
1368             masm.emitInt(setDisp(inst, masm, lab));
1369         }
1370     }
1371 
1372     public static final class Bpr extends ControlTransferOp {
1373         private static final BitKey CBCOND_KEY = new BitKey(BitSpec.cbcond, 0);
1374 
Bpr()1375         public Bpr() {
1376             super(Ops.BranchOp, Op2s.Bpr, true, BitSpec.d16);
1377         }
1378 
emit(SPARCMacroAssembler masm, RCondition rcond, Annul a, BranchPredict p, Register rs1, Label lab)1379         public void emit(SPARCMacroAssembler masm, RCondition rcond, Annul a, BranchPredict p, Register rs1, Label lab) {
1380             int inst = setBits(0);
1381             inst = BitSpec.rcond.setBits(inst, rcond.value);
1382             inst = BitSpec.a.setBits(inst, a.flag);
1383             inst = BitSpec.p.setBits(inst, p.flag);
1384             inst = BitSpec.rs1.setBits(inst, rs1.encoding);
1385             masm.insertNopAfterCBCond();
1386             masm.emitInt(setDisp(inst, masm, lab));
1387         }
1388 
1389         @Override
getKeys()1390         protected List<BitKey[]> getKeys() {
1391             List<BitKey[]> keys = super.getKeys();
1392             keys.add(new BitKey[]{CBCOND_KEY});
1393             return keys;
1394         }
1395 
1396         @Override
isAnnulable(int inst)1397         public boolean isAnnulable(int inst) {
1398             return isConditional(inst);
1399         }
1400 
1401         @Override
isConditional(int inst)1402         public boolean isConditional(int inst) {
1403             int cond = BitSpec.cond.getBits(inst);
1404             return cond != ConditionFlag.Always.value && cond != ConditionFlag.Never.value;
1405         }
1406     }
1407 
1408     public static final class CBCond extends ControlTransferOp {
1409         private static final BitKey CBCOND_KEY = new BitKey(BitSpec.cbcond, 1);
1410 
CBCond()1411         private CBCond() {
1412             super(Ops.BranchOp, Op2s.Bpr, false, BitSpec.d10);
1413         }
1414 
1415         @Override
getKeys()1416         protected List<BitKey[]> getKeys() {
1417             List<BitKey[]> keys = super.getKeys();
1418             keys.add(new BitKey[]{CBCOND_KEY});
1419             return keys;
1420         }
1421 
emit(SPARCMacroAssembler masm, ConditionFlag cf, boolean cc2, Register rs1, Register rs2, Label lab)1422         public void emit(SPARCMacroAssembler masm, ConditionFlag cf, boolean cc2, Register rs1, Register rs2, Label lab) {
1423             int inst = setBits(0, cf, cc2, rs1);
1424             inst = BitSpec.rs2.setBits(inst, rs2.encoding);
1425             inst = BitSpec.i.setBits(inst, 0);
1426             masm.insertNopAfterCBCond();
1427             emit(masm, lab, inst);
1428         }
1429 
emit(SPARCMacroAssembler masm, ConditionFlag cf, boolean cc2, Register rs1, int simm5, Label lab)1430         public void emit(SPARCMacroAssembler masm, ConditionFlag cf, boolean cc2, Register rs1, int simm5, Label lab) {
1431             int inst = setBits(0, cf, cc2, rs1);
1432             inst = BitSpec.simm5.setBits(inst, simm5);
1433             inst = BitSpec.i.setBits(inst, 1);
1434             emit(masm, lab, inst);
1435         }
1436 
emit(SPARCMacroAssembler masm, Label lab, int baseInst)1437         private void emit(SPARCMacroAssembler masm, Label lab, int baseInst) {
1438             int inst = baseInst;
1439             masm.insertNopAfterCBCond();
1440             masm.emitInt(setDisp(inst, masm, lab));
1441         }
1442 
setBits(int base, ConditionFlag cf, boolean cc2, Register rs1)1443         private int setBits(int base, ConditionFlag cf, boolean cc2, Register rs1) {
1444             int inst = super.setBits(base);
1445             inst = BitSpec.rs1.setBits(inst, rs1.encoding);
1446             inst = BitSpec.cc2.setBits(inst, cc2 ? 1 : 0);
1447             inst = BitSpec.c.setBits(inst, cf.value);
1448             return BitSpec.cbcond.setBits(inst, 1);
1449         }
1450 
1451         @Override
isAnnulable(int inst)1452         public boolean isAnnulable(int inst) {
1453             return false;
1454         }
1455 
1456         @Override
isConditional(int inst)1457         public boolean isConditional(int inst) {
1458             return true;
1459         }
1460     }
1461 
1462     public static class Op2Op extends SPARCOp {
1463         private final Op2s op2;
1464         private final BitKey op2Key;
1465 
Op2Op(Ops op, Op2s op2)1466         public Op2Op(Ops op, Op2s op2) {
1467             super(op);
1468             this.op2 = op2;
1469             op2Key = new BitKey(BitSpec.op2, op2.value);
1470         }
1471 
1472         @Override
setBits(int word)1473         protected int setBits(int word) {
1474             int result = super.setBits(word);
1475             return BitSpec.op2.setBits(result, op2.value);
1476         }
1477 
1478         @Override
getKeys()1479         protected List<BitKey[]> getKeys() {
1480             List<BitKey[]> keys = super.getKeys();
1481             keys.add(new BitKey[]{op2Key});
1482             return keys;
1483         }
1484     }
1485 
1486     public static final class Sethi extends Op2Op {
Sethi()1487         public Sethi() {
1488             super(Ops.BranchOp, Op2s.Sethi);
1489         }
1490 
getRS1(int word)1491         public static Register getRS1(int word) {
1492             int regNum = BitSpec.rs1.getBits(word);
1493             return SPARC.cpuRegisters.get(regNum);
1494         }
1495 
getImm22(int word)1496         public static int getImm22(int word) {
1497             return BitSpec.imm22.getBits(word);
1498         }
1499 
isNop(int inst)1500         public static boolean isNop(int inst) {
1501             return getRS1(inst).equals(g0) && getImm22(inst) == 0;
1502         }
1503     }
1504 
1505     public static final class Op3Op extends SPARCOp {
Op3Op()1506         public Op3Op() {
1507             super(ArithOp);
1508         }
1509 
getOp3(int inst)1510         public Op3s getOp3(int inst) {
1511             assert match(inst);
1512             return OP3S[ArithOp.value & 1][BitSpec.op3.getBits(inst)];
1513         }
1514 
emit(SPARCMacroAssembler masm, Op3s opcode, Register rs1, Register rs2, Register rd)1515         public static void emit(SPARCMacroAssembler masm, Op3s opcode, Register rs1, Register rs2, Register rd) {
1516             int instruction = setBits(0, opcode, rs1, rd);
1517             instruction = BitSpec.rs2.setBits(instruction, rs2.encoding);
1518             instruction = BitSpec.i.setBits(instruction, 0);
1519             masm.emitInt(instruction);
1520         }
1521 
emit(SPARCMacroAssembler masm, Op3s opcode, Register rs1, int simm13, Register rd)1522         public static void emit(SPARCMacroAssembler masm, Op3s opcode, Register rs1, int simm13, Register rd) {
1523             int instruction = setBits(0, opcode, rs1, rd);
1524             instruction = BitSpec.i.setBits(instruction, 1);
1525             BitSpec immediateSpec;
1526             switch (opcode) {
1527                 case Sllx:
1528                 case Srlx:
1529                 case Srax:
1530                     immediateSpec = BitSpec.shcnt64;
1531                     break;
1532                 case Sll:
1533                 case Srl:
1534                 case Sra:
1535                     immediateSpec = BitSpec.shcnt32;
1536                     break;
1537                 default:
1538                     immediateSpec = BitSpec.simm13;
1539                     break;
1540             }
1541             instruction = immediateSpec.setBits(instruction, simm13);
1542             masm.emitInt(instruction);
1543         }
1544 
setBits(int instruction, Op3s op3, Register rs1, Register rd)1545         private static int setBits(int instruction, Op3s op3, Register rs1, Register rd) {
1546             assert op3.op.equals(ArithOp);
1547             int tmp = BitSpec.op3.setBits(instruction, op3.value);
1548             switch (op3) {
1549                 case Sllx:
1550                 case Srlx:
1551                 case Srax:
1552                     tmp = BitSpec.x.setBits(tmp, 1);
1553                     break;
1554             }
1555             tmp = BitSpec.op.setBits(tmp, op3.op.value);
1556             tmp = BitSpec.rd.setBits(tmp, rd.encoding);
1557             return BitSpec.rs1.setBits(tmp, rs1.encoding);
1558         }
1559     }
1560 
1561     /**
1562      * Used for interfacing FP and GP conditional move instructions.
1563      */
1564     public interface CMOV {
emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, Register rs2, Register rd)1565         void emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, Register rs2, Register rd);
1566 
emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, int simm11, Register rd)1567         void emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, int simm11, Register rd);
1568     }
1569 
1570     public static final class MOVicc extends SPARCOp implements CMOV {
1571         private static final Op3s op3 = Movcc;
1572 
MOVicc()1573         public MOVicc() {
1574             super(ArithOp);
1575         }
1576 
1577         @Override
emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, Register rs2, Register rd)1578         public void emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, Register rs2, Register rd) {
1579             int inst = setBits(0, condition, cc, rd);
1580             inst = BitSpec.rs2.setBits(inst, rs2.encoding());
1581             masm.emitInt(inst);
1582         }
1583 
1584         @Override
emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, int simm11, Register rd)1585         public void emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, int simm11, Register rd) {
1586             int inst = setBits(0, condition, cc, rd);
1587             inst = BitSpec.i.setBits(inst, 1);
1588             inst = BitSpec.simm11.setBits(inst, simm11);
1589             masm.emitInt(inst);
1590         }
1591 
setBits(int word, ConditionFlag condition, CC cc, Register rd)1592         protected int setBits(int word, ConditionFlag condition, CC cc, Register rd) {
1593             int inst = super.setBits(word);
1594             inst = BitSpec.rd.setBits(inst, rd.encoding());
1595             inst = BitSpec.op3.setBits(inst, op3.value);
1596             inst = BitSpec.movccCond.setBits(inst, condition.value);
1597             inst = BitSpec.movccLo.setBits(inst, cc.value);
1598             return BitSpec.movccHi.setBits(inst, cc.isFloat ? 0 : 1);
1599         }
1600 
1601         @Override
getKeys()1602         protected List<BitKey[]> getKeys() {
1603             List<BitKey[]> keys = super.getKeys();
1604             keys.add(new BitKey[]{new BitKey(BitSpec.op3, op3.value)});
1605             return keys;
1606         }
1607     }
1608 
1609     public static final class FMOVcc extends SPARCOp implements CMOV {
1610         private OpfLow opfLow;
1611 
FMOVcc(OpfLow opfLow)1612         public FMOVcc(OpfLow opfLow) {
1613             super(ArithOp);
1614             this.opfLow = opfLow;
1615         }
1616 
1617         @Override
emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, Register rs2, Register rd)1618         public void emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, Register rs2, Register rd) {
1619             int inst = setBits(0);
1620             inst = BitSpec.rd.setBits(inst, rd.encoding());
1621             inst = BitSpec.op3.setBits(inst, opfLow.op3.value);
1622             inst = BitSpec.opfCond.setBits(inst, condition.value);
1623             inst = BitSpec.opfCC.setBits(inst, cc.getOpfCCValue());
1624             inst = BitSpec.opfLow.setBits(inst, opfLow.value);
1625             inst = BitSpec.rs2.setBits(inst, rs2.encoding());
1626             masm.emitInt(inst);
1627         }
1628 
1629         @Override
emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, int simm11, Register rd)1630         public void emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, int simm11, Register rd) {
1631             throw new IllegalArgumentException("FMOVCC cannot be used with immediate value");
1632         }
1633 
1634         @Override
getKeys()1635         protected List<BitKey[]> getKeys() {
1636             List<BitKey[]> keys = super.getKeys();
1637             keys.add(new BitKey[]{new BitKey(BitSpec.op3, opfLow.op3.value)});
1638             keys.add(new BitKey[]{new BitKey(BitSpec.opfLow, opfLow.value)});
1639             return keys;
1640         }
1641     }
1642 
1643     public static final class OpfOp extends SPARCOp {
1644 
1645         private BitKey[] op3Keys;
1646 
OpfOp(BitKey... op3Keys)1647         public OpfOp(BitKey... op3Keys) {
1648             super(ArithOp);
1649             this.op3Keys = op3Keys;
1650         }
1651 
OpfOp()1652         public OpfOp() {
1653             // @formatter:off
1654             this(new BitKey[]{
1655                             new BitKey(BitSpec.op3, Op3s.Fpop1.value),
1656                             new BitKey(BitSpec.op3, Op3s.Fpop2.value),
1657                             new BitKey(BitSpec.op3, Op3s.Impdep1.value),
1658                             new BitKey(BitSpec.op3, Op3s.Impdep2.value)});
1659             // @formatter:on
1660         }
1661 
emit(SPARCMacroAssembler masm, Opfs opf, Register rs1, Register rs2, Register rd)1662         public static void emit(SPARCMacroAssembler masm, Opfs opf, Register rs1, Register rs2, Register rd) {
1663             int instruction = setBits(0, opf, rs1, rs2);
1664             instruction = BitSpec.rd.setBits(instruction, rd.encoding);
1665             instruction = BitSpec.i.setBits(instruction, 0);
1666             masm.emitInt(instruction);
1667         }
1668 
emitFcmp(SPARCMacroAssembler masm, Opfs opf, CC cc, Register rs1, Register rs2)1669         public static void emitFcmp(SPARCMacroAssembler masm, Opfs opf, CC cc, Register rs1, Register rs2) {
1670             assert opf.equals(Opfs.Fcmpd) || opf.equals(Opfs.Fcmps) : opf;
1671             int instruction = setBits(0, opf, rs1, rs2);
1672             instruction = BitSpec.fcc.setBits(instruction, cc.value);
1673             masm.emitInt(instruction);
1674         }
1675 
setBits(int instruction, Opfs opf, Register rs1, Register rs2)1676         private static int setBits(int instruction, Opfs opf, Register rs1, Register rs2) {
1677             int tmp = BitSpec.op.setBits(instruction, opf.op3.op.value);
1678             tmp = BitSpec.op3.setBits(tmp, opf.op3.value);
1679             tmp = BitSpec.opf.setBits(tmp, opf.value);
1680             tmp = BitSpec.rs1.setBits(tmp, rs1.encoding);
1681             return BitSpec.rs2.setBits(tmp, rs2.encoding);
1682         }
1683 
1684         @Override
getKeys()1685         protected List<BitKey[]> getKeys() {
1686             List<BitKey[]> keys = super.getKeys();
1687             keys.add(op3Keys);
1688             // @formatter:on
1689             return keys;
1690         }
1691     }
1692 
isCPURegister(Register... regs)1693     public static boolean isCPURegister(Register... regs) {
1694         for (Register reg : regs) {
1695             if (!isCPURegister(reg)) {
1696                 return false;
1697             }
1698         }
1699         return true;
1700     }
1701 
isCPURegister(Register r)1702     public static boolean isCPURegister(Register r) {
1703         return r.getRegisterCategory().equals(CPU);
1704     }
1705 
isGlobalRegister(Register r)1706     public static boolean isGlobalRegister(Register r) {
1707         return isCPURegister(r) && g0.number <= r.number && r.number <= g7.number;
1708     }
1709 
isSingleFloatRegister(Register r)1710     public static boolean isSingleFloatRegister(Register r) {
1711         return r.getRegisterCategory().equals(FPUs);
1712     }
1713 
isDoubleFloatRegister(Register r)1714     public static boolean isDoubleFloatRegister(Register r) {
1715         return r.getRegisterCategory().equals(FPUd);
1716     }
1717 
hasFeature(CPUFeature feature)1718     public boolean hasFeature(CPUFeature feature) {
1719         return ((SPARC) this.target.arch).features.contains(feature);
1720     }
1721 
simm(int x, int nbits)1722     public static final int simm(int x, int nbits) {
1723         // assert_signed_range(x, nbits);
1724         return x & ((1 << nbits) - 1);
1725     }
1726 
isImm(int x, int nbits)1727     public static final boolean isImm(int x, int nbits) {
1728         // assert_signed_range(x, nbits);
1729         return simm(x, nbits) == x;
1730     }
1731 
1732     /**
1733      * Minimum value for signed immediate ranges.
1734      */
minSimm(long nbits)1735     public static long minSimm(long nbits) {
1736         return -(1L << (nbits - 1));
1737     }
1738 
1739     /**
1740      * Maximum value for signed immediate ranges.
1741      */
maxSimm(long nbits)1742     public static long maxSimm(long nbits) {
1743         return (1L << (nbits - 1)) - 1;
1744     }
1745 
1746     /**
1747      * Test if imm is within signed immediate range for nbits.
1748      */
isSimm(long imm, int nbits)1749     public static boolean isSimm(long imm, int nbits) {
1750         return minSimm(nbits) <= imm && imm <= maxSimm(nbits);
1751     }
1752 
isSimm10(long imm)1753     public static boolean isSimm10(long imm) {
1754         return isSimm(imm, 10);
1755     }
1756 
isSimm11(long imm)1757     public static boolean isSimm11(long imm) {
1758         return isSimm(imm, 11);
1759     }
1760 
isSimm11(JavaConstant constant)1761     public static boolean isSimm11(JavaConstant constant) {
1762         return constant.isNull() || isSimm11(constant.asLong());
1763     }
1764 
isSimm5(JavaConstant constant)1765     public static boolean isSimm5(JavaConstant constant) {
1766         return constant.isNull() || isSimm(constant.asLong(), 5);
1767     }
1768 
isSimm5(long imm)1769     public static boolean isSimm5(long imm) {
1770         return isSimm(imm, 5);
1771     }
1772 
isSimm13(int imm)1773     public static boolean isSimm13(int imm) {
1774         return isSimm(imm, 13);
1775     }
1776 
isSimm13(JavaConstant constant)1777     public static boolean isSimm13(JavaConstant constant) {
1778         long bits;
1779         switch (constant.getJavaKind()) {
1780             case Double:
1781                 bits = Double.doubleToRawLongBits(constant.asDouble());
1782                 break;
1783             case Float:
1784                 bits = Float.floatToRawIntBits(constant.asFloat());
1785                 break;
1786             case Object:
1787                 return constant.isNull();
1788             default:
1789                 bits = constant.asLong();
1790                 break;
1791         }
1792         return constant.isNull() || isSimm13(bits);
1793     }
1794 
isSimm13(long imm)1795     public static boolean isSimm13(long imm) {
1796         return NumUtil.isInt(imm) && isSimm(imm, 13);
1797     }
1798 
isWordDisp30(long imm)1799     public static boolean isWordDisp30(long imm) {
1800         return isSimm(imm, 30 + 2);
1801     }
1802 
hi22(int x)1803     public static final int hi22(int x) {
1804         return x >>> 10;
1805     }
1806 
lo10(int x)1807     public static final int lo10(int x) {
1808         return x & ((1 << 10) - 1);
1809     }
1810 
1811     // @formatter:off
1812     /**
1813      * Instruction format for Fmt00 instructions. This abstraction is needed as it
1814      * makes the patching easier later on.
1815      * <pre>
1816      * | 00  |    a   | op2 |               b                         |
1817      * |31 30|29    25|24 22|21                                      0|
1818      * </pre>
1819      */
1820     // @formatter:on
fmt00(int a, int op2, int b)1821     protected void fmt00(int a, int op2, int b) {
1822         assert isImm(a, 5) && isImm(op2, 3) && isImm(b, 22) : String.format("a: 0x%x op2: 0x%x b: 0x%x", a, op2, b);
1823         int word = 0;
1824         BitSpec.op.setBits(word, 0);
1825         BitSpec.rd.setBits(word, a);
1826         BitSpec.op2.setBits(word, op2);
1827         BitSpec.imm22.setBits(word, b);
1828         emitInt(a << 25 | op2 << 22 | b);
1829     }
1830 
op3(Op3s op3, Opfs opf, Register rs1, Register rs2, Register rd)1831     private void op3(Op3s op3, Opfs opf, Register rs1, Register rs2, Register rd) {
1832         int b = opf.value << 5 | (rs2 == null ? 0 : rs2.encoding);
1833         fmt(op3.op.value, rd.encoding, op3.value, rs1 == null ? 0 : rs1.encoding, b);
1834     }
1835 
op3(Op3s op3, Register rs1, Register rs2, Register rd)1836     protected void op3(Op3s op3, Register rs1, Register rs2, Register rd) {
1837         int b = rs2 == null ? 0 : rs2.encoding;
1838         int xBit = getXBit(op3);
1839         fmt(op3.op.value, rd.encoding, op3.value, rs1 == null ? 0 : rs1.encoding, b | xBit);
1840     }
1841 
op3(Op3s op3, Register rs1, int simm13, Register rd)1842     protected void op3(Op3s op3, Register rs1, int simm13, Register rd) {
1843         assert isSimm13(simm13) : simm13;
1844         int i = 1 << 13;
1845         int simm13WithX = simm13 | getXBit(op3);
1846         fmt(op3.op.value, rd.encoding, op3.value, rs1.encoding, i | simm13WithX & ((1 << 13) - 1));
1847     }
1848 
insertNopAfterCBCond()1849     public void insertNopAfterCBCond() {
1850         int pos = position() - INSTRUCTION_SIZE;
1851         if (pos == 0) {
1852             return;
1853         }
1854         int inst = getInt(pos);
1855         if (CBCOND.match(inst)) {
1856             nop();
1857         }
1858     }
1859 
patchUnbound(Label label)1860     protected int patchUnbound(Label label) {
1861         label.addPatchAt(position(), this);
1862         return 0;
1863     }
1864 
1865     // @formatter:off
1866     /**
1867      * NOP.
1868      * <pre>
1869      * | 00  |00000| 100 |                0                    |
1870      * |31 30|29 25|24 22|21                                  0|
1871      * </pre>
1872      */
1873     // @formatter:on
nop()1874     public void nop() {
1875         emitInt(1 << 24);
1876     }
1877 
sethi(int imm22, Register dst)1878     public void sethi(int imm22, Register dst) {
1879         fmt00(dst.encoding, Op2s.Sethi.value, imm22);
1880     }
1881 
1882     // @formatter:off
1883     /**
1884      * Instruction format for calls.
1885      * <pre>
1886      * | 01  |                      disp30                             |
1887      * |31 30|29                                                      0|
1888      * </pre>
1889      *
1890      * @return Position of the call instruction
1891      */
1892     // @formatter:on
call(int disp30)1893     public int call(int disp30) {
1894         assert isImm(disp30, 30);
1895         insertNopAfterCBCond();
1896         int before = position();
1897         int instr = 1 << 30;
1898         instr |= disp30;
1899         emitInt(instr);
1900         return before;
1901     }
1902 
add(Register rs1, Register rs2, Register rd)1903     public void add(Register rs1, Register rs2, Register rd) {
1904         op3(Add, rs1, rs2, rd);
1905     }
1906 
add(Register rs1, int simm13, Register rd)1907     public void add(Register rs1, int simm13, Register rd) {
1908         op3(Add, rs1, simm13, rd);
1909     }
1910 
addc(Register rs1, Register rs2, Register rd)1911     public void addc(Register rs1, Register rs2, Register rd) {
1912         op3(Addc, rs1, rs2, rd);
1913     }
1914 
addc(Register rs1, int simm13, Register rd)1915     public void addc(Register rs1, int simm13, Register rd) {
1916         op3(Addc, rs1, simm13, rd);
1917     }
1918 
addcc(Register rs1, Register rs2, Register rd)1919     public void addcc(Register rs1, Register rs2, Register rd) {
1920         op3(Addcc, rs1, rs2, rd);
1921     }
1922 
addcc(Register rs1, int simm13, Register rd)1923     public void addcc(Register rs1, int simm13, Register rd) {
1924         op3(Addcc, rs1, simm13, rd);
1925     }
1926 
and(Register rs1, Register rs2, Register rd)1927     public void and(Register rs1, Register rs2, Register rd) {
1928         op3(And, rs1, rs2, rd);
1929     }
1930 
and(Register rs1, int simm13, Register rd)1931     public void and(Register rs1, int simm13, Register rd) {
1932         op3(And, rs1, simm13, rd);
1933     }
1934 
andcc(Register rs1, Register rs2, Register rd)1935     public void andcc(Register rs1, Register rs2, Register rd) {
1936         op3(Andcc, rs1, rs2, rd);
1937     }
1938 
andcc(Register rs1, int simm13, Register rd)1939     public void andcc(Register rs1, int simm13, Register rd) {
1940         op3(Andcc, rs1, simm13, rd);
1941     }
1942 
andn(Register rs1, Register rs2, Register rd)1943     public void andn(Register rs1, Register rs2, Register rd) {
1944         op3(Andn, rs1, rs2, rd);
1945     }
1946 
andn(Register rs1, int simm13, Register rd)1947     public void andn(Register rs1, int simm13, Register rd) {
1948         op3(Andn, rs1, simm13, rd);
1949     }
1950 
andncc(Register rs1, Register rs2, Register rd)1951     public void andncc(Register rs1, Register rs2, Register rd) {
1952         op3(Andncc, rs1, rs2, rd);
1953     }
1954 
andncc(Register rs1, int simm13, Register rd)1955     public void andncc(Register rs1, int simm13, Register rd) {
1956         op3(Andncc, rs1, simm13, rd);
1957     }
1958 
movwtos(Register rs2, Register rd)1959     public void movwtos(Register rs2, Register rd) {
1960         assert isSingleFloatRegister(rd) && isCPURegister(rs2) : String.format("%s %s", rs2, rd);
1961         op3(Impdep1, Movwtos, null, rs2, rd);
1962     }
1963 
umulxhi(Register rs1, Register rs2, Register rd)1964     public void umulxhi(Register rs1, Register rs2, Register rd) {
1965         op3(Impdep1, UMulxhi, rs1, rs2, rd);
1966     }
1967 
fdtos(Register rs2, Register rd)1968     public void fdtos(Register rs2, Register rd) {
1969         assert isSingleFloatRegister(rd) && isDoubleFloatRegister(rs2) : String.format("%s %s", rs2, rd);
1970         op3(Fpop1, Fdtos, null, rs2, rd);
1971     }
1972 
movstouw(Register rs2, Register rd)1973     public void movstouw(Register rs2, Register rd) {
1974         assert isSingleFloatRegister(rs2) && isCPURegister(rd) : String.format("%s %s", rs2, rd);
1975         op3(Impdep1, Movstosw, null, rs2, rd);
1976     }
1977 
movstosw(Register rs2, Register rd)1978     public void movstosw(Register rs2, Register rd) {
1979         assert isSingleFloatRegister(rs2) && isCPURegister(rd) : String.format("%s %s", rs2, rd);
1980         op3(Impdep1, Movstosw, null, rs2, rd);
1981     }
1982 
movdtox(Register rs2, Register rd)1983     public void movdtox(Register rs2, Register rd) {
1984         assert isDoubleFloatRegister(rs2) && isCPURegister(rd) : String.format("%s %s", rs2, rd);
1985         op3(Impdep1, Movdtox, null, rs2, rd);
1986     }
1987 
movxtod(Register rs2, Register rd)1988     public void movxtod(Register rs2, Register rd) {
1989         assert isCPURegister(rs2) && isDoubleFloatRegister(rd) : String.format("%s %s", rs2, rd);
1990         op3(Impdep1, Movxtod, null, rs2, rd);
1991     }
1992 
fadds(Register rs1, Register rs2, Register rd)1993     public void fadds(Register rs1, Register rs2, Register rd) {
1994         op3(Fpop1, Fadds, rs1, rs2, rd);
1995     }
1996 
faddd(Register rs1, Register rs2, Register rd)1997     public void faddd(Register rs1, Register rs2, Register rd) {
1998         op3(Fpop1, Faddd, rs1, rs2, rd);
1999     }
2000 
fdivs(Register rs1, Register rs2, Register rd)2001     public void fdivs(Register rs1, Register rs2, Register rd) {
2002         op3(Fpop1, Fdivs, rs1, rs2, rd);
2003     }
2004 
fdivd(Register rs1, Register rs2, Register rd)2005     public void fdivd(Register rs1, Register rs2, Register rd) {
2006         op3(Fpop1, Fdivd, rs1, rs2, rd);
2007     }
2008 
fmovs(Register rs2, Register rd)2009     public void fmovs(Register rs2, Register rd) {
2010         op3(Fpop1, Fmovs, null, rs2, rd);
2011     }
2012 
fmovd(Register rs2, Register rd)2013     public void fmovd(Register rs2, Register rd) {
2014         op3(Fpop1, Fmovd, null, rs2, rd);
2015     }
2016 
fsrc2s(Register rs2, Register rd)2017     public void fsrc2s(Register rs2, Register rd) {
2018         op3(Impdep1, Fsrc2s, null, rs2, rd);
2019     }
2020 
fsrc2d(Register rs2, Register rd)2021     public void fsrc2d(Register rs2, Register rd) {
2022         op3(Impdep1, Fsrc2d, null, rs2, rd);
2023     }
2024 
fmuls(Register rs1, Register rs2, Register rd)2025     public void fmuls(Register rs1, Register rs2, Register rd) {
2026         op3(Fpop1, Fmuls, rs1, rs2, rd);
2027     }
2028 
fsmuld(Register rs1, Register rs2, Register rd)2029     public void fsmuld(Register rs1, Register rs2, Register rd) {
2030         op3(Fpop1, Fsmuld, rs1, rs2, rd);
2031     }
2032 
fmuld(Register rs1, Register rs2, Register rd)2033     public void fmuld(Register rs1, Register rs2, Register rd) {
2034         op3(Fpop1, Fmuld, rs1, rs2, rd);
2035     }
2036 
fnegs(Register rs2, Register rd)2037     public void fnegs(Register rs2, Register rd) {
2038         op3(Fpop1, Fnegs, null, rs2, rd);
2039     }
2040 
fnegd(Register rs2, Register rd)2041     public void fnegd(Register rs2, Register rd) {
2042         op3(Fpop1, Fnegd, null, rs2, rd);
2043     }
2044 
2045     /**
2046      * Helper method to determine if the instruction needs the X bit set.
2047      */
getXBit(Op3s op3)2048     private static int getXBit(Op3s op3) {
2049         switch (op3) {
2050             case Sllx:
2051             case Srax:
2052             case Srlx:
2053                 return 1 << 12;
2054             default:
2055                 return 0;
2056         }
2057     }
2058 
fstoi(Register rs2, Register rd)2059     public void fstoi(Register rs2, Register rd) {
2060         op3(Fpop1, Fstoi, null, rs2, rd);
2061     }
2062 
fstox(Register rs2, Register rd)2063     public void fstox(Register rs2, Register rd) {
2064         op3(Fpop1, Fstox, null, rs2, rd);
2065     }
2066 
fdtox(Register rs2, Register rd)2067     public void fdtox(Register rs2, Register rd) {
2068         op3(Fpop1, Fdtox, null, rs2, rd);
2069     }
2070 
fstod(Register rs2, Register rd)2071     public void fstod(Register rs2, Register rd) {
2072         op3(Fpop1, Fstod, null, rs2, rd);
2073     }
2074 
fdtoi(Register rs2, Register rd)2075     public void fdtoi(Register rs2, Register rd) {
2076         op3(Fpop1, Fdtoi, null, rs2, rd);
2077     }
2078 
fitos(Register rs2, Register rd)2079     public void fitos(Register rs2, Register rd) {
2080         op3(Fpop1, Fitos, null, rs2, rd);
2081     }
2082 
fitod(Register rs2, Register rd)2083     public void fitod(Register rs2, Register rd) {
2084         op3(Fpop1, Fitod, null, rs2, rd);
2085     }
2086 
fxtos(Register rs2, Register rd)2087     public void fxtos(Register rs2, Register rd) {
2088         op3(Fpop1, Fxtos, null, rs2, rd);
2089     }
2090 
fxtod(Register rs2, Register rd)2091     public void fxtod(Register rs2, Register rd) {
2092         op3(Fpop1, Fxtod, null, rs2, rd);
2093     }
2094 
fzeros(Register rd)2095     public void fzeros(Register rd) {
2096         op3(Impdep1, Fzeros, null, null, rd);
2097     }
2098 
fzerod(Register rd)2099     public void fzerod(Register rd) {
2100         op3(Impdep1, Fzerod, null, null, rd);
2101     }
2102 
flushw()2103     public void flushw() {
2104         op3(Flushw, g0, g0, g0);
2105     }
2106 
fsqrtd(Register rs2, Register rd)2107     public void fsqrtd(Register rs2, Register rd) {
2108         op3(Fpop1, Fsqrtd, null, rs2, rd);
2109     }
2110 
fsqrts(Register rs2, Register rd)2111     public void fsqrts(Register rs2, Register rd) {
2112         op3(Fpop1, Fsqrts, null, rs2, rd);
2113     }
2114 
fabss(Register rs2, Register rd)2115     public void fabss(Register rs2, Register rd) {
2116         op3(Fpop1, Fabss, null, rs2, rd);
2117     }
2118 
fabsd(Register rs2, Register rd)2119     public void fabsd(Register rs2, Register rd) {
2120         op3(Fpop1, Fabsd, null, rs2, rd);
2121     }
2122 
fsubs(Register rs1, Register rs2, Register rd)2123     public void fsubs(Register rs1, Register rs2, Register rd) {
2124         op3(Fpop1, Fsubs, rs1, rs2, rd);
2125     }
2126 
fsubd(Register rs1, Register rs2, Register rd)2127     public void fsubd(Register rs1, Register rs2, Register rd) {
2128         op3(Fpop1, Fsubd, rs1, rs2, rd);
2129     }
2130 
2131     // @formatter:off
2132     /**
2133      * Instruction format for fcmp.
2134      * <pre>
2135      * | 10  | --- |cc1|cc0|desc |   rs1   |   opf  | rs2 |
2136      * |31 30|29 27|26 |25 |24 19|18     14|13     5|4   0|
2137      * </pre>
2138      */
2139     // @formatter:on
fcmp(CC cc, Opfs opf, Register rs1, Register rs2)2140     public void fcmp(CC cc, Opfs opf, Register rs1, Register rs2) {
2141         int a = cc.value;
2142         int b = opf.value << 5 | rs2.encoding;
2143         delaySlotOptimizationPoints.add(position());
2144         fmt10(a, Fpop2.value, rs1.encoding, b);
2145     }
2146 
2147     // @formatter:off
2148     /**
2149      * Instruction format for most arithmetic stuff.
2150      * <pre>
2151      * |  10 | rd  | op3 | rs1 |   b   |
2152      * |31 30|29 25|24 19|18 14|13    0|
2153      * </pre>
2154      */
2155     // @formatter:on
fmt10(int rd, int op3, int rs1, int b)2156     protected void fmt10(int rd, int op3, int rs1, int b) {
2157         fmt(0b10, rd, op3, rs1, b);
2158     }
2159 
2160     // @formatter:off
2161     /**
2162      * Instruction format for most arithmetic stuff.
2163      * <pre>
2164      * |  op | rd  | op3 | rs1 |   b   |
2165      * |31 30|29 25|24 19|18 14|13    0|
2166      * </pre>
2167      */
2168     // @formatter:on
fmt(int op, int rd, int op3, int rs1, int b)2169     protected void fmt(int op, int rd, int op3, int rs1, int b) {
2170         assert isImm(rd, 5) && isImm(op3, 6) && isImm(b, 14) : String.format("rd: 0x%x op3: 0x%x b: 0x%x", rd, op3, b);
2171         int instr = op << 30 | rd << 25 | op3 << 19 | rs1 << 14 | b;
2172         emitInt(instr);
2173     }
2174 
illtrap(int const22)2175     public void illtrap(int const22) {
2176         fmt00(0, Op2s.Illtrap.value, const22);
2177     }
2178 
jmpl(Register rs1, Register rs2, Register rd)2179     public void jmpl(Register rs1, Register rs2, Register rd) {
2180         insertNopAfterCBCond();
2181         op3(Jmpl, rs1, rs2, rd);
2182     }
2183 
2184     /**
2185      * @return Position of the jmpl instruction
2186      */
jmpl(Register rs1, int simm13, Register rd)2187     public int jmpl(Register rs1, int simm13, Register rd) {
2188         insertNopAfterCBCond();
2189         int before = position();
2190         op3(Jmpl, rs1, simm13, rd);
2191         return before;
2192     }
2193 
fmovdcc(ConditionFlag cond, CC cc, Register rs2, Register rd)2194     public void fmovdcc(ConditionFlag cond, CC cc, Register rs2, Register rd) {
2195         fmovcc(cond, cc, rs2, rd, OpfLow.Fmovdcc.value);
2196     }
2197 
fmovscc(ConditionFlag cond, CC cc, Register rs2, Register rd)2198     public void fmovscc(ConditionFlag cond, CC cc, Register rs2, Register rd) {
2199         fmovcc(cond, cc, rs2, rd, OpfLow.Fmovscc.value);
2200     }
2201 
fmovcc(ConditionFlag cond, CC cc, Register rs2, Register rd, int opfLow)2202     private void fmovcc(ConditionFlag cond, CC cc, Register rs2, Register rd, int opfLow) {
2203         int opfCC = cc.getOpfCCValue();
2204         int a = opfCC << 11 | opfLow << 5 | rs2.encoding;
2205         fmt10(rd.encoding, Fpop2.value, cond.value, a);
2206     }
2207 
movcc(ConditionFlag conditionFlag, CC cc, Register rs2, Register rd)2208     public void movcc(ConditionFlag conditionFlag, CC cc, Register rs2, Register rd) {
2209         movcc(conditionFlag, cc, 0, rs2.encoding, rd);
2210     }
2211 
movcc(ConditionFlag conditionFlag, CC cc, int simm11, Register rd)2212     public void movcc(ConditionFlag conditionFlag, CC cc, int simm11, Register rd) {
2213         assert isSimm11(simm11);
2214         movcc(conditionFlag, cc, 1, simm11 & ((1 << 11) - 1), rd);
2215     }
2216 
movcc(ConditionFlag conditionFlag, CC cc, int i, int imm, Register rd)2217     private void movcc(ConditionFlag conditionFlag, CC cc, int i, int imm, Register rd) {
2218         int cc01 = 0b11 & cc.value;
2219         int cc2 = cc.isFloat ? 0 : 1;
2220         int a = cc2 << 4 | conditionFlag.value;
2221         int b = cc01 << 11 | i << 13 | imm;
2222         fmt10(rd.encoding, Movcc.value, a, b);
2223     }
2224 
mulx(Register rs1, Register rs2, Register rd)2225     public void mulx(Register rs1, Register rs2, Register rd) {
2226         op3(Mulx, rs1, rs2, rd);
2227     }
2228 
mulx(Register rs1, int simm13, Register rd)2229     public void mulx(Register rs1, int simm13, Register rd) {
2230         op3(Mulx, rs1, simm13, rd);
2231     }
2232 
or(Register rs1, Register rs2, Register rd)2233     public void or(Register rs1, Register rs2, Register rd) {
2234         assert isCPURegister(rs1, rs2, rd) : String.format("%s %s %s", rs1, rs2, rd);
2235         op3(Or, rs1, rs2, rd);
2236     }
2237 
or(Register rs1, int simm13, Register rd)2238     public void or(Register rs1, int simm13, Register rd) {
2239         assert isCPURegister(rs1, rd) : String.format("%s %s", rs1, rd);
2240         op3(Or, rs1, simm13, rd);
2241     }
2242 
popc(Register rs2, Register rd)2243     public void popc(Register rs2, Register rd) {
2244         op3(Popc, g0, rs2, rd);
2245     }
2246 
popc(int simm13, Register rd)2247     public void popc(int simm13, Register rd) {
2248         op3(Popc, g0, simm13, rd);
2249     }
2250 
prefetch(SPARCAddress addr, Fcn fcn)2251     public void prefetch(SPARCAddress addr, Fcn fcn) {
2252         Register rs1 = addr.getBase();
2253         if (addr.getIndex().equals(Register.None)) {
2254             int dis = addr.getDisplacement();
2255             assert isSimm13(dis);
2256             fmt(Prefetch.op.value, fcn.value, Prefetch.value, rs1.encoding, 1 << 13 | dis & ((1 << 13) - 1));
2257         } else {
2258             Register rs2 = addr.getIndex();
2259             fmt(Prefetch.op.value, fcn.value, Prefetch.value, rs1.encoding, rs2.encoding);
2260         }
2261     }
2262 
2263     // A.44 Read State Register
2264 
rdpc(Register rd)2265     public void rdpc(Register rd) {
2266         op3(Rd, g5, g0, rd);
2267     }
2268 
restore(Register rs1, Register rs2, Register rd)2269     public void restore(Register rs1, Register rs2, Register rd) {
2270         op3(Restore, rs1, rs2, rd);
2271     }
2272 
2273     public static final int PC_RETURN_OFFSET = 8;
2274 
save(Register rs1, Register rs2, Register rd)2275     public void save(Register rs1, Register rs2, Register rd) {
2276         op3(Save, rs1, rs2, rd);
2277     }
2278 
save(Register rs1, int simm13, Register rd)2279     public void save(Register rs1, int simm13, Register rd) {
2280         op3(Save, rs1, simm13, rd);
2281     }
2282 
sdivx(Register rs1, Register rs2, Register rd)2283     public void sdivx(Register rs1, Register rs2, Register rd) {
2284         op3(Sdivx, rs1, rs2, rd);
2285     }
2286 
sdivx(Register rs1, int simm13, Register rd)2287     public void sdivx(Register rs1, int simm13, Register rd) {
2288         op3(Sdivx, rs1, simm13, rd);
2289     }
2290 
udivx(Register rs1, Register rs2, Register rd)2291     public void udivx(Register rs1, Register rs2, Register rd) {
2292         op3(Udivx, rs1, rs2, rd);
2293     }
2294 
udivx(Register rs1, int simm13, Register rd)2295     public void udivx(Register rs1, int simm13, Register rd) {
2296         op3(Udivx, rs1, simm13, rd);
2297     }
2298 
sll(Register rs1, Register rs2, Register rd)2299     public void sll(Register rs1, Register rs2, Register rd) {
2300         op3(Sll, rs1, rs2, rd);
2301     }
2302 
sll(Register rs1, int shcnt32, Register rd)2303     public void sll(Register rs1, int shcnt32, Register rd) {
2304         assert isImm(shcnt32, 5);
2305         op3(Sll, rs1, shcnt32, rd);
2306     }
2307 
sllx(Register rs1, Register rs2, Register rd)2308     public void sllx(Register rs1, Register rs2, Register rd) {
2309         op3(Sllx, rs1, rs2, rd);
2310     }
2311 
sllx(Register rs1, int shcnt64, Register rd)2312     public void sllx(Register rs1, int shcnt64, Register rd) {
2313         assert isImm(shcnt64, 6);
2314         op3(Sllx, rs1, shcnt64, rd);
2315     }
2316 
sra(Register rs1, Register rs2, Register rd)2317     public void sra(Register rs1, Register rs2, Register rd) {
2318         op3(Sra, rs1, rs2, rd);
2319     }
2320 
sra(Register rs1, int simm13, Register rd)2321     public void sra(Register rs1, int simm13, Register rd) {
2322         op3(Sra, rs1, simm13, rd);
2323     }
2324 
srax(Register rs1, Register rs2, Register rd)2325     public void srax(Register rs1, Register rs2, Register rd) {
2326         op3(Srax, rs1, rs2, rd);
2327     }
2328 
srax(Register rs1, int shcnt64, Register rd)2329     public void srax(Register rs1, int shcnt64, Register rd) {
2330         assert isImm(shcnt64, 6);
2331         op3(Srax, rs1, shcnt64, rd);
2332     }
2333 
srl(Register rs1, Register rs2, Register rd)2334     public void srl(Register rs1, Register rs2, Register rd) {
2335         op3(Srl, rs1, rs2, rd);
2336     }
2337 
srl(Register rs1, int simm13, Register rd)2338     public void srl(Register rs1, int simm13, Register rd) {
2339         op3(Srl, rs1, simm13, rd);
2340     }
2341 
srlx(Register rs1, Register rs2, Register rd)2342     public void srlx(Register rs1, Register rs2, Register rd) {
2343         op3(Srlx, rs1, rs2, rd);
2344     }
2345 
srlx(Register rs1, int shcnt64, Register rd)2346     public void srlx(Register rs1, int shcnt64, Register rd) {
2347         assert isImm(shcnt64, 6);
2348         op3(Srlx, rs1, shcnt64, rd);
2349     }
2350 
sub(Register rs1, Register rs2, Register rd)2351     public void sub(Register rs1, Register rs2, Register rd) {
2352         op3(Sub, rs1, rs2, rd);
2353     }
2354 
sub(Register rs1, int simm13, Register rd)2355     public void sub(Register rs1, int simm13, Register rd) {
2356         op3(Sub, rs1, simm13, rd);
2357     }
2358 
subcc(Register rs1, Register rs2, Register rd)2359     public void subcc(Register rs1, Register rs2, Register rd) {
2360         op3(Subcc, rs1, rs2, rd);
2361     }
2362 
subcc(Register rs1, int simm13, Register rd)2363     public void subcc(Register rs1, int simm13, Register rd) {
2364         op3(Subcc, rs1, simm13, rd);
2365     }
2366 
ta(int trap)2367     public void ta(int trap) {
2368         tcc(Icc, Always, trap);
2369     }
2370 
pause()2371     public void pause() {
2372         // Maybe fmt10(rd=0b1_1011, op3=0b11_0000, rs1=0, i=1, simm13=1), or
2373         // maybe op3(Wr, g0, 1, %pause).
2374         // What should the count be?
2375         GraalError.unimplemented("The SPARC pause instruction is not yet implemented.");
2376     }
2377 
tcc(CC cc, ConditionFlag flag, int trap)2378     public void tcc(CC cc, ConditionFlag flag, int trap) {
2379         assert isImm(trap, 8);
2380         int b = cc.value << 11;
2381         b |= 1 << 13;
2382         b |= trap;
2383         fmt10(flag.value, Op3s.Tcc.getValue(), 0, b);
2384     }
2385 
wrccr(Register rs1, Register rs2)2386     public void wrccr(Register rs1, Register rs2) {
2387         op3(Wr, rs1, rs2, g2);
2388     }
2389 
wrccr(Register rs1, int simm13)2390     public void wrccr(Register rs1, int simm13) {
2391         op3(Wr, rs1, simm13, g2);
2392     }
2393 
xor(Register rs1, Register rs2, Register rd)2394     public void xor(Register rs1, Register rs2, Register rd) {
2395         op3(Xor, rs1, rs2, rd);
2396     }
2397 
xor(Register rs1, int simm13, Register rd)2398     public void xor(Register rs1, int simm13, Register rd) {
2399         op3(Xor, rs1, simm13, rd);
2400     }
2401 
xorcc(Register rs1, Register rs2, Register rd)2402     public void xorcc(Register rs1, Register rs2, Register rd) {
2403         op3(Xorcc, rs1, rs2, rd);
2404     }
2405 
xorcc(Register rs1, int simm13, Register rd)2406     public void xorcc(Register rs1, int simm13, Register rd) {
2407         op3(Xorcc, rs1, simm13, rd);
2408     }
2409 
xnor(Register rs1, Register rs2, Register rd)2410     public void xnor(Register rs1, Register rs2, Register rd) {
2411         op3(Xnor, rs1, rs2, rd);
2412     }
2413 
xnor(Register rs1, int simm13, Register rd)2414     public void xnor(Register rs1, int simm13, Register rd) {
2415         op3(Xnor, rs1, simm13, rd);
2416     }
2417 
2418     /*
2419      * Load/Store
2420      */
ld(Op3s op3, SPARCAddress addr, Register rd, Asi asi)2421     protected void ld(Op3s op3, SPARCAddress addr, Register rd, Asi asi) {
2422         Register rs1 = addr.getBase();
2423         if (!addr.getIndex().equals(Register.None)) {
2424             Register rs2 = addr.getIndex();
2425             if (asi != null) {
2426                 int b = rs2.encoding;
2427                 b |= asi.value << 5;
2428                 fmt(op3.op.value, rd.encoding, op3.value, rs1.encoding, b);
2429             } else {
2430                 op3(op3, rs1, rs2, rd);
2431             }
2432         } else {
2433             int imm = addr.getDisplacement();
2434             op3(op3, rs1, imm, rd);
2435         }
2436     }
2437 
ld(Op3s op3, SPARCAddress addr, Register rd)2438     protected void ld(Op3s op3, SPARCAddress addr, Register rd) {
2439         ld(op3, addr, rd, null);
2440     }
2441 
lddf(SPARCAddress src, Register dst)2442     public void lddf(SPARCAddress src, Register dst) {
2443         assert isDoubleFloatRegister(dst) : dst;
2444         ld(Lddf, src, dst);
2445     }
2446 
ldf(SPARCAddress src, Register dst)2447     public void ldf(SPARCAddress src, Register dst) {
2448         assert isSingleFloatRegister(dst) : dst;
2449         ld(Ldf, src, dst);
2450     }
2451 
lduh(SPARCAddress src, Register dst)2452     public void lduh(SPARCAddress src, Register dst) {
2453         assert isCPURegister(dst) : dst;
2454         ld(Lduh, src, dst);
2455     }
2456 
ldsh(SPARCAddress src, Register dst)2457     public void ldsh(SPARCAddress src, Register dst) {
2458         assert isCPURegister(dst) : dst;
2459         ld(Ldsh, src, dst);
2460     }
2461 
ld(SPARCAddress src, Register dst, int bytes, boolean signExtend)2462     public void ld(SPARCAddress src, Register dst, int bytes, boolean signExtend) {
2463         if (isCPURegister(dst)) {
2464             if (signExtend) {
2465                 switch (bytes) {
2466                     case 1:
2467                         ld(Ldsb, src, dst);
2468                         break;
2469                     case 2:
2470                         ld(Ldsh, src, dst);
2471                         break;
2472                     case 4:
2473                         ld(Ldsw, src, dst);
2474                         break;
2475                     case 8:
2476                         ld(Ldx, src, dst);
2477                         break;
2478                     default:
2479                         throw new InternalError();
2480                 }
2481             } else {
2482                 switch (bytes) {
2483                     case 1:
2484                         ld(Ldub, src, dst);
2485                         break;
2486                     case 2:
2487                         ld(Lduh, src, dst);
2488                         break;
2489                     case 4:
2490                         ld(Lduw, src, dst);
2491                         break;
2492                     case 8:
2493                         ld(Ldx, src, dst);
2494                         break;
2495                     default:
2496                         throw new InternalError();
2497                 }
2498             }
2499         } else if (isDoubleFloatRegister(dst) && bytes == 8) {
2500             assert !signExtend;
2501             ld(Lddf, src, dst);
2502         } else if (isSingleFloatRegister(dst) && bytes == 4) {
2503             assert !signExtend;
2504             ld(Ldf, src, dst);
2505         } else {
2506             throw new InternalError(String.format("src: %s dst: %s bytes: %d signExtend: %b", src, dst, bytes, signExtend));
2507         }
2508     }
2509 
st(Register src, SPARCAddress dst, int bytes)2510     public void st(Register src, SPARCAddress dst, int bytes) {
2511         if (isCPURegister(src)) {
2512             switch (bytes) {
2513                 case 1:
2514                     st(Stb, src, dst);
2515                     break;
2516                 case 2:
2517                     st(Sth, src, dst);
2518                     break;
2519                 case 4:
2520                     st(Stw, src, dst);
2521                     break;
2522                 case 8:
2523                     st(Stx, src, dst);
2524                     break;
2525                 default:
2526                     throw new InternalError(Integer.toString(bytes));
2527             }
2528         } else if (isDoubleFloatRegister(src) && bytes == 8) {
2529             st(Stdf, src, dst);
2530         } else if (isSingleFloatRegister(src) && bytes == 4) {
2531             st(Stf, src, dst);
2532         } else {
2533             throw new InternalError(String.format("src: %s dst: %s bytes: %d", src, dst, bytes));
2534         }
2535     }
2536 
ldub(SPARCAddress src, Register dst)2537     public void ldub(SPARCAddress src, Register dst) {
2538         assert isCPURegister(dst) : dst;
2539         ld(Ldub, src, dst);
2540     }
2541 
ldsb(SPARCAddress src, Register dst)2542     public void ldsb(SPARCAddress src, Register dst) {
2543         assert isCPURegister(dst) : dst;
2544         ld(Ldsb, src, dst);
2545     }
2546 
lduw(SPARCAddress src, Register dst)2547     public void lduw(SPARCAddress src, Register dst) {
2548         assert isCPURegister(dst) : dst;
2549         ld(Lduw, src, dst);
2550     }
2551 
ldsw(SPARCAddress src, Register dst)2552     public void ldsw(SPARCAddress src, Register dst) {
2553         assert isCPURegister(dst) : dst;
2554         ld(Ldsw, src, dst);
2555     }
2556 
ldx(SPARCAddress src, Register dst)2557     public void ldx(SPARCAddress src, Register dst) {
2558         assert isCPURegister(dst) : dst;
2559         ld(Ldx, src, dst);
2560     }
2561 
ldxa(Register rs1, Register rs2, Register rd, Asi asi)2562     public void ldxa(Register rs1, Register rs2, Register rd, Asi asi) {
2563         assert isCPURegister(rs1, rs2, rd) : format("%s %s %s", rs1, rs2, rd);
2564         ld(Ldxa, new SPARCAddress(rs1, rs2), rd, asi);
2565     }
2566 
lduwa(Register rs1, Register rs2, Register rd, Asi asi)2567     public void lduwa(Register rs1, Register rs2, Register rd, Asi asi) {
2568         assert isCPURegister(rs1, rs2, rd) : format("%s %s %s", rs1, rs2, rd);
2569         ld(Lduwa, new SPARCAddress(rs1, rs2), rd, asi);
2570     }
2571 
stxa(Register rd, Register rs1, Register rs2, Asi asi)2572     public void stxa(Register rd, Register rs1, Register rs2, Asi asi) {
2573         assert isCPURegister(rs1, rs2, rd) : format("%s %s %s", rs1, rs2, rd);
2574         ld(Stxa, new SPARCAddress(rs1, rs2), rd, asi);
2575     }
2576 
st(Op3s op3, Register rs1, SPARCAddress dest)2577     protected void st(Op3s op3, Register rs1, SPARCAddress dest) {
2578         ld(op3, dest, rs1);
2579     }
2580 
stdf(Register rd, SPARCAddress addr)2581     public void stdf(Register rd, SPARCAddress addr) {
2582         assert isDoubleFloatRegister(rd) : rd;
2583         st(Stdf, rd, addr);
2584     }
2585 
stf(Register rd, SPARCAddress addr)2586     public void stf(Register rd, SPARCAddress addr) {
2587         assert isSingleFloatRegister(rd) : rd;
2588         st(Stf, rd, addr);
2589     }
2590 
stb(Register rd, SPARCAddress addr)2591     public void stb(Register rd, SPARCAddress addr) {
2592         assert isCPURegister(rd) : rd;
2593         st(Stb, rd, addr);
2594     }
2595 
sth(Register rd, SPARCAddress addr)2596     public void sth(Register rd, SPARCAddress addr) {
2597         assert isCPURegister(rd) : rd;
2598         st(Sth, rd, addr);
2599     }
2600 
stw(Register rd, SPARCAddress addr)2601     public void stw(Register rd, SPARCAddress addr) {
2602         assert isCPURegister(rd) : rd;
2603         st(Stw, rd, addr);
2604     }
2605 
stx(Register rd, SPARCAddress addr)2606     public void stx(Register rd, SPARCAddress addr) {
2607         assert isCPURegister(rd) : rd;
2608         st(Stx, rd, addr);
2609     }
2610 
membar(int barriers)2611     public void membar(int barriers) {
2612         op3(Membar, o7, barriers, g0);
2613     }
2614 
casa(Register rs1, Register rs2, Register rd, Asi asi)2615     public void casa(Register rs1, Register rs2, Register rd, Asi asi) {
2616         ld(Casa, new SPARCAddress(rs1, rs2), rd, asi);
2617     }
2618 
casxa(Register rs1, Register rs2, Register rd, Asi asi)2619     public void casxa(Register rs1, Register rs2, Register rd, Asi asi) {
2620         ld(Casxa, new SPARCAddress(rs1, rs2), rd, asi);
2621     }
2622 
2623     @Override
getInstructionCounter()2624     public InstructionCounter getInstructionCounter() {
2625         return new SPARCInstructionCounter(this);
2626     }
2627 
patchAddImmediate(int position, int simm13)2628     public void patchAddImmediate(int position, int simm13) {
2629         int inst = getInt(position);
2630         assert SPARCAssembler.isSimm13(simm13) : simm13;
2631         assert (inst >>> 30) == 0b10 : String.format("0x%x", inst);
2632         assert ((inst >>> 18) & 0b11_1111) == 0 : String.format("0x%x", inst);
2633         assert (inst & (1 << 13)) != 0 : String.format("0x%x", inst);
2634         inst = inst & (~((1 << 13) - 1));
2635         inst |= simm13 & ((1 << 12) - 1);
2636         emitInt(inst, position);
2637     }
2638 
fpadd32(Register rs1, Register rs2, Register rd)2639     public void fpadd32(Register rs1, Register rs2, Register rd) {
2640         op3(Impdep1, Fpadd32, rs1, rs2, rd);
2641     }
2642 
2643     /**
2644      * Does peephole optimization on code generated by this assembler. This method should be called
2645      * at the end of code generation.
2646      * <p>
2647      * It searches for conditional branch instructions which has nop in the delay slot then looks at
2648      * the instruction at branch target; if it is an arithmetic instruction, which does not throw an
2649      * exception (e.g. division), it pulls this instruction into the delay slot and increments the
2650      * displacement by 1.
2651      */
peephole()2652     public void peephole() {
2653         for (int i : delaySlotOptimizationPoints) {
2654             optimizeDelaySlot(i);
2655         }
2656     }
2657 
2658     /**
2659      * Optimizes branch instruction <i>b</t> which has a nop in the delay slot. It tries to stuff
2660      * the instruction at <i>b</i>s branch target into the delay slot of <i>b</i>, set the annul
2661      * flag and increments <i>b</i>s disp field by 1;
2662      * <p>
2663      * If <i>b</i>s branch target instruction is an unconditional branch <i>t</i>, then it tries to
2664      * put <i>t</i>s delayed instruction into the delay slot of <i>b</i> and add the <i>t</i>s disp
2665      * field to <i>b</i>s disp field.
2666      */
optimizeDelaySlot(int i)2667     private void optimizeDelaySlot(int i) {
2668         int delaySlotAbsolute = i + INSTRUCTION_SIZE;
2669         int nextInst = getInt(delaySlotAbsolute);
2670         SPARCOp nextOp = getSPARCOp(nextInst);
2671         if (nextOp instanceof Sethi && Sethi.isNop(nextInst)) {
2672             int inst = getInt(i);
2673             SPARCOp op = getSPARCOp(inst);
2674             if (op instanceof ControlTransferOp && ((ControlTransferOp) op).hasDelaySlot() && ((ControlTransferOp) op).isAnnulable(inst)) {
2675                 ControlTransferOp ctOp = (ControlTransferOp) op;
2676                 int disp = ctOp.getDisp(inst);
2677                 int branchTargetAbsolute = i + disp * INSTRUCTION_SIZE;
2678                 int branchTargetInst = getInt(branchTargetAbsolute);
2679                 SPARCOp branchTargetOp = getSPARCOp(branchTargetInst);
2680                 if (branchTargetOp instanceof Op3Op) {
2681                     Op3s op3 = ((Op3Op) branchTargetOp).getOp3(branchTargetInst);
2682                     if (!op3.throwsException()) {
2683                         inst = ctOp.setDisp(inst, disp + 1); // Increment the offset
2684                         inst = ctOp.setAnnul(inst, true);
2685                         emitInt(inst, i);
2686                         emitInt(branchTargetInst, delaySlotAbsolute);
2687                     }
2688                 } else if (branchTargetOp instanceof ControlTransferOp && !((ControlTransferOp) branchTargetOp).isConditional(branchTargetInst)) {
2689                     // If branchtarget is a unconditional branch
2690                     ControlTransferOp branchTargetOpBranch = (ControlTransferOp) branchTargetOp;
2691                     int btDisp = branchTargetOpBranch.getDisp(branchTargetInst);
2692                     int newDisp = disp + btDisp;
2693                     if (ctOp.isValidDisp(newDisp)) { // Test if we don't exceed field size
2694                         int instAfter = ctOp.setDisp(inst, newDisp);
2695                         instAfter = ctOp.setAnnul(instAfter, true);
2696                         branchTargetInst = getInt(branchTargetAbsolute + INSTRUCTION_SIZE);
2697                         branchTargetOp = getSPARCOp(branchTargetInst);
2698                         if (branchTargetOp instanceof Op3Op && !((Op3Op) branchTargetOp).getOp3(branchTargetInst).throwsException()) {
2699                             emitInt(instAfter, i);
2700                             emitInt(branchTargetInst, delaySlotAbsolute);
2701                         }
2702                     }
2703                 }
2704             }
2705         }
2706     }
2707 }
2708