* mn10300-dis.c: Start working on disassembler support.
authorJeff Law <law@redhat.com>
Tue, 19 Nov 1996 23:59:27 +0000 (23:59 +0000)
committerJeff Law <law@redhat.com>
Tue, 19 Nov 1996 23:59:27 +0000 (23:59 +0000)
        * mn10300-opc.c (mn10300_opcodes): Fix masks on several insns.
Selects opcodes & consumes bytes.  Breaks badly if given data instead of
code.  No operands yet.

opcodes/ChangeLog
opcodes/mn10300-dis.c
opcodes/mn10300-opc.c

index f845111f4e22293ccd1f079ca83a4c7051b1893a..0aa15651a2b9427ce3292f0c51878754d5035b79 100644 (file)
@@ -1,5 +1,8 @@
 Tue Nov 19 13:33:01 1996  Jeffrey A Law  (law@cygnus.com)
 
+       * mn10300-dis.c: Start working on disassembler support.
+       * mn10300-opc.c (mn10300_opcodes): Fix masks on several insns.
+
        * mn10300-opc.c (mn10300_operands): Add "REGS" for a register
        list.
        (mn10300_opcodes): Use REGS for register list in "movm" instructions.
index b81d49326c5780cf9ddc31c48c2ee7d043f9947c..707940aa803c5857baedbe96ad000de347f0a7dd 100644 (file)
@@ -22,13 +22,277 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "opcode/mn10300.h" 
 #include "dis-asm.h"
 
