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 }