The {Q|Q} construct on lgdt/lidt and the slightly different {Q|IQ}
struck me as odd when encountering. Realizing they both have the same
effect, let's free up the I macro by using the former form of construct
where needed (there aren't that many uses overall).
With there now being several multi-character macros also re-do "alt"
handling slightly: Terminate it when finding the closing brace, rather
than after the next single character. Also set the flag only when
actually in Intel syntax mode.
Multiple -M options can be specified in any order. Therefore stright
assignment to fields affected needs to be avoided, such that earlier
options' effects won't be discarded. This was in particular a problem
for -Msuffix followed by certain of the other sub-options.
While updating documentation, take the liberty and also drop the
redundant mentioning of being able to comma-separate multiple options.
There's clearly a shortage of available macro characters, as can be seen
from the various two-character macros that had to be introduced. Don't
waste characters for things that can be expressed differently. In the
case of J this alternative is {l|}.
SYSRET can't use the same macro as IRET, since there's no 16-bit operand
size form of it. Re-use LQ for it instead.
Doing so made obvious that outside of 64-bit mode {,V}CVTSI2S{S,D} and
PTWRITE should have an 'l' suffix printed only in suffix-always mode.
All of data size, rep, lock, and rex prefixes are invalid with VEX- and
alike encoded insns. Make sure they get printed explicitly in all cases,
to signal the anomaly. With this, do away with "rex_ignored" - if there
is a rex prefix, we want to print it anyway for VEX etc (and there's
nothing "ignored" about it in the first place - such an instruction will
raise #UD).
Neither the legacy nor the VEX-encoded forms are permitted with register
operands, just like is already the case for their store forms as well as
{,V}MOV{L,H}PS.
At the same time, besides folding respective vex_len_table[] entries,
adjust adjacent related legacy mod_table[] entries:
- when the prefix was already decoded, PREFIX_OPCODE is pointless,
- limit the amount of string literals by using X consistently on all
{,V}MOV{L,H}P{S,D} forms.
For major opcodes allowing only packed FP kinds of operands, i.e. the
ones where legacy and AVX decoding uses the X macro, we can do so for
AVX512 as well, by attaching to the checking logic the "EVEX.W must
match presence of embedded 66 prefix" rule. (Encodings not following
this general pattern simply may not gain the PREFIX_OPCODE attribute.)
Note that testing of the thus altered decoding has already been put in
place by "x86: correct decoding of packed-FP-only AVX encodings".
This can also be at least partly applied to scalar-FP-only insns (i.e.
V{,U}COMIS{S,D}) as well as the vector-FP forms of insns also allowing
scalar encodings (e.g. VADDP{S,D}).
Take the opportunity and also fix EVEX-encoded VMOVNTP{S,D} as well as
to-memory forms of VMOV{L,H}PS and both forms of VMOV{L,H}PD to wrongly
disassemble with only register operands.
Various AVX insns utilizing the X macro fail to reject F3/F2 embedded
prefix encodings. As the PREFIX_OPCODE attribute wasn't used by any
non-legacy-encoded insns so far, re-use it to achieve the intended
effect.
Since 16-bit addressing isn't allowed, Disp32 needs to be forced; Disp16
fails to match the templates.
The SDM leaves open whether BNDC[LNU] with a GPR operand require an
operand size override; this aspect is therefore left untouched here.
AMD and Intel differ in their handling of far indirect branches as well
as LFS/LGS/LSS: AMD CPUs ignore REX.W while Intel ones honors it. (Note
how the latter three were hybrids so far, while far branches were fully
AMD-like.)
While vendors agree about default operand size (64 bits) and hence
unavilability of a 32-bit form, AMD honors a 16-bit operand size
override (0x66) while Intel doesn't.
movsxd is a 64-bit only instruction. It supports both 16-bit and 32-bit
destination registers. Its AT&T mnemonic is movslq which only supports
64-bit destination register. There is also a discrepancy between AMD64
and Intel64 on movsxd with 16-bit destination register. AMD64 supports
32-bit source operand and Intel64 supports 16-bit source operand.
This patch updates movsxd encoding and decoding to alow 16-bit and 32-bit
destination registers. It also handles movsxd with 16-bit destination
register for AMD64 and Intel 64.
gas/
PR binutils/25445
* config/tc-i386.c (check_long_reg): Also convert to QWORD for
movsxd.
* doc/c-i386.texi: Add a node for AMD64 vs. Intel64 ISA
differences. Document movslq and movsxd.
* testsuite/gas/i386/i386.exp: Run PR binutils/25445 tests.
* testsuite/gas/i386/x86-64-movsxd-intel.d: New file.
* testsuite/gas/i386/x86-64-movsxd-intel64-intel.d: Likewise.
* testsuite/gas/i386/x86-64-movsxd-intel64-inval.l: Likewise.
* testsuite/gas/i386/x86-64-movsxd-intel64-inval.s: Likewise.
* testsuite/gas/i386/x86-64-movsxd-intel64.d: Likewise.
* testsuite/gas/i386/x86-64-movsxd-intel64.s: Likewise.
* testsuite/gas/i386/x86-64-movsxd-inval.l: Likewise.
* testsuite/gas/i386/x86-64-movsxd-inval.s: Likewise.
* testsuite/gas/i386/x86-64-movsxd.d: Likewise.
* testsuite/gas/i386/x86-64-movsxd.s: Likewise.
opcodes/
PR binutils/25445
* i386-dis.c (MOVSXD_Fixup): New function.
(movsxd_mode): New enum.
(x86_64_table): Use MOVSXD_Fixup and movsxd_mode on movsxd.
(intel_operand_size): Handle movsxd_mode.
(OP_E_register): Likewise.
(OP_G): Likewise.
* i386-opc.tbl: Remove Rex64 and allow 32-bit destination
register on movsxd. Add movsxd with 16-bit destination register
for AMD64 and Intel64 ISAs.
* i386-tbl.h: Regenerated.
binutils* objdump.c (visualize_jumps, color_output, extended_color_output)
(detected_jumps): New variables.
(usage): Add the new jump visualization options.
(option_values): Add new option value.
(long_options): Add the new option.
(jump_info_new, jump_info_free): New functions.
(jump_info_min_address, jump_info_max_address): Likewise.
(jump_info_end_address, jump_info_is_start_address): Likewise.
(jump_info_is_end_address, jump_info_size): Likewise.
(jump_info_unlink, jump_info_insert): Likewise.
(jump_info_add_front, jump_info_move_linked): Likewise.
(jump_info_intersect, jump_info_merge): Likewise.
(jump_info_sort, jump_info_visualize_address): Likewise.
(disassemble_jumps): New function - used to locate jumps.
(disassemble_bytes): Add ascii art generation.
(disassemble_section): Add scan to locate jumps.
(main): Parse the new visualization option.
* doc/binutils.texi: Document the new feature.
* NEWS: Mention the new feature.
opcodes * arm-dis.c (print_insn_arm): Fill in insn info fields for control
flow instructions.
(print_insn_thumb16, print_insn_thumb32): Likewise.
(print_insn): Initialize the insn info.
* i386-dis.c (print_insn): Initialize the insn info fields, and
detect jumps.
The disassembler change is such that in default mode we'd disassemble
the insns (for there not ebing any conflicts), but when AMD64 mode was
explicitly requested, we'd show them as "(bad)".
The expectation of x86-64-branch-3 for "call" / "jmp" with an obvious
direct destination to translate to an indirect _far_ branch is plain
wrong. The operand size prefix should have no effect at all on the
interpretation of the operand. The main underlying issue here is that
the Intel64 templates of the direct branches don't include Disp16, yet
various assumptions exist that it would always be there when there's
also Disp32/Disp32S, toggled by the operand size prefix (which is
being ignored by direct branches in Intel64 mode).
Along these lines it was also wrong to base the displacement width
decision solely on the operand size prefix: REX.W cancels this effect
and hence needs taking into consideration, too.
A disassembler change is needed here as well: XBEGIN was wrongly treated
the same as direct CALL/JMP, which isn't the case - the operand size
prefix does affect displacement size there, it's merely ignored when it
comes to updating [ER]IP.
Test also memory operands with operand size specifier, which was broken
prior to dc2be329b9 ("i386: Only check suffix in instruction
mnemonic"), due to the template not permitting any suffixes. Note that
this uncovered a disassembler issue, which is being fixed here as well.
As the comments (here: almost, in the opcode table: fully) correctly
state - all register operands except MONITOR's address one are fixed
at 32 bit size. Don't print 64-bit registers there.
Also adjust x86-64-suffix.d's name such that it wouldn't be identical to
x86-64-rep-suffix.d's, but instead resemble that of its sibling
x86-64-suffix-intel.d.
The original idea looks to have been for names to be composed in the
order that decoding gets done, which helps both reading and modifying
the code. Switch (back) to this model for some of the affected non-
vector insn enumerators.
Just like their AVX counterparts they can utilize XMVexScalar /
EXdVexScalarS / EXqVexScalarS taking care of dropping the middle operand
for their memory forms.
These encodings aren't valid in real and VM86 modes, but they are very
well usable in 16-bit protected mode.
A few adjustments in the disassembler tables are needed where Ev or Gv
were wrongly used. Additionally an adjustment is needed to avoid
printing "addr32" when that's already recognizable by the use of %eiz.
Furthermore the Iq operand template was wrong for XOP:0Ah encoding
insns: They're having a uniform 32-bit immediate. Drop Iq and introduce
Id instead.
Clone a few existing test cases to exercise assembler and disassembler.
I assume this mode was needed when EVEX.W handling wasn't really correct
yet for other than 64-bit mode. It's clearly not needed anymore. Its
elimination also allows dropping the EVEX.W split of VCVT{,U}SI2SS. (For
the record, the dropped mode would have been wrong if used in any table
entry not already guaranteeing EVEX.W=1.)
The only meaningful difference from OP_I() is the handling of the
VEX.W=1 case in 64-bit mode for bytemode being v_mode. Funnel
everything else into OP_I(), and drop no longer needed local
variables.
MOVNTI was wrongly assembled with a 66h prefix. Add IgnoreSize to
address this. It and the scalar to/from integer conversion insns also
were also wrongly using Ev / Gv, leading to 16-bit register names being
printed when 32-bit ones were meant.
Clone the 32-bit SSE2 test to cover both assembler and disassembler.
Break i386-dis-evex.h into small files such that each file is included
just once.
* i386-dis-evex.h: Break into ...
* i386-dis-evex-len.h: New file.
* i386-dis-evex-mod.h: Likewise.
* i386-dis-evex-prefix.h: Likewise.
* i386-dis-evex-reg.h: Likewise.
* i386-dis-evex-w.h: Likewise.
* i386-dis.c: Include i386-dis-evex-reg.h, i386-dis-evex-prefix.h,
i386-dis-evex.h, i386-dis-evex-len.h, i386-dis-evex-w.h and
i386-dis-evex-mod.h.
If VEX.vvvv and EVEX.vvvv are reserved, they must be all 1s, which are
all 0s in inverted form. Add check for unused VEX.vvvv and EVEX.vvvv
when disassembling VEX and EVEX instructions.
gas/
PR binutils/24626
* testsuite/gas/i386/disassem.s: Add tests for reserved VEX.vvvv
and EVEX.vvvv.
* testsuite/gas/i386/x86-64-disassem.s: Likewise.
* testsuite/gas/i386/disassem.d: Updated.
* testsuite/gas/i386/x86-64-disassem.d: Likewise.
opcodes/
PR binutils/24626
* i386-dis.c (print_insn): Check for unused VEX.vvvv and
EVEX.vvvv when disassembling VEX and EVEX instructions.
(OP_VEX): Set vex.register_specifier to 0 after readding
vex.register_specifier.
(OP_Vex_2src_1): Likewise.
(OP_Vex_2src_2): Likewise.
(OP_LWP_E): Likewise.
(OP_EX_Vex): Don't check vex.register_specifier.
(OP_XMM_Vex): Likewise.