--- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java 2020-05-01 02:30:23.005179233 -0700 +++ /dev/null 2020-03-09 18:57:19.455001459 -0700 @@ -1,2709 +0,0 @@ -/* - * Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -package org.graalvm.compiler.asm.sparc; - -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.CC.Icc; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag.Always; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Add; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Addc; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Addcc; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.And; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Andcc; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Andn; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Andncc; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Casa; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Casxa; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Flushw; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Fpop1; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Fpop2; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Impdep1; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Jmpl; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Lddf; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Ldf; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Ldsb; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Ldsh; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Ldsw; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Ldub; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Lduh; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Lduw; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Lduwa; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Ldx; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Ldxa; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Membar; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Movcc; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Mulx; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Or; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Popc; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Prefetch; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Rd; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Restore; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Save; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Sdivx; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Sll; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Sllx; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Sra; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Srax; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Srl; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Srlx; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Stb; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Stdf; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Stf; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Sth; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Stw; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Stx; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Stxa; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Sub; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Subcc; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Udivx; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Wr; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Xnor; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Xor; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Op3s.Xorcc; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fabsd; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fabss; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Faddd; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fadds; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fdivd; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fdivs; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fdtoi; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fdtos; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fdtox; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fitod; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fitos; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fmovd; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fmovs; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fmuld; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fmuls; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fnegd; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fnegs; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fpadd32; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fsmuld; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fsqrtd; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fsqrts; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fsrc2d; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fsrc2s; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fstod; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fstoi; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fstox; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fsubd; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fsubs; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fxtod; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fxtos; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fzerod; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Fzeros; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Movdtox; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Movstosw; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Movwtos; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.Movxtod; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Opfs.UMulxhi; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Ops.ArithOp; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Ops.LdstOp; -import static java.lang.String.format; -import static jdk.vm.ci.sparc.SPARC.CPU; -import static jdk.vm.ci.sparc.SPARC.FPUd; -import static jdk.vm.ci.sparc.SPARC.FPUs; -import static jdk.vm.ci.sparc.SPARC.g0; -import static jdk.vm.ci.sparc.SPARC.g2; -import static jdk.vm.ci.sparc.SPARC.g5; -import static jdk.vm.ci.sparc.SPARC.g7; -import static jdk.vm.ci.sparc.SPARC.o7; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.graalvm.compiler.asm.Assembler; -import org.graalvm.compiler.asm.BranchTargetOutOfBoundsException; -import org.graalvm.compiler.asm.Label; -import org.graalvm.compiler.core.common.NumUtil; -import org.graalvm.compiler.debug.GraalError; - -import jdk.vm.ci.code.Register; -import jdk.vm.ci.code.TargetDescription; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.PlatformKind; -import jdk.vm.ci.sparc.SPARC; -import jdk.vm.ci.sparc.SPARC.CPUFeature; -import jdk.vm.ci.sparc.SPARCKind; - -/** - * This class implements an assembler that can encode most SPARC instructions. - */ -public abstract class SPARCAssembler extends Assembler { - - /** - * Constructs an assembler for the SPARC architecture. - */ - public SPARCAssembler(TargetDescription target) { - super(target); - } - - /** - * Size of an SPARC assembler instruction in Bytes. - */ - public static final int INSTRUCTION_SIZE = 4; - - /** - * Size in bytes which are cleared by stxa %g0, [%rd] ASI_ST_BLKINIT_PRIMARY. - */ - public static final int BLOCK_ZERO_LENGTH = 64; - - public static final int CCR_ICC_SHIFT = 0; - public static final int CCR_XCC_SHIFT = 4; - public static final int CCR_V_SHIFT = 1; - - public static final int MEMBAR_LOAD_LOAD = 1; - public static final int MEMBAR_STORE_LOAD = 2; - public static final int MEMBAR_LOAD_STORE = 3; - public static final int MEMBAR_STORE_STORE = 4; - - private static final Ops[] OPS; - private static final Op2s[] OP2S; - private static final Op3s[][] OP3S; - - private ArrayList delaySlotOptimizationPoints = new ArrayList<>(5); - - static { - Ops[] ops = Ops.values(); - OPS = new Ops[ops.length]; - for (Ops op : ops) { - OPS[op.value] = op; - } - Op2s[] op2s = Op2s.values(); - OP2S = new Op2s[op2s.length]; - for (Op2s op2 : op2s) { - OP2S[op2.value] = op2; - } - OP3S = new Op3s[2][64]; - for (Op3s op3 : Op3s.values()) { - if (op3.value >= 1 << 6) { - throw new RuntimeException("Error " + op3 + " " + op3.value); - } - OP3S[op3.op.value & 1][op3.value] = op3; - } - } - - public enum Ops { - // @formatter:off - BranchOp(0b00), - CallOp(0b01), - ArithOp(0b10), - LdstOp(0b11); - // @formatter:on - - private final int value; - - Ops(int value) { - this.value = value; - } - - public int getValue() { - return value; - } - - public boolean appliesTo(int instructionWord) { - int opShift = 30; - return (instructionWord >>> opShift) == value; - } - } - - public enum Op2s { - // Checkstyle: stop - // @formatter:off - Illtrap(0b000), - Bpr (0b011), - Fb (0b110), - Fbp (0b101), - Br (0b010), - Bp (0b001), - Cb (0b111), - Sethi (0b100); - // @formatter:on - // Checkstyle: resume - - private final int value; - - Op2s(int value) { - this.value = value; - } - - public int getValue() { - return value; - } - - public static Op2s byValue(int value) { - return OP2S[value]; - } - } - - private static final int COMMUTATIVE = 1; - private static final int BINARY = 2; - private static final int UNARY = 4; - private static final int VOID_IN = 8; - - public enum Op3s { - // Checkstyle: stop - // @formatter:off - Add(0x00, "add", ArithOp, BINARY | COMMUTATIVE), - And(0x01, "and", ArithOp, BINARY | COMMUTATIVE), - Or(0x02, "or", ArithOp, BINARY | COMMUTATIVE), - Xor(0x03, "xor", ArithOp, BINARY | COMMUTATIVE), - Sub(0x04, "sub", ArithOp, BINARY), - Andn(0x05, "andn", ArithOp, BINARY | COMMUTATIVE), - Orn(0x06, "orn", ArithOp, BINARY | COMMUTATIVE), - Xnor(0x07, "xnor", ArithOp, BINARY | COMMUTATIVE), - Addc(0x08, "addc", ArithOp, BINARY | COMMUTATIVE), - Mulx(0x09, "mulx", ArithOp, BINARY | COMMUTATIVE), - Umul(0x0A, "umul", ArithOp, BINARY | COMMUTATIVE), - Smul(0x0B, "smul", ArithOp, BINARY | COMMUTATIVE), - Subc(0x0C, "subc", ArithOp, BINARY), - Udivx(0x0D, "udivx", ArithOp, BINARY), - Udiv(0x0E, "udiv", ArithOp, BINARY), - Sdiv(0x0F, "sdiv", ArithOp, BINARY), - - Addcc(0x10, "addcc", ArithOp, BINARY | COMMUTATIVE), - Andcc(0x11, "andcc", ArithOp, BINARY | COMMUTATIVE), - Orcc(0x12, "orcc", ArithOp, BINARY | COMMUTATIVE), - Xorcc(0x13, "xorcc", ArithOp, BINARY | COMMUTATIVE), - Subcc(0x14, "subcc", ArithOp, BINARY), - Andncc(0x15, "andncc", ArithOp, BINARY | COMMUTATIVE), - Orncc(0x16, "orncc", ArithOp, BINARY | COMMUTATIVE), - Xnorcc(0x17, "xnorcc", ArithOp, BINARY | COMMUTATIVE), - Addccc(0x18, "addccc", ArithOp, BINARY | COMMUTATIVE), - - Umulcc(0x1A, "umulcc", ArithOp, BINARY | COMMUTATIVE), - Smulcc(0x1B, "smulcc", ArithOp, BINARY | COMMUTATIVE), - Subccc(0x1C, "subccc", ArithOp, BINARY), - Udivcc(0x1E, "udivcc", ArithOp, BINARY), - Sdivcc(0x1F, "sdivcc", ArithOp, BINARY), - - Mulscc(0x24, "mulscc", ArithOp, BINARY | COMMUTATIVE), - Sll(0x25, "sll", ArithOp, BINARY), - Sllx(0x25, "sllx", ArithOp, BINARY), - Srl(0x26, "srl", ArithOp, BINARY), - Srlx(0x26, "srlx", ArithOp, BINARY), - Sra(0x27, "srax", ArithOp, BINARY), - Srax(0x27, "srax", ArithOp, BINARY), - Membar(0x28, "membar", ArithOp), - - Flushw(0x2B, "flushw", ArithOp), - Movcc(0x2C, "movcc", ArithOp), - Sdivx(0x2D, "sdivx", ArithOp, BINARY), - Popc(0x2E, "popc", ArithOp, UNARY), - Movr(0x2F, "movr", ArithOp, BINARY), - - Fpop1(0b11_0100, "fpop1", ArithOp), - Fpop2(0b11_0101, "fpop2", ArithOp), - Impdep1(0b11_0110, "impdep1", ArithOp), - Impdep2(0b11_0111, "impdep2", ArithOp), - Jmpl(0x38, "jmpl", ArithOp), - Rett(0x39, "rett", ArithOp), - Trap(0x3a, "trap", ArithOp), - Flush(0x3b, "flush", ArithOp), - Save(0x3c, "save", ArithOp), - Restore(0x3d, "restore", ArithOp), - Retry(0x3e, "retry", ArithOp), - - - Casa(0b111100, "casa", LdstOp), - Casxa(0b111110, "casxa", LdstOp), - Prefetch(0b101101, "prefetch", LdstOp), - Prefetcha(0b111101, "prefetcha", LdstOp), - - Lduw (0b00_0000, "lduw", LdstOp), - Ldub (0b00_0001, "ldub", LdstOp), - Lduh (0b00_0010, "lduh", LdstOp), - Stw (0b00_0100, "stw", LdstOp), - Stb (0b00_0101, "stb", LdstOp), - Sth (0b00_0110, "sth", LdstOp), - Ldsw (0b00_1000, "ldsw", LdstOp), - Ldsb (0b00_1001, "ldsb", LdstOp), - Ldsh (0b00_1010, "ldsh", LdstOp), - Ldx (0b00_1011, "ldx", LdstOp), - Stx (0b00_1110, "stx", LdstOp), - - Ldf (0b10_0000, "ldf", LdstOp), - Ldfsr (0b10_0001, "ldfsr", LdstOp), - Ldaf (0b10_0010, "ldaf", LdstOp), - Lddf (0b10_0011, "lddf", LdstOp), - Stf (0b10_0100, "stf", LdstOp), - Stfsr (0b10_0101, "stfsr", LdstOp), - Staf (0b10_0110, "staf", LdstOp), - Stdf (0b10_0111, "stdf", LdstOp), - - Stba (0b01_0101, "stba", LdstOp), - Stha (0b01_0110, "stha", LdstOp), - Stwa (0b01_0100, "stwa", LdstOp), - Stxa (0b01_1110, "stxa", LdstOp), - - Ldsba (0b01_1001, "ldsba", LdstOp), - Ldsha (0b01_1010, "ldsha", LdstOp), - Ldswa (0b01_1000, "ldswa", LdstOp), - Lduba (0b01_0001, "lduba", LdstOp), - Lduha (0b01_0010, "lduha", LdstOp), - Lduwa (0b01_0000, "lduwa", LdstOp), - - Ldxa (0b01_1011, "ldxa", LdstOp), - - Rd (0b10_1000, "rd", ArithOp), - Wr (0b11_0000, "wr", ArithOp), - - Tcc(0b11_1010, "tcc", ArithOp); - - // @formatter:on - // Checkstyle: resume - - private final int value; - private final String operator; - private final Ops op; - private final int flags; - - Op3s(int value, String name, Ops op) { - this(value, name, op, 0); - } - - Op3s(int value, String name, Ops op, int flags) { - this.value = value; - this.operator = name; - this.op = op; - this.flags = flags; - } - - public int getValue() { - return value; - } - - public String getOperator() { - return operator; - } - - public boolean throwsException() { - if (op == LdstOp) { - return true; - } - switch (this) { - case Udiv: - case Udivx: - case Sdiv: - case Sdivx: - case Udivcc: - case Sdivcc: - return true; - default: - return false; - } - } - - public boolean isBinary() { - return (flags & BINARY) != 0; - } - - public boolean isUnary() { - return (flags & UNARY) != 0; - } - - public boolean isCommutative() { - return (flags & COMMUTATIVE) != 0; - } - } - - public enum Opfs { - // @formatter:off - - Fmovs(0b0_0000_0001, "fmovs", Fpop1, UNARY), - Fmovd(0b0_0000_0010, "fmovd", Fpop1, UNARY), - Fmovq(0b0_0000_0011, "fmovq", Fpop1, UNARY), - Fnegs(0x05, "fnegs", Fpop1, UNARY), - Fnegd(0x06, "fnegd", Fpop1, UNARY), - Fnegq(0x07, "fnegq", Fpop1, UNARY), - Fabss(0x09, "fabss", Fpop1, UNARY), - Fabsd(0x0A, "fabsd", Fpop1, UNARY), - Fabsq(0x0B, "fabsq", Fpop1, UNARY), - - // start VIS1 - Fpadd32(0x52, "fpadd32", Impdep1, BINARY | COMMUTATIVE), - Fzerod(0x60, "fzerod", Impdep1, VOID_IN), - Fzeros(0x61, "fzeros", Impdep1, VOID_IN), - Fsrc2d(0x78, "fsrc2d", Impdep1, UNARY), - Fsrc2s(0x79, "fsrc2s", Impdep1, UNARY), - // end VIS1 - - // start VIS3 - Movdtox(0x110, "movdtox", Impdep1, UNARY), - Movstouw(0x111, "movstouw", Impdep1, UNARY), - Movstosw(0x113, "movstosw", Impdep1, UNARY), - Movxtod(0x118, "movxtod", Impdep1, UNARY), - Movwtos(0b1_0001_1001, "movwtos", Impdep1, UNARY), - UMulxhi(0b0_0001_0110, "umulxhi", Impdep1, BINARY | COMMUTATIVE), - // end VIS3 - - Fadds(0x41, "fadds", Fpop1, BINARY | COMMUTATIVE), - Faddd(0x42, "faddd", Fpop1, BINARY | COMMUTATIVE), - Fsubs(0x45, "fsubs", Fpop1, BINARY), - Fsubd(0x46, "fsubd", Fpop1, BINARY), - Fmuls(0x49, "fmuls", Fpop1, BINARY | COMMUTATIVE), - Fmuld(0x4A, "fmuld", Fpop1, BINARY | COMMUTATIVE), - Fdivs(0x4D, "fdivs", Fpop1, BINARY), - Fdivd(0x4E, "fdivd", Fpop1, BINARY), - - Fsqrts(0x29, "fsqrts", Fpop1, UNARY), - Fsqrtd(0x2A, "fsqrtd", Fpop1, UNARY), - - Fsmuld(0x69, "fsmuld", Fpop1, BINARY | COMMUTATIVE), - - Fstoi(0xD1, "fstoi", Fpop1, UNARY), - Fdtoi(0xD2, "fdtoi", Fpop1, UNARY), - Fstox(0x81, "fstox", Fpop1, UNARY), - Fdtox(0x82, "fdtox", Fpop1, UNARY), - Fxtos(0x84, "fxtos", Fpop1, UNARY), - Fxtod(0x88, "fxtod", Fpop1, UNARY), - Fitos(0xC4, "fitos", Fpop1, UNARY), - Fdtos(0xC6, "fdtos", Fpop1, UNARY), - Fitod(0xC8, "fitod", Fpop1, UNARY), - Fstod(0xC9, "fstod", Fpop1, UNARY), - - - Fcmps(0x51, "fcmps", Fpop2, BINARY), - Fcmpd(0x52, "fcmpd", Fpop2, BINARY); - - // @formatter:on - - private final int value; - private final String operator; - private final Op3s op3; - private final int flags; - - Opfs(int value, String op, Op3s op3, int flags) { - this.value = value; - this.operator = op; - this.op3 = op3; - this.flags = flags; - } - - public int getValue() { - return value; - } - - public String getOperator() { - return operator; - } - - public boolean isBinary() { - return (flags & BINARY) != 0; - } - - public boolean isUnary() { - return (flags & UNARY) != 0; - } - - public boolean isCommutative() { - return (flags & COMMUTATIVE) != 0; - } - } - - public enum OpfLow { - Fmovscc(0b00_0001, "fmovscc", Fpop2), - Fmovdcc(0b00_0010, "fmovdcc", Fpop2); - - private final int value; - private final String operator; - private final Op3s op3; - - OpfLow(int value, String op, Op3s op3) { - this.value = value; - this.operator = op; - this.op3 = op3; - } - - @Override - public String toString() { - return operator; - } - } - - public enum Annul { - ANNUL(1), - NOT_ANNUL(0); - - public final int flag; - - Annul(int flag) { - this.flag = flag; - } - } - - public enum BranchPredict { - PREDICT_TAKEN(1), - PREDICT_NOT_TAKEN(0); - - public final int flag; - - BranchPredict(int flag) { - this.flag = flag; - } - } - - public enum MembarMask { - // @formatter:off - - StoreStore(1 << 3, "storestore"), - LoadStore(1 << 2, "loadstore"), - StoreLoad(1 << 1, "storeload"), - LoadLoad(1 << 0, "loadload"), - Sync(1 << 6, "sync"), - MemIssue(1 << 5, "memissue"), - LookAside(1 << 4, "lookaside"); - - // @formatter:on - - private final int value; - private final String operator; - - MembarMask(int value, String op) { - this.value = value; - this.operator = op; - } - - public int getValue() { - return value | 0x2000; - } - - public String getOperator() { - return operator; - } - } - - /** - * Condition Codes to use for instruction. - */ - public enum CC { - // @formatter:off - /** - * Condition is considered as 32bit operation condition. - */ - Icc(0b00, "icc", false), - /** - * Condition is considered as 64bit operation condition. - */ - Xcc(0b10, "xcc", false), - Fcc0(0b00, "fcc0", true), - Fcc1(0b01, "fcc1", true), - Fcc2(0b10, "fcc2", true), - Fcc3(0b11, "fcc3", true); - - // @formatter:on - - private final int value; - private final String operator; - private boolean isFloat; - - CC(int value, String op, boolean isFloat) { - this.value = value; - this.operator = op; - this.isFloat = isFloat; - } - - public int getValue() { - return value; - } - - public int getOpfCCValue() { - /* - * In the opf_cc encoding for FMOVcc, the third bit is set to indicate icc/xcc. - */ - return (isFloat ? value : (value | 0x4)); - } - - public String getOperator() { - return operator; - } - - public static CC forKind(PlatformKind kind) { - if (kind.equals(SPARCKind.XWORD)) { - return Xcc; - } else if (kind.equals(SPARCKind.WORD)) { - return Icc; - } else if (kind.equals(SPARCKind.SINGLE) || kind.equals(SPARCKind.DOUBLE)) { - return Fcc0; - } else { - throw new IllegalArgumentException("Unknown kind: " + kind); - } - } - } - - public enum ConditionFlag { - // @formatter:off - - // for FBfcc & FBPfcc instruction - F_Never(0, "f_never"), - F_NotEqual(1, "f_notEqual"), - F_LessOrGreater(2, "f_lessOrGreater"), - F_UnorderedOrLess(3, "f_unorderedOrLess"), - F_Less(4, "f_less"), - F_UnorderedOrGreater(5, "f_unorderedOrGreater"), - F_Greater(6, "f_greater"), - F_Unordered(7, "f_unordered"), - F_Always(8, "f_always"), - F_Equal(9, "f_equal"), - F_UnorderedOrEqual(10, "f_unorderedOrEqual"), - F_GreaterOrEqual(11, "f_greaterOrEqual"), - F_UnorderedGreaterOrEqual(12, "f_unorderedGreaterOrEqual"), - F_LessOrEqual(13, "f_lessOrEqual"), - F_UnorderedOrLessOrEqual(14, "f_unorderedOrLessOrEqual"), - F_Ordered(15, "f_ordered"), - - // for integers - Never(0, "never"), - Equal(1, "equal", true), - Zero(1, "zero"), - LessEqual(2, "lessEqual", true), - Less(3, "less", true), - LessEqualUnsigned(4, "lessEqualUnsigned", true), - LessUnsigned(5, "lessUnsigned", true), - CarrySet(5, "carrySet"), - Negative(6, "negative", true), - OverflowSet(7, "overflowSet", true), - Always(8, "always"), - NotEqual(9, "notEqual", true), - NotZero(9, "notZero"), - Greater(10, "greater", true), - GreaterEqual(11, "greaterEqual", true), - GreaterUnsigned(12, "greaterUnsigned", true), - GreaterEqualUnsigned(13, "greaterEqualUnsigned", true), - CarryClear(13, "carryClear"), - Positive(14, "positive", true), - OverflowClear(15, "overflowClear", true); - - // @formatter:on - - private final int value; - private final String operator; - private boolean forCBcond = false; - - ConditionFlag(int value, String op) { - this(value, op, false); - } - - ConditionFlag(int value, String op, boolean cbcond) { - this.value = value; - this.operator = op; - this.forCBcond = cbcond; - } - - public boolean isCBCond() { - return forCBcond; - } - - public int getValue() { - return value; - } - - public String getOperator() { - return operator; - } - - public ConditionFlag negate() { - //@formatter:off - switch (this) { - case F_Never : return F_Always; - case F_Always : return F_Never; - case F_NotEqual : return F_Equal; - case F_Equal : return F_NotEqual; - case F_LessOrGreater : return F_UnorderedOrEqual; - case F_UnorderedOrEqual : return F_LessOrGreater; - case F_Less : return F_UnorderedGreaterOrEqual; - case F_UnorderedGreaterOrEqual: return F_Less; - case F_LessOrEqual : return F_UnorderedOrGreater; - case F_UnorderedOrGreater : return F_LessOrEqual; - case F_Greater : return F_UnorderedOrLessOrEqual; - case F_UnorderedOrLessOrEqual : return F_Greater; - case F_GreaterOrEqual : return F_UnorderedOrLess; - case F_UnorderedOrLess : return F_GreaterOrEqual; - case F_Unordered : return F_Ordered; - case F_Ordered : return F_Unordered; - case Never : return Always; - case Always : return Never; - case Equal : return NotEqual; - case NotEqual : return Equal; - case Zero : return NotZero; - case NotZero : return Zero; - case LessEqual : return Greater; - case Greater : return LessEqual; - case Less : return GreaterEqual; - case GreaterEqual : return Less; - case LessEqualUnsigned : return GreaterUnsigned; - case GreaterUnsigned : return LessEqualUnsigned; - case LessUnsigned : return GreaterEqualUnsigned; - case GreaterEqualUnsigned : return LessUnsigned; - case CarrySet : return CarryClear; - case CarryClear : return CarrySet; - case Negative : return Positive; - case Positive : return Negative; - case OverflowSet : return OverflowClear; - case OverflowClear : return OverflowSet; - default: - throw new InternalError(); - } - //@formatter:on - } - - public ConditionFlag mirror() { - switch (this) { - //@formatter:off - case F_Less : return F_Greater; - case F_Greater : return F_Less; - case F_LessOrEqual : return F_GreaterOrEqual; - case F_UnorderedGreaterOrEqual: return F_UnorderedOrLessOrEqual; - case F_UnorderedOrGreater : return F_UnorderedOrLess; - case F_UnorderedOrLessOrEqual : return F_UnorderedGreaterOrEqual; - case F_GreaterOrEqual : return F_LessOrEqual; - case F_UnorderedOrLess : return F_UnorderedOrGreater; - case LessEqual : return GreaterEqual; - case Greater : return Less; - case Less : return Greater; - case GreaterEqual : return LessEqual; - case LessEqualUnsigned : return GreaterEqualUnsigned; - case GreaterUnsigned : return LessUnsigned; - case LessUnsigned : return GreaterUnsigned; - case GreaterEqualUnsigned : return LessEqualUnsigned; - default: - return this; - //@formatter:on - } - } - - } - - public enum RCondition { - // @formatter:off - - Rc_z(0b001, "rc_z"), - Rc_lez(0b010, "rc_lez"), - Rc_lz(0b011, "rc_lz"), - Rc_nz(0b101, "rc_nz"), - Rc_gz(0b110, "rc_gz"), - Rc_gez(0b111, "rc_gez"), - Rc_last(Rc_gez.getValue(), "rc_last"); - - // @formatter:on - - private final int value; - private final String operator; - - RCondition(int value, String op) { - this.value = value; - this.operator = op; - } - - public int getValue() { - return value; - } - - public String getOperator() { - return operator; - } - } - - /** - * Represents the Address Space Identifier defined in the SPARC architecture. - */ - public enum Asi { - // @formatter:off - - INVALID(-1), - ASI_PRIMARY(0x80), - ASI_PRIMARY_NOFAULT(0x82), - ASI_PRIMARY_LITTLE(0x88), - // Block initializing store - ASI_ST_BLKINIT_PRIMARY(0xE2), - // Most-Recently-Used (MRU) BIS variant - ASI_ST_BLKINIT_MRU_PRIMARY(0xF2); - - // @formatter:on - - private final int value; - - Asi(int value) { - this.value = value; - } - - public int getValue() { - return value; - } - - public boolean isValid() { - return value != INVALID.getValue(); - } - } - - public enum Fcn { - SeveralWritesAndPossiblyReads(2), - SeveralReadsWeak(0), - OneRead(1), - OneWrite(3), - Page(4), - NearestUnifiedCache(17), - SeveralReadsStrong(20), - OneReadStrong(21), - SeveralWritesAndPossiblyReadsStrong(22), - OneWriteStrong(23); - - private final int value; - - Fcn(int value) { - this.value = value; - } - - public int getValue() { - return value; - } - } - - /** - * Specifies various bit fields used in SPARC instructions. - */ - @SuppressWarnings("unused") - public abstract static class BitSpec { - private static final BitSpec op = new ContinousBitSpec(31, 30, "op"); - private static final BitSpec op2 = new ContinousBitSpec(24, 22, "op2"); - private static final BitSpec op3 = new ContinousBitSpec(24, 19, "op3"); - private static final BitSpec opf = new ContinousBitSpec(13, 5, "opf"); - private static final BitSpec opfLow = new ContinousBitSpec(10, 5, "opfLow"); - private static final BitSpec opfCC = new ContinousBitSpec(13, 11, "opfCC"); - private static final BitSpec opfCond = new ContinousBitSpec(17, 14, "opfCond"); - private static final BitSpec rd = new ContinousBitSpec(29, 25, "rd"); - private static final BitSpec rs1 = new ContinousBitSpec(18, 14, "rs1"); - private static final BitSpec rs2 = new ContinousBitSpec(4, 0, "rs2"); - private static final BitSpec simm13 = new ContinousBitSpec(12, 0, true, "simm13"); - private static final BitSpec shcnt32 = new ContinousBitSpec(4, 0, "shcnt32"); - private static final BitSpec shcnt64 = new ContinousBitSpec(5, 0, "shcnt64"); - private static final BitSpec imm22 = new ContinousBitSpec(21, 0, "imm22"); - private static final BitSpec immAsi = new ContinousBitSpec(12, 5, "immASI"); - private static final BitSpec i = new ContinousBitSpec(13, 13, "i"); - private static final BitSpec disp19 = new ContinousBitSpec(18, 0, true, "disp19"); - private static final BitSpec disp22 = new ContinousBitSpec(21, 0, true, "disp22"); - private static final BitSpec disp30 = new ContinousBitSpec(29, 0, true, "disp30"); - private static final BitSpec a = new ContinousBitSpec(29, 29, "a"); - private static final BitSpec p = new ContinousBitSpec(19, 19, "p"); - private static final BitSpec x = new ContinousBitSpec(12, 12, "x"); - private static final BitSpec cond = new ContinousBitSpec(28, 25, "cond"); - private static final BitSpec rcond = new ContinousBitSpec(27, 25, "rcond"); - private static final BitSpec cc = new ContinousBitSpec(21, 20, "cc"); - private static final BitSpec fcc = new ContinousBitSpec(26, 25, "cc"); - private static final BitSpec d16lo = new ContinousBitSpec(13, 0, "d16lo"); - private static final BitSpec d16hi = new ContinousBitSpec(21, 20, true, "d16hi"); - private static final BitSpec d16 = new CompositeBitSpec(d16hi, d16lo); - // Movcc - private static final BitSpec movccLo = new ContinousBitSpec(12, 11, "cc_lo"); - private static final BitSpec movccHi = new ContinousBitSpec(18, 18, "cc_hi"); - private static final BitSpec movccCond = new ContinousBitSpec(17, 14, "cond"); - private static final BitSpec simm11 = new ContinousBitSpec(10, 0, true, "simm11"); - - // CBCond - private static final BitSpec cLo = new ContinousBitSpec(27, 25, "cLo"); - private static final BitSpec cHi = new ContinousBitSpec(29, 29, "cHi"); - private static final BitSpec c = new CompositeBitSpec(cHi, cLo); - private static final BitSpec cbcond = new ContinousBitSpec(28, 28, "cbcond"); - private static final BitSpec cc2 = new ContinousBitSpec(21, 21, "cc2"); - private static final BitSpec d10Lo = new ContinousBitSpec(12, 5, "d10Lo"); - private static final BitSpec d10Hi = new ContinousBitSpec(20, 19, true, "d10Hi"); - private static final BitSpec d10 = new CompositeBitSpec(d10Hi, d10Lo); - private static final BitSpec simm5 = new ContinousBitSpec(4, 0, true, "simm5"); - - protected final boolean signExtend; - - public BitSpec(boolean signExtend) { - super(); - this.signExtend = signExtend; - } - - public final boolean isSignExtend() { - return signExtend; - } - - public abstract int setBits(int word, int value); - - public abstract int getBits(int word); - - public abstract int getWidth(); - - public abstract boolean valueFits(int value); - } - - public static final class ContinousBitSpec extends BitSpec { - private final int hiBit; - private final int lowBit; - private final int width; - private final int mask; - private final String name; - - public ContinousBitSpec(int hiBit, int lowBit, String name) { - this(hiBit, lowBit, false, name); - } - - public ContinousBitSpec(int hiBit, int lowBit, boolean signExt, String name) { - super(signExt); - this.hiBit = hiBit; - this.lowBit = lowBit; - this.width = hiBit - lowBit + 1; - mask = ((1 << width) - 1) << lowBit; - this.name = name; - } - - @Override - public int setBits(int word, int value) { - assert valueFits(value) : String.format("Value 0x%x for field %s does not fit.", value, this); - return (word & ~mask) | ((value << lowBit) & mask); - } - - @Override - public int getBits(int word) { - if (signExtend) { - return ((word & mask) << (31 - hiBit)) >> (32 - width); - } else { - return (word & mask) >>> lowBit; - } - } - - @Override - public int getWidth() { - return width; - } - - @Override - public String toString() { - return String.format("%s [%d:%d]", name, hiBit, lowBit); - } - - @Override - public boolean valueFits(int value) { - if (signExtend) { - return isSimm(value, getWidth()); - } else { - return isImm(value, getWidth()); - } - } - } - - public static final class CompositeBitSpec extends BitSpec { - private final BitSpec left; - private final int leftWidth; - private final BitSpec right; - private final int rightWidth; - private final int width; - - public CompositeBitSpec(BitSpec left, BitSpec right) { - super(left.isSignExtend()); - assert !right.isSignExtend() : String.format("Right field %s must not be sign extended", right); - this.left = left; - this.leftWidth = left.getWidth(); - this.right = right; - this.rightWidth = right.getWidth(); - this.width = leftWidth + rightWidth; - } - - @Override - public int getBits(int word) { - int l = left.getBits(word); - int r = right.getBits(word); - return (l << rightWidth) | r; - } - - @Override - public int setBits(int word, int value) { - int l = leftBits(value); - int r = rightBits(value); - return left.setBits(right.setBits(word, r), l); - } - - private int leftBits(int value) { - return getBits(value, width - 1, rightWidth, signExtend); - } - - private int rightBits(int value) { - return getBits(value, rightWidth - 1, 0, false); - } - - @Override - public int getWidth() { - return width; - } - - @Override - public String toString() { - return String.format("CompositeBitSpec[%s, %s]", left, right); - } - - @Override - public boolean valueFits(int value) { - int l = leftBits(value); - int r = rightBits(value); - return left.valueFits(l) && right.valueFits(r); - } - - private static int getBits(int inst, int hiBit, int lowBit, boolean signExtended) { - int shifted = inst >> lowBit; - if (signExtended) { - return shifted; - } else { - return shifted & ((1 << (hiBit - lowBit + 1)) - 1); - } - } - } - - public static class BitKey { - private final BitSpec spec; - private final int value; - - public BitKey(BitSpec spec, int value) { - super(); - this.spec = spec; - this.value = value; - } - - @Override - public String toString() { - return String.format("BitKey %s=%s", spec, value); - } - } - - /** - * Represents a prefix tree of {@link BitSpec} objects to find the most accurate SPARCOp. - */ - public static final class BitKeyIndex { - private final BitSpec spec; - private final Map nodes; - private SPARCOp op; - - public BitKeyIndex(SPARCOp op) { - assert op != null; - this.op = op; - this.nodes = null; - this.spec = null; - } - - public BitKeyIndex(BitSpec spec) { - assert spec != null; - this.op = null; - this.nodes = new HashMap<>(4); - this.spec = spec; - } - - /** - * Adds operation to the index. - * - * @param keys Ordered by the importance - * @param operation Operation represented by this list of keys - */ - private void addOp(List keys, SPARCOp operation) { - assert keys.size() > 0; - BitKey[] firstKeys = keys.get(0); - for (BitKey first : firstKeys) { - assert first.spec.equals(spec) : first.spec + " " + spec; - BitKeyIndex node; - if (keys.size() == 1) { - if (nodes.containsKey(first.value)) { - node = nodes.get(first.value); - assert node.op == null : node + " " + keys; - node.op = operation; - } else { - assert !nodes.containsKey(first.value) : "Index must be unique. Existing key: " + nodes.get(first.value); - node = new BitKeyIndex(operation); - } - } else { - node = nodes.get(first.value); - BitKey[] next = keys.get(1); - if (node == null) { - for (int i = 1; i < next.length; i++) { - assert next[i - 1].spec.equals(next[i].spec) : "All spec on this node must equal"; - } - node = new BitKeyIndex(next[0].spec); - } - node.addOp(keys.subList(1, keys.size()), operation); - } - nodes.put(first.value, node); - } - } - - /** - * Finds the best matching {@link SPARCOp} for this instruction. - */ - public SPARCOp find(int inst) { - if (nodes != null) { - int key = spec.getBits(inst); - BitKeyIndex sub = nodes.get(key); - if (sub == null) { - if (op != null) { - return op; - } else { - throw new RuntimeException(String.format("%s 0x%x, 0x%x %s", spec, inst, key, nodes)); - } - } - return sub.find(inst); - } else { - return this.op; - } - } - - @Override - public String toString() { - return this.op == null ? this.spec + ": " + this.nodes : this.op.toString(); - } - } - - public static final Bpcc BPCC = new Bpcc(Op2s.Bp); - public static final Bpcc FBPCC = new Bpcc(Op2s.Fbp); - public static final CBCond CBCOND = new CBCond(); - public static final Bpr BPR = new Bpr(); - public static final Br BR = new Br(); - public static final Sethi SETHI = new Sethi(); - public static final FMOVcc FMOVSCC = new FMOVcc(OpfLow.Fmovscc); - public static final FMOVcc FMOVDCC = new FMOVcc(OpfLow.Fmovdcc); - public static final MOVicc MOVICC = new MOVicc(); - public static final OpfOp OPF = new OpfOp(); - public static final Op3Op OP3 = new Op3Op(); - public static final SPARCOp LDST = new SPARCOp(Ops.LdstOp); - public static final SPARCOp BRANCH = new SPARCOp(Ops.BranchOp); - public static final SPARCOp CALL = new SPARCOp(Ops.CallOp); - private static final BitKeyIndex INDEX = new BitKeyIndex(BitSpec.op); - - static { - for (SPARCOp op : SPARCOp.OPS) { - INDEX.addOp(op.getKeys(), op); - } - } - - public static SPARCOp getSPARCOp(int inst) { - return INDEX.find(inst); - } - - /** - * Represents a class of SPARC instruction and gives methods to modify its fields. - */ - public static class SPARCOp { - private final Ops op; - private final BitKey opKey; - private List keyFields; - private static final List OPS = new ArrayList<>(); - - public SPARCOp(Ops op) { - super(); - this.op = op; - this.opKey = new BitKey(BitSpec.op, op.value); - OPS.add(this); - } - - protected int setBits(int word) { - return BitSpec.op.setBits(word, op.value); - } - - public boolean match(int inst) { - for (BitKey[] keys : keyFields) { - for (BitKey k : keys) { - if (k.spec.getBits(inst) != k.value) { - return false; - } - } - } - return true; - } - - protected List getKeys() { - if (keyFields == null) { - keyFields = new ArrayList<>(4); - keyFields.add(new BitKey[]{opKey}); - } - return keyFields; - } - - public Ops getOp(int inst) { - return SPARCAssembler.OPS[BitSpec.op.getBits(inst)]; - } - - @Override - public String toString() { - String name = getClass().getName(); - name = name.substring(name.lastIndexOf(".") + 1); - return name + "[op: " + op + "]"; - } - } - - /** - * Base class for control transfer operations; provides access to the disp field. - */ - public abstract static class ControlTransferOp extends SPARCOp { - private final Op2s op2; - private final boolean delaySlot; - private final BitSpec disp; - private final BitKey[] op2Key; - - private ControlTransferOp(Ops op, Op2s op2, boolean delaySlot, BitSpec disp) { - super(op); - this.op2 = op2; - this.delaySlot = delaySlot; - this.disp = disp; - this.op2Key = new BitKey[]{new BitKey(BitSpec.op2, op2.value)}; - } - - public boolean hasDelaySlot() { - return delaySlot; - } - - @Override - protected int setBits(int word) { - return BitSpec.op2.setBits(super.setBits(word), op2.value); - } - - protected int setDisp(int inst, SPARCMacroAssembler masm, Label lab) { - if (lab.isBound()) { - int d = (lab.position() - masm.position()) / 4; - return setDisp(inst, d); - } else { - masm.patchUnbound(lab); - return inst; - } - } - - public int setDisp(int inst, int d) { - assert this.match(inst); - if (!isValidDisp(d)) { - throw new BranchTargetOutOfBoundsException(true, "Too large displacement 0x%x in field %s in instruction %s", d, this.disp, this); - } - return this.disp.setBits(inst, d); - } - - public boolean isValidDisp(int d) { - return this.disp.valueFits(d); - } - - public int setAnnul(int inst, boolean a) { - return BitSpec.a.setBits(inst, a ? 1 : 0); - } - - @Override - protected List getKeys() { - List keys = super.getKeys(); - keys.add(op2Key); - return keys; - } - - public int getDisp(int inst) { - return this.disp.getBits(inst); - } - - public abstract boolean isAnnulable(int inst); - - public abstract boolean isConditional(int inst); - } - - public static final class Bpcc extends ControlTransferOp { - public Bpcc(Op2s op2) { - super(Ops.BranchOp, op2, true, BitSpec.disp19); - } - - public void emit(SPARCMacroAssembler masm, CC cc, ConditionFlag cf, Annul annul, BranchPredict p, Label lab) { - int inst = setBits(0); - inst = BitSpec.a.setBits(inst, annul.flag); - inst = BitSpec.cond.setBits(inst, cf.value); - inst = BitSpec.cc.setBits(inst, cc.value); - inst = BitSpec.p.setBits(inst, p.flag); - masm.insertNopAfterCBCond(); - masm.emitInt(setDisp(inst, masm, lab)); - } - - @Override - public boolean isAnnulable(int inst) { - return isConditional(inst); - } - - @Override - public boolean isConditional(int inst) { - int cond = BitSpec.cond.getBits(inst); - return cond != ConditionFlag.Always.value && cond != ConditionFlag.Never.value; - } - } - - public static final class Br extends ControlTransferOp { - public Br() { - super(Ops.BranchOp, Op2s.Br, true, BitSpec.disp22); - } - - @Override - public boolean isAnnulable(int inst) { - return isConditional(inst); - } - - @Override - public boolean isConditional(int inst) { - int cond = BitSpec.cond.getBits(inst); - return cond != ConditionFlag.Always.value && cond != ConditionFlag.Never.value; - } - - public void emit(SPARCMacroAssembler masm, ConditionFlag cond, Annul a, Label lab) { - int inst = setBits(0); - inst = BitSpec.cond.setBits(inst, cond.value); - inst = BitSpec.a.setBits(inst, a.flag); - masm.insertNopAfterCBCond(); - masm.emitInt(setDisp(inst, masm, lab)); - } - } - - public static final class Bpr extends ControlTransferOp { - private static final BitKey CBCOND_KEY = new BitKey(BitSpec.cbcond, 0); - - public Bpr() { - super(Ops.BranchOp, Op2s.Bpr, true, BitSpec.d16); - } - - public void emit(SPARCMacroAssembler masm, RCondition rcond, Annul a, BranchPredict p, Register rs1, Label lab) { - int inst = setBits(0); - inst = BitSpec.rcond.setBits(inst, rcond.value); - inst = BitSpec.a.setBits(inst, a.flag); - inst = BitSpec.p.setBits(inst, p.flag); - inst = BitSpec.rs1.setBits(inst, rs1.encoding); - masm.insertNopAfterCBCond(); - masm.emitInt(setDisp(inst, masm, lab)); - } - - @Override - protected List getKeys() { - List keys = super.getKeys(); - keys.add(new BitKey[]{CBCOND_KEY}); - return keys; - } - - @Override - public boolean isAnnulable(int inst) { - return isConditional(inst); - } - - @Override - public boolean isConditional(int inst) { - int cond = BitSpec.cond.getBits(inst); - return cond != ConditionFlag.Always.value && cond != ConditionFlag.Never.value; - } - } - - public static final class CBCond extends ControlTransferOp { - private static final BitKey CBCOND_KEY = new BitKey(BitSpec.cbcond, 1); - - private CBCond() { - super(Ops.BranchOp, Op2s.Bpr, false, BitSpec.d10); - } - - @Override - protected List getKeys() { - List keys = super.getKeys(); - keys.add(new BitKey[]{CBCOND_KEY}); - return keys; - } - - public void emit(SPARCMacroAssembler masm, ConditionFlag cf, boolean cc2, Register rs1, Register rs2, Label lab) { - int inst = setBits(0, cf, cc2, rs1); - inst = BitSpec.rs2.setBits(inst, rs2.encoding); - inst = BitSpec.i.setBits(inst, 0); - masm.insertNopAfterCBCond(); - emit(masm, lab, inst); - } - - public void emit(SPARCMacroAssembler masm, ConditionFlag cf, boolean cc2, Register rs1, int simm5, Label lab) { - int inst = setBits(0, cf, cc2, rs1); - inst = BitSpec.simm5.setBits(inst, simm5); - inst = BitSpec.i.setBits(inst, 1); - emit(masm, lab, inst); - } - - private void emit(SPARCMacroAssembler masm, Label lab, int baseInst) { - int inst = baseInst; - masm.insertNopAfterCBCond(); - masm.emitInt(setDisp(inst, masm, lab)); - } - - private int setBits(int base, ConditionFlag cf, boolean cc2, Register rs1) { - int inst = super.setBits(base); - inst = BitSpec.rs1.setBits(inst, rs1.encoding); - inst = BitSpec.cc2.setBits(inst, cc2 ? 1 : 0); - inst = BitSpec.c.setBits(inst, cf.value); - return BitSpec.cbcond.setBits(inst, 1); - } - - @Override - public boolean isAnnulable(int inst) { - return false; - } - - @Override - public boolean isConditional(int inst) { - return true; - } - } - - public static class Op2Op extends SPARCOp { - private final Op2s op2; - private final BitKey op2Key; - - public Op2Op(Ops op, Op2s op2) { - super(op); - this.op2 = op2; - op2Key = new BitKey(BitSpec.op2, op2.value); - } - - @Override - protected int setBits(int word) { - int result = super.setBits(word); - return BitSpec.op2.setBits(result, op2.value); - } - - @Override - protected List getKeys() { - List keys = super.getKeys(); - keys.add(new BitKey[]{op2Key}); - return keys; - } - } - - public static final class Sethi extends Op2Op { - public Sethi() { - super(Ops.BranchOp, Op2s.Sethi); - } - - public static Register getRS1(int word) { - int regNum = BitSpec.rs1.getBits(word); - return SPARC.cpuRegisters.get(regNum); - } - - public static int getImm22(int word) { - return BitSpec.imm22.getBits(word); - } - - public static boolean isNop(int inst) { - return getRS1(inst).equals(g0) && getImm22(inst) == 0; - } - } - - public static final class Op3Op extends SPARCOp { - public Op3Op() { - super(ArithOp); - } - - public Op3s getOp3(int inst) { - assert match(inst); - return OP3S[ArithOp.value & 1][BitSpec.op3.getBits(inst)]; - } - - public static void emit(SPARCMacroAssembler masm, Op3s opcode, Register rs1, Register rs2, Register rd) { - int instruction = setBits(0, opcode, rs1, rd); - instruction = BitSpec.rs2.setBits(instruction, rs2.encoding); - instruction = BitSpec.i.setBits(instruction, 0); - masm.emitInt(instruction); - } - - public static void emit(SPARCMacroAssembler masm, Op3s opcode, Register rs1, int simm13, Register rd) { - int instruction = setBits(0, opcode, rs1, rd); - instruction = BitSpec.i.setBits(instruction, 1); - BitSpec immediateSpec; - switch (opcode) { - case Sllx: - case Srlx: - case Srax: - immediateSpec = BitSpec.shcnt64; - break; - case Sll: - case Srl: - case Sra: - immediateSpec = BitSpec.shcnt32; - break; - default: - immediateSpec = BitSpec.simm13; - break; - } - instruction = immediateSpec.setBits(instruction, simm13); - masm.emitInt(instruction); - } - - private static int setBits(int instruction, Op3s op3, Register rs1, Register rd) { - assert op3.op.equals(ArithOp); - int tmp = BitSpec.op3.setBits(instruction, op3.value); - switch (op3) { - case Sllx: - case Srlx: - case Srax: - tmp = BitSpec.x.setBits(tmp, 1); - break; - } - tmp = BitSpec.op.setBits(tmp, op3.op.value); - tmp = BitSpec.rd.setBits(tmp, rd.encoding); - return BitSpec.rs1.setBits(tmp, rs1.encoding); - } - } - - /** - * Used for interfacing FP and GP conditional move instructions. - */ - public interface CMOV { - void emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, Register rs2, Register rd); - - void emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, int simm11, Register rd); - } - - public static final class MOVicc extends SPARCOp implements CMOV { - private static final Op3s op3 = Movcc; - - public MOVicc() { - super(ArithOp); - } - - @Override - public void emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, Register rs2, Register rd) { - int inst = setBits(0, condition, cc, rd); - inst = BitSpec.rs2.setBits(inst, rs2.encoding()); - masm.emitInt(inst); - } - - @Override - public void emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, int simm11, Register rd) { - int inst = setBits(0, condition, cc, rd); - inst = BitSpec.i.setBits(inst, 1); - inst = BitSpec.simm11.setBits(inst, simm11); - masm.emitInt(inst); - } - - protected int setBits(int word, ConditionFlag condition, CC cc, Register rd) { - int inst = super.setBits(word); - inst = BitSpec.rd.setBits(inst, rd.encoding()); - inst = BitSpec.op3.setBits(inst, op3.value); - inst = BitSpec.movccCond.setBits(inst, condition.value); - inst = BitSpec.movccLo.setBits(inst, cc.value); - return BitSpec.movccHi.setBits(inst, cc.isFloat ? 0 : 1); - } - - @Override - protected List getKeys() { - List keys = super.getKeys(); - keys.add(new BitKey[]{new BitKey(BitSpec.op3, op3.value)}); - return keys; - } - } - - public static final class FMOVcc extends SPARCOp implements CMOV { - private OpfLow opfLow; - - public FMOVcc(OpfLow opfLow) { - super(ArithOp); - this.opfLow = opfLow; - } - - @Override - public void emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, Register rs2, Register rd) { - int inst = setBits(0); - inst = BitSpec.rd.setBits(inst, rd.encoding()); - inst = BitSpec.op3.setBits(inst, opfLow.op3.value); - inst = BitSpec.opfCond.setBits(inst, condition.value); - inst = BitSpec.opfCC.setBits(inst, cc.getOpfCCValue()); - inst = BitSpec.opfLow.setBits(inst, opfLow.value); - inst = BitSpec.rs2.setBits(inst, rs2.encoding()); - masm.emitInt(inst); - } - - @Override - public void emit(SPARCMacroAssembler masm, ConditionFlag condition, CC cc, int simm11, Register rd) { - throw new IllegalArgumentException("FMOVCC cannot be used with immediate value"); - } - - @Override - protected List getKeys() { - List keys = super.getKeys(); - keys.add(new BitKey[]{new BitKey(BitSpec.op3, opfLow.op3.value)}); - keys.add(new BitKey[]{new BitKey(BitSpec.opfLow, opfLow.value)}); - return keys; - } - } - - public static final class OpfOp extends SPARCOp { - - private BitKey[] op3Keys; - - public OpfOp(BitKey... op3Keys) { - super(ArithOp); - this.op3Keys = op3Keys; - } - - public OpfOp() { - // @formatter:off - this(new BitKey[]{ - new BitKey(BitSpec.op3, Op3s.Fpop1.value), - new BitKey(BitSpec.op3, Op3s.Fpop2.value), - new BitKey(BitSpec.op3, Op3s.Impdep1.value), - new BitKey(BitSpec.op3, Op3s.Impdep2.value)}); - // @formatter:on - } - - public static void emit(SPARCMacroAssembler masm, Opfs opf, Register rs1, Register rs2, Register rd) { - int instruction = setBits(0, opf, rs1, rs2); - instruction = BitSpec.rd.setBits(instruction, rd.encoding); - instruction = BitSpec.i.setBits(instruction, 0); - masm.emitInt(instruction); - } - - public static void emitFcmp(SPARCMacroAssembler masm, Opfs opf, CC cc, Register rs1, Register rs2) { - assert opf.equals(Opfs.Fcmpd) || opf.equals(Opfs.Fcmps) : opf; - int instruction = setBits(0, opf, rs1, rs2); - instruction = BitSpec.fcc.setBits(instruction, cc.value); - masm.emitInt(instruction); - } - - private static int setBits(int instruction, Opfs opf, Register rs1, Register rs2) { - int tmp = BitSpec.op.setBits(instruction, opf.op3.op.value); - tmp = BitSpec.op3.setBits(tmp, opf.op3.value); - tmp = BitSpec.opf.setBits(tmp, opf.value); - tmp = BitSpec.rs1.setBits(tmp, rs1.encoding); - return BitSpec.rs2.setBits(tmp, rs2.encoding); - } - - @Override - protected List getKeys() { - List keys = super.getKeys(); - keys.add(op3Keys); - // @formatter:on - return keys; - } - } - - public static boolean isCPURegister(Register... regs) { - for (Register reg : regs) { - if (!isCPURegister(reg)) { - return false; - } - } - return true; - } - - public static boolean isCPURegister(Register r) { - return r.getRegisterCategory().equals(CPU); - } - - public static boolean isGlobalRegister(Register r) { - return isCPURegister(r) && g0.number <= r.number && r.number <= g7.number; - } - - public static boolean isSingleFloatRegister(Register r) { - return r.getRegisterCategory().equals(FPUs); - } - - public static boolean isDoubleFloatRegister(Register r) { - return r.getRegisterCategory().equals(FPUd); - } - - public boolean hasFeature(CPUFeature feature) { - return ((SPARC) this.target.arch).features.contains(feature); - } - - public static final int simm(int x, int nbits) { - // assert_signed_range(x, nbits); - return x & ((1 << nbits) - 1); - } - - public static final boolean isImm(int x, int nbits) { - // assert_signed_range(x, nbits); - return simm(x, nbits) == x; - } - - /** - * Minimum value for signed immediate ranges. - */ - public static long minSimm(long nbits) { - return -(1L << (nbits - 1)); - } - - /** - * Maximum value for signed immediate ranges. - */ - public static long maxSimm(long nbits) { - return (1L << (nbits - 1)) - 1; - } - - /** - * Test if imm is within signed immediate range for nbits. - */ - public static boolean isSimm(long imm, int nbits) { - return minSimm(nbits) <= imm && imm <= maxSimm(nbits); - } - - public static boolean isSimm10(long imm) { - return isSimm(imm, 10); - } - - public static boolean isSimm11(long imm) { - return isSimm(imm, 11); - } - - public static boolean isSimm11(JavaConstant constant) { - return constant.isNull() || isSimm11(constant.asLong()); - } - - public static boolean isSimm5(JavaConstant constant) { - return constant.isNull() || isSimm(constant.asLong(), 5); - } - - public static boolean isSimm5(long imm) { - return isSimm(imm, 5); - } - - public static boolean isSimm13(int imm) { - return isSimm(imm, 13); - } - - public static boolean isSimm13(JavaConstant constant) { - long bits; - switch (constant.getJavaKind()) { - case Double: - bits = Double.doubleToRawLongBits(constant.asDouble()); - break; - case Float: - bits = Float.floatToRawIntBits(constant.asFloat()); - break; - case Object: - return constant.isNull(); - default: - bits = constant.asLong(); - break; - } - return constant.isNull() || isSimm13(bits); - } - - public static boolean isSimm13(long imm) { - return NumUtil.isInt(imm) && isSimm(imm, 13); - } - - public static boolean isWordDisp30(long imm) { - return isSimm(imm, 30 + 2); - } - - public static final int hi22(int x) { - return x >>> 10; - } - - public static final int lo10(int x) { - return x & ((1 << 10) - 1); - } - - // @formatter:off - /** - * Instruction format for Fmt00 instructions. This abstraction is needed as it - * makes the patching easier later on. - *
-     * | 00  |    a   | op2 |               b                         |
-     * |31 30|29    25|24 22|21                                      0|
-     * 
- */ - // @formatter:on - protected void fmt00(int a, int op2, int b) { - assert isImm(a, 5) && isImm(op2, 3) && isImm(b, 22) : String.format("a: 0x%x op2: 0x%x b: 0x%x", a, op2, b); - int word = 0; - BitSpec.op.setBits(word, 0); - BitSpec.rd.setBits(word, a); - BitSpec.op2.setBits(word, op2); - BitSpec.imm22.setBits(word, b); - emitInt(a << 25 | op2 << 22 | b); - } - - private void op3(Op3s op3, Opfs opf, Register rs1, Register rs2, Register rd) { - int b = opf.value << 5 | (rs2 == null ? 0 : rs2.encoding); - fmt(op3.op.value, rd.encoding, op3.value, rs1 == null ? 0 : rs1.encoding, b); - } - - protected void op3(Op3s op3, Register rs1, Register rs2, Register rd) { - int b = rs2 == null ? 0 : rs2.encoding; - int xBit = getXBit(op3); - fmt(op3.op.value, rd.encoding, op3.value, rs1 == null ? 0 : rs1.encoding, b | xBit); - } - - protected void op3(Op3s op3, Register rs1, int simm13, Register rd) { - assert isSimm13(simm13) : simm13; - int i = 1 << 13; - int simm13WithX = simm13 | getXBit(op3); - fmt(op3.op.value, rd.encoding, op3.value, rs1.encoding, i | simm13WithX & ((1 << 13) - 1)); - } - - public void insertNopAfterCBCond() { - int pos = position() - INSTRUCTION_SIZE; - if (pos == 0) { - return; - } - int inst = getInt(pos); - if (CBCOND.match(inst)) { - nop(); - } - } - - protected int patchUnbound(Label label) { - label.addPatchAt(position(), this); - return 0; - } - - // @formatter:off - /** - * NOP. - *
-     * | 00  |00000| 100 |                0                    |
-     * |31 30|29 25|24 22|21                                  0|
-     * 
- */ - // @formatter:on - public void nop() { - emitInt(1 << 24); - } - - public void sethi(int imm22, Register dst) { - fmt00(dst.encoding, Op2s.Sethi.value, imm22); - } - - // @formatter:off - /** - * Instruction format for calls. - *
-     * | 01  |                      disp30                             |
-     * |31 30|29                                                      0|
-     * 
- * - * @return Position of the call instruction - */ - // @formatter:on - public int call(int disp30) { - assert isImm(disp30, 30); - insertNopAfterCBCond(); - int before = position(); - int instr = 1 << 30; - instr |= disp30; - emitInt(instr); - return before; - } - - public void add(Register rs1, Register rs2, Register rd) { - op3(Add, rs1, rs2, rd); - } - - public void add(Register rs1, int simm13, Register rd) { - op3(Add, rs1, simm13, rd); - } - - public void addc(Register rs1, Register rs2, Register rd) { - op3(Addc, rs1, rs2, rd); - } - - public void addc(Register rs1, int simm13, Register rd) { - op3(Addc, rs1, simm13, rd); - } - - public void addcc(Register rs1, Register rs2, Register rd) { - op3(Addcc, rs1, rs2, rd); - } - - public void addcc(Register rs1, int simm13, Register rd) { - op3(Addcc, rs1, simm13, rd); - } - - public void and(Register rs1, Register rs2, Register rd) { - op3(And, rs1, rs2, rd); - } - - public void and(Register rs1, int simm13, Register rd) { - op3(And, rs1, simm13, rd); - } - - public void andcc(Register rs1, Register rs2, Register rd) { - op3(Andcc, rs1, rs2, rd); - } - - public void andcc(Register rs1, int simm13, Register rd) { - op3(Andcc, rs1, simm13, rd); - } - - public void andn(Register rs1, Register rs2, Register rd) { - op3(Andn, rs1, rs2, rd); - } - - public void andn(Register rs1, int simm13, Register rd) { - op3(Andn, rs1, simm13, rd); - } - - public void andncc(Register rs1, Register rs2, Register rd) { - op3(Andncc, rs1, rs2, rd); - } - - public void andncc(Register rs1, int simm13, Register rd) { - op3(Andncc, rs1, simm13, rd); - } - - public void movwtos(Register rs2, Register rd) { - assert isSingleFloatRegister(rd) && isCPURegister(rs2) : String.format("%s %s", rs2, rd); - op3(Impdep1, Movwtos, null, rs2, rd); - } - - public void umulxhi(Register rs1, Register rs2, Register rd) { - op3(Impdep1, UMulxhi, rs1, rs2, rd); - } - - public void fdtos(Register rs2, Register rd) { - assert isSingleFloatRegister(rd) && isDoubleFloatRegister(rs2) : String.format("%s %s", rs2, rd); - op3(Fpop1, Fdtos, null, rs2, rd); - } - - public void movstouw(Register rs2, Register rd) { - assert isSingleFloatRegister(rs2) && isCPURegister(rd) : String.format("%s %s", rs2, rd); - op3(Impdep1, Movstosw, null, rs2, rd); - } - - public void movstosw(Register rs2, Register rd) { - assert isSingleFloatRegister(rs2) && isCPURegister(rd) : String.format("%s %s", rs2, rd); - op3(Impdep1, Movstosw, null, rs2, rd); - } - - public void movdtox(Register rs2, Register rd) { - assert isDoubleFloatRegister(rs2) && isCPURegister(rd) : String.format("%s %s", rs2, rd); - op3(Impdep1, Movdtox, null, rs2, rd); - } - - public void movxtod(Register rs2, Register rd) { - assert isCPURegister(rs2) && isDoubleFloatRegister(rd) : String.format("%s %s", rs2, rd); - op3(Impdep1, Movxtod, null, rs2, rd); - } - - public void fadds(Register rs1, Register rs2, Register rd) { - op3(Fpop1, Fadds, rs1, rs2, rd); - } - - public void faddd(Register rs1, Register rs2, Register rd) { - op3(Fpop1, Faddd, rs1, rs2, rd); - } - - public void fdivs(Register rs1, Register rs2, Register rd) { - op3(Fpop1, Fdivs, rs1, rs2, rd); - } - - public void fdivd(Register rs1, Register rs2, Register rd) { - op3(Fpop1, Fdivd, rs1, rs2, rd); - } - - public void fmovs(Register rs2, Register rd) { - op3(Fpop1, Fmovs, null, rs2, rd); - } - - public void fmovd(Register rs2, Register rd) { - op3(Fpop1, Fmovd, null, rs2, rd); - } - - public void fsrc2s(Register rs2, Register rd) { - op3(Impdep1, Fsrc2s, null, rs2, rd); - } - - public void fsrc2d(Register rs2, Register rd) { - op3(Impdep1, Fsrc2d, null, rs2, rd); - } - - public void fmuls(Register rs1, Register rs2, Register rd) { - op3(Fpop1, Fmuls, rs1, rs2, rd); - } - - public void fsmuld(Register rs1, Register rs2, Register rd) { - op3(Fpop1, Fsmuld, rs1, rs2, rd); - } - - public void fmuld(Register rs1, Register rs2, Register rd) { - op3(Fpop1, Fmuld, rs1, rs2, rd); - } - - public void fnegs(Register rs2, Register rd) { - op3(Fpop1, Fnegs, null, rs2, rd); - } - - public void fnegd(Register rs2, Register rd) { - op3(Fpop1, Fnegd, null, rs2, rd); - } - - /** - * Helper method to determine if the instruction needs the X bit set. - */ - private static int getXBit(Op3s op3) { - switch (op3) { - case Sllx: - case Srax: - case Srlx: - return 1 << 12; - default: - return 0; - } - } - - public void fstoi(Register rs2, Register rd) { - op3(Fpop1, Fstoi, null, rs2, rd); - } - - public void fstox(Register rs2, Register rd) { - op3(Fpop1, Fstox, null, rs2, rd); - } - - public void fdtox(Register rs2, Register rd) { - op3(Fpop1, Fdtox, null, rs2, rd); - } - - public void fstod(Register rs2, Register rd) { - op3(Fpop1, Fstod, null, rs2, rd); - } - - public void fdtoi(Register rs2, Register rd) { - op3(Fpop1, Fdtoi, null, rs2, rd); - } - - public void fitos(Register rs2, Register rd) { - op3(Fpop1, Fitos, null, rs2, rd); - } - - public void fitod(Register rs2, Register rd) { - op3(Fpop1, Fitod, null, rs2, rd); - } - - public void fxtos(Register rs2, Register rd) { - op3(Fpop1, Fxtos, null, rs2, rd); - } - - public void fxtod(Register rs2, Register rd) { - op3(Fpop1, Fxtod, null, rs2, rd); - } - - public void fzeros(Register rd) { - op3(Impdep1, Fzeros, null, null, rd); - } - - public void fzerod(Register rd) { - op3(Impdep1, Fzerod, null, null, rd); - } - - public void flushw() { - op3(Flushw, g0, g0, g0); - } - - public void fsqrtd(Register rs2, Register rd) { - op3(Fpop1, Fsqrtd, null, rs2, rd); - } - - public void fsqrts(Register rs2, Register rd) { - op3(Fpop1, Fsqrts, null, rs2, rd); - } - - public void fabss(Register rs2, Register rd) { - op3(Fpop1, Fabss, null, rs2, rd); - } - - public void fabsd(Register rs2, Register rd) { - op3(Fpop1, Fabsd, null, rs2, rd); - } - - public void fsubs(Register rs1, Register rs2, Register rd) { - op3(Fpop1, Fsubs, rs1, rs2, rd); - } - - public void fsubd(Register rs1, Register rs2, Register rd) { - op3(Fpop1, Fsubd, rs1, rs2, rd); - } - - // @formatter:off - /** - * Instruction format for fcmp. - *
-     * | 10  | --- |cc1|cc0|desc |   rs1   |   opf  | rs2 |
-     * |31 30|29 27|26 |25 |24 19|18     14|13     5|4   0|
-     * 
- */ - // @formatter:on - public void fcmp(CC cc, Opfs opf, Register rs1, Register rs2) { - int a = cc.value; - int b = opf.value << 5 | rs2.encoding; - delaySlotOptimizationPoints.add(position()); - fmt10(a, Fpop2.value, rs1.encoding, b); - } - - // @formatter:off - /** - * Instruction format for most arithmetic stuff. - *
-     * |  10 | rd  | op3 | rs1 |   b   |
-     * |31 30|29 25|24 19|18 14|13    0|
-     * 
- */ - // @formatter:on - protected void fmt10(int rd, int op3, int rs1, int b) { - fmt(0b10, rd, op3, rs1, b); - } - - // @formatter:off - /** - * Instruction format for most arithmetic stuff. - *
-     * |  op | rd  | op3 | rs1 |   b   |
-     * |31 30|29 25|24 19|18 14|13    0|
-     * 
- */ - // @formatter:on - protected void fmt(int op, int rd, int op3, int rs1, int b) { - assert isImm(rd, 5) && isImm(op3, 6) && isImm(b, 14) : String.format("rd: 0x%x op3: 0x%x b: 0x%x", rd, op3, b); - int instr = op << 30 | rd << 25 | op3 << 19 | rs1 << 14 | b; - emitInt(instr); - } - - public void illtrap(int const22) { - fmt00(0, Op2s.Illtrap.value, const22); - } - - public void jmpl(Register rs1, Register rs2, Register rd) { - insertNopAfterCBCond(); - op3(Jmpl, rs1, rs2, rd); - } - - /** - * @return Position of the jmpl instruction - */ - public int jmpl(Register rs1, int simm13, Register rd) { - insertNopAfterCBCond(); - int before = position(); - op3(Jmpl, rs1, simm13, rd); - return before; - } - - public void fmovdcc(ConditionFlag cond, CC cc, Register rs2, Register rd) { - fmovcc(cond, cc, rs2, rd, OpfLow.Fmovdcc.value); - } - - public void fmovscc(ConditionFlag cond, CC cc, Register rs2, Register rd) { - fmovcc(cond, cc, rs2, rd, OpfLow.Fmovscc.value); - } - - private void fmovcc(ConditionFlag cond, CC cc, Register rs2, Register rd, int opfLow) { - int opfCC = cc.getOpfCCValue(); - int a = opfCC << 11 | opfLow << 5 | rs2.encoding; - fmt10(rd.encoding, Fpop2.value, cond.value, a); - } - - public void movcc(ConditionFlag conditionFlag, CC cc, Register rs2, Register rd) { - movcc(conditionFlag, cc, 0, rs2.encoding, rd); - } - - public void movcc(ConditionFlag conditionFlag, CC cc, int simm11, Register rd) { - assert isSimm11(simm11); - movcc(conditionFlag, cc, 1, simm11 & ((1 << 11) - 1), rd); - } - - private void movcc(ConditionFlag conditionFlag, CC cc, int i, int imm, Register rd) { - int cc01 = 0b11 & cc.value; - int cc2 = cc.isFloat ? 0 : 1; - int a = cc2 << 4 | conditionFlag.value; - int b = cc01 << 11 | i << 13 | imm; - fmt10(rd.encoding, Movcc.value, a, b); - } - - public void mulx(Register rs1, Register rs2, Register rd) { - op3(Mulx, rs1, rs2, rd); - } - - public void mulx(Register rs1, int simm13, Register rd) { - op3(Mulx, rs1, simm13, rd); - } - - public void or(Register rs1, Register rs2, Register rd) { - assert isCPURegister(rs1, rs2, rd) : String.format("%s %s %s", rs1, rs2, rd); - op3(Or, rs1, rs2, rd); - } - - public void or(Register rs1, int simm13, Register rd) { - assert isCPURegister(rs1, rd) : String.format("%s %s", rs1, rd); - op3(Or, rs1, simm13, rd); - } - - public void popc(Register rs2, Register rd) { - op3(Popc, g0, rs2, rd); - } - - public void popc(int simm13, Register rd) { - op3(Popc, g0, simm13, rd); - } - - public void prefetch(SPARCAddress addr, Fcn fcn) { - Register rs1 = addr.getBase(); - if (addr.getIndex().equals(Register.None)) { - int dis = addr.getDisplacement(); - assert isSimm13(dis); - fmt(Prefetch.op.value, fcn.value, Prefetch.value, rs1.encoding, 1 << 13 | dis & ((1 << 13) - 1)); - } else { - Register rs2 = addr.getIndex(); - fmt(Prefetch.op.value, fcn.value, Prefetch.value, rs1.encoding, rs2.encoding); - } - } - - // A.44 Read State Register - - public void rdpc(Register rd) { - op3(Rd, g5, g0, rd); - } - - public void restore(Register rs1, Register rs2, Register rd) { - op3(Restore, rs1, rs2, rd); - } - - public static final int PC_RETURN_OFFSET = 8; - - public void save(Register rs1, Register rs2, Register rd) { - op3(Save, rs1, rs2, rd); - } - - public void save(Register rs1, int simm13, Register rd) { - op3(Save, rs1, simm13, rd); - } - - public void sdivx(Register rs1, Register rs2, Register rd) { - op3(Sdivx, rs1, rs2, rd); - } - - public void sdivx(Register rs1, int simm13, Register rd) { - op3(Sdivx, rs1, simm13, rd); - } - - public void udivx(Register rs1, Register rs2, Register rd) { - op3(Udivx, rs1, rs2, rd); - } - - public void udivx(Register rs1, int simm13, Register rd) { - op3(Udivx, rs1, simm13, rd); - } - - public void sll(Register rs1, Register rs2, Register rd) { - op3(Sll, rs1, rs2, rd); - } - - public void sll(Register rs1, int shcnt32, Register rd) { - assert isImm(shcnt32, 5); - op3(Sll, rs1, shcnt32, rd); - } - - public void sllx(Register rs1, Register rs2, Register rd) { - op3(Sllx, rs1, rs2, rd); - } - - public void sllx(Register rs1, int shcnt64, Register rd) { - assert isImm(shcnt64, 6); - op3(Sllx, rs1, shcnt64, rd); - } - - public void sra(Register rs1, Register rs2, Register rd) { - op3(Sra, rs1, rs2, rd); - } - - public void sra(Register rs1, int simm13, Register rd) { - op3(Sra, rs1, simm13, rd); - } - - public void srax(Register rs1, Register rs2, Register rd) { - op3(Srax, rs1, rs2, rd); - } - - public void srax(Register rs1, int shcnt64, Register rd) { - assert isImm(shcnt64, 6); - op3(Srax, rs1, shcnt64, rd); - } - - public void srl(Register rs1, Register rs2, Register rd) { - op3(Srl, rs1, rs2, rd); - } - - public void srl(Register rs1, int simm13, Register rd) { - op3(Srl, rs1, simm13, rd); - } - - public void srlx(Register rs1, Register rs2, Register rd) { - op3(Srlx, rs1, rs2, rd); - } - - public void srlx(Register rs1, int shcnt64, Register rd) { - assert isImm(shcnt64, 6); - op3(Srlx, rs1, shcnt64, rd); - } - - public void sub(Register rs1, Register rs2, Register rd) { - op3(Sub, rs1, rs2, rd); - } - - public void sub(Register rs1, int simm13, Register rd) { - op3(Sub, rs1, simm13, rd); - } - - public void subcc(Register rs1, Register rs2, Register rd) { - op3(Subcc, rs1, rs2, rd); - } - - public void subcc(Register rs1, int simm13, Register rd) { - op3(Subcc, rs1, simm13, rd); - } - - public void ta(int trap) { - tcc(Icc, Always, trap); - } - - public void pause() { - // Maybe fmt10(rd=0b1_1011, op3=0b11_0000, rs1=0, i=1, simm13=1), or - // maybe op3(Wr, g0, 1, %pause). - // What should the count be? - GraalError.unimplemented("The SPARC pause instruction is not yet implemented."); - } - - public void tcc(CC cc, ConditionFlag flag, int trap) { - assert isImm(trap, 8); - int b = cc.value << 11; - b |= 1 << 13; - b |= trap; - fmt10(flag.value, Op3s.Tcc.getValue(), 0, b); - } - - public void wrccr(Register rs1, Register rs2) { - op3(Wr, rs1, rs2, g2); - } - - public void wrccr(Register rs1, int simm13) { - op3(Wr, rs1, simm13, g2); - } - - public void xor(Register rs1, Register rs2, Register rd) { - op3(Xor, rs1, rs2, rd); - } - - public void xor(Register rs1, int simm13, Register rd) { - op3(Xor, rs1, simm13, rd); - } - - public void xorcc(Register rs1, Register rs2, Register rd) { - op3(Xorcc, rs1, rs2, rd); - } - - public void xorcc(Register rs1, int simm13, Register rd) { - op3(Xorcc, rs1, simm13, rd); - } - - public void xnor(Register rs1, Register rs2, Register rd) { - op3(Xnor, rs1, rs2, rd); - } - - public void xnor(Register rs1, int simm13, Register rd) { - op3(Xnor, rs1, simm13, rd); - } - - /* - * Load/Store - */ - protected void ld(Op3s op3, SPARCAddress addr, Register rd, Asi asi) { - Register rs1 = addr.getBase(); - if (!addr.getIndex().equals(Register.None)) { - Register rs2 = addr.getIndex(); - if (asi != null) { - int b = rs2.encoding; - b |= asi.value << 5; - fmt(op3.op.value, rd.encoding, op3.value, rs1.encoding, b); - } else { - op3(op3, rs1, rs2, rd); - } - } else { - int imm = addr.getDisplacement(); - op3(op3, rs1, imm, rd); - } - } - - protected void ld(Op3s op3, SPARCAddress addr, Register rd) { - ld(op3, addr, rd, null); - } - - public void lddf(SPARCAddress src, Register dst) { - assert isDoubleFloatRegister(dst) : dst; - ld(Lddf, src, dst); - } - - public void ldf(SPARCAddress src, Register dst) { - assert isSingleFloatRegister(dst) : dst; - ld(Ldf, src, dst); - } - - public void lduh(SPARCAddress src, Register dst) { - assert isCPURegister(dst) : dst; - ld(Lduh, src, dst); - } - - public void ldsh(SPARCAddress src, Register dst) { - assert isCPURegister(dst) : dst; - ld(Ldsh, src, dst); - } - - public void ld(SPARCAddress src, Register dst, int bytes, boolean signExtend) { - if (isCPURegister(dst)) { - if (signExtend) { - switch (bytes) { - case 1: - ld(Ldsb, src, dst); - break; - case 2: - ld(Ldsh, src, dst); - break; - case 4: - ld(Ldsw, src, dst); - break; - case 8: - ld(Ldx, src, dst); - break; - default: - throw new InternalError(); - } - } else { - switch (bytes) { - case 1: - ld(Ldub, src, dst); - break; - case 2: - ld(Lduh, src, dst); - break; - case 4: - ld(Lduw, src, dst); - break; - case 8: - ld(Ldx, src, dst); - break; - default: - throw new InternalError(); - } - } - } else if (isDoubleFloatRegister(dst) && bytes == 8) { - assert !signExtend; - ld(Lddf, src, dst); - } else if (isSingleFloatRegister(dst) && bytes == 4) { - assert !signExtend; - ld(Ldf, src, dst); - } else { - throw new InternalError(String.format("src: %s dst: %s bytes: %d signExtend: %b", src, dst, bytes, signExtend)); - } - } - - public void st(Register src, SPARCAddress dst, int bytes) { - if (isCPURegister(src)) { - switch (bytes) { - case 1: - st(Stb, src, dst); - break; - case 2: - st(Sth, src, dst); - break; - case 4: - st(Stw, src, dst); - break; - case 8: - st(Stx, src, dst); - break; - default: - throw new InternalError(Integer.toString(bytes)); - } - } else if (isDoubleFloatRegister(src) && bytes == 8) { - st(Stdf, src, dst); - } else if (isSingleFloatRegister(src) && bytes == 4) { - st(Stf, src, dst); - } else { - throw new InternalError(String.format("src: %s dst: %s bytes: %d", src, dst, bytes)); - } - } - - public void ldub(SPARCAddress src, Register dst) { - assert isCPURegister(dst) : dst; - ld(Ldub, src, dst); - } - - public void ldsb(SPARCAddress src, Register dst) { - assert isCPURegister(dst) : dst; - ld(Ldsb, src, dst); - } - - public void lduw(SPARCAddress src, Register dst) { - assert isCPURegister(dst) : dst; - ld(Lduw, src, dst); - } - - public void ldsw(SPARCAddress src, Register dst) { - assert isCPURegister(dst) : dst; - ld(Ldsw, src, dst); - } - - public void ldx(SPARCAddress src, Register dst) { - assert isCPURegister(dst) : dst; - ld(Ldx, src, dst); - } - - public void ldxa(Register rs1, Register rs2, Register rd, Asi asi) { - assert isCPURegister(rs1, rs2, rd) : format("%s %s %s", rs1, rs2, rd); - ld(Ldxa, new SPARCAddress(rs1, rs2), rd, asi); - } - - public void lduwa(Register rs1, Register rs2, Register rd, Asi asi) { - assert isCPURegister(rs1, rs2, rd) : format("%s %s %s", rs1, rs2, rd); - ld(Lduwa, new SPARCAddress(rs1, rs2), rd, asi); - } - - public void stxa(Register rd, Register rs1, Register rs2, Asi asi) { - assert isCPURegister(rs1, rs2, rd) : format("%s %s %s", rs1, rs2, rd); - ld(Stxa, new SPARCAddress(rs1, rs2), rd, asi); - } - - protected void st(Op3s op3, Register rs1, SPARCAddress dest) { - ld(op3, dest, rs1); - } - - public void stdf(Register rd, SPARCAddress addr) { - assert isDoubleFloatRegister(rd) : rd; - st(Stdf, rd, addr); - } - - public void stf(Register rd, SPARCAddress addr) { - assert isSingleFloatRegister(rd) : rd; - st(Stf, rd, addr); - } - - public void stb(Register rd, SPARCAddress addr) { - assert isCPURegister(rd) : rd; - st(Stb, rd, addr); - } - - public void sth(Register rd, SPARCAddress addr) { - assert isCPURegister(rd) : rd; - st(Sth, rd, addr); - } - - public void stw(Register rd, SPARCAddress addr) { - assert isCPURegister(rd) : rd; - st(Stw, rd, addr); - } - - public void stx(Register rd, SPARCAddress addr) { - assert isCPURegister(rd) : rd; - st(Stx, rd, addr); - } - - public void membar(int barriers) { - op3(Membar, o7, barriers, g0); - } - - public void casa(Register rs1, Register rs2, Register rd, Asi asi) { - ld(Casa, new SPARCAddress(rs1, rs2), rd, asi); - } - - public void casxa(Register rs1, Register rs2, Register rd, Asi asi) { - ld(Casxa, new SPARCAddress(rs1, rs2), rd, asi); - } - - @Override - public InstructionCounter getInstructionCounter() { - return new SPARCInstructionCounter(this); - } - - public void patchAddImmediate(int position, int simm13) { - int inst = getInt(position); - assert SPARCAssembler.isSimm13(simm13) : simm13; - assert (inst >>> 30) == 0b10 : String.format("0x%x", inst); - assert ((inst >>> 18) & 0b11_1111) == 0 : String.format("0x%x", inst); - assert (inst & (1 << 13)) != 0 : String.format("0x%x", inst); - inst = inst & (~((1 << 13) - 1)); - inst |= simm13 & ((1 << 12) - 1); - emitInt(inst, position); - } - - public void fpadd32(Register rs1, Register rs2, Register rd) { - op3(Impdep1, Fpadd32, rs1, rs2, rd); - } - - /** - * Does peephole optimization on code generated by this assembler. This method should be called - * at the end of code generation. - *

- * It searches for conditional branch instructions which has nop in the delay slot then looks at - * the instruction at branch target; if it is an arithmetic instruction, which does not throw an - * exception (e.g. division), it pulls this instruction into the delay slot and increments the - * displacement by 1. - */ - public void peephole() { - for (int i : delaySlotOptimizationPoints) { - optimizeDelaySlot(i); - } - } - - /** - * Optimizes branch instruction b which has a nop in the delay slot. It tries to stuff - * the instruction at bs branch target into the delay slot of b, set the annul - * flag and increments bs disp field by 1; - *

- * If bs branch target instruction is an unconditional branch t, then it tries to - * put ts delayed instruction into the delay slot of b and add the ts disp - * field to bs disp field. - */ - private void optimizeDelaySlot(int i) { - int delaySlotAbsolute = i + INSTRUCTION_SIZE; - int nextInst = getInt(delaySlotAbsolute); - SPARCOp nextOp = getSPARCOp(nextInst); - if (nextOp instanceof Sethi && Sethi.isNop(nextInst)) { - int inst = getInt(i); - SPARCOp op = getSPARCOp(inst); - if (op instanceof ControlTransferOp && ((ControlTransferOp) op).hasDelaySlot() && ((ControlTransferOp) op).isAnnulable(inst)) { - ControlTransferOp ctOp = (ControlTransferOp) op; - int disp = ctOp.getDisp(inst); - int branchTargetAbsolute = i + disp * INSTRUCTION_SIZE; - int branchTargetInst = getInt(branchTargetAbsolute); - SPARCOp branchTargetOp = getSPARCOp(branchTargetInst); - if (branchTargetOp instanceof Op3Op) { - Op3s op3 = ((Op3Op) branchTargetOp).getOp3(branchTargetInst); - if (!op3.throwsException()) { - inst = ctOp.setDisp(inst, disp + 1); // Increment the offset - inst = ctOp.setAnnul(inst, true); - emitInt(inst, i); - emitInt(branchTargetInst, delaySlotAbsolute); - } - } else if (branchTargetOp instanceof ControlTransferOp && !((ControlTransferOp) branchTargetOp).isConditional(branchTargetInst)) { - // If branchtarget is a unconditional branch - ControlTransferOp branchTargetOpBranch = (ControlTransferOp) branchTargetOp; - int btDisp = branchTargetOpBranch.getDisp(branchTargetInst); - int newDisp = disp + btDisp; - if (ctOp.isValidDisp(newDisp)) { // Test if we don't exceed field size - int instAfter = ctOp.setDisp(inst, newDisp); - instAfter = ctOp.setAnnul(instAfter, true); - branchTargetInst = getInt(branchTargetAbsolute + INSTRUCTION_SIZE); - branchTargetOp = getSPARCOp(branchTargetInst); - if (branchTargetOp instanceof Op3Op && !((Op3Op) branchTargetOp).getOp3(branchTargetInst).throwsException()) { - emitInt(instAfter, i); - emitInt(branchTargetInst, delaySlotAbsolute); - } - } - } - } - } - } -}