Line 164... |
Line 164... |
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;
|
|
|
static void (*old_sigint) (); /* Old signal-handler for sigint */
|
|
static int interrupt_requested = 0; /* Interrupted flag */
|
|
static void or1k_request_int ()
|
|
{
|
|
/* restore original signalhandler */
|
|
signal (SIGINT, old_sigint);
|
|
interrupt_requested = 1;
|
|
}
|
|
|
|
/* 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];
|
|
|
/* Number of matchpoint users */
|
/* Number of matchpoint users */
|
Line 334... |
Line 325... |
{
|
{
|
or1k_set_chain (SC_WISHBONE);
|
or1k_set_chain (SC_WISHBONE);
|
return or1k_read_reg (addr);
|
return or1k_read_reg (addr);
|
}
|
}
|
|
|
/* CZ 15/09/01 -- This is hacked in right now. This should
|
|
probably NOT be called directly, but at the moment I don't
|
|
have the time to figure out how to do it right. The problem
|
|
is the following, in order to write the PC, I may need to
|
|
step the processor...(long story, but trust me, I need to
|
|
do this)...I need to do this sometimes even when I have
|
|
not started or even loaded a program, thus I can not
|
|
use the default routines gdb provides for this purpose.
|
|
|
|
I do not wish to embed targets directly into or1k-tdep,
|
|
but I need a simple function there that will cause the
|
|
processor to continue 1 instruction and not pay attention
|
|
to gdb's state machine. I know this could conceivably break
|
|
things if we stop connecting via jtag and start doing
|
|
something else, so anyone who wants to figure out how to do
|
|
this right is welcome. Drop me an email if you want to
|
|
correct it. I'll try to help you understand the issue. */
|
|
|
|
/* The processor should already be in single step mode or
|
|
this will continue indefinitely! */
|
|
void or1k_do_1_processor_step()
|
|
{
|
|
unsigned long drr = 0;
|
|
unsigned long val;
|
|
|
|
/* Run the processor */
|
|
or1k_set_chain (SC_REGISTER);
|
|
val = or1k_read_reg (JTAG_RISCOP);
|
|
or1k_write_reg (JTAG_RISCOP, val & ~1);
|
|
|
|
/* Wait for the DEBUG_REASON_REGISTER to be non zero */
|
|
while(!(drr = or1k_read_spr_reg (DRR_SPRNUM)))
|
|
usleep (10);
|
|
|
|
/* OK..we're done */
|
|
}
|
|
|
|
static int saved_stall_state = 0;
|
|
void or1k_save_stall_state()
|
|
{
|
|
or1k_set_chain (SC_REGISTER);
|
|
saved_stall_state = or1k_read_reg (JTAG_RISCOP) & 0x01;
|
|
}
|
|
void or1k_restore_stall_state()
|
|
{
|
|
int val;
|
|
|
|
or1k_set_chain (SC_REGISTER);
|
|
val = or1k_read_reg (JTAG_RISCOP);
|
|
val |= saved_stall_state;
|
|
or1k_write_reg (JTAG_RISCOP, val);
|
|
saved_stall_state = 0;
|
|
}
|
|
|
|
/* Stalls the CPU. */
|
/* Stalls the CPU. */
|
|
|
static void
|
static void
|
or1k_stall ()
|
or1k_stall ()
|
{
|
{
|
Line 597... |
Line 534... |
/* 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);
|
trace_size = 0;
|
trace_size = 0;
|
|
or1k_status = TARGET_STOPPED;
|
}
|
}
|
|
|
/* Kill the process running on the board. */
|
/* Kill the process running on the board. */
|
|
|
void
|
void
|
Line 819... |
Line 757... |
{
|
{
|
dmr1 &= ~DMR1_ST;
|
dmr1 &= ~DMR1_ST;
|
or1k_write_spr_reg (DMR1_SPRNUM, dmr1);
|
or1k_write_spr_reg (DMR1_SPRNUM, dmr1);
|
}
|
}
|
|
|
/* Run the target. */
|
|
#ifdef NEW_PC_HANDLING
|
|
|
|
/* In the new style PC handling mode, we should always
|
|
keep stepping the target until we get out of the
|
|
breakpoint exception vector assuming that "step"
|
|
has been specified. Otherwise, this isn't
|
|
particularly useful, as we'll keep hitting the
|
|
same breakpoint that put us here in the first
|
|
place. By stepping out of this vector we guarantee
|
|
to step over the instruction that caused the
|
|
breakpoint, so when they are reinserted we are
|
|
already past that location. */
|
|
if(step)
|
|
{
|
|
while((or1k_read_spr_reg(PC_SPRNUM) & 0xFFFFFF00) == 0xD00)
|
|
or1k_do_1_processor_step();
|
|
}
|
|
#endif
|
|
|
|
/* 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 905... |
Line 823... |
status->kind = TARGET_WAITKIND_STOPPED;
|
status->kind = TARGET_WAITKIND_STOPPED;
|
|
|
debug ("epcr0 = %08x\n", or1k_read_spr_reg (EPCR0_SPRNUM));
|
debug ("epcr0 = %08x\n", or1k_read_spr_reg (EPCR0_SPRNUM));
|
debug ("drr = %08x\n", drr);
|
debug ("drr = %08x\n", drr);
|
|
|
|
registers_changed ();
|
pc = read_pc ();
|
pc = read_pc ();
|
|
debug ("pc = %08x\n", pc);
|
|
|
if (drr & DRR_RSTE)
|
if (drr & DRR_RSTE)
|
status->value.sig = TARGET_SIGNAL_REALTIME_33;
|
status->value.sig = TARGET_SIGNAL_REALTIME_33;
|
else if (drr & DRR_BUSEE)
|
else if (drr & DRR_BUSEE)
|
status->value.sig = TARGET_SIGNAL_BUS;
|
status->value.sig = TARGET_SIGNAL_BUS;
|
Line 933... |
Line 853... |
status->value.sig = TARGET_SIGNAL_REALTIME_39;
|
status->value.sig = TARGET_SIGNAL_REALTIME_39;
|
else if (drr & DRR_SCE)
|
else if (drr & DRR_SCE)
|
status->value.sig = TARGET_SIGNAL_REALTIME_40;
|
status->value.sig = TARGET_SIGNAL_REALTIME_40;
|
else if (drr & DRR_BE)
|
else if (drr & DRR_BE)
|
status->value.sig = TARGET_SIGNAL_TRAP;
|
status->value.sig = TARGET_SIGNAL_TRAP;
|
else if (drr & DRR_BE2)
|
else if (drr & DRR_TE)
|
{
|
{
|
/* PC has already stepped over the l.trap instruction. */
|
/* PC has already stepped over the l.trap instruction. */
|
pc -= 4;
|
pc -= 8;
|
status->value.sig = TARGET_SIGNAL_TRAP;
|
status->value.sig = TARGET_SIGNAL_TRAP;
|
} else {
|
} else {
|
status->value.sig = TARGET_SIGNAL_UNKNOWN;
|
status->value.sig = TARGET_SIGNAL_UNKNOWN;
|
warning ("Invalid exception occured.");
|
warning ("Invalid exception occured.");
|
}
|
}
|
|
|
/* Write into PC flushes the pipeline! */
|
/* Write into PC flushes the pipeline! */
|
/* We got the number the register holds, but gdb expects to see a
|
/* We got the number the register holds, but gdb expects to see a
|
value in the target byte ordering. */
|
value in the target byte ordering. */
|
store_unsigned_integer (buf, REGISTER_RAW_SIZE (PC_REGNUM), pc);
|
write_pc (pc);
|
supply_register (PC_REGNUM, buf);
|
/*or1k_write_spr_reg (PC_SPRNUM, pc);
|
|
store_unsigned_integer (buf, REGISTER_RAW_SIZE (PC_REGNUM), pc);
|
|
supply_register (PC_REGNUM, buf);*/
|
|
|
/* Log remote stop. */
|
/* Log remote stop. */
|
or1k_status = TARGET_STOPPED;
|
or1k_status = TARGET_STOPPED;
|
|
|
/* Determine what caused trap - breakpoint or watchpoint. */
|
/* Determine what caused trap - breakpoint or watchpoint. */
|
Line 972... |
Line 894... |
breakpoint = 1;
|
breakpoint = 1;
|
break;
|
break;
|
}
|
}
|
hit_watchpoint = !breakpoint;
|
hit_watchpoint = !breakpoint;
|
|
|
|
|
#ifndef NEW_PC_HANDLING
|
|
/* Cause the trap/breakpoint exception to be ignored. This is
|
/* Cause the trap/breakpoint exception to be ignored. This is
|
the behavior of the simulator when the PC value is changed
|
the behavior of the simulator when the PC value is changed
|
by a write command. All pending exceptions are cleared and
|
by a write command. All pending exceptions are cleared and
|
the simulator continues at the PC value specified. We need
|
the simulator continues at the PC value specified. We need
|
to do this if the instruction at the current PC has the
|
to do this if the instruction at the current PC has the
|
Line 985... |
Line 905... |
|
|
if(b_insn == or1k_read_mem((pc & 3)))
|
if(b_insn == or1k_read_mem((pc & 3)))
|
{
|
{
|
or1k_write_spr_reg(PC_SPRNUM,value);
|
or1k_write_spr_reg(PC_SPRNUM,value);
|
}
|
}
|
#endif
|
|
|
|
#ifdef NEW_PC_HANDLING
|
|
|
|
/* If we're a software breakpoint and we're currently located
|
|
in the breakpoint vector, then we need to reset the pc
|
|
back 4 bytes. This will ensure that the instruction gets
|
|
executed. If we don't do this, gdb will skip this instruction,
|
|
even if we set DECR_PC_AFTER_BREAK, which seems to have no
|
|
effect other than to calculate the correct breakpoint
|
|
address. */
|
|
|
|
if((b_insn == or1k_read_spr_reg(((pc-4) >> 2) + MEM_SPACE)) &&
|
|
or1k_read_spr_reg(PC_SPRNUM) == 0xD00)
|
|
or1k_write_spr_reg(EPC_SPRNUM(CURRENT_CID),pc-4);
|
|
|
|
#endif
|
|
|
|
}
|
}
|
else
|
else
|
hit_watchpoint = 0;
|
hit_watchpoint = 0;
|
|
|
/* If the stop PC is in the _exit function, assume
|
/* If the stop PC is in the _exit function, assume
|