[mips][microMIPS] Implement JALRC16, JRCADDIUSP and JRC16 instructions
authorZoran Jovanovic <zoran.jovanovic@imgtec.com>
Mon, 5 Oct 2015 14:00:09 +0000 (14:00 +0000)
committerZoran Jovanovic <zoran.jovanovic@imgtec.com>
Mon, 5 Oct 2015 14:00:09 +0000 (14:00 +0000)
Differential Revision: http://reviews.llvm.org/D11219

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

12 files changed:
lib/Target/Mips/AsmParser/MipsAsmParser.cpp
lib/Target/Mips/MicroMips32r6InstrFormats.td
lib/Target/Mips/MicroMips32r6InstrInfo.td
lib/Target/Mips/MicroMipsInstrInfo.td
lib/Target/Mips/MipsInstrInfo.td
test/MC/Disassembler/Mips/micromips32r6.txt
test/MC/Disassembler/Mips/micromips64r6.txt
test/MC/Mips/micromips-invalid.s
test/MC/Mips/micromips32r6/invalid.s
test/MC/Mips/micromips32r6/valid.s
test/MC/Mips/micromips64r6/invalid.s
test/MC/Mips/micromips64r6/valid.s

index 76cca79741bc8f3f956ef4b274bd79230ed9d9de..551d7643e14d3c8e930474dd76beb9bca830c18e 100644 (file)
@@ -980,6 +980,9 @@ public:
       && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
       && (getMemBase()->getGPR32Reg() == Mips::SP);
   }
+  bool isUImm5Lsl2() const {
+    return (isImm() && isConstantImm() && isShiftedUInt<5, 2>(getConstantImm()));
+  }
   bool isRegList16() const {
     if (!isRegList())
       return false;
@@ -2085,7 +2088,7 @@ bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
       JalrInst.setOpcode(Mips::JALRS16_MM);
       JalrInst.addOperand(FirstRegOp);
     } else if (inMicroMipsMode()) {
-      JalrInst.setOpcode(Mips::JALR16_MM);
+      JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
       JalrInst.addOperand(FirstRegOp);
     } else {
       JalrInst.setOpcode(Mips::JALR);
@@ -2104,9 +2107,12 @@ bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
   }
   Instructions.push_back(JalrInst);
 
-  // If .set reorder is active, emit a NOP after it.
-  if (AssemblerOptions.back()->isReorder())
+  // If .set reorder is active and branch instruction has a delay slot,
+  // emit a NOP after it.
+  const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
+  if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
     createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions);
+  }
 
   return false;
 }
index 0d7b3e01fc3bd6470ac9826304d5ac0773f95a9d..242037f59412f38c20e4de1039ac8805d2e9abad 100644 (file)
@@ -42,6 +42,26 @@ class BEQZC_BNEZC_FM_MM16R6<bits<6> op> : MicroMipsR6Inst16 {
   let Inst{6-0}   = offset;
 }
 
