Support for microMIPS jump instructions
authorZoran Jovanovic <zoran.jovanovic@imgtec.com>
Tue, 29 Oct 2013 16:38:59 +0000 (16:38 +0000)
committerZoran Jovanovic <zoran.jovanovic@imgtec.com>
Tue, 29 Oct 2013 16:38:59 +0000 (16:38 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@193623 91177308-0d34-0410-b5e6-96231b3b80d8

18 files changed:
include/llvm/Support/ELF.h
lib/Object/ELF.cpp
lib/Target/Mips/Disassembler/MipsDisassembler.cpp
lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp
lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h
lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
lib/Target/Mips/MicroMipsInstrFormats.td
lib/Target/Mips/MicroMipsInstrInfo.td
lib/Target/Mips/Mips64InstrInfo.td
lib/Target/Mips/MipsCodeEmitter.cpp
lib/Target/Mips/MipsInstrFormats.td
lib/Target/Mips/MipsInstrInfo.td
test/MC/Disassembler/Mips/micromips.txt
test/MC/Disassembler/Mips/micromips_le.txt
test/MC/Mips/micromips-jump-instructions.s [new file with mode: 0644]
test/MC/Mips/micromips-jump26.s [new file with mode: 0644]
test/MC/Mips/micromips-tailr.s [new file with mode: 0644]

index ca53f55971a47e7a0076179ecb4d9b2806d90cfb..ae3b1d307ff2c86a8db0fe57eb92c29c0d0d8a61 100644 (file)
@@ -881,6 +881,7 @@ enum {
   R_MIPS_GLOB_DAT          = 51,
   R_MIPS_COPY              = 126,
   R_MIPS_JUMP_SLOT         = 127,
+  R_MICROMIPS_26_S1        = 133,
   R_MICROMIPS_HI16         = 134,
   R_MICROMIPS_LO16         = 135,
   R_MICROMIPS_GOT16        = 138,
index 37e145df958b3b7cb71487cdad4bff8ddbb006aa..2c62eb157e768ba6836db2d9bf2414b8f339bade 100644 (file)
@@ -161,6 +161,7 @@ StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type) {
       LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GLOB_DAT);
       LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_COPY);
       LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_JUMP_SLOT);
+      LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_26_S1);
       LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_HI16);
       LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_LO16);
       LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_GOT16);
index 37ea3827f8843aab667ca821407cc14d8761581f..f9bf1aff5ee9d2cc40005db77ff9bd7a89688568 100644 (file)
@@ -205,6 +205,13 @@ static DecodeStatus DecodeJumpTarget(MCInst &Inst,
                                      uint64_t Address,
                                      const void *Decoder);
 
