From d72dae73a81e5a450309f64864a7c16a5c386460 Mon Sep 17 00:00:00 2001 From: Zoran Jovanovic Date: Tue, 16 Dec 2014 14:59:10 +0000 Subject: [PATCH] [mips][microMIPS] Implement SWP and LWP instructions Differential Revision: http://reviews.llvm.org/D5667 llvm-svn: 224338 --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 48 ++++++++++++++++++- .../Mips/Disassembler/MipsDisassembler.cpp | 3 ++ .../Mips/InstPrinter/MipsInstPrinter.cpp | 5 ++ lib/Target/Mips/InstPrinter/MipsInstPrinter.h | 1 + .../Mips/MCTargetDesc/MipsMCCodeEmitter.cpp | 7 +++ .../Mips/MCTargetDesc/MipsMCCodeEmitter.h | 4 ++ lib/Target/Mips/MicroMipsInstrInfo.td | 34 +++++++++++++ test/MC/Disassembler/Mips/micromips.txt | 6 +++ test/MC/Disassembler/Mips/micromips_le.txt | 6 +++ .../Mips/micromips-loadstore-instructions.s | 6 +++ 10 files changed, 119 insertions(+), 1 deletion(-) diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 67725cb7ffa..44e0532f413 100644 --- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -146,6 +146,9 @@ class MipsAsmParser : public MCTargetAsmParser { MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands); + MipsAsmParser::OperandMatchResultTy + parseRegisterPair (OperandVector &Operands); + MipsAsmParser::OperandMatchResultTy parseRegisterList (OperandVector &Operands); @@ -428,7 +431,8 @@ private: k_PhysRegister, /// A physical register from the Mips namespace k_RegisterIndex, /// A register index in one or more RegKind. k_Token, /// A simple token - k_RegList /// A physical register list + k_RegList, /// A physical register list + k_RegPair /// A pair of physical register } Kind; public: @@ -781,6 +785,13 @@ public: Inst.addOperand(MCOperand::CreateReg(RegNo)); } + void addRegPairOperands(MCInst &Inst, unsigned N) const { + assert(N == 2 && "Invalid number of operands!"); + unsigned RegNo = getRegPair(); + Inst.addOperand(MCOperand::CreateReg(RegNo++)); + Inst.addOperand(MCOperand::CreateReg(RegNo)); + } + bool isReg() const override { // As a special case until we sort out the definition of div/divu, pretend // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly. @@ -845,6 +856,7 @@ public: assert(Kind == k_Token && "Invalid access!"); return StringRef(Tok.Data, Tok.Length); } + bool isRegPair() const { return Kind == k_RegPair; } unsigned getReg() const override { // As a special case until we sort out the definition of div/divu, pretend @@ -886,6 +898,11 @@ public: return *(RegList.List); } + unsigned getRegPair() const { + assert((Kind == k_RegPair) && "Invalid access!"); + return RegIdx.Index; + } + static std::unique_ptr CreateToken(StringRef Str, SMLoc S, MipsAsmParser &Parser) { auto Op = make_unique(k_Token, Parser); @@ -995,6 +1012,15 @@ public: return Op; } + static std::unique_ptr + CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) { + auto Op = make_unique(k_RegPair, Parser); + Op->RegIdx.Index = RegNo; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; + } + bool isGPRAsmReg() const { return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31; } @@ -1061,6 +1087,7 @@ public: case k_PhysRegister: case k_RegisterIndex: case k_Token: + case k_RegPair: break; } } @@ -1094,6 +1121,9 @@ public: OS << Reg << " "; OS << ">"; break; + case k_RegPair: + OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">"; + break; } } }; // class MipsOperand @@ -2723,6 +2753,22 @@ MipsAsmParser::parseRegisterList(OperandVector &Operands) { return MatchOperand_Success; } +MipsAsmParser::OperandMatchResultTy +MipsAsmParser::parseRegisterPair(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); + + SMLoc S = Parser.getTok().getLoc(); + if (parseAnyRegister(Operands) != MatchOperand_Success) + return MatchOperand_ParseFail; + + SMLoc E = Parser.getTok().getLoc(); + MipsOperand &Op = static_cast(*Operands.back()); + unsigned Reg = Op.getGPR32Reg(); + Operands.pop_back(); + Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this)); + return MatchOperand_Success; +} + MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) { MCSymbolRefExpr::VariantKind VK = diff --git a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp index ec90781f629..d29347d6213 100644 --- a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -1222,6 +1222,9 @@ static DecodeStatus DecodeMemMMImm12(MCInst &Inst, // fallthrough default: Inst.addOperand(MCOperand::CreateReg(Reg)); + if (Inst.getOpcode() == Mips::LWP_MM || Inst.getOpcode() == Mips::SWP_MM) + Inst.addOperand(MCOperand::CreateReg(Reg+1)); + Inst.addOperand(MCOperand::CreateReg(Base)); Inst.addOperand(MCOperand::CreateImm(Offset)); } diff --git a/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp b/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp index e8366290c16..80e555e5f5c 100644 --- a/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp +++ b/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp @@ -261,6 +261,11 @@ printFCCOperand(const MCInst *MI, int opNum, raw_ostream &O) { O << MipsFCCToString((Mips::CondCode)MO.getImm()); } +void MipsInstPrinter:: +printRegisterPair(const MCInst *MI, int opNum, raw_ostream &O) { + printRegName(O, MI->getOperand(opNum).getReg()); +} + void MipsInstPrinter:: printSHFMask(const MCInst *MI, int opNum, raw_ostream &O) { llvm_unreachable("TODO"); diff --git a/lib/Target/Mips/InstPrinter/MipsInstPrinter.h b/lib/Target/Mips/InstPrinter/MipsInstPrinter.h index 42df0131d0a..468dc07818e 100644 --- a/lib/Target/Mips/InstPrinter/MipsInstPrinter.h +++ b/lib/Target/Mips/InstPrinter/MipsInstPrinter.h @@ -99,6 +99,7 @@ private: void printMemOperand(const MCInst *MI, int opNum, raw_ostream &O); void printMemOperandEA(const MCInst *MI, int opNum, raw_ostream &O); void printFCCOperand(const MCInst *MI, int opNum, raw_ostream &O); + void printRegisterPair(const MCInst *MI, int opNum, raw_ostream &O); void printSHFMask(const MCInst *MI, int opNum, raw_ostream &O); bool printAlias(const char *Str, const MCInst &MI, unsigned OpNo, diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp index 0c86d11659c..689248b065f 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -862,4 +862,11 @@ MipsMCCodeEmitter::getRegisterListOpValue16(const MCInst &MI, unsigned OpNo, return (MI.getNumOperands() - 4); } +unsigned +MipsMCCodeEmitter::getRegisterPairOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + return getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI); +} + #include "MipsGenMCCodeEmitter.inc" diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h index b557f740430..4a4c9f6e0d3 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h +++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h @@ -184,6 +184,10 @@ public: SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + unsigned getRegisterPairOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + unsigned getExprOpValue(const MCExpr *Expr, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; diff --git a/lib/Target/Mips/MicroMipsInstrInfo.td b/lib/Target/Mips/MicroMipsInstrInfo.td index 9675ef21411..3fae97c32ef 100644 --- a/lib/Target/Mips/MicroMipsInstrInfo.td +++ b/lib/Target/Mips/MicroMipsInstrInfo.td @@ -148,6 +148,36 @@ class StoreLeftRightMM { + let EncoderMethod = "getRegisterPairOpValue"; + let ParserMatchClass = RegPairAsmOperand; + let PrintMethod = "printRegisterPair"; + let DecoderMethod = "DecodeRegPairOperand"; + let MIOperandInfo = (ops GPR32Opnd, GPR32Opnd); +} + +class StorePairMM : + InstSE<(outs), (ins regpair:$rt, mem_mm_12:$addr), + !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI, opstr> { + let DecoderMethod = "DecodeMemMMImm12"; + let mayStore = 1; +} + +class LoadPairMM : + InstSE<(outs regpair:$rt), (ins mem_mm_12:$addr), + !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI, opstr> { + let DecoderMethod = "DecodeMemMMImm12"; + let mayLoad = 1; +} + class LLBaseMM : InstSE<(outs RO:$rt), (ins mem_mm_12:$addr), !strconcat(opstr, "\t$rt, $addr"), [], NoItinerary, FrmI> { @@ -555,6 +585,10 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { def SWM16_MM : StoreMultMM16<"swm16">, LWM_FM_MM16<0x5>; def LWM16_MM : LoadMultMM16<"lwm16">, LWM_FM_MM16<0x4>; + /// Load and Store Pair Instructions + def SWP_MM : StorePairMM<"swp">, LWM_FM_MM<0x9>; + def LWP_MM : LoadPairMM<"lwp">, LWM_FM_MM<0x1>; + /// Move Conditional def MOVZ_I_MM : MMRel, CMov_I_I_FT<"movz", GPR32Opnd, GPR32Opnd, NoItinerary>, ADD_FM_MM<0, 0x58>; diff --git a/test/MC/Disassembler/Mips/micromips.txt b/test/MC/Disassembler/Mips/micromips.txt index 164f5396df9..87aa9ede66d 100644 --- a/test/MC/Disassembler/Mips/micromips.txt +++ b/test/MC/Disassembler/Mips/micromips.txt @@ -343,6 +343,12 @@ # CHECK: swm32 $16, $17, 8($4) 0x20 0x44 0xd0 0x08 +# CHECK: swp $16, 8($4) +0x22 0x04 0x90 0x08 + +# CHECK: lwp $16, 8($4) +0x22 0x04 0x10 0x08 + # CHECK: nop 0x00 0x00 0x00 0x00 diff --git a/test/MC/Disassembler/Mips/micromips_le.txt b/test/MC/Disassembler/Mips/micromips_le.txt index 39be8dc57b6..71acaf28aa0 100644 --- a/test/MC/Disassembler/Mips/micromips_le.txt +++ b/test/MC/Disassembler/Mips/micromips_le.txt @@ -343,6 +343,12 @@ # CHECK: swm32 $16, $17, 8($4) 0x44 0x20 0x08 0xd0 +# CHECK: swp $16, 8($4) +0x04 0x22 0x08 0x90 + +# CHECK: lwp $16, 8($4) +0x04 0x22 0x08 0x10 + # CHECK: nop 0x00 0x00 0x00 0x00 diff --git a/test/MC/Mips/micromips-loadstore-instructions.s b/test/MC/Mips/micromips-loadstore-instructions.s index 8c406695cf6..5133c36bb02 100644 --- a/test/MC/Mips/micromips-loadstore-instructions.s +++ b/test/MC/Mips/micromips-loadstore-instructions.s @@ -31,6 +31,8 @@ # CHECK-EL: swm32 $16, $17, $18, $19, 8($4) # encoding: [0x84,0x20,0x08,0xd0] # CHECK-EL: lwm16 $16, $17, $ra, 8($sp) # encoding: [0x12,0x45] # CHECK-EL: swm16 $16, $17, $ra, 8($sp) # encoding: [0x52,0x45] +# CHECK-EL: swp $16, 8($4) # encoding: [0x04,0x22,0x08,0x90] +# CHECK-EL: lwp $16, 8($4) # encoding: [0x04,0x22,0x08,0x10] #------------------------------------------------------------------------------ # Big endian #------------------------------------------------------------------------------ @@ -56,6 +58,8 @@ # CHECK-EB: swm32 $16, $17, $18, $19, 8($4) # encoding: [0x20,0x84,0xd0,0x08] # CHECK-EB: lwm16 $16, $17, $ra, 8($sp) # encoding: [0x45,0x12] # CHECK-EB: swm16 $16, $17, $ra, 8($sp) # encoding: [0x45,0x52] +# CHECK-EB: swp $16, 8($4) # encoding: [0x22,0x04,0x90,0x08] +# CHECK-EB: lwp $16, 8($4) # encoding: [0x22,0x04,0x10,0x08] lb $5, 8($4) lbu $6, 8($4) lh $2, 8($4) @@ -78,3 +82,5 @@ swm32 $16 - $19, 8($4) lwm16 $16, $17, $ra, 8($sp) swm16 $16, $17, $ra, 8($sp) + swp $16, 8($4) + lwp $16, 8($4)