x86: derive opcode encoding space attribute from base opcode

Just like is already done for VEX/XOP/EVEX encoded insns, record the
encoding space information in the respective opcode modifier field. Do
this again without changing the source table, but rather by deriving the
values from their existing source representation.
This commit is contained in:
Jan Beulich
2021-03-29 12:02:50 +02:00
parent 63b4cc53dc
commit 389d00a5e5
6 changed files with 1814 additions and 1721 deletions

View File

@ -1,3 +1,26 @@
2021-03-29 Jan Beulich <jbeulich@suse.com>
* config/tc-i386.c (optimize_encoding): Replace VEX-encoding
checks by opcodespace ones.
(insert_lfence_before): Likewise.
(maybe_fused_with_jcc_p): Likewise.
(add_branch_padding_frag_p): Likewise.
(output_disp): Likewise.
(load_insn_p): Re-arrange checks to key applicable ones off of
an opcodespace check.
(md_assemble): Adjust opcode checks.
(check_byte_reg): Likewise.
(process_operands): Likewise.
(i386_index_check): Likewise.
(process_suffix): Likewise. New local variable is_movx. Adjust
movsx/movzx and crc32 handling.
(output_insn): Adjust opcode checks. Drop no longer reachable
case labels. Output legacy encoding prefixes in addition to the
base_opcode byte(s). Rework counting of prefixes for extended
opcode maps.
* config/tc-i386-intel.c (i386_intel_simplify_register): Adjust
opcode checks.
2021-03-29 Alan Modra <amodra@gmail.com> 2021-03-29 Alan Modra <amodra@gmail.com>
* atof-generic.c (FALSE, TRUE): Don't define. * atof-generic.c (FALSE, TRUE): Don't define.

View File

@ -318,9 +318,11 @@ i386_intel_simplify_register (expressionS *e)
if (intel_state.in_scale if (intel_state.in_scale
|| (t->opcode_modifier.opcodeprefix == PREFIX_0XF3 || (t->opcode_modifier.opcodeprefix == PREFIX_0XF3
&& t->base_opcode == 0x0f1b /* bndmk */) && t->opcode_modifier.opcodespace == SPACE_0F
&& t->base_opcode == 0x1b /* bndmk */)
|| (t->opcode_modifier.opcodeprefix == PREFIX_NONE || (t->opcode_modifier.opcodeprefix == PREFIX_NONE
&& (t->base_opcode & ~1) == 0x0f1a /* bnd{ld,st}x */) && t->opcode_modifier.opcodespace == SPACE_0F
&& (t->base_opcode & ~1) == 0x1a /* bnd{ld,st}x */)
|| i386_regtab[reg_num].reg_type.bitfield.baseindex) || i386_regtab[reg_num].reg_type.bitfield.baseindex)
intel_state.index = i386_regtab + reg_num; intel_state.index = i386_regtab + reg_num;
else else

View File

