Line 38... |
Line 38... |
#include <sys/types.h>
|
#include <sys/types.h>
|
#include <sys/stat.h>
|
#include <sys/stat.h>
|
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
#include <fcntl.h>
|
#include <fcntl.h>
|
|
|
|
#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);
|
|
|
/* JTAG or1k target ops. */
|
/* JTAG or1k target ops. */
|
Line 147... |
Line 149... |
static int or1k_is_open = 0;
|
static int or1k_is_open = 0;
|
|
|
/* Error last occured, zero = ok. */
|
/* Error last occured, zero = ok. */
|
int err = 0;
|
int err = 0;
|
|
|
/* Nonzero, if we changed something. */
|
/* Nonzero, if we changed something (except DMR1 which is updated on every run anyway). */
|
int debug_regs_changed;
|
int debug_regs_changed;
|
|
|
/* Number of interrupts while waiting for process. */
|
/* Number of interrupts while waiting for process. */
|
static int interrupt_count = 0;
|
static int interrupt_count = 0;
|
|
|
Line 175... |
Line 177... |
|
|
/* 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 */
|
int matchpoint_user_count[MAX_MATCHPOINTS] = {0};
|
int matchpoint_user_count[MAX_MATCHPOINTS] = {0};
|
|
|
|
/* Old SIGINT handler. */
|
|
static void (*ofunc) PARAMS ((int));
|
|
|
|
|
/* Handle low-level error that we can't recover from. Note that just
|
/* Handle low-level error that we can't recover from. Note that just
|
error()ing out from target_wait or some such low-level place will cause
|
error()ing out from target_wait or some such low-level place will cause
|
all hell to break loose--the rest of GDB will tend to get left in an
|
all hell to break loose--the rest of GDB will tend to get left in an
|
inconsistent state. */
|
inconsistent state. */
|
|
|
Line 293... |
Line 300... |
or1k_write_spr_reg (regno, data)
|
or1k_write_spr_reg (regno, data)
|
unsigned int regno;
|
unsigned int regno;
|
unsigned int data;
|
unsigned int data;
|
{
|
{
|
or1k_set_chain (SC_RISC_DEBUG);
|
or1k_set_chain (SC_RISC_DEBUG);
|
or1k_write_reg (regno + REG_SPACE, (ULONGEST)data);
|
or1k_write_reg (regno, (ULONGEST)data);
|
}
|
}
|
|
|
/* Reads register SPR from regno. */
|
/* Reads register SPR from regno. */
|
|
|
unsigned int
|
unsigned int
|
or1k_read_spr_reg (regno)
|
or1k_read_spr_reg (regno)
|
unsigned int regno;
|
unsigned int regno;
|
{
|
{
|
or1k_set_chain (SC_RISC_DEBUG);
|
or1k_set_chain (SC_RISC_DEBUG);
|
return or1k_read_reg (regno + REG_SPACE);
|
return or1k_read_reg (regno);
|
|
}
|
|
|
|
/* Sets mem to data. */
|
|
|
|
void
|
|
or1k_write_mem (addr, data)
|
|
unsigned int addr;
|
|
unsigned int data;
|
|
{
|
|
or1k_set_chain (SC_WISHBONE);
|
|
or1k_write_reg (addr, (ULONGEST)data);
|
|
}
|
|
|
|
/* Reads register SPR from regno. */
|
|
|
|
unsigned int
|
|
or1k_read_mem (addr)
|
|
unsigned int addr;
|
|
{
|
|
or1k_set_chain (SC_WISHBONE);
|
|
return or1k_read_reg (addr);
|
}
|
}
|
|
|
/* CZ 15/09/01 -- This is hacked in right now. This should
|
/* CZ 15/09/01 -- This is hacked in right now. This should
|
probably NOT be called directly, but at the moment I don't
|
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
|
have the time to figure out how to do it right. The problem
|
Line 369... |
Line 397... |
{
|
{
|
int val;
|
int val;
|
or1k_set_chain (SC_REGISTER);
|
or1k_set_chain (SC_REGISTER);
|
val = or1k_read_reg (JTAG_RISCOP);
|
val = or1k_read_reg (JTAG_RISCOP);
|
or1k_write_reg (JTAG_RISCOP, val | 1);
|
or1k_write_reg (JTAG_RISCOP, val | 1);
|
|
or1k_read_reg (JTAG_RISCOP);
|
|
|
/* Be cautious - disable trace. */
|
/* Be cautious - disable trace. */
|
val = or1k_read_reg (JTAG_MODER);
|
val = or1k_read_reg (JTAG_MODER);
|
or1k_write_reg (JTAG_MODER, val & ~2);
|
or1k_write_reg (JTAG_MODER, val & ~2);
|
or1k_flush_pipeline ();
|
|
}
|
}
|
|
|
/* Unstalls the CPU. */
|
/* Unstalls the CPU. */
|
|
|
static void
|
static void
|
Line 387... |
Line 415... |
|
|
|
|
or1k_set_chain (SC_REGISTER);
|
or1k_set_chain (SC_REGISTER);
|
val = or1k_read_reg (JTAG_RISCOP);
|
val = or1k_read_reg (JTAG_RISCOP);
|
or1k_write_reg (JTAG_RISCOP, val & ~1);
|
or1k_write_reg (JTAG_RISCOP, val & ~1);
|
|
or1k_read_reg (JTAG_RISCOP);
|
}
|
}
|
|
|
/* Resets the CPU and stalls it. */
|
/* Resets the CPU and stalls it. */
|
|
|
static void
|
static void
|
or1k_reset ()
|
or1k_reset ()
|
{
|
{
|
unsigned int val;
|
unsigned int val;
|
|
int i;
|
|
debug ("%08x\n", or1k_read_reg (JTAG_RISCOP));
|
or1k_set_chain (SC_REGISTER);
|
or1k_set_chain (SC_REGISTER);
|
|
|
/* Be cautious - disable trace. */
|
/* Be cautious - disable trace. */
|
val = or1k_read_reg (JTAG_MODER);
|
val = or1k_read_reg (JTAG_MODER);
|
or1k_write_reg (JTAG_MODER, val & ~2);
|
or1k_write_reg (JTAG_MODER, val & ~2);
|
Line 406... |
Line 437... |
val = or1k_read_reg (JTAG_RISCOP);
|
val = or1k_read_reg (JTAG_RISCOP);
|
val &= ~3;
|
val &= ~3;
|
/* Assert reset signal. */
|
/* Assert reset signal. */
|
or1k_write_reg (JTAG_RISCOP, val | 3);
|
or1k_write_reg (JTAG_RISCOP, val | 3);
|
|
|
|
/* Just do something */
|
|
for (i = 0; i < 100; i++)
|
|
or1k_read_reg (JTAG_RISCOP);
|
|
|
/* give it some time */
|
/* give it some time */
|
usleep (1000);
|
usleep (1000);
|
or1k_flush_pipeline ();
|
|
|
|
or1k_set_chain (SC_REGISTER); /* CZ: Changed 16/06/01...must reset
|
or1k_set_chain (SC_REGISTER);
|
scan chain after flush_pipeline() */
|
|
/* Release reset signal, but keep in stall state. */
|
/* Release reset signal, but keep in stall state. */
|
or1k_write_reg (JTAG_RISCOP, val | 1);
|
or1k_write_reg (JTAG_RISCOP, val | 1);
|
or1k_flush_pipeline ();
|
or1k_read_reg (JTAG_RISCOP);
|
}
|
}
|
|
|
/* Synchronizes debug registers in memory with those on target,
|
/* Synchronizes debug registers in memory with those on target,
|
if there is any change. */
|
if there is any change. */
|
|
|
Line 492... |
Line 525... |
|
|
or1k_status = TARGET_CONNECTING;
|
or1k_status = TARGET_CONNECTING;
|
if (current_or1k_target != NULL && current_or1k_target->to_init != NULL)
|
if (current_or1k_target != NULL && current_or1k_target->to_init != NULL)
|
current_or1k_target->to_init (args);
|
current_or1k_target->to_init (args);
|
|
|
or1k_reset ();
|
debug("%08x\n", read_pc ());
|
|
or1k_stall ();
|
|
debug("%08x\n", read_pc ());
|
|
usleep (1000);
|
|
|
/* Determine implementation configuration. */
|
/* Determine implementation configuration. */
|
or1k_implementation.VR = or1k_read_spr_reg (VR_SPRNUM);
|
or1k_implementation.VR = or1k_read_spr_reg (VR_SPRNUM);
|
or1k_implementation.UPR = or1k_read_spr_reg (UPR_SPRNUM);
|
or1k_implementation.UPR = or1k_read_spr_reg (UPR_SPRNUM);
|
|
|
Line 542... |
Line 578... |
or1k_commit_debug_registers ();
|
or1k_commit_debug_registers ();
|
|
|
if (err != 0)
|
if (err != 0)
|
error ("Cannot connect.");
|
error ("Cannot connect.");
|
|
|
|
/* Enable exceptions */
|
|
or1k_write_spr_reg (SR_SPRNUM, or1k_read_spr_reg(SR_SPRNUM) | 0x2);
|
|
|
/* Stop when breakpoint occurs. */
|
/* Stop when breakpoint occurs. */
|
or1k_write_spr_reg (DSR_SPRNUM, 0x1000);
|
or1k_write_spr_reg (DSR_SPRNUM, 0x2000);
|
|
|
do_cleanups (old_cleanups);
|
do_cleanups (old_cleanups);
|
|
|
/* This should cause an error if not connected. */
|
/* This should cause an error if not connected. */
|
or1k_fetch_registers (-1);
|
or1k_fetch_registers (-1);
|
Line 603... |
Line 642... |
set_current_frame (create_new_frame (read_fp (), stop_pc));
|
set_current_frame (create_new_frame (read_fp (), stop_pc));
|
select_frame (get_current_frame (), 0);
|
select_frame (get_current_frame (), 0);
|
print_stack_frame (selected_frame, -1, 1);
|
print_stack_frame (selected_frame, -1, 1);
|
}
|
}
|
|
|
|
/* This is the generic stop called via the target vector. When a target
|
|
interrupt is requested, either by the command line or the GUI, we
|
|
will eventually end up here. */
|
|
static void
|
|
or1k_stop ()
|
|
{
|
|
/* Send a break or a ^C, depending on user preference. */
|
|
debug ("remote_stop called\n");
|
|
|
|
/* We should not stop the target immediately, since it can be in an
|
|
unfinished state. So we do a single step. This should not affect
|
|
on anything. */
|
|
or1k_stall ();
|
|
/* HW STEP. Set DMR1_ST. */
|
|
dmr1 |= DMR1_ST;
|
|
or1k_write_spr_reg (DMR1_SPRNUM, dmr1);
|
|
dmr1 &= ~DMR1_ST;
|
|
or1k_unstall ();
|
|
}
|
|
|
/* Close a connection to the remote board. */
|
/* Close a connection to the remote board. */
|
|
|
static void
|
static void
|
or1k_close (quitting)
|
or1k_close (quitting)
|
int quitting;
|
int quitting;
|
Line 672... |
Line 731... |
}
|
}
|
}
|
}
|
fclose (fd);
|
fclose (fd);
|
}
|
}
|
|
|
|
/* ^C Interrupt handling */
|
|
|
|
/* Ask the user what to do when an interrupt is received. */
|
|
static void
|
|
interrupt_query ()
|
|
{
|
|
target_terminal_ours ();
|
|
|
|
if (query ("Interrupted while waiting for the program.\n\
|
|
Give up (and stop debugging it)? "))
|
|
{
|
|
target_mourn_inferior ();
|
|
return_to_top_level (RETURN_QUIT);
|
|
}
|
|
|
|
target_terminal_inferior ();
|
|
}
|
|
|
|
static void or1k_interrupt_twice (int signo);
|
|
|
|
|
|
/* The command line interface's stop routine. This function is installed
|
|
as a signal handler for SIGINT. The first time a user requests a
|
|
stop, we call remote_stop to send a break or ^C. If there is no
|
|
response from the target (it didn't stop when the user requested it),
|
|
we ask the user if he'd like to detach from the target. */
|
|
static void
|
|
or1k_interrupt (signo)
|
|
int signo;
|
|
{
|
|
debug ("interrupt");
|
|
/* If this doesn't work, try more severe steps. */
|
|
signal (signo, or1k_interrupt_twice);
|
|
|
|
debug ("remote_interrupt called\n");
|
|
|
|
interrupt_count++;
|
|
}
|
|
|
|
/* The user typed ^C twice. */
|
|
|
|
static void
|
|
or1k_interrupt_twice (signo)
|
|
int signo;
|
|
{
|
|
debug ("interrupt2");
|
|
signal (signo, ofunc);
|
|
interrupt_query ();
|
|
signal (signo, or1k_interrupt);
|
|
}
|
|
|
/* Resume execution of the target process. STEP says whether to single-step
|
/* Resume execution of the target process. STEP says whether to single-step
|
or to run free; SIGGNAL is the signal value (e.g. SIGINT) to be given
|
or to run free; SIGGNAL is the signal value (e.g. SIGINT) to be given
|
to the target, or zero for no signal. */
|
to the target, or zero for no signal. */
|
|
|
static void
|
static void
|
or1k_resume (pid, step, siggnal)
|
or1k_resume (pid, step, siggnal)
|
int pid, step;
|
int pid, step;
|
enum target_signal siggnal;
|
enum target_signal siggnal;
|
{
|
{
|
|
debug ("pc = %08x\n", read_pc());
|
|
debug ("resume %i, %i, %i\n",step, siggnal, or1k_status);
|
if (or1k_status != TARGET_STOPPED)
|
if (or1k_status != TARGET_STOPPED)
|
if (or1k_status == TARGET_RUNNING)
|
if (or1k_status == TARGET_RUNNING)
|
error ("Program is already running.");
|
error ("Program is already running.");
|
else
|
else
|
error ("The program is not being run.");
|
error ("The program is not being run.");
|
|
|
|
|
/* 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 ();
|
|
|
/* Else clause added by CZ 26/06/01 */
|
/* Else clause added by CZ 26/06/01 */
|
if (step)
|
if (step)
|
{
|
{
|
/* HW STEP. Set DMR1_ST. */
|
/* HW STEP. Set DMR1_ST. */
|
dmr1 |= DMR1_ST;
|
dmr1 |= DMR1_ST;
|
Line 705... |
Line 819... |
{
|
{
|
dmr1 &= ~DMR1_ST;
|
dmr1 &= ~DMR1_ST;
|
or1k_write_spr_reg (DMR1_SPRNUM, dmr1);
|
or1k_write_spr_reg (DMR1_SPRNUM, dmr1);
|
}
|
}
|
|
|
or1k_commit_debug_registers ();
|
|
/* Run the target. */
|
/* Run the target. */
|
#ifdef NEW_PC_HANDLING
|
#ifdef NEW_PC_HANDLING
|
|
|
/* In the new style PC handling mode, we should always
|
/* In the new style PC handling mode, we should always
|
keep stepping the target until we get out of the
|
keep stepping the target until we get out of the
|
Line 729... |
Line 842... |
#endif
|
#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);
|
}
|
}
|
|
|
/* Wait until the remote stops, and return a wait status. */
|
/* Wait until the remote stops, and return a wait status. */
|
|
|
static int
|
static int
|
or1k_wait (pid, status)
|
or1k_wait (pid, status)
|
int pid;
|
int pid;
|
struct target_waitstatus *status;
|
struct target_waitstatus *status;
|
{
|
{
|
|
unsigned long val;
|
|
unsigned long pc;
|
|
char buf[MAX_REGISTER_RAW_SIZE];
|
interrupt_count = 0;
|
interrupt_count = 0;
|
|
|
|
debug ("pc = %08x\n", read_pc());
|
|
debug ("wait %i %i\n", pid, or1k_status);
|
/* If we have not sent a single step or continue command, then the
|
/* If we have not sent a single step or continue command, then the
|
board is waiting for us to do something. Return a status
|
board is waiting for us to do something. Return a status
|
indicating that it is stopped. */
|
indicating that it is stopped. */
|
if (or1k_status != TARGET_RUNNING)
|
if (or1k_status != TARGET_RUNNING)
|
{
|
{
|
Line 755... |
Line 874... |
}
|
}
|
|
|
if (err)
|
if (err)
|
or1k_error ("Remote failure: %s", or1k_err_name (err));
|
or1k_error ("Remote failure: %s", or1k_err_name (err));
|
|
|
/* Wait for or1k DRR register to be nonzero. */
|
/* Set new signal handler */
|
interrupt_requested = 0;
|
ofunc = signal (SIGINT, or1k_interrupt);
|
old_sigint = signal (SIGINT, or1k_request_int);
|
|
do
|
/* Wait for risc to stop. */
|
{
|
do {
|
if(interrupt_requested)
|
or1k_set_chain (SC_REGISTER);
|
{
|
val = or1k_read_reg (JTAG_RISCOP);
|
or1k_stall();
|
|
status->kind = TARGET_WAITKIND_STOPPED;
|
/* When we press Ctrl-C, interrupt count is set, but we must wait
|
status->value.sig = TARGET_SIGNAL_INT;
|
for or1k_read_reg to finish, otherwise we would interrupt transaction. */
|
or1k_status = TARGET_STOPPED;
|
if (interrupt_count)
|
or1k_read_trace();
|
or1k_stop ();
|
return 0;
|
|
}
|
|
drr = or1k_read_spr_reg (DRR_SPRNUM);
|
|
usleep (10);
|
usleep (10);
|
}
|
debug ("%i", val);
|
while (drr == 0);
|
} while ((val & 1) == 0);
|
|
|
|
drr = or1k_read_spr_reg (DRR_SPRNUM);
|
|
|
|
/* Restore old INT signal handler */
|
|
signal (SIGINT, ofunc);
|
|
|
|
/* If we encounter breakpoint, drr is not set, so we set it manually. */
|
|
if (!drr)
|
|
drr |= DRR_BE;
|
|
|
signal (SIGINT, old_sigint);
|
|
status->kind = TARGET_WAITKIND_STOPPED;
|
status->kind = TARGET_WAITKIND_STOPPED;
|
or1k_flush_pipeline ();
|
|
|
debug ("epcr0 = %08x\n", or1k_read_spr_reg (EPCR0_SPRNUM));
|
|
debug ("drr = %08x\n", drr);
|
|
|
|
pc = read_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 804... |
Line 933... |
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_TE)
|
else if (drr & DRR_BE2)
|
status->value.sig = TARGET_SIGNAL_REALTIME_41;
|
|
else if (drr & DRR_SS) /* CZ 16/09/01 */
|
|
status->value.sig = TARGET_SIGNAL_TRAP;
|
|
else
|
|
{
|
{
|
|
/* PC has already stepped over the l.trap instruction. */
|
|
pc -= 4;
|
|
status->value.sig = TARGET_SIGNAL_TRAP;
|
|
} 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! */
|
|
/* We got the number the register holds, but gdb expects to see a
|
|
value in the target byte ordering. */
|
|
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. */
|
if (status->value.sig == TARGET_SIGNAL_TRAP)
|
if (status->value.sig == TARGET_SIGNAL_TRAP)
|
Line 846... |
Line 981... |
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
|
value BRK_INSTR_STRUCT */
|
value BRK_INSTR_STRUCT */
|
|
|
if(b_insn == or1k_read_reg((pc >> 2) + MEM_SPACE))
|
if(b_insn == or1k_read_mem((pc & 3)))
|
{
|
{
|
or1k_write_spr_reg(PC_SPRNUM,value);
|
or1k_write_spr_reg(PC_SPRNUM,value);
|
}
|
}
|
#endif
|
#endif
|
|
|
Line 887... |
Line 1022... |
&& func_start == pc)
|
&& func_start == pc)
|
status->kind = TARGET_WAITKIND_EXITED;
|
status->kind = TARGET_WAITKIND_EXITED;
|
}
|
}
|
|
|
or1k_read_trace ();
|
or1k_read_trace ();
|
|
debug ("-wait %i %i\n", pid, or1k_status);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/* Fetch a word from the target board. All memory accesses to the
|
/* Fetch a word from the target board. All memory accesses to the
|
remote board are word aligned. */
|
remote board are word aligned. */
|
Line 903... |
Line 1039... |
{
|
{
|
int subaddr = addr & 3;
|
int subaddr = addr & 3;
|
unsigned char buf[8];
|
unsigned char buf[8];
|
unsigned int low, high;
|
unsigned int low, high;
|
addr >>= 2;
|
addr >>= 2;
|
low = or1k_read_reg (addr + MEM_SPACE);
|
low = or1k_read_mem (addr << 2);
|
high = or1k_read_reg (addr + 1 + MEM_SPACE);
|
high = or1k_read_reg ((addr + 1) << 2);
|
memcpy (&buf[0], &low, 4);
|
memcpy (&buf[0], &low, 4);
|
memcpy (&buf[4], &high, 4);
|
memcpy (&buf[4], &high, 4);
|
memcpy (&low, &buf[subaddr], 4);
|
memcpy (&low, &buf[subaddr], 4);
|
return low;
|
return low;
|
}
|
}
|
else
|
else
|
{
|
{
|
addr >>= 2;
|
return or1k_read_mem (addr);
|
return or1k_read_reg (addr + MEM_SPACE);
|
|
}
|
}
|
}
|
}
|
|
|
/* Store a word to the target board. Returns errno code or zero for
|
/* Store a word to the target board. Returns errno code or zero for
|
success. All memory accesses to the remote board are word aligned. */
|
success. All memory accesses to the remote board are word aligned. */
|
Line 931... |
Line 1066... |
{
|
{
|
int subaddr = addr & 3;
|
int subaddr = addr & 3;
|
unsigned char buf[8];
|
unsigned char buf[8];
|
unsigned int low, high;
|
unsigned int low, high;
|
addr >>= 2;
|
addr >>= 2;
|
low = or1k_read_reg (addr + MEM_SPACE);
|
low = or1k_read_mem (addr << 2);
|
high = or1k_read_reg (addr + 1 + MEM_SPACE);
|
high = or1k_read_mem ((addr + 1) << 2);
|
memcpy (&buf[0], &low, 4);
|
memcpy (&buf[0], &low, 4);
|
memcpy (&buf[4], &high, 4);
|
memcpy (&buf[4], &high, 4);
|
memcpy (&buf[subaddr], &val, 4);
|
memcpy (&buf[subaddr], &val, 4);
|
memcpy (&low, &buf[0], 4);
|
memcpy (&low, &buf[0], 4);
|
memcpy (&high, &buf[4], 4);
|
memcpy (&high, &buf[4], 4);
|
or1k_write_reg (addr + MEM_SPACE, low);
|
or1k_write_mem (addr << 2, low);
|
or1k_write_reg (addr + 1 + MEM_SPACE, high);
|
or1k_write_mem ((addr + 1) << 2, high);
|
}
|
}
|
else
|
else
|
{
|
{
|
addr >>= 2;
|
or1k_write_mem (addr, val);
|
or1k_write_reg (addr + MEM_SPACE, val);
|
|
}
|
}
|
return err;
|
return err;
|
}
|
}
|
|
|
/* Fetch the remote registers. */
|
/* Fetch the remote registers. */
|
Line 980... |
Line 1114... |
store_unsigned_integer (buf, REGISTER_RAW_SIZE (regno), val);
|
store_unsigned_integer (buf, REGISTER_RAW_SIZE (regno), val);
|
supply_register (regno, buf);
|
supply_register (regno, buf);
|
}
|
}
|
if (err)
|
if (err)
|
or1k_error ("Can't read register %d(%i): %s", regno,
|
or1k_error ("Can't read register %d(%i): %s", regno,
|
REGNUM_TO_SPRNUM(regno) + REG_SPACE, or1k_err_name (err));
|
REGNUM_TO_SPRNUM(regno), or1k_err_name (err));
|
}
|
}
|
|
|
/* Fetch and return instruction from the specified location. */
|
/* Fetch and return instruction from the specified location. */
|
|
|
unsigned int
|
unsigned int
|
Line 1021... |
Line 1155... |
}
|
}
|
|
|
if (regno >= NUM_REGS)
|
if (regno >= NUM_REGS)
|
error("Invalid register number!");
|
error("Invalid register number!");
|
|
|
or1k_write_spr_reg (REGNUM_TO_SPRNUM(regno), or1k_read_spr_reg (REGNUM_TO_SPRNUM(regno)));
|
or1k_write_spr_reg (REGNUM_TO_SPRNUM(regno), read_register (regno));
|
if (err)
|
if (err)
|
or1k_error ("Can't write register %d(%i): %s", regno, REGNUM_TO_SPRNUM(regno), or1k_err_name (err));
|
or1k_error ("Can't write register %d(%i): %s", regno, REGNUM_TO_SPRNUM(regno), or1k_err_name (err));
|
}
|
}
|
|
|
/* Read or write LEN bytes from inferior memory at MEMADDR,
|
/* Read or write LEN bytes from inferior memory at MEMADDR,
|
Line 1054... |
Line 1188... |
|
|
int block_xfer_size = 256; /* CZ 21/06/01 ... number of 32 bit words */
|
int block_xfer_size = 256; /* CZ 21/06/01 ... number of 32 bit words */
|
int nBlocks = (count + block_xfer_size -1)/block_xfer_size;
|
int nBlocks = (count + block_xfer_size -1)/block_xfer_size;
|
int terminate = 0; /* Terminate the printing of '*'s... */
|
int terminate = 0; /* Terminate the printing of '*'s... */
|
|
|
|
#ifdef DEBUG_JTAG
|
|
debug ("xfer_memory %s addr=%x, len=%i, \n", write?"write":"read", memaddr, len);
|
|
fflush(stdout);
|
|
#endif
|
|
|
|
#if 0
|
if (memaddr >= MEM_SPACE)
|
if (memaddr >= MEM_SPACE)
|
error("Invalid address");
|
error("Invalid address");
|
|
#endif
|
|
|
/* (CZ 21/06/01 -- because upper layers which know nothing about
|
/* (CZ 21/06/01 -- because upper layers which know nothing about
|
Or1k or JTAG call this function directly, it is always necessary
|
Or1k or JTAG call this function directly, it is always necessary
|
to set the chain to point to the Debug Unit. Otherwise, it may
|
to set the chain to point to the Debug Unit. Otherwise, it may
|
be pointing to the Development Interface chain, in which case
|
be pointing to the Development Interface chain, in which case
|
we're going to get bupkiss... */
|
we're going to get bupkiss... */
|
|
|
or1k_set_chain (SC_RISC_DEBUG);
|
|
|
|
if (write)
|
if (write)
|
{
|
{
|
/* Fill start and end extra bytes of buffer with existing data. */
|
/* Fill start and end extra bytes of buffer with existing data. */
|
if (addr != memaddr || len < 4)
|
if (addr != memaddr || len < 4)
|
{
|
{
|
Line 1103... |
Line 1242... |
return 0;
|
return 0;
|
}
|
}
|
|
|
for(j=0;j<n;j++)
|
for(j=0;j<n;j++)
|
__buf[j] = (unsigned long)extract_unsigned_integer(&buffer[(i * block_xfer_size +j)*4], 4);
|
__buf[j] = (unsigned long)extract_unsigned_integer(&buffer[(i * block_xfer_size +j)*4], 4);
|
|
or1k_set_chain (SC_WISHBONE);
|
status = or1k_store_block(addr,__buf,n);
|
status = or1k_store_block(addr,__buf,n);
|
free(__buf);
|
free(__buf);
|
if(n == block_xfer_size)
|
if(n == block_xfer_size)
|
{
|
{
|
printf_unfiltered ("*");
|
debug ("*");
|
gdb_flush (gdb_stdout);
|
gdb_flush (gdb_stdout);
|
}
|
}
|
if (status)
|
if (status)
|
{
|
{
|
errno = status;
|
errno = status;
|
return 0;
|
return 0;
|
}
|
}
|
/* FIXME: Do we want a QUIT here? */
|
/* FIXME: Do we want a QUIT here? */
|
}
|
}
|
if (terminate)
|
if (terminate)
|
printf_unfiltered ("\n");
|
debug ("\n");
|
}
|
}
|
else
|
else
|
{
|
{
|
for(i=0;i<nBlocks;i++,count-=block_xfer_size,addr += block_xfer_size*4)
|
for(i=0;i<nBlocks;i++,count-=block_xfer_size,addr += block_xfer_size*4)
|
{
|
{
|
int j;
|
int j;
|
int n = count < block_xfer_size ? count : block_xfer_size;
|
int n = count < block_xfer_size ? count : block_xfer_size;
|
unsigned long *__buf;
|
unsigned long *__buf;
|
|
|
|
or1k_set_chain (SC_WISHBONE);
|
__buf = (unsigned long*)malloc(n*sizeof(unsigned long));
|
__buf = (unsigned long*)malloc(n*sizeof(unsigned long));
|
status = or1k_load_block(addr,__buf,n);
|
status = or1k_load_block(addr,__buf,n);
|
if (!status)
|
if (!status)
|
for(j=0;j<n;j++)
|
for(j=0;j<n;j++)
|
store_unsigned_integer (&buffer[(i * block_xfer_size +j)*4], 4, __buf[j]);
|
store_unsigned_integer (&buffer[(i * block_xfer_size +j)*4], 4, __buf[j]);
|
Line 1149... |
Line 1290... |
}
|
}
|
|
|
int or1k_load_block(CORE_ADDR addr,void* buffer,int nRegisters)
|
int or1k_load_block(CORE_ADDR addr,void* buffer,int nRegisters)
|
{
|
{
|
int i=0;
|
int i=0;
|
unsigned int regno = (addr >> 2) + MEM_SPACE;
|
unsigned int regno = addr;
|
|
|
if (current_or1k_target != NULL && current_or1k_target->to_read_block != NULL)
|
if (current_or1k_target != NULL && current_or1k_target->to_read_block != NULL)
|
return current_or1k_target->to_read_block (regno,buffer,nRegisters);
|
return current_or1k_target->to_read_block (regno,buffer,nRegisters);
|
else
|
else
|
for(i=0;i<nRegisters;i++)
|
for(i=0;i<nRegisters;i++)
|
Line 1161... |
Line 1302... |
return 0;
|
return 0;
|
}
|
}
|
|
|
int or1k_store_block(CORE_ADDR addr,void* buffer,int nRegisters)
|
int or1k_store_block(CORE_ADDR addr,void* buffer,int nRegisters)
|
{
|
{
|
unsigned int regno = (addr >> 2) + MEM_SPACE;
|
unsigned int regno = addr;
|
|
|
if (current_or1k_target != NULL && current_or1k_target->to_write_block != NULL)
|
if (current_or1k_target != NULL && current_or1k_target->to_write_block != NULL)
|
return current_or1k_target->to_write_block (regno,buffer,nRegisters);
|
return current_or1k_target->to_write_block (regno,buffer,nRegisters);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/* Flushes pipeline. May not be needed by all implementations, but
|
|
it doen't hurt to do it. This function should be called every time
|
|
or1k stops.
|
|
When or1k stops it still has instructions in pipeline.
|
|
We do this by inserting nop instructions.
|
|
IF cycle remains unaffacted by writing to DIR, and it still holds
|
|
instruction, that caused break or watchpoint. */
|
|
|
|
void
|
|
or1k_flush_pipeline ()
|
|
{
|
|
/* CZ 15/09/01 -- Damjan has made it perfectly clear
|
|
that the DIR will not be implemented on any chip
|
|
as the entire concept is poorly conceived. This
|
|
section has therefore been removed. */
|
|
/* or1k_write_spr_reg (DIR_SPRNUM, NOP_INSTR);
|
|
or1k_write_spr_reg (DIR_SPRNUM, NOP_INSTR);
|
|
or1k_write_spr_reg (DIR_SPRNUM, NOP_INSTR); */
|
|
}
|
|
|
|
/* Print info on this target. */
|
/* Print info on this target. */
|
|
|
static void
|
static void
|
or1k_files_info (ignore)
|
or1k_files_info (ignore)
|
struct target_ops *ignore;
|
struct target_ops *ignore;
|
Line 1658... |
Line 1779... |
or1k_dummy_ops.to_kill = or1k_kill;
|
or1k_dummy_ops.to_kill = or1k_kill;
|
or1k_dummy_ops.to_load = generic_load;
|
or1k_dummy_ops.to_load = generic_load;
|
or1k_dummy_ops.to_create_inferior = or1k_create_inferior;
|
or1k_dummy_ops.to_create_inferior = or1k_create_inferior;
|
or1k_dummy_ops.to_mourn_inferior = or1k_mourn_inferior;
|
or1k_dummy_ops.to_mourn_inferior = or1k_mourn_inferior;
|
or1k_dummy_ops.to_stratum = process_stratum;
|
or1k_dummy_ops.to_stratum = process_stratum;
|
|
or1k_dummy_ops.to_stop = or1k_stop;
|
|
|
/* We can access memory while program is running. */
|
/* We can access memory while program is running. */
|
or1k_dummy_ops.to_has_all_memory = 0;
|
or1k_dummy_ops.to_has_all_memory = 0;
|
|
|
or1k_dummy_ops.to_has_memory = 1;
|
or1k_dummy_ops.to_has_memory = 1;
|