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

Subversion Repositories or1k

[/] [or1k/] [branches/] [oc/] [insight/] [gdb/] [or1k-tdep.c] - Rev 1778

Go to most recent revision | Compare with Previous | Blame | View Log

/* 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 "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 "opcode/or32.h"
 
/* *INDENT-OFF* */
 
/* Group reg name size.  See or1k_reg_names.  */
int or1k_group_name_sizes[OR1K_NUM_SPR_GROUPS] = {
  64, 0, 0, 0, 0, 0, (24+32+32), 0, 0, 0 };
 
/* Generated reg names.  See or1k_internal_reg_name.  */
int or1k_spr_valid_aliases[OR1K_NUM_SPR_GROUPS] = {
  64, 515, 0, 0, 0, 0, (24+32+32), 0, 0, 0 };
 
/* Register names.  */
char *or1k_reg_names[] = {
  /* group 0 - general*/  
  "?", "VR", "UPR", "SR", "EPCR0", "?", "?", "?", 
  "?", "?", "?", "?", "?", "?", "?", "?",
  "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",
  /* group 1 - Data MMU - not listed, generated */
  /* 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", "PC", "?",
 
  /* general purpose registers */
  "ZERO", "SP", "FP", "A0", "A1", "A2", "A3", "A4",
  "A5", "LR", "R10", "RV", "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"
};
 
static char *or1k_group_names[] = {
  "SYS", "DMMU", "IMMU", "DCACHE", "ICACHE", "MAC", "DEBUG", "PERF", "POWER",
  "PIC", "TIMER"
};
/* *INDENT-ON* */
 
/* The list of available "set or1k " and "show or1k " commands */
static struct cmd_list_element *setor1kcmdlist = NULL;
static struct cmd_list_element *showor1kcmdlist = NULL;
 
/* List of all saved register addresses, produced by skip_prologue.  
   Relative address to sp, not used if 0.  */
static int or1k_saved_reg_addr[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 + MAX_VF_REGS)
    return SPR_REG(SPR_DEBUG_GROUP, regno + SPR_GPR);
  if (regno == PC_REGNUM)
    return PC_SPRNUM;
  if (regno == PS_REGNUM)
    return SR_SPRNUM;
  if (regno == CCR_REGNUM)
    return CCR_SPRNUM(0);
  error ("Invalid register number!");
}
 
/* Builds and returns register name.  */
 
static char tmp_name[16];
static char *
or1k_internal_register_name (i)
     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:
    case 6:
      {
	int group_start = 0;
	for (i = 0; i < group; i++) 
	  group_start += or1k_group_name_sizes[i];
 
	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 MMU group.  */
    case 1:
      if (index < 256) {
	sprintf (tmp_name, "DTLBMR%i", index);
	return (char *)&tmp_name;
      }
      index -= 256;
      if (index < 256) {
	sprintf (tmp_name, "DTLBTR%i", index);
	return (char *)&tmp_name;
      }
      index -= 256;
      switch (index)
	{
	case 0:
	  return "DMMUCR";
	case 1:
	  return "DMMUPR";
	case 2:
	  return "DTLBEIR";
	default:
	  sprintf (tmp_name, "SPR1_%i", index+512);
	  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 (group, name)
     int group;
     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 = 0; i < or1k_spr_valid_aliases[group]; i++)
    {
      char *s;
      s = or1k_internal_register_name (SPR_REG(group, i));
      if (strcasecmp (name, s) == 0)
	return i;
    }
  return -1;
}
 
#define OR1K_BREAKPOINT_STRUCT {0x21, 0x00, 0x00, 0x00}
 
/* Resturs gdb register name.  */
char *
or1k_register_name (regno)
     int regno;
{
  return or1k_internal_register_name (REGNUM_TO_SPRNUM(regno));
}
 
/* 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.  */
 
unsigned char *
or1k_breakpoint_from_pc (bp_addr, bp_size)
     CORE_ADDR * bp_addr;
     int *bp_size;
{ 
  static char breakpoint[] = OR1K_BREAKPOINT_STRUCT;
  *bp_size = OR1K_INSTLEN;
  return breakpoint;
}
 
/* Given a return value in `regbuf' with a type `valtype', extract and
   copy its value into `valbuf'. */
void
or1k_extract_return_value (valtype, regbuf, valbuf)
     struct type *valtype;
     char regbuf[REGISTER_BYTES];
     char *valbuf;
{
  if (TYPE_CODE_FLT == TYPE_CODE (valtype))
    memcpy (valbuf, &regbuf[REGISTER_BYTE (VFRV_REGNUM)], TYPE_LENGTH (valtype));
  else
    memcpy (valbuf, &regbuf[REGISTER_BYTE (RV_REGNUM)], TYPE_LENGTH (valtype));
}
 
/* 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 */
 
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. */
 
CORE_ADDR
or1k_frame_chain (frame)
     struct frame_info *frame;
{
  CORE_ADDR fp;
  if (USE_GENERIC_DUMMY_FRAMES)
    {
      if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
	return frame->frame;	/* dummy frame same as caller's 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, 4);
  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
    fp = read_memory_integer (frame->frame, 4);
 
  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, 4)) != 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.  */
void
or1k_init_saved_regs (struct frame_info *fi)
{
  CORE_ADDR frame_addr;
  int i;
  frame_saved_regs_zalloc (fi);
 
  /* Skip prologue sets or1k_saved_reg_addr[], we will use it later.  */
  or1k_skip_prologue (get_pc_function_start ((fi)->pc) + FUNCTION_START_OFFSET);
 
  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];
}
 
 
static CORE_ADDR
read_next_frame_reg (fi, regno)
     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_init_saved_regs (fi);
	  if (fi->saved_regs[regno])
	    return read_memory_integer (ADDR_BITS_REMOVE (fi->saved_regs[regno]), OR1K_GPR_REGSIZE);
	}
    }
  return read_register (regno);
}
 
