* 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:
parent
45ee1401ab
commit
463f102c0a
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user