From 28dd57780d6359ed931f70c4017dba0e423fe1e3 Mon Sep 17 00:00:00 2001
From: "Cui,Lili" <lili.cui@intel.com>
Date: Tue, 9 Jun 2020 10:43:39 +0800
Subject: [PATCH] Add support for Intel TDX instructions.

gas/

	* NEWS: Add TDX.
	* config/tc-i386.c (cpu_arch): Add .tdx.
	(cpu_noarch): Likewise.
	* doc/c-i386.texi: Document tdx.
	* testsuite/gas/i386/i386.exp: Run tdx tests.
	* testsuite/gas/i386/tdx.d: Likewise.
	* testsuite/gas/i386/tdx.s: Likewise.
	* testsuite/gas/i386/x86-64-tdx.d: Likewise.
	* testsuite/gas/i386/x86-64-tdx.s: Likewise.

opcodes/

	* i386-dis.c (enum): Add PREFIX_0F01_REG_1_RM_5,
	PREFIX_0F01_REG_1_RM_6, PREFIX_0F01_REG_1_RM_7,
	X86_64_0F01_REG_1_RM_5_P_2, X86_64_0F01_REG_1_RM_6_P_2,
	X86_64_0F01_REG_1_RM_7_P_2.
	(prefix_table): Likewise.
	(x86_64_table): Likewise.
	(rm_table): Likewise.
	* i386-gen.c (cpu_flag_init): Add CPU_TDX_FLAGS
	and CPU_ANY_TDX_FLAGS.
	(cpu_flags): Add CpuTDX.
	* i386-opc.h (enum): Add CpuTDX.
	(i386_cpu_flags): Add cputdx.
	* i386-opc.tbl: Add TDX insns.
	* i386-init.h: Regenerate.
	* i386-tbl.h: Likewise.
---
 gas/NEWS                            |  2 +
 gas/config/tc-i386.c                |  3 ++
 gas/doc/c-i386.texi                 |  3 ++
 gas/testsuite/gas/i386/i386.exp     |  2 +
 gas/testsuite/gas/i386/tdx.d        | 12 ++++++
 gas/testsuite/gas/i386/tdx.s        |  5 +++
 gas/testsuite/gas/i386/x86-64-tdx.d | 15 +++++++
 gas/testsuite/gas/i386/x86-64-tdx.s |  8 ++++
 opcodes/i386-dis.c                  | 65 +++++++++++++++++++++++++++--
 opcodes/i386-gen.c                  |  5 +++
 opcodes/i386-opc.h                  |  3 ++
 opcodes/i386-opc.tbl                |  9 ++++
 12 files changed, 128 insertions(+), 4 deletions(-)
 create mode 100644 gas/testsuite/gas/i386/tdx.d
 create mode 100644 gas/testsuite/gas/i386/tdx.s
 create mode 100644 gas/testsuite/gas/i386/x86-64-tdx.d
 create mode 100644 gas/testsuite/gas/i386/x86-64-tdx.s

diff --git a/gas/NEWS b/gas/NEWS
index d709edf9b5..8c9b925005 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -1,5 +1,7 @@
 -*- text -*-
 
+* Add support for Intel TDX instructions.
+
 * Added a .nop directive to generate a single no-op instruction in a target
   neutral manner.  This instruction does have an effect on DWARF line number
   generation, if that is active.
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index d237352fbe..b7934ba8ee 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -1220,6 +1220,8 @@ static const arch_entry cpu_arch[] =
     CPU_AVX512_BF16_FLAGS, 0 },
   { STRING_COMMA_LEN (".avx512_vp2intersect"), PROCESSOR_UNKNOWN,
     CPU_AVX512_VP2INTERSECT_FLAGS, 0 },
