<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv=Content-Type content="text/html; charset=utf8">
<title>/usr/web/sources/contrib/rsc/8dis.c - Plan 9 from Bell Labs</title>
<!-- THIS FILE IS AUTOMATICALLY GENERATED. -->
<!-- EDIT sources.tr INSTEAD. -->
</meta>
</head>
<body>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: center;">
<span style="font-size: 10pt"><a href="/plan9/">Plan 9 from Bell Labs</a>&rsquo;s /usr/web/sources/contrib/rsc/8dis.c</span></p>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<center><font size=-1>
Copyright © 2009 Alcatel-Lucent.<br />
Distributed under the
<a href="/plan9/license.html">Lucent Public License version 1.02</a>.
<br />
<a href="/plan9/download.html">Download the Plan 9 distribution.</a>
</font>
</center>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<table width="100%" cellspacing=0 border=0><tr><td align="center">
<table cellspacing=0 cellpadding=5 bgcolor="#eeeeff"><tr><td align="left">
<pre>
<!-- END HEADER -->
#include &lt;u.h&gt;
#include &lt;libc.h&gt;
#include &lt;bio.h&gt;
#include &lt;ctype.h&gt;

/*
* hacked i386-specific debugger interface
*/

       /* I386/486 - Disassembler and related functions */

/*
*  an instruction
*/
typedef struct Instr Instr;
struct  Instr
{
       uchar   mem[1+1+1+1+2+1+1+4+4];         /* raw instruction */
       ulong   addr;           /* address of start of instruction */
       int     n;              /* number of bytes in instruction */
       char    *prefix;        /* instr prefix */
       char    *segment;       /* segment override */
       uchar   jumptype;       /* set to the operand type for jump/ret/call */
       uchar   jumploc;
       char    osize;          /* 'W' or 'L' */
       char    asize;          /* address size 'W' or 'L' */
       uchar   mod;            /* bits 6-7 of mod r/m field */
       uchar   reg;            /* bits 3-5 of mod r/m field */
       char    ss;             /* bits 6-7 of SIB */
       char    index;          /* bits 3-5 of SIB */
       char    base;           /* bits 0-2 of SIB */
       short   seg;            /* segment of far address */
       ulong   disp;           /* displacement */
       ulong   imm;            /* immediate */
       ulong   imm2;           /* second immediate operand */
       char    *curr;          /* fill level in output buffer */
       char    *end;           /* end of output buffer */
       char    *err;           /* error message */
};

       /* 386 register (ha!) set */
enum{
       AX=0,
       CX,
       DX,
       BX,
       SP,
       BP,
       SI,
       DI,
};
       /* Operand Format codes */
/*
%A      -       address size register modifier (!asize -&gt; 'E')
%C      -       Control register CR0/CR1/CR2
%D      -       Debug register DR0/DR1/DR2/DR3/DR6/DR7
%I      -       second immediate operand
%O      -       Operand size register modifier (!osize -&gt; 'E')
%T      -       Test register TR6/TR7
%S      -       size code ('W' or 'L')
%X      -       Weird opcode: OSIZE == 'W' =&gt; "CBW"; else =&gt; "CWDE"
%d      -       displacement 16-32 bits
%e      -       effective address - Mod R/M value
%f      -       floating point register F0-F7 - from Mod R/M register
%g      -       segment register
%i      -       immediate operand 8-32 bits
%p      -       PC-relative - signed displacement in immediate field
%r      -       Reg from Mod R/M
%x      -       Weird opcode: OSIZE == 'W' =&gt; "CWD"; else =&gt; "CDQ"
*/

typedef struct Optable Optable;
struct Optable
{
       char    operand[2];
       void    *proto;         /* actually either (char*) or (Optable*) */
};
       /* Operand decoding codes */
enum {
       Ib = 1,                 /* 8-bit immediate - (no sign extension)*/
       Ibs,                    /* 8-bit immediate (sign extended) */
       Jbs,                    /* 8-bit sign-extended immediate in jump or call */
       Iw,                     /* 16-bit immediate -&gt; imm */
       Iw2,                    /* 16-bit immediate -&gt; imm2 */
       Iwd,                    /* Operand-sized immediate (no sign extension)*/
       Awd,                    /* Address offset */
       Iwds,                   /* Operand-sized immediate (sign extended) */
       RM,                     /* Word or long R/M field with register (/r) */
       RMB,                    /* Byte R/M field with register (/r) */
       RMOP,                   /* Word or long R/M field with op code (/digit) */
       RMOPB,                  /* Byte R/M field with op code (/digit) */
       RMR,                    /* R/M register only (mod = 11) */
       RMM,                    /* R/M memory only (mod = 0/1/2) */
       R0,                     /* Base reg of Mod R/M is literal 0x00 */
       R1,                     /* Base reg of Mod R/M is literal 0x01 */
       FRMOP,                  /* Floating point R/M field with opcode */
       FRMEX,                  /* Extended floating point R/M field with opcode */
       JUMP,                   /* Jump or Call flag - no operand */
       RET,                    /* Return flag - no operand */
       OA,                     /* literal 0x0a byte */
       PTR,                    /* Seg:Displacement addr (ptr16:16 or ptr16:32) */
       AUX,                    /* Multi-byte op code - Auxiliary table */
       PRE,                    /* Instr Prefix */
       SEG,                    /* Segment Prefix */
       OPOVER,                 /* Operand size override */
       ADDOVER,                /* Address size override */

       JOUT,
       JBOTH,
};

static Optable optab0F00[8]=
{
[0x00]  0,0,            "MOVW   LDT,%e",
[0x01]  0,0,            "MOVW   TR,%e",
[0x02]  0,0,            "MOVW   %e,LDT",
[0x03]  0,0,            "MOVW   %e,TR",
[0x04]  0,0,            "VERR   %e",
[0x05]  0,0,            "VERW   %e",
};

static Optable optab0F01[8]=
{
[0x00]  0,0,            "MOVL   GDTR,%e",
[0x01]  0,0,            "MOVL   IDTR,%e",
[0x02]  0,0,            "MOVL   %e,GDTR",
[0x03]  0,0,            "MOVL   %e,IDTR",
[0x04]  0,0,            "MOVW   MSW,%e",        /* word */
[0x06]  0,0,            "MOVW   %e,MSW",        /* word */
};

static Optable optab0FBA[8]=
{
[0x04]  Ib,0,           "BT%S   %i,%e",
[0x05]  Ib,0,           "BTS%S  %i,%e",
[0x06]  Ib,0,           "BTR%S  %i,%e",
[0x07]  Ib,0,           "BTC%S  %i,%e",
};

