diff options
| author | Vladimir Medic <Vladimir.Medic@imgtec.com> | 2014-07-08 08:59:22 +0000 |
|---|---|---|
| committer | Vladimir Medic <Vladimir.Medic@imgtec.com> | 2014-07-08 08:59:22 +0000 |
| commit | fb8a2a95cd5af1e0202513a559568df8d2882a16 (patch) | |
| tree | 3fc626daa0ab3eba67eedfb47baae3165416f0a2 /llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp | |
| parent | cc02abbb20df1b12ebe5609b9575e9f62b27baf9 (diff) | |
| download | bcm5719-llvm-fb8a2a95cd5af1e0202513a559568df8d2882a16.tar.gz bcm5719-llvm-fb8a2a95cd5af1e0202513a559568df8d2882a16.zip | |
Mips.abiflags is a new implicitly generated section that will be present on all new modules. The section contains a versioned data structure which represents essentially information to allow a program loader to determine the requirements of the application. This patch implements mips.abiflags section and provides test cases for it.
llvm-svn: 212519
Diffstat (limited to 'llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp')
| -rw-r--r-- | llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 233 |
1 files changed, 189 insertions, 44 deletions
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index dc9ed2feeb9..4a0059d55a3 100644 --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -38,7 +38,7 @@ class MCInstrInfo; namespace { class MipsAssemblerOptions { public: - MipsAssemblerOptions() : aTReg(1), reorder(true), macro(true) {} + MipsAssemblerOptions() : aTReg(1), reorder(true), macro(true), fpAbiMode(0) {} unsigned getATRegNum() { return aTReg; } bool setATReg(unsigned Reg); @@ -46,15 +46,18 @@ public: bool isReorder() { return reorder; } void setReorder() { reorder = true; } void setNoreorder() { reorder = false; } + void setFpAbiMode(int Mode) { fpAbiMode = Mode; } bool isMacro() { return macro; } void setMacro() { macro = true; } void setNomacro() { macro = false; } + int getFpAbiMode() { return fpAbiMode; } private: unsigned aTReg; bool reorder; bool macro; + int fpAbiMode; }; } @@ -156,39 +159,17 @@ class MipsAsmParser : public MCTargetAsmParser { bool parseSetReorderDirective(); bool parseSetNoReorderDirective(); bool parseSetNoMips16Directive(); + bool parseSetFpDirective(); bool parseSetAssignment(); bool parseDataDirective(unsigned Size, SMLoc L); bool parseDirectiveGpWord(); bool parseDirectiveGpDWord(); + bool parseDirectiveModule(); MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol); - bool isGP64() const { - return (STI.getFeatureBits() & Mips::FeatureGP64Bit) != 0; - } - - bool isFP64() const { - return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0; - } - - bool isN32() const { return STI.getFeatureBits() & Mips::FeatureN32; } - bool isN64() const { return STI.getFeatureBits() & Mips::FeatureN64; } - - bool isMicroMips() const { - return STI.getFeatureBits() & Mips::FeatureMicroMips; - } - - bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; } - bool hasMips32() const { return STI.getFeatureBits() & Mips::FeatureMips32; } - bool hasMips32r6() const { - return STI.getFeatureBits() & Mips::FeatureMips32r6; - } - bool hasMips64r6() const { - return STI.getFeatureBits() & Mips::FeatureMips64r6; - } - bool eatComma(StringRef ErrorStr); int matchCPURegisterName(StringRef Symbol); @@ -243,12 +224,13 @@ public: }; MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser, - const MCInstrInfo &MII, - const MCTargetOptions &Options) + const MCInstrInfo &MII, const MCTargetOptions &Options) : MCTargetAsmParser(), STI(sti), Parser(parser) { // Initialize the set of available features. setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); + getTargetStreamer().updateABIInfo(*this); + // Assert exactly one ABI was chosen. assert((((STI.getFeatureBits() & Mips::FeatureO32) != 0) + ((STI.getFeatureBits() & Mips::FeatureEABI) != 0) + @@ -262,6 +244,49 @@ public: /// True if all of $fcc0 - $fcc7 exist for the current ISA. bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); } + bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; } + bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; } + bool isABI_N32() const { return STI.getFeatureBits() & Mips::FeatureN32; } + bool isABI_N64() const { return STI.getFeatureBits() & Mips::FeatureN64; } + bool isABI_O32() const { return STI.getFeatureBits() & Mips::FeatureO32; } + bool isABI_FPXX() const { return false; } // TODO: add check for FeatureXX + + bool inMicroMipsMode() const { + return STI.getFeatureBits() & Mips::FeatureMicroMips; + } + bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; } + bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; } + bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; } + bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; } + bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; } + bool hasMips32() const { + return (STI.getFeatureBits() & Mips::FeatureMips32); + } + bool hasMips64() const { + return (STI.getFeatureBits() & Mips::FeatureMips64); + } + bool hasMips32r2() const { + return (STI.getFeatureBits() & Mips::FeatureMips32r2); + } + bool hasMips64r2() const { + return (STI.getFeatureBits() & Mips::FeatureMips64r2); + } + bool hasMips32r6() const { + return (STI.getFeatureBits() & Mips::FeatureMips32r6); + } + bool hasMips64r6() const { + return (STI.getFeatureBits() & Mips::FeatureMips64r6); + } + bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); } + bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); } + bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); } + + bool inMips16Mode() const { + return STI.getFeatureBits() & Mips::FeatureMips16; + } + // TODO: see how can we get this info. + bool mipsSEUsesSoftFloat() const { return false; } + /// Warn if RegNo is the current assembler temporary. void WarnIfAssemblerTemporary(int RegNo, SMLoc Loc); }; @@ -276,9 +301,9 @@ public: /// Broad categories of register classes /// The exact class is finalized by the render method. enum RegKind { - RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64()) + RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit()) RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and - /// isFP64()) + /// isFP64bit()) RegKind_FCC = 4, /// FCC RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which) RegKind_MSACtrl = 16, /// MSA control registers @@ -882,9 +907,10 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, Offset = Inst.getOperand(2); if (!Offset.isImm()) break; // We'll deal with this situation later on when applying fixups. - if (!isIntN(isMicroMips() ? 17 : 18, Offset.getImm())) + if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm())) return Error(IDLoc, "branch target out of range"); - if (OffsetToAlignment(Offset.getImm(), 1LL << (isMicroMips() ? 1 : 2))) + if (OffsetToAlignment(Offset.getImm(), + 1LL << (inMicroMipsMode() ? 1 : 2))) return Error(IDLoc, "branch to misaligned address"); break; case Mips::BGEZ: @@ -907,9 +933,10 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, Offset = Inst.getOperand(1); if (!Offset.isImm()) break; // We'll deal with this situation later on when applying fixups. - if (!isIntN(isMicroMips() ? 17 : 18, Offset.getImm())) + if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm())) return Error(IDLoc, "branch target out of range"); - if (OffsetToAlignment(Offset.getImm(), 1LL << (isMicroMips() ? 1 : 2))) + if (OffsetToAlignment(Offset.getImm(), + 1LL << (inMicroMipsMode() ? 1 : 2))) return Error(IDLoc, "branch to misaligned address"); break; } @@ -994,12 +1021,13 @@ bool MipsAsmParser::needsExpansion(MCInst &Inst) { bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { switch (Inst.getOpcode()) { - default: assert(0 && "unimplemented expansion"); + default: + assert(0 && "unimplemented expansion"); return true; case Mips::LoadImm32Reg: return expandLoadImm(Inst, IDLoc, Instructions); case Mips::LoadImm64Reg: - if (!isGP64()) { + if (!isGP64bit()) { Error(IDLoc, "instruction requires a CPU feature not currently enabled"); return true; } @@ -1074,8 +1102,8 @@ bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc, Instructions.push_back(tmpInst); createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions); } else if ((ImmValue & (0xffffLL << 48)) == 0) { - if (!isGP64()) { - Error (IDLoc, "instruction requires a CPU feature not currently enabled"); + if (!isGP64bit()) { + Error(IDLoc, "instruction requires a CPU feature not currently enabled"); return true; } @@ -1101,8 +1129,8 @@ bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc, createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions); createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions); } else { - if (!isGP64()) { - Error (IDLoc, "instruction requires a CPU feature not currently enabled"); + if (!isGP64bit()) { + Error(IDLoc, "instruction requires a CPU feature not currently enabled"); return true; } @@ -1274,8 +1302,8 @@ void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, // not available. if (!AT) return; - TmpRegNum = - getReg((isGP64()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT); + TmpRegNum = getReg( + (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT); } TempInst.setOpcode(Mips::LUi); @@ -1433,7 +1461,7 @@ int MipsAsmParser::matchCPURegisterName(StringRef Name) { .Case("t9", 25) .Default(-1); - if (isN32() || isN64()) { + if (isABI_N32() || isABI_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. @@ -1546,7 +1574,7 @@ unsigned MipsAsmParser::getReg(int RC, int RegNo) { } unsigned MipsAsmParser::getGPR(int RegNo) { - return getReg(isGP64() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, + return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, RegNo); } @@ -1771,7 +1799,7 @@ bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, // register is a parse error. if (Operand.isGPRAsmReg()) { // Resolve to GPR32 or GPR64 appropriately. - RegNo = isGP64() ? Operand.getGPR64Reg() : Operand.getGPR32Reg(); + RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg(); } return (RegNo == (unsigned)-1); @@ -2227,6 +2255,9 @@ bool MipsAsmParser::ParseBracketSuffix(StringRef Name, bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) { DEBUG(dbgs() << "ParseInstruction\n"); + // We have reached first instruction, module directive after + // this is forbidden. + getTargetStreamer().setCanHaveModuleDir(false); // Check if we have valid mnemonic if (!mnemonicIsValid(Name, 0)) { Parser.eatToEndOfStatement(); @@ -2413,6 +2444,60 @@ bool MipsAsmParser::parseSetNoMips16Directive() { return false; } +bool MipsAsmParser::parseSetFpDirective() { + int FpAbiMode; + // Line can be: .set fp=32 + // .set fp=xx + // .set fp=64 + Parser.Lex(); // Eat fp token + AsmToken Tok = Parser.getTok(); + if (Tok.isNot(AsmToken::Equal)) { + reportParseError("unexpected token in statement"); + return false; + } + Parser.Lex(); // Eat '=' token. + Tok = Parser.getTok(); + if (Tok.is(AsmToken::Identifier)) { + StringRef XX = Tok.getString(); + if (XX != "xx") { + reportParseError("unsupported option"); + return false; + } + if (!isABI_O32()) { + reportParseError("'set fp=xx'option requires O32 ABI"); + return false; + } + FpAbiMode = Val_GNU_MIPS_ABI_FP_XX; + } else if (Tok.is(AsmToken::Integer)) { + unsigned Value = Tok.getIntVal(); + if (Value != 32 && Value != 64) { + reportParseError("unsupported option"); + return false; + } + if (Value == 32) { + if (!isABI_O32()) { + reportParseError("'set fp=32'option requires O32 ABI"); + return false; + } + FpAbiMode = Val_GNU_MIPS_ABI_FP_DOUBLE; + } else { + if (isABI_N32() || isABI_N64()) + FpAbiMode = Val_GNU_MIPS_ABI_FP_DOUBLE; + else if (isABI_O32()) + FpAbiMode = Val_GNU_MIPS_ABI_FP_64; + } + } + Parser.Lex(); // Eat option token. + if (getLexer().isNot(AsmToken::EndOfStatement)) { + reportParseError("unexpected token in statement"); + return false; + } + Options.setFpAbiMode(FpAbiMode); + getTargetStreamer().emitDirectiveSetFp(FpAbiMode, isABI_O32()); + Parser.Lex(); // Consume the EndOfStatement. + return false; +} + bool MipsAsmParser::parseSetAssignment() { StringRef Name; const MCExpr *Value; @@ -2594,6 +2679,8 @@ bool MipsAsmParser::parseDirectiveSet() { return parseSetNoAtDirective(); } else if (Tok.getString() == "at") { return parseSetAtDirective(); + } else if (Tok.getString() == "fp") { + return parseSetFpDirective(); } else if (Tok.getString() == "reorder") { return parseSetReorderDirective(); } else if (Tok.getString() == "noreorder") { @@ -2726,6 +2813,61 @@ bool MipsAsmParser::parseDirectiveOption() { return false; } +bool MipsAsmParser::parseDirectiveModule() { + // Line can be: .module fp=32 + // .module fp=xx + // .module fp=64 + unsigned FpAbiVal = 0; + if (!getTargetStreamer().getCanHaveModuleDir()) { + // TODO : get a better message. + reportParseError(".module directive must appear before any code"); + return false; + } + AsmToken Tok = Parser.getTok(); + if (Tok.isNot(AsmToken::Identifier) && Tok.getString() != "fp") { + reportParseError("unexpected token in .module directive, 'fp' expected"); + return false; + } + Parser.Lex(); // Eat fp token + Tok = Parser.getTok(); + if (Tok.isNot(AsmToken::Equal)) { + reportParseError("unexpected token in statement"); + return false; + } + Parser.Lex(); // Eat '=' token. + Tok = Parser.getTok(); + if (Tok.is(AsmToken::Identifier)) { + StringRef XX = Tok.getString(); + if (XX != "xx") { + reportParseError("unsupported option"); + return false; + } + FpAbiVal = Val_GNU_MIPS_ABI_FP_XX; + } else if (Tok.is(AsmToken::Integer)) { + unsigned Value = Tok.getIntVal(); + if (Value != 32 && Value != 64) { + reportParseError("unsupported value, expected 32 or 64"); + return false; + } + if (Value == 64) { + if (isABI_N32() || isABI_N64()) + FpAbiVal = Val_GNU_MIPS_ABI_FP_DOUBLE; + else if (isABI_O32()) + FpAbiVal = Val_GNU_MIPS_ABI_FP_64; + } else if (isABI_O32()) + FpAbiVal = Val_GNU_MIPS_ABI_FP_DOUBLE; + } + Parser.Lex(); // Eat option token. + if (getLexer().isNot(AsmToken::EndOfStatement)) { + reportParseError("unexpected token in statement"); + return false; + } + // Emit appropriate flags. + getTargetStreamer().emitDirectiveModule(FpAbiVal, isABI_O32()); + getTargetStreamer().setFpABI(FpAbiVal); + Parser.Lex(); // Consume the EndOfStatement. + return false; +} bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { StringRef IDVal = DirectiveID.getString(); @@ -2804,6 +2946,9 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { if (IDVal == ".cpsetup") return parseDirectiveCPSetup(); + if (IDVal == ".module") + return parseDirectiveModule(); + return true; } |

