/* Print i386 instructions for GDB, the GNU debugger.
- Copyright (C) 1988, 1989, 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1988, 89, 91, 93, 94, 95, 96, 97, 1998
+ Free Software Foundation, Inc.
This file is part of GDB.
#include "dis-asm.h"
#include "sysdep.h"
+#include "opintl.h"
#define MAXLEN 20
#include <setjmp.h>
+#ifndef UNIXWARE_COMPAT
+/* Set non-zero for broken, compatible instructions. Set to zero for
+ non-broken opcodes. */
+#define UNIXWARE_COMPAT 1
+#endif
+
+
+static int fetch_data PARAMS ((struct disassemble_info *, bfd_byte *));
+
struct dis_private
{
/* Points to first byte not fetched. */
#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 Av OP_DIR, v_mode
#define Ob OP_OFF, b_mode
#define Ov OP_OFF, v_mode
-#define Xb OP_DSSI, b_mode
-#define Xv OP_DSSI, v_mode
-#define Yb OP_ESDI, b_mode
-#define Yv OP_ESDI, v_mode
+#define Xb OP_DSreg, eSI_reg
+#define Xv OP_DSreg, eSI_reg
+#define Yb OP_ESreg, eDI_reg
+#define Yv OP_ESreg, eDI_reg
+#define DSBX OP_DSreg, eBX_reg
#define es OP_REG, es_reg
#define ss OP_REG, ss_reg
#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
+
+/* bits in sizeflag */
+#if 0 /* leave undefined until someone adds the extra flag to objdump */
+#define SUFFIX_ALWAYS 4
+#endif
+#define AFLAG 2
+#define DFLAG 1
+
+typedef void (*op_rtn) PARAMS ((int bytemode, int sizeflag));
+
+static void OP_E PARAMS ((int, int));
+static void OP_G PARAMS ((int, int));
+static void OP_I PARAMS ((int, int));
+static void OP_indirE PARAMS ((int, int));
+static void OP_sI PARAMS ((int, int));
+static void OP_REG PARAMS ((int, int));
+static void OP_J PARAMS ((int, int));
+static void OP_DIR PARAMS ((int, int));
+static void OP_OFF PARAMS ((int, int));
+static void OP_ESreg PARAMS ((int, int));
+static void OP_DSreg PARAMS ((int, int));
+static void OP_SEG PARAMS ((int, int));
+static void OP_C PARAMS ((int, int));
+static void OP_D PARAMS ((int, int));
+static void OP_T PARAMS ((int, int));
+static void OP_rm PARAMS ((int, int));
+static void OP_ST PARAMS ((int, int));
+static void OP_STi PARAMS ((int, int));
+#if 0
+static void OP_ONE PARAMS ((int, int));
+#endif
+static void OP_MMX PARAMS ((int, int));
+static void OP_EM PARAMS ((int, int));
+static void OP_MS PARAMS ((int, int));
+
+static void append_seg PARAMS ((void));
+static void set_op PARAMS ((unsigned int op));
+static void putop PARAMS ((char *template, int sizeflag));
+static void dofloat PARAMS ((int sizeflag));
+static int get16 PARAMS ((void));
+static int get32 PARAMS ((void));
+static void ckprefix PARAMS ((void));
+static void ptr_reg PARAMS ((int, int));
#define b_mode 1
#define v_mode 2
#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[] = {
+/* Upper case letters in the instruction names here are macros.
+ 'A' => print 'b' if no register operands or suffix_always is true
+ 'B' => print 'b' if suffix_always is true
+ 'E' => print 'e' if 32-bit form of jcxz
+ 'L' => print 'l' if suffix_always is true
+ 'N' => print 'n' if instruction has no wait "prefix"
+ 'P' => print 'w' or 'l' if instruction has an operand size prefix,
+ or suffix_always is true
+ 'Q' => print 'w' or 'l' if no register operands or suffix_always is true
+ 'R' => print 'w' or 'l'
+ 'S' => print 'w' or 'l' if suffix_always is true
+ 'W' => print 'b' or 'w'
+*/
+
+static struct dis386 dis386[] = {
/* 00 */
- { "addb", Eb, Gb },
+ { "addB", Eb, Gb },
{ "addS", Ev, Gv },
- { "addb", Gb, Eb },
+ { "addB", Gb, Eb },
{ "addS", Gv, Ev },
- { "addb", AL, Ib },
+ { "addB", AL, Ib },
{ "addS", eAX, Iv },
- { "pushl", es },
- { "popl", es },
+ { "pushP", es },
+ { "popP", es },
/* 08 */
- { "orb", Eb, Gb },
+ { "orB", Eb, Gb },
{ "orS", Ev, Gv },
- { "orb", Gb, Eb },
+ { "orB", Gb, Eb },
{ "orS", Gv, Ev },
- { "orb", AL, Ib },
+ { "orB", AL, Ib },
{ "orS", eAX, Iv },
- { "pushl", cs },
+ { "pushP", cs },
{ "(bad)" }, /* 0x0f extended opcode escape */
/* 10 */
- { "adcb", Eb, Gb },
+ { "adcB", Eb, Gb },
{ "adcS", Ev, Gv },
- { "adcb", Gb, Eb },
+ { "adcB", Gb, Eb },
{ "adcS", Gv, Ev },
- { "adcb", AL, Ib },
+ { "adcB", AL, Ib },
{ "adcS", eAX, Iv },
- { "pushl", ss },
- { "popl", ss },
+ { "pushP", ss },
+ { "popP", ss },
/* 18 */
- { "sbbb", Eb, Gb },
+ { "sbbB", Eb, Gb },
{ "sbbS", Ev, Gv },
- { "sbbb", Gb, Eb },
+ { "sbbB", Gb, Eb },
{ "sbbS", Gv, Ev },
- { "sbbb", AL, Ib },
+ { "sbbB", AL, Ib },
{ "sbbS", eAX, Iv },
- { "pushl", ds },
- { "popl", ds },
+ { "pushP", ds },
+ { "popP", ds },
/* 20 */
- { "andb", Eb, Gb },
+ { "andB", Eb, Gb },
{ "andS", Ev, Gv },
- { "andb", Gb, Eb },
+ { "andB", Gb, Eb },
{ "andS", Gv, Ev },
- { "andb", AL, Ib },
+ { "andB", AL, Ib },
{ "andS", eAX, Iv },
{ "(bad)" }, /* SEG ES prefix */
{ "daa" },
/* 28 */
- { "subb", Eb, Gb },
+ { "subB", Eb, Gb },
{ "subS", Ev, Gv },
- { "subb", Gb, Eb },
+ { "subB", Gb, Eb },
{ "subS", Gv, Ev },
- { "subb", AL, Ib },
+ { "subB", AL, Ib },
{ "subS", eAX, Iv },
{ "(bad)" }, /* SEG CS prefix */
{ "das" },
/* 30 */
- { "xorb", Eb, Gb },
+ { "xorB", Eb, Gb },
{ "xorS", Ev, Gv },
- { "xorb", Gb, Eb },
+ { "xorB", Gb, Eb },
{ "xorS", Gv, Ev },
- { "xorb", AL, Ib },
+ { "xorB", AL, Ib },
{ "xorS", eAX, Iv },
{ "(bad)" }, /* SEG SS prefix */
{ "aaa" },
/* 38 */
- { "cmpb", Eb, Gb },
+ { "cmpB", Eb, Gb },
{ "cmpS", Ev, Gv },
- { "cmpb", Gb, Eb },
+ { "cmpB", Gb, Eb },
{ "cmpS", Gv, Ev },
- { "cmpb", AL, Ib },
+ { "cmpB", AL, Ib },
{ "cmpS", eAX, Iv },
{ "(bad)" }, /* SEG DS prefix */
{ "aas" },
{ "popS", eSI },
{ "popS", eDI },
/* 60 */
- { "pusha" },
- { "popa" },
+ { "pushaP" },
+ { "popaP" },
{ "boundS", Gv, Ma },
{ "arpl", Ew, Gw },
{ "(bad)" }, /* seg fs */
{ "(bad)" }, /* op size prefix */
{ "(bad)" }, /* adr size prefix */
/* 68 */
- { "pushS", Iv }, /* 386 book wrong */
+ { "pushP", Iv }, /* 386 book wrong */
{ "imulS", Gv, Ev, Iv },
- { "pushl", sIb }, /* push of byte really pushes 4 bytes */
- { "imulS", Gv, Ev, Ib },
+ { "pushP", sIb }, /* push of byte really pushes 2 or 4 bytes */
+ { "imulS", Gv, Ev, sIb },
{ "insb", Yb, indirDX },
- { "insS", Yv, indirDX },
+ { "insR", Yv, indirDX },
{ "outsb", indirDX, Xb },
- { "outsS", indirDX, Xv },
+ { "outsR", indirDX, Xv },
/* 70 */
{ "jo", Jb },
{ "jno", Jb },
{ "jp", Jb },
{ "jnp", Jb },
{ "jl", Jb },
- { "jnl", Jb },
+ { "jge", Jb },
{ "jle", Jb },
{ "jg", Jb },
/* 80 */
{ GRP1S },
{ "(bad)" },
{ GRP1Ss },
- { "testb", Eb, Gb },
+ { "testB", Eb, Gb },
{ "testS", Ev, Gv },
- { "xchgb", Eb, Gb },
+ { "xchgB", Eb, Gb },
{ "xchgS", Ev, Gv },
/* 88 */
- { "movb", Eb, Gb },
+ { "movB", Eb, Gb },
{ "movS", Ev, Gv },
- { "movb", Gb, Eb },
+ { "movB", Gb, Eb },
{ "movS", Gv, Ev },
- { "movw", Ew, Sw },
+ { "movQ", Ev, Sw },
{ "leaS", Gv, M },
- { "movw", Sw, Ew },
- { "popS", Ev },
+ { "movQ", Sw, Ev },
+ { "popQ", Ev },
/* 90 */
{ "nop" },
{ "xchgS", eCX, eAX },
{ "xchgS", eSI, eAX },
{ "xchgS", eDI, eAX },
/* 98 */
- { "cwtl" },
- { "cltd" },
- { "lcall", Ap },
+ { "cWtR" },
+ { "cRtd" },
+ { "lcallP", Ap },
{ "(bad)" }, /* fwait */
- { "pushf" },
- { "popf" },
+ { "pushfP" },
+ { "popfP" },
{ "sahf" },
{ "lahf" },
/* a0 */
- { "movb", AL, Ob },
+ { "movB", AL, Ob },
{ "movS", eAX, Ov },
- { "movb", Ob, AL },
+ { "movB", Ob, AL },
{ "movS", Ov, eAX },
{ "movsb", Yb, Xb },
- { "movsS", Yv, Xv },
- { "cmpsb", Yb, Xb },
- { "cmpsS", Yv, Xv },
+ { "movsR", Yv, Xv },
+ { "cmpsb", Xb, Yb },
+ { "cmpsR", Xv, Yv },
/* a8 */
- { "testb", AL, Ib },
+ { "testB", AL, Ib },
{ "testS", eAX, Iv },
- { "stosb", Yb, AL },
+ { "stosB", Yb, AL },
{ "stosS", Yv, eAX },
- { "lodsb", AL, Xb },
+ { "lodsB", AL, Xb },
{ "lodsS", eAX, Xv },
- { "scasb", AL, Yb },
+ { "scasB", AL, Yb },
{ "scasS", eAX, Yv },
/* b0 */
- { "movb", AL, Ib },
- { "movb", CL, Ib },
- { "movb", DL, Ib },
- { "movb", BL, Ib },
- { "movb", AH, Ib },
- { "movb", CH, Ib },
- { "movb", DH, Ib },
- { "movb", BH, Ib },
+ { "movB", AL, Ib },
+ { "movB", CL, Ib },
+ { "movB", DL, Ib },
+ { "movB", BL, Ib },
+ { "movB", AH, Ib },
+ { "movB", CH, Ib },
+ { "movB", DH, Ib },
+ { "movB", BH, Ib },
/* b8 */
{ "movS", eAX, Iv },
{ "movS", eCX, Iv },
/* c0 */
{ GRP2b },
{ GRP2S },
- { "ret", Iw },
- { "ret" },
+ { "retP", Iw },
+ { "retP" },
{ "lesS", Gv, Mp },
{ "ldsS", Gv, Mp },
- { "movb", Eb, Ib },
- { "movS", Ev, Iv },
+ { "movA", Eb, Ib },
+ { "movQ", Ev, Iv },
/* c8 */
- { "enter", Iw, Ib },
- { "leave" },
- { "lret", Iw },
- { "lret" },
+ { "enterP", Iw, Ib },
+ { "leaveP" },
+ { "lretP", Iw },
+ { "lretP" },
{ "int3" },
{ "int", Ib },
{ "into" },
- { "iret" },
+ { "iretP" },
/* d0 */
{ GRP2b_one },
{ GRP2S_one },
{ GRP2b_cl },
{ GRP2S_cl },
- { "aam", Ib },
- { "aad", Ib },
+ { "aam", sIb },
+ { "aad", sIb },
{ "(bad)" },
- { "xlat" },
+ { "xlat", DSBX },
/* d8 */
{ FLOAT },
{ FLOAT },
{ "loopne", Jb },
{ "loope", Jb },
{ "loop", Jb },
- { "jCcxz", Jb },
- { "inb", AL, Ib },
+ { "jEcxz", Jb },
+ { "inB", AL, Ib },
{ "inS", eAX, Ib },
- { "outb", Ib, AL },
+ { "outB", Ib, AL },
{ "outS", Ib, eAX },
/* e8 */
- { "call", Av },
- { "jmp", Jv },
- { "ljmp", Ap },
+ { "callP", Av },
+ { "jmpP", Jv },
+ { "ljmpP", Ap },
{ "jmp", Jb },
- { "inb", AL, indirDX },
+ { "inB", AL, indirDX },
{ "inS", eAX, indirDX },
- { "outb", indirDX, AL },
+ { "outB", indirDX, AL },
{ "outS", indirDX, eAX },
/* f0 */
{ "(bad)" }, /* lock prefix */
{ GRP5 },
};
-struct dis386 dis386_twobyte[] = {
+static struct dis386 dis386_twobyte[] = {
/* 00 */
{ GRP6 },
{ GRP7 },
/* 08 */
{ "invd" },
{ "wbinvd" },
- { "(bad)" }, { "ud2a" },
+ { "(bad)" },
+ { "ud2a" },
{ "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
/* 10 */
{ "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
{ "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
/* 20 */
/* these are all backward in appendix A of the intel book */
- { "movl", Rd, Cd },
- { "movl", Rd, Dd },
- { "movl", Cd, Rd },
- { "movl", Dd, Rd },
- { "movl", Rd, Td },
+ { "movL", Rd, Cd },
+ { "movL", Rd, Dd },
+ { "movL", Cd, Rd },
+ { "movL", Dd, Rd },
+ { "movL", Rd, Td },
{ "(bad)" },
- { "movl", Td, Rd },
+ { "movL", Td, Rd },
{ "(bad)" },
/* 28 */
{ "(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 },
+ { "pushP", fs },
+ { "popP", fs },
{ "cpuid" },
{ "btS", Ev, Gv },
{ "shldS", Ev, Gv, Ib },
{ "(bad)" },
{ "(bad)" },
/* a8 */
- { "pushl", gs },
- { "popl", gs },
+ { "pushP", gs },
+ { "popP", gs },
{ "rsm" },
{ "btsS", Ev, Gv },
{ "shrdS", Ev, Gv, Ib },
{ "(bad)" },
{ "imulS", Gv, Ev },
/* b0 */
- { "cmpxchgb", Eb, Gb },
+ { "cmpxchgB", Eb, Gb },
{ "cmpxchgS", Ev, Gv },
{ "lssS", Gv, Mp }, /* 386 lists only Mp */
{ "btrS", Ev, Gv },
{ "lfsS", Gv, Mp }, /* 386 lists only Mp */
{ "lgsS", Gv, Mp }, /* 386 lists only Mp */
- { "movzbS", Gv, Eb },
- { "movzwS", Gv, Ew },
+ { "movzbR", Gv, Eb },
+ { "movzwR", Gv, Ew }, /* yes, there really is movzww ! */
/* b8 */
- { "ud2b" },
{ "(bad)" },
+ { "ud2b" },
{ GRP8 },
{ "btcS", Ev, Gv },
{ "bsfS", Gv, Ev },
{ "bsrS", Gv, Ev },
- { "movsbS", Gv, Eb },
- { "movswS", Gv, Ew },
+ { "movsbR", Gv, Eb },
+ { "movswR", Gv, Ew }, /* yes, there really is movsww ! */
/* c0 */
- { "xaddb", Eb, Gb },
+ { "xaddB", Eb, Gb },
{ "xaddS", Ev, Gv },
{ "(bad)" },
{ "(bad)" },
{ "(bad)" },
{ GRP9 },
/* c8 */
- { "bswap", eAX },
+ { "bswap", eAX }, /* bswap doesn't support 16 bit regs */
{ "bswap", eCX },
{ "bswap", eDX },
{ "bswap", eBX },
{ "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] = {
};
static const unsigned char twobyte_has_modrm[256] = {
- 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,
- 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,
- 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,
- 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,1,1,1,1,1,0,0,0,1,1,1,1,1,
- 1,1,1,1,1,1,1,1,0,0,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,0,0,0,0,0,0,0,0
+ /* 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,0,1,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 },
- { "orb", Eb, Ib },
- { "adcb", Eb, Ib },
- { "sbbb", Eb, Ib },
- { "andb", Eb, Ib },
- { "subb", Eb, Ib },
- { "xorb", Eb, Ib },
- { "cmpb", Eb, Ib }
+ { "addA", Eb, Ib },
+ { "orA", Eb, Ib },
+ { "adcA", Eb, Ib },
+ { "sbbA", Eb, Ib },
+ { "andA", Eb, Ib },
+ { "subA", Eb, Ib },
+ { "xorA", Eb, Ib },
+ { "cmpA", Eb, Ib }
},
/* GRP1S */
{
- { "addS", Ev, Iv },
- { "orS", Ev, Iv },
- { "adcS", Ev, Iv },
- { "sbbS", Ev, Iv },
- { "andS", Ev, Iv },
- { "subS", Ev, Iv },
- { "xorS", Ev, Iv },
- { "cmpS", Ev, Iv }
+ { "addQ", Ev, Iv },
+ { "orQ", Ev, Iv },
+ { "adcQ", Ev, Iv },
+ { "sbbQ", Ev, Iv },
+ { "andQ", Ev, Iv },
+ { "subQ", Ev, Iv },
+ { "xorQ", Ev, Iv },
+ { "cmpQ", Ev, Iv }
},
/* GRP1Ss */
{
- { "addS", Ev, sIb },
- { "orS", Ev, sIb },
- { "adcS", Ev, sIb },
- { "sbbS", Ev, sIb },
- { "andS", Ev, sIb },
- { "subS", Ev, sIb },
- { "xorS", Ev, sIb },
- { "cmpS", Ev, sIb }
+ { "addQ", Ev, sIb },
+ { "orQ", Ev, sIb },
+ { "adcQ", Ev, sIb },
+ { "sbbQ", Ev, sIb },
+ { "andQ", Ev, sIb },
+ { "subQ", Ev, sIb },
+ { "xorQ", Ev, sIb },
+ { "cmpQ", Ev, sIb }
},
/* GRP2b */
{
- { "rolb", Eb, Ib },
- { "rorb", Eb, Ib },
- { "rclb", Eb, Ib },
- { "rcrb", Eb, Ib },
- { "shlb", Eb, Ib },
- { "shrb", Eb, Ib },
+ { "rolA", Eb, Ib },
+ { "rorA", Eb, Ib },
+ { "rclA", Eb, Ib },
+ { "rcrA", Eb, Ib },
+ { "shlA", Eb, Ib },
+ { "shrA", Eb, Ib },
{ "(bad)" },
- { "sarb", Eb, Ib },
+ { "sarA", Eb, Ib },
},
/* GRP2S */
{
- { "rolS", Ev, Ib },
- { "rorS", Ev, Ib },
- { "rclS", Ev, Ib },
- { "rcrS", Ev, Ib },
- { "shlS", Ev, Ib },
- { "shrS", Ev, Ib },
+ { "rolQ", Ev, Ib },
+ { "rorQ", Ev, Ib },
+ { "rclQ", Ev, Ib },
+ { "rcrQ", Ev, Ib },
+ { "shlQ", Ev, Ib },
+ { "shrQ", Ev, Ib },
{ "(bad)" },
- { "sarS", Ev, Ib },
+ { "sarQ", Ev, Ib },
},
/* GRP2b_one */
{
- { "rolb", Eb },
- { "rorb", Eb },
- { "rclb", Eb },
- { "rcrb", Eb },
- { "shlb", Eb },
- { "shrb", Eb },
+ { "rolA", Eb },
+ { "rorA", Eb },
+ { "rclA", Eb },
+ { "rcrA", Eb },
+ { "shlA", Eb },
+ { "shrA", Eb },
{ "(bad)" },
- { "sarb", Eb },
+ { "sarA", Eb },
},
/* GRP2S_one */
{
- { "rolS", Ev },
- { "rorS", Ev },
- { "rclS", Ev },
- { "rcrS", Ev },
- { "shlS", Ev },
- { "shrS", Ev },
+ { "rolQ", Ev },
+ { "rorQ", Ev },
+ { "rclQ", Ev },
+ { "rcrQ", Ev },
+ { "shlQ", Ev },
+ { "shrQ", Ev },
{ "(bad)" },
- { "sarS", Ev },
+ { "sarQ", Ev },
},
/* GRP2b_cl */
{
- { "rolb", Eb, CL },
- { "rorb", Eb, CL },
- { "rclb", Eb, CL },
- { "rcrb", Eb, CL },
- { "shlb", Eb, CL },
- { "shrb", Eb, CL },
+ { "rolA", Eb, CL },
+ { "rorA", Eb, CL },
+ { "rclA", Eb, CL },
+ { "rcrA", Eb, CL },
+ { "shlA", Eb, CL },
+ { "shrA", Eb, CL },
{ "(bad)" },
- { "sarb", Eb, CL },
+ { "sarA", Eb, CL },
},
/* GRP2S_cl */
{
- { "rolS", Ev, CL },
- { "rorS", Ev, CL },
- { "rclS", Ev, CL },
- { "rcrS", Ev, CL },
- { "shlS", Ev, CL },
- { "shrS", Ev, CL },
+ { "rolQ", Ev, CL },
+ { "rorQ", Ev, CL },
+ { "rclQ", Ev, CL },
+ { "rcrQ", Ev, CL },
+ { "shlQ", Ev, CL },
+ { "shrQ", Ev, CL },
{ "(bad)" },
- { "sarS", Ev, CL }
+ { "sarQ", Ev, CL }
},
/* GRP3b */
{
- { "testb", Eb, Ib },
+ { "testA", Eb, Ib },
{ "(bad)", Eb },
- { "notb", Eb },
- { "negb", Eb },
- { "mulb", AL, Eb },
- { "imulb", AL, Eb },
- { "divb", AL, Eb },
- { "idivb", AL, Eb }
+ { "notA", Eb },
+ { "negA", Eb },
+ { "mulB", AL, Eb },
+ { "imulB", AL, Eb },
+ { "divB", AL, Eb },
+ { "idivB", AL, Eb }
},
/* GRP3S */
{
- { "testS", Ev, Iv },
+ { "testQ", Ev, Iv },
{ "(bad)" },
- { "notS", Ev },
- { "negS", Ev },
+ { "notQ", Ev },
+ { "negQ", Ev },
{ "mulS", eAX, Ev },
{ "imulS", eAX, Ev },
{ "divS", eAX, Ev },
},
/* GRP4 */
{
- { "incb", Eb },
- { "decb", Eb },
+ { "incA", Eb },
+ { "decA", Eb },
{ "(bad)" },
{ "(bad)" },
{ "(bad)" },
},
/* GRP5 */
{
- { "incS", Ev },
- { "decS", Ev },
- { "call", indirEv },
- { "lcall", indirEv },
- { "jmp", indirEv },
- { "ljmp", indirEv },
- { "pushS", Ev },
+ { "incQ", Ev },
+ { "decQ", Ev },
+ { "callP", indirEv },
+ { "lcallP", indirEv },
+ { "jmpP", indirEv },
+ { "ljmpP", indirEv },
+ { "pushQ", Ev },
{ "(bad)" },
},
/* GRP6 */
{ "(bad)" },
{ "(bad)" },
{ "(bad)" },
- { "btS", Ev, Ib },
- { "btsS", Ev, Ib },
- { "btrS", Ev, Ib },
- { "btcS", Ev, Ib },
+ { "btQ", Ev, Ib },
+ { "btsQ", Ev, Ib },
+ { "btrQ", Ev, Ib },
+ { "btcQ", Ev, Ib },
},
/* GRP9 */
{
{ "(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)" },
}
};
#define PREFIX_FS 0x80
#define PREFIX_GS 0x100
#define PREFIX_DATA 0x200
-#define PREFIX_ADR 0x400
+#define PREFIX_ADDR 0x400
#define PREFIX_FWAIT 0x800
static int prefixes;
prefixes |= PREFIX_DATA;
break;
case 0x67:
- prefixes |= PREFIX_ADR;
+ prefixes |= PREFIX_ADDR;
break;
case 0x9b:
prefixes |= PREFIX_FWAIT;
- break;
+ codep++; /* fwait is really an instruction */
+ return; /* so stop accumulating prefixes */
default:
return;
}
}
}
-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;
+static int op_ad, op_index[3];
+static unsigned int op_address[3];
+static unsigned int start_pc;
\f
/*
* The function returns the length of this instruction in bytes.
*/
+int print_insn_x86 PARAMS ((bfd_vma pc, disassemble_info *info, int sizeflag));
+
int
print_insn_i386 (pc, info)
bfd_vma pc;
disassemble_info *info;
+{
+ int flags;
+ if (info->mach == bfd_mach_i386_i386)
+ flags = AFLAG|DFLAG;
+ else if (info->mach == bfd_mach_i386_i8086)
+ flags = 0;
+ else
+ abort ();
+ return print_insn_x86 (pc, info, flags);
+}
+
+int
+print_insn_x86 (pc, info, sizeflag)
+ bfd_vma pc;
+ disassemble_info *info;
+ int sizeflag;
{
struct dis386 *dp;
int i;
- int enter_instruction;
+ int two_source_ops;
char *first, *second, *third;
int needcomma;
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;
ckprefix ();
FETCH_DATA (info, codep + 1);
- if (*codep == 0xc8)
- enter_instruction = 1;
- else
- enter_instruction = 0;
+ two_source_ops = (*codep == 0x62) || (*codep == 0xc8);
obufp = obuf;
- if (prefixes & PREFIX_REPZ)
- oappend ("repz ");
- if (prefixes & PREFIX_REPNZ)
- oappend ("repnz ");
- if (prefixes & PREFIX_LOCK)
- oappend ("lock ");
-
if ((prefixes & PREFIX_FWAIT)
&& ((*codep < 0xd8) || (*codep > 0xdf)))
{
- /* fwait not followed by floating point instruction */
+ /* fwait not followed by floating point instruction. */
(*info->fprintf_func) (info->stream, "fwait");
- return (1);
+ /* There may be other prefixes. Skip any before the fwait. */
+ return codep - inbuf;
}
- /* these would be initialized to 0 if disassembling for 8086 or 286 */
- dflag = 1;
- aflag = 1;
+ if (prefixes & PREFIX_REPZ)
+ oappend ("repz ");
+ if (prefixes & PREFIX_REPNZ)
+ oappend ("repnz ");
+ if (prefixes & PREFIX_LOCK)
+ oappend ("lock ");
if (prefixes & PREFIX_DATA)
- dflag ^= 1;
+ sizeflag ^= DFLAG;
- if (prefixes & PREFIX_ADR)
+ if (prefixes & PREFIX_ADDR)
{
- aflag ^= 1;
- oappend ("addr16 ");
+ sizeflag ^= AFLAG;
+ if (sizeflag & AFLAG)
+ oappend ("addr32 ");
+ else
+ oappend ("addr16 ");
}
if (*codep == 0x0f)
if (dp->name == NULL && dp->bytemode1 == FLOATCODE)
{
- dofloat ();
+ dofloat (sizeflag);
}
else
{
if (dp->name == NULL)
dp = &grps[dp->bytemode1][reg];
- putop (dp->name);
+ putop (dp->name, sizeflag);
obufp = op1out;
op_ad = 2;
if (dp->op1)
- (*dp->op1)(dp->bytemode1);
+ (*dp->op1)(dp->bytemode1, sizeflag);
obufp = op2out;
op_ad = 1;
if (dp->op2)
- (*dp->op2)(dp->bytemode2);
+ (*dp->op2)(dp->bytemode2, sizeflag);
obufp = op3out;
op_ad = 0;
if (dp->op3)
- (*dp->op3)(dp->bytemode3);
+ (*dp->op3)(dp->bytemode3, sizeflag);
}
obufp = obuf + strlen (obuf);
oappend (" ");
(*info->fprintf_func) (info->stream, "%s", obuf);
- /* enter instruction is printed with operands in the
- * same order as the intel book; everything else
- * is printed in reverse order
- */
- if (enter_instruction)
+ /* The enter and bound instructions are printed with operands in the same
+ order as the intel book; everything else is printed in reverse order. */
+ if (two_source_ops)
{
first = op1out;
second = op2out;
if (*first)
{
if (op_index[0] != -1)
- (*info->print_address_func) (op_address[op_index[0]], info);
+ (*info->print_address_func) ((bfd_vma) op_address[op_index[0]], info);
else
(*info->fprintf_func) (info->stream, "%s", first);
needcomma = 1;
if (needcomma)
(*info->fprintf_func) (info->stream, ",");
if (op_index[1] != -1)
- (*info->print_address_func) (op_address[op_index[1]], info);
+ (*info->print_address_func) ((bfd_vma) op_address[op_index[1]], info);
else
(*info->fprintf_func) (info->stream, "%s", second);
needcomma = 1;
if (needcomma)
(*info->fprintf_func) (info->stream, ",");
if (op_index[2] != -1)
- (*info->print_address_func) (op_address[op_index[2]], info);
+ (*info->print_address_func) ((bfd_vma) op_address[op_index[2]], info);
else
(*info->fprintf_func) (info->stream, "%s", third);
}
- return (codep - inbuf);
+ 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 },
{ "fmul", STi, ST },
{ "(bad)" },
{ "(bad)" },
+#if UNIXWARE_COMPAT
{ "fsub", STi, ST },
{ "fsubr", STi, ST },
{ "fdiv", STi, ST },
{ "fdivr", STi, ST },
+#else
+ { "fsubr", STi, ST },
+ { "fsub", STi, ST },
+ { "fdivr", STi, ST },
+ { "fdiv", STi, ST },
+#endif
},
/* dd */
{
{ "fmulp", STi, ST },
{ "(bad)" },
{ FGRPde_3 },
+#if UNIXWARE_COMPAT
{ "fsubp", STi, ST },
{ "fsubrp", STi, ST },
{ "fdivp", STi, ST },
{ "fdivrp", STi, ST },
+#else
+ { "fsubrp", STi, ST },
+ { "fsubp", STi, ST },
+ { "fdivrp", STi, ST },
+ { "fdivp", STi, ST },
+#endif
},
/* df */
{
};
-char *fgrps[][8] = {
+static char *fgrps[][8] = {
/* d9_2 0 */
{
"fnop","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
};
static void
-dofloat ()
+dofloat (sizeflag)
+ int sizeflag;
{
struct dis386 *dp;
unsigned char floatop;
if (mod != 3)
{
- putop (float_mem[(floatop - 0xd8) * 8 + reg]);
+ putop (float_mem[(floatop - 0xd8) * 8 + reg], sizeflag);
obufp = op1out;
- OP_E (v_mode);
+ OP_E (v_mode, sizeflag);
return;
}
codep++;
dp = &float_reg[floatop - 0xd8][reg];
if (dp->name == NULL)
{
- putop (fgrps[dp->bytemode1][rm]);
+ putop (fgrps[dp->bytemode1][rm], sizeflag);
/* instruction fnstsw is only one with strange arg */
if (floatop == 0xdf
&& FETCH_DATA (the_info, codep + 1)
}
else
{
- putop (dp->name);
+ putop (dp->name, sizeflag);
obufp = op1out;
if (dp->op1)
- (*dp->op1)(dp->bytemode1);
+ (*dp->op1)(dp->bytemode1, sizeflag);
obufp = op2out;
if (dp->op2)
- (*dp->op2)(dp->bytemode2);
+ (*dp->op2)(dp->bytemode2, sizeflag);
}
}
/* ARGSUSED */
-int
-OP_ST (ignore)
+static void
+OP_ST (ignore, sizeflag)
int ignore;
+ int sizeflag;
{
oappend ("%st");
- return (0);
}
/* ARGSUSED */
-int
-OP_STi (ignore)
+static void
+OP_STi (ignore, sizeflag)
int ignore;
+ int sizeflag;
{
sprintf (scratchbuf, "%%st(%d)", rm);
oappend (scratchbuf);
- return (0);
}
/* capital letters in template are macros */
static void
-putop (template)
+putop (template, sizeflag)
char *template;
+ int sizeflag;
{
char *p;
default:
*obufp++ = *p;
break;
- case 'C': /* For jcxz/jecxz */
- if (aflag == 0)
+ case 'A':
+ if (mod != 3
+#ifdef SUFFIX_ALWAYS
+ || (sizeflag & SUFFIX_ALWAYS)
+#endif
+ )
+ *obufp++ = 'b';
+ break;
+ case 'B':
+#ifdef SUFFIX_ALWAYS
+ if (sizeflag & SUFFIX_ALWAYS)
+ *obufp++ = 'b';
+#endif
+ break;
+ case 'E': /* For jcxz/jecxz */
+ if (sizeflag & AFLAG)
*obufp++ = 'e';
break;
+ case 'L':
+#ifdef SUFFIX_ALWAYS
+ if (sizeflag & SUFFIX_ALWAYS)
+ *obufp++ = 'l';
+#endif
+ break;
case 'N':
if ((prefixes & PREFIX_FWAIT) == 0)
*obufp++ = 'n';
break;
- case 'S':
- /* operand size flag */
- if (dflag)
+ case 'P':
+ if ((prefixes & PREFIX_DATA)
+#ifdef SUFFIX_ALWAYS
+ || (sizeflag & SUFFIX_ALWAYS)
+#endif
+ )
+ {
+ if (sizeflag & DFLAG)
+ *obufp++ = 'l';
+ else
+ *obufp++ = 'w';
+ }
+ break;
+ case 'Q':
+ if (mod != 3
+#ifdef SUFFIX_ALWAYS
+ || (sizeflag & SUFFIX_ALWAYS)
+#endif
+ )
+ {
+ if (sizeflag & DFLAG)
+ *obufp++ = 'l';
+ else
+ *obufp++ = 'w';
+ }
+ break;
+ case 'R':
+ if (sizeflag & DFLAG)
*obufp++ = 'l';
else
*obufp++ = 'w';
break;
+ case 'S':
+#ifdef SUFFIX_ALWAYS
+ if (sizeflag & SUFFIX_ALWAYS)
+ {
+ if (sizeflag & DFLAG)
+ *obufp++ = 'l';
+ else
+ *obufp++ = 'w';
+ }
+#endif
+ break;
+ case 'W':
+ /* operand size flag for cwtl, cbtw */
+ if (sizeflag & DFLAG)
+ *obufp++ = 'w';
+ else
+ *obufp++ = 'b';
+ break;
}
}
*obufp = 0;
{
strcpy (obufp, s);
obufp += strlen (s);
- *obufp = 0;
}
static void
-append_prefix ()
+append_seg ()
{
if (prefixes & PREFIX_CS)
oappend ("%cs:");
oappend ("%gs:");
}
-int
-OP_indirE (bytemode)
+static void
+OP_indirE (bytemode, sizeflag)
int bytemode;
+ int sizeflag;
{
oappend ("*");
- OP_E (bytemode);
- return (0);
+ OP_E (bytemode, sizeflag);
}
-int
-OP_E (bytemode)
+static void
+OP_E (bytemode, sizeflag)
int bytemode;
+ int sizeflag;
{
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 (names16[rm]);
break;
case v_mode:
- if (dflag)
+ if (sizeflag & DFLAG)
oappend (names32[rm]);
else
oappend (names16[rm]);
oappend ("<bad dis table>");
break;
}
- return (0);
+ return;
}
-
- append_prefix ();
- if (rm == 4)
+
+ disp = 0;
+ append_seg ();
+
+ if (sizeflag & AFLAG) /* 32 bit address mode */
{
- havesib = 1;
+ int havesib;
+ int havebase;
+ int base;
+ int index = 0;
+ int scale = 0;
+
+ 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 = *codep++;
+ if ((disp & 0x80) != 0)
+ disp -= 0x100;
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)
+
+ if (mod != 0 || base == 5)
{
- havebase = 1;
- base = rm;
+ sprintf (scratchbuf, "0x%x", disp);
+ oappend (scratchbuf);
}
- break;
- case 2:
- disp = get32 ();
- if (rm != 4)
+
+ if (havebase || (havesib && (index != 4 || scale != 0)))
{
- havebase = 1;
- base = rm;
+ oappend ("(");
+ if (havebase)
+ oappend (names32[base]);
+ if (havesib)
+ {
+ if (index != 4)
+ {
+ sprintf (scratchbuf, ",%s", names32[index]);
+ oappend (scratchbuf);
+ }
+ sprintf (scratchbuf, ",%d", 1 << scale);
+ oappend (scratchbuf);
+ }
+ oappend (")");
}
- 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)
+ else
+ { /* 16 bit address mode */
+ switch (mod)
{
- if (index != 4)
+ case 0:
+ if (rm == 6)
{
- sprintf (scratchbuf, ",%s", names32[index]);
- oappend (scratchbuf);
+ disp = get16 ();
+ if ((disp & 0x8000) != 0)
+ disp -= 0x10000;
}
- sprintf (scratchbuf, ",%d", 1 << scale);
+ break;
+ case 1:
+ FETCH_DATA (the_info, codep + 1);
+ disp = *codep++;
+ if ((disp & 0x80) != 0)
+ disp -= 0x100;
+ break;
+ case 2:
+ disp = get16 ();
+ if ((disp & 0x8000) != 0)
+ disp -= 0x10000;
+ 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);
}
-int
-OP_G (bytemode)
+#define INTERNAL_DISASSEMBLER_ERROR _("<internal disassembler error>")
+
+static void
+OP_G (bytemode, sizeflag)
int bytemode;
+ int sizeflag;
{
switch (bytemode)
{
oappend (names32[reg]);
break;
case v_mode:
- if (dflag)
+ if (sizeflag & DFLAG)
oappend (names32[reg]);
else
oappend (names16[reg]);
break;
default:
- oappend ("<internal disassembler error>");
+ oappend (INTERNAL_DISASSEMBLER_ERROR);
break;
}
- return (0);
}
static int
x |= (*codep++ & 0xff) << 8;
x |= (*codep++ & 0xff) << 16;
x |= (*codep++ & 0xff) << 24;
- return (x);
+ return x;
}
static int
FETCH_DATA (the_info, codep + 2);
x = *codep++ & 0xff;
x |= (*codep++ & 0xff) << 8;
- return (x);
+ return x;
}
static void
set_op (op)
- int op;
+ unsigned int op;
{
op_index[op_ad] = op_ad;
op_address[op_ad] = op;
}
-int
-OP_REG (code)
+static void
+OP_REG (code, sizeflag)
int code;
+ int sizeflag;
{
char *s;
break;
case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg:
case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg:
- if (dflag)
+ if (sizeflag & DFLAG)
s = names32[code - eAX_reg];
else
s = names16[code - eAX_reg];
break;
default:
- s = "<internal disassembler error>";
+ s = INTERNAL_DISASSEMBLER_ERROR;
break;
}
oappend (s);
- return (0);
}
-int
-OP_I (bytemode)
+static void
+OP_I (bytemode, sizeflag)
int bytemode;
+ int sizeflag;
{
int op;
op = *codep++ & 0xff;
break;
case v_mode:
- if (dflag)
+ if (sizeflag & DFLAG)
op = get32 ();
else
op = get16 ();
op = get16 ();
break;
default:
- oappend ("<internal disassembler error>");
- return (0);
+ oappend (INTERNAL_DISASSEMBLER_ERROR);
+ return;
}
sprintf (scratchbuf, "$0x%x", op);
oappend (scratchbuf);
- return (0);
}
-int
-OP_sI (bytemode)
+static void
+OP_sI (bytemode, sizeflag)
int bytemode;
+ int sizeflag;
{
int op;
{
case b_mode:
FETCH_DATA (the_info, codep + 1);
- op = *(char *)codep++;
+ op = *codep++;
+ if ((op & 0x80) != 0)
+ op -= 0x100;
break;
case v_mode:
- if (dflag)
+ if (sizeflag & DFLAG)
op = get32 ();
else
- op = (short)get16();
+ {
+ op = get16();
+ if ((op & 0x8000) != 0)
+ op -= 0x10000;
+ }
break;
case w_mode:
- op = (short)get16 ();
+ op = get16 ();
+ if ((op & 0x8000) != 0)
+ op -= 0x10000;
break;
default:
- oappend ("<internal disassembler error>");
- return (0);
+ oappend (INTERNAL_DISASSEMBLER_ERROR);
+ return;
}
sprintf (scratchbuf, "$0x%x", op);
oappend (scratchbuf);
- return (0);
}
-int
-OP_J (bytemode)
+static void
+OP_J (bytemode, sizeflag)
int bytemode;
+ int sizeflag;
{
int disp;
int mask = -1;
{
case b_mode:
FETCH_DATA (the_info, codep + 1);
- disp = *(char *)codep++;
+ disp = *codep++;
+ if ((disp & 0x80) != 0)
+ disp -= 0x100;
break;
case v_mode:
- if (dflag)
+ if (sizeflag & DFLAG)
disp = get32 ();
else
{
- disp = (short)get16 ();
+ disp = get16 ();
+ if ((disp & 0x8000) != 0)
+ disp -= 0x10000;
/* for some reason, a data16 prefix on a jump instruction
means that the pc is masked to 16 bits after the
displacement is added! */
}
break;
default:
- oappend ("<internal disassembler error>");
- return (0);
+ oappend (INTERNAL_DISASSEMBLER_ERROR);
+ return;
}
disp = (start_pc + codep - start_codep + disp) & mask;
set_op (disp);
sprintf (scratchbuf, "0x%x", disp);
oappend (scratchbuf);
- return (0);
}
/* ARGSUSED */
-int
-OP_SEG (dummy)
+static void
+OP_SEG (dummy, sizeflag)
int dummy;
+ int sizeflag;
{
static char *sreg[] = {
"%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
};
oappend (sreg[reg]);
- return (0);
}
-int
-OP_DIR (size)
+static void
+OP_DIR (size, sizeflag)
int size;
+ int sizeflag;
{
int seg, offset;
switch (size)
{
case lptr:
- if (aflag)
+ if (sizeflag & DFLAG)
{
offset = get32 ();
seg = get16 ();
offset = get16 ();
seg = get16 ();
}
- sprintf (scratchbuf, "0x%x,0x%x", seg, offset);
+ sprintf (scratchbuf, "$0x%x,$0x%x", seg, offset);
oappend (scratchbuf);
break;
case v_mode:
- if (aflag)
+ if (sizeflag & DFLAG)
offset = get32 ();
else
- offset = (short)get16 ();
+ {
+ offset = get16 ();
+ if ((offset & 0x8000) != 0)
+ offset -= 0x10000;
+ }
offset = start_pc + codep - start_codep + offset;
set_op (offset);
oappend (scratchbuf);
break;
default:
- oappend ("<internal disassembler error>");
+ oappend (INTERNAL_DISASSEMBLER_ERROR);
break;
}
- return (0);
}
/* ARGSUSED */
-int
-OP_OFF (bytemode)
- int bytemode;
+static void
+OP_OFF (ignore, sizeflag)
+ int ignore;
+ int sizeflag;
{
int off;
-
- if (aflag)
+
+ append_seg ();
+
+ if (sizeflag & AFLAG)
off = get32 ();
else
off = get16 ();
sprintf (scratchbuf, "0x%x", off);
oappend (scratchbuf);
- return (0);
}
-/* ARGSUSED */
-int
-OP_ESDI (dummy)
- int dummy;
+static void
+ptr_reg (code, sizeflag)
+ int code;
+ int sizeflag;
{
- oappend ("%es:(");
- oappend (aflag ? "%edi" : "%di");
+ char *s;
+ oappend ("(");
+ if (sizeflag & AFLAG)
+ s = names32[code - eAX_reg];
+ else
+ s = names16[code - eAX_reg];
+ oappend (s);
oappend (")");
- return (0);
}
-/* ARGSUSED */
-int
-OP_DSSI (dummy)
- int dummy;
+static void
+OP_ESreg (code, sizeflag)
+ int code;
+ int sizeflag;
{
- oappend ("%ds:(");
- oappend (aflag ? "%esi" : "%si");
- oappend (")");
- return (0);
+ oappend ("%es:");
+ ptr_reg (code, sizeflag);
}
+static void
+OP_DSreg (code, sizeflag)
+ int code;
+ int sizeflag;
+{
+ if ((prefixes
+ & (PREFIX_CS
+ | PREFIX_DS
+ | PREFIX_SS
+ | PREFIX_ES
+ | PREFIX_FS
+ | PREFIX_GS)) == 0)
+ prefixes |= PREFIX_DS;
+ append_seg();
+ ptr_reg (code, sizeflag);
+}
+
+#if 0
+/* Not used. */
+
/* ARGSUSED */
-int
-OP_ONE (dummy)
- int dummy;
+static void
+OP_ONE (dummy, sizeflag)
+ int dummy;
+ int sizeflag;
{
oappend ("1");
- return (0);
}
+#endif
+
/* ARGSUSED */
-int
-OP_C (dummy)
- int dummy;
+static void
+OP_C (dummy, sizeflag)
+ int dummy;
+ int sizeflag;
{
codep++; /* skip mod/rm */
sprintf (scratchbuf, "%%cr%d", reg);
oappend (scratchbuf);
- return (0);
}
/* ARGSUSED */
-int
-OP_D (dummy)
- int dummy;
+static void
+OP_D (dummy, sizeflag)
+ int dummy;
+ int sizeflag;
{
codep++; /* skip mod/rm */
sprintf (scratchbuf, "%%db%d", reg);
oappend (scratchbuf);
- return (0);
}
/* ARGSUSED */
-int
-OP_T (dummy)
+static void
+OP_T (dummy, sizeflag)
int dummy;
+ int sizeflag;
{
codep++; /* skip mod/rm */
sprintf (scratchbuf, "%%tr%d", reg);
oappend (scratchbuf);
- return (0);
}
-int
-OP_rm (bytemode)
+static void
+OP_rm (bytemode, sizeflag)
int bytemode;
+ int sizeflag;
{
switch (bytemode)
{
oappend (names16[rm]);
break;
}
- return (0);
+}
+
+static void
+OP_MMX (ignore, sizeflag)
+ int ignore;
+ int sizeflag;
+{
+ sprintf (scratchbuf, "%%mm%d", reg);
+ oappend (scratchbuf);
+}
+
+static void
+OP_EM (bytemode, sizeflag)
+ int bytemode;
+ int sizeflag;
+{
+ if (mod != 3)
+ {
+ OP_E (bytemode, sizeflag);
+ return;
+ }
+
+ codep++;
+ sprintf (scratchbuf, "%%mm%d", rm);
+ oappend (scratchbuf);
+}
+
+static void
+OP_MS (ignore, sizeflag)
+ int ignore;
+ int sizeflag;
+{
+ ++codep;
+ sprintf (scratchbuf, "%%mm%d", rm);
+ oappend (scratchbuf);
}