static Optable optab0F[256]=
{
[0x00]  RMOP,0,         optab0F00,
[0x01]  RMOP,0,         optab0F01,
[0x02]  RM,0,           "LAR    %e,%r",
[0x03]  RM,0,           "LSL    %e,%r",
[0x06]  0,0,            "CLTS",
[0x08]  0,0,            "INVD",
[0x09]  0,0,            "WBINVD",
[0x20]  RMR,0,          "MOVL   %C,%e",
[0x21]  RMR,0,          "MOVL   %D,%e",
[0x22]  RMR,0,          "MOVL   %e,%C",
[0x23]  RMR,0,          "MOVL   %e,%D",
[0x24]  RMR,0,          "MOVL   %T,%e",
[0x26]  RMR,0,          "MOVL   %e,%T",
[0x30]  0,0,            "WRMSR",
[0x31]  0,0,            "RDTSC",
[0x32]  0,0,            "RDMSR",
[0x42]  RM,0,           "CMOVC  %e,%r", /* CF */
[0x43]  RM,0,           "CMOVNC %e,%r", /* ¬ CF */
[0x44]  RM,0,           "CMOVZ  %e,%r", /* ZF */
[0x45]  RM,0,           "CMOVNZ %e,%r", /* ¬ ZF */
[0x46]  RM,0,           "CMOVBE %e,%r", /* CF ∨ ZF */
[0x47]  RM,0,           "CMOVA  %e,%r", /* ¬CF ∧ ¬ZF */
[0x48]  RM,0,           "CMOVS  %e,%r", /* SF */
[0x49]  RM,0,           "CMOVNS %e,%r", /* ¬ SF */
[0x4A]  RM,0,           "CMOVP  %e,%r", /* PF */
[0x4B]  RM,0,           "CMOVNP %e,%r", /* ¬ PF */
[0x4C]  RM,0,           "CMOVLT %e,%r", /* LT ≡ OF ≠ SF */
[0x4D]  RM,0,           "CMOVGE %e,%r", /* GE ≡ ZF ∨ SF */
[0x4E]  RM,0,           "CMOVLE %e,%r", /* LE ≡ ZF ∨ LT */
[0x4F]  RM,0,           "CMOVGT %e,%r", /* GT ≡ ¬ZF ∧ GE */
[0x80]  Iwds,JBOTH,             "JOS    %p",
[0x81]  Iwds,JBOTH,             "JOC    %p",
[0x82]  Iwds,JBOTH,             "JCS    %p",
[0x83]  Iwds,JBOTH,             "JCC    %p",
[0x84]  Iwds,JBOTH,             "JEQ    %p",
[0x85]  Iwds,JBOTH,             "JNE    %p",
[0x86]  Iwds,JBOTH,             "JLS    %p",
[0x87]  Iwds,JBOTH,             "JHI    %p",
[0x88]  Iwds,JBOTH,             "JMI    %p",
[0x89]  Iwds,JBOTH,             "JPL    %p",
[0x8a]  Iwds,JBOTH,             "JPS    %p",
[0x8b]  Iwds,JBOTH,             "JPC    %p",
[0x8c]  Iwds,JBOTH,             "JLT    %p",
[0x8d]  Iwds,JBOTH,             "JGE    %p",
[0x8e]  Iwds,JBOTH,             "JLE    %p",
[0x8f]  Iwds,JBOTH,             "JGT    %p",
[0x90]  RMB,0,          "SETOS  %e",
[0x91]  RMB,0,          "SETOC  %e",
[0x92]  RMB,0,          "SETCS  %e",
[0x93]  RMB,0,          "SETCC  %e",
[0x94]  RMB,0,          "SETEQ  %e",
[0x95]  RMB,0,          "SETNE  %e",
[0x96]  RMB,0,          "SETLS  %e",
[0x97]  RMB,0,          "SETHI  %e",
[0x98]  RMB,0,          "SETMI  %e",
[0x99]  RMB,0,          "SETPL  %e",
[0x9a]  RMB,0,          "SETPS  %e",
[0x9b]  RMB,0,          "SETPC  %e",
[0x9c]  RMB,0,          "SETLT  %e",
[0x9d]  RMB,0,          "SETGE  %e",
[0x9e]  RMB,0,          "SETLE  %e",
[0x9f]  RMB,0,          "SETGT  %e",
[0xa0]  0,0,            "PUSHL  FS",
[0xa1]  0,0,            "POPL   FS",
[0xa2]  0,0,            "CPUID",
[0xa3]  RM,0,           "BT%S   %r,%e",
[0xa4]  RM,Ib,          "SHLD%S %r,%i,%e",
[0xa5]  RM,0,           "SHLD%S %r,CL,%e",
[0xa8]  0,0,            "PUSHL  GS",
[0xa9]  0,0,            "POPL   GS",
[0xab]  RM,0,           "BTS%S  %r,%e",
[0xac]  RM,Ib,          "SHRD%S %r,%i,%e",
[0xad]  RM,0,           "SHRD%S %r,CL,%e",
[0xaf]  RM,0,           "IMUL%S %e,%r",
[0xb2]  RMM,0,          "LSS    %e,%r",
[0xb3]  RM,0,           "BTR%S  %r,%e",
[0xb4]  RMM,0,          "LFS    %e,%r",
[0xb5]  RMM,0,          "LGS    %e,%r",
[0xb6]  RMB,0,          "MOVBZX %e,%R",
[0xb7]  RM,0,           "MOVWZX %e,%R",
[0xba]  RMOP,0,         optab0FBA,
[0xbb]  RM,0,           "BTC%S  %e,%r",
[0xbc]  RM,0,           "BSF%S  %e,%r",
[0xbd]  RM,0,           "BSR%S  %e,%r",
[0xbe]  RMB,0,          "MOVBSX %e,%R",
[0xbf]  RM,0,           "MOVWSX %e,%R",
};

static Optable optab80[8]=
{
[0x00]  Ib,0,           "ADDB   %i,%e",
[0x01]  Ib,0,           "ORB    %i,%e",
[0x02]  Ib,0,           "ADCB   %i,%e",
[0x03]  Ib,0,           "SBBB   %i,%e",
[0x04]  Ib,0,           "ANDB   %i,%e",
[0x05]  Ib,0,           "SUBB   %i,%e",
[0x06]  Ib,0,           "XORB   %i,%e",
[0x07]  Ib,0,           "CMPB   %e,%i",
};

static Optable optab81[8]=
{
[0x00]  Iwd,0,          "ADD%S  %i,%e",
[0x01]  Iwd,0,          "OR%S   %i,%e",
[0x02]  Iwd,0,          "ADC%S  %i,%e",
[0x03]  Iwd,0,          "SBB%S  %i,%e",
[0x04]  Iwd,0,          "AND%S  %i,%e",
[0x05]  Iwd,0,          "SUB%S  %i,%e",
[0x06]  Iwd,0,          "XOR%S  %i,%e",
[0x07]  Iwd,0,          "CMP%S  %e,%i",
};

static Optable optab83[8]=
{
[0x00]  Ibs,0,          "ADD%S  %i,%e",
[0x01]  Ibs,0,          "OR%S   %i,%e",
[0x02]  Ibs,0,          "ADC%S  %i,%e",
[0x03]  Ibs,0,          "SBB%S  %i,%e",
[0x04]  Ibs,0,          "AND%S  %i,%e",
[0x05]  Ibs,0,          "SUB%S  %i,%e",
[0x06]  Ibs,0,          "XOR%S  %i,%e",
[0x07]  Ibs,0,          "CMP%S  %e,%i",
};

static Optable optabC0[8] =
{
[0x00]  Ib,0,           "ROLB   %i,%e",
[0x01]  Ib,0,           "RORB   %i,%e",
[0x02]  Ib,0,           "RCLB   %i,%e",
[0x03]  Ib,0,           "RCRB   %i,%e",
[0x04]  Ib,0,           "SHLB   %i,%e",
[0x05]  Ib,0,           "SHRB   %i,%e",
[0x07]  Ib,0,           "SARB   %i,%e",
};

static Optable optabC1[8] =
{
[0x00]  Ib,0,           "ROL%S  %i,%e",
[0x01]  Ib,0,           "ROR%S  %i,%e",
[0x02]  Ib,0,           "RCL%S  %i,%e",
[0x03]  Ib,0,           "RCR%S  %i,%e",
[0x04]  Ib,0,           "SHL%S  %i,%e",
[0x05]  Ib,0,           "SHR%S  %i,%e",
[0x07]  Ib,0,           "SAR%S  %i,%e",
};

static Optable optabD0[8] =
{
[0x00]  0,0,            "ROLB   %e",
[0x01]  0,0,            "RORB   %e",
[0x02]  0,0,            "RCLB   %e",
[0x03]  0,0,            "RCRB   %e",
[0x04]  0,0,            "SHLB   %e",
[0x05]  0,0,            "SHRB   %e",
[0x07]  0,0,            "SARB   %e",
};

static Optable optabD1[8] =
{
[0x00]  0,0,            "ROL%S  %e",
[0x01]  0,0,            "ROR%S  %e",
[0x02]  0,0,            "RCL%S  %e",
[0x03]  0,0,            "RCR%S  %e",
[0x04]  0,0,            "SHL%S  %e",
[0x05]  0,0,            "SHR%S  %e",
[0x07]  0,0,            "SAR%S  %e",
};

static Optable optabD2[8] =
{
[0x00]  0,0,            "ROLB   CL,%e",
[0x01]  0,0,            "RORB   CL,%e",
[0x02]  0,0,            "RCLB   CL,%e",
[0x03]  0,0,            "RCRB   CL,%e",
[0x04]  0,0,            "SHLB   CL,%e",
[0x05]  0,0,            "SHRB   CL,%e",
[0x07]  0,0,            "SARB   CL,%e",
};

static Optable optabD3[8] =
{
[0x00]  0,0,            "ROL%S  CL,%e",
[0x01]  0,0,            "ROR%S  CL,%e",
[0x02]  0,0,            "RCL%S  CL,%e",
[0x03]  0,0,            "RCR%S  CL,%e",
[0x04]  0,0,            "SHL%S  CL,%e",
[0x05]  0,0,            "SHR%S  CL,%e",
[0x07]  0,0,            "SAR%S  CL,%e",
};

