@c -*-texinfo-*-

@node disassembler
@section Machine code disassemblers
All disassemblers provided here use the same method of signalling
undefined/invalid opcodes. The following procedure can be used to
guard against such errors:

@deffn Procedure invalid-opcode? obj
When an invalid opcode is encountered an exception with the
@code{&invalid-opcode} condition is raised. Use @code{invalid-opcode?}
to guard against it.
@end deffn

The disassemblers take an argument that is called a @emph{collector}.
It is either @code{#f} or a procedure of the following form:
@code{(lambda (tag . bytes) body)}. The tag is specific to the
architecture, but the bytes are the bytes forming the instruction.
The procedure is used to tell the caller what function each byte of
an instruction performs. This works best for architectures that use
variable-length instructions. For most instruction there will be
multiple calls to the collector.

@menu
* disassembler m68hc12::  Freescale 68HC12 disassembler
* disassembler mips::     MIPS II disassembler
* disassembler x86::      Intel x86-16/32/64 disassembler
@end menu

@c ======================================================================
@node disassembler m68hc12
@subsection Freescale 68HC12 disassembler
The @code{(weinholt disassembler m68hc12)} library provides a
disassembler for the Freescale 68HC12 architecture (formerly Motorola
68HC12 and sometimes called 68HCS12, HC12 or CPU12). It is a 16-bit
architecture used in microcontrollers.

@deffn Procedure get-instruction binary-input-port collector
Reads one instruction from the @var{binary-input-port} and returns it
in symbolic form. For a description of the @var{collector},
@pxref{disassembler}.

@example
(import (weinholt disassembler m68hc12))
(get-instruction (open-bytevector-input-port
                  #vu8(#x18 #x01 #xAE #x00 #x00))
                 #f)
@result{} (movw (0) (pre- 2 sp))
@end example
@end deffn

@noindent
Version history:
@itemize
@item
@code{(1 0)} -- Initial version.
@end itemize

@c ======================================================================
@node disassembler mips
@subsection MIPS II disassembler
The @code{(weinholt disassembler mips)} library provides a
disassembler for most 32-bit MIPS II instructions. MIPS is a RISC
architecture and all instructions have the same length.

@deffn Procedure get-instruction binary-input-port endianness collector
Disassembles one instruction from the @var{binary-input-port} and
returns it in symbolic form. The @var{endianness} specifies if
instructions are read in big or little endianness. For a description
of the @var{collector}, @pxref{disassembler}.

@example
(import (weinholt disassembler mips))
(get-instruction (open-bytevector-input-port
                  #vu8(#x10 #x40 #x00 #x02))
                 (endianness big)
                 #f)
@result{} (beq $v0 $zero ($pc 8))
@end example
@end deffn

@noindent
Version history:
@itemize
@item
@code{(1 0)} -- Initial version.
@end itemize

@c ======================================================================
@node disassembler x86
@subsection Intel x86-16/32/64 disassembler
The @code{(weinholt disassembler x86)} library is a disassembler for
the Intel x86 architecture. It supports 16-bit, 32-bit and 64-bit
modes as well as most modern instruction encodings, including the VEX
prefix used by Intel AVX.

The disassembler does not keep track of the instruction pointer, so
relative offsets are returned as they appear in the instruction
encoding. If you wish to show the destination for branches, or the
actual offset for AMD64's RIP-relative addressing, you will need to
compute the offset yourself.

@deffn Procedure get-instruction binary-input-port mode collector
Reads a single instruction from the given @var{binary-input-port}. The
@var{mode} is one of 16, 32 or 64 (which roughly correspond to real,
protected and long mode).

The @var{collector} is either @code{#f} or a procedure that takes a
symbolic tag and a variable number of bytes. The tag is one of the
symbols @code{modr/m}, @code{sib}, @code{disp}, @code{immediate},
@code{/is4}, @code{prefix} and @code{opcode}. The x86 instruction set
uses variable length instructions (of up to 15 bytes) and the
@var{collector} procedure can be used to find out the type of data
each byte of an instruction contains.

@c TODO: should probably document the format of the returned
@c instructions
The returned instructions have the same operand order as Intel's
documentation uses, i.e.@: the left operand is the destination.

@example
(import (weinholt disassembler x86))
(get-instruction (open-bytevector-input-port
                  #vu8(#x69 #x6c #x6c #x65 #x01 #x00 #x00 #x00))
                 64 #f)
@result{} (imul ebp (mem32+ rsp 101 (* rbp 2)) 1)
@end example
@example
(get-instruction (open-bytevector-input-port
                  #vu8(196 227 113 72 194 49))
                 64 (lambda x (display x) (newline)))
@print{} (prefix 196 227 113)
@print{} (opcode 72)
@print{} (modr/m 194)
@print{} (/is4 49)
@result{} (vpermiltd2ps xmm0 xmm1 xmm2 xmm3)
@end example
@example
(get-instruction (open-bytevector-input-port #vu8(#xEB #x20)) 
                 64 #f)
@result{} (jmp (+ rip 32))
@end example
@end deffn

@noindent
Version history:
@itemize
@item
@code{(1 0)} -- Initial version.
@end itemize


@c ======================================================================
@c @node disassembler x86-opcodes
@c @subsection Intel x86 opcode table
@c An opcode table for the Intel x86 that includes all SSE instructions
@c up to SSE5, all Intel AVX instructions and of course the AMD64
@c instructions. The table layout is designed for use with a
@c disassembler, but it can also be transformed for use in an assembler.