+// DecodeJumpTargetMM - Decode microMIPS jump target, which is
+// shifted left by 1 bit.
+static DecodeStatus DecodeJumpTargetMM(MCInst &Inst,
+                                       unsigned Insn,
+                                       uint64_t Address,
+                                       const void *Decoder);
+
 static DecodeStatus DecodeMem(MCInst &Inst,
                               unsigned Insn,
                               uint64_t Address,
@@ -744,6 +751,14 @@ static DecodeStatus DecodeJumpTarget(MCInst &Inst,
   return MCDisassembler::Success;
 }
 
+static DecodeStatus DecodeJumpTargetMM(MCInst &Inst,
+                                       unsigned Insn,
+                                       uint64_t Address,
+                                       const void *Decoder) {
+  unsigned JumpOffset = fieldFromInstruction(Insn, 0, 26) << 1;
+  Inst.addOperand(MCOperand::CreateImm(JumpOffset));
+  return MCDisassembler::Success;
+}
 
 static DecodeStatus DecodeSimm16(MCInst &Inst,
                                  unsigned Insn,
index ae70e25043c5a98c999359b5887de3a17c2dbb82..b47bff66f1111ab050e70d4322ac93d8a7734254 100644 (file)
@@ -81,6 +81,9 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
     // Get the 4th 16-bits.
     Value = ((Value + 0x800080008000LL) >> 48) & 0xffff;
     break;
+  case Mips::fixup_MICROMIPS_26_S1:
+    Value >>= 1;
+    break;
   }
 
   return Value;
@@ -194,6 +197,7 @@ public:
       { "fixup_Mips_GOT_LO16",     0,     16,   0 },
       { "fixup_Mips_CALL_HI16",    0,     16,   0 },
       { "fixup_Mips_CALL_LO16",    0,     16,   0 },
+      { "fixup_MICROMIPS_26_S1",   0,     26,   0 },
       { "fixup_MICROMIPS_HI16",    0,     16,   0 },
       { "fixup_MICROMIPS_LO16",    0,     16,   0 },
       { "fixup_MICROMIPS_GOT16",   0,     16,   0 },
index dc5aabc2e73d8b28f6ca9d8036eca8e914fc6897..60c9f333417fb5c76b56a0fc1686364abbf18c00 100644 (file)
@@ -183,6 +183,9 @@ unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target,
   case Mips::fixup_Mips_CALL_LO16:
     Type = ELF::R_MIPS_CALL_LO16;
     break;
+  case Mips::fixup_MICROMIPS_26_S1:
+    Type = ELF::R_MICROMIPS_26_S1;
+    break;
   case Mips::fixup_MICROMIPS_HI16:
     Type = ELF::R_MICROMIPS_HI16;
     break;
index 5c5b5ed2e10eb692d68ab4fa68eb694e37dbd6b5..ab7eeada4441972779e295ab88b0c210dfd6e46b 100644 (file)
@@ -128,6 +128,9 @@ namespace Mips {
     // resulting in - R_MIPS_CALL_LO16
     fixup_Mips_CALL_LO16,
 
+    // resulting in - R_MICROMIPS_26_S1
+    fixup_MICROMIPS_26_S1,
+
     // resulting in - R_MICROMIPS_HI16
     fixup_MICROMIPS_HI16,
 
index 53558acab15c9b51f679ac97d26771c90a68a416..b965d134edc4014cd3047418955dbb1f970047bb 100644 (file)
@@ -84,6 +84,12 @@ public:
    unsigned getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
                                  SmallVectorImpl<MCFixup> &Fixups) const;
 
+  // getBranchJumpOpValueMM - Return binary encoding of the microMIPS jump
+  // target operand. If the machine operand requires relocation,
+  // record the relocation and return zero.
+  unsigned getJumpTargetOpValueMM(const MCInst &MI, unsigned OpNo,
+                                  SmallVectorImpl<MCFixup> &Fixups) const;
+
    // getBranchTargetOpValue - Return binary encoding of the branch
    // target operand. If the machine operand requires relocation,
    // record the relocation and return zero.
@@ -290,6 +296,23 @@ getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
   return 0;
 }
 
