1 /*
   2  * Copyright (c) 2009, 2019, 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         public final int flag;
 551 
 552         Annul(int flag) {
 553             this.flag = flag;
 554         }
 555     }
 556 
 557     public enum BranchPredict {
 558         PREDICT_TAKEN(1),
 559         PREDICT_NOT_TAKEN(0);
 560         public final int flag;
 561 
 562         BranchPredict(int flag) {
 563             this.flag = flag;
 564         }
 565     }
 566 
 567     public enum MembarMask {
 568         // @formatter:off
 569 
 570         StoreStore(1 << 3, "storestore"),
 571         LoadStore(1 << 2, "loadstore"),
 572         StoreLoad(1 << 1, "storeload"),
 573         LoadLoad(1 << 0, "loadload"),
 574         Sync(1 << 6, "sync"),
 575         MemIssue(1 << 5, "memissue"),
 576         LookAside(1 << 4, "lookaside");
 577 
 578         // @formatter:on
 579 
 580         private final int value;
 581         private final String operator;
 582 
 583         MembarMask(int value, String op) {
 584             this.value = value;
 585             this.operator = op;
 586         }
 587 
 588         public int getValue() {
 589             return value | 0x2000;
 590         }
 591 
 592         public String getOperator() {
 593             return operator;
 594         }
 595     }
 596 
 597     /**
 598      * Condition Codes to use for instruction.
 599      */
 600     public enum CC {
 601         // @formatter:off
 602         /**
 603          * Condition is considered as 32bit operation condition.
 604          */
 605         Icc(0b00, "icc", false),
 606         /**
 607          * Condition is considered as 64bit operation condition.
 608          */
 609         Xcc(0b10, "xcc", false),
 610         Fcc0(0b00, "fcc0", true),
 611         Fcc1(0b01, "fcc1", true),
 612         Fcc2(0b10, "fcc2", true),
 613         Fcc3(0b11, "fcc3", true);
 614 
 615         // @formatter:on
 616 
 617         private final int value;
 618         private final String operator;
 619         private boolean isFloat;
 620 
 621         CC(int value, String op, boolean isFloat) {
 622             this.value = value;
 623             this.operator = op;
 624             this.isFloat = isFloat;
 625         }
 626 
 627         public int getValue() {
 628             return value;
 629         }
 630 
 631         public String getOperator() {
 632             return operator;
 633         }
 634 
 635         public static CC forKind(PlatformKind kind) {
 636             if (kind.equals(SPARCKind.XWORD)) {
 637                 return Xcc;
 638             } else if (kind.equals(SPARCKind.WORD)) {
 639                 return Icc;
 640             } else if (kind.equals(SPARCKind.SINGLE) || kind.equals(SPARCKind.DOUBLE)) {
 641                 return Fcc0;
 642             } else {
 643                 throw new IllegalArgumentException("Unknown kind: " + kind);
 644             }
 645         }
 646     }
 647 
 648     public enum ConditionFlag {
 649         // @formatter:off
 650 
 651         // for FBfcc & FBPfcc instruction
 652         F_Never(0, "f_never"),
 653         F_NotEqual(1, "f_notEqual"),
 654         F_LessOrGreater(2, "f_lessOrGreater"),
 655         F_UnorderedOrLess(3, "f_unorderedOrLess"),
 656         F_Less(4, "f_less"),
 657         F_UnorderedOrGreater(5, "f_unorderedOrGreater"),
 658         F_Greater(6, "f_greater"),
 659         F_Unordered(7, "f_unordered"),
 660         F_Always(8, "f_always"),
 661         F_Equal(9, "f_equal"),
 662         F_UnorderedOrEqual(10, "f_unorderedOrEqual"),
 663         F_GreaterOrEqual(11, "f_greaterOrEqual"),
 664         F_UnorderedGreaterOrEqual(12, "f_unorderedGreaterOrEqual"),
 665         F_LessOrEqual(13, "f_lessOrEqual"),
 666         F_UnorderedOrLessOrEqual(14, "f_unorderedOrLessOrEqual"),
 667         F_Ordered(15, "f_ordered"),
 668 
 669         // for integers
 670         Never(0, "never"),
 671         Equal(1, "equal", true),
 672         Zero(1, "zero"),
 673         LessEqual(2, "lessEqual", true),
 674         Less(3, "less", true),
 675         LessEqualUnsigned(4, "lessEqualUnsigned", true),
 676         LessUnsigned(5, "lessUnsigned", true),
 677         CarrySet(5, "carrySet"),
 678         Negative(6, "negative", true),
 679         OverflowSet(7, "overflowSet", true),
 680         Always(8, "always"),
 681         NotEqual(9, "notEqual", true),
 682         NotZero(9, "notZero"),
 683         Greater(10, "greater", true),
 684         GreaterEqual(11, "greaterEqual", true),
 685         GreaterUnsigned(12, "greaterUnsigned", true),
 686         GreaterEqualUnsigned(13, "greaterEqualUnsigned", true),
 687         CarryClear(13, "carryClear"),
 688         Positive(14, "positive", true),
 689         OverflowClear(15, "overflowClear", true);
 690 
 691         // @formatter:on
 692 
 693         private final int value;
 694         private final String operator;
 695         private boolean forCBcond = false;
 696 
 697         ConditionFlag(int value, String op) {
 698             this(value, op, false);
 699         }
 700 
 701         ConditionFlag(int value, String op, boolean cbcond) {
 702             this.value = value;
 703             this.operator = op;
 704             this.forCBcond = cbcond;
 705         }
 706 
 707         public boolean isCBCond() {
 708             return forCBcond;
 709         }
 710 
 711         public int getValue() {
 712             return value;
 713         }
 714 
 715         public String getOperator() {
 716             return operator;
 717         }
 718 
 719         public ConditionFlag negate() {
 720             //@formatter:off
 721             switch (this) {
 722                 case F_Never                  : return F_Always;
 723                 case F_Always                 : return F_Never;
 724                 case F_NotEqual               : return F_Equal;
 725                 case F_Equal                  : return F_NotEqual;
 726                 case F_LessOrGreater          : return F_UnorderedOrEqual;
 727                 case F_UnorderedOrEqual       : return F_LessOrGreater;
 728                 case F_Less                   : return F_UnorderedGreaterOrEqual;
 729                 case F_UnorderedGreaterOrEqual: return F_Less;
 730                 case F_LessOrEqual            : return F_UnorderedOrGreater;
 731                 case F_UnorderedOrGreater     : return F_LessOrEqual;
 732                 case F_Greater                : return F_UnorderedOrLessOrEqual;
 733                 case F_UnorderedOrLessOrEqual : return F_Greater;
 734                 case F_GreaterOrEqual         : return F_UnorderedOrLess;
 735                 case F_UnorderedOrLess        : return F_GreaterOrEqual;
 736                 case F_Unordered              : return F_Ordered;
 737                 case F_Ordered                : return F_Unordered;
 738                 case Never                    : return Always;
 739                 case Always                   : return Never;
 740                 case Equal                    : return NotEqual;
 741                 case NotEqual                 : return Equal;
 742                 case Zero                     : return NotZero;
 743                 case NotZero                  : return Zero;
 744                 case LessEqual                : return Greater;
 745                 case Greater                  : return LessEqual;
 746                 case Less                     : return GreaterEqual;
 747                 case GreaterEqual             : return Less;
 748                 case LessEqualUnsigned        : return GreaterUnsigned;
 749                 case GreaterUnsigned          : return LessEqualUnsigned;
 750                 case LessUnsigned             : return GreaterEqualUnsigned;
 751                 case GreaterEqualUnsigned     : return LessUnsigned;
 752                 case CarrySet                 : return CarryClear;
 753                 case CarryClear               : return CarrySet;
 754                 case Negative                 : return Positive;
 755                 case Positive                 : return Negative;
 756                 case OverflowSet              : return OverflowClear;
 757                 case OverflowClear            : return OverflowSet;
 758                 default:
 759                     throw new InternalError();
 760             }
 761             //@formatter:on
 762         }
 763 
 764         public ConditionFlag mirror() {
 765             switch (this) {
 766             //@formatter:off
 767                 case F_Less                   : return F_Greater;
 768                 case F_Greater                : return F_Less;
 769                 case F_LessOrEqual            : return F_GreaterOrEqual;
 770                 case F_UnorderedGreaterOrEqual: return F_UnorderedOrLessOrEqual;
 771                 case F_UnorderedOrGreater     : return F_UnorderedOrLess;
 772                 case F_UnorderedOrLessOrEqual : return F_UnorderedGreaterOrEqual;
 773                 case F_GreaterOrEqual         : return F_LessOrEqual;
 774                 case F_UnorderedOrLess        : return F_UnorderedOrGreater;
 775                 case LessEqual                : return GreaterEqual;
 776                 case Greater                  : return Less;
 777                 case Less                     : return Greater;
 778                 case GreaterEqual             : return LessEqual;
 779                 case LessEqualUnsigned        : return GreaterEqualUnsigned;
 780                 case GreaterUnsigned          : return LessUnsigned;
 781                 case LessUnsigned             : return GreaterUnsigned;
 782                 case GreaterEqualUnsigned     : return LessEqualUnsigned;
 783                 default:
 784                     return this;
 785                 //@formatter:on
 786             }
 787         }
 788 
 789     }
 790 
 791     public enum RCondition {
 792         // @formatter:off
 793 
 794         Rc_z(0b001, "rc_z"),
 795         Rc_lez(0b010, "rc_lez"),
 796         Rc_lz(0b011, "rc_lz"),
 797         Rc_nz(0b101, "rc_nz"),
 798         Rc_gz(0b110, "rc_gz"),
 799         Rc_gez(0b111, "rc_gez"),
 800         Rc_last(Rc_gez.getValue(), "rc_last");
 801 
 802         // @formatter:on
 803 
 804         private final int value;
 805         private final String operator;
 806 
 807         RCondition(int value, String op) {
 808             this.value = value;
 809             this.operator = op;
 810         }
 811 
 812         public int getValue() {
 813             return value;
 814         }
 815 
 816         public String getOperator() {
 817             return operator;
 818         }
 819     }
 820 
 821     /**
 822      * Represents the <b>Address Space Identifier</b> defined in the SPARC architecture.
 823      */
 824     public enum Asi {
 825         // @formatter:off
 826 
 827         INVALID(-1),
 828         ASI_PRIMARY(0x80),
 829         ASI_PRIMARY_NOFAULT(0x82),
 830         ASI_PRIMARY_LITTLE(0x88),
 831         // Block initializing store
 832         ASI_ST_BLKINIT_PRIMARY(0xE2),
 833         // Most-Recently-Used (MRU) BIS variant
 834         ASI_ST_BLKINIT_MRU_PRIMARY(0xF2);
 835 
 836         // @formatter:on
 837 
 838         private final int value;
 839 
 840         Asi(int value) {
 841             this.value = value;
 842         }
 843 
 844         public int getValue() {
 845             return value;
 846         }
 847 
 848         public boolean isValid() {
 849             return value != INVALID.getValue();
 850         }
 851     }
 852 
 853     public enum Fcn {
 854         SeveralWritesAndPossiblyReads(2),
 855         SeveralReadsWeak(0),
 856         OneRead(1),
 857         OneWrite(3),
 858         Page(4),
 859         NearestUnifiedCache(17),
 860         SeveralReadsStrong(20),
 861         OneReadStrong(21),
 862         SeveralWritesAndPossiblyReadsStrong(22),
 863         OneWriteStrong(23);
 864 
 865         private final int value;
 866 
 867         Fcn(int value) {
 868             this.value = value;
 869         }
 870 
 871         public int getValue() {
 872             return value;
 873         }
 874     }
 875 
 876     /**
 877      * Specifies various bit fields used in SPARC instructions.
 878      */
 879     @SuppressWarnings("unused")
 880     public abstract static class BitSpec {
 881         private static final BitSpec op = new ContinousBitSpec(31, 30, "op");
 882         private static final BitSpec op2 = new ContinousBitSpec(24, 22, "op2");
 883         private static final BitSpec op3 = new ContinousBitSpec(24, 19, "op3");
 884         private static final BitSpec opf = new ContinousBitSpec(13, 5, "opf");
 885         private static final BitSpec opfLow = new ContinousBitSpec(10, 5, "opfLow");
 886         private static final BitSpec opfCC = new ContinousBitSpec(13, 11, "opfCC");
 887         private static final BitSpec opfCond = new ContinousBitSpec(17, 14, "opfCond");
 888         private static final BitSpec rd = new ContinousBitSpec(29, 25, "rd");
 889         private static final BitSpec rs1 = new ContinousBitSpec(18, 14, "rs1");
 890         private static final BitSpec rs2 = new ContinousBitSpec(4, 0, "rs2");
 891         private static final BitSpec simm13 = new ContinousBitSpec(12, 0, true, "simm13");
 892         private static final BitSpec shcnt32 = new ContinousBitSpec(4, 0, "shcnt32");
 893         private static final BitSpec shcnt64 = new ContinousBitSpec(5, 0, "shcnt64");
 894         private static final BitSpec imm22 = new ContinousBitSpec(21, 0, "imm22");
 895         private static final BitSpec immAsi = new ContinousBitSpec(12, 5, "immASI");
 896         private static final BitSpec i = new ContinousBitSpec(13, 13, "i");
 897         private static final BitSpec disp19 = new ContinousBitSpec(18, 0, true, "disp19");
 898         private static final BitSpec disp22 = new ContinousBitSpec(21, 0, true, "disp22");
 899         private static final BitSpec disp30 = new ContinousBitSpec(29, 0, true, "disp30");
 900         private static final BitSpec a = new ContinousBitSpec(29, 29, "a");
 901         private static final BitSpec p = new ContinousBitSpec(19, 19, "p");
 902         private static final BitSpec x = new ContinousBitSpec(12, 12, "x");
 903         private static final BitSpec cond = new ContinousBitSpec(28, 25, "cond");
 904         private static final BitSpec rcond = new ContinousBitSpec(27, 25, "rcond");
 905         private static final BitSpec cc = new ContinousBitSpec(21, 20, "cc");
 906         private static final BitSpec fcc = new ContinousBitSpec(26, 25, "cc");
 907         private static final BitSpec d16lo = new ContinousBitSpec(13, 0, "d16lo");
 908         private static final BitSpec d16hi = new ContinousBitSpec(21, 20, true, "d16hi");
 909         private static final BitSpec d16 = new CompositeBitSpec(d16hi, d16lo);
 910         // Movcc
 911         private static final BitSpec movccLo = new ContinousBitSpec(12, 11, "cc_lo");
 912         private static final BitSpec movccHi = new ContinousBitSpec(18, 18, "cc_hi");
 913         private static final BitSpec movccCond = new ContinousBitSpec(17, 14, "cond");
 914         private static final BitSpec simm11 = new ContinousBitSpec(10, 0, true, "simm11");
 915 
 916         // CBCond
 917         private static final BitSpec cLo = new ContinousBitSpec(27, 25, "cLo");
 918         private static final BitSpec cHi = new ContinousBitSpec(29, 29, "cHi");
 919         private static final BitSpec c = new CompositeBitSpec(cHi, cLo);
 920         private static final BitSpec cbcond = new ContinousBitSpec(28, 28, "cbcond");
 921         private static final BitSpec cc2 = new ContinousBitSpec(21, 21, "cc2");
 922         private static final BitSpec d10Lo = new ContinousBitSpec(12, 5, "d10Lo");
 923         private static final BitSpec d10Hi = new ContinousBitSpec(20, 19, true, "d10Hi");
 924         private static final BitSpec d10 = new CompositeBitSpec(d10Hi, d10Lo);
 925         private static final BitSpec simm5 = new ContinousBitSpec(4, 0, true, "simm5");
 926 
 927         protected final boolean signExtend;
 928 
 929         public BitSpec(boolean signExtend) {
 930             super();
 931             this.signExtend = signExtend;
 932         }
 933 
 934         public final boolean isSignExtend() {
 935             return signExtend;
 936         }
 937 
 938         public abstract int setBits(int word, int value);
 939 
 940         public abstract int getBits(int word);
 941 
 942         public abstract int getWidth();
 943 
 944         public abstract boolean valueFits(int value);
 945     }
 946 
 947     public static final class ContinousBitSpec extends BitSpec {
 948         private final int hiBit;
 949         private final int lowBit;
 950         private final int width;
 951         private final int mask;
 952         private final String name;
 953 
 954         public ContinousBitSpec(int hiBit, int lowBit, String name) {
 955             this(hiBit, lowBit, false, name);
 956         }
 957 
 958         public ContinousBitSpec(int hiBit, int lowBit, boolean signExt, String name) {
 959             super(signExt);
 960             this.hiBit = hiBit;
 961             this.lowBit = lowBit;
 962             this.width = hiBit - lowBit + 1;
 963             mask = ((1 << width) - 1) << lowBit;
 964             this.name = name;
 965         }
 966 
 967         @Override
 968         public int setBits(int word, int value) {
 969             assert valueFits(value) : String.format("Value 0x%x for field %s does not fit.", value, this);
 970             return (word & ~mask) | ((value << lowBit) & mask);
 971         }
 972 
 973         @Override
 974         public int getBits(int word) {
 975             if (signExtend) {
 976                 return ((word & mask) << (31 - hiBit)) >> (32 - width);
 977             } else {
 978                 return (word & mask) >>> lowBit;
 979             }
 980         }
 981 
 982         @Override
 983         public int getWidth() {
 984             return width;
 985         }
 986 
 987         @Override
 988         public String toString() {
 989             return String.format("%s [%d:%d]", name, hiBit, lowBit);
 990         }
 991 
 992         @Override
 993         public boolean valueFits(int value) {
 994             if (signExtend) {
 995                 return isSimm(value, getWidth());
 996             } else {
 997                 return isImm(value, getWidth());
 998             }
 999         }
1000     }
1001 
1002     public static final class CompositeBitSpec extends BitSpec {
1003         private final BitSpec left;
1004         private final int leftWidth;
1005         private final BitSpec right;
1006         private final int rightWidth;
1007         private final int width;
1008 
1009         public CompositeBitSpec(BitSpec left, BitSpec right) {
1010             super(left.isSignExtend());
1011             assert !right.isSignExtend() : String.format("Right field %s must not be sign extended", right);
1012             this.left = left;
1013             this.leftWidth = left.getWidth();
1014             this.right = right;
1015             this.rightWidth = right.getWidth();
1016             this.width = leftWidth + rightWidth;
1017         }
1018 
1019         @Override
1020         public int getBits(int word) {
1021             int l = left.getBits(word);
1022             int r = right.getBits(word);
1023             return (l << rightWidth) | r;
1024         }
1025 
1026         @Override
1027         public int setBits(int word, int value) {
1028             int l = leftBits(value);
1029             int r = rightBits(value);
1030             return left.setBits(right.setBits(word, r), l);
1031         }
1032 
1033         private int leftBits(int value) {
1034             return getBits(value, width - 1, rightWidth, signExtend);
1035         }
1036 
1037         private int rightBits(int value) {
1038             return getBits(value, rightWidth - 1, 0, false);
1039         }
1040 
1041         @Override
1042         public int getWidth() {
1043             return width;
1044         }
1045 
1046         @Override
1047         public String toString() {
1048             return String.format("CompositeBitSpec[%s, %s]", left, right);
1049         }
1050 
1051         @Override
1052         public boolean valueFits(int value) {
1053             int l = leftBits(value);
1054             int r = rightBits(value);
1055             return left.valueFits(l) && right.valueFits(r);
1056         }
1057 
1058         private static int getBits(int inst, int hiBit, int lowBit, boolean signExtended) {
1059             int shifted = inst >> lowBit;
1060             if (signExtended) {
1061                 return shifted;
1062             } else {
1063                 return shifted & ((1 << (hiBit - lowBit + 1)) - 1);
1064             }
1065         }
1066     }
1067 
1068     public static class BitKey {
1069         private final BitSpec spec;
1070         private final int value;
1071 
1072         public BitKey(BitSpec spec, int value) {
1073             super();
1074             this.spec = spec;
1075             this.value = value;
1076         }
1077 
1078         @Override
1079         public String toString() {
1080             return String.format("BitKey %s=%s", spec, value);
1081         }
1082     }
1083 
1084     /**
1085      * Represents a prefix tree of {@link BitSpec} objects to find the most accurate SPARCOp.
1086      */
1087     public static final class BitKeyIndex {
1088         private final BitSpec spec;
1089         private final Map<Integer, BitKeyIndex> nodes;
1090         private SPARCOp op;
1091 
1092         public BitKeyIndex(SPARCOp op) {
1093             assert op != null;
1094             this.op = op;
1095             this.nodes = null;
1096             this.spec = null;
1097         }
1098 
1099         public BitKeyIndex(BitSpec spec) {
1100             assert spec != null;
1101             this.op = null;
1102             this.nodes = new HashMap<>(4);
1103             this.spec = spec;
1104         }
1105 
1106         /**
1107          * Adds operation to the index.
1108          *
1109          * @param keys Ordered by the importance
1110          * @param operation Operation represented by this list of keys
1111          */
1112         private void addOp(List<BitKey[]> keys, SPARCOp operation) {
1113             assert keys.size() > 0;
1114             BitKey[] firstKeys = keys.get(0);
1115             for (BitKey first : firstKeys) {
1116                 assert first.spec.equals(spec) : first.spec + " " + spec;
1117                 BitKeyIndex node;
1118                 if (keys.size() == 1) {
1119                     if (nodes.containsKey(first.value)) {
1120                         node = nodes.get(first.value);
1121                         assert node.op == null : node + " " + keys;
1122                         node.op = operation;
1123                     } else {
1124                         assert !nodes.containsKey(first.value) : "Index must be unique. Existing key: " + nodes.get(first.value);
1125                         node = new BitKeyIndex(operation);
1126                     }
1127                 } else {
1128                     node = nodes.get(first.value);
1129                     BitKey[] next = keys.get(1);
1130                     if (node == null) {
1131                         for (int i = 1; i < next.length; i++) {
1132                             assert next[i - 1].spec.equals(next[i].spec) : "All spec on this node must equal";
1133                         }
1134                         node = new BitKeyIndex(next[0].spec);
1135                     }
1136                     node.addOp(keys.subList(1, keys.size()), operation);
1137                 }
1138                 nodes.put(first.value, node);
1139             }
1140         }
1141 
1142         /**
1143          * Finds the best matching {@link SPARCOp} for this instruction.
1144          */
1145         public SPARCOp find(int inst) {
1146             if (nodes != null) {
1147                 int key = spec.getBits(inst);
1148                 BitKeyIndex sub = nodes.get(key);
1149                 if (sub == null) {
1150                     if (op != null) {
1151                         return op;
1152                     } else {
1153                         throw new RuntimeException(String.format("%s 0x%x, 0x%x %s", spec, inst, key, nodes));
1154                     }
1155                 }
1156                 return sub.find(inst);
1157             } else {
1158                 return this.op;
1159             }
1160         }
1161 
1162         @Override
1163         public String toString() {
1164             return this.op == null ? this.spec + ": " + this.nodes : this.op.toString();
1165         }
1166     }
1167 
1168     public static final Bpcc BPCC = new Bpcc(Op2s.Bp);
1169     public static final Bpcc FBPCC = new Bpcc(Op2s.Fbp);
1170     public static final CBCond CBCOND = new CBCond();
1171     public static final Bpr BPR = new Bpr();
1172     public static final Br BR = new Br();
1173     public static final Sethi SETHI = new Sethi();
1174     public static final FMOVcc FMOVSCC = new FMOVcc(OpfLow.Fmovscc);
1175     public static final FMOVcc FMOVDCC = new FMOVcc(OpfLow.Fmovdcc);
1176     public static final MOVicc MOVICC = new MOVicc();
1177     public static final OpfOp OPF = new OpfOp();
1178     public static final Op3Op OP3 = new Op3Op();
1179     public static final SPARCOp LDST = new SPARCOp(Ops.LdstOp);
1180     public static final SPARCOp BRANCH = new SPARCOp(Ops.BranchOp);
1181     public static final SPARCOp CALL = new SPARCOp(Ops.CallOp);
1182     private static final BitKeyIndex INDEX = new BitKeyIndex(BitSpec.op);
1183 
1184     static {
1185         for (SPARCOp op : SPARCOp.OPS) {
1186             INDEX.addOp(op.getKeys(), op);
1187         }
1188     }
1189 
1190     public static SPARCOp getSPARCOp(int inst) {
1191         return INDEX.find(inst);
1192     }
1193 
1194     /**
1195      * Represents a class of SPARC instruction and gives methods to modify its fields.
1196      */
1197     public static class SPARCOp {
1198         private final Ops op;
1199         private final BitKey opKey;
1200         private List<BitKey[]> keyFields;
1201         private static final List<SPARCOp> OPS = new ArrayList<>();
1202 
1203         public SPARCOp(Ops op) {
1204             super();
1205             this.op = op;
1206             this.opKey = new BitKey(BitSpec.op, op.value);
1207             OPS.add(this);
1208         }
1209 
1210         protected int setBits(int word) {
1211             return BitSpec.op.setBits(word, op.value);
1212         }
1213 
1214         public boolean match(int inst) {
1215             for (BitKey[] keys : keyFields) {
1216                 for (BitKey k : keys) {
1217                     if (k.spec.getBits(inst) != k.value) {
1218                         return false;
1219                     }
1220                 }
1221             }
1222             return true;
1223         }
1224 
1225         protected List<BitKey[]> getKeys() {
1226             if (keyFields == null) {
1227                 keyFields = new ArrayList<>(4);
1228                 keyFields.add(new BitKey[]{opKey});
1229             }
1230             return keyFields;
1231         }
1232 
1233         public Ops getOp(int inst) {
1234             return SPARCAssembler.OPS[BitSpec.op.getBits(inst)];
1235         }
1236 
1237         @Override
1238         public String toString() {
1239             String name = getClass().getName();
1240             name = name.substring(name.lastIndexOf(".") + 1);
1241             return name + "[op: " + op + "]";
1242         }
1243     }
1244 
1245     /**
1246      * Base class for control transfer operations; provides access to the disp field.
1247      */
1248     public abstract static class ControlTransferOp extends SPARCOp {
1249         private final Op2s op2;
1250         private final boolean delaySlot;
1251         private final BitSpec disp;
1252         private final BitKey[] op2Key;
1253 
1254         private ControlTransferOp(Ops op, Op2s op2, boolean delaySlot, BitSpec disp) {
1255             super(op);
1256             this.op2 = op2;
1257             this.delaySlot = delaySlot;
1258             this.disp = disp;
1259             this.op2Key = new BitKey[]{new BitKey(BitSpec.op2, op2.value)};
1260         }
1261 
1262         public boolean hasDelaySlot() {
1263             return delaySlot;
1264         }
1265 
1266         @Override
1267         protected int setBits(int word) {
1268             return BitSpec.op2.setBits(super.setBits(word), op2.value);
1269         }
1270 
1271         protected int setDisp(int inst, SPARCMacroAssembler masm, Label lab) {
1272             if (lab.isBound()) {
1273                 int d = (lab.position() - masm.position()) / 4;
1274                 return setDisp(inst, d);
1275             } else {
1276                 masm.patchUnbound(lab);
1277                 return inst;
1278             }
1279         }
1280 
1281         public int setDisp(int inst, int d) {
1282             assert this.match(inst);
1283             if (!isValidDisp(d)) {
1284                 throw new BranchTargetOutOfBoundsException(true, "Too large displacement 0x%x in field %s in instruction %s", d, this.disp, this);
1285             }
1286             return this.disp.setBits(inst, d);
1287         }
1288 
1289         public boolean isValidDisp(int d) {
1290             return this.disp.valueFits(d);
1291         }
1292 
1293         public int setAnnul(int inst, boolean a) {
1294             return BitSpec.a.setBits(inst, a ? 1 : 0);
1295         }
1296 
1297         @Override
1298         protected List<BitKey[]> getKeys() {
1299             List<BitKey[]> keys = super.getKeys();
1300             keys.add(op2Key);
1301             return keys;
1302         }
1303 
1304         public int getDisp(int inst) {
1305             return this.disp.getBits(inst);
1306         }
1307 
1308         public abstract boolean isAnnulable(int inst);
1309 
1310         public abstract boolean isConditional(int inst);
1311     }
1312 
1313     public static final class Bpcc extends ControlTransferOp {
1314         public Bpcc(Op2s op2) {
1315             super(Ops.BranchOp, op2, true, BitSpec.disp19);
1316         }
1317 
1318         public void emit(SPARCMacroAssembler masm, CC cc, ConditionFlag cf, Annul annul, BranchPredict p, Label lab) {
1319             int inst = setBits(0);
1320             inst = BitSpec.a.setBits(inst, annul.flag);
1321             inst = BitSpec.cond.setBits(inst, cf.value);
1322             inst = BitSpec.cc.setBits(inst, cc.value);
1323             inst = BitSpec.p.setBits(inst, p.flag);
1324             masm.insertNopAfterCBCond();
1325             masm.emitInt(setDisp(inst, masm, lab));
1326         }
1327 
1328         @Override
1329         public boolean isAnnulable(int inst) {
1330             return isConditional(inst);
1331         }
1332 
1333         @Override
1334         public boolean isConditional(int inst) {
1335             int cond = BitSpec.cond.getBits(inst);
1336             return cond != ConditionFlag.Always.value && cond != ConditionFlag.Never.value;
1337         }
1338     }
1339 
1340     public static final class Br extends ControlTransferOp {
1341         public Br() {
1342             super(Ops.BranchOp, Op2s.Br, true, BitSpec.disp22);
1343         }
1344 
1345         @Override
1346         public boolean isAnnulable(int inst) {
1347             return isConditional(inst);
1348         }
1349 
1350         @Override
1351         public boolean isConditional(int inst) {
1352             int cond = BitSpec.cond.getBits(inst);
1353             return cond != ConditionFlag.Always.value && cond != ConditionFlag.Never.value;
1354         }
1355 
1356         public void emit(SPARCMacroAssembler masm, ConditionFlag cond, Annul a, Label lab) {
1357             int inst = setBits(0);
1358             inst = BitSpec.cond.setBits(inst, cond.value);
1359             inst = BitSpec.a.setBits(inst, a.flag);
1360             masm.insertNopAfterCBCond();
1361             masm.emitInt(setDisp(inst, masm, lab));
1362         }
1363     }
1364 
1365     public static final class Bpr extends ControlTransferOp {
1366         private static final BitKey CBCOND_KEY = new BitKey(BitSpec.cbcond, 0);
1367 
1368         public Bpr() {
1369             super(Ops.BranchOp, Op2s.Bpr, true, BitSpec.d16);
1370         }
1371 
1372         public void emit(SPARCMacroAssembler masm, RCondition rcond, Annul a, BranchPredict p, Register rs1, Label lab) {
1373             int inst = setBits(0);
1374             inst = BitSpec.rcond.setBits(inst, rcond.value);
1375             inst = BitSpec.a.setBits(inst, a.flag);
1376             inst = BitSpec.p.setBits(inst, p.flag);
1377             inst = BitSpec.rs1.setBits(inst, rs1.encoding);
1378             masm.insertNopAfterCBCond();
1379             masm.emitInt(setDisp(inst, masm, lab));
1380         }
1381 
1382         @Override
1383         protected List<BitKey[]> getKeys() {
1384             List<BitKey[]> keys = super.getKeys();
1385             keys.add(new BitKey[]{CBCOND_KEY});
1386             return keys;
1387         }
1388 
1389         @Override
1390         public boolean isAnnulable(int inst) {
1391             return isConditional(inst);
1392         }
1393 
1394         @Override
1395         public boolean isConditional(int inst) {
1396             int cond = BitSpec.cond.getBits(inst);
1397             return cond != ConditionFlag.Always.value && cond != ConditionFlag.Never.value;
1398         }
1399     }
1400 
1401     public static final class CBCond extends ControlTransferOp {
1402         private static final BitKey CBCOND_KEY = new BitKey(BitSpec.cbcond, 1);
1403 
1404         private CBCond() {
1405             super(Ops.BranchOp, Op2s.Bpr, false, BitSpec.d10);
1406         }
1407 
1408         @Override
1409         protected List<BitKey[]> getKeys() {
1410             List<BitKey[]> keys = super.getKeys();
1411             keys.add(new BitKey[]{CBCOND_KEY});
1412             return keys;
1413         }
1414 
1415         public void emit(SPARCMacroAssembler masm, ConditionFlag cf, boolean cc2, Register rs1, Register rs2, Label lab) {
1416             int inst = setBits(0, cf, cc2, rs1);
1417             inst = BitSpec.rs2.setBits(inst, rs2.encoding);
1418             inst = BitSpec.i.setBits(inst, 0);
1419             masm.insertNopAfterCBCond();
1420             emit(masm, lab, inst);
1421         }
1422 
1423         public void emit(SPARCMacroAssembler masm, ConditionFlag cf, boolean cc2, Register rs1, int simm5, Label lab) {
1424             int inst = setBits(0, cf, cc2, rs1);
1425             inst = BitSpec.simm5.setBits(inst, simm5);
1426             inst = BitSpec.i.setBits(inst, 1);
1427             emit(masm, lab, inst);
1428         }
1429 
1430         private void emit(SPARCMacroAssembler masm, Label lab, int baseInst) {
1431             int inst = baseInst;
1432             masm.insertNopAfterCBCond();
1433             masm.emitInt(setDisp(inst, masm, lab));
1434         }
1435 
1436         private int setBits(int base, ConditionFlag cf, boolean cc2, Register rs1) {
1437             int inst = super.setBits(base);
1438             inst = BitSpec.rs1.setBits(inst, rs1.encoding);
1439             inst = BitSpec.cc2.setBits(inst, cc2 ? 1 : 0);
1440             inst = BitSpec.c.setBits(inst, cf.value);
1441             return BitSpec.cbcond.setBits(inst, 1);
1442         }
1443 
1444         @Override
1445         public boolean isAnnulable(int inst) {
1446             return false;
1447         }
1448 
1449         @Override
1450         public boolean isConditional(int inst) {
1451             return true;
1452         }
1453     }
1454 
1455     public static class Op2Op extends SPARCOp {
1456         private final Op2s op2;
1457         private final BitKey op2Key;
1458 
1459         public Op2Op(Ops op, Op2s op2) {
1460             super(op);
1461             this.op2 = op2;
1462             op2Key = new BitKey(BitSpec.op2, op2.value);
1463         }
1464 
1465         @Override
1466         protected int setBits(int word) {
1467             int result = super.setBits(word);
1468             return BitSpec.op2.setBits(result, op2.value);
1469         }
1470 
1471         @Override
1472         protected List<BitKey[]> getKeys() {
1473             List<BitKey[]> keys = super.getKeys();
1474             keys.add(new BitKey[]{op2Key});
1475             return keys;
1476         }
1477     }
1478 
1479     public static final class Sethi extends Op2Op {
1480         public Sethi() {
1481             super(Ops.BranchOp, Op2s.Sethi);
1482         }
1483 
1484         public static Register getRS1(int word) {
1485             int regNum = BitSpec.rs1.getBits(word);
1486             return SPARC.cpuRegisters.get(regNum);
1487         }
1488 
1489         public static int getImm22(int word) {
1490             return BitSpec.imm22.getBits(word);
1491         }
1492 
1493         public static boolean isNop(int inst) {
1494             return getRS1(inst).equals(g0) && getImm22(inst) == 0;
1495         }
1496     }
1497 
1498     public static final class Op3Op extends SPARCOp {
1499         public Op3Op() {
1500             super(ArithOp);
1501         }
1502 
1503         public Op3s getOp3(int inst) {
1504             assert match(inst);
1505             return OP3S[ArithOp.value & 1][BitSpec.op3.getBits(inst)];
1506         }
1507 
1508         public static void emit(SPARCMacroAssembler masm, Op3s opcode, Register rs1, Register rs2, Register rd) {
1509             int instruction = setBits(0, opcode, rs1, rd);
1510             instruction = BitSpec.rs2.setBits(instruction, rs2.encoding);
1511             instruction = BitSpec.i.setBits(instruction, 0);
1512             masm.emitInt(instruction);
1513         }
1514 
1515         public static void emit(SPARCMacroAssembler masm, Op3s opcode, Register rs1, int simm13, Register rd) {
1516             int instruction = setBits(0, opcode, rs1, rd);
1517             instruction = BitSpec.i.setBits(instruction, 1);
1518             BitSpec immediateSpec;
1519             switch (opcode) {
1520                 case Sllx:
1521                 case Srlx:
1522                 case Srax:
1523                     immediateSpec = BitSpec.shcnt64;
1524                     break;
1525                 case Sll:
1526                 case Srl:
1527                 case Sra:
1528                     immediateSpec = BitSpec.shcnt32;
1529                     break;
1530                 default:
1531                     immediateSpec = BitSpec.simm13;
1532                     break;
1533             }
1534             instruction = immediateSpec.setBits(instruction, simm13);
1535             masm.emitInt(instruction);
1536         }
1537 
1538         private static int setBits(int instruction, Op3s op3, Register rs1, Register rd) {
1539             assert op3.op.equals(ArithOp);
1540             int tmp = BitSpec.op3.setBits(instruction, op3.value);
1541             switch (op3) {
1542                 case Sllx:
1543                 case Srlx:
1544                 case Srax:
1545                     tmp = BitSpec.x.setBits(tmp, 1);
1546                     break;
1547             }
1548             tmp = BitSpec.op.setBits(tmp, op3.op.value);
1549             tmp = BitSpec.rd.setBits(tmp, rd.encoding);
1550             return BitSpec.rs1.setBits(tmp, rs1.encoding);
1551         }
1552     }
1553 
1554     /**
1555      * Used for interfacing FP and GP conditional move instructions.
1556      */
1557     public interface CMOV {
1558         void emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, Register rs2, Register rd);
1559 
1560         void emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, int simm11, Register rd);
1561     }
1562 
1563     public static final class MOVicc extends SPARCOp implements CMOV {
1564         private static final Op3s op3 = Movcc;
1565 
1566         public MOVicc() {
1567             super(ArithOp);
1568         }
1569 
1570         @Override
1571         public void emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, Register rs2, Register rd) {
1572             int inst = setBits(0, condition, cc, rd);
1573             inst = BitSpec.rs2.setBits(inst, rs2.encoding());
1574             masm.emitInt(inst);
1575         }
1576 
1577         @Override
1578         public void emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, int simm11, Register rd) {
1579             int inst = setBits(0, condition, cc, rd);
1580             inst = BitSpec.i.setBits(inst, 1);
1581             inst = BitSpec.simm11.setBits(inst, simm11);
1582             masm.emitInt(inst);
1583         }
1584 
1585         protected int setBits(int word, ConditionFlag condition, CC cc, Register rd) {
1586             int inst = super.setBits(word);
1587             inst = BitSpec.rd.setBits(inst, rd.encoding());
1588             inst = BitSpec.op3.setBits(inst, op3.value);
1589             inst = BitSpec.movccCond.setBits(inst, condition.value);
1590             inst = BitSpec.movccLo.setBits(inst, cc.value);
1591             return BitSpec.movccHi.setBits(inst, cc.isFloat ? 0 : 1);
1592         }
1593 
1594         @Override
1595         protected List<BitKey[]> getKeys() {
1596             List<BitKey[]> keys = super.getKeys();
1597             keys.add(new BitKey[]{new BitKey(BitSpec.op3, op3.value)});
1598             return keys;
1599         }
1600     }
1601 
1602     public static final class FMOVcc extends SPARCOp implements CMOV {
1603         private OpfLow opfLow;
1604 
1605         public FMOVcc(OpfLow opfLow) {
1606             super(ArithOp);
1607             this.opfLow = opfLow;
1608         }
1609 
1610         @Override
1611         public void emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, Register rs2, Register rd) {
1612             int inst = setBits(0);
1613             inst = BitSpec.rd.setBits(inst, rd.encoding());
1614             inst = BitSpec.op3.setBits(inst, opfLow.op3.value);
1615             inst = BitSpec.opfCond.setBits(inst, condition.value);
1616             inst = BitSpec.opfCC.setBits(inst, cc.value);
1617             inst = BitSpec.opfLow.setBits(inst, opfLow.value);
1618             inst = BitSpec.rs2.setBits(inst, rs2.encoding());
1619             masm.emitInt(inst);
1620         }
1621 
1622         @Override
1623         public void emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, int simm11, Register rd) {
1624             throw new IllegalArgumentException("FMOVCC cannot be used with immediate value");
1625         }
1626 
1627         @Override
1628         protected List<BitKey[]> getKeys() {
1629             List<BitKey[]> keys = super.getKeys();
1630             keys.add(new BitKey[]{new BitKey(BitSpec.op3, opfLow.op3.value)});
1631             keys.add(new BitKey[]{new BitKey(BitSpec.opfLow, opfLow.value)});
1632             return keys;
1633         }
1634     }
1635 
1636     public static final class OpfOp extends SPARCOp {
1637 
1638         private BitKey[] op3Keys;
1639 
1640         public OpfOp(BitKey... op3Keys) {
1641             super(ArithOp);
1642             this.op3Keys = op3Keys;
1643         }
1644 
1645         public OpfOp() {
1646             // @formatter:off
1647             this(new BitKey[]{
1648                             new BitKey(BitSpec.op3, Op3s.Fpop1.value),
1649                             new BitKey(BitSpec.op3, Op3s.Fpop2.value),
1650                             new BitKey(BitSpec.op3, Op3s.Impdep1.value),
1651                             new BitKey(BitSpec.op3, Op3s.Impdep2.value)});
1652             // @formatter:on
1653         }
1654 
1655         public static void emit(SPARCMacroAssembler masm, Opfs opf, Register rs1, Register rs2, Register rd) {
1656             int instruction = setBits(0, opf, rs1, rs2);
1657             instruction = BitSpec.rd.setBits(instruction, rd.encoding);
1658             instruction = BitSpec.i.setBits(instruction, 0);
1659             masm.emitInt(instruction);
1660         }
1661 
1662         public static void emitFcmp(SPARCMacroAssembler masm, Opfs opf, CC cc, Register rs1, Register rs2) {
1663             assert opf.equals(Opfs.Fcmpd) || opf.equals(Opfs.Fcmps) : opf;
1664             int instruction = setBits(0, opf, rs1, rs2);
1665             instruction = BitSpec.fcc.setBits(instruction, cc.value);
1666             masm.emitInt(instruction);
1667         }
1668 
1669         private static int setBits(int instruction, Opfs opf, Register rs1, Register rs2) {
1670             int tmp = BitSpec.op.setBits(instruction, opf.op3.op.value);
1671             tmp = BitSpec.op3.setBits(tmp, opf.op3.value);
1672             tmp = BitSpec.opf.setBits(tmp, opf.value);
1673             tmp = BitSpec.rs1.setBits(tmp, rs1.encoding);
1674             return BitSpec.rs2.setBits(tmp, rs2.encoding);
1675         }
1676 
1677         @Override
1678         protected List<BitKey[]> getKeys() {
1679             List<BitKey[]> keys = super.getKeys();
1680             keys.add(op3Keys);
1681             // @formatter:on
1682             return keys;
1683         }
1684     }
1685 
1686     public static boolean isCPURegister(Register... regs) {
1687         for (Register reg : regs) {
1688             if (!isCPURegister(reg)) {
1689                 return false;
1690             }
1691         }
1692         return true;
1693     }
1694 
1695     public static boolean isCPURegister(Register r) {
1696         return r.getRegisterCategory().equals(CPU);
1697     }
1698 
1699     public static boolean isGlobalRegister(Register r) {
1700         return isCPURegister(r) && g0.number <= r.number && r.number <= g7.number;
1701     }
1702 
1703     public static boolean isSingleFloatRegister(Register r) {
1704         return r.getRegisterCategory().equals(FPUs);
1705     }
1706 
1707     public static boolean isDoubleFloatRegister(Register r) {
1708         return r.getRegisterCategory().equals(FPUd);
1709     }
1710 
1711     public boolean hasFeature(CPUFeature feature) {
1712         return ((SPARC) this.target.arch).features.contains(feature);
1713     }
1714 
1715     public static final int simm(int x, int nbits) {
1716         // assert_signed_range(x, nbits);
1717         return x & ((1 << nbits) - 1);
1718     }
1719 
1720     public static final boolean isImm(int x, int nbits) {
1721         // assert_signed_range(x, nbits);
1722         return simm(x, nbits) == x;
1723     }
1724 
1725     /**
1726      * Minimum value for signed immediate ranges.
1727      */
1728     public static long minSimm(long nbits) {
1729         return -(1L << (nbits - 1));
1730     }
1731 
1732     /**
1733      * Maximum value for signed immediate ranges.
1734      */
1735     public static long maxSimm(long nbits) {
1736         return (1L << (nbits - 1)) - 1;
1737     }
1738 
1739     /**
1740      * Test if imm is within signed immediate range for nbits.
1741      */
1742     public static boolean isSimm(long imm, int nbits) {
1743         return minSimm(nbits) <= imm && imm <= maxSimm(nbits);
1744     }
1745 
1746     public static boolean isSimm10(long imm) {
1747         return isSimm(imm, 10);
1748     }
1749 
1750     public static boolean isSimm11(long imm) {
1751         return isSimm(imm, 11);
1752     }
1753 
1754     public static boolean isSimm11(JavaConstant constant) {
1755         return constant.isNull() || isSimm11(constant.asLong());
1756     }
1757 
1758     public static boolean isSimm5(JavaConstant constant) {
1759         return constant.isNull() || isSimm(constant.asLong(), 5);
1760     }
1761 
1762     public static boolean isSimm5(long imm) {
1763         return isSimm(imm, 5);
1764     }
1765 
1766     public static boolean isSimm13(int imm) {
1767         return isSimm(imm, 13);
1768     }
1769 
1770     public static boolean isSimm13(JavaConstant constant) {
1771         long bits;
1772         switch (constant.getJavaKind()) {
1773             case Double:
1774                 bits = Double.doubleToRawLongBits(constant.asDouble());
1775                 break;
1776             case Float:
1777                 bits = Float.floatToRawIntBits(constant.asFloat());
1778                 break;
1779             case Object:
1780                 return constant.isNull();
1781             default:
1782                 bits = constant.asLong();
1783                 break;
1784         }
1785         return constant.isNull() || isSimm13(bits);
1786     }
1787 
1788     public static boolean isSimm13(long imm) {
1789         return NumUtil.isInt(imm) && isSimm(imm, 13);
1790     }
1791 
1792     public static boolean isWordDisp30(long imm) {
1793         return isSimm(imm, 30 + 2);
1794     }
1795 
1796     public static final int hi22(int x) {
1797         return x >>> 10;
1798     }
1799 
1800     public static final int lo10(int x) {
1801         return x & ((1 << 10) - 1);
1802     }
1803 
1804     // @formatter:off
1805     /**
1806      * Instruction format for Fmt00 instructions. This abstraction is needed as it
1807      * makes the patching easier later on.
1808      * <pre>
1809      * | 00  |    a   | op2 |               b                         |
1810      * |31 30|29    25|24 22|21                                      0|
1811      * </pre>
1812      */
1813     // @formatter:on
1814     protected void fmt00(int a, int op2, int b) {
1815         assert isImm(a, 5) && isImm(op2, 3) && isImm(b, 22) : String.format("a: 0x%x op2: 0x%x b: 0x%x", a, op2, b);
1816         int word = 0;
1817         BitSpec.op.setBits(word, 0);
1818         BitSpec.rd.setBits(word, a);
1819         BitSpec.op2.setBits(word, op2);
1820         BitSpec.imm22.setBits(word, b);
1821         emitInt(a << 25 | op2 << 22 | b);
1822     }
1823 
1824     private void op3(Op3s op3, Opfs opf, Register rs1, Register rs2, Register rd) {
1825         int b = opf.value << 5 | (rs2 == null ? 0 : rs2.encoding);
1826         fmt(op3.op.value, rd.encoding, op3.value, rs1 == null ? 0 : rs1.encoding, b);
1827     }
1828 
1829     protected void op3(Op3s op3, Register rs1, Register rs2, Register rd) {
1830         int b = rs2 == null ? 0 : rs2.encoding;
1831         int xBit = getXBit(op3);
1832         fmt(op3.op.value, rd.encoding, op3.value, rs1 == null ? 0 : rs1.encoding, b | xBit);
1833     }
1834 
1835     protected void op3(Op3s op3, Register rs1, int simm13, Register rd) {
1836         assert isSimm13(simm13) : simm13;
1837         int i = 1 << 13;
1838         int simm13WithX = simm13 | getXBit(op3);
1839         fmt(op3.op.value, rd.encoding, op3.value, rs1.encoding, i | simm13WithX & ((1 << 13) - 1));
1840     }
1841 
1842     public void insertNopAfterCBCond() {
1843         int pos = position() - INSTRUCTION_SIZE;
1844         if (pos == 0) {
1845             return;
1846         }
1847         int inst = getInt(pos);
1848         if (CBCOND.match(inst)) {
1849             nop();
1850         }
1851     }
1852 
1853     protected int patchUnbound(Label label) {
1854         label.addPatchAt(position(), this);
1855         return 0;
1856     }
1857 
1858     // @formatter:off
1859     /**
1860      * NOP.
1861      * <pre>
1862      * | 00  |00000| 100 |                0                    |
1863      * |31 30|29 25|24 22|21                                  0|
1864      * </pre>
1865      */
1866     // @formatter:on
1867     public void nop() {
1868         emitInt(1 << 24);
1869     }
1870 
1871     public void sethi(int imm22, Register dst) {
1872         fmt00(dst.encoding, Op2s.Sethi.value, imm22);
1873     }
1874 
1875     // @formatter:off
1876     /**
1877      * Instruction format for calls.
1878      * <pre>
1879      * | 01  |                      disp30                             |
1880      * |31 30|29                                                      0|
1881      * </pre>
1882      *
1883      * @return Position of the call instruction
1884      */
1885     // @formatter:on
1886     public int call(int disp30) {
1887         assert isImm(disp30, 30);
1888         insertNopAfterCBCond();
1889         int before = position();
1890         int instr = 1 << 30;
1891         instr |= disp30;
1892         emitInt(instr);
1893         return before;
1894     }
1895 
1896     public void add(Register rs1, Register rs2, Register rd) {
1897         op3(Add, rs1, rs2, rd);
1898     }
1899 
1900     public void add(Register rs1, int simm13, Register rd) {
1901         op3(Add, rs1, simm13, rd);
1902     }
1903 
1904     public void addc(Register rs1, Register rs2, Register rd) {
1905         op3(Addc, rs1, rs2, rd);
1906     }
1907 
1908     public void addc(Register rs1, int simm13, Register rd) {
1909         op3(Addc, rs1, simm13, rd);
1910     }
1911 
1912     public void addcc(Register rs1, Register rs2, Register rd) {
1913         op3(Addcc, rs1, rs2, rd);
1914     }
1915 
1916     public void addcc(Register rs1, int simm13, Register rd) {
1917         op3(Addcc, rs1, simm13, rd);
1918     }
1919 
1920     public void and(Register rs1, Register rs2, Register rd) {
1921         op3(And, rs1, rs2, rd);
1922     }
1923 
1924     public void and(Register rs1, int simm13, Register rd) {
1925         op3(And, rs1, simm13, rd);
1926     }
1927 
1928     public void andcc(Register rs1, Register rs2, Register rd) {
1929         op3(Andcc, rs1, rs2, rd);
1930     }
1931 
1932     public void andcc(Register rs1, int simm13, Register rd) {
1933         op3(Andcc, rs1, simm13, rd);
1934     }
1935 
1936     public void andn(Register rs1, Register rs2, Register rd) {
1937         op3(Andn, rs1, rs2, rd);
1938     }
1939 
1940     public void andn(Register rs1, int simm13, Register rd) {
1941         op3(Andn, rs1, simm13, rd);
1942     }
1943 
1944     public void andncc(Register rs1, Register rs2, Register rd) {
1945         op3(Andncc, rs1, rs2, rd);
1946     }
1947 
1948     public void andncc(Register rs1, int simm13, Register rd) {
1949         op3(Andncc, rs1, simm13, rd);
1950     }
1951 
1952     public void movwtos(Register rs2, Register rd) {
1953         assert isSingleFloatRegister(rd) && isCPURegister(rs2) : String.format("%s %s", rs2, rd);
1954         op3(Impdep1, Movwtos, null, rs2, rd);
1955     }
1956 
1957     public void umulxhi(Register rs1, Register rs2, Register rd) {
1958         op3(Impdep1, UMulxhi, rs1, rs2, rd);
1959     }
1960 
1961     public void fdtos(Register rs2, Register rd) {
1962         assert isSingleFloatRegister(rd) && isDoubleFloatRegister(rs2) : String.format("%s %s", rs2, rd);
1963         op3(Fpop1, Fdtos, null, rs2, rd);
1964     }
1965 
1966     public void movstouw(Register rs2, Register rd) {
1967         assert isSingleFloatRegister(rs2) && isCPURegister(rd) : String.format("%s %s", rs2, rd);
1968         op3(Impdep1, Movstosw, null, rs2, rd);
1969     }
1970 
1971     public void movstosw(Register rs2, Register rd) {
1972         assert isSingleFloatRegister(rs2) && isCPURegister(rd) : String.format("%s %s", rs2, rd);
1973         op3(Impdep1, Movstosw, null, rs2, rd);
1974     }
1975 
1976     public void movdtox(Register rs2, Register rd) {
1977         assert isDoubleFloatRegister(rs2) && isCPURegister(rd) : String.format("%s %s", rs2, rd);
1978         op3(Impdep1, Movdtox, null, rs2, rd);
1979     }
1980 
1981     public void movxtod(Register rs2, Register rd) {
1982         assert isCPURegister(rs2) && isDoubleFloatRegister(rd) : String.format("%s %s", rs2, rd);
1983         op3(Impdep1, Movxtod, null, rs2, rd);
1984     }
1985 
1986     public void fadds(Register rs1, Register rs2, Register rd) {
1987         op3(Fpop1, Fadds, rs1, rs2, rd);
1988     }
1989 
1990     public void faddd(Register rs1, Register rs2, Register rd) {
1991         op3(Fpop1, Faddd, rs1, rs2, rd);
1992     }
1993 
1994     public void fdivs(Register rs1, Register rs2, Register rd) {
1995         op3(Fpop1, Fdivs, rs1, rs2, rd);
1996     }
1997 
1998     public void fdivd(Register rs1, Register rs2, Register rd) {
1999         op3(Fpop1, Fdivd, rs1, rs2, rd);
2000     }
2001 
2002     public void fmovs(Register rs2, Register rd) {
2003         op3(Fpop1, Fmovs, null, rs2, rd);
2004     }
2005 
2006     public void fmovd(Register rs2, Register rd) {
2007         op3(Fpop1, Fmovd, null, rs2, rd);
2008     }
2009 
2010     public void fsrc2s(Register rs2, Register rd) {
2011         op3(Impdep1, Fsrc2s, null, rs2, rd);
2012     }
2013 
2014     public void fsrc2d(Register rs2, Register rd) {
2015         op3(Impdep1, Fsrc2d, null, rs2, rd);
2016     }
2017 
2018     public void fmuls(Register rs1, Register rs2, Register rd) {
2019         op3(Fpop1, Fmuls, rs1, rs2, rd);
2020     }
2021 
2022     public void fsmuld(Register rs1, Register rs2, Register rd) {
2023         op3(Fpop1, Fsmuld, rs1, rs2, rd);
2024     }
2025 
2026     public void fmuld(Register rs1, Register rs2, Register rd) {
2027         op3(Fpop1, Fmuld, rs1, rs2, rd);
2028     }
2029 
2030     public void fnegs(Register rs2, Register rd) {
2031         op3(Fpop1, Fnegs, null, rs2, rd);
2032     }
2033 
2034     public void fnegd(Register rs2, Register rd) {
2035         op3(Fpop1, Fnegd, null, rs2, rd);
2036     }
2037 
2038     /**
2039      * Helper method to determine if the instruction needs the X bit set.
2040      */
2041     private static int getXBit(Op3s op3) {
2042         switch (op3) {
2043             case Sllx:
2044             case Srax:
2045             case Srlx:
2046                 return 1 << 12;
2047             default:
2048                 return 0;
2049         }
2050     }
2051 
2052     public void fstoi(Register rs2, Register rd) {
2053         op3(Fpop1, Fstoi, null, rs2, rd);
2054     }
2055 
2056     public void fstox(Register rs2, Register rd) {
2057         op3(Fpop1, Fstox, null, rs2, rd);
2058     }
2059 
2060     public void fdtox(Register rs2, Register rd) {
2061         op3(Fpop1, Fdtox, null, rs2, rd);
2062     }
2063 
2064     public void fstod(Register rs2, Register rd) {
2065         op3(Fpop1, Fstod, null, rs2, rd);
2066     }
2067 
2068     public void fdtoi(Register rs2, Register rd) {
2069         op3(Fpop1, Fdtoi, null, rs2, rd);
2070     }
2071 
2072     public void fitos(Register rs2, Register rd) {
2073         op3(Fpop1, Fitos, null, rs2, rd);
2074     }
2075 
2076     public void fitod(Register rs2, Register rd) {
2077         op3(Fpop1, Fitod, null, rs2, rd);
2078     }
2079 
2080     public void fxtos(Register rs2, Register rd) {
2081         op3(Fpop1, Fxtos, null, rs2, rd);
2082     }
2083 
2084     public void fxtod(Register rs2, Register rd) {
2085         op3(Fpop1, Fxtod, null, rs2, rd);
2086     }
2087 
2088     public void fzeros(Register rd) {
2089         op3(Impdep1, Fzeros, null, null, rd);
2090     }
2091 
2092     public void fzerod(Register rd) {
2093         op3(Impdep1, Fzerod, null, null, rd);
2094     }
2095 
2096     public void flushw() {
2097         op3(Flushw, g0, g0, g0);
2098     }
2099 
2100     public void fsqrtd(Register rs2, Register rd) {
2101         op3(Fpop1, Fsqrtd, null, rs2, rd);
2102     }
2103 
2104     public void fsqrts(Register rs2, Register rd) {
2105         op3(Fpop1, Fsqrts, null, rs2, rd);
2106     }
2107 
2108     public void fabss(Register rs2, Register rd) {
2109         op3(Fpop1, Fabss, null, rs2, rd);
2110     }
2111 
2112     public void fabsd(Register rs2, Register rd) {
2113         op3(Fpop1, Fabsd, null, rs2, rd);
2114     }
2115 
2116     public void fsubs(Register rs1, Register rs2, Register rd) {
2117         op3(Fpop1, Fsubs, rs1, rs2, rd);
2118     }
2119 
2120     public void fsubd(Register rs1, Register rs2, Register rd) {
2121         op3(Fpop1, Fsubd, rs1, rs2, rd);
2122     }
2123 
2124     // @formatter:off
2125     /**
2126      * Instruction format for fcmp.
2127      * <pre>
2128      * | 10  | --- |cc1|cc0|desc |   rs1   |   opf  | rs2 |
2129      * |31 30|29 27|26 |25 |24 19|18     14|13     5|4   0|
2130      * </pre>
2131      */
2132     // @formatter:on
2133     public void fcmp(CC cc, Opfs opf, Register rs1, Register rs2) {
2134         int a = cc.value;
2135         int b = opf.value << 5 | rs2.encoding;
2136         delaySlotOptimizationPoints.add(position());
2137         fmt10(a, Fpop2.value, rs1.encoding, b);
2138     }
2139 
2140     // @formatter:off
2141     /**
2142      * Instruction format for most arithmetic stuff.
2143      * <pre>
2144      * |  10 | rd  | op3 | rs1 |   b   |
2145      * |31 30|29 25|24 19|18 14|13    0|
2146      * </pre>
2147      */
2148     // @formatter:on
2149     protected void fmt10(int rd, int op3, int rs1, int b) {
2150         fmt(0b10, rd, op3, rs1, b);
2151     }
2152 
2153     // @formatter:off
2154     /**
2155      * Instruction format for most arithmetic stuff.
2156      * <pre>
2157      * |  op | rd  | op3 | rs1 |   b   |
2158      * |31 30|29 25|24 19|18 14|13    0|
2159      * </pre>
2160      */
2161     // @formatter:on
2162     protected void fmt(int op, int rd, int op3, int rs1, int b) {
2163         assert isImm(rd, 5) && isImm(op3, 6) && isImm(b, 14) : String.format("rd: 0x%x op3: 0x%x b: 0x%x", rd, op3, b);
2164         int instr = op << 30 | rd << 25 | op3 << 19 | rs1 << 14 | b;
2165         emitInt(instr);
2166     }
2167 
2168     public void illtrap(int const22) {
2169         fmt00(0, Op2s.Illtrap.value, const22);
2170     }
2171 
2172     public void jmpl(Register rs1, Register rs2, Register rd) {
2173         insertNopAfterCBCond();
2174         op3(Jmpl, rs1, rs2, rd);
2175     }
2176 
2177     /**
2178      * @return Position of the jmpl instruction
2179      */
2180     public int jmpl(Register rs1, int simm13, Register rd) {
2181         insertNopAfterCBCond();
2182         int before = position();
2183         op3(Jmpl, rs1, simm13, rd);
2184         return before;
2185     }
2186 
2187     public void fmovdcc(ConditionFlag cond, CC cc, Register rs2, Register rd) {
2188         fmovcc(cond, cc, rs2, rd, OpfLow.Fmovdcc.value);
2189     }
2190 
2191     public void fmovscc(ConditionFlag cond, CC cc, Register rs2, Register rd) {
2192         fmovcc(cond, cc, rs2, rd, OpfLow.Fmovscc.value);
2193     }
2194 
2195     private void fmovcc(ConditionFlag cond, CC cc, Register rs2, Register rd, int opfLow) {
2196         int opfCC = cc.value;
2197         int a = opfCC << 11 | opfLow << 5 | rs2.encoding;
2198         fmt10(rd.encoding, Fpop2.value, cond.value, a);
2199     }
2200 
2201     public void movcc(ConditionFlag conditionFlag, CC cc, Register rs2, Register rd) {
2202         movcc(conditionFlag, cc, 0, rs2.encoding, rd);
2203     }
2204 
2205     public void movcc(ConditionFlag conditionFlag, CC cc, int simm11, Register rd) {
2206         assert isSimm11(simm11);
2207         movcc(conditionFlag, cc, 1, simm11 & ((1 << 11) - 1), rd);
2208     }
2209 
2210     private void movcc(ConditionFlag conditionFlag, CC cc, int i, int imm, Register rd) {
2211         int cc01 = 0b11 & cc.value;
2212         int cc2 = cc.isFloat ? 0 : 1;
2213         int a = cc2 << 4 | conditionFlag.value;
2214         int b = cc01 << 11 | i << 13 | imm;
2215         fmt10(rd.encoding, Movcc.value, a, b);
2216     }
2217 
2218     public void mulx(Register rs1, Register rs2, Register rd) {
2219         op3(Mulx, rs1, rs2, rd);
2220     }
2221 
2222     public void mulx(Register rs1, int simm13, Register rd) {
2223         op3(Mulx, rs1, simm13, rd);
2224     }
2225 
2226     public void or(Register rs1, Register rs2, Register rd) {
2227         assert isCPURegister(rs1, rs2, rd) : String.format("%s %s %s", rs1, rs2, rd);
2228         op3(Or, rs1, rs2, rd);
2229     }
2230 
2231     public void or(Register rs1, int simm13, Register rd) {
2232         assert isCPURegister(rs1, rd) : String.format("%s %s", rs1, rd);
2233         op3(Or, rs1, simm13, rd);
2234     }
2235 
2236     public void popc(Register rs2, Register rd) {
2237         op3(Popc, g0, rs2, rd);
2238     }
2239 
2240     public void popc(int simm13, Register rd) {
2241         op3(Popc, g0, simm13, rd);
2242     }
2243 
2244     public void prefetch(SPARCAddress addr, Fcn fcn) {
2245         Register rs1 = addr.getBase();
2246         if (addr.getIndex().equals(Register.None)) {
2247             int dis = addr.getDisplacement();
2248             assert isSimm13(dis);
2249             fmt(Prefetch.op.value, fcn.value, Prefetch.value, rs1.encoding, 1 << 13 | dis & ((1 << 13) - 1));
2250         } else {
2251             Register rs2 = addr.getIndex();
2252             fmt(Prefetch.op.value, fcn.value, Prefetch.value, rs1.encoding, rs2.encoding);
2253         }
2254     }
2255 
2256     // A.44 Read State Register
2257 
2258     public void rdpc(Register rd) {
2259         op3(Rd, g5, g0, rd);
2260     }
2261 
2262     public void restore(Register rs1, Register rs2, Register rd) {
2263         op3(Restore, rs1, rs2, rd);
2264     }
2265 
2266     public static final int PC_RETURN_OFFSET = 8;
2267 
2268     public void save(Register rs1, Register rs2, Register rd) {
2269         op3(Save, rs1, rs2, rd);
2270     }
2271 
2272     public void save(Register rs1, int simm13, Register rd) {
2273         op3(Save, rs1, simm13, rd);
2274     }
2275 
2276     public void sdivx(Register rs1, Register rs2, Register rd) {
2277         op3(Sdivx, rs1, rs2, rd);
2278     }
2279 
2280     public void sdivx(Register rs1, int simm13, Register rd) {
2281         op3(Sdivx, rs1, simm13, rd);
2282     }
2283 
2284     public void udivx(Register rs1, Register rs2, Register rd) {
2285         op3(Udivx, rs1, rs2, rd);
2286     }
2287 
2288     public void udivx(Register rs1, int simm13, Register rd) {
2289         op3(Udivx, rs1, simm13, rd);
2290     }
2291 
2292     public void sll(Register rs1, Register rs2, Register rd) {
2293         op3(Sll, rs1, rs2, rd);
2294     }
2295 
2296     public void sll(Register rs1, int shcnt32, Register rd) {
2297         assert isImm(shcnt32, 5);
2298         op3(Sll, rs1, shcnt32, rd);
2299     }
2300 
2301     public void sllx(Register rs1, Register rs2, Register rd) {
2302         op3(Sllx, rs1, rs2, rd);
2303     }
2304 
2305     public void sllx(Register rs1, int shcnt64, Register rd) {
2306         assert isImm(shcnt64, 6);
2307         op3(Sllx, rs1, shcnt64, rd);
2308     }
2309 
2310     public void sra(Register rs1, Register rs2, Register rd) {
2311         op3(Sra, rs1, rs2, rd);
2312     }
2313 
2314     public void sra(Register rs1, int simm13, Register rd) {
2315         op3(Sra, rs1, simm13, rd);
2316     }
2317 
2318     public void srax(Register rs1, Register rs2, Register rd) {
2319         op3(Srax, rs1, rs2, rd);
2320     }
2321 
2322     public void srax(Register rs1, int shcnt64, Register rd) {
2323         assert isImm(shcnt64, 6);
2324         op3(Srax, rs1, shcnt64, rd);
2325     }
2326 
2327     public void srl(Register rs1, Register rs2, Register rd) {
2328         op3(Srl, rs1, rs2, rd);
2329     }
2330 
2331     public void srl(Register rs1, int simm13, Register rd) {
2332         op3(Srl, rs1, simm13, rd);
2333     }
2334 
2335     public void srlx(Register rs1, Register rs2, Register rd) {
2336         op3(Srlx, rs1, rs2, rd);
2337     }
2338 
2339     public void srlx(Register rs1, int shcnt64, Register rd) {
2340         assert isImm(shcnt64, 6);
2341         op3(Srlx, rs1, shcnt64, rd);
2342     }
2343 
2344     public void sub(Register rs1, Register rs2, Register rd) {
2345         op3(Sub, rs1, rs2, rd);
2346     }
2347 
2348     public void sub(Register rs1, int simm13, Register rd) {
2349         op3(Sub, rs1, simm13, rd);
2350     }
2351 
2352     public void subcc(Register rs1, Register rs2, Register rd) {
2353         op3(Subcc, rs1, rs2, rd);
2354     }
2355 
2356     public void subcc(Register rs1, int simm13, Register rd) {
2357         op3(Subcc, rs1, simm13, rd);
2358     }
2359 
2360     public void ta(int trap) {
2361         tcc(Icc, Always, trap);
2362     }
2363 
2364     public void pause() {
2365         // Maybe fmt10(rd=0b1_1011, op3=0b11_0000, rs1=0, i=1, simm13=1), or
2366         // maybe op3(Wr, g0, 1, %pause).
2367         // What should the count be?
2368         GraalError.unimplemented("The SPARC pause instruction is not yet implemented.");
2369     }
2370 
2371     public void tcc(CC cc, ConditionFlag flag, int trap) {
2372         assert isImm(trap, 8);
2373         int b = cc.value << 11;
2374         b |= 1 << 13;
2375         b |= trap;
2376         fmt10(flag.value, Op3s.Tcc.getValue(), 0, b);
2377     }
2378 
2379     public void wrccr(Register rs1, Register rs2) {
2380         op3(Wr, rs1, rs2, g2);
2381     }
2382 
2383     public void wrccr(Register rs1, int simm13) {
2384         op3(Wr, rs1, simm13, g2);
2385     }
2386 
2387     public void xor(Register rs1, Register rs2, Register rd) {
2388         op3(Xor, rs1, rs2, rd);
2389     }
2390 
2391     public void xor(Register rs1, int simm13, Register rd) {
2392         op3(Xor, rs1, simm13, rd);
2393     }
2394 
2395     public void xorcc(Register rs1, Register rs2, Register rd) {
2396         op3(Xorcc, rs1, rs2, rd);
2397     }
2398 
2399     public void xorcc(Register rs1, int simm13, Register rd) {
2400         op3(Xorcc, rs1, simm13, rd);
2401     }
2402 
2403     public void xnor(Register rs1, Register rs2, Register rd) {
2404         op3(Xnor, rs1, rs2, rd);
2405     }
2406 
2407     public void xnor(Register rs1, int simm13, Register rd) {
2408         op3(Xnor, rs1, simm13, rd);
2409     }
2410 
2411     /*
2412      * Load/Store
2413      */
2414     protected void ld(Op3s op3, SPARCAddress addr, Register rd, Asi asi) {
2415         Register rs1 = addr.getBase();
2416         if (!addr.getIndex().equals(Register.None)) {
2417             Register rs2 = addr.getIndex();
2418             if (asi != null) {
2419                 int b = rs2.encoding;
2420                 b |= asi.value << 5;
2421                 fmt(op3.op.value, rd.encoding, op3.value, rs1.encoding, b);
2422             } else {
2423                 op3(op3, rs1, rs2, rd);
2424             }
2425         } else {
2426             int imm = addr.getDisplacement();
2427             op3(op3, rs1, imm, rd);
2428         }
2429     }
2430 
2431     protected void ld(Op3s op3, SPARCAddress addr, Register rd) {
2432         ld(op3, addr, rd, null);
2433     }
2434 
2435     public void lddf(SPARCAddress src, Register dst) {
2436         assert isDoubleFloatRegister(dst) : dst;
2437         ld(Lddf, src, dst);
2438     }
2439 
2440     public void ldf(SPARCAddress src, Register dst) {
2441         assert isSingleFloatRegister(dst) : dst;
2442         ld(Ldf, src, dst);
2443     }
2444 
2445     public void lduh(SPARCAddress src, Register dst) {
2446         assert isCPURegister(dst) : dst;
2447         ld(Lduh, src, dst);
2448     }
2449 
2450     public void ldsh(SPARCAddress src, Register dst) {
2451         assert isCPURegister(dst) : dst;
2452         ld(Ldsh, src, dst);
2453     }
2454 
2455     public void ld(SPARCAddress src, Register dst, int bytes, boolean signExtend) {
2456         if (isCPURegister(dst)) {
2457             if (signExtend) {
2458                 switch (bytes) {
2459                     case 1:
2460                         ld(Ldsb, src, dst);
2461                         break;
2462                     case 2:
2463                         ld(Ldsh, src, dst);
2464                         break;
2465                     case 4:
2466                         ld(Ldsw, src, dst);
2467                         break;
2468                     case 8:
2469                         ld(Ldx, src, dst);
2470                         break;
2471                     default:
2472                         throw new InternalError();
2473                 }
2474             } else {
2475                 switch (bytes) {
2476                     case 1:
2477                         ld(Ldub, src, dst);
2478                         break;
2479                     case 2:
2480                         ld(Lduh, src, dst);
2481                         break;
2482                     case 4:
2483                         ld(Lduw, src, dst);
2484                         break;
2485                     case 8:
2486                         ld(Ldx, src, dst);
2487                         break;
2488                     default:
2489                         throw new InternalError();
2490                 }
2491             }
2492         } else if (isDoubleFloatRegister(dst) && bytes == 8) {
2493             assert !signExtend;
2494             ld(Lddf, src, dst);
2495         } else if (isSingleFloatRegister(dst) && bytes == 4) {
2496             assert !signExtend;
2497             ld(Ldf, src, dst);
2498         } else {
2499             throw new InternalError(String.format("src: %s dst: %s bytes: %d signExtend: %b", src, dst, bytes, signExtend));
2500         }
2501     }
2502 
2503     public void st(Register src, SPARCAddress dst, int bytes) {
2504         if (isCPURegister(src)) {
2505             switch (bytes) {
2506                 case 1:
2507                     st(Stb, src, dst);
2508                     break;
2509                 case 2:
2510                     st(Sth, src, dst);
2511                     break;
2512                 case 4:
2513                     st(Stw, src, dst);
2514                     break;
2515                 case 8:
2516                     st(Stx, src, dst);
2517                     break;
2518                 default:
2519                     throw new InternalError(Integer.toString(bytes));
2520             }
2521         } else if (isDoubleFloatRegister(src) && bytes == 8) {
2522             st(Stdf, src, dst);
2523         } else if (isSingleFloatRegister(src) && bytes == 4) {
2524             st(Stf, src, dst);
2525         } else {
2526             throw new InternalError(String.format("src: %s dst: %s bytes: %d", src, dst, bytes));
2527         }
2528     }
2529 
2530     public void ldub(SPARCAddress src, Register dst) {
2531         assert isCPURegister(dst) : dst;
2532         ld(Ldub, src, dst);
2533     }
2534 
2535     public void ldsb(SPARCAddress src, Register dst) {
2536         assert isCPURegister(dst) : dst;
2537         ld(Ldsb, src, dst);
2538     }
2539 
2540     public void lduw(SPARCAddress src, Register dst) {
2541         assert isCPURegister(dst) : dst;
2542         ld(Lduw, src, dst);
2543     }
2544 
2545     public void ldsw(SPARCAddress src, Register dst) {
2546         assert isCPURegister(dst) : dst;
2547         ld(Ldsw, src, dst);
2548     }
2549 
2550     public void ldx(SPARCAddress src, Register dst) {
2551         assert isCPURegister(dst) : dst;
2552         ld(Ldx, src, dst);
2553     }
2554 
2555     public void ldxa(Register rs1, Register rs2, Register rd, Asi asi) {
2556         assert isCPURegister(rs1, rs2, rd) : format("%s %s %s", rs1, rs2, rd);
2557         ld(Ldxa, new SPARCAddress(rs1, rs2), rd, asi);
2558     }
2559 
2560     public void lduwa(Register rs1, Register rs2, Register rd, Asi asi) {
2561         assert isCPURegister(rs1, rs2, rd) : format("%s %s %s", rs1, rs2, rd);
2562         ld(Lduwa, new SPARCAddress(rs1, rs2), rd, asi);
2563     }
2564 
2565     public void stxa(Register rd, Register rs1, Register rs2, Asi asi) {
2566         assert isCPURegister(rs1, rs2, rd) : format("%s %s %s", rs1, rs2, rd);
2567         ld(Stxa, new SPARCAddress(rs1, rs2), rd, asi);
2568     }
2569 
2570     protected void st(Op3s op3, Register rs1, SPARCAddress dest) {
2571         ld(op3, dest, rs1);
2572     }
2573 
2574     public void stdf(Register rd, SPARCAddress addr) {
2575         assert isDoubleFloatRegister(rd) : rd;
2576         st(Stdf, rd, addr);
2577     }
2578 
2579     public void stf(Register rd, SPARCAddress addr) {
2580         assert isSingleFloatRegister(rd) : rd;
2581         st(Stf, rd, addr);
2582     }
2583 
2584     public void stb(Register rd, SPARCAddress addr) {
2585         assert isCPURegister(rd) : rd;
2586         st(Stb, rd, addr);
2587     }
2588 
2589     public void sth(Register rd, SPARCAddress addr) {
2590         assert isCPURegister(rd) : rd;
2591         st(Sth, rd, addr);
2592     }
2593 
2594     public void stw(Register rd, SPARCAddress addr) {
2595         assert isCPURegister(rd) : rd;
2596         st(Stw, rd, addr);
2597     }
2598 
2599     public void stx(Register rd, SPARCAddress addr) {
2600         assert isCPURegister(rd) : rd;
2601         st(Stx, rd, addr);
2602     }
2603 
2604     public void membar(int barriers) {
2605         op3(Membar, o7, barriers, g0);
2606     }
2607 
2608     public void casa(Register rs1, Register rs2, Register rd, Asi asi) {
2609         ld(Casa, new SPARCAddress(rs1, rs2), rd, asi);
2610     }
2611 
2612     public void casxa(Register rs1, Register rs2, Register rd, Asi asi) {
2613         ld(Casxa, new SPARCAddress(rs1, rs2), rd, asi);
2614     }
2615 
2616     @Override
2617     public InstructionCounter getInstructionCounter() {
2618         return new SPARCInstructionCounter(this);
2619     }
2620 
2621     public void patchAddImmediate(int position, int simm13) {
2622         int inst = getInt(position);
2623         assert SPARCAssembler.isSimm13(simm13) : simm13;
2624         assert (inst >>> 30) == 0b10 : String.format("0x%x", inst);
2625         assert ((inst >>> 18) & 0b11_1111) == 0 : String.format("0x%x", inst);
2626         assert (inst & (1 << 13)) != 0 : String.format("0x%x", inst);
2627         inst = inst & (~((1 << 13) - 1));
2628         inst |= simm13 & ((1 << 12) - 1);
2629         emitInt(inst, position);
2630     }
2631 
2632     public void fpadd32(Register rs1, Register rs2, Register rd) {
2633         op3(Impdep1, Fpadd32, rs1, rs2, rd);
2634     }
2635 
2636     /**
2637      * Does peephole optimization on code generated by this assembler. This method should be called
2638      * at the end of code generation.
2639      * <p>
2640      * It searches for conditional branch instructions which has nop in the delay slot then looks at
2641      * the instruction at branch target; if it is an arithmetic instruction, which does not throw an
2642      * exception (e.g. division), it pulls this instruction into the delay slot and increments the
2643      * displacement by 1.
2644      */
2645     public void peephole() {
2646         for (int i : delaySlotOptimizationPoints) {
2647             optimizeDelaySlot(i);
2648         }
2649     }
2650 
2651     /**
2652      * Optimizes branch instruction <i>b</t> which has a nop in the delay slot. It tries to stuff
2653      * the instruction at <i>b</i>s branch target into the delay slot of <i>b</i>, set the annul
2654      * flag and increments <i>b</i>s disp field by 1;
2655      * <p>
2656      * If <i>b</i>s branch target instruction is an unconditional branch <i>t</i>, then it tries to
2657      * put <i>t</i>s delayed instruction into the delay slot of <i>b</i> and add the <i>t</i>s disp
2658      * field to <i>b</i>s disp field.
2659      */
2660     private void optimizeDelaySlot(int i) {
2661         int delaySlotAbsolute = i + INSTRUCTION_SIZE;
2662         int nextInst = getInt(delaySlotAbsolute);
2663         SPARCOp nextOp = getSPARCOp(nextInst);
2664         if (nextOp instanceof Sethi && Sethi.isNop(nextInst)) {
2665             int inst = getInt(i);
2666             SPARCOp op = getSPARCOp(inst);
2667             if (op instanceof ControlTransferOp && ((ControlTransferOp) op).hasDelaySlot() && ((ControlTransferOp) op).isAnnulable(inst)) {
2668                 ControlTransferOp ctOp = (ControlTransferOp) op;
2669                 int disp = ctOp.getDisp(inst);
2670                 int branchTargetAbsolute = i + disp * INSTRUCTION_SIZE;
2671                 int branchTargetInst = getInt(branchTargetAbsolute);
2672                 SPARCOp branchTargetOp = getSPARCOp(branchTargetInst);
2673                 if (branchTargetOp instanceof Op3Op) {
2674                     Op3s op3 = ((Op3Op) branchTargetOp).getOp3(branchTargetInst);
2675                     if (!op3.throwsException()) {
2676                         inst = ctOp.setDisp(inst, disp + 1); // Increment the offset
2677                         inst = ctOp.setAnnul(inst, true);
2678                         emitInt(inst, i);
2679                         emitInt(branchTargetInst, delaySlotAbsolute);
2680                     }
2681                 } else if (branchTargetOp instanceof ControlTransferOp && !((ControlTransferOp) branchTargetOp).isConditional(branchTargetInst)) {
2682                     // If branchtarget is a unconditional branch
2683                     ControlTransferOp branchTargetOpBranch = (ControlTransferOp) branchTargetOp;
2684                     int btDisp = branchTargetOpBranch.getDisp(branchTargetInst);
2685                     int newDisp = disp + btDisp;
2686                     if (ctOp.isValidDisp(newDisp)) { // Test if we don't exceed field size
2687                         int instAfter = ctOp.setDisp(inst, newDisp);
2688                         instAfter = ctOp.setAnnul(instAfter, true);
2689                         branchTargetInst = getInt(branchTargetAbsolute + INSTRUCTION_SIZE);
2690                         branchTargetOp = getSPARCOp(branchTargetInst);
2691                         if (branchTargetOp instanceof Op3Op && !((Op3Op) branchTargetOp).getOp3(branchTargetInst).throwsException()) {
2692                             emitInt(instAfter, i);
2693                             emitInt(branchTargetInst, delaySlotAbsolute);
2694                         }
2695                     }
2696                 }
2697             }
2698         }
2699     }
2700 }