return uncompressInst(OutInst, MI, STI);
}
-// We expect an 5-bit binary encoding of a floating-point constant here.
-static constexpr std::pair<uint8_t, uint8_t> LoadFPImmArr[] = {
+// Lookup table for fli.h for entries 1-31. Entry 0(-1.0) is handled separately.
+// NOTE: The exponent for entry 1 is larger than entry 2 and 3 because they
+// are denormals.
+static constexpr std::pair<uint8_t, uint8_t> LoadFP16ImmArr[] = {
+ {0b00001, 0b00}, {0b00000, 0b10}, {0b00000, 0b01}, {0b00111, 0b00},
+ {0b01000, 0b00}, {0b01011, 0b00}, {0b01100, 0b00}, {0b01101, 0b00},
+ {0b01101, 0b01}, {0b01101, 0b10}, {0b01101, 0b11}, {0b01110, 0b00},
+ {0b01110, 0b01}, {0b01110, 0b10}, {0b01110, 0b11}, {0b01111, 0b00},
+ {0b01111, 0b01}, {0b01111, 0b10}, {0b01111, 0b11}, {0b10000, 0b00},
+ {0b10000, 0b01}, {0b10000, 0b10}, {0b10001, 0b00}, {0b10010, 0b00},
+ {0b10011, 0b00}, {0b10110, 0b00}, {0b10111, 0b00}, {0b11110, 0b00},
+ {0b11111, 0b00}, {0b11111, 0b00}, {0b11111, 0b10},
+};
+
+// Lookup table for fli.s for entries 1-31.
+static constexpr std::pair<uint8_t, uint8_t> LoadFP32ImmArr[] = {
{0b00000001, 0b00}, {0b01101111, 0b00}, {0b01110000, 0b00},
{0b01110111, 0b00}, {0b01111000, 0b00}, {0b01111011, 0b00},
{0b01111100, 0b00}, {0b01111101, 0b00}, {0b01111101, 0b01},
{0b11111111, 0b10},
};
-int RISCVLoadFPImm::getLoadFPImm(bool Sign, uint8_t Exp, uint8_t Mantissa) {
- // Lookup in the table, ignoring the sign.
- auto EMI = llvm::lower_bound(LoadFPImmArr, std::make_pair(Exp, Mantissa));
- if (EMI == std::end(LoadFPImmArr) || EMI->first != Exp ||
+// Lookup table for fli.d for entries 1-31.
+static constexpr std::pair<uint16_t, uint8_t> LoadFP64ImmArr[] = {
+ {0b00000000001, 0b00}, {0b01111101111, 0b00}, {0b01111110000, 0b00},
+ {0b01111110111, 0b00}, {0b01111111000, 0b00}, {0b01111111011, 0b00},
+ {0b01111111100, 0b00}, {0b01111111101, 0b00}, {0b01111111101, 0b01},
+ {0b01111111101, 0b10}, {0b01111111101, 0b11}, {0b01111111110, 0b00},
+ {0b01111111110, 0b01}, {0b01111111110, 0b10}, {0b01111111110, 0b11},
+ {0b01111111111, 0b00}, {0b01111111111, 0b01}, {0b01111111111, 0b10},
+ {0b01111111111, 0b11}, {0b10000000000, 0b00}, {0b10000000000, 0b01},
+ {0b10000000000, 0b10}, {0b10000000001, 0b00}, {0b10000000010, 0b00},
+ {0b10000000011, 0b00}, {0b10000000110, 0b00}, {0b10000000111, 0b00},
+ {0b10000001110, 0b00}, {0b10000001111, 0b00}, {0b11111111111, 0b00},
+ {0b11111111111, 0b10},
+};
+
+int RISCVLoadFPImm::getLoadFP16Imm(const APFloat &FPImm) {
+ assert(&FPImm.getSemantics() == &APFloat::IEEEhalf());
+
+ APInt Imm = FPImm.bitcastToAPInt();
+
+ if (Imm.extractBitsAsZExtValue(8, 0) != 0)
+ return -1;
+
+ bool Sign = Imm.extractBitsAsZExtValue(1, 15);
+ uint8_t Mantissa = Imm.extractBitsAsZExtValue(2, 8);
+ uint8_t Exp = Imm.extractBitsAsZExtValue(5, 10);
+
+ // The array isn't sorted so we must use std::find unlike fp32 and fp64.
+ auto EMI = llvm::find(LoadFP16ImmArr, std::make_pair(Exp, Mantissa));
+ if (EMI == std::end(LoadFP16ImmArr))
+ return -1;
+
+ // Table doesn't have entry 0.
+ int Entry = std::distance(std::begin(LoadFP16ImmArr), EMI) + 1;
+
+ // The only legal negative value is -1.0(entry 0). 1.0 is entry 16.
+ if (Sign) {
+ if (Entry == 16)
+ return 0;
+ return false;
+ }
+
+ // Entry 29 and 30 are both infinity, but 30 is the real infinity.
+ if (Entry == 29)
+ ++Entry;
+
+ return Entry;
+}
+
+int RISCVLoadFPImm::getLoadFP32Imm(const APFloat &FPImm) {
+ assert(&FPImm.getSemantics() == &APFloat::IEEEsingle());
+
+ APInt Imm = FPImm.bitcastToAPInt();
+
+ if (Imm.extractBitsAsZExtValue(21, 0) != 0)
+ return -1;
+
+ bool Sign = Imm.extractBitsAsZExtValue(1, 31);
+ uint8_t Mantissa = Imm.extractBitsAsZExtValue(2, 21);
+ uint8_t Exp = Imm.extractBitsAsZExtValue(8, 23);
+
+ auto EMI = llvm::lower_bound(LoadFP32ImmArr, std::make_pair(Exp, Mantissa));
+ if (EMI == std::end(LoadFP32ImmArr) || EMI->first != Exp ||
+ EMI->second != Mantissa)
+ return -1;
+
+ // Table doesn't have entry 0.
+ int Entry = std::distance(std::begin(LoadFP32ImmArr), EMI) + 1;
+
+ // The only legal negative value is -1.0(entry 0). 1.0 is entry 16.
+ if (Sign) {
+ if (Entry == 16)
+ return 0;
+ return false;
+ }
+
+ return Entry;
+}
+
+int RISCVLoadFPImm::getLoadFP64Imm(const APFloat &FPImm) {
+ assert(&FPImm.getSemantics() == &APFloat::IEEEdouble());
+
+ APInt Imm = FPImm.bitcastToAPInt();
+
+ if (Imm.extractBitsAsZExtValue(50, 0) != 0)
+ return -1;
+
+ bool Sign = Imm.extractBitsAsZExtValue(1, 63);
+ uint8_t Mantissa = Imm.extractBitsAsZExtValue(2, 50);
+ uint16_t Exp = Imm.extractBitsAsZExtValue(11, 52);
+
+ auto EMI = llvm::lower_bound(LoadFP64ImmArr, std::make_pair(Exp, Mantissa));
+ if (EMI == std::end(LoadFP64ImmArr) || EMI->first != Exp ||
EMI->second != Mantissa)
return -1;
// Table doesn't have entry 0.
- int Entry = std::distance(std::begin(LoadFPImmArr), EMI) + 1;
+ int Entry = std::distance(std::begin(LoadFP64ImmArr), EMI) + 1;
// The only legal negative value is -1.0(entry 0). 1.0 is entry 16.
if (Sign) {
Imm = 16;
}
- uint32_t Exp = LoadFPImmArr[Imm - 1].first;
- uint32_t Mantissa = LoadFPImmArr[Imm - 1].second;
+ uint32_t Exp = LoadFP32ImmArr[Imm - 1].first;
+ uint32_t Mantissa = LoadFP32ImmArr[Imm - 1].second;
uint32_t I = Sign << 31 | Exp << 23 | Mantissa << 21;
return bit_cast<float>(I);
/// getLoadFP32Imm - Return a 5-bit binary encoding of the 32-bit
/// floating-point immediate value. If the value cannot be represented as a
/// 5-bit binary encoding, then return -1.
-static inline int getLoadFP32Imm(const APInt &Imm) {
- if (Imm.extractBitsAsZExtValue(21, 0) != 0)
- return -1;
-
- bool Sign = Imm.extractBitsAsZExtValue(1, 31);
- uint8_t Exp = Imm.extractBitsAsZExtValue(8, 23);
- uint8_t Mantissa = Imm.extractBitsAsZExtValue(2, 21);
- return getLoadFPImm(Sign, Exp, Mantissa);
-}
-
-static inline int getLoadFP32Imm(const APFloat &FPImm) {
- return getLoadFP32Imm(FPImm.bitcastToAPInt());
-}
+int getLoadFP32Imm(const APFloat &FPImm);
/// getLoadFP64Imm - Return a 5-bit binary encoding of the 64-bit
/// floating-point immediate value. If the value cannot be represented as a
/// 5-bit binary encoding, then return -1.
-static inline int getLoadFP64Imm(const APInt &Imm) {
- if (Imm.extractBitsAsZExtValue(50, 0) != 0)
- return -1;
-
- bool Sign = Imm.extractBitsAsZExtValue(1, 63);
- uint8_t Mantissa = Imm.extractBitsAsZExtValue(2, 50);
- uint8_t Exp;
- if (Imm.extractBitsAsZExtValue(11, 52) == 1)
- Exp = 0b00000001;
- else if (Imm.extractBitsAsZExtValue(11, 52) == 2047)
- Exp = 0b11111111;
- else
- Exp = Imm.extractBitsAsZExtValue(11, 52) - 1023 + 127;
-
- return getLoadFPImm(Sign, Exp, Mantissa);
-}
-
-static inline int getLoadFP64Imm(const APFloat &FPImm) {
- return getLoadFP64Imm(FPImm.bitcastToAPInt());
-}
+int getLoadFP64Imm(const APFloat &FPImm);
/// getLoadFP16Imm - Return a 5-bit binary encoding of the 16-bit
/// floating-point immediate value. If the value cannot be represented as a
/// 5-bit binary encoding, then return -1.
-static inline int getLoadFP16Imm(const APInt &Imm) {
- if (Imm.extractBitsAsZExtValue(8, 0) != 0)
- return -1;
-
- bool Sign = Imm.extractBitsAsZExtValue(1, 15);
- uint8_t Mantissa = Imm.extractBitsAsZExtValue(2, 8);
- uint8_t Exp;
- if (Imm.extractBitsAsZExtValue(5, 10) == 1)
- Exp = 0b00000001;
- else if (Imm.extractBitsAsZExtValue(5, 10) == 31)
- Exp = 0b11111111;
- else
- Exp = Imm.extractBitsAsZExtValue(5, 10) - 15 + 127;
-
- return getLoadFPImm(Sign, Exp, Mantissa);
-}
-
-static inline int getLoadFP16Imm(const APFloat &FPImm) {
- return getLoadFP16Imm(FPImm.bitcastToAPInt());
-}
+int getLoadFP16Imm(const APFloat &FPImm);
} // namespace RISCVLoadFPImm
namespace RISCVSysReg {