OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [gdb-5.0/] [opcodes/] [m88k-dis.c] - Diff between revs 579 and 1765

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 579 Rev 1765
/* Print instructions for the Motorola 88000, for GDB and GNU Binutils.
/* Print instructions for the Motorola 88000, for GDB and GNU Binutils.
   Copyright (c) 1986, 1987, 1988, 1989, 1990, 1991, 1993, 1998
   Copyright (c) 1986, 1987, 1988, 1989, 1990, 1991, 1993, 1998
   Free Software Foundation, Inc.
   Free Software Foundation, Inc.
   Contributed by Data General Corporation, November 1989.
   Contributed by Data General Corporation, November 1989.
   Partially derived from an earlier printcmd.c.
   Partially derived from an earlier printcmd.c.
 
 
This file is part of GDB and the GNU Binutils.
This file is part of GDB and the GNU Binutils.
 
 
This program is free software; you can redistribute it and/or modify
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
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
(at your option) any later version.
 
 
This program is distributed in the hope that it will be useful,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
GNU General Public License for more details.
 
 
You should have received a copy of the GNU General Public License
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 
#include "dis-asm.h"
#include "dis-asm.h"
#include "opcode/m88k.h"
#include "opcode/m88k.h"
#include "opintl.h"
#include "opintl.h"
 
 
INSTAB  *hashtable[HASHVAL] = {0};
INSTAB  *hashtable[HASHVAL] = {0};
 
 
static int
static int
m88kdis PARAMS ((bfd_vma, unsigned long, struct disassemble_info *));
m88kdis PARAMS ((bfd_vma, unsigned long, struct disassemble_info *));
 
 
static void
static void
printop PARAMS ((struct disassemble_info *, OPSPEC *,
printop PARAMS ((struct disassemble_info *, OPSPEC *,
                 unsigned long, bfd_vma, int));
                 unsigned long, bfd_vma, int));
 
 
static void
static void
init_disasm PARAMS ((void));
init_disasm PARAMS ((void));
 
 
static void
static void
install PARAMS ((INSTAB *instptr));
install PARAMS ((INSTAB *instptr));
 
 
/*
/*
*               Disassemble an M88000 Instruction
*               Disassemble an M88000 Instruction
*
*
*
*
*       This module decodes the instruction at memaddr.
*       This module decodes the instruction at memaddr.
*
*
*                       Revision History
*                       Revision History
*
*
*       Revision 1.0    11/08/85        Creation date by Motorola
*       Revision 1.0    11/08/85        Creation date by Motorola
*                       05/11/89        R. Trawick adapted to GDB interface.
*                       05/11/89        R. Trawick adapted to GDB interface.
*                       07/12/93        Ian Lance Taylor updated to
*                       07/12/93        Ian Lance Taylor updated to
*                                       binutils interface.
*                                       binutils interface.
*/
*/
 
 
int
int
print_insn_m88k (memaddr, info)
print_insn_m88k (memaddr, info)
     bfd_vma memaddr;
     bfd_vma memaddr;
     struct disassemble_info *info;
     struct disassemble_info *info;
{
{
  bfd_byte buffer[4];
  bfd_byte buffer[4];
  int status;
  int status;
 
 
  /* Instruction addresses may have low two bits set. Clear them.       */
  /* Instruction addresses may have low two bits set. Clear them.       */
  memaddr &=~ (bfd_vma) 3;
  memaddr &=~ (bfd_vma) 3;
 
 
  status = (*info->read_memory_func) (memaddr, buffer, 4, info);
  status = (*info->read_memory_func) (memaddr, buffer, 4, info);
  if (status != 0)
  if (status != 0)
    {
    {
      (*info->memory_error_func) (status, memaddr, info);
      (*info->memory_error_func) (status, memaddr, info);
      return -1;
      return -1;
    }
    }
 
 
  return m88kdis (memaddr, bfd_getb32 (buffer), info);
  return m88kdis (memaddr, bfd_getb32 (buffer), info);
}
}
 
 
/*
/*
 * disassemble the instruction in 'instruction'.
 * disassemble the instruction in 'instruction'.
 * 'pc' should be the address of this instruction, it will
 * '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
 *   be used to print the target address if this is a relative jump or call
 * the disassembled instruction is written to 'info'.
 * the disassembled instruction is written to 'info'.
 * The function returns the length of this instruction in bytes.
 * The function returns the length of this instruction in bytes.
 */
 */
 
 
