X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=opcodes%2Fh8300-dis.c;h=f56ad86771dd892d6bb66f579b35d48c53579dff;hb=4e86f6e7478e40a288ec6567fa7f3b4ef0f8d516;hp=9c77e912ee7961cad49c3e8320e3ed3e5ee029cc;hpb=47b0e7ad8c60ea4b45b22ad5cb376f068991bc88;p=deliverable%2Fbinutils-gdb.git diff --git a/opcodes/h8300-dis.c b/opcodes/h8300-dis.c index 9c77e912ee..f56ad86771 100644 --- a/opcodes/h8300-dis.c +++ b/opcodes/h8300-dis.c @@ -1,16 +1,17 @@ /* Disassemble h8300 instructions. - Copyright 1993, 1994, 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005 - Free Software Foundation, Inc. + Copyright (C) 1993-2020 Free Software Foundation, Inc. - This program is free software; you can redistribute it and/or modify + This file is part of the GNU opcodes library. + + This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + the Free Software Foundation; either version 3, or (at your option) + any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + It is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software @@ -22,13 +23,13 @@ #include "sysdep.h" #define h8_opcodes h8ops #include "opcode/h8300.h" -#include "dis-asm.h" +#include "disassemble.h" #include "opintl.h" #include "libiberty.h" struct h8_instruction { - int length; + unsigned int length; const struct h8_opcode *opcode; }; @@ -51,29 +52,11 @@ bfd_h8_disassemble_init (void) for (p = h8_opcodes, pi = h8_instructions; p->name; p++, pi++) { - int n1 = 0; - int n2 = 0; - - if ((int) p->data.nib[0] < 16) - n1 = (int) p->data.nib[0]; - else - n1 = 0; - - if ((int) p->data.nib[1] < 16) - n2 = (int) p->data.nib[1]; - else - n2 = 0; - /* Just make sure there are an even number of nibbles in it, and that the count is the same as the length. */ for (i = 0; p->data.nib[i] != (op_type) E; i++) ; - - if (i & 1) - { - fprintf (stderr, "Internal error, h8_disassemble_init.\n"); - abort (); - } + OPCODES_ASSERT (!(i & 1)); pi->length = i / 2; pi->opcode = p; @@ -151,7 +134,8 @@ extract_immediate (FILE *stream, break; case L_32: *len = 32; - *cst = (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3]; + *cst = (((unsigned) data[0] << 24) + (data[1] << 16) + + (data[2] << 8) + data[3]); break; default: *len = 0; @@ -279,17 +263,17 @@ print_one_arg (disassemble_info *info, if ((x & SIZE) == L_16 || (x & SIZE) == L_16U) { - outfn (stream, ".%s%d (0x%x)", + outfn (stream, ".%s%d (0x%lx)", (short) cst > 0 ? "+" : "", - (short) cst, - addr + (short) cst + len); + (short) cst, + (long)(addr + (short) cst + len)); } else { - outfn (stream, ".%s%d (0x%x)", + outfn (stream, ".%s%d (0x%lx)", (char) cst > 0 ? "+" : "", - (char) cst, - addr + (char) cst + len); + (char) cst, + (long)(addr + (char) cst + len)); } } else if ((x & MODE) == DISP) @@ -297,19 +281,19 @@ print_one_arg (disassemble_info *info, else if ((x & MODE) == INDEXB) /* Always take low half of reg. */ - outfn (stream, "@(0x%x:%d,%s.b)", cst, cstlen, + outfn (stream, "@(0x%x:%d,%s.b)", cst, cstlen, regnames[rdisp_n < 8 ? rdisp_n + 8 : rdisp_n]); else if ((x & MODE) == INDEXW) /* Always take low half of reg. */ - outfn (stream, "@(0x%x:%d,%s.w)", cst, cstlen, + outfn (stream, "@(0x%x:%d,%s.w)", cst, cstlen, wregnames[rdisp_n < 8 ? rdisp_n : rdisp_n - 8]); else if ((x & MODE) == INDEXL) outfn (stream, "@(0x%x:%d,%s.l)", cst, cstlen, lregnames[rdisp_n]); else if (x & CTRL) - outfn (stream, cregnames[rn]); + outfn (stream, "%s", cregnames[rn]); else if ((x & MODE) == CCR) outfn (stream, "ccr"); @@ -337,8 +321,8 @@ bfd_h8_disassemble (bfd_vma addr, disassemble_info *info, int mach) const struct h8_instruction *qi; char const **pregnames = mach != 0 ? lregnames : wregnames; int status; - unsigned int l; - unsigned char data[MAX_CODE_NIBBLES]; + unsigned int maxlen; + unsigned char data[MAX_CODE_NIBBLES / 2]; void *stream = info->stream; fprintf_ftype outfn = info->fprintf_func; @@ -355,22 +339,34 @@ bfd_h8_disassemble (bfd_vma addr, disassemble_info *info, int mach) return -1; } - for (l = 2; status == 0 && l < sizeof (data) / 2; l += 2) - status = info->read_memory_func (addr + l, data + l, 2, info); + for (maxlen = 2; maxlen < sizeof (data); maxlen += 2) + { + status = info->read_memory_func (addr + maxlen, data + maxlen, 2, info); + if (status != 0) + break; + } /* Find the exact opcode/arg combo. */ for (qi = h8_instructions; qi->opcode->name; qi++) { - const struct h8_opcode *q = qi->opcode; - op_type *nib = q->data.nib; - unsigned int len = 0; - - while (1) + const struct h8_opcode *q; + const op_type *nib; + unsigned int len; + op_type looking_for; + + if (qi->length > maxlen) + continue; + + q = qi->opcode; + nib = q->data.nib; + len = 0; + while ((looking_for = *nib) != (op_type) E) { - op_type looking_for = *nib; - int thisnib = data[len / 2]; + int thisnib; int opnr; + OPCODES_ASSERT (len / 2 < maxlen); + thisnib = data[len / 2]; thisnib = (len & 1) ? (thisnib & 0xf) : ((thisnib / 16) & 0xf); opnr = ((looking_for & OP3) == OP3 ? 2 : (looking_for & DST) == DST ? 1 : 0); @@ -472,8 +468,23 @@ bfd_h8_disassemble (bfd_vma addr, disassemble_info *info, int mach) || (looking_for & MODE) == INDEXW || (looking_for & MODE) == INDEXL) { - extract_immediate (stream, looking_for, thisnib, - data + len / 2, cst + opnr, + int extra; + switch (looking_for & SIZE) + { + case L_16: + case L_16U: + extra = 1; + break; + case L_32: + extra = 3; + break; + default: + extra = 0; + break; + } + OPCODES_ASSERT (len / 2 + extra < maxlen); + extract_immediate (stream, looking_for, thisnib, + data + len / 2, cst + opnr, cstlen + opnr, q); /* Even address == bra, odd == bra/s. */ if (q->how == O (O_BRAS, SB)) @@ -526,6 +537,7 @@ bfd_h8_disassemble (bfd_vma addr, disassemble_info *info, int mach) else if ((looking_for & SIZE) == L_16 || (looking_for & SIZE) == L_16U) { + OPCODES_ASSERT (len / 2 + 1 < maxlen); cst[opnr] = (data[len / 2]) * 256 + data[(len + 2) / 2]; cstlen[opnr] = 16; } @@ -539,10 +551,11 @@ bfd_h8_disassemble (bfd_vma addr, disassemble_info *info, int mach) } else if ((looking_for & SIZE) == L_32) { - int i = len / 2; + unsigned int i = len / 2; - cst[opnr] = ((data[i] << 24) - | (data[i + 1] << 16) + OPCODES_ASSERT (i + 3 < maxlen); + cst[opnr] = (((unsigned) data[i] << 24) + | (data[i + 1] << 16) | (data[i + 2] << 8) | (data[i + 3])); @@ -550,16 +563,13 @@ bfd_h8_disassemble (bfd_vma addr, disassemble_info *info, int mach) } else if ((looking_for & SIZE) == L_24) { - int i = len / 2; + unsigned int i = len / 2; - cst[opnr] = + OPCODES_ASSERT (i + 2 < maxlen); + cst[opnr] = (data[i] << 16) | (data[i + 1] << 8) | (data[i + 2]); cstlen[opnr] = 24; } - else if (looking_for & IGNORE) - { - ; - } else if (looking_for & DISPREG) { dispregno[opnr] = thisnib & 7; @@ -602,105 +612,6 @@ bfd_h8_disassemble (bfd_vma addr, disassemble_info *info, int mach) { cst[opnr] = (thisnib == 3); } - else if (looking_for == (op_type) E) - { - outfn (stream, "%s\t", q->name); - - /* Gross. Disgusting. */ - if (strcmp (q->name, "ldm.l") == 0) - { - int count, high; - - count = (data[1] / 16) & 0x3; - high = regno[1]; - - outfn (stream, "@sp+,er%d-er%d", high - count, high); - return qi->length; - } - - if (strcmp (q->name, "stm.l") == 0) - { - int count, low; - - count = (data[1] / 16) & 0x3; - low = regno[0]; - - outfn (stream, "er%d-er%d,@-sp", low, low + count); - return qi->length; - } - if (strcmp (q->name, "rte/l") == 0 - || strcmp (q->name, "rts/l") == 0) - { - if (regno[0] == 0) - outfn (stream, "er%d", regno[1]); - else - outfn (stream, "er%d-er%d", regno[1] - regno[0], - regno[1]); - return qi->length; - } - if (strncmp (q->name, "mova", 4) == 0) - { - op_type *args = q->args.nib; - - if (args[1] == (op_type) E) - { - /* Short form. */ - print_one_arg (info, addr, args[0], cst[0], - cstlen[0], dispregno[0], regno[0], - pregnames, qi->length); - outfn (stream, ",er%d", dispregno[0]); - } - else - { - outfn (stream, "@(0x%x:%d,", cst[0], cstlen[0]); - print_one_arg (info, addr, args[1], cst[1], - cstlen[1], dispregno[1], regno[1], - pregnames, qi->length); - outfn (stream, ".%c),", - (args[0] & MODE) == INDEXB ? 'b' : 'w'); - print_one_arg (info, addr, args[2], cst[2], - cstlen[2], dispregno[2], regno[2], - pregnames, qi->length); - } - return qi->length; - } - /* Fill in the args. */ - { - op_type *args = q->args.nib; - int hadone = 0; - int nargs; - - /* Special case handling for the adds and subs instructions - since in H8 mode thay can only take the r0-r7 registers - but in other (higher) modes they can take the er0-er7 - registers as well. */ - if (strcmp (qi->opcode->name, "adds") == 0 - || strcmp (qi->opcode->name, "subs") == 0) - { - outfn (stream, "#%d,%s", cst[0], pregnames[regno[1] & 0x7]); - return qi->length; - } - - for (nargs = 0; - nargs < 3 && args[nargs] != (op_type) E; - nargs++) - { - int x = args[nargs]; - - if (hadone) - outfn (stream, ","); - - print_one_arg (info, addr, x, - cst[nargs], cstlen[nargs], - dispregno[nargs], regno[nargs], - pregnames, qi->length); - - hadone = 1; - } - } - - return qi->length; - } else /* xgettext:c-format */ outfn (stream, _("Don't understand 0x%x \n"), looking_for); @@ -710,6 +621,102 @@ bfd_h8_disassemble (bfd_vma addr, disassemble_info *info, int mach) nib++; } + outfn (stream, "%s\t", q->name); + + /* Gross. Disgusting. */ + if (strcmp (q->name, "ldm.l") == 0) + { + int count, high; + + count = (data[1] / 16) & 0x3; + high = regno[1]; + + outfn (stream, "@sp+,er%d-er%d", high - count, high); + return qi->length; + } + + if (strcmp (q->name, "stm.l") == 0) + { + int count, low; + + count = (data[1] / 16) & 0x3; + low = regno[0]; + + outfn (stream, "er%d-er%d,@-sp", low, low + count); + return qi->length; + } + if (strcmp (q->name, "rte/l") == 0 + || strcmp (q->name, "rts/l") == 0) + { + if (regno[0] == 0) + outfn (stream, "er%d", regno[1]); + else + outfn (stream, "er%d-er%d", regno[1] - regno[0], + regno[1]); + return qi->length; + } + if (CONST_STRNEQ (q->name, "mova")) + { + const op_type *args = q->args.nib; + + if (args[1] == (op_type) E) + { + /* Short form. */ + print_one_arg (info, addr, args[0], cst[0], + cstlen[0], dispregno[0], regno[0], + pregnames, qi->length); + outfn (stream, ",er%d", dispregno[0]); + } + else + { + outfn (stream, "@(0x%x:%d,", cst[0], cstlen[0]); + print_one_arg (info, addr, args[1], cst[1], + cstlen[1], dispregno[1], regno[1], + pregnames, qi->length); + outfn (stream, ".%c),", + (args[0] & MODE) == INDEXB ? 'b' : 'w'); + print_one_arg (info, addr, args[2], cst[2], + cstlen[2], dispregno[2], regno[2], + pregnames, qi->length); + } + return qi->length; + } + /* Fill in the args. */ + { + const op_type *args = q->args.nib; + int hadone = 0; + int nargs; + + /* Special case handling for the adds and subs instructions + since in H8 mode thay can only take the r0-r7 registers + but in other (higher) modes they can take the er0-er7 + registers as well. */ + if (strcmp (qi->opcode->name, "adds") == 0 + || strcmp (qi->opcode->name, "subs") == 0) + { + outfn (stream, "#%d,%s", cst[0], pregnames[regno[1] & 0x7]); + return qi->length; + } + + for (nargs = 0; + nargs < 3 && args[nargs] != (op_type) E; + nargs++) + { + int x = args[nargs]; + + if (hadone) + outfn (stream, ","); + + print_one_arg (info, addr, x, + cst[nargs], cstlen[nargs], + dispregno[nargs], regno[nargs], + pregnames, qi->length); + + hadone = 1; + } + } + return qi->length; + fail: ; }