/* Disassemble MN10300 instructions.
- Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+ Copyright 1996, 1997, 1998, 1999, 2000, 2001 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
#include <stdio.h>
#include "sysdep.h"
-#include "opcode/mn10300.h"
+#include "opcode/mn10300.h"
#include "dis-asm.h"
#include "opintl.h"
static void disassemble PARAMS ((bfd_vma, struct disassemble_info *,
unsigned long insn, unsigned int));
-#define HAVE_AM33 (info->mach == AM33)
+#define HAVE_AM33_2 (info->mach == AM33_2)
+#define HAVE_AM33 (info->mach == AM33 || HAVE_AM33_2)
#define HAVE_AM30 (info->mach == AM30)
-int
+int
print_insn_mn10300 (memaddr, info)
bfd_vma memaddr;
struct disassemble_info *info;
if (status != 0)
{
(*info->memory_error_func) (status, memaddr, info);
- return -1;
+ return -1;
}
insn = bfd_getb16 (buffer);
consume = 2;
/* These are three byte insns. */
else if ((insn & 0xff) == 0xf8
- || (insn & 0xff) == 0xcc
+ || (insn & 0xff) == 0xcc
|| (insn & 0xff) == 0xf9
|| (insn & 0xf3) == 0x01
|| (insn & 0xf3) == 0x02
(*info->memory_error_func) (status, memaddr, info);
return -1;
}
- insn |= *(unsigned char *)buffer;
+ insn |= *(unsigned char *) buffer;
consume = 3;
}
insn = bfd_getb32 (buffer);
consume = 7;
+ /* Handle the 5-byte extended instruction codes. */
+ if ((insn & 0xfff80000) == 0xfe800000)
+ consume = 5;
}
disassemble (memaddr, info, insn, consume);
mysize = 5;
else if (op->format == FMT_D2)
mysize = 4;
+ else if (op->format == FMT_D3)
+ mysize = 5;
else if (op->format == FMT_D4)
mysize = 6;
else if (op->format == FMT_D6)
mysize = 7;
else
mysize = 7;
-
+
if ((op->mask & insn) == op->opcode
&& size == (unsigned int) mysize
&& (op->machine == 0
+ || (op->machine == AM33_2 && HAVE_AM33_2)
|| (op->machine == AM33 && HAVE_AM33)
|| (op->machine == AM30 && HAVE_AM30)))
{
const unsigned char *opindex_ptr;
unsigned int nocomma;
int paren = 0;
-
+
if (op->format == FMT_D1 || op->format == FMT_S1)
extra_shift = 8;
else if (op->format == FMT_D2 || op->format == FMT_D4
insn |= (temp & 0xffffff00) >> 8;
extension = temp & 0xff;
}
+ else if (size == 5 && op->format == FMT_D3)
+ {
+ status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
+ if (status != 0)
+ {
+ (*info->memory_error_func) (status, memaddr, info);
+ return;
+ }
+ insn &= 0xffff0000;
+ insn |= bfd_getl16 (buffer);
+
+ status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
+ if (status != 0)
+ {
+ (*info->memory_error_func) (status, memaddr, info);
+ return;
+ }
+ extension = *(unsigned char *) buffer;
+ }
else if (size == 5)
{
unsigned long temp = 0;
(*info->memory_error_func) (status, memaddr, info);
return;
}
- extension = *(unsigned char *)buffer;
+ extension = *(unsigned char *) buffer;
}
else if (size == 6 && op->format == FMT_D8)
{
(*info->memory_error_func) (status, memaddr, info);
return;
}
- insn |= *(unsigned char *)buffer;
+ insn |= *(unsigned char *) buffer;
status = (*info->read_memory_func) (memaddr + 3, buffer, 2, info);
if (status != 0)
insn &= 0xff000000;
insn |= (temp >> 8) & 0xffffff;
extension = (temp & 0xff) << 16;
-
+
status = (*info->read_memory_func) (memaddr + 5, buffer, 2, info);
if (status != 0)
{
insn &= 0xffff0000;
insn |= (temp >> 16) & 0xffff;
extension = (temp & 0xffff) << 8;
-
+
status = (*info->read_memory_func) (memaddr + 6, buffer, 1, info);
if (status != 0)
{
(*info->memory_error_func) (status, memaddr, info);
return;
}
- extension |= *(unsigned char *)buffer;
+ extension |= *(unsigned char *) buffer;
}
match = 1;
temp = extension >> operand->shift;
temp &= ((1 << (32 - operand->bits)) - 1);
value |= temp;
+ value = ((value ^ (((unsigned long) 1) << 31))
+ - (((unsigned long) 1) << 31));
}
else if ((operand->flags & MN10300_OPERAND_24BIT) != 0)
{
temp &= ((1 << (24 - operand->bits)) - 1);
value |= temp;
if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
- value = ((value & 0xffffff) ^ (~0x7fffff)) + 0x800000;
+ value = ((value & 0xffffff) ^ 0x800000) - 0x800000;
+ }
+ else if ((operand->flags & (MN10300_OPERAND_FSREG
+ | MN10300_OPERAND_FDREG)))
+ {
+ /* See m10300-opc.c just before #define FSM0 for an
+ explanation of these variables. Note that
+ FMT-implied shifts are not taken into account for
+ FP registers. */
+ unsigned long mask_low, mask_high;
+ int shl_low, shr_high, shl_high;
+
+ switch (operand->bits)
+ {
+ case 5:
+ /* Handle regular FP registers. */
+ if (operand->shift >= 0)
+ {
+ /* This is an `m' register. */
+ shl_low = operand->shift;
+ shl_high = 8 + (8 & shl_low) + (shl_low & 4) / 4;
+ }
+ else
+ {
+ /* This is an `n' register. */
+ shl_low = -operand->shift;
+ shl_high = shl_low / 4;
+ }
+ mask_low = 0x0f;
+ mask_high = 0x10;
+ shr_high = 4;
+ break;
+
+ case 3:
+ /* Handle accumulators. */
+ shl_low = -operand->shift;
+ shl_high = 0;
+ mask_low = 0x03;
+ mask_high = 0x04;
+ shr_high = 2;
+ break;
+
+ default:
+ abort ();
+ }
+ value = ((((insn >> shl_high) << shr_high) & mask_high)
+ | ((insn >> shl_low) & mask_low));
}
else if ((operand->flags & MN10300_OPERAND_EXTENDED) != 0)
{
}
if ((operand->flags & MN10300_OPERAND_SIGNED) != 0
- /* These are properly extended by the code above. */
- && ((operand->flags & MN10300_OPERAND_24BIT) == 0)
- )
- value = ((long)(value << (32 - operand->bits))
- >> (32 - operand->bits));
+ /* These are properly extended by the code above. */
+ && ((operand->flags & MN10300_OPERAND_24BIT) == 0))
+ value = ((value ^ (((unsigned long) 1) << (operand->bits - 1)))
+ - (((unsigned long) 1) << (operand->bits - 1)));
if (!nocomma
&& (!paren
(*info->fprintf_func) (info->stream, ",");
nocomma = 0;
-
+
if ((operand->flags & MN10300_OPERAND_DREG) != 0)
{
value = ((insn >> (operand->shift + extra_shift))
& ((1 << operand->bits) - 1));
- (*info->fprintf_func) (info->stream, "d%d", value);
+ (*info->fprintf_func) (info->stream, "d%d", (int) value);
}
else if ((operand->flags & MN10300_OPERAND_AREG) != 0)
{
value = ((insn >> (operand->shift + extra_shift))
& ((1 << operand->bits) - 1));
- (*info->fprintf_func) (info->stream, "a%d", value);
+ (*info->fprintf_func) (info->stream, "a%d", (int) value);
}
else if ((operand->flags & MN10300_OPERAND_SP) != 0)
value = ((insn >> (operand->shift + extra_shift))
& ((1 << operand->bits) - 1));
if (value < 8)
- (*info->fprintf_func) (info->stream, "r%d", value);
+ (*info->fprintf_func) (info->stream, "r%d", (int) value);
else if (value < 12)
- (*info->fprintf_func) (info->stream, "a%d", value - 8);
+ (*info->fprintf_func) (info->stream, "a%d", (int) value - 8);
else
- (*info->fprintf_func) (info->stream, "d%d", value - 12);
+ (*info->fprintf_func) (info->stream, "d%d", (int) value - 12);
}
else if ((operand->flags & MN10300_OPERAND_XRREG) != 0)
if (value == 0)
(*info->fprintf_func) (info->stream, "sp", value);
else
- (*info->fprintf_func) (info->stream, "xr%d", value);
+ (*info->fprintf_func) (info->stream, "xr%d", (int) value);
}
+ else if ((operand->flags & MN10300_OPERAND_FSREG) != 0)
+ (*info->fprintf_func) (info->stream, "fs%d", (int) value);
+
+ else if ((operand->flags & MN10300_OPERAND_FDREG) != 0)
+ (*info->fprintf_func) (info->stream, "fd%d", (int) value);
+
+ else if ((operand->flags & MN10300_OPERAND_FPCR) != 0)
+ (*info->fprintf_func) (info->stream, "fpcr");
+
else if ((operand->flags & MN10300_OPERAND_USP) != 0)
(*info->fprintf_func) (info->stream, "usp");
(*info->fprintf_func) (info->stream, "]");
}
- else
- (*info->fprintf_func) (info->stream, "%d", value);
+ else
+ (*info->fprintf_func) (info->stream, "%ld", (long) value);
}
/* All done. */
break;