+unsigned MipsMCCodeEmitter::
+getJumpTargetOpValueMM(const MCInst &MI, unsigned OpNo,
+                       SmallVectorImpl<MCFixup> &Fixups) const {
+
+  const MCOperand &MO = MI.getOperand(OpNo);
+  // If the destination is an immediate, divide by 2.
+  if (MO.isImm()) return MO.getImm() >> 1;
+
+  assert(MO.isExpr() &&
+         "getJumpTargetOpValueMM expects only expressions or an immediate");
+
+  const MCExpr *Expr = MO.getExpr();
+  Fixups.push_back(MCFixup::Create(0, Expr,
+                                   MCFixupKind(Mips::fixup_MICROMIPS_26_S1)));
+  return 0;
+}
+
 unsigned MipsMCCodeEmitter::
 getExprOpValue(const MCExpr *Expr,SmallVectorImpl<MCFixup> &Fixups) const {
   int64_t Res;
index 0b82ef8941cfb3a1c0914c1f41e4a02539182a0e..61a3788b90cd55d80f7bd50984d5fe9cfae797f1 100644 (file)
@@ -204,3 +204,37 @@ class EXT_FM_MM<bits<6> funct> : MMArch {
   let Inst{10-6}  = pos;
   let Inst{5-0}   = funct;
 }
+
+class J_FM_MM<bits<6> op> : MMArch {
+  bits<26> target;
+
+  bits<32> Inst;
+
+  let Inst{31-26} = op;
+  let Inst{25-0}  = target;
+}
+
+class JR_FM_MM<bits<8> funct> : MMArch {
+  bits<5> rs;
+
+  bits<32> Inst;
+
+  let Inst{31-21} = 0x00;
+  let Inst{20-16} = rs;
+  let Inst{15-14} = 0x0;
+  let Inst{13-6}  = funct;
+  let Inst{5-0}   = 0x3c;
+}
+
+class JALR_FM_MM<bits<10> funct> : MMArch {
+  bits<5> rs;
+  bits<5> rd;
+
+  bits<32> Inst;
+
+  let Inst{31-26} = 0x00;
+  let Inst{25-21} = rd;
+  let Inst{20-16} = rs;
+  let Inst{15-6}  = funct;
+  let Inst{5-0}   = 0x3c;
+}
index 11b334eecdbc259c74bd73de08f039b0297dbde8..41273bc4de400a1308ad1a707d86e48cfe90a0d7 100644 (file)
@@ -12,6 +12,14 @@ def mem_mm_12 : Operand<i32> {
   let OperandType = "OPERAND_MEMORY";
 }
 
+def jmptarget_mm : Operand<OtherVT> {
+  let EncoderMethod = "getJumpTargetOpValueMM";
+}
+
+def calltarget_mm : Operand<iPTR> {
+  let EncoderMethod = "getJumpTargetOpValueMM";
+}
+
 let canFoldAsLoad = 1 in
 class LoadLeftRightMM<string opstr, SDNode OpNode, RegisterOperand RO,
                       Operand MemOpnd> :
@@ -155,4 +163,18 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in {
                EXT_FM_MM<0x2c>;
   def INS_MM : MMRel, InsBase<"ins", GPR32Opnd, uimm5, MipsIns>,
                EXT_FM_MM<0x0c>;
+
+  /// Jump Instructions
+  let DecoderMethod = "DecodeJumpTargetMM" in {
+    def J_MM        : MMRel, JumpFJ<jmptarget_mm, "j", br, bb, "j">,
+                      J_FM_MM<0x35>;
+    def JAL_MM      : MMRel, JumpLink<"jal", calltarget_mm>, J_FM_MM<0x3d>;
+    def TAILCALL_MM : MMRel, JumpFJ<calltarget_mm, "j", MipsTailCall, imm,
+                                    "tcall">, J_FM_MM<0x3d>, IsTailCall;
+  }
+  def JR_MM   : MMRel, IndirectBranch<"jr", GPR32Opnd>, JR_FM_MM<0x3c>;
+  def JALR_MM : MMRel, JumpLinkReg<"jalr", GPR32Opnd>, JALR_FM_MM<0x03c>;
+  def TAILCALL_R_MM : MMRel, JumpFR<"tcallr", GPR32Opnd, MipsTailCall>,
+                      JR_FM_MM<0x3c>, IsTailCall;
+  def RET_MM : MMRel, RetBase<"ret", GPR32Opnd>, JR_FM_MM<0x3c>;
 }
index dad478e5c5c2641171efea31a3ac7079e46e9c3f..3b74ced716accfde7a64bc50d0e4b7f6307bd20d 100644 (file)
@@ -150,7 +150,7 @@ def SCD : SCBase<"scd", GPR64Opnd>, LW_FM<0x3c>;
 
 /// Jump and Branch Instructions
 let isCodeGenOnly = 1 in {
-def JR64   : IndirectBranch<GPR64Opnd>, MTLO_FM<8>;
+def JR64   : IndirectBranch<"jr", GPR64Opnd>, MTLO_FM<8>;
 def BEQ64  : CBranch<"beq", seteq, GPR64Opnd>, BEQ_FM<4>;
 def BNE64  : CBranch<"bne", setne, GPR64Opnd>, BEQ_FM<5>;
 def BGEZ64 : CBranchZero<"bgez", setge, GPR64Opnd>, BGEZ_FM<1, 1>;
@@ -159,7 +159,8 @@ def BLEZ64 : CBranchZero<"blez", setle, GPR64Opnd>, BGEZ_FM<6, 0>;
 def BLTZ64 : CBranchZero<"bltz", setlt, GPR64Opnd>, BGEZ_FM<1, 0>;
 def JALR64 : JumpLinkReg<"jalr", GPR64Opnd>, JALR_FM;
 def JALR64Pseudo : JumpLinkRegPseudo<GPR64Opnd, JALR, RA, GPR32Opnd>;
-def TAILCALL64_R : JumpFR<GPR64Opnd, MipsTailCall>, MTLO_FM<8>, IsTailCall;
+def TAILCALL64_R : JumpFR<"tcallr", GPR64Opnd, MipsTailCall>,
+                   MTLO_FM<8>, IsTailCall;
 }
 
 /// Multiply and Divide Instructions.
index b50edf162a7c98bf597ba80db3073adc8e8fc5af..3c737e67de5145797750ce3e101b9c8e6bc29f99 100644 (file)
@@ -105,6 +105,7 @@ private:
                          const MachineOperand &MO) const;
 
   unsigned getJumpTargetOpValue(const MachineInstr &MI, unsigned OpNo) const;
