mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2025-02-24 19:42:32 +00:00
Update to 1995-02-20 release
This commit is contained in:
parent
d3b0a49d0e
commit
eada1efcaf
@ -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.
|
||||
|
@ -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
|
||||
|
106
sim/ppc/cpu.c
106
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)
|
||||
{
|
||||
}
|
||||
|
@ -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
|
||||
#define OEA_START_ADDRESS 0x100000
|
||||
#endif
|
||||
|
||||
#ifndef OEA_MEMORY_SIZE
|
||||
#define OEA_MEMORY_SIZE 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");
|
||||
}
|
||||
|
||||
/* 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");
|
||||
|
||||
{ /* 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
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*/);
|
||||
|
||||
return (os_emul_data*)-1;
|
||||
/* 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);
|
||||
|
||||
device_tree_add_parsed(root, "/openprom/init/stack/stack-type %s",
|
||||
elf_binary ? "elf" : "aix");
|
||||
|
||||
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:
|
||||
|
@ -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_ */
|
||||
|
@ -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",
|
||||
|
700
sim/ppc/psim.c
700
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);
|
||||
}
|
||||
|
||||
|
||||
/* 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)
|
||||
{
|
||||
create_hardware_device_tree(image, root);
|
||||
}
|
||||
|
||||
|
||||
/* 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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"));
|
||||
}
|
||||
|
||||
|
||||
/* 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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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-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();
|
||||
}
|
||||
error("");
|
||||
}
|
||||
|
||||
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 '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;
|
||||
}
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
||||
INLINE_PSIM psim *
|
||||
psim_create(const char *file_name)
|
||||
/* create the simulator proper from the device tree and executable */
|
||||
|
||||
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_ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user