* Makefile.am (ld.info): Invoke makeinfo with -I options directly
[deliverable/binutils-gdb.git] / opcodes / i386-dis.c
index 3be5ac745f8179243cf992b5426eafdbfb2211da..7133337eead730a75409f6195876dd8b1842632c 100644 (file)
@@ -1,5 +1,6 @@
 /* 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.
 
@@ -15,7 +16,7 @@ GNU General Public License for more details.
 
 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)
@@ -33,13 +34,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  */
 
 #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;
@@ -52,7 +55,7 @@ struct private
    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
@@ -61,7 +64,7 @@ fetch_data (info, addr)
      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,
@@ -97,7 +100,9 @@ fetch_data (info, addr)
 #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
@@ -139,13 +144,44 @@ fetch_data (info, addr)
 #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
@@ -205,21 +241,25 @@ static int get16 (), get32 ();
 #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 },
@@ -227,8 +267,8 @@ struct dis386 dis386[] = {
   { "addS",    Gv, Ev },
   { "addb",    AL, Ib },
   { "addS",    eAX, Iv },
-  { "pushl",   es },
-  { "popl",    es },
+  { "pushS",   es },
+  { "popS",    es },
   /* 08 */
   { "orb",     Eb, Gb },
   { "orS",     Ev, Gv },
@@ -236,7 +276,7 @@ struct dis386 dis386[] = {
   { "orS",     Gv, Ev },
   { "orb",     AL, Ib },
   { "orS",     eAX, Iv },
-  { "pushl",   cs },
+  { "pushS",   cs },
   { "(bad)" }, /* 0x0f extended opcode escape */
   /* 10 */
   { "adcb",    Eb, Gb },
@@ -245,8 +285,8 @@ struct dis386 dis386[] = {
   { "adcS",    Gv, Ev },
   { "adcb",    AL, Ib },
   { "adcS",    eAX, Iv },
-  { "pushl",   ss },
-  { "popl",    ss },
+  { "pushS",   ss },
+  { "popS",    ss },
   /* 18 */
   { "sbbb",    Eb, Gb },
   { "sbbS",    Ev, Gv },
@@ -254,8 +294,8 @@ struct dis386 dis386[] = {
   { "sbbS",    Gv, Ev },
   { "sbbb",    AL, Ib },
   { "sbbS",    eAX, Iv },
-  { "pushl",   ds },
-  { "popl",    ds },
+  { "pushS",   ds },
+  { "popS",    ds },
   /* 20 */
   { "andb",    Eb, Gb },
   { "andS",    Ev, Gv },
@@ -340,30 +380,30 @@ struct dis386 dis386[] = {
   /* 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 },
@@ -392,8 +432,8 @@ struct dis386 dis386[] = {
   { "xchgS",   eSI, eAX },
   { "xchgS",   eDI, eAX },
   /* 98 */
-  { "cwtl" },
-  { "cltd" },
+  { "cWtS" },
+  { "cStd" },
   { "lcall",   Ap },
   { "(bad)" },         /* fwait */
   { "pushf" },
@@ -510,7 +550,7 @@ struct dis386 dis386[] = {
   { GRP5 },
 };
 
-struct dis386 dis386_twobyte[] = {
+static struct dis386 dis386_twobyte[] = {
   /* 00 */
   { GRP6 },
   { GRP7 },
@@ -523,7 +563,7 @@ struct dis386 dis386_twobyte[] = {
   /* 08 */
   { "invd" },
   { "wbinvd" },
-  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },  { "ud2a" },  
   { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
   /* 10 */
   { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
@@ -545,17 +585,17 @@ struct dis386 dis386_twobyte[] = {
   { "(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)" },  
@@ -563,17 +603,36 @@ struct dis386 dis386_twobyte[] = {
   { "(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 },
@@ -611,18 +670,18 @@ struct dis386 dis386_twobyte[] = {
   { "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 },
@@ -638,7 +697,7 @@ struct dis386 dis386_twobyte[] = {
   { "movzbS", Gv, Eb },
   { "movzwS", Gv, Ew },  
   /* b8 */
-  { "(bad)" },
+  { "ud2b" },
   { "(bad)" },
   { GRP8 },
   { "btcS", Ev, Gv },  
@@ -649,8 +708,12 @@ struct dis386 dis386_twobyte[] = {
   /* c0 */
   { "xaddb", Eb, Gb },
   { "xaddS", Ev, Gv },
-  { "(bad)" },  { "(bad)" },  
-  { "(bad)" },  { "(bad)" },  { "(bad)" },  { "(bad)" },  
+  { "(bad)" },
+  { "(bad)" },  
+  { "(bad)" },
+  { "(bad)" },
+  { "(bad)" },
+  { GRP9 },  
   /* c8 */
   { "bswap", eAX },
   { "bswap", eCX },
@@ -661,23 +724,94 @@ struct dis386 dis386_twobyte[] = {
   { "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];
@@ -689,7 +823,7 @@ static disassemble_info *the_info;
 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",
@@ -703,8 +837,11 @@ static char *names8[] = {
 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 },
@@ -880,6 +1017,50 @@ struct dis386 grps[][8] = {
     { "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)" },
   }
 };
 
@@ -950,9 +1131,6 @@ ckprefix ()
     }
 }
 
-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;
@@ -967,20 +1145,40 @@ 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;
@@ -1025,63 +1223,64 @@ print_insn_i386 (pc, info)
       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);
@@ -1140,7 +1339,7 @@ print_insn_i386 (pc, info)
   return (codep - inbuf);
 }
 
-char *float_mem[] = {
+static char *float_mem[] = {
   /* d8 */
   "fadds",
   "fmuls",
@@ -1217,7 +1416,6 @@ char *float_mem[] = {
 
 #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
@@ -1229,7 +1427,7 @@ int OP_ST(), OP_STi();
 #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 },
@@ -1254,10 +1452,10 @@ struct dis386 float_reg[][8] = {
   },
   /* da */
   {
-    { "(bad)" },
-    { "(bad)" },
-    { "(bad)" },
-    { "(bad)" },
+    { "fcmovb",        ST, STi },
+    { "fcmove",        ST, STi },
+    { "fcmovbe",ST, STi },
+    { "fcmovu",        ST, STi },
     { "(bad)" },
     { FGRPda_5 },
     { "(bad)" },
@@ -1265,13 +1463,13 @@ struct dis386 float_reg[][8] = {
   },
   /* 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 */
@@ -1314,14 +1512,14 @@ struct dis386 float_reg[][8] = {
     { "(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)",
@@ -1370,7 +1568,9 @@ char *fgrps[][8] = {
 };
 
 static void
-dofloat ()
+dofloat (aflag, dflag)
+     int aflag;
+     int dflag;
 {
   struct dis386 *dp;
   unsigned char floatop;
@@ -1379,9 +1579,9 @@ dofloat ()
   
   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++;
@@ -1389,7 +1589,7 @@ dofloat ()
   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)
@@ -1398,29 +1598,33 @@ dofloat ()
     }
   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);
@@ -1430,8 +1634,10 @@ OP_STi (ignore)
 
 /* capital letters in template are macros */
 static void
-putop (template)
+putop (template, aflag, dflag)
      char *template;
+     int aflag;
+     int dflag;
 {
   char *p;
   
@@ -1443,7 +1649,7 @@ putop (template)
          *obufp++ = *p;
          break;
        case 'C':               /* For jcxz/jecxz */
-         if (aflag == 0)
+         if (aflag)
            *obufp++ = 'e';
          break;
        case 'N':
@@ -1457,6 +1663,13 @@ putop (template)
          else
            *obufp++ = 'w';
          break;
+       case 'W':
+         /* operand size flag for cwtl, cbtw */
+         if (dflag)
+           *obufp++ = 'w';
+         else
+           *obufp++ = 'b';
+         break;
        }
     }
   *obufp = 0;
@@ -1488,33 +1701,27 @@ append_prefix ()
     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)
@@ -1535,90 +1742,114 @@ OP_E (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) 
     {
@@ -1676,9 +1907,11 @@ set_op (op)
   op_address[op_ad] = op;
 }
 
-int
-OP_REG (code)
+static int
+OP_REG (code, aflag, dflag)
      int code;
+     int aflag;
+     int dflag;
 {
   char *s;
   
@@ -1712,9 +1945,11 @@ OP_REG (code)
   return (0);
 }
 
-int
-OP_I (bytemode)
+static int
+OP_I (bytemode, aflag, dflag)
      int bytemode;
+     int aflag;
+     int dflag;
 {
   int op;
   
@@ -1742,9 +1977,11 @@ OP_I (bytemode)
   return (0);
 }
 
-int
-OP_sI (bytemode)
+static int
+OP_sI (bytemode, aflag, dflag)
      int bytemode;
+     int aflag;
+     int dflag;
 {
   int op;
   
@@ -1772,9 +2009,11 @@ OP_sI (bytemode)
   return (0);
 }
 
-int
-OP_J (bytemode)
+static int
+OP_J (bytemode, aflag, dflag)
      int bytemode;
+     int aflag;
+     int dflag;
 {
   int disp;
   int mask = -1;
@@ -1809,9 +2048,11 @@ OP_J (bytemode)
 }
 
 /* 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","%?","%?",
@@ -1821,9 +2062,11 @@ OP_SEG (dummy)
   return (0);
 }
 
-int
-OP_DIR (size)
+static int
+OP_DIR (size, aflag, dflag)
      int size;
+     int aflag;
+     int dflag;
 {
   int seg, offset;
   
@@ -1862,12 +2105,16 @@ OP_DIR (size)
 }
 
 /* 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
@@ -1879,9 +2126,11 @@ OP_OFF (bytemode)
 }
 
 /* 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");
@@ -1890,9 +2139,11 @@ OP_ESDI (dummy)
 }
 
 /* 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");
@@ -1900,19 +2151,28 @@ OP_DSSI (dummy)
   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);
@@ -1921,9 +2181,11 @@ OP_C (dummy)
 }
 
 /* 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);
@@ -1932,9 +2194,11 @@ OP_D (dummy)
 }
 
 /* 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);
@@ -1942,9 +2206,11 @@ OP_T (dummy)
   return (0);
 }
 
-int
-OP_rm (bytemode)
+static int
+OP_rm (bytemode, aflag, dflag)
      int bytemode;
+     int aflag;
+     int dflag;
 {
   switch (bytemode) 
     {
@@ -1957,3 +2223,41 @@ OP_rm (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;
+}
This page took 0.042576 seconds and 4 git commands to generate.