43972
|
1 |
/*
|
58299
|
2 |
* Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
|
43972
|
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 |
*/
|
50858
|
23 |
|
|
24 |
|
43972
|
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;
|
54084
|
139 |
import org.graalvm.compiler.asm.BranchTargetOutOfBoundsException;
|
43972
|
140 |
import org.graalvm.compiler.asm.Label;
|
46344
|
141 |
import org.graalvm.compiler.core.common.NumUtil;
|
43972
|
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 |
*/
|
|
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 |
|
|
219 |
Ops(int value) {
|
|
220 |
this.value = value;
|
|
221 |
}
|
|
222 |
|
|
223 |
public int getValue() {
|
|
224 |
return value;
|
|
225 |
}
|
|
226 |
|
|
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 |
|
|
249 |
Op2s(int value) {
|
|
250 |
this.value = value;
|
|
251 |
}
|
|
252 |
|
|
253 |
public int getValue() {
|
|
254 |
return value;
|
|
255 |
}
|
|
256 |
|
|
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 |
|
|
384 |
Op3s(int value, String name, Ops op) {
|
|
385 |
this(value, name, op, 0);
|
|
386 |
}
|
|
387 |
|
|
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 |
|
|
395 |
public int getValue() {
|
|
396 |
return value;
|
|
397 |
}
|
|
398 |
|
|
399 |
public String getOperator() {
|
|
400 |
return operator;
|
|
401 |
}
|
|
402 |
|
|
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 |
|
|
420 |
public boolean isBinary() {
|
|
421 |
return (flags & BINARY) != 0;
|
|
422 |
}
|
|
423 |
|
|
424 |
public boolean isUnary() {
|
|
425 |
return (flags & UNARY) != 0;
|
|
426 |
}
|
|
427 |
|
|
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 |
|
|
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 |
|
|
506 |
public int getValue() {
|
|
507 |
return value;
|
|
508 |
}
|
|
509 |
|
|
510 |
public String getOperator() {
|
|
511 |
return operator;
|
|
512 |
}
|
|
513 |
|
|
514 |
public boolean isBinary() {
|
|
515 |
return (flags & BINARY) != 0;
|
|
516 |
}
|
|
517 |
|
|
518 |
public boolean isUnary() {
|
|
519 |
return (flags & UNARY) != 0;
|
|
520 |
}
|
|
521 |
|
|
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 |
|
|
535 |
OpfLow(int value, String op, Op3s op3) {
|
|
536 |
this.value = value;
|
|
537 |
this.operator = op;
|
|
538 |
this.op3 = op3;
|
|
539 |
}
|
|
540 |
|
|
541 |
@Override
|
|
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 |
|
|
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 |
|
|
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 |
|
|
583 |
MembarMask(int value, String op) {
|
|
584 |
this.value = value;
|
|
585 |
this.operator = op;
|
|
586 |
}
|
|
587 |
|
|
588 |
public int getValue() {
|
|
589 |
return value | 0x2000;
|
|
590 |
}
|
|
591 |
|
|
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 |
|
|
621 |
CC(int value, String op, boolean isFloat) {
|
|
622 |
this.value = value;
|
|
623 |
this.operator = op;
|
|
624 |
this.isFloat = isFloat;
|
|
625 |
}
|
|
626 |
|
|
627 |
public int getValue() {
|
|
628 |
return value;
|
|
629 |
}
|
|
630 |
|
|
631 |
public String getOperator() {
|
|
632 |
return operator;
|
|
633 |
}
|
|
634 |
|
|
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 |
|
|
697 |
ConditionFlag(int value, String op) {
|
|
698 |
this(value, op, false);
|
|
699 |
}
|
|
700 |
|
|
701 |
ConditionFlag(int value, String op, boolean cbcond) {
|
|
702 |
this.value = value;
|
|
703 |
this.operator = op;
|
|
704 |
this.forCBcond = cbcond;
|
|
705 |
}
|
|
706 |
|
|
707 |
public boolean isCBCond() {
|
|
708 |
return forCBcond;
|
|
709 |
}
|
|
710 |
|
|
711 |
public int getValue() {
|
|
712 |
return value;
|
|
713 |
}
|
|
714 |
|
|
715 |
public String getOperator() {
|
|
716 |
return operator;
|
|
717 |
}
|
|
718 |
|
|
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 |
|
|
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 |
|
|
807 |
RCondition(int value, String op) {
|
|
808 |
this.value = value;
|
|
809 |
this.operator = op;
|
|
810 |
}
|
|
811 |
|
|
812 |
public int getValue() {
|
|
813 |
return value;
|
|
814 |
}
|
|
815 |
|
|
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 |
|
|
840 |
Asi(int value) {
|
|
841 |
this.value = value;
|
|
842 |
}
|
|
843 |
|
|
844 |
public int getValue() {
|
|
845 |
return value;
|
|
846 |
}
|
|
847 |
|
|
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 |
|
|
867 |
Fcn(int value) {
|
|
868 |
this.value = value;
|
|
869 |
}
|
|
870 |
|
|
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 |
|
|
929 |
public BitSpec(boolean signExtend) {
|
|
930 |
super();
|
|
931 |
this.signExtend = signExtend;
|
|
932 |
}
|
|
933 |
|
|
934 |
public final boolean isSignExtend() {
|
|
935 |
return signExtend;
|
|
936 |
}
|
|
937 |
|
|
938 |
public abstract int setBits(int word, int value);
|
|
939 |
|
|
940 |
public abstract int getBits(int word);
|
|
941 |
|
|
942 |
public abstract int getWidth();
|
|
943 |
|
|
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 |
|
|
954 |
public ContinousBitSpec(int hiBit, int lowBit, String name) {
|
|
955 |
this(hiBit, lowBit, false, name);
|
|
956 |
}
|
|
957 |
|
|
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
|
|
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
|
|
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
|
|
983 |
public int getWidth() {
|
|
984 |
return width;
|
|
985 |
}
|
|
986 |
|
|
987 |
@Override
|
|
988 |
public String toString() {
|
|
989 |
return String.format("%s [%d:%d]", name, hiBit, lowBit);
|
|
990 |
}
|
|
991 |
|
|
992 |
@Override
|
|
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 |
|
|
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
|
|
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
|
|
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 |
|
|
1033 |
private int leftBits(int value) {
|
|
1034 |
return getBits(value, width - 1, rightWidth, signExtend);
|
|
1035 |
}
|
|
1036 |
|
|
1037 |
private int rightBits(int value) {
|
|
1038 |
return getBits(value, rightWidth - 1, 0, false);
|
|
1039 |
}
|
|
1040 |
|
|
1041 |
@Override
|
|
1042 |
public int getWidth() {
|
|
1043 |
return width;
|
|
1044 |
}
|
|
1045 |
|
|
1046 |
@Override
|
|
1047 |
public String toString() {
|
|
1048 |
return String.format("CompositeBitSpec[%s, %s]", left, right);
|
|
1049 |
}
|
|
1050 |
|
|
1051 |
@Override
|
|
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 |
|
|
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 |
|
|
1072 |
public BitKey(BitSpec spec, int value) {
|
|
1073 |
super();
|
|
1074 |
this.spec = spec;
|
|
1075 |
this.value = value;
|
|
1076 |
}
|
|
1077 |
|
|
1078 |
@Override
|
|
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 |
|
|
1092 |
public BitKeyIndex(SPARCOp op) {
|
|
1093 |
assert op != null;
|
|
1094 |
this.op = op;
|
|
1095 |
this.nodes = null;
|
|
1096 |
this.spec = null;
|
|
1097 |
}
|
|
1098 |
|
|
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 |
*/
|
|
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 |
*/
|
|
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
|
|
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);
|
51436
|
1176 |
public static final MOVicc MOVICC = new MOVicc();
|
43972
|
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) {
|
|
1186 |
INDEX.addOp(op.getKeys(), op);
|
|
1187 |
}
|
|
1188 |
}
|
|
1189 |
|
|
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 |
|
|
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 |
|
|
1210 |
protected int setBits(int word) {
|
|
1211 |
return BitSpec.op.setBits(word, op.value);
|
|
1212 |
}
|
|
1213 |
|
|
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 |
|
|
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 |
|
|
1233 |
public Ops getOp(int inst) {
|
|
1234 |
return SPARCAssembler.OPS[BitSpec.op.getBits(inst)];
|
|
1235 |
}
|
|
1236 |
|
|
1237 |
@Override
|
|
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 |
|
|
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 |
|
|
1262 |
public boolean hasDelaySlot() {
|
|
1263 |
return delaySlot;
|
|
1264 |
}
|
|
1265 |
|
|
1266 |
@Override
|
|
1267 |
protected int setBits(int word) {
|
|
1268 |
return BitSpec.op2.setBits(super.setBits(word), op2.value);
|
|
1269 |
}
|
|
1270 |
|
|
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 |
|
|
1281 |
public int setDisp(int inst, int d) {
|
|
1282 |
assert this.match(inst);
|
|
1283 |
if (!isValidDisp(d)) {
|
54084
|
1284 |
throw new BranchTargetOutOfBoundsException(true, "Too large displacement 0x%x in field %s in instruction %s", d, this.disp, this);
|
43972
|
1285 |
}
|
|
1286 |
return this.disp.setBits(inst, d);
|
|
1287 |
}
|
|
1288 |
|
|
1289 |
public boolean isValidDisp(int d) {
|
|
1290 |
return this.disp.valueFits(d);
|
|
1291 |
}
|
|
1292 |
|
|
1293 |
public int setAnnul(int inst, boolean a) {
|
|
1294 |
return BitSpec.a.setBits(inst, a ? 1 : 0);
|
|
1295 |
}
|
|
1296 |
|
|
1297 |
@Override
|
|
1298 |
protected List<BitKey[]> getKeys() {
|
|
1299 |
List<BitKey[]> keys = super.getKeys();
|
|
1300 |
keys.add(op2Key);
|
|
1301 |
return keys;
|
|
1302 |
}
|
|
1303 |
|
|
1304 |
public int getDisp(int inst) {
|
|
1305 |
return this.disp.getBits(inst);
|
|
1306 |
}
|
|
1307 |
|
|
1308 |
public abstract boolean isAnnulable(int inst);
|
|
1309 |
|
|
1310 |
public abstract boolean isConditional(int inst);
|
|
1311 |
}
|
|
1312 |
|
|
1313 |
public static final class Bpcc extends ControlTransferOp {
|
|
1314 |
public Bpcc(Op2s op2) {
|
|
1315 |
super(Ops.BranchOp, op2, true, BitSpec.disp19);
|
|
1316 |
}
|
|
1317 |
|
|
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
|
|
1329 |
public boolean isAnnulable(int inst) {
|
|
1330 |
return isConditional(inst);
|
|
1331 |
}
|
|
1332 |
|
|
1333 |
@Override
|
|
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 {
|
|
1341 |
public Br() {
|
|
1342 |
super(Ops.BranchOp, Op2s.Br, true, BitSpec.disp22);
|
|
1343 |
}
|
|
1344 |
|
|
1345 |
@Override
|
|
1346 |
public boolean isAnnulable(int inst) {
|
|
1347 |
return isConditional(inst);
|
|
1348 |
}
|
|
1349 |
|
|
1350 |
@Override
|
|
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 |
|
|
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 |
|
|
1368 |
public Bpr() {
|
|
1369 |
super(Ops.BranchOp, Op2s.Bpr, true, BitSpec.d16);
|
|
1370 |
}
|
|
1371 |
|
|
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
|
|
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
|
|
1390 |
public boolean isAnnulable(int inst) {
|
|
1391 |
return isConditional(inst);
|
|
1392 |
}
|
|
1393 |
|
|
1394 |
@Override
|
|
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 |
|
|
1404 |
private CBCond() {
|
|
1405 |
super(Ops.BranchOp, Op2s.Bpr, false, BitSpec.d10);
|
|
1406 |
}
|
|
1407 |
|
|
1408 |
@Override
|
|
1409 |
protected List<BitKey[]> getKeys() {
|
|
1410 |
List<BitKey[]> keys = super.getKeys();
|
|
1411 |
keys.add(new BitKey[]{CBCOND_KEY});
|
|
1412 |
return keys;
|
|
1413 |
}
|
|
1414 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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
|
|
1445 |
public boolean isAnnulable(int inst) {
|
|
1446 |
return false;
|
|
1447 |
}
|
|
1448 |
|
|
1449 |
@Override
|
|
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 |
|
|
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
|
|
1466 |
protected int setBits(int word) {
|
|
1467 |
int result = super.setBits(word);
|
|
1468 |
return BitSpec.op2.setBits(result, op2.value);
|
|
1469 |
}
|
|
1470 |
|
|
1471 |
@Override
|
|
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 {
|
|
1480 |
public Sethi() {
|
|
1481 |
super(Ops.BranchOp, Op2s.Sethi);
|
|
1482 |
}
|
|
1483 |
|
|
1484 |
public static Register getRS1(int word) {
|
|
1485 |
int regNum = BitSpec.rs1.getBits(word);
|
|
1486 |
return SPARC.cpuRegisters.get(regNum);
|
|
1487 |
}
|
|
1488 |
|
|
1489 |
public static int getImm22(int word) {
|
|
1490 |
return BitSpec.imm22.getBits(word);
|
|
1491 |
}
|
|
1492 |
|
|
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 {
|
|
1499 |
public Op3Op() {
|
|
1500 |
super(ArithOp);
|
|
1501 |
}
|
|
1502 |
|
|
1503 |
public Op3s getOp3(int inst) {
|
|
1504 |
assert match(inst);
|
|
1505 |
return OP3S[ArithOp.value & 1][BitSpec.op3.getBits(inst)];
|
|
1506 |
}
|
|
1507 |
|
|
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 |
|
|
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 |
|
|
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 {
|
|
1558 |
void emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, Register rs2, Register rd);
|
|
1559 |
|
|
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 |
|
|
1566 |
public MOVicc() {
|
|
1567 |
super(ArithOp);
|
|
1568 |
}
|
|
1569 |
|
|
1570 |
@Override
|
|
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
|
|
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 |
|
|
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
|
|
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 |
|
|
1605 |
public FMOVcc(OpfLow opfLow) {
|
|
1606 |
super(ArithOp);
|
|
1607 |
this.opfLow = opfLow;
|
|
1608 |
}
|
|
1609 |
|
|
1610 |
@Override
|
|
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
|
|
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
|
|
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 |
|
|
1640 |
public OpfOp(BitKey... op3Keys) {
|
|
1641 |
super(ArithOp);
|
|
1642 |
this.op3Keys = op3Keys;
|
|
1643 |
}
|
|
1644 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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
|
|
1678 |
protected List<BitKey[]> getKeys() {
|
|
1679 |
List<BitKey[]> keys = super.getKeys();
|
|
1680 |
keys.add(op3Keys);
|
|
1681 |
// @formatter:on
|
|
1682 |
return keys;
|
|
1683 |
}
|
|
1684 |
}
|
|
1685 |
|
|
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 |
|
|
1695 |
public static boolean isCPURegister(Register r) {
|
|
1696 |
return r.getRegisterCategory().equals(CPU);
|
|
1697 |
}
|
|
1698 |
|
|
1699 |
public static boolean isGlobalRegister(Register r) {
|
|
1700 |
return isCPURegister(r) && g0.number <= r.number && r.number <= g7.number;
|
|
1701 |
}
|
|
1702 |
|
|
1703 |
public static boolean isSingleFloatRegister(Register r) {
|
|
1704 |
return r.getRegisterCategory().equals(FPUs);
|
|
1705 |
}
|
|
1706 |
|
|
1707 |
public static boolean isDoubleFloatRegister(Register r) {
|
|
1708 |
return r.getRegisterCategory().equals(FPUd);
|
|
1709 |
}
|
|
1710 |
|
|
1711 |
public boolean hasFeature(CPUFeature feature) {
|
|
1712 |
return ((SPARC) this.target.arch).features.contains(feature);
|
|
1713 |
}
|
|
1714 |
|
|
1715 |
public static final int simm(int x, int nbits) {
|
|
1716 |
// assert_signed_range(x, nbits);
|
|
1717 |
return x & ((1 << nbits) - 1);
|
|
1718 |
}
|
|
1719 |
|
|
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 |
*/
|
|
1728 |
public static long minSimm(long nbits) {
|
|
1729 |
return -(1L << (nbits - 1));
|
|
1730 |
}
|
|
1731 |
|
|
1732 |
/**
|
|
1733 |
* Maximum value for signed immediate ranges.
|
|
1734 |
*/
|
|
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 |
*/
|
|
1742 |
public static boolean isSimm(long imm, int nbits) {
|
|
1743 |
return minSimm(nbits) <= imm && imm <= maxSimm(nbits);
|
|
1744 |
}
|
|
1745 |
|
|
1746 |
public static boolean isSimm10(long imm) {
|
|
1747 |
return isSimm(imm, 10);
|
|
1748 |
}
|
|
1749 |
|
|
1750 |
public static boolean isSimm11(long imm) {
|
|
1751 |
return isSimm(imm, 11);
|
|
1752 |
}
|
|
1753 |
|
|
1754 |
public static boolean isSimm11(JavaConstant constant) {
|
|
1755 |
return constant.isNull() || isSimm11(constant.asLong());
|
|
1756 |
}
|
|
1757 |
|
|
1758 |
public static boolean isSimm5(JavaConstant constant) {
|
|
1759 |
return constant.isNull() || isSimm(constant.asLong(), 5);
|
|
1760 |
}
|
|
1761 |
|
46371
|
1762 |
public static boolean isSimm5(long imm) {
|
|
1763 |
return isSimm(imm, 5);
|
|
1764 |
}
|
|
1765 |
|
43972
|
1766 |
public static boolean isSimm13(int imm) {
|
|
1767 |
return isSimm(imm, 13);
|
|
1768 |
}
|
|
1769 |
|
|
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 |
|
|
1788 |
public static boolean isSimm13(long imm) {
|
|
1789 |
return NumUtil.isInt(imm) && isSimm(imm, 13);
|
|
1790 |
}
|
|
1791 |
|
|
1792 |
public static boolean isWordDisp30(long imm) {
|
|
1793 |
return isSimm(imm, 30 + 2);
|
|
1794 |
}
|
|
1795 |
|
|
1796 |
public static final int hi22(int x) {
|
|
1797 |
return x >>> 10;
|
|
1798 |
}
|
|
1799 |
|
|
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
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
1853 |
protected int patchUnbound(Label label) {
|
54601
|
1854 |
label.addPatchAt(position(), this);
|
43972
|
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
|
|
1867 |
public void nop() {
|
|
1868 |
emitInt(1 << 24);
|
|
1869 |
}
|
|
1870 |
|
|
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
|
|
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 |
|
|
1896 |
public void add(Register rs1, Register rs2, Register rd) {
|
|
1897 |
op3(Add, rs1, rs2, rd);
|
|
1898 |
}
|
|
1899 |
|
|
1900 |
public void add(Register rs1, int simm13, Register rd) {
|
|
1901 |
op3(Add, rs1, simm13, rd);
|
|
1902 |
}
|
|
1903 |
|
|
1904 |
public void addc(Register rs1, Register rs2, Register rd) {
|
|
1905 |
op3(Addc, rs1, rs2, rd);
|
|
1906 |
}
|
|
1907 |
|
|
1908 |
public void addc(Register rs1, int simm13, Register rd) {
|
|
1909 |
op3(Addc, rs1, simm13, rd);
|
|
1910 |
}
|
|
1911 |
|
|
1912 |
public void addcc(Register rs1, Register rs2, Register rd) {
|
|
1913 |
op3(Addcc, rs1, rs2, rd);
|
|
1914 |
}
|
|
1915 |
|
|
1916 |
public void addcc(Register rs1, int simm13, Register rd) {
|
|
1917 |
op3(Addcc, rs1, simm13, rd);
|
|
1918 |
}
|
|
1919 |
|
|
1920 |
public void and(Register rs1, Register rs2, Register rd) {
|
|
1921 |
op3(And, rs1, rs2, rd);
|
|
1922 |
}
|
|
1923 |
|
|
1924 |
public void and(Register rs1, int simm13, Register rd) {
|
|
1925 |
op3(And, rs1, simm13, rd);
|
|
1926 |
}
|
|
1927 |
|
|
1928 |
public void andcc(Register rs1, Register rs2, Register rd) {
|
|
1929 |
op3(Andcc, rs1, rs2, rd);
|
|
1930 |
}
|
|
1931 |
|
|
1932 |
public void andcc(Register rs1, int simm13, Register rd) {
|
|
1933 |
op3(Andcc, rs1, simm13, rd);
|
|
1934 |
}
|
|
1935 |
|
|
1936 |
public void andn(Register rs1, Register rs2, Register rd) {
|
|
1937 |
op3(Andn, rs1, rs2, rd);
|
|
1938 |
}
|
|
1939 |
|
|
1940 |
public void andn(Register rs1, int simm13, Register rd) {
|
|
1941 |
op3(Andn, rs1, simm13, rd);
|
|
1942 |
}
|
|
1943 |
|
|
1944 |
public void andncc(Register rs1, Register rs2, Register rd) {
|
|
1945 |
op3(Andncc, rs1, rs2, rd);
|
|
1946 |
}
|
|
1947 |
|
|
1948 |
public void andncc(Register rs1, int simm13, Register rd) {
|
|
1949 |
op3(Andncc, rs1, simm13, rd);
|
|
1950 |
}
|
|
1951 |
|
|
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 |
|
|
1957 |
public void umulxhi(Register rs1, Register rs2, Register rd) {
|
|
1958 |
op3(Impdep1, UMulxhi, rs1, rs2, rd);
|
|
1959 |
}
|
|
1960 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
1986 |
public void fadds(Register rs1, Register rs2, Register rd) {
|
|
1987 |
op3(Fpop1, Fadds, rs1, rs2, rd);
|
|
1988 |
}
|
|
1989 |
|
|
1990 |
public void faddd(Register rs1, Register rs2, Register rd) {
|
|
1991 |
op3(Fpop1, Faddd, rs1, rs2, rd);
|
|
1992 |
}
|
|
1993 |
|
|
1994 |
public void fdivs(Register rs1, Register rs2, Register rd) {
|
|
1995 |
op3(Fpop1, Fdivs, rs1, rs2, rd);
|
|
1996 |
}
|
|
1997 |
|
|
1998 |
public void fdivd(Register rs1, Register rs2, Register rd) {
|
|
1999 |
op3(Fpop1, Fdivd, rs1, rs2, rd);
|
|
2000 |
}
|
|
2001 |
|
|
2002 |
public void fmovs(Register rs2, Register rd) {
|
|
2003 |
op3(Fpop1, Fmovs, null, rs2, rd);
|
|
2004 |
}
|
|
2005 |
|
|
2006 |
public void fmovd(Register rs2, Register rd) {
|
|
2007 |
op3(Fpop1, Fmovd, null, rs2, rd);
|
|
2008 |
}
|
|
2009 |
|
|
2010 |
public void fsrc2s(Register rs2, Register rd) {
|
|
2011 |
op3(Impdep1, Fsrc2s, null, rs2, rd);
|
|
2012 |
}
|
|
2013 |
|
|
2014 |
public void fsrc2d(Register rs2, Register rd) {
|
|
2015 |
op3(Impdep1, Fsrc2d, null, rs2, rd);
|
|
2016 |
}
|
|
2017 |
|
|
2018 |
public void fmuls(Register rs1, Register rs2, Register rd) {
|
|
2019 |
op3(Fpop1, Fmuls, rs1, rs2, rd);
|
|
2020 |
}
|
|
2021 |
|
|
2022 |
public void fsmuld(Register rs1, Register rs2, Register rd) {
|
|
2023 |
op3(Fpop1, Fsmuld, rs1, rs2, rd);
|
|
2024 |
}
|
|
2025 |
|
|
2026 |
public void fmuld(Register rs1, Register rs2, Register rd) {
|
|
2027 |
op3(Fpop1, Fmuld, rs1, rs2, rd);
|
|
2028 |
}
|
|
2029 |
|
|
2030 |
public void fnegs(Register rs2, Register rd) {
|
|
2031 |
op3(Fpop1, Fnegs, null, rs2, rd);
|
|
2032 |
}
|
|
2033 |
|
|
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 |
*/
|
|
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 |
|
|
2052 |
public void fstoi(Register rs2, Register rd) {
|
|
2053 |
op3(Fpop1, Fstoi, null, rs2, rd);
|
|
2054 |
}
|
|
2055 |
|
|
2056 |
public void fstox(Register rs2, Register rd) {
|
|
2057 |
op3(Fpop1, Fstox, null, rs2, rd);
|
|
2058 |
}
|
|
2059 |
|
|
2060 |
public void fdtox(Register rs2, Register rd) {
|
|
2061 |
op3(Fpop1, Fdtox, null, rs2, rd);
|
|
2062 |
}
|
|
2063 |
|
|
2064 |
public void fstod(Register rs2, Register rd) {
|
|
2065 |
op3(Fpop1, Fstod, null, rs2, rd);
|
|
2066 |
}
|
|
2067 |
|
|
2068 |
public void fdtoi(Register rs2, Register rd) {
|
|
2069 |
op3(Fpop1, Fdtoi, null, rs2, rd);
|
|
2070 |
}
|
|
2071 |
|
|
2072 |
public void fitos(Register rs2, Register rd) {
|
|
2073 |
op3(Fpop1, Fitos, null, rs2, rd);
|
|
2074 |
}
|
|
2075 |
|
|
2076 |
public void fitod(Register rs2, Register rd) {
|
|
2077 |
op3(Fpop1, Fitod, null, rs2, rd);
|
|
2078 |
}
|
|
2079 |
|
|
2080 |
public void fxtos(Register rs2, Register rd) {
|
|
2081 |
op3(Fpop1, Fxtos, null, rs2, rd);
|
|
2082 |
}
|
|
2083 |
|
|
2084 |
public void fxtod(Register rs2, Register rd) {
|
|
2085 |
op3(Fpop1, Fxtod, null, rs2, rd);
|
|
2086 |
}
|
|
2087 |
|
|
2088 |
public void fzeros(Register rd) {
|
|
2089 |
op3(Impdep1, Fzeros, null, null, rd);
|
|
2090 |
}
|
|
2091 |
|
|
2092 |
public void fzerod(Register rd) {
|
|
2093 |
op3(Impdep1, Fzerod, null, null, rd);
|
|
2094 |
}
|
|
2095 |
|
|
2096 |
public void flushw() {
|
|
2097 |
op3(Flushw, g0, g0, g0);
|
|
2098 |
}
|
|
2099 |
|
|
2100 |
public void fsqrtd(Register rs2, Register rd) {
|
|
2101 |
op3(Fpop1, Fsqrtd, null, rs2, rd);
|
|
2102 |
}
|
|
2103 |
|
|
2104 |
public void fsqrts(Register rs2, Register rd) {
|
|
2105 |
op3(Fpop1, Fsqrts, null, rs2, rd);
|
|
2106 |
}
|
|
2107 |
|
|
2108 |
public void fabss(Register rs2, Register rd) {
|
|
2109 |
op3(Fpop1, Fabss, null, rs2, rd);
|
|
2110 |
}
|
|
2111 |
|
|
2112 |
public void fabsd(Register rs2, Register rd) {
|
|
2113 |
op3(Fpop1, Fabsd, null, rs2, rd);
|
|
2114 |
}
|
|
2115 |
|
|
2116 |
public void fsubs(Register rs1, Register rs2, Register rd) {
|
|
2117 |
op3(Fpop1, Fsubs, rs1, rs2, rd);
|
|
2118 |
}
|
|
2119 |
|
|
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
|
|
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
|
|
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
|
|
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 |
|
|
2168 |
public void illtrap(int const22) {
|
|
2169 |
fmt00(0, Op2s.Illtrap.value, const22);
|
|
2170 |
}
|
|
2171 |
|
|
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 |
*/
|
|
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 |
|
|
2187 |
public void fmovdcc(ConditionFlag cond, CC cc, Register rs2, Register rd) {
|
|
2188 |
fmovcc(cond, cc, rs2, rd, OpfLow.Fmovdcc.value);
|
|
2189 |
}
|
|
2190 |
|
|
2191 |
public void fmovscc(ConditionFlag cond, CC cc, Register rs2, Register rd) {
|
|
2192 |
fmovcc(cond, cc, rs2, rd, OpfLow.Fmovscc.value);
|
|
2193 |
}
|
|
2194 |
|
|
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 |
|
|
2201 |
public void movcc(ConditionFlag conditionFlag, CC cc, Register rs2, Register rd) {
|
|
2202 |
movcc(conditionFlag, cc, 0, rs2.encoding, rd);
|
|
2203 |
}
|
|
2204 |
|
|
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 |
|
|
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 |
|
|
2218 |
public void mulx(Register rs1, Register rs2, Register rd) {
|
|
2219 |
op3(Mulx, rs1, rs2, rd);
|
|
2220 |
}
|
|
2221 |
|
|
2222 |
public void mulx(Register rs1, int simm13, Register rd) {
|
|
2223 |
op3(Mulx, rs1, simm13, rd);
|
|
2224 |
}
|
|
2225 |
|
|
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 |
|
|
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 |
|
|
2236 |
public void popc(Register rs2, Register rd) {
|
|
2237 |
op3(Popc, g0, rs2, rd);
|
|
2238 |
}
|
|
2239 |
|
|
2240 |
public void popc(int simm13, Register rd) {
|
|
2241 |
op3(Popc, g0, simm13, rd);
|
|
2242 |
}
|
|
2243 |
|
|
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 |
|
|
2258 |
public void rdpc(Register rd) {
|
|
2259 |
op3(Rd, g5, g0, rd);
|
|
2260 |
}
|
|
2261 |
|
|
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 |
|
|
2268 |
public void save(Register rs1, Register rs2, Register rd) {
|
|
2269 |
op3(Save, rs1, rs2, rd);
|
|
2270 |
}
|
|
2271 |
|
|
2272 |
public void save(Register rs1, int simm13, Register rd) {
|
|
2273 |
op3(Save, rs1, simm13, rd);
|
|
2274 |
}
|
|
2275 |
|
|
2276 |
public void sdivx(Register rs1, Register rs2, Register rd) {
|
|
2277 |
op3(Sdivx, rs1, rs2, rd);
|
|
2278 |
}
|
|
2279 |
|
|
2280 |
public void sdivx(Register rs1, int simm13, Register rd) {
|
|
2281 |
op3(Sdivx, rs1, simm13, rd);
|
|
2282 |
}
|
|
2283 |
|
|
2284 |
public void udivx(Register rs1, Register rs2, Register rd) {
|
|
2285 |
op3(Udivx, rs1, rs2, rd);
|
|
2286 |
}
|
|
2287 |
|
|
2288 |
public void udivx(Register rs1, int simm13, Register rd) {
|
|
2289 |
op3(Udivx, rs1, simm13, rd);
|
|
2290 |
}
|
|
2291 |
|
|
2292 |
public void sll(Register rs1, Register rs2, Register rd) {
|
|
2293 |
op3(Sll, rs1, rs2, rd);
|
|
2294 |
}
|
|
2295 |
|
|
2296 |
public void sll(Register rs1, int shcnt32, Register rd) {
|
|
2297 |
assert isImm(shcnt32, 5);
|
|
2298 |
op3(Sll, rs1, shcnt32, rd);
|
|
2299 |
}
|
|
2300 |
|
|
2301 |
public void sllx(Register rs1, Register rs2, Register rd) {
|
|
2302 |
op3(Sllx, rs1, rs2, rd);
|
|
2303 |
}
|
|
2304 |
|
|
2305 |
public void sllx(Register rs1, int shcnt64, Register rd) {
|
|
2306 |
assert isImm(shcnt64, 6);
|
|
2307 |
op3(Sllx, rs1, shcnt64, rd);
|
|
2308 |
}
|
|
2309 |
|
|
2310 |
public void sra(Register rs1, Register rs2, Register rd) {
|
|
2311 |
op3(Sra, rs1, rs2, rd);
|
|
2312 |
}
|
|
2313 |
|
|
2314 |
public void sra(Register rs1, int simm13, Register rd) {
|
|
2315 |
op3(Sra, rs1, simm13, rd);
|
|
2316 |
}
|
|
2317 |
|
|
2318 |
public void srax(Register rs1, Register rs2, Register rd) {
|
|
2319 |
op3(Srax, rs1, rs2, rd);
|
|
2320 |
}
|
|
2321 |
|
|
2322 |
public void srax(Register rs1, int shcnt64, Register rd) {
|
|
2323 |
assert isImm(shcnt64, 6);
|
|
2324 |
op3(Srax, rs1, shcnt64, rd);
|
|
2325 |
}
|
|
2326 |
|
|
2327 |
public void srl(Register rs1, Register rs2, Register rd) {
|
|
2328 |
op3(Srl, rs1, rs2, rd);
|
|
2329 |
}
|
|
2330 |
|
|
2331 |
public void srl(Register rs1, int simm13, Register rd) {
|
|
2332 |
op3(Srl, rs1, simm13, rd);
|
|
2333 |
}
|
|
2334 |
|
|
2335 |
public void srlx(Register rs1, Register rs2, Register rd) {
|
|
2336 |
op3(Srlx, rs1, rs2, rd);
|
|
2337 |
}
|
|
2338 |
|
|
2339 |
public void srlx(Register rs1, int shcnt64, Register rd) {
|
|
2340 |
assert isImm(shcnt64, 6);
|
|
2341 |
op3(Srlx, rs1, shcnt64, rd);
|
|
2342 |
}
|
|
2343 |
|
|
2344 |
public void sub(Register rs1, Register rs2, Register rd) {
|
|
2345 |
op3(Sub, rs1, rs2, rd);
|
|
2346 |
}
|
|
2347 |
|
|
2348 |
public void sub(Register rs1, int simm13, Register rd) {
|
|
2349 |
op3(Sub, rs1, simm13, rd);
|
|
2350 |
}
|
|
2351 |
|
|
2352 |
public void subcc(Register rs1, Register rs2, Register rd) {
|
|
2353 |
op3(Subcc, rs1, rs2, rd);
|
|
2354 |
}
|
|
2355 |
|
|
2356 |
public void subcc(Register rs1, int simm13, Register rd) {
|
|
2357 |
op3(Subcc, rs1, simm13, rd);
|
|
2358 |
}
|
|
2359 |
|
|
2360 |
public void ta(int trap) {
|
|
2361 |
tcc(Icc, Always, trap);
|
|
2362 |
}
|
|
2363 |
|
|
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 |
|
|
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 |
|
|
2379 |
public void wrccr(Register rs1, Register rs2) {
|
|
2380 |
op3(Wr, rs1, rs2, g2);
|
|
2381 |
}
|
|
2382 |
|
|
2383 |
public void wrccr(Register rs1, int simm13) {
|
|
2384 |
op3(Wr, rs1, simm13, g2);
|
|
2385 |
}
|
|
2386 |
|
|
2387 |
public void xor(Register rs1, Register rs2, Register rd) {
|
|
2388 |
op3(Xor, rs1, rs2, rd);
|
|
2389 |
}
|
|
2390 |
|
|
2391 |
public void xor(Register rs1, int simm13, Register rd) {
|
|
2392 |
op3(Xor, rs1, simm13, rd);
|
|
2393 |
}
|
|
2394 |
|
|
2395 |
public void xorcc(Register rs1, Register rs2, Register rd) {
|
|
2396 |
op3(Xorcc, rs1, rs2, rd);
|
|
2397 |
}
|
|
2398 |
|
|
2399 |
public void xorcc(Register rs1, int simm13, Register rd) {
|
|
2400 |
op3(Xorcc, rs1, simm13, rd);
|
|
2401 |
}
|
|
2402 |
|
|
2403 |
public void xnor(Register rs1, Register rs2, Register rd) {
|
|
2404 |
op3(Xnor, rs1, rs2, rd);
|
|
2405 |
}
|
|
2406 |
|
|
2407 |
public void xnor(Register rs1, int simm13, Register rd) {
|
|
2408 |
op3(Xnor, rs1, simm13, rd);
|
|
2409 |
}
|
|
2410 |
|
|
2411 |
/*
|
|
2412 |
* Load/Store
|
|
2413 |
*/
|
|
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 |
|
|
2431 |
protected void ld(Op3s op3, SPARCAddress addr, Register rd) {
|
|
2432 |
ld(op3, addr, rd, null);
|
|
2433 |
}
|
|
2434 |
|
|
2435 |
public void lddf(SPARCAddress src, Register dst) {
|
|
2436 |
assert isDoubleFloatRegister(dst) : dst;
|
|
2437 |
ld(Lddf, src, dst);
|
|
2438 |
}
|
|
2439 |
|
|
2440 |
public void ldf(SPARCAddress src, Register dst) {
|
|
2441 |
assert isSingleFloatRegister(dst) : dst;
|
|
2442 |
ld(Ldf, src, dst);
|
|
2443 |
}
|
|
2444 |
|
|
2445 |
public void lduh(SPARCAddress src, Register dst) {
|
|
2446 |
assert isCPURegister(dst) : dst;
|
|
2447 |
ld(Lduh, src, dst);
|
|
2448 |
}
|
|
2449 |
|
|
2450 |
public void ldsh(SPARCAddress src, Register dst) {
|
|
2451 |
assert isCPURegister(dst) : dst;
|
|
2452 |
ld(Ldsh, src, dst);
|
|
2453 |
}
|
|
2454 |
|
|
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 |
|
|
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 |
|
|
2530 |
public void ldub(SPARCAddress src, Register dst) {
|
|
2531 |
assert isCPURegister(dst) : dst;
|
|
2532 |
ld(Ldub, src, dst);
|
|
2533 |
}
|
|
2534 |
|
|
2535 |
public void ldsb(SPARCAddress src, Register dst) {
|
|
2536 |
assert isCPURegister(dst) : dst;
|
|
2537 |
ld(Ldsb, src, dst);
|
|
2538 |
}
|
|
2539 |
|
|
2540 |
public void lduw(SPARCAddress src, Register dst) {
|
|
2541 |
assert isCPURegister(dst) : dst;
|
|
2542 |
ld(Lduw, src, dst);
|
|
2543 |
}
|
|
2544 |
|
|
2545 |
public void ldsw(SPARCAddress src, Register dst) {
|
|
2546 |
assert isCPURegister(dst) : dst;
|
|
2547 |
ld(Ldsw, src, dst);
|
|
2548 |
}
|
|
2549 |
|
|
2550 |
public void ldx(SPARCAddress src, Register dst) {
|
|
2551 |
assert isCPURegister(dst) : dst;
|
|
2552 |
ld(Ldx, src, dst);
|
|
2553 |
}
|
|
2554 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
2570 |
protected void st(Op3s op3, Register rs1, SPARCAddress dest) {
|
|
2571 |
ld(op3, dest, rs1);
|
|
2572 |
}
|
|
2573 |
|
|
2574 |
public void stdf(Register rd, SPARCAddress addr) {
|
|
2575 |
assert isDoubleFloatRegister(rd) : rd;
|
|
2576 |
st(Stdf, rd, addr);
|
|
2577 |
}
|
|
2578 |
|
|
2579 |
public void stf(Register rd, SPARCAddress addr) {
|
|
2580 |
assert isSingleFloatRegister(rd) : rd;
|
|
2581 |
st(Stf, rd, addr);
|
|
2582 |
}
|
|
2583 |
|
|
2584 |
public void stb(Register rd, SPARCAddress addr) {
|
|
2585 |
assert isCPURegister(rd) : rd;
|
|
2586 |
st(Stb, rd, addr);
|
|
2587 |
}
|
|
2588 |
|
|
2589 |
public void sth(Register rd, SPARCAddress addr) {
|
|
2590 |
assert isCPURegister(rd) : rd;
|
|
2591 |
st(Sth, rd, addr);
|
|
2592 |
}
|
|
2593 |
|
|
2594 |
public void stw(Register rd, SPARCAddress addr) {
|
|
2595 |
assert isCPURegister(rd) : rd;
|
|
2596 |
st(Stw, rd, addr);
|
|
2597 |
}
|
|
2598 |
|
|
2599 |
public void stx(Register rd, SPARCAddress addr) {
|
|
2600 |
assert isCPURegister(rd) : rd;
|
|
2601 |
st(Stx, rd, addr);
|
|
2602 |
}
|
|
2603 |
|
|
2604 |
public void membar(int barriers) {
|
|
2605 |
op3(Membar, o7, barriers, g0);
|
|
2606 |
}
|
|
2607 |
|
|
2608 |
public void casa(Register rs1, Register rs2, Register rd, Asi asi) {
|
|
2609 |
ld(Casa, new SPARCAddress(rs1, rs2), rd, asi);
|
|
2610 |
}
|
|
2611 |
|
|
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
|
|
2617 |
public InstructionCounter getInstructionCounter() {
|
|
2618 |
return new SPARCInstructionCounter(this);
|
|
2619 |
}
|
|
2620 |
|
|
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 |
|
|
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 |
*/
|
|
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 |
*/
|
|
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 |
}
|