+  unsigned getJumpTargetOpValueMM(const MachineInstr &MI, unsigned OpNo) const;
 
   unsigned getBranchTargetOpValue(const MachineInstr &MI, unsigned OpNo) const;
   unsigned getMemEncoding(const MachineInstr &MI, unsigned OpNo) const;
@@ -187,6 +188,12 @@ unsigned MipsCodeEmitter::getJumpTargetOpValue(const MachineInstr &MI,
   return 0;
 }
 
+unsigned MipsCodeEmitter::getJumpTargetOpValueMM(const MachineInstr &MI,
+                                                 unsigned OpNo) const {
+  llvm_unreachable("Unimplemented function.");
+  return 0;
+}
+
 unsigned MipsCodeEmitter::getBranchTargetOpValue(const MachineInstr &MI,
                                                  unsigned OpNo) const {
   MachineOperand MO = MI.getOperand(OpNo);
index 68872fe8f2ffc2d5b5384d4e244c1f458ae370ed..c46706b1515dc7175167b8597a02abd1d94895d3 100644 (file)
@@ -183,7 +183,7 @@ class BranchBase<bits<6> op, dag outs, dag ins, string asmstr,
 // Format J instruction class in Mips : <|opcode|address|>
 //===----------------------------------------------------------------------===//
 
-class FJ<bits<6> op>
+class FJ<bits<6> op> : StdArch
 {
   bits<26> target;
 
@@ -375,7 +375,7 @@ class LUI_FM : StdArch {
   let Inst{15-0}  = imm16;
 }
 
-class JALR_FM {
+class JALR_FM : StdArch {
   bits<5> rd;
   bits<5> rs;
 
index 34f9918c7e939b1e16c2e02d6bbcb59318886498..f5a519d71ccb0d50b3d278cd8e0129ac6e4db441 100644 (file)
@@ -541,9 +541,9 @@ class SetCC_I<string opstr, PatFrag cond_op, Operand Od, PatLeaf imm_type,
 
 // Jump
 class JumpFJ<DAGOperand opnd, string opstr, SDPatternOperator operator,
-             SDPatternOperator targetoperator> :
+             SDPatternOperator targetoperator, string bopstr> :
   InstSE<(outs), (ins opnd:$target), !strconcat(opstr, "\t$target"),
-         [(operator targetoperator:$target)], IIBranch, FrmJ> {
+         [(operator targetoperator:$target)], IIBranch, FrmJ, bopstr> {
   let isTerminator=1;
   let isBarrier=1;
   let hasDelaySlot = 1;
@@ -565,17 +565,20 @@ class UncondBranch<Instruction BEQInst> :
 
 // Base class for indirect branch and return instruction classes.
 let isTerminator=1, isBarrier=1, hasDelaySlot = 1 in
-class JumpFR<RegisterOperand RO, SDPatternOperator operator = null_frag>:
-  InstSE<(outs), (ins RO:$rs), "jr\t$rs", [(operator RO:$rs)], IIBranch, FrmR>;
+class JumpFR<string opstr, RegisterOperand RO,
+             SDPatternOperator operator = null_frag>:
+  InstSE<(outs), (ins RO:$rs), "jr\t$rs", [(operator RO:$rs)], IIBranch,
+         FrmR, opstr>;
 
 // Indirect branch
-class IndirectBranch<RegisterOperand RO>: JumpFR<RO, brind> {
+class IndirectBranch<string opstr, RegisterOperand RO> :
+      JumpFR<opstr, RO, brind> {
   let isBranch = 1;
   let isIndirectBranch = 1;
 }
 
 // Return instruction
-class RetBase<RegisterOperand RO>: JumpFR<RO> {
+class RetBase<string opstr, RegisterOperand RO>: JumpFR<opstr, RO> {
   let isReturn = 1;
   let isCodeGenOnly = 1;
   let hasCtrlDep = 1;
@@ -584,9 +587,9 @@ class RetBase<RegisterOperand RO>: JumpFR<RO> {
 
 // Jump and Link (Call)
 let isCall=1, hasDelaySlot=1, Defs = [RA] in {
-  class JumpLink<string opstr> :
-    InstSE<(outs), (ins calltarget:$target), !strconcat(opstr, "\t$target"),
-           [(MipsJmpLink imm:$target)], IIBranch, FrmJ> {
+  class JumpLink<string opstr, DAGOperand opnd> :
+    InstSE<(outs), (ins opnd:$target), !strconcat(opstr, "\t$target"),
+           [(MipsJmpLink imm:$target)], IIBranch, FrmJ, opstr> {
     let DecoderMethod = "DecodeJumpTarget";
   }
 
@@ -597,7 +600,7 @@ let isCall=1, hasDelaySlot=1, Defs = [RA] in {
 
   class JumpLinkReg<string opstr, RegisterOperand RO>:
     InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"),
-           [], IIBranch, FrmR>;
+           [], IIBranch, FrmR, opstr>;
 
   class BGEZAL_FT<string opstr, RegisterOperand RO> :
     InstSE<(outs), (ins RO:$rs, brtarget:$offset),
@@ -988,9 +991,9 @@ def LL : LLBase<"ll", GPR32Opnd>, LW_FM<0x30>;
 def SC : SCBase<"sc", GPR32Opnd>, LW_FM<0x38>;
 
 /// Jump and Branch Instructions
-def J       : JumpFJ<jmptarget, "j", br, bb>, FJ<2>,
+def J       : MMRel, JumpFJ<jmptarget, "j", br, bb, "j">, FJ<2>,
               Requires<[RelocStatic, HasStdEnc]>, IsBranch;
-def JR      : IndirectBranch<GPR32Opnd>, MTLO_FM<8>;
+def JR      : MMRel, IndirectBranch<"jr", GPR32Opnd>, MTLO_FM<8>;
 def BEQ     : CBranch<"beq", seteq, GPR32Opnd>, BEQ_FM<4>;
 def BNE     : CBranch<"bne", setne, GPR32Opnd>, BEQ_FM<5>;
 def BGEZ    : CBranchZero<"bgez", setge, GPR32Opnd>, BGEZ_FM<1, 1>;
@@ -999,16 +1002,18 @@ def BLEZ    : CBranchZero<"blez", setle, GPR32Opnd>, BGEZ_FM<6, 0>;
 def BLTZ    : CBranchZero<"bltz", setlt, GPR32Opnd>, BGEZ_FM<1, 0>;
 def B       : UncondBranch<BEQ>;
 
-def JAL  : JumpLink<"jal">, FJ<3>;
-def JALR : JumpLinkReg<"jalr", GPR32Opnd>, JALR_FM;
+def JAL  : MMRel, JumpLink<"jal", calltarget>, FJ<3>;
+def JALR : MMRel, JumpLinkReg<"jalr", GPR32Opnd>, JALR_FM;
 def JALRPseudo : JumpLinkRegPseudo<GPR32Opnd, JALR, RA>;
 def BGEZAL : BGEZAL_FT<"bgezal", GPR32Opnd>, BGEZAL_FM<0x11>;
 def BLTZAL : BGEZAL_FT<"bltzal", GPR32Opnd>, BGEZAL_FM<0x10>;
 def BAL_BR : BAL_BR_Pseudo<BGEZAL>;
-def TAILCALL : JumpFJ<calltarget, "j", MipsTailCall, imm>, FJ<2>, IsTailCall;
-def TAILCALL_R : JumpFR<GPR32Opnd, MipsTailCall>, MTLO_FM<8>, IsTailCall;
+def TAILCALL : MMRel, JumpFJ<calltarget, "j", MipsTailCall, imm, "tcall">,
+               FJ<2>, IsTailCall;
+def TAILCALL_R : MMRel, JumpFR<"tcallr", GPR32Opnd, MipsTailCall>, MTLO_FM<8>,
+                 IsTailCall;
 
-def RET : RetBase<GPR32Opnd>, MTLO_FM<8>;
+def RET : MMRel, RetBase<"ret", GPR32Opnd>, MTLO_FM<8>;
 
 // Exception handling related node and instructions.
 // The conversion sequence is:
index 30e2b5719c91ed83a182c9993cd5820e54689bad..e82732616fc5d8a62cac2162bbef054266f33469 100644 (file)
 
 # CHECK: ins $9, $6, 3, 7
 0x01 0x26 0x48 0xcc
+
+# CHECK: j 1328
+0xd4 0x00 0x02 0x98
+
+# CHECK: jal 1328
+0xf4 0x00 0x02 0x98
+
+# CHECK: jalr $ra, $6
+0x03 0xe6 0x0f 0x3c
+
+# CHECK: jr $7
+0x00 0x07 0x0f 0x3c
index ff77de518774aae7dee36aa93906d38db7ebdd93..a42bf7933c1788adc143a79067adcc1cc7b5ec02 100644 (file)
 
 # CHECK: ins $9, $6, 3, 7
 0x26 0x01 0xcc 0x48
+
+# CHECK: j 1328
+0x00 0xd4 0x98 0x02
+
+# CHECK: jal 1328
+0x00 0xf4 0x98 0x02
+
+# CHECK: jalr $ra, $6
+0xe6 0x03 0x3c 0x0f
+
+# CHECK: jr $7
+0x07 0x00 0x3c 0x0f
diff --git a/test/MC/Mips/micromips-jump-instructions.s b/test/MC/Mips/micromips-jump-instructions.s
new file mode 100644 (file)
index 0000000..6f571b6
--- /dev/null
@@ -0,0 +1,40 @@
+# RUN: llvm-mc %s -triple=mipsel -show-encoding -mattr=micromips \
+# RUN: | FileCheck %s -check-prefix=CHECK-EL
+# RUN: llvm-mc %s -triple=mips -show-encoding -mattr=micromips \
+# RUN: | FileCheck %s -check-prefix=CHECK-EB
+# Check that the assembler can handle the documented syntax
+# for jump and branch instructions.
+#------------------------------------------------------------------------------
+# Jump instructions
+#------------------------------------------------------------------------------
+# Little endian
+#------------------------------------------------------------------------------
+# CHECK-EL: j 1328      # encoding: [0x00,0xd4,0x98,0x02]
+# CHECK-EL: nop         # encoding: [0x00,0x00,0x00,0x00]
+# CHECK-EL: jal 1328    # encoding: [0x00,0xf4,0x98,0x02]
+# CHECK-EL: nop         # encoding: [0x00,0x00,0x00,0x00]
+# CHECK-EL: jalr $6     # encoding: [0xe6,0x03,0x3c,0x0f]
+# CHECK-EL: nop         # encoding: [0x00,0x00,0x00,0x00]
+# CHECK-EL: jr $7       # encoding: [0x07,0x00,0x3c,0x0f]
+# CHECK-EL: nop         # encoding: [0x00,0x00,0x00,0x00]
+# CHECK-EL: jr $7       # encoding: [0x07,0x00,0x3c,0x0f]
+# CHECK-EL: nop         # encoding: [0x00,0x00,0x00,0x00]
+#------------------------------------------------------------------------------
+# Big endian
+#------------------------------------------------------------------------------
+# CHECK-EB: j 1328      # encoding: [0xd4,0x00,0x02,0x98]
+# CHECK-EB: nop         # encoding: [0x00,0x00,0x00,0x00]
+# CHECK-EB: jal 1328    # encoding: [0xf4,0x00,0x02,0x98]
+# CHECK-EB: nop         # encoding: [0x00,0x00,0x00,0x00]
+# CHECK-EB: jalr $6     # encoding: [0x03,0xe6,0x0f,0x3c]
+# CHECK-EB: nop         # encoding: [0x00,0x00,0x00,0x00]
+# CHECK-EB: jr $7       # encoding: [0x00,0x07,0x0f,0x3c]
+# CHECK-EB: nop         # encoding: [0x00,0x00,0x00,0x00]
+# CHECK-EB: jr $7       # encoding: [0x00,0x07,0x0f,0x3c]
+# CHECK-EB: nop         # encoding: [0x00,0x00,0x00,0x00]
+
+     j 1328
+     jal 1328
+     jalr $6
+     jr $7
+     j $7
diff --git a/test/MC/Mips/micromips-jump26.s b/test/MC/Mips/micromips-jump26.s
new file mode 100644 (file)
index 0000000..936a998
--- /dev/null
@@ -0,0 +1,23 @@
+# RUN: llvm-mc %s -triple=mipsel-unknown-linux -show-encoding \
+# RUN: -mattr=micromips | FileCheck %s -check-prefix=CHECK-FIXUP
+# RUN: llvm-mc %s -filetype=obj -triple=mipsel-unknown-linux \
+# RUN: -mattr=micromips | llvm-readobj -r \
+# RUN: | FileCheck %s -check-prefix=CHECK-ELF
+#------------------------------------------------------------------------------
+# Check that the assembler can handle the documented syntax
+# for relocations.
+#------------------------------------------------------------------------------
+# CHECK-FIXUP: foo:
+# CHECK-FIXUP:   jal bar # encoding: [A,0xf4'A',A,0b000000AA]
+# CHECK-FIXUP:           #   fixup A - offset: 0,
+# CHECK-FIXUP:               value: bar, kind: fixup_MICROMIPS_26_S1
+# CHECK-FIXUP:   nop     # encoding: [0x00,0x00,0x00,0x00]
+#------------------------------------------------------------------------------
+# Check that the appropriate relocations were created.
+#------------------------------------------------------------------------------
+# CHECK-ELF: Relocations [
+# CHECK-ELF:     0x{{[0-9,A-F]+}} R_MICROMIPS_26_S1
+# CHECK-ELF: ]
+
+foo:
+  jal bar
diff --git a/test/MC/Mips/micromips-tailr.s b/test/MC/Mips/micromips-tailr.s
new file mode 100644 (file)
index 0000000..0c21a7b
--- /dev/null
@@ -0,0 +1,26 @@
+# RUN: llvm-mc %s -triple=mipsel-unknown-linux -show-encoding \
+# RUN: -mattr=micromips | FileCheck %s -check-prefix=CHECK-FIXUP
+# RUN: llvm-mc %s -filetype=obj -triple=mipsel-unknown-linux \
+# RUN: -mattr=micromips | llvm-readobj -r \
+# RUN: | FileCheck %s -check-prefix=CHECK-ELF
+#------------------------------------------------------------------------------
+# Check that the assembler can handle the documented syntax
+# for relocations.
+#------------------------------------------------------------------------------
+# CHECK-FIXUP: foo:
+# CHECK-FIXUP:   addiu $2, $zero, 1332
+# CHECK-FIXUP:         # encoding: [0x40,0x30,0x34,0x05]
+# CHECK-FIXUP:   j foo # encoding: [A,0xd4'A',A,0b000000AA]
+# CHECK-FIXUP:         #   fixup A - offset: 0,
+# CHECK-FIXUP:             value: foo, kind: fixup_MICROMIPS_26_S1
+# CHECK-FIXUP:   nop   # encoding: [0x00,0x00,0x00,0x00]
+#------------------------------------------------------------------------------
+# Check that the appropriate relocations were created.
+#------------------------------------------------------------------------------
+# CHECK-ELF: Relocations [
+# CHECK-ELF:     0x{{[0-9,A-F]+}} R_MICROMIPS_26_S1
+# CHECK-ELF: ]
+
+foo:
+  addiu $2, $0, 1332
+  j foo