Update to 1995-02-20 release

This commit is contained in:
Michael Meissner 1996-02-21 16:47:06 +00:00
parent d3b0a49d0e
commit eada1efcaf
7 changed files with 656 additions and 506 deletions

View File

@ -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.

View File

@ -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

View File

@ -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)
{
}

View File

@ -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:

View File

@ -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_ */

View File

@ -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",

View File

@ -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_ */