[mips][microMIPS] Implement LWSP and SWSP instructions
authorJozef Kolek <jozef.kolek@imgtec.com>
Tue, 23 Dec 2014 16:16:33 +0000 (16:16 +0000)
committerJozef Kolek <jozef.kolek@imgtec.com>
Tue, 23 Dec 2014 16:16:33 +0000 (16:16 +0000)
Differential Revision: http://reviews.llvm.org/D6416

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@224771 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-16-bit-instructions.s
test/MC/Mips/micromips-loadstore-instructions.s

index 44e0532f413c2365917db16b3433ba202153dcef..a00e57953f96f4be2304d30d49a50b109e36eea2 100644 (file)
@@ -824,6 +824,11 @@ public:
     return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
       && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
   }
+  template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
+    return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
+      && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
+      && (getMemBase()->getGPR32Reg() == Mips::SP);
+  }
   bool isRegList16() const {
     if (!isRegList())
       return false;
index 1b955f59dcf781df75e6af93b9f0055ec622f5b9..f4f870bc4ecd1796d9c79ea12e755ba345fb6155 100644 (file)
@@ -265,6 +265,11 @@ static DecodeStatus DecodeMemMMImm4(MCInst &Inst,
                                     uint64_t Address,
                                     const void *Decoder);
 
+static DecodeStatus DecodeMemMMSPImm5Lsl2(MCInst &Inst,
+                                          unsigned Insn,
+                                          uint64_t Address,
+                                          const void *Decoder);
+
 static DecodeStatus DecodeMemMMImm12(MCInst &Inst,
                                      unsigned Insn,
                                      uint64_t Address,
@@ -1197,6 +1202,22 @@ static DecodeStatus DecodeMemMMImm4(MCInst &Inst,
   return MCDisassembler::Success;
 }
 
+static DecodeStatus DecodeMemMMSPImm5Lsl2(MCInst &Inst,
+                                          unsigned Insn,
+                                          uint64_t Address,
+                                          const void *Decoder) {
+  unsigned Offset = Insn & 0x1F;
+  unsigned Reg = fieldFromInstruction(Insn, 5, 5);
+
+  Reg = getReg(Decoder, Mips::GPR32RegClassID, Reg);
+
+  Inst.addOperand(MCOperand::CreateReg(Reg));
+  Inst.addOperand(MCOperand::CreateReg(Mips::SP));
+  Inst.addOperand(MCOperand::CreateImm(Offset << 2));
+
+  return MCDisassembler::Success;
+}
+
 static DecodeStatus DecodeMemMMImm12(MCInst &Inst,
                                      unsigned Insn,
                                      uint64_t Address,
index 689248b065f7c798bc0e4a5b171d7fcf9ec649a3..223a95a698a72eb585e5d5455a5f4620d28044f6 100644 (file)
@@ -677,6 +677,20 @@ getMemEncodingMMImm4Lsl2(const MCInst &MI, unsigned OpNo,
   return (OffBits & 0xF) | RegBits;
 }
 
+unsigned MipsMCCodeEmitter::
+getMemEncodingMMSPImm5Lsl2(const MCInst &MI, unsigned OpNo,
+                           SmallVectorImpl<MCFixup> &Fixups,
+                           const MCSubtargetInfo &STI) const {
+  // Register is encoded in bits 9-5, offset is encoded in bits 4-0.
+  assert(MI.getOperand(OpNo).isReg() &&
+         MI.getOperand(OpNo).getReg() == Mips::SP &&
+         "Unexpected base register!");
+  unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),
+                                       Fixups, STI) >> 2;
+
+  return OffBits & 0x1F;
+}
+
 unsigned MipsMCCodeEmitter::
 getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo,
                       SmallVectorImpl<MCFixup> &Fixups,
index 4a4c9f6e0d3dea5185ec7ca2b81d36c81c099fec..863dd3b152750b3ac067da526d501c107d6a48b5 100644 (file)
@@ -151,6 +151,9 @@ public:
   unsigned getMemEncodingMMImm4Lsl2(const MCInst &MI, unsigned OpNo,
                                     SmallVectorImpl<MCFixup> &Fixups,
                                     const MCSubtargetInfo &STI) const;
+  unsigned getMemEncodingMMSPImm5Lsl2(const MCInst &MI, unsigned OpNo,
+                                      SmallVectorImpl<MCFixup> &Fixups,
+                                      const MCSubtargetInfo &STI) const;
   unsigned getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo,
                                  SmallVectorImpl<MCFixup> &Fixups,
                                  const MCSubtargetInfo &STI) const;
