From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mgamail.intel.com (mgamail.intel.com [134.134.136.126]) by sourceware.org (Postfix) with ESMTPS id 2D74E3858D32 for ; Tue, 31 Oct 2023 02:16:18 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 2D74E3858D32 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=intel.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 2D74E3858D32 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=134.134.136.126 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698718582; cv=none; b=W3cEkjRdj/BFMSQEikuznWorop8ZvwhDcjQkCbNxpEEYpXkPG7hypAm5mvJPvb9G/OzvUoq/cWgAKcURG4b7HUoiiBKZDtxN1TfRZmUu+nRF9mzPMQGav7QRCnMmn+pSoYQBY3mS0gbRLJIdEeKL+nav537lCtIa/ViCD8ngFDI= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698718582; c=relaxed/simple; bh=zWlByFi7CnYZMk+zjVSibpoksSrnsMWGHJcgVyf4Ewc=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=HB8OLhgL1pHt5GQZlKjriYC+vmdhjRHVNljQwRKdSU3yd7hmqJpHZMfQkUmwuahieeTKpHro0gpq8saFI2Kz9SY4SD/iEkgE4RdszE5rjDk17S0apODUfzV7Z48SXfD6a9dwn99wWFmHfVWIOnv0yTVcIbA514a70EaQISmMDss= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1698718578; x=1730254578; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=zWlByFi7CnYZMk+zjVSibpoksSrnsMWGHJcgVyf4Ewc=; b=UlpcDidAPrSjODgc4ZXXUgl010sVcmPKyuTNwyb1d+iHYD/L4cLcxr8c weHrdhND2kQWfSdQO5yaaKD3yX3/gZhMNsGp3klxyJ9hihKj8UWXG7WTH RYJYB7bdb+UtB9cW38ExiMaeHdyPtCIUgKEanMcdWZPMDGoB35RGbwacx n8x8jV8QXa4j4nopQK3XiDBhGOBnxoECHMJa9brNBPQjX9H23Hp0WVAAk C3fKaXailHXd91JETxzK3/k0GiJm9iIHTYoFuaSkF8ZpiJ+0SSfIH8AZq 4ORZ1cgv+xFqZkzetsxopbFy4jSw5HT/9W72TvGyRlmG4FzZaDmcWHpIw Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10879"; a="373248523" X-IronPort-AV: E=Sophos;i="6.03,264,1694761200"; d="scan'208";a="373248523" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 Oct 2023 19:16:17 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10879"; a="933963949" X-IronPort-AV: E=Sophos;i="6.03,264,1694761200"; d="scan'208";a="933963949" Received: from shvmail03.sh.intel.com ([10.239.245.20]) by orsmga005.jf.intel.com with ESMTP; 30 Oct 2023 19:16:11 -0700 Received: from shliclel4217.sh.intel.com (shliclel4217.sh.intel.com [10.239.240.127]) by shvmail03.sh.intel.com (Postfix) with ESMTP id 0F199100567A; Tue, 31 Oct 2023 10:16:11 +0800 (CST) From: "Hu, Lin1" To: binutils@sourceware.org Cc: JBeulich@suse.com, hongjiu.lu@intel.com Subject: [PATCH][v6] Support Intel USER_MSR Date: Tue, 31 Oct 2023 10:14:10 +0800 Message-Id: <20231031021410.1543517-1-lin1.hu@intel.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <260c522e-dbb0-7e40-1419-5bb269fef823@suse.com> References: <260c522e-dbb0-7e40-1419-5bb269fef823@suse.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-10.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,LOTS_OF_MONEY,SPF_HELO_NONE,SPF_NONE,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: This is the current version. BRs, Lin gas/ChangeLog: * NEWS: Support Intel USER_MSR. * config/tc-i386.c (smallest_imm_type): Reject imm32 in 64bit mode. (build_vex_prefix): Add VEXMAP7. (md_assemble): Handling the imm32 of USER_MSR. (match_template): Handling the unusual immediate. * doc/c-i386.texi: Document .user_msr. * testsuite/gas/i386/i386.exp: Run USER_MSR tests. * testsuite/gas/i386/x86-64.exp: Ditto. * testsuite/gas/i386/user_msr-inval.l: New test. * testsuite/gas/i386/user_msr-inval.s: Ditto. * testsuite/gas/i386/x86-64-user_msr-intel.d: Ditto. * testsuite/gas/i386/x86-64-user_msr-inval.l: New test. * testsuite/gas/i386/x86-64-user_msr-inval.s: New test. * testsuite/gas/i386/x86-64-user_msr.d: Ditto. * testsuite/gas/i386/x86-64-user_msr.s: Ditto. opcodes/ChangeLog: * i386-dis.c (struct instr_info): Add a new attribute has_skipped_modrm. (Gq): New. (Rq): Ditto. (q_mm_mode): Ditto. (Nq): Change mode from q_mode to q_mm_mode. (VEX_LEN_TABLE): (get_valid_dis386): Add VEX_MAP7 in VEX prefix. and handle the map7_f8 for save space. (OP_Skip_MODRM): Set has_skipped_modrm. (OP_E): Skip codep++ when has skipped modrm byte. (OP_R): Support q_mode and q_mm_mode. (REG_VEX_MAP7_F8_L_0_W_0): New. (PREFIX_VEX_MAP7_F8_L_0_W_0_R_0_X86_64): Ditto. (X86_64_VEX_MAP7_F8_L_0_W_0_R_0): Ditto. (VEX_LEN_MAP7_F8): Ditto. (VEX_W_MAP7_F8_L_0): Ditto. (MOD_0F38F8): Ditto. (PREFIX_0F38F8_M_0): Ditto. (PREFIX_0F38F8_M_1_X86_64): Ditto. (X86_64_0F38F8_M_1): Ditto. (PREFIX_0F38F8): Remove. (prefix_table): Add PREFIX_0F38F8_M_1_X86_64. Remove PREFIX_0F38F8. (reg_table): Add REG_VEX_MAP7_F8_L_0_W_0, PREFIX_VEX_MAP7_F8_L_0_W_0_R_0_X86_64. (x86_64_table): Add X86_64_0F38F8_PREFIX_3_M_1, X86_64_VEX_MAP7_F8_L_0_W_0_R_0 and X86_64_0F38F8_M_1. (vex_table): Add VEX_MAP7. (vex_len_table): Add VEX_LEN_MAP7_F8, VEX_W_MAP7_F8_L_0. (mod_table): New entry for USER_MSR and add MOD_0F38F8. * i386-gen.c (cpu_flag_init): Add CPU_USER_MSR_FLAGS and CPU_ANY_USER_MSR_FLAGS. Add add VEXMAP7. * i386-init.h: Regenerated. * i386-mnem.h: Ditto. * i386-opc.h (SPACE_VEXMAP7): New. (CPU_USER_MSR_FLAGS): Ditoo. (CPU_ANY_USER_MSR_FLAGS): Ditto. (i386_cpu_flags): Add cpuuser_msr. * i386-opc.tbl: Add USER_MSR instructions. * i386-tbl.h: Regenerated. --- gas/NEWS | 2 + gas/config/tc-i386.c | 40 +- gas/doc/c-i386.texi | 3 +- gas/testsuite/gas/i386/i386.exp | 1 + gas/testsuite/gas/i386/user_msr-inval.l | 3 + gas/testsuite/gas/i386/user_msr-inval.s | 6 + .../gas/i386/x86-64-user_msr-intel.d | 46 + .../gas/i386/x86-64-user_msr-inval.l | 9 + .../gas/i386/x86-64-user_msr-inval.s | 12 + gas/testsuite/gas/i386/x86-64-user_msr.d | 46 + gas/testsuite/gas/i386/x86-64-user_msr.s | 42 + gas/testsuite/gas/i386/x86-64.exp | 3 + opcodes/i386-dis.c | 96 +- opcodes/i386-gen.c | 2 + opcodes/i386-init.h | 816 +++++------ opcodes/i386-mnem.h | 1278 +++++++++-------- opcodes/i386-opc.h | 5 + opcodes/i386-opc.tbl | 11 + opcodes/i386-tbl.h | 272 ++-- 19 files changed, 1522 insertions(+), 1171 deletions(-) create mode 100644 gas/testsuite/gas/i386/user_msr-inval.l create mode 100644 gas/testsuite/gas/i386/user_msr-inval.s create mode 100644 gas/testsuite/gas/i386/x86-64-user_msr-intel.d create mode 100644 gas/testsuite/gas/i386/x86-64-user_msr-inval.l create mode 100644 gas/testsuite/gas/i386/x86-64-user_msr-inval.s create mode 100644 gas/testsuite/gas/i386/x86-64-user_msr.d create mode 100644 gas/testsuite/gas/i386/x86-64-user_msr.s diff --git a/gas/NEWS b/gas/NEWS index 71a1269b893..ab0e7813f27 100644 --- a/gas/NEWS +++ b/gas/NEWS @@ -1,5 +1,7 @@ -*- text -*- +* Add support for Intel USER_MSR instructions. + * Add support for Intel AVX10.1. * Add support for Intel PBNDKB instructions. diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 714354d5116..8a47e8715dc 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -1164,6 +1164,7 @@ static const arch_entry cpu_arch[] = VECARCH (sm4, SM4, ANY_SM4, reset), SUBARCH (pbndkb, PBNDKB, PBNDKB, false), VECARCH (avx10.1, AVX10_1, ANY_AVX512F, set), + SUBARCH (user_msr, USER_MSR, USER_MSR, false), }; #undef SUBARCH @@ -2504,7 +2505,8 @@ smallest_imm_type (offsetT num) t.bitfield.imm8 = 1; t.bitfield.imm8s = 1; t.bitfield.imm16 = 1; - t.bitfield.imm32 = 1; + if (flag_code != CODE_64BIT || fits_in_unsigned_long (num)) + t.bitfield.imm32 = 1; t.bitfield.imm32s = 1; } else if (fits_in_unsigned_byte (num)) @@ -2517,12 +2519,14 @@ smallest_imm_type (offsetT num) else if (fits_in_signed_word (num) || fits_in_unsigned_word (num)) { t.bitfield.imm16 = 1; - t.bitfield.imm32 = 1; + if (flag_code != CODE_64BIT || fits_in_unsigned_long (num)) + t.bitfield.imm32 = 1; t.bitfield.imm32s = 1; } else if (fits_in_signed_long (num)) { - t.bitfield.imm32 = 1; + if (flag_code != CODE_64BIT || fits_in_unsigned_long (num)) + t.bitfield.imm32 = 1; t.bitfield.imm32s = 1; } else if (fits_in_unsigned_long (num)) @@ -3863,6 +3867,7 @@ build_vex_prefix (const insn_template *t) case SPACE_0F: case SPACE_0F38: case SPACE_0F3A: + case SPACE_VEXMAP7: i.vex.bytes[0] = 0xc4; break; case SPACE_XOP08: @@ -5233,7 +5238,23 @@ md_assemble (char *line) swap_2_operands (0, 1); if (i.imm_operands) - optimize_imm (); + { + /* For USER_MSR instructions, imm32 stands for the name of an model specific + register (MSR). That's an unsigned quantity, whereas all other insns with + 32-bit immediate and 64-bit operand size use sign-extended + immediates (imm32s). Therefore these insns are special-cased, bypassing + the normal handling of immediates here. */ + if (is_cpu(current_templates->start, CpuUSER_MSR)) + { + for (j = 0; j < i.operands; j++) + { + if (operand_type_check(i.types[j], imm)) + i.types[j] = smallest_imm_type (i.op[j].imms->X_add_number); + } + } + else + optimize_imm (); + } if (i.disp_operands && !optimize_disp (t)) return; @@ -7566,6 +7587,17 @@ match_template (char mnem_suffix) break; } + /* This pattern aims to put the unusually placed imm operand to a usual + place. The constraints are currently only adapted to uwrmsr, and may + need further tweaking when new similar instructions become available. */ + if (i.imm_operands && i.imm_operands < i.operands + && operand_type_check (operand_types[i.operands - 1], imm)) + { + i.tm.operand_types[0] = operand_types[i.operands - 1]; + i.tm.operand_types[i.operands - 1] = operand_types[0]; + swap_2_operands(0, i.operands - 1); + } + return t; } diff --git a/gas/doc/c-i386.texi b/gas/doc/c-i386.texi index b04e1b00b4b..03ee980bef7 100644 --- a/gas/doc/c-i386.texi +++ b/gas/doc/c-i386.texi @@ -216,6 +216,7 @@ accept various extension mnemonics. For example, @code{avx10.1/512}, @code{avx10.1/256}, @code{avx10.1/128}, +@code{user_msr}, @code{amx_int8}, @code{amx_bf16}, @code{amx_fp16}, @@ -1650,7 +1651,7 @@ supported on the CPU specified. The choices for @var{cpu_type} are: @item @samp{.cmpccxadd} @tab @samp{.wrmsrns} @tab @samp{.msrlist} @item @samp{.avx_ne_convert} @tab @samp{.rao_int} @tab @samp{.fred} @tab @samp{.lkgs} @item @samp{.avx_vnni_int16} @tab @samp{.sha512} @tab @samp{.sm3} @tab @samp{.sm4} -@item @samp{.pbndkb} +@item @samp{.pbndkb} @tab @samp{.user_msr} @item @samp{.wbnoinvd} @tab @samp{.pconfig} @tab @samp{.waitpkg} @tab @samp{.cldemote} @item @samp{.shstk} @tab @samp{.gfni} @tab @samp{.vaes} @tab @samp{.vpclmulqdq} @item @samp{.movdiri} @tab @samp{.movdir64b} @tab @samp{.enqcmd} @tab @samp{.tsxldtrk} diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp index ee74bcd4615..81ce1e38b10 100644 --- a/gas/testsuite/gas/i386/i386.exp +++ b/gas/testsuite/gas/i386/i386.exp @@ -509,6 +509,7 @@ if [gas_32_check] then { run_dump_test "sm4" run_dump_test "sm4-intel" run_list_test "pbndkb-inval" + run_list_test "user_msr-inval" run_list_test "sg" run_dump_test "clzero" run_dump_test "invlpgb" diff --git a/gas/testsuite/gas/i386/user_msr-inval.l b/gas/testsuite/gas/i386/user_msr-inval.l new file mode 100644 index 00000000000..54c48f1953b --- /dev/null +++ b/gas/testsuite/gas/i386/user_msr-inval.l @@ -0,0 +1,3 @@ +.* Assembler messages: +.*:5: Error: `urdmsr' is only supported in 64-bit mode +.*:6: Error: `uwrmsr' is only supported in 64-bit mode diff --git a/gas/testsuite/gas/i386/user_msr-inval.s b/gas/testsuite/gas/i386/user_msr-inval.s new file mode 100644 index 00000000000..1682a1e8d79 --- /dev/null +++ b/gas/testsuite/gas/i386/user_msr-inval.s @@ -0,0 +1,6 @@ +# Check Illegal 32bit USER_MSR instructions + + .text +_start: + urdmsr %r12, %r14 + uwrmsr %r12, %r14 diff --git a/gas/testsuite/gas/i386/x86-64-user_msr-intel.d b/gas/testsuite/gas/i386/x86-64-user_msr-intel.d new file mode 100644 index 00000000000..e68b5eacfa9 --- /dev/null +++ b/gas/testsuite/gas/i386/x86-64-user_msr-intel.d @@ -0,0 +1,46 @@ +#as: +#objdump: -dw -Mintel +#name: x86_64 USER_MSR insns (Intel disassembly) +#source: x86-64-user_msr.s + +.*: +file format .* + +Disassembly of section \.text: + +0+ <_start>: +\s*[a-f0-9]+:\s*f2 45 0f 38 f8 f4\s+urdmsr r12,r14 +\s*[a-f0-9]+:\s*f2 44 0f 38 f8 f0\s+urdmsr rax,r14 +\s*[a-f0-9]+:\s*f2 41 0f 38 f8 d4\s+urdmsr r12,rdx +\s*[a-f0-9]+:\s*f2 0f 38 f8 d0\s+urdmsr rax,rdx +\s*[a-f0-9]+:\s*c4 c7 7b f8 c4 0f 0f 12 03\s+urdmsr r12,0x3120f0f +\s*[a-f0-9]+:\s*c4 e7 7b f8 c0 0f 0f 12 03\s+urdmsr rax,0x3120f0f +\s*[a-f0-9]+:\s*c4 c7 7b f8 c4 7f 00 00 00\s+urdmsr r12,0x7f +\s*[a-f0-9]+:\s*c4 c7 7b f8 c4 ff 7f 00 00\s+urdmsr r12,0x7fff +\s*[a-f0-9]+:\s*c4 c7 7b f8 c4 00 00 00 80\s+urdmsr r12,0x80000000 +\s*[a-f0-9]+:\s*f3 45 0f 38 f8 f4\s+uwrmsr r14,r12 +\s*[a-f0-9]+:\s*f3 44 0f 38 f8 f0\s+uwrmsr r14,rax +\s*[a-f0-9]+:\s*f3 41 0f 38 f8 d4\s+uwrmsr rdx,r12 +\s*[a-f0-9]+:\s*f3 0f 38 f8 d0\s+uwrmsr rdx,rax +\s*[a-f0-9]+:\s*c4 c7 7a f8 c4 0f 0f 12 03\s+uwrmsr 0x3120f0f,r12 +\s*[a-f0-9]+:\s*c4 e7 7a f8 c0 0f 0f 12 03\s+uwrmsr 0x3120f0f,rax +\s*[a-f0-9]+:\s*c4 c7 7a f8 c4 7f 00 00 00\s+uwrmsr 0x7f,r12 +\s*[a-f0-9]+:\s*c4 c7 7a f8 c4 ff 7f 00 00\s+uwrmsr 0x7fff,r12 +\s*[a-f0-9]+:\s*c4 c7 7a f8 c4 00 00 00 80\s+uwrmsr 0x80000000,r12 +\s*[a-f0-9]+:\s*f2 45 0f 38 f8 f4\s+urdmsr r12,r14 +\s*[a-f0-9]+:\s*f2 44 0f 38 f8 f0\s+urdmsr rax,r14 +\s*[a-f0-9]+:\s*f2 41 0f 38 f8 d4\s+urdmsr r12,rdx +\s*[a-f0-9]+:\s*f2 0f 38 f8 d0\s+urdmsr rax,rdx +\s*[a-f0-9]+:\s*c4 c7 7b f8 c4 0f 0f 12 03\s+urdmsr r12,0x3120f0f +\s*[a-f0-9]+:\s*c4 e7 7b f8 c0 0f 0f 12 03\s+urdmsr rax,0x3120f0f +\s*[a-f0-9]+:\s*c4 c7 7b f8 c4 7f 00 00 00\s+urdmsr r12,0x7f +\s*[a-f0-9]+:\s*c4 c7 7b f8 c4 ff 7f 00 00\s+urdmsr r12,0x7fff +\s*[a-f0-9]+:\s*c4 c7 7b f8 c4 00 00 00 80\s+urdmsr r12,0x80000000 +\s*[a-f0-9]+:\s*f3 45 0f 38 f8 f4\s+uwrmsr r14,r12 +\s*[a-f0-9]+:\s*f3 44 0f 38 f8 f0\s+uwrmsr r14,rax +\s*[a-f0-9]+:\s*f3 41 0f 38 f8 d4\s+uwrmsr rdx,r12 +\s*[a-f0-9]+:\s*f3 0f 38 f8 d0\s+uwrmsr rdx,rax +\s*[a-f0-9]+:\s*c4 c7 7a f8 c4 0f 0f 12 03\s+uwrmsr 0x3120f0f,r12 +\s*[a-f0-9]+:\s*c4 e7 7a f8 c0 0f 0f 12 03\s+uwrmsr 0x3120f0f,rax +\s*[a-f0-9]+:\s*c4 c7 7a f8 c4 7f 00 00 00\s+uwrmsr 0x7f,r12 +\s*[a-f0-9]+:\s*c4 c7 7a f8 c4 ff 7f 00 00\s+uwrmsr 0x7fff,r12 +\s*[a-f0-9]+:\s*c4 c7 7a f8 c4 00 00 00 80\s+uwrmsr 0x80000000,r12 diff --git a/gas/testsuite/gas/i386/x86-64-user_msr-inval.l b/gas/testsuite/gas/i386/x86-64-user_msr-inval.l new file mode 100644 index 00000000000..9eb3044e16e --- /dev/null +++ b/gas/testsuite/gas/i386/x86-64-user_msr-inval.l @@ -0,0 +1,9 @@ +.* Assembler messages: +.*:5: Error: operand type mismatch for `urdmsr' +.*:6: Error: operand type mismatch for `urdmsr' +.*:7: Error: operand type mismatch for `urdmsr' +.*:8: Error: operand type mismatch for `urdmsr' +.*:9: Error: operand type mismatch for `uwrmsr' +.*:10: Error: operand type mismatch for `uwrmsr' +.*:11: Error: operand type mismatch for `uwrmsr' +.*:12: Error: operand type mismatch for `uwrmsr' diff --git a/gas/testsuite/gas/i386/x86-64-user_msr-inval.s b/gas/testsuite/gas/i386/x86-64-user_msr-inval.s new file mode 100644 index 00000000000..e7b6d6eea83 --- /dev/null +++ b/gas/testsuite/gas/i386/x86-64-user_msr-inval.s @@ -0,0 +1,12 @@ +# Check Illegal 64bit USER_MSR instructions + + .text +_start: + urdmsr $-1, %r14 + urdmsr $-32767, %r14 + urdmsr $-2147483648, %r14 + urdmsr $0x7fffffffffffffff, %r14 + uwrmsr %r12, $-1 + uwrmsr %r12, $-32767 + uwrmsr %r12, $-2147483648 + uwrmsr %r12, $0x7fffffffffffffff diff --git a/gas/testsuite/gas/i386/x86-64-user_msr.d b/gas/testsuite/gas/i386/x86-64-user_msr.d new file mode 100644 index 00000000000..41f29718ab0 --- /dev/null +++ b/gas/testsuite/gas/i386/x86-64-user_msr.d @@ -0,0 +1,46 @@ +#as: +#objdump: -dw +#name: x86_64 USER_MSR insns +#source: x86-64-user_msr.s + +.*: +file format .* + +Disassembly of section \.text: + +0+ <_start>: +\s*[a-f0-9]+:\s*f2 45 0f 38 f8 f4\s+urdmsr %r14,%r12 +\s*[a-f0-9]+:\s*f2 44 0f 38 f8 f0\s+urdmsr %r14,%rax +\s*[a-f0-9]+:\s*f2 41 0f 38 f8 d4\s+urdmsr %rdx,%r12 +\s*[a-f0-9]+:\s*f2 0f 38 f8 d0\s+urdmsr %rdx,%rax +\s*[a-f0-9]+:\s*c4 c7 7b f8 c4 0f 0f 12 03\s+urdmsr \$0x3120f0f,%r12 +\s*[a-f0-9]+:\s*c4 e7 7b f8 c0 0f 0f 12 03\s+urdmsr \$0x3120f0f,%rax +\s*[a-f0-9]+:\s*c4 c7 7b f8 c4 7f 00 00 00\s+urdmsr \$0x7f,%r12 +\s*[a-f0-9]+:\s*c4 c7 7b f8 c4 ff 7f 00 00\s+urdmsr \$0x7fff,%r12 +\s*[a-f0-9]+:\s*c4 c7 7b f8 c4 00 00 00 80\s+urdmsr \$0x80000000,%r12 +\s*[a-f0-9]+:\s*f3 45 0f 38 f8 f4\s+uwrmsr %r12,%r14 +\s*[a-f0-9]+:\s*f3 44 0f 38 f8 f0\s+uwrmsr %rax,%r14 +\s*[a-f0-9]+:\s*f3 41 0f 38 f8 d4\s+uwrmsr %r12,%rdx +\s*[a-f0-9]+:\s*f3 0f 38 f8 d0\s+uwrmsr %rax,%rdx +\s*[a-f0-9]+:\s*c4 c7 7a f8 c4 0f 0f 12 03\s+uwrmsr %r12,\$0x3120f0f +\s*[a-f0-9]+:\s*c4 e7 7a f8 c0 0f 0f 12 03\s+uwrmsr %rax,\$0x3120f0f +\s*[a-f0-9]+:\s*c4 c7 7a f8 c4 7f 00 00 00\s+uwrmsr %r12,\$0x7f +\s*[a-f0-9]+:\s*c4 c7 7a f8 c4 ff 7f 00 00\s+uwrmsr %r12,\$0x7fff +\s*[a-f0-9]+:\s*c4 c7 7a f8 c4 00 00 00 80\s+uwrmsr %r12,\$0x80000000 +\s*[a-f0-9]+:\s*f2 45 0f 38 f8 f4\s+urdmsr %r14,%r12 +\s*[a-f0-9]+:\s*f2 44 0f 38 f8 f0\s+urdmsr %r14,%rax +\s*[a-f0-9]+:\s*f2 41 0f 38 f8 d4\s+urdmsr %rdx,%r12 +\s*[a-f0-9]+:\s*f2 0f 38 f8 d0\s+urdmsr %rdx,%rax +\s*[a-f0-9]+:\s*c4 c7 7b f8 c4 0f 0f 12 03\s+urdmsr \$0x3120f0f,%r12 +\s*[a-f0-9]+:\s*c4 e7 7b f8 c0 0f 0f 12 03\s+urdmsr \$0x3120f0f,%rax +\s*[a-f0-9]+:\s*c4 c7 7b f8 c4 7f 00 00 00\s+urdmsr \$0x7f,%r12 +\s*[a-f0-9]+:\s*c4 c7 7b f8 c4 ff 7f 00 00\s+urdmsr \$0x7fff,%r12 +\s*[a-f0-9]+:\s*c4 c7 7b f8 c4 00 00 00 80\s+urdmsr \$0x80000000,%r12 +\s*[a-f0-9]+:\s*f3 45 0f 38 f8 f4\s+uwrmsr %r12,%r14 +\s*[a-f0-9]+:\s*f3 44 0f 38 f8 f0\s+uwrmsr %rax,%r14 +\s*[a-f0-9]+:\s*f3 41 0f 38 f8 d4\s+uwrmsr %r12,%rdx +\s*[a-f0-9]+:\s*f3 0f 38 f8 d0\s+uwrmsr %rax,%rdx +\s*[a-f0-9]+:\s*c4 c7 7a f8 c4 0f 0f 12 03\s+uwrmsr %r12,\$0x3120f0f +\s*[a-f0-9]+:\s*c4 e7 7a f8 c0 0f 0f 12 03\s+uwrmsr %rax,\$0x3120f0f +\s*[a-f0-9]+:\s*c4 c7 7a f8 c4 7f 00 00 00\s+uwrmsr %r12,\$0x7f +\s*[a-f0-9]+:\s*c4 c7 7a f8 c4 ff 7f 00 00\s+uwrmsr %r12,\$0x7fff +\s*[a-f0-9]+:\s*c4 c7 7a f8 c4 00 00 00 80\s+uwrmsr %r12,\$0x80000000 diff --git a/gas/testsuite/gas/i386/x86-64-user_msr.s b/gas/testsuite/gas/i386/x86-64-user_msr.s new file mode 100644 index 00000000000..63bc6c1352c --- /dev/null +++ b/gas/testsuite/gas/i386/x86-64-user_msr.s @@ -0,0 +1,42 @@ +# Check 64bit USER_MSR instructions + + .text +_start: + urdmsr %r14, %r12 + urdmsr %r14, %rax + urdmsr %rdx, %r12 + urdmsr %rdx, %rax + urdmsr $51515151, %r12 + urdmsr $51515151, %rax + urdmsr $0x7f, %r12 + urdmsr $0x7fff, %r12 + urdmsr $0x80000000, %r12 + uwrmsr %r12, %r14 + uwrmsr %rax, %r14 + uwrmsr %r12, %rdx + uwrmsr %rax, %rdx + uwrmsr %r12, $51515151 + uwrmsr %rax, $51515151 + uwrmsr %r12, $0x7f + uwrmsr %r12, $0x7fff + uwrmsr %r12, $0x80000000 + + .intel_syntax noprefix + urdmsr r12, r14 + urdmsr rax, r14 + urdmsr r12, rdx + urdmsr rax, rdx + urdmsr r12, 51515151 + urdmsr rax, 51515151 + urdmsr r12, 0x7f + urdmsr r12, 0x7fff + urdmsr r12, 0x80000000 + uwrmsr r14, r12 + uwrmsr r14, rax + uwrmsr rdx, r12 + uwrmsr rdx, rax + uwrmsr 51515151, r12 + uwrmsr 51515151, rax + uwrmsr 0x7f, r12 + uwrmsr 0x7fff, r12 + uwrmsr 0x80000000, r12 diff --git a/gas/testsuite/gas/i386/x86-64.exp b/gas/testsuite/gas/i386/x86-64.exp index 52711cdcf6f..22fdb0d9bcd 100644 --- a/gas/testsuite/gas/i386/x86-64.exp +++ b/gas/testsuite/gas/i386/x86-64.exp @@ -450,6 +450,9 @@ run_dump_test "x86-64-sm4" run_dump_test "x86-64-sm4-intel" run_dump_test "x86-64-pbndkb" run_dump_test "x86-64-pbndkb-intel" +run_dump_test "x86-64-user_msr" +run_dump_test "x86-64-user_msr-intel" +run_list_test "x86-64-user_msr-inval" run_dump_test "x86-64-clzero" run_dump_test "x86-64-mwaitx-bdver4" run_list_test "x86-64-mwaitx-reg" diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c index 87ecf0f5e23..2e2043d467b 100644 --- a/opcodes/i386-dis.c +++ b/opcodes/i386-dis.c @@ -221,6 +221,9 @@ struct instr_info /* Record whether EVEX masking is used incorrectly. */ bool illegal_masking; + /* Record whether the modrm byte has been skipped. */ + bool has_skipped_modrm; + unsigned char op_ad; signed char op_index[MAX_OPERANDS]; bool op_riprel[MAX_OPERANDS]; @@ -418,6 +421,7 @@ fetch_error (const instr_info *ins) #define Gv { OP_G, v_mode } #define Gd { OP_G, d_mode } #define Gdq { OP_G, dq_mode } +#define Gq { OP_G, q_mode } #define Gm { OP_G, m_mode } #define Gva { OP_G, va_mode } #define Gw { OP_G, w_mode } @@ -527,7 +531,8 @@ fetch_error (const instr_info *ins) #define EXEvexXNoBcst { OP_EX, evex_x_nobcst_mode } #define Rd { OP_R, d_mode } #define Rdq { OP_R, dq_mode } -#define Nq { OP_R, q_mode } +#define Rq { OP_R, q_mode } +#define Nq { OP_R, q_mm_mode } #define Ux { OP_R, x_mode } #define Uxmm { OP_R, xmm_mode } #define Rxmmq { OP_R, xmmq_mode } @@ -624,6 +629,8 @@ enum d_swap_mode, /* quad word operand */ q_mode, + /* 8-byte MM operand */ + q_mm_mode, /* quad word operand with operand swapped */ q_swap_mode, /* ten-byte operand */ @@ -845,6 +852,7 @@ enum REG_VEX_0FAE, REG_VEX_0F3849_X86_64_L_0_W_0_M_1_P_0, REG_VEX_0F38F3_L_0, + REG_VEX_MAP7_F8_L_0_W_0, REG_XOP_09_01_L_0, REG_XOP_09_02_L_0, @@ -893,6 +901,7 @@ enum MOD_0FC7_REG_6, MOD_0FC7_REG_7, MOD_0F38DC_PREFIX_1, + MOD_0F38F8, MOD_VEX_0F3849_X86_64_L_0_W_0, }; @@ -1010,7 +1019,8 @@ enum PREFIX_0F38F0, PREFIX_0F38F1, PREFIX_0F38F6, - PREFIX_0F38F8, + PREFIX_0F38F8_M_0, + PREFIX_0F38F8_M_1_X86_64, PREFIX_0F38FA, PREFIX_0F38FB, PREFIX_0F38FC, @@ -1073,6 +1083,7 @@ enum PREFIX_VEX_0F38F6_L_0, PREFIX_VEX_0F38F7_L_0, PREFIX_VEX_0F3AF0_L_0, + PREFIX_VEX_MAP7_F8_L_0_W_0_R_0_X86_64, PREFIX_EVEX_0F5B, PREFIX_EVEX_0F6F, @@ -1217,6 +1228,7 @@ enum X86_64_0F18_REG_7_MOD_0, X86_64_0F24, X86_64_0F26, + X86_64_0F38F8_M_1, X86_64_0FC7_REG_6_MOD_3_PREFIX_1, X86_64_VEX_0F3849, @@ -1240,6 +1252,7 @@ enum X86_64_VEX_0F38ED, X86_64_VEX_0F38EE, X86_64_VEX_0F38EF, + X86_64_VEX_MAP7_F8_L_0_W_0_R_0, }; enum @@ -1259,7 +1272,8 @@ enum { VEX_0F = 0, VEX_0F38, - VEX_0F3A + VEX_0F3A, + VEX_MAP7, }; enum @@ -1350,6 +1364,7 @@ enum VEX_LEN_0F3ADE_W_0, VEX_LEN_0F3ADF, VEX_LEN_0F3AF0, + VEX_LEN_MAP7_F8, VEX_LEN_XOP_08_85, VEX_LEN_XOP_08_86, VEX_LEN_XOP_08_87, @@ -1510,6 +1525,7 @@ enum VEX_W_0F3ACE, VEX_W_0F3ACF, VEX_W_0F3ADE, + VEX_W_MAP7_F8_L_0, VEX_W_XOP_08_85_L_0, VEX_W_XOP_08_86_L_0, @@ -2849,6 +2865,10 @@ static const struct dis386 reg_table[][8] = { { "blsmskS", { VexGdq, Edq }, PREFIX_OPCODE }, { "blsiS", { VexGdq, Edq }, PREFIX_OPCODE }, }, + /* REG_VEX_MAP7_F8_L_0_W_0 */ + { + { X86_64_TABLE (X86_64_VEX_MAP7_F8_L_0_W_0_R_0) }, + }, /* REG_XOP_09_01_L_0 */ { { Bad_Opcode }, @@ -3555,13 +3575,22 @@ static const struct dis386 prefix_table[][4] = { { Bad_Opcode }, }, - /* PREFIX_0F38F8 */ + /* PREFIX_0F38F8_M_0 */ { { Bad_Opcode }, { "enqcmds", { Gva, M }, 0 }, { "movdir64b", { Gva, M }, 0 }, { "enqcmd", { Gva, M }, 0 }, }, + + /* PREFIX_0F38F8_M_1_X86_64 */ + { + { Bad_Opcode }, + { "uwrmsr", { Gq, Rq }, 0 }, + { Bad_Opcode }, + { "urdmsr", { Rq, Gq }, 0 }, + }, + /* PREFIX_0F38FA */ { { Bad_Opcode }, @@ -4014,6 +4043,14 @@ static const struct dis386 prefix_table[][4] = { { "rorxS", { Gdq, Edq, Ib }, 0 }, }, + /* PREFIX_VEX_MAP7_F8_L_0_W_0_R_0_X86_64 */ + { + { Bad_Opcode }, + { "uwrmsr", { Skip_MODRM, Id, Rq }, 0 }, + { Bad_Opcode }, + { "urdmsr", { Rq, Id }, 0 }, + }, + #include "i386-dis-evex-prefix.h" }; @@ -4322,6 +4359,12 @@ static const struct dis386 x86_64_table[][2] = { { "movZ", { Td, Em }, 0 }, }, + { + /* X86_64_0F38F8_M_1 */ + { Bad_Opcode }, + { PREFIX_TABLE (PREFIX_0F38F8_M_1_X86_64) }, + }, + /* X86_64_0FC7_REG_6_MOD_3_PREFIX_1 */ { { Bad_Opcode }, @@ -4453,6 +4496,13 @@ static const struct dis386 x86_64_table[][2] = { { Bad_Opcode }, { "cmpnlexadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA }, }, + + /* X86_64_VEX_MAP7_F8_L_0_W_0_R_0 */ + { + { Bad_Opcode }, + { PREFIX_TABLE (PREFIX_VEX_MAP7_F8_L_0_W_0_R_0_X86_64) }, + }, + }; static const struct dis386 three_byte_table[][256] = { @@ -4739,7 +4789,7 @@ static const struct dis386 three_byte_table[][256] = { { PREFIX_TABLE (PREFIX_0F38F6) }, { Bad_Opcode }, /* f8 */ - { PREFIX_TABLE (PREFIX_0F38F8) }, + { MOD_TABLE (MOD_0F38F8) }, { "movdiri", { Mdq, Gdq }, PREFIX_OPCODE }, { PREFIX_TABLE (PREFIX_0F38FA) }, { PREFIX_TABLE (PREFIX_0F38FB) }, @@ -7205,6 +7255,11 @@ static const struct dis386 vex_len_table[][2] = { { PREFIX_TABLE (PREFIX_VEX_0F3AF0_L_0) }, }, + /* VEX_LEN_MAP7_F8 */ + { + { VEX_W_TABLE (VEX_W_MAP7_F8_L_0) }, + }, + /* VEX_LEN_XOP_08_85 */ { { VEX_W_TABLE (VEX_W_XOP_08_85_L_0) }, @@ -7811,6 +7866,10 @@ static const struct dis386 vex_w_table[][2] = { /* VEX_W_0F3ADE */ { VEX_LEN_TABLE (VEX_LEN_0F3ADE_W_0) }, }, + { + /* VEX_W_MAP7_F8_L_0 */ + { REG_TABLE (REG_VEX_MAP7_F8_L_0_W_0) }, + }, /* VEX_W_XOP_08_85_L_0 */ { { "vpmacssww", { XM, Vex, EXx, XMVexI4 }, 0 }, @@ -8153,6 +8212,11 @@ static const struct dis386 mod_table[][2] = { { "aesenc128kl", { XM, M }, 0 }, { "loadiwkey", { XM, EXx }, 0 }, }, + /* MOD_0F38F8 */ + { + { PREFIX_TABLE (PREFIX_0F38F8_M_0) }, + { X86_64_TABLE (X86_64_0F38F8_M_1) }, + }, { /* MOD_VEX_0F3849_X86_64_L_0_W_0 */ { PREFIX_TABLE (PREFIX_VEX_0F3849_X86_64_L_0_W_0_M_0) }, @@ -8527,6 +8591,8 @@ static const struct dis386 bad_opcode = { "(bad)", { XX }, 0 }; /* Fetch error indicator. */ static const struct dis386 err_opcode = { NULL, { XX }, 0 }; +static const struct dis386 map7_f8_opcode = { VEX_LEN_TABLE (VEX_LEN_MAP7_F8) }; + /* Get a pointer to struct dis386 with a valid name. */ static const struct dis386 * @@ -8769,6 +8835,9 @@ get_valid_dis386 (const struct dis386 *dp, instr_info *ins) case 0x3: vex_table_index = VEX_0F3A; break; + case 0x7: + vex_table_index = VEX_MAP7; + break; } ins->codep++; ins->vex.w = *ins->codep & 0x80; @@ -8803,7 +8872,12 @@ get_valid_dis386 (const struct dis386 *dp, instr_info *ins) ins->need_vex = 3; ins->codep++; vindex = *ins->codep++; - dp = &vex_table[vex_table_index][vindex]; + if (vex_table_index != VEX_MAP7) + dp = &vex_table[vex_table_index][vindex]; + else if (vindex == 0xf8) + dp = &map7_f8_opcode; + else + dp = &bad_opcode; ins->end_codep = ins->codep; /* There is no MODRM byte for VEX0F 77. */ if ((vex_table_index != VEX_0F || vindex != 0x77) @@ -11300,6 +11374,7 @@ OP_Skip_MODRM (instr_info *ins, int bytemode ATTRIBUTE_UNUSED, /* Skip mod/rm byte. */ MODRM_CHECK; ins->codep++; + ins->has_skipped_modrm = true; return true; } @@ -11818,7 +11893,11 @@ OP_E (instr_info *ins, int bytemode, int sizeflag) { /* Skip mod/rm byte. */ MODRM_CHECK; - ins->codep++; + if (!ins->has_skipped_modrm) + { + ins->codep++; + ins->has_skipped_modrm = true; + } if (ins->modrm.mod == 3) { @@ -12623,9 +12702,10 @@ OP_R (instr_info *ins, int bytemode, int sizeflag) { case d_mode: case dq_mode: + case q_mode: case mask_mode: return OP_E (ins, bytemode, sizeflag); - case q_mode: + case q_mm_mode: return OP_EM (ins, x_mode, sizeflag); case xmm_mode: if (ins->vex.length <= 128) diff --git a/opcodes/i386-gen.c b/opcodes/i386-gen.c index cfc5a7a6172..bb58afcbc06 100644 --- a/opcodes/i386-gen.c +++ b/opcodes/i386-gen.c @@ -380,6 +380,7 @@ static bitfield cpu_flags[] = BITFIELD (RAO_INT), BITFIELD (FRED), BITFIELD (LKGS), + BITFIELD (USER_MSR), BITFIELD (MWAITX), BITFIELD (CLZERO), BITFIELD (OSPKE), @@ -1023,6 +1024,7 @@ process_i386_opcode_modifier (FILE *table, char *mod, unsigned int space, SPACE(0F3A), SPACE(EVEXMAP5), SPACE(EVEXMAP6), + SPACE(VEXMAP7), SPACE(XOP08), SPACE(XOP09), SPACE(XOP0A), diff --git a/opcodes/i386-opc.h b/opcodes/i386-opc.h index 149ae0e950c..529eb7c41c8 100644 --- a/opcodes/i386-opc.h +++ b/opcodes/i386-opc.h @@ -223,6 +223,8 @@ enum i386_cpu CpuFRED, /* lkgs instruction required */ CpuLKGS, + /* Intel USER_MSR Instruction support required. */ + CpuUSER_MSR, /* mwaitx instruction required */ CpuMWAITX, /* Clzero instruction required */ @@ -471,6 +473,7 @@ typedef union i386_cpu_flags unsigned int cpurao_int:1; unsigned int cpufred:1; unsigned int cpulkgs:1; + unsigned int cpuuser_msr:1; unsigned int cpumwaitx:1; unsigned int cpuclzero:1; unsigned int cpuospke:1; @@ -966,6 +969,7 @@ typedef struct insn_template 3: 0F3A opcode prefix / space. 5: EVEXMAP5 opcode prefix / space. 6: EVEXMAP6 opcode prefix / space. + 7: VEXMAP7 opcode prefix / space. 8: XOP 08 opcode space. 9: XOP 09 opcode space. A: XOP 0A opcode space. @@ -976,6 +980,7 @@ typedef struct insn_template #define SPACE_0F3A 3 #define SPACE_EVEXMAP5 5 #define SPACE_EVEXMAP6 6 +#define SPACE_VEXMAP7 7 #define SPACE_XOP08 8 #define SPACE_XOP09 9 #define SPACE_XOP0A 0xA diff --git a/opcodes/i386-opc.tbl b/opcodes/i386-opc.tbl index e60184ba154..a3426298340 100644 --- a/opcodes/i386-opc.tbl +++ b/opcodes/i386-opc.tbl @@ -112,6 +112,8 @@ #define EVexMap5 OpcodeSpace=SPACE_EVEXMAP5 #define EVexMap6 OpcodeSpace=SPACE_EVEXMAP6 +#define VexMap7 OpcodeSpace=SPACE_VEXMAP7 + #define VexW0 VexW=VEXW0 #define VexW1 VexW=VEXW1 #define VexWIG VexW=VEXWIG @@ -3346,3 +3348,12 @@ erets, 0xf20f01ca, FRED|x64, NoSuf, {} eretu, 0xf30f01ca, FRED|x64, NoSuf, {} // FRED instructions end. + +// USER_MSR instructions. + +urdmsr, 0xf20f38f8, USER_MSR|x64, RegMem|NoSuf|NoRex64, { Reg64, Reg64 } +urdmsr, 0xf2f8/0, USER_MSR|x64, Modrm|Vex128|VexMap7|VexW0|NoSuf, { Imm32, Reg64 } +uwrmsr, 0xf30f38f8, USER_MSR|x64, Modrm|NoSuf|NoRex64, { Reg64, Reg64 } +uwrmsr, 0xf3f8/0, USER_MSR|x64, Modrm|Vex128|VexMap7|VexW0|NoSuf, { Reg64, Imm32 } + +// USER_MSR instructions end. -- 2.31.1