[mips][microMIPS] Implement ADDIUPC instruction
authorJozef Kolek <jozef.kolek@imgtec.com>
Wed, 21 Jan 2015 12:10:11 +0000 (12:10 +0000)
committerJozef Kolek <jozef.kolek@imgtec.com>
Wed, 21 Jan 2015 12:10:11 +0000 (12:10 +0000)
Differential Revision: http://reviews.llvm.org/D6582

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

lib/Target/Mips/AsmParser/MipsAsmParser.cpp
lib/Target/Mips/Disassembler/MipsDisassembler.cpp
lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h
lib/Target/Mips/MicroMipsInstrFormats.td
lib/Target/Mips/MicroMipsInstrInfo.td
test/MC/Disassembler/Mips/micromips.txt
test/MC/Disassembler/Mips/micromips_le.txt
test/MC/Mips/micromips-alu-instructions.s
test/MC/Mips/micromips-invalid.s

index 7db5b34204c340cdb78054d757db85d1cf34ff51..efb987e281b9bb1fdc855cabbb74df2a55325bd2 100644 (file)
@@ -1396,6 +1396,14 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
         if (!isUInt<5>(Imm))
           return Error(IDLoc, "immediate operand value out of range");
         break;
+      case Mips::ADDIUPC_MM:
+        MCOperand Opnd = Inst.getOperand(1);
+        if (!Opnd.isImm())
+          return Error(IDLoc, "expected immediate operand kind");
+        int Imm = Opnd.getImm();
+        if ((Imm % 4 != 0) || !isIntN(25, Imm))
+          return Error(IDLoc, "immediate operand value out of range");
+        break;
     }
   }
 
index 98fc1ebba1559f20eff4818fe2d2e7516d9773c3..501e066c910f33f408b9f620eb7ce8530e5a3b38 100644 (file)
@@ -370,6 +370,9 @@ static DecodeStatus DecodeANDI16Imm(MCInst &Inst, unsigned Insn,
 static DecodeStatus DecodeUImm5lsl2(MCInst &Inst, unsigned Insn,
                                    uint64_t Address, const void *Decoder);
 
+static DecodeStatus DecodeSimm23Lsl2(MCInst &Inst, unsigned Insn,
+                                     uint64_t Address, const void *Decoder);
+
 /// INSVE_[BHWD] have an implicit operand that the generated decoder doesn't
 /// handle.
 template <typename InsnType>
@@ -1756,3 +1759,9 @@ static DecodeStatus DecodeRegListOperand16(MCInst &Inst, unsigned Insn,
 
   return MCDisassembler::Success;
 }
+
+static DecodeStatus DecodeSimm23Lsl2(MCInst &Inst, unsigned Insn,
+                                     uint64_t Address, const void *Decoder) {
+  Inst.addOperand(MCOperand::CreateImm(SignExtend32<23>(Insn) << 2));
+  return MCDisassembler::Success;
+}
index a54a2eb6b4526f656aa88ee2f2e6d0a610de937a..1fe85ec79a5d955b4501cefd7ab38182c1cf7f1c 100644 (file)
@@ -905,4 +905,16 @@ MipsMCCodeEmitter::getRegisterPairOpValue(const MCInst &MI, unsigned OpNo,
   return getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
 }
 
+unsigned
+MipsMCCodeEmitter::getSimm23Lsl2Encoding(const MCInst &MI, unsigned OpNo,
+                                         SmallVectorImpl<MCFixup> &Fixups,
+                                         const MCSubtargetInfo &STI) const {
+  const MCOperand &MO = MI.getOperand(OpNo);
+  assert(MO.isImm() && "getSimm23Lsl2Encoding expects only an immediate");
+  // The immediate is encoded as 'immediate >> 2'.
+  unsigned Res = static_cast<unsigned>(MO.getImm());
+  assert((Res & 3) == 0);
+  return Res >> 2;
+}
+
 #include "MipsGenMCCodeEmitter.inc"
index 0f0f49ddb9788e480eebf2663bb5bf5428adde8c..33cc8b63f0dd839da61fdbdc3619b8b810431b49 100644 (file)
@@ -198,6 +198,10 @@ public:
                                   SmallVectorImpl<MCFixup> &Fixups,
                                   const MCSubtargetInfo &STI) const;
 
+  unsigned getSimm23Lsl2Encoding(const MCInst &MI, unsigned OpNo,
+                                 SmallVectorImpl<MCFixup> &Fixups,
+                                 const MCSubtargetInfo &STI) const;
+
   unsigned getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups,
                           const MCSubtargetInfo &STI) const;
 
index 51b5c0cd612bf3b34070b59d65db8e03f4a8547b..fdc365959c93e7fe70179b183c44ce705c572fb9 100644 (file)
@@ -898,3 +898,14 @@ class BARRIER_FM_MM<bits<5> op> : MMArch {
   let Inst{10-6}  = 0x0;
   let Inst{5-0}   = 0x0;
 }
+
+class ADDIUPC_FM_MM {
+  bits<3> rs;
+  bits<23> imm;
+
+  bits<32> Inst;
+
+  let Inst{31-26} = 0x1e;
+  let Inst{25-23} = rs;
+  let Inst{22-0} = imm;
+}
index 241f4528658cf605ea5590267aa96fe956746360..ed4e8946f99fe50e379b48381a7ed1d1b3d6fbd3 100644 (file)
@@ -141,6 +141,11 @@ def brtarget_mm : Operand<OtherVT> {
   let DecoderMethod = "DecodeBranchTargetMM";
 }
 
