blob: 27605422983d8909b3a796fdde3043c8b9ee5b0a [file] [log] [blame]
//===-- ARMBaseInfo.h - Top level definitions for ARM ---*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains small standalone helper functions and enum definitions for
// the ARM target useful for the compiler back-end and the MC libraries.
// As such, it deliberately does not include references to LLVM core
// code gen types, passes, etc..
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TARGET_ARM_UTILS_ARMBASEINFO_H
#define LLVM_LIB_TARGET_ARM_UTILS_ARMBASEINFO_H
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/MC/SubtargetFeature.h"
#include "MCTargetDesc/ARMMCTargetDesc.h"
namespace llvm {
// Enums corresponding to ARM condition codes
namespace ARMCC {
// The CondCodes constants map directly to the 4-bit encoding of the
// condition field for predicated instructions.
enum CondCodes { // Meaning (integer) Meaning (floating-point)
EQ, // Equal Equal
NE, // Not equal Not equal, or unordered
HS, // Carry set >, ==, or unordered
LO, // Carry clear Less than
MI, // Minus, negative Less than
PL, // Plus, positive or zero >, ==, or unordered
VS, // Overflow Unordered
VC, // No overflow Not unordered
HI, // Unsigned higher Greater than, or unordered
LS, // Unsigned lower or same Less than or equal
GE, // Greater than or equal Greater than or equal
LT, // Less than Less than, or unordered
GT, // Greater than Greater than
LE, // Less than or equal <, ==, or unordered
AL // Always (unconditional) Always (unconditional)
};
inline static CondCodes getOppositeCondition(CondCodes CC) {
switch (CC) {
default: llvm_unreachable("Unknown condition code");
case EQ: return NE;
case NE: return EQ;
case HS: return LO;
case LO: return HS;
case MI: return PL;
case PL: return MI;
case VS: return VC;
case VC: return VS;
case HI: return LS;
case LS: return HI;
case GE: return LT;
case LT: return GE;
case GT: return LE;
case LE: return GT;
}
}
/// getSwappedCondition - assume the flags are set by MI(a,b), return
/// the condition code if we modify the instructions such that flags are
/// set by MI(b,a).
inline static ARMCC::CondCodes getSwappedCondition(ARMCC::CondCodes CC) {
switch (CC) {
default: return ARMCC::AL;
case ARMCC::EQ: return ARMCC::EQ;
case ARMCC::NE: return ARMCC::NE;
case ARMCC::HS: return ARMCC::LS;
case ARMCC::LO: return ARMCC::HI;
case ARMCC::HI: return ARMCC::LO;
case ARMCC::LS: return ARMCC::HS;
case ARMCC::GE: return ARMCC::LE;
case ARMCC::LT: return ARMCC::GT;
case ARMCC::GT: return ARMCC::LT;
case ARMCC::LE: return ARMCC::GE;
}
}
} // end namespace ARMCC
namespace ARMVCC {
enum VPTCodes {
None = 0,
Then,
Else
};
enum VPTMaskValue {
T = 8, // 0b1000
TT = 4, // 0b0100
TE = 12, // 0b1100
TTT = 2, // 0b0010
TTE = 6, // 0b0110
TEE = 10, // 0b1010
TET = 14, // 0b1110
TTTT = 1, // 0b0001
TTTE = 3, // 0b0011
TTEE = 5, // 0b0101
TTET = 7, // 0b0111
TEEE = 9, // 0b1001
TEET = 11, // 0b1011
TETT = 13, // 0b1101
TETE = 15 // 0b1111
};
}
inline static unsigned getARMVPTBlockMask(unsigned NumInsts) {
switch (NumInsts) {
case 1:
return ARMVCC::T;
case 2:
return ARMVCC::TT;
case 3:
return ARMVCC::TTT;
case 4:
return ARMVCC::TTTT;
default:
break;
};
llvm_unreachable("Unexpected number of instruction in a VPT block");
}
inline static const char *ARMVPTPredToString(ARMVCC::VPTCodes CC) {
switch (CC) {
case ARMVCC::None: return "none";
case ARMVCC::Then: return "t";
case ARMVCC::Else: return "e";
}
llvm_unreachable("Unknown VPT code");
}
inline static unsigned ARMVectorCondCodeFromString(StringRef CC) {
return StringSwitch<unsigned>(CC.lower())
.Case("t", ARMVCC::Then)
.Case("e", ARMVCC::Else)
.Default(~0U);
}
inline static const char *ARMCondCodeToString(ARMCC::CondCodes CC) {
switch (CC) {
case ARMCC::EQ: return "eq";
case ARMCC::NE: return "ne";
case ARMCC::HS: return "hs";
case ARMCC::LO: return "lo";
case ARMCC::MI: return "mi";
case ARMCC::PL: return "pl";
case ARMCC::VS: return "vs";
case ARMCC::VC: return "vc";
case ARMCC::HI: return "hi";
case ARMCC::LS: return "ls";
case ARMCC::GE: return "ge";
case ARMCC::LT: return "lt";
case ARMCC::GT: return "gt";
case ARMCC::LE: return "le";
case ARMCC::AL: return "al";
}
llvm_unreachable("Unknown condition code");
}
inline static unsigned ARMCondCodeFromString(StringRef CC) {
return StringSwitch<unsigned>(CC.lower())
.Case("eq", ARMCC::EQ)
.Case("ne", ARMCC::NE)
.Case("hs", ARMCC::HS)
.Case("cs", ARMCC::HS)
.Case("lo", ARMCC::LO)
.Case("cc", ARMCC::LO)
.Case("mi", ARMCC::MI)
.Case("pl", ARMCC::PL)
.Case("vs", ARMCC::VS)
.Case("vc", ARMCC::VC)
.Case("hi", ARMCC::HI)
.Case("ls", ARMCC::LS)
.Case("ge", ARMCC::GE)
.Case("lt", ARMCC::LT)
.Case("gt", ARMCC::GT)
.Case("le", ARMCC::LE)
.Case("al", ARMCC::AL)
.Default(~0U);
}
// System Registers
namespace ARMSysReg {
struct MClassSysReg {
const char *Name;
uint16_t M1Encoding12;
uint16_t M2M3Encoding8;
uint16_t Encoding;
FeatureBitset FeaturesRequired;
// return true if FeaturesRequired are all present in ActiveFeatures
bool hasRequiredFeatures(FeatureBitset ActiveFeatures) const {
return (FeaturesRequired & ActiveFeatures) == FeaturesRequired;
}
// returns true if TestFeatures are all present in FeaturesRequired
bool isInRequiredFeatures(FeatureBitset TestFeatures) const {
return (FeaturesRequired & TestFeatures) == TestFeatures;
}
};
#define GET_MCLASSSYSREG_DECL
#include "ARMGenSystemRegister.inc"
// lookup system register using 12-bit SYSm value.
// Note: the search is uniqued using M1 mask
const MClassSysReg *lookupMClassSysRegBy12bitSYSmValue(unsigned SYSm);
// returns APSR with _<bits> qualifier.
// Note: ARMv7-M deprecates using MSR APSR without a _<bits> qualifier
const MClassSysReg *lookupMClassSysRegAPSRNonDeprecated(unsigned SYSm);
// lookup system registers using 8-bit SYSm value
const MClassSysReg *lookupMClassSysRegBy8bitSYSmValue(unsigned SYSm);
} // end namespace ARMSysReg
// Banked Registers
namespace ARMBankedReg {
struct BankedReg {
const char *Name;
uint16_t Encoding;
};
#define GET_BANKEDREG_DECL
#include "ARMGenSystemRegister.inc"
} // end namespace ARMBankedReg
} // end namespace llvm
#endif // LLVM_LIB_TARGET_ARM_UTILS_ARMBASEINFO_H