Index: llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -302,6 +302,9 @@ bool expandLoadStoreDMacro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI, bool IsLoad); + bool expandStoreDM1Macro(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI); + bool expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI); @@ -2538,6 +2541,10 @@ Inst.getOpcode() == Mips::LDMacro) ? MER_Fail : MER_Success; + case Mips::SDC1_M1: + return expandStoreDM1Macro(Inst, IDLoc, Out, STI) + ? MER_Fail + : MER_Success; case Mips::SEQMacro: return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; case Mips::SEQIMacro: @@ -4844,6 +4851,49 @@ return false; } + +// Expand 's.d $ offset($reg2)' to 'swc1 $, offset($reg2); +// swc1 $, offset+4($reg2)' +// or if little endian to 'swc1 $, offset($reg2); +// swc1 $, offset+4($reg2)' +// for Mips1. +bool MipsAsmParser::expandStoreDM1Macro(MCInst &Inst, SMLoc IDLoc, + MCStreamer &Out, + const MCSubtargetInfo *STI) { + if (!isABI_O32()) + return true; + + warnIfNoMacro(IDLoc); + + MipsTargetStreamer &TOut = getTargetStreamer(); + unsigned Opcode = Mips::SWC1; + unsigned FirstReg = Inst.getOperand(0).getReg(); + unsigned SecondReg = nextReg(FirstReg); + unsigned BaseReg = Inst.getOperand(1).getReg(); + if (!SecondReg) + return true; + + warnIfRegIndexIsAT(FirstReg, IDLoc); + + assert(Inst.getOperand(2).isImm() && + "Offset for macro is not immediate!"); + + MCOperand &FirstOffset = Inst.getOperand(2); + signed NextOffset = FirstOffset.getImm() + 4; + MCOperand SecondOffset = MCOperand::createImm(NextOffset); + + if (!isInt<16>(FirstOffset.getImm()) || !isInt<16>(NextOffset)) + return true; + + if (!IsLittleEndian) + std::swap(FirstReg, SecondReg); + + TOut.emitRRX(Opcode, FirstReg, BaseReg, FirstOffset, IDLoc, STI); + TOut.emitRRX(Opcode, SecondReg, BaseReg, SecondOffset, IDLoc, STI); + + return false; +} + bool MipsAsmParser::expandSeq(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI) { Index: llvm/trunk/lib/Target/Mips/MipsInstrFPU.td =================================================================== --- llvm/trunk/lib/Target/Mips/MipsInstrFPU.td +++ llvm/trunk/lib/Target/Mips/MipsInstrFPU.td @@ -787,6 +787,11 @@ "li.d\t$rd, $fpimm">, FGR_64, HARDFLOAT; +def SDC1_M1 : MipsAsmPseudoInst<(outs AFGR64Opnd:$fd), + (ins mem_simm16:$addr), + "s.d\t$fd, $addr">, + FGR_32, ISA_MIPS1, HARDFLOAT; + //===----------------------------------------------------------------------===// // InstAliases. //===----------------------------------------------------------------------===// @@ -799,6 +804,9 @@ def : MipsInstAlias <"s.d $fd, $addr", (SDC164 FGR64Opnd:$fd, mem_simm16:$addr), 0>, FGR_64, ISA_MIPS2, HARDFLOAT; +def : MipsInstAlias + <"s.d $fd, $addr", (SDC1_M1 AFGR64Opnd:$fd, mem_simm16:$addr), 0>, + FGR_32, ISA_MIPS1, HARDFLOAT; def : MipsInstAlias <"l.s $fd, $addr", (LWC1 FGR32Opnd:$fd, mem_simm16:$addr), 0>, Index: llvm/trunk/test/MC/Mips/mips1/sd.s =================================================================== --- llvm/trunk/test/MC/Mips/mips1/sd.s +++ llvm/trunk/test/MC/Mips/mips1/sd.s @@ -0,0 +1,13 @@ +# RUN: llvm-mc -filetype=obj -triple mips -mcpu=mips1 %s -o - \ +# RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=MIPS1-EB +# RUN: llvm-mc -filetype=obj -triple mipsel -mcpu=mips1 %s -o - \ +# RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=MIPS1-EL + +# Check if s.d instruction alias is suported on Mips1. + +# MIPS1-EB: 0: e4 c1 00 00 swc1 $f1, 0($6) +# MIPS1-EB: 4: e4 c0 00 04 swc1 $f0, 4($6) + +# MIPS1-EL: 0: 00 00 c0 e4 swc1 $f0, 0($6) +# MIPS1-EL: 4: 04 00 c1 e4 swc1 $f1, 4($6) +s.d $f0, 0($6)