-static void disassemble PARAMS ((bfd_vma memaddr,
-                                struct disassemble_info *info,
-                                unsigned long insn));
+static void disassemble PARAMS ((bfd_vma, struct disassemble_info *,
+                                unsigned long insn, unsigned long,
+                                unsigned int));
+
+static const char *const mn10300_reg_names[] =
+{ "d0", "d1", "d2", "d3", "a0", "a1", "a2", "a3", };
 
 int 
 print_insn_mn10300 (memaddr, info)
      bfd_vma memaddr;
      struct disassemble_info *info;
 {
+  int status;
+  bfd_byte buffer[4];
+  unsigned long insn;
+  unsigned long extension;
+  unsigned int consume;
+
+  /* First figure out how big the opcode is.  */
+  status = (*info->read_memory_func) (memaddr, buffer, 1, info);
+  if (status != 0)
+    {
+      (*info->memory_error_func) (status, memaddr, info);
+      return -1;
+    }
+  insn = *(unsigned char *) buffer;
+
+  /* These are one byte insns XXX imm8 versions of mov, cmp.  */
+  if ((insn & 0xf3) == 0x00
+      || (insn & 0xf0) == 0x10
+      || (insn & 0xfc) == 0x3c
+      || (insn & 0xf3) == 0x41
+      || (insn & 0xf3) == 0x40
+      || (insn & 0xfc) == 0x50
+      || (insn & 0xfc) == 0x54
+      || (insn & 0xf0) == 0x60
+      || (insn & 0xf0) == 0x70
+      || ((insn & 0xf0) == 0x80
+         && (insn & 0x0c) >> 2 != (insn & 0x03))
+      || ((insn & 0xf0) == 0x90
+         && (insn & 0x0c) >> 2 != (insn & 0x03))
+      || ((insn & 0xf0) == 0xa0
+         && (insn & 0x0c) >> 2 != (insn & 0x03))
+      || ((insn & 0xf0) == 0xb0
+         && (insn & 0x0c) >> 2 != (insn & 0x03))
+      || (insn & 0xff) == 0xcb
+      || (insn & 0xfc) == 0xd0
+      || (insn & 0xfc) == 0xd4
+      || (insn & 0xfc) == 0xd8
+      || (insn & 0xf0) == 0xe0)
+    {
+      extension = 0;
+      consume = 1;
+    }
+
+  /* These are two byte insns.  */
+  else if ((insn & 0xf0) == 0x80
+          || (insn & 0xf0) == 0x90
+          || (insn & 0xf0) == 0xa0
+          || (insn & 0xf0) == 0xb0
+          || (insn & 0xfc) == 0x20
+          || (insn & 0xfc) == 0x28
+          || (insn & 0xf3) == 0x43
+          || (insn & 0xf3) == 0x42
+          || (insn & 0xfc) == 0x58
+          || (insn & 0xfc) == 0x5c
+          || ((insn & 0xf0) == 0xc0
+              && (insn & 0xff) != 0xcb
+              && (insn & 0xff) != 0xcc
+              && (insn & 0xff) != 0xcd)
+          || (insn & 0xff) == 0xf0
+          || (insn & 0xff) == 0xf1
+          || (insn & 0xff) == 0xf2
+          || (insn & 0xff) == 0xf3
+          || (insn & 0xff) == 0xf4
+          || (insn & 0xff) == 0xf5
+          || (insn & 0xff) == 0xf6)
+    {
+      status = (*info->read_memory_func) (memaddr, buffer, 2, info);
+      if (status != 0)
+       {
+         (*info->memory_error_func) (status, memaddr, info);
+          return -1;
+       }
+      insn = bfd_getb16 (buffer);
+      extension = 0;
+      consume = 2;
+    }
+
+  /* These are three byte insns.  */
+  else if ((insn & 0xff) == 0xf8
+          || (insn & 0xff) == 0xcc 
+          || (insn & 0xff) == 0xf9
+          || (insn & 0xf3) == 0x01
+          || (insn & 0xf3) == 0x02
+          || (insn & 0xf3) == 0x03
+          || (insn & 0xfc) == 0x24
+          || (insn & 0xfc) == 0x2c
+          || (insn & 0xfc) == 0x30
+          || (insn & 0xfc) == 0x34
+          || (insn & 0xfc) == 0x38
+          || (insn & 0xff) == 0xde
+          || (insn & 0xff) == 0xdf
+          || (insn & 0xff) == 0xcc)
+    {
+      status = (*info->read_memory_func) (memaddr, buffer, 2, info);
+      if (status != 0)
+       {
+         (*info->memory_error_func) (status, memaddr, info);
+         return -1;
+       }
+      insn = bfd_getb16 (buffer);
+      insn <<= 8;
+      insn |= *(unsigned char *)buffer + 2;
+      extension = 0;
+      consume = 3;
+    }
+
+  /* These are four byte insns.  */
+  else if ((insn & 0xff) == 0xfa
+          || (insn & 0xff) == 0xfb)
+    {
+      status = (*info->read_memory_func) (memaddr, buffer, 4, info);
+      if (status != 0)
+       {
+         (*info->memory_error_func) (status, memaddr, info);
+         return -1;
+       }
+      insn = bfd_getb32 (buffer);
+      extension = 0;
+      consume = 4;
+    }
+
+  /* These are five byte insns.  */
+  else if ((insn & 0xff) == 0xcd
+          || (insn & 0xff) == 0xdc)
+    {
+      status = (*info->read_memory_func) (memaddr, buffer, 4, info);
+      if (status != 0)
+       {
+         (*info->memory_error_func) (status, memaddr, info);
+         return -1;
+       }
+      insn = bfd_getb32 (buffer);
+
+      status = (*info->read_memory_func) (memaddr, buffer, 1, info);
+      if (status != 0)
+       {
+         (*info->memory_error_func) (status, memaddr, info);
+         return -1;
+       }
+      extension = *(unsigned char *) buffer + 4;
+      consume = 5;
+    }
+
+  /* These are six byte insns.  */
+  else if ((insn & 0xff) == 0xfd
+          || (insn & 0xff) == 0xfc)
+    {
+      status = (*info->read_memory_func) (memaddr, buffer, 4, info);
+      if (status != 0)
+       {
+         (*info->memory_error_func) (status, memaddr, info);
+         return -1;
+       }
+
+      insn = bfd_getb32 (buffer);
+      status = (*info->read_memory_func) (memaddr, buffer, 2, info);
+      if (status != 0)
+       {
+         (*info->memory_error_func) (status, memaddr, info);
+         return -1;
+       }
+      extension = bfd_getb16 (buffer + 4);
+      consume = 6;
+    }
+
+  /* Else its a seven byte insns (in theory).  */
+  else
+    {
+      status = (*info->read_memory_func) (memaddr, buffer, 4, info);
+      if (status != 0)
+       {
+         (*info->memory_error_func) (status, memaddr, info);
+         return -1;
+       }
+
+      insn = bfd_getb32 (buffer);
+      status = (*info->read_memory_func) (memaddr, buffer, 2, info);
+      if (status != 0)
+       {
+         (*info->memory_error_func) (status, memaddr, info);
+         return -1;
+       }
+      extension = bfd_getb16 (buffer);
+      extension <<= 8;
+      extension |= *(unsigned char *)buffer + 2;
+      consume = 7;
+    }
+
+  disassemble (memaddr, info, insn, extension, consume);
+
+  return consume;
+}
+
+static void
+disassemble (memaddr, info, insn, extension, size)
+     bfd_vma memaddr;
+     struct disassemble_info *info;
+     unsigned long insn;
+     unsigned long extension;
+     unsigned int size;
+{
+  struct mn10300_opcode *op = (struct mn10300_opcode *)mn10300_opcodes;
+  const struct mn10300_operand *operand;
+  int match = 0;
+
+  /* Find the opcode.  */
+  while (op->name)
+    {
+      int mysize;
+
+      if (op->format == FMT_S0)
+       mysize = 1;
+      else if (op->format == FMT_S1
+              || op->format == FMT_D0)
+       mysize = 2;
+      else if (op->format == FMT_S2
+              || op->format == FMT_D1)
+       mysize = 3;
+      else if (op->format == FMT_S4)
+       mysize = 5;
+      else if (op->format == FMT_D2)
+       mysize = 4;
+      else if (op->format == FMT_D4)
+       mysize = 6;
+      else
+       mysize = 7;
+       
+      if ((op->mask & insn) == op->opcode
+         && size == mysize)
+       {
+         const unsigned char *opindex_ptr;
+         unsigned int opnum, memop;
+         
+         match = 1;
+         (*info->fprintf_func) (info->stream, "%s\t", op->name);
+
+         /* Now print the operands.  */
+         for (opindex_ptr = op->operands, opnum = 1;
+              *opindex_ptr != 0;
+              opindex_ptr++, opnum++)
+           {
+             unsigned long value;
+
+             operand = &mn10300_operands[*opindex_ptr];
+
+             value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
+
+             if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
+               value = ((long)(value << (32 - operand->bits))
+                         >> (32 - operand->bits));
+
+         /* All done. */
+         break;
+       }
+      op++;
+    }
+
+  if (!match)
+    {
+       (*info->fprintf_func) (info->stream, "unknown\t0x%04x", insn);
+    }
 }
index 9484d4e347745c6edf75ed2ed3a3ee1f346f9d8a..936bc8c85947750416c3aae3c257387d51d49b03 100644 (file)
@@ -299,8 +299,8 @@ const struct mn10300_opcode mn10300_opcodes[] = {
 { "add",       0xfad00000,     0xfffc0000,     FMT_D2, {SIMM16, AN0}},
 { "add",       0xfcd00000,     0xfffc0000,     FMT_D4, {IMM32, AN0}},
 { "add",       0xf8fe00,       0xffff00,       FMT_D1, {SIMM8, SP}},
-{ "add",       0xfafe0000,     0xfffc0000,     FMT_D2, {SIMM16, SP}},
-{ "add",       0xfcfe0000,     0xfff0000,      FMT_D4, {IMM32, SP}},
+{ "add",       0xfafe0000,     0xffff0000,     FMT_D2, {SIMM16, SP}},
+{ "add",       0xfcfe0000,     0xffff0000,     FMT_D4, {IMM32, SP}},
 { "addc",      0xf140,         0xfff0,         FMT_D0, {DM1, DN0}},
 
 { "sub",       0xf100,         0xfff0,         FMT_D0, {DM1, DN0}},
@@ -336,12 +336,12 @@ const struct mn10300_opcode mn10300_opcodes[] = {
 { "and",       0xf8e000,       0xfffc00,       FMT_D1, {IMM8, DN0}},
 { "and",       0xfae00000,     0xfffc0000,     FMT_D2, {IMM16, DN0}},
 { "and",       0xfce00000,     0xfffc0000,     FMT_D4, {IMM32, DN0}},
-{ "and",       0xfafc0000,     0xfffc0000,     FMT_D2, {IMM16, PSW}},
+{ "and",       0xfafc0000,     0xffff0000,     FMT_D2, {IMM16, PSW}},
 { "or",                0xf210,         0xfff0,         FMT_D0, {DM1, DN0}},
 { "or",                0xf8e400,       0xfffc00,       FMT_D1, {IMM8, DN0}},
 { "or",                0xfae40000,     0xfffc0000,     FMT_D2, {IMM16, DN0}},
 { "or",                0xfce40000,     0xfffc0000,     FMT_D4, {IMM32, DN0}},
-{ "or",                0xfafd0000,     0xfffc0000,     FMT_D2, {IMM16, PSW}},
+{ "or",                0xfafd0000,     0xffff0000,     FMT_D2, {IMM16, PSW}},
 { "xor",       0xf220,         0xfff0,         FMT_D0, {DM1, DN0}},
 { "xor",       0xfae80000,     0xfffc0000,     FMT_D2, {IMM16, DN0}},
 { "xor",       0xfce80000,     0xfffc0000,     FMT_D4, {IMM32, DN0}},
@@ -415,8 +415,8 @@ const struct mn10300_opcode mn10300_opcodes[] = {
 { "calls",     0xfaff0000,     0xffff0000,     FMT_D2, {IMM16}},
 { "calls",     0xfcff0000,     0xffff0000,     FMT_D4, {IMM32}},
 
-{ "ret",       0xdf0000,       0xff00000,      FMT_S2, {IMM8_SHIFT8, IMM8}},
-{ "retf",      0xde0000,       0xff00000,      FMT_S2, {IMM8_SHIFT8, IMM8}},
+{ "ret",       0xdf0000,       0xff0000      FMT_S2, {IMM8_SHIFT8, IMM8}},
+{ "retf",      0xde0000,       0xff0000      FMT_S2, {IMM8_SHIFT8, IMM8}},
 { "rets",      0xf0fc,         0xffff,         FMT_D0, {UNUSED}},
 { "rti",       0xf0fd,         0xffff,         FMT_D0, {UNUSED}},
 { "trap",      0xf0fe,         0xffff,         FMT_D0, {UNUSED}},