/* 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.  */
 
CORE_ADDR
or1k_frame_saved_pc (fi)
     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);
}
 
/* 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_init_saved_regs (frame);
  for (regnum = 0; regnum < 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 ();
}
 
CORE_ADDR
or1k_push_arguments (nargs, args, sp, struct_return, struct_addr)
     int nargs;
     value_ptr *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];
      value_ptr 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;
}
 
/* Return nonzero when instruction has delay slot.  */
static int
is_delayed (insn)
     unsigned long insn;
{
  int i;
  for (i = 0; i < num_opcodes; ++i)
    if ((or32_opcodes[i].flags & OR32_IF_DELAY)
	&& (or32_opcode_match (insn, or32_opcodes[i].encoding)))
      break;
  return (i < num_opcodes);
}
 
int
or1k_step_skips_delay (pc)
     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));
}
 
CORE_ADDR
or1k_push_return_address (pc, sp)
     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;
}
 
/* Root of all "set or1k "/"show or1k " commands. This will eventually be
   used for all OR1K-specific commands.  */
 
static void show_or1k_command PARAMS ((char *, int));
static void
show_or1k_command (args, from_tty)
     char *args;
     int from_tty;
{
  help_list (showor1kcmdlist, "show or1k ", all_commands, gdb_stdout);
}
 
static void set_or1k_command PARAMS ((char *, int));
static void
set_or1k_command (args, from_tty)
     char *args;
     int from_tty;
{
  printf_unfiltered ("\"set or1k\" must be followed by an appropriate subcommand.\n");
  help_list (setor1kcmdlist, "set or1k ", all_commands, gdb_stdout);
}
 
static char *
parse_spr_params (args, group, index)
		  char *args;
		  int *group, *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;
		    }
		}
	    }
	}
      if (*group < 0 || *group >= OR1K_NUM_SPR_GROUPS)
	error ("Invalid group or register.\n");
 
      if (*index < 0)
	{
	  args += strlen(args) + 1;
	  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)
	    {
	      for (i = 0; i < or1k_spr_valid_aliases[*group]; i++)
		printf_unfiltered ("%s\t", or1k_internal_register_name (SPR_REG(*group, i)));
	      printf_unfiltered ("\n");
	      return args + strlen(args) + 1;
	    }
	}
    }
  else
  /* No parameters - print groups */
    {
      int i;
      printf_unfiltered ("No parameter supplied. Valid groups are:\n");
      for (i = 0; i < OR1K_NUM_SPR_GROUPS; i++)
	printf_unfiltered ("%s\t", or1k_group_names[i]);
      printf_unfiltered ("\nSingle register name or register name or number after the group can be also supplied.\n");
    }
  return args + strlen(args) + 1;
}
 
/* SPR register info.  */
 
void
info_spr_cmd (char *args, int from_tty)
{
  int group, index;
  parse_spr_params (args, &group, &index);
  if (index >= 0)
    {
      printf_unfiltered ("%s.%s (SPR%i_%i) set to %i(%X), was:%i(%X)\n", or1k_group_names[group], 
			 or1k_internal_register_name (SPR_REG(group, index)), group, index,
			 or1k_read_reg (SPR_REG(group, index)));
    }
}
 
/* Set SPR register.  */
 
void
spr_cmd (char *args, int from_tty)
{
  int group, index;
  char *nargs = parse_spr_params (args, &group, &index);
  /* Any arguments left?  */
  if (args + strlen(args) >= nargs)
    error ("Invalid register value.");
  if (index >= 0)
    {
      unsigned long prev;
      unsigned long value;
      char *ptr_c;
 
      prev = or1k_read_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.");
      printf_unfiltered ("%s.%s (SPR%i_%i) set to %i(%X), was:%i(%X)\n", or1k_group_names[group], 
			 or1k_internal_register_name (SPR_REG(group, index)), group, index,
			 value, value, prev, prev);      
    }
}
 
/* Calls extended command on target.  */
 
void
sim_command (char *args, int from_tty)
{
  or1k_sim_cmd (args, from_tty);
}
 
void
_initialize_or1k_tdep ()
{
  struct cmd_list_element *c;
  /* Add root prefix command for all "set or1k"/"show or1k" commands */
  add_prefix_cmd ("or1k", no_class, set_or1k_command,
		  "Various OR1K specific commands.",
		  &setor1kcmdlist, "set or1k ", 0, &setlist);
 
  add_prefix_cmd ("or1k", no_class, show_or1k_command,
		  "Various OR1K specific commands.",
		  &showor1kcmdlist, "show or1k ", 0, &showlist);
 
  /* Commands to show information about the sprs.  */
  add_cmd ("spr", class_info, info_spr_cmd,
	   "Show information about the spr registers.",
	   &infolist);
  c = add_cmd ("spr", class_support, spr_cmd,
		   "Set specified SPR register.",
		   &cmdlist);
  add_com ("sim", class_obscure, sim_command,
	   "Send a extended command to the simulator.");
}
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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