Index: include/llvm/Support/ARMTargetParser.def =================================================================== --- include/llvm/Support/ARMTargetParser.def +++ include/llvm/Support/ARMTargetParser.def @@ -90,7 +90,7 @@ AEK_HWDIV | AEK_DSP | AEK_CRC)) ARM_ARCH("armv8.2-a", AK_ARMV8_2A, "8.2-A", "v8.2a", ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8, (AEK_SEC | AEK_MP | AEK_VIRT | AEK_HWDIVARM | - AEK_HWDIV | AEK_DSP | AEK_CRC)) + AEK_HWDIV | AEK_DSP | AEK_CRC | AEK_RAS)) ARM_ARCH("armv8-m.base", AK_ARMV8MBaseline, "8-M.Baseline", "v8m.base", ARMBuildAttrs::CPUArch::v8_M_Base, FK_NONE, AEK_HWDIV) ARM_ARCH("armv8-m.main", AK_ARMV8MMainline, "8-M.Mainline", "v8m.main", @@ -124,6 +124,7 @@ ARM_ARCH_EXT_NAME("sec", AEK_SEC, nullptr, nullptr) ARM_ARCH_EXT_NAME("virt", AEK_VIRT, nullptr, nullptr) ARM_ARCH_EXT_NAME("fp16", AEK_FP16, "+fullfp16", "-fullfp16") +ARM_ARCH_EXT_NAME("ras", AEK_RAS, "+ras", "-ras") ARM_ARCH_EXT_NAME("os", AEK_OS, nullptr, nullptr) ARM_ARCH_EXT_NAME("iwmmxt", AEK_IWMMXT, nullptr, nullptr) ARM_ARCH_EXT_NAME("iwmmxt2", AEK_IWMMXT2, nullptr, nullptr) Index: include/llvm/Support/TargetParser.h =================================================================== --- include/llvm/Support/TargetParser.h +++ include/llvm/Support/TargetParser.h @@ -83,6 +83,7 @@ AEK_VIRT = 0x200, AEK_DSP = 0x400, AEK_FP16 = 0x800, + AEK_RAS = 0x1000, // Unsupported extensions. AEK_OS = 0x8000000, AEK_IWMMXT = 0x10000000, Index: lib/Target/AArch64/AArch64.td =================================================================== --- lib/Target/AArch64/AArch64.td +++ lib/Target/AArch64/AArch64.td @@ -32,6 +32,9 @@ def FeatureCRC : SubtargetFeature<"crc", "HasCRC", "true", "Enable ARMv8 CRC-32 checksum instructions">; +def FeatureRAS : SubtargetFeature<"ras", "HasRAS", "true", + "Enable ARMv8 Reliability, Availability and Serviceability Extensions">; + def FeaturePerfMon : SubtargetFeature<"perfmon", "HasPerfMon", "true", "Enable ARMv8 PMUv3 Performance Monitors extension">; @@ -66,7 +69,7 @@ "Support ARM v8.1a instructions", [FeatureCRC]>; def HasV8_2aOps : SubtargetFeature<"v8.2a", "HasV8_2aOps", "true", - "Support ARM v8.2a instructions", [HasV8_1aOps]>; + "Support ARM v8.2a instructions", [HasV8_1aOps, FeatureRAS]>; //===----------------------------------------------------------------------===// // Register File Description Index: lib/Target/AArch64/AArch64InstrInfo.td =================================================================== --- lib/Target/AArch64/AArch64InstrInfo.td +++ lib/Target/AArch64/AArch64InstrInfo.td @@ -26,6 +26,8 @@ AssemblerPredicate<"FeatureCrypto", "crypto">; def HasCRC : Predicate<"Subtarget->hasCRC()">, AssemblerPredicate<"FeatureCRC", "crc">; +def HasRAS : Predicate<"Subtarget->hasRAS()">, + AssemblerPredicate<"FeatureRAS", "ras">; def HasPerfMon : Predicate<"Subtarget->hasPerfMon()">; def HasFullFP16 : Predicate<"Subtarget->hasFullFP16()">, AssemblerPredicate<"FeatureFullFP16", "fullfp16">; @@ -389,6 +391,7 @@ def : InstAlias<"wfi", (HINT 0b011)>; def : InstAlias<"sev", (HINT 0b100)>; def : InstAlias<"sevl", (HINT 0b101)>; +def : InstAlias<"esb", (HINT 0b10000)>, Requires<[HasRAS]>; // v8.2a Statistical Profiling extension def : InstAlias<"psb $op", (HINT psbhint_op:$op)>, Requires<[HasSPE]>; Index: lib/Target/AArch64/AArch64Subtarget.h =================================================================== --- lib/Target/AArch64/AArch64Subtarget.h +++ lib/Target/AArch64/AArch64Subtarget.h @@ -54,6 +54,7 @@ bool HasNEON; bool HasCrypto; bool HasCRC; + bool HasRAS; bool HasPerfMon; bool HasFullFP16; bool HasSPE; @@ -140,6 +141,7 @@ bool hasNEON() const { return HasNEON; } bool hasCrypto() const { return HasCrypto; } bool hasCRC() const { return HasCRC; } + bool hasRAS() const { return HasRAS; } /// CPU has TBI (top byte of addresses is ignored during HW address /// translation) and OS enables it. bool supportsAddressTopByteIgnored() const; Index: lib/Target/AArch64/AArch64Subtarget.cpp =================================================================== --- lib/Target/AArch64/AArch64Subtarget.cpp +++ lib/Target/AArch64/AArch64Subtarget.cpp @@ -51,10 +51,11 @@ const TargetMachine &TM, bool LittleEndian) : AArch64GenSubtargetInfo(TT, CPU, FS), ARMProcFamily(Others), HasV8_1aOps(false), HasV8_2aOps(false), HasFPARMv8(false), HasNEON(false), - HasCrypto(false), HasCRC(false), HasPerfMon(false), HasFullFP16(false), - HasZeroCycleRegMove(false), HasZeroCycleZeroing(false), - StrictAlign(false), ReserveX18(TT.isOSDarwin()), IsLittle(LittleEndian), - CPUString(CPU), TargetTriple(TT), FrameLowering(), + HasCrypto(false), HasCRC(false), HasRAS(false), HasPerfMon(false), + HasFullFP16(false), HasZeroCycleRegMove(false), + HasZeroCycleZeroing(false), StrictAlign(false), + ReserveX18(TT.isOSDarwin()), IsLittle(LittleEndian), CPUString(CPU), + TargetTriple(TT), FrameLowering(), InstrInfo(initializeSubtargetDependencies(FS)), TSInfo(), TLInfo(TM, *this), GISel() {} Index: lib/Target/AArch64/Utils/AArch64BaseInfo.h =================================================================== --- lib/Target/AArch64/Utils/AArch64BaseInfo.h +++ lib/Target/AArch64/Utils/AArch64BaseInfo.h @@ -672,7 +672,11 @@ ICC_RPR_EL1 = 0xc65b, // 11 000 1100 1011 011 ICH_VTR_EL2 = 0xe659, // 11 100 1100 1011 001 ICH_EISR_EL2 = 0xe65b, // 11 100 1100 1011 011 - ICH_ELSR_EL2 = 0xe65d // 11 100 1100 1011 101 + ICH_ELSR_EL2 = 0xe65d, // 11 100 1100 1011 101 + + // RAS extension registers + ERRIDR_EL1 = 0xc298, // 11 000 0101 0011 000 + ERXFR_EL1 = 0xc2a0 // 11 000 0101 0100 000 }; enum SysRegWOValues { @@ -1211,6 +1215,17 @@ SPSR_EL12 = 0xea00, // 11 101 0100 0000 000 ELR_EL12 = 0xea01, // 11 101 0100 0000 001 + // RAS extension registers + ERRSELR_EL1 = 0xc299, // 11 000 0101 0011 001 + ERXCTLR_EL1 = 0xc2a1, // 11 000 0101 0100 001 + ERXSTATUS_EL1 = 0xc2a2, // 11 000 0101 0100 010 + ERXADDR_EL1 = 0xc2a3, // 11 000 0101 0100 011 + ERXMISC0_EL1 = 0xc2a8, // 11 000 0101 0101 000 + ERXMISC1_EL1 = 0xc2a9, // 11 000 0101 0101 001 + DISR_EL1 = 0xc609, // 11 000 1100 0001 001 + VDISR_EL2 = 0xe609, // 11 100 1100 0001 001 + VSESR_EL2 = 0xe293, // 11 100 0101 0010 011 + // v8.2a registers UAO = 0xc214, // 11 000 0100 0010 100 Index: lib/Target/AArch64/Utils/AArch64BaseInfo.cpp =================================================================== --- lib/Target/AArch64/Utils/AArch64BaseInfo.cpp +++ lib/Target/AArch64/Utils/AArch64BaseInfo.cpp @@ -263,6 +263,10 @@ // v8.1a "Limited Ordering Regions" extension-specific system registers {"lorid_el1", LORID_EL1, {AArch64::HasV8_1aOps}}, + + // v8.2a "Reliability, Availability and Serviceability" extensions registers + {"erridr_el1", ERRIDR_EL1, {AArch64::FeatureRAS}}, + {"erxfr_el1", ERXFR_EL1, {AArch64::FeatureRAS}} }; AArch64SysReg::MRSMapper::MRSMapper() { @@ -816,6 +820,17 @@ // v8.2a registers {"uao", UAO, {AArch64::HasV8_2aOps}}, + // v8.2a "Reliability, Availability and Serviceability" extensions registers + {"errselr_el1", ERRSELR_EL1, {AArch64::FeatureRAS}}, + {"erxctlr_el1", ERXCTLR_EL1, {AArch64::FeatureRAS}}, + {"erxstatus_el1", ERXSTATUS_EL1, {AArch64::FeatureRAS}}, + {"erxaddr_el1", ERXADDR_EL1, {AArch64::FeatureRAS}}, + {"erxmisc0_el1", ERXMISC0_EL1, {AArch64::FeatureRAS}}, + {"erxmisc1_el1", ERXMISC1_EL1, {AArch64::FeatureRAS}}, + {"disr_el1", DISR_EL1, {AArch64::FeatureRAS}}, + {"vdisr_el2", VDISR_EL2, {AArch64::FeatureRAS}}, + {"vsesr_el2", VSESR_EL2, {AArch64::FeatureRAS}}, + // v8.2a "Statistical Profiling extension" registers {"pmblimitr_el1", PMBLIMITR_EL1, {AArch64::FeatureSPE}}, {"pmbptr_el1", PMBPTR_EL1, {AArch64::FeatureSPE}}, Index: lib/Target/ARM/ARM.td =================================================================== --- lib/Target/ARM/ARM.td +++ lib/Target/ARM/ARM.td @@ -96,6 +96,10 @@ [FeatureNEON]>; def FeatureCRC : SubtargetFeature<"crc", "HasCRC", "true", "Enable support for CRC instructions">; +// Not to be confused with FeatureHasRetAddrStack (return address stack) +def FeatureRAS : SubtargetFeature<"ras", "HasRAS", "true", + "Enable Reliability, Availability and Serviceability extensions">; + // Cyclone has preferred instructions for zeroing VFP registers, which can // execute in 0 cycles. @@ -137,7 +141,7 @@ // Some processors perform return stack prediction. CodeGen should avoid issue // "normal" call instructions to callees which do not return. -def FeatureHasRAS : SubtargetFeature<"ras", "HasRAS", "true", +def FeatureHasRetAddrStack : SubtargetFeature<"ret-addr-stack", "HasRetAddrStack", "true", "Has return address stack">; /// DSP extension. @@ -392,7 +396,8 @@ FeatureMP, FeatureVirtualization, FeatureCrypto, - FeatureCRC]>; + FeatureCRC, + FeatureRAS]>; def ARMv8mBaseline : Architecture<"armv8-m.base", "ARMv8mBaseline", [HasV8MBaselineOps, @@ -489,7 +494,7 @@ // FIXME: A5 has currently the same Schedule model as A8 def : ProcessorModel<"cortex-a5", CortexA8Model, [ARMv7a, ProcA5, - FeatureHasRAS, + FeatureHasRetAddrStack, FeatureTrustZone, FeatureSlowFPBrcc, FeatureHasSlowFPVMLx, @@ -499,7 +504,7 @@ FeatureVFP4]>; def : ProcessorModel<"cortex-a7", CortexA8Model, [ARMv7a, ProcA7, - FeatureHasRAS, + FeatureHasRetAddrStack, FeatureTrustZone, FeatureSlowFPBrcc, FeatureHasSlowFPVMLx, @@ -512,7 +517,7 @@ FeatureVirtualization]>; def : ProcessorModel<"cortex-a8", CortexA8Model, [ARMv7a, ProcA8, - FeatureHasRAS, + FeatureHasRetAddrStack, FeatureTrustZone, FeatureSlowFPBrcc, FeatureHasSlowFPVMLx, @@ -520,7 +525,7 @@ FeatureT2XtPk]>; def : ProcessorModel<"cortex-a9", CortexA9Model, [ARMv7a, ProcA9, - FeatureHasRAS, + FeatureHasRetAddrStack, FeatureTrustZone, FeatureVMLxForwarding, FeatureT2XtPk, @@ -530,7 +535,7 @@ // FIXME: A12 has currently the same Schedule model as A9 def : ProcessorModel<"cortex-a12", CortexA9Model, [ARMv7a, ProcA12, - FeatureHasRAS, + FeatureHasRetAddrStack, FeatureTrustZone, FeatureVMLxForwarding, FeatureT2XtPk, @@ -543,7 +548,7 @@ // FIXME: A15 has currently the same Schedule model as A9. def : ProcessorModel<"cortex-a15", CortexA9Model, [ARMv7a, ProcA15, - FeatureHasRAS, + FeatureHasRetAddrStack, FeatureTrustZone, FeatureT2XtPk, FeatureVFP4, @@ -555,7 +560,7 @@ // FIXME: A17 has currently the same Schedule model as A9 def : ProcessorModel<"cortex-a17", CortexA9Model, [ARMv7a, ProcA17, - FeatureHasRAS, + FeatureHasRetAddrStack, FeatureTrustZone, FeatureMP, FeatureVMLxForwarding, @@ -570,7 +575,7 @@ // FIXME: krait has currently the same features as A9 plus VFP4 and hardware // division features. def : ProcessorModel<"krait", CortexA9Model, [ARMv7a, ProcKrait, - FeatureHasRAS, + FeatureHasRetAddrStack, FeatureVMLxForwarding, FeatureT2XtPk, FeatureFP16, @@ -580,7 +585,7 @@ FeatureHWDivARM]>; def : ProcessorModel<"swift", SwiftModel, [ARMv7a, ProcSwift, - FeatureHasRAS, + FeatureHasRetAddrStack, FeatureNEONForFP, FeatureT2XtPk, FeatureVFP4, @@ -593,13 +598,13 @@ // FIXME: R4 has currently the same ProcessorModel as A8. def : ProcessorModel<"cortex-r4", CortexA8Model, [ARMv7r, ProcR4, - FeatureHasRAS, + FeatureHasRetAddrStack, FeatureAvoidPartialCPSR, FeatureT2XtPk]>; // FIXME: R4F has currently the same ProcessorModel as A8. def : ProcessorModel<"cortex-r4f", CortexA8Model, [ARMv7r, ProcR4, - FeatureHasRAS, + FeatureHasRetAddrStack, FeatureSlowFPBrcc, FeatureHasSlowFPVMLx, FeatureVFP3, @@ -609,7 +614,7 @@ // FIXME: R5 has currently the same ProcessorModel as A8. def : ProcessorModel<"cortex-r5", CortexA8Model, [ARMv7r, ProcR5, - FeatureHasRAS, + FeatureHasRetAddrStack, FeatureVFP3, FeatureD16, FeatureSlowFPBrcc, @@ -620,7 +625,7 @@ // FIXME: R7 has currently the same ProcessorModel as A8 and is modelled as R5. def : ProcessorModel<"cortex-r7", CortexA8Model, [ARMv7r, ProcR7, - FeatureHasRAS, + FeatureHasRetAddrStack, FeatureVFP3, FeatureD16, FeatureFP16, @@ -632,7 +637,7 @@ FeatureT2XtPk]>; def : ProcessorModel<"cortex-r8", CortexA8Model, [ARMv7r, - FeatureHasRAS, + FeatureHasRetAddrStack, FeatureVFP3, FeatureD16, FeatureFP16, @@ -692,7 +697,7 @@ // Cyclone is very similar to swift def : ProcessorModel<"cyclone", SwiftModel, [ARMv8a, ProcSwift, - FeatureHasRAS, + FeatureHasRetAddrStack, FeatureNEONForFP, FeatureT2XtPk, FeatureVFP4, Index: lib/Target/ARM/ARMISelLowering.cpp =================================================================== --- lib/Target/ARM/ARMISelLowering.cpp +++ lib/Target/ARM/ARMISelLowering.cpp @@ -1919,7 +1919,7 @@ } else { if (!isDirect && !Subtarget->hasV5TOps()) CallOpc = ARMISD::CALL_NOLINK; - else if (doesNotRet && isDirect && Subtarget->hasRAS() && + else if (doesNotRet && isDirect && Subtarget->hasRetAddrStack() && // Emit regular call when code size is the priority !MF.getFunction()->optForMinSize()) // "mov lr, pc; b _foo" to avoid confusing the RSP Index: lib/Target/ARM/ARMInstrInfo.td =================================================================== --- lib/Target/ARM/ARMInstrInfo.td +++ lib/Target/ARM/ARMInstrInfo.td @@ -241,6 +241,8 @@ AssemblerPredicate<"FeatureCrypto", "crypto">; def HasCRC : Predicate<"Subtarget->hasCRC()">, AssemblerPredicate<"FeatureCRC", "crc">; +def HasRAS : Predicate<"Subtarget->hasRAS()">, + AssemblerPredicate<"FeatureRAS", "ras">; def HasFP16 : Predicate<"Subtarget->hasFP16()">, AssemblerPredicate<"FeatureFP16","half-float conversions">; def HasFullFP16 : Predicate<"Subtarget->hasFullFP16()">, @@ -1910,6 +1912,7 @@ bits<8> imm; let Inst{27-8} = 0b00110010000011110000; let Inst{7-0} = imm; + let DecoderMethod = "DecodeHINTInstruction"; } def : InstAlias<"nop$p", (HINT 0, pred:$p)>, Requires<[IsARM, HasV6K]>; @@ -1918,6 +1921,7 @@ def : InstAlias<"wfi$p", (HINT 3, pred:$p)>, Requires<[IsARM, HasV6K]>; def : InstAlias<"sev$p", (HINT 4, pred:$p)>, Requires<[IsARM, HasV6K]>; def : InstAlias<"sevl$p", (HINT 5, pred:$p)>, Requires<[IsARM, HasV8]>; +def : InstAlias<"esb$p", (HINT 16, pred:$p)>, Requires<[IsARM, HasRAS]>; def SEL : AI<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), DPFrm, NoItinerary, "sel", "\t$Rd, $Rn, $Rm", []>, Requires<[IsARM, HasV6]> { Index: lib/Target/ARM/ARMInstrThumb2.td =================================================================== --- lib/Target/ARM/ARMInstrThumb2.td +++ lib/Target/ARM/ARMInstrThumb2.td @@ -3729,6 +3729,12 @@ def : t2InstAlias<"sevl$p.w", (t2HINT 5, pred:$p), 1> { let Predicates = [IsThumb2, HasV8]; } +def : t2InstAlias<"esb$p.w", (t2HINT 16, pred:$p), 1> { + let Predicates = [IsThumb2, HasRAS]; +} +def : t2InstAlias<"esb$p", (t2HINT 16, pred:$p), 0> { + let Predicates = [IsThumb2, HasRAS]; +} def t2DBG : T2I<(outs), (ins imm0_15:$opt), NoItinerary, "dbg", "\t$opt", [(int_arm_dbg imm0_15:$opt)]> { Index: lib/Target/ARM/ARMSubtarget.h =================================================================== --- lib/Target/ARM/ARMSubtarget.h +++ lib/Target/ARM/ARMSubtarget.h @@ -178,9 +178,9 @@ /// movs with shifter operand (i.e. asr, lsl, lsr). bool AvoidMOVsShifterOperand; - /// HasRAS - Some processors perform return stack prediction. CodeGen should + /// HasRetAddrStack - Some processors perform return stack prediction. CodeGen should /// avoid issue "normal" call instructions to callees which do not return. - bool HasRAS; + bool HasRetAddrStack; /// HasMPExtension - True if the subtarget supports Multiprocessing /// extension (ARMv7 only). @@ -211,6 +211,9 @@ /// HasCRC - if true, processor supports CRC instructions bool HasCRC; + /// HasRAS - if true, the processor supports RAS extensions + bool HasRAS; + /// If true, the instructions "vmov.i32 d0, #0" and "vmov.i32 q0, #0" are /// particularly effective at zeroing a VFP register. bool HasZeroCycleZeroing; @@ -349,6 +352,7 @@ bool hasNEON() const { return HasNEON; } bool hasCrypto() const { return HasCrypto; } bool hasCRC() const { return HasCRC; } + bool hasRAS() const { return HasRAS; } bool hasVirtualization() const { return HasVirtualization; } bool useNEONForSinglePrecisionFP() const { return hasNEON() && UseNEONForSinglePrecisionFP; @@ -375,7 +379,7 @@ bool prefers32BitThumb() const { return Pref32BitThumb; } bool avoidCPSRPartialUpdate() const { return AvoidCPSRPartialUpdate; } bool avoidMOVsShifterOperand() const { return AvoidMOVsShifterOperand; } - bool hasRAS() const { return HasRAS; } + bool hasRetAddrStack() const { return HasRetAddrStack; } bool hasMPExtension() const { return HasMPExtension; } bool hasDSP() const { return HasDSP; } bool useNaClTrap() const { return UseNaClTrap; } Index: lib/Target/ARM/ARMSubtarget.cpp =================================================================== --- lib/Target/ARM/ARMSubtarget.cpp +++ lib/Target/ARM/ARMSubtarget.cpp @@ -142,7 +142,7 @@ Pref32BitThumb = false; AvoidCPSRPartialUpdate = false; AvoidMOVsShifterOperand = false; - HasRAS = false; + HasRetAddrStack = false; HasMPExtension = false; HasVirtualization = false; FPOnlySP = false; @@ -151,6 +151,7 @@ Has8MSecExt = false; HasCrypto = false; HasCRC = false; + HasRAS = false; HasZeroCycleZeroing = false; StrictAlign = false; HasDSP = false; Index: lib/Target/ARM/AsmParser/ARMAsmParser.cpp =================================================================== --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -290,6 +290,9 @@ bool hasV8_1aOps() const { return getSTI().getFeatureBits()[ARM::HasV8_1aOps]; } + bool hasRAS() const { + return getSTI().getFeatureBits()[ARM::FeatureRAS]; + } void SwitchMode() { MCSubtargetInfo &STI = copySTI(); @@ -6474,6 +6477,20 @@ "immediate expression for mov requires :lower16: or :upper16"); break; } + case ARM::HINT: + case ARM::t2HINT: { + if (hasRAS()) { + // ESB is not predicable (pred must be AL) + unsigned Imm8 = Inst.getOperand(0).getImm(); + unsigned Pred = Inst.getOperand(1).getImm(); + if (Imm8 == 0x10 && Pred != ARMCC::AL) + return Error(Operands[1]->getStartLoc(), "instruction 'esb' is not " + "predicable, but condition " + "code specified"); + } + // Without the RAS extension, this behaves as any other unallocated hint. + break; + } } return false; @@ -10031,6 +10048,7 @@ // FIXME: Only available in A-class, isel not predicated { ARM::AEK_VIRT, Feature_HasV7, {ARM::FeatureVirtualization} }, { ARM::AEK_FP16, Feature_HasV8_2a, {ARM::FeatureFPARMv8, ARM::FeatureFullFP16} }, + { ARM::AEK_RAS, Feature_HasV8, {ARM::FeatureRAS} }, // FIXME: Unsupported extensions. { ARM::AEK_OS, Feature_None, {} }, { ARM::AEK_IWMMXT, Feature_None, {} }, Index: lib/Target/ARM/Disassembler/ARMDisassembler.cpp =================================================================== --- lib/Target/ARM/Disassembler/ARMDisassembler.cpp +++ lib/Target/ARM/Disassembler/ARMDisassembler.cpp @@ -210,6 +210,8 @@ uint64_t Address, const void *Decoder); static DecodeStatus DecodeSMLAInstruction(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeHINTInstruction(MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder); static DecodeStatus DecodeCPSInstruction(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeTSTInstruction(MCInst &Inst, unsigned Insn, @@ -592,6 +594,8 @@ ThumbDisassembler::AddThumbPredicate(MCInst &MI) const { MCDisassembler::DecodeStatus S = Success; + const FeatureBitset &FeatureBits = getSubtargetInfo().getFeatureBits(); + // A few instructions actually have predicates encoded in them. Don't // try to overwrite it if we're seeing one of those. switch (MI.getOpcode()) { @@ -612,6 +616,10 @@ else return Success; break; + case ARM::t2HINT: + if (MI.getOperand(0).getImm() == 0x10 && (FeatureBits[ARM::FeatureRAS]) != 0) + S = SoftFail; + break; case ARM::tB: case ARM::t2B: case ARM::t2TBB: @@ -1943,6 +1951,29 @@ return S; } +// Check for UNPREDICTABLE predicated ESB instruction +static DecodeStatus DecodeHINTInstruction(MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + unsigned pred = fieldFromInstruction(Insn, 28, 4); + unsigned imm8 = fieldFromInstruction(Insn, 0, 8); + const MCDisassembler *Dis = static_cast(Decoder); + const FeatureBitset &FeatureBits = Dis->getSubtargetInfo().getFeatureBits(); + + DecodeStatus S = MCDisassembler::Success; + + Inst.addOperand(MCOperand::createImm(imm8)); + + if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder))) + return MCDisassembler::Fail; + + // ESB is unpredictable if pred != AL. Without the RAS extension, it is a NOP, + // so all predicates should be allowed. + if (imm8 == 0x10 && pred != 0xe && ((FeatureBits[ARM::FeatureRAS]) != 0)) + S = MCDisassembler::SoftFail; + + return S; +} + static DecodeStatus DecodeCPSInstruction(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { unsigned imod = fieldFromInstruction(Insn, 18, 2); Index: test/MC/AArch64/ras-extension.s =================================================================== --- /dev/null +++ test/MC/AArch64/ras-extension.s @@ -0,0 +1,55 @@ +// RUN: llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=+ras < %s | FileCheck %s + + esb +// CHECK: esb // encoding: [0x1f,0x22,0x03,0xd5] + + msr errselr_el1, x0 + msr errselr_el1, x15 + msr errselr_el1, x25 + msr erxctlr_el1, x1 + msr erxstatus_el1, x2 + msr erxaddr_el1, x3 + msr erxmisc0_el1, x4 + msr erxmisc1_el1, x5 + msr disr_el1, x6 + msr vdisr_el2, x7 + msr vsesr_el2, x8 +// CHECK: msr ERRSELR_EL1, x0 // encoding: [0x20,0x53,0x18,0xd5] +// CHECK: msr ERRSELR_EL1, x15 // encoding: [0x2f,0x53,0x18,0xd5] +// CHECK: msr ERRSELR_EL1, x25 // encoding: [0x39,0x53,0x18,0xd5] +// CHECK: msr ERXCTLR_EL1, x1 // encoding: [0x21,0x54,0x18,0xd5] +// CHECK: msr ERXSTATUS_EL1, x2 // encoding: [0x42,0x54,0x18,0xd5] +// CHECK: msr ERXADDR_EL1, x3 // encoding: [0x63,0x54,0x18,0xd5] +// CHECK: msr ERXMISC0_EL1, x4 // encoding: [0x04,0x55,0x18,0xd5] +// CHECK: msr ERXMISC1_EL1, x5 // encoding: [0x25,0x55,0x18,0xd5] +// CHECK: msr DISR_EL1, x6 // encoding: [0x26,0xc1,0x18,0xd5] +// CHECK: msr VDISR_EL2, x7 // encoding: [0x27,0xc1,0x1c,0xd5] +// CHECK: msr VSESR_EL2, x8 // encoding: [0x68,0x52,0x1c,0xd5] + + mrs x0, errselr_el1 + mrs x15, errselr_el1 + mrs x25, errselr_el1 + mrs x1, erxctlr_el1 + mrs x2, erxstatus_el1 + mrs x3, erxaddr_el1 + mrs x4, erxmisc0_el1 + mrs x5, erxmisc1_el1 + mrs x6, disr_el1 + mrs x7, vdisr_el2 + mrs x8, vsesr_el2 +// CHECK: mrs x0, ERRSELR_EL1 // encoding: [0x20,0x53,0x38,0xd5] +// CHECK: mrs x15, ERRSELR_EL1 // encoding: [0x2f,0x53,0x38,0xd5] +// CHECK: mrs x25, ERRSELR_EL1 // encoding: [0x39,0x53,0x38,0xd5] +// CHECK: mrs x1, ERXCTLR_EL1 // encoding: [0x21,0x54,0x38,0xd5] +// CHECK: mrs x2, ERXSTATUS_EL1 // encoding: [0x42,0x54,0x38,0xd5] +// CHECK: mrs x3, ERXADDR_EL1 // encoding: [0x63,0x54,0x38,0xd5] +// CHECK: mrs x4, ERXMISC0_EL1 // encoding: [0x04,0x55,0x38,0xd5] +// CHECK: mrs x5, ERXMISC1_EL1 // encoding: [0x25,0x55,0x38,0xd5] +// CHECK: mrs x6, DISR_EL1 // encoding: [0x26,0xc1,0x38,0xd5] +// CHECK: mrs x7, VDISR_EL2 // encoding: [0x27,0xc1,0x3c,0xd5] +// CHECK: mrs x8, VSESR_EL2 // encoding: [0x68,0x52,0x3c,0xd5] + + mrs x0, erridr_el1 + mrs x1, erxfr_el1 +// CHECK: mrs x0, ERRIDR_EL1 // encoding: [0x00,0x53,0x38,0xd5] +// CHECK: mrs x1, ERXFR_EL1 // encoding: [0x01,0x54,0x38,0xd5] Index: test/MC/ARM/ras-extension.s =================================================================== --- /dev/null +++ test/MC/ARM/ras-extension.s @@ -0,0 +1,6 @@ +@ RUN: llvm-mc -triple armv8a-none-eabi -mattr=+ras -show-encoding %s | FileCheck %s --check-prefix=ARM +@ RUN: llvm-mc -triple thumbv8a-none-eabi -mattr=+ras -show-encoding %s | FileCheck %s --check-prefix=THUMB + + esb +@ ARM: esb @ encoding: [0x10,0xf0,0x20,0xe3] +@ THUMB: esb.w @ encoding: [0xaf,0xf3,0x10,0x80] Index: test/MC/Disassembler/AArch64/ras-extension.txt =================================================================== --- /dev/null +++ test/MC/Disassembler/AArch64/ras-extension.txt @@ -0,0 +1,47 @@ +# RUN: llvm-mc -triple aarch64-none-linux-gnu -mattr=+ras --disassemble < %s | FileCheck %s + +[0x1f,0x22,0x03,0xd5] +# CHECK: esb + +# CHECK: msr ERRSELR_EL1, x0 +# CHECK: msr ERXCTLR_EL1, x0 +# CHECK: msr ERXSTATUS_EL1, x0 +# CHECK: msr ERXADDR_EL1, x0 +# CHECK: msr ERXMISC0_EL1, x0 +# CHECK: msr ERXMISC1_EL1, x0 +# CHECK: msr DISR_EL1, x0 +# CHECK: msr VDISR_EL2, x0 +# CHECK: msr VSESR_EL2, x0 +[0x20,0x53,0x18,0xd5] +[0x20,0x54,0x18,0xd5] +[0x40,0x54,0x18,0xd5] +[0x60,0x54,0x18,0xd5] +[0x00,0x55,0x18,0xd5] +[0x20,0x55,0x18,0xd5] +[0x20,0xc1,0x18,0xd5] +[0x20,0xc1,0x1c,0xd5] +[0x60,0x52,0x1c,0xd5] + +# CHECK: mrs x0, ERRSELR_EL1 +# CHECK: mrs x0, ERXCTLR_EL1 +# CHECK: mrs x0, ERXSTATUS_EL1 +# CHECK: mrs x0, ERXADDR_EL1 +# CHECK: mrs x0, ERXMISC0_EL1 +# CHECK: mrs x0, ERXMISC1_EL1 +# CHECK: mrs x0, DISR_EL1 +# CHECK: mrs x0, VDISR_EL2 +# CHECK: mrs x0, VSESR_EL2 +[0x20,0x53,0x38,0xd5] +[0x20,0x54,0x38,0xd5] +[0x40,0x54,0x38,0xd5] +[0x60,0x54,0x38,0xd5] +[0x00,0x55,0x38,0xd5] +[0x20,0x55,0x38,0xd5] +[0x20,0xc1,0x38,0xd5] +[0x20,0xc1,0x3c,0xd5] +[0x60,0x52,0x3c,0xd5] + +# CHECK: mrs x0, ERRIDR_EL1 +# CHECK: mrs x0, ERXFR_EL1 +[0x00,0x53,0x38,0xd5] +[0x00,0x54,0x38,0xd5] Index: test/MC/Disassembler/ARM/ras-extension-arm.txt =================================================================== --- /dev/null +++ test/MC/Disassembler/ARM/ras-extension-arm.txt @@ -0,0 +1,6 @@ +# RUN: llvm-mc < %s -triple armv8a-none-eabi -mattr=+ras -disassemble | FileCheck %s --check-prefix=RAS +# RUN: llvm-mc < %s -triple armv8a-none-eabi -mattr=-ras -disassemble | FileCheck %s --check-prefix=NO-RAS + +[0x10,0xf0,0x20,0xe3] +# RAS: esb +# NO-RAS: hint #16 Index: test/MC/Disassembler/ARM/ras-extension-thumb.txt =================================================================== --- /dev/null +++ test/MC/Disassembler/ARM/ras-extension-thumb.txt @@ -0,0 +1,6 @@ +# RUN: llvm-mc < %s -triple thumbv8a-none-eabi -mattr=+ras -disassemble | FileCheck %s --check-prefix=RAS +# RUN: llvm-mc < %s -triple thumbv8a-none-eabi -mattr=-ras -disassemble | FileCheck %s --check-prefix=NO-RAS + +[0xaf,0xf3,0x10,0x80] +# RAS: esb +# NO-RAS: hint.w #16