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