aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/AArch64/Utils
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/AArch64/Utils')
-rw-r--r--lib/Target/AArch64/Utils/AArch64BaseInfo.cpp424
-rw-r--r--lib/Target/AArch64/Utils/AArch64BaseInfo.h592
-rw-r--r--lib/Target/AArch64/Utils/Android.mk15
-rw-r--r--lib/Target/AArch64/Utils/LLVMBuild.txt2
-rw-r--r--lib/Target/AArch64/Utils/Makefile5
5 files changed, 469 insertions, 569 deletions
diff --git a/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp b/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp
index 2a97cd6..3c24bb3 100644
--- a/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp
+++ b/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp
@@ -18,7 +18,7 @@
using namespace llvm;
-StringRef NamedImmMapper::toString(uint32_t Value, bool &Valid) const {
+StringRef AArch64NamedImmMapper::toString(uint32_t Value, bool &Valid) const {
for (unsigned i = 0; i < NumPairs; ++i) {
if (Pairs[i].Value == Value) {
Valid = true;
@@ -30,7 +30,7 @@ StringRef NamedImmMapper::toString(uint32_t Value, bool &Valid) const {
return StringRef();
}
-uint32_t NamedImmMapper::fromString(StringRef Name, bool &Valid) const {
+uint32_t AArch64NamedImmMapper::fromString(StringRef Name, bool &Valid) const {
std::string LowerCaseName = Name.lower();
for (unsigned i = 0; i < NumPairs; ++i) {
if (Pairs[i].Name == LowerCaseName) {
@@ -43,11 +43,11 @@ uint32_t NamedImmMapper::fromString(StringRef Name, bool &Valid) const {
return -1;
}
-bool NamedImmMapper::validImm(uint32_t Value) const {
+bool AArch64NamedImmMapper::validImm(uint32_t Value) const {
return Value < TooBigImm;
}
-const NamedImmMapper::Mapping A64AT::ATMapper::ATPairs[] = {
+const AArch64NamedImmMapper::Mapping AArch64AT::ATMapper::ATPairs[] = {
{"s1e1r", S1E1R},
{"s1e2r", S1E2R},
{"s1e3r", S1E3R},
@@ -62,10 +62,10 @@ const NamedImmMapper::Mapping A64AT::ATMapper::ATPairs[] = {
{"s12e0w", S12E0W},
};
-A64AT::ATMapper::ATMapper()
- : NamedImmMapper(ATPairs, 0) {}
+AArch64AT::ATMapper::ATMapper()
+ : AArch64NamedImmMapper(ATPairs, 0) {}
-const NamedImmMapper::Mapping A64DB::DBarrierMapper::DBarrierPairs[] = {
+const AArch64NamedImmMapper::Mapping AArch64DB::DBarrierMapper::DBarrierPairs[] = {
{"oshld", OSHLD},
{"oshst", OSHST},
{"osh", OSH},
@@ -80,10 +80,10 @@ const NamedImmMapper::Mapping A64DB::DBarrierMapper::DBarrierPairs[] = {
{"sy", SY}
};
-A64DB::DBarrierMapper::DBarrierMapper()
- : NamedImmMapper(DBarrierPairs, 16u) {}
+AArch64DB::DBarrierMapper::DBarrierMapper()
+ : AArch64NamedImmMapper(DBarrierPairs, 16u) {}
-const NamedImmMapper::Mapping A64DC::DCMapper::DCPairs[] = {
+const AArch64NamedImmMapper::Mapping AArch64DC::DCMapper::DCPairs[] = {
{"zva", ZVA},
{"ivac", IVAC},
{"isw", ISW},
@@ -94,26 +94,26 @@ const NamedImmMapper::Mapping A64DC::DCMapper::DCPairs[] = {
{"cisw", CISW}
};
-A64DC::DCMapper::DCMapper()
- : NamedImmMapper(DCPairs, 0) {}
+AArch64DC::DCMapper::DCMapper()
+ : AArch64NamedImmMapper(DCPairs, 0) {}
-const NamedImmMapper::Mapping A64IC::ICMapper::ICPairs[] = {
+const AArch64NamedImmMapper::Mapping AArch64IC::ICMapper::ICPairs[] = {
{"ialluis", IALLUIS},
{"iallu", IALLU},
{"ivau", IVAU}
};
-A64IC::ICMapper::ICMapper()
- : NamedImmMapper(ICPairs, 0) {}
+AArch64IC::ICMapper::ICMapper()
+ : AArch64NamedImmMapper(ICPairs, 0) {}
-const NamedImmMapper::Mapping A64ISB::ISBMapper::ISBPairs[] = {
+const AArch64NamedImmMapper::Mapping AArch64ISB::ISBMapper::ISBPairs[] = {
{"sy", SY},
};
-A64ISB::ISBMapper::ISBMapper()
- : NamedImmMapper(ISBPairs, 16) {}
+AArch64ISB::ISBMapper::ISBMapper()
+ : AArch64NamedImmMapper(ISBPairs, 16) {}
-const NamedImmMapper::Mapping A64PRFM::PRFMMapper::PRFMPairs[] = {
+const AArch64NamedImmMapper::Mapping AArch64PRFM::PRFMMapper::PRFMPairs[] = {
{"pldl1keep", PLDL1KEEP},
{"pldl1strm", PLDL1STRM},
{"pldl2keep", PLDL2KEEP},
@@ -134,19 +134,19 @@ const NamedImmMapper::Mapping A64PRFM::PRFMMapper::PRFMPairs[] = {
{"pstl3strm", PSTL3STRM}
};
-A64PRFM::PRFMMapper::PRFMMapper()
- : NamedImmMapper(PRFMPairs, 32) {}
+AArch64PRFM::PRFMMapper::PRFMMapper()
+ : AArch64NamedImmMapper(PRFMPairs, 32) {}
-const NamedImmMapper::Mapping A64PState::PStateMapper::PStatePairs[] = {
+const AArch64NamedImmMapper::Mapping AArch64PState::PStateMapper::PStatePairs[] = {
{"spsel", SPSel},
{"daifset", DAIFSet},
{"daifclr", DAIFClr}
};
-A64PState::PStateMapper::PStateMapper()
- : NamedImmMapper(PStatePairs, 0) {}
+AArch64PState::PStateMapper::PStateMapper()
+ : AArch64NamedImmMapper(PStatePairs, 0) {}
-const NamedImmMapper::Mapping A64SysReg::MRSMapper::MRSPairs[] = {
+const AArch64NamedImmMapper::Mapping AArch64SysReg::MRSMapper::MRSPairs[] = {
{"mdccsr_el0", MDCCSR_EL0},
{"dbgdtrrx_el0", DBGDTRRX_EL0},
{"mdrar_el1", MDRAR_EL1},
@@ -176,16 +176,16 @@ const NamedImmMapper::Mapping A64SysReg::MRSMapper::MRSPairs[] = {
{"id_isar3_el1", ID_ISAR3_EL1},
{"id_isar4_el1", ID_ISAR4_EL1},
{"id_isar5_el1", ID_ISAR5_EL1},
- {"id_aa64pfr0_el1", ID_AA64PFR0_EL1},
- {"id_aa64pfr1_el1", ID_AA64PFR1_EL1},
- {"id_aa64dfr0_el1", ID_AA64DFR0_EL1},
- {"id_aa64dfr1_el1", ID_AA64DFR1_EL1},
- {"id_aa64afr0_el1", ID_AA64AFR0_EL1},
- {"id_aa64afr1_el1", ID_AA64AFR1_EL1},
- {"id_aa64isar0_el1", ID_AA64ISAR0_EL1},
- {"id_aa64isar1_el1", ID_AA64ISAR1_EL1},
- {"id_aa64mmfr0_el1", ID_AA64MMFR0_EL1},
- {"id_aa64mmfr1_el1", ID_AA64MMFR1_EL1},
+ {"id_aa64pfr0_el1", ID_A64PFR0_EL1},
+ {"id_aa64pfr1_el1", ID_A64PFR1_EL1},
+ {"id_aa64dfr0_el1", ID_A64DFR0_EL1},
+ {"id_aa64dfr1_el1", ID_A64DFR1_EL1},
+ {"id_aa64afr0_el1", ID_A64AFR0_EL1},
+ {"id_aa64afr1_el1", ID_A64AFR1_EL1},
+ {"id_aa64isar0_el1", ID_A64ISAR0_EL1},
+ {"id_aa64isar1_el1", ID_A64ISAR1_EL1},
+ {"id_aa64mmfr0_el1", ID_A64MMFR0_EL1},
+ {"id_aa64mmfr1_el1", ID_A64MMFR1_EL1},
{"mvfr0_el1", MVFR0_EL1},
{"mvfr1_el1", MVFR1_EL1},
{"mvfr2_el1", MVFR2_EL1},
@@ -245,12 +245,13 @@ const NamedImmMapper::Mapping A64SysReg::MRSMapper::MRSPairs[] = {
{"ich_elsr_el2", ICH_ELSR_EL2}
};
-A64SysReg::MRSMapper::MRSMapper() {
+AArch64SysReg::MRSMapper::MRSMapper(uint64_t FeatureBits)
+ : SysRegMapper(FeatureBits) {
InstPairs = &MRSPairs[0];
NumInstPairs = llvm::array_lengthof(MRSPairs);
}
-const NamedImmMapper::Mapping A64SysReg::MSRMapper::MSRPairs[] = {
+const AArch64NamedImmMapper::Mapping AArch64SysReg::MSRMapper::MSRPairs[] = {
{"dbgdtrtx_el0", DBGDTRTX_EL0},
{"oslar_el1", OSLAR_EL1},
{"pmswinc_el0", PMSWINC_EL0},
@@ -268,13 +269,14 @@ const NamedImmMapper::Mapping A64SysReg::MSRMapper::MSRPairs[] = {
{"icc_sgi0r_el1", ICC_SGI0R_EL1}
};
-A64SysReg::MSRMapper::MSRMapper() {
+AArch64SysReg::MSRMapper::MSRMapper(uint64_t FeatureBits)
+ : SysRegMapper(FeatureBits) {
InstPairs = &MSRPairs[0];
NumInstPairs = llvm::array_lengthof(MSRPairs);
}
-const NamedImmMapper::Mapping A64SysReg::SysRegMapper::SysRegPairs[] = {
+const AArch64NamedImmMapper::Mapping AArch64SysReg::SysRegMapper::SysRegPairs[] = {
{"osdtrrx_el1", OSDTRRX_EL1},
{"osdtrtx_el1", OSDTRTX_EL1},
{"teecr32_el1", TEECR32_EL1},
@@ -753,10 +755,16 @@ const NamedImmMapper::Mapping A64SysReg::SysRegMapper::SysRegPairs[] = {
{"ich_lr15_el2", ICH_LR15_EL2}
};
+const AArch64NamedImmMapper::Mapping
+AArch64SysReg::SysRegMapper::CycloneSysRegPairs[] = {
+ {"cpm_ioacc_ctl_el3", CPM_IOACC_CTL_EL3}
+};
+
uint32_t
-A64SysReg::SysRegMapper::fromString(StringRef Name, bool &Valid) const {
- // First search the registers shared by all
+AArch64SysReg::SysRegMapper::fromString(StringRef Name, bool &Valid) const {
std::string NameLower = Name.lower();
+
+ // First search the registers shared by all
for (unsigned i = 0; i < array_lengthof(SysRegPairs); ++i) {
if (SysRegPairs[i].Name == NameLower) {
Valid = true;
@@ -764,6 +772,16 @@ A64SysReg::SysRegMapper::fromString(StringRef Name, bool &Valid) const {
}
}
+ // Next search for target specific registers
+ if (FeatureBits & AArch64::ProcCyclone) {
+ for (unsigned i = 0; i < array_lengthof(CycloneSysRegPairs); ++i) {
+ if (CycloneSysRegPairs[i].Name == NameLower) {
+ Valid = true;
+ return CycloneSysRegPairs[i].Value;
+ }
+ }
+ }
+
// Now try the instruction-specific registers (either read-only or
// write-only).
for (unsigned i = 0; i < NumInstPairs; ++i) {
@@ -796,7 +814,8 @@ A64SysReg::SysRegMapper::fromString(StringRef Name, bool &Valid) const {
}
std::string
-A64SysReg::SysRegMapper::toString(uint32_t Bits, bool &Valid) const {
+AArch64SysReg::SysRegMapper::toString(uint32_t Bits, bool &Valid) const {
+ // First search the registers shared by all
for (unsigned i = 0; i < array_lengthof(SysRegPairs); ++i) {
if (SysRegPairs[i].Value == Bits) {
Valid = true;
@@ -804,6 +823,18 @@ A64SysReg::SysRegMapper::toString(uint32_t Bits, bool &Valid) const {
}
}
+ // Next search for target specific registers
+ if (FeatureBits & AArch64::ProcCyclone) {
+ for (unsigned i = 0; i < array_lengthof(CycloneSysRegPairs); ++i) {
+ if (CycloneSysRegPairs[i].Value == Bits) {
+ Valid = true;
+ return CycloneSysRegPairs[i].Name;
+ }
+ }
+ }
+
+ // Now try the instruction-specific registers (either read-only or
+ // write-only).
for (unsigned i = 0; i < NumInstPairs; ++i) {
if (InstPairs[i].Value == Bits) {
Valid = true;
@@ -831,7 +862,7 @@ A64SysReg::SysRegMapper::toString(uint32_t Bits, bool &Valid) const {
+ "_c" + utostr(CRm) + "_" + utostr(Op2);
}
-const NamedImmMapper::Mapping A64TLBI::TLBIMapper::TLBIPairs[] = {
+const AArch64NamedImmMapper::Mapping AArch64TLBI::TLBIMapper::TLBIPairs[] = {
{"ipas2e1is", IPAS2E1IS},
{"ipas2le1is", IPAS2LE1IS},
{"vmalle1is", VMALLE1IS},
@@ -866,308 +897,5 @@ const NamedImmMapper::Mapping A64TLBI::TLBIMapper::TLBIPairs[] = {
{"vaale1", VAALE1}
};
-A64TLBI::TLBIMapper::TLBIMapper()
- : NamedImmMapper(TLBIPairs, 0) {}
-
-bool A64Imms::isFPImm(const APFloat &Val, uint32_t &Imm8Bits) {
- const fltSemantics &Sem = Val.getSemantics();
- unsigned FracBits = APFloat::semanticsPrecision(Sem) - 1;
-
- uint32_t ExpMask;
- switch (FracBits) {
- case 10: // IEEE half-precision
- ExpMask = 0x1f;
- break;
- case 23: // IEEE single-precision
- ExpMask = 0xff;
- break;
- case 52: // IEEE double-precision
- ExpMask = 0x7ff;
- break;
- case 112: // IEEE quad-precision
- // No immediates are valid for double precision.
- return false;
- default:
- llvm_unreachable("Only half, single and double precision supported");
- }
-
- uint32_t ExpStart = FracBits;
- uint64_t FracMask = (1ULL << FracBits) - 1;
-
- uint32_t Sign = Val.isNegative();
-
- uint64_t Bits= Val.bitcastToAPInt().getLimitedValue();
- uint64_t Fraction = Bits & FracMask;
- int32_t Exponent = ((Bits >> ExpStart) & ExpMask);
- Exponent -= ExpMask >> 1;
-
- // S[d] = imm8<7>:NOT(imm8<6>):Replicate(imm8<6>, 5):imm8<5:0>:Zeros(19)
- // D[d] = imm8<7>:NOT(imm8<6>):Replicate(imm8<6>, 8):imm8<5:0>:Zeros(48)
- // This translates to: only 4 bits of fraction; -3 <= exp <= 4.
- uint64_t A64FracStart = FracBits - 4;
- uint64_t A64FracMask = 0xf;
-
- // Are there too many fraction bits?
- if (Fraction & ~(A64FracMask << A64FracStart))
- return false;
-
- if (Exponent < -3 || Exponent > 4)
- return false;
-
- uint32_t PackedFraction = (Fraction >> A64FracStart) & A64FracMask;
- uint32_t PackedExp = (Exponent + 7) & 0x7;
-
- Imm8Bits = (Sign << 7) | (PackedExp << 4) | PackedFraction;
- return true;
-}
-
-// Encoding of the immediate for logical (immediate) instructions:
-//
-// | N | imms | immr | size | R | S |
-// |---+--------+--------+------+--------------+--------------|
-// | 1 | ssssss | rrrrrr | 64 | UInt(rrrrrr) | UInt(ssssss) |
-// | 0 | 0sssss | xrrrrr | 32 | UInt(rrrrr) | UInt(sssss) |
-// | 0 | 10ssss | xxrrrr | 16 | UInt(rrrr) | UInt(ssss) |
-// | 0 | 110sss | xxxrrr | 8 | UInt(rrr) | UInt(sss) |
-// | 0 | 1110ss | xxxxrr | 4 | UInt(rr) | UInt(ss) |
-// | 0 | 11110s | xxxxxr | 2 | UInt(r) | UInt(s) |
-// | 0 | 11111x | - | | UNALLOCATED | |
-//
-// Columns 'R', 'S' and 'size' specify a "bitmask immediate" of size bits in
-// which the lower S+1 bits are ones and the remaining bits are zero, then
-// rotated right by R bits, which is then replicated across the datapath.
-//
-// + Values of 'N', 'imms' and 'immr' which do not match the above table are
-// RESERVED.
-// + If all 's' bits in the imms field are set then the instruction is
-// RESERVED.
-// + The 'x' bits in the 'immr' field are IGNORED.
-
-bool A64Imms::isLogicalImm(unsigned RegWidth, uint64_t Imm, uint32_t &Bits) {
- int RepeatWidth;
- int Rotation = 0;
- int Num1s = 0;
-
- // Because there are S+1 ones in the replicated mask, an immediate of all
- // zeros is not allowed. Filtering it here is probably more efficient.
- if (Imm == 0) return false;
-
- for (RepeatWidth = RegWidth; RepeatWidth > 1; RepeatWidth /= 2) {
- uint64_t RepeatMask = RepeatWidth == 64 ? -1 : (1ULL << RepeatWidth) - 1;
- uint64_t ReplicatedMask = Imm & RepeatMask;
-
- if (ReplicatedMask == 0) continue;
-
- // First we have to make sure the mask is actually repeated in each slot for
- // this width-specifier.
- bool IsReplicatedMask = true;
- for (unsigned i = RepeatWidth; i < RegWidth; i += RepeatWidth) {
- if (((Imm >> i) & RepeatMask) != ReplicatedMask) {
- IsReplicatedMask = false;
- break;
- }
- }
- if (!IsReplicatedMask) continue;
-
- // Now we have to work out the amount of rotation needed. The first part of
- // this calculation is actually independent of RepeatWidth, but the complex
- // case will depend on it.
- Rotation = countTrailingZeros(Imm);
- if (Rotation == 0) {
- // There were no leading zeros, which means it's either in place or there
- // are 1s at each end (e.g. 0x8003 needs rotating).
- Rotation = RegWidth == 64 ? CountLeadingOnes_64(Imm)
- : CountLeadingOnes_32(Imm);
- Rotation = RepeatWidth - Rotation;
- }
-
- uint64_t ReplicatedOnes = ReplicatedMask;
- if (Rotation != 0 && Rotation != 64)
- ReplicatedOnes = (ReplicatedMask >> Rotation)
- | ((ReplicatedMask << (RepeatWidth - Rotation)) & RepeatMask);
-
- // Of course, they may not actually be ones, so we have to check that:
- if (!isMask_64(ReplicatedOnes))
- continue;
-
- Num1s = CountTrailingOnes_64(ReplicatedOnes);
-
- // We know we've got an almost valid encoding (certainly, if this is invalid
- // no other parameters would work).
- break;
- }
-
- // The encodings which would produce all 1s are RESERVED.
- if (RepeatWidth == 1 || Num1s == RepeatWidth) return false;
-
- uint32_t N = RepeatWidth == 64;
- uint32_t ImmR = RepeatWidth - Rotation;
- uint32_t ImmS = Num1s - 1;
-
- switch (RepeatWidth) {
- default: break; // No action required for other valid rotations.
- case 16: ImmS |= 0x20; break; // 10ssss
- case 8: ImmS |= 0x30; break; // 110sss
- case 4: ImmS |= 0x38; break; // 1110ss
- case 2: ImmS |= 0x3c; break; // 11110s
- }
-
- Bits = ImmS | (ImmR << 6) | (N << 12);
-
- return true;
-}
-
-
-bool A64Imms::isLogicalImmBits(unsigned RegWidth, uint32_t Bits,
- uint64_t &Imm) {
- uint32_t N = Bits >> 12;
- uint32_t ImmR = (Bits >> 6) & 0x3f;
- uint32_t ImmS = Bits & 0x3f;
-
- // N=1 encodes a 64-bit replication and is invalid for the 32-bit
- // instructions.
- if (RegWidth == 32 && N != 0) return false;
-
- int Width = 0;
- if (N == 1)
- Width = 64;
- else if ((ImmS & 0x20) == 0)
- Width = 32;
- else if ((ImmS & 0x10) == 0)
- Width = 16;
- else if ((ImmS & 0x08) == 0)
- Width = 8;
- else if ((ImmS & 0x04) == 0)
- Width = 4;
- else if ((ImmS & 0x02) == 0)
- Width = 2;
- else {
- // ImmS is 0b11111x: UNALLOCATED
- return false;
- }
-
- int Num1s = (ImmS & (Width - 1)) + 1;
-
- // All encodings which would map to -1 (signed) are RESERVED.
- if (Num1s == Width) return false;
-
- int Rotation = (ImmR & (Width - 1));
- uint64_t Mask = (1ULL << Num1s) - 1;
- uint64_t WidthMask = Width == 64 ? -1 : (1ULL << Width) - 1;
- if (Rotation != 0 && Rotation != 64)
- Mask = (Mask >> Rotation)
- | ((Mask << (Width - Rotation)) & WidthMask);
-
- Imm = Mask;
- for (unsigned i = 1; i < RegWidth / Width; ++i) {
- Mask <<= Width;
- Imm |= Mask;
- }
-
- return true;
-}
-
-bool A64Imms::isMOVZImm(int RegWidth, uint64_t Value, int &UImm16, int &Shift) {
- // If high bits are set then a 32-bit MOVZ can't possibly work.
- if (RegWidth == 32 && (Value & ~0xffffffffULL))
- return false;
-
- for (int i = 0; i < RegWidth; i += 16) {
- // If the value is 0 when we mask out all the bits that could be set with
- // the current LSL value then it's representable.
- if ((Value & ~(0xffffULL << i)) == 0) {
- Shift = i / 16;
- UImm16 = (Value >> i) & 0xffff;
- return true;
- }
- }
- return false;
-}
-
-bool A64Imms::isMOVNImm(int RegWidth, uint64_t Value, int &UImm16, int &Shift) {
- // MOVN is defined to set its register to NOT(LSL(imm16, shift)).
-
- // We have to be a little careful about a 32-bit register: 0xffff_1234 *is*
- // representable, but ~0xffff_1234 == 0xffff_ffff_0000_edcb which is not
- // a valid input for isMOVZImm.
- if (RegWidth == 32 && (Value & ~0xffffffffULL))
- return false;
-
- uint64_t MOVZEquivalent = RegWidth == 32 ? ~Value & 0xffffffff : ~Value;
-
- return isMOVZImm(RegWidth, MOVZEquivalent, UImm16, Shift);
-}
-
-bool A64Imms::isOnlyMOVNImm(int RegWidth, uint64_t Value,
- int &UImm16, int &Shift) {
- if (isMOVZImm(RegWidth, Value, UImm16, Shift))
- return false;
-
- return isMOVNImm(RegWidth, Value, UImm16, Shift);
-}
-
-// decodeNeonModShiftImm - Decode a Neon OpCmode value into the
-// the shift amount and the shift type (shift zeros or ones in) and
-// returns whether the OpCmode value implies a shift operation.
-bool A64Imms::decodeNeonModShiftImm(unsigned OpCmode, unsigned &ShiftImm,
- unsigned &ShiftOnesIn) {
- ShiftImm = 0;
- ShiftOnesIn = false;
- bool HasShift = true;
-
- if (OpCmode == 0xe) {
- // movi byte
- HasShift = false;
- } else if (OpCmode == 0x1e) {
- // movi 64-bit bytemask
- HasShift = false;
- } else if ((OpCmode & 0xc) == 0x8) {
- // shift zeros, per halfword
- ShiftImm = ((OpCmode & 0x2) >> 1);
- } else if ((OpCmode & 0x8) == 0) {
- // shift zeros, per word
- ShiftImm = ((OpCmode & 0x6) >> 1);
- } else if ((OpCmode & 0xe) == 0xc) {
- // shift ones, per word
- ShiftOnesIn = true;
- ShiftImm = (OpCmode & 0x1);
- } else {
- // per byte, per bytemask
- llvm_unreachable("Unsupported Neon modified immediate");
- }
-
- return HasShift;
-}
-
-// decodeNeonModImm - Decode a NEON modified immediate and OpCmode values
-// into the element value and the element size in bits.
-uint64_t A64Imms::decodeNeonModImm(unsigned Val, unsigned OpCmode,
- unsigned &EltBits) {
- uint64_t DecodedVal = Val;
- EltBits = 0;
-
- if (OpCmode == 0xe) {
- // movi byte
- EltBits = 8;
- } else if (OpCmode == 0x1e) {
- // movi 64-bit bytemask
- DecodedVal = 0;
- for (unsigned ByteNum = 0; ByteNum < 8; ++ByteNum) {
- if ((Val >> ByteNum) & 1)
- DecodedVal |= (uint64_t)0xff << (8 * ByteNum);
- }
- EltBits = 64;
- } else if ((OpCmode & 0xc) == 0x8) {
- // shift zeros, per halfword
- EltBits = 16;
- } else if ((OpCmode & 0x8) == 0) {
- // shift zeros, per word
- EltBits = 32;
- } else if ((OpCmode & 0xe) == 0xc) {
- // shift ones, per word
- EltBits = 32;
- } else {
- llvm_unreachable("Unsupported Neon modified immediate");
- }
- return DecodedVal;
-}
+AArch64TLBI::TLBIMapper::TLBIMapper()
+ : AArch64NamedImmMapper(TLBIPairs, 0) {}
diff --git a/lib/Target/AArch64/Utils/AArch64BaseInfo.h b/lib/Target/AArch64/Utils/AArch64BaseInfo.h
index 39b042b..9e4c389 100644
--- a/lib/Target/AArch64/Utils/AArch64BaseInfo.h
+++ b/lib/Target/AArch64/Utils/AArch64BaseInfo.h
@@ -1,4 +1,4 @@
-//===-- AArch64BaseInfo.h - Top level definitions for AArch64- --*- C++ -*-===//
+//===-- AArch64BaseInfo.h - Top level definitions for AArch64 ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,96 +14,271 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_AARCH64_BASEINFO_H
-#define LLVM_AARCH64_BASEINFO_H
+#ifndef AArch64BASEINFO_H
+#define AArch64BASEINFO_H
+// FIXME: Is it easiest to fix this layering violation by moving the .inc
+// #includes from AArch64MCTargetDesc.h to here?
+#include "MCTargetDesc/AArch64MCTargetDesc.h" // For AArch64::X0 and friends.
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"
namespace llvm {
-// // Enums corresponding to AArch64 condition codes
-namespace A64CC {
- // 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 = 0, // Equal Equal
- NE, // Not equal Not equal, or unordered
- HS, // Unsigned higher or same >, ==, or unordered
- LO, // Unsigned lower or same Less than
- MI, // Minus, negative Less than
- PL, // Plus, positive or zero >, ==, or unordered
- VS, // Overflow Unordered
- VC, // No overflow Ordered
- 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, // Signed greater than Greater than
- LE, // Signed less than or equal <, ==, or unordered
- AL, // Always (unconditional) Always (unconditional)
- NV, // Always (unconditional) Always (unconditional)
- // Note the NV exists purely to disassemble 0b1111. Execution
- // is "always".
- Invalid
- };
+inline static unsigned getWRegFromXReg(unsigned Reg) {
+ switch (Reg) {
+ case AArch64::X0: return AArch64::W0;
+ case AArch64::X1: return AArch64::W1;
+ case AArch64::X2: return AArch64::W2;
+ case AArch64::X3: return AArch64::W3;
+ case AArch64::X4: return AArch64::W4;
+ case AArch64::X5: return AArch64::W5;
+ case AArch64::X6: return AArch64::W6;
+ case AArch64::X7: return AArch64::W7;
+ case AArch64::X8: return AArch64::W8;
+ case AArch64::X9: return AArch64::W9;
+ case AArch64::X10: return AArch64::W10;
+ case AArch64::X11: return AArch64::W11;
+ case AArch64::X12: return AArch64::W12;
+ case AArch64::X13: return AArch64::W13;
+ case AArch64::X14: return AArch64::W14;
+ case AArch64::X15: return AArch64::W15;
+ case AArch64::X16: return AArch64::W16;
+ case AArch64::X17: return AArch64::W17;
+ case AArch64::X18: return AArch64::W18;
+ case AArch64::X19: return AArch64::W19;
+ case AArch64::X20: return AArch64::W20;
+ case AArch64::X21: return AArch64::W21;
+ case AArch64::X22: return AArch64::W22;
+ case AArch64::X23: return AArch64::W23;
+ case AArch64::X24: return AArch64::W24;
+ case AArch64::X25: return AArch64::W25;
+ case AArch64::X26: return AArch64::W26;
+ case AArch64::X27: return AArch64::W27;
+ case AArch64::X28: return AArch64::W28;
+ case AArch64::FP: return AArch64::W29;
+ case AArch64::LR: return AArch64::W30;
+ case AArch64::SP: return AArch64::WSP;
+ case AArch64::XZR: return AArch64::WZR;
+ }
+ // For anything else, return it unchanged.
+ return Reg;
+}
-} // namespace A64CC
+inline static unsigned getXRegFromWReg(unsigned Reg) {
+ switch (Reg) {
+ case AArch64::W0: return AArch64::X0;
+ case AArch64::W1: return AArch64::X1;
+ case AArch64::W2: return AArch64::X2;
+ case AArch64::W3: return AArch64::X3;
+ case AArch64::W4: return AArch64::X4;
+ case AArch64::W5: return AArch64::X5;
+ case AArch64::W6: return AArch64::X6;
+ case AArch64::W7: return AArch64::X7;
+ case AArch64::W8: return AArch64::X8;
+ case AArch64::W9: return AArch64::X9;
+ case AArch64::W10: return AArch64::X10;
+ case AArch64::W11: return AArch64::X11;
+ case AArch64::W12: return AArch64::X12;
+ case AArch64::W13: return AArch64::X13;
+ case AArch64::W14: return AArch64::X14;
+ case AArch64::W15: return AArch64::X15;
+ case AArch64::W16: return AArch64::X16;
+ case AArch64::W17: return AArch64::X17;
+ case AArch64::W18: return AArch64::X18;
+ case AArch64::W19: return AArch64::X19;
+ case AArch64::W20: return AArch64::X20;
+ case AArch64::W21: return AArch64::X21;
+ case AArch64::W22: return AArch64::X22;
+ case AArch64::W23: return AArch64::X23;
+ case AArch64::W24: return AArch64::X24;
+ case AArch64::W25: return AArch64::X25;
+ case AArch64::W26: return AArch64::X26;
+ case AArch64::W27: return AArch64::X27;
+ case AArch64::W28: return AArch64::X28;
+ case AArch64::W29: return AArch64::FP;
+ case AArch64::W30: return AArch64::LR;
+ case AArch64::WSP: return AArch64::SP;
+ case AArch64::WZR: return AArch64::XZR;
+ }
+ // For anything else, return it unchanged.
+ return Reg;
+}
-inline static const char *A64CondCodeToString(A64CC::CondCodes CC) {
- switch (CC) {
- default: llvm_unreachable("Unknown condition code");
- case A64CC::EQ: return "eq";
- case A64CC::NE: return "ne";
- case A64CC::HS: return "hs";
- case A64CC::LO: return "lo";
- case A64CC::MI: return "mi";
- case A64CC::PL: return "pl";
- case A64CC::VS: return "vs";
- case A64CC::VC: return "vc";
- case A64CC::HI: return "hi";
- case A64CC::LS: return "ls";
- case A64CC::GE: return "ge";
- case A64CC::LT: return "lt";
- case A64CC::GT: return "gt";
- case A64CC::LE: return "le";
- case A64CC::AL: return "al";
- case A64CC::NV: return "nv";
+static inline unsigned getBRegFromDReg(unsigned Reg) {
+ switch (Reg) {
+ case AArch64::D0: return AArch64::B0;
+ case AArch64::D1: return AArch64::B1;
+ case AArch64::D2: return AArch64::B2;
+ case AArch64::D3: return AArch64::B3;
+ case AArch64::D4: return AArch64::B4;
+ case AArch64::D5: return AArch64::B5;
+ case AArch64::D6: return AArch64::B6;
+ case AArch64::D7: return AArch64::B7;
+ case AArch64::D8: return AArch64::B8;
+ case AArch64::D9: return AArch64::B9;
+ case AArch64::D10: return AArch64::B10;
+ case AArch64::D11: return AArch64::B11;
+ case AArch64::D12: return AArch64::B12;
+ case AArch64::D13: return AArch64::B13;
+ case AArch64::D14: return AArch64::B14;
+ case AArch64::D15: return AArch64::B15;
+ case AArch64::D16: return AArch64::B16;
+ case AArch64::D17: return AArch64::B17;
+ case AArch64::D18: return AArch64::B18;
+ case AArch64::D19: return AArch64::B19;
+ case AArch64::D20: return AArch64::B20;
+ case AArch64::D21: return AArch64::B21;
+ case AArch64::D22: return AArch64::B22;
+ case AArch64::D23: return AArch64::B23;
+ case AArch64::D24: return AArch64::B24;
+ case AArch64::D25: return AArch64::B25;
+ case AArch64::D26: return AArch64::B26;
+ case AArch64::D27: return AArch64::B27;
+ case AArch64::D28: return AArch64::B28;
+ case AArch64::D29: return AArch64::B29;
+ case AArch64::D30: return AArch64::B30;
+ case AArch64::D31: return AArch64::B31;
}
+ // For anything else, return it unchanged.
+ return Reg;
}
-inline static A64CC::CondCodes A64StringToCondCode(StringRef CondStr) {
- return StringSwitch<A64CC::CondCodes>(CondStr.lower())
- .Case("eq", A64CC::EQ)
- .Case("ne", A64CC::NE)
- .Case("ne", A64CC::NE)
- .Case("hs", A64CC::HS)
- .Case("cs", A64CC::HS)
- .Case("lo", A64CC::LO)
- .Case("cc", A64CC::LO)
- .Case("mi", A64CC::MI)
- .Case("pl", A64CC::PL)
- .Case("vs", A64CC::VS)
- .Case("vc", A64CC::VC)
- .Case("hi", A64CC::HI)
- .Case("ls", A64CC::LS)
- .Case("ge", A64CC::GE)
- .Case("lt", A64CC::LT)
- .Case("gt", A64CC::GT)
- .Case("le", A64CC::LE)
- .Case("al", A64CC::AL)
- .Case("nv", A64CC::NV)
- .Default(A64CC::Invalid);
+
+static inline unsigned getDRegFromBReg(unsigned Reg) {
+ switch (Reg) {
+ case AArch64::B0: return AArch64::D0;
+ case AArch64::B1: return AArch64::D1;
+ case AArch64::B2: return AArch64::D2;
+ case AArch64::B3: return AArch64::D3;
+ case AArch64::B4: return AArch64::D4;
+ case AArch64::B5: return AArch64::D5;
+ case AArch64::B6: return AArch64::D6;
+ case AArch64::B7: return AArch64::D7;
+ case AArch64::B8: return AArch64::D8;
+ case AArch64::B9: return AArch64::D9;
+ case AArch64::B10: return AArch64::D10;
+ case AArch64::B11: return AArch64::D11;
+ case AArch64::B12: return AArch64::D12;
+ case AArch64::B13: return AArch64::D13;
+ case AArch64::B14: return AArch64::D14;
+ case AArch64::B15: return AArch64::D15;
+ case AArch64::B16: return AArch64::D16;
+ case AArch64::B17: return AArch64::D17;
+ case AArch64::B18: return AArch64::D18;
+ case AArch64::B19: return AArch64::D19;
+ case AArch64::B20: return AArch64::D20;
+ case AArch64::B21: return AArch64::D21;
+ case AArch64::B22: return AArch64::D22;
+ case AArch64::B23: return AArch64::D23;
+ case AArch64::B24: return AArch64::D24;
+ case AArch64::B25: return AArch64::D25;
+ case AArch64::B26: return AArch64::D26;
+ case AArch64::B27: return AArch64::D27;
+ case AArch64::B28: return AArch64::D28;
+ case AArch64::B29: return AArch64::D29;
+ case AArch64::B30: return AArch64::D30;
+ case AArch64::B31: return AArch64::D31;
+ }
+ // For anything else, return it unchanged.
+ return Reg;
}
-inline static A64CC::CondCodes A64InvertCondCode(A64CC::CondCodes CC) {
- // It turns out that the condition codes have been designed so that in order
- // to reverse the intent of the condition you only have to invert the low bit:
+namespace AArch64CC {
+
+// The CondCodes constants map directly to the 4-bit encoding of the condition
+// field for predicated instructions.
+enum CondCode { // Meaning (integer) Meaning (floating-point)
+ EQ = 0x0, // Equal Equal
+ NE = 0x1, // Not equal Not equal, or unordered
+ HS = 0x2, // Unsigned higher or same >, ==, or unordered
+ LO = 0x3, // Unsigned lower Less than
+ MI = 0x4, // Minus, negative Less than
+ PL = 0x5, // Plus, positive or zero >, ==, or unordered
+ VS = 0x6, // Overflow Unordered
+ VC = 0x7, // No overflow Not unordered
+ HI = 0x8, // Unsigned higher Greater than, or unordered
+ LS = 0x9, // Unsigned lower or same Less than or equal
+ GE = 0xa, // Greater than or equal Greater than or equal
+ LT = 0xb, // Less than Less than, or unordered
+ GT = 0xc, // Greater than Greater than
+ LE = 0xd, // Less than or equal <, ==, or unordered
+ AL = 0xe, // Always (unconditional) Always (unconditional)
+ NV = 0xf, // Always (unconditional) Always (unconditional)
+ // Note the NV exists purely to disassemble 0b1111. Execution is "always".
+ Invalid
+};
- return static_cast<A64CC::CondCodes>(static_cast<unsigned>(CC) ^ 0x1);
+inline static const char *getCondCodeName(CondCode Code) {
+ switch (Code) {
+ default: llvm_unreachable("Unknown condition code");
+ case EQ: return "eq";
+ case NE: return "ne";
+ case HS: return "hs";
+ case LO: return "lo";
+ case MI: return "mi";
+ case PL: return "pl";
+ case VS: return "vs";
+ case VC: return "vc";
+ case HI: return "hi";
+ case LS: return "ls";
+ case GE: return "ge";
+ case LT: return "lt";
+ case GT: return "gt";
+ case LE: return "le";
+ case AL: return "al";
+ case NV: return "nv";
+ }
+}
+
+inline static CondCode getInvertedCondCode(CondCode Code) {
+ switch (Code) {
+ 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;
+ }
}
+/// Given a condition code, return NZCV flags that would satisfy that condition.
+/// The flag bits are in the format expected by the ccmp instructions.
+/// Note that many different flag settings can satisfy a given condition code,
+/// this function just returns one of them.
+inline static unsigned getNZCVToSatisfyCondCode(CondCode Code) {
+ // NZCV flags encoded as expected by ccmp instructions, ARMv8 ISA 5.5.7.
+ enum { N = 8, Z = 4, C = 2, V = 1 };
+ switch (Code) {
+ default: llvm_unreachable("Unknown condition code");
+ case EQ: return Z; // Z == 1
+ case NE: return 0; // Z == 0
+ case HS: return C; // C == 1
+ case LO: return 0; // C == 0
+ case MI: return N; // N == 1
+ case PL: return 0; // N == 0
+ case VS: return V; // V == 1
+ case VC: return 0; // V == 0
+ case HI: return C; // C == 1 && Z == 0
+ case LS: return 0; // C == 0 || Z == 1
+ case GE: return 0; // N == V
+ case LT: return N; // N != V
+ case GT: return 0; // Z == 0 && N == V
+ case LE: return Z; // Z == 1 || N != V
+ }
+}
+} // end namespace AArch64CC
+
/// Instances of this class can perform bidirectional mapping from random
/// identifier strings to operand encodings. For example "MSR" takes a named
/// system-register which must be encoded somehow and decoded for printing. This
@@ -115,14 +290,14 @@ inline static A64CC::CondCodes A64InvertCondCode(A64CC::CondCodes CC) {
/// out just how often these instructions are emitted before working on it. It
/// might even be optimal to just reorder the tables for the common instructions
/// rather than changing the algorithm.
-struct NamedImmMapper {
+struct AArch64NamedImmMapper {
struct Mapping {
const char *Name;
uint32_t Value;
};
template<int N>
- NamedImmMapper(const Mapping (&Pairs)[N], uint32_t TooBigImm)
+ AArch64NamedImmMapper(const Mapping (&Pairs)[N], uint32_t TooBigImm)
: Pairs(&Pairs[0]), NumPairs(N), TooBigImm(TooBigImm) {}
StringRef toString(uint32_t Value, bool &Valid) const;
@@ -138,7 +313,7 @@ protected:
uint32_t TooBigImm;
};
-namespace A64AT {
+namespace AArch64AT {
enum ATValues {
Invalid = -1, // Op0 Op1 CRn CRm Op2
S1E1R = 0x43c0, // 01 000 0111 1000 000
@@ -155,14 +330,14 @@ namespace A64AT {
S12E0W = 0x63c7 // 01 100 0111 1000 111
};
- struct ATMapper : NamedImmMapper {
+ struct ATMapper : AArch64NamedImmMapper {
const static Mapping ATPairs[];
ATMapper();
};
}
-namespace A64DB {
+namespace AArch64DB {
enum DBValues {
Invalid = -1,
OSHLD = 0x1,
@@ -179,14 +354,14 @@ namespace A64DB {
SY = 0xf
};
- struct DBarrierMapper : NamedImmMapper {
+ struct DBarrierMapper : AArch64NamedImmMapper {
const static Mapping DBarrierPairs[];
DBarrierMapper();
};
}
-namespace A64DC {
+namespace AArch64DC {
enum DCValues {
Invalid = -1, // Op1 CRn CRm Op2
ZVA = 0x5ba1, // 01 011 0111 0100 001
@@ -199,7 +374,7 @@ namespace A64DC {
CISW = 0x43f2 // 01 000 0111 1110 010
};
- struct DCMapper : NamedImmMapper {
+ struct DCMapper : AArch64NamedImmMapper {
const static Mapping DCPairs[];
DCMapper();
@@ -207,7 +382,7 @@ namespace A64DC {
}
-namespace A64IC {
+namespace AArch64IC {
enum ICValues {
Invalid = -1, // Op1 CRn CRm Op2
IALLUIS = 0x0388, // 000 0111 0001 000
@@ -216,7 +391,7 @@ namespace A64IC {
};
- struct ICMapper : NamedImmMapper {
+ struct ICMapper : AArch64NamedImmMapper {
const static Mapping ICPairs[];
ICMapper();
@@ -227,19 +402,19 @@ namespace A64IC {
}
}
-namespace A64ISB {
+namespace AArch64ISB {
enum ISBValues {
Invalid = -1,
SY = 0xf
};
- struct ISBMapper : NamedImmMapper {
+ struct ISBMapper : AArch64NamedImmMapper {
const static Mapping ISBPairs[];
ISBMapper();
};
}
-namespace A64PRFM {
+namespace AArch64PRFM {
enum PRFMValues {
Invalid = -1,
PLDL1KEEP = 0x00,
@@ -262,14 +437,14 @@ namespace A64PRFM {
PSTL3STRM = 0x15
};
- struct PRFMMapper : NamedImmMapper {
+ struct PRFMMapper : AArch64NamedImmMapper {
const static Mapping PRFMPairs[];
PRFMMapper();
};
}
-namespace A64PState {
+namespace AArch64PState {
enum PStateValues {
Invalid = -1,
SPSel = 0x05,
@@ -277,7 +452,7 @@ namespace A64PState {
DAIFClr = 0x1f
};
- struct PStateMapper : NamedImmMapper {
+ struct PStateMapper : AArch64NamedImmMapper {
const static Mapping PStatePairs[];
PStateMapper();
@@ -285,7 +460,7 @@ namespace A64PState {
}
-namespace A64SE {
+namespace AArch64SE {
enum ShiftExtSpecifiers {
Invalid = -1,
LSL,
@@ -306,7 +481,7 @@ namespace A64SE {
};
}
-namespace A64Layout {
+namespace AArch64Layout {
enum VectorLayout {
Invalid = -1,
VL_8B,
@@ -329,43 +504,43 @@ namespace A64Layout {
}
inline static const char *
-A64VectorLayoutToString(A64Layout::VectorLayout Layout) {
+AArch64VectorLayoutToString(AArch64Layout::VectorLayout Layout) {
switch (Layout) {
- case A64Layout::VL_8B: return ".8b";
- case A64Layout::VL_4H: return ".4h";
- case A64Layout::VL_2S: return ".2s";
- case A64Layout::VL_1D: return ".1d";
- case A64Layout::VL_16B: return ".16b";
- case A64Layout::VL_8H: return ".8h";
- case A64Layout::VL_4S: return ".4s";
- case A64Layout::VL_2D: return ".2d";
- case A64Layout::VL_B: return ".b";
- case A64Layout::VL_H: return ".h";
- case A64Layout::VL_S: return ".s";
- case A64Layout::VL_D: return ".d";
+ case AArch64Layout::VL_8B: return ".8b";
+ case AArch64Layout::VL_4H: return ".4h";
+ case AArch64Layout::VL_2S: return ".2s";
+ case AArch64Layout::VL_1D: return ".1d";
+ case AArch64Layout::VL_16B: return ".16b";
+ case AArch64Layout::VL_8H: return ".8h";
+ case AArch64Layout::VL_4S: return ".4s";
+ case AArch64Layout::VL_2D: return ".2d";
+ case AArch64Layout::VL_B: return ".b";
+ case AArch64Layout::VL_H: return ".h";
+ case AArch64Layout::VL_S: return ".s";
+ case AArch64Layout::VL_D: return ".d";
default: llvm_unreachable("Unknown Vector Layout");
}
}
-inline static A64Layout::VectorLayout
-A64StringToVectorLayout(StringRef LayoutStr) {
- return StringSwitch<A64Layout::VectorLayout>(LayoutStr)
- .Case(".8b", A64Layout::VL_8B)
- .Case(".4h", A64Layout::VL_4H)
- .Case(".2s", A64Layout::VL_2S)
- .Case(".1d", A64Layout::VL_1D)
- .Case(".16b", A64Layout::VL_16B)
- .Case(".8h", A64Layout::VL_8H)
- .Case(".4s", A64Layout::VL_4S)
- .Case(".2d", A64Layout::VL_2D)
- .Case(".b", A64Layout::VL_B)
- .Case(".h", A64Layout::VL_H)
- .Case(".s", A64Layout::VL_S)
- .Case(".d", A64Layout::VL_D)
- .Default(A64Layout::Invalid);
+inline static AArch64Layout::VectorLayout
+AArch64StringToVectorLayout(StringRef LayoutStr) {
+ return StringSwitch<AArch64Layout::VectorLayout>(LayoutStr)
+ .Case(".8b", AArch64Layout::VL_8B)
+ .Case(".4h", AArch64Layout::VL_4H)
+ .Case(".2s", AArch64Layout::VL_2S)
+ .Case(".1d", AArch64Layout::VL_1D)
+ .Case(".16b", AArch64Layout::VL_16B)
+ .Case(".8h", AArch64Layout::VL_8H)
+ .Case(".4s", AArch64Layout::VL_4S)
+ .Case(".2d", AArch64Layout::VL_2D)
+ .Case(".b", AArch64Layout::VL_B)
+ .Case(".h", AArch64Layout::VL_H)
+ .Case(".s", AArch64Layout::VL_S)
+ .Case(".d", AArch64Layout::VL_D)
+ .Default(AArch64Layout::Invalid);
}
-namespace A64SysReg {
+namespace AArch64SysReg {
enum SysRegROValues {
MDCCSR_EL0 = 0x9808, // 10 011 0000 0001 000
DBGDTRRX_EL0 = 0x9828, // 10 011 0000 0101 000
@@ -396,16 +571,16 @@ namespace A64SysReg {
ID_ISAR3_EL1 = 0xc013, // 11 000 0000 0010 011
ID_ISAR4_EL1 = 0xc014, // 11 000 0000 0010 100
ID_ISAR5_EL1 = 0xc015, // 11 000 0000 0010 101
- ID_AA64PFR0_EL1 = 0xc020, // 11 000 0000 0100 000
- ID_AA64PFR1_EL1 = 0xc021, // 11 000 0000 0100 001
- ID_AA64DFR0_EL1 = 0xc028, // 11 000 0000 0101 000
- ID_AA64DFR1_EL1 = 0xc029, // 11 000 0000 0101 001
- ID_AA64AFR0_EL1 = 0xc02c, // 11 000 0000 0101 100
- ID_AA64AFR1_EL1 = 0xc02d, // 11 000 0000 0101 101
- ID_AA64ISAR0_EL1 = 0xc030, // 11 000 0000 0110 000
- ID_AA64ISAR1_EL1 = 0xc031, // 11 000 0000 0110 001
- ID_AA64MMFR0_EL1 = 0xc038, // 11 000 0000 0111 000
- ID_AA64MMFR1_EL1 = 0xc039, // 11 000 0000 0111 001
+ ID_A64PFR0_EL1 = 0xc020, // 11 000 0000 0100 000
+ ID_A64PFR1_EL1 = 0xc021, // 11 000 0000 0100 001
+ ID_A64DFR0_EL1 = 0xc028, // 11 000 0000 0101 000
+ ID_A64DFR1_EL1 = 0xc029, // 11 000 0000 0101 001
+ ID_A64AFR0_EL1 = 0xc02c, // 11 000 0000 0101 100
+ ID_A64AFR1_EL1 = 0xc02d, // 11 000 0000 0101 101
+ ID_A64ISAR0_EL1 = 0xc030, // 11 000 0000 0110 000
+ ID_A64ISAR1_EL1 = 0xc031, // 11 000 0000 0110 001
+ ID_A64MMFR0_EL1 = 0xc038, // 11 000 0000 0111 000
+ ID_A64MMFR1_EL1 = 0xc039, // 11 000 0000 0111 001
MVFR0_EL1 = 0xc018, // 11 000 0000 0011 000
MVFR1_EL1 = 0xc019, // 11 000 0000 0011 001
MVFR2_EL1 = 0xc01a, // 11 000 0000 0011 010
@@ -960,38 +1135,45 @@ namespace A64SysReg {
ICH_LR12_EL2 = 0xe66c, // 11 100 1100 1101 100
ICH_LR13_EL2 = 0xe66d, // 11 100 1100 1101 101
ICH_LR14_EL2 = 0xe66e, // 11 100 1100 1101 110
- ICH_LR15_EL2 = 0xe66f // 11 100 1100 1101 111
+ ICH_LR15_EL2 = 0xe66f, // 11 100 1100 1101 111
+ };
+
+ // Cyclone specific system registers
+ enum CycloneSysRegValues {
+ CPM_IOACC_CTL_EL3 = 0xff90
};
- // Note that these do not inherit from NamedImmMapper. This class is
+ // Note that these do not inherit from AArch64NamedImmMapper. This class is
// sufficiently different in its behaviour that I don't believe it's worth
- // burdening the common NamedImmMapper with abstractions only needed in
+ // burdening the common AArch64NamedImmMapper with abstractions only needed in
// this one case.
struct SysRegMapper {
- static const NamedImmMapper::Mapping SysRegPairs[];
+ static const AArch64NamedImmMapper::Mapping SysRegPairs[];
+ static const AArch64NamedImmMapper::Mapping CycloneSysRegPairs[];
- const NamedImmMapper::Mapping *InstPairs;
+ const AArch64NamedImmMapper::Mapping *InstPairs;
size_t NumInstPairs;
+ uint64_t FeatureBits;
- SysRegMapper() {}
+ SysRegMapper(uint64_t FeatureBits) : FeatureBits(FeatureBits) { }
uint32_t fromString(StringRef Name, bool &Valid) const;
std::string toString(uint32_t Bits, bool &Valid) const;
};
struct MSRMapper : SysRegMapper {
- static const NamedImmMapper::Mapping MSRPairs[];
- MSRMapper();
+ static const AArch64NamedImmMapper::Mapping MSRPairs[];
+ MSRMapper(uint64_t FeatureBits);
};
struct MRSMapper : SysRegMapper {
- static const NamedImmMapper::Mapping MRSPairs[];
- MRSMapper();
+ static const AArch64NamedImmMapper::Mapping MRSPairs[];
+ MRSMapper(uint64_t FeatureBits);
};
uint32_t ParseGenericRegister(StringRef Name, bool &Valid);
}
-namespace A64TLBI {
+namespace AArch64TLBI {
enum TLBIValues {
Invalid = -1, // Op0 Op1 CRn CRm Op2
IPAS2E1IS = 0x6401, // 01 100 1000 0000 001
@@ -1028,7 +1210,7 @@ namespace A64TLBI {
VAALE1 = 0x443f // 01 000 1000 0111 111
};
- struct TLBIMapper : NamedImmMapper {
+ struct TLBIMapper : AArch64NamedImmMapper {
const static Mapping TLBIPairs[];
TLBIMapper();
@@ -1051,88 +1233,62 @@ namespace A64TLBI {
return true;
}
}
-}
+}
namespace AArch64II {
-
+ /// Target Operand Flag enum.
enum TOF {
- //===--------------------------------------------------------------===//
+ //===------------------------------------------------------------------===//
// AArch64 Specific MachineOperand flags.
MO_NO_FLAG,
- // MO_GOT - Represents a relocation referring to the GOT entry of a given
- // symbol. Used in adrp.
- MO_GOT,
-
- // MO_GOT_LO12 - Represents a relocation referring to the low 12 bits of the
- // GOT entry of a given symbol. Used in ldr only.
- MO_GOT_LO12,
-
- // MO_DTPREL_* - Represents a relocation referring to the offset from a
- // module's dynamic thread pointer. Used in the local-dynamic TLS access
- // model.
- MO_DTPREL_G1,
- MO_DTPREL_G0_NC,
-
- // MO_GOTTPREL_* - Represents a relocation referring to a GOT entry
- // providing the offset of a variable from the thread-pointer. Used in
- // initial-exec TLS model where this offset is assigned in the static thread
- // block and thus known by the dynamic linker.
- MO_GOTTPREL,
- MO_GOTTPREL_LO12,
-
- // MO_TLSDESC_* - Represents a relocation referring to a GOT entry providing
- // a TLS descriptor chosen by the dynamic linker. Used for the
- // general-dynamic and local-dynamic TLS access models where very littls is
- // known at link-time.
- MO_TLSDESC,
- MO_TLSDESC_LO12,
-
- // MO_TPREL_* - Represents a relocation referring to the offset of a
- // variable from the thread pointer itself. Used in the local-exec TLS
- // access model.
- MO_TPREL_G1,
- MO_TPREL_G0_NC,
-
- // MO_LO12 - On a symbol operand, this represents a relocation containing
- // lower 12 bits of the address. Used in add/sub/ldr/str.
- MO_LO12,
-
- // MO_ABS_G* - Represent the 16-bit granules of an absolute reference using
- // movz/movk instructions.
- MO_ABS_G3,
- MO_ABS_G2_NC,
- MO_ABS_G1_NC,
- MO_ABS_G0_NC
+ MO_FRAGMENT = 0x7,
+
+ /// MO_PAGE - A symbol operand with this flag represents the pc-relative
+ /// offset of the 4K page containing the symbol. This is used with the
+ /// ADRP instruction.
+ MO_PAGE = 1,
+
+ /// MO_PAGEOFF - A symbol operand with this flag represents the offset of
+ /// that symbol within a 4K page. This offset is added to the page address
+ /// to produce the complete address.
+ MO_PAGEOFF = 2,
+
+ /// MO_G3 - A symbol operand with this flag (granule 3) represents the high
+ /// 16-bits of a 64-bit address, used in a MOVZ or MOVK instruction
+ MO_G3 = 3,
+
+ /// MO_G2 - A symbol operand with this flag (granule 2) represents the bits
+ /// 32-47 of a 64-bit address, used in a MOVZ or MOVK instruction
+ MO_G2 = 4,
+
+ /// MO_G1 - A symbol operand with this flag (granule 1) represents the bits
+ /// 16-31 of a 64-bit address, used in a MOVZ or MOVK instruction
+ MO_G1 = 5,
+
+ /// MO_G0 - A symbol operand with this flag (granule 0) represents the bits
+ /// 0-15 of a 64-bit address, used in a MOVZ or MOVK instruction
+ MO_G0 = 6,
+
+ /// MO_GOT - This flag indicates that a symbol operand represents the
+ /// address of the GOT entry for the symbol, rather than the address of
+ /// the symbol itself.
+ MO_GOT = 8,
+
+ /// MO_NC - Indicates whether the linker is expected to check the symbol
+ /// reference for overflow. For example in an ADRP/ADD pair of relocations
+ /// the ADRP usually does check, but not the ADD.
+ MO_NC = 0x10,
+
+ /// MO_TLS - Indicates that the operand being accessed is some kind of
+ /// thread-local symbol. On Darwin, only one type of thread-local access
+ /// exists (pre linker-relaxation), but on ELF the TLSModel used for the
+ /// referee will affect interpretation.
+ MO_TLS = 0x20
};
-}
-
-class APFloat;
-
-namespace A64Imms {
- bool isFPImm(const APFloat &Val, uint32_t &Imm8Bits);
-
- inline bool isFPImm(const APFloat &Val) {
- uint32_t Imm8;
- return isFPImm(Val, Imm8);
- }
-
- bool isLogicalImm(unsigned RegWidth, uint64_t Imm, uint32_t &Bits);
- bool isLogicalImmBits(unsigned RegWidth, uint32_t Bits, uint64_t &Imm);
-
- bool isMOVZImm(int RegWidth, uint64_t Value, int &UImm16, int &Shift);
- bool isMOVNImm(int RegWidth, uint64_t Value, int &UImm16, int &Shift);
-
- // We sometimes want to know whether the immediate is representable with a
- // MOVN but *not* with a MOVZ (because that would take priority).
- bool isOnlyMOVNImm(int RegWidth, uint64_t Value, int &UImm16, int &Shift);
-
- uint64_t decodeNeonModImm(unsigned Val, unsigned OpCmode, unsigned &EltBits);
- bool decodeNeonModShiftImm(unsigned OpCmode, unsigned &ShiftImm,
- unsigned &ShiftOnesIn);
- }
+} // end namespace AArch64II
-} // end namespace llvm;
+} // end namespace llvm
#endif
diff --git a/lib/Target/AArch64/Utils/Android.mk b/lib/Target/AArch64/Utils/Android.mk
index b8bf795..3c1d194 100644
--- a/lib/Target/AArch64/Utils/Android.mk
+++ b/lib/Target/AArch64/Utils/Android.mk
@@ -1,5 +1,10 @@
LOCAL_PATH := $(call my-dir)
+arm64_utils_TBLGEN_TABLES := \
+ AArch64GenRegisterInfo.inc \
+ AArch64GenInstrInfo.inc \
+ AArch64GenSubtargetInfo.inc
+
arm64_utils_SRC_FILES := \
AArch64BaseInfo.cpp
@@ -16,7 +21,12 @@ LOCAL_MODULE:= libLLVMARM64Utils
LOCAL_MODULE_TAGS := optional
+TBLGEN_TD_DIR := $(LOCAL_PATH)/..
+TBLGEN_TABLES := $(arm64_utils_TBLGEN_TABLES)
+
include $(LLVM_DEVICE_BUILD_MK)
+include $(LLVM_TBLGEN_RULES_MK)
+include $(LLVM_GEN_INTRINSICS_MK)
include $(BUILD_STATIC_LIBRARY)
endif
@@ -32,5 +42,10 @@ LOCAL_MODULE:= libLLVMARM64Utils
LOCAL_MODULE_TAGS := optional
+TBLGEN_TD_DIR := $(LOCAL_PATH)/..
+TBLGEN_TABLES := $(arm64_utils_TBLGEN_TABLES)
+
include $(LLVM_HOST_BUILD_MK)
+include $(LLVM_TBLGEN_RULES_MK)
+include $(LLVM_GEN_INTRINSICS_MK)
include $(BUILD_HOST_STATIC_LIBRARY)
diff --git a/lib/Target/AArch64/Utils/LLVMBuild.txt b/lib/Target/AArch64/Utils/LLVMBuild.txt
index 4acecc9..bcefeb6 100644
--- a/lib/Target/AArch64/Utils/LLVMBuild.txt
+++ b/lib/Target/AArch64/Utils/LLVMBuild.txt
@@ -1,4 +1,4 @@
-;===- ./lib/Target/AArch646/Utils/LLVMBuild.txt ----------------*- Conf -*--===;
+;===- ./lib/Target/AArch64/Utils/LLVMBuild.txt ----------------*- Conf -*--===;
;
; The LLVM Compiler Infrastructure
;
diff --git a/lib/Target/AArch64/Utils/Makefile b/lib/Target/AArch64/Utils/Makefile
index 0f4a645..0b80f82 100644
--- a/lib/Target/AArch64/Utils/Makefile
+++ b/lib/Target/AArch64/Utils/Makefile
@@ -9,7 +9,8 @@
LEVEL = ../../../..
LIBRARYNAME = LLVMAArch64Utils
-# Hack: we need to include 'main' AArch64 target directory to grab private headers
-#CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
+# Hack: we need to include 'main' AArch64 target directory to grab private
+# headers
+CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
include $(LEVEL)/Makefile.common