static Optable optabD8[8+8] =
{
[0x00]  0,0,            "FADDF  %e,F0",
[0x01]  0,0,            "FMULF  %e,F0",
[0x02]  0,0,            "FCOMF  %e,F0",
[0x03]  0,0,            "FCOMFP %e,F0",
[0x04]  0,0,            "FSUBF  %e,F0",
[0x05]  0,0,            "FSUBRF %e,F0",
[0x06]  0,0,            "FDIVF  %e,F0",
[0x07]  0,0,            "FDIVRF %e,F0",
[0x08]  0,0,            "FADDD  %f,F0",
[0x09]  0,0,            "FMULD  %f,F0",
[0x0a]  0,0,            "FCOMD  %f,F0",
[0x0b]  0,0,            "FCOMPD %f,F0",
[0x0c]  0,0,            "FSUBD  %f,F0",
[0x0d]  0,0,            "FSUBRD %f,F0",
[0x0e]  0,0,            "FDIVD  %f,F0",
[0x0f]  0,0,            "FDIVRD %f,F0",
};
/*
*      optabD9 and optabDB use the following encoding:
*      if (0 &lt;= modrm &lt;= 2) instruction = optabDx[modrm&amp;0x07];
*      else instruction = optabDx[(modrm&amp;0x3f)+8];
*
*      the instructions for MOD == 3, follow the 8 instructions
*      for the other MOD values stored at the front of the table.
*/
static Optable optabD9[64+8] =
{
[0x00]  0,0,            "FMOVF  %e,F0",
[0x02]  0,0,            "FMOVF  F0,%e",
[0x03]  0,0,            "FMOVFP F0,%e",
[0x04]  0,0,            "FLDENV%S %e",
[0x05]  0,0,            "FLDCW  %e",
[0x06]  0,0,            "FSTENV%S %e",
[0x07]  0,0,            "FSTCW  %e",
[0x08]  0,0,            "FMOVD  F0,F0",         /* Mod R/M = 11xx xxxx*/
[0x09]  0,0,            "FMOVD  F1,F0",
[0x0a]  0,0,            "FMOVD  F2,F0",
[0x0b]  0,0,            "FMOVD  F3,F0",
[0x0c]  0,0,            "FMOVD  F4,F0",
[0x0d]  0,0,            "FMOVD  F5,F0",
[0x0e]  0,0,            "FMOVD  F6,F0",
[0x0f]  0,0,            "FMOVD  F7,F0",
[0x10]  0,0,            "FXCHD  F0,F0",
[0x11]  0,0,            "FXCHD  F1,F0",
[0x12]  0,0,            "FXCHD  F2,F0",
[0x13]  0,0,            "FXCHD  F3,F0",
[0x14]  0,0,            "FXCHD  F4,F0",
[0x15]  0,0,            "FXCHD  F5,F0",
[0x16]  0,0,            "FXCHD  F6,F0",
[0x17]  0,0,            "FXCHD  F7,F0",
[0x18]  0,0,            "FNOP",
[0x28]  0,0,            "FCHS",
[0x29]  0,0,            "FABS",
[0x2c]  0,0,            "FTST",
[0x2d]  0,0,            "FXAM",
[0x30]  0,0,            "FLD1",
[0x31]  0,0,            "FLDL2T",
[0x32]  0,0,            "FLDL2E",
[0x33]  0,0,            "FLDPI",
[0x34]  0,0,            "FLDLG2",
[0x35]  0,0,            "FLDLN2",
[0x36]  0,0,            "FLDZ",
[0x38]  0,0,            "F2XM1",
[0x39]  0,0,            "FYL2X",
[0x3a]  0,0,            "FPTAN",
[0x3b]  0,0,            "FPATAN",
[0x3c]  0,0,            "FXTRACT",
[0x3d]  0,0,            "FPREM1",
[0x3e]  0,0,            "FDECSTP",
[0x3f]  0,0,            "FNCSTP",
[0x40]  0,0,            "FPREM",
[0x41]  0,0,            "FYL2XP1",
[0x42]  0,0,            "FSQRT",
[0x43]  0,0,            "FSINCOS",
[0x44]  0,0,            "FRNDINT",
[0x45]  0,0,            "FSCALE",
[0x46]  0,0,            "FSIN",
[0x47]  0,0,            "FCOS",
};

static Optable optabDA[8+8] =
{
[0x00]  0,0,            "FADDL  %e,F0",
[0x01]  0,0,            "FMULL  %e,F0",
[0x02]  0,0,            "FCOML  %e,F0",
[0x03]  0,0,            "FCOMLP %e,F0",
[0x04]  0,0,            "FSUBL  %e,F0",
[0x05]  0,0,            "FSUBRL %e,F0",
[0x06]  0,0,            "FDIVL  %e,F0",
[0x07]  0,0,            "FDIVRL %e,F0",
[0x0d]  R1,0,           "FUCOMPP",
};

static Optable optabDB[8+64] =
{
[0x00]  0,0,            "FMOVL  %e,F0",
[0x02]  0,0,            "FMOVL  F0,%e",
[0x03]  0,0,            "FMOVLP F0,%e",
[0x05]  0,0,            "FMOVX  %e,F0",
[0x07]  0,0,            "FMOVXP F0,%e",
[0x2a]  0,0,            "FCLEX",
[0x2b]  0,0,            "FINIT",
};

static Optable optabDC[8+8] =
{
[0x00]  0,0,            "FADDD  %e,F0",
[0x01]  0,0,            "FMULD  %e,F0",
[0x02]  0,0,            "FCOMD  %e,F0",
[0x03]  0,0,            "FCOMDP %e,F0",
[0x04]  0,0,            "FSUBD  %e,F0",
[0x05]  0,0,            "FSUBRD %e,F0",
[0x06]  0,0,            "FDIVD  %e,F0",
[0x07]  0,0,            "FDIVRD %e,F0",
[0x08]  0,0,            "FADDD  F0,%f",
[0x09]  0,0,            "FMULD  F0,%f",
[0x0c]  0,0,            "FSUBRD F0,%f",
[0x0d]  0,0,            "FSUBD  F0,%f",
[0x0e]  0,0,            "FDIVRD F0,%f",
[0x0f]  0,0,            "FDIVD  F0,%f",
};

static Optable optabDD[8+8] =
{
[0x00]  0,0,            "FMOVD  %e,F0",
[0x02]  0,0,            "FMOVD  F0,%e",
[0x03]  0,0,            "FMOVDP F0,%e",
[0x04]  0,0,            "FRSTOR%S %e",
[0x06]  0,0,            "FSAVE%S %e",
[0x07]  0,0,            "FSTSW  %e",
[0x08]  0,0,            "FFREED %f",
[0x0a]  0,0,            "FMOVD  %f,F0",
[0x0b]  0,0,            "FMOVDP %f,F0",
[0x0c]  0,0,            "FUCOMD %f,F0",
[0x0d]  0,0,            "FUCOMDP %f,F0",
};

static Optable optabDE[8+8] =
{
[0x00]  0,0,            "FADDW  %e,F0",
[0x01]  0,0,            "FMULW  %e,F0",
[0x02]  0,0,            "FCOMW  %e,F0",
[0x03]  0,0,            "FCOMWP %e,F0",
[0x04]  0,0,            "FSUBW  %e,F0",
[0x05]  0,0,            "FSUBRW %e,F0",
[0x06]  0,0,            "FDIVW  %e,F0",
[0x07]  0,0,            "FDIVRW %e,F0",
[0x08]  0,0,            "FADDDP F0,%f",
[0x09]  0,0,            "FMULDP F0,%f",
[0x0b]  R1,0,           "FCOMPDP",
[0x0c]  0,0,            "FSUBRDP F0,%f",
[0x0d]  0,0,            "FSUBDP F0,%f",
[0x0e]  0,0,            "FDIVRDP F0,%f",
[0x0f]  0,0,            "FDIVDP F0,%f",
};

static Optable optabDF[8+8] =
{
[0x00]  0,0,            "FMOVW  %e,F0",
[0x02]  0,0,            "FMOVW  F0,%e",
[0x03]  0,0,            "FMOVWP F0,%e",
[0x04]  0,0,            "FBLD   %e",
[0x05]  0,0,            "FMOVL  %e,F0",
[0x06]  0,0,            "FBSTP  %e",
[0x07]  0,0,            "FMOVLP F0,%e",
[0x0c]  R0,0,           "FSTSW  %OAX",
};

static Optable optabF6[8] =
{
[0x00]  Ib,0,           "TESTB  %i,%e",
[0x02]  0,0,            "NOTB   %e",
[0x03]  0,0,            "NEGB   %e",
[0x04]  0,0,            "MULB   AL,%e",
[0x05]  0,0,            "IMULB  AL,%e",
[0x06]  0,0,            "DIVB   AL,%e",
[0x07]  0,0,            "IDIVB  AL,%e",
};

static Optable optabF7[8] =
{
[0x00]  Iwd,0,          "TEST%S %i,%e",
[0x02]  0,0,            "NOT%S  %e",
[0x03]  0,0,            "NEG%S  %e",
[0x04]  0,0,            "MUL%S  %OAX,%e",
[0x05]  0,0,            "IMUL%S %OAX,%e",
[0x06]  0,0,            "DIV%S  %OAX,%e",
[0x07]  0,0,            "IDIV%S %OAX,%e",
};

static Optable optabFE[8] =
{
[0x00]  0,0,            "INCB   %e",
[0x01]  0,0,            "DECB   %e",
};

static Optable optabFF[8] =
{
[0x00]  0,0,            "INC%S  %e",
[0x01]  0,0,            "DEC%S  %e",
[0x02]  JUMP,0,         "CALL*%S %e",
[0x03]  JUMP,0,         "CALLF*%S %e",
[0x04]  JUMP,0,         "JMP*%S %e",
[0x05]  JUMP,0,         "JMPF*%S %e",
[0x06]  0,0,            "PUSHL  %e",
};

