changeset 22126:5f622eadfa5b

[SPARC] Put nop after cbcond only for following branch/call instructions
author Stefan Anzinger <stefan.anzinger@oracle.com>
date Tue, 30 Jun 2015 10:41:03 +0200
parents 9f58c0d2bd5a
children a27d4ef9b3a3
files graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCall.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java
diffstat 3 files changed, 66 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Mon Jun 29 11:51:57 2015 -0700
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Tue Jun 30 10:41:03 2015 +0200
@@ -87,6 +87,21 @@
     protected static final int D10LO_SHIFT = 5;
     protected static final int D10HI_SHIFT = 19;
 
+    private static final Ops[] OPS;
+    private static final Op2s[] OP2S;
+    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;
+        }
+    }
+
     public enum Ops {
         // @formatter:off
 
@@ -967,6 +982,7 @@
      */
     // @formatter:on
     private void bcc(Op2s op2, ConditionFlag cond, Annul annul, Label l) {
+        insertNopAfterCBCond();
         int pos = !l.isBound() ? patchUnbound(l) : (l.position() - position()) / 4;
         final int disp = 22;
         assert isSimm(pos, disp);
@@ -975,6 +991,33 @@
         fmt00(a, op2.getValue(), pos);
     }
 
+    public void insertNopAfterCBCond() {
+        int pos = position();
+        if (pos == 0) {
+            return;
+        }
+        int inst = getInt(pos);
+        if (isCBCond(inst)) {
+            nop();
+        }
+    }
+
+    private static boolean isCBCond(int inst) {
+        return getOp(inst).equals(Ops.BranchOp) && getOp2(inst).equals(Op2s.Bpr) && getBits(inst, 28, 28) == 1;
+    }
+
+    private static Ops getOp(int inst) {
+        return OPS[getBits(inst, 31, 30)];
+    }
+
+    private static Op2s getOp2(int inst) {
+        return OP2S[getBits(inst, 24, 22)];
+    }
+
+    private static int getBits(int inst, int hiBit, int lowBit) {
+        return (inst >> lowBit) & ((1 << (hiBit - lowBit + 1)) - 1);
+    }
+
     // @formatter:off
     /**
      * Branch on Integer Condition Codes with Prediction.
@@ -1011,6 +1054,7 @@
      */
     // @formatter:on
     private void bpcc(Op2s op2, ConditionFlag cond, Annul annul, Label l, CC cc, BranchPredict predictTaken) {
+        insertNopAfterCBCond();
         int pos = !l.isBound() ? patchUnbound(l) : (l.position() - position()) / 4;
         final int disp = 19;
         assert isSimm(pos, disp);
@@ -1030,6 +1074,7 @@
      */
     // @formatter:on
     public void bpr(RCondition cond, Annul annul, Label l, BranchPredict predictTaken, Register rs1) {
+        insertNopAfterCBCond();
         int pos = !l.isBound() ? patchUnbound(l) : (l.position() - position()) / 4;
         final int disp = 16;
         assert isSimm(pos, disp);
@@ -1065,6 +1110,7 @@
     }
 
     private void cbcond(int cc2, int i, ConditionFlag cf, Register rs1, int rs2, Label l) {
+        insertNopAfterCBCond();
         int disp10 = !l.isBound() ? patchUnbound(l) : (l.position() - position()) / 4;
         assert isSimm(disp10, 10) && isImm(rs2, 5);
         disp10 &= (1 << 10) - 1;
@@ -1101,13 +1147,18 @@
      * | 01  |                      disp30                             |
      * |31 30|29                                                      0|
      * </pre>
+     *
+     * @return Position of the call instruction
      */
     // @formatter:on
-    public void call(int disp30) {
+    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) {
@@ -1382,11 +1433,18 @@
     }
 
     public void jmpl(Register rs1, Register rs2, Register rd) {
+        insertNopAfterCBCond();
         op3(Jmpl, rs1, rs2, rd);
     }
 
-    public void jmpl(Register rs1, int simm13, Register 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) {
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCall.java	Mon Jun 29 11:51:57 2015 -0700
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCall.java	Tue Jun 30 10:41:03 2015 +0200
@@ -106,8 +106,7 @@
         public void emitControlTransfer(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
             assert !emitted;
             emitCallPrefixCode(crb, masm);
-            before = masm.position();
-            masm.call(0);
+            before = masm.call(0);
             emitted = true;
         }
 
@@ -189,14 +188,16 @@
         if (align) {
             // We don't need alignment on SPARC.
         }
-        int before = masm.position();
+
+        int before;
         if (scratch != null) {
             // offset might not fit a 30-bit displacement, generate an
             // indirect call with a 64-bit immediate
+            before = masm.position();
             new Sethix(0L, scratch, true).emit(masm);
             masm.jmpl(scratch, 0, o7);
         } else {
-            masm.call(0);
+            before = masm.call(0);
         }
         masm.nop();  // delay slot
         int after = masm.position();
@@ -216,8 +217,7 @@
     }
 
     public static void indirectCall(CompilationResultBuilder crb, SPARCMacroAssembler masm, Register dst, InvokeTarget callTarget, LIRFrameState info) {
-        int before = masm.position();
-        masm.jmpl(dst, 0, o7);
+        int before = masm.jmpl(dst, 0, o7);
         masm.nop();  // delay slot
         int after = masm.position();
         crb.recordIndirectCall(before, after, callTarget, info);
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Mon Jun 29 11:51:57 2015 -0700
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Tue Jun 30 10:41:03 2015 +0200
@@ -227,7 +227,6 @@
             }
             try (ScratchRegister scratch = masm.getScratchRegister()) {
                 emitCBCond(masm, actualX, actualY, actualTrueTarget, actualConditionFlag);
-                masm.nop();
             }
             if (needJump) {
                 masm.jmp(actualFalseTarget);