since this mail is not short, first the motivation:
Nicer disassembler output, shorter source code, smaller core.
There is a FIXME in "src/compiler/x86[-64]/insts.lisp" at the
instruction definition of LOCK: "It would be better to make the
disassembler understand the prefix as part of the instructions...".
This is addressed herewith, but I didn't want to do it in the same way
as REX etc. are currently treated, as that would have meant to double
the number of printer clauses of all relevant instructions again (making
that eight for CMPXCHG on x86-64, for example). So instead I changed the
prefix implementation which allows both to make the disassembly of LOCK
and other prefixes look nicer, but also to treat REX and #x66 better
so that the already existing combinatorial explosion in the number of
printer clauses can be imploded back.
This removes much redundancy from the source code, cutting some 300
lines from "x86-64/insts.lisp", and reduces the core size by nearly
200 KB on x86-64 (and a little bit on x86, too).
Here are examples of the disassembler output changes:
; 156: 64 FS-SEGMENT-PREFIX
; 157: 892D5C000000 MOV [#x5C], EBP
; 156: 64892D5C000000 FS: MOV [#x5C], EBP
; 9B: F0 LOCK
; 9C: 480FB171F9 CMPXCHG [RCX-7], RSI
; 9B: F0480FB171F9 LOCK CMPXCHG [RCX-7], RSI
The patch consists of several commits -- I wanted to separate the
logically distinct steps. Please feel free to combine any of them.
Please see the commit messages for the details.
Apart from that, I'd like to mention:
The way instructions are marked as prefixes (by using NIL as the printer
expression) I took from a remark in the sources. To use the PRINT-NAME
to distinguish between visible and invisible prefixes seemed simple and
natural. There was already some support in MAP-SEGMENT-INSTRUCTIONS to
deal with prefixes which I only extended and made functional.
I didn't find a nice place to document how prefix instructions can be
defined -- DEFINE-INSTRUCTION, where it would fit, was completely
undocumented which discouraged me. Sorry.
I have tried to make things work also when the instruction alignment is
larger than one byte but could not test that.
AFAIK it is customary to have the segment override prefixes print
with a colon appended, but for the other prefixes I don't like that.
This can easily be changed.
The second commit (make some disassembler parameters work) I did purely
because I saw the comments at the parameter's definitions and because
it was easy to include the functionality while touching the relevant
functions anyway. There is still SET-DISASSEM-PARAMS from CMUCL
commented out, so there is currently no nice way to set them; one
parameter is not even exported from its package. I don't know if anyone
wants to have this functionality -- the commit can also be left out.
On the assembler side the LOCK prefix is already a prefix while REP is
a standalone instruction. I have left REP as is for no special reason;
it can be made an assembler prefix anytime later -- when LOCK was made
an assembler prefix in 220.127.116.11, Nikodemus wrote that this seemed
necessary if the instruction scheduler was ever to be used on x86oids
and to support a peephole optimizer.
Finally, not to conceal a disadvantage: The disassembler becomes more
liberal with the patch such that it will happily consume/print actually
illegal numbers, orders, combinations and repetitions of prefixes, too.
My apologies to Alastair Bridgewater who added the #x66-versions of
the instruction printers to the x86 port -- they become completely