static Optable optable[256] =
{
[0x00]  RMB,0,          "ADDB   %r,%e",
[0x01]  RM,0,           "ADD%S  %r,%e",
[0x02]  RMB,0,          "ADDB   %e,%r",
[0x03]  RM,0,           "ADD%S  %e,%r",
[0x04]  Ib,0,           "ADDB   %i,AL",
[0x05]  Iwd,0,          "ADD%S  %i,%OAX",
[0x06]  0,0,            "PUSHL  ES",
[0x07]  0,0,            "POPL   ES",
[0x08]  RMB,0,          "ORB    %r,%e",
[0x09]  RM,0,           "OR%S   %r,%e",
[0x0a]  RMB,0,          "ORB    %e,%r",
[0x0b]  RM,0,           "OR%S   %e,%r",
[0x0c]  Ib,0,           "ORB    %i,AL",
[0x0d]  Iwd,0,          "OR%S   %i,%OAX",
[0x0e]  0,0,            "PUSHL  CS",
[0x0f]  AUX,0,          optab0F,
[0x10]  RMB,0,          "ADCB   %r,%e",
[0x11]  RM,0,           "ADC%S  %r,%e",
[0x12]  RMB,0,          "ADCB   %e,%r",
[0x13]  RM,0,           "ADC%S  %e,%r",
[0x14]  Ib,0,           "ADCB   %i,AL",
[0x15]  Iwd,0,          "ADC%S  %i,%OAX",
[0x16]  0,0,            "PUSHL  SS",
[0x17]  0,0,            "POPL   SS",
[0x18]  RMB,0,          "SBBB   %r,%e",
[0x19]  RM,0,           "SBB%S  %r,%e",
[0x1a]  RMB,0,          "SBBB   %e,%r",
[0x1b]  RM,0,           "SBB%S  %e,%r",
[0x1c]  Ib,0,           "SBBB   %i,AL",
[0x1d]  Iwd,0,          "SBB%S  %i,%OAX",
[0x1e]  0,0,            "PUSHL  DS",
[0x1f]  0,0,            "POPL   DS",
[0x20]  RMB,0,          "ANDB   %r,%e",
[0x21]  RM,0,           "AND%S  %r,%e",
[0x22]  RMB,0,          "ANDB   %e,%r",
[0x23]  RM,0,           "AND%S  %e,%r",
[0x24]  Ib,0,           "ANDB   %i,AL",
[0x25]  Iwd,0,          "AND%S  %i,%OAX",
[0x26]  SEG,0,          "ES:",
[0x27]  0,0,            "DAA",
[0x28]  RMB,0,          "SUBB   %r,%e",
[0x29]  RM,0,           "SUB%S  %r,%e",
[0x2a]  RMB,0,          "SUBB   %e,%r",
[0x2b]  RM,0,           "SUB%S  %e,%r",
[0x2c]  Ib,0,           "SUBB   %i,AL",
[0x2d]  Iwd,0,          "SUB%S  %i,%OAX",
[0x2e]  SEG,0,          "CS:",
[0x2f]  0,0,            "DAS",
[0x30]  RMB,0,          "XORB   %r,%e",
[0x31]  RM,0,           "XOR%S  %r,%e",
[0x32]  RMB,0,          "XORB   %e,%r",
[0x33]  RM,0,           "XOR%S  %e,%r",
[0x34]  Ib,0,           "XORB   %i,AL",
[0x35]  Iwd,0,          "XOR%S  %i,%OAX",
[0x36]  SEG,0,          "SS:",
[0x37]  0,0,            "AAA",
[0x38]  RMB,0,          "CMPB   %r,%e",
[0x39]  RM,0,           "CMP%S  %r,%e",
[0x3a]  RMB,0,          "CMPB   %e,%r",
[0x3b]  RM,0,           "CMP%S  %e,%r",
[0x3c]  Ib,0,           "CMPB   %i,AL",
[0x3d]  Iwd,0,          "CMP%S  %i,%OAX",
[0x3e]  SEG,0,          "DS:",
[0x3f]  0,0,            "AAS",
[0x40]  0,0,            "INC%S  %OAX",
[0x41]  0,0,            "INC%S  %OCX",
[0x42]  0,0,            "INC%S  %ODX",
[0x43]  0,0,            "INC%S  %OBX",
[0x44]  0,0,            "INC%S  %OSP",
[0x45]  0,0,            "INC%S  %OBP",
[0x46]  0,0,            "INC%S  %OSI",
[0x47]  0,0,            "INC%S  %ODI",
[0x48]  0,0,            "DEC%S  %OAX",
[0x49]  0,0,            "DEC%S  %OCX",
[0x4a]  0,0,            "DEC%S  %ODX",
[0x4b]  0,0,            "DEC%S  %OBX",
[0x4c]  0,0,            "DEC%S  %OSP",
[0x4d]  0,0,            "DEC%S  %OBP",
[0x4e]  0,0,            "DEC%S  %OSI",
[0x4f]  0,0,            "DEC%S  %ODI",
[0x50]  0,0,            "PUSH%S %OAX",
[0x51]  0,0,            "PUSH%S %OCX",
[0x52]  0,0,            "PUSH%S %ODX",
[0x53]  0,0,            "PUSH%S %OBX",
[0x54]  0,0,            "PUSH%S %OSP",
[0x55]  0,0,            "PUSH%S %OBP",
[0x56]  0,0,            "PUSH%S %OSI",
[0x57]  0,0,            "PUSH%S %ODI",
[0x58]  0,0,            "POP%S  %OAX",
[0x59]  0,0,            "POP%S  %OCX",
[0x5a]  0,0,            "POP%S  %ODX",
[0x5b]  0,0,            "POP%S  %OBX",
[0x5c]  0,0,            "POP%S  %OSP",
[0x5d]  0,0,            "POP%S  %OBP",
[0x5e]  0,0,            "POP%S  %OSI",
[0x5f]  0,0,            "POP%S  %ODI",
[0x60]  0,0,            "PUSHA%S",
[0x61]  0,0,            "POPA%S",
[0x62]  RMM,0,          "BOUND  %e,%r",
[0x63]  RM,0,           "ARPL   %r,%e",
[0x64]  SEG,0,          "FS:",
[0x65]  SEG,0,          "GS:",
[0x66]  OPOVER,0,       "",
[0x67]  ADDOVER,0,      "",
[0x68]  Iwd,0,          "PUSH%S %i",
[0x69]  RM,Iwd,         "IMUL%S %e,%i,%r",
[0x6a]  Ib,0,           "PUSH%S %i",
[0x6b]  RM,Ibs,         "IMUL%S %e,%i,%r",
[0x6c]  0,0,            "INSB   DX,(%ODI)",
[0x6d]  0,0,            "INS%S  DX,(%ODI)",
[0x6e]  0,0,            "OUTSB  (%ASI),DX",
[0x6f]  0,0,            "OUTS%S (%ASI),DX",
[0x70]  Jbs,JBOTH,              "JOS    %p",
[0x71]  Jbs,JBOTH,              "JOC    %p",
[0x72]  Jbs,JBOTH,              "JCS    %p",
[0x73]  Jbs,JBOTH,              "JCC    %p",
[0x74]  Jbs,JBOTH,              "JEQ    %p",
[0x75]  Jbs,JBOTH,              "JNE    %p",
[0x76]  Jbs,JBOTH,              "JLS    %p",
[0x77]  Jbs,JBOTH,              "JHI    %p",
[0x78]  Jbs,JBOTH,              "JMI    %p",
[0x79]  Jbs,JBOTH,              "JPL    %p",
[0x7a]  Jbs,JBOTH,              "JPS    %p",
[0x7b]  Jbs,JBOTH,              "JPC    %p",
[0x7c]  Jbs,JBOTH,              "JLT    %p",
[0x7d]  Jbs,JBOTH,              "JGE    %p",
[0x7e]  Jbs,JBOTH,              "JLE    %p",
[0x7f]  Jbs,JBOTH,              "JGT    %p",
[0x80]  RMOPB,0,        optab80,
[0x81]  RMOP,0,         optab81,
[0x83]  RMOP,0,         optab83,
[0x84]  RMB,0,          "TESTB  %r,%e",
[0x85]  RM,0,           "TEST%S %r,%e",
[0x86]  RMB,0,          "XCHGB  %r,%e",
[0x87]  RM,0,           "XCHG%S %r,%e",
[0x88]  RMB,0,          "MOVB   %r,%e",
[0x89]  RM,0,           "MOV%S  %r,%e",
[0x8a]  RMB,0,          "MOVB   %e,%r",
[0x8b]  RM,0,           "MOV%S  %e,%r",
[0x8c]  RM,0,           "MOVW   %g,%e",
[0x8d]  RM,0,           "LEA    %e,%r",
[0x8e]  RM,0,           "MOVW   %e,%g",
[0x8f]  RM,0,           "POP%S  %e",
[0x90]  0,0,            "NOP",
[0x91]  0,0,            "XCHG   %OCX,%OAX",
[0x92]  0,0,            "XCHG   %ODX,%OAX",
[0x93]  0,0,            "XCHG   %OBX,%OAX",
[0x94]  0,0,            "XCHG   %OSP,%OAX",
[0x95]  0,0,            "XCHG   %OBP,%OAX",
[0x96]  0,0,            "XCHG   %OSI,%OAX",
[0x97]  0,0,            "XCHG   %ODI,%OAX",
[0x98]  0,0,            "%X",                   /* miserable CBW or CWDE */
[0x99]  0,0,            "%x",                   /* idiotic CWD or CDQ */
[0x9a]  PTR,JBOTH,              "CALL%S %d",
[0x9b]  0,0,            "WAIT",
[0x9c]  0,0,            "PUSHF",
[0x9d]  0,0,            "POPF",
[0x9e]  0,0,            "SAHF",
[0x9f]  0,0,            "LAHF",
[0xa0]  Awd,0,          "MOVB   %i,AL",
[0xa1]  Awd,0,          "MOV%S  %i,%OAX",
[0xa2]  Awd,0,          "MOVB   AL,%i",
[0xa3]  Awd,0,          "MOV%S  %OAX,%i",
[0xa4]  0,0,            "MOVSB  (%ASI),(%ADI)",
[0xa5]  0,0,            "MOVS%S (%ASI),(%ADI)",
[0xa6]  0,0,            "CMPSB  (%ASI),(%ADI)",
[0xa7]  0,0,            "CMPS%S (%ASI),(%ADI)",
[0xa8]  Ib,0,           "TESTB  %i,AL",
[0xa9]  Iwd,0,          "TEST%S %i,%OAX",
[0xaa]  0,0,            "STOSB  AL,(%ADI)",
[0xab]  0,0,            "STOS%S %OAX,(%ADI)",
[0xac]  0,0,            "LODSB  (%ASI),AL",
[0xad]  0,0,            "LODS%S (%ASI),%OAX",
[0xae]  0,0,            "SCASB  (%ADI),AL",
[0xaf]  0,0,            "SCAS%S (%ADI),%OAX",
[0xb0]  Ib,0,           "MOVB   %i,AL",
[0xb1]  Ib,0,           "MOVB   %i,CL",
[0xb2]  Ib,0,           "MOVB   %i,DL",
[0xb3]  Ib,0,           "MOVB   %i,BL",
[0xb4]  Ib,0,           "MOVB   %i,AH",
[0xb5]  Ib,0,           "MOVB   %i,CH",
[0xb6]  Ib,0,           "MOVB   %i,DH",
[0xb7]  Ib,0,           "MOVB   %i,BH",
[0xb8]  Iwd,0,          "MOV%S  %i,%OAX",
[0xb9]  Iwd,0,          "MOV%S  %i,%OCX",
[0xba]  Iwd,0,          "MOV%S  %i,%ODX",
[0xbb]  Iwd,0,          "MOV%S  %i,%OBX",
[0xbc]  Iwd,0,          "MOV%S  %i,%OSP",
[0xbd]  Iwd,0,          "MOV%S  %i,%OBP",
[0xbe]  Iwd,0,          "MOV%S  %i,%OSI",
[0xbf]  Iwd,0,          "MOV%S  %i,%ODI",
[0xc0]  RMOPB,0,        optabC0,
[0xc1]  RMOP,0,         optabC1,
[0xc2]  Iw,JOUT,                "RET    %i",
[0xc3]  RET,JOUT,               "RET",
[0xc4]  RM,0,           "LES    %e,%r",
[0xc5]  RM,0,           "LDS    %e,%r",
[0xc6]  RMB,Ib,         "MOVB   %i,%e",
[0xc7]  RM,Iwd,         "MOV%S  %i,%e",
[0xc8]  Iw2,Ib,         "ENTER  %i,%I",         /* loony ENTER */
[0xc9]  0,0,            "LEAVE",                /* bizarre LEAVE */
[0xca]  Iw,JOUT,                "RETF   %i",
[0xcb]  RET,JOUT,               "RETF",
[0xcc]  0,0,            "INT    3",
[0xcd]  Ib,0,           "INTB   %i",
[0xce]  0,0,            "INTO",
[0xcf]  JOUT,0,         "IRET",
[0xd0]  RMOPB,0,        optabD0,
[0xd1]  RMOP,0,         optabD1,
[0xd2]  RMOPB,0,        optabD2,
[0xd3]  RMOP,0,         optabD3,
[0xd4]  OA,0,           "AAM",
[0xd5]  OA,0,           "AAD",
[0xd7]  0,0,            "XLAT",
[0xd8]  FRMOP,0,        optabD8,
[0xd9]  FRMEX,0,        optabD9,
[0xda]  FRMOP,0,        optabDA,
[0xdb]  FRMEX,0,        optabDB,
[0xdc]  FRMOP,0,        optabDC,
[0xdd]  FRMOP,0,        optabDD,
[0xde]  FRMOP,0,        optabDE,
[0xdf]  FRMOP,0,        optabDF,
[0xe0]  Jbs,JBOTH,              "LOOPNE %p",
[0xe1]  Jbs,JBOTH,              "LOOPE  %p",
[0xe2]  Jbs,JBOTH,              "LOOP   %p",
[0xe3]  Jbs,JBOTH,              "JCXZ   %p",
[0xe4]  Ib,0,           "INB    %i,AL",
[0xe5]  Ib,0,           "IN%S   %i,%OAX",
[0xe6]  Ib,0,           "OUTB   AL,%i",
[0xe7]  Ib,0,           "OUT%S  %OAX,%i",
[0xe8]  Iwds,JBOTH,             "CALL   %p",
[0xe9]  Iwds,JOUT,              "JMP    %p",
[0xea]  PTR,JOUT,               "JMP    %d",
[0xeb]  Jbs,JOUT,               "JMP    %p",
[0xec]  0,0,            "INB    DX,AL",
[0xed]  0,0,            "IN%S   DX,%OAX",
[0xee]  0,0,            "OUTB   AL,DX",
[0xef]  0,0,            "OUT%S  %OAX,DX",
[0xf0]  PRE,0,          "LOCK",
[0xf2]  PRE,0,          "REPNE",
[0xf3]  PRE,0,          "REP",
[0xf4]  0,0,            "HALT",
[0xf5]  0,0,            "CMC",
[0xf6]  RMOPB,0,        optabF6,
[0xf7]  RMOP,0,         optabF7,
[0xf8]  0,0,            "CLC",
[0xf9]  0,0,            "STC",
[0xfa]  0,0,            "CLI",
[0xfb]  0,0,            "STI",
[0xfc]  0,0,            "CLD",
[0xfd]  0,0,            "STD",
[0xfe]  RMOPB,0,        optabFE,
[0xff]  RMOP,0,         optabFF,
};

