1//===- MipsABIFlagsSection.h - Mips ELF ABI Flags Section -------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSABIFLAGSSECTION_H
10#define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSABIFLAGSSECTION_H
11
12#include "llvm/ADT/StringRef.h"
13#include "llvm/Support/ErrorHandling.h"
14#include "llvm/Support/MipsABIFlags.h"
15#include <cstdint>
16
17namespace llvm {
18
19class MCStreamer;
20
21struct MipsABIFlagsSection {
22  // Internal representation of the fp_abi related values used in .module.
23  enum class FpABIKind { ANY, XX, S32, S64, SOFT };
24
25  // Version of flags structure.
26  uint16_t Version = 0;
27  // The level of the ISA: 1-5, 32, 64.
28  uint8_t ISALevel = 0;
29  // The revision of ISA: 0 for MIPS V and below, 1-n otherwise.
30  uint8_t ISARevision = 0;
31  // The size of general purpose registers.
32  Mips::AFL_REG GPRSize = Mips::AFL_REG_NONE;
33  // The size of co-processor 1 registers.
34  Mips::AFL_REG CPR1Size = Mips::AFL_REG_NONE;
35  // The size of co-processor 2 registers.
36  Mips::AFL_REG CPR2Size = Mips::AFL_REG_NONE;
37  // Processor-specific extension.
38  Mips::AFL_EXT ISAExtension = Mips::AFL_EXT_NONE;
39  // Mask of ASEs used.
40  uint32_t ASESet = 0;
41
42  bool OddSPReg = false;
43
44  bool Is32BitABI = false;
45
46protected:
47  // The floating-point ABI.
48  FpABIKind FpABI = FpABIKind::ANY;
49
50public:
51  MipsABIFlagsSection() = default;
52
53  uint16_t getVersionValue() { return (uint16_t)Version; }
54  uint8_t getISALevelValue() { return (uint8_t)ISALevel; }
55  uint8_t getISARevisionValue() { return (uint8_t)ISARevision; }
56  uint8_t getGPRSizeValue() { return (uint8_t)GPRSize; }
57  uint8_t getCPR1SizeValue();
58  uint8_t getCPR2SizeValue() { return (uint8_t)CPR2Size; }
59  uint8_t getFpABIValue();
60  uint32_t getISAExtensionValue() { return (uint32_t)ISAExtension; }
61  uint32_t getASESetValue() { return (uint32_t)ASESet; }
62
63  uint32_t getFlags1Value() {
64    uint32_t Value = 0;
65
66    if (OddSPReg)
67      Value |= (uint32_t)Mips::AFL_FLAGS1_ODDSPREG;
68
69    return Value;
70  }
71
72  uint32_t getFlags2Value() { return 0; }
73
74  FpABIKind getFpABI() { return FpABI; }
75  void setFpABI(FpABIKind Value, bool IsABI32Bit) {
76    FpABI = Value;
77    Is32BitABI = IsABI32Bit;
78  }
79
80  StringRef getFpABIString(FpABIKind Value);
81
82  template <class PredicateLibrary>
83  void setISALevelAndRevisionFromPredicates(const PredicateLibrary &P) {
84    if (P.hasMips64()) {
85      ISALevel = 64;
86      if (P.hasMips64r6())
87        ISARevision = 6;
88      else if (P.hasMips64r5())
89        ISARevision = 5;
90      else if (P.hasMips64r3())
91        ISARevision = 3;
92      else if (P.hasMips64r2())
93        ISARevision = 2;
94      else
95        ISARevision = 1;
96    } else if (P.hasMips32()) {
97      ISALevel = 32;
98      if (P.hasMips32r6())
99        ISARevision = 6;
100      else if (P.hasMips32r5())
101        ISARevision = 5;
102      else if (P.hasMips32r3())
103        ISARevision = 3;
104      else if (P.hasMips32r2())
105        ISARevision = 2;
106      else
107        ISARevision = 1;
108    } else {
109      ISARevision = 0;
110      if (P.hasMips5())
111        ISALevel = 5;
112      else if (P.hasMips4())
113        ISALevel = 4;
114      else if (P.hasMips3())
115        ISALevel = 3;
116      else if (P.hasMips2())
117        ISALevel = 2;
118      else if (P.hasMips1())
119        ISALevel = 1;
120      else
121        llvm_unreachable("Unknown ISA level!");
122    }
123  }
124
125  template <class PredicateLibrary>
126  void setGPRSizeFromPredicates(const PredicateLibrary &P) {
127    GPRSize = P.isGP64bit() ? Mips::AFL_REG_64 : Mips::AFL_REG_32;
128  }
129
130  template <class PredicateLibrary>
131  void setCPR1SizeFromPredicates(const PredicateLibrary &P) {
132    if (P.useSoftFloat())
133      CPR1Size = Mips::AFL_REG_NONE;
134    else if (P.hasMSA())
135      CPR1Size = Mips::AFL_REG_128;
136    else
137      CPR1Size = P.isFP64bit() ? Mips::AFL_REG_64 : Mips::AFL_REG_32;
138  }
139
140  template <class PredicateLibrary>
141  void setISAExtensionFromPredicates(const PredicateLibrary &P) {
142    if (P.hasCnMipsP())
143      ISAExtension = Mips::AFL_EXT_OCTEONP;
144    else if (P.hasCnMips())
145      ISAExtension = Mips::AFL_EXT_OCTEON;
146    else
147      ISAExtension = Mips::AFL_EXT_NONE;
148  }
149
150  template <class PredicateLibrary>
151  void setASESetFromPredicates(const PredicateLibrary &P) {
152    ASESet = 0;
153    if (P.hasDSP())
154      ASESet |= Mips::AFL_ASE_DSP;
155    if (P.hasDSPR2())
156      ASESet |= Mips::AFL_ASE_DSPR2;
157    if (P.hasMSA())
158      ASESet |= Mips::AFL_ASE_MSA;
159    if (P.inMicroMipsMode())
160      ASESet |= Mips::AFL_ASE_MICROMIPS;
161    if (P.inMips16Mode())
162      ASESet |= Mips::AFL_ASE_MIPS16;
163    if (P.hasMT())
164      ASESet |= Mips::AFL_ASE_MT;
165    if (P.hasCRC())
166      ASESet |= Mips::AFL_ASE_CRC;
167    if (P.hasVirt())
168      ASESet |= Mips::AFL_ASE_VIRT;
169    if (P.hasGINV())
170      ASESet |= Mips::AFL_ASE_GINV;
171  }
172
173  template <class PredicateLibrary>
174  void setFpAbiFromPredicates(const PredicateLibrary &P) {
175    Is32BitABI = P.isABI_O32();
176
177    FpABI = FpABIKind::ANY;
178    if (P.useSoftFloat())
179      FpABI = FpABIKind::SOFT;
180    else if (P.isABI_N32() || P.isABI_N64())
181      FpABI = FpABIKind::S64;
182    else if (P.isABI_O32()) {
183      if (P.isABI_FPXX())
184        FpABI = FpABIKind::XX;
185      else if (P.isFP64bit())
186        FpABI = FpABIKind::S64;
187      else
188        FpABI = FpABIKind::S32;
189    }
190  }
191
192  template <class PredicateLibrary>
193  void setAllFromPredicates(const PredicateLibrary &P) {
194    setISALevelAndRevisionFromPredicates(P);
195    setGPRSizeFromPredicates(P);
196    setCPR1SizeFromPredicates(P);
197    setISAExtensionFromPredicates(P);
198    setASESetFromPredicates(P);
199    setFpAbiFromPredicates(P);
200    OddSPReg = P.useOddSPReg();
201  }
202};
203
204MCStreamer &operator<<(MCStreamer &OS, MipsABIFlagsSection &ABIFlagsSection);
205
206} // end namespace llvm
207
208#endif // LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSABIFLAGSSECTION_H
209