This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Merging OC gdb with official gdb


> >> If you find that you do appear to need to define certain macro's then
> >> post a question to check what is going on.
> >
> > Ok, how should we handle following macros:
> > (I looked at the current code, but they look like they are not yet in
> > gdbarch)
> >
> > #define GDB_MULTI_ARCH 1
> > #define CANNOT_STEP_BREAKPOINT
>
> This will need to be multi-arched (or deleted).
What do you mean deleted? This will change functionality right?
how can I do multi-arched.

> > #define TARGET_HAS_HARDWARE_WATCHPOINTS
Is this one automatic?

> > #define HAVE_NONSTEPPABLE_WATCHPOINT
What about this?

> > #define TARGET_CAN_USE_HARDWARE_WATCHPOINT(bp_type, cnt, ot) \
> >   or1k_can_use_hardware_watchpoint(bp_type, cnt)
>
> As part of the change:
>
> 2002-08-01  Grace Sainsbury  <graces@redhat.com>
>
>          * target.h: Add to_insert_hw_breakpoint, to_remove_hw_breakpoint,
>          to_insert_watchpoint, to_remove_watchpoint,
>          to_stopped_by_watchpoint, to_stopped_data_address,
>          to_region_size_ok_for_hw_watchpoint, to_can_use_hw_breakpoint to
>          target vecctor. Define their corresponding macros so they call
>          them.
>
>          * target.c: Add default and debug versions of for
>          to_insert_hw_breakpoint, to_remove_hw_breakpoint,
>          to_insert_watchpoint, to_remove_watchpoint,
>          to_stopped_by_watchpoint, to_stopped_data_address,
>          to_region_size_ok_for_hw_watchpoint, to_can_use_hw_breakpoint.
>
> Much of the above was moved into the target vector.  The file
> remote-or1k.c would need to add entries for them in its target vector.
done.

> > #define STEP_SKIPS_DELAY_P (1)
> > #define STEP_SKIPS_DELAY(pc) (or1k_step_skips_delay (pc))
what needs to be defined instead?

> Sane as for CANNOT_STEP_BREAKPOINT, this will need to be multi-arched.
again - what need to be defined?

> The code that uses it mind:
>
>        if (STEP_SKIPS_DELAY_P
>            && breakpoint_here_p (read_pc () + 4)
>            && STEP_SKIPS_DELAY (read_pc ()))
>          oneproc = 1;
>
> is pretty bogus -- what is ``4''?
that is delay slot instruction size; I changed the const to OR1K_INSTLEN.

> The intent is to make it as easy as possible to debug for anyone that
> follows.  You can't step into, breakpoint, or call a macro (and
> suprisingly it is to often the one line macro's that contain the bugs :-( )
Ok then, I will change all the macros that have some meaningfull code inside.

> (A useful and generic feature would be a command to select the case of
> register names.  Some people, apparently, like using the shift key)
Actually parsing was not case sensitive, just names in file were written in 
hicaps.

> > or1k architecture has special address space of registers called Special
> > Purpose Registers. These include cache, tick timer, supervision
> > registers, debug registers, etc.
> > They have to be separatedfrom General Purpose Registers, also GPRs.
> > Due to large number of SPRs (several thousands), I did not include them
> > into gdb register space (except program counter PC).
>
> That's ok.  A 1000 registers is nothing!  I know of an arch with 4k (or
> was it 8k!).
it is about 8k here also.

> The problem with the above is that it assumes that there will never be
> more than one outstanding register_name() call.  That assumption is wrong.
>
> register_name() should use (for want of a better word) permenant memory,
> instead of a scratch array, when returning a register's name.
>
> Easiest might be to generate all the names once in
> _initialize_or1k_tdep().  Another would be to generate each on-demand.
Huh, I must say I don't the idea pretty much. Some of the registers have e.g.: 
read&clear or write&do_something functionality.
This also involves your expression evaluator - how many times are values 
evalueated in (and what order):
$BAR + $FOE
$BAR + $FOE * $BAR

I find it higly inconvenient to use them as SW variables...

If you still insist tell me what would be best way to include them in gdb 
registers structure. Note that they should not be cached.

> > How do I get relevant frame? Is there a target already doing what you are
> > proposing?
>
> The more up-to-date multi-arch method print_registers_info() takes the
> architecture and frame as parameters.
ok, done.

> No, I wasn't
>
> >> >   if (inv1)
> >> >     printf_filtered (" %-5s flt: <invalid float>", REGISTER_NAME
> >> > (regnum)); else
> >> >     printf_filtered (" %-5s flt:%-17.9g", REGISTER_NAME (regnum),
> >> > flt); printf_filtered (inv3 ? " dbl: <invalid double> " :
> >> > 		   " dbl: %-24.17g ", doub);
>
> (Er, but thinking about it).
>
> The ``-17.9g'' isn't going to be portable.  DOUBLEST can either be
> ``double'' or ``long double''.
>
> Does something like:
> print_floating (raw_buffer, builtin_type_ieee_single_big, gdb_stdout)
> or
> print_floating (raw_buffer, REGISTER_VIRTUAL_TYPE(i), gdb_stdout)
> do what you want?
Do I have a choice? :)

> >> This should be ``info or1k spr''.  See ppc for an example of how to do
> >> this.
> >
> > the command is already long, e.g.: info spr debug dmr1
> > since it is used a lot and it is registered only with or1k target, can we
> > make an exception;) ?
>
> A GDB may include support for more than one ISA.  By including the <cpu>
> prefix any potential conflict between similar CPU commands is avoided
> (without introducing modal commands).
We will se how the story goes with (on-demand?) registers.

> Can you summarize what the limitations were and post this, separatly, to
> gdb@.  If there is some sort of limitation, people need to understand it
> and determine if fixing it, or living with it, is best.
ok.

> > I am reposting the files. Changes to config.gdb stays the same.
>
> Lets just get or1k-tdep.c in.  I'm currently ignoring the others.
>
> How is your texinfo?
You really know how to set the questions ;)
BTW: The question I asked you week ago :)))

Marko

/* Target-dependent code for the or1k architecture, for GDB, the GNU Debugger.

   Copyright 1988-1999, Free Software Foundation, Inc.
   Contributed by Alessandro Forin(af@cs.cmu.edu at CMU
   and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin.

   This file is part of GDB.

   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 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.

   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., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  */

#include <ctype.h>
#include "demangle.h"
#include "defs.h"
#include "gdb_string.h"
#include "frame.h"
#include "inferior.h"
#include "symtab.h"
#include "value.h"
#include "gdbcmd.h"
#include "language.h"
#include "gdbcore.h"
#include "symfile.h"
#include "objfiles.h"
#include "gdbtypes.h"
#include "target.h"
#include "regcache.h"
#include "osabi.h"
#include "arch-utils.h"

#include "opcode/or32.h"

/* *INDENT-OFF* */

/* Group reg name size.  See or1k_reg_names.  */
static int or1k_group_name_sizes[OR1K_NUM_SPR_GROUPS] = {
  80,   0,   0, 6, 4, 2,
  22, 16, 1, 3, 2, 8
};

static int or1k_group_name_start[OR1K_NUM_SPR_GROUPS] = {
  0,   0,   0, 253, 254, 256,
  0, 248,  16, 16,  255, 0
};

/* Generated reg names (max valid alias index).
   See or1k_spr_reg_name.  */
static int or1k_spr_valid_aliases[OR1K_NUM_SPR_GROUPS] = {
  2047+1, 2047+1, 2047+1, 258+1, 257+1, 257+1,
  78+1, 263+1, 16+1, 18+1, 256+1, 7+1
};