char *
_hexify(char *buf, ulong p, int zeros)
{
       ulong d;

       d = p/16;
       if(d)
               buf = _hexify(buf, d, zeros-1);
       else
               while(zeros--)
                       *buf++ = '0';
       *buf++ = "0123456789abcdef"[p&amp;0x0f];
       return buf;
}

/*
*  get a byte of the instruction
*/
static int
igetc(Instr *ip, uchar *c)
{
       if(ip-&gt;n+1 &gt; sizeof(ip-&gt;mem)){
               werrstr("instruction too long");
               return -1;
       }
       ip-&gt;mem[ip-&gt;n++] = *c = *(((uchar*)ip-&gt;addr)+ip-&gt;n);
       return 1;
}

/*
*  get two bytes of the instruction
*/
static int
igets(Instr *ip, ushort *sp)
{
       uchar   c;
       ushort s;

       if (igetc( ip, &amp;c) &lt; 0)
               return -1;
       s = c;
       if (igetc(ip, &amp;c) &lt; 0)
               return -1;
       s |= (c&lt;&lt;8);
       *sp = s;
       return 1;
}

/*
*  get 4 bytes of the instruction
*/
static int
igetl( Instr *ip, ulong *lp)
{
       ushort s;
       long    l;

       if (igets( ip, &amp;s) &lt; 0)
               return -1;
       l = s;
       if (igets(ip, &amp;s) &lt; 0)
               return -1;
       l |= (s&lt;&lt;16);
       *lp = l;
       return 1;
}

static int
getdisp(Instr *ip, int mod, int rm, int code)
{
       uchar c;
       ushort s;

       if (mod &gt; 2)
               return 1;
       if (mod == 1) {
               if (igetc(ip, &amp;c) &lt; 0)
                       return -1;
               if (c&amp;0x80)
                       ip-&gt;disp = c|0xffffff00;
               else
                       ip-&gt;disp = c&amp;0xff;
       } else if (mod == 2 || rm == code) {
               if (ip-&gt;asize == 'E') {
                       if (igetl(ip, &amp;ip-&gt;disp) &lt; 0)
                               return -1;
               } else {
                       if (igets( ip, &amp;s) &lt; 0)
                               return -1;
                       if (s&amp;0x8000)
                               ip-&gt;disp = s|0xffff0000;
                       else
                               ip-&gt;disp = s;
               }
               if (mod == 0)
                       ip-&gt;base = -1;
       }
       return 1;
}

