Line 198... |
Line 198... |
char **tok);
|
char **tok);
|
static char *or1k_parse_spr_params (char *args,
|
static char *or1k_parse_spr_params (char *args,
|
int *group,
|
int *group,
|
int *index,
|
int *index,
|
int is_set);
|
int is_set);
|
|
static ULONGEST or1k_read_spr (unsigned int regnum);
|
|
static void or1k_write_spr (unsigned int regnum,
|
|
ULONGEST data);
|
static void info_spr_command (char *args,
|
static void info_spr_command (char *args,
|
int from_tty);
|
int from_tty);
|
static void or1k_spr_command (char *args,
|
static void or1k_spr_command (char *args,
|
int from_tty);
|
int from_tty);
|
static void info_matchpoints_command (char *args,
|
static void info_matchpoints_command (char *args,
|
Line 667... |
Line 670... |
end_iaddr = (this_pc > prologue_end_iaddr) ? prologue_end_iaddr : this_pc;
|
end_iaddr = (this_pc > prologue_end_iaddr) ? prologue_end_iaddr : this_pc;
|
|
|
/* The default is to find the PC of the PREVIOUS frame in the link register
|
/* The default is to find the PC of the PREVIOUS frame in the link register
|
of this frame. This may be changed if we find the link register was saved
|
of this frame. This may be changed if we find the link register was saved
|
on the stack. */
|
on the stack. */
|
trad_frame_set_reg_realreg (info, OR1K_PC_REGNUM, OR1K_LR_REGNUM);
|
trad_frame_set_reg_realreg (info, OR1K_NPC_REGNUM, OR1K_LR_REGNUM);
|
|
|
/* All the following analysis only occurs if we are in the prologue and have
|
/* All the following analysis only occurs if we are in the prologue and have
|
executed the code. Get THIS frame size (which implies framelessness if
|
executed the code. Get THIS frame size (which implies framelessness if
|
zero) */
|
zero) */
|
|
|
Line 743... |
Line 746... |
tmp = or1k_link_address (next_frame,
|
tmp = or1k_link_address (next_frame,
|
start_iaddr + (3 * OR1K_INSTLEN));
|
start_iaddr + (3 * OR1K_INSTLEN));
|
if ((-1 != tmp) && (tmp == (fp_save_offset - OR1K_INSTLEN)))
|
if ((-1 != tmp) && (tmp == (fp_save_offset - OR1K_INSTLEN)))
|
{
|
{
|
trad_frame_set_reg_addr (info, OR1K_LR_REGNUM, this_sp + tmp);
|
trad_frame_set_reg_addr (info, OR1K_LR_REGNUM, this_sp + tmp);
|
trad_frame_set_reg_addr (info, OR1K_PC_REGNUM, this_sp + tmp);
|
trad_frame_set_reg_addr (info, OR1K_NPC_REGNUM, this_sp + tmp);
|
saved_regs_iaddr = start_iaddr + (3 * OR1K_INSTLEN);
|
saved_regs_iaddr = start_iaddr + (3 * OR1K_INSTLEN);
|
}
|
}
|
else
|
else
|
{
|
{
|
saved_regs_iaddr = start_iaddr + (2 * OR1K_INSTLEN);
|
saved_regs_iaddr = start_iaddr + (2 * OR1K_INSTLEN);
|
Line 1019... |
Line 1022... |
|
|
static int
|
static int
|
or1k_single_step_through_delay( struct gdbarch *gdbarch,
|
or1k_single_step_through_delay( struct gdbarch *gdbarch,
|
struct frame_info *this_frame )
|
struct frame_info *this_frame )
|
{
|
{
|
CORE_ADDR ppc = or1k_read_spr (OR1K_PPC_SPRNUM);
|
struct regcache *regcache = get_current_regcache ();
|
int index = insn_decode (or1k_fetch_instruction (this_frame, ppc));
|
ULONGEST val;
|
|
CORE_ADDR ppc;
|
|
int index;
|
|
|
|
/* Get and decode the previous instruction. */
|
|
regcache_cooked_read_unsigned (regcache, OR1K_PPC_REGNUM, &val);
|
|
ppc = (CORE_ADDR)val;
|
|
index = insn_decode (or1k_fetch_instruction (this_frame, ppc));
|
|
|
/* We are only executing a delay slot if the previous instruction was a
|
/* We are only executing a delay slot if the previous instruction was a
|
branch or jump. */
|
branch or jump. */
|
|
|
return or32_opcodes[index].flags & OR32_IF_DELAY;
|
return or32_opcodes[index].flags & OR32_IF_DELAY;
|
|
|
} /* or1k_single_step_through_delay() */
|
} /* or1k_single_step_through_delay() */
|
|
|
|
|
Line 1107... |
Line 1116... |
"gpr0", "gpr1", "gpr2", "gpr3", "gpr4", "gpr5", "gpr6", "gpr7",
|
"gpr0", "gpr1", "gpr2", "gpr3", "gpr4", "gpr5", "gpr6", "gpr7",
|
"gpr8", "gpr9", "gpr10", "gpr11", "gpr12", "gpr13", "gpr14", "gpr15",
|
"gpr8", "gpr9", "gpr10", "gpr11", "gpr12", "gpr13", "gpr14", "gpr15",
|
"gpr16", "gpr17", "gpr18", "gpr19", "gpr20", "gpr21", "gpr22", "gpr23",
|
"gpr16", "gpr17", "gpr18", "gpr19", "gpr20", "gpr21", "gpr22", "gpr23",
|
"gpr24", "gpr25", "gpr26", "gpr27", "gpr28", "gpr29", "gpr30", "gpr31",
|
"gpr24", "gpr25", "gpr26", "gpr27", "gpr28", "gpr29", "gpr30", "gpr31",
|
|
|
/* program counter and status register */
|
/* previous program counter, next program counter and status register */
|
"pc", "sr"
|
"ppc", "npc", "sr"
|
|
|
/* Floating point and vector registers may appear as pseudo registers in
|
/* Floating point and vector registers may appear as pseudo registers in
|
the future. */
|
the future. */
|
};
|
};
|
|
|
Line 1150... |
Line 1159... |
|
|
if((regnum >= 0) && (regnum < OR1K_TOTAL_NUM_REGS))
|
if((regnum >= 0) && (regnum < OR1K_TOTAL_NUM_REGS))
|
{
|
{
|
switch (regnum)
|
switch (regnum)
|
{
|
{
|
case OR1K_PC_REGNUM:
|
case OR1K_PPC_REGNUM:
|
|
case OR1K_NPC_REGNUM:
|
return void_func_ptr; /* Pointer to code */
|
return void_func_ptr; /* Pointer to code */
|
|
|
case OR1K_SP_REGNUM:
|
case OR1K_SP_REGNUM:
|
case OR1K_FP_REGNUM:
|
case OR1K_FP_REGNUM:
|
return void_ptr; /* Pointer to data */
|
return void_ptr; /* Pointer to data */
|
Line 1259... |
Line 1269... |
/* For now everything except the PC */
|
/* For now everything except the PC */
|
if (group == general_reggroup)
|
if (group == general_reggroup)
|
{
|
{
|
return ((regnum >= OR1K_ZERO_REGNUM) &&
|
return ((regnum >= OR1K_ZERO_REGNUM) &&
|
(regnum < tdep->num_gpr_regs) &&
|
(regnum < tdep->num_gpr_regs) &&
|
(regnum != OR1K_PC_REGNUM));
|
(regnum != OR1K_PPC_REGNUM) &&
|
|
(regnum != OR1K_NPC_REGNUM));
|
}
|
}
|
|
|
if (group == float_reggroup)
|
if (group == float_reggroup)
|
{
|
{
|
return 0; /* No float regs. */
|
return 0; /* No float regs. */
|
Line 1538... |
Line 1549... |
|
|
static CORE_ADDR
|
static CORE_ADDR
|
or1k_unwind_pc (struct gdbarch *gdbarch,
|
or1k_unwind_pc (struct gdbarch *gdbarch,
|
struct frame_info *next_frame)
|
struct frame_info *next_frame)
|
{
|
{
|
return frame_unwind_register_unsigned (next_frame, OR1K_PC_REGNUM);
|
return frame_unwind_register_unsigned (next_frame, OR1K_NPC_REGNUM);
|
|
|
} /* or1k_unwind_pc() */
|
} /* or1k_unwind_pc() */
|
|
|
|
|
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
Line 1577... |
Line 1588... |
@param[in] bp_addr Breakpoint address
|
@param[in] bp_addr Breakpoint address
|
@param[in] nargs Number of ags to push
|
@param[in] nargs Number of ags to push
|
@param[in] args The arguments
|
@param[in] args The arguments
|
@param[in] sp The stack pointer
|
@param[in] sp The stack pointer
|
@param[in] struct_return True (1) if this returns a structure
|
@param[in] struct_return True (1) if this returns a structure
|
@param[in] struct_addr Address for returning structurs
|
@param[in] struct_addr Address for returning structures
|
|
|
@return The updated stack pointer */
|
@return The updated stack pointer */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
|
|
static CORE_ADDR
|
static CORE_ADDR
|
Line 1896... |
Line 1907... |
set_gdbarch_pseudo_register_read (gdbarch, or1k_pseudo_register_read);
|
set_gdbarch_pseudo_register_read (gdbarch, or1k_pseudo_register_read);
|
set_gdbarch_pseudo_register_write (gdbarch, or1k_pseudo_register_write);
|
set_gdbarch_pseudo_register_write (gdbarch, or1k_pseudo_register_write);
|
set_gdbarch_num_regs (gdbarch, OR1K_NUM_REGS);
|
set_gdbarch_num_regs (gdbarch, OR1K_NUM_REGS);
|
set_gdbarch_num_pseudo_regs (gdbarch, OR1K_NUM_PSEUDO_REGS);
|
set_gdbarch_num_pseudo_regs (gdbarch, OR1K_NUM_PSEUDO_REGS);
|
set_gdbarch_sp_regnum (gdbarch, OR1K_SP_REGNUM);
|
set_gdbarch_sp_regnum (gdbarch, OR1K_SP_REGNUM);
|
set_gdbarch_pc_regnum (gdbarch, OR1K_PC_REGNUM);
|
set_gdbarch_pc_regnum (gdbarch, OR1K_NPC_REGNUM);
|
set_gdbarch_ps_regnum (gdbarch, OR1K_SR_REGNUM);
|
set_gdbarch_ps_regnum (gdbarch, OR1K_SR_REGNUM);
|
set_gdbarch_deprecated_fp_regnum (gdbarch, OR1K_FP_REGNUM);
|
set_gdbarch_deprecated_fp_regnum (gdbarch, OR1K_FP_REGNUM);
|
|
|
/* Functions to supply register information */
|
/* Functions to supply register information */
|
set_gdbarch_register_name (gdbarch, or1k_register_name);
|
set_gdbarch_register_name (gdbarch, or1k_register_name);
|
Line 2780... |
Line 2791... |
return trailer;
|
return trailer;
|
}
|
}
|
} /* or1k_parse_spr_params() */
|
} /* or1k_parse_spr_params() */
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/*!Read a special purpose register from the target
|
|
|
|
This has to be done using the target remote command "readspr"
|
|
|
|
@param[in] regnum The register to read
|
|
|
|
@return The value read */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
static ULONGEST
|
|
or1k_read_spr (unsigned int regnum)
|
|
{
|
|
struct ui_file *uibuf = mem_fileopen ();
|
|
char cmd[sizeof ("readspr ffff")];
|
|
unsigned long int data;
|
|
char *res;
|
|
long int len;
|
|
|
|
/* Create the command string and pass it to target remote command function */
|
|
sprintf (cmd, "readspr %4x", regnum);
|
|
target_rcmd (cmd, uibuf);
|
|
|
|
/* Get the output for the UI file as a string */
|
|
res = ui_file_xstrdup (uibuf, &len);
|
|
sscanf (res, "%lx", &data);
|
|
|
|
/* Tidy up */
|
|
xfree (res);
|
|
ui_file_delete (uibuf);
|
|
|
|
return (ULONGEST)data;
|
|
|
|
} /* or1k_read_spr() */
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/*!Write a special purpose register on the target
|
|
|
|
This has to be done using the target remote command "writespr"
|
|
|
|
Since the SPRs may map to GPR's or the other GDB register (PPC, NPC, SR),
|
|
any register cache is flushed.
|
|
|
|
@param[in] regnum The register to write
|
|
@param[in] data The value to write */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
static void
|
|
or1k_write_spr (unsigned int regnum,
|
|
ULONGEST data)
|
|
{
|
|
struct ui_file *uibuf = mem_fileopen ();
|
|
char cmd[sizeof ("writespr ffff ffffffff")];
|
|
char *res;
|
|
long int len;
|
|
|
|
/* Create the command string and pass it to target remote command function */
|
|
sprintf (cmd, "writespr %4x %8llx", regnum, data);
|
|
target_rcmd (cmd, uibuf);
|
|
|
|
/* Flush the register cache */
|
|
registers_changed ();
|
|
|
|
/* We ignore the result - Rcmd can put out its own error messages. Just
|
|
tidy up */
|
|
ui_file_delete (uibuf);
|
|
|
|
} /* or1k_write_spr() */
|
|
|
|
|
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
/*!Show the value of a special purpose register or group
|
/*!Show the value of a special purpose register or group
|
|
|
This is a custom extension to the GDB info command.
|
This is a custom extension to the GDB info command.
|
|
|
Line 2877... |
Line 2959... |
ui_out_message (uiout, 0, "Invalid value - register not changed\n");
|
ui_out_message (uiout, 0, "Invalid value - register not changed\n");
|
return;
|
return;
|
}
|
}
|
|
|
old_val = or1k_read_spr (OR1K_SPR (group, index));
|
old_val = or1k_read_spr (OR1K_SPR (group, index));
|
|
|
or1k_write_spr (OR1K_SPR (group, index) , new_val);
|
or1k_write_spr (OR1K_SPR (group, index) , new_val);
|
|
|
ui_out_field_fmt (uiout, NULL,
|
ui_out_field_fmt (uiout, NULL,
|
"%s.%s (SPR%i_%i) set to %llu (0x%llx), "
|
"%s.%s (SPR%i_%i) set to %llu (0x%llx), "
|
"was: %llu (0x%llx)\n",
|
"was: %llu (0x%llx)\n",
|