/* Register names.  */
static char *or1k_reg_names[] = {

  /* group 0 - general*/
  "vr", "upr", "cpucfgr", "dmmucfgr", "immucfgr", "dccfgr", "iccfgr", "dcfgr",
  "pccfgr", "spr0_9", "spr0_10", "spr0_11", "spr0_12", "spr0_13", "spr0_14", "spr0_15",
  "npc", "sr", "ppc", "spr0_19", "spr0_20", "spr0_21", "spr0_22", "spr0_23",
  "spr0_24", "spr0_25", "spr0_26", "spr0_27", "spr0_28", "spr0_29", "spr0_30", "spr0_31", 
  "epcr0", "epcr1", "epcr2", "epcr3", "epcr4", "epcr5", "epcr6", "epcr7",
  "epcr8", "epcr9", "epcr10", "epcr11", "epcr12", "epcr13", "epcr14", "epcr15",
  "eear0","eear1", "eear2", "eear3", "eear4", "eear5", "eear6", "eear7",
  "eear8", "eear9", "eear10", "eear11", "eear12", "eear13", "eear14", "eear15",
  "esr0", "esr1", "esr2", "esr3", "esr4", "esr5", "esr6", "esr7",
  "esr8", "esr9", "esr10", "esr11", "esr12", "esr13", "esr14", "esr15",

  /* gpr+vf registers generated */ 
  /* group 1 - Data MMU - not listed, generated */
  /* group 2 - Instruction MMU - not listed, generated */

  /* group 3 - Data cache */
  "dccr", "dcbpr", "dcbfr", "dcbir", "dcbwr", "dcblr",

  /* group 4 - Instruction cache */
  "iccr", "icbpr", "icbir", "icblr",

  /* group 5 - MAC */
  "maclo", "machi",

  /* group 6 - debug */
  "dvr0", "dvr1", "dvr2", "dvr3", "dvr4", "dvr5", "dvr6", "dvr7",
  "dcr0", "dcr1", "dcr2", "dcr3", "dcr4", "dcr5", "dcr6", "dcr7",
  "dmr1", "dmr2", "dcwr0","dcwr1","dsr",  "drr",

  /* group 7 - performance counters unit */
  "pccm0", "pcmr1", "pcmr2", "pcmr3", "pcmr4", "pcmr5", "pcmr6", "pcmr7",
  "pccr0", "pccr1", "pccr2", "pccr3", "pccr4", "pccr5", "pccr6", "pccr7",
    
  /* group 8 - power management */
  "pmr",
  
  /* group 9 - PIC */
  "picmr", "picpr",
  
  /* group 10 - tick timer */
  "ttmr", "ttcr",

  /* group 11 - configuration */
  "cpucfgr", "dmmucfgr", "immucfgr", "dccfgr", "iccfgr", "spr11_5", "dcfgr", "pccfgr"
};

static char *or1k_gdb_reg_names[] = {

  /* general purpose registers */
  "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
  "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
  "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
  "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",

  /* vector/floating point registers */
  "vfa0",  "vfa1",  "vfa2",  "vfa3",  "vfa4",  "vfa5",  "vfrv ", "vfr7", 
  "vfr8",  "vfr9",  "vfr10", "vfr11", "vfr12", "vfr13", "vfr14", "vfr15",
  "vfr16", "vfr17", "vfr18", "vfr19", "vfr20", "vfr21", "vfr22", "vfr23",
  "vfr24", "vfr25", "vfr26", "vfr27", "vfr28", "vfr29", "vfr30", "vfr31",
  "pc",    "sr",    "epcr", "expc", "exear", "exsr"
};

static char *or1k_group_names[] = {
  "sys", "dmmu", "immu", "dcache", "icache", "mac", "debug", "perf",
  "power", "pic", "timer", "config"
};

/* Table of or1k signals.  */
static struct
  {
  char *name;
  char *string;
  } or1k_signals [NUM_OR1K_SIGNALS + 1] =
  {
    {"RSTE", "Reset Exception"},
    {"BUSE", "Bus Error" },
    {"DFPE", "Data Page Fault Exception"},
    {"IFPE", "Instruction Page Fault Exception"},
    {"LPINTE", "Low Priority Interrupt Exception"},
    {"AE", "Alignment Exception"},
    {"ILINSE" "Illegal Instruction" },
    {"HPINTE", "High Priority Interrupt Exception"},
    {"DME", "DTLB Miss Exception"},
    {"IME", "ITLB Miss Exception"},
    {"RE", "Range Exception"},
    {"SCE", "SCE Exception"},
    {"BRKPTE", "Breakpoint Exception"},
    {NULL, NULL}
  };

/* *INDENT-ON* */

/* List of all saved register addresses, produced by skip_prologue.  
   Relative address to sp, not used if 0.  */
static int or1k_saved_reg_addr[OR1K_NUM_REGS];

/* Converts regno to sprno.  or1k debug unit has GPRs mapped to SPRs,
   which are not compact, so we are mapping them for GDB.  */
int
or1k_regnum_to_sprnum (int regno)
{
  if (regno < MAX_GPR_REGS)
    return SPR_REG (SPR_SYSTEM_GROUP, regno + CURRENT_CID * MAX_GPR_REGS + SPR_GPR_START);

  if (regno < MAX_GPR_REGS + MAX_VF_REGS)
    return SPR_REG (SPR_SYSTEM_GROUP, regno - MAX_GPR_REGS
		   + CURRENT_CID * MAX_GPR_REGS + SPR_VFPR_START);

  switch (regno)
    {
    case PS_REGNUM:         return SR_SPRNUM;
    case PC_REGNUM:         return PC_SPRNUM;
    /*case CCR_REGNUM:        return CCR_SPRNUM (CURRENT_CID);*/
    case EPCR_REGNUM:        return EPCR_SPRNUM (CURRENT_CID);
    /*case EAR_REGNUM:        return EAR_SPRNUM (CURRENT_CID);
    case ESR_REGNUM:        return ESR_SPRNUM (CURRENT_CID);*/
    default:
      error ("Invalid register number!");
      break;
    }

  return 0;
}

/* Builds and returns register name.  */

static char tmp_name[16];
static const char *
or1k_spr_register_name (int i)
{
  int group = i >> SPR_GROUP_SIZE_BITS;
  int index = i & (SPR_GROUP_SIZE - 1);
  switch (group)
    {
      /* Names covered in or1k_reg_names.  */
    case 0:

      /* Generate upper names.  */
      if (index >= SPR_GPR_START)
	{
	  if (index < SPR_VFPR_START)
	    sprintf (tmp_name, "gpr%i", index - SPR_GPR_START);
	  else
	    sprintf (tmp_name, "vfr%i", index - SPR_VFPR_START);
	  return (char *)&tmp_name;
	}
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:
    case 8:
    case 9:
    case 10:
      {
	int group_start = 0;
	for (i = 0; i < group; i++) 
	  group_start += or1k_group_name_sizes[i];
	
	index -= or1k_group_name_start[group];
	if (index >= or1k_group_name_sizes[group])
	  {
	    sprintf (tmp_name, "spr%i_%i", group, index);
	    return (char *)&tmp_name;
	  }
	else
	  return or1k_reg_names[group_start + index];
      }

      /* Build names for DMMU group.  */
    case 1:
    case 2:
      strcpy (tmp_name, (group == 1) ? "D" : "I");
      switch (index)
	{
	case 16:
	  return strcat (tmp_name, "mmucr");
	case 17:
	  return strcat (tmp_name, "mmupr");
	case 18:
	  return strcat (tmp_name, "tlbeir");
	case 24:
	  return strcat (tmp_name, "atbmr0");
	case 25:
	  return strcat (tmp_name, "atbmr1");
	case 26:
	  return strcat (tmp_name, "atbmr2");
	case 27:
	  return strcat (tmp_name, "atbmr3");
	case 28:
	  return strcat (tmp_name, "atbtr0");
	case 29:
	  return strcat (tmp_name, "atbtr0");
	case 30:
	  return strcat (tmp_name, "atbtr0");
	case 31:
	  return strcat (tmp_name, "atbtr0");
	default:
	  if (index >= 1024) {
	    index -= 1024;
	    sprintf (tmp_name, "%stlbw%imr%i", (group == 1) ? "d" : "i",
                            index / 128, index % 128);
	    return (char *)&tmp_name;
	  }	  
	  sprintf (tmp_name, "spr%i_%i", group, index);
	  return (char *)&tmp_name;
      }
    default:
      sprintf (tmp_name, "spr%i_%i", group, index);
      return (char *)&tmp_name;
    }
}

