/* Print instructions for the Motorola 88000, for GDB and GNU Binutils.
- Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1993, 1998, 2000, 2001,
- 2002 Free Software Foundation, Inc.
+ Copyright (C) 1986-2014 Free Software Foundation, Inc.
Contributed by Data General Corporation, November 1989.
Partially derived from an earlier printcmd.c.
-This file is part of GDB and the GNU Binutils.
+ This file is part of the GNU opcodes library.
-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 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 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
-Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
+ 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., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
#include "sysdep.h"
#include "dis-asm.h"
#include "opintl.h"
#include "libiberty.h"
-typedef struct HASHTAB {
+typedef struct HASHTAB
+{
const INSTAB *instr;
struct HASHTAB *next;
} HASHTAB;
/* Opcode Mnemonic Op 1 Spec Op 2 Spec Op 3 Spec Simflags Next */
-const INSTAB instructions[] = {
+const INSTAB instructions[] =
+{
{0xf400c800,"jsr ",{0,5,REG} ,NO_OPERAND ,NO_OPERAND , {2,2,NA,JSR , 0,0,1,0,0,0,0,1,0,0,0,0} },
{0xf400cc00,"jsr.n ",{0,5,REG} ,NO_OPERAND ,NO_OPERAND , {1,1,NA,JSR , 0,0,1,0,0,0,1,1,0,0,0,0} },
{0xf400c000,"jmp ",{0,5,REG} ,NO_OPERAND ,NO_OPERAND , {2,2,NA,JMP , 0,0,1,0,0,0,0,1,0,0,0,0} },
{0x8400bc20,"fcmpu.sxs ",{21,5,REG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} },
{0x8400bd20,"fcmpu.sxx ",{21,5,REG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} },
- {0x84000820,"fcvt.sd ",{21,5,REG} ,{0,5,REG} ,NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} },
- {0x84000880,"fcvt.ds ",{21,5,REG} ,{0,5,REG} ,NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} },
+ {0x84000820,"fcvt.ds ",{21,5,REG} ,{0,5,REG} ,NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} },
+ {0x84000880,"fcvt.sd ",{21,5,REG} ,{0,5,REG} ,NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} },
- {0x84008880,"fcvt.ds ",{21,5,XREG} ,{0,5,XREG} ,NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} },
- {0x840088c0,"fcvt.dx ",{21,5,XREG} ,{0,5,XREG} ,NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} },
- {0x84008820,"fcvt.sd ",{21,5,XREG} ,{0,5,XREG} ,NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} },
- {0x84008840,"fcvt.sx ",{21,5,XREG} ,{0,5,XREG} ,NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} },
- {0x84008920,"fcvt.xd ",{21,5,XREG} ,{0,5,XREG} ,NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} },
- {0x84008900,"fcvt.xs ",{21,5,XREG} ,{0,5,XREG} ,NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} },
+ {0x84008880,"fcvt.sd ",{21,5,XREG} ,{0,5,XREG} ,NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} },
+ {0x840088c0,"fcvt.xd ",{21,5,XREG} ,{0,5,XREG} ,NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} },
+ {0x84008820,"fcvt.ds ",{21,5,XREG} ,{0,5,XREG} ,NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} },
+ {0x84008840,"fcvt.xs ",{21,5,XREG} ,{0,5,XREG} ,NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} },
+ {0x84008920,"fcvt.dx ",{21,5,XREG} ,{0,5,XREG} ,NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} },
+ {0x84008900,"fcvt.sx ",{21,5,XREG} ,{0,5,XREG} ,NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} },
{0x8400f2a0,"fdiv.ddd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} },
{0x8400f280,"fdiv.dds ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} },
};
HASHTAB *hashtable[HASHVAL] = {0};
-
-static int
-m88kdis PARAMS ((bfd_vma, unsigned long, struct disassemble_info *));
-
-static void
-printop PARAMS ((struct disassemble_info *, const OPSPEC *, unsigned long, bfd_vma, int));
-
-static void
-init_disasm PARAMS ((void));
\f
-/* Disassemble an M88000 instruction at `memaddr'. */
-
-int
-print_insn_m88k (memaddr, info)
- bfd_vma memaddr;
- struct disassemble_info *info;
-{
- bfd_byte buffer[4];
- int status;
-
- /* Instruction addresses may have low two bits set. Clear them. */
- memaddr &=~ (bfd_vma) 3;
-
- status = (*info->read_memory_func) (memaddr, buffer, 4, info);
- if (status != 0)
- {
- (*info->memory_error_func) (status, memaddr, info);
- return -1;
- }
-
- return m88kdis (memaddr, bfd_getb32 (buffer), info);
-}
-
-/*
- * Disassemble the instruction in `instruction'.
- * `pc' should be the address of this instruction, it will be used to
- * print the target address if this is a relative jump or call the
- * disassembled instruction is written to `info'.
- *
- * The function returns the length of this instruction in bytes.
- */
+/* Initialize the disassembler instruction table.
+
+ Initialize the hash table and instruction table for the
+ disassembler. This should be called once before the first call to
+ disasm(). */
-static int
-m88kdis (pc, instruction, info)
- bfd_vma pc;
- unsigned long instruction;
- struct disassemble_info *info;
+static void
+init_disasm (void)
{
- static int ihashtab_initialized = 0;
- unsigned int opcode;
- const HASHTAB *entry_ptr;
- int opmask;
- unsigned int class;
-
- if (! ihashtab_initialized)
- {
- init_disasm ();
- ihashtab_initialized = 1;
- }
+ unsigned int hashvalue, hashsize;
+ struct HASHTAB *hashentries;
+ unsigned int i;
- /* Create the appropriate mask to isolate the opcode. */
- opmask = DEFMASK;
- class = instruction & DEFMASK;
- if ((class >= SFU0) && (class <= SFU7))
- {
- if (instruction < SFU1)
- opmask = CTRLMASK;
- else
- opmask = SFUMASK;
- }
- else if (class == RRR)
- opmask = RRRMASK;
- else if (class == RRI10)
- opmask = RRI10MASK;
+ hashsize = sizeof (instructions) / sizeof (INSTAB);
- /* Isolate the opcode. */
- opcode = instruction & opmask;
+ hashentries = xmalloc (hashsize * sizeof (struct HASHTAB));
- /* Search the hash table with the isolated opcode. */
- for (entry_ptr = hashtable[opcode % HASHVAL];
- (entry_ptr != NULL) && (entry_ptr->instr->opcode != opcode);
- entry_ptr = entry_ptr->next)
- ;
+ for (i = 0; i < HASHVAL; i++)
+ hashtable[i] = NULL;
- if (entry_ptr == NULL)
- (*info->fprintf_func) (info->stream, "word\t%08x", instruction);
- else
+ for (i = 0; i < hashsize; i++)
{
- (*info->fprintf_func) (info->stream, "%s", entry_ptr->instr->mnemonic);
- printop (info, &(entry_ptr->instr->op1), instruction, pc, 1);
- printop (info, &(entry_ptr->instr->op2), instruction, pc, 0);
- printop (info, &(entry_ptr->instr->op3), instruction, pc, 0);
+ hashvalue = (instructions[i].opcode) % HASHVAL;
+ hashentries[i].instr = &instructions[i];
+ hashentries[i].next = hashtable[hashvalue];
+ hashtable[hashvalue] = &hashentries[i];
}
-
- return 4;
}
-\f
-/*
- * Decode an Operand of an instruction.
- *
- * This function formats and writes an operand of an instruction to
- * info based on the operand specification. When the `first' flag is
- * set this is the first operand of an instruction. Undefined operand
- * types cause a <dis error> message.
- *
- * Parameters:
- * disassemble_info where the operand may be printed
- * OPSPEC *opptr pointer to an operand specification
- * UINT inst instruction from which operand is extracted
- * UINT pc pc of instruction; used for pc-relative disp.
- * int first flag which if nonzero indicates the first
- * operand of an instruction
- *
- * The operand specified is extracted from the instruction and is
- * written to buf in the format specified. The operand is preceded by
- * a comma if it is not the first operand of an instruction and it is
- * not a register indirect form. Registers are preceded by 'r' and
- * hex values by '0x'.
- */
+
+/* Decode an Operand of an instruction.
+
+ This function formats and writes an operand of an instruction to
+ info based on the operand specification. When the `first' flag is
+ set this is the first operand of an instruction. Undefined operand
+ types cause a <dis error> message.
+
+ Parameters:
+ disassemble_info where the operand may be printed
+ OPSPEC *opptr pointer to an operand specification
+ UINT inst instruction from which operand is extracted
+ UINT pc pc of instruction; used for pc-relative disp.
+ int first flag which if nonzero indicates the first
+ operand of an instruction
+
+ The operand specified is extracted from the instruction and is
+ written to buf in the format specified. The operand is preceded by
+ a comma if it is not the first operand of an instruction and it is
+ not a register indirect form. Registers are preceded by 'r' and
+ hex values by '0x'. */
static void
-printop (info, opptr, inst, pc, first)
- struct disassemble_info *info;
- const OPSPEC *opptr;
- unsigned long inst;
- bfd_vma pc;
- int first;
+printop (struct disassemble_info *info,
+ const OPSPEC *opptr,
+ unsigned long inst,
+ bfd_vma pc,
+ int first)
{
int extracted_field;
char *cond_mask_sym;
default:
/* xgettext:c-format */
- (*info->fprintf_func) (info->stream, _("# <dis error: %08x>"), inst);
+ (*info->fprintf_func) (info->stream, _("# <dis error: %08lx>"), inst);
}
}
-/*
- * Initialize the disassembler instruction table.
- *
- * Initialize the hash table and instruction table for the
- * disassembler. This should be called once before the first call to
- * disasm().
- */
+/* Disassemble the instruction in `instruction'.
+ `pc' should be the address of this instruction, it will be used to
+ print the target address if this is a relative jump or call the
+ disassembled instruction is written to `info'.
+
+ The function returns the length of this instruction in bytes. */
-static void
-init_disasm ()
+static int
+m88kdis (bfd_vma pc,
+ unsigned long instruction,
+ struct disassemble_info *info)
{
- unsigned int hashvalue, hashsize;
- struct HASHTAB *hashentries;
- unsigned int i;
+ static int ihashtab_initialized = 0;
+ unsigned int opcode;
+ const HASHTAB *entry_ptr;
+ int opmask;
+ unsigned int in_class;
- hashsize = sizeof (instructions) / sizeof (INSTAB);
+ if (! ihashtab_initialized)
+ {
+ init_disasm ();
+ ihashtab_initialized = 1;
+ }
- hashentries = (struct HASHTAB *) xmalloc (hashsize * sizeof (struct HASHTAB));
+ /* Create the appropriate mask to isolate the opcode. */
+ opmask = DEFMASK;
+ in_class = instruction & DEFMASK;
+ if ((in_class >= SFU0) && (in_class <= SFU7))
+ {
+ if (instruction < SFU1)
+ opmask = CTRLMASK;
+ else
+ opmask = SFUMASK;
+ }
+ else if (in_class == RRR)
+ opmask = RRRMASK;
+ else if (in_class == RRI10)
+ opmask = RRI10MASK;
- for (i = 0; i < HASHVAL; i++)
- hashtable[i] = NULL;
+ /* Isolate the opcode. */
+ opcode = instruction & opmask;
- for (i = 0; i < hashsize; i++)
+ /* Search the hash table with the isolated opcode. */
+ for (entry_ptr = hashtable[opcode % HASHVAL];
+ (entry_ptr != NULL) && (entry_ptr->instr->opcode != opcode);
+ entry_ptr = entry_ptr->next)
+ ;
+
+ if (entry_ptr == NULL)
+ (*info->fprintf_func) (info->stream, "word\t%08lx", instruction);
+ else
{
- hashvalue = (instructions[i].opcode) % HASHVAL;
- hashentries[i].instr = &instructions[i];
- hashentries[i].next = hashtable[hashvalue];
- hashtable[hashvalue] = &hashentries[i];
+ (*info->fprintf_func) (info->stream, "%s", entry_ptr->instr->mnemonic);
+ printop (info, &(entry_ptr->instr->op1), instruction, pc, 1);
+ printop (info, &(entry_ptr->instr->op2), instruction, pc, 0);
+ printop (info, &(entry_ptr->instr->op3), instruction, pc, 0);
}
+
+ return 4;
+}
+\f
+/* Disassemble an M88000 instruction at `memaddr'. */
+
+int
+print_insn_m88k (bfd_vma memaddr, struct disassemble_info *info)
+{
+ bfd_byte buffer[4];
+ int status;
+
+ /* Instruction addresses may have low two bits set. Clear them. */
+ memaddr &=~ (bfd_vma) 3;
+
+ status = (*info->read_memory_func) (memaddr, buffer, 4, info);
+ if (status != 0)
+ {
+ (*info->memory_error_func) (status, memaddr, info);
+ return -1;
+ }
+
+ return m88kdis (memaddr, bfd_getb32 (buffer), info);
}
-