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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [ns32k-tdep.c] - Diff between revs 105 and 1765

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

Rev 105 Rev 1765
/* Print NS 32000 instructions for GDB, the GNU debugger.
/* Print NS 32000 instructions for GDB, the GNU debugger.
   Copyright 1986, 1988, 1991, 1992, 1994, 1995
   Copyright 1986, 1988, 1991, 1992, 1994, 1995
   Free Software Foundation, Inc.
   Free Software Foundation, Inc.
 
 
   This file is part of GDB.
   This file is part of GDB.
 
 
   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,
   Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  */
   Boston, MA 02111-1307, USA.  */
 
 
#include "defs.h"
#include "defs.h"
 
 
void
void
_initialize_ns32k_tdep ()
_initialize_ns32k_tdep ()
{
{
  tm_print_insn = print_insn_ns32k;
  tm_print_insn = print_insn_ns32k;
}
}
 
 
/* Advance PC across any function entry prologue instructions
/* Advance PC across any function entry prologue instructions
   to reach some "real" code.  */
   to reach some "real" code.  */
 
 
CORE_ADDR
CORE_ADDR
merlin_skip_prologue (pc)
merlin_skip_prologue (pc)
     CORE_ADDR pc;
     CORE_ADDR pc;
{
{
  register int op = read_memory_integer (pc, 1);
  register int op = read_memory_integer (pc, 1);
  if (op == 0x82)
  if (op == 0x82)
    {
    {
      op = read_memory_integer (pc + 2, 1);
      op = read_memory_integer (pc + 2, 1);
      if ((op & 0x80) == 0)
      if ((op & 0x80) == 0)
        pc += 3;
        pc += 3;
      else if ((op & 0xc0) == 0x80)
      else if ((op & 0xc0) == 0x80)
        pc += 4;
        pc += 4;
      else
      else
        pc += 6;
        pc += 6;
    }
    }
  return pc;
  return pc;
}
}
 
 
CORE_ADDR
CORE_ADDR
umax_skip_prologue (pc)
umax_skip_prologue (pc)
     CORE_ADDR pc;
     CORE_ADDR pc;
{
{
  register unsigned char op = read_memory_integer (pc, 1);
  register unsigned char op = read_memory_integer (pc, 1);
  if (op == 0x82)
  if (op == 0x82)
    {
    {
      op = read_memory_integer (pc + 2, 1);
      op = read_memory_integer (pc + 2, 1);
      if ((op & 0x80) == 0)
      if ((op & 0x80) == 0)
        pc += 3;
        pc += 3;
      else if ((op & 0xc0) == 0x80)
      else if ((op & 0xc0) == 0x80)
        pc += 4;
        pc += 4;
      else
      else
        pc += 6;
        pc += 6;
    }
    }
  return pc;
  return pc;
}
}
 
 
/* Return number of args passed to a frame.
/* Return number of args passed to a frame.
   Can return -1, meaning no way to tell.  */
   Can return -1, meaning no way to tell.  */
 
 
int
int
merlin_frame_num_args (fi)
merlin_frame_num_args (fi)
     struct frame_info *fi;
     struct frame_info *fi;
{
{
  int numargs;
  int numargs;
  CORE_ADDR pc;
  CORE_ADDR pc;
  int insn;
  int insn;
  int addr_mode;
  int addr_mode;
  int width;
  int width;
 
 
  pc = FRAME_SAVED_PC (fi);
  pc = FRAME_SAVED_PC (fi);
  insn = read_memory_integer (pc, 2);
  insn = read_memory_integer (pc, 2);
  addr_mode = (insn >> 11) & 0x1f;
  addr_mode = (insn >> 11) & 0x1f;
  insn = insn & 0x7ff;
  insn = insn & 0x7ff;
  if ((insn & 0x7fc) == 0x57c
  if ((insn & 0x7fc) == 0x57c
      && addr_mode == 0x14)     /* immediate */
      && addr_mode == 0x14)     /* immediate */
    {
    {
      if (insn == 0x57c)        /* adjspb */
      if (insn == 0x57c)        /* adjspb */
        width = 1;
        width = 1;
      else if (insn == 0x57d)   /* adjspw */
      else if (insn == 0x57d)   /* adjspw */
        width = 2;
        width = 2;
      else if (insn == 0x57f)   /* adjspd */
      else if (insn == 0x57f)   /* adjspd */
        width = 4;
        width = 4;
      numargs = read_memory_integer (pc + 2, width);
      numargs = read_memory_integer (pc + 2, width);
      if (width > 1)
      if (width > 1)
        flip_bytes (&numargs, width);
        flip_bytes (&numargs, width);
      numargs = -sign_extend (numargs, width * 8) / 4;
      numargs = -sign_extend (numargs, width * 8) / 4;
    }
    }
  else
  else
    numargs = -1;
    numargs = -1;
  return numargs;
  return numargs;
}
}
 
 
 
 
/* Return number of args passed to a frame.
/* Return number of args passed to a frame.
   Can return -1, meaning no way to tell.
   Can return -1, meaning no way to tell.
   Encore's C compiler often reuses same area on stack for args,
   Encore's C compiler often reuses same area on stack for args,
   so this will often not work properly.  If the arg names
   so this will often not work properly.  If the arg names
   are known, it's likely most of them will be printed. */
   are known, it's likely most of them will be printed. */