/* Get register index in group from name.  Negative if no match.  */

static int
or1k_regno_from_name (int group, const char *name)
{
  int i;
  if (toupper (name[0]) == 'S' && toupper (name[1]) == 'P' && toupper (name[2]) == 'R')
    {
      char *ptr_c;      
      name += 3;
      i = (int) strtoul (name, &ptr_c, 10);
      if (*ptr_c != '_' || i != group)
	return -1;
      ptr_c++;
      i = (int) strtoul (name, &ptr_c, 10);
      if (*ptr_c)
	return -1;
      else return i;
    }
  for (i = or1k_group_name_start[group]; i < or1k_spr_valid_aliases[group]; i++)
    {
      const char *s;
      s = or1k_spr_register_name (SPR_REG (group, i));
      if (strcasecmp (name, s) == 0)
	return i;
    }
  return -1;
}

/* Returns gdb register name.  */

static const char *
or1k_register_name (int regno)
{
  return or1k_gdb_reg_names[regno];
}

/* Utility function to display vf regs.  */

static int
do_vf_register (struct frame_info *frame, int regnum)
{
  /* do values for FP (float) regs */
  char *raw_buffer;

  raw_buffer = (char *) alloca (OR1K_VF_REGSIZE);

  /* Get the data in raw format.  */

  if (!frame_register_read (frame, regnum, raw_buffer))
    error ("can't read register %d (%s)", regnum, REGISTER_NAME (regnum));
  
  if (OR1K_VF_REGSIZE == 4)
    print_floating (raw_buffer, builtin_type_ieee_single_big, gdb_stdout)
  else
    print_floating (raw_buffer, builtin_type_ieee_double_big, gdb_stdout)

  /* pad small registers */
  for (byte = 0; byte < (OR1K_GPR_REGSIZE - REGISTER_VIRTUAL_SIZE (regnum)); byte++)
    printf_filtered ("  ");

  /* Now print the register value in hex, endian order. */
  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
    for (byte = REGISTER_RAW_SIZE (regnum) - REGISTER_VIRTUAL_SIZE (regnum);
	 byte < REGISTER_RAW_SIZE (regnum);
	 byte++)
      printf_filtered ("%02x", (unsigned char) raw_buffer[byte]);
  else
    for (byte = REGISTER_VIRTUAL_SIZE (regnum) - 1;
	 byte >= 0;
	 byte--)
      printf_filtered ("%02x", (unsigned char) raw_buffer[byte]);
  printf_filtered ("\n");
  
  regnum++;
  return regnum;
}

/* Print a row's worth of GP (int) registers, with name labels above */

static int
do_gp_register_row (struct frame_info *frame, int regnum)
{
  /* do values for GP (int) regs */
  char raw_buffer[MAX_REGISTER_RAW_SIZE];

  /* display cols per row */
  int ncols = (OR1K_64BIT_IMPLEMENTATION ? 4 : 8);
  int col, byte;
  int start_regnum = regnum;
  int numregs = OR1K_NUM_REGS;

  /* For GP registers, we print a separate row of names above the vals */
  printf_filtered ("     ");
  for (col = 0; col < ncols && regnum < numregs; regnum++)
    {
      if (*REGISTER_NAME (regnum) == '\0')
	continue;		/* unused register */
      if (OR1K_IS_VF (regnum))
	break;			/* end the row: reached VF register */
      printf_filtered (OR1K_64BIT_IMPLEMENTATION ? "%17s" : "%9s",
		       REGISTER_NAME (regnum));
      col++;
    }
  printf_filtered ("\n      ");

  regnum = start_regnum;	/* go back to start of row */

  /* now print the values in hex, 4 or 8 to the row */
  for (col = 0; col < ncols && regnum < numregs; regnum++)
    {
      /* unused register? */
      if (*REGISTER_NAME (regnum) == '\0')
	continue;		

      /* end row: reached VF register? */
      if (OR1K_IS_VF (regnum))
	break;			

      /* OK: get the data in raw format.  */
      if (!frame_register_read (frame, regnum, raw_buffer))
	error ("can't read register %d (%s)", regnum, REGISTER_NAME (regnum));

      /* pad small registers */
      for (byte = 0; byte < (OR1K_GPR_REGSIZE - REGISTER_VIRTUAL_SIZE (regnum)); byte++)
	printf_filtered ("  ");

      /* Now print the register value in hex, endian order. */
      if (TARGET_BYTE_ORDER == BIG_ENDIAN)
	for (byte = REGISTER_RAW_SIZE (regnum) - REGISTER_VIRTUAL_SIZE (regnum);
	     byte < REGISTER_RAW_SIZE (regnum);
	     byte++)
	  printf_filtered ("%02x", (unsigned char) raw_buffer[byte]);
      else
	for (byte = REGISTER_VIRTUAL_SIZE (regnum) - 1;
	     byte >= 0;
	     byte--)
	  printf_filtered ("%02x", (unsigned char) raw_buffer[byte]);
      printf_filtered (" ");
      col++;
    }

  /* ie. if we actually printed anything... */
  if (col > 0)		    
    printf_filtered ("\n");

  return regnum;
}

/* Replacement for generic do_registers_info.  
   Print regs in pretty columns.  */

static void
print_register (struct frame_info *frame, int regnum, int all)
{
  int offset;
  char raw_buffer[MAX_REGISTER_RAW_SIZE];

  /* Get the data in raw format.  */
  if (!frame_register_read (frame, regnum, raw_buffer))
    {
      printf_filtered ("%s: [Invalid]", REGISTER_NAME (regnum));
      return;
    }

  /* If virtual format is floating, print it that way.  */
  if (OR1K_IS_VF (regnum))
    do_vf_register (frame, regnum);
  else
    {
      int byte;
      printf_filtered ("%-16s\t", REGISTER_NAME (regnum));
      
      /* pad small registers */
      for (byte = 0; byte < (OR1K_GPR_REGSIZE - REGISTER_VIRTUAL_SIZE (regnum)); byte++)
	printf_filtered ("  ");

      /* Now print the register value in hex, endian order. */
      if (TARGET_BYTE_ORDER == BIG_ENDIAN)
	for (byte = REGISTER_RAW_SIZE (regnum) - REGISTER_VIRTUAL_SIZE (regnum);
	     byte < REGISTER_RAW_SIZE (regnum);
	     byte++)
	  printf_filtered ("%02x", (unsigned char) raw_buffer[byte]);
      else
	for (byte = REGISTER_VIRTUAL_SIZE (regnum) - 1;
	     byte >= 0;
	     byte--)
	  printf_filtered ("%02x", (unsigned char) raw_buffer[byte]);
      printf_filtered (" ");
    }
}

/* DO_REGISTERS_INFO: called by "info register" command */
static void
or1k_print_registers_info (struct gdbarch *gdbarch,
                           struct ui_file *file,
                           struct frame_info *frame,
                           int regnum, int fpregs)
{
  if (fpregs && !or1k_implementation.vf_present)
    {
      warning ("VF register set not present in this implementation.");
      fpregs = 0;
    }
  if (regnum != -1)		
    {
      /* do one specified register */
      if (*(REGISTER_NAME (regnum)) == '\0')
	error ("Not a valid register for the current processor type");

      print_register (frame, regnum, 0);
      printf_filtered ("\n");
    }
  else
    /* do all (or most) registers */
    {
      regnum = 0;
      while (regnum < OR1K_NUM_REGS)
	{
	  if (OR1K_IS_VF (regnum))
	    /* true for "INFO ALL-REGISTERS" command */
	    if (fpregs)		
	      /* FP regs */
	      regnum = do_vf_register (frame, regnum);	
	    else
	      /* skip floating point regs */
	      regnum++; 	
	  else
	    /* GP (int) regs */
	    regnum = do_gp_register_row (frame, regnum);	
	}
    }
}

