* 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> 2000-08-04 Ben Elliston <bje@redhat.com>
* cgen-dis.in, cgen-asm.in, cgen-ibld.in: New files. * 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} {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, static int
unsigned int pc, int constraint, char *buf,
char *comment, int regs);
static void
avr_operand (insn, insn2, pc, constraint, buf, comment, regs) avr_operand (insn, insn2, pc, constraint, buf, comment, regs)
unsigned int insn; unsigned int insn;
unsigned int insn2; unsigned int insn2;
@@ -58,6 +56,8 @@ avr_operand (insn, insn2, pc, constraint, buf, comment, regs)
char *comment; char *comment;
int regs; int regs;
{ {
int ok = 1;
switch (constraint) switch (constraint)
{ {
/* Any register operand. */ /* Any register operand. */
@@ -96,18 +96,27 @@ avr_operand (insn, insn2, pc, constraint, buf, comment, regs)
break; break;
case 'e': case 'e':
if (insn & 0x2)
*buf++ = '-';
switch ((insn >> 2) & 0x3)
{ {
case 0: *buf++ = 'Z'; break; char *xyz;
case 2: *buf++ = 'Y'; break;
case 3: *buf++ = 'X'; break; switch (insn & 0x100f)
default: buf += sprintf (buf, _(" unknown register ")); break; {
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"));
} }
if (insn & 0x1)
*buf++ = '+';
*buf = '\0';
break; break;
case 'z': case 'z':
@@ -115,11 +124,13 @@ avr_operand (insn, insn2, pc, constraint, buf, comment, regs)
if (insn & 0x1) if (insn & 0x1)
*buf++ = '+'; *buf++ = '+';
*buf = '\0'; *buf = '\0';
if (AVR_UNDEF_P (insn))
sprintf (comment, _("undefined"));
break; break;
case 'b': case 'b':
{ {
unsigned int x = insn; unsigned int x;
x = (insn & 7); x = (insn & 7);
x |= (insn >> 7) & (3 << 3); x |= (insn >> 7) & (3 << 3);
@@ -165,11 +176,19 @@ avr_operand (insn, insn2, pc, constraint, buf, comment, regs)
break; break;
case 'n': case 'n':
sprintf (buf, _("Internal disassembler error")); sprintf (buf, "??");
fprintf (stderr, _("Internal disassembler error"));
ok = 0;
break; break;
case 'K': 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; break;
case 's': case 's':
@@ -205,8 +224,12 @@ avr_operand (insn, insn2, pc, constraint, buf, comment, regs)
break; break;
default: 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 *)); 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; fprintf_ftype prin = info->fprintf_func;
static int initialized; static int initialized;
int cmd_len = 2; int cmd_len = 2;
int ok = 0;
char op1[20], op2[20], comment1[40], comment2[40];
if (!initialized) if (!initialized)
{ {
@@ -271,16 +296,23 @@ print_insn_avr(addr, info)
break; break;
} }
if (opcode->name) /* 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). */
char op1[20], op2[20], comment1[40], comment2[40];
char *op = opcode->constraints; if (AVR_DISP0_P (insn))
opcode++;
op1[0] = 0; op1[0] = 0;
op2[0] = 0; op2[0] = 0;
comment1[0] = 0; comment1[0] = 0;
comment2[0] = 0; comment2[0] = 0;
if (opcode->name)
{
char *op = opcode->constraints;
insn2 = 0; insn2 = 0;
ok = 1;
if (opcode->insn_size > 1) if (opcode->insn_size > 1)
{ {
@@ -292,17 +324,27 @@ print_insn_avr(addr, info)
{ {
int regs = REGISTER_P (*op); 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) == ',') if (ok && *(++op) == ',')
avr_operand (insn, insn2, addr, *(++op), op2, ok = avr_operand (insn, insn2, addr, *(++op), op2,
*comment1 ? comment2 : comment1, regs); *comment1 ? comment2 : comment1, regs);
} }
}
(*prin) (stream, " %-8s", opcode->name); 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) if (*op1)
(*prin) (stream, "%s", op1); (*prin) (stream, "\t%s", op1);
if (*op2) if (*op2)
(*prin) (stream, ", %s", op2); (*prin) (stream, ", %s", op2);
@@ -312,9 +354,6 @@ print_insn_avr(addr, info)
if (*comment2) if (*comment2)
(*prin) (stream, " %s", comment2); (*prin) (stream, " %s", comment2);
}
else
(*prin) (stream, ".word 0x%04x\t; ????", insn);
return cmd_len; return cmd_len;
} }