#ifndef _PSIM_C_
#define _PSIM_C_
#include "cpu.h"
#include "idecode.h"
#include "options.h"
#include "tree.h"
#include <signal.h>
#include <stdio.h>
#include <ctype.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include <setjmp.h>
#ifdef HAVE_STRING_H
#include <string.h>
#else
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#endif
#include "bfd.h"
struct _psim {
event_queue *events;
device *devices;
mon *monitor;
os_emul *os_emulation;
core *memory;
void *path_to_halt;
void *path_to_restart;
psim_status halt_status;
int nr_cpus;
int last_cpu;
cpu *processors[MAX_NR_PROCESSORS];
};
int current_target_byte_order;
int current_host_byte_order;
int current_environment;
int current_alignment;
int current_floating_point;
int current_model_issue = MODEL_ISSUE_IGNORE;
int current_stdio = DO_USE_STDIO;
model_enum current_model = WITH_DEFAULT_MODEL;
INLINE_PSIM\
(device *)
psim_tree(void)
{
device *root = tree_parse(NULL, "core");
tree_parse(root, "/aliases");
tree_parse(root, "/options");
tree_parse(root, "/chosen");
tree_parse(root, "/packages");
tree_parse(root, "/cpus");
tree_parse(root, "/openprom");
tree_parse(root, "/openprom/init");
tree_parse(root, "/openprom/trace");
tree_parse(root, "/openprom/options");
return root;
}
STATIC_INLINE_PSIM\
(char *)
find_arg(char *err_msg,
int *ptr_to_argp,
char **argv)
{
*ptr_to_argp += 1;
if (argv[*ptr_to_argp] == NULL)
error(err_msg);
return argv[*ptr_to_argp];
}
INLINE_PSIM\
(void)
psim_usage(int verbose)
{
printf_filtered("Usage:\n");
printf_filtered("\n");
printf_filtered("\tpsim [ <psim-option> ... ] <image> [ <image-arg> ... ]\n");
printf_filtered("\n");
printf_filtered("Where\n");
printf_filtered("\n");
printf_filtered("\t<image> Name of the PowerPC program to run.\n");
if (verbose) {
printf_filtered("\t This can either be a PowerPC binary or\n");
printf_filtered("\t a text file containing a device tree\n");
printf_filtered("\t specification.\n");
printf_filtered("\t PSIM will attempt to determine from the\n");
printf_filtered("\t specified <image> the intended emulation\n");
printf_filtered("\t environment.\n");
printf_filtered("\t If PSIM gets it wrong, the emulation\n");
printf_filtered("\t environment can be specified using the\n");
printf_filtered("\t `-e' option (described below).\n");
printf_filtered("\n"); }
printf_filtered("\t<image-arg> Argument to be passed to <image>\n");
if (verbose) {
printf_filtered("\t These arguments will be passed to\n");
printf_filtered("\t <image> (as standard C argv, argc)\n");
printf_filtered("\t when <image> is started.\n");
printf_filtered("\n"); }
printf_filtered("\t<psim-option> See below\n");
printf_filtered("\n");
printf_filtered("The following are valid <psim-option>s:\n");
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"); }
printf_filtered("\t-e <os-emul> specify an OS or platform to model\n");
if (verbose) {
printf_filtered("\t Can be any of the following:\n");
printf_filtered("\t bug - OEA + MOTO BUG ROM calls\n");
printf_filtered("\t netbsd - UEA + NetBSD system calls\n");
printf_filtered("\t solaris - UEA + Solaris system calls\n");
printf_filtered("\t linux - UEA + Linux system calls\n");
printf_filtered("\t chirp - OEA + a few OpenBoot calls\n");
printf_filtered("\n"); }
printf_filtered("\t-E <endian> Specify the endianness of the target\n");
if (verbose) {
printf_filtered("\t Can be any of the following:\n");
printf_filtered("\t big - big endian target\n");
printf_filtered("\t little - little endian target\n");
printf_filtered("\n"); }
printf_filtered("\t-f <file> Merge <file> into the device tree\n");
if (verbose) { printf_filtered("\n"); }
printf_filtered("\t-h -? -H give more detailed usage\n");
if (verbose) { printf_filtered("\n"); }
printf_filtered("\t-m <model> Specify the processor to model (604)\n");
if (verbose) {
printf_filtered("\t Selects the processor to use when\n");
printf_filtered("\t modeling execution units. Includes:\n");
printf_filtered("\t 604, 603 and 603e\n");
printf_filtered("\n"); }
printf_filtered("\t-n <nr-smp> Specify the number of processors in SMP simulations\n");
if (verbose) {
printf_filtered("\t Specifies the number of processors that are\n");
printf_filtered("\t to be modeled in a symetric multi-processor (SMP)\n");
printf_filtered("\t simulation\n");
printf_filtered("\n"); }
printf_filtered("\t-o <dev-spec> Add device <dev-spec> to the device tree\n");
if (verbose) { printf_filtered("\n"); }
printf_filtered("\t-r <ram-size> Set RAM size in bytes (OEA environments)\n");
if (verbose) { printf_filtered("\n"); }
printf_filtered("\t-t [!]<trace> Enable (disable) <trace> option\n");
if (verbose) { printf_filtered("\n"); }
printf_filtered("\n");
trace_usage(verbose);
device_usage(verbose);
if (verbose > 1) {
printf_filtered("\n");
print_options();
}
error("");
}
static
int is_num( char *string, int min, int max, int err)
{
int result = 0;
for ( ; *string; ++string)
{
if (!isdigit(*string))
{
result = err;
break;
}
result = result * 10 + (*string - '0');
}
if (result < min || result > max)
result = err;
return result;
}
INLINE_PSIM\
(char **)
psim_options(device *root,
char **argv)
{
device *current = root;
int argp;
if (argv == NULL)
return NULL;
argp = 0;
while (argv[argp] != NULL && argv[argp][0] == '-') {
char *p = argv[argp] + 1;
char *param;
while (*p != '\0') {
switch (*p) {
default:
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 (os-emul)\n", &argp, argv);
tree_parse(root, "/openprom/options/os-emul %s", param);
break;
case 'E':
param = find_arg("Missing <endian> option for -E (target-endian)\n", &argp, argv);
if (strcmp (param, "big") == 0)
tree_parse (root, "/options/little-endian? false");
else if (strcmp (param, "little") == 0)
tree_parse (root, "/options/little-endian? true");
else
{
printf_filtered ("Invalid <endian> option for -E (target-endian)\n");
psim_usage (0);
}
break;
case 'f':
param = find_arg("Missing <file> option for -f\n", &argp, argv);
psim_merge_device_file(root, param);
break;
case 'h':
case '?':
psim_usage(1);
break;
case 'H':
psim_usage(2);
break;
case 'i':
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");
tree_parse(root, "/openprom/options/model-issue %d",
MODEL_ISSUE_PROCESS);
break;
case 'm':
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 (smp)\n", &argp, argv);
tree_parse(root, "/openprom/options/smp %s", param);
break;
case 'o':
param = find_arg("Missing <dev-spec> option for -o\n", &argp, argv);
if (memcmp(param, "mpc860c0", 8) == 0)
{
if (param[8] == '\0')
tree_parse(root, "/options/mpc860c0 5");
else if (param[8] == '=' && is_num(param+9, 1, 10, 0))
{
tree_parse(root, "/options/mpc860c0 %s", param+9);
}
else error("Invalid mpc860c0 option for -o\n");
}
else
current = tree_parse(current, "%s", param);
break;
case 'r':
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 (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 '-':
if (strstr(argv[argp], "architecture") != NULL) {
p = argv[argp] + strlen(argv[argp]) - 1;
printf_filtered("Warning - architecture parameter ignored\n");
}
else
error("Unrecognized option");
break;
}
p += 1;
}
argp += 1;
}
device_ioctl(tree_find_device(root, "/openprom/trace"),
NULL, 0,
device_ioctl_set_trace);
{
void semantic_init(device* root);
semantic_init(root);
}
return argv + argp;
}
INLINE_PSIM\
(void)
psim_command(device *root,
char **argv)
{
int argp = 0;
if (argv[argp] == NULL) {
return;
}
else if (strcmp(argv[argp], "trace") == 0) {
const char *opt = find_arg("Missing <trace> option", &argp, argv);
if (opt[0] == '!')
trace_option(opt + 1, 0);
else
trace_option(opt, 1);
}
else if (strcmp(*argv, "change-media") == 0) {
char *device = find_arg("Missing device name", &argp, argv);
char *media = argv[++argp];
device_ioctl(tree_find_device(root, device), NULL, 0,
device_ioctl_change_media, media);
}
else {
printf_filtered("Unknown PSIM command %s, try\n", argv[argp]);
printf_filtered(" trace <trace-option>\n");
printf_filtered(" change-media <device> [ <new-image> ]\n");
}
}
INLINE_PSIM\
(psim *)
psim_create(const char *file_name,
device *root)
{
int cpu_nr;
const char *env;
psim *system;
os_emul *os_emulation;
int nr_cpus;
os_emulation = os_emul_create(file_name, root);
if (os_emulation == NULL)
error("psim: either file %s was not reconized or unreconized or unknown os-emulation type\n", file_name);
nr_cpus = tree_find_integer_property(root, "/openprom/options/smp");
if (MAX_NR_PROCESSORS < nr_cpus)
error("target and configured number of cpus conflict\n");
current_target_byte_order
= (tree_find_boolean_property(root, "/options/little-endian?")
? LITTLE_ENDIAN
: BIG_ENDIAN);
if (CURRENT_TARGET_BYTE_ORDER != current_target_byte_order)
error("target and configured byte order conflict\n");
current_host_byte_order = (current_host_byte_order = 1,
(*(char*)(¤t_host_byte_order)
? LITTLE_ENDIAN
: BIG_ENDIAN));
if (CURRENT_HOST_BYTE_ORDER != current_host_byte_order)
error("host and configured byte order conflict\n");
env = tree_find_string_property(root, "/openprom/options/env");
current_environment = ((strcmp(env, "user") == 0
|| strcmp(env, "uea") == 0)
? USER_ENVIRONMENT
: (strcmp(env, "virtual") == 0
|| strcmp(env, "vea") == 0)
? VIRTUAL_ENVIRONMENT
: (strcmp(env, "operating") == 0
|| strcmp(env, "oea") == 0)
? OPERATING_ENVIRONMENT
: 0);
if (current_environment == 0)
error("unreconized /options env property\n");
if (CURRENT_ENVIRONMENT != current_environment)
error("target and configured environment conflict\n");
current_alignment
= (tree_find_boolean_property(root, "/openprom/options/strict-alignment?")
? STRICT_ALIGNMENT
: NONSTRICT_ALIGNMENT);
if (CURRENT_ALIGNMENT != current_alignment)
error("target and configured alignment conflict\n");
current_floating_point
= (tree_find_boolean_property(root, "/openprom/options/floating-point?")
? HARD_FLOATING_POINT
: SOFT_FLOATING_POINT);
if (CURRENT_FLOATING_POINT != current_floating_point)
error("target and configured floating-point conflict\n");
current_stdio
= (tree_find_boolean_property(root, "/openprom/options/use-stdio?")
? DO_USE_STDIO
: DONT_USE_STDIO);
if (CURRENT_STDIO != current_stdio)
error("target and configured stdio interface conflict\n");
current_model_issue
= tree_find_integer_property(root, "/openprom/options/model-issue");
if (CURRENT_MODEL_ISSUE != current_model_issue)
error("target and configured model-issue conflict\n");
model_set(tree_find_string_property(root, "/openprom/options/model"));
system = ZALLOC(psim);
system->events = event_queue_create();
system->memory = core_from_device(root);
system->monitor = mon_create();
system->nr_cpus = nr_cpus;
system->os_emulation = os_emulation;
system->devices = root;
for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) {
system->processors[cpu_nr] = cpu_create(system,
system->memory,
mon_cpu(system->monitor,
cpu_nr),
system->os_emulation,
cpu_nr);
}
if (ppc_trace[trace_print_device_tree] || ppc_trace[trace_dump_device_tree])
tree_print(root);
if (ppc_trace[trace_dump_device_tree])
error("");
return system;
}
INLINE_PSIM\
(void)
psim_set_halt_and_restart(psim *system,
void *halt_jmp_buf,
void *restart_jmp_buf)
{
system->path_to_halt = halt_jmp_buf;
system->path_to_restart = restart_jmp_buf;
}
INLINE_PSIM\
(void)
psim_clear_halt_and_restart(psim *system)
{
system->path_to_halt = NULL;
system->path_to_restart = NULL;
}
INLINE_PSIM\
(void)
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);
}
static void
cntrl_c_simulation(void *data)
{
psim *system = data;
psim_halt(system,
psim_nr_cpus(system),
was_continuing,
SIGINT);
}
INLINE_PSIM\
(void)
psim_stop(psim *system)
{
event_queue_schedule_after_signal(psim_event_queue(system),
0 ,
cntrl_c_simulation,
system);
}
INLINE_PSIM\
(void)
psim_halt(psim *system,
int current_cpu,
stop_reason reason,
int signal)
{
ASSERT(current_cpu >= 0 && current_cpu <= system->nr_cpus);
ASSERT(system->path_to_halt != NULL);
system->last_cpu = current_cpu;
system->halt_status.reason = reason;
system->halt_status.signal = signal;
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);
}
INLINE_PSIM\
(int)
psim_last_cpu(psim *system)
{
return system->last_cpu;
}
INLINE_PSIM\
(int)
psim_nr_cpus(psim *system)
{
return system->nr_cpus;
}
INLINE_PSIM\
(psim_status)
psim_get_status(psim *system)
{
return system->halt_status;
}
INLINE_PSIM\
(cpu *)
psim_cpu(psim *system,
int cpu_nr)
{
if (cpu_nr < 0 || cpu_nr >= system->nr_cpus)
return NULL;
else
return system->processors[cpu_nr];
}
INLINE_PSIM\
(device *)
psim_device(psim *system,
const char *path)
{
return tree_find_device(system->devices, path);
}
INLINE_PSIM\
(event_queue *)
psim_event_queue(psim *system)
{
return system->events;
}
STATIC_INLINE_PSIM\
(void)
psim_max_iterations_exceeded(void *data)
{
psim *system = data;
psim_halt(system,
system->nr_cpus,
was_signalled,
-1);
}
INLINE_PSIM\
(void)
psim_init(psim *system)
{
int cpu_nr;
mon_init(system->monitor, system->nr_cpus);
event_queue_init(system->events);
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);
}
for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
cpu_init(system->processors[cpu_nr]);
tree_init(system->devices, system);
os_emul_init(system->os_emulation, system->nr_cpus);
for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++) {
cpu *processor = system->processors[cpu_nr];
cpu_synchronize_context(processor, cpu_get_program_counter(processor));
cpu_page_tlb_invalidate_all(processor);
}
system->last_cpu = -1;
}
INLINE_PSIM\
(void)
psim_stack(psim *system,
char **argv,
char **envp)
{
device *stack_device = tree_find_device(system->devices,
"/openprom/init/stack");
if (stack_device != (device*)0) {
unsigned_word stack_pointer;
psim_read_register(system, 0, &stack_pointer, "sp", cooked_transfer);
device_ioctl(stack_device,
NULL,
0,
device_ioctl_create_stack,
stack_pointer,
argv,
envp);
}
}
INLINE_PSIM\
(void)
psim_step(psim *system)
{
volatile int keep_running = 0;
idecode_run_until_stop(system, &keep_running,
system->events, system->processors, system->nr_cpus);
}
INLINE_PSIM\
(void)
psim_run(psim *system)
{
idecode_run(system,
system->events, system->processors, system->nr_cpus);
}
INLINE_PSIM\
(void)
psim_read_register(psim *system,
int which_cpu,
void *buf,
const char reg[],
transfer_mode mode)
{
register_descriptions description;
char cooked_buf[sizeof(unsigned_8)];
cpu *processor;
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];
description = register_description(reg);
if (description.type == reg_invalid)
error("psim_read_register() invalid register name `%s'\n", reg);
switch (description.type) {
case reg_gpr:
*(gpreg*)cooked_buf = cpu_registers(processor)->gpr[description.index];
break;
case reg_spr:
*(spreg*)cooked_buf = cpu_registers(processor)->spr[description.index];
break;
case reg_sr:
*(sreg*)cooked_buf = cpu_registers(processor)->sr[description.index];
break;
case reg_fpr:
*(fpreg*)cooked_buf = cpu_registers(processor)->fpr[description.index];
break;
case reg_pc:
*(unsigned_word*)cooked_buf = cpu_get_program_counter(processor);
break;
case reg_cr:
*(creg*)cooked_buf = cpu_registers(processor)->cr;
break;
case reg_msr:
*(msreg*)cooked_buf = cpu_registers(processor)->msr;
break;
case reg_fpscr:
*(fpscreg*)cooked_buf = cpu_registers(processor)->fpscr;
break;
case reg_insns:
*(unsigned_word*)cooked_buf = mon_get_number_of_insns(system->monitor,
which_cpu);
break;
case reg_stalls:
if (cpu_model(processor) == NULL)
error("$stalls only valid if processor unit model enabled (-I)\n");
*(unsigned_word*)cooked_buf = model_get_number_of_stalls(cpu_model(processor));
break;
case reg_cycles:
if (cpu_model(processor) == NULL)
error("$cycles only valid if processor unit model enabled (-I)\n");
*(unsigned_word*)cooked_buf = model_get_number_of_cycles(cpu_model(processor));
break;
default:
printf_filtered("psim_read_register(processor=0x%lx,buf=0x%lx,reg=%s) %s\n",
(unsigned long)processor, (unsigned long)buf, reg,
"read of this register unimplemented");
break;
}
if (mode == raw_transfer) {
switch (description.size) {
case 1:
*(unsigned_1*)buf = H2T_1(*(unsigned_1*)cooked_buf);
break;
case 2:
*(unsigned_2*)buf = H2T_2(*(unsigned_2*)cooked_buf);
break;
case 4:
*(unsigned_4*)buf = H2T_4(*(unsigned_4*)cooked_buf);
break;
case 8:
*(unsigned_8*)buf = H2T_8(*(unsigned_8*)cooked_buf);
break;
}
}
else {
memcpy(buf, cooked_buf, description.size);
}
}
INLINE_PSIM\
(void)
psim_write_register(psim *system,
int which_cpu,
const void *buf,
const char reg[],
transfer_mode mode)
{
cpu *processor;
register_descriptions description;
char cooked_buf[sizeof(unsigned_8)];
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;
}
ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
processor = system->processors[which_cpu];
description = register_description(reg);
if (description.type == reg_invalid)
error("psim_write_register() invalid register name %s\n", reg);
if (mode == raw_transfer) {
switch (description.size) {
case 1:
*(unsigned_1*)cooked_buf = T2H_1(*(unsigned_1*)buf);
break;
case 2:
*(unsigned_2*)cooked_buf = T2H_2(*(unsigned_2*)buf);
break;
case 4:
*(unsigned_4*)cooked_buf = T2H_4(*(unsigned_4*)buf);
break;
case 8:
*(unsigned_8*)cooked_buf = T2H_8(*(unsigned_8*)buf);
break;
}
}
else {
memcpy(cooked_buf, buf, description.size);
}
switch (description.type) {
case reg_gpr:
cpu_registers(processor)->gpr[description.index] = *(gpreg*)cooked_buf;
break;
case reg_fpr:
cpu_registers(processor)->fpr[description.index] = *(fpreg*)cooked_buf;
break;
case reg_pc:
cpu_set_program_counter(processor, *(unsigned_word*)cooked_buf);
break;
case reg_spr:
cpu_registers(processor)->spr[description.index] = *(spreg*)cooked_buf;
break;
case reg_sr:
cpu_registers(processor)->sr[description.index] = *(sreg*)cooked_buf;
break;
case reg_cr:
cpu_registers(processor)->cr = *(creg*)cooked_buf;
break;
case reg_msr:
cpu_registers(processor)->msr = *(msreg*)cooked_buf;
break;
case reg_fpscr:
cpu_registers(processor)->fpscr = *(fpscreg*)cooked_buf;
break;
default:
printf_filtered("psim_write_register(processor=0x%lx,cooked_buf=0x%lx,reg=%s) %s\n",
(unsigned long)processor, (unsigned long)cooked_buf, reg,
"read of this register unimplemented");
break;
}
}
INLINE_PSIM\
(unsigned)
psim_read_memory(psim *system,
int which_cpu,
void *buffer,
unsigned_word vaddr,
unsigned nr_bytes)
{
cpu *processor;
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,
NULL, -1);
}
INLINE_PSIM\
(unsigned)
psim_write_memory(psim *system,
int which_cpu,
const void *buffer,
unsigned_word vaddr,
unsigned nr_bytes,
int violate_read_only_section)
{
cpu *processor;
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,
NULL, -1);
}
INLINE_PSIM\
(void)
psim_print_info(psim *system,
int verbose)
{
mon_print_info(system, system->monitor, verbose);
}
INLINE_PSIM\
(void)
psim_merge_device_file(device *root,
const char *file_name)
{
FILE *description;
int line_nr;
char device_path[1000];
device *current;
description = fopen(file_name, "r");
if (description == NULL) {
perror(file_name);
error("Invalid file %s specified", file_name);
}
line_nr = 0;
current = root;
while (fgets(device_path, sizeof(device_path), description)) {
char *device;
if (strchr(device_path, '\n') == NULL) {
fclose(description);
error("%s:%d: line to long - %s",
file_name, line_nr, device_path);
}
else
*strchr(device_path, '\n') = '\0';
line_nr++;
for (device = device_path;
*device != '\0' && isspace(*device);
device++);
if (device[0] == '#'
|| device[0] == ';'
|| device[0] == '\0')
continue;
while (device_path[strlen(device_path) - 1] == '\\') {
int curlen = strlen(device_path) - 1;
device_path[curlen] = '\0';
if (!fgets(device_path + curlen, sizeof(device_path) - curlen, description)) {
fclose(description);
error("%s:%s: unexpected eof in line continuation - %s",
file_name, line_nr, device_path);
}
if (strchr(device_path, '\n') == NULL) {
fclose(description);
error("%s:%d: line to long - %s",
file_name, line_nr, device_path);
}
else
*strchr(device_path, '\n') = '\0';
line_nr++;
}
current = tree_parse(current, "%s", device);
}
fclose(description);
}
#endif