/* Return the string for a signal.
   Replacement for target_signal_to_string (sig).  NOT USED.  */

static const char *
or1k_signal_to_string (enum target_signal sig)
{
  if ((sig >= TARGET_SIGNAL_FIRST) && (sig <= TARGET_SIGNAL_LAST))
    return or1k_signals[sig].string;
  else
    if (sig <= TARGET_SIGNAL_LAST + NUM_OR1K_SIGNALS)
      return or1k_signals[sig - TARGET_SIGNAL_LAST].string;
    else
      return 0;
}

/* Return the name for a signal.  */

const char *
or1k_signal_to_name (enum target_signal sig)
{
  if (sig >= TARGET_SIGNAL_LAST)
    {
      if (sig <= TARGET_SIGNAL_LAST + NUM_OR1K_SIGNALS)
        return or1k_signals[sig - TARGET_SIGNAL_LAST].name;
      else

      /* I think the code which prints this will always print it along with
         the string, so no need to be verbose.  */
        return "?";
    }
  if (sig == TARGET_SIGNAL_UNKNOWN)
    return "?";
  return 0;
}

/* Given a name, return its signal.  NOT USED.  */
enum target_signal
or1k_signal_from_name (const char *name)
{
  enum target_signal sig;

  /* It's possible we also should allow "SIGCLD" as well as "SIGCHLD"
     for TARGET_SIGNAL_SIGCHLD.  SIGIOT, on the other hand, is more
     questionable; seems like by now people should call it SIGABRT
     instead.  */

  /* This ugly cast brought to you by the native VAX compiler.  */
  for (sig = TARGET_SIGNAL_FIRST;
       or1k_signal_to_name (sig) != NULL;
       sig = (enum target_signal) ((int) sig + 1))
    if (STREQ (name, or1k_signal_to_name (sig)))
      return sig;
  return TARGET_SIGNAL_UNKNOWN;
}

/* XFER a value from the big/little/left end of the register.
   Depending on the size of the value it might occupy the entire
   register or just part of it.  Make an allowance for this, aligning
   things accordingly.  */

static void
or1k_xfer_register (struct regcache *regcache, int reg_num, int length,
                    enum bfd_endian endian, bfd_byte *in, const bfd_byte *out,
                    int buf_offset)
{
  bfd_byte *reg = alloca (MAX_REGISTER_RAW_SIZE);
  int reg_offset = 0;
  /* Need to transfer the left or right part of the register, based on
     the targets byte order.  */
     switch (endian)
       {
       case BFD_ENDIAN_BIG:
         reg_offset = REGISTER_RAW_SIZE (reg_num) - length;
         break;
       case BFD_ENDIAN_LITTLE:
         reg_offset = 0;
         break;
       case BFD_ENDIAN_UNKNOWN: /* Indicates no alignment.  */
         reg_offset = 0;
         break;
       default:
         internal_error (__FILE__, __LINE__, "bad switch");
       }
  if (gdbarch_debug) printf_unfiltered ("xfer $%d, reg offset %d, buf offset %d, length %d, ",
                  reg_num, reg_offset, buf_offset, length);
  if (out != NULL) 
    {
      int i;
      if (gdbarch_debug) printf_unfiltered ("out ");
      for (i = 0; i < length; i++)
        printf_unfiltered ("%02x", out[buf_offset + i]);
    }
  if (in != NULL)
    regcache_raw_read_part (regcache, reg_num, reg_offset, length, in + buf_offset);
  if (out != NULL)
    regcache_raw_write_part (regcache, reg_num, reg_offset, length, out + buf_offset);
  if (gdbarch_debug && in != NULL)
    {
      int i;
      printf_unfiltered ("in ");
      for (i = 0; i < length; i++)
        printf_unfiltered ("%02x", in[buf_offset + i]);
    }
  if (gdbarch_debug) printf_unfiltered ("\n");
}



/* Advance PC across any function entry prologue instructions
   to reach some "real" code.

   The or1k CC defines the following
   prologue:
00000000 <_proc1>:
   0:   d7 e1 17 e4     l.sw 0xffffffe4(r1),r2
   4:   9c 41 00 00     l.addi r2,r1,0x0
   8:   9c 21 ff e8     l.addi r1,r1,0xffffffe8
   c:   d7 e2 1f f8     l.sw 0xfffffff8(r2),r3
  10:   d7 e2 27 f4     l.sw 0xfffffff4(r2),r4
  14:   84 82 ff f8     l.lwz r4,0xfffffff8(r2)
  18:   9d 24 00 00     l.addi r9,r4,0x0
  1c:   00 00 00 02     l.j 0x2
  20:   15 00 00 00     l.nop 

00000024 <_L2>:
  24:   84 41 ff fc     l.lwz r2,0xfffffffc (r1)
  28:   48 00 58 00     l.jalr r11
  2c:   9c 21 00 18     l.addi r1,r1,0x18 */

static CORE_ADDR
or1k_skip_prologue (CORE_ADDR pc)
{
  unsigned long inst;
  CORE_ADDR skip_pc;
  CORE_ADDR func_addr, func_end;
  struct symtab_and_line sal;
  int i;
  int offset = 0;
  
  for (i = 0; i < MAX_GPR_REGS; i++)
    or1k_saved_reg_addr[i] = -1;

  /* Is there a prologue?  */
  inst = or1k_fetch_instruction (pc);
  if ((inst & 0xfc1ff800) != 0xd4011000) return pc; /* l.sw I (r1),r2 */
  or1k_saved_reg_addr[2] = offset++;
  inst = or1k_fetch_instruction (pc + OR1K_INSTLEN);
  if ((inst & 0xFFFF0000) != 0x9c410000) return pc; /* l.addi r2,r1,I */
  pc += 2 * OR1K_INSTLEN;
  inst = or1k_fetch_instruction (pc);
  if ((inst & 0xFFFF0000) != 0x9c210000) return pc; /* l.addi r1,r1,I */
  pc += OR1K_INSTLEN;

  /* Skip stored registers.  */
  inst = or1k_fetch_instruction (pc);
  while ((inst & 0xfc1ff800) != 0xd4020000)  /* l.sw 0x0(r2),rx */
    {
      /* get saved reg. */
      or1k_saved_reg_addr[(inst >> 11) & 0x1f] = offset++;
      pc += OR1K_INSTLEN;
      inst = or1k_fetch_instruction (pc);
    }
  return pc;
}

/* Determines whether this function has frame.  */

int
or1k_frameless_function_invocation (struct frame_info *fi)
{
  CORE_ADDR func_start, after_prologue;
  int frameless;
  func_start = (get_pc_function_start ((fi)->pc) + FUNCTION_START_OFFSET);
  after_prologue = SKIP_PROLOGUE (func_start);

  /* If we don't skip pc, we don't have even shortest possible  prologue.  */
  frameless = (after_prologue <= func_start);
  return frameless;
}

/* Given a GDB frame, determine the address of the calling function's frame.
   This will be used to create a new GDB frame struct, and then
   INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC will be called for the new frame. */