+def simm23_lsl2 : Operand<i32> {
+  let EncoderMethod = "getSimm23Lsl2Encoding";
+  let DecoderMethod = "DecodeSimm23Lsl2";
+}
+
 class CompactBranchMM<string opstr, DAGOperand opnd, PatFrag cond_op,
                       RegisterOperand RO> :
   InstSE<(outs), (ins RO:$rs, opnd:$offset),
@@ -422,6 +427,10 @@ class LoadWordIndexedScaledMM<string opstr, RegisterOperand RO,
   InstSE<(outs RO:$rd), (ins PtrRC:$base, PtrRC:$index),
          !strconcat(opstr, "\t$rd, ${index}(${base})"), [], Itin, FrmFI>;
 
+class AddImmUPC<string opstr, RegisterOperand RO> :
+  InstSE<(outs RO:$rs), (ins simm23_lsl2:$imm),
+         !strconcat(opstr, "\t$rs, $imm"), [], NoItinerary, FrmR>;
+
 /// A list of registers used by load/store multiple instructions.
 def RegListAsmOperand : AsmOperandClass {
   let Name = "RegList";
@@ -591,6 +600,9 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in {
   def UDIV_MM  : MMRel, Div<"divu", II_DIVU, GPR32Opnd, [HI0, LO0]>,
                  MULT_FM_MM<0x2ec>;
 
+  /// Arithmetic Instructions with PC and Immediate
+  def ADDIUPC_MM : AddImmUPC<"addiupc", GPRMM16Opnd>, ADDIUPC_FM_MM;
+
   /// Shift Instructions
   def SLL_MM   : MMRel, shift_rotate_imm<"sll", uimm5, GPR32Opnd, II_SLL>,
                  SRA_FM_MM<0, 0>;
index 07c1df91441af422013826bb9e06b0047f372f33..cca5cb725aa701f33c031b3a43ab7fe75c28c766 100644 (file)
 # CHECK: nop
 0x00 0x00 0x00 0x00
 
+# CHECK: addiupc $2, 20
+0x79 0x00 0x00 0x05
+
+# CHECK: addiupc $7, 16777212
+0x7b 0xbf 0xff 0xff
+
+# CHECK: addiupc $7, -16777216
+0x7b 0xc0 0x00 0x00
+
 # CHECK: addu16 $6, $17, $4
 0x07 0x42
 
index 9a8c4a94530cac2d0991168f3c80ec9cdc666853..44b6b5d3f9d807b45cf969b045cda7e8736a3321 100644 (file)
 # CHECK: nop
 0x00 0x00 0x00 0x00
 
+# CHECK: addiupc $2, 20
+0x00 0x79 0x05 0x00
+
+# CHECK: addiupc $7, 16777212
+0xbf 0x7b 0xff 0xff
+
+# CHECK: addiupc $7, -16777216
+0xc0 0x7b 0x00 0x00
+
 # CHECK: addu16 $6, $17, $4
 0x42 0x07
 
index 1131d1f3eae9b1b8f83bfdb6dc0863ff231e75b3..aeab09e78fa96e969c5649b2915cc7086f189316 100644 (file)
@@ -38,6 +38,9 @@
 # CHECK-EL: multu  $9, $7         # encoding: [0xe9,0x00,0x3c,0x9b]
 # CHECK-EL: div    $zero, $9, $7  # encoding: [0xe9,0x00,0x3c,0xab]
 # CHECK-EL: divu   $zero, $9, $7  # encoding: [0xe9,0x00,0x3c,0xbb]
+# CHECK-EL: addiupc $2, 20        # encoding: [0x00,0x79,0x05,0x00]
+# CHECK-EL: addiupc $7, 16777212  # encoding: [0xbf,0x7b,0xff,0xff]
+# CHECK-EL: addiupc $7, -16777216 # encoding: [0xc0,0x7b,0x00,0x00]
 #------------------------------------------------------------------------------
 # Big endian
 #------------------------------------------------------------------------------
@@ -72,6 +75,9 @@
 # CHECK-EB:  multu $9, $7         # encoding: [0x00,0xe9,0x9b,0x3c]
 # CHECK-EB: div  $zero, $9, $7    # encoding: [0x00,0xe9,0xab,0x3c]
 # CHECK-EB: divu $zero, $9, $7    # encoding: [0x00,0xe9,0xbb,0x3c]
+# CHECK-EB: addiupc $2, 20        # encoding: [0x79,0x00,0x00,0x05]
+# CHECK-EB: addiupc $7, 16777212  # encoding: [0x7b,0xbf,0xff,0xff]
+# CHECK-EB: addiupc $7, -16777216 # encoding: [0x7b,0xc0,0x00,0x00]
     add    $9, $6, $7
     add    $9, $6, 17767
     addu   $9, $6, -15001
     multu  $9, $7
     div    $0, $9, $7
     divu   $0, $9, $7
+    addiupc $2, 20
+    addiupc $7, 16777212
+    addiupc $7, -16777216
index 1dbfb113a2c9be42614c31a517a4789fc5e0741c..5ab111f958dd2a4ca51bdc18291db8fbd35314af 100644 (file)
@@ -38,6 +38,9 @@
   swm32   $16, $19, 8($4)  # CHECK: :[[@LINE]]:{{[0-9]+}}: error: consecutive register numbers expected
   swm32   $16-$25, 8($4)   # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid register operand
   lwm32 $16, $17, $18, $19, $20, $21, $22, $23, $24, 8($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid register operand
+  addiupc $7, 16777216  # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range
+  addiupc $6, -16777220 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range
+  addiupc $3, 3         # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range
   lbu16 $9, 8($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
   lhu16 $9, 4($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
   lw16  $9, 8($17) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction