diff options
author | Jack Carter <jcarter@mips.com> | 2012-10-04 04:03:53 +0000 |
---|---|---|
committer | Jack Carter <jcarter@mips.com> | 2012-10-04 04:03:53 +0000 |
commit | 9d577c861414c28967d77c2a1edf64b68efdeaee (patch) | |
tree | a63152b36a6d8437c3ba11914e687e1183dda3fe | |
parent | 34c6b7e925566cfa71e3087f70c6e4453f51cd25 (diff) |
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) 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)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@165199 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 131 | ||||
-rw-r--r-- | lib/Target/Mips/MipsInstrFormats.td | 8 | ||||
-rw-r--r-- | lib/Target/Mips/MipsInstrInfo.td | 4 | ||||
-rw-r--r-- | test/MC/Mips/mips-expansions.s | 14 |
4 files changed, 129 insertions, 28 deletions
diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index ff55905dfe..f2800d3b61 100644 --- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -92,6 +92,12 @@ class MipsAsmParser : public MCTargetAsmParser { bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Mnemonic); + bool needsExpansion(MCInst &Inst); + + void expandInstruction(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst*> &Instructions); + void expandLoadImm(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst*> &Instructions); bool reportParseError(StringRef ErrorMsg); bool parseMemOffset(const MCExpr *&Res); @@ -296,6 +302,68 @@ public: }; } +bool MipsAsmParser::needsExpansion(MCInst &Inst) { + + switch(Inst.getOpcode()) { + case Mips::LoadImm32Reg: + 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); + } + return; +} +void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst*> &Instructions){ + MCInst *tmpInst = new MCInst(); + const MCOperand &ImmOp = Inst.getOperand(1); + assert(ImmOp.isImm() && "expected imediate operand kind"); + const MCOperand &RegOp = Inst.getOperand(0); + assert(RegOp.isReg() && "expected register operand kind"); + + int ImmValue = ImmOp.getImm(); + tmpInst->setLoc(IDLoc); + if ( 0 <= ImmValue && ImmValue <= 65535) { + // for 0 = j = 65535. + // li d,j => ori d,$zero,j + tmpInst->setOpcode(isMips64() ? Mips::ORi64 : Mips::ORi); + tmpInst->addOperand(MCOperand::CreateReg(RegOp.getReg())); + tmpInst->addOperand( + MCOperand::CreateReg(isMips64() ? Mips::ZERO_64 : Mips::ZERO)); + tmpInst->addOperand(MCOperand::CreateImm(ImmValue)); + Instructions.push_back(tmpInst); + } else if ( ImmValue < 0 && ImmValue >= -32768) { + // for -32768 = j < 0. + // li d,j => addiu d,$zero,j + tmpInst->setOpcode(Mips::ADDiu); //TODO:no ADDiu64 in td files? + tmpInst->addOperand(MCOperand::CreateReg(RegOp.getReg())); + tmpInst->addOperand( + MCOperand::CreateReg(isMips64() ? Mips::ZERO_64 : 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. + // li d,j => lui d,hi16(j) + // ori d,d,lo16(j) + tmpInst->setOpcode(isMips64() ? Mips::LUi64 : Mips::LUi); + tmpInst->addOperand(MCOperand::CreateReg(RegOp.getReg())); + tmpInst->addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16)); + Instructions.push_back(tmpInst); + tmpInst = new MCInst(); + tmpInst->setOpcode(isMips64() ? Mips::ORi64 : Mips::ORi); + tmpInst->addOperand(MCOperand::CreateReg(RegOp.getReg())); + tmpInst->addOperand(MCOperand::CreateReg(RegOp.getReg())); + tmpInst->addOperand(MCOperand::CreateImm(ImmValue & 0xffff)); + tmpInst->setLoc(IDLoc); + Instructions.push_back(tmpInst); + } +} bool MipsAsmParser:: MatchAndEmitInstruction(SMLoc IDLoc, SmallVectorImpl<MCParsedAsmOperand*> &Operands, @@ -311,8 +379,17 @@ MatchAndEmitInstruction(SMLoc IDLoc, switch (MatchResult) { default: break; case Match_Success: { - Inst.setLoc(IDLoc); - Out.EmitInstruction(Inst); + if (needsExpansion(Inst)) { + SmallVector<MCInst*, 4> Instructions; + expandInstruction(Inst, IDLoc, Instructions); + for(unsigned i =0; i < Instructions.size(); i++){ + Inst = *(Instructions[i]); + Out.EmitInstruction(Inst); + } + } else { + Inst.setLoc(IDLoc); + Out.EmitInstruction(Inst); + } return false; } case Match_MissingFeature: @@ -375,7 +452,7 @@ int MipsAsmParser::matchRegisterName(StringRef Name) { .Default(-1); if (CC != -1) { - //64 bit register in Mips are following 32 bit definitions. + // 64 bit register in Mips are following 32 bit definitions. if (isMips64()) CC++; return CC; @@ -385,7 +462,7 @@ int MipsAsmParser::matchRegisterName(StringRef Name) { StringRef NumString = Name.substr(1); unsigned IntVal; if( NumString.getAsInteger(10, IntVal)) - return -1; //not integer + return -1; // not integer if (IntVal > 31) return -1; @@ -397,7 +474,7 @@ int MipsAsmParser::matchRegisterName(StringRef Name) { if(isFP64()) { return getReg(Mips::FGR64RegClassID, IntVal); } - //only even numbers available as register pairs + // only even numbers available as register pairs if (( IntVal > 31) || (IntVal%2 != 0)) return -1; return getReg(Mips::AFGR64RegClassID, IntVal/2); @@ -458,7 +535,7 @@ unsigned MipsAsmParser::getReg(int RC,int RegNo) { int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic) { if (Mnemonic.lower() == "rdhwr") { - //at the moment only hwreg29 is supported + // at the moment only hwreg29 is supported if (RegNum != 29) return -1; return Mips::HWR29; @@ -478,11 +555,11 @@ int MipsAsmParser::tryParseRegister(StringRef Mnemonic) { std::string lowerCase = Tok.getString().lower(); RegNum = matchRegisterName(lowerCase); } else if (Tok.is(AsmToken::Integer)) - RegNum = matchRegisterByNumber(static_cast<unsigned> (Tok.getIntVal()), + RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()), Mnemonic.lower()); else return RegNum; //error - //64 bit div operations require Mips::ZERO instead of MIPS::ZERO_64 + // 64 bit div operations require Mips::ZERO instead of MIPS::ZERO_64 if (isMips64() && RegNum == Mips::ZERO_64) { if (Mnemonic.find("ddiv") != StringRef::npos) RegNum = Mips::ZERO; @@ -497,11 +574,11 @@ bool MipsAsmParser:: SMLoc S = Parser.getTok().getLoc(); int RegNo = -1; - //FIXME: we should make a more generic method for CCR + // FIXME: we should make a more generic method for CCR if ((Mnemonic == "cfc1" || Mnemonic == "ctc1") && Operands.size() == 2 && Parser.getTok().is(AsmToken::Integer)){ - RegNo = Parser.getTok().getIntVal(); //get the int value - //at the moment only fcc0 is supported + RegNo = Parser.getTok().getIntVal(); // get the int value + // at the moment only fcc0 is supported if (RegNo == 0) RegNo = Mips::FCC0; } else @@ -517,8 +594,8 @@ bool MipsAsmParser:: bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands, StringRef Mnemonic) { - //Check if the current operand has a custom associated parser, if so, try to - //custom parse the operand, or fallback to the general approach. + // Check if the current operand has a custom associated parser, if so, try to + // custom parse the operand, or fallback to the general approach. OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); if (ResTy == MatchOperand_Success) return false; @@ -533,20 +610,20 @@ bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands, Error(Parser.getTok().getLoc(), "unexpected token in operand"); return true; case AsmToken::Dollar: { - //parse register + // parse register SMLoc S = Parser.getTok().getLoc(); Parser.Lex(); // Eat dollar token. - //parse register operand - if (!tryParseRegisterOperand(Operands,Mnemonic)) { + // parse register operand + if (!tryParseRegisterOperand(Operands, Mnemonic)) { 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 parenthesis if (getLexer().isNot(AsmToken::Dollar)) return true; - Parser.Lex(); //eat dollar - if (tryParseRegisterOperand(Operands,Mnemonic)) + Parser.Lex(); // eat dollar + if (tryParseRegisterOperand(Operands, Mnemonic)) return true; if (!getLexer().is(AsmToken::RParen)) @@ -558,7 +635,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; @@ -590,9 +667,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; @@ -608,13 +685,13 @@ bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands, bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) { Parser.Lex(); // eat % token - const AsmToken &Tok = Parser.getTok(); //get next token, operation + 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 + Parser.Lex(); // eat identifier // now make expression from the rest of the operand const MCExpr *IdVal; SMLoc EndLoc; @@ -646,7 +723,7 @@ bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) { // Check the type of the expression if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) { - //it's a constant, evaluate lo or hi value + // it's a constant, evaluate lo or hi value int Val = MCE->getValue(); if (Str == "lo") { Val = Val & 0xffff; @@ -1094,8 +1171,6 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { } if (DirectiveID.getString() == ".set") { - // ignore this directive for now - //Parser.EatToEndOfStatement(); return parseDirectiveSet(); } diff --git a/lib/Target/Mips/MipsInstrFormats.td b/lib/Target/Mips/MipsInstrFormats.td index 8feb853572..5cc95a1f5b 100644 --- a/lib/Target/Mips/MipsInstrFormats.td +++ b/lib/Target/Mips/MipsInstrFormats.td @@ -92,6 +92,14 @@ class PseudoSE<dag outs, dag ins, string asmstr, list<dag> pattern>: let Predicates = [HasStandardEncoding]; } +// Pseudo-instructions for alternate assembly syntax (never used by codegen). +// These are aliases that require C++ handling to convert to the target +// instruction, while InstAliases can be handled directly by tblgen. +class MipsAsmPseudoInst<dag outs, dag ins, string asmstr>: + MipsInst<outs, ins, asmstr, [], IIPseudo, Pseudo> { + let isPseudo = 1; + let Pattern = []; +} //===----------------------------------------------------------------------===// // Format R instruction class in Mips : <|opcode|rs|rt|rd|shamt|funct|> //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index 685b785bd2..57615f8db5 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -864,6 +864,10 @@ let usesCustomInserter = 1 in { // Instruction definition //===----------------------------------------------------------------------===// +class LoadImm32< string instr_asm, Operand Od, RegisterClass RC> : + MipsAsmPseudoInst<(outs RC:$rt), (ins Od:$imm32), + !strconcat(instr_asm, "\t$rt, $imm32")> ; +def LoadImm32Reg : LoadImm32<"li",shamt,CPURegs>; //===----------------------------------------------------------------------===// // MipsI Instructions //===----------------------------------------------------------------------===// diff --git a/test/MC/Mips/mips-expansions.s b/test/MC/Mips/mips-expansions.s new file mode 100644 index 0000000000..b87bfbdc5b --- /dev/null +++ b/test/MC/Mips/mips-expansions.s @@ -0,0 +1,14 @@ +# RUN: llvm-mc %s -triple=mipsel-unknown-linux -show-encoding -mcpu=mips32r2 | FileCheck %s +# Check that the assembler can handle the documented syntax +# for macro instructions +# CHECK: .section __TEXT,__text,regular,pure_instructions +#------------------------------------------------------------------------------ +# Load immediate instructions +#------------------------------------------------------------------------------ +# CHECK: ori $5, $zero, 123 # encoding: [0x7b,0x00,0x05,0x34] +# CHECK: addiu $6, $zero, -2345 # encoding: [0xd7,0xf6,0x06,0x24] +# CHECK: lui $7, 1 # encoding: [0x01,0x00,0x07,0x3c] +# CHECK: ori $7, $7, 2 # encoding: [0x02,0x00,0xe7,0x34] + li $5,123 + li $6,-2345 + li $7,65538 |