Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -38,7 +38,7 @@ namespace { class MipsAssemblerOptions { public: - MipsAssemblerOptions() : aTReg(1), reorder(true), macro(true), fpAbiMode(0) {} + MipsAssemblerOptions() : aTReg(1), reorder(true), macro(true) {} unsigned getATRegNum() { return aTReg; } bool setATReg(unsigned Reg); @@ -55,7 +55,6 @@ unsigned aTReg; bool reorder; bool macro; - int fpAbiMode; }; } @@ -134,8 +133,8 @@ void expandMemInst(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl &Instructions, bool isLoad, bool isImmOpnd); - bool reportParseError(StringRef ErrorMsg); - bool reportParseError(SMLoc Loc, StringRef ErrorMsg); + bool reportParseError(Twine ErrorMsg); + bool reportParseError(SMLoc Loc, Twine ErrorMsg); bool parseMemOffset(const MCExpr *&Res, bool isParenExpr); bool parseRelocOperand(const MCExpr *&Res); @@ -166,6 +165,7 @@ bool parseDirectiveGpDWord(); bool parseDirectiveModule(); bool parseDirectiveModuleFP(); + bool parseFpABIValue(Val_GNU_MIPS_ABI &FpABI, StringRef Directive); MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol); @@ -2303,13 +2303,13 @@ return false; } -bool MipsAsmParser::reportParseError(StringRef ErrorMsg) { +bool MipsAsmParser::reportParseError(Twine ErrorMsg) { SMLoc Loc = getLexer().getLoc(); Parser.eatToEndOfStatement(); return Error(Loc, ErrorMsg); } -bool MipsAsmParser::reportParseError(SMLoc Loc, StringRef ErrorMsg) { +bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) { return Error(Loc, ErrorMsg); } @@ -2444,7 +2444,7 @@ } bool MipsAsmParser::parseSetFpDirective() { - int FpAbiMode; + Val_GNU_MIPS_ABI FpAbiVal; // Line can be: .set fp=32 // .set fp=xx // .set fp=64 @@ -2456,42 +2456,15 @@ } 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 (!parseFpABIValue(FpAbiVal, ".set")) + return false; + if (getLexer().isNot(AsmToken::EndOfStatement)) { reportParseError("unexpected token in statement"); return false; } - getTargetStreamer().emitDirectiveSetFp(FpAbiMode, isABI_O32()); + getTargetStreamer().emitDirectiveSetFp(FpAbiVal, isABI_O32()); Parser.Lex(); // Consume the EndOfStatement. return false; } @@ -2858,44 +2831,75 @@ } Parser.Lex(); // Eat '=' token. - unsigned FpAbiVal = 0; + Val_GNU_MIPS_ABI FpABI; + if (!parseFpABIValue(FpABI, ".module")) + return false; + + if (getLexer().isNot(AsmToken::EndOfStatement)) { + reportParseError("unexpected token in statement"); + return false; + } + + // Emit appropriate flags. + getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32()); + Parser.Lex(); // Consume the EndOfStatement. + return false; +} + +bool MipsAsmParser::parseFpABIValue(Val_GNU_MIPS_ABI &FpABI, + StringRef Directive) { + MCAsmLexer &Lexer = getLexer(); + if (Lexer.is(AsmToken::Identifier)) { StringRef Value = Parser.getTok().getString(); Parser.Lex(); if (Value != "xx") { - reportParseError("unsupported option"); + reportParseError("unsupported value, expected 'xx', '32' or '64'"); return false; } - FpAbiVal = Val_GNU_MIPS_ABI_FP_XX; - } else if (Lexer.is(AsmToken::Integer)) { - unsigned Value = Lexer.getTok().getIntVal(); + if (!isABI_O32()) { + reportParseError("'" + Directive + " fp=xx' requires the O32 ABI"); + return false; + } + + FpABI = MipsABIFlagsSection::Val_GNU_MIPS_ABI_FP_XX; + return true; + } + + if (Lexer.is(AsmToken::Integer)) { + unsigned Value = Parser.getTok().getIntVal(); + Parser.Lex(); if (Value != 32 && Value != 64) { - reportParseError("unsupported value, expected 32 or 64"); + reportParseError("unsupported value, expected 'xx', '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; + if (Value == 32) { + if (!isABI_O32()) { + reportParseError("'" + Directive + " fp=32' requires the O32 ABI"); + return false; + } - Parser.Lex(); // Eat option token. - } + FpABI = MipsABIFlagsSection::Val_GNU_MIPS_ABI_FP_DOUBLE; + return true; + } else { + if (isABI_N32() || isABI_N64()) { + FpABI = MipsABIFlagsSection::Val_GNU_MIPS_ABI_FP_DOUBLE; + return true; + } - if (getLexer().isNot(AsmToken::EndOfStatement)) { - reportParseError("unexpected token in statement"); - return false; + if (isABI_O32()) { + FpABI = MipsABIFlagsSection::Val_GNU_MIPS_ABI_FP_64; + return true; + } + + llvm_unreachable("Unknown ABI"); + } } - // Emit appropriate flags. - getTargetStreamer().emitDirectiveModuleFP(FpAbiVal, isABI_O32()); - Parser.Lex(); // Consume the EndOfStatement. return false; } Index: lib/Target/Mips/MCTargetDesc/CMakeLists.txt =================================================================== --- lib/Target/Mips/MCTargetDesc/CMakeLists.txt +++ lib/Target/Mips/MCTargetDesc/CMakeLists.txt @@ -1,4 +1,5 @@ add_llvm_library(LLVMMipsDesc + MipsABIFlagsSection.cpp MipsAsmBackend.cpp MipsELFObjectWriter.cpp MipsELFStreamer.cpp Index: lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h =================================================================== --- /dev/null +++ lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h @@ -0,0 +1,220 @@ +//===-- MipsABIFlagsSection.h - Mips ELF ABI Flags Section -----*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef MIPSABIFLAGSSECTION_H +#define MIPSABIFLAGSSECTION_H + +#include "llvm/MC/MCStreamer.h" + +namespace llvm { + +class MCStreamer; + +struct MipsABIFlagsSection { + // Values for the xxx_size bytes of an ABI flags structure. + enum AFL_REG { + 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 { + 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 { + 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 { + Val_GNU_MIPS_ABI_FP_ANY = 0, + Val_GNU_MIPS_ABI_FP_DOUBLE = 1, + Val_GNU_MIPS_ABI_FP_XX = 5, + Val_GNU_MIPS_ABI_FP_64 = 6 + }; + + enum class AFL_FLAGS1 : uint32_t { ODDSPREG = 1 }; + + // Version of flags structure. + uint16_t Version; + // The level of the ISA: 1-5, 32, 64. + uint8_t ISALevel; + // The revision of ISA: 0 for MIPS V and below, 1-n otherwise. + uint8_t ISARevision; + // The size of general purpose registers. + AFL_REG GPRSize; + // The size of co-processor 1 registers. + AFL_REG CPR1Size; + // The size of co-processor 2 registers. + AFL_REG CPR2Size; + // The floating-point ABI. + Val_GNU_MIPS_ABI FpABI; + // Processor-specific extension. + uint32_t ISAExtensionSet; + // Mask of ASEs used. + uint32_t ASESet; + + bool OddSPReg; + + MipsABIFlagsSection() + : Version(0), ISALevel(0), ISARevision(0), GPRSize(AFL_REG_NONE), + CPR1Size(AFL_REG_NONE), CPR2Size(AFL_REG_NONE), + FpABI(Val_GNU_MIPS_ABI_FP_ANY), ISAExtensionSet(0), ASESet(0), + OddSPReg(false) {} + + uint16_t getVersion() { return (uint16_t)Version; } + uint8_t getISALevel() { return (uint8_t)ISALevel; } + uint8_t getISARevision() { return (uint8_t)ISARevision; } + uint8_t getGPRSize() { return (uint8_t)GPRSize; } + uint8_t getCPR1Size() { return (uint8_t)CPR1Size; } + uint8_t getCPR2Size() { return (uint8_t)CPR2Size; } + uint8_t getFpABI() { return (uint8_t)FpABI; } + uint32_t getISAExtensionSet() { return (uint32_t)ISAExtensionSet; } + uint32_t getASESet() { return (uint32_t)ASESet; } + + uint32_t getFlags1() { + uint32_t Value = 0; + + if (OddSPReg) + Value |= (uint32_t)AFL_FLAGS1::ODDSPREG; + + return Value; + } + + uint32_t getFlags2() { return 0; } + + StringRef getFpABIString(Val_GNU_MIPS_ABI Value, bool Is32BitAbi); + + template + void setISALevelAndRevisionFromPredicates(const PredicateLibrary &P) { + if (P.hasMips64()) { + ISALevel = 64; + if (P.hasMips64r6()) + ISARevision = 6; + else if (P.hasMips64r2()) + ISARevision = 2; + else + ISARevision = 1; + } else if (P.hasMips32()) { + ISALevel = 32; + if (P.hasMips32r6()) + ISARevision = 6; + else if (P.hasMips32r2()) + ISARevision = 2; + else + ISARevision = 1; + } else { + ISARevision = 0; + if (P.hasMips5()) + ISALevel = 5; + else if (P.hasMips4()) + ISALevel = 4; + else if (P.hasMips3()) + ISALevel = 3; + else if (P.hasMips2()) + ISALevel = 2; + else if (P.hasMips1()) + ISALevel = 1; + else + llvm_unreachable("Unknown ISA level!"); + } + } + + template + void setGPRSizeFromPredicates(const PredicateLibrary &P) { + GPRSize = P.isGP64bit() ? AFL_REG_64 : AFL_REG_32; + } + + template + void setCPR1SizeFromPredicates(const PredicateLibrary &P) { + if (P.mipsSEUsesSoftFloat()) + CPR1Size = AFL_REG_NONE; + else if (P.hasMSA()) + CPR1Size = AFL_REG_128; + else + CPR1Size = P.isFP64bit() ? AFL_REG_64 : AFL_REG_32; + } + + template + void setASESetFromPredicates(const PredicateLibrary &P) { + ASESet = 0; + if (P.hasDSP()) + ASESet |= AFL_ASE_DSP; + if (P.hasDSPR2()) + ASESet |= AFL_ASE_DSPR2; + if (P.hasMSA()) + ASESet |= AFL_ASE_MSA; + if (P.inMicroMipsMode()) + ASESet |= AFL_ASE_MICROMIPS; + if (P.inMips16Mode()) + ASESet |= AFL_ASE_MIPS16; + } + + template + void setFpAbiFromPredicates(const PredicateLibrary &P) { + FpABI = Val_GNU_MIPS_ABI_FP_ANY; + if (P.isABI_N32() || P.isABI_N64()) + FpABI = Val_GNU_MIPS_ABI_FP_DOUBLE; + else if (P.isABI_O32()) { + if (P.isFP64bit()) + FpABI = Val_GNU_MIPS_ABI_FP_64; + else if (P.isABI_FPXX()) + FpABI = Val_GNU_MIPS_ABI_FP_XX; + else + FpABI = Val_GNU_MIPS_ABI_FP_DOUBLE; + } + } + + template + void setAllFromPredicates(const PredicateLibrary &P) { + setISALevelAndRevisionFromPredicates(P); + setGPRSizeFromPredicates(P); + setCPR1SizeFromPredicates(P); + setASESetFromPredicates(P); + setFpAbiFromPredicates(P); + } +}; + +MCStreamer &operator<<(MCStreamer &OS, MipsABIFlagsSection &ABIFlagsSection); +} + +#endif Index: lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp =================================================================== --- /dev/null +++ lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp @@ -0,0 +1,46 @@ +//===-- MipsABIFlagsSection.cpp - Mips ELF ABI Flags Section ---*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MipsABIFlagsSection.h" + +using namespace llvm; + +StringRef MipsABIFlagsSection::getFpABIString(Val_GNU_MIPS_ABI Value, + bool Is32BitAbi) { + switch (Value) { + case MipsABIFlagsSection::Val_GNU_MIPS_ABI_FP_XX: + return "xx"; + case MipsABIFlagsSection::Val_GNU_MIPS_ABI_FP_64: + return "64"; + case MipsABIFlagsSection::Val_GNU_MIPS_ABI_FP_DOUBLE: + if (Is32BitAbi) + return "32"; + return "64"; + default: + llvm_unreachable("unsupported fp abi value"); + } +} + +namespace llvm { +MCStreamer &operator<<(MCStreamer &OS, MipsABIFlagsSection &ABIFlagsSection) { + // Write out a Elf_Internal_ABIFlags_v0 struct + OS.EmitIntValue(ABIFlagsSection.getVersion(), 2); // version + OS.EmitIntValue(ABIFlagsSection.getISALevel(), 1); // isa_level + OS.EmitIntValue(ABIFlagsSection.getISARevision(), 1); // isa_rev + OS.EmitIntValue(ABIFlagsSection.getGPRSize(), 1); // gpr_size + OS.EmitIntValue(ABIFlagsSection.getCPR1Size(), 1); // cpr1_size + OS.EmitIntValue(ABIFlagsSection.getCPR2Size(), 1); // cpr2_size + OS.EmitIntValue(ABIFlagsSection.getFpABI(), 1); // fp_abi + OS.EmitIntValue(ABIFlagsSection.getISAExtensionSet(), 4); // isa_ext + OS.EmitIntValue(ABIFlagsSection.getASESet(), 4); // ases + OS.EmitIntValue(ABIFlagsSection.getFlags1(), 4); // flags1 + OS.EmitIntValue(ABIFlagsSection.getFlags2(), 4); // flags2 + return OS; +} +} Index: lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -212,52 +212,20 @@ setCanHaveModuleDir(false); } -void MipsTargetAsmStreamer::emitDirectiveModuleFP(unsigned Value, - bool is32BitAbi) { - MipsTargetStreamer::emitDirectiveModuleFP(Value, is32BitAbi); +void MipsTargetAsmStreamer::emitDirectiveModuleFP(Val_GNU_MIPS_ABI Value, + bool Is32BitAbi) { + MipsTargetStreamer::emitDirectiveModuleFP(Value, 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"; + OS << ABIFlagsSection.getFpABIString(Value, Is32BitAbi) << "\n"; } -void MipsTargetAsmStreamer::emitDirectiveSetFp(unsigned Value, - bool is32BitAbi) { +void MipsTargetAsmStreamer::emitDirectiveSetFp(Val_GNU_MIPS_ABI 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"; + OS << ABIFlagsSection.getFpABIString(Value, Is32BitAbi) << "\n"; } void MipsTargetAsmStreamer::emitMipsAbiFlags() { @@ -668,19 +636,9 @@ 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.getFlags1(), 4); - OS.EmitIntValue(MipsABIFlags.getFlags2(), 4); + OS << ABIFlagsSection; } void MipsTargetELFStreamer::emitDirectiveModuleOddSPReg(bool Enabled) { - MipsABIFlags.OddSPReg = Enabled; + ABIFlagsSection.OddSPReg = Enabled; } Index: lib/Target/Mips/MipsAsmPrinter.cpp =================================================================== --- lib/Target/Mips/MipsAsmPrinter.cpp +++ lib/Target/Mips/MipsAsmPrinter.cpp @@ -706,18 +706,8 @@ } 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().emitDirectiveModuleFP(FpAbiVal, Subtarget->isABI_O32()); + getTargetStreamer().emitDirectiveModuleFP( + getTargetStreamer().getABIFlagsSection().FpABI, Subtarget->isABI_O32()); if (Subtarget->isFP64bit()) getTargetStreamer().emitDirectiveModuleOddSPReg(Subtarget->useOddSPReg()); Index: lib/Target/Mips/MipsTargetStreamer.h =================================================================== --- lib/Target/Mips/MipsTargetStreamer.h +++ lib/Target/Mips/MipsTargetStreamer.h @@ -12,101 +12,13 @@ #include "llvm/MC/MCELFStreamer.h" #include "llvm/MC/MCStreamer.h" +#include "MCTargetDesc/MipsABIFlagsSection.h" namespace llvm { -struct Elf_Internal_ABIFlags_v0 { - enum class AFL_FLAGS1 : uint32_t { ODDSPREG = 1 }; - // 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; +class MipsABIFlagsSection; - bool OddSPReg; - - 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), OddSPReg(false) {} - - uint32_t getFlags1() { - uint32_t Value = 0; - - if (OddSPReg) - Value |= (uint32_t)AFL_FLAGS1::ODDSPREG; - - return Value; - } - - uint32_t getFlags2() { return 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 -}; +using Val_GNU_MIPS_ABI = MipsABIFlagsSection::Val_GNU_MIPS_ABI; class MipsTargetStreamer : public MCTargetStreamer { public: @@ -145,106 +57,26 @@ virtual void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, const MCSymbol &Sym, bool IsReg); // ABI Flags - virtual void emitDirectiveModuleFP(unsigned Value, bool is32BitAbi) { - setFpABI(Value); + virtual void emitDirectiveModuleFP(Val_GNU_MIPS_ABI Value, bool Is32BitAbi) { + ABIFlagsSection.FpABI = Value; } virtual void emitDirectiveModuleOddSPReg(bool Enabled); - virtual void emitDirectiveSetFp(unsigned Value, bool is32BitAbi){}; + virtual void emitDirectiveSetFp(Val_GNU_MIPS_ABI 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; } - - 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. + ABIFlagsSection.setAllFromPredicates(P); } + MipsABIFlagsSection &getABIFlagsSection() { return ABIFlagsSection; } + protected: - Elf_Internal_ABIFlags_v0 MipsABIFlags; + MipsABIFlagsSection ABIFlagsSection; private: bool canHaveModuleDirective; @@ -291,9 +123,9 @@ const MCSymbol &Sym, bool IsReg) override; // ABI Flags - void emitDirectiveModuleFP(unsigned Value, bool is32BitAbi) override; + void emitDirectiveModuleFP(Val_GNU_MIPS_ABI Value, bool Is32BitAbi) override; void emitDirectiveModuleOddSPReg(bool Enabled) override; - void emitDirectiveSetFp(unsigned Value, bool is32BitAbi) override; + void emitDirectiveSetFp(Val_GNU_MIPS_ABI Value, bool Is32BitAbi) override; void emitMipsAbiFlags() override; }; Index: test/MC/Mips/msa/abiflags.s =================================================================== --- /dev/null +++ test/MC/Mips/msa/abiflags.s @@ -0,0 +1,38 @@ +# RUN: llvm-mc %s -arch=mips -mcpu=mips32r2 -mattr=+msa | \ +# RUN: FileCheck %s -check-prefix=CHECK-ASM +# +# RUN: llvm-mc %s -arch=mips -mcpu=mips32r2 -mattr=+msa -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 01030001 00000000 00000200 |.. .............| +# 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.