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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-7.1/] [opcodes/] [or32-dis.c] - Diff between revs 673 and 816

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

Rev 673 Rev 816
/* Instruction printing code for the OpenRISC 1000
/* Instruction printing code for the OpenRISC 1000
   Copyright (C) 2002, 2005, 2007 Free Software Foundation, Inc.
   Copyright (C) 2002, 2005, 2007 Free Software Foundation, Inc.
   Contributed by Damjan Lampret <lampret@opencores.org>.
   Contributed by Damjan Lampret <lampret@opencores.org>.
   Modified from a29k port.
   Modified from a29k port.
 
 
   This file is part of the GNU opcodes library.
   This file is part of the GNU opcodes library.
 
 
   This library is free software; you can redistribute it and/or modify
   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
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3, or (at your option)
   the Free Software Foundation; either version 3, or (at your option)
   any later version.
   any later version.
 
 
   It is distributed in the hope that it will be useful, but WITHOUT
   It is distributed in the hope that it will be useful, but WITHOUT
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
   License for more details.
   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., 51 Franklin Street - Fifth Floor, Boston,
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
   MA 02110-1301, USA.  */
   MA 02110-1301, USA.  */
 
 
#define DEBUG 0
#define DEBUG 0
 
 
#include "dis-asm.h"
#include "dis-asm.h"
#include "opcode/or32.h"
#include "opcode/or32.h"
#include "safe-ctype.h"
#include "safe-ctype.h"
#include <string.h>
#include <string.h>
#include <stdlib.h>
#include <stdlib.h>
 
 
#define EXTEND29(x) ((x) & 0x10000000UL ? ((x) | ~0x0fffffffUL) : ((x)))
#define EXTEND29(x) ((x) & 0x10000000UL ? ((x) | ~0x0fffffffUL) : ((x)))
 
 
/* Now find the four bytes of INSN_CH and put them in *INSN.  */
/* Now find the four bytes of INSN_CH and put them in *INSN.  */
 
 
static void
static void
find_bytes_big (unsigned char *insn_ch, unsigned long *insn)
find_bytes_big (unsigned char *insn_ch, unsigned long *insn)
{
{
  *insn =
  *insn =
    ((unsigned long) insn_ch[0] << 24) +
    ((unsigned long) insn_ch[0] << 24) +
    ((unsigned long) insn_ch[1] << 16) +
    ((unsigned long) insn_ch[1] << 16) +
    ((unsigned long) insn_ch[2] << 8) +
    ((unsigned long) insn_ch[2] << 8) +
    ((unsigned long) insn_ch[3]);
    ((unsigned long) insn_ch[3]);
#if DEBUG
#if DEBUG
  printf ("find_bytes_big3: %x\n", *insn);
  printf ("find_bytes_big3: %x\n", *insn);
#endif
#endif
}
}
 
 
static void
static void
find_bytes_little (unsigned char *insn_ch, unsigned long *insn)
find_bytes_little (unsigned char *insn_ch, unsigned long *insn)
{
{
  *insn =
  *insn =
    ((unsigned long) insn_ch[3] << 24) +
    ((unsigned long) insn_ch[3] << 24) +
    ((unsigned long) insn_ch[2] << 16) +
    ((unsigned long) insn_ch[2] << 16) +
    ((unsigned long) insn_ch[1] << 8) +
    ((unsigned long) insn_ch[1] << 8) +
    ((unsigned long) insn_ch[0]);
    ((unsigned long) insn_ch[0]);
}
}
 
 
typedef void (*find_byte_func_type) (unsigned char *, unsigned long *);
typedef void (*find_byte_func_type) (unsigned char *, unsigned long *);
 
 
static unsigned long
static unsigned long
or32_extract (char param_ch, char *enc_initial, unsigned long insn)
or32_extract (char param_ch, char *enc_initial, unsigned long insn)
{
{
  char *enc;
  char *enc;
  unsigned long ret = 0;
  unsigned long ret = 0;
  int opc_pos = 0;
  int opc_pos = 0;
  int param_pos = 0;
  int param_pos = 0;
 
 
  for (enc = enc_initial; *enc != '\0'; enc++)
  for (enc = enc_initial; *enc != '\0'; enc++)
    if (*enc == param_ch)
    if (*enc == param_ch)
      {
      {
        if (enc - 2 >= enc_initial && (*(enc - 2) == '0') && (*(enc - 1) == 'x'))
        if (enc - 2 >= enc_initial && (*(enc - 2) == '0') && (*(enc - 1) == 'x'))
          continue;
          continue;
        else
        else
          param_pos++;
          param_pos++;
      }
      }
 
 
#if DEBUG
#if DEBUG
  printf ("or32_extract: %c %x ", param_ch, param_pos);
  printf ("or32_extract: %c %x ", param_ch, param_pos);
#endif
#endif
  opc_pos = 32;
  opc_pos = 32;
 
 
  for (enc = enc_initial; *enc != '\0'; )
  for (enc = enc_initial; *enc != '\0'; )
    if ((*enc == '0') && (*(enc + 1) == 'x'))
    if ((*enc == '0') && (*(enc + 1) == 'x'))
      {
      {
        opc_pos -= 4;
        opc_pos -= 4;
 
 
        if ((param_ch == '0') || (param_ch == '1'))
        if ((param_ch == '0') || (param_ch == '1'))
          {
          {
            unsigned long tmp = strtoul (enc, NULL, 16);
            unsigned long tmp = strtoul (enc, NULL, 16);
#if DEBUG
#if DEBUG
            printf (" enc=%s, tmp=%x ", enc, tmp);
            printf (" enc=%s, tmp=%x ", enc, tmp);
#endif
#endif
            if (param_ch == '0')
            if (param_ch == '0')
              tmp = 15 - tmp;
              tmp = 15 - tmp;
            ret |= tmp << opc_pos;
            ret |= tmp << opc_pos;
          }
          }
        enc += 3;
        enc += 3;
      }
      }
    else if ((*enc == '0') || (*enc == '1'))
    else if ((*enc == '0') || (*enc == '1'))
      {
      {
        opc_pos--;
        opc_pos--;
        if (param_ch == *enc)
        if (param_ch == *enc)
          ret |= 1UL << opc_pos;
          ret |= 1UL << opc_pos;
        enc++;
        enc++;
      }
      }
    else if (*enc == param_ch)
    else if (*enc == param_ch)
      {
      {
        opc_pos--;
        opc_pos--;
        param_pos--;
        param_pos--;
#if DEBUG
#if DEBUG
        printf ("\n  ret=%x opc_pos=%x, param_pos=%x\n", ret, opc_pos, param_pos);
        printf ("\n  ret=%x opc_pos=%x, param_pos=%x\n", ret, opc_pos, param_pos);
#endif
#endif
        ret += ((insn >> opc_pos) & 0x1) << param_pos;
        ret += ((insn >> opc_pos) & 0x1) << param_pos;
 
 
        if (!param_pos
        if (!param_pos
            && letter_signed (param_ch)
            && letter_signed (param_ch)
            && ret >> (letter_range (param_ch) - 1))
            && ret >> (letter_range (param_ch) - 1))
          {
          {
#if DEBUG
#if DEBUG
            printf ("\n  ret=%x opc_pos=%x, param_pos=%x\n",
            printf ("\n  ret=%x opc_pos=%x, param_pos=%x\n",
                    ret, opc_pos, param_pos);
                    ret, opc_pos, param_pos);
#endif
#endif
            ret |= -1L << letter_range(param_ch);
            ret |= -1L << letter_range(param_ch);
#if DEBUG
#if DEBUG
            printf ("\n  after conversion to signed: ret=%x\n", ret);
            printf ("\n  after conversion to signed: ret=%x\n", ret);
#endif
#endif
          }
          }
        enc++;
        enc++;
      }
      }
    else if (ISALPHA (*enc))
    else if (ISALPHA (*enc))
      {
      {
        opc_pos--;
        opc_pos--;
        enc++;
        enc++;
      }
      }
    else if (*enc == '-')
    else if (*enc == '-')
      {
      {
        opc_pos--;
        opc_pos--;
        enc++;
        enc++;
      }
      }
    else
    else
      enc++;
      enc++;
 
 
#if DEBUG
#if DEBUG
  printf ("ret=%x\n", ret);
  printf ("ret=%x\n", ret);
#endif
#endif
  return ret;
  return ret;
}
}
 
 
static int
static int
or32_opcode_match (unsigned long insn, char *encoding)
or32_opcode_match (unsigned long insn, char *encoding)
{
{
  unsigned long ones, zeros;
  unsigned long ones, zeros;
 
 
#if DEBUG
#if DEBUG
  printf ("or32_opcode_match: %.8lx\n", insn);
  printf ("or32_opcode_match: %.8lx\n", insn);
#endif    
#endif    
  ones  = or32_extract ('1', encoding, insn);
  ones  = or32_extract ('1', encoding, insn);
  zeros = or32_extract ('0', encoding, insn);
  zeros = or32_extract ('0', encoding, insn);
 
 
#if DEBUG
#if DEBUG
  printf ("ones: %x \n", ones);
  printf ("ones: %x \n", ones);
  printf ("zeros: %x \n", zeros);
  printf ("zeros: %x \n", zeros);
#endif
#endif
  if ((insn & ones) != ones)
  if ((insn & ones) != ones)
    {
    {
#if DEBUG
#if DEBUG
      printf ("ret1\n");
      printf ("ret1\n");
#endif
#endif
      return 0;
      return 0;
    }
    }
 
 
  if ((~insn & zeros) != zeros)
  if ((~insn & zeros) != zeros)
    {
    {
#if DEBUG
#if DEBUG
      printf ("ret2\n");
      printf ("ret2\n");
#endif
#endif
      return 0;
      return 0;
    }
    }
 
 
#if DEBUG
#if DEBUG
  printf ("ret3\n");
  printf ("ret3\n");
#endif
#endif
  return 1;
  return 1;
}
}
 
 
/* Print register to INFO->STREAM. Used only by print_insn.  */
/* Print register to INFO->STREAM. Used only by print_insn.  */
 
 
static void
static void
or32_print_register (char param_ch,
or32_print_register (char param_ch,
                     char *encoding,
                     char *encoding,
                     unsigned long insn,
                     unsigned long insn,
                     struct disassemble_info *info)
                     struct disassemble_info *info)
{
{
  int regnum = or32_extract (param_ch, encoding, insn);
  int regnum = or32_extract (param_ch, encoding, insn);
 
 
#if DEBUG
#if DEBUG
  printf ("or32_print_register: %c, %s, %x\n", param_ch, encoding, insn);
  printf ("or32_print_register: %c, %s, %x\n", param_ch, encoding, insn);
#endif  
#endif  
  if (param_ch == 'A')
  if (param_ch == 'A')
    (*info->fprintf_func) (info->stream, "r%d", regnum);
    (*info->fprintf_func) (info->stream, "r%d", regnum);
  else if (param_ch == 'B')
  else if (param_ch == 'B')
    (*info->fprintf_func) (info->stream, "r%d", regnum);
    (*info->fprintf_func) (info->stream, "r%d", regnum);
  else if (param_ch == 'D')
  else if (param_ch == 'D')
    (*info->fprintf_func) (info->stream, "r%d", regnum);
    (*info->fprintf_func) (info->stream, "r%d", regnum);
  else if (regnum < 16)
  else if (regnum < 16)
    (*info->fprintf_func) (info->stream, "r%d", regnum);
    (*info->fprintf_func) (info->stream, "r%d", regnum);
  else if (regnum < 32)
  else if (regnum < 32)
    (*info->fprintf_func) (info->stream, "r%d", regnum-16);
    (*info->fprintf_func) (info->stream, "r%d", regnum-16);
  else
  else
    (*info->fprintf_func) (info->stream, "X%d", regnum);
    (*info->fprintf_func) (info->stream, "X%d", regnum);
}
}
 
 
/* Print immediate to INFO->STREAM. Used only by print_insn.  */
/* Print immediate to INFO->STREAM. Used only by print_insn.  */
 
 
static void
static void
or32_print_immediate (char param_ch,
or32_print_immediate (char param_ch,
                      char *encoding,
                      char *encoding,
                      unsigned long insn,
                      unsigned long insn,
                      struct disassemble_info *info)
                      struct disassemble_info *info)
{
{
  int imm = or32_extract(param_ch, encoding, insn);
  int imm = or32_extract(param_ch, encoding, insn);
 
 
  if (letter_signed(param_ch))
  if (letter_signed(param_ch))
    (*info->fprintf_func) (info->stream, "0x%x", imm);
    (*info->fprintf_func) (info->stream, "0x%x", imm);
/*    (*info->fprintf_func) (info->stream, "%d", imm); */
/*    (*info->fprintf_func) (info->stream, "%d", imm); */
  else
  else
    (*info->fprintf_func) (info->stream, "0x%x", imm);
    (*info->fprintf_func) (info->stream, "0x%x", imm);
}
}
 
 
/* Print one instruction from MEMADDR on INFO->STREAM.
/* Print one instruction from MEMADDR on INFO->STREAM.
   Return the size of the instruction (always 4 on or32).  */
   Return the size of the instruction (always 4 on or32).  */
 
 
