Line 43... |
Line 43... |
#define debug if (remote_debug) printf_unfiltered
|
#define debug if (remote_debug) printf_unfiltered
|
|
|
/* The following prototype is necessary or the compiler will not
|
/* The following prototype is necessary or the compiler will not
|
correctly promote the data argument to ULONGEST */
|
correctly promote the data argument to ULONGEST */
|
static void or1k_write_reg (unsigned int, ULONGEST);
|
static void or1k_write_reg (unsigned int, ULONGEST);
|
static int insn_has_delay_slot (unsigned int);
|
static int insn_modifies_gprs (unsigned int insn);
|
|
|
/* JTAG or1k target ops. */
|
/* JTAG or1k target ops. */
|
extern void jtag_init PARAMS ((char * args));
|
extern void jtag_init PARAMS ((char * args));
|
extern ULONGEST jtag_read_reg PARAMS ((unsigned int regno));
|
extern ULONGEST jtag_read_reg PARAMS ((unsigned int regno));
|
extern void jtag_write_reg PARAMS ((unsigned int regno, ULONGEST data));
|
extern void jtag_write_reg PARAMS ((unsigned int regno, ULONGEST data));
|
Line 159... |
Line 159... |
static int interrupt_count = 0;
|
static int interrupt_count = 0;
|
|
|
/* Reason of last stop. */
|
/* Reason of last stop. */
|
static int hit_watchpoint = 0;
|
static int hit_watchpoint = 0;
|
static int hit_breakpoint = 0;
|
static int hit_breakpoint = 0;
|
|
static int step_link_insn = 0;
|
static int new_pc_set = 0;
|
static int new_pc_set = 0;
|
|
|
/* Current register values. */
|
/* Current register values. */
|
unsigned int dmr1 = 0;
|
unsigned int dmr1 = 0;
|
unsigned int dmr2 = 0;
|
unsigned int dmr2 = 0;
|
unsigned int dsr = 0;
|
unsigned int dsr = 0;
|
unsigned int drr = 0;
|
unsigned int drr = 0;
|
|
unsigned int lr = 0;
|
|
|
/* Current matchpoints. */
|
/* Current matchpoints. */
|
unsigned int dvr[MAX_MATCHPOINTS];
|
unsigned int dvr[MAX_MATCHPOINTS];
|
struct dcr_struct dcr[MAX_MATCHPOINTS];
|
struct dcr_struct dcr[MAX_MATCHPOINTS];
|
|
|
Line 297... |
Line 299... |
{
|
{
|
or1k_set_chain (SC_RISC_DEBUG);
|
or1k_set_chain (SC_RISC_DEBUG);
|
or1k_write_reg (regno, (ULONGEST)data);
|
or1k_write_reg (regno, (ULONGEST)data);
|
if (regno == PC_SPRNUM) {
|
if (regno == PC_SPRNUM) {
|
hit_breakpoint = 0;
|
hit_breakpoint = 0;
|
|
step_link_insn = 0;
|
new_pc_set = 1;
|
new_pc_set = 1;
|
}
|
}
|
}
|
}
|
|
|
/* Reads register SPR from regno. */
|
/* Reads register SPR from regno. */
|
Line 516... |
Line 519... |
memset (&or1k_htrace, 0, sizeof (or1k_htrace));
|
memset (&or1k_htrace, 0, sizeof (or1k_htrace));
|
|
|
/* RECSELDEPEND = 0 does not match our trace scheme. */
|
/* RECSELDEPEND = 0 does not match our trace scheme. */
|
or1k_htrace.moder.rec_sel_dep = 1;
|
or1k_htrace.moder.rec_sel_dep = 1;
|
|
|
debug_regs_changed = 1;
|
debug_regs_changed = 0;//1;
|
or1k_commit_debug_registers ();
|
or1k_commit_debug_registers ();
|
|
|
if (err != 0)
|
if (err != 0)
|
error ("Cannot connect.");
|
error ("Cannot connect.");
|
|
|
Line 741... |
Line 744... |
unsigned int pc;
|
unsigned int pc;
|
unsigned int ppc;
|
unsigned int ppc;
|
unsigned int npc;
|
unsigned int npc;
|
unsigned int val;
|
unsigned int val;
|
unsigned int ppc_insn;
|
unsigned int ppc_insn;
|
|
unsigned int pc_insn;
|
|
|
pc = read_pc();
|
pc = read_pc();
|
npc = or1k_read_spr_reg (PC_SPRNUM);
|
npc = or1k_read_spr_reg (PC_SPRNUM);
|
ppc = or1k_read_spr_reg (PPC_SPRNUM);
|
ppc = or1k_read_spr_reg (PPC_SPRNUM);
|
debug ("pc = %08x BP = %x npc = %08x ppc = %08x\n", pc, breakpoint_here_p (pc), npc, ppc);
|
debug ("pc = %08x BP = %x npc = %08x ppc = %08x\n", pc, breakpoint_here_p (pc), npc, ppc);
|
Line 759... |
Line 763... |
/* Clear reason register for later. */
|
/* Clear reason register for later. */
|
or1k_write_spr_reg (DRR_SPRNUM, 0);
|
or1k_write_spr_reg (DRR_SPRNUM, 0);
|
|
|
or1k_commit_debug_registers ();
|
or1k_commit_debug_registers ();
|
|
|
|
/* Fetch previous insn */
|
ppc_insn = or1k_fetch_instruction(ppc);
|
ppc_insn = or1k_fetch_instruction(ppc);
|
|
|
/* Else clause added by CZ 26/06/01 */
|
/* Fetch next insn */
|
|
pc_insn = or1k_fetch_instruction (pc);
|
|
|
if (step)
|
if (step)
|
{
|
{
|
/* HW STEP. Set DMR1_ST. */
|
/* HW STEP. Set DMR1_ST. */
|
dmr1 |= DMR1_ST;
|
dmr1 |= DMR1_ST;
|
or1k_write_spr_reg (DMR1_SPRNUM, dmr1);
|
or1k_write_spr_reg (DMR1_SPRNUM, dmr1);
|
dmr1 &= ~DMR1_ST;
|
dmr1 &= ~DMR1_ST;
|
|
|
if (new_pc_set)
|
if (new_pc_set)
|
{
|
{
|
debug("resume: 1\n");
|
debug("resume: 1\n");
|
|
/* If new PC was set, then just set it again to fill the pipeline */
|
|
|
or1k_write_spr_reg (PC_SPRNUM, pc);
|
or1k_write_spr_reg (PC_SPRNUM, pc);
|
new_pc_set = 0;
|
|
|
if (is_delayed (pc_insn) && insn_modifies_gprs (pc_insn))
|
|
{
|
|
debug("resume: 10\n");
|
|
/* We are steping across jump an link insn - save link
|
|
register, so we will be able to restore it when we will
|
|
step across delay slot insn */
|
|
step_link_insn = 1;
|
|
lr = or1k_read_spr_reg (REGNUM_TO_SPRNUM(9));
|
}
|
}
|
else if (insn_has_delay_slot (ppc_insn) && (ppc != pc))
|
}
|
|
else if (is_delayed (ppc_insn) && (ppc != pc))
|
{
|
{
|
/* Steping across delay slot insn - we have to reexcute branch insn */
|
|
debug("resume: 2\n");
|
debug("resume: 2\n");
|
|
/* Steping across delay slot insn - we have to reexcute branch insn */
|
|
|
if(breakpoint_here_p (ppc))
|
if(breakpoint_here_p (ppc))
|
or1k_write_mem(ppc, ppc_insn);
|
or1k_write_mem(ppc, ppc_insn);
|
|
|
|
if (insn_modifies_gprs (ppc_insn) && step_link_insn)
|
|
{
|
|
debug("resume: 11\n");
|
|
/* If this is delay slot of jump an link insn that was
|
|
allready executed - restore link register first */
|
|
or1k_write_spr_reg (REGNUM_TO_SPRNUM(9), lr);
|
|
step_link_insn = 0;
|
|
}
|
|
|
or1k_write_spr_reg (PC_SPRNUM, ppc);
|
or1k_write_spr_reg (PC_SPRNUM, ppc);
|
|
|
or1k_unstall ();
|
or1k_unstall ();
|
|
|
or1k_set_chain (SC_REGISTER);
|
or1k_set_chain (SC_REGISTER);
|
val = or1k_read_reg (JTAG_RISCOP);
|
val = or1k_read_reg (JTAG_RISCOP);
|
do {
|
do {
|
val = or1k_read_reg (JTAG_RISCOP);
|
val = or1k_read_reg (JTAG_RISCOP);
|
} while ((val & 1) == 0);
|
} while ((val & 1) == 0);
|
|
|
new_pc_set = 0;
|
|
}
|
}
|
else if (hit_breakpoint && ((ppc + 4) != npc))
|
else if (hit_breakpoint && ((ppc + 4) != npc) && (pc != npc))
|
{
|
{
|
debug("resume: 3\n");
|
debug("resume: 3\n");
|
/* Trapped on delay slot instruction. */
|
/* Trapped on delay slot instruction. */
|
/* Set PC to branch insn preceding delay slot. */
|
/* Set PC to branch insn preceding delay slot. */
|
or1k_write_spr_reg (PC_SPRNUM, ppc - 4);
|
or1k_write_spr_reg (PC_SPRNUM, ppc - 4);
|
|
|
|
if (insn_modifies_gprs (or1k_fetch_instruction (ppc - 4)))
|
|
{
|
|
debug("resume: 12\n");
|
|
/* We are steping across jump an link insn - save link
|
|
register, so we will be able to restore it when we will
|
|
step across delay slot insn */
|
|
step_link_insn = 1;
|
|
lr = or1k_read_spr_reg (REGNUM_TO_SPRNUM(9));
|
|
}
|
|
|
or1k_unstall ();
|
or1k_unstall ();
|
|
|
or1k_set_chain (SC_REGISTER);
|
or1k_set_chain (SC_REGISTER);
|
val = or1k_read_reg (JTAG_RISCOP);
|
val = or1k_read_reg (JTAG_RISCOP);
|
do {
|
do {
|
val = or1k_read_reg (JTAG_RISCOP);
|
val = or1k_read_reg (JTAG_RISCOP);
|
} while ((val & 1) == 0);
|
} while ((val & 1) == 0);
|
|
|
new_pc_set = 0;
|
|
}
|
}
|
else
|
else
|
{
|
{
|
debug("resume: 4\n");
|
debug("resume: 4\n");
|
|
/* Steping across 'non delay slot' insn - set PC to fill the pipeline */
|
|
|
or1k_write_spr_reg (PC_SPRNUM, pc);
|
or1k_write_spr_reg (PC_SPRNUM, pc);
|
|
|
new_pc_set = 0;
|
if (is_delayed (pc_insn) && insn_modifies_gprs (pc_insn))
|
|
{
|
|
debug("resume: 13\n");
|
|
/* We are steping across jump an link insn - save link
|
|
register, so we will be able to restore it when we will
|
|
step across delay slot insn */
|
|
step_link_insn = 1;
|
|
lr = or1k_read_spr_reg (REGNUM_TO_SPRNUM(9));
|
|
}
|
}
|
}
|
}
|
}
|
else
|
else
|
{
|
{
|
dmr1 &= ~DMR1_ST;
|
dmr1 &= ~DMR1_ST;
|
or1k_write_spr_reg (DMR1_SPRNUM, dmr1);
|
or1k_write_spr_reg (DMR1_SPRNUM, dmr1);
|
|
|
if (new_pc_set)
|
if (new_pc_set)
|
{
|
{
|
debug("resume: 5\n");
|
debug("resume: 5\n");
|
or1k_write_spr_reg (PC_SPRNUM, pc);
|
/* If new PC was set, then just set it again to fill the pipeline */
|
|
|
new_pc_set = 0;
|
step_link_insn = 0;
|
|
or1k_write_spr_reg (PC_SPRNUM, pc);
|
}
|
}
|
else if (insn_has_delay_slot (ppc_insn) && !breakpoint_here_p (ppc))
|
else if (is_delayed (ppc_insn) && !breakpoint_here_p (ppc))
|
{
|
{
|
debug("resume: 6\n");
|
debug("resume: 6\n");
|
or1k_write_spr_reg (PC_SPRNUM, ppc);
|
/* If next insn is delay slot insn - set PC to previous branch insn
|
|
and continue from there to refill the pipeline */
|
|
|
new_pc_set = 0;
|
if (insn_modifies_gprs (ppc_insn) && step_link_insn)
|
|
{
|
|
debug("resume: 14\n");
|
|
/* If this is delay slot of jump an link insn that was
|
|
allready executed - restore link register first */
|
|
or1k_write_spr_reg (REGNUM_TO_SPRNUM(9), lr);
|
|
step_link_insn = 0;
|
|
}
|
|
|
|
or1k_write_spr_reg (PC_SPRNUM, ppc);
|
}
|
}
|
else if (insn_has_delay_slot (ppc_insn) && breakpoint_here_p (ppc))
|
else if (is_delayed (ppc_insn) && breakpoint_here_p (ppc))
|
{
|
{
|
debug("resume: 7\n");
|
debug("resume: 7\n");
|
|
/* If next insn is delay slot insn and previous branch insn
|
|
is actually BP - replace BP with original branch insn, set PC
|
|
to that insn step over it, put back BP and continue */
|
|
|
or1k_write_mem(ppc, ppc_insn);
|
or1k_write_mem(ppc, ppc_insn);
|
|
|
dmr1 |= DMR1_ST;
|
dmr1 |= DMR1_ST;
|
or1k_write_spr_reg (DMR1_SPRNUM, dmr1);
|
or1k_write_spr_reg (DMR1_SPRNUM, dmr1);
|
dmr1 &= ~DMR1_ST;
|
dmr1 &= ~DMR1_ST;
|
|
|
or1k_write_spr_reg (PC_SPRNUM, ppc);
|
or1k_write_spr_reg (PC_SPRNUM, ppc);
|
|
|
|
if (insn_modifies_gprs (ppc_insn) && step_link_insn)
|
|
{
|
|
debug("resume: 15\n");
|
|
/* If this is delay slot of jump an link insn that was
|
|
allready executed - restore link register first */
|
|
or1k_write_spr_reg (REGNUM_TO_SPRNUM(9), lr);
|
|
step_link_insn = 0;
|
|
}
|
|
|
or1k_unstall ();
|
or1k_unstall ();
|
|
|
or1k_set_chain (SC_REGISTER);
|
or1k_set_chain (SC_REGISTER);
|
val = or1k_read_reg (JTAG_RISCOP);
|
val = or1k_read_reg (JTAG_RISCOP);
|
do {
|
do {
|
Line 861... |
Line 928... |
} while ((val & 1) == 0);
|
} while ((val & 1) == 0);
|
|
|
or1k_write_mem(ppc, 0x21000001);
|
or1k_write_mem(ppc, 0x21000001);
|
|
|
or1k_write_spr_reg (DMR1_SPRNUM, dmr1);
|
or1k_write_spr_reg (DMR1_SPRNUM, dmr1);
|
|
|
new_pc_set = 0;
|
|
}
|
}
|
else
|
else
|
{
|
{
|
debug("resume: 8\n");
|
debug("resume: 8\n");
|
or1k_write_spr_reg (PC_SPRNUM, pc);
|
/* Continue from 'non delay slot' insn - set PC to fill the pipeline */
|
|
|
new_pc_set = 0;
|
or1k_write_spr_reg (PC_SPRNUM, pc);
|
}
|
}
|
}
|
}
|
|
|
|
/* Now we are in normal program flow again */
|
|
new_pc_set = 0;
|
|
|
/* We can now continue normally, independent of step */
|
/* We can now continue normally, independent of step */
|
or1k_unstall ();
|
or1k_unstall ();
|
or1k_status = TARGET_RUNNING;
|
or1k_status = TARGET_RUNNING;
|
debug ("-resume %i, %i, %i\n",step, siggnal, or1k_status);
|
debug ("-resume %i, %i, %i\n",step, siggnal, or1k_status);
|
}
|
}
|
Line 1826... |
Line 1894... |
if ((dmr2 >> (i + 11)) & 1)
|
if ((dmr2 >> (i + 11)) & 1)
|
printf_filtered (", increments counter");
|
printf_filtered (", increments counter");
|
printf_filtered ("\n");
|
printf_filtered ("\n");
|
}
|
}
|
}
|
}
|
|
|
static int
|
static int
|
insn_has_delay_slot (insn)
|
insn_modifies_gprs(unsigned int insn)
|
unsigned int insn;
|
|
{
|
{
|
if (((insn >> 26) <= 4) || ((insn >> 26) == 17) || ((insn >> 26) == 18))
|
/* l.jal */
|
|
if ((insn >> 26) == 0x01)
|
return 1;
|
return 1;
|
else
|
|
|
/* l.jalr */
|
|
if ((insn >> 26) == 0x12)
|
|
return 1;
|
|
|
return 0;
|
return 0;
|
}
|
}
|
|
|
void
|
void
|
_initialize_remote_or1k ()
|
_initialize_remote_or1k ()
|