/* 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, 1996 Free Software Foundation, Inc.
This file is part of GDB.
#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();
+typedef int op_rtn PARAMS ((int bytemode, int aflag, int dflag));
-static void dofloat (), putop (), append_prefix (), set_op ();
-static int get16 (), get32 ();
+static op_rtn OP_E, OP_G, OP_I, OP_indirE, OP_sI, OP_REG, OP_J, OP_DIR, OP_OFF;
+static op_rtn OP_ESDI, OP_DSSI, OP_SEG, OP_ONE, OP_C, OP_D, OP_T, OP_rm, OP_ST;
+static op_rtn OP_STi;
+
+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
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 },
{ GRP5 },
};
-struct dis386 dis386_twobyte[] = {
+static struct dis386 dis386_twobyte[] = {
/* 00 */
{ GRP6 },
{ GRP7 },
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 },
}
}
-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;
+{
+ print_insn_x86 (pc, info, 1, 1);
+}
+
+int
+print_insn_i8086 (pc, info)
+ bfd_vma pc;
+ disassemble_info *info;
+{
+ print_insn_x86 (pc, info, 0, 0);
+}
+
+int
+print_insn_x86 (pc, info, aflag, dflag)
+ bfd_vma pc;
+ disassemble_info *info;
{
struct dis386 *dp;
int i;
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 (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 },
};
-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':
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");
}
/* ARGSUSED */
-int
-OP_ONE (dummy)
- int dummy;
+static int
+OP_ONE (dummy, aflag, dflag)
+ int dummy;
+ int aflag;
+ int dflag;
{
oappend ("1");
return (0);
}
/* 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)
{