diff options
author | Zoran Jovanovic <zoran.jovanovic@imgtec.com> | 2014-11-27 18:28:59 +0000 |
---|---|---|
committer | Zoran Jovanovic <zoran.jovanovic@imgtec.com> | 2014-11-27 18:28:59 +0000 |
commit | f9a02500b662551804e4f2d27311e2ec7ec9031c (patch) | |
tree | 81fb8711417fcd113b963c71b3acb6f04484ccf6 /llvm/lib/Target | |
parent | 56a6a7d3bde9c4e38eb3f50a15f2ebc598dc03bc (diff) | |
download | bcm5719-llvm-f9a02500b662551804e4f2d27311e2ec7ec9031c.tar.gz bcm5719-llvm-f9a02500b662551804e4f2d27311e2ec7ec9031c.zip |
[mips][microMIPS] Implement SWM16 and LWM16 instructions
Differential Revision: http://reviews.llvm.org/D5579
llvm-svn: 222901
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r-- | llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 23 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp | 24 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp | 31 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h | 7 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MicroMipsInstrFormats.td | 12 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MicroMipsInstrInfo.td | 48 |
7 files changed, 147 insertions, 0 deletions
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index f458b5bf520..67725cb7ffa 100644 --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -809,6 +809,29 @@ public: bool isMemWithGRPMM16Base() const { return isMem() && getMemBase()->isMM16AsmReg(); } + template <unsigned Bits> bool isMemWithUimmOffsetSP() const { + return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff()) + && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP); + } + bool isRegList16() const { + if (!isRegList()) + return false; + + int Size = RegList.List->size(); + if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 || + RegList.List->back() != Mips::RA) + return false; + + int PrevReg = *RegList.List->begin(); + for (int i = 1; i < Size - 1; i++) { + int Reg = (*(RegList.List))[i]; + if ( Reg != PrevReg + 1) + return false; + PrevReg = Reg; + } + + return true; + } bool isInvNum() const { return Kind == k_Immediate; } bool isLSAImm() const { if (!isConstantImm()) diff --git a/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp index 58a857b662a..878bc23dbab 100644 --- a/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ b/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -380,6 +380,10 @@ static DecodeStatus DecodeRegListOperand(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeRegListOperand16(MCInst &Inst, unsigned Insn, + uint64_t Address, + const void *Decoder); + namespace llvm { extern Target TheMipselTarget, TheMipsTarget, TheMips64Target, TheMips64elTarget; @@ -1609,3 +1613,23 @@ static DecodeStatus DecodeRegListOperand(MCInst &Inst, return MCDisassembler::Success; } + +static DecodeStatus DecodeRegListOperand16(MCInst &Inst, unsigned Insn, + uint64_t Address, + const void *Decoder) { + unsigned Regs[] = {Mips::S0, Mips::S1, Mips::S2, Mips::S3}; + unsigned RegNum; + + unsigned RegLst = fieldFromInstruction(Insn, 4, 2); + // Empty register lists are not allowed. + if (RegLst == 0) + return MCDisassembler::Fail; + + RegNum = RegLst & 0x3; + for (unsigned i = 0; i < RegNum - 1; i++) + Inst.addOperand(MCOperand::CreateReg(Regs[i])); + + Inst.addOperand(MCOperand::CreateReg(Mips::RA)); + + return MCDisassembler::Success; +} diff --git a/llvm/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp b/llvm/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp index ab6b22562ce..e8366290c16 100644 --- a/llvm/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp +++ b/llvm/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp @@ -233,6 +233,8 @@ printMemOperand(const MCInst *MI, int opNum, raw_ostream &O) { break; case Mips::SWM32_MM: case Mips::LWM32_MM: + case Mips::SWM16_MM: + case Mips::LWM16_MM: opNum = MI->getNumOperands() - 2; break; } diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp index 6cd1eb2e622..521ef0d0b69 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -699,6 +699,30 @@ getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo, return (OffBits & 0x0FFF) | RegBits; } +unsigned MipsMCCodeEmitter:: +getMemEncodingMMImm4sp(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + // opNum can be invalid if instruction had reglist as operand + // MemOperand is always last operand of instruction (base + offset) + switch (MI.getOpcode()) { + default: + break; + case Mips::SWM16_MM: + case Mips::LWM16_MM: + OpNo = MI.getNumOperands() - 2; + break; + } + + // Offset is encoded in bits 4-0. + assert(MI.getOperand(OpNo).isReg()); + // Base register is always SP - thus it is not encoded. + assert(MI.getOperand(OpNo+1).isImm()); + unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); + + return ((OffBits >> 2) & 0x0F); +} + unsigned MipsMCCodeEmitter::getSizeExtEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, @@ -830,4 +854,11 @@ MipsMCCodeEmitter::getRegisterListOpValue(const MCInst &MI, unsigned OpNo, return res; } +unsigned +MipsMCCodeEmitter::getRegisterListOpValue16(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + return (MI.getNumOperands() - 4); +} + #include "MipsGenMCCodeEmitter.inc" diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h index 24d0b45bb45..b557f740430 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h @@ -154,6 +154,9 @@ public: unsigned getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; + unsigned getMemEncodingMMImm4sp(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; unsigned getSizeExtEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; @@ -187,6 +190,10 @@ public: unsigned getRegisterListOpValue(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; + + unsigned getRegisterListOpValue16(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; }; // class MipsMCCodeEmitter } // namespace llvm. diff --git a/llvm/lib/Target/Mips/MicroMipsInstrFormats.td b/llvm/lib/Target/Mips/MicroMipsInstrFormats.td index dcd0e597178..2301a1ccf8f 100644 --- a/llvm/lib/Target/Mips/MicroMipsInstrFormats.td +++ b/llvm/lib/Target/Mips/MicroMipsInstrFormats.td @@ -838,3 +838,15 @@ class LWM_FM_MM<bits<4> funct> : MMArch { let Inst{15-12} = funct; let Inst{11-0} = addr{11-0}; } + +class LWM_FM_MM16<bits<4> funct> : MMArch { + bits<2> rt; + bits<4> addr; + + bits<16> Inst; + + let Inst{15-10} = 0x11; + let Inst{9-6} = funct; + let Inst{5-4} = rt; + let Inst{3-0} = addr; +} diff --git a/llvm/lib/Target/Mips/MicroMipsInstrInfo.td b/llvm/lib/Target/Mips/MicroMipsInstrInfo.td index bfd05303d1d..7180fb449aa 100644 --- a/llvm/lib/Target/Mips/MicroMipsInstrInfo.td +++ b/llvm/lib/Target/Mips/MicroMipsInstrInfo.td @@ -86,6 +86,22 @@ def mem_mm_12 : Operand<i32> { let OperandType = "OPERAND_MEMORY"; } +def MipsMemUimm4AsmOperand : AsmOperandClass { + let Name = "MemOffsetUimm4"; + let SuperClasses = [MipsMemAsmOperand]; + let RenderMethod = "addMemOperands"; + let ParserMethod = "parseMemOperand"; + let PredicateMethod = "isMemWithUimmOffsetSP<6>"; +} + +def mem_mm_4sp : Operand<i32> { + let PrintMethod = "printMemOperand"; + let MIOperandInfo = (ops GPR32, uimm8); + let EncoderMethod = "getMemEncodingMMImm4sp"; + let ParserMatchClass = MipsMemUimm4AsmOperand; + let OperandType = "OPERAND_MEMORY"; +} + def jmptarget_mm : Operand<OtherVT> { let EncoderMethod = "getJumpTargetOpValueMM"; } @@ -339,6 +355,20 @@ def reglist : Operand<i32> { let DecoderMethod = "DecodeRegListOperand"; } +def RegList16AsmOperand : AsmOperandClass { + let Name = "RegList16"; + let ParserMethod = "parseRegisterList"; + let PredicateMethod = "isRegList16"; + let RenderMethod = "addRegListOperands"; +} + +def reglist16 : Operand<i32> { + let EncoderMethod = "getRegisterListOpValue16"; + let DecoderMethod = "DecodeRegListOperand16"; + let PrintMethod = "printRegisterList"; + let ParserMatchClass = RegList16AsmOperand; +} + class StoreMultMM<string opstr, InstrItinClass Itin = NoItinerary, ComplexPattern Addr = addr> : InstSE<(outs), (ins reglist:$rt, mem_mm_12:$addr), @@ -355,6 +385,22 @@ class LoadMultMM<string opstr, let mayLoad = 1; } +class StoreMultMM16<string opstr, + InstrItinClass Itin = NoItinerary, + ComplexPattern Addr = addr> : + MicroMipsInst16<(outs), (ins reglist16:$rt, mem_mm_4sp:$addr), + !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI> { + let mayStore = 1; +} + +class LoadMultMM16<string opstr, + InstrItinClass Itin = NoItinerary, + ComplexPattern Addr = addr> : + MicroMipsInst16<(outs reglist16:$rt), (ins mem_mm_4sp:$addr), + !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI> { + let mayLoad = 1; +} + def ADDU16_MM : ArithRMM16<"addu16", GPRMM16Opnd, 1, II_ADDU, add>, ARITH_FM_MM16<0>; def SUBU16_MM : ArithRMM16<"subu16", GPRMM16Opnd, 0, II_SUBU, sub>, @@ -504,6 +550,8 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { /// Load and Store Instructions - multiple def SWM32_MM : StoreMultMM<"swm32">, LWM_FM_MM<0xd>; def LWM32_MM : LoadMultMM<"lwm32">, LWM_FM_MM<0x5>; + def SWM16_MM : StoreMultMM16<"swm16">, LWM_FM_MM16<0x5>; + def LWM16_MM : LoadMultMM16<"lwm16">, LWM_FM_MM16<0x4>; /// Move Conditional def MOVZ_I_MM : MMRel, CMov_I_I_FT<"movz", GPR32Opnd, GPR32Opnd, |