Index: llvm/trunk/lib/Target/AArch64/AArch64.td =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64.td +++ llvm/trunk/lib/Target/AArch64/AArch64.td @@ -211,6 +211,9 @@ "Enable FRInt[32|64][Z|X] instructions that round a floating-point number to " "an integer (in FP format) forcing it to fit into a 32- or 64-bit int" >; +def FeatureSpecRestrict : SubtargetFeature<"specrestrict", "HasSpecRestrict", + "true", "Enable architectural speculation restriction" >; + def FeatureSpecCtrl : SubtargetFeature<"specctrl", "HasSpecCtrl", "true", "Enable speculation control barrier" >; @@ -241,8 +244,8 @@ def HasV8_5aOps : SubtargetFeature< "v8.5a", "HasV8_5aOps", "true", "Support ARM v8.5a instructions", - [HasV8_4aOps, FeatureAltFPCmp, FeatureFRInt3264, FeatureSpecCtrl, - FeaturePredCtrl, FeatureCacheDeepPersist] + [HasV8_4aOps, FeatureAltFPCmp, FeatureFRInt3264, FeatureSpecRestrict, + FeatureSpecCtrl, FeaturePredCtrl, FeatureCacheDeepPersist] >; //===----------------------------------------------------------------------===// Index: llvm/trunk/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp +++ llvm/trunk/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp @@ -2686,7 +2686,7 @@ unsigned Reg = PMapper->Encoding; uint64_t Immed = cast(N->getOperand(2))->getZExtValue(); unsigned State; - if (Reg == AArch64PState::PAN || Reg == AArch64PState::UAO) { + if (Reg == AArch64PState::PAN || Reg == AArch64PState::UAO || Reg == AArch64PState::SSBS) { assert(Immed < 2 && "Bad imm"); State = AArch64::MSRpstateImm1; } else { Index: llvm/trunk/lib/Target/AArch64/AArch64Subtarget.h =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64Subtarget.h +++ llvm/trunk/lib/Target/AArch64/AArch64Subtarget.h @@ -97,6 +97,7 @@ // Armv8.5-A Extensions bool HasAlternativeNZCV = false; bool HasFRInt3264 = false; + bool HasSpecRestrict = false; bool HasSpecCtrl = false; bool HasPredCtrl = false; bool HasCCDP = false; @@ -316,6 +317,7 @@ bool hasAggressiveFMA() const { return HasAggressiveFMA; } bool hasAlternativeNZCV() const { return HasAlternativeNZCV; } bool hasFRInt3264() const { return HasFRInt3264; } + bool hasSpecRestrict() { return HasSpecRestrict; } bool hasSpecCtrl() { return HasSpecCtrl; } bool hasPredCtrl() { return HasPredCtrl; } bool hasCCDP() { return HasCCDP; } Index: llvm/trunk/lib/Target/AArch64/AArch64SystemOperands.td =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64SystemOperands.td +++ llvm/trunk/lib/Target/AArch64/AArch64SystemOperands.td @@ -301,6 +301,9 @@ // v8.4a timining insensitivity of data processing instructions let Requires = [{ {AArch64::HasV8_4aOps} }] in def : PState<"DIT", 0b11010>; +// v8.5a Spectre Mitigation +let Requires = [{ {AArch64::FeatureSpecRestrict} }] in +def : PState<"SSBS", 0b11001>; //===----------------------------------------------------------------------===// // PSB instruction options. @@ -507,6 +510,9 @@ def : ROSysReg<"DCZID_EL0", 0b11, 0b011, 0b0000, 0b0000, 0b111>; def : ROSysReg<"ID_PFR0_EL1", 0b11, 0b000, 0b0000, 0b0001, 0b000>; def : ROSysReg<"ID_PFR1_EL1", 0b11, 0b000, 0b0000, 0b0001, 0b001>; +def : ROSysReg<"ID_PFR2_EL1", 0b11, 0b000, 0b0000, 0b0011, 0b100> { + let Requires = [{ {AArch64::FeatureSpecRestrict} }]; +} def : ROSysReg<"ID_DFR0_EL1", 0b11, 0b000, 0b0000, 0b0001, 0b010>; def : ROSysReg<"ID_AFR0_EL1", 0b11, 0b000, 0b0000, 0b0001, 0b011>; def : ROSysReg<"ID_MMFR0_EL1", 0b11, 0b000, 0b0000, 0b0001, 0b100>; @@ -621,6 +627,15 @@ def : ROSysReg<"RNDRRS", 0b11, 0b011, 0b0010, 0b0100, 0b001>; } +// v8.5a Software Context Number registers +let Requires = [{ {AArch64::FeatureSpecRestrict} }] in { +def : RWSysReg<"SCXTNUM_EL0", 0b11, 0b011, 0b1101, 0b0000, 0b111>; +def : RWSysReg<"SCXTNUM_EL1", 0b11, 0b000, 0b1101, 0b0000, 0b111>; +def : RWSysReg<"SCXTNUM_EL2", 0b11, 0b100, 0b1101, 0b0000, 0b111>; +def : RWSysReg<"SCXTNUM_EL3", 0b11, 0b110, 0b1101, 0b0000, 0b111>; +def : RWSysReg<"SCXTNUM_EL12", 0b11, 0b101, 0b1101, 0b0000, 0b111>; +} + //===---------------------- // Write-only regs //===---------------------- @@ -1353,6 +1368,11 @@ def : RWSysReg<"ZCR_EL12", 0b11, 0b101, 0b0001, 0b0010, 0b000>; } +// V8.5a Spectre mitigation SSBS register +// Op0 Op1 CRn CRm Op2 +let Requires = [{ {AArch64::FeatureSpecRestrict} }] in +def : RWSysReg<"SSBS", 0b11, 0b011, 0b0100, 0b0010, 0b110>; + // Cyclone specific system registers // Op0 Op1 CRn CRm Op2 let Requires = [{ {AArch64::ProcCyclone} }] in Index: llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp =================================================================== --- llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -998,7 +998,8 @@ if (!isSysReg()) return false; return (SysReg.PStateField == AArch64PState::PAN || SysReg.PStateField == AArch64PState::DIT || - SysReg.PStateField == AArch64PState::UAO); + SysReg.PStateField == AArch64PState::UAO || + SysReg.PStateField == AArch64PState::SSBS); } bool isSystemPStateFieldWithImm0_15() const { Index: llvm/trunk/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp =================================================================== --- llvm/trunk/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp +++ llvm/trunk/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp @@ -1721,7 +1721,8 @@ } if ((pstate_field == AArch64PState::PAN || - pstate_field == AArch64PState::UAO) && crm > 1) + pstate_field == AArch64PState::UAO || + pstate_field == AArch64PState::SSBS) && crm > 1) return Fail; Inst.addOperand(MCOperand::createImm(pstate_field)); Index: llvm/trunk/test/MC/AArch64/armv8.5a-specrestrict-error.s =================================================================== --- llvm/trunk/test/MC/AArch64/armv8.5a-specrestrict-error.s +++ llvm/trunk/test/MC/AArch64/armv8.5a-specrestrict-error.s @@ -0,0 +1,10 @@ +// RUN: not llvm-mc -triple aarch64 -show-encoding -mattr=+specrestrict < %s 2>&1 | FileCheck %s +// RUN: not llvm-mc -triple aarch64 -show-encoding -mattr=+v8.5a < %s 2>&1 | FileCheck %s +// RUN: not llvm-mc -triple aarch64 -show-encoding -mattr=-specrestrict < %s 2>&1 | FileCheck %s --check-prefix=NOSPECID + +msr SSBS, #2 + +// CHECK: error: immediate must be an integer in range [0, 1]. +// CHECK-NEXT: msr SSBS, #2 +// NOSPECID: error: expected writable system register or pstate +// NOSPECID-NEXT: msr {{ssbs|SSBS}}, #2 Index: llvm/trunk/test/MC/AArch64/armv8.5a-specrestrict.s =================================================================== --- llvm/trunk/test/MC/AArch64/armv8.5a-specrestrict.s +++ llvm/trunk/test/MC/AArch64/armv8.5a-specrestrict.s @@ -0,0 +1,69 @@ +// RUN: llvm-mc -triple aarch64 -show-encoding -mattr=+specrestrict < %s | FileCheck %s +// RUN: llvm-mc -triple aarch64 -show-encoding -mattr=+v8.5a < %s | FileCheck %s +// RUN: not llvm-mc -triple aarch64 -show-encoding -mattr=-specrestrict < %s 2>&1 | FileCheck %s --check-prefix=NOSPECID + +mrs x9, ID_PFR2_EL1 + +// CHECK: mrs x9, {{id_pfr2_el1|ID_PFR2_EL1}} // encoding: [0x89,0x03,0x38,0xd5] +// NOSPECID: error: expected readable system register +// NOSPECID-NEXT: mrs x9, ID_PFR2_EL1 + +mrs x8, SCXTNUM_EL0 +mrs x7, SCXTNUM_EL1 +mrs x6, SCXTNUM_EL2 +mrs x5, SCXTNUM_EL3 +mrs x4, SCXTNUM_EL12 + +// CHECK: mrs x8, {{scxtnum_el0|SCXTNUM_EL0}} // encoding: [0xe8,0xd0,0x3b,0xd5] +// CHECK: mrs x7, {{scxtnum_el1|SCXTNUM_EL1}} // encoding: [0xe7,0xd0,0x38,0xd5] +// CHECK: mrs x6, {{scxtnum_el2|SCXTNUM_EL2}} // encoding: [0xe6,0xd0,0x3c,0xd5] +// CHECK: mrs x5, {{scxtnum_el3|SCXTNUM_EL3}} // encoding: [0xe5,0xd0,0x3e,0xd5] +// CHECK: mrs x4, {{scxtnum_el12|SCXTNUM_EL12}} // encoding: [0xe4,0xd0,0x3d,0xd5] +// NOSPECID: error: expected readable system register +// NOSPECID-NEXT: mrs x8, {{scxtnum_el0|SCXTNUM_EL0}} +// NOSPECID: error: expected readable system register +// NOSPECID-NEXT: mrs x7, {{scxtnum_el1|SCXTNUM_EL1}} +// NOSPECID: error: expected readable system register +// NOSPECID-NEXT: mrs x6, {{scxtnum_el2|SCXTNUM_EL2}} +// NOSPECID: error: expected readable system register +// NOSPECID-NEXT: mrs x5, {{scxtnum_el3|SCXTNUM_EL3}} +// NOSPECID: error: expected readable system register +// NOSPECID-NEXT: mrs x4, {{scxtnum_el12|SCXTNUM_EL12}} + +msr SCXTNUM_EL0, x8 +msr SCXTNUM_EL1, x7 +msr SCXTNUM_EL2, x6 +msr SCXTNUM_EL3, x5 +msr SCXTNUM_EL12, x4 + +// CHECK: msr {{scxtnum_el0|SCXTNUM_EL0}}, x8 // encoding: [0xe8,0xd0,0x1b,0xd5] +// CHECK: msr {{scxtnum_el1|SCXTNUM_EL1}}, x7 // encoding: [0xe7,0xd0,0x18,0xd5] +// CHECK: msr {{scxtnum_el2|SCXTNUM_EL2}}, x6 // encoding: [0xe6,0xd0,0x1c,0xd5] +// CHECK: msr {{scxtnum_el3|SCXTNUM_EL3}}, x5 // encoding: [0xe5,0xd0,0x1e,0xd5] +// CHECK: msr {{scxtnum_el12|SCXTNUM_EL12}}, x4 // encoding: [0xe4,0xd0,0x1d,0xd5] +// NOSPECID: error: expected writable system register +// NOSPECID-NEXT: {{scxtnum_el0|SCXTNUM_EL0}} +// NOSPECID: error: expected writable system register +// NOSPECID-NEXT: {{scxtnum_el1|SCXTNUM_EL1}} +// NOSPECID: error: expected writable system register +// NOSPECID-NEXT: {{scxtnum_el2|SCXTNUM_EL2}} +// NOSPECID: error: expected writable system register +// NOSPECID-NEXT: {{scxtnum_el3|SCXTNUM_EL3}} +// NOSPECID: error: expected writable system register +// NOSPECID-NEXT: {{scxtnum_el12|SCXTNUM_EL12}} + +mrs x2, SSBS + +// CHECK: mrs x2, {{ssbs|SSBS}} // encoding: [0xc2,0x42,0x3b,0xd5] +// NOSPECID: error: expected readable system register +// NOSPECID-NEXT: mrs x2, {{ssbs|SSBS}} + +msr SSBS, x3 +msr SSBS, #1 + +// CHECK: msr {{ssbs|SSBS}}, x3 // encoding: [0xc3,0x42,0x1b,0xd5] +// CHECK: msr {{ssbs|SSBS}}, #1 // encoding: [0x3f,0x41,0x03,0xd5] +// NOSPECID: error: expected writable system register or pstate +// NOSPECID-NEXT: msr {{ssbs|SSBS}}, x3 +// NOSPECID: error: expected writable system register or pstate +// NOSPECID-NEXT: msr {{ssbs|SSBS}}, #1 Index: llvm/trunk/test/MC/Disassembler/AArch64/armv8.5a-specrestrict.txt =================================================================== --- llvm/trunk/test/MC/Disassembler/AArch64/armv8.5a-specrestrict.txt +++ llvm/trunk/test/MC/Disassembler/AArch64/armv8.5a-specrestrict.txt @@ -0,0 +1,52 @@ +# RUN: llvm-mc -triple=aarch64 -mattr=+specrestrict -disassemble < %s | FileCheck %s +# RUN: llvm-mc -triple=aarch64 -mattr=+v8.5a -disassemble < %s | FileCheck %s +# RUN: llvm-mc -triple=aarch64 -mattr=-specrestrict -disassemble < %s | FileCheck %s --check-prefix=NOSPECID + +[0x81 0x03 0x38 0xd5] + +# CHECK: mrs x1, {{id_pfr2_el1|ID_PFR2_EL1}} +# NOSPECID: mrs x1, S3_0_C0_C3_4 + +[0xe8 0xd0 0x3b 0xd5] +[0xe7 0xd0 0x38 0xd5] +[0xe6 0xd0 0x3c 0xd5] +[0xe5 0xd0 0x3e 0xd5] +[0xe4 0xd0 0x3d 0xd5] + +# CHECK: mrs x8, {{scxtnum_el0|SCXTNUM_EL0}} +# CHECK: mrs x7, {{scxtnum_el1|SCXTNUM_EL1}} +# CHECK: mrs x6, {{scxtnum_el2|SCXTNUM_EL2}} +# CHECK: mrs x5, {{scxtnum_el3|SCXTNUM_EL3}} +# CHECK: mrs x4, {{scxtnum_el12|SCXTNUM_EL12}} +# NOSPECID: mrs x8, S3_3_C13_C0_7 +# NOSPECID: mrs x7, S3_0_C13_C0_7 +# NOSPECID: mrs x6, S3_4_C13_C0_7 +# NOSPECID: mrs x5, S3_6_C13_C0_7 +# NOSPECID: mrs x4, S3_5_C13_C0_7 + +[0xe8 0xd0 0x1b 0xd5] +[0xe7 0xd0 0x18 0xd5] +[0xe6 0xd0 0x1c 0xd5] +[0xe5 0xd0 0x1e 0xd5] +[0xe4 0xd0 0x1d 0xd5] + +# CHECK: msr {{scxtnum_el0|SCXTNUM_EL0}}, x8 +# CHECK: msr {{scxtnum_el1|SCXTNUM_EL1}}, x7 +# CHECK: msr {{scxtnum_el2|SCXTNUM_EL2}}, x6 +# CHECK: msr {{scxtnum_el3|SCXTNUM_EL3}}, x5 +# CHECK: msr {{scxtnum_el12|SCXTNUM_EL12}}, x4 +# NOSPECID: msr S3_3_C13_C0_7, x8 +# NOSPECID: msr S3_0_C13_C0_7, x7 +# NOSPECID: msr S3_4_C13_C0_7, x6 +# NOSPECID: msr S3_6_C13_C0_7, x5 +# NOSPECID: msr S3_5_C13_C0_7, x4 + +[0x3f 0x41 0x03 0xd5] +[0xc3 0x42 0x1b 0xd5] +[0xc2 0x42 0x3b 0xd5] +# CHECK: msr SSBS, #1 +# CHECK: msr SSBS, x3 +# CHECK: mrs x2, SSBS +# NOSPECID: msr S0_3_C4_C1_1, xzr +# NOSPECID: msr S3_3_C4_C2_6, x3 +# NOSPECID: mrs x2, S3_3_C4_C2_6