printf_filtered("The following are valid <psim-option>s:\n");
printf_filtered("\n");
- printf_filtered("\t-i Print instruction counting statistics\n");
- if (verbose) { printf_filtered("\n"); }
+ printf_filtered("\t-c <count> Limit the simulation to <count> iterations\n");
+ if (verbose) {
+ printf_filtered("\n");
+ }
+
+ printf_filtered("\t-i or -i2 Print instruction counting statistics\n");
+ if (verbose) {
+ printf_filtered("\t Specify -i2 for a more detailed display\n");
+ printf_filtered("\n");
+ }
printf_filtered("\t-I Print execution unit statistics\n");
if (verbose) { printf_filtered("\n"); }
psim_usage(0);
error ("");
break;
+ case 'c':
+ param = find_arg("Missing <count> option for -c (max-iterations)\n", &argp, argv);
+ tree_parse(root, "/openprom/options/max-iterations %s", param);
+ break;
case 'e':
- param = find_arg("Missing <emul> option for -e\n", &argp, argv);
+ param = find_arg("Missing <emul> option for -e (os-emul)\n", &argp, argv);
tree_parse(root, "/openprom/options/os-emul %s", param);
break;
case 'f':
psim_usage(2);
break;
case 'i':
- tree_parse(root, "/openprom/trace/print-info 1");
+ if (isdigit(p[1])) {
+ tree_parse(root, "/openprom/trace/print-info %c", p[1]);
+ p++;
+ }
+ else {
+ tree_parse(root, "/openprom/trace/print-info 1");
+ }
break;
case 'I':
tree_parse(root, "/openprom/trace/print-info 2");
MODEL_ISSUE_PROCESS);
break;
case 'm':
- param = find_arg("Missing <model> option for -m\n", &argp, argv);
+ param = find_arg("Missing <model> option for -m (model)\n", &argp, argv);
tree_parse(root, "/openprom/options/model \"%s", param);
break;
case 'n':
- param = find_arg("Missing <nr-smp> option for -n\n", &argp, argv);
+ param = find_arg("Missing <nr-smp> option for -n (smp)\n", &argp, argv);
tree_parse(root, "/openprom/options/smp %s", param);
break;
case 'o':
current = tree_parse(current, "%s", param);
break;
case 'r':
- param = find_arg("Missing <ram-size> option for -r\n", &argp, argv);
+ param = find_arg("Missing <ram-size> option for -r (oea-memory-size)\n", &argp, argv);
tree_parse(root, "/openprom/options/oea-memory-size %s",
param);
break;
case 't':
- param = find_arg("Missing <trace> option for -t\n", &argp, argv);
+ param = find_arg("Missing <trace> option for -t (trace/*)\n", &argp, argv);
if (param[0] == '!')
tree_parse(root, "/openprom/trace/%s 0", param+1);
else
tree_parse(root, "/openprom/trace/%s 1", param);
break;
+ case 'E':
+ /* endian spec, ignored for now */
+ ++p;
+ break;
}
p += 1;
}
psim_restart(psim *system,
int current_cpu)
{
+ ASSERT(current_cpu >= 0 && current_cpu < system->nr_cpus);
+ ASSERT(system->path_to_restart != NULL);
system->last_cpu = current_cpu;
longjmp(*(jmp_buf*)(system->path_to_restart), current_cpu + 1);
}
stop_reason reason,
int signal)
{
- ASSERT(current_cpu >= 0 && current_cpu < system->nr_cpus);
+ ASSERT(current_cpu >= 0 && current_cpu <= system->nr_cpus);
+ ASSERT(system->path_to_halt != NULL);
system->last_cpu = current_cpu;
- system->halt_status.cpu_nr = current_cpu;
system->halt_status.reason = reason;
system->halt_status.signal = signal;
- system->halt_status.program_counter =
- cpu_get_program_counter(system->processors[current_cpu]);
+ if (current_cpu == system->nr_cpus) {
+ system->halt_status.cpu_nr = 0;
+ system->halt_status.program_counter =
+ cpu_get_program_counter(system->processors[0]);
+ }
+ else {
+ system->halt_status.cpu_nr = current_cpu;
+ system->halt_status.program_counter =
+ cpu_get_program_counter(system->processors[current_cpu]);
+ }
longjmp(*(jmp_buf*)(system->path_to_halt), current_cpu + 1);
}
+STATIC_INLINE_PSIM\
+(void)
+psim_max_iterations_exceeded(void *data)
+{
+ psim *system = data;
+ psim_halt(system,
+ system->nr_cpus, /* halted during an event */
+ was_signalled,
+ -1);
+}
+
+
INLINE_PSIM\
(void)
psim_init(psim *system)
/* trash any pending events */
event_queue_init(system->events);
+ /* if needed, schedule a halt event. FIXME - In the future this
+ will be replaced by a more generic change to psim_command(). A
+ new command `schedule NNN halt' being added. */
+ if (tree_find_property(system->devices, "/openprom/options/max-iterations")) {
+ event_queue_schedule(system->events,
+ tree_find_integer_property(system->devices,
+ "/openprom/options/max-iterations") - 2,
+ psim_max_iterations_exceeded,
+ system);
+ }
+
/* scrub all the cpus */
for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
cpu_init(system->processors[cpu_nr]);
cpu_page_tlb_invalidate_all(processor);
}
- /* force loop to start with first cpu (after processing events) */
- system->last_cpu = system->nr_cpus - 1;
+ /* force loop to start with first cpu */
+ system->last_cpu = -1;
}
INLINE_PSIM\
cpu *processor;
/* find our processor */
- if (which_cpu == MAX_NR_PROCESSORS)
- which_cpu = system->last_cpu;
- if (which_cpu < 0 || which_cpu >= system->nr_cpus)
- error("psim_read_register() - invalid processor %d\n", which_cpu);
+ if (which_cpu == MAX_NR_PROCESSORS) {
+ if (system->last_cpu == system->nr_cpus
+ || system->last_cpu == -1)
+ which_cpu = 0;
+ else
+ which_cpu = system->last_cpu;
+ }
+ ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
+
processor = system->processors[which_cpu];
/* find the register description */
char cooked_buf[sizeof(unsigned_8)];
/* find our processor */
- if (which_cpu == MAX_NR_PROCESSORS)
- which_cpu = system->last_cpu;
+ if (which_cpu == MAX_NR_PROCESSORS) {
+ if (system->last_cpu == system->nr_cpus
+ || system->last_cpu == -1)
+ which_cpu = 0;
+ else
+ which_cpu = system->last_cpu;
+ }
if (which_cpu == -1) {
int i;
for (i = 0; i < system->nr_cpus; i++)
psim_write_register(system, i, buf, reg, mode);
return;
}
- else if (which_cpu < 0 || which_cpu >= system->nr_cpus) {
- error("psim_read_register() - invalid processor %d\n", which_cpu);
- }
+ ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
processor = system->processors[which_cpu];
unsigned nr_bytes)
{
cpu *processor;
- if (which_cpu == MAX_NR_PROCESSORS)
- which_cpu = system->last_cpu;
- if (which_cpu < 0 || which_cpu >= system->nr_cpus)
- error("psim_read_memory() invalid cpu\n");
+ if (which_cpu == MAX_NR_PROCESSORS) {
+ if (system->last_cpu == system->nr_cpus
+ || system->last_cpu == -1)
+ which_cpu = 0;
+ else
+ which_cpu = system->last_cpu;
+ }
processor = system->processors[which_cpu];
return vm_data_map_read_buffer(cpu_data_map(processor),
buffer, vaddr, nr_bytes,
int violate_read_only_section)
{
cpu *processor;
- if (which_cpu == MAX_NR_PROCESSORS)
- which_cpu = system->last_cpu;
- if (which_cpu < 0 || which_cpu >= system->nr_cpus)
- error("psim_read_memory() invalid cpu\n");
+ if (which_cpu == MAX_NR_PROCESSORS) {
+ if (system->last_cpu == system->nr_cpus
+ || system->last_cpu == -1)
+ which_cpu = 0;
+ else
+ which_cpu = system->last_cpu;
+ }
+ ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
processor = system->processors[which_cpu];
return vm_data_map_write_buffer(cpu_data_map(processor),
buffer, vaddr, nr_bytes, 1/*violate-read-only*/,
#endif
#include "defs.h"
+#include "bfd.h"
#include "callback.h"
#include "remote-sim.h"
static device *root_device;
static const char *register_names[] = REGISTER_NAMES;
-void
-sim_open (char *args)
+/* For communication between sim_load and sim_create_inferior.
+ This can be made to go away, please do. */
+static unsigned_word entry_point;
+
+SIM_DESC
+sim_open (SIM_OPEN_KIND kind, char **argv)
{
/* Note: The simulation is not created by sim_open() because
complete information is not yet available */
/* trace the call */
- TRACE(trace_gdb, ("sim_open(args=%s) called\n", args ? args : "(null)"));
+ TRACE(trace_gdb, ("sim_open called\n"));
if (root_device != NULL)
sim_io_printf_filtered("Warning - re-open of simulator leaks memory\n");
root_device = psim_tree();
simulator = NULL;
- if (args) {
- char **argv = buildargv(args);
- psim_options(root_device, argv);
- freeargv(argv);
- }
+ psim_options(root_device, argv + 1);
if (ppc_trace[trace_opts])
print_options ();
+
+ /* fudge our descriptor for now */
+ return (SIM_DESC) 1;
}
void
-sim_close (int quitting)
+sim_close (SIM_DESC sd, int quitting)
{
TRACE(trace_gdb, ("sim_close(quitting=%d) called\n", quitting));
if (ppc_trace[trace_print_info] && simulator != NULL)
}
-int
-sim_load (char *prog, int from_tty)
+SIM_RC
+sim_load (SIM_DESC sd, char *prog, bfd *abfd, int from_tty)
{
char **argv;
TRACE(trace_gdb, ("sim_load(prog=%s, from_tty=%d) called\n",
/* release the arguments */
freeargv(argv);
- /* `I did it my way' */
- return 0;
+ /* get the start address */
+ if (abfd != NULL)
+ entry_point = bfd_get_start_address (abfd);
+ else
+ {
+ abfd = bfd_openr (argv[0], 0);
+ if (abfd == NULL)
+ error ("psim: can't open \"%s\": %s\n",
+ argv[0], bfd_errmsg (bfd_get_error ()));
+ if (!bfd_check_format (abfd, bfd_object))
+ {
+ const char *errmsg = bfd_errmsg (bfd_get_error ());
+ bfd_close (abfd);
+ error ("psim: \"%s\" is not an object file: %s\n",
+ argv[0], errmsg);
+ }
+ entry_point = bfd_get_start_address (abfd);
+ bfd_close (abfd);
+ }
+
+ return SIM_RC_OK;
}
void
-sim_kill (void)
+sim_kill (SIM_DESC sd)
{
TRACE(trace_gdb, ("sim_kill(void) called\n"));
/* do nothing, nothing to do */
int
-sim_read (SIM_ADDR mem, unsigned char *buf, int length)
+sim_read (SIM_DESC sd, SIM_ADDR mem, unsigned char *buf, int length)
{
int result = psim_read_memory(simulator, MAX_NR_PROCESSORS,
buf, mem, length);
int
-sim_write (SIM_ADDR mem, unsigned char *buf, int length)
+sim_write (SIM_DESC sd, SIM_ADDR mem, unsigned char *buf, int length)
{
int result = psim_write_memory(simulator, MAX_NR_PROCESSORS,
buf, mem, length,
void
-sim_fetch_register (int regno, unsigned char *buf)
+sim_fetch_register (SIM_DESC sd, int regno, unsigned char *buf)
{
if (simulator == NULL) {
return;
void
-sim_store_register (int regno, unsigned char *buf)
+sim_store_register (SIM_DESC sd, int regno, unsigned char *buf)
{
if (simulator == NULL)
return;
void
-sim_info (int verbose)
+sim_info (SIM_DESC sd, int verbose)
{
TRACE(trace_gdb, ("sim_info(verbose=%d) called\n", verbose));
psim_print_info (simulator, verbose);
}
-void
-sim_create_inferior (SIM_ADDR start_address, char **argv, char **envp)
+SIM_RC
+sim_create_inferior (SIM_DESC sd, char **argv, char **envp)
{
- unsigned_word entry_point = start_address;
-
TRACE(trace_gdb, ("sim_create_inferior(start_address=0x%x, ...)\n",
- start_address));
+ entry_point));
psim_init(simulator);
psim_stack(simulator, argv, envp);
psim_write_register(simulator, -1 /* all start at same PC */,
&entry_point, "pc", cooked_transfer);
+ return SIM_RC_OK;
}
static volatile int sim_should_run;
void
-sim_stop_reason (enum sim_stop *reason, int *sigrc)
+sim_stop_reason (SIM_DESC sd, enum sim_stop *reason, int *sigrc)
{
psim_status status = psim_get_status(simulator);
/* Run (or resume) the program. */
-static void
-sim_ctrl_c()
+static RETSIGTYPE
+sim_ctrl_c(int sig)
{
sim_should_run = 0;
}
void
-sim_resume (int step, int siggnal)
+sim_resume (SIM_DESC sd, int step, int siggnal)
{
TRACE(trace_gdb, ("sim_resume(step=%d, siggnal=%d)\n",
step, siggnal));
}
else
{
- void (*prev) ();
+ RETSIGTYPE (*prev) ();
prev = signal(SIGINT, sim_ctrl_c);
sim_should_run = 1;
}
void
-sim_do_command (char *cmd)
+sim_do_command (SIM_DESC sd, char *cmd)
{
TRACE(trace_gdb, ("sim_do_commands(cmd=%s) called\n",
cmd ? cmd : "(null)"));
}
void
-sim_set_callbacks (host_callback *callback)
+sim_set_callbacks (SIM_DESC sd, host_callback *callback)
{
callbacks = callback;
TRACE(trace_gdb, ("sim_set_callbacks called\n"));