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

Subversion Repositories or1k

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

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

Rev 1333 Rev 1765
/* Target-dependent code for the or1k architecture, for GDB, the GNU Debugger.
/* Target-dependent code for the or1k architecture, for GDB, the GNU Debugger.
 
 
   Copyright 1988-1999, Free Software Foundation, Inc.
   Copyright 1988-1999, Free Software Foundation, Inc.
   Contributed by Alessandro Forin(af@cs.cmu.edu at CMU
   Contributed by Alessandro Forin(af@cs.cmu.edu at CMU
   and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin.
   and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin.
 
 
   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 "demangle.h"
#include "demangle.h"
#include "defs.h"
#include "defs.h"
#include "gdb_string.h"
#include "gdb_string.h"
#include "frame.h"
#include "frame.h"
#include "inferior.h"
#include "inferior.h"
#include "symtab.h"
#include "symtab.h"
#include "value.h"
#include "value.h"
#include "gdbcmd.h"
#include "gdbcmd.h"
#include "language.h"
#include "language.h"
#include "gdbcore.h"
#include "gdbcore.h"
#include "symfile.h"
#include "symfile.h"
#include "objfiles.h"
#include "objfiles.h"
#include "gdbtypes.h"
#include "gdbtypes.h"
#include "target.h"
#include "target.h"
 
 
#include "opcode/or32.h"
#include "opcode/or32.h"
 
 
/* *INDENT-OFF* */
/* *INDENT-OFF* */
 
 
/* Group reg name size.  See or1k_reg_names.  */
/* Group reg name size.  See or1k_reg_names.  */
int or1k_group_name_sizes[OR1K_NUM_SPR_GROUPS] = {
int or1k_group_name_sizes[OR1K_NUM_SPR_GROUPS] = {
  80,   0,   0, 6, 4, 3,
  80,   0,   0, 6, 4, 3,
  22, 16, 1, 3, 2, 8
  22, 16, 1, 3, 2, 8
};
};
 
 
/* Generated reg names (max valid alias index).
/* Generated reg names (max valid alias index).
   See or1k_spr_reg_name.  */
   See or1k_spr_reg_name.  */
int or1k_spr_valid_aliases[OR1K_NUM_SPR_GROUPS] = {
int or1k_spr_valid_aliases[OR1K_NUM_SPR_GROUPS] = {
  2047+1, 2047+1, 2047+1, 258+1, 257+1, 257+1,
  2047+1, 2047+1, 2047+1, 258+1, 257+1, 257+1,
  78+1, 263+1, 16+1, 18+1, 256+1, 7+1
  78+1, 263+1, 16+1, 18+1, 256+1, 7+1
};
};
 
 
/* Register names.  */
/* Register names.  */
char *or1k_reg_names[] = {
char *or1k_reg_names[] = {
 
 
  /* group 0 - general*/
  /* group 0 - general*/
  "VR", "UPR", "CPUCFGR", "DMMUCFGR", "IMMUCFGR", "DCCFGR", "ICCFGR", "DCFGR",
  "VR", "UPR", "CPUCFGR", "DMMUCFGR", "IMMUCFGR", "DCCFGR", "ICCFGR", "DCFGR",
  "PCCFGR", "SPR0_9", "SPR0_10", "SPR0_11", "SPR0_12", "SPR0_13", "SPR0_14", "SPR0_15",
  "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",
  "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",
  "SPR0_24", "SPR0_25", "SPR0_26", "SPR0_27", "SPR0_28", "SPR0_29", "SPR0_30", "SPR0_31",
  "EPCR0", "EPCR1", "EPCR2", "EPCR3", "EPCR4", "EPCR5", "EPCR6", "EPCR7",
  "EPCR0", "EPCR1", "EPCR2", "EPCR3", "EPCR4", "EPCR5", "EPCR6", "EPCR7",
  "EPCR8", "EPCR9", "EPCR10", "EPCR11", "EPCR12", "EPCR13", "EPCR14", "EPCR15",
  "EPCR8", "EPCR9", "EPCR10", "EPCR11", "EPCR12", "EPCR13", "EPCR14", "EPCR15",
  "EEAR0","EEAR1", "EEAR2", "EEAR3", "EEAR4", "EEAR5", "EEAR6", "EEAR7",
  "EEAR0","EEAR1", "EEAR2", "EEAR3", "EEAR4", "EEAR5", "EEAR6", "EEAR7",
  "EEAR8", "EEAR9", "EEAR10", "EEAR11", "EEAR12", "EEAR13", "EEAR14", "EEAR15",
  "EEAR8", "EEAR9", "EEAR10", "EEAR11", "EEAR12", "EEAR13", "EEAR14", "EEAR15",
  "ESR0", "ESR1", "ESR2", "ESR3", "ESR4", "ESR5", "ESR6", "ESR7",
  "ESR0", "ESR1", "ESR2", "ESR3", "ESR4", "ESR5", "ESR6", "ESR7",
  "ESR8", "ESR9", "ESR10", "ESR11", "ESR12", "ESR13", "ESR14", "ESR15",
  "ESR8", "ESR9", "ESR10", "ESR11", "ESR12", "ESR13", "ESR14", "ESR15",
 
 
  /* gpr+vf registers generated */
  /* gpr+vf registers generated */
  /* group 1 - Data MMU - not listed, generated */
  /* group 1 - Data MMU - not listed, generated */
  /* group 2 - Instruction MMU - not listed, generated */
  /* group 2 - Instruction MMU - not listed, generated */
 
 
  /* group 3 - Data cache */
  /* group 3 - Data cache */
  "DCCR", "DCBPR", "DCBFR", "DCBIR", "DCBWR", "DCBLR",
  "DCCR", "DCBPR", "DCBFR", "DCBIR", "DCBWR", "DCBLR",
 
 
  /* group 4 - Instruction cache */
  /* group 4 - Instruction cache */
  "ICCR", "ICBPR", "ICBIR", "ICBLR",
  "ICCR", "ICBPR", "ICBIR", "ICBLR",
 
 
  /* group 5 - MAC */
  /* group 5 - MAC */
  "SPR5_0", "MACLO", "MACHI",
  "SPR5_0", "MACLO", "MACHI",
 
 
  /* group 6 - debug */
  /* group 6 - debug */
  "DVR0", "DVR1", "DVR2", "DVR3", "DVR4", "DVR5", "DVR6", "DVR7",
  "DVR0", "DVR1", "DVR2", "DVR3", "DVR4", "DVR5", "DVR6", "DVR7",
  "DCR0", "DCR1", "DCR2", "DCR3", "DCR4", "DCR5", "DCR6", "DCR7",
  "DCR0", "DCR1", "DCR2", "DCR3", "DCR4", "DCR5", "DCR6", "DCR7",
  "DMR1", "DMR2", "DCWR0","DCWR1","DSR",  "DRR",
  "DMR1", "DMR2", "DCWR0","DCWR1","DSR",  "DRR",
 
 
  /* group 7 - performance counters unit */
  /* group 7 - performance counters unit */
  "PCCR0",  "PCCR1", "PCCR2", "PCCR3", "PCCR4", "PCCR5", "PCCR6", "PCCR7",
  "PCCR0",  "PCCR1", "PCCR2", "PCCR3", "PCCR4", "PCCR5", "PCCR6", "PCCR7",
  "PCCMR0", "PCMR1", "PCMR2", "PCMR3", "PCMR4", "PCMR5", "PCMR6", "PCMR7",
  "PCCMR0", "PCMR1", "PCMR2", "PCMR3", "PCMR4", "PCMR5", "PCMR6", "PCMR7",
 
 
  /* group 8 - power management */
  /* group 8 - power management */
  "PMR",
  "PMR",
 
 
  /* group 9 - PIC */
  /* group 9 - PIC */
  "PICMR", /* now-defunct PICPR */ "SPR9_1", "PICSR",
  "PICMR", /* now-defunct PICPR */ "SPR9_1", "PICSR",
  /* group 10 - tick timer */
  /* group 10 - tick timer */
  "TTMR", "TTCR",
  "TTMR", "TTCR",
 
 
  /* group 11 - configuration */
  /* group 11 - configuration */
  "CPUCFGR", "DMMUCFGR", "IMMUCFGR", "DCCFGR", "ICCFGR", "SPR11_5", "DCFGR", "PCCFGR"
  "CPUCFGR", "DMMUCFGR", "IMMUCFGR", "DCCFGR", "ICCFGR", "SPR11_5", "DCFGR", "PCCFGR"
};
};
 
 
static char *or1k_gdb_reg_names[] = {
static char *or1k_gdb_reg_names[] = {
 
 
  /* general purpose registers */
  /* general purpose registers */
  "R0",  "R1",  "R2",  "R3",  "R4",  "R5",  "R6",  "R7",
  "R0",  "R1",  "R2",  "R3",  "R4",  "R5",  "R6",  "R7",
  "R8",  "R9",  "R10", "R11", "R12", "R13", "R14", "R15",
  "R8",  "R9",  "R10", "R11", "R12", "R13", "R14", "R15",
  "R16", "R17", "R18", "R19", "R20", "R21", "R22", "R23",
  "R16", "R17", "R18", "R19", "R20", "R21", "R22", "R23",
  "R24", "R25", "R26", "R27", "R28", "R29", "R30", "R31",
  "R24", "R25", "R26", "R27", "R28", "R29", "R30", "R31",
 
 
  /* Modified by CZ 12/09/01 */
  /* Modified by CZ 12/09/01 */
  /* vector/floating point registers */
  /* vector/floating point registers */
  "VFA0",  "VFA1",  "VFA2",  "VFA3",  "VFA4",  "VFA5",  "VFRV ", "VFR7",
  "VFA0",  "VFA1",  "VFA2",  "VFA3",  "VFA4",  "VFA5",  "VFRV ", "VFR7",
  "VFR8",  "VFR9",  "VFR10", "VFR11", "VFR12", "VFR13", "VFR14", "VFR15",
  "VFR8",  "VFR9",  "VFR10", "VFR11", "VFR12", "VFR13", "VFR14", "VFR15",
  "VFR16", "VFR17", "VFR18", "VFR19", "VFR20", "VFR21", "VFR22", "VFR23",
  "VFR16", "VFR17", "VFR18", "VFR19", "VFR20", "VFR21", "VFR22", "VFR23",
  "VFR24", "VFR25", "VFR26", "VFR27", "VFR28", "VFR29", "VFR30", "VFR31",
  "VFR24", "VFR25", "VFR26", "VFR27", "VFR28", "VFR29", "VFR30", "VFR31",
  "PC",    "SR",    "EPCR", "ExPC", "ExEAR", "ExSR"
  "PC",    "SR",    "EPCR", "ExPC", "ExEAR", "ExSR"
};
};
 
 
static char *or1k_group_names[] = {
static char *or1k_group_names[] = {
  "SYS", "DMMU", "IMMU", "DCACHE", "ICACHE", "MAC", "DEBUG", "PERF",
  "SYS", "DMMU", "IMMU", "DCACHE", "ICACHE", "MAC", "DEBUG", "PERF",
  "POWER", "PIC", "TIMER", "CONFIG"
  "POWER", "PIC", "TIMER", "CONFIG"
};
};
 
 
/* Table of or1k signals.  */
/* Table of or1k signals.  */
static struct
static struct
  {
  {
  char *name;
  char *name;
  char *string;
  char *string;
  } or1k_signals [NUM_OR1K_SIGNALS + 1] =
  } or1k_signals [NUM_OR1K_SIGNALS + 1] =
  {
  {
    {"RSTE", "Reset Exception"},
    {"RSTE", "Reset Exception"},
    {"BUSE", "Bus Error" },
    {"BUSE", "Bus Error" },
    {"DFPE", "Data Page Fault Exception"},
    {"DFPE", "Data Page Fault Exception"},
    {"IFPE", "Instruction Page Fault Exception"},
    {"IFPE", "Instruction Page Fault Exception"},
    {"LPINTE", "Low Priority Interrupt Exception"},
    {"LPINTE", "Low Priority Interrupt Exception"},
    {"AE", "Alignment Exception"},
    {"AE", "Alignment Exception"},
    {"ILINSE" "Illegal Instruction" },
    {"ILINSE" "Illegal Instruction" },
    {"HPINTE", "High Priority Interrupt Exception"},
    {"HPINTE", "High Priority Interrupt Exception"},
    {"DME", "DTLB Miss Exception"},
    {"DME", "DTLB Miss Exception"},
    {"IME", "ITLB Miss Exception"},
    {"IME", "ITLB Miss Exception"},
    {"RE", "Range Exception"},
    {"RE", "Range Exception"},
    {"SCE", "SCE Exception"},
    {"SCE", "SCE Exception"},
    {"BRKPTE", "Breakpoint Exception"},
    {"BRKPTE", "Breakpoint Exception"},
    {NULL, NULL}
    {NULL, NULL}
  };
  };
 
 
const char *compare_to_names[NUM_CT_NAMES] =
const char *compare_to_names[NUM_CT_NAMES] =
  {
  {
    "DISABLED", "FETCH", "LEA", "SEA", "LDATA", "SDATA", "AEA", "ADATA"
    "DISABLED", "FETCH", "LEA", "SEA", "LDATA", "SDATA", "AEA", "ADATA"
  };
  };
 
 
const char *or1k_record_names[MAX_RECORD_NAMES] =
const char *or1k_record_names[MAX_RECORD_NAMES] =
  {
  {
    "PC", "LSEA", "LDATA", "SDATA", "READSPR", "WRITESPR", "INSTR"
    "PC", "LSEA", "LDATA", "SDATA", "READSPR", "WRITESPR", "INSTR"
  };
  };
 
 
const char *or1k_is_names[MAX_IS_NAMES] =
const char *or1k_is_names[MAX_IS_NAMES] =
  {
  {
    "IF_NONE", "IF_NORMAL", "IF_BRANCH", "IF_DELAY"
    "IF_NONE", "IF_NORMAL", "IF_BRANCH", "IF_DELAY"
  };
  };
 
 
const char *or1k_ls_names[MAX_LS_NAMES] =
const char *or1k_ls_names[MAX_LS_NAMES] =
  {
  {
    "LS_NONE", " ", "LBZ", "LBS", "LHZ", "LHS", "LWZ", "LWS",
    "LS_NONE", " ", "LBZ", "LBS", "LHZ", "LHS", "LWZ", "LWS",
    " ", " ", "SB", " ", "SH", " ", "SW", " "
    " ", " ", "SB", " ", "SH", " ", "SW", " "
  };
  };
 
 
/* *INDENT-ON* */
/* *INDENT-ON* */
 
 
/* The list of available "set or1k " and "show or1k " commands */
/* The list of available "set or1k " and "show or1k " commands */
static struct cmd_list_element *htrace_cmdlist = NULL;
static struct cmd_list_element *htrace_cmdlist = NULL;
static struct cmd_list_element *htrace_mode_cmdlist = NULL;
static struct cmd_list_element *htrace_mode_cmdlist = NULL;
 
 
struct htrace_struct or1k_htrace;
struct htrace_struct or1k_htrace;
struct hwatch_struct or1k_hwatch[MAX_HW_WATCHES];
struct hwatch_struct or1k_hwatch[MAX_HW_WATCHES];
int num_hw_watches = 0;
int num_hw_watches = 0;
 
 
/* Trace data.  */
/* Trace data.  */
char trace_filename[TRACE_FILENAME_SIZE] = "trace.dat";
char trace_filename[TRACE_FILENAME_SIZE] = "trace.dat";
 
 
/* Size of trace file in records.  */
/* Size of trace file in records.  */
int trace_size = 0;
int trace_size = 0;
 
 
/* Previous values for buffer display.  */
/* Previous values for buffer display.  */
static int prev_length = 10;
static int prev_length = 10;
static int prev_from = 0;
static int prev_from = 0;
 
 
/* Converts regno to sprno.  or1k debug unit has GPRs mapped to SPRs,
/* Converts regno to sprno.  or1k debug unit has GPRs mapped to SPRs,
   which are not compact, so we are mapping them for GDB.  */
   which are not compact, so we are mapping them for GDB.  */
