summaryrefslogtreecommitdiff
path: root/opcodes/mcore-dis.c
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>1999-05-07 07:57:25 +0000
committerNick Clifton <nickc@redhat.com>1999-05-07 07:57:25 +0000
commit3f230321daaad517b4203d19e90ebc3b63b43a42 (patch)
tree65cff75e79d48b38d9e2aec5d04b6b8600c094cb /opcodes/mcore-dis.c
parentb23f908b61631f2a173b349e73ad793ac00a887d (diff)
downloadbinutils-gdb-3f230321daaad517b4203d19e90ebc3b63b43a42.tar.gz
restore mcore files (Duh!)
Diffstat (limited to 'opcodes/mcore-dis.c')
-rw-r--r--opcodes/mcore-dis.c277
1 files changed, 277 insertions, 0 deletions
diff --git a/opcodes/mcore-dis.c b/opcodes/mcore-dis.c
new file mode 100644
index 00000000000..7e3d45056b3
--- /dev/null
+++ b/opcodes/mcore-dis.c
@@ -0,0 +1,277 @@
+/* Disassemble Motorolla M*Core instructions.
+ Copyright (C) 1993, 1999 Free Software Foundation, Inc.
+
+This program 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.
+
+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.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#define STATIC_TABLE
+#define DEFINE_TABLE
+
+#include "mcore-opc.h"
+#include "dis-asm.h"
+
+/* Mask for each mcore_opclass: */
+static const unsigned short imsk[] =
+{
+ /* O0 */ 0xFFFF,
+ /* OT */ 0xFFFC,
+ /* O1 */ 0xFFF0,
+ /* OC */ 0xFFE0,
+ /* O2 */ 0xFF00,
+ /* X1 */ 0xFFF0,
+ /* OI */ 0xFE00,
+ /* OB */ 0xFE00,
+
+ /* OMa */ 0xFFF0,
+ /* SI */ 0xFE00,
+ /* I7 */ 0xF800,
+ /* LS */ 0xF000,
+ /* BR */ 0xF800,
+ /* BL */ 0xFF00,
+ /* LR */ 0xF000,
+ /* LJ */ 0xFF00,
+
+ /* RM */ 0xFFF0,
+ /* RQ */ 0xFFF0,
+ /* JSR */ 0xFFF0,
+ /* JMP */ 0xFFF0,
+ /* OBRa*/ 0xFFF0,
+ /* OBRb*/ 0xFF80,
+ /* OBRc*/ 0xFF00,
+ /* OBR2*/ 0xFE00,
+
+ /* O1R1*/ 0xFFF0,
+ /* OMb */ 0xFF80,
+ /* OMc */ 0xFF00,
+ /* SIa */ 0xFE00,
+
+/* start-sanitize-m340 */
+ /* MULSH */ 0xFF00,
+/* end-sanitize-m340 */
+
+ /* JC */ 0, /* JC,JU,JL don't appear in object */
+ /* JU */ 0,
+ /* JL */ 0,
+ /* RSI */ 0,
+ /* DO21*/ 0,
+ /* OB2 */ 0 /* OB2 won't appear in object. */
+};
+
+static const char * grname[] =
+{
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
+};
+
+static const char X[] = "??";
+
+static const char * crname[] =
+{
+ "psr", "vbr", "epsr", "fpsr", "epc", "fpc", "ss0", "ss1",
+ "ss2", "ss3", "ss4", "gcr", "gsr", X, X, X,
+ X, X, X, X, X, X, X, X,
+ X, X, X, X, X, X, X, X
+};
+
+static const unsigned isiz[] = { 2, 0, 1, 0 };
+
+int
+print_insn_mcore (memaddr, info)
+ bfd_vma memaddr;
+ struct disassemble_info * info;
+{
+ unsigned char ibytes[4];
+ fprintf_ftype fprintf = info->fprintf_func;
+ void * stream = info->stream;
+ unsigned short inst;
+ mcore_opcode_info * op;
+ int status;
+
+ info->bytes_per_chunk = 2;
+
+ status = info->read_memory_func (memaddr, ibytes, 2, info);
+
+ if (status != 0)
+ {
+ info->memory_error_func (status, memaddr, info);
+ return -1;
+ }
+
+/* start-sanitize-m340 */
+ if (info->endian == BFD_ENDIAN_BIG)
+/* end-sanitize-m340 */
+ inst = (ibytes[0] << 8) | ibytes[1];
+/* start-sanitize-m340 */
+ else if (info->endian == BFD_ENDIAN_LITTLE)
+ inst = (ibytes[1] << 8) | ibytes[0];
+ else
+ abort ();
+/* end-sanitize-m340 */
+
+ /* Just a linear search of the table. */
+ for (op = mcore_table; op->name != 0; op ++)
+ if (op->inst == (inst & imsk[op->opclass]))
+ break;
+
+ if (op->name == 0)
+ fprintf (stream, ".word 0x%04x", inst);
+ else
+ {
+ const char * name = grname[inst & 0x0F];
+
+ fprintf (stream, "%s", op->name);
+
+ switch (op->opclass)
+ {
+ case O0: break;
+ case OT: fprintf (stream, "\t%d", inst & 0x3); break;
+ case O1:
+ case JMP:
+ case JSR: fprintf (stream, "\t%s", name); break;
+ case OC: fprintf (stream, "\t%s, %s", name, crname[(inst >> 4) & 0x1F]); break;
+ case O1R1: fprintf (stream, "\t%s, r1", name); break;
+/* start-sanitize-m340 */
+ case MULSH:
+/* end-sanitize-m340 */
+ case O2: fprintf (stream, "\t%s, %s", name, grname[(inst >> 4) & 0xF]); break;
+ case X1: fprintf (stream, "\tr1, %s", name); break;
+ case OI: fprintf (stream, "\t%s, %d", name, ((inst >> 4) & 0x1F) + 1); break;
+ case RM: fprintf (stream, "\t%s-r15, (r0)", name); break;
+ case RQ: fprintf (stream, "\tr4-r7, (%s)", name); break;
+ case OB:
+ case OBRa:
+ case OBRb:
+ case OBRc:
+ case SI:
+ case SIa:
+ case OMa:
+ case OMb:
+ case OMc: fprintf (stream, "\t%s, %d", name, (inst >> 4) & 0x1F); break;
+ case I7: fprintf (stream, "\t%s, %d", name, (inst >> 4) & 0x7F); break;
+ case LS: fprintf (stream, "\t%s, (%s, %d)", grname[(inst >> 8) & 0xF],
+ name, ((inst >> 4) & 0xF) << isiz[(inst >> 13) & 3]);
+ break;
+
+ case BR:
+ {
+ long val = inst & 0x3FF;
+
+ if (inst & 0x400)
+ val |= 0xFFFFFC00;
+
+ fprintf (stream, "\t0x%x", memaddr + 2 + (val<<1));
+
+ if (strcmp (op->name, "bsr") == 0)
+ {
+ /* for bsr, we'll try to get a symbol for the target */
+ val = memaddr + 2 + (val << 1);
+
+ if (info->print_address_func && val != 0)
+ {
+ fprintf (stream, "\t// ");
+ info->print_address_func (val, info);
+ }
+ }
+ }
+ break;
+
+ case BL:
+ {
+ long val;
+ val = (inst & 0x000F);
+ fprintf (stream, "\t%s, 0x%x",
+ grname[(inst >> 4) & 0xF], memaddr - (val << 1));
+ }
+ break;
+
+ case LR:
+ {
+ unsigned long val;
+
+ val = (memaddr + 2 + ((inst & 0xFF) << 2)) & 0xFFFFFFFC;
+
+ status = info->read_memory_func (val, ibytes, 4, info);
+ if (status != 0)
+ {
+ info->memory_error_func (status, memaddr, info);
+ break;
+ }
+
+/* start-sanitize-m340 */
+ if (info->endian == BFD_ENDIAN_LITTLE)
+ val = (ibytes[3] << 24) | (ibytes[2] << 16)
+ | (ibytes[1] << 8) | (ibytes[0]);
+ else
+/* end-sanitize-m340 */
+ val = (ibytes[0] << 24) | (ibytes[1] << 16)
+ | (ibytes[2] << 8) | (ibytes[3]);
+
+ /* Removed [] around literal value to match ABI syntax 12/95. */
+ fprintf (stream, "\t%s, 0x%X", grname[(inst >> 8) & 0xF], val);
+
+ if (val == 0)
+ fprintf (stream, "\t// from address pool at 0x%x",
+ (memaddr + 2 + ((inst & 0xFF) << 2)) & 0xFFFFFFFC);
+ }
+ break;
+
+ case LJ:
+ {
+ unsigned long val;
+
+ val = (memaddr + 2 + ((inst & 0xFF) << 2)) & 0xFFFFFFFC;
+
+ status = info->read_memory_func (val, ibytes, 4, info);
+ if (status != 0)
+ {
+ info->memory_error_func (status, memaddr, info);
+ break;
+ }
+
+/* start-sanitize-m340 */
+ if (info->endian == BFD_ENDIAN_LITTLE)
+ val = (ibytes[3] << 24) | (ibytes[2] << 16)
+ | (ibytes[1] << 8) | (ibytes[0]);
+ else
+/* end-sanitize-m340 */
+ val = (ibytes[0] << 24) | (ibytes[1] << 16)
+ | (ibytes[2] << 8) | (ibytes[3]);
+
+ /* Removed [] around literal value to match ABI syntax 12/95. */
+ fprintf (stream, "\t0x%X", val);
+ /* For jmpi/jsri, we'll try to get a symbol for the target. */
+ if (info->print_address_func && val != 0)
+ {
+ fprintf (stream, "\t// ");
+ info->print_address_func (val, info);
+ }
+ else
+ {
+ fprintf (stream, "\t// from address pool at 0x%x",
+ (memaddr + 2 + ((inst & 0xFF) << 2)) & 0xFFFFFFFC);
+ }
+ }
+ break;
+
+ default:
+ /* if the disassembler lags the instruction set */
+ fprintf (stream, "\tundecoded operands, inst is 0x%04x", inst);
+ break;
+ }
+ }
+
+ /* Say how many bytes we consumed? */
+ return 2;
+}