diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 6d315e9f84ddf..52d5b9a3f66d1 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -551,6 +551,9 @@ X86 Support - Added option ``-m[no-]evex512`` to disable ZMM and 64-bit mask instructions for AVX512 features. +- Support ISA of ``USER_MSR``. + * Support intrinsic of ``_urdmsr``. + * Support intrinsic of ``_uwrmsr``. Arm and AArch64 Support ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Basic/BuiltinsX86_64.def b/clang/include/clang/Basic/BuiltinsX86_64.def index e5c1fe8b31921..5e00916d4b25a 100644 --- a/clang/include/clang/Basic/BuiltinsX86_64.def +++ b/clang/include/clang/Basic/BuiltinsX86_64.def @@ -104,6 +104,9 @@ TARGET_BUILTIN(__builtin_ia32_clui, "v", "n", "uintr") TARGET_BUILTIN(__builtin_ia32_stui, "v", "n", "uintr") TARGET_BUILTIN(__builtin_ia32_testui, "Uc", "n", "uintr") TARGET_BUILTIN(__builtin_ia32_senduipi, "vUWi", "n", "uintr") +// USERMSR +TARGET_BUILTIN(__builtin_ia32_urdmsr, "ULLiULLi", "n", "usermsr") +TARGET_BUILTIN(__builtin_ia32_uwrmsr, "vULLiULLi", "n", "usermsr") // AMX internal builtin TARGET_BUILTIN(__builtin_ia32_tile_loadconfig_internal, "vvC*", "n", "amx-tile") diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 54afd652ad3d0..640044622fc09 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -5904,6 +5904,8 @@ def mtsxldtrk : Flag<["-"], "mtsxldtrk">, Group; def mno_tsxldtrk : Flag<["-"], "mno-tsxldtrk">, Group; def muintr : Flag<["-"], "muintr">, Group; def mno_uintr : Flag<["-"], "mno-uintr">, Group; +def musermsr : Flag<["-"], "musermsr">, Group; +def mno_usermsr : Flag<["-"], "mno-usermsr">, Group; def mvaes : Flag<["-"], "mvaes">, Group; def mno_vaes : Flag<["-"], "mno-vaes">, Group; def mvpclmulqdq : Flag<["-"], "mvpclmulqdq">, Group; diff --git a/clang/lib/Basic/Targets/X86.cpp b/clang/lib/Basic/Targets/X86.cpp index 022d5753135e1..bea5c52a7b8d7 100644 --- a/clang/lib/Basic/Targets/X86.cpp +++ b/clang/lib/Basic/Targets/X86.cpp @@ -376,6 +376,8 @@ bool X86TargetInfo::handleTargetFeatures(std::vector &Features, HasTSXLDTRK = true; } else if (Feature == "+uintr") { HasUINTR = true; + } else if (Feature == "+usermsr") { + HasUSERMSR = true; } else if (Feature == "+crc32") { HasCRC32 = true; } else if (Feature == "+x87") { @@ -869,6 +871,8 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__TSXLDTRK__"); if (HasUINTR) Builder.defineMacro("__UINTR__"); + if (HasUSERMSR) + Builder.defineMacro("__USERMSR__"); if (HasCRC32) Builder.defineMacro("__CRC32__"); @@ -1053,6 +1057,7 @@ bool X86TargetInfo::isValidFeatureName(StringRef Name) const { .Case("tbm", true) .Case("tsxldtrk", true) .Case("uintr", true) + .Case("usermsr", true) .Case("vaes", true) .Case("vpclmulqdq", true) .Case("wbnoinvd", true) @@ -1162,6 +1167,7 @@ bool X86TargetInfo::hasFeature(StringRef Feature) const { .Case("tbm", HasTBM) .Case("tsxldtrk", HasTSXLDTRK) .Case("uintr", HasUINTR) + .Case("usermsr", HasUSERMSR) .Case("vaes", HasVAES) .Case("vpclmulqdq", HasVPCLMULQDQ) .Case("wbnoinvd", HasWBNOINVD) diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h index 4fdc94de1e0cb..298db55c67442 100644 --- a/clang/lib/Basic/Targets/X86.h +++ b/clang/lib/Basic/Targets/X86.h @@ -162,6 +162,7 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo { bool HasAMXCOMPLEX = false; bool HasSERIALIZE = false; bool HasTSXLDTRK = false; + bool HasUSERMSR = false; bool HasUINTR = false; bool HasCRC32 = false; bool HasX87 = false; diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt index 8deea823e3966..3b6fec3da2b16 100644 --- a/clang/lib/Headers/CMakeLists.txt +++ b/clang/lib/Headers/CMakeLists.txt @@ -224,6 +224,7 @@ set(x86_files tmmintrin.h tsxldtrkintrin.h uintrintrin.h + usermsrintrin.h vaesintrin.h vpclmulqdqintrin.h waitpkgintrin.h diff --git a/clang/lib/Headers/usermsrintrin.h b/clang/lib/Headers/usermsrintrin.h new file mode 100644 index 0000000000000..6d1424ad3b2ed --- /dev/null +++ b/clang/lib/Headers/usermsrintrin.h @@ -0,0 +1,30 @@ +/*===--------------- usermsrintrin.h - USERMSR intrinsics -----------------=== + * + * 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 + * + *===-----------------------------------------------------------------------=== + */ +#ifndef __X86GPRINTRIN_H +#error "Never use directly; include instead." +#endif // __X86GPRINTRIN_H + +#ifndef __USERMSRINTRIN_H +#define __USERMSRINTRIN_H +#ifdef __x86_64__ + +static __inline__ unsigned long long + __attribute__((__always_inline__, __nodebug__, __target__("usermsr"))) + _urdmsr(unsigned long long __A) { + return __builtin_ia32_urdmsr(__A); +} + +static __inline__ void + __attribute__((__always_inline__, __nodebug__, __target__("usermsr"))) + _uwrmsr(unsigned long long __A, unsigned long long __B) { + return __builtin_ia32_uwrmsr(__A, __B); +} + +#endif // __x86_64__ +#endif // __USERMSRINTRIN_H diff --git a/clang/lib/Headers/x86gprintrin.h b/clang/lib/Headers/x86gprintrin.h index f9a765be43221..ed141879fbc74 100644 --- a/clang/lib/Headers/x86gprintrin.h +++ b/clang/lib/Headers/x86gprintrin.h @@ -20,6 +20,11 @@ #include #endif +#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ + defined(__USERMSR__) +#include +#endif + #if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ defined(__CRC32__) #include diff --git a/clang/test/CodeGen/X86/usermsr-builtins-error-32.c b/clang/test/CodeGen/X86/usermsr-builtins-error-32.c new file mode 100644 index 0000000000000..180b99a4212a1 --- /dev/null +++ b/clang/test/CodeGen/X86/usermsr-builtins-error-32.c @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 %s -ffreestanding -triple=i386-unknown-unknown -target-feature +usermsr \ +// RUN: -emit-llvm -fsyntax-only -verify + +#include + +unsigned long long test_urdmsr(unsigned long long __A) { + return _urdmsr(__A); // expected-error {{call to undeclared function '_urdmsr'}} +} + +void test_uwrmsr(unsigned long long __A, unsigned long long __B) { + // CHECK-LABEL: @test_uwrmsr( + // CHECK: call void @llvm.x86.uwrmsr( + _uwrmsr(__A, __B); // expected-error {{call to undeclared function '_uwrmsr'}} +} diff --git a/clang/test/CodeGen/X86/usermsr-builtins.c b/clang/test/CodeGen/X86/usermsr-builtins.c new file mode 100644 index 0000000000000..0d58bc98c204c --- /dev/null +++ b/clang/test/CodeGen/X86/usermsr-builtins.c @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 %s -ffreestanding -triple=x86_64-unknown-unknown -target-feature +usermsr \ +// RUN: -emit-llvm -o - -Wall -Werror -pedantic -Wno-gnu-statement-expression | FileCheck %s + +#include + +unsigned long long test_urdmsr(unsigned long long __A) { + // CHECK-LABEL: @test_urdmsr( + // CHECK: call i64 @llvm.x86.urdmsr( + return _urdmsr(__A); +} + +unsigned long long test_urdmsr_const(unsigned long long __A) { + // CHECK-LABEL: @test_urdmsr_const( + // CHECK: call i64 @llvm.x86.urdmsr( + return _urdmsr(123u); +} + +void test_uwrmsr(unsigned long long __A, unsigned long long __B) { + // CHECK-LABEL: @test_uwrmsr( + // CHECK: call void @llvm.x86.uwrmsr( + _uwrmsr(__A, __B); +} + +void test_uwrmsr_const(unsigned long long __A, unsigned long long __B) { + // CHECK-LABEL: @test_uwrmsr_const( + // CHECK: call void @llvm.x86.uwrmsr( + _uwrmsr(123u, __B); +} + diff --git a/clang/test/Driver/x86-target-features.c b/clang/test/Driver/x86-target-features.c index a6ecedbb8a58e..464dcda504bbd 100644 --- a/clang/test/Driver/x86-target-features.c +++ b/clang/test/Driver/x86-target-features.c @@ -374,6 +374,11 @@ // EVEX512: "-target-feature" "+evex512" // NO-EVEX512: "-target-feature" "-evex512" +// RUN: %clang --target=i386 -musermsr %s -### -o %t.o 2>&1 | FileCheck -check-prefix=USERMSR %s +// RUN: %clang --target=i386 -mno-usermsr %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-USERMSR %s +// USERMSR: "-target-feature" "+usermsr" +// NO-USERMSR: "-target-feature" "-usermsr" + // RUN: %clang --target=i386 -march=i386 -mcrc32 %s -### 2>&1 | FileCheck -check-prefix=CRC32 %s // RUN: %clang --target=i386 -march=i386 -mno-crc32 %s -### 2>&1 | FileCheck -check-prefix=NO-CRC32 %s // CRC32: "-target-feature" "+crc32" diff --git a/clang/test/Preprocessor/x86_target_features.c b/clang/test/Preprocessor/x86_target_features.c index 36d4af59d4c66..873416d79b125 100644 --- a/clang/test/Preprocessor/x86_target_features.c +++ b/clang/test/Preprocessor/x86_target_features.c @@ -750,6 +750,12 @@ // AVXVNNIINT16NOAVX2-NOT: #define __AVX2__ 1 // AVXVNNIINT16NOAVX2-NOT: #define __AVXVNNIINT16__ 1 +// RUN: %clang -target i686-unknown-linux-gnu -march=atom -musermsr -x c -E -dM -o - %s | FileCheck -check-prefix=USERMSR %s +// USERMSR: #define __USERMSR__ 1 + +// RUN: %clang -target i686-unknown-linux-gnu -march=atom -mno-usermsr -x c -E -dM -o - %s | FileCheck -check-prefix=NO-USERMSR %s +// NO-USERMSR-NOT: #define __USERMSR__ 1 + // RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mcrc32 -x c -E -dM -o - %s | FileCheck -check-prefix=CRC32 %s // CRC32: #define __CRC32__ 1 diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index 467b4b5320ad9..94b43800c17bd 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -133,6 +133,7 @@ Changes to the X86 Backend benefits external projects such as Rust which aim to be binary compatible with C, but also fixes code generation where LLVM already assumed that the type matched and called into libgcc helper functions. +* Support ISA of ``USER_MSR``. Changes to the OCaml bindings ----------------------------- diff --git a/llvm/include/llvm/IR/IntrinsicsX86.td b/llvm/include/llvm/IR/IntrinsicsX86.td index 57cd1dc47bd9f..fdc2b0fb7f80f 100644 --- a/llvm/include/llvm/IR/IntrinsicsX86.td +++ b/llvm/include/llvm/IR/IntrinsicsX86.td @@ -5673,8 +5673,16 @@ let TargetPrefix = "x86" in { Intrinsic<[], [llvm_i64_ty], []>; } +let TargetPrefix = "x86" in { +def int_x86_urdmsr : ClangBuiltin<"__builtin_ia32_urdmsr">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty], + [IntrInaccessibleMemOnly]>; +def int_x86_uwrmsr : ClangBuiltin<"__builtin_ia32_uwrmsr">, + Intrinsic<[], [llvm_i64_ty, llvm_i64_ty], + [IntrInaccessibleMemOnly]>; +} + //===----------------------------------------------------------------------===// -// avx512_fp16: vaddph let TargetPrefix = "x86" in { def int_x86_avx512fp16_add_ph_512 : ClangBuiltin<"__builtin_ia32_addph512">, diff --git a/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h b/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h index 169b8e97986e1..6e08fc6a0ccb6 100644 --- a/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h +++ b/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h @@ -33,6 +33,7 @@ namespace X86Disassembler { #define THREEDNOW_MAP_SYM x86Disassembler3DNowOpcodes #define MAP5_SYM x86DisassemblerMap5Opcodes #define MAP6_SYM x86DisassemblerMap6Opcodes +#define MAP7_SYM x86DisassemblerMap7Opcodes #define INSTRUCTIONS_STR "x86DisassemblerInstrSpecifiers" #define CONTEXTS_STR "x86DisassemblerContexts" @@ -46,6 +47,7 @@ namespace X86Disassembler { #define THREEDNOW_MAP_STR "x86Disassembler3DNowOpcodes" #define MAP5_STR "x86DisassemblerMap5Opcodes" #define MAP6_STR "x86DisassemblerMap6Opcodes" +#define MAP7_STR "x86DisassemblerMap7Opcodes" // Attributes of an instruction that must be known before the opcode can be // processed correctly. Most of these indicate the presence of particular @@ -296,7 +298,8 @@ enum OpcodeType { XOPA_MAP = 6, THREEDNOW_MAP = 7, MAP5 = 8, - MAP6 = 9 + MAP6 = 9, + MAP7 = 10 }; // The following structs are used for the hierarchical decode table. After diff --git a/llvm/include/llvm/TargetParser/X86TargetParser.def b/llvm/include/llvm/TargetParser/X86TargetParser.def index 85ff6996d335a..709ff8603b042 100644 --- a/llvm/include/llvm/TargetParser/X86TargetParser.def +++ b/llvm/include/llvm/TargetParser/X86TargetParser.def @@ -241,6 +241,7 @@ X86_FEATURE (SM3, "sm3") X86_FEATURE (SM4, "sm4") X86_FEATURE (AVXVNNIINT16, "avxvnniint16") X86_FEATURE (EVEX512, "evex512") +X86_FEATURE (USERMSR, "usermsr") // These features aren't really CPU features, but the frontend can set them. X86_FEATURE (RETPOLINE_EXTERNAL_THUNK, "retpoline-external-thunk") X86_FEATURE (RETPOLINE_INDIRECT_BRANCHES, "retpoline-indirect-branches") diff --git a/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp b/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp index 967c7574355db..2ec7a57093f4b 100644 --- a/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp +++ b/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp @@ -156,6 +156,9 @@ static InstrUID decode(OpcodeType type, InstructionContext insnContext, case MAP6: dec = &MAP6_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode]; break; + case MAP7: + dec = &MAP7_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode]; + break; } switch (dec->modrm_type) { @@ -918,6 +921,9 @@ static bool readOpcode(struct InternalInstruction *insn) { case VEX_LOB_MAP6: insn->opcodeType = MAP6; return consume(insn, insn->opcode); + case VEX_LOB_MAP7: + insn->opcodeType = MAP7; + return consume(insn, insn->opcode); } } else if (insn->vectorExtensionType == TYPE_VEX_2B) { insn->opcodeType = TWOBYTE; @@ -1059,6 +1065,9 @@ static int getInstructionIDWithAttrMask(uint16_t *instructionID, case MAP6: decision = &MAP6_SYM; break; + case MAP7: + decision = &MAP7_SYM; + break; } if (decision->opcodeDecisions[insnCtx] diff --git a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h index 95d3c8ede366f..2d728143d3c9a 100644 --- a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h +++ b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h @@ -484,7 +484,8 @@ enum VEXLeadingOpcodeByte { VEX_LOB_0F38 = 0x2, VEX_LOB_0F3A = 0x3, VEX_LOB_MAP5 = 0x5, - VEX_LOB_MAP6 = 0x6 + VEX_LOB_MAP6 = 0x6, + VEX_LOB_MAP7 = 0x7 }; enum XOPMapSelect { diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h b/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h index e2293fe30561f..1e5a3606f33a6 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h +++ b/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h @@ -829,9 +829,10 @@ namespace X86II { /// this flag to indicate that the encoder should do the wacky 3DNow! thing. ThreeDNow = 7 << OpMapShift, - // MAP5, MAP6 - Prefix after the 0x0F prefix. + // MAP5, MAP6, MAP7 - Prefix after the 0x0F prefix. T_MAP5 = 8 << OpMapShift, T_MAP6 = 9 << OpMapShift, + T_MAP7 = 10 << OpMapShift, //===------------------------------------------------------------------===// // REX_W - REX prefixes are instruction prefixes used in 64-bit mode. diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp index 59a04f3167d86..b85404be3063d 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp @@ -89,6 +89,7 @@ class X86OpcodePrefixHelper { // 0b00100: Reserved for future use // 0b00101: VEX MAP5 // 0b00110: VEX MAP6 + // 0b00111: VEX MAP7 // 0b00111-0b11111: Reserved for future use // 0b01000: XOP map select - 08h instructions with imm byte // 0b01001: XOP map select - 09h instructions with no imm byte @@ -917,6 +918,9 @@ X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI, case X86II::T_MAP6: Prefix.set5M(0x6); break; + case X86II::T_MAP7: + Prefix.set5M(0x7); + break; } Prefix.setL(TSFlags & X86II::VEX_L); diff --git a/llvm/lib/Target/X86/X86.td b/llvm/lib/Target/X86/X86.td index 64f91ae90e2b0..f3f8d5718dfc2 100644 --- a/llvm/lib/Target/X86/X86.td +++ b/llvm/lib/Target/X86/X86.td @@ -325,6 +325,8 @@ def FeatureTSXLDTRK : SubtargetFeature<"tsxldtrk", "HasTSXLDTRK", "true", "Support TSXLDTRK instructions">; def FeatureUINTR : SubtargetFeature<"uintr", "HasUINTR", "true", "Has UINTR Instructions">; +def FeatureUSERMSR : SubtargetFeature<"usermsr", "HasUSERMSR", "true", + "Support USERMSR instructions">; def FeaturePCONFIG : SubtargetFeature<"pconfig", "HasPCONFIG", "true", "platform configuration instruction">; def FeatureMOVDIRI : SubtargetFeature<"movdiri", "HasMOVDIRI", "true", diff --git a/llvm/lib/Target/X86/X86InstrFormats.td b/llvm/lib/Target/X86/X86InstrFormats.td index f45869e15267c..70ffd4175e1f1 100644 --- a/llvm/lib/Target/X86/X86InstrFormats.td +++ b/llvm/lib/Target/X86/X86InstrFormats.td @@ -163,6 +163,7 @@ def XOPA : Map<6>; def ThreeDNow : Map<7>; def T_MAP5 : Map<8>; def T_MAP6 : Map<9>; +def T_MAP7 : Map<10>; // Class specifying the encoding class Encoding val> { @@ -217,6 +218,9 @@ class T_MAP6PS : T_MAP6 { Prefix OpPrefix = PS; } class T_MAP6PD : T_MAP6 { Prefix OpPrefix = PD; } class T_MAP6XS : T_MAP6 { Prefix OpPrefix = XS; } class T_MAP6XD : T_MAP6 { Prefix OpPrefix = XD; } +class T_MAP7 { Map OpMap = T_MAP7; } +class T_MAP7XS : T_MAP7 { Prefix OpPrefix = XS; } // 0xF3 +class T_MAP7XD : T_MAP7 { Prefix OpPrefix = XD; } // 0xF2 class OBXS { Prefix OpPrefix = XS; } class PS : TB { Prefix OpPrefix = PS; } class PD : TB { Prefix OpPrefix = PD; } diff --git a/llvm/lib/Target/X86/X86InstrInfo.td b/llvm/lib/Target/X86/X86InstrInfo.td index a20fa6a0c3b6c..cb740bc99f788 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.td +++ b/llvm/lib/Target/X86/X86InstrInfo.td @@ -1017,6 +1017,7 @@ def HasAMXBF16 : Predicate<"Subtarget->hasAMXBF16()">; def HasAMXINT8 : Predicate<"Subtarget->hasAMXINT8()">; def HasAMXCOMPLEX : Predicate<"Subtarget->hasAMXCOMPLEX()">; def HasUINTR : Predicate<"Subtarget->hasUINTR()">; +def HasUSERMSR : Predicate<"Subtarget->hasUSERMSR()">; def HasCRC32 : Predicate<"Subtarget->hasCRC32()">; def HasX86_64 : Predicate<"Subtarget->hasX86_64()">; diff --git a/llvm/lib/Target/X86/X86InstrSystem.td b/llvm/lib/Target/X86/X86InstrSystem.td index 0272f7de0f9e4..b55956169ff2c 100644 --- a/llvm/lib/Target/X86/X86InstrSystem.td +++ b/llvm/lib/Target/X86/X86InstrSystem.td @@ -436,6 +436,22 @@ def WRMSRLIST : I<0x01, MRM_C6, (outs), (ins), "wrmsrlist", []>, XS; def RDMSRLIST : I<0x01, MRM_C6, (outs), (ins), "rdmsrlist", []>, XD; } +let Predicates = [HasUSERMSR], mayLoad = 1 in { + def URDMSRrr : I<0xf8, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), + "urdmsr\t{$src, $dst|$dst, $src}", + [(set GR64:$dst, (int_x86_urdmsr GR64:$src))]>, T8XD; + def URDMSRri : Ii32<0xf8, MRM0r, (outs GR64:$dst), (ins i64i32imm:$imm), + "urdmsr\t{$imm, $dst|$dst, $imm}", + [(set GR64:$dst, (int_x86_urdmsr i64immSExt32_su:$imm))]>, T_MAP7XD, VEX; +} +let Predicates = [HasUSERMSR], mayStore = 1 in { + def UWRMSRrr : I<0xf8, MRMSrcReg, (outs), (ins GR64:$src1, GR64:$src2), + "uwrmsr\t{$src1, $src2|$src2, $src1}", + [(int_x86_uwrmsr GR64:$src1, GR64:$src2)]>, T8XS; + def UWRMSRir : Ii32<0xf8, MRM0r, (outs), (ins GR64:$src, i64i32imm:$imm), + "uwrmsr\t{$src, $imm|$imm, $src}", + [(int_x86_uwrmsr GR64:$src, i64immSExt32_su:$imm)]>, T_MAP7XS, VEX; +} let Defs = [RAX, RDX], Uses = [ECX] in def RDPMC : I<0x33, RawFrm, (outs), (ins), "rdpmc", []>, TB; diff --git a/llvm/lib/TargetParser/Host.cpp b/llvm/lib/TargetParser/Host.cpp index 436a5eb04c8d3..b320911d3ce27 100644 --- a/llvm/lib/TargetParser/Host.cpp +++ b/llvm/lib/TargetParser/Host.cpp @@ -1796,6 +1796,7 @@ bool sys::getHostCPUFeatures(StringMap &Features) { Features["amx-complex"] = HasLeaf7Subleaf1 && ((EDX >> 8) & 1) && HasAMXSave; Features["avxvnniint16"] = HasLeaf7Subleaf1 && ((EDX >> 10) & 1) && HasAVXSave; Features["prefetchi"] = HasLeaf7Subleaf1 && ((EDX >> 14) & 1); + Features["usermsr"] = HasLeaf7Subleaf1 && ((EDX >> 15) & 1); bool HasLeafD = MaxLevel >= 0xd && !getX86CpuIDAndInfoEx(0xd, 0x1, &EAX, &EBX, &ECX, &EDX); diff --git a/llvm/lib/TargetParser/X86TargetParser.cpp b/llvm/lib/TargetParser/X86TargetParser.cpp index b9908dd2629ff..94849f915daa1 100644 --- a/llvm/lib/TargetParser/X86TargetParser.cpp +++ b/llvm/lib/TargetParser/X86TargetParser.cpp @@ -509,6 +509,7 @@ constexpr FeatureBitset ImpliedFeaturesSHSTK = {}; constexpr FeatureBitset ImpliedFeaturesTBM = {}; constexpr FeatureBitset ImpliedFeaturesTSXLDTRK = {}; constexpr FeatureBitset ImpliedFeaturesUINTR = {}; +constexpr FeatureBitset ImpliedFeaturesUSERMSR = {}; constexpr FeatureBitset ImpliedFeaturesWAITPKG = {}; constexpr FeatureBitset ImpliedFeaturesWBNOINVD = {}; constexpr FeatureBitset ImpliedFeaturesVZEROUPPER = {}; diff --git a/llvm/test/CodeGen/X86/usermsr-intrinsics.ll b/llvm/test/CodeGen/X86/usermsr-intrinsics.ll new file mode 100644 index 0000000000000..29801a494f498 --- /dev/null +++ b/llvm/test/CodeGen/X86/usermsr-intrinsics.ll @@ -0,0 +1,64 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 +; RUN: llc < %s -verify-machineinstrs -mtriple=x86_64-unknown-unknown --show-mc-encoding -mattr=+usermsr | FileCheck %s --check-prefixes=X64 + +define i64 @test_int_x86_urdmsr(i64 %A) nounwind { +; X64-LABEL: test_int_x86_urdmsr: +; X64: # %bb.0: +; X64-NEXT: urdmsr %rdi, %rax # encoding: [0xf2,0x0f,0x38,0xf8,0xc7] +; X64-NEXT: retq # encoding: [0xc3] + %ret = call i64 @llvm.x86.urdmsr(i64 %A) + ret i64 %ret +} + +define i64 @test_int_x86_urdmsr_const() nounwind { +; X64-LABEL: test_int_x86_urdmsr_const: +; X64: # %bb.0: +; X64-NEXT: urdmsr $123, %rax # encoding: [0xc4,0xe7,0x7b,0xf8,0xc0,0x7b,0x00,0x00,0x00] +; X64-NEXT: retq # encoding: [0xc3] + %ret = call i64 @llvm.x86.urdmsr(i64 123) + ret i64 %ret +} + +define i64 @test_int_x86_urdmsr_const_i64() nounwind { +; X64-LABEL: test_int_x86_urdmsr_const_i64: +; X64: # %bb.0: +; X64-NEXT: movabsq $8589934591, %rax # encoding: [0x48,0xb8,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00] +; X64-NEXT: # imm = 0x1FFFFFFFF +; X64-NEXT: urdmsr %rax, %rax # encoding: [0xf2,0x0f,0x38,0xf8,0xc0] +; X64-NEXT: retq # encoding: [0xc3] + %ret = call i64 @llvm.x86.urdmsr(i64 8589934591) + ret i64 %ret +} + +declare i64 @llvm.x86.urdmsr(i64 %A) + +define void @test_int_x86_uwrmsr(i64 %A, i64 %B) nounwind { +; X64-LABEL: test_int_x86_uwrmsr: +; X64: # %bb.0: +; X64-NEXT: uwrmsr %rdi, %rsi # encoding: [0xf3,0x0f,0x38,0xf8,0xfe] +; X64-NEXT: retq # encoding: [0xc3] + call void @llvm.x86.uwrmsr(i64 %A, i64 %B) + ret void +} + +define void @test_int_x86_uwrmsr_const(i64 %A) nounwind { +; X64-LABEL: test_int_x86_uwrmsr_const: +; X64: # %bb.0: +; X64-NEXT: uwrmsr %rdi, $123 # encoding: [0xc4,0xe7,0x7a,0xf8,0xc7,0x7b,0x00,0x00,0x00] +; X64-NEXT: retq # encoding: [0xc3] + call void @llvm.x86.uwrmsr(i64 %A, i64 123) + ret void +} + +define void @test_int_x86_uwrmsr_const_i64(i64 %A) nounwind { +; X64-LABEL: test_int_x86_uwrmsr_const_i64: +; X64: # %bb.0: +; X64-NEXT: movabsq $8589934591, %rax # encoding: [0x48,0xb8,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00] +; X64-NEXT: # imm = 0x1FFFFFFFF +; X64-NEXT: uwrmsr %rdi, %rax # encoding: [0xf3,0x0f,0x38,0xf8,0xf8] +; X64-NEXT: retq # encoding: [0xc3] + call void @llvm.x86.uwrmsr(i64 %A, i64 8589934591) + ret void +} + +declare void @llvm.x86.uwrmsr(i64 %A, i64 %B) diff --git a/llvm/test/MC/Disassembler/X86/usermsr-64.txt b/llvm/test/MC/Disassembler/X86/usermsr-64.txt new file mode 100644 index 0000000000000..592a1a204f5c6 --- /dev/null +++ b/llvm/test/MC/Disassembler/X86/usermsr-64.txt @@ -0,0 +1,28 @@ +# RUN: llvm-mc --disassemble %s -triple=x86_64 | FileCheck %s --check-prefixes=ATT +# RUN: llvm-mc --disassemble %s -triple=x86_64 --output-asm-variant=1 | FileCheck %s --check-prefixes=INTEL + +# ATT: urdmsr $123, %r9 +# INTEL: urdmsr r9, 123 +0xc4,0xc7,0x7b,0xf8,0xc1,0x7b,0x00,0x00,0x00 + +# ATT: urdmsr %r9, %r9 +# INTEL: urdmsr r9, r9 +0xf2,0x45,0x0f,0x38,0xf8,0xc9 + +# Test if WIG is supported for this instruction/form. +# ATT: urdmsr %r9, %r9 +# INTEL: urdmsr r9, r9 +0xf2,0x4d,0x0f,0x38,0xf8,0xc9 + +# ATT: uwrmsr %r9, $123 +# INTEL: uwrmsr 123, r9 +0xc4,0xc7,0x7a,0xf8,0xc1,0x7b,0x00,0x00,0x00 + +# ATT: uwrmsr %r9, %r9 +# INTEL: uwrmsr r9, r9 +0xf3,0x45,0x0f,0x38,0xf8,0xc9 + +# Test if WIG is supported for this instruction/form. +# ATT: uwrmsr %r9, %r9 +# INTEL: uwrmsr r9, r9 +0xf3,0x4d,0x0f,0x38,0xf8,0xc9 diff --git a/llvm/test/MC/X86/usermsr-64-att.s b/llvm/test/MC/X86/usermsr-64-att.s new file mode 100644 index 0000000000000..e89d0a800ab0b --- /dev/null +++ b/llvm/test/MC/X86/usermsr-64-att.s @@ -0,0 +1,18 @@ +// RUN: llvm-mc -triple x86_64 --show-encoding %s | FileCheck %s + +// CHECK: urdmsr $123, %r9 +// CHECK: encoding: [0xc4,0xc7,0x7b,0xf8,0xc1,0x7b,0x00,0x00,0x00] + urdmsr $123, %r9 + +// CHECK: urdmsr %r9, %r9 +// CHECK: encoding: [0xf2,0x45,0x0f,0x38,0xf8,0xc9] + urdmsr %r9, %r9 + +// CHECK: uwrmsr %r9, $123 +// CHECK: encoding: [0xc4,0xc7,0x7a,0xf8,0xc1,0x7b,0x00,0x00,0x00] + uwrmsr %r9, $123 + +// CHECK: uwrmsr %r9, %r9 +// CHECK: encoding: [0xf3,0x45,0x0f,0x38,0xf8,0xc9] + uwrmsr %r9, %r9 + diff --git a/llvm/test/MC/X86/usermsr-64-intel.s b/llvm/test/MC/X86/usermsr-64-intel.s new file mode 100644 index 0000000000000..13d9161080af4 --- /dev/null +++ b/llvm/test/MC/X86/usermsr-64-intel.s @@ -0,0 +1,18 @@ +// RUN: llvm-mc -triple x86_64 -x86-asm-syntax=intel -output-asm-variant=1 --show-encoding %s | FileCheck %s + +// CHECK: urdmsr r9, 123 +// CHECK: encoding: [0xc4,0xc7,0x7b,0xf8,0xc1,0x7b,0x00,0x00,0x00] + urdmsr r9, 123 + +// CHECK: urdmsr r9, r9 +// CHECK: encoding: [0xf2,0x45,0x0f,0x38,0xf8,0xc9] + urdmsr r9, r9 + +// CHECK: uwrmsr 123, r9 +// CHECK: encoding: [0xc4,0xc7,0x7a,0xf8,0xc1,0x7b,0x00,0x00,0x00] + uwrmsr 123, r9 + +// CHECK: uwrmsr r9, r9 +// CHECK: encoding: [0xf3,0x45,0x0f,0x38,0xf8,0xc9] + uwrmsr r9, r9 + diff --git a/llvm/utils/TableGen/X86DisassemblerTables.cpp b/llvm/utils/TableGen/X86DisassemblerTables.cpp index 708c92aecfc85..ba51bf4858e19 100644 --- a/llvm/utils/TableGen/X86DisassemblerTables.cpp +++ b/llvm/utils/TableGen/X86DisassemblerTables.cpp @@ -982,6 +982,7 @@ void DisassemblerTables::emitContextDecisions(raw_ostream &o1, raw_ostream &o2, emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[7], THREEDNOW_MAP_STR); emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[8], MAP5_STR); emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[9], MAP6_STR); + emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[10], MAP7_STR); } void DisassemblerTables::emit(raw_ostream &o) const { diff --git a/llvm/utils/TableGen/X86DisassemblerTables.h b/llvm/utils/TableGen/X86DisassemblerTables.h index 966f7406efec1..4b6f6543acccf 100644 --- a/llvm/utils/TableGen/X86DisassemblerTables.h +++ b/llvm/utils/TableGen/X86DisassemblerTables.h @@ -46,7 +46,8 @@ class DisassemblerTables { /// [7] 3dnow map opcode /// [8] fixed length MAP5 opcode /// [9] fixed length MAP6 opcode - std::unique_ptr Tables[10]; + /// [10] fixed length MAP7 opcode + std::unique_ptr Tables[11]; // Table of ModRM encodings. typedef std::map, unsigned> ModRMMapTy; diff --git a/llvm/utils/TableGen/X86RecognizableInstr.cpp b/llvm/utils/TableGen/X86RecognizableInstr.cpp index b2f51ba016899..962da623b1cad 100644 --- a/llvm/utils/TableGen/X86RecognizableInstr.cpp +++ b/llvm/utils/TableGen/X86RecognizableInstr.cpp @@ -791,6 +791,7 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { case X86Local::ThreeDNow: opcodeType = THREEDNOW_MAP; break; case X86Local::T_MAP5: opcodeType = MAP5; break; case X86Local::T_MAP6: opcodeType = MAP6; break; + case X86Local::T_MAP7: opcodeType = MAP7; break; } std::unique_ptr filter; diff --git a/llvm/utils/TableGen/X86RecognizableInstr.h b/llvm/utils/TableGen/X86RecognizableInstr.h index 5efacdb27465b..38bca87bfe614 100644 --- a/llvm/utils/TableGen/X86RecognizableInstr.h +++ b/llvm/utils/TableGen/X86RecognizableInstr.h @@ -137,7 +137,7 @@ namespace X86Local { enum { OB = 0, TB = 1, T8 = 2, TA = 3, XOP8 = 4, XOP9 = 5, XOPA = 6, ThreeDNow = 7, - T_MAP5 = 8, T_MAP6 = 9 + T_MAP5 = 8, T_MAP6 = 9, T_MAP7 = 10 }; enum {