January 23rd merge

This commit is contained in:
Michael Meissner 1997-01-27 21:34:50 +00:00
parent 1d5c6cfdf0
commit 5c04f4f7fc
18 changed files with 7090 additions and 2868 deletions

47
sim/ppc/BUGS Normal file
View File

@ -0,0 +1,47 @@
ChangeLog
See the ChangeLog file looking for lines taged with the word FIXME.
COREFILE.C:
The implementation of corefile.c (defined by corefile.h) isn't the
best. It is intended to be functionaly correct rather than fast. One
option being considered is to add a data cache to reduce the overhead
of the most common case of data read/writes.
VEA
Missing VEA system calls.
ppc-instructions:
Missing or commented out instructions.
64bit:
64bit target untested. 64bit host broken. For instance use of scanf
"%x", &long long.
events.c:
Event code for pending events from within signal handlers not
finished/tested.
hw_*.c:
Better and more devices.
PORTABILITY:
(Notes taken from Michael Meissner): Heavy use of the ## operator -
fix using the clasic X/**/Y hack; Use of the signed keyword. In
particular, signed char has no analogue in classic C (though most
implementations of classic C use signed chars); Use of long long which
restricts the target compiler to be GCC.
device_ioctl():
Should have an extra argument (unsigned request) as standard.

File diff suppressed because it is too large Load Diff

View File