@ -4040,7 +4040,7 @@ optimize_encoding (void)
unsigned int j; unsigned int j;
if (optimize_for_space if (optimize_for_space
&& !is_any_vex_encoding (&i.tm) && i.tm.opcode_modifier.opcodespace == SPACE_BASE
&& i.reg_operands == 1 && i.reg_operands == 1
&& i.imm_operands == 1 && i.imm_operands == 1
&& !i.types[1].bitfield.byte && !i.types[1].bitfield.byte
@ -4072,7 +4072,7 @@ optimize_encoding (void)
} }
} }
else if (flag_code == CODE_64BIT else if (flag_code == CODE_64BIT
&& !is_any_vex_encoding (&i.tm) && i.tm.opcode_modifier.opcodespace == SPACE_BASE
&& ((i.types[1].bitfield.qword && ((i.types[1].bitfield.qword
&& i.reg_operands == 1 && i.reg_operands == 1
&& i.imm_operands == 1 && i.imm_operands == 1
@ -4138,7 +4138,7 @@ optimize_encoding (void)
} }
else if (optimize > 1 else if (optimize > 1
&& !optimize_for_space && !optimize_for_space
&& !is_any_vex_encoding (&i.tm) && i.tm.opcode_modifier.opcodespace == SPACE_BASE
&& i.reg_operands == 2 && i.reg_operands == 2
&& i.op[0].regs == i.op[1].regs && i.op[0].regs == i.op[1].regs
&& ((i.tm.base_opcode & ~(Opcode_D | 1)) == 0x8 && ((i.tm.base_opcode & ~(Opcode_D | 1)) == 0x8
@ -4343,9 +4343,15 @@ load_insn_p (void)
if (i.tm.opcode_modifier.anysize) if (i.tm.opcode_modifier.anysize)
return 0; return 0;
/* pop, popf, popa. */ /* pop. */
if (strcmp (i.tm.name, "pop") == 0 if (strcmp (i.tm.name, "pop") == 0)
|| i.tm.base_opcode == 0x9d return 1;
}
if (i.tm.opcode_modifier.opcodespace == SPACE_BASE)
{
/* popf, popa. */
if (i.tm.base_opcode == 0x9d
|| i.tm.base_opcode == 0x61) || i.tm.base_opcode == 0x61)
return 1; return 1;
@ -4375,7 +4381,7 @@ load_insn_p (void)
&& i.tm.extension_opcode == 2) && i.tm.extension_opcode == 2)
return 1; return 1;
} }
else else if (i.tm.opcode_modifier.opcodespace == SPACE_BASE)
{ {
/* test, not, neg, mul, imul, div, idiv. */ /* test, not, neg, mul, imul, div, idiv. */
if ((i.tm.base_opcode == 0xf6 || i.tm.base_opcode == 0xf7) if ((i.tm.base_opcode == 0xf6 || i.tm.base_opcode == 0xf7)
@ -4390,40 +4396,14 @@ load_insn_p (void)
if (i.tm.base_opcode >= 0x80 && i.tm.base_opcode <= 0x83) if (i.tm.base_opcode >= 0x80 && i.tm.base_opcode <= 0x83)
return 1; return 1;
/* bt, bts, btr, btc. */
if (i.tm.base_opcode == 0xfba
&& (i.tm.extension_opcode >= 4 && i.tm.extension_opcode <= 7))
return 1;
/* rol, ror, rcl, rcr, shl/sal, shr, sar. */ /* rol, ror, rcl, rcr, shl/sal, shr, sar. */
if ((base_opcode == 0xc1 if ((base_opcode == 0xc1
|| (i.tm.base_opcode >= 0xd0 && i.tm.base_opcode <= 0xd3)) || (i.tm.base_opcode >= 0xd0 && i.tm.base_opcode <= 0xd3))
&& i.tm.extension_opcode != 6) && i.tm.extension_opcode != 6)
return 1; return 1;
/* cmpxchg8b, cmpxchg16b, xrstors, vmptrld. */
if (i.tm.base_opcode == 0xfc7
&& i.tm.opcode_modifier.opcodeprefix == PREFIX_NONE
&& (i.tm.extension_opcode == 1 || i.tm.extension_opcode == 3
|| i.tm.extension_opcode == 6))
return 1;
/* fxrstor, ldmxcsr, xrstor. */
if (i.tm.base_opcode == 0xfae
&& (i.tm.extension_opcode == 1
|| i.tm.extension_opcode == 2
|| i.tm.extension_opcode == 5))
return 1;
/* lgdt, lidt, lmsw. */
if (i.tm.base_opcode == 0xf01
&& (i.tm.extension_opcode == 2
|| i.tm.extension_opcode == 3
|| i.tm.extension_opcode == 6))
return 1;
/* Check for x87 instructions. */ /* Check for x87 instructions. */
if (i.tm.base_opcode >= 0xd8 && i.tm.base_opcode <= 0xdf) if (base_opcode >= 0xd8 && base_opcode <= 0xdf)
{ {
/* Skip fst, fstp, fstenv, fstcw. */ /* Skip fst, fstp, fstenv, fstcw. */
if (i.tm.base_opcode == 0xd9 if (i.tm.base_opcode == 0xd9
@ -4462,6 +4442,34 @@ load_insn_p (void)
return 1; return 1;
} }
} }
else if (i.tm.opcode_modifier.opcodespace == SPACE_0F)
{
/* bt, bts, btr, btc. */
if (i.tm.base_opcode == 0xba
&& (i.tm.extension_opcode >= 4 && i.tm.extension_opcode <= 7))
return 1;
/* cmpxchg8b, cmpxchg16b, xrstors, vmptrld. */
if (i.tm.base_opcode == 0xc7
&& i.tm.opcode_modifier.opcodeprefix == PREFIX_NONE
&& (i.tm.extension_opcode == 1 || i.tm.extension_opcode == 3
|| i.tm.extension_opcode == 6))
return 1;
/* fxrstor, ldmxcsr, xrstor. */
if (i.tm.base_opcode == 0xae
&& (i.tm.extension_opcode == 1
|| i.tm.extension_opcode == 2
|| i.tm.extension_opcode == 5))
return 1;
/* lgdt, lidt, lmsw. */
if (i.tm.base_opcode == 0x01
&& (i.tm.extension_opcode == 2
|| i.tm.extension_opcode == 3
|| i.tm.extension_opcode == 6))
return 1;
}
dest = i.operands - 1; dest = i.operands - 1;
@ -4471,8 +4479,8 @@ load_insn_p (void)
&& i.types[dest].bitfield.imm8) && i.types[dest].bitfield.imm8)
dest--; dest--;
/* add, or, adc, sbb, and, sub, xor, cmp, test, xchg, xadd */ /* add, or, adc, sbb, and, sub, xor, cmp, test, xchg. */
if (!any_vex_p if (i.tm.opcode_modifier.opcodespace == SPACE_BASE
&& (base_opcode == 0x1 && (base_opcode == 0x1
|| base_opcode == 0x9 || base_opcode == 0x9
|| base_opcode == 0x11 || base_opcode == 0x11
@ -4481,8 +4489,12 @@ load_insn_p (void)
|| base_opcode == 0x29 || base_opcode == 0x29
|| base_opcode == 0x31 || base_opcode == 0x31
|| base_opcode == 0x39 || base_opcode == 0x39
|| (i.tm.base_opcode >= 0x84 && i.tm.base_opcode <= 0x87) || (base_opcode | 2) == 0x87))
|| base_opcode == 0xfc1)) return 1;
/* xadd. */
if (i.tm.opcode_modifier.opcodespace == SPACE_0F
&& base_opcode == 0xc1)
return 1; return 1;
/* Check for load instruction. */ /* Check for load instruction. */
@ -4527,7 +4539,7 @@ insert_lfence_before (void)
{ {
char *p; char *p;
if (is_any_vex_encoding (&i.tm)) if (i.tm.opcode_modifier.opcodespace != SPACE_BASE)
return; return;
if (i.tm.base_opcode == 0xff if (i.tm.base_opcode == 0xff
@ -4908,7 +4920,8 @@ md_assemble (char *line)
/* Handle conversion of 'int $3' --> special int3 insn. XOP or FMA4 /* Handle conversion of 'int $3' --> special int3 insn. XOP or FMA4
instructions may define INT_OPCODE as well, so avoid this corner instructions may define INT_OPCODE as well, so avoid this corner
case for those instructions that use MODRM. */ case for those instructions that use MODRM. */
if (i.tm.base_opcode == INT_OPCODE if (i.tm.opcode_modifier.opcodespace == SPACE_BASE
&& i.tm.base_opcode == INT_OPCODE
&& !i.tm.opcode_modifier.modrm && !i.tm.opcode_modifier.modrm
&& i.op[0].imms->X_add_number == 3) && i.op[0].imms->X_add_number == 3)
{ {
@ -6289,7 +6302,8 @@ match_template (char mnem_suffix)
j = i.imm_operands + (t->operands > i.imm_operands + 1); j = i.imm_operands + (t->operands > i.imm_operands + 1);
if (((i.suffix == QWORD_MNEM_SUFFIX if (((i.suffix == QWORD_MNEM_SUFFIX
&& flag_code != CODE_64BIT && flag_code != CODE_64BIT
&& !(t->base_opcode == 0xfc7 && !(t->opcode_modifier.opcodespace == SPACE_0F
&& t->base_opcode == 0xc7
&& t->opcode_modifier.opcodeprefix == PREFIX_NONE && t->opcode_modifier.opcodeprefix == PREFIX_NONE
&& t->extension_opcode == 1) /* cmpxchg8b */) && t->extension_opcode == 1) /* cmpxchg8b */)
|| (i.suffix == LONG_MNEM_SUFFIX || (i.suffix == LONG_MNEM_SUFFIX
@ -6740,7 +6754,7 @@ check_string (void)
static int static int
process_suffix (void) process_suffix (void)
{ {
bfd_boolean is_crc32 = FALSE; bfd_boolean is_crc32 = FALSE, is_movx = FALSE;
/* If matched instruction specifies an explicit instruction mnemonic /* If matched instruction specifies an explicit instruction mnemonic
suffix, use it. */ suffix, use it. */
@ -6755,17 +6769,23 @@ process_suffix (void)
&& !i.tm.opcode_modifier.addrprefixopreg) && !i.tm.opcode_modifier.addrprefixopreg)
{ {
unsigned int numop = i.operands; unsigned int numop = i.operands;
/* MOVSX/MOVZX */
is_movx = (i.tm.opcode_modifier.opcodespace == SPACE_0F
&& (i.tm.base_opcode | 8) == 0xbe)
|| (i.tm.opcode_modifier.opcodespace == SPACE_BASE
&& i.tm.base_opcode == 0x63
&& i.tm.cpu_flags.bitfield.cpu64);
/* CRC32 */ /* CRC32 */
is_crc32 = (i.tm.base_opcode == 0xf38f0 is_crc32 = (i.tm.base_opcode == 0xf0
&& i.tm.opcode_modifier.opcodespace == SPACE_0F38
&& i.tm.opcode_modifier.opcodeprefix == PREFIX_0XF2); && i.tm.opcode_modifier.opcodeprefix == PREFIX_0XF2);
/* movsx/movzx want only their source operand considered here, for the /* movsx/movzx want only their source operand considered here, for the
ambiguity checking below. The suffix will be replaced afterwards ambiguity checking below. The suffix will be replaced afterwards
to represent the destination (register). */ to represent the destination (register). */
if (((i.tm.base_opcode | 8) == 0xfbe && i.tm.opcode_modifier.w) if (is_movx && (i.tm.opcode_modifier.w || i.tm.base_opcode == 0x63))
|| (i.tm.base_opcode == 0x63
&& i.tm.opcode_modifier.opcodespace == SPACE_BASE
&& i.tm.cpu_flags.bitfield.cpu64))
--i.operands; --i.operands;
/* crc32 needs REX.W set regardless of suffix / source operand size. */ /* crc32 needs REX.W set regardless of suffix / source operand size. */
@ -6803,8 +6823,7 @@ process_suffix (void)
/* As an exception, movsx/movzx silently default to a byte source /* As an exception, movsx/movzx silently default to a byte source
in AT&T mode. */ in AT&T mode. */
if ((i.tm.base_opcode | 8) == 0xfbe && i.tm.opcode_modifier.w if (is_movx && i.tm.opcode_modifier.w && !i.suffix && !intel_syntax)
&& !i.suffix && !intel_syntax)
i.suffix = BYTE_MNEM_SUFFIX; i.suffix = BYTE_MNEM_SUFFIX;
} }
else if (i.suffix == BYTE_MNEM_SUFFIX) else if (i.suffix == BYTE_MNEM_SUFFIX)
@ -6883,7 +6902,8 @@ process_suffix (void)
&& (i.tm.opcode_modifier.jump == JUMP_ABSOLUTE && (i.tm.opcode_modifier.jump == JUMP_ABSOLUTE
|| i.tm.opcode_modifier.jump == JUMP_BYTE || i.tm.opcode_modifier.jump == JUMP_BYTE
|| i.tm.opcode_modifier.jump == JUMP_INTERSEGMENT || i.tm.opcode_modifier.jump == JUMP_INTERSEGMENT
|| (i.tm.base_opcode == 0x0f01 /* [ls][gi]dt */ || (i.tm.opcode_modifier.opcodespace == SPACE_0F
&& i.tm.base_opcode == 0x01 /* [ls][gi]dt */
&& i.tm.extension_opcode <= 3))) && i.tm.extension_opcode <= 3)))
{ {
switch (flag_code) switch (flag_code)
@ -7011,10 +7031,7 @@ process_suffix (void)
if (i.tm.opcode_modifier.floatmf) if (i.tm.opcode_modifier.floatmf)
i.suffix = SHORT_MNEM_SUFFIX; i.suffix = SHORT_MNEM_SUFFIX;
else if ((i.tm.base_opcode | 8) == 0xfbe else if (is_movx)
|| (i.tm.base_opcode == 0x63
&& i.tm.opcode_modifier.opcodespace == SPACE_BASE
&& i.tm.cpu_flags.bitfield.cpu64))
/* handled below */; /* handled below */;
else if (evex) else if (evex)
i.tm.opcode_modifier.evex = evex; i.tm.opcode_modifier.evex = evex;
@ -7027,10 +7044,7 @@ process_suffix (void)
} }
} }
if ((i.tm.base_opcode | 8) == 0xfbe if (is_movx)
|| (i.tm.base_opcode == 0x63
&& i.tm.opcode_modifier.opcodespace == SPACE_BASE
&& i.tm.cpu_flags.bitfield.cpu64))
{ {
/* In Intel syntax, movsx/movzx must have a "suffix" (checked above). /* In Intel syntax, movsx/movzx must have a "suffix" (checked above).
In AT&T syntax, if there is no suffix (warned about above), the default In AT&T syntax, if there is no suffix (warned about above), the default
@ -7252,7 +7266,8 @@ check_byte_reg (void)
continue; continue;
/* crc32 only wants its source operand checked here. */ /* crc32 only wants its source operand checked here. */
if (i.tm.base_opcode == 0xf38f0 if (i.tm.base_opcode == 0xf0
&& i.tm.opcode_modifier.opcodespace == SPACE_0F38
&& i.tm.opcode_modifier.opcodeprefix == PREFIX_0XF2 && i.tm.opcode_modifier.opcodeprefix == PREFIX_0XF2
&& op != 0) && op != 0)
continue; continue;
@ -7678,21 +7693,23 @@ process_operands (void)
if (flag_code != CODE_64BIT if (flag_code != CODE_64BIT
? i.tm.base_opcode == POP_SEG_SHORT ? i.tm.base_opcode == POP_SEG_SHORT
&& i.op[0].regs->reg_num == 1 && i.op[0].regs->reg_num == 1
: (i.tm.base_opcode | 1) == POP_SEG386_SHORT : (i.tm.base_opcode | 1) == (POP_SEG386_SHORT & 0xff)
&& i.op[0].regs->reg_num < 4) && i.op[0].regs->reg_num < 4)
{ {
as_bad (_("you can't `%s %s%s'"), as_bad (_("you can't `%s %s%s'"),
i.tm.name, register_prefix, i.op[0].regs->reg_name); i.tm.name, register_prefix, i.op[0].regs->reg_name);
return 0; return 0;
} }
if ( i.op[0].regs->reg_num > 3 && i.opcode_length == 1 ) if (i.op[0].regs->reg_num > 3
&& i.tm.opcode_modifier.opcodespace == SPACE_BASE )
{ {
i.tm.base_opcode ^= POP_SEG_SHORT ^ POP_SEG386_SHORT; i.tm.base_opcode ^= (POP_SEG_SHORT ^ POP_SEG386_SHORT) & 0xff;
i.opcode_length = 2; i.tm.opcode_modifier.opcodespace = SPACE_0F;
} }
i.tm.base_opcode |= (i.op[0].regs->reg_num << 3); i.tm.base_opcode |= (i.op[0].regs->reg_num << 3);
} }
else if ((i.tm.base_opcode & ~0x3) == MOV_AX_DISP32) else if (i.tm.opcode_modifier.opcodespace == SPACE_BASE
&& (i.tm.base_opcode & ~3) == MOV_AX_DISP32)
{ {
default_seg = &ds; default_seg = &ds;
} }
@ -8949,8 +8966,8 @@ maybe_fused_with_jcc_p (enum mf_cmp_kind* mf_cmp_p)
if (i.base_reg && i.base_reg->reg_num == RegIP) if (i.base_reg && i.base_reg->reg_num == RegIP)
return 0; return 0;
/* No VEX/EVEX encoding. */ /* No opcodes outside of base encoding space. */
if (is_any_vex_encoding (&i.tm)) if (i.tm.opcode_modifier.opcodespace != SPACE_BASE)
return 0; return 0;
/* add, sub without add/sub m, imm. */ /* add, sub without add/sub m, imm. */
@ -9073,7 +9090,8 @@ add_branch_padding_frag_p (enum align_branch_kind *branch_p,
/* NB: Don't work with COND_JUMP86 without i386. */ /* NB: Don't work with COND_JUMP86 without i386. */
if (!align_branch_power if (!align_branch_power
|| now_seg == absolute_section || now_seg == absolute_section
|| !cpu_arch_flags.bitfield.cpui386) || !cpu_arch_flags.bitfield.cpui386
|| i.tm.opcode_modifier.opcodespace != SPACE_BASE)
return 0; return 0;
add_padding = 0; add_padding = 0;
@ -9096,8 +9114,6 @@ add_branch_padding_frag_p (enum align_branch_kind *branch_p,
add_padding = 1; add_padding = 1;
} }
} }
else if (is_any_vex_encoding (&i.tm))
return 0;
else if ((i.tm.base_opcode | 1) == 0xc3) else if ((i.tm.base_opcode | 1) == 0xc3)
{ {
/* Near ret. */ /* Near ret. */
@ -9181,8 +9197,10 @@ output_insn (void)
x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_X87; x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_X87;
if ((i.xstate & xstate_mmx) if ((i.xstate & xstate_mmx)
|| i.tm.base_opcode == 0xf77 /* emms */ || (i.tm.opcode_modifier.opcodespace == SPACE_0F
|| i.tm.base_opcode == 0xf0e /* femms */) && !is_any_vex_encoding (&i.tm)
&& (i.tm.base_opcode == 0x77 /* emms */
|| i.tm.base_opcode == 0x0e /* femms */)))
x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_MMX; x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_MMX;
if (i.index_reg) if (i.index_reg)
@ -9200,10 +9218,10 @@ output_insn (void)
i.xstate |= xstate_ymm; i.xstate |= xstate_ymm;
if ((i.xstate & xstate_xmm) if ((i.xstate & xstate_xmm)
/* ldmxcsr / stmxcsr */ /* ldmxcsr / stmxcsr / vldmxcsr / vstmxcsr */
|| (i.tm.base_opcode == 0xfae && i.tm.cpu_flags.bitfield.cpusse) || (i.tm.base_opcode == 0xae
/* vldmxcsr / vstmxcsr */ && (i.tm.cpu_flags.bitfield.cpusse
|| (i.tm.base_opcode == 0xae && i.tm.cpu_flags.bitfield.cpuavx) || i.tm.cpu_flags.bitfield.cpuavx))
|| i.tm.cpu_flags.bitfield.cpuwidekl || i.tm.cpu_flags.bitfield.cpuwidekl
|| i.tm.cpu_flags.bitfield.cpukl) || i.tm.cpu_flags.bitfield.cpukl)
x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_XMM; x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_XMM;
@ -9226,7 +9244,8 @@ output_insn (void)
if (x86_feature_2_used if (x86_feature_2_used
|| i.tm.cpu_flags.bitfield.cpucmov || i.tm.cpu_flags.bitfield.cpucmov
|| i.tm.cpu_flags.bitfield.cpusyscall || i.tm.cpu_flags.bitfield.cpusyscall
|| (i.tm.base_opcode == 0xfc7 || (i.tm.opcode_modifier.opcodespace == SPACE_0F
&& i.tm.base_opcode == 0xc7
&& i.tm.opcode_modifier.opcodeprefix == PREFIX_NONE && i.tm.opcode_modifier.opcodeprefix == PREFIX_NONE
&& i.tm.extension_opcode == 1) /* cmpxchg8b */) && i.tm.extension_opcode == 1) /* cmpxchg8b */)
x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_BASELINE; x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_BASELINE;
@ -9327,9 +9346,9 @@ output_insn (void)
enum mf_cmp_kind mf_cmp; enum mf_cmp_kind mf_cmp;
if (avoid_fence if (avoid_fence
&& (i.tm.base_opcode == 0xfaee8 && (i.tm.base_opcode == 0xaee8
|| i.tm.base_opcode == 0xfaef0 || i.tm.base_opcode == 0xaef0
|| i.tm.base_opcode == 0xfaef8)) || i.tm.base_opcode == 0xaef8))
{ {
/* Encode lfence, mfence, and sfence as /* Encode lfence, mfence, and sfence as
f0 83 04 24 00 lock addl $0x0, (%{re}sp). */ f0 83 04 24 00 lock addl $0x0, (%{re}sp). */
@ -9411,7 +9430,6 @@ output_insn (void)
case PREFIX_NONE: case PREFIX_NONE:
switch (i.opcode_length) switch (i.opcode_length)
{ {
case 3:
case 2: case 2:
break; break;
case 1: case 1:
@ -9482,36 +9500,55 @@ output_insn (void)
} }
/* Now the opcode; be careful about word order here! */ /* Now the opcode; be careful about word order here! */
j = i.opcode_length;
if (!i.vex.length)
switch (i.tm.opcode_modifier.opcodespace)
{
case SPACE_BASE:
break;
case SPACE_0F:
++j;
break;
case SPACE_0F38:
case SPACE_0F3A:
j += 2;
break;
default:
abort ();
}
if (now_seg == absolute_section) if (now_seg == absolute_section)
abs_section_offset += i.opcode_length; abs_section_offset += j;
else if (i.opcode_length == 1) else if (j == 1)
{ {
FRAG_APPEND_1_CHAR (i.tm.base_opcode); FRAG_APPEND_1_CHAR (i.tm.base_opcode);
} }
else else
{ {
p = frag_more (j);
if (!i.vex.length
&& i.tm.opcode_modifier.opcodespace != SPACE_BASE)
{
*p++ = 0x0f;
if (i.tm.opcode_modifier.opcodespace != SPACE_0F)
*p++ = i.tm.opcode_modifier.opcodespace == SPACE_0F38
? 0x38 : 0x3a;
}
switch (i.opcode_length) switch (i.opcode_length)
{ {
case 4:
p = frag_more (4);
*p++ = (i.tm.base_opcode >> 24) & 0xff;
*p++ = (i.tm.base_opcode >> 16) & 0xff;
break;
case 3:
p = frag_more (3);
*p++ = (i.tm.base_opcode >> 16) & 0xff;
break;
case 2: case 2:
p = frag_more (2); /* Put out high byte first: can't use md_number_to_chars! */
*p++ = (i.tm.base_opcode >> 8) & 0xff;
/* Fall through. */
case 1:
*p = i.tm.base_opcode & 0xff;
break; break;
default: default:
abort (); abort ();
break; break;
} }
/* Put out high byte first: can't use md_number_to_chars! */
*p++ = (i.tm.base_opcode >> 8) & 0xff;
*p = i.tm.base_opcode & 0xff;
} }
/* Now the modrm byte and sib byte (if present). */ /* Now the modrm byte and sib byte (if present). */
@ -9566,28 +9603,16 @@ output_insn (void)
/* Count prefixes for extended opcode maps. */ /* Count prefixes for extended opcode maps. */
if (!i.vex.length) if (!i.vex.length)
switch (i.opcode_length) switch (i.tm.opcode_modifier.opcodespace)
{ {
case 3: case SPACE_BASE:
if (((i.tm.base_opcode >> 16) & 0xff) == 0xf) break;
{ case SPACE_0F:
count++;
switch ((i.tm.base_opcode >> 8) & 0xff)
{
case 0x38:
case 0x3a:
count++; count++;
break; break;
default: case SPACE_0F38:
break; case SPACE_0F3A:
} count += 2;
}
break;
case 2:
if (((i.tm.base_opcode >> 8) & 0xff) == 0xf)
count++;
break;
case 1:
break; break;
default: default:
abort (); abort ();
@ -9807,7 +9832,7 @@ output_disp (fragS *insn_start_frag, offsetT insn_start_off)
&& i.rm.regmem == 5)) && i.rm.regmem == 5))
&& (i.rm.mode == 2 && (i.rm.mode == 2
|| (i.rm.mode == 0 && i.rm.regmem == 5)) || (i.rm.mode == 0 && i.rm.regmem == 5))
&& !is_any_vex_encoding(&i.tm) && i.tm.opcode_modifier.opcodespace == SPACE_BASE
&& ((i.operands == 1 && ((i.operands == 1
&& i.tm.base_opcode == 0xff && i.tm.base_opcode == 0xff
&& (i.rm.reg == 2 || i.rm.reg == 4)) && (i.rm.reg == 2 || i.rm.reg == 4))
@ -11103,9 +11128,11 @@ i386_index_check (const char *operand_string)
/* bndmk, bndldx, bndstx and mandatory non-vector SIB have special restrictions. */ /* bndmk, bndldx, bndstx and mandatory non-vector SIB have special restrictions. */
if ((t->opcode_modifier.opcodeprefix == PREFIX_0XF3 if ((t->opcode_modifier.opcodeprefix == PREFIX_0XF3
&& t->base_opcode == 0x0f1b) && t->opcode_modifier.opcodespace == SPACE_0F
&& t->base_opcode == 0x1b)
|| (t->opcode_modifier.opcodeprefix == PREFIX_NONE || (t->opcode_modifier.opcodeprefix == PREFIX_NONE
&& (t->base_opcode & ~1) == 0x0f1a) && t->opcode_modifier.opcodespace == SPACE_0F
&& (t->base_opcode & ~1) == 0x1a)
|| t->opcode_modifier.sib == SIBMEM) || t->opcode_modifier.sib == SIBMEM)
{ {
/* They cannot use RIP-relative addressing. */ /* They cannot use RIP-relative addressing. */
@ -11117,7 +11144,8 @@ i386_index_check (const char *operand_string)
/* bndldx and bndstx ignore their scale factor. */ /* bndldx and bndstx ignore their scale factor. */
if (t->opcode_modifier.opcodeprefix == PREFIX_NONE if (t->opcode_modifier.opcodeprefix == PREFIX_NONE
&& (t->base_opcode & ~1) == 0x0f1a && t->opcode_modifier.opcodespace == SPACE_0F
&& (t->base_opcode & ~1) == 0x1a
&& i.log2_scale_factor) && i.log2_scale_factor)
as_warn (_("register scaling is being ignored here")); as_warn (_("register scaling is being ignored here"));
} }

View File

@ -1,3 +1,13 @@
2021-03-29 Jan Beulich <jbeulich@suse.com>
* i386-gen.c (process_i386_opcode_modifier): New parameter
"space".
(output_i386_opcode): New local variable "space". Adjust
process_i386_opcode_modifier() invocation.
(process_i386_opcodes): Adjust process_i386_opcode_modifier()
invocation.
* i386-tbl.h: Re-generate.
2021-03-29 Alan Modra <amodra@gmail.com> 2021-03-29 Alan Modra <amodra@gmail.com>
* aarch64-opc.c (vector_qualifier_p): Simplify boolean expression. * aarch64-opc.c (vector_qualifier_p): Simplify boolean expression.

View File

@ -1176,8 +1176,8 @@ adjust_broadcast_modifier (char **opnd)
} }
static void static void
process_i386_opcode_modifier (FILE *table, char *mod, unsigned int prefix, process_i386_opcode_modifier (FILE *table, char *mod, unsigned int space,
char **opnd, int lineno) unsigned int prefix, char **opnd, int lineno)
{ {
char *str, *next, *last; char *str, *next, *last;
bitfield modifiers [ARRAY_SIZE (opcode_modifiers)]; bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
@ -1220,6 +1220,19 @@ process_i386_opcode_modifier (FILE *table, char *mod, unsigned int prefix,
} }
} }
if (space)
{
if (!modifiers[OpcodeSpace].value)
modifiers[OpcodeSpace].value = space;
else if (modifiers[OpcodeSpace].value != space)
fail (_("%s:%d: Conflicting opcode space specifications\n"),
filename, lineno);
else
fprintf (stderr,
_("%s:%d: Warning: redundant opcode space specification\n"),
filename, lineno);
}
if (prefix) if (prefix)
{ {
if (!modifiers[OpcodePrefix].value) if (!modifiers[OpcodePrefix].value)
@ -1355,7 +1368,7 @@ static void
output_i386_opcode (FILE *table, const char *name, char *str, output_i386_opcode (FILE *table, const char *name, char *str,
char *last, int lineno) char *last, int lineno)
{ {
unsigned int i, length, prefix = 0; unsigned int i, length, prefix = 0, space = 0;
char *base_opcode, *extension_opcode, *end; char *base_opcode, *extension_opcode, *end;
char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS]; char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
unsigned long int opcode; unsigned long int opcode;
@ -1427,10 +1440,27 @@ output_i386_opcode (FILE *table, const char *name, char *str,
opcode &= (1UL << (8 * --length)) - 1; opcode &= (1UL << (8 * --length)) - 1;
} }
/* Transform opcode space encoded in the opcode into opcode modifier
representation. */
if (length > 1 && (opcode >> (8 * length - 8)) == 0xf)
{
switch ((opcode >> (8 * length - 16)) & 0xff)
{
default: space = SPACE_0F; break;
case 0x38: space = SPACE_0F38; break;
case 0x3A: space = SPACE_0F3A; break;
}
if (space != SPACE_0F && --length == 1)
fail (_("%s:%d: %s: unrecognized opcode encoding space\n"),
filename, lineno, name);
opcode &= (1UL << (8 * --length)) - 1;
}
fprintf (table, " { \"%s\", 0x%0*lx%s, %s, %lu,\n", fprintf (table, " { \"%s\", 0x%0*lx%s, %s, %lu,\n",
name, 2 * (int)length, opcode, end, extension_opcode, i); name, 2 * (int)length, opcode, end, extension_opcode, i);
process_i386_opcode_modifier (table, opcode_modifier, prefix, process_i386_opcode_modifier (table, opcode_modifier, space, prefix,
operand_types, lineno); operand_types, lineno);
process_i386_cpu_flag (table, cpu_flags, 0, ",", " ", lineno); process_i386_cpu_flag (table, cpu_flags, 0, ",", " ", lineno);
@ -1822,7 +1852,7 @@ process_i386_opcodes (FILE *table)
fprintf (table, " { NULL, 0, 0, 0,\n"); fprintf (table, " { NULL, 0, 0, 0,\n");
process_i386_opcode_modifier (table, "0", 0, NULL, -1); process_i386_opcode_modifier (table, "0", 0, 0, NULL, -1);
process_i386_cpu_flag (table, "0", 0, ",", " ", -1); process_i386_cpu_flag (table, "0", 0, ",", " ", -1);

File diff suppressed because it is too large Load Diff