static CORE_ADDR
or1k_frame_chain (struct frame_info *frame)
{
  CORE_ADDR fp;
  if (USE_GENERIC_DUMMY_FRAMES)
    {
      if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
	/* dummy frame same as caller's frame */
	return frame->frame;
    }

  if (inside_entry_file (frame->pc) ||
      frame->pc == entry_point_address ())
    return 0;

  if (frame->signal_handler_caller)
    fp = read_memory_integer (frame->frame, OR1K_INSTLEN);
  else if (frame->next != NULL
	   && frame->next->signal_handler_caller
	   && FRAMELESS_FUNCTION_INVOCATION (frame))
    /* A frameless function interrupted by a signal did not change the
       frame pointer.  */
    fp = FRAME_FP (frame);
  else
    {
      unsigned long func_pc = get_pc_function_start (frame->pc);
      unsigned long insn = read_memory_integer (func_pc, OR1K_INSTLEN);
      int i;
      int offset = 0;

      /* The first instruction should be the number of bytes
	 in our frame. If it isn't we're in trouble because
	 the function is without a prologue... */
      if (((insn & 0xFC000000) == 0x9C000000) &&
	 ((insn & 0x03E00000) == 0x00200000) &&
	 ((insn & 0x001F0000) == 0x00010000))
	{
	  short off = insn & 0xFFFF;

	  /* Look for the storage of the frame pointer in the
	     function prologue.. */
	  for (i = 1; i < 20; i++)
	    {
	      unsigned long insn = read_memory_integer (func_pc + OR1K_INSTLEN * i, OR1K_INSTLEN);
	  
	      /* If bits are 31 - 26 are %110101,
		 and bits 20 - 16 are %00001,
		 and bits 15 - 11 are %00010,
		 then our frame pointer lies at the offset specified
		 by bits [25-21][10-0]. */
	  
	      int code = insn >> 26;
	      int r1    = (insn & 0x001F0000) >> 16;
	      int r2    = (insn & 0x0000F800) >> 11;
	      int idx_h = (insn & 0x03E00000) >> 10;
	      int idx   = (insn & 0x000007FF) | idx_h;

	      if (code == 0x35 && r1 == 1 && r2 == 2)
		{
		  offset = off + idx;
		  break;
		}
	    }
	}

      fp = read_memory_integer (frame->frame + offset, OR1K_INSTLEN);
    }

  if (USE_GENERIC_DUMMY_FRAMES)
    {
      CORE_ADDR fpp, lr;

      lr = read_register (LR_REGNUM);
      if (lr == entry_point_address ())
	if (fp != 0 && (fpp = read_memory_integer (fp, OR1K_INSTLEN)) != 0)
	  if (PC_IN_CALL_DUMMY (lr, fpp, fpp))
	    return fpp;
    }
  
  return fp;
}

/* The code to store, into a struct frame_saved_regs,
   the addresses of the saved registers of frame described by FRAME_INFO.
   This includes special registers such as pc and fp saved in special
   ways in the stack frame.  sp is even more special:
   the address we return for it IS the sp for the next frame.  */
static void
or1k_frame_init_saved_regs (struct frame_info *fi)
{
  int i;
  CORE_ADDR frame_addr;
  CORE_ADDR func_pc = get_pc_function_start ((fi)->pc) + FUNCTION_START_OFFSET;
  int frame_size;
  int pc_found = 0;

  frame_saved_regs_zalloc (fi);
  
  /* Skip prologue sets or1k_saved_reg_addr[], we will use it later.  */
  or1k_skip_prologue (func_pc);

  frame_size = or1k_saved_reg_addr[1];
  or1k_saved_reg_addr[1] = -1;

  /* If the frame_size is less than 0, we have hit an assembly
     routine which we can't traverse beyond. Let's give up here,
     because attempting to continue will only lead to trouble. */
  if (frame_size < 0)
    {
      printf ("Found a function without a prologue at 0x%08lx\n", func_pc);
      printf ("Frame pc was at 0x%08lx\n", fi->pc);
      return;
    }

  for (i = 0; i < NUM_GPR_REGS + NUM_VF_REGS; i++)
    if (or1k_saved_reg_addr[i] >= 0)
      fi->saved_regs[i] = fi->frame - or1k_saved_reg_addr[i];

  /* We want to make sure we fill in the PC with the value of the
     r9 register from the NEXT frame, and that the value of r1 is
     the correct value of r1 for the next frame, which can be
     calculated by adding the frame_size to the frame pointer. */
  fi->saved_regs[1] = fi->frame - frame_size;

  if (fi->saved_regs[LR_REGNUM])
    fi->saved_regs[PC_REGNUM] = read_memory_integer (fi->saved_regs[LR_REGNUM], OR1K_INSTLEN);
  else
    fi->saved_regs[PC_REGNUM] = read_register (LR_REGNUM);
}

static CORE_ADDR
read_next_frame_reg (struct frame_info *fi, int regno)
{
  for (; fi; fi = fi->next)
    {
      /* We have to get the saved sp from the sigcontext
         if it is a signal handler frame.  */
      if (regno == SP_REGNUM && !fi->signal_handler_caller)
	return fi->frame;
      else
	{
	  if (fi->saved_regs == NULL)
	    or1k_frame_init_saved_regs (fi);
	  if (fi->saved_regs[regno])
	    {
	      if (regno == SP_REGNUM || regno == PC_REGNUM)
		return fi->saved_regs[regno];
	      else
		return read_memory_integer (ADDR_BITS_REMOVE (fi->saved_regs[regno]), OR1K_GPR_REGSIZE);
	    }
	}
    }
  return read_register (regno);
}

/* Return nonzero when instruction has delay slot.  */

int
is_delayed (unsigned long insn)
{
  int index;
  index = insn_decode (insn);
  return or32_opcodes[index].flags & OR32_IF_DELAY;
}

int
or1k_step_skips_delay (CORE_ADDR pc)
{
  char buf[OR1K_INSTLEN];

  if (target_read_memory (pc, buf, OR1K_INSTLEN) != 0)
    /* If error reading memory, guess that it is not a delayed branch.  */
    return 0;
  return is_delayed ((unsigned long) extract_unsigned_integer (buf, OR1K_INSTLEN));
}

/* Parses args for spr name and puts result into group and index.  */

static char *
parse_spr_params (char *args, int *group, int *index)
{
  *index = -1;
  if (args)
    {
      int i; 
      char *ptr_c;

      /* Check if group number was supplied.  */
      ptr_c = args;
      while (*ptr_c != ' ' && *ptr_c != 0)
	ptr_c++;
      *ptr_c = 0;

      *group = (int) strtoul (args, &ptr_c, 0);
      if (*ptr_c != 0)
	{
	  *group = OR1K_NUM_SPR_GROUPS;

	  /* check for group name */
	  for (i = 0; i < OR1K_NUM_SPR_GROUPS; i++)
	    if (strcasecmp (or1k_group_names[i], args) == 0)
	      {
		*group = i;
		break;
	      }

	  /* Invalid group => check all register names in all groups.  */
	  if (*group >= OR1K_NUM_SPR_GROUPS)
	    {	      
	      for (i = 0; i < OR1K_NUM_SPR_GROUPS; i++)
		{
		  int regno;
		  regno = or1k_regno_from_name (i, args);
		  if (regno >= 0)
		    {
		      *group = i;
		      *index = regno;
		      break;
		    }
		}
	    }
	}
      if (*group < 0 || *group >= OR1K_NUM_SPR_GROUPS)
	error ("Invalid group or register.\n");
      
      if (*index < 0)
	{
	  printf ("a'%s'\n", args);
	  args += strlen (args) + 1;
	  printf ("b'%s'\n", args);
	  if (*args != 0)
	    {
	      ptr_c = args;
	      while (*ptr_c != ' ' && *ptr_c != 0)
	        ptr_c++;
	      *ptr_c = 0;
	  
	      *index = (int) strtoul (args, &ptr_c, 0);
	      if (*ptr_c != 0)
	        *index = or1k_regno_from_name (*group, args);
	    }

	  if (*index < 0)
	    {
	      printf_filtered ("No register supplied. Valid registers are:\n");
	      for (i = 0; i < or1k_spr_valid_aliases[*group]; i++)
		{
		  char reg_name[16];
		  const char *gen_name = or1k_spr_register_name (SPR_REG (*group, i + or1k_group_name_start[*group]));
		  sprintf (reg_name, "SPR%i_%i", *group, i);
		  if (strcmp (reg_name, gen_name) != 0) 
		    printf_filtered ("%s\t", gen_name);
		}
	      printf_filtered ("\n");
	      return args + strlen (args) + 1;
	    }
	}
    }
  else
    {
      /* No parameters - print groups */
      int i;
      printf_filtered ("No parameter supplied. Valid groups are:\n");
      for (i = 0; i < OR1K_NUM_SPR_GROUPS; i++)
	printf_filtered ("%s\t", or1k_group_names[i]);
      printf_filtered ("\nSingle register name or register name or number after the group can be also supplied.\n");
      return args;
    }
  return args + strlen (args) + 1;
}