@ -196,12 +196,14 @@ DEVICE_TABLE_H = \
$(BASICS_H) \
device_table.h \
device.h \
tree.h \
hw.h
EMUL_GENERIC_H = \
$(CPU_H) \
$(IDECODE_H) \
emul_generic.h \
tree.h \
os_emul.h
@ -227,7 +229,7 @@ BUILT_SRC = \
config.h \
ppc-config.h
LIB_SRC = \
LIB_INLINE_SRC = \
psim.c \
bits.c \
debug.c \
@ -239,21 +241,20 @@ LIB_SRC = \
corefile.c \
events.c \
os_emul.c \
emul_generic.c \
emul_netbsd.c \
emul_unix.c \
emul_chirp.c \
emul_bugapi.c \
registers.c \
cpu.c \
interrupts.c \
device.c \
tree.c \
device_table.c \
cap.c \
mon.c \
options.c \
options.c
LIB_SRC = \
$(PACKAGE_SRC) \
$(HW_SRC)
$(HW_SRC) \
$(LIB_INLINE_SRC)
MAIN_SRC = \
main.c \
@ -269,10 +270,10 @@ LIB_OBJ = \
sim-endian.o \
os_emul.o \
emul_generic.o \
emul_bugapi.o \
emul_chirp.o \
emul_netbsd.o \
emul_unix.o \
emul_chirp.o \
emul_bugapi.o \
registers.o \
vm.o \
corefile.o \
@ -283,6 +284,7 @@ LIB_OBJ = \
events.o \
cap.o \
device.o \
tree.o \
device_table.o \
itable.o \
mon.o \
@ -291,9 +293,9 @@ LIB_OBJ = \
idecode.o \
support.o \
psim.o \
options.o \
$(PACKAGE_OBJ) \
$(HW_OBJ)
$(HW_OBJ) \
options.o
GDB_OBJ = sim_calls.o
@ -317,9 +319,7 @@ $(TARGETLIB): tmp-igen tmp-dgen tmp-hw tmp-pk $(LIB_OBJ) $(GDB_OBJ)
$(AR) $(AR_FLAGS) $(TARGETLIB) $(LIB_OBJ) $(GDB_OBJ)
$(RANLIB) $(TARGETLIB)
# Given that inlines are turned on now, rebuild psim whenever
# anything changes.
psim.o: psim.c psim.h $(CPU_H) $(IDECODE_H) $(INLINE) $(LIB_SRC) $(BUILT_SRC)
psim.o: psim.c psim.h tree.h $(CPU_H) $(IDECODE_H)
bits.o: bits.c $(BASICS_H)
@ -331,10 +331,10 @@ sim-endian.o: sim-endian.c sim-endian-n.h $(BASICS_H)
os_emul.o: os_emul.c emul_netbsd.h emul_unix.h emul_chirp.h emul_bugapi.h $(EMUL_GENERIC_H)
emul_generic.o: emul_generic.c $(EMUL_GENERIC_H)
emul_bugapi.o: emul_bugapi.c emul_bugapi.h $(EMUL_GENERIC_H)
emul_chirp.o: emul_chirp.c emul_chirp.h $(EMUL_GENERIC_H)
emul_netbsd.o: emul_netbsd.c emul_netbsd.h $(EMUL_GENERIC_H)
emul_unix.o: emul_unix.c emul_unix.h $(EMUL_GENERIC_H)
emul_chirp.o: emul_chirp.c emul_chirp.h $(EMUL_GENERIC_H)
emul_bugapi.o: emul_bugapi.c emul_bugapi.h $(EMUL_GENERIC_H)
registers.o: registers.c $(REGISTERS_H) $(BASICS_H)
@ -342,13 +342,14 @@ cpu.o: cpu.c $(CPU_H) $(IDECODE_H)
interrupts.o: interrupts.c $(CPU_H) $(IDECODE_H) os_emul.h
idecode.o: idecode.c $(CPU_H) $(IDECODE_H) semantics.h
# Given that inlines are turned on now, rebuild idecode whenever
# anything changes.
idecode.o: idecode.c $(CPU_H) $(IDECODE_H) semantics.h $(LIB_INLINE_SRC) $(BUILT_SRC)
$(CC) -c $(NOWARN_CFLAGS) $<
# double.o: double.c dp-bit.c
vm.o: vm.c vm.h vm_n.h $(BASICS_H) $(REGISTERS_H) \
device.h corefile.h interrupts.h itable.h mon.h
vm.o: vm.c vm.h vm_n.h $(CPU_H)
corefile.o: corefile.c corefile.h corefile-n.h $(BASICS_H) $(DEVICE_TABLE_H)
@ -364,6 +365,8 @@ main.o: main.c $(PSIM_H) itable.h options.h
device.o: device.c $(DEVICE_TABLE_H) cap.h
tree.o: tree.c tree.h device.h $(DEVICE_TABLE_H)
device_table.o: device_table.c $(DEVICE_TABLE_H) events.h hw.c
cap.o: cap.c cap.h $(BASICS_H)
@ -381,9 +384,12 @@ itable.o: itable.c itable.h
mon.o: mon.c $(CPU_H)
# Rebuild options whenever something changes so the date/time is up to date.
options.o: options.c $(BASICS_H) $(CPU_H) $(IDECODE_H) $(INLINE) $(LIB_SRC) $(BUILT_SRC) config.status Makefile
options.o: options.c $(BASICS_H) $(CPU_H) $(IDECODE_H) $(INLINE) $(LIB_SRC) $(BUILT_SRC) config.status Makefile defines.h
$(CC) -c $(STD_CFLAGS) '-DOPCODE_RULES="@sim_opcode@"' '-DIGEN_FLAGS="$(IGEN_FLAGS)"' '-DDGEN_FLAGS="$(DGEN_FLAGS)"' $<
defines.h: config.h Makefile
rm -f defines.h
sed -n -e '/^#define HAVE_/s/ 1$$/",/' -e '/^#define HAVE_/s//"HAVE_/p' < config.h > defines.h
#
# Rules to create the built c source code files
#
@ -510,13 +516,13 @@ misc.o: misc.c misc.h filter_filename.h
# real hardware
tmp-hw: Makefile $(HW_SRC) $(srcdir)/../../move-if-change
for hw in $(HW_SRC) ; do echo $$hw ; done \
| sort -u \
| cat -n | sort +1 -u | sort -n \
| sed -e 's/^.*\(hw_.*\)\.c/\1/' \
-e 's/^/extern const device_descriptor /' \
-e 's/$$/_device_descriptor\[\];/' \
> tmp-hw.h
for hw in $(HW_SRC) ; do echo $$hw ; done \
| sort -u \
| cat -n | sort +1 -u | sort -n \
| sed -e 's/^.*\(hw_.*\)\.c/\1/' \
-e 's/^/ /' \
-e 's/$$/_device_descriptor,/' \
@ -526,17 +532,21 @@ tmp-hw: Makefile $(HW_SRC) $(srcdir)/../../move-if-change
touch tmp-hw
hw_cpu.o: hw_cpu.c $(DEVICE_TABLE_H)
hw_core.o: hw_core.c $(DEVICE_TABLE_H)
hw_disk.o: hw_disk.c $(DEVICE_TABLE_H) pk.h
hw_glue.o: hw_glue.c $(DEVICE_TABLE_H)
hw_htab.o: hw_htab.c $(DEVICE_TABLE_H)
hw_ide.o: hw_ide.c $(DEVICE_TABLE_H)
hw_init.o: hw_init.c $(DEVICE_TABLE_H)
hw_iobus.o: hw_iobus.c $(DEVICE_TABLE_H)
hw_memory.o: hw_memory.c $(DEVICE_TABLE_H)
hw_nvram.o: hw_nvram.c $(DEVICE_TABLE_H)
hw_iobus.o: hw_iobus.c $(DEVICE_TABLE_H)
hw_core.o: hw_core.c $(DEVICE_TABLE_H)
hw_opic.o: hw_opic.c $(DEVICE_TABLE_H)
hw_pal.o: hw_pal.c $(DEVICE_TABLE_H)
hw_htab.o: hw_htab.c $(DEVICE_TABLE_H)
hw_disk.o: hw_disk.c $(DEVICE_TABLE_H) pk.h
hw_trace.o: hw_trace.c $(DEVICE_TABLE_H)
hw_phb.o: hw_phb.c $(DEVICE_TABLE_H) hw_phb.h
hw_register.o: hw_register.c $(DEVICE_TABLE_H)
hw_trace.o: hw_trace.c $(DEVICE_TABLE_H)
hw_vm.o: hw_vm.c $(DEVICE_TABLE_H)
hw_init.o: hw_init.c $(DEVICE_TABLE_H)
# ignore this line, it stops make from getting confused
@ -544,8 +554,8 @@ hw_init.o: hw_init.c $(DEVICE_TABLE_H)
# real packages
tmp-pk: Makefile $(PACKAGE_SRC) $(srcdir)/../../move-if-change
for pk in $(PACKAGE_SRC) ; do echo $$pk ; done \
| sort -u \
| sed -e 's/^pk_\(.*\)\.c/\1/' \
| cat -n | sort +1 -u | sort -n \
| sed -e 's/^.*pk_\(.*\)\.c/\1/' \
-e 's/^/extern package_create_instance_callback pk_/' \
-e 's/$$/_create_instance;/' \
> tmp-pk.h
@ -563,10 +573,10 @@ TAGS: $(BUILT_SRC)
etags $(srcdir)/*.h $(srcdir)/*.c $(BUILT_SRC)
clean mostlyclean:
rm -f tmp-* *.[oasi] core psim run igen dgen config.log $(BUILT_SRC_WO_CONFIG)
rm -f tmp-* *.[oasi] core psim run igen dgen $(BUILT_SRC_WO_CONFIG)
distclean realclean: clean
rm -f TAGS Makefile config.cache config.status config.h stamp-h
rm -f TAGS Makefile config.cache config.status config.h defines.h stamp-h config.log
maintainer-clean: distclean
rm -f *~ *.log ppc-config.h core *.core

1571
sim/ppc/configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -237,11 +237,11 @@ fi])dnl
AC_ARG_ENABLE(sim-icache,
[ --enable-sim-icache=size Specify instruction cache size.],
[icache=""
[ --enable-sim-icache=size Specify instruction-decode cache size and type.],
[icache="-R"
case "${enableval}" in
yes) icache="1024"; sim_icache="-I $icache";;
no) sim_icache="";;
no) sim_icache="-R";;
*) icache=1024
sim_icache="-"
for x in `echo "${enableval}" | sed -e "s/,/ /g"`; do
@ -257,7 +257,7 @@ AC_ARG_ENABLE(sim-icache,
esac
if test x"$silent" != x"yes" && test x"$icache" != x""; then
echo "Setting instruction cache size to $icache ($sim_icache)"
fi],[sim_icache="-CSI 1024"
fi],[sim_icache="-CSRI 1024"
if test x"$silent" != x"yes"; then
echo "Setting instruction cache size to 1024 ($sim_icache)"
fi])dnl
@ -307,7 +307,7 @@ AC_ARG_ENABLE(sim-jump,
esac
if test x"$silent" != x"yes" && test x"$sim_jump" != x""; then
echo "Setting jump flag = $sim_jump" 6>&1
fi],[sim_jump="-E"
fi],[sim_jump=""
if test x"$silent" != x"yes"; then
echo "Setting jump flag = $sim_jump" 6>&1
fi])dnl

File diff suppressed because it is too large Load Diff

View File

@ -42,40 +42,47 @@
*/
/* Constructing the device tree:
The initial device tree populated with devices and basic properties
is created using the function <<device_tree_add_parsed()>>. This
function parses a PSIM device specification and uses it to populate
the tree accordingly.
This function accepts a printf style formatted string as the
argument that describes the entry. Any properties or interrupt
connections added to a device tree using this function are marked
as having a permenant disposition. When the tree is (re)
initialized they will be restored to their initial value.
*/
EXTERN_DEVICE\
(device *) device_tree_add_parsed
(device *current,
const char *fmt,
...) __attribute__ ((format (printf, 2, 3)));
/* Initializing the created tree:
Once a device tree has been created the <<device_tree_init()>>
function is used to initialize it. The exact sequence of events
that occure during initialization are described separatly.
*/
/* Device creation: */
INLINE_DEVICE\
(void) device_tree_init
(device *) device_create
(device *parent,
const char *base,
const char *name,
const char *unit_address,
const char *args);
INLINE_DEVICE\
(void) device_usage
(int verbose);
/* Device initialization: */
INLINE_DEVICE\
(void) device_clean
(device *root,
psim *system);
void *data);
INLINE_DEVICE\
(void) device_init_static_properties
(device *me,
void *data);
INLINE_DEVICE\
(void) device_init_address
(device *me,
void *data);
INLINE_DEVICE\
(void) device_init_runtime_properties
(device *me,
void *data);
INLINE_DEVICE\
(void) device_init_data
(device *me,
void *data);
/* Relationships:
@ -90,6 +97,10 @@ INLINE_DEVICE\
(device *) device_parent
(device *me);
INLINE_DEVICE\
(device *) device_root
(device *me);
INLINE_DEVICE\
(device *) device_sibling
(device *me);
@ -102,6 +113,10 @@ INLINE_DEVICE\
(const char *) device_name
(device *me);
INLINE_DEVICE\
(const char *) device_base
(device *me);
INLINE_DEVICE\
(const char *) device_path
(device *me);
@ -116,13 +131,63 @@ INLINE_DEVICE\
typedef struct _device_unit {
int nr_cells;
unsigned32 cells[4]; /* unused cells are zero */
unsigned_cell cells[4]; /* unused cells are zero */
} device_unit;
INLINE_DEVICE\
(const device_unit *) device_unit_address
(device *me);
INLINE_DEVICE\
(int) device_decode_unit
(device *bus,
const char *unit,
device_unit *address);
INLINE_DEVICE\
(int) device_encode_unit
(device *bus,
const device_unit *unit_address,
char *buf,
int sizeof_buf);
/* Convert an Open Firmware size into a form suitable for attach
address calls.
Return a zero result if the address should be ignored when looking
for attach addresses */
INLINE_DEVICE\
(int) device_address_to_attach_address
(device *me,
const device_unit *address,
int *attach_space,
unsigned_word *attach_address,
device *client);
/* Convert an Open Firmware size into a form suitable for attach
address calls
Return a zero result if the address should be ignored */
INLINE_DEVICE\
(int) device_size_to_attach_size
(device *me,
const device_unit *size,
unsigned *nr_bytes,
device *client);
INLINE_DEVICE\
(unsigned) device_nr_address_cells
(device *me);
INLINE_DEVICE\
(unsigned) device_nr_size_cells
(device *me);
/* Properties:
@ -132,15 +197,18 @@ INLINE_DEVICE\
*/
/* The following are valid property types. The property `array' is a
/* The following are valid property types. The property `array' is
for generic untyped data. */
typedef enum {
array_property,
boolean_property,
ihandle_property,
ihandle_property, /*runtime*/
integer_property,
range_array_property,
reg_array_property,
string_property,
string_array_property,
} device_property_type;
typedef struct _device_property device_property;
@ -176,8 +244,24 @@ INLINE_DEVICE\
FIND returns the specified properties value, aborting the
simulation if the property is missing. Code locating a property
should first check its type (using device_find_property above) and
then obtain its value using the below. */
then obtain its value using the below.
void device_add_<type>_property(device *, const char *, <type>)
void device_add_*_array_property(device *, const char *, const <type>*, int)
void device_set_*_property(device *, const char *, <type>)
void device_set_*_array_property(device *, const char *, const <type>*, int)
<type> device_find_*_property(device *, const char *)
int device_find_*_array_property(device *, const char *, int, <type>*)
*/
INLINE_DEVICE\
(void) device_add_array_property
(device *me,
const char *property,
const void *array,
int sizeof_array);
INLINE_DEVICE\
(void) device_set_array_property
@ -192,13 +276,12 @@ INLINE_DEVICE\
const char *property);
#if 0
INLINE_DEVICE\
(void) device_set_boolean_property
(void) device_add_boolean_property
(device *me,
const char *property,
int bool);
#endif
INLINE_DEVICE\
(int) device_find_boolean_property
@ -206,13 +289,30 @@ INLINE_DEVICE\
const char *property);
#if 0
typedef struct _ihandle_runtime_property_spec {
device *phandle;
const char *full_path;
const char *args;
} ihandle_runtime_property_spec;
INLINE_DEVICE\
(void) device_add_ihandle_runtime_property
(device *me,
const char *property,
const ihandle_runtime_property_spec *ihandle);
INLINE_DEVICE\
(void) device_find_ihandle_runtime_property
(device *me,
const char *property,
ihandle_runtime_property_spec *ihandle);
INLINE_DEVICE\
(void) device_set_ihandle_property
(device *me,
const char *property,
device_instance *ihandle);
#endif
INLINE_DEVICE\
(device_instance *) device_find_ihandle_property
@ -220,27 +320,75 @@ INLINE_DEVICE\
const char *property);
#if 0
INLINE_DEVICE\
(void) device_set_integer_property
(device *me,
const char *property,
signed_word integer);
#endif
INLINE_DEVICE\
(signed_word) device_find_integer_property
(void) device_add_integer_property
(device *me,
const char *property,
signed_cell integer);
INLINE_DEVICE\
(signed_cell) device_find_integer_property
(device *me,
const char *property);
#if 0
INLINE_DEVICE\
(void) device_set_string_property
(int) device_find_integer_array_property
(device *me,
const char *property,
unsigned index,
signed_word *integer);
typedef struct _range_property_spec {
device_unit child_address;
device_unit parent_address;
device_unit size;
} range_property_spec;
INLINE_DEVICE\
(void) device_add_range_array_property
(device *me,
const char *property,
const range_property_spec *ranges,
unsigned nr_ranges);
INLINE_DEVICE\
(int) device_find_range_array_property
(device *me,
const char *property,
unsigned index,
range_property_spec *range);
typedef struct _reg_property_spec {
device_unit address;
device_unit size;
} reg_property_spec;
INLINE_DEVICE\
(void) device_add_reg_array_property
(device *me,
const char *property,
const reg_property_spec *reg,
unsigned nr_regs);
INLINE_DEVICE\
(int) device_find_reg_array_property
(device *me,
const char *property,
unsigned index,
reg_property_spec *reg);
INLINE_DEVICE\
(void) device_add_string_property
(device *me,
const char *property,
const char *string);
#endif
INLINE_DEVICE\
(const char *) device_find_string_property
@ -248,6 +396,33 @@ INLINE_DEVICE\
const char *property);
typedef const char *string_property_spec;
INLINE_DEVICE\
(void) device_add_string_array_property
(device *me,
const char *property,
const string_property_spec *strings,
unsigned nr_strings);
INLINE_DEVICE\
(int) device_find_string_array_property
(device *me,
const char *property,
unsigned index,
string_property_spec *string);
INLINE_DEVICE\
(void) device_add_duplicate_property
(device *me,
const char *property,
const device_property *original);
/* Instances:
As with IEEE1275, a device can be opened, creating an instance.
@ -277,7 +452,8 @@ INLINE_DEVICE\
INLINE_DEVICE\
(device_instance *) device_create_instance
(device *me,
const char *device_specifier);
const char *full_path,
const char *args);
INLINE_DEVICE\
(void) device_instance_delete
@ -302,17 +478,13 @@ INLINE_DEVICE\
unsigned_word pos_lo);
INLINE_DEVICE\
(unsigned_word) device_instance_claim
(int) device_instance_call_method
(device_instance *instance,
unsigned_word address,
unsigned_word length,
unsigned_word alignment);
INLINE_DEVICE\
(void) device_instance_release
(device_instance *instance,
unsigned_word address,
unsigned_word length);
const char *method,
int n_stack_args,
unsigned_cell stack_args[/*n_stack_args*/],
int n_stack_returns,
unsigned_cell stack_returns[/*n_stack_returns*/]);
INLINE_DEVICE\
(device *) device_instance_device
@ -378,6 +550,20 @@ INLINE_DEVICE\
device *dest,
int dest_port);
typedef void (device_interrupt_traverse_function)
(device *me,
int my_port,
device *dest,
int my_dest,
void *data);
INLINE_DEVICE\
(void) device_interrupt_traverse
(device *me,
device_interrupt_traverse_function *handler,
void *data);
/* DESTINATION is attached (detached) to LINE of the device ME
@ -393,14 +579,16 @@ INLINE_DEVICE\
INLINE_DEVICE\
(int) device_interrupt_decode
(device *me,
const char *symbolic_name);
const char *symbolic_name,
port_direction direction);
INLINE_DEVICE\
(int) device_interrupt_encode
(device *me,
int port_number,
char *buf,
int sizeof_buf);
int sizeof_buf,
port_direction direction);
/* Hardware operations:
@ -480,24 +668,22 @@ typedef enum _attach_type {
INLINE_DEVICE\
(void) device_attach_address
(device *me,
const char *name,
attach_type attach,
int space,
unsigned_word addr,
unsigned nr_bytes,
access_type access,
device *who); /*callback/default*/
device *client); /*callback/default*/
INLINE_DEVICE\
(void) device_detach_address
(device *me,
const char *name,
attach_type attach,
int space,
unsigned_word addr,
unsigned nr_bytes,
access_type access,
device *who); /*callback/default*/
device *client); /*callback/default*/
/* Utilities:
@ -513,11 +699,20 @@ INLINE_DEVICE\
*/
typedef enum {
device_ioctl_break, /* unsigned_word requested_break */
device_ioctl_set_trace, /* void */
device_ioctl_create_stack, /* unsigned_word *sp, char **argv, char **envp */
device_ioctl_change_media, /* const char *new_image (possibly NULL) */
nr_device_ioctl_requests,
} device_ioctl_request;
EXTERN_DEVICE\
(int) device_ioctl
(device *me,
cpu *processor,
unsigned_word cia,
device_ioctl_request request,
...);
@ -539,60 +734,10 @@ EXTERN_DEVICE\
const char *fmt,
...) __attribute__ ((format (printf, 2, 3)));
/* Tree traversal::
The entire device tree can be traversed using the
<<device_tree_traverse()>> function. The traversal can be in
either pre- or postfix order.
*/
typedef void (device_tree_traverse_function)
(device *device,
void *data);
INLINE_DEVICE\
(void) device_tree_traverse
(device *root,
device_tree_traverse_function *prefix,
device_tree_traverse_function *postfix,
void *data);
(int) device_trace
(device *me);
/* Device description::
*/
INLINE_DEVICE\
(void) device_tree_print_device
(device *device,
void *ignore_data_argument);
/* Tree lookup::
The function <<device_tree_find_device()>> will attempt to locate
the specified device within the tree. If the device is not found a
NULL device is returned.
*/
INLINE_DEVICE\
(device *) device_tree_find_device
(device *root,
const char *path);
/* Device list or usage::
The <<device_usage()>> function outputs a list of all the devices
compiled into PSIM. The verbose option will result in additional
information being printed (for instance, the interrupt ports).
*/
INLINE_DEVICE\
(void) device_usage
(int verbose);
/* External representation:
@ -612,19 +757,43 @@ INLINE_DEVICE\
INLINE_DEVICE\
(device *) external_to_device
(device *tree_member,
unsigned32 phandle);
unsigned_cell phandle);
INLINE_DEVICE\
(unsigned32) device_to_external
(unsigned_cell) device_to_external
(device *me);
INLINE_DEVICE\
(device_instance *) external_to_device_instance
(device *tree_member,
unsigned32 ihandle);
unsigned_cell ihandle);
INLINE_DEVICE\
(unsigned32) device_instance_to_external
(unsigned_cell) device_instance_to_external
(device_instance *me);
/* Event queue:
The device inherets certain event queue operations from the main
simulation. */
typedef void device_event_handler(void *data);
INLINE_DEVICE\
(event_entry_tag) device_event_queue_schedule
(device *me,
signed64 delta_time,
device_event_handler *handler,
void *data);
INLINE_EVENTS\
(void) device_event_queue_deschedule
(device *me,
event_entry_tag event_to_remove);
INLINE_EVENTS\
(signed64) device_event_queue_time
(device *me);
#endif /* _DEVICE_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -83,45 +83,51 @@ print_icache_declaration(insn_table *entry,
static void
print_icache_extraction(lf *file,
insn *instruction,
char *field_name,
char *field_type,
char *field_expression,
const char *entry_name,
const char *entry_type,
const char *entry_expression,
const char *original_name,
const char *file_name,
int line_nr,
insn_field *cur_field,
insn_bits *bits,
int use_defines,
int get_value_from_cache,
int put_value_in_cache)
icache_decl_type what_to_declare,
icache_body_type what_to_do)
{
ASSERT(field_name != NULL);
if (use_defines && put_value_in_cache) {
ASSERT(entry_name != NULL);
/* Define a storage area for the cache element */
if (what_to_declare == undef_variables) {
/* We've finished with the value - destory it */
lf_indent_suppress(file);
lf_printf(file, "#undef %s\n", field_name);
lf_printf(file, "#undef %s\n", entry_name);
return;
}
else if (use_defines && get_value_from_cache) {
lf_indent_suppress(file);
lf_printf(file, "#define %s ", field_name);
else if (what_to_declare == define_variables) {
lf_indent_suppress(file);
lf_printf(file, "#define %s ", entry_name);
}
else {
lf_print__external_reference(file, line_nr, file_name);
lf_printf(file, "%s const %s __attribute__((__unused__)) = ",
field_type == NULL ? "unsigned" : field_type,
field_name);
if (file_name != NULL)
lf_print__external_reference(file, line_nr, file_name);
lf_printf(file, "%s const %s UNUSED = ",
entry_type == NULL ? "unsigned" : entry_type,
entry_name);
}
/* define a value for that storage area as determined by what is in
the cache */
if (bits != NULL
&& ((bits->opcode->is_boolean
&& bits->value == 0)
|| !bits->opcode->is_boolean)
&& strcmp(field_name, cur_field->val_string) == 0) {
&& strcmp(entry_name, cur_field->val_string) == 0
&& ((bits->opcode->is_boolean && bits->value == 0)
|| (!bits->opcode->is_boolean))) {
/* The field has been made constant (as a result of expanding
instructions or similar) - define a constant variable with the
corresponding value. */
instructions or similar). Remember that for a boolean field,
value is either 0 (implying the required boolean_constant) or
nonzero (implying some other value) - Define the variable
accordingly */
ASSERT(bits->field == cur_field);
ASSERT(field_type == NULL);
ASSERT(entry_type == NULL);
if (bits->opcode->is_boolean)
lf_printf(file, "%d", bits->opcode->boolean_constant);
else if (bits->opcode->last < bits->field->last)
@ -130,30 +136,48 @@ print_icache_extraction(lf *file,
else
lf_printf(file, "%d", bits->value);
}
else if (bits != NULL
&& bits->opcode->is_boolean
&& original_name != NULL
&& strncmp(entry_name,
original_name, strlen(original_name)) == 0
&& strncmp(entry_name + strlen(original_name),
"_is_", strlen("_is_")) == 0
&& (atol(entry_name + strlen(original_name) + strlen("_is_"))
== bits->opcode->boolean_constant)) {
/* An entry, derived from ORIGINAL_NAME, is testing to see of the
ORIGINAL_NAME has a specific constant value. That value
matching a boolean bit field */
lf_printf(file, "%d /* %s == %d */",
bits->value == 0, original_name, bits->opcode->boolean_constant);
}
else {
/* put the field in the local variable, possibly also enter it
into the cache */
/* getting it from the cache */
if (get_value_from_cache || put_value_in_cache) {
/* handle the cache */
if ((what_to_do & get_values_from_icache)
|| (what_to_do & put_values_in_icache)) {
lf_printf(file, "cache_entry->crack.%s.%s",
instruction->file_entry->fields[insn_form],
field_name);
if (put_value_in_cache) /* also put it in the cache? */
entry_name);
if (what_to_do & put_values_in_icache) /* also put it in the cache? */
lf_printf(file, " = ");
}
if (!get_value_from_cache) {
if (strcmp(field_name, cur_field->val_string) == 0)
if ((what_to_do & put_values_in_icache)
|| what_to_do == do_not_use_icache) {
if (cur_field != NULL && strcmp(entry_name, cur_field->val_string) == 0)
lf_printf(file, "EXTRACTED32(instruction, %d, %d)",
i2target(hi_bit_nr, cur_field->first),
i2target(hi_bit_nr, cur_field->last));
else if (field_expression != NULL)
lf_printf(file, "%s", field_expression);
else if (entry_expression != NULL)
lf_printf(file, "%s", entry_expression);
else
lf_printf(file, "eval_%s", field_name);
lf_printf(file, "eval_%s", entry_name);
}
}
if (use_defines && get_value_from_cache)
if ((what_to_declare == define_variables)
|| (what_to_declare == undef_variables))
lf_printf(file, "\n");
else
lf_printf(file, ";\n");
@ -165,16 +189,41 @@ print_icache_body(lf *file,
insn *instruction,
insn_bits *expanded_bits,
cache_table *cache_rules,
int use_defines,
int get_value_from_cache,
int put_value_in_cache)
icache_decl_type what_to_declare,
icache_body_type what_to_do)
{
insn_field *cur_field;
/* extract instruction fields */
lf_printf(file, "/* extraction: %s defines=%d get-value=%d put-value=%d */\n",
instruction->file_entry->fields[insn_format],
use_defines, get_value_from_cache, put_value_in_cache);
lf_printf(file, "/* extraction: %s ",
instruction->file_entry->fields[insn_format]);
switch (what_to_declare) {
case define_variables:
lf_printf(file, "#define");
break;
case declare_variables:
lf_printf(file, "declare");
break;
case undef_variables:
lf_printf(file, "#undef");
break;
}
lf_printf(file, " ");
switch (what_to_do) {
case get_values_from_icache:
lf_printf(file, "get-values-from-icache");
break;
case put_values_in_icache:
lf_printf(file, "put-values-in-icache");
break;
case both_values_and_icache:
lf_printf(file, "get-values-from-icache|put-values-in-icache");
break;
case do_not_use_icache:
lf_printf(file, "do-not-use-icache");
break;
}
lf_printf(file, " */\n");
for (cur_field = instruction->fields->first;
cur_field->first < insn_bit_size;
@ -190,100 +239,98 @@ print_icache_body(lf *file,
break;
}
/* try the cache rule table for what to do */
if (get_value_from_cache || put_value_in_cache) {
{
cache_table *cache_rule;
for (cache_rule = cache_rules;
cache_rule != NULL;
cache_rule = cache_rule->next) {
if (strcmp(cur_field->val_string, cache_rule->old_name) == 0) {
if (strcmp(cur_field->val_string, cache_rule->field_name) == 0) {
found_rule = 1;
if (cache_rule->type == compute_value
&& put_value_in_cache
&& !use_defines)
if (cache_rule->type == scratch_value
&& ((what_to_do & put_values_in_icache)
|| what_to_do == do_not_use_icache))
print_icache_extraction(file,
instruction,
cache_rule->new_name,
cache_rule->derived_name,
cache_rule->type_def,
cache_rule->expression,
cache_rule->field_name,
cache_rule->file_entry->file_name,
cache_rule->file_entry->line_nr,
cur_field,
bits,
0 /*use_defines*/,
0 /*get-value-from-cache*/,
0 /*put-value-in-cache*/);
else if (cache_rule->type == cache_value)
what_to_declare,
do_not_use_icache);
else if (cache_rule->type == compute_value
&& ((what_to_do & get_values_from_icache)
|| what_to_do == do_not_use_icache))
print_icache_extraction(file,
instruction,
cache_rule->new_name,
cache_rule->derived_name,
cache_rule->type_def,
cache_rule->expression,
cache_rule->field_name,
cache_rule->file_entry->file_name,
cache_rule->file_entry->line_nr,
cur_field,
bits,
use_defines,
get_value_from_cache,
put_value_in_cache);
what_to_declare,
do_not_use_icache);
else if (cache_rule->type == cache_value
&& ((what_to_declare != undef_variables)
|| !(what_to_do & put_values_in_icache)))
print_icache_extraction(file,
instruction,
cache_rule->derived_name,
cache_rule->type_def,
cache_rule->expression,
cache_rule->field_name,
cache_rule->file_entry->file_name,
cache_rule->file_entry->line_nr,
cur_field,
bits,
((what_to_do & put_values_in_icache)
? declare_variables
: what_to_declare),
what_to_do);
}
}
}
if (found_rule == 0)
/* No rule at all, assume that it should go into the cache */
if (found_rule == 0
&& ((what_to_declare != undef_variables)
|| !(what_to_do & put_values_in_icache)))
print_icache_extraction(file,
instruction,
cur_field->val_string,
0,
0,
NULL, NULL, NULL, /* type, exp, orig */
instruction->file_entry->file_name,
instruction->file_entry->line_nr,
cur_field,
bits,
use_defines,
get_value_from_cache,
put_value_in_cache);
/* if any (XXX == 0), output a corresponding test */
if (instruction->file_entry->annex != NULL) {
char *field_name = cur_field->val_string;
char *is_0_ptr = instruction->file_entry->annex;
int field_len = strlen(field_name);
if (strlen(is_0_ptr) >= (strlen("_is_0") + field_len)) {
is_0_ptr += field_len;
while ((is_0_ptr = strstr(is_0_ptr, "_is_0")) != NULL) {
if (strncmp(is_0_ptr - field_len, field_name, field_len) == 0
&& !isalpha(is_0_ptr[ - field_len - 1])) {
if (!use_defines || (use_defines && get_value_from_cache)) {
if (use_defines) {
lf_indent_suppress(file);
lf_printf(file, "#define %s_is_0 ", field_name);
}
else {
table_entry_print_cpp_line_nr(file, instruction->file_entry);
lf_printf(file, "const unsigned %s_is_0 __attribute__((__unused__)) = ",
field_name);
}
if (bits != NULL)
lf_printf(file, "(%d == 0)", bits->value);
else
lf_printf(file, "(%s == 0)", field_name);
if (use_defines)
lf_printf(file, "\n");
else
lf_printf(file, ";\n");
}
else if (use_defines && put_value_in_cache) {
lf_indent_suppress(file);
lf_printf(file, "#undef %s_is_0\n", field_name);
}
break;
}
is_0_ptr += strlen("_is_0");
}
}
}
((what_to_do & put_values_in_icache)
? declare_variables
: what_to_declare),
what_to_do);
/* any thing else ... */
}
}
lf_print__internal_reference(file);
if ((code & generate_with_insn_in_icache)) {
lf_printf(file, "\n");
print_icache_extraction(file,
instruction,
"insn",
"instruction_word",
"instruction",
NULL, /* origin */
NULL, 0, /* file_name & line_nr */
NULL, NULL,
what_to_declare,
what_to_do);
}
}
@ -356,6 +403,7 @@ print_icache_struct(insn_table *instructions,
{
icache_tree *tree = insn_table_cache_fields(instructions);
lf_printf(file, "\n");
lf_printf(file, "#define WITH_IDECODE_CACHE_SIZE %d\n",
(code & generate_with_icache) ? icache_size : 0);
lf_printf(file, "\n");
@ -372,6 +420,8 @@ print_icache_struct(insn_table *instructions,
form = form->next) {
icache_tree *field;
lf_printf(file, " struct {\n");
if (code & generate_with_insn_in_icache)
lf_printf(file, " instruction_word insn;\n");
for (field = form->children;
field != NULL;
field = field->next) {
@ -380,15 +430,15 @@ print_icache_struct(insn_table *instructions,
for (cache_rule = cache_rules;
cache_rule != NULL;
cache_rule = cache_rule->next) {
if (strcmp(field->name, cache_rule->old_name) == 0) {
if (strcmp(field->name, cache_rule->field_name) == 0) {
found_rule = 1;
if (cache_rule->new_name != NULL)
if (cache_rule->derived_name != NULL)
lf_printf(file, " %s %s; /* %s */\n",
(cache_rule->type_def == NULL
? "unsigned"
: cache_rule->type_def),
cache_rule->new_name,
cache_rule->old_name);
cache_rule->derived_name,
cache_rule->field_name);
}
}
if (!found_rule)
@ -400,23 +450,11 @@ print_icache_struct(insn_table *instructions,
lf_printf(file, "} idecode_cache;\n");
}
else {
/* alernativly, since no cache, #define the fields to be
extractions from the instruction variable. Emit a dummy
definition for idecode_cache to allow model_issue to not
be #ifdefed at the call level */
cache_table *cache_rule;
lf_printf(file, "\n");
/* alernativly, since no cache, emit a dummy definition for
idecode_cache so that code refering to the type can still compile */
lf_printf(file, "typedef void idecode_cache;\n");
lf_printf(file, "\n");
for (cache_rule = cache_rules;
cache_rule != NULL;
cache_rule = cache_rule->next) {
if (cache_rule->expression != NULL
&& strlen(cache_rule->expression) > 0)
lf_printf(file, "#define %s %s\n",
cache_rule->new_name, cache_rule->expression);
}
}
lf_printf(file, "\n");
}
@ -445,7 +483,7 @@ print_icache_function(lf *file,
lf_printf(file, "{\n");
lf_indent(file, +2);
print_define_my_index(file, instruction->file_entry);
print_my_defines(file, expanded_bits, instruction->file_entry);
print_itrace(file, instruction->file_entry, 1/*putting-value-in-cache*/);
print_idecode_validate(file, instruction, opcodes);
@ -453,47 +491,60 @@ print_icache_function(lf *file,
lf_printf(file, "\n");
lf_printf(file, "{\n");
lf_indent(file, +2);
if ((code & generate_with_semantic_icache))
lf_printf(file, "unsigned_word nia;\n");
print_icache_body(file,
instruction,
expanded_bits,
cache_rules,
0/*use_defines*/,
0/*get_value_from_cache*/,
1/*put_value_in_cache*/);
((code & generate_with_direct_access)
? define_variables
: declare_variables),
((code & generate_with_semantic_icache)
? both_values_and_icache
: put_values_in_icache));
lf_printf(file, "\n");
lf_printf(file, "cache_entry->address = cia;\n");
lf_printf(file, "cache_entry->semantic = ");
print_function_name(file,
instruction->file_entry->fields[insn_name],
expanded_bits,
function_name_prefix_semantics);
lf_printf(file, ";\n");
lf_printf(file, "\n");
if ((code & generate_with_semantic_icache)) {
lf_printf(file, "unsigned_word nia;\n");
lf_printf(file, "cache_entry->address = cia;\n");
lf_printf(file, "cache_entry->semantic = ");
print_function_name(file,
instruction->file_entry->fields[insn_name],
expanded_bits,
function_name_prefix_semantics);
lf_printf(file, ";\n");
lf_printf(file, "/* semantic routine */\n");
print_semantic_body(file,
instruction,
expanded_bits,
opcodes);
lf_printf(file, "\n");
lf_printf(file, "return nia;\n");
}
lf_indent(file, -2);
lf_printf(file, "}\n");
if (!(code & generate_with_semantic_icache)) {
/* return the function propper (main sorts this one out) */
lf_printf(file, "\n");
lf_printf(file, "/* semantic routine */\n");
table_entry_print_cpp_line_nr(file, instruction->file_entry);
lf_printf(file, "/* return the function proper */\n");
lf_printf(file, "return ");
print_function_name(file,
instruction->file_entry->fields[insn_name],
expanded_bits,
function_name_prefix_semantics);
lf_printf(file, ";\n");
lf_print__internal_reference(file);
}
if ((code & generate_with_direct_access))
print_icache_body(file,
instruction,
expanded_bits,
cache_rules,
undef_variables,
((code & generate_with_semantic_icache)
? both_values_and_icache
: put_values_in_icache));
lf_indent(file, -2);
lf_printf(file, "}\n");
lf_indent(file, -2);
lf_printf(file, "}\n");
}

View File

@ -42,6 +42,7 @@ lf_print_opcodes(lf *file,
{
if (table != NULL) {
while (1) {
ASSERT(table->opcode != NULL);
lf_printf(file, "_%d_%d",
table->opcode->first,
table->opcode->last);
@ -70,9 +71,10 @@ print_idecode_table(lf *file,
insn_table *entry,
const char *result)
{
/* int can_assume_leaf; */
#if 0
/* FIXME: I don't think the second part of this is correct! */
int can_assume_leaf;
decode_table *opcode_rule;
/* have a look at the rule table, if all table rules follow all
switch rules, I can assume that all end points are leaves */
opcode_rule = entry->opcode_rule;
@ -80,9 +82,6 @@ print_idecode_table(lf *file,
&& (opcode_rule->gen == switch_gen
|| opcode_rule->gen == padded_switch_gen))
opcode_rule = opcode_rule->next;
#if 0
/* FIXME: I don't get this bit! */
while (opcode_rule != NULL
&& (opcode_rule->gen == switch_gen
|| opcode_rule->gen == padded_switch_gen)
@ -189,6 +188,7 @@ print_idecode_table_leaf(insn_table *entry,
lf_printf(file, " },\n");
}
else if (entry->opcode_rule->gen == switch_gen
|| entry->opcode_rule->gen == goto_switch_gen
|| entry->opcode_rule->gen == padded_switch_gen) {
/* table calling switch statement */
lf_printf(file, " /*%d*/ { table_function_entry, 0, 0, 0, ",
@ -250,12 +250,89 @@ print_idecode_table_padding(insn_table *table,
/****************************************************************/
static void
print_goto_switch_name(lf *file,
insn_table *entry)
{
lf_printf(file, "case_");
if (entry->opcode == NULL)
print_function_name(file,
entry->insns->file_entry->fields[insn_name],
entry->expanded_bits,
((code & generate_with_icache)
? function_name_prefix_icache
: function_name_prefix_semantics));
else
lf_print_table_name(file, entry);
}
static void
print_goto_switch_table_leaf(insn_table *entry,
lf *file,
void *data,
insn *instruction,
int depth)
{
ASSERT(entry->parent != NULL);
ASSERT(depth == 0);
ASSERT(entry->parent->opcode_rule->gen == goto_switch_gen);
ASSERT(entry->parent->opcode);
lf_printf(file, "&&");
print_goto_switch_name(file, entry);
lf_printf(file, ",\n");
}
static void
print_goto_switch_table_padding(insn_table *table,
lf *file,
void *data,
int depth,
int opcode_nr)
{
ASSERT(depth == 0);
ASSERT(table->opcode_rule->gen == goto_switch_gen);
lf_printf(file, "&&illegal_");
lf_print_table_name(file, table);
lf_printf(file, ",\n");
}
static void
print_goto_switch_break(lf *file,
insn_table *entry)
{
lf_printf(file, "goto break_");
lf_print_table_name(file, entry->parent);
lf_printf(file, ";\n");
}
static void
print_goto_switch_table(lf *file,
insn_table *table)
{
lf_printf(file, "const static void *");
lf_print_table_name(file, table);
lf_printf(file, "[] = {\n");
lf_indent(file, +2);
insn_table_traverse_tree(table,
file, NULL/*data*/,
0,
NULL/*start*/,
print_goto_switch_table_leaf,
NULL/*end*/,
print_goto_switch_table_padding);
lf_indent(file, -2);
lf_printf(file, "};\n");
}
void print_idecode_switch
(lf *file,
insn_table *table,
const char *result);
static void
idecode_switch_start(insn_table *table,
lf *file,
@ -265,15 +342,39 @@ idecode_switch_start(insn_table *table,
/* const char *result = data; */
ASSERT(depth == 0);
ASSERT(table->opcode_rule->gen == switch_gen
|| table->opcode_rule->gen == padded_switch_gen
|| table->opcode_rule->gen == goto_gen);
|| table->opcode_rule->gen == goto_switch_gen
|| table->opcode_rule->gen == padded_switch_gen);
switch (table->opcode_rule->gen) {
default:
if (table->opcode->is_boolean
|| table->opcode_rule->gen == switch_gen
|| table->opcode_rule->gen == padded_switch_gen) {
lf_printf(file, "switch (EXTRACTED32(instruction, %d, %d)) {\n",
i2target(hi_bit_nr, table->opcode->first),
i2target(hi_bit_nr, table->opcode->last));
break;
}
else if (table->opcode_rule->gen == goto_switch_gen) {
if (table->parent != NULL
&& (table->parent->opcode_rule->gen == switch_gen
|| table->parent->opcode_rule->gen == goto_switch_gen
|| table->parent->opcode_rule->gen == padded_switch_gen)) {
lf_printf(file, "{\n");
lf_indent(file, +2);
}
print_goto_switch_table(file, table);
lf_printf(file, "ASSERT(EXTRACTED32(instruction, %d, %d)\n",
i2target(hi_bit_nr, table->opcode->first),
i2target(hi_bit_nr, table->opcode->last));
lf_printf(file, " < (sizeof(");
lf_print_table_name(file, table);
lf_printf(file, ") / sizeof(void*)));\n");
lf_printf(file, "goto *");
lf_print_table_name(file, table);
lf_printf(file, "[EXTRACTED32(instruction, %d, %d)];\n",
i2target(hi_bit_nr, table->opcode->first),
i2target(hi_bit_nr, table->opcode->last));
}
else {
ASSERT("bad switch" == NULL);
}
}
@ -289,16 +390,34 @@ idecode_switch_leaf(insn_table *entry,
ASSERT(entry->parent != NULL);
ASSERT(depth == 0);
ASSERT(entry->parent->opcode_rule->gen == switch_gen
|| entry->parent->opcode_rule->gen == goto_switch_gen
|| entry->parent->opcode_rule->gen == padded_switch_gen);
ASSERT(entry->parent->opcode);
if (entry->parent->opcode->is_boolean
&& entry->opcode_nr == 0)
&& entry->opcode_nr == 0) {
/* boolean false target */
lf_printf(file, "case %d:\n", entry->parent->opcode->boolean_constant);
else if (!entry->parent->opcode->is_boolean)
lf_printf(file, "case %d:\n", entry->opcode_nr);
else
}
else if (entry->parent->opcode->is_boolean
&& entry->opcode_nr != 0) {
/* boolean true case */
lf_printf(file, "default:\n");
}
else if (entry->parent->opcode_rule->gen == switch_gen
|| entry->parent->opcode_rule->gen == padded_switch_gen) {
/* normal goto */
lf_printf(file, "case %d:\n", entry->opcode_nr);
}
else if (entry->parent->opcode_rule->gen == goto_switch_gen) {
/* lf_indent(file, -1); */
print_goto_switch_name(file, entry);
lf_printf(file, ":\n");
/* lf_indent(file, +1); */
}
else {
ASSERT("bad switch" == NULL);
}
lf_indent(file, +2);
{
if (entry->opcode == NULL) {
@ -318,6 +437,7 @@ idecode_switch_leaf(insn_table *entry,
lf_printf(file, ";\n");
}
else if (entry->opcode_rule->gen == switch_gen
|| entry->opcode_rule->gen == goto_switch_gen
|| entry->opcode_rule->gen == padded_switch_gen) {
/* switch calling switch */
print_idecode_switch(file, entry, result);
@ -330,7 +450,17 @@ idecode_switch_leaf(insn_table *entry,
lf_indent(file, -2);
lf_printf(file, "}\n");
}
lf_printf(file, "break;\n");
if (entry->parent->opcode->is_boolean
|| entry->parent->opcode_rule->gen == switch_gen
|| entry->parent->opcode_rule->gen == padded_switch_gen) {
lf_printf(file, "break;\n");
}
else if (entry->parent->opcode_rule->gen == goto_switch_gen) {
print_goto_switch_break(file, entry);
}
else {
ASSERT("bad switch" == NULL);
}
}
lf_indent(file, -2);
}
@ -342,7 +472,7 @@ print_idecode_switch_illegal(lf *file,
{
lf_indent(file, +2);
print_idecode_illegal(file, result);
/*lf_printf(file, "break;\n");*/
lf_printf(file, "break;\n");
lf_indent(file, -2);
}
@ -355,11 +485,15 @@ idecode_switch_end(insn_table *table,
const char *result = data;
ASSERT(depth == 0);
ASSERT(table->opcode_rule->gen == switch_gen
|| table->opcode_rule->gen == padded_switch_gen
|| table->opcode_rule->gen == goto_gen);
|| table->opcode_rule->gen == goto_switch_gen
|| table->opcode_rule->gen == padded_switch_gen);
ASSERT(table->opcode);
if (!table->opcode->is_boolean) {
if (table->opcode->is_boolean) {
lf_printf(file, "}\n");
}
else if (table->opcode_rule->gen == switch_gen
|| table->opcode_rule->gen == padded_switch_gen) {
lf_printf(file, "default:\n");
switch (table->opcode_rule->gen) {
case switch_gen:
@ -370,10 +504,29 @@ idecode_switch_end(insn_table *table,
lf_printf(file, " break;\n");
break;
default:
error("idecode_switch_end - unknown switch type\n");
ASSERT("bad switch" == NULL);
}
lf_printf(file, "}\n");
}
else if (table->opcode_rule->gen == goto_switch_gen) {
lf_printf(file, "illegal_");
lf_print_table_name(file, table);
lf_printf(file, ":\n");
print_idecode_illegal(file, result);
lf_printf(file, "break_");
lf_print_table_name(file, table);
lf_printf(file, ":;\n");
if (table->parent != NULL
&& (table->parent->opcode_rule->gen == switch_gen
|| table->parent->opcode_rule->gen == goto_switch_gen
|| table->parent->opcode_rule->gen == padded_switch_gen)) {
lf_indent(file, -2);
lf_printf(file, "}\n");
}
}
lf_printf(file, "}\n");
else {
ASSERT("bad switch" == NULL);
}
}
static void
@ -386,15 +539,21 @@ idecode_switch_padding(insn_table *table,
const char *result = data;
ASSERT(depth == 0);
ASSERT(table->opcode_rule->gen == switch_gen
|| table->opcode_rule->gen == goto_switch_gen
|| table->opcode_rule->gen == padded_switch_gen);
if (table->opcode_rule->gen == padded_switch_gen) {
switch (table->opcode_rule->gen) {
case switch_gen:
break;
case padded_switch_gen:
lf_printf(file, "case %d:\n", opcode_nr);
print_idecode_switch_illegal(file, result);
}
else if (table->opcode_rule->gen == goto_gen) {
lf_printf(file, "goto_%d:\n", opcode_nr);
print_idecode_switch_illegal(file, result);
break;
case goto_switch_gen:
/* no padding needed */
break;
default:
ASSERT("bad switch" != NULL);
}
}
@ -452,12 +611,13 @@ idecode_declare_if_switch(insn_table *table,
int depth)
{
if ((table->opcode_rule->gen == switch_gen
|| table->opcode_rule->gen == goto_switch_gen
|| table->opcode_rule->gen == padded_switch_gen)
&& table->parent != NULL /* don't declare the top one yet */
&& table->parent->opcode_rule->gen == array_gen) {
print_idecode_switch_function_header(file,
table,
0/*isnt function definition*/);
table,
0/*isnt function definition*/);
}
}
@ -469,6 +629,7 @@ idecode_expand_if_switch(insn_table *table,
int depth)
{
if ((table->opcode_rule->gen == switch_gen
|| table->opcode_rule->gen == goto_switch_gen
|| table->opcode_rule->gen == padded_switch_gen)
&& table->parent != NULL /* don't expand the top one yet */
&& table->parent->opcode_rule->gen == array_gen) {
@ -537,6 +698,7 @@ print_idecode_body(lf *file,
lf_putstr(file, "{\n");
lf_indent(file, +2);
if (table->opcode_rule->gen == switch_gen
|| table->opcode_rule->gen == goto_switch_gen
|| table->opcode_rule->gen == padded_switch_gen)
print_idecode_switch(file, table, result);
else
@ -565,8 +727,6 @@ print_run_until_stop_body(lf *file,
lf_putstr(file, "{\n");
lf_indent(file, +2);
if (!can_stop)
lf_putstr(file, "int *keep_running = NULL;\n");
lf_putstr(file, "jmp_buf halt;\n");
lf_putstr(file, "jmp_buf restart;\n");
lf_putstr(file, "cpu *processor = NULL;\n");
@ -630,6 +790,11 @@ print_run_until_stop_body(lf *file,
if (!(code & generate_with_icache)) {
lf_putstr(file, "instruction = vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
print_idecode_body(file, table, "cia =", "");
/* tail */
if (can_stop) {
lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
lf_putstr(file, " cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n");
}
}
if ((code & generate_with_icache)) {
@ -638,6 +803,12 @@ print_run_until_stop_body(lf *file,
lf_putstr(file, " /* cache hit */\n");
lf_putstr(file, " idecode_semantic *const semantic = cache_entry->semantic;\n");
lf_putstr(file, " cia = semantic(processor, cache_entry, cia);\n");
/* tail */
if (can_stop) {
lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
lf_putstr(file, " cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n");
}
lf_putstr(file, " continue;\n");
lf_putstr(file, "}\n");
lf_putstr(file, "else {\n");
lf_putstr(file, " /* cache miss */\n");
@ -656,11 +827,15 @@ print_run_until_stop_body(lf *file,
print_idecode_body(file, table, "semantic =", " ");
lf_putstr(file, " cia = semantic(processor, cache_entry, cia);\n");
}
/* tail */
if (can_stop) {
lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
lf_putstr(file, " cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n");
}
lf_putstr(file, " continue;\n");
lf_putstr(file, "}\n");
}
lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
lf_putstr(file, " cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n");
lf_indent(file, -2);
lf_putstr(file, "}\n");
}
@ -698,41 +873,63 @@ print_run_until_stop_body(lf *file,
if (!(code & generate_with_icache)) {
lf_putstr(file, "instruction = vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
print_idecode_body(file, table, "cia =", "");
if (can_stop) {
lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
lf_putstr(file, " cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n");
}
lf_putstr(file, "cpu_set_program_counter(processor, cia);\n");
lf_putstr(file, "continue;\n");
}
if ((code & generate_with_icache)) {
lf_putstr(file, "cache_entry = cpu_icache_entry(processor, cia);\n");
lf_putstr(file, "if (cache_entry->address == cia) {\n");
lf_putstr(file, " /* cache hit */\n");
lf_putstr(file, " idecode_semantic *semantic = cache_entry->semantic;\n");
lf_putstr(file, " cia = semantic(processor, cache_entry, cia);\n");
lf_putstr(file, "}\n");
lf_putstr(file, "else {\n");
lf_putstr(file, " /* cache miss */\n");
if (!(code & generate_with_semantic_icache)) {
{
lf_indent(file, +2);
lf_putstr(file, " idecode_semantic *semantic;\n");
lf_putstr(file, "/* cache hit */\n");
lf_putstr(file, "idecode_semantic *semantic = cache_entry->semantic;\n");
lf_putstr(file, "cia = semantic(processor, cache_entry, cia);\n");
/* tail */
if (can_stop) {
lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
lf_putstr(file, " cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n");
}
lf_putstr(file, "cpu_set_program_counter(processor, cia);\n");
lf_putstr(file, "continue;\n");
lf_indent(file, -2);
}
lf_putstr(file, " instruction =\n");
lf_putstr(file, " vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
lf_putstr(file, " if (WITH_MON != 0)\n");
lf_putstr(file, " mon_event(mon_event_icache_miss, processors[current_cpu], cia);\n");
if ((code & generate_with_semantic_icache)) {
print_idecode_body(file, table, "cia =", " ");
}
else {
print_idecode_body(file, table, "semantic = ", " ");
lf_putstr(file, "}\n");
lf_putstr(file, "else {\n");
{
lf_indent(file, +2);
lf_putstr(file, "cia = semantic(processor, cache_entry, cia));\n");
lf_putstr(file, "/* cache miss */\n");
if (!(code & generate_with_semantic_icache)) {
lf_putstr(file, "idecode_semantic *semantic;\n");
}
lf_putstr(file, "instruction =\n");
lf_putstr(file, " vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
lf_putstr(file, "if (WITH_MON != 0)\n");
lf_putstr(file, " mon_event(mon_event_icache_miss, processors[current_cpu], cia);\n");
if ((code & generate_with_semantic_icache)) {
print_idecode_body(file, table, "cia =", "");
}
else {
print_idecode_body(file, table, "semantic = ", " ");
lf_putstr(file, "cia = semantic(processor, cache_entry, cia);\n");
}
/* tail */
if (can_stop) {
lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
lf_putstr(file, " cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n");
}
lf_putstr(file, "cpu_set_program_counter(processor, cia);\n");
lf_putstr(file, "continue;\n");
lf_indent(file, -2);
}
lf_putstr(file, "}\n");
}
lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
lf_putstr(file, " cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n");
lf_putstr(file, "cpu_set_program_counter(processor, cia);\n");
/* tail */
lf_indent(file, -2);
lf_putstr(file, "}\n");
}
@ -765,10 +962,11 @@ print_jump(lf *file,
}
if (generate_smp) {
lf_putstr(file, "cpu_set_program_counter(processor, nia);\n");
if (is_tail)
lf_putstr(file, "cpu_set_program_counter(processor, nia);\n");
lf_putstr(file, "if (WITH_EVENTS) {\n");
lf_putstr(file, " current_cpu += 1;\n");
lf_putstr(file, " if (current_cpu == nr_cpus) {\n");
lf_putstr(file, " if (current_cpu >= nr_cpus) {\n");
lf_putstr(file, " if (event_queue_tick(events)) {\n");
lf_putstr(file, " event_queue_process(events);\n");
lf_putstr(file, " }\n");
@ -793,7 +991,7 @@ print_jump(lf *file,
}
}
if (!(code & generate_with_icache)) {
if (!(code & generate_with_icache) && is_tail) {
lf_printf(file, "goto idecode;\n");
}
@ -813,7 +1011,7 @@ print_jump_insn(lf *file,
/* what we are for the moment */
lf_printf(file, "\n");
print_define_my_index(file, instruction->file_entry);
print_my_defines(file, expanded_bits, instruction->file_entry);
/* output the icache entry */
if ((code & generate_with_icache)) {
@ -837,9 +1035,8 @@ print_jump_insn(lf *file,
instruction,
expanded_bits,
cache_rules,
0,
0/*get_value_from_cache*/,
1/*put_value_in_cache*/);
0, /*use_defines*/
put_values_in_icache);
lf_printf(file, "cache_entry->address = nia;\n");
lf_printf(file, "cache_entry->semantic = &&");
print_function_name(file,
@ -884,13 +1081,25 @@ print_jump_insn(lf *file,
instruction,
expanded_bits,
cache_rules,
(code & generate_with_direct_access_icache),
(code & generate_with_icache)/*get_value_from_cache*/,
0/*put_value_in_cache*/);
((code & generate_with_direct_access)
? define_variables
: declare_variables),
((code & generate_with_icache)
? get_values_from_icache
: do_not_use_icache));
print_semantic_body(file,
instruction,
expanded_bits,
opcodes);
if (code & generate_with_direct_access)
print_icache_body(file,
instruction,
expanded_bits,
cache_rules,
undef_variables,
((code & generate_with_icache)
? get_values_from_icache
: do_not_use_icache));
print_jump(file, 1/*is tail*/);
lf_indent(file, -2);
lf_printf(file, "}\n");

View File

@ -48,7 +48,7 @@ int insn_bit_size = max_insn_bit_size;
igen_code code = generate_calls;
int generate_expanded_instructions;
int icache_size;
int icache_size = 1024;
int generate_smp;
/****************************************************************/
@ -127,9 +127,11 @@ print_function_name(lf *file,
void
print_define_my_index(lf *file,
table_entry *file_entry)
print_my_defines(lf *file,
insn_bits *expanded_bits,
table_entry *file_entry)
{
/* #define MY_INDEX xxxxx */
lf_indent_suppress(file);
lf_printf(file, "#undef MY_INDEX\n");
lf_indent_suppress(file);
@ -139,6 +141,16 @@ print_define_my_index(lf *file,
NULL,
function_name_prefix_itable);
lf_printf(file, "\n");
/* #define MY_PREFIX xxxxxx */
lf_indent_suppress(file);
lf_printf(file, "#undef MY_PREFIX\n");
lf_indent_suppress(file);
lf_printf(file, "#define MY_PREFIX ");
print_function_name(file,
file_entry->fields[insn_name],
expanded_bits,
function_name_prefix_none);
lf_printf(file, "\n");
}
@ -321,9 +333,10 @@ main(int argc,
printf(" igen <config-opts> ... <input-opts>... <output-opts>...\n");
printf("Config options:\n");
printf(" -F <filter-out-flag> eg -F 64 to skip 64bit instructions\n");
printf(" -C Include semantics in cache functions\n");
printf(" -E Expand (duplicate) semantic functions\n");
printf(" -I <icache-size> Generate cracking cache version\n");
printf(" -C Include semantics in cache functions\n");
printf(" -S Include insn (instruction) in icache\n");
printf(" -R Use defines to reference cache vars\n");
printf(" -L Supress line numbering in output files\n");
printf(" -B <bit-size> Set the number of bits in an instruction\n");
@ -348,15 +361,17 @@ main(int argc,
}
while ((ch = getopt(argc, argv,
"F:EI:RLJCB:H:N:o:k:i:n:hc:d:m:s:t:f:"))
"F:EI:RSLJCB:H:N:o:k:i:n:hc:d:m:s:t:f:"))
!= -1) {
fprintf(stderr, "\t-%c %s\n", ch, (optarg ? optarg : ""));
switch(ch) {
case 'C':
code |= generate_with_icache;
code |= generate_with_semantic_icache;
if (icache_size == 0)
icache_size = 1024;
break;
case 'S':
code |= generate_with_icache;
code |= generate_with_insn_in_icache;
break;
case 'L':
file_references = lf_omit_references;
@ -372,10 +387,7 @@ main(int argc,
generate_smp = a2i(optarg);
break;
case 'R':
code |= generate_with_icache;
code |= generate_with_direct_access_icache;
if (icache_size == 0)
icache_size = 1024;
code |= generate_with_direct_access;
break;
case 'B':
insn_bit_size = a2i(optarg);

View File

@ -43,6 +43,8 @@
#endif
#endif
#include <errno.h>
#if !defined(O_NDELAY) || !defined(F_GETFL) || !defined(F_SETFL)
#undef WITH_STDIO
#define WITH_STDIO DO_USE_STDIO
@ -69,6 +71,7 @@ error (char *msg, ...)
va_list ap;
va_start(ap, msg);
vprintf(msg, ap);
printf("\n");
va_end(ap);
/* any final clean up */
@ -98,6 +101,7 @@ sim_io_write_stdout(const char *buf,
default:
error("sim_io_write_stdout: invalid switch\n");
}
return 0;
}
int
@ -120,6 +124,7 @@ sim_io_write_stderr(const char *buf,
default:
error("sim_io_write_stdout: invalid switch\n");
}
return 0;
}
int
@ -128,10 +133,20 @@ sim_io_read_stdin(char *buf,
{
switch (CURRENT_STDIO) {
case DO_USE_STDIO:
if (fgets(buf, sizeof_buf, stdin) == NULL)
return sim_io_eof;
else
return strlen(buf);
if (sizeof_buf > 1) {
if (fgets(buf, sizeof_buf, stdin) != NULL)
return strlen(buf);
}
else if (sizeof_buf == 1) {
char b[2];
if (fgets(b, sizeof(b), stdin) != NULL) {
memcpy(buf, b, strlen(b));
return strlen(b);
}
}
else if (sizeof_buf == 0)
return 0;
return sim_io_eof;
break;
case DONT_USE_STDIO:
{
@ -139,6 +154,7 @@ sim_io_read_stdin(char *buf,
int flags;
int status;
int nr_read;
int result;
/* get the old status */
flags = fcntl(0, F_GETFL, 0);
if (flags == -1) {
@ -152,25 +168,32 @@ sim_io_read_stdin(char *buf,
return sim_io_eof;
}
/* try for input */
nr_read = read(0, &buf, sizeof_buf);
nr_read = read(0, buf, sizeof_buf);
if (nr_read > 0
|| (nr_read == 0 && sizeof_buf == 0))
result = nr_read;
else if (nr_read == 0)
result = sim_io_eof;
else { /* nr_read < 0 */
if (errno == EAGAIN)
result = sim_io_not_ready;
else
result = sim_io_eof;
}
/* return to regular vewing */
status = fcntl(0, F_SETFL, flags);
if (status == -1) {
perror("sim_io_read_stdin");
return sim_io_eof;
}
if (status > 0)
return 1;
else if (status < 0)
return sim_io_eof;
else
return sim_io_not_ready;
return result;
}
break;
default:
error("sim_io_read_stdin: invalid switch\n");
break;
}
return 0;
}
void
@ -215,8 +238,14 @@ main(int argc, char **argv)
/* parse the arguments */
argv = psim_options(root, argv + 1);
if (argv[0] == NULL)
psim_usage(0);
if (argv[0] == NULL) {
if (ppc_trace[trace_opts]) {
print_options ();
return 0;
} else {
psim_usage(0);
}
}
name_of_file = argv[0];
if (ppc_trace[trace_opts])

View File

@ -20,6 +20,7 @@
cache:RA:RA::
cache:RA:rA:signed_word *:(cpu_registers(processor)->gpr + RA)
cache:RA:RA_BITMASK:unsigned32:(1 << RA)
compute:RA:RA_is_0:int:(RA == 0)
cache:RT:RT::
cache:RT:rT:signed_word *:(cpu_registers(processor)->gpr + RT)
cache:RT:RT_BITMASK:unsigned32:(1 << RT)
@ -29,30 +30,30 @@ cache:RS:RS_BITMASK:unsigned32:(1 << RS)
cache:RB:RB::
cache:RB:rB:signed_word *:(cpu_registers(processor)->gpr + RB)
cache:RB:RB_BITMASK:unsigned32:(1 << RB)
compute:FRA:FRA::
scratch:FRA:FRA::
cache:FRA:frA:unsigned64 *:(cpu_registers(processor)->fpr + FRA)
cache:FRA:FRA_BITMASK:unsigned32:(1 << FRA)
compute:FRB:FRB::
scratch:FRB:FRB::
cache:FRB:frB:unsigned64 *:(cpu_registers(processor)->fpr + FRB)
cache:FRB:FRB_BITMASK:unsigned32:(1 << FRB)
compute:FRC:FRC::
scratch:FRC:FRC::
cache:FRC:frC:unsigned64 *:(cpu_registers(processor)->fpr + FRC)
cache:FRC:FRC_BITMASK:unsigned32:(1 << FRC)
compute:FRS:FRS::
scratch:FRS:FRS::
cache:FRS:frS:unsigned64 *:(cpu_registers(processor)->fpr + FRS)
cache:FRS:FRS_BITMASK:unsigned32:(1 << FRS)
compute:FRT:FRT::
scratch:FRT:FRT::
cache:FRT:frT:unsigned64 *:(cpu_registers(processor)->fpr + FRT)
cache:FRT:FRT_BITMASK:unsigned32:(1 << FRT)
cache:SI:EXTS_SI:unsigned_word:((signed_word)(signed16)instruction)
compute:BI:BI::
scratch:BI:BI::
cache:BI:BIT32_BI::BIT32(BI)
cache:BF:BF::
cache:BF:BF_BITMASK:unsigned32:(1 << BF)
compute:BA:BA::
scratch:BA:BA::
cache:BA:BIT32_BA::BIT32(BA)
cache:BA:BA_BITMASK:unsigned32:(1 << BA)
compute:BB:BB::
scratch:BB:BB::
cache:BB:BIT32_BB::BIT32(BB)
cache:BB:BB_BITMASK:unsigned32:(1 << BB)
cache:BT:BT::
@ -61,3 +62,4 @@ cache:BD:EXTS_BD_0b00:unsigned_word:(((signed_word)(signed16)instruction) & ~3)
cache:LI:EXTS_LI_0b00:unsigned_word:((((signed_word)(signed32)(instruction << 6)) >> 6) & ~0x3)
cache:D:EXTS_D:unsigned_word:((signed_word)(signed16)(instruction))
cache:DS:EXTS_DS_0b00:unsigned_word:(((signed_word)(signed16)instruction) & ~0x3)
#compute:SPR:SPR_is_256:int:(SPR == 256)

View File

@ -1109,18 +1109,14 @@ void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64
int rbit = 0;
int xbit = 0;
int sign = EXTRACTED64(frb, 0, 0);
enum { start, finish, Infinity_Operand, SNaN_Operand, QNaN_Operand, Large_Operand, Done } label = start;
while (label != finish) switch (label) {
case finish:
error("Unhandled switch\n");
case start:
/***/
if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 63) == 0)
{ label = Infinity_Operand; break; }
GOTO(Infinity_Operand);
if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 0)
{ label = SNaN_Operand; break; }
GOTO(SNaN_Operand);
if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 1)
{ label = QNaN_Operand; break; }
if (EXTRACTED64(frb, 1, 11) > 1086) { label = Large_Operand; break; }
GOTO(QNaN_Operand);
if (EXTRACTED64(frb, 1, 11) > 1086) GOTO(Large_Operand);
if (EXTRACTED64(frb, 1, 11) > 0) exp = EXTRACTED64(frb, 1, 11) - 1023;
if (EXTRACTED64(frb, 1, 11) == 0) exp = -1022;
if (EXTRACTED64(frb, 1, 11) > 0) { /* normal */
@ -1148,25 +1144,25 @@ void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64
}
if (tgt_precision == 32 /* can ignore frac64 in compare */
&& (signed64)frac > (signed64)MASK64(33+1, 63)/*2^31-1 >>1*/)
{ label = Large_Operand; break; }
GOTO(Large_Operand);
if (tgt_precision == 64 /* can ignore frac64 in compare */
&& (signed64)frac > (signed64)MASK64(1+1, 63)/*2^63-1 >>1*/)
{ label = Large_Operand; break; }
GOTO(Large_Operand);
if (tgt_precision == 32 /* can ignore frac64 in compare */
&& (signed64)frac < (signed64)MASK64(0, 32+1)/*-2^31 >>1*/)
{ label = Large_Operand; break; }
GOTO(Large_Operand);
if (tgt_precision == 64 /* can ignore frac64 in compare */
&& (signed64)frac < (signed64)MASK64(0, 0+1)/*-2^63 >>1*/)
{ label = Large_Operand; break; }
GOTO(Large_Operand);
FPSCR_SET_XX(FPSCR & fpscr_fi);
if (tgt_precision == 32)
*frt = MASKED64(*frt, 0, 31) | (EXTRACTED64(frac, 33, 63) << 1) | frac64;
if (tgt_precision == 64)
*frt = (EXTRACTED64(frac, 1, 63) << 1) | frac64;
/*FPSCR[fprf] = undefined */
{ label = Done; break; }
GOTO(Done);
/**/
case Infinity_Operand:
LABEL(Infinity_Operand):
FPSCR_SET_FR(0);
FPSCR_SET_FI(0);
FPSCR_OR_VX(fpscr_vxcvi);
@ -1181,9 +1177,9 @@ void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64
}
/* FPSCR[FPRF] = undefined */
}
{ label = Done; break; }
GOTO(Done);
/**/
case SNaN_Operand:
LABEL(SNaN_Operand):
FPSCR_SET_FR(0);
FPSCR_SET_FI(0);
FPSCR_OR_VX(fpscr_vxsnan | fpscr_vxcvi);
@ -1192,9 +1188,9 @@ void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64
if (tgt_precision == 64) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
/* FPSCR[fprf] = undefined */
}
{ label = Done; break; }
GOTO(Done);
/**/
case QNaN_Operand:
LABEL(QNaN_Operand):
FPSCR_SET_FR(0);
FPSCR_SET_FI(0);
FPSCR_OR_VX(fpscr_vxcvi);
@ -1203,9 +1199,9 @@ void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64
if (tgt_precision == 64) *frt = BIT64(0);/*0x8000_0000_0000_0000*/
/* FPSCR[fprf] = undefined */
}
{ label = Done; break; }
GOTO(Done);
/**/
case Large_Operand:
LABEL(Large_Operand):
FPSCR_SET_FR(0);
FPSCR_SET_FI(0);
FPSCR_OR_VX(fpscr_vxcvi);
@ -1221,9 +1217,7 @@ void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64
/* FPSCR[fprf] = undefined */
}
/**/
case Done:
{ label = finish; break; }
}
LABEL(Done):
# extract out raw fields of a FP number
@ -2126,8 +2120,40 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
#
0.46,6.RT,11.RA,16.D:D:::Load Multiple Word
unsigned_word EA;
unsigned_word b;
int r;
if (RA == 0) b = 0;
else b = *rA;
EA = b + EXTS(D);
r = RT;
if (RA >= r)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT || (EA % 4 != 0))
alignment_interrupt(processor, cia, EA);
while (r <= 31) {
GPR(r) = MEM(unsigned, EA, 4);
r = r + 1;
EA = EA + 4;
}
0.47,6.RS,11.RA,16.D:D:::Store Multiple Word
unsigned_word EA;
unsigned_word b;
int r;
if (RA == 0) b = 0;
else b = *rA;
EA = b + EXTS(D);
if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT
|| (EA % 4 != 0))
alignment_interrupt(processor, cia, EA);
r = RS;
while (r <= 31) {
STORE(EA, 4, GPR(r));
r = r + 1;
EA = EA + 4;
}
#
@ -2135,12 +2161,116 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
#
0.31,6.RT,11.RA,16.NB,21.597,31./:X:::Load String Word Immediate
# unsigned_word EA;
# int n;
# int r;
# int i;
# int nr;
# if (RA == 0) EA = 0;
# else EA = *rA;
# if (NB == 0) n = 32;
# else n = NB;
# r = RT - 1;
# i = 32;
# nr = (n + 3) / 4;
# if ((RT + nr >= 32)
# ? (RA >= RT && RA < RT + nr)
# : (RA >= RT || RA < (RT + nr) % 32))
# program_interrupt(processor, cia,
# illegal_instruction_program_interrupt);
# if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
# alignment_interrupt(processor, cia, EA);
# while (n > 0) {
# if (i == 32) {
# r = (r + 1) % 32;
# GPR(r) = 0;
# }
# GPR(r) |= INSERTED(MEM(unsigned, EA, 1), i, i+7);
# if (i == 64) i = 32;
# EA = EA + 1;
# n = n - 1;
# }
0.31,6.RT,11.RA,16.RB,21.533,31./:X:::Load String Word Indexed
# unsigned_word EA;
# unsigned_word b;
# int n;
# int r;
# int i;
# int nr;
# if (RA == 0) b = 0;
# else b = *rA;
# EA = b + *rB;
# n = EXTRACTED32(XER, 25, 31);
# r = RT - 1;
# i = 32;
# nr = (n + 3) / 4;
# if (((RT + n >= 32)
# ? ((RA >= RT && RA < RT + n)
# || (RB >= RT && RB < RT + n))
# : ((RA >= RT || RA < (RT + n) % 32)
# || (RB >= RT || RB < (RT + n) % 32)))
# || (RT == RA || RT == RB))
# program_interrupt(processor, cia,
# illegal_instruction_program_interrupt);
# if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
# alignment_interrupt(processor, cia, EA);
# while (n > 0) {
# if (i == 32) {
# r = (r + 1) % 32;
# GPR(i) = 0;
# }
# GPR(r) |= INSERTED(MEM(unsigned, EA, 1), i, i+7);
# i = i + 8;
# if (i == 64) i = 32;
# EA = EA + 1;
# n = n - 1;
# }
0.31,6.RS,11.RA,16.NB,21.725,31./:X:::Store String Word Immedate
# unsigned_word EA;
# int n;
# int r;
# int i;
# if (RA == 0) EA = 0;
# else EA = *rA;
# if (NB == 0) n = 32;
# else n = NB;
# r = RS - 1;
# i = 32;
# if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
# alignment_interrupt(processor, cia, EA);
# while (n > 0) {
# if (i == 32) r = (r + 1) % 32;
# STORE(EA, 1, EXTRACTED(GPR(r), i, i+7));
# i = i + 8;
# if (i == 64) i = 32;
# EA = EA + 1;
# n = n - 1;
# }
0.31,6.RS,11.RA,16.RB,21.661,31./:X:::Store String Word Indexed
# unsigned_word EA;
# unsigned_word b;
# int n;
# int r;
# int i;
# if (RA == 0) b = 0;
# else b = *rA;
# EA = b + *rB;
# if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
# alignment_interrupt(processor, cia, EA);
# n = EXTRACTED32(XER, 25, 31);
# r = RS - 1;
# i = 32;
# while (n > 0) {
# if (i == 32) r = (r + 1) % 32;
# STORE(EA, 1, EXTRACTED(GPR(r), i, i+7));
# i = i + 8;
# if (i == 64) i = 32;
# EA = EA + 1;
# n = n - 1;
# }
#
@ -2944,12 +3074,12 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
# CR0_COMPARE(result, 0, Rc);
0.23,6.RS,11.RA,16.RB,21.MB,26.ME,31.Rc:M:::Rotate Left Word then AND with Mask
# long n = MASKED(*rB, 59, 63);
# unsigned32 r = ROTL32(*rS, n);
# unsigned32 m = MASK(MB+32, ME+32);
# signed_word result = r & m;
# *rA = result;
# CR0_COMPARE(result, 0, Rc);
long n = MASKED(*rB, 59, 63);
unsigned32 r = ROTL32(*rS, n);
unsigned32 m = MASK(MB+32, ME+32);
signed_word result = r & m;
*rA = result;
CR0_COMPARE(result, 0, Rc);
0.30,6.RS,11.RA,16.sh_0_4,21.mb,27.3,30.sh_5,31.Rc:MD:64::Rotate Left Doubleword Immediate then Mask Insert
# long n = (sh_5 << 4) | sh_0_4;
@ -3124,8 +3254,23 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
else {
/* HACK - some SPR's need to get their value extracted specially */
*rT = SPREG(n);
/* HACK - time base registers need to be calculated */
if (WITH_TIME_BASE) {
switch (n) {
case spr_dec:
*rT = cpu_get_decrementer(processor);
break;
case spr_tbu:
case spr_tbl:
/* NOTE - these SPR's are not readable. Use mftb[ul] */
default:
*rT = SPREG(n);
break;
}
}
else {
*rT = SPREG(n);
}
}
PPC_INSN_FROM_SPR(RT_BITMASK, n);
@ -3149,6 +3294,8 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
PPC_INSN_MTCR(RS_BITMASK, FXM);
0.31,6.BF,9./,11./,16./,21.512,31./:X:::Move to Condition Register from XER
# CR_SET(BF, EXTRACTED32(XER, 0, 3));
# MBLIT32(XER, 0, 3, 0);
0.31,6.RT,11./,16./,21.19,31./:X:::Move From Condition Register
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
@ -4010,32 +4157,29 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
int sign;
int exp;
unsigned64 frac_grx;
enum { start, finish, Disabled_Exponent_Underflow, Enabled_Exponent_Underflow, Disabled_Exponent_Overflow, Enabled_Exponent_Overflow, Normal_Operand, Zero_Operand, Infinity_Operand, QNaN_Operand, SNaN_Operand, Enabled_Overflow, Done } label = start;
while (label != finish) switch (label) {
case finish:
error("Unhandled switch\n");
case start:
/***/
/* split off cases for what to do */
if (EXTRACTED64(*frB, 1, 11) < 897
&& EXTRACTED64(*frB, 1, 63) > 0) {
if ((FPSCR & fpscr_ue) == 0) { label = Disabled_Exponent_Underflow; break; }
if ((FPSCR & fpscr_ue) != 0) { label = Enabled_Exponent_Underflow; break; }
if ((FPSCR & fpscr_ue) == 0) GOTO(Disabled_Exponent_Underflow);
if ((FPSCR & fpscr_ue) != 0) GOTO(Enabled_Exponent_Underflow);
}
if (EXTRACTED64(*frB, 1, 11) > 1150
&& EXTRACTED64(*frB, 1, 11) < 2047) {
if ((FPSCR & fpscr_oe) == 0) { label = Disabled_Exponent_Overflow; break; }
if ((FPSCR & fpscr_oe) != 0) { label = Enabled_Exponent_Overflow; break; }
if ((FPSCR & fpscr_oe) == 0) GOTO(Disabled_Exponent_Overflow);
if ((FPSCR & fpscr_oe) != 0) GOTO(Enabled_Exponent_Overflow);
}
if (EXTRACTED64(*frB, 1, 11) > 896
&& EXTRACTED64(*frB, 1, 11) < 1151) { label = Normal_Operand; break; }
if (EXTRACTED64(*frB, 1, 63) == 0) { label = Zero_Operand; break; }
&& EXTRACTED64(*frB, 1, 11) < 1151) GOTO(Normal_Operand);
if (EXTRACTED64(*frB, 1, 63) == 0) GOTO(Zero_Operand);
if (EXTRACTED64(*frB, 1, 11) == 2047) {
if (EXTRACTED64(*frB, 12, 63) == 0) { label = Infinity_Operand; break; }
if (EXTRACTED64(*frB, 12, 12) == 1) { label = QNaN_Operand; break; }
if (EXTRACTED64(*frB, 12, 63) == 0) GOTO(Infinity_Operand);
if (EXTRACTED64(*frB, 12, 12) == 1) GOTO(QNaN_Operand);
if (EXTRACTED64(*frB, 12, 12) == 0
&& EXTRACTED64(*frB, 13, 63) > 0) { label = SNaN_Operand; break; }
&& EXTRACTED64(*frB, 13, 63) > 0) GOTO(SNaN_Operand);
}
case Disabled_Exponent_Underflow:
/**/
LABEL(Disabled_Exponent_Underflow):
sign = EXTRACTED64(*frB, 0, 0);
if (EXTRACTED64(*frB, 1, 11) == 0) {
exp = -1022;
@ -4077,8 +4221,9 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
| INSERTED64(exp + 1023, 1, 11)
| INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
}
{ label = Done; break; }
case Enabled_Exponent_Underflow:
GOTO(Done);
/**/
LABEL(Enabled_Exponent_Underflow):
FPSCR_SET_UX(1);
sign = EXTRACTED64(*frB, 0, 0);
if (EXTRACTED64(*frB, 1, 11) == 0) {
@ -4103,8 +4248,9 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
| INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
{ label = Done; break; }
case Disabled_Exponent_Overflow:
GOTO(Done);
/**/
LABEL(Disabled_Exponent_Overflow):
FPSCR_SET_OX(1);
if ((FPSCR & fpscr_rn) == fpscr_rn_round_to_nearest) {
if (EXTRACTED64(*frB, 0, 0) == 0) {
@ -4149,14 +4295,16 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
/* FPSCR[FR] <- undefined */
FPSCR_SET_FI(1);
FPSCR_SET_XX(1);
{ label = Done; break; }
case Enabled_Exponent_Overflow:
GOTO(Done);
/**/
LABEL(Enabled_Exponent_Overflow):
sign = EXTRACTED64(*frB, 0, 0);
exp = EXTRACTED64(*frB, 1, 11) - 1023;
frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
Round_Single(processor, sign, &exp, &frac_grx);
FPSCR_SET_XX(FPSCR & fpscr_fi);
case Enabled_Overflow:
/**/
LABEL(Enabled_Overflow):
FPSCR_SET_OX(1);
exp = exp - 192;
*frT = (INSERTED64(sign, 0, 0)
@ -4164,28 +4312,32 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
| INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
{ label = Done; break; }
case Zero_Operand:
GOTO(Done);
/**/
LABEL(Zero_Operand):
*frT = *frB;
if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero);
if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero);
FPSCR_SET_FR(0);
FPSCR_SET_FI(0);
{ label = Done; break; }
case Infinity_Operand:
GOTO(Done);
/**/
LABEL(Infinity_Operand):
*frT = *frB;
if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
FPSCR_SET_FR(0);
FPSCR_SET_FI(0);
{ label = Done; break; }
case QNaN_Operand:
GOTO(Done);
/**/
LABEL(QNaN_Operand):
*frT = INSERTED64(EXTRACTED64(*frB, 0, 34), 0, 34);
FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
FPSCR_SET_FR(0);
FPSCR_SET_FI(0);
{ label = Done; break; }
case SNaN_Operand:
GOTO(Done);
/**/
LABEL(SNaN_Operand):
FPSCR_OR_VX(fpscr_vxsnan);
if ((FPSCR & fpscr_ve) == 0) {
*frT = (MASKED64(*frB, 0, 11)
@ -4195,31 +4347,35 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
}
FPSCR_SET_FR(0);
FPSCR_SET_FI(0);
{ label = Done; break; }
case Normal_Operand:
GOTO(Done);
/**/
LABEL(Normal_Operand):
sign = EXTRACTED64(*frB, 0, 0);
exp = EXTRACTED64(*frB, 1, 11) - 1023;
frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
Round_Single(processor, sign, &exp, &frac_grx);
FPSCR_SET_XX(FPSCR & fpscr_fi);
if (exp > 127 && (FPSCR & fpscr_oe) == 0) { label = Disabled_Exponent_Overflow; break; }
if (exp > 127 && (FPSCR & fpscr_oe) != 0) { label = Enabled_Overflow; break; }
if (exp > 127 && (FPSCR & fpscr_oe) == 0) GOTO(Disabled_Exponent_Overflow);
if (exp > 127 && (FPSCR & fpscr_oe) != 0) GOTO(Enabled_Overflow);
*frT = (INSERTED64(sign, 0, 0)
| INSERTED64(exp + 1023, 1, 11)
| INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
{ label = Done; break; }
case Done:
GOTO(Done);
/**/
LABEL(Done):
PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
{ label = finish; break; }
}
0.63,6.FRT,11./,16.FRB,21.814,31.Rc:X:64,f::Floating Convert To Integer Doubleword
floating_point_assist_interrupt(processor, cia);
0.63,6.FRT,11./,16.FRB,21.815,31.Rc:X:64,f::Floating Convert To Integer Doubleword with round towards Zero
floating_point_assist_interrupt(processor, cia);
0.63,6.FRT,11./,16.FRB,21.14,31.Rc:X:f::Floating Convert To Integer Word
floating_point_assist_interrupt(processor, cia);
0.63,6.FRT,11./,16.FRB,21.15,31.Rc:X:f:fctiwz:Floating Convert To Integer Word with round towards Zero
*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
@ -4237,12 +4393,8 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
int sign = EXTRACTED64(*frB, 0, 0);
int exp = 63;
unsigned64 frac = *frB;
enum { start, finish, Zero_Operand, Done } label = start;
while (label != finish) switch (label) {
case finish:
error("Unhandled switch\n");
case start:
if (frac == 0) { label = Zero_Operand; break; }
/***/
if (frac == 0) GOTO(Zero_Operand);
if (sign == 1) frac = ~frac + 1;
while (EXTRACTED64(frac, 0, 0) == 0) {
/*??? do the loop 0 times if (FRB) = max negative integer */
@ -4255,19 +4407,18 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*frT = (INSERTED64(sign, 0, 0)
| INSERTED64(exp + 1023, 1, 11)
| INSERTED64(EXTRACTED64(frac, 1, 52), 12, 63));
{ label = Done; break; }
GOTO(Done);
/**/
case Zero_Operand:
LABEL(Zero_Operand):
FPSCR_SET_FR(0);
FPSCR_SET_FI(0);
FPSCR_SET_FPRF(fpscr_rf_pos_zero);
*frT = 0;
{ label = Done; break; }
GOTO(Done);
/**/
case Done:
LABEL(Done):
PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
{ label = finish; break; }
}
#
# I.4.6.7 Floating-Point Compare Instructions
@ -4329,41 +4480,115 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
#
0.63,6.FRT,11./,16./,21.583,31.Rc:X:f::Move From FPSCR
floating_point_assist_interrupt(processor, cia);
# FPSCR_BEGIN;
# *frT = FPSCR;
# FPSCR_END(Rc);
0.63,6.BF,9./,11.BFA,14./,16./,21.64,31./:X:f::Move to Condition Register from FPSCR
floating_point_assist_interrupt(processor, cia);
# FPSCR_BEGIN;
# unsigned field = FPSCR_FIELD(BFA);
# CR_SET(BF, field);
# switch (BFA) {
# case 0:
# FPSCR &= ~(fpscr_fx | fpscr_ox);
# break;
# case 1:
# FPSCR &= ~(fpscr_ux | fpscr_zx | fpscr_xx | fpscr_vxsnan);
# break;
# case 2:
# FPSCR &= ~(fpscr_vxisi | fpscr_vxidi | fpscr_vxzdz | fpscr_vximz);
# break;
# case 3:
# FPSCR &= ~(fpscr_vxvc);
# break;
# case 5:
# FPSCR &= ~(fpscr_vxsoft | fpscr_vxsqrt | fpscr_vxcvi);
# break;
# }
# FPSCR_END(0);
0.64,6.BF,9./,11./,16.U,20./,21.134,31.Rc:X:f::Move To FPSCR Field Immediate
floating_point_assist_interrupt(processor, cia);
# FPSCR_BEGIN;
# FPSCR_SET(BF, U);
# /* FIXME - what about the effect this has on exception bits */
# FPSCR_END(Rc);
0.63,6./,7.FLM,15./,16.FRB,21.711,31.Rc:XFL:f::Move To FPSCR Fields
FPSCR_BEGIN;
int i;
for (i = 0; i < 8; i++) {
if ((FLM & BIT8(i))) {
FPSCR &= ~MASK32(i*4, i*4+3);
FPSCR |= MASKED32(*frB, i*4, i*4+3);
}
}
FPSCR_END(Rc);
0.63,6.BT,11./,16./,21.70,31.Rc:X:f::Move To FPSCR Bit 0
floating_point_assist_interrupt(processor, cia);
# FPSCR_BEGIN;
# unsigned32 mask = ~BIT32(BT) | (fpscr_fex | fpscr_vx);
# FPSCR &= mask;
# /* FIXME - what about the effect this has on exception bits */
# FPSCR_END(Rc);
0.63,6.BT,11./,16./,21.38,31.Rc:X:f::Move To FPSCR Bit 1
floating_point_assist_interrupt(processor, cia);
# FPSCR_BEGIN;
# unsigned32 bit = BIT32(BT) & ~(fpscr_fex | fpscr_vx);
# FPSCR |= bit;
# /* FIXME - need to take care of when and why FX is set */
# /* FIXME - if FX (or another exception bit is set) shall
# an exception occure */
# /* FPSCR |= fpscr_fx; */
# /* FIXME - what about the effect this has on exception bits */
# FPSCR_END(Rc);
#
# I.A.1.1 Floating-Point Store Instruction
#
0.31,6.FRS,11.RA,16.RB,21.983,31./:X:f::Store Floating-Point as Integer Word Indexed
0.31,6.FRS,11.RA,16.RB,21.983,31./:X:f,o::Store Floating-Point as Integer Word Indexed
program_interrupt(processor, cia, optional_instruction_program_interrupt);
#
# I.A.1.2 Floating-Point Arithmetic Instructions
#
0.63,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f::Floating Square Root
0.63,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f,o::Floating Square Root
program_interrupt(processor, cia, optional_instruction_program_interrupt);
0.59,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f::Floating Square Root Single
0.59,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f,o::Floating Square Root Single
program_interrupt(processor, cia, optional_instruction_program_interrupt);
0.59,6.FRT,11./,16.FRB,21./,26.24,31.Rc:A:f::Floating Reciprocal Estimate Single
0.59,6.FRT,11./,16.FRB,21./,26.24,31.Rc:A:f,o::Floating Reciprocal Estimate Single
program_interrupt(processor, cia, optional_instruction_program_interrupt);
0.63,6.FRT,11./,16.FRB,21./,26.26,31.Rc:A:f::Floating Reciprocal Square Root Estimate
0.63,6.FRT,11./,16.FRB,21./,26.26,31.Rc:A:f,o::Floating Reciprocal Square Root Estimate
program_interrupt(processor, cia, optional_instruction_program_interrupt);
#
# I.A.1.3 Floating-Point Select Instruction
#
0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.23,31.Rc:A:f::Floating Select
0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.23,31.Rc:A:f,o::Floating Select
*601: PPC_UNIT_BAD, PPC_UNIT_BAD, 0, 0, 0
*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
if (CURRENT_MODEL == MODEL_ppc601) {
program_interrupt(processor, cia, optional_instruction_program_interrupt);
} else {
unsigned64 zero = 0;
FPSCR_BEGIN;
if (is_NaN(*frA, 0) || is_less_than (frA, &zero)) *frT = *frB;
else *frT = *frC;
FPSCR_END(Rc);
PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
}
#
# II.3.2 Cache Management Instructions
@ -4385,7 +4610,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
cpu_synchronize_context(processor);
cpu_synchronize_context(processor, cia);
PPC_INSN_INT(0, 0, 0);
@ -4481,7 +4706,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
| MASKED(SRR1, 37, 41)
| MASKED(SRR1, 48, 63));
NIA = MASKED(SRR0, 0, 61);
cpu_synchronize_context(processor);
cpu_synchronize_context(processor, cia);
check_masked_interrupts(processor);
}

View File

@ -22,6 +22,6 @@ array,normal: 21:31:32:-1:OE,LR,AA,Rc,LK:
array,expand-forced: 6: 9: 6: 9:BO: 0xfc000000:0x40000000
array,boolean: 11:15:11:15:0RA: 0xfc000000:0x38000000:0
array,boolean: 11:15:11:15:RA: 0xfc000000:0x3c000000:0
# BLR instruction - LR=8 is munged into 0x100
array,boolean: 11:20:11:20:SPR: 0xfc0007ff:0x7c0003a6:0x100
array,boolean: 11:20:11:20:SPR: 0xfc0007ff:0x7c0002a6:0x100
# BLR instruction - LR=8 is munged into 0x100 == 256
array,boolean: 11:20:11:20:SPR: 0xfc0007ff:0x7c0003a6:256
array,boolean: 11:20:11:20:SPR: 0xfc0007ff:0x7c0002a6:256

View File

@ -26,6 +26,7 @@
#include "idecode.h"
#include "options.h"
#include "tree.h"
#include <stdio.h>
#include <ctype.h>
@ -78,6 +79,7 @@ int current_environment;
int current_alignment;
int current_floating_point;
int current_model_issue = MODEL_ISSUE_IGNORE;
int current_stdio = DO_USE_STDIO;
model_enum current_model = WITH_DEFAULT_MODEL;
@ -87,16 +89,16 @@ INLINE_PSIM\
(device *)
psim_tree(void)
{
device *root = device_tree_add_parsed(NULL, "core");
device_tree_add_parsed(root, "/aliases");
device_tree_add_parsed(root, "/options");
device_tree_add_parsed(root, "/chosen");
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");
device *root = tree_parse(NULL, "core");
tree_parse(root, "/aliases");
tree_parse(root, "/options");
tree_parse(root, "/chosen");
tree_parse(root, "/packages");
tree_parse(root, "/cpus");
tree_parse(root, "/openprom");
tree_parse(root, "/openprom/init");
tree_parse(root, "/openprom/trace");
tree_parse(root, "/openprom/options");
return root;
}
@ -122,55 +124,74 @@ psim_usage(int verbose)
printf_filtered("\n");
printf_filtered("Where\n");
printf_filtered("\n");
printf_filtered("\t<image> Name of the PowerPC program to run.\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("\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");
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("\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("\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");
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-e <os-emul> specify an OS or platform to model\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("\t Can be any of the following:\n");
printf_filtered("\t bug - OEA + MOTO BUG ROM calls\n");
printf_filtered("\t netbsd - UEA + NetBSD system calls\n");
printf_filtered("\t solaris - UEA + Solaris system calls\n");
printf_filtered("\t linux - UEA + Linux system calls\n");
printf_filtered("\t chirp - OEA + a few OpenBoot calls\n");
printf_filtered("\n"); }
printf_filtered("\t-e <os-emul> specify an OS or platform to model\n");
printf_filtered("\t-f <file> Merge <file> into the device tree\n");
if (verbose) { printf_filtered("\n"); }
printf_filtered("\t-h -? -H give more detailed usage\n");
if (verbose) { printf_filtered("\n"); }
printf_filtered("\t-m <model> Specify the processor to model (604)\n");
if (verbose) {
printf_filtered("\t Can be any of the following:\n");
printf_filtered("\t bug - OEA + MOTO BUG ROM calls\n");
printf_filtered("\t netbsd - UEA + NetBSD system calls\n");
printf_filtered("\t solaris - UEA + Solaris system calls\n");
printf_filtered("\t linux - UEA + Linux system calls\n");
printf_filtered("\t chirp - OEA + a few OpenBoot calls\n");
printf_filtered("\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-i Print instruction counting statistics\n");
printf_filtered("\t-n <nr-smp> Specify the number of processors in SMP simulations\n");
if (verbose) {
printf_filtered("\t Specifies the number of processors that are\n");
printf_filtered("\t to be modeled in a symetric multi-processor (SMP)\n");
printf_filtered("\t simulation\n");
printf_filtered("\n"); }
printf_filtered("\t-o <dev-spec> Add device <dev-spec> to the device tree\n");
if (verbose) { printf_filtered("\n"); }
printf_filtered("\t-I Print execution unit statistics\n");
printf_filtered("\t-r <ram-size> Set RAM size in bytes (OEA environments)\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");
printf_filtered("\t-t [!]<trace> Enable (disable) <trace> option\n");
if (verbose) { printf_filtered("\n"); }
printf_filtered("\n");
trace_usage(verbose);
device_usage(verbose);
@ -202,7 +223,11 @@ psim_options(device *root,
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);
tree_parse(root, "/openprom/options/os-emul %s", param);
break;
case 'f':
param = find_arg("Missing <file> option for -f\n", &argp, argv);
psim_merge_device_file(root, param);
break;
case 'h':
case '?':
@ -212,45 +237,81 @@ psim_options(device *root,
psim_usage(2);
break;
case 'i':
device_tree_add_parsed(root, "/openprom/trace/print-info 1");
tree_parse(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);
tree_parse(root, "/openprom/trace/print-info 2");
tree_parse(root, "/openprom/options/model-issue %d",
MODEL_ISSUE_PROCESS);
break;
case 'm':
param = find_arg("Missing <model> option for -m\n", &argp, argv);
device_tree_add_parsed(root, "/openprom/options/model \"%s", param);
tree_parse(root, "/openprom/options/model \"%s", param);
break;
case 'n':
param = find_arg("Missing <nr-smp> option for -n\n", &argp, argv);
tree_parse(root, "/openprom/options/smp %s", param);
break;
case 'o':
param = find_arg("Missing <device> option for -o\n", &argp, argv);
current = device_tree_add_parsed(current, "%s", param);
param = find_arg("Missing <dev-spec> option for -o\n", &argp, argv);
current = tree_parse(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));
tree_parse(root, "/openprom/options/oea-memory-size %s",
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);
tree_parse(root, "/openprom/trace/%s 0", param+1);
else
device_tree_add_parsed(root, "/openprom/trace/%s 1", param);
tree_parse(root, "/openprom/trace/%s 1", param);
break;
}
p += 1;
}
argp += 1;
}
/* force the trace node to (re)process its options */
device_ioctl(device_tree_find_device(root, "/openprom/trace"), NULL, 0);
/* force the trace node to process its options now *before* the tree
initialization occures */
device_ioctl(tree_find_device(root, "/openprom/trace"),
NULL, 0,
device_ioctl_set_trace);
/* return where the options end */
return argv + argp;
}
INLINE_PSIM\
(void)
psim_command(device *root,
char **argv)
{
int argp = 0;
if (argv[argp] == NULL) {
return;
}
else if (strcmp(argv[argp], "trace") == 0) {
const char *opt = find_arg("Missing <trace> option", &argp, argv);
if (opt[0] == '!')
trace_option(opt + 1, 0);
else
trace_option(opt, 1);
}
else if (strcmp(*argv, "change-media") == 0) {
char *device = find_arg("Missing device name", &argp, argv);
char *media = argv[++argp];
device_ioctl(tree_find_device(root, device), NULL, 0,
device_ioctl_change_media, media);
}
else {
printf_filtered("Unknown PSIM command %s, try\n", argv[argp]);
printf_filtered(" trace <trace-option>\n");
printf_filtered(" change-media <device> [ <new-image> ]\n");
}
}
/* create the simulator proper from the device tree and executable */
@ -274,13 +335,13 @@ psim_create(const char *file_name,
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 */
nr_cpus = device_find_integer_property(root, "/openprom/options/smp");
nr_cpus = tree_find_integer_property(root, "/openprom/options/smp");
if (MAX_NR_PROCESSORS < nr_cpus)
error("target and configured number of cpus conflict\n");
/* fill in the missing TARGET BYTE ORDER information */
current_target_byte_order
= (device_find_boolean_property(root, "/options/little-endian?")
= (tree_find_boolean_property(root, "/options/little-endian?")
? LITTLE_ENDIAN
: BIG_ENDIAN);
if (CURRENT_TARGET_BYTE_ORDER != current_target_byte_order)
@ -295,7 +356,7 @@ psim_create(const char *file_name,
error("host and configured byte order conflict\n");
/* fill in the missing OEA/VEA information */
env = device_find_string_property(root, "/openprom/options/env");
env = tree_find_string_property(root, "/openprom/options/env");
current_environment = ((strcmp(env, "user") == 0
|| strcmp(env, "uea") == 0)
? USER_ENVIRONMENT
@ -313,7 +374,7 @@ psim_create(const char *file_name,
/* fill in the missing ALLIGNMENT information */
current_alignment
= (device_find_boolean_property(root, "/openprom/options/strict-alignment?")
= (tree_find_boolean_property(root, "/openprom/options/strict-alignment?")
? STRICT_ALIGNMENT
: NONSTRICT_ALIGNMENT);
if (CURRENT_ALIGNMENT != current_alignment)
@ -321,15 +382,23 @@ psim_create(const char *file_name,
/* fill in the missing FLOATING POINT information */
current_floating_point
= (device_find_boolean_property(root, "/openprom/options/floating-point?")
= (tree_find_boolean_property(root, "/openprom/options/floating-point?")
? HARD_FLOATING_POINT
: SOFT_FLOATING_POINT);
if (CURRENT_FLOATING_POINT != current_floating_point)
error("target and configured floating-point conflict\n");
/* fill in the missing STDIO information */
current_stdio
= (tree_find_boolean_property(root, "/openprom/options/use-stdio?")
? DO_USE_STDIO
: DONT_USE_STDIO);
if (CURRENT_STDIO != current_stdio)
error("target and configured stdio interface conflict\n");
/* sort out the level of detail for issue modeling */
current_model_issue
= device_find_integer_property(root, "/openprom/options/model-issue");
= tree_find_integer_property(root, "/openprom/options/model-issue");
if (CURRENT_MODEL_ISSUE != current_model_issue)
error("target and configured model-issue conflict\n");
@ -341,7 +410,7 @@ psim_create(const char *file_name,
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"));
model_set(tree_find_string_property(root, "/openprom/options/model"));
/* create things */
system = ZALLOC(psim);
@ -364,7 +433,7 @@ psim_create(const char *file_name,
/* 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);
tree_print(root);
if (ppc_trace[trace_dump_device_tree])
error("");
@ -419,6 +488,7 @@ psim_halt(psim *system,
longjmp(*(jmp_buf*)(system->path_to_halt), current_cpu + 1);
}
INLINE_PSIM\
(int)
psim_last_cpu(psim *system)
@ -458,7 +528,7 @@ INLINE_PSIM\
psim_device(psim *system,
const char *path)
{
return device_tree_find_device(system->devices, path);
return tree_find_device(system->devices, path);
}
INLINE_PSIM\
@ -487,19 +557,20 @@ psim_init(psim *system)
cpu_init(system->processors[cpu_nr]);
/* init all the devices (which updates the cpus) */
device_tree_init(system->devices, system);
tree_init(system->devices, system);
/* and the emulation (which needs an initialized device tree) */
os_emul_init(system->os_emulation, system->nr_cpus);
/* now sync each cpu against the initialized state of its registers */
for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++) {
cpu_synchronize_context(system->processors[cpu_nr]);
cpu_page_tlb_invalidate_all(system->processors[cpu_nr]);
cpu *processor = system->processors[cpu_nr];
cpu_synchronize_context(processor, cpu_get_program_counter(processor));
cpu_page_tlb_invalidate_all(processor);
}
/* force loop to restart */
system->last_cpu = -1; /* when incremented will become 0 - first CPU */
/* force loop to start with first cpu (after processing events) */
system->last_cpu = system->nr_cpus - 1;
}
INLINE_PSIM\
@ -510,14 +581,15 @@ psim_stack(psim *system,
{
/* pass the stack device the argv/envp and let it work out what to
do with it */
device *stack_device = device_tree_find_device(system->devices,
"/openprom/init/stack");
device *stack_device = tree_find_device(system->devices,
"/openprom/init/stack");
if (stack_device != (device*)0) {
unsigned_word stack_pointer;
psim_read_register(system, 0, &stack_pointer, "sp", cooked_transfer);
device_ioctl(stack_device,
NULL, /*cpu*/
0, /*cia*/
device_ioctl_create_stack,
stack_pointer,
argv,
envp);
@ -778,7 +850,8 @@ psim_read_memory(psim *system,
error("psim_read_memory() invalid cpu\n");
processor = system->processors[which_cpu];
return vm_data_map_read_buffer(cpu_data_map(processor),
buffer, vaddr, nr_bytes);
buffer, vaddr, nr_bytes,
NULL, -1);
}
@ -798,7 +871,8 @@ psim_write_memory(psim *system,
error("psim_read_memory() invalid cpu\n");
processor = system->processors[which_cpu];
return vm_data_map_write_buffer(cpu_data_map(processor),
buffer, vaddr, nr_bytes, 1);
buffer, vaddr, nr_bytes, 1/*violate-read-only*/,
NULL, -1);
}
@ -818,20 +892,61 @@ INLINE_PSIM\
psim_merge_device_file(device *root,
const char *file_name)
{
FILE *description = fopen(file_name, "r");
int line_nr = 0;
FILE *description;
int line_nr;
char device_path[1000];
device *current = root;
device *current;
/* try opening the file */
description = fopen(file_name, "r");
if (description == NULL) {
perror(file_name);
error("Invalid file %s specified", file_name);
}
line_nr = 0;
current = root;
while (fgets(device_path, sizeof(device_path), description)) {
/* check all of line was read */
char *device;
/* check that the full 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);
error("%s:%d: line to long - %s",
file_name, line_nr, device_path);
}
else
*strchr(device_path, '\n') = '\0';
line_nr++;
/* skip comments ("#" or ";") and blank lines lines */
for (device = device_path;
*device != '\0' && isspace(*device);
device++);
if (device[0] == '#'
|| device[0] == ';'
|| device[0] == '\0')
continue;
/* merge any appended lines */
while (device_path[strlen(device_path) - 1] == '\\') {
int curlen = strlen(device_path) - 1;
/* zap \ */
device_path[curlen] = '\0';
/* append the next line */
if (!fgets(device_path + curlen, sizeof(device_path) - curlen, description)) {
fclose(description);
error("%s:%s: unexpected eof in line continuation - %s",
file_name, line_nr, device_path);
}
if (strchr(device_path, '\n') == NULL) {
fclose(description);
error("%s:%d: line to long - %s",
file_name, line_nr, device_path);
}
else
*strchr(device_path, '\n') = '\0';
line_nr++;
}
/* parse this line */
current = device_tree_add_parsed(current, "%s", device_path);
current = tree_parse(current, "%s", device);
}
fclose(description);
}

View File

@ -40,10 +40,9 @@
#endif
#endif
#include "../../gdb/defs.h"
#include "../../gdb/remote-sim.h"
#include "../../gdb/callback.h"
#include "defs.h"
#include "callback.h"
#include "remote-sim.h"
/* Structures used by the simulator, for gdb just have static structures */
@ -280,9 +279,9 @@ sim_do_command (char *cmd)
{
TRACE(trace_gdb, ("sim_do_commands(cmd=%s) called\n",
cmd ? cmd : "(null)"));
if (cmd) {
if (cmd != NULL) {
char **argv = buildargv(cmd);
psim_options(root_device, argv);
psim_command(root_device, argv);
freeargv(argv);
}
}
@ -312,6 +311,7 @@ sim_io_read_stdin(char *buf,
error("sim_io_read_stdin: unaccounted switch\n");
break;
}
return 0;
}
int
@ -329,6 +329,7 @@ sim_io_write_stdout(const char *buf,
error("sim_io_write_stdout: unaccounted switch\n");
break;
}
return 0;
}
int
@ -347,6 +348,7 @@ sim_io_write_stderr(const char *buf,
error("sim_io_write_stderr: unaccounted switch\n");
break;
}
return 0;
}

1273
sim/ppc/tree.c Normal file

File diff suppressed because it is too large Load Diff