static int
static int
m88kdis (pc, instruction, info)
m88kdis (pc, instruction, info)
     bfd_vma pc;
     bfd_vma pc;
     unsigned long instruction;
     unsigned long instruction;
     struct disassemble_info *info;
     struct disassemble_info *info;
{
{
  static int ihashtab_initialized = 0;
  static int ihashtab_initialized = 0;
  unsigned int opcode;
  unsigned int opcode;
  INSTAB *entry_ptr;
  INSTAB *entry_ptr;
  int opmask;
  int opmask;
  unsigned int class;
  unsigned int class;
 
 
  if (! ihashtab_initialized)
  if (! ihashtab_initialized)
    init_disasm ();
    init_disasm ();
 
 
  /* create the appropriate mask to isolate the opcode */
  /* create the appropriate mask to isolate the opcode */
  opmask = DEFMASK;
  opmask = DEFMASK;
  class = instruction & DEFMASK;
  class = instruction & DEFMASK;
  if ((class >= SFU0) && (class <= SFU7))
  if ((class >= SFU0) && (class <= SFU7))
    {
    {
      if (instruction < SFU1)
      if (instruction < SFU1)
        opmask = CTRLMASK;
        opmask = CTRLMASK;
      else
      else
        opmask = SFUMASK;
        opmask = SFUMASK;
    }
    }
  else if (class == RRR)
  else if (class == RRR)
    opmask = RRRMASK;
    opmask = RRRMASK;
  else if (class == RRI10)
  else if (class == RRI10)
    opmask = RRI10MASK;
    opmask = RRI10MASK;
 
 
  /* isolate the opcode */
  /* isolate the opcode */
  opcode = instruction & opmask;
  opcode = instruction & opmask;
 
 
  /* search the hash table with the isolated opcode */
  /* search the hash table with the isolated opcode */
  for (entry_ptr = hashtable[opcode % HASHVAL];
  for (entry_ptr = hashtable[opcode % HASHVAL];
       (entry_ptr != NULL) && (entry_ptr->opcode != opcode);
       (entry_ptr != NULL) && (entry_ptr->opcode != opcode);
       entry_ptr = entry_ptr->next)
       entry_ptr = entry_ptr->next)
    ;
    ;
 
 
  if (entry_ptr == NULL)
  if (entry_ptr == NULL)
    (*info->fprintf_func) (info->stream, "word\t%08x", instruction);
    (*info->fprintf_func) (info->stream, "word\t%08x", instruction);
  else
  else
    {
    {
      (*info->fprintf_func) (info->stream, "%s", entry_ptr->mnemonic);
      (*info->fprintf_func) (info->stream, "%s", entry_ptr->mnemonic);
      printop (info, &(entry_ptr->op1), instruction, pc, 1);
      printop (info, &(entry_ptr->op1), instruction, pc, 1);
      printop (info, &(entry_ptr->op2), instruction, pc, 0);
      printop (info, &(entry_ptr->op2), instruction, pc, 0);
      printop (info, &(entry_ptr->op3), instruction, pc, 0);
      printop (info, &(entry_ptr->op3), instruction, pc, 0);
    }
    }
 
 
  return 4;
  return 4;
}
}