/* SPR register info.  */

void
info_spr_command (char *args, int from_tty)
{
  int group, index;
  parse_spr_params (args, &group, &index);
  if (index >= 0)
    {
      unsigned long value = or1k_read_spr_reg (SPR_REG (group, index));
      printf_unfiltered ("%s.%s = SPR%i_%i = %li (%lx)\n", or1k_group_names[group], 
			 or1k_spr_register_name (SPR_REG (group, index)), group, index, value, value);
    }
}

/* Set SPR register.  */

void
spr_command (char *args, int from_tty)
{
  int group, index;
  char *nargs = parse_spr_params (args, &group, &index);
  if (index >= 0)
    {
      unsigned long prev;
      unsigned long value;
      char *ptr_c;

      /* Any arguments left?  */
      if (args + strlen (args) >= nargs)
	error ("Invalid register value.");

      prev = or1k_read_spr_reg (SPR_REG (group, index));

      ptr_c = nargs;
      while (*ptr_c != ' ' && *ptr_c != 0)
	ptr_c++;
      *ptr_c = 0;
      value = strtoul (nargs, &ptr_c, 0);
      if (*ptr_c != 0)
				error ("Invalid register value.");
			or1k_write_spr_reg (SPR_REG (group, index), value);
      printf_unfiltered ("%s.%s (spr%i_%i) set to %li (%lx), was:%li (%lx)\n", or1k_group_names[group], 
			 or1k_spr_register_name (SPR_REG (group, index)), group, index,
			 value, value, prev, prev);      
    }
}

/* Calls extended command on target.  */

void
or1ksim_command (char *args, int from_tty)
{
  or1k_or1ksim_cmd (args, from_tty);
}

int print_insn_big_or32 (bfd_vma, struct disassemble_info *);
int print_insn_little_or32 (bfd_vma, struct disassemble_info *);

/* returns nonzero, if register is readonly */
static int
or1k_cannot_store_register (int regnum)
{
  return regnum == ZERO_REGNUM;
}

/* Returns the byte position in the register cache for register regnum.  */

static int
or1k_register_byte (int regnum)
{
  if (regnum < 0 || regnum >= OR1K_NUM_REGS)
    internal_error (__FILE__, __LINE__,
                    "or1k_register_byte: illegal register number %d", regnum);
  else
    return regnum * OR1K_SPR_REGSIZE;
}

/* Number of bytes of storage in the actual machine representation for
   register N.  NOTE: This indirectly defines the register size
   transfered by the GDB protocol.  If we have 64bit processor
   implementation, GPR register raw size is 8B, otherwise 4B.  */
static int
or1k_register_raw_size (int regnum)
{
 if (regnum < 0 || regnum >= OR1K_NUM_REGS)
   internal_error (__FILE__, __LINE__,
                   "or1k_register_raw_size: illegal register number %d", regnum);
   else
    return ((OR1K_IS_GPR(regnum) ? ((OR1K_64BIT_IMPLEMENTATION) ? (8) : (4))
                            : (OR1K_SPR_REGSIZE)));
}

/* Returns the default type for register N. */
static struct type *
or1k_reg_virtual_type (int regnum)
{
  if (regnum < 0 || regnum >= OR1K_NUM_REGS)
    internal_error (__FILE__, __LINE__,
                    "or1k_register_virtual_type: illegal register number %d", regnum);
  else if (OR1K_IS_GPR(regnum))
    return OR1K_64BIT_IMPLEMENTATION ? builtin_type_int64 : builtin_type_int;
  else if (OR1K_IS_VF(regnum))
    return builtin_type_ieee_single_big;
  else
    return builtin_type_uint32;
}

/* Find a register's saved value on the call stack. */

static void
or1k_get_saved_register (char *raw_buffer, int *optimized, CORE_ADDR *addrp,
                         struct frame_info *fi, int regnum, enum lval_type *lval)
{
  /* TODO: check if OK */
  generic_get_saved_register (raw_buffer, optimized, addrp, fi, regnum, lval);
}

/* Returns the previous PC immediately after a function call.
   This function is meant to bypass the regular get_saved_register
   mechanism, ie. it is meant to work even if the frame isn't complete.
   Called by step_over_function, and sometimes by get_prev_frame.  */

static CORE_ADDR
or1k_saved_pc_after_call (struct frame_info *ignore)
{
  return read_register(LR_REGNUM);
}

/* Find the caller of this frame.  We do this by seeing if LR_REGNUM
   is saved in the stack anywhere, otherwise we get it from the
   registers.  */

static CORE_ADDR
or1k_frame_saved_pc (struct frame_info *fi)
{
  CORE_ADDR saved_pc;
  
  /* We have to get the saved pc from the sigcontext
     if it is a signal handler frame.  */
  if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
    saved_pc = read_memory_integer (fi->frame, OR1K_GPR_REGSIZE);
  else
    saved_pc = read_next_frame_reg (fi, PC_REGNUM);

  return ADDR_BITS_REMOVE (saved_pc);
}

/* This is the constructor function for the frame_info struct,
   called whenever a new frame_info is created (from create_new_frame,
   and from get_prev_frame).  */

static void
or1k_init_extra_frame_info (int fromleaf, struct frame_info *fi)
{
  if (!fi->extra_info)
    {
#if 0
      fi->extra_info = (struct frame_extra_info *)
                       frame_obstack_alloc (sizeof (struct frame_extra_info));
      fi->extra_info->framesize = 0;
      fi->extra_info->frameless_p = 1;  /* Default frameless, detect framed */
#else
      fi->extra_info = NULL;
#endif

      /* By default, the fi->frame is set to the value of the FP reg by gdb.
         This may not always be right; we may be in a frameless function,
         or we may be in the prologue, before the FP has been set up.
         Unfortunately, we can't make this determination without first
         calling scan_prologue, and we can't do that unles we know the
         fi->pc.  */

      if (!fi->pc)
        {
          /* Sometimes we are called from get_prev_frame without
             the PC being set up first.  Long history, don't ask.
             Fortunately this will never happen from the outermost
             frame, so we should be able to get the saved pc from
             the next frame. */
          if (fi->next)
            fi->pc = or1k_frame_saved_pc (fi->next);
        }
      /* Take care of the saved_regs right here (non-lazy). */
      or1k_frame_init_saved_regs (fi);
  }
}

/* Setup the return address for GDB to call a function in the inferior.
   Called only in the context of a target function call from the debugger.
   Returns the value of the SP register when the operation is finished
   (which may or may not be the same as before).  */

static CORE_ADDR
or1k_push_return_address (CORE_ADDR pc, CORE_ADDR sp)
{
  /* Set the return address register to point to the entry
     point of the program, where a breakpoint lies in wait.  */
  write_register (LR_REGNUM, CALL_DUMMY_ADDRESS ());
  return sp;
}

/* Copy the function's return value into VALBUF.
   This function is called only in the context of "target function calls",
   ie. when the debugger forces a function to be called in the child, and
   when the debugger forces a function to return prematurely via the
   "return" command. */
        
