From fb8a2a95cd5af1e0202513a559568df8d2882a16 Mon Sep 17 00:00:00 2001 From: Vladimir Medic Date: Tue, 8 Jul 2014 08:59:22 +0000 Subject: [PATCH] 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 --- llvm/include/llvm/Support/ELF.h | 4 +- llvm/lib/MC/ELFObjectWriter.cpp | 1 + llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 233 +++++++++++++++++---- .../Mips/MCTargetDesc/MipsTargetStreamer.cpp | 145 +++++++++++-- llvm/lib/Target/Mips/MipsAsmPrinter.cpp | 17 +- llvm/lib/Target/Mips/MipsSubtarget.h | 4 + llvm/lib/Target/Mips/MipsTargetStreamer.h | 193 +++++++++++++++++ llvm/test/CodeGen/Mips/abiflags-xx.ll | 6 + llvm/test/CodeGen/Mips/abiflags32.ll | 12 ++ llvm/test/MC/Mips/mips-abi-bad.s | 20 ++ llvm/test/MC/Mips/mips-data-directives.s | 4 +- llvm/test/MC/Mips/mips32/abiflags.s | 37 ++++ llvm/test/MC/Mips/mips32r2/abiflags.s | 38 ++++ llvm/test/MC/Mips/mips64/abiflags.s | 37 ++++ llvm/test/MC/Mips/mips64r2/abi-bad.s | 9 + llvm/test/MC/Mips/mips64r2/abiflags.s | 37 ++++ llvm/test/MC/Mips/mips_abi_flags_xx.s | 37 ++++ llvm/test/MC/Mips/mips_abi_flags_xx_set.s | 38 ++++ 18 files changed, 804 insertions(+), 68 deletions(-) create mode 100644 llvm/test/CodeGen/Mips/abiflags-xx.ll create mode 100644 llvm/test/CodeGen/Mips/abiflags32.ll create mode 100644 llvm/test/MC/Mips/mips-abi-bad.s create mode 100644 llvm/test/MC/Mips/mips32/abiflags.s create mode 100644 llvm/test/MC/Mips/mips32r2/abiflags.s create mode 100644 llvm/test/MC/Mips/mips64/abiflags.s create mode 100644 llvm/test/MC/Mips/mips64r2/abi-bad.s create mode 100644 llvm/test/MC/Mips/mips64r2/abiflags.s create mode 100644 llvm/test/MC/Mips/mips_abi_flags_xx.s create mode 100644 llvm/test/MC/Mips/mips_abi_flags_xx_set.s diff --git a/llvm/include/llvm/Support/ELF.h b/llvm/include/llvm/Support/ELF.h index 31b34ff..67cc651 100644 --- a/llvm/include/llvm/Support/ELF.h +++ b/llvm/include/llvm/Support/ELF.h @@ -1299,6 +1299,7 @@ enum : unsigned { SHT_MIPS_REGINFO = 0x70000006, // Register usage information SHT_MIPS_OPTIONS = 0x7000000d, // General options + SHT_MIPS_ABIFLAGS = 0x7000002a, // ABI information. SHT_HIPROC = 0x7fffffff, // Highest processor arch-specific type. SHT_LOUSER = 0x80000000, // Lowest type reserved for applications. @@ -1616,7 +1617,8 @@ enum { // MIPS program header types. PT_MIPS_REGINFO = 0x70000000, // Register usage information. PT_MIPS_RTPROC = 0x70000001, // Runtime procedure table. - PT_MIPS_OPTIONS = 0x70000002 // Options segment. + PT_MIPS_OPTIONS = 0x70000002, // Options segment. + PT_MIPS_ABIFLAGS = 0x70000003 // Abiflags segment. }; // Segment flag bits. diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp index ead0535..7fb9fae 100644 --- a/llvm/lib/MC/ELFObjectWriter.cpp +++ b/llvm/lib/MC/ELFObjectWriter.cpp @@ -1565,6 +1565,7 @@ void ELFObjectWriter::WriteSection(MCAssembler &Asm, case ELF::SHT_X86_64_UNWIND: case ELF::SHT_MIPS_REGINFO: case ELF::SHT_MIPS_OPTIONS: + case ELF::SHT_MIPS_ABIFLAGS: // Nothing to do. break; diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index dc9ed2f..4a0059d 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 &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; } diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp index 1b03024..a81849e 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -27,7 +27,8 @@ using namespace llvm; -MipsTargetStreamer::MipsTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {} +MipsTargetStreamer::MipsTargetStreamer(MCStreamer &S) + : MCTargetStreamer(S), canHaveModuleDirective(true) {} void MipsTargetStreamer::emitDirectiveSetMicroMips() {} void MipsTargetStreamer::emitDirectiveSetNoMicroMips() {} void MipsTargetStreamer::emitDirectiveSetMips16() {} @@ -65,42 +66,52 @@ MipsTargetAsmStreamer::MipsTargetAsmStreamer(MCStreamer &S, void MipsTargetAsmStreamer::emitDirectiveSetMicroMips() { OS << "\t.set\tmicromips\n"; + setCanHaveModuleDir(false); } void MipsTargetAsmStreamer::emitDirectiveSetNoMicroMips() { OS << "\t.set\tnomicromips\n"; + setCanHaveModuleDir(false); } void MipsTargetAsmStreamer::emitDirectiveSetMips16() { OS << "\t.set\tmips16\n"; + setCanHaveModuleDir(false); } void MipsTargetAsmStreamer::emitDirectiveSetNoMips16() { OS << "\t.set\tnomips16\n"; + setCanHaveModuleDir(false); } void MipsTargetAsmStreamer::emitDirectiveSetReorder() { OS << "\t.set\treorder\n"; + setCanHaveModuleDir(false); } void MipsTargetAsmStreamer::emitDirectiveSetNoReorder() { OS << "\t.set\tnoreorder\n"; + setCanHaveModuleDir(false); } void MipsTargetAsmStreamer::emitDirectiveSetMacro() { OS << "\t.set\tmacro\n"; + setCanHaveModuleDir(false); } void MipsTargetAsmStreamer::emitDirectiveSetNoMacro() { OS << "\t.set\tnomacro\n"; + setCanHaveModuleDir(false); } void MipsTargetAsmStreamer::emitDirectiveSetAt() { OS << "\t.set\tat\n"; + setCanHaveModuleDir(false); } void MipsTargetAsmStreamer::emitDirectiveSetNoAt() { OS << "\t.set\tnoat\n"; + setCanHaveModuleDir(false); } void MipsTargetAsmStreamer::emitDirectiveEnd(StringRef Name) { @@ -137,24 +148,28 @@ void MipsTargetAsmStreamer::emitFrame(unsigned StackReg, unsigned StackSize, void MipsTargetAsmStreamer::emitDirectiveSetMips32R2() { OS << "\t.set\tmips32r2\n"; + setCanHaveModuleDir(false); } void MipsTargetAsmStreamer::emitDirectiveSetMips64() { OS << "\t.set\tmips64\n"; + setCanHaveModuleDir(false); } void MipsTargetAsmStreamer::emitDirectiveSetMips64R2() { OS << "\t.set\tmips64r2\n"; + setCanHaveModuleDir(false); } void MipsTargetAsmStreamer::emitDirectiveSetDsp() { OS << "\t.set\tdsp\n"; + setCanHaveModuleDir(false); } // Print a 32 bit hex number with all numbers. static void printHex32(unsigned Value, raw_ostream &OS) { OS << "0x"; for (int i = 7; i >= 0; i--) - OS.write_hex((Value & (0xF << (i*4))) >> (i*4)); + OS.write_hex((Value & (0xF << (i * 4))) >> (i * 4)); } void MipsTargetAsmStreamer::emitMask(unsigned CPUBitmask, @@ -174,6 +189,7 @@ void MipsTargetAsmStreamer::emitFMask(unsigned FPUBitmask, void MipsTargetAsmStreamer::emitDirectiveCpload(unsigned RegNo) { OS << "\t.cpload\t$" << StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << "\n"; + setCanHaveModuleDir(false); } void MipsTargetAsmStreamer::emitDirectiveCpsetup(unsigned RegNo, @@ -192,6 +208,57 @@ void MipsTargetAsmStreamer::emitDirectiveCpsetup(unsigned RegNo, OS << ", "; OS << Sym.getName() << "\n"; + setCanHaveModuleDir(false); +} + +void MipsTargetAsmStreamer::emitDirectiveModule(unsigned Value, + bool is32BitAbi) { + StringRef ModuleValue; + OS << "\t.module\tfp="; + switch (Value) { + case Val_GNU_MIPS_ABI_FP_XX: + ModuleValue = "xx"; + break; + case Val_GNU_MIPS_ABI_FP_64: + ModuleValue = "64"; + break; + case Val_GNU_MIPS_ABI_FP_DOUBLE: + if (is32BitAbi) + ModuleValue = "32"; + else + ModuleValue = "64"; + break; + default: + llvm_unreachable("unsupported .module value"); + } + OS << ModuleValue << "\n"; +} + +void MipsTargetAsmStreamer::emitDirectiveSetFp(unsigned Value, + bool is32BitAbi) { + StringRef ModuleValue; + OS << "\t.set\tfp="; + switch (Value) { + case Val_GNU_MIPS_ABI_FP_XX: + ModuleValue = "xx"; + break; + case Val_GNU_MIPS_ABI_FP_64: + ModuleValue = "64"; + break; + case Val_GNU_MIPS_ABI_FP_DOUBLE: + if (is32BitAbi) + ModuleValue = "32"; + else + ModuleValue = "64"; + break; + default: + llvm_unreachable("unsupported .set fp value"); + } + OS << ModuleValue << "\n"; +} + +void MipsTargetAsmStreamer::emitMipsAbiFlags() { + // No action required for text output. } // This part is for ELF object output. @@ -201,7 +268,7 @@ MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S, MCAssembler &MCA = getStreamer().getAssembler(); uint64_t Features = STI.getFeatureBits(); Triple T(STI.getTargetTriple()); - Pic = (MCA.getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_) + Pic = (MCA.getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_) ? true : false; @@ -283,17 +350,17 @@ void MipsTargetELFStreamer::finish() { ELF::SHF_ALLOC | ELF::SHF_MIPS_NOSTRIP, SectionKind::getMetadata()); OS.SwitchSection(Sec); - OS.EmitIntValue(1, 1); // kind + OS.EmitIntValue(1, 1); // kind OS.EmitIntValue(40, 1); // size - OS.EmitIntValue(0, 2); // section - OS.EmitIntValue(0, 4); // info - OS.EmitIntValue(0, 4); // ri_gprmask - OS.EmitIntValue(0, 4); // pad - OS.EmitIntValue(0, 4); // ri_cpr[0]mask - OS.EmitIntValue(0, 4); // ri_cpr[1]mask - OS.EmitIntValue(0, 4); // ri_cpr[2]mask - OS.EmitIntValue(0, 4); // ri_cpr[3]mask - OS.EmitIntValue(0, 8); // ri_gp_value + OS.EmitIntValue(0, 2); // section + OS.EmitIntValue(0, 4); // info + OS.EmitIntValue(0, 4); // ri_gprmask + OS.EmitIntValue(0, 4); // pad + OS.EmitIntValue(0, 4); // ri_cpr[0]mask + OS.EmitIntValue(0, 4); // ri_cpr[1]mask + OS.EmitIntValue(0, 4); // ri_cpr[2]mask + OS.EmitIntValue(0, 4); // ri_cpr[3]mask + OS.EmitIntValue(0, 8); // ri_gp_value } else { const MCSectionELF *Sec = Context.getELFSection(".reginfo", ELF::SHT_MIPS_REGINFO, ELF::SHF_ALLOC, @@ -307,6 +374,7 @@ void MipsTargetELFStreamer::finish() { OS.EmitIntValue(0, 4); // ri_cpr[3]mask OS.EmitIntValue(0, 4); // ri_gp_value } + emitMipsAbiFlags(); } void MipsTargetELFStreamer::emitAssignment(MCSymbol *Symbol, @@ -315,11 +383,11 @@ void MipsTargetELFStreamer::emitAssignment(MCSymbol *Symbol, if (Value->getKind() != MCExpr::SymbolRef) return; const MCSymbol &RhsSym = - static_cast(Value)->getSymbol(); + static_cast(Value)->getSymbol(); MCSymbolData &Data = getStreamer().getOrCreateSymbolData(&RhsSym); uint8_t Type = MCELF::GetType(Data); - if ((Type != ELF::STT_FUNC) - || !(MCELF::getOther(Data) & (ELF::STO_MIPS_MICROMIPS >> 2))) + if ((Type != ELF::STT_FUNC) || + !(MCELF::getOther(Data) & (ELF::STO_MIPS_MICROMIPS >> 2))) return; MCSymbolData &SymbolData = getStreamer().getOrCreateSymbolData(Symbol); @@ -344,6 +412,7 @@ void MipsTargetELFStreamer::emitDirectiveSetMicroMips() { void MipsTargetELFStreamer::emitDirectiveSetNoMicroMips() { MicroMipsEnabled = false; + setCanHaveModuleDir(false); } void MipsTargetELFStreamer::emitDirectiveSetMips16() { @@ -351,14 +420,17 @@ void MipsTargetELFStreamer::emitDirectiveSetMips16() { unsigned Flags = MCA.getELFHeaderEFlags(); Flags |= ELF::EF_MIPS_ARCH_ASE_M16; MCA.setELFHeaderEFlags(Flags); + setCanHaveModuleDir(false); } void MipsTargetELFStreamer::emitDirectiveSetNoMips16() { // FIXME: implement. + setCanHaveModuleDir(false); } void MipsTargetELFStreamer::emitDirectiveSetReorder() { // FIXME: implement. + setCanHaveModuleDir(false); } void MipsTargetELFStreamer::emitDirectiveSetNoReorder() { @@ -366,22 +438,27 @@ void MipsTargetELFStreamer::emitDirectiveSetNoReorder() { unsigned Flags = MCA.getELFHeaderEFlags(); Flags |= ELF::EF_MIPS_NOREORDER; MCA.setELFHeaderEFlags(Flags); + setCanHaveModuleDir(false); } void MipsTargetELFStreamer::emitDirectiveSetMacro() { // FIXME: implement. + setCanHaveModuleDir(false); } void MipsTargetELFStreamer::emitDirectiveSetNoMacro() { // FIXME: implement. + setCanHaveModuleDir(false); } void MipsTargetELFStreamer::emitDirectiveSetAt() { // FIXME: implement. + setCanHaveModuleDir(false); } void MipsTargetELFStreamer::emitDirectiveSetNoAt() { // FIXME: implement. + setCanHaveModuleDir(false); } void MipsTargetELFStreamer::emitDirectiveEnd(StringRef Name) { @@ -450,19 +527,19 @@ void MipsTargetELFStreamer::emitFMask(unsigned FPUBitmask, } void MipsTargetELFStreamer::emitDirectiveSetMips32R2() { - // No action required for ELF output. + setCanHaveModuleDir(false); } void MipsTargetELFStreamer::emitDirectiveSetMips64() { - // No action required for ELF output. + setCanHaveModuleDir(false); } void MipsTargetELFStreamer::emitDirectiveSetMips64R2() { - // No action required for ELF output. + setCanHaveModuleDir(false); } void MipsTargetELFStreamer::emitDirectiveSetDsp() { - // No action required for ELF output. + setCanHaveModuleDir(false); } void MipsTargetELFStreamer::emitDirectiveCpload(unsigned RegNo) { @@ -512,6 +589,8 @@ void MipsTargetELFStreamer::emitDirectiveCpload(unsigned RegNo) { TmpInst.addOperand(MCOperand::CreateReg(Mips::GP)); TmpInst.addOperand(MCOperand::CreateReg(RegNo)); getStreamer().EmitInstruction(TmpInst, STI); + + setCanHaveModuleDir(false); } void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo, @@ -567,4 +646,30 @@ void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo, Inst.addOperand(MCOperand::CreateReg(Mips::GP)); Inst.addOperand(MCOperand::CreateReg(RegNo)); getStreamer().EmitInstruction(Inst, STI); + + setCanHaveModuleDir(false); +} + +void MipsTargetELFStreamer::emitMipsAbiFlags() { + MCAssembler &MCA = getStreamer().getAssembler(); + MCContext &Context = MCA.getContext(); + MCStreamer &OS = getStreamer(); + const MCSectionELF *Sec = + Context.getELFSection(".MIPS.abiflags", ELF::SHT_MIPS_ABIFLAGS, + ELF::SHF_ALLOC, SectionKind::getMetadata()); + MCSectionData &ABIShndxSD = MCA.getOrCreateSectionData(*Sec); + ABIShndxSD.setAlignment(8); + OS.SwitchSection(Sec); + + OS.EmitIntValue(MipsABIFlags.version, 2); // version + OS.EmitIntValue(MipsABIFlags.isa_level, 1); // isa_level + OS.EmitIntValue(MipsABIFlags.isa_rev, 1); // isa_rev + OS.EmitIntValue(MipsABIFlags.gpr_size, 1); // gpr_size + OS.EmitIntValue(MipsABIFlags.cpr1_size, 1); // cpr1_size + OS.EmitIntValue(MipsABIFlags.cpr2_size, 1); // cpr2_size + OS.EmitIntValue(MipsABIFlags.fp_abi, 1); // fp_abi + OS.EmitIntValue(MipsABIFlags.isa_ext, 4); // isa_ext + OS.EmitIntValue(MipsABIFlags.ases, 4); // ases + OS.EmitIntValue(MipsABIFlags.flags1, 4); // flags1 + OS.EmitIntValue(MipsABIFlags.flags2, 4); // flags2 } diff --git a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp index 6df90aa..6070932 100644 --- a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp @@ -92,6 +92,8 @@ bool MipsAsmPrinter::lowerOperand(const MachineOperand &MO, MCOperand &MCOp) { #include "MipsGenMCPseudoLowering.inc" void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { + MipsTargetStreamer &TS = getTargetStreamer(); + TS.setCanHaveModuleDir(false); if (MI->isDebugValue()) { SmallString<128> Str; raw_svector_ostream OS(Str); @@ -657,6 +659,19 @@ void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { OutContext.getELFSection(".gcc_compiled_long64", ELF::SHT_PROGBITS, 0, SectionKind::getDataRel())); } + getTargetStreamer().updateABIInfo(*Subtarget); + unsigned FpAbiVal; + if (Subtarget->isABI_N32() || Subtarget->isABI_N64()) + FpAbiVal = Val_GNU_MIPS_ABI_FP_DOUBLE; + else if(Subtarget->isABI_O32()) { + if (Subtarget->isFP64bit()) + FpAbiVal = Val_GNU_MIPS_ABI_FP_64; + else if(Subtarget->isABI_FPXX()) + FpAbiVal = Val_GNU_MIPS_ABI_FP_XX; + else + FpAbiVal = Val_GNU_MIPS_ABI_FP_DOUBLE; + } + getTargetStreamer().emitDirectiveModule(FpAbiVal, Subtarget->isABI_O32()); } void MipsAsmPrinter::EmitJal(MCSymbol *Symbol) { @@ -852,7 +867,7 @@ void MipsAsmPrinter::EmitFPCallStub( TS.emitDirectiveSetNoMicroMips(); // // .ent __call_stub_fp_xxxx - // .type __call_stub_fp_xxxx,@function + // .type __call_stub_fp_xxxx,@function // __call_stub_fp_xxxx: // std::string x = "__call_stub_fp_" + std::string(Symbol); diff --git a/llvm/lib/Target/Mips/MipsSubtarget.h b/llvm/lib/Target/Mips/MipsSubtarget.h index f8c4e3b..1d94bba 100644 --- a/llvm/lib/Target/Mips/MipsSubtarget.h +++ b/llvm/lib/Target/Mips/MipsSubtarget.h @@ -162,6 +162,7 @@ public: bool isABI_N64() const { return MipsABI == N64; } bool isABI_N32() const { return MipsABI == N32; } bool isABI_O32() const { return MipsABI == O32; } + bool isABI_FPXX() const { return false; } // TODO: add check for FPXX unsigned getTargetABI() const { return MipsABI; } /// This constructor initializes the data members to match that @@ -174,8 +175,11 @@ public: /// subtarget options. Definition of function is auto generated by tblgen. void ParseSubtargetFeatures(StringRef CPU, StringRef FS); + bool hasMips1() const { return MipsArchVersion >= Mips1; } bool hasMips2() const { return MipsArchVersion >= Mips2; } bool hasMips3() const { return MipsArchVersion >= Mips3; } + bool hasMips4() const { return MipsArchVersion >= Mips4; } + bool hasMips5() const { return MipsArchVersion >= Mips5; } bool hasMips4_32() const { return HasMips4_32; } bool hasMips4_32r2() const { return HasMips4_32r2; } bool hasMips32() const { diff --git a/llvm/lib/Target/Mips/MipsTargetStreamer.h b/llvm/lib/Target/Mips/MipsTargetStreamer.h index 2ae6138..a0edc6f 100644 --- a/llvm/lib/Target/Mips/MipsTargetStreamer.h +++ b/llvm/lib/Target/Mips/MipsTargetStreamer.h @@ -14,6 +14,88 @@ #include "llvm/MC/MCStreamer.h" namespace llvm { +struct Elf_Internal_ABIFlags_v0 { + // Version of flags structure. + uint16_t version; + // The level of the ISA: 1-5, 32, 64. + uint8_t isa_level; + // The revision of ISA: 0 for MIPS V and below, 1-n otherwise. + uint8_t isa_rev; + // The size of general purpose registers. + uint8_t gpr_size; + // The size of co-processor 1 registers. + uint8_t cpr1_size; + // The size of co-processor 2 registers. + uint8_t cpr2_size; + // The floating-point ABI. + uint8_t fp_abi; + // Processor-specific extension. + uint32_t isa_ext; + // Mask of ASEs used. + uint32_t ases; + // Mask of general flags. + uint32_t flags1; + uint32_t flags2; + + Elf_Internal_ABIFlags_v0() + : version(0), isa_level(0), isa_rev(0), gpr_size(0), cpr1_size(0), + cpr2_size(0), fp_abi(0), isa_ext(0), ases(0), flags1(0), flags2(0) {} +}; + +// Values for the xxx_size bytes of an ABI flags structure. +enum { + AFL_REG_NONE = 0x00, // No registers. + AFL_REG_32 = 0x01, // 32-bit registers. + AFL_REG_64 = 0x02, // 64-bit registers. + AFL_REG_128 = 0x03 // 128-bit registers. +}; + +// Masks for the ases word of an ABI flags structure. +enum { + AFL_ASE_DSP = 0x00000001, // DSP ASE. + AFL_ASE_DSPR2 = 0x00000002, // DSP R2 ASE. + AFL_ASE_EVA = 0x00000004, // Enhanced VA Scheme. + AFL_ASE_MCU = 0x00000008, // MCU (MicroController) ASE. + AFL_ASE_MDMX = 0x00000010, // MDMX ASE. + AFL_ASE_MIPS3D = 0x00000020, // MIPS-3D ASE. + AFL_ASE_MT = 0x00000040, // MT ASE. + AFL_ASE_SMARTMIPS = 0x00000080, // SmartMIPS ASE. + AFL_ASE_VIRT = 0x00000100, // VZ ASE. + AFL_ASE_MSA = 0x00000200, // MSA ASE. + AFL_ASE_MIPS16 = 0x00000400, // MIPS16 ASE. + AFL_ASE_MICROMIPS = 0x00000800, // MICROMIPS ASE. + AFL_ASE_XPA = 0x00001000 // XPA ASE. +}; + +// Values for the isa_ext word of an ABI flags structure. +enum { + AFL_EXT_XLR = 1, // RMI Xlr instruction. + AFL_EXT_OCTEON2 = 2, // Cavium Networks Octeon2. + AFL_EXT_OCTEONP = 3, // Cavium Networks OcteonP. + AFL_EXT_LOONGSON_3A = 4, // Loongson 3A. + AFL_EXT_OCTEON = 5, // Cavium Networks Octeon. + AFL_EXT_5900 = 6, // MIPS R5900 instruction. + AFL_EXT_4650 = 7, // MIPS R4650 instruction. + AFL_EXT_4010 = 8, // LSI R4010 instruction. + AFL_EXT_4100 = 9, // NEC VR4100 instruction. + AFL_EXT_3900 = 10, // Toshiba R3900 instruction. + AFL_EXT_10000 = 11, // MIPS R10000 instruction. + AFL_EXT_SB1 = 12, // Broadcom SB-1 instruction. + AFL_EXT_4111 = 13, // NEC VR4111/VR4181 instruction. + AFL_EXT_4120 = 14, // NEC VR4120 instruction. + AFL_EXT_5400 = 15, // NEC VR5400 instruction. + AFL_EXT_5500 = 16, // NEC VR5500 instruction. + AFL_EXT_LOONGSON_2E = 17, // ST Microelectronics Loongson 2E. + AFL_EXT_LOONGSON_2F = 18 // ST Microelectronics Loongson 2F. +}; + +// Values for the fp_abi word of an ABI flags structure. +enum { + Val_GNU_MIPS_ABI_FP_DOUBLE = 1, + Val_GNU_MIPS_ABI_FP_XX = 5, + Val_GNU_MIPS_ABI_FP_64 = 6 +}; + class MipsTargetStreamer : public MCTargetStreamer { public: MipsTargetStreamer(MCStreamer &S); @@ -50,6 +132,109 @@ public: virtual void emitDirectiveCpload(unsigned RegNo); virtual void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, const MCSymbol &Sym, bool IsReg); + // ABI Flags + virtual void emitDirectiveModule(unsigned Value, bool is32BitAbi){}; + virtual void emitDirectiveSetFp(unsigned Value, bool is32BitAbi){}; + virtual void emitMipsAbiFlags(){}; + void setCanHaveModuleDir(bool Can) { canHaveModuleDirective = Can; } + bool getCanHaveModuleDir() { return canHaveModuleDirective; } + + void setVersion(uint16_t Version) { MipsABIFlags.version = Version; } + void setISALevel(uint8_t Level) { MipsABIFlags.isa_level = Level; } + void setISARev(uint8_t Rev) { MipsABIFlags.isa_rev = Rev; } + void setGprSize(uint8_t Size) { MipsABIFlags.gpr_size = Size; } + void setCpr1Size(uint8_t Size) { MipsABIFlags.cpr1_size = Size; } + void setCpr2Size(uint8_t Size) { MipsABIFlags.cpr2_size = Size; } + void setFpABI(uint8_t Abi) { MipsABIFlags.fp_abi = Abi; } + void setIsaExt(uint32_t IsaExt) { MipsABIFlags.isa_ext = IsaExt; } + void setASEs(uint32_t Ases) { MipsABIFlags.ases = Ases; } + void setFlags1(uint32_t Flags) { MipsABIFlags.flags1 = Flags; } + void setFlags2(uint32_t Flags) { MipsABIFlags.flags2 = Flags; } + + uint8_t getFPAbi() { return MipsABIFlags.fp_abi; } + // This method enables template classes to set internal abi flags + // structure values. + template + void updateABIInfo(const PredicateLibrary &P) { + setVersion(0); // Version, default value is 0. + + if (P.hasMips64()) { // isa_level + setISALevel(64); + if (P.hasMips64r6()) + setISARev(6); + else if (P.hasMips64r2()) + setISARev(2); + else + setISARev(1); + } else if (P.hasMips32()) { + setISALevel(32); + if (P.hasMips32r6()) + setISARev(6); + else if (P.hasMips32r2()) + setISARev(2); + else + setISARev(1); + } else { + setISARev(0); + if (P.hasMips5()) + setISALevel(5); + else if (P.hasMips4()) + setISALevel(4); + else if (P.hasMips3()) + setISALevel(3); + else if (P.hasMips2()) + setISALevel(2); + else if (P.hasMips1()) + setISALevel(1); + else + llvm_unreachable("Unknown ISA level!"); + } + + if (P.isGP64bit()) // GPR size. + setGprSize(AFL_REG_64); + else + setGprSize(AFL_REG_32); + + // TODO: check for MSA128 value. + if (P.mipsSEUsesSoftFloat()) + setCpr1Size(AFL_REG_NONE); + else if (P.isFP64bit()) + setCpr1Size(AFL_REG_64); + else + setCpr1Size(AFL_REG_32); + setCpr2Size(AFL_REG_NONE); // Default value. + + // Set ASE. + unsigned AseFlags = 0; + if (P.hasDSP()) + AseFlags |= AFL_ASE_DSP; + if (P.hasDSPR2()) + AseFlags |= AFL_ASE_DSPR2; + if (P.hasMSA()) + AseFlags |= AFL_ASE_MSA; + if (P.inMicroMipsMode()) + AseFlags |= AFL_ASE_MICROMIPS; + if (P.inMips16Mode()) + AseFlags |= AFL_ASE_MIPS16; + + if (P.isABI_N32() || P.isABI_N64()) + setFpABI(Val_GNU_MIPS_ABI_FP_DOUBLE); + else if (P.isABI_O32()) { + if (P.isFP64bit()) + setFpABI(Val_GNU_MIPS_ABI_FP_64); + else if (P.isABI_FPXX()) + setFpABI(Val_GNU_MIPS_ABI_FP_XX); + else + setFpABI(Val_GNU_MIPS_ABI_FP_DOUBLE); + } else + setFpABI(0); // Default value. + } + +protected: + Elf_Internal_ABIFlags_v0 MipsABIFlags; + +private: + bool canHaveModuleDirective; }; // This part is for ascii assembly output @@ -91,6 +276,11 @@ public: virtual void emitDirectiveCpload(unsigned RegNo); void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, const MCSymbol &Sym, bool IsReg) override; + + // ABI Flags + void emitDirectiveModule(unsigned Value, bool is32BitAbi) override; + void emitDirectiveSetFp(unsigned Value, bool is32BitAbi) override; + void emitMipsAbiFlags() override; }; // This part is for ELF object output @@ -142,6 +332,9 @@ public: void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, const MCSymbol &Sym, bool IsReg) override; + // ABI Flags + void emitMipsAbiFlags() override; + protected: bool isO32() const { return STI.getFeatureBits() & Mips::FeatureO32; } bool isN32() const { return STI.getFeatureBits() & Mips::FeatureN32; } diff --git a/llvm/test/CodeGen/Mips/abiflags-xx.ll b/llvm/test/CodeGen/Mips/abiflags-xx.ll new file mode 100644 index 0000000..b8aa071 --- /dev/null +++ b/llvm/test/CodeGen/Mips/abiflags-xx.ll @@ -0,0 +1,6 @@ +; RUN: llc -filetype=asm -mtriple mipsel-unknown-linux -mcpu=mips32 -mattr=fpxx %s -o - | FileCheck %s +; XFAIL: * + +; CHECK: .nan legacy +; CHECK: .module fp=xx + diff --git a/llvm/test/CodeGen/Mips/abiflags32.ll b/llvm/test/CodeGen/Mips/abiflags32.ll new file mode 100644 index 0000000..093964f --- /dev/null +++ b/llvm/test/CodeGen/Mips/abiflags32.ll @@ -0,0 +1,12 @@ +; RUN: llc -filetype=asm -mtriple mipsel-unknown-linux -mcpu=mips32 %s -o - | FileCheck %s +; RUN: llc -filetype=asm -mtriple mipsel-unknown-linux -mcpu=mips32 -mattr=fp64 %s -o - | FileCheck -check-prefix=CHECK-64 %s +; RUN: llc -filetype=asm -mtriple mipsel-unknown-linux -mcpu=mips64 -mattr=-n64,n32 %s -o - | FileCheck -check-prefix=CHECK-64n %s + +; CHECK: .nan legacy +; CHECK: .module fp=32 + +; CHECK-64: .nan legacy +; CHECK-64: .module fp=64 + +; CHECK-64n: .nan legacy +; CHECK-64n: .module fp=64 diff --git a/llvm/test/MC/Mips/mips-abi-bad.s b/llvm/test/MC/Mips/mips-abi-bad.s new file mode 100644 index 0000000..c4653cf --- /dev/null +++ b/llvm/test/MC/Mips/mips-abi-bad.s @@ -0,0 +1,20 @@ +# Error checking for malformed abi related directives +# RUN: not llvm-mc -triple mips-unknown-unknown %s 2>&1 | FileCheck %s +# CHECK: .text + .module fp=3 +# CHECK : mips-abi-bad.s:4:16: error: unsupported option +# CHECK-NEXT : .module fp=3 +# CHECK-NEXT : ^ + + .set fp=xx,6 +# CHECK :mips-abi-bad.s:5:15: error: unexpected token in statement +# CHECK-NEXT : .set fp=xx,6 +# CHECK-NEXT : ^ + +# CHECK :.set mips16 + .set mips16 + .module fp=32 + +# CHECK :mips-abi-bad.s:14:13: error: .module directive must come before any code +# CHECK-NEXT : .module fp=32 +# CHECK-NEXT : ^ diff --git a/llvm/test/MC/Mips/mips-data-directives.s b/llvm/test/MC/Mips/mips-data-directives.s index 630a807..8b3e0b3 100644 --- a/llvm/test/MC/Mips/mips-data-directives.s +++ b/llvm/test/MC/Mips/mips-data-directives.s @@ -12,7 +12,7 @@ # Checking if the data and reloations were correctly emitted # CHECK-OBJ: Section { -# CHECK-OBJ: Name: .data (51) +# CHECK-OBJ: Name: .data (66) # CHECK-OBJ: SectionData ( # CHECK-OBJ: 0000: DEADC0DE DEADC0DE DEADBEEF 00000000 # CHECK-OBJ: 0010: 00000000 00000000 @@ -20,7 +20,7 @@ # CHECK-OBJ: } # CHECK-OBJ: Section { -# CHECK-OBJ: Name: .rel.data (47) +# CHECK-OBJ: Name: .rel.data (62) # CHECK-OBJ: Relocations [ # CHECK-OBJ: 0xC R_MIPS_32 .data 0x0 # CHECK-OBJ: 0x10 R_MIPS_64 .data 0x0 diff --git a/llvm/test/MC/Mips/mips32/abiflags.s b/llvm/test/MC/Mips/mips32/abiflags.s new file mode 100644 index 0000000..896dd842 --- /dev/null +++ b/llvm/test/MC/Mips/mips32/abiflags.s @@ -0,0 +1,37 @@ +# RUN: llvm-mc %s -arch=mips -mcpu=mips32 | \ +# RUN: FileCheck %s -check-prefix=CHECK-ASM +# +# RUN: llvm-mc %s -arch=mips -mcpu=mips32 -filetype=obj -o - | \ +# RUN: llvm-readobj -sections -section-data -section-relocations - | \ +# RUN: FileCheck %s -check-prefix=CHECK-OBJ + +# CHECK-ASM: .module fp=32 + +# Checking if the Mips.abiflags were correctly emitted. +# CHECK-OBJ: Section { +# CHECK-OBJ: Index: 5 +# CHECK-OBJ: Name: .MIPS.abiflags (12) +# CHECK-OBJ: Type: (0x7000002A) +# CHECK-OBJ: Flags [ (0x2) +# CHECK-OBJ: SHF_ALLOC (0x2) +# CHECK-OBJ: ] +# CHECK-OBJ: Address: 0x0 +# CHECK-OBJ: Offset: 0x50 +# CHECK-OBJ: Size: 24 +# CHECK-OBJ: Link: 0 +# CHECK-OBJ: Info: 0 +# CHECK-OBJ: AddressAlignment: 8 +# CHECK-OBJ: EntrySize: 0 +# CHECK-OBJ: Relocations [ +# CHECK-OBJ: ] +# CHECK-OBJ: SectionData ( +# CHECK-OBJ: 0000: 00002001 01010001 00000000 00000000 |.. .............| +# CHECK-OBJ: 0010: 00000000 00000000 |........| +# CHECK-OBJ: ) +# CHECK-OBJ: } + + .module fp=32 + +# FIXME: Test should include gnu_attributes directive when implemented. +# An explicit .gnu_attribute must be checked against the effective +# command line options and any inconsistencies reported via a warning. diff --git a/llvm/test/MC/Mips/mips32r2/abiflags.s b/llvm/test/MC/Mips/mips32r2/abiflags.s new file mode 100644 index 0000000..41a809a --- /dev/null +++ b/llvm/test/MC/Mips/mips32r2/abiflags.s @@ -0,0 +1,38 @@ +# RUN: llvm-mc %s -arch=mips -mcpu=mips32r2 | \ +# RUN: FileCheck %s -check-prefix=CHECK-ASM +# +# RUN: llvm-mc %s -arch=mips -mcpu=mips32r2 -filetype=obj -o - | \ +# RUN: llvm-readobj -sections -section-data -section-relocations - | \ +# RUN: FileCheck %s -check-prefix=CHECK-OBJ + +# CHECK-ASM: .module fp=32 +# CHECK-ASM: .set fp=64 + +# Checking if the Mips.abiflags were correctly emitted. +# CHECK-OBJ: Section { +# CHECK-OBJ: Index: 5 +# CHECK-OBJ: Name: .MIPS.abiflags (12) +# CHECK-OBJ: Type: (0x7000002A) +# CHECK-OBJ: Flags [ (0x2) +# CHECK-OBJ: SHF_ALLOC (0x2) +# CHECK-OBJ: ] +# CHECK-OBJ: Address: 0x0 +# CHECK-OBJ: Offset: 0x50 +# CHECK-OBJ: Size: 24 +# CHECK-OBJ: Link: 0 +# CHECK-OBJ: Info: 0 +# CHECK-OBJ: AddressAlignment: 8 +# CHECK-OBJ: EntrySize: 0 +# CHECK-OBJ: Relocations [ +# CHECK-OBJ: ] +# CHECK-OBJ: SectionData ( +# CHECK-OBJ: 0000: 00002002 01010001 00000000 00000000 |.. .............| +# CHECK-OBJ: 0010: 00000000 00000000 |........| +# CHECK-OBJ: ) +# CHECK-OBJ: } + + .module fp=32 + .set fp=64 +# FIXME: Test should include gnu_attributes directive when implemented. +# An explicit .gnu_attribute must be checked against the effective +# command line options and any inconsistencies reported via a warning. diff --git a/llvm/test/MC/Mips/mips64/abiflags.s b/llvm/test/MC/Mips/mips64/abiflags.s new file mode 100644 index 0000000..557e32a --- /dev/null +++ b/llvm/test/MC/Mips/mips64/abiflags.s @@ -0,0 +1,37 @@ +# RUN: llvm-mc %s -arch=mips -mcpu=mips64 | \ +# RUN: FileCheck %s -check-prefix=CHECK-ASM +# +# RUN: llvm-mc %s -arch=mips -mcpu=mips64 -filetype=obj -o - | \ +# RUN: llvm-readobj -sections -section-data -section-relocations - | \ +# RUN: FileCheck %s -check-prefix=CHECK-OBJ + +# CHECK-ASM: .module fp=64 + +# Checking if the Mips.abiflags were correctly emitted. +# CHECK-OBJ: Section { +# CHECK-OBJ: Index: 5 +# CHECK-OBJ: Name: .MIPS.abiflags (12) +# CHECK-OBJ: Type: (0x7000002A) +# CHECK-OBJ: Flags [ (0x2) +# CHECK-OBJ: SHF_ALLOC (0x2) +# CHECK-OBJ: ] +# CHECK-OBJ: Address: 0x0 +# CHECK-OBJ: Offset: 0x50 +# CHECK-OBJ: Size: 24 +# CHECK-OBJ: Link: 0 +# CHECK-OBJ: Info: 0 +# CHECK-OBJ: AddressAlignment: 8 +# CHECK-OBJ: EntrySize: 0 +# CHECK-OBJ: Relocations [ +# CHECK-OBJ: ] +# CHECK-OBJ: SectionData ( +# CHECK-OBJ: 0000: 00004001 02020001 00000000 00000000 |..@.............| +# CHECK-OBJ: 0010: 00000000 00000000 |........| +# CHECK-OBJ: ) +# CHECK-OBJ: } + + .module fp=64 + +# FIXME: Test should include gnu_attributes directive when implemented. +# An explicit .gnu_attribute must be checked against the effective +# command line options and any inconsistencies reported via a warning. diff --git a/llvm/test/MC/Mips/mips64r2/abi-bad.s b/llvm/test/MC/Mips/mips64r2/abi-bad.s new file mode 100644 index 0000000..31d13ab --- /dev/null +++ b/llvm/test/MC/Mips/mips64r2/abi-bad.s @@ -0,0 +1,9 @@ +# RUN: not llvm-mc %s -triple mips-unknown-unknown -mcpu=mips64r2 2>&1 | FileCheck %s +# CHECK: .text + + + + .set fp=xx +# CHECK : error: 'set fp=xx'option requires O32 ABI +# CHECK : .set fp=xx +# CHECK : ^ diff --git a/llvm/test/MC/Mips/mips64r2/abiflags.s b/llvm/test/MC/Mips/mips64r2/abiflags.s new file mode 100644 index 0000000..aa76dee --- /dev/null +++ b/llvm/test/MC/Mips/mips64r2/abiflags.s @@ -0,0 +1,37 @@ +# RUN: llvm-mc %s -arch=mips -mcpu=mips64r2 | \ +# RUN: FileCheck %s -check-prefix=CHECK-ASM +# +# RUN: llvm-mc %s -arch=mips -mcpu=mips64r2 -filetype=obj -o - | \ +# RUN: llvm-readobj -sections -section-data -section-relocations - | \ +# RUN: FileCheck %s -check-prefix=CHECK-OBJ + +# CHECK-ASM: .module fp=64 + +# Checking if the Mips.abiflags were correctly emitted. +# CHECK-OBJ: Section { +# CHECK-OBJ: Index: 5 +# CHECK-OBJ: Name: .MIPS.abiflags (12) +# CHECK-OBJ: Type: (0x7000002A) +# CHECK-OBJ: Flags [ (0x2) +# CHECK-OBJ: SHF_ALLOC (0x2) +# CHECK-OBJ: ] +# CHECK-OBJ: Address: 0x0 +# CHECK-OBJ: Offset: 0x50 +# CHECK-OBJ: Size: 24 +# CHECK-OBJ: Link: 0 +# CHECK-OBJ: Info: 0 +# CHECK-OBJ: AddressAlignment: 8 +# CHECK-OBJ: EntrySize: 0 +# CHECK-OBJ: Relocations [ +# CHECK-OBJ: ] +# CHECK-OBJ: SectionData ( +# CHECK-OBJ: 0000: 00004002 02020001 00000000 00000000 |..@.............| +# CHECK-OBJ: 0010: 00000000 00000000 |........| +# CHECK-OBJ: ) +# CHECK-OBJ: } + + .module fp=64 + +# FIXME: Test should include gnu_attributes directive when implemented. +# An explicit .gnu_attribute must be checked against the effective +# command line options and any inconsistencies reported via a warning. diff --git a/llvm/test/MC/Mips/mips_abi_flags_xx.s b/llvm/test/MC/Mips/mips_abi_flags_xx.s new file mode 100644 index 0000000..1d65e99 --- /dev/null +++ b/llvm/test/MC/Mips/mips_abi_flags_xx.s @@ -0,0 +1,37 @@ +# RUN: llvm-mc %s -arch=mips -mcpu=mips32 | \ +# RUN: FileCheck %s -check-prefix=CHECK-ASM +# +# RUN: llvm-mc %s -arch=mips -mcpu=mips32 -filetype=obj -o - | \ +# RUN: llvm-readobj -sections -section-data -section-relocations - | \ +# RUN: FileCheck %s -check-prefix=CHECK-OBJ + +# CHECK-ASM: .module fp=xx + +# Checking if the Mips.abiflags were correctly emitted. +# CHECK-OBJ: Section { +# CHECK-OBJ: Index: 5 +# CHECK-OBJ: Name: .MIPS.abiflags (12) +# CHECK-OBJ: Type: (0x7000002A) +# CHECK-OBJ: Flags [ (0x2) +# CHECK-OBJ: SHF_ALLOC (0x2) +# CHECK-OBJ: ] +# CHECK-OBJ: Address: 0x0 +# CHECK-OBJ: Offset: 0x50 +# CHECK-OBJ: Size: 24 +# CHECK-OBJ: Link: 0 +# CHECK-OBJ: Info: 0 +# CHECK-OBJ: AddressAlignment: 8 +# CHECK-OBJ: EntrySize: 0 +# CHECK-OBJ: Relocations [ +# CHECK-OBJ: ] +# CHECK-OBJ: SectionData ( +# CHECK-OBJ: 0000: 00002001 01010005 00000000 00000000 |.. .............| +# CHECK-OBJ: 0010: 00000000 00000000 |........| +# CHECK-OBJ: ) +# CHECK-OBJ: } + + .module fp=xx + +# FIXME: Test should include gnu_attributes directive when implemented. +# An explicit .gnu_attribute must be checked against the effective +# command line options and any inconsistencies reported via a warning. diff --git a/llvm/test/MC/Mips/mips_abi_flags_xx_set.s b/llvm/test/MC/Mips/mips_abi_flags_xx_set.s new file mode 100644 index 0000000..56f19d3 --- /dev/null +++ b/llvm/test/MC/Mips/mips_abi_flags_xx_set.s @@ -0,0 +1,38 @@ +# RUN: llvm-mc %s -arch=mips -mcpu=mips32 | \ +# RUN: FileCheck %s -check-prefix=CHECK-ASM +# +# RUN: llvm-mc %s -arch=mips -mcpu=mips32 -filetype=obj -o - | \ +# RUN: llvm-readobj -sections -section-data -section-relocations - | \ +# RUN: FileCheck %s -check-prefix=CHECK-OBJ + +# CHECK-ASM: .module fp=xx +# CHECK-ASM: .set fp=64 + +# Checking if the Mips.abiflags were correctly emitted. +# CHECK-OBJ: Section { +# CHECK-OBJ: Index: 5 +# CHECK-OBJ: Name: .MIPS.abiflags (12) +# CHECK-OBJ: Type: (0x7000002A) +# CHECK-OBJ: Flags [ (0x2) +# CHECK-OBJ: SHF_ALLOC (0x2) +# CHECK-OBJ: ] +# CHECK-OBJ: Address: 0x0 +# CHECK-OBJ: Offset: 0x50 +# CHECK-OBJ: Size: 24 +# CHECK-OBJ: Link: 0 +# CHECK-OBJ: Info: 0 +# CHECK-OBJ: AddressAlignment: 8 +# CHECK-OBJ: EntrySize: 0 +# CHECK-OBJ: Relocations [ +# CHECK-OBJ: ] +# CHECK-OBJ: SectionData ( +# CHECK-OBJ: 0000: 00002001 01010005 00000000 00000000 |.. .............| +# CHECK-OBJ: 0010: 00000000 00000000 |........| +# CHECK-OBJ: ) +# CHECK-OBJ: } + + .module fp=xx + .set fp=64 +# FIXME: Test should include gnu_attributes directive when implemented. +# An explicit .gnu_attribute must be checked against the effective +# command line options and any inconsistencies reported via a warning. -- 2.7.4