001/*
002 * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.
008 *
009 * This code is distributed in the hope that it will be useful, but WITHOUT
010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
011 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
012 * version 2 for more details (a copy is included in the LICENSE file that
013 * accompanied this code).
014 *
015 * You should have received a copy of the GNU General Public License version
016 * 2 along with this work; if not, write to the Free Software Foundation,
017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
018 *
019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
020 * or visit www.oracle.com if you need additional information or have any
021 * questions.
022 */
023package com.oracle.graal.asm.sparc;
024
025import static com.oracle.graal.asm.sparc.SPARCAssembler.CC.*;
026import static com.oracle.graal.asm.sparc.SPARCAssembler.ConditionFlag.*;
027import static com.oracle.graal.asm.sparc.SPARCAssembler.Op3s.*;
028import static com.oracle.graal.asm.sparc.SPARCAssembler.Opfs.*;
029import static com.oracle.graal.asm.sparc.SPARCAssembler.Ops.*;
030import static java.lang.String.*;
031import static jdk.internal.jvmci.sparc.SPARC.*;
032
033import java.util.*;
034
035import jdk.internal.jvmci.code.*;
036import jdk.internal.jvmci.meta.*;
037import jdk.internal.jvmci.sparc.*;
038import jdk.internal.jvmci.sparc.SPARC.CPUFeature;
039
040import com.oracle.graal.asm.*;
041
042/**
043 * This class implements an assembler that can encode most SPARC instructions.
044 */
045public abstract class SPARCAssembler extends Assembler {
046
047    /**
048     * Constructs an assembler for the SPARC architecture.
049     *
050     * @param registerConfig the register configuration used to bind {@link Register#Frame} and
051     *            {@link Register#CallerFrame} to physical registers. This value can be null if this
052     *            assembler instance will not be used to assemble instructions using these logical
053     *            registers.
054     */
055    public SPARCAssembler(TargetDescription target, RegisterConfig registerConfig) {
056        super(target);
057    }
058
059    public static final int CCR_ICC_SHIFT = 0;
060    public static final int CCR_XCC_SHIFT = 4;
061    public static final int CCR_V_SHIFT = 1;
062
063    protected static final int OP2_SHIFT = 22;
064    protected static final int OP2_MASK = 0b0000_0001_1100_0000_0000_0000_0000_0000;
065
066    protected static final int DISP22_SHIFT = 0;
067    protected static final int DISP22_MASK = 0b00000000001111111111111111111111;
068
069    protected static final int DISP19_SHIFT = 0;
070    protected static final int DISP19_MASK = 0b00000000000001111111111111111111;
071
072    protected static final int D16HI_SHIFT = 20;
073    protected static final int D16HI_MASK = 0b0000_0000_0011_0000_0000_0000_0000_0000;
074    protected static final int D16LO_SHIFT = 0;
075    protected static final int D16LO_MASK = 0b0000_0000_0000_0000_0011_1111_1111_1111;
076
077    protected static final int D10LO_MASK = 0b0000_0000_0000_0000_0001_1111_1110_0000;
078    protected static final int D10HI_MASK = 0b0000_0000_0001_1000_0000_0000_0000_0000;
079    protected static final int D10LO_SHIFT = 5;
080    protected static final int D10HI_SHIFT = 19;
081
082    private static final Ops[] OPS;
083    private static final Op2s[] OP2S;
084    private static final Op3s[][] OP3S;
085
086    private ArrayList<Integer> delaySlotOptimizationPoints = new ArrayList<>(5);
087
088    static {
089        Ops[] ops = Ops.values();
090        OPS = new Ops[ops.length];
091        for (Ops op : ops) {
092            OPS[op.value] = op;
093        }
094        Op2s[] op2s = Op2s.values();
095        OP2S = new Op2s[op2s.length];
096        for (Op2s op2 : op2s) {
097            OP2S[op2.value] = op2;
098        }
099        OP3S = new Op3s[2][64];
100        for (Op3s op3 : Op3s.values()) {
101            if (op3.value >= 1 << 6) {
102                throw new RuntimeException("Error " + op3 + " " + op3.value);
103            }
104            OP3S[op3.op.value & 1][op3.value] = op3;
105        }
106    }
107
108    public enum Ops {
109        // @formatter:off
110
111        BranchOp(0b00),
112        CallOp(0b01),
113        ArithOp(0b10),
114        LdstOp(0b11);
115
116        // @formatter:on
117
118        private final int value;
119
120        private Ops(int value) {
121            this.value = value;
122        }
123
124        public int getValue() {
125            return value;
126        }
127
128        public boolean appliesTo(int instructionWord) {
129            int opShift = 30;
130            return (instructionWord >>> opShift) == value;
131        }
132    }
133
134    public enum Op2s {
135        // @formatter:off
136
137        Illtrap(0b000),
138        Bpr    (0b011),
139        Fb     (0b110),
140        Fbp    (0b101),
141        Br     (0b010),
142        Bp     (0b001),
143        Cb     (0b111),
144        Sethi  (0b100);
145
146
147        // @formatter:on
148
149        private final int value;
150
151        private Op2s(int value) {
152            this.value = value;
153        }
154
155        public int getValue() {
156            return value;
157        }
158
159        public static Op2s byValue(int value) {
160            return OP2S[value];
161        }
162    }
163
164    public enum Op3s {
165        // @formatter:off
166
167        Add(0x00, "add", ArithOp),
168        And(0x01, "and", ArithOp),
169        Or(0x02, "or", ArithOp),
170        Xor(0x03, "xor", ArithOp),
171        Sub(0x04, "sub", ArithOp),
172        Andn(0x05, "andn", ArithOp),
173        Orn(0x06, "orn", ArithOp),
174        Xnor(0x07, "xnor", ArithOp),
175        Addc(0x08, "addc", ArithOp),
176        Mulx(0x09, "mulx", ArithOp),
177        Umul(0x0A, "umul", ArithOp),
178        Smul(0x0B, "smul", ArithOp),
179        Subc(0x0C, "subc", ArithOp),
180        Udivx(0x0D, "udivx", ArithOp),
181        Udiv(0x0E, "udiv", ArithOp),
182        Sdiv(0x0F, "sdiv", ArithOp),
183
184        Addcc(0x10, "addcc", ArithOp),
185        Andcc(0x11, "andcc", ArithOp),
186        Orcc(0x12, "orcc", ArithOp),
187        Xorcc(0x13, "xorcc", ArithOp),
188        Subcc(0x14, "subcc", ArithOp),
189        Andncc(0x15, "andncc", ArithOp),
190        Orncc(0x16, "orncc", ArithOp),
191        Xnorcc(0x17, "xnorcc", ArithOp),
192        Addccc(0x18, "addccc", ArithOp),
193
194        Umulcc(0x1A, "umulcc", ArithOp),
195        Smulcc(0x1B, "smulcc", ArithOp),
196        Subccc(0x1C, "subccc", ArithOp),
197        Udivcc(0x1E, "udivcc", ArithOp),
198        Sdivcc(0x1F, "sdivcc", ArithOp),
199
200        Taddcc(0x20, "taddcc", ArithOp),
201        Tsubcc(0x21, "tsubcc", ArithOp),
202        Taddcctv(0x22, "taddcctv", ArithOp),
203        Tsubcctv(0x23, "tsubcctv", ArithOp),
204        Mulscc(0x24, "mulscc", ArithOp),
205        Sll(0x25, "sll", ArithOp),
206        Sllx(0x25, "sllx", ArithOp),
207        Srl(0x26, "srl", ArithOp),
208        Srlx(0x26, "srlx", ArithOp),
209        Sra(0x27, "srax", ArithOp),
210        Srax(0x27, "srax", ArithOp),
211        Membar(0x28, "membar", ArithOp),
212
213        Flushw(0x2B, "flushw", ArithOp),
214        Movcc(0x2C, "movcc", ArithOp),
215        Sdivx(0x2D, "sdivx", ArithOp),
216        Popc(0x2E, "popc", ArithOp),
217        Movr(0x2F, "movr", ArithOp),
218
219        Fpop1(0b11_0100, "fpop1", ArithOp),
220        Fpop2(0b11_0101, "fpop2", ArithOp),
221        Impdep1(0b11_0110, "impdep1", ArithOp),
222        Impdep2(0b11_0111, "impdep2", ArithOp),
223        Jmpl(0x38, "jmpl", ArithOp),
224        Rett(0x39, "rett", ArithOp),
225        Trap(0x3a, "trap", ArithOp),
226        Flush(0x3b, "flush", ArithOp),
227        Save(0x3c, "save", ArithOp),
228        Restore(0x3d, "restore", ArithOp),
229        Retry(0x3e, "retry", ArithOp),
230
231
232        Casa(0b111100, "casa", LdstOp),
233        Casxa(0b111110, "casxa", LdstOp),
234        Prefetch(0b101101, "prefetch", LdstOp),
235        Prefetcha(0b111101, "prefetcha", LdstOp),
236
237        Lduw  (0b00_0000, "lduw", LdstOp),
238        Ldub  (0b00_0001, "ldub", LdstOp),
239        Lduh  (0b00_0010, "lduh", LdstOp),
240        Stw   (0b00_0100, "stw", LdstOp),
241        Stb   (0b00_0101, "stb", LdstOp),
242        Sth   (0b00_0110, "sth", LdstOp),
243        Ldsw  (0b00_1000, "ldsw", LdstOp),
244        Ldsb  (0b00_1001, "ldsb", LdstOp),
245        Ldsh  (0b00_1010, "ldsh", LdstOp),
246        Ldx   (0b00_1011, "ldx", LdstOp),
247        Stx   (0b00_1110, "stx", LdstOp),
248
249        Ldf   (0b10_0000, "ldf", LdstOp),
250        Ldfsr (0b10_0001, "ldfsr", LdstOp),
251        Ldaf  (0b10_0010, "ldaf", LdstOp),
252        Lddf  (0b10_0011, "lddf", LdstOp),
253        Stf   (0b10_0100, "stf", LdstOp),
254        Stfsr (0b10_0101, "stfsr", LdstOp),
255        Staf  (0b10_0110, "staf", LdstOp),
256        Stdf  (0b10_0111, "stdf", LdstOp),
257
258        Rd    (0b10_1000, "rd", ArithOp),
259        Wr    (0b11_0000, "wr", ArithOp),
260        Fcmp  (0b11_0101, "fcmp", ArithOp),
261
262        Ldxa  (0b01_1011, "ldxa", LdstOp),
263        Lduwa (0b01_0000, "lduwa", LdstOp),
264
265        Tcc(0b11_1010, "tcc", ArithOp);
266
267        // @formatter:on
268
269        private final int value;
270        private final String operator;
271        private final Ops op;
272
273        private Op3s(int value, String name, Ops op) {
274            assert isImm(value, 6);
275            this.value = value;
276            this.operator = name;
277            this.op = op;
278        }
279
280        public int getValue() {
281            return value;
282        }
283
284        public String getOperator() {
285            return operator;
286        }
287
288        public boolean throwsException() {
289            if (op == LdstOp) {
290                return true;
291            }
292            switch (this) {
293                case Udiv:
294                case Udivx:
295                case Sdiv:
296                case Sdivx:
297                case Udivcc:
298                case Sdivcc:
299                    return true;
300                default:
301                    return false;
302            }
303        }
304    }
305
306    public enum Opfs {
307        // @formatter:off
308
309        Fmovs(0b0_0000_0001, "fmovs"),
310        Fmovd(0b0_0000_0010, "fmovd"),
311        Fmovq(0b0_0000_0011, "fmovq"),
312        Fmovscc(0b00_0001, "fmovscc"),
313        Fmovdcc(0b00_0010, "fmovdcc"),
314        Fnegs(0x05, "fnegs"),
315        Fnegd(0x06, "fnegd"),
316        Fnegq(0x07, "fnegq"),
317        Fabss(0x09, "fabss"),
318        Fabsd(0x0A, "fabsd"),
319        Fabsq(0x0B, "fabsq"),
320
321        // start VIS1
322        Edge8cc(0x0, "edge8cc"),
323        Edge8n(0x1, "edge8n"),
324        Edge8lcc(0x2, "edge8lcc"),
325        Edge8ln(0x3, "edge8ln"),
326        Edge16cc(0x4, "edge16cc"),
327        Edge16n(0x5, "edge16n"),
328        Edge16lcc(0x6, "edge16lcc"),
329        Edge16ln(0x7, "edge16ln"),
330        Edge32cc(0x8, "edge32cc"),
331        Edge32n(0x9, "edge32n"),
332        Edge32lcc(0xA, "edge32lcc"),
333        Edge32ln(0xB, "edge32ln"),
334        Array8(0x10, "array8"),
335        Array16(0x12, "array16"),
336        Array32(0x14, "array32"),
337        AlignAddress(0x18, "alignaddress"),
338        AlignAddressLittle(0x1A, "alignaddress_little"),
339        Fpcmple16(0x20, "fpcmple16"),
340        Fpcmpne16(0x22, "fpcmpne16"),
341        Fpcmple32(0x24, "fpcmple32"),
342        Fpcmpne32(0x26, "fpcmpne32"),
343        Fpcmpgt16(0x28, "fpcmpgt16"),
344        Fpcmpeq16(0x2A, "fpcmpeq16"),
345        Fpcmpgt32(0x2C, "fpcmpgt32"),
346        Fpcmpeq32(0x2E, "fpcmpeq32"),
347        Fmul8x16(0x31, "fmul8x16"),
348        Fmul8x16au(0x33, "fmul8x16au"),
349        Fmul8x16al(0x35, "fmul8x16al"),
350        Fmul8sux16(0x36, "fmul8sux16"),
351        Fmul8ulx16(0x37, "fmul8ulx16"),
352        Fmuld8sux16(0x38, "fmuld8sux16"),
353        Fmuld8ulx16(0x39, "fmuld8ulx16"),
354        Fpack32(0x3A, "fpack32"),
355        Fpack16(0x3B, "fpack16"),
356        Fpackfix(0x3D, "fpackfix"),
357        Faligndatag(0x48, "faligndata"),
358        Fpmerge(0x4B, "fpmerge"),
359        Fpadd16(0x50, "fpadd16"),
360        Fpadd16s(0x51, "fpadd16s"),
361        Fpadd32(0x52, "fpadd32"),
362        Fpadd32s(0x53, "fpadd32s"),
363        Fpsub16(0x54, "fpadd16"),
364        Fpsub16s(0x55, "fpadd16s"),
365        Fpsub32(0x56, "fpadd32"),
366        Fpsub32s(0x57, "fpadd32s"),
367        Fzerod(0x60, "fzerod"),
368        Fzeros(0x61, "fzeros"),
369        Fnot2d(0x66, "fnot1d"),
370        Fnot2s(0x67, "fnot1s"),
371        Fnot1d(0x6A, "fnot1d"),
372        Fnot1s(0x6B, "fnot1s"),
373        Fsrc1d(0x74, "fsrc1d"),
374        Fsrc1s(0x75, "fsrc1s"),
375        Fsrc2d(0x78, "fsrc2d"),
376        Fsrc2s(0x79, "fsrc2s"),
377        Foned(0x7E, "foned"),
378        Fones(0x7F, "fones"),
379        Fandd(0b0_0111_0000, "fandd"),
380        Fands(0b0_0111_0001, "fands"),
381        Fxord(0b0_0110_1100, "fxord"),
382        Fxors(0b0_0110_1101, "fxors"),
383        // end VIS1
384
385        // start VIS2
386        Bmask(0x19, "bmask"),
387        Bshuffle(0x4c, "bshuffle"),
388        // end VIS2 only
389
390        // start VIS3
391        Addxc(0x11, "addxc"),
392        Addxccc(0x13, "addxccc"),
393        Cmask8(0x1B, "cmask8"),
394        Cmask16(0x1D, "cmask16"),
395        Cmask32(0x1F, "cmask32"),
396        Fmean16(0x40, "fmean16"),
397        Fnadds(0x51, "fnadds"),
398        Fnaddd(0x52, "fnaddd"),
399        Fnmuls(0x59, "fnmuls"),
400        Fnmuld(0x5A, "fnmuld"),
401        Fnsmuld(0x79, "fnsmuld"),
402        Fnhadds(0x71, "fnhadds"),
403        Fnhaddd(0x72, "fnhaddd"),
404        Movdtox(0x110, "movdtox"),
405        Movstouw(0x111, "movstouw"),
406        Movstosw(0x113, "movstosw"),
407        Movxtod(0x118, "movxtod"),
408        Movwtos(0b1_0001_1001, "movwtos"),
409        UMulxhi(0b0_0001_0110, "umulxhi"),
410        Lzcnt  (0b0_0001_0111, "lzcnt"),
411        // end VIS3
412
413        // start CAMMELLIA
414        CammelliaFl(0x13C, "cammelia_fl"),
415        CammelliaFli(0x13D, "cammellia_fli"),
416        // end CAMMELLIA
417
418        // start CRYPTO
419        Crc32c(0x147, "crc32c"),
420        // end CRYPTO
421
422        // start OSA 2011
423        Fpadd64(0x44, "fpadd64"),
424        Fpsub64(0x46, "fpsub64"),
425        Fpadds16(0x58, "fpadds16"),
426        Fpadds16s(0x59, "fpadds16"),
427        Fpadds32(0x5A, "fpadds32"),
428        Fpadds32s(0x5B, "fpadds32s"),
429        Fpsubs16(0x5C, "fpsubs16"),
430        Fpsubs16s(0x5D, "fpsubs16s"),
431        Fpsubs32(0x5E, "fpsubs32"),
432        Fpsubs32s(0x5F, "fpsubs32s"),
433        Fpcmpne8(0x122, "fpcmpne8"),
434        Fpcmpeq8(0x12C, "fpcmpeq8"),
435        // end OSA 2011
436
437        Fadds(0x41, "fadds"),
438        Faddd(0x42, "faddd"),
439        Faddq(0x43, "faddq"),
440        Fsubs(0x45, "fsubs"),
441        Fsubd(0x46, "fsubd"),
442        Fsubq(0x47, "fsubq"),
443        Fmuls(0x49, "fmuls"),
444        Fmuld(0x4A, "fmuld"),
445        Fdivs(0x4D, "fdivs"),
446        Fdivd(0x4E, "fdivd"),
447        Fdivq(0x4F, "fdivq"),
448
449        Fsqrts(0x29, "fsqrts"),
450        Fsqrtd(0x2A, "fsqrtd"),
451        Fsqrtq(0x2B, "fsqrtq"),
452
453        Fsmuld(0x69, "fsmuld"),
454        Fmulq(0x6B, "fmulq"),
455        Fdmuldq(0x6E, "fdmulq"),
456
457        Fstoi(0xD1, "fstoi"),
458        Fdtoi(0xD2, "fdtoi"),
459        Fstox(0x81, "fstox"),
460        Fdtox(0x82, "fdtox"),
461        Fxtos(0x84, "fxtos"),
462        Fxtod(0x88, "fxtod"),
463        Fxtoq(0x8C, "fxtoq"),
464        Fitos(0xC4, "fitos"),
465        Fdtos(0xC6, "fdtos"),
466        Fitod(0xC8, "fitod"),
467        Fstod(0xC9, "fstod"),
468        Fitoq(0xCC, "fitoq"),
469
470
471        Fcmps(0x51, "fcmps"),
472        Fcmpd(0x52, "fcmpd"),
473        Fcmpq(0x53, "fcmpq");
474
475        // @formatter:on
476
477        private final int value;
478        private final String operator;
479
480        private Opfs(int value, String op) {
481            this.value = value;
482            this.operator = op;
483        }
484
485        public int getValue() {
486            return value;
487        }
488
489        public String getOperator() {
490            return operator;
491        }
492    }
493
494    public enum Annul {
495        ANNUL(1),
496        NOT_ANNUL(0);
497        public final int flag;
498
499        Annul(int flag) {
500            this.flag = flag;
501        }
502    }
503
504    public enum BranchPredict {
505        PREDICT_TAKEN(1),
506        PREDICT_NOT_TAKEN(0);
507        public final int flag;
508
509        BranchPredict(int flag) {
510            this.flag = flag;
511        }
512    }
513
514    public enum MembarMask {
515        // @formatter:off
516
517        StoreStore(1 << 3, "storestore"),
518        LoadStore(1 << 2, "loadstore"),
519        StoreLoad(1 << 1, "storeload"),
520        LoadLoad(1 << 0, "loadload"),
521        Sync(1 << 6, "sync"),
522        MemIssue(1 << 5, "memissue"),
523        LookAside(1 << 4, "lookaside");
524
525        // @formatter:on
526
527        private final int value;
528        private final String operator;
529
530        private MembarMask(int value, String op) {
531            this.value = value;
532            this.operator = op;
533        }
534
535        public int getValue() {
536            return value | 0x2000;
537        }
538
539        public String getOperator() {
540            return operator;
541        }
542    }
543
544    /**
545     * Condition Codes to use for instruction.
546     */
547    public enum CC {
548        // @formatter:off
549        /**
550         * Condition is considered as 32bit operation condition.
551         */
552        Icc(0b00, "icc", false),
553        /**
554         * Condition is considered as 64bit operation condition.
555         */
556        Xcc(0b10, "xcc", false),
557        Fcc0(0b00, "fcc0", true),
558        Fcc1(0b01, "fcc1", true),
559        Fcc2(0b10, "fcc2", true),
560        Fcc3(0b11, "fcc3", true);
561
562        // @formatter:on
563
564        private final int value;
565        private final String operator;
566        private boolean isFloat;
567
568        private CC(int value, String op, boolean isFloat) {
569            this.value = value;
570            this.operator = op;
571            this.isFloat = isFloat;
572        }
573
574        public int getValue() {
575            return value;
576        }
577
578        public String getOperator() {
579            return operator;
580        }
581
582        public static CC forKind(Kind kind) {
583            boolean isInt = kind == Kind.Boolean || kind == Kind.Byte || kind == Kind.Char || kind == Kind.Short || kind == Kind.Int;
584            boolean isFloat = kind == Kind.Float || kind == Kind.Double;
585            boolean isLong = kind == Kind.Long || kind == Kind.Object;
586            assert isInt || isFloat || isLong;
587            if (isLong) {
588                return Xcc;
589            } else if (isInt) {
590                return Icc;
591            } else if (isFloat) {
592                return Fcc0;
593            } else {
594                throw new InternalError();
595            }
596        }
597    }
598
599    public enum ConditionFlag {
600        // @formatter:off
601
602        // for FBfcc & FBPfcc instruction
603        F_Never(0, "f_never"),
604        F_NotEqual(1, "f_notEqual"),
605        F_LessOrGreater(2, "f_lessOrGreater"),
606        F_UnorderedOrLess(3, "f_unorderedOrLess"),
607        F_Less(4, "f_less"),
608        F_UnorderedOrGreater(5, "f_unorderedOrGreater"),
609        F_Greater(6, "f_greater"),
610        F_Unordered(7, "f_unordered"),
611        F_Always(8, "f_always"),
612        F_Equal(9, "f_equal"),
613        F_UnorderedOrEqual(10, "f_unorderedOrEqual"),
614        F_GreaterOrEqual(11, "f_greaterOrEqual"),
615        F_UnorderedGreaterOrEqual(12, "f_unorderedGreaterOrEqual"),
616        F_LessOrEqual(13, "f_lessOrEqual"),
617        F_UnorderedOrLessOrEqual(14, "f_unorderedOrLessOrEqual"),
618        F_Ordered(15, "f_ordered"),
619
620        // for integers
621        Never(0, "never"),
622        Equal(1, "equal", true),
623        Zero(1, "zero"),
624        LessEqual(2, "lessEqual", true),
625        Less(3, "less", true),
626        LessEqualUnsigned(4, "lessEqualUnsigned", true),
627        LessUnsigned(5, "lessUnsigned", true),
628        CarrySet(5, "carrySet"),
629        Negative(6, "negative", true),
630        OverflowSet(7, "overflowSet", true),
631        Always(8, "always"),
632        NotEqual(9, "notEqual", true),
633        NotZero(9, "notZero"),
634        Greater(10, "greater", true),
635        GreaterEqual(11, "greaterEqual", true),
636        GreaterUnsigned(12, "greaterUnsigned", true),
637        GreaterEqualUnsigned(13, "greaterEqualUnsigned", true),
638        CarryClear(13, "carryClear"),
639        Positive(14, "positive", true),
640        OverflowClear(15, "overflowClear", true);
641
642        // @formatter:on
643
644        private final int value;
645        private final String operator;
646        private boolean forCBcond = false;
647
648        private ConditionFlag(int value, String op) {
649            this(value, op, false);
650        }
651
652        private ConditionFlag(int value, String op, boolean cbcond) {
653            this.value = value;
654            this.operator = op;
655            this.forCBcond = cbcond;
656        }
657
658        public boolean isCBCond() {
659            return forCBcond;
660        }
661
662        public int getValue() {
663            return value;
664        }
665
666        public String getOperator() {
667            return operator;
668        }
669
670        public ConditionFlag negate() {
671            //@formatter:off
672            switch (this) {
673                case F_Never                  : return F_Always;
674                case F_Always                 : return F_Never;
675                case F_NotEqual               : return F_Equal;
676                case F_Equal                  : return F_NotEqual;
677                case F_LessOrGreater          : return F_UnorderedOrEqual;
678                case F_UnorderedOrEqual       : return F_LessOrGreater;
679                case F_Less                   : return F_UnorderedGreaterOrEqual;
680                case F_UnorderedGreaterOrEqual: return F_Less;
681                case F_LessOrEqual            : return F_UnorderedOrGreater;
682                case F_UnorderedOrGreater     : return F_LessOrEqual;
683                case F_Greater                : return F_UnorderedOrLessOrEqual;
684                case F_UnorderedOrLessOrEqual : return F_Greater;
685                case F_GreaterOrEqual         : return F_UnorderedOrLess;
686                case F_UnorderedOrLess        : return F_GreaterOrEqual;
687                case F_Unordered              : return F_Ordered;
688                case F_Ordered                : return F_Unordered;
689                case Never                    : return Always;
690                case Always                   : return Never;
691                case Equal                    : return NotEqual;
692                case NotEqual                 : return Equal;
693                case Zero                     : return NotZero;
694                case NotZero                  : return Zero;
695                case LessEqual                : return Greater;
696                case Greater                  : return LessEqual;
697                case Less                     : return GreaterEqual;
698                case GreaterEqual             : return Less;
699                case LessEqualUnsigned        : return GreaterUnsigned;
700                case GreaterUnsigned          : return LessEqualUnsigned;
701                case LessUnsigned             : return GreaterEqualUnsigned;
702                case GreaterEqualUnsigned     : return LessUnsigned;
703                case CarrySet                 : return CarryClear;
704                case CarryClear               : return CarrySet;
705                case Negative                 : return Positive;
706                case Positive                 : return Negative;
707                case OverflowSet              : return OverflowClear;
708                case OverflowClear            : return OverflowSet;
709                default:
710                    throw new InternalError();
711            }
712            //@formatter:on
713        }
714
715        public ConditionFlag mirror() {
716            switch (this) {
717            //@formatter:off
718                case F_Less                   : return F_Greater;
719                case F_Greater                : return F_Less;
720                case F_LessOrEqual            : return F_GreaterOrEqual;
721                case F_UnorderedGreaterOrEqual: return F_UnorderedOrLessOrEqual;
722                case F_UnorderedOrGreater     : return F_UnorderedOrLess;
723                case F_UnorderedOrLessOrEqual : return F_UnorderedGreaterOrEqual;
724                case F_GreaterOrEqual         : return F_LessOrEqual;
725                case F_UnorderedOrLess        : return F_UnorderedOrGreater;
726                case LessEqual                : return GreaterEqual;
727                case Greater                  : return Less;
728                case Less                     : return Greater;
729                case GreaterEqual             : return LessEqual;
730                case LessEqualUnsigned        : return GreaterEqualUnsigned;
731                case GreaterUnsigned          : return LessUnsigned;
732                case LessUnsigned             : return GreaterUnsigned;
733                case GreaterEqualUnsigned     : return LessEqualUnsigned;
734                default:
735                    return this;
736                //@formatter:on
737            }
738        }
739
740    }
741
742    public enum RCondition {
743        // @formatter:off
744
745        Rc_z(0b001, "rc_z"),
746        Rc_lez(0b010, "rc_lez"),
747        Rc_lz(0b011, "rc_lz"),
748        Rc_nz(0b101, "rc_nz"),
749        Rc_gz(0b110, "rc_gz"),
750        Rc_gez(0b111, "rc_gez"),
751        Rc_last(Rc_gez.getValue(), "rc_last");
752
753        // @formatter:on
754
755        private final int value;
756        private final String operator;
757
758        private RCondition(int value, String op) {
759            this.value = value;
760            this.operator = op;
761        }
762
763        public int getValue() {
764            return value;
765        }
766
767        public String getOperator() {
768            return operator;
769        }
770    }
771
772    /**
773     * Represents the <b>Address Space Identifier</b> defined in the SPARC architecture.
774     */
775    public enum Asi {
776        // @formatter:off
777
778        INVALID(-1),
779        ASI_PRIMARY(0x80),
780        ASI_PRIMARY_NOFAULT(0x82),
781        ASI_PRIMARY_LITTLE(0x88),
782        // Block initializing store
783        ASI_ST_BLKINIT_PRIMARY(0xE2),
784        // Most-Recently-Used (MRU) BIS variant
785        ASI_ST_BLKINIT_MRU_PRIMARY(0xF2);
786
787        // @formatter:on
788
789        private final int value;
790
791        private Asi(int value) {
792            this.value = value;
793        }
794
795        public int getValue() {
796            return value;
797        }
798
799        public boolean isValid() {
800            return value != INVALID.getValue();
801        }
802    }
803
804    public enum Fcn {
805        SeveralWritesAndPossiblyReads(2),
806        SeveralReadsWeak(0),
807        OneRead(1),
808        OneWrite(3),
809        Page(4),
810        NearestUnifiedCache(17),
811        SeveralReadsStrong(20),
812        OneReadStrong(21),
813        SeveralWritesAndPossiblyReadsStrong(22),
814        OneWriteStrong(23);
815
816        private final int value;
817
818        private Fcn(int value) {
819            this.value = value;
820        }
821
822        public int getValue() {
823            return value;
824        }
825    }
826
827    /**
828     * Specifies various bit fields used in SPARC instructions.
829     */
830    @SuppressWarnings("unused")
831    public abstract static class BitSpec {
832        private static final BitSpec op = new ContinousBitSpec(31, 30, "op");
833        private static final BitSpec op2 = new ContinousBitSpec(24, 22, "op2");
834        private static final BitSpec op3 = new ContinousBitSpec(24, 19, "op3");
835        private static final BitSpec rd = new ContinousBitSpec(29, 25, "rd");
836        private static final BitSpec rs1 = new ContinousBitSpec(18, 14, "rs1");
837        private static final BitSpec rs2 = new ContinousBitSpec(4, 0, "rs2");
838        private static final BitSpec simm13 = new ContinousBitSpec(12, 0, "simm13");
839        private static final BitSpec imm22 = new ContinousBitSpec(21, 0, "imm22");
840        private static final BitSpec immAsi = new ContinousBitSpec(12, 5, "immASI");
841        private static final BitSpec i = new ContinousBitSpec(13, 13, "i");
842        private static final BitSpec disp19 = new ContinousBitSpec(18, 0, true, "disp19");
843        private static final BitSpec disp22 = new ContinousBitSpec(21, 0, true, "disp22");
844        private static final BitSpec disp30 = new ContinousBitSpec(29, 0, true, "disp30");
845        private static final BitSpec a = new ContinousBitSpec(29, 29, "a");
846        private static final BitSpec p = new ContinousBitSpec(19, 19, "p");
847        private static final BitSpec cond = new ContinousBitSpec(28, 25, "cond");
848        private static final BitSpec rcond = new ContinousBitSpec(27, 25, "rcond");
849        private static final BitSpec cc = new ContinousBitSpec(21, 20, "cc");
850        private static final BitSpec d16hi = new ContinousBitSpec(21, 20, "d16hi");
851        private static final BitSpec d16lo = new ContinousBitSpec(13, 0, "d16lo");
852        private static final BitSpec d16 = new CompositeBitSpec(d16hi, d16lo);
853        // CBCond
854        private static final BitSpec cLo = new ContinousBitSpec(27, 25, "cLo");
855        private static final BitSpec cHi = new ContinousBitSpec(29, 29, "cHi");
856        private static final BitSpec c = new CompositeBitSpec(cHi, cLo);
857        private static final BitSpec cbcond = new ContinousBitSpec(28, 28, "cbcond");
858        private static final BitSpec cc2 = new ContinousBitSpec(21, 21, "cc2");
859        private static final BitSpec d10Lo = new ContinousBitSpec(12, 5, "d10Lo");
860        private static final BitSpec d10Hi = new ContinousBitSpec(20, 19, "d10Hi");
861        private static final BitSpec d10 = new CompositeBitSpec(d10Hi, d10Lo);
862        private static final BitSpec simm5 = new ContinousBitSpec(4, 0, true, "simm5");
863
864        public abstract int setBits(int word, int value);
865
866        public abstract int getBits(int word);
867
868        public abstract int getWidth();
869
870        public abstract boolean valueFits(int value);
871    }
872
873    public static class ContinousBitSpec extends BitSpec {
874        private final int hiBit;
875        private final int lowBit;
876        private final int width;
877        private final boolean signExt;
878        private final int mask;
879        private final String name;
880
881        public ContinousBitSpec(int hiBit, int lowBit, String name) {
882            this(hiBit, lowBit, false, name);
883        }
884
885        public ContinousBitSpec(int hiBit, int lowBit, boolean signExt, String name) {
886            super();
887            this.hiBit = hiBit;
888            this.lowBit = lowBit;
889            this.signExt = signExt;
890            this.width = hiBit - lowBit + 1;
891            mask = ((1 << width) - 1) << lowBit;
892            this.name = name;
893        }
894
895        @Override
896        public int setBits(int word, int value) {
897            assert valueFits(value) : "Value: " + value + " does not fit in " + this;
898            return (word & ~mask) | ((value << lowBit) & mask);
899        }
900
901        @Override
902        public int getBits(int word) {
903            if (signExt) {
904                return ((word & mask) << (31 - hiBit)) >> (32 - width);
905            } else {
906                return (word & mask) >>> lowBit;
907            }
908        }
909
910        @Override
911        public int getWidth() {
912            return width;
913        }
914
915        @Override
916        public String toString() {
917            return String.format("%s [%d:%d]", name, hiBit, lowBit);
918        }
919
920        @Override
921        public boolean valueFits(int value) {
922            if (signExt) {
923                return isSimm(value, getWidth());
924            } else {
925                return isImm(value, getWidth());
926            }
927        }
928    }
929
930    public static class CompositeBitSpec extends BitSpec {
931        private final BitSpec left;
932        private final int leftWidth;
933        private final BitSpec right;
934        private final int rightWidth;
935
936        public CompositeBitSpec(BitSpec left, BitSpec right) {
937            super();
938            this.left = left;
939            this.leftWidth = left.getWidth();
940            this.right = right;
941            this.rightWidth = right.getWidth();
942        }
943
944        @Override
945        public int getBits(int word) {
946            int l = left.getBits(word);
947            int r = right.getBits(word);
948            return l << rightWidth | r;
949        }
950
951        @Override
952        public int setBits(int word, int value) {
953            int l = leftBits(value);
954            int r = rightBits(value);
955            return left.setBits(right.setBits(word, r), l);
956        }
957
958        private int leftBits(int value) {
959            return SPARCAssembler.getBits(value, rightWidth + leftWidth, rightWidth);
960        }
961
962        private int rightBits(int value) {
963            return SPARCAssembler.getBits(value, rightWidth - 1, 0);
964        }
965
966        @Override
967        public int getWidth() {
968            return left.getWidth() + right.getWidth();
969        }
970
971        @Override
972        public String toString() {
973            return String.format("CompositeBitSpec[%s, %s]", left, right);
974        }
975
976        @Override
977        public boolean valueFits(int value) {
978            return left.valueFits(leftBits(value)) && right.valueFits(rightBits(value));
979        }
980    }
981
982    public static class BitKey {
983        private final BitSpec spec;
984        private final int value;
985
986        public BitKey(BitSpec spec, int value) {
987            super();
988            this.spec = spec;
989            this.value = value;
990        }
991
992        @Override
993        public String toString() {
994            return String.format("BitKey %s=%s", spec, value);
995        }
996    }
997
998    /**
999     * Represents a prefix tree of {@link BitSpec} objects to find the most accurate SPARCOp.
1000     */
1001    public static class BitKeyIndex {
1002        private final BitSpec spec;
1003        private final Map<Integer, BitKeyIndex> nodes;
1004        private SPARCOp op;
1005
1006        public BitKeyIndex(SPARCOp op) {
1007            assert op != null;
1008            this.op = op;
1009            this.nodes = null;
1010            this.spec = null;
1011        }
1012
1013        public BitKeyIndex(BitSpec spec) {
1014            assert spec != null;
1015            this.op = null;
1016            this.nodes = new HashMap<>(4);
1017            this.spec = spec;
1018        }
1019
1020        /**
1021         * Adds operation to the index.
1022         *
1023         * @param keys Ordered by the importance
1024         * @param operation Operation represented by this list of keys
1025         */
1026        private void addOp(List<BitKey> keys, SPARCOp operation) {
1027            assert keys.size() > 0;
1028            BitKey first = keys.get(0);
1029            assert first.spec.equals(spec) : first.spec + " " + spec;
1030            BitKeyIndex node;
1031            if (keys.size() == 1) {
1032                if (nodes.containsKey(first.value)) {
1033                    node = nodes.get(first.value);
1034                    assert node.op == null : node + " " + keys;
1035                    node.op = operation;
1036                } else {
1037                    assert !nodes.containsKey(first.value) : "Index must be unique. Existing key: " + nodes.get(first.value);
1038                    node = new BitKeyIndex(operation);
1039                }
1040            } else {
1041                node = nodes.get(first.value);
1042                if (node == null) {
1043                    node = new BitKeyIndex(keys.get(1).spec);
1044                }
1045                node.addOp(keys.subList(1, keys.size()), operation);
1046            }
1047            nodes.put(first.value, node);
1048        }
1049
1050        /**
1051         * Finds the best matching {@link SPARCOp} for this instruction.
1052         */
1053        public SPARCOp find(int inst) {
1054            if (nodes != null) {
1055                int key = spec.getBits(inst);
1056                BitKeyIndex sub = nodes.get(key);
1057                if (sub == null) {
1058                    if (op != null) {
1059                        return op;
1060                    } else {
1061                        throw new RuntimeException(String.format("%s 0x%x, 0x%x %s", spec, inst, key, nodes));
1062                    }
1063                }
1064                return sub.find(inst);
1065            } else {
1066                return this.op;
1067            }
1068        }
1069
1070        @Override
1071        public String toString() {
1072            return this.op == null ? this.spec + ": " + this.nodes : this.op.toString();
1073        }
1074    }
1075
1076    public static final Bpcc BPCC = new Bpcc(Op2s.Bp);
1077    public static final Bpcc FBPCC = new Bpcc(Op2s.Fbp);
1078    public static final CBCond CBCOND = new CBCond();
1079    public static final Bpr BPR = new Bpr();
1080    public static final Br BR = new Br();
1081    public static final Sethi SETHI = new Sethi();
1082    public static final Op3Op OP3 = new Op3Op();
1083    public static final SPARCOp LDST = new SPARCOp(Ops.LdstOp);
1084    public static final SPARCOp BRANCH = new SPARCOp(Ops.BranchOp);
1085    public static final SPARCOp CALL = new SPARCOp(Ops.CallOp);
1086    private static final BitKeyIndex INDEX = new BitKeyIndex(BitSpec.op);
1087
1088    static {
1089        for (SPARCOp op : SPARCOp.OPS) {
1090            INDEX.addOp(op.getKeys(), op);
1091        }
1092    }
1093
1094    public static SPARCOp getSPARCOp(int inst) {
1095        return INDEX.find(inst);
1096    }
1097
1098    /**
1099     * Represents a class of SPARC instruction and gives methods to modify its fields.
1100     */
1101    public static class SPARCOp {
1102        private final Ops op;
1103        private final BitKey opKey;
1104        private List<BitKey> keyFields;
1105        private static final List<SPARCOp> OPS = new ArrayList<>();
1106
1107        public SPARCOp(Ops op) {
1108            super();
1109            this.op = op;
1110            this.opKey = new BitKey(BitSpec.op, op.value);
1111            OPS.add(this);
1112        }
1113
1114        protected int setBits(int word) {
1115            return BitSpec.op.setBits(word, op.value);
1116        }
1117
1118        public boolean match(int inst) {
1119            for (BitKey k : keyFields) {
1120                if (k.spec.getBits(inst) != k.value) {
1121                    return false;
1122                }
1123            }
1124            return true;
1125        }
1126
1127        protected List<BitKey> getKeys() {
1128            if (keyFields == null) {
1129                keyFields = new ArrayList<>(4);
1130                keyFields.add(opKey);
1131            }
1132            return keyFields;
1133        }
1134
1135        public Ops getOp(int inst) {
1136            return SPARCAssembler.OPS[BitSpec.op.getBits(inst)];
1137        }
1138
1139        @Override
1140        public String toString() {
1141            String name = getClass().getName();
1142            name = name.substring(name.lastIndexOf(".") + 1);
1143            return name + "[op: " + op + "]";
1144        }
1145    }
1146
1147    /**
1148     * Base class for control transfer operations; provides access to the disp field.
1149     */
1150    public abstract static class ControlTransferOp extends SPARCOp {
1151        private final Op2s op2;
1152        private final boolean delaySlot;
1153        private final BitSpec disp;
1154        private final BitKey op2Key;
1155
1156        private ControlTransferOp(Ops op, Op2s op2, boolean delaySlot, BitSpec disp) {
1157            super(op);
1158            this.op2 = op2;
1159            this.delaySlot = delaySlot;
1160            this.disp = disp;
1161            this.op2Key = new BitKey(BitSpec.op2, op2.value);
1162        }
1163
1164        public boolean hasDelaySlot() {
1165            return delaySlot;
1166        }
1167
1168        @Override
1169        protected int setBits(int word) {
1170            return BitSpec.op2.setBits(super.setBits(word), op2.value);
1171        }
1172
1173        protected int setDisp(int inst, SPARCMacroAssembler masm, Label lab) {
1174            if (lab.isBound()) {
1175                int d = (lab.position() - masm.position()) / 4;
1176                return setDisp(inst, d);
1177            } else {
1178                masm.patchUnbound(lab);
1179                return inst;
1180            }
1181        }
1182
1183        public int setDisp(int inst, int d) {
1184            assert this.match(inst);
1185            return this.disp.setBits(inst, d);
1186        }
1187
1188        public boolean isValidDisp(int d) {
1189            return this.disp.valueFits(d);
1190        }
1191
1192        public int setAnnul(int inst, boolean a) {
1193            return BitSpec.a.setBits(inst, a ? 1 : 0);
1194        }
1195
1196        @Override
1197        protected List<BitKey> getKeys() {
1198            List<BitKey> keys = super.getKeys();
1199            keys.add(op2Key);
1200            return keys;
1201        }
1202
1203        public int getDisp(int inst) {
1204            return this.disp.getBits(inst);
1205        }
1206
1207        public abstract boolean isAnnulable(int inst);
1208
1209        public abstract boolean isConditional(int inst);
1210    }
1211
1212    public static class Bpcc extends ControlTransferOp {
1213        public Bpcc(Op2s op2) {
1214            super(Ops.BranchOp, op2, true, BitSpec.disp19);
1215        }
1216
1217        public void emit(SPARCMacroAssembler masm, CC cc, ConditionFlag cf, Annul annul, BranchPredict p, Label lab) {
1218            int inst = setBits(0);
1219            inst = BitSpec.a.setBits(inst, annul.flag);
1220            inst = BitSpec.cond.setBits(inst, cf.value);
1221            inst = BitSpec.cc.setBits(inst, cc.value);
1222            inst = BitSpec.p.setBits(inst, p.flag);
1223            masm.emitInt(setDisp(inst, masm, lab));
1224        }
1225
1226        @Override
1227        public boolean isAnnulable(int inst) {
1228            return isConditional(inst);
1229        }
1230
1231        @Override
1232        public boolean isConditional(int inst) {
1233            int cond = BitSpec.cond.getBits(inst);
1234            return cond != ConditionFlag.Always.value && cond != ConditionFlag.Never.value;
1235        }
1236    }
1237
1238    public static class Br extends ControlTransferOp {
1239        public Br() {
1240            super(Ops.BranchOp, Op2s.Br, true, BitSpec.disp22);
1241        }
1242
1243        @Override
1244        public boolean isAnnulable(int inst) {
1245            return isConditional(inst);
1246        }
1247
1248        @Override
1249        public boolean isConditional(int inst) {
1250            int cond = BitSpec.cond.getBits(inst);
1251            return cond != ConditionFlag.Always.value && cond != ConditionFlag.Never.value;
1252        }
1253    }
1254
1255    public static class Bpr extends ControlTransferOp {
1256        private static final BitKey CBCOND_KEY = new BitKey(BitSpec.cbcond, 0);
1257
1258        public Bpr() {
1259            super(Ops.BranchOp, Op2s.Bpr, true, BitSpec.d16);
1260        }
1261
1262        public void emit(SPARCMacroAssembler masm, RCondition rcond, Annul a, BranchPredict p, Register rs1, Label lab) {
1263            int inst = setBits(0);
1264            inst = BitSpec.rcond.setBits(inst, rcond.value);
1265            inst = BitSpec.a.setBits(inst, a.flag);
1266            inst = BitSpec.p.setBits(inst, p.flag);
1267            inst = BitSpec.rs1.setBits(inst, rs1.encoding);
1268            masm.emitInt(setDisp(inst, masm, lab));
1269        }
1270
1271        @Override
1272        protected List<BitKey> getKeys() {
1273            List<BitKey> keys = super.getKeys();
1274            keys.add(CBCOND_KEY);
1275            return keys;
1276        }
1277
1278        @Override
1279        public boolean isAnnulable(int inst) {
1280            return isConditional(inst);
1281        }
1282
1283        @Override
1284        public boolean isConditional(int inst) {
1285            int cond = BitSpec.cond.getBits(inst);
1286            return cond != ConditionFlag.Always.value && cond != ConditionFlag.Never.value;
1287        }
1288    }
1289
1290    public static final class CBCond extends ControlTransferOp {
1291        private static final BitKey CBCOND_KEY = new BitKey(BitSpec.cbcond, 1);
1292
1293        private CBCond() {
1294            super(Ops.BranchOp, Op2s.Bpr, false, BitSpec.d10);
1295        }
1296
1297        @Override
1298        protected List<BitKey> getKeys() {
1299            List<BitKey> keys = super.getKeys();
1300            keys.add(CBCOND_KEY);
1301            return keys;
1302        }
1303
1304        public void emit(SPARCMacroAssembler masm, ConditionFlag cf, boolean cc2, Register rs1, Register rs2, Label lab) {
1305            int inst = setBits(0, cf, cc2, rs1);
1306            inst = BitSpec.rs2.setBits(inst, rs2.encoding);
1307            emit(masm, lab, inst);
1308        }
1309
1310        public void emit(SPARCMacroAssembler masm, ConditionFlag cf, boolean cc2, Register rs1, int simm5, Label lab) {
1311            int inst = setBits(0, cf, cc2, rs1);
1312            inst = BitSpec.simm5.setBits(inst, simm5);
1313            emit(masm, lab, inst);
1314        }
1315
1316        private void emit(SPARCMacroAssembler masm, Label lab, int baseInst) {
1317            int inst = baseInst;
1318            masm.insertNopAfterCBCond();
1319            masm.emitInt(setDisp(inst, masm, lab));
1320        }
1321
1322        private int setBits(int base, ConditionFlag cf, boolean cc2, Register rs1) {
1323            int inst = super.setBits(base);
1324            inst = BitSpec.rs1.setBits(inst, rs1.encoding);
1325            inst = BitSpec.cc2.setBits(inst, cc2 ? 1 : 0);
1326            inst = BitSpec.c.setBits(inst, cf.value);
1327            return BitSpec.cbcond.setBits(inst, 1);
1328        }
1329
1330        @Override
1331        public boolean isAnnulable(int inst) {
1332            return false;
1333        }
1334
1335        @Override
1336        public boolean isConditional(int inst) {
1337            return true;
1338        }
1339    }
1340
1341    public static class Op2Op extends SPARCOp {
1342        private final Op2s op2;
1343        private final BitKey op2Key;
1344
1345        public Op2Op(Ops op, Op2s op2) {
1346            super(op);
1347            this.op2 = op2;
1348            op2Key = new BitKey(BitSpec.op2, op2.value);
1349        }
1350
1351        @Override
1352        protected int setBits(int word) {
1353            int result = super.setBits(word);
1354            return BitSpec.op2.setBits(result, op2.value);
1355        }
1356
1357        @Override
1358        protected List<BitKey> getKeys() {
1359            List<BitKey> keys = super.getKeys();
1360            keys.add(op2Key);
1361            return keys;
1362        }
1363    }
1364
1365    public static class Sethi extends Op2Op {
1366        public Sethi() {
1367            super(Ops.BranchOp, Op2s.Sethi);
1368        }
1369
1370        public Register getRS1(int word) {
1371            int regNum = BitSpec.rs1.getBits(word);
1372            return SPARC.cpuRegisters[regNum];
1373        }
1374
1375        public int getImm22(int word) {
1376            return BitSpec.imm22.getBits(word);
1377        }
1378
1379        public boolean isNop(int inst) {
1380            return getRS1(inst).equals(g0) && getImm22(inst) == 0;
1381        }
1382    }
1383
1384    public static class Op3Op extends SPARCOp {
1385        public Op3Op() {
1386            super(ArithOp);
1387        }
1388
1389        public Op3s getOp3(int inst) {
1390            assert match(inst);
1391            return OP3S[ArithOp.value & 1][BitSpec.op3.getBits(inst)];
1392        }
1393    }
1394
1395    public boolean hasFeature(CPUFeature feature) {
1396        return ((SPARC) this.target.arch).features.contains(feature);
1397    }
1398
1399    public static final int simm(int x, int nbits) {
1400        // assert_signed_range(x, nbits);
1401        return x & ((1 << nbits) - 1);
1402    }
1403
1404    public static final boolean isImm(int x, int nbits) {
1405        // assert_signed_range(x, nbits);
1406        return simm(x, nbits) == x;
1407    }
1408
1409    /**
1410     * Minimum value for signed immediate ranges.
1411     */
1412    public static long minSimm(long nbits) {
1413        return -(1L << (nbits - 1));
1414    }
1415
1416    /**
1417     * Maximum value for signed immediate ranges.
1418     */
1419    public static long maxSimm(long nbits) {
1420        return (1L << (nbits - 1)) - 1;
1421    }
1422
1423    /**
1424     * Test if imm is within signed immediate range for nbits.
1425     */
1426    public static boolean isSimm(long imm, int nbits) {
1427        return minSimm(nbits) <= imm && imm <= maxSimm(nbits);
1428    }
1429
1430    public static boolean isSimm10(long imm) {
1431        return isSimm(imm, 10);
1432    }
1433
1434    public static boolean isSimm11(long imm) {
1435        return isSimm(imm, 11);
1436    }
1437
1438    public static boolean isSimm11(JavaConstant constant) {
1439        return constant.isNull() || isSimm11(constant.asLong());
1440    }
1441
1442    public static boolean isSimm5(JavaConstant constant) {
1443        return constant.isNull() || isSimm(constant.asLong(), 5);
1444    }
1445
1446    public static boolean isSimm13(int imm) {
1447        return isSimm(imm, 13);
1448    }
1449
1450    public static boolean isSimm13(JavaConstant constant) {
1451        long bits;
1452        switch (constant.getKind()) {
1453            case Double:
1454                bits = Double.doubleToRawLongBits(constant.asDouble());
1455                break;
1456            case Float:
1457                bits = Float.floatToRawIntBits(constant.asFloat());
1458                break;
1459            case Object:
1460                return JavaConstant.NULL_POINTER.equals(constant);
1461            default:
1462                bits = constant.asLong();
1463                break;
1464        }
1465        return constant.isNull() || isSimm13(bits);
1466    }
1467
1468    public static boolean isSimm13(long imm) {
1469        return NumUtil.isInt(imm) && isSimm(imm, 13);
1470    }
1471
1472    public static boolean isWordDisp30(long imm) {
1473        return isSimm(imm, 30 + 2);
1474    }
1475
1476    public static final int hi22(int x) {
1477        return x >>> 10;
1478    }
1479
1480    public static final int lo10(int x) {
1481        return x & ((1 << 10) - 1);
1482    }
1483
1484    // @formatter:off
1485    /**
1486     * Instruction format for Fmt00 instructions. This abstraction is needed as it
1487     * makes the patching easier later on.
1488     * <pre>
1489     * | 00  |    a   | op2 |               b                         |
1490     * |31 30|29    25|24 22|21                                      0|
1491     * </pre>
1492     */
1493    // @formatter:on
1494    protected void fmt00(int a, int op2, int b) {
1495        assert isImm(a, 5) && isImm(op2, 3) && isImm(b, 22) : String.format("a: 0x%x op2: 0x%x b: 0x%x", a, op2, b);
1496        int word = 0;
1497        BitSpec.op.setBits(word, 0);
1498        BitSpec.rd.setBits(word, a);
1499        BitSpec.op2.setBits(word, op2);
1500        BitSpec.imm22.setBits(word, b);
1501        emitInt(a << 25 | op2 << 22 | b);
1502    }
1503
1504    private void op3(Op3s op3, Opfs opf, Register rs1, Register rs2, Register rd) {
1505        int b = opf.value << 5 | (rs2 == null ? 0 : rs2.encoding);
1506        fmt(op3.op.value, rd.encoding, op3.value, rs1 == null ? 0 : rs1.encoding, b);
1507    }
1508
1509    protected void op3(Op3s op3, Register rs1, Register rs2, Register rd) {
1510        int b = rs2 == null ? 0 : rs2.encoding;
1511        int xBit = getXBit(op3);
1512        fmt(op3.op.value, rd.encoding, op3.value, rs1 == null ? 0 : rs1.encoding, b | xBit);
1513    }
1514
1515    protected void op3(Op3s op3, Register rs1, int simm13, Register rd) {
1516        assert isSimm13(simm13);
1517        int i = 1 << 13;
1518        int simm13WithX = simm13 | getXBit(op3);
1519        fmt(op3.op.value, rd.encoding, op3.value, rs1.encoding, i | simm13WithX & ((1 << 13) - 1));
1520    }
1521
1522    // @formatter:off
1523    /**
1524     * Branch on Integer Condition Codes.
1525     * <pre>
1526     * | 00  |annul| cond| 010 |               disp22                 |
1527     * |31 30|29   |28 25|24 22|21                                   0|
1528     * </pre>
1529     */
1530    // @formatter:on
1531    public void bicc(ConditionFlag cond, Annul annul, Label l) {
1532        bcc(Op2s.Br, cond, annul, l);
1533    }
1534
1535    // @formatter:off
1536    /**
1537     * Branch on Floating-Point Condition Codes.
1538     * <pre>
1539     * | 00  |annul| cond| 110 |               disp22                 |
1540     * |31 30|29   |28 25|24 22|21                                   0|
1541     * </pre>
1542     */
1543    // @formatter:on
1544    public void fbcc(ConditionFlag cond, Annul annul, Label l) {
1545        bcc(Op2s.Fb, cond, annul, l);
1546    }
1547
1548    // @formatter:off
1549    /**
1550     * Branch on (Integer|Floatingpoint) Condition Codes.
1551     * <pre>
1552     * | 00  |annul| cond| op2 |               disp22                 |
1553     * |31 30|29   |28 25|24 22|21                                   0|
1554     * </pre>
1555     */
1556    // @formatter:on
1557    private void bcc(Op2s op2, ConditionFlag cond, Annul annul, Label l) {
1558        insertNopAfterCBCond();
1559        int pos = !l.isBound() ? patchUnbound(l) : (l.position() - position()) / 4;
1560        final int disp = 22;
1561        assert isSimm(pos, disp);
1562        pos &= (1 << disp) - 1;
1563        int a = (annul.flag << 4) | cond.getValue();
1564        fmt00(a, op2.getValue(), pos);
1565    }
1566
1567    public void insertNopAfterCBCond() {
1568        int pos = position() - INSTRUCTION_SIZE;
1569        if (pos == 0) {
1570            return;
1571        }
1572        int inst = getInt(pos);
1573        if (isCBCond(inst)) {
1574            nop();
1575        }
1576    }
1577
1578    protected static boolean isCBCond(int inst) {
1579        return isOp2(Ops.BranchOp, Op2s.Bpr, inst) && getBits(inst, 28, 28) == 1;
1580    }
1581
1582    private static boolean isOp2(Ops ops, Op2s op2s, int inst) {
1583        return getOp(inst).equals(ops) && getOp2(inst).equals(op2s);
1584    }
1585
1586    private static Ops getOp(int inst) {
1587        return OPS[getBits(inst, 31, 30)];
1588    }
1589
1590    private static Op2s getOp2(int inst) {
1591        return OP2S[getBits(inst, 24, 22)];
1592    }
1593
1594    public static int getBits(int inst, int hiBit, int lowBit) {
1595        return (inst >> lowBit) & ((1 << (hiBit - lowBit + 1)) - 1);
1596    }
1597
1598    // @formatter:off
1599    /**
1600     * Branch on Integer Condition Codes with Prediction.
1601     * <pre>
1602     * | 00  |an|cond | 001 |cc1 2|p |           disp19               |
1603     * |31 30|29|28 25|24 22|21 20|19|                               0|
1604     * </pre>
1605     */
1606    // @formatter:on
1607    public void bpcc(ConditionFlag cond, Annul annul, Label l, CC cc, BranchPredict predictTaken) {
1608        bpcc(Op2s.Bp, cond, annul, l, cc, predictTaken);
1609    }
1610
1611    // @formatter:off
1612    /**
1613     * Branch on Integer Condition Codes with Prediction.
1614     * <pre>
1615     * | 00  |an|cond | 101 |cc1 2|p |           disp19               |
1616     * |31 30|29|28 25|24 22|21 20|19|                               0|
1617     * </pre>
1618     */
1619    // @formatter:on
1620    public void fbpcc(ConditionFlag cond, Annul annul, Label l, CC cc, BranchPredict predictTaken) {
1621        bpcc(Op2s.Fbp, cond, annul, l, cc, predictTaken);
1622    }
1623
1624    // @formatter:off
1625    /**
1626     * Used for fbpcc (Float) and bpcc (Integer).
1627     * <pre>
1628     * | 00  |an|cond | op2 |cc1 2|p |           disp19               |
1629     * |31 30|29|28 25|24 22|21 20|19|                               0|
1630     * </pre>
1631     */
1632    // @formatter:on
1633    private void bpcc(Op2s op2, ConditionFlag cond, Annul annul, Label l, CC cc, BranchPredict predictTaken) {
1634        insertNopAfterCBCond();
1635        int pos = !l.isBound() ? patchUnbound(l) : (l.position() - position()) / 4;
1636        final int disp = 19;
1637        assert isSimm(pos, disp);
1638        pos &= (1 << disp) - 1;
1639        int a = (annul.flag << 4) | cond.getValue();
1640        int b = (cc.getValue() << 20) | ((predictTaken.flag) << 19) | pos;
1641        delaySlotOptimizationPoints.add(position());
1642        fmt00(a, op2.getValue(), b);
1643    }
1644
1645    // @formatter:off
1646    /**
1647     * Branch on Integer Register with Prediction.
1648     * <pre>
1649     * | 00  |an| 0|rcond | 011 |d16hi|p | rs1 |    d16lo             |
1650     * |31 30|29|28|27 25 |24 22|21 20|19|18 14|                     0|
1651     * </pre>
1652     */
1653    // @formatter:on
1654    public void bpr(RCondition cond, Annul annul, Label l, BranchPredict predictTaken, Register rs1) {
1655        insertNopAfterCBCond();
1656        int pos = !l.isBound() ? patchUnbound(l) : (l.position() - position()) / 4;
1657        final int disp = 16;
1658        assert isSimm(pos, disp);
1659        pos &= (1 << disp) - 1;
1660        int a = (annul.flag << 4) | cond.getValue();
1661        int d16hi = (pos >> 13) << 13;
1662        int d16lo = d16hi ^ pos;
1663        int b = (d16hi << 20) | (predictTaken.flag << 19) | (rs1.encoding() << 14) | d16lo;
1664        delaySlotOptimizationPoints.add(position());
1665        fmt00(a, Op2s.Bpr.getValue(), b);
1666    }
1667
1668    protected int patchUnbound(Label label) {
1669        label.addPatchAt(position());
1670        return 0;
1671    }
1672
1673    public void cbcondw(ConditionFlag cf, Register rs1, Register rs2, Label lab) {
1674        cbcond(0, 0, cf, rs1, rs2.encoding, lab);
1675    }
1676
1677    public void cbcondw(ConditionFlag cf, Register rs1, int rs2, Label lab) {
1678        assert isSimm(rs2, 5);
1679        cbcond(0, 1, cf, rs1, rs2 & ((1 << 5) - 1), lab);
1680    }
1681
1682    public void cbcondx(ConditionFlag cf, Register rs1, Register rs2, Label lab) {
1683        cbcond(1, 0, cf, rs1, rs2.encoding, lab);
1684    }
1685
1686    public void cbcondx(ConditionFlag cf, Register rs1, int rs2, Label lab) {
1687        assert isSimm(rs2, 5);
1688        cbcond(1, 1, cf, rs1, rs2 & ((1 << 5) - 1), lab);
1689    }
1690
1691    private void cbcond(int cc2, int i, ConditionFlag cf, Register rs1, int rs2, Label l) {
1692        insertNopAfterCBCond();
1693        int disp10 = !l.isBound() ? patchUnbound(l) : (l.position() - position()) / 4;
1694        assert isSimm(disp10, 10) && isImm(rs2, 5);
1695        disp10 &= (1 << 10) - 1;
1696        final int cLo = cf.value & 0b111;
1697        final int cHi = cf.value >> 3;
1698        final int d10Lo = disp10 & ((1 << 8) - 1);
1699        final int d10Hi = disp10 >> 8;
1700        int a = cHi << 4 | 0b1000 | cLo;
1701        int b = cc2 << 21 | d10Hi << D10HI_SHIFT | rs1.encoding << 14 | i << 13 | d10Lo << D10LO_SHIFT | rs2;
1702        fmt00(a, Op2s.Bpr.value, b);
1703    }
1704
1705    // @formatter:off
1706    /**
1707     * NOP.
1708     * <pre>
1709     * | 00  |00000| 100 |                0                    |
1710     * |31 30|29 25|24 22|21                                  0|
1711     * </pre>
1712     */
1713    // @formatter:on
1714    public void nop() {
1715        emitInt(1 << 24);
1716    }
1717
1718    public void sethi(int imm22, Register dst) {
1719        fmt00(dst.encoding, Op2s.Sethi.value, imm22);
1720    }
1721
1722    // @formatter:off
1723    /**
1724     * Instruction format for calls.
1725     * <pre>
1726     * | 01  |                      disp30                             |
1727     * |31 30|29                                                      0|
1728     * </pre>
1729     *
1730     * @return Position of the call instruction
1731     */
1732    // @formatter:on
1733    public int call(int disp30) {
1734        assert isImm(disp30, 30);
1735        insertNopAfterCBCond();
1736        int before = position();
1737        int instr = 1 << 30;
1738        instr |= disp30;
1739        emitInt(instr);
1740        return before;
1741    }
1742
1743    public void add(Register rs1, Register rs2, Register rd) {
1744        op3(Add, rs1, rs2, rd);
1745    }
1746
1747    public void add(Register rs1, int simm13, Register rd) {
1748        op3(Add, rs1, simm13, rd);
1749    }
1750
1751    public void addc(Register rs1, Register rs2, Register rd) {
1752        op3(Addc, rs1, rs2, rd);
1753    }
1754
1755    public void addc(Register rs1, int simm13, Register rd) {
1756        op3(Addc, rs1, simm13, rd);
1757    }
1758
1759    public void addcc(Register rs1, Register rs2, Register rd) {
1760        op3(Addcc, rs1, rs2, rd);
1761    }
1762
1763    public void addcc(Register rs1, int simm13, Register rd) {
1764        op3(Addcc, rs1, simm13, rd);
1765    }
1766
1767    public void and(Register rs1, Register rs2, Register rd) {
1768        op3(And, rs1, rs2, rd);
1769    }
1770
1771    public void and(Register rs1, int simm13, Register rd) {
1772        op3(And, rs1, simm13, rd);
1773    }
1774
1775    public void andcc(Register rs1, Register rs2, Register rd) {
1776        op3(Andcc, rs1, rs2, rd);
1777    }
1778
1779    public void andcc(Register rs1, int simm13, Register rd) {
1780        op3(Andcc, rs1, simm13, rd);
1781    }
1782
1783    public void andn(Register rs1, Register rs2, Register rd) {
1784        op3(Andn, rs1, rs2, rd);
1785    }
1786
1787    public void andn(Register rs1, int simm13, Register rd) {
1788        op3(Andn, rs1, simm13, rd);
1789    }
1790
1791    public void andncc(Register rs1, Register rs2, Register rd) {
1792        op3(Andncc, rs1, rs2, rd);
1793    }
1794
1795    public void andncc(Register rs1, int simm13, Register rd) {
1796        op3(Andncc, rs1, simm13, rd);
1797    }
1798
1799    public void movwtos(Register rs2, Register rd) {
1800        assert isSingleFloatRegister(rd) && isCPURegister(rs2) : String.format("%s %s", rs2, rd);
1801        op3(Impdep1, Movwtos, null, rs2, rd);
1802    }
1803
1804    public void umulxhi(Register rs1, Register rs2, Register rd) {
1805        op3(Impdep1, UMulxhi, rs1, rs2, rd);
1806    }
1807
1808    public void fdtos(Register rs2, Register rd) {
1809        assert isSingleFloatRegister(rd) && isDoubleFloatRegister(rs2) : String.format("%s %s", rs2, rd);
1810        op3(Fpop1, Fdtos, null, rs2, rd);
1811    }
1812
1813    public void movstouw(Register rs2, Register rd) {
1814        assert isSingleFloatRegister(rs2) && isCPURegister(rd) : String.format("%s %s", rs2, rd);
1815        op3(Impdep1, Movstosw, null, rs2, rd);
1816    }
1817
1818    public void movstosw(Register rs2, Register rd) {
1819        assert isSingleFloatRegister(rs2) && isCPURegister(rd) : String.format("%s %s", rs2, rd);
1820        op3(Impdep1, Movstosw, null, rs2, rd);
1821    }
1822
1823    public void movdtox(Register rs2, Register rd) {
1824        assert isDoubleFloatRegister(rs2) && isCPURegister(rd) : String.format("%s %s", rs2, rd);
1825        op3(Impdep1, Movdtox, null, rs2, rd);
1826    }
1827
1828    public void movxtod(Register rs2, Register rd) {
1829        assert isCPURegister(rs2) && isDoubleFloatRegister(rd) : String.format("%s %s", rs2, rd);
1830        op3(Impdep1, Movxtod, null, rs2, rd);
1831    }
1832
1833    public void fadds(Register rs1, Register rs2, Register rd) {
1834        op3(Fpop1, Fadds, rs1, rs2, rd);
1835    }
1836
1837    public void faddd(Register rs1, Register rs2, Register rd) {
1838        op3(Fpop1, Faddd, rs1, rs2, rd);
1839    }
1840
1841    public void faddq(Register rs1, Register rs2, Register rd) {
1842        op3(Fpop1, Faddq, rs1, rs2, rd);
1843    }
1844
1845    public void fdivs(Register rs1, Register rs2, Register rd) {
1846        op3(Fpop1, Fdivs, rs1, rs2, rd);
1847    }
1848
1849    public void fdivd(Register rs1, Register rs2, Register rd) {
1850        op3(Fpop1, Fdivd, rs1, rs2, rd);
1851    }
1852
1853    public void fmovs(Register rs2, Register rd) {
1854        op3(Fpop1, Fmovs, null, rs2, rd);
1855    }
1856
1857    public void fmovd(Register rs2, Register rd) {
1858        op3(Fpop1, Fmovd, null, rs2, rd);
1859    }
1860
1861    public void fsrc2s(Register rs2, Register rd) {
1862        op3(Impdep1, Fsrc2s, null, rs2, rd);
1863    }
1864
1865    public void fsrc2d(Register rs2, Register rd) {
1866        op3(Impdep1, Fsrc2d, null, rs2, rd);
1867    }
1868
1869    public void fmuls(Register rs1, Register rs2, Register rd) {
1870        op3(Fpop1, Fmuls, rs1, rs2, rd);
1871    }
1872
1873    public void fsmuld(Register rs1, Register rs2, Register rd) {
1874        op3(Fpop1, Fsmuld, rs1, rs2, rd);
1875    }
1876
1877    public void fmuld(Register rs1, Register rs2, Register rd) {
1878        op3(Fpop1, Fmuld, rs1, rs2, rd);
1879    }
1880
1881    public void fnegs(Register rs2, Register rd) {
1882        op3(Fpop1, Fnegs, null, rs2, rd);
1883    }
1884
1885    public void fnegd(Register rs2, Register rd) {
1886        op3(Fpop1, Fnegd, null, rs2, rd);
1887    }
1888
1889    /**
1890     * Helper method to determine if the instruction needs the X bit set.
1891     */
1892    private static int getXBit(Op3s op3) {
1893        switch (op3) {
1894            case Sllx:
1895            case Srax:
1896            case Srlx:
1897                return 1 << 12;
1898            default:
1899                return 0;
1900        }
1901    }
1902
1903    public void fstoi(Register rs2, Register rd) {
1904        op3(Fpop1, Fstoi, null, rs2, rd);
1905    }
1906
1907    public void fstox(Register rs2, Register rd) {
1908        op3(Fpop1, Fstox, null, rs2, rd);
1909    }
1910
1911    public void fdtox(Register rs2, Register rd) {
1912        op3(Fpop1, Fdtox, null, rs2, rd);
1913    }
1914
1915    public void fstod(Register rs2, Register rd) {
1916        op3(Fpop1, Fstod, null, rs2, rd);
1917    }
1918
1919    public void fdtoi(Register rs2, Register rd) {
1920        op3(Fpop1, Fdtoi, null, rs2, rd);
1921    }
1922
1923    public void fitos(Register rs2, Register rd) {
1924        op3(Fpop1, Fitos, null, rs2, rd);
1925    }
1926
1927    public void fitod(Register rs2, Register rd) {
1928        op3(Fpop1, Fitod, null, rs2, rd);
1929    }
1930
1931    public void fxtos(Register rs2, Register rd) {
1932        op3(Fpop1, Fxtos, null, rs2, rd);
1933    }
1934
1935    public void fxtod(Register rs2, Register rd) {
1936        op3(Fpop1, Fxtod, null, rs2, rd);
1937    }
1938
1939    public void fzeros(Register rd) {
1940        op3(Impdep1, Fzeros, null, null, rd);
1941    }
1942
1943    public void fzerod(Register rd) {
1944        op3(Impdep1, Fzerod, null, null, rd);
1945    }
1946
1947    public void flushw() {
1948        op3(Flushw, g0, g0, g0);
1949    }
1950
1951    public void fsqrtd(Register rs2, Register rd) {
1952        op3(Fpop1, Fsqrtd, null, rs2, rd);
1953    }
1954
1955    public void fsqrts(Register rs2, Register rd) {
1956        op3(Fpop1, Fsqrts, null, rs2, rd);
1957    }
1958
1959    public void fabss(Register rs2, Register rd) {
1960        op3(Fpop1, Fabss, null, rs2, rd);
1961    }
1962
1963    public void fabsd(Register rs2, Register rd) {
1964        op3(Fpop1, Fabsd, null, rs2, rd);
1965    }
1966
1967    public void fsubs(Register rs1, Register rs2, Register rd) {
1968        op3(Fpop1, Fsubs, rs1, rs2, rd);
1969    }
1970
1971    public void fsubd(Register rs1, Register rs2, Register rd) {
1972        op3(Fpop1, Fsubd, rs1, rs2, rd);
1973    }
1974
1975    // @formatter:off
1976    /**
1977     * Instruction format for fcmp.
1978     * <pre>
1979     * | 10  | --- |cc1|cc0|desc |   rs1   |   opf  | rs2 |
1980     * |31 30|29 27|26 |25 |24 19|18     14|13     5|4   0|
1981     * </pre>
1982     */
1983    // @formatter:on
1984    public void fcmp(CC cc, Opfs opf, Register rs1, Register rs2) {
1985        int a = cc.value;
1986        int b = opf.value << 5 | rs2.encoding;
1987        delaySlotOptimizationPoints.add(position());
1988        fmt10(a, Fcmp.value, rs1.encoding, b);
1989    }
1990
1991    // @formatter:off
1992    /**
1993     * Instruction format for most arithmetic stuff.
1994     * <pre>
1995     * |  10 | rd  | op3 | rs1 |   b   |
1996     * |31 30|29 25|24 19|18 14|13    0|
1997     * </pre>
1998     */
1999    // @formatter:on
2000    protected void fmt10(int rd, int op3, int rs1, int b) {
2001        fmt(0b10, rd, op3, rs1, b);
2002    }
2003
2004    // @formatter:off
2005    /**
2006     * Instruction format for most arithmetic stuff.
2007     * <pre>
2008     * |  op | rd  | op3 | rs1 |   b   |
2009     * |31 30|29 25|24 19|18 14|13    0|
2010     * </pre>
2011     */
2012    // @formatter:on
2013    protected void fmt(int op, int rd, int op3, int rs1, int b) {
2014        assert isImm(rd, 5) && isImm(op3, 6) && isImm(b, 14) : String.format("rd: 0x%x op3: 0x%x b: 0x%x", rd, op3, b);
2015        int instr = op << 30 | rd << 25 | op3 << 19 | rs1 << 14 | b;
2016        emitInt(instr);
2017    }
2018
2019    public void illtrap(int const22) {
2020        fmt00(0, Op2s.Illtrap.value, const22);
2021    }
2022
2023    public void jmpl(Register rs1, Register rs2, Register rd) {
2024        insertNopAfterCBCond();
2025        op3(Jmpl, rs1, rs2, rd);
2026    }
2027
2028    /**
2029     * @return Position of the jmpl instruction
2030     */
2031    public int jmpl(Register rs1, int simm13, Register rd) {
2032        insertNopAfterCBCond();
2033        int before = position();
2034        op3(Jmpl, rs1, simm13, rd);
2035        return before;
2036    }
2037
2038    public void fmovdcc(ConditionFlag cond, CC cc, Register rs2, Register rd) {
2039        fmovcc(cond, cc, rs2, rd, Fmovdcc.value);
2040    }
2041
2042    public void fmovscc(ConditionFlag cond, CC cc, Register rs2, Register rd) {
2043        fmovcc(cond, cc, rs2, rd, Fmovscc.value);
2044    }
2045
2046    private void fmovcc(ConditionFlag cond, CC cc, Register rs2, Register rd, int opfLow) {
2047        int opfCC = cc.value;
2048        int a = opfCC << 11 | opfLow << 5 | rs2.encoding;
2049        fmt10(rd.encoding, Fpop2.value, cond.value, a);
2050    }
2051
2052    public void movcc(ConditionFlag conditionFlag, CC cc, Register rs2, Register rd) {
2053        movcc(conditionFlag, cc, 0, rs2.encoding, rd);
2054    }
2055
2056    public void movcc(ConditionFlag conditionFlag, CC cc, int simm11, Register rd) {
2057        assert isSimm11(simm11);
2058        movcc(conditionFlag, cc, 1, simm11 & ((1 << 11) - 1), rd);
2059    }
2060
2061    private void movcc(ConditionFlag conditionFlag, CC cc, int i, int imm, Register rd) {
2062        int cc01 = 0b11 & cc.value;
2063        int cc2 = cc.isFloat ? 0 : 1;
2064        int a = cc2 << 4 | conditionFlag.value;
2065        int b = cc01 << 11 | i << 13 | imm;
2066        fmt10(rd.encoding, Movcc.value, a, b);
2067    }
2068
2069    public void mulx(Register rs1, Register rs2, Register rd) {
2070        op3(Mulx, rs1, rs2, rd);
2071    }
2072
2073    public void mulx(Register rs1, int simm13, Register rd) {
2074        op3(Mulx, rs1, simm13, rd);
2075    }
2076
2077    public void or(Register rs1, Register rs2, Register rd) {
2078        assert isCPURegister(rs1, rs2, rd) : String.format("%s %s %s", rs1, rs2, rd);
2079        op3(Or, rs1, rs2, rd);
2080    }
2081
2082    public void or(Register rs1, int simm13, Register rd) {
2083        assert isCPURegister(rs1, rd) : String.format("%s %s", rs1, rd);
2084        op3(Or, rs1, simm13, rd);
2085    }
2086
2087    public void popc(Register rs2, Register rd) {
2088        op3(Popc, g0, rs2, rd);
2089    }
2090
2091    public void popc(int simm13, Register rd) {
2092        op3(Popc, g0, simm13, rd);
2093    }
2094
2095    public void prefetch(SPARCAddress addr, Fcn fcn) {
2096        Register rs1 = addr.getBase();
2097        if (addr.getIndex().equals(Register.None)) {
2098            int dis = addr.getDisplacement();
2099            assert isSimm13(dis);
2100            fmt(Prefetch.op.value, fcn.value, Prefetch.value, rs1.encoding, 1 << 13 | dis & ((1 << 13) - 1));
2101        } else {
2102            Register rs2 = addr.getIndex();
2103            fmt(Prefetch.op.value, fcn.value, Prefetch.value, rs1.encoding, rs2.encoding);
2104        }
2105    }
2106
2107    // A.44 Read State Register
2108
2109    public void rdpc(Register rd) {
2110        op3(Rd, r5, g0, rd);
2111    }
2112
2113    public void restore(Register rs1, Register rs2, Register rd) {
2114        op3(Restore, rs1, rs2, rd);
2115    }
2116
2117    public static final int PC_RETURN_OFFSET = 8;
2118
2119    public void save(Register rs1, Register rs2, Register rd) {
2120        op3(Save, rs1, rs2, rd);
2121    }
2122
2123    public void save(Register rs1, int simm13, Register rd) {
2124        op3(Save, rs1, simm13, rd);
2125    }
2126
2127    public void sdivx(Register rs1, Register rs2, Register rd) {
2128        op3(Sdivx, rs1, rs2, rd);
2129    }
2130
2131    public void sdivx(Register rs1, int simm13, Register rd) {
2132        op3(Sdivx, rs1, simm13, rd);
2133    }
2134
2135    public void udivx(Register rs1, Register rs2, Register rd) {
2136        op3(Udivx, rs1, rs2, rd);
2137    }
2138
2139    public void udivx(Register rs1, int simm13, Register rd) {
2140        op3(Udivx, rs1, simm13, rd);
2141    }
2142
2143    public void sll(Register rs1, Register rs2, Register rd) {
2144        op3(Sll, rs1, rs2, rd);
2145    }
2146
2147    public void sll(Register rs1, int shcnt32, Register rd) {
2148        assert isImm(shcnt32, 5);
2149        op3(Sll, rs1, shcnt32, rd);
2150    }
2151
2152    public void sllx(Register rs1, Register rs2, Register rd) {
2153        op3(Sllx, rs1, rs2, rd);
2154    }
2155
2156    public void sllx(Register rs1, int shcnt64, Register rd) {
2157        assert isImm(shcnt64, 6);
2158        op3(Sllx, rs1, shcnt64, rd);
2159    }
2160
2161    public void sra(Register rs1, Register rs2, Register rd) {
2162        op3(Sra, rs1, rs2, rd);
2163    }
2164
2165    public void sra(Register rs1, int simm13, Register rd) {
2166        op3(Sra, rs1, simm13, rd);
2167    }
2168
2169    public void srax(Register rs1, Register rs2, Register rd) {
2170        op3(Srax, rs1, rs2, rd);
2171    }
2172
2173    public void srax(Register rs1, int shcnt64, Register rd) {
2174        assert isImm(shcnt64, 6);
2175        op3(Srax, rs1, shcnt64, rd);
2176    }
2177
2178    public void srl(Register rs1, Register rs2, Register rd) {
2179        op3(Srl, rs1, rs2, rd);
2180    }
2181
2182    public void srl(Register rs1, int simm13, Register rd) {
2183        op3(Srl, rs1, simm13, rd);
2184    }
2185
2186    public void srlx(Register rs1, Register rs2, Register rd) {
2187        op3(Srlx, rs1, rs2, rd);
2188    }
2189
2190    public void srlx(Register rs1, int shcnt64, Register rd) {
2191        assert isImm(shcnt64, 6);
2192        op3(Srlx, rs1, shcnt64, rd);
2193    }
2194
2195    public void fandd(Register rs1, Register rs2, Register rd) {
2196        op3(Impdep1, Fandd, rs1, rs2, rd);
2197    }
2198
2199    public void sub(Register rs1, Register rs2, Register rd) {
2200        op3(Sub, rs1, rs2, rd);
2201    }
2202
2203    public void sub(Register rs1, int simm13, Register rd) {
2204        op3(Sub, rs1, simm13, rd);
2205    }
2206
2207    public void subcc(Register rs1, Register rs2, Register rd) {
2208        op3(Subcc, rs1, rs2, rd);
2209    }
2210
2211    public void subcc(Register rs1, int simm13, Register rd) {
2212        op3(Subcc, rs1, simm13, rd);
2213    }
2214
2215    public void ta(int trap) {
2216        tcc(Icc, Always, trap);
2217    }
2218
2219    public void tcc(CC cc, ConditionFlag flag, int trap) {
2220        assert isImm(trap, 8);
2221        int b = cc.value << 11;
2222        b |= 1 << 13;
2223        b |= trap;
2224        fmt10(flag.value, Op3s.Tcc.getValue(), 0, b);
2225    }
2226
2227    public void wrccr(Register rs1, Register rs2) {
2228        op3(Wr, rs1, rs2, r2);
2229    }
2230
2231    public void wrccr(Register rs1, int simm13) {
2232        op3(Wr, rs1, simm13, r2);
2233    }
2234
2235    public void xor(Register rs1, Register rs2, Register rd) {
2236        op3(Xor, rs1, rs2, rd);
2237    }
2238
2239    public void xor(Register rs1, int simm13, Register rd) {
2240        op3(Xor, rs1, simm13, rd);
2241    }
2242
2243    public void xorcc(Register rs1, Register rs2, Register rd) {
2244        op3(Xorcc, rs1, rs2, rd);
2245    }
2246
2247    public void xorcc(Register rs1, int simm13, Register rd) {
2248        op3(Xorcc, rs1, simm13, rd);
2249    }
2250
2251    public void xnor(Register rs1, Register rs2, Register rd) {
2252        op3(Xnor, rs1, rs2, rd);
2253    }
2254
2255    public void xnor(Register rs1, int simm13, Register rd) {
2256        op3(Xnor, rs1, simm13, rd);
2257    }
2258
2259    /*
2260     * Load/Store
2261     */
2262    protected void ld(Op3s op3, SPARCAddress addr, Register rd, Asi asi) {
2263        Register rs1 = addr.getBase();
2264        if (!addr.getIndex().equals(Register.None)) {
2265            Register rs2 = addr.getIndex();
2266            if (asi != null) {
2267                int b = rs2.encoding;
2268                b |= asi.value << 5;
2269                fmt(op3.op.value, rd.encoding, op3.value, rs1.encoding, b);
2270            } else {
2271                op3(op3, rs1, rs2, rd);
2272            }
2273        } else {
2274            int imm = addr.getDisplacement();
2275            op3(op3, rs1, imm, rd);
2276        }
2277    }
2278
2279    protected void ld(Op3s op3, SPARCAddress addr, Register rd) {
2280        ld(op3, addr, rd, null);
2281    }
2282
2283    public void lddf(SPARCAddress src, Register dst) {
2284        assert isDoubleFloatRegister(dst) : dst;
2285        ld(Lddf, src, dst);
2286    }
2287
2288    public void ldf(SPARCAddress src, Register dst) {
2289        assert isSingleFloatRegister(dst) : dst;
2290        ld(Ldf, src, dst);
2291    }
2292
2293    public void lduh(SPARCAddress src, Register dst) {
2294        assert isCPURegister(dst) : dst;
2295        ld(Lduh, src, dst);
2296    }
2297
2298    public void ldsh(SPARCAddress src, Register dst) {
2299        assert isCPURegister(dst) : dst;
2300        ld(Ldsh, src, dst);
2301    }
2302
2303    public void ld(SPARCAddress src, Register dst, int bytes, boolean signed) {
2304        if (signed) {
2305            switch (bytes) {
2306                case 1:
2307                    ldub(src, dst);
2308                    break;
2309                case 2:
2310                    lduh(src, dst);
2311                    break;
2312                case 4:
2313                    lduw(src, dst);
2314                    break;
2315                case 8:
2316                    ldx(src, dst);
2317                    break;
2318                default:
2319                    throw new InternalError();
2320            }
2321        } else {
2322            switch (bytes) {
2323                case 1:
2324                    ldsb(src, dst);
2325                    break;
2326                case 2:
2327                    ldsh(src, dst);
2328                    break;
2329                case 4:
2330                    ldsw(src, dst);
2331                    break;
2332                case 8:
2333                    ldx(src, dst);
2334                    break;
2335                default:
2336                    throw new InternalError();
2337            }
2338        }
2339    }
2340
2341    public void ldub(SPARCAddress src, Register dst) {
2342        assert isCPURegister(dst) : dst;
2343        ld(Ldub, src, dst);
2344    }
2345
2346    public void ldsb(SPARCAddress src, Register dst) {
2347        assert isCPURegister(dst) : dst;
2348        ld(Ldsb, src, dst);
2349    }
2350
2351    public void lduw(SPARCAddress src, Register dst) {
2352        assert isCPURegister(dst) : dst;
2353        ld(Lduw, src, dst);
2354    }
2355
2356    public void ldsw(SPARCAddress src, Register dst) {
2357        assert isCPURegister(dst) : dst;
2358        ld(Ldsw, src, dst);
2359    }
2360
2361    public void ldx(SPARCAddress src, Register dst) {
2362        assert isCPURegister(dst) : dst;
2363        ld(Ldx, src, dst);
2364    }
2365
2366    public void ldxa(Register rs1, Register rs2, Register rd, Asi asi) {
2367        assert SPARC.isCPURegister(rs1, rs2, rd) : format("%s %s %s", rs1, rs2, rd);
2368        ld(Ldxa, new SPARCAddress(rs1, rs2), rd, asi);
2369    }
2370
2371    public void lduwa(Register rs1, Register rs2, Register rd, Asi asi) {
2372        assert SPARC.isCPURegister(rs1, rs2, rd) : format("%s %s %s", rs1, rs2, rd);
2373        ld(Lduwa, new SPARCAddress(rs1, rs2), rd, asi);
2374    }
2375
2376    protected void st(Op3s op3, Register rs1, SPARCAddress dest) {
2377        ld(op3, dest, rs1);
2378    }
2379
2380    public void stdf(Register rd, SPARCAddress addr) {
2381        assert isDoubleFloatRegister(rd) : rd;
2382        st(Stdf, rd, addr);
2383    }
2384
2385    public void stf(Register rd, SPARCAddress addr) {
2386        assert isSingleFloatRegister(rd) : rd;
2387        st(Stf, rd, addr);
2388    }
2389
2390    public void stb(Register rd, SPARCAddress addr) {
2391        assert isCPURegister(rd) : rd;
2392        st(Stb, rd, addr);
2393    }
2394
2395    public void sth(Register rd, SPARCAddress addr) {
2396        assert isCPURegister(rd) : rd;
2397        st(Sth, rd, addr);
2398    }
2399
2400    public void stw(Register rd, SPARCAddress addr) {
2401        assert isCPURegister(rd) : rd;
2402        st(Stw, rd, addr);
2403    }
2404
2405    public void stx(Register rd, SPARCAddress addr) {
2406        assert isCPURegister(rd) : rd;
2407        st(Stx, rd, addr);
2408    }
2409
2410    public void membar(int barriers) {
2411        op3(Membar, r15, barriers, g0);
2412    }
2413
2414    public void casa(Register rs1, Register rs2, Register rd, Asi asi) {
2415        ld(Casa, new SPARCAddress(rs1, rs2), rd, asi);
2416    }
2417
2418    public void casxa(Register rs1, Register rs2, Register rd, Asi asi) {
2419        ld(Casxa, new SPARCAddress(rs1, rs2), rd, asi);
2420    }
2421
2422    @Override
2423    public InstructionCounter getInstructionCounter() {
2424        return new SPARCInstructionCounter(this);
2425    }
2426
2427    public void patchAddImmediate(int position, int simm13) {
2428        int inst = getInt(position);
2429        assert SPARCAssembler.isSimm13(simm13) : simm13;
2430        assert (inst >>> 30) == 0b10 : String.format("0x%x", inst);
2431        assert ((inst >>> 18) & 0b11_1111) == 0 : String.format("0x%x", inst);
2432        assert (inst & (1 << 13)) != 0 : String.format("0x%x", inst);
2433        inst = inst & (~((1 << 13) - 1));
2434        inst |= simm13 & ((1 << 12) - 1);
2435        emitInt(inst, position);
2436    }
2437
2438    public void fpadd32(Register rs1, Register rs2, Register rd) {
2439        op3(Impdep1, Fpadd32, rs1, rs2, rd);
2440    }
2441
2442    /**
2443     * Does peephole optimization on code generated by this assembler. This method should be called
2444     * at the end of code generation.
2445     * <p>
2446     * It searches for conditional branch instructions which has nop in the delay slot then looks at
2447     * the instruction at branch target; if it is an arithmetic instruction, which does not throw an
2448     * exception (e.g. division), it pulls this instruction into the delay slot and increments the
2449     * displacement by 1.
2450     */
2451    public void peephole() {
2452        for (int i : delaySlotOptimizationPoints) {
2453            optimizeDelaySlot(i);
2454        }
2455    }
2456
2457    /**
2458     * Optimizes branch instruction <i>b</t> which has a nop in the delay slot. It tries to stuff
2459     * the instruction at <i>b</i>s branch target into the delay slot of <i>b</i>, set the annul
2460     * flag and increments <i>b</i>s disp field by 1;
2461     * <p>
2462     * If <i>b</i>s branch target instruction is an unconditional branch <i>t</i>, then it tries to
2463     * put <i>t</i>s delayed instruction into the delay slot of <i>b</i> and add the <i>t</i>s disp
2464     * field to <i>b</i>s disp field.
2465     */
2466    private void optimizeDelaySlot(int i) {
2467        int delaySlotAbsolute = i + INSTRUCTION_SIZE;
2468        int nextInst = getInt(delaySlotAbsolute);
2469        SPARCOp nextOp = getSPARCOp(nextInst);
2470        if (nextOp instanceof Sethi && ((Sethi) nextOp).isNop(nextInst)) {
2471            int inst = getInt(i);
2472            SPARCOp op = getSPARCOp(inst);
2473            if (op instanceof ControlTransferOp && ((ControlTransferOp) op).hasDelaySlot() && ((ControlTransferOp) op).isAnnulable(inst)) {
2474                ControlTransferOp ctOp = (ControlTransferOp) op;
2475                int disp = ctOp.getDisp(inst);
2476                int branchTargetAbsolute = i + disp * INSTRUCTION_SIZE;
2477                int branchTargetInst = getInt(branchTargetAbsolute);
2478                SPARCOp branchTargetOp = getSPARCOp(branchTargetInst);
2479                if (branchTargetOp instanceof Op3Op) {
2480                    Op3s op3 = ((Op3Op) branchTargetOp).getOp3(branchTargetInst);
2481                    if (!op3.throwsException()) {
2482                        inst = ctOp.setDisp(inst, disp + 1); // Increment the offset
2483                        inst = ctOp.setAnnul(inst, true);
2484                        emitInt(inst, i);
2485                        emitInt(branchTargetInst, delaySlotAbsolute);
2486                    }
2487                } else if (branchTargetOp instanceof ControlTransferOp && !((ControlTransferOp) branchTargetOp).isConditional(branchTargetInst)) {
2488                    // If branchtarget is a unconditional branch
2489                    ControlTransferOp branchTargetOpBranch = (ControlTransferOp) branchTargetOp;
2490                    int btDisp = branchTargetOpBranch.getDisp(branchTargetInst);
2491                    int newDisp = disp + btDisp;
2492                    if (ctOp.isValidDisp(newDisp)) { // Test if we don't exceed field size
2493                        int instAfter = ctOp.setDisp(inst, newDisp);
2494                        instAfter = ctOp.setAnnul(instAfter, true);
2495                        branchTargetInst = getInt(branchTargetAbsolute + INSTRUCTION_SIZE);
2496                        branchTargetOp = getSPARCOp(branchTargetInst);
2497                        if (branchTargetOp instanceof Op3Op && !((Op3Op) branchTargetOp).getOp3(branchTargetInst).throwsException()) {
2498                            emitInt(instAfter, i);
2499                            emitInt(branchTargetInst, delaySlotAbsolute);
2500                        }
2501                    }
2502                }
2503            }
2504        }
2505    }
2506}