mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-22 19:09:31 +08:00
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:
@ -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>
|
||||
|
||||
* atof-generic.c (FALSE, TRUE): Don't define.
|
||||
|
@ -318,9 +318,11 @@ i386_intel_simplify_register (expressionS *e)
|
||||
|
||||
if (intel_state.in_scale
|
||||
|| (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->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)
|
||||
intel_state.index = i386_regtab + reg_num;
|
||||
else
|
||||
|
@ -4040,7 +4040,7 @@ optimize_encoding (void)
|
||||
unsigned int j;
|
||||
|
||||
if (optimize_for_space
|
||||
&& !is_any_vex_encoding (&i.tm)
|
||||
&& i.tm.opcode_modifier.opcodespace == SPACE_BASE
|
||||
&& i.reg_operands == 1
|
||||
&& i.imm_operands == 1
|
||||
&& !i.types[1].bitfield.byte
|
||||
@ -4072,7 +4072,7 @@ optimize_encoding (void)
|
||||
}
|
||||
}
|
||||
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.reg_operands == 1
|
||||
&& i.imm_operands == 1
|
||||
@ -4138,7 +4138,7 @@ optimize_encoding (void)
|
||||
}
|
||||
else if (optimize > 1
|
||||
&& !optimize_for_space
|
||||
&& !is_any_vex_encoding (&i.tm)
|
||||
&& i.tm.opcode_modifier.opcodespace == SPACE_BASE
|
||||
&& i.reg_operands == 2
|
||||
&& i.op[0].regs == i.op[1].regs
|
||||
&& ((i.tm.base_opcode & ~(Opcode_D | 1)) == 0x8
|
||||
@ -4343,9 +4343,15 @@ load_insn_p (void)
|
||||
if (i.tm.opcode_modifier.anysize)
|
||||
return 0;
|
||||
|
||||
/* pop, popf, popa. */
|
||||
if (strcmp (i.tm.name, "pop") == 0
|
||||
|| i.tm.base_opcode == 0x9d
|
||||
/* pop. */
|
||||
if (strcmp (i.tm.name, "pop") == 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (i.tm.opcode_modifier.opcodespace == SPACE_BASE)
|
||||
{
|
||||
/* popf, popa. */
|
||||
if (i.tm.base_opcode == 0x9d
|
||||
|| i.tm.base_opcode == 0x61)
|
||||
return 1;
|
||||
|
||||
@ -4375,7 +4381,7 @@ load_insn_p (void)
|
||||
&& i.tm.extension_opcode == 2)
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
else if (i.tm.opcode_modifier.opcodespace == SPACE_BASE)
|
||||
{
|
||||
/* test, not, neg, mul, imul, div, idiv. */
|
||||
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)
|
||||
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. */
|
||||
if ((base_opcode == 0xc1
|
||||
|| (i.tm.base_opcode >= 0xd0 && i.tm.base_opcode <= 0xd3))
|
||||
&& i.tm.extension_opcode != 6)
|
||||
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. */
|
||||
if (i.tm.base_opcode >= 0xd8 && i.tm.base_opcode <= 0xdf)
|
||||
if (base_opcode >= 0xd8 && base_opcode <= 0xdf)
|
||||
{
|
||||
/* Skip fst, fstp, fstenv, fstcw. */
|
||||
if (i.tm.base_opcode == 0xd9
|
||||
@ -4462,6 +4442,34 @@ load_insn_p (void)
|
||||
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;
|
||||
|
||||
@ -4471,8 +4479,8 @@ load_insn_p (void)
|
||||
&& i.types[dest].bitfield.imm8)
|
||||
dest--;
|
||||
|
||||
/* add, or, adc, sbb, and, sub, xor, cmp, test, xchg, xadd */
|
||||
if (!any_vex_p
|
||||
/* add, or, adc, sbb, and, sub, xor, cmp, test, xchg. */
|
||||
if (i.tm.opcode_modifier.opcodespace == SPACE_BASE
|
||||
&& (base_opcode == 0x1
|
||||
|| base_opcode == 0x9
|
||||
|| base_opcode == 0x11
|
||||
@ -4481,8 +4489,12 @@ load_insn_p (void)
|
||||
|| base_opcode == 0x29
|
||||
|| base_opcode == 0x31
|
||||
|| base_opcode == 0x39
|
||||
|| (i.tm.base_opcode >= 0x84 && i.tm.base_opcode <= 0x87)
|
||||
|| base_opcode == 0xfc1))
|
||||
|| (base_opcode | 2) == 0x87))
|
||||
return 1;
|
||||
|
||||
/* xadd. */
|
||||
if (i.tm.opcode_modifier.opcodespace == SPACE_0F
|
||||
&& base_opcode == 0xc1)
|
||||
return 1;
|
||||
|
||||
/* Check for load instruction. */
|
||||
@ -4527,7 +4539,7 @@ insert_lfence_before (void)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (is_any_vex_encoding (&i.tm))
|
||||
if (i.tm.opcode_modifier.opcodespace != SPACE_BASE)
|
||||
return;
|
||||
|
||||
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
|
||||
instructions may define INT_OPCODE as well, so avoid this corner
|
||||
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.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);
|
||||
if (((i.suffix == QWORD_MNEM_SUFFIX
|
||||
&& 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->extension_opcode == 1) /* cmpxchg8b */)
|
||||
|| (i.suffix == LONG_MNEM_SUFFIX
|
||||
@ -6740,7 +6754,7 @@ check_string (void)
|
||||
static int
|
||||
process_suffix (void)
|
||||
{
|
||||
bfd_boolean is_crc32 = FALSE;
|
||||
bfd_boolean is_crc32 = FALSE, is_movx = FALSE;
|
||||
|
||||
/* If matched instruction specifies an explicit instruction mnemonic
|
||||
suffix, use it. */
|
||||
@ -6755,17 +6769,23 @@ process_suffix (void)
|
||||
&& !i.tm.opcode_modifier.addrprefixopreg)
|
||||
{
|
||||
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 */
|
||||
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);
|
||||
|
||||
/* movsx/movzx want only their source operand considered here, for the
|
||||
ambiguity checking below. The suffix will be replaced afterwards
|
||||
to represent the destination (register). */
|
||||
if (((i.tm.base_opcode | 8) == 0xfbe && i.tm.opcode_modifier.w)
|
||||
|| (i.tm.base_opcode == 0x63
|
||||
&& i.tm.opcode_modifier.opcodespace == SPACE_BASE
|
||||
&& i.tm.cpu_flags.bitfield.cpu64))
|
||||
if (is_movx && (i.tm.opcode_modifier.w || i.tm.base_opcode == 0x63))
|
||||
--i.operands;
|
||||
|
||||
/* 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
|
||||
in AT&T mode. */
|
||||
if ((i.tm.base_opcode | 8) == 0xfbe && i.tm.opcode_modifier.w
|
||||
&& !i.suffix && !intel_syntax)
|
||||
if (is_movx && i.tm.opcode_modifier.w && !i.suffix && !intel_syntax)
|
||||
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_BYTE
|
||||
|| 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)))
|
||||
{
|
||||
switch (flag_code)
|
||||
@ -7011,10 +7031,7 @@ process_suffix (void)
|
||||
|
||||
if (i.tm.opcode_modifier.floatmf)
|
||||
i.suffix = SHORT_MNEM_SUFFIX;
|
||||
else if ((i.tm.base_opcode | 8) == 0xfbe
|
||||
|| (i.tm.base_opcode == 0x63
|
||||
&& i.tm.opcode_modifier.opcodespace == SPACE_BASE
|
||||
&& i.tm.cpu_flags.bitfield.cpu64))
|
||||
else if (is_movx)
|
||||
/* handled below */;
|
||||
else if (evex)
|
||||
i.tm.opcode_modifier.evex = evex;
|
||||
@ -7027,10 +7044,7 @@ process_suffix (void)
|
||||
}
|
||||
}
|
||||
|
||||
if ((i.tm.base_opcode | 8) == 0xfbe
|
||||
|| (i.tm.base_opcode == 0x63
|
||||
&& i.tm.opcode_modifier.opcodespace == SPACE_BASE
|
||||
&& i.tm.cpu_flags.bitfield.cpu64))
|
||||
if (is_movx)
|
||||
{
|
||||
/* 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
|
||||
@ -7252,7 +7266,8 @@ check_byte_reg (void)
|
||||
continue;
|
||||
|
||||
/* 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
|
||||
&& op != 0)
|
||||
continue;
|
||||
@ -7678,21 +7693,23 @@ process_operands (void)
|
||||
if (flag_code != CODE_64BIT
|
||||
? i.tm.base_opcode == POP_SEG_SHORT
|
||||
&& 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)
|
||||
{
|
||||
as_bad (_("you can't `%s %s%s'"),
|
||||
i.tm.name, register_prefix, i.op[0].regs->reg_name);
|
||||
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.opcode_length = 2;
|
||||
i.tm.base_opcode ^= (POP_SEG_SHORT ^ POP_SEG386_SHORT) & 0xff;
|
||||
i.tm.opcode_modifier.opcodespace = SPACE_0F;
|
||||
}
|
||||
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;
|
||||
}
|
||||
@ -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)
|
||||
return 0;
|
||||
|
||||
/* No VEX/EVEX encoding. */
|
||||
if (is_any_vex_encoding (&i.tm))
|
||||
/* No opcodes outside of base encoding space. */
|
||||
if (i.tm.opcode_modifier.opcodespace != SPACE_BASE)
|
||||
return 0;
|
||||
|
||||
/* 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. */
|
||||
if (!align_branch_power
|
||||
|| now_seg == absolute_section
|
||||
|| !cpu_arch_flags.bitfield.cpui386)
|
||||
|| !cpu_arch_flags.bitfield.cpui386
|
||||
|| i.tm.opcode_modifier.opcodespace != SPACE_BASE)
|
||||
return 0;
|
||||
|
||||
add_padding = 0;
|
||||
@ -9096,8 +9114,6 @@ add_branch_padding_frag_p (enum align_branch_kind *branch_p,
|
||||
add_padding = 1;
|
||||
}
|
||||
}
|
||||
else if (is_any_vex_encoding (&i.tm))
|
||||
return 0;
|
||||
else if ((i.tm.base_opcode | 1) == 0xc3)
|
||||
{
|
||||
/* Near ret. */
|
||||
@ -9181,8 +9197,10 @@ output_insn (void)
|
||||
x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_X87;
|
||||
|
||||
if ((i.xstate & xstate_mmx)
|
||||
|| i.tm.base_opcode == 0xf77 /* emms */
|
||||
|| i.tm.base_opcode == 0xf0e /* femms */)
|
||||
|| (i.tm.opcode_modifier.opcodespace == SPACE_0F
|
||||
&& !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;
|
||||
|
||||
if (i.index_reg)
|
||||
@ -9200,10 +9218,10 @@ output_insn (void)
|
||||
i.xstate |= xstate_ymm;
|
||||
|
||||
if ((i.xstate & xstate_xmm)
|
||||
/* ldmxcsr / stmxcsr */
|
||||
|| (i.tm.base_opcode == 0xfae && i.tm.cpu_flags.bitfield.cpusse)
|
||||
/* vldmxcsr / vstmxcsr */
|
||||
|| (i.tm.base_opcode == 0xae && i.tm.cpu_flags.bitfield.cpuavx)
|
||||
/* ldmxcsr / stmxcsr / vldmxcsr / vstmxcsr */
|
||||
|| (i.tm.base_opcode == 0xae
|
||||
&& (i.tm.cpu_flags.bitfield.cpusse
|
||||
|| i.tm.cpu_flags.bitfield.cpuavx))
|
||||
|| i.tm.cpu_flags.bitfield.cpuwidekl
|
||||
|| i.tm.cpu_flags.bitfield.cpukl)
|
||||
x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_XMM;
|
||||
@ -9226,7 +9244,8 @@ output_insn (void)
|
||||
if (x86_feature_2_used
|
||||
|| i.tm.cpu_flags.bitfield.cpucmov
|
||||
|| 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.extension_opcode == 1) /* cmpxchg8b */)
|
||||
x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_BASELINE;
|
||||
@ -9327,9 +9346,9 @@ output_insn (void)
|
||||
enum mf_cmp_kind mf_cmp;
|
||||
|
||||
if (avoid_fence
|
||||
&& (i.tm.base_opcode == 0xfaee8
|
||||
|| i.tm.base_opcode == 0xfaef0
|
||||
|| i.tm.base_opcode == 0xfaef8))
|
||||
&& (i.tm.base_opcode == 0xaee8
|
||||
|| i.tm.base_opcode == 0xaef0
|
||||
|| i.tm.base_opcode == 0xaef8))
|
||||
{
|
||||
/* Encode lfence, mfence, and sfence as
|
||||
f0 83 04 24 00 lock addl $0x0, (%{re}sp). */
|
||||
@ -9411,7 +9430,6 @@ output_insn (void)
|
||||
case PREFIX_NONE:
|
||||
switch (i.opcode_length)
|
||||
{
|
||||
case 3:
|
||||
case 2:
|
||||
break;
|
||||
case 1:
|
||||
@ -9482,36 +9500,55 @@ output_insn (void)
|
||||
}
|
||||
|
||||
/* 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)
|
||||
abs_section_offset += i.opcode_length;
|
||||
else if (i.opcode_length == 1)
|
||||
abs_section_offset += j;
|
||||
else if (j == 1)
|
||||
{
|
||||
FRAG_APPEND_1_CHAR (i.tm.base_opcode);
|
||||
}
|
||||
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)
|
||||
{
|
||||
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:
|
||||
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;
|
||||
default:
|
||||
abort ();
|
||||
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). */
|
||||
@ -9566,28 +9603,16 @@ output_insn (void)
|
||||
|
||||
/* Count prefixes for extended opcode maps. */
|
||||
if (!i.vex.length)
|
||||
switch (i.opcode_length)
|
||||
switch (i.tm.opcode_modifier.opcodespace)
|
||||
{
|
||||
case 3:
|
||||
if (((i.tm.base_opcode >> 16) & 0xff) == 0xf)
|
||||
{
|
||||
count++;
|
||||
switch ((i.tm.base_opcode >> 8) & 0xff)
|
||||
{
|
||||
case 0x38:
|
||||
case 0x3a:
|
||||
count++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
case SPACE_BASE:
|
||||
break;
|
||||
case 2:
|
||||
if (((i.tm.base_opcode >> 8) & 0xff) == 0xf)
|
||||
count++;
|
||||
case SPACE_0F:
|
||||
count++;
|
||||
break;
|
||||
case 1:
|
||||
case SPACE_0F38:
|
||||
case SPACE_0F3A:
|
||||
count += 2;
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
@ -9807,7 +9832,7 @@ output_disp (fragS *insn_start_frag, offsetT insn_start_off)
|
||||
&& i.rm.regmem == 5))
|
||||
&& (i.rm.mode == 2
|
||||
|| (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.tm.base_opcode == 0xff
|
||||
&& (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. */
|
||||
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->base_opcode & ~1) == 0x0f1a)
|
||||
&& t->opcode_modifier.opcodespace == SPACE_0F
|
||||
&& (t->base_opcode & ~1) == 0x1a)
|
||||
|| t->opcode_modifier.sib == SIBMEM)
|
||||
{
|
||||
/* They cannot use RIP-relative addressing. */
|
||||
@ -11117,7 +11144,8 @@ i386_index_check (const char *operand_string)
|
||||
|
||||
/* bndldx and bndstx ignore their scale factor. */
|
||||
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)
|
||||
as_warn (_("register scaling is being ignored here"));
|
||||
}
|
||||
|
@ -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>
|
||||
|
||||
* aarch64-opc.c (vector_qualifier_p): Simplify boolean expression.
|
||||
|
@ -1176,8 +1176,8 @@ adjust_broadcast_modifier (char **opnd)
|
||||
}
|
||||
|
||||
static void
|
||||
process_i386_opcode_modifier (FILE *table, char *mod, unsigned int prefix,
|
||||
char **opnd, int lineno)
|
||||
process_i386_opcode_modifier (FILE *table, char *mod, unsigned int space,
|
||||
unsigned int prefix, char **opnd, int lineno)
|
||||
{
|
||||
char *str, *next, *last;
|
||||
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 (!modifiers[OpcodePrefix].value)
|
||||
@ -1355,7 +1368,7 @@ static void
|
||||
output_i386_opcode (FILE *table, const char *name, char *str,
|
||||
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 *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
|
||||
unsigned long int opcode;
|
||||
@ -1427,10 +1440,27 @@ output_i386_opcode (FILE *table, const char *name, char *str,
|
||||
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",
|
||||
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);
|
||||
|
||||
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");
|
||||
|
||||
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);
|
||||
|
||||
|
3192
opcodes/i386-tbl.h
3192
opcodes/i386-tbl.h
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user