aboutsummaryrefslogtreecommitdiff
path: root/sim/ppc/psim.c
diff options
context:
space:
mode:
Diffstat (limited to 'sim/ppc/psim.c')
-rw-r--r--sim/ppc/psim.c283
1 files changed, 54 insertions, 229 deletions
diff --git a/sim/ppc/psim.c b/sim/ppc/psim.c
index 2a89782..0c7024e 100644
--- a/sim/ppc/psim.c
+++ b/sim/ppc/psim.c
@@ -22,7 +22,10 @@
#ifndef _PSIM_C_
#define _PSIM_C_
-#include "inline.c"
+#include "cpu.h" /* includes psim.h */
+#include "idecode.h"
+#include "options.h"
+
#include <stdio.h>
#include <ctype.h>
@@ -33,10 +36,6 @@
#include <setjmp.h>
-#include "cpu.h" /* includes psim.h */
-#include "idecode.h"
-#include "options.h"
-
#ifdef HAVE_STRING_H
#include <string.h>
#else
@@ -45,6 +44,7 @@
#endif
#endif
+
#include "bfd.h"
@@ -87,7 +87,7 @@ INLINE_PSIM\
(device *)
psim_tree(void)
{
- device *root = core_device_create();
+ device *root = device_tree_add_parsed(NULL, "core");
device_tree_add_parsed(root, "/aliases");
device_tree_add_parsed(root, "/options");
device_tree_add_parsed(root, "/chosen");
@@ -245,7 +245,8 @@ psim_options(device *root,
argp += 1;
}
/* force the trace node to (re)process its options */
- device_init_data(device_tree_find_device(root, "/openprom/trace"), NULL);
+ device_ioctl(device_tree_find_device(root, "/openprom/trace"), NULL, 0);
+
/* return where the options end */
return argv + argp;
}
@@ -345,7 +346,7 @@ psim_create(const char *file_name,
/* create things */
system = ZALLOC(psim);
system->events = event_queue_create();
- system->memory = core_create(root);
+ system->memory = core_from_device(root);
system->monitor = mon_create();
system->nr_cpus = nr_cpus;
system->os_emulation = os_emulation;
@@ -373,7 +374,7 @@ psim_create(const char *file_name,
/* allow the simulation to stop/restart abnormaly */
-STATIC_INLINE_PSIM\
+INLINE_PSIM\
(void)
psim_set_halt_and_restart(psim *system,
void *halt_jmp_buf,
@@ -383,7 +384,7 @@ psim_set_halt_and_restart(psim *system,
system->path_to_restart = restart_jmp_buf;
}
-STATIC_INLINE_PSIM\
+INLINE_PSIM\
(void)
psim_clear_halt_and_restart(psim *system)
{
@@ -419,6 +420,20 @@ psim_halt(psim *system,
}
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)
{
@@ -463,7 +478,8 @@ psim_init(psim *system)
/* scrub the monitor */
mon_init(system->monitor, system->nr_cpus);
- os_emul_init(system->os_emulation, system->nr_cpus);
+
+ /* trash any pending events */
event_queue_init(system->events);
/* scrub all the cpus */
@@ -473,6 +489,9 @@ psim_init(psim *system)
/* init all the devices (which updates the cpus) */
device_tree_init(system->devices, system);
+ /* and the emulation (which needs an initialized device tree) */
+ os_emul_init(system->os_emulation, system->nr_cpus);
+
/* 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]);
@@ -480,7 +499,7 @@ psim_init(psim *system)
}
/* force loop to restart */
- system->last_cpu = system->nr_cpus - 1;
+ system->last_cpu = -1; /* when incremented will become 0 - first CPU */
}
INLINE_PSIM\
@@ -497,7 +516,6 @@ psim_stack(psim *system,
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,
@@ -508,219 +526,6 @@ psim_stack(psim *system,
-/* EXECUTE REAL CODE:
-
- Unfortunatly, there are multiple cases to consider vis:
-
- <icache> X <smp> X <events> X <keep-running-flag> X ...
-
- Consequently this function is written in multiple different ways */
-
-STATIC_INLINE_PSIM\
-(void)
-run_until_stop(psim *system,
- volatile int *keep_running)
-{
- jmp_buf halt;
- jmp_buf restart;
-#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
- psim_set_halt_and_restart(system, &halt, &restart);
-
-#if (!WITH_IDECODE_CACHE_SIZE && WITH_SMP == 0)
-
- /* CASE 1: No instruction cache and no SMP.
-
- In this case, we can take advantage of the fact that the current
- instruction address does not need to be returned to the cpu
- object after every execution of an instruction. Instead it only
- needs to be saved when either A. the main loop exits or B. a
- cpu-{halt,restart} call forces the loop to be re-entered. The
- later functions always save the current cpu instruction
- address. */
-
- if (!setjmp(halt)) {
- do {
- if (!setjmp(restart)) {
- cpu *const processor = system->processors[0];
- unsigned_word cia = cpu_get_program_counter(processor);
- do {
- if (WITH_EVENTS) {
- if (event_queue_tick(system->events)) {
- cpu_set_program_counter(processor, cia);
- event_queue_process(system->events);
- cia = cpu_get_program_counter(processor);
- }
- }
- {
- instruction_word const instruction
- = vm_instruction_map_read(cpu_instruction_map(processor),
- processor, cia);
- cia = idecode_issue(processor, instruction, cia);
- }
- } while (keep_running == NULL || *keep_running);
- cpu_set_program_counter(processor, cia);
- }
- } while(keep_running == NULL || *keep_running);
- }
-#endif
-
-
-#if (WITH_IDECODE_CACHE_SIZE && WITH_SMP == 0)
-
- /* CASE 2: Instruction case but no SMP
-
- Here, the additional complexity comes from there being two
- different cache implementations. A simple function address cache
- or a full cracked instruction cache */
-
- if (!setjmp(halt)) {
- do {
- if (!setjmp(restart)) {
- cpu *const processor = system->processors[0];
- unsigned_word cia = cpu_get_program_counter(processor);
- do {
- if (WITH_EVENTS)
- if (event_queue_tick(system->events)) {
- cpu_set_program_counter(processor, cia);
- event_queue_process(system->events);
- cia = cpu_get_program_counter(processor);
- }
- {
- idecode_cache *const cache_entry = cpu_icache_entry(processor,
- cia);
- if (cache_entry->address == cia) {
- idecode_semantic *const semantic = cache_entry->semantic;
- cia = semantic(processor, cache_entry, cia);
- }
- else {
- instruction_word const instruction
- = vm_instruction_map_read(cpu_instruction_map(processor),
- processor,
- cia);
- idecode_semantic *const semantic = idecode(processor,
- instruction,
- cia,
- cache_entry);
-
- 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);
- }
- }
- } while (keep_running == NULL || *keep_running);
- cpu_set_program_counter(processor, cia);
- }
- } while(keep_running == NULL || *keep_running);
- }
-#endif
-
-
-#if (!WITH_IDECODE_CACHE_SIZE && WITH_SMP > 0)
-
- /* CASE 3: No ICACHE but SMP
-
- The complexity here comes from needing to correctly restart the
- system when it is aborted. In particular if cpu0 requests a
- restart, the next cpu is still cpu1. Cpu0 being restarted after
- all the other CPU's and the event queue have been processed */
-
- if (!setjmp(halt)) {
- int first_cpu = setjmp(restart);
- if (first_cpu == 0)
- first_cpu = system->last_cpu + 1;
- do {
- int current_cpu;
- for (current_cpu = first_cpu, first_cpu = 0;
- current_cpu < system->nr_cpus + (WITH_EVENTS ? 1 : 0);
- current_cpu++) {
- if (WITH_EVENTS && current_cpu == system->nr_cpus) {
- if (event_queue_tick(system->events))
- event_queue_process(system->events);
- }
- else {
- cpu *const processor = system->processors[current_cpu];
- unsigned_word const cia = cpu_get_program_counter(processor);
- instruction_word instruction =
- vm_instruction_map_read(cpu_instruction_map(processor),
- processor,
- cia);
- cpu_set_program_counter(processor,
- idecode_issue(processor, instruction, cia));
- }
- if (!(keep_running == NULL || *keep_running)) {
- system->last_cpu = current_cpu;
- break;
- }
- }
- } while (keep_running == NULL || *keep_running);
- }
-#endif
-
-#if (WITH_IDECODE_CACHE_SIZE && WITH_SMP > 0)
-
- /* CASE 4: ICACHE and SMP ...
-
- This time, everything goes wrong. Need to restart loops
- correctly, need to save the program counter and finally need to
- keep track of each processors current address! */
-
- if (!setjmp(halt)) {
- int first_cpu = setjmp(restart);
- if (!first_cpu)
- first_cpu = system->last_cpu + 1;
- do {
- int current_cpu;
- for (current_cpu = first_cpu, first_cpu = 0;
- current_cpu < system->nr_cpus + (WITH_EVENTS ? 1 : 0);
- current_cpu++) {
- if (WITH_EVENTS && current_cpu == system->nr_cpus) {
- if (event_queue_tick(system->events))
- event_queue_process(system->events);
- }
- else {
- cpu *processor = system->processors[current_cpu];
- unsigned_word const cia = cpu_get_program_counter(processor);
- idecode_cache *cache_entry = cpu_icache_entry(processor, cia);
- if (cache_entry->address == cia) {
- idecode_semantic *semantic = cache_entry->semantic;
- cpu_set_program_counter(processor,
- semantic(processor, cache_entry, cia));
- }
- else {
- instruction_word instruction =
- vm_instruction_map_read(cpu_instruction_map(processor),
- processor,
- cia);
- idecode_semantic *semantic = idecode(processor,
- instruction,
- cia,
- cache_entry);
-
- 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,
- semantic(processor, cache_entry, cia));
- }
- }
- if (!(keep_running == NULL || *keep_running))
- break;
- }
- } while (keep_running == NULL || *keep_running);
- }
-#endif
-
- psim_clear_halt_and_restart(system);
-}
-
-
/* SIMULATE INSTRUCTIONS, various different ways of achieving the same
thing */
@@ -729,14 +534,16 @@ INLINE_PSIM\
psim_step(psim *system)
{
volatile int keep_running = 0;
- run_until_stop(system, &keep_running);
+ idecode_run_until_stop(system, &keep_running,
+ system->events, system->processors, system->nr_cpus);
}
INLINE_PSIM\
(void)
psim_run(psim *system)
{
- run_until_stop(system, NULL);
+ idecode_run(system,
+ system->events, system->processors, system->nr_cpus);
}
INLINE_PSIM\
@@ -744,7 +551,8 @@ INLINE_PSIM\
psim_run_until_stop(psim *system,
volatile int *keep_running)
{
- run_until_stop(system, keep_running);
+ idecode_run_until_stop(system, keep_running,
+ system->events, system->processors, system->nr_cpus);
}
@@ -806,6 +614,23 @@ psim_read_register(psim *system,
*(msreg*)cooked_buf = cpu_registers(processor)->msr;
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,