[llvm] r188312 - [Mips] Support for unaligned load/store microMips instructions

Jack Carter jack.carter at imgtec.com
Tue Aug 13 13:19:17 PDT 2013


Author: jacksprat
Date: Tue Aug 13 15:19:16 2013
New Revision: 188312

URL: http://llvm.org/viewvc/llvm-project?rev=188312&view=rev
Log:
[Mips] Support for unaligned load/store microMips instructions

This includes instructions lwl, lwr, swl and swr.

Patch by Zoran Jovnovic

Added:
    llvm/trunk/test/MC/Mips/micromips-loadstore-unaligned.s
Modified:
    llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
    llvm/trunk/lib/Target/Mips/MicroMipsInstrFormats.td
    llvm/trunk/lib/Target/Mips/MicroMipsInstrInfo.td
    llvm/trunk/lib/Target/Mips/MipsCodeEmitter.cpp
    llvm/trunk/lib/Target/Mips/MipsISelDAGToDAG.cpp
    llvm/trunk/lib/Target/Mips/MipsISelDAGToDAG.h
    llvm/trunk/lib/Target/Mips/MipsInstrInfo.td
    llvm/trunk/lib/Target/Mips/MipsSEISelDAGToDAG.cpp
    llvm/trunk/lib/Target/Mips/MipsSEISelDAGToDAG.h

Modified: llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp?rev=188312&r1=188311&r2=188312&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp Tue Aug 13 15:19:16 2013
@@ -97,6 +97,8 @@ public:
 
   unsigned getMemEncoding(const MCInst &MI, unsigned OpNo,
                           SmallVectorImpl<MCFixup> &Fixups) const;
+  unsigned getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo,
+                                 SmallVectorImpl<MCFixup> &Fixups) const;
   unsigned getSizeExtEncoding(const MCInst &MI, unsigned OpNo,
                               SmallVectorImpl<MCFixup> &Fixups) const;
   unsigned getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
@@ -212,6 +214,7 @@ EncodeInstruction(const MCInst &MI, raw_
     LowerDextDins(TmpInst);
   }
 
+  unsigned long N = Fixups.size();
   uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups);
 
   // Check for unimplemented opcodes.
