/* Print i386 instructions for GDB, the GNU debugger.
- Copyright (C) 1988, 1989, 1991, 1993, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1988, 89, 91, 93, 94, 95, 96, 1997
+ Free Software Foundation, Inc.
This file is part of GDB.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/*
* 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu)
*/
#include "dis-asm.h"
-#include <string.h>
+#include "sysdep.h"
#define MAXLEN 20
#include <setjmp.h>
-struct private
+static int fetch_data PARAMS ((struct disassemble_info *, bfd_byte *));
+
+struct dis_private
{
/* Points to first byte not fetched. */
bfd_byte *max_fetched;
to ADDR (exclusive) are valid. Returns 1 for success, longjmps
on error. */
#define FETCH_DATA(info, addr) \
- ((addr) <= ((struct private *)(info->private_data))->max_fetched \
+ ((addr) <= ((struct dis_private *)(info->private_data))->max_fetched \
? 1 : fetch_data ((info), (addr)))
static int
bfd_byte *addr;
{
int status;
- struct private *priv = (struct private *)info->private_data;
+ struct dis_private *priv = (struct dis_private *)info->private_data;
bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
status = (*info->read_memory_func) (start,
#define Iw OP_I, w_mode
#define Jb OP_J, b_mode
#define Jv OP_J, v_mode
+#if 0
#define ONE OP_ONE, 0
+#endif
#define Cd OP_C, d_mode
#define Dd OP_D, d_mode
#define Td OP_T, d_mode
#define fs OP_REG, fs_reg
#define gs OP_REG, gs_reg
-int OP_E(), OP_indirE(), OP_G(), OP_I(), OP_sI(), OP_REG();
-int OP_J(), OP_SEG();
-int OP_DIR(), OP_OFF(), OP_DSSI(), OP_ESDI(), OP_ONE(), OP_C();
-int OP_D(), OP_T(), OP_rm();
-
-static void dofloat (), putop (), append_prefix (), set_op ();
-static int get16 (), get32 ();
+#define MX OP_MMX, 0
+#define EM OP_EM, v_mode
+#define MS OP_MS, b_mode
+
+typedef int (*op_rtn) PARAMS ((int bytemode, int aflag, int dflag));
+
+static int OP_E PARAMS ((int, int, int));
+static int OP_G PARAMS ((int, int, int));
+static int OP_I PARAMS ((int, int, int));
+static int OP_indirE PARAMS ((int, int, int));
+static int OP_sI PARAMS ((int, int, int));
+static int OP_REG PARAMS ((int, int, int));
+static int OP_J PARAMS ((int, int, int));
+static int OP_DIR PARAMS ((int, int, int));
+static int OP_OFF PARAMS ((int, int, int));
+static int OP_ESDI PARAMS ((int, int, int));
+static int OP_DSSI PARAMS ((int, int, int));
+static int OP_SEG PARAMS ((int, int, int));
+static int OP_C PARAMS ((int, int, int));
+static int OP_D PARAMS ((int, int, int));
+static int OP_T PARAMS ((int, int, int));
+static int OP_rm PARAMS ((int, int, int));
+static int OP_ST PARAMS ((int, int, int));
+static int OP_STi PARAMS ((int, int, int));
+#if 0
+static int OP_ONE PARAMS ((int, int, int));
+#endif
+static int OP_MMX PARAMS ((int, int, int));
+static int OP_EM PARAMS ((int, int, int));
+static int OP_MS PARAMS ((int, int, int));
+
+static void append_prefix PARAMS ((void));
+static void set_op PARAMS ((int op));
+static void putop PARAMS ((char *template, int aflag, int dflag));
+static void dofloat PARAMS ((int aflag, int dflag));
+static int get16 PARAMS ((void));
+static int get32 PARAMS ((void));
+static void ckprefix PARAMS ((void));
#define b_mode 1
#define v_mode 2
#define GRP6 NULL, NULL, 13
#define GRP7 NULL, NULL, 14
#define GRP8 NULL, NULL, 15
+#define GRP9 NULL, NULL, 16
+#define GRP10 NULL, NULL, 17
+#define GRP11 NULL, NULL, 18
+#define GRP12 NULL, NULL, 19
#define FLOATCODE 50
#define FLOAT NULL, NULL, FLOATCODE
struct dis386 {
char *name;
- int (*op1)();
+ op_rtn op1;
int bytemode1;
- int (*op2)();
+ op_rtn op2;
int bytemode2;
- int (*op3)();
+ op_rtn op3;
int bytemode3;
};
-struct dis386 dis386[] = {
+static struct dis386 dis386[] = {
/* 00 */
{ "addb", Eb, Gb },
{ "addS", Ev, Gv },
{ "addS", Gv, Ev },
{ "addb", AL, Ib },
{ "addS", eAX, Iv },
- { "pushl", es },
- { "popl", es },
+ { "pushS", es },
+ { "popS", es },
/* 08 */
{ "orb", Eb, Gb },
{ "orS", Ev, Gv },
{ "orS", Gv, Ev },
{ "orb", AL, Ib },
{ "orS", eAX, Iv },
- { "pushl", cs },
+ { "pushS", cs },
{ "(bad)" }, /* 0x0f extended opcode escape */
/* 10 */
{ "adcb", Eb, Gb },
{ "adcS", Gv, Ev },
{ "adcb", AL, Ib },
{ "adcS", eAX, Iv },
- { "pushl", ss },
- { "popl", ss },
+ { "pushS", ss },
+ { "popS", ss },
/* 18 */
{ "sbbb", Eb, Gb },
{ "sbbS", Ev, Gv },
{ "sbbS", Gv, Ev },
{ "sbbb", AL, Ib },
{ "sbbS", eAX, Iv },
- { "pushl", ds },
- { "popl", ds },
+ { "pushS", ds },
+ { "popS", ds },
/* 20 */
{ "andb", Eb, Gb },
{ "andS", Ev, Gv },
/* 68 */
{ "pushS", Iv }, /* 386 book wrong */
{ "imulS", Gv, Ev, Iv },
- { "pushl", sIb }, /* push of byte really pushes 4 bytes */
+ { "pushS", sIb }, /* push of byte really pushes 2 or 4 bytes */
{ "imulS", Gv, Ev, Ib },
{ "insb", Yb, indirDX },
{ "insS", Yv, indirDX },
{ "outsb", indirDX, Xb },
{ "outsS", indirDX, Xv },
/* 70 */
- { "jo", Jb },
+ { "jo", Jb },
{ "jno", Jb },
- { "jb", Jb },
+ { "jb", Jb },
{ "jae", Jb },
- { "je", Jb },
+ { "je", Jb },
{ "jne", Jb },
{ "jbe", Jb },
- { "ja", Jb },
+ { "ja", Jb },
/* 78 */
- { "js", Jb },
+ { "js", Jb },
{ "jns", Jb },
- { "jp", Jb },
+ { "jp", Jb },
{ "jnp", Jb },
- { "jl", Jb },
+ { "jl", Jb },
{ "jnl", Jb },
{ "jle", Jb },
- { "jg", Jb },
+ { "jg", Jb },
/* 80 */
{ GRP1b },
{ GRP1S },
{ "xchgS", eSI, eAX },
{ "xchgS", eDI, eAX },
/* 98 */
- { "cwtl" },
- { "cltd" },
+ { "cWtS" },
+ { "cStd" },
{ "lcall", Ap },
{ "(bad)" }, /* fwait */
{ "pushf" },
{ GRP5 },
};
-struct dis386 dis386_twobyte[] = {
+static struct dis386 dis386_twobyte[] = {
/* 00 */
{ GRP6 },
{ GRP7 },
/* 08 */
{ "invd" },
{ "wbinvd" },
- { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "ud2a" },
{ "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
/* 10 */
{ "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
{ "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
{ "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
/* 30 */
- { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "wrmsr" }, { "rdtsc" }, { "rdmsr" }, { "rdpmc" },
{ "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
/* 38 */
{ "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
{ "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
/* 40 */
- { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
- { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "cmovo", Gv,Ev }, { "cmovno", Gv,Ev }, { "cmovb", Gv,Ev }, { "cmovae", Gv,Ev },
+ { "cmove", Gv,Ev }, { "cmovne", Gv,Ev }, { "cmovbe", Gv,Ev }, { "cmova", Gv,Ev },
/* 48 */
- { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
- { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "cmovs", Gv,Ev }, { "cmovns", Gv,Ev }, { "cmovp", Gv,Ev }, { "cmovnp", Gv,Ev },
+ { "cmovl", Gv,Ev }, { "cmovge", Gv,Ev }, { "cmovle", Gv,Ev }, { "cmovg", Gv,Ev },
/* 50 */
{ "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
{ "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
{ "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
{ "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
/* 60 */
- { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
- { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "punpcklbw", MX, EM },
+ { "punpcklwd", MX, EM },
+ { "punpckldq", MX, EM },
+ { "packsswb", MX, EM },
+ { "pcmpgtb", MX, EM },
+ { "pcmpgtw", MX, EM },
+ { "pcmpgtd", MX, EM },
+ { "packuswb", MX, EM },
/* 68 */
- { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
- { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "punpckhbw", MX, EM },
+ { "punpckhwd", MX, EM },
+ { "punpckhdq", MX, EM },
+ { "packssdw", MX, EM },
+ { "(bad)" }, { "(bad)" },
+ { "movd", MX, Ev },
+ { "movq", MX, EM },
/* 70 */
- { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
- { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" },
+ { GRP10 },
+ { GRP11 },
+ { GRP12 },
+ { "pcmpeqb", MX, EM },
+ { "pcmpeqw", MX, EM },
+ { "pcmpeqd", MX, EM },
+ { "emms" },
/* 78 */
{ "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
- { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" },
+ { "movd", Ev, MX },
+ { "movq", EM, MX },
/* 80 */
{ "jo", Jv },
{ "jno", Jv },
{ "setle", Eb },
{ "setg", Eb },
/* a0 */
- { "pushl", fs },
- { "popl", fs },
- { "(bad)" },
+ { "pushS", fs },
+ { "popS", fs },
+ { "cpuid" },
{ "btS", Ev, Gv },
{ "shldS", Ev, Gv, Ib },
{ "shldS", Ev, Gv, CL },
{ "(bad)" },
{ "(bad)" },
/* a8 */
- { "pushl", gs },
- { "popl", gs },
- { "(bad)" },
+ { "pushS", gs },
+ { "popS", gs },
+ { "rsm" },
{ "btsS", Ev, Gv },
{ "shrdS", Ev, Gv, Ib },
{ "shrdS", Ev, Gv, CL },
{ "movzbS", Gv, Eb },
{ "movzwS", Gv, Ew },
/* b8 */
- { "(bad)" },
+ { "ud2b" },
{ "(bad)" },
{ GRP8 },
{ "btcS", Ev, Gv },
/* c0 */
{ "xaddb", Eb, Gb },
{ "xaddS", Ev, Gv },
- { "(bad)" }, { "(bad)" },
- { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { GRP9 },
/* c8 */
{ "bswap", eAX },
{ "bswap", eCX },
{ "bswap", eSI },
{ "bswap", eDI },
/* d0 */
- { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
- { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" },
+ { "psrlw", MX, EM },
+ { "psrld", MX, EM },
+ { "psrlq", MX, EM },
+ { "(bad)" },
+ { "pmullw", MX, EM },
+ { "(bad)" }, { "(bad)" },
/* d8 */
- { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
- { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "psubusb", MX, EM },
+ { "psubusw", MX, EM },
+ { "(bad)" },
+ { "pand", MX, EM },
+ { "paddusb", MX, EM },
+ { "paddusw", MX, EM },
+ { "(bad)" },
+ { "pandn", MX, EM },
/* e0 */
- { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
- { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" },
+ { "psraw", MX, EM },
+ { "psrad", MX, EM },
+ { "(bad)" },
+ { "(bad)" },
+ { "pmulhw", MX, EM },
+ { "(bad)" }, { "(bad)" },
/* e8 */
- { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
- { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "psubsb", MX, EM },
+ { "psubsw", MX, EM },
+ { "(bad)" },
+ { "por", MX, EM },
+ { "paddsb", MX, EM },
+ { "paddsw", MX, EM },
+ { "(bad)" },
+ { "pxor", MX, EM },
/* f0 */
- { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
- { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" },
+ { "psllw", MX, EM },
+ { "pslld", MX, EM },
+ { "psllq", MX, EM },
+ { "(bad)" },
+ { "pmaddwd", MX, EM },
+ { "(bad)" }, { "(bad)" },
/* f8 */
- { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
- { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "psubb", MX, EM },
+ { "psubw", MX, EM },
+ { "psubd", MX, EM },
+ { "(bad)" },
+ { "paddb", MX, EM },
+ { "paddw", MX, EM },
+ { "paddd", MX, EM },
+ { "(bad)" }
+};
+
+static const unsigned char onebyte_has_modrm[256] = {
+ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
+ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
+ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
+ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,1,1,0,0,0,0,0,1,0,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0,
+ 1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1
+};
+
+static const unsigned char twobyte_has_modrm[256] = {
+ /* 00 */ 1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */
+ /* 10 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */
+ /* 20 */ 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, /* 2f */
+ /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
+ /* 40 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 4f */
+ /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 5f */
+ /* 60 */ 1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1, /* 6f */
+ /* 70 */ 0,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1, /* 7f */
+ /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
+ /* 90 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 9f */
+ /* a0 */ 0,0,0,1,1,1,1,1,0,0,0,1,1,1,1,1, /* af */
+ /* b0 */ 1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1, /* bf */
+ /* c0 */ 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, /* cf */
+ /* d0 */ 0,1,1,1,0,1,0,0,1,1,1,0,1,1,0,1, /* df */
+ /* e0 */ 0,1,1,0,0,1,0,0,1,1,0,1,1,1,0,1, /* ef */
+ /* f0 */ 0,1,1,1,0,1,0,0,1,1,1,0,1,1,1,0 /* ff */
};
static char obuf[100];
static int mod;
static int rm;
static int reg;
-static void oappend ();
+static void oappend PARAMS ((char *s));
static char *names32[]={
"%eax","%ecx","%edx","%ebx", "%esp","%ebp","%esi","%edi",
static char *names_seg[] = {
"%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
};
+static char *index16[] = {
+ "bx+si","bx+di","bp+si","bp+di","si","di","bp","bx"
+};
-struct dis386 grps[][8] = {
+static struct dis386 grps[][8] = {
/* GRP1b */
{
{ "addb", Eb, Ib },
{ "btsS", Ev, Ib },
{ "btrS", Ev, Ib },
{ "btcS", Ev, Ib },
+ },
+ /* GRP9 */
+ {
+ { "(bad)" },
+ { "cmpxchg8b", Ev },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ },
+ /* GRP10 */
+ {
+ { "(bad)" },
+ { "(bad)" },
+ { "psrlw", MS, Ib },
+ { "(bad)" },
+ { "psraw", MS, Ib },
+ { "(bad)" },
+ { "psllw", MS, Ib },
+ { "(bad)" },
+ },
+ /* GRP11 */
+ {
+ { "(bad)" },
+ { "(bad)" },
+ { "psrld", MS, Ib },
+ { "(bad)" },
+ { "psrad", MS, Ib },
+ { "(bad)" },
+ { "pslld", MS, Ib },
+ { "(bad)" },
+ },
+ /* GRP12 */
+ {
+ { "(bad)" },
+ { "(bad)" },
+ { "psrlq", MS, Ib },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "psllq", MS, Ib },
+ { "(bad)" },
}
};
}
}
-static int dflag;
-static int aflag;
-
static char op1out[100], op2out[100], op3out[100];
static int op_address[3], op_ad, op_index[3];
static int start_pc;
* The function returns the length of this instruction in bytes.
*/
+int print_insn_x86 PARAMS ((bfd_vma pc, disassemble_info *info, int aflag,
+ int dflag));
int
print_insn_i386 (pc, info)
bfd_vma pc;
disassemble_info *info;
+{
+ if (info->mach == bfd_mach_i386_i386)
+ return print_insn_x86 (pc, info, 1, 1);
+ else if (info->mach == bfd_mach_i386_i8086)
+ return print_insn_x86 (pc, info, 0, 0);
+ else
+ abort ();
+}
+
+int
+print_insn_x86 (pc, info, aflag, dflag)
+ bfd_vma pc;
+ disassemble_info *info;
{
struct dis386 *dp;
int i;
int enter_instruction;
char *first, *second, *third;
int needcomma;
-
- struct private priv;
+ unsigned char need_modrm;
+
+ struct dis_private priv;
bfd_byte *inbuf = priv.the_buffer;
+ /* The output looks better if we put 5 bytes on a line, since that
+ puts long word instructions on a single line. */
+ info->bytes_per_line = 5;
+
info->private_data = (PTR) &priv;
priv.max_fetched = priv.the_buffer;
priv.insn_start = pc;
return (1);
}
- /* these would be initialized to 0 if disassembling for 8086 or 286 */
- dflag = 1;
- aflag = 1;
-
if (prefixes & PREFIX_DATA)
dflag ^= 1;
if (prefixes & PREFIX_ADR)
{
aflag ^= 1;
- oappend ("addr16 ");
+ if (aflag)
+ oappend ("addr32 ");
+ else
+ oappend ("addr16 ");
}
if (*codep == 0x0f)
{
FETCH_DATA (info, codep + 2);
dp = &dis386_twobyte[*++codep];
+ need_modrm = twobyte_has_modrm[*codep];
}
else
- dp = &dis386[*codep];
+ {
+ dp = &dis386[*codep];
+ need_modrm = onebyte_has_modrm[*codep];
+ }
codep++;
- /* Fetch the mod/reg/rm byte. FIXME: We should be only fetching
- this if we need it. As it is, this code loses if there is a
- one-byte instruction (without a mod/reg/rm byte) at the end of
- the address space. */
-
- FETCH_DATA (info, codep + 1);
- mod = (*codep >> 6) & 3;
- reg = (*codep >> 3) & 7;
- rm = *codep & 7;
+ if (need_modrm)
+ {
+ FETCH_DATA (info, codep + 1);
+ mod = (*codep >> 6) & 3;
+ reg = (*codep >> 3) & 7;
+ rm = *codep & 7;
+ }
if (dp->name == NULL && dp->bytemode1 == FLOATCODE)
{
- dofloat ();
+ dofloat (aflag, dflag);
}
else
{
if (dp->name == NULL)
dp = &grps[dp->bytemode1][reg];
- putop (dp->name);
+ putop (dp->name, aflag, dflag);
obufp = op1out;
op_ad = 2;
if (dp->op1)
- (*dp->op1)(dp->bytemode1);
+ (*dp->op1)(dp->bytemode1, aflag, dflag);
obufp = op2out;
op_ad = 1;
if (dp->op2)
- (*dp->op2)(dp->bytemode2);
+ (*dp->op2)(dp->bytemode2, aflag, dflag);
obufp = op3out;
op_ad = 0;
if (dp->op3)
- (*dp->op3)(dp->bytemode3);
+ (*dp->op3)(dp->bytemode3, aflag, dflag);
}
obufp = obuf + strlen (obuf);
return (codep - inbuf);
}
-char *float_mem[] = {
+static char *float_mem[] = {
/* d8 */
"fadds",
"fmuls",
#define ST OP_ST, 0
#define STi OP_STi, 0
-int OP_ST(), OP_STi();
#define FGRPd9_2 NULL, NULL, 0
#define FGRPd9_4 NULL, NULL, 1
#define FGRPde_3 NULL, NULL, 7
#define FGRPdf_4 NULL, NULL, 8
-struct dis386 float_reg[][8] = {
+static struct dis386 float_reg[][8] = {
/* d8 */
{
{ "fadd", ST, STi },
},
/* da */
{
- { "(bad)" },
- { "(bad)" },
- { "(bad)" },
- { "(bad)" },
+ { "fcmovb", ST, STi },
+ { "fcmove", ST, STi },
+ { "fcmovbe",ST, STi },
+ { "fcmovu", ST, STi },
{ "(bad)" },
{ FGRPda_5 },
{ "(bad)" },
},
/* db */
{
- { "(bad)" },
- { "(bad)" },
- { "(bad)" },
- { "(bad)" },
+ { "fcmovnb",ST, STi },
+ { "fcmovne",ST, STi },
+ { "fcmovnbe",ST, STi },
+ { "fcmovnu",ST, STi },
{ FGRPdb_4 },
- { "(bad)" },
- { "(bad)" },
+ { "fucomi", ST, STi },
+ { "fcomi", ST, STi },
{ "(bad)" },
},
/* dc */
{ "(bad)" },
{ "(bad)" },
{ FGRPdf_4 },
- { "(bad)" },
- { "(bad)" },
+ { "fucomip",ST, STi },
+ { "fcomip", ST, STi },
{ "(bad)" },
},
};
-char *fgrps[][8] = {
+static char *fgrps[][8] = {
/* d9_2 0 */
{
"fnop","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
};
static void
-dofloat ()
+dofloat (aflag, dflag)
+ int aflag;
+ int dflag;
{
struct dis386 *dp;
unsigned char floatop;
if (mod != 3)
{
- putop (float_mem[(floatop - 0xd8) * 8 + reg]);
+ putop (float_mem[(floatop - 0xd8) * 8 + reg], aflag, dflag);
obufp = op1out;
- OP_E (v_mode);
+ OP_E (v_mode, aflag, dflag);
return;
}
codep++;
dp = &float_reg[floatop - 0xd8][reg];
if (dp->name == NULL)
{
- putop (fgrps[dp->bytemode1][rm]);
+ putop (fgrps[dp->bytemode1][rm], aflag, dflag);
/* instruction fnstsw is only one with strange arg */
if (floatop == 0xdf
&& FETCH_DATA (the_info, codep + 1)
}
else
{
- putop (dp->name);
+ putop (dp->name, aflag, dflag);
obufp = op1out;
if (dp->op1)
- (*dp->op1)(dp->bytemode1);
+ (*dp->op1)(dp->bytemode1, aflag, dflag);
obufp = op2out;
if (dp->op2)
- (*dp->op2)(dp->bytemode2);
+ (*dp->op2)(dp->bytemode2, aflag, dflag);
}
}
/* ARGSUSED */
-int
-OP_ST (ignore)
+static int
+OP_ST (ignore, aflag, dflag)
int ignore;
+ int aflag;
+ int dflag;
{
oappend ("%st");
return (0);
}
/* ARGSUSED */
-int
-OP_STi (ignore)
+static int
+OP_STi (ignore, aflag, dflag)
int ignore;
+ int aflag;
+ int dflag;
{
sprintf (scratchbuf, "%%st(%d)", rm);
oappend (scratchbuf);
/* capital letters in template are macros */
static void
-putop (template)
+putop (template, aflag, dflag)
char *template;
+ int aflag;
+ int dflag;
{
char *p;
*obufp++ = *p;
break;
case 'C': /* For jcxz/jecxz */
- if (aflag == 0)
+ if (aflag)
*obufp++ = 'e';
break;
case 'N':
else
*obufp++ = 'w';
break;
+ case 'W':
+ /* operand size flag for cwtl, cbtw */
+ if (dflag)
+ *obufp++ = 'w';
+ else
+ *obufp++ = 'b';
+ break;
}
}
*obufp = 0;
oappend ("%gs:");
}
-int
-OP_indirE (bytemode)
+static int
+OP_indirE (bytemode, aflag, dflag)
int bytemode;
+ int aflag;
+ int dflag;
{
oappend ("*");
- OP_E (bytemode);
- return (0);
+ return OP_E (bytemode, aflag, dflag);
}
-int
-OP_E (bytemode)
+static int
+OP_E (bytemode, aflag, dflag)
int bytemode;
+ int aflag;
+ int dflag;
{
int disp;
- int havesib;
- int base;
- int index;
- int scale;
- int havebase;
-
+
/* skip mod/rm byte */
codep++;
-
- havesib = 0;
- havebase = 0;
- disp = 0;
-
+
if (mod == 3)
{
switch (bytemode)
oappend ("<bad dis table>");
break;
}
- return (0);
+ return 0;
}
-
+
+ disp = 0;
append_prefix ();
- if (rm == 4)
+
+ if (aflag) /* 32 bit address mode */
{
- havesib = 1;
+ int havesib;
+ int havebase;
+ int base;
+ int index;
+ int scale;
+
+ havesib = 0;
havebase = 1;
- FETCH_DATA (the_info, codep + 1);
- scale = (*codep >> 6) & 3;
- index = (*codep >> 3) & 7;
- base = *codep & 7;
- codep++;
- }
-
- switch (mod)
- {
- case 0:
- switch (rm)
+ base = rm;
+
+ if (base == 4)
+ {
+ havesib = 1;
+ FETCH_DATA (the_info, codep + 1);
+ scale = (*codep >> 6) & 3;
+ index = (*codep >> 3) & 7;
+ base = *codep & 7;
+ codep++;
+ }
+
+ switch (mod)
{
- case 4:
- /* implies havesib and havebase */
- if (base == 5) {
- havebase = 0;
- disp = get32 ();
- }
+ case 0:
+ if (base == 5)
+ {
+ havebase = 0;
+ disp = get32 ();
+ }
break;
- case 5:
- disp = get32 ();
+ case 1:
+ FETCH_DATA (the_info, codep + 1);
+ disp = *(char *)codep++;
break;
- default:
- havebase = 1;
- base = rm;
+ case 2:
+ disp = get32 ();
break;
}
- break;
- case 1:
- FETCH_DATA (the_info, codep + 1);
- disp = *(char *)codep++;
- if (rm != 4)
- {
- havebase = 1;
- base = rm;
- }
- break;
- case 2:
- disp = get32 ();
- if (rm != 4)
+
+ if (mod != 0 || base == 5)
{
- havebase = 1;
- base = rm;
+ sprintf (scratchbuf, "0x%x", disp);
+ oappend (scratchbuf);
}
- break;
- }
-
- if (mod != 0 || rm == 5 || (havesib && base == 5))
- {
- sprintf (scratchbuf, "0x%x", disp);
- oappend (scratchbuf);
- }
-
- if (havebase || havesib)
- {
- oappend ("(");
- if (havebase)
- oappend (names32[base]);
- if (havesib)
+
+ if (havebase || (havesib && (index != 4 || scale != 0)))
{
- if (index != 4)
+ oappend ("(");
+ if (havebase)
+ oappend (names32[base]);
+ if (havesib)
{
- sprintf (scratchbuf, ",%s", names32[index]);
+ if (index != 4)
+ {
+ sprintf (scratchbuf, ",%s", names32[index]);
+ oappend (scratchbuf);
+ }
+ sprintf (scratchbuf, ",%d", 1 << scale);
oappend (scratchbuf);
}
- sprintf (scratchbuf, ",%d", 1 << scale);
+ oappend (")");
+ }
+ }
+ else
+ { /* 16 bit address mode */
+ switch (mod)
+ {
+ case 0:
+ if (rm == 6)
+ disp = (short) get16 ();
+ break;
+ case 1:
+ FETCH_DATA (the_info, codep + 1);
+ disp = *(char *)codep++;
+ break;
+ case 2:
+ disp = (short) get16 ();
+ break;
+ }
+
+ if (mod != 0 || rm == 6)
+ {
+ sprintf (scratchbuf, "0x%x", disp);
oappend (scratchbuf);
}
- oappend (")");
+
+ if (mod != 0 || rm != 6)
+ {
+ oappend ("(");
+ oappend (index16[rm]);
+ oappend (")");
+ }
}
- return (0);
+ return 0;
}
-int
-OP_G (bytemode)
+static int
+OP_G (bytemode, aflag, dflag)
int bytemode;
+ int aflag;
+ int dflag;
{
switch (bytemode)
{
op_address[op_ad] = op;
}
-int
-OP_REG (code)
+static int
+OP_REG (code, aflag, dflag)
int code;
+ int aflag;
+ int dflag;
{
char *s;
return (0);
}
-int
-OP_I (bytemode)
+static int
+OP_I (bytemode, aflag, dflag)
int bytemode;
+ int aflag;
+ int dflag;
{
int op;
return (0);
}
-int
-OP_sI (bytemode)
+static int
+OP_sI (bytemode, aflag, dflag)
int bytemode;
+ int aflag;
+ int dflag;
{
int op;
return (0);
}
-int
-OP_J (bytemode)
+static int
+OP_J (bytemode, aflag, dflag)
int bytemode;
+ int aflag;
+ int dflag;
{
int disp;
int mask = -1;
}
/* ARGSUSED */
-int
-OP_SEG (dummy)
+static int
+OP_SEG (dummy, aflag, dflag)
int dummy;
+ int aflag;
+ int dflag;
{
static char *sreg[] = {
"%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
return (0);
}
-int
-OP_DIR (size)
+static int
+OP_DIR (size, aflag, dflag)
int size;
+ int aflag;
+ int dflag;
{
int seg, offset;
}
/* ARGSUSED */
-int
-OP_OFF (bytemode)
+static int
+OP_OFF (bytemode, aflag, dflag)
int bytemode;
+ int aflag;
+ int dflag;
{
int off;
-
+
+ append_prefix ();
+
if (aflag)
off = get32 ();
else
}
/* ARGSUSED */
-int
-OP_ESDI (dummy)
- int dummy;
+static int
+OP_ESDI (dummy, aflag, dflag)
+ int dummy;
+ int aflag;
+ int dflag;
{
oappend ("%es:(");
oappend (aflag ? "%edi" : "%di");
}
/* ARGSUSED */
-int
-OP_DSSI (dummy)
- int dummy;
+static int
+OP_DSSI (dummy, aflag, dflag)
+ int dummy;
+ int aflag;
+ int dflag;
{
oappend ("%ds:(");
oappend (aflag ? "%esi" : "%si");
return (0);
}
+#if 0
+/* Not used. */
+
/* ARGSUSED */
-int
-OP_ONE (dummy)
- int dummy;
+static int
+OP_ONE (dummy, aflag, dflag)
+ int dummy;
+ int aflag;
+ int dflag;
{
oappend ("1");
return (0);
}
+#endif
+
/* ARGSUSED */
-int
-OP_C (dummy)
- int dummy;
+static int
+OP_C (dummy, aflag, dflag)
+ int dummy;
+ int aflag;
+ int dflag;
{
codep++; /* skip mod/rm */
sprintf (scratchbuf, "%%cr%d", reg);
}
/* ARGSUSED */
-int
-OP_D (dummy)
- int dummy;
+static int
+OP_D (dummy, aflag, dflag)
+ int dummy;
+ int aflag;
+ int dflag;
{
codep++; /* skip mod/rm */
sprintf (scratchbuf, "%%db%d", reg);
}
/* ARGSUSED */
-int
-OP_T (dummy)
+static int
+OP_T (dummy, aflag, dflag)
int dummy;
+ int aflag;
+ int dflag;
{
codep++; /* skip mod/rm */
sprintf (scratchbuf, "%%tr%d", reg);
return (0);
}
-int
-OP_rm (bytemode)
+static int
+OP_rm (bytemode, aflag, dflag)
int bytemode;
+ int aflag;
+ int dflag;
{
switch (bytemode)
{
}
return (0);
}
+
+static int
+OP_MMX (bytemode, aflag, dflag)
+ int bytemode;
+ int aflag;
+ int dflag;
+{
+ sprintf (scratchbuf, "%%mm%d", reg);
+ oappend (scratchbuf);
+ return 0;
+}
+
+static int
+OP_EM (bytemode, aflag, dflag)
+ int bytemode;
+ int aflag;
+ int dflag;
+{
+ if (mod != 3)
+ return OP_E (bytemode, aflag, dflag);
+
+ codep++;
+ sprintf (scratchbuf, "%%mm%d", rm);
+ oappend (scratchbuf);
+ return 0;
+}
+
+static int
+OP_MS (bytemode, aflag, dflag)
+ int bytemode;
+ int aflag;
+ int dflag;
+{
+ ++codep;
+ sprintf (scratchbuf, "%%mm%d", rm);
+ oappend (scratchbuf);
+ return 0;
+}