static int
modrm(Instr *ip, uchar c)
{
       uchar rm, mod;

       mod = (c&gt;&gt;6)&amp;3;
       rm = c&amp;7;
       ip-&gt;mod = mod;
       ip-&gt;base = rm;
       ip-&gt;reg = (c&gt;&gt;3)&amp;7;
       if (mod == 3)                   /* register */
               return 1;
       if (ip-&gt;asize == 0) {                /* 16-bit mode */
               switch(rm)
               {
               case 0:
                       ip-&gt;base = BX; ip-&gt;index = SI;
                       break;
               case 1:
                       ip-&gt;base = BX; ip-&gt;index = DI;
                       break;
               case 2:
                       ip-&gt;base = BP; ip-&gt;index = SI;
                       break;
               case 3:
                       ip-&gt;base = BP; ip-&gt;index = DI;
                       break;
               case 4:
                       ip-&gt;base = SI;
                       break;
               case 5:
                       ip-&gt;base = DI;
                       break;
               case 6:
                       ip-&gt;base = BP;
                       break;
               case 7:
                       ip-&gt;base = BX;
                       break;
               default:
                       break;
               }
               return getdisp(ip, mod, rm, 6);
       }
       if (rm == 4) {  /* scummy sib byte */
               if (igetc( ip, &amp;c) &lt; 0)
                       return -1;
               ip-&gt;ss = (c&gt;&gt;6)&amp;0x03;
               ip-&gt;index = (c&gt;&gt;3)&amp;0x07;
               if (ip-&gt;index == 4)
                       ip-&gt;index = -1;
               ip-&gt;base = c&amp;0x07;
               return getdisp(ip, mod, ip-&gt;base, 5);
       }
       return getdisp(ip, mod, rm, 5);
}

static Optable *
mkinstr(Instr *ip, uchar* pc)
{
       int i, n;
       uchar c;
       ushort s;
       Optable *op, *obase;
       char buf[128];

       memset(ip, 0, sizeof(*ip));
       ip-&gt;base = -1;
       ip-&gt;index = -1;
       if(1 /*asstype == AI8086 */)
               ip-&gt;osize = 'W';
       else {
               ip-&gt;osize = 'L';
               ip-&gt;asize = 'E';
       }
       ip-&gt;addr = (ulong) pc;
       if (igetc(ip, &amp;c) &lt; 0)
               return 0;
       obase = optable;
newop:
       op = &amp;obase[c];
       if (op-&gt;proto == 0) {
badop:
               n = snprint(buf, sizeof(buf), "opcode: ??");
               for (i = 0; i &lt; ip-&gt;n &amp;&amp; n &lt; sizeof(buf)-3; i++, n+=2)
                       _hexify(buf+n, ip-&gt;mem[i], 1);
               strcpy(buf+n, "??");
               werrstr(buf);
               return 0;
       }
       for(i = 0; i &lt; 2 &amp;&amp; op-&gt;operand[i]; i++) {
               switch(op-&gt;operand[i])
               {
               case Ib:        /* 8-bit immediate - (no sign extension)*/
                       if (igetc( ip, &amp;c) &lt; 0)
                               return 0;
                       ip-&gt;imm = c&amp;0xff;
                       break;
               case Jbs:       /* 8-bit jump immediate (sign extended) */
                       if (igetc(ip, &amp;c) &lt; 0)
                               return 0;
                       if (c&amp;0x80)
                               ip-&gt;imm = c|0xffffff00;
                       else
                               ip-&gt;imm = c&amp;0xff;
                       ip-&gt;jumptype = Jbs;
                       break;
               case Ibs:       /* 8-bit immediate (sign extended) */
                       if (igetc(ip, &amp;c) &lt; 0)
                               return 0;
                       if (c&amp;0x80)
                               if (ip-&gt;osize == 'L')
                                       ip-&gt;imm = c|0xffffff00;
                               else
                                       ip-&gt;imm = c|0xff00;
                       else
                               ip-&gt;imm = c&amp;0xff;
                       break;
               case Iw:        /* 16-bit immediate -&gt; imm */
                       if (igets(ip, &amp;s) &lt; 0)
                               return 0;
                       ip-&gt;imm = s&amp;0xffff;
                       ip-&gt;jumptype = Iw;
                       break;
               case Iw2:       /* 16-bit immediate -&gt; in imm2*/
                       if (igets(ip, &amp;s) &lt; 0)
                               return 0;
                       ip-&gt;imm2 = s&amp;0xffff;
                       break;
               case Iwd:       /* Operand-sized immediate (no sign extension)*/
                       if (ip-&gt;osize == 'L') {
                               if (igetl(ip, &amp;ip-&gt;imm) &lt; 0)
                                       return 0;
                       } else {
                               if (igets(ip, &amp;s)&lt; 0)
                                       return 0;
                               ip-&gt;imm = s&amp;0xffff;
                       }
                       break;
               case Awd:       /* Address-sized immediate (no sign extension)*/
                       if (ip-&gt;asize == 'E') {
                               if (igetl(ip, &amp;ip-&gt;imm) &lt; 0)
                                       return 0;
                       } else {
                               if (igets(ip, &amp;s)&lt; 0)
                                       return 0;
                               ip-&gt;imm = s&amp;0xffff;
                       }
                       break;
               case Iwds:      /* Operand-sized immediate (sign extended) */
                       if (ip-&gt;osize == 'L') {
                               if (igetl(ip, &amp;ip-&gt;imm) &lt; 0)
                                       return 0;
                       } else {
                               if (igets(ip, &amp;s)&lt; 0)
                                       return 0;
                               if (s&amp;0x8000)
                                       ip-&gt;imm = s|0xffff0000;
                               else
                                       ip-&gt;imm = s&amp;0xffff;
                       }
                       ip-&gt;jumptype = Iwds;
                       break;
               case OA:        /* literal 0x0a byte */
                       if (igetc(ip, &amp;c) &lt; 0)
                               return 0;
                       if (c != 0x0a)
                               goto badop;
                       break;
               case R0:        /* base register must be R0 */
                       if (ip-&gt;base != 0)
                               goto badop;
                       break;
               case R1:        /* base register must be R1 */
                       if (ip-&gt;base != 1)
                               goto badop;
                       break;
               case RMB:       /* R/M field with byte register (/r)*/
                       if (igetc(ip, &amp;c) &lt; 0)
                               return 0;
                       if (modrm(ip, c) &lt; 0)
                               return 0;
                       ip-&gt;osize = 'B';
                       break;
               case RM:        /* R/M field with register (/r) */
                       if (igetc(ip, &amp;c) &lt; 0)
                               return 0;
                       if (modrm(ip, c) &lt; 0)
                               return 0;
                       break;
               case RMOPB:     /* R/M field with op code (/digit) */
                       if (igetc(ip, &amp;c) &lt; 0)
                               return 0;
                       if (modrm(ip, c) &lt; 0)
                               return 0;
                       c = ip-&gt;reg;         /* secondary op code */
                       obase = (Optable*)op-&gt;proto;
                       ip-&gt;osize = 'B';
                       goto newop;
               case RMOP:      /* R/M field with op code (/digit) */
                       if (igetc(ip, &amp;c) &lt; 0)
                               return 0;
                       if (modrm(ip, c) &lt; 0)
                               return 0;
                       c = ip-&gt;reg;
                       obase = (Optable*)op-&gt;proto;
                       goto newop;
               case FRMOP:     /* FP R/M field with op code (/digit) */
                       if (igetc(ip, &amp;c) &lt; 0)
                               return 0;
                       if (modrm(ip, c) &lt; 0)
                               return 0;
                       if ((c&amp;0xc0) == 0xc0)
                               c = ip-&gt;reg+8;               /* 16 entry table */
                       else
                               c = ip-&gt;reg;
                       obase = (Optable*)op-&gt;proto;
                       goto newop;
               case FRMEX:     /* Extended FP R/M field with op code (/digit) */
                       if (igetc(ip, &amp;c) &lt; 0)
                               return 0;
                       if (modrm(ip, c) &lt; 0)
                               return 0;
                       if ((c&amp;0xc0) == 0xc0)
                               c = (c&amp;0x3f)+8;             /* 64-entry table */
                       else
                               c = ip-&gt;reg;
                       obase = (Optable*)op-&gt;proto;
                       goto newop;
               case RMR:       /* R/M register only (mod = 11) */
                       if (igetc(ip, &amp;c) &lt; 0)
                               return 0;
                       if ((c&amp;0xc0) != 0xc0) {
                               werrstr("invalid R/M register: %x", c);
                               return 0;
                       }
                       if (modrm(ip, c) &lt; 0)
                               return 0;
                       break;
               case RMM:       /* R/M register only (mod = 11) */
                       if (igetc(ip, &amp;c) &lt; 0)
                               return 0;
                       if ((c&amp;0xc0) == 0xc0) {
                               werrstr("invalid R/M memory mode: %x", c);
                               return 0;
                       }
                       if (modrm(ip, c) &lt; 0)
                               return 0;
                       break;
               case PTR:       /* Seg:Displacement addr (ptr16:16 or ptr16:32) */
                       if (ip-&gt;osize == 'L') {
                               if (igetl(ip, &amp;ip-&gt;disp) &lt; 0)
                                       return 0;
                       } else {
                               if (igets(ip, &amp;s)&lt; 0)
                                       return 0;
                               ip-&gt;disp = s&amp;0xffff;
                       }
                       if (igets(ip, (ushort*)&amp;ip-&gt;seg) &lt; 0)
                               return 0;
                       ip-&gt;jumptype = PTR;
                       break;
               case AUX:       /* Multi-byte op code - Auxiliary table */
                       obase = (Optable*)op-&gt;proto;
                       if (igetc(ip, &amp;c) &lt; 0)
                               return 0;
                       goto newop;
               case PRE:       /* Instr Prefix */
                       ip-&gt;prefix = (char*)op-&gt;proto;
                       if (igetc(ip, &amp;c) &lt; 0)
                               return 0;
                       goto newop;
               case SEG:       /* Segment Prefix */
                       ip-&gt;segment = (char*)op-&gt;proto;
                       if (igetc(ip, &amp;c) &lt; 0)
                               return 0;
                       goto newop;
               case OPOVER:    /* Operand size override */
                       ip-&gt;osize = 'W';
                       if (igetc(ip, &amp;c) &lt; 0)
                               return 0;
                       goto newop;
               case ADDOVER:   /* Address size override */
                       ip-&gt;asize = 0;
                       if (igetc(ip, &amp;c) &lt; 0)
                               return 0;
                       goto newop;
               case JUMP:      /* mark instruction as JUMP or RET */
               case RET:
                       ip-&gt;jumptype = op-&gt;operand[i];
                       break;
               case JBOTH:
               case JOUT:
                       ip-&gt;jumploc = op-&gt;operand[i];
                       break;
               default:
                       werrstr("bad operand type %d", op-&gt;operand[i]);
                       return 0;
               }
       }
       return op;
}