int
int
umax_frame_num_args (fi)
umax_frame_num_args (fi)
     struct frame_info *fi;
     struct frame_info *fi;
{
{
  int numargs;
  int numargs;
  CORE_ADDR pc;
  CORE_ADDR pc;
  CORE_ADDR enter_addr;
  CORE_ADDR enter_addr;
  unsigned int insn;
  unsigned int insn;
  unsigned int addr_mode;
  unsigned int addr_mode;
  int width;
  int width;
 
 
  numargs = -1;
  numargs = -1;
  enter_addr = ns32k_get_enter_addr ((fi)->pc);
  enter_addr = ns32k_get_enter_addr ((fi)->pc);
  if (enter_addr > 0)
  if (enter_addr > 0)
    {
    {
      pc = ((enter_addr == 1)
      pc = ((enter_addr == 1)
            ? SAVED_PC_AFTER_CALL (fi)
            ? SAVED_PC_AFTER_CALL (fi)
            : FRAME_SAVED_PC (fi));
            : FRAME_SAVED_PC (fi));
      insn = read_memory_integer (pc, 2);
      insn = read_memory_integer (pc, 2);
      addr_mode = (insn >> 11) & 0x1f;
      addr_mode = (insn >> 11) & 0x1f;
      insn = insn & 0x7ff;
      insn = insn & 0x7ff;
      if ((insn & 0x7fc) == 0x57c
      if ((insn & 0x7fc) == 0x57c
          && addr_mode == 0x14) /* immediate */
          && addr_mode == 0x14) /* immediate */
        {
        {
          if (insn == 0x57c)    /* adjspb */
          if (insn == 0x57c)    /* adjspb */
            width = 1;
            width = 1;
          else if (insn == 0x57d)       /* adjspw */
          else if (insn == 0x57d)       /* adjspw */
            width = 2;
            width = 2;
          else if (insn == 0x57f)       /* adjspd */
          else if (insn == 0x57f)       /* adjspd */
            width = 4;
            width = 4;
          numargs = read_memory_integer (pc + 2, width);
          numargs = read_memory_integer (pc + 2, width);
          if (width > 1)
          if (width > 1)
            flip_bytes (&numargs, width);
            flip_bytes (&numargs, width);
          numargs = -sign_extend (numargs, width * 8) / 4;
          numargs = -sign_extend (numargs, width * 8) / 4;
        }
        }
    }
    }
  return numargs;
  return numargs;
}
}
 
 
 
 
sign_extend (value, bits)
sign_extend (value, bits)
{
{
  value = value & ((1 << bits) - 1);
  value = value & ((1 << bits) - 1);
  return (value & (1 << (bits - 1))
  return (value & (1 << (bits - 1))
          ? value | (~((1 << bits) - 1))
          ? value | (~((1 << bits) - 1))
          : value);
          : value);
}
}
 
 
void
void
flip_bytes (ptr, count)
flip_bytes (ptr, count)
     char *ptr;
     char *ptr;
     int count;
     int count;
{
{
  char tmp;
  char tmp;
 
 
  while (count > 0)
  while (count > 0)
    {
    {
      tmp = *ptr;
      tmp = *ptr;
      ptr[0] = ptr[count - 1];
      ptr[0] = ptr[count - 1];
      ptr[count - 1] = tmp;
      ptr[count - 1] = tmp;
      ptr++;
      ptr++;
      count -= 2;
      count -= 2;
    }
    }
}
}
 
 
/* Return the number of locals in the current frame given a pc
/* Return the number of locals in the current frame given a pc
   pointing to the enter instruction.  This is used in the macro
   pointing to the enter instruction.  This is used in the macro
   FRAME_FIND_SAVED_REGS.  */
   FRAME_FIND_SAVED_REGS.  */
 
 
