* interp.c (sim_open): Create second 1mb memory region at 0x40000000.
(sim_open): Create a device tree. (sim-hw.h): Include. (do_interrupt): Delete, needs to use dv-mn103cpu.c * dv-mn103int.c, dv-mn103cpu.c: New files.
This commit is contained in:
parent
8388c9a564
commit
6100784a60
@ -28,6 +28,8 @@ Makefile.in
|
||||
config.in
|
||||
configure
|
||||
configure.in
|
||||
dv-mn103cpu.c
|
||||
dv-mn103int.c
|
||||
mn10300_sim.h
|
||||
gencode.c
|
||||
interp.c
|
||||
|
@ -1,3 +1,13 @@
|
||||
Wed Mar 25 15:08:49 1998 Andrew Cagney <cagney@b1.cygnus.com>
|
||||
|
||||
* interp.c (sim_open): Create second 1mb memory region at
|
||||
0x40000000.
|
||||
(sim_open): Create a device tree.
|
||||
(sim-hw.h): Include.
|
||||
(do_interrupt): Delete, needs to use dv-mn103cpu.c
|
||||
|
||||
* dv-mn103int.c, dv-mn103cpu.c: New files.
|
||||
|
||||
Wed Mar 25 08:47:38 1998 Andrew Cagney <cagney@b1.cygnus.com>
|
||||
|
||||
* mn10300_sim.h (EXTRACT_PSW_LM, INSERT_PSW_LM, PSW_IE, PSW_LM):
|
||||
|
132
sim/mn10300/configure
vendored
132
sim/mn10300/configure
vendored
@ -114,6 +114,8 @@ ac_help="$ac_help
|
||||
--enable-sim-reserved-bits Specify whether to check reserved bits in instruction."
|
||||
ac_help="$ac_help
|
||||
--enable-sim-bitsize=N Specify target bitsize (32 or 64)."
|
||||
ac_help="$ac_help
|
||||
--enable-sim-hardware=LIST Specify the hardware to be included in the build."
|
||||
ac_help="$ac_help
|
||||
--enable-sim-common Enable common simulator"
|
||||
|
||||
@ -626,7 +628,7 @@ fi
|
||||
|
||||
|
||||
echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
|
||||
echo "configure:630: checking how to run the C preprocessor" >&5
|
||||
echo "configure:632: checking how to run the C preprocessor" >&5
|
||||
# On Suns, sometimes $CPP names a directory.
|
||||
if test -n "$CPP" && test -d "$CPP"; then
|
||||
CPP=
|
||||
@ -641,13 +643,13 @@ else
|
||||
# On the NeXT, cc -E runs the code through the compiler's parser,
|
||||
# not just through cpp.
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 645 "configure"
|
||||
#line 647 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <assert.h>
|
||||
Syntax Error
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:651: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
{ (eval echo configure:653: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out`
|
||||
if test -z "$ac_err"; then
|
||||
:
|
||||
@ -658,13 +660,13 @@ else
|
||||
rm -rf conftest*
|
||||
CPP="${CC-cc} -E -traditional-cpp"
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 662 "configure"
|
||||
#line 664 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <assert.h>
|
||||
Syntax Error
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:668: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
{ (eval echo configure:670: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out`
|
||||
if test -z "$ac_err"; then
|
||||
:
|
||||
@ -737,7 +739,7 @@ else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
|
||||
fi
|
||||
|
||||
echo $ac_n "checking host system type""... $ac_c" 1>&6
|
||||
echo "configure:741: checking host system type" >&5
|
||||
echo "configure:743: checking host system type" >&5
|
||||
|
||||
host_alias=$host
|
||||
case "$host_alias" in
|
||||
@ -758,7 +760,7 @@ host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
|
||||
echo "$ac_t""$host" 1>&6
|
||||
|
||||
echo $ac_n "checking target system type""... $ac_c" 1>&6
|
||||
echo "configure:762: checking target system type" >&5
|
||||
echo "configure:764: checking target system type" >&5
|
||||
|
||||
target_alias=$target
|
||||
case "$target_alias" in
|
||||
@ -776,7 +778,7 @@ target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
|
||||
echo "$ac_t""$target" 1>&6
|
||||
|
||||
echo $ac_n "checking build system type""... $ac_c" 1>&6
|
||||
echo "configure:780: checking build system type" >&5
|
||||
echo "configure:782: checking build system type" >&5
|
||||
|
||||
build_alias=$build
|
||||
case "$build_alias" in
|
||||
@ -820,7 +822,7 @@ test "$program_transform_name" = "" && program_transform_name="s,x,x,"
|
||||
# Extract the first word of "gcc", so it can be a program name with args.
|
||||
set dummy gcc; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:824: checking for $ac_word" >&5
|
||||
echo "configure:826: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@ -849,7 +851,7 @@ if test -z "$CC"; then
|
||||
# Extract the first word of "cc", so it can be a program name with args.
|
||||
set dummy cc; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:853: checking for $ac_word" >&5
|
||||
echo "configure:855: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@ -897,7 +899,7 @@ fi
|
||||
fi
|
||||
|
||||
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
|
||||
echo "configure:901: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
|
||||
echo "configure:903: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
|
||||
|
||||
ac_ext=c
|
||||
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
|
||||
@ -907,11 +909,11 @@ ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS
|
||||
cross_compiling=$ac_cv_prog_cc_cross
|
||||
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 911 "configure"
|
||||
#line 913 "configure"
|
||||
#include "confdefs.h"
|
||||
main(){return(0);}
|
||||
EOF
|
||||
if { (eval echo configure:915: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
|
||||
if { (eval echo configure:917: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
|
||||
ac_cv_prog_cc_works=yes
|
||||
# If we can't run a trivial program, we are probably using a cross compiler.
|
||||
if (./conftest; exit) 2>/dev/null; then
|
||||
@ -931,12 +933,12 @@ if test $ac_cv_prog_cc_works = no; then
|
||||
{ echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
|
||||
fi
|
||||
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
|
||||
echo "configure:935: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
|
||||
echo "configure:937: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
|
||||
echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
|
||||
cross_compiling=$ac_cv_prog_cc_cross
|
||||
|
||||
echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
|
||||
echo "configure:940: checking whether we are using GNU C" >&5
|
||||
echo "configure:942: checking whether we are using GNU C" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@ -945,7 +947,7 @@ else
|
||||
yes;
|
||||
#endif
|
||||
EOF
|
||||
if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:949: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
|
||||
if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:951: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
|
||||
ac_cv_prog_gcc=yes
|
||||
else
|
||||
ac_cv_prog_gcc=no
|
||||
@ -960,7 +962,7 @@ if test $ac_cv_prog_gcc = yes; then
|
||||
ac_save_CFLAGS="$CFLAGS"
|
||||
CFLAGS=
|
||||
echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
|
||||
echo "configure:964: checking whether ${CC-cc} accepts -g" >&5
|
||||
echo "configure:966: checking whether ${CC-cc} accepts -g" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@ -999,7 +1001,7 @@ fi
|
||||
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
|
||||
# ./install, which can be erroneously created by make from ./install.sh.
|
||||
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
|
||||
echo "configure:1003: checking for a BSD compatible install" >&5
|
||||
echo "configure:1005: checking for a BSD compatible install" >&5
|
||||
if test -z "$INSTALL"; then
|
||||
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
@ -1065,7 +1067,7 @@ AR=${AR-ar}
|
||||
# Extract the first word of "ranlib", so it can be a program name with args.
|
||||
set dummy ranlib; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:1069: checking for $ac_word" >&5
|
||||
echo "configure:1071: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@ -1099,17 +1101,17 @@ for ac_hdr in stdlib.h string.h strings.h unistd.h time.h
|
||||
do
|
||||
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
|
||||
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
|
||||
echo "configure:1103: checking for $ac_hdr" >&5
|
||||
echo "configure:1105: checking for $ac_hdr" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 1108 "configure"
|
||||
#line 1110 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <$ac_hdr>
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:1113: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
{ (eval echo configure:1115: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out`
|
||||
if test -z "$ac_err"; then
|
||||
rm -rf conftest*
|
||||
@ -1139,17 +1141,17 @@ for ac_hdr in sys/time.h sys/resource.h
|
||||
do
|
||||
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
|
||||
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
|
||||
echo "configure:1143: checking for $ac_hdr" >&5
|
||||
echo "configure:1145: checking for $ac_hdr" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 1148 "configure"
|
||||
#line 1150 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <$ac_hdr>
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:1153: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
{ (eval echo configure:1155: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out`
|
||||
if test -z "$ac_err"; then
|
||||
rm -rf conftest*
|
||||
@ -1179,17 +1181,17 @@ for ac_hdr in fcntl.h
|
||||
do
|
||||
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
|
||||
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
|
||||
echo "configure:1183: checking for $ac_hdr" >&5
|
||||
echo "configure:1185: checking for $ac_hdr" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 1188 "configure"
|
||||
#line 1190 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <$ac_hdr>
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:1193: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
{ (eval echo configure:1195: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out`
|
||||
if test -z "$ac_err"; then
|
||||
rm -rf conftest*
|
||||
@ -1218,12 +1220,12 @@ done
|
||||
for ac_func in getrusage time sigaction
|
||||
do
|
||||
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
|
||||
echo "configure:1222: checking for $ac_func" >&5
|
||||
echo "configure:1224: checking for $ac_func" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 1227 "configure"
|
||||
#line 1229 "configure"
|
||||
#include "confdefs.h"
|
||||
/* System header to define __stub macros and hopefully few prototypes,
|
||||
which can conflict with char $ac_func(); below. */
|
||||
@ -1246,7 +1248,7 @@ $ac_func();
|
||||
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:1250: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
|
||||
if { (eval echo configure:1252: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
|
||||
rm -rf conftest*
|
||||
eval "ac_cv_func_$ac_func=yes"
|
||||
else
|
||||
@ -1419,12 +1421,12 @@ fi
|
||||
|
||||
|
||||
echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
|
||||
echo "configure:1423: checking return type of signal handlers" >&5
|
||||
echo "configure:1425: checking return type of signal handlers" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 1428 "configure"
|
||||
#line 1430 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
@ -1441,7 +1443,7 @@ int main() {
|
||||
int i;
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:1445: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
|
||||
if { (eval echo configure:1447: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
|
||||
rm -rf conftest*
|
||||
ac_cv_type_signal=void
|
||||
else
|
||||
@ -1591,14 +1593,14 @@ else
|
||||
|
||||
if test "x$cross_compiling" = "xno"; then
|
||||
echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6
|
||||
echo "configure:1595: checking whether byte ordering is bigendian" >&5
|
||||
echo "configure:1597: checking whether byte ordering is bigendian" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
ac_cv_c_bigendian=unknown
|
||||
# See if sys/param.h defines the BYTE_ORDER macro.
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 1602 "configure"
|
||||
#line 1604 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
@ -1609,11 +1611,11 @@ int main() {
|
||||
#endif
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:1613: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
|
||||
if { (eval echo configure:1615: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
|
||||
rm -rf conftest*
|
||||
# It does; now see whether it defined to BIG_ENDIAN or not.
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 1617 "configure"
|
||||
#line 1619 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
@ -1624,7 +1626,7 @@ int main() {
|
||||
#endif
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:1628: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
|
||||
if { (eval echo configure:1630: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
|
||||
rm -rf conftest*
|
||||
ac_cv_c_bigendian=yes
|
||||
else
|
||||
@ -1644,7 +1646,7 @@ if test "$cross_compiling" = yes; then
|
||||
{ echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 1648 "configure"
|
||||
#line 1650 "configure"
|
||||
#include "confdefs.h"
|
||||
main () {
|
||||
/* Are we little or big endian? From Harbison&Steele. */
|
||||
@ -1657,7 +1659,7 @@ main () {
|
||||
exit (u.c[sizeof (long) - 1] == 1);
|
||||
}
|
||||
EOF
|
||||
if { (eval echo configure:1661: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
|
||||
if { (eval echo configure:1663: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
|
||||
then
|
||||
ac_cv_c_bigendian=no
|
||||
else
|
||||
@ -1784,15 +1786,51 @@ fi
|
||||
fi
|
||||
|
||||
|
||||
sim_hardware="-DWITH_HW=1"
|
||||
sim_hw_obj="hw-device.o hw-ports.o hw-properties.o hw-base.o hw-tree.o"
|
||||
hardware="core pal glue mn103cpu mn103int"
|
||||
# Check whether --enable-sim-hardware or --disable-sim-hardware was given.
|
||||
if test "${enable_sim_hardware+set}" = set; then
|
||||
enableval="$enable_sim_hardware"
|
||||
|
||||
case "${enableval}" in
|
||||
yes) ;;
|
||||
no) hardware=""; sim_hardware="-DWITH_HW=0"; sim_hw_obj="";;
|
||||
,*) hardware="${hardware} `echo ${enableval} | sed -e 's/,/ /'`";;
|
||||
*,) hardware="`echo ${enableval} | sed -e 's/,/ /'` ${hardware}";;
|
||||
*) hardware="`echo ${enableval} | sed -e 's/,/ /'`"'';;
|
||||
esac
|
||||
sim_hw=""
|
||||
for i in x $hardware ; do
|
||||
case " $f " in
|
||||
x) ;;
|
||||
*" $i "*) ;;
|
||||
*) sim_hw="$sim_hw $i" ;;
|
||||
esac
|
||||
done
|
||||
sim_hw_obj="$sim_hw_obj `echo $sim_hw | sed -e 's/\([^ ]*\)/dv-\1.o/g'`"
|
||||
if test x"$silent" != x"yes" && test x"$hardware" != x""; then
|
||||
echo "Setting hardware to $sim_hardware, $sim_hw, $sim_hw_obj"
|
||||
fi
|
||||
else
|
||||
|
||||
sim_hw="$hardware"
|
||||
sim_hw_obj="$sim_hw_obj `echo $sim_hw | sed -e 's/\([^ ]*\)/dv-\1.o/g'`"
|
||||
if test x"$silent" != x"yes"; then
|
||||
echo "Setting hardware to $sim_hardware, $sim_hw, $sim_hw_obj"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
for ac_func in time chmod utime fork execve execv chown
|
||||
do
|
||||
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
|
||||
echo "configure:1791: checking for $ac_func" >&5
|
||||
echo "configure:1829: checking for $ac_func" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 1796 "configure"
|
||||
#line 1834 "configure"
|
||||
#include "confdefs.h"
|
||||
/* System header to define __stub macros and hopefully few prototypes,
|
||||
which can conflict with char $ac_func(); below. */
|
||||
@ -1815,7 +1853,7 @@ $ac_func();
|
||||
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:1819: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
|
||||
if { (eval echo configure:1857: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
|
||||
rm -rf conftest*
|
||||
eval "ac_cv_func_$ac_func=yes"
|
||||
else
|
||||
@ -1843,17 +1881,17 @@ for ac_hdr in unistd.h stdlib.h string.h strings.h utime.h time.h
|
||||
do
|
||||
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
|
||||
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
|
||||
echo "configure:1847: checking for $ac_hdr" >&5
|
||||
echo "configure:1885: checking for $ac_hdr" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 1852 "configure"
|
||||
#line 1890 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <$ac_hdr>
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:1857: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
{ (eval echo configure:1895: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out`
|
||||
if test -z "$ac_err"; then
|
||||
rm -rf conftest*
|
||||
|
@ -12,6 +12,7 @@ SIM_AC_OPTION_HOSTENDIAN
|
||||
SIM_AC_OPTION_WARNINGS
|
||||
SIM_AC_OPTION_RESERVED_BITS
|
||||
SIM_AC_OPTION_BITSIZE(32,31)
|
||||
SIM_AC_OPTION_HARDWARE(,mn103cpu mn103int)
|
||||
|
||||
AC_CHECK_FUNCS(time chmod utime fork execve execv chown)
|
||||
AC_CHECK_HEADERS(unistd.h stdlib.h string.h strings.h utime.h time.h)
|
||||
|
431
sim/mn10300/dv-mn103cpu.c
Normal file
431
sim/mn10300/dv-mn103cpu.c
Normal file
@ -0,0 +1,431 @@
|
||||
/* This file is part of the program GDB, the GU debugger.
|
||||
|
||||
Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Solutions.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "sim-main.h"
|
||||
#include "hw-base.h"
|
||||
|
||||
/* DEVICE
|
||||
|
||||
|
||||
mn103cpu - mn10300 cpu virtual device
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
|
||||
Implements the external mn10300 functionality. This includes the
|
||||
delivery of of interrupts generated from other devices and the
|
||||
handling of device specific registers.
|
||||
|
||||
|
||||
PROPERTIES
|
||||
|
||||
|
||||
reg = <address> <size>
|
||||
|
||||
Specify the address of the mn10300's control register block. This
|
||||
block contains the Interrupt Vector Registers.
|
||||
|
||||
The reg property value `0x20000000 0x42' locates the register block
|
||||
at the address specified in the mn10300 user guide.
|
||||
|
||||
|
||||
PORTS
|
||||
|
||||
|
||||
reset (input)
|
||||
|
||||
Currently ignored.
|
||||
|
||||
|
||||
nmi (input)
|
||||
|
||||
Deliver a non-maskable interrupt to the processor.
|
||||
|
||||
|
||||
level (input)
|
||||
|
||||
Maskable interrupt level port port. The interrupt controller
|
||||
notifies the processor of any change in the level of pending
|
||||
requested interrupts via this port.
|
||||
|
||||
|
||||
ack (output)
|
||||
|
||||
Output signal indicating that the processor is delivering a level
|
||||
interrupt. The value passed with the event specfies the level of
|
||||
the interrupt being delivered.
|
||||
|
||||
|
||||
BUGS
|
||||
|
||||
|
||||
When delivering an interrupt, this code assumes that there is only
|
||||
one processor (number 0).
|
||||
|
||||
This code does not attempt to be efficient at handling pending
|
||||
interrupts. It simply schedules the interrupt delivery handler
|
||||
every instruction cycle until all pending interrupts go away. An
|
||||
alternative implementation might modify instructions that change
|
||||
the PSW and have them check to see if the change makes an interrupt
|
||||
delivery possible.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* The interrupt vectors */
|
||||
|
||||
enum { NR_VECTORS = 7, };
|
||||
|
||||
|
||||
/* The interrupt controller register address blocks */
|
||||
|
||||
struct mn103cpu_block {
|
||||
unsigned_word base;
|
||||
unsigned_word bound;
|
||||
};
|
||||
|
||||
|
||||
struct mn103cpu {
|
||||
struct mn103cpu_block block;
|
||||
hw_event *pending_handler;
|
||||
int pending_level;
|
||||
int pending_nmi;
|
||||
int pending_reset;
|
||||
/* the visible registers */
|
||||
unsigned16 interrupt_vector[NR_VECTORS];
|
||||
unsigned16 internal_memory_control;
|
||||
unsigned16 cpu_mode;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* input port ID's */
|
||||
|
||||
enum {
|
||||
RESET_PORT,
|
||||
NMI_PORT,
|
||||
LEVEL_PORT,
|
||||
};
|
||||
|
||||
|
||||
/* input port ID's */
|
||||
|
||||
enum {
|
||||
ACK_PORT,
|
||||
};
|
||||
|
||||
static const struct hw_port_descriptor mn103cpu_ports[] = {
|
||||
|
||||
/* interrupt inputs */
|
||||
{ "reset", RESET_PORT, 0, input_port, },
|
||||
{ "nmi", NMI_PORT, 0, input_port, },
|
||||
{ "level", LEVEL_PORT, 0, input_port, },
|
||||
|
||||
/* interrupt ack (latch) output from cpu */
|
||||
{ "ack", ACK_PORT, 0, output_port, },
|
||||
|
||||
{ NULL, },
|
||||
};
|
||||
|
||||
|
||||
/* Finish off the partially created hw device. Attach our local
|
||||
callbacks. Wire up our port names etc */
|
||||
|
||||
static hw_io_read_buffer_callback mn103cpu_io_read_buffer;
|
||||
static hw_io_write_buffer_callback mn103cpu_io_write_buffer;
|
||||
static hw_port_event_callback mn103cpu_port_event;
|
||||
|
||||
static void
|
||||
attach_mn103cpu_regs (struct hw *me,
|
||||
struct mn103cpu *controller)
|
||||
{
|
||||
unsigned_word attach_address;
|
||||
int attach_space;
|
||||
unsigned attach_size;
|
||||
reg_property_spec reg;
|
||||
if (hw_find_property (me, "reg") == NULL)
|
||||
hw_abort (me, "Missing \"reg\" property");
|
||||
if (!hw_find_reg_array_property (me, "reg", 0, ®))
|
||||
hw_abort (me, "\"reg\" property must contain three addr/size entries");
|
||||
hw_unit_address_to_attach_address (hw_parent (me),
|
||||
®.address,
|
||||
&attach_space,
|
||||
&attach_address,
|
||||
me);
|
||||
controller->block.base = attach_address;
|
||||
hw_unit_size_to_attach_size (hw_parent (me),
|
||||
®.size,
|
||||
&attach_size, me);
|
||||
controller->block.bound = attach_address + (attach_size - 1);
|
||||
if ((controller->block.base & 3) != 0)
|
||||
hw_abort (me, "cpu register block must be 4 byte aligned");
|
||||
hw_attach_address (hw_parent (me),
|
||||
0,
|
||||
attach_space, attach_address, attach_size,
|
||||
me);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
mn103cpu_finish (struct hw *me)
|
||||
{
|
||||
struct mn103cpu *controller;
|
||||
|
||||
controller = HW_ZALLOC (me, struct mn103cpu);
|
||||
set_hw_data (me, controller);
|
||||
set_hw_io_read_buffer (me, mn103cpu_io_read_buffer);
|
||||
set_hw_io_write_buffer (me, mn103cpu_io_write_buffer);
|
||||
set_hw_ports (me, mn103cpu_ports);
|
||||
set_hw_port_event (me, mn103cpu_port_event);
|
||||
|
||||
/* Attach ourself to our parent bus */
|
||||
attach_mn103cpu_regs (me, controller);
|
||||
|
||||
/* Initialize the read-only registers */
|
||||
controller->pending_level = 7; /* FIXME */
|
||||
/* ... */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* An event arrives on an interrupt port */
|
||||
|
||||
static void
|
||||
deliver_mn103cpu_interrupt (struct hw *me,
|
||||
void *data)
|
||||
{
|
||||
struct mn103cpu *controller = hw_data (me);
|
||||
SIM_DESC simulator = hw_system (me);
|
||||
sim_cpu *cpu = STATE_CPU (simulator, 0);
|
||||
|
||||
if (controller->pending_reset)
|
||||
{
|
||||
controller->pending_reset = 0;
|
||||
/* need to clear all registers et.al! */
|
||||
HW_TRACE ((me, "Reset!"));
|
||||
hw_abort (me, "Reset!");
|
||||
}
|
||||
else if (controller->pending_nmi)
|
||||
{
|
||||
controller->pending_nmi = 0;
|
||||
store_half (SP - 4, CIA_GET (cpu));
|
||||
store_half (SP - 8, PSW);
|
||||
PSW &= ~PSW_IE;
|
||||
SP = SP - 8;
|
||||
CIA_SET (cpu, 0x40000008);
|
||||
HW_TRACE ((me, "nmi pc=0x%08lx psw=0x%04x sp=0x%08lx",
|
||||
(long) CIA_GET (cpu), (unsigned) PSW, (long) SP));
|
||||
}
|
||||
else if ((controller->pending_level < EXTRACT_PSW_LM)
|
||||
&& (PSW & PSW_IE))
|
||||
{
|
||||
/* Don't clear pending level. Request continues to be pending
|
||||
until the interrupt controller clears/changes it */
|
||||
store_half (SP - 4, CIA_GET (cpu));
|
||||
store_half (SP - 8, PSW);
|
||||
PSW &= ~PSW_IE;
|
||||
PSW &= ~PSW_LM;
|
||||
PSW |= INSERT_PSW_LM (controller->pending_level);
|
||||
SP = SP - 8;
|
||||
CIA_SET (cpu, 0x40000000 + controller->interrupt_vector[controller->pending_level]);
|
||||
HW_TRACE ((me, "port-out ack %d", controller->pending_level));
|
||||
hw_port_event (me, ACK_PORT, controller->pending_level, NULL, NULL_CIA);
|
||||
HW_TRACE ((me, "int level=%d pc=0x%08lx psw=0x%04x sp=0x%08lx",
|
||||
controller->pending_level,
|
||||
(long) CIA_GET (cpu), (unsigned) PSW, (long) SP));
|
||||
}
|
||||
|
||||
/* As long as there is the potential need to deliver an interrupt we
|
||||
keep rescheduling this routine. */
|
||||
if (controller->pending_level < 7) /* FIXME */
|
||||
{
|
||||
if (controller->pending_handler != NULL)
|
||||
controller->pending_handler =
|
||||
hw_event_queue_schedule (me, 1, deliver_mn103cpu_interrupt, NULL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
mn103cpu_port_event (struct hw *me,
|
||||
int my_port,
|
||||
struct hw *source,
|
||||
int source_port,
|
||||
int level,
|
||||
sim_cpu *processor,
|
||||
sim_cia cia)
|
||||
{
|
||||
struct mn103cpu *controller = hw_data (me);
|
||||
|
||||
/* Schedule our event handler *now* */
|
||||
if (controller->pending_handler == NULL)
|
||||
controller->pending_handler =
|
||||
hw_event_queue_schedule (me, 0, deliver_mn103cpu_interrupt, NULL);
|
||||
|
||||
switch (my_port)
|
||||
{
|
||||
|
||||
case RESET_PORT:
|
||||
controller->pending_reset = 1;
|
||||
HW_TRACE ((me, "port-in reset"));
|
||||
break;
|
||||
|
||||
case NMI_PORT:
|
||||
controller->pending_nmi = 1;
|
||||
HW_TRACE ((me, "port-in nmi"));
|
||||
break;
|
||||
|
||||
case LEVEL_PORT:
|
||||
controller->pending_level = level;
|
||||
HW_TRACE ((me, "port-in level=%d", level));
|
||||
break;
|
||||
|
||||
default:
|
||||
hw_abort (me, "bad switch");
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Read/write to a CPU register */
|
||||
|
||||
enum mn103cpu_regs {
|
||||
INVALID_REG,
|
||||
IVR0_REG,
|
||||
IVR1_REG,
|
||||
IVR2_REG,
|
||||
IVR3_REG,
|
||||
IVR4_REG,
|
||||
IVR5_REG,
|
||||
IVR6_REG,
|
||||
IMCR_REG,
|
||||
CPUM_REG,
|
||||
};
|
||||
|
||||
static enum mn103cpu_regs
|
||||
decode_mn103cpu_addr (struct hw *me,
|
||||
struct mn103cpu *controller,
|
||||
unsigned_word base)
|
||||
{
|
||||
switch (base - controller->block.base)
|
||||
{
|
||||
case 0x000: return IVR0_REG;
|
||||
case 0x004: return IVR1_REG;
|
||||
case 0x008: return IVR2_REG;
|
||||
case 0x00c: return IVR3_REG;
|
||||
case 0x010: return IVR4_REG;
|
||||
case 0x014: return IVR5_REG;
|
||||
case 0x018: return IVR6_REG;
|
||||
case 0x020: return IMCR_REG;
|
||||
case 0x040: return CPUM_REG;
|
||||
default: return INVALID_REG;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned
|
||||
mn103cpu_io_read_buffer (struct hw *me,
|
||||
void *dest,
|
||||
int space,
|
||||
unsigned_word base,
|
||||
unsigned nr_bytes,
|
||||
sim_cpu *processor,
|
||||
sim_cia cia)
|
||||
{
|
||||
struct mn103cpu *controller = hw_data (me);
|
||||
unsigned16 val = 0;
|
||||
enum mn103cpu_regs reg = decode_mn103cpu_addr (me, controller, base);
|
||||
|
||||
switch (reg)
|
||||
{
|
||||
case IVR0_REG:
|
||||
case IVR1_REG:
|
||||
case IVR2_REG:
|
||||
case IVR3_REG:
|
||||
case IVR4_REG:
|
||||
case IVR5_REG:
|
||||
case IVR6_REG:
|
||||
val = controller->interrupt_vector[reg - IVR0_REG];
|
||||
break;
|
||||
case IMCR_REG:
|
||||
val = controller->internal_memory_control;
|
||||
break;
|
||||
case CPUM_REG:
|
||||
val = controller->cpu_mode;
|
||||
break;
|
||||
default:
|
||||
/* just ignore the read */
|
||||
break;
|
||||
}
|
||||
|
||||
if (nr_bytes == 2)
|
||||
*(unsigned16*) dest = H2LE_2 (val);
|
||||
|
||||
return nr_bytes;
|
||||
}
|
||||
|
||||
static unsigned
|
||||
mn103cpu_io_write_buffer (struct hw *me,
|
||||
const void *source,
|
||||
int space,
|
||||
unsigned_word base,
|
||||
unsigned nr_bytes,
|
||||
sim_cpu *cpu,
|
||||
sim_cia cia)
|
||||
{
|
||||
struct mn103cpu *controller = hw_data (me);
|
||||
unsigned16 val;
|
||||
enum mn103cpu_regs reg;
|
||||
|
||||
if (nr_bytes != 2)
|
||||
hw_abort (me, "must be two byte write");
|
||||
|
||||
reg = decode_mn103cpu_addr (me, controller, base);
|
||||
val = LE2H_2 (* (unsigned16 *) source);
|
||||
|
||||
switch (reg)
|
||||
{
|
||||
case IVR0_REG:
|
||||
case IVR1_REG:
|
||||
case IVR2_REG:
|
||||
case IVR3_REG:
|
||||
case IVR4_REG:
|
||||
case IVR5_REG:
|
||||
case IVR6_REG:
|
||||
controller->interrupt_vector[reg - IVR0_REG] = val;
|
||||
HW_TRACE ((me, "ivr%d = 0x%04lx", reg - IVR0_REG, (long) val));
|
||||
break;
|
||||
default:
|
||||
/* just ignore the write */
|
||||
break;
|
||||
}
|
||||
|
||||
return nr_bytes;
|
||||
}
|
||||
|
||||
|
||||
const struct hw_device_descriptor dv_mn103cpu_descriptor[] = {
|
||||
{ "mn103cpu", mn103cpu_finish, },
|
||||
{ NULL },
|
||||
};
|
785
sim/mn10300/dv-mn103int.c
Normal file
785
sim/mn10300/dv-mn103int.c
Normal file
@ -0,0 +1,785 @@
|
||||
/* This file is part of the program GDB, the GU debugger.
|
||||
|
||||
Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Solutions.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "sim-main.h"
|
||||
#include "hw-base.h"
|
||||
|
||||
/* DEVICE
|
||||
|
||||
|
||||
mn103int - mn10300 interrupt controller
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
|
||||
Implements the mn10300 interrupt controller described in the
|
||||
mn10300 user guide.
|
||||
|
||||
|
||||
PROPERTIES
|
||||
|
||||
|
||||
reg = <icr-adr> <icr-siz> <iagr-adr> <iadr-siz> <extmd-adr> <extmd-siz>
|
||||
|
||||
Specify the address of the ICR (total of 25 registers), IAGR and
|
||||
EXTMD registers (within the parent bus).
|
||||
|
||||
The reg property value `0x34000100 0x68 0x34000200 0x8 0x3400280
|
||||
0x8' locates the interrupt controller at the addresses specified in
|
||||
the mn10300 interrupt controller user guide.
|
||||
|
||||
|
||||
PORTS
|
||||
|
||||
|
||||
nmi (output)
|
||||
|
||||
Non-maskable interrupt output port. An event on this output ports
|
||||
indicates a NMI request from the interrupt controller. The value
|
||||
attached to the event should be ignored.
|
||||
|
||||
|
||||
level (output)
|
||||
|
||||
Maskable interrupt level output port. An event on this output port
|
||||
indicates a maskable interrupt request at the specified level. The
|
||||
event value defines the level being requested.
|
||||
|
||||
The interrupt controller will generate an event on this port
|
||||
whenever there is a change to the internal state of the interrupt
|
||||
controller.
|
||||
|
||||
|
||||
ack (input)
|
||||
|
||||
Signal from processor indicating that a maskable interrupt has been
|
||||
accepted and the interrupt controller should latch the IAGR with
|
||||
value of the current highest priority interrupting group.
|
||||
|
||||
The event value is the interrupt level being accepted by the
|
||||
processor. It should be consistent with the most recent LEVEL sent
|
||||
to the processor from the interrupt controller.
|
||||
|
||||
|
||||
int[0..100] (input)
|
||||
|
||||
Level or edge triggered interrupt input port. Each of the 25
|
||||
groups (0..24) can have up to 4 (0..3) interrupt inputs. The
|
||||
interpretation of a port event/value is determined by the
|
||||
configuration of the corresponding interrupt group.
|
||||
|
||||
For convenience, numerous aliases to these interrupt inputs are
|
||||
provided.
|
||||
|
||||
|
||||
BUGS
|
||||
|
||||
|
||||
For edge triggered interrupts, the interrupt controller does not
|
||||
differentiate between POSITIVE (rising) and NEGATIVE (falling)
|
||||
edges. Instead any input port event is considered to be an
|
||||
interrupt trigger.
|
||||
|
||||
For level sensative interrupts, the interrupt controller ignores
|
||||
active HIGH/LOW settings and instead always interprets a nonzero
|
||||
port value as an interupt assertion and a zero port value as a
|
||||
negation.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* The interrupt groups - numbered according to mn10300 convention */
|
||||
|
||||
enum mn103int_trigger {
|
||||
ACTIVE_LOW,
|
||||
ACTIVE_HIGH,
|
||||
POSITIVE_EDGE,
|
||||
NEGATIVE_EDGE,
|
||||
};
|
||||
|
||||
enum mn103int_type {
|
||||
NMI_GROUP,
|
||||
INT_GROUP,
|
||||
};
|
||||
|
||||
struct mn103int_group {
|
||||
int level;
|
||||
unsigned enable;
|
||||
unsigned request;
|
||||
unsigned input;
|
||||
enum mn103int_trigger trigger;
|
||||
enum mn103int_type type;
|
||||
};
|
||||
|
||||
enum {
|
||||
FIRST_NMI_GROUP = 0,
|
||||
LAST_NMI_GROUP = 1,
|
||||
FIRST_INT_GROUP = 2,
|
||||
LAST_INT_GROUP = 24,
|
||||
NR_GROUPS,
|
||||
};
|
||||
|
||||
enum {
|
||||
LOWEST_LEVEL = 7,
|
||||
};
|
||||
|
||||
/* The interrupt controller register address blocks */
|
||||
|
||||
struct mn103int_block {
|
||||
unsigned_word base;
|
||||
unsigned_word bound;
|
||||
};
|
||||
|
||||
enum { ICR_BLOCK, IAGR_BLOCK, EXTMD_BLOCK, NR_BLOCKS };
|
||||
|
||||
|
||||
struct mn103int {
|
||||
struct mn103int_block block[NR_BLOCKS];
|
||||
struct mn103int_group group[NR_GROUPS];
|
||||
unsigned interrupt_accepted_group;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* output port ID's */
|
||||
|
||||
enum {
|
||||
NMI_PORT,
|
||||
LEVEL_PORT,
|
||||
};
|
||||
|
||||
|
||||
/* input port ID's */
|
||||
|
||||
enum {
|
||||
G0_PORT = 0,
|
||||
G1_PORT = 4,
|
||||
G2_PORT = 8,
|
||||
G3_PORT = 12,
|
||||
G4_PORT = 16,
|
||||
G5_PORT = 20,
|
||||
G6_PORT = 24,
|
||||
G7_PORT = 28,
|
||||
G8_PORT = 32,
|
||||
G9_PORT = 36,
|
||||
G10_PORT = 40,
|
||||
G11_PORT = 44,
|
||||
G12_PORT = 48,
|
||||
G13_PORT = 52,
|
||||
G14_PORT = 56,
|
||||
G15_PORT = 60,
|
||||
G16_PORT = 64,
|
||||
G17_PORT = 68,
|
||||
G18_PORT = 72,
|
||||
G19_PORT = 76,
|
||||
G20_PORT = 80,
|
||||
G21_PORT = 84,
|
||||
G22_PORT = 88,
|
||||
G23_PORT = 92,
|
||||
G24_PORT = 96,
|
||||
NR_G_PORTS = 100,
|
||||
ACK_PORT,
|
||||
};
|
||||
|
||||
static const struct hw_port_descriptor mn103int_ports[] = {
|
||||
|
||||
/* interrupt outputs */
|
||||
|
||||
{ "nmi", NMI_PORT, 0, output_port, },
|
||||
{ "level", LEVEL_PORT, 0, output_port, },
|
||||
|
||||
/* interrupt ack (latch) input from cpu */
|
||||
|
||||
{ "ack", ACK_PORT, 0, input_port, },
|
||||
|
||||
/* interrupt inputs (as names) */
|
||||
|
||||
{ "nmirq", G0_PORT + 0, 0, input_port, },
|
||||
{ "watchdog", G0_PORT + 1, 0, input_port, },
|
||||
{ "syserr", G0_PORT + 2, 0, input_port, },
|
||||
|
||||
{ "timer-0-underflow", G2_PORT + 0, 0, input_port, },
|
||||
{ "timer-1-underflow", G2_PORT + 1, 0, input_port, },
|
||||
{ "timer-2-underflow", G2_PORT + 2, 0, input_port, },
|
||||
{ "timer-3-underflow", G2_PORT + 3, 0, input_port, },
|
||||
{ "timer-4-underflow", G3_PORT + 0, 0, input_port, },
|
||||
{ "timer-5-underflow", G3_PORT + 1, 0, input_port, },
|
||||
{ "timer-6-underflow", G3_PORT + 2, 0, input_port, },
|
||||
{ "timer-7-underflow", G3_PORT + 3, 0, input_port, },
|
||||
|
||||
{ "timer-8-underflow", G4_PORT + 0, 0, input_port, },
|
||||
{ "timer-8-compare-a", G4_PORT + 1, 0, input_port, },
|
||||
{ "timer-8-compare-b", G4_PORT + 2, 0, input_port, },
|
||||
|
||||
{ "timer-9-underflow", G5_PORT + 0, 0, input_port, },
|
||||
{ "timer-9-compare-a", G5_PORT + 1, 0, input_port, },
|
||||
{ "timer-9-compare-b", G5_PORT + 2, 0, input_port, },
|
||||
|
||||
{ "timer-10-underflow", G6_PORT + 0, 0, input_port, },
|
||||
{ "timer-10-compare-a", G6_PORT + 1, 0, input_port, },
|
||||
{ "timer-10-compare-b", G6_PORT + 2, 0, input_port, },
|
||||
{ "timer-10-compare-c", G6_PORT + 3, 0, input_port, },
|
||||
|
||||
{ "timer-11-underflow", G7_PORT + 0, 0, input_port, },
|
||||
{ "timer-11-compare-a", G7_PORT + 1, 0, input_port, },
|
||||
{ "timer-11-compare-b", G7_PORT + 2, 0, input_port, },
|
||||
{ "timer-11-compare-c", G7_PORT + 3, 0, input_port, },
|
||||
|
||||
{ "timer-12-underflow", G8_PORT + 0, 0, input_port, },
|
||||
{ "timer-12-compare-a", G8_PORT + 1, 0, input_port, },
|
||||
{ "timer-12-compare-b", G8_PORT + 2, 0, input_port, },
|
||||
{ "timer-12-compare-c", G8_PORT + 3, 0, input_port, },
|
||||
|
||||
{ "timer-11-compare-d", G9_PORT + 0, 0, input_port, },
|
||||
{ "timer-12-compare-d", G9_PORT + 1, 0, input_port, },
|
||||
|
||||
{ "dma-0-end", G10_PORT, 0, input_port, },
|
||||
{ "dma-1-end", G11_PORT, 0, input_port, },
|
||||
{ "dma-2-end", G12_PORT, 0, input_port, },
|
||||
{ "dma-3-end", G13_PORT, 0, input_port, },
|
||||
|
||||
{ "serial-0-recieve", G14_PORT + 0, 0, input_port, },
|
||||
{ "serial-0-transmit", G14_PORT + 1, 0, input_port, },
|
||||
|
||||
{ "serial-1-recieve", G15_PORT + 0, 0, input_port, },
|
||||
{ "serial-1-transmit", G15_PORT + 1, 0, input_port, },
|
||||
|
||||
{ "irq-0", G16_PORT, 0, input_port, },
|
||||
{ "irq-1", G17_PORT, 0, input_port, },
|
||||
{ "irq-2", G18_PORT, 0, input_port, },
|
||||
{ "irq-3", G19_PORT, 0, input_port, },
|
||||
{ "irq-4", G20_PORT, 0, input_port, },
|
||||
{ "irq-5", G21_PORT, 0, input_port, },
|
||||
{ "irq-6", G22_PORT, 0, input_port, },
|
||||
{ "irq-7", G23_PORT, 0, input_port, },
|
||||
|
||||
{ "ad-end", G24_PORT, 0, input_port, },
|
||||
|
||||
/* interrupt inputs (as generic numbers) */
|
||||
|
||||
{ "int", 0, NR_G_PORTS, input_port, },
|
||||
|
||||
{ NULL, },
|
||||
};
|
||||
|
||||
|
||||
/* Macros for extracting/restoring the various register bits */
|
||||
|
||||
#define EXTRACT_ID(X) (LSEXTRACTED8 ((X), 3, 0))
|
||||
#define INSERT_ID(X) (LSINSERTED8 ((X), 3, 0))
|
||||
|
||||
#define EXTRACT_IR(X) (LSEXTRACTED8 ((X), 7, 4))
|
||||
#define INSERT_IR(X) (LSINSERTED8 ((X), 7, 4))
|
||||
|
||||
#define EXTRACT_IE(X) (LSEXTRACTED8 ((X), 3, 0))
|
||||
#define INSERT_IE(X) (LSINSERTED8 ((X), 3, 0))
|
||||
|
||||
#define EXTRACT_LV(X) (LSEXTRACTED8 ((X), 6, 4))
|
||||
#define INSERT_LV(X) (LSINSERTED8 ((X), 6, 4))
|
||||
|
||||
|
||||
|
||||
/* Finish off the partially created hw device. Attach our local
|
||||
callbacks. Wire up our port names etc */
|
||||
|
||||
static hw_io_read_buffer_callback mn103int_io_read_buffer;
|
||||
static hw_io_write_buffer_callback mn103int_io_write_buffer;
|
||||
static hw_port_event_callback mn103int_port_event;
|
||||
|
||||
static void
|
||||
attach_mn103int_regs (struct hw *me,
|
||||
struct mn103int *controller)
|
||||
{
|
||||
int i;
|
||||
if (hw_find_property (me, "reg") == NULL)
|
||||
hw_abort (me, "Missing \"reg\" property");
|
||||
for (i = 0; i < NR_BLOCKS; i++)
|
||||
{
|
||||
unsigned_word attach_address;
|
||||
int attach_space;
|
||||
unsigned attach_size;
|
||||
reg_property_spec reg;
|
||||
if (!hw_find_reg_array_property (me, "reg", i, ®))
|
||||
hw_abort (me, "\"reg\" property must contain three addr/size entries");
|
||||
hw_unit_address_to_attach_address (hw_parent (me),
|
||||
®.address,
|
||||
&attach_space,
|
||||
&attach_address,
|
||||
me);
|
||||
controller->block[i].base = attach_address;
|
||||
hw_unit_size_to_attach_size (hw_parent (me),
|
||||
®.size,
|
||||
&attach_size, me);
|
||||
controller->block[i].bound = attach_address + (attach_size - 1);
|
||||
hw_attach_address (hw_parent (me),
|
||||
0,
|
||||
attach_space, attach_address, attach_size,
|
||||
me);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mn103int_finish (struct hw *me)
|
||||
{
|
||||
int gid;
|
||||
struct mn103int *controller;
|
||||
|
||||
controller = HW_ZALLOC (me, struct mn103int);
|
||||
set_hw_data (me, controller);
|
||||
set_hw_io_read_buffer (me, mn103int_io_read_buffer);
|
||||
set_hw_io_write_buffer (me, mn103int_io_write_buffer);
|
||||
set_hw_ports (me, mn103int_ports);
|
||||
set_hw_port_event (me, mn103int_port_event);
|
||||
|
||||
/* Attach ourself to our parent bus */
|
||||
attach_mn103int_regs (me, controller);
|
||||
|
||||
/* Initialize all the groups according to their default configuration */
|
||||
for (gid = 0; gid < NR_GROUPS; gid++)
|
||||
{
|
||||
struct mn103int_group *group = &controller->group[gid];
|
||||
group->enable = 0xf;
|
||||
group->trigger = NEGATIVE_EDGE;
|
||||
if (FIRST_NMI_GROUP <= gid && gid <= LAST_NMI_GROUP)
|
||||
{
|
||||
group->type = NMI_GROUP;
|
||||
}
|
||||
else if (FIRST_INT_GROUP <= gid && gid <= LAST_INT_GROUP)
|
||||
{
|
||||
group->type = INT_GROUP;
|
||||
}
|
||||
else
|
||||
hw_abort (me, "internal error - unknown group id");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Perform the nasty work of figuring out which of the interrupt
|
||||
groups should have its interrupt delivered. */
|
||||
|
||||
static int
|
||||
find_highest_interrupt_group (struct hw *me,
|
||||
struct mn103int *controller)
|
||||
{
|
||||
int gid;
|
||||
int selected;
|
||||
|
||||
/* FIRST_NMI_GROUP (group zero) is used as a special default value
|
||||
when searching for an interrupt group */
|
||||
selected = FIRST_NMI_GROUP;
|
||||
controller->group[FIRST_NMI_GROUP].level = 7;
|
||||
|
||||
for (gid = FIRST_INT_GROUP; gid <= LAST_INT_GROUP; gid++)
|
||||
{
|
||||
struct mn103int_group *group = &controller->group[gid];
|
||||
if ((group->request & group->enable) != 0)
|
||||
{
|
||||
if (group->level > controller->group[selected].level)
|
||||
{
|
||||
selected = gid;
|
||||
}
|
||||
}
|
||||
}
|
||||
return selected;
|
||||
}
|
||||
|
||||
|
||||
/* Notify the processor of an interrupt level update */
|
||||
|
||||
static void
|
||||
push_interrupt_level (struct hw *me,
|
||||
struct mn103int *controller)
|
||||
{
|
||||
int selected = find_highest_interrupt_group (me, controller);
|
||||
int level = controller->group[selected].level;
|
||||
HW_TRACE ((me, "port-out - selected=%d level=%d", selected, level));
|
||||
hw_port_event (me, LEVEL_PORT, level, NULL, NULL_CIA);
|
||||
}
|
||||
|
||||
|
||||
/* An event arrives on an interrupt port */
|
||||
|
||||
static void
|
||||
mn103int_port_event (struct hw *me,
|
||||
int my_port,
|
||||
struct hw *source,
|
||||
int source_port,
|
||||
int level,
|
||||
sim_cpu *processor,
|
||||
sim_cia cia)
|
||||
{
|
||||
struct mn103int *controller = hw_data (me);
|
||||
|
||||
switch (my_port)
|
||||
{
|
||||
|
||||
case ACK_PORT:
|
||||
{
|
||||
int selected = find_highest_interrupt_group (me, controller);
|
||||
if (controller->group[selected].level != level)
|
||||
hw_abort (me, "botched level synchronisation");
|
||||
controller->interrupt_accepted_group = selected;
|
||||
HW_TRACE ((me, "port-event port=ack level=%d - selected=%d",
|
||||
level, selected));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
int gid;
|
||||
int iid;
|
||||
struct mn103int_group *group;
|
||||
unsigned interrupt;
|
||||
if (my_port > NR_G_PORTS)
|
||||
hw_abort (me, "Event on unknown port %d", my_port);
|
||||
|
||||
/* map the port onto an interrupt group */
|
||||
gid = (my_port % NR_G_PORTS) / 4;
|
||||
group = &controller->group[gid];
|
||||
iid = (my_port % 4);
|
||||
interrupt = 1 << iid;
|
||||
|
||||
/* update our cached input */
|
||||
if (level)
|
||||
group->input |= interrupt;
|
||||
else
|
||||
group->input &= ~interrupt;
|
||||
|
||||
/* update the request bits */
|
||||
switch (group->trigger)
|
||||
{
|
||||
case ACTIVE_LOW:
|
||||
case ACTIVE_HIGH:
|
||||
if (level)
|
||||
group->request |= interrupt;
|
||||
break;
|
||||
case NEGATIVE_EDGE:
|
||||
case POSITIVE_EDGE:
|
||||
group->request |= interrupt;
|
||||
}
|
||||
|
||||
/* force a corresponding output */
|
||||
switch (group->type)
|
||||
{
|
||||
|
||||
case NMI_GROUP:
|
||||
{
|
||||
/* for NMI's the event is the trigger */
|
||||
HW_TRACE ((me, "port-in port=%d group=%d interrupt=%d - NMI",
|
||||
my_port, gid, iid));
|
||||
if ((group->request & group->enable) != 0)
|
||||
{
|
||||
HW_TRACE ((me, "port-out NMI"));
|
||||
hw_port_event (me, NMI_PORT, 0, NULL, NULL_CIA);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case INT_GROUP:
|
||||
{
|
||||
/* if an interrupt is now pending */
|
||||
HW_TRACE ((me, "port-in port=%d group=%d interrupt=%d - INT",
|
||||
my_port, gid, iid));
|
||||
push_interrupt_level (me, controller);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Read/write to to an ICR (group control register) */
|
||||
|
||||
static unsigned8
|
||||
read_icr (struct hw *me,
|
||||
struct mn103int *controller,
|
||||
struct mn103int_group *group,
|
||||
unsigned_word offset)
|
||||
{
|
||||
unsigned8 val = 0;
|
||||
switch (group->type)
|
||||
{
|
||||
|
||||
case NMI_GROUP:
|
||||
switch (offset)
|
||||
{
|
||||
case 0:
|
||||
val = INSERT_ID (group->request);
|
||||
HW_TRACE ((me, "read-icr 0x%02x", val));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case INT_GROUP:
|
||||
switch (offset)
|
||||
{
|
||||
case 0:
|
||||
val = (INSERT_IR (group->request)
|
||||
| INSERT_ID (group->request & group->enable));
|
||||
HW_TRACE ((me, "read-icr 0:0x%02x", val));
|
||||
break;
|
||||
case 1:
|
||||
val = (INSERT_LV (group->level)
|
||||
| INSERT_IE (group->enable));
|
||||
HW_TRACE ((me, "read-icr 1:0x%02x", val));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void
|
||||
write_icr (struct hw *me,
|
||||
struct mn103int *controller,
|
||||
struct mn103int_group *group,
|
||||
unsigned_word offset,
|
||||
unsigned8 val)
|
||||
{
|
||||
switch (group->type)
|
||||
{
|
||||
|
||||
case NMI_GROUP:
|
||||
switch (offset)
|
||||
{
|
||||
case 0:
|
||||
HW_TRACE ((me, "write-icr 0x%02x", val));
|
||||
group->request &= ~EXTRACT_ID (val);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case INT_GROUP:
|
||||
switch (offset)
|
||||
{
|
||||
case 0: /* request/detect */
|
||||
/* Clear any ID bits and then set them according to IR */
|
||||
HW_TRACE ((me, "write-icr 0:0x%02x", val));
|
||||
group->request &= EXTRACT_ID (val);
|
||||
group->request |= EXTRACT_IR (val) & EXTRACT_ID (val);
|
||||
break;
|
||||
case 1: /* level/enable */
|
||||
HW_TRACE ((me, "write-icr 1:0x%02x", val));
|
||||
group->level = EXTRACT_LV (val);
|
||||
group->enable = EXTRACT_IE (val);
|
||||
break;
|
||||
default:
|
||||
/* ignore */
|
||||
break;
|
||||
}
|
||||
push_interrupt_level (me, controller);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Read the IAGR (Interrupt accepted group register) */
|
||||
|
||||
static unsigned8
|
||||
read_iagr (struct hw *me,
|
||||
struct mn103int *controller,
|
||||
unsigned_word offset)
|
||||
{
|
||||
unsigned8 val;
|
||||
switch (offset)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
val = (controller->interrupt_accepted_group << 2);
|
||||
if (!(controller->group[val].request
|
||||
& controller->group[val].enable))
|
||||
/* oops, lost the request */
|
||||
val = 0;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
val = 0;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
/* Reads/writes to the EXTMD (external interrupt trigger configuration
|
||||
register) */
|
||||
|
||||
static struct mn103int_group *
|
||||
external_group (struct mn103int *controller,
|
||||
unsigned_word offset)
|
||||
{
|
||||
switch (offset)
|
||||
{
|
||||
case 0:
|
||||
return &controller->group[16];
|
||||
case 1:
|
||||
return &controller->group[20];
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned8
|
||||
read_extmd (struct hw *me,
|
||||
struct mn103int *controller,
|
||||
unsigned_word offset)
|
||||
{
|
||||
int gid;
|
||||
unsigned8 val = 0;
|
||||
struct mn103int_group *group = external_group (controller, offset);
|
||||
if (group != NULL)
|
||||
{
|
||||
for (gid = 0; gid < 4; gid++)
|
||||
{
|
||||
val |= (group[gid].trigger << (gid * 2));
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static void
|
||||
write_extmd (struct hw *me,
|
||||
struct mn103int *controller,
|
||||
unsigned_word offset,
|
||||
unsigned8 val)
|
||||
{
|
||||
int gid;
|
||||
struct mn103int_group *group = external_group (controller, offset);
|
||||
if (group != NULL)
|
||||
{
|
||||
for (gid = 0; gid < 4; gid++)
|
||||
{
|
||||
group[gid].trigger = (val >> (gid * 2)) & 0x3;
|
||||
/* MAYBE: interrupts already pending? */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* generic read/write */
|
||||
|
||||
static int
|
||||
decode_addr (struct hw *me,
|
||||
struct mn103int *controller,
|
||||
unsigned_word addr)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < NR_BLOCKS; i++)
|
||||
{
|
||||
if (addr >= controller->block[i].base
|
||||
&& addr <= controller->block[i].bound)
|
||||
return i;
|
||||
}
|
||||
hw_abort (me, "bad address");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct mn103int_group *
|
||||
decode_group (struct hw *me,
|
||||
struct mn103int *controller,
|
||||
unsigned_word addr)
|
||||
{
|
||||
unsigned_word offset = (addr - controller->block[ICR_BLOCK].base);
|
||||
int gid = (offset / 8) % NR_GROUPS;
|
||||
return &controller->group[gid];
|
||||
}
|
||||
|
||||
static unsigned
|
||||
mn103int_io_read_buffer (struct hw *me,
|
||||
void *dest,
|
||||
int space,
|
||||
unsigned_word base,
|
||||
unsigned nr_bytes,
|
||||
sim_cpu *processor,
|
||||
sim_cia cia)
|
||||
{
|
||||
struct mn103int *controller = hw_data (me);
|
||||
unsigned8 *buf = dest;
|
||||
unsigned byte;
|
||||
for (byte = 0; byte < nr_bytes; byte++)
|
||||
{
|
||||
unsigned_word address = base + byte;
|
||||
switch (decode_addr (me, controller, address))
|
||||
{
|
||||
case ICR_BLOCK:
|
||||
buf[byte] = read_icr (me, controller,
|
||||
decode_group (me, controller, address),
|
||||
address);
|
||||
break;
|
||||
case IAGR_BLOCK:
|
||||
buf[byte] = read_iagr (me, controller, address);
|
||||
break;
|
||||
case EXTMD_BLOCK:
|
||||
buf[byte] = read_extmd (me, controller, address);
|
||||
break;
|
||||
default:
|
||||
hw_abort (me, "bad switch");
|
||||
}
|
||||
}
|
||||
return nr_bytes;
|
||||
}
|
||||
|
||||
static unsigned
|
||||
mn103int_io_write_buffer (struct hw *me,
|
||||
const void *source,
|
||||
int space,
|
||||
unsigned_word base,
|
||||
unsigned nr_bytes,
|
||||
sim_cpu *cpu,
|
||||
sim_cia cia)
|
||||
{
|
||||
struct mn103int *controller = hw_data (me);
|
||||
const unsigned8 *buf = source;
|
||||
unsigned byte;
|
||||
for (byte = 0; byte < nr_bytes; byte++)
|
||||
{
|
||||
unsigned_word address = base + byte;
|
||||
switch (decode_addr (me, controller, address))
|
||||
{
|
||||
case ICR_BLOCK:
|
||||
write_icr (me, controller,
|
||||
decode_group (me, controller, address),
|
||||
address, buf[byte]);
|
||||
break;
|
||||
case IAGR_BLOCK:
|
||||
/* not allowed */
|
||||
break;
|
||||
case EXTMD_BLOCK:
|
||||
write_extmd (me, controller, address, buf[byte]);
|
||||
break;
|
||||
default:
|
||||
hw_abort (me, "bad switch");
|
||||
}
|
||||
}
|
||||
return nr_bytes;
|
||||
}
|
||||
|
||||
|
||||
const struct hw_device_descriptor dv_mn103int_descriptor[] = {
|
||||
{ "mn103int", mn103int_finish, },
|
||||
{ NULL },
|
||||
};
|
@ -3,6 +3,7 @@
|
||||
#if WITH_COMMON
|
||||
#include "sim-main.h"
|
||||
#include "sim-options.h"
|
||||
#include "sim-hw.h"
|
||||
#else
|
||||
#include "mn10300_sim.h"
|
||||
#endif
|
||||
@ -892,151 +893,6 @@ sim_load (sd, prog, abfd, from_tty)
|
||||
/* For compatibility */
|
||||
SIM_DESC simulator;
|
||||
|
||||
/* mn10300 interrupt model */
|
||||
|
||||
enum interrupt_type
|
||||
{
|
||||
int_reset,
|
||||
int_nmi,
|
||||
int_intov1,
|
||||
int_intp10,
|
||||
int_intp11,
|
||||
int_intp12,
|
||||
int_intp13,
|
||||
int_intcm4,
|
||||
num_int_types
|
||||
};
|
||||
|
||||
char *interrupt_names[] = {
|
||||
"reset",
|
||||
"nmi",
|
||||
"intov1",
|
||||
"intp10",
|
||||
"intp11",
|
||||
"intp12",
|
||||
"intp13",
|
||||
"intcm4",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
do_interrupt (sd, data)
|
||||
SIM_DESC sd;
|
||||
void *data;
|
||||
{
|
||||
#if 0
|
||||
char **interrupt_name = (char**)data;
|
||||
enum interrupt_type inttype;
|
||||
inttype = (interrupt_name - STATE_WATCHPOINTS (sd)->interrupt_names);
|
||||
|
||||
/* For a hardware reset, drop everything and jump to the start
|
||||
address */
|
||||
if (inttype == int_reset)
|
||||
{
|
||||
PC = 0;
|
||||
PSW = 0x20;
|
||||
ECR = 0;
|
||||
sim_engine_restart (sd, NULL, NULL, NULL_CIA);
|
||||
}
|
||||
|
||||
/* Deliver an NMI when allowed */
|
||||
if (inttype == int_nmi)
|
||||
{
|
||||
if (PSW & PSW_NP)
|
||||
{
|
||||
/* We're already working on an NMI, so this one must wait
|
||||
around until the previous one is done. The processor
|
||||
ignores subsequent NMIs, so we don't need to count them.
|
||||
Just keep re-scheduling a single NMI until it manages to
|
||||
be delivered */
|
||||
if (STATE_CPU (sd, 0)->pending_nmi != NULL)
|
||||
sim_events_deschedule (sd, STATE_CPU (sd, 0)->pending_nmi);
|
||||
STATE_CPU (sd, 0)->pending_nmi =
|
||||
sim_events_schedule (sd, 1, do_interrupt, data);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* NMI can be delivered. Do not deschedule pending_nmi as
|
||||
that, if still in the event queue, is a second NMI that
|
||||
needs to be delivered later. */
|
||||
FEPC = PC;
|
||||
FEPSW = PSW;
|
||||
/* Set the FECC part of the ECR. */
|
||||
ECR &= 0x0000ffff;
|
||||
ECR |= 0x10;
|
||||
PSW |= PSW_NP;
|
||||
PSW &= ~PSW_EP;
|
||||
PSW |= PSW_ID;
|
||||
PC = 0x10;
|
||||
sim_engine_restart (sd, NULL, NULL, NULL_CIA);
|
||||
}
|
||||
}
|
||||
|
||||
/* deliver maskable interrupt when allowed */
|
||||
if (inttype > int_nmi && inttype < num_int_types)
|
||||
{
|
||||
if ((PSW & PSW_NP) || (PSW & PSW_ID))
|
||||
{
|
||||
/* Can't deliver this interrupt, reschedule it for later */
|
||||
sim_events_schedule (sd, 1, do_interrupt, data);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* save context */
|
||||
EIPC = PC;
|
||||
EIPSW = PSW;
|
||||
/* Disable further interrupts. */
|
||||
PSW |= PSW_ID;
|
||||
/* Indicate that we're doing interrupt not exception processing. */
|
||||
PSW &= ~PSW_EP;
|
||||
/* Clear the EICC part of the ECR, will set below. */
|
||||
ECR &= 0xffff0000;
|
||||
switch (inttype)
|
||||
{
|
||||
case int_intov1:
|
||||
PC = 0x80;
|
||||
ECR |= 0x80;
|
||||
break;
|
||||
case int_intp10:
|
||||
PC = 0x90;
|
||||
ECR |= 0x90;
|
||||
break;
|
||||
case int_intp11:
|
||||
PC = 0xa0;
|
||||
ECR |= 0xa0;
|
||||
break;
|
||||
case int_intp12:
|
||||
PC = 0xb0;
|
||||
ECR |= 0xb0;
|
||||
break;
|
||||
case int_intp13:
|
||||
PC = 0xc0;
|
||||
ECR |= 0xc0;
|
||||
break;
|
||||
case int_intcm4:
|
||||
PC = 0xd0;
|
||||
ECR |= 0xd0;
|
||||
break;
|
||||
default:
|
||||
/* Should never be possible. */
|
||||
sim_engine_abort (sd, NULL, NULL_CIA,
|
||||
"do_interrupt - internal error - bad switch");
|
||||
break;
|
||||
}
|
||||
}
|
||||
sim_engine_restart (sd, NULL, NULL, NULL_CIA);
|
||||
}
|
||||
|
||||
/* some other interrupt? */
|
||||
sim_engine_abort (sd, NULL, NULL_CIA,
|
||||
"do_interrupt - internal error - interrupt %d unknown",
|
||||
inttype);
|
||||
#endif /* 0 */
|
||||
}
|
||||
|
||||
/* These default values correspond to expected usage for the chip. */
|
||||
|
||||
SIM_DESC
|
||||
@ -1047,6 +903,7 @@ sim_open (kind, cb, abfd, argv)
|
||||
char **argv;
|
||||
{
|
||||
SIM_DESC sd = sim_state_alloc (kind, cb);
|
||||
struct hw *hw;
|
||||
mn10300_callback = cb;
|
||||
|
||||
SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
|
||||
@ -1054,19 +911,20 @@ sim_open (kind, cb, abfd, argv)
|
||||
/* for compatibility */
|
||||
simulator = sd;
|
||||
|
||||
/* FIXME: should be better way of setting up interrupts */
|
||||
/* FIXME: should be better way of setting up interrupts. For
|
||||
moment, only support watchpoints causing a breakpoint (gdb
|
||||
halt). */
|
||||
STATE_WATCHPOINTS (sd)->pc = &(PC);
|
||||
STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PC);
|
||||
STATE_WATCHPOINTS (sd)->interrupt_handler = do_interrupt;
|
||||
STATE_WATCHPOINTS (sd)->interrupt_names = interrupt_names;
|
||||
STATE_WATCHPOINTS (sd)->interrupt_handler = NULL;
|
||||
STATE_WATCHPOINTS (sd)->interrupt_names = NULL;
|
||||
|
||||
if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
|
||||
return 0;
|
||||
|
||||
/* Allocate core managed memory */
|
||||
|
||||
/* "Mirror" the ROM addresses below 1MB. */
|
||||
sim_do_command (sd, "memory region 0,0x100000");
|
||||
sim_do_command (sd, "memory region 0x40000000,0x100000");
|
||||
|
||||
/* getopt will print the error message so we just have to exit if this fails.
|
||||
FIXME: Hmmm... in the case of gdb we need getopt to call
|
||||
@ -1079,6 +937,117 @@ sim_open (kind, cb, abfd, argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
hw = hw_tree_create (sd, "core");
|
||||
hw_tree_parse (hw, "/");
|
||||
if (STATE_VERBOSE_P (sd))
|
||||
hw_tree_parse (hw, "/trace? true");
|
||||
|
||||
|
||||
/* interrupt controller */
|
||||
|
||||
hw_tree_parse (hw, "/mn103int@0x34000100");
|
||||
if (STATE_VERBOSE_P (sd))
|
||||
hw_tree_parse (hw, "/mn103int/trace? true");
|
||||
hw_tree_parse (hw, "/mn103int/reg 0x34000100 0x68 0x34000200 0x8 0x3400280 0x8");
|
||||
|
||||
/* NMI input's */
|
||||
hw_tree_parse (hw, "/glue@0x30000000");
|
||||
if (STATE_VERBOSE_P (sd))
|
||||
hw_tree_parse (hw, "/glue@0x30000000/trace? true");
|
||||
hw_tree_parse (hw, "/glue@0x30000000/reg 0x30000000 16");
|
||||
hw_tree_parse (hw, "/glue@0x30000000 > int1 nmirq /mn103int");
|
||||
hw_tree_parse (hw, "/glue@0x30000000 > int2 watchdog /mn103int");
|
||||
hw_tree_parse (hw, "/glue@0x30000000 > int3 syserr /mn103int");
|
||||
|
||||
/* NMI output */
|
||||
hw_tree_parse (hw, "/mn103int > nmi int0 /glue@0x30000000");
|
||||
|
||||
/* ACK input */
|
||||
hw_tree_parse (hw, "/glue@0x30002000");
|
||||
if (STATE_VERBOSE_P (sd))
|
||||
hw_tree_parse (hw, "/glue@0x30002000/trace? true");
|
||||
hw_tree_parse (hw, "/glue@0x30002000/reg 0x30002000 4");
|
||||
hw_tree_parse (hw, "/glue@0x30002000 > int ack /mn103int");
|
||||
|
||||
/* LEVEL output */
|
||||
hw_tree_parse (hw, "/glue@0x30004000");
|
||||
if (STATE_VERBOSE_P (sd))
|
||||
hw_tree_parse (hw, "/glue@0x30004000/trace? true");
|
||||
hw_tree_parse (hw, "/glue@0x30004000/reg 0x30004000 4");
|
||||
hw_tree_parse (hw, "/mn103int > level int /glue@0x30004000");
|
||||
|
||||
/* A bunch of interrupt inputs */
|
||||
hw_tree_parse (hw, "/glue@0x30006000");
|
||||
if (STATE_VERBOSE_P (sd))
|
||||
hw_tree_parse (hw, "/glue@0x30006000/trace? true");
|
||||
hw_tree_parse (hw, "/glue@0x30006000/reg 0x30006000 16");
|
||||
hw_tree_parse (hw, "/glue@0x30006000 > int0 irq-0 /mn103int");
|
||||
hw_tree_parse (hw, "/glue@0x30006000 > int1 irq-1 /mn103int");
|
||||
hw_tree_parse (hw, "/glue@0x30006000 > int2 irq-2 /mn103int");
|
||||
hw_tree_parse (hw, "/glue@0x30006000 > int3 irq-3 /mn103int");
|
||||
|
||||
|
||||
/* processor interrupt device */
|
||||
|
||||
/* the device */
|
||||
hw_tree_parse (hw, "/mn103cpu@0x20000000");
|
||||
if (STATE_VERBOSE_P (sd))
|
||||
hw_tree_parse (hw, "/mn103cpu@0x20000000/trace? true");
|
||||
hw_tree_parse (hw, "/mn103cpu@0x20000000/reg 0x20000000 0x42");
|
||||
|
||||
/* DEBUG: ACK output wired upto a glue device */
|
||||
hw_tree_parse (hw, "/glue@0x20002000");
|
||||
if (STATE_VERBOSE_P (sd))
|
||||
hw_tree_parse (hw, "/glue@0x20002000/trace? true");
|
||||
hw_tree_parse (hw, "/glue@0x20002000/reg 0x20002000 4");
|
||||
hw_tree_parse (hw, "/mn103cpu > ack int0 /glue@0x20002000");
|
||||
|
||||
/* DEBUG: RESET/NMI/LEVEL wired up to a glue device */
|
||||
hw_tree_parse (hw, "/glue@0x20004000");
|
||||
if (STATE_VERBOSE_P (sd))
|
||||
hw_tree_parse (hw, "/glue@0x20004000/trace? true");
|
||||
hw_tree_parse (hw, "/glue@0x20004000/reg 0x20004000 12");
|
||||
hw_tree_parse (hw, "/glue@0x20004000 > int0 reset /mn103cpu");
|
||||
hw_tree_parse (hw, "/glue@0x20004000 > int1 nmi /mn103cpu");
|
||||
hw_tree_parse (hw, "/glue@0x20004000 > int2 level /mn103cpu");
|
||||
|
||||
/* The processor wired up to the real interrupt controller */
|
||||
hw_tree_parse (hw, "/mn103cpu > ack ack /mn103int");
|
||||
hw_tree_parse (hw, "/mn103int > level level /mn103cpu");
|
||||
hw_tree_parse (hw, "/mn103int > nmi nmi /mn103cpu");
|
||||
|
||||
|
||||
/* PAL */
|
||||
|
||||
/* the device */
|
||||
hw_tree_parse (hw, "/pal@0x31000000");
|
||||
if (STATE_VERBOSE_P (sd))
|
||||
hw_tree_parse (hw, "/pal@0x31000000/trace? true");
|
||||
hw_tree_parse (hw, "/pal@0x31000000/reg 0x31000000 64");
|
||||
|
||||
/* DEBUG: PAL wired up to a glue device */
|
||||
hw_tree_parse (hw, "/glue@0x31002000");
|
||||
if (STATE_VERBOSE_P (sd))
|
||||
hw_tree_parse (hw, "/glue@0x31002000/trace? true");
|
||||
hw_tree_parse (hw, "/glue@0x31002000/reg 0x31002000 16");
|
||||
hw_tree_parse (hw, "/pal@0x31000000 > countdown int0 /glue@0x31002000");
|
||||
hw_tree_parse (hw, "/pal@0x31000000 > timer int1 /glue@0x31002000");
|
||||
hw_tree_parse (hw, "/pal@0x31000000 > int int2 /glue@0x31002000");
|
||||
hw_tree_parse (hw, "/glue@0x31002000 > int0 int3 /glue@0x31002000");
|
||||
hw_tree_parse (hw, "/glue@0x31002000 > int1 int3 /glue@0x31002000");
|
||||
hw_tree_parse (hw, "/glue@0x31002000 > int2 int3 /glue@0x31002000");
|
||||
|
||||
/* The PAL wired up to the real interrupt controller */
|
||||
hw_tree_parse (hw, "/pal@0x31000000 > countdown irq-0 /mn103int");
|
||||
hw_tree_parse (hw, "/pal@0x31000000 > timer irq-1 /mn103int");
|
||||
hw_tree_parse (hw, "/pal@0x31000000 > int irq-2 /mn103int");
|
||||
|
||||
|
||||
|
||||
hw_tree_finish (hw);
|
||||
if (STATE_VERBOSE_P (sd))
|
||||
hw_tree_print (hw);
|
||||
|
||||
/* check for/establish the a reference program image */
|
||||
if (sim_analyze_program (sd,
|
||||
(STATE_PROG_ARGV (sd) != NULL
|
||||
|
Loading…
Reference in New Issue
Block a user