static int
static int
print_insn (bfd_vma memaddr, struct disassemble_info *info)
print_insn (bfd_vma memaddr, struct disassemble_info *info)
{
{
  /* The raw instruction.  */
  /* The raw instruction.  */
  unsigned char insn_ch[4];
  unsigned char insn_ch[4];
  /* Address. Will be sign extened 27-bit.  */
  /* Address. Will be sign extened 27-bit.  */
  unsigned long addr;
  unsigned long addr;
  /* The four bytes of the instruction.  */
  /* The four bytes of the instruction.  */
  unsigned long insn;
  unsigned long insn;
  find_byte_func_type find_byte_func = (find_byte_func_type) info->private_data;
  find_byte_func_type find_byte_func = (find_byte_func_type) info->private_data;
  struct or32_opcode const * opcode;
  struct or32_opcode const * opcode;
 
 
  {
  {
    int status =
    int status =
      (*info->read_memory_func) (memaddr, (bfd_byte *) &insn_ch[0], 4, info);
      (*info->read_memory_func) (memaddr, (bfd_byte *) &insn_ch[0], 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;
      }
      }
  }
  }
 
 
  (*find_byte_func) (&insn_ch[0], &insn);
  (*find_byte_func) (&insn_ch[0], &insn);
 
 
  for (opcode = &or32_opcodes[0];
  for (opcode = &or32_opcodes[0];
       opcode < &or32_opcodes[or32_num_opcodes];
       opcode < &or32_opcodes[or32_num_opcodes];
       ++opcode)
       ++opcode)
    {
    {
      if (or32_opcode_match (insn, opcode->encoding))
      if (or32_opcode_match (insn, opcode->encoding))
        {
        {
          char *s;
          char *s;
 
 
          (*info->fprintf_func) (info->stream, "%s ", opcode->name);
          (*info->fprintf_func) (info->stream, "%s ", opcode->name);
 
 
          for (s = opcode->args; *s != '\0'; ++s)
          for (s = opcode->args; *s != '\0'; ++s)
            {
            {
              switch (*s)
              switch (*s)
                {
                {
                case '\0':
                case '\0':
                  return 4;
                  return 4;
 
 
                case 'r':
                case 'r':
                  or32_print_register (*++s, opcode->encoding, insn, info);
                  or32_print_register (*++s, opcode->encoding, insn, info);
                  break;
                  break;
 
 
                case 'X':
                case 'X':
                  addr = or32_extract ('X', opcode->encoding, insn) << 2;
                  addr = or32_extract ('X', opcode->encoding, insn) << 2;
 
 
                  /* Calulate the correct address.  XXX is this really correct ??  */
                  /* Calulate the correct address.  XXX is this really correct ??  */
                  addr = memaddr + EXTEND29 (addr);
                  addr = memaddr + EXTEND29 (addr);
 
 
                  (*info->print_address_func)
                  (*info->print_address_func)
                    (addr, info);
                    (addr, info);
                  break;
                  break;
 
 
                default:
                default:
                  if (strchr (opcode->encoding, *s))
                  if (strchr (opcode->encoding, *s))
                    or32_print_immediate (*s, opcode->encoding, insn, info);
                    or32_print_immediate (*s, opcode->encoding, insn, info);
                  else
                  else
                    (*info->fprintf_func) (info->stream, "%c", *s);
                    (*info->fprintf_func) (info->stream, "%c", *s);
                }
                }
            }
            }
 
 
          return 4;
          return 4;
        }
        }
    }
    }
 
 
  /* This used to be %8x for binutils.  */
  /* This used to be %8x for binutils.  */
  (*info->fprintf_func)
  (*info->fprintf_func)
    (info->stream, ".word 0x%08lx", insn);
    (info->stream, ".word 0x%08lx", insn);
  return 4;
  return 4;
}
}
 
 
/* Disassemble a big-endian or32 instruction.  */
/* Disassemble a big-endian or32 instruction.  */
 
 
int
int
print_insn_big_or32 (bfd_vma memaddr, struct disassemble_info *info)
print_insn_big_or32 (bfd_vma memaddr, struct disassemble_info *info)
{
{
  info->private_data = find_bytes_big;
  info->private_data = find_bytes_big;
 
 
  return print_insn (memaddr, info);
  return print_insn (memaddr, info);
}
}
 
 
/* Disassemble a little-endian or32 instruction.  */
/* Disassemble a little-endian or32 instruction.  */
 
 
int
int
print_insn_little_or32 (bfd_vma memaddr, struct disassemble_info *info)
print_insn_little_or32 (bfd_vma memaddr, struct disassemble_info *info)
{
{
  info->private_data = find_bytes_little;
  info->private_data = find_bytes_little;
  return print_insn (memaddr, info);
  return print_insn (memaddr, info);
}
}
 
 

powered by: WebSVN 2.1.0

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