diff options
Diffstat (limited to 'lib/Target/Mips')
38 files changed, 2266 insertions, 982 deletions
diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index c403f21..0795cb9 100644 --- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -63,7 +63,6 @@ class MipsAsmParser : public MCTargetAsmParser { MCAsmParser &Parser; MipsAssemblerOptions Options; - #define GET_ASSEMBLER_HEADER #include "MipsGenAsmMatcher.inc" @@ -127,9 +126,12 @@ class MipsAsmParser : public MCTargetAsmParser { bool isLoad,bool isImmOpnd); bool reportParseError(StringRef ErrorMsg); - bool parseMemOffset(const MCExpr *&Res); + bool parseMemOffset(const MCExpr *&Res, bool isParenExpr); bool parseRelocOperand(const MCExpr *&Res); + const MCExpr* evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr); + + bool isEvaluated(const MCExpr *Expr); bool parseDirectiveSet(); bool parseSetAtDirective(); @@ -171,7 +173,7 @@ class MipsAsmParser : public MCTargetAsmParser { bool requestsDoubleOperand(StringRef Mnemonic); - unsigned getReg(int RC,int RegNo); + unsigned getReg(int RC, int RegNo); int getATReg(); @@ -269,7 +271,7 @@ public: void addImmOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); const MCExpr *Expr = getImm(); - addExpr(Inst,Expr); + addExpr(Inst, Expr); } void addMemOperands(MCInst &Inst, unsigned N) const { @@ -278,7 +280,7 @@ public: Inst.addOperand(MCOperand::CreateReg(getMemBase())); const MCExpr *Expr = getMemOff(); - addExpr(Inst,Expr); + addExpr(Inst, Expr); } bool isReg() const { return Kind == k_Register; } @@ -391,15 +393,19 @@ public: } /// getStartLoc - Get the location of the first token of this operand. - SMLoc getStartLoc() const { return StartLoc; } + SMLoc getStartLoc() const { + return StartLoc; + } /// getEndLoc - Get the location of the last token of this operand. - SMLoc getEndLoc() const { return EndLoc; } + SMLoc getEndLoc() const { + return EndLoc; + } virtual void print(raw_ostream &OS) const { llvm_unreachable("unimplemented!"); } -}; -} +}; // class MipsOperand +} // namespace namespace llvm { extern const MCInstrDesc MipsInsts[]; @@ -409,39 +415,55 @@ static const MCInstrDesc &getInstDesc(unsigned Opcode) { } bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions) { + SmallVectorImpl<MCInst> &Instructions) { const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode()); Inst.setLoc(IDLoc); + if (MCID.hasDelaySlot() && Options.isReorder()) { + // If this instruction has a delay slot and .set reorder is active, + // emit a NOP after it. + Instructions.push_back(Inst); + MCInst NopInst; + NopInst.setOpcode(Mips::SLL); + NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); + NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); + NopInst.addOperand(MCOperand::CreateImm(0)); + Instructions.push_back(NopInst); + return false; + } + if (MCID.mayLoad() || MCID.mayStore()) { // Check the offset of memory operand, if it is a symbol - // reference or immediate we may have to expand instructions - for (unsigned i=0;i<MCID.getNumOperands();i++) { + // reference or immediate we may have to expand instructions. + for (unsigned i = 0; i < MCID.getNumOperands(); i++) { const MCOperandInfo &OpInfo = MCID.OpInfo[i]; - if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) || - (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) { + if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) + || (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) { MCOperand &Op = Inst.getOperand(i); if (Op.isImm()) { int MemOffset = Op.getImm(); if (MemOffset < -32768 || MemOffset > 32767) { - // Offset can't exceed 16bit value - expandMemInst(Inst,IDLoc,Instructions,MCID.mayLoad(),true); + // Offset can't exceed 16bit value. + expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true); return false; } } else if (Op.isExpr()) { const MCExpr *Expr = Op.getExpr(); - if (Expr->getKind() == MCExpr::SymbolRef){ + if (Expr->getKind() == MCExpr::SymbolRef) { const MCSymbolRefExpr *SR = - static_cast<const MCSymbolRefExpr*>(Expr); + static_cast<const MCSymbolRefExpr*>(Expr); if (SR->getKind() == MCSymbolRefExpr::VK_None) { - // Expand symbol - expandMemInst(Inst,IDLoc,Instructions,MCID.mayLoad(),false); + // Expand symbol. + expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false); return false; } + } else if (!isEvaluated(Expr)) { + expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false); + return false; } } } - } - } + } // for + } // if load/store if (needsExpansion(Inst)) expandInstruction(Inst, IDLoc, Instructions); @@ -453,30 +475,30 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, bool MipsAsmParser::needsExpansion(MCInst &Inst) { - switch(Inst.getOpcode()) { - case Mips::LoadImm32Reg: - case Mips::LoadAddr32Imm: - case Mips::LoadAddr32Reg: - return true; - default: - return false; + switch (Inst.getOpcode()) { + case Mips::LoadImm32Reg: + case Mips::LoadAddr32Imm: + case Mips::LoadAddr32Reg: + return true; + default: + return false; } } void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions){ - switch(Inst.getOpcode()) { - case Mips::LoadImm32Reg: - return expandLoadImm(Inst, IDLoc, Instructions); - case Mips::LoadAddr32Imm: - return expandLoadAddressImm(Inst,IDLoc,Instructions); - case Mips::LoadAddr32Reg: - return expandLoadAddressReg(Inst,IDLoc,Instructions); - } + SmallVectorImpl<MCInst> &Instructions) { + switch (Inst.getOpcode()) { + case Mips::LoadImm32Reg: + return expandLoadImm(Inst, IDLoc, Instructions); + case Mips::LoadAddr32Imm: + return expandLoadAddressImm(Inst, IDLoc, Instructions); + case Mips::LoadAddr32Reg: + return expandLoadAddressReg(Inst, IDLoc, Instructions); + } } void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions){ + SmallVectorImpl<MCInst> &Instructions) { MCInst tmpInst; const MCOperand &ImmOp = Inst.getOperand(1); assert(ImmOp.isImm() && "expected immediate operand kind"); @@ -485,26 +507,24 @@ void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc, int ImmValue = ImmOp.getImm(); tmpInst.setLoc(IDLoc); - if ( 0 <= ImmValue && ImmValue <= 65535) { - // for 0 <= j <= 65535. + if (0 <= ImmValue && ImmValue <= 65535) { + // For 0 <= j <= 65535. // li d,j => ori d,$zero,j tmpInst.setOpcode(Mips::ORi); tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg())); - tmpInst.addOperand( - MCOperand::CreateReg(Mips::ZERO)); + tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); tmpInst.addOperand(MCOperand::CreateImm(ImmValue)); Instructions.push_back(tmpInst); - } else if ( ImmValue < 0 && ImmValue >= -32768) { - // for -32768 <= j < 0. + } else if (ImmValue < 0 && ImmValue >= -32768) { + // For -32768 <= j < 0. // li d,j => addiu d,$zero,j tmpInst.setOpcode(Mips::ADDiu); tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg())); - tmpInst.addOperand( - MCOperand::CreateReg(Mips::ZERO)); + tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); tmpInst.addOperand(MCOperand::CreateImm(ImmValue)); Instructions.push_back(tmpInst); } else { - // for any other value of j that is representable as a 32-bit integer. + // For any other value of j that is representable as a 32-bit integer. // li d,j => lui d,hi16(j) // ori d,d,lo16(j) tmpInst.setOpcode(Mips::LUi); @@ -522,7 +542,7 @@ void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc, } void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions){ + SmallVectorImpl<MCInst> &Instructions) { MCInst tmpInst; const MCOperand &ImmOp = Inst.getOperand(2); assert(ImmOp.isImm() && "expected immediate operand kind"); @@ -531,19 +551,19 @@ void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc, const MCOperand &DstRegOp = Inst.getOperand(0); assert(DstRegOp.isReg() && "expected register operand kind"); int ImmValue = ImmOp.getImm(); - if ( -32768 <= ImmValue && ImmValue <= 65535) { - //for -32768 <= j <= 65535. - //la d,j(s) => addiu d,s,j + if (-32768 <= ImmValue && ImmValue <= 65535) { + // For -32768 <= j <= 65535. + // la d,j(s) => addiu d,s,j tmpInst.setOpcode(Mips::ADDiu); tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg())); tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg())); tmpInst.addOperand(MCOperand::CreateImm(ImmValue)); Instructions.push_back(tmpInst); } else { - //for any other value of j that is representable as a 32-bit integer. - //la d,j(s) => lui d,hi16(j) - // ori d,d,lo16(j) - // addu d,d,s + // For any other value of j that is representable as a 32-bit integer. + // la d,j(s) => lui d,hi16(j) + // ori d,d,lo16(j) + // addu d,d,s tmpInst.setOpcode(Mips::LUi); tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg())); tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16)); @@ -564,26 +584,25 @@ void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc, } void MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions){ + SmallVectorImpl<MCInst> &Instructions) { MCInst tmpInst; const MCOperand &ImmOp = Inst.getOperand(1); assert(ImmOp.isImm() && "expected immediate operand kind"); const MCOperand &RegOp = Inst.getOperand(0); assert(RegOp.isReg() && "expected register operand kind"); int ImmValue = ImmOp.getImm(); - if ( -32768 <= ImmValue && ImmValue <= 65535) { - //for -32768 <= j <= 65535. - //la d,j => addiu d,$zero,j + if (-32768 <= ImmValue && ImmValue <= 65535) { + // For -32768 <= j <= 65535. + // la d,j => addiu d,$zero,j tmpInst.setOpcode(Mips::ADDiu); tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg())); - tmpInst.addOperand( - MCOperand::CreateReg(Mips::ZERO)); + tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); tmpInst.addOperand(MCOperand::CreateImm(ImmValue)); Instructions.push_back(tmpInst); } else { - //for any other value of j that is representable as a 32-bit integer. - //la d,j => lui d,hi16(j) - // ori d,d,lo16(j) + // For any other value of j that is representable as a 32-bit integer. + // la d,j => lui d,hi16(j) + // ori d,d,lo16(j) tmpInst.setOpcode(Mips::LUi); tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg())); tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16)); @@ -598,40 +617,37 @@ void MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc, } void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions, - bool isLoad,bool isImmOpnd) { + SmallVectorImpl<MCInst> &Instructions, bool isLoad, bool isImmOpnd) { const MCSymbolRefExpr *SR; MCInst TempInst; - unsigned ImmOffset,HiOffset,LoOffset; + unsigned ImmOffset, HiOffset, LoOffset; const MCExpr *ExprOffset; unsigned TmpRegNum; - unsigned AtRegNum = getReg((isMips64()) ? Mips::CPU64RegsRegClassID: - Mips::CPURegsRegClassID, - getATReg()); - // 1st operand is either source or dst register + unsigned AtRegNum = getReg((isMips64()) ? Mips::CPU64RegsRegClassID + : Mips::CPURegsRegClassID, getATReg()); + // 1st operand is either the source or destination register. assert(Inst.getOperand(0).isReg() && "expected register operand kind"); unsigned RegOpNum = Inst.getOperand(0).getReg(); - // 2nd operand is base register + // 2nd operand is the base register. assert(Inst.getOperand(1).isReg() && "expected register operand kind"); unsigned BaseRegNum = Inst.getOperand(1).getReg(); - // 3rd operand is either immediate or expression + // 3rd operand is either an immediate or expression. if (isImmOpnd) { assert(Inst.getOperand(2).isImm() && "expected immediate operand kind"); ImmOffset = Inst.getOperand(2).getImm(); LoOffset = ImmOffset & 0x0000ffff; HiOffset = (ImmOffset & 0xffff0000) >> 16; - // If msb of LoOffset is 1(negative number) we must increment HiOffset + // If msb of LoOffset is 1(negative number) we must increment HiOffset. if (LoOffset & 0x8000) HiOffset++; - } - else + } else ExprOffset = Inst.getOperand(2).getExpr(); - // All instructions will have the same location + // All instructions will have the same location. TempInst.setLoc(IDLoc); // 1st instruction in expansion is LUi. For load instruction we can use // the dst register as a temporary if base and dst are different, - // but for stores we must use $at - TmpRegNum = (isLoad && (BaseRegNum != RegOpNum))?RegOpNum:AtRegNum; + // but for stores we must use $at. + TmpRegNum = (isLoad && (BaseRegNum != RegOpNum)) ? RegOpNum : AtRegNum; TempInst.setOpcode(Mips::LUi); TempInst.addOperand(MCOperand::CreateReg(TmpRegNum)); if (isImmOpnd) @@ -639,26 +655,28 @@ void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, else { if (ExprOffset->getKind() == MCExpr::SymbolRef) { SR = static_cast<const MCSymbolRefExpr*>(ExprOffset); - const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr:: - Create(SR->getSymbol().getName(), - MCSymbolRefExpr::VK_Mips_ABS_HI, - getContext()); + const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create( + SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI, + getContext()); + TempInst.addOperand(MCOperand::CreateExpr(HiExpr)); + } else { + const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi"); TempInst.addOperand(MCOperand::CreateExpr(HiExpr)); } } - // Add the instruction to the list + // Add the instruction to the list. Instructions.push_back(TempInst); - // and prepare TempInst for next instruction + // Prepare TempInst for next instruction. TempInst.clear(); - // which is add temp register to base + // Add temp register to base. TempInst.setOpcode(Mips::ADDu); TempInst.addOperand(MCOperand::CreateReg(TmpRegNum)); TempInst.addOperand(MCOperand::CreateReg(TmpRegNum)); TempInst.addOperand(MCOperand::CreateReg(BaseRegNum)); Instructions.push_back(TempInst); TempInst.clear(); - // and finaly, create original instruction with low part - // of offset and new base + // And finaly, create original instruction with low part + // of offset and new base. TempInst.setOpcode(Inst.getOpcode()); TempInst.addOperand(MCOperand::CreateReg(RegOpNum)); TempInst.addOperand(MCOperand::CreateReg(TmpRegNum)); @@ -666,10 +684,12 @@ void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, TempInst.addOperand(MCOperand::CreateImm(LoOffset)); else { if (ExprOffset->getKind() == MCExpr::SymbolRef) { - const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr:: - Create(SR->getSymbol().getName(), - MCSymbolRefExpr::VK_Mips_ABS_LO, - getContext()); + const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create( + SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO, + getContext()); + TempInst.addOperand(MCOperand::CreateExpr(LoExpr)); + } else { + const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo"); TempInst.addOperand(MCOperand::CreateExpr(LoExpr)); } } @@ -688,11 +708,12 @@ MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, MatchingInlineAsm); switch (MatchResult) { - default: break; + default: + break; case Match_Success: { - if (processInstruction(Inst,IDLoc,Instructions)) + if (processInstruction(Inst, IDLoc, Instructions)) return true; - for(unsigned i =0; i < Instructions.size(); i++) + for (unsigned i = 0; i < Instructions.size(); i++) Out.EmitInstruction(Instructions[i]); return false; } @@ -705,8 +726,9 @@ MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, if (ErrorInfo >= Operands.size()) return Error(IDLoc, "too few operands for instruction"); - ErrorLoc = ((MipsOperand*)Operands[ErrorInfo])->getStartLoc(); - if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc; + ErrorLoc = ((MipsOperand*) Operands[ErrorInfo])->getStartLoc(); + if (ErrorLoc == SMLoc()) + ErrorLoc = IDLoc; } return Error(ErrorLoc, "invalid operand for instruction"); @@ -757,10 +779,10 @@ int MipsAsmParser::matchCPURegisterName(StringRef Name) { .Case("t9", 25) .Default(-1); - // Although SGI documentation just cut out t0-t3 for n32/n64, + // Although SGI documentation just cuts out t0-t3 for n32/n64, // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7. - if (isMips64() && 8 <= CC && CC <= 11) + if (isMips64() && 8 <= CC && CC <= 11) CC += 4; if (CC == -1 && isMips64()) @@ -776,19 +798,23 @@ int MipsAsmParser::matchCPURegisterName(StringRef Name) { return CC; } + int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) { + if (Name.equals("fcc0")) + return Mips::FCC0; + int CC; CC = matchCPURegisterName(Name); if (CC != -1) - return matchRegisterByNumber(CC,is64BitReg?Mips::CPU64RegsRegClassID: - Mips::CPURegsRegClassID); + return matchRegisterByNumber(CC, is64BitReg ? Mips::CPU64RegsRegClassID + : Mips::CPURegsRegClassID); if (Name[0] == 'f') { StringRef NumString = Name.substr(1); unsigned IntVal; - if( NumString.getAsInteger(10, IntVal)) - return -1; // not integer + if (NumString.getAsInteger(10, IntVal)) + return -1; // This is not an integer. if (IntVal > 31) return -1; @@ -797,18 +823,19 @@ int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) { if (Format == FP_FORMAT_S || Format == FP_FORMAT_W) return getReg(Mips::FGR32RegClassID, IntVal); if (Format == FP_FORMAT_D) { - if(isFP64()) { + if (isFP64()) { return getReg(Mips::FGR64RegClassID, IntVal); } - // only even numbers available as register pairs - if (( IntVal > 31) || (IntVal%2 != 0)) + // Only even numbers available as register pairs. + if ((IntVal > 31) || (IntVal % 2 != 0)) return -1; - return getReg(Mips::AFGR64RegClassID, IntVal/2); + return getReg(Mips::AFGR64RegClassID, IntVal / 2); } } return -1; } + void MipsAsmParser::setDefaultFpFormat() { if (isMips64() || isFP64()) @@ -828,6 +855,7 @@ bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){ return IsDouble; } + void MipsAsmParser::setFpFormat(StringRef Format) { FpFormat = StringSwitch<FpFormatTy>(Format.lower()) @@ -850,7 +878,7 @@ int MipsAsmParser::getATReg() { return Options.getATRegNum(); } -unsigned MipsAsmParser::getReg(int RC,int RegNo) { +unsigned MipsAsmParser::getReg(int RC, int RegNo) { return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo); } @@ -871,14 +899,12 @@ int MipsAsmParser::tryParseRegister(bool is64BitReg) { RegNum = matchRegisterName(lowerCase, is64BitReg); } else if (Tok.is(AsmToken::Integer)) RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()), - is64BitReg ? Mips::CPU64RegsRegClassID - : Mips::CPURegsRegClassID); + is64BitReg ? Mips::CPU64RegsRegClassID : Mips::CPURegsRegClassID); return RegNum; } -bool MipsAsmParser:: - tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands, - bool is64BitReg){ +bool MipsAsmParser::tryParseRegisterOperand( + SmallVectorImpl<MCParsedAsmOperand*> &Operands, bool is64BitReg) { SMLoc S = Parser.getTok().getLoc(); int RegNo = -1; @@ -888,7 +914,7 @@ bool MipsAsmParser:: return true; Operands.push_back(MipsOperand::CreateReg(RegNo, S, - Parser.getTok().getLoc())); + Parser.getTok().getLoc())); Parser.Lex(); // Eat register token. return false; } @@ -911,19 +937,19 @@ bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands, Error(Parser.getTok().getLoc(), "unexpected token in operand"); return true; case AsmToken::Dollar: { - // parse register + // Parse the register. SMLoc S = Parser.getTok().getLoc(); Parser.Lex(); // Eat dollar token. - // parse register operand + // Parse the register operand. if (!tryParseRegisterOperand(Operands, isMips64())) { if (getLexer().is(AsmToken::LParen)) { - // check if it is indexed addressing operand + // Check if it is indexed addressing operand. Operands.push_back(MipsOperand::CreateToken("(", S)); - Parser.Lex(); // eat parenthesis + Parser.Lex(); // Eat the parenthesis. if (getLexer().isNot(AsmToken::Dollar)) return true; - Parser.Lex(); // eat dollar + Parser.Lex(); // Eat the dollar if (tryParseRegisterOperand(Operands, isMips64())) return true; @@ -936,7 +962,7 @@ bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands, } return false; } - // maybe it is a symbol reference + // Maybe it is a symbol reference. StringRef Identifier; if (Parser.parseIdentifier(Identifier)) return true; @@ -945,7 +971,7 @@ bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands, MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier); - // Otherwise create a symbol ref. + // Otherwise create a symbol reference. const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext()); @@ -954,16 +980,16 @@ bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands, } case AsmToken::Identifier: // Look for the existing symbol, we should check if - // we need to assigne the propper RegisterKind - if (searchSymbolAlias(Operands,MipsOperand::Kind_None)) - return false; - //else drop to expression parsing + // we need to assigne the propper RegisterKind. + if (searchSymbolAlias(Operands, MipsOperand::Kind_None)) + return false; + // Else drop to expression parsing. case AsmToken::LParen: case AsmToken::Minus: case AsmToken::Plus: case AsmToken::Integer: case AsmToken::String: { - // quoted label names + // Quoted label names. const MCExpr *IdVal; SMLoc S = Parser.getTok().getLoc(); if (getParser().parseExpression(IdVal)) @@ -973,9 +999,9 @@ bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands, return false; } case AsmToken::Percent: { - // it is a symbol reference or constant expression + // It is a symbol reference or constant expression. const MCExpr *IdVal; - SMLoc S = Parser.getTok().getLoc(); // start location of the operand + SMLoc S = Parser.getTok().getLoc(); // Start location of the operand. if (parseRelocOperand(IdVal)) return true; @@ -988,131 +1014,200 @@ bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands, return true; } -bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) { +const MCExpr* MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr, + StringRef RelocStr) { + const MCExpr *Res; + // Check the type of the expression. + if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) { + // It's a constant, evaluate lo or hi value. + if (RelocStr == "lo") { + short Val = MCE->getValue(); + Res = MCConstantExpr::Create(Val, getContext()); + } else if (RelocStr == "hi") { + int Val = MCE->getValue(); + int LoSign = Val & 0x8000; + Val = (Val & 0xffff0000) >> 16; + // Lower part is treated as a signed int, so if it is negative + // we must add 1 to the hi part to compensate. + if (LoSign) + Val++; + Res = MCConstantExpr::Create(Val, getContext()); + } else { + llvm_unreachable("Invalid RelocStr value"); + } + return Res; + } + + if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) { + // It's a symbol, create a symbolic expression from the symbol. + StringRef Symbol = MSRE->getSymbol().getName(); + MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr); + Res = MCSymbolRefExpr::Create(Symbol, VK, getContext()); + return Res; + } + + if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) { + const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr); + const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr); + Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext()); + return Res; + } - Parser.Lex(); // eat % token - const AsmToken &Tok = Parser.getTok(); // get next token, operation + if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) { + const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr); + Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext()); + return Res; + } + // Just return the original expression. + return Expr; +} + +bool MipsAsmParser::isEvaluated(const MCExpr *Expr) { + + switch (Expr->getKind()) { + case MCExpr::Constant: + return true; + case MCExpr::SymbolRef: + return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None); + case MCExpr::Binary: + if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) { + if (!isEvaluated(BE->getLHS())) + return false; + return isEvaluated(BE->getRHS()); + } + case MCExpr::Unary: + return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr()); + default: + return false; + } + return false; +} + +bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) { + Parser.Lex(); // Eat the % token. + const AsmToken &Tok = Parser.getTok(); // Get next token, operation. if (Tok.isNot(AsmToken::Identifier)) return true; std::string Str = Tok.getIdentifier().str(); - Parser.Lex(); // eat identifier - // now make expression from the rest of the operand + Parser.Lex(); // Eat the identifier. + // Now make an expression from the rest of the operand. const MCExpr *IdVal; SMLoc EndLoc; if (getLexer().getKind() == AsmToken::LParen) { while (1) { - Parser.Lex(); // eat '(' token + Parser.Lex(); // Eat the '(' token. if (getLexer().getKind() == AsmToken::Percent) { - Parser.Lex(); // eat % token + Parser.Lex(); // Eat the % token. const AsmToken &nextTok = Parser.getTok(); if (nextTok.isNot(AsmToken::Identifier)) return true; Str += "(%"; Str += nextTok.getIdentifier(); - Parser.Lex(); // eat identifier + Parser.Lex(); // Eat the identifier. if (getLexer().getKind() != AsmToken::LParen) return true; } else break; } - if (getParser().parseParenExpression(IdVal,EndLoc)) + if (getParser().parseParenExpression(IdVal, EndLoc)) return true; while (getLexer().getKind() == AsmToken::RParen) - Parser.Lex(); // eat ')' token + Parser.Lex(); // Eat the ')' token. } else - return true; // parenthesis must follow reloc operand - - // Check the type of the expression - if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) { - // It's a constant, evaluate lo or hi value - if (Str == "lo") { - short Val = MCE->getValue(); - Res = MCConstantExpr::Create(Val, getContext()); - } else if (Str == "hi") { - int Val = MCE->getValue(); - int LoSign = Val & 0x8000; - Val = (Val & 0xffff0000) >> 16; - // Lower part is treated as a signed int, so if it is negative - // we must add 1 to the hi part to compensate - if (LoSign) - Val++; - Res = MCConstantExpr::Create(Val, getContext()); - } - return false; - } + return true; // Parenthesis must follow the relocation operand. - if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) { - // It's a symbol, create symbolic expression from symbol - StringRef Symbol = MSRE->getSymbol().getName(); - MCSymbolRefExpr::VariantKind VK = getVariantKind(Str); - Res = MCSymbolRefExpr::Create(Symbol,VK,getContext()); - return false; - } - return true; + Res = evaluateRelocExpr(IdVal, Str); + return false; } bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { - StartLoc = Parser.getTok().getLoc(); RegNo = tryParseRegister(isMips64()); EndLoc = Parser.getTok().getLoc(); - return (RegNo == (unsigned)-1); + return (RegNo == (unsigned) -1); } -bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) { - +bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) { SMLoc S; + bool Result = true; - switch(getLexer().getKind()) { + while (getLexer().getKind() == AsmToken::LParen) + Parser.Lex(); + + switch (getLexer().getKind()) { default: return true; case AsmToken::Identifier: + case AsmToken::LParen: case AsmToken::Integer: case AsmToken::Minus: case AsmToken::Plus: - return (getParser().parseExpression(Res)); + if (isParenExpr) + Result = getParser().parseParenExpression(Res, S); + else + Result = (getParser().parseExpression(Res)); + while (getLexer().getKind() == AsmToken::RParen) + Parser.Lex(); + break; case AsmToken::Percent: - return parseRelocOperand(Res); - case AsmToken::LParen: - return false; // it's probably assuming 0 + Result = parseRelocOperand(Res); } - return true; + return Result; } MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand( - SmallVectorImpl<MCParsedAsmOperand*>&Operands) { + SmallVectorImpl<MCParsedAsmOperand*>&Operands) { const MCExpr *IdVal = 0; SMLoc S; - // first operand is the offset + bool isParenExpr = false; + // First operand is the offset. S = Parser.getTok().getLoc(); - if (parseMemOffset(IdVal)) - return MatchOperand_ParseFail; + if (getLexer().getKind() == AsmToken::LParen) { + Parser.Lex(); + isParenExpr = true; + } - const AsmToken &Tok = Parser.getTok(); // get next token - if (Tok.isNot(AsmToken::LParen)) { - MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]); - if (Mnemonic->getToken() == "la") { - SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() -1); - Operands.push_back(MipsOperand::CreateImm(IdVal, S, E)); - return MatchOperand_Success; + if (getLexer().getKind() != AsmToken::Dollar) { + if (parseMemOffset(IdVal, isParenExpr)) + return MatchOperand_ParseFail; + + const AsmToken &Tok = Parser.getTok(); // Get the next token. + if (Tok.isNot(AsmToken::LParen)) { + MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]); + if (Mnemonic->getToken() == "la") { + SMLoc E = SMLoc::getFromPointer( + Parser.getTok().getLoc().getPointer() - 1); + Operands.push_back(MipsOperand::CreateImm(IdVal, S, E)); + return MatchOperand_Success; + } + if (Tok.is(AsmToken::EndOfStatement)) { + SMLoc E = SMLoc::getFromPointer( + Parser.getTok().getLoc().getPointer() - 1); + + // Zero register assumed, add a memory operand with ZERO as its base. + Operands.push_back(MipsOperand::CreateMem(isMips64() ? Mips::ZERO_64 + : Mips::ZERO, + IdVal, S, E)); + return MatchOperand_Success; + } + Error(Parser.getTok().getLoc(), "'(' expected"); + return MatchOperand_ParseFail; } - Error(Parser.getTok().getLoc(), "'(' expected"); - return MatchOperand_ParseFail; - } - Parser.Lex(); // Eat '(' token. + Parser.Lex(); // Eat the '(' token. + } - const AsmToken &Tok1 = Parser.getTok(); // get next token + const AsmToken &Tok1 = Parser.getTok(); // Get next token if (Tok1.is(AsmToken::Dollar)) { - Parser.Lex(); // Eat '$' token. + Parser.Lex(); // Eat the '$' token. if (tryParseRegisterOperand(Operands, isMips64())) { Error(Parser.getTok().getLoc(), "unexpected token in operand"); return MatchOperand_ParseFail; @@ -1123,7 +1218,7 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand( return MatchOperand_ParseFail; } - const AsmToken &Tok2 = Parser.getTok(); // get next token + const AsmToken &Tok2 = Parser.getTok(); // Get next token. if (Tok2.isNot(AsmToken::RParen)) { Error(Parser.getTok().getLoc(), "')' expected"); return MatchOperand_ParseFail; @@ -1131,17 +1226,26 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand( SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - Parser.Lex(); // Eat ')' token. + Parser.Lex(); // Eat the ')' token. if (IdVal == 0) IdVal = MCConstantExpr::Create(0, getContext()); - // now replace register operand with the mem operand + // Replace the register operand with the memory operand. MipsOperand* op = static_cast<MipsOperand*>(Operands.back()); int RegNo = op->getReg(); - // remove register from operands + // Remove the register from the operands. Operands.pop_back(); - // and add memory operand + // Add the memory operand. + if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) { + int64_t Imm; + if (IdVal->EvaluateAsAbsolute(Imm)) + IdVal = MCConstantExpr::Create(Imm, getContext()); + else if (BE->getLHS()->getKind() != MCExpr::SymbolRef) + IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(), + getContext()); + } + Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E)); delete op; return MatchOperand_Success; @@ -1153,17 +1257,17 @@ MipsAsmParser::parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { if (!isMips64()) return MatchOperand_NoMatch; if (getLexer().getKind() == AsmToken::Identifier) { - if (searchSymbolAlias(Operands,MipsOperand::Kind_CPU64Regs)) + if (searchSymbolAlias(Operands, MipsOperand::Kind_CPU64Regs)) return MatchOperand_Success; return MatchOperand_NoMatch; } - // if the first token is not '$' we have an error + // If the first token is not '$', we have an error. if (Parser.getTok().isNot(AsmToken::Dollar)) return MatchOperand_NoMatch; Parser.Lex(); // Eat $ - if(!tryParseRegisterOperand(Operands, true)) { - // set the proper register kind + if (!tryParseRegisterOperand(Operands, true)) { + // Set the proper register kind. MipsOperand* op = static_cast<MipsOperand*>(Operands.back()); op->setRegKind(MipsOperand::Kind_CPU64Regs); return MatchOperand_Success; @@ -1171,9 +1275,8 @@ MipsAsmParser::parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { return MatchOperand_NoMatch; } -bool MipsAsmParser:: -searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand*> &Operands, - unsigned RegisterKind) { +bool MipsAsmParser::searchSymbolAlias( + SmallVectorImpl<MCParsedAsmOperand*> &Operands, unsigned RegisterKind) { MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier()); if (Sym) { @@ -1187,13 +1290,13 @@ searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand*> &Operands, const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Expr); const StringRef DefSymbol = Ref->getSymbol().getName(); if (DefSymbol.startswith("$")) { - // Lookup for the register with corresponding name - int RegNum = matchRegisterName(DefSymbol.substr(1),isMips64()); + // Lookup for the register with the corresponding name. + int RegNum = matchRegisterName(DefSymbol.substr(1), isMips64()); if (RegNum > -1) { Parser.Lex(); - MipsOperand *op = MipsOperand::CreateReg(RegNum,S, - Parser.getTok().getLoc()); - op->setRegKind((MipsOperand::RegisterKind)RegisterKind); + MipsOperand *op = MipsOperand::CreateReg(RegNum, S, + Parser.getTok().getLoc()); + op->setRegKind((MipsOperand::RegisterKind) RegisterKind); Operands.push_back(op); return true; } @@ -1201,29 +1304,30 @@ searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand*> &Operands, } else if (Expr->getKind() == MCExpr::Constant) { Parser.Lex(); const MCConstantExpr *Const = static_cast<const MCConstantExpr*>(Expr); - MipsOperand *op = MipsOperand::CreateImm(Const,S, - Parser.getTok().getLoc()); + MipsOperand *op = MipsOperand::CreateImm(Const, S, + Parser.getTok().getLoc()); Operands.push_back(op); return true; } } return false; } + MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { if (getLexer().getKind() == AsmToken::Identifier) { - if (searchSymbolAlias(Operands,MipsOperand::Kind_CPURegs)) + if (searchSymbolAlias(Operands, MipsOperand::Kind_CPURegs)) return MatchOperand_Success; return MatchOperand_NoMatch; } - // if the first token is not '$' we have an error + // If the first token is not '$' we have an error. if (Parser.getTok().isNot(AsmToken::Dollar)) return MatchOperand_NoMatch; Parser.Lex(); // Eat $ - if(!tryParseRegisterOperand(Operands, false)) { - // set the propper register kind + if (!tryParseRegisterOperand(Operands, false)) { + // Set the proper register kind. MipsOperand* op = static_cast<MipsOperand*>(Operands.back()); op->setRegKind(MipsOperand::Kind_CPURegs); return MatchOperand_Success; @@ -1237,87 +1341,88 @@ MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { if (isMips64()) return MatchOperand_NoMatch; - // if the first token is not '$' we have error + // If the first token is not '$' we have error. if (Parser.getTok().isNot(AsmToken::Dollar)) return MatchOperand_NoMatch; SMLoc S = Parser.getTok().getLoc(); - Parser.Lex(); // Eat $ + Parser.Lex(); // Eat the '$'. - const AsmToken &Tok = Parser.getTok(); // get next token + const AsmToken &Tok = Parser.getTok(); // Get the next token. if (Tok.isNot(AsmToken::Integer)) return MatchOperand_NoMatch; unsigned RegNum = Tok.getIntVal(); - // at the moment only hwreg29 is supported + // At the moment only hwreg29 is supported. if (RegNum != 29) return MatchOperand_ParseFail; MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29, S, - Parser.getTok().getLoc()); + Parser.getTok().getLoc()); op->setRegKind(MipsOperand::Kind_HWRegs); Operands.push_back(op); - Parser.Lex(); // Eat reg number + Parser.Lex(); // Eat the register number. return MatchOperand_Success; } MipsAsmParser::OperandMatchResultTy -MipsAsmParser::parseHW64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { +MipsAsmParser::parseHW64Regs( + SmallVectorImpl<MCParsedAsmOperand*> &Operands) { if (!isMips64()) return MatchOperand_NoMatch; - //if the first token is not '$' we have error + // If the first token is not '$' we have an error. if (Parser.getTok().isNot(AsmToken::Dollar)) return MatchOperand_NoMatch; SMLoc S = Parser.getTok().getLoc(); Parser.Lex(); // Eat $ - const AsmToken &Tok = Parser.getTok(); // get next token + const AsmToken &Tok = Parser.getTok(); // Get the next token. if (Tok.isNot(AsmToken::Integer)) return MatchOperand_NoMatch; unsigned RegNum = Tok.getIntVal(); - // at the moment only hwreg29 is supported + // At the moment only hwreg29 is supported. if (RegNum != 29) return MatchOperand_ParseFail; MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29_64, S, - Parser.getTok().getLoc()); + Parser.getTok().getLoc()); op->setRegKind(MipsOperand::Kind_HW64Regs); Operands.push_back(op); - Parser.Lex(); // Eat reg number + Parser.Lex(); // Eat the register number. return MatchOperand_Success; } MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { unsigned RegNum; - //if the first token is not '$' we have error + // If the first token is not '$' we have an error. if (Parser.getTok().isNot(AsmToken::Dollar)) return MatchOperand_NoMatch; SMLoc S = Parser.getTok().getLoc(); - Parser.Lex(); // Eat $ + Parser.Lex(); // Eat the '$' - const AsmToken &Tok = Parser.getTok(); // get next token + const AsmToken &Tok = Parser.getTok(); // Get next token. if (Tok.is(AsmToken::Integer)) { RegNum = Tok.getIntVal(); - // at the moment only fcc0 is supported + // At the moment only fcc0 is supported. if (RegNum != 0) return MatchOperand_ParseFail; } else if (Tok.is(AsmToken::Identifier)) { - // at the moment only fcc0 is supported + // At the moment only fcc0 is supported. if (Tok.getIdentifier() != "fcc0") return MatchOperand_ParseFail; } else return MatchOperand_NoMatch; MipsOperand *op = MipsOperand::CreateReg(Mips::FCC0, S, - Parser.getTok().getLoc()); + Parser.getTok().getLoc()); op->setRegKind(MipsOperand::Kind_CCRRegs); Operands.push_back(op); - Parser.Lex(); // Eat reg number + Parser.Lex(); // Eat the register number. return MatchOperand_Success; } @@ -1349,23 +1454,23 @@ MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) { static int ConvertCcString(StringRef CondString) { int CC = StringSwitch<unsigned>(CondString) - .Case(".f", 0) - .Case(".un", 1) - .Case(".eq", 2) - .Case(".ueq", 3) - .Case(".olt", 4) - .Case(".ult", 5) - .Case(".ole", 6) - .Case(".ule", 7) - .Case(".sf", 8) - .Case(".ngle", 9) - .Case(".seq", 10) - .Case(".ngl", 11) - .Case(".lt", 12) - .Case(".nge", 13) - .Case(".le", 14) - .Case(".ngt", 15) - .Default(-1); + .Case(".f", 0) + .Case(".un", 1) + .Case(".eq", 2) + .Case(".ueq", 3) + .Case(".olt", 4) + .Case(".ult", 5) + .Case(".ole", 6) + .Case(".ule", 7) + .Case(".sf", 8) + .Case(".ngle", 9) + .Case(".seq", 10) + .Case(".ngl", 11) + .Case(".lt", 12) + .Case(".nge", 13) + .Case(".le", 14) + .Case(".ngt", 15) + .Default(-1); return CC; } @@ -1373,16 +1478,16 @@ static int ConvertCcString(StringRef CondString) { bool MipsAsmParser:: parseMathOperation(StringRef Name, SMLoc NameLoc, SmallVectorImpl<MCParsedAsmOperand*> &Operands) { - // split the format + // Split the format. size_t Start = Name.find('.'), Next = Name.rfind('.'); StringRef Format1 = Name.slice(Start, Next); - // and add the first format to the operands + // Add the first format to the operands. Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc)); - // now for the second format + // Now for the second format. StringRef Format2 = Name.slice(Next, StringRef::npos); Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc)); - // set the format for the first register + // Set the format for the first register. setFpFormat(Format1); // Read the remaining operands. @@ -1398,11 +1503,10 @@ parseMathOperation(StringRef Name, SMLoc NameLoc, SMLoc Loc = getLexer().getLoc(); Parser.eatToEndOfStatement(); return Error(Loc, "unexpected token in argument list"); - } - Parser.Lex(); // Eat the comma. + Parser.Lex(); // Eat the comma. - //set the format for the first register + // Set the format for the first register setFpFormat(Format2); // Parse and remember the operand. @@ -1419,7 +1523,7 @@ parseMathOperation(StringRef Name, SMLoc NameLoc, return Error(Loc, "unexpected token in argument list"); } - Parser.Lex(); // Consume the EndOfStatement + Parser.Lex(); // Consume the EndOfStatement. return false; } @@ -1427,13 +1531,12 @@ bool MipsAsmParser:: ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, SmallVectorImpl<MCParsedAsmOperand*> &Operands) { StringRef Mnemonic; - // floating point instructions: should register be treated as double? + // Floating point instructions: Should the register be treated as a double? if (requestsDoubleOperand(Name)) { setFpFormat(FP_FORMAT_D); - Operands.push_back(MipsOperand::CreateToken(Name, NameLoc)); - Mnemonic = Name; - } - else { + Operands.push_back(MipsOperand::CreateToken(Name, NameLoc)); + Mnemonic = Name; + } else { setDefaultFpFormat(); // Create the leading tokens for the mnemonic, split by '.' characters. size_t Start = 0, Next = Name.find('.'); @@ -1442,30 +1545,30 @@ ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc)); if (Next != StringRef::npos) { - // there is a format token in mnemonic - // StringRef Rest = Name.slice(Next, StringRef::npos); - size_t Dot = Name.find('.', Next+1); + // There is a format token in mnemonic. + size_t Dot = Name.find('.', Next + 1); StringRef Format = Name.slice(Next, Dot); - if (Dot == StringRef::npos) //only one '.' in a string, it's a format + if (Dot == StringRef::npos) // Only one '.' in a string, it's a format. Operands.push_back(MipsOperand::CreateToken(Format, NameLoc)); else { - if (Name.startswith("c.")){ - // floating point compare, add '.' and immediate represent for cc + if (Name.startswith("c.")) { + // Floating point compare, add '.' and immediate represent for cc. Operands.push_back(MipsOperand::CreateToken(".", NameLoc)); int Cc = ConvertCcString(Format); if (Cc == -1) { return Error(NameLoc, "Invalid conditional code"); } SMLoc E = SMLoc::getFromPointer( - Parser.getTok().getLoc().getPointer() -1 ); - Operands.push_back(MipsOperand::CreateImm( - MCConstantExpr::Create(Cc, getContext()), NameLoc, E)); + Parser.getTok().getLoc().getPointer() - 1); + Operands.push_back( + MipsOperand::CreateImm(MCConstantExpr::Create(Cc, getContext()), + NameLoc, E)); } else { // trunc, ceil, floor ... return parseMathOperation(Name, NameLoc, Operands); } - // the rest is a format + // The rest is a format. Format = Name.slice(Dot, StringRef::npos); Operands.push_back(MipsOperand::CreateToken(Format, NameLoc)); } @@ -1483,8 +1586,8 @@ ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, return Error(Loc, "unexpected token in argument list"); } - while (getLexer().is(AsmToken::Comma) ) { - Parser.Lex(); // Eat the comma. + while (getLexer().is(AsmToken::Comma)) { + Parser.Lex(); // Eat the comma. // Parse and remember the operand. if (ParseOperand(Operands, Name)) { @@ -1501,48 +1604,47 @@ ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, return Error(Loc, "unexpected token in argument list"); } - Parser.Lex(); // Consume the EndOfStatement + Parser.Lex(); // Consume the EndOfStatement. return false; } bool MipsAsmParser::reportParseError(StringRef ErrorMsg) { - SMLoc Loc = getLexer().getLoc(); - Parser.eatToEndOfStatement(); - return Error(Loc, ErrorMsg); + SMLoc Loc = getLexer().getLoc(); + Parser.eatToEndOfStatement(); + return Error(Loc, ErrorMsg); } bool MipsAsmParser::parseSetNoAtDirective() { - // Line should look like: - // .set noat - // set at reg to 0 + // Line should look like: ".set noat". + // set at reg to 0. Options.setATReg(0); // eat noat Parser.Lex(); - // If this is not the end of the statement, report error + // If this is not the end of the statement, report an error. if (getLexer().isNot(AsmToken::EndOfStatement)) { reportParseError("unexpected token in statement"); return false; } - Parser.Lex(); // Consume the EndOfStatement + Parser.Lex(); // Consume the EndOfStatement. return false; } + bool MipsAsmParser::parseSetAtDirective() { - // line can be - // .set at - defaults to $1 + // Line can be .set at - defaults to $1 // or .set at=$reg int AtRegNo; getParser().Lex(); if (getLexer().is(AsmToken::EndOfStatement)) { Options.setATReg(1); - Parser.Lex(); // Consume the EndOfStatement + Parser.Lex(); // Consume the EndOfStatement. return false; } else if (getLexer().is(AsmToken::Equal)) { - getParser().Lex(); // eat '=' + getParser().Lex(); // Eat the '='. if (getLexer().isNot(AsmToken::Dollar)) { reportParseError("unexpected token in statement"); return false; } - Parser.Lex(); // Eat '$' + Parser.Lex(); // Eat the '$'. const AsmToken &Reg = Parser.getTok(); if (Reg.is(AsmToken::Identifier)) { AtRegNo = matchCPURegisterName(Reg.getIdentifier()); @@ -1553,7 +1655,7 @@ bool MipsAsmParser::parseSetAtDirective() { return false; } - if ( AtRegNo < 1 || AtRegNo > 31) { + if (AtRegNo < 1 || AtRegNo > 31) { reportParseError("unexpected token in statement"); return false; } @@ -1562,13 +1664,13 @@ bool MipsAsmParser::parseSetAtDirective() { reportParseError("unexpected token in statement"); return false; } - getParser().Lex(); // Eat reg + getParser().Lex(); // Eat the register. if (getLexer().isNot(AsmToken::EndOfStatement)) { reportParseError("unexpected token in statement"); return false; - } - Parser.Lex(); // Consume the EndOfStatement + } + Parser.Lex(); // Consume the EndOfStatement. return false; } else { reportParseError("unexpected token in statement"); @@ -1578,43 +1680,43 @@ bool MipsAsmParser::parseSetAtDirective() { bool MipsAsmParser::parseSetReorderDirective() { Parser.Lex(); - // If this is not the end of the statement, report error + // If this is not the end of the statement, report an error. if (getLexer().isNot(AsmToken::EndOfStatement)) { reportParseError("unexpected token in statement"); return false; } Options.setReorder(); - Parser.Lex(); // Consume the EndOfStatement + Parser.Lex(); // Consume the EndOfStatement. return false; } bool MipsAsmParser::parseSetNoReorderDirective() { - Parser.Lex(); - // if this is not the end of the statement, report error - if (getLexer().isNot(AsmToken::EndOfStatement)) { - reportParseError("unexpected token in statement"); - return false; - } - Options.setNoreorder(); - Parser.Lex(); // Consume the EndOfStatement + Parser.Lex(); + // If this is not the end of the statement, report an error. + if (getLexer().isNot(AsmToken::EndOfStatement)) { + reportParseError("unexpected token in statement"); return false; + } + Options.setNoreorder(); + Parser.Lex(); // Consume the EndOfStatement. + return false; } bool MipsAsmParser::parseSetMacroDirective() { Parser.Lex(); - // if this is not the end of the statement, report error + // If this is not the end of the statement, report an error. if (getLexer().isNot(AsmToken::EndOfStatement)) { reportParseError("unexpected token in statement"); return false; } Options.setMacro(); - Parser.Lex(); // Consume the EndOfStatement + Parser.Lex(); // Consume the EndOfStatement. return false; } bool MipsAsmParser::parseSetNoMacroDirective() { Parser.Lex(); - // if this is not the end of the statement, report error + // If this is not the end of the statement, report an error. if (getLexer().isNot(AsmToken::EndOfStatement)) { reportParseError("`noreorder' must be set before `nomacro'"); return false; @@ -1624,7 +1726,7 @@ bool MipsAsmParser::parseSetNoMacroDirective() { return false; } Options.setNomacro(); - Parser.Lex(); // Consume the EndOfStatement + Parser.Lex(); // Consume the EndOfStatement. return false; } @@ -1637,24 +1739,24 @@ bool MipsAsmParser::parseSetAssignment() { if (getLexer().isNot(AsmToken::Comma)) return reportParseError("unexpected token in .set directive"); - Lex(); //eat comma + Lex(); // Eat comma if (Parser.parseExpression(Value)) reportParseError("expected valid expression after comma"); - // check if the Name already exists as a symbol + // Check if the Name already exists as a symbol. MCSymbol *Sym = getContext().LookupSymbol(Name); - if (Sym) { + if (Sym) return reportParseError("symbol already defined"); - } Sym = getContext().GetOrCreateSymbol(Name); Sym->setVariableValue(Value); return false; } + bool MipsAsmParser::parseDirectiveSet() { - // get next token + // Get the next token. const AsmToken &Tok = Parser.getTok(); if (Tok.getString() == "noat") { @@ -1670,15 +1772,15 @@ bool MipsAsmParser::parseDirectiveSet() { } else if (Tok.getString() == "nomacro") { return parseSetNoMacroDirective(); } else if (Tok.getString() == "nomips16") { - // ignore this directive for now + // Ignore this directive for now. Parser.eatToEndOfStatement(); return false; } else if (Tok.getString() == "nomicromips") { - // ignore this directive for now + // Ignore this directive for now. Parser.eatToEndOfStatement(); return false; } else { - // it is just an identifier, look for assignment + // It is just an identifier, look for an assignment. parseSetAssignment(); return false; } @@ -1715,20 +1817,20 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { StringRef IDVal = DirectiveID.getString(); - if ( IDVal == ".ent") { - // ignore this directive for now + if (IDVal == ".ent") { + // Ignore this directive for now. Parser.Lex(); return false; } if (IDVal == ".end") { - // ignore this directive for now + // Ignore this directive for now. Parser.Lex(); return false; } if (IDVal == ".frame") { - // ignore this directive for now + // Ignore this directive for now. Parser.eatToEndOfStatement(); return false; } @@ -1738,19 +1840,19 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { } if (IDVal == ".fmask") { - // ignore this directive for now + // Ignore this directive for now. Parser.eatToEndOfStatement(); return false; } if (IDVal == ".mask") { - // ignore this directive for now + // Ignore this directive for now. Parser.eatToEndOfStatement(); return false; } if (IDVal == ".gpword") { - // ignore this directive for now + // Ignore this directive for now. Parser.eatToEndOfStatement(); return false; } diff --git a/lib/Target/Mips/CMakeLists.txt b/lib/Target/Mips/CMakeLists.txt index cf8bb18..78a9f70 100644 --- a/lib/Target/Mips/CMakeLists.txt +++ b/lib/Target/Mips/CMakeLists.txt @@ -32,6 +32,8 @@ add_llvm_target(MipsCodeGen MipsLongBranch.cpp MipsMCInstLower.cpp MipsMachineFunction.cpp + MipsModuleISelDAGToDAG.cpp + MipsOs16.cpp MipsRegisterInfo.cpp MipsSEFrameLowering.cpp MipsSEInstrInfo.cpp diff --git a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp index 59e49d8..0dba33a 100644 --- a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -143,6 +143,16 @@ static DecodeStatus DecodeACRegsDSPRegisterClass(MCInst &Inst, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeHIRegsDSPRegisterClass(MCInst &Inst, + unsigned RegNo, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeLORegsDSPRegisterClass(MCInst &Inst, + unsigned RegNo, + uint64_t Address, + const void *Decoder); + static DecodeStatus DecodeBranchTarget(MCInst &Inst, unsigned Offset, uint64_t Address, @@ -496,6 +506,30 @@ static DecodeStatus DecodeACRegsDSPRegisterClass(MCInst &Inst, return MCDisassembler::Success; } +static DecodeStatus DecodeHIRegsDSPRegisterClass(MCInst &Inst, + unsigned RegNo, + uint64_t Address, + const void *Decoder) { + if (RegNo >= 4) + return MCDisassembler::Fail; + + unsigned Reg = getReg(Decoder, Mips::HIRegsDSPRegClassID, RegNo); + Inst.addOperand(MCOperand::CreateReg(Reg)); + return MCDisassembler::Success; +} + +static DecodeStatus DecodeLORegsDSPRegisterClass(MCInst &Inst, + unsigned RegNo, + uint64_t Address, + const void *Decoder) { + if (RegNo >= 4) + return MCDisassembler::Fail; + + unsigned Reg = getReg(Decoder, Mips::LORegsDSPRegClassID, RegNo); + Inst.addOperand(MCOperand::CreateReg(Reg)); + return MCDisassembler::Success; +} + static DecodeStatus DecodeBranchTarget(MCInst &Inst, unsigned Offset, uint64_t Address, diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp index e198a7c..9460731 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -27,6 +27,9 @@ #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/raw_ostream.h" +#define GET_INSTRMAP_INFO +#include "MipsGenInstrInfo.inc" + using namespace llvm; namespace { @@ -35,12 +38,13 @@ class MipsMCCodeEmitter : public MCCodeEmitter { void operator=(const MipsMCCodeEmitter &) LLVM_DELETED_FUNCTION; const MCInstrInfo &MCII; MCContext &Ctx; + const MCSubtargetInfo &STI; bool IsLittleEndian; public: MipsMCCodeEmitter(const MCInstrInfo &mcii, MCContext &Ctx_, const MCSubtargetInfo &sti, bool IsLittle) : - MCII(mcii), Ctx(Ctx_), IsLittleEndian(IsLittle) {} + MCII(mcii), Ctx(Ctx_), STI (sti), IsLittleEndian(IsLittle) {} ~MipsMCCodeEmitter() {} @@ -88,6 +92,9 @@ public: unsigned getSizeInsEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups) const; + unsigned + getExprOpValue(const MCExpr *Expr,SmallVectorImpl<MCFixup> &Fixups) const; + }; // class MipsMCCodeEmitter } // namespace @@ -141,6 +148,15 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) && !Binary) llvm_unreachable("unimplemented opcode in EncodeInstruction()"); + if (STI.getFeatureBits() & Mips::FeatureMicroMips) { + int NewOpcode = Mips::Std2MicroMips (Opcode, Mips::Arch_micromips); + if (NewOpcode != -1) { + Opcode = NewOpcode; + TmpInst.setOpcode (NewOpcode); + Binary = getBinaryCodeForInstr(TmpInst, Fixups); + } + } + const MCInstrDesc &Desc = MCII.get(TmpInst.getOpcode()); // Get byte count of instruction @@ -192,35 +208,24 @@ getJumpTargetOpValue(const MCInst &MI, unsigned OpNo, return 0; } -/// getMachineOpValue - Return binary encoding of operand. If the machine -/// operand requires relocation, record the relocation and return zero. unsigned MipsMCCodeEmitter:: -getMachineOpValue(const MCInst &MI, const MCOperand &MO, - SmallVectorImpl<MCFixup> &Fixups) const { - if (MO.isReg()) { - unsigned Reg = MO.getReg(); - unsigned RegNo = Ctx.getRegisterInfo().getEncodingValue(Reg); - return RegNo; - } else if (MO.isImm()) { - return static_cast<unsigned>(MO.getImm()); - } else if (MO.isFPImm()) { - return static_cast<unsigned>(APFloat(MO.getFPImm()) - .bitcastToAPInt().getHiBits(32).getLimitedValue()); - } +getExprOpValue(const MCExpr *Expr,SmallVectorImpl<MCFixup> &Fixups) const { + int64_t Res; - // MO must be an Expr. - assert(MO.isExpr()); + if (Expr->EvaluateAsAbsolute(Res)) + return Res; - const MCExpr *Expr = MO.getExpr(); MCExpr::ExprKind Kind = Expr->getKind(); + if (Kind == MCExpr::Constant) { + return cast<MCConstantExpr>(Expr)->getValue(); + } if (Kind == MCExpr::Binary) { - Expr = static_cast<const MCBinaryExpr*>(Expr)->getLHS(); - Kind = Expr->getKind(); + unsigned Res = getExprOpValue(cast<MCBinaryExpr>(Expr)->getLHS(), Fixups); + Res += getExprOpValue(cast<MCBinaryExpr>(Expr)->getRHS(), Fixups); + return Res; } - - assert (Kind == MCExpr::SymbolRef); - + if (Kind == MCExpr::SymbolRef) { Mips::Fixups FixupKind = Mips::Fixups(0); switch(cast<MCSymbolRefExpr>(Expr)->getKind()) { @@ -300,12 +305,32 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO, break; } // switch - Fixups.push_back(MCFixup::Create(0, MO.getExpr(), MCFixupKind(FixupKind))); - - // All of the information is in the fixup. + Fixups.push_back(MCFixup::Create(0, Expr, MCFixupKind(FixupKind))); + return 0; + } return 0; } +/// getMachineOpValue - Return binary encoding of operand. If the machine +/// operand requires relocation, record the relocation and return zero. +unsigned MipsMCCodeEmitter:: +getMachineOpValue(const MCInst &MI, const MCOperand &MO, + SmallVectorImpl<MCFixup> &Fixups) const { + if (MO.isReg()) { + unsigned Reg = MO.getReg(); + unsigned RegNo = Ctx.getRegisterInfo().getEncodingValue(Reg); + return RegNo; + } else if (MO.isImm()) { + return static_cast<unsigned>(MO.getImm()); + } else if (MO.isFPImm()) { + return static_cast<unsigned>(APFloat(MO.getFPImm()) + .bitcastToAPInt().getHiBits(32).getLimitedValue()); + } + // MO must be an Expr. + assert(MO.isExpr()); + return getExprOpValue(MO.getExpr(),Fixups); +} + /// getMemEncoding - Return binary encoding of memory related operand. /// If the offset operand requires relocation, record the relocation. unsigned diff --git a/lib/Target/Mips/MicroMipsInstrFormats.td b/lib/Target/Mips/MicroMipsInstrFormats.td new file mode 100644 index 0000000..665b4d2 --- /dev/null +++ b/lib/Target/Mips/MicroMipsInstrFormats.td @@ -0,0 +1,112 @@ +class MMArch { + string Arch = "micromips"; + list<dag> Pattern = []; +} + +class ADD_FM_MM<bits<6> op, bits<10> funct> : MMArch { + bits<5> rt; + bits<5> rs; + bits<5> rd; + + bits<32> Inst; + + let Inst{31-26} = op; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-11} = rd; + let Inst{10} = 0; + let Inst{9-0} = funct; +} + +class ADDI_FM_MM<bits<6> op> : MMArch { + bits<5> rs; + bits<5> rt; + bits<16> imm16; + + bits<32> Inst; + + let Inst{31-26} = op; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-0} = imm16; +} + +class SLTI_FM_MM<bits<6> op> : MMArch { + bits<5> rt; + bits<5> rs; + bits<16> imm16; + + bits<32> Inst; + + let Inst{31-26} = op; + let Inst{25-21} = rs; + let Inst{20-16} = rt; + let Inst{15-0} = imm16; +} + +class LUI_FM_MM : MMArch { + bits<5> rt; + bits<16> imm16; + + bits<32> Inst; + + let Inst{31-26} = 0x10; + let Inst{25-21} = 0xd; + let Inst{20-16} = rt; + let Inst{15-0} = imm16; +} + +class MULT_FM_MM<bits<10> funct> : MMArch { + bits<5> rs; + bits<5> rt; + + bits<32> Inst; + + let Inst{31-26} = 0x00; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-6} = funct; + let Inst{5-0} = 0x3c; +} + +class SRA_FM_MM<bits<10> funct, bit rotate> : MMArch { + bits<5> rd; + bits<5> rt; + bits<5> shamt; + + bits<32> Inst; + + let Inst{31-26} = 0; + let Inst{25-21} = rd; + let Inst{20-16} = rt; + let Inst{15-11} = shamt; + let Inst{10} = rotate; + let Inst{9-0} = funct; +} + +class SRLV_FM_MM<bits<10> funct, bit rotate> : MMArch { + bits<5> rd; + bits<5> rt; + bits<5> rs; + + bits<32> Inst; + + let Inst{31-26} = 0; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-11} = rd; + let Inst{10} = rotate; + let Inst{9-0} = funct; +} + +class LW_FM_MM<bits<6> op> : MMArch { + bits<5> rt; + bits<21> addr; + + bits<32> Inst; + + let Inst{31-26} = op; + let Inst{25-21} = rt; + let Inst{20-16} = addr{20-16}; + let Inst{15-0} = addr{15-0}; +} diff --git a/lib/Target/Mips/MicroMipsInstrInfo.td b/lib/Target/Mips/MicroMipsInstrInfo.td new file mode 100644 index 0000000..74cdccd --- /dev/null +++ b/lib/Target/Mips/MicroMipsInstrInfo.td @@ -0,0 +1,67 @@ +let isCodeGenOnly = 1 in { + /// Arithmetic Instructions (ALU Immediate) + def ADDiu_MM : MMRel, ArithLogicI<"addiu", simm16, CPURegsOpnd>, + ADDI_FM_MM<0xc>; + def ADDi_MM : MMRel, ArithLogicI<"addi", simm16, CPURegsOpnd>, + ADDI_FM_MM<0x4>; + def SLTi_MM : MMRel, SetCC_I<"slti", setlt, simm16, immSExt16, CPURegs>, + SLTI_FM_MM<0x24>; + def SLTiu_MM : MMRel, SetCC_I<"sltiu", setult, simm16, immSExt16, CPURegs>, + SLTI_FM_MM<0x2c>; + def ANDi_MM : MMRel, ArithLogicI<"andi", uimm16, CPURegsOpnd, immZExt16, and>, + ADDI_FM_MM<0x34>; + def ORi_MM : MMRel, ArithLogicI<"ori", uimm16, CPURegsOpnd, immZExt16, or>, + ADDI_FM_MM<0x14>; + def XORi_MM : MMRel, ArithLogicI<"xori", uimm16, CPURegsOpnd, immZExt16, xor>, + ADDI_FM_MM<0x1c>; + def LUi_MM : MMRel, LoadUpper<"lui", CPURegs, uimm16>, LUI_FM_MM; + + /// Arithmetic Instructions (3-Operand, R-Type) + def ADDu_MM : MMRel, ArithLogicR<"addu", CPURegsOpnd>, ADD_FM_MM<0, 0x150>; + def SUBu_MM : MMRel, ArithLogicR<"subu", CPURegsOpnd>, ADD_FM_MM<0, 0x1d0>; + def MUL_MM : MMRel, ArithLogicR<"mul", CPURegsOpnd>, ADD_FM_MM<0, 0x210>; + def ADD_MM : MMRel, ArithLogicR<"add", CPURegsOpnd>, ADD_FM_MM<0, 0x110>; + def SUB_MM : MMRel, ArithLogicR<"sub", CPURegsOpnd>, ADD_FM_MM<0, 0x190>; + def SLT_MM : MMRel, SetCC_R<"slt", setlt, CPURegs>, ADD_FM_MM<0, 0x350>; + def SLTu_MM : MMRel, SetCC_R<"sltu", setult, CPURegs>, + ADD_FM_MM<0, 0x390>; + def AND_MM : MMRel, ArithLogicR<"and", CPURegsOpnd, 1, IIAlu, and>, + ADD_FM_MM<0, 0x250>; + def OR_MM : MMRel, ArithLogicR<"or", CPURegsOpnd, 1, IIAlu, or>, + ADD_FM_MM<0, 0x290>; + def XOR_MM : MMRel, ArithLogicR<"xor", CPURegsOpnd, 1, IIAlu, xor>, + ADD_FM_MM<0, 0x310>; + def NOR_MM : MMRel, LogicNOR<"nor", CPURegsOpnd>, ADD_FM_MM<0, 0x2d0>; + def MULT_MM : MMRel, Mult<"mult", IIImul, CPURegsOpnd, [HI, LO]>, + MULT_FM_MM<0x22c>; + def MULTu_MM : MMRel, Mult<"multu", IIImul, CPURegsOpnd, [HI, LO]>, + MULT_FM_MM<0x26c>; + + /// Shift Instructions + def SLL_MM : MMRel, shift_rotate_imm<"sll", shamt, CPURegsOpnd>, + SRA_FM_MM<0, 0>; + def SRL_MM : MMRel, shift_rotate_imm<"srl", shamt, CPURegsOpnd>, + SRA_FM_MM<0x40, 0>; + def SRA_MM : MMRel, shift_rotate_imm<"sra", shamt, CPURegsOpnd>, + SRA_FM_MM<0x80, 0>; + def SLLV_MM : MMRel, shift_rotate_reg<"sllv", CPURegsOpnd>, + SRLV_FM_MM<0x10, 0>; + def SRLV_MM : MMRel, shift_rotate_reg<"srlv", CPURegsOpnd>, + SRLV_FM_MM<0x50, 0>; + def SRAV_MM : MMRel, shift_rotate_reg<"srav", CPURegsOpnd>, + SRLV_FM_MM<0x90, 0>; + def ROTR_MM : MMRel, shift_rotate_imm<"rotr", shamt, CPURegsOpnd>, + SRA_FM_MM<0xc0, 0>; + def ROTRV_MM : MMRel, shift_rotate_reg<"rotrv", CPURegsOpnd>, + SRLV_FM_MM<0xd0, 0>; + + /// Load and Store Instructions - aligned + defm LB_MM : LoadM<"lb", CPURegs, sextloadi8>, MMRel, LW_FM_MM<0x7>; + defm LBu_MM : LoadM<"lbu", CPURegs, zextloadi8>, MMRel, LW_FM_MM<0x5>; + defm LH_MM : LoadM<"lh", CPURegs, sextloadi16>, MMRel, LW_FM_MM<0xf>; + defm LHu_MM : LoadM<"lhu", CPURegs, zextloadi16>, MMRel, LW_FM_MM<0xd>; + defm LW_MM : LoadM<"lw", CPURegs>, MMRel, LW_FM_MM<0x3f>; + defm SB_MM : StoreM<"sb", CPURegs, truncstorei8>, MMRel, LW_FM_MM<0x6>; + defm SH_MM : StoreM<"sh", CPURegs, truncstorei16>, MMRel, LW_FM_MM<0xe>; + defm SW_MM : StoreM<"sw", CPURegs>, MMRel, LW_FM_MM<0x3e>; +} diff --git a/lib/Target/Mips/Mips16ISelDAGToDAG.cpp b/lib/Target/Mips/Mips16ISelDAGToDAG.cpp index 00b3449..c1c635c 100644 --- a/lib/Target/Mips/Mips16ISelDAGToDAG.cpp +++ b/lib/Target/Mips/Mips16ISelDAGToDAG.cpp @@ -35,6 +35,11 @@ #include "llvm/Target/TargetMachine.h" using namespace llvm; +bool Mips16DAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { + if (!Subtarget.inMips16Mode()) + return false; + return MipsDAGToDAGISel::runOnMachineFunction(MF); +} /// Select multiply instructions. std::pair<SDNode*, SDNode*> Mips16DAGToDAGISel::selectMULT(SDNode *N, unsigned Opc, DebugLoc DL, EVT Ty, @@ -267,7 +272,7 @@ std::pair<bool, SDNode*> Mips16DAGToDAGISel::selectNode(SDNode *Node) { EVT VT = LHS.getValueType(); unsigned Sltu_op = Mips::SltuRxRyRz16; - SDNode *Carry = CurDAG->getMachineNode(Sltu_op, DL, VT, Ops, 2); + SDNode *Carry = CurDAG->getMachineNode(Sltu_op, DL, VT, Ops); unsigned Addu_op = Mips::AdduRxRyRz16; SDNode *AddCarry = CurDAG->getMachineNode(Addu_op, DL, VT, SDValue(Carry,0), RHS); diff --git a/lib/Target/Mips/Mips16ISelDAGToDAG.h b/lib/Target/Mips/Mips16ISelDAGToDAG.h index baa8587..f05f9b7 100644 --- a/lib/Target/Mips/Mips16ISelDAGToDAG.h +++ b/lib/Target/Mips/Mips16ISelDAGToDAG.h @@ -28,6 +28,8 @@ private: SDValue getMips16SPAliasReg(); + virtual bool runOnMachineFunction(MachineFunction &MF); + void getMips16SPRefReg(SDNode *Parent, SDValue &AliasReg); virtual bool selectAddr16(SDNode *Parent, SDValue N, SDValue &Base, diff --git a/lib/Target/Mips/Mips16ISelLowering.cpp b/lib/Target/Mips/Mips16ISelLowering.cpp index 23eb537..f63318f 100644 --- a/lib/Target/Mips/Mips16ISelLowering.cpp +++ b/lib/Target/Mips/Mips16ISelLowering.cpp @@ -53,7 +53,6 @@ Mips16TargetLowering::Mips16TargetLowering(MipsTargetMachine &TM) if (Mips16HardFloat) setMips16HardFloatLibCalls(); - setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand); setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Expand); setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i32, Expand); setOperationAction(ISD::ATOMIC_SWAP, MVT::i32, Expand); @@ -614,7 +613,8 @@ MachineBasicBlock unsigned regX = MI->getOperand(0).getReg(); unsigned regY = MI->getOperand(1).getReg(); MachineBasicBlock *target = MI->getOperand(2).getMBB(); - BuildMI(*BB, MI, MI->getDebugLoc(), TII->get(CmpOpc)).addReg(regX).addReg(regY); + BuildMI(*BB, MI, MI->getDebugLoc(), TII->get(CmpOpc)).addReg(regX) + .addReg(regY); BuildMI(*BB, MI, MI->getDebugLoc(), TII->get(BtOpc)).addMBB(target); MI->eraseFromParent(); // The pseudo instruction is gone now. return BB; @@ -636,7 +636,8 @@ MachineBasicBlock *Mips16TargetLowering::emitFEXT_T8I8I16_ins( CmpOpc = CmpiXOpc; else llvm_unreachable("immediate field not usable"); - BuildMI(*BB, MI, MI->getDebugLoc(), TII->get(CmpOpc)).addReg(regX).addImm(imm); + BuildMI(*BB, MI, MI->getDebugLoc(), TII->get(CmpOpc)).addReg(regX) + .addImm(imm); BuildMI(*BB, MI, MI->getDebugLoc(), TII->get(BtOpc)).addMBB(target); MI->eraseFromParent(); // The pseudo instruction is gone now. return BB; diff --git a/lib/Target/Mips/Mips16RegisterInfo.cpp b/lib/Target/Mips/Mips16RegisterInfo.cpp index 6cca227..7ad18f2 100644 --- a/lib/Target/Mips/Mips16RegisterInfo.cpp +++ b/lib/Target/Mips/Mips16RegisterInfo.cpp @@ -1,5 +1,4 @@ - -//===-- Mips16RegisterInfo.cpp - MIPS16 Register Information -== ----------===// +//===-- Mips16RegisterInfo.cpp - MIPS16 Register Information --------------===// // // The LLVM Compiler Infrastructure // diff --git a/lib/Target/Mips/Mips64InstrInfo.td b/lib/Target/Mips/Mips64InstrInfo.td index 846a822..fc533fb 100644 --- a/lib/Target/Mips/Mips64InstrInfo.td +++ b/lib/Target/Mips/Mips64InstrInfo.td @@ -66,14 +66,12 @@ let usesCustomInserter = 1, Predicates = [HasStdEnc], defm ATOMIC_CMP_SWAP_I64 : AtomicCmpSwap64<atomic_cmp_swap_64>; } -/// Pseudo instructions for loading, storing and copying accumulator registers. +/// Pseudo instructions for loading and storing accumulator registers. let isPseudo = 1 in { defm LOAD_AC128 : LoadM<"load_ac128", ACRegs128>; defm STORE_AC128 : StoreM<"store_ac128", ACRegs128>; } -def COPY_AC128 : PseudoSE<(outs ACRegs128:$dst), (ins ACRegs128:$src), []>; - //===----------------------------------------------------------------------===// // Instruction definition //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp index 1876cb6..6e4feda 100644 --- a/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/lib/Target/Mips/MipsAsmPrinter.cpp @@ -46,6 +46,10 @@ using namespace llvm; bool MipsAsmPrinter::runOnMachineFunction(MachineFunction &MF) { + // Initialize TargetLoweringObjectFile. + if (Subtarget->allowMixed16_32()) + const_cast<TargetLoweringObjectFile&>(getObjFileLowering()) + .Initialize(OutContext, TM); MipsFI = MF.getInfo<MipsFunctionInfo>(); AsmPrinter::runOnMachineFunction(MF); return true; @@ -245,12 +249,18 @@ void MipsAsmPrinter::EmitFunctionEntryLabel() { void MipsAsmPrinter::EmitFunctionBodyStart() { MCInstLowering.Initialize(Mang, &MF->getContext()); - emitFrameDirective(); + bool IsNakedFunction = + MF->getFunction()-> + getAttributes().hasAttribute(AttributeSet::FunctionIndex, + Attribute::Naked); + if (!IsNakedFunction) + emitFrameDirective(); if (OutStreamer.hasRawTextSupport()) { SmallString<128> Str; raw_svector_ostream OS(Str); - printSavedRegsBitmask(OS); + if (!IsNakedFunction) + printSavedRegsBitmask(OS); OutStreamer.EmitRawText(OS.str()); if (!Subtarget->inMips16Mode()) { OutStreamer.EmitRawText(StringRef("\t.set\tnoreorder")); @@ -419,12 +429,18 @@ bool MipsAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, unsigned AsmVariant, const char *ExtraCode, raw_ostream &O) { - if (ExtraCode && ExtraCode[0]) - return true; // Unknown modifier. + int Offset = 0; + // Currently we are expecting either no ExtraCode or 'D' + if (ExtraCode) { + if (ExtraCode[0] == 'D') + Offset = 4; + else + return true; // Unknown modifier. + } const MachineOperand &MO = MI->getOperand(OpNum); assert(MO.isReg() && "unexpected inline asm memory operand"); - O << "0($" << MipsInstPrinter::getRegisterName(MO.getReg()) << ")"; + O << Offset << "($" << MipsInstPrinter::getRegisterName(MO.getReg()) << ")"; return false; } diff --git a/lib/Target/Mips/MipsCodeEmitter.cpp b/lib/Target/Mips/MipsCodeEmitter.cpp index 1d86d90..3fc402b 100644 --- a/lib/Target/Mips/MipsCodeEmitter.cpp +++ b/lib/Target/Mips/MipsCodeEmitter.cpp @@ -116,7 +116,7 @@ private: int Offset) const; /// Expand pseudo instructions with accumulator register operands. - void expandACCInstr(MachineBasicBlock::instr_iterator &MI, + void expandACCInstr(MachineBasicBlock::instr_iterator MI, MachineBasicBlock &MBB, unsigned Opc) const; /// \brief Expand pseudo instruction. Return true if MI was expanded. @@ -302,7 +302,7 @@ void MipsCodeEmitter::emitWord(unsigned Word) { MCE.emitWordBE(Word); } -void MipsCodeEmitter::expandACCInstr(MachineBasicBlock::instr_iterator &MI, +void MipsCodeEmitter::expandACCInstr(MachineBasicBlock::instr_iterator MI, MachineBasicBlock &MBB, unsigned Opc) const { // Expand "pseudomult $ac0, $t0, $t1" to "mult $t0, $t1". diff --git a/lib/Target/Mips/MipsConstantIslandPass.cpp b/lib/Target/Mips/MipsConstantIslandPass.cpp index b5de1eb..1951324 100644 --- a/lib/Target/Mips/MipsConstantIslandPass.cpp +++ b/lib/Target/Mips/MipsConstantIslandPass.cpp @@ -80,6 +80,10 @@ FunctionPass *llvm::createMipsConstantIslandPass(MipsTargetMachine &tm) { } bool MipsConstantIslands::runOnMachineFunction(MachineFunction &F) { - return true; + // The intention is for this to be a mips16 only pass for now + // FIXME: + // if (!TM.getSubtarget<MipsSubtarget>().inMips16Mode()) + // return false; + return false; } diff --git a/lib/Target/Mips/MipsDSPInstrFormats.td b/lib/Target/Mips/MipsDSPInstrFormats.td index a72a763..cf09113 100644 --- a/lib/Target/Mips/MipsDSPInstrFormats.td +++ b/lib/Target/Mips/MipsDSPInstrFormats.td @@ -219,6 +219,33 @@ class MULT_FMT<bits<6> opcode, bits<6> funct> : DSPInst { let Inst{5-0} = funct; } +// MFHI sub-class format. +class MFHI_FMT<bits<6> funct> : DSPInst { + bits<5> rd; + bits<2> ac; + + let Inst{31-26} = 0; + let Inst{25-23} = 0; + let Inst{22-21} = ac; + let Inst{20-16} = 0; + let Inst{15-11} = rd; + let Inst{10-6} = 0; + let Inst{5-0} = funct; +} + +// MTHI sub-class format. +class MTHI_FMT<bits<6> funct> : DSPInst { + bits<5> rs; + bits<2> ac; + + let Inst{31-26} = 0; + let Inst{25-21} = rs; + let Inst{20-13} = 0; + let Inst{12-11} = ac; + let Inst{10-6} = 0; + let Inst{5-0} = funct; +} + // EXTR.W sub-class format (type 1). class EXTR_W_TY1_FMT<bits<5> op> : DSPInst { bits<5> rt; diff --git a/lib/Target/Mips/MipsDSPInstrInfo.td b/lib/Target/Mips/MipsDSPInstrInfo.td index 3c116e1..c12878a 100644 --- a/lib/Target/Mips/MipsDSPInstrInfo.td +++ b/lib/Target/Mips/MipsDSPInstrInfo.td @@ -26,6 +26,8 @@ def SDT_MipsShilo : SDTypeProfile<1, 2, [SDTCisVT<0, untyped>, SDTCisSameAs<0, 2>, SDTCisVT<1, i32>]>; def SDT_MipsDPA : SDTypeProfile<1, 3, [SDTCisVT<0, untyped>, SDTCisSameAs<0, 3>, SDTCisVT<1, i32>, SDTCisSameAs<1, 2>]>; +def SDT_MipsSHIFT_DSP : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisSameAs<0, 1>, + SDTCisVT<2, i32>]>; class MipsDSPBase<string Opc, SDTypeProfile Prof> : SDNode<!strconcat("MipsISD::", Opc), Prof>; @@ -74,18 +76,19 @@ def MipsMADD_DSP : MipsDSPBase<"MADD_DSP", SDT_MipsDPA>; def MipsMADDU_DSP : MipsDSPBase<"MADDU_DSP", SDT_MipsDPA>; def MipsMSUB_DSP : MipsDSPBase<"MSUB_DSP", SDT_MipsDPA>; def MipsMSUBU_DSP : MipsDSPBase<"MSUBU_DSP", SDT_MipsDPA>; +def MipsSHLL_DSP : MipsDSPBase<"SHLL_DSP", SDT_MipsSHIFT_DSP>; +def MipsSHRA_DSP : MipsDSPBase<"SHRA_DSP", SDT_MipsSHIFT_DSP>; +def MipsSHRL_DSP : MipsDSPBase<"SHRL_DSP", SDT_MipsSHIFT_DSP>; +def MipsSETCC_DSP : MipsDSPBase<"SETCC_DSP", SDTSetCC>; +def MipsSELECT_CC_DSP : MipsDSPBase<"SELECT_CC_DSP", SDTSelectCC>; // Flags. -class UseAC { - list<Register> Uses = [AC0]; +class Uses<list<Register> Regs> { + list<Register> Uses = Regs; } -class UseDSPCtrl { - list<Register> Uses = [DSPCtrl]; -} - -class ClearDefs { - list<Register> Defs = []; +class Defs<list<Register> Regs> { + list<Register> Defs = Regs; } // Instruction encoding. @@ -145,6 +148,10 @@ class MAQ_S_W_PHL_ENC : DPA_W_PH_FMT<0b10100>; class MAQ_S_W_PHR_ENC : DPA_W_PH_FMT<0b10110>; class MAQ_SA_W_PHL_ENC : DPA_W_PH_FMT<0b10000>; class MAQ_SA_W_PHR_ENC : DPA_W_PH_FMT<0b10010>; +class MFHI_ENC : MFHI_FMT<0b010000>; +class MFLO_ENC : MFHI_FMT<0b010010>; +class MTHI_ENC : MTHI_FMT<0b010001>; +class MTLO_ENC : MTHI_FMT<0b010011>; class DPAU_H_QBL_ENC : DPA_W_PH_FMT<0b00011>; class DPAU_H_QBR_ENC : DPA_W_PH_FMT<0b00111>; class DPSU_H_QBL_ENC : DPA_W_PH_FMT<0b01011>; @@ -256,7 +263,6 @@ class ADDU_QB_DESC_BASE<string instr_asm, SDPatternOperator OpNode, string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt"); list<dag> Pattern = [(set RCD:$rd, (OpNode RCS:$rs, RCT:$rt))]; InstrItinClass Itinerary = itin; - list<Register> Defs = [DSPCtrl]; } class RADDU_W_QB_DESC_BASE<string instr_asm, SDPatternOperator OpNode, @@ -267,7 +273,6 @@ class RADDU_W_QB_DESC_BASE<string instr_asm, SDPatternOperator OpNode, string AsmString = !strconcat(instr_asm, "\t$rd, $rs"); list<dag> Pattern = [(set RCD:$rd, (OpNode RCS:$rs))]; InstrItinClass Itinerary = itin; - list<Register> Defs = [DSPCtrl]; } class CMP_EQ_QB_R2_DESC_BASE<string instr_asm, SDPatternOperator OpNode, @@ -278,7 +283,6 @@ class CMP_EQ_QB_R2_DESC_BASE<string instr_asm, SDPatternOperator OpNode, string AsmString = !strconcat(instr_asm, "\t$rs, $rt"); list<dag> Pattern = [(OpNode RCS:$rs, RCT:$rt)]; InstrItinClass Itinerary = itin; - list<Register> Defs = [DSPCtrl]; } class CMP_EQ_QB_R3_DESC_BASE<string instr_asm, SDPatternOperator OpNode, @@ -289,7 +293,6 @@ class CMP_EQ_QB_R3_DESC_BASE<string instr_asm, SDPatternOperator OpNode, string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt"); list<dag> Pattern = [(set RCD:$rd, (OpNode RCS:$rs, RCT:$rt))]; InstrItinClass Itinerary = itin; - list<Register> Defs = [DSPCtrl]; } class PRECR_SRA_PH_W_DESC_BASE<string instr_asm, SDPatternOperator OpNode, @@ -300,7 +303,6 @@ class PRECR_SRA_PH_W_DESC_BASE<string instr_asm, SDPatternOperator OpNode, string AsmString = !strconcat(instr_asm, "\t$rt, $rs, $sa"); list<dag> Pattern = [(set RCT:$rt, (OpNode RCS:$src, RCS:$rs, immZExt5:$sa))]; InstrItinClass Itinerary = itin; - list<Register> Defs = [DSPCtrl]; string Constraints = "$src = $rt"; } @@ -312,7 +314,6 @@ class ABSQ_S_PH_R2_DESC_BASE<string instr_asm, SDPatternOperator OpNode, string AsmString = !strconcat(instr_asm, "\t$rd, $rt"); list<dag> Pattern = [(set RCD:$rd, (OpNode RCT:$rt))]; InstrItinClass Itinerary = itin; - list<Register> Defs = [DSPCtrl]; } class REPL_DESC_BASE<string instr_asm, SDPatternOperator OpNode, @@ -322,7 +323,6 @@ class REPL_DESC_BASE<string instr_asm, SDPatternOperator OpNode, string AsmString = !strconcat(instr_asm, "\t$rd, $imm"); list<dag> Pattern = [(set RC:$rd, (OpNode immPat:$imm))]; InstrItinClass Itinerary = itin; - list<Register> Defs = [DSPCtrl]; } class SHLL_QB_R3_DESC_BASE<string instr_asm, SDPatternOperator OpNode, @@ -332,7 +332,6 @@ class SHLL_QB_R3_DESC_BASE<string instr_asm, SDPatternOperator OpNode, string AsmString = !strconcat(instr_asm, "\t$rd, $rt, $rs_sa"); list<dag> Pattern = [(set RC:$rd, (OpNode RC:$rt, CPURegs:$rs_sa))]; InstrItinClass Itinerary = itin; - list<Register> Defs = [DSPCtrl]; } class SHLL_QB_R2_DESC_BASE<string instr_asm, SDPatternOperator OpNode, @@ -343,7 +342,7 @@ class SHLL_QB_R2_DESC_BASE<string instr_asm, SDPatternOperator OpNode, string AsmString = !strconcat(instr_asm, "\t$rd, $rt, $rs_sa"); list<dag> Pattern = [(set RC:$rd, (OpNode RC:$rt, ImmPat:$rs_sa))]; InstrItinClass Itinerary = itin; - list<Register> Defs = [DSPCtrl]; + bit hasSideEffects = 1; } class LX_DESC_BASE<string instr_asm, SDPatternOperator OpNode, @@ -354,7 +353,6 @@ class LX_DESC_BASE<string instr_asm, SDPatternOperator OpNode, list<dag> Pattern = [(set CPURegs:$rd, (OpNode CPURegs:$base, CPURegs:$index))]; InstrItinClass Itinerary = itin; - list<Register> Defs = [DSPCtrl]; bit mayLoad = 1; } @@ -366,7 +364,6 @@ class ADDUH_QB_DESC_BASE<string instr_asm, SDPatternOperator OpNode, string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt"); list<dag> Pattern = [(set RCD:$rd, (OpNode RCS:$rs, RCT:$rt))]; InstrItinClass Itinerary = itin; - list<Register> Defs = [DSPCtrl]; } class APPEND_DESC_BASE<string instr_asm, SDPatternOperator OpNode, @@ -377,7 +374,6 @@ class APPEND_DESC_BASE<string instr_asm, SDPatternOperator OpNode, list<dag> Pattern = [(set CPURegs:$rt, (OpNode CPURegs:$src, CPURegs:$rs, ImmOp:$sa))]; InstrItinClass Itinerary = itin; - list<Register> Defs = [DSPCtrl]; string Constraints = "$src = $rt"; } @@ -387,7 +383,6 @@ class EXTR_W_TY1_R2_DESC_BASE<string instr_asm, SDPatternOperator OpNode, dag InOperandList = (ins ACRegsDSP:$ac, CPURegs:$shift_rs); string AsmString = !strconcat(instr_asm, "\t$rt, $ac, $shift_rs"); InstrItinClass Itinerary = itin; - list<Register> Defs = [DSPCtrl]; } class EXTR_W_TY1_R1_DESC_BASE<string instr_asm, SDPatternOperator OpNode, @@ -396,7 +391,6 @@ class EXTR_W_TY1_R1_DESC_BASE<string instr_asm, SDPatternOperator OpNode, dag InOperandList = (ins ACRegsDSP:$ac, uimm16:$shift_rs); string AsmString = !strconcat(instr_asm, "\t$rt, $ac, $shift_rs"); InstrItinClass Itinerary = itin; - list<Register> Defs = [DSPCtrl]; } class SHILO_R1_DESC_BASE<string instr_asm, SDPatternOperator OpNode> { @@ -405,7 +399,6 @@ class SHILO_R1_DESC_BASE<string instr_asm, SDPatternOperator OpNode> { string AsmString = !strconcat(instr_asm, "\t$ac, $shift"); list<dag> Pattern = [(set ACRegsDSP:$ac, (OpNode immSExt6:$shift, ACRegsDSP:$acin))]; - list<Register> Defs = [DSPCtrl]; string Constraints = "$acin = $ac"; } @@ -415,7 +408,6 @@ class SHILO_R2_DESC_BASE<string instr_asm, SDPatternOperator OpNode> { string AsmString = !strconcat(instr_asm, "\t$ac, $rs"); list<dag> Pattern = [(set ACRegsDSP:$ac, (OpNode CPURegs:$rs, ACRegsDSP:$acin))]; - list<Register> Defs = [DSPCtrl]; string Constraints = "$acin = $ac"; } @@ -425,7 +417,6 @@ class MTHLIP_DESC_BASE<string instr_asm, SDPatternOperator OpNode> { string AsmString = !strconcat(instr_asm, "\t$rs, $ac"); list<dag> Pattern = [(set ACRegsDSP:$ac, (OpNode CPURegs:$rs, ACRegsDSP:$acin))]; - list<Register> Uses = [DSPCtrl]; string Constraints = "$acin = $ac"; } @@ -436,7 +427,6 @@ class RDDSP_DESC_BASE<string instr_asm, SDPatternOperator OpNode, string AsmString = !strconcat(instr_asm, "\t$rd, $mask"); list<dag> Pattern = [(set CPURegs:$rd, (OpNode immZExt10:$mask))]; InstrItinClass Itinerary = itin; - list<Register> Uses = [DSPCtrl]; } class WRDSP_DESC_BASE<string instr_asm, SDPatternOperator OpNode, @@ -446,7 +436,6 @@ class WRDSP_DESC_BASE<string instr_asm, SDPatternOperator OpNode, string AsmString = !strconcat(instr_asm, "\t$rs, $mask"); list<dag> Pattern = [(OpNode CPURegs:$rs, immZExt10:$mask)]; InstrItinClass Itinerary = itin; - list<Register> Defs = [DSPCtrl]; } class DPA_W_PH_DESC_BASE<string instr_asm, SDPatternOperator OpNode> { @@ -455,7 +444,6 @@ class DPA_W_PH_DESC_BASE<string instr_asm, SDPatternOperator OpNode> { string AsmString = !strconcat(instr_asm, "\t$ac, $rs, $rt"); list<dag> Pattern = [(set ACRegsDSP:$ac, (OpNode CPURegs:$rs, CPURegs:$rt, ACRegsDSP:$acin))]; - list<Register> Defs = [DSPCtrl]; string Constraints = "$acin = $ac"; } @@ -482,9 +470,22 @@ class MADD_DESC_BASE<string instr_asm, SDPatternOperator OpNode, string Constraints = "$acin = $ac"; } +class MFHI_DESC_BASE<string instr_asm, RegisterClass RC, InstrItinClass itin> { + dag OutOperandList = (outs CPURegs:$rd); + dag InOperandList = (ins RC:$ac); + string AsmString = !strconcat(instr_asm, "\t$rd, $ac"); + InstrItinClass Itinerary = itin; +} + +class MTHI_DESC_BASE<string instr_asm, RegisterClass RC, InstrItinClass itin> { + dag OutOperandList = (outs RC:$ac); + dag InOperandList = (ins CPURegs:$rs); + string AsmString = !strconcat(instr_asm, "\t$rs, $ac"); + InstrItinClass Itinerary = itin; +} + class BPOSGE32_PSEUDO_DESC_BASE<SDPatternOperator OpNode, InstrItinClass itin> : MipsPseudo<(outs CPURegs:$dst), (ins), [(set CPURegs:$dst, (OpNode))]> { - list<Register> Uses = [DSPCtrl]; bit usesCustomInserter = 1; } @@ -493,7 +494,6 @@ class BPOSGE32_DESC_BASE<string instr_asm, InstrItinClass itin> { dag InOperandList = (ins brtarget:$offset); string AsmString = !strconcat(instr_asm, "\t$offset"); InstrItinClass Itinerary = itin; - list<Register> Uses = [DSPCtrl]; bit isBranch = 1; bit isTerminator = 1; bit hasDelaySlot = 1; @@ -506,7 +506,6 @@ class INSV_DESC_BASE<string instr_asm, SDPatternOperator OpNode, string AsmString = !strconcat(instr_asm, "\t$rt, $rs"); list<dag> Pattern = [(set CPURegs:$rt, (OpNode CPURegs:$src, CPURegs:$rs))]; InstrItinClass Itinerary = itin; - list<Register> Uses = [DSPCtrl]; string Constraints = "$src = $rt"; } @@ -515,178 +514,183 @@ class INSV_DESC_BASE<string instr_asm, SDPatternOperator OpNode, //===----------------------------------------------------------------------===// // Addition/subtraction -class ADDU_QB_DESC : ADDU_QB_DESC_BASE<"addu.qb", int_mips_addu_qb, NoItinerary, - DSPRegs, DSPRegs>, IsCommutable; +class ADDU_QB_DESC : ADDU_QB_DESC_BASE<"addu.qb", null_frag, NoItinerary, + DSPRegs, DSPRegs>, IsCommutable, + Defs<[DSPOutFlag20]>; class ADDU_S_QB_DESC : ADDU_QB_DESC_BASE<"addu_s.qb", int_mips_addu_s_qb, NoItinerary, DSPRegs, DSPRegs>, - IsCommutable; + IsCommutable, Defs<[DSPOutFlag20]>; -class SUBU_QB_DESC : ADDU_QB_DESC_BASE<"subu.qb", int_mips_subu_qb, NoItinerary, - DSPRegs, DSPRegs>; +class SUBU_QB_DESC : ADDU_QB_DESC_BASE<"subu.qb", null_frag, NoItinerary, + DSPRegs, DSPRegs>, + Defs<[DSPOutFlag20]>; class SUBU_S_QB_DESC : ADDU_QB_DESC_BASE<"subu_s.qb", int_mips_subu_s_qb, - NoItinerary, DSPRegs, DSPRegs>; + NoItinerary, DSPRegs, DSPRegs>, + Defs<[DSPOutFlag20]>; -class ADDQ_PH_DESC : ADDU_QB_DESC_BASE<"addq.ph", int_mips_addq_ph, NoItinerary, - DSPRegs, DSPRegs>, IsCommutable; +class ADDQ_PH_DESC : ADDU_QB_DESC_BASE<"addq.ph", null_frag, NoItinerary, + DSPRegs, DSPRegs>, IsCommutable, + Defs<[DSPOutFlag20]>; class ADDQ_S_PH_DESC : ADDU_QB_DESC_BASE<"addq_s.ph", int_mips_addq_s_ph, NoItinerary, DSPRegs, DSPRegs>, - IsCommutable; + IsCommutable, Defs<[DSPOutFlag20]>; -class SUBQ_PH_DESC : ADDU_QB_DESC_BASE<"subq.ph", int_mips_subq_ph, NoItinerary, - DSPRegs, DSPRegs>; +class SUBQ_PH_DESC : ADDU_QB_DESC_BASE<"subq.ph", null_frag, NoItinerary, + DSPRegs, DSPRegs>, + Defs<[DSPOutFlag20]>; class SUBQ_S_PH_DESC : ADDU_QB_DESC_BASE<"subq_s.ph", int_mips_subq_s_ph, - NoItinerary, DSPRegs, DSPRegs>; + NoItinerary, DSPRegs, DSPRegs>, + Defs<[DSPOutFlag20]>; class ADDQ_S_W_DESC : ADDU_QB_DESC_BASE<"addq_s.w", int_mips_addq_s_w, NoItinerary, CPURegs, CPURegs>, - IsCommutable; + IsCommutable, Defs<[DSPOutFlag20]>; class SUBQ_S_W_DESC : ADDU_QB_DESC_BASE<"subq_s.w", int_mips_subq_s_w, - NoItinerary, CPURegs, CPURegs>; + NoItinerary, CPURegs, CPURegs>, + Defs<[DSPOutFlag20]>; -class ADDSC_DESC : ADDU_QB_DESC_BASE<"addsc", int_mips_addsc, NoItinerary, - CPURegs, CPURegs>, IsCommutable; +class ADDSC_DESC : ADDU_QB_DESC_BASE<"addsc", null_frag, NoItinerary, + CPURegs, CPURegs>, IsCommutable, + Defs<[DSPCarry]>; -class ADDWC_DESC : ADDU_QB_DESC_BASE<"addwc", int_mips_addwc, NoItinerary, +class ADDWC_DESC : ADDU_QB_DESC_BASE<"addwc", null_frag, NoItinerary, CPURegs, CPURegs>, - IsCommutable, UseDSPCtrl; + IsCommutable, Uses<[DSPCarry]>, Defs<[DSPOutFlag20]>; class MODSUB_DESC : ADDU_QB_DESC_BASE<"modsub", int_mips_modsub, NoItinerary, - CPURegs, CPURegs>, ClearDefs; + CPURegs, CPURegs>; class RADDU_W_QB_DESC : RADDU_W_QB_DESC_BASE<"raddu.w.qb", int_mips_raddu_w_qb, - NoItinerary, CPURegs, DSPRegs>, - ClearDefs; + NoItinerary, CPURegs, DSPRegs>; // Absolute value class ABSQ_S_PH_DESC : ABSQ_S_PH_R2_DESC_BASE<"absq_s.ph", int_mips_absq_s_ph, - NoItinerary, DSPRegs>; + NoItinerary, DSPRegs>, + Defs<[DSPOutFlag20]>; class ABSQ_S_W_DESC : ABSQ_S_PH_R2_DESC_BASE<"absq_s.w", int_mips_absq_s_w, - NoItinerary, CPURegs>; + NoItinerary, CPURegs>, + Defs<[DSPOutFlag20]>; // Precision reduce/expand class PRECRQ_QB_PH_DESC : CMP_EQ_QB_R3_DESC_BASE<"precrq.qb.ph", int_mips_precrq_qb_ph, - NoItinerary, DSPRegs, DSPRegs>, - ClearDefs; + NoItinerary, DSPRegs, DSPRegs>; class PRECRQ_PH_W_DESC : CMP_EQ_QB_R3_DESC_BASE<"precrq.ph.w", int_mips_precrq_ph_w, - NoItinerary, DSPRegs, CPURegs>, - ClearDefs; + NoItinerary, DSPRegs, CPURegs>; class PRECRQ_RS_PH_W_DESC : CMP_EQ_QB_R3_DESC_BASE<"precrq_rs.ph.w", int_mips_precrq_rs_ph_w, NoItinerary, DSPRegs, - CPURegs>; + CPURegs>, + Defs<[DSPOutFlag22]>; class PRECRQU_S_QB_PH_DESC : CMP_EQ_QB_R3_DESC_BASE<"precrqu_s.qb.ph", int_mips_precrqu_s_qb_ph, NoItinerary, DSPRegs, - DSPRegs>; + DSPRegs>, + Defs<[DSPOutFlag22]>; class PRECEQ_W_PHL_DESC : ABSQ_S_PH_R2_DESC_BASE<"preceq.w.phl", int_mips_preceq_w_phl, - NoItinerary, CPURegs, DSPRegs>, - ClearDefs; + NoItinerary, CPURegs, DSPRegs>; class PRECEQ_W_PHR_DESC : ABSQ_S_PH_R2_DESC_BASE<"preceq.w.phr", int_mips_preceq_w_phr, - NoItinerary, CPURegs, DSPRegs>, - ClearDefs; + NoItinerary, CPURegs, DSPRegs>; class PRECEQU_PH_QBL_DESC : ABSQ_S_PH_R2_DESC_BASE<"precequ.ph.qbl", int_mips_precequ_ph_qbl, - NoItinerary, DSPRegs>, - ClearDefs; + NoItinerary, DSPRegs>; class PRECEQU_PH_QBR_DESC : ABSQ_S_PH_R2_DESC_BASE<"precequ.ph.qbr", int_mips_precequ_ph_qbr, - NoItinerary, DSPRegs>, - ClearDefs; + NoItinerary, DSPRegs>; class PRECEQU_PH_QBLA_DESC : ABSQ_S_PH_R2_DESC_BASE<"precequ.ph.qbla", int_mips_precequ_ph_qbla, - NoItinerary, DSPRegs>, - ClearDefs; + NoItinerary, DSPRegs>; class PRECEQU_PH_QBRA_DESC : ABSQ_S_PH_R2_DESC_BASE<"precequ.ph.qbra", int_mips_precequ_ph_qbra, - NoItinerary, DSPRegs>, - ClearDefs; + NoItinerary, DSPRegs>; class PRECEU_PH_QBL_DESC : ABSQ_S_PH_R2_DESC_BASE<"preceu.ph.qbl", int_mips_preceu_ph_qbl, - NoItinerary, DSPRegs>, - ClearDefs; + NoItinerary, DSPRegs>; class PRECEU_PH_QBR_DESC : ABSQ_S_PH_R2_DESC_BASE<"preceu.ph.qbr", int_mips_preceu_ph_qbr, - NoItinerary, DSPRegs>, - ClearDefs; + NoItinerary, DSPRegs>; class PRECEU_PH_QBLA_DESC : ABSQ_S_PH_R2_DESC_BASE<"preceu.ph.qbla", int_mips_preceu_ph_qbla, - NoItinerary, DSPRegs>, - ClearDefs; + NoItinerary, DSPRegs>; class PRECEU_PH_QBRA_DESC : ABSQ_S_PH_R2_DESC_BASE<"preceu.ph.qbra", int_mips_preceu_ph_qbra, - NoItinerary, DSPRegs>, - ClearDefs; + NoItinerary, DSPRegs>; // Shift -class SHLL_QB_DESC : SHLL_QB_R2_DESC_BASE<"shll.qb", int_mips_shll_qb, immZExt3, - NoItinerary, DSPRegs>; +class SHLL_QB_DESC : SHLL_QB_R2_DESC_BASE<"shll.qb", null_frag, immZExt3, + NoItinerary, DSPRegs>, + Defs<[DSPOutFlag22]>; class SHLLV_QB_DESC : SHLL_QB_R3_DESC_BASE<"shllv.qb", int_mips_shll_qb, - NoItinerary, DSPRegs>; + NoItinerary, DSPRegs>, + Defs<[DSPOutFlag22]>; -class SHRL_QB_DESC : SHLL_QB_R2_DESC_BASE<"shrl.qb", int_mips_shrl_qb, immZExt3, - NoItinerary, DSPRegs>, ClearDefs; +class SHRL_QB_DESC : SHLL_QB_R2_DESC_BASE<"shrl.qb", null_frag, immZExt3, + NoItinerary, DSPRegs>; class SHRLV_QB_DESC : SHLL_QB_R3_DESC_BASE<"shrlv.qb", int_mips_shrl_qb, - NoItinerary, DSPRegs>, ClearDefs; + NoItinerary, DSPRegs>; -class SHLL_PH_DESC : SHLL_QB_R2_DESC_BASE<"shll.ph", int_mips_shll_ph, immZExt4, - NoItinerary, DSPRegs>; +class SHLL_PH_DESC : SHLL_QB_R2_DESC_BASE<"shll.ph", null_frag, immZExt4, + NoItinerary, DSPRegs>, + Defs<[DSPOutFlag22]>; class SHLLV_PH_DESC : SHLL_QB_R3_DESC_BASE<"shllv.ph", int_mips_shll_ph, - NoItinerary, DSPRegs>; + NoItinerary, DSPRegs>, + Defs<[DSPOutFlag22]>; class SHLL_S_PH_DESC : SHLL_QB_R2_DESC_BASE<"shll_s.ph", int_mips_shll_s_ph, - immZExt4, NoItinerary, DSPRegs>; + immZExt4, NoItinerary, DSPRegs>, + Defs<[DSPOutFlag22]>; class SHLLV_S_PH_DESC : SHLL_QB_R3_DESC_BASE<"shllv_s.ph", int_mips_shll_s_ph, - NoItinerary, DSPRegs>; + NoItinerary, DSPRegs>, + Defs<[DSPOutFlag22]>; -class SHRA_PH_DESC : SHLL_QB_R2_DESC_BASE<"shra.ph", int_mips_shra_ph, immZExt4, - NoItinerary, DSPRegs>, ClearDefs; +class SHRA_PH_DESC : SHLL_QB_R2_DESC_BASE<"shra.ph", null_frag, immZExt4, + NoItinerary, DSPRegs>; class SHRAV_PH_DESC : SHLL_QB_R3_DESC_BASE<"shrav.ph", int_mips_shra_ph, - NoItinerary, DSPRegs>, ClearDefs; + NoItinerary, DSPRegs>; class SHRA_R_PH_DESC : SHLL_QB_R2_DESC_BASE<"shra_r.ph", int_mips_shra_r_ph, - immZExt4, NoItinerary, DSPRegs>, - ClearDefs; + immZExt4, NoItinerary, DSPRegs>; class SHRAV_R_PH_DESC : SHLL_QB_R3_DESC_BASE<"shrav_r.ph", int_mips_shra_r_ph, - NoItinerary, DSPRegs>, ClearDefs; + NoItinerary, DSPRegs>; class SHLL_S_W_DESC : SHLL_QB_R2_DESC_BASE<"shll_s.w", int_mips_shll_s_w, - immZExt5, NoItinerary, CPURegs>; + immZExt5, NoItinerary, CPURegs>, + Defs<[DSPOutFlag22]>; class SHLLV_S_W_DESC : SHLL_QB_R3_DESC_BASE<"shllv_s.w", int_mips_shll_s_w, - NoItinerary, CPURegs>; + NoItinerary, CPURegs>, + Defs<[DSPOutFlag22]>; class SHRA_R_W_DESC : SHLL_QB_R2_DESC_BASE<"shra_r.w", int_mips_shra_r_w, - immZExt5, NoItinerary, CPURegs>, - ClearDefs; + immZExt5, NoItinerary, CPURegs>; class SHRAV_R_W_DESC : SHLL_QB_R3_DESC_BASE<"shrav_r.w", int_mips_shra_r_w, NoItinerary, CPURegs>; @@ -694,36 +698,49 @@ class SHRAV_R_W_DESC : SHLL_QB_R3_DESC_BASE<"shrav_r.w", int_mips_shra_r_w, // Multiplication class MULEU_S_PH_QBL_DESC : ADDU_QB_DESC_BASE<"muleu_s.ph.qbl", int_mips_muleu_s_ph_qbl, - NoItinerary, DSPRegs, DSPRegs>; + NoItinerary, DSPRegs, DSPRegs>, + Defs<[DSPOutFlag21]>; class MULEU_S_PH_QBR_DESC : ADDU_QB_DESC_BASE<"muleu_s.ph.qbr", int_mips_muleu_s_ph_qbr, - NoItinerary, DSPRegs, DSPRegs>; + NoItinerary, DSPRegs, DSPRegs>, + Defs<[DSPOutFlag21]>; class MULEQ_S_W_PHL_DESC : ADDU_QB_DESC_BASE<"muleq_s.w.phl", int_mips_muleq_s_w_phl, NoItinerary, CPURegs, DSPRegs>, - IsCommutable; + IsCommutable, Defs<[DSPOutFlag21]>; class MULEQ_S_W_PHR_DESC : ADDU_QB_DESC_BASE<"muleq_s.w.phr", int_mips_muleq_s_w_phr, NoItinerary, CPURegs, DSPRegs>, - IsCommutable; + IsCommutable, Defs<[DSPOutFlag21]>; class MULQ_RS_PH_DESC : ADDU_QB_DESC_BASE<"mulq_rs.ph", int_mips_mulq_rs_ph, NoItinerary, DSPRegs, DSPRegs>, - IsCommutable; + IsCommutable, Defs<[DSPOutFlag21]>; class MULSAQ_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"mulsaq_s.w.ph", - MipsMULSAQ_S_W_PH>; + MipsMULSAQ_S_W_PH>, + Defs<[DSPOutFlag16_19]>; -class MAQ_S_W_PHL_DESC : DPA_W_PH_DESC_BASE<"maq_s.w.phl", MipsMAQ_S_W_PHL>; +class MAQ_S_W_PHL_DESC : DPA_W_PH_DESC_BASE<"maq_s.w.phl", MipsMAQ_S_W_PHL>, + Defs<[DSPOutFlag16_19]>; -class MAQ_S_W_PHR_DESC : DPA_W_PH_DESC_BASE<"maq_s.w.phr", MipsMAQ_S_W_PHR>; +class MAQ_S_W_PHR_DESC : DPA_W_PH_DESC_BASE<"maq_s.w.phr", MipsMAQ_S_W_PHR>, + Defs<[DSPOutFlag16_19]>; -class MAQ_SA_W_PHL_DESC : DPA_W_PH_DESC_BASE<"maq_sa.w.phl", MipsMAQ_SA_W_PHL>; +class MAQ_SA_W_PHL_DESC : DPA_W_PH_DESC_BASE<"maq_sa.w.phl", MipsMAQ_SA_W_PHL>, + Defs<[DSPOutFlag16_19]>; -class MAQ_SA_W_PHR_DESC : DPA_W_PH_DESC_BASE<"maq_sa.w.phr", MipsMAQ_SA_W_PHR>; +class MAQ_SA_W_PHR_DESC : DPA_W_PH_DESC_BASE<"maq_sa.w.phr", MipsMAQ_SA_W_PHR>, + Defs<[DSPOutFlag16_19]>; + +// Move from/to hi/lo. +class MFHI_DESC : MFHI_DESC_BASE<"mfhi", HIRegsDSP, NoItinerary>; +class MFLO_DESC : MFHI_DESC_BASE<"mflo", LORegsDSP, NoItinerary>; +class MTHI_DESC : MTHI_DESC_BASE<"mthi", HIRegsDSP, NoItinerary>; +class MTLO_DESC : MTHI_DESC_BASE<"mtlo", LORegsDSP, NoItinerary>; // Dot product with accumulate/subtract class DPAU_H_QBL_DESC : DPA_W_PH_DESC_BASE<"dpau.h.qbl", MipsDPAU_H_QBL>; @@ -734,13 +751,17 @@ class DPSU_H_QBL_DESC : DPA_W_PH_DESC_BASE<"dpsu.h.qbl", MipsDPSU_H_QBL>; class DPSU_H_QBR_DESC : DPA_W_PH_DESC_BASE<"dpsu.h.qbr", MipsDPSU_H_QBR>; -class DPAQ_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpaq_s.w.ph", MipsDPAQ_S_W_PH>; +class DPAQ_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpaq_s.w.ph", MipsDPAQ_S_W_PH>, + Defs<[DSPOutFlag16_19]>; -class DPSQ_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpsq_s.w.ph", MipsDPSQ_S_W_PH>; +class DPSQ_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpsq_s.w.ph", MipsDPSQ_S_W_PH>, + Defs<[DSPOutFlag16_19]>; -class DPAQ_SA_L_W_DESC : DPA_W_PH_DESC_BASE<"dpaq_sa.l.w", MipsDPAQ_SA_L_W>; +class DPAQ_SA_L_W_DESC : DPA_W_PH_DESC_BASE<"dpaq_sa.l.w", MipsDPAQ_SA_L_W>, + Defs<[DSPOutFlag16_19]>; -class DPSQ_SA_L_W_DESC : DPA_W_PH_DESC_BASE<"dpsq_sa.l.w", MipsDPSQ_SA_L_W>; +class DPSQ_SA_L_W_DESC : DPA_W_PH_DESC_BASE<"dpsq_sa.l.w", MipsDPSQ_SA_L_W>, + Defs<[DSPOutFlag16_19]>; class MULT_DSP_DESC : MULT_DESC_BASE<"mult", MipsMult, NoItinerary>; class MULTU_DSP_DESC : MULT_DESC_BASE<"multu", MipsMultu, NoItinerary>; @@ -752,15 +773,16 @@ class MSUBU_DSP_DESC : MADD_DESC_BASE<"msubu", MipsMSubu, NoItinerary>; // Comparison class CMPU_EQ_QB_DESC : CMP_EQ_QB_R2_DESC_BASE<"cmpu.eq.qb", int_mips_cmpu_eq_qb, NoItinerary, - DSPRegs>, IsCommutable; + DSPRegs>, + IsCommutable, Defs<[DSPCCond]>; class CMPU_LT_QB_DESC : CMP_EQ_QB_R2_DESC_BASE<"cmpu.lt.qb", int_mips_cmpu_lt_qb, NoItinerary, - DSPRegs>, IsCommutable; + DSPRegs>, Defs<[DSPCCond]>; class CMPU_LE_QB_DESC : CMP_EQ_QB_R2_DESC_BASE<"cmpu.le.qb", int_mips_cmpu_le_qb, NoItinerary, - DSPRegs>, IsCommutable; + DSPRegs>, Defs<[DSPCCond]>; class CMPGU_EQ_QB_DESC : CMP_EQ_QB_R3_DESC_BASE<"cmpgu.eq.qb", int_mips_cmpgu_eq_qb, @@ -769,222 +791,235 @@ class CMPGU_EQ_QB_DESC : CMP_EQ_QB_R3_DESC_BASE<"cmpgu.eq.qb", class CMPGU_LT_QB_DESC : CMP_EQ_QB_R3_DESC_BASE<"cmpgu.lt.qb", int_mips_cmpgu_lt_qb, - NoItinerary, CPURegs, DSPRegs>, - IsCommutable; + NoItinerary, CPURegs, DSPRegs>; class CMPGU_LE_QB_DESC : CMP_EQ_QB_R3_DESC_BASE<"cmpgu.le.qb", int_mips_cmpgu_le_qb, - NoItinerary, CPURegs, DSPRegs>, - IsCommutable; + NoItinerary, CPURegs, DSPRegs>; class CMP_EQ_PH_DESC : CMP_EQ_QB_R2_DESC_BASE<"cmp.eq.ph", int_mips_cmp_eq_ph, NoItinerary, DSPRegs>, - IsCommutable; + IsCommutable, Defs<[DSPCCond]>; class CMP_LT_PH_DESC : CMP_EQ_QB_R2_DESC_BASE<"cmp.lt.ph", int_mips_cmp_lt_ph, NoItinerary, DSPRegs>, - IsCommutable; + Defs<[DSPCCond]>; class CMP_LE_PH_DESC : CMP_EQ_QB_R2_DESC_BASE<"cmp.le.ph", int_mips_cmp_le_ph, NoItinerary, DSPRegs>, - IsCommutable; + Defs<[DSPCCond]>; // Misc class BITREV_DESC : ABSQ_S_PH_R2_DESC_BASE<"bitrev", int_mips_bitrev, - NoItinerary, CPURegs>, ClearDefs; + NoItinerary, CPURegs>; class PACKRL_PH_DESC : CMP_EQ_QB_R3_DESC_BASE<"packrl.ph", int_mips_packrl_ph, - NoItinerary, DSPRegs, DSPRegs>, - ClearDefs; + NoItinerary, DSPRegs, DSPRegs>; class REPL_QB_DESC : REPL_DESC_BASE<"repl.qb", int_mips_repl_qb, immZExt8, - NoItinerary, DSPRegs>, ClearDefs; + NoItinerary, DSPRegs>; class REPL_PH_DESC : REPL_DESC_BASE<"repl.ph", int_mips_repl_ph, immZExt10, - NoItinerary, DSPRegs>, ClearDefs; + NoItinerary, DSPRegs>; class REPLV_QB_DESC : ABSQ_S_PH_R2_DESC_BASE<"replv.qb", int_mips_repl_qb, - NoItinerary, DSPRegs, CPURegs>, - ClearDefs; + NoItinerary, DSPRegs, CPURegs>; class REPLV_PH_DESC : ABSQ_S_PH_R2_DESC_BASE<"replv.ph", int_mips_repl_ph, - NoItinerary, DSPRegs, CPURegs>, - ClearDefs; + NoItinerary, DSPRegs, CPURegs>; class PICK_QB_DESC : CMP_EQ_QB_R3_DESC_BASE<"pick.qb", int_mips_pick_qb, NoItinerary, DSPRegs, DSPRegs>, - ClearDefs, UseDSPCtrl; + Uses<[DSPCCond]>; class PICK_PH_DESC : CMP_EQ_QB_R3_DESC_BASE<"pick.ph", int_mips_pick_ph, NoItinerary, DSPRegs, DSPRegs>, - ClearDefs, UseDSPCtrl; + Uses<[DSPCCond]>; -class LWX_DESC : LX_DESC_BASE<"lwx", int_mips_lwx, NoItinerary>, ClearDefs; +class LWX_DESC : LX_DESC_BASE<"lwx", int_mips_lwx, NoItinerary>; -class LHX_DESC : LX_DESC_BASE<"lhx", int_mips_lhx, NoItinerary>, ClearDefs; +class LHX_DESC : LX_DESC_BASE<"lhx", int_mips_lhx, NoItinerary>; -class LBUX_DESC : LX_DESC_BASE<"lbux", int_mips_lbux, NoItinerary>, ClearDefs; +class LBUX_DESC : LX_DESC_BASE<"lbux", int_mips_lbux, NoItinerary>; class BPOSGE32_DESC : BPOSGE32_DESC_BASE<"bposge32", NoItinerary>; // Extr -class EXTP_DESC : EXTR_W_TY1_R1_DESC_BASE<"extp", MipsEXTP, NoItinerary>; +class EXTP_DESC : EXTR_W_TY1_R1_DESC_BASE<"extp", MipsEXTP, NoItinerary>, + Uses<[DSPPos]>, Defs<[DSPEFI]>; -class EXTPV_DESC : EXTR_W_TY1_R2_DESC_BASE<"extpv", MipsEXTP, NoItinerary>; +class EXTPV_DESC : EXTR_W_TY1_R2_DESC_BASE<"extpv", MipsEXTP, NoItinerary>, + Uses<[DSPPos]>, Defs<[DSPEFI]>; -class EXTPDP_DESC : EXTR_W_TY1_R1_DESC_BASE<"extpdp", MipsEXTPDP, NoItinerary>; +class EXTPDP_DESC : EXTR_W_TY1_R1_DESC_BASE<"extpdp", MipsEXTPDP, NoItinerary>, + Uses<[DSPPos]>, Defs<[DSPPos, DSPEFI]>; class EXTPDPV_DESC : EXTR_W_TY1_R2_DESC_BASE<"extpdpv", MipsEXTPDP, - NoItinerary>; + NoItinerary>, + Uses<[DSPPos]>, Defs<[DSPPos, DSPEFI]>; -class EXTR_W_DESC : EXTR_W_TY1_R1_DESC_BASE<"extr.w", MipsEXTR_W, NoItinerary>; +class EXTR_W_DESC : EXTR_W_TY1_R1_DESC_BASE<"extr.w", MipsEXTR_W, NoItinerary>, + Defs<[DSPOutFlag23]>; class EXTRV_W_DESC : EXTR_W_TY1_R2_DESC_BASE<"extrv.w", MipsEXTR_W, - NoItinerary>; + NoItinerary>, Defs<[DSPOutFlag23]>; class EXTR_R_W_DESC : EXTR_W_TY1_R1_DESC_BASE<"extr_r.w", MipsEXTR_R_W, - NoItinerary>; + NoItinerary>, + Defs<[DSPOutFlag23]>; class EXTRV_R_W_DESC : EXTR_W_TY1_R2_DESC_BASE<"extrv_r.w", MipsEXTR_R_W, - NoItinerary>; + NoItinerary>, + Defs<[DSPOutFlag23]>; class EXTR_RS_W_DESC : EXTR_W_TY1_R1_DESC_BASE<"extr_rs.w", MipsEXTR_RS_W, - NoItinerary>; + NoItinerary>, + Defs<[DSPOutFlag23]>; class EXTRV_RS_W_DESC : EXTR_W_TY1_R2_DESC_BASE<"extrv_rs.w", MipsEXTR_RS_W, - NoItinerary>; + NoItinerary>, + Defs<[DSPOutFlag23]>; class EXTR_S_H_DESC : EXTR_W_TY1_R1_DESC_BASE<"extr_s.h", MipsEXTR_S_H, - NoItinerary>; + NoItinerary>, + Defs<[DSPOutFlag23]>; class EXTRV_S_H_DESC : EXTR_W_TY1_R2_DESC_BASE<"extrv_s.h", MipsEXTR_S_H, - NoItinerary>; + NoItinerary>, + Defs<[DSPOutFlag23]>; class SHILO_DESC : SHILO_R1_DESC_BASE<"shilo", MipsSHILO>; class SHILOV_DESC : SHILO_R2_DESC_BASE<"shilov", MipsSHILO>; -class MTHLIP_DESC : MTHLIP_DESC_BASE<"mthlip", MipsMTHLIP>; +class MTHLIP_DESC : MTHLIP_DESC_BASE<"mthlip", MipsMTHLIP>, Defs<[DSPPos]>; class RDDSP_DESC : RDDSP_DESC_BASE<"rddsp", int_mips_rddsp, NoItinerary>; class WRDSP_DESC : WRDSP_DESC_BASE<"wrdsp", int_mips_wrdsp, NoItinerary>; -class INSV_DESC : INSV_DESC_BASE<"insv", int_mips_insv, NoItinerary>; +class INSV_DESC : INSV_DESC_BASE<"insv", int_mips_insv, NoItinerary>, + Uses<[DSPPos, DSPSCount]>; //===----------------------------------------------------------------------===// // MIPS DSP Rev 2 // Addition/subtraction class ADDU_PH_DESC : ADDU_QB_DESC_BASE<"addu.ph", int_mips_addu_ph, NoItinerary, - DSPRegs, DSPRegs>, IsCommutable; + DSPRegs, DSPRegs>, IsCommutable, + Defs<[DSPOutFlag20]>; class ADDU_S_PH_DESC : ADDU_QB_DESC_BASE<"addu_s.ph", int_mips_addu_s_ph, NoItinerary, DSPRegs, DSPRegs>, - IsCommutable; + IsCommutable, Defs<[DSPOutFlag20]>; class SUBU_PH_DESC : ADDU_QB_DESC_BASE<"subu.ph", int_mips_subu_ph, NoItinerary, - DSPRegs, DSPRegs>; + DSPRegs, DSPRegs>, + Defs<[DSPOutFlag20]>; class SUBU_S_PH_DESC : ADDU_QB_DESC_BASE<"subu_s.ph", int_mips_subu_s_ph, - NoItinerary, DSPRegs, DSPRegs>; + NoItinerary, DSPRegs, DSPRegs>, + Defs<[DSPOutFlag20]>; class ADDUH_QB_DESC : ADDUH_QB_DESC_BASE<"adduh.qb", int_mips_adduh_qb, - NoItinerary, DSPRegs>, - ClearDefs, IsCommutable; + NoItinerary, DSPRegs>, IsCommutable; class ADDUH_R_QB_DESC : ADDUH_QB_DESC_BASE<"adduh_r.qb", int_mips_adduh_r_qb, - NoItinerary, DSPRegs>, - ClearDefs, IsCommutable; + NoItinerary, DSPRegs>, IsCommutable; class SUBUH_QB_DESC : ADDUH_QB_DESC_BASE<"subuh.qb", int_mips_subuh_qb, - NoItinerary, DSPRegs>, ClearDefs; + NoItinerary, DSPRegs>; class SUBUH_R_QB_DESC : ADDUH_QB_DESC_BASE<"subuh_r.qb", int_mips_subuh_r_qb, - NoItinerary, DSPRegs>, ClearDefs; + NoItinerary, DSPRegs>; class ADDQH_PH_DESC : ADDUH_QB_DESC_BASE<"addqh.ph", int_mips_addqh_ph, - NoItinerary, DSPRegs>, - ClearDefs, IsCommutable; + NoItinerary, DSPRegs>, IsCommutable; class ADDQH_R_PH_DESC : ADDUH_QB_DESC_BASE<"addqh_r.ph", int_mips_addqh_r_ph, - NoItinerary, DSPRegs>, - ClearDefs, IsCommutable; + NoItinerary, DSPRegs>, IsCommutable; class SUBQH_PH_DESC : ADDUH_QB_DESC_BASE<"subqh.ph", int_mips_subqh_ph, - NoItinerary, DSPRegs>, ClearDefs; + NoItinerary, DSPRegs>; class SUBQH_R_PH_DESC : ADDUH_QB_DESC_BASE<"subqh_r.ph", int_mips_subqh_r_ph, - NoItinerary, DSPRegs>, ClearDefs; + NoItinerary, DSPRegs>; class ADDQH_W_DESC : ADDUH_QB_DESC_BASE<"addqh.w", int_mips_addqh_w, - NoItinerary, CPURegs>, - ClearDefs, IsCommutable; + NoItinerary, CPURegs>, IsCommutable; class ADDQH_R_W_DESC : ADDUH_QB_DESC_BASE<"addqh_r.w", int_mips_addqh_r_w, - NoItinerary, CPURegs>, - ClearDefs, IsCommutable; + NoItinerary, CPURegs>, IsCommutable; class SUBQH_W_DESC : ADDUH_QB_DESC_BASE<"subqh.w", int_mips_subqh_w, - NoItinerary, CPURegs>, ClearDefs; + NoItinerary, CPURegs>; class SUBQH_R_W_DESC : ADDUH_QB_DESC_BASE<"subqh_r.w", int_mips_subqh_r_w, - NoItinerary, CPURegs>, ClearDefs; + NoItinerary, CPURegs>; // Comparison class CMPGDU_EQ_QB_DESC : CMP_EQ_QB_R3_DESC_BASE<"cmpgdu.eq.qb", int_mips_cmpgdu_eq_qb, NoItinerary, CPURegs, DSPRegs>, - IsCommutable; + IsCommutable, Defs<[DSPCCond]>; class CMPGDU_LT_QB_DESC : CMP_EQ_QB_R3_DESC_BASE<"cmpgdu.lt.qb", int_mips_cmpgdu_lt_qb, NoItinerary, CPURegs, DSPRegs>, - IsCommutable; + Defs<[DSPCCond]>; class CMPGDU_LE_QB_DESC : CMP_EQ_QB_R3_DESC_BASE<"cmpgdu.le.qb", int_mips_cmpgdu_le_qb, NoItinerary, CPURegs, DSPRegs>, - IsCommutable; + Defs<[DSPCCond]>; // Absolute class ABSQ_S_QB_DESC : ABSQ_S_PH_R2_DESC_BASE<"absq_s.qb", int_mips_absq_s_qb, - NoItinerary, DSPRegs>; + NoItinerary, DSPRegs>, + Defs<[DSPOutFlag20]>; // Multiplication -class MUL_PH_DESC : ADDUH_QB_DESC_BASE<"mul.ph", int_mips_mul_ph, NoItinerary, - DSPRegs>, IsCommutable; +class MUL_PH_DESC : ADDUH_QB_DESC_BASE<"mul.ph", null_frag, NoItinerary, + DSPRegs>, IsCommutable, + Defs<[DSPOutFlag21]>; class MUL_S_PH_DESC : ADDUH_QB_DESC_BASE<"mul_s.ph", int_mips_mul_s_ph, - NoItinerary, DSPRegs>, IsCommutable; + NoItinerary, DSPRegs>, IsCommutable, + Defs<[DSPOutFlag21]>; class MULQ_S_W_DESC : ADDUH_QB_DESC_BASE<"mulq_s.w", int_mips_mulq_s_w, - NoItinerary, CPURegs>, IsCommutable; + NoItinerary, CPURegs>, IsCommutable, + Defs<[DSPOutFlag21]>; class MULQ_RS_W_DESC : ADDUH_QB_DESC_BASE<"mulq_rs.w", int_mips_mulq_rs_w, - NoItinerary, CPURegs>, IsCommutable; + NoItinerary, CPURegs>, IsCommutable, + Defs<[DSPOutFlag21]>; class MULQ_S_PH_DESC : ADDU_QB_DESC_BASE<"mulq_s.ph", int_mips_mulq_s_ph, NoItinerary, DSPRegs, DSPRegs>, - IsCommutable; + IsCommutable, Defs<[DSPOutFlag21]>; // Dot product with accumulate/subtract class DPA_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpa.w.ph", MipsDPA_W_PH>; class DPS_W_PH_DESC : DPA_W_PH_DESC_BASE<"dps.w.ph", MipsDPS_W_PH>; -class DPAQX_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpaqx_s.w.ph", MipsDPAQX_S_W_PH>; +class DPAQX_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpaqx_s.w.ph", MipsDPAQX_S_W_PH>, + Defs<[DSPOutFlag16_19]>; class DPAQX_SA_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpaqx_sa.w.ph", - MipsDPAQX_SA_W_PH>; + MipsDPAQX_SA_W_PH>, + Defs<[DSPOutFlag16_19]>; class DPAX_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpax.w.ph", MipsDPAX_W_PH>; class DPSX_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpsx.w.ph", MipsDPSX_W_PH>; -class DPSQX_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpsqx_s.w.ph", MipsDPSQX_S_W_PH>; +class DPSQX_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpsqx_s.w.ph", MipsDPSQX_S_W_PH>, + Defs<[DSPOutFlag16_19]>; class DPSQX_SA_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpsqx_sa.w.ph", - MipsDPSQX_SA_W_PH>; + MipsDPSQX_SA_W_PH>, + Defs<[DSPOutFlag16_19]>; class MULSA_W_PH_DESC : DPA_W_PH_DESC_BASE<"mulsa.w.ph", MipsMULSA_W_PH>; @@ -996,45 +1031,45 @@ class PRECR_QB_PH_DESC : CMP_EQ_QB_R3_DESC_BASE<"precr.qb.ph", class PRECR_SRA_PH_W_DESC : PRECR_SRA_PH_W_DESC_BASE<"precr_sra.ph.w", int_mips_precr_sra_ph_w, NoItinerary, DSPRegs, - CPURegs>, ClearDefs; + CPURegs>; class PRECR_SRA_R_PH_W_DESC : PRECR_SRA_PH_W_DESC_BASE<"precr_sra_r.ph.w", int_mips_precr_sra_r_ph_w, NoItinerary, DSPRegs, - CPURegs>, ClearDefs; + CPURegs>; // Shift -class SHRA_QB_DESC : SHLL_QB_R2_DESC_BASE<"shra.qb", int_mips_shra_qb, immZExt3, - NoItinerary, DSPRegs>, ClearDefs; +class SHRA_QB_DESC : SHLL_QB_R2_DESC_BASE<"shra.qb", null_frag, immZExt3, + NoItinerary, DSPRegs>; class SHRAV_QB_DESC : SHLL_QB_R3_DESC_BASE<"shrav.qb", int_mips_shra_qb, - NoItinerary, DSPRegs>, ClearDefs; + NoItinerary, DSPRegs>; class SHRA_R_QB_DESC : SHLL_QB_R2_DESC_BASE<"shra_r.qb", int_mips_shra_r_qb, - immZExt3, NoItinerary, DSPRegs>, - ClearDefs; + immZExt3, NoItinerary, DSPRegs>; class SHRAV_R_QB_DESC : SHLL_QB_R3_DESC_BASE<"shrav_r.qb", int_mips_shra_r_qb, - NoItinerary, DSPRegs>, ClearDefs; + NoItinerary, DSPRegs>; -class SHRL_PH_DESC : SHLL_QB_R2_DESC_BASE<"shrl.ph", int_mips_shrl_ph, immZExt4, - NoItinerary, DSPRegs>, ClearDefs; +class SHRL_PH_DESC : SHLL_QB_R2_DESC_BASE<"shrl.ph", null_frag, immZExt4, + NoItinerary, DSPRegs>; class SHRLV_PH_DESC : SHLL_QB_R3_DESC_BASE<"shrlv.ph", int_mips_shrl_ph, - NoItinerary, DSPRegs>, ClearDefs; + NoItinerary, DSPRegs>; // Misc class APPEND_DESC : APPEND_DESC_BASE<"append", int_mips_append, immZExt5, - NoItinerary>, ClearDefs; + NoItinerary>; class BALIGN_DESC : APPEND_DESC_BASE<"balign", int_mips_balign, immZExt2, - NoItinerary>, ClearDefs; + NoItinerary>; class PREPEND_DESC : APPEND_DESC_BASE<"prepend", int_mips_prepend, immZExt5, - NoItinerary>, ClearDefs; + NoItinerary>; // Pseudos. -def BPOSGE32_PSEUDO : BPOSGE32_PSEUDO_DESC_BASE<int_mips_bposge32, NoItinerary>; +def BPOSGE32_PSEUDO : BPOSGE32_PSEUDO_DESC_BASE<int_mips_bposge32, + NoItinerary>, Uses<[DSPPos]>; // Instruction defs. // MIPS DSP Rev 1 @@ -1094,6 +1129,10 @@ def MAQ_S_W_PHL : MAQ_S_W_PHL_ENC, MAQ_S_W_PHL_DESC; def MAQ_S_W_PHR : MAQ_S_W_PHR_ENC, MAQ_S_W_PHR_DESC; def MAQ_SA_W_PHL : MAQ_SA_W_PHL_ENC, MAQ_SA_W_PHL_DESC; def MAQ_SA_W_PHR : MAQ_SA_W_PHR_ENC, MAQ_SA_W_PHR_DESC; +def MFHI_DSP : MFHI_ENC, MFHI_DESC; +def MFLO_DSP : MFLO_ENC, MFLO_DESC; +def MTHI_DSP : MTHI_ENC, MTHI_DESC; +def MTLO_DSP : MTLO_ENC, MTLO_DESC; def DPAU_H_QBL : DPAU_H_QBL_ENC, DPAU_H_QBL_DESC; def DPAU_H_QBR : DPAU_H_QBR_ENC, DPAU_H_QBR_DESC; def DPSU_H_QBL : DPSU_H_QBL_ENC, DPSU_H_QBL_DESC; @@ -1201,13 +1240,35 @@ def PREPEND : PREPEND_ENC, PREPEND_DESC; } // Pseudos. -/// Pseudo instructions for loading, storing and copying accumulator registers. let isPseudo = 1 in { + // Pseudo instructions for loading and storing accumulator registers. defm LOAD_AC_DSP : LoadM<"load_ac_dsp", ACRegsDSP>; defm STORE_AC_DSP : StoreM<"store_ac_dsp", ACRegsDSP>; + + // Pseudos for loading and storing ccond field of DSP control register. + defm LOAD_CCOND_DSP : LoadM<"load_ccond_dsp", DSPCC>; + defm STORE_CCOND_DSP : StoreM<"store_ccond_dsp", DSPCC>; } -def COPY_AC_DSP : PseudoSE<(outs ACRegsDSP:$dst), (ins ACRegsDSP:$src), []>; +// Pseudo CMP and PICK instructions. +class PseudoCMP<Instruction RealInst> : + PseudoDSP<(outs DSPCC:$cmp), (ins DSPRegs:$rs, DSPRegs:$rt), []>, + PseudoInstExpansion<(RealInst DSPRegs:$rs, DSPRegs:$rt)>, NeverHasSideEffects; + +class PseudoPICK<Instruction RealInst> : + PseudoDSP<(outs DSPRegs:$rd), (ins DSPCC:$cmp, DSPRegs:$rs, DSPRegs:$rt), []>, + PseudoInstExpansion<(RealInst DSPRegs:$rd, DSPRegs:$rs, DSPRegs:$rt)>, + NeverHasSideEffects; + +def PseudoCMP_EQ_PH : PseudoCMP<CMP_EQ_PH>; +def PseudoCMP_LT_PH : PseudoCMP<CMP_LT_PH>; +def PseudoCMP_LE_PH : PseudoCMP<CMP_LE_PH>; +def PseudoCMPU_EQ_QB : PseudoCMP<CMPU_EQ_QB>; +def PseudoCMPU_LT_QB : PseudoCMP<CMPU_LT_QB>; +def PseudoCMPU_LE_QB : PseudoCMP<CMPU_LE_QB>; + +def PseudoPICK_PH : PseudoPICK<PICK_PH>; +def PseudoPICK_QB : PseudoPICK<PICK_QB>; // Patterns. class DSPPat<dag pattern, dag result, Predicate pred = HasDSP> : @@ -1232,6 +1293,95 @@ def : DSPPat<(store (v2i16 DSPRegs:$val), addr:$a), def : DSPPat<(store (v4i8 DSPRegs:$val), addr:$a), (SW (COPY_TO_REGCLASS DSPRegs:$val, CPURegs), addr:$a)>; +// Binary operations. +class DSPBinPat<Instruction Inst, ValueType ValTy, SDPatternOperator Node, + Predicate Pred = HasDSP> : + DSPPat<(Node ValTy:$a, ValTy:$b), (Inst ValTy:$a, ValTy:$b), Pred>; + +def : DSPBinPat<ADDQ_PH, v2i16, int_mips_addq_ph>; +def : DSPBinPat<ADDQ_PH, v2i16, add>; +def : DSPBinPat<SUBQ_PH, v2i16, int_mips_subq_ph>; +def : DSPBinPat<SUBQ_PH, v2i16, sub>; +def : DSPBinPat<MUL_PH, v2i16, int_mips_mul_ph, HasDSPR2>; +def : DSPBinPat<MUL_PH, v2i16, mul, HasDSPR2>; +def : DSPBinPat<ADDU_QB, v4i8, int_mips_addu_qb>; +def : DSPBinPat<ADDU_QB, v4i8, add>; +def : DSPBinPat<SUBU_QB, v4i8, int_mips_subu_qb>; +def : DSPBinPat<SUBU_QB, v4i8, sub>; +def : DSPBinPat<ADDSC, i32, int_mips_addsc>; +def : DSPBinPat<ADDSC, i32, addc>; +def : DSPBinPat<ADDWC, i32, int_mips_addwc>; +def : DSPBinPat<ADDWC, i32, adde>; + +// Shift immediate patterns. +class DSPShiftPat<Instruction Inst, ValueType ValTy, SDPatternOperator Node, + SDPatternOperator Imm, Predicate Pred = HasDSP> : + DSPPat<(Node ValTy:$a, Imm:$shamt), (Inst ValTy:$a, Imm:$shamt), Pred>; + +def : DSPShiftPat<SHLL_PH, v2i16, MipsSHLL_DSP, imm>; +def : DSPShiftPat<SHRA_PH, v2i16, MipsSHRA_DSP, imm>; +def : DSPShiftPat<SHRL_PH, v2i16, MipsSHRL_DSP, imm, HasDSPR2>; +def : DSPShiftPat<SHLL_PH, v2i16, int_mips_shll_ph, immZExt4>; +def : DSPShiftPat<SHRA_PH, v2i16, int_mips_shra_ph, immZExt4>; +def : DSPShiftPat<SHRL_PH, v2i16, int_mips_shrl_ph, immZExt4, HasDSPR2>; +def : DSPShiftPat<SHLL_QB, v4i8, MipsSHLL_DSP, imm>; +def : DSPShiftPat<SHRA_QB, v4i8, MipsSHRA_DSP, imm, HasDSPR2>; +def : DSPShiftPat<SHRL_QB, v4i8, MipsSHRL_DSP, imm>; +def : DSPShiftPat<SHLL_QB, v4i8, int_mips_shll_qb, immZExt3>; +def : DSPShiftPat<SHRA_QB, v4i8, int_mips_shra_qb, immZExt3, HasDSPR2>; +def : DSPShiftPat<SHRL_QB, v4i8, int_mips_shrl_qb, immZExt3>; + +// SETCC/SELECT_CC patterns. +class DSPSetCCPat<Instruction Cmp, Instruction Pick, ValueType ValTy, + CondCode CC> : + DSPPat<(ValTy (MipsSETCC_DSP ValTy:$a, ValTy:$b, CC)), + (ValTy (Pick (ValTy (Cmp ValTy:$a, ValTy:$b)), + (ValTy (COPY_TO_REGCLASS (ADDiu ZERO, -1), DSPRegs)), + (ValTy ZERO)))>; + +class DSPSetCCPatInv<Instruction Cmp, Instruction Pick, ValueType ValTy, + CondCode CC> : + DSPPat<(ValTy (MipsSETCC_DSP ValTy:$a, ValTy:$b, CC)), + (ValTy (Pick (ValTy (Cmp ValTy:$a, ValTy:$b)), + (ValTy ZERO), + (ValTy (COPY_TO_REGCLASS (ADDiu ZERO, -1), DSPRegs))))>; + +class DSPSelectCCPat<Instruction Cmp, Instruction Pick, ValueType ValTy, + CondCode CC> : + DSPPat<(ValTy (MipsSELECT_CC_DSP ValTy:$a, ValTy:$b, ValTy:$c, ValTy:$d, CC)), + (ValTy (Pick (ValTy (Cmp ValTy:$a, ValTy:$b)), $c, $d))>; + +class DSPSelectCCPatInv<Instruction Cmp, Instruction Pick, ValueType ValTy, + CondCode CC> : + DSPPat<(ValTy (MipsSELECT_CC_DSP ValTy:$a, ValTy:$b, ValTy:$c, ValTy:$d, CC)), + (ValTy (Pick (ValTy (Cmp ValTy:$a, ValTy:$b)), $d, $c))>; + +def : DSPSetCCPat<PseudoCMP_EQ_PH, PseudoPICK_PH, v2i16, SETEQ>; +def : DSPSetCCPat<PseudoCMP_LT_PH, PseudoPICK_PH, v2i16, SETLT>; +def : DSPSetCCPat<PseudoCMP_LE_PH, PseudoPICK_PH, v2i16, SETLE>; +def : DSPSetCCPatInv<PseudoCMP_EQ_PH, PseudoPICK_PH, v2i16, SETNE>; +def : DSPSetCCPatInv<PseudoCMP_LT_PH, PseudoPICK_PH, v2i16, SETGE>; +def : DSPSetCCPatInv<PseudoCMP_LE_PH, PseudoPICK_PH, v2i16, SETGT>; +def : DSPSetCCPat<PseudoCMPU_EQ_QB, PseudoPICK_QB, v4i8, SETEQ>; +def : DSPSetCCPat<PseudoCMPU_LT_QB, PseudoPICK_QB, v4i8, SETULT>; +def : DSPSetCCPat<PseudoCMPU_LE_QB, PseudoPICK_QB, v4i8, SETULE>; +def : DSPSetCCPatInv<PseudoCMPU_EQ_QB, PseudoPICK_QB, v4i8, SETNE>; +def : DSPSetCCPatInv<PseudoCMPU_LT_QB, PseudoPICK_QB, v4i8, SETUGE>; +def : DSPSetCCPatInv<PseudoCMPU_LE_QB, PseudoPICK_QB, v4i8, SETUGT>; + +def : DSPSelectCCPat<PseudoCMP_EQ_PH, PseudoPICK_PH, v2i16, SETEQ>; +def : DSPSelectCCPat<PseudoCMP_LT_PH, PseudoPICK_PH, v2i16, SETLT>; +def : DSPSelectCCPat<PseudoCMP_LE_PH, PseudoPICK_PH, v2i16, SETLE>; +def : DSPSelectCCPatInv<PseudoCMP_EQ_PH, PseudoPICK_PH, v2i16, SETNE>; +def : DSPSelectCCPatInv<PseudoCMP_LT_PH, PseudoPICK_PH, v2i16, SETGE>; +def : DSPSelectCCPatInv<PseudoCMP_LE_PH, PseudoPICK_PH, v2i16, SETGT>; +def : DSPSelectCCPat<PseudoCMPU_EQ_QB, PseudoPICK_QB, v4i8, SETEQ>; +def : DSPSelectCCPat<PseudoCMPU_LT_QB, PseudoPICK_QB, v4i8, SETULT>; +def : DSPSelectCCPat<PseudoCMPU_LE_QB, PseudoPICK_QB, v4i8, SETULE>; +def : DSPSelectCCPatInv<PseudoCMPU_EQ_QB, PseudoPICK_QB, v4i8, SETNE>; +def : DSPSelectCCPatInv<PseudoCMPU_LT_QB, PseudoPICK_QB, v4i8, SETUGE>; +def : DSPSelectCCPatInv<PseudoCMPU_LE_QB, PseudoPICK_QB, v4i8, SETUGT>; + // Extr patterns. class EXTR_W_TY1_R2_Pat<SDPatternOperator OpNode, Instruction Instr> : DSPPat<(i32 (OpNode CPURegs:$rs, ACRegsDSP:$ac)), diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp index 77b08cb..968e536 100644 --- a/lib/Target/Mips/MipsISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -17,7 +17,6 @@ #include "MipsSEISelDAGToDAG.h" #include "Mips.h" #include "MCTargetDesc/MipsBaseInfo.h" -#include "MipsAnalyzeImmediate.h" #include "MipsMachineFunction.h" #include "MipsRegisterInfo.h" #include "llvm/CodeGen/MachineConstantPool.h" diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index e2219f2..4d76181 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -30,7 +30,6 @@ #include "llvm/IR/CallingConv.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/GlobalVariable.h" -#include "llvm/IR/Intrinsics.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" @@ -198,6 +197,11 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { case MipsISD::MADDU_DSP: return "MipsISD::MADDU_DSP"; case MipsISD::MSUB_DSP: return "MipsISD::MSUB_DSP"; case MipsISD::MSUBU_DSP: return "MipsISD::MSUBU_DSP"; + case MipsISD::SHLL_DSP: return "MipsISD::SHLL_DSP"; + case MipsISD::SHRA_DSP: return "MipsISD::SHRA_DSP"; + case MipsISD::SHRL_DSP: return "MipsISD::SHRL_DSP"; + case MipsISD::SETCC_DSP: return "MipsISD::SETCC_DSP"; + case MipsISD::SELECT_CC_DSP: return "MipsISD::SELECT_CC_DSP"; default: return NULL; } } @@ -211,7 +215,7 @@ MipsTargetLowering(MipsTargetMachine &TM) // Mips does not have i1 type, so use i32 for // setcc operations results (slt, sgt, ...). setBooleanContents(ZeroOrOneBooleanContent); - setBooleanVectorContents(ZeroOrOneBooleanContent); // FIXME: Is this correct? + setBooleanVectorContents(ZeroOrNegativeOneBooleanContent); // Load extented operations for i1 types must be promoted setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote); @@ -346,9 +350,6 @@ MipsTargetLowering(MipsTargetMachine &TM) setOperationAction(ISD::VACOPY, MVT::Other, Expand); setOperationAction(ISD::VAEND, MVT::Other, Expand); - setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::i64, Custom); - setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::i64, Custom); - // Use the default for now setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); @@ -449,7 +450,7 @@ static SDValue performDivRemCombine(SDNode *N, SelectionDAG &DAG, return SDValue(); } -static Mips::CondCode FPCondCCodeToFCC(ISD::CondCode CC) { +static Mips::CondCode condCodeToFCC(ISD::CondCode CC) { switch (CC) { default: llvm_unreachable("Unknown fp condition code!"); case ISD::SETEQ: @@ -508,7 +509,7 @@ static SDValue createFPCmp(SelectionDAG &DAG, const SDValue &Op) { ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get(); return DAG.getNode(MipsISD::FPCmp, DL, MVT::Glue, LHS, RHS, - DAG.getConstant(FPCondCCodeToFCC(CC), MVT::i32)); + DAG.getConstant(condCodeToFCC(CC), MVT::i32)); } // Creates and returns a CMovFPT/F node. @@ -712,10 +713,7 @@ void MipsTargetLowering::ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results, SelectionDAG &DAG) const { - SDValue Res = LowerOperation(SDValue(N, 0), DAG); - - for (unsigned I = 0, E = Res->getNumValues(); I != E; ++I) - Results.push_back(Res.getValue(I)); + return LowerOperationWrapper(N, Results, DAG); } SDValue MipsTargetLowering:: @@ -739,15 +737,12 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const case ISD::FRAMEADDR: return lowerFRAMEADDR(Op, DAG); case ISD::RETURNADDR: return lowerRETURNADDR(Op, DAG); case ISD::EH_RETURN: return lowerEH_RETURN(Op, DAG); - case ISD::MEMBARRIER: return lowerMEMBARRIER(Op, DAG); case ISD::ATOMIC_FENCE: return lowerATOMIC_FENCE(Op, DAG); case ISD::SHL_PARTS: return lowerShiftLeftParts(Op, DAG); case ISD::SRA_PARTS: return lowerShiftRightParts(Op, DAG, true); case ISD::SRL_PARTS: return lowerShiftRightParts(Op, DAG, false); case ISD::LOAD: return lowerLOAD(Op, DAG); case ISD::STORE: return lowerSTORE(Op, DAG); - case ISD::INTRINSIC_WO_CHAIN: return lowerINTRINSIC_WO_CHAIN(Op, DAG); - case ISD::INTRINSIC_W_CHAIN: return lowerINTRINSIC_W_CHAIN(Op, DAG); case ISD::ADD: return lowerADD(Op, DAG); } return SDValue(); @@ -1827,15 +1822,6 @@ SDValue MipsTargetLowering::lowerEH_RETURN(SDValue Op, SelectionDAG &DAG) Chain.getValue(1)); } -// TODO: set SType according to the desired memory barrier behavior. -SDValue -MipsTargetLowering::lowerMEMBARRIER(SDValue Op, SelectionDAG &DAG) const { - unsigned SType = 0; - DebugLoc DL = Op.getDebugLoc(); - return DAG.getNode(MipsISD::Sync, DL, MVT::Other, Op.getOperand(0), - DAG.getConstant(SType, MVT::i32)); -} - SDValue MipsTargetLowering::lowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG) const { // FIXME: Need pseudo-fence for 'singlethread' fences @@ -1918,7 +1904,7 @@ SDValue MipsTargetLowering::lowerShiftRightParts(SDValue Op, SelectionDAG &DAG, return DAG.getMergeValues(Ops, 2, DL); } -static SDValue CreateLoadLR(unsigned Opc, SelectionDAG &DAG, LoadSDNode *LD, +static SDValue createLoadLR(unsigned Opc, SelectionDAG &DAG, LoadSDNode *LD, SDValue Chain, SDValue Src, unsigned Offset) { SDValue Ptr = LD->getBasePtr(); EVT VT = LD->getValueType(0), MemVT = LD->getMemoryVT(); @@ -1958,15 +1944,15 @@ SDValue MipsTargetLowering::lowerLOAD(SDValue Op, SelectionDAG &DAG) const { // (set tmp, (ldl (add baseptr, 7), undef)) // (set dst, (ldr baseptr, tmp)) if ((VT == MVT::i64) && (ExtType == ISD::NON_EXTLOAD)) { - SDValue LDL = CreateLoadLR(MipsISD::LDL, DAG, LD, Chain, Undef, + SDValue LDL = createLoadLR(MipsISD::LDL, DAG, LD, Chain, Undef, IsLittle ? 7 : 0); - return CreateLoadLR(MipsISD::LDR, DAG, LD, LDL.getValue(1), LDL, + return createLoadLR(MipsISD::LDR, DAG, LD, LDL.getValue(1), LDL, IsLittle ? 0 : 7); } - SDValue LWL = CreateLoadLR(MipsISD::LWL, DAG, LD, Chain, Undef, + SDValue LWL = createLoadLR(MipsISD::LWL, DAG, LD, Chain, Undef, IsLittle ? 3 : 0); - SDValue LWR = CreateLoadLR(MipsISD::LWR, DAG, LD, LWL.getValue(1), LWL, + SDValue LWR = createLoadLR(MipsISD::LWR, DAG, LD, LWL.getValue(1), LWL, IsLittle ? 0 : 3); // Expand @@ -1997,7 +1983,7 @@ SDValue MipsTargetLowering::lowerLOAD(SDValue Op, SelectionDAG &DAG) const { return DAG.getMergeValues(Ops, 2, DL); } -static SDValue CreateStoreLR(unsigned Opc, SelectionDAG &DAG, StoreSDNode *SD, +static SDValue createStoreLR(unsigned Opc, SelectionDAG &DAG, StoreSDNode *SD, SDValue Chain, unsigned Offset) { SDValue Ptr = SD->getBasePtr(), Value = SD->getValue(); EVT MemVT = SD->getMemoryVT(), BasePtrVT = Ptr.getValueType(); @@ -2034,9 +2020,9 @@ SDValue MipsTargetLowering::lowerSTORE(SDValue Op, SelectionDAG &DAG) const { // (swl val, (add baseptr, 3)) // (swr val, baseptr) if ((VT == MVT::i32) || SD->isTruncatingStore()) { - SDValue SWL = CreateStoreLR(MipsISD::SWL, DAG, SD, Chain, + SDValue SWL = createStoreLR(MipsISD::SWL, DAG, SD, Chain, IsLittle ? 3 : 0); - return CreateStoreLR(MipsISD::SWR, DAG, SD, SWL, IsLittle ? 0 : 3); + return createStoreLR(MipsISD::SWR, DAG, SD, SWL, IsLittle ? 0 : 3); } assert(VT == MVT::i64); @@ -2046,172 +2032,8 @@ SDValue MipsTargetLowering::lowerSTORE(SDValue Op, SelectionDAG &DAG) const { // to // (sdl val, (add baseptr, 7)) // (sdr val, baseptr) - SDValue SDL = CreateStoreLR(MipsISD::SDL, DAG, SD, Chain, IsLittle ? 7 : 0); - return CreateStoreLR(MipsISD::SDR, DAG, SD, SDL, IsLittle ? 0 : 7); -} - -static SDValue initAccumulator(SDValue In, DebugLoc DL, SelectionDAG &DAG) { - SDValue InLo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, In, - DAG.getConstant(0, MVT::i32)); - SDValue InHi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, In, - DAG.getConstant(1, MVT::i32)); - return DAG.getNode(MipsISD::InsertLOHI, DL, MVT::Untyped, InLo, InHi); -} - -static SDValue extractLOHI(SDValue Op, DebugLoc DL, SelectionDAG &DAG) { - SDValue Lo = DAG.getNode(MipsISD::ExtractLOHI, DL, MVT::i32, Op, - DAG.getConstant(Mips::sub_lo, MVT::i32)); - SDValue Hi = DAG.getNode(MipsISD::ExtractLOHI, DL, MVT::i32, Op, - DAG.getConstant(Mips::sub_hi, MVT::i32)); - return DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, Lo, Hi); -} - -// This function expands mips intrinsic nodes which have 64-bit input operands -// or output values. -// -// out64 = intrinsic-node in64 -// => -// lo = copy (extract-element (in64, 0)) -// hi = copy (extract-element (in64, 1)) -// mips-specific-node -// v0 = copy lo -// v1 = copy hi -// out64 = merge-values (v0, v1) -// -static SDValue lowerDSPIntr(SDValue Op, SelectionDAG &DAG, unsigned Opc) { - DebugLoc DL = Op.getDebugLoc(); - bool HasChainIn = Op->getOperand(0).getValueType() == MVT::Other; - SmallVector<SDValue, 3> Ops; - unsigned OpNo = 0; - - // See if Op has a chain input. - if (HasChainIn) - Ops.push_back(Op->getOperand(OpNo++)); - - // The next operand is the intrinsic opcode. - assert(Op->getOperand(OpNo).getOpcode() == ISD::TargetConstant); - - // See if the next operand has type i64. - SDValue Opnd = Op->getOperand(++OpNo), In64; - - if (Opnd.getValueType() == MVT::i64) - In64 = initAccumulator(Opnd, DL, DAG); - else - Ops.push_back(Opnd); - - // Push the remaining operands. - for (++OpNo ; OpNo < Op->getNumOperands(); ++OpNo) - Ops.push_back(Op->getOperand(OpNo)); - - // Add In64 to the end of the list. - if (In64.getNode()) - Ops.push_back(In64); - - // Scan output. - SmallVector<EVT, 2> ResTys; - - for (SDNode::value_iterator I = Op->value_begin(), E = Op->value_end(); - I != E; ++I) - ResTys.push_back((*I == MVT::i64) ? MVT::Untyped : *I); - - // Create node. - SDValue Val = DAG.getNode(Opc, DL, ResTys, &Ops[0], Ops.size()); - SDValue Out = (ResTys[0] == MVT::Untyped) ? extractLOHI(Val, DL, DAG) : Val; - - if (!HasChainIn) - return Out; - - assert(Val->getValueType(1) == MVT::Other); - SDValue Vals[] = { Out, SDValue(Val.getNode(), 1) }; - return DAG.getMergeValues(Vals, 2, DL); -} - -SDValue MipsTargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op, - SelectionDAG &DAG) const { - switch (cast<ConstantSDNode>(Op->getOperand(0))->getZExtValue()) { - default: - return SDValue(); - case Intrinsic::mips_shilo: - return lowerDSPIntr(Op, DAG, MipsISD::SHILO); - case Intrinsic::mips_dpau_h_qbl: - return lowerDSPIntr(Op, DAG, MipsISD::DPAU_H_QBL); - case Intrinsic::mips_dpau_h_qbr: - return lowerDSPIntr(Op, DAG, MipsISD::DPAU_H_QBR); - case Intrinsic::mips_dpsu_h_qbl: - return lowerDSPIntr(Op, DAG, MipsISD::DPSU_H_QBL); - case Intrinsic::mips_dpsu_h_qbr: - return lowerDSPIntr(Op, DAG, MipsISD::DPSU_H_QBR); - case Intrinsic::mips_dpa_w_ph: - return lowerDSPIntr(Op, DAG, MipsISD::DPA_W_PH); - case Intrinsic::mips_dps_w_ph: - return lowerDSPIntr(Op, DAG, MipsISD::DPS_W_PH); - case Intrinsic::mips_dpax_w_ph: - return lowerDSPIntr(Op, DAG, MipsISD::DPAX_W_PH); - case Intrinsic::mips_dpsx_w_ph: - return lowerDSPIntr(Op, DAG, MipsISD::DPSX_W_PH); - case Intrinsic::mips_mulsa_w_ph: - return lowerDSPIntr(Op, DAG, MipsISD::MULSA_W_PH); - case Intrinsic::mips_mult: - return lowerDSPIntr(Op, DAG, MipsISD::Mult); - case Intrinsic::mips_multu: - return lowerDSPIntr(Op, DAG, MipsISD::Multu); - case Intrinsic::mips_madd: - return lowerDSPIntr(Op, DAG, MipsISD::MAdd); - case Intrinsic::mips_maddu: - return lowerDSPIntr(Op, DAG, MipsISD::MAddu); - case Intrinsic::mips_msub: - return lowerDSPIntr(Op, DAG, MipsISD::MSub); - case Intrinsic::mips_msubu: - return lowerDSPIntr(Op, DAG, MipsISD::MSubu); - } -} - -SDValue MipsTargetLowering::lowerINTRINSIC_W_CHAIN(SDValue Op, - SelectionDAG &DAG) const { - switch (cast<ConstantSDNode>(Op->getOperand(1))->getZExtValue()) { - default: - return SDValue(); - case Intrinsic::mips_extp: - return lowerDSPIntr(Op, DAG, MipsISD::EXTP); - case Intrinsic::mips_extpdp: - return lowerDSPIntr(Op, DAG, MipsISD::EXTPDP); - case Intrinsic::mips_extr_w: - return lowerDSPIntr(Op, DAG, MipsISD::EXTR_W); - case Intrinsic::mips_extr_r_w: - return lowerDSPIntr(Op, DAG, MipsISD::EXTR_R_W); - case Intrinsic::mips_extr_rs_w: - return lowerDSPIntr(Op, DAG, MipsISD::EXTR_RS_W); - case Intrinsic::mips_extr_s_h: - return lowerDSPIntr(Op, DAG, MipsISD::EXTR_S_H); - case Intrinsic::mips_mthlip: - return lowerDSPIntr(Op, DAG, MipsISD::MTHLIP); - case Intrinsic::mips_mulsaq_s_w_ph: - return lowerDSPIntr(Op, DAG, MipsISD::MULSAQ_S_W_PH); - case Intrinsic::mips_maq_s_w_phl: - return lowerDSPIntr(Op, DAG, MipsISD::MAQ_S_W_PHL); - case Intrinsic::mips_maq_s_w_phr: - return lowerDSPIntr(Op, DAG, MipsISD::MAQ_S_W_PHR); - case Intrinsic::mips_maq_sa_w_phl: - return lowerDSPIntr(Op, DAG, MipsISD::MAQ_SA_W_PHL); - case Intrinsic::mips_maq_sa_w_phr: - return lowerDSPIntr(Op, DAG, MipsISD::MAQ_SA_W_PHR); - case Intrinsic::mips_dpaq_s_w_ph: - return lowerDSPIntr(Op, DAG, MipsISD::DPAQ_S_W_PH); - case Intrinsic::mips_dpsq_s_w_ph: - return lowerDSPIntr(Op, DAG, MipsISD::DPSQ_S_W_PH); - case Intrinsic::mips_dpaq_sa_l_w: - return lowerDSPIntr(Op, DAG, MipsISD::DPAQ_SA_L_W); - case Intrinsic::mips_dpsq_sa_l_w: - return lowerDSPIntr(Op, DAG, MipsISD::DPSQ_SA_L_W); - case Intrinsic::mips_dpaqx_s_w_ph: - return lowerDSPIntr(Op, DAG, MipsISD::DPAQX_S_W_PH); - case Intrinsic::mips_dpaqx_sa_w_ph: - return lowerDSPIntr(Op, DAG, MipsISD::DPAQX_SA_W_PH); - case Intrinsic::mips_dpsqx_s_w_ph: - return lowerDSPIntr(Op, DAG, MipsISD::DPSQX_S_W_PH); - case Intrinsic::mips_dpsqx_sa_w_ph: - return lowerDSPIntr(Op, DAG, MipsISD::DPSQX_SA_W_PH); - } + SDValue SDL = createStoreLR(MipsISD::SDL, DAG, SD, Chain, IsLittle ? 7 : 0); + return createStoreLR(MipsISD::SDR, DAG, SD, SDL, IsLittle ? 0 : 7); } SDValue MipsTargetLowering::lowerADD(SDValue Op, SelectionDAG &DAG) const { @@ -3009,8 +2831,8 @@ getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const return std::make_pair((unsigned)Mips::T9_64, &Mips::CPU64RegsRegClass); case 'l': // register suitable for indirect jump if (VT == MVT::i32) - return std::make_pair((unsigned)Mips::LO, &Mips::HILORegClass); - return std::make_pair((unsigned)Mips::LO64, &Mips::HILO64RegClass); + return std::make_pair((unsigned)Mips::LO, &Mips::LORegsRegClass); + return std::make_pair((unsigned)Mips::LO64, &Mips::LORegs64RegClass); case 'x': // register suitable for indirect jump // Fixme: Not triggering the use of both hi and low // This will generate an error message diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index cab71a6..5587e8f 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -143,6 +143,15 @@ namespace llvm { MSUB_DSP, MSUBU_DSP, + // DSP shift nodes. + SHLL_DSP, + SHRA_DSP, + SHRL_DSP, + + // DSP setcc and select_cc nodes. + SETCC_DSP, + SELECT_CC_DSP, + // Load/Store Left/Right nodes. LWL = ISD::FIRST_TARGET_MEMORY_OPCODE, LWR, @@ -338,15 +347,12 @@ namespace llvm { SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const; SDValue lowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerMEMBARRIER(SDValue Op, SelectionDAG& DAG) const; SDValue lowerATOMIC_FENCE(SDValue Op, SelectionDAG& DAG) const; SDValue lowerShiftLeftParts(SDValue Op, SelectionDAG& DAG) const; SDValue lowerShiftRightParts(SDValue Op, SelectionDAG& DAG, bool IsSRA) const; SDValue lowerLOAD(SDValue Op, SelectionDAG &DAG) const; SDValue lowerSTORE(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerINTRINSIC_W_CHAIN(SDValue Op, SelectionDAG &DAG) const; SDValue lowerADD(SDValue Op, SelectionDAG &DAG) const; /// isEligibleForTailCallOptimization - Check whether the call is eligible diff --git a/lib/Target/Mips/MipsInstrFormats.td b/lib/Target/Mips/MipsInstrFormats.td index ee432c8..ea07372 100644 --- a/lib/Target/Mips/MipsInstrFormats.td +++ b/lib/Target/Mips/MipsInstrFormats.td @@ -36,6 +36,24 @@ def FrmFR : Format<4>; def FrmFI : Format<5>; def FrmOther : Format<6>; // Instruction w/ a custom format +class MMRel; + +def Std2MicroMips : InstrMapping { + let FilterClass = "MMRel"; + // Instructions with the same BaseOpcode and isNVStore values form a row. + let RowFields = ["BaseOpcode"]; + // Instructions with the same predicate sense form a column. + let ColFields = ["Arch"]; + // The key column is the unpredicated instructions. + let KeyCol = ["se"]; + // Value columns are PredSense=true and PredSense=false + let ValueCols = [["se"], ["micromips"]]; +} + +class StdArch { + string Arch = "se"; +} + // Generic Mips Format class MipsInst<dag outs, dag ins, string asmstr, list<dag> pattern, InstrItinClass itin, Format f>: Instruction @@ -74,9 +92,11 @@ class MipsInst<dag outs, dag ins, string asmstr, list<dag> pattern, // Mips32/64 Instruction Format class InstSE<dag outs, dag ins, string asmstr, list<dag> pattern, - InstrItinClass itin, Format f>: + InstrItinClass itin, Format f, string opstr = ""> : MipsInst<outs, ins, asmstr, pattern, itin, f> { let Predicates = [HasStdEnc]; + string BaseOpcode = opstr; + string Arch; } // Mips Pseudo Instructions Format @@ -192,7 +212,7 @@ class MFC3OP_FM<bits<6> op, bits<5> mfmt> let Inst{2-0} = sel; } -class ADD_FM<bits<6> op, bits<6> funct> { +class ADD_FM<bits<6> op, bits<6> funct> : StdArch { bits<5> rd; bits<5> rs; bits<5> rt; @@ -207,7 +227,7 @@ class ADD_FM<bits<6> op, bits<6> funct> { let Inst{5-0} = funct; } -class ADDI_FM<bits<6> op> { +class ADDI_FM<bits<6> op> : StdArch { bits<5> rs; bits<5> rt; bits<16> imm16; @@ -220,7 +240,7 @@ class ADDI_FM<bits<6> op> { let Inst{15-0} = imm16; } -class SRA_FM<bits<6> funct, bit rotate> { +class SRA_FM<bits<6> funct, bit rotate> : StdArch { bits<5> rd; bits<5> rt; bits<5> shamt; @@ -236,7 +256,7 @@ class SRA_FM<bits<6> funct, bit rotate> { let Inst{5-0} = funct; } -class SRLV_FM<bits<6> funct, bit rotate> { +class SRLV_FM<bits<6> funct, bit rotate> : StdArch { bits<5> rd; bits<5> rt; bits<5> rs; @@ -288,7 +308,7 @@ class B_FM { let Inst{15-0} = offset; } -class SLTI_FM<bits<6> op> { +class SLTI_FM<bits<6> op> : StdArch { bits<5> rt; bits<5> rs; bits<16> imm16; @@ -413,7 +433,7 @@ class SYNC_FM { let Inst{5-0} = 0xf; } -class MULT_FM<bits<6> op, bits<6> funct> { +class MULT_FM<bits<6> op, bits<6> funct> : StdArch { bits<5> rs; bits<5> rt; @@ -529,7 +549,7 @@ class MFC1_FM<bits<5> funct> { let Inst{10-0} = 0; } -class LW_FM<bits<6> op> { +class LW_FM<bits<6> op> : StdArch { bits<5> rt; bits<21> addr; diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index 3a82e81..86ec729 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -179,6 +179,7 @@ def NoNaNsFPMath : Predicate<"TM.Options.NoNaNsFPMath">, AssemblerPredicate<"FeatureMips32">; def HasStdEnc : Predicate<"Subtarget.hasStandardEncoding()">, AssemblerPredicate<"!FeatureMips16">; +def NotDSP : Predicate<"!Subtarget.hasDSP()">; class MipsPat<dag pattern, dag result> : Pat<pattern, result> { let Predicates = [HasStdEnc]; @@ -374,11 +375,9 @@ class ArithLogicR<string opstr, RegisterOperand RO, bit isComm = 0, SDPatternOperator OpNode = null_frag>: InstSE<(outs RO:$rd), (ins RO:$rs, RO:$rt), !strconcat(opstr, "\t$rd, $rs, $rt"), - [(set RO:$rd, (OpNode RO:$rs, RO:$rt))], Itin, FrmR> { + [(set RO:$rd, (OpNode RO:$rs, RO:$rt))], Itin, FrmR, opstr> { let isCommutable = isComm; let isReMaterializable = 1; - string BaseOpcode; - string Arch; } // Arithmetic and logical instructions with 2 register operands. @@ -387,7 +386,8 @@ class ArithLogicI<string opstr, Operand Od, RegisterOperand RO, SDPatternOperator OpNode = null_frag> : InstSE<(outs RO:$rt), (ins RO:$rs, Od:$imm16), !strconcat(opstr, "\t$rt, $rs, $imm16"), - [(set RO:$rt, (OpNode RO:$rs, imm_type:$imm16))], IIAlu, FrmI> { + [(set RO:$rt, (OpNode RO:$rs, imm_type:$imm16))], + IIAlu, FrmI, opstr> { let isReMaterializable = 1; } @@ -404,7 +404,7 @@ class MArithR<string opstr, bit isComm = 0> : class LogicNOR<string opstr, RegisterOperand RC>: InstSE<(outs RC:$rd), (ins RC:$rs, RC:$rt), !strconcat(opstr, "\t$rd, $rs, $rt"), - [(set RC:$rd, (not (or RC:$rs, RC:$rt)))], IIAlu, FrmR> { + [(set RC:$rd, (not (or RC:$rs, RC:$rt)))], IIAlu, FrmR, opstr> { let isCommutable = 1; } @@ -414,13 +414,13 @@ class shift_rotate_imm<string opstr, Operand ImmOpnd, SDPatternOperator PF = null_frag> : InstSE<(outs RC:$rd), (ins RC:$rt, ImmOpnd:$shamt), !strconcat(opstr, "\t$rd, $rt, $shamt"), - [(set RC:$rd, (OpNode RC:$rt, PF:$shamt))], IIAlu, FrmR>; + [(set RC:$rd, (OpNode RC:$rt, PF:$shamt))], IIAlu, FrmR, opstr>; class shift_rotate_reg<string opstr, RegisterOperand RC, SDPatternOperator OpNode = null_frag>: InstSE<(outs RC:$rd), (ins CPURegsOpnd:$rs, RC:$rt), !strconcat(opstr, "\t$rd, $rt, $rs"), - [(set RC:$rd, (OpNode RC:$rt, CPURegsOpnd:$rs))], IIAlu, FrmR>; + [(set RC:$rd, (OpNode RC:$rt, CPURegsOpnd:$rs))], IIAlu, FrmR, opstr>; // Load Upper Imediate class LoadUpper<string opstr, RegisterClass RC, Operand Imm>: @@ -440,18 +440,20 @@ class FMem<bits<6> op, dag outs, dag ins, string asmstr, list<dag> pattern, // Memory Load/Store class Load<string opstr, SDPatternOperator OpNode, RegisterClass RC, - Operand MemOpnd, ComplexPattern Addr> : + Operand MemOpnd, ComplexPattern Addr, string ofsuffix> : InstSE<(outs RC:$rt), (ins MemOpnd:$addr), !strconcat(opstr, "\t$rt, $addr"), - [(set RC:$rt, (OpNode Addr:$addr))], NoItinerary, FrmI> { + [(set RC:$rt, (OpNode Addr:$addr))], NoItinerary, FrmI, + !strconcat(opstr, ofsuffix)> { let DecoderMethod = "DecodeMem"; let canFoldAsLoad = 1; let mayLoad = 1; } class Store<string opstr, SDPatternOperator OpNode, RegisterClass RC, - Operand MemOpnd, ComplexPattern Addr> : + Operand MemOpnd, ComplexPattern Addr, string ofsuffix> : InstSE<(outs), (ins RC:$rt, MemOpnd:$addr), !strconcat(opstr, "\t$rt, $addr"), - [(OpNode RC:$rt, Addr:$addr)], NoItinerary, FrmI> { + [(OpNode RC:$rt, Addr:$addr)], NoItinerary, FrmI, + !strconcat(opstr, ofsuffix)> { let DecoderMethod = "DecodeMem"; let mayStore = 1; } @@ -459,8 +461,9 @@ class Store<string opstr, SDPatternOperator OpNode, RegisterClass RC, multiclass LoadM<string opstr, RegisterClass RC, SDPatternOperator OpNode = null_frag, ComplexPattern Addr = addr> { - def NAME : Load<opstr, OpNode, RC, mem, Addr>, Requires<[NotN64, HasStdEnc]>; - def _P8 : Load<opstr, OpNode, RC, mem64, Addr>, + def NAME : Load<opstr, OpNode, RC, mem, Addr, "">, + Requires<[NotN64, HasStdEnc]>; + def _P8 : Load<opstr, OpNode, RC, mem64, Addr, "_p8">, Requires<[IsN64, HasStdEnc]> { let DecoderNamespace = "Mips64"; let isCodeGenOnly = 1; @@ -470,8 +473,9 @@ multiclass LoadM<string opstr, RegisterClass RC, multiclass StoreM<string opstr, RegisterClass RC, SDPatternOperator OpNode = null_frag, ComplexPattern Addr = addr> { - def NAME : Store<opstr, OpNode, RC, mem, Addr>, Requires<[NotN64, HasStdEnc]>; - def _P8 : Store<opstr, OpNode, RC, mem64, Addr>, + def NAME : Store<opstr, OpNode, RC, mem, Addr, "">, + Requires<[NotN64, HasStdEnc]>; + def _P8 : Store<opstr, OpNode, RC, mem64, Addr, "_p8">, Requires<[IsN64, HasStdEnc]> { let DecoderNamespace = "Mips64"; let isCodeGenOnly = 1; @@ -542,14 +546,15 @@ class CBranchZero<string opstr, PatFrag cond_op, RegisterClass RC> : class SetCC_R<string opstr, PatFrag cond_op, RegisterClass RC> : InstSE<(outs CPURegsOpnd:$rd), (ins RC:$rs, RC:$rt), !strconcat(opstr, "\t$rd, $rs, $rt"), - [(set CPURegsOpnd:$rd, (cond_op RC:$rs, RC:$rt))], IIAlu, FrmR>; + [(set CPURegsOpnd:$rd, (cond_op RC:$rs, RC:$rt))], + IIAlu, FrmR, opstr>; class SetCC_I<string opstr, PatFrag cond_op, Operand Od, PatLeaf imm_type, RegisterClass RC>: InstSE<(outs CPURegsOpnd:$rt), (ins RC:$rs, Od:$imm16), !strconcat(opstr, "\t$rt, $rs, $imm16"), [(set CPURegsOpnd:$rt, (cond_op RC:$rs, imm_type:$imm16))], - IIAlu, FrmI>; + IIAlu, FrmI, opstr>; // Jump class JumpFJ<DAGOperand opnd, string opstr, SDPatternOperator operator, @@ -636,7 +641,7 @@ class SYNC_FT : class Mult<string opstr, InstrItinClass itin, RegisterOperand RO, list<Register> DefRegs> : InstSE<(outs), (ins RO:$rs, RO:$rt), !strconcat(opstr, "\t$rs, $rt"), [], - itin, FrmR> { + itin, FrmR, opstr> { let isCommutable = 1; let Defs = DefRegs; let neverHasSideEffects = 1; @@ -832,14 +837,12 @@ let usesCustomInserter = 1 in { defm ATOMIC_CMP_SWAP_I32 : AtomicCmpSwap32<atomic_cmp_swap_32>; } -/// Pseudo instructions for loading, storing and copying accumulator registers. +/// Pseudo instructions for loading and storing accumulator registers. let isPseudo = 1 in { defm LOAD_AC64 : LoadM<"load_ac64", ACRegs>; defm STORE_AC64 : StoreM<"store_ac64", ACRegs>; } -def COPY_AC64 : PseudoSE<(outs ACRegs:$dst), (ins ACRegs:$src), []>; - //===----------------------------------------------------------------------===// // Instruction definition //===----------------------------------------------------------------------===// @@ -848,60 +851,70 @@ def COPY_AC64 : PseudoSE<(outs ACRegs:$dst), (ins ACRegs:$src), []>; //===----------------------------------------------------------------------===// /// Arithmetic Instructions (ALU Immediate) -def ADDiu : ArithLogicI<"addiu", simm16, CPURegsOpnd, immSExt16, add>, +def ADDiu : MMRel, ArithLogicI<"addiu", simm16, CPURegsOpnd, immSExt16, add>, ADDI_FM<0x9>, IsAsCheapAsAMove; -def ADDi : ArithLogicI<"addi", simm16, CPURegsOpnd>, ADDI_FM<0x8>; -def SLTi : SetCC_I<"slti", setlt, simm16, immSExt16, CPURegs>, SLTI_FM<0xa>; -def SLTiu : SetCC_I<"sltiu", setult, simm16, immSExt16, CPURegs>, SLTI_FM<0xb>; -def ANDi : ArithLogicI<"andi", uimm16, CPURegsOpnd, immZExt16, and>, +def ADDi : MMRel, ArithLogicI<"addi", simm16, CPURegsOpnd>, ADDI_FM<0x8>; +def SLTi : MMRel, SetCC_I<"slti", setlt, simm16, immSExt16, CPURegs>, + SLTI_FM<0xa>; +def SLTiu : MMRel, SetCC_I<"sltiu", setult, simm16, immSExt16, CPURegs>, + SLTI_FM<0xb>; +def ANDi : MMRel, ArithLogicI<"andi", uimm16, CPURegsOpnd, immZExt16, and>, ADDI_FM<0xc>; -def ORi : ArithLogicI<"ori", uimm16, CPURegsOpnd, immZExt16, or>, +def ORi : MMRel, ArithLogicI<"ori", uimm16, CPURegsOpnd, immZExt16, or>, ADDI_FM<0xd>; -def XORi : ArithLogicI<"xori", uimm16, CPURegsOpnd, immZExt16, xor>, +def XORi : MMRel, ArithLogicI<"xori", uimm16, CPURegsOpnd, immZExt16, xor>, ADDI_FM<0xe>; -def LUi : LoadUpper<"lui", CPURegs, uimm16>, LUI_FM; +def LUi : MMRel, LoadUpper<"lui", CPURegs, uimm16>, LUI_FM; /// Arithmetic Instructions (3-Operand, R-Type) -def ADDu : ArithLogicR<"addu", CPURegsOpnd, 1, IIAlu, add>, ADD_FM<0, 0x21>; -def SUBu : ArithLogicR<"subu", CPURegsOpnd, 0, IIAlu, sub>, ADD_FM<0, 0x23>; -def MUL : ArithLogicR<"mul", CPURegsOpnd, 1, IIImul, mul>, ADD_FM<0x1c, 2>; -def ADD : ArithLogicR<"add", CPURegsOpnd>, ADD_FM<0, 0x20>; -def SUB : ArithLogicR<"sub", CPURegsOpnd>, ADD_FM<0, 0x22>; -def SLT : SetCC_R<"slt", setlt, CPURegs>, ADD_FM<0, 0x2a>; -def SLTu : SetCC_R<"sltu", setult, CPURegs>, ADD_FM<0, 0x2b>; -def AND : ArithLogicR<"and", CPURegsOpnd, 1, IIAlu, and>, ADD_FM<0, 0x24>; -def OR : ArithLogicR<"or", CPURegsOpnd, 1, IIAlu, or>, ADD_FM<0, 0x25>; -def XOR : ArithLogicR<"xor", CPURegsOpnd, 1, IIAlu, xor>, ADD_FM<0, 0x26>; -def NOR : LogicNOR<"nor", CPURegsOpnd>, ADD_FM<0, 0x27>; +def ADDu : MMRel, ArithLogicR<"addu", CPURegsOpnd, 1, IIAlu, add>, + ADD_FM<0, 0x21>; +def SUBu : MMRel, ArithLogicR<"subu", CPURegsOpnd, 0, IIAlu, sub>, + ADD_FM<0, 0x23>; +def MUL : MMRel, ArithLogicR<"mul", CPURegsOpnd, 1, IIImul, mul>, + ADD_FM<0x1c, 2>; +def ADD : MMRel, ArithLogicR<"add", CPURegsOpnd>, ADD_FM<0, 0x20>; +def SUB : MMRel, ArithLogicR<"sub", CPURegsOpnd>, ADD_FM<0, 0x22>; +def SLT : MMRel, SetCC_R<"slt", setlt, CPURegs>, ADD_FM<0, 0x2a>; +def SLTu : MMRel, SetCC_R<"sltu", setult, CPURegs>, ADD_FM<0, 0x2b>; +def AND : MMRel, ArithLogicR<"and", CPURegsOpnd, 1, IIAlu, and>, + ADD_FM<0, 0x24>; +def OR : MMRel, ArithLogicR<"or", CPURegsOpnd, 1, IIAlu, or>, + ADD_FM<0, 0x25>; +def XOR : MMRel, ArithLogicR<"xor", CPURegsOpnd, 1, IIAlu, xor>, + ADD_FM<0, 0x26>; +def NOR : MMRel, LogicNOR<"nor", CPURegsOpnd>, ADD_FM<0, 0x27>; /// Shift Instructions -def SLL : shift_rotate_imm<"sll", shamt, CPURegsOpnd, shl, immZExt5>, +def SLL : MMRel, shift_rotate_imm<"sll", shamt, CPURegsOpnd, shl, immZExt5>, SRA_FM<0, 0>; -def SRL : shift_rotate_imm<"srl", shamt, CPURegsOpnd, srl, immZExt5>, +def SRL : MMRel, shift_rotate_imm<"srl", shamt, CPURegsOpnd, srl, immZExt5>, SRA_FM<2, 0>; -def SRA : shift_rotate_imm<"sra", shamt, CPURegsOpnd, sra, immZExt5>, +def SRA : MMRel, shift_rotate_imm<"sra", shamt, CPURegsOpnd, sra, immZExt5>, SRA_FM<3, 0>; -def SLLV : shift_rotate_reg<"sllv", CPURegsOpnd, shl>, SRLV_FM<4, 0>; -def SRLV : shift_rotate_reg<"srlv", CPURegsOpnd, srl>, SRLV_FM<6, 0>; -def SRAV : shift_rotate_reg<"srav", CPURegsOpnd, sra>, SRLV_FM<7, 0>; +def SLLV : MMRel, shift_rotate_reg<"sllv", CPURegsOpnd, shl>, SRLV_FM<4, 0>; +def SRLV : MMRel, shift_rotate_reg<"srlv", CPURegsOpnd, srl>, SRLV_FM<6, 0>; +def SRAV : MMRel, shift_rotate_reg<"srav", CPURegsOpnd, sra>, SRLV_FM<7, 0>; // Rotate Instructions let Predicates = [HasMips32r2, HasStdEnc] in { - def ROTR : shift_rotate_imm<"rotr", shamt, CPURegsOpnd, rotr, immZExt5>, + def ROTR : MMRel, shift_rotate_imm<"rotr", shamt, CPURegsOpnd, rotr, + immZExt5>, SRA_FM<2, 1>; - def ROTRV : shift_rotate_reg<"rotrv", CPURegsOpnd, rotr>, SRLV_FM<6, 1>; + def ROTRV : MMRel, shift_rotate_reg<"rotrv", CPURegsOpnd, rotr>, + SRLV_FM<6, 1>; } /// Load and Store Instructions /// aligned -defm LB : LoadM<"lb", CPURegs, sextloadi8>, LW_FM<0x20>; -defm LBu : LoadM<"lbu", CPURegs, zextloadi8, addrDefault>, LW_FM<0x24>; -defm LH : LoadM<"lh", CPURegs, sextloadi16, addrDefault>, LW_FM<0x21>; -defm LHu : LoadM<"lhu", CPURegs, zextloadi16>, LW_FM<0x25>; -defm LW : LoadM<"lw", CPURegs, load, addrDefault>, LW_FM<0x23>; -defm SB : StoreM<"sb", CPURegs, truncstorei8>, LW_FM<0x28>; -defm SH : StoreM<"sh", CPURegs, truncstorei16>, LW_FM<0x29>; -defm SW : StoreM<"sw", CPURegs, store>, LW_FM<0x2b>; +defm LB : LoadM<"lb", CPURegs, sextloadi8>, MMRel, LW_FM<0x20>; +defm LBu : LoadM<"lbu", CPURegs, zextloadi8, addrDefault>, MMRel, LW_FM<0x24>; +defm LH : LoadM<"lh", CPURegs, sextloadi16, addrDefault>, MMRel, LW_FM<0x21>; +defm LHu : LoadM<"lhu", CPURegs, zextloadi16>, MMRel, LW_FM<0x25>; +defm LW : LoadM<"lw", CPURegs, load, addrDefault>, MMRel, LW_FM<0x23>; +defm SB : StoreM<"sb", CPURegs, truncstorei8>, MMRel, LW_FM<0x28>; +defm SH : StoreM<"sh", CPURegs, truncstorei16>, MMRel, LW_FM<0x29>; +defm SW : StoreM<"sw", CPURegs, store>, MMRel, LW_FM<0x2b>; /// load/store left/right defm LWL : LoadLeftRightM<"lwl", MipsLWL, CPURegs>, LW_FM<0x22>; @@ -968,8 +981,10 @@ let Uses = [V0, V1], isTerminator = 1, isReturn = 1, isBarrier = 1 in { } /// Multiply and Divide Instructions. -def MULT : Mult<"mult", IIImul, CPURegsOpnd, [HI, LO]>, MULT_FM<0, 0x18>; -def MULTu : Mult<"multu", IIImul, CPURegsOpnd, [HI, LO]>, MULT_FM<0, 0x19>; +def MULT : MMRel, Mult<"mult", IIImul, CPURegsOpnd, [HI, LO]>, + MULT_FM<0, 0x18>; +def MULTu : MMRel, Mult<"multu", IIImul, CPURegsOpnd, [HI, LO]>, + MULT_FM<0, 0x19>; def PseudoMULT : MultDivPseudo<MULT, ACRegs, CPURegsOpnd, MipsMult, IIImul>; def PseudoMULTu : MultDivPseudo<MULTu, ACRegs, CPURegsOpnd, MipsMultu, IIImul>; def SDIV : Div<"div", IIIdiv, CPURegsOpnd, [HI, LO]>, MULT_FM<0, 0x1a>; @@ -1066,10 +1081,10 @@ def : InstAlias<"negu $rt, $rs", def : InstAlias<"slt $rs, $rt, $imm", (SLTi CPURegsOpnd:$rs, CPURegs:$rt, simm16:$imm), 0>; def : InstAlias<"xor $rs, $rt, $imm", - (XORi CPURegsOpnd:$rs, CPURegsOpnd:$rt, simm16:$imm), 0>, + (XORi CPURegsOpnd:$rs, CPURegsOpnd:$rt, uimm16:$imm), 1>, Requires<[NotMips64]>; def : InstAlias<"or $rs, $rt, $imm", - (ORi CPURegsOpnd:$rs, CPURegsOpnd:$rt, simm16:$imm), 0>, + (ORi CPURegsOpnd:$rs, CPURegsOpnd:$rt, uimm16:$imm), 1>, Requires<[NotMips64]>; def : InstAlias<"nop", (SLL ZERO, ZERO, 0), 1>; def : InstAlias<"mfc0 $rt, $rd", @@ -1128,10 +1143,12 @@ def : MipsPat<(i32 imm:$imm), // Carry MipsPatterns def : MipsPat<(subc CPURegs:$lhs, CPURegs:$rhs), (SUBu CPURegs:$lhs, CPURegs:$rhs)>; -def : MipsPat<(addc CPURegs:$lhs, CPURegs:$rhs), - (ADDu CPURegs:$lhs, CPURegs:$rhs)>; -def : MipsPat<(addc CPURegs:$src, immSExt16:$imm), - (ADDiu CPURegs:$src, imm:$imm)>; +let Predicates = [HasStdEnc, NotDSP] in { + def : MipsPat<(addc CPURegs:$lhs, CPURegs:$rhs), + (ADDu CPURegs:$lhs, CPURegs:$rhs)>; + def : MipsPat<(addc CPURegs:$src, immSExt16:$imm), + (ADDiu CPURegs:$src, imm:$imm)>; +} // Call def : MipsPat<(MipsJmpLink (i32 tglobaladdr:$dst)), @@ -1326,3 +1343,6 @@ include "Mips16InstrInfo.td" include "MipsDSPInstrFormats.td" include "MipsDSPInstrInfo.td" +// Micromips +include "MicroMipsInstrFormats.td" +include "MicroMipsInstrInfo.td" diff --git a/lib/Target/Mips/MipsLongBranch.cpp b/lib/Target/Mips/MipsLongBranch.cpp index 2efe534..bf5ad37 100644 --- a/lib/Target/Mips/MipsLongBranch.cpp +++ b/lib/Target/Mips/MipsLongBranch.cpp @@ -399,6 +399,8 @@ static void emitGPDisp(MachineFunction &F, const MipsInstrInfo *TII) { } bool MipsLongBranch::runOnMachineFunction(MachineFunction &F) { + if (TM.getSubtarget<MipsSubtarget>().inMips16Mode()) + return false; if ((TM.getRelocationModel() == Reloc::PIC_) && TM.getSubtarget<MipsSubtarget>().isABI_O32() && F.getInfo<MipsFunctionInfo>()->globalBaseRegSet()) diff --git a/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp b/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp new file mode 100644 index 0000000..c6abf17 --- /dev/null +++ b/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// Instruction Selector Subtarget Control +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// This file defines a pass used to change the subtarget for the +// Mips Instruction selector. +// +//===----------------------------------------------------------------------===// + +#include "MipsISelDAGToDAG.h" +#include "MipsModuleISelDAGToDAG.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +bool MipsModuleDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { + DEBUG(errs() << "In MipsModuleDAGToDAGISel::runMachineFunction\n"); + const_cast<MipsSubtarget&>(Subtarget).resetSubtarget(&MF); + return false; +} + +char MipsModuleDAGToDAGISel::ID = 0; + +} + + +llvm::FunctionPass *llvm::createMipsModuleISelDag(MipsTargetMachine &TM) { + return new MipsModuleDAGToDAGISel(TM); +} + + diff --git a/lib/Target/Mips/MipsModuleISelDAGToDAG.h b/lib/Target/Mips/MipsModuleISelDAGToDAG.h new file mode 100644 index 0000000..fda35ae --- /dev/null +++ b/lib/Target/Mips/MipsModuleISelDAGToDAG.h @@ -0,0 +1,66 @@ +//===---- MipsModuleISelDAGToDAG.h - Change Subtarget --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a pass used to change the subtarget for the +// Mips Instruction selector. +// +//===----------------------------------------------------------------------===// + +#ifndef MIPSMODULEISELDAGTODAG_H +#define MIPSMODULEISELDAGTODAG_H + +#include "Mips.h" +#include "MipsSubtarget.h" +#include "MipsTargetMachine.h" +#include "llvm/CodeGen/SelectionDAGISel.h" + + +//===----------------------------------------------------------------------===// +// Instruction Selector Implementation +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// MipsModuleDAGToDAGISel - MIPS specific code to select MIPS machine +// instructions for SelectionDAG operations. +//===----------------------------------------------------------------------===// +namespace llvm { + +class MipsModuleDAGToDAGISel : public MachineFunctionPass { +public: + + static char ID; + + explicit MipsModuleDAGToDAGISel(MipsTargetMachine &TM_) + : MachineFunctionPass(ID), + TM(TM_), Subtarget(TM.getSubtarget<MipsSubtarget>()) {} + + // Pass Name + virtual const char *getPassName() const { + return "MIPS DAG->DAG Pattern Instruction Selection"; + } + + virtual bool runOnMachineFunction(MachineFunction &MF); + + virtual SDNode *Select(SDNode *N) { + llvm_unreachable("unexpected"); + } + +protected: + /// Keep a pointer to the MipsSubtarget around so that we can make the right + /// decision when generating code for different targets. + const TargetMachine &TM; + const MipsSubtarget &Subtarget; +}; + +/// createMipsISelDag - This pass converts a legalized DAG into a +/// MIPS-specific DAG, ready for instruction scheduling. +FunctionPass *createMipsModuleISelDag(MipsTargetMachine &TM); +} + +#endif diff --git a/lib/Target/Mips/MipsOs16.cpp b/lib/Target/Mips/MipsOs16.cpp new file mode 100644 index 0000000..1919077 --- /dev/null +++ b/lib/Target/Mips/MipsOs16.cpp @@ -0,0 +1,113 @@ +//===---- MipsOs16.cpp for Mips Option -Os16 --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines an optimization phase for the MIPS target. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "mips-os16" +#include "MipsOs16.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +namespace { + + // Figure out if we need float point based on the function signature. + // We need to move variables in and/or out of floating point + // registers because of the ABI + // + bool needsFPFromSig(Function &F) { + Type* RetType = F.getReturnType(); + switch (RetType->getTypeID()) { + case Type::FloatTyID: + case Type::DoubleTyID: + return true; + default: + ; + } + if (F.arg_size() >=1) { + Argument &Arg = F.getArgumentList().front(); + switch (Arg.getType()->getTypeID()) { + case Type::FloatTyID: + case Type::DoubleTyID: + return true; + default: + ; + } + } + return false; + } + + // Figure out if the function will need floating point operations + // + bool needsFP(Function &F) { + if (needsFPFromSig(F)) + return true; + for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); + I != E; ++I) { + const Instruction &Inst = *I; + switch (Inst.getOpcode()) { + case Instruction::FAdd: + case Instruction::FSub: + case Instruction::FMul: + case Instruction::FDiv: + case Instruction::FRem: + case Instruction::FPToUI: + case Instruction::FPToSI: + case Instruction::UIToFP: + case Instruction::SIToFP: + case Instruction::FPTrunc: + case Instruction::FPExt: + case Instruction::FCmp: + return true; + default: + ; + } + if (const CallInst *CI = dyn_cast<CallInst>(I)) { + DEBUG(dbgs() << "Working on call" << "\n"); + Function &F_ = *CI->getCalledFunction(); + if (needsFPFromSig(F_)) + return true; + } + } + return false; + } +} +namespace llvm { + + +bool MipsOs16::runOnModule(Module &M) { + DEBUG(errs() << "Run on Module MipsOs16\n"); + bool modified = false; + for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { + if (F->isDeclaration()) continue; + DEBUG(dbgs() << "Working on " << F->getName() << "\n"); + if (needsFP(*F)) { + DEBUG(dbgs() << " need to compile as nomips16 \n"); + F->addFnAttr("nomips16"); + } + else { + F->addFnAttr("mips16"); + DEBUG(dbgs() << " no need to compile as nomips16 \n"); + } + } + return modified; +} + +char MipsOs16::ID = 0; + +} + +ModulePass *llvm::createMipsOs16(MipsTargetMachine &TM) { + return new MipsOs16; +} + + diff --git a/lib/Target/Mips/MipsOs16.h b/lib/Target/Mips/MipsOs16.h new file mode 100644 index 0000000..21beef8 --- /dev/null +++ b/lib/Target/Mips/MipsOs16.h @@ -0,0 +1,49 @@ +//===---- MipsOs16.h for Mips Option -Os16 --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines an optimization phase for the MIPS target. +// +//===----------------------------------------------------------------------===// + +#include "MCTargetDesc/MipsMCTargetDesc.h" +#include "MipsTargetMachine.h" +#include "llvm/Pass.h" +#include "llvm/Target/TargetMachine.h" + + + +#ifndef MIPSOS16_H +#define MIPSOS16_H + +using namespace llvm; + +namespace llvm { + +class MipsOs16 : public ModulePass { + +public: + static char ID; + + MipsOs16() : ModulePass(ID) { + + } + + virtual const char *getPassName() const { + return "MIPS Os16 Optimization"; + } + + virtual bool runOnModule(Module &M); + +}; + +ModulePass *createMipsOs16(MipsTargetMachine &TM); + +} + +#endif diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp index 3250733..dead07b 100644 --- a/lib/Target/Mips/MipsRegisterInfo.cpp +++ b/lib/Target/Mips/MipsRegisterInfo.cpp @@ -145,7 +145,11 @@ getReservedRegs(const MachineFunction &MF) const { Reserved.set(Mips::HWR29_64); // Reserve DSP control register. - Reserved.set(Mips::DSPCtrl); + Reserved.set(Mips::DSPPos); + Reserved.set(Mips::DSPSCount); + Reserved.set(Mips::DSPCarry); + Reserved.set(Mips::DSPEFI); + Reserved.set(Mips::DSPOutFlag); // Reserve RA if in mips16 mode. if (Subtarget.inMips16Mode()) { diff --git a/lib/Target/Mips/MipsRegisterInfo.td b/lib/Target/Mips/MipsRegisterInfo.td index 64458bc..229f167 100644 --- a/lib/Target/Mips/MipsRegisterInfo.td +++ b/lib/Target/Mips/MipsRegisterInfo.td @@ -16,6 +16,11 @@ def sub_fpodd : SubRegIndex; def sub_32 : SubRegIndex; def sub_lo : SubRegIndex; def sub_hi : SubRegIndex; +def sub_dsp16_19 : SubRegIndex; +def sub_dsp20 : SubRegIndex; +def sub_dsp21 : SubRegIndex; +def sub_dsp22 : SubRegIndex; +def sub_dsp23 : SubRegIndex; } class Unallocatable { @@ -229,14 +234,14 @@ let Namespace = "Mips" in { def D31_64 : AFPR64<31, "f31", [F31]>, DwarfRegNum<[63]>; // Hi/Lo registers - def HI : Register<"hi">, DwarfRegNum<[64]>; - def HI1 : Register<"hi1">, DwarfRegNum<[176]>; - def HI2 : Register<"hi2">, DwarfRegNum<[178]>; - def HI3 : Register<"hi3">, DwarfRegNum<[180]>; - def LO : Register<"lo">, DwarfRegNum<[65]>; - def LO1 : Register<"lo1">, DwarfRegNum<[177]>; - def LO2 : Register<"lo2">, DwarfRegNum<[179]>; - def LO3 : Register<"lo3">, DwarfRegNum<[181]>; + def HI : Register<"ac0">, DwarfRegNum<[64]>; + def HI1 : Register<"ac1">, DwarfRegNum<[176]>; + def HI2 : Register<"ac2">, DwarfRegNum<[178]>; + def HI3 : Register<"ac3">, DwarfRegNum<[180]>; + def LO : Register<"ac0">, DwarfRegNum<[65]>; + def LO1 : Register<"ac1">, DwarfRegNum<[177]>; + def LO2 : Register<"ac2">, DwarfRegNum<[179]>; + def LO3 : Register<"ac3">, DwarfRegNum<[181]>; let SubRegIndices = [sub_32] in { def HI64 : RegisterWithSubRegs<"hi", [HI]>; @@ -264,7 +269,23 @@ let Namespace = "Mips" in { def AC0_64 : ACC<0, "ac0", [LO64, HI64]>; - def DSPCtrl : Register<"dspctrl">; + // DSP-ASE control register fields. + def DSPPos : Register<"">; + def DSPSCount : Register<"">; + def DSPCarry : Register<"">; + def DSPEFI : Register<"">; + def DSPOutFlag16_19 : Register<"">; + def DSPOutFlag20 : Register<"">; + def DSPOutFlag21 : Register<"">; + def DSPOutFlag22 : Register<"">; + def DSPOutFlag23 : Register<"">; + def DSPCCond : Register<"">; + + let SubRegIndices = [sub_dsp16_19, sub_dsp20, sub_dsp21, sub_dsp22, + sub_dsp23] in + def DSPOutFlag : RegisterWithSubRegs<"", [DSPOutFlag16_19, DSPOutFlag20, + DSPOutFlag21, DSPOutFlag22, + DSPOutFlag23]>; } //===----------------------------------------------------------------------===// @@ -340,8 +361,12 @@ def FGR64 : RegisterClass<"Mips", [f64], 64, (sequence "D%u_64", 0, 31)>; def CCR : RegisterClass<"Mips", [i32], 32, (add FCR31,FCC0)>, Unallocatable; // Hi/Lo Registers -def HILO : RegisterClass<"Mips", [i32], 32, (add HI, LO)>, Unallocatable; -def HILO64 : RegisterClass<"Mips", [i64], 64, (add HI64, LO64)>, Unallocatable; +def LORegs : RegisterClass<"Mips", [i32], 32, (add LO)>; +def HIRegs : RegisterClass<"Mips", [i32], 32, (add HI)>; +def LORegsDSP : RegisterClass<"Mips", [i32], 32, (add LO, LO1, LO2, LO3)>; +def HIRegsDSP : RegisterClass<"Mips", [i32], 32, (add HI, HI1, HI2, HI3)>; +def LORegs64 : RegisterClass<"Mips", [i64], 64, (add LO64)>; +def HIRegs64 : RegisterClass<"Mips", [i64], 64, (add HI64)>; // Hardware registers def HWRegs : RegisterClass<"Mips", [i32], 32, (add HWR29)>, Unallocatable; @@ -360,6 +385,9 @@ def ACRegsDSP : RegisterClass<"Mips", [untyped], 64, (sequence "AC%u", 0, 3)> { let Size = 64; } +def DSPCC : RegisterClass<"Mips", [v4i8, v2i16], 32, (add DSPCCond)>; + +// Register Operands. def CPURegsAsmOperand : AsmOperandClass { let Name = "CPURegsAsm"; let ParserMethod = "parseCPURegs"; diff --git a/lib/Target/Mips/MipsSEFrameLowering.cpp b/lib/Target/Mips/MipsSEFrameLowering.cpp index 68ec921..b295e91 100644 --- a/lib/Target/Mips/MipsSEFrameLowering.cpp +++ b/lib/Target/Mips/MipsSEFrameLowering.cpp @@ -32,17 +32,21 @@ using namespace llvm; namespace { typedef MachineBasicBlock::iterator Iter; -/// Helper class to expand accumulator pseudos. -class ExpandACCPseudo { +/// Helper class to expand pseudos. +class ExpandPseudo { public: - ExpandACCPseudo(MachineFunction &MF); + ExpandPseudo(MachineFunction &MF); bool expand(); private: bool expandInstr(MachineBasicBlock &MBB, Iter I); - void expandLoad(MachineBasicBlock &MBB, Iter I, unsigned RegSize); - void expandStore(MachineBasicBlock &MBB, Iter I, unsigned RegSize); - void expandCopy(MachineBasicBlock &MBB, Iter I, unsigned RegSize); + void expandLoadCCond(MachineBasicBlock &MBB, Iter I); + void expandStoreCCond(MachineBasicBlock &MBB, Iter I); + void expandLoadACC(MachineBasicBlock &MBB, Iter I, unsigned RegSize); + void expandStoreACC(MachineBasicBlock &MBB, Iter I, unsigned RegSize); + bool expandCopy(MachineBasicBlock &MBB, Iter I); + bool expandCopyACC(MachineBasicBlock &MBB, Iter I, unsigned Dst, + unsigned Src, unsigned RegSize); MachineFunction &MF; const MipsSEInstrInfo &TII; @@ -51,12 +55,12 @@ private: }; } -ExpandACCPseudo::ExpandACCPseudo(MachineFunction &MF_) +ExpandPseudo::ExpandPseudo(MachineFunction &MF_) : MF(MF_), TII(*static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo())), RegInfo(TII.getRegisterInfo()), MRI(MF.getRegInfo()) {} -bool ExpandACCPseudo::expand() { +bool ExpandPseudo::expand() { bool Expanded = false; for (MachineFunction::iterator BB = MF.begin(), BBEnd = MF.end(); @@ -67,34 +71,39 @@ bool ExpandACCPseudo::expand() { return Expanded; } -bool ExpandACCPseudo::expandInstr(MachineBasicBlock &MBB, Iter I) { +bool ExpandPseudo::expandInstr(MachineBasicBlock &MBB, Iter I) { switch(I->getOpcode()) { + case Mips::LOAD_CCOND_DSP: + case Mips::LOAD_CCOND_DSP_P8: + expandLoadCCond(MBB, I); + break; + case Mips::STORE_CCOND_DSP: + case Mips::STORE_CCOND_DSP_P8: + expandStoreCCond(MBB, I); + break; case Mips::LOAD_AC64: case Mips::LOAD_AC64_P8: case Mips::LOAD_AC_DSP: case Mips::LOAD_AC_DSP_P8: - expandLoad(MBB, I, 4); + expandLoadACC(MBB, I, 4); break; case Mips::LOAD_AC128: case Mips::LOAD_AC128_P8: - expandLoad(MBB, I, 8); + expandLoadACC(MBB, I, 8); break; case Mips::STORE_AC64: case Mips::STORE_AC64_P8: case Mips::STORE_AC_DSP: case Mips::STORE_AC_DSP_P8: - expandStore(MBB, I, 4); + expandStoreACC(MBB, I, 4); break; case Mips::STORE_AC128: case Mips::STORE_AC128_P8: - expandStore(MBB, I, 8); + expandStoreACC(MBB, I, 8); break; - case Mips::COPY_AC64: - case Mips::COPY_AC_DSP: - expandCopy(MBB, I, 4); - break; - case Mips::COPY_AC128: - expandCopy(MBB, I, 8); + case TargetOpcode::COPY: + if (!expandCopy(MBB, I)) + return false; break; default: return false; @@ -104,7 +113,37 @@ bool ExpandACCPseudo::expandInstr(MachineBasicBlock &MBB, Iter I) { return true; } -void ExpandACCPseudo::expandLoad(MachineBasicBlock &MBB, Iter I, +void ExpandPseudo::expandLoadCCond(MachineBasicBlock &MBB, Iter I) { + // load $vr, FI + // copy ccond, $vr + + assert(I->getOperand(0).isReg() && I->getOperand(1).isFI()); + + const TargetRegisterClass *RC = RegInfo.intRegClass(4); + unsigned VR = MRI.createVirtualRegister(RC); + unsigned Dst = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex(); + + TII.loadRegFromStack(MBB, I, VR, FI, RC, &RegInfo, 0); + BuildMI(MBB, I, I->getDebugLoc(), TII.get(TargetOpcode::COPY), Dst) + .addReg(VR, RegState::Kill); +} + +void ExpandPseudo::expandStoreCCond(MachineBasicBlock &MBB, Iter I) { + // copy $vr, ccond + // store $vr, FI + + assert(I->getOperand(0).isReg() && I->getOperand(1).isFI()); + + const TargetRegisterClass *RC = RegInfo.intRegClass(4); + unsigned VR = MRI.createVirtualRegister(RC); + unsigned Src = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex(); + + BuildMI(MBB, I, I->getDebugLoc(), TII.get(TargetOpcode::COPY), VR) + .addReg(Src, getKillRegState(I->getOperand(0).isKill())); + TII.storeRegToStack(MBB, I, VR, true, FI, RC, &RegInfo, 0); +} + +void ExpandPseudo::expandLoadACC(MachineBasicBlock &MBB, Iter I, unsigned RegSize) { // load $vr0, FI // copy lo, $vr0 @@ -128,7 +167,7 @@ void ExpandACCPseudo::expandLoad(MachineBasicBlock &MBB, Iter I, BuildMI(MBB, I, DL, Desc, Hi).addReg(VR1, RegState::Kill); } -void ExpandACCPseudo::expandStore(MachineBasicBlock &MBB, Iter I, +void ExpandPseudo::expandStoreACC(MachineBasicBlock &MBB, Iter I, unsigned RegSize) { // copy $vr0, lo // store $vr0, FI @@ -152,8 +191,20 @@ void ExpandACCPseudo::expandStore(MachineBasicBlock &MBB, Iter I, TII.storeRegToStack(MBB, I, VR1, true, FI, RC, &RegInfo, RegSize); } -void ExpandACCPseudo::expandCopy(MachineBasicBlock &MBB, Iter I, - unsigned RegSize) { +bool ExpandPseudo::expandCopy(MachineBasicBlock &MBB, Iter I) { + unsigned Dst = I->getOperand(0).getReg(), Src = I->getOperand(1).getReg(); + + if (Mips::ACRegsDSPRegClass.contains(Dst, Src)) + return expandCopyACC(MBB, I, Dst, Src, 4); + + if (Mips::ACRegs128RegClass.contains(Dst, Src)) + return expandCopyACC(MBB, I, Dst, Src, 8); + + return false; +} + +bool ExpandPseudo::expandCopyACC(MachineBasicBlock &MBB, Iter I, unsigned Dst, + unsigned Src, unsigned RegSize) { // copy $vr0, src_lo // copy dst_lo, $vr0 // copy $vr1, src_hi @@ -162,7 +213,6 @@ void ExpandACCPseudo::expandCopy(MachineBasicBlock &MBB, Iter I, const TargetRegisterClass *RC = RegInfo.intRegClass(RegSize); unsigned VR0 = MRI.createVirtualRegister(RC); unsigned VR1 = MRI.createVirtualRegister(RC); - unsigned Dst = I->getOperand(0).getReg(), Src = I->getOperand(1).getReg(); unsigned SrcKill = getKillRegState(I->getOperand(1).isKill()); unsigned DstLo = RegInfo.getSubReg(Dst, Mips::sub_lo); unsigned DstHi = RegInfo.getSubReg(Dst, Mips::sub_hi); @@ -176,6 +226,7 @@ void ExpandACCPseudo::expandCopy(MachineBasicBlock &MBB, Iter I, BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), VR1).addReg(SrcHi, SrcKill); BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), DstHi) .addReg(VR1, RegState::Kill); + return true; } unsigned MipsSEFrameLowering::ehDataReg(unsigned I) const { @@ -438,7 +489,7 @@ processFunctionBeforeCalleeSavedScan(MachineFunction &MF, // Expand pseudo instructions which load, store or copy accumulators. // Add an emergency spill slot if a pseudo was expanded. - if (ExpandACCPseudo(MF).expand()) { + if (ExpandPseudo(MF).expand()) { // The spill slot should be half the size of the accumulator. If target is // mips64, it should be 64-bit, otherwise it should be 32-bt. const TargetRegisterClass *RC = STI.hasMips64() ? diff --git a/lib/Target/Mips/MipsSEISelDAGToDAG.cpp b/lib/Target/Mips/MipsSEISelDAGToDAG.cpp index d6d2207..8a6523a 100644 --- a/lib/Target/Mips/MipsSEISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsSEISelDAGToDAG.cpp @@ -35,6 +35,36 @@ #include "llvm/Target/TargetMachine.h" using namespace llvm; +bool MipsSEDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { + if (Subtarget.inMips16Mode()) + return false; + return MipsDAGToDAGISel::runOnMachineFunction(MF); +} + +void MipsSEDAGToDAGISel::addDSPCtrlRegOperands(bool IsDef, MachineInstr &MI, + MachineFunction &MF) { + MachineInstrBuilder MIB(MF, &MI); + unsigned Mask = MI.getOperand(1).getImm(); + unsigned Flag = IsDef ? RegState::ImplicitDefine : RegState::Implicit; + + if (Mask & 1) + MIB.addReg(Mips::DSPPos, Flag); + + if (Mask & 2) + MIB.addReg(Mips::DSPSCount, Flag); + + if (Mask & 4) + MIB.addReg(Mips::DSPCarry, Flag); + + if (Mask & 8) + MIB.addReg(Mips::DSPOutFlag, Flag); + + if (Mask & 16) + MIB.addReg(Mips::DSPCCond, Flag); + + if (Mask & 32) + MIB.addReg(Mips::DSPEFI, Flag); +} bool MipsSEDAGToDAGISel::replaceUsesWithZeroReg(MachineRegisterInfo *MRI, const MachineInstr& MI) { @@ -173,29 +203,14 @@ void MipsSEDAGToDAGISel::processFunctionAfterISel(MachineFunction &MF) { for (MachineFunction::iterator MFI = MF.begin(), MFE = MF.end(); MFI != MFE; ++MFI) - for (MachineBasicBlock::iterator I = MFI->begin(); I != MFI->end(); ++I) - replaceUsesWithZeroReg(MRI, *I); -} - -/// Select multiply instructions. -std::pair<SDNode*, SDNode*> -MipsSEDAGToDAGISel::selectMULT(SDNode *N, unsigned Opc, DebugLoc DL, EVT Ty, - bool HasLo, bool HasHi) { - SDNode *Lo = 0, *Hi = 0; - SDNode *Mul = CurDAG->getMachineNode(Opc, DL, MVT::Glue, N->getOperand(0), - N->getOperand(1)); - SDValue InFlag = SDValue(Mul, 0); - - if (HasLo) { - unsigned Opcode = (Ty == MVT::i32 ? Mips::MFLO : Mips::MFLO64); - Lo = CurDAG->getMachineNode(Opcode, DL, Ty, MVT::Glue, InFlag); - InFlag = SDValue(Lo, 1); - } - if (HasHi) { - unsigned Opcode = (Ty == MVT::i32 ? Mips::MFHI : Mips::MFHI64); - Hi = CurDAG->getMachineNode(Opcode, DL, Ty, InFlag); - } - return std::make_pair(Lo, Hi); + for (MachineBasicBlock::iterator I = MFI->begin(); I != MFI->end(); ++I) { + if (I->getOpcode() == Mips::RDDSP) + addDSPCtrlRegOperands(false, *I, MF); + else if (I->getOpcode() == Mips::WRDSP) + addDSPCtrlRegOperands(true, *I, MF); + else + replaceUsesWithZeroReg(MRI, *I); + } } SDNode *MipsSEDAGToDAGISel::selectAddESubE(unsigned MOp, SDValue InFlag, @@ -211,7 +226,7 @@ SDNode *MipsSEDAGToDAGISel::selectAddESubE(unsigned MOp, SDValue InFlag, SDValue LHS = Node->getOperand(0), RHS = Node->getOperand(1); EVT VT = LHS.getValueType(); - SDNode *Carry = CurDAG->getMachineNode(Mips::SLTu, DL, VT, Ops, 2); + SDNode *Carry = CurDAG->getMachineNode(Mips::SLTu, DL, VT, Ops); SDNode *AddCarry = CurDAG->getMachineNode(Mips::ADDu, DL, VT, SDValue(Carry, 0), RHS); return CurDAG->SelectNodeTo(Node, MOp, VT, MVT::Glue, LHS, @@ -307,9 +322,7 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) { // Instruction Selection not handled by the auto-generated // tablegen selection should be handled here. /// - EVT NodeTy = Node->getValueType(0); SDNode *Result; - unsigned MultOpc; switch(Opcode) { default: break; @@ -321,51 +334,13 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) { } case ISD::ADDE: { + if (Subtarget.hasDSP()) // Select DSP instructions, ADDSC and ADDWC. + break; SDValue InFlag = Node->getOperand(2); Result = selectAddESubE(Mips::ADDu, InFlag, InFlag.getValue(0), DL, Node); return std::make_pair(true, Result); } - /// Mul with two results - case ISD::SMUL_LOHI: - case ISD::UMUL_LOHI: { - if (NodeTy == MVT::i32) - MultOpc = (Opcode == ISD::UMUL_LOHI ? Mips::MULTu : Mips::MULT); - else - MultOpc = (Opcode == ISD::UMUL_LOHI ? Mips::DMULTu : Mips::DMULT); - - std::pair<SDNode*, SDNode*> LoHi = selectMULT(Node, MultOpc, DL, NodeTy, - true, true); - - if (!SDValue(Node, 0).use_empty()) - ReplaceUses(SDValue(Node, 0), SDValue(LoHi.first, 0)); - - if (!SDValue(Node, 1).use_empty()) - ReplaceUses(SDValue(Node, 1), SDValue(LoHi.second, 0)); - - return std::make_pair(true, (SDNode*)NULL); - } - - /// Special Muls - case ISD::MUL: { - // Mips32 has a 32-bit three operand mul instruction. - if (Subtarget.hasMips32() && NodeTy == MVT::i32) - break; - MultOpc = NodeTy == MVT::i32 ? Mips::MULT : Mips::DMULT; - Result = selectMULT(Node, MultOpc, DL, NodeTy, true, false).first; - return std::make_pair(true, Result); - } - case ISD::MULHS: - case ISD::MULHU: { - if (NodeTy == MVT::i32) - MultOpc = (Opcode == ISD::MULHU ? Mips::MULTu : Mips::MULT); - else - MultOpc = (Opcode == ISD::MULHU ? Mips::DMULTu : Mips::DMULT); - - Result = selectMULT(Node, MultOpc, DL, NodeTy, false, true).second; - return std::make_pair(true, Result); - } - case ISD::ConstantFP: { ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(Node); if (Node->getValueType(0) == MVT::f64 && CN->isExactlyValue(+0.0)) { @@ -460,7 +435,7 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) { const SDValue Ops[] = { RegClass, Node->getOperand(0), LoIdx, Node->getOperand(1), HiIdx }; SDNode *Res = CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, DL, - MVT::Untyped, Ops, 5); + MVT::Untyped, Ops); return std::make_pair(true, Res); } } diff --git a/lib/Target/Mips/MipsSEISelDAGToDAG.h b/lib/Target/Mips/MipsSEISelDAGToDAG.h index 6137ab0..a235e96 100644 --- a/lib/Target/Mips/MipsSEISelDAGToDAG.h +++ b/lib/Target/Mips/MipsSEISelDAGToDAG.h @@ -24,6 +24,12 @@ public: explicit MipsSEDAGToDAGISel(MipsTargetMachine &TM) : MipsDAGToDAGISel(TM) {} private: + + virtual bool runOnMachineFunction(MachineFunction &MF); + + void addDSPCtrlRegOperands(bool IsDef, MachineInstr &MI, + MachineFunction &MF); + bool replaceUsesWithZeroReg(MachineRegisterInfo *MRI, const MachineInstr&); std::pair<SDNode*, SDNode*> selectMULT(SDNode *N, unsigned Opc, DebugLoc dl, diff --git a/lib/Target/Mips/MipsSEISelLowering.cpp b/lib/Target/Mips/MipsSEISelLowering.cpp index 4f21921..8544bb8 100644 --- a/lib/Target/Mips/MipsSEISelLowering.cpp +++ b/lib/Target/Mips/MipsSEISelLowering.cpp @@ -15,6 +15,7 @@ #include "MipsTargetMachine.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/IR/Intrinsics.h" #include "llvm/Support/CommandLine.h" #include "llvm/Target/TargetInstrInfo.h" @@ -27,6 +28,9 @@ EnableMipsTailCalls("enable-mips-tail-calls", cl::Hidden, MipsSETargetLowering::MipsSETargetLowering(MipsTargetMachine &TM) : MipsTargetLowering(TM) { // Set up the register classes + + clearRegisterClasses(); + addRegisterClass(MVT::i32, &Mips::CPURegsRegClass); if (HasMips64) @@ -42,12 +46,23 @@ MipsSETargetLowering::MipsSETargetLowering(MipsTargetMachine &TM) for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc) setOperationAction(Opc, VecTys[i], Expand); + setOperationAction(ISD::ADD, VecTys[i], Legal); + setOperationAction(ISD::SUB, VecTys[i], Legal); setOperationAction(ISD::LOAD, VecTys[i], Legal); setOperationAction(ISD::STORE, VecTys[i], Legal); setOperationAction(ISD::BITCAST, VecTys[i], Legal); } + + setTargetDAGCombine(ISD::SHL); + setTargetDAGCombine(ISD::SRA); + setTargetDAGCombine(ISD::SRL); + setTargetDAGCombine(ISD::SETCC); + setTargetDAGCombine(ISD::VSELECT); } + if (Subtarget->hasDSPR2()) + setOperationAction(ISD::MUL, MVT::v2i16, Legal); + if (!TM.Options.UseSoftFloat) { addRegisterClass(MVT::f32, &Mips::FGR32RegClass); @@ -65,14 +80,19 @@ MipsSETargetLowering::MipsSETargetLowering(MipsTargetMachine &TM) setOperationAction(ISD::MULHS, MVT::i32, Custom); setOperationAction(ISD::MULHU, MVT::i32, Custom); - if (HasMips64) + if (HasMips64) { + setOperationAction(ISD::MULHS, MVT::i64, Custom); + setOperationAction(ISD::MULHU, MVT::i64, Custom); setOperationAction(ISD::MUL, MVT::i64, Custom); + } + + setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::i64, Custom); + setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::i64, Custom); setOperationAction(ISD::SDIVREM, MVT::i32, Custom); setOperationAction(ISD::UDIVREM, MVT::i32, Custom); setOperationAction(ISD::SDIVREM, MVT::i64, Custom); setOperationAction(ISD::UDIVREM, MVT::i64, Custom); - setOperationAction(ISD::MEMBARRIER, MVT::Other, Custom); setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom); setOperationAction(ISD::LOAD, MVT::i32, Custom); setOperationAction(ISD::STORE, MVT::i32, Custom); @@ -113,7 +133,10 @@ SDValue MipsSETargetLowering::LowerOperation(SDValue Op, case ISD::MULHU: return lowerMulDiv(Op, MipsISD::Multu, false, true, DAG); case ISD::MUL: return lowerMulDiv(Op, MipsISD::Mult, true, false, DAG); case ISD::SDIVREM: return lowerMulDiv(Op, MipsISD::DivRem, true, true, DAG); - case ISD::UDIVREM: return lowerMulDiv(Op, MipsISD::DivRemU, true, true, DAG); + case ISD::UDIVREM: return lowerMulDiv(Op, MipsISD::DivRemU, true, true, + DAG); + case ISD::INTRINSIC_WO_CHAIN: return lowerINTRINSIC_WO_CHAIN(Op, DAG); + case ISD::INTRINSIC_W_CHAIN: return lowerINTRINSIC_W_CHAIN(Op, DAG); } return MipsTargetLowering::LowerOperation(Op, DAG); @@ -297,18 +320,136 @@ static SDValue performSUBECombine(SDNode *N, SelectionDAG &DAG, return SDValue(); } +static SDValue performDSPShiftCombine(unsigned Opc, SDNode *N, EVT Ty, + SelectionDAG &DAG, + const MipsSubtarget *Subtarget) { + // See if this is a vector splat immediate node. + APInt SplatValue, SplatUndef; + unsigned SplatBitSize; + bool HasAnyUndefs; + unsigned EltSize = Ty.getVectorElementType().getSizeInBits(); + BuildVectorSDNode *BV = dyn_cast<BuildVectorSDNode>(N->getOperand(1)); + + if (!BV || + !BV->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs, + EltSize, !Subtarget->isLittle()) || + (SplatBitSize != EltSize) || + (SplatValue.getZExtValue() >= EltSize)) + return SDValue(); + + return DAG.getNode(Opc, N->getDebugLoc(), Ty, N->getOperand(0), + DAG.getConstant(SplatValue.getZExtValue(), MVT::i32)); +} + +static SDValue performSHLCombine(SDNode *N, SelectionDAG &DAG, + TargetLowering::DAGCombinerInfo &DCI, + const MipsSubtarget *Subtarget) { + EVT Ty = N->getValueType(0); + + if ((Ty != MVT::v2i16) && (Ty != MVT::v4i8)) + return SDValue(); + + return performDSPShiftCombine(MipsISD::SHLL_DSP, N, Ty, DAG, Subtarget); +} + +static SDValue performSRACombine(SDNode *N, SelectionDAG &DAG, + TargetLowering::DAGCombinerInfo &DCI, + const MipsSubtarget *Subtarget) { + EVT Ty = N->getValueType(0); + + if ((Ty != MVT::v2i16) && ((Ty != MVT::v4i8) || !Subtarget->hasDSPR2())) + return SDValue(); + + return performDSPShiftCombine(MipsISD::SHRA_DSP, N, Ty, DAG, Subtarget); +} + + +static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG, + TargetLowering::DAGCombinerInfo &DCI, + const MipsSubtarget *Subtarget) { + EVT Ty = N->getValueType(0); + + if (((Ty != MVT::v2i16) || !Subtarget->hasDSPR2()) && (Ty != MVT::v4i8)) + return SDValue(); + + return performDSPShiftCombine(MipsISD::SHRL_DSP, N, Ty, DAG, Subtarget); +} + +static bool isLegalDSPCondCode(EVT Ty, ISD::CondCode CC) { + bool IsV216 = (Ty == MVT::v2i16); + + switch (CC) { + case ISD::SETEQ: + case ISD::SETNE: return true; + case ISD::SETLT: + case ISD::SETLE: + case ISD::SETGT: + case ISD::SETGE: return IsV216; + case ISD::SETULT: + case ISD::SETULE: + case ISD::SETUGT: + case ISD::SETUGE: return !IsV216; + default: return false; + } +} + +static SDValue performSETCCCombine(SDNode *N, SelectionDAG &DAG) { + EVT Ty = N->getValueType(0); + + if ((Ty != MVT::v2i16) && (Ty != MVT::v4i8)) + return SDValue(); + + if (!isLegalDSPCondCode(Ty, cast<CondCodeSDNode>(N->getOperand(2))->get())) + return SDValue(); + + return DAG.getNode(MipsISD::SETCC_DSP, N->getDebugLoc(), Ty, N->getOperand(0), + N->getOperand(1), N->getOperand(2)); +} + +static SDValue performVSELECTCombine(SDNode *N, SelectionDAG &DAG) { + EVT Ty = N->getValueType(0); + + if ((Ty != MVT::v2i16) && (Ty != MVT::v4i8)) + return SDValue(); + + SDValue SetCC = N->getOperand(0); + + if (SetCC.getOpcode() != MipsISD::SETCC_DSP) + return SDValue(); + + return DAG.getNode(MipsISD::SELECT_CC_DSP, N->getDebugLoc(), Ty, + SetCC.getOperand(0), SetCC.getOperand(1), N->getOperand(1), + N->getOperand(2), SetCC.getOperand(2)); +} + SDValue MipsSETargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { SelectionDAG &DAG = DCI.DAG; + SDValue Val; switch (N->getOpcode()) { case ISD::ADDE: return performADDECombine(N, DAG, DCI, Subtarget); case ISD::SUBE: return performSUBECombine(N, DAG, DCI, Subtarget); - default: - return MipsTargetLowering::PerformDAGCombine(N, DCI); + case ISD::SHL: + return performSHLCombine(N, DAG, DCI, Subtarget); + case ISD::SRA: + return performSRACombine(N, DAG, DCI, Subtarget); + case ISD::SRL: + return performSRLCombine(N, DAG, DCI, Subtarget); + case ISD::VSELECT: + return performVSELECTCombine(N, DAG); + case ISD::SETCC: { + Val = performSETCCCombine(N, DAG); + break; } + } + + if (Val.getNode()) + return Val; + + return MipsTargetLowering::PerformDAGCombine(N, DCI); } MachineBasicBlock * @@ -378,6 +519,171 @@ SDValue MipsSETargetLowering::lowerMulDiv(SDValue Op, unsigned NewOpc, return DAG.getMergeValues(Vals, 2, DL); } + +static SDValue initAccumulator(SDValue In, DebugLoc DL, SelectionDAG &DAG) { + SDValue InLo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, In, + DAG.getConstant(0, MVT::i32)); + SDValue InHi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, In, + DAG.getConstant(1, MVT::i32)); + return DAG.getNode(MipsISD::InsertLOHI, DL, MVT::Untyped, InLo, InHi); +} + +static SDValue extractLOHI(SDValue Op, DebugLoc DL, SelectionDAG &DAG) { + SDValue Lo = DAG.getNode(MipsISD::ExtractLOHI, DL, MVT::i32, Op, + DAG.getConstant(Mips::sub_lo, MVT::i32)); + SDValue Hi = DAG.getNode(MipsISD::ExtractLOHI, DL, MVT::i32, Op, + DAG.getConstant(Mips::sub_hi, MVT::i32)); + return DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, Lo, Hi); +} + +// This function expands mips intrinsic nodes which have 64-bit input operands +// or output values. +// +// out64 = intrinsic-node in64 +// => +// lo = copy (extract-element (in64, 0)) +// hi = copy (extract-element (in64, 1)) +// mips-specific-node +// v0 = copy lo +// v1 = copy hi +// out64 = merge-values (v0, v1) +// +static SDValue lowerDSPIntr(SDValue Op, SelectionDAG &DAG, unsigned Opc) { + DebugLoc DL = Op.getDebugLoc(); + bool HasChainIn = Op->getOperand(0).getValueType() == MVT::Other; + SmallVector<SDValue, 3> Ops; + unsigned OpNo = 0; + + // See if Op has a chain input. + if (HasChainIn) + Ops.push_back(Op->getOperand(OpNo++)); + + // The next operand is the intrinsic opcode. + assert(Op->getOperand(OpNo).getOpcode() == ISD::TargetConstant); + + // See if the next operand has type i64. + SDValue Opnd = Op->getOperand(++OpNo), In64; + + if (Opnd.getValueType() == MVT::i64) + In64 = initAccumulator(Opnd, DL, DAG); + else + Ops.push_back(Opnd); + + // Push the remaining operands. + for (++OpNo ; OpNo < Op->getNumOperands(); ++OpNo) + Ops.push_back(Op->getOperand(OpNo)); + + // Add In64 to the end of the list. + if (In64.getNode()) + Ops.push_back(In64); + + // Scan output. + SmallVector<EVT, 2> ResTys; + + for (SDNode::value_iterator I = Op->value_begin(), E = Op->value_end(); + I != E; ++I) + ResTys.push_back((*I == MVT::i64) ? MVT::Untyped : *I); + + // Create node. + SDValue Val = DAG.getNode(Opc, DL, ResTys, &Ops[0], Ops.size()); + SDValue Out = (ResTys[0] == MVT::Untyped) ? extractLOHI(Val, DL, DAG) : Val; + + if (!HasChainIn) + return Out; + + assert(Val->getValueType(1) == MVT::Other); + SDValue Vals[] = { Out, SDValue(Val.getNode(), 1) }; + return DAG.getMergeValues(Vals, 2, DL); +} + +SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op, + SelectionDAG &DAG) const { + switch (cast<ConstantSDNode>(Op->getOperand(0))->getZExtValue()) { + default: + return SDValue(); + case Intrinsic::mips_shilo: + return lowerDSPIntr(Op, DAG, MipsISD::SHILO); + case Intrinsic::mips_dpau_h_qbl: + return lowerDSPIntr(Op, DAG, MipsISD::DPAU_H_QBL); + case Intrinsic::mips_dpau_h_qbr: + return lowerDSPIntr(Op, DAG, MipsISD::DPAU_H_QBR); + case Intrinsic::mips_dpsu_h_qbl: + return lowerDSPIntr(Op, DAG, MipsISD::DPSU_H_QBL); + case Intrinsic::mips_dpsu_h_qbr: + return lowerDSPIntr(Op, DAG, MipsISD::DPSU_H_QBR); + case Intrinsic::mips_dpa_w_ph: + return lowerDSPIntr(Op, DAG, MipsISD::DPA_W_PH); + case Intrinsic::mips_dps_w_ph: + return lowerDSPIntr(Op, DAG, MipsISD::DPS_W_PH); + case Intrinsic::mips_dpax_w_ph: + return lowerDSPIntr(Op, DAG, MipsISD::DPAX_W_PH); + case Intrinsic::mips_dpsx_w_ph: + return lowerDSPIntr(Op, DAG, MipsISD::DPSX_W_PH); + case Intrinsic::mips_mulsa_w_ph: + return lowerDSPIntr(Op, DAG, MipsISD::MULSA_W_PH); + case Intrinsic::mips_mult: + return lowerDSPIntr(Op, DAG, MipsISD::Mult); + case Intrinsic::mips_multu: + return lowerDSPIntr(Op, DAG, MipsISD::Multu); + case Intrinsic::mips_madd: + return lowerDSPIntr(Op, DAG, MipsISD::MAdd); + case Intrinsic::mips_maddu: + return lowerDSPIntr(Op, DAG, MipsISD::MAddu); + case Intrinsic::mips_msub: + return lowerDSPIntr(Op, DAG, MipsISD::MSub); + case Intrinsic::mips_msubu: + return lowerDSPIntr(Op, DAG, MipsISD::MSubu); + } +} + +SDValue MipsSETargetLowering::lowerINTRINSIC_W_CHAIN(SDValue Op, + SelectionDAG &DAG) const { + switch (cast<ConstantSDNode>(Op->getOperand(1))->getZExtValue()) { + default: + return SDValue(); + case Intrinsic::mips_extp: + return lowerDSPIntr(Op, DAG, MipsISD::EXTP); + case Intrinsic::mips_extpdp: + return lowerDSPIntr(Op, DAG, MipsISD::EXTPDP); + case Intrinsic::mips_extr_w: + return lowerDSPIntr(Op, DAG, MipsISD::EXTR_W); + case Intrinsic::mips_extr_r_w: + return lowerDSPIntr(Op, DAG, MipsISD::EXTR_R_W); + case Intrinsic::mips_extr_rs_w: + return lowerDSPIntr(Op, DAG, MipsISD::EXTR_RS_W); + case Intrinsic::mips_extr_s_h: + return lowerDSPIntr(Op, DAG, MipsISD::EXTR_S_H); + case Intrinsic::mips_mthlip: + return lowerDSPIntr(Op, DAG, MipsISD::MTHLIP); + case Intrinsic::mips_mulsaq_s_w_ph: + return lowerDSPIntr(Op, DAG, MipsISD::MULSAQ_S_W_PH); + case Intrinsic::mips_maq_s_w_phl: + return lowerDSPIntr(Op, DAG, MipsISD::MAQ_S_W_PHL); + case Intrinsic::mips_maq_s_w_phr: + return lowerDSPIntr(Op, DAG, MipsISD::MAQ_S_W_PHR); + case Intrinsic::mips_maq_sa_w_phl: + return lowerDSPIntr(Op, DAG, MipsISD::MAQ_SA_W_PHL); + case Intrinsic::mips_maq_sa_w_phr: + return lowerDSPIntr(Op, DAG, MipsISD::MAQ_SA_W_PHR); + case Intrinsic::mips_dpaq_s_w_ph: + return lowerDSPIntr(Op, DAG, MipsISD::DPAQ_S_W_PH); + case Intrinsic::mips_dpsq_s_w_ph: + return lowerDSPIntr(Op, DAG, MipsISD::DPSQ_S_W_PH); + case Intrinsic::mips_dpaq_sa_l_w: + return lowerDSPIntr(Op, DAG, MipsISD::DPAQ_SA_L_W); + case Intrinsic::mips_dpsq_sa_l_w: + return lowerDSPIntr(Op, DAG, MipsISD::DPSQ_SA_L_W); + case Intrinsic::mips_dpaqx_s_w_ph: + return lowerDSPIntr(Op, DAG, MipsISD::DPAQX_S_W_PH); + case Intrinsic::mips_dpaqx_sa_w_ph: + return lowerDSPIntr(Op, DAG, MipsISD::DPAQX_SA_W_PH); + case Intrinsic::mips_dpsqx_s_w_ph: + return lowerDSPIntr(Op, DAG, MipsISD::DPSQX_S_W_PH); + case Intrinsic::mips_dpsqx_sa_w_ph: + return lowerDSPIntr(Op, DAG, MipsISD::DPSQX_SA_W_PH); + } +} + MachineBasicBlock * MipsSETargetLowering:: emitBPOSGE32(MachineInstr *MI, MachineBasicBlock *BB) const{ // $bb: diff --git a/lib/Target/Mips/MipsSEISelLowering.h b/lib/Target/Mips/MipsSEISelLowering.h index 186f6a3..ec8a5c7 100644 --- a/lib/Target/Mips/MipsSEISelLowering.h +++ b/lib/Target/Mips/MipsSEISelLowering.h @@ -31,6 +31,11 @@ namespace llvm { virtual MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const; + virtual bool isShuffleMaskLegal(const SmallVectorImpl<int> &Mask, + EVT VT) const { + return false; + } + virtual const TargetRegisterClass *getRepRegClassFor(MVT VT) const { if (VT == MVT::Untyped) return Subtarget->hasDSP() ? &Mips::ACRegsDSPRegClass : @@ -54,6 +59,9 @@ namespace llvm { SDValue lowerMulDiv(SDValue Op, unsigned NewOpc, bool HasLo, bool HasHi, SelectionDAG &DAG) const; + SDValue lowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const; + SDValue lowerINTRINSIC_W_CHAIN(SDValue Op, SelectionDAG &DAG) const; + MachineBasicBlock *emitBPOSGE32(MachineInstr *MI, MachineBasicBlock *BB) const; }; diff --git a/lib/Target/Mips/MipsSEInstrInfo.cpp b/lib/Target/Mips/MipsSEInstrInfo.cpp index ca0315e..a0768e5 100644 --- a/lib/Target/Mips/MipsSEInstrInfo.cpp +++ b/lib/Target/Mips/MipsSEInstrInfo.cpp @@ -95,20 +95,39 @@ void MipsSEInstrInfo::copyPhysReg(MachineBasicBlock &MBB, Opc = Mips::CFC1; else if (Mips::FGR32RegClass.contains(SrcReg)) Opc = Mips::MFC1; - else if (SrcReg == Mips::HI) + else if (Mips::HIRegsRegClass.contains(SrcReg)) Opc = Mips::MFHI, SrcReg = 0; - else if (SrcReg == Mips::LO) + else if (Mips::LORegsRegClass.contains(SrcReg)) Opc = Mips::MFLO, SrcReg = 0; + else if (Mips::HIRegsDSPRegClass.contains(SrcReg)) + Opc = Mips::MFHI_DSP; + else if (Mips::LORegsDSPRegClass.contains(SrcReg)) + Opc = Mips::MFLO_DSP; + else if (Mips::DSPCCRegClass.contains(SrcReg)) { + BuildMI(MBB, I, DL, get(Mips::RDDSP), DestReg).addImm(1 << 4) + .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc)); + return; + } } else if (Mips::CPURegsRegClass.contains(SrcReg)) { // Copy from CPU Reg. if (Mips::CCRRegClass.contains(DestReg)) Opc = Mips::CTC1; else if (Mips::FGR32RegClass.contains(DestReg)) Opc = Mips::MTC1; - else if (DestReg == Mips::HI) + else if (Mips::HIRegsRegClass.contains(DestReg)) Opc = Mips::MTHI, DestReg = 0; - else if (DestReg == Mips::LO) + else if (Mips::LORegsRegClass.contains(DestReg)) Opc = Mips::MTLO, DestReg = 0; + else if (Mips::HIRegsDSPRegClass.contains(DestReg)) + Opc = Mips::MTHI_DSP; + else if (Mips::LORegsDSPRegClass.contains(DestReg)) + Opc = Mips::MTLO_DSP; + else if (Mips::DSPCCRegClass.contains(DestReg)) { + BuildMI(MBB, I, DL, get(Mips::WRDSP)) + .addReg(SrcReg, getKillRegState(KillSrc)).addImm(1 << 4) + .addReg(DestReg, RegState::ImplicitDefine); + return; + } } else if (Mips::FGR32RegClass.contains(DestReg, SrcReg)) Opc = Mips::FMOV_S; @@ -121,27 +140,21 @@ void MipsSEInstrInfo::copyPhysReg(MachineBasicBlock &MBB, else if (Mips::CPU64RegsRegClass.contains(DestReg)) { // Copy to CPU64 Reg. if (Mips::CPU64RegsRegClass.contains(SrcReg)) Opc = Mips::OR64, ZeroReg = Mips::ZERO_64; - else if (SrcReg == Mips::HI64) + else if (Mips::HIRegs64RegClass.contains(SrcReg)) Opc = Mips::MFHI64, SrcReg = 0; - else if (SrcReg == Mips::LO64) + else if (Mips::LORegs64RegClass.contains(SrcReg)) Opc = Mips::MFLO64, SrcReg = 0; else if (Mips::FGR64RegClass.contains(SrcReg)) Opc = Mips::DMFC1; } else if (Mips::CPU64RegsRegClass.contains(SrcReg)) { // Copy from CPU64 Reg. - if (DestReg == Mips::HI64) + if (Mips::HIRegs64RegClass.contains(DestReg)) Opc = Mips::MTHI64, DestReg = 0; - else if (DestReg == Mips::LO64) + else if (Mips::LORegs64RegClass.contains(DestReg)) Opc = Mips::MTLO64, DestReg = 0; else if (Mips::FGR64RegClass.contains(DestReg)) Opc = Mips::DMTC1; } - else if (Mips::ACRegsRegClass.contains(DestReg, SrcReg)) - Opc = Mips::COPY_AC64; - else if (Mips::ACRegsDSPRegClass.contains(DestReg, SrcReg)) - Opc = Mips::COPY_AC_DSP; - else if (Mips::ACRegs128RegClass.contains(DestReg, SrcReg)) - Opc = Mips::COPY_AC128; assert(Opc && "Cannot copy registers"); @@ -178,6 +191,8 @@ storeRegToStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, Opc = IsN64 ? Mips::STORE_AC_DSP_P8 : Mips::STORE_AC_DSP; else if (Mips::ACRegs128RegClass.hasSubClassEq(RC)) Opc = IsN64 ? Mips::STORE_AC128_P8 : Mips::STORE_AC128; + else if (Mips::DSPCCRegClass.hasSubClassEq(RC)) + Opc = IsN64 ? Mips::STORE_CCOND_DSP_P8 : Mips::STORE_CCOND_DSP; else if (Mips::FGR32RegClass.hasSubClassEq(RC)) Opc = IsN64 ? Mips::SWC1_P8 : Mips::SWC1; else if (Mips::AFGR64RegClass.hasSubClassEq(RC)) @@ -209,6 +224,8 @@ loadRegFromStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, Opc = IsN64 ? Mips::LOAD_AC_DSP_P8 : Mips::LOAD_AC_DSP; else if (Mips::ACRegs128RegClass.hasSubClassEq(RC)) Opc = IsN64 ? Mips::LOAD_AC128_P8 : Mips::LOAD_AC128; + else if (Mips::DSPCCRegClass.hasSubClassEq(RC)) + Opc = IsN64 ? Mips::LOAD_CCOND_DSP_P8 : Mips::LOAD_CCOND_DSP; else if (Mips::FGR32RegClass.hasSubClassEq(RC)) Opc = IsN64 ? Mips::LWC1_P8 : Mips::LWC1; else if (Mips::AFGR64RegClass.hasSubClassEq(RC)) diff --git a/lib/Target/Mips/MipsSubtarget.cpp b/lib/Target/Mips/MipsSubtarget.cpp index e11e5d1..14a2b27 100644 --- a/lib/Target/Mips/MipsSubtarget.cpp +++ b/lib/Target/Mips/MipsSubtarget.cpp @@ -11,29 +11,56 @@ // //===----------------------------------------------------------------------===// +#define DEBUG_TYPE "mips-subtarget" + +#include "MipsMachineFunction.h" #include "MipsSubtarget.h" +#include "MipsTargetMachine.h" #include "Mips.h" #include "MipsRegisterInfo.h" +#include "llvm/IR/Attributes.h" +#include "llvm/IR/Function.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/raw_ostream.h" #define GET_SUBTARGETINFO_TARGET_DESC #define GET_SUBTARGETINFO_CTOR #include "MipsGenSubtargetInfo.inc" + using namespace llvm; +// FIXME: Maybe this should be on by default when Mips16 is specified +// +static cl::opt<bool> Mixed16_32( + "mips-mixed-16-32", + cl::init(false), + cl::desc("Allow for a mixture of Mips16 " + "and Mips32 code in a single source file"), + cl::Hidden); + +static cl::opt<bool> Mips_Os16( + "mips-os16", + cl::init(false), + cl::desc("Compile all functions that don' use " + "floating point as Mips 16"), + cl::Hidden); + void MipsSubtarget::anchor() { } MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU, const std::string &FS, bool little, - Reloc::Model _RM) : + Reloc::Model _RM, MipsTargetMachine *_TM) : MipsGenSubtargetInfo(TT, CPU, FS), MipsArchVersion(Mips32), MipsABI(UnknownABI), IsLittle(little), IsSingleFloat(false), IsFP64bit(false), IsGP64bit(false), HasVFPU(false), IsLinux(true), HasSEInReg(false), HasCondMov(false), HasSwap(false), HasBitCount(false), HasFPIdx(false), InMips16Mode(false), InMicroMipsMode(false), HasDSP(false), HasDSPR2(false), - RM(_RM) + AllowMixed16_32(Mixed16_32 | Mips_Os16), Os16(Mips_Os16), + RM(_RM), OverrideMode(NoOverride), TM(_TM) { std::string CPUName = CPU; if (CPUName.empty()) @@ -42,6 +69,8 @@ MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU, // Parse features string. ParseSubtargetFeatures(CPUName, FS); + PreviousInMips16Mode = InMips16Mode; + // Initialize scheduling itinerary for the specified CPU. InstrItins = getInstrItineraryForCPU(CPUName); @@ -72,3 +101,48 @@ MipsSubtarget::enablePostRAScheduler(CodeGenOpt::Level OptLevel, &Mips::CPU64RegsRegClass : &Mips::CPURegsRegClass); return OptLevel >= CodeGenOpt::Aggressive; } + +//FIXME: This logic for reseting the subtarget along with +// the helper classes can probably be simplified but there are a lot of +// cases so we will defer rewriting this to later. +// +void MipsSubtarget::resetSubtarget(MachineFunction *MF) { + bool ChangeToMips16 = false, ChangeToNoMips16 = false; + DEBUG(dbgs() << "resetSubtargetFeatures" << "\n"); + AttributeSet FnAttrs = MF->getFunction()->getAttributes(); + ChangeToMips16 = FnAttrs.hasAttribute(AttributeSet::FunctionIndex, + "mips16"); + ChangeToNoMips16 = FnAttrs.hasAttribute(AttributeSet::FunctionIndex, + "nomips16"); + assert (!(ChangeToMips16 & ChangeToNoMips16) && + "mips16 and nomips16 specified on the same function"); + if (ChangeToMips16) { + if (PreviousInMips16Mode) + return; + OverrideMode = Mips16Override; + PreviousInMips16Mode = true; + TM->setHelperClassesMips16(); + return; + } else if (ChangeToNoMips16) { + if (!PreviousInMips16Mode) + return; + OverrideMode = NoMips16Override; + PreviousInMips16Mode = false; + TM->setHelperClassesMipsSE(); + return; + } else { + if (OverrideMode == NoOverride) + return; + OverrideMode = NoOverride; + DEBUG(dbgs() << "back to default" << "\n"); + if (inMips16Mode() && !PreviousInMips16Mode) { + TM->setHelperClassesMips16(); + PreviousInMips16Mode = true; + } else if (!inMips16Mode() && PreviousInMips16Mode) { + TM->setHelperClassesMipsSE(); + PreviousInMips16Mode = false; + } + return; + } +} + diff --git a/lib/Target/Mips/MipsSubtarget.h b/lib/Target/Mips/MipsSubtarget.h index 7a2e47c..f2f0e15 100644 --- a/lib/Target/Mips/MipsSubtarget.h +++ b/lib/Target/Mips/MipsSubtarget.h @@ -16,7 +16,9 @@ #include "MCTargetDesc/MipsReginfo.h" #include "llvm/MC/MCInstrItineraries.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Target/TargetSubtargetInfo.h" + #include <string> #define GET_SUBTARGETINFO_HEADER @@ -25,6 +27,8 @@ namespace llvm { class StringRef; +class MipsTargetMachine; + class MipsSubtarget : public MipsGenSubtargetInfo { virtual void anchor(); @@ -89,12 +93,23 @@ protected: // InMips16 -- can process Mips16 instructions bool InMips16Mode; + // PreviousInMips16 -- the function we just processed was in Mips 16 Mode + bool PreviousInMips16Mode; + // InMicroMips -- can process MicroMips instructions bool InMicroMipsMode; // HasDSP, HasDSPR2 -- supports DSP ASE. bool HasDSP, HasDSPR2; + // Allow mixed Mips16 and Mips32 in one source file + bool AllowMixed16_32; + + // Optimize for space by compiling all functions as Mips 16 unless + // it needs floating point. Functions needing floating point are + // compiled as Mips32 + bool Os16; + InstrItineraryData InstrItins; // The instance to the register info section object @@ -103,6 +118,12 @@ protected: // Relocation Model Reloc::Model RM; + // We can override the determination of whether we are in mips16 mode + // as from the command line + enum {NoOverride, Mips16Override, NoMips16Override} OverrideMode; + + MipsTargetMachine *TM; + public: virtual bool enablePostRAScheduler(CodeGenOpt::Level OptLevel, AntiDepBreakMode& Mode, @@ -118,7 +139,8 @@ public: /// This constructor initializes the data members to match that /// of the specified triple. MipsSubtarget(const std::string &TT, const std::string &CPU, - const std::string &FS, bool little, Reloc::Model RM); + const std::string &FS, bool little, Reloc::Model RM, + MipsTargetMachine *TM); /// ParseSubtargetFeatures - Parses features string setting specified /// subtarget options. Definition of function is auto generated by tblgen. @@ -137,7 +159,20 @@ public: bool isSingleFloat() const { return IsSingleFloat; } bool isNotSingleFloat() const { return !IsSingleFloat; } bool hasVFPU() const { return HasVFPU; } - bool inMips16Mode() const { return InMips16Mode; } + bool inMips16Mode() const { + switch (OverrideMode) { + case NoOverride: + return InMips16Mode; + case Mips16Override: + return true; + case NoMips16Override: + return false; + } + llvm_unreachable("Unexpected mode"); + } + bool inMips16ModeDefault() { + return InMips16Mode; + } bool inMicroMipsMode() const { return InMicroMipsMode; } bool hasDSP() const { return HasDSP; } bool hasDSPR2() const { return HasDSPR2; } @@ -153,11 +188,20 @@ public: bool hasBitCount() const { return HasBitCount; } bool hasFPIdx() const { return HasFPIdx; } + bool allowMixed16_32() const { return AllowMixed16_32;}; + + bool os16() const { return Os16;}; + // Grab MipsRegInfo object const MipsReginfo &getMReginfo() const { return MRI; } // Grab relocation model Reloc::Model getRelocationModel() const {return RM;} + + /// \brief Reset the subtarget for the Mips target. + void resetSubtarget(MachineFunction *MF); + + }; } // End llvm namespace diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp index 3336358..ee28e2a 100644 --- a/lib/Target/Mips/MipsTargetMachine.cpp +++ b/lib/Target/Mips/MipsTargetMachine.cpp @@ -15,11 +15,26 @@ #include "Mips.h" #include "MipsFrameLowering.h" #include "MipsInstrInfo.h" +#include "MipsModuleISelDAGToDAG.h" +#include "MipsOs16.h" +#include "MipsSEFrameLowering.h" +#include "MipsSEInstrInfo.h" +#include "MipsSEISelLowering.h" +#include "MipsSEISelDAGToDAG.h" +#include "Mips16FrameLowering.h" +#include "Mips16InstrInfo.h" +#include "Mips16ISelDAGToDAG.h" +#include "Mips16ISelLowering.h" +#include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/CodeGen/Passes.h" #include "llvm/PassManager.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Support/TargetRegistry.h" using namespace llvm; + + extern "C" void LLVMInitializeMipsTarget() { // Register the target. RegisterTargetMachine<MipsebTargetMachine> X(TheMipsTarget); @@ -42,7 +57,7 @@ MipsTargetMachine(const Target &T, StringRef TT, CodeGenOpt::Level OL, bool isLittle) : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL), - Subtarget(TT, CPU, FS, isLittle, RM), + Subtarget(TT, CPU, FS, isLittle, RM, this), DL(isLittle ? (Subtarget.isABI_N64() ? "e-p:64:64:64-i8:8:32-i16:16:32-i64:64:64-f128:128:128-" @@ -54,9 +69,46 @@ MipsTargetMachine(const Target &T, StringRef TT, "E-p:32:32:32-i8:8:32-i16:16:32-i64:64:64-n32-S64")), InstrInfo(MipsInstrInfo::create(*this)), FrameLowering(MipsFrameLowering::create(*this, Subtarget)), - TLInfo(MipsTargetLowering::create(*this)), TSInfo(*this), JITInfo() { + TLInfo(MipsTargetLowering::create(*this)), + TSInfo(*this), JITInfo() { +} + + +void MipsTargetMachine::setHelperClassesMips16() { + InstrInfoSE.swap(InstrInfo); + FrameLoweringSE.swap(FrameLowering); + TLInfoSE.swap(TLInfo); + if (!InstrInfo16) { + InstrInfo.reset(MipsInstrInfo::create(*this)); + FrameLowering.reset(MipsFrameLowering::create(*this, Subtarget)); + TLInfo.reset(MipsTargetLowering::create(*this)); + } else { + InstrInfo16.swap(InstrInfo); + FrameLowering16.swap(FrameLowering); + TLInfo16.swap(TLInfo); + } + assert(TLInfo && "null target lowering 16"); + assert(InstrInfo && "null instr info 16"); + assert(FrameLowering && "null frame lowering 16"); } +void MipsTargetMachine::setHelperClassesMipsSE() { + InstrInfo16.swap(InstrInfo); + FrameLowering16.swap(FrameLowering); + TLInfo16.swap(TLInfo); + if (!InstrInfoSE) { + InstrInfo.reset(MipsInstrInfo::create(*this)); + FrameLowering.reset(MipsFrameLowering::create(*this, Subtarget)); + TLInfo.reset(MipsTargetLowering::create(*this)); + } else { + InstrInfoSE.swap(InstrInfo); + FrameLoweringSE.swap(FrameLowering); + TLInfoSE.swap(TLInfo); + } + assert(TLInfo && "null target lowering in SE"); + assert(InstrInfo && "null instr info SE"); + assert(FrameLowering && "null frame lowering SE"); +} void MipsebTargetMachine::anchor() { } MipsebTargetMachine:: @@ -90,6 +142,7 @@ public: return *getMipsTargetMachine().getSubtargetImpl(); } + virtual void addIRPasses(); virtual bool addInstSelector(); virtual bool addPreEmitPass(); }; @@ -99,24 +152,50 @@ TargetPassConfig *MipsTargetMachine::createPassConfig(PassManagerBase &PM) { return new MipsPassConfig(this, PM); } +void MipsPassConfig::addIRPasses() { + TargetPassConfig::addIRPasses(); + if (getMipsSubtarget().os16()) + addPass(createMipsOs16(getMipsTargetMachine())); +} // Install an instruction selector pass using // the ISelDag to gen Mips code. bool MipsPassConfig::addInstSelector() { - addPass(createMipsISelDag(getMipsTargetMachine())); + if (getMipsSubtarget().allowMixed16_32()) { + addPass(createMipsModuleISelDag(getMipsTargetMachine())); + addPass(createMips16ISelDag(getMipsTargetMachine())); + addPass(createMipsSEISelDag(getMipsTargetMachine())); + } else { + addPass(createMipsISelDag(getMipsTargetMachine())); + } return false; } +void MipsTargetMachine::addAnalysisPasses(PassManagerBase &PM) { + if (Subtarget.allowMixed16_32()) { + DEBUG(errs() << "No "); + //FIXME: The Basic Target Transform Info + // pass needs to become a function pass instead of + // being an immutable pass and then this method as it exists now + // would be unnecessary. + PM.add(createNoTargetTransformInfoPass()); + } else + LLVMTargetMachine::addAnalysisPasses(PM); + DEBUG(errs() << "Target Transform Info Pass Added\n"); +} + // Implemented by targets that want to run passes immediately before // machine code is emitted. return true if -print-machineinstrs should // print out the code after the passes. bool MipsPassConfig::addPreEmitPass() { MipsTargetMachine &TM = getMipsTargetMachine(); + const MipsSubtarget &Subtarget = TM.getSubtarget<MipsSubtarget>(); addPass(createMipsDelaySlotFillerPass(TM)); - // NOTE: long branch has not been implemented for mips16. - if (TM.getSubtarget<MipsSubtarget>().hasStandardEncoding()) + if (Subtarget.hasStandardEncoding() || + Subtarget.allowMixed16_32()) addPass(createMipsLongBranchPass(TM)); - if (TM.getSubtarget<MipsSubtarget>().inMips16Mode()) + if (Subtarget.inMips16Mode() || + Subtarget.allowMixed16_32()) addPass(createMipsConstantIslandPass(TM)); return true; diff --git a/lib/Target/Mips/MipsTargetMachine.h b/lib/Target/Mips/MipsTargetMachine.h index 7e5f192..ee55708 100644 --- a/lib/Target/Mips/MipsTargetMachine.h +++ b/lib/Target/Mips/MipsTargetMachine.h @@ -21,6 +21,8 @@ #include "MipsSelectionDAGInfo.h" #include "MipsSubtarget.h" #include "llvm/ADT/OwningPtr.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/IR/DataLayout.h" #include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetMachine.h" @@ -35,6 +37,12 @@ class MipsTargetMachine : public LLVMTargetMachine { OwningPtr<const MipsInstrInfo> InstrInfo; OwningPtr<const MipsFrameLowering> FrameLowering; OwningPtr<const MipsTargetLowering> TLInfo; + OwningPtr<const MipsInstrInfo> InstrInfo16; + OwningPtr<const MipsFrameLowering> FrameLowering16; + OwningPtr<const MipsTargetLowering> TLInfo16; + OwningPtr<const MipsInstrInfo> InstrInfoSE; + OwningPtr<const MipsFrameLowering> FrameLoweringSE; + OwningPtr<const MipsTargetLowering> TLInfoSE; MipsSelectionDAGInfo TSInfo; MipsJITInfo JITInfo; @@ -47,6 +55,8 @@ public: virtual ~MipsTargetMachine() {} + virtual void addAnalysisPasses(PassManagerBase &PM); + virtual const MipsInstrInfo *getInstrInfo() const { return InstrInfo.get(); } virtual const TargetFrameLowering *getFrameLowering() const @@ -73,6 +83,13 @@ public: // Pass Pipeline Configuration virtual TargetPassConfig *createPassConfig(PassManagerBase &PM); virtual bool addCodeEmitter(PassManagerBase &PM, JITCodeEmitter &JCE); + + // Set helper classes + void setHelperClassesMips16(); + + void setHelperClassesMipsSE(); + + }; /// MipsebTargetMachine - Mips32/64 big endian target machine. |