static void
bprint(Instr *ip, char *fmt, ...)
{
       va_list arg;

       va_start(arg, fmt);
       ip-&gt;curr = doprint(ip-&gt;curr, ip-&gt;end, fmt, arg);
       va_end(arg);
}

/*
*      if 32-bit registers are to be named E&lt;rr&gt;, macro ANAME should
*      always return ip-&gt;asize and ONAME should return a 'E' when
*      when ip-&gt;osize == 'L'.  The macros should return a null character
*      when 32-bit registers are ddesignated by &lt;rr&gt;.
*/
#define ANAME(ip)       ip-&gt;asize
#define ONAME(ip)       ((ip)-&gt;osize == 'L' ? 'E' : 0)

static char *reg[] =  {
[AX]    "AX",
[CX]    "CX",
[DX]    "DX",
[BX]    "BX",
[SP]    "SP",
[BP]    "BP",
[SI]    "SI",
[DI]    "DI",
};

static char *breg[] = { "AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH" };
static char *sreg[] = { "ES", "CS", "SS", "DS", "FS", "GS" };

static void
plocal(Instr *ip)
{
       int offset;
//      int ret;
//      Symbol s;
//      char *reg;

       offset = ip-&gt;disp;
//      if (!findsym(ip-&gt;addr, CTEXT, &amp;s) || !findlocal(&amp;s, FRAMENAME, &amp;s)) {
               bprint(ip, "%lx(SP)", offset);
               return;
//      }

//      if (s.value &gt; ip-&gt;disp) {
//              ret = getauto(&amp;s, s.value-ip-&gt;disp-mach-&gt;szaddr, CAUTO, &amp;s);
//              reg = "(SP)";
//      } else {
//              offset -= s.value;
//              ret = getauto(&amp;s, offset, CPARAM, &amp;s);
//              reg = "(FP)";
//      }
//      if (ret)
//              bprint(ip, "%s+", s.name);
//      else
//              offset = ip-&gt;disp;
//      bprint(ip, "%lux%s", offset, reg);
}

static void
pea(Instr *ip)
{
       if (ip-&gt;mod == 3) {
               if (ip-&gt;osize == 'B')
                       bprint(ip, breg[ip-&gt;base]);
               else
                       bprint(ip, "%c%s", ANAME(ip), reg[ip-&gt;base]);
               return;
       }
       if (ip-&gt;segment)
               bprint(ip, ip-&gt;segment);
       if (ip-&gt;asize == 'E' &amp;&amp; ip-&gt;base == SP)
               plocal(ip);
       else {
               bprint(ip,"%lx", ip-&gt;disp);
               if (ip-&gt;base &gt;= 0)
                       bprint(ip,"(%c%s)", ANAME(ip), reg[ip-&gt;base]);
               else
                       bprint(ip, "()");
       }
       if (ip-&gt;index &gt;= 0)
               bprint(ip,"(%c%s*%d)", ANAME(ip), reg[ip-&gt;index], 1&lt;&lt;ip-&gt;ss);
}


int findsym(long, char**, long*);

static void
immediate(Instr *ip, long val)
{
/*
       char *s;
       long w, value;

       if(findsym(val, &amp;s, &amp;value)){
               w = val - s.value;
               if (w &lt; 0)
                       w = -w;
               if (w &lt; 4096) {
                       if (w)
                               bprint(ip, "%s+%lux", s.name, w);
                       else
                               bprint(ip, "%s", s.name);
                       return;
               }
       }
*/
       bprint(ip, "%lx", val);
}

long irel, offset;

static void
prinstr(Instr *ip, char *fmt)
{
       if (ip-&gt;prefix)
               bprint(ip, "%s ", ip-&gt;prefix);
       for (; *fmt &amp;&amp; ip-&gt;curr &lt; ip-&gt;end; fmt++) {
               if (*fmt != '%')
                       *ip-&gt;curr++ = *fmt;
               else switch(*++fmt)
               {
               case '%':
                       *ip-&gt;curr++ = '%';
                       break;
               case 'A':
                       bprint(ip, "%c", ANAME(ip));
                       break;
               case 'C':
                       bprint(ip, "CR%d", ip-&gt;reg);
                       break;
               case 'D':
                       if (ip-&gt;reg &lt; 4 || ip-&gt;reg == 6 || ip-&gt;reg == 7)
                               bprint(ip, "DR%d",ip-&gt;reg);
                       else
                               bprint(ip, "???");
                       break;
               case 'I':
                       bprint(ip, "$");
                       immediate(ip, ip-&gt;imm2);
                       break;
               case 'O':
                       bprint(ip,"%c", ONAME(ip));
                       break;
               case 'i':
                       bprint(ip, "$");
                       immediate(ip,ip-&gt;imm);
                       break;
               case 'R':
                       bprint(ip, "%c%s", ONAME(ip), reg[ip-&gt;reg]);
                       break;
               case 'S':
                       bprint(ip, "%c", ip-&gt;osize);
                       break;
               case 'T':
                       if (ip-&gt;reg == 6 || ip-&gt;reg == 7)
                               bprint(ip, "TR%d",ip-&gt;reg);
                       else
                               bprint(ip, "???");
                       break;
               case 'X':
                       if (ip-&gt;osize == 'L')
                               bprint(ip,"CWDE");
                       else
                               bprint(ip, "CBW");
                       break;
               case 'd':
                       bprint(ip,"%lux:%lux",ip-&gt;seg,ip-&gt;disp);
                       break;
               case 'e':
                       pea(ip);
                       break;
               case 'f':
                       bprint(ip, "F%d", ip-&gt;base);
                       break;
               case 'g':
                       if (ip-&gt;reg &lt; 6)
                               bprint(ip,"%s",sreg[ip-&gt;reg]);
                       else
                               bprint(ip,"???");
                       break;
               case 'p':
                       immediate(ip, ip-&gt;imm+ip-&gt;addr+ip-&gt;n-irel+offset);
                       break;
               case 'r':
                       if (ip-&gt;osize == 'B')
                               bprint(ip,"%s",breg[ip-&gt;reg]);
                       else
                               bprint(ip, reg[ip-&gt;reg]);
                       break;
               case 'x':
                       if (ip-&gt;osize == 'L')
                               bprint(ip,"CDQ");
                       else
                               bprint(ip, "CWD");
                       break;
               default:
                       bprint(ip, "%%%c", *fmt);
                       break;
               }
       }
       *ip-&gt;curr = 0;               /* there's always room for 1 byte */
}

int
i386das(uchar* pc, char *buf, int n)
{
       Instr   instr;
       Optable *op;

       op = mkinstr( &amp;instr, pc);
       if (op == 0) {
               if (n &gt;= ERRLEN)
                       errstr(buf);
               else
                       snprint(buf,n,"%r");
               return -1;
       }
       instr.curr = buf;
       instr.end = buf+n-1;
       prinstr(&amp;instr, op-&gt;proto);
       return instr.n;
}

int
i386hexinst(uchar* pc, char *buf, int n)
{
       Instr   instr;
       int i;

       if (mkinstr( &amp;instr, pc) == 0) {
               if (n &gt;= ERRLEN)
                       errstr(buf);
               else
                       snprint(buf,n,"%r");
               return -1;
       }
       for(i = 0; i &lt; instr.n &amp;&amp; n &gt; 2; i++) {
               _hexify(buf, instr.mem[i], 1);
               buf += 2;
               n -= 2;
       }
       *buf = 0;
       return instr.n;
}

int
i386instlen(uchar* pc)
{
       Instr i;

       if (mkinstr( &amp;i, pc))
               return i.n;
       return -1;
}

void
disasm(uchar *v, int start, int nv)
{
       int i, n;
       char buf[100];

       for(n=start; n&lt;nv; n+=i) {
               i = i386das(v+n, buf, sizeof buf);
               if(i &lt;= 0) {
                       print("fail %r\n");
                       break;
               }
               print("%x+%x %s\n", n, i, buf);
       }
}

enum {
       Tunknown,
       Tstring,
       Tbyte,
       Tword,
       Tlong,
       Tinst,
};

#pragma varargck type "P" void*

int start;
int interactive;
uchar *code, *type;
int ncode;
int cs, ce;

