diff options
-rw-r--r-- | opcodes/ChangeLog | 8 | ||||
-rw-r--r-- | opcodes/i386-dis.c | 389 |
2 files changed, 240 insertions, 157 deletions
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index f1561ff..21b2f34 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,11 @@ +Fri Jul 12 10:12:01 1996 Stu Grossman (grossman@critters.cygnus.com) + + * i386-dis.c (print_insn_i8086): New routine to disassemble using + the 8086 instruction set. + * i386-dis.c: General cleanups. Make most things static. Add + prototypes. Get rid of static variables aflags and dflags. Pass + them as args (to almost everything). + Thu Jul 11 11:58:44 1996 Jeffrey A Law (law@cygnus.com) * h8300-dis.c (bfd_h8_disassemble): Handle macregs in ldmac insns. diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c index b21e276..6fcc724 100644 --- a/opcodes/i386-dis.c +++ b/opcodes/i386-dis.c @@ -1,5 +1,5 @@ /* 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. @@ -139,13 +139,19 @@ 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(); +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 @@ -212,15 +218,15 @@ static int get16 (), get32 (); 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 }, @@ -511,7 +517,7 @@ struct dis386 dis386[] = { { GRP5 }, }; -struct dis386 dis386_twobyte[] = { +static struct dis386 dis386_twobyte[] = { /* 00 */ { GRP6 }, { GRP7 }, @@ -732,7 +738,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", @@ -746,8 +752,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 }, @@ -1004,9 +1013,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; @@ -1021,11 +1027,29 @@ 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; int enter_instruction; @@ -1080,10 +1104,6 @@ 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; @@ -1116,29 +1136,29 @@ print_insn_i386 (pc, info) 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); @@ -1197,7 +1217,7 @@ print_insn_i386 (pc, info) return (codep - inbuf); } -char *float_mem[] = { +static char *float_mem[] = { /* d8 */ "fadds", "fmuls", @@ -1274,7 +1294,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 @@ -1286,7 +1305,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 }, @@ -1378,7 +1397,7 @@ struct dis386 float_reg[][8] = { }; -char *fgrps[][8] = { +static char *fgrps[][8] = { /* d9_2 0 */ { "fnop","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)", @@ -1427,7 +1446,9 @@ char *fgrps[][8] = { }; static void -dofloat () +dofloat (aflag, dflag) + int aflag; + int dflag; { struct dis386 *dp; unsigned char floatop; @@ -1436,9 +1457,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++; @@ -1446,7 +1467,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) @@ -1455,29 +1476,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); @@ -1487,8 +1512,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; @@ -1500,7 +1527,7 @@ putop (template) *obufp++ = *p; break; case 'C': /* For jcxz/jecxz */ - if (aflag == 0) + if (aflag) *obufp++ = 'e'; break; case 'N': @@ -1545,33 +1572,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) @@ -1592,90 +1613,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) { @@ -1733,9 +1778,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; @@ -1769,9 +1816,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; @@ -1799,9 +1848,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; @@ -1829,9 +1880,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; @@ -1866,9 +1919,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","%?","%?", @@ -1878,9 +1933,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; @@ -1919,12 +1976,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 @@ -1936,9 +1997,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"); @@ -1947,9 +2010,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"); @@ -1958,18 +2023,22 @@ OP_DSSI (dummy) } /* 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); @@ -1978,9 +2047,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); @@ -1989,9 +2060,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); @@ -1999,9 +2072,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) { |