[mips] Add checks for alignment and maximum displacements for most of the
authorMatheus Almeida <matheus.almeida@imgtec.com>
Fri, 13 Dec 2013 11:11:02 +0000 (11:11 +0000)
committerMatheus Almeida <matheus.almeida@imgtec.com>
Fri, 13 Dec 2013 11:11:02 +0000 (11:11 +0000)
branch instructions for mips and micromips instruction sets thus avoiding
the situation of generating branches to undesired locations if offsets
cannot be encoded.

This patch also checks if a fixup cannot be applied and returns a fatal error
if that's the case.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@197223 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/Mips/AsmParser/MipsAsmParser.cpp
lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
test/MC/Mips/micromips-bad-branches.s [new file with mode: 0644]
test/MC/Mips/micromips-diagnostic-fixup.s [new file with mode: 0644]
test/MC/Mips/mips-bad-branches.s [new file with mode: 0644]
test/MC/Mips/mips-diagnostic-fixup.s [new file with mode: 0644]

index 135ca7772f56e531a434974752b58671965906ce..cae3999c12bc94bce5f53c26b83cc840fe8145e5 100644 (file)
@@ -22,6 +22,7 @@
 #include "llvm/MC/MCTargetAsmParser.h"
 #include "llvm/Support/TargetRegistry.h"
 #include "llvm/ADT/APInt.h"
+#include "llvm/Support/MathExtras.h"
 
 using namespace llvm;
 
@@ -220,6 +221,10 @@ class MipsAsmParser : public MCTargetAsmParser {
 
   bool isN64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
 
+  bool isMicroMips() const {
+    return STI.getFeatureBits() & Mips::FeatureMicroMips;
+  }
+
   int matchRegisterName(StringRef Symbol, bool is64BitReg);
 
   int matchCPURegisterName(StringRef Symbol);
@@ -563,6 +568,45 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
                                        SmallVectorImpl<MCInst> &Instructions) {
   const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
   Inst.setLoc(IDLoc);
+
+  if (MCID.isBranch() || MCID.isCall()) {
+    const unsigned Opcode = Inst.getOpcode();
+    MCOperand Offset;
+
+    switch (Opcode) {
+    default:
+      break;
+    case Mips::BEQ:
+    case Mips::BNE:
+      assert (MCID.getNumOperands() == 3 && "unexpected number of operands");
+      Offset = Inst.getOperand(2);
+      if (!Offset.isImm())
+        break; // We'll deal with this situation later on when applying fixups.
+      if (!isIntN(isMicroMips() ? 17 : 18, Offset.getImm()))
+        return Error(IDLoc, "branch target out of range");
+      if (OffsetToAlignment (Offset.getImm(), 1LL << (isMicroMips() ? 1 : 2)))
+        return Error(IDLoc, "branch to misaligned address");
+      break;
+    case Mips::BGEZ:
+    case Mips::BGTZ:
+    case Mips::BLEZ:
+    case Mips::BLTZ:
+    case Mips::BGEZAL:
+    case Mips::BLTZAL:
+    case Mips::BC1F:
+    case Mips::BC1T:
+      assert (MCID.getNumOperands() == 2 && "unexpected number of operands");
+      Offset = Inst.getOperand(1);
+      if (!Offset.isImm())
+        break; // We'll deal with this situation later on when applying fixups.
+      if (!isIntN(isMicroMips() ? 17 : 18, Offset.getImm()))
+        return Error(IDLoc, "branch target out of range");
+      if (OffsetToAlignment (Offset.getImm(), 1LL << (isMicroMips() ? 1 : 2)))
+        return Error(IDLoc, "branch to misaligned address");
+      break;
+    }
+  }
+
   if (MCID.hasDelaySlot() && Options.isReorder()) {
     // If this instruction has a delay slot and .set reorder is active,
     // emit a NOP after it.
index 3e70b23dccc64b3db0ad58fc5ed94cc67b8da4c7..81d976a34cdab20bf957b6b1087e22475ec79497 100644 (file)
@@ -16,6 +16,7 @@
 #include "MCTargetDesc/MipsMCTargetDesc.h"
 #include "llvm/MC/MCAsmBackend.h"
 #include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCDirectives.h"
 #include "llvm/MC/MCELFObjectWriter.h"
 #include "llvm/MC/MCFixupKindInfo.h"
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/MathExtras.h"
 
 using namespace llvm;
 
 // Prepare value for the target space for it
-static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
+static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
+                                 MCContext *Ctx = NULL) {
+
+  unsigned Kind = Fixup.getKind();
 
   // Add/subtract and shift
   switch (Kind) {
@@ -56,8 +61,11 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
     // so the displacement will be one instruction size less.
     Value -= 4;
     // The displacement is then divided by 4 to give us an 18 bit
-    // address range.
-    Value >>= 2;
+    // address range. Forcing a signed division because Value can be negative.
+    Value = (int64_t)Value / 4;
+    // We now check if Value can be encoded as a 16-bit signed immediate.
+    if (!isIntN(15, Value) && Ctx)
+      Ctx->FatalError(Fixup.getLoc(), "out of range PC16 fixup");
     break;
   case Mips::fixup_Mips_26:
     // So far we are only using this type for jumps.
@@ -86,7 +94,11 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
     break;
   case Mips::fixup_MICROMIPS_PC16_S1:
     Value -= 4;
-    Value >>= 1;
+    // Forcing a signed division because Value can be negative.
+    Value = (int64_t)Value / 2;
+    // We now check if Value can be encoded as a 16-bit signed immediate.
+    if (!isIntN(15, Value) && Ctx)
+      Ctx->FatalError(Fixup.getLoc(), "out of range PC16 fixup");
     break;
   }
 
@@ -115,7 +127,7 @@ public:
   void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
                   uint64_t Value) const {
     MCFixupKind Kind = Fixup.getKind();
-    Value = adjustFixupValue((unsigned)Kind, Value);
+    Value = adjustFixupValue(Fixup, Value);
 
     if (!Value)
       return; // Doesn't change encoding.
@@ -273,6 +285,20 @@ public:
       OW->Write32(0);
     return true;
   }
+
+  /// processFixupValue - Target hook to process the literal value of a fixup
+  /// if necessary.
+  void processFixupValue(const MCAssembler &Asm, const MCAsmLayout &Layout,
+                         const MCFixup &Fixup, const MCFragment *DF,
+                         MCValue &Target, uint64_t &Value,
+                         bool &IsResolved) {
+    // At this point we'll ignore the value returned by adjustFixupValue as
+    // we are only checking if the fixup can be applied correctly. We have
+    // access to MCContext from here which allows us to report a fatal error
+    // with *possibly* a source code location.
+    (void)adjustFixupValue(Fixup, Value, &Asm.getContext());
+  }
+
 }; // class MipsAsmBackend
 
 } // namespace