static void
or1k_extract_return_value (struct type *valtype, char *regbuf, char *valbuf)
{
  CORE_ADDR return_buffer;
  int rv_regnum = (TYPE_CODE_FLT == TYPE_CODE (valtype)) ? VFRV_REGNUM : RV_REGNUM;

  if (TYPE_CODE (valtype) != TYPE_CODE_STRUCT
      && TYPE_CODE (valtype) != TYPE_CODE_UNION
      && TYPE_CODE (valtype) != TYPE_CODE_ARRAY
      && TYPE_LENGTH (valtype) <= OR1K_GPR_REGSIZE)
    {
      /* Scalar return values */
      memcpy (valbuf, &regbuf[REGISTER_BYTE (rv_regnum)], TYPE_LENGTH (valtype));
    }
  else
    {
      /* Aggregates */
      return_buffer = extract_address (regbuf + REGISTER_BYTE (rv_regnum),
                                       REGISTER_RAW_SIZE (rv_regnum));
                                       read_memory (return_buffer, valbuf, TYPE_LENGTH (valtype));
    }
}

/* Setup the function arguments for GDB to call a function in the inferior.
   Called only in the context of a target function call from the debugger.
   Returns the value of the SP register after the args are pushed.  */

static CORE_ADDR
or1k_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
                     int struct_return, CORE_ADDR struct_addr)
{
  int argreg;
  int float_argreg;
  int argnum;
  int len = 0;
  int stack_offset = 0;

  /* Initialize the integer and float register pointers.  */
  argreg = A0_REGNUM;
  float_argreg = VFA0_REGNUM;

  /* The struct_return pointer occupies the RV value register.  */
  if (struct_return)
    write_register (RV_REGNUM, struct_addr);

  /* Now load as many as possible of the first arguments into
     registers, and push the rest onto the stack.  Loop thru args
     from first to last.  */
  for (argnum = 0; argnum < nargs; argnum++)
    {
      char *val;
      char valbuf[MAX_REGISTER_RAW_SIZE];
      struct value *arg = args[argnum];
      struct type *arg_type = check_typedef (VALUE_TYPE (arg));
      int len = TYPE_LENGTH (arg_type);
      enum type_code typecode = TYPE_CODE (arg_type);

      /* The EABI passes structures that do not fit in a register by
         reference. In all other cases, pass the structure by value.  */
      if (len > OR1K_GPR_REGSIZE &&
	  (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION))
	{
	  store_address (valbuf, OR1K_GPR_REGSIZE, VALUE_ADDRESS (arg));
	  typecode = TYPE_CODE_PTR;
	  len = OR1K_GPR_REGSIZE;
	  val = valbuf;
	}
      else
	{
	  val = (char *) VALUE_CONTENTS (arg);
	  
	  if (typecode == TYPE_CODE_FLT
	      /* Doubles are not stored in regs on 32b target.  */
	      && len <= OR1K_VF_REGSIZE
	      && OR1K_VF_PRESENT)
	    {
	      if (float_argreg <= OR1K_LAST_FP_ARG_REGNUM)
		{
		  CORE_ADDR regval = extract_address (val, len);
		  write_register (float_argreg++, regval);
		}
	      else
		{
		  write_memory ((CORE_ADDR) sp, val, OR1K_VF_REGSIZE);	      
		  sp -= OR1K_STACK_ALIGN;
		}
	    }
	  else
	    {	
	      if (argreg <= OR1K_LAST_ARG_REGNUM)
		{
		  CORE_ADDR regval = extract_address (val, len);
		  write_register (argreg++, regval);
		}
	      else
		{
		  write_memory ((CORE_ADDR) sp, val, OR1K_GPR_REGSIZE);	      
		  sp -= OR1K_STACK_ALIGN;
		}
	    }
	}
    }

  /* Return adjusted stack pointer.  */
  return sp;
}

/* Discard from the stack the innermost frame, restoring all registers.  */

void
or1k_pop_frame ()
{
  register int regnum;
  struct frame_info *frame = get_current_frame ();
  CORE_ADDR new_sp = FRAME_FP (frame);

  write_register (PC_REGNUM, FRAME_SAVED_PC (frame));
  if (frame->saved_regs == NULL)
    or1k_frame_init_saved_regs (frame);
  for (regnum = 0; regnum < OR1K_NUM_REGS; regnum++)    {
      if (regnum != SP_REGNUM && regnum != PC_REGNUM
	  && frame->saved_regs[regnum] >= 0)
	write_register (regnum,
			read_memory_integer (frame->saved_regs[regnum],
					     OR1K_GPR_REGSIZE));
    }
  write_register (SP_REGNUM, new_sp);
  flush_cached_frames ();
}

static void
or1k_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
{
  /* Nothing to do -- push_arguments does all the work.  */
}

/* Copy the function return value from VALBUF into the
   proper location for a function return.
   Called only in the context of the "return" command.  */

static void
or1k_store_return_value (struct type *type, char *valbuf)
{
  if (TYPE_CODE (type) == TYPE_CODE_FLT)
    write_register_bytes (REGISTER_BYTE (VFRV_REGNUM), valbuf, TYPE_LENGTH (type));
  else
    write_register_bytes (REGISTER_BYTE (RV_REGNUM), valbuf, TYPE_LENGTH (type));
}

/* Returns the address in which a function should return a struct value.
   Used in the contexts of the "return" command, and of
   target function calls from the debugger.  */

static CORE_ADDR
or1k_extract_struct_value_address (char *regbuf)
{
/* Extract from an array regbuf containing the (raw) register state
   the address in which a function should return its structure value,
   as a CORE_ADDR (or an expression that can be used as one).  */
  return extract_address (regbuf + REGISTER_BYTE (RV_REGNUM), REGISTER_RAW_SIZE (RV_REGNUM));
}

/* Returns non-zero if the given struct type will be returned using
   a special convention, rather than the normal function return method.
   Used in the contexts of the "return" command, and of
   target function calls from the debugger.  */

static int
or1k_use_struct_convention (int gcc_p, struct type *type)
{
  return (TYPE_LENGTH (type) > OR1K_STRUCT_CONV_SIZE);
}

/* Given the address at which to insert a breakpoint (BP_ADDR),
   what will that breakpoint be?

   For or1k, we have a breakpoint instruction. Since all or1k
   instructions are 32 bits, this is all we need, regardless of
   address. K is not used.  */

static const unsigned char *
or1k_breakpoint_from_pc (CORE_ADDR * bp_addr, int *bp_size)
{ 
  static char breakpoint[] = BRK_INSTR_STRUCT;
  *bp_size = OR1K_INSTLEN;
  return breakpoint;
}

/* Aligns address to valid stack entry */

static CORE_ADDR
or1k_stack_align (CORE_ADDR addr)
{
  if (OR1K_64BIT_IMPLEMENTATION)
    return addr & ~7;
  else
    return addr & ~3;
}

static struct gdbarch *
or1k_gdbarch_init (struct gdbarch_info info,
		   struct gdbarch_list *arches)
{
  static LONGEST call_dummy_words[1] = {0};
  struct gdbarch *gdbarch;
  struct gdbarch_tdep *tdep;
  int elf_flags;
  
  /* find a candidate among the list of pre-declared architectures. */
  arches = gdbarch_list_lookup_by_info (arches, &info);
  if (arches != NULL)
    return (arches->gdbarch);

  gdbarch = gdbarch_alloc (&info, NULL);

