* avr-dis.c (avr_operand): Use PARAMS macro in declaration.

Change return type from void to int.  Check the combination
	of operands, return 1 if valid.  Fix to avoid BUF overflow.
	Report undefined combinations of operands in COMMENT.
	Report internal errors to stderr.  Output the adiw/sbiw
	constant operand in both decimal and hex.
	(print_insn_avr): Disassemble ldd/std with displacement of 0
	as ld/st.  Check avr_operand () return value, handle invalid
	combinations of operands like unknown opcodes.
This commit is contained in:
Denis Chertykov 2000-08-06 14:12:36 +00:00
parent 45ee1401ab
commit 463f102c0a
2 changed files with 98 additions and 47 deletions

View File

@ -1,3 +1,15 @@
2000-07-29 Marek Michalkiewicz <marekm@linux.org.pl>
* avr-dis.c (avr_operand): Use PARAMS macro in declaration.
Change return type from void to int. Check the combination
of operands, return 1 if valid. Fix to avoid BUF overflow.
Report undefined combinations of operands in COMMENT.
Report internal errors to stderr. Output the adiw/sbiw
constant operand in both decimal and hex.
(print_insn_avr): Disassemble ldd/std with displacement of 0
as ld/st. Check avr_operand () return value, handle invalid
combinations of operands like unknown opcodes.
2000-08-04 Ben Elliston <bje@redhat.com>
* cgen-dis.in, cgen-asm.in, cgen-ibld.in: New files.

View File

@ -43,12 +43,10 @@ struct avr_opcodes_s avr_opcodes[] =
{NULL, NULL, NULL, 0, 0, 0, 0}
};
static int avr_operand PARAMS ((unsigned int, unsigned int,
unsigned int, int, char *, char *, int));
static void avr_operand (unsigned int insn, unsigned int insn2,
unsigned int pc, int constraint, char *buf,
char *comment, int regs);
static void
static int
avr_operand (insn, insn2, pc, constraint, buf, comment, regs)
unsigned int insn;
unsigned int insn2;
@ -58,6 +56,8 @@ avr_operand (insn, insn2, pc, constraint, buf, comment, regs)
char *comment;
int regs;
{
int ok = 1;
switch (constraint)
{
/* Any register operand. */
@ -96,18 +96,27 @@ avr_operand (insn, insn2, pc, constraint, buf, comment, regs)
break;
case 'e':
if (insn & 0x2)
*buf++ = '-';
switch ((insn >> 2) & 0x3)
{
case 0: *buf++ = 'Z'; break;
case 2: *buf++ = 'Y'; break;
case 3: *buf++ = 'X'; break;
default: buf += sprintf (buf, _(" unknown register ")); break;
}
if (insn & 0x1)
*buf++ = '+';
*buf = '\0';
{
char *xyz;
switch (insn & 0x100f)
{
case 0x0000: xyz = "Z"; break;
case 0x1001: xyz = "Z+"; break;
case 0x1002: xyz = "-Z"; break;
case 0x0008: xyz = "Y"; break;
case 0x1009: xyz = "Y+"; break;
case 0x100a: xyz = "-Y"; break;
case 0x100c: xyz = "X"; break;
case 0x100d: xyz = "X+"; break;
case 0x100e: xyz = "-X"; break;
default: xyz = "??"; ok = 0;
}
sprintf (buf, xyz);
if (AVR_UNDEF_P (insn))
sprintf (comment, _("undefined"));
}
break;
case 'z':
@ -115,11 +124,13 @@ avr_operand (insn, insn2, pc, constraint, buf, comment, regs)
if (insn & 0x1)
*buf++ = '+';
*buf = '\0';
if (AVR_UNDEF_P (insn))
sprintf (comment, _("undefined"));
break;
case 'b':
{
unsigned int x = insn;
unsigned int x;
x = (insn & 7);
x |= (insn >> 7) & (3 << 3);
@ -165,11 +176,19 @@ avr_operand (insn, insn2, pc, constraint, buf, comment, regs)
break;
case 'n':
sprintf (buf, _("Internal disassembler error"));
sprintf (buf, "??");
fprintf (stderr, _("Internal disassembler error"));
ok = 0;
break;
case 'K':
sprintf (buf, "%d", (insn & 0xf) | ((insn >> 2) & 0x30));
{
unsigned int x;
x = (insn & 0xf) | ((insn >> 2) & 0x30);
sprintf (buf, "0x%02x", x);
sprintf (comment, "%d", x);
}
break;
case 's':
@ -205,8 +224,12 @@ avr_operand (insn, insn2, pc, constraint, buf, comment, regs)
break;
default:
sprintf (buf, _("unknown constraint `%c'"), constraint);
sprintf (buf, "??");
fprintf (stderr, _("unknown constraint `%c'"), constraint);
ok = 0;
}
return ok;
}
static unsigned short avrdis_opcode PARAMS ((bfd_vma, disassemble_info *));
@ -239,6 +262,8 @@ print_insn_avr(addr, info)
fprintf_ftype prin = info->fprintf_func;
static int initialized;
int cmd_len = 2;
int ok = 0;
char op1[20], op2[20], comment1[40], comment2[40];
if (!initialized)
{
@ -271,16 +296,23 @@ print_insn_avr(addr, info)
break;
}
/* Special case: disassemble `ldd r,b+0' as `ld r,b', and
`std b+0,r' as `st b,r' (next entry in the table). */
if (AVR_DISP0_P (insn))
opcode++;
op1[0] = 0;
op2[0] = 0;
comment1[0] = 0;
comment2[0] = 0;
if (opcode->name)
{
char op1[20], op2[20], comment1[40], comment2[40];
char *op = opcode->constraints;
op1[0] = 0;
op2[0] = 0;
comment1[0] = 0;
comment2[0] = 0;
insn2 = 0;
ok = 1;
if (opcode->insn_size > 1)
{
@ -292,29 +324,36 @@ print_insn_avr(addr, info)
{
int regs = REGISTER_P (*op);
avr_operand (insn, insn2, addr, *op, op1, comment1, 0);
ok = avr_operand (insn, insn2, addr, *op, op1, comment1, 0);
if (*(++op) == ',')
avr_operand (insn, insn2, addr, *(++op), op2,
*comment1 ? comment2 : comment1, regs);
if (ok && *(++op) == ',')
ok = avr_operand (insn, insn2, addr, *(++op), op2,
*comment1 ? comment2 : comment1, regs);
}
(*prin) (stream, " %-8s", opcode->name);
if (*op1)
(*prin) (stream, "%s", op1);
if (*op2)
(*prin) (stream, ", %s", op2);
if (*comment1)
(*prin) (stream, "\t; %s", comment1);
if (*comment2)
(*prin) (stream, " %s", comment2);
}
else
(*prin) (stream, ".word 0x%04x\t; ????", insn);
if (!ok)
{
/* Unknown opcode, or invalid combination of operands. */
sprintf (op1, "0x%04x", insn);
op2[0] = 0;
sprintf (comment1, "????");
comment2[0] = 0;
}
(*prin) (stream, "%s", ok ? opcode->name : ".word");
if (*op1)
(*prin) (stream, "\t%s", op1);
if (*op2)
(*prin) (stream, ", %s", op2);
if (*comment1)
(*prin) (stream, "\t; %s", comment1);
if (*comment2)
(*prin) (stream, " %s", comment2);
return cmd_len;
}