void
change(int a)
{
       if(cs == ce){
               cs = a;
               ce = a+1;
               return;
       }
       if(cs &gt; a)
               cs = a;
       if(ce &lt;= a)
               ce = a+1;
}

void
explore(void)
{
       int i, j, ji, lcs, lce;
       Instr instr;

       while(cs != ce){
               lcs = cs;
               lce = ce;
               cs = ce = 0;
               for(i=lcs; i&lt;lce; i++){
                       if(type[i] != Tinst)
                               continue;
                       if(mkinstr(&amp;instr, code+i) == nil)
                               continue;
                       for(j=0; j&lt;instr.n; j++)
                               if(type[i] != 0 &amp;&amp; type[i] != Tinst)
                                       break;
                       if(j != instr.n)
                               continue;

                       switch(instr.jumploc){
                       case 0:
                       case JBOTH:
                               if(i+instr.n &lt; ncode &amp;&amp; type[i+instr.n] == 0){
                                       type[i+instr.n] = Tinst;
                                       if(i+instr.n &gt;= lce)
                                               change(i+instr.n);
                               }
                               if(instr.jumploc == 0)
                                       break;
                       case JOUT:
                               ji = instr.imm+instr.addr+instr.n-irel;
                               if(0 &lt;= ji &amp;&amp; ji &lt; ncode &amp;&amp; type[ji] == 0){
                                       type[ji] = Tinst;
                                       if(ji &lt; i || lce &lt;= ji)
                                               change(ji);
                               }
                               break;
                       }
               }
       }
}

int
Pconv(va_list *arg, Fconv *f)
{
       char buf[10];
       int i, n;
       uchar *p;

       p = va_arg(*arg, uchar*);
       n = f-&gt;f2;
       if(n &gt; 0){
               f-&gt;f2 = -1000;
               for(i=0; i&lt;n; i++){
                       sprint(buf, "%2.2uX", p[i]);
                       strconv(buf, f);
               }
               for(; n*2 &lt; 16; n++)
                       strconv("  ", f);
       }

       return 0;
}

static int partial, bstart;
Biobuf bout;

void
endbyte(void)
{
       int j;

       if(partial){
               for(j=partial; j%16; j++)
                       Bprint(&amp;bout, "   ");
               for(j=partial&amp;~15; j&lt;bstart; j++)
                       Bprint(&amp;bout, " ");
               for(; j&lt;partial; j++){
                       if(isprint(code[j]))
                               Bprint(&amp;bout, "%c", code[j]);
                       else
                               Bprint(&amp;bout, ".");
               }
               for(; j%16; j++)
                       Bprint(&amp;bout, " ");
               Bprint(&amp;bout, "\n");
               partial = 0;
       }
}

void
printbyte(int i)
{
       int j;

       if(partial != 0 &amp;&amp; partial != i){
               endbyte();
               partial = 0;
       }
       if(partial == 0){
               bstart = i;
               partial = i;
               Bprint(&amp;bout, "%.4lX\t", i+offset);
               for(j=i&amp;~15; j&lt;i; j++)
                       Bprint(&amp;bout, "   ");
       }
       Bprint(&amp;bout, "%2.2uX ", code[i]);
       partial++;
       if(partial%16 == 0){
               for(j=bstart; j&lt;partial; j++){
                       if(isprint(code[j]))
                               Bprint(&amp;bout, "%c", code[j]);
                       else
                               Bprint(&amp;bout, ".");
               }
               Bprint(&amp;bout, "\n");
               Bprint(&amp;bout, "%.4lX\t", (partial&amp;~15)+offset);
               bstart = partial;
       }
}

void
dumpasm(void)
{
       int i, j;
       Instr instr;
       Optable *op;
       char buf[128];

       Binit(&amp;bout, 1, OWRITE);
       for(i=0; i&lt;ncode; ){
               switch(type[i]){
               case Tstring:
                       for(j=i; j&lt;ncode &amp;&amp; code[j]; j++)
                               if(type[i] != 0 &amp;&amp; type[i] != Tstring)
                                       goto Default;
                       if(j==ncode)
                               goto Default;
                       endbyte();
                       Bprint(&amp;bout, "%.4lX\t\"%s\"\n", i+offset, (char*)code+i);
                       i=j+1;
                       break;
               case Tinst:
                       if(op = mkinstr(&amp;instr, code+i)){
                               for(j=0; j&lt;instr.n; j++)
                                       if(type[i] != 0 &amp;&amp; type[i] != Tinst)
                                               goto Default;
                               instr.curr = buf;
                               instr.end = buf+sizeof(buf)-1;
                               prinstr(&amp;instr, op-&gt;proto);
                               endbyte();
                               Bprint(&amp;bout, "%.4lX\t%.*P\t%s\n", i+offset, instr.n, code+i, buf);
                               i += instr.n;
                               break;
                       }
               Default:
               default:
                       printbyte(i);
                       i++;
                       break;
               }
       }
       endbyte();
       Bprint(&amp;bout, "\n");
       Bflush(&amp;bout);
}

void
usage(void)
{
       fprint(2, "usage: 8dis [-i] [-s start-offset] file\n");
       exits("usage");
}

void
main(int argc, char **argv)
{
       int fd;
       char buf[128];
       Dir d;

       fmtinstall('P', Pconv);
       ARGBEGIN{
       case 'i':
               interactive++;
               break;
       case 'o':
               offset = strtol(EARGF(usage()), 0, 0);
               break;
       case 's':
               start = strtol(EARGF(usage()), 0, 0);
               break;
       default:
               usage();
       }ARGEND

       if(argc != 1)
               usage();

       if((fd = open(argv[0], OREAD)) &lt; 0) {
               fprint(2, "cannot open %s: %r\n", argv[0]);
               exits("open");
       }

       if(dirfstat(fd, &amp;d) &lt; 0) {
               fprint(2, "dirfstat: %r\n");
               exits("dirfstat");
       }

       ncode = d.length;
       code = malloc(ncode);
       assert(code != nil);

       type = malloc(ncode);
       assert(type != nil);
       memset(type, 0, ncode);
       irel = (long)code;

       if(readn(fd, code, ncode) != ncode) {
               fprint(2, "read error: %r\n");
               exits("read");
       }

       if(interactive){
               char *p, *f[10];
               int addr, lineno, nf, t;
               Biobuf b;

               lineno = 0;
               Binit(&amp;b, 0, OREAD);
               while(p = Brdline(&amp;b, '\n')){
                       lineno++;
                       p[Blinelen(&amp;b)-1] = '\0';
                       if(p[0] == '#')
                               continue;
                       strecpy(buf, buf+sizeof buf, p);
                       nf = tokenize(p, f, nelem(f));
                       if(nf == 0)
                               continue;
                       switch(f[0][0]){
                       case 't':       /* tc addr: addr is type c */
                               if(nf &lt; 2 || f[0][1] == '\0'){
                                       print("\"%s\": usage: tc addr [name]\n", buf);
                                       continue;
                               }
                               addr = atoi(f[1])-offset;
                               if(addr &lt; 0 || addr &gt;= ncode){
                                       print("\"%s\": bad addr %#x\n", buf, addr);
                                       continue;
                               }
                               switch(f[0][1]){
                               case 's':       t = Tstring;    break;
                               case 'b':       t = Tbyte;              break;
                               case 'w':       t = Tword;              break;
                               case 'l':       t = Tlong;              break;
                               case 'i':       t = Tinst;              break;
                               default:
                                       print("\"%s\": bad type '%c'\n", buf, f[0][1]);
                                       continue;
                               }
                               type[addr] = t;
                               change(addr);
                               break;
                       }
               }
       }
       if(start || cs==ce){
               type[start] = Tinst;
               change(start);
       }
       explore();
       dumpasm();
       exits(0);
}
<!-- BEGIN TAIL -->
</pre>
</td></tr></table>
</td></tr></table>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: center;">
<span style="font-size: 10pt"></span></p>
<p style="margin-top: 0; margin-bottom: 0.50in"></p>
<p style="margin-top: 0; margin-bottom: 0.33in"></p>
<center><table border="0"><tr>
<td valign="middle"><a href="http://www.alcatel-lucent.com/"><img border="0" src="/plan9/img/logo_ft.gif" alt="Bell Labs" />
</a></td>
<td valign="middle"><a href="http://www.opensource.org"><img border="0" alt="OSI certified" src="/plan9/img/osi-certified-60x50.gif" />
</a></td>
<td><img style="padding-right: 45px;" alt="Powered by Plan 9" src="/plan9/img/power36.gif" />
</td>
</tr></table></center>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<center>
<span style="font-size: 10pt">(<a href="/plan9/">Return to Plan 9 Home Page</a>)</span>
</center>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<center><font size=-1>
<span style="font-size: 10pt"><a href="http://www.lucent.com/copyright.html">Copyright</a></span>
<span style="font-size: 10pt">© 2009 Alcatel-Lucent.</span>
<span style="font-size: 10pt">All Rights Reserved.</span>
<br />
<span style="font-size: 10pt">Comments to</span>
<span style="font-size: 10pt"><a href="mailto:[email protected]">[email protected]</a>.</span>
</font></center>
</body>
</html>