mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-03-25 14:01:00 +08:00
Add PowerPC simulator from Andrew Cagney <cagney@highland.com.au>
This commit is contained in:
parent
19c3fec4bf
commit
cb7a68927a
sim
.SanitizeChangeLogconfigureconfigure.in
ppc
.SanitizeCOPYINGCOPYING.LIBChangeLogMakefile.inREADME.psimbits.hconfigure.incore.ccore.hdevice_tree.cdevice_tree.hdevices.cdevices.hdouble.cdp-bit.cevents.cevents.hgen.cidecode_branch.hidecode_fields.hidecode_insn.hmemory_map.cmemory_map.hppc-endian.cppc-endian.hppc.mtsim_callbacks.hsystem.csystem.hvm.hwords.h
@ -30,6 +30,7 @@ configure
|
||||
configure.in
|
||||
h8300
|
||||
h8500
|
||||
ppc
|
||||
sh
|
||||
w65
|
||||
z8k
|
||||
|
@ -1,5 +1,29 @@
|
||||
Mon Aug 21 17:53:48 1995 Michael Meissner <meissner@tiktok.cygnus.com>
|
||||
|
||||
* configure.in (powerpc{,le}-*-*): Add psim from Andrew Cagney
|
||||
<cagney@highland.com.au>.
|
||||
* configure: Regnerate from configure.in.
|
||||
|
||||
Thu Aug 3 10:45:37 1995 Fred Fish <fnf@cygnus.com>
|
||||
|
||||
* Update all FSF addresses except those in COPYING* files.
|
||||
|
||||
Thu Jul 20 15:17:29 1995 Fred Fish <fnf@cygnus.com>
|
||||
|
||||
* Makefile.in (CC_FOR_BUILD): Define default and arrange to pass
|
||||
submakes either default or passed in value.
|
||||
|
||||
Wed Jul 5 14:32:54 1995 J.T. Conklin <jtc@rtl.cygnus.com>
|
||||
|
||||
* Makefile.in (all, clean, distclean, mostlyclean, realclean,
|
||||
install): Changed targets so that they descend all
|
||||
subdirectories in $(SUBDIRS).
|
||||
(*-all, *-clean, *-install): Removed targets.
|
||||
|
||||
* configure.in: Don't bother with target makefile fragments, they
|
||||
are no longer needed.
|
||||
* configure: regenerated.
|
||||
|
||||
* Makefile.in, configure.in: converted to autoconf.
|
||||
* configure: New file, generated with autconf 2.4.
|
||||
|
||||
|
25
sim/configure
vendored
25
sim/configure
vendored
@ -1,7 +1,7 @@
|
||||
#! /bin/sh
|
||||
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated automatically using autoconf version 2.4
|
||||
# Generated automatically using autoconf version 2.3
|
||||
# Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
|
||||
#
|
||||
# This configure script is free software; the Free Software Foundation
|
||||
@ -216,7 +216,7 @@ EOF
|
||||
verbose=yes ;;
|
||||
|
||||
-version | --version | --versio | --versi | --vers)
|
||||
echo "configure generated by autoconf version 2.4"
|
||||
echo "configure generated by autoconf version 2.3"
|
||||
exit 0 ;;
|
||||
|
||||
-with-* | --with-*)
|
||||
@ -401,7 +401,6 @@ fi
|
||||
|
||||
ac_aux_dir=
|
||||
for ac_dir in `cd $srcdir;pwd`/.. $srcdir/`cd $srcdir;pwd`/..; do
|
||||
ac_dir=`cd $ac_dir; pwd`
|
||||
if test -f $ac_dir/install-sh; then
|
||||
ac_aux_dir=$ac_dir
|
||||
ac_install_sh="$ac_aux_dir/install-sh -c"
|
||||
@ -533,6 +532,8 @@ case "${target}" in
|
||||
h8300*-*-*) sim_target=h8300 ;;
|
||||
h8500-*-*) sim_target=h8500 ;;
|
||||
sh*-*-*) sim_target=sh ;;
|
||||
powerpc-*-*) sim_target=ppc ;;
|
||||
powerpcle-*-*) sim_target=ppc ;;
|
||||
w65-*-*) sim_target=w65 ;;
|
||||
z8k*-*-*) sim_target=z8k ;;
|
||||
*) sim_target=none ;;
|
||||
@ -542,19 +543,6 @@ configdirs=${sim_target}
|
||||
subdirs="$configdirs"
|
||||
|
||||
|
||||
if test ! -f ${srcdir}/${sim_target}/${sim_target}.mt ; then
|
||||
target_makefile_frag=/dev/null
|
||||
else
|
||||
target_makefile_frag=${srcdir}/${sim_target}/${sim_target}.mt
|
||||
fi
|
||||
|
||||
frags=
|
||||
if test $target_makefile_frag != /dev/null; then
|
||||
frags="$frags $target_makefile_frag"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
trap '' 1 2 15
|
||||
cat > confcache <<\EOF
|
||||
# This file is a shell script that caches the results of configure
|
||||
@ -643,7 +631,7 @@ do
|
||||
echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
|
||||
exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
|
||||
-version | --version | --versio | --versi | --vers | --ver | --ve | --v)
|
||||
echo "$CONFIG_STATUS generated by autoconf version 2.4"
|
||||
echo "$CONFIG_STATUS generated by autoconf version 2.3"
|
||||
exit 0 ;;
|
||||
-help | --help | --hel | --he | --h)
|
||||
echo "\$ac_cs_usage"; exit 0 ;;
|
||||
@ -685,9 +673,6 @@ s%@build_cpu@%$build_cpu%g
|
||||
s%@build_vendor@%$build_vendor%g
|
||||
s%@build_os@%$build_os%g
|
||||
s%@subdirs@%$subdirs%g
|
||||
/@target_makefile_frag@/r $target_makefile_frag
|
||||
s%@target_makefile_frag@%%g
|
||||
s%@frags@%$frags%g
|
||||
|
||||
CEOF
|
||||
EOF
|
||||
|
@ -16,6 +16,8 @@ case "${target}" in
|
||||
h8300*-*-*) sim_target=h8300 ;;
|
||||
h8500-*-*) sim_target=h8500 ;;
|
||||
sh*-*-*) sim_target=sh ;;
|
||||
powerpc-*-*) sim_target=ppc ;;
|
||||
powerpcle-*-*) sim_target=ppc ;;
|
||||
w65-*-*) sim_target=w65 ;;
|
||||
z8k*-*-*) sim_target=z8k ;;
|
||||
*) sim_target=none ;;
|
||||
|
85
sim/ppc/.Sanitize
Normal file
85
sim/ppc/.Sanitize
Normal file
@ -0,0 +1,85 @@
|
||||
# .Sanitize for devo/sim/ppc.
|
||||
|
||||
# Each directory to survive it's way into a release will need a file
|
||||
# like this one called "./.Sanitize". All keyword lines must exist,
|
||||
# and must exist in the order specified by this file. Each directory
|
||||
# in the tree will be processed, top down, in the following order.
|
||||
|
||||
# Hash started lines like this one are comments and will be deleted
|
||||
# before anything else is done. Blank lines will also be squashed
|
||||
# out.
|
||||
|
||||
# The lines between the "Do-first:" line and the "Things-to-keep:"
|
||||
# line are executed as a /bin/sh shell script before anything else is
|
||||
# done in this
|
||||
|
||||
Do-first:
|
||||
|
||||
# All files listed between the "Things-to-keep:" line and the
|
||||
# "Files-to-sed:" line will be kept. All other files will be removed.
|
||||
# Directories listed in this section will have their own Sanitize
|
||||
# called. Directories not listed will be removed in their entirety
|
||||
# with rm -rf.
|
||||
|
||||
Things-to-keep:
|
||||
|
||||
COPYING
|
||||
COPYING.LIB
|
||||
ChangeLog
|
||||
Makefile.in
|
||||
README.psim
|
||||
basics.h
|
||||
bits.c
|
||||
bits.h
|
||||
configure
|
||||
configure.in
|
||||
core.c
|
||||
core.h
|
||||
cpu.c
|
||||
cpu.h
|
||||
debug.c
|
||||
debug.h
|
||||
device_tree.c
|
||||
device_tree.h
|
||||
devices.c
|
||||
devices.h
|
||||
double.c
|
||||
dp-bit.c
|
||||
events.c
|
||||
events.h
|
||||
gen.c
|
||||
idecode_branch.h
|
||||
idecode_expression.h
|
||||
idecode_fields.h
|
||||
idecode_insn.h
|
||||
inline.c
|
||||
inline.h
|
||||
interrupts.c
|
||||
interrupts.h
|
||||
main.c
|
||||
memory_map.c
|
||||
memory_map.h
|
||||
ppc-endian.c
|
||||
ppc-endian.h
|
||||
ppc-instructions
|
||||
ppc-spr-table
|
||||
ppc.mt
|
||||
psim.c
|
||||
psim.h
|
||||
registers.c
|
||||
registers.h
|
||||
sim_callbacks.h
|
||||
sim_calls.c
|
||||
std-config.h
|
||||
system.c
|
||||
system.h
|
||||
vm.c
|
||||
vm.h
|
||||
words.h
|
||||
|
||||
Things-to-lose:
|
||||
|
||||
|
||||
Do-last:
|
||||
|
||||
# End of file.
|
339
sim/ppc/COPYING
Normal file
339
sim/ppc/COPYING
Normal file
@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
675 Mass Ave, Cambridge, MA 02139, USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Appendix: How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
|
||||
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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
481
sim/ppc/COPYING.LIB
Normal file
481
sim/ppc/COPYING.LIB
Normal file
@ -0,0 +1,481 @@
|
||||
GNU LIBRARY GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1991 Free Software Foundation, Inc.
|
||||
675 Mass Ave, Cambridge, MA 02139, USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the library GPL. It is
|
||||
numbered 2 because it goes with version 2 of the ordinary GPL.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Library General Public License, applies to some
|
||||
specially designated Free Software Foundation software, and to any
|
||||
other libraries whose authors decide to use it. You can use it for
|
||||
your libraries, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if
|
||||
you distribute copies of the library, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link a program with the library, you must provide
|
||||
complete object files to the recipients so that they can relink them
|
||||
with the library, after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
Our method of protecting your rights has two steps: (1) copyright
|
||||
the library, and (2) offer you this license which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
Also, for each distributor's protection, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
library. If the library is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original
|
||||
version, so that any problems introduced by others will not reflect on
|
||||
the original authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that companies distributing free
|
||||
software will individually obtain patent licenses, thus in effect
|
||||
transforming the program into proprietary software. To prevent this,
|
||||
we have made it clear that any patent must be licensed for everyone's
|
||||
free use or not licensed at all.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the ordinary
|
||||
GNU General Public License, which was designed for utility programs. This
|
||||
license, the GNU Library General Public License, applies to certain
|
||||
designated libraries. This license is quite different from the ordinary
|
||||
one; be sure to read it in full, and don't assume that anything in it is
|
||||
the same as in the ordinary license.
|
||||
|
||||
The reason we have a separate public license for some libraries is that
|
||||
they blur the distinction we usually make between modifying or adding to a
|
||||
program and simply using it. Linking a program with a library, without
|
||||
changing the library, is in some sense simply using the library, and is
|
||||
analogous to running a utility program or application program. However, in
|
||||
a textual and legal sense, the linked executable is a combined work, a
|
||||
derivative of the original library, and the ordinary General Public License
|
||||
treats it as such.
|
||||
|
||||
Because of this blurred distinction, using the ordinary General
|
||||
Public License for libraries did not effectively promote software
|
||||
sharing, because most developers did not use the libraries. We
|
||||
concluded that weaker conditions might promote sharing better.
|
||||
|
||||
However, unrestricted linking of non-free programs would deprive the
|
||||
users of those programs of all benefit from the free status of the
|
||||
libraries themselves. This Library General Public License is intended to
|
||||
permit developers of non-free programs to use free libraries, while
|
||||
preserving your freedom as a user of such programs to change the free
|
||||
libraries that are incorporated in them. (We have not seen how to achieve
|
||||
this as regards changes in header files, but we have achieved it as regards
|
||||
changes in the actual functions of the Library.) The hope is that this
|
||||
will lead to faster development of free libraries.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, while the latter only
|
||||
works together with the library.
|
||||
|
||||
Note that it is possible for a library to be covered by the ordinary
|
||||
General Public License rather than by this special one.
|
||||
|
||||
GNU LIBRARY GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library which
|
||||
contains a notice placed by the copyright holder or other authorized
|
||||
party saying it may be distributed under the terms of this Library
|
||||
General Public License (also called "this License"). Each licensee is
|
||||
addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also compile or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
c) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
d) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the source code distributed need not include anything that is normally
|
||||
distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Library General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Appendix: How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
81
sim/ppc/ChangeLog
Normal file
81
sim/ppc/ChangeLog
Normal file
@ -0,0 +1,81 @@
|
||||
Tue Aug 22 09:31:18 1995 Michael Meissner <meissner@tiktok.cygnus.com>
|
||||
|
||||
* system.c (system_call): Add read support.
|
||||
|
||||
* main.c (main): -t sets trace_device_tree. Correct usage message
|
||||
to current reality.
|
||||
|
||||
* device_tree.c (update_memory_node_for_section): Make tracing
|
||||
output line up. If not code or readonly, assume that the section
|
||||
is a data section and has read/write permissions. Add readonly
|
||||
support.
|
||||
|
||||
* core.c (create_core_from_addresses): Print end address in traces
|
||||
and make tracing output line up.
|
||||
|
||||
* Makefile.in: Rewrite from Makefile to work with the Cygnus
|
||||
environment, and support compiling in a different directory than
|
||||
the sources reside in.
|
||||
|
||||
* ppc-endian.h: Rename from endian.h so that it doesn't get
|
||||
confused with /usr/include/sys/endian.h on Linux. Add Linux
|
||||
endian support.
|
||||
|
||||
* ppc-endian.c: Rename to be consistant with ppc-endian.h.
|
||||
Include ppc-endian.h, not endian.h.
|
||||
|
||||
* basics.h (sysdep.h): Include sysdep.h that configure makes.
|
||||
Include ppc-endian.h, not endian.h.
|
||||
|
||||
* std-config.h: Rename from ppc-config. Put #ifndefs around most
|
||||
configuration macros, so they can be overridden via CFLAGS. By
|
||||
default, turn off tracing.
|
||||
|
||||
* configure.in: Clone from other simulator targets.
|
||||
* configure: Generate via autoconf from configure.in.
|
||||
|
||||
Sat Aug 19 09:05:32 1995 Andrew Cagney - aka Noid <cagney@kremvax>
|
||||
|
||||
* ppc-instructions: fix srawi (was geting XER[CA] real wrong).
|
||||
|
||||
* interrupts.c (data_storage_interrupt): allow stack to grow by
|
||||
upto one MB per increment.
|
||||
|
||||
* ppc-instructions: divw was computing rA / rA not rA / rB
|
||||
|
||||
* main.c (main): really stupid. Wasn't exiting with correct status
|
||||
|
||||
Fri Aug 18 00:38:01 1995 Andrew Cagney - aka Noid <cagney@kremvax>
|
||||
|
||||
* system.c (system_call): add system calls kill(2) and getpid(2).
|
||||
|
||||
* main.c (main): Check/return exit status when simulation
|
||||
finishes.
|
||||
|
||||
Thu Aug 17 14:29:18 1995 Andrew Cagney <cagney@kremvax>
|
||||
|
||||
* device_tree.c (create_option_device_node): Alignment rules (at
|
||||
least for the moment) now are for strict alignment only for LE OEA
|
||||
mode. (Because of compiler problems).
|
||||
|
||||
* system.c (system_call) SYS_exit: Wasn't exiting with correct status.
|
||||
|
||||
Thu Aug 17 01:16:38 1995 Andrew Cagney - aka Noid <cagney@kremvax>
|
||||
|
||||
* vm.c (DEFINE_VM_DATA_MAP_WRITE_N): For miss aligned transfer
|
||||
forgot to return.
|
||||
|
||||
* system.c (system_call): didn't page align break argument before
|
||||
determining increment break increment.
|
||||
|
||||
* psim/ppc: Re-arange entire directory structure so that
|
||||
everything lives in the one directory. While a pain for cleaning,
|
||||
makes building across multiple architectures much simpler.
|
||||
|
||||
* devices.c, device_tree.c: Added code that provides a simple
|
||||
illustration of how an interrupt control device could be
|
||||
implemented.
|
||||
|
||||
* devices.c: Added code so that the dumb console device can read
|
||||
(from stdin) as well as write to stdout.
|
||||
|
297
sim/ppc/Makefile.in
Normal file
297
sim/ppc/Makefile.in
Normal file
@ -0,0 +1,297 @@
|
||||
#
|
||||
# This file is part of the program psim.
|
||||
#
|
||||
# Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# 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.
|
||||
#
|
||||
|
||||
VPATH = @srcdir@
|
||||
srcdir = @srcdir@
|
||||
srcroot = $(srcdir)/../..
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
||||
host_alias = @host_alias@
|
||||
target_alias = @target_alias@
|
||||
program_transform_name = @program_transform_name@
|
||||
bindir = $(exec_prefix)/bin
|
||||
libdir = $(exec_prefix)/lib
|
||||
tooldir = $(libdir)/$(target_alias)
|
||||
|
||||
datadir = $(prefix)/lib
|
||||
mandir = $(prefix)/man
|
||||
man1dir = $(mandir)/man1
|
||||
man2dir = $(mandir)/man2
|
||||
man3dir = $(mandir)/man3
|
||||
man4dir = $(mandir)/man4
|
||||
man5dir = $(mandir)/man5
|
||||
man6dir = $(mandir)/man6
|
||||
man7dir = $(mandir)/man7
|
||||
man8dir = $(mandir)/man8
|
||||
man9dir = $(mandir)/man9
|
||||
infodir = $(prefix)/info
|
||||
includedir = $(prefix)/include
|
||||
docdir = $(datadir)/doc
|
||||
|
||||
SHELL = /bin/sh
|
||||
|
||||
# FIXME: use autoconf's AC_PROG_INSTALL
|
||||
INSTALL = $(srcroot)/install.sh -c
|
||||
INSTALL_PROGRAM = $(INSTALL)
|
||||
INSTALL_DATA = $(INSTALL)
|
||||
INSTALL_XFORM = $(INSTALL) -t='$(program_transform_name)'
|
||||
INSTALL_XFORM1= $(INSTALL_XFORM) -b=.1
|
||||
|
||||
AR = ar
|
||||
AR_FLAGS = rc
|
||||
CFLAGS = -g
|
||||
BISON = bison
|
||||
MAKEINFO = makeinfo
|
||||
RANLIB = ranlib
|
||||
|
||||
.NOEXPORT:
|
||||
MAKEOVERRIDES=
|
||||
|
||||
LIB_INCLUDES = -I$(srcdir)/../../include
|
||||
BFD_INCLUDES = -I../../bfd -I$(srcdir)/../../bfd
|
||||
GDB_INCLUDES = -I../../gdb -I$(srcdir)/../../gdb -I$(srcdir)/../../gdb/config -I$(srcdir)/../../mmalloc
|
||||
INCLUDES = -I. -I$(srcdir) $(LIB_INCLUDES) $(BFD_INCLUDES) $(GDB_INCLUDES)
|
||||
|
||||
CONFIG_FILE = std-config.h
|
||||
|
||||
LIBIBERTY_LIB = ../../libiberty/libiberty.a
|
||||
BFD_LIB = ../../bfd/libbfd.a
|
||||
|
||||
#### Makefile fragments come in here.
|
||||
# @host_makefile_frag@
|
||||
###
|
||||
|
||||
TARGETLIB = libsim.a
|
||||
|
||||
all: run libsim.a $(GDB_OBJ)
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $(HDEFINES) $(TDEFINES) $(INCLUDES) $<
|
||||
|
||||
|
||||
|
||||
BASICS_H = \
|
||||
sysdep.h \
|
||||
config.h \
|
||||
words.h \
|
||||
ppc-endian.h \
|
||||
debug.h \
|
||||
bits.h \
|
||||
sim_callbacks.h
|
||||
|
||||
PSIM_H = \
|
||||
psim.h \
|
||||
$(BASICS_H)
|
||||
|
||||
IDECODE_H = \
|
||||
idecode.h \
|
||||
idecode_insn.h \
|
||||
idecode_expression.h \
|
||||
idecode_branch.h \
|
||||
idecode_fields.h \
|
||||
icache.h
|
||||
|
||||
REGISTERS_H = \
|
||||
registers.h \
|
||||
spreg.h
|
||||
|
||||
CPU_H = \
|
||||
cpu.h \
|
||||
$(BASICS_H) \
|
||||
$(REGISTERS_H) \
|
||||
device_tree.h \
|
||||
memory_map.h \
|
||||
core.h \
|
||||
vm.h \
|
||||
events.h \
|
||||
interrupts.h \
|
||||
psim.h \
|
||||
icache.h
|
||||
|
||||
|
||||
INLINE = \
|
||||
inline.h \
|
||||
inline.c
|
||||
|
||||
BUILT_SRC = \
|
||||
icache.h \
|
||||
idecode.h idecode.c \
|
||||
semantics.h semantics.c \
|
||||
spreg.h spreg.c \
|
||||
config.h
|
||||
|
||||
LIB_SRC = \
|
||||
psim.c \
|
||||
bits.c \
|
||||
ppc-endian.c \
|
||||
debug.c \
|
||||
memory_map.c \
|
||||
vm.c \
|
||||
core.c \
|
||||
events.c \
|
||||
system.c \
|
||||
registers.c \
|
||||
cpu.c \
|
||||
interrupts.c \
|
||||
devices.c \
|
||||
device_tree.c
|
||||
|
||||
MAIN_SRC = \
|
||||
main.c \
|
||||
sim_calls.c
|
||||
|
||||
|
||||
LIB_OBJ = \
|
||||
debug.o \
|
||||
bits.o \
|
||||
ppc-endian.o \
|
||||
system.o \
|
||||
registers.o \
|
||||
memory_map.o \
|
||||
vm.o \
|
||||
core.o \
|
||||
spreg.o \
|
||||
cpu.o \
|
||||
interrupts.o \
|
||||
events.o \
|
||||
devices.o \
|
||||
device_tree.o \
|
||||
semantics.o \
|
||||
idecode.o \
|
||||
psim.o
|
||||
|
||||
|
||||
GDB_OBJ = sim_calls.o
|
||||
|
||||
|
||||
psim: libsim.a main.o $(LIBIBERTY_LIB) $(BFD_LIB) $(LIBS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o psim main.o libsim.a $(BFD_LIB) $(LIBIBERTY_LIB) $(LIBS)
|
||||
|
||||
run: psim
|
||||
rm -f run
|
||||
ln psim run
|
||||
|
||||
libsim.a: $(BUILT_SRC) $(LIB_OBJ) $(GDB_OBJ)
|
||||
rm -f $(TARGETLIB)
|
||||
$(AR) $(AR_FLAGS) $(TARGETLIB) $(LIB_OBJ) $(GDB_OBJ)
|
||||
$(RANLIB) $(TARGETLIB)
|
||||
|
||||
psim.o: psim.c psim.h $(CPU_H) $(IDECODE_H) $(INLINE)
|
||||
|
||||
bits.o: bits.c bits.h
|
||||
|
||||
debug.o: debug.c $(BASICS_H)
|
||||
|
||||
ppc-endian.o: ppc-endian.c ppc-endian.h \
|
||||
config.h words.h sim_callbacks.h
|
||||
|
||||
system.o: system.c system.h $(CPU_H) $(IDECODE_H)
|
||||
|
||||
registers.o: registers.c $(REGISTERS_H) $(BASICS_H)
|
||||
|
||||
cpu.o: cpu.c $(CPU_H) $(IDECODE_H)
|
||||
|
||||
interrupts.o: interrupts.c $(CPU_H) $(IDECODE_H) system.h
|
||||
|
||||
idecode.o: idecode.c $(CPU_H) $(IDECODE_H) semantics.h
|
||||
|
||||
memory_map.o: memory_map.c memory_map.h $(BASICS_H) device_tree.h interrupts.h
|
||||
|
||||
# double.o: double.c dp-bit.c
|
||||
|
||||
vm.o: vm.c vm.h $(BASICS_H) $(REGISTERS_H) \
|
||||
device_tree.h memory_map.h core.h interrupts.h
|
||||
|
||||
core.o: core.c core.h $(BASICS_H) \
|
||||
device_tree.h memory_map.h
|
||||
|
||||
events.o: events.c events.h $(BASICS_H)
|
||||
|
||||
sim_calls.o: sim_calls.c $(PSIM_H) ../../gdb/tm.h devices.h
|
||||
|
||||
spreg.o: spreg.h spreg.c words.h
|
||||
|
||||
main.o: main.c $(PSIM_H)
|
||||
|
||||
devices.o: devices.c devices.h $(BASICS_H) \
|
||||
device_tree.h events.h
|
||||
|
||||
device_tree.o: device_tree.c device_tree.h devices.h $(BASICS_H)
|
||||
|
||||
semantics.o: semantics.c semantics.h $(CPU_H) $(IDECODE_H)
|
||||
|
||||
|
||||
#
|
||||
# Rules to create the built c source code files
|
||||
#
|
||||
|
||||
config.h: $(CONFIG_FILE)
|
||||
cp $(srcdir)/$(CONFIG_FILE) config.h
|
||||
|
||||
|
||||
tmp-gencode: gen ppc-instructions ppc-spr-table $(srcdir)/../../move-if-change
|
||||
./gen -r $(srcdir)/ppc-spr-table \
|
||||
-P tmp-spreg.h \
|
||||
-p tmp-spreg.c \
|
||||
-i $(srcdir)/ppc-instructions \
|
||||
-C tmp-icache.h \
|
||||
-S tmp-semantics.h \
|
||||
-s tmp-semantics.c \
|
||||
-D tmp-idecode.h \
|
||||
-d tmp-idecode.c
|
||||
$(srcdir)/../../move-if-change tmp-icache.h icache.h
|
||||
$(srcdir)/../../move-if-change tmp-idecode.h idecode.h
|
||||
$(srcdir)/../../move-if-change tmp-idecode.c idecode.c
|
||||
$(srcdir)/../../move-if-change tmp-semantics.h semantics.h
|
||||
$(srcdir)/../../move-if-change tmp-semantics.c semantics.c
|
||||
$(srcdir)/../../move-if-change tmp-spreg.h spreg.h
|
||||
$(srcdir)/../../move-if-change tmp-spreg.c spreg.c
|
||||
touch tmp-gencode
|
||||
|
||||
icache.h idecode.h idecode.c semantics.h semantics.c spreg.h spreg.c: tmp-gencode
|
||||
|
||||
gen.o: gen.c config.h
|
||||
|
||||
gen: gen.o config.h $(LIBIBERTY_LIB) $(LIBS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o gen gen.o $(LIBIBERTY_LIB) $(LIBS)
|
||||
|
||||
#
|
||||
|
||||
tags etags: TAGS
|
||||
|
||||
TAGS: tmp-gencode config.h
|
||||
etags $(srcdir)/*.h $(srcdir)/*.c $(BUILT_SRC)
|
||||
|
||||
clean:
|
||||
rm -f tmp-* *.[oas] core psim run gen
|
||||
|
||||
distclean mostlyclean realclean: clean
|
||||
rm -f TAGS $(BUILT_SRC) Makefile config.cache config.log config.status
|
||||
|
||||
Makefile: Makefile.in config.status @frags@
|
||||
$(SHELL) ./config.status
|
||||
|
||||
config.status: configure
|
||||
$(SHELL) ./config.status --recheck
|
||||
|
||||
install:
|
||||
echo Install psim ...
|
253
sim/ppc/README.psim
Normal file
253
sim/ppc/README.psim
Normal file
@ -0,0 +1,253 @@
|
||||
|
||||
PSIM
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
This directory contains the program PSIM that models the PowerPC
|
||||
architecture. It can either be run stand alone (psim) or linked with
|
||||
GDB.
|
||||
|
||||
|
||||
CONTENTS:
|
||||
|
||||
psim-*.tar:
|
||||
|
||||
psim-sim-*.tar.gz simulator source code
|
||||
|
||||
psim-test-*.tar.gz test directory for simulator
|
||||
|
||||
psim-gdb-*.diff.gz patches to integrated psim
|
||||
into gdb
|
||||
|
||||
gnu-*.tar:
|
||||
|
||||
gnu-gdb-*.diff.gz patches to gdb that may have
|
||||
already been merged into the
|
||||
GDB source tree.
|
||||
|
||||
gnu-*-*.diff.gz Other noise
|
||||
|
||||
|
||||
BUILDING:
|
||||
|
||||
o Install flex, bison, gnu-make, native gcc and probably also byacc.
|
||||
|
||||
|
||||
o First you will need a fairly current copy of GDB (try the ftp site
|
||||
ftp.cygnus.com:pub). I've built it with a beta version of gdb-4.15.
|
||||
|
||||
Unpack gdb vis:
|
||||
|
||||
$ gunzip < gdb-4.15.tar.gz | tar xf -
|
||||
|
||||
|
||||
o Apply any patches that haven't yet been merged into the GDB source
|
||||
tree.
|
||||
|
||||
$ cd gdb-4.15
|
||||
$ gunzip < ../psim-gdb-*.diff.gz | patch -p1
|
||||
$ gunzip < ../gnu-gdb-*.diff.gz | patch -p1
|
||||
|
||||
|
||||
o Unpack the psim source code (and optionally the test directory)
|
||||
|
||||
$ cd gdb-4.15
|
||||
$ gunzip < ../psim-sim-*.tar.gz | tar xvf -
|
||||
$ gunzip < ../psim-test-*.tar.gz | tar xvf -
|
||||
|
||||
|
||||
o Configure gdb as per normal. I use something along the lines of:
|
||||
|
||||
$ cd gdb-4.15
|
||||
$ CC=gcc ./configure --target=powerpcle-unknown-eabi
|
||||
|
||||
|
||||
o Build your entire gdb tree as per normal. Something along the
|
||||
lines of:
|
||||
|
||||
$ cd gdb-4.15
|
||||
$ make CC=gcc
|
||||
.
|
||||
.
|
||||
.
|
||||
|
||||
|
||||
|
||||
o Install it it all as per normal. Something along the lines of:
|
||||
|
||||
$ cd gdb-4.15
|
||||
$ make CC=gcc install
|
||||
|
||||
The program sim/ppc/psim is not installed.
|
||||
|
||||
|
||||
RUNNING:
|
||||
|
||||
PSIM can either be run as a stand alone program or as part
|
||||
of gdb. The psim-test archive contains pre-compiled and
|
||||
linked programs that can be run on PSIM. The notes below
|
||||
assume that you have unpacked that tar archive.
|
||||
|
||||
To rebuild the archive you will need to obtain a working
|
||||
version of an ELF compiler/linker for the PowerPC.
|
||||
|
||||
Example of running PSIM:
|
||||
|
||||
Print out the users environment:
|
||||
|
||||
$ sim/ppc/psim sim/ppc/test/envp
|
||||
|
||||
Print out the arguments:
|
||||
|
||||
$ sim/ppc/psim sim/ppc/test/argv a b c
|
||||
|
||||
Check the OEA model:
|
||||
|
||||
$ sim/ppc/psim sim/ppc/test/interrupt
|
||||
|
||||
Check that sbrk works
|
||||
|
||||
$ sim/ppc/psim sim/ppc/test/break
|
||||
|
||||
Try for speed. The program count contains a loop
|
||||
of two instructions which is looped <arg> times.
|
||||
See later for how to make PSIM run 10-100 times
|
||||
faster.
|
||||
|
||||
$ time sim/ppc/sim sim/ppc/test/count 5000000
|
||||
$ expr 10 \* 1000 \* 1000 / <seconds>
|
||||
|
||||
|
||||
Example of running GDB:
|
||||
|
||||
The most important thing to be aware of is the fact
|
||||
that before the simulator is used, the user must attach
|
||||
to it (target sim) and than load the executable (load count).
|
||||
|
||||
$ cd sim/ppc/test
|
||||
$ powerpc-unknown-eabi-gdb count
|
||||
(gdb) target sim
|
||||
(gdb) load count
|
||||
(gdb) break main
|
||||
(gdb) run
|
||||
.
|
||||
.
|
||||
.
|
||||
|
||||
|
||||
CONFIGURATION: Making it go faster
|
||||
|
||||
See the file sim/ppc/config.h (a.k.a. sim/ppc/data/ppc-config)
|
||||
for notes.
|
||||
|
||||
|
||||
KNOWN FEATURES
|
||||
|
||||
SMP, dual-endian, VEA and OEA models, hardware devices
|
||||
(console, icu, reset) ...
|
||||
|
||||
|
||||
KNOWN PROBLEMS:
|
||||
|
||||
Configuration could be better.
|
||||
|
||||
HTAB (page) code for OEA model untested. Some of the vm code
|
||||
instructions unimplemented.
|
||||
|
||||
Doesn't detect/handle changing endian bits. In fact they are
|
||||
ignored.
|
||||
|
||||
Return from interrupt instruction unimplemented.
|
||||
|
||||
Flush instruction cache instructions do nothing. Perhaphs they
|
||||
should (if there is an instruction cache) flush it.
|
||||
|
||||
PowerOpen VEA model (a.k.a XCOFF a.k.a AIX) broken. It was
|
||||
working but that is before I changed the create stack frame
|
||||
code into an ELF version.
|
||||
|
||||
OpenBoot and PR*P interfaces missing. Open boot could be
|
||||
implemented by putting special instructions at the address
|
||||
of the OpenBoot callback functions. Those instructions
|
||||
could than emulate OpenBoot behavour.
|
||||
|
||||
VEA memory read/write performance could be improved by merging
|
||||
the data sections.
|
||||
|
||||
When reading in a VEA executable, the binaries text and data
|
||||
sections are not made page aligned.
|
||||
|
||||
Missing or commented out instructions.
|
||||
|
||||
Lack of floating point support.
|
||||
[workaround: build everything using -msoft-float]
|
||||
|
||||
64bit untested.
|
||||
|
||||
Event code for pending events from signal handlers not
|
||||
finished/tested.
|
||||
|
||||
Better and more devices.
|
||||
|
||||
Only two device trees VEA and OEA (clayton) and those hard coded.
|
||||
Should be possible to specify a file containing a device tree
|
||||
description as the program to run. At present it a device tree
|
||||
file is detected causing psim to abort.
|
||||
|
||||
I wonder if I've got my ppc.instructions copyright
|
||||
notice correct.
|
||||
|
||||
|
||||
THANKS:
|
||||
|
||||
Thanks go to the following who each helped in some way.
|
||||
|
||||
Allen Briggs, Bett Koch, David Edelsohn,
|
||||
Michael Meissner, Bob Mercier, Richard Perini,
|
||||
Richard Stallman, Mitchele Walker
|
||||
|
||||
|
||||
----------------------------------------------------------------
|
||||
|
||||
|
||||
Random notes on performance:
|
||||
|
||||
|
||||
$ cd test
|
||||
time ../psim count `expr 10000000 / 2`
|
||||
time ../psim volatile-count `expr 10000000 / 7`
|
||||
|
||||
Where 2 and 7 are the number of instructions in the main loop.
|
||||
|
||||
|
||||
611/729 - baseline
|
||||
|
||||
Tests:
|
||||
|
||||
CFLAGS= -c -O2 -m486 -fomit-frame-pointer
|
||||
|
||||
o different first/second level table/switch combinations
|
||||
|
||||
0 - use a table
|
||||
1 - use a simple switch
|
||||
2 - use an expanded switch
|
||||
|
||||
i486DX4/100 - AMD
|
||||
|
||||
1/108/140 - switch=0/0/0,expand=2,inline=2,nia=1,cache=1
|
||||
1/114/140 - switch=0/0/0,expand=2,inline=2,nia=1,cache=1
|
||||
1/137/149 - switch=0/0,expand=2,inline=1,nia=1,cache=1
|
||||
1/144/155 - switch=2/1,expand=2,inline=1,nia=1,cache=1
|
||||
1/153/159 - switch=2/1,expand=0,inline=1,nia=1,cache=1
|
||||
1/185/189 - switch=0/0,expand=0,inline=1,nia=1
|
||||
|
||||
i486DX2/66
|
||||
|
||||
1/572/695 - switch=1/1,expand=0,inline=0
|
||||
1/579/729 - switch=0/0,expand=0,inline=0
|
||||
1/570/682 - switch=2/2,expand=0,inline=0
|
||||
1/431/492 - switch=0/0,expand=0,inline=1,nia=0
|
||||
1/271/292 - switch=2/1,expand=0,inline=1,nia=0
|
||||
1/270/316 - switch=2/2,expand=0,inline=1,nia=0
|
||||
1/271/281 - switch=1/1,expand=0,inline=1,nia=1
|
||||
1/267/274 - switch=2/1,expand=0,inline=1,nia=1
|
194
sim/ppc/bits.h
Normal file
194
sim/ppc/bits.h
Normal file
@ -0,0 +1,194 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _BITS_H_
|
||||
#define _BITS_H_
|
||||
|
||||
/* bit manipulation routines:
|
||||
|
||||
Bit numbering: The bits are numbered according to the PowerPC
|
||||
convention - the left most (or most significant) is bit 0 while the
|
||||
right most (least significant) is bit 1.
|
||||
|
||||
Size convention: Each macro is in three forms - <MACRO>32 which
|
||||
operates in 32bit quantity (bits are numbered 0..31); <MACRO>64
|
||||
which operates using 64bit quantites (and bits are numbered 0..64);
|
||||
and <MACRO> which operates using the bit size of the target
|
||||
architecture (bits are still numbered 0..63), with 32bit
|
||||
architectures ignoring the first 32bits having bit 32 as the most
|
||||
significant.
|
||||
|
||||
BIT*(POS): Quantity with just 1 bit set.
|
||||
|
||||
MASK*(FIRST, LAST): Create a constant bit mask of the specified
|
||||
size with bits [FIRST .. LAST] set.
|
||||
|
||||
MASKED*(VALUE, FIRST, LAST): Masks out all but bits [FIRST
|
||||
.. LAST].
|
||||
|
||||
EXTRACTED*(VALUE, FIRST, LAST): Masks out bits [FIRST .. LAST] but
|
||||
also right shifts the masked value so that bit LAST becomes the
|
||||
least significant (right most).
|
||||
|
||||
SHUFFLE*(VALUE, OLD, NEW): Moves things around so that bit pos OLD
|
||||
is extracted and than moved to bit pos NEW.
|
||||
|
||||
|
||||
|
||||
IEA_MASKED(SHOULD_MASK, ADDR): Convert the address to the targets
|
||||
natural size. If in 32bit mode, discard the high 32bits.
|
||||
|
||||
EXTENDED(VALUE): Convert VALUE (32bits of it) to the targets
|
||||
natural size. If in 64bit mode, sign extend the value.
|
||||
|
||||
*/
|
||||
|
||||
/* Bit operators */
|
||||
#define BIT4(POS) (1 << _MAKE_SHIFT(4, POS))
|
||||
#define BIT5(POS) (1 << _MAKE_SHIFT(5, POS))
|
||||
#define BIT10(POS) (1 << _MAKE_SHIFT(10, POS))
|
||||
#define BIT32(POS) _BITn(32, POS)
|
||||
#define BIT64(POS) _BITn(64, POS)
|
||||
|
||||
#if (WITH_64BIT_TARGET)
|
||||
#define BIT(POS) BIT64(POS)
|
||||
#else
|
||||
#define BIT(POS) (((POS) < 32) ? 0 : _BITn(32, (POS)-32))
|
||||
#endif
|
||||
|
||||
|
||||
/* multi bit mask */
|
||||
|
||||
#define MASK32(START, STOP) _MASKn(32, START, STOP)
|
||||
#define MASK64(START, STOP) _MASKn(64, START, STOP)
|
||||
|
||||
#if (WITH_64BIT_TARGET)
|
||||
#define MASK(START, STOP) (((START) <= (STOP)) \
|
||||
? _MASKn(64, START, STOP) \
|
||||
: (_MASKn(64, 0, STOP) \
|
||||
| _MASKn(64, START, 63)))
|
||||
#else
|
||||
#define MASK(START, STOP) (((START) <= (STOP)) \
|
||||
? (((STOP) < 32) \
|
||||
? 0 \
|
||||
: _MASKn(32, \
|
||||
(START) < 32 ? 0 : (START) - 32, \
|
||||
(STOP)-32)) \
|
||||
: (_MASKn(32, \
|
||||
(START) < 32 ? 0 : (START) - 32, \
|
||||
31) \
|
||||
| (((STOP) < 32) \
|
||||
? 0 \
|
||||
: _MASKn(32, \
|
||||
0, \
|
||||
(STOP) - 32))))
|
||||
#endif
|
||||
|
||||
|
||||
#define MASKED32(WORD, START, STOP) _MASKEDn(32, WORD, START, STOP)
|
||||
#define MASKED64(WORD, START, STOP) _MASKEDn(64, WORD, START, STOP)
|
||||
#define MASKED10(WORD, START, STOP) _MASKEDn(10, WORD, START, STOP)
|
||||
#define EXTRACTED32(WORD, START, STOP) _EXTRACTEDn(32, WORD, START, STOP)
|
||||
#define EXTRACTED64(WORD, START, STOP) _EXTRACTEDn(64, WORD, START, STOP)
|
||||
#define EXTRACTED10(WORD, START, STOP) _EXTRACTEDn(10, WORD, START, STOP)
|
||||
|
||||
#define MASKED(WORD, START, STOP) ((natural_word)(WORD) & MASK(START, STOP))
|
||||
#if (WITH_64BITS_TARGET)
|
||||
#define EXTRACTED(WORD, START, STOP) _EXTRACTEDn(64, WORD, START, STOP)
|
||||
#else
|
||||
#define EXTRACTED(WORD, START, STOP) (STOP < 32 \
|
||||
? 0 \
|
||||
: (((natural_word)WORD \
|
||||
>> (63 - (STOP))) \
|
||||
&& MASK(START+(63-STOP), 63)))
|
||||
#endif
|
||||
|
||||
|
||||
#define SHUFFLE32(WORD, OLD, NEW) _SHUFFLEn(32, WORD, OLD, NEW)
|
||||
#define SHUFFLE64(WORD, OLD, NEW) _SHUFFLEn(64, WORD, OLD, NEW)
|
||||
#define SHUFFLE(WORD, OLD, NEW) _SHUFFLEn(_word, WORD, OLD, NEW)
|
||||
/* NB: the wierdness (N>O?N-O:0) is to stop a warning from GCC */
|
||||
#define _SHUFFLEn(N, WORD, OLD, NEW) \
|
||||
((OLD) < (NEW) \
|
||||
? (((unsigned##N)(WORD) \
|
||||
>> (((NEW) > (OLD)) ? ((NEW) - (OLD)) : 0)) \
|
||||
& MASK32((NEW), (NEW))) \
|
||||
: (((unsigned##N)(WORD) \
|
||||
<< (((OLD) > (NEW)) ? ((OLD) - (NEW)) : 0)) \
|
||||
& MASK32((NEW), (NEW))))
|
||||
|
||||
|
||||
|
||||
/* depending on MODE return a 64bit or 32bit (sign extended) value */
|
||||
#if (WITH_64BIT_TARGET)
|
||||
#define EXTENDED(X) ((signed64)(signed32)(X))
|
||||
#else
|
||||
#define EXTENDED(X) (X)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/* memory alignment macro's */
|
||||
#define _ALIGNa(A,X) (((X) + ((A)-1)) & ~((A)-1))
|
||||
#define ALIGN_8(X) _ALIGNa(8, X)
|
||||
#define ALIGN_16(X) _ALIGNa(16, X)
|
||||
#define ALIGN_PAGE(X) _ALIGNa(0x1000, X)
|
||||
#define FLOOR_PAGE(X) ((X) & ~(0x1000 - 1))
|
||||
|
||||
/* bit bliting macro's */
|
||||
#define BLIT32(V, POS, BIT) \
|
||||
do { \
|
||||
if (BIT) \
|
||||
V |= BIT32(POS); \
|
||||
else \
|
||||
V &= ~BIT32(POS); \
|
||||
} while (0)
|
||||
#define MLIT32(V, LO, HI, VAL) \
|
||||
do { \
|
||||
(V) = (((V) & ~MASK32((LO), (HI))) \
|
||||
| ((VAL) << _MAKE_SHIFT(32,HI))); \
|
||||
} while (0)
|
||||
|
||||
|
||||
|
||||
/* Things for creating single bit set values */
|
||||
/* MakeBit */
|
||||
#define _MAKE_SHIFT(WIDTH, pos) (WIDTH - 1 - (pos))
|
||||
#define _BITn(WIDTH, pos) (((natural##WIDTH)(1)) \
|
||||
<< _MAKE_SHIFT(WIDTH, pos))
|
||||
/* MakeBitMask */
|
||||
#define _MASKn(WIDTH, START, STOP) (((((unsigned##WIDTH)0) - 1) \
|
||||
>> (WIDTH - ((STOP) - (START) + 1))) \
|
||||
<< (WIDTH - 1 - (STOP)))
|
||||
|
||||
|
||||
|
||||
/* mask the required bits, leaving them in place */
|
||||
#define _MASKEDn(WIDTH, WORD, START, STOP) \
|
||||
(((natural##WIDTH)(WORD)) & MASK##WIDTH(START, STOP))
|
||||
|
||||
/* extract the required bits aligning them with the lsb */
|
||||
#define _EXTRACTEDn(WIDTH, WORD, START, STOP) \
|
||||
((((natural##WIDTH)(WORD)) >> (WIDTH - (STOP) - 1)) \
|
||||
& _MASKn(WIDTH, WIDTH-1+(START)-(STOP), WIDTH-1))
|
||||
|
||||
#endif /* _BITS_H_ */
|
32
sim/ppc/configure.in
Normal file
32
sim/ppc/configure.in
Normal file
@ -0,0 +1,32 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
AC_PREREQ(2.3)dnl
|
||||
AC_INIT(Makefile.in)
|
||||
|
||||
AC_CONFIG_AUX_DIR(`cd $srcdir;pwd`/../..)
|
||||
AC_CANONICAL_SYSTEM
|
||||
AC_ARG_PROGRAM
|
||||
|
||||
. ${srcdir}/../../bfd/configure.host
|
||||
|
||||
# Set up to make a link between the host's include file and "sysdep.h".
|
||||
files="../../bfd/hosts/${my_host}.h"
|
||||
if test ! -f ${srcdir}/${files} ; then
|
||||
files=../../bfd/hosts/std-host.h
|
||||
AC_MSG_WARN(z8k sim has no specific support for host ${host} -- using std-host)
|
||||
fi
|
||||
AC_LINK_FILES($files, sysdep.h)
|
||||
|
||||
if test -f ${srcdir}/../../bfd/config/${my_host}.mh; then
|
||||
host_makefile_frag=../../bfd/config/${my_host}.mh
|
||||
else
|
||||
host_makefile_frag=/dev/null
|
||||
fi
|
||||
|
||||
frags=
|
||||
if test $host_makefile_frag != /dev/null; then
|
||||
frags="$frags $host_makefile_frag"
|
||||
fi
|
||||
AC_SUBST_FILE(host_makefile_frag)
|
||||
AC_SUBST(frags)
|
||||
|
||||
AC_OUTPUT(Makefile)
|
356
sim/ppc/core.c
Normal file
356
sim/ppc/core.c
Normal file
@ -0,0 +1,356 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _CORE_C_
|
||||
#define _CORE_C_
|
||||
|
||||
#ifndef STATIC_INLINE_CORE
|
||||
#define STATIC_INLINE_CORE STATIC_INLINE
|
||||
#endif
|
||||
|
||||
#include "basics.h"
|
||||
#include "device_tree.h"
|
||||
#include "memory_map.h"
|
||||
#include "core.h"
|
||||
|
||||
|
||||
struct _core {
|
||||
/* attached devices */
|
||||
device_node *device_tree;
|
||||
/* different memory maps */
|
||||
memory_map *readable; /* really everything */
|
||||
memory_map *writeable;
|
||||
memory_map *executable;
|
||||
/* VEA model requires additional memory information */
|
||||
unsigned_word data_upper_bound;
|
||||
unsigned_word data_high_water;
|
||||
unsigned_word stack_upper_bound;
|
||||
unsigned_word stack_lower_bound;
|
||||
unsigned_word stack_low_water;
|
||||
/* misc */
|
||||
int trace;
|
||||
};
|
||||
|
||||
|
||||
STATIC_INLINE_CORE void
|
||||
create_core_from_addresses(device_node *device,
|
||||
void *data)
|
||||
{
|
||||
core *memory = (core*)data;
|
||||
device_address *address;
|
||||
for (address = device->addresses;
|
||||
address != NULL;
|
||||
address = address->next_address) {
|
||||
switch (device->type) {
|
||||
case memory_device:
|
||||
{
|
||||
void *ram = zalloc(address->size);
|
||||
TRACE(trace_core,
|
||||
("create_core_from_addresses() adding memory at 0x%.8x-0x%.8x, size %8d\n",
|
||||
address->lower_bound, address->lower_bound + address->size - 1, address->size));
|
||||
core_add_raw_memory(memory,
|
||||
ram,
|
||||
address->lower_bound,
|
||||
address->size,
|
||||
address->access);
|
||||
}
|
||||
break;
|
||||
case sequential_device:
|
||||
case block_device:
|
||||
case bus_device:
|
||||
case other_device:
|
||||
{
|
||||
TRACE(trace_core,
|
||||
("create_core_from_addresses() adding device at 0x%.8x-0x%.8x, size %8d\n",
|
||||
address->lower_bound, address->lower_bound + address->size - 1, address->size));
|
||||
ASSERT(device->callbacks != NULL);
|
||||
core_add_callback_memory(memory,
|
||||
device,
|
||||
device->callbacks->read_callback,
|
||||
device->callbacks->write_callback,
|
||||
address->lower_bound,
|
||||
address->size,
|
||||
address->access);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
TRACE(trace_core,
|
||||
("create_core_from_addresses() unknown type %d\n", (int)device->type));
|
||||
break;
|
||||
/* nothing happens here */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
INLINE_CORE core *
|
||||
core_create(device_node *root,
|
||||
int trace)
|
||||
{
|
||||
core *memory;
|
||||
|
||||
/* Initialize things */
|
||||
memory = ZALLOC(core);
|
||||
memory->trace = trace;
|
||||
memory->device_tree = root;
|
||||
|
||||
/* allocate space for the separate virtual to physical maps */
|
||||
memory->executable = new_memory_map();
|
||||
memory->readable = new_memory_map();
|
||||
memory->writeable = new_memory_map();
|
||||
|
||||
/* initial values for the water marks */
|
||||
memory->data_high_water = 0;
|
||||
memory->stack_low_water = memory->data_high_water - sizeof(unsigned_word);
|
||||
|
||||
/* go over the device tree looking for address ranges to add to
|
||||
memory */
|
||||
device_tree_traverse(root,
|
||||
create_core_from_addresses,
|
||||
NULL,
|
||||
memory);
|
||||
|
||||
/* return the created core object */
|
||||
return memory;
|
||||
}
|
||||
|
||||
|
||||
STATIC_INLINE_CORE void
|
||||
zero_core_from_addresses(device_node *device,
|
||||
void *data)
|
||||
{
|
||||
core *memory = (core*)data;
|
||||
device_address *address;
|
||||
|
||||
/* for memory nodes, copy or zero any data */
|
||||
if (device->type == memory_device) {
|
||||
for (address = device->addresses;
|
||||
address != NULL;
|
||||
address = address->next_address) {
|
||||
if (memory_map_zero(memory->readable,
|
||||
address->lower_bound,
|
||||
address->size) != address->size)
|
||||
error("init_core_from_addresses() - zero failed\n");
|
||||
/* adjust high water mark (sbrk) */
|
||||
if (memory->data_upper_bound < address->upper_bound)
|
||||
memory->data_upper_bound = address->upper_bound;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STATIC_INLINE_CORE void
|
||||
load_core_from_addresses(device_node *device,
|
||||
void *data)
|
||||
{
|
||||
core *memory = (core*)data;
|
||||
device_address *address;
|
||||
|
||||
/* initialize the address range with the value attached to the
|
||||
address. Even works for devices! */
|
||||
for (address = device->addresses;
|
||||
address != NULL;
|
||||
address = address->next_address) {
|
||||
/* (re)init the address range. I don't want to think about what
|
||||
this is doing to callback devices! */
|
||||
if (address->init) {
|
||||
if (memory_map_write_buffer(memory->readable,
|
||||
address->init,
|
||||
address->lower_bound,
|
||||
address->size,
|
||||
raw_transfer) != address->size)
|
||||
error("init_core_from_addresses() - write failed\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INLINE_CORE void
|
||||
core_init(core *memory)
|
||||
{
|
||||
unsigned nr_cleared;
|
||||
unsigned_word clear_base;
|
||||
unsigned_word clear_bound;
|
||||
|
||||
/* for vea, several memory break points */
|
||||
memory->data_upper_bound = 0;
|
||||
memory->stack_upper_bound = device_tree_find_int(memory->device_tree,
|
||||
"/options/stack-pointer");;
|
||||
memory->stack_lower_bound = memory->stack_upper_bound;
|
||||
|
||||
/* (re) clear all of memory that is specified by memory-address
|
||||
entries. While we're at it determine the upper bound for memory
|
||||
areas */
|
||||
device_tree_traverse(memory->device_tree,
|
||||
NULL,
|
||||
zero_core_from_addresses,
|
||||
memory);
|
||||
|
||||
/* May have grown the data sectioin (vea model), zero that too if
|
||||
present */
|
||||
clear_base = memory->data_upper_bound;
|
||||
clear_bound = memory->data_high_water;
|
||||
if (clear_bound > clear_base) {
|
||||
while ((nr_cleared = memory_map_zero(memory->readable,
|
||||
clear_base,
|
||||
clear_bound - clear_base)) > 0) {
|
||||
clear_base += nr_cleared;
|
||||
}
|
||||
}
|
||||
|
||||
/* clear any part of the stack that was dynamically allocated */
|
||||
clear_base = memory->stack_low_water;
|
||||
clear_bound = memory->stack_upper_bound;
|
||||
if (clear_bound > clear_base) {
|
||||
while ((nr_cleared = memory_map_zero(memory->readable,
|
||||
clear_base,
|
||||
clear_bound - clear_base)) > 0) {
|
||||
clear_base += nr_cleared;
|
||||
}
|
||||
}
|
||||
|
||||
/* with everything zero'ed, now (re) load any data sections */
|
||||
device_tree_traverse(memory->device_tree,
|
||||
NULL,
|
||||
load_core_from_addresses,
|
||||
memory);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
INLINE_CORE void
|
||||
core_add_raw_memory(core *memory,
|
||||
void *buffer,
|
||||
unsigned_word base,
|
||||
unsigned size,
|
||||
device_access access)
|
||||
{
|
||||
if (access & device_is_readable)
|
||||
memory_map_add_raw_memory(memory->readable,
|
||||
buffer, base, size);
|
||||
if (access & device_is_writeable)
|
||||
memory_map_add_raw_memory(memory->writeable,
|
||||
buffer, base, size);
|
||||
if (access & device_is_executable)
|
||||
memory_map_add_raw_memory(memory->executable,
|
||||
buffer, base, size);
|
||||
}
|
||||
|
||||
|
||||
INLINE_CORE void
|
||||
core_add_callback_memory(core *memory,
|
||||
device_node *device,
|
||||
device_reader_callback *reader,
|
||||
device_writer_callback *writer,
|
||||
unsigned_word base,
|
||||
unsigned size,
|
||||
device_access access)
|
||||
{
|
||||
if (access & device_is_readable)
|
||||
memory_map_add_callback_memory(memory->readable,
|
||||
device, reader, writer,
|
||||
base, size);
|
||||
if (access & device_is_writeable)
|
||||
memory_map_add_callback_memory(memory->writeable,
|
||||
device, reader, writer,
|
||||
base, size);
|
||||
if (access & device_is_executable)
|
||||
memory_map_add_callback_memory(memory->executable,
|
||||
device, reader, writer,
|
||||
base, size);
|
||||
}
|
||||
|
||||
|
||||
STATIC_INLINE_CORE void
|
||||
malloc_core_memory(core *memory,
|
||||
unsigned_word base,
|
||||
unsigned size,
|
||||
device_access access)
|
||||
{
|
||||
void *buffer = (void*)zalloc(size);
|
||||
core_add_raw_memory(memory, buffer, base, size, access);
|
||||
}
|
||||
|
||||
INLINE_CORE unsigned_word
|
||||
core_data_upper_bound(core *memory)
|
||||
{
|
||||
return memory->data_upper_bound;
|
||||
}
|
||||
|
||||
|
||||
INLINE_CORE unsigned_word
|
||||
core_stack_lower_bound(core *memory)
|
||||
{
|
||||
return memory->stack_lower_bound;
|
||||
}
|
||||
|
||||
INLINE_CORE unsigned_word
|
||||
core_stack_size(core *memory)
|
||||
{
|
||||
return (memory->stack_upper_bound - memory->stack_lower_bound);
|
||||
}
|
||||
|
||||
|
||||
|
||||
INLINE_CORE void
|
||||
core_add_data(core *memory, unsigned_word incr)
|
||||
{
|
||||
memory->data_upper_bound += incr;
|
||||
if (memory->data_upper_bound > memory->data_high_water) {
|
||||
malloc_core_memory(memory, memory->data_high_water, incr,
|
||||
device_is_readable | device_is_writeable);
|
||||
memory->data_high_water = memory->data_upper_bound;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
INLINE_CORE void
|
||||
core_add_stack(core *memory, unsigned_word incr)
|
||||
{
|
||||
memory->stack_lower_bound -= incr;
|
||||
if (memory->stack_lower_bound < memory->stack_low_water) {
|
||||
malloc_core_memory(memory, memory->stack_lower_bound, incr,
|
||||
device_is_readable | device_is_writeable);
|
||||
memory->stack_low_water = memory->stack_lower_bound;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
INLINE_CORE memory_map *
|
||||
core_readable(core *core)
|
||||
{
|
||||
return core->readable;
|
||||
}
|
||||
|
||||
|
||||
INLINE_CORE memory_map *
|
||||
core_writeable(core *core)
|
||||
{
|
||||
return core->writeable;
|
||||
}
|
||||
|
||||
|
||||
INLINE_CORE memory_map *
|
||||
core_executable(core *core)
|
||||
{
|
||||
return core->executable;
|
||||
}
|
||||
|
||||
#endif /* _CORE_ */
|
103
sim/ppc/core.h
Normal file
103
sim/ppc/core.h
Normal file
@ -0,0 +1,103 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _CORE_H_
|
||||
#define _CORE_H_
|
||||
|
||||
#ifndef INLINE_CORE
|
||||
#define INLINE_CORE
|
||||
#endif
|
||||
|
||||
/* the base type */
|
||||
|
||||
typedef struct _core core;
|
||||
|
||||
|
||||
/* create the hardware's core (memory and devices) from the device
|
||||
tree */
|
||||
INLINE_CORE core *core_create
|
||||
(device_node *root,
|
||||
int trace);
|
||||
|
||||
|
||||
/* given a created core object, (re)initialize it from the
|
||||
information provided in it's associated device tree */
|
||||
|
||||
INLINE_CORE void core_init
|
||||
(core *memory);
|
||||
|
||||
|
||||
/* from this core extract out the three different types of memory -
|
||||
executable, readable, writeable */
|
||||
|
||||
INLINE_CORE memory_map *core_readable
|
||||
(core *memory);
|
||||
|
||||
INLINE_CORE memory_map *core_writeable
|
||||
(core *memory);
|
||||
|
||||
INLINE_CORE memory_map *core_executable
|
||||
(core *memory);
|
||||
|
||||
|
||||
/* operators to grow memory on the fly */
|
||||
|
||||
INLINE_CORE void core_add_raw_memory
|
||||
(core *memory,
|
||||
void *buffer,
|
||||
unsigned_word base,
|
||||
unsigned size,
|
||||
device_access access);
|
||||
|
||||
INLINE_CORE void core_add_callback_memory
|
||||
(core *memory,
|
||||
device_node *device,
|
||||
device_reader_callback *reader,
|
||||
device_writer_callback *writer,
|
||||
unsigned_word base,
|
||||
unsigned size,
|
||||
device_access access);
|
||||
|
||||
|
||||
/* In the VEA model, memory grow's after it is created. Operators
|
||||
below grow memory as required.
|
||||
|
||||
FIXME - should this be inside of vm? */
|
||||
|
||||
INLINE_CORE unsigned_word core_data_upper_bound
|
||||
(core *memory);
|
||||
|
||||
INLINE_CORE unsigned_word core_stack_lower_bound
|
||||
(core *memory);
|
||||
|
||||
INLINE_CORE unsigned_word core_stack_size
|
||||
(core *memory);
|
||||
|
||||
INLINE_CORE void core_add_data
|
||||
(core *memory,
|
||||
unsigned_word incr);
|
||||
|
||||
INLINE_CORE void core_add_stack
|
||||
(core *memory,
|
||||
unsigned_word incr);
|
||||
|
||||
|
||||
#endif /* _CORE_ */
|
506
sim/ppc/device_tree.c
Normal file
506
sim/ppc/device_tree.c
Normal file
@ -0,0 +1,506 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _DEVICE_TREE_C_
|
||||
#define _DEVICE_TREE_C_
|
||||
|
||||
#ifndef STATIC_INLINE_DEVICE_TREE
|
||||
#define STATIC_INLINE_DEVICE_TREE STATIC_INLINE
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "basics.h"
|
||||
#include "device_tree.h"
|
||||
#include "devices.h"
|
||||
|
||||
#include "bfd.h"
|
||||
|
||||
enum { clayton_memory_size = 0x100000 };
|
||||
|
||||
/* insert the address into the device_nodes sorted list of addresses */
|
||||
INLINE_DEVICE_TREE void
|
||||
device_node_add_address(device_node *node,
|
||||
unsigned_word lower_bound,
|
||||
unsigned size,
|
||||
device_access access,
|
||||
void *init)
|
||||
{
|
||||
unsigned_word upper_bound = lower_bound + size;
|
||||
device_address *new_address;
|
||||
device_address **current_address;
|
||||
|
||||
/* find the insertion point */
|
||||
current_address = &node->addresses;
|
||||
while (*current_address != NULL
|
||||
&& (*current_address)->upper_bound >= upper_bound) {
|
||||
current_address = &(*current_address)->next_address;
|
||||
}
|
||||
|
||||
/* insert */
|
||||
new_address = ZALLOC(device_address);
|
||||
new_address->lower_bound = lower_bound;
|
||||
new_address->upper_bound = lower_bound + size;
|
||||
new_address->size = size;
|
||||
new_address->access = access;
|
||||
new_address->init = init;
|
||||
new_address->next_address = *current_address;
|
||||
*current_address = new_address;
|
||||
}
|
||||
|
||||
|
||||
/* create a new device tree optionally making it a child of the parent
|
||||
node */
|
||||
|
||||
INLINE_DEVICE_TREE device_node *
|
||||
device_node_create(device_node *parent,
|
||||
char *name,
|
||||
device_type type,
|
||||
device_callbacks *callbacks,
|
||||
void *data)
|
||||
{
|
||||
device_node *new_node;
|
||||
new_node = ZALLOC(device_node);
|
||||
new_node->parent = parent;
|
||||
new_node->name = name;
|
||||
new_node->type = type;
|
||||
new_node->callbacks = callbacks;
|
||||
new_node->data = data;
|
||||
if (parent != NULL) {
|
||||
new_node->sibling = parent->children;
|
||||
parent->children = new_node;
|
||||
}
|
||||
return new_node;
|
||||
}
|
||||
|
||||
|
||||
/* Binary file:
|
||||
|
||||
The specified file is a binary, assume VEA is required, construct a
|
||||
fake device tree based on the addresses of the text / data segments
|
||||
requested by the binary */
|
||||
|
||||
|
||||
/* Update the fake device tree so that memory is allocated for this
|
||||
section */
|
||||
STATIC_INLINE_DEVICE_TREE void
|
||||
update_memory_node_for_section(bfd *abfd,
|
||||
asection *the_section,
|
||||
PTR obj)
|
||||
{
|
||||
unsigned_word section_vma;
|
||||
unsigned_word section_size;
|
||||
device_access section_access;
|
||||
void *section_init;
|
||||
device_node *memory = (device_node*)obj;
|
||||
|
||||
/* skip the section if no memory to allocate */
|
||||
if (! (bfd_get_section_flags(abfd, the_section) & SEC_ALLOC))
|
||||
return;
|
||||
|
||||
/* check/ignore any sections of size zero */
|
||||
section_size = bfd_get_section_size_before_reloc(the_section);
|
||||
if (section_size == 0)
|
||||
return;
|
||||
|
||||
/* find where it is to go */
|
||||
section_vma = bfd_get_section_vma(abfd, the_section);
|
||||
|
||||
TRACE(trace_device_tree,
|
||||
("name=%-7s, vma=0x%.8x, size=%6d, flags=%3x(%s%s%s%s )\n",
|
||||
bfd_get_section_name(abfd, the_section),
|
||||
section_vma, section_size,
|
||||
bfd_get_section_flags(abfd, the_section),
|
||||
bfd_get_section_flags(abfd, the_section) & SEC_LOAD ? " LOAD" : "",
|
||||
bfd_get_section_flags(abfd, the_section) & SEC_CODE ? " CODE" : "",
|
||||
bfd_get_section_flags(abfd, the_section) & SEC_DATA ? " DATA" : "",
|
||||
bfd_get_section_flags(abfd, the_section) & SEC_ALLOC ? " ALLOC" : "",
|
||||
bfd_get_section_flags(abfd, the_section) & SEC_READONLY ? " READONLY" : ""
|
||||
));
|
||||
|
||||
if (bfd_get_section_flags(abfd, the_section) & SEC_LOAD) {
|
||||
section_init = zalloc(section_size);
|
||||
if (!bfd_get_section_contents(abfd,
|
||||
the_section,
|
||||
section_init, 0,
|
||||
section_size)) {
|
||||
bfd_perror("core:load_section()");
|
||||
error("load of data failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
section_init = NULL;
|
||||
}
|
||||
|
||||
/* determine the devices access */
|
||||
if (bfd_get_section_flags(abfd, the_section) & SEC_CODE)
|
||||
section_access = (device_is_readable | device_is_executable);
|
||||
else if (bfd_get_section_flags(abfd, the_section) & SEC_READONLY)
|
||||
section_access = device_is_readable;
|
||||
else
|
||||
section_access = (device_is_readable | device_is_writeable);
|
||||
|
||||
/* find our memory and add this section to its list of addresses */
|
||||
device_node_add_address(memory,
|
||||
section_vma,
|
||||
section_size,
|
||||
section_access,
|
||||
section_init);
|
||||
}
|
||||
|
||||
|
||||
/* construct the device tree from the executable */
|
||||
|
||||
STATIC_INLINE_DEVICE_TREE device_node *
|
||||
create_option_device_node(device_node *root,
|
||||
bfd *image)
|
||||
{
|
||||
device_node *option_node;
|
||||
|
||||
/* the option node and than its members */
|
||||
option_node = device_node_create(root, "options", options_device,
|
||||
NULL, NULL);
|
||||
|
||||
/* which endian are we ? */
|
||||
device_node_create(option_node,
|
||||
"little-endian?",
|
||||
boolean_type_device,
|
||||
NULL,
|
||||
(void*)(image->xvec->byteorder_big_p ? 0 : -1));
|
||||
|
||||
/* what is the initial entry point */
|
||||
device_node_create(option_node,
|
||||
"program-counter",
|
||||
integer_type_device,
|
||||
NULL,
|
||||
(void*)(bfd_get_start_address(image)));
|
||||
|
||||
/* address of top of boot stack */
|
||||
TRACE(trace_tbd, ("create_optioin_device_node() - TBD - NT/OpenBoot?\n"));
|
||||
device_node_create(option_node,
|
||||
"stack-pointer",
|
||||
integer_type_device,
|
||||
NULL,
|
||||
(void*)(bfd_get_start_address(image) == 0
|
||||
? clayton_memory_size /* OEA */
|
||||
: (image->xvec->flavour == bfd_target_elf_flavour
|
||||
? 0xe0000000 /* elf */
|
||||
: 0x20000000 /* xcoff */)));
|
||||
|
||||
/* execution environment */
|
||||
device_node_create(option_node,
|
||||
"vea?",
|
||||
boolean_type_device,
|
||||
NULL,
|
||||
(void*)(bfd_get_start_address(image) == 0
|
||||
? 0
|
||||
: -1));
|
||||
|
||||
/* what type of binary */
|
||||
TRACE(trace_tbd, ("create_optioin_device_node() - TBD - NT/OpenBoot?\n"));
|
||||
device_node_create(option_node,
|
||||
"elf?",
|
||||
boolean_type_device,
|
||||
NULL,
|
||||
(void*)(image->xvec->flavour == bfd_target_elf_flavour
|
||||
? -1 /* elf binary */
|
||||
: 0 /* probably aix binary */));
|
||||
|
||||
/* must all memory transfers be naturally aligned? */
|
||||
device_node_create(option_node,
|
||||
"aligned?",
|
||||
boolean_type_device,
|
||||
NULL,
|
||||
(void*)((WITH_ALIGNMENT == NONSTRICT_ALIGNMENT
|
||||
|| image->xvec->byteorder_big_p
|
||||
|| bfd_get_start_address(image) != 0)
|
||||
? 0
|
||||
: -1));
|
||||
|
||||
|
||||
return option_node;
|
||||
}
|
||||
|
||||
|
||||
/* clatyon is a simple machine that does not require interrupts or any
|
||||
thing else */
|
||||
|
||||
STATIC_INLINE_DEVICE_TREE device_node *
|
||||
create_clayton_device_tree(bfd *image)
|
||||
{
|
||||
device_node *root;
|
||||
device_node *io_node;
|
||||
device_node *data_node;
|
||||
device_node *memory_node;
|
||||
|
||||
/* the root */
|
||||
root = ZALLOC(device_node);
|
||||
|
||||
/* memory - clayton has 2mb of RAM at location 0 */
|
||||
memory_node = device_node_create(root,
|
||||
"memory",
|
||||
memory_device,
|
||||
NULL,
|
||||
NULL);
|
||||
device_node_add_address(memory_node, 0x0, clayton_memory_size,
|
||||
(device_is_readable
|
||||
| device_is_writeable
|
||||
| device_is_executable),
|
||||
NULL);
|
||||
|
||||
/* io address space */
|
||||
io_node = device_node_create(root, "io", bus_device, NULL, NULL);
|
||||
|
||||
/* and IO devices */
|
||||
find_device_descriptor("console")
|
||||
->creator(io_node, "console@0x400000,0");
|
||||
find_device_descriptor("halt")
|
||||
->creator(io_node, "halt@0x500000,0");
|
||||
find_device_descriptor("icu")
|
||||
->creator(io_node, "icu@0x600000,0");
|
||||
|
||||
/* data to load */
|
||||
data_node = device_node_create(root, "image", data_device, NULL, NULL);
|
||||
bfd_map_over_sections(image,
|
||||
update_memory_node_for_section,
|
||||
(PTR)data_node);
|
||||
|
||||
/* options */
|
||||
create_option_device_node(root, image);
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
|
||||
/* user mode executable build up a device tree that reflects this */
|
||||
|
||||
STATIC_INLINE_DEVICE_TREE device_node *
|
||||
create_vea_device_tree(bfd *image)
|
||||
{
|
||||
device_node *root;
|
||||
device_node *memory_node;
|
||||
device_node *option_node;
|
||||
|
||||
/* the root */
|
||||
root = ZALLOC(device_node);
|
||||
|
||||
/* memory */
|
||||
memory_node = device_node_create(root, "memory", memory_device,
|
||||
NULL, NULL);
|
||||
bfd_map_over_sections(image,
|
||||
update_memory_node_for_section,
|
||||
(PTR)memory_node);
|
||||
/* options - only endian so far */
|
||||
option_node = create_option_device_node(root, image);
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
|
||||
/* create a device tree from the specified file */
|
||||
INLINE_DEVICE_TREE device_node *
|
||||
device_tree_create(const char *file_name)
|
||||
{
|
||||
bfd *image;
|
||||
device_node *tree;
|
||||
|
||||
bfd_init(); /* could be redundant but ... */
|
||||
|
||||
/* open the file */
|
||||
image = bfd_openr(file_name, NULL);
|
||||
if (image == NULL) {
|
||||
bfd_perror("open failed:");
|
||||
error("nothing loaded\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* check it is valid */
|
||||
if (!bfd_check_format(image, bfd_object)) {
|
||||
printf_filtered("create_device_tree() - FIXME - should check more bfd bits\n");
|
||||
printf_filtered("create_device_tree() - %s not an executable, assume device file\n", file_name);
|
||||
bfd_close(image);
|
||||
image = NULL;
|
||||
}
|
||||
|
||||
/* depending on what was found about the file, load it */
|
||||
if (image != NULL) {
|
||||
if (bfd_get_start_address(image) == 0) {
|
||||
TRACE(trace_device_tree, ("create_device_tree() - clayton image\n"));
|
||||
tree = create_clayton_device_tree(image);
|
||||
}
|
||||
else if (bfd_get_start_address(image) > 0) {
|
||||
TRACE(trace_device_tree, ("create_device_tree() - vea image\n"));
|
||||
tree = create_vea_device_tree(image);
|
||||
}
|
||||
bfd_close(image);
|
||||
}
|
||||
else {
|
||||
error("TBD - create_device_tree() text file defining device tree\n");
|
||||
tree = NULL;
|
||||
}
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
|
||||
/* traverse a device tree applying prefix/postfix functions to it */
|
||||
|
||||
INLINE_DEVICE_TREE void
|
||||
device_tree_traverse(device_node *root,
|
||||
device_tree_traverse_function *prefix,
|
||||
device_tree_traverse_function *postfix,
|
||||
void *data)
|
||||
{
|
||||
device_node *child;
|
||||
if (prefix != NULL)
|
||||
prefix(root, data);
|
||||
for (child = root->children; child != NULL; child = child->sibling) {
|
||||
device_tree_traverse(child, prefix, postfix, data);
|
||||
}
|
||||
if (postfix != NULL)
|
||||
postfix(root, data);
|
||||
}
|
||||
|
||||
|
||||
/* query the device tree */
|
||||
|
||||
INLINE_DEVICE_TREE device_node *
|
||||
device_tree_find_node(device_node *root,
|
||||
const char *path)
|
||||
{
|
||||
char *chp;
|
||||
int name_len;
|
||||
device_node *child;
|
||||
|
||||
/* strip off any leading `/', `../' or `./' */
|
||||
while (1) {
|
||||
if (strncmp(path, "/", strlen("/")) == 0) {
|
||||
while (root->parent != NULL)
|
||||
root = root->parent;
|
||||
path += strlen("/");
|
||||
}
|
||||
else if (strncmp(path, "./", strlen("./")) == 0) {
|
||||
root = root;
|
||||
path += strlen("./");
|
||||
}
|
||||
else if (strncmp(path, "../", strlen("../")) == 0) {
|
||||
if (root->parent != NULL)
|
||||
root = root->parent;
|
||||
path += strlen("../");
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* find the qualified (with @) and unqualified names in the path */
|
||||
chp = strchr(path, '/');
|
||||
name_len = (chp == NULL
|
||||
? strlen(path)
|
||||
: chp - path);
|
||||
|
||||
/* search through children for a match */
|
||||
for (child = root->children;
|
||||
child != NULL;
|
||||
child = child->sibling) {
|
||||
if (strncmp(path, child->name, name_len) == 0
|
||||
&& (strlen(child->name) == name_len
|
||||
|| strchr(child->name, '@') == child->name + name_len)) {
|
||||
if (path[name_len] == '\0')
|
||||
return child;
|
||||
else
|
||||
return device_tree_find_node(child, path + name_len + 1);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
INLINE_DEVICE_TREE device_node *device_tree_find_next_node
|
||||
(device_node *root,
|
||||
const char *path,
|
||||
device_node *last);
|
||||
|
||||
INLINE_DEVICE_TREE signed_word
|
||||
device_tree_find_int(device_node *root,
|
||||
const char *path)
|
||||
{
|
||||
device_node *int_node = device_tree_find_node(root, path);
|
||||
if (int_node == NULL) {
|
||||
error("device_tree_find_int() - node %s does not exist\n", path);
|
||||
return 0;
|
||||
}
|
||||
else if (int_node->type != integer_type_device) {
|
||||
error("device_tree_find_int() - node %s is not an int\n", path);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return (signed_word)(int_node->data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
INLINE_DEVICE_TREE const char *device_tree_find_string
|
||||
(device_node *root,
|
||||
const char *path);
|
||||
|
||||
INLINE_DEVICE_TREE int
|
||||
device_tree_find_boolean(device_node *root,
|
||||
const char *path)
|
||||
{
|
||||
device_node *int_node = device_tree_find_node(root, path);
|
||||
if (int_node == NULL) {
|
||||
error("device_tree_find_boolean() - node %s does not exist\n", path);
|
||||
return 0;
|
||||
}
|
||||
else if (int_node->type != boolean_type_device) {
|
||||
error("device_tree_find_boolean() - node %s is not a boolean\n", path);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return (signed_word)(int_node->data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
INLINE_DEVICE_TREE void *device_tree_find_bytes
|
||||
(device_node *root,
|
||||
const char *path);
|
||||
|
||||
/* dump out a device node and addresses */
|
||||
|
||||
INLINE_DEVICE_TREE void
|
||||
device_tree_dump(device_node *device,
|
||||
void *ignore_data_argument)
|
||||
{
|
||||
printf_filtered("(device_node@0x%x\n", device);
|
||||
printf_filtered(" (parent 0x%x)\n", device->parent);
|
||||
printf_filtered(" (children 0x%x)\n", device->children);
|
||||
printf_filtered(" (sibling 0x%x)\n", device->sibling);
|
||||
printf_filtered(" (name %s)\n", device->name ? device->name : "(null)");
|
||||
printf_filtered(" (type %d)\n", device->type);
|
||||
printf_filtered(" (handlers 0x%x)\n", device->callbacks);
|
||||
printf_filtered(" (addresses %d)\n", device->addresses);
|
||||
printf_filtered(" (data %d)\n", device->data);
|
||||
printf_filtered(")\n");
|
||||
}
|
||||
|
||||
#endif /* _DEVICE_TREE_C_ */
|
234
sim/ppc/device_tree.h
Normal file
234
sim/ppc/device_tree.h
Normal file
@ -0,0 +1,234 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _DEVICE_TREE_H_
|
||||
#define _DEVICE_TREE_H_
|
||||
|
||||
#ifndef INLINE_DEVICE_TREE
|
||||
#define INLINE_DEVICE_TREE
|
||||
#endif
|
||||
|
||||
|
||||
/* forward declaration of types */
|
||||
|
||||
typedef struct _device_node device_node;
|
||||
typedef struct _device_address device_address;
|
||||
typedef struct _device_callbacks device_callbacks;
|
||||
|
||||
|
||||
/* Device callbacks: */
|
||||
|
||||
|
||||
/* Memory operations: transfer data to/from a processor.
|
||||
|
||||
These callbacks pass/return data in *host* byte order.
|
||||
|
||||
Should a memory read/write operation cause an interrupt (external
|
||||
exception) then a device would typically pass an interrupt message
|
||||
to the devices parent. Hopefully that is an interrupt controler
|
||||
and will know what to do with it.
|
||||
|
||||
Devices normally never either restart a processor or issue an
|
||||
interrupt directly. The only exception I've thought of could be
|
||||
machine check type event. */
|
||||
|
||||
typedef unsigned64 (device_reader_callback)
|
||||
(device_node *device,
|
||||
unsigned_word base,
|
||||
unsigned nr_bytes,
|
||||
cpu *processor,
|
||||
unsigned_word cia);
|
||||
|
||||
typedef void (device_writer_callback)
|
||||
(device_node *device,
|
||||
unsigned_word base,
|
||||
unsigned nr_bytes,
|
||||
unsigned64 val,
|
||||
cpu *processor,
|
||||
unsigned_word cia);
|
||||
|
||||
/* Interrupts:
|
||||
|
||||
A child device uses the below to pass on to its parent changes in
|
||||
the state of a child devices interrupt lines.
|
||||
|
||||
Typically, the parent being an interrupt control device, would, in
|
||||
responce, schedule an event at the start of the next clock cycle.
|
||||
On this event, the state of any cpu could be changed. Other
|
||||
devices could either ignore or pass on the interrupt message */
|
||||
|
||||
typedef void (device_interrupt_callback)
|
||||
(device_node *me,
|
||||
int interrupt_status,
|
||||
device_node *device,
|
||||
cpu *processor,
|
||||
unsigned_word cia);
|
||||
|
||||
/* Create:
|
||||
|
||||
DEVICE_CREATOR is called once, as part of building the device tree.
|
||||
This function gives the device the chance to attach any additional
|
||||
data to this particular device instance.
|
||||
|
||||
DEVICE_INIT_CALLBACK is (re)called when ever the system is
|
||||
(re)initialised. */
|
||||
|
||||
typedef device_node *(device_creator)
|
||||
(device_node *parent,
|
||||
char *name);
|
||||
|
||||
typedef void (device_init_callback)
|
||||
(device_node *device);
|
||||
|
||||
|
||||
|
||||
/* constructs to describe the hardware's tree of devices */
|
||||
|
||||
typedef enum _device_type {
|
||||
/* default */
|
||||
unknown_device,
|
||||
/* typical devices */
|
||||
memory_device,
|
||||
sequential_device,
|
||||
block_device,
|
||||
bus_device,
|
||||
other_device,
|
||||
/* atypical devices, these are for data being loaded into ram/rom */
|
||||
data_device,
|
||||
options_device,
|
||||
/* types of primative nodes containing just data */
|
||||
boolean_type_device,
|
||||
integer_type_device,
|
||||
string_type_device,
|
||||
byte_type_device,
|
||||
} device_type;
|
||||
|
||||
typedef enum _device_access {
|
||||
device_is_readable = 1,
|
||||
device_is_writeable = 2,
|
||||
device_is_read_write = 3,
|
||||
device_is_executable = 4,
|
||||
device_is_read_exec = 5,
|
||||
device_is_write_exec = 6,
|
||||
device_is_read_write_exec = 7,
|
||||
} device_access;
|
||||
|
||||
struct _device_address {
|
||||
unsigned_word lower_bound;
|
||||
unsigned_word upper_bound;
|
||||
unsigned size; /* host limited */
|
||||
void *init; /* initial data */
|
||||
device_access access;
|
||||
device_address *next_address;
|
||||
};
|
||||
|
||||
struct _device_callbacks {
|
||||
device_reader_callback *read_callback;
|
||||
device_writer_callback *write_callback;
|
||||
device_interrupt_callback *interrupt_callback;
|
||||
/* device_init_callback *init_callback; */
|
||||
/* device_init_hander *post_init_handler; */
|
||||
};
|
||||
|
||||
struct _device_node {
|
||||
/* where i am */
|
||||
device_node *parent;
|
||||
device_node *children;
|
||||
device_node *sibling;
|
||||
/* what I am */
|
||||
char *name; /* eg rom@0x1234,0x40 */
|
||||
device_type type;
|
||||
device_callbacks *callbacks;
|
||||
device_address *addresses;
|
||||
void *data;
|
||||
};
|
||||
|
||||
|
||||
/* given the image to run, return its device tree */
|
||||
|
||||
INLINE_DEVICE_TREE device_node *device_tree_create
|
||||
(const char *hardware_description);
|
||||
|
||||
|
||||
/* traverse the tree eiter pre or post fix */
|
||||
|
||||
typedef void (device_tree_traverse_function)
|
||||
(device_node *device,
|
||||
void *data);
|
||||
|
||||
INLINE_DEVICE_TREE void device_tree_traverse
|
||||
(device_node *root,
|
||||
device_tree_traverse_function *prefix,
|
||||
device_tree_traverse_function *postfix,
|
||||
void *data);
|
||||
|
||||
|
||||
/* query the device tree */
|
||||
|
||||
INLINE_DEVICE_TREE device_node *device_tree_find_node
|
||||
(device_node *root,
|
||||
const char *path);
|
||||
|
||||
INLINE_DEVICE_TREE device_node *device_tree_find_next_node
|
||||
(device_node *root,
|
||||
const char *path,
|
||||
device_node *last);
|
||||
|
||||
INLINE_DEVICE_TREE signed_word device_tree_find_int
|
||||
(device_node *root,
|
||||
const char *path);
|
||||
|
||||
INLINE_DEVICE_TREE const char *device_tree_find_string
|
||||
(device_node *root,
|
||||
const char *path);
|
||||
|
||||
INLINE_DEVICE_TREE int device_tree_find_boolean
|
||||
(device_node *root,
|
||||
const char *path);
|
||||
|
||||
INLINE_DEVICE_TREE void *device_tree_find_bytes
|
||||
(device_node *root,
|
||||
const char *path);
|
||||
|
||||
/* add to the device tree */
|
||||
|
||||
INLINE_DEVICE_TREE device_node *device_node_create
|
||||
(device_node *parent,
|
||||
char *name,
|
||||
device_type type,
|
||||
device_callbacks *callbacks,
|
||||
void *data);
|
||||
|
||||
INLINE_DEVICE_TREE void device_node_add_address
|
||||
(device_node *node,
|
||||
unsigned_word lower_bound,
|
||||
unsigned size,
|
||||
device_access access,
|
||||
void *init);
|
||||
|
||||
/* dump a node, pass this to the device_tree_traverse() function to
|
||||
dump the tree */
|
||||
|
||||
INLINE_DEVICE_TREE void device_tree_dump
|
||||
(device_node *device,
|
||||
void *ignore_data_argument);
|
||||
|
||||
#endif /* _DEVICE_TREE_H_ */
|
442
sim/ppc/devices.c
Normal file
442
sim/ppc/devices.c
Normal file
@ -0,0 +1,442 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _DEVICES_C_
|
||||
#define _DEVICES_C_
|
||||
|
||||
#ifndef STATIC_INLINE_DEVICES
|
||||
#define STATIC_INLINE_DEVICES STATIC_INLINE
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "basics.h"
|
||||
#include "device_tree.h"
|
||||
#include "devices.h"
|
||||
#include "events.h"
|
||||
|
||||
#include "cpu.h" /* drats */
|
||||
|
||||
/* Helper functions */
|
||||
|
||||
STATIC_INLINE_DEVICES void
|
||||
parse_device_address(char *name,
|
||||
unsigned *base,
|
||||
unsigned *flags)
|
||||
{
|
||||
/* extract the two arguments */
|
||||
name = strchr(name, '@');
|
||||
if (name == NULL)
|
||||
error("missing address for device %s\n", name);
|
||||
name++;
|
||||
*base = strtol(name, &name, 0);
|
||||
*flags = (*name == ','
|
||||
? strtol(name+1, &name, 0)
|
||||
: 0);
|
||||
}
|
||||
|
||||
|
||||
/* Simple console device:
|
||||
|
||||
Implements a simple text output device that is attached to stdout
|
||||
of the process running the simulation. The devices has four
|
||||
word registers:
|
||||
|
||||
0: read
|
||||
4: read-status
|
||||
8: write
|
||||
c: write-status
|
||||
|
||||
Where a nonzero status register indicates that the device is ready
|
||||
(input fifo contains a character or output fifo has space).
|
||||
|
||||
Illustrates: Mapping read/write to device operations onto actual
|
||||
registers.
|
||||
|
||||
*/
|
||||
|
||||
typedef struct _console_buffer {
|
||||
char buffer;
|
||||
int status;
|
||||
event_entry_tag event_tag;
|
||||
} console_buffer;
|
||||
|
||||
typedef struct _console_device {
|
||||
unsigned_word my_base_address;
|
||||
int interrupt_delay;
|
||||
console_buffer input;
|
||||
console_buffer output;
|
||||
} console_device;
|
||||
|
||||
typedef enum {
|
||||
console_read_buffer = 0,
|
||||
console_read_status = 4,
|
||||
console_write_buffer = 8,
|
||||
console_write_status = 12,
|
||||
console_offset_mask = 0xc,
|
||||
console_size = 16,
|
||||
} console_offsets;
|
||||
|
||||
|
||||
STATIC_INLINE_DEVICES unsigned64
|
||||
console_read_callback(device_node *device,
|
||||
unsigned_word base,
|
||||
unsigned nr_bytes,
|
||||
cpu *processor,
|
||||
unsigned_word cia)
|
||||
{
|
||||
console_device *con = (console_device*)device->data;
|
||||
TRACE(trace_console_device,
|
||||
("device=0x%x, base=0x%x, nr_bytes=%d\n",
|
||||
device, base, nr_bytes));
|
||||
|
||||
/* handle the request */
|
||||
|
||||
switch (base & console_offset_mask) {
|
||||
|
||||
case console_read_buffer:
|
||||
return con->input.buffer;
|
||||
|
||||
case console_read_status:
|
||||
{ /* check for input */
|
||||
int flags;
|
||||
int status;
|
||||
/* get the old status */
|
||||
flags = fcntl(0, F_GETFL, 0);
|
||||
if (flags == -1) {
|
||||
perror("console");
|
||||
return 0;
|
||||
}
|
||||
/* temp, disable blocking IO */
|
||||
status = fcntl(0, F_SETFL, flags | O_NDELAY);
|
||||
if (status == -1) {
|
||||
perror("console");
|
||||
return 0;
|
||||
}
|
||||
/* try for input */
|
||||
status = read(0, &con->input.buffer, 1);
|
||||
if (status == 1) {
|
||||
con->input.status = 1;
|
||||
}
|
||||
else {
|
||||
con->input.status = 0;
|
||||
}
|
||||
/* return to regular vewing */
|
||||
fcntl(0, F_SETFL, flags);
|
||||
}
|
||||
return con->input.status;
|
||||
|
||||
case console_write_buffer:
|
||||
return con->output.buffer;
|
||||
|
||||
case console_write_status:
|
||||
return con->output.status;
|
||||
|
||||
default:
|
||||
error("console_read_callback() internal error\n");
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
STATIC_INLINE_DEVICES void
|
||||
console_write_callback(device_node *device,
|
||||
unsigned_word base,
|
||||
unsigned nr_bytes,
|
||||
unsigned64 val,
|
||||
cpu *processor,
|
||||
unsigned_word cia)
|
||||
{
|
||||
console_device *con = (console_device*)device->data;
|
||||
|
||||
TRACE(trace_console_device,
|
||||
("device=0x%x, base=0x%x, nr_bytes=%d, val=0x%x\n",
|
||||
device, base, nr_bytes, val));
|
||||
|
||||
/* check for bus error */
|
||||
if (base & 0x3) {
|
||||
error("%s - misaligned base address, base=0x%x, nr_bytes=%d\n",
|
||||
"console_write_callback", base, nr_bytes);
|
||||
}
|
||||
|
||||
switch (base & console_offset_mask) {
|
||||
case console_read_buffer: con->input.buffer = val; break;
|
||||
case console_read_status: con->input.status = val; break;
|
||||
case console_write_buffer:
|
||||
TRACE(trace_console_device,
|
||||
("<%c:%d>", val, val));
|
||||
printf_filtered("%c", val);
|
||||
con->output.buffer = val;
|
||||
con->output.status = 1;
|
||||
break;
|
||||
case console_write_status:
|
||||
con->output.status = val;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static device_callbacks console_callbacks = {
|
||||
console_read_callback,
|
||||
console_write_callback,
|
||||
};
|
||||
|
||||
STATIC_INLINE_DEVICES device_node *
|
||||
console_create(device_node *parent,
|
||||
char *name)
|
||||
{
|
||||
device_node *device;
|
||||
unsigned address_base;
|
||||
unsigned address_flags;
|
||||
|
||||
/* create the descriptor */
|
||||
console_device *console = ZALLOC(console_device);
|
||||
|
||||
/* extract the two arguments */
|
||||
parse_device_address(name, &address_base, &address_flags);
|
||||
|
||||
/* fill in the details */
|
||||
console->my_base_address = address_base;
|
||||
console->interrupt_delay = address_flags;
|
||||
console->output.status = 1;
|
||||
console->output.buffer = '\0';
|
||||
console->input.status = 0;
|
||||
console->input.buffer = '\0';
|
||||
|
||||
/* insert into the device tree along with its address info */
|
||||
device = device_node_create(parent, name, sequential_device,
|
||||
&console_callbacks, console);
|
||||
device_node_add_address(device,
|
||||
address_base,
|
||||
console_size,
|
||||
device_is_read_write_exec,
|
||||
NULL);
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
static device_descriptor console_descriptor = {
|
||||
"console",
|
||||
console_create,
|
||||
};
|
||||
|
||||
|
||||
/* ICU device:
|
||||
|
||||
Single 4 byte register. Read returns processor number. Write
|
||||
interrupts specified processor.
|
||||
|
||||
Illustrates passing of events to parent device. Passing of
|
||||
interrupts to parent bus.
|
||||
|
||||
NB: For the sake of illustrating the passing of interrupts. This
|
||||
device doesn't pass interrupt events to its parent. Instead it
|
||||
passes them back to its self. */
|
||||
|
||||
STATIC_INLINE_DEVICES unsigned64
|
||||
icu_read_callback(device_node *device,
|
||||
unsigned_word base,
|
||||
unsigned nr_bytes,
|
||||
cpu *processor,
|
||||
unsigned_word cia)
|
||||
{
|
||||
TRACE(trace_icu_device,
|
||||
("device=0x%x, base=0x%x, nr_bytes=%d\n",
|
||||
device, base, nr_bytes));
|
||||
return cpu_nr(processor);
|
||||
}
|
||||
|
||||
STATIC_INLINE_DEVICES void
|
||||
icu_write_callback(device_node *device,
|
||||
unsigned_word base,
|
||||
unsigned nr_bytes,
|
||||
unsigned64 val,
|
||||
cpu *processor,
|
||||
unsigned_word cia)
|
||||
{
|
||||
psim *system = cpu_system(processor);
|
||||
device_node *parent = device; /* NB: normally would be device->parent */
|
||||
TRACE(trace_icu_device,
|
||||
("device=0x%x, base=0x%x, nr_bytes=%d, val=0x%x\n",
|
||||
device, base, nr_bytes, val));
|
||||
/* tell the parent device that the interrupt lines have changed.
|
||||
For this fake ICU. The interrupt lines just indicate the cpu to
|
||||
interrupt next */
|
||||
parent->callbacks->interrupt_callback(parent, val, device, processor, cia);
|
||||
}
|
||||
|
||||
STATIC_INLINE_DEVICES void
|
||||
icu_do_interrupt(event_queue *queue,
|
||||
void *data)
|
||||
{
|
||||
cpu *target = (cpu*)data;
|
||||
/* try to interrupt the processor. If the attempt fails, try again
|
||||
on the next tick */
|
||||
if (!external_interrupt(target))
|
||||
event_queue_schedule(queue, 1, icu_do_interrupt, target);
|
||||
}
|
||||
|
||||
STATIC_INLINE_DEVICES void
|
||||
icu_interrupt_callback(device_node *me,
|
||||
int interrupt_status,
|
||||
device_node *device,
|
||||
cpu *processor,
|
||||
unsigned_word cia)
|
||||
{
|
||||
/* the interrupt controler can't interrupt a cpu at any time.
|
||||
Rather it must synchronize with the system clock before
|
||||
performing an interrupt on the given processor */
|
||||
psim *system = cpu_system(processor);
|
||||
cpu *target = psim_cpu(system, interrupt_status);
|
||||
if (target != NULL) {
|
||||
event_queue *events = cpu_event_queue(target);
|
||||
event_queue_schedule(events, 1, icu_do_interrupt, target);
|
||||
}
|
||||
}
|
||||
|
||||
static device_callbacks icu_callbacks = {
|
||||
icu_read_callback,
|
||||
icu_write_callback,
|
||||
icu_interrupt_callback,
|
||||
};
|
||||
|
||||
STATIC_INLINE_DEVICES device_node *
|
||||
icu_create(device_node *parent,
|
||||
char *name)
|
||||
{
|
||||
device_node *device;
|
||||
unsigned address_base;
|
||||
unsigned address_flags;
|
||||
|
||||
/* extract the two arguments */
|
||||
parse_device_address(name, &address_base, &address_flags);
|
||||
|
||||
/* insert into the device tree along with its address info */
|
||||
device = device_node_create(parent, name, sequential_device,
|
||||
&icu_callbacks, 0);
|
||||
device_node_add_address(device,
|
||||
address_base,
|
||||
4,
|
||||
device_is_read_write_exec,
|
||||
NULL);
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
static device_descriptor icu_descriptor = {
|
||||
"icu",
|
||||
icu_create,
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* HALT device:
|
||||
|
||||
With real hardware, the processor operation is normally terminated
|
||||
through a reset. This device illustrates how a reset device could
|
||||
be attached to an address */
|
||||
|
||||
STATIC_INLINE_DEVICES unsigned64
|
||||
halt_read_callback(device_node *device,
|
||||
unsigned_word base,
|
||||
unsigned nr_bytes,
|
||||
cpu *processor,
|
||||
unsigned_word cia)
|
||||
{
|
||||
cpu_halt(processor, cia, was_exited, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
STATIC_INLINE_DEVICES void
|
||||
halt_write_callback(device_node *device,
|
||||
unsigned_word base,
|
||||
unsigned nr_bytes,
|
||||
unsigned64 val,
|
||||
cpu *processor,
|
||||
unsigned_word cia)
|
||||
{
|
||||
cpu_halt(processor, cia, was_exited, 0);
|
||||
}
|
||||
|
||||
|
||||
static device_callbacks halt_callbacks = {
|
||||
halt_read_callback,
|
||||
halt_write_callback,
|
||||
};
|
||||
|
||||
STATIC_INLINE_DEVICES device_node *
|
||||
halt_create(device_node *parent,
|
||||
char *name)
|
||||
{
|
||||
device_node *device;
|
||||
unsigned address_base;
|
||||
unsigned address_flags;
|
||||
|
||||
parse_device_address(name, &address_base, &address_flags);
|
||||
device = device_node_create(parent, name, other_device,
|
||||
&halt_callbacks, NULL);
|
||||
device_node_add_address(device,
|
||||
address_base,
|
||||
4,
|
||||
device_is_read_write_exec,
|
||||
NULL);
|
||||
return device;
|
||||
}
|
||||
|
||||
static device_descriptor halt_descriptor = {
|
||||
"halt",
|
||||
halt_create,
|
||||
};
|
||||
|
||||
|
||||
static device_descriptor *devices[] = {
|
||||
&console_descriptor,
|
||||
&halt_descriptor,
|
||||
&icu_descriptor,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
INLINE_DEVICES device_descriptor *
|
||||
find_device_descriptor(char *name)
|
||||
{
|
||||
device_descriptor **device;
|
||||
int name_len;
|
||||
char *chp;
|
||||
chp = strchr(name, '@');
|
||||
name_len = (chp == NULL ? strlen(name) : chp - name);
|
||||
for (device = devices; *device != NULL; device++) {
|
||||
if (strncmp(name, (*device)->name, name_len) == 0
|
||||
&& ((*device)->name[name_len] == '\0'
|
||||
|| (*device)->name[name_len] == '@'))
|
||||
return *device;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* _DEVICES_C_ */
|
42
sim/ppc/devices.h
Normal file
42
sim/ppc/devices.h
Normal file
@ -0,0 +1,42 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _DEVICES_H_
|
||||
#define _DEVICES_H_
|
||||
|
||||
#ifndef INLINE_DEVICES
|
||||
#define INLINE_DEVICES
|
||||
#endif
|
||||
|
||||
#include "device_tree.h"
|
||||
|
||||
/* table of all the configured devices */
|
||||
|
||||
typedef struct _device_descriptor device_descriptor;
|
||||
struct _device_descriptor {
|
||||
char *name;
|
||||
device_creator *creator;
|
||||
};
|
||||
|
||||
|
||||
INLINE_DEVICES device_descriptor *find_device_descriptor(char *name);
|
||||
|
||||
#endif /* _DEVICES_H_ */
|
42
sim/ppc/double.c
Normal file
42
sim/ppc/double.c
Normal file
@ -0,0 +1,42 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _DOUBLE_C_
|
||||
#define _DOUBLE_C_
|
||||
|
||||
#include "basics.h"
|
||||
|
||||
#define SFtype unsigned32
|
||||
#define DFtype unsigned64
|
||||
|
||||
#define HItype signed16
|
||||
#define SItype signed32
|
||||
#define DItype signed64
|
||||
|
||||
#define UHItype unsigned16
|
||||
#define USItype unsigned32
|
||||
#define UDItype unsigned64
|
||||
|
||||
|
||||
#define US_SOFTWARE_GOFAST
|
||||
#include "dp-bit.c"
|
||||
|
||||
#endif
|
1307
sim/ppc/dp-bit.c
Normal file
1307
sim/ppc/dp-bit.c
Normal file
File diff suppressed because it is too large
Load Diff
238
sim/ppc/events.c
Normal file
238
sim/ppc/events.c
Normal file
@ -0,0 +1,238 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _EVENTS_C_
|
||||
#define _EVENTS_C_
|
||||
|
||||
#ifndef STATIC_INLINE_EVENTS
|
||||
#define STATIC_INLINE_EVENTS STATIC_INLINE
|
||||
#endif
|
||||
|
||||
|
||||
#include "basics.h"
|
||||
#include "events.h"
|
||||
|
||||
|
||||
/* The event queue maintains a single absolute time using two
|
||||
variables.
|
||||
|
||||
TIME_OF_EVENT: this holds the time at which the next event is ment
|
||||
to occure. If no next event it will hold the time of the last
|
||||
event. The first event occures at time 0 - system start.
|
||||
|
||||
TIME_FROM_EVENT: The current distance from TIME_OF_EVENT. If an
|
||||
event is pending, this will be positive. If no future event is
|
||||
pending this will be negative. This variable is decremented once
|
||||
for each iteration of a clock cycle.
|
||||
|
||||
Clearly there is a bug in that this code assumes that the absolute
|
||||
time counter will never become greater than 2^62. */
|
||||
|
||||
typedef struct _event_entry event_entry;
|
||||
struct _event_entry {
|
||||
void *data;
|
||||
event_handler *handler;
|
||||
signed64 time_of_event;
|
||||
event_entry *next;
|
||||
};
|
||||
|
||||
struct _event_queue {
|
||||
event_entry *queue;
|
||||
event_entry *volatile held;
|
||||
event_entry *volatile *volatile held_end;
|
||||
signed64 time_of_event;
|
||||
signed64 time_from_event;
|
||||
};
|
||||
|
||||
|
||||
INLINE_EVENTS event_queue *
|
||||
event_queue_create(void)
|
||||
{
|
||||
event_queue *new_event_queue = ZALLOC(event_queue);
|
||||
|
||||
new_event_queue->queue = NULL;
|
||||
new_event_queue->held = NULL;
|
||||
new_event_queue->held_end = &new_event_queue->held;
|
||||
/* both times are already zero */
|
||||
return new_event_queue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
STATIC_INLINE_EVENTS void
|
||||
insert_event_entry(event_queue *events,
|
||||
event_entry *new_event,
|
||||
signed64 delta)
|
||||
{
|
||||
event_entry *curr;
|
||||
event_entry **last;
|
||||
signed64 time_of_event;
|
||||
|
||||
if (delta <= 0)
|
||||
error("can not schedule event for current time\n");
|
||||
|
||||
/* compute when the event should occure */
|
||||
time_of_event = (events->time_of_event
|
||||
- events->time_from_event
|
||||
+ delta);
|
||||
|
||||
/* find the queue insertion point - things are time ordered */
|
||||
last = &events->queue;
|
||||
curr = events->queue;
|
||||
while (curr != NULL && time_of_event >= curr->time_of_event) {
|
||||
last = &curr->next;
|
||||
curr = curr->next;
|
||||
}
|
||||
|
||||
/* insert it */
|
||||
new_event->next = curr;
|
||||
*last = new_event;
|
||||
new_event->time_of_event = time_of_event;
|
||||
|
||||
/* adjust the time until the first event */
|
||||
events->time_from_event = (events->queue->time_of_event
|
||||
- (events->time_of_event
|
||||
- events->time_from_event));
|
||||
events->time_of_event = events->queue->time_of_event;
|
||||
}
|
||||
|
||||
INLINE_EVENTS event_entry_tag
|
||||
event_queue_schedule(event_queue *events,
|
||||
signed64 delta_time,
|
||||
event_handler *handler,
|
||||
void *data)
|
||||
{
|
||||
event_entry *new_event = ZALLOC(event_entry);
|
||||
new_event->data = data;
|
||||
new_event->handler = handler;
|
||||
insert_event_entry(events, new_event, delta_time);
|
||||
return new_event;
|
||||
}
|
||||
|
||||
|
||||
INLINE_EVENTS event_entry_tag
|
||||
event_queue_schedule_after_signal(event_queue *events,
|
||||
signed64 delta_time,
|
||||
event_handler *handler,
|
||||
void *data)
|
||||
{
|
||||
event_entry *new_event = ZALLOC(event_entry);
|
||||
|
||||
new_event->data = data;
|
||||
new_event->handler = handler;
|
||||
new_event->time_of_event = delta_time; /* work it out later */
|
||||
new_event->next = NULL;
|
||||
|
||||
/*-LOCK-*/
|
||||
if (events->held == NULL) {
|
||||
events->held = new_event;
|
||||
}
|
||||
else {
|
||||
*events->held_end = new_event;
|
||||
}
|
||||
events->held_end = &new_event->next;
|
||||
/*-UNLOCK-*/
|
||||
|
||||
return new_event;
|
||||
}
|
||||
|
||||
|
||||
INLINE_EVENTS void
|
||||
event_queue_deschedule(event_queue *events,
|
||||
event_entry_tag event_to_remove)
|
||||
{
|
||||
if (event_to_remove != NULL) {
|
||||
event_entry *current;
|
||||
event_entry **ptr_to_current;
|
||||
for (ptr_to_current = &events->queue, current = *ptr_to_current;
|
||||
current != NULL && current != event_to_remove;
|
||||
ptr_to_current = ¤t->next, current = *ptr_to_current);
|
||||
if (current == event_to_remove) {
|
||||
*ptr_to_current = current->next;
|
||||
zfree(current);
|
||||
/* Just forget to recompute the delay to the next event */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
INLINE_EVENTS int
|
||||
event_queue_tick(event_queue *events)
|
||||
{
|
||||
/* remove things from the asynchronous event queue onto the real one */
|
||||
if (events->held != NULL) {
|
||||
event_entry *held_events;
|
||||
event_entry *curr_event;
|
||||
|
||||
/*-LOCK-*/
|
||||
held_events = events->held;
|
||||
events->held = NULL;
|
||||
events->held_end = &events->held;
|
||||
/*-UNLOCK-*/
|
||||
|
||||
do {
|
||||
curr_event = held_events;
|
||||
held_events = curr_event->next;
|
||||
insert_event_entry(events, curr_event, curr_event->time_of_event);
|
||||
} while (held_events != NULL);
|
||||
}
|
||||
|
||||
/* advance time, checking to see if we've reached time zero which
|
||||
would indicate the time for the next event has arrived */
|
||||
events->time_from_event -= 1;
|
||||
return events->time_from_event == 0;
|
||||
}
|
||||
|
||||
INLINE_EVENTS void
|
||||
event_queue_process(event_queue *events)
|
||||
{
|
||||
if (events->time_from_event == 0) {
|
||||
/* consume all events for this or earlier times */
|
||||
do {
|
||||
event_entry *to_do = events->queue;
|
||||
events->queue = to_do->next;
|
||||
to_do->handler(events,
|
||||
to_do->data);
|
||||
zfree(to_do);
|
||||
} while (events->queue != NULL
|
||||
&& events->queue->time_of_event <= events->time_of_event);
|
||||
/* re-caculate time for new events */
|
||||
if (events->queue != NULL) {
|
||||
events->time_from_event = (events->queue->time_of_event
|
||||
- events->time_of_event);
|
||||
events->time_of_event = events->queue->time_of_event;
|
||||
}
|
||||
else {
|
||||
/* nothing to do, time_from_event will go negative */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INLINE_EVENTS signed64
|
||||
event_queue_time(event_queue *queue)
|
||||
{
|
||||
return queue->time_of_event - queue->time_from_event;
|
||||
}
|
||||
|
||||
|
||||
#endif /* _EVENTS_C_ */
|
75
sim/ppc/events.h
Normal file
75
sim/ppc/events.h
Normal file
@ -0,0 +1,75 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _EVENTS_H_
|
||||
#define _EVENTS_H_
|
||||
|
||||
#ifndef INLINE_EVENTS
|
||||
#define INLINE_EVENTS
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct _event_queue event_queue;
|
||||
typedef void *event_entry_tag;
|
||||
|
||||
typedef void event_handler
|
||||
(event_queue *queue,
|
||||
void *data);
|
||||
|
||||
INLINE_EVENTS event_queue *event_queue_create
|
||||
(void);
|
||||
|
||||
|
||||
/* (de)Schedule things to happen in the future. */
|
||||
|
||||
INLINE_EVENTS event_entry_tag event_queue_schedule
|
||||
(event_queue *queue,
|
||||
signed64 delta_time,
|
||||
event_handler *handler,
|
||||
void *data);
|
||||
|
||||
INLINE_EVENTS event_entry_tag event_queue_schedule_after_signal
|
||||
(event_queue *queue,
|
||||
signed64 delta_time,
|
||||
event_handler *handler,
|
||||
void *data);
|
||||
|
||||
INLINE_EVENTS void event_queue_deschedule
|
||||
(event_queue *queue,
|
||||
event_entry_tag event_to_remove);
|
||||
|
||||
|
||||
/* progress time. In to parts so that if something is pending, the
|
||||
caller has a chance to save any cached state */
|
||||
|
||||
INLINE_EVENTS int event_queue_tick
|
||||
(event_queue *queue);
|
||||
|
||||
INLINE_EVENTS void event_queue_process
|
||||
(event_queue *events);
|
||||
|
||||
|
||||
/* local concept of time */
|
||||
|
||||
INLINE_EVENTS signed64 event_queue_time
|
||||
(event_queue *queue);
|
||||
|
||||
#endif /* _EVENTS_H_ */
|
3111
sim/ppc/gen.c
Normal file
3111
sim/ppc/gen.c
Normal file
File diff suppressed because it is too large
Load Diff
62
sim/ppc/idecode_branch.h
Normal file
62
sim/ppc/idecode_branch.h
Normal file
@ -0,0 +1,62 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* branch macro's:
|
||||
|
||||
The macro's below implement the semantics of the PowerPC jump
|
||||
instructions. */
|
||||
|
||||
|
||||
/* If so required, update the Link Register with the next sequential
|
||||
instruction address */
|
||||
|
||||
#define UPDATE_LK \
|
||||
do { \
|
||||
if (update_LK) { \
|
||||
ppc_ia target = cia + 4; \
|
||||
ppc_spr new_address = (ppc_spr)IEA_MASKED(ppc_is_64bit(processor), \
|
||||
target); \
|
||||
LR = new_address; \
|
||||
} \
|
||||
ITRACE(trace_branch, \
|
||||
("UPDATE_LK - update_LK=%d lr=0x%x cia=0x%x\n", \
|
||||
update_LK, LR, cia); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* take the branch - absolute or relative - possibly updating the link
|
||||
register */
|
||||
|
||||
#define BRANCH(ADDRESS) \
|
||||
do { \
|
||||
UPDATE_LK; \
|
||||
if (update_AA) { \
|
||||
ppc_ia target = (ppc_ia)(ADDRESS); \
|
||||
nia = (ppc_ia)IEA_MASKED(ppc_is_64bit(processor), target); \
|
||||
} \
|
||||
else { \
|
||||
ppc_ia target = cia + ADDRESS; \
|
||||
nia = (ppc_ia)IEA_MASKED(ppc_is_64bit(processor), target); \
|
||||
} \
|
||||
PTRACE(trace_branch, \
|
||||
("BRANCH - update_AA=%d update_LK=%d nia=0x%x cia=0x%x\n", \
|
||||
update_AA, update_LK, nia, cia); \
|
||||
} while (0)
|
103
sim/ppc/idecode_fields.h
Normal file
103
sim/ppc/idecode_fields.h
Normal file
@ -0,0 +1,103 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* Instruction field macros:
|
||||
|
||||
The macro's below greatly simplify the process of translating the
|
||||
pseudo code found in the PowerPC manual into C.
|
||||
|
||||
In addition to the below, more will be found in the gen program's
|
||||
cache table */
|
||||
|
||||
|
||||
/* map some statements and variables directly across */
|
||||
|
||||
#define then /*then*/
|
||||
#define is_64bit_implementation WITH_64BIT_TARGET
|
||||
#define is_64bit_mode IS_64BIT_MODE(processor)
|
||||
|
||||
#define NIA nia
|
||||
#define CIA cia
|
||||
|
||||
|
||||
/* reservation */
|
||||
|
||||
#define RESERVE cpu_reservation(processor)->valid
|
||||
#define RESERVE_ADDR cpu_reservation(processor)->addr
|
||||
#define RESERVE_DATA cpu_reservation(processor)->data
|
||||
|
||||
#define real_addr(EA, IS_READ) vm_real_data_addr(cpu_data_map(processor), \
|
||||
EA, \
|
||||
IS_READ, \
|
||||
processor, \
|
||||
cia)
|
||||
|
||||
|
||||
/* depending on mode return a 32 or 64bit number */
|
||||
|
||||
#define IEA(X) (is_64bit_mode \
|
||||
? (X) \
|
||||
: MASKED((X), 32, 63))
|
||||
|
||||
/* Expand argument to current architecture size */
|
||||
|
||||
#define EXTS(X) EXTS_##X
|
||||
|
||||
|
||||
/* Gen translates text of the form A{XX:YY} into A_XX_YY_ the macro's
|
||||
below define such translated text into real expressions */
|
||||
|
||||
/* the spr field as it normally is used */
|
||||
|
||||
#define spr_5_9_ (spr & 0x1f)
|
||||
#define spr_0_4_ (spr >> 5)
|
||||
#define spr_0_ ((spr & BIT10(0)) != 0)
|
||||
|
||||
#define tbr_5_9_ (tbr & 0x1f)
|
||||
#define tbr_0_4_ (tbr >> 5)
|
||||
|
||||
|
||||
#define TB cpu_get_time_base(processor)
|
||||
|
||||
|
||||
/* various registers with important masks */
|
||||
|
||||
#define LR_0b00 (LR & ~3)
|
||||
#define CTR_0b00 (CTR & ~3)
|
||||
|
||||
#define CR_BI_ ((CR & BIT32_BI) != 0)
|
||||
#define CR_BA_ ((CR & BIT32_BA) != 0)
|
||||
#define CR_BB_ ((CR & BIT32_BB) != 0)
|
||||
|
||||
|
||||
/* extended extracted fields */
|
||||
|
||||
#define TO_0_ ((TO & BIT5(0)) != 0)
|
||||
#define TO_1_ ((TO & BIT5(1)) != 0)
|
||||
#define TO_2_ ((TO & BIT5(2)) != 0)
|
||||
#define TO_3_ ((TO & BIT5(3)) != 0)
|
||||
#define TO_4_ ((TO & BIT5(4)) != 0)
|
||||
|
||||
#define BO_0_ ((BO & BIT5(0)) != 0)
|
||||
#define BO_1_ ((BO & BIT5(1)) != 0)
|
||||
#define BO_2_ ((BO & BIT5(2)) != 0)
|
||||
#define BO_3_ ((BO & BIT5(3)) != 0)
|
||||
#define BO_4_ ((BO & BIT5(4)) != 0)
|
67
sim/ppc/idecode_insn.h
Normal file
67
sim/ppc/idecode_insn.h
Normal file
@ -0,0 +1,67 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Interface for the Instruction execution routines
|
||||
*/
|
||||
|
||||
/*
|
||||
* Macro's that define the parts of an instruction
|
||||
*/
|
||||
|
||||
#define FLOATING_POINT_ENABLED_PROGRAM_INTERRUPT \
|
||||
program_interrupt(processor, \
|
||||
cia, \
|
||||
floating_point_enabled_program_interrupt)
|
||||
|
||||
#define ILLEGAL_INSN_PROGRAM_INTERRUPT \
|
||||
program_interrupt(processor, \
|
||||
cia, \
|
||||
illegal_instruction_program_interrupt)
|
||||
#define PRIVILEGED_INSN_PROGRAM_INTERRUPT \
|
||||
program_interrupt(processor, \
|
||||
cia, \
|
||||
privileged_instruction_program_interrupt)
|
||||
|
||||
#define TRAP_PROGRAM_INTERRUPT \
|
||||
program_interrupt(processor, \
|
||||
cia, \
|
||||
trap_program_interrupt)
|
||||
|
||||
#define FLOATING_POINT_UNAVAILABLE_INTERRUPT \
|
||||
floating_point_unavailable_interrupt(processor, \
|
||||
cia)
|
||||
|
||||
#define FLOATING_POINT_ASSIST_INTERRUPT \
|
||||
floating_point_assist_interrupt(processor, \
|
||||
cia)
|
||||
|
||||
#define BREAKPOINT \
|
||||
do { \
|
||||
ITRACE(trace_breakpoint, \
|
||||
("breakpoint - cia0x%x\n", \
|
||||
cia)); \
|
||||
cpu_halt(processor, cia, was_trap, 0); \
|
||||
} while (0)
|
||||
|
||||
#define SYSTEM_CALL_INTERRUPT \
|
||||
system_call_interrupt(processor, \
|
||||
cia)
|
355
sim/ppc/memory_map.c
Normal file
355
sim/ppc/memory_map.c
Normal file
@ -0,0 +1,355 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _MEMORY_MAP_C_
|
||||
#define _MEMORY_MAP_C_
|
||||
|
||||
#ifndef STATIC_INLINE_MEMORY_MAP
|
||||
#define STATIC_INLINE_MEMORY_MAP STATIC_INLINE
|
||||
#endif
|
||||
|
||||
|
||||
#include "basics.h"
|
||||
#include "device_tree.h"
|
||||
#include "memory_map.h"
|
||||
#include "interrupts.h"
|
||||
|
||||
|
||||
typedef struct _memory_mapping memory_mapping;
|
||||
struct _memory_mapping {
|
||||
/* ram map */
|
||||
void *buffer;
|
||||
/* device map */
|
||||
device_node *device;
|
||||
device_reader_callback *reader;
|
||||
device_writer_callback *writer;
|
||||
/* common */
|
||||
unsigned_word base;
|
||||
unsigned_word bound;
|
||||
unsigned_word size;
|
||||
struct _memory_mapping *next;
|
||||
};
|
||||
|
||||
struct _memory_map {
|
||||
memory_mapping *first;
|
||||
};
|
||||
|
||||
INLINE_MEMORY_MAP memory_map *
|
||||
new_memory_map(void)
|
||||
{
|
||||
memory_map *new_map;
|
||||
new_map = ZALLOC(memory_map);
|
||||
return new_map;
|
||||
}
|
||||
|
||||
STATIC_INLINE_MEMORY_MAP void
|
||||
memory_map_add_memory(memory_map *map,
|
||||
device_node *device,
|
||||
device_reader_callback *reader,
|
||||
device_writer_callback *writer,
|
||||
void *buffer,
|
||||
unsigned_word base,
|
||||
unsigned size)
|
||||
{
|
||||
memory_mapping *new_mapping;
|
||||
memory_mapping *next_mapping;
|
||||
memory_mapping **last_mapping;
|
||||
|
||||
/* actually do occasionally get a zero size map */
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
new_mapping = ZALLOC(memory_mapping);
|
||||
|
||||
/* ram */
|
||||
new_mapping->buffer = buffer;
|
||||
/* devices */
|
||||
new_mapping->device = device;
|
||||
new_mapping->reader = reader;
|
||||
new_mapping->writer = writer;
|
||||
/* common */
|
||||
new_mapping->base = base;
|
||||
new_mapping->size = size;
|
||||
new_mapping->bound = base + size;
|
||||
|
||||
/* find the insertion point (between last/next) */
|
||||
next_mapping = map->first;
|
||||
last_mapping = &map->first;
|
||||
while(next_mapping != NULL && next_mapping->bound <= new_mapping->base) {
|
||||
/* assert: new_mapping->base > all bases before next_mapping */
|
||||
/* assert: new_mapping->bound >= all bounds before next_mapping */
|
||||
last_mapping = &next_mapping->next;
|
||||
next_mapping = next_mapping->next;
|
||||
}
|
||||
|
||||
/* check insertion point correct */
|
||||
if (next_mapping != NULL && next_mapping->base < new_mapping->bound) {
|
||||
error("memory_map_add_callback_memory() internal error - map overlap\n");
|
||||
}
|
||||
|
||||
/* insert the new mapping */
|
||||
*last_mapping = new_mapping;
|
||||
new_mapping->next = next_mapping;
|
||||
|
||||
}
|
||||
|
||||
|
||||
INLINE_MEMORY_MAP void
|
||||
memory_map_add_callback_memory(memory_map *map,
|
||||
device_node *device,
|
||||
device_reader_callback *reader,
|
||||
device_writer_callback *writer,
|
||||
unsigned_word base,
|
||||
unsigned size)
|
||||
{
|
||||
memory_map_add_memory(map, device, reader, writer, NULL, base, size);
|
||||
}
|
||||
|
||||
INLINE_MEMORY_MAP void
|
||||
memory_map_add_raw_memory(memory_map *map,
|
||||
void *buffer,
|
||||
unsigned_word base,
|
||||
unsigned size)
|
||||
{
|
||||
memory_map_add_memory(map, NULL, NULL, NULL, buffer, base, size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
STATIC_INLINE_MEMORY_MAP memory_mapping *
|
||||
memory_map_find_mapping(memory_map *map,
|
||||
unsigned_word addr,
|
||||
unsigned nr_bytes,
|
||||
int abort,
|
||||
cpu *processor,
|
||||
unsigned_word cia)
|
||||
{
|
||||
memory_mapping *mapping = map->first;
|
||||
ASSERT((addr & (nr_bytes-1)) == 0);
|
||||
while (1) {
|
||||
if (addr >= mapping->base
|
||||
&& (addr + nr_bytes) <= mapping->bound)
|
||||
break;
|
||||
mapping = mapping->next;
|
||||
if (mapping == NULL) {
|
||||
if (abort) {
|
||||
switch (CURRENT_ENVIRONMENT) {
|
||||
case VIRTUAL_ENVIRONMENT:
|
||||
data_storage_interrupt(processor,
|
||||
cia,
|
||||
addr,
|
||||
vea_storage_interrupt,
|
||||
0/* doesnt matter */);
|
||||
break;
|
||||
default:
|
||||
error("memory_map_find_mapping() - %s%x%s%s%s%s%s",
|
||||
"access to undefined address 0x", addr, "\n",
|
||||
"this code should be passing back up the device tree an\n",
|
||||
"abort event (with processor attached). Somewhere in\n",
|
||||
"the device tree this would be caught and either halt,\n",
|
||||
"interrupt, or reset the processor\n");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return mapping;
|
||||
}
|
||||
|
||||
|
||||
STATIC_INLINE_MEMORY_MAP void *
|
||||
memory_map_translate(memory_mapping *mapping,
|
||||
unsigned_word addr)
|
||||
{
|
||||
return mapping->buffer + addr - mapping->base;
|
||||
}
|
||||
|
||||
|
||||
INLINE_MEMORY_MAP unsigned
|
||||
memory_map_read_buffer(memory_map *map,
|
||||
void *buffer,
|
||||
unsigned_word addr,
|
||||
unsigned len,
|
||||
transfer_mode mode)
|
||||
{
|
||||
unsigned count;
|
||||
unsigned_1 byte;
|
||||
for (count = 0; count < len; count++) {
|
||||
unsigned pos = 0;
|
||||
unsigned_word raddr = addr + count;
|
||||
memory_mapping *mapping =
|
||||
memory_map_find_mapping(map, raddr, 1,
|
||||
0/*abort*/,
|
||||
0, 0/*processor, cia*/);
|
||||
if (mapping == NULL)
|
||||
break;
|
||||
if (mode == raw_transfer ||
|
||||
CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER)
|
||||
pos = count;
|
||||
else if (mode == cooked_transfer)
|
||||
pos = len-count-1;
|
||||
else
|
||||
error("memory_map_read_buffer() - transfer mode unknown\n");
|
||||
if (mapping->reader != NULL)
|
||||
/* hope it doesn't barf */
|
||||
byte = mapping->reader(mapping->device,
|
||||
raddr - mapping->base,
|
||||
1,
|
||||
0, 0/*processor, cia*/);
|
||||
else
|
||||
byte = *(unsigned_1*)memory_map_translate(mapping,
|
||||
raddr);
|
||||
((unsigned_1*)buffer)[pos] = T2H_1(byte);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
INLINE_MEMORY_MAP unsigned
|
||||
memory_map_write_buffer(memory_map *map,
|
||||
const void *buffer,
|
||||
unsigned_word addr,
|
||||
unsigned len,
|
||||
transfer_mode mode)
|
||||
{
|
||||
unsigned count;
|
||||
unsigned_1 byte;
|
||||
for (count = 0; count < len; count++) {
|
||||
unsigned pos = 0;
|
||||
unsigned_word raddr = addr + count;
|
||||
memory_mapping *mapping =
|
||||
memory_map_find_mapping(map, raddr, 1,
|
||||
0/*abort*/,
|
||||
0, 0/*processor, cia*/);
|
||||
if (mapping == NULL)
|
||||
break;
|
||||
if (mode == raw_transfer ||
|
||||
CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER)
|
||||
pos = count;
|
||||
else if (mode == cooked_transfer)
|
||||
pos = len-count-1;
|
||||
else
|
||||
error("memory_map_write_buffer() - transfer mode unknown\n");
|
||||
byte = H2T_1(((unsigned_1*)buffer)[pos]);
|
||||
if (mapping->writer != NULL)
|
||||
/* hope it doesn't barf */
|
||||
mapping->writer(mapping->device,
|
||||
raddr - mapping->base,
|
||||
1,
|
||||
byte,
|
||||
0, 0/*processor, cia*/);
|
||||
else
|
||||
*(unsigned_1*)memory_map_translate(mapping, raddr) = byte;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
INLINE_MEMORY_MAP unsigned
|
||||
memory_map_zero(memory_map *map,
|
||||
unsigned_word addr,
|
||||
unsigned len)
|
||||
{
|
||||
unsigned pos;
|
||||
for (pos = 0; pos < len; pos++) {
|
||||
unsigned_word raddr = addr + pos;
|
||||
memory_mapping *mapping =
|
||||
memory_map_find_mapping(map, raddr, 1,
|
||||
0/*abort*/,
|
||||
0, 0/*processor, cia*/);
|
||||
if (mapping == NULL)
|
||||
break;
|
||||
if (mapping->writer != NULL)
|
||||
mapping->writer(mapping->device,
|
||||
raddr - mapping->base,
|
||||
1,
|
||||
0,
|
||||
0, 0/*processor, cia*/);
|
||||
else
|
||||
*(unsigned_1*)memory_map_translate(mapping, raddr) = 0;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
#define DEFINE_MEMORY_MAP_READ_N(N) \
|
||||
INLINE_MEMORY_MAP unsigned_##N \
|
||||
memory_map_read_##N(memory_map *map, \
|
||||
unsigned_word addr, \
|
||||
cpu *processor, \
|
||||
unsigned_word cia) \
|
||||
{ \
|
||||
memory_mapping *mapping = memory_map_find_mapping(map, addr, \
|
||||
sizeof(unsigned_##N), \
|
||||
1, \
|
||||
processor, \
|
||||
cia); \
|
||||
if (WITH_CALLBACK_MEMORY && mapping->reader != NULL) \
|
||||
return ((unsigned_##N) \
|
||||
mapping->reader(mapping->device, \
|
||||
addr - mapping->base, \
|
||||
sizeof(unsigned_##N), \
|
||||
processor, \
|
||||
cia)); \
|
||||
else \
|
||||
return T2H_##N(*(unsigned_##N*)memory_map_translate(mapping, addr)); \
|
||||
}
|
||||
|
||||
DEFINE_MEMORY_MAP_READ_N(1)
|
||||
DEFINE_MEMORY_MAP_READ_N(2)
|
||||
DEFINE_MEMORY_MAP_READ_N(4)
|
||||
DEFINE_MEMORY_MAP_READ_N(8)
|
||||
DEFINE_MEMORY_MAP_READ_N(word)
|
||||
|
||||
#define DEFINE_MEMORY_MAP_WRITE_N(N) \
|
||||
INLINE_MEMORY_MAP void \
|
||||
memory_map_write_##N(memory_map *map, \
|
||||
unsigned_word addr, \
|
||||
unsigned_##N val, \
|
||||
cpu *processor, \
|
||||
unsigned_word cia) \
|
||||
{ \
|
||||
memory_mapping *mapping = memory_map_find_mapping(map, addr, \
|
||||
sizeof(unsigned_##N), \
|
||||
1, \
|
||||
processor, \
|
||||
cia); \
|
||||
if (WITH_CALLBACK_MEMORY && mapping->writer != NULL) \
|
||||
mapping->writer(mapping->device, \
|
||||
addr - mapping->base, \
|
||||
sizeof(unsigned_##N), \
|
||||
val, \
|
||||
processor, \
|
||||
cia); \
|
||||
else \
|
||||
*(unsigned_##N*)memory_map_translate(mapping, addr) = H2T_##N(val); \
|
||||
}
|
||||
|
||||
DEFINE_MEMORY_MAP_WRITE_N(1)
|
||||
DEFINE_MEMORY_MAP_WRITE_N(2)
|
||||
DEFINE_MEMORY_MAP_WRITE_N(4)
|
||||
DEFINE_MEMORY_MAP_WRITE_N(8)
|
||||
DEFINE_MEMORY_MAP_WRITE_N(word)
|
||||
|
||||
#endif /* _MEMORY_MAP_C_ */
|
126
sim/ppc/memory_map.h
Normal file
126
sim/ppc/memory_map.h
Normal file
@ -0,0 +1,126 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _MEMORY_MAP_H_
|
||||
#define _MEMORY_MAP_H_
|
||||
|
||||
#ifndef INLINE_MEMORY_MAP
|
||||
#define INLINE_MEMORY_MAP
|
||||
#endif
|
||||
|
||||
/* basic types */
|
||||
|
||||
typedef struct _memory_map memory_map;
|
||||
|
||||
|
||||
/* constructor */
|
||||
|
||||
INLINE_MEMORY_MAP memory_map *new_memory_map
|
||||
(void);
|
||||
|
||||
|
||||
/* operators to add memory to a memory map
|
||||
|
||||
callback-memory:
|
||||
|
||||
includes a callback routine that is called upon for the data.
|
||||
Useful when modeling memory mapped devices.
|
||||
|
||||
raw-memory:
|
||||
|
||||
normal base and bound memory map used to model ram or mapped memory
|
||||
pages */
|
||||
|
||||
INLINE_MEMORY_MAP void memory_map_add_callback_memory
|
||||
(memory_map *map,
|
||||
device_node *device,
|
||||
device_reader_callback *reader,
|
||||
device_writer_callback *writer,
|
||||
unsigned_word base,
|
||||
unsigned size); /* host limited */
|
||||
|
||||
INLINE_MEMORY_MAP void memory_map_add_raw_memory
|
||||
(memory_map *map,
|
||||
void *buffer,
|
||||
unsigned_word base,
|
||||
unsigned size/*host limited*/);
|
||||
|
||||
|
||||
/* Variable sized read/write/zero:
|
||||
|
||||
Transfer (zero) a variable size block of data between the host and
|
||||
target (possibly byte swapping it). Should any problems occure,
|
||||
the number of bytes actually transfered is returned. */
|
||||
|
||||
INLINE_MEMORY_MAP unsigned memory_map_read_buffer
|
||||
(memory_map *map,
|
||||
void *buffer,
|
||||
unsigned_word addr,
|
||||
unsigned len,
|
||||
transfer_mode mode);
|
||||
|
||||
INLINE_MEMORY_MAP unsigned memory_map_write_buffer
|
||||
(memory_map *map,
|
||||
const void *buffer,
|
||||
unsigned_word addr,
|
||||
unsigned len,
|
||||
transfer_mode mode);
|
||||
|
||||
INLINE_MEMORY_MAP unsigned memory_map_zero
|
||||
(memory_map *map,
|
||||
unsigned_word addr,
|
||||
unsigned len);
|
||||
|
||||
|
||||
/* Fixed sized read/write:
|
||||
|
||||
Transfer a fixed amout of memory between the host and target. The
|
||||
memory always being translated and the operation always aborting
|
||||
should a problem occure */
|
||||
|
||||
#define DECLARE_MEMORY_MAP_WRITE_N(N) \
|
||||
INLINE_MEMORY_MAP void memory_map_write_##N \
|
||||
(memory_map *map, \
|
||||
unsigned_word addr, \
|
||||
unsigned_##N val, \
|
||||
cpu *processor, \
|
||||
unsigned_word cia);
|
||||
|
||||
DECLARE_MEMORY_MAP_WRITE_N(1)
|
||||
DECLARE_MEMORY_MAP_WRITE_N(2)
|
||||
DECLARE_MEMORY_MAP_WRITE_N(4)
|
||||
DECLARE_MEMORY_MAP_WRITE_N(8)
|
||||
DECLARE_MEMORY_MAP_WRITE_N(word)
|
||||
|
||||
#define DECLARE_MEMORY_MAP_READ_N(N) \
|
||||
INLINE_MEMORY_MAP unsigned_##N memory_map_read_##N \
|
||||
(memory_map *map, \
|
||||
unsigned_word addr, \
|
||||
cpu *processor, \
|
||||
unsigned_word cia);
|
||||
|
||||
DECLARE_MEMORY_MAP_READ_N(1)
|
||||
DECLARE_MEMORY_MAP_READ_N(2)
|
||||
DECLARE_MEMORY_MAP_READ_N(4)
|
||||
DECLARE_MEMORY_MAP_READ_N(8)
|
||||
DECLARE_MEMORY_MAP_READ_N(word)
|
||||
|
||||
#endif
|
70
sim/ppc/ppc-endian.c
Normal file
70
sim/ppc/ppc-endian.c
Normal file
@ -0,0 +1,70 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _ENDIAN_C_
|
||||
#define _ENDIAN_C_
|
||||
|
||||
#ifndef STATIC_INLINE_ENDIAN
|
||||
#define STATIC_INLINE_ENDIAN STATIC_INLINE
|
||||
#endif
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include "words.h"
|
||||
#include "ppc-endian.h"
|
||||
#include "sim_callbacks.h"
|
||||
|
||||
|
||||
typedef union {
|
||||
unsigned_1 val_1[8];
|
||||
unsigned_2 val_2[4];
|
||||
unsigned_4 val_4[2];
|
||||
unsigned_8 val_8[1];
|
||||
} endian_map;
|
||||
|
||||
#define ENDIAN_N(NAME,BYTE_SIZE) \
|
||||
unsigned_##BYTE_SIZE \
|
||||
endian_##NAME##_##BYTE_SIZE(unsigned_##BYTE_SIZE raw_in) \
|
||||
{ \
|
||||
if (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER) { \
|
||||
return raw_in; \
|
||||
} \
|
||||
else { \
|
||||
endian_map in; \
|
||||
endian_map out; \
|
||||
int byte_nr; \
|
||||
in.val_##BYTE_SIZE[0] = raw_in; \
|
||||
for (byte_nr = 0; byte_nr < BYTE_SIZE; byte_nr++) { \
|
||||
out.val_1[BYTE_SIZE-1-byte_nr] = in.val_1[byte_nr]; \
|
||||
} \
|
||||
return out.val_##BYTE_SIZE[0]; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
ENDIAN_N(h2t, 2)
|
||||
ENDIAN_N(h2t, 4)
|
||||
ENDIAN_N(h2t, 8)
|
||||
ENDIAN_N(t2h, 2)
|
||||
ENDIAN_N(t2h, 4)
|
||||
ENDIAN_N(t2h, 8)
|
||||
|
||||
#endif /* _ENDIAN_C_ */
|
256
sim/ppc/ppc-endian.h
Normal file
256
sim/ppc/ppc-endian.h
Normal file
@ -0,0 +1,256 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _ENDIAN_H_
|
||||
#define _ENDIAN_H_
|
||||
|
||||
/* C byte conversion functions */
|
||||
|
||||
extern unsigned_1 endian_h2t_1(unsigned_1 x);
|
||||
extern unsigned_2 endian_h2t_2(unsigned_2 x);
|
||||
extern unsigned_4 endian_h2t_4(unsigned_4 x);
|
||||
extern unsigned_8 endian_h2t_8(unsigned_8 x);
|
||||
|
||||
extern unsigned_1 endian_t2h_1(unsigned_1 x);
|
||||
extern unsigned_2 endian_t2h_2(unsigned_2 x);
|
||||
extern unsigned_4 endian_t2h_4(unsigned_4 x);
|
||||
extern unsigned_8 endian_t2h_8(unsigned_8 x);
|
||||
|
||||
/* Host dependant:
|
||||
|
||||
The CPP below defines information about the compilation host. In
|
||||
particular it defines the macro's:
|
||||
|
||||
WITH_HOST_BYTE_ORDER The byte order of the host. Could
|
||||
be any of LITTLE_ENDIAN, BIG_ENDIAN
|
||||
or 0 (unknown). Those macro's also
|
||||
need to be defined.
|
||||
|
||||
WITH_NTOH Network byte order macros defined.
|
||||
Possible value is 32 or (maybe one
|
||||
day 64 because some 64bit network
|
||||
byte order macro is defined.
|
||||
*/
|
||||
|
||||
|
||||
/* NetBSD:
|
||||
|
||||
NetBSD is easy, everything you could ever want is in a header file
|
||||
(well almost :-) */
|
||||
|
||||
#if defined(__NetBSD__)
|
||||
# include <machine/endian.h>
|
||||
# define WITH_NTOH 32 /* what about alpha? */
|
||||
# if (WITH_HOST_BYTE_ORDER == 0)
|
||||
# undef WITH_HOST_BYTE_ORDER
|
||||
# define WITH_HOST_BYTE_ORDER BYTE_ORDER
|
||||
# endif
|
||||
# if (BYTE_ORDER != WITH_HOST_BYTE_ORDER)
|
||||
# error "host endian incorrectly configured, check config.h"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Linux is similarly easy. */
|
||||
|
||||
#if defined(__linux__)
|
||||
# include <endian.h>
|
||||
# include <asm/byteorder.h>
|
||||
# if defined(__LITTLE_ENDIAN) && !defined(LITTLE_ENDIAN)
|
||||
# define LITTLE_ENDIAN __LITTLE_ENDIAN
|
||||
# endif
|
||||
# if defined(__BIG_ENDIAN) && !defined(BIG_ENDIAN)
|
||||
# define BIG_ENDIAN __BIG_ENDIAN
|
||||
# endif
|
||||
# if defined(__BYTE_ORDER) && !defined(BYTE_ORDER)
|
||||
# define BYTE_ORDER __BYTE_ORDER
|
||||
# endif
|
||||
# if !defined(__alpha__)
|
||||
# define WITH_NTOH 32 /* what about alpha? */
|
||||
# endif
|
||||
# if (WITH_HOST_BYTE_ORDER == 0)
|
||||
# undef WITH_HOST_BYTE_ORDER
|
||||
# define WITH_HOST_BYTE_ORDER BYTE_ORDER
|
||||
# endif
|
||||
# if (BYTE_ORDER != WITH_HOST_BYTE_ORDER)
|
||||
# error "host endian incorrectly configured, check config.h"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* INSERT HERE - hosts that have available LITTLE_ENDIAN and
|
||||
BIG_ENDIAN macro's */
|
||||
|
||||
|
||||
/* Some hosts don't define LITTLE_ENDIAN or BIG_ENDIAN, help them out */
|
||||
|
||||
#ifndef LITTLE_ENDIAN
|
||||
#define LITTLE_ENDIAN 1234
|
||||
#endif
|
||||
#ifndef BIG_ENDIAN
|
||||
#define BIG_ENDIAN 4321
|
||||
#endif
|
||||
|
||||
|
||||
/* SunOS on SPARC:
|
||||
|
||||
Big endian last time I looked */
|
||||
|
||||
#if defined(sparc) || defined(__sparc__)
|
||||
# if (WITH_HOST_BYTE_ORDER == 0)
|
||||
# undef WITH_HOST_BYTE_ORDER
|
||||
# define WITH_HOST_BYTE_ORDER BIG_ENDIAN
|
||||
# endif
|
||||
# if (WITH_HOST_BYTE_ORDER != BIG_ENDIAN)
|
||||
# error "sun was big endian last time I looked ..."
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/* Random x86
|
||||
|
||||
Little endian last time I looked */
|
||||
|
||||
#if defined(i386) || defined(i486) || defined(i586) || defined(__i386__) || defined(__i486__) || defined(__i586__)
|
||||
# if (WITH_HOST_BYTE_ORDER == 0)
|
||||
# undef WITH_HOST_BYTE_ORDER
|
||||
# define WITH_HOST_BYTE_ORDER LITTLE_ENDIAN
|
||||
# endif
|
||||
# if (WITH_HOST_BYTE_ORDER != LITTLE_ENDIAN)
|
||||
# error "x86 was little endian last time I looked ..."
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/* INSERT HERE - additional hosts that do not have LITTLE_ENDIAN and
|
||||
BIG_ENDIAN definitions available. */
|
||||
|
||||
|
||||
/* SWAPPING:
|
||||
|
||||
According to the following table:
|
||||
|
||||
TARG BE TARG LE TARG ??
|
||||
HOST BE ok s/w s/w
|
||||
HOST LE htohl ok ok|ntohl
|
||||
HOST ?? ntohl s/w s/w
|
||||
|
||||
define host <-> target byte order conversion macro's */
|
||||
|
||||
|
||||
/* IN PLACE:
|
||||
|
||||
These macro's given a variable argument swap its value in place if
|
||||
so required */
|
||||
|
||||
#define H2T(VARIABLE) \
|
||||
do { \
|
||||
switch (sizeof(VARIABLE)) { \
|
||||
case 1: VARIABLE = H2T_1(VARIABLE); break; \
|
||||
case 2: VARIABLE = H2T_2(VARIABLE); break; \
|
||||
case 4: VARIABLE = H2T_4(VARIABLE); break; \
|
||||
case 8: VARIABLE = H2T_8(VARIABLE); break; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define T2H(VARIABLE) \
|
||||
do { \
|
||||
switch (sizeof(VARIABLE)) { \
|
||||
case 1: VARIABLE = T2H_1(VARIABLE); break; \
|
||||
case 2: VARIABLE = T2H_2(VARIABLE); break; \
|
||||
case 4: VARIABLE = T2H_4(VARIABLE); break; \
|
||||
case 8: VARIABLE = T2H_8(VARIABLE); break; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* TARGET WORD:
|
||||
|
||||
Byte swap a quantity the size of the targets word */
|
||||
|
||||
#if WITH_64BIT_TARGET
|
||||
#define H2T_word(X) H2T_8(X)
|
||||
#define T2H_word(X) T2H_8(X)
|
||||
#else
|
||||
#define H2T_word(X) H2T_4(X)
|
||||
#define T2H_word(X) T2H_4(X)
|
||||
#endif
|
||||
|
||||
|
||||
/* FUNCTIONS:
|
||||
|
||||
Returns the value swapped according to the host/target byte order */
|
||||
|
||||
/* no need to swap */
|
||||
#if 0
|
||||
#if (WITH_HOST_BYTE_ORDER \
|
||||
&& WITH_TARGET_BYTE_ORDER \
|
||||
&& WITH_HOST_BYTE_ORDER == WITH_TARGET_BYTE_ORDER )
|
||||
#define H2T_1(X) (X)
|
||||
#define H2T_2(X) (X)
|
||||
#define H2T_4(X) (X)
|
||||
#define H2T_8(X) (X)
|
||||
#define T2H_1(X) (X)
|
||||
#define T2H_2(X) (X)
|
||||
#define T2H_4(X) (X)
|
||||
#define T2H_8(X) (X)
|
||||
#endif
|
||||
|
||||
/* have ntoh and big endian target */
|
||||
#if (WITH_TARGET_BYTE_ORDER == BIG_ENDIAN \
|
||||
&& WITH_HOST_BYTE_ORDER != BIG_ENDIAN \
|
||||
&& WITH_NTOH)
|
||||
#define H2T_8(X) endian_h2t_8(X)
|
||||
#define H2T_4(X) htonl(X)
|
||||
#define H2T_2(X) htons(X)
|
||||
#define H2T_1(X) (X)
|
||||
#define T2H_8(X) endian_t2h_8(X)
|
||||
#define T2H_4(X) htonl(X)
|
||||
#define T2H_2(X) htons(X)
|
||||
#define T2H_1(X) (X)
|
||||
#endif
|
||||
|
||||
/* have ntoh, little host and unknown target */
|
||||
#if (WITH_HOST_BYTE_ORDER == LITTLE_ENDIAN \
|
||||
&& WITH_TARGET_BYTE_ORDER == 0 \
|
||||
&& WITH_NTOH)
|
||||
#define H2T_8(X) (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER ? (X) : endian_h2t_8(X))
|
||||
#define H2T_4(X) (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER ? (X) : htonl(X))
|
||||
#define H2T_2(X) (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER ? (X) : htons(X))
|
||||
#define H2T_1(X) (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER ? (X) : (X))
|
||||
#define T2H_8(X) (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER ? (X) : endian_t2h_8(X))
|
||||
#define T2H_4(X) (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER ? (X) : htonl(X))
|
||||
#define T2H_2(X) (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER ? (X) : htons(X))
|
||||
#define T2H_1(X) (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER ? (X) : (X))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* if all else fails use software */
|
||||
#ifndef H2T_1
|
||||
#define H2T_1(X) (X)
|
||||
#define H2T_2(X) endian_h2t_2(X)
|
||||
#define H2T_4(X) endian_h2t_4(X)
|
||||
#define H2T_8(X) endian_h2t_8(X)
|
||||
#define T2H_1(X) (X)
|
||||
#define T2H_2(X) endian_t2h_2(X)
|
||||
#define T2H_4(X) endian_t2h_4(X)
|
||||
#define T2H_8(X) endian_t2h_8(X)
|
||||
#endif
|
||||
|
||||
#endif
|
3
sim/ppc/ppc.mt
Normal file
3
sim/ppc/ppc.mt
Normal file
@ -0,0 +1,3 @@
|
||||
ALL=all-ppc
|
||||
CLEAN=clean-ppc
|
||||
DO_INSTALL=install-ppc
|
36
sim/ppc/sim_callbacks.h
Normal file
36
sim/ppc/sim_callbacks.h
Normal file
@ -0,0 +1,36 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _SIM_CALLBACKS_H_
|
||||
#define _SIM_CALLBACKS_H_
|
||||
|
||||
#ifndef NORETURN
|
||||
#define NORETURN
|
||||
#endif
|
||||
|
||||
|
||||
void printf_filtered (char *msg, ...);
|
||||
void NORETURN error (char *msg, ...);
|
||||
void *zalloc (long size);
|
||||
#define ZALLOC(TYPE) (TYPE*)zalloc(sizeof (TYPE))
|
||||
void zfree(void*);
|
||||
|
||||
#endif
|
387
sim/ppc/system.c
Normal file
387
sim/ppc/system.c
Normal file
@ -0,0 +1,387 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _SYSTEM_C_
|
||||
#define _SYSTEM_C_
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#if (NetBSD >= 199306) /* here NetBSD as that is what we're emulating */
|
||||
#include <sys/syscall.h> /* FIXME - should not be including this one */
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
#if (BSD < 199306) /* here BSD as just a bug */
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#include "cpu.h"
|
||||
#include "idecode.h"
|
||||
#include "system.h"
|
||||
|
||||
|
||||
void
|
||||
system_call(cpu *processor,
|
||||
unsigned_word cia)
|
||||
{
|
||||
switch (cpu_registers(processor)->gpr[0]) {
|
||||
|
||||
|
||||
case 1/*SYS_exit*/:
|
||||
#if (NetBSD >= 199306) && (SYS_exit != 1)
|
||||
# error "SYS_exit"
|
||||
#endif
|
||||
{
|
||||
int status = (int)cpu_registers(processor)->gpr[3];
|
||||
cpu_halt(processor, cia, was_exited, status);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 3/*SYS_read*/:
|
||||
#if (NetBSD >= 199306) && (SYS_read != 3)
|
||||
# error "SYS_read"
|
||||
#endif
|
||||
{
|
||||
void *scratch_buffer;
|
||||
int d = (int)cpu_registers(processor)->gpr[3];
|
||||
unsigned_word buf = cpu_registers(processor)->gpr[4];
|
||||
int nbytes = cpu_registers(processor)->gpr[5];
|
||||
int status;
|
||||
int nr_moved;
|
||||
|
||||
/* get a tempoary bufer */
|
||||
scratch_buffer = zalloc(cpu_registers(processor)->gpr[5]);
|
||||
|
||||
/* check if buffer exists by reading it */
|
||||
nr_moved = vm_data_map_read_buffer(cpu_data_map(processor),
|
||||
scratch_buffer,
|
||||
buf,
|
||||
nbytes,
|
||||
raw_transfer);
|
||||
if (nr_moved != nbytes)
|
||||
error("system_call()read - check on buffer failed\n");
|
||||
|
||||
/* read */
|
||||
if (d == 0) {
|
||||
status = fread (scratch_buffer, 1, nbytes, stdin);
|
||||
if (status == 0 && ferror (stdin))
|
||||
status = -1;
|
||||
} else {
|
||||
status = read (d, scratch_buffer, nbytes);
|
||||
}
|
||||
|
||||
if (status == -1) {
|
||||
cpu_registers(processor)->gpr[0] = errno;
|
||||
break;
|
||||
} else {
|
||||
cpu_registers(processor)->gpr[0] = 0;
|
||||
cpu_registers(processor)->gpr[3] = status;
|
||||
|
||||
if (status > 0) {
|
||||
nr_moved = vm_data_map_write_buffer(cpu_data_map(processor),
|
||||
scratch_buffer,
|
||||
buf,
|
||||
status,
|
||||
raw_transfer,
|
||||
0/*violate_ro*/);
|
||||
|
||||
if (nr_moved != nbytes)
|
||||
error("system_call()read - write to buffer failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
zfree(scratch_buffer);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 4/*SYS_write*/:
|
||||
#if (NetBSD >= 199306) && (SYS_write != 4)
|
||||
# error "SYS_write"
|
||||
#endif
|
||||
{
|
||||
void *scratch_buffer;
|
||||
int nr_moved;
|
||||
int d = (int)cpu_registers(processor)->gpr[3];
|
||||
unsigned_word buf = cpu_registers(processor)->gpr[4];
|
||||
int nbytes = cpu_registers(processor)->gpr[5];
|
||||
int status;
|
||||
|
||||
/* get a tempoary bufer */
|
||||
scratch_buffer = zalloc(cpu_registers(processor)->gpr[5]);
|
||||
|
||||
/* copy in */
|
||||
nr_moved = vm_data_map_read_buffer(cpu_data_map(processor),
|
||||
scratch_buffer,
|
||||
buf,
|
||||
nbytes,
|
||||
raw_transfer);
|
||||
if (nr_moved != nbytes) {
|
||||
/* FIXME - should handle better */
|
||||
error("system_call()write copy failed (nr_moved=%d != nbytes=%d)\n",
|
||||
nr_moved, nbytes);
|
||||
}
|
||||
|
||||
/* write */
|
||||
status = write(d, scratch_buffer, nbytes);
|
||||
if (status == -1) {
|
||||
cpu_registers(processor)->gpr[0] = errno;
|
||||
break;
|
||||
}
|
||||
cpu_registers(processor)->gpr[0] = 0;
|
||||
cpu_registers(processor)->gpr[3] = status;
|
||||
|
||||
zfree(scratch_buffer);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 17/*SYS_break*/:
|
||||
#if (NetBSD >= 199306) && (SYS_break != 17)
|
||||
# error "SYS_break"
|
||||
#endif
|
||||
{
|
||||
unsigned_word new_sbrk = ALIGN_PAGE(cpu_registers(processor)->gpr[3]);
|
||||
unsigned_word old_sbrk = core_data_upper_bound(cpu_core(processor));
|
||||
signed_word delta = new_sbrk - old_sbrk;
|
||||
if (delta > 0)
|
||||
core_add_data(cpu_core(processor), delta);
|
||||
cpu_registers(processor)->gpr[0] = 0;
|
||||
cpu_registers(processor)->gpr[3] = new_sbrk;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 20/*SYS_getpid*/:
|
||||
#if (NetBSD >= 199306) && (SYS_getpid != 20)
|
||||
# error "SYS_getpid"
|
||||
#endif
|
||||
{
|
||||
cpu_registers(processor)->gpr[3] = (int)getpid();
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 37/*SYS_kill*/:
|
||||
#if (NetBSD >= 199306) && (SYS_kill != 37)
|
||||
# error "SYS_kill"
|
||||
#endif
|
||||
{
|
||||
pid_t pid = cpu_registers(processor)->gpr[3];
|
||||
int sig = cpu_registers(processor)->gpr[4];
|
||||
TRACE(trace_tbd, ("SYS_kill - more to this than just a kill\n"));
|
||||
cpu_halt(processor, cia, was_signalled, sig);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 48/*SYS_sigprocmask*/:
|
||||
#if (NetBSD >= 199306) && (SYS_sigprocmask != 48)
|
||||
# error "SYS_sigprocmask"
|
||||
#endif
|
||||
{
|
||||
natural_word how = cpu_registers(processor)->gpr[3];
|
||||
unsigned_word set = cpu_registers(processor)->gpr[4];
|
||||
unsigned_word oset = cpu_registers(processor)->gpr[5];
|
||||
TRACE(trace_system, ("SYS_sigprocmask: how=%d, set=0x%x, oset=0x%x\n",
|
||||
how, set, oset));
|
||||
cpu_registers(processor)->gpr[0] = 0;
|
||||
cpu_registers(processor)->gpr[3] = 0;
|
||||
cpu_registers(processor)->gpr[4] = set;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 54/*SYS_ioctl*/:
|
||||
#if (NetBSD >= 199306) && (SYS_ioctl != 54)
|
||||
# error "SYS_ioctl"
|
||||
#endif
|
||||
{
|
||||
TRACE(trace_system, ("SYS_ioctl: d=%d, request=0x%x, argp=0x%x\n",
|
||||
cpu_registers(processor)->gpr[3], cpu_registers(processor)->gpr[4], cpu_registers(processor)->gpr[5]));
|
||||
cpu_registers(processor)->gpr[0] = 0;
|
||||
cpu_registers(processor)->gpr[3] = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 189/*SYS_fstat*/:
|
||||
#if (NetBSD >= 199306) && (SYS_fstat != 189)
|
||||
# error "SYS_fstat"
|
||||
#endif
|
||||
{
|
||||
int fd = cpu_registers(processor)->gpr[3];
|
||||
unsigned_word stat_buf_addr = cpu_registers(processor)->gpr[4];
|
||||
struct stat buf;
|
||||
int nr_moved;
|
||||
int status;
|
||||
|
||||
/* check buffer all there, by reading it */
|
||||
nr_moved = vm_data_map_read_buffer(cpu_data_map(processor),
|
||||
&buf,
|
||||
stat_buf_addr,
|
||||
sizeof(buf),
|
||||
raw_transfer);
|
||||
if (nr_moved != sizeof(buf))
|
||||
error("system_call()fstat - check on buffer failed\n");
|
||||
|
||||
/* do the fstat call */
|
||||
status = fstat(fd, &buf);
|
||||
if (status == -1) {
|
||||
cpu_registers(processor)->gpr[0] = errno;
|
||||
break;
|
||||
}
|
||||
cpu_registers(processor)->gpr[0] = 0;
|
||||
cpu_registers(processor)->gpr[3] = 0;
|
||||
|
||||
H2T(buf.st_dev);
|
||||
H2T(buf.st_ino);
|
||||
H2T(buf.st_mode);
|
||||
H2T(buf.st_nlink);
|
||||
H2T(buf.st_uid);
|
||||
H2T(buf.st_gid);
|
||||
H2T(buf.st_rdev);
|
||||
H2T(buf.st_size);
|
||||
H2T(buf.st_atime);
|
||||
/* H2T(buf.st_spare1); */
|
||||
H2T(buf.st_mtime);
|
||||
/* H2T(buf.st_spare2); */
|
||||
H2T(buf.st_ctime);
|
||||
/* H2T(buf.st_spare3); */
|
||||
H2T(buf.st_blksize);
|
||||
H2T(buf.st_blocks);
|
||||
#if (NetBSD >= 199306)
|
||||
H2T(buf.st_flags);
|
||||
H2T(buf.st_gen);
|
||||
#endif
|
||||
|
||||
nr_moved = vm_data_map_write_buffer(cpu_data_map(processor),
|
||||
&buf,
|
||||
stat_buf_addr,
|
||||
sizeof(buf),
|
||||
raw_transfer,
|
||||
0/*violate_ro*/);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 202/*SYS___sysctl*/:
|
||||
#if (NetBSD >= 199306) && (SYS___sysctl != 202)
|
||||
# error "SYS__sysctl"
|
||||
#endif
|
||||
{
|
||||
/* call the arguments by their real name */
|
||||
unsigned_word name = cpu_registers(processor)->gpr[3];
|
||||
natural_word namelen = cpu_registers(processor)->gpr[4];
|
||||
unsigned_word oldp = cpu_registers(processor)->gpr[5];
|
||||
unsigned_word oldlenp = cpu_registers(processor)->gpr[6];
|
||||
natural_word oldlen;
|
||||
natural_word mib;
|
||||
natural_word int_val;
|
||||
|
||||
/* pluck out the management information base id */
|
||||
if (namelen < 1
|
||||
|| sizeof(mib) != vm_data_map_read_buffer(cpu_data_map(processor),
|
||||
&mib,
|
||||
name,
|
||||
sizeof(mib),
|
||||
cooked_transfer))
|
||||
error("system_call()SYS___sysctl bad name[0]\n");
|
||||
name += sizeof(mib);
|
||||
|
||||
/* see what to do with it ... */
|
||||
switch (mib) {
|
||||
case 6/*CTL_HW*/:
|
||||
#if (NetBSD >= 199306) && (CTL_HW != 6)
|
||||
# error "CTL_HW"
|
||||
#endif
|
||||
if (namelen < 2
|
||||
|| sizeof(mib) != vm_data_map_read_buffer(cpu_data_map(processor),
|
||||
&mib,
|
||||
name,
|
||||
sizeof(mib),
|
||||
cooked_transfer))
|
||||
error("system_call()SYS___sysctl - CTL_HW - bad name[1]\n");
|
||||
name += sizeof(mib);
|
||||
switch (mib) {
|
||||
case 7/*HW_PAGESIZE*/:
|
||||
#if (NetBSD >= 199306) && (HW_PAGESIZE != 7)
|
||||
# error "HW_PAGESIZE"
|
||||
#endif
|
||||
if (sizeof(oldlen) != vm_data_map_read_buffer(cpu_data_map(processor),
|
||||
&oldlen,
|
||||
oldlenp,
|
||||
sizeof(oldlen),
|
||||
cooked_transfer))
|
||||
error("system_call()sysctl - CTL_HW.HW_PAGESIZE - oldlen read\n");
|
||||
if (sizeof(natural_word) > oldlen)
|
||||
error("system_call()sysctl - CTL_HW.HW_PAGESIZE - to small\n");
|
||||
int_val = 8192;
|
||||
oldlen = sizeof(int_val);
|
||||
if (sizeof(int_val) != vm_data_map_write_buffer(cpu_data_map(processor),
|
||||
&int_val,
|
||||
oldp,
|
||||
sizeof(int_val),
|
||||
cooked_transfer,
|
||||
0/*violate_ro*/))
|
||||
error("system_call()sysctl - CTL_HW.HW_PAGESIZE - int_val\n");
|
||||
if (sizeof(oldlen) != vm_data_map_write_buffer(cpu_data_map(processor),
|
||||
&oldlen,
|
||||
oldlenp,
|
||||
sizeof(oldlen),
|
||||
cooked_transfer,
|
||||
0/*violate_ro*/))
|
||||
error("system_call()sysctl - CTL_HW.HW_PAGESIZE - oldlen write\n");
|
||||
break;
|
||||
default:
|
||||
error("sysctl() CTL_HW.%d unknown\n", mib);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error("sysctl() name[0]=%s unknown\n", (int)mib);
|
||||
break;
|
||||
}
|
||||
cpu_registers(processor)->gpr[0] = 0;
|
||||
cpu_registers(processor)->gpr[3] = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
error("system_call() unimplemented system call %d, cia=0x%x, arg[0]=0x%x, lr=0x%x\n",
|
||||
cpu_registers(processor)->gpr[0], cia, cpu_registers(processor)->gpr[3], LR);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _SYSTEM_C_ */
|
29
sim/ppc/system.h
Normal file
29
sim/ppc/system.h
Normal file
@ -0,0 +1,29 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _SYSTEM_H_
|
||||
#define _SYSTEM_H_
|
||||
|
||||
void system_call
|
||||
(cpu *processor,
|
||||
unsigned_word cia);
|
||||
|
||||
#endif
|
127
sim/ppc/vm.h
Normal file
127
sim/ppc/vm.h
Normal file
@ -0,0 +1,127 @@
|
||||
/* This file is part of the program psim.
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _VM_H_
|
||||
#define _VM_H_
|
||||
|
||||
#ifndef INLINE_VM
|
||||
#define INLINE_VM
|
||||
#endif
|
||||
|
||||
typedef struct _vm vm;
|
||||
typedef struct _vm_data_map vm_data_map;
|
||||
typedef struct _vm_instruction_map vm_instruction_map;
|
||||
|
||||
|
||||
/* each PowerPC requires two virtual memory maps */
|
||||
|
||||
INLINE_VM vm *vm_create
|
||||
(core *memory);
|
||||
|
||||
INLINE_VM vm_data_map *vm_create_data_map
|
||||
(vm *memory);
|
||||
|
||||
INLINE_VM vm_instruction_map *vm_create_instruction_map
|
||||
(vm *memory);
|
||||
|
||||
|
||||
/* address translation, if the translation is invalid
|
||||
these will not return */
|
||||
|
||||
INLINE_VM unsigned_word vm_real_data_addr
|
||||
(vm_data_map *data_map,
|
||||
unsigned_word ea,
|
||||
int is_read,
|
||||
cpu *processor,
|
||||
unsigned_word cia);
|
||||
|
||||
INLINE_VM unsigned_word vm_real_instruction_addr
|
||||
(vm_instruction_map *instruction_map,
|
||||
cpu *processor,
|
||||
unsigned_word cia);
|
||||
|
||||
|
||||
/* block transfers */
|
||||
|
||||
INLINE_VM int vm_data_map_read_buffer
|
||||
(vm_data_map *data_map,
|
||||
void *target,
|
||||
unsigned_word addr,
|
||||
unsigned len,
|
||||
transfer_mode mode);
|
||||
|
||||
INLINE_VM int vm_data_map_write_buffer
|
||||
(vm_data_map *data_map,
|
||||
const void *source,
|
||||
unsigned_word addr,
|
||||
unsigned len,
|
||||
transfer_mode mode,
|
||||
int violate_read_only_section);
|
||||
|
||||
|
||||
/* fetch the next instruction from memory */
|
||||
|
||||
INLINE_VM instruction_word vm_instruction_map_read
|
||||
(vm_instruction_map *instruction_map,
|
||||
cpu *processor,
|
||||
unsigned_word cia);
|
||||
|
||||
|
||||
/* read data from memory */
|
||||
|
||||
#define DECLARE_VM_DATA_MAP_READ_N(N) \
|
||||
INLINE_VM unsigned_##N vm_data_map_read_##N \
|
||||
(vm_data_map *map, \
|
||||
unsigned_word ea, \
|
||||
cpu *processor, \
|
||||
unsigned_word cia);
|
||||
|
||||
DECLARE_VM_DATA_MAP_READ_N(1)
|
||||
DECLARE_VM_DATA_MAP_READ_N(2)
|
||||
DECLARE_VM_DATA_MAP_READ_N(4)
|
||||
DECLARE_VM_DATA_MAP_READ_N(8)
|
||||
|
||||
|
||||
/* write data to memory */
|
||||
|
||||
#define DECLARE_VM_DATA_MAP_WRITE_N(N) \
|
||||
INLINE_VM void vm_data_map_write_##N \
|
||||
(vm_data_map *map, \
|
||||
unsigned_word addr, \
|
||||
unsigned_##N val, \
|
||||
cpu *processor, \
|
||||
unsigned_word cia);
|
||||
|
||||
DECLARE_VM_DATA_MAP_WRITE_N(1)
|
||||
DECLARE_VM_DATA_MAP_WRITE_N(2)
|
||||
DECLARE_VM_DATA_MAP_WRITE_N(4)
|
||||
DECLARE_VM_DATA_MAP_WRITE_N(8)
|
||||
|
||||
|
||||
/* update vm data structures due to a synchronization point */
|
||||
|
||||
INLINE_VM void vm_synchronize_context
|
||||
(vm *memory,
|
||||
spreg *sprs,
|
||||
sreg *srs,
|
||||
msreg msr);
|
||||
|
||||
#endif
|
100
sim/ppc/words.h
Normal file
100
sim/ppc/words.h
Normal file
@ -0,0 +1,100 @@
|
||||
/* This file is part of psim (model of the PowerPC(tm) architecture)
|
||||
|
||||
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License
|
||||
as published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
--
|
||||
|
||||
PowerPC is a trademark of International Business Machines Corporation. */
|
||||
|
||||
|
||||
/* Basic type sizes for the PowerPC */
|
||||
|
||||
#ifndef _WORDS_H_
|
||||
#define _WORDS_H_
|
||||
|
||||
/* TYPES:
|
||||
|
||||
natural* sign determined by host
|
||||
signed* signed type of the given size
|
||||
unsigned* The corresponding insigned type
|
||||
|
||||
SIZES
|
||||
|
||||
*NN Size based on the number of bits
|
||||
*_NN Size according to the number of bytes
|
||||
*_word Size based on the target architecture's word
|
||||
word size (32/64 bits)
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* bit based */
|
||||
typedef char natural8;
|
||||
typedef short natural16;
|
||||
typedef long natural32;
|
||||
typedef long long natural64;
|
||||
|
||||
typedef signed char signed8;
|
||||
typedef signed short signed16;
|
||||
typedef signed long signed32;
|
||||
typedef signed long long signed64;
|
||||
|
||||
typedef unsigned char unsigned8;
|
||||
typedef unsigned short unsigned16;
|
||||
typedef unsigned long unsigned32;
|
||||
typedef unsigned long long unsigned64;
|
||||
|
||||
|
||||
/* byte based */
|
||||
typedef natural8 natural_1;
|
||||
typedef natural16 natural_2;
|
||||
typedef natural32 natural_4;
|
||||
typedef natural64 natural_8;
|
||||
|
||||
typedef signed8 signed_1;
|
||||
typedef signed16 signed_2;
|
||||
typedef signed32 signed_4;
|
||||
typedef signed64 signed_8;
|
||||
|
||||
typedef unsigned8 unsigned_1;
|
||||
typedef unsigned16 unsigned_2;
|
||||
typedef unsigned32 unsigned_4;
|
||||
typedef unsigned64 unsigned_8;
|
||||
|
||||
|
||||
/* for general work, the following are defined */
|
||||
/* unsigned: >= 32 bits */
|
||||
/* signed: >= 32 bits */
|
||||
/* long: >= 32 bits, sign undefined */
|
||||
/* int: small indicator */
|
||||
|
||||
/* target architecture based */
|
||||
#if (WITH_64BIT_TARGET)
|
||||
typedef natural64 natural_word;
|
||||
typedef unsigned64 unsigned_word;
|
||||
typedef signed64 signed_word;
|
||||
#else
|
||||
typedef natural32 natural_word;
|
||||
typedef unsigned32 unsigned_word;
|
||||
typedef signed32 signed_word;
|
||||
#endif
|
||||
|
||||
|
||||
/* Other instructions */
|
||||
typedef unsigned32 instruction_word;
|
||||
|
||||
#endif /* _WORDS_H_ */
|
Loading…
x
Reference in New Issue
Block a user