diff --git a/test/MC/Mips/micromips-bad-branches.s b/test/MC/Mips/micromips-bad-branches.s
new file mode 100644 (file)
index 0000000..573605e
--- /dev/null
@@ -0,0 +1,225 @@
+# RUN: not llvm-mc %s -triple=mipsel-unknown-linux -mcpu=mips32r2 -mattr=+msa -arch=mips -mattr=+micromips 2>&1  | FileCheck %s
+#
+# CHECK: error: branch to misaligned address
+# CHECK:        b -65535
+# CHECK: error: branch target out of range
+# CHECK:        b -65537
+# CHECK: error: branch to misaligned address
+# CHECK:        b 65535
+# CHECK: error: branch target out of range
+# CHECK:        b 65536
+
+# CHECK: error: branch to misaligned address
+# CHECK:        beq $1, $1, -65535
+# CHECK: error: branch target out of range
+# CHECK:        beq $1, $1, -65537
+# CHECK: error: branch to misaligned address
+# CHECK:        beq $1, $1, 65535
+# CHECK: error: branch target out of range
+# CHECK:        beq $1, $1, 65536
+
+# CHECK: error: branch to misaligned address
+# CHECK:        bne $1, $1, -65535
+# CHECK: error: branch target out of range
+# CHECK:        bne $1, $1, -65537
+# CHECK: error: branch to misaligned address
+# CHECK:        bne $1, $1, 65535
+# CHECK: error: branch target out of range
+# CHECK:        bne $1, $1, 65536
+
+# CHECK: error: branch to misaligned address
+# CHECK:        bal -65535
+# CHECK: error: branch target out of range
+# CHECK:        bal -65537
+# CHECK: error: branch to misaligned address
+# CHECK:        bal 65535
+# CHECK: error: branch target out of range
+# CHECK:        bal 65536
+
+# CHECK: error: branch to misaligned address
+# CHECK:        bgez $1, -65535
+# CHECK: error: branch target out of range
+# CHECK:        bgez $1, -65537
+# CHECK: error: branch to misaligned address
+# CHECK:        bgez $1, 65535
+# CHECK: error: branch target out of range
+# CHECK:        bgez $1, 65536
+
+# CHECK: error: branch to misaligned address
+# CHECK:        bgtz $1, -65535
+# CHECK: error: branch target out of range
+# CHECK:        bgtz $1, -65537
+# CHECK: error: branch to misaligned address
+# CHECK:        bgtz $1, 65535
+# CHECK: error: branch target out of range
+# CHECK:        bgtz $1, 65536
+
+# CHECK: error: branch to misaligned address
+# CHECK:        blez $1, -65535
+# CHECK: error: branch target out of range
+# CHECK:        blez $1, -65537
+# CHECK: error: branch to misaligned address
+# CHECK:        blez $1, 65535
+# CHECK: error: branch target out of range
+# CHECK:        blez $1, 65536
+
+# CHECK: error: branch to misaligned address
+# CHECK:        bltz $1, -65535
+# CHECK: error: branch target out of range
+# CHECK:        bltz $1, -65537
+# CHECK: error: branch to misaligned address
+# CHECK:        bltz $1, 65535
+# CHECK: error: branch target out of range
+# CHECK:        bltz $1, 65536
+
+# CHECK: error: branch to misaligned address
+# CHECK:        bgezal $1, -65535
+# CHECK: error: branch target out of range
+# CHECK:        bgezal $1, -65537
+# CHECK: error: branch to misaligned address
+# CHECK:        bgezal $1, 65535
+# CHECK: error: branch target out of range
+# CHECK:        bgezal $1, 65536
+
+# CHECK: error: branch to misaligned address
+# CHECK:        bltzal $1, -65535
+# CHECK: error: branch target out of range
+# CHECK:        bltzal $1, -65537
+# CHECK: error: branch to misaligned address
+# CHECK:        bltzal $1, 65535
+# CHECK: error: branch target out of range
+# CHECK:        bltzal $1, 65536
+
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1f -65535
+# CHECK: error: branch target out of range
+# CHECK:        bc1f -65537
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1f 65535
+# CHECK: error: branch target out of range
+# CHECK:        bc1f 65536
+
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1f $fcc0, -65535
+# CHECK: error: branch target out of range
+# CHECK:        bc1f $fcc0, -65537
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1f $fcc0, 65535
+# CHECK: error: branch target out of range
+# CHECK:        bc1f $fcc0, 65536
+
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1t -65535
+# CHECK: error: branch target out of range
+# CHECK:        bc1t -65537
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1t 65535
+# CHECK: error: branch target out of range
+# CHECK:        bc1t 65536
+
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1t $fcc0, -65535
+# CHECK: error: branch target out of range
+# CHECK:        bc1t $fcc0, -65537
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1t $fcc0, 65535
+# CHECK: error: branch target out of range
+# CHECK:        bc1t $fcc0, 65536
+
+        b -65535
+        b -65536
+        b -65537
+        b 65534
+        b 65535
+        b 65536
+
+        beq $1, $1, -65535
+        beq $1, $1, -65536
+        beq $1, $1, -65537
+        beq $1, $1, 65534
+        beq $1, $1, 65535
+        beq $1, $1, 65536
+
+        bne $1, $1, -65535
+        bne $1, $1, -65536
+        bne $1, $1, -65537
+        bne $1, $1, 65534
+        bne $1, $1, 65535
+        bne $1, $1, 65536
+
+        bal -65535
+        bal -65536
+        bal -65537
+        bal 65534
+        bal 65535
+        bal 65536
+
+        bgez $1, -65535
+        bgez $1, -65536
+        bgez $1, -65537
+        bgez $1, 65534
+        bgez $1, 65535
+        bgez $1, 65536
+
+        bgtz $1, -65535
+        bgtz $1, -65536
+        bgtz $1, -65537
+        bgtz $1, 65534
+        bgtz $1, 65535
+        bgtz $1, 65536
+
+        blez $1, -65535
+        blez $1, -65536
+        blez $1, -65537
+        blez $1, 65534
+        blez $1, 65535
+        blez $1, 65536
+
+        bltz $1, -65535
+        bltz $1, -65536
+        bltz $1, -65537
+        bltz $1, 65534
+        bltz $1, 65535
+        bltz $1, 65536
+
+        bgezal $1, -65535
+        bgezal $1, -65536
+        bgezal $1, -65537
+        bgezal $1, 65534
+        bgezal $1, 65535
+        bgezal $1, 65536
+
+        bltzal $1, -65535
+        bltzal $1, -65536
+        bltzal $1, -65537
+        bltzal $1, 65534
+        bltzal $1, 65535
+        bltzal $1, 65536
+
+        bc1f -65535
+        bc1f -65536
+        bc1f -65537
+        bc1f 65534
+        bc1f 65535
+        bc1f 65536
+
+        bc1f $fcc0, -65535
+        bc1f $fcc0, -65536
+        bc1f $fcc0, -65537
+        bc1f $fcc0, 65534
+        bc1f $fcc0, 65535
+        bc1f $fcc0, 65536
+
+        bc1t -65535
+        bc1t -65536
+        bc1t -65537
+        bc1t 65534
+        bc1t 65535
+        bc1t 65536
+
+        bc1t $fcc0, -65535
+        bc1t $fcc0, -65536
+        bc1t $fcc0, -65537
+        bc1t $fcc0, 65534
+        bc1t $fcc0, 65535
+        bc1t $fcc0, 65536
diff --git a/test/MC/Mips/micromips-diagnostic-fixup.s b/test/MC/Mips/micromips-diagnostic-fixup.s
new file mode 100644 (file)
index 0000000..f8fe447
--- /dev/null
@@ -0,0 +1,10 @@
+# RUN: not llvm-mc %s -triple=mipsel-unknown-linux -mcpu=mips32r2 -arch=mips -mattr=+micromips 2>&1 -filetype=obj | FileCheck %s
+#
+# CHECK: LLVM ERROR: out of range PC16 fixup
+
+.text
+  b foo
+  .space 65536 - 8, 1   # -8 = size of b instr plus size of automatically inserted nop
+  nop                   # This instr makes the branch too long to fit into a 17-bit offset
+foo:
+  add $0,$0,$0
diff --git a/test/MC/Mips/mips-bad-branches.s b/test/MC/Mips/mips-bad-branches.s
new file mode 100644 (file)
index 0000000..321b3c4
--- /dev/null
@@ -0,0 +1,409 @@
+# RUN: not llvm-mc %s -triple=mipsel-unknown-linux -mcpu=mips32r2 -arch=mips 2>&1 | FileCheck %s
+#
+# CHECK: error: branch to misaligned address
+# CHECK:        b -131069
+# CHECK: error: branch to misaligned address
+# CHECK:        b -131070
+# CHECK: error: branch to misaligned address
+# CHECK:        b -131071
+# CHECK: error: branch target out of range
+# CHECK:        b -131073
+# CHECK: error: branch to misaligned address
+# CHECK:        b 131069
+# CHECK: error: branch to misaligned address
+# CHECK:        b 131070
+# CHECK: error: branch to misaligned address
+# CHECK:        b 131071
+# CHECK: error: branch target out of range
+# CHECK:        b 131072
+
+# CHECK: error: branch to misaligned address
+# CHECK:        beq $1, $1, -131069
+# CHECK: error: branch to misaligned address
+# CHECK:        beq $1, $1, -131070
+# CHECK: error: branch to misaligned address
+# CHECK:        beq $1, $1, -131071
+# CHECK: error: branch target out of range
+# CHECK:        beq $1, $1, -131073
+# CHECK: error: branch to misaligned address
+# CHECK:        beq $1, $1, 131069
+# CHECK: error: branch to misaligned address
+# CHECK:        beq $1, $1, 131070
+# CHECK: error: branch to misaligned address
+# CHECK:        beq $1, $1, 131071
+# CHECK: error: branch target out of range
+# CHECK:        beq $1, $1, 131072
+
+# CHECK: error: branch to misaligned address
+# CHECK:        bne $1, $1, -131069
+# CHECK: error: branch to misaligned address
+# CHECK:        bne $1, $1, -131070
+# CHECK: error: branch to misaligned address
+# CHECK:        bne $1, $1, -131071
+# CHECK: error: branch target out of range
+# CHECK:        bne $1, $1, -131073
+# CHECK: error: branch to misaligned address
+# CHECK:        bne $1, $1, 131069
+# CHECK: error: branch to misaligned address
+# CHECK:        bne $1, $1, 131070
+# CHECK: error: branch to misaligned address
+# CHECK:        bne $1, $1, 131071
+# CHECK: error: branch target out of range
+# CHECK:        bne $1, $1, 131072
+
+# CHECK: error: branch to misaligned address
+# CHECK:        bal -131069
+# CHECK: error: branch to misaligned address
+# CHECK:        bal -131070
+# CHECK: error: branch to misaligned address
+# CHECK:        bal -131071
+# CHECK: error: branch target out of range
+# CHECK:        bal -131073
+# CHECK: error: branch to misaligned address
+# CHECK:        bal 131069
+# CHECK: error: branch to misaligned address
+# CHECK:        bal 131070
+# CHECK: error: branch to misaligned address
+# CHECK:        bal 131071
+# CHECK: error: branch target out of range
+# CHECK:        bal 131072
+
+# CHECK: error: branch to misaligned address
+# CHECK:        bgez $1, -131069
+# CHECK: error: branch to misaligned address
+# CHECK:        bgez $1, -131070
+# CHECK: error: branch to misaligned address
+# CHECK:        bgez $1, -131071
+# CHECK: error: branch target out of range
+# CHECK:        bgez $1, -131073
+# CHECK: error: branch to misaligned address
+# CHECK:        bgez $1, 131069
+# CHECK: error: branch to misaligned address
+# CHECK:        bgez $1, 131070
+# CHECK: error: branch to misaligned address
+# CHECK:        bgez $1, 131071
+# CHECK: error: branch target out of range
+# CHECK:        bgez $1, 131072
+
+# CHECK: error: branch to misaligned address
+# CHECK:        bgtz $1, -131069
+# CHECK: error: branch to misaligned address
+# CHECK:        bgtz $1, -131070
+# CHECK: error: branch to misaligned address
+# CHECK:        bgtz $1, -131071
+# CHECK: error: branch target out of range
+# CHECK:        bgtz $1, -131073
+# CHECK: error: branch to misaligned address
+# CHECK:        bgtz $1, 131069
+# CHECK: error: branch to misaligned address
+# CHECK:        bgtz $1, 131070
+# CHECK: error: branch to misaligned address
+# CHECK:        bgtz $1, 131071
+# CHECK: error: branch target out of range
+# CHECK:        bgtz $1, 131072
+
+# CHECK: error: branch to misaligned address
+# CHECK:        blez $1, -131069
+# CHECK: error: branch to misaligned address
+# CHECK:        blez $1, -131070
+# CHECK: error: branch to misaligned address
+# CHECK:        blez $1, -131071
+# CHECK: error: branch target out of range
+# CHECK:        blez $1, -131073
+# CHECK: error: branch to misaligned address
+# CHECK:        blez $1, 131069
+# CHECK: error: branch to misaligned address
+# CHECK:        blez $1, 131070
+# CHECK: error: branch to misaligned address
+# CHECK:        blez $1, 131071
+# CHECK: error: branch target out of range
+# CHECK:        blez $1, 131072
+
+# CHECK: error: branch to misaligned address
+# CHECK:        bltz $1, -131069
+# CHECK: error: branch to misaligned address
+# CHECK:        bltz $1, -131070
+# CHECK: error: branch to misaligned address
+# CHECK:        bltz $1, -131071
+# CHECK: error: branch target out of range
+# CHECK:        bltz $1, -131073
+# CHECK: error: branch to misaligned address
+# CHECK:        bltz $1, 131069
+# CHECK: error: branch to misaligned address
+# CHECK:        bltz $1, 131070
+# CHECK: error: branch to misaligned address
+# CHECK:        bltz $1, 131071
+# CHECK: error: branch target out of range
+# CHECK:        bltz $1, 131072
+
+# CHECK: error: branch to misaligned address
+# CHECK:        bgezal $1, -131069
+# CHECK: error: branch to misaligned address
+# CHECK:        bgezal $1, -131070
+# CHECK: error: branch to misaligned address
+# CHECK:        bgezal $1, -131071
+# CHECK: error: branch target out of range
+# CHECK:        bgezal $1, -131073
+# CHECK: error: branch to misaligned address
+# CHECK:        bgezal $1, 131069
+# CHECK: error: branch to misaligned address
+# CHECK:        bgezal $1, 131070
+# CHECK: error: branch to misaligned address
+# CHECK:        bgezal $1, 131071
+# CHECK: error: branch target out of range
+# CHECK:        bgezal $1, 131072
+
+# CHECK: error: branch to misaligned address
+# CHECK:        bltzal $1, -131069
+# CHECK: error: branch to misaligned address
+# CHECK:        bltzal $1, -131070
+# CHECK: error: branch to misaligned address
+# CHECK:        bltzal $1, -131071
+# CHECK: error: branch target out of range
+# CHECK:        bltzal $1, -131073
+# CHECK: error: branch to misaligned address
+# CHECK:        bltzal $1, 131069
+# CHECK: error: branch to misaligned address
+# CHECK:        bltzal $1, 131070
+# CHECK: error: branch to misaligned address
+# CHECK:        bltzal $1, 131071
+# CHECK: error: branch target out of range
+# CHECK:        bltzal $1, 131072
+
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1f -131069
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1f -131070
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1f -131071
+# CHECK: error: branch target out of range
+# CHECK:        bc1f -131073
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1f 131069
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1f 131070
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1f 131071
+# CHECK: error: branch target out of range
+# CHECK:        bc1f 131072
+
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1f $fcc0, -131069
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1f $fcc0, -131070
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1f $fcc0, -131071
+# CHECK: error: branch target out of range
+# CHECK:        bc1f $fcc0, -131073
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1f $fcc0, 131069
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1f $fcc0, 131070
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1f $fcc0, 131071
+# CHECK: error: branch target out of range
+# CHECK:        bc1f $fcc0, 131072
+
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1t -131069
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1t -131070
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1t -131071
+# CHECK: error: branch target out of range
+# CHECK:        bc1t -131073
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1t 131069
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1t 131070
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1t 131071
+# CHECK: error: branch target out of range
+# CHECK:        bc1t 131072
+
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1t $fcc0, -131069
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1t $fcc0, -131070
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1t $fcc0, -131071
+# CHECK: error: branch target out of range
+# CHECK:        bc1t $fcc0, -131073
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1t $fcc0, 131069
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1t $fcc0, 131070
+# CHECK: error: branch to misaligned address
+# CHECK:        bc1t $fcc0, 131071
+# CHECK: error: branch target out of range
+# CHECK:        bc1t $fcc0, 131072
+
+.text
+.set noat
+  b -131068
+  b -131069
+  b -131070
+  b -131071
+  b -131072
+  b -131073
+  b 131068
+  b 131069
+  b 131070
+  b 131071
+  b 131072
+
+  beq $1, $1, -131068
+  beq $1, $1, -131069
+  beq $1, $1, -131070
+  beq $1, $1, -131071
+  beq $1, $1, -131072
+  beq $1, $1, -131073
+  beq $1, $1, 131068
+  beq $1, $1, 131069
+  beq $1, $1, 131070
+  beq $1, $1, 131071
+  beq $1, $1, 131072
+
+  bne $1, $1, -131068
+  bne $1, $1, -131069
+  bne $1, $1, -131070
+  bne $1, $1, -131071
+  bne $1, $1, -131072
+  bne $1, $1, -131073
+  bne $1, $1, 131068
+  bne $1, $1, 131069
+  bne $1, $1, 131070
+  bne $1, $1, 131071
+  bne $1, $1, 131072
+
+  bal -131068
+  bal -131069
+  bal -131070
+  bal -131071
+  bal -131072
+  bal -131073
+  bal 131068
+  bal 131069
+  bal 131070
+  bal 131071
+  bal 131072
+
+  bgez $1, -131068
+  bgez $1, -131069
+  bgez $1, -131070
+  bgez $1, -131071
+  bgez $1, -131072
+  bgez $1, -131073
+  bgez $1, 131068
+  bgez $1, 131069
+  bgez $1, 131070
+  bgez $1, 131071
+  bgez $1, 131072
+
+  bgtz $1, -131068
+  bgtz $1, -131069
+  bgtz $1, -131070
+  bgtz $1, -131071
+  bgtz $1, -131072
+  bgtz $1, -131073
+  bgtz $1, 131068
+  bgtz $1, 131069
+  bgtz $1, 131070
+  bgtz $1, 131071
+  bgtz $1, 131072
+
+  blez $1, -131068
+  blez $1, -131069
+  blez $1, -131070
+  blez $1, -131071
+  blez $1, -131072
+  blez $1, -131073
+  blez $1, 131068
+  blez $1, 131069
+  blez $1, 131070
+  blez $1, 131071
+  blez $1, 131072
+
+  bltz $1, -131068
+  bltz $1, -131069
+  bltz $1, -131070
+  bltz $1, -131071
+  bltz $1, -131072
+  bltz $1, -131073
+  bltz $1, 131068
+  bltz $1, 131069
+  bltz $1, 131070
+  bltz $1, 131071
+  bltz $1, 131072
+
+  bgezal $1, -131068
+  bgezal $1, -131069
+  bgezal $1, -131070
+  bgezal $1, -131071
+  bgezal $1, -131072
+  bgezal $1, -131073
+  bgezal $1, 131068
+  bgezal $1, 131069
+  bgezal $1, 131070
+  bgezal $1, 131071
+  bgezal $1, 131072
+
+  bltzal $1, -131068
+  bltzal $1, -131069
+  bltzal $1, -131070
+  bltzal $1, -131071
+  bltzal $1, -131072
+  bltzal $1, -131073
+  bltzal $1, 131068
+  bltzal $1, 131069
+  bltzal $1, 131070
+  bltzal $1, 131071
+  bltzal $1, 131072
+
+  bc1f -131068
+  bc1f -131069
+  bc1f -131070
+  bc1f -131071
+  bc1f -131072
+  bc1f -131073
+  bc1f 131068
+  bc1f 131069
+  bc1f 131070
+  bc1f 131071
+  bc1f 131072
+
+  bc1f $fcc0, -131068
+  bc1f $fcc0, -131069
+  bc1f $fcc0, -131070
+  bc1f $fcc0, -131071
+  bc1f $fcc0, -131072
+  bc1f $fcc0, -131073
+  bc1f $fcc0, 131068
+  bc1f $fcc0, 131069
+  bc1f $fcc0, 131070
+  bc1f $fcc0, 131071
+  bc1f $fcc0, 131072
+
+  bc1t -131068
+  bc1t -131069
+  bc1t -131070
+  bc1t -131071
+  bc1t -131072
+  bc1t -131073
+  bc1t 131068
+  bc1t 131069
+  bc1t 131070
+  bc1t 131071
+  bc1t 131072
+
+  bc1t $fcc0, -131068
+  bc1t $fcc0, -131069
+  bc1t $fcc0, -131070
+  bc1t $fcc0, -131071
+  bc1t $fcc0, -131072
+  bc1t $fcc0, -131073
+  bc1t $fcc0, 131068
+  bc1t $fcc0, 131069
+  bc1t $fcc0, 131070
+  bc1t $fcc0, 131071
+  bc1t $fcc0, 131072
diff --git a/test/MC/Mips/mips-diagnostic-fixup.s b/test/MC/Mips/mips-diagnostic-fixup.s
new file mode 100644 (file)
index 0000000..864d739
--- /dev/null
@@ -0,0 +1,10 @@
+# RUN: not llvm-mc %s -triple=mipsel-unknown-linux -mcpu=mips32r2 -arch=mips 2>&1 -filetype=obj | FileCheck %s
+#
+# CHECK: LLVM ERROR: out of range PC16 fixup
+
+.text
+  b foo
+  .space 131072 - 8, 1  # -8 = size of b instr plus size of automatically inserted nop
+  nop                   # This instr makes the branch too long to fit into a 18-bit offset
+foo:
+  add $0,$0,$0