+class POOL16C_JALRC_FM_MM16R6<bits<5> op> {
+  bits<5> rs;
+
+  bits<16> Inst;
+
+  let Inst{15-10} = 0x11;
+  let Inst{9-5}   = rs;
+  let Inst{4-0}   = op;
+}
+
+class POOL16C_JRCADDIUSP_FM_MM16R6<bits<5> op> {
+  bits<5> imm;
+
+  bits<16> Inst;
+
+  let Inst{15-10} = 0x11;
+  let Inst{9-5}   = imm;
+  let Inst{4-0}   = op;
+}
+
 class POOL32A_BITSWAP_FM_MMR6<bits<6> funct> : MipsR6Inst {
   bits<5> rd;
   bits<5> rt;
index d944894da77ca28b2567bbea853512892ff269fa..44e4e56e0a712253e3bf0154eec4d504763e083a 100644 (file)
@@ -48,8 +48,11 @@ class EHB_MMR6_ENC : BARRIER_MMR6_ENC<"ehb", 0x3>;
 class EI_MMR6_ENC : EIDI_MMR6_ENC<"ei", 0x15d>;
 class ERET_MMR6_ENC : ERET_FM_MMR6<"eret">;
 class ERETNC_MMR6_ENC : ERETNC_FM_MMR6<"eretnc">;
+class JALRC16_MMR6_ENC : POOL16C_JALRC_FM_MM16R6<0xb>;
 class JIALC_MMR6_ENC : JMP_IDX_COMPACT_FM<0b100000>;
 class JIC_MMR6_ENC   : JMP_IDX_COMPACT_FM<0b101000>;
+class JRC16_MMR6_ENC: POOL16C_JALRC_FM_MM16R6<0x3>;
+class JRCADDIUSP_MMR6_ENC : POOL16C_JRCADDIUSP_FM_MM16R6<0x13>;
 class LSA_MMR6_ENC : POOL32A_LSA_FM<0b001111>;
 class LWPC_MMR6_ENC  : PCREL19_FM_MMR6<0b01>;
 class MOD_MMR6_ENC : ARITH_FM_MMR6<"mod", 0x158>;
@@ -292,6 +295,16 @@ class EI_MMR6_DESC : DEI_FT<"ei", GPR32Opnd>;
 class ERET_MMR6_DESC : ER_FT<"eret">;
 class ERETNC_MMR6_DESC : ER_FT<"eretnc">;
 
+class JALRC16_MMR6_DESC_BASE<string opstr, RegisterOperand RO>
+    : MicroMipsInst16<(outs), (ins RO:$rs), !strconcat(opstr, "\t$rs"),
+                      [(MipsJmpLink RO:$rs)], II_JALR, FrmR>,
+      MMR6Arch<opstr>, MicroMipsR6Inst16 {
+  let isCall = 1;
+  let hasDelaySlot = 0;
+  let Defs = [RA];
+}
+class JALRC16_MMR6_DESC : JALRC16_MMR6_DESC_BASE<"jalr", GPR32Opnd>;
+
 class JMP_MMR6_IDX_COMPACT_DESC_BASE<string opstr, DAGOperand opnd,
                                      RegisterOperand GPROpnd>
     : MMR6Arch<opstr> {
@@ -314,6 +327,27 @@ class JIC_MMR6_DESC : JMP_MMR6_IDX_COMPACT_DESC_BASE<"jic", jmpoffset16,
   list<Register> Defs = [AT];
 }
 
+class JRC16_MMR6_DESC_BASE<string opstr, RegisterOperand RO>
+    : MicroMipsInst16<(outs), (ins RO:$rs), !strconcat(opstr, "\t$rs"),
+                      [], II_JR, FrmR>,
+      MMR6Arch<opstr>, MicroMipsR6Inst16 {
+  let hasDelaySlot = 0;
+  let isBranch = 1;
+  let isIndirectBranch = 1;
+}
+class JRC16_MMR6_DESC : JRC16_MMR6_DESC_BASE<"jrc16", GPR32Opnd>;
+
+class JRCADDIUSP_MMR6_DESC
+    : MicroMipsInst16<(outs), (ins uimm5_lsl2:$imm), "jrcaddiusp\t$imm",
+                      [], II_JRADDIUSP, FrmR>,
+      MMR6Arch<"jrcaddiusp">, MicroMipsR6Inst16 {
+  let hasDelaySlot = 0;
+  let isTerminator = 1;
+  let isBarrier = 1;
+  let isBranch = 1;
+  let isIndirectBranch = 1;
+}
+
 class ALIGN_MMR6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd,
                       Operand ImmOpnd>  : MMR6Arch<instr_asm> {
   dag OutOperandList = (outs GPROpnd:$rd);
@@ -745,8 +779,13 @@ def EI_MMR6 : StdMMR6Rel, EI_MMR6_DESC, EI_MMR6_ENC, ISA_MICROMIPS32R6;
 def ERET_MMR6 : R6MMR6Rel, ERET_MMR6_DESC, ERET_MMR6_ENC, ISA_MICROMIPS32R6;
 def ERETNC_MMR6 : R6MMR6Rel, ERETNC_MMR6_DESC, ERETNC_MMR6_ENC,
                   ISA_MICROMIPS32R6;
+def JALRC16_MMR6 : R6MMR6Rel, JALRC16_MMR6_DESC, JALRC16_MMR6_ENC,
+                   ISA_MICROMIPS32R6;
 def JIALC_MMR6 : R6MMR6Rel, JIALC_MMR6_ENC, JIALC_MMR6_DESC, ISA_MICROMIPS32R6;
 def JIC_MMR6 : R6MMR6Rel, JIC_MMR6_ENC, JIC_MMR6_DESC, ISA_MICROMIPS32R6;
+def JRC16_MMR6 : R6MMR6Rel, JRC16_MMR6_DESC, JRC16_MMR6_ENC, ISA_MICROMIPS32R6;
+def JRCADDIUSP_MMR6 : R6MMR6Rel, JRCADDIUSP_MMR6_DESC, JRCADDIUSP_MMR6_ENC,
+                      ISA_MICROMIPS32R6;
 def LSA_MMR6 : R6MMR6Rel, LSA_MMR6_ENC, LSA_MMR6_DESC, ISA_MICROMIPS32R6;
 def LWPC_MMR6 : R6MMR6Rel, LWPC_MMR6_ENC, LWPC_MMR6_DESC, ISA_MICROMIPS32R6;
 def MOD_MMR6 : R6MMR6Rel, MOD_MMR6_DESC, MOD_MMR6_ENC, ISA_MICROMIPS32R6;
index 35958bd7c6e0ea92b1b189913f67cc3ce53c8ed3..4e7a1776014ebbc442aada0310b498670bae6015 100644 (file)
@@ -13,9 +13,17 @@ def simm12 : Operand<i32> {
   let DecoderMethod = "DecodeSimm12";
 }
 
+def MipsUimm5Lsl2AsmOperand : AsmOperandClass {
+  let Name = "Uimm5Lsl2";
+  let RenderMethod = "addImmOperands";
+  let ParserMethod = "parseImm";
+  let PredicateMethod = "isUImm5Lsl2";
+}
+
 def uimm5_lsl2 : Operand<OtherVT> {
   let EncoderMethod = "getUImm5Lsl2Encoding";
   let DecoderMethod = "DecodeUImm5lsl2";
+  let ParserMatchClass = MipsUimm5Lsl2AsmOperand;
 }
 
 def uimm6_lsl2 : Operand<i32> {
@@ -401,7 +409,7 @@ class LoadImmMM16<string opstr, Operand Od, RegisterOperand RO> :
 // 16-bit Jump and Link (Call)
 class JumpLinkRegMM16<string opstr, RegisterOperand RO> :
   MicroMipsInst16<(outs), (ins RO:$rs), !strconcat(opstr, "\t$rs"),
-           [(MipsJmpLink RO:$rs)], II_JALR, FrmR> {
+           [(MipsJmpLink RO:$rs)], II_JALR, FrmR>, PredicateControl {
   let isCall = 1;
   let hasDelaySlot = 1;
   let Defs = [RA];
@@ -613,7 +621,8 @@ def MOVE16_MM : MoveMM16<"move", GPR32Opnd>, MOVE_FM_MM16<0x03>;
 def MOVEP_MM : MovePMM16<"movep", GPRMM16OpndMoveP>, MOVEP_FM_MM16;
 def LI16_MM : LoadImmMM16<"li16", li_simm7, GPRMM16Opnd>, LI_FM_MM16,
               IsAsCheapAsAMove;
-def JALR16_MM : JumpLinkRegMM16<"jalr", GPR32Opnd>, JALR_FM_MM16<0x0e>;
+def JALR16_MM : JumpLinkRegMM16<"jalr", GPR32Opnd>, JALR_FM_MM16<0x0e>,
+                ISA_MICROMIPS32_NOT_MIPS32R6;
 def JALRS16_MM : JumpLinkRegSMM16<"jalrs16", GPR32Opnd>, JALR_FM_MM16<0x0f>;
 def JRC16_MM : JumpRegCMM16<"jrc", GPR32Opnd>, JALR_FM_MM16<0x0d>;
 def JRADDIUSP : JumpRAddiuStackMM16, JRADDIUSP_FM_MM16<0x18>;
index d15b785517cfaf39a476360109c57be8fd734237..1bd352453e2dc3878b02a8ab98f3af6c6c2dd7d2 100644 (file)
@@ -267,6 +267,9 @@ class ISA_MICROMIPS32R6 {
 class ISA_MICROMIPS64R6 {
   list<Predicate> InsnPredicates = [HasMicroMips64r6];
 }
+class ISA_MICROMIPS32_NOT_MIPS32R6 {
+  list<Predicate> InsnPredicates = [InMicroMips, NotMips32r6];
+}
 
 class INSN_EVA { list<Predicate> InsnPredicates = [HasEVA]; }
 class INSN_EVA_NOT_32R6_64R6 {
index 0d6123ea3dffed5c890247cb9a0e4b085f5bdd41..5440642dfc563957bceadd1c3900d0aca5d678e9 100644 (file)
 
 0x00 0x01 0xf3 0x7c # CHECK: eretnc
 
+0x45 0x2b # CHECK: jalr $9
+
 0x80 0x05 0x01 0x00 # CHECK: jialc $5, 256
 
 0xa0 0x05 0x01 0x00 # CHECK: jic $5, 256
 
+0x45 0x23 # CHECK: jrc16 $9
+
+0x44 0xb3 # CHECK: jrcaddiusp 20
+
 0x78 0x48 0x00 0x43 # CHECK: lwpc $2, 268
 
 0x00 0x43 0x26 0x0f # CHECK: lsa $2, $3, $4, 3
index 606b6fbb203834235cad2cc7ba8193b0fcd60fbf..10c9304138dfcaa304ad4f897805cf7cf6069fbe 100644 (file)
 0x00 0x64 0xf1 0x7c # CHECK: wrpgpr $3, $4
 
 0x00 0x64 0x7b 0x3c # CHECK: wsbh $3, $4
+
+0x45 0x2b # CHECK: jalr $9
+
+0x45 0x23 # CHECK: jrc16 $9
+
+0x44 0xb3 # CHECK: jrcaddiusp 20
index 1cf792eec55f64c2258bce94ffdf30c61742fad8..99e9eb4fa4355f70a4d0dc6d8d287838f236e3f3 100644 (file)
   break 1024, 1024  # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
   wait 1024         # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
   prefx 33, $8($5) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range
+  jraddiusp 1       # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+  jraddiusp 2       # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+  jraddiusp 3       # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+  jraddiusp 10      # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+  jraddiusp 18      # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+  jraddiusp 31      # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+  jraddiusp 33      # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+  jraddiusp 125     # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+  jraddiusp 132     # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
index 6b844ec2f5787b1fb8a2b270cc320283e8f575bd..d6458997c49e33877da30fb978e9c0bcbb195188 100644 (file)
   wrpgpr $3, $33           # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
   wsbh $34, $4             # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
   wsbh $3, $33             # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+  jrcaddiusp 1             # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+  jrcaddiusp 2             # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+  jrcaddiusp 3             # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+  jrcaddiusp 10            # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+  jrcaddiusp 18            # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+  jrcaddiusp 31            # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+  jrcaddiusp 33            # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+  jrcaddiusp 125           # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+  jrcaddiusp 132           # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
index d4ab500f9e4ec385c2881fe6cf8c270bf2d62c04..e8f9c85bc99a81b7509ceacb37528522612728c3 100644 (file)
   ei $10                   # CHECK: ei $10              # encoding: [0x00,0x0a,0x57,0x7c]
   eret                     # CHECK: eret                # encoding: [0x00,0x00,0xf3,0x7c]
   eretnc                   # CHECK: eretnc              # encoding: [0x00,0x01,0xf3,0x7c]
+  jalr $9                  # CHECK: jalr $9             # encoding: [0x45,0x2b]
   jialc $5, 256            # CHECK: jialc $5, 256       # encoding: [0x80,0x05,0x01,0x00]
   jic   $5, 256            # CHECK: jic $5, 256         # encoding: [0xa0,0x05,0x01,0x00]
+  jrc16 $9                 # CHECK: jrc16 $9            # encoding: [0x45,0x23]
+  jrcaddiusp 20            # CHECK: jrcaddiusp 20       # encoding: [0x44,0xb3]
   lsa $2, $3, $4, 3        # CHECK: lsa  $2, $3, $4, 3  # encoding: [0x00,0x43,0x26,0x0f]
   lwpc    $2,268           # CHECK: lwpc $2, 268        # encoding: [0x78,0x48,0x00,0x43]
   mod $3, $4, $5           # CHECK: mod $3, $4, $5      # encoding: [0x00,0xa4,0x19,0x58]
index fea7a3754f9511c85b1961766cca9dd4b341d40b..59e7cd61243df89ac2a9a008932c6016a3088cb0 100644 (file)
   wrpgpr $3, $33           # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
   wsbh $34, $4             # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
   wsbh $3, $33             # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+  jrcaddiusp 1             # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+  jrcaddiusp 2             # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+  jrcaddiusp 3             # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+  jrcaddiusp 10            # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+  jrcaddiusp 18            # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+  jrcaddiusp 31            # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+  jrcaddiusp 33            # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+  jrcaddiusp 125           # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
+  jrcaddiusp 132           # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
index 346ab484a35054c42e32fe2105bcc316c9573b93..9567601680ed05aa985e3a016ad03fd00afc5617 100644 (file)
@@ -112,5 +112,8 @@ a:
         cachee 1, 8($5)          # CHECK: cachee 1, 8($5)     # encoding: [0x60,0x25,0xa6,0x08]
         wrpgpr $3, $4            # CHECK: wrpgpr $3, $4       # encoding: [0x00,0x64,0xf1,0x7c]
         wsbh $3, $4              # CHECK: wsbh $3, $4         # encoding: [0x00,0x64,0x7b,0x3c]
+        jalr $9                  # CHECK: jalr $9             # encoding: [0x45,0x2b]
+        jrc16 $9                 # CHECK: jrc16 $9            # encoding: [0x45,0x23]
+        jrcaddiusp 20            # CHECK: jrcaddiusp 20       # encoding: [0x44,0xb3]
 
 1: