1 /*
2  * Copyright (c) 2009, 2018, 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.Label;
140 import org.graalvm.compiler.core.common.NumUtil;
141 import org.graalvm.compiler.core.common.PermanentBailoutException;
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 
getOperator()631         public String getOperator() {
632             return operator;
633         }
634 
forKind(PlatformKind kind)635         public static CC forKind(PlatformKind kind) {
636             if (kind.equals(SPARCKind.XWORD)) {
637                 return Xcc;
638             } else if (kind.equals(SPARCKind.WORD)) {
639                 return Icc;
640             } else if (kind.equals(SPARCKind.SINGLE) || kind.equals(SPARCKind.DOUBLE)) {
641                 return Fcc0;
642             } else {
643                 throw new IllegalArgumentException("Unknown kind: " + kind);
644             }
645         }
646     }
647 
648     public enum ConditionFlag {
649         // @formatter:off
650 
651         // for FBfcc & FBPfcc instruction
652         F_Never(0, "f_never"),
653         F_NotEqual(1, "f_notEqual"),
654         F_LessOrGreater(2, "f_lessOrGreater"),
655         F_UnorderedOrLess(3, "f_unorderedOrLess"),
656         F_Less(4, "f_less"),
657         F_UnorderedOrGreater(5, "f_unorderedOrGreater"),
658         F_Greater(6, "f_greater"),
659         F_Unordered(7, "f_unordered"),
660         F_Always(8, "f_always"),
661         F_Equal(9, "f_equal"),
662         F_UnorderedOrEqual(10, "f_unorderedOrEqual"),
663         F_GreaterOrEqual(11, "f_greaterOrEqual"),
664         F_UnorderedGreaterOrEqual(12, "f_unorderedGreaterOrEqual"),
665         F_LessOrEqual(13, "f_lessOrEqual"),
666         F_UnorderedOrLessOrEqual(14, "f_unorderedOrLessOrEqual"),
667         F_Ordered(15, "f_ordered"),
668 
669         // for integers
670         Never(0, "never"),
671         Equal(1, "equal", true),
672         Zero(1, "zero"),
673         LessEqual(2, "lessEqual", true),
674         Less(3, "less", true),
675         LessEqualUnsigned(4, "lessEqualUnsigned", true),
676         LessUnsigned(5, "lessUnsigned", true),
677         CarrySet(5, "carrySet"),
678         Negative(6, "negative", true),
679         OverflowSet(7, "overflowSet", true),
680         Always(8, "always"),
681         NotEqual(9, "notEqual", true),
682         NotZero(9, "notZero"),
683         Greater(10, "greater", true),
684         GreaterEqual(11, "greaterEqual", true),
685         GreaterUnsigned(12, "greaterUnsigned", true),
686         GreaterEqualUnsigned(13, "greaterEqualUnsigned", true),
687         CarryClear(13, "carryClear"),
688         Positive(14, "positive", true),
689         OverflowClear(15, "overflowClear", true);
690 
691         // @formatter:on
692 
693         private final int value;
694         private final String operator;
695         private boolean forCBcond = false;
696 
ConditionFlag(int value, String op)697         ConditionFlag(int value, String op) {
698             this(value, op, false);
699         }
700 
ConditionFlag(int value, String op, boolean cbcond)701         ConditionFlag(int value, String op, boolean cbcond) {
702             this.value = value;
703             this.operator = op;
704             this.forCBcond = cbcond;
705         }
706 
isCBCond()707         public boolean isCBCond() {
708             return forCBcond;
709         }
710 
getValue()711         public int getValue() {
712             return value;
713         }
714 
getOperator()715         public String getOperator() {
716             return operator;
717         }
718 
negate()719         public ConditionFlag negate() {
720             //@formatter:off
721             switch (this) {
722                 case F_Never                  : return F_Always;
723                 case F_Always                 : return F_Never;
724                 case F_NotEqual               : return F_Equal;
725                 case F_Equal                  : return F_NotEqual;
726                 case F_LessOrGreater          : return F_UnorderedOrEqual;
727                 case F_UnorderedOrEqual       : return F_LessOrGreater;
728                 case F_Less                   : return F_UnorderedGreaterOrEqual;
729                 case F_UnorderedGreaterOrEqual: return F_Less;
730                 case F_LessOrEqual            : return F_UnorderedOrGreater;
731                 case F_UnorderedOrGreater     : return F_LessOrEqual;
732                 case F_Greater                : return F_UnorderedOrLessOrEqual;
733                 case F_UnorderedOrLessOrEqual : return F_Greater;
734                 case F_GreaterOrEqual         : return F_UnorderedOrLess;
735                 case F_UnorderedOrLess        : return F_GreaterOrEqual;
736                 case F_Unordered              : return F_Ordered;
737                 case F_Ordered                : return F_Unordered;
738                 case Never                    : return Always;
739                 case Always                   : return Never;
740                 case Equal                    : return NotEqual;
741                 case NotEqual                 : return Equal;
742                 case Zero                     : return NotZero;
743                 case NotZero                  : return Zero;
744                 case LessEqual                : return Greater;
745                 case Greater                  : return LessEqual;
746                 case Less                     : return GreaterEqual;
747                 case GreaterEqual             : return Less;
748                 case LessEqualUnsigned        : return GreaterUnsigned;
749                 case GreaterUnsigned          : return LessEqualUnsigned;
750                 case LessUnsigned             : return GreaterEqualUnsigned;
751                 case GreaterEqualUnsigned     : return LessUnsigned;
752                 case CarrySet                 : return CarryClear;
753                 case CarryClear               : return CarrySet;
754                 case Negative                 : return Positive;
755                 case Positive                 : return Negative;
756                 case OverflowSet              : return OverflowClear;
757                 case OverflowClear            : return OverflowSet;
758                 default:
759                     throw new InternalError();
760             }
761             //@formatter:on
762         }
763 
mirror()764         public ConditionFlag mirror() {
765             switch (this) {
766             //@formatter:off
767                 case F_Less                   : return F_Greater;
768                 case F_Greater                : return F_Less;
769                 case F_LessOrEqual            : return F_GreaterOrEqual;
770                 case F_UnorderedGreaterOrEqual: return F_UnorderedOrLessOrEqual;
771                 case F_UnorderedOrGreater     : return F_UnorderedOrLess;
772                 case F_UnorderedOrLessOrEqual : return F_UnorderedGreaterOrEqual;
773                 case F_GreaterOrEqual         : return F_LessOrEqual;
774                 case F_UnorderedOrLess        : return F_UnorderedOrGreater;
775                 case LessEqual                : return GreaterEqual;
776                 case Greater                  : return Less;
777                 case Less                     : return Greater;
778                 case GreaterEqual             : return LessEqual;
779                 case LessEqualUnsigned        : return GreaterEqualUnsigned;
780                 case GreaterUnsigned          : return LessUnsigned;
781                 case LessUnsigned             : return GreaterUnsigned;
782                 case GreaterEqualUnsigned     : return LessEqualUnsigned;
783                 default:
784                     return this;
785                 //@formatter:on
786             }
787         }
788 
789     }
790 
791     public enum RCondition {
792         // @formatter:off
793 
794         Rc_z(0b001, "rc_z"),
795         Rc_lez(0b010, "rc_lez"),
796         Rc_lz(0b011, "rc_lz"),
797         Rc_nz(0b101, "rc_nz"),
798         Rc_gz(0b110, "rc_gz"),
799         Rc_gez(0b111, "rc_gez"),
800         Rc_last(Rc_gez.getValue(), "rc_last");
801 
802         // @formatter:on
803 
804         private final int value;
805         private final String operator;
806 
RCondition(int value, String op)807         RCondition(int value, String op) {
808             this.value = value;
809             this.operator = op;
810         }
811 
getValue()812         public int getValue() {
813             return value;
814         }
815 
getOperator()816         public String getOperator() {
817             return operator;
818         }
819     }
820 
821     /**
822      * Represents the <b>Address Space Identifier</b> defined in the SPARC architecture.
823      */
824     public enum Asi {
825         // @formatter:off
826 
827         INVALID(-1),
828         ASI_PRIMARY(0x80),
829         ASI_PRIMARY_NOFAULT(0x82),
830         ASI_PRIMARY_LITTLE(0x88),
831         // Block initializing store
832         ASI_ST_BLKINIT_PRIMARY(0xE2),
833         // Most-Recently-Used (MRU) BIS variant
834         ASI_ST_BLKINIT_MRU_PRIMARY(0xF2);
835 
836         // @formatter:on
837 
838         private final int value;
839 
Asi(int value)840         Asi(int value) {
841             this.value = value;
842         }
843 
getValue()844         public int getValue() {
845             return value;
846         }
847 
isValid()848         public boolean isValid() {
849             return value != INVALID.getValue();
850         }
851     }
852 
853     public enum Fcn {
854         SeveralWritesAndPossiblyReads(2),
855         SeveralReadsWeak(0),
856         OneRead(1),
857         OneWrite(3),
858         Page(4),
859         NearestUnifiedCache(17),
860         SeveralReadsStrong(20),
861         OneReadStrong(21),
862         SeveralWritesAndPossiblyReadsStrong(22),
863         OneWriteStrong(23);
864 
865         private final int value;
866 
Fcn(int value)867         Fcn(int value) {
868             this.value = value;
869         }
870 
getValue()871         public int getValue() {
872             return value;
873         }
874     }
875 
876     /**
877      * Specifies various bit fields used in SPARC instructions.
878      */
879     @SuppressWarnings("unused")
880     public abstract static class BitSpec {
881         private static final BitSpec op = new ContinousBitSpec(31, 30, "op");
882         private static final BitSpec op2 = new ContinousBitSpec(24, 22, "op2");
883         private static final BitSpec op3 = new ContinousBitSpec(24, 19, "op3");
884         private static final BitSpec opf = new ContinousBitSpec(13, 5, "opf");
885         private static final BitSpec opfLow = new ContinousBitSpec(10, 5, "opfLow");
886         private static final BitSpec opfCC = new ContinousBitSpec(13, 11, "opfCC");
887         private static final BitSpec opfCond = new ContinousBitSpec(17, 14, "opfCond");
888         private static final BitSpec rd = new ContinousBitSpec(29, 25, "rd");
889         private static final BitSpec rs1 = new ContinousBitSpec(18, 14, "rs1");
890         private static final BitSpec rs2 = new ContinousBitSpec(4, 0, "rs2");
891         private static final BitSpec simm13 = new ContinousBitSpec(12, 0, true, "simm13");
892         private static final BitSpec shcnt32 = new ContinousBitSpec(4, 0, "shcnt32");
893         private static final BitSpec shcnt64 = new ContinousBitSpec(5, 0, "shcnt64");
894         private static final BitSpec imm22 = new ContinousBitSpec(21, 0, "imm22");
895         private static final BitSpec immAsi = new ContinousBitSpec(12, 5, "immASI");
896         private static final BitSpec i = new ContinousBitSpec(13, 13, "i");
897         private static final BitSpec disp19 = new ContinousBitSpec(18, 0, true, "disp19");
898         private static final BitSpec disp22 = new ContinousBitSpec(21, 0, true, "disp22");
899         private static final BitSpec disp30 = new ContinousBitSpec(29, 0, true, "disp30");
900         private static final BitSpec a = new ContinousBitSpec(29, 29, "a");
901         private static final BitSpec p = new ContinousBitSpec(19, 19, "p");
902         private static final BitSpec x = new ContinousBitSpec(12, 12, "x");
903         private static final BitSpec cond = new ContinousBitSpec(28, 25, "cond");
904         private static final BitSpec rcond = new ContinousBitSpec(27, 25, "rcond");
905         private static final BitSpec cc = new ContinousBitSpec(21, 20, "cc");
906         private static final BitSpec fcc = new ContinousBitSpec(26, 25, "cc");
907         private static final BitSpec d16lo = new ContinousBitSpec(13, 0, "d16lo");
908         private static final BitSpec d16hi = new ContinousBitSpec(21, 20, true, "d16hi");
909         private static final BitSpec d16 = new CompositeBitSpec(d16hi, d16lo);
910         // Movcc
911         private static final BitSpec movccLo = new ContinousBitSpec(12, 11, "cc_lo");
912         private static final BitSpec movccHi = new ContinousBitSpec(18, 18, "cc_hi");
913         private static final BitSpec movccCond = new ContinousBitSpec(17, 14, "cond");
914         private static final BitSpec simm11 = new ContinousBitSpec(10, 0, true, "simm11");
915 
916         // CBCond
917         private static final BitSpec cLo = new ContinousBitSpec(27, 25, "cLo");
918         private static final BitSpec cHi = new ContinousBitSpec(29, 29, "cHi");
919         private static final BitSpec c = new CompositeBitSpec(cHi, cLo);
920         private static final BitSpec cbcond = new ContinousBitSpec(28, 28, "cbcond");
921         private static final BitSpec cc2 = new ContinousBitSpec(21, 21, "cc2");
922         private static final BitSpec d10Lo = new ContinousBitSpec(12, 5, "d10Lo");
923         private static final BitSpec d10Hi = new ContinousBitSpec(20, 19, true, "d10Hi");
924         private static final BitSpec d10 = new CompositeBitSpec(d10Hi, d10Lo);
925         private static final BitSpec simm5 = new ContinousBitSpec(4, 0, true, "simm5");
926 
927         protected final boolean signExtend;
928 
BitSpec(boolean signExtend)929         public BitSpec(boolean signExtend) {
930             super();
931             this.signExtend = signExtend;
932         }
933 
isSignExtend()934         public final boolean isSignExtend() {
935             return signExtend;
936         }
937 
setBits(int word, int value)938         public abstract int setBits(int word, int value);
939 
getBits(int word)940         public abstract int getBits(int word);
941 
getWidth()942         public abstract int getWidth();
943 
valueFits(int value)944         public abstract boolean valueFits(int value);
945     }
946 
947     public static final class ContinousBitSpec extends BitSpec {
948         private final int hiBit;
949         private final int lowBit;
950         private final int width;
951         private final int mask;
952         private final String name;
953 
ContinousBitSpec(int hiBit, int lowBit, String name)954         public ContinousBitSpec(int hiBit, int lowBit, String name) {
955             this(hiBit, lowBit, false, name);
956         }
957 
ContinousBitSpec(int hiBit, int lowBit, boolean signExt, String name)958         public ContinousBitSpec(int hiBit, int lowBit, boolean signExt, String name) {
959             super(signExt);
960             this.hiBit = hiBit;
961             this.lowBit = lowBit;
962             this.width = hiBit - lowBit + 1;
963             mask = ((1 << width) - 1) << lowBit;
964             this.name = name;
965         }
966 
967         @Override
setBits(int word, int value)968         public int setBits(int word, int value) {
969             assert valueFits(value) : String.format("Value 0x%x for field %s does not fit.", value, this);
970             return (word & ~mask) | ((value << lowBit) & mask);
971         }
972 
973         @Override
getBits(int word)974         public int getBits(int word) {
975             if (signExtend) {
976                 return ((word & mask) << (31 - hiBit)) >> (32 - width);
977             } else {
978                 return (word & mask) >>> lowBit;
979             }
980         }
981 
982         @Override
getWidth()983         public int getWidth() {
984             return width;
985         }
986 
987         @Override
toString()988         public String toString() {
989             return String.format("%s [%d:%d]", name, hiBit, lowBit);
990         }
991 
992         @Override
valueFits(int value)993         public boolean valueFits(int value) {
994             if (signExtend) {
995                 return isSimm(value, getWidth());
996             } else {
997                 return isImm(value, getWidth());
998             }
999         }
1000     }
1001 
1002     public static final class CompositeBitSpec extends BitSpec {
1003         private final BitSpec left;
1004         private final int leftWidth;
1005         private final BitSpec right;
1006         private final int rightWidth;
1007         private final int width;
1008 
CompositeBitSpec(BitSpec left, BitSpec right)1009         public CompositeBitSpec(BitSpec left, BitSpec right) {
1010             super(left.isSignExtend());
1011             assert !right.isSignExtend() : String.format("Right field %s must not be sign extended", right);
1012             this.left = left;
1013             this.leftWidth = left.getWidth();
1014             this.right = right;
1015             this.rightWidth = right.getWidth();
1016             this.width = leftWidth + rightWidth;
1017         }
1018 
1019         @Override
getBits(int word)1020         public int getBits(int word) {
1021             int l = left.getBits(word);
1022             int r = right.getBits(word);
1023             return (l << rightWidth) | r;
1024         }
1025 
1026         @Override
setBits(int word, int value)1027         public int setBits(int word, int value) {
1028             int l = leftBits(value);
1029             int r = rightBits(value);
1030             return left.setBits(right.setBits(word, r), l);
1031         }
1032 
leftBits(int value)1033         private int leftBits(int value) {
1034             return getBits(value, width - 1, rightWidth, signExtend);
1035         }
1036 
rightBits(int value)1037         private int rightBits(int value) {
1038             return getBits(value, rightWidth - 1, 0, false);
1039         }
1040 
1041         @Override
getWidth()1042         public int getWidth() {
1043             return width;
1044         }
1045 
1046         @Override
toString()1047         public String toString() {
1048             return String.format("CompositeBitSpec[%s, %s]", left, right);
1049         }
1050 
1051         @Override
valueFits(int value)1052         public boolean valueFits(int value) {
1053             int l = leftBits(value);
1054             int r = rightBits(value);
1055             return left.valueFits(l) && right.valueFits(r);
1056         }
1057 
getBits(int inst, int hiBit, int lowBit, boolean signExtended)1058         private static int getBits(int inst, int hiBit, int lowBit, boolean signExtended) {
1059             int shifted = inst >> lowBit;
1060             if (signExtended) {
1061                 return shifted;
1062             } else {
1063                 return shifted & ((1 << (hiBit - lowBit + 1)) - 1);
1064             }
1065         }
1066     }
1067 
1068     public static class BitKey {
1069         private final BitSpec spec;
1070         private final int value;
1071 
BitKey(BitSpec spec, int value)1072         public BitKey(BitSpec spec, int value) {
1073             super();
1074             this.spec = spec;
1075             this.value = value;
1076         }
1077 
1078         @Override
toString()1079         public String toString() {
1080             return String.format("BitKey %s=%s", spec, value);
1081         }
1082     }
1083 
1084     /**
1085      * Represents a prefix tree of {@link BitSpec} objects to find the most accurate SPARCOp.
1086      */
1087     public static final class BitKeyIndex {
1088         private final BitSpec spec;
1089         private final Map<Integer, BitKeyIndex> nodes;
1090         private SPARCOp op;
1091 
BitKeyIndex(SPARCOp op)1092         public BitKeyIndex(SPARCOp op) {
1093             assert op != null;
1094             this.op = op;
1095             this.nodes = null;
1096             this.spec = null;
1097         }
1098 
BitKeyIndex(BitSpec spec)1099         public BitKeyIndex(BitSpec spec) {
1100             assert spec != null;
1101             this.op = null;
1102             this.nodes = new HashMap<>(4);
1103             this.spec = spec;
1104         }
1105 
1106         /**
1107          * Adds operation to the index.
1108          *
1109          * @param keys Ordered by the importance
1110          * @param operation Operation represented by this list of keys
1111          */
addOp(List<BitKey[]> keys, SPARCOp operation)1112         private void addOp(List<BitKey[]> keys, SPARCOp operation) {
1113             assert keys.size() > 0;
1114             BitKey[] firstKeys = keys.get(0);
1115             for (BitKey first : firstKeys) {
1116                 assert first.spec.equals(spec) : first.spec + " " + spec;
1117                 BitKeyIndex node;
1118                 if (keys.size() == 1) {
1119                     if (nodes.containsKey(first.value)) {
1120                         node = nodes.get(first.value);
1121                         assert node.op == null : node + " " + keys;
1122                         node.op = operation;
1123                     } else {
1124                         assert !nodes.containsKey(first.value) : "Index must be unique. Existing key: " + nodes.get(first.value);
1125                         node = new BitKeyIndex(operation);
1126                     }
1127                 } else {
1128                     node = nodes.get(first.value);
1129                     BitKey[] next = keys.get(1);
1130                     if (node == null) {
1131                         for (int i = 1; i < next.length; i++) {
1132                             assert next[i - 1].spec.equals(next[i].spec) : "All spec on this node must equal";
1133                         }
1134                         node = new BitKeyIndex(next[0].spec);
1135                     }
1136                     node.addOp(keys.subList(1, keys.size()), operation);
1137                 }
1138                 nodes.put(first.value, node);
1139             }
1140         }
1141 
1142         /**
1143          * Finds the best matching {@link SPARCOp} for this instruction.
1144          */
find(int inst)1145         public SPARCOp find(int inst) {
1146             if (nodes != null) {
1147                 int key = spec.getBits(inst);
1148                 BitKeyIndex sub = nodes.get(key);
1149                 if (sub == null) {
1150                     if (op != null) {
1151                         return op;
1152                     } else {
1153                         throw new RuntimeException(String.format("%s 0x%x, 0x%x %s", spec, inst, key, nodes));
1154                     }
1155                 }
1156                 return sub.find(inst);
1157             } else {
1158                 return this.op;
1159             }
1160         }
1161 
1162         @Override
toString()1163         public String toString() {
1164             return this.op == null ? this.spec + ": " + this.nodes : this.op.toString();
1165         }
1166     }
1167 
1168     public static final Bpcc BPCC = new Bpcc(Op2s.Bp);
1169     public static final Bpcc FBPCC = new Bpcc(Op2s.Fbp);
1170     public static final CBCond CBCOND = new CBCond();
1171     public static final Bpr BPR = new Bpr();
1172     public static final Br BR = new Br();
1173     public static final Sethi SETHI = new Sethi();
1174     public static final FMOVcc FMOVSCC = new FMOVcc(OpfLow.Fmovscc);
1175     public static final FMOVcc FMOVDCC = new FMOVcc(OpfLow.Fmovdcc);
1176     public static final MOVicc MOVICC = new MOVicc();
1177     public static final OpfOp OPF = new OpfOp();
1178     public static final Op3Op OP3 = new Op3Op();
1179     public static final SPARCOp LDST = new SPARCOp(Ops.LdstOp);
1180     public static final SPARCOp BRANCH = new SPARCOp(Ops.BranchOp);
1181     public static final SPARCOp CALL = new SPARCOp(Ops.CallOp);
1182     private static final BitKeyIndex INDEX = new BitKeyIndex(BitSpec.op);
1183 
1184     static {
1185         for (SPARCOp op : SPARCOp.OPS) {
op.getKeys()1186             INDEX.addOp(op.getKeys(), op);
1187         }
1188     }
1189 
getSPARCOp(int inst)1190     public static SPARCOp getSPARCOp(int inst) {
1191         return INDEX.find(inst);
1192     }
1193 
1194     /**
1195      * Represents a class of SPARC instruction and gives methods to modify its fields.
1196      */
1197     public static class SPARCOp {
1198         private final Ops op;
1199         private final BitKey opKey;
1200         private List<BitKey[]> keyFields;
1201         private static final List<SPARCOp> OPS = new ArrayList<>();
1202 
SPARCOp(Ops op)1203         public SPARCOp(Ops op) {
1204             super();
1205             this.op = op;
1206             this.opKey = new BitKey(BitSpec.op, op.value);
1207             OPS.add(this);
1208         }
1209 
setBits(int word)1210         protected int setBits(int word) {
1211             return BitSpec.op.setBits(word, op.value);
1212         }
1213 
match(int inst)1214         public boolean match(int inst) {
1215             for (BitKey[] keys : keyFields) {
1216                 for (BitKey k : keys) {
1217                     if (k.spec.getBits(inst) != k.value) {
1218                         return false;
1219                     }
1220                 }
1221             }
1222             return true;
1223         }
1224 
getKeys()1225         protected List<BitKey[]> getKeys() {
1226             if (keyFields == null) {
1227                 keyFields = new ArrayList<>(4);
1228                 keyFields.add(new BitKey[]{opKey});
1229             }
1230             return keyFields;
1231         }
1232 
getOp(int inst)1233         public Ops getOp(int inst) {
1234             return SPARCAssembler.OPS[BitSpec.op.getBits(inst)];
1235         }
1236 
1237         @Override
toString()1238         public String toString() {
1239             String name = getClass().getName();
1240             name = name.substring(name.lastIndexOf(".") + 1);
1241             return name + "[op: " + op + "]";
1242         }
1243     }
1244 
1245     /**
1246      * Base class for control transfer operations; provides access to the disp field.
1247      */
1248     public abstract static class ControlTransferOp extends SPARCOp {
1249         private final Op2s op2;
1250         private final boolean delaySlot;
1251         private final BitSpec disp;
1252         private final BitKey[] op2Key;
1253 
ControlTransferOp(Ops op, Op2s op2, boolean delaySlot, BitSpec disp)1254         private ControlTransferOp(Ops op, Op2s op2, boolean delaySlot, BitSpec disp) {
1255             super(op);
1256             this.op2 = op2;
1257             this.delaySlot = delaySlot;
1258             this.disp = disp;
1259             this.op2Key = new BitKey[]{new BitKey(BitSpec.op2, op2.value)};
1260         }
1261 
hasDelaySlot()1262         public boolean hasDelaySlot() {
1263             return delaySlot;
1264         }
1265 
1266         @Override
setBits(int word)1267         protected int setBits(int word) {
1268             return BitSpec.op2.setBits(super.setBits(word), op2.value);
1269         }
1270 
setDisp(int inst, SPARCMacroAssembler masm, Label lab)1271         protected int setDisp(int inst, SPARCMacroAssembler masm, Label lab) {
1272             if (lab.isBound()) {
1273                 int d = (lab.position() - masm.position()) / 4;
1274                 return setDisp(inst, d);
1275             } else {
1276                 masm.patchUnbound(lab);
1277                 return inst;
1278             }
1279         }
1280 
setDisp(int inst, int d)1281         public int setDisp(int inst, int d) {
1282             assert this.match(inst);
1283             if (!isValidDisp(d)) {
1284                 throw new PermanentBailoutException("Too large displacement 0x%x in field %s in instruction %s", d, this.disp, this);
1285             }
1286             return this.disp.setBits(inst, d);
1287         }
1288 
isValidDisp(int d)1289         public boolean isValidDisp(int d) {
1290             return this.disp.valueFits(d);
1291         }
1292 
setAnnul(int inst, boolean a)1293         public int setAnnul(int inst, boolean a) {
1294             return BitSpec.a.setBits(inst, a ? 1 : 0);
1295         }
1296 
1297         @Override
getKeys()1298         protected List<BitKey[]> getKeys() {
1299             List<BitKey[]> keys = super.getKeys();
1300             keys.add(op2Key);
1301             return keys;
1302         }
1303 
getDisp(int inst)1304         public int getDisp(int inst) {
1305             return this.disp.getBits(inst);
1306         }
1307 
isAnnulable(int inst)1308         public abstract boolean isAnnulable(int inst);
1309 
isConditional(int inst)1310         public abstract boolean isConditional(int inst);
1311     }
1312 
1313     public static final class Bpcc extends ControlTransferOp {
Bpcc(Op2s op2)1314         public Bpcc(Op2s op2) {
1315             super(Ops.BranchOp, op2, true, BitSpec.disp19);
1316         }
1317 
emit(SPARCMacroAssembler masm, CC cc, ConditionFlag cf, Annul annul, BranchPredict p, Label lab)1318         public void emit(SPARCMacroAssembler masm, CC cc, ConditionFlag cf, Annul annul, BranchPredict p, Label lab) {
1319             int inst = setBits(0);
1320             inst = BitSpec.a.setBits(inst, annul.flag);
1321             inst = BitSpec.cond.setBits(inst, cf.value);
1322             inst = BitSpec.cc.setBits(inst, cc.value);
1323             inst = BitSpec.p.setBits(inst, p.flag);
1324             masm.insertNopAfterCBCond();
1325             masm.emitInt(setDisp(inst, masm, lab));
1326         }
1327 
1328         @Override
isAnnulable(int inst)1329         public boolean isAnnulable(int inst) {
1330             return isConditional(inst);
1331         }
1332 
1333         @Override
isConditional(int inst)1334         public boolean isConditional(int inst) {
1335             int cond = BitSpec.cond.getBits(inst);
1336             return cond != ConditionFlag.Always.value && cond != ConditionFlag.Never.value;
1337         }
1338     }
1339 
1340     public static final class Br extends ControlTransferOp {
Br()1341         public Br() {
1342             super(Ops.BranchOp, Op2s.Br, true, BitSpec.disp22);
1343         }
1344 
1345         @Override
isAnnulable(int inst)1346         public boolean isAnnulable(int inst) {
1347             return isConditional(inst);
1348         }
1349 
1350         @Override
isConditional(int inst)1351         public boolean isConditional(int inst) {
1352             int cond = BitSpec.cond.getBits(inst);
1353             return cond != ConditionFlag.Always.value && cond != ConditionFlag.Never.value;
1354         }
1355 
emit(SPARCMacroAssembler masm, ConditionFlag cond, Annul a, Label lab)1356         public void emit(SPARCMacroAssembler masm, ConditionFlag cond, Annul a, Label lab) {
1357             int inst = setBits(0);
1358             inst = BitSpec.cond.setBits(inst, cond.value);
1359             inst = BitSpec.a.setBits(inst, a.flag);
1360             masm.insertNopAfterCBCond();
1361             masm.emitInt(setDisp(inst, masm, lab));
1362         }
1363     }
1364 
1365     public static final class Bpr extends ControlTransferOp {
1366         private static final BitKey CBCOND_KEY = new BitKey(BitSpec.cbcond, 0);
1367 
Bpr()1368         public Bpr() {
1369             super(Ops.BranchOp, Op2s.Bpr, true, BitSpec.d16);
1370         }
1371 
emit(SPARCMacroAssembler masm, RCondition rcond, Annul a, BranchPredict p, Register rs1, Label lab)1372         public void emit(SPARCMacroAssembler masm, RCondition rcond, Annul a, BranchPredict p, Register rs1, Label lab) {
1373             int inst = setBits(0);
1374             inst = BitSpec.rcond.setBits(inst, rcond.value);
1375             inst = BitSpec.a.setBits(inst, a.flag);
1376             inst = BitSpec.p.setBits(inst, p.flag);
1377             inst = BitSpec.rs1.setBits(inst, rs1.encoding);
1378             masm.insertNopAfterCBCond();
1379             masm.emitInt(setDisp(inst, masm, lab));
1380         }
1381 
1382         @Override
getKeys()1383         protected List<BitKey[]> getKeys() {
1384             List<BitKey[]> keys = super.getKeys();
1385             keys.add(new BitKey[]{CBCOND_KEY});
1386             return keys;
1387         }
1388 
1389         @Override
isAnnulable(int inst)1390         public boolean isAnnulable(int inst) {
1391             return isConditional(inst);
1392         }
1393 
1394         @Override
isConditional(int inst)1395         public boolean isConditional(int inst) {
1396             int cond = BitSpec.cond.getBits(inst);
1397             return cond != ConditionFlag.Always.value && cond != ConditionFlag.Never.value;
1398         }
1399     }
1400 
1401     public static final class CBCond extends ControlTransferOp {
1402         private static final BitKey CBCOND_KEY = new BitKey(BitSpec.cbcond, 1);
1403 
CBCond()1404         private CBCond() {
1405             super(Ops.BranchOp, Op2s.Bpr, false, BitSpec.d10);
1406         }
1407 
1408         @Override
getKeys()1409         protected List<BitKey[]> getKeys() {
1410             List<BitKey[]> keys = super.getKeys();
1411             keys.add(new BitKey[]{CBCOND_KEY});
1412             return keys;
1413         }
1414 
emit(SPARCMacroAssembler masm, ConditionFlag cf, boolean cc2, Register rs1, Register rs2, Label lab)1415         public void emit(SPARCMacroAssembler masm, ConditionFlag cf, boolean cc2, Register rs1, Register rs2, Label lab) {
1416             int inst = setBits(0, cf, cc2, rs1);
1417             inst = BitSpec.rs2.setBits(inst, rs2.encoding);
1418             inst = BitSpec.i.setBits(inst, 0);
1419             masm.insertNopAfterCBCond();
1420             emit(masm, lab, inst);
1421         }
1422 
emit(SPARCMacroAssembler masm, ConditionFlag cf, boolean cc2, Register rs1, int simm5, Label lab)1423         public void emit(SPARCMacroAssembler masm, ConditionFlag cf, boolean cc2, Register rs1, int simm5, Label lab) {
1424             int inst = setBits(0, cf, cc2, rs1);
1425             inst = BitSpec.simm5.setBits(inst, simm5);
1426             inst = BitSpec.i.setBits(inst, 1);
1427             emit(masm, lab, inst);
1428         }
1429 
emit(SPARCMacroAssembler masm, Label lab, int baseInst)1430         private void emit(SPARCMacroAssembler masm, Label lab, int baseInst) {
1431             int inst = baseInst;
1432             masm.insertNopAfterCBCond();
1433             masm.emitInt(setDisp(inst, masm, lab));
1434         }
1435 
setBits(int base, ConditionFlag cf, boolean cc2, Register rs1)1436         private int setBits(int base, ConditionFlag cf, boolean cc2, Register rs1) {
1437             int inst = super.setBits(base);
1438             inst = BitSpec.rs1.setBits(inst, rs1.encoding);
1439             inst = BitSpec.cc2.setBits(inst, cc2 ? 1 : 0);
1440             inst = BitSpec.c.setBits(inst, cf.value);
1441             return BitSpec.cbcond.setBits(inst, 1);
1442         }
1443 
1444         @Override
isAnnulable(int inst)1445         public boolean isAnnulable(int inst) {
1446             return false;
1447         }
1448 
1449         @Override
isConditional(int inst)1450         public boolean isConditional(int inst) {
1451             return true;
1452         }
1453     }
1454 
1455     public static class Op2Op extends SPARCOp {
1456         private final Op2s op2;
1457         private final BitKey op2Key;
1458 
Op2Op(Ops op, Op2s op2)1459         public Op2Op(Ops op, Op2s op2) {
1460             super(op);
1461             this.op2 = op2;
1462             op2Key = new BitKey(BitSpec.op2, op2.value);
1463         }
1464 
1465         @Override
setBits(int word)1466         protected int setBits(int word) {
1467             int result = super.setBits(word);
1468             return BitSpec.op2.setBits(result, op2.value);
1469         }
1470 
1471         @Override
getKeys()1472         protected List<BitKey[]> getKeys() {
1473             List<BitKey[]> keys = super.getKeys();
1474             keys.add(new BitKey[]{op2Key});
1475             return keys;
1476         }
1477     }
1478 
1479     public static final class Sethi extends Op2Op {
Sethi()1480         public Sethi() {
1481             super(Ops.BranchOp, Op2s.Sethi);
1482         }
1483 
getRS1(int word)1484         public static Register getRS1(int word) {
1485             int regNum = BitSpec.rs1.getBits(word);
1486             return SPARC.cpuRegisters.get(regNum);
1487         }
1488 
getImm22(int word)1489         public static int getImm22(int word) {
1490             return BitSpec.imm22.getBits(word);
1491         }
1492 
isNop(int inst)1493         public static boolean isNop(int inst) {
1494             return getRS1(inst).equals(g0) && getImm22(inst) == 0;
1495         }
1496     }
1497 
1498     public static final class Op3Op extends SPARCOp {
Op3Op()1499         public Op3Op() {
1500             super(ArithOp);
1501         }
1502 
getOp3(int inst)1503         public Op3s getOp3(int inst) {
1504             assert match(inst);
1505             return OP3S[ArithOp.value & 1][BitSpec.op3.getBits(inst)];
1506         }
1507 
emit(SPARCMacroAssembler masm, Op3s opcode, Register rs1, Register rs2, Register rd)1508         public static void emit(SPARCMacroAssembler masm, Op3s opcode, Register rs1, Register rs2, Register rd) {
1509             int instruction = setBits(0, opcode, rs1, rd);
1510             instruction = BitSpec.rs2.setBits(instruction, rs2.encoding);
1511             instruction = BitSpec.i.setBits(instruction, 0);
1512             masm.emitInt(instruction);
1513         }
1514 
emit(SPARCMacroAssembler masm, Op3s opcode, Register rs1, int simm13, Register rd)1515         public static void emit(SPARCMacroAssembler masm, Op3s opcode, Register rs1, int simm13, Register rd) {
1516             int instruction = setBits(0, opcode, rs1, rd);
1517             instruction = BitSpec.i.setBits(instruction, 1);
1518             BitSpec immediateSpec;
1519             switch (opcode) {
1520                 case Sllx:
1521                 case Srlx:
1522                 case Srax:
1523                     immediateSpec = BitSpec.shcnt64;
1524                     break;
1525                 case Sll:
1526                 case Srl:
1527                 case Sra:
1528                     immediateSpec = BitSpec.shcnt32;
1529                     break;
1530                 default:
1531                     immediateSpec = BitSpec.simm13;
1532                     break;
1533             }
1534             instruction = immediateSpec.setBits(instruction, simm13);
1535             masm.emitInt(instruction);
1536         }
1537 
setBits(int instruction, Op3s op3, Register rs1, Register rd)1538         private static int setBits(int instruction, Op3s op3, Register rs1, Register rd) {
1539             assert op3.op.equals(ArithOp);
1540             int tmp = BitSpec.op3.setBits(instruction, op3.value);
1541             switch (op3) {
1542                 case Sllx:
1543                 case Srlx:
1544                 case Srax:
1545                     tmp = BitSpec.x.setBits(tmp, 1);
1546                     break;
1547             }
1548             tmp = BitSpec.op.setBits(tmp, op3.op.value);
1549             tmp = BitSpec.rd.setBits(tmp, rd.encoding);
1550             return BitSpec.rs1.setBits(tmp, rs1.encoding);
1551         }
1552     }
1553 
1554     /**
1555      * Used for interfacing FP and GP conditional move instructions.
1556      */
1557     public interface CMOV {
emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, Register rs2, Register rd)1558         void emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, Register rs2, Register rd);
1559 
emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, int simm11, Register rd)1560         void emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, int simm11, Register rd);
1561     }
1562 
1563     public static final class MOVicc extends SPARCOp implements CMOV {
1564         private static final Op3s op3 = Movcc;
1565 
MOVicc()1566         public MOVicc() {
1567             super(ArithOp);
1568         }
1569 
1570         @Override
emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, Register rs2, Register rd)1571         public void emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, Register rs2, Register rd) {
1572             int inst = setBits(0, condition, cc, rd);
1573             inst = BitSpec.rs2.setBits(inst, rs2.encoding());
1574             masm.emitInt(inst);
1575         }
1576 
1577         @Override
emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, int simm11, Register rd)1578         public void emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, int simm11, Register rd) {
1579             int inst = setBits(0, condition, cc, rd);
1580             inst = BitSpec.i.setBits(inst, 1);
1581             inst = BitSpec.simm11.setBits(inst, simm11);
1582             masm.emitInt(inst);
1583         }
1584 
setBits(int word, ConditionFlag condition, CC cc, Register rd)1585         protected int setBits(int word, ConditionFlag condition, CC cc, Register rd) {
1586             int inst = super.setBits(word);
1587             inst = BitSpec.rd.setBits(inst, rd.encoding());
1588             inst = BitSpec.op3.setBits(inst, op3.value);
1589             inst = BitSpec.movccCond.setBits(inst, condition.value);
1590             inst = BitSpec.movccLo.setBits(inst, cc.value);
1591             return BitSpec.movccHi.setBits(inst, cc.isFloat ? 0 : 1);
1592         }
1593 
1594         @Override
getKeys()1595         protected List<BitKey[]> getKeys() {
1596             List<BitKey[]> keys = super.getKeys();
1597             keys.add(new BitKey[]{new BitKey(BitSpec.op3, op3.value)});
1598             return keys;
1599         }
1600     }
1601 
1602     public static final class FMOVcc extends SPARCOp implements CMOV {
1603         private OpfLow opfLow;
1604 
FMOVcc(OpfLow opfLow)1605         public FMOVcc(OpfLow opfLow) {
1606             super(ArithOp);
1607             this.opfLow = opfLow;
1608         }
1609 
1610         @Override
emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, Register rs2, Register rd)1611         public void emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, Register rs2, Register rd) {
1612             int inst = setBits(0);
1613             inst = BitSpec.rd.setBits(inst, rd.encoding());
1614             inst = BitSpec.op3.setBits(inst, opfLow.op3.value);
1615             inst = BitSpec.opfCond.setBits(inst, condition.value);
1616             inst = BitSpec.opfCC.setBits(inst, cc.value);
1617             inst = BitSpec.opfLow.setBits(inst, opfLow.value);
1618             inst = BitSpec.rs2.setBits(inst, rs2.encoding());
1619             masm.emitInt(inst);
1620         }
1621 
1622         @Override
emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, int simm11, Register rd)1623         public void emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, int simm11, Register rd) {
1624             throw new IllegalArgumentException("FMOVCC cannot be used with immediate value");
1625         }
1626 
1627         @Override
getKeys()1628         protected List<BitKey[]> getKeys() {
1629             List<BitKey[]> keys = super.getKeys();
1630             keys.add(new BitKey[]{new BitKey(BitSpec.op3, opfLow.op3.value)});
1631             keys.add(new BitKey[]{new BitKey(BitSpec.opfLow, opfLow.value)});
1632             return keys;
1633         }
1634     }
1635 
1636     public static final class OpfOp extends SPARCOp {
1637 
1638         private BitKey[] op3Keys;
1639 
OpfOp(BitKey... op3Keys)1640         public OpfOp(BitKey... op3Keys) {
1641             super(ArithOp);
1642             this.op3Keys = op3Keys;
1643         }
1644 
OpfOp()1645         public OpfOp() {
1646             // @formatter:off
1647             this(new BitKey[]{
1648                             new BitKey(BitSpec.op3, Op3s.Fpop1.value),
1649                             new BitKey(BitSpec.op3, Op3s.Fpop2.value),
1650                             new BitKey(BitSpec.op3, Op3s.Impdep1.value),
1651                             new BitKey(BitSpec.op3, Op3s.Impdep2.value)});
1652             // @formatter:on
1653         }
1654 
emit(SPARCMacroAssembler masm, Opfs opf, Register rs1, Register rs2, Register rd)1655         public static void emit(SPARCMacroAssembler masm, Opfs opf, Register rs1, Register rs2, Register rd) {
1656             int instruction = setBits(0, opf, rs1, rs2);
1657             instruction = BitSpec.rd.setBits(instruction, rd.encoding);
1658             instruction = BitSpec.i.setBits(instruction, 0);
1659             masm.emitInt(instruction);
1660         }
1661 
emitFcmp(SPARCMacroAssembler masm, Opfs opf, CC cc, Register rs1, Register rs2)1662         public static void emitFcmp(SPARCMacroAssembler masm, Opfs opf, CC cc, Register rs1, Register rs2) {
1663             assert opf.equals(Opfs.Fcmpd) || opf.equals(Opfs.Fcmps) : opf;
1664             int instruction = setBits(0, opf, rs1, rs2);
1665             instruction = BitSpec.fcc.setBits(instruction, cc.value);
1666             masm.emitInt(instruction);
1667         }
1668 
setBits(int instruction, Opfs opf, Register rs1, Register rs2)1669         private static int setBits(int instruction, Opfs opf, Register rs1, Register rs2) {
1670             int tmp = BitSpec.op.setBits(instruction, opf.op3.op.value);
1671             tmp = BitSpec.op3.setBits(tmp, opf.op3.value);
1672             tmp = BitSpec.opf.setBits(tmp, opf.value);
1673             tmp = BitSpec.rs1.setBits(tmp, rs1.encoding);
1674             return BitSpec.rs2.setBits(tmp, rs2.encoding);
1675         }
1676 
1677         @Override
getKeys()1678         protected List<BitKey[]> getKeys() {
1679             List<BitKey[]> keys = super.getKeys();
1680             keys.add(op3Keys);
1681             // @formatter:on
1682             return keys;
1683         }
1684     }
1685 
isCPURegister(Register... regs)1686     public static boolean isCPURegister(Register... regs) {
1687         for (Register reg : regs) {
1688             if (!isCPURegister(reg)) {
1689                 return false;
1690             }
1691         }
1692         return true;
1693     }
1694 
isCPURegister(Register r)1695     public static boolean isCPURegister(Register r) {
1696         return r.getRegisterCategory().equals(CPU);
1697     }
1698 
isGlobalRegister(Register r)1699     public static boolean isGlobalRegister(Register r) {
1700         return isCPURegister(r) && g0.number <= r.number && r.number <= g7.number;
1701     }
1702 
isSingleFloatRegister(Register r)1703     public static boolean isSingleFloatRegister(Register r) {
1704         return r.getRegisterCategory().equals(FPUs);
1705     }
1706 
isDoubleFloatRegister(Register r)1707     public static boolean isDoubleFloatRegister(Register r) {
1708         return r.getRegisterCategory().equals(FPUd);
1709     }
1710 
hasFeature(CPUFeature feature)1711     public boolean hasFeature(CPUFeature feature) {
1712         return ((SPARC) this.target.arch).features.contains(feature);
1713     }
1714 
simm(int x, int nbits)1715     public static final int simm(int x, int nbits) {
1716         // assert_signed_range(x, nbits);
1717         return x & ((1 << nbits) - 1);
1718     }
1719 
isImm(int x, int nbits)1720     public static final boolean isImm(int x, int nbits) {
1721         // assert_signed_range(x, nbits);
1722         return simm(x, nbits) == x;
1723     }
1724 
1725     /**
1726      * Minimum value for signed immediate ranges.
1727      */
minSimm(long nbits)1728     public static long minSimm(long nbits) {
1729         return -(1L << (nbits - 1));
1730     }
1731 
1732     /**
1733      * Maximum value for signed immediate ranges.
1734      */
maxSimm(long nbits)1735     public static long maxSimm(long nbits) {
1736         return (1L << (nbits - 1)) - 1;
1737     }
1738 
1739     /**
1740      * Test if imm is within signed immediate range for nbits.
1741      */
isSimm(long imm, int nbits)1742     public static boolean isSimm(long imm, int nbits) {
1743         return minSimm(nbits) <= imm && imm <= maxSimm(nbits);
1744     }
1745 
isSimm10(long imm)1746     public static boolean isSimm10(long imm) {
1747         return isSimm(imm, 10);
1748     }
1749 
isSimm11(long imm)1750     public static boolean isSimm11(long imm) {
1751         return isSimm(imm, 11);
1752     }
1753 
isSimm11(JavaConstant constant)1754     public static boolean isSimm11(JavaConstant constant) {
1755         return constant.isNull() || isSimm11(constant.asLong());
1756     }
1757 
isSimm5(JavaConstant constant)1758     public static boolean isSimm5(JavaConstant constant) {
1759         return constant.isNull() || isSimm(constant.asLong(), 5);
1760     }
1761 
isSimm5(long imm)1762     public static boolean isSimm5(long imm) {
1763         return isSimm(imm, 5);
1764     }
1765 
isSimm13(int imm)1766     public static boolean isSimm13(int imm) {
1767         return isSimm(imm, 13);
1768     }
1769 
isSimm13(JavaConstant constant)1770     public static boolean isSimm13(JavaConstant constant) {
1771         long bits;
1772         switch (constant.getJavaKind()) {
1773             case Double:
1774                 bits = Double.doubleToRawLongBits(constant.asDouble());
1775                 break;
1776             case Float:
1777                 bits = Float.floatToRawIntBits(constant.asFloat());
1778                 break;
1779             case Object:
1780                 return constant.isNull();
1781             default:
1782                 bits = constant.asLong();
1783                 break;
1784         }
1785         return constant.isNull() || isSimm13(bits);
1786     }
1787 
isSimm13(long imm)1788     public static boolean isSimm13(long imm) {
1789         return NumUtil.isInt(imm) && isSimm(imm, 13);
1790     }
1791 
isWordDisp30(long imm)1792     public static boolean isWordDisp30(long imm) {
1793         return isSimm(imm, 30 + 2);
1794     }
1795 
hi22(int x)1796     public static final int hi22(int x) {
1797         return x >>> 10;
1798     }
1799 
lo10(int x)1800     public static final int lo10(int x) {
1801         return x & ((1 << 10) - 1);
1802     }
1803 
1804     // @formatter:off
1805     /**
1806      * Instruction format for Fmt00 instructions. This abstraction is needed as it
1807      * makes the patching easier later on.
1808      * <pre>
1809      * | 00  |    a   | op2 |               b                         |
1810      * |31 30|29    25|24 22|21                                      0|
1811      * </pre>
1812      */
1813     // @formatter:on
fmt00(int a, int op2, int b)1814     protected void fmt00(int a, int op2, int b) {
1815         assert isImm(a, 5) && isImm(op2, 3) && isImm(b, 22) : String.format("a: 0x%x op2: 0x%x b: 0x%x", a, op2, b);
1816         int word = 0;
1817         BitSpec.op.setBits(word, 0);
1818         BitSpec.rd.setBits(word, a);
1819         BitSpec.op2.setBits(word, op2);
1820         BitSpec.imm22.setBits(word, b);
1821         emitInt(a << 25 | op2 << 22 | b);
1822     }
1823 
op3(Op3s op3, Opfs opf, Register rs1, Register rs2, Register rd)1824     private void op3(Op3s op3, Opfs opf, Register rs1, Register rs2, Register rd) {
1825         int b = opf.value << 5 | (rs2 == null ? 0 : rs2.encoding);
1826         fmt(op3.op.value, rd.encoding, op3.value, rs1 == null ? 0 : rs1.encoding, b);
1827     }
1828 
op3(Op3s op3, Register rs1, Register rs2, Register rd)1829     protected void op3(Op3s op3, Register rs1, Register rs2, Register rd) {
1830         int b = rs2 == null ? 0 : rs2.encoding;
1831         int xBit = getXBit(op3);
1832         fmt(op3.op.value, rd.encoding, op3.value, rs1 == null ? 0 : rs1.encoding, b | xBit);
1833     }
1834 
op3(Op3s op3, Register rs1, int simm13, Register rd)1835     protected void op3(Op3s op3, Register rs1, int simm13, Register rd) {
1836         assert isSimm13(simm13) : simm13;
1837         int i = 1 << 13;
1838         int simm13WithX = simm13 | getXBit(op3);
1839         fmt(op3.op.value, rd.encoding, op3.value, rs1.encoding, i | simm13WithX & ((1 << 13) - 1));
1840     }
1841 
insertNopAfterCBCond()1842     public void insertNopAfterCBCond() {
1843         int pos = position() - INSTRUCTION_SIZE;
1844         if (pos == 0) {
1845             return;
1846         }
1847         int inst = getInt(pos);
1848         if (CBCOND.match(inst)) {
1849             nop();
1850         }
1851     }
1852 
patchUnbound(Label label)1853     protected int patchUnbound(Label label) {
1854         label.addPatchAt(position());
1855         return 0;
1856     }
1857 
1858     // @formatter:off
1859     /**
1860      * NOP.
1861      * <pre>
1862      * | 00  |00000| 100 |                0                    |
1863      * |31 30|29 25|24 22|21                                  0|
1864      * </pre>
1865      */
1866     // @formatter:on
nop()1867     public void nop() {
1868         emitInt(1 << 24);
1869     }
1870 
sethi(int imm22, Register dst)1871     public void sethi(int imm22, Register dst) {
1872         fmt00(dst.encoding, Op2s.Sethi.value, imm22);
1873     }
1874 
1875     // @formatter:off
1876     /**
1877      * Instruction format for calls.
1878      * <pre>
1879      * | 01  |                      disp30                             |
1880      * |31 30|29                                                      0|
1881      * </pre>
1882      *
1883      * @return Position of the call instruction
1884      */
1885     // @formatter:on
call(int disp30)1886     public int call(int disp30) {
1887         assert isImm(disp30, 30);
1888         insertNopAfterCBCond();
1889         int before = position();
1890         int instr = 1 << 30;
1891         instr |= disp30;
1892         emitInt(instr);
1893         return before;
1894     }
1895 
add(Register rs1, Register rs2, Register rd)1896     public void add(Register rs1, Register rs2, Register rd) {
1897         op3(Add, rs1, rs2, rd);
1898     }
1899 
add(Register rs1, int simm13, Register rd)1900     public void add(Register rs1, int simm13, Register rd) {
1901         op3(Add, rs1, simm13, rd);
1902     }
1903 
addc(Register rs1, Register rs2, Register rd)1904     public void addc(Register rs1, Register rs2, Register rd) {
1905         op3(Addc, rs1, rs2, rd);
1906     }
1907 
addc(Register rs1, int simm13, Register rd)1908     public void addc(Register rs1, int simm13, Register rd) {
1909         op3(Addc, rs1, simm13, rd);
1910     }
1911 
addcc(Register rs1, Register rs2, Register rd)1912     public void addcc(Register rs1, Register rs2, Register rd) {
1913         op3(Addcc, rs1, rs2, rd);
1914     }
1915 
addcc(Register rs1, int simm13, Register rd)1916     public void addcc(Register rs1, int simm13, Register rd) {
1917         op3(Addcc, rs1, simm13, rd);
1918     }
1919 
and(Register rs1, Register rs2, Register rd)1920     public void and(Register rs1, Register rs2, Register rd) {
1921         op3(And, rs1, rs2, rd);
1922     }
1923 
and(Register rs1, int simm13, Register rd)1924     public void and(Register rs1, int simm13, Register rd) {
1925         op3(And, rs1, simm13, rd);
1926     }
1927 
andcc(Register rs1, Register rs2, Register rd)1928     public void andcc(Register rs1, Register rs2, Register rd) {
1929         op3(Andcc, rs1, rs2, rd);
1930     }
1931 
andcc(Register rs1, int simm13, Register rd)1932     public void andcc(Register rs1, int simm13, Register rd) {
1933         op3(Andcc, rs1, simm13, rd);
1934     }
1935 
andn(Register rs1, Register rs2, Register rd)1936     public void andn(Register rs1, Register rs2, Register rd) {
1937         op3(Andn, rs1, rs2, rd);
1938     }
1939 
andn(Register rs1, int simm13, Register rd)1940     public void andn(Register rs1, int simm13, Register rd) {
1941         op3(Andn, rs1, simm13, rd);
1942     }
1943 
andncc(Register rs1, Register rs2, Register rd)1944     public void andncc(Register rs1, Register rs2, Register rd) {
1945         op3(Andncc, rs1, rs2, rd);
1946     }
1947 
andncc(Register rs1, int simm13, Register rd)1948     public void andncc(Register rs1, int simm13, Register rd) {
1949         op3(Andncc, rs1, simm13, rd);
1950     }
1951 
movwtos(Register rs2, Register rd)1952     public void movwtos(Register rs2, Register rd) {
1953         assert isSingleFloatRegister(rd) && isCPURegister(rs2) : String.format("%s %s", rs2, rd);
1954         op3(Impdep1, Movwtos, null, rs2, rd);
1955     }
1956 
umulxhi(Register rs1, Register rs2, Register rd)1957     public void umulxhi(Register rs1, Register rs2, Register rd) {
1958         op3(Impdep1, UMulxhi, rs1, rs2, rd);
1959     }
1960 
fdtos(Register rs2, Register rd)1961     public void fdtos(Register rs2, Register rd) {
1962         assert isSingleFloatRegister(rd) && isDoubleFloatRegister(rs2) : String.format("%s %s", rs2, rd);
1963         op3(Fpop1, Fdtos, null, rs2, rd);
1964     }
1965 
movstouw(Register rs2, Register rd)1966     public void movstouw(Register rs2, Register rd) {
1967         assert isSingleFloatRegister(rs2) && isCPURegister(rd) : String.format("%s %s", rs2, rd);
1968         op3(Impdep1, Movstosw, null, rs2, rd);
1969     }
1970 
movstosw(Register rs2, Register rd)1971     public void movstosw(Register rs2, Register rd) {
1972         assert isSingleFloatRegister(rs2) && isCPURegister(rd) : String.format("%s %s", rs2, rd);
1973         op3(Impdep1, Movstosw, null, rs2, rd);
1974     }
1975 
movdtox(Register rs2, Register rd)1976     public void movdtox(Register rs2, Register rd) {
1977         assert isDoubleFloatRegister(rs2) && isCPURegister(rd) : String.format("%s %s", rs2, rd);
1978         op3(Impdep1, Movdtox, null, rs2, rd);
1979     }
1980 
movxtod(Register rs2, Register rd)1981     public void movxtod(Register rs2, Register rd) {
1982         assert isCPURegister(rs2) && isDoubleFloatRegister(rd) : String.format("%s %s", rs2, rd);
1983         op3(Impdep1, Movxtod, null, rs2, rd);
1984     }
1985 
fadds(Register rs1, Register rs2, Register rd)1986     public void fadds(Register rs1, Register rs2, Register rd) {
1987         op3(Fpop1, Fadds, rs1, rs2, rd);
1988     }
1989 
faddd(Register rs1, Register rs2, Register rd)1990     public void faddd(Register rs1, Register rs2, Register rd) {
1991         op3(Fpop1, Faddd, rs1, rs2, rd);
1992     }
1993 
fdivs(Register rs1, Register rs2, Register rd)1994     public void fdivs(Register rs1, Register rs2, Register rd) {
1995         op3(Fpop1, Fdivs, rs1, rs2, rd);
1996     }
1997 
fdivd(Register rs1, Register rs2, Register rd)1998     public void fdivd(Register rs1, Register rs2, Register rd) {
1999         op3(Fpop1, Fdivd, rs1, rs2, rd);
2000     }
2001 
fmovs(Register rs2, Register rd)2002     public void fmovs(Register rs2, Register rd) {
2003         op3(Fpop1, Fmovs, null, rs2, rd);
2004     }
2005 
fmovd(Register rs2, Register rd)2006     public void fmovd(Register rs2, Register rd) {
2007         op3(Fpop1, Fmovd, null, rs2, rd);
2008     }
2009 
fsrc2s(Register rs2, Register rd)2010     public void fsrc2s(Register rs2, Register rd) {
2011         op3(Impdep1, Fsrc2s, null, rs2, rd);
2012     }
2013 
fsrc2d(Register rs2, Register rd)2014     public void fsrc2d(Register rs2, Register rd) {
2015         op3(Impdep1, Fsrc2d, null, rs2, rd);
2016     }
2017 
fmuls(Register rs1, Register rs2, Register rd)2018     public void fmuls(Register rs1, Register rs2, Register rd) {
2019         op3(Fpop1, Fmuls, rs1, rs2, rd);
2020     }
2021 
fsmuld(Register rs1, Register rs2, Register rd)2022     public void fsmuld(Register rs1, Register rs2, Register rd) {
2023         op3(Fpop1, Fsmuld, rs1, rs2, rd);
2024     }
2025 
fmuld(Register rs1, Register rs2, Register rd)2026     public void fmuld(Register rs1, Register rs2, Register rd) {
2027         op3(Fpop1, Fmuld, rs1, rs2, rd);
2028     }
2029 
fnegs(Register rs2, Register rd)2030     public void fnegs(Register rs2, Register rd) {
2031         op3(Fpop1, Fnegs, null, rs2, rd);
2032     }
2033 
fnegd(Register rs2, Register rd)2034     public void fnegd(Register rs2, Register rd) {
2035         op3(Fpop1, Fnegd, null, rs2, rd);
2036     }
2037 
2038     /**
2039      * Helper method to determine if the instruction needs the X bit set.
2040      */
getXBit(Op3s op3)2041     private static int getXBit(Op3s op3) {
2042         switch (op3) {
2043             case Sllx:
2044             case Srax:
2045             case Srlx:
2046                 return 1 << 12;
2047             default:
2048                 return 0;
2049         }
2050     }
2051 
fstoi(Register rs2, Register rd)2052     public void fstoi(Register rs2, Register rd) {
2053         op3(Fpop1, Fstoi, null, rs2, rd);
2054     }
2055 
fstox(Register rs2, Register rd)2056     public void fstox(Register rs2, Register rd) {
2057         op3(Fpop1, Fstox, null, rs2, rd);
2058     }
2059 
fdtox(Register rs2, Register rd)2060     public void fdtox(Register rs2, Register rd) {
2061         op3(Fpop1, Fdtox, null, rs2, rd);
2062     }
2063 
fstod(Register rs2, Register rd)2064     public void fstod(Register rs2, Register rd) {
2065         op3(Fpop1, Fstod, null, rs2, rd);
2066     }
2067 
fdtoi(Register rs2, Register rd)2068     public void fdtoi(Register rs2, Register rd) {
2069         op3(Fpop1, Fdtoi, null, rs2, rd);
2070     }
2071 
fitos(Register rs2, Register rd)2072     public void fitos(Register rs2, Register rd) {
2073         op3(Fpop1, Fitos, null, rs2, rd);
2074     }
2075 
fitod(Register rs2, Register rd)2076     public void fitod(Register rs2, Register rd) {
2077         op3(Fpop1, Fitod, null, rs2, rd);
2078     }
2079 
fxtos(Register rs2, Register rd)2080     public void fxtos(Register rs2, Register rd) {
2081         op3(Fpop1, Fxtos, null, rs2, rd);
2082     }
2083 
fxtod(Register rs2, Register rd)2084     public void fxtod(Register rs2, Register rd) {
2085         op3(Fpop1, Fxtod, null, rs2, rd);
2086     }
2087 
fzeros(Register rd)2088     public void fzeros(Register rd) {
2089         op3(Impdep1, Fzeros, null, null, rd);
2090     }
2091 
fzerod(Register rd)2092     public void fzerod(Register rd) {
2093         op3(Impdep1, Fzerod, null, null, rd);
2094     }
2095 
flushw()2096     public void flushw() {
2097         op3(Flushw, g0, g0, g0);
2098     }
2099 
fsqrtd(Register rs2, Register rd)2100     public void fsqrtd(Register rs2, Register rd) {
2101         op3(Fpop1, Fsqrtd, null, rs2, rd);
2102     }
2103 
fsqrts(Register rs2, Register rd)2104     public void fsqrts(Register rs2, Register rd) {
2105         op3(Fpop1, Fsqrts, null, rs2, rd);
2106     }
2107 
fabss(Register rs2, Register rd)2108     public void fabss(Register rs2, Register rd) {
2109         op3(Fpop1, Fabss, null, rs2, rd);
2110     }
2111 
fabsd(Register rs2, Register rd)2112     public void fabsd(Register rs2, Register rd) {
2113         op3(Fpop1, Fabsd, null, rs2, rd);
2114     }
2115 
fsubs(Register rs1, Register rs2, Register rd)2116     public void fsubs(Register rs1, Register rs2, Register rd) {
2117         op3(Fpop1, Fsubs, rs1, rs2, rd);
2118     }
2119 
fsubd(Register rs1, Register rs2, Register rd)2120     public void fsubd(Register rs1, Register rs2, Register rd) {
2121         op3(Fpop1, Fsubd, rs1, rs2, rd);
2122     }
2123 
2124     // @formatter:off
2125     /**
2126      * Instruction format for fcmp.
2127      * <pre>
2128      * | 10  | --- |cc1|cc0|desc |   rs1   |   opf  | rs2 |
2129      * |31 30|29 27|26 |25 |24 19|18     14|13     5|4   0|
2130      * </pre>
2131      */
2132     // @formatter:on
fcmp(CC cc, Opfs opf, Register rs1, Register rs2)2133     public void fcmp(CC cc, Opfs opf, Register rs1, Register rs2) {
2134         int a = cc.value;
2135         int b = opf.value << 5 | rs2.encoding;
2136         delaySlotOptimizationPoints.add(position());
2137         fmt10(a, Fpop2.value, rs1.encoding, b);
2138     }
2139 
2140     // @formatter:off
2141     /**
2142      * Instruction format for most arithmetic stuff.
2143      * <pre>
2144      * |  10 | rd  | op3 | rs1 |   b   |
2145      * |31 30|29 25|24 19|18 14|13    0|
2146      * </pre>
2147      */
2148     // @formatter:on
fmt10(int rd, int op3, int rs1, int b)2149     protected void fmt10(int rd, int op3, int rs1, int b) {
2150         fmt(0b10, rd, op3, rs1, b);
2151     }
2152 
2153     // @formatter:off
2154     /**
2155      * Instruction format for most arithmetic stuff.
2156      * <pre>
2157      * |  op | rd  | op3 | rs1 |   b   |
2158      * |31 30|29 25|24 19|18 14|13    0|
2159      * </pre>
2160      */
2161     // @formatter:on
fmt(int op, int rd, int op3, int rs1, int b)2162     protected void fmt(int op, int rd, int op3, int rs1, int b) {
2163         assert isImm(rd, 5) && isImm(op3, 6) && isImm(b, 14) : String.format("rd: 0x%x op3: 0x%x b: 0x%x", rd, op3, b);
2164         int instr = op << 30 | rd << 25 | op3 << 19 | rs1 << 14 | b;
2165         emitInt(instr);
2166     }
2167 
illtrap(int const22)2168     public void illtrap(int const22) {
2169         fmt00(0, Op2s.Illtrap.value, const22);
2170     }
2171 
jmpl(Register rs1, Register rs2, Register rd)2172     public void jmpl(Register rs1, Register rs2, Register rd) {
2173         insertNopAfterCBCond();
2174         op3(Jmpl, rs1, rs2, rd);
2175     }
2176 
2177     /**
2178      * @return Position of the jmpl instruction
2179      */
jmpl(Register rs1, int simm13, Register rd)2180     public int jmpl(Register rs1, int simm13, Register rd) {
2181         insertNopAfterCBCond();
2182         int before = position();
2183         op3(Jmpl, rs1, simm13, rd);
2184         return before;
2185     }
2186 
fmovdcc(ConditionFlag cond, CC cc, Register rs2, Register rd)2187     public void fmovdcc(ConditionFlag cond, CC cc, Register rs2, Register rd) {
2188         fmovcc(cond, cc, rs2, rd, OpfLow.Fmovdcc.value);
2189     }
2190 
fmovscc(ConditionFlag cond, CC cc, Register rs2, Register rd)2191     public void fmovscc(ConditionFlag cond, CC cc, Register rs2, Register rd) {
2192         fmovcc(cond, cc, rs2, rd, OpfLow.Fmovscc.value);
2193     }
2194 
fmovcc(ConditionFlag cond, CC cc, Register rs2, Register rd, int opfLow)2195     private void fmovcc(ConditionFlag cond, CC cc, Register rs2, Register rd, int opfLow) {
2196         int opfCC = cc.value;
2197         int a = opfCC << 11 | opfLow << 5 | rs2.encoding;
2198         fmt10(rd.encoding, Fpop2.value, cond.value, a);
2199     }
2200 
movcc(ConditionFlag conditionFlag, CC cc, Register rs2, Register rd)2201     public void movcc(ConditionFlag conditionFlag, CC cc, Register rs2, Register rd) {
2202         movcc(conditionFlag, cc, 0, rs2.encoding, rd);
2203     }
2204 
movcc(ConditionFlag conditionFlag, CC cc, int simm11, Register rd)2205     public void movcc(ConditionFlag conditionFlag, CC cc, int simm11, Register rd) {
2206         assert isSimm11(simm11);
2207         movcc(conditionFlag, cc, 1, simm11 & ((1 << 11) - 1), rd);
2208     }
2209 
movcc(ConditionFlag conditionFlag, CC cc, int i, int imm, Register rd)2210     private void movcc(ConditionFlag conditionFlag, CC cc, int i, int imm, Register rd) {
2211         int cc01 = 0b11 & cc.value;
2212         int cc2 = cc.isFloat ? 0 : 1;
2213         int a = cc2 << 4 | conditionFlag.value;
2214         int b = cc01 << 11 | i << 13 | imm;
2215         fmt10(rd.encoding, Movcc.value, a, b);
2216     }
2217 
mulx(Register rs1, Register rs2, Register rd)2218     public void mulx(Register rs1, Register rs2, Register rd) {
2219         op3(Mulx, rs1, rs2, rd);
2220     }
2221 
mulx(Register rs1, int simm13, Register rd)2222     public void mulx(Register rs1, int simm13, Register rd) {
2223         op3(Mulx, rs1, simm13, rd);
2224     }
2225 
or(Register rs1, Register rs2, Register rd)2226     public void or(Register rs1, Register rs2, Register rd) {
2227         assert isCPURegister(rs1, rs2, rd) : String.format("%s %s %s", rs1, rs2, rd);
2228         op3(Or, rs1, rs2, rd);
2229     }
2230 
or(Register rs1, int simm13, Register rd)2231     public void or(Register rs1, int simm13, Register rd) {
2232         assert isCPURegister(rs1, rd) : String.format("%s %s", rs1, rd);
2233         op3(Or, rs1, simm13, rd);
2234     }
2235 
popc(Register rs2, Register rd)2236     public void popc(Register rs2, Register rd) {
2237         op3(Popc, g0, rs2, rd);
2238     }
2239 
popc(int simm13, Register rd)2240     public void popc(int simm13, Register rd) {
2241         op3(Popc, g0, simm13, rd);
2242     }
2243 
prefetch(SPARCAddress addr, Fcn fcn)2244     public void prefetch(SPARCAddress addr, Fcn fcn) {
2245         Register rs1 = addr.getBase();
2246         if (addr.getIndex().equals(Register.None)) {
2247             int dis = addr.getDisplacement();
2248             assert isSimm13(dis);
2249             fmt(Prefetch.op.value, fcn.value, Prefetch.value, rs1.encoding, 1 << 13 | dis & ((1 << 13) - 1));
2250         } else {
2251             Register rs2 = addr.getIndex();
2252             fmt(Prefetch.op.value, fcn.value, Prefetch.value, rs1.encoding, rs2.encoding);
2253         }
2254     }
2255 
2256     // A.44 Read State Register
2257 
rdpc(Register rd)2258     public void rdpc(Register rd) {
2259         op3(Rd, g5, g0, rd);
2260     }
2261 
restore(Register rs1, Register rs2, Register rd)2262     public void restore(Register rs1, Register rs2, Register rd) {
2263         op3(Restore, rs1, rs2, rd);
2264     }
2265 
2266     public static final int PC_RETURN_OFFSET = 8;
2267 
save(Register rs1, Register rs2, Register rd)2268     public void save(Register rs1, Register rs2, Register rd) {
2269         op3(Save, rs1, rs2, rd);
2270     }
2271 
save(Register rs1, int simm13, Register rd)2272     public void save(Register rs1, int simm13, Register rd) {
2273         op3(Save, rs1, simm13, rd);
2274     }
2275 
sdivx(Register rs1, Register rs2, Register rd)2276     public void sdivx(Register rs1, Register rs2, Register rd) {
2277         op3(Sdivx, rs1, rs2, rd);
2278     }
2279 
sdivx(Register rs1, int simm13, Register rd)2280     public void sdivx(Register rs1, int simm13, Register rd) {
2281         op3(Sdivx, rs1, simm13, rd);
2282     }
2283 
udivx(Register rs1, Register rs2, Register rd)2284     public void udivx(Register rs1, Register rs2, Register rd) {
2285         op3(Udivx, rs1, rs2, rd);
2286     }
2287 
udivx(Register rs1, int simm13, Register rd)2288     public void udivx(Register rs1, int simm13, Register rd) {
2289         op3(Udivx, rs1, simm13, rd);
2290     }
2291 
sll(Register rs1, Register rs2, Register rd)2292     public void sll(Register rs1, Register rs2, Register rd) {
2293         op3(Sll, rs1, rs2, rd);
2294     }
2295 
sll(Register rs1, int shcnt32, Register rd)2296     public void sll(Register rs1, int shcnt32, Register rd) {
2297         assert isImm(shcnt32, 5);
2298         op3(Sll, rs1, shcnt32, rd);
2299     }
2300 
sllx(Register rs1, Register rs2, Register rd)2301     public void sllx(Register rs1, Register rs2, Register rd) {
2302         op3(Sllx, rs1, rs2, rd);
2303     }
2304 
sllx(Register rs1, int shcnt64, Register rd)2305     public void sllx(Register rs1, int shcnt64, Register rd) {
2306         assert isImm(shcnt64, 6);
2307         op3(Sllx, rs1, shcnt64, rd);
2308     }
2309 
sra(Register rs1, Register rs2, Register rd)2310     public void sra(Register rs1, Register rs2, Register rd) {
2311         op3(Sra, rs1, rs2, rd);
2312     }
2313 
sra(Register rs1, int simm13, Register rd)2314     public void sra(Register rs1, int simm13, Register rd) {
2315         op3(Sra, rs1, simm13, rd);
2316     }
2317 
srax(Register rs1, Register rs2, Register rd)2318     public void srax(Register rs1, Register rs2, Register rd) {
2319         op3(Srax, rs1, rs2, rd);
2320     }
2321 
srax(Register rs1, int shcnt64, Register rd)2322     public void srax(Register rs1, int shcnt64, Register rd) {
2323         assert isImm(shcnt64, 6);
2324         op3(Srax, rs1, shcnt64, rd);
2325     }
2326 
srl(Register rs1, Register rs2, Register rd)2327     public void srl(Register rs1, Register rs2, Register rd) {
2328         op3(Srl, rs1, rs2, rd);
2329     }
2330 
srl(Register rs1, int simm13, Register rd)2331     public void srl(Register rs1, int simm13, Register rd) {
2332         op3(Srl, rs1, simm13, rd);
2333     }
2334 
srlx(Register rs1, Register rs2, Register rd)2335     public void srlx(Register rs1, Register rs2, Register rd) {
2336         op3(Srlx, rs1, rs2, rd);
2337     }
2338 
srlx(Register rs1, int shcnt64, Register rd)2339     public void srlx(Register rs1, int shcnt64, Register rd) {
2340         assert isImm(shcnt64, 6);
2341         op3(Srlx, rs1, shcnt64, rd);
2342     }
2343 
sub(Register rs1, Register rs2, Register rd)2344     public void sub(Register rs1, Register rs2, Register rd) {
2345         op3(Sub, rs1, rs2, rd);
2346     }
2347 
sub(Register rs1, int simm13, Register rd)2348     public void sub(Register rs1, int simm13, Register rd) {
2349         op3(Sub, rs1, simm13, rd);
2350     }
2351 
subcc(Register rs1, Register rs2, Register rd)2352     public void subcc(Register rs1, Register rs2, Register rd) {
2353         op3(Subcc, rs1, rs2, rd);
2354     }
2355 
subcc(Register rs1, int simm13, Register rd)2356     public void subcc(Register rs1, int simm13, Register rd) {
2357         op3(Subcc, rs1, simm13, rd);
2358     }
2359 
ta(int trap)2360     public void ta(int trap) {
2361         tcc(Icc, Always, trap);
2362     }
2363 
pause()2364     public void pause() {
2365         // Maybe fmt10(rd=0b1_1011, op3=0b11_0000, rs1=0, i=1, simm13=1), or
2366         // maybe op3(Wr, g0, 1, %pause).
2367         // What should the count be?
2368         GraalError.unimplemented("The SPARC pause instruction is not yet implemented.");
2369     }
2370 
tcc(CC cc, ConditionFlag flag, int trap)2371     public void tcc(CC cc, ConditionFlag flag, int trap) {
2372         assert isImm(trap, 8);
2373         int b = cc.value << 11;
2374         b |= 1 << 13;
2375         b |= trap;
2376         fmt10(flag.value, Op3s.Tcc.getValue(), 0, b);
2377     }
2378 
wrccr(Register rs1, Register rs2)2379     public void wrccr(Register rs1, Register rs2) {
2380         op3(Wr, rs1, rs2, g2);
2381     }
2382 
wrccr(Register rs1, int simm13)2383     public void wrccr(Register rs1, int simm13) {
2384         op3(Wr, rs1, simm13, g2);
2385     }
2386 
xor(Register rs1, Register rs2, Register rd)2387     public void xor(Register rs1, Register rs2, Register rd) {
2388         op3(Xor, rs1, rs2, rd);
2389     }
2390 
xor(Register rs1, int simm13, Register rd)2391     public void xor(Register rs1, int simm13, Register rd) {
2392         op3(Xor, rs1, simm13, rd);
2393     }
2394 
xorcc(Register rs1, Register rs2, Register rd)2395     public void xorcc(Register rs1, Register rs2, Register rd) {
2396         op3(Xorcc, rs1, rs2, rd);
2397     }
2398 
xorcc(Register rs1, int simm13, Register rd)2399     public void xorcc(Register rs1, int simm13, Register rd) {
2400         op3(Xorcc, rs1, simm13, rd);
2401     }
2402 
xnor(Register rs1, Register rs2, Register rd)2403     public void xnor(Register rs1, Register rs2, Register rd) {
2404         op3(Xnor, rs1, rs2, rd);
2405     }
2406 
xnor(Register rs1, int simm13, Register rd)2407     public void xnor(Register rs1, int simm13, Register rd) {
2408         op3(Xnor, rs1, simm13, rd);
2409     }
2410 
2411     /*
2412      * Load/Store
2413      */
ld(Op3s op3, SPARCAddress addr, Register rd, Asi asi)2414     protected void ld(Op3s op3, SPARCAddress addr, Register rd, Asi asi) {
2415         Register rs1 = addr.getBase();
2416         if (!addr.getIndex().equals(Register.None)) {
2417             Register rs2 = addr.getIndex();
2418             if (asi != null) {
2419                 int b = rs2.encoding;
2420                 b |= asi.value << 5;
2421                 fmt(op3.op.value, rd.encoding, op3.value, rs1.encoding, b);
2422             } else {
2423                 op3(op3, rs1, rs2, rd);
2424             }
2425         } else {
2426             int imm = addr.getDisplacement();
2427             op3(op3, rs1, imm, rd);
2428         }
2429     }
2430 
ld(Op3s op3, SPARCAddress addr, Register rd)2431     protected void ld(Op3s op3, SPARCAddress addr, Register rd) {
2432         ld(op3, addr, rd, null);
2433     }
2434 
lddf(SPARCAddress src, Register dst)2435     public void lddf(SPARCAddress src, Register dst) {
2436         assert isDoubleFloatRegister(dst) : dst;
2437         ld(Lddf, src, dst);
2438     }
2439 
ldf(SPARCAddress src, Register dst)2440     public void ldf(SPARCAddress src, Register dst) {
2441         assert isSingleFloatRegister(dst) : dst;
2442         ld(Ldf, src, dst);
2443     }
2444 
lduh(SPARCAddress src, Register dst)2445     public void lduh(SPARCAddress src, Register dst) {
2446         assert isCPURegister(dst) : dst;
2447         ld(Lduh, src, dst);
2448     }
2449 
ldsh(SPARCAddress src, Register dst)2450     public void ldsh(SPARCAddress src, Register dst) {
2451         assert isCPURegister(dst) : dst;
2452         ld(Ldsh, src, dst);
2453     }
2454 
ld(SPARCAddress src, Register dst, int bytes, boolean signExtend)2455     public void ld(SPARCAddress src, Register dst, int bytes, boolean signExtend) {
2456         if (isCPURegister(dst)) {
2457             if (signExtend) {
2458                 switch (bytes) {
2459                     case 1:
2460                         ld(Ldsb, src, dst);
2461                         break;
2462                     case 2:
2463                         ld(Ldsh, src, dst);
2464                         break;
2465                     case 4:
2466                         ld(Ldsw, src, dst);
2467                         break;
2468                     case 8:
2469                         ld(Ldx, src, dst);
2470                         break;
2471                     default:
2472                         throw new InternalError();
2473                 }
2474             } else {
2475                 switch (bytes) {
2476                     case 1:
2477                         ld(Ldub, src, dst);
2478                         break;
2479                     case 2:
2480                         ld(Lduh, src, dst);
2481                         break;
2482                     case 4:
2483                         ld(Lduw, src, dst);
2484                         break;
2485                     case 8:
2486                         ld(Ldx, src, dst);
2487                         break;
2488                     default:
2489                         throw new InternalError();
2490                 }
2491             }
2492         } else if (isDoubleFloatRegister(dst) && bytes == 8) {
2493             assert !signExtend;
2494             ld(Lddf, src, dst);
2495         } else if (isSingleFloatRegister(dst) && bytes == 4) {
2496             assert !signExtend;
2497             ld(Ldf, src, dst);
2498         } else {
2499             throw new InternalError(String.format("src: %s dst: %s bytes: %d signExtend: %b", src, dst, bytes, signExtend));
2500         }
2501     }
2502 
st(Register src, SPARCAddress dst, int bytes)2503     public void st(Register src, SPARCAddress dst, int bytes) {
2504         if (isCPURegister(src)) {
2505             switch (bytes) {
2506                 case 1:
2507                     st(Stb, src, dst);
2508                     break;
2509                 case 2:
2510                     st(Sth, src, dst);
2511                     break;
2512                 case 4:
2513                     st(Stw, src, dst);
2514                     break;
2515                 case 8:
2516                     st(Stx, src, dst);
2517                     break;
2518                 default:
2519                     throw new InternalError(Integer.toString(bytes));
2520             }
2521         } else if (isDoubleFloatRegister(src) && bytes == 8) {
2522             st(Stdf, src, dst);
2523         } else if (isSingleFloatRegister(src) && bytes == 4) {
2524             st(Stf, src, dst);
2525         } else {
2526             throw new InternalError(String.format("src: %s dst: %s bytes: %d", src, dst, bytes));
2527         }
2528     }
2529 
ldub(SPARCAddress src, Register dst)2530     public void ldub(SPARCAddress src, Register dst) {
2531         assert isCPURegister(dst) : dst;
2532         ld(Ldub, src, dst);
2533     }
2534 
ldsb(SPARCAddress src, Register dst)2535     public void ldsb(SPARCAddress src, Register dst) {
2536         assert isCPURegister(dst) : dst;
2537         ld(Ldsb, src, dst);
2538     }
2539 
lduw(SPARCAddress src, Register dst)2540     public void lduw(SPARCAddress src, Register dst) {
2541         assert isCPURegister(dst) : dst;
2542         ld(Lduw, src, dst);
2543     }
2544 
ldsw(SPARCAddress src, Register dst)2545     public void ldsw(SPARCAddress src, Register dst) {
2546         assert isCPURegister(dst) : dst;
2547         ld(Ldsw, src, dst);
2548     }
2549 
ldx(SPARCAddress src, Register dst)2550     public void ldx(SPARCAddress src, Register dst) {
2551         assert isCPURegister(dst) : dst;
2552         ld(Ldx, src, dst);
2553     }
2554 
ldxa(Register rs1, Register rs2, Register rd, Asi asi)2555     public void ldxa(Register rs1, Register rs2, Register rd, Asi asi) {
2556         assert isCPURegister(rs1, rs2, rd) : format("%s %s %s", rs1, rs2, rd);
2557         ld(Ldxa, new SPARCAddress(rs1, rs2), rd, asi);
2558     }
2559 
lduwa(Register rs1, Register rs2, Register rd, Asi asi)2560     public void lduwa(Register rs1, Register rs2, Register rd, Asi asi) {
2561         assert isCPURegister(rs1, rs2, rd) : format("%s %s %s", rs1, rs2, rd);
2562         ld(Lduwa, new SPARCAddress(rs1, rs2), rd, asi);
2563     }
2564 
stxa(Register rd, Register rs1, Register rs2, Asi asi)2565     public void stxa(Register rd, Register rs1, Register rs2, Asi asi) {
2566         assert isCPURegister(rs1, rs2, rd) : format("%s %s %s", rs1, rs2, rd);
2567         ld(Stxa, new SPARCAddress(rs1, rs2), rd, asi);
2568     }
2569 
st(Op3s op3, Register rs1, SPARCAddress dest)2570     protected void st(Op3s op3, Register rs1, SPARCAddress dest) {
2571         ld(op3, dest, rs1);
2572     }
2573 
stdf(Register rd, SPARCAddress addr)2574     public void stdf(Register rd, SPARCAddress addr) {
2575         assert isDoubleFloatRegister(rd) : rd;
2576         st(Stdf, rd, addr);
2577     }
2578 
stf(Register rd, SPARCAddress addr)2579     public void stf(Register rd, SPARCAddress addr) {
2580         assert isSingleFloatRegister(rd) : rd;
2581         st(Stf, rd, addr);
2582     }
2583 
stb(Register rd, SPARCAddress addr)2584     public void stb(Register rd, SPARCAddress addr) {
2585         assert isCPURegister(rd) : rd;
2586         st(Stb, rd, addr);
2587     }
2588 
sth(Register rd, SPARCAddress addr)2589     public void sth(Register rd, SPARCAddress addr) {
2590         assert isCPURegister(rd) : rd;
2591         st(Sth, rd, addr);
2592     }
2593 
stw(Register rd, SPARCAddress addr)2594     public void stw(Register rd, SPARCAddress addr) {
2595         assert isCPURegister(rd) : rd;
2596         st(Stw, rd, addr);
2597     }
2598 
stx(Register rd, SPARCAddress addr)2599     public void stx(Register rd, SPARCAddress addr) {
2600         assert isCPURegister(rd) : rd;
2601         st(Stx, rd, addr);
2602     }
2603 
membar(int barriers)2604     public void membar(int barriers) {
2605         op3(Membar, o7, barriers, g0);
2606     }
2607 
casa(Register rs1, Register rs2, Register rd, Asi asi)2608     public void casa(Register rs1, Register rs2, Register rd, Asi asi) {
2609         ld(Casa, new SPARCAddress(rs1, rs2), rd, asi);
2610     }
2611 
casxa(Register rs1, Register rs2, Register rd, Asi asi)2612     public void casxa(Register rs1, Register rs2, Register rd, Asi asi) {
2613         ld(Casxa, new SPARCAddress(rs1, rs2), rd, asi);
2614     }
2615 
2616     @Override
getInstructionCounter()2617     public InstructionCounter getInstructionCounter() {
2618         return new SPARCInstructionCounter(this);
2619     }
2620 
patchAddImmediate(int position, int simm13)2621     public void patchAddImmediate(int position, int simm13) {
2622         int inst = getInt(position);
2623         assert SPARCAssembler.isSimm13(simm13) : simm13;
2624         assert (inst >>> 30) == 0b10 : String.format("0x%x", inst);
2625         assert ((inst >>> 18) & 0b11_1111) == 0 : String.format("0x%x", inst);
2626         assert (inst & (1 << 13)) != 0 : String.format("0x%x", inst);
2627         inst = inst & (~((1 << 13) - 1));
2628         inst |= simm13 & ((1 << 12) - 1);
2629         emitInt(inst, position);
2630     }
2631 
fpadd32(Register rs1, Register rs2, Register rd)2632     public void fpadd32(Register rs1, Register rs2, Register rd) {
2633         op3(Impdep1, Fpadd32, rs1, rs2, rd);
2634     }
2635 
2636     /**
2637      * Does peephole optimization on code generated by this assembler. This method should be called
2638      * at the end of code generation.
2639      * <p>
2640      * It searches for conditional branch instructions which has nop in the delay slot then looks at
2641      * the instruction at branch target; if it is an arithmetic instruction, which does not throw an
2642      * exception (e.g. division), it pulls this instruction into the delay slot and increments the
2643      * displacement by 1.
2644      */
peephole()2645     public void peephole() {
2646         for (int i : delaySlotOptimizationPoints) {
2647             optimizeDelaySlot(i);
2648         }
2649     }
2650 
2651     /**
2652      * Optimizes branch instruction <i>b</t> which has a nop in the delay slot. It tries to stuff
2653      * the instruction at <i>b</i>s branch target into the delay slot of <i>b</i>, set the annul
2654      * flag and increments <i>b</i>s disp field by 1;
2655      * <p>
2656      * If <i>b</i>s branch target instruction is an unconditional branch <i>t</i>, then it tries to
2657      * put <i>t</i>s delayed instruction into the delay slot of <i>b</i> and add the <i>t</i>s disp
2658      * field to <i>b</i>s disp field.
2659      */
optimizeDelaySlot(int i)2660     private void optimizeDelaySlot(int i) {
2661         int delaySlotAbsolute = i + INSTRUCTION_SIZE;
2662         int nextInst = getInt(delaySlotAbsolute);
2663         SPARCOp nextOp = getSPARCOp(nextInst);
2664         if (nextOp instanceof Sethi && Sethi.isNop(nextInst)) {
2665             int inst = getInt(i);
2666             SPARCOp op = getSPARCOp(inst);
2667             if (op instanceof ControlTransferOp && ((ControlTransferOp) op).hasDelaySlot() && ((ControlTransferOp) op).isAnnulable(inst)) {
2668                 ControlTransferOp ctOp = (ControlTransferOp) op;
2669                 int disp = ctOp.getDisp(inst);
2670                 int branchTargetAbsolute = i + disp * INSTRUCTION_SIZE;
2671                 int branchTargetInst = getInt(branchTargetAbsolute);
2672                 SPARCOp branchTargetOp = getSPARCOp(branchTargetInst);
2673                 if (branchTargetOp instanceof Op3Op) {
2674                     Op3s op3 = ((Op3Op) branchTargetOp).getOp3(branchTargetInst);
2675                     if (!op3.throwsException()) {
2676                         inst = ctOp.setDisp(inst, disp + 1); // Increment the offset
2677                         inst = ctOp.setAnnul(inst, true);
2678                         emitInt(inst, i);
2679                         emitInt(branchTargetInst, delaySlotAbsolute);
2680                     }
2681                 } else if (branchTargetOp instanceof ControlTransferOp && !((ControlTransferOp) branchTargetOp).isConditional(branchTargetInst)) {
2682                     // If branchtarget is a unconditional branch
2683                     ControlTransferOp branchTargetOpBranch = (ControlTransferOp) branchTargetOp;
2684                     int btDisp = branchTargetOpBranch.getDisp(branchTargetInst);
2685                     int newDisp = disp + btDisp;
2686                     if (ctOp.isValidDisp(newDisp)) { // Test if we don't exceed field size
2687                         int instAfter = ctOp.setDisp(inst, newDisp);
2688                         instAfter = ctOp.setAnnul(instAfter, true);
2689                         branchTargetInst = getInt(branchTargetAbsolute + INSTRUCTION_SIZE);
2690                         branchTargetOp = getSPARCOp(branchTargetInst);
2691                         if (branchTargetOp instanceof Op3Op && !((Op3Op) branchTargetOp).getOp3(branchTargetInst).throwsException()) {
2692                             emitInt(instAfter, i);
2693                             emitInt(branchTargetInst, delaySlotAbsolute);
2694                         }
2695                     }
2696                 }
2697             }
2698         }
2699     }
2700 }
2701