mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-03-19 13:51:44 +08:00
January 23rd merge
This commit is contained in:
parent
1d5c6cfdf0
commit
5c04f4f7fc
47
sim/ppc/BUGS
Normal file
47
sim/ppc/BUGS
Normal 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.
|
||||
|
||||
|
1001
sim/ppc/ChangeLog
1001
sim/ppc/ChangeLog
File diff suppressed because it is too large
Load Diff
@ -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
1571
sim/ppc/configure
vendored
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
2226
sim/ppc/device.c
2226
sim/ppc/device.c
File diff suppressed because it is too large
Load Diff
419
sim/ppc/device.h
419
sim/ppc/device.h
@ -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_ */
|
||||
|
1856
sim/ppc/emul_chirp.c
1856
sim/ppc/emul_chirp.c
File diff suppressed because it is too large
Load Diff
@ -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");
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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])
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
283
sim/ppc/psim.c
283
sim/ppc/psim.c
@ -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);
|
||||
}
|
||||
|
@ -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
1273
sim/ppc/tree.c
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user