diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index aadaf053512..af9a731e606 100644 --- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -182,6 +182,10 @@ class MipsAsmParser : public MCTargetAsmParser { void expandMemInst(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl &Instructions, bool isLoad, bool isImmOpnd); + + bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl &Instructions); + bool reportParseError(Twine ErrorMsg); bool reportParseError(SMLoc Loc, Twine ErrorMsg); @@ -1532,6 +1536,8 @@ bool MipsAsmParser::needsExpansion(MCInst &Inst) { case Mips::LoadAddr32Reg: case Mips::LoadImm64Reg: case Mips::B_MM_Pseudo: + case Mips::LWM_MM: + case Mips::SWM_MM: return true; default: return false; @@ -1556,6 +1562,9 @@ bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc, return expandLoadAddressReg(Inst, IDLoc, Instructions); case Mips::B_MM_Pseudo: return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions); + case Mips::SWM_MM: + case Mips::LWM_MM: + return expandLoadStoreMultiple(Inst, IDLoc, Instructions); } } @@ -2000,6 +2009,29 @@ void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, TempInst.clear(); } +bool +MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl &Instructions) { + unsigned OpNum = Inst.getNumOperands(); + unsigned Opcode = Inst.getOpcode(); + unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM; + + assert (Inst.getOperand(OpNum - 1).isImm() && + Inst.getOperand(OpNum - 2).isReg() && + Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand."); + + if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 && + Inst.getOperand(OpNum - 1).getImm() >= 0 && + Inst.getOperand(OpNum - 2).getReg() == Mips::SP && + Inst.getOperand(OpNum - 3).getReg() == Mips::RA) + // It can be implemented as SWM16 or LWM16 instruction. + NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM; + + Inst.setOpcode(NewOpcode); + Instructions.push_back(Inst); + return false; +} + unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) { // As described by the Mips32r2 spec, the registers Rd and Rs for // jalr.hb must be different. diff --git a/lib/Target/Mips/MicroMipsInstrInfo.td b/lib/Target/Mips/MicroMipsInstrInfo.td index c6b984df7de..e03cad30b41 100644 --- a/lib/Target/Mips/MicroMipsInstrInfo.td +++ b/lib/Target/Mips/MicroMipsInstrInfo.td @@ -697,6 +697,19 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { def SWP_MM : StorePairMM<"swp">, LWM_FM_MM<0x9>; def LWP_MM : LoadPairMM<"lwp">, LWM_FM_MM<0x1>; + /// Load and Store multiple pseudo Instructions + class LoadWordMultMM : + MipsAsmPseudoInst<(outs reglist:$rt), (ins mem_mm_12:$addr), + !strconcat(instr_asm, "\t$rt, $addr")> ; + + class StoreWordMultMM : + MipsAsmPseudoInst<(outs), (ins reglist:$rt, mem_mm_12:$addr), + !strconcat(instr_asm, "\t$rt, $addr")> ; + + + def SWM_MM : StoreWordMultMM<"swm">; + def LWM_MM : LoadWordMultMM<"lwm">; + /// 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/Mips/micromips-loadstore-instructions.s b/test/MC/Mips/micromips-loadstore-instructions.s index de89056ce3c..f22719dff94 100644 --- a/test/MC/Mips/micromips-loadstore-instructions.s +++ b/test/MC/Mips/micromips-loadstore-instructions.s @@ -34,6 +34,14 @@ # 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: lwm16 $16, $17, $ra, 8($sp) # encoding: [0x12,0x45] +# CHECK-EL: lwm32 $16, $17, $ra, 64($sp) # encoding: [0x5d,0x22,0x40,0x50] +# CHECK-EL: lwm32 $16, $17, $ra, 8($4) # encoding: [0x44,0x22,0x08,0x50] +# CHECK-EL: lwm32 $16, $17, 8($sp) # encoding: [0x5d,0x20,0x08,0x50] +# CHECK-EL: swm16 $16, $17, $ra, 8($sp) # encoding: [0x52,0x45] +# CHECK-EL: swm32 $16, $17, $ra, 64($sp) # encoding: [0x5d,0x22,0x40,0xd0] +# CHECK-EL: swm32 $16, $17, $ra, 8($4) # encoding: [0x44,0x22,0x08,0xd0] +# CHECK-EL: swm32 $16, $17, 8($sp) # encoding: [0x5d,0x20,0x08,0xd0] # CHECK-EL: swp $16, 8($4) # encoding: [0x04,0x22,0x08,0x90] # CHECK-EL: lwp $16, 8($4) # encoding: [0x04,0x22,0x08,0x10] #------------------------------------------------------------------------------ @@ -64,6 +72,14 @@ # 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: lwm16 $16, $17, $ra, 8($sp) # encoding: [0x45,0x12] +# CHECK-EB: lwm32 $16, $17, $ra, 64($sp) # encoding: [0x22,0x5d,0x50,0x40] +# CHECK-EB: lwm32 $16, $17, $ra, 8($4) # encoding: [0x22,0x44,0x50,0x08] +# CHECK-EB: lwm32 $16, $17, 8($sp) # encoding: [0x20,0x5d,0x50,0x08] +# CHECK-EB: swm16 $16, $17, $ra, 8($sp) # encoding: [0x45,0x52] +# CHECK-EB: swm32 $16, $17, $ra, 64($sp) # encoding: [0x22,0x5d,0xd0,0x40] +# CHECK-EB: swm32 $16, $17, $ra, 8($4) # encoding: [0x22,0x44,0xd0,0x08] +# CHECK-EB: swm32 $16, $17, 8($sp) # encoding: [0x20,0x5d,0xd0,0x08] # 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) @@ -91,5 +107,13 @@ swm32 $16 - $19, 8($4) lwm16 $16, $17, $ra, 8($sp) swm16 $16, $17, $ra, 8($sp) + lwm $16, $17, $ra, 8($sp) + lwm $16, $17, $ra, 64($sp) + lwm $16, $17, $ra, 8($4) + lwm $16, $17, 8($sp) + swm $16, $17, $ra, 8($sp) + swm $16, $17, $ra, 64($sp) + swm $16, $17, $ra, 8($4) + swm $16, $17, 8($sp) swp $16, 8($4) lwp $16, 8($4)