mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-12 13:30:51 +00:00
[mips] Improve encapsulation of the .MIPS.abiflags implementation and limit scope of related enums
Summary: Follow on to r212519 to improve the encapsulation and limit the scope of the enums. Also merged two very similar parser functions, fixed a bug where ASE's were not being reported, and marked CPR1's as being 128-bit when MSA is enabled. Differential Revision: http://reviews.llvm.org/D4384 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@212522 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
aebcee661e
commit
fbdb8e1eac
@ -38,7 +38,7 @@ class MCInstrInfo;
|
||||
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);
|
||||
@ -46,18 +46,15 @@ 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;
|
||||
};
|
||||
}
|
||||
|
||||
@ -136,8 +133,8 @@ class MipsAsmParser : public MCTargetAsmParser {
|
||||
void expandMemInst(MCInst &Inst, SMLoc IDLoc,
|
||||
SmallVectorImpl<MCInst> &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);
|
||||
@ -167,6 +164,8 @@ class MipsAsmParser : public MCTargetAsmParser {
|
||||
bool parseDirectiveGpWord();
|
||||
bool parseDirectiveGpDWord();
|
||||
bool parseDirectiveModule();
|
||||
bool parseDirectiveModuleFP();
|
||||
bool parseFpABIValue(Val_GNU_MIPS_ABI &FpABI, StringRef Directive);
|
||||
|
||||
MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
|
||||
|
||||
@ -2304,13 +2303,13 @@ bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
|
||||
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);
|
||||
}
|
||||
|
||||
@ -2445,7 +2444,7 @@ bool MipsAsmParser::parseSetNoMips16Directive() {
|
||||
}
|
||||
|
||||
bool MipsAsmParser::parseSetFpDirective() {
|
||||
int FpAbiMode;
|
||||
Val_GNU_MIPS_ABI FpAbiVal;
|
||||
// Line can be: .set fp=32
|
||||
// .set fp=xx
|
||||
// .set fp=64
|
||||
@ -2457,43 +2456,15 @@ bool MipsAsmParser::parseSetFpDirective() {
|
||||
}
|
||||
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;
|
||||
}
|
||||
Options.setFpAbiMode(FpAbiMode);
|
||||
getTargetStreamer().emitDirectiveSetFp(FpAbiMode, isABI_O32());
|
||||
getTargetStreamer().emitDirectiveSetFp(FpAbiVal, isABI_O32());
|
||||
Parser.Lex(); // Consume the EndOfStatement.
|
||||
return false;
|
||||
}
|
||||
@ -2817,7 +2788,6 @@ 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");
|
||||
@ -2835,39 +2805,76 @@ bool MipsAsmParser::parseDirectiveModule() {
|
||||
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.
|
||||
|
||||
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().emitDirectiveModule(FpAbiVal, isABI_O32());
|
||||
getTargetStreamer().setFpABI(FpAbiVal);
|
||||
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 value, expected 'xx', '32' or '64'");
|
||||
return false;
|
||||
}
|
||||
|
||||
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 'xx', '32' or '64'");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Value == 32) {
|
||||
if (!isABI_O32()) {
|
||||
reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
|
||||
return false;
|
||||
}
|
||||
|
||||
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 (isABI_O32()) {
|
||||
FpABI = MipsABIFlagsSection::Val_GNU_MIPS_ABI_FP_64;
|
||||
return true;
|
||||
}
|
||||
|
||||
llvm_unreachable("Unknown ABI");
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
|
||||
StringRef IDVal = DirectiveID.getString();
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
add_llvm_library(LLVMMipsDesc
|
||||
MipsABIFlagsSection.cpp
|
||||
MipsAsmBackend.cpp
|
||||
MipsELFObjectWriter.cpp
|
||||
MipsELFStreamer.cpp
|
||||
|
46
lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp
Normal file
46
lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp
Normal file
@ -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;
|
||||
}
|
||||
}
|
206
lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h
Normal file
206
lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h
Normal file
@ -0,0 +1,206 @@
|
||||
//===-- 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
|
||||
};
|
||||
|
||||
// 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;
|
||||
|
||||
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) {}
|
||||
|
||||
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() { return 0; }
|
||||
uint32_t getFlags2() { return 0; }
|
||||
|
||||
StringRef getFpABIString(Val_GNU_MIPS_ABI Value, bool Is32BitAbi);
|
||||
|
||||
template <class PredicateLibrary>
|
||||
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 <class PredicateLibrary>
|
||||
void setGPRSizeFromPredicates(const PredicateLibrary &P) {
|
||||
GPRSize = P.isGP64bit() ? AFL_REG_64 : AFL_REG_32;
|
||||
}
|
||||
|
||||
template <class PredicateLibrary>
|
||||
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 <class PredicateLibrary>
|
||||
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 <class PredicateLibrary>
|
||||
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 <class PredicateLibrary>
|
||||
void setAllFromPredicates(const PredicateLibrary &P) {
|
||||
setISALevelAndRevisionFromPredicates(P);
|
||||
setGPRSizeFromPredicates(P);
|
||||
setCPR1SizeFromPredicates(P);
|
||||
setASESetFromPredicates(P);
|
||||
setFpAbiFromPredicates(P);
|
||||
}
|
||||
};
|
||||
|
||||
MCStreamer &operator<<(MCStreamer &OS, MipsABIFlagsSection &ABIFlagsSection);
|
||||
}
|
||||
|
||||
#endif
|
@ -211,50 +211,20 @@ void MipsTargetAsmStreamer::emitDirectiveCpsetup(unsigned RegNo,
|
||||
setCanHaveModuleDir(false);
|
||||
}
|
||||
|
||||
void MipsTargetAsmStreamer::emitDirectiveModule(unsigned Value,
|
||||
bool 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() {
|
||||
@ -661,15 +631,5 @@ void MipsTargetELFStreamer::emitMipsAbiFlags() {
|
||||
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
|
||||
OS << ABIFlagsSection;
|
||||
}
|
||||
|
@ -94,6 +94,7 @@ bool MipsAsmPrinter::lowerOperand(const MachineOperand &MO, MCOperand &MCOp) {
|
||||
void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
MipsTargetStreamer &TS = getTargetStreamer();
|
||||
TS.setCanHaveModuleDir(false);
|
||||
|
||||
if (MI->isDebugValue()) {
|
||||
SmallString<128> Str;
|
||||
raw_svector_ostream OS(Str);
|
||||
@ -660,18 +661,8 @@ void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) {
|
||||
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());
|
||||
getTargetStreamer().emitDirectiveModuleFP(
|
||||
getTargetStreamer().getABIFlagsSection().FpABI, Subtarget->isABI_O32());
|
||||
}
|
||||
|
||||
void MipsAsmPrinter::EmitJal(MCSymbol *Symbol) {
|
||||
|
@ -12,89 +12,13 @@
|
||||
|
||||
#include "llvm/MC/MCELFStreamer.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
#include "MCTargetDesc/MipsABIFlagsSection.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) {}
|
||||
};
|
||||
class MipsABIFlagsSection;
|
||||
|
||||
// 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:
|
||||
@ -133,105 +57,25 @@ public:
|
||||
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 emitDirectiveModuleFP(Val_GNU_MIPS_ABI Value, bool Is32BitAbi) {
|
||||
ABIFlagsSection.FpABI = Value;
|
||||
}
|
||||
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; }
|
||||
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 <class PredicateLibrary>
|
||||
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;
|
||||
@ -278,8 +122,8 @@ public:
|
||||
const MCSymbol &Sym, bool IsReg) override;
|
||||
|
||||
// ABI Flags
|
||||
void emitDirectiveModule(unsigned Value, bool is32BitAbi) override;
|
||||
void emitDirectiveSetFp(unsigned Value, bool is32BitAbi) override;
|
||||
void emitDirectiveModuleFP(Val_GNU_MIPS_ABI Value, bool Is32BitAbi) override;
|
||||
void emitDirectiveSetFp(Val_GNU_MIPS_ABI Value, bool Is32BitAbi) override;
|
||||
void emitMipsAbiFlags() override;
|
||||
};
|
||||
|
||||
|
38
test/MC/Mips/msa/abiflags.s
Normal file
38
test/MC/Mips/msa/abiflags.s
Normal file
@ -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.
|
Loading…
Reference in New Issue
Block a user