  /* Basic register fields and methods. */
  set_gdbarch_num_regs (gdbarch, OR1K_NUM_REGS);
  set_gdbarch_num_pseudo_regs (gdbarch, 0);
  set_gdbarch_sp_regnum (gdbarch, SP_REGNUM);
  set_gdbarch_fp_regnum (gdbarch, FP_REGNUM);
  set_gdbarch_pc_regnum (gdbarch, PC_REGNUM);
  set_gdbarch_cannot_store_register (gdbarch, or1k_cannot_store_register);
  set_gdbarch_register_name (gdbarch, or1k_register_name);
  set_gdbarch_register_size (gdbarch, OR1K_64BIT_IMPLEMENTATION ? 8 : 4);
  /* Total amount of space needed to store our copies of the machine's
     register state, the array `registers'.  */
  set_gdbarch_register_bytes (gdbarch, OR1K_NUM_REGS * OR1K_GPR_REGSIZE);
  set_gdbarch_register_byte (gdbarch, or1k_register_byte);
  set_gdbarch_register_raw_size (gdbarch, or1k_register_raw_size);
  /* Largest value REGISTER_RAW_SIZE can have.  */
  set_gdbarch_max_register_raw_size (gdbarch, OR1K_64BIT_IMPLEMENTATION ? 8 : 4);
  set_gdbarch_register_virtual_size (gdbarch, generic_register_size);
  /* Largest value REGISTER_VIRTUAL_SIZE can have.  */
  set_gdbarch_max_register_virtual_size (gdbarch, OR1K_64BIT_IMPLEMENTATION ? 8 : 4);
  set_gdbarch_register_virtual_type (gdbarch, or1k_reg_virtual_type);

  /* Frame Info */
#if 0
  set_gdbarch_init_extra_frame_info (gdbarch, or1k_init_extra_frame_info);
#endif
  set_gdbarch_frame_init_saved_regs (gdbarch, or1k_frame_init_saved_regs);
  set_gdbarch_get_saved_register (gdbarch, or1k_get_saved_register);
  set_gdbarch_saved_pc_after_call (gdbarch, or1k_saved_pc_after_call);
  set_gdbarch_frame_saved_pc (gdbarch, or1k_frame_saved_pc);
  set_gdbarch_skip_prologue (gdbarch, or1k_skip_prologue);
  set_gdbarch_frame_chain (gdbarch, or1k_frame_chain);
  set_gdbarch_frame_chain_valid (gdbarch, func_frame_chain_valid);
  set_gdbarch_frame_args_address (gdbarch, default_frame_address);
  set_gdbarch_frame_locals_address (gdbarch, default_frame_address);
  /* Offset from address of function to start of its code.  */
  set_gdbarch_frame_args_skip (gdbarch, 0);
  /* OK to default this value to 'unknown'. */
  set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);

#if 0 /* Do we need to define these? */
  set_gdbarch_in_function_epilogue_p (gdbarch, or1k_in_function_epilogue_p);
#endif

  /* Miscelany */
  /* Stack grows down. */
  set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
  /* PC stops zero byte after a trap instruction
     (which means: exactly on trap instruction).  */
  set_gdbarch_decr_pc_after_break (gdbarch, 0);
  /* This value is almost never non-zero... */
  set_gdbarch_function_start_offset (gdbarch, 0);

  /* W/o prototype, coerce float args to double. */
  set_gdbarch_coerce_float_to_double (gdbarch,
                                      standard_coerce_float_to_double);

  /*
   * Call Dummies
   * These values and methods are used when gdb calls a target function.  */
  set_gdbarch_use_generic_dummy_frames (gdbarch, 1);
  set_gdbarch_push_dummy_frame (gdbarch, generic_push_dummy_frame);
  set_gdbarch_push_return_address (gdbarch, or1k_push_return_address);
  set_gdbarch_deprecated_extract_return_value (gdbarch, or1k_extract_return_value);
  /* Stack must be aligned on 32-bit boundaries when synthesizing
    function calls. or1k_push_arguments will handle it. */
  set_gdbarch_push_arguments (gdbarch, or1k_push_arguments);
  set_gdbarch_pop_frame (gdbarch, or1k_pop_frame);
  set_gdbarch_store_struct_return (gdbarch, or1k_store_struct_return);
  set_gdbarch_deprecated_store_return_value (gdbarch, or1k_store_return_value);
  set_gdbarch_deprecated_extract_struct_value_address (gdbarch, or1k_extract_struct_value_address);
  set_gdbarch_use_struct_convention (gdbarch, or1k_use_struct_convention);
  set_gdbarch_call_dummy_location (gdbarch, AT_ENTRY_POINT);
  /* Return a location where we can set a breakpoint that will be hit
     when an inferior function call returns.  This is normally the
     program's entry point.  */
  set_gdbarch_call_dummy_address (gdbarch, entry_point_address);
  set_gdbarch_call_dummy_start_offset (gdbarch, 0);
  set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 0);
  set_gdbarch_call_dummy_breakpoint_offset_p (gdbarch, 1);
  set_gdbarch_call_dummy_length (gdbarch, 0);
  set_gdbarch_pc_in_call_dummy (gdbarch, generic_pc_in_call_dummy);
  set_gdbarch_call_dummy_p (gdbarch, 1);
  set_gdbarch_call_dummy_words (gdbarch, call_dummy_words);
  set_gdbarch_sizeof_call_dummy_words (gdbarch, 0);
  set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 0); //!
  /* set_gdbarch_call_dummy_stack_adjust */
  set_gdbarch_fix_call_dummy (gdbarch, generic_fix_call_dummy);
  set_gdbarch_save_dummy_frame_tos (gdbarch, generic_save_dummy_frame_tos);
#if 0
  /* probably not needed: Extract return value from RV reg */
  set_gdbarch_extract_struct_value_address (gdbarch, or1k_extract_struct_value_address);
#endif

  /* break- and watchpoints */
  set_gdbarch_breakpoint_from_pc (gdbarch, or1k_breakpoint_from_pc);

  /* Set target type sizes */
  set_gdbarch_short_bit (gdbarch, 16);
  set_gdbarch_int_bit (gdbarch, 32 /* OR1K_64BIT_IMPLEMENTATION ? 64 : 32 */);
  set_gdbarch_float_bit (gdbarch, 32);
  set_gdbarch_double_bit (gdbarch, 64);
  set_gdbarch_long_double_bit (gdbarch, 64);
  set_gdbarch_long_bit (gdbarch, 32 /* OR1K_64BIT_IMPLEMENTATION ? 64 : 32 */);
  set_gdbarch_ptr_bit (gdbarch, 32 /* OR1K_64BIT_IMPLEMENTATION ? 64 : 32 */);
  set_gdbarch_long_long_bit (gdbarch, 64 /* OR1K_64BIT_IMPLEMENTATION ? 128 : 64 */);

#if 0
  set_gdbarch_pointer_to_address (gdbarch, unsigned_pointer_to_address);
  set_gdbarch_address_to_pointer (gdbarch, address_to_unsigned_pointer);
#endif

  set_gdbarch_stack_align (gdbarch, or1k_stack_align);
  set_gdbarch_extra_stack_alignment_needed (gdbarch, 0);

#if 0 /* TODO */
  set_gdbarch_skip_trampoline_code (gdbarch, or1k_skip_trampoline_code);
  set_gdbarch_in_solib_call_trampoline (gdbarch, or1k_in_solib_call_trampoline);
  /* possibly: */
  set_gdbarch_pc_in_sigtramp (gdbarch, or1k_pc_in_sigtramp);
  set_gdbarch_in_solib_return_trampoline (gdbarch, mips_in_return_stub);
#endif
  set_gdbarch_print_registers_info (gdbarch, or1k_print_registers_info);
  return gdbarch;
}

void
_initialize_or1k_tdep ()
{
  build_automata ();
  register_gdbarch_init (bfd_arch_or32, or1k_gdbarch_init);

  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
    tm_print_insn = print_insn_big_or32;
  else
    tm_print_insn = print_insn_little_or32;
    
  /* Commands to show and set sprs.  */
  add_info ("spr", info_spr_command, "Show information about the spr registers.");
  add_com ("spr", class_support, spr_command, "Set specified SPR register.");

  add_htrace_commands ();

  /* Extra functions supported by simulator.  */
  add_com ("or1ksim", class_obscure, or1ksim_command,
	   "Send a extended command to the or1ksim simulator.");
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]