@@ -224,6 +227,8 @@ EncodeInstruction(const MCInst &MI, raw_
   if (STI.getFeatureBits() & Mips::FeatureMicroMips) {
     int NewOpcode = Mips::Std2MicroMips (Opcode, Mips::Arch_micromips);
     if (NewOpcode != -1) {
+      if (Fixups.size() > N)
+        Fixups.pop_back();
       Opcode = NewOpcode;
       TmpInst.setOpcode (NewOpcode);
       Binary = getBinaryCodeForInstr(TmpInst, Fixups);
@@ -417,6 +422,17 @@ MipsMCCodeEmitter::getMemEncoding(const
   return (OffBits & 0xFFFF) | RegBits;
 }
 
+unsigned MipsMCCodeEmitter::
+getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo,
+                      SmallVectorImpl<MCFixup> &Fixups) const {
+  // Base register is encoded in bits 20-16, offset is encoded in bits 11-0.
+  assert(MI.getOperand(OpNo).isReg());
+  unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups) << 16;
+  unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups);
+
+  return (OffBits & 0x0FFF) | RegBits;
+}
+
 unsigned
 MipsMCCodeEmitter::getSizeExtEncoding(const MCInst &MI, unsigned OpNo,
                                       SmallVectorImpl<MCFixup> &Fixups) const {

Modified: llvm/trunk/lib/Target/Mips/MicroMipsInstrFormats.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MicroMipsInstrFormats.td?rev=188312&r1=188311&r2=188312&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MicroMipsInstrFormats.td (original)
+++ llvm/trunk/lib/Target/Mips/MicroMipsInstrFormats.td Tue Aug 13 15:19:16 2013
@@ -110,3 +110,16 @@ class LW_FM_MM<bits<6> op> : MMArch {
   let Inst{20-16} = addr{20-16};
   let Inst{15-0}  = addr{15-0};
 }
+
+class LWL_FM_MM<bits<4> funct> {
+  bits<5> rt;
+  bits<21> addr;
+
+  bits<32> Inst;
+
+  let Inst{31-26} = 0x18;
+  let Inst{25-21} = rt;
+  let Inst{20-16} = addr{20-16};
+  let Inst{15-12} = funct;
+  let Inst{11-0}  = addr{11-0};
+}

Modified: llvm/trunk/lib/Target/Mips/MicroMipsInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MicroMipsInstrInfo.td?rev=188312&r1=188311&r2=188312&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MicroMipsInstrInfo.td (original)
+++ llvm/trunk/lib/Target/Mips/MicroMipsInstrInfo.td Tue Aug 13 15:19:16 2013
@@ -1,4 +1,34 @@
-let isCodeGenOnly = 1 in {
+def addrimm12 : ComplexPattern<iPTR, 2, "selectIntAddrMM", [frameindex]>;
+
+def simm12 : Operand<i32> {
+  let DecoderMethod = "DecodeSimm12";
+}
+
+def mem_mm_12 : Operand<i32> {
+  let PrintMethod = "printMemOperand";
+  let MIOperandInfo = (ops GPR32, simm12);
+  let EncoderMethod = "getMemEncodingMMImm12";
+  let ParserMatchClass = MipsMemAsmOperand;
+  let OperandType = "OPERAND_MEMORY";
+}
+
+let canFoldAsLoad = 1 in
+class LoadLeftRightMM<string opstr, SDNode OpNode, RegisterOperand RO,
+                      Operand MemOpnd> :
+  InstSE<(outs RO:$rt), (ins MemOpnd:$addr, RO:$src),
+         !strconcat(opstr, "\t$rt, $addr"),
+         [(set RO:$rt, (OpNode addrimm12:$addr, RO:$src))],
+         NoItinerary, FrmI> {
+  string Constraints = "$src = $rt";
+}
+
+class StoreLeftRightMM<string opstr, SDNode OpNode, RegisterOperand RO,
+                       Operand MemOpnd>:
+  InstSE<(outs), (ins RO:$rt, MemOpnd:$addr),
+         !strconcat(opstr, "\t$rt, $addr"),
+         [(OpNode RO:$rt, addrimm12:$addr)], NoItinerary, FrmI>;
+
+let DecoderNamespace = "MicroMips" in {
   /// Arithmetic Instructions (ALU Immediate)
   def ADDiu_MM : MMRel, ArithLogicI<"addiu", simm16, GPR32Opnd>,
                  ADDI_FM_MM<0xc>;
@@ -64,4 +94,16 @@ let isCodeGenOnly = 1 in {
   defm SB_MM  : StoreM<"sb", GPR32Opnd, truncstorei8>, MMRel, LW_FM_MM<0x6>;
   defm SH_MM  : StoreM<"sh", GPR32Opnd, truncstorei16>, MMRel, LW_FM_MM<0xe>;
   defm SW_MM  : StoreM<"sw", GPR32Opnd>, MMRel, LW_FM_MM<0x3e>;
+
+  /// Load and Store Instructions - unaligned
+  let Predicates = [InMicroMips] in {
+    def LWL_MM : LoadLeftRightMM<"lwl", MipsLWL, GPR32Opnd, mem_mm_12>,
+                 LWL_FM_MM<0x0>;
+    def LWR_MM : LoadLeftRightMM<"lwr", MipsLWR, GPR32Opnd, mem_mm_12>,
+                 LWL_FM_MM<0x1>;
+    def SWL_MM : StoreLeftRightMM<"swl", MipsSWL, GPR32Opnd, mem_mm_12>,
+                 LWL_FM_MM<0x8>;
+    def SWR_MM : StoreLeftRightMM<"swr", MipsSWR, GPR32Opnd, mem_mm_12>,
+                 LWL_FM_MM<0x9>;
+  }
 }

Modified: llvm/trunk/lib/Target/Mips/MipsCodeEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsCodeEmitter.cpp?rev=188312&r1=188311&r2=188312&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsCodeEmitter.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MipsCodeEmitter.cpp Tue Aug 13 15:19:16 2013
@@ -108,6 +108,7 @@ private:
 
   unsigned getBranchTargetOpValue(const MachineInstr &MI, unsigned OpNo) const;
   unsigned getMemEncoding(const MachineInstr &MI, unsigned OpNo) const;
+  unsigned getMemEncodingMMImm12(const MachineInstr &MI, unsigned OpNo) const;
   unsigned getSizeExtEncoding(const MachineInstr &MI, unsigned OpNo) const;
   unsigned getSizeInsEncoding(const MachineInstr &MI, unsigned OpNo) const;
 
@@ -201,6 +202,12 @@ unsigned MipsCodeEmitter::getMemEncoding
   return (getMachineOpValue(MI, MI.getOperand(OpNo+1)) & 0xFFFF) | RegBits;
 }
 
+unsigned MipsCodeEmitter::getMemEncodingMMImm12(const MachineInstr &MI,
+                                                unsigned OpNo) const {
+  llvm_unreachable("Unimplemented function.");
+  return 0;
+}
+
 unsigned MipsCodeEmitter::getSizeExtEncoding(const MachineInstr &MI,
                                              unsigned OpNo) const {
   // size is encoded as size-1.

Modified: llvm/trunk/lib/Target/Mips/MipsISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsISelDAGToDAG.cpp?rev=188312&r1=188311&r2=188312&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MipsISelDAGToDAG.cpp Tue Aug 13 15:19:16 2013
@@ -81,6 +81,12 @@ bool MipsDAGToDAGISel::selectIntAddr(SDV
   return false;
 }
 
+bool MipsDAGToDAGISel::selectIntAddrMM(SDValue Addr, SDValue &Base,
+                                       SDValue &Offset) const {
+  llvm_unreachable("Unimplemented function.");
+  return false;
+}
+
 bool MipsDAGToDAGISel::selectAddr16(SDNode *Parent, SDValue N, SDValue &Base,
                                     SDValue &Offset, SDValue &Alias) {
   llvm_unreachable("Unimplemented function.");

Modified: llvm/trunk/lib/Target/Mips/MipsISelDAGToDAG.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsISelDAGToDAG.h?rev=188312&r1=188311&r2=188312&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsISelDAGToDAG.h (original)
+++ llvm/trunk/lib/Target/Mips/MipsISelDAGToDAG.h Tue Aug 13 15:19:16 2013
@@ -65,6 +65,9 @@ private:
   virtual bool selectIntAddr(SDValue Addr, SDValue &Base,
                              SDValue &Offset) const;
 
+  virtual bool selectIntAddrMM(SDValue Addr, SDValue &Base,
+                               SDValue &Offset) const;
+
   virtual bool selectAddr16(SDNode *Parent, SDValue N, SDValue &Base,
                             SDValue &Offset, SDValue &Alias);
 

Modified: llvm/trunk/lib/Target/Mips/MipsInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsInstrInfo.td?rev=188312&r1=188311&r2=188312&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsInstrInfo.td (original)
+++ llvm/trunk/lib/Target/Mips/MipsInstrInfo.td Tue Aug 13 15:19:16 2013
@@ -182,6 +182,10 @@ def NoNaNsFPMath :    Predicate<"TM.Opti
 def HasStdEnc :       Predicate<"Subtarget.hasStandardEncoding()">,
                       AssemblerPredicate<"!FeatureMips16">;
 def NotDSP :          Predicate<"!Subtarget.hasDSP()">;
+def InMicroMips    :  Predicate<"Subtarget.inMicroMipsMode()">,
+                      AssemblerPredicate<"FeatureMicroMips">;
+def NotInMicroMips :  Predicate<"!Subtarget.inMicroMipsMode()">,
+                      AssemblerPredicate<"!FeatureMicroMips">;
 
 class MipsPat<dag pattern, dag result> : Pat<pattern, result> {
   let Predicates = [HasStdEnc];
@@ -516,7 +520,7 @@ class StoreLeftRight<string opstr, SDNod
 
 multiclass LoadLeftRightM<string opstr, SDNode OpNode, RegisterOperand RO> {
   def NAME : LoadLeftRight<opstr, OpNode, RO, mem>,
-             Requires<[NotN64, HasStdEnc]>;
+             Requires<[NotN64, HasStdEnc, NotInMicroMips]>;
   def _P8  : LoadLeftRight<opstr, OpNode, RO, mem64>,
              Requires<[IsN64, HasStdEnc]> {
     let DecoderNamespace = "Mips64";
@@ -526,7 +530,7 @@ multiclass LoadLeftRightM<string opstr,
 
 multiclass StoreLeftRightM<string opstr, SDNode OpNode, RegisterOperand RO> {
   def NAME : StoreLeftRight<opstr, OpNode, RO, mem>,
-             Requires<[NotN64, HasStdEnc]>;
+             Requires<[NotN64, HasStdEnc, NotInMicroMips]>;
   def _P8  : StoreLeftRight<opstr, OpNode, RO, mem64>,
              Requires<[IsN64, HasStdEnc]> {
     let DecoderNamespace = "Mips64";

Modified: llvm/trunk/lib/Target/Mips/MipsSEISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsSEISelDAGToDAG.cpp?rev=188312&r1=188311&r2=188312&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsSEISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MipsSEISelDAGToDAG.cpp Tue Aug 13 15:19:16 2013
@@ -314,6 +314,37 @@ bool MipsSEDAGToDAGISel::selectIntAddr(S
     selectAddrDefault(Addr, Base, Offset);
 }
 
+/// Used on microMIPS Load/Store unaligned instructions (12-bit offset)
+bool MipsSEDAGToDAGISel::selectAddrRegImm12(SDValue Addr, SDValue &Base,
+                                            SDValue &Offset) const {
+  EVT ValTy = Addr.getValueType();
+
+  // Addresses of the form FI+const or FI|const
+  if (CurDAG->isBaseWithConstantOffset(Addr)) {
+    ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1));
+    if (isInt<12>(CN->getSExtValue())) {
+
+      // If the first operand is a FI, get the TargetFI Node
+      if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>
+                                  (Addr.getOperand(0)))
+        Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy);
+      else
+        Base = Addr.getOperand(0);
+
+      Offset = CurDAG->getTargetConstant(CN->getZExtValue(), ValTy);
+      return true;
+    }
+  }
+
+  return false;
+}
+
+bool MipsSEDAGToDAGISel::selectIntAddrMM(SDValue Addr, SDValue &Base,
+                                         SDValue &Offset) const {
+  return selectAddrRegImm12(Addr, Base, Offset) ||
+    selectAddrDefault(Addr, Base, Offset);
+}
+
 std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) {
   unsigned Opcode = Node->getOpcode();
   SDLoc DL(Node);

Modified: llvm/trunk/lib/Target/Mips/MipsSEISelDAGToDAG.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsSEISelDAGToDAG.h?rev=188312&r1=188311&r2=188312&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsSEISelDAGToDAG.h (original)
+++ llvm/trunk/lib/Target/Mips/MipsSEISelDAGToDAG.h Tue Aug 13 15:19:16 2013
@@ -47,6 +47,12 @@ private:
   virtual bool selectIntAddr(SDValue Addr, SDValue &Base,
                              SDValue &Offset) const;
 
+  virtual bool selectAddrRegImm12(SDValue Addr, SDValue &Base,
+                                  SDValue &Offset) const;
+
+  virtual bool selectIntAddrMM(SDValue Addr, SDValue &Base,
+                               SDValue &Offset) const;
+
   virtual std::pair<bool, SDNode*> selectNode(SDNode *Node);
 
   virtual void processFunctionAfterISel(MachineFunction &MF);

Added: llvm/trunk/test/MC/Mips/micromips-loadstore-unaligned.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Mips/micromips-loadstore-unaligned.s?rev=188312&view=auto
==============================================================================
--- llvm/trunk/test/MC/Mips/micromips-loadstore-unaligned.s (added)
+++ llvm/trunk/test/MC/Mips/micromips-loadstore-unaligned.s Tue Aug 13 15:19:16 2013
@@ -0,0 +1,26 @@
+# RUN: llvm-mc %s -triple=mipsel-unknown-linux -show-encoding \
+# RUN: -mattr=micromips | FileCheck -check-prefix=CHECK-EL %s
+# RUN: llvm-mc %s -triple=mips-unknown-linux -show-encoding \
+# RUN: -mattr=micromips | FileCheck -check-prefix=CHECK-EB %s
+# Check that the assembler can handle the documented syntax
+# for loads and stores.
+#------------------------------------------------------------------------------
+# Load and Store unaligned instructions
+#------------------------------------------------------------------------------
+# Little endian
+#------------------------------------------------------------------------------
+# CHECK-EL: lwl $4, 16($5)   # encoding: [0x85,0x60,0x10,0x00]
+# CHECK-EL: lwr $4, 16($5)   # encoding: [0x85,0x60,0x10,0x10]
+# CHECK-EL: swl $4, 16($5)   # encoding: [0x85,0x60,0x10,0x80]
+# CHECK-EL: swr $4, 16($5)   # encoding: [0x85,0x60,0x10,0x90]
+#------------------------------------------------------------------------------
+# Big endian
+#------------------------------------------------------------------------------
+# CHECK-EB: lwl $4, 16($5)   # encoding: [0x60,0x85,0x00,0x10]
+# CHECK-EB: lwr $4, 16($5)   # encoding: [0x60,0x85,0x10,0x10]
+# CHECK-EB: swl $4, 16($5)   # encoding: [0x60,0x85,0x80,0x10]
+# CHECK-EB: swr $4, 16($5)   # encoding: [0x60,0x85,0x90,0x10]
+     lwl  $4, 16($5)
+     lwr  $4, 16($5)
+     swl  $4, 16($5)
+     swr  $4, 16($5)





More information about the llvm-commits mailing list