Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -824,6 +824,11 @@ return isMem() && isConstantMemOff() && isUInt(getConstantMemOff()) && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP); } + template bool isMemWithUimmWordAlignedOffsetSP() const { + return isMem() && isConstantMemOff() && isUInt(getConstantMemOff()) + && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx() + && (getMemBase()->getGPR32Reg() == Mips::SP); + } bool isRegList16() const { if (!isRegList()) return false; Index: lib/Target/Mips/Disassembler/MipsDisassembler.cpp =================================================================== --- lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -265,6 +265,11 @@ uint64_t Address, const void *Decoder); +static DecodeStatus DecodeMemMMSPImm5Lsl2(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + static DecodeStatus DecodeMemMMImm12(MCInst &Inst, unsigned Insn, uint64_t Address, @@ -1200,6 +1205,22 @@ return MCDisassembler::Success; } +static DecodeStatus DecodeMemMMSPImm5Lsl2(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + unsigned Offset = Insn & 0x1F; + unsigned Reg = fieldFromInstruction(Insn, 5, 5); + + Reg = getReg(Decoder, Mips::GPR32RegClassID, Reg); + + Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::CreateReg(Mips::SP)); + Inst.addOperand(MCOperand::CreateImm(Offset << 2)); + + return MCDisassembler::Success; +} + static DecodeStatus DecodeMemMMImm12(MCInst &Inst, unsigned Insn, uint64_t Address, Index: lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h +++ lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h @@ -151,6 +151,9 @@ unsigned getMemEncodingMMImm4Lsl2(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + unsigned getMemEncodingMMSPImm5Lsl2(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; unsigned getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo, 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 @@ -678,6 +678,20 @@ } unsigned MipsMCCodeEmitter:: +getMemEncodingMMSPImm5Lsl2(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + // Register is encoded in bits 9-5, offset is encoded in bits 4-0. + assert(MI.getOperand(OpNo).isReg() && + MI.getOperand(OpNo).getReg() == Mips::SP && + "Unexpected base register!"); + unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), + Fixups, STI) >> 2; + + return OffBits & 0x1F; +} + +unsigned MipsMCCodeEmitter:: getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { Index: lib/Target/Mips/MicroMipsInstrFormats.td =================================================================== --- lib/Target/Mips/MicroMipsInstrFormats.td +++ lib/Target/Mips/MicroMipsInstrFormats.td @@ -120,6 +120,17 @@ let Inst{3-0} = addr{3-0}; } +class LOAD_STORE_SP_FM_MM16 op> { + bits<5> rt; + bits<5> offset; + + bits<16> Inst; + + let Inst{15-10} = op; + let Inst{9-5} = rt; + let Inst{4-0} = offset; +} + class ADDIUS5_FM_MM16 { bits<5> rd; bits<4> imm; Index: lib/Target/Mips/MicroMipsInstrInfo.td =================================================================== --- lib/Target/Mips/MicroMipsInstrInfo.td +++ lib/Target/Mips/MicroMipsInstrInfo.td @@ -81,6 +81,21 @@ let EncoderMethod = "getMemEncodingMMImm4Lsl2"; } +def MicroMipsMemSPAsmOperand : AsmOperandClass { + let Name = "MicroMipsMemSP"; + let RenderMethod = "addMemOperands"; + let ParserMethod = "parseMemOperand"; + let PredicateMethod = "isMemWithUimmWordAlignedOffsetSP<7>"; +} + +def mem_mm_sp_imm5_lsl2 : Operand { + let PrintMethod = "printMemOperand"; + let MIOperandInfo = (ops GPR32:$base, simm5:$offset); + let OperandType = "OPERAND_MEMORY"; + let ParserMatchClass = MicroMipsMemSPAsmOperand; + let EncoderMethod = "getMemEncodingMMSPImm5Lsl2"; +} + def mem_mm_12 : Operand { let PrintMethod = "printMemOperand"; let MIOperandInfo = (ops GPR32, simm12); @@ -260,6 +275,23 @@ let mayStore = 1; } +class LoadSPMM16 : + MicroMipsInst16<(outs RO:$rt), (ins MemOpnd:$offset), + !strconcat(opstr, "\t$rt, $offset"), [], Itin, FrmI> { + let DecoderMethod = "DecodeMemMMSPImm5Lsl2"; + let canFoldAsLoad = 1; + let mayLoad = 1; +} + +class StoreSPMM16 : + MicroMipsInst16<(outs), (ins RO:$rt, MemOpnd:$offset), + !strconcat(opstr, "\t$rt, $offset"), [], Itin, FrmI> { + let DecoderMethod = "DecodeMemMMSPImm5Lsl2"; + let mayStore = 1; +} + class AddImmUR2 : MicroMipsInst16<(outs RO:$rd), (ins RO:$rs, simm3_lsa2:$imm), !strconcat(opstr, "\t$rd, $rs, $imm"), @@ -471,6 +503,10 @@ LOAD_STORE_FM_MM16<0x2a>; def SW16_MM : StoreMM16<"sw16", GPRMM16OpndZero, GPRMM16Opnd, store, II_SW, mem_mm_4_lsl2>, LOAD_STORE_FM_MM16<0x3a>; +def LWSP_MM : LoadSPMM16<"lw", GPR32Opnd, II_LW, mem_mm_sp_imm5_lsl2>, + LOAD_STORE_SP_FM_MM16<0x12>; +def SWSP_MM : StoreSPMM16<"sw", GPR32Opnd, II_SW, mem_mm_sp_imm5_lsl2>, + LOAD_STORE_SP_FM_MM16<0x32>; def ADDIUR1SP_MM : AddImmUR1SP<"addiur1sp", GPRMM16Opnd>, ADDIUR1SP_FM_MM16; def ADDIUR2_MM : AddImmUR2<"addiur2", GPRMM16Opnd>, ADDIUR2_FM_MM16; def ADDIUS5_MM : AddImmUS5<"addius5", GPR32Opnd>, ADDIUS5_FM_MM16; Index: test/MC/Disassembler/Mips/micromips.txt =================================================================== --- test/MC/Disassembler/Mips/micromips.txt +++ test/MC/Disassembler/Mips/micromips.txt @@ -154,6 +154,9 @@ # CHECK: lw $6, 4($5) 0xfc 0xc5 0x00 0x04 +# CHECK: lw $6, 123($sp) +0xfc 0xdd 0x00 0x7b + # CHECK: sb $5, 8($4) 0x18 0xa4 0x00 0x08 @@ -163,6 +166,9 @@ # CHECK: sw $5, 4($6) 0xf8 0xa6 0x00 0x04 +# CHECK: sw $5, 123($sp) +0xf8 0xbd 0x00 0x7b + # CHECK: lwu $2, 8($4) 0x60 0x44 0xe0 0x08 @@ -450,3 +456,9 @@ # CHECK: nop 0x0c 0x00 + +# CHECK: lw $3, 32($sp) +0x48 0x68 + +# CHECK: sw $4, 124($sp) +0xc8 0x9f Index: test/MC/Disassembler/Mips/micromips_le.txt =================================================================== --- test/MC/Disassembler/Mips/micromips_le.txt +++ test/MC/Disassembler/Mips/micromips_le.txt @@ -154,6 +154,9 @@ # CHECK: lw $6, 4($5) 0xc5 0xfc 0x04 0x00 +# CHECK: lw $6, 123($sp) +0xdd 0xfc 0x7b 0x00 + # CHECK: sb $5, 8($4) 0xa4 0x18 0x08 0x00 @@ -163,6 +166,9 @@ # CHECK: sw $5, 4($6) 0xa6 0xf8 0x04 0x00 +# CHECK: sw $5, 123($sp) +0xbd 0xf8 0x7b 0x00 + # CHECK: lwu $2, 8($4) 0x44 0x60 0x08 0xe0 @@ -450,3 +456,9 @@ # CHECK: nop 0x00 0x0c + +# CHECK: lw $3, 32($sp) +0x68 0x48 + +# CHECK: sw $4, 124($sp) +0x9f 0xc8 Index: test/MC/Mips/micromips-16-bit-instructions.s =================================================================== --- test/MC/Mips/micromips-16-bit-instructions.s +++ test/MC/Mips/micromips-16-bit-instructions.s @@ -26,6 +26,8 @@ # CHECK-EL: sh16 $4, 8($17) # encoding: [0x14,0xaa] # CHECK-EL: sw16 $4, 4($17) # encoding: [0x11,0xea] # CHECK-EL: sw16 $zero, 4($17) # encoding: [0x11,0xe8] +# CHECK-EL: lw $3, 32($sp) # encoding: [0x68,0x48] +# CHECK-EL: sw $4, 124($sp) # encoding: [0x9f,0xc8] # CHECK-EL: li16 $3, -1 # encoding: [0xff,0xed] # CHECK-EL: li16 $3, 126 # encoding: [0xfe,0xed] # CHECK-EL: addiur1sp $7, 4 # encoding: [0x83,0x6f] @@ -69,6 +71,8 @@ # CHECK-EB: sh16 $4, 8($17) # encoding: [0xaa,0x14] # CHECK-EB: sw16 $4, 4($17) # encoding: [0xea,0x11] # CHECK-EB: sw16 $zero, 4($17) # encoding: [0xe8,0x11] +# CHECK-EB: lw $3, 32($sp) # encoding: [0x48,0x68] +# CHECK-EB: sw $4, 124($sp) # encoding: [0xc8,0x9f] # CHECK-EB: li16 $3, -1 # encoding: [0xed,0xff] # CHECK-EB: li16 $3, 126 # encoding: [0xed,0xfe] # CHECK-EB: addiur1sp $7, 4 # encoding: [0x6f,0x83] @@ -110,6 +114,8 @@ sh16 $4, 8($17) sw16 $4, 4($17) sw16 $0, 4($17) + lw $3, 32($sp) + sw $4, 124($sp) li16 $3, -1 li16 $3, 126 addiur1sp $7, 4 Index: test/MC/Mips/micromips-loadstore-instructions.s =================================================================== --- test/MC/Mips/micromips-loadstore-instructions.s +++ test/MC/Mips/micromips-loadstore-instructions.s @@ -14,9 +14,11 @@ # CHECK-EL: lh $2, 8($4) # encoding: [0x44,0x3c,0x08,0x00] # CHECK-EL: lhu $4, 8($2) # encoding: [0x82,0x34,0x08,0x00] # CHECK-EL: lw $6, 4($5) # encoding: [0xc5,0xfc,0x04,0x00] +# CHECK-EL: lw $6, 123($sp) # encoding: [0xdd,0xfc,0x7b,0x00] # CHECK-EL: sb $5, 8($4) # encoding: [0xa4,0x18,0x08,0x00] # CHECK-EL: sh $2, 8($4) # encoding: [0x44,0x38,0x08,0x00] # CHECK-EL: sw $5, 4($6) # encoding: [0xa6,0xf8,0x04,0x00] +# CHECK-EL: sw $5, 123($sp) # encoding: [0xbd,0xf8,0x7b,0x00] # CHECK-EL: ll $2, 8($4) # encoding: [0x44,0x60,0x08,0x30] # CHECK-EL: sc $2, 8($4) # encoding: [0x44,0x60,0x08,0xb0] # CHECK-EL: lwu $2, 8($4) # encoding: [0x44,0x60,0x08,0xe0] @@ -41,9 +43,11 @@ # CHECK-EB: lh $2, 8($4) # encoding: [0x3c,0x44,0x00,0x08] # CHECK-EB: lhu $4, 8($2) # encoding: [0x34,0x82,0x00,0x08] # CHECK-EB: lw $6, 4($5) # encoding: [0xfc,0xc5,0x00,0x04] +# CHECK-EB: lw $6, 123($sp) # encoding: [0xfc,0xdd,0x00,0x7b] # CHECK-EB: sb $5, 8($4) # encoding: [0x18,0xa4,0x00,0x08] # CHECK-EB: sh $2, 8($4) # encoding: [0x38,0x44,0x00,0x08] # CHECK-EB: sw $5, 4($6) # encoding: [0xf8,0xa6,0x00,0x04] +# CHECK-EB: sw $5, 123($sp) # encoding: [0xf8,0xbd,0x00,0x7b] # CHECK-EB: ll $2, 8($4) # encoding: [0x60,0x44,0x30,0x08] # CHECK-EB: sc $2, 8($4) # encoding: [0x60,0x44,0xb0,0x08] # CHECK-EB: lwu $2, 8($4) # encoding: [0x60,0x44,0xe0,0x08] @@ -65,9 +69,11 @@ lh $2, 8($4) lhu $4, 8($2) lw $6, 4($5) + lw $6, 123($sp) sb $5, 8($4) sh $2, 8($4) sw $5, 4($6) + sw $5, 123($sp) ll $2, 8($4) sc $2, 8($4) lwu $2, 8($4)