aboutsummaryrefslogtreecommitdiff
path: root/gas/config
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2017-05-22 11:02:46 -0700
committerH.J. Lu <hjl.tools@gmail.com>2017-05-22 11:02:58 -0700
commit04ef582ace91cad765d056cc95624478e0421144 (patch)
treece513249defa49cae554a37f0f532d696a6e788a /gas/config
parent25f94347373b1b6f4bfc79eeb38e79d383195779 (diff)
downloadgdb-04ef582ace91cad765d056cc95624478e0421144.zip
gdb-04ef582ace91cad765d056cc95624478e0421144.tar.gz
gdb-04ef582ace91cad765d056cc95624478e0421144.tar.bz2
x86: Add NOTRACK prefix support
For register indirect branches, NOTRACK prefix (0x3e), which is also the DS segment register prefix, can be used to ignore the CET indirect branch track. gas/ * config/tc-i386.c (REX_PREFIX): Changed to 7. (NOTRACK_PREFIX): New. (MAX_PREFIXES): Changed to 8. (_i386_insn): Add notrack_prefix. (PREFIX_GROUP): Add PREFIX_DS. (add_prefix): Return PREFIX_DS for DS_PREFIX_OPCODE. (md_assemble): Check if NOTRACK prefix is supported. (parse_insn): Set notrack_prefix and issue an error for other prefixes after NOTRACK prefix. * testsuite/gas/i386/i386.exp: Run tests for NOTRACK prefix. * testsuite/gas/i386/notrack-intel.d: New file. * testsuite/gas/i386/notrack.d: Likewise. * testsuite/gas/i386/notrack.s: Likewise. * testsuite/gas/i386/notrackbad.l: Likewise. * testsuite/gas/i386/notrackbad.s: Likewise. * testsuite/gas/i386/x86-64-notrack-intel.d: Likewise. * testsuite/gas/i386/x86-64-notrack.d: Likewise. * testsuite/gas/i386/x86-64-notrack.s: Likewise. * testsuite/gas/i386/x86-64-notrackbad.l: Likewise. * testsuite/gas/i386/x86-64-notrackbad.s: Likewise. include/ * include/opcode/i386.h (NOTRACK_PREFIX_OPCODE): New. opcodes/ * i386-dis.c (NOTRACK_Fixup): New. (NOTRACK): Likewise. (NOTRACK_PREFIX): Likewise. (last_active_prefix): Likewise. (reg_table): Use NOTRACK on indirect call and jmp. (ckprefix): Set last_active_prefix. (prefix_name): Return "notrack" for NOTRACK_PREFIX. * i386-gen.c (opcode_modifiers): Add NoTrackPrefixOk. * i386-opc.h (NoTrackPrefixOk): New. (i386_opcode_modifier): Add notrackprefixok. * i386-opc.tbl: Add NoTrackPrefixOk to indirect call and jmp. Add notrack. * i386-tbl.h: Regenerated.
Diffstat (limited to 'gas/config')
-rw-r--r--gas/config/tc-i386.c75
1 files changed, 58 insertions, 17 deletions
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 6250793..6c1091e 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -66,8 +66,11 @@
#define HLE_PREFIX REP_PREFIX
#define BND_PREFIX REP_PREFIX
#define LOCK_PREFIX 5
-#define REX_PREFIX 6 /* must come last. */
-#define MAX_PREFIXES 7 /* max prefixes per opcode */
+/* Only one of NOTRACK_PREFIX and SEG_PREFIX can be used at the same
+ time. */
+#define NOTRACK_PREFIX 6
+#define REX_PREFIX 7 /* must come last. */
+#define MAX_PREFIXES 8 /* max prefixes per opcode */
/* we define the syntax here (modulo base,index,scale syntax) */
#define REGISTER_PREFIX '%'
@@ -388,6 +391,9 @@ struct _i386_insn
/* Have BND prefix. */
const char *bnd_prefix;
+ /* Have NOTRACK prefix. */
+ const char *notrack_prefix;
+
/* Error message. */
enum i386_error error;
};
@@ -2144,6 +2150,7 @@ enum PREFIX_GROUP
PREFIX_EXIST = 0,
PREFIX_LOCK,
PREFIX_REP,
+ PREFIX_DS,
PREFIX_OTHER
};
@@ -2152,7 +2159,8 @@ enum PREFIX_GROUP
same class already exists.
b. PREFIX_LOCK if lock prefix is added.
c. PREFIX_REP if rep/repne prefix is added.
- d. PREFIX_OTHER if other prefix is added.
+ d. PREFIX_DS if ds prefix is added.
+ e. PREFIX_OTHER if other prefix is added.
*/
static enum PREFIX_GROUP
@@ -2177,8 +2185,10 @@ add_prefix (unsigned int prefix)
default:
abort ();
- case CS_PREFIX_OPCODE:
case DS_PREFIX_OPCODE:
+ ret = PREFIX_DS;
+ /* Fall through. */
+ case CS_PREFIX_OPCODE:
case ES_PREFIX_OPCODE:
case FS_PREFIX_OPCODE:
case GS_PREFIX_OPCODE:
@@ -3702,6 +3712,15 @@ md_assemble (char *line)
if (i.bnd_prefix && !i.tm.opcode_modifier.bndprefixok)
as_bad (_("expecting valid branch instruction after `bnd'"));
+ /* Check NOTRACK prefix. */
+ if (i.notrack_prefix
+ && (!i.tm.opcode_modifier.notrackprefixok
+ || i.reg_operands != 1
+ || i.disp_operands != 0
+ || i.mem_operands != 0
+ || i.imm_operands != 0))
+ as_bad (_("expecting register indirect branch instruction after `notrack'"));
+
if (i.tm.cpu_flags.bitfield.cpumpx)
{
if (flag_code == CODE_64BIT && i.prefix[ADDR_PREFIX])
@@ -3964,20 +3983,42 @@ parse_insn (char *line, char *mnemonic)
else
{
/* Add prefix, checking for repeated prefixes. */
- switch (add_prefix (current_templates->start->base_opcode))
+ enum PREFIX_GROUP p
+ = add_prefix (current_templates->start->base_opcode);
+ if (p == PREFIX_DS
+ && current_templates->start->cpu_flags.bitfield.cpucet)
{
- case PREFIX_EXIST:
- return NULL;
- case PREFIX_REP:
- if (current_templates->start->cpu_flags.bitfield.cpuhle)
- i.hle_prefix = current_templates->start->name;
- else if (current_templates->start->cpu_flags.bitfield.cpumpx)
- i.bnd_prefix = current_templates->start->name;
- else
- i.rep_prefix = current_templates->start->name;
- break;
- default:
- break;
+ i.notrack_prefix = current_templates->start->name;
+ /* Move NOTRACK_PREFIX_OPCODE to NOTRACK_PREFIX slot so
+ that it is placed before others. */
+ i.prefix[SEG_PREFIX] = 0;
+ i.prefix[NOTRACK_PREFIX] = NOTRACK_PREFIX_OPCODE;
+ }
+ else
+ {
+ switch (p)
+ {
+ case PREFIX_EXIST:
+ return NULL;
+ case PREFIX_REP:
+ if (current_templates->start->cpu_flags.bitfield.cpuhle)
+ i.hle_prefix = current_templates->start->name;
+ else if (current_templates->start->cpu_flags.bitfield.cpumpx)
+ i.bnd_prefix = current_templates->start->name;
+ else
+ i.rep_prefix = current_templates->start->name;
+ break;
+ default:
+ break;
+ }
+
+ if (i.notrack_prefix != NULL)
+ {
+ /* There must be no other prefixes after NOTRACK
+ prefix. */
+ as_bad (_("expecting no other prefixes after `notrack'"));
+ return NULL;
+ }
}
}
/* Skip past PREFIX_SEPARATOR and reset token_start. */