index 2301a1ccf8fdc1347da050291fcbfd8067bbeafb..fb9608200b5517a180b420f46f229387ddda619a 100644 (file)
@@ -120,6 +120,17 @@ class LOAD_STORE_FM_MM16<bits<6> op> {
   let Inst{3-0}   = addr{3-0};
 }
 
+class LOAD_STORE_SP_FM_MM16<bits<6> op> {
+  bits<5> rt;
+  bits<5> offset;
+
+  bits<16> Inst;
+
+  let Inst{15-10} = op;
+  let Inst{9-5}   = rt;
+  let Inst{4-0}   = offset;
+}
+
 class ADDIUS5_FM_MM16 {
   bits<5> rd;
   bits<4> imm;
index 3fae97c32ef47ed0195cec02f01dc10459bcbe00..86d44bbe666790bbf1b995cab31d0d93ffc3ec72 100644 (file)
@@ -81,6 +81,21 @@ def mem_mm_4_lsl2 : mem_mm_4_generic {
   let EncoderMethod = "getMemEncodingMMImm4Lsl2";
 }
 
+def MicroMipsMemSPAsmOperand : AsmOperandClass {
+  let Name = "MicroMipsMemSP";
+  let RenderMethod = "addMemOperands";
+  let ParserMethod = "parseMemOperand";
+  let PredicateMethod = "isMemWithUimmWordAlignedOffsetSP<7>";
+}
+
+def mem_mm_sp_imm5_lsl2 : Operand<i32> {
+  let PrintMethod = "printMemOperand";
+  let MIOperandInfo = (ops GPR32:$base, simm5:$offset);
+  let OperandType = "OPERAND_MEMORY";
+  let ParserMatchClass = MicroMipsMemSPAsmOperand;
+  let EncoderMethod = "getMemEncodingMMSPImm5Lsl2";
+}
+
 def mem_mm_12 : Operand<i32> {
   let PrintMethod = "printMemOperand";
   let MIOperandInfo = (ops GPR32, simm12);
@@ -255,6 +270,23 @@ class StoreMM16<string opstr, DAGOperand RTOpnd, DAGOperand RO,
   let mayStore = 1;
 }
 
+class LoadSPMM16<string opstr, DAGOperand RO, InstrItinClass Itin,
+                 Operand MemOpnd> :
+  MicroMipsInst16<(outs RO:$rt), (ins MemOpnd:$offset),
+                  !strconcat(opstr, "\t$rt, $offset"), [], Itin, FrmI> {
+  let DecoderMethod = "DecodeMemMMSPImm5Lsl2";
+  let canFoldAsLoad = 1;
+  let mayLoad = 1;
+}
+
+class StoreSPMM16<string opstr, DAGOperand RO, InstrItinClass Itin,
+                  Operand MemOpnd> :
+  MicroMipsInst16<(outs), (ins RO:$rt, MemOpnd:$offset),
+                  !strconcat(opstr, "\t$rt, $offset"), [], Itin, FrmI> {
+  let DecoderMethod = "DecodeMemMMSPImm5Lsl2";
+  let mayStore = 1;
+}
+
 class AddImmUR2<string opstr, RegisterOperand RO> :
   MicroMipsInst16<(outs RO:$rd), (ins RO:$rs, simm3_lsa2:$imm),
                   !strconcat(opstr, "\t$rd, $rs, $imm"),
@@ -462,6 +494,10 @@ def SH16_MM : StoreMM16<"sh16", GPRMM16OpndZero, GPRMM16Opnd, truncstorei16,
                         LOAD_STORE_FM_MM16<0x2a>;
 def SW16_MM : StoreMM16<"sw16", GPRMM16OpndZero, GPRMM16Opnd, store, II_SW,
                         mem_mm_4_lsl2>, LOAD_STORE_FM_MM16<0x3a>;
+def LWSP_MM : LoadSPMM16<"lw", GPR32Opnd, II_LW, mem_mm_sp_imm5_lsl2>,
+              LOAD_STORE_SP_FM_MM16<0x12>;
+def SWSP_MM : StoreSPMM16<"sw", GPR32Opnd, II_SW, mem_mm_sp_imm5_lsl2>,
+              LOAD_STORE_SP_FM_MM16<0x32>;
 def ADDIUR1SP_MM : AddImmUR1SP<"addiur1sp", GPRMM16Opnd>, ADDIUR1SP_FM_MM16;
 def ADDIUR2_MM : AddImmUR2<"addiur2", GPRMM16Opnd>, ADDIUR2_FM_MM16;
 def ADDIUS5_MM : AddImmUS5<"addius5", GPR32Opnd>, ADDIUS5_FM_MM16;
index 87aa9ede66d17df4fa390a3305bc65cb99e1dcde..6de6bba9c2311ed4e30072498d65090eab00a0fd 100644 (file)
 # CHECK: lw  $6, 4($5)
 0xfc 0xc5 0x00 0x04
 
+# CHECK: lw $6, 123($sp)
+0xfc 0xdd 0x00 0x7b
+
 # CHECK: sb $5, 8($4)
 0x18 0xa4 0x00 0x08
 
 # CHECK: sw  $5, 4($6)
 0xf8 0xa6 0x00 0x04
 
+# CHECK: sw $5, 123($sp)
+0xf8 0xbd 0x00 0x7b
+
 # CHECK: lwu $2, 8($4)
 0x60 0x44 0xe0 0x08
 
 
 # CHECK: nop
 0x0c 0x00
+
+# CHECK: lw $3, 32($sp)
+0x48 0x68
+
+# CHECK: sw $4, 124($sp)
+0xc8 0x9f
index 71acaf28aa0701d9ca309464b4f010381a6da14f..5cc582be2ad9cc1f1a31e01e20ba34c254ca66e1 100644 (file)
 # CHECK: lw $6, 4($5)
 0xc5 0xfc 0x04 0x00
 
+# CHECK: lw $6, 123($sp)
+0xdd 0xfc 0x7b 0x00
+
 # CHECK: sb $5, 8($4)
 0xa4 0x18 0x08 0x00
 
 # CHECK: sw $5, 4($6)
 0xa6 0xf8 0x04 0x00
 
+# CHECK: sw $5, 123($sp)
+0xbd 0xf8 0x7b 0x00
+
 # CHECK: lwu $2, 8($4)
 0x44 0x60 0x08 0xe0
 
 
 # CHECK: nop
 0x00 0x0c
+
+# CHECK: lw $3, 32($sp)
+0x68 0x48
+
+# CHECK: sw $4, 124($sp)
+0x9f 0xc8
index 7ff6d9d4c50c0b69648b5190b6058524c8909854..7a9e84baa3dff57be6905c3ed8f1e154518fdc03 100644 (file)
@@ -26,6 +26,8 @@
 # CHECK-EL: sh16    $4, 8($17)      # encoding: [0x14,0xaa]
 # CHECK-EL: sw16    $4, 4($17)      # encoding: [0x11,0xea]
 # CHECK-EL: sw16    $zero, 4($17)   # encoding: [0x11,0xe8]
+# CHECK-EL: lw      $3, 32($sp)     # encoding: [0x68,0x48]
+# CHECK-EL: sw      $4, 124($sp)    # encoding: [0x9f,0xc8]
 # CHECK-EL: li16    $3, -1          # encoding: [0xff,0xed]
 # CHECK-EL: li16    $3, 126         # encoding: [0xfe,0xed]
 # CHECK-EL: addiur1sp $7, 4         # encoding: [0x83,0x6f]
@@ -69,6 +71,8 @@
 # CHECK-EB: sh16    $4, 8($17)      # encoding: [0xaa,0x14]
 # CHECK-EB: sw16    $4, 4($17)      # encoding: [0xea,0x11]
 # CHECK-EB: sw16    $zero, 4($17)   # encoding: [0xe8,0x11]
+# CHECK-EB: lw      $3, 32($sp)     # encoding: [0x48,0x68]
+# CHECK-EB: sw      $4, 124($sp)    # encoding: [0xc8,0x9f]
 # CHECK-EB: li16    $3, -1          # encoding: [0xed,0xff]
 # CHECK-EB: li16    $3, 126         # encoding: [0xed,0xfe]
 # CHECK-EB: addiur1sp $7, 4         # encoding: [0x6f,0x83]
     sh16    $4, 8($17)
     sw16    $4, 4($17)
     sw16    $0, 4($17)
+    lw      $3, 32($sp)
+    sw      $4, 124($sp)
     li16    $3, -1
     li16    $3, 126
     addiur1sp $7, 4
index 5133c36bb02a109c05efdb80a58f93a0280ebf64..995af035dde50c8df54f8a3c2a5553760015f74d 100644 (file)
 # CHECK-EL: lh     $2, 8($4)                  # encoding: [0x44,0x3c,0x08,0x00]
 # CHECK-EL: lhu    $4, 8($2)                  # encoding: [0x82,0x34,0x08,0x00]
 # CHECK-EL: lw     $6, 4($5)                  # encoding: [0xc5,0xfc,0x04,0x00]
+# CHECK-EL: lw     $6, 123($sp)               # encoding: [0xdd,0xfc,0x7b,0x00]
 # CHECK-EL: sb     $5, 8($4)                  # encoding: [0xa4,0x18,0x08,0x00]
 # CHECK-EL: sh     $2, 8($4)                  # encoding: [0x44,0x38,0x08,0x00]
 # CHECK-EL: sw     $5, 4($6)                  # encoding: [0xa6,0xf8,0x04,0x00]
+# CHECK-EL: sw     $5, 123($sp)               # encoding: [0xbd,0xf8,0x7b,0x00]
 # CHECK-EL: ll     $2, 8($4)                  # encoding: [0x44,0x60,0x08,0x30]
 # CHECK-EL: sc     $2, 8($4)                  # encoding: [0x44,0x60,0x08,0xb0]
 # CHECK-EL: lwu    $2, 8($4)                  # encoding: [0x44,0x60,0x08,0xe0]
 # CHECK-EB: lh     $2, 8($4)                 # encoding: [0x3c,0x44,0x00,0x08]
 # CHECK-EB: lhu    $4, 8($2)                 # encoding: [0x34,0x82,0x00,0x08]
 # CHECK-EB: lw     $6, 4($5)                 # encoding: [0xfc,0xc5,0x00,0x04]
+# CHECK-EB: lw     $6, 123($sp)              # encoding: [0xfc,0xdd,0x00,0x7b]
 # CHECK-EB: sb     $5, 8($4)                 # encoding: [0x18,0xa4,0x00,0x08]
 # CHECK-EB: sh     $2, 8($4)                 # encoding: [0x38,0x44,0x00,0x08]
 # CHECK-EB: sw     $5, 4($6)                 # encoding: [0xf8,0xa6,0x00,0x04]
+# CHECK-EB: sw     $5, 123($sp)              # encoding: [0xf8,0xbd,0x00,0x7b]
 # CHECK-EB: ll     $2, 8($4)                 # encoding: [0x60,0x44,0x30,0x08]
 # CHECK-EB: sc     $2, 8($4)                 # encoding: [0x60,0x44,0xb0,0x08]
 # CHECK-EB: lwu    $2, 8($4)                 # encoding: [0x60,0x44,0xe0,0x08]
      lh     $2, 8($4)
      lhu    $4, 8($2)
      lw     $6, 4($5)
+     lw     $6, 123($sp)
      sb     $5, 8($4)
      sh     $2, 8($4)
      sw     $5, 4($6)
+     sw     $5, 123($sp)
      ll     $2, 8($4)
      sc     $2, 8($4)
      lwu    $2, 8($4)