# HG changeset patch # User Stefan Anzinger # Date 1410998797 25200 # Node ID 2e4bd9de8682dca2511723118ada3c1e940dc19d # Parent d75276c49399379aa521e5e75f05467c5a88b60a# Parent 62d7d16b170bbd162b1095a13b4dd4df771ee053 Merge diff -r 62d7d16b170b -r 2e4bd9de8682 graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java --- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java Wed Sep 17 09:33:48 2014 -0700 +++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java Wed Sep 17 17:06:37 2014 -0700 @@ -60,11 +60,13 @@ public static abstract class Fmt00 { protected static final int OP_SHIFT = 30; + protected static final int CBCOND_SHIFT = 28; protected static final int OP2_SHIFT = 22; // @formatter:off - protected static final int OP_MASK = 0b1100_0000_0000_0000_0000_0000_0000_0000; - protected static final int OP2_MASK = 0b0000_0001_1100_0000_0000_0000_0000_0000; + protected static final int OP_MASK = 0b1100_0000_0000_0000_0000_0000_0000_0000; + protected static final int CBCOND_MASK = 0b0001_0000_0000_0000_0000_0000_0000_0000; // Used for distinguish CBcond and BPr instructions + protected static final int OP2_MASK = 0b0000_0001_1100_0000_0000_0000_0000_0000; // @formatter:off private int op2; @@ -86,7 +88,12 @@ case Bp: return Fmt00c.read(masm, pos); case Bpr: - return Fmt00d.read(masm, pos); + boolean isCBcond = (inst & CBCOND_MASK) != 0; + if(isCBcond) { + return Fmt00e.read(masm, pos); + } else { + return Fmt00d.read(masm, pos); + } default: throw GraalInternalError.shouldNotReachHere("Unknown op2 " + op2); } @@ -106,7 +113,7 @@ } public void verify() { - assert ((op2 << OP2_SHIFT) & OP2_MASK) == (op2 << OP2_SHIFT); + assert ((op2 << OP2_SHIFT) & OP2_MASK) == (op2 << OP2_SHIFT) : Integer.toHexString(op2); assert Op2s.byValue(op2) != null : op2; } /** @@ -520,7 +527,7 @@ super(op2); this.annul = annul; this.rCondition = rCondition; - this.disp16 = d16; + setDisp16(d16); this.predictTaken = predictTaken; this.rs1 = rs1; this.label = label; @@ -563,19 +570,20 @@ // Make sure it's the right instruction: final int op = (inst & OP_MASK) >> OP_SHIFT; - assert op == Ops.BranchOp.getValue(); + final int op2 = (inst & OP2_MASK) >> OP2_SHIFT; + final int condFlag = (inst & CBCOND_MASK) >> CBCOND_SHIFT; + assert op2 == Op2s.Bpr.getValue() && op == Ops.BranchOp.getValue() && condFlag == 0 : "0x" + Integer.toHexString(inst); // Get the instruction fields: final int a = (inst & A_MASK) >> A_SHIFT; final int cond = (inst & RCOND_MASK) >> RCOND_SHIFT; - final int op2 = (inst & OP2_MASK) >> OP2_SHIFT; final int p = (inst & P_MASK) >> P_SHIFT; final int rs1 = (inst & RS1_MASK) >> RS1_SHIFT; final int d16hi = (inst & D16HI_MASK) >> D16HI_SHIFT; assert (d16hi & ~0b11) == 0; final int d16lo = (inst & D16LO_MASK) >> D16LO_SHIFT; assert (d16lo & ~((1 << 14) - 1)) == 0; - final int d16 = (short) (((d16hi << 14) | d16lo) << 2); // sign extend + final int d16 = (short) (((d16hi << 14) | d16lo) << 2); // times 4 and sign extend Fmt00d fmt = new Fmt00d(op2, cond, p, a, d16, rs1, null); fmt.verify(); return fmt; @@ -592,18 +600,138 @@ } } - public static class Fmt00e { - - public Fmt00e(SPARCAssembler asm, int op, int c4lo, int cc2, int rs1, int d10lo, int regOrImmediate) { - assert op == 0; - assert (cc2 & 0xFFFFFFFE) == 0; - assert c4lo >= 0 && rs1 < 0x10; - assert rs1 >= 0 && rs1 < 0x20; - assert (regOrImmediate & 0x1F) < 0x20; - assert (regOrImmediate & 0xFFFFC000) == 0; - assert (d10lo & 0xFFFFFC00) == 0; - - asm.emitInt(op << 30 | 1 << 28 | 3 << 22 | cc2 << 21 | (d10lo >> 8) << 19 | rs1 << 14 | (d10lo & 0xff) << 5 | regOrImmediate); + // @formatter:off + /** + * Instruction format CBcond + * + * |00 |chi|1 | clo | 011 |cc2|d10hi|rs1 |i |d10lo|rs2/simm5| + * |31 30|29 |28|27 25|24 22|21 |20 19|18 14|13|12 5|4 0| + */ + // @formatter:on + public static class Fmt00e extends Fmt00 { + private static final int CHI_SHIFT = 29; + private static final int CLO_SHIFT = 25; + private static final int CC2_SHIFT = 21; + private static final int D10HI_SHIFT = 19; + private static final int RS1_SHIFT = 14; + private static final int I_SHIFT = 13; + private static final int D10LO_SHIFT = 5; + private static final int RS2_SHIFT = 0; + + // @formatter:off + private static final int CHI_MASK = 0b0010_0000_0000_0000_0000_0000_0000_0000; + private static final int CLO_MASK = 0b0000_1110_0000_0000_0000_0000_0000_0000; + private static final int CC2_MASK = 0b0000_0000_0010_0000_0000_0000_0000_0000; + private static final int D10HI_MASK = 0b0000_0000_0001_1000_0000_0000_0000_0000; + private static final int RS1_MASK = 0b0000_0000_0000_0111_1100_0000_0000_0000; + private static final int I_MASK = 0b0000_0000_0000_0000_0010_0000_0000_0000; + private static final int D10LO_MASK = 0b0000_0000_0000_0000_0001_1111_1110_0000; + private static final int RS2_MASK = 0b0000_0000_0000_0000_0000_0000_0001_1111; + // @formatter:on + + private int c; + private int cc2; + private int disp10; + private int rs1; + private int i; + private int regOrImmediate; + private Label label; + + public Fmt00e(int c, int cc2, int rs1, int disp10, int i, int regOrImmediate, Label label) { + super(Op2s.Bpr.getValue()); + this.c = c; + this.cc2 = cc2; + this.rs1 = rs1; + setDisp10(disp10); + this.i = i; + this.regOrImmediate = regOrImmediate; + this.label = label; + } + + @Override + public void setImm(int imm) { + setDisp10(imm); + } + + public void setDisp10(int disp10) { + this.disp10 = disp10 >> 2; + } + + public void emit(SPARCAssembler masm) { + assert masm.hasFeature(CPUFeature.CBCOND); + if (label != null) { + final int pos = label.isBound() ? label.position() : patchUnbound(masm, label); + if (label.isBound()) { + final int disp = pos - masm.position(); + setDisp10(disp); + } else { + setDisp10(0); + } + } + verify(); + masm.emitInt(getInstructionBits()); + } + + private static int patchUnbound(SPARCAssembler masm, Label label) { + label.addPatchAt(masm.position()); + return 0; + } + + @Override + protected int getInstructionBits() { + int cSplit = 0; + cSplit |= (c & 0b1000) << CHI_SHIFT - 3; + cSplit |= (c & 0b0111) << CLO_SHIFT; + int d10Split = 0; + d10Split |= (disp10 & 0b11_0000_0000) << D10HI_SHIFT - 8; + d10Split |= (disp10 & 0b00_1111_1111) << D10LO_SHIFT; + return super.getInstructionBits() | 1 << 28 | cSplit | cc2 << CC2_SHIFT | d10Split | rs1 << RS1_SHIFT | i << I_SHIFT | regOrImmediate << RS2_SHIFT; + } + + public static Fmt00e read(SPARCAssembler masm, int pos) { + assert masm.hasFeature(CPUFeature.CBCOND); + final int inst = masm.getInt(pos); + + // Make sure it's the right instruction: + final int op = (inst & OP_MASK) >> OP_SHIFT; + final int op2 = (inst & OP2_MASK) >> OP2_SHIFT; + final int condFlag = (inst & CBCOND_MASK) >> CBCOND_SHIFT; + assert op2 == Op2s.Bpr.getValue() && op == Ops.BranchOp.getValue() && condFlag == 1 : "0x" + Integer.toHexString(inst); + + // @formatter:off + // Get the instruction fields: + final int chi = (inst & CHI_MASK) >> CHI_SHIFT; + final int clo = (inst & CLO_MASK) >> CLO_SHIFT; + final int cc2 = (inst & CC2_MASK) >> CC2_SHIFT; + final int d10hi = (inst & D10HI_MASK) >> D10HI_SHIFT; + final int rs1 = (inst & RS1_MASK) >> RS1_SHIFT; + final int i = (inst & I_MASK) >> I_SHIFT; + final int d10lo = (inst & D10LO_MASK) >> D10LO_SHIFT; + final int regOrImmediate = (inst & RS2_MASK) >> RS2_SHIFT; + // @formatter:on + + int c = chi << 3 | clo; + + assert (d10lo & ~((1 << 8) - 1)) == 0; + final int d10 = ((short) (((d10hi << 8) | d10lo) << 6)) >> 4; // Times 4 and sign extend + Fmt00e fmt = new Fmt00e(c, cc2, rs1, d10, i, regOrImmediate, null); + fmt.verify(); + return fmt; + } + + @Override + public void verify() { + super.verify(); + assert (c & ~0b1111) == 0 : c; + assert (cc2 & ~1) == 0 : cc2; + assert isSimm(disp10, 10) : disp10; + assert (rs1 & ~0b1_1111) == 0 : rs1; + assert (i & ~1) == 0 : i; + if (i == 1) { + assert isSimm(regOrImmediate, 5) : regOrImmediate; + } else { + assert (regOrImmediate & ~0b1_1111) == 0 : regOrImmediate; + } } } @@ -1869,6 +1997,10 @@ } } + public boolean hasFeature(CPUFeature feature) { + return ((SPARC) this.target.arch).features.contains(feature); + } + public static int getFloatEncoding(int reg) { assert reg < 32; return reg; @@ -2426,353 +2558,23 @@ } } - /** - * Compare and Branch if Carry Clear ( Greater not C Than or Equal, Unsigned ) - */ - public static class Cwbcc extends Fmt00e { - - public Cwbcc(SPARCAssembler asm, Register src1, Register src2, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarryClear.getValue(), 0, src1.encoding(), simm10, src2.encoding()); - } - - public Cwbcc(SPARCAssembler asm, Register src1, int immed5, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.Equal.getValue(), 0, src1.encoding(), simm10, immed5 | ImmedTrue); - } - } - - /** - * Compare and Branch if Carry Set (Less Than, Unsigned) - */ - public static class Cwbcs extends Fmt00e { - - public Cwbcs(SPARCAssembler asm, Register src1, Register src2, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarrySet.getValue(), 0, src1.encoding(), simm10, src2.encoding()); - } - - public Cwbcs(SPARCAssembler asm, Register src1, int immed5, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarrySet.getValue(), 0, src1.encoding(), simm10, immed5 | ImmedTrue); - } - } - - /** - * Compare and Branch if Equal - */ - public static class Cwbe extends Fmt00e { - - public Cwbe(SPARCAssembler asm, Register src1, Register src2, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarryClear.getValue(), 0, src1.encoding(), simm10, src2.encoding()); - } - - public Cwbe(SPARCAssembler asm, Register src1, int immed5, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.Equal.getValue(), 0, src1.encoding(), simm10, immed5 | ImmedTrue); - } - } - - /** - * Compare and Branch if Greater - */ - public static class Cwbg extends Fmt00e { - - public Cwbg(SPARCAssembler asm, Register src1, Register src2, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.Greater.getValue(), 0, src1.encoding(), simm10, src2.encoding()); - } - - public Cwbg(SPARCAssembler asm, Register src1, int immed5, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.Greater.getValue(), 0, src1.encoding(), simm10, immed5 | ImmedTrue); - } - } - - /** - * Compare and Branch if Greater or Equal - */ - public static class Cwbge extends Fmt00e { - - public Cwbge(SPARCAssembler asm, Register src1, Register src2, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterEqual.getValue(), 0, src1.encoding(), simm10, src2.encoding()); - } - - public Cwbge(SPARCAssembler asm, Register src1, int immed5, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterEqual.getValue(), 0, src1.encoding(), simm10, immed5 | ImmedTrue); - } - } - - /** - * Compare and Branch if Greater Unsigned - */ - public static class Cwbgu extends Fmt00e { - - public Cwbgu(SPARCAssembler asm, Register src1, Register src2, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterUnsigned.getValue(), 0, src1.encoding(), simm10, src2.encoding()); - } - - public Cwbgu(SPARCAssembler asm, Register src1, int immed5, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterUnsigned.getValue(), 0, src1.encoding(), simm10, immed5 | ImmedTrue); - } - } - - /** - * Compare and Branch if Less - */ - public static class Cwbl extends Fmt00e { - - public Cwbl(SPARCAssembler asm, Register src1, Register src2, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.Less.getValue(), 0, src1.encoding(), simm10, src2.encoding()); - } - - public Cwbl(SPARCAssembler asm, Register src1, int immed5, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.Less.getValue(), 0, src1.encoding(), simm10, immed5 | ImmedTrue); - } - } - - /** - * Compare and Branch if Less or Equal - */ - public static class Cwble extends Fmt00e { - - public Cwble(SPARCAssembler asm, Register src1, Register src2, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqual.getValue(), 0, src1.encoding(), simm10, src2.encoding()); - } - - public Cwble(SPARCAssembler asm, Register src1, int immed5, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqual.getValue(), 0, src1.encoding(), simm10, immed5 | ImmedTrue); - } - } - - /** - * Compare and Branch if Less or Equal Unsigned - */ - public static class Cwbleu extends Fmt00e { - - public Cwbleu(SPARCAssembler asm, Register src1, Register src2, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqualUnsigned.getValue(), 0, src1.encoding(), simm10, src2.encoding()); - } - - public Cwbleu(SPARCAssembler asm, Register src1, int immed5, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqualUnsigned.getValue(), 0, src1.encoding(), simm10, immed5 | ImmedTrue); - } - } - - /** - * Compare and Branch if Not Equal - */ - public static class Cwbne extends Fmt00e { - - public Cwbne(SPARCAssembler asm, Register src1, Register src2, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.NotEqual.getValue(), 0, src1.encoding(), simm10, src2.encoding()); - } - - public Cwbne(SPARCAssembler asm, Register src1, int immed5, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.NotEqual.getValue(), 0, src1.encoding(), simm10, immed5 | ImmedTrue); - } - } - - /** - * Compare and Branch if Negative - */ - public static class Cwbneg extends Fmt00e { - - public Cwbneg(SPARCAssembler asm, Register src1, Register src2, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.Negative.getValue(), 0, src1.encoding(), simm10, src2.encoding()); - } - - public Cwbneg(SPARCAssembler asm, Register src1, int immed5, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.Negative.getValue(), 0, src1.encoding(), simm10, immed5 | ImmedTrue); - } - } - - /** - * Compare and Branch if Positive - */ - public static class Cwbpos extends Fmt00e { - - public Cwbpos(SPARCAssembler asm, Register src1, Register src2, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.Positive.getValue(), 0, src1.encoding(), simm10, src2.encoding()); - } - - public Cwbpos(SPARCAssembler asm, Register src1, int immed5, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.Positive.getValue(), 0, src1.encoding(), simm10, immed5 | ImmedTrue); - } - } - - /** - * Compare and Branch if Overflow Clear - */ - public static class Cwbvc extends Fmt00e { - - public Cwbvc(SPARCAssembler asm, Register src1, Register src2, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowClear.getValue(), 0, src1.encoding(), simm10, src2.encoding()); - } - - public Cwbvc(SPARCAssembler asm, Register src1, int immed5, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowClear.getValue(), 0, src1.encoding(), simm10, immed5 | ImmedTrue); - } - } - - /** - * Compare and Branch if Overflow Set - */ - public static class Cwbvs extends Fmt00e { - - public Cwbvs(SPARCAssembler asm, Register src1, Register src2, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowSet.getValue(), 0, src1.encoding(), simm10, src2.encoding()); - } - - public Cwbvs(SPARCAssembler asm, Register src1, int immed5, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowSet.getValue(), 0, src1.encoding(), simm10, immed5 | ImmedTrue); - } - } - - public static class Cxbcc extends Fmt00e { - - public Cxbcc(SPARCAssembler asm, Register src1, Register src2, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarryClear.getValue(), 1, src1.encoding(), simm10, src2.encoding()); - } - - public Cxbcc(SPARCAssembler asm, Register src1, int immed5, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.Equal.getValue(), 1, src1.encoding(), simm10, immed5 | ImmedTrue); - } - } - - public static class Cxbcs extends Fmt00e { - - public Cxbcs(SPARCAssembler asm, Register src1, Register src2, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarrySet.getValue(), 1, src1.encoding(), simm10, src2.encoding()); - } - - public Cxbcs(SPARCAssembler asm, Register src1, int immed5, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarrySet.getValue(), 1, src1.encoding(), simm10, immed5 | ImmedTrue); - } - } - - public static class Cxbe extends Fmt00e { - - public Cxbe(SPARCAssembler asm, Register src1, Register src2, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.CarryClear.getValue(), 1, src1.encoding(), simm10, src2.encoding()); - } - - public Cxbe(SPARCAssembler asm, Register src1, int immed5, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.Equal.getValue(), 1, src1.encoding(), simm10, immed5 | ImmedTrue); - } - } - - public static class Cxbg extends Fmt00e { - - public Cxbg(SPARCAssembler asm, Register src1, Register src2, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.Greater.getValue(), 1, src1.encoding(), simm10, src2.encoding()); - } - - public Cxbg(SPARCAssembler asm, Register src1, int immed5, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.Greater.getValue(), 1, src1.encoding(), simm10, immed5 | ImmedTrue); - } - } - - public static class Cxbge extends Fmt00e { - - public Cxbge(SPARCAssembler asm, Register src1, Register src2, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterEqual.getValue(), 1, src1.encoding(), simm10, src2.encoding()); - } - - public Cxbge(SPARCAssembler asm, Register src1, int immed5, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterEqual.getValue(), 1, src1.encoding(), simm10, immed5 | ImmedTrue); - } - } - - public static class Cxbgu extends Fmt00e { - - public Cxbgu(SPARCAssembler asm, Register src1, Register src2, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterUnsigned.getValue(), 1, src1.encoding(), simm10, src2.encoding()); - } - - public Cxbgu(SPARCAssembler asm, Register src1, int immed5, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.GreaterUnsigned.getValue(), 1, src1.encoding(), simm10, immed5 | ImmedTrue); - } - } - - public static class Cxbl extends Fmt00e { - - public Cxbl(SPARCAssembler asm, Register src1, Register src2, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.Less.getValue(), 1, src1.encoding(), simm10, src2.encoding()); - } - - public Cxbl(SPARCAssembler asm, Register src1, int immed5, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.Less.getValue(), 1, src1.encoding(), simm10, immed5 | ImmedTrue); - } - } - - public static class Cxble extends Fmt00e { - - public Cxble(SPARCAssembler asm, Register src1, Register src2, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqual.getValue(), 1, src1.encoding(), simm10, src2.encoding()); - } - - public Cxble(SPARCAssembler asm, Register src1, int immed5, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqual.getValue(), 1, src1.encoding(), simm10, immed5 | ImmedTrue); - } - } - - public static class Cxbleu extends Fmt00e { - - public Cxbleu(SPARCAssembler asm, Register src1, Register src2, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqualUnsigned.getValue(), 1, src1.encoding(), simm10, src2.encoding()); - } - - public Cxbleu(SPARCAssembler asm, Register src1, int immed5, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.LessEqualUnsigned.getValue(), 1, src1.encoding(), simm10, immed5 | ImmedTrue); - } - } - - public static class Cxbne extends Fmt00e { - - public Cxbne(SPARCAssembler asm, Register src1, Register src2, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.NotEqual.getValue(), 1, src1.encoding(), simm10, src2.encoding()); - } - - public Cxbne(SPARCAssembler asm, Register src1, int immed5, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.NotEqual.getValue(), 1, src1.encoding(), simm10, immed5 | ImmedTrue); - } - } - - public static class Cxbneg extends Fmt00e { - - public Cxbneg(SPARCAssembler asm, Register src1, Register src2, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.Negative.getValue(), 1, src1.encoding(), simm10, src2.encoding()); - } - - public Cxbneg(SPARCAssembler asm, Register src1, int immed5, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.Negative.getValue(), 1, src1.encoding(), simm10, immed5 | ImmedTrue); - } - } - - public static class Cxbpos extends Fmt00e { - - public Cxbpos(SPARCAssembler asm, Register src1, Register src2, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.Positive.getValue(), 1, src1.encoding(), simm10, src2.encoding()); - } - - public Cxbpos(SPARCAssembler asm, Register src1, int immed5, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.Positive.getValue(), 1, src1.encoding(), simm10, immed5 | ImmedTrue); - } - } - - public static class Cxbvc extends Fmt00e { - - public Cxbvc(SPARCAssembler asm, Register src1, Register src2, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowClear.getValue(), 1, src1.encoding(), simm10, src2.encoding()); - } - - public Cxbvc(SPARCAssembler asm, Register src1, int immed5, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowClear.getValue(), 1, src1.encoding(), simm10, immed5 | ImmedTrue); - } - } - - public static class Cxbvs extends Fmt00e { - - public Cxbvs(SPARCAssembler asm, Register src1, Register src2, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowSet.getValue(), 1, src1.encoding(), simm10, src2.encoding()); - } - - public Cxbvs(SPARCAssembler asm, Register src1, int immed5, int simm10) { - super(asm, Ops.BranchOp.getValue(), ConditionFlag.OverflowSet.getValue(), 1, src1.encoding(), simm10, immed5 | ImmedTrue); + public static class CBcondw extends Fmt00e { + public CBcondw(ConditionFlag flag, Register src1, Register src2, Label label) { + super(flag.getValue(), 0, src1.encoding(), -1, 0, src2.encoding(), label); + } + + public CBcondw(ConditionFlag flag, Register src1, int simm5, Label label) { + super(flag.getValue(), 0, src1.encoding(), -1, 1, simm5, label); + } + } + + public static class CBcondx extends Fmt00e { + public CBcondx(ConditionFlag flag, Register src1, Register src2, Label label) { + super(flag.getValue(), 1, src1.encoding(), -1, 0, src2.encoding(), label); + } + + public CBcondx(ConditionFlag flag, Register src1, int simm5, Label label) { + super(flag.getValue(), 1, src1.encoding(), -1, 1, simm5, label); } } diff -r 62d7d16b170b -r 2e4bd9de8682 graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java --- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java Wed Sep 17 09:33:48 2014 -0700 +++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java Wed Sep 17 17:06:37 2014 -0700 @@ -27,8 +27,6 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.asm.*; -import com.oracle.graal.sparc.*; -import com.oracle.graal.sparc.SPARC.CPUFeature; public class SPARCMacroAssembler extends SPARCAssembler { @@ -63,10 +61,6 @@ fmt.write(this, branch); } - protected boolean hasFeature(CPUFeature feature) { - return ((SPARC) this.target.arch).features.contains(feature); - } - @Override public AbstractAddress makeAddress(Register base, int displacement) { return new SPARCAddress(base, displacement); diff -r 62d7d16b170b -r 2e4bd9de8682 graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java --- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Wed Sep 17 09:33:48 2014 -0700 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Wed Sep 17 17:06:37 2014 -0700 @@ -179,9 +179,8 @@ // If we don't have an index register we can use a displacement, otherwise load the // displacement into a register and add it to the base. - if (indexRegister.equals(Value.ILLEGAL)) { + if (indexRegister.equals(Value.ILLEGAL) && SPARCAssembler.isSimm13(finalDisp)) { displacementInt = (int) finalDisp; - assert SPARCAssembler.isSimm13(displacementInt) : displacementInt; } else { displacementInt = 0; if (baseRegister.equals(Value.ILLEGAL)) { diff -r 62d7d16b170b -r 2e4bd9de8682 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java Wed Sep 17 09:33:48 2014 -0700 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java Wed Sep 17 17:06:37 2014 -0700 @@ -85,6 +85,9 @@ if ((config.sparcFeatures & config.vis3Instructions) != 0) { features.add(CPUFeature.VIS3); } + if ((config.sparcFeatures & config.cbcondInstructions) != 0) { + features.add(CPUFeature.CBCOND); + } return features; } diff -r 62d7d16b170b -r 2e4bd9de8682 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Wed Sep 17 09:33:48 2014 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Wed Sep 17 17:06:37 2014 -0700 @@ -798,6 +798,7 @@ @HotSpotVMConstant(name = "VM_Version::vis3_instructions_m", archs = {"sparc"}) @Stable public int vis3Instructions; @HotSpotVMConstant(name = "VM_Version::vis2_instructions_m", archs = {"sparc"}) @Stable public int vis2Instructions; @HotSpotVMConstant(name = "VM_Version::vis1_instructions_m", archs = {"sparc"}) @Stable public int vis1Instructions; + @HotSpotVMConstant(name = "VM_Version::cbcond_instructions_m", archs = {"sparc"}) @Stable public int cbcondInstructions; // offsets, ... @HotSpotVMFlag(name = "StackShadowPages") @Stable public int stackShadowPages; diff -r 62d7d16b170b -r 2e4bd9de8682 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArrayEqualsOp.java --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArrayEqualsOp.java Wed Sep 17 09:33:48 2014 -0700 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArrayEqualsOp.java Wed Sep 17 17:06:37 2014 -0700 @@ -129,16 +129,18 @@ private void emit8ByteCompare(SPARCMacroAssembler masm, Register result, Register array1, Register array2, Register length, Label trueLabel, Label falseLabel) { Label loop = new Label(); Label compareTail = new Label(); - // new Ldx(new SPARCAddress(o6, 3), g0).emit(masm); + Label compareTailCorrectVectorEnd = new Label(); + Register tempReg1 = asRegister(temp4); Register tempReg2 = asRegister(temp5); + + boolean hasCBcond = masm.hasFeature(CPUFeature.CBCOND); + new And(result, VECTOR_SIZE - 1, result).emit(masm); // tail count (in bytes) new Andcc(length, ~(VECTOR_SIZE - 1), length).emit(masm); // vector count (in bytes) new Bpe(CC.Xcc, compareTail).emit(masm); - new Nop().emit(masm); - Label compareTailCorrectVectorEnd = new Label(); - new Sub(length, VECTOR_SIZE, length).emit(masm); + new Sub(length, VECTOR_SIZE, length).emit(masm); // Delay slot new Add(array1, length, array1).emit(masm); new Add(array2, length, array2).emit(masm); new Sub(g0, length, length).emit(masm); @@ -146,11 +148,18 @@ // Compare the last element first new Ldx(new SPARCAddress(array1, 0), tempReg1).emit(masm); new Ldx(new SPARCAddress(array2, 0), tempReg2).emit(masm); - new Cmp(tempReg1, tempReg2).emit(masm); - new Bpne(Xcc, true, false, falseLabel).emit(masm); - new Nop().emit(masm); - new Bpr(RCondition.Rc_z, false, false, length, compareTailCorrectVectorEnd).emit(masm); - new Nop().emit(masm); + if (hasCBcond) { + new CBcondx(ConditionFlag.NotEqual, tempReg1, tempReg2, falseLabel).emit(masm); + new Nop().emit(masm); // for optimal performance (see manual) + new CBcondx(ConditionFlag.Equal, length, 0, compareTailCorrectVectorEnd).emit(masm); + new Nop().emit(masm); // for optimal performance (see manual) + } else { + new Cmp(tempReg1, tempReg2).emit(masm); + new Bpne(Xcc, true, false, falseLabel).emit(masm); + new Nop().emit(masm); + new Bpr(RCondition.Rc_z, false, false, length, compareTailCorrectVectorEnd).emit(masm); + new Nop().emit(masm); + } // Load the first value from array 1 (Later done in back branch delay-slot) new Ldx(new SPARCAddress(array1, length), tempReg1).emit(masm); @@ -164,8 +173,12 @@ new Ldx(new SPARCAddress(array1, length), tempReg1).emit(masm); // Load in delay slot // Tail count zero, therefore we can go to the end - new Bpr(RCondition.Rc_z, true, true, result, trueLabel).emit(masm); - new Nop().emit(masm); + if (hasCBcond) { + new CBcondx(ConditionFlag.Equal, result, 0, trueLabel).emit(masm); + } else { + new Bpr(RCondition.Rc_z, true, true, result, trueLabel).emit(masm); + new Nop().emit(masm); + } masm.bind(compareTailCorrectVectorEnd); // Correct the array pointers @@ -184,18 +197,28 @@ Register tempReg1 = asRegister(temp3); Register tempReg2 = asRegister(temp4); + boolean hasCBcond = masm.hasFeature(CPUFeature.CBCOND); if (kind.getByteCount() <= 4) { // Compare trailing 4 bytes, if any. - new Cmp(result, 4).emit(masm); - new Bpl(Xcc, false, false, compare2Bytes).emit(masm); - new Nop().emit(masm); + if (hasCBcond) { + new CBcondx(ConditionFlag.Less, result, 4, compare2Bytes).emit(masm); + } else { + new Cmp(result, 4).emit(masm); + new Bpl(Xcc, false, false, compare2Bytes).emit(masm); + new Nop().emit(masm); + } + new Lduw(new SPARCAddress(array1, 0), tempReg1).emit(masm); new Lduw(new SPARCAddress(array2, 0), tempReg2).emit(masm); - new Cmp(tempReg1, tempReg2).emit(masm); - new Bpne(Xcc, false, false, falseLabel).emit(masm); - new Nop().emit(masm); + if (hasCBcond) { + new CBcondx(ConditionFlag.NotEqual, tempReg1, tempReg2, falseLabel).emit(masm); + } else { + new Cmp(tempReg1, tempReg2).emit(masm); + new Bpne(Xcc, false, false, falseLabel).emit(masm); + new Nop().emit(masm); + } if (kind.getByteCount() <= 2) { // Move array pointers forward. @@ -206,14 +229,24 @@ // Compare trailing 2 bytes, if any. masm.bind(compare2Bytes); - new Cmp(result, 2).emit(masm); - new Bpl(Xcc, false, true, compare1Byte).emit(masm); - new Nop().emit(masm); + if (hasCBcond) { + new CBcondx(ConditionFlag.Less, result, 2, compare1Byte).emit(masm); + } else { + new Cmp(result, 2).emit(masm); + new Bpl(Xcc, false, true, compare1Byte).emit(masm); + new Nop().emit(masm); + } + new Lduh(new SPARCAddress(array1, 0), tempReg1).emit(masm); new Lduh(new SPARCAddress(array2, 0), tempReg2).emit(masm); - new Cmp(tempReg1, tempReg2).emit(masm); - new Bpne(Xcc, false, true, falseLabel).emit(masm); - new Nop().emit(masm); + + if (hasCBcond) { + new CBcondx(ConditionFlag.NotEqual, tempReg1, tempReg2, falseLabel).emit(masm); + } else { + new Cmp(tempReg1, tempReg2).emit(masm); + new Bpne(Xcc, false, true, falseLabel).emit(masm); + new Nop().emit(masm); + } // The one-byte tail compare is only required for boolean and byte arrays. if (kind.getByteCount() <= 1) { @@ -224,14 +257,23 @@ // Compare trailing byte, if any. masm.bind(compare1Byte); - new Cmp(result, 1).emit(masm); - new Bpne(Xcc, trueLabel).emit(masm); - new Nop().emit(masm); + if (hasCBcond) { + new CBcondx(ConditionFlag.NotEqual, result, 1, trueLabel).emit(masm); + } else { + new Cmp(result, 1).emit(masm); + new Bpne(Xcc, trueLabel).emit(masm); + new Nop().emit(masm); + } new Ldub(new SPARCAddress(array1, 0), tempReg1).emit(masm); new Ldub(new SPARCAddress(array2, 0), tempReg2).emit(masm); - new Cmp(tempReg1, tempReg2).emit(masm); - new Bpne(Xcc, falseLabel).emit(masm); - new Nop().emit(masm); + if (hasCBcond) { + // new SPARCAssembler.Ldx(new SPARCAddress(o7, 1), g3).emit(masm); + new CBcondx(ConditionFlag.NotEqual, tempReg1, tempReg2, falseLabel).emit(masm); + } else { + new Cmp(tempReg1, tempReg2).emit(masm); + new Bpne(Xcc, falseLabel).emit(masm); + new Nop().emit(masm); + } } else { masm.bind(compare1Byte); } diff -r 62d7d16b170b -r 2e4bd9de8682 graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java --- a/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java Wed Sep 17 09:33:48 2014 -0700 +++ b/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java Wed Sep 17 17:06:37 2014 -0700 @@ -291,9 +291,14 @@ return features; } + public boolean hasFeature(CPUFeature feature) { + return features.contains(feature); + } + public enum CPUFeature { VIS1, VIS2, - VIS3 + VIS3, + CBCOND } } diff -r 62d7d16b170b -r 2e4bd9de8682 src/cpu/sparc/vm/vmStructs_sparc.hpp --- a/src/cpu/sparc/vm/vmStructs_sparc.hpp Wed Sep 17 09:33:48 2014 -0700 +++ b/src/cpu/sparc/vm/vmStructs_sparc.hpp Wed Sep 17 17:06:37 2014 -0700 @@ -82,7 +82,8 @@ declare_c2_constant(R_G7_num) \ declare_constant(VM_Version::vis1_instructions_m) \ declare_constant(VM_Version::vis2_instructions_m) \ - declare_constant(VM_Version::vis3_instructions_m) + declare_constant(VM_Version::vis3_instructions_m) \ + declare_constant(VM_Version::cbcond_instructions_m) #define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) diff -r 62d7d16b170b -r 2e4bd9de8682 test/blacklist_sparc.txt --- a/test/blacklist_sparc.txt Wed Sep 17 09:33:48 2014 -0700 +++ b/test/blacklist_sparc.txt Wed Sep 17 17:06:37 2014 -0700 @@ -1,6 +1,3 @@ com.oracle.graal.replacements.test.StandardMethodSubstitutionsTest -com.oracle.graal.replacements.test.StringSubstitutionsTest com.oracle.graal.hotspot.amd64.test.CompressedNullCheckTest -com.oracle.graal.replacements.test.ArraysSubstitutionsTest -com.oracle.graal.compiler.test.CheckGraalInvariants com.oracle.graal.truffle.test.SLTruffleGraalTestSuite