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

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [gdb-5.0/] [opcodes/] [i370-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
 
 
/* i370-dis.c -- Disassemble Instruction 370 (ESA/390) instructions
/* i370-dis.c -- Disassemble Instruction 370 (ESA/390) instructions
   Copyright 1994, 2000 Free Software Foundation, Inc.
   Copyright 1994, 2000 Free Software Foundation, Inc.
   PowerPC version written by Ian Lance Taylor, Cygnus Support
   PowerPC version written by Ian Lance Taylor, Cygnus Support
   Rewritten for i370 ESA/390 support by Linas Vepstas <linas@linas.org>
   Rewritten for i370 ESA/390 support by Linas Vepstas <linas@linas.org>
 
 
This file is part of GDB, GAS, and the GNU binutils.
This file is part of GDB, GAS, and the GNU binutils.
 
 
GDB, GAS, and the GNU binutils are free software; you can redistribute
GDB, GAS, and the GNU binutils are free software; you can redistribute
them and/or modify them under the terms of the GNU General Public
them and/or modify them under the terms of the GNU General Public
License as published by the Free Software Foundation; either version
License as published by the Free Software Foundation; either version
2, or (at your option) any later version.
2, or (at your option) any later version.
 
 
GDB, GAS, and the GNU binutils are distributed in the hope that they
GDB, GAS, and the GNU binutils are distributed in the hope that they
will be useful, but WITHOUT ANY WARRANTY; without even the implied
will be useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
the GNU General Public License for more details.
the 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 file; see the file COPYING.  If not, write to the Free
along with this file; see the file COPYING.  If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 
#include <stdio.h>
#include <stdio.h>
#include "ansidecl.h"
#include "ansidecl.h"
#include "sysdep.h"
#include "sysdep.h"
#include "dis-asm.h"
#include "dis-asm.h"
#include "opcode/i370.h"
#include "opcode/i370.h"
 
 
/* This file provides several disassembler functions, all of which use
/* This file provides several disassembler functions, all of which use
   the disassembler interface defined in dis-asm.h.
   the disassembler interface defined in dis-asm.h.
*/
*/
 
 
int
int
print_insn_i370 (memaddr, info)
print_insn_i370 (memaddr, info)
     bfd_vma memaddr;
     bfd_vma memaddr;
     struct disassemble_info *info;
     struct disassemble_info *info;
{
{
  bfd_byte buffer[8];
  bfd_byte buffer[8];
  int status;
  int status;
  i370_insn_t insn;
  i370_insn_t insn;
  const struct i370_opcode *opcode;
  const struct i370_opcode *opcode;
  const struct i370_opcode *opcode_end;
  const struct i370_opcode *opcode_end;
 
 
  status = (*info->read_memory_func) (memaddr, buffer, 6, info);
  status = (*info->read_memory_func) (memaddr, buffer, 6, 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;
    }
    }
 
 
  /* Cast the bytes into the insn (in a host-endian indep way) */
  /* Cast the bytes into the insn (in a host-endian indep way) */
  insn.i[0] = (buffer[0] << 24) & 0xff000000;
  insn.i[0] = (buffer[0] << 24) & 0xff000000;
  insn.i[0] |= (buffer[1] << 16) & 0xff0000;
  insn.i[0] |= (buffer[1] << 16) & 0xff0000;
  insn.i[0] |= (buffer[2] << 8) & 0xff00;
  insn.i[0] |= (buffer[2] << 8) & 0xff00;
  insn.i[0] |= buffer[3]  & 0xff;
  insn.i[0] |= buffer[3]  & 0xff;
  insn.i[1] = (buffer[4] << 24) & 0xff000000;
  insn.i[1] = (buffer[4] << 24) & 0xff000000;
  insn.i[1] |= (buffer[5] << 16) & 0xff0000;
  insn.i[1] |= (buffer[5] << 16) & 0xff0000;
 
 
  /* Find the first match in the opcode table.  We could speed this up
  /* Find the first match in the opcode table.  We could speed this up
     a bit by doing a binary search on the major opcode.  */
     a bit by doing a binary search on the major opcode.  */
  opcode_end = i370_opcodes + i370_num_opcodes;
  opcode_end = i370_opcodes + i370_num_opcodes;
  for (opcode = i370_opcodes; opcode < opcode_end; opcode++)
  for (opcode = i370_opcodes; opcode < opcode_end; opcode++)
    {
    {
      const unsigned char *opindex;
      const unsigned char *opindex;
      const struct i370_operand *operand;
      const struct i370_operand *operand;
      i370_insn_t masked;
      i370_insn_t masked;
      int invalid;
      int invalid;
 
 
      /* Mask off operands, and look for a match ... */
      /* Mask off operands, and look for a match ... */
      masked = insn;
      masked = insn;
      if (2 == opcode->len)
      if (2 == opcode->len)
        {
        {
          masked.i[0] >>= 16;
          masked.i[0] >>= 16;
          masked.i[0] &= 0xffff;
          masked.i[0] &= 0xffff;
        }
        }
      masked.i[0] &= opcode->mask.i[0];
      masked.i[0] &= opcode->mask.i[0];
      if (masked.i[0] != opcode->opcode.i[0]) continue;
      if (masked.i[0] != opcode->opcode.i[0]) continue;
 
 
      if (6 == opcode->len)
      if (6 == opcode->len)
        {
        {
          masked.i[1] &= opcode->mask.i[1];
          masked.i[1] &= opcode->mask.i[1];
          if (masked.i[1] != opcode->opcode.i[1]) continue;
          if (masked.i[1] != opcode->opcode.i[1]) continue;
        }
        }
 
 
      /* Found a match.  adjust a tad */
      /* Found a match.  adjust a tad */
      if (2 == opcode->len)
      if (2 == opcode->len)
        {
        {
          insn.i[0] >>= 16;
          insn.i[0] >>= 16;
          insn.i[0] &= 0xffff;
          insn.i[0] &= 0xffff;
        }
        }
 
 
      /* Make two passes over the operands.  First see if any of them
      /* Make two passes over the operands.  First see if any of them
         have extraction functions, and, if they do, make sure the
         have extraction functions, and, if they do, make sure the
         instruction is valid.  */
         instruction is valid.  */
      invalid = 0;
      invalid = 0;
      for (opindex = opcode->operands; *opindex != 0; opindex++)
      for (opindex = opcode->operands; *opindex != 0; opindex++)
        {
        {
          operand = i370_operands + *opindex;
          operand = i370_operands + *opindex;
          if (operand->extract)
          if (operand->extract)
            (*operand->extract) (insn, &invalid);
            (*operand->extract) (insn, &invalid);
        }
        }
      if (invalid) continue;
      if (invalid) continue;
 
 
      /* The instruction is valid.  */
      /* The instruction is valid.  */
      (*info->fprintf_func) (info->stream, "%s", opcode->name);
      (*info->fprintf_func) (info->stream, "%s", opcode->name);
      if (opcode->operands[0] != 0)
      if (opcode->operands[0] != 0)
        (*info->fprintf_func) (info->stream, "\t");
        (*info->fprintf_func) (info->stream, "\t");
 
 
      /* Now extract and print the operands.  */
      /* Now extract and print the operands.  */
      for (opindex = opcode->operands; *opindex != 0; opindex++)
      for (opindex = opcode->operands; *opindex != 0; opindex++)
        {
        {
          long value;
          long value;
 
 
          operand = i370_operands + *opindex;
          operand = i370_operands + *opindex;
 
 
          /* Extract the value from the instruction.  */
          /* Extract the value from the instruction.  */
          if (operand->extract)
          if (operand->extract)
            value = (*operand->extract) (insn, (int *) NULL);
            value = (*operand->extract) (insn, (int *) NULL);
          else
          else
            {
            {
              value = (insn.i[0] >> operand->shift) & ((1 << operand->bits) - 1);
              value = (insn.i[0] >> operand->shift) & ((1 << operand->bits) - 1);
            }
            }
 
 
          /* Print the operand as directed by the flags.  */
          /* Print the operand as directed by the flags.  */
          if ((operand->flags & I370_OPERAND_OPTIONAL) != 0)
          if ((operand->flags & I370_OPERAND_OPTIONAL) != 0)
            {
            {
              if (value)
              if (value)
                (*info->fprintf_func) (info->stream, "(r%ld)", value);
                (*info->fprintf_func) (info->stream, "(r%ld)", value);
            }
            }
          else if ((operand->flags & I370_OPERAND_SBASE) != 0)
          else if ((operand->flags & I370_OPERAND_SBASE) != 0)
            {
            {
              (*info->fprintf_func) (info->stream, "(r%ld)", value);
              (*info->fprintf_func) (info->stream, "(r%ld)", value);
            }
            }
          else if ((operand->flags & I370_OPERAND_INDEX) != 0)
          else if ((operand->flags & I370_OPERAND_INDEX) != 0)
            {
            {
              if (value)
              if (value)
                (*info->fprintf_func) (info->stream, "(r%ld,", value);
                (*info->fprintf_func) (info->stream, "(r%ld,", value);
              else
              else
                (*info->fprintf_func) (info->stream, "(,");
                (*info->fprintf_func) (info->stream, "(,");
            }
            }
          else if ((operand->flags & I370_OPERAND_LENGTH) != 0)
          else if ((operand->flags & I370_OPERAND_LENGTH) != 0)
            {
            {
              (*info->fprintf_func) (info->stream, "(%ld,", value);
              (*info->fprintf_func) (info->stream, "(%ld,", value);
            }
            }
          else if ((operand->flags & I370_OPERAND_BASE) != 0)
          else if ((operand->flags & I370_OPERAND_BASE) != 0)
            (*info->fprintf_func) (info->stream, "r%ld)", value);
            (*info->fprintf_func) (info->stream, "r%ld)", value);
          else if ((operand->flags & I370_OPERAND_GPR) != 0)
          else if ((operand->flags & I370_OPERAND_GPR) != 0)
            (*info->fprintf_func) (info->stream, "r%ld,", value);
            (*info->fprintf_func) (info->stream, "r%ld,", value);
          else if ((operand->flags & I370_OPERAND_FPR) != 0)
          else if ((operand->flags & I370_OPERAND_FPR) != 0)
            (*info->fprintf_func) (info->stream, "f%ld,", value);
            (*info->fprintf_func) (info->stream, "f%ld,", value);
          else if ((operand->flags & I370_OPERAND_RELATIVE) != 0)
          else if ((operand->flags & I370_OPERAND_RELATIVE) != 0)
            (*info->fprintf_func) (info->stream, "%ld", value);
            (*info->fprintf_func) (info->stream, "%ld", value);
          else
          else
            (*info->fprintf_func) (info->stream, " %ld, ", value);
            (*info->fprintf_func) (info->stream, " %ld, ", value);
 
 
        }
        }
 
 
      return opcode->len;
      return opcode->len;
 
 
    }
    }
 
 
 
 
  /* We could not find a match.  */
  /* We could not find a match.  */
  (*info->fprintf_func) (info->stream, ".short 0x%02x%02x", buffer[0], buffer[1]);
  (*info->fprintf_func) (info->stream, ".short 0x%02x%02x", buffer[0], buffer[1]);
 
 
  return 2;
  return 2;
}
}
 
 

powered by: WebSVN 2.1.0

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