int
int
ns32k_localcount (enter_pc)
ns32k_localcount (enter_pc)
     CORE_ADDR enter_pc;
     CORE_ADDR enter_pc;
{
{
  unsigned char localtype;
  unsigned char localtype;
  int localcount;
  int localcount;
 
 
  localtype = read_memory_integer (enter_pc + 2, 1);
  localtype = read_memory_integer (enter_pc + 2, 1);
  if ((localtype & 0x80) == 0)
  if ((localtype & 0x80) == 0)
    localcount = localtype;
    localcount = localtype;
  else if ((localtype & 0xc0) == 0x80)
  else if ((localtype & 0xc0) == 0x80)
    localcount = (((localtype & 0x3f) << 8)
    localcount = (((localtype & 0x3f) << 8)
                  | (read_memory_integer (enter_pc + 3, 1) & 0xff));
                  | (read_memory_integer (enter_pc + 3, 1) & 0xff));
  else
  else
    localcount = (((localtype & 0x3f) << 24)
    localcount = (((localtype & 0x3f) << 24)
                  | ((read_memory_integer (enter_pc + 3, 1) & 0xff) << 16)
                  | ((read_memory_integer (enter_pc + 3, 1) & 0xff) << 16)
                  | ((read_memory_integer (enter_pc + 4, 1) & 0xff) << 8)
                  | ((read_memory_integer (enter_pc + 4, 1) & 0xff) << 8)
                  | (read_memory_integer (enter_pc + 5, 1) & 0xff));
                  | (read_memory_integer (enter_pc + 5, 1) & 0xff));
  return localcount;
  return localcount;
}
}
 
 
 
 
/* Nonzero if instruction at PC is a return instruction.  */
/* Nonzero if instruction at PC is a return instruction.  */
 
 
static int
static int
ns32k_about_to_return (pc)
ns32k_about_to_return (pc)
     CORE_ADDR pc;
     CORE_ADDR pc;
{
{
  return (read_memory_integer (pc, 1) == 0x12);
  return (read_memory_integer (pc, 1) == 0x12);
}
}
 
 
 
 
/*
/*
 * Get the address of the enter opcode for the function
 * Get the address of the enter opcode for the function
 * containing PC, if there is an enter for the function,
 * containing PC, if there is an enter for the function,
 * and if the pc is between the enter and exit.
 * and if the pc is between the enter and exit.
 * Returns positive address if pc is between enter/exit,
 * Returns positive address if pc is between enter/exit,
 * 1 if pc before enter or after exit, 0 otherwise.
 * 1 if pc before enter or after exit, 0 otherwise.
 */
 */
 
 
CORE_ADDR
CORE_ADDR
ns32k_get_enter_addr (pc)
ns32k_get_enter_addr (pc)
     CORE_ADDR pc;
     CORE_ADDR pc;
{
{
  CORE_ADDR enter_addr;
  CORE_ADDR enter_addr;
  unsigned char op;
  unsigned char op;
 
 
  if (pc == 0)
  if (pc == 0)
    return 0;
    return 0;
 
 
  if (ns32k_about_to_return (pc))
  if (ns32k_about_to_return (pc))
    return 1;                   /* after exit */
    return 1;                   /* after exit */
 
 
  enter_addr = get_pc_function_start (pc);
  enter_addr = get_pc_function_start (pc);
 
 
  if (pc == enter_addr)
  if (pc == enter_addr)
    return 1;                   /* before enter */
    return 1;                   /* before enter */
 
 
  op = read_memory_integer (enter_addr, 1);
  op = read_memory_integer (enter_addr, 1);
 
 
  if (op != 0x82)
  if (op != 0x82)
    return 0;                    /* function has no enter/exit */
    return 0;                    /* function has no enter/exit */
 
 
  return enter_addr;            /* pc is between enter and exit */
  return enter_addr;            /* pc is between enter and exit */
}
}
 
 

powered by: WebSVN 2.1.0

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