/* Rewritten by CZ 12/09/01 */
/* Rewritten by CZ 12/09/01 */
int
int
or1k_regnum_to_sprnum (int regno)
or1k_regnum_to_sprnum (int regno)
{
{
  if(regno < MAX_GPR_REGS)
  if(regno < MAX_GPR_REGS)
    return SPR_REG(SPR_SYSTEM_GROUP, regno + CURRENT_CID * MAX_GPR_REGS + SPR_GPR_START);
    return SPR_REG(SPR_SYSTEM_GROUP, regno + CURRENT_CID * MAX_GPR_REGS + SPR_GPR_START);
 
 
  if (regno < MAX_GPR_REGS + MAX_VF_REGS)
  if (regno < MAX_GPR_REGS + MAX_VF_REGS)
    return SPR_REG(SPR_SYSTEM_GROUP, regno - MAX_GPR_REGS
    return SPR_REG(SPR_SYSTEM_GROUP, regno - MAX_GPR_REGS
                   + CURRENT_CID * MAX_GPR_REGS + SPR_VFPR_START);
                   + CURRENT_CID * MAX_GPR_REGS + SPR_VFPR_START);
 
 
  switch(regno)
  switch(regno)
    {
    {
    case PS_REGNUM:         return SR_SPRNUM;
    case PS_REGNUM:         return SR_SPRNUM;
    case PC_REGNUM:         return PC_SPRNUM;
    case PC_REGNUM:         return PC_SPRNUM;
    /*case CCR_REGNUM:        return CCR_SPRNUM(CURRENT_CID);*/
    /*case CCR_REGNUM:        return CCR_SPRNUM(CURRENT_CID);*/
    case EPCR_REGNUM:        return EPCR_SPRNUM(CURRENT_CID);
    case EPCR_REGNUM:        return EPCR_SPRNUM(CURRENT_CID);
    /*case EAR_REGNUM:        return EAR_SPRNUM(CURRENT_CID);
    /*case EAR_REGNUM:        return EAR_SPRNUM(CURRENT_CID);
    case ESR_REGNUM:        return ESR_SPRNUM(CURRENT_CID);*/
    case ESR_REGNUM:        return ESR_SPRNUM(CURRENT_CID);*/
    default:
    default:
      error("Invalid register number!");
      error("Invalid register number!");
      break;
      break;
    }
    }
 
 
  return 0;
  return 0;
}
}
 
 
/* Builds and returns register name.  */
/* Builds and returns register name.  */
 
 
static char tmp_name[16];
static char tmp_name[16];
static char *
static char *
or1k_spr_register_name (i)
or1k_spr_register_name (i)
     int i;
     int i;
{
{
  int group = i >> SPR_GROUP_SIZE_BITS;
  int group = i >> SPR_GROUP_SIZE_BITS;
  int index = i & (SPR_GROUP_SIZE - 1);
  int index = i & (SPR_GROUP_SIZE - 1);
  switch (group)
  switch (group)
    {
    {
      /* Names covered in or1k_reg_names.  */
      /* Names covered in or1k_reg_names.  */
    case 0:
    case 0:
 
 
      /* Generate upper names.  */
      /* Generate upper names.  */
      if (index >= SPR_GPR_START)
      if (index >= SPR_GPR_START)
        {
        {
          if (index < SPR_VFPR_START)
          if (index < SPR_VFPR_START)
            sprintf (tmp_name, "GPR%i", index - SPR_GPR_START);
            sprintf (tmp_name, "GPR%i", index - SPR_GPR_START);
          else
          else
            sprintf (tmp_name, "VFR%i", index - SPR_VFPR_START);
            sprintf (tmp_name, "VFR%i", index - SPR_VFPR_START);
          return (char *)&tmp_name;
          return (char *)&tmp_name;
        }
        }
    case 3:
    case 3:
    case 4:
    case 4:
    case 5:
    case 5:
    case 6:
    case 6:
    case 7:
    case 7:
    case 8:
    case 8:
    case 9:
    case 9:
    case 10:
    case 10:
      {
      {
        int group_start = 0;
        int group_start = 0;
        for (i = 0; i < group; i++)
        for (i = 0; i < group; i++)
          group_start += or1k_group_name_sizes[i];
          group_start += or1k_group_name_sizes[i];
 
 
        if (index >= or1k_group_name_sizes[group])
        if (index >= or1k_group_name_sizes[group])
          {
          {
            sprintf (tmp_name, "SPR%i_%i", group, index);
            sprintf (tmp_name, "SPR%i_%i", group, index);
            return (char *)&tmp_name;
            return (char *)&tmp_name;
          }
          }
        else
        else
          return or1k_reg_names[group_start + index];
          return or1k_reg_names[group_start + index];
      }
      }
 
 
      /* Build names for DMMU group.  */
      /* Build names for DMMU group.  */
    case 1:
    case 1:
    case 2:
    case 2:
      strcpy (tmp_name, (group == 1)?"D":"I");
      strcpy (tmp_name, (group == 1)?"D":"I");
      switch (index)
      switch (index)
        {
        {
        case 16:
        case 16:
          return strcat (tmp_name, "MMUCR");
          return strcat (tmp_name, "MMUCR");
        case 17:
        case 17:
          return strcat (tmp_name, "MMUPR");
          return strcat (tmp_name, "MMUPR");
        case 18:
        case 18:
          return strcat (tmp_name, "TLBEIR");
          return strcat (tmp_name, "TLBEIR");
        case 24:
        case 24:
          return strcat (tmp_name, "ATBMR0");
          return strcat (tmp_name, "ATBMR0");
        case 25:
        case 25:
          return strcat (tmp_name, "ATBMR1");
          return strcat (tmp_name, "ATBMR1");
        case 26:
        case 26:
          return strcat (tmp_name, "ATBMR2");
          return strcat (tmp_name, "ATBMR2");
        case 27:
        case 27:
          return strcat (tmp_name, "ATBMR3");
          return strcat (tmp_name, "ATBMR3");
        case 28:
        case 28:
          return strcat (tmp_name, "ATBTR0");
          return strcat (tmp_name, "ATBTR0");
        case 29:
        case 29:
          return strcat (tmp_name, "ATBTR0");
          return strcat (tmp_name, "ATBTR0");
        case 30:
        case 30:
          return strcat (tmp_name, "ATBTR0");
          return strcat (tmp_name, "ATBTR0");
        case 31:
        case 31:
          return strcat (tmp_name, "ATBTR0");
          return strcat (tmp_name, "ATBTR0");
        default:
        default:
          if (index >= 1024) {
          if (index >= 1024) {
            index -= 1024;
            index -= 1024;
            sprintf (tmp_name, "%sTLBW%iMR%i", (group == 1)?"D":"I", index / 128, index % 128);
            sprintf (tmp_name, "%sTLBW%iMR%i", (group == 1)?"D":"I", index / 128, index % 128);
            return (char *)&tmp_name;
            return (char *)&tmp_name;
          }
          }
          sprintf (tmp_name, "SPR%i_%i", group, index);
          sprintf (tmp_name, "SPR%i_%i", group, index);
          return (char *)&tmp_name;
          return (char *)&tmp_name;
      }
      }
    default:
    default:
      sprintf (tmp_name, "SPR%i_%i", group, index);
      sprintf (tmp_name, "SPR%i_%i", group, index);
      return (char *)&tmp_name;
      return (char *)&tmp_name;
    }
    }
}
}
 
 
/* Get register index in group from name.  Negative if no match.  */
/* Get register index in group from name.  Negative if no match.  */
 
 
static int
static int
or1k_regno_from_name (group, name)
or1k_regno_from_name (group, name)
     int group;
     int group;
     char *name;
     char *name;
{
{
  int i;
  int i;
  if (toupper(name[0]) == 'S' && toupper(name[1]) == 'P' && toupper(name[2]) == 'R')
  if (toupper(name[0]) == 'S' && toupper(name[1]) == 'P' && toupper(name[2]) == 'R')
    {
    {
      char *ptr_c;
      char *ptr_c;
      name += 3;
      name += 3;
      i = (int) strtoul (name, &ptr_c, 10);
      i = (int) strtoul (name, &ptr_c, 10);
      if (*ptr_c != '_' || i != group)
      if (*ptr_c != '_' || i != group)
        return -1;
        return -1;
      ptr_c++;
      ptr_c++;
      i = (int) strtoul (name, &ptr_c, 10);
      i = (int) strtoul (name, &ptr_c, 10);
      if (*ptr_c)
      if (*ptr_c)
        return -1;
        return -1;
      else return i;
      else return i;
    }
    }
  for (i = 0; i < or1k_spr_valid_aliases[group]; i++)
  for (i = 0; i < or1k_spr_valid_aliases[group]; i++)
    {
    {
      char *s;
      char *s;
      s = or1k_spr_register_name (SPR_REG(group, i));
      s = or1k_spr_register_name (SPR_REG(group, i));
      if (strcasecmp (name, s) == 0)
      if (strcasecmp (name, s) == 0)
        return i;
        return i;
    }
    }
  return -1;
  return -1;
}
}
 
 
/* Returns gdb register name.  */
/* Returns gdb register name.  */
 
 
char *
char *
or1k_register_name (regno)
or1k_register_name (regno)
     int regno;
     int regno;
{
{
  return or1k_gdb_reg_names[regno];
  return or1k_gdb_reg_names[regno];
}
}
 
 
/* Utility function to display vf regs.  */
/* Utility function to display vf regs.  */
 
 
static int
static int
do_vf_register (regnum)
do_vf_register (regnum)
     int regnum;
     int regnum;
{
{
  /* do values for FP (float) regs */
  /* do values for FP (float) regs */
  char *raw_buffer;
  char *raw_buffer;
 
 
   /* doubles extracted from raw hex data */
   /* doubles extracted from raw hex data */
  double doub, flt;
  double doub, flt;
  int inv1, inv3, byte;
  int inv1, inv3, byte;
 
 
  raw_buffer = (char *) alloca (OR1K_VF_REGSIZE);
  raw_buffer = (char *) alloca (OR1K_VF_REGSIZE);
 
 
  /* Get the data in raw format.  */
  /* Get the data in raw format.  */
  if (read_relative_register_raw_bytes (regnum, raw_buffer))
  if (read_relative_register_raw_bytes (regnum, raw_buffer))
    error ("can't read register %d (%s)", regnum, REGISTER_NAME (regnum));
    error ("can't read register %d (%s)", regnum, REGISTER_NAME (regnum));
 
 
  flt = unpack_double (builtin_type_float, raw_buffer, &inv1);
  flt = unpack_double (builtin_type_float, raw_buffer, &inv1);
  doub = unpack_double (builtin_type_double, raw_buffer, &inv3);
  doub = unpack_double (builtin_type_double, raw_buffer, &inv3);
 
 
  if (inv1)
  if (inv1)
    printf_filtered (" %-5s flt: <invalid float>", REGISTER_NAME (regnum));
    printf_filtered (" %-5s flt: <invalid float>", REGISTER_NAME (regnum));
  else
  else
    printf_filtered (" %-5s flt:%-17.9g", REGISTER_NAME (regnum), flt);
    printf_filtered (" %-5s flt:%-17.9g", REGISTER_NAME (regnum), flt);
  printf_filtered (inv3 ? " dbl: <invalid double> " :
  printf_filtered (inv3 ? " dbl: <invalid double> " :
                   " dbl: %-24.17g ", doub);
                   " dbl: %-24.17g ", doub);
 
 
  /* pad small registers */
  /* pad small registers */
  for (byte = 0; byte < (OR1K_GPR_REGSIZE - REGISTER_VIRTUAL_SIZE (regnum)); byte++)
  for (byte = 0; byte < (OR1K_GPR_REGSIZE - REGISTER_VIRTUAL_SIZE (regnum)); byte++)
    printf_filtered ("  ");
    printf_filtered ("  ");
 
 
  /* Now print the register value in hex, endian order. */
  /* Now print the register value in hex, endian order. */
  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
    for (byte = REGISTER_RAW_SIZE (regnum) - REGISTER_VIRTUAL_SIZE (regnum);
    for (byte = REGISTER_RAW_SIZE (regnum) - REGISTER_VIRTUAL_SIZE (regnum);
         byte < REGISTER_RAW_SIZE (regnum);
         byte < REGISTER_RAW_SIZE (regnum);
         byte++)
         byte++)
      printf_filtered ("%02x", (unsigned char) raw_buffer[byte]);
      printf_filtered ("%02x", (unsigned char) raw_buffer[byte]);
  else
  else
    for (byte = REGISTER_VIRTUAL_SIZE (regnum) - 1;
    for (byte = REGISTER_VIRTUAL_SIZE (regnum) - 1;
         byte >= 0;
         byte >= 0;
         byte--)
         byte--)
      printf_filtered ("%02x", (unsigned char) raw_buffer[byte]);
      printf_filtered ("%02x", (unsigned char) raw_buffer[byte]);
  printf_filtered ("\n");
  printf_filtered ("\n");
 
 
  regnum++;
  regnum++;
  return regnum;
  return regnum;
}
}
 
 
/* Print a row's worth of GP (int) registers, with name labels above */
/* Print a row's worth of GP (int) registers, with name labels above */
 
 
static int
static int
do_gp_register_row (regnum)
do_gp_register_row (regnum)
     int regnum;
     int regnum;
{
{
  /* do values for GP (int) regs */
  /* do values for GP (int) regs */
  char raw_buffer[MAX_REGISTER_RAW_SIZE];
  char raw_buffer[MAX_REGISTER_RAW_SIZE];
 
 
  /* display cols per row */
  /* display cols per row */
  int ncols = (OR1K_64BIT_IMPLEMENTATION ? 4 : 8);
  int ncols = (OR1K_64BIT_IMPLEMENTATION ? 4 : 8);
  int col, byte;
  int col, byte;
  int start_regnum = regnum;
  int start_regnum = regnum;
  int numregs = NUM_REGS;
  int numregs = NUM_REGS;
 
 
  /* For GP registers, we print a separate row of names above the vals */
  /* For GP registers, we print a separate row of names above the vals */
  printf_filtered ("     ");
  printf_filtered ("     ");
  for (col = 0; col < ncols && regnum < numregs; regnum++)
  for (col = 0; col < ncols && regnum < numregs; regnum++)
    {
    {
      if (*REGISTER_NAME (regnum) == '\0')
      if (*REGISTER_NAME (regnum) == '\0')
        continue;               /* unused register */
        continue;               /* unused register */
      if (OR1K_IS_VF(regnum))
      if (OR1K_IS_VF(regnum))
        break;                  /* end the row: reached VF register */
        break;                  /* end the row: reached VF register */
      printf_filtered (OR1K_64BIT_IMPLEMENTATION ? "%17s" : "%9s",
      printf_filtered (OR1K_64BIT_IMPLEMENTATION ? "%17s" : "%9s",
                       REGISTER_NAME (regnum));
                       REGISTER_NAME (regnum));
      col++;
      col++;
    }
    }
  printf_filtered ("\n      ");
  printf_filtered ("\n      ");
 
 
  regnum = start_regnum;        /* go back to start of row */
  regnum = start_regnum;        /* go back to start of row */
 
 
  /* now print the values in hex, 4 or 8 to the row */
  /* now print the values in hex, 4 or 8 to the row */
  for (col = 0; col < ncols && regnum < numregs; regnum++)
  for (col = 0; col < ncols && regnum < numregs; regnum++)
    {
    {
      /* unused register? */
      /* unused register? */
      if (*REGISTER_NAME (regnum) == '\0')
      if (*REGISTER_NAME (regnum) == '\0')
        continue;
        continue;
 
 
      /* end row: reached VF register? */
      /* end row: reached VF register? */
      if (OR1K_IS_VF(regnum))
      if (OR1K_IS_VF(regnum))
        break;
        break;
 
 
      /* OK: get the data in raw format.  */
      /* OK: get the data in raw format.  */
      if (read_relative_register_raw_bytes (regnum, raw_buffer))
      if (read_relative_register_raw_bytes (regnum, raw_buffer))
        error ("can't read register %d (%s)", regnum, REGISTER_NAME (regnum));
        error ("can't read register %d (%s)", regnum, REGISTER_NAME (regnum));
 
 
      /* pad small registers */
      /* pad small registers */
      for (byte = 0; byte < (OR1K_GPR_REGSIZE - REGISTER_VIRTUAL_SIZE (regnum)); byte++)
      for (byte = 0; byte < (OR1K_GPR_REGSIZE - REGISTER_VIRTUAL_SIZE (regnum)); byte++)
        printf_filtered ("  ");
        printf_filtered ("  ");
 
 
      /* Now print the register value in hex, endian order. */
      /* Now print the register value in hex, endian order. */
      if (TARGET_BYTE_ORDER == BIG_ENDIAN)
      if (TARGET_BYTE_ORDER == BIG_ENDIAN)
        for (byte = REGISTER_RAW_SIZE (regnum) - REGISTER_VIRTUAL_SIZE (regnum);
        for (byte = REGISTER_RAW_SIZE (regnum) - REGISTER_VIRTUAL_SIZE (regnum);
             byte < REGISTER_RAW_SIZE (regnum);
             byte < REGISTER_RAW_SIZE (regnum);
             byte++)
             byte++)
          printf_filtered ("%02x", (unsigned char) raw_buffer[byte]);
          printf_filtered ("%02x", (unsigned char) raw_buffer[byte]);
      else
      else
        for (byte = REGISTER_VIRTUAL_SIZE (regnum) - 1;
        for (byte = REGISTER_VIRTUAL_SIZE (regnum) - 1;
             byte >= 0;
             byte >= 0;
             byte--)
             byte--)
          printf_filtered ("%02x", (unsigned char) raw_buffer[byte]);
          printf_filtered ("%02x", (unsigned char) raw_buffer[byte]);
      printf_filtered (" ");
      printf_filtered (" ");
      col++;
      col++;
    }
    }
 
 
  /* ie. if we actually printed anything... */
  /* ie. if we actually printed anything... */
  if (col > 0)
  if (col > 0)
    printf_filtered ("\n");
    printf_filtered ("\n");
 
 
  return regnum;
  return regnum;
}
}
 
 
/* Replacement for generic do_registers_info.
/* Replacement for generic do_registers_info.
   Print regs in pretty columns.  */
   Print regs in pretty columns.  */
 
 
static void
static void
print_register (regnum, all)
print_register (regnum, all)
     int regnum, all;
     int regnum, all;
{
{
  int offset;
  int offset;
  char raw_buffer[MAX_REGISTER_RAW_SIZE];
  char raw_buffer[MAX_REGISTER_RAW_SIZE];
 
 
  /* Get the data in raw format.  */
  /* Get the data in raw format.  */
  if (read_relative_register_raw_bytes (regnum, raw_buffer))
  if (read_relative_register_raw_bytes (regnum, raw_buffer))
    {
    {
      printf_filtered ("%s: [Invalid]", REGISTER_NAME (regnum));
      printf_filtered ("%s: [Invalid]", REGISTER_NAME (regnum));
      return;
      return;
    }
    }
 
 
  /* If virtual format is floating, print it that way.  */
  /* If virtual format is floating, print it that way.  */
  if (OR1K_IS_VF (regnum))
  if (OR1K_IS_VF (regnum))
    do_vf_register (regnum);
    do_vf_register (regnum);
  else
  else
    {
    {
      int byte;
      int byte;
      printf_filtered ("%-16s\t", REGISTER_NAME (regnum));
      printf_filtered ("%-16s\t", REGISTER_NAME (regnum));
 
 
      /* pad small registers */
      /* pad small registers */
      for (byte = 0; byte < (OR1K_GPR_REGSIZE - REGISTER_VIRTUAL_SIZE (regnum)); byte++)
      for (byte = 0; byte < (OR1K_GPR_REGSIZE - REGISTER_VIRTUAL_SIZE (regnum)); byte++)
        printf_filtered ("  ");
        printf_filtered ("  ");
 
 
      /* Now print the register value in hex, endian order. */
      /* Now print the register value in hex, endian order. */
      if (TARGET_BYTE_ORDER == BIG_ENDIAN)
      if (TARGET_BYTE_ORDER == BIG_ENDIAN)
        for (byte = REGISTER_RAW_SIZE (regnum) - REGISTER_VIRTUAL_SIZE (regnum);
        for (byte = REGISTER_RAW_SIZE (regnum) - REGISTER_VIRTUAL_SIZE (regnum);
             byte < REGISTER_RAW_SIZE (regnum);
             byte < REGISTER_RAW_SIZE (regnum);
             byte++)
             byte++)
          printf_filtered ("%02x", (unsigned char) raw_buffer[byte]);
          printf_filtered ("%02x", (unsigned char) raw_buffer[byte]);
      else
      else
        for (byte = REGISTER_VIRTUAL_SIZE (regnum) - 1;
        for (byte = REGISTER_VIRTUAL_SIZE (regnum) - 1;
             byte >= 0;
             byte >= 0;
             byte--)
             byte--)
          printf_filtered ("%02x", (unsigned char) raw_buffer[byte]);
          printf_filtered ("%02x", (unsigned char) raw_buffer[byte]);
      printf_filtered (" ");
      printf_filtered (" ");
    }
    }
}
}
 
 
/* DO_REGISTERS_INFO: called by "info register" command */
/* DO_REGISTERS_INFO: called by "info register" command */
 
 
void
void
or1k_do_registers_info (regnum, fpregs)
or1k_do_registers_info (regnum, fpregs)
     int regnum;
     int regnum;
     int fpregs;
     int fpregs;
{
{
  if (fpregs && !or1k_implementation.vf_present)
  if (fpregs && !or1k_implementation.vf_present)
    {
    {
      warning ("VF register set not present in this implementation.");
      warning ("VF register set not present in this implementation.");
      fpregs = 0;
      fpregs = 0;
    }
    }
  if (regnum != -1)
  if (regnum != -1)
    {
    {
      /* do one specified register */
      /* do one specified register */
      if (*(REGISTER_NAME (regnum)) == '\0')
      if (*(REGISTER_NAME (regnum)) == '\0')
        error ("Not a valid register for the current processor type");
        error ("Not a valid register for the current processor type");
 
 
      print_register (regnum, 0);
      print_register (regnum, 0);
      printf_filtered ("\n");
      printf_filtered ("\n");
    }
    }
  else
  else
    /* do all (or most) registers */
    /* do all (or most) registers */
    {
    {
      regnum = 0;
      regnum = 0;
      while (regnum < NUM_REGS)
      while (regnum < NUM_REGS)
        {
        {
          if (OR1K_IS_VF (regnum))
          if (OR1K_IS_VF (regnum))
            /* true for "INFO ALL-REGISTERS" command */
            /* true for "INFO ALL-REGISTERS" command */
            if (fpregs)
            if (fpregs)
              /* FP regs */
              /* FP regs */
              regnum = do_vf_register (regnum);
              regnum = do_vf_register (regnum);
            else
            else
              /* skip floating point regs */
              /* skip floating point regs */
              regnum++;
              regnum++;
          else
          else
            /* GP (int) regs */
            /* GP (int) regs */
            regnum = do_gp_register_row (regnum);
            regnum = do_gp_register_row (regnum);
        }
        }
    }
    }
}
}
 
 
/* Given the address at which to insert a breakpoint (BP_ADDR),
/* Given the address at which to insert a breakpoint (BP_ADDR),
   what will that breakpoint be?
   what will that breakpoint be?
 
 
   For or1k, we have a breakpoint instruction. Since all or1k
   For or1k, we have a breakpoint instruction. Since all or1k
   instructions are 32 bits, this is all we need, regardless of
   instructions are 32 bits, this is all we need, regardless of
   address. K is not used.  */
   address. K is not used.  */
 
 
