[mips] [IAS] Add support for BNE and BEQ with an immediate operand.
authorToma Tabacu <toma.tabacu@imgtec.com>
Tue, 9 Jun 2015 10:34:31 +0000 (10:34 +0000)
committerToma Tabacu <toma.tabacu@imgtec.com>
Tue, 9 Jun 2015 10:34:31 +0000 (10:34 +0000)
Summary:
For some branches, GAS accepts an immediate instead of the 2nd register operand.
We only implement this for BNE and BEQ for now. Other branch instructions can be added later, if needed.

Reviewers: dsanders

Reviewed By: dsanders

Subscribers: seanbruno, emaste, llvm-commits

Differential Revision: http://reviews.llvm.org/D9666

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

lib/Target/Mips/AsmParser/MipsAsmParser.cpp
lib/Target/Mips/Mips64InstrInfo.td
test/MC/Mips/mips-expansions-bad.s
test/MC/Mips/mips-expansions.s
test/MC/Mips/mips64-expansions.s
test/MC/Mips/set-nomacro.s

index 0d08138f8a94725e573fbb398b120f6c49236d5a..5029482a40d87d35da2eac80f3e8371be269957f 100644 (file)
@@ -208,6 +208,9 @@ class MipsAsmParser : public MCTargetAsmParser {
   bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
                                SmallVectorImpl<MCInst> &Instructions);
 
+  bool expandBranchImm(MCInst &Inst, SMLoc IDLoc,
+                       SmallVectorImpl<MCInst> &Instructions);
+
   void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
                  SmallVectorImpl<MCInst> &Instructions);
 
@@ -1616,6 +1619,8 @@ bool MipsAsmParser::needsExpansion(MCInst &Inst) {
   case Mips::SWM_MM:
   case Mips::JalOneReg:
   case Mips::JalTwoReg:
+  case Mips::BneImm:
+  case Mips::BeqImm:
     return true;
   default:
     return false;
@@ -1642,6 +1647,9 @@ bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
   case Mips::JalOneReg:
   case Mips::JalTwoReg:
     return expandJalWithRegs(Inst, IDLoc, Instructions);
+  case Mips::BneImm:
+  case Mips::BeqImm:
+    return expandBranchImm(Inst, IDLoc, Instructions);
   }
 }
 
@@ -2032,6 +2040,59 @@ bool MipsAsmParser::expandUncondBranchMMPseudo(
   return false;
 }
 
+bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
+                                    SmallVectorImpl<MCInst> &Instructions) {
+  const MCOperand &DstRegOp = Inst.getOperand(0);
+  assert(DstRegOp.isReg() && "expected register operand kind");
+
+  const MCOperand &ImmOp = Inst.getOperand(1);
+  assert(ImmOp.isImm() && "expected immediate operand kind");
+
+  const MCOperand &MemOffsetOp = Inst.getOperand(2);
+  assert(MemOffsetOp.isImm() && "expected immediate operand kind");
+
+  unsigned OpCode = 0;
+  switch(Inst.getOpcode()) {
+    case Mips::BneImm:
+      OpCode = Mips::BNE;
+      break;
+    case Mips::BeqImm:
+      OpCode = Mips::BEQ;
+      break;
+    default:
+      llvm_unreachable("Unknown immediate branch pseudo-instruction.");
+      break;
+  }
+
+  int64_t ImmValue = ImmOp.getImm();
+  if (ImmValue == 0) {
+    MCInst BranchInst;
+    BranchInst.setOpcode(OpCode);
+    BranchInst.addOperand(DstRegOp);
+    BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
+    BranchInst.addOperand(MemOffsetOp);
+    Instructions.push_back(BranchInst);
+  } else {
+    warnIfNoMacro(IDLoc);
+
+    unsigned ATReg = getATReg(IDLoc);
+    if (!ATReg)
+      return true;
+
+    if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), IDLoc,
+                      Instructions))
+      return true;
+
+    MCInst BranchInst;
+    BranchInst.setOpcode(OpCode);
+    BranchInst.addOperand(DstRegOp);
+    BranchInst.addOperand(MCOperand::createReg(ATReg));
+    BranchInst.addOperand(MemOffsetOp);
+    Instructions.push_back(BranchInst);
+  }
+  return false;
+}
+
 void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
                                   SmallVectorImpl<MCInst> &Instructions,
                                   bool isLoad, bool isImmOpnd) {
index 8a27874a37ce73707f4b6c79f5572d4c82601915..83781ff24ac583eeccdfcade4208c7f26dd68e58 100644 (file)
@@ -27,8 +27,6 @@ def uimm16_64      : Operand<i64> {
 // Signed Operand
 def simm10_64 : Operand<i64>;
 
-def imm64: Operand<i64>;
-
 // Transformation Function - get Imm - 32.
 def Subtract32 : SDNodeXForm<imm, [{
   return getImm(N, (unsigned)N->getZExtValue() - 32);
index 6bbde263f5f8d56b083a9a954ea8aecffbd17167..6e747c38c3c5f3e7550e1fafa6d2230e22a39689 100644 (file)
@@ -22,3 +22,7 @@
   # 64-BIT: ori $5, $5, %lo(symbol)
   dli $5, 1
   # 32-BIT: :[[@LINE-1]]:3: error: instruction requires a 64-bit architecture
+  bne $2, 0x100010001, 1332
+  # 32-BIT: :[[@LINE-1]]:3: error: instruction requires a 32-bit immediate
+  beq $2, 0x100010001, 1332
+  # 32-BIT: :[[@LINE-1]]:3: error: instruction requires a 32-bit immediate
index d3fdf39ff8b0fad50cd7f763834592331de1a847..0491c311aef8b8c2be788633e54ca1f08fe98881 100644 (file)
   sdc1 $f0, symbol
 # CHECK: lui     $1, %hi(symbol)
 # CHECK: sdc1    $f0, %lo(symbol)($1)
+
+# Test BNE with an immediate as the 2nd operand.
+  bne $2, 0, 1332
+# CHECK: bnez  $2, 1332          # encoding: [0x4d,0x01,0x40,0x14]
+# CHECK: nop                     # encoding: [0x00,0x00,0x00,0x00]
+
+  bne $2, 123, 1332
+# CHECK: ori   $1, $zero, 123    # encoding: [0x7b,0x00,0x01,0x34]
+# CHECK: bne   $2, $1, 1332      # encoding: [0x4d,0x01,0x41,0x14]
+# CHECK: nop                     # encoding: [0x00,0x00,0x00,0x00]
+
+  bne $2, -2345, 1332
+# CHECK: addiu $1, $zero, -2345  # encoding: [0xd7,0xf6,0x01,0x24]
+# CHECK: bne   $2, $1, 1332      # encoding: [0x4d,0x01,0x41,0x14]
+# CHECK: nop                     # encoding: [0x00,0x00,0x00,0x00]
+
+  bne $2, 65538, 1332
+# CHECK: lui   $1, 1             # encoding: [0x01,0x00,0x01,0x3c]
+# CHECK: ori   $1, $1, 2         # encoding: [0x02,0x00,0x21,0x34]
+# CHECK: bne   $2, $1, 1332      # encoding: [0x4d,0x01,0x41,0x14]
+# CHECK: nop                     # encoding: [0x00,0x00,0x00,0x00]
+
+  bne $2, ~7, 1332
+# CHECK: addiu $1, $zero, -8     # encoding: [0xf8,0xff,0x01,0x24]
+# CHECK: bne   $2, $1, 1332      # encoding: [0x4d,0x01,0x41,0x14]
+# CHECK: nop                     # encoding: [0x00,0x00,0x00,0x00]
+
+  bne $2, 0x10000, 1332
+# CHECK: lui   $1, 1             # encoding: [0x01,0x00,0x01,0x3c]
+# CHECK: bne   $2, $1, 1332      # encoding: [0x4d,0x01,0x41,0x14]
+# CHECK: nop                     # encoding: [0x00,0x00,0x00,0x00]
+
+# Test BEQ with an immediate as the 2nd operand.
+  beq $2, 0, 1332
+# CHECK: beqz  $2, 1332          # encoding: [0x4d,0x01,0x40,0x10]
+# CHECK: nop                     # encoding: [0x00,0x00,0x00,0x00]
+
+  beq $2, 123, 1332
+# CHECK: ori   $1, $zero, 123    # encoding: [0x7b,0x00,0x01,0x34]
+# CHECK: beq   $2, $1, 1332      # encoding: [0x4d,0x01,0x41,0x10]
+# CHECK: nop                     # encoding: [0x00,0x00,0x00,0x00]
+
+  beq $2, -2345, 1332
+# CHECK: addiu $1, $zero, -2345  # encoding: [0xd7,0xf6,0x01,0x24]
+# CHECK: beq   $2, $1, 1332      # encoding: [0x4d,0x01,0x41,0x10]
+# CHECK: nop                     # encoding: [0x00,0x00,0x00,0x00]
+
+  beq $2, 65538, 1332
+# CHECK: lui   $1, 1             # encoding: [0x01,0x00,0x01,0x3c]
+# CHECK: ori   $1, $1, 2         # encoding: [0x02,0x00,0x21,0x34]
+# CHECK: beq   $2, $1, 1332      # encoding: [0x4d,0x01,0x41,0x10]
+# CHECK: nop                     # encoding: [0x00,0x00,0x00,0x00]
+
+  beq $2, ~7, 1332
+# CHECK: addiu $1, $zero, -8     # encoding: [0xf8,0xff,0x01,0x24]
+# CHECK: beq   $2, $1, 1332      # encoding: [0x4d,0x01,0x41,0x10]
+# CHECK: nop                     # encoding: [0x00,0x00,0x00,0x00]
+
+  beq $2, 0x10000, 1332
+# CHECK: lui   $1, 1             # encoding: [0x01,0x00,0x01,0x3c]
+# CHECK: beq   $2, $1, 1332      # encoding: [0x4d,0x01,0x41,0x10]
+# CHECK: nop                     # encoding: [0x00,0x00,0x00,0x00]
index 62a95200f247ea4e55541bd8a050120d9bab92e7..620793a64fdd245a393736f9babc5ef3c87d4fd4 100644 (file)
   dli $9, 0x80000000
 # CHECK: ori  $9, $zero, 32768 # encoding: [0x00,0x80,0x09,0x34]
 # CHECK: dsll $9, $9, 16       # encoding: [0x38,0x4c,0x09,0x00]
+
+# Test bne with an immediate as the 2nd operand.
+  bne $2, 0x100010001, 1332
+# CHECK: lui  $1, 1                 # encoding: [0x01,0x00,0x01,0x3c]
+# CHECK: ori  $1, $1, 1             # encoding: [0x01,0x00,0x21,0x34]
+# CHECK: dsll $1, $1, 16            # encoding: [0x38,0x0c,0x01,0x00]
+# CHECK: ori  $1, $1, 1             # encoding: [0x01,0x00,0x21,0x34]
+# CHECK: bne  $2, $1, 1332          # encoding: [0x4d,0x01,0x41,0x14]
+# CHECK: nop                        # encoding: [0x00,0x00,0x00,0x00]
+
+  bne $2, 0x1000100010001, 1332
+# CHECK: lui  $1, 1                 # encoding: [0x01,0x00,0x01,0x3c]
+# CHECK: ori  $1, $1, 1             # encoding: [0x01,0x00,0x21,0x34]
+# CHECK: dsll $1, $1, 16            # encoding: [0x38,0x0c,0x01,0x00]
+# CHECK: ori  $1, $1, 1             # encoding: [0x01,0x00,0x21,0x34]
+# CHECK: dsll $1, $1, 16            # encoding: [0x38,0x0c,0x01,0x00]
+# CHECK: ori  $1, $1, 1             # encoding: [0x01,0x00,0x21,0x34]
+# CHECK: bne  $2, $1, 1332          # encoding: [0x4d,0x01,0x41,0x14]
+# CHECK: nop                        # encoding: [0x00,0x00,0x00,0x00]
+
+  bne $2, -0x100010001, 1332
+# CHECK: lui  $1, 65535             # encoding: [0xff,0xff,0x01,0x3c]
+# CHECK: ori  $1, $1, 65534         # encoding: [0xfe,0xff,0x21,0x34]
+# CHECK: dsll $1, $1, 16            # encoding: [0x38,0x0c,0x01,0x00]
+# CHECK: ori  $1, $1, 65534         # encoding: [0xfe,0xff,0x21,0x34]
+# CHECK: dsll $1, $1, 16            # encoding: [0x38,0x0c,0x01,0x00]
+# CHECK: ori  $1, $1, 65535         # encoding: [0xff,0xff,0x21,0x34]
+# CHECK: bne  $2, $1, 1332          # encoding: [0x4d,0x01,0x41,0x14]
+# CHECK: nop                        # encoding: [0x00,0x00,0x00,0x00]
+
+  bne $2, -0x1000100010001, 1332
+# CHECK: lui  $1, 65534             # encoding: [0xfe,0xff,0x01,0x3c]
+# CHECK: ori  $1, $1, 65534         # encoding: [0xfe,0xff,0x21,0x34]
+# CHECK: dsll $1, $1, 16            # encoding: [0x38,0x0c,0x01,0x00]
+# CHECK: ori  $1, $1, 65534         # encoding: [0xfe,0xff,0x21,0x34]
+# CHECK: dsll $1, $1, 16            # encoding: [0x38,0x0c,0x01,0x00]
+# CHECK: ori  $1, $1, 65535         # encoding: [0xff,0xff,0x21,0x34]
+# CHECK: bne  $2, $1, 1332          # encoding: [0x4d,0x01,0x41,0x14]
+# CHECK: nop                        # encoding: [0x00,0x00,0x00,0x00]
+
+# Test beq with an immediate as the 2nd operand.
+  beq $2, 0x100010001, 1332
+# CHECK: lui  $1, 1                 # encoding: [0x01,0x00,0x01,0x3c]
+# CHECK: ori  $1, $1, 1             # encoding: [0x01,0x00,0x21,0x34]
+# CHECK: dsll $1, $1, 16            # encoding: [0x38,0x0c,0x01,0x00]
+# CHECK: ori  $1, $1, 1             # encoding: [0x01,0x00,0x21,0x34]
+# CHECK: beq  $2, $1, 1332          # encoding: [0x4d,0x01,0x41,0x10]
+# CHECK: nop                        # encoding: [0x00,0x00,0x00,0x00]
+
+  beq $2, 0x1000100010001, 1332
+# CHECK: lui  $1, 1                 # encoding: [0x01,0x00,0x01,0x3c]
+# CHECK: ori  $1, $1, 1             # encoding: [0x01,0x00,0x21,0x34]
+# CHECK: dsll $1, $1, 16            # encoding: [0x38,0x0c,0x01,0x00]
+# CHECK: ori  $1, $1, 1             # encoding: [0x01,0x00,0x21,0x34]
+# CHECK: dsll $1, $1, 16            # encoding: [0x38,0x0c,0x01,0x00]
+# CHECK: ori  $1, $1, 1             # encoding: [0x01,0x00,0x21,0x34]
+# CHECK: beq  $2, $1, 1332          # encoding: [0x4d,0x01,0x41,0x10]
+# CHECK: nop                        # encoding: [0x00,0x00,0x00,0x00]
+
+  beq $2, -0x100010001, 1332
+# CHECK: lui  $1, 65535             # encoding: [0xff,0xff,0x01,0x3c]
+# CHECK: ori  $1, $1, 65534         # encoding: [0xfe,0xff,0x21,0x34]
+# CHECK: dsll $1, $1, 16            # encoding: [0x38,0x0c,0x01,0x00]
+# CHECK: ori  $1, $1, 65534         # encoding: [0xfe,0xff,0x21,0x34]
+# CHECK: dsll $1, $1, 16            # encoding: [0x38,0x0c,0x01,0x00]
+# CHECK: ori  $1, $1, 65535         # encoding: [0xff,0xff,0x21,0x34]
+# CHECK: beq  $2, $1, 1332          # encoding: [0x4d,0x01,0x41,0x10]
+# CHECK: nop                        # encoding: [0x00,0x00,0x00,0x00]
+
+  beq $2, -0x1000100010001, 1332
+# CHECK: lui  $1, 65534             # encoding: [0xfe,0xff,0x01,0x3c]
+# CHECK: ori  $1, $1, 65534         # encoding: [0xfe,0xff,0x21,0x34]
+# CHECK: dsll $1, $1, 16            # encoding: [0x38,0x0c,0x01,0x00]
+# CHECK: ori  $1, $1, 65534         # encoding: [0xfe,0xff,0x21,0x34]
+# CHECK: dsll $1, $1, 16            # encoding: [0x38,0x0c,0x01,0x00]
+# CHECK: ori  $1, $1, 65535         # encoding: [0xff,0xff,0x21,0x34]
+# CHECK: beq  $2, $1, 1332          # encoding: [0x4d,0x01,0x41,0x10]
+# CHECK: nop                        # encoding: [0x00,0x00,0x00,0x00]
index d81048ff12e14169a1ffa4bfdc343129f32c63c4..0f66bce551b69ca3536efea0f8f5cb30eac9b3bc 100644 (file)
   jal $25
   jal $4, $25
 
+  bne $2, 0, 1332
+  bne $2, 1, 1332
+  beq $2, 0, 1332
+  beq $2, 1, 1332
+
   add $4, $5, $6
 
   .set noreorder
   jal $4, $25
 # CHECK-NOT: [[@LINE-1]]:3: warning: macro instruction expanded into multiple instructions
 
+  bne $2, 0, 1332
+# CHECK-NOT: [[@LINE-1]]:3: warning: macro instruction expanded into multiple instructions
+  bne $2, 1, 1332
+# CHECK: [[@LINE-1]]:3: warning: macro instruction expanded into multiple instructions
+  beq $2, 0, 1332
+# CHECK-NOT: [[@LINE-1]]:3: warning: macro instruction expanded into multiple instructions
+  beq $2, 1, 1332
+# CHECK: [[@LINE-1]]:3: warning: macro instruction expanded into multiple instructions
+
   add $4, $5, $6
 # CHECK-NOT: [[@LINE-1]]:3: warning: macro instruction expanded into multiple instructions