Add missing files from last change in gas/testsuite.
i386-dis.c: Catch a number of cases where an invalid modrm would result in
bogus disassembly.  const lots of places.
This commit is contained in:
Alan Modra 1999-05-17 08:35:42 +00:00
parent 5028a927f6
commit 2da11e11a4

View file

@ -93,24 +93,21 @@ fetch_data (info, addr)
#define indirEb OP_indirE, b_mode #define indirEb OP_indirE, b_mode
#define Gb OP_G, b_mode #define Gb OP_G, b_mode
#define Ev OP_E, v_mode #define Ev OP_E, v_mode
#define Ed OP_E, d_mode
#define indirEv OP_indirE, v_mode #define indirEv OP_indirE, v_mode
#define Ew OP_E, w_mode #define Ew OP_E, w_mode
#define Ma OP_E, v_mode #define Ma OP_E, v_mode
#define M OP_E, 0 #define M OP_E, 0 /* lea */
#define Mp OP_E, 0 /* ? */ #define Mp OP_E, 0 /* 32 or 48 bit memory operand for LDS, LES etc */
#define Gv OP_G, v_mode #define Gv OP_G, v_mode
#define Gw OP_G, w_mode #define Gw OP_G, w_mode
#define Rw OP_rm, w_mode #define Rd OP_Rd, d_mode
#define Rd OP_rm, d_mode
#define Ib OP_I, b_mode #define Ib OP_I, b_mode
#define sIb OP_sI, b_mode /* sign extened byte */ #define sIb OP_sI, b_mode /* sign extened byte */
#define Iv OP_I, v_mode #define Iv OP_I, v_mode
#define Iw OP_I, w_mode #define Iw OP_I, w_mode
#define Jb OP_J, b_mode #define Jb OP_J, b_mode
#define Jv OP_J, v_mode #define Jv OP_J, v_mode
#if 0
#define ONE OP_ONE, 0
#endif
#define Cd OP_C, d_mode #define Cd OP_C, d_mode
#define Dd OP_D, d_mode #define Dd OP_D, d_mode
#define Td OP_T, d_mode #define Td OP_T, d_mode
@ -156,7 +153,7 @@ fetch_data (info, addr)
#define XM OP_XMM, 0 #define XM OP_XMM, 0
#define EM OP_EM, v_mode #define EM OP_EM, v_mode
#define EX OP_EX, v_mode #define EX OP_EX, v_mode
#define MS OP_MS, b_mode #define MS OP_MS, v_mode
#define None OP_E, 0 #define None OP_E, 0
#define OPSUF OP_3DNowSuffix, 0 #define OPSUF OP_3DNowSuffix, 0
#define OPSIMD OP_SIMD_Suffix, 0 #define OPSIMD OP_SIMD_Suffix, 0
@ -168,7 +165,7 @@ fetch_data (info, addr)
#define AFLAG 2 #define AFLAG 2
#define DFLAG 1 #define DFLAG 1
typedef void (*op_rtn) PARAMS ((int bytemode, int sizeflag )); typedef void (*op_rtn) PARAMS ((int bytemode, int sizeflag));
static void OP_E PARAMS ((int, int)); static void OP_E PARAMS ((int, int));
static void OP_G PARAMS ((int, int)); static void OP_G PARAMS ((int, int));
@ -185,12 +182,9 @@ static void OP_SEG PARAMS ((int, int));
static void OP_C PARAMS ((int, int)); static void OP_C PARAMS ((int, int));
static void OP_D PARAMS ((int, int)); static void OP_D PARAMS ((int, int));
static void OP_T PARAMS ((int, int)); static void OP_T PARAMS ((int, int));
static void OP_rm PARAMS ((int, int)); static void OP_Rd PARAMS ((int, int));
static void OP_ST PARAMS ((int, int)); static void OP_ST PARAMS ((int, int));
static void OP_STi 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_MMX PARAMS ((int, int));
static void OP_XMM PARAMS ((int, int)); static void OP_XMM PARAMS ((int, int));
static void OP_EM PARAMS ((int, int)); static void OP_EM PARAMS ((int, int));
@ -202,12 +196,13 @@ static void SIMD_Fixup PARAMS ((int, int));
static void append_seg PARAMS ((void)); static void append_seg PARAMS ((void));
static void set_op PARAMS ((unsigned int op)); static void set_op PARAMS ((unsigned int op));
static void putop PARAMS ((char *template, int sizeflag)); static void putop PARAMS ((const char *template, int sizeflag));
static void dofloat PARAMS ((int sizeflag)); static void dofloat PARAMS ((int sizeflag));
static int get16 PARAMS ((void)); static int get16 PARAMS ((void));
static int get32 PARAMS ((void)); static int get32 PARAMS ((void));
static void ckprefix PARAMS ((void)); static void ckprefix PARAMS ((void));
static void ptr_reg PARAMS ((int, int)); static void ptr_reg PARAMS ((int, int));
static void BadOp PARAMS ((void));
#define b_mode 1 #define b_mode 1
#define v_mode 2 #define v_mode 2
@ -298,7 +293,7 @@ static void ptr_reg PARAMS ((int, int));
#define FLOAT NULL, NULL, FLOATCODE #define FLOAT NULL, NULL, FLOATCODE
struct dis386 { struct dis386 {
char *name; const char *name;
op_rtn op1; op_rtn op1;
int bytemode1; int bytemode1;
op_rtn op2; op_rtn op2;
@ -321,7 +316,7 @@ struct dis386 {
'W' => print 'b' or 'w' 'W' => print 'b' or 'w'
*/ */
static struct dis386 dis386_att[] = { static const struct dis386 dis386_att[] = {
/* 00 */ /* 00 */
{ "addB", Eb, Gb }, { "addB", Eb, Gb },
{ "addS", Ev, Gv }, { "addS", Ev, Gv },
@ -612,7 +607,7 @@ static struct dis386 dis386_att[] = {
{ GRP5 }, { GRP5 },
}; };
static struct dis386 dis386_intel[] = { static const struct dis386 dis386_intel[] = {
/* 00 */ /* 00 */
{ "add", Eb, Gb }, { "add", Eb, Gb },
{ "add", Ev, Gv }, { "add", Ev, Gv },
@ -903,7 +898,7 @@ static struct dis386 dis386_intel[] = {
{ GRP5 }, { GRP5 },
}; };
static struct dis386 dis386_twobyte_att[] = { static const struct dis386 dis386_twobyte_att[] = {
/* 00 */ /* 00 */
{ GRP6 }, { GRP6 },
{ GRP7 }, { GRP7 },
@ -999,7 +994,7 @@ static struct dis386 dis386_twobyte_att[] = {
{ "punpckhdq", MX, EM }, { "punpckhdq", MX, EM },
{ "packssdw", MX, EM }, { "packssdw", MX, EM },
{ "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
{ "movd", MX, Ev }, { "movd", MX, Ed },
{ "movq", MX, EM }, { "movq", MX, EM },
/* 70 */ /* 70 */
{ "pshufw", MX, EM, Ib }, { "pshufw", MX, EM, Ib },
@ -1013,7 +1008,7 @@ static struct dis386 dis386_twobyte_att[] = {
/* 78 */ /* 78 */
{ "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
{ "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
{ "movd", Ev, MX }, { "movd", Ed, MX },
{ "movq", EM, MX }, { "movq", EM, MX },
/* 80 */ /* 80 */
{ "jo", Jv }, { "jo", Jv },
@ -1072,10 +1067,10 @@ static struct dis386 dis386_twobyte_att[] = {
/* b0 */ /* b0 */
{ "cmpxchgB", Eb, Gb }, { "cmpxchgB", Eb, Gb },
{ "cmpxchgS", Ev, Gv }, { "cmpxchgS", Ev, Gv },
{ "lssS", Gv, Mp }, /* 386 lists only Mp */ { "lssS", Gv, Mp },
{ "btrS", Ev, Gv }, { "btrS", Ev, Gv },
{ "lfsS", Gv, Mp }, /* 386 lists only Mp */ { "lfsS", Gv, Mp },
{ "lgsS", Gv, Mp }, /* 386 lists only Mp */ { "lgsS", Gv, Mp },
{ "movzbR", Gv, Eb }, { "movzbR", Gv, Eb },
{ "movzwR", Gv, Ew }, /* yes, there really is movzww ! */ { "movzwR", Gv, Ew }, /* yes, there really is movzww ! */
/* b8 */ /* b8 */
@ -1161,7 +1156,7 @@ static struct dis386 dis386_twobyte_att[] = {
{ "(bad)" } { "(bad)" }
}; };
static struct dis386 dis386_twobyte_intel[] = { static const struct dis386 dis386_twobyte_intel[] = {
/* 00 */ /* 00 */
{ GRP6 }, { GRP6 },
{ GRP7 }, { GRP7 },
@ -1257,7 +1252,7 @@ static struct dis386 dis386_twobyte_intel[] = {
{ "punpckhdq", MX, EM }, { "punpckhdq", MX, EM },
{ "packssdw", MX, EM }, { "packssdw", MX, EM },
{ "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
{ "movd", MX, Ev }, { "movd", MX, Ed },
{ "movq", MX, EM }, { "movq", MX, EM },
/* 70 */ /* 70 */
{ "pshufw", MX, EM, Ib }, { "pshufw", MX, EM, Ib },
@ -1271,7 +1266,7 @@ static struct dis386 dis386_twobyte_intel[] = {
/* 78 */ /* 78 */
{ "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
{ "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
{ "movd", Ev, MX }, { "movd", Ed, MX },
{ "movq", EM, MX }, { "movq", EM, MX },
/* 80 */ /* 80 */
{ "jo", Jv }, { "jo", Jv },
@ -1330,10 +1325,10 @@ static struct dis386 dis386_twobyte_intel[] = {
/* b0 */ /* b0 */
{ "cmpxchg", Eb, Gb }, { "cmpxchg", Eb, Gb },
{ "cmpxchg", Ev, Gv }, { "cmpxchg", Ev, Gv },
{ "lss", Gv, Mp }, /* 386 lists only Mp */ { "lss", Gv, Mp },
{ "btr", Ev, Gv }, { "btr", Ev, Gv },
{ "lfs", Gv, Mp }, /* 386 lists only Mp */ { "lfs", Gv, Mp },
{ "lgs", Gv, Mp }, /* 386 lists only Mp */ { "lgs", Gv, Mp },
{ "movzx", Gv, Eb }, { "movzx", Gv, Eb },
{ "movzx", Gv, Ew }, { "movzx", Gv, Ew },
/* b8 */ /* b8 */
@ -1498,25 +1493,25 @@ static disassemble_info *the_info;
static int mod; static int mod;
static int rm; static int rm;
static int reg; static int reg;
static void oappend PARAMS ((char *s)); static void oappend PARAMS ((const char *s));
static char *names32[]={ static const char *names32[]={
"%eax","%ecx","%edx","%ebx", "%esp","%ebp","%esi","%edi", "%eax","%ecx","%edx","%ebx", "%esp","%ebp","%esi","%edi",
}; };
static char *names16[] = { static const char *names16[] = {
"%ax","%cx","%dx","%bx","%sp","%bp","%si","%di", "%ax","%cx","%dx","%bx","%sp","%bp","%si","%di",
}; };
static char *names8[] = { static const char *names8[] = {
"%al","%cl","%dl","%bl","%ah","%ch","%dh","%bh", "%al","%cl","%dl","%bl","%ah","%ch","%dh","%bh",
}; };
static char *names_seg[] = { static const char *names_seg[] = {
"%es","%cs","%ss","%ds","%fs","%gs","%?","%?", "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
}; };
static char *index16[] = { static const char *index16[] = {
"%bx,%si","%bx,%di","%bp,%si","%bp,%di","%si","%di","%bp","%bx" "%bx,%si","%bx,%di","%bp,%si","%bp,%di","%si","%di","%bp","%bx"
}; };
static struct dis386 grps[][8] = { static const struct dis386 grps[][8] = {
/* GRP1b */ /* GRP1b */
{ {
{ "addA", Eb, Ib }, { "addA", Eb, Ib },
@ -1773,7 +1768,7 @@ static struct dis386 grps[][8] = {
}; };
static struct dis386 prefix_user_table[][2] = { static const struct dis386 prefix_user_table[][2] = {
/* PREGRP0 */ /* PREGRP0 */
{ {
{ "addps", XM, EX }, { "addps", XM, EX },
@ -1944,8 +1939,6 @@ static unsigned int start_pc;
* The function returns the length of this instruction in bytes. * The function returns the length of this instruction in bytes.
*/ */
static int print_insn_x86
PARAMS ((bfd_vma pc, disassemble_info *info, int sizeflag));
static int print_insn_i386 static int print_insn_i386
PARAMS ((bfd_vma pc, disassemble_info *info)); PARAMS ((bfd_vma pc, disassemble_info *info));
@ -1988,34 +1981,26 @@ print_insn_i386 (pc, info)
bfd_vma pc; bfd_vma pc;
disassemble_info *info; disassemble_info *info;
{ {
int flags; const struct dis386 *dp;
if (info->mach == bfd_mach_i386_i386
|| info->mach == bfd_mach_i386_i386_intel_syntax)
flags = AFLAG|DFLAG;
else if (info->mach == bfd_mach_i386_i8086)
flags = 0;
else
abort ();
return print_insn_x86 (pc, info, flags);
}
static int
print_insn_x86 (pc, info, sizeflag)
bfd_vma pc;
disassemble_info *info;
int sizeflag;
{
struct dis386 *dp;
int i; int i;
int two_source_ops; int two_source_ops;
char *first, *second, *third; char *first, *second, *third;
int needcomma; int needcomma;
unsigned char need_modrm; unsigned char need_modrm;
unsigned char uses_f3_prefix; unsigned char uses_f3_prefix;
int sizeflag;
struct dis_private priv; struct dis_private priv;
bfd_byte *inbuf = priv.the_buffer; bfd_byte *inbuf = priv.the_buffer;
if (info->mach == bfd_mach_i386_i386
|| info->mach == bfd_mach_i386_i386_intel_syntax)
sizeflag = AFLAG|DFLAG;
else if (info->mach == bfd_mach_i386_i8086)
sizeflag = 0;
else
abort ();
/* The output looks better if we put 6 bytes on a line, since that /* The output looks better if we put 6 bytes on a line, since that
puts most long word instructions on a single line. */ puts most long word instructions on a single line. */
info->bytes_per_line = 6; info->bytes_per_line = 6;
@ -2199,7 +2184,7 @@ print_insn_x86 (pc, info, sizeflag)
return codep - inbuf; return codep - inbuf;
} }
static char *float_mem_att[] = { static const char *float_mem_att[] = {
/* d8 */ /* d8 */
"fadds", "fadds",
"fmuls", "fmuls",
@ -2274,7 +2259,7 @@ static char *float_mem_att[] = {
"fistpll", "fistpll",
}; };
static char *float_mem_intel[] = { static const char *float_mem_intel[] = {
/* d8 */ /* d8 */
"fadd", "fadd",
"fmul", "fmul",
@ -2362,7 +2347,7 @@ static char *float_mem_intel[] = {
#define FGRPde_3 NULL, NULL, 7 #define FGRPde_3 NULL, NULL, 7
#define FGRPdf_4 NULL, NULL, 8 #define FGRPdf_4 NULL, NULL, 8
static struct dis386 float_reg[][8] = { static const struct dis386 float_reg[][8] = {
/* d8 */ /* d8 */
{ {
{ "fadd", ST, STi }, { "fadd", ST, STi },
@ -2520,7 +2505,7 @@ static void
dofloat (sizeflag) dofloat (sizeflag)
int sizeflag; int sizeflag;
{ {
struct dis386 *dp; const struct dis386 *dp;
unsigned char floatop; unsigned char floatop;
floatop = codep[-1]; floatop = codep[-1];
@ -2587,10 +2572,10 @@ OP_STi (ignore, sizeflag)
/* capital letters in template are macros */ /* capital letters in template are macros */
static void static void
putop (template, sizeflag) putop (template, sizeflag)
char *template; const char *template;
int sizeflag; int sizeflag;
{ {
char *p; const char *p;
for (p = template; *p; p++) for (p = template; *p; p++)
{ {
@ -2724,7 +2709,7 @@ putop (template, sizeflag)
static void static void
oappend (s) oappend (s)
char *s; const char *s;
{ {
strcpy (obufp, s); strcpy (obufp, s);
obufp += strlen (s); obufp += strlen (s);
@ -2777,13 +2762,18 @@ OP_E (bytemode, sizeflag)
case w_mode: case w_mode:
oappend (names16[rm]); oappend (names16[rm]);
break; break;
case d_mode:
oappend (names32[rm]);
break;
case v_mode: case v_mode:
if (sizeflag & DFLAG) if (sizeflag & DFLAG)
oappend (names32[rm]); oappend (names32[rm]);
else else
oappend (names16[rm]); oappend (names16[rm]);
break; break;
case 0: /* sfence */ case 0:
if ( !(codep[-2] == 0xAE && codep[-1] == 0xF8 /* sfence */))
BadOp(); /* bad sfence,lea,lds,les,lfs,lgs,lss modrm */
break; break;
default: default:
oappend (INTERNAL_DISASSEMBLER_ERROR); oappend (INTERNAL_DISASSEMBLER_ERROR);
@ -3046,7 +3036,7 @@ OP_REG (code, sizeflag)
int code; int code;
int sizeflag; int sizeflag;
{ {
char *s; const char *s;
switch (code) switch (code)
{ {
@ -3261,7 +3251,7 @@ ptr_reg (code, sizeflag)
int code; int code;
int sizeflag; int sizeflag;
{ {
char *s; const char *s;
oappend ("("); oappend ("(");
if (sizeflag & AFLAG) if (sizeflag & AFLAG)
s = names32[code - eAX_reg]; s = names32[code - eAX_reg];
@ -3297,27 +3287,12 @@ OP_DSreg (code, sizeflag)
ptr_reg (code, sizeflag); ptr_reg (code, sizeflag);
} }
#if 0
/* Not used. */
/* ARGSUSED */
static void
OP_ONE (dummy, sizeflag)
int dummy;
int sizeflag;
{
oappend ("1");
}
#endif
/* ARGSUSED */ /* ARGSUSED */
static void static void
OP_C (dummy, sizeflag) OP_C (dummy, sizeflag)
int dummy; int dummy;
int sizeflag; int sizeflag;
{ {
codep++; /* skip mod/rm */
sprintf (scratchbuf, "%%cr%d", reg); sprintf (scratchbuf, "%%cr%d", reg);
oappend (scratchbuf); oappend (scratchbuf);
} }
@ -3328,7 +3303,6 @@ OP_D (dummy, sizeflag)
int dummy; int dummy;
int sizeflag; int sizeflag;
{ {
codep++; /* skip mod/rm */
sprintf (scratchbuf, "%%db%d", reg); sprintf (scratchbuf, "%%db%d", reg);
oappend (scratchbuf); oappend (scratchbuf);
} }
@ -3339,25 +3313,19 @@ OP_T (dummy, sizeflag)
int dummy; int dummy;
int sizeflag; int sizeflag;
{ {
codep++; /* skip mod/rm */
sprintf (scratchbuf, "%%tr%d", reg); sprintf (scratchbuf, "%%tr%d", reg);
oappend (scratchbuf); oappend (scratchbuf);
} }
static void static void
OP_rm (bytemode, sizeflag) OP_Rd (bytemode, sizeflag)
int bytemode; int bytemode;
int sizeflag; int sizeflag;
{ {
switch (bytemode) if (mod == 3)
{ OP_E (bytemode, sizeflag);
case d_mode: else
oappend (names32[rm]); BadOp();
break;
case w_mode:
oappend (names16[rm]);
break;
}
} }
static void static void
@ -3411,13 +3379,14 @@ OP_EX (bytemode, sizeflag)
} }
static void static void
OP_MS (ignore, sizeflag) OP_MS (bytemode, sizeflag)
int ignore; int bytemode;
int sizeflag; int sizeflag;
{ {
++codep; if (mod == 3)
sprintf (scratchbuf, "%%mm%d", rm); OP_EM (bytemode, sizeflag);
oappend (scratchbuf); else
BadOp();
} }
static const char *Suffix3DNow[] = { static const char *Suffix3DNow[] = {
@ -3498,19 +3467,19 @@ OP_3DNowSuffix (bytemode, sizeflag)
/* AMD 3DNow! instructions are specified by an opcode suffix in the /* AMD 3DNow! instructions are specified by an opcode suffix in the
place where an 8-bit immediate would normally go. ie. the last place where an 8-bit immediate would normally go. ie. the last
byte of the instruction. */ byte of the instruction. */
obufp = obuf + strlen(obuf);
mnemonic = Suffix3DNow[*codep++ & 0xff]; mnemonic = Suffix3DNow[*codep++ & 0xff];
if (mnemonic) if (mnemonic)
strcat (obuf, mnemonic); oappend (mnemonic);
else else
{ {
/* Since a variable sized modrm/sib chunk is between the start /* Since a variable sized modrm/sib chunk is between the start
of the opcode (0x0f0f) and the opcode suffix, we need to do of the opcode (0x0f0f) and the opcode suffix, we need to do
all the modrm processing first, and don't know until now that all the modrm processing first, and don't know until now that
we have a bad opcode. This necessitates some cleaning up. */ we have a bad opcode. This necessitates some cleaning up. */
op1out[0] = 0; op1out[0] = '\0';
op2out[0] = 0; op2out[0] = '\0';
codep = insn_codep + 1; BadOp();
strcat (obuf, "(bad)");
} }
} }
@ -3534,21 +3503,21 @@ OP_SIMD_Suffix (bytemode, sizeflag)
unsigned int cmp_type; unsigned int cmp_type;
FETCH_DATA (the_info, codep + 1); FETCH_DATA (the_info, codep + 1);
obufp = obuf + strlen(obuf);
cmp_type = *codep++ & 0xff; cmp_type = *codep++ & 0xff;
if (cmp_type < 8) if (cmp_type < 8)
{ {
sprintf (scratchbuf, "cmp%s%cs", sprintf (scratchbuf, "cmp%s%cs",
simd_cmp_op[cmp_type], simd_cmp_op[cmp_type],
prefixes & PREFIX_REPZ ? 's' : 'p'); prefixes & PREFIX_REPZ ? 's' : 'p');
strcat (obuf, scratchbuf); oappend (scratchbuf);
} }
else else
{ {
/* We have a bad extension byte. Clean up. */ /* We have a bad extension byte. Clean up. */
op1out[0] = 0; op1out[0] = '\0';
op2out[0] = 0; op2out[0] = '\0';
codep = insn_codep + 1; BadOp();
strcat (obuf, "(bad)");
} }
} }
@ -3569,3 +3538,9 @@ SIMD_Fixup (extrachar, sizeflag)
*(p-3) = extrachar; *(p-3) = extrachar;
} }
} }
static void BadOp (void)
{
codep = insn_codep + 1; /* throw away prefixes and 1st. opcode byte */
oappend ("(bad)");
}