target/i386: add core of new i386 decoder
commitb3e22b2318afcaff6fe6e0e031dda11d324c8b4a
authorPaolo Bonzini <pbonzini@redhat.com>
Tue, 23 Aug 2022 09:20:55 +0000 (23 11:20 +0200)
committerPaolo Bonzini <pbonzini@redhat.com>
Tue, 18 Oct 2022 11:58:04 +0000 (18 13:58 +0200)
treecfcc4372682f1ac566f87f0296a18b21b8e008a9
parenta61ef762f976e58363efd6124b3a2992a2d0cdca
target/i386: add core of new i386 decoder

The new decoder is based on three principles:

- use mostly table-driven decoding, using tables derived as much as possible
  from the Intel manual.  Centralizing the decode the operands makes it
  more homogeneous, for example all immediates are signed.  All modrm
  handling is in one function, and can be shared between SSE and ALU
  instructions (including XMM<->GPR instructions).  The SSE/AVX decoder
  will also not have duplicated code between the 0F, 0F38 and 0F3A tables.

- keep the code as "non-branchy" as possible.  Generally, the code for
  the new decoder is more verbose, but the control flow is simpler.
  Conditionals are not nested and have small bodies.  All instruction
  groups are resolved even before operands are decoded, and code
  generation is separated as much as possible within small functions
  that only handle one instruction each.

- keep address generation and (for ALU operands) memory loads and writeback
  as much in common code as possible.  All ALU operations for example
  are implemented as T0=f(T0,T1).  For non-ALU instructions,
  read-modify-write memory operations are rare, but registers do not
  have TCGv equivalents: therefore, the common logic sets up pointer
  temporaries with the operands, while load and writeback are handled
  by gvec or by helpers.

These principles make future code review and extensibility simpler, at
the cost of having a relatively large amount of code in the form of this
patch.  Even EVEX should not be _too_ hard to implement (it's just a crazy
large amount of possibilities).

This patch introduces the main decoder flow, and integrates the old
decoder with the new one.  The old decoder takes care of parsing
prefixes and then optionally drops to the new one.  The changes to the
old decoder are minimal and allow it to be replaced incrementally with
the new one.

There is a debugging mechanism through a "LIMIT" environment variable.
In user-mode emulation, the variable is the number of instructions
decoded by the new decoder before permanently switching to the old one.
In system emulation, the variable is the highest opcode that is decoded
by the new decoder (this is less friendly, but it's the best that can
be done without requiring deterministic execution).

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
target/i386/tcg/decode-new.c.inc [new file with mode: 0644]
target/i386/tcg/decode-new.h [new file with mode: 0644]
target/i386/tcg/emit.c.inc [new file with mode: 0644]
target/i386/tcg/translate.c