Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -147,6 +147,9 @@ MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands); MipsAsmParser::OperandMatchResultTy + parseRegisterPair (OperandVector &Operands); + + MipsAsmParser::OperandMatchResultTy parseRegisterList (OperandVector &Operands); bool searchSymbolAlias(OperandVector &Operands); @@ -428,7 +431,8 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ case k_PhysRegister: case k_RegisterIndex: case k_Token: + case k_RegPair: break; } } @@ -1094,6 +1121,9 @@ OS << Reg << " "; OS << ">"; break; + case k_RegPair: + OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">"; + break; } } }; // class MipsOperand @@ -2723,6 +2753,22 @@ 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 = Index: lib/Target/Mips/Disassembler/MipsDisassembler.cpp =================================================================== --- lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -1221,6 +1221,9 @@ // 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)); } Index: lib/Target/Mips/InstPrinter/MipsInstPrinter.h =================================================================== --- lib/Target/Mips/InstPrinter/MipsInstPrinter.h +++ lib/Target/Mips/InstPrinter/MipsInstPrinter.h @@ -99,6 +99,7 @@ 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, Index: lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp =================================================================== --- lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp +++ lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp @@ -262,6 +262,11 @@ } 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"); } Index: lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h +++ lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h @@ -184,6 +184,10 @@ 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; Index: lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -862,4 +862,11 @@ 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" Index: lib/Target/Mips/MicroMipsInstrInfo.td =================================================================== --- lib/Target/Mips/MicroMipsInstrInfo.td +++ lib/Target/Mips/MicroMipsInstrInfo.td @@ -148,6 +148,36 @@ let DecoderMethod = "DecodeMemMMImm12"; } +/// A register pair used by load/store pair instructions. +def RegPairAsmOperand : AsmOperandClass { + let Name = "RegPair"; + let ParserMethod = "parseRegisterPair"; +} + +def regpair : Operand { + 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> { @@ -556,6 +586,10 @@ 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>; Index: test/MC/Disassembler/Mips/micromips.txt =================================================================== --- test/MC/Disassembler/Mips/micromips.txt +++ 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 Index: test/MC/Disassembler/Mips/micromips_le.txt =================================================================== --- test/MC/Disassembler/Mips/micromips_le.txt +++ 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 Index: test/MC/Mips/micromips-loadstore-instructions.s =================================================================== --- test/MC/Mips/micromips-loadstore-instructions.s +++ 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)