10b57cec5SDimitry Andric //===-- ARMBaseInfo.h - Top level definitions for ARM ---*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains small standalone helper functions and enum definitions for
100b57cec5SDimitry Andric // the ARM target useful for the compiler back-end and the MC libraries.
110b57cec5SDimitry Andric // As such, it deliberately does not include references to LLVM core
120b57cec5SDimitry Andric // code gen types, passes, etc..
130b57cec5SDimitry Andric //
140b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
150b57cec5SDimitry Andric
160b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_ARM_UTILS_ARMBASEINFO_H
170b57cec5SDimitry Andric #define LLVM_LIB_TARGET_ARM_UTILS_ARMBASEINFO_H
180b57cec5SDimitry Andric
190b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
200b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
21*06c3fb27SDimitry Andric #include "llvm/TargetParser/SubtargetFeature.h"
220b57cec5SDimitry Andric #include "MCTargetDesc/ARMMCTargetDesc.h"
230b57cec5SDimitry Andric
240b57cec5SDimitry Andric namespace llvm {
250b57cec5SDimitry Andric
260b57cec5SDimitry Andric // Enums corresponding to ARM condition codes
270b57cec5SDimitry Andric namespace ARMCC {
280b57cec5SDimitry Andric // The CondCodes constants map directly to the 4-bit encoding of the
290b57cec5SDimitry Andric // condition field for predicated instructions.
300b57cec5SDimitry Andric enum CondCodes { // Meaning (integer) Meaning (floating-point)
310b57cec5SDimitry Andric EQ, // Equal Equal
320b57cec5SDimitry Andric NE, // Not equal Not equal, or unordered
330b57cec5SDimitry Andric HS, // Carry set >, ==, or unordered
340b57cec5SDimitry Andric LO, // Carry clear Less than
350b57cec5SDimitry Andric MI, // Minus, negative Less than
360b57cec5SDimitry Andric PL, // Plus, positive or zero >, ==, or unordered
370b57cec5SDimitry Andric VS, // Overflow Unordered
380b57cec5SDimitry Andric VC, // No overflow Not unordered
390b57cec5SDimitry Andric HI, // Unsigned higher Greater than, or unordered
400b57cec5SDimitry Andric LS, // Unsigned lower or same Less than or equal
410b57cec5SDimitry Andric GE, // Greater than or equal Greater than or equal
420b57cec5SDimitry Andric LT, // Less than Less than, or unordered
430b57cec5SDimitry Andric GT, // Greater than Greater than
440b57cec5SDimitry Andric LE, // Less than or equal <, ==, or unordered
450b57cec5SDimitry Andric AL // Always (unconditional) Always (unconditional)
460b57cec5SDimitry Andric };
470b57cec5SDimitry Andric
getOppositeCondition(CondCodes CC)480b57cec5SDimitry Andric inline static CondCodes getOppositeCondition(CondCodes CC) {
490b57cec5SDimitry Andric switch (CC) {
500b57cec5SDimitry Andric default: llvm_unreachable("Unknown condition code");
510b57cec5SDimitry Andric case EQ: return NE;
520b57cec5SDimitry Andric case NE: return EQ;
530b57cec5SDimitry Andric case HS: return LO;
540b57cec5SDimitry Andric case LO: return HS;
550b57cec5SDimitry Andric case MI: return PL;
560b57cec5SDimitry Andric case PL: return MI;
570b57cec5SDimitry Andric case VS: return VC;
580b57cec5SDimitry Andric case VC: return VS;
590b57cec5SDimitry Andric case HI: return LS;
600b57cec5SDimitry Andric case LS: return HI;
610b57cec5SDimitry Andric case GE: return LT;
620b57cec5SDimitry Andric case LT: return GE;
630b57cec5SDimitry Andric case GT: return LE;
640b57cec5SDimitry Andric case LE: return GT;
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric }
67480093f4SDimitry Andric
68480093f4SDimitry Andric /// getSwappedCondition - assume the flags are set by MI(a,b), return
69480093f4SDimitry Andric /// the condition code if we modify the instructions such that flags are
70480093f4SDimitry Andric /// set by MI(b,a).
getSwappedCondition(ARMCC::CondCodes CC)71480093f4SDimitry Andric inline static ARMCC::CondCodes getSwappedCondition(ARMCC::CondCodes CC) {
72480093f4SDimitry Andric switch (CC) {
73480093f4SDimitry Andric default: return ARMCC::AL;
74480093f4SDimitry Andric case ARMCC::EQ: return ARMCC::EQ;
75480093f4SDimitry Andric case ARMCC::NE: return ARMCC::NE;
76480093f4SDimitry Andric case ARMCC::HS: return ARMCC::LS;
77480093f4SDimitry Andric case ARMCC::LO: return ARMCC::HI;
78480093f4SDimitry Andric case ARMCC::HI: return ARMCC::LO;
79480093f4SDimitry Andric case ARMCC::LS: return ARMCC::HS;
80480093f4SDimitry Andric case ARMCC::GE: return ARMCC::LE;
81480093f4SDimitry Andric case ARMCC::LT: return ARMCC::GT;
82480093f4SDimitry Andric case ARMCC::GT: return ARMCC::LT;
83480093f4SDimitry Andric case ARMCC::LE: return ARMCC::GE;
84480093f4SDimitry Andric }
85480093f4SDimitry Andric }
860b57cec5SDimitry Andric } // end namespace ARMCC
870b57cec5SDimitry Andric
880b57cec5SDimitry Andric namespace ARMVCC {
890b57cec5SDimitry Andric enum VPTCodes {
900b57cec5SDimitry Andric None = 0,
910b57cec5SDimitry Andric Then,
920b57cec5SDimitry Andric Else
930b57cec5SDimitry Andric };
945ffd83dbSDimitry Andric } // namespace ARMVCC
95480093f4SDimitry Andric
965ffd83dbSDimitry Andric namespace ARM {
975ffd83dbSDimitry Andric /// Mask values for IT and VPT Blocks, to be used by MCOperands.
985ffd83dbSDimitry Andric /// Note that this is different from the "real" encoding used by the
995ffd83dbSDimitry Andric /// instructions. In this encoding, the lowest set bit indicates the end of
1005ffd83dbSDimitry Andric /// the encoding, and above that, "1" indicates an else, while "0" indicates
1015ffd83dbSDimitry Andric /// a then.
1025ffd83dbSDimitry Andric /// Tx = x100
1035ffd83dbSDimitry Andric /// Txy = xy10
1045ffd83dbSDimitry Andric /// Txyz = xyz1
1055ffd83dbSDimitry Andric enum class PredBlockMask {
1065ffd83dbSDimitry Andric T = 0b1000,
1075ffd83dbSDimitry Andric TT = 0b0100,
1085ffd83dbSDimitry Andric TE = 0b1100,
1095ffd83dbSDimitry Andric TTT = 0b0010,
1105ffd83dbSDimitry Andric TTE = 0b0110,
1115ffd83dbSDimitry Andric TEE = 0b1110,
1125ffd83dbSDimitry Andric TET = 0b1010,
1135ffd83dbSDimitry Andric TTTT = 0b0001,
1145ffd83dbSDimitry Andric TTTE = 0b0011,
1155ffd83dbSDimitry Andric TTEE = 0b0111,
1165ffd83dbSDimitry Andric TTET = 0b0101,
1175ffd83dbSDimitry Andric TEEE = 0b1111,
1185ffd83dbSDimitry Andric TEET = 0b1101,
1195ffd83dbSDimitry Andric TETT = 0b1001,
1205ffd83dbSDimitry Andric TETE = 0b1011
121480093f4SDimitry Andric };
1225ffd83dbSDimitry Andric } // namespace ARM
123480093f4SDimitry Andric
1245ffd83dbSDimitry Andric // Expands a PredBlockMask by adding an E or a T at the end, depending on Kind.
1255ffd83dbSDimitry Andric // e.g ExpandPredBlockMask(T, Then) = TT, ExpandPredBlockMask(TT, Else) = TTE,
1265ffd83dbSDimitry Andric // and so on.
1275ffd83dbSDimitry Andric ARM::PredBlockMask expandPredBlockMask(ARM::PredBlockMask BlockMask,
1285ffd83dbSDimitry Andric ARMVCC::VPTCodes Kind);
1290b57cec5SDimitry Andric
ARMVPTPredToString(ARMVCC::VPTCodes CC)1300b57cec5SDimitry Andric inline static const char *ARMVPTPredToString(ARMVCC::VPTCodes CC) {
1310b57cec5SDimitry Andric switch (CC) {
1320b57cec5SDimitry Andric case ARMVCC::None: return "none";
1330b57cec5SDimitry Andric case ARMVCC::Then: return "t";
1340b57cec5SDimitry Andric case ARMVCC::Else: return "e";
1350b57cec5SDimitry Andric }
1360b57cec5SDimitry Andric llvm_unreachable("Unknown VPT code");
1370b57cec5SDimitry Andric }
1380b57cec5SDimitry Andric
ARMVectorCondCodeFromString(StringRef CC)1390b57cec5SDimitry Andric inline static unsigned ARMVectorCondCodeFromString(StringRef CC) {
1400b57cec5SDimitry Andric return StringSwitch<unsigned>(CC.lower())
1410b57cec5SDimitry Andric .Case("t", ARMVCC::Then)
1420b57cec5SDimitry Andric .Case("e", ARMVCC::Else)
1430b57cec5SDimitry Andric .Default(~0U);
1440b57cec5SDimitry Andric }
1450b57cec5SDimitry Andric
ARMCondCodeToString(ARMCC::CondCodes CC)1460b57cec5SDimitry Andric inline static const char *ARMCondCodeToString(ARMCC::CondCodes CC) {
1470b57cec5SDimitry Andric switch (CC) {
1480b57cec5SDimitry Andric case ARMCC::EQ: return "eq";
1490b57cec5SDimitry Andric case ARMCC::NE: return "ne";
1500b57cec5SDimitry Andric case ARMCC::HS: return "hs";
1510b57cec5SDimitry Andric case ARMCC::LO: return "lo";
1520b57cec5SDimitry Andric case ARMCC::MI: return "mi";
1530b57cec5SDimitry Andric case ARMCC::PL: return "pl";
1540b57cec5SDimitry Andric case ARMCC::VS: return "vs";
1550b57cec5SDimitry Andric case ARMCC::VC: return "vc";
1560b57cec5SDimitry Andric case ARMCC::HI: return "hi";
1570b57cec5SDimitry Andric case ARMCC::LS: return "ls";
1580b57cec5SDimitry Andric case ARMCC::GE: return "ge";
1590b57cec5SDimitry Andric case ARMCC::LT: return "lt";
1600b57cec5SDimitry Andric case ARMCC::GT: return "gt";
1610b57cec5SDimitry Andric case ARMCC::LE: return "le";
1620b57cec5SDimitry Andric case ARMCC::AL: return "al";
1630b57cec5SDimitry Andric }
1640b57cec5SDimitry Andric llvm_unreachable("Unknown condition code");
1650b57cec5SDimitry Andric }
1660b57cec5SDimitry Andric
ARMCondCodeFromString(StringRef CC)1670b57cec5SDimitry Andric inline static unsigned ARMCondCodeFromString(StringRef CC) {
1680b57cec5SDimitry Andric return StringSwitch<unsigned>(CC.lower())
1690b57cec5SDimitry Andric .Case("eq", ARMCC::EQ)
1700b57cec5SDimitry Andric .Case("ne", ARMCC::NE)
1710b57cec5SDimitry Andric .Case("hs", ARMCC::HS)
1720b57cec5SDimitry Andric .Case("cs", ARMCC::HS)
1730b57cec5SDimitry Andric .Case("lo", ARMCC::LO)
1740b57cec5SDimitry Andric .Case("cc", ARMCC::LO)
1750b57cec5SDimitry Andric .Case("mi", ARMCC::MI)
1760b57cec5SDimitry Andric .Case("pl", ARMCC::PL)
1770b57cec5SDimitry Andric .Case("vs", ARMCC::VS)
1780b57cec5SDimitry Andric .Case("vc", ARMCC::VC)
1790b57cec5SDimitry Andric .Case("hi", ARMCC::HI)
1800b57cec5SDimitry Andric .Case("ls", ARMCC::LS)
1810b57cec5SDimitry Andric .Case("ge", ARMCC::GE)
1820b57cec5SDimitry Andric .Case("lt", ARMCC::LT)
1830b57cec5SDimitry Andric .Case("gt", ARMCC::GT)
1840b57cec5SDimitry Andric .Case("le", ARMCC::LE)
1850b57cec5SDimitry Andric .Case("al", ARMCC::AL)
1860b57cec5SDimitry Andric .Default(~0U);
1870b57cec5SDimitry Andric }
1880b57cec5SDimitry Andric
1890b57cec5SDimitry Andric // System Registers
1900b57cec5SDimitry Andric namespace ARMSysReg {
1910b57cec5SDimitry Andric struct MClassSysReg {
1920b57cec5SDimitry Andric const char *Name;
1930b57cec5SDimitry Andric uint16_t M1Encoding12;
1940b57cec5SDimitry Andric uint16_t M2M3Encoding8;
1950b57cec5SDimitry Andric uint16_t Encoding;
1960b57cec5SDimitry Andric FeatureBitset FeaturesRequired;
1970b57cec5SDimitry Andric
1980b57cec5SDimitry Andric // return true if FeaturesRequired are all present in ActiveFeatures
hasRequiredFeaturesMClassSysReg1990b57cec5SDimitry Andric bool hasRequiredFeatures(FeatureBitset ActiveFeatures) const {
2000b57cec5SDimitry Andric return (FeaturesRequired & ActiveFeatures) == FeaturesRequired;
2010b57cec5SDimitry Andric }
2020b57cec5SDimitry Andric
2030b57cec5SDimitry Andric // returns true if TestFeatures are all present in FeaturesRequired
isInRequiredFeaturesMClassSysReg2040b57cec5SDimitry Andric bool isInRequiredFeatures(FeatureBitset TestFeatures) const {
2050b57cec5SDimitry Andric return (FeaturesRequired & TestFeatures) == TestFeatures;
2060b57cec5SDimitry Andric }
2070b57cec5SDimitry Andric };
2080b57cec5SDimitry Andric
2090b57cec5SDimitry Andric #define GET_MCLASSSYSREG_DECL
2100b57cec5SDimitry Andric #include "ARMGenSystemRegister.inc"
2110b57cec5SDimitry Andric
2120b57cec5SDimitry Andric // lookup system register using 12-bit SYSm value.
2130b57cec5SDimitry Andric // Note: the search is uniqued using M1 mask
2140b57cec5SDimitry Andric const MClassSysReg *lookupMClassSysRegBy12bitSYSmValue(unsigned SYSm);
2150b57cec5SDimitry Andric
2160b57cec5SDimitry Andric // returns APSR with _<bits> qualifier.
2170b57cec5SDimitry Andric // Note: ARMv7-M deprecates using MSR APSR without a _<bits> qualifier
2180b57cec5SDimitry Andric const MClassSysReg *lookupMClassSysRegAPSRNonDeprecated(unsigned SYSm);
2190b57cec5SDimitry Andric
2200b57cec5SDimitry Andric // lookup system registers using 8-bit SYSm value
2210b57cec5SDimitry Andric const MClassSysReg *lookupMClassSysRegBy8bitSYSmValue(unsigned SYSm);
2220b57cec5SDimitry Andric
2230b57cec5SDimitry Andric } // end namespace ARMSysReg
2240b57cec5SDimitry Andric
2250b57cec5SDimitry Andric // Banked Registers
2260b57cec5SDimitry Andric namespace ARMBankedReg {
2270b57cec5SDimitry Andric struct BankedReg {
2280b57cec5SDimitry Andric const char *Name;
2290b57cec5SDimitry Andric uint16_t Encoding;
2300b57cec5SDimitry Andric };
2310b57cec5SDimitry Andric #define GET_BANKEDREG_DECL
2320b57cec5SDimitry Andric #include "ARMGenSystemRegister.inc"
2330b57cec5SDimitry Andric } // end namespace ARMBankedReg
2340b57cec5SDimitry Andric
2350b57cec5SDimitry Andric } // end namespace llvm
2360b57cec5SDimitry Andric
2370b57cec5SDimitry Andric #endif // LLVM_LIB_TARGET_ARM_UTILS_ARMBASEINFO_H
238