unsigned char *
unsigned char *
or1k_breakpoint_from_pc (bp_addr, bp_size)
or1k_breakpoint_from_pc (bp_addr, bp_size)
     CORE_ADDR * bp_addr;
     CORE_ADDR * bp_addr;
     int *bp_size;
     int *bp_size;
{
{
  static char breakpoint[] = BRK_INSTR_STRUCT;
  static char breakpoint[] = BRK_INSTR_STRUCT;
  *bp_size = OR1K_INSTLEN;
  *bp_size = OR1K_INSTLEN;
  return breakpoint;
  return breakpoint;
}
}
 
 
/* Return the string for a signal.
/* Return the string for a signal.
   Replacement for target_signal_to_string (sig).  NOT USED.  */
   Replacement for target_signal_to_string (sig).  NOT USED.  */
 
 
char
char
*or1k_signal_to_string (sig)
*or1k_signal_to_string (sig)
     enum target_signal sig;
     enum target_signal sig;
{
{
  if ((sig >= TARGET_SIGNAL_FIRST) && (sig <= TARGET_SIGNAL_LAST))
  if ((sig >= TARGET_SIGNAL_FIRST) && (sig <= TARGET_SIGNAL_LAST))
    return or1k_signals[sig].string;
    return or1k_signals[sig].string;
  else
  else
    if (sig <= TARGET_SIGNAL_LAST + NUM_OR1K_SIGNALS)
    if (sig <= TARGET_SIGNAL_LAST + NUM_OR1K_SIGNALS)
      return or1k_signals[sig - TARGET_SIGNAL_LAST].string;
      return or1k_signals[sig - TARGET_SIGNAL_LAST].string;
    else
    else
      return 0;
      return 0;
}
}
 
 
/* Return the name for a signal.  */
/* Return the name for a signal.  */
 
 
char *
char *
or1k_signal_to_name (sig)
or1k_signal_to_name (sig)
     enum target_signal sig;
     enum target_signal sig;
{
{
  if (sig >= TARGET_SIGNAL_LAST)
  if (sig >= TARGET_SIGNAL_LAST)
    if (sig <= TARGET_SIGNAL_LAST + NUM_OR1K_SIGNALS)
    if (sig <= TARGET_SIGNAL_LAST + NUM_OR1K_SIGNALS)
      return or1k_signals[sig - TARGET_SIGNAL_LAST].name;
      return or1k_signals[sig - TARGET_SIGNAL_LAST].name;
    else
    else
 
 
    /* I think the code which prints this will always print it along with
    /* I think the code which prints this will always print it along with
       the string, so no need to be verbose.  */
       the string, so no need to be verbose.  */
      return "?";
      return "?";
  if (sig == TARGET_SIGNAL_UNKNOWN)
  if (sig == TARGET_SIGNAL_UNKNOWN)
    return "?";
    return "?";
  return 0;
  return 0;
}
}
 
 
/* Given a name, return its signal.  NOT USED.  */
/* Given a name, return its signal.  NOT USED.  */
enum target_signal
enum target_signal
or1k_signal_from_name (name)
or1k_signal_from_name (name)
     char *name;
     char *name;
{
{
  enum target_signal sig;
  enum target_signal sig;
 
 
  /* It's possible we also should allow "SIGCLD" as well as "SIGCHLD"
  /* It's possible we also should allow "SIGCLD" as well as "SIGCHLD"
     for TARGET_SIGNAL_SIGCHLD.  SIGIOT, on the other hand, is more
     for TARGET_SIGNAL_SIGCHLD.  SIGIOT, on the other hand, is more
     questionable; seems like by now people should call it SIGABRT
     questionable; seems like by now people should call it SIGABRT
     instead.  */
     instead.  */
 
 
  /* This ugly cast brought to you by the native VAX compiler.  */
  /* This ugly cast brought to you by the native VAX compiler.  */
  for (sig = TARGET_SIGNAL_FIRST;
  for (sig = TARGET_SIGNAL_FIRST;
       or1k_signal_to_name (sig) != NULL;
       or1k_signal_to_name (sig) != NULL;
       sig = (enum target_signal) ((int) sig + 1))
       sig = (enum target_signal) ((int) sig + 1))
    if (STREQ (name, or1k_signal_to_name (sig)))
    if (STREQ (name, or1k_signal_to_name (sig)))
      return sig;
      return sig;
  return TARGET_SIGNAL_UNKNOWN;
  return TARGET_SIGNAL_UNKNOWN;
}
}
 
 
/* Given a return value in `regbuf' with a type `valtype', extract and
/* Given a return value in `regbuf' with a type `valtype', extract and
   copy its value into `valbuf'. */
   copy its value into `valbuf'. */
 
 
void
void
or1k_extract_return_value (valtype, regbuf, valbuf)
or1k_extract_return_value (valtype, regbuf, valbuf)
     struct type *valtype;
     struct type *valtype;
     char regbuf[REGISTER_BYTES];
     char regbuf[REGISTER_BYTES];
     char *valbuf;
     char *valbuf;
{
{
  if (TYPE_CODE_FLT == TYPE_CODE (valtype))
  if (TYPE_CODE_FLT == TYPE_CODE (valtype))
    memcpy (valbuf, &regbuf[REGISTER_BYTE (VFRV_REGNUM)], TYPE_LENGTH (valtype));
    memcpy (valbuf, &regbuf[REGISTER_BYTE (VFRV_REGNUM)], TYPE_LENGTH (valtype));
  else
  else
    memcpy (valbuf, &regbuf[REGISTER_BYTE (RV_REGNUM)], TYPE_LENGTH (valtype));
    memcpy (valbuf, &regbuf[REGISTER_BYTE (RV_REGNUM)], TYPE_LENGTH (valtype));
}
}
 
 
/* Given a register index, return the first byte of the register within a remote
/* Given a register index, return the first byte of the register within a remote
   protocol packet.  This applies only to serial targets, not jtag or sim. */
   protocol packet.  This applies only to serial targets, not jtag or sim. */
int
int
or1k_register_byte(regnum)
or1k_register_byte(regnum)
     int regnum;
     int regnum;
{
{
  int byte_offset;
  int byte_offset;
 
 
  byte_offset = 0;
  byte_offset = 0;
  if (regnum < MAX_GPR_REGS) {
  if (regnum < MAX_GPR_REGS) {
    if (regnum < NUM_GPR_REGS)
    if (regnum < NUM_GPR_REGS)
      return byte_offset + regnum * OR1K_GPR_REGSIZE;
      return byte_offset + regnum * OR1K_GPR_REGSIZE;
    else
    else
      return -1;
      return -1;
  }
  }
 
 
  byte_offset += NUM_GPR_REGS * OR1K_GPR_REGSIZE;
  byte_offset += NUM_GPR_REGS * OR1K_GPR_REGSIZE;
  regnum -= MAX_GPR_REGS;
  regnum -= MAX_GPR_REGS;
  if (regnum < MAX_VF_REGS) {
  if (regnum < MAX_VF_REGS) {
    if (regnum < NUM_VF_REGS)
    if (regnum < NUM_VF_REGS)
      return byte_offset + regnum * OR1K_VF_REGSIZE;
      return byte_offset + regnum * OR1K_VF_REGSIZE;
    else
    else
      return -1;
      return -1;
  }
  }
 
 
  /* Must be PC, SR, or EPC */
  /* Must be PC, SR, or EPC */
  byte_offset += NUM_VF_REGS * OR1K_VF_REGSIZE;
  byte_offset += NUM_VF_REGS * OR1K_VF_REGSIZE;
  regnum -= MAX_VF_REGS;
  regnum -= MAX_VF_REGS;
  if (regnum < 3)
  if (regnum < 3)
    return byte_offset + regnum * OR1K_SPR_REGSIZE;
    return byte_offset + regnum * OR1K_SPR_REGSIZE;
 
 
  /* Illegal register */
  /* Illegal register */
  return -1;
  return -1;
}
}
 
 
/* Number of bytes of storage in the actual machine representation for
/* Number of bytes of storage in the actual machine representation for
   register N.  NOTE: This indirectly defines the register size
   register N.  NOTE: This indirectly defines the register size
   transfered by the GDB protocol.  If we have 64bit processor
   transfered by the GDB protocol.  If we have 64bit processor
   implementation, GPR register raw size is 8B, otherwise 4B.  */
   implementation, GPR register raw size is 8B, otherwise 4B.  */
int
int
or1k_register_raw_size(int regnum)
or1k_register_raw_size(int regnum)
{
{
  int byte_offset;
  int byte_offset;
 
 
  if (regnum < MAX_GPR_REGS) {
  if (regnum < MAX_GPR_REGS) {
    if (regnum < NUM_GPR_REGS)
    if (regnum < NUM_GPR_REGS)
      return OR1K_GPR_REGSIZE;
      return OR1K_GPR_REGSIZE;
    else
    else
      return 0;
      return 0;
  }
  }
 
 
  regnum -= MAX_GPR_REGS;
  regnum -= MAX_GPR_REGS;
  if (regnum < MAX_VF_REGS) {
  if (regnum < MAX_VF_REGS) {
    if (regnum < NUM_VF_REGS)
    if (regnum < NUM_VF_REGS)
      return OR1K_VF_REGSIZE;
      return OR1K_VF_REGSIZE;
    else
    else
      return 0;
      return 0;
  }
  }
 
 
  /* Must be PC, SR, or EPC */
  /* Must be PC, SR, or EPC */
  regnum -= MAX_VF_REGS;
  regnum -= MAX_VF_REGS;
  if (regnum < 3)
  if (regnum < 3)
    return OR1K_SPR_REGSIZE;
    return OR1K_SPR_REGSIZE;
 
 
  /* Illegal register */
  /* Illegal register */
  return 0;
  return 0;
}
}
 
 
/* Extra arch-specific data tied to frame */
/* Extra arch-specific data tied to frame */
struct frame_extra_info
struct frame_extra_info
{
{
  /* Size of stack frame, in bytes.  Produced by skip_prologue() */
  /* Size of stack frame, in bytes.  Produced by skip_prologue() */
  int frame_size;
  int frame_size;
 
 
  /* List of frame offsets of all registers saved in a function's
  /* List of frame offsets of all registers saved in a function's
     prologue.  This is deduced by skip_prologue().  Offset is in bytes,
     prologue.  This is deduced by skip_prologue().  Offset is in bytes,
     relative to sp.  If value is -1, corresponding reg is not saved by
     relative to sp.  If value is -1, corresponding reg is not saved by
     the prologue code. */
     the prologue code. */
  int saved_reg_frame_offset[NUM_REGS];
  int saved_reg_frame_offset[NUM_REGS];
 
 
  /* Address of first instruction after the last prologue instruction;
  /* Address of first instruction after the last prologue instruction;
     Note that there may be instructions from the function's body
     Note that there may be instructions from the function's body
     intermingled with the prologue.
     intermingled with the prologue.
     If value is -1, not initialized. */
     If value is -1, not initialized. */
  CORE_ADDR after_prologue;
  CORE_ADDR after_prologue;
};
};
 
 
/* Initialize arch-specific frame data */
/* Initialize arch-specific frame data */
void
void
or1k_init_extra_frame_info (int fromleaf, struct frame_info *frame)
or1k_init_extra_frame_info (int fromleaf, struct frame_info *frame)
{
{
  int i;
  int i;
 
 
  frame->extra_info = (struct frame_extra_info *)
  frame->extra_info = (struct frame_extra_info *)
    frame_obstack_alloc (sizeof (struct frame_extra_info));
    frame_obstack_alloc (sizeof (struct frame_extra_info));
 
 
  frame->extra_info->after_prologue = -1;
  frame->extra_info->after_prologue = -1;
  frame->extra_info->frame_size = -1;
  frame->extra_info->frame_size = -1;
  for (i = 0; i < NUM_REGS; i++)
  for (i = 0; i < NUM_REGS; i++)
    frame->extra_info->saved_reg_frame_offset[i] = -1;
    frame->extra_info->saved_reg_frame_offset[i] = -1;
}
}
 
 
/* For stack frame sizes less than 0x8000, the or1k version of gcc
/* For stack frame sizes less than 0x8000, the or1k version of gcc
   emits the following prologue:
   emits the following prologue:
 
 
     l.addi    r1, r1, -<STACK_FRAME_SIZE>
     l.addi    r1, r1, -<STACK_FRAME_SIZE>
     l.sw      <FP_OFFSET>(r1),r2
     l.sw      <FP_OFFSET>(r1),r2
     l.addi    r2, r1, <STACK_FRAME_SIZE>
     l.addi    r2, r1, <STACK_FRAME_SIZE>
 
 
     ; Save regs that will be clobbered
     ; Save regs that will be clobbered
     l.sw      <OFFSET_Rx>(r1),rx
     l.sw      <OFFSET_Rx>(r1),rx
     l.sw      <OFFSET_Ry>(r1),ry
     l.sw      <OFFSET_Ry>(r1),ry
     ; ...
     ; ...
 
 
*/
*/
 
 
/* FIXME: Does not work with frames greater than 0x7fff in size */
/* FIXME: Does not work with frames greater than 0x7fff in size */
 
 
/* If pframeless is non-NULL, only parse enough of the prologue to
/* If pframeless is non-NULL, only parse enough of the prologue to
   determine if a function has a frame or not and return the result in
   determine if a function has a frame or not and return the result in
   *pframeless.  This may save some remote transactions with the
   *pframeless.  This may save some remote transactions with the
   target. */
   target. */
CORE_ADDR
CORE_ADDR
or1k_skip_prologue (CORE_ADDR pc, struct frame_info *fi)
or1k_skip_prologue (CORE_ADDR pc, struct frame_info *fi)
{
{
  unsigned long insn;
  unsigned long insn;
  CORE_ADDR skip_pc;
  CORE_ADDR skip_pc;
  CORE_ADDR func_addr, func_end;
  CORE_ADDR func_addr, func_end;
  struct symtab_and_line sal;
  struct symtab_and_line sal;
  int i, frameless;
  int i, frameless;
  int offset = 0;
  int offset = 0;
  int rB, immediate, immediate_hi;
  int rB, immediate, immediate_hi;
  int* saved_reg_frame_offset;
  int* saved_reg_frame_offset;
 
 
  /* Check to see if prologue analysis is cached from prior call */
  /* Check to see if prologue analysis is cached from prior call */
  if (fi && fi->extra_info->after_prologue != -1)
  if (fi && fi->extra_info->after_prologue != -1)
    return fi->extra_info->after_prologue;
    return fi->extra_info->after_prologue;
 
 
  if (fi)
  if (fi)
    saved_reg_frame_offset = &fi->extra_info->saved_reg_frame_offset[0];
    saved_reg_frame_offset = &fi->extra_info->saved_reg_frame_offset[0];
 
 
  /* Is there a prologue?  */
  /* Is there a prologue?  */
  insn = or1k_fetch_instruction (pc);
  insn = or1k_fetch_instruction (pc);
  if ((insn & 0xFFFF0000) != 0x9c210000) /* l.addi r1,r1,I */
  if ((insn & 0xFFFF0000) != 0x9c210000) /* l.addi r1,r1,I */
    goto done;
    goto done;
 
 
  pc += OR1K_INSTLEN;
  pc += OR1K_INSTLEN;
 
 
  insn = or1k_fetch_instruction (pc);
  insn = or1k_fetch_instruction (pc);
  if ((insn & 0xfc1ff800) != 0xd4011000) /* l.sw I(r1),r2 */
  if ((insn & 0xfc1ff800) != 0xd4011000) /* l.sw I(r1),r2 */
    goto done;
    goto done;
  immediate_hi = (insn & 0x03E00000) >> 10;
  immediate_hi = (insn & 0x03E00000) >> 10;
  immediate    = (insn & 0x000007FF) | immediate_hi;
  immediate    = (insn & 0x000007FF) | immediate_hi;
  pc += OR1K_INSTLEN;
  pc += OR1K_INSTLEN;
  if (fi)
  if (fi)
    saved_reg_frame_offset[2] = immediate;
    saved_reg_frame_offset[2] = immediate;
 
 
  insn = or1k_fetch_instruction (pc);
  insn = or1k_fetch_instruction (pc);
  if ((insn & 0xFFFF0000) != 0x9c410000) /* l.addi r2,r1,I */
  if ((insn & 0xFFFF0000) != 0x9c410000) /* l.addi r2,r1,I */
    goto done;
    goto done;
  if (fi)
  if (fi)
    fi->extra_info->frame_size = insn & 0xFFFF;
    fi->extra_info->frame_size = insn & 0xFFFF;
  pc += OR1K_INSTLEN;
  pc += OR1K_INSTLEN;
 
 
  /* Skip stored registers.  */
  /* Skip stored registers.  */
  insn = or1k_fetch_instruction (pc);
  insn = or1k_fetch_instruction (pc);
  while ((insn & 0xfc1f0000) == 0xd4010000)  /* l.sw I(r1),rx */
  while ((insn & 0xfc1f0000) == 0xd4010000)  /* l.sw I(r1),rx */
    {
    {
      rB           = (insn & 0x0000F800) >> 11;
      rB           = (insn & 0x0000F800) >> 11;
      immediate_hi = (insn & 0x03E00000) >> 10;
      immediate_hi = (insn & 0x03E00000) >> 10;
      immediate    = (insn & 0x000007FF) | immediate_hi;
      immediate    = (insn & 0x000007FF) | immediate_hi;
 
 
      /* get saved reg. */
      /* get saved reg. */
      if (fi)
      if (fi)
        saved_reg_frame_offset[rB] = immediate;
        saved_reg_frame_offset[rB] = immediate;
      pc += OR1K_INSTLEN;
      pc += OR1K_INSTLEN;
      insn = or1k_fetch_instruction (pc);
      insn = or1k_fetch_instruction (pc);
    }
    }
 done:
 done:
  if (fi)
  if (fi)
    fi->extra_info->after_prologue = pc;
    fi->extra_info->after_prologue = pc;
  return pc;
  return pc;
}
}
 
 
/* Determines whether this function has frame.  */
/* Determines whether this function has frame.  */
 
 
int
int
or1k_frameless_function_invocation (struct frame_info *fi)
or1k_frameless_function_invocation (struct frame_info *fi)
{
{
  int frameless;
  int frameless;
  CORE_ADDR func_start, after_prologue;
  CORE_ADDR func_start, after_prologue;
  func_start = (get_pc_function_start ((fi)->pc) + FUNCTION_START_OFFSET);
  func_start = (get_pc_function_start ((fi)->pc) + FUNCTION_START_OFFSET);
 
 
  /* If we don't skip pc, we don't have even shortest possible  prologue.  */
  /* If we don't skip pc, we don't have even shortest possible  prologue.  */
  after_prologue = or1k_skip_prologue (func_start, fi);
  after_prologue = or1k_skip_prologue (func_start, fi);
  frameless = (after_prologue <= func_start);
  frameless = (after_prologue <= func_start);
  return frameless;
  return frameless;
}
}
 
 
/* Given a GDB frame, determine the address of the calling function's frame.
/* 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
   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. */
   INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC will be called for the new frame. */
 
 
CORE_ADDR
CORE_ADDR
or1k_frame_chain (frame)
or1k_frame_chain (frame)
     struct frame_info *frame;
     struct frame_info *frame;
{
{
  CORE_ADDR fp = 0;
  CORE_ADDR fp = 0;
  if (USE_GENERIC_DUMMY_FRAMES)
  if (USE_GENERIC_DUMMY_FRAMES)
    {
    {
      if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
      if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
        /* dummy frame same as caller's frame */
        /* dummy frame same as caller's frame */
        return frame->frame;
        return frame->frame;
    }
    }
 
 
  if (inside_entry_file (frame->pc) ||
  if (inside_entry_file (frame->pc) ||
      frame->pc == entry_point_address ())
      frame->pc == entry_point_address ())
    return 0;
    return 0;
 
 
  if (frame->signal_handler_caller)
  if (frame->signal_handler_caller)
    fp = read_memory_integer (frame->frame, 4);
    fp = read_memory_integer (frame->frame, 4);
  else if (frame->next != NULL
  else if (frame->next != NULL
           && frame->next->signal_handler_caller
           && frame->next->signal_handler_caller
           && FRAMELESS_FUNCTION_INVOCATION (frame))
           && FRAMELESS_FUNCTION_INVOCATION (frame))
    /* A frameless function interrupted by a signal did not change the
    /* A frameless function interrupted by a signal did not change the
       frame pointer.  */
       frame pointer.  */
    fp = FRAME_FP (frame);
    fp = FRAME_FP (frame);
  else
  else
    {
    {
      unsigned long func_pc = get_pc_function_start(frame->pc);
      unsigned long func_pc = get_pc_function_start(frame->pc);
      unsigned long insn = read_memory_integer(func_pc,4);
      unsigned long insn = read_memory_integer(func_pc,4);
      int i;
      int i;
      int offset = 0;
      int offset = 0;
 
 
      /* The first instruction should tell us the number of bytes
      /* The first instruction should tell us the number of bytes
         in our frame. If it isn't we're in trouble because
         in our frame. If it isn't we're in trouble because
         the function is without a prologue... */
         the function is without a prologue... */
      if ((insn & 0xFFFF0000) == 0x9c210000) /* l.addi r1,r1,I */
      if ((insn & 0xFFFF0000) == 0x9c210000) /* l.addi r1,r1,I */
        {
        {
          /* Sign extend immediate */
          /* Sign extend immediate */
          int immediate = (long)(insn << 16) >> 16;
          int immediate = (long)(insn << 16) >> 16;
          int frame_size = -immediate;
          int frame_size = -immediate;
 
 
          /* Look for the storage of the frame pointer in the
          /* Look for the storage of the frame pointer in the
             function prologue.. */
             function prologue.. */
          unsigned long insn = read_memory_integer(func_pc+4,4);
          unsigned long insn = read_memory_integer(func_pc+4,4);
 
 
          /* If bits are 31 - 26 are %110101,
          /* If bits are 31 - 26 are %110101,
             and bits 20 - 16 are %00001,
             and bits 20 - 16 are %00001,
             and bits 15 - 11 are %00010,
             and bits 15 - 11 are %00010,
             then our frame pointer lies at the offset specified
             then our frame pointer lies at the offset specified
             by bits [25-21][10-0]. */
             by bits [25-21][10-0]. */
 
 
          int code = insn >> 26;
          int code = insn >> 26;
          int r1    = (insn & 0x001F0000) >> 16;
          int r1    = (insn & 0x001F0000) >> 16;
          int r2    = (insn & 0x0000F800) >> 11;
          int r2    = (insn & 0x0000F800) >> 11;
          int idx_h = (insn & 0x03E00000) >> 10;
          int idx_h = (insn & 0x03E00000) >> 10;
          int idx   = (insn & 0x000007FF) | idx_h;
          int idx   = (insn & 0x000007FF) | idx_h;
 
 
          if(code == 0x35 && r1 == 1 && r2 == 2)
          if(code == 0x35 && r1 == 1 && r2 == 2)
            {
            {
              offset = idx - frame_size;
              offset = idx - frame_size;
              fp = read_memory_integer (frame->frame + offset, 4);
              fp = read_memory_integer (frame->frame + offset, 4);
            }
            }
        }
        }
    }
    }
 
 
  if (USE_GENERIC_DUMMY_FRAMES)
  if (USE_GENERIC_DUMMY_FRAMES)
    {
    {
      CORE_ADDR fpp, lr;
      CORE_ADDR fpp, lr;
 
 
      lr = read_register (LR_REGNUM);
      lr = read_register (LR_REGNUM);
      if (lr == entry_point_address ())
      if (lr == entry_point_address ())
        if (fp != 0 && (fpp = read_memory_integer (fp, 4)) != 0)
        if (fp != 0 && (fpp = read_memory_integer (fp, 4)) != 0)
          if (PC_IN_CALL_DUMMY (lr, fpp, fpp))
          if (PC_IN_CALL_DUMMY (lr, fpp, fpp))
            return fpp;
            return fpp;
    }
    }
 
 
  return fp;
  return fp;
}
}
 
 
/* The code to store, into a struct frame_saved_regs,
/* The code to store, into a struct frame_saved_regs,
   the addresses of the saved registers of frame described by FRAME_INFO.
   the addresses of the saved registers of frame described by FRAME_INFO.
   This includes special registers such as pc and fp saved in special
   This includes special registers such as pc and fp saved in special
   ways in the stack frame.  sp is even more special:
   ways in the stack frame.  sp is even more special:
   the address we return for it IS the sp for the next frame.  */
   the address we return for it IS the sp for the next frame.  */
void
void
or1k_init_saved_regs (struct frame_info *fi)
or1k_init_saved_regs (struct frame_info *fi)
{
{
  int i;
  int i;
  CORE_ADDR frame_addr;
  CORE_ADDR frame_addr;
  CORE_ADDR func_pc = get_pc_function_start ((fi)->pc) + FUNCTION_START_OFFSET;
  CORE_ADDR func_pc = get_pc_function_start ((fi)->pc) + FUNCTION_START_OFFSET;
  int pc_found = 0;
  int pc_found = 0;
 
 
  frame_saved_regs_zalloc (fi);
  frame_saved_regs_zalloc (fi);
 
 
  /* Skip prologue sets frame_size and register frame save offsets
  /* Skip prologue sets frame_size and register frame save offsets
     which will both be used shortly. */
     which will both be used shortly. */
  or1k_skip_prologue (func_pc, fi);
  or1k_skip_prologue (func_pc, fi);
 
 
  /* If the frame_size is less than 0, we have hit an assembly
  /* 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,
     routine which we can't traverse beyond. Let's give up here,
     because attempting to continue will only lead to trouble. */
     because attempting to continue will only lead to trouble. */
  if(fi->extra_info->frame_size < 0)
  if(fi->extra_info->frame_size < 0)
    {
    {
      printf("Found a function without a prologue at 0x%08x\n",func_pc);
      printf("Found a function without a prologue at 0x%08x\n",func_pc);
      printf("Frame pc was at 0x%08x\n",fi->pc);
      printf("Frame pc was at 0x%08x\n",fi->pc);
      return;
      return;
    }
    }
 
 
  for (i = 0; i < NUM_GPR_REGS + NUM_VF_REGS; i++)
  for (i = 0; i < NUM_GPR_REGS + NUM_VF_REGS; i++)
    if (fi->extra_info->saved_reg_frame_offset[i] >= 0)
    if (fi->extra_info->saved_reg_frame_offset[i] >= 0)
      fi->saved_regs[i] =
      fi->saved_regs[i] =
        fi->frame + (fi->extra_info->saved_reg_frame_offset[i] - fi->extra_info->frame_size);
        fi->frame + (fi->extra_info->saved_reg_frame_offset[i] - fi->extra_info->frame_size);
 
 
  /* We want to make sure we fill in the PC with the value of the
  /* 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
     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
     the correct value of r1 for the next frame, which can be
     calculated by adding the frame_size to the frame pointer. */
     calculated by adding the frame_size to the frame pointer. */
  fi->saved_regs[1] = fi->frame - fi->extra_info->frame_size;
  fi->saved_regs[1] = fi->frame - fi->extra_info->frame_size;
 
 
  if(fi->saved_regs[LR_REGNUM])
  if(fi->saved_regs[LR_REGNUM])
    fi->saved_regs[PC_REGNUM] = read_memory_integer(fi->saved_regs[LR_REGNUM],4);
    fi->saved_regs[PC_REGNUM] = read_memory_integer(fi->saved_regs[LR_REGNUM],4);
  else
  else
    fi->saved_regs[PC_REGNUM] = read_register(LR_REGNUM);
    fi->saved_regs[PC_REGNUM] = read_register(LR_REGNUM);
}
}
 
 
static CORE_ADDR
static CORE_ADDR
read_next_frame_reg (fi, regno)
read_next_frame_reg (fi, regno)
     struct frame_info *fi;
     struct frame_info *fi;
     int regno;
     int regno;
{
{
  for (; fi; fi = fi->next)
  for (; fi; fi = fi->next)
    {
    {
      /* We have to get the saved sp from the sigcontext
      /* We have to get the saved sp from the sigcontext
         if it is a signal handler frame.  */
         if it is a signal handler frame.  */
      if (regno == SP_REGNUM && !fi->signal_handler_caller)
      if (regno == SP_REGNUM && !fi->signal_handler_caller)
        return fi->frame;
        return fi->frame;
      else
      else
        {
        {
          if (fi->saved_regs == NULL)
          if (fi->saved_regs == NULL)
            or1k_init_saved_regs (fi);
            or1k_init_saved_regs (fi);
          if (fi->saved_regs[regno])
          if (fi->saved_regs[regno])
            {
            {
              if(regno == SP_REGNUM || regno == PC_REGNUM)
              if(regno == SP_REGNUM || regno == PC_REGNUM)
                return fi->saved_regs[regno];
                return fi->saved_regs[regno];
              else
              else
                return read_memory_integer (ADDR_BITS_REMOVE (fi->saved_regs[regno]), OR1K_GPR_REGSIZE);
                return read_memory_integer (ADDR_BITS_REMOVE (fi->saved_regs[regno]), OR1K_GPR_REGSIZE);
            }
            }
        }
        }
    }
    }
  return read_register (regno);
  return read_register (regno);
}
}
 
 
/* Find the caller of this frame.  We do this by seeing if 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
   is saved in the stack anywhere, otherwise we get it from the
   registers.  */
   registers.  */
 
 
CORE_ADDR
CORE_ADDR
or1k_frame_saved_pc (fi)
or1k_frame_saved_pc (fi)
     struct frame_info *fi;
     struct frame_info *fi;
{
{
  CORE_ADDR saved_pc;
  CORE_ADDR saved_pc;
 
 
  /* We have to get the saved pc from the sigcontext
  /* We have to get the saved pc from the sigcontext
     if it is a signal handler frame.  */
     if it is a signal handler frame.  */
  if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
  if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
    saved_pc = read_memory_integer (fi->frame, OR1K_GPR_REGSIZE);
    saved_pc = read_memory_integer (fi->frame, OR1K_GPR_REGSIZE);
  else
  else
    saved_pc = read_next_frame_reg (fi, PC_REGNUM);
    saved_pc = read_next_frame_reg (fi, PC_REGNUM);
 
 
  return ADDR_BITS_REMOVE (saved_pc);
  return ADDR_BITS_REMOVE (saved_pc);
}
}
 
 
/* Discard from the stack the innermost frame, restoring all registers.  */
/* Discard from the stack the innermost frame, restoring all registers.  */
 
 
void
void
or1k_pop_frame ()
or1k_pop_frame ()
{
{
  register int regnum;
  register int regnum;
  struct frame_info *frame = get_current_frame ();
  struct frame_info *frame = get_current_frame ();
  CORE_ADDR new_sp = FRAME_FP (frame);
  CORE_ADDR new_sp = FRAME_FP (frame);
 
 
  write_register (PC_REGNUM, FRAME_SAVED_PC (frame));
  write_register (PC_REGNUM, FRAME_SAVED_PC (frame));
  if (frame->saved_regs == NULL)
  if (frame->saved_regs == NULL)
    or1k_init_saved_regs (frame);
    or1k_init_saved_regs (frame);
  for (regnum = 0; regnum < NUM_REGS; regnum++)    {
  for (regnum = 0; regnum < NUM_REGS; regnum++)    {
      if (regnum != SP_REGNUM && regnum != PC_REGNUM
      if (regnum != SP_REGNUM && regnum != PC_REGNUM
          && frame->saved_regs[regnum] >= 0)
          && frame->saved_regs[regnum] >= 0)
        write_register (regnum,
        write_register (regnum,
                        read_memory_integer (frame->saved_regs[regnum],
                        read_memory_integer (frame->saved_regs[regnum],
                                             OR1K_GPR_REGSIZE));
                                             OR1K_GPR_REGSIZE));
    }
    }
  write_register (SP_REGNUM, new_sp);
  write_register (SP_REGNUM, new_sp);
  flush_cached_frames ();
  flush_cached_frames ();
}
}
 
 
CORE_ADDR
CORE_ADDR
or1k_push_arguments (nargs, args, sp, struct_return, struct_addr)
or1k_push_arguments (nargs, args, sp, struct_return, struct_addr)
     int nargs;
     int nargs;
     value_ptr *args;
     value_ptr *args;
     CORE_ADDR sp;
     CORE_ADDR sp;
     int struct_return;
     int struct_return;
     CORE_ADDR struct_addr;
     CORE_ADDR struct_addr;
{
{
  int argreg;
  int argreg;
  int float_argreg;
  int float_argreg;
  int argnum;
  int argnum;
  int len = 0;
  int len = 0;
  int stack_offset = 0;
  int stack_offset = 0;
 
 
  /* Initialize the integer and float register pointers.  */
  /* Initialize the integer and float register pointers.  */
  argreg = A0_REGNUM;
  argreg = A0_REGNUM;
  float_argreg = VFA0_REGNUM;
  float_argreg = VFA0_REGNUM;
 
 
  /* The struct_return pointer occupies the RV value register.  */
  /* The struct_return pointer occupies the RV value register.  */
  if (struct_return)
  if (struct_return)
    write_register (RV_REGNUM, struct_addr);
    write_register (RV_REGNUM, struct_addr);
 
 
  /* Now load as many as possible of the first arguments into
  /* Now load as many as possible of the first arguments into
     registers, and push the rest onto the stack.  Loop thru args
     registers, and push the rest onto the stack.  Loop thru args
     from first to last.  */
     from first to last.  */
  for (argnum = 0; argnum < nargs; argnum++)
  for (argnum = 0; argnum < nargs; argnum++)
    {
    {
      char *val;
      char *val;
      char valbuf[MAX_REGISTER_RAW_SIZE];
      char valbuf[MAX_REGISTER_RAW_SIZE];
      value_ptr arg = args[argnum];
      value_ptr arg = args[argnum];
      struct type *arg_type = check_typedef (VALUE_TYPE (arg));
      struct type *arg_type = check_typedef (VALUE_TYPE (arg));
      int len = TYPE_LENGTH (arg_type);
      int len = TYPE_LENGTH (arg_type);
      enum type_code typecode = TYPE_CODE (arg_type);
      enum type_code typecode = TYPE_CODE (arg_type);
 
 
      /* The EABI passes structures that do not fit in a register by
      /* The EABI passes structures that do not fit in a register by
         reference. In all other cases, pass the structure by value.  */
         reference. In all other cases, pass the structure by value.  */
      if (len > OR1K_GPR_REGSIZE &&
      if (len > OR1K_GPR_REGSIZE &&
          (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION))
          (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION))
        {
        {
          store_address (valbuf, OR1K_GPR_REGSIZE, VALUE_ADDRESS (arg));
          store_address (valbuf, OR1K_GPR_REGSIZE, VALUE_ADDRESS (arg));
          typecode = TYPE_CODE_PTR;
          typecode = TYPE_CODE_PTR;
          len = OR1K_GPR_REGSIZE;
          len = OR1K_GPR_REGSIZE;
          val = valbuf;
          val = valbuf;
        }
        }
      else
      else
        {
        {
          val = (char *) VALUE_CONTENTS (arg);
          val = (char *) VALUE_CONTENTS (arg);
 
 
          if (typecode == TYPE_CODE_FLT
          if (typecode == TYPE_CODE_FLT
              /* Doubles are not stored in regs on 32b target.  */
              /* Doubles are not stored in regs on 32b target.  */
              && len <= OR1K_VF_REGSIZE
              && len <= OR1K_VF_REGSIZE
              && OR1K_VF_PRESENT)
              && OR1K_VF_PRESENT)
            {
            {
              if (float_argreg <= OR1K_LAST_FP_ARG_REGNUM)
              if (float_argreg <= OR1K_LAST_FP_ARG_REGNUM)
                {
                {
                  CORE_ADDR regval = extract_address (val, len);
                  CORE_ADDR regval = extract_address (val, len);
                  write_register (float_argreg++, regval);
                  write_register (float_argreg++, regval);
                }
                }
              else
              else
                {
                {
                  write_memory ((CORE_ADDR) sp, val, OR1K_VF_REGSIZE);
                  write_memory ((CORE_ADDR) sp, val, OR1K_VF_REGSIZE);
                  sp -= OR1K_STACK_ALIGN;
                  sp -= OR1K_STACK_ALIGN;
                }
                }
            }
            }
          else
          else
            {
            {
              if (argreg <= OR1K_LAST_ARG_REGNUM)
              if (argreg <= OR1K_LAST_ARG_REGNUM)
                {
                {
                  CORE_ADDR regval = extract_address (val, len);
                  CORE_ADDR regval = extract_address (val, len);
                  write_register (argreg++, regval);
                  write_register (argreg++, regval);
                }
                }
              else
              else
                {
                {
                  write_memory ((CORE_ADDR) sp, val, OR1K_GPR_REGSIZE);
                  write_memory ((CORE_ADDR) sp, val, OR1K_GPR_REGSIZE);
                  sp -= OR1K_STACK_ALIGN;
                  sp -= OR1K_STACK_ALIGN;
                }
                }
            }
            }
        }
        }
    }
    }
 
 
  /* Return adjusted stack pointer.  */
  /* Return adjusted stack pointer.  */
  return sp;
  return sp;
}
}
 
 
/* Return nonzero when instruction has delay slot.  */
/* Return nonzero when instruction has delay slot.  */
 
 
int
int
is_delayed (insn)
is_delayed (insn)
     unsigned long insn;
     unsigned long insn;
{
{
  int index;
  int index;
  index = insn_decode (insn);
  index = insn_decode (insn);
  return or32_opcodes[index].flags & OR32_IF_DELAY;
  return or32_opcodes[index].flags & OR32_IF_DELAY;
}
}
 
 
int
int
or1k_step_skips_delay (pc)
or1k_step_skips_delay (pc)
     CORE_ADDR pc;
     CORE_ADDR pc;
{
{
  char buf[OR1K_INSTLEN];
  char buf[OR1K_INSTLEN];
 
 
  if (target_read_memory (pc, buf, OR1K_INSTLEN) != 0)
  if (target_read_memory (pc, buf, OR1K_INSTLEN) != 0)
    /* If error reading memory, guess that it is not a delayed branch.  */
    /* If error reading memory, guess that it is not a delayed branch.  */
    return 0;
    return 0;
  return is_delayed ((unsigned long) extract_unsigned_integer (buf, OR1K_INSTLEN));
  return is_delayed ((unsigned long) extract_unsigned_integer (buf, OR1K_INSTLEN));
}
}
 
 
CORE_ADDR
CORE_ADDR
or1k_push_return_address (pc, sp)
or1k_push_return_address (pc, sp)
     CORE_ADDR pc;
     CORE_ADDR pc;
     CORE_ADDR sp;
     CORE_ADDR sp;
{
{
  /* Set the return address register to point to the entry
  /* Set the return address register to point to the entry
     point of the program, where a breakpoint lies in wait.  */
     point of the program, where a breakpoint lies in wait.  */
  write_register (LR_REGNUM, CALL_DUMMY_ADDRESS ());
  write_register (LR_REGNUM, CALL_DUMMY_ADDRESS ());
  return sp;
  return sp;
}
}
 
 
/* Parses args for spr name and puts result into group and index.  */
/* Parses args for spr name and puts result into group and index.  */
 
 
static char *
static char *
parse_spr_params (args, group, index)
parse_spr_params (args, group, index)
                  char *args;
                  char *args;
                  int *group, *index;
                  int *group, *index;
{
{
  *index = -1;
  *index = -1;
  if (args)
  if (args)
    {
    {
      int i;
      int i;
      char *ptr_c;
      char *ptr_c;
 
 
      /* Check if group number was supplied.  */
      /* Check if group number was supplied.  */
      ptr_c = args;
      ptr_c = args;
      while (*ptr_c != ' ' && *ptr_c != 0)
      while (*ptr_c != ' ' && *ptr_c != 0)
        ptr_c++;
        ptr_c++;
      *ptr_c = 0;
      *ptr_c = 0;
 
 
      *group = (int) strtoul (args, &ptr_c, 0);
      *group = (int) strtoul (args, &ptr_c, 0);
      if (*ptr_c != 0)
      if (*ptr_c != 0)
        {
        {
          *group = OR1K_NUM_SPR_GROUPS;
          *group = OR1K_NUM_SPR_GROUPS;
 
 
          /* check for group name */
          /* check for group name */
          for (i = 0; i < OR1K_NUM_SPR_GROUPS; i++)
          for (i = 0; i < OR1K_NUM_SPR_GROUPS; i++)
            if (strcasecmp (or1k_group_names[i], args) == 0)
            if (strcasecmp (or1k_group_names[i], args) == 0)
              {
              {
                *group = i;
                *group = i;
                break;
                break;
              }
              }
 
 
          /* Invalid group => check all register names in all groups.  */
          /* Invalid group => check all register names in all groups.  */
          if (*group >= OR1K_NUM_SPR_GROUPS)
          if (*group >= OR1K_NUM_SPR_GROUPS)
            {
            {
              for (i = 0; i < OR1K_NUM_SPR_GROUPS; i++)
              for (i = 0; i < OR1K_NUM_SPR_GROUPS; i++)
                {
                {
                  int regno;
                  int regno;
                  regno = or1k_regno_from_name (i, args);
                  regno = or1k_regno_from_name (i, args);
                  if (regno >= 0)
                  if (regno >= 0)
                    {
                    {
                      *group = i;
                      *group = i;
                      *index = regno;
                      *index = regno;
                      break;
                      break;
                    }
                    }
                }
                }
            }
            }
        }
        }
      if (*group < 0 || *group >= OR1K_NUM_SPR_GROUPS)
      if (*group < 0 || *group >= OR1K_NUM_SPR_GROUPS)
        error ("Invalid group or register.\n");
        error ("Invalid group or register.\n");
 
 
      if (*index < 0)
      if (*index < 0)
        {
        {
          printf ("a'%s'\n", args);
          printf ("a'%s'\n", args);
          args += strlen(args) + 1;
          args += strlen(args) + 1;
          printf ("b'%s'\n", args);
          printf ("b'%s'\n", args);
          if (*args != 0)
          if (*args != 0)
            {
            {
              ptr_c = args;
              ptr_c = args;
              while (*ptr_c != ' ' && *ptr_c != 0)
              while (*ptr_c != ' ' && *ptr_c != 0)
                ptr_c++;
                ptr_c++;
              *ptr_c = 0;
              *ptr_c = 0;
 
 
              *index = (int) strtoul (args, &ptr_c, 0);
              *index = (int) strtoul (args, &ptr_c, 0);
              if (*ptr_c != 0)
              if (*ptr_c != 0)
                *index = or1k_regno_from_name (*group, args);
                *index = or1k_regno_from_name (*group, args);
            }
            }
 
 
          if (*index < 0)
          if (*index < 0)
            {
            {
              printf_filtered ("No register supplied. Valid registers are:\n");
              printf_filtered ("No register supplied. Valid registers are:\n");
              for (i = 0; i < or1k_spr_valid_aliases[*group]; i++)
              for (i = 0; i < or1k_spr_valid_aliases[*group]; i++)
                {
                {
                  char reg_name[16];
                  char reg_name[16];
                  char *gen_name = or1k_spr_register_name (SPR_REG(*group, i));
                  char *gen_name = or1k_spr_register_name (SPR_REG(*group, i));
                  sprintf (reg_name, "SPR%i_%i", *group, i);
                  sprintf (reg_name, "SPR%i_%i", *group, i);
                  if (strcmp (reg_name, gen_name) != 0)
                  if (strcmp (reg_name, gen_name) != 0)
                    printf_filtered ("%s\t", gen_name);
                    printf_filtered ("%s\t", gen_name);
                }
                }
              printf_filtered ("\n");
              printf_filtered ("\n");
              return args + strlen(args) + 1;
              return args + strlen(args) + 1;
            }
            }
        }
        }
    }
    }
  else
  else
    {
    {
      /* No parameters - print groups */
      /* No parameters - print groups */
      int i;
      int i;
      printf_filtered ("No parameter supplied. Valid groups are:\n");
      printf_filtered ("No parameter supplied. Valid groups are:\n");
      for (i = 0; i < OR1K_NUM_SPR_GROUPS; i++)
      for (i = 0; i < OR1K_NUM_SPR_GROUPS; i++)
        printf_filtered ("%s\t", or1k_group_names[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");
      printf_filtered ("\nSingle register name or register name or number after the group can be also supplied.\n");
      return args;
      return args;
    }
    }
  return args + strlen(args) + 1;
  return args + strlen(args) + 1;
}
}
 
 
/* SPR register info.  */
/* SPR register info.  */
 
 
void
void
info_spr_command (args, from_tty)
info_spr_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  int group, index;
  int group, index;
  parse_spr_params (args, &group, &index);
  parse_spr_params (args, &group, &index);
  if (index >= 0)
  if (index >= 0)
    {
    {
      unsigned long value = or1k_read_spr_reg (SPR_REG(group, index));
      unsigned long value = or1k_read_spr_reg (SPR_REG(group, index));
      printf_unfiltered ("%s.%s = SPR%i_%i = %i(%x)\n", or1k_group_names[group],
      printf_unfiltered ("%s.%s = SPR%i_%i = %i(%x)\n", or1k_group_names[group],
                         or1k_spr_register_name (SPR_REG(group, index)), group, index, value, value);
                         or1k_spr_register_name (SPR_REG(group, index)), group, index, value, value);
    }
    }
}
}
 
 
void
void
info_trace_command (args, from_tty)
info_trace_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  unsigned char i;
  unsigned char i;
  int j;
  int j;
  printf_filtered ("        add      insn     res     time\n");
  printf_filtered ("        add      insn     res     time\n");
  i = or1k_read_spr_reg (SPR_REG(6, 255));
  i = or1k_read_spr_reg (SPR_REG(6, 255));
  for (j = 0; j < 256; j++, i++)
  for (j = 0; j < 256; j++, i++)
    printf_filtered ("%03d %03u %08x %08x %08x %08x\n", 255 - j, i,
    printf_filtered ("%03d %03u %08x %08x %08x %08x\n", 255 - j, i,
                      or1k_read_spr_reg (SPR_REG(6, 0x100 + i)),
                      or1k_read_spr_reg (SPR_REG(6, 0x100 + i)),
                      or1k_read_spr_reg (SPR_REG(6, 0x200 + i)),
                      or1k_read_spr_reg (SPR_REG(6, 0x200 + i)),
                      or1k_read_spr_reg (SPR_REG(6, 0x300 + i)),
                      or1k_read_spr_reg (SPR_REG(6, 0x300 + i)),
                      or1k_read_spr_reg (SPR_REG(6, 0x400 + i)));
                      or1k_read_spr_reg (SPR_REG(6, 0x400 + i)));
 
 
}
}
 
 
/* Set SPR register.  */
/* Set SPR register.  */
 
 
void
void
spr_command (args, from_tty)
spr_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  int group, index;
  int group, index;
  char *nargs = parse_spr_params (args, &group, &index);
  char *nargs = parse_spr_params (args, &group, &index);
  if (index >= 0)
  if (index >= 0)
    {
    {
      unsigned long prev;
      unsigned long prev;
      unsigned long value;
      unsigned long value;
      char *ptr_c;
      char *ptr_c;
 
 
      /* Any arguments left?  */
      /* Any arguments left?  */
      if (args + strlen(args) >= nargs)
      if (args + strlen(args) >= nargs)
        error ("Invalid register value.");
        error ("Invalid register value.");
 
 
      prev = or1k_read_spr_reg (SPR_REG(group, index));
      prev = or1k_read_spr_reg (SPR_REG(group, index));
 
 
      ptr_c = nargs;
      ptr_c = nargs;
      while (*ptr_c != ' ' && *ptr_c != 0)
      while (*ptr_c != ' ' && *ptr_c != 0)
        ptr_c++;
        ptr_c++;
      *ptr_c = 0;
      *ptr_c = 0;
      value = strtoul (nargs, &ptr_c, 0);
      value = strtoul (nargs, &ptr_c, 0);
      if (*ptr_c != 0)
      if (*ptr_c != 0)
                                error ("Invalid register value.");
                                error ("Invalid register value.");
                        or1k_write_spr_reg (SPR_REG(group, index), value);
                        or1k_write_spr_reg (SPR_REG(group, index), value);
      printf_unfiltered ("%s.%s (SPR%i_%i) set to %i(%x), was:%i(%x)\n", or1k_group_names[group],
      printf_unfiltered ("%s.%s (SPR%i_%i) set to %i(%x), was:%i(%x)\n", or1k_group_names[group],
                         or1k_spr_register_name (SPR_REG(group, index)), group, index,
                         or1k_spr_register_name (SPR_REG(group, index)), group, index,
                         value, value, prev, prev);
                         value, value, prev, prev);
    }
    }
}
}
 
 
/* Calls extended command on target.  */
/* Calls extended command on target.  */
 
 
void
void
sim_command (args, from_tty)
sim_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  or1k_sim_cmd (args, from_tty);
  or1k_sim_cmd (args, from_tty);
}
}
 
 
 
 
static union exp_element exp_error;
static union exp_element exp_error;
 
 
/* Parses compare variable and returns it into ct.  */
/* Parses compare variable and returns it into ct.  */
 
 
union exp_element * or1k_parse_ct (exp, ct)
union exp_element * or1k_parse_ct (exp, ct)
     union exp_element *exp;
     union exp_element *exp;
     int *ct;
     int *ct;
{
{
  int i;
  int i;
  if (exp->opcode != OP_INTERNALVAR)
  if (exp->opcode != OP_INTERNALVAR)
    error ("Valid lvalue expected.");
    error ("Valid lvalue expected.");
  exp++;
  exp++;
 
 
  for (i = 1; i < NUM_CT_NAMES; i++)
  for (i = 1; i < NUM_CT_NAMES; i++)
    if (strcasecmp (compare_to_names[i], exp->internalvar->name) == 0) break;
    if (strcasecmp (compare_to_names[i], exp->internalvar->name) == 0) break;
 
 
  if (i >= NUM_CT_NAMES)
  if (i >= NUM_CT_NAMES)
    error ("Invalid compare to operand.");
    error ("Invalid compare to operand.");
  *ct = i;
  *ct = i;
  exp++;
  exp++;
 
 
  if (exp->opcode != OP_INTERNALVAR)
  if (exp->opcode != OP_INTERNALVAR)
    return &exp_error;
    return &exp_error;
  exp++;
  exp++;
  return exp;
  return exp;
}
}
 
 
/* Parses compare value and returns it into cv.  */
/* Parses compare value and returns it into cv.  */
 
 
union exp_element * or1k_parse_cv (exp, cv)
union exp_element * or1k_parse_cv (exp, cv)
     union exp_element *exp;
     union exp_element *exp;
     unsigned int *cv;
     unsigned int *cv;
{
{
  switch (exp->opcode)
  switch (exp->opcode)
    {
    {
    case UNOP_IND:
    case UNOP_IND:
      exp++;
      exp++;
      exp = or1k_parse_cv (exp, cv);
      exp = or1k_parse_cv (exp, cv);
      *cv = or1k_fetch_word (*cv);
      *cv = or1k_fetch_word (*cv);
      break;
      break;
    case OP_LONG:
    case OP_LONG:
      exp += 2;
      exp += 2;
      *cv = exp->longconst;
      *cv = exp->longconst;
      exp += 2;
      exp += 2;
      break;
      break;
    case OP_REGISTER:
    case OP_REGISTER:
      exp++;
      exp++;
      *cv = read_register (exp->longconst);
      *cv = read_register (exp->longconst);
      exp += 2;
      exp += 2;
      break;
      break;
    default:
    default:
      error ("Value expected.");
      error ("Value expected.");
    }
    }
  return exp;
  return exp;
}
}
 
 
/* Parse conditional.
/* Parse conditional.
   Puts freshly allocated array of matchpoints into match.  */
   Puts freshly allocated array of matchpoints into match.  */
 
 
union exp_element *
union exp_element *
or1k_parse_cond (exp, match, nmatch)
or1k_parse_cond (exp, match, nmatch)
     union exp_element *exp;
     union exp_element *exp;
     struct matchpoint **match;
     struct matchpoint **match;
     int *nmatch;
     int *nmatch;
{
{
  unsigned int ct;
  unsigned int ct;
  *match = (struct matchpoint *) malloc (sizeof (struct matchpoint));
  *match = (struct matchpoint *) malloc (sizeof (struct matchpoint));
  *nmatch = 1;
  *nmatch = 1;
  switch (exp->opcode)
  switch (exp->opcode)
    {
    {
    case BINOP_EQUAL:
    case BINOP_EQUAL:
      (*match)->dcr.cc = CC_EQUAL;
      (*match)->dcr.cc = CC_EQUAL;
      break;
      break;
    case BINOP_NOTEQUAL:
    case BINOP_NOTEQUAL:
      (*match)->dcr.cc = CC_NEQUAL;
      (*match)->dcr.cc = CC_NEQUAL;
      break;
      break;
    case BINOP_LESS:
    case BINOP_LESS:
      (*match)->dcr.cc = CC_LESS;
      (*match)->dcr.cc = CC_LESS;
      break;
      break;
    case BINOP_GTR:
    case BINOP_GTR:
      (*match)->dcr.cc = CC_GREAT;
      (*match)->dcr.cc = CC_GREAT;
      break;
      break;
    case BINOP_LEQ:
    case BINOP_LEQ:
      (*match)->dcr.cc = CC_LESSE;
      (*match)->dcr.cc = CC_LESSE;
      break;
      break;
    case BINOP_GEQ:
    case BINOP_GEQ:
      (*match)->dcr.cc = CC_GREATE;
      (*match)->dcr.cc = CC_GREATE;
      break;
      break;
    case BINOP_BITWISE_AND:
    case BINOP_BITWISE_AND:
      (*match)->dcr.cc = CC_MASKED;
      (*match)->dcr.cc = CC_MASKED;
      break;
      break;
    default:
    default:
      return &exp_error;
      return &exp_error;
    }
    }
 
 
  exp++;
  exp++;
  (*match)->dcr.dp = 1;
  (*match)->dcr.dp = 1;
  (*match)->dcr.sc = 0;
  (*match)->dcr.sc = 0;
  if (exp->opcode == OP_INTERNALVAR)
  if (exp->opcode == OP_INTERNALVAR)
    {
    {
      exp = or1k_parse_ct (exp, &ct);
      exp = or1k_parse_ct (exp, &ct);
      exp = or1k_parse_cv (exp, &(*match)->dvr);
      exp = or1k_parse_cv (exp, &(*match)->dvr);
    }
    }
  else
  else
    {
    {
      exp = or1k_parse_cv (exp, &(*match)->dvr);
      exp = or1k_parse_cv (exp, &(*match)->dvr);
      exp = or1k_parse_ct (exp, &ct);
      exp = or1k_parse_ct (exp, &ct);
    }
    }
 
 
  (*match)->dcr.ct = ct;
  (*match)->dcr.ct = ct;
  (*match)->chain_type = CHAINING_NONE;
  (*match)->chain_type = CHAINING_NONE;
  (*match)->cause_breakpoint = 0;
  (*match)->cause_breakpoint = 0;
  return exp;
  return exp;
}
}
 
 
/* Parses expression with && or || operators.
/* Parses expression with && or || operators.
   Puts freshly allocated array of matchpoints into match.
   Puts freshly allocated array of matchpoints into match.
   valid & 1: && is allowed,
   valid & 1: && is allowed,
   valid & 2: || is allowed.  */
   valid & 2: || is allowed.  */
 
 
union exp_element *
union exp_element *
or1k_parse_any (exp, match, nmatch, valid)
or1k_parse_any (exp, match, nmatch, valid)
     union exp_element *exp;
     union exp_element *exp;
     struct matchpoint **match;
     struct matchpoint **match;
     int *nmatch;
     int *nmatch;
     int valid;
     int valid;
{
{
  union exp_element *tmp;
  union exp_element *tmp;
  int first_and_only = 0, first_or_only = 0;
  int first_and_only = 0, first_or_only = 0;
  struct matchpoint *tmp_match1, *tmp_match2, *tmpm;
  struct matchpoint *tmp_match1, *tmp_match2, *tmpm;
  int tmp_nmatch1, tmp_nmatch2, tmpn;
  int tmp_nmatch1, tmp_nmatch2, tmpn;
 
 
  switch (exp->opcode)
  switch (exp->opcode)
    {
    {
    case BINOP_LOGICAL_AND:
    case BINOP_LOGICAL_AND:
      if (!(valid & 1))
      if (!(valid & 1))
        return &exp_error;
        return &exp_error;
      exp++;
      exp++;
 
 
      /* Parse first argument.  */
      /* Parse first argument.  */
      tmp = or1k_parse_any (exp, &tmp_match1, &tmp_nmatch1, 1);
      tmp = or1k_parse_any (exp, &tmp_match1, &tmp_nmatch1, 1);
      if (tmp == &exp_error)
      if (tmp == &exp_error)
        exp = or1k_parse_any (exp, &tmp_match1, &tmp_nmatch1, valid);
        exp = or1k_parse_any (exp, &tmp_match1, &tmp_nmatch1, valid);
      else
      else
        {
        {
          /* and_only successful */
          /* and_only successful */
          exp = tmp;
          exp = tmp;
          first_and_only = 1;
          first_and_only = 1;
        }
        }
      if (exp == &exp_error)
      if (exp == &exp_error)
        return &exp_error;
        return &exp_error;
 
 
      /* Parse second argument.  */
      /* Parse second argument.  */
      if (first_and_only)
      if (first_and_only)
        exp = or1k_parse_any (exp, &tmp_match2, &tmp_nmatch2, valid);
        exp = or1k_parse_any (exp, &tmp_match2, &tmp_nmatch2, valid);
      else
      else
        exp = or1k_parse_any (exp, &tmp_match2, &tmp_nmatch2, 1);
        exp = or1k_parse_any (exp, &tmp_match2, &tmp_nmatch2, 1);
 
 
      if (exp == &exp_error)
      if (exp == &exp_error)
        return &exp_error;
        return &exp_error;
 
 
      if (first_and_only)
      if (first_and_only)
        {
        {
          /* Exchange structures, so that and_only is listed last.  */
          /* Exchange structures, so that and_only is listed last.  */
          struct matchpoint *tmpm = tmp_match1;
          struct matchpoint *tmpm = tmp_match1;
          int tmpn = tmp_nmatch1;
          int tmpn = tmp_nmatch1;
          tmp_match1 = tmp_match2;
          tmp_match1 = tmp_match2;
          tmp_nmatch1 = tmp_nmatch2;
          tmp_nmatch1 = tmp_nmatch2;
          tmp_match2 = tmpm;
          tmp_match2 = tmpm;
          tmp_nmatch2 = tmpn;
          tmp_nmatch2 = tmpn;
        }
        }
 
 
      *nmatch = tmp_nmatch1 + tmp_nmatch2;
      *nmatch = tmp_nmatch1 + tmp_nmatch2;
      *match = (struct matchpoint *)malloc (*nmatch * sizeof (struct matchpoint));
      *match = (struct matchpoint *)malloc (*nmatch * sizeof (struct matchpoint));
      memcpy (*match, tmp_match1, tmp_nmatch1 * sizeof (struct matchpoint));
      memcpy (*match, tmp_match1, tmp_nmatch1 * sizeof (struct matchpoint));
      free (tmp_match1);
      free (tmp_match1);
      tmp_match2[0].chain_type = CHAINING_AND;
      tmp_match2[0].chain_type = CHAINING_AND;
      memcpy (*match + tmp_nmatch1, tmp_match2, tmp_nmatch2 * sizeof (struct matchpoint));
      memcpy (*match + tmp_nmatch1, tmp_match2, tmp_nmatch2 * sizeof (struct matchpoint));
      free (tmp_match2);
      free (tmp_match2);
      return exp;
      return exp;
 
 
    case BINOP_LOGICAL_OR:
    case BINOP_LOGICAL_OR:
      if (!(valid & 2))
      if (!(valid & 2))
        return &exp_error;
        return &exp_error;
      exp++;
      exp++;
 
 
      /* Parse first argument.  */
      /* Parse first argument.  */
      tmp = or1k_parse_any (exp, &tmp_match1, &tmp_nmatch1, 2);
      tmp = or1k_parse_any (exp, &tmp_match1, &tmp_nmatch1, 2);
      if (tmp == &exp_error)
      if (tmp == &exp_error)
        exp = or1k_parse_any (exp, &tmp_match1, &tmp_nmatch1, valid);
        exp = or1k_parse_any (exp, &tmp_match1, &tmp_nmatch1, valid);
      else
      else
        {
        {
          /* and_only successful */
          /* and_only successful */
          exp = tmp;
          exp = tmp;
          first_or_only = 1;
          first_or_only = 1;
        }
        }
      if (exp == &exp_error)
      if (exp == &exp_error)
        return &exp_error;
        return &exp_error;
 
 
      /* Parse second argument.  */
      /* Parse second argument.  */
      if (first_or_only)
      if (first_or_only)
        exp = or1k_parse_any (exp, &tmp_match2, &tmp_nmatch2, valid);
        exp = or1k_parse_any (exp, &tmp_match2, &tmp_nmatch2, valid);
      else
      else
        exp = or1k_parse_any (exp, &tmp_match2, &tmp_nmatch2, 2);
        exp = or1k_parse_any (exp, &tmp_match2, &tmp_nmatch2, 2);
 
 
      if (exp == &exp_error)
      if (exp == &exp_error)
        return &exp_error;
        return &exp_error;
 
 
      if (first_or_only)
      if (first_or_only)
        {
        {
          /* Exchange structures, so that and_only is listed first.  */
          /* Exchange structures, so that and_only is listed first.  */
          struct matchpoint *tmpm = tmp_match1;
          struct matchpoint *tmpm = tmp_match1;
          int tmpn = tmp_nmatch1;
          int tmpn = tmp_nmatch1;
          tmp_match1 = tmp_match2;
          tmp_match1 = tmp_match2;
          tmp_nmatch1 = tmp_nmatch2;
          tmp_nmatch1 = tmp_nmatch2;
          tmp_match2 = tmpm;
          tmp_match2 = tmpm;
          tmp_nmatch2 = tmpn;
          tmp_nmatch2 = tmpn;
        }
        }
 
 
      *nmatch = tmp_nmatch1 + tmp_nmatch2;
      *nmatch = tmp_nmatch1 + tmp_nmatch2;
      *match = (struct matchpoint *)malloc (*nmatch * sizeof (struct matchpoint));
      *match = (struct matchpoint *)malloc (*nmatch * sizeof (struct matchpoint));
      memcpy (*match, tmp_match1, tmp_nmatch1 * sizeof (struct matchpoint));
      memcpy (*match, tmp_match1, tmp_nmatch1 * sizeof (struct matchpoint));
      free (tmp_match1);
      free (tmp_match1);
      tmp_match2[0].chain_type = CHAINING_OR;
      tmp_match2[0].chain_type = CHAINING_OR;
      memcpy (*match + tmp_nmatch1, tmp_match2, tmp_nmatch2 * sizeof (struct matchpoint));
      memcpy (*match + tmp_nmatch1, tmp_match2, tmp_nmatch2 * sizeof (struct matchpoint));
      free (tmp_match2);
      free (tmp_match2);
      return exp;
      return exp;
 
 
    default:
    default:
      return or1k_parse_cond (exp, match, nmatch);
      return or1k_parse_cond (exp, match, nmatch);
    }
    }
}
}
 
 
/* Parses sequence of ||s.
/* Parses sequence of ||s.
   Puts freshly allocated array of matchpoints into match.  */
   Puts freshly allocated array of matchpoints into match.  */
 
 
union exp_element *
union exp_element *
or1k_parse_or (exp, match, nmatch, set_break)
or1k_parse_or (exp, match, nmatch, set_break)
     union exp_element *exp;
     union exp_element *exp;
     struct matchpoint **match;
     struct matchpoint **match;
     int *nmatch;
     int *nmatch;
     int set_break;
     int set_break;
{
{
  struct matchpoint *tmp_match1, *tmp_match2;
  struct matchpoint *tmp_match1, *tmp_match2;
  int tmp_nmatch1, tmp_nmatch2;
  int tmp_nmatch1, tmp_nmatch2;
 
 
  switch (exp->opcode)
  switch (exp->opcode)
    {
    {
    case BINOP_LOGICAL_OR:
    case BINOP_LOGICAL_OR:
      exp++;
      exp++;
      exp = or1k_parse_or (exp, &tmp_match1, &tmp_nmatch1);
      exp = or1k_parse_or (exp, &tmp_match1, &tmp_nmatch1);
      if (exp == &exp_error)
      if (exp == &exp_error)
        return &exp_error;
        return &exp_error;
 
 
      exp = or1k_parse_any (exp, &tmp_match2, &tmp_nmatch2, 3);
      exp = or1k_parse_any (exp, &tmp_match2, &tmp_nmatch2, 3);
      if (set_break)
      if (set_break)
        {
        {
          tmp_match1[tmp_nmatch1 - 1].cause_breakpoint = 1;
          tmp_match1[tmp_nmatch1 - 1].cause_breakpoint = 1;
          tmp_match2[tmp_nmatch2 - 1].cause_breakpoint = 1;
          tmp_match2[tmp_nmatch2 - 1].cause_breakpoint = 1;
        }
        }
      *nmatch = tmp_nmatch1 + tmp_nmatch2;
      *nmatch = tmp_nmatch1 + tmp_nmatch2;
      *match = (struct matchpoint *)malloc (*nmatch * sizeof (struct matchpoint));
      *match = (struct matchpoint *)malloc (*nmatch * sizeof (struct matchpoint));
      memcpy (*match, tmp_match1, tmp_nmatch1 * sizeof (struct matchpoint));
      memcpy (*match, tmp_match1, tmp_nmatch1 * sizeof (struct matchpoint));
      free (tmp_match1);
      free (tmp_match1);
      memcpy (*match + tmp_nmatch1, tmp_match2, tmp_nmatch2 * sizeof (struct matchpoint));
      memcpy (*match + tmp_nmatch1, tmp_match2, tmp_nmatch2 * sizeof (struct matchpoint));
      free (tmp_match2);
      free (tmp_match2);
      return exp;
      return exp;
 
 
    default:
    default:
      return or1k_parse_any (exp, match, nmatch, 3);
      return or1k_parse_any (exp, match, nmatch, 3);
      if (set_break)
      if (set_break)
        (*match)[*nmatch - 1].cause_breakpoint = 1;
        (*match)[*nmatch - 1].cause_breakpoint = 1;
    }
    }
}
}
 
 
/* Prints single matchpoint from specified struct.  */
/* Prints single matchpoint from specified struct.  */
 
 
static void
static void
print_matchpoint_struct (mp)
print_matchpoint_struct (mp)
     struct matchpoint *mp;
     struct matchpoint *mp;
{
{
  printf_filtered ("%-6s (%i) %u, ON=%i, chain_type=%i, cause break=%i\n", compare_to_names[mp->dcr.ct],
  printf_filtered ("%-6s (%i) %u, ON=%i, chain_type=%i, cause break=%i\n", compare_to_names[mp->dcr.ct],
                   mp->dcr.cc, mp->dvr, mp->dcr.dp, mp->chain_type, mp->cause_breakpoint);
                   mp->dcr.cc, mp->dvr, mp->dcr.dp, mp->chain_type, mp->cause_breakpoint);
}
}
 
 
/* Build watchpoint(s) based on given structure.  */
/* Build watchpoint(s) based on given structure.  */
 
 
static void
static void
set_matchpoints (match, nmatch)
set_matchpoints (match, nmatch)
     struct matchpoint *match;
     struct matchpoint *match;
     int nmatch;
     int nmatch;
{
{
  int i;
  int i;
  debug_regs_changed = 1;
  debug_regs_changed = 1;
  sift_matchpoints ();
  sift_matchpoints ();
  for (i = 0; i < nmatch; i++)
  for (i = 0; i < nmatch; i++)
    {
    {
      int num = or1k_implementation.num_used_matchpoints;
      int num = or1k_implementation.num_used_matchpoints;
      dcr[num] = match[i].dcr;
      dcr[num] = match[i].dcr;
      dvr[num] = match[i].dvr;
      dvr[num] = match[i].dvr;
 
 
      /* Set chaining bits.  */
      /* Set chaining bits.  */
      dmr1 &= ~(3 << (2 * num));
      dmr1 &= ~(3 << (2 * num));
      dmr1 |= match[i].chain_type << (2 * num);
      dmr1 |= match[i].chain_type << (2 * num);
 
 
      /* Set watchpoint bits */
      /* Set watchpoint bits */
      dmr2 &= 1 << num;
      dmr2 &= 1 << num;
      dmr2 |= match[i].cause_breakpoint << num;
      dmr2 |= match[i].cause_breakpoint << num;
      matchpoint_user_count[i]++;
      matchpoint_user_count[i]++;
      or1k_implementation.num_used_matchpoints++;
      or1k_implementation.num_used_matchpoints++;
    }
    }
}
}
 
 
/* Returns nonzero, if matchpoints [start .. start+nmatch-1] are
/* Returns nonzero, if matchpoints [start .. start+nmatch-1] are
   equal to match record. */
   equal to match record. */
 
 
static int
static int
matchpoint_matches (start, match, nmatch)
matchpoint_matches (start, match, nmatch)
     int start;
     int start;
     struct matchpoint *match;
     struct matchpoint *match;
     int nmatch;
     int nmatch;
{
{
  int i;
  int i;
  if (nmatch + start >= or1k_implementation.num_matchpoints)
  if (nmatch + start >= or1k_implementation.num_matchpoints)
    return 0;
    return 0;
 
 
  for (i = 0; i < nmatch; i++)
  for (i = 0; i < nmatch; i++)
    {
    {
      int j = i + start;
      int j = i + start;
 
 
      /* Everything exept cause breakpoint must match.  */
      /* Everything exept cause breakpoint must match.  */
      if (dcr[j].dp != match[i].dcr.dp
      if (dcr[j].dp != match[i].dcr.dp
          || dcr[j].ct != match[i].dcr.ct
          || dcr[j].ct != match[i].dcr.ct
          || dcr[j].cc != match[i].dcr.cc
          || dcr[j].cc != match[i].dcr.cc
          || dcr[j].sc != match[i].dcr.sc
          || dcr[j].sc != match[i].dcr.sc
          || dvr[j] != match[i].dvr
          || dvr[j] != match[i].dvr
          || match[i].chain_type != (dmr1 >> (2 * j)) & 3)
          || match[i].chain_type != (dmr1 >> (2 * j)) & 3)
        return 0;
        return 0;
    }
    }
  return 1;
  return 1;
}
}
 
 
static void
static void
hwatch_command (arg, from_tty)
hwatch_command (arg, from_tty)
     char *arg;
     char *arg;
     int from_tty;
     int from_tty;
{
{
  struct expression *exp;
  struct expression *exp;
  int i, nfree, nmatch, remove = 0;
  int i, nfree, nmatch, remove = 0;
  struct matchpoint *match;
  struct matchpoint *match;
 
 
  if (arg == NULL)
  if (arg == NULL)
    arg = "";
    arg = "";
  if (strncasecmp ("remove ", arg, 7) == 0)
  if (strncasecmp ("remove ", arg, 7) == 0)
    {
    {
      arg += 7;
      arg += 7;
      remove = 1;
      remove = 1;
    }
    }
 
 
  /* Parse arguments.  */
  /* Parse arguments.  */
  exp = parse_exp_1 (&arg, 0, 0);
  exp = parse_exp_1 (&arg, 0, 0);
 
 
#ifdef DEBUG
#ifdef DEBUG
  dump_prefix_expression (exp, gdb_stdout, "expr1");
  dump_prefix_expression (exp, gdb_stdout, "expr1");
#endif  
#endif  
 
 
  if (or1k_parse_or (&exp->elts[0], &match, &nmatch, 1) == &exp_error)
  if (or1k_parse_or (&exp->elts[0], &match, &nmatch, 1) == &exp_error)
    error ("Watchpoint too complex.");
    error ("Watchpoint too complex.");
 
 
  for (i = 0; i < nmatch; i++)
  for (i = 0; i < nmatch; i++)
    print_matchpoint_struct (&match[i]);
    print_matchpoint_struct (&match[i]);
 
 
  if (remove)
  if (remove)
    {
    {
      int start = -1;
      int start = -1;
      int cleared = 0;
      int cleared = 0;
 
 
      if (num_hw_watches <= 0)
      if (num_hw_watches <= 0)
        error ("No extended hardware supported watchpoints present.");
        error ("No extended hardware supported watchpoints present.");
 
 
      for (i = 0; i < num_hw_watches; i++)
      for (i = 0; i < num_hw_watches; i++)
        if (matchpoint_matches (or1k_hwatch[i].matchpoint_start, match, nmatch))
        if (matchpoint_matches (or1k_hwatch[i].matchpoint_start, match, nmatch))
          {
          {
            start = or1k_hwatch[i].matchpoint_start;
            start = or1k_hwatch[i].matchpoint_start;
            break;
            break;
          }
          }
 
 
      if (start < 0)
      if (start < 0)
        error ("Watchpoint not found.");
        error ("Watchpoint not found.");
 
 
      for (i = 0; i < nmatch; i++)
      for (i = 0; i < nmatch; i++)
        {
        {
          int j = start + i;
          int j = start + i;
          if (--matchpoint_user_count[j] <= 0)
          if (--matchpoint_user_count[j] <= 0)
            {
            {
              debug_regs_changed = 1;
              debug_regs_changed = 1;
              memset (&dcr[j], 0, sizeof (dcr[j]));
              memset (&dcr[j], 0, sizeof (dcr[j]));
              or1k_implementation.num_used_matchpoints--;
              or1k_implementation.num_used_matchpoints--;
              cleared = 1;
              cleared = 1;
            }
            }
        }
        }
      if (!cleared)
      if (!cleared)
        warning ("No matchpoint(s) freed. Resources are busy.");
        warning ("No matchpoint(s) freed. Resources are busy.");
    }
    }
  else
  else
    {
    {
      if (num_hw_watches >= MAX_HW_WATCHES)
      if (num_hw_watches >= MAX_HW_WATCHES)
        error ("Number of watchpoints too large.");
        error ("Number of watchpoints too large.");
 
 
      /* Now we have to find out if given prefix expression matches
      /* Now we have to find out if given prefix expression matches
         our HW based support. It may take up to
         our HW based support. It may take up to
         or1k_implementation.num_matchpoints - or1k_implementation.num_used_matchpoints. */
         or1k_implementation.num_matchpoints - or1k_implementation.num_used_matchpoints. */
      nfree = or1k_implementation.num_matchpoints - or1k_implementation.num_used_matchpoints;
      nfree = or1k_implementation.num_matchpoints - or1k_implementation.num_used_matchpoints;
 
 
      if (nmatch > nfree)
      if (nmatch > nfree)
        error ("Not enough free matchpoint resources.");
        error ("Not enough free matchpoint resources.");
 
 
      /* Build watchpoint(s) based on just built structure.  */
      /* Build watchpoint(s) based on just built structure.  */
      or1k_hwatch[num_hw_watches].matchpoint_start = or1k_implementation.num_used_matchpoints;
      or1k_hwatch[num_hw_watches].matchpoint_start = or1k_implementation.num_used_matchpoints;
      set_matchpoints (match, nmatch);
      set_matchpoints (match, nmatch);
      num_hw_watches++;
      num_hw_watches++;
      printf_unfiltered ("Watchpoint successfully allocated.\n");
      printf_unfiltered ("Watchpoint successfully allocated.\n");
    }
    }
  free (match);
  free (match);
  free (exp);
  free (exp);
}
}
 
 
static void
static void
htrace_command (args, from_tty)
htrace_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  help_list (htrace_cmdlist, "htrace ", all_commands, gdb_stdout);
  help_list (htrace_cmdlist, "htrace ", all_commands, gdb_stdout);
}
}
 
 
static void
static void
htrace_mode_command (args, from_tty)
htrace_mode_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  help_list (htrace_mode_cmdlist, "htrace mode ", all_commands, gdb_stdout);
  help_list (htrace_mode_cmdlist, "htrace mode ", all_commands, gdb_stdout);
}
}
 
 
static void
static void
htrace_mode_contin_command (args, from_tty)
htrace_mode_contin_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  or1k_htrace.moder.contin = 1;
  or1k_htrace.moder.contin = 1;
  printf_unfiltered ("Continuous trace mode set.\n");
  printf_unfiltered ("Continuous trace mode set.\n");
}
}
 
 
static void
static void
htrace_mode_suspend_command (args, from_tty)
htrace_mode_suspend_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  or1k_htrace.moder.contin = 0;
  or1k_htrace.moder.contin = 0;
  printf_unfiltered ("Suspend trace mode set.\n");
  printf_unfiltered ("Suspend trace mode set.\n");
}
}
 
 
static void print_event_struct (event, stop)
static void print_event_struct (event, stop)
     struct htrace_event_struct *event;
     struct htrace_event_struct *event;
     int stop;
     int stop;
{
{
  int i;
  int i;
  if (event->operation == TRIGOP_ANY)
  if (event->operation == TRIGOP_ANY)
    if (stop)
    if (stop)
      printf_filtered ("not active");
      printf_filtered ("not active");
    else
    else
      printf_filtered ("always active");
      printf_filtered ("always active");
  else
  else
    {
    {
      char *comma;
      char *comma;
      if (event->operation == TRIGOP_AND)
      if (event->operation == TRIGOP_AND)
        comma = "&(";
        comma = "&(";
      else
      else
        comma = "|(";
        comma = "|(";
 
 
      if (event->is_valid)
      if (event->is_valid)
        {
        {
          printf_filtered ("%s%s", comma, or1k_is_names[event->is_trig]);
          printf_filtered ("%s%s", comma, or1k_is_names[event->is_trig]);
          comma = ", ";
          comma = ", ";
        }
        }
      if (event->ls_valid)
      if (event->ls_valid)
        {
        {
          printf_filtered ("%s%s", comma, or1k_ls_names[event->ls_trig]);
          printf_filtered ("%s%s", comma, or1k_ls_names[event->ls_trig]);
          comma = ", ";
          comma = ", ";
        }
        }
      if (event->bp_valid)
      if (event->bp_valid)
        {
        {
          printf_filtered ("%sbreak", comma);
          printf_filtered ("%sbreak", comma);
          comma = ", ";
          comma = ", ";
        }
        }
      if (event->wp_valid)
      if (event->wp_valid)
        for (i = 0; i < 11; i++)
        for (i = 0; i < 11; i++)
          if ((event->wp_trig >> i) & 1)
          if ((event->wp_trig >> i) & 1)
            {
            {
              printf_filtered ("%sWP%i", comma, i);
              printf_filtered ("%sWP%i", comma, i);
              comma = ", ";
              comma = ", ";
            }
            }
      if (comma[0] == ',')
      if (comma[0] == ',')
        printf_filtered (")");
        printf_filtered (")");
      else
      else
        printf_filtered ("not active");
        printf_filtered ("not active");
    }
    }
}
}
 
 
static void
static void
print_record_struct (record)
print_record_struct (record)
     struct htrace_record_struct *record;
     struct htrace_record_struct *record;
{
{
  int i;
  int i;
  char *comma = "";
  char *comma = "";
  for (i = 0; i < MAX_RECORD_NAMES; i++)
  for (i = 0; i < MAX_RECORD_NAMES; i++)
    {
    {
      if ((record->rec >> i)&1)
      if ((record->rec >> i)&1)
        {
        {
          printf_filtered ("%s%s", comma, or1k_record_names[i]);
          printf_filtered ("%s%s", comma, or1k_record_names[i]);
          comma = ", ";
          comma = ", ";
        }
        }
    }
    }
  if (!*comma)
  if (!*comma)
    printf_unfiltered ("none");
    printf_unfiltered ("none");
}
}
 
 
static void
static void
htrace_info_command (args, from_tty)
htrace_info_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  int i;
  int i;
  printf_filtered ("Trace trigger: ");
  printf_filtered ("Trace trigger: ");
  print_event_struct (&or1k_htrace.trig, 0);
  print_event_struct (&or1k_htrace.trig, 0);
  printf_filtered ("\nTrace qualifier: ");
  printf_filtered ("\nTrace qualifier: ");
  print_event_struct (&or1k_htrace.qual, 0);
  print_event_struct (&or1k_htrace.qual, 0);
  for (i = 0; i < MAX_MATCHPOINTS; i++)
  for (i = 0; i < MAX_MATCHPOINTS; i++)
    {
    {
      printf_filtered ("\n WP%i records: ", i);
      printf_filtered ("\n WP%i records: ", i);
      print_record_struct (&or1k_htrace.recwp[i]);
      print_record_struct (&or1k_htrace.recwp[i]);
    }
    }
  printf_filtered ("\n BP records: ");
  printf_filtered ("\n BP records: ");
  print_record_struct (&or1k_htrace.recbp);
  print_record_struct (&or1k_htrace.recbp);
  printf_filtered ("\nTrace stop: ");
  printf_filtered ("\nTrace stop: ");
  print_event_struct (&or1k_htrace.stop, 1);
  print_event_struct (&or1k_htrace.stop, 1);
  printf_filtered ("\n");
  printf_filtered ("\n");
}
}
 
 
/* Parses event from given string.
/* Parses event from given string.
   Result is placed into event structure, and previously allocated
   Result is placed into event structure, and previously allocated
   resources are freed.  Parameter stop is nonzero, when we are parsing
   resources are freed.  Parameter stop is nonzero, when we are parsing
   for stop criteria.  */
   for stop criteria.  */
 
 
static void
static void
parse_event (args, event, stop)
parse_event (args, event, stop)
     char *args;
     char *args;
     struct htrace_event_struct *event;
     struct htrace_event_struct *event;
     int stop;
     int stop;
{
{
  int i, op_type = 0, was_last_op = 1, any = 0;
  int i, op_type = 0, was_last_op = 1, any = 0;
 
 
  /* Release previous resources.  */
  /* Release previous resources.  */
  for (i = 0; i < MAX_MATCHPOINTS; i++)
  for (i = 0; i < MAX_MATCHPOINTS; i++)
    {
    {
      if ((event->wp_trig << i) & 1)
      if ((event->wp_trig << i) & 1)
        if (--matchpoint_user_count[i] <= 0)
        if (--matchpoint_user_count[i] <= 0)
          {
          {
            memset (&dcr[i], 0, sizeof (dcr[i]));
            memset (&dcr[i], 0, sizeof (dcr[i]));
            debug_regs_changed = 1;
            debug_regs_changed = 1;
            or1k_implementation.num_used_matchpoints--;
            or1k_implementation.num_used_matchpoints--;
          }
          }
    }
    }
 
 
  event->is_valid = event->is_trig = 0;
  event->is_valid = event->is_trig = 0;
  event->ls_valid = event->ls_trig = 0;
  event->ls_valid = event->ls_trig = 0;
  event->bp_valid = event->bp_trig = 0;
  event->bp_valid = event->bp_trig = 0;
  event->wp_valid = event->wp_trig = 0;
  event->wp_valid = event->wp_trig = 0;
 
 
  if (args == NULL)
  if (args == NULL)
    args = "";
    args = "";
  while (*args == ' ')
  while (*args == ' ')
    args++;
    args++;
 
 
  while (*args != '\0')
  while (*args != '\0')
    {
    {
      if (strncasecmp ("breakpoint", args, 10) == 0)
      if (strncasecmp ("breakpoint", args, 10) == 0)
        {
        {
          if (!was_last_op)
          if (!was_last_op)
            error ("Syntax error.");
            error ("Syntax error.");
          was_last_op = 0;
          was_last_op = 0;
          event->bp_valid = event->bp_trig = 1;
          event->bp_valid = event->bp_trig = 1;
        }
        }
      else if (!stop && strncasecmp ("any", args, 3) == 0
      else if (!stop && strncasecmp ("any", args, 3) == 0
               || stop && strncasecmp ("none", args, 4) == 0)
               || stop && strncasecmp ("none", args, 4) == 0)
        {
        {
          if (!was_last_op)
          if (!was_last_op)
            error ("Syntax error.");
            error ("Syntax error.");
          was_last_op = 0;
          was_last_op = 0;
          any = 1;
          any = 1;
        }
        }
      else if (strncasecmp ("||", args, 2) == 0)
      else if (strncasecmp ("||", args, 2) == 0)
        {
        {
          if (op_type == TRIGOP_AND)
          if (op_type == TRIGOP_AND)
            error ("Only one type of logical operator allowed at a time.");
            error ("Only one type of logical operator allowed at a time.");
          op_type = TRIGOP_OR;
          op_type = TRIGOP_OR;
          if (was_last_op)
          if (was_last_op)
            error ("Syntax error.");
            error ("Syntax error.");
          was_last_op = 1;
          was_last_op = 1;
          args += 2;
          args += 2;
        }
        }
      else if (strncasecmp ("&&", args, 2) == 0)
      else if (strncasecmp ("&&", args, 2) == 0)
        {
        {
          if (op_type == TRIGOP_OR)
          if (op_type == TRIGOP_OR)
            error ("Only one type of logical operator allowed at a time.");
            error ("Only one type of logical operator allowed at a time.");
          op_type = TRIGOP_AND;
          op_type = TRIGOP_AND;
          if (was_last_op)
          if (was_last_op)
            error ("Syntax error.");
            error ("Syntax error.");
          was_last_op = 1;
          was_last_op = 1;
          args += 2;
          args += 2;
        }
        }
      else
      else
        {
        {
          int found = 0;
          int found = 0;
          if (!was_last_op)
          if (!was_last_op)
            error ("Syntax error.");
            error ("Syntax error.");
          was_last_op = 0;
          was_last_op = 0;
 
 
          /* Search through is and ls tables for a match.  */
          /* Search through is and ls tables for a match.  */
          for (i = 0; i < MAX_IS_NAMES; i++)
          for (i = 0; i < MAX_IS_NAMES; i++)
            if (strncasecmp (args, or1k_is_names[i], strlen (or1k_is_names[i])) == 0)
            if (strncasecmp (args, or1k_is_names[i], strlen (or1k_is_names[i])) == 0)
              {
              {
                event->is_valid = 1;
                event->is_valid = 1;
                event->is_trig = i;
                event->is_trig = i;
                args +=  strlen (or1k_is_names[i]);
                args +=  strlen (or1k_is_names[i]);
                found = 1;
                found = 1;
                break;
                break;
              }
              }
          if (!found)
          if (!found)
            {
            {
              for (i = 0; i < MAX_LS_NAMES; i++)
              for (i = 0; i < MAX_LS_NAMES; i++)
                if (strncasecmp (args, or1k_ls_names[i], strlen (or1k_ls_names[i])) == 0)
                if (strncasecmp (args, or1k_ls_names[i], strlen (or1k_ls_names[i])) == 0)
                  {
                  {
                    event->ls_valid = 1;
                    event->ls_valid = 1;
                    event->ls_trig = i;
                    event->ls_trig = i;
                    args +=  strlen (or1k_ls_names[i]);
                    args +=  strlen (or1k_ls_names[i]);
                    found = 1;
                    found = 1;
                    break;
                    break;
                  }
                  }
            }
            }
          if (!found)
          if (!found)
            {
            {
              /* No special name was found => parse expression.  */
              /* No special name was found => parse expression.  */
              struct expression *exp;
              struct expression *exp;
              struct matchpoint *match;
              struct matchpoint *match;
              int nmatch, nfree;
              int nmatch, nfree;
 
 
              exp = parse_exp_1 (&args, 0, 0);
              exp = parse_exp_1 (&args, 0, 0);
 
 
              if (or1k_parse_any (&exp->elts[0], &match, &nmatch, 3) == &exp_error)
              if (or1k_parse_any (&exp->elts[0], &match, &nmatch, 3) == &exp_error)
                error ("Expression too complex.");
                error ("Expression too complex.");
              for (i = 0; i < nmatch; i++)
              for (i = 0; i < nmatch; i++)
                print_matchpoint_struct (&match[i]);
                print_matchpoint_struct (&match[i]);
 
 
              /* Now we have to find out if given prefix expression matches
              /* Now we have to find out if given prefix expression matches
                 our HW based support. It may take up to
                 our HW based support. It may take up to
                 or1k_implementation.num_matchpoints - or1k_implementation.num_used_matchpoints. */
                 or1k_implementation.num_matchpoints - or1k_implementation.num_used_matchpoints. */
              nfree = or1k_implementation.num_matchpoints - or1k_implementation.num_used_matchpoints;
              nfree = or1k_implementation.num_matchpoints - or1k_implementation.num_used_matchpoints;
 
 
              if (nmatch > nfree)
              if (nmatch > nfree)
                error ("Not enough free matchpoint resources.");
                error ("Not enough free matchpoint resources.");
 
 
              /* Build matchpoint(s) based on just built structure.  */
              /* Build matchpoint(s) based on just built structure.  */
              set_matchpoints (match, nmatch);
              set_matchpoints (match, nmatch);
              event->wp_valid = 1;
              event->wp_valid = 1;
              event->wp_trig |= 1 << (or1k_implementation.num_used_matchpoints - 1);
              event->wp_trig |= 1 << (or1k_implementation.num_used_matchpoints - 1);
              printf_unfiltered ("Watchpoint successfully allocated.\n");
              printf_unfiltered ("Watchpoint successfully allocated.\n");
              free (match);
              free (match);
              free (exp);
              free (exp);
              found = 1;
              found = 1;
            }
            }
          if (!found)
          if (!found)
            warning ("Invalid event at '%s'", args);
            warning ("Invalid event at '%s'", args);
        }
        }
      while (*args == ' ') args++;
      while (*args == ' ') args++;
    }
    }
  if (any)
  if (any)
    event->operation = TRIGOP_ANY;
    event->operation = TRIGOP_ANY;
  else
  else
    {
    {
      if (op_type == 0)
      if (op_type == 0)
        op_type = TRIGOP_AND;
        op_type = TRIGOP_AND;
      event->operation = op_type;
      event->operation = op_type;
    }
    }
}
}
 
 
static void
static void
htrace_trigger_command (args, from_tty)
htrace_trigger_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  parse_event (args, &or1k_htrace.trig, 0);
  parse_event (args, &or1k_htrace.trig, 0);
  printf_filtered ("Trace starts, when:\n");
  printf_filtered ("Trace starts, when:\n");
  print_event_struct (&or1k_htrace.trig, 0);
  print_event_struct (&or1k_htrace.trig, 0);
  printf_filtered ("\n");
  printf_filtered ("\n");
}
}
 
 
static void
static void
htrace_qualifier_command (args, from_tty)
htrace_qualifier_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  parse_event (args, &or1k_htrace.qual, 0);
  parse_event (args, &or1k_htrace.qual, 0);
  printf_filtered ("Trace records, when:\n");
  printf_filtered ("Trace records, when:\n");
  print_event_struct (&or1k_htrace.qual, 0);
  print_event_struct (&or1k_htrace.qual, 0);
  printf_filtered ("\n");
  printf_filtered ("\n");
}
}
 
 
static void
static void
htrace_stop_command (args, from_tty)
htrace_stop_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  parse_event (args, &or1k_htrace.stop, 1);
  parse_event (args, &or1k_htrace.stop, 1);
  printf_filtered ("Trace stops, when:\n");
  printf_filtered ("Trace stops, when:\n");
  print_event_struct (&or1k_htrace.stop, 1);
  print_event_struct (&or1k_htrace.stop, 1);
  printf_filtered ("\n");
  printf_filtered ("\n");
}
}
 
 
static void
static void
htrace_clear_records_command (args, from_tty)
htrace_clear_records_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  int i, j, cleared = 0;
  int i, j, cleared = 0;
 
 
  /* Clear all. */
  /* Clear all. */
  for (i = 0; i < MAX_MATCHPOINTS; i++)
  for (i = 0; i < MAX_MATCHPOINTS; i++)
    {
    {
      for (j = 0; j < MAX_MATCHPOINTS; j++)
      for (j = 0; j < MAX_MATCHPOINTS; j++)
        {
        {
          if ((or1k_htrace.wp_record_uses[i] << j) & 1)
          if ((or1k_htrace.wp_record_uses[i] << j) & 1)
            if (--matchpoint_user_count[j] <= 0)
            if (--matchpoint_user_count[j] <= 0)
            {
            {
              memset (&dcr[j], 0, sizeof (dcr[j]));
              memset (&dcr[j], 0, sizeof (dcr[j]));
              debug_regs_changed = 1;
              debug_regs_changed = 1;
              cleared = 1;
              cleared = 1;
              or1k_implementation.num_used_matchpoints--;
              or1k_implementation.num_used_matchpoints--;
            }
            }
        }
        }
      or1k_htrace.wp_record_uses[i] = 0;
      or1k_htrace.wp_record_uses[i] = 0;
    }
    }
  if (!cleared)
  if (!cleared)
    warning ("No matchpoints freed. Resources are busy.");
    warning ("No matchpoints freed. Resources are busy.");
}
}
 
 
/* Syntax: htrace record {data}* when {expr} */
/* Syntax: htrace record {data}* when {expr} */
 
 
static void
static void
htrace_record_command (args, from_tty)
htrace_record_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  struct expression *exp;
  struct expression *exp;
  int i, nfree, nmatch, wp;
  int i, nfree, nmatch, wp;
  struct matchpoint *match;
  struct matchpoint *match;
  unsigned int recdata = 0;
  unsigned int recdata = 0;
  char *c;
  char *c;
 
 
  if (args == '\0')
  if (args == '\0')
    error ( "Please specify data to record, e.g.:\n"
    error ( "Please specify data to record, e.g.:\n"
            "htrace record PC SDATA when $SEA == 100\n"
            "htrace record PC SDATA when $SEA == 100\n"
            "htrace record when $SEA == 100 to remove record");
            "htrace record when $SEA == 100 to remove record");
 
 
  for (i = 0; *args != '\0' && strncasecmp ("when ", args, 5); i++)
  for (i = 0; *args != '\0' && strncasecmp ("when ", args, 5); i++)
    {
    {
      int j, found = 0;
      int j, found = 0;
      for (j = 0; j < MAX_RECORD_NAMES; j++)
      for (j = 0; j < MAX_RECORD_NAMES; j++)
        if (strncasecmp (args, or1k_record_names[j], strlen (or1k_record_names[j])) == 0)
        if (strncasecmp (args, or1k_record_names[j], strlen (or1k_record_names[j])) == 0)
          {
          {
            recdata |= 1 << j;
            recdata |= 1 << j;
            found = 1;
            found = 1;
            break;
            break;
          }
          }
      if (!found)
      if (!found)
        warning ("Invalid record data name at '%s'.", args);
        warning ("Invalid record data name at '%s'.", args);
      while (*args != ' ' && *args != '\0') args++;
      while (*args != ' ' && *args != '\0') args++;
      while (*args == ' ') args++;
      while (*args == ' ') args++;
    }
    }
 
 
  if (strncasecmp ("when ", args, 5) != 0)
  if (strncasecmp ("when ", args, 5) != 0)
    if (*args == '\0')
    if (*args == '\0')
      {
      {
        warning ("Condition not set. Assuming breakpoint.");
        warning ("Condition not set. Assuming breakpoint.");
        wp = -1;
        wp = -1;
      }
      }
    else
    else
      error ("Syntax error.");
      error ("Syntax error.");
  else
  else
    {
    {
      args += 5;
      args += 5;
      if (strcasecmp ("breakpoint", args) == 0)
      if (strcasecmp ("breakpoint", args) == 0)
        wp = -1;
        wp = -1;
      else
      else
        {
        {
          /* Parse arguments.  */
          /* Parse arguments.  */
          exp = parse_exp_1 (&args, 0, 0);
          exp = parse_exp_1 (&args, 0, 0);
 
 
#ifdef DEBUG
#ifdef DEBUG
          dump_prefix_expression (exp, gdb_stdout, "expr1");
          dump_prefix_expression (exp, gdb_stdout, "expr1");
#endif
#endif
          if (or1k_parse_any (&exp->elts[0], &match, &nmatch, 3) == &exp_error)
          if (or1k_parse_any (&exp->elts[0], &match, &nmatch, 3) == &exp_error)
            error ("Expression too complex.");
            error ("Expression too complex.");
 
 
          for (i = 0; i < nmatch; i++)
          for (i = 0; i < nmatch; i++)
            print_matchpoint_struct (&match[i]);
            print_matchpoint_struct (&match[i]);
 
 
          if (recdata)
          if (recdata)
            {
            {
              /* Now we have to find out if given prefix expression matches
              /* Now we have to find out if given prefix expression matches
                 our HW based support. It may take up to
                 our HW based support. It may take up to
                 or1k_implementation.num_matchpoints - or1k_implementation.num_used_matchpoints. */
                 or1k_implementation.num_matchpoints - or1k_implementation.num_used_matchpoints. */
              nfree = or1k_implementation.num_matchpoints - or1k_implementation.num_used_matchpoints;
              nfree = or1k_implementation.num_matchpoints - or1k_implementation.num_used_matchpoints;
 
 
              if (nmatch > nfree)
              if (nmatch > nfree)
                error ("Not enough free matchpoint resources.");
                error ("Not enough free matchpoint resources.");
 
 
              wp = or1k_implementation.num_used_matchpoints - 1;
              wp = or1k_implementation.num_used_matchpoints - 1;
              or1k_htrace.wp_record_uses[wp] = 0;
              or1k_htrace.wp_record_uses[wp] = 0;
              for (i = or1k_implementation.num_used_matchpoints; i <= wp; i++)
              for (i = or1k_implementation.num_used_matchpoints; i <= wp; i++)
                or1k_htrace.wp_record_uses[wp] |= 1 << i;
                or1k_htrace.wp_record_uses[wp] |= 1 << i;
              set_matchpoints (match, nmatch);
              set_matchpoints (match, nmatch);
            }
            }
          else
          else
            {
            {
              /* Remove record. */
              /* Remove record. */
              int start = -1, cleared = 0;
              int start = -1, cleared = 0;
 
 
              for (i = 0; i < MAX_MATCHPOINTS; i++)
              for (i = 0; i < MAX_MATCHPOINTS; i++)
                {
                {
                  int mp_start = 0, j;
                  int mp_start = 0, j;
                  j = or1k_htrace.wp_record_uses[i];
                  j = or1k_htrace.wp_record_uses[i];
                  while (j > 0 && j & 1 == 0)
                  while (j > 0 && j & 1 == 0)
                    mp_start++;
                    mp_start++;
 
 
                  if (matchpoint_matches (mp_start, match, nmatch))
                  if (matchpoint_matches (mp_start, match, nmatch))
                    {
                    {
                      start = mp_start;
                      start = mp_start;
                      or1k_htrace.wp_record_uses[i] = 0;
                      or1k_htrace.wp_record_uses[i] = 0;
                      break;
                      break;
                    }
                    }
                }
                }
              if (start < 0)
              if (start < 0)
                error ("Record with such expression not found.");
                error ("Record with such expression not found.");
 
 
              for (i = 0; i < nmatch; i++)
              for (i = 0; i < nmatch; i++)
                {
                {
                  int j = i + start;
                  int j = i + start;
                  if (--matchpoint_user_count[j] <= 0)
                  if (--matchpoint_user_count[j] <= 0)
                    {
                    {
                      memset (&dcr[j], 0, sizeof (dcr[j]));
                      memset (&dcr[j], 0, sizeof (dcr[j]));
                      debug_regs_changed = 1;
                      debug_regs_changed = 1;
                      cleared = 1;
                      cleared = 1;
                    }
                    }
                }
                }
              if (!cleared)
              if (!cleared)
                warning ("No matchpoint(s) freed.");
                warning ("No matchpoint(s) freed.");
            }
            }
        }
        }
    }
    }
 
 
  /* If we reached this point we have matchpoints set, and wp
  /* If we reached this point we have matchpoints set, and wp
     holds the value of that watchpoint.  wp == -1, if breakpoint
     holds the value of that watchpoint.  wp == -1, if breakpoint
     was specified.  */
     was specified.  */
  if (wp < 0)
  if (wp < 0)
    or1k_htrace.recbp.rec = recdata;
    or1k_htrace.recbp.rec = recdata;
  else
  else
    or1k_htrace.recwp[wp].rec = recdata;
    or1k_htrace.recwp[wp].rec = recdata;
 
 
  if (recdata)
  if (recdata)
    {
    {
      printf_unfiltered ("Data");
      printf_unfiltered ("Data");
      for (i = 0; i < MAX_RECORD_NAMES; i++)
      for (i = 0; i < MAX_RECORD_NAMES; i++)
        if ((recdata >> i) & 1)
        if ((recdata >> i) & 1)
          printf_unfiltered (" %s,", or1k_record_names[i]);
          printf_unfiltered (" %s,", or1k_record_names[i]);
    }
    }
  else
  else
    printf_unfiltered ("No data");
    printf_unfiltered ("No data");
  if (wp < 0)
  if (wp < 0)
    printf_unfiltered (" will be recorded when breakpoint occurs\n");
    printf_unfiltered (" will be recorded when breakpoint occurs\n");
  else
  else
    printf_unfiltered (" will be recorded when watchpoint #%i occurs\n", wp);
    printf_unfiltered (" will be recorded when watchpoint #%i occurs\n", wp);
}
}
 
 
static void
static void
htrace_enable_command (args, from_tty)
htrace_enable_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  or1k_htrace.moder.trace_enable = 1;
  or1k_htrace.moder.trace_enable = 1;
  printf_unfiltered ("HW Trace enabled.\n");
  printf_unfiltered ("HW Trace enabled.\n");
}
}
 
 
static void
static void
htrace_disable_command (args, from_tty)
htrace_disable_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  or1k_htrace.moder.trace_enable = 0;
  or1k_htrace.moder.trace_enable = 0;
  printf_unfiltered ("HW Trace disabled.\n");
  printf_unfiltered ("HW Trace disabled.\n");
}
}
 
 
static void
static void
htrace_rewind_command (args, from_tty)
htrace_rewind_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  FILE *f;
  FILE *f;
  if (args != NULL && *args != '\0')
  if (args != NULL && *args != '\0')
    strncpy (TRACE_FILENAME, args, TRACE_FILENAME_SIZE);
    strncpy (TRACE_FILENAME, args, TRACE_FILENAME_SIZE);
 
 
  /* Just empty it.  */
  /* Just empty it.  */
  if ((f = fopen (TRACE_FILENAME, "wb+")) == NULL)
  if ((f = fopen (TRACE_FILENAME, "wb+")) == NULL)
    error ("Cannot open trace file.");
    error ("Cannot open trace file.");
  fclose (f);
  fclose (f);
  printf_unfiltered ("Trace data cleared.\n");
  printf_unfiltered ("Trace data cleared.\n");
}
}
 
 
static void
static void
print_data_struct (pos, data)
print_data_struct (pos, data)
     unsigned int pos;
     unsigned int pos;
     struct htrace_data_struct *data;
     struct htrace_data_struct *data;
{
{
  struct symbol *func;
  struct symbol *func;
  char *funname = NULL;
  char *funname = NULL;
 
 
  if (data->type < 4)
  if (data->type < 4)
    {
    {
      /* Determine function name - copied from stack.c  */
      /* Determine function name - copied from stack.c  */
      func = find_pc_function (data->data);
      func = find_pc_function (data->data);
      if (func)
      if (func)
        {
        {
          struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (data->data);
          struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (data->data);
          if (msymbol != NULL
          if (msymbol != NULL
              && (SYMBOL_VALUE_ADDRESS (msymbol)
              && (SYMBOL_VALUE_ADDRESS (msymbol)
                  > BLOCK_START (SYMBOL_BLOCK_VALUE (func))))
                  > BLOCK_START (SYMBOL_BLOCK_VALUE (func))))
            funname = SYMBOL_NAME (msymbol);
            funname = SYMBOL_NAME (msymbol);
          else
          else
            {
            {
              char *demangled;
              char *demangled;
              funname = SYMBOL_NAME (func);
              funname = SYMBOL_NAME (func);
              if (SYMBOL_LANGUAGE (func) == language_cplus)
              if (SYMBOL_LANGUAGE (func) == language_cplus)
                {
                {
                  demangled = cplus_demangle (funname, DMGL_ANSI);
                  demangled = cplus_demangle (funname, DMGL_ANSI);
                  if (demangled == NULL)
                  if (demangled == NULL)
                    funname = SYMBOL_SOURCE_NAME (func);
                    funname = SYMBOL_SOURCE_NAME (func);
                }
                }
            }
            }
        }
        }
      else
      else
        {
        {
          struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (data->data);
          struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (data->data);
          if (msymbol != NULL)
          if (msymbol != NULL)
            funname = SYMBOL_NAME (msymbol);
            funname = SYMBOL_NAME (msymbol);
        }
        }
    }
    }
 
 
  printf_filtered ("%06X%c %-8s %08X", pos, data->valid ? '>' : ':',
  printf_filtered ("%06X%c %-8s %08X", pos, data->valid ? '>' : ':',
                   or1k_record_names[data->type], data->data);
                   or1k_record_names[data->type], data->data);
  if (funname)
  if (funname)
    printf_filtered (" (%s)\n", funname);
    printf_filtered (" (%s)\n", funname);
  else
  else
    printf_filtered ("\n");
    printf_filtered ("\n");
}
}
 
 
/* Prints out trace buffer.  */
/* Prints out trace buffer.  */
 
 
static void
static void
htrace_print_command (args, from_tty)
htrace_print_command (args, from_tty)
     char *args;
     char *args;
     int from_tty;
     int from_tty;
{
{
  int i, from = 0, length = prev_length;
  int i, from = 0, length = prev_length;
  FILE *f;
  FILE *f;
  struct htrace_data_struct *td;
  struct htrace_data_struct *td;
 
 
  if (args == NULL) args = "";
  if (args == NULL) args = "";
  while (*args == ' ') args++;
  while (*args == ' ') args++;
  if (*args == '\0')
  if (*args == '\0')
    {
    {
      /* We will display buffer further. */
      /* We will display buffer further. */
      from = prev_from + prev_length;
      from = prev_from + prev_length;
    }
    }
  else
  else
    {
    {
      /* Display buffer range.  */
      /* Display buffer range.  */
      int numbers = 0;
      int numbers = 0;
      char *cnum = args;
      char *cnum = args;
      while (*args != ' ' && *args != '\0')
      while (*args != ' ' && *args != '\0')
        args++;
        args++;
 
 
      /* Any arguments?  */
      /* Any arguments?  */
      if (*args == '\0')
      if (*args == '\0')
        numbers = 1;
        numbers = 1;
      else
      else
        {
        {
          *args = 0;
          *args = 0;
          args++;
          args++;
          numbers = 2;
          numbers = 2;
        }
        }
      from = strtoul (cnum, &cnum, 0);
      from = strtoul (cnum, &cnum, 0);
      if (*cnum != 0)
      if (*cnum != 0)
        error ("Invalid from value.");
        error ("Invalid from value.");
      if (from < 0) from += trace_size;
      if (from < 0) from += trace_size;
      if (numbers == 2)
      if (numbers == 2)
        {
        {
          while (*args == ' ') args++;
          while (*args == ' ') args++;
          length = strtoul (cnum, &cnum, 0);
          length = strtoul (cnum, &cnum, 0);
          if (*args != 0)
          if (*args != 0)
            error ("Invalid length value.");
            error ("Invalid length value.");
          if (length < 0)
          if (length < 0)
            {
            {
              from += length;
              from += length;
              length = -length;
              length = -length;
            }
            }
        }
        }
    }
    }
 
 
  if (from >= trace_size)
  if (from >= trace_size)
    from = trace_size - 1;
    from = trace_size - 1;
  if (from < 0)
  if (from < 0)
    from = 0;
    from = 0;
  if (from + length >= trace_size)
  if (from + length >= trace_size)
    length = trace_size - from;
    length = trace_size - from;
 
 
  prev_length = length;
  prev_length = length;
  prev_from = from;
  prev_from = from;
  if (length == 0)
  if (length == 0)
    error ("Nothing to print.");
    error ("Nothing to print.");
 
 
  printf_filtered ("Trace buffer %06x:%06x (size = %i)\n", from, from + length - 1, length);
  printf_filtered ("Trace buffer %06x:%06x (size = %i)\n", from, from + length - 1, length);
  if ((f = fopen (TRACE_FILENAME, "rb")) == NULL)
  if ((f = fopen (TRACE_FILENAME, "rb")) == NULL)
    error ("Cannot open trace file.");
    error ("Cannot open trace file.");
  if (fseek (f, TRACE_DATA_SIZE * from, SEEK_SET))
  if (fseek (f, TRACE_DATA_SIZE * from, SEEK_SET))
    error ("Error reading trace file.");
    error ("Error reading trace file.");
  td = (struct htrace_data_struct *) malloc (TRACE_DATA_SIZE * length);
  td = (struct htrace_data_struct *) malloc (TRACE_DATA_SIZE * length);
  length = fread (td, TRACE_DATA_SIZE, length, f);
  length = fread (td, TRACE_DATA_SIZE, length, f);
  for (i = 0; i < length; i++)
  for (i = 0; i < length; i++)
    print_data_struct (from + i, &td[i]);
    print_data_struct (from + i, &td[i]);
  fclose (f);
  fclose (f);
}
}
 
 
int print_insn_big_or32 (bfd_vma,struct disassemble_info*);
int print_insn_big_or32 (bfd_vma,struct disassemble_info*);
int print_insn_little_or32 (bfd_vma,struct disassemble_info*);
int print_insn_little_or32 (bfd_vma,struct disassemble_info*);
 
 
void
void
_initialize_or1k_tdep ()
_initialize_or1k_tdep ()
{
{
  build_automata ();
  build_automata ();
  /* Added by CZ 26/06/01 */
  /* Added by CZ 26/06/01 */
  if(TARGET_BYTE_ORDER == BIG_ENDIAN)
  if(TARGET_BYTE_ORDER == BIG_ENDIAN)
    tm_print_insn = print_insn_big_or32;
    tm_print_insn = print_insn_big_or32;
  else
  else
    tm_print_insn = print_insn_little_or32;
    tm_print_insn = print_insn_little_or32;
 
 
  /* Commands to show and set sprs.  */
  /* Commands to show and set sprs.  */
  add_info ("spr", info_spr_command, "Show information about the spr registers.");
  add_info ("spr", info_spr_command, "Show information about the spr registers.");
  add_info ("trace", info_trace_command, "Display trace buffer contents.");
  add_info ("trace", info_trace_command, "Display trace buffer contents.");
  add_com ("spr", class_support, spr_command, "Set specified SPR register.");
  add_com ("spr", class_support, spr_command, "Set specified SPR register.");
 
 
  /* hwatch command.  */
  /* hwatch command.  */
  add_com ("hwatch", class_breakpoint, hwatch_command, "Set hardware watch"
  add_com ("hwatch", class_breakpoint, hwatch_command, "Set hardware watch"
           "point.\nExample: ($LEA == my_var)&&($LDATA < 50)||($SEA == my_"
           "point.\nExample: ($LEA == my_var)&&($LDATA < 50)||($SEA == my_"
           "var)&&($SDATA >= 50).\nSee OR1k Architecture document for more"
           "var)&&($SDATA >= 50).\nSee OR1k Architecture document for more"
           " info.");
           " info.");
 
 
  /* htrace commands.  */
  /* htrace commands.  */
  add_prefix_cmd ("htrace", class_breakpoint, htrace_command,
  add_prefix_cmd ("htrace", class_breakpoint, htrace_command,
                  "Group of commands for handling hardware assisted trace\n\n"
                  "Group of commands for handling hardware assisted trace\n\n"
                  "See OR1k Architecture and gdb for or1k documents for more info.",
                  "See OR1k Architecture and gdb for or1k documents for more info.",
                  &htrace_cmdlist, "htrace ", 0, &cmdlist);
                  &htrace_cmdlist, "htrace ", 0, &cmdlist);
  add_cmd ("info", class_breakpoint, htrace_info_command, "Display information about HW trace.",
  add_cmd ("info", class_breakpoint, htrace_info_command, "Display information about HW trace.",
           &htrace_cmdlist);
           &htrace_cmdlist);
  add_alias_cmd ("i", "info", class_breakpoint, 1, &htrace_cmdlist);
  add_alias_cmd ("i", "info", class_breakpoint, 1, &htrace_cmdlist);
  add_cmd ("trigger", class_breakpoint, htrace_trigger_command, "Set starting criteria for trace.",
  add_cmd ("trigger", class_breakpoint, htrace_trigger_command, "Set starting criteria for trace.",
           &htrace_cmdlist);
           &htrace_cmdlist);
  add_alias_cmd ("t", "trigger", class_breakpoint, 1, &htrace_cmdlist);
  add_alias_cmd ("t", "trigger", class_breakpoint, 1, &htrace_cmdlist);
  add_cmd ("qualifier", class_breakpoint, htrace_qualifier_command, "Set acquisition qualifier for HW trace.",
  add_cmd ("qualifier", class_breakpoint, htrace_qualifier_command, "Set acquisition qualifier for HW trace.",
           &htrace_cmdlist);
           &htrace_cmdlist);
  add_alias_cmd ("q", "qualifier", class_breakpoint, 1, &htrace_cmdlist);
  add_alias_cmd ("q", "qualifier", class_breakpoint, 1, &htrace_cmdlist);
  add_cmd ("stop", class_breakpoint, htrace_stop_command, "Set HW trace stopping criteria.",
  add_cmd ("stop", class_breakpoint, htrace_stop_command, "Set HW trace stopping criteria.",
           &htrace_cmdlist);
           &htrace_cmdlist);
  add_alias_cmd ("s", "stop", class_breakpoint, 1, &htrace_cmdlist);
  add_alias_cmd ("s", "stop", class_breakpoint, 1, &htrace_cmdlist);
  add_cmd ("record", class_breakpoint, htrace_record_command, "Sets data to be recorded when expression occurs.",
  add_cmd ("record", class_breakpoint, htrace_record_command, "Sets data to be recorded when expression occurs.",
           &htrace_cmdlist);
           &htrace_cmdlist);
  add_alias_cmd ("r", "record", class_breakpoint, 1, &htrace_cmdlist);
  add_alias_cmd ("r", "record", class_breakpoint, 1, &htrace_cmdlist);
  add_cmd ("clear records", class_breakpoint, htrace_clear_records_command,
  add_cmd ("clear records", class_breakpoint, htrace_clear_records_command,
           "Disposes all matchpoints used by records.", &htrace_cmdlist);
           "Disposes all matchpoints used by records.", &htrace_cmdlist);
  add_cmd ("enable", class_breakpoint, htrace_enable_command, "Enables the HW trace.", &htrace_cmdlist);
  add_cmd ("enable", class_breakpoint, htrace_enable_command, "Enables the HW trace.", &htrace_cmdlist);
  add_alias_cmd ("e", "enable", class_breakpoint, 1, &htrace_cmdlist);
  add_alias_cmd ("e", "enable", class_breakpoint, 1, &htrace_cmdlist);
  add_cmd ("disable", class_breakpoint, htrace_disable_command, "Disables the HW trace.", &htrace_cmdlist);
  add_cmd ("disable", class_breakpoint, htrace_disable_command, "Disables the HW trace.", &htrace_cmdlist);
  add_alias_cmd ("d", "disable", class_breakpoint, 1, &htrace_cmdlist);
  add_alias_cmd ("d", "disable", class_breakpoint, 1, &htrace_cmdlist);
  add_cmd ("rewind", class_breakpoint, htrace_rewind_command, "Clears currently recorded trace data.\n"
  add_cmd ("rewind", class_breakpoint, htrace_rewind_command, "Clears currently recorded trace data.\n"
           "If filename is specified, new trace file is made and any newly collected data\n"
           "If filename is specified, new trace file is made and any newly collected data\n"
           "will be written there.", &htrace_cmdlist);
           "will be written there.", &htrace_cmdlist);
  add_cmd ("print", class_breakpoint, htrace_print_command,
  add_cmd ("print", class_breakpoint, htrace_print_command,
           "Prints trace buffer, using current record configuration.\n"
           "Prints trace buffer, using current record configuration.\n"
           "htrace print [<start> [<len>]]\n"
           "htrace print [<start> [<len>]]\n"
           "htrace print"
           "htrace print"
           , &htrace_cmdlist);
           , &htrace_cmdlist);
  add_alias_cmd ("p", "print", class_breakpoint, 1, &htrace_cmdlist);
  add_alias_cmd ("p", "print", class_breakpoint, 1, &htrace_cmdlist);
  add_prefix_cmd ("mode", class_breakpoint, htrace_mode_command,
  add_prefix_cmd ("mode", class_breakpoint, htrace_mode_command,
           "Configures the HW trace.\n"
           "Configures the HW trace.\n"
           "htrace mode [continuous|suspend]"
           "htrace mode [continuous|suspend]"
           , &htrace_mode_cmdlist, "htrace mode ", 0, &htrace_cmdlist);
           , &htrace_mode_cmdlist, "htrace mode ", 0, &htrace_cmdlist);
  add_alias_cmd ("m", "mode", class_breakpoint, 1, &htrace_cmdlist);
  add_alias_cmd ("m", "mode", class_breakpoint, 1, &htrace_cmdlist);
  add_cmd ("continuous", class_breakpoint, htrace_mode_contin_command,
  add_cmd ("continuous", class_breakpoint, htrace_mode_contin_command,
           "Set continuous trace mode.\n", &htrace_mode_cmdlist);
           "Set continuous trace mode.\n", &htrace_mode_cmdlist);
  add_cmd ("suspend", class_breakpoint, htrace_mode_suspend_command,
  add_cmd ("suspend", class_breakpoint, htrace_mode_suspend_command,
           "Set suspend trace mode.\n", &htrace_mode_cmdlist);
           "Set suspend trace mode.\n", &htrace_mode_cmdlist);
 
 
  /* Extra functions supported by simulator.  */
  /* Extra functions supported by simulator.  */
  add_com ("sim", class_obscure, sim_command,
  add_com ("sim", class_obscure, sim_command,
           "Send a extended command to the simulator.");
           "Send a extended command to the simulator.");
}
}
 
 
 
 

powered by: WebSVN 2.1.0

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