Mercurial > hg > truffle
comparison graal/com.oracle.jvmci.asm.sparc/src/com/oracle/jvmci/asm/sparc/SPARCAssembler.java @ 21708:6df25b1418be
moved com.oracle.asm.** to jvmci-util.jar (JBS:GRAAL-53)
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Wed, 03 Jun 2015 18:06:44 +0200 |
parents | graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java@5024c80224c7 |
children |
comparison
equal
deleted
inserted
replaced
21707:e0f311284930 | 21708:6df25b1418be |
---|---|
1 /* | |
2 * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. | |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
20 * or visit www.oracle.com if you need additional information or have any | |
21 * questions. | |
22 */ | |
23 package com.oracle.jvmci.asm.sparc; | |
24 | |
25 import static com.oracle.jvmci.asm.sparc.SPARCAssembler.CC.*; | |
26 import static com.oracle.jvmci.asm.sparc.SPARCAssembler.ConditionFlag.*; | |
27 import static com.oracle.jvmci.asm.sparc.SPARCAssembler.Op.*; | |
28 import static com.oracle.jvmci.asm.sparc.SPARCAssembler.Op3s.*; | |
29 import static com.oracle.jvmci.asm.sparc.SPARCAssembler.Opfs.*; | |
30 import static com.oracle.jvmci.sparc.SPARC.*; | |
31 import static java.lang.String.*; | |
32 | |
33 import com.oracle.jvmci.asm.*; | |
34 import com.oracle.jvmci.code.*; | |
35 import com.oracle.jvmci.meta.*; | |
36 import com.oracle.jvmci.sparc.*; | |
37 import com.oracle.jvmci.sparc.SPARC.CPUFeature; | |
38 | |
39 /** | |
40 * This class implements an assembler that can encode most SPARC instructions. | |
41 */ | |
42 public abstract class SPARCAssembler extends Assembler { | |
43 | |
44 /** | |
45 * Constructs an assembler for the SPARC architecture. | |
46 * | |
47 * @param registerConfig the register configuration used to bind {@link Register#Frame} and | |
48 * {@link Register#CallerFrame} to physical registers. This value can be null if this | |
49 * assembler instance will not be used to assemble instructions using these logical | |
50 * registers. | |
51 */ | |
52 public SPARCAssembler(TargetDescription target, RegisterConfig registerConfig) { | |
53 super(target); | |
54 } | |
55 | |
56 public static final int CCR_ICC_SHIFT = 0; | |
57 public static final int CCR_XCC_SHIFT = 4; | |
58 public static final int CCR_C_SHIFT = 0; | |
59 public static final int CCR_V_SHIFT = 1; | |
60 public static final int CCR_Z_SHIFT = 2; | |
61 public static final int CCR_N_SHIFT = 3; | |
62 | |
63 protected static final int OP_SHIFT = 30; | |
64 protected static final int CBCOND_SHIFT = 28; | |
65 protected static final int OP2_SHIFT = 22; | |
66 protected static final int A_SHIFT = 29; | |
67 | |
68 protected static final int A_MASK = 0b0010_0000_0000_0000_0000_0000_0000_0000; | |
69 protected static final int OP_MASK = 0b1100_0000_0000_0000_0000_0000_0000_0000; | |
70 protected static final int CBCOND_MASK = 0b0001_0000_0000_0000_0000_0000_0000_0000; // Used for | |
71 // distinguish CBcond and BPr instructions | |
72 protected static final int OP2_MASK = 0b0000_0001_1100_0000_0000_0000_0000_0000; | |
73 | |
74 protected static final int DISP22_SHIFT = 0; | |
75 protected static final int DISP22_MASK = 0b00000000001111111111111111111111; | |
76 | |
77 protected static final int DISP19_SHIFT = 0; | |
78 protected static final int DISP19_MASK = 0b00000000000001111111111111111111; | |
79 | |
80 protected static final int D16HI_SHIFT = 20; | |
81 protected static final int D16HI_MASK = 0b0000_0000_0011_0000_0000_0000_0000_0000; | |
82 protected static final int D16LO_SHIFT = 0; | |
83 protected static final int D16LO_MASK = 0b0000_0000_0000_0000_0011_1111_1111_1111; | |
84 | |
85 protected static final int D10LO_MASK = 0b0000_0000_0000_0000_0001_1111_1110_0000; | |
86 protected static final int D10HI_MASK = 0b0000_0000_0001_1000_0000_0000_0000_0000; | |
87 protected static final int D10LO_SHIFT = 5; | |
88 protected static final int D10HI_SHIFT = 19; | |
89 | |
90 public enum Ops { | |
91 // @formatter:off | |
92 | |
93 BranchOp(0b00), | |
94 CallOp(0b01), | |
95 ArithOp(0b10), | |
96 LdstOp(0b11); | |
97 | |
98 // @formatter:on | |
99 | |
100 private final int value; | |
101 | |
102 private Ops(int value) { | |
103 this.value = value; | |
104 } | |
105 | |
106 public int getValue() { | |
107 return value; | |
108 } | |
109 | |
110 public boolean appliesTo(int instructionWord) { | |
111 int opShift = 30; | |
112 return (instructionWord >>> opShift) == value; | |
113 } | |
114 } | |
115 | |
116 public enum Op { | |
117 Op00(0b00), | |
118 Op01(0b01), | |
119 Op10(0b10), | |
120 Op11(0b11); | |
121 int op; | |
122 | |
123 Op(int op) { | |
124 this.op = op; | |
125 } | |
126 } | |
127 | |
128 public enum Op2s { | |
129 // @formatter:off | |
130 | |
131 Illtrap(0b000), | |
132 Bpr (0b011), | |
133 Fb (0b110), | |
134 Fbp (0b101), | |
135 Br (0b010), | |
136 Bp (0b001), | |
137 Cb (0b111), | |
138 Sethi (0b100); | |
139 | |
140 | |
141 // @formatter:on | |
142 | |
143 private final int value; | |
144 | |
145 private Op2s(int value) { | |
146 this.value = value; | |
147 } | |
148 | |
149 public int getValue() { | |
150 return value; | |
151 } | |
152 | |
153 public static Op2s byValue(int value) { | |
154 for (Op2s op : values()) { | |
155 if (op.getValue() == value) { | |
156 return op; | |
157 } | |
158 } | |
159 return null; | |
160 } | |
161 } | |
162 | |
163 public enum Op3s { | |
164 // @formatter:off | |
165 | |
166 Add(0x00, "add", Op10), | |
167 And(0x01, "and", Op10), | |
168 Or(0x02, "or", Op10), | |
169 Xor(0x03, "xor", Op10), | |
170 Sub(0x04, "sub", Op10), | |
171 Andn(0x05, "andn", Op10), | |
172 Orn(0x06, "orn", Op10), | |
173 Xnor(0x07, "xnor", Op10), | |
174 Addc(0x08, "addc", Op10), | |
175 Mulx(0x09, "mulx", Op10), | |
176 Umul(0x0A, "umul", Op10), | |
177 Smul(0x0B, "smul", Op10), | |
178 Subc(0x0C, "subc", Op10), | |
179 Udivx(0x0D, "udivx", Op10), | |
180 Udiv(0x0E, "udiv", Op10), | |
181 Sdiv(0x0F, "sdiv", Op10), | |
182 | |
183 Addcc(0x10, "addcc", Op10), | |
184 Andcc(0x11, "andcc", Op10), | |
185 Orcc(0x12, "orcc", Op10), | |
186 Xorcc(0x13, "xorcc", Op10), | |
187 Subcc(0x14, "subcc", Op10), | |
188 Andncc(0x15, "andncc", Op10), | |
189 Orncc(0x16, "orncc", Op10), | |
190 Xnorcc(0x17, "xnorcc", Op10), | |
191 Addccc(0x18, "addccc", Op10), | |
192 | |
193 Umulcc(0x1A, "umulcc", Op10), | |
194 Smulcc(0x1B, "smulcc", Op10), | |
195 Subccc(0x1C, "subccc", Op10), | |
196 Udivcc(0x1E, "udivcc", Op10), | |
197 Sdivcc(0x1F, "sdivcc", Op10), | |
198 | |
199 Taddcc(0x20, "taddcc", Op10), | |
200 Tsubcc(0x21, "tsubcc", Op10), | |
201 Taddcctv(0x22, "taddcctv", Op10), | |
202 Tsubcctv(0x23, "tsubcctv", Op10), | |
203 Mulscc(0x24, "mulscc", Op10), | |
204 Sll(0x25, "sll", Op10), | |
205 Sllx(0x25, "sllx", Op10), | |
206 Srl(0x26, "srl", Op10), | |
207 Srlx(0x26, "srlx", Op10), | |
208 Sra(0x27, "srax", Op10), | |
209 Srax(0x27, "srax", Op10), | |
210 Membar(0x28, "membar", Op10), | |
211 | |
212 Flushw(0x2B, "flushw", Op10), | |
213 Movcc(0x2C, "movcc", Op10), | |
214 Sdivx(0x2D, "sdivx", Op10), | |
215 Popc(0x2E, "popc", Op10), | |
216 Movr(0x2F, "movr", Op10), | |
217 | |
218 Fpop1(0b11_0100, "fpop1", Op10), | |
219 Fpop2(0b11_0101, "fpop2", Op10), | |
220 Impdep1(0b11_0110, "impdep1", Op10), | |
221 Impdep2(0b11_0111, "impdep2", Op10), | |
222 Jmpl(0x38, "jmpl", Op10), | |
223 Rett(0x39, "rett", Op10), | |
224 Trap(0x3a, "trap", Op10), | |
225 Flush(0x3b, "flush", Op10), | |
226 Save(0x3c, "save", Op10), | |
227 Restore(0x3d, "restore", Op10), | |
228 Retry(0x3e, "retry", Op10), | |
229 | |
230 | |
231 Casa(0b111100, "casa", Op11), | |
232 Casxa(0b111110, "casxa", Op11), | |
233 Prefetch(0b101101, "prefetch", Op11), | |
234 Prefetcha(0b111101, "prefetcha", Op11), | |
235 | |
236 Lduw (0b00_0000, "lduw", Op11), | |
237 Ldub (0b00_0001, "ldub", Op11), | |
238 Lduh (0b00_0010, "lduh", Op11), | |
239 Stw (0b00_0100, "stw", Op11), | |
240 Stb (0b00_0101, "stb", Op11), | |
241 Sth (0b00_0110, "sth", Op11), | |
242 Ldsw (0b00_1000, "ldsw", Op11), | |
243 Ldsb (0b00_1001, "ldsb", Op11), | |
244 Ldsh (0b00_1010, "ldsh", Op11), | |
245 Ldx (0b00_1011, "ldx", Op11), | |
246 Stx (0b00_1110, "stx", Op11), | |
247 | |
248 Ldf (0b10_0000, "ldf", Op11), | |
249 Ldfsr (0b10_0001, "ldfsr", Op11), | |
250 Ldaf (0b10_0010, "ldaf", Op11), | |
251 Lddf (0b10_0011, "lddf", Op11), | |
252 Stf (0b10_0100, "stf", Op11), | |
253 Stfsr (0b10_0101, "stfsr", Op11), | |
254 Staf (0x10_0110, "staf", Op11), | |
255 Stdf (0b10_0111, "stdf", Op11), | |
256 | |
257 Rd (0b10_1000, "rd", Op10), | |
258 Wr (0b11_0000, "wr", Op10), | |
259 Fcmp (0b11_0101, "fcmp", Op10), | |
260 | |
261 Ldxa (0b01_1011, "ldxa", Op11), | |
262 Lduwa (0b01_0000, "lduwa", Op11), | |
263 | |
264 Tcc(0b11_1010, "tcc", Op10); | |
265 | |
266 // @formatter:on | |
267 | |
268 private final int value; | |
269 private final String operator; | |
270 private final Op op; | |
271 | |
272 private Op3s(int value, String name, Op op) { | |
273 this.value = value; | |
274 this.operator = name; | |
275 this.op = op; | |
276 } | |
277 | |
278 public int getValue() { | |
279 return value; | |
280 } | |
281 | |
282 public String getOperator() { | |
283 return operator; | |
284 } | |
285 | |
286 public boolean appliesTo(int instructionWord) { | |
287 return ((instructionWord >>> 19) & 0b1_1111) == value; | |
288 } | |
289 } | |
290 | |
291 public enum Opfs { | |
292 // @formatter:off | |
293 | |
294 Fmovs(0b0_0000_0001, "fmovs"), | |
295 Fmovd(0b0_0000_0010, "fmovd"), | |
296 Fmovq(0b0_0000_0011, "fmovq"), | |
297 Fmovscc(0b00_0001, "fmovscc"), | |
298 Fmovdcc(0b00_0010, "fmovdcc"), | |
299 Fnegs(0x05, "fnegs"), | |
300 Fnegd(0x06, "fnegd"), | |
301 Fnegq(0x07, "fnegq"), | |
302 Fabss(0x09, "fabss"), | |
303 Fabsd(0x0A, "fabsd"), | |
304 Fabsq(0x0B, "fabsq"), | |
305 | |
306 // start VIS1 | |
307 Edge8cc(0x0, "edge8cc"), | |
308 Edge8n(0x1, "edge8n"), | |
309 Edge8lcc(0x2, "edge8lcc"), | |
310 Edge8ln(0x3, "edge8ln"), | |
311 Edge16cc(0x4, "edge16cc"), | |
312 Edge16n(0x5, "edge16n"), | |
313 Edge16lcc(0x6, "edge16lcc"), | |
314 Edge16ln(0x7, "edge16ln"), | |
315 Edge32cc(0x8, "edge32cc"), | |
316 Edge32n(0x9, "edge32n"), | |
317 Edge32lcc(0xA, "edge32lcc"), | |
318 Edge32ln(0xB, "edge32ln"), | |
319 Array8(0x10, "array8"), | |
320 Array16(0x12, "array16"), | |
321 Array32(0x14, "array32"), | |
322 AlignAddress(0x18, "alignaddress"), | |
323 AlignAddressLittle(0x1A, "alignaddress_little"), | |
324 Fpcmple16(0x20, "fpcmple16"), | |
325 Fpcmpne16(0x22, "fpcmpne16"), | |
326 Fpcmple32(0x24, "fpcmple32"), | |
327 Fpcmpne32(0x26, "fpcmpne32"), | |
328 Fpcmpgt16(0x28, "fpcmpgt16"), | |
329 Fpcmpeq16(0x2A, "fpcmpeq16"), | |
330 Fpcmpgt32(0x2C, "fpcmpgt32"), | |
331 Fpcmpeq32(0x2E, "fpcmpeq32"), | |
332 Fmul8x16(0x31, "fmul8x16"), | |
333 Fmul8x16au(0x33, "fmul8x16au"), | |
334 Fmul8x16al(0x35, "fmul8x16al"), | |
335 Fmul8sux16(0x36, "fmul8sux16"), | |
336 Fmul8ulx16(0x37, "fmul8ulx16"), | |
337 Fmuld8sux16(0x38, "fmuld8sux16"), | |
338 Fmuld8ulx16(0x39, "fmuld8ulx16"), | |
339 Fpack32(0x3A, "fpack32"), | |
340 Fpack16(0x3B, "fpack16"), | |
341 Fpackfix(0x3D, "fpackfix"), | |
342 Faligndatag(0x48, "faligndata"), | |
343 Fpmerge(0x4B, "fpmerge"), | |
344 Fpadd16(0x50, "fpadd16"), | |
345 Fpadd16s(0x51, "fpadd16s"), | |
346 Fpadd32(0x52, "fpadd32"), | |
347 Fpadd32s(0x53, "fpadd32s"), | |
348 Fpsub16(0x54, "fpadd16"), | |
349 Fpsub16s(0x55, "fpadd16s"), | |
350 Fpsub32(0x56, "fpadd32"), | |
351 Fpsub32s(0x57, "fpadd32s"), | |
352 Fzerod(0x60, "fzerod"), | |
353 Fzeros(0x61, "fzeros"), | |
354 Fnot2d(0x66, "fnot1d"), | |
355 Fnot2s(0x67, "fnot1s"), | |
356 Fnot1d(0x6A, "fnot1d"), | |
357 Fnot1s(0x6B, "fnot1s"), | |
358 Fsrc1d(0x74, "fsrc1d"), | |
359 Fsrc1s(0x75, "fsrc1s"), | |
360 Fsrc2d(0x78, "fsrc2d"), | |
361 Fsrc2s(0x79, "fsrc2s"), | |
362 Foned(0x7E, "foned"), | |
363 Fones(0x7F, "fones"), | |
364 Fandd(0b0_0111_0000, "fandd"), | |
365 Fands(0b0_0111_0001, "fands"), | |
366 Fxord(0b0_0110_1100, "fxord"), | |
367 Fxors(0b0_0110_1101, "fxors"), | |
368 // end VIS1 | |
369 | |
370 // start VIS2 | |
371 Bmask(0x19, "bmask"), | |
372 Bshuffle(0x4c, "bshuffle"), | |
373 // end VIS2 only | |
374 | |
375 // start VIS3 | |
376 Addxc(0x11, "addxc"), | |
377 Addxccc(0x13, "addxccc"), | |
378 Cmask8(0x1B, "cmask8"), | |
379 Cmask16(0x1D, "cmask16"), | |
380 Cmask32(0x1F, "cmask32"), | |
381 Fmean16(0x40, "fmean16"), | |
382 Fnadds(0x51, "fnadds"), | |
383 Fnaddd(0x52, "fnaddd"), | |
384 Fnmuls(0x59, "fnmuls"), | |
385 Fnmuld(0x5A, "fnmuld"), | |
386 Fnsmuld(0x79, "fnsmuld"), | |
387 Fnhadds(0x71, "fnhadds"), | |
388 Fnhaddd(0x72, "fnhaddd"), | |
389 Movdtox(0x110, "movdtox"), | |
390 Movstouw(0x111, "movstouw"), | |
391 Movstosw(0x113, "movstosw"), | |
392 Movxtod(0x118, "movxtod"), | |
393 Movwtos(0b1_0001_1001, "movwtos"), | |
394 UMulxhi(0b0_0001_0110, "umulxhi"), | |
395 Lzcnt (0b0_0001_0111, "lzcnt"), | |
396 // end VIS3 | |
397 | |
398 // start CAMMELLIA | |
399 CammelliaFl(0x13C, "cammelia_fl"), | |
400 CammelliaFli(0x13D, "cammellia_fli"), | |
401 // end CAMMELLIA | |
402 | |
403 // start CRYPTO | |
404 Crc32c(0x147, "crc32c"), | |
405 // end CRYPTO | |
406 | |
407 // start OSA 2011 | |
408 Fpadd64(0x44, "fpadd64"), | |
409 Fpsub64(0x46, "fpsub64"), | |
410 Fpadds16(0x58, "fpadds16"), | |
411 Fpadds16s(0x59, "fpadds16"), | |
412 Fpadds32(0x5A, "fpadds32"), | |
413 Fpadds32s(0x5B, "fpadds32s"), | |
414 Fpsubs16(0x5C, "fpsubs16"), | |
415 Fpsubs16s(0x5D, "fpsubs16s"), | |
416 Fpsubs32(0x5E, "fpsubs32"), | |
417 Fpsubs32s(0x5F, "fpsubs32s"), | |
418 Fpcmpne8(0x122, "fpcmpne8"), | |
419 Fpcmpeq8(0x12C, "fpcmpeq8"), | |
420 // end OSA 2011 | |
421 | |
422 Fadds(0x41, "fadds"), | |
423 Faddd(0x42, "faddd"), | |
424 Faddq(0x43, "faddq"), | |
425 Fsubs(0x45, "fsubs"), | |
426 Fsubd(0x46, "fsubd"), | |
427 Fsubq(0x47, "fsubq"), | |
428 Fmuls(0x49, "fmuls"), | |
429 Fmuld(0x4A, "fmuld"), | |
430 Fdivs(0x4D, "fdivs"), | |
431 Fdivd(0x4E, "fdivd"), | |
432 Fdivq(0x4F, "fdivq"), | |
433 | |
434 Fsqrts(0x29, "fsqrts"), | |
435 Fsqrtd(0x2A, "fsqrtd"), | |
436 Fsqrtq(0x2B, "fsqrtq"), | |
437 | |
438 Fsmuld(0x69, "fsmuld"), | |
439 Fmulq(0x6B, "fmulq"), | |
440 Fdmuldq(0x6E, "fdmulq"), | |
441 | |
442 Fstoi(0xD1, "fstoi"), | |
443 Fdtoi(0xD2, "fdtoi"), | |
444 Fstox(0x81, "fstox"), | |
445 Fdtox(0x82, "fdtox"), | |
446 Fxtos(0x84, "fxtos"), | |
447 Fxtod(0x88, "fxtod"), | |
448 Fxtoq(0x8C, "fxtoq"), | |
449 Fitos(0xC4, "fitos"), | |
450 Fdtos(0xC6, "fdtos"), | |
451 Fitod(0xC8, "fitod"), | |
452 Fstod(0xC9, "fstod"), | |
453 Fitoq(0xCC, "fitoq"), | |
454 | |
455 | |
456 Fcmps(0x51, "fcmps"), | |
457 Fcmpd(0x52, "fcmpd"), | |
458 Fcmpq(0x53, "fcmpq"); | |
459 | |
460 // @formatter:on | |
461 | |
462 private final int value; | |
463 private final String operator; | |
464 | |
465 private Opfs(int value, String op) { | |
466 this.value = value; | |
467 this.operator = op; | |
468 } | |
469 | |
470 public int getValue() { | |
471 return value; | |
472 } | |
473 | |
474 public String getOperator() { | |
475 return operator; | |
476 } | |
477 } | |
478 | |
479 public enum Annul { | |
480 ANNUL(1), | |
481 NOT_ANNUL(0); | |
482 public final int flag; | |
483 | |
484 Annul(int flag) { | |
485 this.flag = flag; | |
486 } | |
487 } | |
488 | |
489 public enum BranchPredict { | |
490 PREDICT_TAKEN(1), | |
491 PREDICT_NOT_TAKEN(0); | |
492 public final int flag; | |
493 | |
494 BranchPredict(int flag) { | |
495 this.flag = flag; | |
496 } | |
497 } | |
498 | |
499 public enum MembarMask { | |
500 // @formatter:off | |
501 | |
502 StoreStore(1 << 3, "storestore"), | |
503 LoadStore(1 << 2, "loadstore"), | |
504 StoreLoad(1 << 1, "storeload"), | |
505 LoadLoad(1 << 0, "loadload"), | |
506 Sync(1 << 6, "sync"), | |
507 MemIssue(1 << 5, "memissue"), | |
508 LookAside(1 << 4, "lookaside"); | |
509 | |
510 // @formatter:on | |
511 | |
512 private final int value; | |
513 private final String operator; | |
514 | |
515 private MembarMask(int value, String op) { | |
516 this.value = value; | |
517 this.operator = op; | |
518 } | |
519 | |
520 public int getValue() { | |
521 return value | 0x2000; | |
522 } | |
523 | |
524 public String getOperator() { | |
525 return operator; | |
526 } | |
527 } | |
528 | |
529 /** | |
530 * Condition Codes to use for instruction. | |
531 */ | |
532 public enum CC { | |
533 // @formatter:off | |
534 /** | |
535 * Condition is considered as 32bit operation condition. | |
536 */ | |
537 Icc(0b00, "icc", false), | |
538 /** | |
539 * Condition is considered as 64bit operation condition. | |
540 */ | |
541 Xcc(0b10, "xcc", false), | |
542 Fcc0(0b00, "fcc0", true), | |
543 Fcc1(0b01, "fcc1", true), | |
544 Fcc2(0b10, "fcc2", true), | |
545 Fcc3(0b11, "fcc3", true); | |
546 | |
547 // @formatter:on | |
548 | |
549 private final int value; | |
550 private final String operator; | |
551 private boolean isFloat; | |
552 | |
553 private CC(int value, String op, boolean isFloat) { | |
554 this.value = value; | |
555 this.operator = op; | |
556 this.isFloat = isFloat; | |
557 } | |
558 | |
559 public int getValue() { | |
560 return value; | |
561 } | |
562 | |
563 public String getOperator() { | |
564 return operator; | |
565 } | |
566 | |
567 public static CC forKind(Kind kind) { | |
568 boolean isInt = kind == Kind.Boolean || kind == Kind.Byte || kind == Kind.Char || kind == Kind.Short || kind == Kind.Int; | |
569 boolean isFloat = kind == Kind.Float || kind == Kind.Double; | |
570 boolean isLong = kind == Kind.Long || kind == Kind.Object; | |
571 assert isInt || isFloat || isLong; | |
572 if (isLong) { | |
573 return Xcc; | |
574 } else if (isInt) { | |
575 return Icc; | |
576 } else if (isFloat) { | |
577 return Fcc0; | |
578 } else { | |
579 throw new InternalError(); | |
580 } | |
581 } | |
582 } | |
583 | |
584 public enum ConditionFlag { | |
585 // @formatter:off | |
586 | |
587 // for FBfcc & FBPfcc instruction | |
588 F_Never(0, "f_never"), | |
589 F_NotEqual(1, "f_notEqual"), | |
590 F_LessOrGreater(2, "f_lessOrGreater"), | |
591 F_UnorderedOrLess(3, "f_unorderedOrLess"), | |
592 F_Less(4, "f_less"), | |
593 F_UnorderedOrGreater(5, "f_unorderedOrGreater"), | |
594 F_Greater(6, "f_greater"), | |
595 F_Unordered(7, "f_unordered"), | |
596 F_Always(8, "f_always"), | |
597 F_Equal(9, "f_equal"), | |
598 F_UnorderedOrEqual(10, "f_unorderedOrEqual"), | |
599 F_GreaterOrEqual(11, "f_greaterOrEqual"), | |
600 F_UnorderedGreaterOrEqual(12, "f_unorderedGreaterOrEqual"), | |
601 F_LessOrEqual(13, "f_lessOrEqual"), | |
602 F_UnorderedOrLessOrEqual(14, "f_unorderedOrLessOrEqual"), | |
603 F_Ordered(15, "f_ordered"), | |
604 | |
605 // for integers | |
606 Never(0, "never"), | |
607 Equal(1, "equal", true), | |
608 Zero(1, "zero"), | |
609 LessEqual(2, "lessEqual", true), | |
610 Less(3, "less", true), | |
611 LessEqualUnsigned(4, "lessEqualUnsigned", true), | |
612 LessUnsigned(5, "lessUnsigned", true), | |
613 CarrySet(5, "carrySet"), | |
614 Negative(6, "negative", true), | |
615 OverflowSet(7, "overflowSet", true), | |
616 Always(8, "always"), | |
617 NotEqual(9, "notEqual", true), | |
618 NotZero(9, "notZero"), | |
619 Greater(10, "greater", true), | |
620 GreaterEqual(11, "greaterEqual", true), | |
621 GreaterUnsigned(12, "greaterUnsigned", true), | |
622 GreaterEqualUnsigned(13, "greaterEqualUnsigned", true), | |
623 CarryClear(13, "carryClear"), | |
624 Positive(14, "positive", true), | |
625 OverflowClear(15, "overflowClear", true); | |
626 | |
627 // @formatter:on | |
628 | |
629 private final int value; | |
630 private final String operator; | |
631 private boolean forCBcond = false; | |
632 | |
633 private ConditionFlag(int value, String op) { | |
634 this(value, op, false); | |
635 } | |
636 | |
637 private ConditionFlag(int value, String op, boolean cbcond) { | |
638 this.value = value; | |
639 this.operator = op; | |
640 this.forCBcond = cbcond; | |
641 } | |
642 | |
643 public boolean isCBCond() { | |
644 return forCBcond; | |
645 } | |
646 | |
647 public int getValue() { | |
648 return value; | |
649 } | |
650 | |
651 public String getOperator() { | |
652 return operator; | |
653 } | |
654 | |
655 public ConditionFlag negate() { | |
656 //@formatter:off | |
657 switch (this) { | |
658 case F_Never : return F_Always; | |
659 case F_Always : return F_Never; | |
660 case F_NotEqual : return F_Equal; | |
661 case F_Equal : return F_NotEqual; | |
662 case F_LessOrGreater : return F_UnorderedOrEqual; | |
663 case F_UnorderedOrEqual : return F_LessOrGreater; | |
664 case F_Less : return F_UnorderedGreaterOrEqual; | |
665 case F_UnorderedGreaterOrEqual: return F_Less; | |
666 case F_LessOrEqual : return F_UnorderedOrGreater; | |
667 case F_UnorderedOrGreater : return F_LessOrEqual; | |
668 case F_Greater : return F_UnorderedOrLessOrEqual; | |
669 case F_UnorderedOrLessOrEqual : return F_Greater; | |
670 case F_GreaterOrEqual : return F_UnorderedOrLess; | |
671 case F_UnorderedOrLess : return F_GreaterOrEqual; | |
672 case F_Unordered : return F_Ordered; | |
673 case F_Ordered : return F_Unordered; | |
674 case Never : return Always; | |
675 case Always : return Never; | |
676 case Equal : return NotEqual; | |
677 case NotEqual : return Equal; | |
678 case Zero : return NotZero; | |
679 case NotZero : return Zero; | |
680 case LessEqual : return Greater; | |
681 case Greater : return LessEqual; | |
682 case Less : return GreaterEqual; | |
683 case GreaterEqual : return Less; | |
684 case LessEqualUnsigned : return GreaterUnsigned; | |
685 case GreaterUnsigned : return LessEqualUnsigned; | |
686 case LessUnsigned : return GreaterEqualUnsigned; | |
687 case GreaterEqualUnsigned : return LessUnsigned; | |
688 case CarrySet : return CarryClear; | |
689 case CarryClear : return CarrySet; | |
690 case Negative : return Positive; | |
691 case Positive : return Negative; | |
692 case OverflowSet : return OverflowClear; | |
693 case OverflowClear : return OverflowSet; | |
694 default: | |
695 throw new InternalError(); | |
696 } | |
697 //@formatter:on | |
698 } | |
699 | |
700 public ConditionFlag mirror() { | |
701 switch (this) { | |
702 //@formatter:off | |
703 case F_Less : return F_Greater; | |
704 case F_Greater : return F_Less; | |
705 case F_LessOrEqual : return F_GreaterOrEqual; | |
706 case F_UnorderedGreaterOrEqual: return F_UnorderedOrLessOrEqual; | |
707 case F_UnorderedOrGreater : return F_UnorderedOrLess; | |
708 case F_UnorderedOrLessOrEqual : return F_UnorderedGreaterOrEqual; | |
709 case F_GreaterOrEqual : return F_LessOrEqual; | |
710 case F_UnorderedOrLess : return F_UnorderedOrGreater; | |
711 case LessEqual : return GreaterEqual; | |
712 case Greater : return Less; | |
713 case Less : return Greater; | |
714 case GreaterEqual : return LessEqual; | |
715 case LessEqualUnsigned : return GreaterEqualUnsigned; | |
716 case GreaterUnsigned : return LessUnsigned; | |
717 case LessUnsigned : return GreaterUnsigned; | |
718 case GreaterEqualUnsigned : return LessEqualUnsigned; | |
719 default: | |
720 return this; | |
721 //@formatter:on | |
722 } | |
723 } | |
724 | |
725 } | |
726 | |
727 public enum RCondition { | |
728 // @formatter:off | |
729 | |
730 Rc_z(0b001, "rc_z"), | |
731 Rc_lez(0b010, "rc_lez"), | |
732 Rc_lz(0b011, "rc_lz"), | |
733 Rc_nz(0b101, "rc_nz"), | |
734 Rc_gz(0b110, "rc_gz"), | |
735 Rc_gez(0b111, "rc_gez"), | |
736 Rc_last(Rc_gez.getValue(), "rc_last"); | |
737 | |
738 // @formatter:on | |
739 | |
740 private final int value; | |
741 private final String operator; | |
742 | |
743 private RCondition(int value, String op) { | |
744 this.value = value; | |
745 this.operator = op; | |
746 } | |
747 | |
748 public int getValue() { | |
749 return value; | |
750 } | |
751 | |
752 public String getOperator() { | |
753 return operator; | |
754 } | |
755 } | |
756 | |
757 /** | |
758 * Represents the <b>Address Space Identifier</b> defined in the SPARC architecture. | |
759 */ | |
760 public enum Asi { | |
761 // @formatter:off | |
762 | |
763 INVALID(-1), | |
764 ASI_PRIMARY(0x80), | |
765 ASI_PRIMARY_NOFAULT(0x82), | |
766 ASI_PRIMARY_LITTLE(0x88), | |
767 // Block initializing store | |
768 ASI_ST_BLKINIT_PRIMARY(0xE2), | |
769 // Most-Recently-Used (MRU) BIS variant | |
770 ASI_ST_BLKINIT_MRU_PRIMARY(0xF2); | |
771 | |
772 // @formatter:on | |
773 | |
774 private final int value; | |
775 | |
776 private Asi(int value) { | |
777 this.value = value; | |
778 } | |
779 | |
780 public int getValue() { | |
781 return value; | |
782 } | |
783 | |
784 public boolean isValid() { | |
785 return value != INVALID.getValue(); | |
786 } | |
787 } | |
788 | |
789 public enum Fcn { | |
790 SeveralWritesAndPossiblyReads(2), | |
791 SeveralReadsWeak(0), | |
792 OneRead(1), | |
793 OneWrite(3), | |
794 Page(4), | |
795 NearestUnifiedCache(17), | |
796 SeveralReadsStrong(20), | |
797 OneReadStrong(21), | |
798 SeveralWritesAndPossiblyReadsStrong(22), | |
799 OneWriteStrong(23); | |
800 | |
801 private final int value; | |
802 | |
803 private Fcn(int value) { | |
804 this.value = value; | |
805 } | |
806 | |
807 public int getValue() { | |
808 return value; | |
809 } | |
810 } | |
811 | |
812 public boolean hasFeature(CPUFeature feature) { | |
813 return ((SPARC) this.target.arch).features.contains(feature); | |
814 } | |
815 | |
816 public static final int simm(int x, int nbits) { | |
817 // assert_signed_range(x, nbits); | |
818 return x & ((1 << nbits) - 1); | |
819 } | |
820 | |
821 public static final boolean isImm(int x, int nbits) { | |
822 // assert_signed_range(x, nbits); | |
823 return simm(x, nbits) == x; | |
824 } | |
825 | |
826 /** | |
827 * Minimum value for signed immediate ranges. | |
828 */ | |
829 public static long minSimm(long nbits) { | |
830 return -(1L << (nbits - 1)); | |
831 } | |
832 | |
833 /** | |
834 * Maximum value for signed immediate ranges. | |
835 */ | |
836 public static long maxSimm(long nbits) { | |
837 return (1L << (nbits - 1)) - 1; | |
838 } | |
839 | |
840 /** | |
841 * Test if imm is within signed immediate range for nbits. | |
842 */ | |
843 public static boolean isSimm(long imm, int nbits) { | |
844 return minSimm(nbits) <= imm && imm <= maxSimm(nbits); | |
845 } | |
846 | |
847 public static boolean isSimm10(long imm) { | |
848 return isSimm(imm, 10); | |
849 } | |
850 | |
851 public static boolean isSimm11(long imm) { | |
852 return isSimm(imm, 11); | |
853 } | |
854 | |
855 public static boolean isSimm11(JavaConstant constant) { | |
856 return constant.isNull() || isSimm11(constant.asLong()); | |
857 } | |
858 | |
859 public static boolean isSimm5(JavaConstant constant) { | |
860 return constant.isNull() || isSimm(constant.asLong(), 5); | |
861 } | |
862 | |
863 public static boolean isSimm13(int imm) { | |
864 return isSimm(imm, 13); | |
865 } | |
866 | |
867 public static boolean isSimm13(JavaConstant constant) { | |
868 return constant.isNull() || isSimm13(constant.asLong()); | |
869 } | |
870 | |
871 public static boolean isSimm13(long imm) { | |
872 return NumUtil.isInt(imm) && isSimm(imm, 13); | |
873 } | |
874 | |
875 public static boolean isWordDisp30(long imm) { | |
876 return isSimm(imm, 30 + 2); | |
877 } | |
878 | |
879 public static final int hi22(int x) { | |
880 return x >>> 10; | |
881 } | |
882 | |
883 public static final int lo10(int x) { | |
884 return x & ((1 << 10) - 1); | |
885 } | |
886 | |
887 // @formatter:off | |
888 /** | |
889 * Instruction format for Fmt00 instructions. This abstraction is needed as it | |
890 * makes the patching easier later on. | |
891 * <pre> | |
892 * | 00 | a | op2 | b | | |
893 * |31 30|29 25|24 22|21 0| | |
894 * </pre> | |
895 */ | |
896 // @formatter:on | |
897 protected void fmt00(int a, int op2, int b) { | |
898 assert isImm(a, 5) && isImm(op2, 3) && isImm(b, 22) : String.format("a: 0x%x op2: 0x%x b: 0x%x", a, op2, b); | |
899 this.emitInt(a << 25 | op2 << 22 | b); | |
900 } | |
901 | |
902 private void op3(Op3s op3, Opfs opf, Register rs1, Register rs2, Register rd) { | |
903 int b = opf.value << 5 | (rs2 == null ? 0 : rs2.encoding); | |
904 fmt(op3.op.op, rd.encoding, op3.value, rs1 == null ? 0 : rs1.encoding, b); | |
905 } | |
906 | |
907 protected void op3(Op3s op3, Register rs1, Register rs2, Register rd) { | |
908 int b = rs2 == null ? 0 : rs2.encoding; | |
909 int xBit = getXBit(op3); | |
910 fmt(op3.op.op, rd.encoding, op3.value, rs1 == null ? 0 : rs1.encoding, b | xBit); | |
911 } | |
912 | |
913 protected void op3(Op3s op3, Register rs1, int simm13, Register rd) { | |
914 assert isSimm13(simm13); | |
915 int i = 1 << 13; | |
916 int simm13WithX = simm13 | getXBit(op3); | |
917 fmt(op3.op.op, rd.encoding, op3.value, rs1.encoding, i | simm13WithX & ((1 << 13) - 1)); | |
918 } | |
919 | |
920 // @formatter:off | |
921 /** | |
922 * Branch on Integer Condition Codes. | |
923 * <pre> | |
924 * | 00 |annul| cond| 010 | disp22 | | |
925 * |31 30|29 |28 25|24 22|21 0| | |
926 * </pre> | |
927 */ | |
928 // @formatter:on | |
929 public void bicc(ConditionFlag cond, Annul annul, Label l) { | |
930 bcc(Op2s.Br, cond, annul, l); | |
931 } | |
932 | |
933 // @formatter:off | |
934 /** | |
935 * Branch on Floating-Point Condition Codes. | |
936 * <pre> | |
937 * | 00 |annul| cond| 110 | disp22 | | |
938 * |31 30|29 |28 25|24 22|21 0| | |
939 * </pre> | |
940 */ | |
941 // @formatter:on | |
942 public void fbcc(ConditionFlag cond, Annul annul, Label l) { | |
943 bcc(Op2s.Fb, cond, annul, l); | |
944 } | |
945 | |
946 // @formatter:off | |
947 /** | |
948 * Branch on (Integer|Floatingpoint) Condition Codes. | |
949 * <pre> | |
950 * | 00 |annul| cond| op2 | disp22 | | |
951 * |31 30|29 |28 25|24 22|21 0| | |
952 * </pre> | |
953 */ | |
954 // @formatter:on | |
955 private void bcc(Op2s op2, ConditionFlag cond, Annul annul, Label l) { | |
956 int pos = !l.isBound() ? patchUnbound(l) : (l.position() - position()) / 4; | |
957 final int disp = 22; | |
958 assert isSimm(pos, disp); | |
959 pos &= (1 << disp) - 1; | |
960 int a = (annul.flag << 4) | cond.getValue(); | |
961 fmt00(a, op2.getValue(), pos); | |
962 } | |
963 | |
964 // @formatter:off | |
965 /** | |
966 * Branch on Integer Condition Codes with Prediction. | |
967 * <pre> | |
968 * | 00 |an|cond | 001 |cc1 2|p | disp19 | | |
969 * |31 30|29|28 25|24 22|21 20|19| 0| | |
970 * </pre> | |
971 */ | |
972 // @formatter:on | |
973 public void bpcc(ConditionFlag cond, Annul annul, Label l, CC cc, BranchPredict predictTaken) { | |
974 bpcc(Op2s.Bp, cond, annul, l, cc, predictTaken); | |
975 } | |
976 | |
977 // @formatter:off | |
978 /** | |
979 * Branch on Integer Condition Codes with Prediction. | |
980 * <pre> | |
981 * | 00 |an|cond | 101 |cc1 2|p | disp19 | | |
982 * |31 30|29|28 25|24 22|21 20|19| 0| | |
983 * </pre> | |
984 */ | |
985 // @formatter:on | |
986 public void fbpcc(ConditionFlag cond, Annul annul, Label l, CC cc, BranchPredict predictTaken) { | |
987 bpcc(Op2s.Fbp, cond, annul, l, cc, predictTaken); | |
988 } | |
989 | |
990 // @formatter:off | |
991 /** | |
992 * Used for fbpcc (Float) and bpcc (Integer). | |
993 * <pre> | |
994 * | 00 |an|cond | op2 |cc1 2|p | disp19 | | |
995 * |31 30|29|28 25|24 22|21 20|19| 0| | |
996 * </pre> | |
997 */ | |
998 // @formatter:on | |
999 private void bpcc(Op2s op2, ConditionFlag cond, Annul annul, Label l, CC cc, BranchPredict predictTaken) { | |
1000 int pos = !l.isBound() ? patchUnbound(l) : (l.position() - position()) / 4; | |
1001 final int disp = 19; | |
1002 assert isSimm(pos, disp); | |
1003 pos &= (1 << disp) - 1; | |
1004 int a = (annul.flag << 4) | cond.getValue(); | |
1005 int b = (cc.getValue() << 20) | ((predictTaken.flag) << 19) | pos; | |
1006 fmt00(a, op2.getValue(), b); | |
1007 } | |
1008 | |
1009 // @formatter:off | |
1010 /** | |
1011 * Branch on Integer Register with Prediction. | |
1012 * <pre> | |
1013 * | 00 |an| 0|rcond | 011 |d16hi|p | rs1 | d16lo | | |
1014 * |31 30|29|28|27 25 |24 22|21 20|19|18 14| 0| | |
1015 * </pre> | |
1016 */ | |
1017 // @formatter:on | |
1018 public void bpr(RCondition cond, Annul annul, Label l, BranchPredict predictTaken, Register rs1) { | |
1019 int pos = !l.isBound() ? patchUnbound(l) : (l.position() - position()) / 4; | |
1020 final int disp = 16; | |
1021 assert isSimm(pos, disp); | |
1022 pos &= (1 << disp) - 1; | |
1023 int a = (annul.flag << 4) | cond.getValue(); | |
1024 int d16hi = (pos >> 13) << 13; | |
1025 int d16lo = d16hi ^ pos; | |
1026 int b = (d16hi << 20) | (predictTaken.flag << 19) | (rs1.encoding() << 14) | d16lo; | |
1027 fmt00(a, Op2s.Bpr.getValue(), b); | |
1028 } | |
1029 | |
1030 private int patchUnbound(Label label) { | |
1031 label.addPatchAt(position()); | |
1032 return 0; | |
1033 } | |
1034 | |
1035 public void cbcondw(ConditionFlag cf, Register rs1, Register rs2, Label lab) { | |
1036 cbcond(0, 0, cf, rs1, rs2.encoding, lab); | |
1037 } | |
1038 | |
1039 public void cbcondw(ConditionFlag cf, Register rs1, int rs2, Label lab) { | |
1040 assert isSimm(rs2, 5); | |
1041 cbcond(0, 1, cf, rs1, rs2 & ((1 << 5) - 1), lab); | |
1042 } | |
1043 | |
1044 public void cbcondx(ConditionFlag cf, Register rs1, Register rs2, Label lab) { | |
1045 cbcond(1, 0, cf, rs1, rs2.encoding, lab); | |
1046 } | |
1047 | |
1048 public void cbcondx(ConditionFlag cf, Register rs1, int rs2, Label lab) { | |
1049 assert isSimm(rs2, 5); | |
1050 cbcond(1, 1, cf, rs1, rs2 & ((1 << 5) - 1), lab); | |
1051 } | |
1052 | |
1053 private void cbcond(int cc2, int i, ConditionFlag cf, Register rs1, int rs2, Label l) { | |
1054 int disp10 = !l.isBound() ? patchUnbound(l) : (l.position() - position()) / 4; | |
1055 assert isSimm(disp10, 10) && isImm(rs2, 5); | |
1056 disp10 &= (1 << 10) - 1; | |
1057 final int cLo = cf.value & 0b111; | |
1058 final int cHi = cf.value >> 3; | |
1059 final int d10Lo = disp10 & ((1 << 8) - 1); | |
1060 final int d10Hi = disp10 >> 8; | |
1061 int a = cHi << 4 | 0b1000 | cLo; | |
1062 int b = cc2 << 21 | d10Hi << D10HI_SHIFT | rs1.encoding << 14 | i << 13 | d10Lo << D10LO_SHIFT | rs2; | |
1063 fmt00(a, Op2s.Bpr.value, b); | |
1064 } | |
1065 | |
1066 // @formatter:off | |
1067 /** | |
1068 * NOP. | |
1069 * <pre> | |
1070 * | 00 |00000| 100 | 0 | | |
1071 * |31 30|29 25|24 22|21 0| | |
1072 * </pre> | |
1073 */ | |
1074 // @formatter:on | |
1075 public void nop() { | |
1076 emitInt(1 << 24); | |
1077 } | |
1078 | |
1079 public void sethi(int imm22, Register dst) { | |
1080 fmt00(dst.encoding, Op2s.Sethi.value, imm22); | |
1081 } | |
1082 | |
1083 // @formatter:off | |
1084 /** | |
1085 * Instruction format for calls. | |
1086 * <pre> | |
1087 * | 01 | disp30 | | |
1088 * |31 30|29 0| | |
1089 * </pre> | |
1090 */ | |
1091 // @formatter:on | |
1092 public void call(int disp30) { | |
1093 assert isImm(disp30, 30); | |
1094 int instr = 1 << 30; | |
1095 instr |= disp30; | |
1096 emitInt(instr); | |
1097 } | |
1098 | |
1099 public void add(Register rs1, Register rs2, Register rd) { | |
1100 op3(Add, rs1, rs2, rd); | |
1101 } | |
1102 | |
1103 public void add(Register rs1, int simm13, Register rd) { | |
1104 op3(Add, rs1, simm13, rd); | |
1105 } | |
1106 | |
1107 public void addc(Register rs1, Register rs2, Register rd) { | |
1108 op3(Addc, rs1, rs2, rd); | |
1109 } | |
1110 | |
1111 public void addc(Register rs1, int simm13, Register rd) { | |
1112 op3(Addc, rs1, simm13, rd); | |
1113 } | |
1114 | |
1115 public void addcc(Register rs1, Register rs2, Register rd) { | |
1116 op3(Addcc, rs1, rs2, rd); | |
1117 } | |
1118 | |
1119 public void addcc(Register rs1, int simm13, Register rd) { | |
1120 op3(Addcc, rs1, simm13, rd); | |
1121 } | |
1122 | |
1123 public void and(Register rs1, Register rs2, Register rd) { | |
1124 op3(And, rs1, rs2, rd); | |
1125 } | |
1126 | |
1127 public void and(Register rs1, int simm13, Register rd) { | |
1128 op3(And, rs1, simm13, rd); | |
1129 } | |
1130 | |
1131 public void andcc(Register rs1, Register rs2, Register rd) { | |
1132 op3(Andcc, rs1, rs2, rd); | |
1133 } | |
1134 | |
1135 public void andcc(Register rs1, int simm13, Register rd) { | |
1136 op3(Andcc, rs1, simm13, rd); | |
1137 } | |
1138 | |
1139 public void andn(Register rs1, Register rs2, Register rd) { | |
1140 op3(Andn, rs1, rs2, rd); | |
1141 } | |
1142 | |
1143 public void andn(Register rs1, int simm13, Register rd) { | |
1144 op3(Andn, rs1, simm13, rd); | |
1145 } | |
1146 | |
1147 public void andncc(Register rs1, Register rs2, Register rd) { | |
1148 op3(Andncc, rs1, rs2, rd); | |
1149 } | |
1150 | |
1151 public void andncc(Register rs1, int simm13, Register rd) { | |
1152 op3(Andncc, rs1, simm13, rd); | |
1153 } | |
1154 | |
1155 public void movwtos(Register rs2, Register rd) { | |
1156 assert isSingleFloatRegister(rd) && isCPURegister(rs2) : String.format("%s %s", rs2, rd); | |
1157 op3(Impdep1, Movwtos, null, rs2, rd); | |
1158 } | |
1159 | |
1160 public void umulxhi(Register rs1, Register rs2, Register rd) { | |
1161 op3(Impdep1, UMulxhi, rs1, rs2, rd); | |
1162 } | |
1163 | |
1164 public void fdtos(Register rs2, Register rd) { | |
1165 assert isSingleFloatRegister(rd) && isDoubleFloatRegister(rs2) : String.format("%s %s", rs2, rd); | |
1166 op3(Fpop1, Fdtos, null, rs2, rd); | |
1167 } | |
1168 | |
1169 public void movstouw(Register rs2, Register rd) { | |
1170 assert isSingleFloatRegister(rs2) && isCPURegister(rd) : String.format("%s %s", rs2, rd); | |
1171 op3(Impdep1, Movstosw, null, rs2, rd); | |
1172 } | |
1173 | |
1174 public void movstosw(Register rs2, Register rd) { | |
1175 assert isSingleFloatRegister(rs2) && isCPURegister(rd) : String.format("%s %s", rs2, rd); | |
1176 op3(Impdep1, Movstosw, null, rs2, rd); | |
1177 } | |
1178 | |
1179 public void movdtox(Register rs2, Register rd) { | |
1180 assert isDoubleFloatRegister(rs2) && isCPURegister(rd) : String.format("%s %s", rs2, rd); | |
1181 op3(Impdep1, Movdtox, null, rs2, rd); | |
1182 } | |
1183 | |
1184 public void movxtod(Register rs2, Register rd) { | |
1185 assert isCPURegister(rs2) && isDoubleFloatRegister(rd) : String.format("%s %s", rs2, rd); | |
1186 op3(Impdep1, Movxtod, null, rs2, rd); | |
1187 } | |
1188 | |
1189 public void fadds(Register rs1, Register rs2, Register rd) { | |
1190 op3(Fpop1, Fadds, rs1, rs2, rd); | |
1191 } | |
1192 | |
1193 public void faddd(Register rs1, Register rs2, Register rd) { | |
1194 op3(Fpop1, Faddd, rs1, rs2, rd); | |
1195 } | |
1196 | |
1197 public void faddq(Register rs1, Register rs2, Register rd) { | |
1198 op3(Fpop1, Faddq, rs1, rs2, rd); | |
1199 } | |
1200 | |
1201 public void fdivs(Register rs1, Register rs2, Register rd) { | |
1202 op3(Fpop1, Fdivs, rs1, rs2, rd); | |
1203 } | |
1204 | |
1205 public void fdivd(Register rs1, Register rs2, Register rd) { | |
1206 op3(Fpop1, Fdivd, rs1, rs2, rd); | |
1207 } | |
1208 | |
1209 public void fmovs(Register rs2, Register rd) { | |
1210 op3(Fpop1, Fmovs, null, rs2, rd); | |
1211 } | |
1212 | |
1213 public void fmovd(Register rs2, Register rd) { | |
1214 op3(Fpop1, Fmovd, null, rs2, rd); | |
1215 } | |
1216 | |
1217 public void fmuls(Register rs1, Register rs2, Register rd) { | |
1218 op3(Fpop1, Fmuls, rs1, rs2, rd); | |
1219 } | |
1220 | |
1221 public void fsmuld(Register rs1, Register rs2, Register rd) { | |
1222 op3(Fpop1, Fsmuld, rs1, rs2, rd); | |
1223 } | |
1224 | |
1225 public void fmuld(Register rs1, Register rs2, Register rd) { | |
1226 op3(Fpop1, Fmuld, rs1, rs2, rd); | |
1227 } | |
1228 | |
1229 public void fnegs(Register rs2, Register rd) { | |
1230 op3(Fpop1, Fnegs, null, rs2, rd); | |
1231 } | |
1232 | |
1233 public void fnegd(Register rs2, Register rd) { | |
1234 op3(Fpop1, Fnegd, null, rs2, rd); | |
1235 } | |
1236 | |
1237 /** | |
1238 * Helper method to determine if the instruction needs the X bit set. | |
1239 */ | |
1240 private static int getXBit(Op3s op3) { | |
1241 switch (op3) { | |
1242 case Sllx: | |
1243 case Srax: | |
1244 case Srlx: | |
1245 return 1 << 12; | |
1246 default: | |
1247 return 0; | |
1248 } | |
1249 } | |
1250 | |
1251 public void fstoi(Register rs2, Register rd) { | |
1252 op3(Fpop1, Fstoi, null, rs2, rd); | |
1253 } | |
1254 | |
1255 public void fstox(Register rs2, Register rd) { | |
1256 op3(Fpop1, Fstox, null, rs2, rd); | |
1257 } | |
1258 | |
1259 public void fdtox(Register rs2, Register rd) { | |
1260 op3(Fpop1, Fdtox, null, rs2, rd); | |
1261 } | |
1262 | |
1263 public void fstod(Register rs2, Register rd) { | |
1264 op3(Fpop1, Fstod, null, rs2, rd); | |
1265 } | |
1266 | |
1267 public void fdtoi(Register rs2, Register rd) { | |
1268 op3(Fpop1, Fdtoi, null, rs2, rd); | |
1269 } | |
1270 | |
1271 public void fitos(Register rs2, Register rd) { | |
1272 op3(Fpop1, Fitos, null, rs2, rd); | |
1273 } | |
1274 | |
1275 public void fitod(Register rs2, Register rd) { | |
1276 op3(Fpop1, Fitod, null, rs2, rd); | |
1277 } | |
1278 | |
1279 public void fxtos(Register rs2, Register rd) { | |
1280 op3(Fpop1, Fxtos, null, rs2, rd); | |
1281 } | |
1282 | |
1283 public void fxtod(Register rs2, Register rd) { | |
1284 op3(Fpop1, Fxtod, null, rs2, rd); | |
1285 } | |
1286 | |
1287 public void fzeros(Register rd) { | |
1288 op3(Impdep1, Fzeros, null, null, rd); | |
1289 } | |
1290 | |
1291 public void fzerod(Register rd) { | |
1292 op3(Impdep1, Fzerod, null, null, rd); | |
1293 } | |
1294 | |
1295 public void flushw() { | |
1296 op3(Flushw, g0, g0, g0); | |
1297 } | |
1298 | |
1299 public void fsqrtd(Register rs2, Register rd) { | |
1300 op3(Fpop1, Fsqrtd, null, rs2, rd); | |
1301 } | |
1302 | |
1303 public void fsqrts(Register rs2, Register rd) { | |
1304 op3(Fpop1, Fsqrts, null, rs2, rd); | |
1305 } | |
1306 | |
1307 public void fabss(Register rs2, Register rd) { | |
1308 op3(Fpop1, Fabss, null, rs2, rd); | |
1309 } | |
1310 | |
1311 public void fabsd(Register rs2, Register rd) { | |
1312 op3(Fpop1, Fabsd, null, rs2, rd); | |
1313 } | |
1314 | |
1315 public void fsubs(Register rs1, Register rs2, Register rd) { | |
1316 op3(Fpop1, Fsubs, rs1, rs2, rd); | |
1317 } | |
1318 | |
1319 public void fsubd(Register rs1, Register rs2, Register rd) { | |
1320 op3(Fpop1, Fsubd, rs1, rs2, rd); | |
1321 } | |
1322 | |
1323 // @formatter:off | |
1324 /** | |
1325 * Instruction format for fcmp. | |
1326 * <pre> | |
1327 * | 10 | --- |cc1|cc0|desc | rs1 | opf | rs2 | | |
1328 * |31 30|29 27|26 |25 |24 19|18 14|13 5|4 0| | |
1329 * </pre> | |
1330 */ | |
1331 // @formatter:on | |
1332 public void fcmp(CC cc, Opfs opf, Register rs1, Register rs2) { | |
1333 int a = cc.value; | |
1334 int b = opf.value << 5 | rs2.encoding; | |
1335 fmt10(a, Fcmp.value, rs1.encoding, b); | |
1336 } | |
1337 | |
1338 // @formatter:off | |
1339 /** | |
1340 * Instruction format for most arithmetic stuff. | |
1341 * <pre> | |
1342 * | 10 | rd | op3 | rs1 | b | | |
1343 * |31 30|29 25|24 19|18 14|13 0| | |
1344 * </pre> | |
1345 */ | |
1346 // @formatter:on | |
1347 protected void fmt10(int rd, int op3, int rs1, int b) { | |
1348 fmt(0b10, rd, op3, rs1, b); | |
1349 } | |
1350 | |
1351 // @formatter:off | |
1352 /** | |
1353 * Instruction format for most arithmetic stuff. | |
1354 * <pre> | |
1355 * | op | rd | op3 | rs1 | b | | |
1356 * |31 30|29 25|24 19|18 14|13 0| | |
1357 * </pre> | |
1358 */ | |
1359 // @formatter:on | |
1360 protected void fmt(int op, int rd, int op3, int rs1, int b) { | |
1361 assert isImm(rd, 5) && isImm(op3, 6) && isImm(b, 14) : String.format("rd: 0x%x op3: 0x%x b: 0x%x", rd, op3, b); | |
1362 int instr = op << 30 | rd << 25 | op3 << 19 | rs1 << 14 | b; | |
1363 emitInt(instr); | |
1364 } | |
1365 | |
1366 public void illtrap(int const22) { | |
1367 fmt00(0, Op2s.Illtrap.value, const22); | |
1368 } | |
1369 | |
1370 public void jmpl(Register rs1, Register rs2, Register rd) { | |
1371 op3(Jmpl, rs1, rs2, rd); | |
1372 } | |
1373 | |
1374 public void jmpl(Register rs1, int simm13, Register rd) { | |
1375 op3(Jmpl, rs1, simm13, rd); | |
1376 } | |
1377 | |
1378 public void fmovdcc(ConditionFlag cond, CC cc, Register rs2, Register rd) { | |
1379 fmovcc(cond, cc, rs2, rd, Fmovdcc.value); | |
1380 } | |
1381 | |
1382 public void fmovscc(ConditionFlag cond, CC cc, Register rs2, Register rd) { | |
1383 fmovcc(cond, cc, rs2, rd, Fmovscc.value); | |
1384 } | |
1385 | |
1386 private void fmovcc(ConditionFlag cond, CC cc, Register rs2, Register rd, int opfLow) { | |
1387 int opfCC = cc.value; | |
1388 int a = opfCC << 11 | opfLow << 5 | rs2.encoding; | |
1389 fmt10(rd.encoding, Fpop2.value, cond.value, a); | |
1390 } | |
1391 | |
1392 public void movcc(ConditionFlag conditionFlag, CC cc, Register rs2, Register rd) { | |
1393 movcc(conditionFlag, cc, 0, rs2.encoding, rd); | |
1394 } | |
1395 | |
1396 public void movcc(ConditionFlag conditionFlag, CC cc, int simm11, Register rd) { | |
1397 assert isSimm11(simm11); | |
1398 movcc(conditionFlag, cc, 1, simm11 & ((1 << 11) - 1), rd); | |
1399 } | |
1400 | |
1401 private void movcc(ConditionFlag conditionFlag, CC cc, int i, int imm, Register rd) { | |
1402 int cc01 = 0b11 & cc.value; | |
1403 int cc2 = cc.isFloat ? 0 : 1; | |
1404 int a = cc2 << 4 | conditionFlag.value; | |
1405 int b = cc01 << 11 | i << 13 | imm; | |
1406 fmt10(rd.encoding, Movcc.value, a, b); | |
1407 } | |
1408 | |
1409 public void mulx(Register rs1, Register rs2, Register rd) { | |
1410 op3(Mulx, rs1, rs2, rd); | |
1411 } | |
1412 | |
1413 public void mulx(Register rs1, int simm13, Register rd) { | |
1414 op3(Mulx, rs1, simm13, rd); | |
1415 } | |
1416 | |
1417 public void or(Register rs1, Register rs2, Register rd) { | |
1418 assert isCPURegister(rs1, rs2, rd) : String.format("%s %s %s", rs1, rs2, rd); | |
1419 op3(Or, rs1, rs2, rd); | |
1420 } | |
1421 | |
1422 public void or(Register rs1, int simm13, Register rd) { | |
1423 assert isCPURegister(rs1, rd) : String.format("%s %s", rs1, rd); | |
1424 op3(Or, rs1, simm13, rd); | |
1425 } | |
1426 | |
1427 public void popc(Register rs2, Register rd) { | |
1428 op3(Popc, g0, rs2, rd); | |
1429 } | |
1430 | |
1431 public void popc(int simm13, Register rd) { | |
1432 op3(Popc, g0, simm13, rd); | |
1433 } | |
1434 | |
1435 public void prefetch(SPARCAddress addr, Fcn fcn) { | |
1436 Register rs1 = addr.getBase(); | |
1437 if (addr.getIndex().equals(Register.None)) { | |
1438 int dis = addr.getDisplacement(); | |
1439 assert isSimm13(dis); | |
1440 fmt(Prefetch.op.op, fcn.value, Prefetch.value, rs1.encoding, 1 << 13 | dis & ((1 << 13) - 1)); | |
1441 } else { | |
1442 Register rs2 = addr.getIndex(); | |
1443 fmt(Prefetch.op.op, fcn.value, Prefetch.value, rs1.encoding, rs2.encoding); | |
1444 } | |
1445 } | |
1446 | |
1447 // A.44 Read State Register | |
1448 | |
1449 public void rdpc(Register rd) { | |
1450 op3(Rd, r5, g0, rd); | |
1451 } | |
1452 | |
1453 public void restore(Register rs1, Register rs2, Register rd) { | |
1454 op3(Restore, rs1, rs2, rd); | |
1455 } | |
1456 | |
1457 public static final int PC_RETURN_OFFSET = 8; | |
1458 | |
1459 public void save(Register rs1, Register rs2, Register rd) { | |
1460 op3(Save, rs1, rs2, rd); | |
1461 } | |
1462 | |
1463 public void save(Register rs1, int simm13, Register rd) { | |
1464 op3(Save, rs1, simm13, rd); | |
1465 } | |
1466 | |
1467 public void sdivx(Register rs1, Register rs2, Register rd) { | |
1468 op3(Sdivx, rs1, rs2, rd); | |
1469 } | |
1470 | |
1471 public void sdivx(Register rs1, int simm13, Register rd) { | |
1472 op3(Sdivx, rs1, simm13, rd); | |
1473 } | |
1474 | |
1475 public void udivx(Register rs1, Register rs2, Register rd) { | |
1476 op3(Udivx, rs1, rs2, rd); | |
1477 } | |
1478 | |
1479 public void udivx(Register rs1, int simm13, Register rd) { | |
1480 op3(Udivx, rs1, simm13, rd); | |
1481 } | |
1482 | |
1483 public void sll(Register rs1, Register rs2, Register rd) { | |
1484 op3(Sll, rs1, rs2, rd); | |
1485 } | |
1486 | |
1487 public void sll(Register rs1, int shcnt32, Register rd) { | |
1488 assert isImm(shcnt32, 5); | |
1489 op3(Sll, rs1, shcnt32, rd); | |
1490 } | |
1491 | |
1492 public void sllx(Register rs1, Register rs2, Register rd) { | |
1493 op3(Sllx, rs1, rs2, rd); | |
1494 } | |
1495 | |
1496 public void sllx(Register rs1, int shcnt64, Register rd) { | |
1497 assert isImm(shcnt64, 6); | |
1498 op3(Sllx, rs1, shcnt64, rd); | |
1499 } | |
1500 | |
1501 public void sra(Register rs1, Register rs2, Register rd) { | |
1502 op3(Sra, rs1, rs2, rd); | |
1503 } | |
1504 | |
1505 public void sra(Register rs1, int simm13, Register rd) { | |
1506 op3(Sra, rs1, simm13, rd); | |
1507 } | |
1508 | |
1509 public void srax(Register rs1, Register rs2, Register rd) { | |
1510 op3(Srax, rs1, rs2, rd); | |
1511 } | |
1512 | |
1513 public void srax(Register rs1, int shcnt64, Register rd) { | |
1514 assert isImm(shcnt64, 6); | |
1515 op3(Srax, rs1, shcnt64, rd); | |
1516 } | |
1517 | |
1518 public void srl(Register rs1, Register rs2, Register rd) { | |
1519 op3(Srl, rs1, rs2, rd); | |
1520 } | |
1521 | |
1522 public void srl(Register rs1, int simm13, Register rd) { | |
1523 op3(Srl, rs1, simm13, rd); | |
1524 } | |
1525 | |
1526 public void srlx(Register rs1, Register rs2, Register rd) { | |
1527 op3(Srlx, rs1, rs2, rd); | |
1528 } | |
1529 | |
1530 public void srlx(Register rs1, int shcnt64, Register rd) { | |
1531 assert isImm(shcnt64, 6); | |
1532 op3(Srlx, rs1, shcnt64, rd); | |
1533 } | |
1534 | |
1535 public void fandd(Register rs1, Register rs2, Register rd) { | |
1536 op3(Impdep1, Fandd, rs1, rs2, rd); | |
1537 } | |
1538 | |
1539 public void sub(Register rs1, Register rs2, Register rd) { | |
1540 op3(Sub, rs1, rs2, rd); | |
1541 } | |
1542 | |
1543 public void sub(Register rs1, int simm13, Register rd) { | |
1544 op3(Sub, rs1, simm13, rd); | |
1545 } | |
1546 | |
1547 public void subcc(Register rs1, Register rs2, Register rd) { | |
1548 op3(Subcc, rs1, rs2, rd); | |
1549 } | |
1550 | |
1551 public void subcc(Register rs1, int simm13, Register rd) { | |
1552 op3(Subcc, rs1, simm13, rd); | |
1553 } | |
1554 | |
1555 public void ta(int trap) { | |
1556 tcc(Icc, Always, trap); | |
1557 } | |
1558 | |
1559 public void tcc(CC cc, ConditionFlag flag, int trap) { | |
1560 assert isImm(trap, 8); | |
1561 int b = cc.value << 11; | |
1562 b |= 1 << 13; | |
1563 b |= trap; | |
1564 fmt10(flag.value, Op3s.Tcc.getValue(), 0, b); | |
1565 } | |
1566 | |
1567 public void wrccr(Register rs1, Register rs2) { | |
1568 op3(Wr, rs1, rs2, r2); | |
1569 } | |
1570 | |
1571 public void wrccr(Register rs1, int simm13) { | |
1572 op3(Wr, rs1, simm13, r2); | |
1573 } | |
1574 | |
1575 public void xor(Register rs1, Register rs2, Register rd) { | |
1576 op3(Xor, rs1, rs2, rd); | |
1577 } | |
1578 | |
1579 public void xor(Register rs1, int simm13, Register rd) { | |
1580 op3(Xor, rs1, simm13, rd); | |
1581 } | |
1582 | |
1583 public void xorcc(Register rs1, Register rs2, Register rd) { | |
1584 op3(Xorcc, rs1, rs2, rd); | |
1585 } | |
1586 | |
1587 public void xorcc(Register rs1, int simm13, Register rd) { | |
1588 op3(Xorcc, rs1, simm13, rd); | |
1589 } | |
1590 | |
1591 public void xnor(Register rs1, Register rs2, Register rd) { | |
1592 op3(Xnor, rs1, rs2, rd); | |
1593 } | |
1594 | |
1595 public void xnor(Register rs1, int simm13, Register rd) { | |
1596 op3(Xnor, rs1, simm13, rd); | |
1597 } | |
1598 | |
1599 /* | |
1600 * Load/Store | |
1601 */ | |
1602 protected void ld(Op3s op3, SPARCAddress addr, Register rd, Asi asi) { | |
1603 Register rs1 = addr.getBase(); | |
1604 if (!addr.getIndex().equals(Register.None)) { | |
1605 Register rs2 = addr.getIndex(); | |
1606 if (asi != null) { | |
1607 int b = rs2.encoding; | |
1608 b |= asi.value << 5; | |
1609 fmt(op3.op.op, rd.encoding, op3.value, rs1.encoding, b); | |
1610 } else { | |
1611 op3(op3, rs1, rs2, rd); | |
1612 } | |
1613 } else { | |
1614 int imm = addr.getDisplacement(); | |
1615 op3(op3, rs1, imm, rd); | |
1616 } | |
1617 } | |
1618 | |
1619 protected void ld(Op3s op3, SPARCAddress addr, Register rd) { | |
1620 ld(op3, addr, rd, null); | |
1621 } | |
1622 | |
1623 public void lddf(SPARCAddress src, Register dst) { | |
1624 assert isDoubleFloatRegister(dst) : dst; | |
1625 ld(Lddf, src, dst); | |
1626 } | |
1627 | |
1628 public void ldf(SPARCAddress src, Register dst) { | |
1629 assert isSingleFloatRegister(dst) : dst; | |
1630 ld(Ldf, src, dst); | |
1631 } | |
1632 | |
1633 public void lduh(SPARCAddress src, Register dst) { | |
1634 assert isCPURegister(dst) : dst; | |
1635 ld(Lduh, src, dst); | |
1636 } | |
1637 | |
1638 public void ldsh(SPARCAddress src, Register dst) { | |
1639 assert isCPURegister(dst) : dst; | |
1640 ld(Ldsh, src, dst); | |
1641 } | |
1642 | |
1643 public void ldub(SPARCAddress src, Register dst) { | |
1644 assert isCPURegister(dst) : dst; | |
1645 ld(Ldub, src, dst); | |
1646 } | |
1647 | |
1648 public void ldsb(SPARCAddress src, Register dst) { | |
1649 assert isCPURegister(dst) : dst; | |
1650 ld(Ldsb, src, dst); | |
1651 } | |
1652 | |
1653 public void lduw(SPARCAddress src, Register dst) { | |
1654 assert isCPURegister(dst) : dst; | |
1655 ld(Lduw, src, dst); | |
1656 } | |
1657 | |
1658 public void ldsw(SPARCAddress src, Register dst) { | |
1659 assert isCPURegister(dst) : dst; | |
1660 ld(Ldsw, src, dst); | |
1661 } | |
1662 | |
1663 public void ldx(SPARCAddress src, Register dst) { | |
1664 assert isCPURegister(dst) : dst; | |
1665 ld(Ldx, src, dst); | |
1666 } | |
1667 | |
1668 public void ldxa(Register rs1, Register rs2, Register rd, Asi asi) { | |
1669 assert SPARC.isCPURegister(rs1, rs2, rd) : format("%s %s %s", rs1, rs2, rd); | |
1670 ld(Ldxa, new SPARCAddress(rs1, rs2), rd, asi); | |
1671 } | |
1672 | |
1673 public void lduwa(Register rs1, Register rs2, Register rd, Asi asi) { | |
1674 assert SPARC.isCPURegister(rs1, rs2, rd) : format("%s %s %s", rs1, rs2, rd); | |
1675 ld(Lduwa, new SPARCAddress(rs1, rs2), rd, asi); | |
1676 } | |
1677 | |
1678 protected void st(Op3s op3, Register rs1, SPARCAddress dest) { | |
1679 ld(op3, dest, rs1); | |
1680 } | |
1681 | |
1682 public void stdf(Register rd, SPARCAddress addr) { | |
1683 assert isDoubleFloatRegister(rd) : rd; | |
1684 st(Stdf, rd, addr); | |
1685 } | |
1686 | |
1687 public void stf(Register rd, SPARCAddress addr) { | |
1688 assert isSingleFloatRegister(rd) : rd; | |
1689 st(Stf, rd, addr); | |
1690 } | |
1691 | |
1692 public void stb(Register rd, SPARCAddress addr) { | |
1693 assert isCPURegister(rd) : rd; | |
1694 st(Stb, rd, addr); | |
1695 } | |
1696 | |
1697 public void sth(Register rd, SPARCAddress addr) { | |
1698 assert isCPURegister(rd) : rd; | |
1699 st(Sth, rd, addr); | |
1700 } | |
1701 | |
1702 public void stw(Register rd, SPARCAddress addr) { | |
1703 assert isCPURegister(rd) : rd; | |
1704 st(Stw, rd, addr); | |
1705 } | |
1706 | |
1707 public void stx(Register rd, SPARCAddress addr) { | |
1708 assert isCPURegister(rd) : rd; | |
1709 st(Stx, rd, addr); | |
1710 } | |
1711 | |
1712 public void membar(int barriers) { | |
1713 op3(Membar, r15, barriers, g0); | |
1714 } | |
1715 | |
1716 public void casa(Register rs1, Register rs2, Register rd, Asi asi) { | |
1717 ld(Casa, new SPARCAddress(rs1, rs2), rd, asi); | |
1718 } | |
1719 | |
1720 public void casxa(Register rs1, Register rs2, Register rd, Asi asi) { | |
1721 ld(Casxa, new SPARCAddress(rs1, rs2), rd, asi); | |
1722 } | |
1723 | |
1724 @Override | |
1725 public InstructionCounter getInstructionCounter() { | |
1726 return new SPARCInstructionCounter(this); | |
1727 } | |
1728 | |
1729 public void patchAddImmediate(int position, int simm13) { | |
1730 int inst = getInt(position); | |
1731 assert SPARCAssembler.isSimm13(simm13) : simm13; | |
1732 assert (inst >>> 30) == 0b10 : String.format("0x%x", inst); | |
1733 assert ((inst >>> 18) & 0b11_1111) == 0 : String.format("0x%x", inst); | |
1734 assert (inst & (1 << 13)) != 0 : String.format("0x%x", inst); | |
1735 inst = inst & (~((1 << 13) - 1)); | |
1736 inst |= simm13 & ((1 << 12) - 1); | |
1737 emitInt(inst, position); | |
1738 } | |
1739 | |
1740 public void fpadd32(Register rs1, Register rs2, Register rd) { | |
1741 op3(Impdep1, Fpadd32, rs1, rs2, rd); | |
1742 } | |
1743 | |
1744 public boolean isCbcond(int i) { | |
1745 return (i & 0xC1C00000) == 0xC00000; | |
1746 } | |
1747 } |