summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/Mips/MipsTargetStreamer.h
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/Mips/MipsTargetStreamer.h')
-rw-r--r--llvm/lib/Target/Mips/MipsTargetStreamer.h193
1 files changed, 193 insertions, 0 deletions
diff --git a/llvm/lib/Target/Mips/MipsTargetStreamer.h b/llvm/lib/Target/Mips/MipsTargetStreamer.h
index 2ae61382cd5..a0edc6f85d8 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 <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.
+ }
+
+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; }
OpenPOWER on IntegriCloud