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