aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sim/ppc/ChangeLog46
-rw-r--r--sim/ppc/config.in5
-rw-r--r--sim/ppc/cpu.c106
-rw-r--r--sim/ppc/emul_bugapi.c204
-rw-r--r--sim/ppc/emul_generic.c80
-rw-r--r--sim/ppc/emul_netbsd.c19
-rw-r--r--sim/ppc/psim.c676
7 files changed, 643 insertions, 493 deletions
diff --git a/sim/ppc/ChangeLog b/sim/ppc/ChangeLog
index b9976a1..613eea1 100644
--- a/sim/ppc/ChangeLog
+++ b/sim/ppc/ChangeLog
@@ -1,3 +1,49 @@
+Wed Feb 21 10:39:35 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * emul_bugapi.c (emul_bugapi_create): Make formats type
+ compatible.
+
+Mon Feb 19 22:54:40 1996 Andrew Cagney <cagney@highland.com.au>
+
+ * ppc-instructions (TLB Invalidate Entry, TLB Invalidate ALL):
+ Implement by passing on request to all processors.
+ * ppc-instructions (TLB Synchronize): Implement as empty, processor
+ tlb's are always in sync.
+
+ * cpu.c (cpu_page_tlb_invalidate_all): New function. Pass on TLB
+ invalidate request to processors VM sub-system.
+ * cpu.c (cpu_page_tlb_invalidate_entry): Ditto.
+
+ * vm.c (vm_page_tlb_invalidate_all): New function. Mark all page
+ TLB entries as invalid.
+ * vm.c (vm_page_tlb_invalidate_entry): New function. Ditt but only
+ invalidate one TLB entry.
+
+ * psim.c (psim_init): Invalidate TLB's before (re)starting.
+
+Mon Feb 19 21:25:56 1996 Andrew Cagney <cagney@highland.com.au>
+
+ * emul_generic.c (emul_add_tree_options): Add argument
+ oea_interrupt_prefix (0 or 1) that specifies the prefix MSR[IP]
+ and hence the location of the interrupt vectors. Add this to the
+ device tree.
+
+ * emul_chirp.c (emul_chirp_create): Allow configuration of
+ floating-point and interrupt prefix (default 0) using the above.
+
+ * emul_netbsd.c (emul_netbsd_create): Pass dummy arg for
+ interrupt-prefix.
+
+ * emul_bugapi.c (emul_bugapi_create): Allow configuration of
+ interrupt prefix (default 1) and configure interrupt table traps
+ accordingly.
+
+ * emul_generic.c (emul_add_tree_hardware): Include a small eeprom
+ in the list of devices.
+
+ * device_table.c: For moment fake eeprom device by a memory
+ device. In future will need a proper eeprom device.
+
Tue Feb 20 17:01:26 1996 J.T. Conklin <jtc@rtl.cygnus.com>
* config.in: Regenerated.
diff --git a/sim/ppc/config.in b/sim/ppc/config.in
index 7434926..e081c74 100644
--- a/sim/ppc/config.in
+++ b/sim/ppc/config.in
@@ -1,5 +1,8 @@
/* config.in. Generated automatically from configure.in by autoheader. */
+#ifndef CONFIG_H
+#define CONFIG_H
+
/* Define if your processor stores words with the most significant
byte first (like Motorola and SPARC, unlike Intel and VAX). */
#undef WORDS_BIGENDIAN
@@ -45,3 +48,5 @@
/* Define if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
+
+#endif
diff --git a/sim/ppc/cpu.c b/sim/ppc/cpu.c
index ef8cfeb..9e9e7e7 100644
--- a/sim/ppc/cpu.c
+++ b/sim/ppc/cpu.c
@@ -22,10 +22,6 @@
#ifndef _CPU_C_
#define _CPU_C_
-#ifndef STATIC_INLINE_CPU
-#define STATIC_INLINE_CPU STATIC_INLINE
-#endif
-
#include <setjmp.h>
#include "cpu.h"
@@ -58,6 +54,7 @@ struct _cpu {
/* the system this processor is contained within */
cpu_mon *monitor;
+ os_emul *os_emulation;
psim *system;
event_queue *events;
int cpu_nr;
@@ -81,12 +78,13 @@ struct _cpu {
};
-
-INLINE_CPU cpu *
+INLINE_CPU\
+(cpu *)
cpu_create(psim *system,
core *memory,
event_queue *events,
cpu_mon *monitor,
+ os_emul *os_emulation,
int cpu_nr)
{
cpu *processor = ZALLOC(cpu);
@@ -105,17 +103,19 @@ cpu_create(psim *system,
processor->events = events;
processor->cpu_nr = cpu_nr;
processor->monitor = monitor;
+ processor->os_emulation = os_emulation;
return processor;
}
-INLINE_CPU void
+INLINE_CPU\
+(void)
cpu_init(cpu *processor)
{
memset(&processor->regs, 0, sizeof(processor->regs));
- /* FIXME - should any of VM be inited also ? */
-
+ /* vm init is delayed until after the device tree has been init as
+ the devices may further init the cpu */
if (CURRENT_MODEL_ISSUE > 0)
model_init (processor->model_ptr);
}
@@ -123,31 +123,43 @@ cpu_init(cpu *processor)
/* find ones way home */
-INLINE_CPU psim *
+INLINE_CPU\
+(psim *)
cpu_system(cpu *processor)
{
return processor->system;
}
-INLINE_CPU int
+INLINE_CPU\
+(int)
cpu_nr(cpu *processor)
{
return processor->cpu_nr;
}
-INLINE_CPU event_queue *
+INLINE_CPU\
+(event_queue *)
cpu_event_queue(cpu *processor)
{
return processor->events;
}
-INLINE_CPU cpu_mon *
+INLINE_CPU\
+(cpu_mon *)
cpu_monitor(cpu *processor)
{
return processor->monitor;
}
-INLINE_CPU model_data *
+INLINE_CPU\
+(os_emul *)
+cpu_os_emulation(cpu *processor)
+{
+ return processor->os_emulation;
+}
+
+INLINE_CPU\
+(model_data *)
cpu_model(cpu *processor)
{
return processor->model_ptr;
@@ -155,14 +167,16 @@ cpu_model(cpu *processor)
/* The processors local concept of time */
-INLINE_CPU signed64
+INLINE_CPU\
+(signed64)
cpu_get_time_base(cpu *processor)
{
return (event_queue_time(processor->events)
- processor->time_base_local_time);
}
-INLINE_CPU void
+INLINE_CPU\
+(void)
cpu_set_time_base(cpu *processor,
signed64 time_base)
{
@@ -170,14 +184,16 @@ cpu_set_time_base(cpu *processor,
- time_base);
}
-INLINE_CPU signed32
+INLINE_CPU\
+(signed32)
cpu_get_decrementer(cpu *processor)
{
return (processor->decrementer_local_time
- event_queue_time(processor->events));
}
-STATIC_INLINE_CPU void
+STATIC_INLINE_CPU\
+(void)
cpu_decrement_event(event_queue *queue,
void *data)
{
@@ -190,7 +206,8 @@ cpu_decrement_event(event_queue *queue,
}
}
-INLINE_CPU void
+INLINE_CPU\
+(void)
cpu_set_decrementer(cpu *processor,
signed32 decrementer)
{
@@ -216,20 +233,23 @@ cpu_set_decrementer(cpu *processor,
/* program counter manipulation */
-INLINE_CPU void
+INLINE_CPU\
+(void)
cpu_set_program_counter(cpu *processor,
unsigned_word new_program_counter)
{
processor->program_counter = new_program_counter;
}
-INLINE_CPU unsigned_word
+INLINE_CPU\
+(unsigned_word)
cpu_get_program_counter(cpu *processor)
{
return processor->program_counter;
}
-INLINE_CPU void
+INLINE_CPU\
+(void)
cpu_restart(cpu *processor,
unsigned_word nia)
{
@@ -237,7 +257,8 @@ cpu_restart(cpu *processor,
psim_restart(processor->system, processor->cpu_nr);
}
-INLINE_CPU void
+INLINE_CPU\
+(void)
cpu_halt(cpu *processor,
unsigned_word cia,
stop_reason reason,
@@ -261,7 +282,8 @@ cpu_halt(cpu *processor,
#if WITH_IDECODE_CACHE_SIZE
/* allow access to the cpu's instruction cache */
-INLINE_CPU idecode_cache *
+INLINE_CPU\
+(idecode_cache *)
cpu_icache_entry(cpu *processor,
unsigned_word cia)
{
@@ -269,7 +291,8 @@ cpu_icache_entry(cpu *processor,
}
-INLINE_CPU void
+INLINE_CPU\
+(void)
cpu_flush_icache(cpu *processor)
{
int i;
@@ -282,22 +305,40 @@ cpu_flush_icache(cpu *processor)
/* address map revelation */
-INLINE_CPU vm_instruction_map *
+INLINE_CPU\
+(vm_instruction_map *)
cpu_instruction_map(cpu *processor)
{
return processor->instruction_map;
}
-INLINE_CPU vm_data_map *
+INLINE_CPU\
+(vm_data_map *)
cpu_data_map(cpu *processor)
{
return processor->data_map;
}
+INLINE_CPU\
+(void)
+cpu_page_tlb_invalidate_entry(cpu *processor,
+ unsigned_word ea)
+{
+ vm_page_tlb_invalidate_entry(processor->virtual, ea);
+}
+
+INLINE_CPU\
+(void)
+cpu_page_tlb_invalidate_all(cpu *processor)
+{
+ vm_page_tlb_invalidate_all(processor->virtual);
+}
+
/* reservation access */
-INLINE_CPU memory_reservation *
+INLINE_CPU\
+(memory_reservation *)
cpu_reservation(cpu *processor)
{
return &processor->reservation;
@@ -306,13 +347,15 @@ cpu_reservation(cpu *processor)
/* register access */
-INLINE_CPU registers *
+INLINE_CPU\
+(registers *)
cpu_registers(cpu *processor)
{
return &processor->regs;
}
-INLINE_CPU void
+INLINE_CPU\
+(void)
cpu_synchronize_context(cpu *processor)
{
#if (WITH_IDECODE_CACHE)
@@ -330,7 +373,8 @@ cpu_synchronize_context(cpu *processor)
/* might again be useful one day */
-INLINE_CPU void
+INLINE_CPU\
+(void)
cpu_print_info(cpu *processor, int verbose)
{
}
diff --git a/sim/ppc/emul_bugapi.c b/sim/ppc/emul_bugapi.c
index f325901..a202541 100644
--- a/sim/ppc/emul_bugapi.c
+++ b/sim/ppc/emul_bugapi.c
@@ -1,6 +1,6 @@
/* This file is part of the program psim.
- Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+ Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -50,28 +50,23 @@
#include "emul_generic.h"
#include "emul_bugapi.h"
-/* Any starting address less than this is assumed to be an OEA program
- rather than VEA. */
-#ifndef OEA_START_ADDRESS
-#define OEA_START_ADDRESS 0x4000
-#endif
-#ifndef OEA_MEMORY_SIZE
-#define OEA_MEMORY_SIZE 0x100000
+#ifndef OEA_START_ADDRESS
+#define OEA_START_ADDRESS 0x100000
#endif
-/* All but CPU 0 are put into an infinate loop, this loop instruction
- is stored at the address below */
-#ifndef OEA_STALL_CPU_LOOP_ADDRESS
-#define OEA_STALL_CPU_LOOP_ADDRESS 0x00c10
-#endif
-/* At initiallization, the system call exception branches to the BUG
- emulation code */
-#ifndef OEA_SYSTEM_CALL_ADDRESS
-#define OEA_SYSTEM_CALL_ADDRESS 0x00c00
-#endif
+struct _os_emul_data {
+ unsigned_word memory_size;
+ unsigned_word top_of_stack;
+ int interrupt_prefix;
+ unsigned_word interrupt_vector_address;
+ unsigned_word system_call_address;
+ unsigned_word stall_cpu_loop_address;
+ int little_endian;
+ int floating_point_available;
+};
static os_emul_data *
@@ -79,6 +74,9 @@ emul_bugapi_create(device *root,
bfd *image,
const char *name)
{
+ int elf_binary;
+ device *node;
+ os_emul_data *bugapi;
/* check it really is for us */
if (name != NULL
@@ -90,99 +88,85 @@ emul_bugapi_create(device *root,
&& bfd_get_start_address(image) > OEA_START_ADDRESS)
return NULL;
- {
-
- const memory_size = OEA_MEMORY_SIZE;
- const elf_binary = (image != NULL
- && image->xvec->flavour == bfd_target_elf_flavour);
-#ifdef bfd_little_endian /* new bfd */
- const little_endian = (image != NULL && bfd_little_endian(image));
-#else
- const little_endian = (image != NULL &&
- !image->xvec->byteorder_big_p);
-#endif
-
- { /* options */
- device *options = device_tree_add_found(root, "/", "options");
- device_add_integer_property(options,
- "smp",
- MAX_NR_PROCESSORS);
- device_add_boolean_property(options,
- "little-endian?",
- little_endian);
- device_add_string_property(options,
- "env",
- "operating");
- device_add_boolean_property(options,
- "strict-alignment?",
- (WITH_ALIGNMENT == STRICT_ALIGNMENT
- || little_endian));
- device_add_boolean_property(options,
- "floating-point?",
- WITH_FLOATING_POINT);
- device_add_string_property(options,
- "os-emul",
- "bugapi");
- }
+ bugapi = ZALLOC(os_emul_data);
+
+ /* some defaults */
+ elf_binary = image->xvec->flavour == bfd_target_elf_flavour;
+
+ /* options */
+ emul_add_tree_options(root, image, "bug", "oea",
+ 1 /*oea-interrupt-prefix*/);
+
+ /* add some real hardware */
+ emul_add_tree_hardware(root);
+
+ bugapi->memory_size
+ = device_find_integer_property(root, "/openprom/options/oea-memory-size");
+ bugapi->interrupt_prefix =
+ device_find_integer_property(root, "/openprom/options/oea-interrupt-prefix");
+ bugapi->interrupt_vector_address = (bugapi->interrupt_prefix
+ ? MASK(0, 43)
+ : 0);
+ bugapi->system_call_address = (bugapi->interrupt_vector_address + 0x00c00);
+ bugapi->stall_cpu_loop_address = (bugapi->system_call_address + 0x000f0);
+ bugapi->top_of_stack = bugapi->memory_size - 0x1000;
+ bugapi->little_endian
+ = device_find_boolean_property(root, "/options/little-endian?");
+ bugapi->floating_point_available
+ = device_find_boolean_property(root, "/openprom/options/floating-point?");
+
+ /* initialization */
+ device_tree_add_parsed(root, "/openprom/init/register/0.pc 0x%lx",
+ (unsigned long)bfd_get_start_address(image));
+ device_tree_add_parsed(root, "/openprom/init/register/pc 0x%lx",
+ (unsigned long)bugapi->stall_cpu_loop_address);
+ device_tree_add_parsed(root, "/openprom/init/register/sp 0x%lx",
+ (unsigned long)(bugapi->top_of_stack - 16));
+ device_tree_add_parsed(root, "/openprom/init/register/msr 0x%x",
+ (msr_recoverable_interrupt
+ | (bugapi->little_endian
+ ? (msr_little_endian_mode
+ | msr_interrupt_little_endian_mode)
+ : 0)
+ | (bugapi->floating_point_available
+ ? msr_floating_point_available
+ : 0)
+ | (bugapi->interrupt_prefix
+ ? msr_interrupt_prefix
+ : 0)
+ ));
+
+ /* patch the system call instruction to call this emulation and then
+ do an rfi */
+ node = device_tree_add_parsed(root, "/openprom/init/data@0x%lx",
+ (long)bugapi->system_call_address);
+ device_tree_add_parsed(node, "./real-address 0x%lx",
+ (long)bugapi->system_call_address);
+ device_tree_add_parsed(node, "./data 0x%x",
+ emul_call_instruction);
+ node = device_tree_add_parsed(root, "/openprom/init/data@0x%lx",
+ (long)(bugapi->system_call_address + 4));
+ device_tree_add_parsed(node, "./real-address 0x%lx",
+ (long)(bugapi->system_call_address + 4));
+ device_tree_add_parsed(node, "./data 0x%x",
+ emul_rfi_instruction);
+
+ /* patch the end of the system call instruction so that it contains
+ a loop to self instruction and point all the cpu's at this */
+ node = device_tree_add_parsed(root, "/openprom/init/data@0x%lx",
+ (unsigned long)bugapi->stall_cpu_loop_address);
+ device_tree_add_parsed(node, "./real-address 0x%lx",
+ (unsigned long)bugapi->stall_cpu_loop_address);
+ device_tree_add_parsed(node, "./data 0x%lx",
+ (unsigned long)emul_loop_instruction);
- /* hardware */
- device_tree_add_found_uw_u_u(root, "/", "memory",
- 0, memory_size, access_read_write_exec);
- device_tree_add_found(root, "/", "iobus@0x400000");
- device_tree_add_found(root, "/iobus", "console@0x000000,16");
- device_tree_add_found(root, "/iobus", "halt@0x100000,4");
- device_tree_add_found(root, "/iobus", "icu@0x200000,4");
+ device_tree_add_parsed(root, "/openprom/init/stack/stack-type %s",
+ elf_binary ? "elf" : "aix");
- { /* initialization */
- device *init = device_tree_add_found(root, "/", "init");
- {
- device *init_register = device_tree_add_found(init, "", "register");
- device_add_integer_property(init_register,
- "pc",
- OEA_STALL_CPU_LOOP_ADDRESS);
- device_add_integer_property(init_register,
- "0.pc",
- bfd_get_start_address(image));
- device_add_integer_property(init_register,
- "sp",
- memory_size-16);
- device_add_integer_property(init_register,
- "msr",
- (msr_recoverable_interrupt
- | (little_endian
- ? msr_little_endian_mode
- : 0)
- ));
- device_tree_add_found_uw_u_u(init, "",
- "data",
- OEA_SYSTEM_CALL_ADDRESS,
- 4, emul_call_instruction);
- device_tree_add_found_uw_u_u(init, "",
- "data",
- OEA_SYSTEM_CALL_ADDRESS + 4,
- 4, emul_rfi_instruction);
- device_tree_add_found_uw_u_u(init, "",
- "data",
- OEA_STALL_CPU_LOOP_ADDRESS,
- 4, emul_loop_instruction);
- }
- {
- device *init_stack = device_tree_add_found(init, "", "stack");
- device_add_null_property(init_stack,
- (elf_binary
- ? "elf"
- : "aix"));
- }
- {
- device *init_load_binary = device_tree_add_found(init, "",
- "load-binary");
- device_add_null_property(init_load_binary,
- bfd_get_filename(image));
- }
- }
- }
-
- return (os_emul_data*)-1;
+ device_tree_add_parsed(root, "/openprom/init/load-binary/file-name \"%s",
+ bfd_get_filename(image));
+
+ return bugapi;
}
static void
@@ -200,7 +184,7 @@ emul_bugapi_instruction_call(cpu *processor,
{
const int call_id = cpu_registers(processor)->gpr[10];
/* check that this isn't an invalid instruction */
- if (cia != OEA_SYSTEM_CALL_ADDRESS)
+ if (cia != emul_data->system_call_address)
return 0;
switch (call_id) {
case _OUTCHR:
diff --git a/sim/ppc/emul_generic.c b/sim/ppc/emul_generic.c
index 8f8ae09..f45df6c 100644
--- a/sim/ppc/emul_generic.c
+++ b/sim/ppc/emul_generic.c
@@ -1,6 +1,6 @@
/* This file is part of the program psim.
- Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+ Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -214,4 +214,82 @@ emul_do_system_call(os_emul_data *emul_data,
emul_syscall_exit(emul, call, arg0, processor, cia);
}
+
+/* default size for the first bank of memory */
+
+#ifndef OEA_MEMORY_SIZE
+#define OEA_MEMORY_SIZE 0x100000
+#endif
+
+
+/* Add options to the device tree */
+
+INLINE_EMUL_GENERIC void
+emul_add_tree_options(device *tree,
+ bfd *image,
+ const char *emul,
+ const char *env,
+ int oea_interrupt_prefix)
+{
+ int little_endian = 0;
+
+ /* sort out little endian */
+ if (device_find_property(tree, "/options/little-endian?"))
+ little_endian = device_find_boolean_property(tree, "/options/little-endian?");
+ else {
+#ifdef bfd_little_endian /* new bfd */
+ little_endian = (image != NULL && bfd_little_endian(image));
+#else
+ little_endian = (image != NULL &&
+ !image->xvec->byteorder_big_p);
+#endif
+ device_tree_add_parsed(tree, "/options/little-endian? %s",
+ little_endian ? "true" : "false");
+ }
+
+ /* misc other stuff */
+ device_tree_add_parsed(tree, "/openprom/options/oea-memory-size 0x%x",
+ OEA_MEMORY_SIZE);
+ device_tree_add_parsed(tree, "/openprom/options/oea-interrupt-prefix %d",
+ oea_interrupt_prefix);
+ device_tree_add_parsed(tree, "/openprom/options/smp 1");
+ device_tree_add_parsed(tree, "/openprom/options/env %s", env);
+ device_tree_add_parsed(tree, "/openprom/options/os-emul %s", emul);
+ device_tree_add_parsed(tree, "/openprom/options/strict-alignment? %s",
+ (WITH_ALIGNMENT == STRICT_ALIGNMENT || little_endian)
+ ? "true" : "false");
+ device_tree_add_parsed(tree, "/openprom/options/floating-point? %s",
+ WITH_FLOATING_POINT ? "true" : "false");
+ device_tree_add_parsed(tree, "/openprom/options/model \"%s",
+ model_name[WITH_DEFAULT_MODEL]);
+ device_tree_add_parsed(tree, "/openprom/options/model-issue %d",
+ MODEL_ISSUE_IGNORE);
+}
+
+INLINE_EMUL_GENERIC void
+emul_add_tree_hardware(device *root)
+{
+ /* add some memory */
+ if (device_tree_find_device(root, "/memory") == NULL) {
+ unsigned_word memory_size =
+ device_find_integer_property(root, "/openprom/options/oea-memory-size");
+ device_tree_add_parsed(root, "/memory@0/reg { 0x0 0x%lx",
+ (unsigned long)memory_size);
+ /* what about allocated? */
+ }
+ /* an eeprom */
+ device_tree_add_parsed(root, "/openprom/eeprom@0xfff00000/reg { 0xfff00000 0x3000");
+ /* the IO bus */
+ device_tree_add_parsed(root, "/iobus@0x400000/reg { 0x400000 0x400000");
+ device_tree_add_parsed(root, "/iobus/console@0x000000/reg { 0x000000 16");
+ device_tree_add_parsed(root, "/iobus/halt@0x100000/reg { 0x100000 4");
+ device_tree_add_parsed(root, "/iobus/icu@0x200000/reg { 0x200000 8");
+ device_tree_add_parsed(root, "/iobus/icu > 0 0 /iobus/icu");
+ device_tree_add_parsed(root, "/iobus/icu > 1 1 /iobus/icu");
+ /* chosen etc */
+ device_tree_add_parsed(root, "/chosen/stdin */iobus/console");
+ device_tree_add_parsed(root, "/chosen/stdout !/chosen/stdin");
+ device_tree_add_parsed(root, "/chosen/memory */memory");
+}
+
#endif /* _SYSTEM_C_ */
diff --git a/sim/ppc/emul_netbsd.c b/sim/ppc/emul_netbsd.c
index 6db39a4..27de365 100644
--- a/sim/ppc/emul_netbsd.c
+++ b/sim/ppc/emul_netbsd.c
@@ -45,8 +45,17 @@
#include <sys/errno.h>
#include <sys/param.h>
#include <sys/time.h>
+
+#ifdef HAVE_GETRUSAGE
+#ifndef HAVE_SYS_RESOURCE_H
+#undef HAVE_GETRUSAGE
+#endif
+#endif
+
+#ifdef HAVE_GETRUSAGE
#include <sys/resource.h>
int getrusage();
+#endif
#include <sys/ioctl.h>
#include <sys/mount.h>
@@ -224,6 +233,7 @@ write_direntries(unsigned_word addr,
#endif
+#ifdef HAVE_GETRUSAGE
STATIC_INLINE_EMUL_NETBSD void
write_rusage(unsigned_word addr,
struct rusage rusage,
@@ -250,7 +260,7 @@ write_rusage(unsigned_word addr,
H2T(rusage.ru_nivcsw); /* involuntary context switches */
emul_write_buffer(&rusage, addr, sizeof(rusage), processor, cia);
}
-
+#endif
static void
do_exit(os_emul_data *emul,
@@ -648,6 +658,9 @@ do_gettimeofday(os_emul_data *emul,
}
+#ifndef HAVE_GETRUSAGE
+#define do_getrusage 0
+#else
static void
do_getrusage(os_emul_data *emul,
unsigned call,
@@ -670,6 +683,7 @@ do_getrusage(os_emul_data *emul,
write_rusage(rusage_addr, rusage, processor, cia);
}
}
+#endif
#if !WITH_NetBSD_HOST
@@ -1277,7 +1291,8 @@ emul_netbsd_create(device *root,
/* options */
emul_add_tree_options(root, image, "netbsd",
(WITH_ENVIRONMENT == USER_ENVIRONMENT
- ? "user" : "virtual"));
+ ? "user" : "virtual"),
+ 0 /*oea-interrupt-prefix*/);
/* virtual memory - handles growth of stack/heap */
vm = device_tree_add_parsed(root, "/openprom/vm@0x%lx",
diff --git a/sim/ppc/psim.c b/sim/ppc/psim.c
index e12556c..cbdc35e 100644
--- a/sim/ppc/psim.c
+++ b/sim/ppc/psim.c
@@ -1,6 +1,6 @@
/* This file is part of the program psim.
- Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+ Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -22,25 +22,20 @@
#ifndef _PSIM_C_
#define _PSIM_C_
+#include "inline.c"
+
#include <stdio.h>
#include <ctype.h>
-#include "config.h"
-#include "ppc-config.h"
-#include "inline.h"
-
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
-#ifndef STATIC_INLINE_PSIM
-#define STATIC_INLINE_PSIM STATIC_INLINE
-#endif
-
#include <setjmp.h>
#include "cpu.h" /* includes psim.h */
#include "idecode.h"
+#include "options.h"
#ifdef HAVE_STRING_H
#include <string.h>
@@ -53,39 +48,24 @@
#include "bfd.h"
-#include "inline.c"
-
-/* Any starting address less than this is assumed to be an OEA program
- rather than VEA. */
-#ifndef OEA_START_ADDRESS
-#define OEA_START_ADDRESS 4096
-#endif
-
-/* Any starting address greater than this is assumed to be an OpenBoot
- rather than VEA */
-#ifndef OPENBOOT_START_ADDRESS
-#define OPENBOOT_START_ADDRESS 0x80000000
-#endif
-
-#ifndef OEA_MEMORY_SIZE
-#define OEA_MEMORY_SIZE 0x100000
-#endif
-
-
/* system structure, actual size of processor array determined at
runtime */
struct _psim {
event_queue *events;
- device_tree *devices;
+ device *devices;
mon *monitor;
+ os_emul *os_emulation;
core *memory;
+
/* escape routine for inner functions */
void *path_to_halt;
void *path_to_restart;
+
/* status from last halt */
psim_status halt_status;
- /* the processes proper */
+
+ /* the processors proper */
int nr_cpus;
int last_cpu; /* CPU that last (tried to) execute an instruction */
cpu *processors[MAX_NR_PROCESSORS];
@@ -101,306 +81,207 @@ int current_model_issue = MODEL_ISSUE_IGNORE;
model_enum current_model = WITH_DEFAULT_MODEL;
-/* create a device tree from the image */
-
-
+/* create the device tree */
-/* Raw hardware tree:
-
- A small default set of devices are configured. Each section of the
- image is loaded directly into physical memory. */
-
-STATIC_INLINE_PSIM void
-create_hardware_device_tree(bfd *image,
- device_tree *root)
+INLINE_PSIM\
+(device *)
+psim_tree(void)
{
- char *name;
- const memory_size = OEA_MEMORY_SIZE;
-
- /* options */
- device_tree_add_passthrough(root, "/options");
- device_tree_add_integer(root, "/options/smp",
- MAX_NR_PROCESSORS);
- device_tree_add_boolean(root, "/options/little-endian?",
- !image->xvec->byteorder_big_p);
- device_tree_add_string(root, "/options/env",
- "operating");
- device_tree_add_boolean(root, "/options/strict-alignment?",
- (WITH_ALIGNMENT == STRICT_ALIGNMENT
- || !image->xvec->byteorder_big_p));
- device_tree_add_boolean(root, "/options/floating-point?",
- WITH_FLOATING_POINT);
-
- /* hardware */
- name = printd_uw_u_u("/memory", 0, memory_size, access_read_write_exec);
- device_tree_add_found_device(root, name);
- zfree(name);
- device_tree_add_found_device(root, "/iobus@0x400000");
- device_tree_add_found_device(root, "/iobus/console@0x000000,16");
- device_tree_add_found_device(root, "/iobus/halt@0x100000,4");
- device_tree_add_found_device(root, "/iobus/icu@0x200000,4");
-
- /* initialization */
- device_tree_add_passthrough(root, "/init");
- device_tree_add_found_device(root, "/init/register@pc,0x0");
- name = printd_c_uw("/init/register", "sp", memory_size);
- device_tree_add_found_device(root, name);
- zfree(name);
- name = printd_c_uw("/init/register", "msr",
- (image->xvec->byteorder_big_p
- ? 0
- : msr_little_endian_mode));
- device_tree_add_found_device(root, name);
- zfree(name);
- /* AJC puts the PC at zero and wants a stack while MM puts it above
- zero and doesn't. Really there should be no stack *but* this
- makes testing easier */
- device_tree_add_found_device(root,
- (bfd_get_start_address(image) == 0
- ? "/init/stack@elf"
- : "/init/stack@none"));
- name = printd_c("/init/load-binary", bfd_get_filename(image));
- device_tree_add_found_device(root, name);
- zfree(name);
+ device *root = core_device_create();
+ device_tree_add_parsed(root, "/aliases");
+ device_tree_add_parsed(root, "/options");
+ device_tree_add_parsed(root, "/chosen");
+ device_tree_add_parsed(root, "/packages");
+ device_tree_add_parsed(root, "/cpus");
+ device_tree_add_parsed(root, "/openprom");
+ device_tree_add_parsed(root, "/openprom/init");
+ device_tree_add_parsed(root, "/openprom/trace");
+ device_tree_add_parsed(root, "/openprom/options");
+ return root;
}
-
-/* Openboot model (under development):
-
- An extension of the hardware model. The image is read into memory
- as a single block. Sections of the image are then mapped as
- required using a HTAB. */
-
-STATIC_INLINE_PSIM void
-create_openboot_device_tree(bfd *image,
- device_tree *root)
+STATIC_INLINE_PSIM\
+(char *)
+find_arg(char *err_msg,
+ int *ptr_to_argp,
+ char **argv)
{
- create_hardware_device_tree(image, root);
+ *ptr_to_argp += 1;
+ if (argv[*ptr_to_argp] == NULL)
+ error(err_msg);
+ return argv[*ptr_to_argp];
}
-
-/* User mode model:
-
- Image sections loaded into virtual addresses as specified. A
- (large) stack is reserved (but only allocated as needed). System
- calls that include suport for heap growth are attached. */
-
-STATIC_INLINE_PSIM void
-create_vea_device_tree(bfd *image,
- device_tree *root)
+INLINE_PSIM\
+(void)
+psim_usage(int verbose)
{
- unsigned_word top_of_stack;
- unsigned stack_size;
- int elf_binary;
- char *name;
-
- /* establish a few defaults */
- if (image->xvec->flavour == bfd_target_elf_flavour) {
- elf_binary = 1;
- top_of_stack = 0xe0000000;
- stack_size = 0x00100000;
- }
- else {
- elf_binary = 0;
- top_of_stack = 0x20000000;
- stack_size = 0x00100000;
+ 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-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-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 chirp - OEA + a few OpenBoot calls\n");
+ printf_filtered("\n"); }
+ printf_filtered("\t-i Print instruction counting statistics\n");
+ if (verbose) { printf_filtered("\n"); }
+ printf_filtered("\t-I Print execution unit statistics\n");
+ if (verbose) { printf_filtered("\n"); }
+ printf_filtered("\t-r <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("\t-o <spec> add device <spec> to 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("\n");
+ trace_usage(verbose);
+ device_usage(verbose);
+ if (verbose > 1) {
+ printf_filtered("\n");
+ print_options();
}
-
- /* options */
- device_tree_add_passthrough(root, "/options");
- device_tree_add_integer(root, "/options/smp", 1); /* always */
- device_tree_add_boolean(root, "/options/little-endian?",
- !image->xvec->byteorder_big_p);
- device_tree_add_string(root, "/options/env",
- (WITH_ENVIRONMENT == USER_ENVIRONMENT
- ? "user" : "virtual"));
- device_tree_add_boolean(root, "/options/strict-alignment?",
- (WITH_ALIGNMENT == STRICT_ALIGNMENT
- || !image->xvec->byteorder_big_p));
- device_tree_add_boolean(root, "/options/floating-point?",
- WITH_FLOATING_POINT);
-
- /* virtual memory - handles growth of stack/heap */
- name = printd_uw_u("/vm", top_of_stack - stack_size, stack_size);
- device_tree_add_found_device(root, name);
- zfree(name);
- name = printd_c("/vm/map-binary", bfd_get_filename(image));
- device_tree_add_found_device(root, name);
- zfree(name);
-
- /* finish the init */
- device_tree_add_passthrough(root, "/init");
- name = printd_c_uw("/init/register", "pc", bfd_get_start_address(image));
- device_tree_add_found_device(root, name); /*pc*/
- zfree(name);
- name = printd_c_uw("/init/register", "sp", top_of_stack);
- device_tree_add_found_device(root, name);
- zfree(name);
- name = printd_c_uw("/init/register", "msr",
- (image->xvec->byteorder_big_p
- ? 0
- : msr_little_endian_mode));
- device_tree_add_found_device(root, name);
- zfree(name);
- device_tree_add_found_device(root, (elf_binary
- ? "/init/stack@elf"
- : "/init/stack@xcoff"));
+ error("");
}
-
-/* File device:
-
- The file contains lines that specify the describe the device tree
- to be created, read them in and load them into the tree */
-
-STATIC_INLINE_PSIM void
-create_filed_device_tree(const char *file_name,
- device_tree *root)
+INLINE_PSIM\
+(char **)
+psim_options(device *root,
+ char **argv)
{
- FILE *description = fopen(file_name, "r");
- int line_nr = 0;
- char device_path[1000];
- while (fgets(device_path, sizeof(device_path), description)) {
- /* check all of line was read */
- {
- char *end = strchr(device_path, '\n');
- if (end == NULL) {
- fclose(description);
- error("create_filed_device_tree() line %d to long: %s\n",
- line_nr, device_path);
- }
- line_nr++;
- *end = '\0';
- }
- /* check for leading comment */
- if (device_path[0] != '/')
- continue;
- /* enter it in varying ways */
- if (strchr(device_path, '@') != NULL) {
- device_tree_add_found_device(root, device_path);
- }
- else {
- char *space = strchr(device_path, ' ');
- if (space == NULL) {
- /* intermediate node */
- device_tree_add_passthrough(root, device_path);
- }
- else if (space[-1] == '?') {
- /* boolean */
- *space = '\0';
- device_tree_add_boolean(root, device_path, space[1] != '0');
- }
- else if (isdigit(space[1])) {
- /* integer */
- *space = '\0';
- device_tree_add_integer(root, device_path, strtoul(space+1, 0, 0));
- }
- else if (space[1] == '"') {
- /* quoted string */
- char *end = strchr(space+2, '\0');
- if (end[-1] == '"')
- end[-1] = '\0';
- *space = '\0';
- device_tree_add_string(root, device_path, space + 2);
- }
- else {
- /* any thing else */
- *space = '\0';
- device_tree_add_string(root, device_path, space + 1);
+ 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 'e':
+ param = find_arg("Missing <emul> option for -e\n", &argp, argv);
+ device_tree_add_parsed(root, "/openprom/options/os-emul %s", param);
+ break;
+ case 'h':
+ case '?':
+ psim_usage(1);
+ break;
+ case 'H':
+ psim_usage(2);
+ break;
+ case 'i':
+ device_tree_add_parsed(root, "/openprom/trace/print-info 1");
+ break;
+ case 'I':
+ device_tree_add_parsed(root, "/openprom/trace/print-info 2");
+ device_tree_add_parsed(root, "/openprom/options/model-issue %d",
+ MODEL_ISSUE_PROCESS);
+ break;
+ case 'm':
+ param = find_arg("Missing <model> option for -m\n", &argp, argv);
+ device_tree_add_parsed(root, "/openprom/options/model %s", param);
+ break;
+ case 'o':
+ param = find_arg("Missing <device> option for -o\n", &argp, argv);
+ current = device_tree_add_parsed(current, "%s", param);
+ break;
+ case 'r':
+ param = find_arg("Missing <ram-size> option for -r\n", &argp, argv);
+ device_tree_add_parsed(root, "/openprom/options/oea-memory-size 0x%lx",
+ atol(param));
+ break;
+ case 't':
+ param = find_arg("Missing <trace> option for -t\n", &argp, argv);
+ if (param[0] == '!')
+ device_tree_add_parsed(root, "/openprom/trace/%s 0", param+1);
+ else
+ device_tree_add_parsed(root, "/openprom/trace/%s 1", param);
+ break;
}
+ p += 1;
}
+ argp += 1;
}
- fclose(description);
-}
-
-
-/* Given the file containing the `image', create a device tree that
- defines the machine to be modeled */
-
-STATIC_INLINE_PSIM device_tree *
-create_device_tree(const char *file_name,
- core *memory)
-{
- bfd *image;
- const device *core_device = core_device_create(memory);
- device_tree *root = device_tree_add_device(NULL, "/", core_device);
-
- bfd_init(); /* could be redundant but ... */
-
- /* open the file */
- image = bfd_openr(file_name, NULL);
- if (image == NULL) {
- bfd_perror("open failed:");
- error("nothing loaded\n");
- }
-
- /* check it is valid */
- if (!bfd_check_format(image, bfd_object)) {
- printf_filtered("create_device_tree() - FIXME - should check more bfd bits\n");
- printf_filtered("create_device_tree() - %s not an executable, assume device file\n", file_name);
- bfd_close(image);
- image = NULL;
- }
-
- /* depending on what was found about the file, load it */
- if (image != NULL) {
- if (bfd_get_start_address(image) < OEA_START_ADDRESS) {
- TRACE(trace_device_tree, ("create_device_tree() - hardware image\n"));
- create_hardware_device_tree(image, root);
- }
- else if (bfd_get_start_address(image) < OPENBOOT_START_ADDRESS) {
- TRACE(trace_device_tree, ("create_device_tree() - vea image\n"));
- create_vea_device_tree(image, root);
- }
- else {
- TRACE(trace_device_tree, ("create_device_tree() - openboot? image\n"));
- create_openboot_device_tree(image, root);
- }
- bfd_close(image);
- }
- else {
- TRACE(trace_device_tree, ("create_device_tree() - text image\n"));
- create_filed_device_tree(file_name, root);
- }
-
- return root;
+ /* force the trace node to (re)process its options */
+ device_init_data(device_tree_find_device(root, "/openprom/trace"), NULL);
+ /* return where the options end */
+ return argv + argp;
}
+/* create the simulator proper from the device tree and executable */
-INLINE_PSIM psim *
-psim_create(const char *file_name)
+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;
- /* create things */
- system = ZALLOC(psim);
- system->events = event_queue_create();
- system->memory = core_create();
- system->monitor = mon_create();
- system->devices = create_device_tree(file_name, system->memory);
- for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) {
- system->processors[cpu_nr] = cpu_create(system,
- system->memory,
- system->events,
- mon_cpu(system->monitor,
- cpu_nr),
- cpu_nr);
- }
+ /* given this partially populated device tree, os_emul_create() uses
+ it and file_name to determine the selected emulation and hence
+ further populate the tree with any other required nodes. */
+
+ 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);
/* fill in the missing real number of CPU's */
- system->nr_cpus = device_tree_find_integer(system->devices,
- "/options/smp");
+ nr_cpus = device_find_integer_property(root, "/openprom/options/smp");
+ if (MAX_NR_PROCESSORS < nr_cpus)
+ error("target and configured number of cpus conflict\n");
/* fill in the missing TARGET BYTE ORDER information */
- current_target_byte_order = (device_tree_find_boolean(system->devices,
- "/options/little-endian?")
- ? LITTLE_ENDIAN
- : BIG_ENDIAN);
+ current_target_byte_order
+ = (device_find_boolean_property(root, "/options/little-endian?")
+ ? LITTLE_ENDIAN
+ : BIG_ENDIAN);
if (CURRENT_TARGET_BYTE_ORDER != current_target_byte_order)
- error("target byte order conflict\n");
+ error("target and configured byte order conflict\n");
/* fill in the missing HOST BYTE ORDER information */
current_host_byte_order = (current_host_byte_order = 1,
@@ -408,11 +289,10 @@ psim_create(const char *file_name)
? LITTLE_ENDIAN
: BIG_ENDIAN));
if (CURRENT_HOST_BYTE_ORDER != current_host_byte_order)
- error("host byte order conflict\n");
+ error("host and configured byte order conflict\n");
/* fill in the missing OEA/VEA information */
- env = device_tree_find_string(system->devices,
- "/options/env");
+ env = device_find_string_property(root, "/openprom/options/env");
current_environment = ((strcmp(env, "user") == 0
|| strcmp(env, "uea") == 0)
? USER_ENVIRONMENT
@@ -424,25 +304,67 @@ psim_create(const char *file_name)
? OPERATING_ENVIRONMENT
: 0);
if (current_environment == 0)
- error("unreconized /options/env\n");
+ error("unreconized /options env property\n");
if (CURRENT_ENVIRONMENT != current_environment)
- error("target environment conflict\n");
+ error("target and configured environment conflict\n");
/* fill in the missing ALLIGNMENT information */
- current_alignment = (device_tree_find_boolean(system->devices,
- "/options/strict-alignment?")
- ? STRICT_ALIGNMENT
- : NONSTRICT_ALIGNMENT);
+ current_alignment
+ = (device_find_boolean_property(root, "/openprom/options/strict-alignment?")
+ ? STRICT_ALIGNMENT
+ : NONSTRICT_ALIGNMENT);
if (CURRENT_ALIGNMENT != current_alignment)
- error("target alignment conflict\n");
+ error("target and configured alignment conflict\n");
/* fill in the missing FLOATING POINT information */
- current_floating_point = (device_tree_find_boolean(system->devices,
- "/options/floating-point?")
- ? HARD_FLOATING_POINT
- : SOFT_FLOATING_POINT);
+ current_floating_point
+ = (device_find_boolean_property(root, "/openprom/options/floating-point?")
+ ? HARD_FLOATING_POINT
+ : SOFT_FLOATING_POINT);
if (CURRENT_FLOATING_POINT != current_floating_point)
- error("target floating-point conflict\n");
+ error("target and configured floating-point conflict\n");
+
+ /* sort out the level of detail for issue modeling */
+ current_model_issue
+ = device_find_integer_property(root, "/openprom/options/model-issue");
+ if (CURRENT_MODEL_ISSUE != current_model_issue)
+ error("target and configured model-issue conflict\n");
+
+ /* sort out our model architecture - wrong.
+
+ FIXME: this should be obtaining the required information from the
+ device tree via the "/chosen" property "cpu" which is an instance
+ (ihandle) for the only executing processor. By converting that
+ ihandle into the corresponding cpu's phandle and then querying
+ the "name" property, the cpu type can be determined. Ok? */
+
+ model_set(device_find_string_property(root, "/openprom/options/model"));
+
+ /* create things */
+ system = ZALLOC(psim);
+ system->events = event_queue_create();
+ system->memory = core_create(root);
+ system->monitor = mon_create();
+ system->nr_cpus = nr_cpus;
+ system->os_emulation = os_emulation;
+ system->devices = root;
+
+ /* now all the processors attaching to each their per-cpu information */
+ for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) {
+ system->processors[cpu_nr] = cpu_create(system,
+ system->memory,
+ system->events,
+ mon_cpu(system->monitor,
+ cpu_nr),
+ system->os_emulation,
+ cpu_nr);
+ }
+
+ /* dump out the contents of the device tree */
+ if (ppc_trace[trace_print_device_tree] || ppc_trace[trace_dump_device_tree])
+ device_tree_traverse(root, device_tree_print_device, NULL, NULL);
+ if (ppc_trace[trace_dump_device_tree])
+ error("");
return system;
}
@@ -450,7 +372,8 @@ psim_create(const char *file_name)
/* allow the simulation to stop/restart abnormaly */
-STATIC_INLINE_PSIM void
+STATIC_INLINE_PSIM\
+(void)
psim_set_halt_and_restart(psim *system,
void *halt_jmp_buf,
void *restart_jmp_buf)
@@ -459,14 +382,16 @@ psim_set_halt_and_restart(psim *system,
system->path_to_restart = restart_jmp_buf;
}
-STATIC_INLINE_PSIM void
+STATIC_INLINE_PSIM\
+(void)
psim_clear_halt_and_restart(psim *system)
{
system->path_to_halt = NULL;
system->path_to_restart = NULL;
}
-INLINE_PSIM void
+INLINE_PSIM\
+(void)
psim_restart(psim *system,
int current_cpu)
{
@@ -475,7 +400,8 @@ psim_restart(psim *system,
}
-INLINE_PSIM void
+INLINE_PSIM\
+(void)
psim_halt(psim *system,
int current_cpu,
unsigned_word cia,
@@ -490,14 +416,16 @@ psim_halt(psim *system,
longjmp(*(jmp_buf*)(system->path_to_halt), current_cpu + 1);
}
-INLINE_PSIM psim_status
+INLINE_PSIM\
+(psim_status)
psim_get_status(psim *system)
{
return system->halt_status;
}
-cpu *
+INLINE_PSIM\
+(cpu *)
psim_cpu(psim *system,
int cpu_nr)
{
@@ -508,7 +436,8 @@ psim_cpu(psim *system,
}
-const device *
+INLINE_PSIM\
+(device *)
psim_device(psim *system,
const char *path)
{
@@ -517,43 +446,55 @@ psim_device(psim *system,
-INLINE_PSIM void
+INLINE_PSIM\
+(void)
psim_init(psim *system)
{
int cpu_nr;
/* scrub the monitor */
mon_init(system->monitor, system->nr_cpus);
+ os_emul_init(system->os_emulation, system->nr_cpus);
+ event_queue_init(system->events);
/* scrub all the cpus */
for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
cpu_init(system->processors[cpu_nr]);
- /* init all the devices */
+ /* init all the devices (which updates the cpus) */
device_tree_init(system->devices, system);
+ /* now sync each cpu against the initialized state of its registers */
+ for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++) {
+ cpu_synchronize_context(system->processors[cpu_nr]);
+ cpu_page_tlb_invalidate_all(system->processors[cpu_nr]);
+ }
+
/* force loop to restart */
system->last_cpu = system->nr_cpus - 1;
}
-INLINE_PSIM void
+INLINE_PSIM\
+(void)
psim_stack(psim *system,
char **argv,
char **envp)
{
/* pass the stack device the argv/envp and let it work out what to
do with it */
- const device *stack_device = device_tree_find_device(system->devices,
- "/init/stack");
- unsigned_word stack_pointer;
- psim_read_register(system, 0, &stack_pointer, "sp", cooked_transfer);
- stack_device->callback->ioctl(stack_device,
- system,
- NULL, /*cpu*/
- 0, /*cia*/
- stack_pointer,
- argv,
- envp);
+ device *stack_device = 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,
+ system,
+ NULL, /*cpu*/
+ 0, /*cia*/
+ stack_pointer,
+ argv,
+ envp);
+ }
}
@@ -566,14 +507,15 @@ psim_stack(psim *system,
Consequently this function is written in multiple different ways */
-STATIC_INLINE_PSIM void
+STATIC_INLINE_PSIM\
+(void)
run_until_stop(psim *system,
volatile int *keep_running)
{
jmp_buf halt;
jmp_buf restart;
- int cpu_nr;
#if WITH_IDECODE_CACHE_SIZE
+ int cpu_nr;
for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
cpu_flush_icache(system->processors[cpu_nr]);
#endif
@@ -655,7 +597,8 @@ run_until_stop(psim *system,
cia,
cache_entry);
- mon_event(mon_event_icache_miss, processor, cia);
+ if (WITH_MON != 0)
+ mon_event(mon_event_icache_miss, processor, cia);
cache_entry->address = cia;
cache_entry->semantic = semantic;
cia = semantic(processor, cache_entry, cia);
@@ -750,7 +693,8 @@ run_until_stop(psim *system,
cia,
cache_entry);
- mon_event(mon_event_icache_miss, system->processors[current_cpu], cia);
+ if (WITH_MON != 0)
+ mon_event(mon_event_icache_miss, system->processors[current_cpu], cia);
cache_entry->address = cia;
cache_entry->semantic = semantic;
cpu_set_program_counter(processor,
@@ -771,20 +715,23 @@ run_until_stop(psim *system,
/* SIMULATE INSTRUCTIONS, various different ways of achieving the same
thing */
-INLINE_PSIM void
+INLINE_PSIM\
+(void)
psim_step(psim *system)
{
volatile int keep_running = 0;
run_until_stop(system, &keep_running);
}
-INLINE_PSIM void
+INLINE_PSIM\
+(void)
psim_run(psim *system)
{
run_until_stop(system, NULL);
}
-INLINE_PSIM void
+INLINE_PSIM\
+(void)
psim_run_until_stop(psim *system,
volatile int *keep_running)
{
@@ -795,7 +742,8 @@ psim_run_until_stop(psim *system,
/* storage manipulation functions */
-INLINE_PSIM void
+INLINE_PSIM\
+(void)
psim_read_register(psim *system,
int which_cpu,
void *buf,
@@ -884,7 +832,8 @@ psim_read_register(psim *system,
-INLINE_PSIM void
+INLINE_PSIM\
+(void)
psim_write_register(psim *system,
int which_cpu,
const void *buf,
@@ -980,7 +929,8 @@ psim_write_register(psim *system,
-INLINE_PSIM unsigned
+INLINE_PSIM\
+(unsigned)
psim_read_memory(psim *system,
int which_cpu,
void *buffer,
@@ -998,7 +948,8 @@ psim_read_memory(psim *system,
}
-INLINE_PSIM unsigned
+INLINE_PSIM\
+(unsigned)
psim_write_memory(psim *system,
int which_cpu,
const void *buffer,
@@ -1017,7 +968,8 @@ psim_write_memory(psim *system,
}
-INLINE_PSIM void
+INLINE_PSIM\
+(void)
psim_print_info(psim *system,
int verbose)
{
@@ -1025,4 +977,30 @@ psim_print_info(psim *system,
}
+/* Merge a device tree and a device file. */
+
+INLINE_PSIM\
+(void)
+psim_merge_device_file(device *root,
+ const char *file_name)
+{
+ FILE *description = fopen(file_name, "r");
+ int line_nr = 0;
+ char device_path[1000];
+ device *current = root;
+ while (fgets(device_path, sizeof(device_path), description)) {
+ /* check all of line was read */
+ if (strchr(device_path, '\n') == NULL) {
+ fclose(description);
+ error("create_filed_device_tree() line %d to long: %s\n",
+ line_nr, device_path);
+ }
+ line_nr++;
+ /* parse this line */
+ current = device_tree_add_parsed(current, "%s", device_path);
+ }
+ fclose(description);
+}
+
+
#endif /* _PSIM_C_ */