/*
/*
*                      Decode an Operand of an Instruction
*                      Decode an Operand of an Instruction
*
*
*                       Functional Description
*                       Functional Description
*
*
*       This module formats and writes an operand of an instruction to info
*       This module formats and writes an operand of an instruction to info
*       based on the operand specification.  When the first flag is set this
*       based on the operand specification.  When the first flag is set this
*       is the first operand of an instruction.  Undefined operand types
*       is the first operand of an instruction.  Undefined operand types
*       cause a <dis error> message.
*       cause a <dis error> message.
*
*
*                       Parameters
*                       Parameters
*       disassemble_info        where the operand may be printed
*       disassemble_info        where the operand may be printed
*       OPSPEC  *opptr          Pointer to an operand specification
*       OPSPEC  *opptr          Pointer to an operand specification
*       UINT    inst            Instruction from which operand is extracted
*       UINT    inst            Instruction from which operand is extracted
*       UINT    pc              PC of instruction; used for pc-relative disp.
*       UINT    pc              PC of instruction; used for pc-relative disp.
*       int     first           Flag which if nonzero indicates the first
*       int     first           Flag which if nonzero indicates the first
*                               operand of an instruction
*                               operand of an instruction
*
*
*                       Output
*                       Output
*
*
*       The operand specified is extracted from the instruction and is
*       The operand specified is extracted from the instruction and is
*       written to buf in the format specified. The operand is preceded
*       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
*       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
*       is not a register indirect form.  Registers are preceded by 'r' and
*       hex values by '0x'.
*       hex values by '0x'.
*
*
*                       Revision History
*                       Revision History
*
*
*       Revision 1.0    11/08/85        Creation date
*       Revision 1.0    11/08/85        Creation date
*/
*/
 
 
static void
static void
printop (info, opptr, inst, pc, first)
printop (info, opptr, inst, pc, first)
     struct disassemble_info *info;
     struct disassemble_info *info;
     OPSPEC *opptr;
     OPSPEC *opptr;
     unsigned long inst;
     unsigned long inst;
     bfd_vma pc;
     bfd_vma pc;
     int first;
     int first;
{
{
  int extracted_field;
  int extracted_field;
  char *cond_mask_sym;
  char *cond_mask_sym;
 
 
  if (opptr->width == 0)
  if (opptr->width == 0)
    return;
    return;
 
 
  if (! first)
  if (! first)
    {
    {
      switch (opptr->type)
      switch (opptr->type)
        {
        {
        case REGSC:
        case REGSC:
        case CONT:
        case CONT:
          break;
          break;
        default:
        default:
          (*info->fprintf_func) (info->stream, ",");
          (*info->fprintf_func) (info->stream, ",");
          break;
          break;
        }
        }
    }
    }
 
 
  switch (opptr->type)
  switch (opptr->type)
    {
    {
    case CRREG:
    case CRREG:
      (*info->fprintf_func) (info->stream, "cr%d",
      (*info->fprintf_func) (info->stream, "cr%d",
                             UEXT (inst, opptr->offset, opptr->width));
                             UEXT (inst, opptr->offset, opptr->width));
      break;
      break;
 
 
    case FCRREG:
    case FCRREG:
      (*info->fprintf_func) (info->stream, "fcr%d",
      (*info->fprintf_func) (info->stream, "fcr%d",
                             UEXT (inst, opptr->offset, opptr->width));
                             UEXT (inst, opptr->offset, opptr->width));
      break;
      break;
 
 
    case REGSC:
    case REGSC:
      (*info->fprintf_func) (info->stream, "[r%d]",
      (*info->fprintf_func) (info->stream, "[r%d]",
                             UEXT (inst, opptr->offset, opptr->width));
                             UEXT (inst, opptr->offset, opptr->width));
      break;
      break;
 
 
    case REG:
    case REG:
      (*info->fprintf_func) (info->stream, "r%d",
      (*info->fprintf_func) (info->stream, "r%d",
                             UEXT (inst, opptr->offset, opptr->width));
                             UEXT (inst, opptr->offset, opptr->width));
      break;
      break;
 
 
    case XREG:
    case XREG:
      (*info->fprintf_func) (info->stream, "x%d",
      (*info->fprintf_func) (info->stream, "x%d",
                             UEXT (inst, opptr->offset, opptr->width));
                             UEXT (inst, opptr->offset, opptr->width));
      break;
      break;
 
 
    case HEX:
    case HEX:
      extracted_field = UEXT (inst, opptr->offset, opptr->width);
      extracted_field = UEXT (inst, opptr->offset, opptr->width);
      if (extracted_field == 0)
      if (extracted_field == 0)
        (*info->fprintf_func) (info->stream, "0");
        (*info->fprintf_func) (info->stream, "0");
      else
      else
        (*info->fprintf_func) (info->stream, "0x%02x", extracted_field);
        (*info->fprintf_func) (info->stream, "0x%02x", extracted_field);
      break;
      break;
 
 
    case DEC:
    case DEC:
      extracted_field = UEXT (inst, opptr->offset, opptr->width);
      extracted_field = UEXT (inst, opptr->offset, opptr->width);
      (*info->fprintf_func) (info->stream, "%d", extracted_field);
      (*info->fprintf_func) (info->stream, "%d", extracted_field);
      break;
      break;
 
 
    case CONDMASK:
    case CONDMASK:
      extracted_field = UEXT (inst, opptr->offset, opptr->width);
      extracted_field = UEXT (inst, opptr->offset, opptr->width);
      switch (extracted_field & 0x0f)
      switch (extracted_field & 0x0f)
        {
        {
        case 0x1: cond_mask_sym = "gt0"; break;
        case 0x1: cond_mask_sym = "gt0"; break;
        case 0x2: cond_mask_sym = "eq0"; break;
        case 0x2: cond_mask_sym = "eq0"; break;
        case 0x3: cond_mask_sym = "ge0"; break;
        case 0x3: cond_mask_sym = "ge0"; break;
        case 0xc: cond_mask_sym = "lt0"; break;
        case 0xc: cond_mask_sym = "lt0"; break;
        case 0xd: cond_mask_sym = "ne0"; break;
        case 0xd: cond_mask_sym = "ne0"; break;
        case 0xe: cond_mask_sym = "le0"; break;
        case 0xe: cond_mask_sym = "le0"; break;
        default: cond_mask_sym = NULL; break;
        default: cond_mask_sym = NULL; break;
        }
        }
      if (cond_mask_sym != NULL)
      if (cond_mask_sym != NULL)
        (*info->fprintf_func) (info->stream, "%s", cond_mask_sym);
        (*info->fprintf_func) (info->stream, "%s", cond_mask_sym);
      else
      else
        (*info->fprintf_func) (info->stream, "%x", extracted_field);
        (*info->fprintf_func) (info->stream, "%x", extracted_field);
      break;
      break;
 
 
    case PCREL:
    case PCREL:
      (*info->print_address_func)
      (*info->print_address_func)
        (pc + (4 * (SEXT (inst, opptr->offset, opptr->width))),
        (pc + (4 * (SEXT (inst, opptr->offset, opptr->width))),
         info);
         info);
      break;
      break;
 
 
    case CONT:
    case CONT:
      (*info->fprintf_func) (info->stream, "%d,r%d",
      (*info->fprintf_func) (info->stream, "%d,r%d",
                             UEXT (inst, opptr->offset, 5),
                             UEXT (inst, opptr->offset, 5),
                             UEXT (inst, (opptr->offset) + 5, 5));
                             UEXT (inst, (opptr->offset) + 5, 5));
      break;
      break;
 
 
    case BF:
    case BF:
      (*info->fprintf_func) (info->stream, "%d<%d>",
      (*info->fprintf_func) (info->stream, "%d<%d>",
                              UEXT (inst, (opptr->offset) + 5, 5),
                              UEXT (inst, (opptr->offset) + 5, 5),
                              UEXT (inst, opptr->offset, 5));
                              UEXT (inst, opptr->offset, 5));
      break;
      break;
 
 
    default:
    default:
      /* xgettext:c-format */
      /* xgettext:c-format */
      (*info->fprintf_func) (info->stream, _("# <dis error: %08x>"), inst);
      (*info->fprintf_func) (info->stream, _("# <dis error: %08x>"), inst);
    }
    }
}
}
 
 
/*
/*
*                 Initialize the Disassembler Instruction Table
*                 Initialize the Disassembler Instruction Table
*
*
*       Initialize the hash table and instruction table for the disassembler.
*       Initialize the hash table and instruction table for the disassembler.
*       This should be called once before the first call to disasm().
*       This should be called once before the first call to disasm().
*
*
*                       Parameters
*                       Parameters
*
*
*                       Output
*                       Output
*
*
*       If the debug option is selected, certain statistics about the hashing
*       If the debug option is selected, certain statistics about the hashing
*       distribution are written to stdout.
*       distribution are written to stdout.
*
*
*                       Revision History
*                       Revision History
*
*
*       Revision 1.0    11/08/85        Creation date
*       Revision 1.0    11/08/85        Creation date
*/
*/
 
 
static void
static void
init_disasm ()
init_disasm ()
{
{
   int i, size;
   int i, size;
 
 
   for (i = 0; i < HASHVAL; i++)
   for (i = 0; i < HASHVAL; i++)
     hashtable[i] = NULL;
     hashtable[i] = NULL;
 
 
   size = sizeof (instructions) / sizeof (INSTAB);
   size = sizeof (instructions) / sizeof (INSTAB);
   for (i = 0; i < size; i++)
   for (i = 0; i < size; i++)
     install (&instructions[i]);
     install (&instructions[i]);
}
}
 
 
/*
/*
*       Insert an instruction into the disassembler table by hashing the
*       Insert an instruction into the disassembler table by hashing the
*       opcode and inserting it into the linked list for that hash value.
*       opcode and inserting it into the linked list for that hash value.
*
*
*                       Parameters
*                       Parameters
*
*
*       INSTAB *instptr         Pointer to the entry in the instruction table
*       INSTAB *instptr         Pointer to the entry in the instruction table
*                               to be installed
*                               to be installed
*
*
*       Revision 1.0    11/08/85        Creation date
*       Revision 1.0    11/08/85        Creation date
*                       05/11/89        R. TRAWICK ADAPTED FROM MOTOROLA
*                       05/11/89        R. TRAWICK ADAPTED FROM MOTOROLA
*/
*/
 
 
static void
static void
install (instptr)
install (instptr)
     INSTAB *instptr;
     INSTAB *instptr;
{
{
  unsigned int i;
  unsigned int i;
 
 
  i = (instptr->opcode) % HASHVAL;
  i = (instptr->opcode) % HASHVAL;
  instptr->next = hashtable[i];
  instptr->next = hashtable[i];
  hashtable[i] = instptr;
  hashtable[i] = instptr;
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.