+  { STRING_COMMA_LEN (".tdx"), PROCESSOR_UNKNOWN,
+    CPU_TDX_FLAGS, 0 },
   { STRING_COMMA_LEN (".enqcmd"), PROCESSOR_UNKNOWN,
     CPU_ENQCMD_FLAGS, 0 },
   { STRING_COMMA_LEN (".serialize"), PROCESSOR_UNKNOWN,
@@ -1278,6 +1280,7 @@ static const noarch_entry cpu_noarch[] =
   { STRING_COMMA_LEN ("noavx512_bf16"), CPU_ANY_AVX512_BF16_FLAGS },
   { STRING_COMMA_LEN ("noavx512_vp2intersect"),
     CPU_ANY_AVX512_VP2INTERSECT_FLAGS },
+  { STRING_COMMA_LEN ("notdx"), CPU_ANY_TDX_FLAGS },
   { STRING_COMMA_LEN ("noenqcmd"), CPU_ANY_ENQCMD_FLAGS },
   { STRING_COMMA_LEN ("noserialize"), CPU_ANY_SERIALIZE_FLAGS },
   { STRING_COMMA_LEN ("notsxldtrk"), CPU_ANY_TSXLDTRK_FLAGS },
diff --git a/gas/doc/c-i386.texi b/gas/doc/c-i386.texi
index 64a563aacb..d079c8e3bb 100644
--- a/gas/doc/c-i386.texi
+++ b/gas/doc/c-i386.texi
@@ -205,6 +205,7 @@ accept various extension mnemonics.  For example,
 @code{avx512_vnni},
 @code{avx512_bitalg},
 @code{avx512_vp2intersect},
+@code{tdx},
 @code{avx512_bf16},
 @code{noavx512f},
 @code{noavx512cd},
@@ -222,6 +223,7 @@ accept various extension mnemonics.  For example,
 @code{noavx512_vnni},
 @code{noavx512_bitalg},
 @code{noavx512_vp2intersect},
+@code{notdx},
 @code{noavx512_bf16},
 @code{noenqcmd},
 @code{noserialize},
@@ -1499,6 +1501,7 @@ supported on the CPU specified.  The choices for @var{cpu_type} are:
 @item @samp{.avx512vbmi} @tab @samp{.avx512_4fmaps} @tab @samp{.avx512_4vnniw}
 @item @samp{.avx512_vpopcntdq} @tab @samp{.avx512_vbmi2} @tab @samp{.avx512_vnni}
 @item @samp{.avx512_bitalg} @tab @samp{.avx512_bf16} @tab @samp{.avx512_vp2intersect}
+@item @samp{.tdx}
 @item @samp{.clwb} @tab @samp{.rdpid} @tab @samp{.ptwrite} @tab @item @samp{.ibt}
 @item @samp{.wbnoinvd} @tab @samp{.pconfig} @tab @samp{.waitpkg} @tab @samp{.cldemote}
 @item @samp{.shstk} @tab @samp{.gfni} @tab @samp{.vaes} @tab @samp{.vpclmulqdq}
diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp
index 132e5d7834..285d26e231 100644
--- a/gas/testsuite/gas/i386/i386.exp
+++ b/gas/testsuite/gas/i386/i386.exp
@@ -489,6 +489,7 @@ if [gas_32_check] then {
     run_dump_test "enqcmd-intel"
     run_list_test "enqcmd-inval"
     run_dump_test "serialize"
+    run_dump_test "tdx"
     run_dump_test "tsxldtrk"
     run_dump_test "vp2intersect"
     run_dump_test "vp2intersect-intel"
@@ -1094,6 +1095,7 @@ if [gas_64_check] then {
     run_dump_test "x86-64-enqcmd-intel"
     run_list_test "x86-64-enqcmd-inval"
     run_dump_test "x86-64-serialize"
+    run_dump_test "x86-64-tdx"
     run_dump_test "x86-64-tsxldtrk"
     run_dump_test "x86-64-vp2intersect"
     run_dump_test "x86-64-vp2intersect-intel"
diff --git a/gas/testsuite/gas/i386/tdx.d b/gas/testsuite/gas/i386/tdx.d
new file mode 100644
index 0000000000..35263be397
--- /dev/null
+++ b/gas/testsuite/gas/i386/tdx.d
@@ -0,0 +1,12 @@
+#as:
+#objdump: -dw
+#name: TDX insns
+#source: tdx.s
+
+.*: +file format .*
+
+Disassembly of section \.text:
+
+0+ <_start>:
+[ 	]*[a-f0-9]+:	66 0f 01 cc +	tdcall *
+#pass
diff --git a/gas/testsuite/gas/i386/tdx.s b/gas/testsuite/gas/i386/tdx.s
new file mode 100644
index 0000000000..6097fe3a76
--- /dev/null
+++ b/gas/testsuite/gas/i386/tdx.s
@@ -0,0 +1,5 @@
+# Check TDX instructions.
+
+	.text
+_start:
+	tdcall
diff --git a/gas/testsuite/gas/i386/x86-64-tdx.d b/gas/testsuite/gas/i386/x86-64-tdx.d
new file mode 100644
index 0000000000..ea3e83cde6
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-tdx.d
@@ -0,0 +1,15 @@
+#as:
+#objdump: -dw
+#name: x86_64 TDX insns
+#source: x86-64-tdx.s
+
+.*: +file format .*
+
+Disassembly of section \.text:
+
+0+ <_start>:
+[ 	]*[a-f0-9]+:	66 0f 01 cc +	tdcall *
+[ 	]*[a-f0-9]+:	66 0f 01 cd +	seamret *
+[ 	]*[a-f0-9]+:	66 0f 01 ce +	seamops *
+[ 	]*[a-f0-9]+:	66 0f 01 cf +	seamcall *
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-tdx.s b/gas/testsuite/gas/i386/x86-64-tdx.s
new file mode 100644
index 0000000000..1cf4035475
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-tdx.s
@@ -0,0 +1,8 @@
+# Check TDX instructions.
+
+	.text
+_start:
+	tdcall
+	seamret
+	seamops
+	seamcall
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c
index 6d803258ef..89d8fc64fc 100644
--- a/opcodes/i386-dis.c
+++ b/opcodes/i386-dis.c
@@ -945,6 +945,10 @@ enum
 enum
 {
   PREFIX_90 = 0,
+  PREFIX_0F01_REG_1_RM_4,
+  PREFIX_0F01_REG_1_RM_5,
+  PREFIX_0F01_REG_1_RM_6,
+  PREFIX_0F01_REG_1_RM_7,
   PREFIX_0F01_REG_3_RM_1,
   PREFIX_0F01_REG_5_MOD_0,
   PREFIX_0F01_REG_5_MOD_3_RM_0,
@@ -1161,6 +1165,9 @@ enum
   X86_64_EA,
   X86_64_0F01_REG_0,
   X86_64_0F01_REG_1,
+  X86_64_0F01_REG_1_RM_5_PREFIX_2,
+  X86_64_0F01_REG_1_RM_6_PREFIX_2,
+  X86_64_0F01_REG_1_RM_7_PREFIX_2,
   X86_64_0F01_REG_2,
   X86_64_0F01_REG_3,
   X86_64_0F24,
@@ -3062,6 +3069,38 @@ static const struct dis386 prefix_table[][4] = {
     { NULL, { { NULL, 0 } }, PREFIX_IGNORED }
   },
 
+  /* PREFIX_0F01_REG_1_RM_4 */
+  {
+    { Bad_Opcode },
+    { Bad_Opcode },
+    { "tdcall", 	{ Skip_MODRM }, 0 },
+    { Bad_Opcode },
+  },
+
+  /* PREFIX_0F01_REG_1_RM_5 */
+  {
+    { Bad_Opcode },
+    { Bad_Opcode },
+    { X86_64_TABLE (X86_64_0F01_REG_1_RM_5_PREFIX_2) },
+    { Bad_Opcode },
+  },
+
+  /* PREFIX_0F01_REG_1_RM_6 */
+  {
+    { Bad_Opcode },
+    { Bad_Opcode },
+    { X86_64_TABLE (X86_64_0F01_REG_1_RM_6_PREFIX_2) },
+    { Bad_Opcode },
+  },
+
+  /* PREFIX_0F01_REG_1_RM_7 */
+  {
+    { "encls",		{ Skip_MODRM }, 0 },
+    { Bad_Opcode },
+    { X86_64_TABLE (X86_64_0F01_REG_1_RM_7_PREFIX_2) },
+    { Bad_Opcode },
+  },
+
   /* PREFIX_0F01_REG_3_RM_1 */
   {
     { "vmmcall",	{ Skip_MODRM }, 0 },
@@ -4139,6 +4178,24 @@ static const struct dis386 x86_64_table[][2] = {
     { "sidt", { M }, 0 },
   },
 
+  /* X86_64_0F01_REG_1_RM_5_PREFIX_2 */
+  {
+    { Bad_Opcode },
+    { "seamret",	{ Skip_MODRM }, 0 },
+  },
+
+  /* X86_64_0F01_REG_1_RM_6_PREFIX_2 */
+  {
+    { Bad_Opcode },
+    { "seamops",	{ Skip_MODRM }, 0 },
+  },
+
+  /* X86_64_0F01_REG_1_RM_7_PREFIX_2 */
+  {
+    { Bad_Opcode },
+    { "seamcall",	{ Skip_MODRM }, 0 },
+  },
+
   /* X86_64_0F01_REG_2 */
   {
     { "lgdt{Q|Q}", { M }, 0 },
@@ -8691,10 +8748,10 @@ static const struct dis386 rm_table[][8] = {
     { "mwait",		{ { OP_Mwait, 0 } }, 0 },
     { "clac",		{ Skip_MODRM }, 0 },
     { "stac",		{ Skip_MODRM }, 0 },
-    { Bad_Opcode },
-    { Bad_Opcode },
-    { Bad_Opcode },
-    { "encls",		{ Skip_MODRM }, 0 },
+    { PREFIX_TABLE (PREFIX_0F01_REG_1_RM_4) },
+    { PREFIX_TABLE (PREFIX_0F01_REG_1_RM_5) },
+    { PREFIX_TABLE (PREFIX_0F01_REG_1_RM_6) },
+    { PREFIX_TABLE (PREFIX_0F01_REG_1_RM_7) },
   },
   {
     /* RM_0F01_REG_2 */
diff --git a/opcodes/i386-gen.c b/opcodes/i386-gen.c
index 3334155071..642297518f 100644
--- a/opcodes/i386-gen.c
+++ b/opcodes/i386-gen.c
@@ -313,6 +313,8 @@ static initializer cpu_flag_init[] =
     "CpuSERIALIZE" },
   { "CPU_AVX512_VP2INTERSECT_FLAGS",
     "CpuAVX512_VP2INTERSECT" },
+  { "CPU_TDX_FLAGS",
+    "CpuTDX" },
   { "CPU_RDPRU_FLAGS",
     "CpuRDPRU" },
   { "CPU_MCOMMIT_FLAGS",
@@ -405,6 +407,8 @@ static initializer cpu_flag_init[] =
     "CpuSERIALIZE" },
   { "CPU_ANY_AVX512_VP2INTERSECT_FLAGS",
     "CpuAVX512_VP2INTERSECT" },
+  { "CPU_ANY_TDX_FLAGS",
+    "CpuTDX" },
   { "CPU_ANY_TSXLDTRK_FLAGS",
     "CpuTSXLDTRK" },
 };
@@ -611,6 +615,7 @@ static bitfield cpu_flags[] =
   BITFIELD (CpuAVX512_BITALG),
   BITFIELD (CpuAVX512_BF16),
   BITFIELD (CpuAVX512_VP2INTERSECT),
+  BITFIELD (CpuTDX),
   BITFIELD (CpuMWAITX),
   BITFIELD (CpuCLZERO),
   BITFIELD (CpuOSPKE),
diff --git a/opcodes/i386-opc.h b/opcodes/i386-opc.h
index 09ee615db1..3a2e260ff2 100644
--- a/opcodes/i386-opc.h
+++ b/opcodes/i386-opc.h
@@ -210,6 +210,8 @@ enum
   CpuAVX512_BF16,
   /* Intel AVX-512 VP2INTERSECT Instructions support required.  */
   CpuAVX512_VP2INTERSECT,
+  /* TDX Instructions support required.  */
+  CpuTDX,
   /* mwaitx instruction required */
   CpuMWAITX,
   /* Clzero instruction required */
@@ -371,6 +373,7 @@ typedef union i386_cpu_flags
       unsigned int cpuavx512_bitalg:1;
       unsigned int cpuavx512_bf16:1;
       unsigned int cpuavx512_vp2intersect:1;
+      unsigned int cputdx:1;
       unsigned int cpumwaitx:1;
       unsigned int cpuclzero:1;
       unsigned int cpuospke:1;
diff --git a/opcodes/i386-opc.tbl b/opcodes/i386-opc.tbl
index 181d0df1ce..c51d5ea14d 100644
--- a/opcodes/i386-opc.tbl
+++ b/opcodes/i386-opc.tbl
@@ -4117,3 +4117,12 @@ tilerelease, 0, 0x49c0, None, 2, CpuAMX_TILE|Cpu64, Vex128|VexOpcode=1|VexW0|No_
 tilezero, 1, 0xf249, None, 1, CpuAMX_TILE|Cpu64, Modrm|Vex128|VexOpcode=1|VexW0|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { RegTMM }
 
 // AMX instructions end.
+
+// TDX instructions.
+
+tdcall, 0, 0x660f01cc, None, 3, CpuTDX, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { 0 }
+seamret, 0, 0x660f01cd, None, 3, CpuTDX|Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { 0 }
+seamops, 0, 0x660f01ce, None, 3, CpuTDX|Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { 0 }
+seamcall, 0, 0x660f01cf, None, 3, CpuTDX|Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { 0 }
+
+// TDX instructions end.
-- 
2.17.1

