/* Print i386 instructions for GDB, the GNU debugger.
- Copyright (C) 1988 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc.
-GDB is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY. No author or distributor accepts responsibility to anyone
-for the consequences of using it or for whether it serves any
-particular purpose or works at all, unless he says so in writing.
-Refer to the GDB General Public License for full details.
+This file is part of GDB.
-Everyone is granted permission to copy, modify and redistribute GDB,
-but only under the conditions described in the GDB General Public
-License. A copy of this license is supposed to have been given to you
-along with GDB so you can know your rights and responsibilities. It
-should be in a file named COPYING. Among other things, the copyright
-notice and this notice must be preserved on all copies.
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
-In other words, go ahead and share GDB, but don't try to stop
-anyone else from sharing it farther. Help stamp out software hoarding!
-*/
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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. */
/*
* 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu)
* the Intel manual for details.
*/
-#include <stdio.h>
+#include "defs.h"
+
#include <ctype.h>
+/* For the GDB interface at the bottom of the file... */
+#include "gdbcore.h"
+
#define Eb OP_E, b_mode
#define indirEb OP_indirE, b_mode
#define Gb OP_G, b_mode
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 b_mode 1
#define v_mode 2
static int mod;
static int rm;
static int reg;
+static void oappend ();
static char *names32[]={
"%eax","%ecx","%edx","%ebx", "%esp","%ebp","%esi","%edi",
static int prefixes;
+static void
ckprefix ()
{
prefixes = 0;
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;
+extern void fputs_filtered ();
/*
* disassemble the first instruction in 'inbuf'. You have to make
* 100 bytes is certainly enough, unless symbol printing is added later
* The function returns the length of this instruction in bytes.
*/
-i386dis (pc, inbuf, outbuf)
+
+int
+i386dis (pc, inbuf, stream)
int pc;
unsigned char *inbuf;
- char *outbuf;
+ FILE *stream;
{
struct dis386 *dp;
- char *p;
int i;
int enter_instruction;
char *first, *second, *third;
op1out[0] = 0;
op2out[0] = 0;
op3out[0] = 0;
+
+ op_index[0] = op_index[1] = op_index[2] = -1;
start_pc = pc;
start_codep = inbuf;
&& ((*codep < 0xd8) || (*codep > 0xdf)))
{
/* fwait not followed by floating point instruction */
- oappend ("fwait");
- strcpy (outbuf, obuf);
+ fputs_filtered ("fwait", stream);
return (1);
}
putop (dp->name);
obufp = op1out;
+ op_ad = 2;
if (dp->op1)
(*dp->op1)(dp->bytemode1);
obufp = op2out;
+ op_ad = 1;
if (dp->op2)
(*dp->op2)(dp->bytemode2);
obufp = op3out;
+ op_ad = 0;
if (dp->op3)
(*dp->op3)(dp->bytemode3);
}
for (i = strlen (obuf); i < 6; i++)
oappend (" ");
oappend (" ");
+ fputs_filtered (obuf, stream);
/* enter instruction is printed with operands in the
* same order as the intel book; everything else
first = op1out;
second = op2out;
third = op3out;
+ op_ad = op_index[0];
+ op_index[0] = op_index[2];
+ op_index[2] = op_ad;
}
else
{
needcomma = 0;
if (*first)
{
- oappend (first);
+ if (op_index[0] != -1)
+ print_address (op_address[op_index[0]], stream);
+ else
+ fputs_filtered (first, stream);
needcomma = 1;
}
if (*second)
{
if (needcomma)
- oappend (",");
- oappend (second);
+ fputs_filtered (",", stream);
+ if (op_index[1] != -1)
+ print_address (op_address[op_index[1]], stream);
+ else
+ fputs_filtered (second, stream);
needcomma = 1;
}
if (*third)
{
if (needcomma)
- oappend (",");
- oappend (third);
+ fputs_filtered (",", stream);
+ if (op_index[2] != -1)
+ print_address (op_address[op_index[2]], stream);
+ else
+ fputs_filtered (third, stream);
}
- strcpy (outbuf, obuf);
return (codep - inbuf);
}
},
};
-
+static void
dofloat ()
{
struct dis386 *dp;
}
/* ARGSUSED */
+int
OP_ST (ignore)
+ int ignore;
{
oappend ("%st");
+ return (0);
}
/* ARGSUSED */
+int
OP_STi (ignore)
+ int ignore;
{
sprintf (scratchbuf, "%%st(%d)", rm);
oappend (scratchbuf);
+ return (0);
}
/* capital letters in template are macros */
+static void
putop (template)
char *template;
{
*obufp = 0;
}
+static void
oappend (s)
-char *s;
+ char *s;
{
strcpy (obufp, s);
obufp += strlen (s);
*obufp = 0;
}
+static void
append_prefix ()
{
if (prefixes & PREFIX_CS)
oappend ("%gs:");
}
+int
OP_indirE (bytemode)
+ int bytemode;
{
oappend ("*");
OP_E (bytemode);
+ return (0);
}
+int
OP_E (bytemode)
+ int bytemode;
{
int disp;
int havesib;
- int didoutput = 0;
int base;
int index;
int scale;
oappend ("<bad dis table>");
break;
}
- return;
+ return (0);
}
append_prefix ();
if (mod != 0 || rm == 5 || (havesib && base == 5))
{
- sprintf (scratchbuf, "%d", disp);
+ sprintf (scratchbuf, "0x%x", disp);
oappend (scratchbuf);
}
}
oappend (")");
}
+ return (0);
}
+int
OP_G (bytemode)
+ int bytemode;
{
switch (bytemode)
{
oappend ("<internal disassembler error>");
break;
}
+ return (0);
}
+static int
get32 ()
{
int x = 0;
return (x);
}
+static int
get16 ()
{
int x = 0;
return (x);
}
+static void
+set_op (op)
+ int op;
+{
+ op_index[op_ad] = op_ad;
+ op_address[op_ad] = op;
+}
+
+int
OP_REG (code)
+ int code;
{
char *s;
break;
}
oappend (s);
+ return (0);
}
+int
OP_I (bytemode)
+ int bytemode;
{
int op;
break;
default:
oappend ("<internal disassembler error>");
- return;
+ return (0);
}
sprintf (scratchbuf, "$0x%x", op);
oappend (scratchbuf);
+ return (0);
}
+int
OP_sI (bytemode)
+ int bytemode;
{
int op;
break;
default:
oappend ("<internal disassembler error>");
- return;
+ return (0);
}
sprintf (scratchbuf, "$0x%x", op);
oappend (scratchbuf);
+ return (0);
}
+int
OP_J (bytemode)
+ int bytemode;
{
int disp;
int mask = -1;
}
break;
default:
- oappend ("<internal disassembelr error>");
- return;
+ oappend ("<internal disassembler error>");
+ return (0);
}
-
- sprintf (scratchbuf, "0x%x",
- (start_pc + codep - start_codep + disp) & mask);
+ 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)
+ int dummy;
{
static char *sreg[] = {
"%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
};
oappend (sreg[reg]);
+ return (0);
}
+int
OP_DIR (size)
+ int size;
{
int seg, offset;
else
offset = (short)get16 ();
- sprintf (scratchbuf, "0x%x",
- start_pc + codep - start_codep + offset);
+ offset = start_pc + codep - start_codep + offset;
+ set_op (offset);
+ sprintf (scratchbuf, "0x%x", offset);
oappend (scratchbuf);
break;
default:
oappend ("<internal disassembler error>");
break;
}
+ return (0);
}
/* ARGSUSED */
+int
OP_OFF (bytemode)
+ int bytemode;
{
int off;
sprintf (scratchbuf, "0x%x", off);
oappend (scratchbuf);
+ return (0);
}
/* ARGSUSED */
+int
OP_ESDI (dummy)
+ int dummy;
{
oappend ("%es:(");
oappend (aflag ? "%edi" : "%di");
oappend (")");
+ return (0);
}
/* ARGSUSED */
+int
OP_DSSI (dummy)
+ int dummy;
{
oappend ("%ds:(");
oappend (aflag ? "%esi" : "%si");
oappend (")");
+ return (0);
}
/* ARGSUSED */
+int
OP_ONE (dummy)
+ int dummy;
{
oappend ("1");
+ return (0);
}
/* ARGSUSED */
+int
OP_C (dummy)
+ int dummy;
{
codep++; /* skip mod/rm */
sprintf (scratchbuf, "%%cr%d", reg);
oappend (scratchbuf);
+ return (0);
}
/* ARGSUSED */
+int
OP_D (dummy)
+ int dummy;
{
codep++; /* skip mod/rm */
sprintf (scratchbuf, "%%db%d", reg);
oappend (scratchbuf);
+ return (0);
}
/* ARGSUSED */
+int
OP_T (dummy)
+ int dummy;
{
codep++; /* skip mod/rm */
sprintf (scratchbuf, "%%tr%d", reg);
oappend (scratchbuf);
+ return (0);
}
+int
OP_rm (bytemode)
+ int bytemode;
{
switch (bytemode)
{
oappend (names16[rm]);
break;
}
+ return (0);
}
-/* GDB interface */
-#include "defs.h"
-#include "param.h"
-#include "symtab.h"
-#include "frame.h"
-#include "inferior.h"
-
#define MAXLEN 20
+
+int
print_insn (memaddr, stream)
CORE_ADDR memaddr;
FILE *stream;
{
unsigned char buffer[MAXLEN];
- /* should be expanded if disassembler prints symbol names */
- char outbuf[100];
- int n;
-
- read_memory (memaddr, buffer, MAXLEN);
-
- n = i386dis ((int)memaddr, buffer, outbuf);
- fputs (outbuf, stream);
+ read_memory (memaddr, (char *) buffer, MAXLEN);
- return (n);
+ return (i386dis ((int)memaddr, buffer, stream));
}