mirror of
https://github.com/DoctorWkt/unix-jun72.git
synced 2026-02-27 01:10:21 +00:00
Import of wkt's apout src tree into svn.
This commit is contained in:
173
tools/apout/CHANGES
Normal file
173
tools/apout/CHANGES
Normal file
@@ -0,0 +1,173 @@
|
||||
2.3 Beta1: to 10th June 2002
|
||||
----------------------------
|
||||
|
||||
Changed debug statements in cpu.c to be TrapDebug statements as I was
|
||||
seeing output from these in the output file of 2.11BSD /lib/cpp.
|
||||
|
||||
The problem with scripts has also been fixed, finally. I was passing
|
||||
the wrong path into the shell arguments.
|
||||
|
||||
On a 1.6GHz Pentium 4 running FreeBSD 4.5, a make depend; make of the
|
||||
2.11BSD GENERIC kernel takes 72 seconds.
|
||||
|
||||
2.3 Alpha3: to 1st June 2001
|
||||
----------------------------
|
||||
|
||||
Added patches from Wilhelm B. Kloke wb@vestein.arb-phys.uni-dortmund.de
|
||||
to get Apout to run the Algol 68 binaries found which were added into
|
||||
the Unix Archive.
|
||||
|
||||
A few changes for better Linux compilation. However, stream buffering
|
||||
doesn't seem to work on Linux, at least RedHat 6.2.
|
||||
|
||||
2.3 Alpha2: to 10th Jan 2000
|
||||
----------------------------
|
||||
|
||||
Added partial support for 0407-magic binaries from 2nd Edition. At
|
||||
present, this is enough for the C compiler on Dennis Ritchie's s2.tar
|
||||
archive to work. It's also good enough for the C compiler to recompile
|
||||
the last1120c compiler, and for the last1120c compiler to recompile itself.
|
||||
|
||||
Added code to support 512-byte block seeks on /dev files for 1st Edition
|
||||
binaries. This was required to get tap(1) to work. This should really
|
||||
only force 512-byte seeks on specific /dev/files, not all of them.
|
||||
|
||||
A significant rearrangement of the code in aout.c was done to make it
|
||||
more logical. I wouldn't say it was much tidier than before, though.
|
||||
|
||||
A redefinition of sigset_t in NetBSD stopped Apout from being compiled
|
||||
there. Thanks to Soren, bsdsignal.c was modified to fix this problem.
|
||||
|
||||
Some small changes to the output from -inst to make it look better.
|
||||
Added a WRITEBASE #define to help improve performance just a bit more.
|
||||
|
||||
2.3 Alpha1: to 2nd Jan 2000
|
||||
---------------------------
|
||||
|
||||
Added nearly complete support for 0405-magic binaries from 1st Edition,
|
||||
including emulating the KE11A extended arithmetic element. Still some
|
||||
work needed here on both the trap handling and KE11A support. Thanks to
|
||||
Tim Shoppa (shoppa@trailing-edge.com) for his eae code. The 0407-magic
|
||||
binaries from Dennis Ritchie's s2.tar archive are not yet supported. I
|
||||
need the V2/V3 manuals from Norman Wilson for this.
|
||||
|
||||
Some tidying up of the code has been done, using LCLINT and by hand.
|
||||
I've made a Debug() macro which make the code look a bit cleaner.
|
||||
|
||||
Some memory leaks removed. Natives exec()s now inherit the original
|
||||
environment, not the emulated one. Some mov() functions split into
|
||||
separate functions to help improve performance. Added a workaround
|
||||
for date handling in V5/V6 ctime(): see tail of v7trap.c.
|
||||
|
||||
Stream buffering variables consolidated into main.c and some bugs
|
||||
removed (e.g "rw" -> "w+"). 2.11BSD emulation now has stream buffering,
|
||||
but it is turned off by default as it doesn't seem to provide any
|
||||
improvement in performance.
|
||||
|
||||
2.2 Alpha9: to 2nd Mar 1999
|
||||
---------------------------
|
||||
|
||||
I've added magic numbers for some 2.9BSD binaries: all 2.9 binaries
|
||||
run in the V7 environment, which seems to work but I'm sure that
|
||||
2.9 != V7.
|
||||
|
||||
With help from Jonathan Naylor (g4klx@g4klx.demon.co.uk), and some work
|
||||
myself, I've managed to compile Apout under RedHat Linux 2.2. There are
|
||||
some 2.11BSD syscalls not implemented as a result, but I can recompile
|
||||
the V7 and the 2.11BSD kernels, which is a good indicator.
|
||||
|
||||
|
||||
2.2 Alpha8: to 15th Jan 1999
|
||||
----------------------------
|
||||
|
||||
These changes came about due to my attempt to compile the UNIX `nsys'
|
||||
kernel source code, dated 1973, with the 5th Edition development tools.
|
||||
|
||||
Added better detection of some special UNIX a.out binaries: the
|
||||
environment for these binaries was being incorrectly set by aout.c.
|
||||
There is now a magic.c which fixes the problem. See also LIMITATIONS
|
||||
for a note of bugs in some a.out binaries.
|
||||
|
||||
Modified v7trap.c to be much cleaner, and to look a bit more like
|
||||
bsdtrap.c. Introduced several small bugs in V5/V6/V7 syscall emulation,
|
||||
notably pipe() and dup(), by the cleanup. These are fixed.
|
||||
|
||||
|
||||
2.2 Alpha7: to 11th Jan 1999
|
||||
----------------------------
|
||||
|
||||
Modified the code to handle the syscall differences between
|
||||
V6 and V7: note that V5 and V6 are syscall identical. V6 has
|
||||
a different seek() and stat() to V7.
|
||||
|
||||
Added a new file for 2.11BSD ioctls, did many of the terminal
|
||||
ioctls, and a few more syscalls. Now 2.11 vi runs. However,
|
||||
longjmp() doesn't work yet, because it requires working signals.
|
||||
|
||||
Changed some types and #ifdefs for NetBSD and OpenBSD: thanks Soren!
|
||||
|
||||
|
||||
2.2 Alpha6: to 6th Jan 1999
|
||||
---------------------------
|
||||
|
||||
Bugfixes: none that I can think of.
|
||||
|
||||
Enhancements: tidied the code up somewhat. Changed uint -> u_int
|
||||
throughout. Added support for execution of native binaries: now I can
|
||||
run vi from inside 2.11 bin/sh, yay! Finally wrote the long-overdue
|
||||
manual page. Added RCS tags to all sources. Ensured that it compiled on
|
||||
FreeBSD 3.x and 2.1.x: I need to take it home for FreeBSD 2.2.x.
|
||||
|
||||
|
||||
2.2 Alpha5: to 5th Jan 1999
|
||||
---------------------------
|
||||
|
||||
Bugfixes: fixed malloc bug, which was a too-large blksize from stat/fstat.
|
||||
Fixed the gtty/stty emulation, which was causing make to break.
|
||||
|
||||
Enhancements: Apout can now run shell scripts. 2.11BSD overlay binaries
|
||||
are now supported, which is good news. I can now compile the 2.11 GENERIC
|
||||
kernel with no manual intervention. On a Pentium II 350MHz, this takes
|
||||
4:16secs with an optimised Apout.
|
||||
|
||||
|
||||
2.2 Alpha4: to 2nd Jan 1999
|
||||
---------------------------
|
||||
|
||||
Fixed more deficiencies in the 2.11BSD emulation, in particular
|
||||
fork(), vfork() and sbrk(). The argv/envp environment is better
|
||||
but still not totally correct, I think. Finally got the correct
|
||||
code for 2.11 readdir().
|
||||
|
||||
We now have a semi-working FP emulation. It's enough to keep 2.11
|
||||
happy, but it isn't very good. It will do for now.
|
||||
|
||||
Many of the 2.11BSD syscalls are now implemented. Most are not
|
||||
verified, but a lot of 2.11BSD commands run, including sh, make,
|
||||
cc, date, cal. ls(1) goes into an infinite loop when doing ls -l,
|
||||
the inf. loop is in malloc(3). By substituting malloc(3) from
|
||||
Minix 1.3, this problem goes away. I don't know if it's a bug
|
||||
in the emulator, or in the 2.11 malloc() code.
|
||||
|
||||
|
||||
2.2 Alpha3 to 5th Dec 1998
|
||||
--------------------------
|
||||
|
||||
Reorganised bsdtrap.[ch], and started work on the
|
||||
2.11BSD emulated syscalls; this is surprisingly
|
||||
easy for many of them.
|
||||
|
||||
|
||||
Changes from 2.1 to 2.2
|
||||
-----------------------
|
||||
|
||||
+ General code tidying up and niggling bug removal.
|
||||
+ Code optimisation to speed things up, although
|
||||
I haven't quantified the improvement yet.
|
||||
+ Separation of the binary loader and trap handlers
|
||||
from the main program. This doesn't do anything now,
|
||||
but it will make the emulation of several PDP-11
|
||||
environments (e.g 2.11BSD, RT-11) much easier to do.
|
||||
+ Finished getting the stream buffering of I/O to work.
|
||||
I still don't know why fdopen doesn't work on "rw".
|
||||
+ Some extra trap functionality, e.g basic signal handling.
|
||||
46
tools/apout/COPYRIGHT
Normal file
46
tools/apout/COPYRIGHT
Normal file
@@ -0,0 +1,46 @@
|
||||
The Apout simulator is copyright Warren Toomey, and is protected by the
|
||||
following notice.
|
||||
|
||||
/* Apout is a PDP-11 a.out simulator.
|
||||
*
|
||||
* For information contact:
|
||||
*
|
||||
* Email: wkt@tuhs.org
|
||||
* FTP: ftp://minnie.tuhs.org/pup/PDP-11/Sims/Apout
|
||||
*
|
||||
* Copyright 1995-2002, Warren Toomey
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted, provided
|
||||
* that the above copyright notice appear in all copies. Warren Toomey
|
||||
* makes no representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without expressed or implied warranty.
|
||||
*/
|
||||
|
||||
------
|
||||
|
||||
The parts of Apout that deal with PDP-11 instruction emulation are derived
|
||||
from the PDP-11 simulator written by Eric A. Edwards, and are protected by
|
||||
the following notice.
|
||||
|
||||
/* Parts of Apout are derived from 'pdp', a PDP-11 simulator.
|
||||
*
|
||||
* For information contact:
|
||||
*
|
||||
* Computer Science House
|
||||
* Attn: Eric Edwards
|
||||
* Box 861
|
||||
* 25 Andrews Memorial Drive
|
||||
* Rochester, NY 14623
|
||||
*
|
||||
* Email: mag@potter.csh.rit.edu
|
||||
* FTP: ftp.csh.rit.edu:/pub/csh/mag/pdp.tar.Z
|
||||
*
|
||||
* Copyright 1994, Eric A. Edwards
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted, provided
|
||||
* that the above copyright notice appear in all copies. Eric A. Edwards
|
||||
* makes no representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without expressed or implied warranty.
|
||||
*/
|
||||
16
tools/apout/LCLINT
Normal file
16
tools/apout/LCLINT
Normal file
@@ -0,0 +1,16 @@
|
||||
aout.c Fri Sep 17 13:00:33 EST 1999
|
||||
branch.c Fri Sep 17 13:00:33 EST 1999
|
||||
bsd_ioctl.c Fri Sep 17 13:03:34 EST 1999
|
||||
bsd_signal.c
|
||||
bsdtrap.c
|
||||
cpu.c Fri Sep 17 15:04:05 EST 1999 bits to do
|
||||
debug.c Fri Sep 17 15:04:01 EST 1999
|
||||
double.c Fri Sep 17 15:08:46 EST 1999
|
||||
ea.c Fri Sep 17 15:10:51 EST 1999
|
||||
fp.c
|
||||
itab.c Fri Sep 17 13:00:33 EST 1999
|
||||
ke11a.c
|
||||
magic.c Fri Sep 17 13:00:33 EST 1999
|
||||
main.c
|
||||
single.c
|
||||
v7trap.c
|
||||
155
tools/apout/LIMITATIONS
Normal file
155
tools/apout/LIMITATIONS
Normal file
@@ -0,0 +1,155 @@
|
||||
Bugs in Binaries
|
||||
----------------
|
||||
|
||||
One of the V5 C compiler passes requires -DZERO_MEMORY: it must not
|
||||
initialise a variable properly. V5 and V6 ar(1) do not close a file
|
||||
descriptor after writing has finished. If Apout is compiled with
|
||||
stream buffering, when this file is copied it is truncated. Either
|
||||
turn off Apout stream buffering (a performance penalty), or patch
|
||||
ar.s to behave itself. The patch is:
|
||||
|
||||
*** ar.s.orig Thu Jan 14 09:40:46 1999
|
||||
--- ar.s Thu Jan 14 09:41:12 1999
|
||||
***************
|
||||
*** 444,449 ****
|
||||
--- 444,451 ----
|
||||
bes crterr
|
||||
mov r0,afo
|
||||
sys write; magic; 2
|
||||
+ mov tfo,r0 / need to close before reading
|
||||
+ sys close
|
||||
1:
|
||||
mov tfi,r0
|
||||
sys read; buf; 512.
|
||||
|
||||
|
||||
Floating-point Limitations
|
||||
--------------------------
|
||||
|
||||
PDP-11 doubles are treated as floats. FEA/FEC don't exist.
|
||||
FP errors are not dealt with. Mistrust FP results for now.
|
||||
|
||||
Limitations for 7th Edition Emulation in Apout 2.3
|
||||
--------------------------------------------------
|
||||
|
||||
Note that V5 and V6 binaries are considered V7 binaries. Overlay
|
||||
binaries (type 0405) are not recognised.
|
||||
|
||||
The errno values on the native system are not translated back to
|
||||
the V7 errno values. There is normally a 1-to-1 mapping, but V7
|
||||
only had 32 errno values; native errno values above this are going
|
||||
to confuse the emulated application.
|
||||
|
||||
The following system calls are not implemented, and return an
|
||||
EPERM error to the application: phys(2), prof(2), ptrace(2),
|
||||
acct(2), mount(2), umount(2), times(2). The following system
|
||||
calls are ignored: lock(2), stime(2).
|
||||
|
||||
The following systems calls are only partially implemented:
|
||||
|
||||
signal(2): Only SIG_DFL and SIG_IGN are implemented.
|
||||
stty(2), gtty(2): These should work, but V7 stty(1) doesn't work.
|
||||
ioctl(2): Only enough to emulate stty(2) amd gtty(2).
|
||||
|
||||
The emulated applications use the native filesystem. Native filenames bigger
|
||||
than 14 characters are truncated to 14 characters before being passed to
|
||||
the application. In a similar way, inode numbers bigger than 65,536 are
|
||||
truncated modulo 65,536 before being passed to the application.
|
||||
|
||||
Limitations for 5th & 6th Edition Emulation in Apout 2.3
|
||||
--------------------------------------------------------
|
||||
|
||||
There seems to be a bug in V5/V6 ctime() which stops dates after
|
||||
November 1999 being displayed correctly. Apout works around this
|
||||
problem by modifying dates returned from system calls to be in
|
||||
the year 1998 if they are 1999 or later.
|
||||
|
||||
Limitations for 2.9BSD Emulation in Apout 2.3
|
||||
---------------------------------------------
|
||||
|
||||
At present, 2.9BSD binaries are treated as V7 binaries, so the limitations
|
||||
above apply. This also means that overlays are not understood, and also the
|
||||
2.9-specific system calls have not yet been implemented.
|
||||
|
||||
Limitations for 2.11BSD Emulation in Apout 2.3
|
||||
----------------------------------------------
|
||||
|
||||
Flags passed as arguments to the 2.11 syscalls are promoted to 32-bit
|
||||
ints and passed to the native syscall. The errno values on the native
|
||||
system are not translated back to the 2.11 errno values. To find out
|
||||
what syscalls have been implemented, grep for the word DONE in bsdtrap.c.
|
||||
|
||||
The following 2.11 syscalls are not handled:
|
||||
|
||||
S_GETSOCKOPT, S_SETSOCKOPT, S_SELECT,
|
||||
S_RECVMSG, S_SENDMSG, S_SENDTO,
|
||||
S_SIGBLOCK, S_SIGPAUSE, S_SIGRETURN,
|
||||
S_SIGSETMASK, S_SIGSTACK, S_SIGVEC
|
||||
|
||||
Limitations for 1st Edition Emulation in Apout 2.3
|
||||
--------------------------------------------------
|
||||
|
||||
This is still in the experimental stages, with some problems with time
|
||||
values. The KE11A emulation is also incomplete. However, the following
|
||||
0405-magic binaries from Dennis Ritchie's s2.tar archive are known to work:
|
||||
|
||||
cat, cp, date, echo, ls, mkdir, sh, wc
|
||||
|
||||
Most of the others seem to work as well, but I haven't tested them completely.
|
||||
The list of 0405-magic files on the s2 archive is:
|
||||
|
||||
bin/: bin/mv
|
||||
bin/ar bin/od
|
||||
bin/bas bin/pr
|
||||
bin/cat bin/rew
|
||||
bin/chball bin/rmdir
|
||||
bin/check bin/roff
|
||||
bin/chown bin/sh
|
||||
bin/cmp bin/skip
|
||||
bin/cp bin/sort
|
||||
bin/date bin/stat
|
||||
bin/db bin/stty
|
||||
bin/dc bin/su
|
||||
bin/df bin/sum
|
||||
bin/du bin/tap
|
||||
bin/echo bin/tm
|
||||
bin/ed bin/tty
|
||||
bin/exit bin/wc
|
||||
bin/form bin/who
|
||||
bin/goto bin/write
|
||||
bin/if etc/getty
|
||||
bin/login etc/glob
|
||||
bin/ls etc/init
|
||||
bin/mail etc/msh
|
||||
bin/mesg /tc/suftab
|
||||
bin/mkdir
|
||||
|
||||
The following 1st Edition system calls are not yet emulated: GTTY, STTY, TELL.
|
||||
|
||||
Limitations for 2nd Edition Emulation in Apout 2.3
|
||||
--------------------------------------------------
|
||||
|
||||
The few 2nd Edition binaries with 0407-magic on the s2 archive can now
|
||||
be run with Apout. Essentially, they receive the same environment as
|
||||
the 1st Edition binaries, with a few small syscall differences. Note
|
||||
that, at present, I don't have a copy of the V2 manuals, so I can
|
||||
guarantee that 2nd Edition emulation still needs work.
|
||||
|
||||
However, the emulation is good enough to allow the C compiler on the s2
|
||||
archive to compile the last1120c C compiler on Dennis Ritchie's homepage.
|
||||
|
||||
The list of 0407-magic files in the s2 archive is below. I have starred
|
||||
those binaries that I know work with Apout.
|
||||
|
||||
* bin/as usr/fort/fc1
|
||||
* bin/cc usr/fort/fc2
|
||||
bin/ds usr/fort/fc3
|
||||
bin/fc usr/fort/fc4
|
||||
bin/find usr/jack/a.out
|
||||
* bin/ld usr/jack/x.o
|
||||
bin/maki * usr/lib/c0
|
||||
bin/nm * usr/lib/c1
|
||||
* bin/size usr/lib/crt0.o
|
||||
bin/strip usr/lib/fr0.o
|
||||
bin/un usr/sys/a.out
|
||||
* etc/as2
|
||||
78
tools/apout/Makefile
Normal file
78
tools/apout/Makefile
Normal file
@@ -0,0 +1,78 @@
|
||||
# Makefile for Apout PDP-11 application emulator
|
||||
#
|
||||
# $Revision: 1.29 $
|
||||
# $Date: 2002/06/10 11:49:48 $
|
||||
#
|
||||
# You will need gcc if you choose the optimised compile below
|
||||
CC=gcc
|
||||
|
||||
# Set the CFLAGS, LDFLAGS for speed or debugging. If you don't want 2.11BSD
|
||||
# emulation, then remove the -DEMU211 flag.
|
||||
# Set up the LIBS if required for your system
|
||||
#
|
||||
# These flags for doing debugging
|
||||
CFLAGS= -Wall -g -DEMU211 -DEMUV1 -DNATIVES -DDEBUG -DZERO_MEMORY -DWRITEBASE
|
||||
LDFLAGS= -static -g
|
||||
|
||||
# These flags for speed
|
||||
#CFLAGS= -DEMU211 -DNATIVES -DINLINE=inline -O2 -Winline -Wall \
|
||||
# -finline-functions -fomit-frame-pointer
|
||||
#LDFLAGS=
|
||||
|
||||
# Any extra libraries required
|
||||
LIBS= -lm
|
||||
|
||||
# Install destinations
|
||||
MANDIR=/usr/local/man/man1
|
||||
BINDIR=/usr/local/bin
|
||||
|
||||
VERSION= apout2.3beta1
|
||||
SRCS= cpu.c aout.c aout.h branch.c double.c ea.c itab.c main.c ke11a.c \
|
||||
single.c fp.c v7trap.c bsdtrap.c defines.h v7trap.h debug.c \
|
||||
bsdtrap.h bsd_ioctl.c bsd_signal.c magic.c v1trap.c v1trap.h \
|
||||
apout.1 apout.0 README COPYRIGHT CHANGES LIMITATIONS TODO Makefile
|
||||
OBJS= aout.o branch.o bsd_ioctl.o bsd_signal.o bsdtrap.o cpu.o debug.o \
|
||||
double.o ea.o fp.o itab.o ke11a.o magic.o main.o single.o v1trap.o \
|
||||
v7trap.o
|
||||
|
||||
apout: $(OBJS)
|
||||
cc $(LDFLAGS) $(OBJS) -o apout $(LIBS)
|
||||
|
||||
install: apout
|
||||
cp apout $(BINDIR)
|
||||
chmod 755 $(BINDIR)/apout
|
||||
cp apout.1 $(MANDIR)
|
||||
chmod 644 $(MANDIR)/apout.1
|
||||
|
||||
clean:
|
||||
rm -rf apout *core $(OBJS) *.dbg $(VERSION) $(VERSION).tar.gz apout.0
|
||||
|
||||
apout.0: apout.1
|
||||
nroff -man apout.1 > apout.0
|
||||
|
||||
disttar: clean apout.0
|
||||
- mkdir $(VERSION)
|
||||
cp $(SRCS) $(VERSION)
|
||||
chmod -R go+rX $(VERSION)
|
||||
chmod -R u+w $(VERSION)
|
||||
chown -R wkt $(VERSION)
|
||||
tar vzcf $(VERSION).tar.gz $(VERSION)
|
||||
|
||||
# Dependencies for object files
|
||||
aout.o: aout.c defines.h aout.h Makefile
|
||||
branch.o: branch.c defines.h Makefile
|
||||
bsd_ioctl.o: bsd_ioctl.c defines.h Makefile
|
||||
bsd_signal.o: bsd_signal.c defines.h bsdtrap.h Makefile
|
||||
bsdtrap.o: bsdtrap.c bsdtrap.h defines.h Makefile
|
||||
cpu.o: cpu.c defines.h Makefile
|
||||
debug.o: debug.c defines.h Makefile
|
||||
double.o: double.c defines.h Makefile
|
||||
ea.o: ea.c defines.h Makefile
|
||||
fp.o: fp.c defines.h Makefile
|
||||
itab.o: itab.c defines.h Makefile
|
||||
ke11a.o: ke11a.c defines.h Makefile
|
||||
magic.o: magic.c defines.h Makefile
|
||||
main.o: main.c defines.h Makefile
|
||||
single.o: single.c defines.h Makefile
|
||||
v1trap.o: v1trap.c v1trap.h defines.h Makefile
|
||||
v7trap.o: v7trap.c v7trap.h defines.h Makefile
|
||||
140
tools/apout/README
Normal file
140
tools/apout/README
Normal file
@@ -0,0 +1,140 @@
|
||||
Apout -- Simulate PDP-11 Unix a.out binaries
|
||||
Version 2.3 Beta 1
|
||||
|
||||
Warren Toomey wkt@tuhs.org
|
||||
June 2002
|
||||
|
||||
Introduction
|
||||
------------
|
||||
This program is a user-level simulator for UNIX a.out binaries. Binaries
|
||||
for V1, V2, V5, V6, V7, 2.9BSD and 2.11BSD can be run with this simulator.
|
||||
The user-mode PDP-11 instructions are simulated, and TRAP instructions
|
||||
are emulated by calling equivalent native-mode system calls.
|
||||
|
||||
The advantages of an a.out simulator over a full-blown PDP-11 simulator are:
|
||||
|
||||
+ system calls can be done natively, thus speeding up execution
|
||||
+ the simulator is less of a CPU-hog than a full-blown PDP-11 simulator
|
||||
+ you don't need a simulated operating system or a simulated file system
|
||||
|
||||
Apout can be obtained via anonymous ftp at minnie.tuhs.org in the
|
||||
directory pub/PDP-11/Sims/Apout. The directory pub/PDP-11/Sims/Apout/UnixBins
|
||||
contains tar archives of a.out binaries from several versions of UNIX.
|
||||
|
||||
Status
|
||||
------
|
||||
The program is now at release 2.3 Alpha2. Most of the binaries from V5, V6
|
||||
and V7 run fine. All of the V5/V6/V7 system calls are caught, but some are
|
||||
ignored and some generate EPERM errors. The V1, V2, 2.9BSD and 2.11BSD
|
||||
environments are still under construction: see the file LIMITATIONS for
|
||||
details. Finally, the simulator won't run on a big-endian machine.
|
||||
|
||||
INSTALLATION
|
||||
------------
|
||||
I have only tested this program on FreeBSD 2.x and 3.x, and on RedHat
|
||||
Linux 2.2. It should compile on a 32-bit little-endian machine with
|
||||
some form of Unix; you may need to change some header file includes etc.
|
||||
See `defines.h' for the details. In particular, if your system doesn't have
|
||||
types for:
|
||||
|
||||
int8_t, int16_t, int32_t, u_int8_t, u_int16_t, u_int32_t
|
||||
|
||||
or if your compiler doesn't have char=1 byte, short= 2 bytes, int=4 bytes,
|
||||
then alter the relevant typedefs in `defines.h'.
|
||||
|
||||
The Makefile has two sets of CFLAGS/LDFLAGS: one set is for debugging, and
|
||||
the other set is for speed. If you define the C pre-processor macro `DEBUG',
|
||||
then this includes debugging code into the program. I use it quite heavily
|
||||
when trying to fix niggling problems.
|
||||
|
||||
If you remove the -DEMU211 macro definition from the Makefile, the emulation
|
||||
of 2.11BSD will not be compiled in to the simulator. Similarly, if you remove
|
||||
the -DEMUV1 macro definition from the Makefile, the emulation of 1st and 2nd
|
||||
Edition UNIX will not be compiled in to the simulator. By default, EMUV1
|
||||
is disabled.
|
||||
|
||||
|
||||
Once you have configured apout, now type `make'. Hopefully, things will
|
||||
compile ok. You will eventually get the `apout' program.
|
||||
|
||||
Now go find an old PDP-11 UNIX binary, e.g 7th Edition cal, and say:
|
||||
|
||||
% setenv APOUT_ROOT / # for now
|
||||
% apout cal 1970
|
||||
|
||||
If the simulator is working, the calendar for 1970 will be printed out.
|
||||
The V7 shell works, and from there, you can run other programs.
|
||||
|
||||
% apout sh
|
||||
# ls -l
|
||||
output of ls
|
||||
#
|
||||
|
||||
Finally, install apout in /usr/local/bin, and the manual page apout.1 in
|
||||
the appropriate place. If you can't use the man page because of incompatible
|
||||
macros, then apout.0 is a text file which has the pre-formatted man page.
|
||||
|
||||
DEBUG OPTIONS
|
||||
-------------
|
||||
When debugging is compiled in, the program has several options:
|
||||
|
||||
-inst turns on instruction tracing, which is _very_ verbose
|
||||
-trap turns on TRAP tracing; not all syscalls have debugging code
|
||||
-jsr prints out the details of each jsr and rts
|
||||
-fp prints out some details of floating-point instructions
|
||||
|
||||
All debugging output goes out to the file `apout.dbg'. These debugging options
|
||||
are mainly used for testing apout, and so the output in apout.dbg may not be
|
||||
very useful to you.
|
||||
|
||||
ENVIRONMENT VARIABLES
|
||||
---------------------
|
||||
Apout has the concept of a simulated root filesystem for the simulated PDP-11
|
||||
binaries. When working with filenames, if the filenames are relative, they
|
||||
stay relative. If the filenames are absolute (i.e /usr/...), then apout
|
||||
prepends the value of the environment variable APOUT_ROOT to the filename.
|
||||
This allows you to say:
|
||||
|
||||
# setenv APOUT_ROOT /usr/misc/v7root
|
||||
|
||||
before running apout to set the `root' of the filesystem wherever you want.
|
||||
You MUST set APOUT_ROOT before running apout.
|
||||
|
||||
TODO
|
||||
----
|
||||
There's lots to do. Here's what I'd like to do, in a somewhat ordered list.
|
||||
|
||||
+ Verify that the instruction simulation and high priority
|
||||
the syscalls all work correctly
|
||||
+ Complete some of the syscalls that are med priority
|
||||
not fully simulated
|
||||
+ Speed the simulator up med priority
|
||||
|
||||
SOURCE ORGANISATION
|
||||
-------------------
|
||||
|
||||
main.c parses any arguments, loads the binary and calls run()
|
||||
cpu.c holds the main instruction decode/execute loop
|
||||
itab.c holds function lookup tables for all instructions
|
||||
ea.c holds functions to decode the PDP-11 addressing modes
|
||||
debug.c holds strings for all emulated opcodes
|
||||
|
||||
single.c single.c, double.c and branch.c hold most of the functions
|
||||
double.c which perform the PDP-11 user-mode instructions. The code
|
||||
branch.c in these files comes from a PDP-11 simulator by Eric Edwards
|
||||
fp.c partially emulates FP instructions
|
||||
|
||||
aout.c determines what type of a.out the binary is, and what UNIX
|
||||
magic.c environment to set up. If V5/V6/V7, trap instructions fall
|
||||
v7trap.c into v7trap.c which runs them using native system calls
|
||||
v7trap.h
|
||||
|
||||
v1trap.c if the binary is a 1st or 2nd Edition binary, traps fall
|
||||
v1trap.h into v1trap.c, which likewise does the syscalls natively
|
||||
ke11a.c emulates the KE11A extended arithmetic unit, used by V1/V2
|
||||
|
||||
bsdtrap.c if the binary is a 2.11BSD binary, trap instructions fall
|
||||
bsdtrap.h into bsdtrap.c, which likewise does the syscalls natively
|
||||
bsd_ioctl.c 2.11BSD ioctl calls are handled with this file
|
||||
|
||||
defines.h holds function & typedef prototypes and useful cpp macros
|
||||
72
tools/apout/TODO
Normal file
72
tools/apout/TODO
Normal file
@@ -0,0 +1,72 @@
|
||||
Things to do in the Apout Emulator
|
||||
----------------------------------
|
||||
|
||||
Ensure stream buffering works!
|
||||
|
||||
Do some decent testing and code reading to make me happier.
|
||||
|
||||
Speed Apout up
|
||||
|
||||
The biggest bottlenecks are the effective address calculations
|
||||
in ea.c. After compiling 2.11BSD /sys/GENERIC kernel with a
|
||||
gprof'd apout, we get:
|
||||
|
||||
% cumulative self self total
|
||||
time seconds seconds calls ms/call ms/call name
|
||||
64.9 3.64 3.64 .mcount (123)
|
||||
6.1 3.99 0.34 1609635 0.00 0.00 load_src [5]
|
||||
5.6 4.30 0.31 1665976 0.00 0.00 mov [4]
|
||||
5.3 4.60 0.30 2 148.44 959.47 run <cycle 1> [3]
|
||||
3.4 4.79 0.19 1238127 0.00 0.00 load_dst [7]
|
||||
2.2 4.91 0.12 602275 0.00 0.00 store_dst [10]
|
||||
1.3 4.98 0.08 374121 0.00 0.00 loadb_src [12]
|
||||
1.3 5.05 0.07 672481 0.00 0.00 store_dst_2 [13]
|
||||
1.2 5.12 0.07 365911 0.00 0.00 cmp [6]
|
||||
1.1 5.18 0.06 323386 0.00 0.00 movb [8]
|
||||
1.1 5.24 0.06 515335 0.00 0.00 bne [15]
|
||||
|
||||
Everything else is below 1%. It doesn't look like there is
|
||||
much room for improvement, maybe 10% worth?
|
||||
|
||||
We could go to having 65,536 separate functions, one for
|
||||
each possible instruction. That would mean a large reorganisation
|
||||
of the source, and would result in a significantly larger
|
||||
binary for apout.
|
||||
|
||||
I've broken open some of the mov() functions which has improved
|
||||
things a few percent. I did expand itab[] to 64K entries, but
|
||||
the improvement was negligible. However, I should come back &
|
||||
revisit this sometime.
|
||||
|
||||
Would it be worth adding STREAM_BUFFERING into bsdtrap.c? Possibly.
|
||||
After a GENERIC kernel compile, I found that reads averaged 580
|
||||
chars/read, writes averaged 115 chars/write. However, after getting
|
||||
buffering to work in bsdtrap.c, I found that it actually slowed down
|
||||
the GENERIC kernel compile, so I've left the code in but disabled it.
|
||||
|
||||
Finish off 2.11BSD emulation
|
||||
|
||||
Finish off all the missing syscalls. This means I will have to
|
||||
learn how the new signal stuff actually works. Emulating signals
|
||||
is going to be really interesting, I can see!
|
||||
|
||||
Enumerate and write all of the ioctls: yucko. That means all of
|
||||
the terminal stuff, blah!
|
||||
|
||||
Fix up the floating-point
|
||||
|
||||
If the UNIX binaries never use the FP error handling, then don't
|
||||
bother to implement it. We should, however, implement doubles.
|
||||
We should spend some time to ensure that the FP operations are
|
||||
accurate, both in terms of FP accuracy, and in giving results
|
||||
as if they were on a real PDP-11.
|
||||
|
||||
Make it work on big-endian machines
|
||||
|
||||
This would cause a lot of heartache in the code. It's not that
|
||||
pretty now, but can you imagine the #ifdefs once big-endian
|
||||
support is added? I guess some well-written macros could help.
|
||||
|
||||
Tidy up the code
|
||||
|
||||
In particular, aout.c is a mess. Should be more modular.
|
||||
609
tools/apout/aout.c
Normal file
609
tools/apout/aout.c
Normal file
@@ -0,0 +1,609 @@
|
||||
/* aout.c - parse and load the contents of a UNIX a.out file, for
|
||||
* several flavours of PDP-11 UNIX
|
||||
*
|
||||
* $Revision: 1.50 $
|
||||
* $Date: 2002/06/10 11:43:24 $
|
||||
*/
|
||||
#include "defines.h"
|
||||
#include "aout.h"
|
||||
|
||||
/* Array of 64K for data and instruction space */
|
||||
static u_int8_t darray[PDP_MEM_SIZE], iarray[PDP_MEM_SIZE];
|
||||
|
||||
#ifdef EMU211
|
||||
/* 2.11BSD allows up to 16 8K overlays in the 0430 and 0431 a.out types.
|
||||
* Each overlay is loaded at the first 8K `click' above the end of the
|
||||
* main text. The following structures hold the overlays from the current
|
||||
* a.out, if there are any. Missing overlays have size 0 and pointer NULL.
|
||||
*/
|
||||
static struct {
|
||||
u_int16_t size;
|
||||
u_int8_t *ovlay;
|
||||
} ovlist[NOVL] = {
|
||||
{0, NULL}, {0, NULL}, {0, NULL}, {0, NULL}, {0, NULL}, {0, NULL},
|
||||
{0, NULL}, {0, NULL}, {0, NULL}, {0, NULL}, {0, NULL}, {0, NULL},
|
||||
{0, NULL}, {0, NULL}, {0, NULL}
|
||||
};
|
||||
|
||||
static u_int8_t *ovbase; /* Base address of 2.11BSD overlays */
|
||||
u_int32_t ov_changes = 0; /* Number of overlay changes */
|
||||
u_int8_t current_ov = 0; /* Current overlay number */
|
||||
#endif
|
||||
|
||||
/* Global array of pointers to arguments and environment. This
|
||||
* allows load_a_out() to modify it when dealing with shell
|
||||
* scripts, before calling set_arg_env()
|
||||
*/
|
||||
char *Argv[MAX_ARGS], *Envp[MAX_ARGS];
|
||||
int Argc, Envc;
|
||||
int Binary; /* Type of binary this a.out is */
|
||||
|
||||
/* For programs without an environment, we set the environment statically.
|
||||
* Eventually there will be code to get some environment variables
|
||||
*/
|
||||
static char *default_envp[4] = {
|
||||
"PATH=/bin:/usr/bin:/usr/sbin:/usr/ucb:/usr/games:/usr/local/bin:.",
|
||||
"HOME=/",
|
||||
"TERM=vt100",
|
||||
"USER=root"
|
||||
};
|
||||
static int default_envc = 4;
|
||||
|
||||
/* Prototypes */
|
||||
static void set_arg_env(int want_env);
|
||||
|
||||
|
||||
/* Load the a.out header from the given file pointer, and return it.
|
||||
* Also return an integer describing which version of UNIX the a.out
|
||||
* belongs to. If errors on reading, return -1.
|
||||
*/
|
||||
int load_aout_header(FILE * zin, struct exec * E)
|
||||
{
|
||||
char *cptr;
|
||||
|
||||
/* Read the a_magic value first */
|
||||
/* This makes it easier to deal with */
|
||||
/* parsing any script interpreter below */
|
||||
if (fread(E, sizeof(u_int16_t), 1, zin) != 1) return (-1);
|
||||
|
||||
switch (E->a_magic) {
|
||||
case ANY_SCRIPT: /* Shell script, return now */
|
||||
return (IS_UNKNOWN);
|
||||
case V1_NORMAL:
|
||||
case ANY_NORMAL: /* These are recognised below */
|
||||
case ANY_ROTEXT:
|
||||
case ANY_SPLITID:
|
||||
case BSD_OVERLAY:
|
||||
case BSD_ROVERLAY:
|
||||
case A68_MAGIC:
|
||||
break;
|
||||
|
||||
default: /* Unrecognised binary, mark as such */
|
||||
E->a_magic = UNKNOWN_AOUT; return (IS_UNKNOWN);
|
||||
}
|
||||
|
||||
/* We can deal with this a.out, so */
|
||||
/* read in the rest of the header */
|
||||
cptr = (char *) &(E->a_text);
|
||||
if (fread(cptr, sizeof(struct exec) - sizeof(u_int16_t), 1, zin) != 1)
|
||||
return (-1);
|
||||
|
||||
switch (E->a_magic) {
|
||||
case A68_MAGIC: if (E->a_data==A68_DATA) return(IS_A68);
|
||||
else { E->a_magic = UNKNOWN_AOUT; return (IS_UNKNOWN); }
|
||||
case V1_NORMAL: return (IS_V1);
|
||||
case BSD_OVERLAY:
|
||||
case BSD_ROVERLAY: return (IS_211BSD);
|
||||
case ANY_NORMAL:
|
||||
case ANY_ROTEXT:
|
||||
case ANY_SPLITID: /* Check crt0.o 2nd magic for V2/V6/V7/2.11BSD */
|
||||
if (E->a_magic2 == V2_M2) return (IS_V2);
|
||||
if (E->a_magic2 == V6_M2) return (IS_V6);
|
||||
if (E->a_magic2 == V7_M2) return (IS_V7);
|
||||
if (E->a_magic2 == BSD_M2) return (IS_211BSD);
|
||||
|
||||
/* Still no idea, use checksum to determine */
|
||||
return(special_magic((u_int16_t *) E));
|
||||
|
||||
default: /* Should never get here */
|
||||
E->a_magic = UNKNOWN_AOUT; return (IS_UNKNOWN);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Read in the executable name and its arguments from the shell script,
|
||||
* and the re-call load_a_out to load in that binary. Returns 0 on
|
||||
* success, -1 on error. Input file is always closed by this routine.
|
||||
*/
|
||||
int load_script(const char *file, const char *origpath,FILE * zin, int want_env)
|
||||
{
|
||||
#define SCRIPT_LINESIZE 512 /* Max size of 1st line in script */
|
||||
char *script_line;
|
||||
char *script_arg[MAX_ARGS];
|
||||
int i, script_cnt = 0;
|
||||
char **ap;
|
||||
|
||||
for (i=0;i<Argc;i++)
|
||||
TrapDebug((dbg_file, "In load_script Argv[%d] is %s\n", i, Argv[i]));
|
||||
/* Get the first line of the file */
|
||||
if (((script_line = (char *) malloc(SCRIPT_LINESIZE)) == NULL) ||
|
||||
(fgets(script_line, SCRIPT_LINESIZE, zin) == NULL)) {
|
||||
(void) fprintf(stderr, "Apout - could not read 1st line of script\n");
|
||||
(void) fclose(zin);
|
||||
return (-1);
|
||||
}
|
||||
/* Now break into separate words */
|
||||
for (ap = script_arg; (*ap = strsep(&script_line, " \t\n")) != NULL;)
|
||||
if (**ap != '\0') {
|
||||
ap++; script_cnt++;
|
||||
if (script_cnt >= MAX_ARGS) break;
|
||||
}
|
||||
if (fclose(zin) != 0) { free(script_line); return (-1); }
|
||||
|
||||
#ifdef DEBUG
|
||||
TrapDebug((dbg_file, "Script: extra args are is %d\n", script_cnt));
|
||||
if (trap_debug) {
|
||||
for (i = 0; i < script_cnt; i++)
|
||||
fprintf(dbg_file, " script_arg[%d] is %s\n", i, script_arg[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Ensure we have room to shift the args */
|
||||
if ((Argc + script_cnt) > MAX_ARGS) {
|
||||
(void) fprintf(stderr, "Apout - out of argv space in script\n");
|
||||
free(script_line); return (-1);
|
||||
}
|
||||
/* Now shift the args up and insert new ones */
|
||||
for (i = Argc - 1; i != 0; i--) Argv[i + script_cnt] = Argv[i];
|
||||
for (i=0;i<Argc;i++)
|
||||
TrapDebug((dbg_file, "Part A load_script Argv[%d] is %s\n", i, Argv[i]));
|
||||
for (i = 0; i < script_cnt; i++) Argv[i] = script_arg[i];
|
||||
if (origpath!=NULL) Argv[i] = strdup(origpath);
|
||||
else Argv[i] = strdup(file);
|
||||
Argc += script_cnt;
|
||||
for (i=0;i<Argc;i++)
|
||||
TrapDebug((dbg_file, "Part B load_script Argv[%d] is %s\n", i, Argv[i]));
|
||||
|
||||
file = xlate_filename(script_arg[0]);
|
||||
free(script_line);
|
||||
for (i=0;i<Argc;i++)
|
||||
TrapDebug((dbg_file, "Leaving load_script Argv[%d] is %s\n", i, Argv[i]));
|
||||
return (load_a_out(file, origpath, want_env));
|
||||
}
|
||||
|
||||
|
||||
/* Load the named PDP-11 executable file into the emulator's memory.
|
||||
* Returns 0 if ok, -1 if error. Also initialise the simulator and set
|
||||
* up the stack for the process with Argc, Argv, Envc, Envp.
|
||||
* origpath is the path to the executable as seen by the simulated
|
||||
* parent, or NULL if this is not known.
|
||||
*/
|
||||
int load_a_out(const char *file, const char *origpath, int want_env)
|
||||
{ /* @globals errno,stdout,stderr; @ */
|
||||
#define V12_MEMBASE 16384 /* Offset for V1/V2 binaries load */
|
||||
FILE *zin;
|
||||
struct exec e;
|
||||
u_int8_t *ibase, *dbase, *bbase; /* Instruction, data, bss bases */
|
||||
u_int16_t size;
|
||||
int i;
|
||||
#ifdef EMU211
|
||||
int j;
|
||||
#endif
|
||||
|
||||
for (i=0;i<Argc;i++)
|
||||
TrapDebug((dbg_file, "In load_a_out Argv[%d] is %s\n", i, Argv[i]));
|
||||
|
||||
(void) signal(SIGBUS, bus_error); /* Catch all bus errors here */
|
||||
|
||||
if ((zin = fopen(file, "r"))==NULL) /* Open the file */
|
||||
return (-1);
|
||||
|
||||
Binary = load_aout_header(zin, &e); /* Determine a.out & Unix type */
|
||||
|
||||
if (e.a_magic == ANY_SCRIPT) { /* Shell script, run that */
|
||||
return (load_script(file, origpath, zin, want_env));
|
||||
}
|
||||
#ifndef EMU211
|
||||
if (Binary == IS_211BSD) {
|
||||
(void) fprintf(stderr, "Apout not compiled to support 2.11BSD binaries\n");
|
||||
(void) fclose(zin); return (-1);
|
||||
}
|
||||
#endif
|
||||
#ifndef EMUV1
|
||||
if (Binary == IS_V1) {
|
||||
(void) fprintf(stderr,
|
||||
"Apout not compiled to support 1st Edition binaries\n");
|
||||
(void) fclose(zin); return (-1);
|
||||
}
|
||||
if (Binary == IS_V2) {
|
||||
(void) fprintf(stderr,
|
||||
"Apout not compiled to support 2nd Edition binaries\n");
|
||||
(void) fclose(zin); return (-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NATIVES
|
||||
/* Executable was not recognised.
|
||||
* Try to exec it as a native binary.
|
||||
* If it fails, doesn't matter. If it
|
||||
* succeeds, then great. This allows
|
||||
* us to have mixed native and PDP-11
|
||||
* binaries in the same filespace.
|
||||
*/
|
||||
if (e.a_magic == UNKNOWN_AOUT) {
|
||||
#ifdef DEBUG
|
||||
TrapDebug((dbg_file, "About to try native exec on %s\n", file));
|
||||
fflush(dbg_file);
|
||||
#endif
|
||||
(void) fclose(zin);
|
||||
execv(file, Argv); /* envp[] is the one Apout's main() got */
|
||||
TrapDebug((dbg_file, "Nope, didn't work\n"));
|
||||
(void) fprintf(stderr, "Apout - unknown a.out file %s\n", file);
|
||||
return (-1);
|
||||
}
|
||||
#endif
|
||||
/* Now we know what environment to
|
||||
* create, set up the memory areas
|
||||
* according to the magic numbers
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
switch(Binary) {
|
||||
case IS_A68: TrapDebug((dbg_file, "A68 binary\n")); break;
|
||||
case IS_V1: TrapDebug((dbg_file, "V1 binary\n")); break;
|
||||
case IS_V2: TrapDebug((dbg_file, "V2 binary\n")); break;
|
||||
case IS_V5: TrapDebug((dbg_file, "V5 binary\n")); break;
|
||||
case IS_V6: TrapDebug((dbg_file, "V6 binary\n")); break;
|
||||
case IS_V7: TrapDebug((dbg_file, "V7 binary\n")); break;
|
||||
case IS_211BSD: TrapDebug((dbg_file, "2.11BSD binary\n")); break;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (e.a_magic) {
|
||||
#ifdef EMUV1
|
||||
case V1_NORMAL: /* V1 a.out binary looks like */
|
||||
e.a_bss = e.a_syms; /* 0405 */
|
||||
e.a_syms = e.a_data; /* size of text */
|
||||
e.a_data = 0; /* size of symbol table */
|
||||
/* reloc bits */
|
||||
/* size of data (i.e bss) */
|
||||
/* unused and zeroed */
|
||||
/* We must rearrange fields */
|
||||
/* Move back to start of V1 header */
|
||||
if (fseek(zin, 0, SEEK_SET) != 0) {
|
||||
(void) fclose(zin); return (-1);
|
||||
}
|
||||
ispace = dspace = darray;
|
||||
ibase = &(ispace[V12_MEMBASE]); /* Load & run the binary starting */
|
||||
dbase = &(ispace[e.a_text]); /* at address 16384 (040000) */
|
||||
bbase = &(ispace[e.a_text + e.a_data]);
|
||||
dwrite_base = 0;
|
||||
e.a_entry = V12_MEMBASE;
|
||||
break;
|
||||
#endif
|
||||
case A68_MAGIC: /* Algol 68 image */
|
||||
if (fseek(zin, 0, SEEK_SET) != 0) {
|
||||
(void) fclose(zin); return (-1);
|
||||
}
|
||||
e.a_text= e.ov_siz[0]+1;
|
||||
e.a_data= 0;
|
||||
e.a_bss= 0160000-e.a_text;
|
||||
e.a_entry= e.a_flag;
|
||||
ibase = ispace = dspace = darray;
|
||||
dbase= ibase;
|
||||
dwrite_base = 0;
|
||||
bbase= &(ispace[e.a_text+e.a_data]);
|
||||
break;
|
||||
case ANY_NORMAL:
|
||||
/* Move back to end of V5/6/7 header */
|
||||
if (fseek(zin, 16, SEEK_SET) != 0) {
|
||||
(void) fclose(zin); return (-1);
|
||||
}
|
||||
ibase = ispace = dspace = darray;
|
||||
#ifdef EMUV1
|
||||
if (Binary == IS_V2) {
|
||||
ibase = &(ispace[V12_MEMBASE]);
|
||||
e.a_entry = V12_MEMBASE;
|
||||
dbase = &(ispace[e.a_text + V12_MEMBASE]);
|
||||
bbase = &(ispace[e.a_text + e.a_data + V12_MEMBASE]);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
dbase = &(ispace[e.a_text]);
|
||||
bbase = &(ispace[e.a_text + e.a_data]);
|
||||
}
|
||||
if ((Binary < IS_V7))
|
||||
dwrite_base = 0;
|
||||
else dwrite_base = e.a_text;
|
||||
break;
|
||||
case ANY_ROTEXT:
|
||||
/* Move back to end of V5/6/7 header */
|
||||
if (fseek(zin, 16, SEEK_SET) != 0) {
|
||||
(void) fclose(zin); return (-1);
|
||||
}
|
||||
/* @fallthrough@ */
|
||||
case BSD_OVERLAY:
|
||||
/* Round up text area to next 8K boundary */
|
||||
if (e.a_text % EIGHT_K) {
|
||||
size = EIGHT_K * (1 + e.a_text / EIGHT_K);
|
||||
} else size = e.a_text;
|
||||
/* And the next 8K boundary if overlays! */
|
||||
if (e.a_magic == BSD_OVERLAY) {
|
||||
if (e.max_ovl % EIGHT_K) {
|
||||
size += EIGHT_K * (1 + e.max_ovl / EIGHT_K);
|
||||
} else size += e.max_ovl;
|
||||
}
|
||||
ibase = ispace = dspace = darray;
|
||||
dbase = &(ispace[size]);
|
||||
bbase = &(ispace[size + e.a_data]);
|
||||
dwrite_base = size;
|
||||
break;
|
||||
case ANY_SPLITID:
|
||||
/* Move back to end of V5/6/7 header */
|
||||
if (fseek(zin, 16, SEEK_SET) != 0) {
|
||||
(void) fclose(zin); return (-1);
|
||||
}
|
||||
/* @fallthrough@ */
|
||||
case BSD_ROVERLAY:
|
||||
ibase = ispace = iarray;
|
||||
dbase = dspace = darray;
|
||||
bbase = &(dspace[e.a_data]);
|
||||
|
||||
/* Try to stop null refs */
|
||||
if (Binary == IS_211BSD) dwrite_base = 0;
|
||||
else dwrite_base = 2;
|
||||
break;
|
||||
default:
|
||||
(void) fprintf(stderr, "Apout - unknown a.out format 0%o\n", e.a_magic);
|
||||
(void) fclose(zin); return (-1);
|
||||
}
|
||||
|
||||
|
||||
/* Initialise the instruction table for our environment */
|
||||
switch (Binary) {
|
||||
#ifdef EMU211
|
||||
case IS_211BSD:
|
||||
for (i = 548; i < 552; i++) itab[i] = bsdtrap;
|
||||
break;
|
||||
#endif
|
||||
#ifdef EMUV1
|
||||
case IS_V1:
|
||||
case IS_V2:
|
||||
for (i = 544; i < 548; i++) itab[i] = rts;
|
||||
for (i = 548; i < 552; i++) itab[i] = v1trap;
|
||||
break;
|
||||
#endif
|
||||
case IS_A68:
|
||||
for (i = 544; i < 552; i++) itab[i] = v7trap;
|
||||
break;
|
||||
case IS_V5:
|
||||
case IS_V6:
|
||||
case IS_V7:
|
||||
for (i = 548; i < 552; i++) itab[i] = v7trap;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Apout - unknown Unix version for %s\n", file);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
#ifdef ZERO_MEMORY
|
||||
memset(darray, 0, PDP_MEM_SIZE); /* Clear all memory */
|
||||
if (ispace != dspace) memset(iarray, 0, PDP_MEM_SIZE);
|
||||
#endif
|
||||
|
||||
/* Now load the text into ibase */
|
||||
for (size = e.a_text; size;) {
|
||||
i = (int) fread(ibase, 1, (size_t) size, zin);
|
||||
if (i == -1) { (void) fclose(zin); return (i); }
|
||||
size -= i;
|
||||
ibase += i;
|
||||
}
|
||||
|
||||
#ifdef EMU211
|
||||
/* Now deal with any overlays */
|
||||
if (Binary == IS_211BSD)
|
||||
switch (e.a_magic) {
|
||||
case BSD_OVERLAY:
|
||||
case BSD_ROVERLAY:
|
||||
/* Round up text area to next 8K boundary */
|
||||
if (e.a_text % EIGHT_K) {
|
||||
size = EIGHT_K * (1 + e.a_text / EIGHT_K);
|
||||
} else size = e.a_text;
|
||||
ovbase = &ispace[size];
|
||||
|
||||
for (i = 0; i < NOVL; i++) {
|
||||
if (e.ov_siz[i] == 0) {
|
||||
ovlist[i].size = 0;
|
||||
ovlist[i].ovlay = NULL;
|
||||
continue;
|
||||
}
|
||||
/* Create memory for the overlay */
|
||||
ovlist[i].size = e.ov_siz[i];
|
||||
if (ovlist[i].ovlay)
|
||||
free(ovlist[i].ovlay);
|
||||
ovlist[i].ovlay = (u_int8_t *) malloc(e.ov_siz[i]);
|
||||
if (ovlist[i].ovlay == NULL) {
|
||||
fprintf(stderr, "Apout - can't malloc overlay!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
/* Load the overlay into memory */
|
||||
for (size = ovlist[i].size, ibase = ovlist[i].ovlay; size;) {
|
||||
j = fread(ibase, 1, size, zin);
|
||||
if (j == -1) {
|
||||
fclose(zin); return (j);
|
||||
}
|
||||
size -= j;
|
||||
ibase += j;
|
||||
}
|
||||
}
|
||||
|
||||
/* And deal with the emt instructions */
|
||||
for (i = 544; i < 548; i++)
|
||||
itab[i] = do_bsd_overlay;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Now load the data into dbase */
|
||||
if (dbase)
|
||||
for (size = e.a_data; size;) {
|
||||
i = (int) fread(dbase, 1, (size_t) size, zin);
|
||||
if (i == -1) { (void) fclose(zin); return (i); }
|
||||
size -= i;
|
||||
dbase += i;
|
||||
}
|
||||
|
||||
/* Now clear the bss */
|
||||
if ((bbase != 0) && (e.a_bss != 0))
|
||||
memset(bbase, 0, (size_t) e.a_bss);
|
||||
|
||||
|
||||
/* Set up the registers and flags, and the stack */
|
||||
(void) fclose(zin);
|
||||
sim_init();
|
||||
regs[PC] = e.a_entry;
|
||||
if( Binary == IS_A68 ) {
|
||||
regs[5]= e.max_ovl;
|
||||
regs[4]= 0160000;
|
||||
}
|
||||
set_arg_env(want_env);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* C runtime startoff. When an a.out is loaded by the kernel, the kernel
|
||||
* sets up the stack as follows:
|
||||
*
|
||||
* _________________________________
|
||||
* | (NULL) | 0177776: top of memory
|
||||
* |-------------------------------|
|
||||
* | |
|
||||
* | environment strings |
|
||||
* | |
|
||||
* |-------------------------------|
|
||||
* | |
|
||||
* | argument strings |
|
||||
* | |
|
||||
* |-------------------------------|
|
||||
* | envv[envc] (NULL) | end of environment vector tag, a 0
|
||||
* |-------------------------------|
|
||||
* | envv[envc-1] | pointer to last environment string
|
||||
* |-------------------------------|
|
||||
* | ... |
|
||||
* |-------------------------------|
|
||||
* | envv[0] | pointer to first environment string
|
||||
* |-------------------------------|
|
||||
* | argv[argc] (NULL) | end of argument vector tag, a 0
|
||||
* |-------------------------------|
|
||||
* | argv[argc-1] | pointer to last argument string
|
||||
* |-------------------------------|
|
||||
* | ... |
|
||||
* |-------------------------------|
|
||||
* | argv[0] | pointer to first argument string
|
||||
* |-------------------------------|
|
||||
* sp-> | argc | number of arguments
|
||||
* ---------------------------------
|
||||
*
|
||||
* Crt0 simply moves the argc down two places in the stack, calculates the
|
||||
* the addresses of argv[0] and envv[0], putting those values into the two
|
||||
* spaces opened up to set the stack up as main expects to see it.
|
||||
*
|
||||
* If want_env is set, create a stack by including environment variables:
|
||||
* used by V7, 2.9BSD, 2.11BSD. Otherwise, don't create environment
|
||||
* variables: used by V1 up to V6.
|
||||
*/
|
||||
static void set_arg_env(int want_env)
|
||||
{
|
||||
int i, posn, len;
|
||||
int eposn[MAX_ARGS];
|
||||
int aposn[MAX_ARGS];
|
||||
|
||||
/* Set default environment if there is none */
|
||||
if (Envp[0] == NULL) {
|
||||
Envc = default_envc;
|
||||
for (i = 0; i < Envc; i++)
|
||||
Envp[i] = default_envp[i];
|
||||
}
|
||||
#ifdef DEBUG
|
||||
/* Set up the program's name -- used for debugging */
|
||||
if (progname) free(progname);
|
||||
progname = strdup(Argv[0]);
|
||||
|
||||
if (trap_debug) {
|
||||
fprintf(dbg_file, "In set_arg_env, Argc is %d\n", Argc);
|
||||
for (i = 0; i < Argc; i++)
|
||||
fprintf(dbg_file, " Argv[%d] is %s\n", i, Argv[i]);
|
||||
for (i = 0; i < Envc; i++)
|
||||
fprintf(dbg_file, " Envp[%d] is %s\n", i, Envp[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Now build the arguments and pointers on the stack */
|
||||
|
||||
#ifdef EMUV1
|
||||
if ((Binary == IS_V1) || (Binary == IS_V2))
|
||||
posn = KE11LO - 2; /* Start below the KE11A */
|
||||
else
|
||||
#endif
|
||||
posn = PDP_MEM_SIZE - 2;
|
||||
sl_word(posn, 0); /* Put a NULL on top of stack */
|
||||
|
||||
if (want_env == 1)
|
||||
for (i = Envc - 1; i != -1; i--) { /* For each env string */
|
||||
len = strlen(Envp[i]) + 1; /* get its length */
|
||||
posn -= len;
|
||||
memcpy(&dspace[posn], Envp[i], (size_t) len);
|
||||
eposn[i] = posn;
|
||||
}
|
||||
|
||||
for (i = Argc - 1; i != -1; i--) { /* For each arg string */
|
||||
len = strlen(Argv[i]) + 1; /* get its length */
|
||||
posn -= len;
|
||||
memcpy(&dspace[posn], Argv[i], (size_t) len);
|
||||
aposn[i] = posn;
|
||||
}
|
||||
posn -= 2;
|
||||
sl_word(posn, 0); /* Put a NULL at end of env array */
|
||||
|
||||
if (want_env == 1) { /* For each env string */
|
||||
for (i = Envc - 1; i != -1; i--) {
|
||||
posn -= 2; /* put a pointer to the string */
|
||||
sl_word(posn, (u_int16_t) eposn[i]);
|
||||
}
|
||||
posn -= 2;
|
||||
}
|
||||
/* Put a NULL or -1 before arg ptrs */
|
||||
if (want_env == 0) sl_word(posn, -1)
|
||||
else sl_word(posn, 0);
|
||||
|
||||
for (i = Argc - 1; i != -1; i--) { /* For each arg string */
|
||||
posn -= 2;
|
||||
sl_word(posn, (u_int16_t) aposn[i]); /* put a ptr to the string */
|
||||
}
|
||||
posn -= 2;
|
||||
sl_word(posn, (u_int16_t) Argc); /* Save the count of args */
|
||||
regs[SP] = (u_int16_t) posn; /* and initialise the SP */
|
||||
}
|
||||
|
||||
|
||||
#ifdef EMU211
|
||||
/* This function probably belongs in bsdtrap.c, but all the vars are
|
||||
* here, so why not!
|
||||
*
|
||||
* Deal with overlay changes which come in via an emt instruction.
|
||||
*/
|
||||
|
||||
void do_bsd_overlay()
|
||||
{
|
||||
int ov = regs[0] - 1;
|
||||
|
||||
if (ovlist[ov].size == 0) {
|
||||
fprintf(stderr, "Apout - can't switch to empty overlay %d\n", ov);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
JsrDebug((dbg_file, "switching to overlay %d\n", ov));
|
||||
|
||||
/* Memcpy overlay into main ispace */
|
||||
memcpy(ovbase, ovlist[ov].ovlay, ovlist[ov].size);
|
||||
ov_changes++;
|
||||
current_ov = ov;
|
||||
}
|
||||
#endif
|
||||
54
tools/apout/aout.h
Normal file
54
tools/apout/aout.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/* aout.h - parse and load the contents of a UNIX a.out file, for
|
||||
* several flavours of PDP-11 UNIX
|
||||
*
|
||||
* $Revision: 1.4 $
|
||||
* $Date: 2000/08/11 07:07:35 $
|
||||
*/
|
||||
#include <unistd.h>
|
||||
#define EIGHT_K 8192
|
||||
|
||||
/* UNIX magic numbers for the a.out header */
|
||||
#define V1_NORMAL 0405 /* normal: 1st Edition, six words long */
|
||||
#define ANY_NORMAL 0407 /* normal: V5,V6,V7,2.11BSD */
|
||||
#define ANY_ROTEXT 0410 /* read-only text: V5,V6,V7,2.11BSD */
|
||||
#define ANY_SPLITID 0411 /* seperated I&D: V5,V6,V7,2.11BSD */
|
||||
#define BSD_OVERLAY 0430 /* 2.11BSD overlay, non-separate */
|
||||
#define BSD_ROVERLAY 0431 /* 2.11BSD overlay, separate */
|
||||
#define ANY_SCRIPT 020443 /* Shell script, i.e #! */
|
||||
#define A68_MAGIC 0 /* Algol68 binaries have these magic nums */
|
||||
#define A68_DATA 0107116 /* Algol68 binaries have these magic nums */
|
||||
|
||||
#define UNKNOWN_AOUT 034567 /* An unknown a.out header */
|
||||
|
||||
/* a.out header for nearly all UNIX flavours */
|
||||
struct exec {
|
||||
u_int16_t a_magic; /* magic number */
|
||||
u_int16_t a_text; /* size of text segment */
|
||||
u_int16_t a_data; /* size of initialised data */
|
||||
u_int16_t a_bss; /* size of initialised bss */
|
||||
u_int16_t a_syms; /* size of symbol table */
|
||||
u_int16_t a_entry; /* entry point */
|
||||
u_int16_t a_unused; /* unused */
|
||||
u_int16_t a_flag; /* relocation info stripped */
|
||||
/* 16 bytes up to here */
|
||||
|
||||
/* 2.11BSD overlay files have the following */
|
||||
#define NOVL 15
|
||||
int16_t max_ovl; /* maximum overlay size */
|
||||
u_int16_t ov_siz[NOVL]; /* size of the i'th overlay */
|
||||
/* Note that if the file isn't a 2.11BSD */
|
||||
/* overlay, we have to rewind to undo */
|
||||
/* the read of this section */
|
||||
};
|
||||
|
||||
/* Because V5, V6, V7 and 2.11BSD share several magic numbers
|
||||
* in their a.out headers, we must distinguish them so as to
|
||||
* set up the correct emulated environment. This is done by
|
||||
* observing the differences in their crt0.s code: they all
|
||||
* differ at position 021
|
||||
*/
|
||||
#define a_magic2 ov_siz[0]
|
||||
#define V2_M2 0177304 /* Doesn't apply to all, tho */
|
||||
#define V6_M2 0010600
|
||||
#define V7_M2 0016600
|
||||
#define BSD_M2 0162706
|
||||
234
tools/apout/apout.1
Normal file
234
tools/apout/apout.1
Normal file
@@ -0,0 +1,234 @@
|
||||
.\" Copyright Warren Toomey
|
||||
.\"
|
||||
.\" $Revision: 1.9 $
|
||||
.\" $Date: 2002/06/10 12:08:27 $
|
||||
.\"
|
||||
.Dd December, 2000
|
||||
.Dt APOUT 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm apout
|
||||
.Nd run PDP-11 UNIX a.out binaries
|
||||
.Sh SYNOPSIS
|
||||
.Nm apout
|
||||
.Op Fl inst
|
||||
.Op Fl trap
|
||||
.Op Fl jsr
|
||||
.Op Fl fp
|
||||
.Ar file
|
||||
.Op Ar arguments ...
|
||||
.Sh DESCRIPTION
|
||||
.Nm apout
|
||||
runs the
|
||||
.Ar file
|
||||
which contains a PDP-11 UNIX a.out binary from one of the following
|
||||
versions of UNIX: 1st Edition, 2nd Edition, 5th Edition, 6th Edition,
|
||||
7th Edition, 2.9BSD or 2.11BSD. Any arguments after the named
|
||||
.Ar file
|
||||
are passed as arguments to the a.out binary.
|
||||
.Pp
|
||||
User-mode PDP-11 instructions are interpreted and executed by
|
||||
.Nm apout,
|
||||
and system calls made by the interpreted a.out binary are performed
|
||||
by making real systems calls to the underlying native operating system.
|
||||
In this way, the interpreted a.out binary can interact with the real
|
||||
files and processes on the system.
|
||||
.Pp
|
||||
If
|
||||
.Nm apout
|
||||
has been compiled with debugging enabled, the following options are available:
|
||||
.Bl -tag -width trap
|
||||
.It Fl inst
|
||||
Output a line for each instruction emulated which gives:
|
||||
the PC in octal, the instruction in octal, the instruction's name,
|
||||
r0 to r6 in octal, and the values of the N, Z, V and C flags.
|
||||
.It Fl trap
|
||||
Output a line for each system call, which gives the name of the system
|
||||
call, possibly a list of arguments, and the value returned by the system
|
||||
call.
|
||||
.It Fl jsr
|
||||
Output a line for each
|
||||
.Ar jsr
|
||||
or
|
||||
.Ar rts
|
||||
giving the value of the new PC. For 2.11BSD overlay binaries, also output
|
||||
a line describing each overlay change.
|
||||
.It Fl fp
|
||||
For many of the emulated floating-point instructions, output a line
|
||||
describing the operation.
|
||||
.El
|
||||
.Pp
|
||||
If
|
||||
.Nm apout
|
||||
was not compiled with debugging enabled, none of these options exist.
|
||||
Any debugging output is directed to the file
|
||||
.Ar apout.dbg
|
||||
in the directory where
|
||||
.Nm apout
|
||||
was started. The debugging output is primarily designed to aid the
|
||||
developers of
|
||||
.Nm apout,
|
||||
and so it isn't exhaustive for all instructions, traps or floating-point
|
||||
operations.
|
||||
.Sh ENVIRONMENT VARIABLES
|
||||
.Nm apout
|
||||
requires one environment variable to be set:
|
||||
.Ev APOUT_ROOT.
|
||||
This variable names the `root' of the emulated filesystem.
|
||||
.Pp
|
||||
When
|
||||
.Nm apout
|
||||
works with filenames, if the filenames are relative, then they
|
||||
stay relative i.e all files on the system can be named, as long as they are
|
||||
given relative names. However, if the filenames are absolute, i.e they
|
||||
start with a slash, then
|
||||
.Nm apout
|
||||
prepends the value of the environment variable
|
||||
.Ev APOUT_ROOT
|
||||
to the filename. Therefore, if you have the 7th Edition files located in
|
||||
.Ar /usr/misc/v7root
|
||||
and you do:
|
||||
.Bd -literal
|
||||
% setenv APOUT_ROOT /usr/misc/v7root
|
||||
% apout $APOUT_ROOT/bin/sh
|
||||
$
|
||||
.Ed
|
||||
.Pp
|
||||
then you will be greeted with the 7th Edition Bourne shell prompt as shown:
|
||||
you will still be in the directory where you started
|
||||
.Nm apout,
|
||||
but if you cd to /, then you will be taken to
|
||||
.Ar /usr/misc/v7root
|
||||
.Pp
|
||||
Note that you must set
|
||||
.Ev APOUT_ROOT
|
||||
before you can run
|
||||
.Nm apout.
|
||||
.Sh EMULATED ENVIRONMENT VARIABLES
|
||||
Initially, PDP-11 binaries run via
|
||||
.Nm apout
|
||||
receive the following set of emulated environment variables:
|
||||
.Bd -literal
|
||||
PATH /bin:/usr/bin:/usr/sbin:/usr/ucb:/usr/games:/usr/local/bin:.
|
||||
HOME /
|
||||
TERM vt100
|
||||
.Ed
|
||||
.Pp
|
||||
Emulated programs can, of course, change this emulated environment;
|
||||
they can also fork and exec other PDP-11 binaries, which will inherit the
|
||||
modified emulated environment.
|
||||
.Sh INTERACTION WITH NATIVE PROGRAMS
|
||||
Binaries that are interpreted by
|
||||
.Nm apout
|
||||
can interact with native programs in several ways: through files in the
|
||||
filesystem, and through pipes. For example, you can do the following:
|
||||
.Bd -literal
|
||||
% ls -lR | apout $APOUT_ROOT/bin/wc | lpr
|
||||
% apout $APOUT_ROOT/bin/sort < file | uniq > newfile
|
||||
.Ed
|
||||
.Pp
|
||||
where
|
||||
.Ar ls,
|
||||
.Ar lpr
|
||||
and
|
||||
.Ar uniq
|
||||
are native programs.
|
||||
.Pp
|
||||
If
|
||||
.Nm apout
|
||||
is compiled with the NATIVES preprocessor directive enabled, then native system
|
||||
binaries can be executed as well as PDP-11 binaries. For example:
|
||||
.Bd -literal
|
||||
% cd $APOUT_ROOT
|
||||
% ln -s `which vi` bin/vi Add vi into the filespace
|
||||
% apout bin/sh
|
||||
$ ls -l Run the PDP-11 ls
|
||||
....
|
||||
$ vi kim.c Run the native vi
|
||||
$ cc -o kim kim.c Compile with the PDP-11 compiler
|
||||
.Ed
|
||||
.Pp
|
||||
Note that native executable receive the same environment variables inherited
|
||||
by the
|
||||
.Nm apout
|
||||
process, and not the emulated environment that
|
||||
.Nm apout
|
||||
passes to emulated executables.
|
||||
.Sh ERROR MESSAGES
|
||||
So as to distinguish from error messages generated by the interpreted PDP-11
|
||||
binaries,
|
||||
.Nm apout
|
||||
prepends the word `Apout' to the beginning of its error messages. Below is
|
||||
the list of error messages that
|
||||
.Nm apout
|
||||
can generate:
|
||||
.Bd -ragged
|
||||
Apout - V1 sectosixty too big
|
||||
Apout - can't malloc overlay!
|
||||
Apout - can't switch to empty overlay %d
|
||||
Apout - could not read 1st line of script
|
||||
Apout - couldn't load %s
|
||||
Apout - open_dir couldn't open %s
|
||||
Apout - out of argv space in script
|
||||
Apout - pid %d bad FP register used at PC 0%o
|
||||
Apout - pid %d bpt instruction at PC 0%o
|
||||
Apout - pid %d bus error at PC 0%06o
|
||||
Apout - pid %d emt instruction at PC 0%o
|
||||
Apout - pid %d halt instruction at PC 0%o
|
||||
Apout - pid %d illegal instruction %o at PC 0%o
|
||||
Apout - pid %d iot instruction at PC 0%o
|
||||
Apout - pid %d mark instruction at PC 0%o
|
||||
Apout - pid %d mfpd instruction at PC 0%o
|
||||
Apout - pid %d mtpd instruction at PC 0%o
|
||||
Apout - pid %d segmentation fault at PC 0%06o
|
||||
Apout - pid %d trap instruction at PC 0%o
|
||||
Apout - pid %d unimplemented instruction at PC 0%o
|
||||
Apout - pid %d unknown KE11 register 0%o
|
||||
Apout - pid %d waiti instruction at PC 0%o
|
||||
Apout - the %s syscall is not yet implemented
|
||||
Apout - the 2.11BSD %s syscall is not yet implemented
|
||||
Apout - unknown a.out format 0%o
|
||||
Apout - unknown magic in header: 0x%x
|
||||
Apout - unknown syscall %d at PC 0%o
|
||||
Apout cannot set the environment for the a.out %s
|
||||
Apout not compiled to support 1st Edition binaries
|
||||
Apout not compiled to support 2nd Edition binaries
|
||||
Apout not compiled to support 2.11BSD binaries
|
||||
.Ed
|
||||
.Sh CAVEATS
|
||||
As far as is known, the emulation of user-mode integer instructions is correct.
|
||||
The emulation of floating-point instructions is seriously deficient:
|
||||
only 32-bit floats are emulated: the extra 32-bits of precision in PDP-11
|
||||
doubles goes unused. None of the FP errors are emulated.
|
||||
.Pp
|
||||
The emulation of each of the emulated UNIX environments is mostly,
|
||||
but not fully, complete. Any UNIX system call environment is very
|
||||
sophisticated, and
|
||||
.Ar apout
|
||||
must translate from the emulated UNIX environment to the native one, and
|
||||
back. For an authorative description of what is missing from, or deficient
|
||||
in, each of the emulated UNIX environments, see the source files
|
||||
.Ar v1trap.c,
|
||||
.Ar v7trap.c
|
||||
and
|
||||
.Ar bsdtrap.c
|
||||
in the source directory for
|
||||
.Nm apout.
|
||||
You should also consult the file
|
||||
.Ar LIMITATIONS
|
||||
in the source directory for
|
||||
.Nm apout.
|
||||
.Sh SEE ALSO
|
||||
The latest source for
|
||||
.Nm apout
|
||||
can be obtained via anonymous ftp at minnie.tuhs.org in the directory
|
||||
pub/PDP-11/Sims/Apout. The directory pub/PDP-11/Sims/Apout/UnixBins
|
||||
contains tar archives of a.out binaries from several versions of UNIX.
|
||||
Information on PDP-11 UNIX can be found on the PUPS web page at
|
||||
http://minnie.tuhs.org/PUPS/
|
||||
.Sh HISTORY
|
||||
The first version of
|
||||
.Nm apout
|
||||
appeared in 1995, and provided support for 6th and 7th Edition
|
||||
UNIX binaries. In 1998/1999, support was added for 2.11BSD binaries.
|
||||
In 1999/2000, support was added for 1st and 2nd Edition UNIX binaries.
|
||||
387
tools/apout/branch.c
Normal file
387
tools/apout/branch.c
Normal file
@@ -0,0 +1,387 @@
|
||||
/* branch.c - Branch instructions, and instructions which are complex to do
|
||||
*
|
||||
* $Revision: 2.22 $
|
||||
* $Date: 1999/12/27 04:38:29 $
|
||||
*/
|
||||
#include "defines.h"
|
||||
|
||||
/* We use the following macro for the branch instructions below */
|
||||
|
||||
#define do_branch() \
|
||||
{ offset = LOW8(ir); \
|
||||
if (offset & SIGN_B) \
|
||||
offset += 0177400; \
|
||||
regs[PC] += (offset * 2); \
|
||||
} \
|
||||
|
||||
static u_int16_t offset;
|
||||
|
||||
void bne() {
|
||||
if (CC_Z==0) do_branch();
|
||||
}
|
||||
void beq() {
|
||||
if (CC_Z==1) do_branch();
|
||||
}
|
||||
void bpl() {
|
||||
if (CC_N==0) do_branch();
|
||||
}
|
||||
void bmi() {
|
||||
if (CC_N==1) do_branch();
|
||||
}
|
||||
void bhi() {
|
||||
if ((CC_Z==0) && (CC_C==0)) do_branch();
|
||||
}
|
||||
void bvc() {
|
||||
if (CC_V==0) do_branch();
|
||||
}
|
||||
void bvs() {
|
||||
if (CC_V==1) do_branch();
|
||||
}
|
||||
void bcc() {
|
||||
if (CC_C==0) do_branch();
|
||||
}
|
||||
void bcs() {
|
||||
if (CC_C==1) do_branch();
|
||||
}
|
||||
|
||||
/* br() - Branch Always. */
|
||||
void br() {
|
||||
do_branch();
|
||||
}
|
||||
|
||||
|
||||
/* blos() - Branch Lower or Same Instruction. */
|
||||
void blos() {
|
||||
if ((CC_C!=0) || (CC_Z!=0)) do_branch();
|
||||
}
|
||||
|
||||
/* bge() - Branch Greater Than or Equal Instruction. */
|
||||
void bge() {
|
||||
if ((CC_N ^ CC_V) == 0) do_branch();
|
||||
}
|
||||
|
||||
/* blt() - Branch Less Than Instruction. */
|
||||
void blt() {
|
||||
if ((CC_N ^ CC_V) == 1) do_branch();
|
||||
}
|
||||
|
||||
/* ble() - Branch Less Than Or Equal Instruction. */
|
||||
void ble() {
|
||||
if (((CC_N ^ CC_V) == 1) || ((CC_Z)!=0)) do_branch();
|
||||
}
|
||||
|
||||
/* bgt() - Branch Greater Than Instruction. */
|
||||
void bgt() {
|
||||
if (((CC_N ^ CC_V) == 0) && ((CC_Z) == 0)) do_branch();
|
||||
}
|
||||
|
||||
/* jmp() - Jump Instruction. */
|
||||
void jmp() {
|
||||
load_ea(); regs[PC]=dstword;
|
||||
}
|
||||
|
||||
/* jsr() - Jump To Subroutine Instruction. */
|
||||
void jsr() {
|
||||
load_ea();
|
||||
srcword=regs[SRC_REG]; push();
|
||||
regs[SRC_REG] = regs[PC];
|
||||
regs[PC] = dstword;
|
||||
JsrDebug((dbg_file, "jsr to 0%o\n", dstword));
|
||||
}
|
||||
|
||||
/* rts() - Return From Subroutine Instruction. */
|
||||
void rts() {
|
||||
regs[PC] = regs[DST_REG];
|
||||
pop(); regs[DST_REG] = dstword;
|
||||
JsrDebug((dbg_file, "rts to 0%o\n", regs[PC]));
|
||||
}
|
||||
|
||||
void scc() {
|
||||
if (ir & CC_NBIT) CC_N=1;
|
||||
if (ir & CC_ZBIT) CC_Z=1;
|
||||
if (ir & CC_VBIT) CC_V=1;
|
||||
if (ir & CC_CBIT) CC_C=1;
|
||||
}
|
||||
void ccc() {
|
||||
if (ir & CC_NBIT) CC_N=0;
|
||||
if (ir & CC_ZBIT) CC_Z=0;
|
||||
if (ir & CC_VBIT) CC_V=0;
|
||||
if (ir & CC_CBIT) CC_C=0;
|
||||
}
|
||||
|
||||
/* sob() - Subtract One and Branch Instruction. */
|
||||
void sob() {
|
||||
regs[SRC_REG] -= 1;
|
||||
if (regs[SRC_REG]) {
|
||||
regs[PC] -= (ir & 077) * 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* mfps() - Move from Processor Status Instruction. */
|
||||
void mfps() {
|
||||
srcbyte=(u_int8_t)0;
|
||||
if (CC_N) srcbyte|= CC_NBIT;
|
||||
if (CC_Z) srcbyte|= CC_ZBIT;
|
||||
if (CC_V) srcbyte|= CC_VBIT;
|
||||
if (CC_C) srcbyte|= CC_CBIT;
|
||||
|
||||
CHGB_CC_N(srcbyte);
|
||||
CHGB_CC_Z(srcbyte);
|
||||
CLR_CC_V();
|
||||
|
||||
if (DST_MODE) {
|
||||
storeb_dst();
|
||||
} else {
|
||||
if (srcbyte & SIGN_B) {
|
||||
dstword = 0177400;
|
||||
} else {
|
||||
dstword = 0;
|
||||
}
|
||||
dstword += (u_int16_t)srcbyte;
|
||||
store_dst();
|
||||
}
|
||||
}
|
||||
|
||||
/* mtps() - Move to Processor Status Instruction. */
|
||||
void mtps() {
|
||||
loadb_dst();
|
||||
if (dstbyte & CC_NBIT) CC_N=1;
|
||||
if (dstbyte & CC_ZBIT) CC_Z=1;
|
||||
if (dstbyte & CC_VBIT) CC_V=1;
|
||||
if (dstbyte & CC_CBIT) CC_C=1;
|
||||
}
|
||||
|
||||
/* mfpi() - Move From Previous Instruction Space Instruction. */
|
||||
void mfpi() {
|
||||
loadp_dst(); push();
|
||||
}
|
||||
|
||||
|
||||
/* mtpi() - To From Previous Instruction Space Instruction. */
|
||||
void mtpi() {
|
||||
pop(); storep_dst();
|
||||
}
|
||||
|
||||
/* ash() - Arithmetic Shift Instruction. */
|
||||
void ash() {
|
||||
u_int16_t temp;
|
||||
u_int16_t old;
|
||||
u_int16_t sign;
|
||||
u_int16_t count;
|
||||
|
||||
temp = regs[SRC_REG];
|
||||
load_dst();
|
||||
old = temp;
|
||||
|
||||
if ((dstword & 077) == 0) { /* no shift */
|
||||
CHG_CC_N(temp);
|
||||
CHG_CC_Z(temp);
|
||||
CLR_CC_V();
|
||||
return;
|
||||
}
|
||||
if (dstword & 040) { /* right shift */
|
||||
count = 0100 - (dstword & 077);
|
||||
sign = temp & SIGN;
|
||||
while (count--) {
|
||||
if (temp & LSBIT) {
|
||||
SET_CC_C();
|
||||
} else {
|
||||
CLR_CC_C();
|
||||
}
|
||||
temp >>= 1;
|
||||
temp += sign;
|
||||
}
|
||||
} else { /* left shift */
|
||||
count = dstword & 037;
|
||||
while (count--) {
|
||||
if (temp & SIGN) {
|
||||
SET_CC_C();
|
||||
} else {
|
||||
CLR_CC_C();
|
||||
}
|
||||
temp <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
CHG_CC_N(temp);
|
||||
CHG_CC_Z(temp);
|
||||
|
||||
if ((old & SIGN) == (temp & SIGN)) {
|
||||
CLR_CC_V();
|
||||
} else {
|
||||
SET_CC_V();
|
||||
}
|
||||
regs[SRC_REG] = temp;
|
||||
}
|
||||
|
||||
|
||||
/* mul() and divide() - Multiply and Divide Instructions. These work on
|
||||
* signed values, and we'll do the same. This may not be portable. */
|
||||
|
||||
union s_u_word {
|
||||
u_int16_t u_word;
|
||||
short s_word;
|
||||
};
|
||||
|
||||
union s_u_long {
|
||||
u_int32_t u_long;
|
||||
long s_long;
|
||||
};
|
||||
|
||||
void mul() {
|
||||
union s_u_word data1;
|
||||
union s_u_word data2;
|
||||
union s_u_long tmp;
|
||||
|
||||
data1.u_word = regs[SRC_REG];
|
||||
load_dst();
|
||||
data2.u_word=dstword;
|
||||
|
||||
tmp.s_long = ((long) data1.s_word) * ((long) data2.s_word);
|
||||
|
||||
regs[SRC_REG] = (u_int16_t)(tmp.u_long >> 16);
|
||||
regs[(SRC_REG) | 1] = (u_int16_t)(tmp.u_long & 0177777);
|
||||
|
||||
CLR_CC_ALL();
|
||||
|
||||
if (tmp.u_long == 0)
|
||||
SET_CC_Z();
|
||||
else
|
||||
CLR_CC_Z();
|
||||
|
||||
if (tmp.u_long & 0x80000000)
|
||||
SET_CC_N();
|
||||
else
|
||||
CLR_CC_N();
|
||||
}
|
||||
|
||||
void divide() {
|
||||
union s_u_long tmp;
|
||||
union s_u_long eql;
|
||||
union s_u_word data2;
|
||||
|
||||
tmp.u_long = regs[SRC_REG];
|
||||
tmp.u_long = tmp.u_long << 16;
|
||||
tmp.u_long += regs[(SRC_REG) | 1];
|
||||
|
||||
load_dst();
|
||||
data2.u_word=dstword;
|
||||
|
||||
if (data2.u_word == 0) {
|
||||
SET_CC_C();
|
||||
SET_CC_V();
|
||||
return;
|
||||
} else {
|
||||
CLR_CC_C();
|
||||
}
|
||||
|
||||
eql.s_long = tmp.s_long / data2.s_word;
|
||||
regs[SRC_REG] = (u_int16_t)eql.u_long & 0177777;
|
||||
|
||||
if (eql.u_long == 0)
|
||||
SET_CC_Z();
|
||||
else
|
||||
CLR_CC_Z();
|
||||
|
||||
if ((eql.s_long > 077777) || (eql.s_long < -0100000))
|
||||
SET_CC_V();
|
||||
else
|
||||
CLR_CC_V();
|
||||
|
||||
if (eql.s_long < 0)
|
||||
SET_CC_N();
|
||||
else
|
||||
CLR_CC_N();
|
||||
|
||||
eql.s_long = tmp.s_long % data2.s_word;
|
||||
regs[(SRC_REG) | 1] = (u_int16_t)eql.u_long & 0177777;
|
||||
}
|
||||
|
||||
/* ashc() - Arithmetic Shift Combined Instruction. */
|
||||
void ashc() {
|
||||
u_int32_t temp;
|
||||
u_int32_t old;
|
||||
u_int32_t sign;
|
||||
u_int16_t count;
|
||||
|
||||
temp = regs[SRC_REG];
|
||||
temp <<= 16;
|
||||
temp += regs[(SRC_REG) | 1];
|
||||
old = temp;
|
||||
load_dst();
|
||||
|
||||
if ((dstword & 077) == 0) { /* no shift */
|
||||
|
||||
CLR_CC_V();
|
||||
|
||||
if (temp & 0x80000000) {
|
||||
SET_CC_N();
|
||||
} else {
|
||||
CLR_CC_N();
|
||||
}
|
||||
|
||||
if (temp) {
|
||||
CLR_CC_Z();
|
||||
} else {
|
||||
SET_CC_Z();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (dstword & 040) { /* right shift */
|
||||
count = 0100 - (dstword & 077);
|
||||
sign = temp & 0x80000000;
|
||||
while (count--) {
|
||||
if (temp & LSBIT) {
|
||||
SET_CC_C();
|
||||
} else {
|
||||
CLR_CC_C();
|
||||
}
|
||||
temp >>= 1;
|
||||
temp += sign;
|
||||
}
|
||||
} else { /* left shift */
|
||||
count = dstword & 037;
|
||||
while (count--) {
|
||||
if (temp & 0x80000000) {
|
||||
SET_CC_C();
|
||||
} else {
|
||||
CLR_CC_C();
|
||||
}
|
||||
temp <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (temp & 0x80000000)
|
||||
SET_CC_N();
|
||||
else
|
||||
CLR_CC_N();
|
||||
|
||||
if (temp)
|
||||
CLR_CC_Z();
|
||||
else
|
||||
SET_CC_Z();
|
||||
|
||||
if ((old & 0x80000000) == (temp & 0x80000000)) {
|
||||
CLR_CC_V();
|
||||
} else {
|
||||
SET_CC_V();
|
||||
}
|
||||
|
||||
regs[SRC_REG] = (u_int16_t)(temp >> 16);
|
||||
regs[(SRC_REG) | 1] = LOW16(temp);
|
||||
}
|
||||
|
||||
/* xor() - Exclusive Or Instruction */
|
||||
void xor() {
|
||||
tmpword = regs[SRC_REG];
|
||||
|
||||
load_dst();
|
||||
|
||||
tmpword = tmpword ^ dstword;
|
||||
|
||||
CHG_CC_N(tmpword);
|
||||
CHG_CC_Z(tmpword);
|
||||
CLR_CC_V();
|
||||
|
||||
dstword=tmpword; store_dst_2();
|
||||
}
|
||||
479
tools/apout/bsd_ioctl.c
Normal file
479
tools/apout/bsd_ioctl.c
Normal file
@@ -0,0 +1,479 @@
|
||||
/*
|
||||
* bsd_ioctl.c - Deal with 2.11BSD ioctl system calls.
|
||||
*
|
||||
* $Revision: 1.13 $ $Date: 1999/12/27 04:38:29 $
|
||||
*/
|
||||
#ifdef EMU211
|
||||
#include "defines.h"
|
||||
#include <sys/ioctl.h>
|
||||
#include <termios.h>
|
||||
#include "bsdtrap.h"
|
||||
#ifdef __linux__
|
||||
#include <linux/sockios.h> /* FIOSETOWN */
|
||||
#endif
|
||||
|
||||
/* Structures and defines required by this file */
|
||||
|
||||
/* First the list of ioctls handled so far */
|
||||
#define TR_FIOCLEX 0x20006601 /* 0x2 is void */
|
||||
#define TR_TIOCGETP 0x40067408 /* 0x4 is a read */
|
||||
#define TR_TIOCSETP 0x40067409 /* 0x8 is a write */
|
||||
#define TR_TIOCSETN 0x8006740a
|
||||
#define TR_TIOCSETC 0x80067411
|
||||
#define TR_TIOCGETD 0x40027400
|
||||
#define TR_TIOCSETD 0x80027401
|
||||
#define TR_TIOCGETC 0x40067412
|
||||
#define TR_TIOCGLTC 0x40067474
|
||||
#define TR_TIOCSLTC 0x80067475
|
||||
#define TR_TIOCGWINSZ 0x40087468
|
||||
#define TR_TIOCSWINSZ 0x40027467
|
||||
#define TR_FIOSETOWN 0x8002667b
|
||||
#define TR_TIOCMGET 0x4002746a
|
||||
#define TR_TIOCGPGRP 0x40027477
|
||||
#define TR_TIOCSPGRP 0x80027476
|
||||
|
||||
/* sgtty structure */
|
||||
struct tr_sgttyb {
|
||||
int8_t sg_ispeed; /* input speed */
|
||||
int8_t sg_ospeed; /* output speed */
|
||||
int8_t sg_erase; /* erase character */
|
||||
int8_t sg_kill; /* kill character */
|
||||
int16_t sg_flags; /* mode flags */
|
||||
};
|
||||
|
||||
struct tr_tchars {
|
||||
int8_t t_intrc; /* interrupt */
|
||||
int8_t t_quitc; /* quit */
|
||||
int8_t t_startc; /* start output */
|
||||
int8_t t_stopc; /* stop output */
|
||||
int8_t t_eofc; /* end-of-file */
|
||||
int8_t t_brkc; /* input delimiter (like nl) */
|
||||
};
|
||||
|
||||
struct tr_ltchars {
|
||||
int8_t t_suspc; /* stop process signal */
|
||||
int8_t t_dsuspc; /* delayed stop process signal */
|
||||
int8_t t_rprntc; /* reprint line */
|
||||
int8_t t_flushc; /* flush output (toggles) */
|
||||
int8_t t_werasc; /* word erase */
|
||||
int8_t t_lnextc; /* literal next character */
|
||||
};
|
||||
|
||||
/*
|
||||
* Values for sg_flags
|
||||
*/
|
||||
#define TR_TANDEM 0x00000001 /* send stopc on out q full */
|
||||
#define TR_CBREAK 0x00000002 /* half-cooked mode */
|
||||
/* 0x4 (old LCASE) */
|
||||
#define TR_ECHO 0x00000008 /* echo input */
|
||||
#define TR_CRMOD 0x00000010 /* map \r to \r\n on output */
|
||||
#define TR_RAW 0x00000020 /* no i/o processing */
|
||||
#define TR_ODDP 0x00000040 /* get/send odd parity */
|
||||
#define TR_EVENP 0x00000080 /* get/send even parity */
|
||||
#define TR_ANYP 0x000000c0 /* get any parity/send none */
|
||||
/* 0x100 (old NLDELAY) */
|
||||
/* 0x200 */
|
||||
#define TR_XTABS 0x00000400 /* expand tabs on output */
|
||||
|
||||
/* Values for sg_ispeed and sg_ospeed */
|
||||
#define TR_B0 0
|
||||
#define TR_B50 1
|
||||
#define TR_B75 2
|
||||
#define TR_B110 3
|
||||
#define TR_B134 4
|
||||
#define TR_B150 5
|
||||
#define TR_B200 6
|
||||
#define TR_B300 7
|
||||
#define TR_B600 8
|
||||
#define TR_B1200 9
|
||||
#define TR_B1800 10
|
||||
#define TR_B2400 11
|
||||
#define TR_B4800 12
|
||||
#define TR_B9600 13
|
||||
#define TR_EXTA 14
|
||||
#define TR_EXTB 15
|
||||
|
||||
|
||||
|
||||
/* Variables, functions and the actual code of this file */
|
||||
|
||||
extern arglist *A; /* Pointer to various arguments on stack */
|
||||
|
||||
/* Forward prototypes */
|
||||
#ifdef __STDC__
|
||||
#define P(s) s
|
||||
#else
|
||||
#define P(s) ()
|
||||
#endif
|
||||
|
||||
static int trap_gettermios(u_int16_t fd, u_int32_t type, u_int16_t ucnt);
|
||||
static int trap_settermios(u_int16_t fd, u_int32_t type, u_int16_t ucnt);
|
||||
|
||||
#undef P
|
||||
|
||||
int trap_ioctl()
|
||||
{
|
||||
int i, val;
|
||||
long larg1;
|
||||
#ifdef DEBUG
|
||||
u_int8_t size, letter, value;
|
||||
#endif
|
||||
int16_t *shortptr;
|
||||
struct winsize *winptr;
|
||||
|
||||
larg1 = (sarg2 << 16) | uarg3;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (trap_debug) {
|
||||
fprintf(dbg_file, "val %d ",uarg1);
|
||||
switch (larg1) {
|
||||
case TR_FIOCLEX: fprintf(dbg_file, "FIOCLEX "); break;
|
||||
case TR_TIOCGETP: fprintf(dbg_file, "TIOCGETP "); break;
|
||||
case TR_TIOCSETP: fprintf(dbg_file, "TIOCSETP "); break;
|
||||
case TR_TIOCSETN: fprintf(dbg_file, "TIOCSETN "); break;
|
||||
case TR_TIOCSETC: fprintf(dbg_file, "TIOCSETC "); break;
|
||||
case TR_TIOCGETD: fprintf(dbg_file, "TIOCGETD "); break;
|
||||
case TR_TIOCSETD: fprintf(dbg_file, "TIOCSETD "); break;
|
||||
case TR_TIOCGETC: fprintf(dbg_file, "TIOCGETC "); break;
|
||||
case TR_TIOCGLTC: fprintf(dbg_file, "TIOCGLTC "); break;
|
||||
case TR_TIOCSLTC: fprintf(dbg_file, "TIOCSLTC "); break;
|
||||
case TR_TIOCGWINSZ: fprintf(dbg_file, "TIOCGWINSZ "); break;
|
||||
case TR_TIOCSWINSZ: fprintf(dbg_file, "TIOCSWINSZ "); break;
|
||||
case TR_FIOSETOWN: fprintf(dbg_file, "FIOSETOWN "); break;
|
||||
case TR_TIOCMGET: fprintf(dbg_file, "TIOCMGET "); break;
|
||||
case TR_TIOCGPGRP: fprintf(dbg_file, "TIOCGPGRP "); break;
|
||||
case TR_TIOCSPGRP: fprintf(dbg_file, "TIOCSPGRP "); break;
|
||||
default: fprintf(dbg_file, "0x%lx ", larg1);
|
||||
|
||||
value = larg1 & 0xff;
|
||||
letter = (larg1 >> 8) & 0xff;
|
||||
size = (larg1 >> 16) & 0xff;
|
||||
|
||||
fprintf(dbg_file, "('%c' ", letter);
|
||||
fprintf(dbg_file, "size %d ", size);
|
||||
fprintf(dbg_file, "val %d) ", value);
|
||||
}
|
||||
if (size) fprintf(dbg_file, "ptr %d ", uarg4);
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (larg1) {
|
||||
|
||||
case TR_TIOCGETP:
|
||||
case TR_TIOCGETC:
|
||||
case TR_TIOCGLTC:
|
||||
i = trap_gettermios(uarg1, larg1, uarg4); break;
|
||||
|
||||
case TR_TIOCSETP:
|
||||
case TR_TIOCSETN:
|
||||
case TR_TIOCSETC:
|
||||
case TR_TIOCSLTC:
|
||||
i = trap_settermios(uarg1, larg1, uarg4); break;
|
||||
|
||||
case TR_FIOCLEX:
|
||||
i = ioctl(uarg1, FIOCLEX, NULL); break;
|
||||
case TR_TIOCGETD:
|
||||
shortptr = (int16_t *) &dspace[uarg4];
|
||||
i = ioctl(uarg1, TIOCGETD, &val);
|
||||
if (i==0) *shortptr= val;
|
||||
break;
|
||||
case TR_TIOCGPGRP:
|
||||
shortptr = (int16_t *) &dspace[uarg4];
|
||||
i = ioctl(uarg1, TIOCGPGRP, &val);
|
||||
if (i==0) *shortptr= val;
|
||||
break;
|
||||
case TR_TIOCSPGRP:
|
||||
shortptr = (int16_t *) &dspace[uarg4];
|
||||
val= *shortptr; i = ioctl(uarg1, TIOCSPGRP, &val); break;
|
||||
case TR_TIOCSETD:
|
||||
shortptr = (int16_t *) &dspace[uarg4];
|
||||
val= *shortptr; i = ioctl(uarg1, TIOCSETD, &val); break;
|
||||
case TR_FIOSETOWN:
|
||||
shortptr = (int16_t *) &dspace[uarg4];
|
||||
val= *shortptr;
|
||||
/* Something wrong here, wonder why! */
|
||||
TrapDebug((dbg_file, "fd %d val %d ",uarg1,val));
|
||||
i = ioctl(uarg1, FIOSETOWN, &val); break;
|
||||
case TR_TIOCMGET:
|
||||
shortptr = (int16_t *) &dspace[uarg4];
|
||||
i = ioctl(uarg1, TIOCMGET, &val);
|
||||
if (i==0) *shortptr= val;
|
||||
break;
|
||||
|
||||
case TR_TIOCGWINSZ:
|
||||
/* 2.11BSD and POSIX winsize the same! */
|
||||
winptr = (struct winsize *) &dspace[uarg4];
|
||||
i= ioctl(uarg1, TIOCGWINSZ, winptr); break;
|
||||
case TR_TIOCSWINSZ:
|
||||
winptr = (struct winsize *) &dspace[uarg4];
|
||||
i= ioctl(uarg1, TIOCSWINSZ, winptr); break;
|
||||
|
||||
default:
|
||||
i = 0;
|
||||
}
|
||||
return (i);
|
||||
}
|
||||
|
||||
|
||||
/* Convert from termios to old sgttyb structure */
|
||||
static void to_sgttyb(struct tr_sgttyb * sgtb, struct termios * tios)
|
||||
{
|
||||
switch (tios->c_ispeed) {
|
||||
case B0: sgtb->sg_ispeed= TR_B0; break;
|
||||
case B50: sgtb->sg_ispeed= TR_B50; break;
|
||||
case B75: sgtb->sg_ispeed= TR_B75; break;
|
||||
case B110: sgtb->sg_ispeed= TR_B110; break;
|
||||
case B134: sgtb->sg_ispeed= TR_B134; break;
|
||||
case B150: sgtb->sg_ispeed= TR_B150; break;
|
||||
case B200: sgtb->sg_ispeed= TR_B200; break;
|
||||
case B300: sgtb->sg_ispeed= TR_B300; break;
|
||||
case B600: sgtb->sg_ispeed= TR_B600; break;
|
||||
case B1200: sgtb->sg_ispeed= TR_B1200; break;
|
||||
case B1800: sgtb->sg_ispeed= TR_B1800; break;
|
||||
case B2400: sgtb->sg_ispeed= TR_B2400; break;
|
||||
case B4800: sgtb->sg_ispeed= TR_B4800; break;
|
||||
case B9600: sgtb->sg_ispeed= TR_B9600; break;
|
||||
case B19200: sgtb->sg_ispeed= TR_EXTA; break;
|
||||
case B38400: sgtb->sg_ispeed= TR_EXTB; break;
|
||||
default: sgtb->sg_ispeed= TR_B0; break;
|
||||
}
|
||||
switch (tios->c_ospeed) {
|
||||
case B0: sgtb->sg_ospeed= TR_B0; break;
|
||||
case B50: sgtb->sg_ospeed= TR_B50; break;
|
||||
case B75: sgtb->sg_ospeed= TR_B75; break;
|
||||
case B110: sgtb->sg_ospeed= TR_B110; break;
|
||||
case B134: sgtb->sg_ospeed= TR_B134; break;
|
||||
case B150: sgtb->sg_ospeed= TR_B150; break;
|
||||
case B200: sgtb->sg_ospeed= TR_B200; break;
|
||||
case B300: sgtb->sg_ospeed= TR_B300; break;
|
||||
case B600: sgtb->sg_ospeed= TR_B600; break;
|
||||
case B1200: sgtb->sg_ospeed= TR_B1200; break;
|
||||
case B1800: sgtb->sg_ospeed= TR_B1800; break;
|
||||
case B2400: sgtb->sg_ospeed= TR_B2400; break;
|
||||
case B4800: sgtb->sg_ospeed= TR_B4800; break;
|
||||
case B9600: sgtb->sg_ospeed= TR_B9600; break;
|
||||
case B19200: sgtb->sg_ospeed= TR_EXTA; break;
|
||||
case B38400: sgtb->sg_ospeed= TR_EXTB; break;
|
||||
default: sgtb->sg_ospeed= TR_B0; break;
|
||||
}
|
||||
sgtb->sg_erase = tios->c_cc[VERASE];
|
||||
sgtb->sg_kill = tios->c_cc[VKILL];
|
||||
sgtb->sg_flags = 0;
|
||||
if (tios->c_oflag & OXTABS)
|
||||
sgtb->sg_flags |= TR_XTABS;
|
||||
if (tios->c_cflag & PARENB) {
|
||||
if (tios->c_cflag & PARODD)
|
||||
sgtb->sg_flags |= TR_ODDP;
|
||||
else
|
||||
sgtb->sg_flags |= TR_EVENP;
|
||||
} else
|
||||
sgtb->sg_flags |= TR_ANYP;
|
||||
if (tios->c_oflag & ONLCR)
|
||||
sgtb->sg_flags |= TR_CRMOD;
|
||||
if (tios->c_lflag & ECHO)
|
||||
sgtb->sg_flags |= TR_ECHO;
|
||||
if (!(tios->c_lflag & ICANON)) {
|
||||
if (!(tios->c_lflag & ECHO))
|
||||
sgtb->sg_flags |= TR_CBREAK;
|
||||
else
|
||||
sgtb->sg_flags |= TR_RAW;
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert from old sgttyb to termios structure */
|
||||
static void to_termios(struct tr_sgttyb * sgtb, struct termios * tios)
|
||||
{
|
||||
TrapDebug((dbg_file, "\n\tto_termios: sgtty flags are 0x%x ",
|
||||
sgtb->sg_flags));
|
||||
|
||||
switch (sgtb->sg_ispeed) {
|
||||
case TR_B0: tios->c_ispeed= B0; break;
|
||||
case TR_B50: tios->c_ispeed= B50; break;
|
||||
case TR_B75: tios->c_ispeed= B75; break;
|
||||
case TR_B110: tios->c_ispeed= B110; break;
|
||||
case TR_B134: tios->c_ispeed= B134; break;
|
||||
case TR_B150: tios->c_ispeed= B150; break;
|
||||
case TR_B200: tios->c_ispeed= B200; break;
|
||||
case TR_B300: tios->c_ispeed= B300; break;
|
||||
case TR_B600: tios->c_ispeed= B600; break;
|
||||
case TR_B1200: tios->c_ispeed= B1200; break;
|
||||
case TR_B1800: tios->c_ispeed= B1800; break;
|
||||
case TR_B2400: tios->c_ispeed= B2400; break;
|
||||
case TR_B4800: tios->c_ispeed= B4800; break;
|
||||
case TR_B9600: tios->c_ispeed= B9600; break;
|
||||
case TR_EXTA: tios->c_ispeed= B19200; break;
|
||||
case TR_EXTB: tios->c_ispeed= B38400; break;
|
||||
default: tios->c_ispeed= B0; break;
|
||||
}
|
||||
switch (sgtb->sg_ospeed) {
|
||||
case TR_B0: tios->c_ospeed= B0; break;
|
||||
case TR_B50: tios->c_ospeed= B50; break;
|
||||
case TR_B75: tios->c_ospeed= B75; break;
|
||||
case TR_B110: tios->c_ospeed= B110; break;
|
||||
case TR_B134: tios->c_ospeed= B134; break;
|
||||
case TR_B150: tios->c_ospeed= B150; break;
|
||||
case TR_B200: tios->c_ospeed= B200; break;
|
||||
case TR_B300: tios->c_ospeed= B300; break;
|
||||
case TR_B600: tios->c_ospeed= B600; break;
|
||||
case TR_B1200: tios->c_ospeed= B1200; break;
|
||||
case TR_B1800: tios->c_ospeed= B1800; break;
|
||||
case TR_B2400: tios->c_ospeed= B2400; break;
|
||||
case TR_B4800: tios->c_ospeed= B4800; break;
|
||||
case TR_B9600: tios->c_ospeed= B9600; break;
|
||||
case TR_EXTA: tios->c_ospeed= B19200; break;
|
||||
case TR_EXTB: tios->c_ospeed= B38400; break;
|
||||
default: tios->c_ospeed= B0; break;
|
||||
}
|
||||
tios->c_cc[VERASE] = sgtb->sg_erase;
|
||||
tios->c_cc[VKILL] = sgtb->sg_kill;
|
||||
|
||||
/* Initially turn off any flags we might set */
|
||||
tios->c_oflag &= ~(OXTABS|ONLCR);
|
||||
tios->c_cflag &= ~(PARENB|PARODD);
|
||||
tios->c_lflag &= ~(ECHO);
|
||||
|
||||
if (sgtb->sg_flags & TR_XTABS)
|
||||
tios->c_oflag |= OXTABS;
|
||||
if (sgtb->sg_flags & TR_ODDP) {
|
||||
tios->c_cflag |= PARENB;
|
||||
tios->c_cflag &= ~PARODD;
|
||||
}
|
||||
if (sgtb->sg_flags & TR_EVENP)
|
||||
tios->c_cflag |= PARENB | PARODD;
|
||||
if (sgtb->sg_flags & TR_ANYP)
|
||||
tios->c_cflag &= ~PARENB;
|
||||
if (sgtb->sg_flags & TR_CRMOD)
|
||||
tios->c_oflag |= ONLCR;
|
||||
if (sgtb->sg_flags & TR_ECHO)
|
||||
tios->c_lflag |= ECHO;
|
||||
|
||||
if (sgtb->sg_flags & TR_RAW) {
|
||||
tios->c_lflag &= ~(ECHO|ICANON|IEXTEN|ISIG|BRKINT|ICRNL|INPCK|ISTRIP|IXON);
|
||||
tios->c_cflag &= ~(CSIZE|PARENB);
|
||||
tios->c_cflag |= CS8;
|
||||
tios->c_oflag &= ~(OPOST);
|
||||
tios->c_cc[VMIN] = 1;
|
||||
tios->c_cc[VTIME] = 0;
|
||||
}
|
||||
|
||||
if (sgtb->sg_flags & TR_CBREAK) {
|
||||
TrapDebug((dbg_file, "\n\tto_termios: setting cbreak I hope "));
|
||||
tios->c_lflag &= ~(ECHO|ICANON);
|
||||
tios->c_cc[VMIN] = 1;
|
||||
tios->c_cc[VTIME] = 0;
|
||||
}
|
||||
TrapDebug((dbg_file, "\n\tto_termios: iflag is 0x%x", (int)tios->c_iflag));
|
||||
TrapDebug((dbg_file, "\n\tto_termios: oflag is 0x%x", (int)tios->c_oflag));
|
||||
TrapDebug((dbg_file, "\n\tto_termios: lflag is 0x%x ", (int)tios->c_lflag));
|
||||
}
|
||||
|
||||
/* Convert from termios to old [l]tchars structures */
|
||||
static void to_tchars(struct tr_tchars *tc, struct tr_ltchars *ltc,
|
||||
struct termios * tios)
|
||||
{
|
||||
if (tc) {
|
||||
tc->t_intrc=tios->c_cc[VINTR];
|
||||
tc->t_quitc=tios->c_cc[VQUIT];
|
||||
tc->t_startc=tios->c_cc[VSTART];
|
||||
tc->t_stopc=tios->c_cc[VSTOP];
|
||||
tc->t_eofc=tios->c_cc[VEOF];
|
||||
tc->t_brkc=tios->c_cc[VEOL];
|
||||
}
|
||||
if (ltc) {
|
||||
ltc->t_suspc=tios->c_cc[VSUSP];
|
||||
ltc->t_dsuspc=tios->c_cc[VDSUSP];
|
||||
ltc->t_rprntc=tios->c_cc[VREPRINT];
|
||||
ltc->t_flushc=tios->c_cc[VDISCARD];
|
||||
ltc->t_werasc=tios->c_cc[VERASE];
|
||||
ltc->t_lnextc=tios->c_cc[VLNEXT];
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert from old [l]tchars to termios structures */
|
||||
static void tc_to_tchars(struct tr_tchars *tc, struct tr_ltchars *ltc,
|
||||
struct termios * tios)
|
||||
{
|
||||
if (tc) {
|
||||
tios->c_cc[VINTR]= tc->t_intrc;
|
||||
tios->c_cc[VQUIT]= tc->t_quitc;
|
||||
tios->c_cc[VSTART]= tc->t_startc;
|
||||
tios->c_cc[VSTOP]= tc->t_stopc;
|
||||
tios->c_cc[VEOF]= tc->t_eofc;
|
||||
tios->c_cc[VEOL]= tc->t_brkc;
|
||||
}
|
||||
if (ltc) {
|
||||
tios->c_cc[VSUSP]= ltc->t_suspc;
|
||||
tios->c_cc[VDSUSP]= ltc->t_dsuspc;
|
||||
tios->c_cc[VREPRINT]= ltc->t_rprntc;
|
||||
tios->c_cc[VDISCARD]= ltc->t_flushc;
|
||||
tios->c_cc[VERASE]= ltc->t_werasc;
|
||||
tios->c_cc[VLNEXT]= ltc->t_lnextc;
|
||||
}
|
||||
}
|
||||
/* Handle most get ioctls that deal with termios stuff */
|
||||
static int trap_gettermios(u_int16_t fd, u_int32_t type, u_int16_t ucnt)
|
||||
{
|
||||
struct termios tios;
|
||||
struct tr_sgttyb *sgtb;
|
||||
struct tr_tchars *tc;
|
||||
struct tr_ltchars *ltc;
|
||||
int i;
|
||||
|
||||
if (ucnt == 0) return -1;
|
||||
i = tcgetattr(fd, &tios);
|
||||
if (i == -1) return i;
|
||||
CLR_CC_C();
|
||||
|
||||
switch (type) {
|
||||
case TR_TIOCGETP:
|
||||
sgtb = (struct tr_sgttyb *) &dspace[ucnt];
|
||||
to_sgttyb(sgtb, &tios); return 0;
|
||||
case TR_TIOCGETC:
|
||||
tc = (struct tr_tchars *) &dspace[ucnt];
|
||||
to_tchars(tc, NULL, &tios); return 0;
|
||||
case TR_TIOCGLTC:
|
||||
ltc = (struct tr_ltchars *) &dspace[ucnt];
|
||||
to_tchars(NULL, ltc, &tios); return 0;
|
||||
}
|
||||
/* Unknown type, should never get here */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Handle most set ioctls that deal with termios stuff */
|
||||
static int trap_settermios(u_int16_t fd, u_int32_t type, u_int16_t ucnt)
|
||||
{
|
||||
struct termios tios;
|
||||
struct tr_sgttyb *sgtb;
|
||||
struct tr_tchars *tc;
|
||||
struct tr_ltchars *ltc;
|
||||
int i;
|
||||
|
||||
if (ucnt == 0) return -1;
|
||||
i = tcgetattr(fd, &tios);
|
||||
if (i == -1) return i;
|
||||
switch (type) {
|
||||
case TR_TIOCSETP:
|
||||
sgtb = (struct tr_sgttyb *) & dspace[ucnt];
|
||||
to_termios(sgtb, &tios);
|
||||
i = tcsetattr(fd, TCSANOW, &tios);
|
||||
return (i);
|
||||
case TR_TIOCSETN:
|
||||
sgtb = (struct tr_sgttyb *) & dspace[ucnt];
|
||||
to_termios(sgtb, &tios);
|
||||
i = tcsetattr(fd, TCSADRAIN, &tios);
|
||||
return (i);
|
||||
case TR_TIOCSETC:
|
||||
tc = (struct tr_tchars *) & dspace[ucnt];
|
||||
tc_to_tchars(tc, NULL, &tios);
|
||||
i = tcsetattr(fd, TCSANOW, &tios);
|
||||
return (i);
|
||||
case TR_TIOCSLTC:
|
||||
ltc = (struct tr_ltchars *) & dspace[ucnt];
|
||||
tc_to_tchars(NULL, ltc, &tios);
|
||||
i = tcsetattr(fd, TCSANOW, &tios);
|
||||
return (i);
|
||||
}
|
||||
/* Unknown type, should never get here */
|
||||
return -1;
|
||||
}
|
||||
#endif /* EMU211 */
|
||||
232
tools/apout/bsd_signal.c
Normal file
232
tools/apout/bsd_signal.c
Normal file
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* Much of this file comes from 2.11BSD's /usr/include/signal.h and is
|
||||
* Copyright (c) 1986 Regents of the University of California.
|
||||
* All rights reserved. The Berkeley software License Agreement
|
||||
* specifies the terms and conditions for redistribution.
|
||||
*
|
||||
* Code to deal with 2.11BSD signals
|
||||
*/
|
||||
#include "defines.h"
|
||||
#include <signal.h>
|
||||
#include "bsdtrap.h"
|
||||
|
||||
|
||||
#define NBSDSIG 32
|
||||
|
||||
#define BSDSIGHUP 1 /* hangup */
|
||||
#define BSDSIGINT 2 /* interrupt */
|
||||
#define BSDSIGQUIT 3 /* quit */
|
||||
#define BSDSIGILL 4 /* illegal instruct (not reset when caught) */
|
||||
#define BSDSIGTRAP 5 /* trace trap (not reset when caught) */
|
||||
#define BSDSIGIOT 6 /* IOT instruction */
|
||||
#define BSDSIGEMT 7 /* EMT instruction */
|
||||
#define BSDSIGFPE 8 /* floating point exception */
|
||||
#define BSDSIGKILL 9 /* kill (cannot be caught or ignored) */
|
||||
#define BSDSIGBUS 10 /* bus error */
|
||||
#define BSDSIGSEGV 11 /* segmentation violation */
|
||||
#define BSDSIGSYS 12 /* bad argument to system call */
|
||||
#define BSDSIGPIPE 13 /* write on a pipe with no one to read it */
|
||||
#define BSDSIGALRM 14 /* alarm clock */
|
||||
#define BSDSIGTERM 15 /* software termination signal from kill */
|
||||
#define BSDSIGURG 16 /* urgent condition on IO channel */
|
||||
#define BSDSIGSTOP 17 /* sendable stop signal not from tty */
|
||||
#define BSDSIGTSTP 18 /* stop signal from tty */
|
||||
#define BSDSIGCONT 19 /* continue a stopped process */
|
||||
#define BSDSIGCHLD 20 /* to parent on child stop or exit */
|
||||
#define BSDSIGTTIN 21 /* to readers pgrp upon background tty read */
|
||||
#define BSDSIGTTOU 22 /* like TTIN for output if (tp->t_local<OSTOP) */
|
||||
#define BSDSIGIO 23 /* input/output possible signal */
|
||||
#define BSDSIGXCPU 24 /* exceeded CPU time limit */
|
||||
#define BSDSIGXFSZ 25 /* exceeded file size limit */
|
||||
#define BSDSIGVTALRM 26 /* virtual time alarm */
|
||||
#define BSDSIGPROF 27 /* profiling time alarm */
|
||||
#define BSDSIGWINCH 28 /* window size changes */
|
||||
#define BSDSIGUSR1 30 /* user defined signal 1 */
|
||||
#define BSDSIGUSR2 31 /* user defined signal 2 */
|
||||
#define bsdsigismember(set, signo) ((*(set) & (1L << ((signo) - 1))) != 0)
|
||||
|
||||
#define BSDSIG_ERR -1
|
||||
#define BSDSIG_DFL 0
|
||||
#define BSDSIG_IGN 1
|
||||
|
||||
/*
|
||||
* Signal vector "template" used in sigaction call.
|
||||
*/
|
||||
struct bsd_sigaction {
|
||||
int16_t sig_handler; /* signal handler */
|
||||
u_int32_t sa_mask; /* signal mask to apply */
|
||||
int16_t sa_flags; /* see signal options below */
|
||||
};
|
||||
|
||||
#define BSD_ONSTACK 0x0001 /* take signal on signal stack */
|
||||
#define BSD_RESTART 0x0002 /* restart system on signal return */
|
||||
#define BSD_DISABLE 0x0004 /* disable taking signals on alternate stack */
|
||||
#define BSD_NOCLDSTOP 0x0008 /* do not generate SIGCHLD on child stop */
|
||||
|
||||
|
||||
/* Translate 2.11BSD signal value to our value */
|
||||
|
||||
static int bsdsig[] = {
|
||||
0, SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGIOT, SIGEMT,
|
||||
SIGFPE, SIGKILL, SIGBUS, SIGSEGV, SIGSYS, SIGPIPE, SIGALRM,
|
||||
SIGTERM, SIGURG, SIGSTOP, SIGTSTP, SIGCONT, SIGCHLD, SIGTTIN,
|
||||
SIGTTOU, SIGIO, SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, SIGWINCH,
|
||||
SIGUSR1, SIGUSR2
|
||||
};
|
||||
|
||||
/* We keep a set of struct sigactions
|
||||
* for each 2.11BSD signal
|
||||
*/
|
||||
struct bsd_sigaction Sigact[NBSDSIG];
|
||||
|
||||
|
||||
/* Set all signals to their default value */
|
||||
void set_bsdsig_dfl(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0;i<NBSDSIG;i++) {
|
||||
if (bsdsig[i]) signal(bsdsig[i], SIG_DFL);
|
||||
Sigact[i].sig_handler= BSDSIG_DFL;
|
||||
Sigact[i].sa_mask= Sigact[i].sa_flags= 0;
|
||||
}
|
||||
}
|
||||
|
||||
int do_sigaction(int sig, int a, int oa)
|
||||
{
|
||||
int i;
|
||||
struct bsd_sigaction *act, *oact;
|
||||
struct sigaction ouraction;
|
||||
|
||||
if ((sig<0) || (sig >= NBSDSIG)) return(EINVAL);
|
||||
|
||||
if (oa) {
|
||||
oact= (struct bsd_sigaction *)&dspace[oa];
|
||||
memcpy(oact, &Sigact[sig], sizeof(struct bsd_sigaction));
|
||||
}
|
||||
|
||||
if (a) {
|
||||
act= (struct bsd_sigaction *)&dspace[a];
|
||||
|
||||
/* If required, map mask here */
|
||||
/* Currently, the assumption is a 1-1 match */
|
||||
sigemptyset(&(ouraction.sa_mask));
|
||||
for (i=1; i<NBSDSIG;i++) {
|
||||
if bsdsigismember(&(act->sa_mask), i)
|
||||
sigaddset(&(ouraction.sa_mask), i);
|
||||
}
|
||||
/* If required, map flags here */
|
||||
ouraction.sa_flags= act->sa_flags;
|
||||
ouraction.sa_handler= sigcatcher;
|
||||
}
|
||||
|
||||
i= sigaction(bsdsig[sig], &ouraction, NULL);
|
||||
if (i==-1) return(i);
|
||||
|
||||
/* Else save the new sigaction */
|
||||
act= (struct bsd_sigaction *)&dspace[a];
|
||||
memcpy(&Sigact[sig], act, sizeof(struct bsd_sigaction));
|
||||
return(i);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* For now, the rest commented out. One day I might
|
||||
* get around to implementing 2.11BSD signals properly
|
||||
*/
|
||||
|
||||
#if 0
|
||||
int (*signal())();
|
||||
|
||||
typedef unsigned long sigset_t;
|
||||
|
||||
|
||||
/*
|
||||
* Flags for sigprocmask:
|
||||
*/
|
||||
#define BSDSIG_BLOCK 1 /* block specified signal set */
|
||||
#define BSDSIG_UNBLOCK 2 /* unblock specified signal set */
|
||||
#define BSDSIG_SETMASK 3 /* set specified signal set */
|
||||
|
||||
typedef int (*sig_t)(); /* type of signal function */
|
||||
|
||||
/*
|
||||
* Structure used in sigaltstack call.
|
||||
*/
|
||||
struct sigaltstack {
|
||||
char *ss_base; /* signal stack base */
|
||||
int ss_size; /* signal stack length */
|
||||
int ss_flags; /* SA_DISABLE and/or SA_ONSTACK */
|
||||
};
|
||||
#define MINBSDSIGSTKSZ 128 /* minimum allowable stack */
|
||||
#define BSDSIGSTKSZ (MINBSDSIGSTKSZ + 384) /* recommended stack size */
|
||||
|
||||
/*
|
||||
* 4.3 compatibility:
|
||||
* Signal vector "template" used in sigvec call.
|
||||
*/
|
||||
struct sigvec {
|
||||
int (*sv_handler)(); /* signal handler */
|
||||
long sv_mask; /* signal mask to apply */
|
||||
int sv_flags; /* see signal options below */
|
||||
};
|
||||
#define SV_ONSTACK SA_ONSTACK /* take signal on signal stack */
|
||||
#define SV_INTERRUPT SA_RESTART /* same bit, opposite sense */
|
||||
#define sv_onstack sv_flags /* isn't compatibility wonderful! */
|
||||
|
||||
/*
|
||||
* 4.3 compatibility:
|
||||
* Structure used in sigstack call.
|
||||
*/
|
||||
struct sigstack {
|
||||
char *ss_sp; /* signal stack pointer */
|
||||
int ss_onstack; /* current status */
|
||||
};
|
||||
|
||||
/*
|
||||
* Information pushed on stack when a signal is delivered.
|
||||
* This is used by the kernel to restore state following
|
||||
* execution of the signal handler. It is also made available
|
||||
* to the handler to allow it to properly restore state if
|
||||
* a non-standard exit is performed.
|
||||
*/
|
||||
struct sigcontext {
|
||||
int sc_onstack; /* sigstack state to restore */
|
||||
long sc_mask; /* signal mask to restore */
|
||||
int sc_sp; /* sp to restore */
|
||||
int sc_fp; /* fp to restore */
|
||||
int sc_r1; /* r1 to restore */
|
||||
int sc_r0; /* r0 to restore */
|
||||
int sc_pc; /* pc to restore */
|
||||
int sc_ps; /* psl to restore */
|
||||
int sc_ovno /* overlay to restore */
|
||||
};
|
||||
|
||||
/*
|
||||
* Macro for converting signal number to a mask suitable for
|
||||
* sigblock().
|
||||
*/
|
||||
#define sigmask(m) (1L << ((m)-1))
|
||||
#define sigaddset(set, signo) (*(set) |= 1L << ((signo) - 1), 0)
|
||||
#define sigdelset(set, signo) (*(set) &= ~(1L << ((signo) - 1)), 0)
|
||||
#define sigemptyset(set) (*(set) = (sigset_t)0, (int)0)
|
||||
#define sigfillset(set) (*(set) = ~(sigset_t)0, (int)0)
|
||||
#define sigismember(set, signo) ((*(set) & (1L << ((signo) - 1))) != 0)
|
||||
|
||||
#endif /* 0 */
|
||||
877
tools/apout/bsdtrap.c
Normal file
877
tools/apout/bsdtrap.c
Normal file
@@ -0,0 +1,877 @@
|
||||
/* bsdtrap.c - Deal with 2.11BSD trap instructions.
|
||||
*
|
||||
* $Revision: 1.65 $
|
||||
* $Date: 2002/06/10 11:43:24 $
|
||||
*/
|
||||
#ifdef EMU211
|
||||
|
||||
/* NOTE NOTE NOTE NOTE
|
||||
* Grep for the word DONE in this file to see the implemented syscalls.
|
||||
*/
|
||||
|
||||
#define BSDTRAP_NAME
|
||||
#include "defines.h"
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/wait.h>
|
||||
#include <signal.h>
|
||||
#include <utime.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/uio.h>
|
||||
#include "bsdtrap.h"
|
||||
#ifdef __linux__
|
||||
#include <grp.h> /* setgroups() */
|
||||
#endif
|
||||
|
||||
#define MAX_BLKSIZE 1024 /* Maximum block size from stat/fstat */
|
||||
|
||||
#undef STREAM_BUFFERING /* This works, but doesn't seem to give */
|
||||
/* any speed improvement */
|
||||
|
||||
arglist *A; /* Pointer to various arguments on stack */
|
||||
|
||||
|
||||
/* Forward prototypes */
|
||||
#ifdef __STDC__
|
||||
#define P(s) s
|
||||
#else
|
||||
#define P(s) ()
|
||||
#endif
|
||||
static int trap_execve P((int));
|
||||
static int bsdopen_dir P((char *name));
|
||||
#ifdef NEED_MAP_FCNTL
|
||||
static int16_t map_fcntl P((int16_t f));
|
||||
#endif
|
||||
#undef P
|
||||
|
||||
void
|
||||
bsdtrap()
|
||||
{
|
||||
int i, j, len, pid, pfd[2];
|
||||
char *buf, *buf2;
|
||||
int16_t *shortptr;
|
||||
long larg1;
|
||||
char *fmode; /* used with fdopen only */
|
||||
struct stat stbuf; /* used in STAT */
|
||||
struct tr_stat *tr_stbuf; /* used in STAT */
|
||||
struct tr_timeval *tr_del, *tr_oldel; /* used in ADJTIME */
|
||||
struct timeval del, oldel; /* used in ADJTIME */
|
||||
struct timeval utv[2]; /* used in UTIMES */
|
||||
struct tr_timezone *tr_zone; /* used in GETTIMEOFDAY */
|
||||
struct timezone zone; /* used in GETTIMEOFDAY */
|
||||
struct tr_itimerval *tr_tval, *tr_oltval; /* used in itimer calls */
|
||||
struct itimerval tval, oltval; /* used in itimer calls */
|
||||
struct tr_sockaddr *tr_sock; /* used in socket calls */
|
||||
struct sockaddr sock; /* used in socket calls */
|
||||
gid_t *gidset; /* used in GETGROUPS */
|
||||
struct tr_rlimit *tr_rlp; /* used in rlimit calls */
|
||||
struct rlimit rlp; /* used in rlimit calls */
|
||||
struct tr_rusage *tr_use; /* used in getrusage */
|
||||
struct rusage use; /* used in getrusage */
|
||||
struct iovec *ivec; /* used in writev, readv */
|
||||
struct tr_iovec *trivec; /* used in writev, readv */
|
||||
|
||||
TrapDebug((dbg_file, "pid %d %s: ", (int)getpid(),bsdtrap_name[ir & 0xff]));
|
||||
|
||||
A= (arglist *)&dspace[(regs[SP]+2)];
|
||||
|
||||
i=errno=0;
|
||||
switch (ir & 0xff) {
|
||||
case S_INDIR:
|
||||
(void)printf("Does 2.11BSD use INDIR? I don't think so\n");
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
case S_QUOTA: /* DONE - for now */
|
||||
case S_SETQUOTA: /* DONE - for now */
|
||||
i=-1; errno=EINVAL; break;
|
||||
|
||||
/* These syscalls are not implemented, and */
|
||||
/* always return EPERM to the caller */
|
||||
case S_PTRACE: /* DONE - bad syscall */
|
||||
case S_MOUNT: /* DONE - bad syscall */
|
||||
case S_UMOUNT: /* DONE - bad syscall */
|
||||
case S_PROFIL: /* DONE - bad syscall */
|
||||
case S_NOSYS147: /* DONE - bad syscall */
|
||||
case S_SYSCTL:
|
||||
i=-1; errno=EPERM; break;
|
||||
/* These syscalls are ignored, and */
|
||||
/* always return C=0 to the caller */
|
||||
case S_OLDLOCK: /* DONE - ok syscall */
|
||||
case S_OLDPHYS: /* DONE - ok syscall */
|
||||
case S_FSTATFS: /* DONE - ok syscall */
|
||||
case S_SIGPROCMASK: /* DONE - ok syscall */
|
||||
case S_SIGRETURN: /* DONE - ok syscall */
|
||||
case S_SIGALTSTACK: /* DONE - ok syscall */
|
||||
case S_VHANGUP: /* DONE - ok syscall */
|
||||
i=0; break;
|
||||
case S_SIGACTION: /* DONE */
|
||||
#define NO_SIGNALS_YET
|
||||
#ifdef NO_SIGNALS_YET
|
||||
i=0;
|
||||
#else
|
||||
i= do_sigaction(uarg1, uarg2, uarg3);
|
||||
#endif
|
||||
break;
|
||||
case S_IOCTL: /* DONE a bit */
|
||||
i=trap_ioctl(); break;
|
||||
case S_SBRK: /* DONE */
|
||||
if (uarg1<regs[SP]) {
|
||||
i=0;
|
||||
TrapDebug((dbg_file, "set break to %d ", uarg1));
|
||||
} else {
|
||||
i=-1; errno=ENOMEM;
|
||||
TrapDebug((dbg_file, "break %d > SP %d", uarg1, regs[SP]));
|
||||
}
|
||||
break;
|
||||
case S_SYNC: /* DONE */
|
||||
sync(); i=0; break;
|
||||
case S_FSYNC: /* DONE */
|
||||
i= fsync(sarg1); break;
|
||||
case S_GETDTABLESIZE: /* DONE */
|
||||
i= getdtablesize(); break;
|
||||
case S_EXIT: /* DONE */
|
||||
#ifdef DEBUG
|
||||
TrapDebug((dbg_file, "val %d\n",sarg1)); fflush(dbg_file);
|
||||
#endif
|
||||
exit(sarg1);
|
||||
case S_DUP: /* DONE */
|
||||
TrapDebug((dbg_file, "on %d ",sarg1));
|
||||
i = dup(sarg1);
|
||||
#ifdef STREAM_BUFFERING
|
||||
if ((i!=-1) && ValidFD(sarg1) && stream[sarg1]) {
|
||||
fmode= streammode[sarg1];
|
||||
stream[i] = fdopen(i, fmode);
|
||||
streammode[i]=fmode;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case S_DUP2: /* DONE */
|
||||
TrapDebug((dbg_file, "on %d %d ",sarg1,sarg2));
|
||||
i = dup2(sarg1,sarg2);
|
||||
#ifdef STREAM_BUFFERING
|
||||
if ((i!=-1) && ValidFD(sarg2) && ValidFD(sarg1) && stream[sarg1]) {
|
||||
fmode= streammode[sarg1];
|
||||
stream[sarg2] = fdopen(sarg2, fmode);
|
||||
streammode[sarg2]=fmode;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case S_REBOOT: /* DONE */
|
||||
(void)Reboot(sarg1); break;
|
||||
case S_UMASK: /* DONE */
|
||||
i = umask((mode_t)sarg1); break;
|
||||
case S_GETPAGESIZE: /* DONE */
|
||||
i = getpagesize(); break;
|
||||
case S_GETHOSTNAME: /* DONE */
|
||||
buf = (char *)&dspace[uarg1];
|
||||
i= gethostname(buf,sarg2); break;
|
||||
case S_SETHOSTNAME: /* DONE */
|
||||
buf = (char *)&dspace[uarg1];
|
||||
sethostname(buf,sarg2); break;
|
||||
case S_LSEEK: /* DONE */
|
||||
larg1 = (sarg2 << 16) | uarg3;
|
||||
#ifdef STREAM_BUFFERING
|
||||
if (ValidFD(sarg1) && stream[sarg1]) {
|
||||
i = fseek(stream[sarg1], larg1, sarg4);
|
||||
if (i == 0) i = ftell(stream[sarg1]);
|
||||
} else
|
||||
#endif
|
||||
i = lseek(sarg1, larg1, sarg4);
|
||||
if (i == -1) break;
|
||||
else {
|
||||
regs[1] = i & 0xffff;
|
||||
i= (i >> 16) & 0xffff;
|
||||
break;
|
||||
}
|
||||
case S_READ: /* DONE */
|
||||
TrapDebug((dbg_file, "%d bytes on %d ",uarg3,sarg1));
|
||||
buf = &dspace[uarg2];
|
||||
#ifdef STREAM_BUFFERING
|
||||
if (ValidFD(sarg1) && stream[sarg1])
|
||||
i = fread(buf, 1, uarg3, stream[sarg1]);
|
||||
else
|
||||
#endif
|
||||
i = read(sarg1, buf, uarg3); break;
|
||||
case S_LINK: /* DONE */
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
buf2 = xlate_filename(&dspace[uarg2]);
|
||||
i = link(buf, buf2); break;
|
||||
case S_SYMLINK: /* DONE */
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
buf2 = xlate_filename(&dspace[uarg2]);
|
||||
i = symlink(buf, buf2); break;
|
||||
case S_RENAME: /* DONE */
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
buf2 = xlate_filename(&dspace[uarg2]);
|
||||
i = rename(buf, buf2); break;
|
||||
case S_READLINK: /* DONE */
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
i = readlink(buf, &dspace[uarg2], sarg3); break;
|
||||
case S_ACCESS: /* DONE */
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
i = access(buf, sarg2); break;
|
||||
case S_MKDIR: /* DONE */
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
i = mkdir(buf, sarg2); break;
|
||||
case S_RMDIR: /* DONE */
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
i = rmdir(buf); break;
|
||||
case S_ACCT: /* DONE */
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
i = acct(buf); break;
|
||||
case S_WRITEV: /* DONE */
|
||||
case S_READV: /* DONE */
|
||||
ivec= (struct iovec *)malloc(uarg3 * sizeof(struct iovec));
|
||||
if (ivec==NULL) { i=-1; errno=EINVAL; break; }
|
||||
trivec= (struct tr_iovec *)&dspace[uarg2];
|
||||
|
||||
for (j=0; j<uarg3; j++) {
|
||||
ivec[j].iov_len= trivec[j].iov_len;
|
||||
ivec[j].iov_base= (char *)&dspace[trivec[j].iov_base];
|
||||
}
|
||||
if ((ir & 0xff)==S_READV) i= readv(sarg1, ivec, uarg3);
|
||||
else i= writev(sarg1, ivec, uarg3);
|
||||
free(ivec);
|
||||
break;
|
||||
case S_WRITE: /* DONE */
|
||||
buf = &dspace[uarg2];
|
||||
TrapDebug((dbg_file, "%d bytes on %d ",uarg3,sarg1));
|
||||
#ifdef STREAM_BUFFERING
|
||||
if (ValidFD(sarg1) && stream[sarg1])
|
||||
i = fwrite(buf, 1, uarg3, stream[sarg1]);
|
||||
else
|
||||
#endif
|
||||
i = write(sarg1, buf, uarg3); break;
|
||||
case S_CLOSE: /* DONE */
|
||||
#ifdef DEBUG
|
||||
TrapDebug((dbg_file, "on %d ",sarg1));
|
||||
if ((dbg_file!=NULL) && (sarg1==fileno(dbg_file))) {
|
||||
i=0; break; /* Don't close our debug file! */
|
||||
}
|
||||
#endif
|
||||
#ifdef STREAM_BUFFERING
|
||||
if (ValidFD(sarg1) && stream[sarg1]) {
|
||||
i = fclose(stream[sarg1]);
|
||||
stream[sarg1] = NULL;
|
||||
} else
|
||||
#endif
|
||||
i = close(sarg1); break;
|
||||
case S_FCNTL:
|
||||
TrapDebug((dbg_file, "on %d %d %d ",sarg1,sarg2, sarg3));
|
||||
i = fcntl(sarg1,sarg2,sarg3); break;
|
||||
case S_FLOCK:
|
||||
i = flock(sarg1,sarg2); break;
|
||||
case S_LSTAT: /* DONE */
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
tr_stbuf = (struct tr_stat *) &dspace[uarg2];
|
||||
i = lstat(buf, &stbuf);
|
||||
TrapDebug((dbg_file, "on %s ",buf));
|
||||
goto dostat;
|
||||
case S_STAT: /* DONE */
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
tr_stbuf = (struct tr_stat *) &dspace[uarg2];
|
||||
i = stat(buf, &stbuf);
|
||||
TrapDebug((dbg_file, "on %s ",buf));
|
||||
goto dostat;
|
||||
case S_FSTAT: /* DONE */
|
||||
tr_stbuf = (struct tr_stat *) &dspace[uarg2];
|
||||
i = fstat(uarg1, &stbuf);
|
||||
TrapDebug((dbg_file, "on fd %d ",uarg1));
|
||||
|
||||
dostat:
|
||||
if (i == -1) break;
|
||||
else {
|
||||
/* The following stops blksize equalling 64K,
|
||||
* which becomes 0 in a 16-bit int. This then
|
||||
* causes 2.11BSD flsbuf() to malloc(0), which
|
||||
* then causes malloc to go crazy - wkt.
|
||||
*/
|
||||
if (stbuf.st_blksize>MAX_BLKSIZE) stbuf.st_blksize=MAX_BLKSIZE;
|
||||
|
||||
tr_stbuf->st_dev = stbuf.st_dev;
|
||||
tr_stbuf->st_ino = stbuf.st_ino;
|
||||
tr_stbuf->st_mode = stbuf.st_mode;
|
||||
tr_stbuf->st_nlink = stbuf.st_nlink;
|
||||
tr_stbuf->st_uid = stbuf.st_uid;
|
||||
tr_stbuf->st_gid = stbuf.st_gid;
|
||||
tr_stbuf->st_rdev = stbuf.st_rdev;
|
||||
#ifndef NO_STFLAGS
|
||||
tr_stbuf->st_flags = stbuf.st_flags;
|
||||
#endif
|
||||
copylong(tr_stbuf->st_size, stbuf.st_size);
|
||||
copylong(tr_stbuf->st_atim, stbuf.st_atime);
|
||||
copylong(tr_stbuf->st_mtim, stbuf.st_mtime);
|
||||
copylong(tr_stbuf->st_ctim, stbuf.st_ctime);
|
||||
copylong(tr_stbuf->st_blksize, stbuf.st_blksize);
|
||||
larg1= stbuf.st_blocks; copylong(tr_stbuf->st_blocks, larg1);
|
||||
}
|
||||
break;
|
||||
case S_UTIMES: /* DONE */
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
tr_del = (struct tr_timeval *) &dspace[uarg2];
|
||||
tr_oldel = (struct tr_timeval *) &dspace[uarg4];
|
||||
i= utimes(buf, utv);
|
||||
if (i==-1) break;
|
||||
copylong(tr_del->tv_sec, utv[0].tv_sec);
|
||||
copylong(tr_del->tv_usec, utv[0].tv_usec);
|
||||
copylong(tr_oldel->tv_sec, utv[1].tv_sec);
|
||||
copylong(tr_oldel->tv_usec, utv[1].tv_usec);
|
||||
break;
|
||||
case S_ADJTIME: /* DONE */
|
||||
tr_del = (struct tr_timeval *) &dspace[uarg1];
|
||||
/* Convert tr_del to del */
|
||||
copylong(del.tv_sec, tr_del->tv_sec);
|
||||
copylong(del.tv_usec, tr_del->tv_usec);
|
||||
i= adjtime(&del, &oldel);
|
||||
|
||||
if (uarg2) {
|
||||
tr_oldel = (struct tr_timeval *) &dspace[uarg2];
|
||||
copylong(tr_oldel->tv_sec, oldel.tv_sec);
|
||||
copylong(tr_oldel->tv_usec, oldel.tv_usec);
|
||||
}
|
||||
break;
|
||||
case S_GETTIMEOFDAY: /* DONE */
|
||||
tr_del = (struct tr_timeval *) &dspace[uarg1];
|
||||
tr_zone = (struct tr_timezone *) &dspace[uarg2];
|
||||
i= gettimeofday(&del, &zone);
|
||||
copylong(tr_del->tv_sec, del.tv_sec);
|
||||
copylong(tr_del->tv_usec, del.tv_usec);
|
||||
tr_zone->tz_minuteswest= zone.tz_minuteswest;
|
||||
tr_zone->tz_dsttime= zone.tz_dsttime;
|
||||
break;
|
||||
case S_SETTIMEOFDAY: /* DONE */
|
||||
tr_del = (struct tr_timeval *) &dspace[uarg1];
|
||||
tr_zone = (struct tr_timezone *) &dspace[uarg2];
|
||||
copylong(del.tv_sec, tr_del->tv_sec);
|
||||
copylong(del.tv_usec, tr_del->tv_usec);
|
||||
zone.tz_minuteswest= tr_zone->tz_minuteswest;
|
||||
zone.tz_dsttime= tr_zone->tz_dsttime;
|
||||
i= settimeofday(&del, &zone);
|
||||
break;
|
||||
case S_GETITIMER: /* DONE */
|
||||
tr_tval = (struct tr_itimerval *) &dspace[uarg2];
|
||||
i= getitimer(sarg1, &tval);
|
||||
copylong(tr_tval->it_interval.tv_sec, tval.it_interval.tv_sec);
|
||||
copylong(tr_tval->it_interval.tv_usec, tval.it_interval.tv_usec);
|
||||
copylong(tr_tval->it_value.tv_sec, tval.it_value.tv_sec);
|
||||
copylong(tr_tval->it_value.tv_usec, tval.it_value.tv_usec);
|
||||
break;
|
||||
case S_SETITIMER: /* DONE */
|
||||
tr_tval = (struct tr_itimerval *) &dspace[uarg2];
|
||||
tr_oltval = (struct tr_itimerval *) &dspace[uarg2];
|
||||
copylong(tval.it_interval.tv_sec, tr_tval->it_interval.tv_sec);
|
||||
copylong(tval.it_interval.tv_usec, tr_tval->it_interval.tv_usec);
|
||||
copylong(tval.it_value.tv_sec, tr_tval->it_value.tv_sec);
|
||||
copylong(tval.it_value.tv_usec, tr_tval->it_value.tv_usec);
|
||||
i= setitimer(sarg1, &tval, &oltval);
|
||||
if (i == -1) break;
|
||||
copylong(tr_oltval->it_interval.tv_sec, oltval.it_interval.tv_sec);
|
||||
copylong(tr_oltval->it_interval.tv_usec, oltval.it_interval.tv_usec);
|
||||
copylong(tr_oltval->it_value.tv_sec, oltval.it_value.tv_sec);
|
||||
copylong(tr_oltval->it_value.tv_usec, oltval.it_value.tv_usec);
|
||||
break;
|
||||
case S_UNLINK: /* DONE */
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
i = unlink(buf); break;
|
||||
case S_OPEN: /* DONE */
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
|
||||
i = stat(buf, &stbuf); /* If file is a directory */
|
||||
if (i == 0 && (stbuf.st_mode & S_IFDIR)) {
|
||||
i = bsdopen_dir(buf);
|
||||
fmode = "w+";
|
||||
TrapDebug((dbg_file, "(dir) on %s ",buf));
|
||||
} else {
|
||||
#ifdef NEED_MAP_FCNTL
|
||||
sarg2= map_fcntl(sarg2);
|
||||
#endif
|
||||
switch (sarg2 & O_ACCMODE) {
|
||||
case O_RDONLY: fmode = "r"; break;
|
||||
case O_WRONLY: fmode = "w"; break;
|
||||
default: fmode = "w+"; break;
|
||||
}
|
||||
i = open(buf, sarg2, sarg3);
|
||||
TrapDebug((dbg_file, "on %s ",buf));
|
||||
TrapDebug((dbg_file, "sarg2 is %d, sarg3 is 0x%x ",sarg2,sarg3));
|
||||
}
|
||||
#ifdef STREAM_BUFFERING
|
||||
if (i==-1) break;
|
||||
/* Now get its stream pointer if possible */
|
||||
/* Can someone explain why fdopen doesn't work for O_RDWR? */
|
||||
# if 0
|
||||
if (ValidFD(i) && !isatty(i) && (sarg2!=O_RDWR)) {
|
||||
stream[i] = fdopen(i, fmode); streammode[i]=fmode;
|
||||
}
|
||||
# endif
|
||||
stream[i] = fdopen(i, fmode); streammode[i]=fmode;
|
||||
#endif
|
||||
break;
|
||||
case S_MKNOD: /* DONE */
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
i = mknod(buf, sarg2, sarg3); break;
|
||||
case S_CHMOD: /* DONE */
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
i = chmod(buf, sarg2); break;
|
||||
case S_FCHMOD: /* DONE */
|
||||
i = fchmod(sarg1, sarg2); break;
|
||||
case S_TRUNCATE: /* DONE */
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
larg1 = (sarg2 << 16) | uarg3;
|
||||
i = truncate(buf, larg1); break;
|
||||
case S_FTRUNCATE: /* DONE */
|
||||
larg1 = (sarg2 << 16) | uarg3;
|
||||
i = ftruncate(sarg1, larg1); break;
|
||||
case S_KILL: /* DONE */
|
||||
i = kill(sarg1, sarg2); break;
|
||||
case S_KILLPG: /* DONE */
|
||||
i = killpg(sarg1, sarg2); break;
|
||||
case S_CHOWN: /* DONE */
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
i = chown(buf, sarg2, sarg3); break;
|
||||
case S_PIPE: /* DONE */
|
||||
i = pipe(pfd);
|
||||
#ifdef STREAM_BUFFERING
|
||||
if (ValidFD(pfd[0])) {
|
||||
stream[pfd[0]] = fdopen(pfd[0], "r");
|
||||
streammode[pfd[0]]= "r";
|
||||
}
|
||||
if (ValidFD(pfd[1])) {
|
||||
stream[pfd[1]] = fdopen(pfd[1], "w");
|
||||
streammode[pfd[1]]= "w";
|
||||
}
|
||||
#endif
|
||||
if (i == -1) break;
|
||||
i = pfd[0]; regs[1] = pfd[1]; break;
|
||||
case S_CHROOT: /* DONE */
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
if (buf == NULL) {
|
||||
errno=ENOENT; i=-1; break;
|
||||
}
|
||||
set_apout_root(buf);
|
||||
i=0; break;
|
||||
case S_CHDIR: /* DONE */
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
i = chdir(buf); break;
|
||||
case S_FCHDIR: /* DONE */
|
||||
i = fchdir(sarg1); break;
|
||||
|
||||
#ifndef NO_CHFLAGS
|
||||
case S_CHFLAGS: /* DONE */
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
i = chflags(buf,uarg2); break;
|
||||
case S_FCHFLAGS: /* DONE */
|
||||
i = fchflags(sarg1,uarg2); break;
|
||||
#endif
|
||||
|
||||
case S_CREAT: /* DONE */
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
i = creat(buf, sarg2);
|
||||
#ifdef STREAM_BUFFERING
|
||||
if (ValidFD(i)) {
|
||||
stream[i] = fdopen(i, "w");
|
||||
streammode[i]= "w";
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case S_EXECVE: /* DONE, I think */
|
||||
i= trap_execve(1); break;
|
||||
case S_EXECV: /* Not sure here */
|
||||
i= trap_execve(0); break;
|
||||
case S_WAIT: /* Not sure here */
|
||||
i = wait(&pid);
|
||||
if (i == -1) break;
|
||||
regs[1] = pid;
|
||||
break;
|
||||
case S_WAIT4: /* Definitely incomplete */
|
||||
TrapDebug((dbg_file, "on pid %d options %d ",sarg1,uarg3));
|
||||
if (uarg4) TrapDebug((dbg_file, " rusage on!!! "));
|
||||
shortptr = (int16_t *)&dspace[uarg2];
|
||||
i= wait4(sarg1, &j, uarg3, 0);
|
||||
*shortptr= j;
|
||||
break;
|
||||
case S_FORK: /* DONE */
|
||||
case S_VFORK: /* DONE */
|
||||
i = fork();
|
||||
if (i!=0) { regs[PC]+=2; } /* Took ages to find this! */
|
||||
else ov_changes=0;
|
||||
break;
|
||||
case S_GETHOSTID: /* DONE */
|
||||
i = gethostid();
|
||||
regs[1] = i & 0xffff;
|
||||
i= (i >> 16) & 0xffff;
|
||||
break;
|
||||
case S_SETHOSTID: /* DONE */
|
||||
larg1 = (sarg2 << 16) | uarg3;
|
||||
sethostid(larg1); i=0; break;
|
||||
case S_GETUID: /* DONE */
|
||||
i = getuid(); break;
|
||||
case S_SETUID: /* DONE */
|
||||
i = setuid(uarg1); break;
|
||||
case S_GETEUID: /* DONE */
|
||||
i = geteuid(); break;
|
||||
case S_GETPID: /* DONE */
|
||||
i = getpid(); break;
|
||||
case S_GETPPID: /* DONE */
|
||||
i = getppid(); break;
|
||||
case S_GETGID: /* DONE */
|
||||
i = getgid(); break;
|
||||
case S_GETEGID: /* DONE */
|
||||
i = getegid(); break;
|
||||
#ifndef NO_GETPGID
|
||||
case S_GETPGRP: /* DONE */
|
||||
i = getpgid(sarg1); break;
|
||||
#endif
|
||||
case S_SETPGRP: /* DONE */
|
||||
i = setpgid(sarg1,sarg2); break;
|
||||
case S_SETREGID: /* DONE */
|
||||
i = setregid(sarg1,sarg2); break;
|
||||
case S_SETREUID: /* DONE */
|
||||
i = setreuid(sarg1,sarg2); break;
|
||||
case S_GETPRIORITY: /* DONE */
|
||||
i = getpriority(sarg1,sarg2); break;
|
||||
case S_SETPRIORITY: /* DONE */
|
||||
i = setpriority(sarg1,sarg2,sarg3); break;
|
||||
case S_LISTEN: /* DONE */
|
||||
i = listen(sarg1,sarg2); break;
|
||||
case S_SHUTDOWN: /* DONE */
|
||||
i = shutdown(sarg1,sarg2); break;
|
||||
case S_SOCKET: /* DONE */
|
||||
i = socket(sarg1,sarg2,sarg3); break;
|
||||
case S_SOCKETPAIR: /* DONE */
|
||||
i = socketpair(sarg1,sarg2,sarg3, pfd); break;
|
||||
shortptr= (int16_t *)&dspace[uarg4];
|
||||
*shortptr= pfd[0]; shortptr+=2;
|
||||
*shortptr= pfd[1];
|
||||
break;
|
||||
case S_RECV: /* DONE */
|
||||
buf = &dspace[uarg2];
|
||||
i = recv(sarg1, buf, sarg3, sarg4); break;
|
||||
case S_SEND: /* DONE */
|
||||
buf = &dspace[uarg2];
|
||||
i = send(sarg1, buf, sarg3, sarg4); break;
|
||||
case S_ACCEPT: /* DONE */
|
||||
tr_sock= (struct tr_sockaddr *)&dspace[uarg2];
|
||||
sock.sa_family= tr_sock->sa_family;
|
||||
ll_word(uarg3, len);
|
||||
#ifndef __linux__
|
||||
sock.sa_len=len;
|
||||
#endif
|
||||
memcpy(sock.sa_data, tr_sock->sa_data, len);
|
||||
i= accept(sarg1, &sock, &len);
|
||||
if (i != -1) {
|
||||
sl_word(uarg3,len);
|
||||
memcpy(tr_sock->sa_data, sock.sa_data, len);
|
||||
}
|
||||
break;
|
||||
case S_GETPEERNAME: /* DONE */
|
||||
tr_sock= (struct tr_sockaddr *)&dspace[uarg2];
|
||||
sock.sa_family= tr_sock->sa_family;
|
||||
ll_word(uarg3, len);
|
||||
#ifndef __linux__
|
||||
sock.sa_len=len;
|
||||
#endif
|
||||
memcpy(sock.sa_data, tr_sock->sa_data, len);
|
||||
i= getpeername(sarg1, &sock, &len);
|
||||
if (i != -1) {
|
||||
sl_word(uarg3,len);
|
||||
memcpy(tr_sock->sa_data, sock.sa_data, len);
|
||||
}
|
||||
break;
|
||||
case S_GETSOCKNAME: /* DONE */
|
||||
tr_sock= (struct tr_sockaddr *)&dspace[uarg2];
|
||||
sock.sa_family= tr_sock->sa_family;
|
||||
ll_word(uarg3, len);
|
||||
#ifndef __linux__
|
||||
sock.sa_len=len;
|
||||
#endif
|
||||
memcpy(sock.sa_data, tr_sock->sa_data, len);
|
||||
i= getsockname(sarg1, &sock, &len);
|
||||
if (i != -1) {
|
||||
sl_word(uarg3,len);
|
||||
memcpy(tr_sock->sa_data, sock.sa_data, len);
|
||||
}
|
||||
break;
|
||||
case S_BIND: /* DONE */
|
||||
tr_sock= (struct tr_sockaddr *)&dspace[uarg2];
|
||||
sock.sa_family= tr_sock->sa_family;
|
||||
len= sarg3;
|
||||
#ifndef __linux__
|
||||
sock.sa_len= sarg3;
|
||||
#endif
|
||||
memcpy(sock.sa_data, tr_sock->sa_data, len);
|
||||
i= bind(sarg1, &sock, len);
|
||||
break;
|
||||
case S_CONNECT: /* DONE */
|
||||
tr_sock= (struct tr_sockaddr *)&dspace[uarg2];
|
||||
sock.sa_family= tr_sock->sa_family;
|
||||
len= sarg3;
|
||||
#ifndef __linux__
|
||||
sock.sa_len= sarg3;
|
||||
#endif
|
||||
memcpy(sock.sa_data, tr_sock->sa_data, len);
|
||||
i= connect(sarg1, &sock, len);
|
||||
break;
|
||||
case S_RECVFROM: /* DONE I think */
|
||||
tr_sock= (struct tr_sockaddr *)&dspace[uarg5];
|
||||
sock.sa_family= tr_sock->sa_family;
|
||||
ll_word(uarg6, len);
|
||||
#ifndef __linux__
|
||||
sock.sa_len=len;
|
||||
#endif
|
||||
memcpy(sock.sa_data, tr_sock->sa_data, len);
|
||||
buf = &dspace[uarg2];
|
||||
i= recvfrom(sarg1, buf, sarg3, sarg4, &sock, &len);
|
||||
if (i != -1) {
|
||||
sl_word(uarg6,len);
|
||||
memcpy(tr_sock->sa_data, sock.sa_data, len);
|
||||
}
|
||||
break;
|
||||
case S_GETGROUPS:
|
||||
len= sarg1;
|
||||
gidset= (gid_t *)malloc(len * sizeof(gid_t));
|
||||
if (gidset==NULL) { i=-1; errno=EINVAL; break; }
|
||||
i= getgroups(len, gidset);
|
||||
shortptr= (int16_t *)&dspace[uarg2];
|
||||
for (j=0; j<i; j++) shortptr[j]= gidset[j];
|
||||
free(gidset);
|
||||
break;
|
||||
case S_SETGROUPS:
|
||||
len= sarg1;
|
||||
if (len>16) { i=-1; errno=EFAULT; break; }
|
||||
gidset= (gid_t *)malloc(len * sizeof(gid_t));
|
||||
if (gidset==NULL) { i=-1; errno=EINVAL; break; }
|
||||
shortptr= (int16_t *)&dspace[uarg2];
|
||||
for (j=0; j<len; j++) gidset[j]= shortptr[j];
|
||||
i= setgroups(len, gidset);
|
||||
free(gidset);
|
||||
break;
|
||||
case S_GETRLIMIT: /* DONE */
|
||||
tr_rlp= (struct tr_rlimit *)&dspace[uarg2];
|
||||
i= getrlimit(sarg1, &rlp);
|
||||
if (i== -1) break;
|
||||
copylong(tr_rlp->rlim_cur, rlp.rlim_cur);
|
||||
copylong(tr_rlp->rlim_max, rlp.rlim_max);
|
||||
break;
|
||||
case S_SETRLIMIT: /* DONE */
|
||||
tr_rlp= (struct tr_rlimit *)&dspace[uarg2];
|
||||
copylong(rlp.rlim_cur, tr_rlp->rlim_cur);
|
||||
copylong(rlp.rlim_max, tr_rlp->rlim_max);
|
||||
i= setrlimit(sarg1, &rlp);
|
||||
break;
|
||||
case S_GETRUSAGE:
|
||||
TrapDebug((dbg_file, "arg1 %d pointer 0%o ",sarg1,uarg2));
|
||||
tr_use = (struct tr_rusage *) &dspace[uarg2];
|
||||
i= getrusage(sarg1, &use);
|
||||
if (i==-1) break;
|
||||
|
||||
/* Should do tr_use->ru_utime; user time used */
|
||||
/* Should do tr_use->ru_stime; system time used */
|
||||
copylong(tr_use->ru_maxrss, use.ru_maxrss);
|
||||
copylong(tr_use->ru_ixrss, use.ru_ixrss);
|
||||
copylong(tr_use->ru_idrss, use.ru_idrss);
|
||||
copylong(tr_use->ru_isrss, use.ru_isrss);
|
||||
copylong(tr_use->ru_minflt, use.ru_minflt);
|
||||
copylong(tr_use->ru_majflt, use.ru_majflt);
|
||||
copylong(tr_use->ru_ovly, ov_changes);
|
||||
copylong(tr_use->ru_nswap, use.ru_nswap);
|
||||
copylong(tr_use->ru_inblock, use.ru_inblock);
|
||||
copylong(tr_use->ru_oublock, use.ru_oublock);
|
||||
copylong(tr_use->ru_msgsnd, use.ru_msgsnd);
|
||||
copylong(tr_use->ru_msgrcv, use.ru_msgrcv);
|
||||
copylong(tr_use->ru_nsignals, use.ru_nsignals);
|
||||
copylong(tr_use->ru_nvcsw, use.ru_nvcsw);
|
||||
copylong(tr_use->ru_nivcsw, use.ru_nivcsw);
|
||||
break;
|
||||
default:
|
||||
if ((ir & 0xff)>S_GETSOCKNAME) {
|
||||
TrapDebug((stderr,"Apout - unknown syscall %d at PC 0%o\n",
|
||||
ir & 0xff,regs[PC]));
|
||||
} else {
|
||||
(void)fprintf(stderr,
|
||||
"Apout - the 2.11BSD %s syscall is not yet implemented\n",
|
||||
bsdtrap_name[ir & 0xff]);
|
||||
}
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Set r0 to either errno or i, */
|
||||
/* and clear/set C bit */
|
||||
|
||||
if (i == -1) {
|
||||
SET_CC_C(); regs[0] = errno;
|
||||
TrapDebug((dbg_file, "errno is %s\n", strerror(errno)));
|
||||
} else {
|
||||
CLR_CC_C(); regs[0]=i;
|
||||
TrapDebug((dbg_file, "return %d\n", i));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
trap_execve(int want_env)
|
||||
{
|
||||
u_int16_t cptr, cptr2;
|
||||
char *buf, *name, *origpath;
|
||||
|
||||
origpath = strdup(&dspace[uarg1]);
|
||||
name = xlate_filename(origpath);
|
||||
TrapDebug((dbg_file, "%s Execing %s (%s) ", progname, name, origpath));
|
||||
|
||||
set_bsdsig_dfl(); /* Set signals to default values */
|
||||
|
||||
cptr=uarg2;
|
||||
Argc=0; Envc=0;
|
||||
while (Argc < MAX_ARGS) {
|
||||
ll_word(cptr, cptr2);
|
||||
if (cptr2 == 0)
|
||||
break;
|
||||
buf = &dspace[cptr2];
|
||||
Argv[Argc++] = strdup(buf);
|
||||
cptr += 2;
|
||||
TrapDebug((dbg_file, "%s ", buf));
|
||||
}
|
||||
Argv[Argc] = NULL;
|
||||
TrapDebug((dbg_file, "\n"));
|
||||
|
||||
if (want_env)
|
||||
{ cptr=uarg3;
|
||||
while (Envc < MAX_ARGS) {
|
||||
ll_word(cptr, cptr2);
|
||||
if (cptr2 == 0)
|
||||
break;
|
||||
buf = &dspace[cptr2];
|
||||
Envp[Envc++] = strdup(buf);
|
||||
cptr += 2;
|
||||
}
|
||||
Envp[Envc] = NULL;
|
||||
}
|
||||
|
||||
if (load_a_out(name,origpath,want_env) == -1) {
|
||||
for (Argc--; Argc >= 0; Argc--)
|
||||
free(Argv[Argc]);
|
||||
if (want_env) for (Envc--; Envc >= 0; Envc--)
|
||||
free(Envp[Envc]);
|
||||
errno= ENOENT; return(-1);
|
||||
}
|
||||
run(); /* Ok, so it's recursive, I dislike setjmp */
|
||||
return(0); /* Just to shut the compiler up */
|
||||
}
|
||||
|
||||
/* 2.11BSD reads directories as if they were ordinary files.
|
||||
* The solution is to read the directory entries, and build a
|
||||
* real file, which is passed back to the open call.
|
||||
*
|
||||
* A directory consists of some number of blocks of DIRBLKSIZ
|
||||
* bytes, where DIRBLKSIZ is chosen such that it can be transferred
|
||||
* to disk in a single atomic operation (e.g. 512 bytes on most machines).
|
||||
*
|
||||
* Each DIRBLKSIZ byte block contains some number of directory entry
|
||||
* structures, which are of variable length. Each directory entry has
|
||||
* a struct direct at the front of it, containing its inode number,
|
||||
* the length of the entry, and the length of the name contained in
|
||||
* the entry. These are followed by the name padded to a 4 byte boundary
|
||||
* with null bytes. All names are guaranteed null terminated.
|
||||
* The maximum length of a name in a directory is MAXNAMLEN.
|
||||
*
|
||||
* The macro DIRSIZ(dp) gives the amount of space required to represent
|
||||
* a directory entry. Free space in a directory is represented by
|
||||
* entries which have dp->d_reclen > DIRSIZ(dp). All DIRBLKSIZ bytes
|
||||
* in a directory block are claimed by the directory entries. This
|
||||
* usually results in the last entry in a directory having a large
|
||||
* dp->d_reclen. When entries are deleted from a directory, the
|
||||
* space is returned to the previous entry in the same directory
|
||||
* block by increasing its dp->d_reclen. If the first entry of
|
||||
* a directory block is free, then its dp->d_ino is set to 0.
|
||||
* Entries other than the first in a directory do not normally have
|
||||
* dp->d_ino set to 0.
|
||||
*/
|
||||
|
||||
static int
|
||||
bsdopen_dir(char *name)
|
||||
{
|
||||
DIR *d;
|
||||
char *tmpname;
|
||||
int i, nlen, total_left;
|
||||
struct dirent *dent;
|
||||
struct tr_direct odent, empty;
|
||||
|
||||
d = opendir(name);
|
||||
if (d == NULL) return (-1);
|
||||
tmpname= strdup(TMP_PLATE);
|
||||
i= mkstemp(tmpname);
|
||||
if (i == -1) {
|
||||
(void)fprintf(stderr,"Apout - open_dir couldn't open %s\n", tmpname);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
unlink(tmpname); free(tmpname);
|
||||
|
||||
total_left=TR_DIRBLKSIZ;
|
||||
empty.d_ino=0; empty.d_namlen=0; empty.d_name[0]='\0';
|
||||
empty.d_name[1]='\0'; empty.d_name[2]='\0'; empty.d_name[3]='\0';
|
||||
|
||||
while ((dent = readdir(d)) != NULL) {
|
||||
memset(odent.d_name, 0, TR_MAXNAMLEN+1); /* Null name */
|
||||
nlen= strlen(dent->d_name) +1; /* Name length */
|
||||
if (nlen>TR_MAXNAMLEN+1) nlen=TR_MAXNAMLEN+1;
|
||||
strncpy(odent.d_name, dent->d_name, nlen);
|
||||
odent.d_ino = dent->d_fileno;
|
||||
/* Nasty hack: ensure inode */
|
||||
/* is never 0 */
|
||||
if (odent.d_ino==0) odent.d_ino=1;
|
||||
odent.d_namlen= nlen;
|
||||
nlen+= (nlen & 3); /* Round up to mult of 4 */
|
||||
odent.d_reclen= nlen+6; /* Name + 3 u_int16_ts */
|
||||
|
||||
/* Not enough room, write */
|
||||
/* a blank entry */
|
||||
if ( (total_left - odent.d_reclen) < 10) {
|
||||
empty.d_reclen=total_left;
|
||||
write(i, &empty, empty.d_reclen);
|
||||
total_left=TR_DIRBLKSIZ;
|
||||
}
|
||||
write(i, &odent, odent.d_reclen);
|
||||
total_left-= odent.d_reclen;
|
||||
}
|
||||
closedir(d);
|
||||
|
||||
if (total_left) {
|
||||
empty.d_reclen=total_left; write(i, &empty, empty.d_reclen);
|
||||
}
|
||||
lseek(i, 0, SEEK_SET);
|
||||
return (i);
|
||||
}
|
||||
|
||||
#ifdef NEED_MAP_FCNTL
|
||||
/* Map the 2.11BSD fcntl mode bits to the underlying
|
||||
* system's bits. We have to do this for Linux
|
||||
*/
|
||||
static int16_t map_fcntl(int16_t f)
|
||||
{
|
||||
int16_t out=0;
|
||||
|
||||
if (f & BSD_RDONLY) out |= O_RDONLY;
|
||||
if (f & BSD_WRONLY) out |= O_WRONLY;
|
||||
if (f & BSD_RDWR) out |= O_RDWR;
|
||||
if (f & BSD_NONBLOCK) out |= O_NONBLOCK;
|
||||
if (f & BSD_APPEND) out |= O_APPEND;
|
||||
if (f & BSD_SHLOCK) out |= O_SHLOCK;
|
||||
if (f & BSD_EXLOCK) out |= O_EXLOCK;
|
||||
if (f & BSD_ASYNC) out |= O_ASYNC;
|
||||
if (f & BSD_FSYNC) out |= O_FSYNC;
|
||||
if (f & BSD_CREAT) out |= O_CREAT;
|
||||
if (f & BSD_TRUNC) out |= O_TRUNC;
|
||||
if (f & BSD_EXCL) out |= O_EXCL;
|
||||
|
||||
TrapDebug((dbg_file, "map_fcntl: 0x%x -> 0x%x, ",f,out));
|
||||
return(out);
|
||||
}
|
||||
#endif
|
||||
#endif /* EMU211 */
|
||||
429
tools/apout/bsdtrap.h
Normal file
429
tools/apout/bsdtrap.h
Normal file
@@ -0,0 +1,429 @@
|
||||
/* bsdtrap.h. Definitions for values and structures used in bsdtrap.c
|
||||
*
|
||||
* $Revision: 1.30 $
|
||||
* $Date: 1999/03/01 19:14:16 $
|
||||
*/
|
||||
|
||||
/* In this file, we list the trap number for each system call,
|
||||
* and the structures associated with several of the systems
|
||||
* calls in 2.11BSD UNIX
|
||||
*/
|
||||
|
||||
#define S_INDIR 0
|
||||
#define S_EXIT 1
|
||||
#define S_FORK 2
|
||||
#define S_READ 3
|
||||
#define S_WRITE 4
|
||||
#define S_OPEN 5
|
||||
#define S_CLOSE 6
|
||||
#define S_WAIT4 7
|
||||
#define S_CREAT 8
|
||||
#define S_LINK 9
|
||||
#define S_UNLINK 10
|
||||
#define S_EXECV 11
|
||||
#define S_CHDIR 12
|
||||
#define S_FCHDIR 13
|
||||
#define S_MKNOD 14
|
||||
#define S_CHMOD 15
|
||||
#define S_CHOWN 16
|
||||
#define S_CHFLAGS 17
|
||||
#define S_FCHFLAGS 18
|
||||
#define S_LSEEK 19
|
||||
#define S_GETPID 20
|
||||
#define S_MOUNT 21
|
||||
#define S_UMOUNT 22
|
||||
#define S_SYSCTL 23
|
||||
#define S_GETUID 24
|
||||
#define S_GETEUID 25
|
||||
#define S_PTRACE 26
|
||||
#define S_GETPPID 27
|
||||
#define S_STATFS 28
|
||||
#define S_FSTATFS 29
|
||||
#define S_GETFSSTAT 30
|
||||
#define S_SIGACTION 31
|
||||
#define S_SIGPROCMASK 32
|
||||
#define S_ACCESS 33
|
||||
#define S_SIGPENDING 34
|
||||
#define S_SIGALTSTACK 35
|
||||
#define S_SYNC 36
|
||||
#define S_KILL 37
|
||||
#define S_STAT 38
|
||||
#define S_GETLOGIN 39
|
||||
#define S_LSTAT 40
|
||||
#define S_DUP 41
|
||||
#define S_PIPE 42
|
||||
#define S_SETLOGIN 43
|
||||
#define S_PROFIL 44
|
||||
#define S_SETUID 45
|
||||
#define S_SETEUID 46
|
||||
#define S_GETGID 47
|
||||
#define S_GETEGID 48
|
||||
#define S_SETGID 49
|
||||
#define S_SETEGID 50
|
||||
#define S_ACCT 51
|
||||
#define S_OLDPHYS 52
|
||||
#define S_OLDLOCK 53
|
||||
#define S_IOCTL 54
|
||||
#define S_REBOOT 55
|
||||
#define S_SYMLINK 57
|
||||
#define S_READLINK 58
|
||||
#define S_EXECVE 59
|
||||
#define S_UMASK 60
|
||||
#define S_CHROOT 61
|
||||
#define S_FSTAT 62
|
||||
#define S_GETPAGESIZE 64
|
||||
#define S_VFORK 66
|
||||
#define S_SBRK 69
|
||||
#define S_VHANGUP 76
|
||||
#define S_GETGROUPS 79
|
||||
#define S_SETGROUPS 80
|
||||
#define S_GETPGRP 81
|
||||
#define S_SETPGRP 82
|
||||
#define S_SETITIMER 83
|
||||
#define S_WAIT 84
|
||||
#define S_GETITIMER 86
|
||||
#define S_GETHOSTNAME 87
|
||||
#define S_SETHOSTNAME 88
|
||||
#define S_GETDTABLESIZE 89
|
||||
#define S_DUP2 90
|
||||
#define S_UNUSED1 91
|
||||
#define S_FCNTL 92
|
||||
#define S_SELECT 93
|
||||
#define S_UNUSED2 94
|
||||
#define S_FSYNC 95
|
||||
#define S_SETPRIORITY 96
|
||||
#define S_SOCKET 97
|
||||
#define S_CONNECT 98
|
||||
#define S_ACCEPT 99
|
||||
#define S_GETPRIORITY 100
|
||||
#define S_SEND 101
|
||||
#define S_RECV 102
|
||||
#define S_SIGRETURN 103
|
||||
#define S_BIND 104
|
||||
#define S_SETSOCKOPT 105
|
||||
#define S_LISTEN 106
|
||||
#define S_SIGSUSPEND 107
|
||||
#define S_SIGVEC 108
|
||||
#define S_SIGBLOCK 109
|
||||
#define S_SIGSETMASK 110
|
||||
#define S_SIGPAUSE 111
|
||||
#define S_SIGSTACK 112
|
||||
#define S_RECVMSG 113
|
||||
#define S_SENDMSG 114
|
||||
#define S_GETTIMEOFDAY 116
|
||||
#define S_GETRUSAGE 117
|
||||
#define S_GETSOCKOPT 118
|
||||
#define S_READV 120
|
||||
#define S_WRITEV 121
|
||||
#define S_SETTIMEOFDAY 122
|
||||
#define S_FCHOWN 123
|
||||
#define S_FCHMOD 124
|
||||
#define S_RECVFROM 125
|
||||
#define S_SETREUID 126
|
||||
#define S_SETREGID 127
|
||||
#define S_RENAME 128
|
||||
#define S_TRUNCATE 129
|
||||
#define S_FTRUNCATE 130
|
||||
#define S_FLOCK 131
|
||||
#define S_SENDTO 133
|
||||
#define S_SHUTDOWN 134
|
||||
#define S_SOCKETPAIR 135
|
||||
#define S_MKDIR 136
|
||||
#define S_RMDIR 137
|
||||
#define S_UTIMES 138
|
||||
#define S_ADJTIME 140
|
||||
#define S_GETPEERNAME 141
|
||||
#define S_GETHOSTID 142
|
||||
#define S_SETHOSTID 143
|
||||
#define S_GETRLIMIT 144
|
||||
#define S_SETRLIMIT 145
|
||||
#define S_KILLPG 146
|
||||
#define S_NOSYS147 147
|
||||
#define S_SETQUOTA 148
|
||||
#define S_QUOTA 149
|
||||
#define S_GETSOCKNAME 150
|
||||
|
||||
|
||||
/*
|
||||
* System call names.
|
||||
*/
|
||||
#ifdef BSDTRAP_NAME
|
||||
char *bsdtrap_name[] = {
|
||||
"indir", /* 0 = indir */
|
||||
"exit", /* 1 = exit */
|
||||
"fork", /* 2 = fork */
|
||||
"read", /* 3 = read */
|
||||
"write", /* 4 = write */
|
||||
"open", /* 5 = open */
|
||||
"close", /* 6 = close */
|
||||
"wait4", /* 7 = wait4 */
|
||||
"creat", /* 8 = creat */
|
||||
"link", /* 9 = link */
|
||||
"unlink", /* 10 = unlink */
|
||||
"execv", /* 11 = execv */
|
||||
"chdir", /* 12 = chdir */
|
||||
"fchdir", /* 13 = fchdir */
|
||||
"mknod", /* 14 = mknod */
|
||||
"chmod", /* 15 = chmod */
|
||||
"chown", /* 16 = chown; now 3 args */
|
||||
"chflags", /* 17 = chflags */
|
||||
"fchflags", /* 18 = fchflags */
|
||||
"lseek", /* 19 = lseek */
|
||||
"getpid", /* 20 = getpid */
|
||||
"mount", /* 21 = mount */
|
||||
"umount", /* 22 = umount */
|
||||
"__sysctl", /* 23 = __sysctl */
|
||||
"getuid", /* 24 = getuid */
|
||||
"geteuid", /* 25 = geteuid */
|
||||
"ptrace", /* 26 = ptrace */
|
||||
"getppid", /* 27 = getppid */
|
||||
"statfs", /* 28 = statfs */
|
||||
"fstatfs", /* 29 = fstatfs */
|
||||
"getfsstat", /* 30 = getfsstat */
|
||||
"sigaction", /* 31 = sigaction */
|
||||
"sigprocmask", /* 32 = sigprocmask */
|
||||
"access", /* 33 = access */
|
||||
"sigpending", /* 34 = sigpending */
|
||||
"sigaltstack", /* 35 = sigaltstack */
|
||||
"sync", /* 36 = sync */
|
||||
"kill", /* 37 = kill */
|
||||
"stat", /* 38 = stat */
|
||||
"getlogin", /* 39 = getlogin */
|
||||
"lstat", /* 40 = lstat */
|
||||
"dup", /* 41 = dup */
|
||||
"pipe", /* 42 = pipe */
|
||||
"setlogin", /* 43 = setlogin */
|
||||
"profil", /* 44 = profil */
|
||||
"setuid", /* 45 = setuid */
|
||||
"seteuid", /* 46 = seteuid */
|
||||
"getgid", /* 47 = getgid */
|
||||
"getegid", /* 48 = getegid */
|
||||
"setgid", /* 49 = setgid */
|
||||
"setegid", /* 50 = setegid */
|
||||
"acct", /* 51 = turn acct off/on */
|
||||
"old phys", /* 52 = old set phys addr */
|
||||
"old lock", /* 53 = old lock in core */
|
||||
"ioctl", /* 54 = ioctl */
|
||||
"reboot", /* 55 = reboot */
|
||||
"old mpx - nosys", /* 56 = old mpxchan */
|
||||
"symlink", /* 57 = symlink */
|
||||
"readlink", /* 58 = readlink */
|
||||
"execve", /* 59 = execve */
|
||||
"umask", /* 60 = umask */
|
||||
"chroot", /* 61 = chroot */
|
||||
"fstat", /* 62 = fstat */
|
||||
"#63", /* 63 = used internally */
|
||||
"getpagesize", /* 64 = getpagesize */
|
||||
"4.3 mremap - nosys", /* 65 = mremap */
|
||||
"vfork", /* 66 = vfork */
|
||||
"old vread - nosys", /* 67 = old vread */
|
||||
"old vwrite - nosys", /* 68 = old vwrite */
|
||||
"sbrk", /* 69 = sbrk */
|
||||
"4.3 sstk - nosys", /* 70 = sstk */
|
||||
"4.3 mmap - nosys", /* 71 = mmap */
|
||||
"old vadvise - nosys", /* 72 = old vadvise */
|
||||
"4.3 munmap - nosys", /* 73 = munmap */
|
||||
"4.3 mprotect - nosys", /* 74 = mprotect */
|
||||
"4.3 madvise - nosys", /* 75 = madvise */
|
||||
"vhangup", /* 76 = vhangup */
|
||||
"old vlimit - nosys", /* 77 = old vlimit */
|
||||
"4.3 mincore - nosys", /* 78 = mincore */
|
||||
"getgroups", /* 79 = getgroups */
|
||||
"setgroups", /* 80 = setgroups */
|
||||
"getpgrp", /* 81 = getpgrp */
|
||||
"setpgrp", /* 82 = setpgrp */
|
||||
"setitimer", /* 83 = setitimer */
|
||||
"wait", /* 84 = wait */
|
||||
"4.3 swapon - nosys", /* 85 = swapon */
|
||||
"getitimer", /* 86 = getitimer */
|
||||
"gethostname", /* 87 = gethostname */
|
||||
"sethostname", /* 88 = sethostname */
|
||||
"getdtablesize", /* 89 = getdtablesize */
|
||||
"dup2", /* 90 = dup2 */
|
||||
"nosys", /* 91 = unused */
|
||||
"fcntl", /* 92 = fcntl */
|
||||
"select", /* 93 = select */
|
||||
"nosys", /* 94 = unused */
|
||||
"fsync", /* 95 = fsync */
|
||||
"setpriority", /* 96 = setpriority */
|
||||
"socket", /* 97 = socket */
|
||||
"connect", /* 98 = connect */
|
||||
"accept", /* 99 = accept */
|
||||
"getpriority", /* 100 = getpriority */
|
||||
"send", /* 101 = send */
|
||||
"recv", /* 102 = recv */
|
||||
"sigreturn", /* 103 = sigreturn */
|
||||
"bind", /* 104 = bind */
|
||||
"setsockopt", /* 105 = setsockopt */
|
||||
"listen", /* 106 = listen */
|
||||
"sigsuspend", /* 107 = sigsuspend */
|
||||
"sigvec", /* 108 = sigvec */
|
||||
"sigblock", /* 109 = sigblock */
|
||||
"sigsetmask", /* 110 = sigsetmask */
|
||||
"sigpause", /* 111 = sigpause */
|
||||
"sigstack", /* 112 = sigstack */
|
||||
"recvmsg", /* 113 = recvmsg */
|
||||
"sendmsg", /* 114 = sendmsg */
|
||||
"old vtrace - nosys", /* 115 = old vtrace */
|
||||
"gettimeofday", /* 116 = gettimeofday */
|
||||
"getrusage", /* 117 = getrusage */
|
||||
"getsockopt", /* 118 = getsockopt */
|
||||
"4.3 resuba - nosys", /* 119 = resuba */
|
||||
"readv", /* 120 = readv */
|
||||
"writev", /* 121 = writev */
|
||||
"settimeofday", /* 122 = settimeofday */
|
||||
"fchown", /* 123 = fchown */
|
||||
"fchmod", /* 124 = fchmod */
|
||||
"recvfrom", /* 125 = recvfrom */
|
||||
"setreuid", /* 126 = setreuid */
|
||||
"setregid", /* 127 = setregid */
|
||||
"rename", /* 128 = rename */
|
||||
"truncate", /* 129 = truncate */
|
||||
"ftruncate", /* 130 = ftruncate */
|
||||
"flock", /* 131 = flock */
|
||||
"old portal - nosys", /* 132 = old portal */
|
||||
"sendto", /* 133 = sendto */
|
||||
"shutdown", /* 134 = shutdown */
|
||||
"socketpair", /* 135 = socketpair */
|
||||
"mkdir", /* 136 = mkdir */
|
||||
"rmdir", /* 137 = rmdir */
|
||||
"utimes", /* 138 = utimes */
|
||||
"4.2 sigreturn - nosys", /* 139 = old 4.2 sigreturn */
|
||||
"adjtime", /* 140 = adjtime */
|
||||
"getpeername", /* 141 = getpeername */
|
||||
"gethostid", /* 142 = gethostid */
|
||||
"sethostid", /* 143 = sethostid */
|
||||
"getrlimit", /* 144 = getrlimit */
|
||||
"setrlimit", /* 145 = setrlimit */
|
||||
"killpg", /* 146 = killpg */
|
||||
"#147", /* 147 = nosys */
|
||||
"setquota", /* 148 = setquota */
|
||||
"quota", /* 149 = quota */
|
||||
"getsockname", /* 150 = getsockname */
|
||||
};
|
||||
#endif
|
||||
|
||||
/* fcntl defines used by open */
|
||||
#define BSD_RDONLY 0x0000 /* open for reading only */
|
||||
#define BSD_WRONLY 0x0001 /* open for writing only */
|
||||
#define BSD_RDWR 0x0002 /* open for reading and writing */
|
||||
#define BSD_NONBLOCK 0x0004 /* no delay */
|
||||
#define BSD_APPEND 0x0008 /* set append mode */
|
||||
#define BSD_SHLOCK 0x0010 /* open with shared file lock */
|
||||
#define BSD_EXLOCK 0x0020 /* open with exclusive file lock */
|
||||
#define BSD_ASYNC 0x0040 /* signal pgrp when data ready */
|
||||
#define BSD_FSYNC 0x0080 /* synchronous writes */
|
||||
#define BSD_CREAT 0x0200 /* create if nonexistant */
|
||||
#define BSD_TRUNC 0x0400 /* truncate to zero length */
|
||||
#define BSD_EXCL 0x0800 /* error if already exists */
|
||||
|
||||
|
||||
/* stat struct, used by S_STAT, S_FSTAT, S_LSTAT */
|
||||
struct tr_stat
|
||||
{
|
||||
int16_t st_dev;
|
||||
u_int16_t st_ino;
|
||||
u_int16_t st_mode;
|
||||
int16_t st_nlink;
|
||||
u_int16_t st_uid;
|
||||
u_int16_t st_gid;
|
||||
int16_t st_rdev;
|
||||
int8_t st_size[4]; /* Alignment problems */
|
||||
int8_t st_atim[4]; /* Alignment problems */
|
||||
int16_t st_spare1;
|
||||
int8_t st_mtim[4]; /* Alignment problems */
|
||||
int16_t st_spare2;
|
||||
int8_t st_ctim[4]; /* Alignment problems */
|
||||
int16_t st_spare3;
|
||||
int8_t st_blksize[4]; /* Alignment problems */
|
||||
int8_t st_blocks[4]; /* Alignment problems */
|
||||
u_int16_t st_flags;
|
||||
u_int16_t st_spare4[3];
|
||||
};
|
||||
|
||||
/* Directory entry */
|
||||
#define TR_DIRBLKSIZ 512
|
||||
#define TR_MAXNAMLEN 63
|
||||
struct tr_direct {
|
||||
u_int16_t d_ino; /* inode number of entry */
|
||||
u_int16_t d_reclen; /* length of this record */
|
||||
u_int16_t d_namlen; /* length of string in d_name */
|
||||
char d_name[TR_MAXNAMLEN+1]; /* name must be no longer than this */
|
||||
};
|
||||
|
||||
/* used by S_ADJTIME */
|
||||
struct tr_timeval {
|
||||
u_int32_t tv_sec; /* seconds */
|
||||
u_int32_t tv_usec; /* and microseconds */
|
||||
};
|
||||
/* Used by S_GETTIMEOFDAY */
|
||||
struct tr_timezone {
|
||||
int16_t tz_minuteswest; /* minutes west of Greenwich */
|
||||
int16_t tz_dsttime; /* type of dst correction */
|
||||
};
|
||||
|
||||
/* used in itimer calls */
|
||||
struct tr_itimerval {
|
||||
struct tr_timeval it_interval; /* timer interval */
|
||||
struct tr_timeval it_value; /* current value */
|
||||
};
|
||||
|
||||
/* Used by socket calls */
|
||||
struct tr_sockaddr {
|
||||
u_int16_t sa_family; /* address family */
|
||||
char sa_data[14]; /* up to 14 bytes of direct address */
|
||||
};
|
||||
|
||||
/* used in rlimit calls */
|
||||
struct tr_rlimit {
|
||||
int32_t rlim_cur; /* current (soft) limit */
|
||||
int32_t rlim_max; /* maximum value for rlim_cur */
|
||||
};
|
||||
|
||||
struct tr_rusage {
|
||||
struct tr_timeval ru_utime; /* user time used */
|
||||
struct tr_timeval ru_stime; /* system time used */
|
||||
u_int32_t ru_maxrss;
|
||||
u_int32_t ru_ixrss; /* integral shared memory size */
|
||||
u_int32_t ru_idrss; /* integral unshared data size */
|
||||
u_int32_t ru_isrss; /* integral unshared stack size */
|
||||
u_int32_t ru_minflt; /* page reclaims */
|
||||
u_int32_t ru_majflt; /* page faults */
|
||||
u_int32_t ru_ovly; /* overlay changes */
|
||||
u_int32_t ru_nswap; /* swaps */
|
||||
u_int32_t ru_inblock; /* block input operations */
|
||||
u_int32_t ru_oublock; /* block output operations */
|
||||
u_int32_t ru_msgsnd; /* messages sent */
|
||||
u_int32_t ru_msgrcv; /* messages received */
|
||||
u_int32_t ru_nsignals; /* signals received */
|
||||
u_int32_t ru_nvcsw; /* voluntary context switches */
|
||||
u_int32_t ru_nivcsw; /* involuntary context switches */
|
||||
};
|
||||
|
||||
/* for writev, readv */
|
||||
struct tr_iovec {
|
||||
u_int16_t iov_base;
|
||||
u_int16_t iov_len;
|
||||
};
|
||||
|
||||
|
||||
/* A union which will point at the trap args, so that
|
||||
* we can get at the various args of different types
|
||||
*/
|
||||
typedef union {
|
||||
int16_t sarg[6]; /* Signed 16-bit args */
|
||||
u_int16_t uarg[6]; /* Unsigned 16-bit args */
|
||||
} arglist;
|
||||
|
||||
#define sarg1 A->sarg[0]
|
||||
#define sarg2 A->sarg[1]
|
||||
#define sarg3 A->sarg[2]
|
||||
#define sarg4 A->sarg[3]
|
||||
#define sarg5 A->sarg[4]
|
||||
#define sarg6 A->sarg[5]
|
||||
#define uarg1 A->uarg[0]
|
||||
#define uarg2 A->uarg[1]
|
||||
#define uarg3 A->uarg[2]
|
||||
#define uarg4 A->uarg[3]
|
||||
#define uarg5 A->uarg[4]
|
||||
#define uarg6 A->uarg[5]
|
||||
209
tools/apout/cpu.c
Normal file
209
tools/apout/cpu.c
Normal file
@@ -0,0 +1,209 @@
|
||||
/* cpu.c - this holds the main loop for the emulator, plus generic
|
||||
* functions to deal with exceptional instructions and events
|
||||
*
|
||||
* $Revision: 1.25 $
|
||||
* $Date: 2002/06/10 11:41:40 $
|
||||
*/
|
||||
#include "defines.h"
|
||||
#include <unistd.h>
|
||||
|
||||
u_int8_t *ispace, *dspace; /* Instruction and Data spaces */
|
||||
u_int16_t dwrite_base=2; /* Lowest addr where dspace writes can occur */
|
||||
|
||||
u_int16_t regs[8]; /* general registers */
|
||||
u_int16_t ir; /* current instruction register */
|
||||
u_int16_t *adptr; /* used in memory access macros */
|
||||
u_int16_t ea_addr; /* stored address for dest modifying insts */
|
||||
|
||||
int CC_N=0; /* The processor status word is represented */
|
||||
int CC_Z=0; /* by these four values. On some */
|
||||
int CC_V=0; /* architectures, you may get a performance */
|
||||
int CC_C=0; /* increase by using shorts or bytes */
|
||||
|
||||
u_int16_t dstword; /* These globals are used in the effective */
|
||||
u_int16_t srcword; /* address calculations, mainly to save */
|
||||
u_int16_t tmpword; /* parameter passing overheads in */
|
||||
u_int8_t dstbyte; /* function calls */
|
||||
u_int8_t srcbyte;
|
||||
u_int8_t tmpbyte;
|
||||
struct our_siglist *Sighead=NULL; /* List of pending signals */
|
||||
struct our_siglist *Sigtail=NULL; /* List of pending signals */
|
||||
void (*sigrunner)(void)= NULL; /* F'n that will run the signal */
|
||||
|
||||
#ifdef DEBUG
|
||||
extern char *iname[1024];
|
||||
extern char *iname0[64]; /* Name of each instruction */
|
||||
extern char *iname1[64];
|
||||
char *name;
|
||||
#endif
|
||||
|
||||
|
||||
/* Run until told to stop. */
|
||||
void run() {
|
||||
#ifdef DEBUG
|
||||
int i;
|
||||
|
||||
if (trap_debug) {
|
||||
TrapDebug((dbg_file, "Just starting to run pid %d\n",(int)getpid()));
|
||||
TrapDebug((dbg_file, "Regs are "));
|
||||
for (i=0;i<=PC;i++) TrapDebug((dbg_file, "%06o ",regs[i]));
|
||||
TrapDebug((dbg_file, "\n"));
|
||||
}
|
||||
#endif
|
||||
|
||||
while (1) {
|
||||
|
||||
/* Fetch and execute the instruction. */
|
||||
|
||||
#ifdef DEBUG
|
||||
lli_word(regs[PC], ir);
|
||||
if (inst_debug) {
|
||||
i= ir >> 6;
|
||||
switch (i) {
|
||||
case 0: name= iname0[ir & 077]; break;
|
||||
case 2: name= iname1[ir & 077]; break;
|
||||
default: name= iname[i];
|
||||
}
|
||||
TrapDebug((dbg_file, "%06o %06o %4s ", regs[7], ir, name));
|
||||
TrapDebug((dbg_file, "%06o %06o %06o %06o %06o %06o %06o ",
|
||||
regs[0], regs[1], regs[2], regs[3],
|
||||
regs[4], regs[5], regs[6]));
|
||||
TrapDebug((dbg_file, "NZVC1 %d%d%d%d\n",CC_N,CC_Z,CC_V,CC_C));
|
||||
}
|
||||
regs[PC] += 2; itab[ir >> 6] ();
|
||||
if ((Sighead!=NULL) && (sigrunner!=NULL)) (void) (*sigrunner)();
|
||||
#else
|
||||
/* When not debugging, we can manually unroll this inner loop */
|
||||
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
||||
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
||||
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
||||
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
||||
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
||||
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
||||
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
||||
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
||||
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
||||
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
||||
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
||||
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
||||
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
||||
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
||||
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
||||
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
||||
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
||||
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
||||
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
||||
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
||||
if ((Sighead!=NULL) && (sigrunner!=NULL)) (void) (*sigrunner)();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* sim_init() - Initialize the cpu registers. */
|
||||
void sim_init() {
|
||||
int x;
|
||||
|
||||
for (x = 0; x < 8; ++x) { regs[x] = 0; }
|
||||
ir = 0; CLR_CC_ALL();
|
||||
}
|
||||
|
||||
void bus_error(int signo)
|
||||
{
|
||||
TrapDebug((dbg_file, "Apout - pid %d bus error at PC 0%06o\n",
|
||||
(int)getpid(), regs[PC]));
|
||||
TrapDebug((dbg_file, "%06o ", ir));
|
||||
TrapDebug((dbg_file, "%o %o %o %o %o %o %o %o ",
|
||||
regs[0], regs[1], regs[2], regs[3],
|
||||
regs[4], regs[5], regs[6], regs[7]));
|
||||
TrapDebug((dbg_file, "NZVC2 are %d%d%d%d\n",CC_N,CC_Z,CC_V,CC_C));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void seg_fault() {
|
||||
TrapDebug((dbg_file, "Apout - pid %d segmentation fault at PC 0%06o\n",
|
||||
(int)getpid(), regs[PC]));
|
||||
TrapDebug((dbg_file, "%06o ", ir));
|
||||
TrapDebug((dbg_file, "%o %o %o %o %o %o %o %o ",
|
||||
regs[0], regs[1], regs[2], regs[3],
|
||||
regs[4], regs[5], regs[6], regs[7]));
|
||||
TrapDebug((dbg_file, "NZVC3 are %d%d%d%d\n",CC_N,CC_Z,CC_V,CC_C));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void waiti() {
|
||||
TrapDebug((stderr, "Apout - pid %d waiti instruction at PC 0%o\n",
|
||||
(int)getpid(), regs[PC]));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
void halt() {
|
||||
TrapDebug((stderr, "Apout - pid %d halt instruction at PC 0%o\n",
|
||||
(int)getpid(), regs[PC]));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
void iot() {
|
||||
TrapDebug((stderr, "Apout - pid %d iot instruction at PC 0%o\n",
|
||||
(int)getpid(), regs[PC]));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
void emt() {
|
||||
TrapDebug((stderr, "Apout - pid %d emt instruction at PC 0%o\n",
|
||||
(int)getpid(), regs[PC]));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
void bpt() {
|
||||
TrapDebug((stderr, "Apout - pid %d bpt instruction at PC 0%o\n",
|
||||
(int)getpid(), regs[PC]));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
void illegal() {
|
||||
TrapDebug((stderr, "Apout - pid %d illegal instruction %o at PC 0%o\n",
|
||||
(int)getpid(),ir, regs[PC]));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
void not_impl() {
|
||||
TrapDebug((stderr, "Apout - pid %d unimplemented instruction at PC 0%o\n",
|
||||
(int)getpid(), regs[PC]));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
void mark() {
|
||||
TrapDebug((stderr, "Apout - pid %d mark instruction at PC 0%o\n",
|
||||
(int)getpid(), regs[PC]));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
void mfpd() {
|
||||
TrapDebug((stderr, "Apout - pid %d mfpd instruction at PC 0%o\n",
|
||||
(int)getpid(), regs[PC]));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
void mtpd() {
|
||||
TrapDebug((stderr, "Apout - pid %d mtpd instruction at PC 0%o\n",
|
||||
(int)getpid(), regs[PC]));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
void trap() {
|
||||
TrapDebug((stderr, "Apout - pid %d trap instruction at PC 0%o\n",
|
||||
(int)getpid(), regs[PC]));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
void bad_FP_reg() {
|
||||
TrapDebug((stderr, "Apout - pid %d bad FP register used at PC 0%o\n",
|
||||
(int)getpid(), regs[PC]));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* This is the generic function which catches
|
||||
* a signal, and appends it to the queue.
|
||||
*/
|
||||
void sigcatcher(int sig)
|
||||
{
|
||||
struct our_siglist *this;
|
||||
|
||||
this= (struct our_siglist *)malloc(sizeof(struct our_siglist));
|
||||
if (this==NULL) return;
|
||||
|
||||
TrapDebug((dbg_file, "Caught signal %d\n",sig));
|
||||
|
||||
this->sig=sig; this->next=NULL;
|
||||
if (Sighead==NULL) { Sighead=Sigtail=this; }
|
||||
else { Sigtail->next= this; Sigtail=this; }
|
||||
}
|
||||
159
tools/apout/debug.c
Normal file
159
tools/apout/debug.c
Normal file
@@ -0,0 +1,159 @@
|
||||
/* List of names for each instruction
|
||||
*
|
||||
* $Revision: 1.5 $
|
||||
* $Date: 1999/01/05 22:50:48 $
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
char *iname0[64] = {
|
||||
"halt","waiti","illegal","bpt","iot","illegal","illegal","illegal",
|
||||
"illegal","illegal","illegal","illegal","illegal","illegal","illegal","illegal",
|
||||
"illegal","illegal","illegal","illegal","illegal","illegal","illegal","illegal",
|
||||
"illegal","illegal","illegal","illegal","illegal","illegal","illegal","illegal",
|
||||
"illegal","illegal","illegal","illegal","illegal","illegal","illegal","illegal",
|
||||
"illegal","illegal","illegal","illegal","illegal","illegal","illegal","illegal",
|
||||
"illegal","illegal","illegal","illegal","illegal","illegal","illegal","illegal",
|
||||
"illegal","illegal","illegal","illegal","illegal","illegal","illegal","illegal"
|
||||
};
|
||||
|
||||
char *iname1[64] = {
|
||||
"rts","rts","rts","rts","rts","rts","rts","rts",
|
||||
"illegal","illegal","illegal","illegal","illegal","illegal","illegal","illegal",
|
||||
"illegal","illegal","illegal","illegal","illegal","illegal","illegal","illegal",
|
||||
"illegal","illegal","illegal","illegal","illegal","illegal","illegal","illegal",
|
||||
"ccc","ccc","ccc","ccc","ccc","ccc","ccc","ccc",
|
||||
"ccc","ccc","ccc","ccc","ccc","ccc","ccc","ccc",
|
||||
"scc","scc","scc","scc","scc","scc","scc","scc",
|
||||
"scc","scc","scc","scc","scc","scc","scc","scc"
|
||||
};
|
||||
|
||||
char *iname[1024] = {
|
||||
"dositab0","jmp","dositab1","swabi","br","br","br","br",
|
||||
"bne","bne","bne","bne","beq","beq","beq","beq",
|
||||
"bge","bge","bge","bge","blt","blt","blt","blt",
|
||||
"bgt","bgt","bgt","bgt","ble","ble","ble","ble",
|
||||
"jsr","jsr","jsr","jsr","jsr","jsr","jsr","jsr",
|
||||
"clr","com","inc","dec","neg","adc","sbc","tst",
|
||||
"ror","rol","asr","asl","mark","mfpi","mtpi","sxt",
|
||||
"illegal","illegal","illegal","illegal","illegal","illegal","illegal","illegal",
|
||||
"mov","mov","mov","mov","mov","mov","mov","mov",
|
||||
"mov","mov","mov","mov","mov","mov","mov","mov",
|
||||
"mov","mov","mov","mov","mov","mov","mov","mov",
|
||||
"mov","mov","mov","mov","mov","mov","mov","mov",
|
||||
"mov","mov","mov","mov","mov","mov","mov","mov",
|
||||
"mov","mov","mov","mov","mov","mov","mov","mov",
|
||||
"mov","mov","mov","mov","mov","mov","mov","mov",
|
||||
"mov","mov","mov","mov","mov","mov","mov","mov",
|
||||
"cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp",
|
||||
"cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp",
|
||||
"cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp",
|
||||
"cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp",
|
||||
"cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp",
|
||||
"cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp",
|
||||
"cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp",
|
||||
"cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp",
|
||||
"bit","bit","bit","bit","bit","bit","bit","bit",
|
||||
"bit","bit","bit","bit","bit","bit","bit","bit",
|
||||
"bit","bit","bit","bit","bit","bit","bit","bit",
|
||||
"bit","bit","bit","bit","bit","bit","bit","bit",
|
||||
"bit","bit","bit","bit","bit","bit","bit","bit",
|
||||
"bit","bit","bit","bit","bit","bit","bit","bit",
|
||||
"bit","bit","bit","bit","bit","bit","bit","bit",
|
||||
"bit","bit","bit","bit","bit","bit","bit","bit",
|
||||
"bic","bic","bic","bic","bic","bic","bic","bic",
|
||||
"bic","bic","bic","bic","bic","bic","bic","bic",
|
||||
"bic","bic","bic","bic","bic","bic","bic","bic",
|
||||
"bic","bic","bic","bic","bic","bic","bic","bic",
|
||||
"bic","bic","bic","bic","bic","bic","bic","bic",
|
||||
"bic","bic","bic","bic","bic","bic","bic","bic",
|
||||
"bic","bic","bic","bic","bic","bic","bic","bic",
|
||||
"bic","bic","bic","bic","bic","bic","bic","bic",
|
||||
"bis","bis","bis","bis","bis","bis","bis","bis",
|
||||
"bis","bis","bis","bis","bis","bis","bis","bis",
|
||||
"bis","bis","bis","bis","bis","bis","bis","bis",
|
||||
"bis","bis","bis","bis","bis","bis","bis","bis",
|
||||
"bis","bis","bis","bis","bis","bis","bis","bis",
|
||||
"bis","bis","bis","bis","bis","bis","bis","bis",
|
||||
"bis","bis","bis","bis","bis","bis","bis","bis",
|
||||
"bis","bis","bis","bis","bis","bis","bis","bis",
|
||||
"add","add","add","add","add","add","add","add",
|
||||
"add","add","add","add","add","add","add","add",
|
||||
"add","add","add","add","add","add","add","add",
|
||||
"add","add","add","add","add","add","add","add",
|
||||
"add","add","add","add","add","add","add","add",
|
||||
"add","add","add","add","add","add","add","add",
|
||||
"add","add","add","add","add","add","add","add",
|
||||
"add","add","add","add","add","add","add","add",
|
||||
"mul","mul","mul","mul","mul","mul","mul","mul",
|
||||
"divide","divide","divide","divide","divide","divide","divide","divide",
|
||||
"ash","ash","ash","ash","ash","ash","ash","ash",
|
||||
"ashc","ashc","ashc","ashc","ashc","ashc","ashc","ashc",
|
||||
"xor","xor","xor","xor","xor","xor","xor","xor",
|
||||
"illegal","illegal","illegal","illegal","illegal","illegal","illegal","illegal",
|
||||
"illegal","illegal","illegal","illegal","illegal","illegal","illegal","illegal",
|
||||
"sob","sob","sob","sob","sob","sob","sob","sob",
|
||||
"bpl","bpl","bpl","bpl","bmi","bmi","bmi","bmi",
|
||||
"bhi","bhi","bhi","bhi","blos","blos","blos","blos",
|
||||
"bvc","bvc","bvc","bvc","bvs","bvs","bvs","bvs",
|
||||
"bcc","bcc","bcc","bcc","bcs","bcs","bcs","bcs",
|
||||
"emt","emt","emt","emt","trap","trap","trap","trap",
|
||||
"clrb","comb","incb","decb","negb","adcb","sbcb","tstb",
|
||||
"rorb","rolb","asrb","aslb","mtps","mfpd","mtpd","mfps",
|
||||
"illegal","illegal","illegal","illegal","illegal","illegal","illegal","illegal",
|
||||
"movb","movb","movb","movb","movb","movb","movb","movb",
|
||||
"movb","movb","movb","movb","movb","movb","movb","movb",
|
||||
"movb","movb","movb","movb","movb","movb","movb","movb",
|
||||
"movb","movb","movb","movb","movb","movb","movb","movb",
|
||||
"movb","movb","movb","movb","movb","movb","movb","movb",
|
||||
"movb","movb","movb","movb","movb","movb","movb","movb",
|
||||
"movb","movb","movb","movb","movb","movb","movb","movb",
|
||||
"movb","movb","movb","movb","movb","movb","movb","movb",
|
||||
"cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb",
|
||||
"cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb",
|
||||
"cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb",
|
||||
"cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb",
|
||||
"cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb",
|
||||
"cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb",
|
||||
"cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb",
|
||||
"cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb",
|
||||
"bitb","bitb","bitb","bitb","bitb","bitb","bitb","bitb",
|
||||
"bitb","bitb","bitb","bitb","bitb","bitb","bitb","bitb",
|
||||
"bitb","bitb","bitb","bitb","bitb","bitb","bitb","bitb",
|
||||
"bitb","bitb","bitb","bitb","bitb","bitb","bitb","bitb",
|
||||
"bitb","bitb","bitb","bitb","bitb","bitb","bitb","bitb",
|
||||
"bitb","bitb","bitb","bitb","bitb","bitb","bitb","bitb",
|
||||
"bitb","bitb","bitb","bitb","bitb","bitb","bitb","bitb",
|
||||
"bitb","bitb","bitb","bitb","bitb","bitb","bitb","bitb",
|
||||
"bicb","bicb","bicb","bicb","bicb","bicb","bicb","bicb",
|
||||
"bicb","bicb","bicb","bicb","bicb","bicb","bicb","bicb",
|
||||
"bicb","bicb","bicb","bicb","bicb","bicb","bicb","bicb",
|
||||
"bicb","bicb","bicb","bicb","bicb","bicb","bicb","bicb",
|
||||
"bicb","bicb","bicb","bicb","bicb","bicb","bicb","bicb",
|
||||
"bicb","bicb","bicb","bicb","bicb","bicb","bicb","bicb",
|
||||
"bicb","bicb","bicb","bicb","bicb","bicb","bicb","bicb",
|
||||
"bicb","bicb","bicb","bicb","bicb","bicb","bicb","bicb",
|
||||
"bisb","bisb","bisb","bisb","bisb","bisb","bisb","bisb",
|
||||
"bisb","bisb","bisb","bisb","bisb","bisb","bisb","bisb",
|
||||
"bisb","bisb","bisb","bisb","bisb","bisb","bisb","bisb",
|
||||
"bisb","bisb","bisb","bisb","bisb","bisb","bisb","bisb",
|
||||
"bisb","bisb","bisb","bisb","bisb","bisb","bisb","bisb",
|
||||
"bisb","bisb","bisb","bisb","bisb","bisb","bisb","bisb",
|
||||
"bisb","bisb","bisb","bisb","bisb","bisb","bisb","bisb",
|
||||
"bisb","bisb","bisb","bisb","bisb","bisb","bisb","bisb",
|
||||
"sub","sub","sub","sub","sub","sub","sub","sub",
|
||||
"sub","sub","sub","sub","sub","sub","sub","sub",
|
||||
"sub","sub","sub","sub","sub","sub","sub","sub",
|
||||
"sub","sub","sub","sub","sub","sub","sub","sub",
|
||||
"sub","sub","sub","sub","sub","sub","sub","sub",
|
||||
"sub","sub","sub","sub","sub","sub","sub","sub",
|
||||
"sub","sub","sub","sub","sub","sub","sub","sub",
|
||||
"sub","sub","sub","sub","sub","sub","sub","sub",
|
||||
"fpset","ldfps","stfps","stst","clrf","tstf","absf","negf",
|
||||
"mulf","mulf","mulf","mulf","moddf","moddf","moddf","moddf",
|
||||
"addf","addf","addf","addf","ldf","ldf","ldf","ldf",
|
||||
"subf","subf","subf","subf","cmpf","cmpf","cmpf","cmpf",
|
||||
"stf","stf","stf","stf","divf","divf","divf","divf",
|
||||
"stexp","stexp","stexp","stexp","stcfi","stcfi","stcfi","stcfi",
|
||||
"stcdf","stcdf","stcdf","stcdf","ldexpp","ldexpp","ldexpp","ldexpp",
|
||||
"lcdif","lcdif","lcdif","lcdif","ldcdf","ldcdf","ldcdf","ldcdf"
|
||||
};
|
||||
#endif
|
||||
636
tools/apout/defines.h
Normal file
636
tools/apout/defines.h
Normal file
@@ -0,0 +1,636 @@
|
||||
/* defines.h - Definitions of things needed in all C files
|
||||
*
|
||||
* $Revision: 2.73 $
|
||||
* $Date: 2002/06/10 12:08:27 $
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* Defines for ifdef'd code -- define them in the Makefile */
|
||||
|
||||
/* #define DEBUG adds in debugging code */
|
||||
/* #define ZERO_MEMORY zeros all of process memory before
|
||||
it starts to run */
|
||||
/* #define NATIVES allows native binaries and PDP-11
|
||||
binaries in the filespace */
|
||||
/* #define EMU211 add 2.11BSD emulation */
|
||||
/* #define EMUV1 add 1st Edition emulation */
|
||||
/* #define INLINE inline inlines some functions (needs gcc) */
|
||||
|
||||
|
||||
/* Optimisation defines */
|
||||
#ifndef INLINE
|
||||
# define INLINE
|
||||
#endif
|
||||
|
||||
/* Special defines to enable/disable certain
|
||||
* functionality. These are added as required
|
||||
* to port to new platforms. Please send in new
|
||||
* defines, please!
|
||||
*/
|
||||
|
||||
#if defined(__FreeBSD__) && __FreeBSD__ < 3
|
||||
# define NO_GETPGID
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
# define Reboot(x) reboot(x)
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
# define NO_CHFLAGS
|
||||
# define NO_STFLAGS
|
||||
# define NO_GETPGID
|
||||
# define NEED_MAP_FCNTL
|
||||
# define SIGEMT 0
|
||||
# ifndef SIGSYS
|
||||
# define SIGSYS 0
|
||||
# endif
|
||||
# define OXTABS XTABS
|
||||
# define VDSUSP VSUSP /* I don't think these are equivalent */
|
||||
# define O_SHLOCK 0
|
||||
# define O_EXLOCK 0
|
||||
#endif
|
||||
|
||||
#if defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
# define Reboot(x) reboot(x,NULL)
|
||||
#endif
|
||||
|
||||
#ifndef Reboot
|
||||
# define Reboot(x) exit(0)
|
||||
#endif
|
||||
|
||||
#if !defined(__FreeBSD__) && !defined(__NetBSD__) && \
|
||||
!defined(__OpenBSD__) && !defined(__linux__)
|
||||
# define NEED_INT_N
|
||||
#endif
|
||||
|
||||
/* Type definitions for PDP data types. You may need to
|
||||
* define NEED_INT_N if your system doesn't provide the
|
||||
* types defined below. If you do this, the best way is
|
||||
* to add some #if .. #define .. #endif lines above,
|
||||
* rather then modifying the ones below. If you make
|
||||
* changes to the #if's above, then I would be very
|
||||
* happy to include them.
|
||||
*
|
||||
* Warren Toomey: wkt@tuhs.org
|
||||
*/
|
||||
|
||||
#ifdef NEED_INT_N
|
||||
typedef char int8_t;
|
||||
typedef short int16_t;
|
||||
typedef long int32_t;
|
||||
typedef unsigned char u_int8_t;
|
||||
typedef unsigned short u_int16_t;
|
||||
typedef unsigned long u_int32_t;
|
||||
#endif
|
||||
|
||||
/* Macro defines for debug output, makes
|
||||
* the code look somewhat cleaner
|
||||
*/
|
||||
|
||||
#ifdef DEBUG
|
||||
# define TrapDebug(x) if (trap_debug) (void)fprintf x
|
||||
# define InstDebug(x) if (inst_debug) (void)fprintf x
|
||||
# define JsrDebug(x) if (jsr_debug) (void)fprintf x
|
||||
# define FpDebug(x) if (fp_debug) (void)fprintf x
|
||||
#else
|
||||
# define TrapDebug(x)
|
||||
# define InstDebug(x)
|
||||
# define JsrDebug(x)
|
||||
# define FpDebug(x)
|
||||
#endif
|
||||
|
||||
/* Defines for -DSTREAM_BUFFERING */
|
||||
#define NFILE 40 /* Number of file pointers we can buffer */
|
||||
#define ValidFD(x) ((x>=0) && (x<NFILE))
|
||||
/* Used for opening on directories */
|
||||
#define TMP_PLATE "/usr/tmp/apout_dir.XXXXXX"
|
||||
|
||||
|
||||
/* Set up prototype macro for
|
||||
* both K&R and ANSI C platforms
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
#define P(s) s
|
||||
#else
|
||||
#define P(s) ()
|
||||
#endif
|
||||
|
||||
typedef void (*_itab) P((void));
|
||||
extern _itab itab[]; /* Instruction Table for Fast Decode. */
|
||||
|
||||
typedef float FLOAT; /* For now, we use floats to do FP */
|
||||
|
||||
/* PDP processor defines. */
|
||||
|
||||
#define SP 6 /* stack pointer */
|
||||
#define PC 7 /* program counter */
|
||||
#define CC_NBIT 010 /* Positions of the flags in the */
|
||||
#define CC_ZBIT 04 /* processor status word */
|
||||
#define CC_VBIT 02
|
||||
#define CC_CBIT 01
|
||||
|
||||
#define PDP_MEM_SIZE 65536 /* Size of inst-space and data-space */
|
||||
#define MAX_ARGS 200 /* Max cmd-line args per process */
|
||||
|
||||
|
||||
/* Global variables. */
|
||||
|
||||
extern u_int16_t regs[8]; /* general registers */
|
||||
extern u_int16_t ir; /* current instruction register */
|
||||
extern int CC_N; /* The processor status word is represented */
|
||||
extern int CC_Z; /* by these four values. On some */
|
||||
extern int CC_V; /* architectures, you may get a performance */
|
||||
extern int CC_C; /* increase by changing the size of the vars */
|
||||
|
||||
extern FLOAT fregs[8]; /* FP registers */
|
||||
extern int FPC; /* FP Status flags */
|
||||
extern int FPZ;
|
||||
extern int FPN;
|
||||
extern int FPV;
|
||||
extern int FPMODE; /* 0 = float, 1 = doubles */
|
||||
extern int INTMODE; /* 0 = integers, 1 = longs */
|
||||
|
||||
extern u_int16_t ea_addr; /* stored address for dest modifying insts */
|
||||
extern u_int8_t *ispace, *dspace;
|
||||
extern u_int16_t dwrite_base; /* Lowest addr where dspace writes can occur */
|
||||
|
||||
extern u_int16_t dstword; /* These globals are used in the effective */
|
||||
extern u_int16_t srcword; /* address calculations, mainly to save */
|
||||
extern u_int16_t tmpword; /* parameter passing overheads in */
|
||||
extern u_int8_t dstbyte; /* function calls */
|
||||
extern u_int8_t srcbyte;
|
||||
extern u_int8_t tmpbyte;
|
||||
|
||||
/* The following array holds the FILE pointers
|
||||
* that correspond to open file descriptors.
|
||||
* Only fds which are not ttys have
|
||||
* FILE * pointers
|
||||
*/
|
||||
extern FILE *stream[NFILE];
|
||||
extern char *streammode[NFILE];
|
||||
|
||||
extern int sig_arrived; /* Indicates if a signal has arrived */
|
||||
extern int Argc, Envc; /* Arguments passed to new process */
|
||||
extern char *Argv[MAX_ARGS], *Envp[MAX_ARGS];
|
||||
extern int Binary; /* Type of binary this a.out is. One of: */
|
||||
#define IS_UNKNOWN 0
|
||||
#define IS_V1 1
|
||||
#define IS_V2 2
|
||||
#define IS_V3 3
|
||||
#define IS_V4 4
|
||||
#define IS_V5 5
|
||||
#define IS_V6 6
|
||||
#define IS_V7 7
|
||||
#define IS_A68 68
|
||||
#define IS_29BSD 29
|
||||
#define IS_211BSD 211
|
||||
|
||||
/* 2.11BSD overlay stuff */
|
||||
extern u_int32_t ov_changes; /* Number of overlay changes */
|
||||
extern u_int8_t current_ov; /* Current overlay number */
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Debugging flags */
|
||||
extern int inst_debug, /* Print a line before each instruction */
|
||||
trap_debug, /* Print details of each trap */
|
||||
jsr_debug, /* Print out each jsr */
|
||||
fp_debug; /* Print out each floating-point instruction */
|
||||
extern FILE *dbg_file; /* Debugging output file */
|
||||
extern char *progname; /* The program's name - used in debugging */
|
||||
#endif
|
||||
|
||||
/* We keep a list of signals that are pending */
|
||||
struct our_siglist {
|
||||
int sig; /* Number of the signal */
|
||||
struct our_siglist *next;
|
||||
};
|
||||
extern struct our_siglist *Sighead; /* Head of the list */
|
||||
extern struct our_siglist *Sigtail; /* Tail of the list */
|
||||
|
||||
/* Inline defines. */
|
||||
|
||||
#define CLR_CC_V() CC_V=0
|
||||
#define CLR_CC_C() CC_C=0
|
||||
#define CLR_CC_Z() CC_Z=0
|
||||
#define CLR_CC_N() CC_N=0
|
||||
#define CLR_CC_ALL() CC_V=CC_C=CC_Z=CC_N=0
|
||||
|
||||
#define SET_CC_V() CC_V=1
|
||||
#define SET_CC_C() CC_C=1
|
||||
#define SET_CC_Z() CC_Z=1
|
||||
#define SET_CC_N() CC_N=1
|
||||
|
||||
#define SRC_MODE (( ir & 07000 ) >> 9 )
|
||||
#define SRC_REG (( ir & 0700 ) >> 6 )
|
||||
#define DST_MODE (( ir & 070 ) >> 3 )
|
||||
#define DST_REG ( ir & 07 )
|
||||
|
||||
#define LSBIT 1 /* least significant bit */
|
||||
|
||||
#define MPI 0077777 /* most positive integer */
|
||||
#define MNI 0100000 /* most negative integer */
|
||||
#define NEG_1 0177777 /* negative one */
|
||||
#define SIGN 0100000 /* sign bit */
|
||||
#define CARRY 0200000 /* set if carry out */
|
||||
|
||||
#define MPI_B 0177 /* most positive integer (byte) */
|
||||
#define MNI_B 0200 /* most negative integer (byte) */
|
||||
#define NEG_1_B 0377 /* negative one (byte) */
|
||||
#define SIGN_B 0200 /* sign bit (byte) */
|
||||
#define CARRY_B 0400 /* set if carry out (byte) */
|
||||
|
||||
#define LOW16( data ) (u_int16_t)(( data ) & 0177777 ) /* mask the lower 16 bits */
|
||||
#define LOW8( data ) (u_int8_t)(( data ) & 0377 ) /* mask the lower 8 bits */
|
||||
|
||||
#define CHG_CC_N( d ) if ((d) & SIGN ) \
|
||||
SET_CC_N(); \
|
||||
else \
|
||||
CLR_CC_N()
|
||||
|
||||
#define CHGB_CC_N( d ) if ((d) & SIGN_B ) \
|
||||
SET_CC_N(); \
|
||||
else \
|
||||
CLR_CC_N()
|
||||
|
||||
#define CHG_CC_Z( d ) if ( d ) \
|
||||
CLR_CC_Z(); \
|
||||
else \
|
||||
SET_CC_Z()
|
||||
|
||||
#define CHGB_CC_Z( d ) if ( LOW8( d )) \
|
||||
CLR_CC_Z(); \
|
||||
else \
|
||||
SET_CC_Z()
|
||||
|
||||
#define CHG_CC_C( d ) if ((d) & CARRY ) \
|
||||
SET_CC_C(); \
|
||||
else \
|
||||
CLR_CC_C()
|
||||
|
||||
#define CHG_CC_IC( d ) if ((d) & CARRY ) \
|
||||
CLR_CC_C(); \
|
||||
else \
|
||||
SET_CC_C()
|
||||
|
||||
#define CHGB_CC_IC( d ) if ((d) & CARRY_B ) \
|
||||
CLR_CC_C(); \
|
||||
else \
|
||||
SET_CC_C()
|
||||
|
||||
#define CHG_CC_V( d1, d2, d3 ) \
|
||||
if ((( d1 & SIGN ) == ( d2 & SIGN )) \
|
||||
&& (( d1 & SIGN ) != ( d3 & SIGN ))) \
|
||||
SET_CC_V(); \
|
||||
else \
|
||||
CLR_CC_V()
|
||||
|
||||
#define CHG_CC_VC( d1, d2, d3 ) \
|
||||
if ((( d1 & SIGN ) != ( d2 & SIGN )) \
|
||||
&& (( d2 & SIGN ) == ( d3 & SIGN ))) \
|
||||
SET_CC_V(); \
|
||||
else \
|
||||
CLR_CC_V()
|
||||
|
||||
#define CHG_CC_VS( d1, d2, d3 ) \
|
||||
if ((( d1 & SIGN ) != ( d2 & SIGN )) \
|
||||
&& (( d1 & SIGN ) == ( d3 & SIGN ))) \
|
||||
SET_CC_V(); \
|
||||
else \
|
||||
CLR_CC_V()
|
||||
|
||||
#define CHGB_CC_V( d1, d2, d3 ) \
|
||||
if ((( d1 & SIGN_B ) == ( d2 & SIGN_B )) \
|
||||
&& (( d1 & SIGN_B ) != ( d3 & SIGN_B ))) \
|
||||
SET_CC_V(); \
|
||||
else \
|
||||
CLR_CC_V()
|
||||
|
||||
#define CHGB_CC_VC(d1,d2,d3) \
|
||||
if ((( d1 & SIGN_B ) != ( d2 & SIGN_B )) \
|
||||
&& (( d2 & SIGN_B ) == ( d3 & SIGN_B ))) \
|
||||
SET_CC_V(); \
|
||||
else \
|
||||
CLR_CC_V()
|
||||
|
||||
#define CHG_CC_V_XOR_C_N() \
|
||||
if ((( CC_C ) && \
|
||||
( CC_N )) \
|
||||
|| ((!( CC_C )) && \
|
||||
( ! ( CC_N )))) \
|
||||
CLR_CC_V(); \
|
||||
else \
|
||||
SET_CC_V()
|
||||
|
||||
|
||||
/* Macros to read and write loctions in
|
||||
* main memory.
|
||||
*/
|
||||
|
||||
extern u_int16_t *adptr;
|
||||
|
||||
#define copylong(to,from) \
|
||||
buf = (char *) &(to); buf2 = (char *) &(from); \
|
||||
buf[0]=buf2[2]; buf[1]=buf2[3]; buf[2]=buf2[0]; buf[3]=buf2[1]
|
||||
|
||||
#ifndef EMUV1
|
||||
/* lli_word() - Load a word from the given ispace logical address. */
|
||||
#define lli_word(addr, word) \
|
||||
{ adptr= (u_int16_t *)&(ispace[addr]); word= *adptr; }
|
||||
|
||||
/* ll_word() - Load a word from the given logical address. */
|
||||
#define ll_word(addr, word) \
|
||||
{ adptr= (u_int16_t *)&(dspace[addr]); word= *adptr; }
|
||||
|
||||
/* sl_word() - Store a word at the given logical address. */
|
||||
#ifdef WRITEBASE
|
||||
#define sl_word(addr, word) \
|
||||
{ if ((u_int16_t)addr < dwrite_base) seg_fault(); \
|
||||
adptr= (u_int16_t *)&(dspace[addr]); *adptr= word; }
|
||||
#else
|
||||
#define sl_word(addr, word) \
|
||||
{ adptr= (u_int16_t *)&(dspace[addr]); *adptr= word; }
|
||||
#endif
|
||||
|
||||
/* lli_byte() - Load a byte from the given logical ispace address. */
|
||||
#define lli_byte(addr, byte) \
|
||||
byte = ispace[addr];
|
||||
|
||||
/* ll_byte() - Load a byte from the given logical address. */
|
||||
#define ll_byte(addr, byte) \
|
||||
byte = dspace[addr];
|
||||
|
||||
/* sl_byte() - Store a byte at the given logical address. */
|
||||
#ifdef WRITEBASE
|
||||
#define sl_byte(addr, byte) \
|
||||
{ if (addr < dwrite_base) seg_fault(); \
|
||||
dspace[addr]= byte; }
|
||||
#else
|
||||
#define sl_byte(addr, byte) \
|
||||
{ dspace[addr]= byte; }
|
||||
#endif
|
||||
#else
|
||||
/* These versions of the macros are required */
|
||||
/* because the KE11-A module is mapped into */
|
||||
/* a process' memory space in 1st Edition */
|
||||
#define KE11LO 0177300
|
||||
#define KE11HI 0177317
|
||||
|
||||
/* lli_word() - Load a word from the given ispace logical address. */
|
||||
#define lli_word(addr, word) \
|
||||
{ if ((Binary<IS_V3) && (addr>=KE11LO) && (addr<=KE11HI)) { \
|
||||
word= kell_word(addr); \
|
||||
} else { adptr= (u_int16_t *)&(ispace[addr]); word= *adptr; } \
|
||||
}
|
||||
|
||||
/* ll_word() - Load a word from the given logical address. */
|
||||
#define ll_word(addr, word) \
|
||||
{ if ((Binary<IS_V3) && (addr>=KE11LO) && (addr<=KE11HI)) { \
|
||||
word= kell_word(addr); \
|
||||
} else { adptr= (u_int16_t *)&(dspace[addr]); word= *adptr; } \
|
||||
}
|
||||
|
||||
/* sl_word() - Store a word at the given logical address. */
|
||||
#ifdef WRITEBASE
|
||||
#define sl_word(addr, word) \
|
||||
{ if ((u_int16_t)addr < dwrite_base) seg_fault(); \
|
||||
if ((Binary<IS_V3) && (addr>=KE11LO) && (addr<=KE11HI)) { \
|
||||
kesl_word(addr, word); \
|
||||
} else { adptr= (u_int16_t *)&(dspace[addr]); *adptr= word; } \
|
||||
}
|
||||
#else
|
||||
#define sl_word(addr, word) \
|
||||
{ if ((Binary<IS_V3) && (addr>=KE11LO) && (addr<=KE11HI)) { \
|
||||
kesl_word(addr, word); \
|
||||
} else { adptr= (u_int16_t *)&(dspace[addr]); *adptr= word; } \
|
||||
}
|
||||
#endif
|
||||
|
||||
/* lli_byte() - Load a byte from the given logical ispace address. */
|
||||
#define lli_byte(addr, byte) \
|
||||
byte = ispace[addr];
|
||||
|
||||
/* ll_byte() - Load a byte from the given logical address. */
|
||||
#define ll_byte(addr, byte) \
|
||||
{ if ((Binary<IS_V3) && (addr>=KE11LO) && (addr<=KE11HI)) { \
|
||||
byte= kell_byte(addr); \
|
||||
} else byte = dspace[addr]; \
|
||||
}
|
||||
|
||||
/* sl_byte() - Store a byte at the given logical address. */
|
||||
#ifdef WRITEBASE
|
||||
#define sl_byte(addr, byte) \
|
||||
{ if (addr < dwrite_base) seg_fault(); \
|
||||
if ((Binary<IS_V3) && (addr>=KE11LO) && (addr<=KE11HI)) { \
|
||||
kesl_byte(addr, byte); \
|
||||
} else dspace[addr]= byte; \
|
||||
}
|
||||
#else
|
||||
#define sl_byte(addr, byte) \
|
||||
{ if ((Binary<IS_V3) && (addr>=KE11LO) && (addr<=KE11HI)) { \
|
||||
kesl_byte(addr, byte); \
|
||||
} else dspace[addr]= byte; \
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
/* aout.c */
|
||||
int load_a_out P((const char *file, const char *origpath, int want_env))
|
||||
/*@globals errno,stdout,stderr; @*/ ;
|
||||
#ifdef EMU211
|
||||
void do_bsd_overlay P((void));
|
||||
#endif
|
||||
|
||||
/* branch.c */
|
||||
void br P((void));
|
||||
void blos P((void));
|
||||
void bge P((void));
|
||||
void blt P((void));
|
||||
void ble P((void));
|
||||
void bgt P((void));
|
||||
void jmp P((void));
|
||||
void jsr P((void));
|
||||
void rts P((void));
|
||||
void bne P((void));
|
||||
void beq P((void));
|
||||
void bpl P((void));
|
||||
void bmi P((void));
|
||||
void bhi P((void));
|
||||
void bvc P((void));
|
||||
void bvs P((void));
|
||||
void bcc P((void));
|
||||
void bcs P((void));
|
||||
void scc P((void));
|
||||
void ccc P((void));
|
||||
void sob P((void));
|
||||
void mfps P((void));
|
||||
void mtps P((void));
|
||||
void mfpi P((void));
|
||||
void mtpi P((void));
|
||||
void ash P((void));
|
||||
void mul P((void));
|
||||
void divide P((void));
|
||||
void ashc P((void));
|
||||
void xor P((void));
|
||||
|
||||
/* double.c */
|
||||
void mov P((void));
|
||||
void movsreg P((void));
|
||||
void movsreg1 P((void));
|
||||
void movsreg1pc P((void));
|
||||
void cmp P((void));
|
||||
void add P((void));
|
||||
void sub P((void));
|
||||
void bit P((void));
|
||||
void bic P((void));
|
||||
void bis P((void));
|
||||
void movb P((void));
|
||||
void cmpb P((void));
|
||||
void bitb P((void));
|
||||
void bicb P((void));
|
||||
void bisb P((void));
|
||||
|
||||
/* cpu.c */
|
||||
void run P((void));
|
||||
void sim_init P((void));
|
||||
void bus_error P((int));
|
||||
void seg_fault P((void));
|
||||
void waiti P((void));
|
||||
void halt P((void));
|
||||
void iot P((void));
|
||||
void emt P((void));
|
||||
void bpt P((void));
|
||||
void fis P((void));
|
||||
void illegal P((void));
|
||||
void not_impl P((void));
|
||||
void mark P((void));
|
||||
void mfpd P((void));
|
||||
void mtpd P((void));
|
||||
void trap P((void));
|
||||
void bad_FP_reg P((void));
|
||||
void sigcatcher P((int sig));
|
||||
|
||||
/* ea.c */
|
||||
void load_ea P((void));
|
||||
void pop P((void));
|
||||
void push P((void));
|
||||
void loadb_dst P((void));
|
||||
void loadb_src P((void));
|
||||
void storeb_dst P((void));
|
||||
void storeb_dst_2 P((void));
|
||||
void loadp_dst P((void));
|
||||
void storep_dst P((void));
|
||||
void load_src P((void));
|
||||
void store_dst P((void));
|
||||
void load_dst P((void));
|
||||
void store_dst_2 P((void));
|
||||
|
||||
/* fp.c */
|
||||
void fpset P((void));
|
||||
void ldf P((void));
|
||||
void stf P((void));
|
||||
void clrf P((void));
|
||||
void addf P((void));
|
||||
void subf P((void));
|
||||
void negf P((void));
|
||||
void absf P((void));
|
||||
void mulf P((void));
|
||||
void moddf P((void));
|
||||
void divf P((void));
|
||||
void cmpf P((void));
|
||||
void tstf P((void));
|
||||
void ldfps P((void));
|
||||
void stfps P((void));
|
||||
void lcdif P((void));
|
||||
void stcfi P((void));
|
||||
void stexp P((void));
|
||||
void stcdf P((void));
|
||||
void ldcdf P((void));
|
||||
void stst P((void));
|
||||
void ldexpp P((void));
|
||||
|
||||
/* itab.c */
|
||||
void dositab0 P((void));
|
||||
void dositab1 P((void));
|
||||
|
||||
/* main.c */
|
||||
int main P((int argc, char **argv));
|
||||
void usage P((void));
|
||||
char * xlate_filename P((char *name));
|
||||
void set_apout_root P((char *dirname));
|
||||
|
||||
/* magic.c */
|
||||
int special_magic P((u_int16_t *cptr));
|
||||
|
||||
/* single.c */
|
||||
void adc P((void));
|
||||
void asl P((void));
|
||||
void asr P((void));
|
||||
void clr P((void));
|
||||
void com P((void));
|
||||
void dec P((void));
|
||||
void inc P((void));
|
||||
void neg P((void));
|
||||
void rol P((void));
|
||||
void ror P((void));
|
||||
void sbc P((void));
|
||||
void swabi P((void));
|
||||
void sxt P((void));
|
||||
void tst P((void));
|
||||
void tstb P((void));
|
||||
void aslb P((void));
|
||||
void asrb P((void));
|
||||
void clrb P((void));
|
||||
void comb P((void));
|
||||
void decb P((void));
|
||||
void incb P((void));
|
||||
void negb P((void));
|
||||
void rolb P((void));
|
||||
void rorb P((void));
|
||||
void adcb P((void));
|
||||
void sbcb P((void));
|
||||
|
||||
/* v6trap.c */
|
||||
void v6trap P((void));
|
||||
|
||||
/* v7trap.c */
|
||||
void v7trap P((void));
|
||||
|
||||
/* v1trap.c */
|
||||
void v1trap P((void));
|
||||
|
||||
/* bsdtrap.c */
|
||||
#ifdef EMU211
|
||||
void bsdtrap P((void)) /*@globals errno,stdout,stderr; @*/ ;
|
||||
|
||||
/* bsd_ioctl.h */
|
||||
int trap_ioctl P((void));
|
||||
|
||||
/* bsd_signal.c */
|
||||
void set_bsdsig_dfl P((void));
|
||||
int do_sigaction P((int sig, int a, int oa));
|
||||
#endif
|
||||
|
||||
/* ke11a.c */
|
||||
#ifdef EMUV1
|
||||
int16_t kell_word P((u_int16_t addr));
|
||||
void kesl_word P((u_int16_t addr, u_int16_t word));
|
||||
int8_t kell_byte P((u_int16_t addr));
|
||||
void kesl_byte P((u_int16_t addr, u_int8_t byte));
|
||||
void set_SR P((void));
|
||||
#endif
|
||||
|
||||
#undef P
|
||||
280
tools/apout/double.c
Normal file
280
tools/apout/double.c
Normal file
@@ -0,0 +1,280 @@
|
||||
/* double.c - Double operand instructions.
|
||||
*
|
||||
* $Revision: 2.11 $
|
||||
* $Date: 1999/12/27 10:19:40 $
|
||||
*/
|
||||
#include "defines.h"
|
||||
|
||||
static u_int32_t templong;
|
||||
|
||||
|
||||
/* mov() - Move Instruction. Move operations with registers as the source
|
||||
* and/or destination have been inlined. */
|
||||
void
|
||||
mov()
|
||||
{
|
||||
|
||||
if (SRC_MODE) {
|
||||
load_src(); dstword=srcword;
|
||||
} else {
|
||||
dstword = regs[SRC_REG];
|
||||
}
|
||||
|
||||
CHG_CC_N(dstword);
|
||||
CHG_CC_Z(dstword);
|
||||
CLR_CC_V();
|
||||
|
||||
if (DST_MODE) {
|
||||
store_dst();
|
||||
} else {
|
||||
regs[DST_REG] = dstword;
|
||||
}
|
||||
}
|
||||
|
||||
/* movsreg(), movsreg1() and movsreg1pc() can all be replaced with
|
||||
* mov() above. I've broken them out in an attempt to improve
|
||||
* performance.
|
||||
*/
|
||||
void
|
||||
movsreg()
|
||||
{
|
||||
dstword = regs[SRC_REG];
|
||||
CHG_CC_N(dstword);
|
||||
CHG_CC_Z(dstword);
|
||||
CLR_CC_V();
|
||||
|
||||
if (DST_MODE) {
|
||||
store_dst();
|
||||
} else {
|
||||
regs[DST_REG] = dstword;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
movsreg1()
|
||||
{
|
||||
ll_word(regs[SRC_REG], dstword);
|
||||
CHG_CC_N(dstword);
|
||||
CHG_CC_Z(dstword);
|
||||
CLR_CC_V();
|
||||
|
||||
if (DST_MODE) {
|
||||
store_dst();
|
||||
} else {
|
||||
regs[DST_REG] = dstword;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
movsreg1pc()
|
||||
{
|
||||
lli_word(regs[PC], dstword)
|
||||
CHG_CC_N(dstword);
|
||||
CHG_CC_Z(dstword);
|
||||
CLR_CC_V();
|
||||
|
||||
if (DST_MODE) {
|
||||
store_dst();
|
||||
} else {
|
||||
regs[DST_REG] = dstword;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* cmp() - Compare Instruction. */
|
||||
void
|
||||
cmp()
|
||||
{
|
||||
load_src();
|
||||
load_dst();
|
||||
|
||||
tmpword = ~dstword;
|
||||
templong = ((u_int32_t) srcword) + ((u_int32_t) (tmpword)) + 1;
|
||||
tmpword = LOW16(templong);
|
||||
|
||||
CHG_CC_N(tmpword);
|
||||
CHG_CC_Z(tmpword);
|
||||
CHG_CC_VC(srcword, dstword, tmpword); /* was CHG_CC_V */
|
||||
CHG_CC_IC(templong);
|
||||
}
|
||||
|
||||
|
||||
/* add() - Add Instruction. */
|
||||
void
|
||||
add()
|
||||
{
|
||||
load_src();
|
||||
load_dst();
|
||||
|
||||
templong = ((u_int32_t) srcword) + ((u_int32_t) dstword);
|
||||
tmpword = LOW16(templong);
|
||||
|
||||
CHG_CC_N(tmpword);
|
||||
CHG_CC_Z(tmpword);
|
||||
CHG_CC_V(srcword, dstword, tmpword);
|
||||
CHG_CC_C(templong);
|
||||
|
||||
dstword=tmpword; store_dst_2();
|
||||
}
|
||||
|
||||
/* Subtract Instruction. */
|
||||
void
|
||||
sub()
|
||||
{
|
||||
load_src();
|
||||
load_dst();
|
||||
|
||||
tmpword = ~srcword;
|
||||
templong = ((u_int32_t) dstword) + ((u_int32_t) tmpword) + 1;
|
||||
tmpword = LOW16(templong);
|
||||
|
||||
CHG_CC_N(tmpword);
|
||||
CHG_CC_Z(tmpword);
|
||||
CHG_CC_VS(srcword, dstword, tmpword); /* was CHG_CC_V */
|
||||
CHG_CC_IC(templong);
|
||||
|
||||
dstword=tmpword; store_dst_2();
|
||||
}
|
||||
|
||||
|
||||
/* bit() - Bit Test Instruction. */
|
||||
void
|
||||
bit()
|
||||
{
|
||||
load_src();
|
||||
load_dst();
|
||||
|
||||
dstword = srcword & dstword;
|
||||
|
||||
CHG_CC_N(dstword);
|
||||
CHG_CC_Z(dstword);
|
||||
CLR_CC_V();
|
||||
}
|
||||
|
||||
/* bic() - Bit Clear Instruction. */
|
||||
void
|
||||
bic()
|
||||
{
|
||||
load_src();
|
||||
load_dst();
|
||||
|
||||
dstword = (~srcword) & dstword;
|
||||
CHG_CC_N(dstword);
|
||||
CHG_CC_Z(dstword);
|
||||
CLR_CC_V();
|
||||
|
||||
store_dst_2();
|
||||
}
|
||||
|
||||
|
||||
/* bis() - Bit Set Instruction. */
|
||||
void
|
||||
bis()
|
||||
{
|
||||
load_src();
|
||||
load_dst();
|
||||
|
||||
dstword = srcword | dstword;
|
||||
|
||||
CHG_CC_N(dstword);
|
||||
CHG_CC_Z(dstword);
|
||||
CLR_CC_V();
|
||||
|
||||
store_dst_2();
|
||||
}
|
||||
|
||||
/* movb() - Move Byte Instruction. Move operations with registers as the
|
||||
* source and/or destination have been inlined. */
|
||||
void
|
||||
movb()
|
||||
{
|
||||
if (SRC_MODE) {
|
||||
loadb_src();
|
||||
} else {
|
||||
srcbyte = LOW8(regs[SRC_REG]);
|
||||
}
|
||||
|
||||
CHGB_CC_N(srcbyte);
|
||||
CHGB_CC_Z(srcbyte);
|
||||
CLR_CC_V();
|
||||
|
||||
/* move byte to a register causes sign extension */
|
||||
|
||||
if (DST_MODE) {
|
||||
storeb_dst();
|
||||
} else {
|
||||
if (srcbyte & SIGN_B)
|
||||
regs[DST_REG] = (u_int16_t)0177400 + (u_int16_t)srcbyte;
|
||||
else
|
||||
regs[DST_REG] = (u_int16_t)srcbyte;
|
||||
}
|
||||
}
|
||||
|
||||
/* cmpb() - Compare Byte Instruction. */
|
||||
void
|
||||
cmpb()
|
||||
{
|
||||
u_int8_t data3;
|
||||
|
||||
loadb_src();
|
||||
loadb_dst();
|
||||
|
||||
data3 = (u_int8_t)~dstbyte;
|
||||
tmpword = ((u_int16_t) srcbyte) + ((u_int16_t) (data3)) + 1;
|
||||
data3 = LOW8(tmpword);
|
||||
|
||||
CHGB_CC_N(data3);
|
||||
CHGB_CC_Z(data3);
|
||||
CHGB_CC_VC(srcbyte, dstbyte, data3);
|
||||
CHGB_CC_IC(tmpword);
|
||||
}
|
||||
|
||||
|
||||
/* bitb() - Bit Test Byte Instruction. */
|
||||
void
|
||||
bitb()
|
||||
{
|
||||
loadb_src();
|
||||
loadb_dst();
|
||||
|
||||
dstbyte = srcbyte & dstbyte;
|
||||
|
||||
CHGB_CC_N(dstbyte);
|
||||
CHGB_CC_Z(dstbyte);
|
||||
CLR_CC_V();
|
||||
}
|
||||
|
||||
/* bicb() - Bit Clear Byte Instruction. */
|
||||
void
|
||||
bicb()
|
||||
{
|
||||
loadb_src();
|
||||
loadb_dst();
|
||||
|
||||
dstbyte = (u_int8_t)((~srcbyte) & dstbyte);
|
||||
|
||||
CHGB_CC_N(dstbyte);
|
||||
CHGB_CC_Z(dstbyte);
|
||||
CLR_CC_V();
|
||||
|
||||
storeb_dst_2();
|
||||
}
|
||||
|
||||
|
||||
/* bisb() - Bit Set Byte Instruction. */
|
||||
|
||||
void
|
||||
bisb()
|
||||
{
|
||||
loadb_src();
|
||||
loadb_dst();
|
||||
|
||||
dstbyte = srcbyte | dstbyte;
|
||||
|
||||
CHGB_CC_N(dstbyte);
|
||||
CHGB_CC_Z(dstbyte);
|
||||
CLR_CC_V();
|
||||
|
||||
storeb_dst_2();
|
||||
}
|
||||
588
tools/apout/ea.c
Normal file
588
tools/apout/ea.c
Normal file
@@ -0,0 +1,588 @@
|
||||
/* ea.c - Calculate, load, and store using the proper effective address as
|
||||
* specified by the current instruction. Also push and pop stack operations.
|
||||
*
|
||||
* $Revision: 2.17 $
|
||||
* $Date: 1999/09/17 05:11:10 $
|
||||
*/
|
||||
#include "defines.h"
|
||||
|
||||
void
|
||||
load_ea(void)
|
||||
{
|
||||
u_int16_t indirect;
|
||||
|
||||
switch (DST_MODE) {
|
||||
case 0:
|
||||
illegal();
|
||||
return;
|
||||
case 1:
|
||||
dstword = regs[DST_REG];
|
||||
return;
|
||||
case 2:
|
||||
dstword = regs[DST_REG]; /* this is wrong for 11/34 */
|
||||
regs[DST_REG] += 2;
|
||||
return;
|
||||
case 3:
|
||||
indirect = regs[DST_REG]; /* this is wrong for 11/34 */
|
||||
regs[DST_REG] += 2;
|
||||
lli_word(indirect, dstword);
|
||||
return;
|
||||
case 4:
|
||||
regs[DST_REG] -= 2;
|
||||
dstword = regs[DST_REG];
|
||||
return;
|
||||
case 5:
|
||||
regs[DST_REG] -= 2;
|
||||
indirect = regs[DST_REG];
|
||||
lli_word(indirect, dstword);
|
||||
return;
|
||||
case 6:
|
||||
lli_word(regs[PC], indirect);
|
||||
regs[PC] += 2;
|
||||
dstword = regs[DST_REG] + indirect;
|
||||
return;
|
||||
case 7:
|
||||
lli_word(regs[PC], indirect);
|
||||
regs[PC] += 2;
|
||||
indirect = regs[DST_REG] + indirect;
|
||||
ll_word(indirect, dstword);
|
||||
return;
|
||||
}
|
||||
illegal();
|
||||
}
|
||||
|
||||
|
||||
INLINE void
|
||||
pop(void)
|
||||
{
|
||||
ll_word(regs[SP], dstword);
|
||||
regs[SP] += 2;
|
||||
}
|
||||
|
||||
|
||||
INLINE void
|
||||
push(void)
|
||||
{
|
||||
regs[SP] -= 2;
|
||||
sl_word(regs[SP], srcword);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
loadb_dst(void)
|
||||
{
|
||||
u_int16_t addr, indirect;
|
||||
|
||||
switch (DST_MODE) {
|
||||
case 0:
|
||||
dstbyte = (u_int8_t)(regs[DST_REG] & 0377);
|
||||
return;
|
||||
case 1:
|
||||
addr = regs[DST_REG];
|
||||
ea_addr = addr;
|
||||
if (DST_REG == PC) {
|
||||
lli_byte(addr, dstbyte)
|
||||
} else {
|
||||
ll_byte(addr, dstbyte);
|
||||
}
|
||||
return;
|
||||
case 2:
|
||||
addr = regs[DST_REG];
|
||||
ea_addr = addr;
|
||||
if (DST_REG == PC) {
|
||||
lli_byte(addr, dstbyte)
|
||||
} else {
|
||||
ll_byte(addr, dstbyte);
|
||||
}
|
||||
if (DST_REG >= 6)
|
||||
regs[DST_REG] += 2;
|
||||
else
|
||||
regs[DST_REG] += 1;
|
||||
return;
|
||||
case 3:
|
||||
indirect = regs[DST_REG];
|
||||
if (DST_REG == PC) {
|
||||
lli_word(indirect, addr)
|
||||
} else {
|
||||
ll_word(indirect, addr);
|
||||
}
|
||||
ea_addr = addr;
|
||||
ll_byte(addr, dstbyte);
|
||||
regs[DST_REG] += 2;
|
||||
return;
|
||||
case 4:
|
||||
if (DST_REG >= 6)
|
||||
regs[DST_REG] -= 2;
|
||||
else
|
||||
regs[DST_REG] -= 1;
|
||||
addr = regs[DST_REG];
|
||||
ea_addr = addr;
|
||||
ll_byte(addr, dstbyte);
|
||||
return;
|
||||
case 5:
|
||||
regs[DST_REG] -= 2;
|
||||
indirect = regs[DST_REG];
|
||||
ll_word(indirect, addr);
|
||||
ea_addr = addr;
|
||||
ll_byte(addr, dstbyte);
|
||||
return;
|
||||
case 6:
|
||||
lli_word(regs[PC], indirect);
|
||||
regs[PC] += 2;
|
||||
addr = regs[DST_REG] + indirect;
|
||||
ea_addr = addr;
|
||||
ll_byte(addr, dstbyte);
|
||||
return;
|
||||
case 7:
|
||||
lli_word(regs[PC], indirect);
|
||||
regs[PC] += 2;
|
||||
indirect = regs[DST_REG] + indirect;
|
||||
ll_word(indirect, addr);
|
||||
ea_addr = addr;
|
||||
ll_byte(addr, dstbyte);
|
||||
return;
|
||||
}
|
||||
illegal();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
loadb_src(void)
|
||||
{
|
||||
u_int16_t addr, indirect;
|
||||
|
||||
switch (SRC_MODE) {
|
||||
case 0:
|
||||
srcbyte = (u_int8_t)(regs[SRC_REG] & 0377);
|
||||
return;
|
||||
case 1:
|
||||
addr = regs[SRC_REG];
|
||||
if (SRC_REG == PC) {
|
||||
lli_byte(addr, srcbyte);
|
||||
} else {
|
||||
ll_byte(addr, srcbyte);
|
||||
}
|
||||
return;
|
||||
case 2:
|
||||
addr = regs[SRC_REG];
|
||||
if (SRC_REG == PC) {
|
||||
lli_byte(addr, srcbyte);
|
||||
} else {
|
||||
ll_byte(addr, srcbyte);
|
||||
}
|
||||
if (SRC_REG >= 6)
|
||||
regs[SRC_REG] += 2;
|
||||
else
|
||||
regs[SRC_REG] += 1;
|
||||
return;
|
||||
case 3:
|
||||
indirect = regs[SRC_REG];
|
||||
if (SRC_REG == PC) {
|
||||
lli_word(indirect, addr)
|
||||
} else {
|
||||
ll_word(indirect, addr);
|
||||
}
|
||||
ll_byte(addr, srcbyte);
|
||||
regs[SRC_REG] += 2;
|
||||
return;
|
||||
case 4:
|
||||
if (SRC_REG >= 6)
|
||||
regs[SRC_REG] -= 2;
|
||||
else
|
||||
regs[SRC_REG] -= 1;
|
||||
addr = regs[SRC_REG];
|
||||
ll_byte(addr, srcbyte);
|
||||
return;
|
||||
case 5:
|
||||
regs[SRC_REG] -= 2;
|
||||
indirect = regs[SRC_REG];
|
||||
ll_word(indirect, addr);
|
||||
ll_byte(addr, srcbyte);
|
||||
return;
|
||||
case 6:
|
||||
lli_word(regs[PC], indirect);
|
||||
regs[PC] += 2;
|
||||
addr = regs[SRC_REG] + indirect;
|
||||
ll_byte(addr, srcbyte);
|
||||
return;
|
||||
case 7:
|
||||
lli_word(regs[PC], indirect);
|
||||
regs[PC] += 2;
|
||||
indirect = regs[SRC_REG] + indirect;
|
||||
ll_word(indirect, addr);
|
||||
ll_byte(addr, srcbyte);
|
||||
return;
|
||||
}
|
||||
illegal();
|
||||
}
|
||||
|
||||
void
|
||||
storeb_dst(void)
|
||||
{
|
||||
u_int16_t addr, indirect;
|
||||
|
||||
switch (DST_MODE) {
|
||||
case 0:
|
||||
regs[DST_REG]&= 0xff00;
|
||||
regs[DST_REG]|= srcbyte;
|
||||
return;
|
||||
case 1:
|
||||
addr = regs[DST_REG];
|
||||
sl_byte(addr, srcbyte);
|
||||
return;
|
||||
case 2:
|
||||
addr = regs[DST_REG];
|
||||
sl_byte(addr, srcbyte);
|
||||
if (DST_REG >= 6)
|
||||
regs[DST_REG] += 2;
|
||||
else
|
||||
regs[DST_REG] += 1;
|
||||
return;
|
||||
case 3:
|
||||
indirect = regs[DST_REG];
|
||||
ll_word(indirect, addr);
|
||||
sl_byte(addr, srcbyte);
|
||||
regs[DST_REG] += 2;
|
||||
return;
|
||||
case 4:
|
||||
if (DST_REG >= 6) /* xyz */
|
||||
regs[DST_REG] -= 2;
|
||||
else
|
||||
regs[DST_REG] -= 1;
|
||||
addr = regs[DST_REG];
|
||||
sl_byte(addr, srcbyte);
|
||||
return;
|
||||
case 5:
|
||||
regs[DST_REG] -= 2;
|
||||
indirect = regs[DST_REG];
|
||||
ll_word(indirect, addr);
|
||||
sl_byte(addr, srcbyte);
|
||||
return;
|
||||
case 6:
|
||||
lli_word(regs[PC], indirect);
|
||||
regs[PC] += 2;
|
||||
addr = regs[DST_REG] + indirect;
|
||||
sl_byte(addr, srcbyte);
|
||||
return;
|
||||
case 7:
|
||||
lli_word(regs[PC], indirect);
|
||||
regs[PC] += 2;
|
||||
indirect = regs[DST_REG] + indirect;
|
||||
ll_word(indirect, addr);
|
||||
sl_byte(addr, srcbyte);
|
||||
return;
|
||||
}
|
||||
illegal();
|
||||
}
|
||||
|
||||
|
||||
INLINE void
|
||||
storeb_dst_2(void)
|
||||
{
|
||||
if (DST_MODE == 0) {
|
||||
regs[DST_REG]&= 0xff00;
|
||||
regs[DST_REG]|= dstbyte;
|
||||
return;
|
||||
}
|
||||
sl_byte(ea_addr, dstbyte);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
loadp_dst(void)
|
||||
{
|
||||
u_int16_t addr, indirect;
|
||||
|
||||
switch (DST_MODE) {
|
||||
case 0:
|
||||
srcword = regs[DST_REG];
|
||||
return;
|
||||
case 1:
|
||||
addr = regs[DST_REG];
|
||||
ll_word(addr, srcword);
|
||||
return;
|
||||
case 2:
|
||||
addr = regs[DST_REG];
|
||||
ll_word(addr, srcword);
|
||||
regs[DST_REG] += 2;
|
||||
return;
|
||||
case 3:
|
||||
indirect = regs[DST_REG];
|
||||
ll_word(indirect, addr);
|
||||
ll_word(addr, srcword);
|
||||
regs[DST_REG] += 2;
|
||||
return;
|
||||
case 4:
|
||||
regs[DST_REG] -= 2;
|
||||
addr = regs[DST_REG];
|
||||
ll_word(addr, srcword);
|
||||
return;
|
||||
case 5:
|
||||
regs[DST_REG] -= 2;
|
||||
indirect = regs[DST_REG];
|
||||
ll_word(indirect, addr);
|
||||
ll_word(addr, srcword);
|
||||
return;
|
||||
case 6:
|
||||
lli_word(regs[PC], indirect);
|
||||
regs[PC] += 2;
|
||||
addr = regs[DST_REG] + indirect;
|
||||
if (DST_REG == PC)
|
||||
lli_word(addr, srcword)
|
||||
else
|
||||
ll_word(addr, srcword);
|
||||
return;
|
||||
case 7:
|
||||
not_impl();
|
||||
}
|
||||
illegal();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
storep_dst(void)
|
||||
{
|
||||
u_int16_t addr, indirect;
|
||||
|
||||
switch (DST_MODE) {
|
||||
case 0:
|
||||
regs[DST_REG] = dstword;
|
||||
return;
|
||||
case 1:
|
||||
addr = regs[DST_REG];
|
||||
sl_word(addr, dstword);
|
||||
return;
|
||||
case 2:
|
||||
addr = regs[DST_REG];
|
||||
sl_word(addr, dstword);
|
||||
regs[DST_REG] += 2;
|
||||
return;
|
||||
case 3:
|
||||
indirect = regs[DST_REG];
|
||||
ll_word(indirect, addr);
|
||||
sl_word(addr, dstword);
|
||||
regs[DST_REG] += 2;
|
||||
return;
|
||||
case 4:
|
||||
regs[DST_REG] -= 2;
|
||||
addr = regs[DST_REG];
|
||||
sl_word(addr, dstword);
|
||||
return;
|
||||
case 5:
|
||||
regs[DST_REG] -= 2;
|
||||
indirect = regs[DST_REG];
|
||||
ll_word(indirect, addr);
|
||||
sl_word(addr, dstword);
|
||||
return;
|
||||
case 6:
|
||||
lli_word(regs[PC], indirect);
|
||||
regs[PC] += 2;
|
||||
addr = regs[DST_REG] + indirect;
|
||||
sl_word(addr, dstword);
|
||||
return;
|
||||
case 7:
|
||||
not_impl();
|
||||
}
|
||||
illegal();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
load_src(void)
|
||||
{
|
||||
u_int16_t addr, indirect;
|
||||
|
||||
switch (SRC_MODE) {
|
||||
case 0:
|
||||
srcword = regs[SRC_REG];
|
||||
return;
|
||||
case 1:
|
||||
addr = regs[SRC_REG];
|
||||
if (SRC_REG == PC) {
|
||||
lli_word(addr, srcword)
|
||||
} else {
|
||||
ll_word(addr, srcword);
|
||||
}
|
||||
return;
|
||||
case 2:
|
||||
addr = regs[SRC_REG];
|
||||
if (SRC_REG == PC) {
|
||||
lli_word(addr, srcword)
|
||||
} else {
|
||||
ll_word(addr, srcword);
|
||||
}
|
||||
regs[SRC_REG] += 2;
|
||||
return;
|
||||
case 3:
|
||||
indirect = regs[SRC_REG];
|
||||
if (SRC_REG == PC) {
|
||||
lli_word(indirect, addr)
|
||||
} else {
|
||||
ll_word(indirect, addr);
|
||||
}
|
||||
regs[SRC_REG] += 2; /* is this right ? */
|
||||
ll_word(addr, srcword);
|
||||
return;
|
||||
case 4:
|
||||
regs[SRC_REG] -= 2;
|
||||
addr = regs[SRC_REG];
|
||||
ll_word(addr, srcword);
|
||||
return;
|
||||
case 5:
|
||||
regs[SRC_REG] -= 2;
|
||||
indirect = regs[SRC_REG];
|
||||
ll_word(indirect, addr);
|
||||
ll_word(addr, srcword);
|
||||
return;
|
||||
case 6:
|
||||
lli_word(regs[PC], indirect);
|
||||
regs[PC] += 2;
|
||||
addr = regs[SRC_REG] + indirect;
|
||||
ll_word(addr, srcword);
|
||||
return;
|
||||
case 7:
|
||||
lli_word(regs[PC], indirect);
|
||||
regs[PC] += 2;
|
||||
indirect = regs[SRC_REG] + indirect;
|
||||
ll_word(indirect, addr);
|
||||
ll_word(addr, srcword);
|
||||
return;
|
||||
}
|
||||
illegal();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
store_dst(void)
|
||||
{
|
||||
u_int16_t addr, indirect;
|
||||
|
||||
switch (DST_MODE) {
|
||||
case 0:
|
||||
regs[DST_REG] = dstword;
|
||||
return;
|
||||
case 1:
|
||||
addr = regs[DST_REG];
|
||||
sl_word(addr, dstword);
|
||||
return;
|
||||
case 2:
|
||||
addr = regs[DST_REG];
|
||||
sl_word(addr, dstword);
|
||||
regs[DST_REG] += 2;
|
||||
return;
|
||||
case 3:
|
||||
indirect = regs[DST_REG];
|
||||
ll_word(indirect, addr);
|
||||
regs[DST_REG] += 2; /* is this right ? */
|
||||
sl_word(addr, dstword);
|
||||
return;
|
||||
case 4:
|
||||
regs[DST_REG] -= 2;
|
||||
addr = regs[DST_REG];
|
||||
sl_word(addr, dstword);
|
||||
return;
|
||||
case 5:
|
||||
regs[DST_REG] -= 2;
|
||||
indirect = regs[DST_REG];
|
||||
ll_word(indirect, addr);
|
||||
sl_word(addr, dstword);
|
||||
return;
|
||||
case 6:
|
||||
lli_word(regs[PC], indirect);
|
||||
regs[PC] += 2;
|
||||
addr = regs[DST_REG] + indirect;
|
||||
sl_word(addr, dstword);
|
||||
return;
|
||||
case 7:
|
||||
lli_word(regs[PC], indirect);
|
||||
regs[PC] += 2;
|
||||
indirect = regs[DST_REG] + indirect;
|
||||
ll_word(indirect, addr);
|
||||
sl_word(addr, dstword);
|
||||
return;
|
||||
}
|
||||
illegal();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
load_dst(void)
|
||||
{
|
||||
u_int16_t addr, indirect;
|
||||
|
||||
switch (DST_MODE) {
|
||||
case 0:
|
||||
dstword = regs[DST_REG];
|
||||
return;
|
||||
case 1:
|
||||
addr = regs[DST_REG];
|
||||
ea_addr = addr;
|
||||
if (DST_REG == PC) {
|
||||
lli_word(addr, dstword)
|
||||
} else {
|
||||
ll_word(addr, dstword);
|
||||
}
|
||||
return;
|
||||
case 2:
|
||||
addr = regs[DST_REG];
|
||||
ea_addr = addr;
|
||||
if (DST_REG == PC) {
|
||||
lli_word(addr, dstword)
|
||||
} else {
|
||||
ll_word(addr, dstword);
|
||||
}
|
||||
regs[DST_REG] += 2;
|
||||
return;
|
||||
case 3:
|
||||
indirect = regs[DST_REG];
|
||||
if (DST_REG == PC) {
|
||||
lli_word(indirect, addr)
|
||||
} else {
|
||||
ll_word(indirect, addr);
|
||||
}
|
||||
ea_addr = addr;
|
||||
ll_word(addr, dstword);
|
||||
regs[DST_REG] += 2;
|
||||
return;
|
||||
case 4:
|
||||
regs[DST_REG] -= 2;
|
||||
addr = regs[DST_REG];
|
||||
ea_addr = addr;
|
||||
ll_word(addr, dstword);
|
||||
return;
|
||||
case 5:
|
||||
regs[DST_REG] -= 2;
|
||||
indirect = regs[DST_REG];
|
||||
ll_word(indirect, addr);
|
||||
ea_addr = addr;
|
||||
ll_word(addr, dstword);
|
||||
return;
|
||||
case 6:
|
||||
lli_word(regs[PC], indirect);
|
||||
regs[PC] += 2;
|
||||
addr = regs[DST_REG] + indirect;
|
||||
ea_addr = addr;
|
||||
ll_word(addr, dstword);
|
||||
return;
|
||||
case 7:
|
||||
lli_word(regs[PC], indirect);
|
||||
regs[PC] += 2;
|
||||
indirect = regs[DST_REG] + indirect;
|
||||
ll_word(indirect, addr);
|
||||
ea_addr = addr;
|
||||
ll_word(addr, dstword);
|
||||
return;
|
||||
}
|
||||
illegal();
|
||||
}
|
||||
|
||||
|
||||
INLINE void
|
||||
store_dst_2(void)
|
||||
{
|
||||
if (DST_MODE == 0) {
|
||||
regs[DST_REG] = dstword;
|
||||
return;
|
||||
}
|
||||
sl_word(ea_addr, dstword);
|
||||
}
|
||||
616
tools/apout/fp.c
Normal file
616
tools/apout/fp.c
Normal file
@@ -0,0 +1,616 @@
|
||||
/* fp.c - PDP-11 floating point operations
|
||||
*
|
||||
* $Revision: 2.23 $
|
||||
* $Date: 1999/12/30 02:11:16 $
|
||||
*/
|
||||
|
||||
/* The floating-point emulation code here is just enough to allow
|
||||
* 2.11BSD binaries to run. There is only emulation of PDP-11
|
||||
* 32-bit floats: the extra 32-bits of precision in PDP-11 doubles
|
||||
* goes unused. As well, I don't try to emulate any of the FP errors.
|
||||
*
|
||||
* If this is a problem, then feel free to correct it.
|
||||
*/
|
||||
#include "defines.h"
|
||||
#include <math.h>
|
||||
float powf(float x, float y); /* FreeBSD 3.X no longer defines this */
|
||||
|
||||
#define XUL 170141163178059628080016879768632819712.0 /* Biggest float */
|
||||
|
||||
typedef struct {
|
||||
unsigned frac1:7; /* Fractional part of number */
|
||||
unsigned exp: 8; /* Excess 128 notation: exponenents -128 to +127 */
|
||||
/* become 0 to 255 */
|
||||
unsigned sign: 1; /* If 1, float is negative */
|
||||
unsigned frac2: 16; /* Fractional part of number */
|
||||
} pdpfloat;
|
||||
|
||||
|
||||
/* Internal variables */
|
||||
FLOAT fregs[8]; /* Yes, I know there are only 6, it makes it easier */
|
||||
int FPC=0; /* Status flags */
|
||||
int FPZ=0;
|
||||
int FPN=0;
|
||||
int FPV=0;
|
||||
int FPMODE=0; /* 0 = float, 1 = doubles */
|
||||
int INTMODE=0; /* 0 = integers, 1 = longs */
|
||||
|
||||
/* Temporary variables */
|
||||
FLOAT Srcflt; /* Float specified by FSRC field */
|
||||
pdpfloat *fladdr; /* Address of float in dspace */
|
||||
int AC; /* Accumulator field in ir */
|
||||
int32_t srclong; /* Longword from source address */
|
||||
int32_t dstlong; /* Longword for destination address */
|
||||
static char *buf, *buf2; /* for copylong */
|
||||
|
||||
|
||||
|
||||
|
||||
/* Convert from PDP-11 float representation to native representation */
|
||||
static void from11float(FLOAT *out, pdpfloat *in)
|
||||
{
|
||||
int32_t exponent;
|
||||
u_int32_t fraction;
|
||||
FLOAT z;
|
||||
|
||||
exponent= in->exp - 128 - 24; /* 24 so as to shift the radix point left */
|
||||
/* Add in the missing significant bit */
|
||||
fraction= (in->frac1 << 16) + in->frac2 + 8388608;
|
||||
|
||||
z= powf(2.0, (float)exponent);
|
||||
*out= (float)fraction * z;
|
||||
if (in->sign) *out= -(*out);
|
||||
FpDebug((dbg_file, "\t0%o from11float out is %f\n",regs[7], *out));
|
||||
}
|
||||
|
||||
/* Convert from native representation to PDP-11 float representation */
|
||||
static void to11float(FLOAT *in, pdpfloat *out)
|
||||
{
|
||||
int32_t exponent=129;
|
||||
u_int32_t fraction;
|
||||
FLOAT infloat= *in;
|
||||
|
||||
FpDebug((dbg_file, "\t0%o to11float in is %f\n",regs[7], infloat));
|
||||
if (infloat < 0.0) { out->sign=1; infloat= -infloat; }
|
||||
else out->sign=0;
|
||||
|
||||
if (infloat==0.0) { out->frac1=0; out->frac2=0; out->exp=0; return; }
|
||||
|
||||
/* We want the float's fraction to start with 1.0 (in binary) */
|
||||
/* Therefore it must be < 2.0 and >= 1.0 */
|
||||
while (infloat >= 2.0) { infloat *= 0.5; exponent++; }
|
||||
while (infloat < 1.0) { infloat *= 2.0; exponent--; }
|
||||
|
||||
infloat= infloat - 1.0; /* Remove significant bit */
|
||||
fraction= (int)(infloat * 8388608.0); /* Multiply fraction by 2^24 */
|
||||
out->frac2= fraction & 0xffff;
|
||||
out->frac1= (fraction>>16);
|
||||
out->exp= exponent;
|
||||
}
|
||||
|
||||
static struct { u_int16_t lo; u_int16_t hi; } intpair;
|
||||
/* Load (and convert if necessary) the float described by the source */
|
||||
/* address into Srcflt. */
|
||||
static void
|
||||
load_flt(void)
|
||||
{
|
||||
u_int16_t indirect,addr;
|
||||
u_int16_t *intptr;
|
||||
|
||||
FpDebug((dbg_file, "\tload_flt mode %d\n", DST_MODE));
|
||||
switch (DST_MODE) {
|
||||
case 0:
|
||||
Srcflt = fregs[DST_REG];
|
||||
fladdr=NULL; return;
|
||||
case 1:
|
||||
if (DST_REG == PC) {
|
||||
intptr = (u_int16_t *)&ispace[regs[DST_REG]];
|
||||
intpair.lo= *intptr;
|
||||
intpair.hi=0;
|
||||
fladdr= (pdpfloat *)&intpair;
|
||||
} else fladdr = (pdpfloat *)&dspace[regs[DST_REG]];
|
||||
from11float(&Srcflt, fladdr);
|
||||
return;
|
||||
case 2:
|
||||
if (DST_REG == PC) {
|
||||
intptr = (u_int16_t *)&ispace[regs[DST_REG]];
|
||||
intpair.lo= *intptr;
|
||||
intpair.hi=0;
|
||||
fladdr= (pdpfloat *)&intpair;
|
||||
from11float(&Srcflt, fladdr);
|
||||
regs[DST_REG] += 2;
|
||||
} else {
|
||||
fladdr = (pdpfloat *)&dspace[regs[DST_REG]];
|
||||
from11float(&Srcflt, fladdr);
|
||||
if (FPMODE) regs[DST_REG] += 8;
|
||||
else regs[DST_REG] += 4;
|
||||
}
|
||||
return;
|
||||
case 3:
|
||||
ll_word(regs[DST_REG], indirect);
|
||||
if (DST_REG == PC) {
|
||||
intptr = (u_int16_t *)&ispace[indirect];
|
||||
intpair.lo= *intptr;
|
||||
intpair.hi=0;
|
||||
fladdr= (pdpfloat *)&intpair;
|
||||
from11float(&Srcflt, fladdr);
|
||||
regs[DST_REG] += 2;
|
||||
} else {
|
||||
fladdr = (pdpfloat *)&dspace[indirect];
|
||||
from11float(&Srcflt, fladdr);
|
||||
if (FPMODE) regs[DST_REG] += 8;
|
||||
else regs[DST_REG] += 4;
|
||||
}
|
||||
return;
|
||||
case 4:
|
||||
if (FPMODE) regs[DST_REG] -= 8;
|
||||
else regs[DST_REG] -= 4;
|
||||
fladdr = (pdpfloat *)&dspace[regs[DST_REG]];
|
||||
from11float(&Srcflt, fladdr);
|
||||
return;
|
||||
case 5:
|
||||
if (FPMODE) regs[DST_REG] -= 8;
|
||||
else regs[DST_REG] -= 4;
|
||||
ll_word(regs[DST_REG], indirect);
|
||||
fladdr = (pdpfloat *)&dspace[indirect];
|
||||
from11float(&Srcflt, fladdr);
|
||||
return;
|
||||
case 6:
|
||||
lli_word(regs[PC], indirect);
|
||||
regs[PC] += 2;
|
||||
indirect= regs[DST_REG] + indirect;
|
||||
fladdr = (pdpfloat *)&dspace[indirect];
|
||||
from11float(&Srcflt, fladdr);
|
||||
return;
|
||||
case 7:
|
||||
lli_word(regs[PC], indirect);
|
||||
regs[PC] += 2;
|
||||
indirect = regs[DST_REG] + indirect;
|
||||
ll_word(indirect, addr);
|
||||
fladdr = (pdpfloat *)&dspace[addr];
|
||||
from11float(&Srcflt, fladdr);
|
||||
return;
|
||||
}
|
||||
illegal();
|
||||
}
|
||||
|
||||
/* Save (and convert if necessary) Srcflt into the float described by the
|
||||
* destination address */
|
||||
static void
|
||||
save_flt(void)
|
||||
{
|
||||
u_int16_t indirect;
|
||||
u_int16_t addr;
|
||||
pdpfloat *fladdr;
|
||||
|
||||
FpDebug((dbg_file, "\tsave_flt mode %d\n", DST_MODE));
|
||||
switch (DST_MODE) {
|
||||
case 0:
|
||||
fregs[DST_REG] = Srcflt;
|
||||
return;
|
||||
case 1:
|
||||
fladdr = (pdpfloat *)&dspace[regs[DST_REG]];
|
||||
to11float(&Srcflt, fladdr);
|
||||
return;
|
||||
case 2:
|
||||
fladdr = (pdpfloat *)&dspace[regs[DST_REG]];
|
||||
to11float(&Srcflt, fladdr);
|
||||
if (DST_REG == PC) regs[DST_REG] += 2;
|
||||
else if (FPMODE) regs[DST_REG] += 8;
|
||||
else regs[DST_REG] += 4;
|
||||
return;
|
||||
case 3:
|
||||
ll_word(regs[DST_REG], indirect);
|
||||
fladdr = (pdpfloat *)&dspace[indirect];
|
||||
to11float(&Srcflt, fladdr);
|
||||
if (DST_REG == PC) regs[DST_REG] += 2;
|
||||
else if (FPMODE) regs[DST_REG] += 8;
|
||||
else regs[DST_REG] += 4;
|
||||
return;
|
||||
case 4:
|
||||
if (FPMODE) regs[DST_REG] -= 8;
|
||||
else regs[DST_REG] -= 4;
|
||||
fladdr = (pdpfloat *)&dspace[regs[DST_REG]];
|
||||
to11float(&Srcflt, fladdr);
|
||||
return;
|
||||
case 5:
|
||||
if (FPMODE) regs[DST_REG] -= 8;
|
||||
else regs[DST_REG] -= 4;
|
||||
ll_word(regs[DST_REG], indirect);
|
||||
fladdr = (pdpfloat *)&dspace[indirect];
|
||||
to11float(&Srcflt, fladdr);
|
||||
return;
|
||||
case 6:
|
||||
lli_word(regs[PC], indirect);
|
||||
regs[PC] += 2;
|
||||
indirect = regs[DST_REG] + indirect;
|
||||
fladdr = (pdpfloat *)&dspace[indirect];
|
||||
to11float(&Srcflt, fladdr);
|
||||
return;
|
||||
case 7:
|
||||
lli_word(regs[PC], indirect);
|
||||
regs[PC] += 2;
|
||||
indirect = regs[DST_REG] + indirect;
|
||||
ll_word(indirect, addr);
|
||||
fladdr = (pdpfloat *)&dspace[addr];
|
||||
to11float(&Srcflt, fladdr);
|
||||
return;
|
||||
}
|
||||
illegal();
|
||||
}
|
||||
|
||||
/* lli_long() - Load a long from the given ispace logical address. */
|
||||
#define lli_long(addr, word) \
|
||||
{ adptr= (u_int16_t *)&(ispace[addr]); copylong(word, *adptr); } \
|
||||
|
||||
/* ll_long() - Load a long from the given logical address. */
|
||||
#define ll_long(addr, word) \
|
||||
{ adptr= (u_int16_t *)&(dspace[addr]); copylong(word, *adptr); } \
|
||||
|
||||
/* sl_long() - Store a long from the given logical address. */
|
||||
#define sl_long(addr, word) \
|
||||
{ adptr= (u_int16_t *)&(dspace[addr]); copylong(*adptr, word); } \
|
||||
|
||||
static void
|
||||
load_long(void)
|
||||
{
|
||||
u_int16_t addr, indirect;
|
||||
|
||||
switch (DST_MODE) {
|
||||
case 0:
|
||||
srclong = regs[DST_REG];
|
||||
return;
|
||||
case 1:
|
||||
addr = regs[DST_REG];
|
||||
if (DST_REG == PC) {
|
||||
lli_long(addr, srclong)
|
||||
} else {
|
||||
ll_long(addr, srclong);
|
||||
}
|
||||
return;
|
||||
case 2:
|
||||
addr = regs[DST_REG];
|
||||
if (DST_REG == PC) {
|
||||
lli_long(addr, srclong)
|
||||
} else {
|
||||
ll_long(addr, srclong);
|
||||
}
|
||||
regs[DST_REG] += 4;
|
||||
return;
|
||||
case 3:
|
||||
indirect = regs[DST_REG];
|
||||
if (DST_REG == PC) {
|
||||
lli_word(indirect, addr)
|
||||
} else {
|
||||
ll_word(indirect, addr);
|
||||
}
|
||||
regs[DST_REG] += 4;
|
||||
ll_long(addr, srclong);
|
||||
return;
|
||||
case 4:
|
||||
regs[DST_REG] -= 4;
|
||||
addr = regs[DST_REG];
|
||||
ll_long(addr, srclong);
|
||||
return;
|
||||
case 5:
|
||||
regs[DST_REG] -= 4;
|
||||
indirect = regs[DST_REG];
|
||||
ll_word(indirect, addr);
|
||||
ll_long(addr, srclong);
|
||||
return;
|
||||
case 6:
|
||||
lli_word(regs[PC], indirect);
|
||||
regs[PC] += 2;
|
||||
addr = regs[DST_REG] + indirect;
|
||||
ll_long(addr, srclong);
|
||||
return;
|
||||
case 7:
|
||||
lli_word(regs[PC], indirect);
|
||||
regs[PC] += 2;
|
||||
indirect = regs[DST_REG] + indirect;
|
||||
ll_word(indirect, addr);
|
||||
ll_long(addr, srclong);
|
||||
return;
|
||||
}
|
||||
illegal();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
store_long(void)
|
||||
{
|
||||
u_int16_t addr, indirect;
|
||||
|
||||
switch (DST_MODE) {
|
||||
case 0:
|
||||
regs[DST_REG]= dstlong;
|
||||
return;
|
||||
case 1:
|
||||
addr = regs[DST_REG];
|
||||
sl_long(addr, dstlong)
|
||||
return;
|
||||
case 2:
|
||||
addr = regs[DST_REG];
|
||||
sl_long(addr, dstlong)
|
||||
regs[DST_REG] += 4;
|
||||
return;
|
||||
case 3:
|
||||
indirect = regs[DST_REG];
|
||||
ll_word(indirect, addr);
|
||||
regs[DST_REG] += 4;
|
||||
sl_long(addr, dstlong);
|
||||
return;
|
||||
case 4:
|
||||
regs[DST_REG] -= 4;
|
||||
addr = regs[DST_REG];
|
||||
sl_long(addr, dstlong);
|
||||
return;
|
||||
case 5:
|
||||
regs[DST_REG] -= 4;
|
||||
indirect = regs[DST_REG];
|
||||
ll_word(indirect, addr);
|
||||
sl_long(addr, dstlong);
|
||||
return;
|
||||
case 6:
|
||||
lli_word(regs[PC], indirect);
|
||||
regs[PC] += 2;
|
||||
addr = regs[DST_REG] + indirect;
|
||||
sl_long(addr, dstlong);
|
||||
return;
|
||||
case 7:
|
||||
lli_word(regs[PC], indirect);
|
||||
regs[PC] += 2;
|
||||
indirect = regs[DST_REG] + indirect;
|
||||
ll_word(indirect, addr);
|
||||
sl_long(addr, dstlong);
|
||||
return;
|
||||
}
|
||||
illegal();
|
||||
}
|
||||
|
||||
|
||||
/* Instruction handlers */
|
||||
void
|
||||
fpset()
|
||||
{
|
||||
switch (ir) {
|
||||
case 0170000: /* CFCC */
|
||||
CC_C= FPC; CC_V= FPV;
|
||||
CC_Z= FPZ; CC_N= FPN;
|
||||
return;
|
||||
case 0170001: /* SETF */
|
||||
FPMODE=0; return;
|
||||
case 0170002: /* SETI */
|
||||
INTMODE=0; return;
|
||||
case 0170011: /* SETD */
|
||||
FPMODE=1; return;
|
||||
case 0170012: /* SETL */
|
||||
INTMODE=1; return;
|
||||
default:
|
||||
not_impl();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ldf() /* Load float */
|
||||
{
|
||||
AC= (ir >> 6) & 3;
|
||||
load_flt();
|
||||
fregs[AC]= Srcflt;
|
||||
FPC=0; FPV=0;
|
||||
if (fregs[AC]==0.0) FPZ=1; else FPZ=0;
|
||||
if (fregs[AC]<0.0) FPN=1; else FPN=0;
|
||||
}
|
||||
|
||||
void
|
||||
stf() /* Store float */
|
||||
{
|
||||
AC= (ir >> 6) & 3;
|
||||
Srcflt= fregs[AC];
|
||||
save_flt();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
clrf() /* Store float */
|
||||
{
|
||||
AC= (ir >> 6) & 3;
|
||||
Srcflt= 0.0;
|
||||
save_flt();
|
||||
FPC= FPZ= FPV= 0; FPZ=1;
|
||||
}
|
||||
void
|
||||
addf() /* Add float */
|
||||
{
|
||||
AC= (ir >> 6) & 3;
|
||||
load_flt();
|
||||
fregs[AC]+= Srcflt;
|
||||
FPC=0;
|
||||
if (fregs[AC]>XUL) FPV=1; else FPV=0;
|
||||
if (fregs[AC]==0.0) FPZ=1; else FPZ=0;
|
||||
if (fregs[AC]<0.0) FPN=1; else FPN=0;
|
||||
}
|
||||
|
||||
void
|
||||
subf() /* Subtract float */
|
||||
{
|
||||
AC= (ir >> 6) & 3;
|
||||
load_flt();
|
||||
fregs[AC]-= Srcflt;
|
||||
FPC=0;
|
||||
if (fregs[AC]>XUL) FPV=1; else FPV=0;
|
||||
if (fregs[AC]==0.0) FPZ=1; else FPZ=0;
|
||||
if (fregs[AC]<0.0) FPN=1; else FPN=0;
|
||||
}
|
||||
|
||||
void
|
||||
negf() /* Negate float */
|
||||
{
|
||||
load_flt();
|
||||
fladdr->sign= -(fladdr->sign);
|
||||
FPC=0; FPV=0;
|
||||
if (Srcflt==0.0) FPZ=1; else FPZ=0;
|
||||
if (Srcflt<0.0) FPN=1; else FPN=0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
absf() /* Absolute float */
|
||||
{
|
||||
load_flt();
|
||||
fladdr->sign= 0;
|
||||
FPC=0; FPV=0; FPN=0;
|
||||
if (Srcflt==0.0) FPZ=1; else FPZ=0;
|
||||
}
|
||||
|
||||
void
|
||||
mulf() /* Multiply float */
|
||||
{
|
||||
AC= (ir >> 6) & 3;
|
||||
load_flt();
|
||||
fregs[AC]*= Srcflt;
|
||||
FPC=0;
|
||||
if (fregs[AC]>XUL) FPV=1; else FPV=0;
|
||||
if (fregs[AC]==0.0) FPZ=1; else FPZ=0;
|
||||
if (fregs[AC]<0.0) FPN=1; else FPN=0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
moddf() /* Multiply and integerise float */
|
||||
{
|
||||
FLOAT x,y;
|
||||
|
||||
AC= (ir >> 6) & 3;
|
||||
load_flt();
|
||||
fregs[AC]*= Srcflt; y= fregs[AC];
|
||||
if (y>0.0) x= (FLOAT) floor((double)y);
|
||||
else x= (FLOAT) ceil((double)y);
|
||||
fregs[AC|1]= x;
|
||||
|
||||
y=y-x; fregs[AC]=y;
|
||||
|
||||
FPC=0;
|
||||
if (fregs[AC]>XUL) FPV=1; else FPV=0;
|
||||
if (fregs[AC]==0.0) FPZ=1; else FPZ=0;
|
||||
if (fregs[AC]<0.0) FPN=1; else FPN=0;
|
||||
}
|
||||
|
||||
void
|
||||
divf() /* Divide float */
|
||||
{
|
||||
AC= (ir >> 6) & 3;
|
||||
load_flt();
|
||||
fregs[AC]/= Srcflt;
|
||||
FPC=0;
|
||||
if (fregs[AC]>XUL) FPV=1; else FPV=0;
|
||||
if (fregs[AC]==0.0) FPZ=1; else FPZ=0;
|
||||
if (fregs[AC]<0.0) FPN=1; else FPN=0;
|
||||
}
|
||||
|
||||
void
|
||||
cmpf() /* Compare float */
|
||||
{
|
||||
AC= (ir >> 6) & 3;
|
||||
load_flt();
|
||||
FPC=0; FPV=0;
|
||||
if (fregs[AC]>Srcflt) FPN=1; else FPN=0;
|
||||
if (fregs[AC]==Srcflt) FPZ=1; else FPZ=0;
|
||||
}
|
||||
|
||||
void
|
||||
tstf() /* Test float */
|
||||
{
|
||||
AC= (ir >> 6) & 3;
|
||||
load_flt();
|
||||
FPC=0; FPV=0;
|
||||
if (Srcflt<0.0) FPN=1; else FPN=0;
|
||||
if (Srcflt==0.0) FPZ=1; else FPZ=0;
|
||||
}
|
||||
|
||||
void
|
||||
ldfps() /* Load FPP status */
|
||||
{
|
||||
load_dst();
|
||||
if (dstword & CC_NBIT) CC_N=1;
|
||||
if (dstword & CC_ZBIT) CC_Z=1;
|
||||
if (dstword & CC_VBIT) CC_V=1;
|
||||
if (dstword & CC_CBIT) CC_C=1;
|
||||
}
|
||||
|
||||
void
|
||||
stfps() /* Store FPP status */
|
||||
{
|
||||
srcword=0;
|
||||
if (CC_N) srcword|= CC_NBIT;
|
||||
if (CC_Z) srcword|= CC_ZBIT;
|
||||
if (CC_V) srcword|= CC_VBIT;
|
||||
if (CC_C) srcword|= CC_CBIT;
|
||||
store_dst();
|
||||
}
|
||||
|
||||
void
|
||||
lcdif() /* Convert int to float */
|
||||
{
|
||||
AC= (ir >> 6) & 3;
|
||||
if (INTMODE==0) { /* ints */
|
||||
load_src();
|
||||
fregs[AC]= (float) srcword;
|
||||
} else {
|
||||
load_long();
|
||||
fregs[AC]= (float) srclong;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
stcfi() /* Convert int to float */
|
||||
{
|
||||
AC= (ir >> 6) & 3;
|
||||
if (INTMODE==0) { /* ints */
|
||||
dstword= (int16_t) fregs[AC];
|
||||
store_dst();
|
||||
} else {
|
||||
dstlong= (int32_t) fregs[AC];
|
||||
store_long();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
stexp() /* Store exponent */
|
||||
{
|
||||
pdpfloat pdptmp;
|
||||
|
||||
AC= (ir >> 6) & 3;
|
||||
to11float(&fregs[AC], &pdptmp);
|
||||
dstword= pdptmp.exp - 128;
|
||||
store_dst();
|
||||
}
|
||||
|
||||
void stcdf()
|
||||
{
|
||||
/* Switch FPMODE just while we're saving */
|
||||
FPMODE=1 - FPMODE; stf(); FPMODE=1 - FPMODE;
|
||||
}
|
||||
|
||||
void ldcdf()
|
||||
{
|
||||
ldf();
|
||||
}
|
||||
|
||||
void stst()
|
||||
{
|
||||
/* For now */
|
||||
}
|
||||
|
||||
void ldexpp()
|
||||
{
|
||||
pdpfloat pdptmp;
|
||||
|
||||
AC= (ir >> 6) & 3;
|
||||
to11float(&fregs[AC], &pdptmp);
|
||||
load_src(); /* srcword now holds new exponent */
|
||||
srcword +=128; /* Convert to required exponent */
|
||||
srcword &= 0xff;
|
||||
pdptmp.exp= srcword;
|
||||
from11float(&fregs[AC], &pdptmp);
|
||||
}
|
||||
176
tools/apout/itab.c
Normal file
176
tools/apout/itab.c
Normal file
@@ -0,0 +1,176 @@
|
||||
/* itab.c - Instruction decode table.
|
||||
*
|
||||
* $Revision: 2.12 $
|
||||
* $Date: 1999/12/27 10:19:40 $
|
||||
*/
|
||||
|
||||
#include "defines.h"
|
||||
|
||||
static _itab sitab0[64] = {
|
||||
halt, waiti, illegal, bpt, iot, illegal, illegal, illegal,
|
||||
illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
|
||||
illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
|
||||
illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
|
||||
illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
|
||||
illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
|
||||
illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
|
||||
illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal
|
||||
};
|
||||
|
||||
static _itab sitab1[64] = {
|
||||
rts, rts, rts, rts, rts, rts, rts, rts,
|
||||
illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
|
||||
illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
|
||||
illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
|
||||
ccc, ccc, ccc, ccc, ccc, ccc, ccc, ccc,
|
||||
ccc, ccc, ccc, ccc, ccc, ccc, ccc, ccc,
|
||||
scc, scc, scc, scc, scc, scc, scc, scc,
|
||||
scc, scc, scc, scc, scc, scc, scc, scc
|
||||
};
|
||||
|
||||
void
|
||||
dositab0(void)
|
||||
{
|
||||
sitab0[ir & 077] ();
|
||||
}
|
||||
|
||||
void
|
||||
dositab1(void)
|
||||
{
|
||||
sitab1[ir & 077] ();
|
||||
}
|
||||
|
||||
_itab itab[1024] = {
|
||||
dositab0, jmp, dositab1, swabi, br, br, br, br,
|
||||
bne, bne, bne, bne, beq, beq, beq, beq,
|
||||
bge, bge, bge, bge, blt, blt, blt, blt,
|
||||
bgt, bgt, bgt, bgt, ble, ble, ble, ble,
|
||||
jsr, jsr, jsr, jsr, jsr, jsr, jsr, jsr,
|
||||
clr, com, inc, dec, neg, adc, sbc, tst,
|
||||
ror, rol, asr, asl, mark, mfpi, mtpi, sxt,
|
||||
illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
|
||||
movsreg,movsreg,movsreg,movsreg,movsreg,movsreg,movsreg,movsreg,
|
||||
movsreg1,movsreg1,movsreg1,movsreg1,movsreg1,movsreg1,movsreg1,movsreg1pc,
|
||||
mov, mov, mov, mov, mov, mov, mov, mov,
|
||||
mov, mov, mov, mov, mov, mov, mov, mov,
|
||||
mov, mov, mov, mov, mov, mov, mov, mov,
|
||||
mov, mov, mov, mov, mov, mov, mov, mov,
|
||||
mov, mov, mov, mov, mov, mov, mov, mov,
|
||||
mov, mov, mov, mov, mov, mov, mov, mov,
|
||||
cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp,
|
||||
cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp,
|
||||
cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp,
|
||||
cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp,
|
||||
cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp,
|
||||
cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp,
|
||||
cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp,
|
||||
cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp,
|
||||
bit, bit, bit, bit, bit, bit, bit, bit,
|
||||
bit, bit, bit, bit, bit, bit, bit, bit,
|
||||
bit, bit, bit, bit, bit, bit, bit, bit,
|
||||
bit, bit, bit, bit, bit, bit, bit, bit,
|
||||
bit, bit, bit, bit, bit, bit, bit, bit,
|
||||
bit, bit, bit, bit, bit, bit, bit, bit,
|
||||
bit, bit, bit, bit, bit, bit, bit, bit,
|
||||
bit, bit, bit, bit, bit, bit, bit, bit,
|
||||
bic, bic, bic, bic, bic, bic, bic, bic,
|
||||
bic, bic, bic, bic, bic, bic, bic, bic,
|
||||
bic, bic, bic, bic, bic, bic, bic, bic,
|
||||
bic, bic, bic, bic, bic, bic, bic, bic,
|
||||
bic, bic, bic, bic, bic, bic, bic, bic,
|
||||
bic, bic, bic, bic, bic, bic, bic, bic,
|
||||
bic, bic, bic, bic, bic, bic, bic, bic,
|
||||
bic, bic, bic, bic, bic, bic, bic, bic,
|
||||
bis, bis, bis, bis, bis, bis, bis, bis,
|
||||
bis, bis, bis, bis, bis, bis, bis, bis,
|
||||
bis, bis, bis, bis, bis, bis, bis, bis,
|
||||
bis, bis, bis, bis, bis, bis, bis, bis,
|
||||
bis, bis, bis, bis, bis, bis, bis, bis,
|
||||
bis, bis, bis, bis, bis, bis, bis, bis,
|
||||
bis, bis, bis, bis, bis, bis, bis, bis,
|
||||
bis, bis, bis, bis, bis, bis, bis, bis,
|
||||
add, add, add, add, add, add, add, add,
|
||||
add, add, add, add, add, add, add, add,
|
||||
add, add, add, add, add, add, add, add,
|
||||
add, add, add, add, add, add, add, add,
|
||||
add, add, add, add, add, add, add, add,
|
||||
add, add, add, add, add, add, add, add,
|
||||
add, add, add, add, add, add, add, add,
|
||||
add, add, add, add, add, add, add, add,
|
||||
mul, mul, mul, mul, mul, mul, mul, mul,
|
||||
divide, divide, divide, divide, divide, divide, divide, divide,
|
||||
ash, ash, ash, ash, ash, ash, ash, ash,
|
||||
ashc, ashc, ashc, ashc, ashc, ashc, ashc, ashc,
|
||||
xor, xor, xor, xor, xor, xor, xor, xor,
|
||||
illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
|
||||
illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
|
||||
sob, sob, sob, sob, sob, sob, sob, sob,
|
||||
bpl, bpl, bpl, bpl, bmi, bmi, bmi, bmi,
|
||||
bhi, bhi, bhi, bhi, blos, blos, blos, blos,
|
||||
bvc, bvc, bvc, bvc, bvs, bvs, bvs, bvs,
|
||||
bcc, bcc, bcc, bcc, bcs, bcs, bcs, bcs,
|
||||
|
||||
/* emt at itab[544] to itab[547] */
|
||||
/* trap at itab[548] to itab[551] */
|
||||
|
||||
emt, emt, emt, emt, trap, trap, trap, trap,
|
||||
clrb, comb, incb, decb, negb, adcb, sbcb, tstb,
|
||||
rorb, rolb, asrb, aslb, mtps, mfpd, mtpd, mfps,
|
||||
illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
|
||||
movb, movb, movb, movb, movb, movb, movb, movb,
|
||||
movb, movb, movb, movb, movb, movb, movb, movb,
|
||||
movb, movb, movb, movb, movb, movb, movb, movb,
|
||||
movb, movb, movb, movb, movb, movb, movb, movb,
|
||||
movb, movb, movb, movb, movb, movb, movb, movb,
|
||||
movb, movb, movb, movb, movb, movb, movb, movb,
|
||||
movb, movb, movb, movb, movb, movb, movb, movb,
|
||||
movb, movb, movb, movb, movb, movb, movb, movb,
|
||||
cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb,
|
||||
cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb,
|
||||
cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb,
|
||||
cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb,
|
||||
cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb,
|
||||
cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb,
|
||||
cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb,
|
||||
cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb,
|
||||
bitb, bitb, bitb, bitb, bitb, bitb, bitb, bitb,
|
||||
bitb, bitb, bitb, bitb, bitb, bitb, bitb, bitb,
|
||||
bitb, bitb, bitb, bitb, bitb, bitb, bitb, bitb,
|
||||
bitb, bitb, bitb, bitb, bitb, bitb, bitb, bitb,
|
||||
bitb, bitb, bitb, bitb, bitb, bitb, bitb, bitb,
|
||||
bitb, bitb, bitb, bitb, bitb, bitb, bitb, bitb,
|
||||
bitb, bitb, bitb, bitb, bitb, bitb, bitb, bitb,
|
||||
bitb, bitb, bitb, bitb, bitb, bitb, bitb, bitb,
|
||||
bicb, bicb, bicb, bicb, bicb, bicb, bicb, bicb,
|
||||
bicb, bicb, bicb, bicb, bicb, bicb, bicb, bicb,
|
||||
bicb, bicb, bicb, bicb, bicb, bicb, bicb, bicb,
|
||||
bicb, bicb, bicb, bicb, bicb, bicb, bicb, bicb,
|
||||
bicb, bicb, bicb, bicb, bicb, bicb, bicb, bicb,
|
||||
bicb, bicb, bicb, bicb, bicb, bicb, bicb, bicb,
|
||||
bicb, bicb, bicb, bicb, bicb, bicb, bicb, bicb,
|
||||
bicb, bicb, bicb, bicb, bicb, bicb, bicb, bicb,
|
||||
bisb, bisb, bisb, bisb, bisb, bisb, bisb, bisb,
|
||||
bisb, bisb, bisb, bisb, bisb, bisb, bisb, bisb,
|
||||
bisb, bisb, bisb, bisb, bisb, bisb, bisb, bisb,
|
||||
bisb, bisb, bisb, bisb, bisb, bisb, bisb, bisb,
|
||||
bisb, bisb, bisb, bisb, bisb, bisb, bisb, bisb,
|
||||
bisb, bisb, bisb, bisb, bisb, bisb, bisb, bisb,
|
||||
bisb, bisb, bisb, bisb, bisb, bisb, bisb, bisb,
|
||||
bisb, bisb, bisb, bisb, bisb, bisb, bisb, bisb,
|
||||
sub, sub, sub, sub, sub, sub, sub, sub,
|
||||
sub, sub, sub, sub, sub, sub, sub, sub,
|
||||
sub, sub, sub, sub, sub, sub, sub, sub,
|
||||
sub, sub, sub, sub, sub, sub, sub, sub,
|
||||
sub, sub, sub, sub, sub, sub, sub, sub,
|
||||
sub, sub, sub, sub, sub, sub, sub, sub,
|
||||
sub, sub, sub, sub, sub, sub, sub, sub,
|
||||
sub, sub, sub, sub, sub, sub, sub, sub,
|
||||
fpset, ldfps, stfps, stst, clrf, tstf, absf, negf,
|
||||
mulf, mulf, mulf, mulf, moddf, moddf, moddf, moddf,
|
||||
addf, addf, addf, addf, ldf, ldf, ldf, ldf,
|
||||
subf, subf, subf, subf, cmpf, cmpf, cmpf, cmpf,
|
||||
stf, stf, stf, stf, divf, divf, divf, divf,
|
||||
stexp, stexp, stexp, stexp, stcfi, stcfi, stcfi, stcfi,
|
||||
stcdf, stcdf, stcdf, stcdf, ldexpp, ldexpp, ldexpp, ldexpp,
|
||||
lcdif, lcdif, lcdif, lcdif, ldcdf, ldcdf, ldcdf, ldcdf
|
||||
};
|
||||
230
tools/apout/ke11a.c
Normal file
230
tools/apout/ke11a.c
Normal file
@@ -0,0 +1,230 @@
|
||||
/* ke11a.c - this holds the emulation of the PDP 11/20 extended
|
||||
* arithmetic element. We only need this for 1st Edition a.out support.
|
||||
* Code kindly borrowed from the eae support written by Tim Shoppa
|
||||
* (shoppa@trailing-edge.com) for Bob Supnik's PDP-11 emulator.
|
||||
*
|
||||
* $Revision: 1.7 $
|
||||
* $Date: 1999/12/28 03:57:31 $
|
||||
*/
|
||||
#ifdef EMUV1
|
||||
#include "defines.h"
|
||||
#include <unistd.h>
|
||||
|
||||
void eae_wr(u_int16_t data, u_int16_t PA, int32_t access);
|
||||
void set_SR(void);
|
||||
|
||||
/* I/O dispatch routine, I/O addresses 177300 - 177316 */
|
||||
|
||||
#define eae_DIV 0177300 /* Divide */
|
||||
#define eae_AC 0177302 /* Accumulator */
|
||||
#define eae_MQ 0177304 /* MQ */
|
||||
#define eae_MUL 0177306 /* Multiply */
|
||||
#define eae_SC 0177310 /* Step counter */
|
||||
#define eae_SR 0177311 /* Status register */
|
||||
#define eae_NOR 0177312 /* Normalize */
|
||||
#define eae_LSH 0177314 /* Logical shift */
|
||||
#define eae_ASH 0177316 /* Arithmetic shift */
|
||||
#define WRITEB 1 /* Write of a byte */
|
||||
#define WRITEW 2 /* Write of a word */
|
||||
|
||||
/* The MQ, AC, SC, and SR registers specify the state of the EAE */
|
||||
/* Here we define them as int32's, though in real life the MQ and AC */
|
||||
/* are 16 bits and the SC and SR are 8 bits */
|
||||
|
||||
int32_t MQ; /* Multiply quotient */
|
||||
int32_t AC; /* Accumulator */
|
||||
int32_t SC = 0; /* Shift counter */
|
||||
int32_t SR; /* Status register */
|
||||
|
||||
|
||||
/* Load a word from one of the KE11 registers */
|
||||
int16_t kell_word(u_int16_t addr)
|
||||
{
|
||||
int16_t data;
|
||||
int pid;
|
||||
|
||||
switch (addr) {
|
||||
case eae_DIV:
|
||||
data = 0; break;
|
||||
case eae_MQ:
|
||||
data = MQ; break;
|
||||
case eae_AC: /* high 16 bits of MQ */
|
||||
data = AC; break;
|
||||
case eae_SC:
|
||||
set_SR();
|
||||
data = (SR << 8) | SC; break;
|
||||
case eae_SR:
|
||||
set_SR();
|
||||
data = (SR << 8); break;
|
||||
case eae_NOR:
|
||||
data = SC; break;
|
||||
case eae_LSH:
|
||||
case eae_ASH:
|
||||
case eae_MUL:
|
||||
data = 0; break;
|
||||
default:
|
||||
pid = getpid();
|
||||
(void) fprintf(stderr, "Apout - pid %d unknown KE11 register 0%o\n",
|
||||
pid, addr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/* Load a byte from one of the KE11 registers */
|
||||
int8_t kell_byte(u_int16_t addr)
|
||||
{
|
||||
if (addr&1) printf("Hmm, KE11 access on 0%o\n",addr);
|
||||
return ((int8_t) kell_word(addr));
|
||||
}
|
||||
|
||||
/* Save a word to one of the KE11 registers */
|
||||
void kesl_word(u_int16_t addr, u_int16_t word)
|
||||
{
|
||||
eae_wr(word, addr, WRITEW);
|
||||
}
|
||||
|
||||
/* Save a byte to one of the KE11 registers */
|
||||
void kesl_byte(u_int16_t addr, u_int8_t byte)
|
||||
{
|
||||
eae_wr(byte, addr, WRITEB);
|
||||
}
|
||||
|
||||
void eae_wr(u_int16_t data, u_int16_t PA, int32_t access)
|
||||
{
|
||||
int32_t divisor, quotient, remainder;
|
||||
int32_t dividend, product;
|
||||
int32_t oldMQ;
|
||||
int pid;
|
||||
|
||||
switch (PA) {
|
||||
case eae_DIV:
|
||||
SC = 0;
|
||||
dividend = (AC << 16) | MQ;
|
||||
divisor = data;
|
||||
if (divisor >> 15) divisor = divisor | ~077777;
|
||||
quotient = dividend / divisor;
|
||||
MQ = quotient & 0177777;
|
||||
remainder = dividend % divisor;
|
||||
AC = remainder & 0177777;
|
||||
SR = SR & 076;
|
||||
if ((quotient > 32767) || (quotient < -32768)) { /* did we overflow? */
|
||||
if (dividend < 0) SR = SR | 0100;
|
||||
else SR = SR | 0200;
|
||||
} else {
|
||||
if (quotient < 0) SR = SR | 0300;
|
||||
}
|
||||
return;
|
||||
case eae_AC:
|
||||
AC = data;
|
||||
if ((access == WRITEB) & (data >> 7))
|
||||
AC = AC | 0177400;
|
||||
return;
|
||||
case eae_AC + 1:
|
||||
printf("write to AC+1; data=%o", data);
|
||||
AC = (AC & 0377) | (data << 8);
|
||||
return;
|
||||
case eae_MQ:
|
||||
MQ = data;
|
||||
if ((access == WRITEB) & (data >> 7)) MQ = MQ | 0177400;
|
||||
if (MQ >> 15) AC = 0177777;
|
||||
else AC = 0;
|
||||
return;
|
||||
case eae_MQ + 1:
|
||||
printf("write to MQ+1; data=%o", data);
|
||||
MQ = (MQ & 0377) | (data << 8);
|
||||
if (MQ >> 15) AC = 0177777;
|
||||
else AC = 0;
|
||||
return;
|
||||
case eae_MUL:
|
||||
SC = 0;
|
||||
if (data >> 15) data = data | ~077777;
|
||||
if (MQ >> 15) MQ = MQ | ~077777;
|
||||
product = MQ * data;
|
||||
MQ = product & 0177777;
|
||||
AC = (product >> 16) & 0177777;
|
||||
SR = SR & 076;
|
||||
if (AC >> 15) SR = SR | 0300; /* set sign bit if necessary */
|
||||
return;
|
||||
case eae_SC:
|
||||
if (access == WRITEB) return; /* byte writes are no-ops */
|
||||
SR = (data >> 8) & 0177777;
|
||||
SC = data & 0000077;
|
||||
return;
|
||||
case eae_SR:
|
||||
return; /* this is a No-op */
|
||||
case eae_NOR: /* Normalize */
|
||||
MQ = (AC << 16) | MQ; /* 32-bit number to normalize in MQ */
|
||||
for (SC = 0; SC < 31; SC++) {
|
||||
if (MQ == (0140000 << 16))
|
||||
break;
|
||||
if ((((MQ >> 30) & 3) == 1) || (((MQ >> 30) & 3) == 2))
|
||||
break;
|
||||
MQ = MQ << 1;
|
||||
}
|
||||
printf("SC = %o\r\n", SC);
|
||||
AC = (MQ >> 16) & 0177777;
|
||||
MQ = MQ & 0177777;
|
||||
return;
|
||||
case eae_LSH: /* Logical shift */
|
||||
MQ=(AC<<16)|MQ; /* Form a temporary 32-bit entity */
|
||||
oldMQ=MQ & 0x80000000; /* Save the sign bit for later */
|
||||
SR=SR&0176; /* Clear overflow & carry bits */
|
||||
data=data & 077; /* Convert data from 6-bit */
|
||||
if (data>31) {
|
||||
data=64-data; /* Shift in a -ve direction */
|
||||
SR=SR|((MQ>>(data-1))&1); /* Get the bit that went off the end */
|
||||
MQ=MQ>>data; /* and do the right shift */
|
||||
} else { /* Else left shift */
|
||||
if ((MQ<<(data-1))&0x80000000) SR|=1; /* Get the bit off the end */
|
||||
MQ=MQ<<data; /* and do the left shift */
|
||||
}
|
||||
oldMQ= oldMQ ^ MQ; /* Any difference in sign bit? */
|
||||
if (oldMQ & 0x80000000) SR|=0200;/* Yes, set the overflow bit */
|
||||
AC=(MQ>>16)&0177777; /* Save result in AC and MQ */
|
||||
MQ=MQ&0177777;
|
||||
set_SR();
|
||||
return;
|
||||
|
||||
case eae_ASH: /* Arithmetic shift */
|
||||
MQ=(AC<<16)|MQ; /* Form a temporary 32-bit entity */
|
||||
oldMQ=MQ & 0x80000000; /* Save the sign bit for later */
|
||||
SR=SR&0176; /* Clear overflow & carry bits */
|
||||
data=data & 077; /* Convert data from 6-bit */
|
||||
if (data>31) {
|
||||
data=64-data; /* Shift in a -ve direction */
|
||||
divisor=1 << data; /* Work out the dividing factor */
|
||||
SR=SR|((MQ>>(data-1))&1); /* Get the bit that went off the end */
|
||||
MQ=MQ/divisor; /* and do the right shift */
|
||||
} else { /* Else left shift */
|
||||
product=1 << data; /* Work out the multiplying factor */
|
||||
if ((MQ<<(data-1))&0x80000000) SR|=1; /* Get the bit off the end */
|
||||
MQ=MQ*product; /* and do the left shift */
|
||||
}
|
||||
oldMQ= oldMQ ^ MQ; /* Any difference in sign bit? */
|
||||
if (oldMQ & 0x80000000) SR|=0200;/* Yes, set the overflow bit */
|
||||
AC=(MQ>>16)&0177777; /* Save result in AC and MQ */
|
||||
MQ=MQ&0177777;
|
||||
set_SR();
|
||||
return;
|
||||
|
||||
default:
|
||||
pid = getpid();
|
||||
(void) fprintf(stderr, "Apout - pid %d unknown KE11 register 0%o\n",
|
||||
pid, PA);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void set_SR(void)
|
||||
{
|
||||
SR = SR & 0301; /* clear the result bits we can set here */
|
||||
if (((MQ & 0100000) == 0) && (AC == 0)) SR = SR | 002;
|
||||
if (((MQ & 0100000) == 0100000) && (AC == 0177777)) SR = SR | 002;
|
||||
|
||||
if ((AC == 0) && (MQ == 0)) SR = SR | 0004;
|
||||
if (MQ == 0) SR = SR | 0010;
|
||||
if (AC == 0) SR = SR | 0020;
|
||||
if (AC == 0177777) SR = SR | 0040;
|
||||
}
|
||||
#endif /* EMUV1 */
|
||||
134
tools/apout/magic.c
Normal file
134
tools/apout/magic.c
Normal file
@@ -0,0 +1,134 @@
|
||||
/* magic.c - determine the environment for certain PDP-11 a.out binaries
|
||||
*
|
||||
* Some binaries in V1, V2, V5, V6, V7 and 2.11BSD are not caught with the
|
||||
* magic numbers in aout.c. If this is the case, we fall into the
|
||||
* special_magic() function, which calculates a checksum on the
|
||||
* a.out header. If it matches any of the checksums below, it returns
|
||||
* the appropriate environment value. Otherwise, it returns IS_UNKNOWN.
|
||||
*
|
||||
* $Revision: 1.13 $
|
||||
* $Date: 2000/01/10 01:31:48 $
|
||||
*/
|
||||
#include "defines.h"
|
||||
|
||||
struct spec_aout {
|
||||
u_int32_t cksum;
|
||||
int environment;
|
||||
};
|
||||
|
||||
static struct spec_aout S[]= {
|
||||
{ 0x1042c2, IS_V6 }, /* V6 bin/dc */
|
||||
{ 0x10f02, IS_V5 }, /* V5 etc/update */
|
||||
{ 0x11002, IS_V5 }, /* V5 bin/clri */
|
||||
{ 0x1117c2, IS_V7 }, /* V7 bin/roff */
|
||||
{ 0x11702, IS_V6 }, /* V6 etc/update */
|
||||
{ 0x11a82, IS_V5 }, /* V5 bin/sum */
|
||||
{ 0x1319c2, IS_V5 }, /* V5 usr/fort/fc1 */
|
||||
{ 0x1332c2, IS_V2 }, /* /lib/c0 dated Jun 30 1973 from s2 tape */
|
||||
{ 0x13642, IS_V5 }, /* V5 bin/rew */
|
||||
{ 0x139e02, IS_V5 }, /* V5 bin/dc */
|
||||
{ 0x13c0, IS_V6 }, /* V6 usr/lib/tmgc */
|
||||
{ 0x14042, IS_V6 }, /* V6 bin/tty */
|
||||
{ 0x143c2, IS_V5 }, /* V5 bin/tty */
|
||||
{ 0x152ac2, IS_V6 }, /* V6 usr/lib/tmg */
|
||||
{ 0x15f42, IS_V5 }, /* V5 bin/kill */
|
||||
{ 0x16802, IS_V5 }, /* V5 bin/dsw */
|
||||
{ 0x16902, IS_V5 }, /* V5 bin/mkdir */
|
||||
{ 0x1720c2, IS_V6 }, /* V6 bin/cdb */
|
||||
{ 0x17742, IS_V5 }, /* V5 usr/bin/pfe */
|
||||
{ 0x17cc2, IS_V5 }, /* V5 usr/bin/mesg */
|
||||
{ 0x18702, IS_V5 }, /* V5 bin/rmdir */
|
||||
{ 0x194c2, IS_V6 }, /* V6 bin/chgrp */
|
||||
{ 0x197c2, IS_V6 }, /* V6 bin/chown */
|
||||
{ 0x19a42, IS_V5 }, /* V5 bin/chown */
|
||||
{ 0x19b342, IS_V6 }, /* V6 usr/bin/nroff */
|
||||
{ 0x19f682, IS_V6 }, /* V6 usr/fort/fc1 */
|
||||
{ 0x1b102, IS_V5 }, /* V5 bin/strip */
|
||||
{ 0x1ba02, IS_V6 }, /* V6 bin/strip */
|
||||
{ 0x1c342, IS_V5 }, /* V5 bin/cat */
|
||||
{ 0x1c8442, IS_V7 }, /* V7 usr/games/maze */
|
||||
{ 0x1cc782, IS_V6 }, /* V6 lib/fc0 */
|
||||
{ 0x1dfc2, IS_V5 }, /* V5 etc/getty */
|
||||
{ 0x1f9c2, IS_V2 }, /* /bin/nm dated Jun 30 1973 from s2 tape */
|
||||
{ 0x20202, IS_V5 }, /* V5 usr/games/bj */
|
||||
{ 0x21e42, IS_V6 }, /* V6 usr/bin/units */
|
||||
{ 0x23f82, IS_V5 }, /* V5 usr/bin/passwd */
|
||||
{ 0x260642, IS_V6 }, /* V6 lib/fc1 */
|
||||
{ 0x262a82, IS_211BSD }, /* 2.11 usr/new/m11 */
|
||||
{ 0x27e82, IS_V5 }, /* V5 usr/bin/grep */
|
||||
{ 0x290c2, IS_V7 }, /* V7 usr/games/cubic */
|
||||
{ 0x299c2, IS_V5 }, /* V5 usr/games/cubic */
|
||||
{ 0x2f482, IS_V5 }, /* V5 usr/bin/form */
|
||||
{ 0x3382, IS_V6 }, /* V6 bin/write */
|
||||
{ 0x326642, IS_V7 }, /* 2.9 awk */
|
||||
{ 0x33c42, IS_211BSD }, /* 2.11 usr/games/moo */
|
||||
{ 0x351382, IS_211BSD }, /* 2.11 usr/games/lib/zork */
|
||||
{ 0x3702, IS_V5 }, /* V5 usr/games/moo */
|
||||
{ 0x3b402, IS_V5 }, /* V5 bin/ar */
|
||||
{ 0x3cc02, IS_V2 }, /* /bin/size from from s2 tape */
|
||||
{ 0x4382, IS_V5 }, /* V5 bin/write */
|
||||
{ 0x451f42, IS_V7 }, /* 2.9 /lib/c1 */
|
||||
{ 0x47042, IS_211BSD }, /* 2.11 usr/games/ttt */
|
||||
{ 0x4fa02, IS_V5 }, /* V5 bin/ld */
|
||||
{ 0x51342, IS_211BSD }, /* 2.11 usr/games/bj */
|
||||
{ 0x53302, IS_V6 }, /* V6 usr/lib/suftab */
|
||||
{ 0x55882, IS_V7 }, /* 2.9 /bin/as */
|
||||
{ 0x54702, IS_V5 }, /* V5 usr/games/ttt */
|
||||
{ 0x55702, IS_V7 }, /* V7 bin/as */
|
||||
{ 0x5c342, IS_V2 }, /* /bin/cc dated Jun 30 1973 from s2 tape */
|
||||
{ 0x6f742, IS_V6 }, /* V6 usr/bin/sa */
|
||||
{ 0x7042, IS_V7 }, /* V7 bin/factor */
|
||||
{ 0x71702, IS_V7 }, /* V7 lib/as2 */
|
||||
{ 0x7342, IS_V5 }, /* V5 bin/du */
|
||||
{ 0x73782, IS_V7}, /* 2.9 /lib/as2 */
|
||||
{ 0x73e00, IS_V2 }, /* /bin/ld from s2 tape */
|
||||
{ 0x7a242, IS_V6 }, /* V6 lib/as2 */
|
||||
{ 0x7b102, IS_V6 }, /* V6 bin/as */
|
||||
{ 0x7d082, IS_V5 }, /* V5 bin/as */
|
||||
{ 0x7d6844, IS_V1 }, /* bin/cal from s2 tape */
|
||||
{ 0x7d942, IS_V5 }, /* V5 lib/as2 */
|
||||
{ 0x8002, IS_V5 }, /* V5 etc/lpd */
|
||||
{ 0x85842, IS_V5 }, /* V5 bin/ed */
|
||||
{ 0x8f00, IS_V6 }, /* V6 usr/lib/tmga */
|
||||
{ 0x915c2, IS_V6 }, /* V6 bin/bas */
|
||||
{ 0x94542, IS_V5 }, /* V5 bin/db */
|
||||
{ 0x98442, IS_V6 }, /* V6 usr/bin/ac */
|
||||
{ 0x9adc2, IS_V6 }, /* V6 bin/db */
|
||||
{ 0xa242, IS_V7 }, /* V7 bin/primes */
|
||||
{ 0xa4602, IS_V2 }, /* /bin/as from s2 tape */
|
||||
{ 0xa702, IS_V5 }, /* V5 bin/time */
|
||||
{ 0xad882, IS_V7 }, /* V7 bin/bas */
|
||||
{ 0xadc42, IS_V2 }, /* /usr/lib/c1 from s2 tape */
|
||||
{ 0xb5a82, IS_V6 }, /* V6 usr/bin/prof */
|
||||
{ 0xc1e42, IS_V5 }, /* V5 usr/bin/fed */
|
||||
{ 0xc3102, IS_V6 }, /* V6 bin/tp */
|
||||
{ 0xc8bc2, IS_V5 }, /* V5 bin/tp */
|
||||
{ 0xe1642, IS_V6 }, /* V6 usr/bin/roff */
|
||||
{ 0xe1f42, IS_V5 }, /* V5 usr/bin/roff */
|
||||
{ 0xec582, IS_V5 }, /* V5 bin/bas */
|
||||
{ 0xfc2, IS_V6 }, /* V6 usr/bin/typo */
|
||||
{ 0xfc002, IS_V2 }, /* /bin/as dated Jun 30 1973 from s2 tape */
|
||||
{ 0x38ec0, IS_V5 }, /* V5 bin/ar, Warrens */
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
/* cptr points at the start of the a.out header */
|
||||
int special_magic(u_int16_t *cptr)
|
||||
{
|
||||
u_int32_t cksum=0;
|
||||
int i;
|
||||
|
||||
if (cptr==NULL) return(IS_UNKNOWN);
|
||||
/* Calculate the checksum */
|
||||
for (i=0;i<8; i++) { cksum ^= cptr[i]; cksum = cksum<<1; }
|
||||
|
||||
/* Try and find a match */
|
||||
for (i=0; S[i].cksum!=0; i++) if (S[i].cksum==cksum) {
|
||||
TrapDebug((dbg_file, "This a.out has special magic %d\n",i));
|
||||
return(S[i].environment);
|
||||
}
|
||||
|
||||
/* None, return 0 */
|
||||
(void)printf("Apout - unknown magic in header: 0x%x\n",cksum);
|
||||
return(IS_UNKNOWN);
|
||||
}
|
||||
132
tools/apout/main.c
Normal file
132
tools/apout/main.c
Normal file
@@ -0,0 +1,132 @@
|
||||
/* Startup for apout. Parse arguments, load the binary, and run it.
|
||||
*
|
||||
* $Revision: 1.22 $
|
||||
* $Date: 2002/06/10 11:44:21 $
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include "defines.h"
|
||||
|
||||
/* The following array holds the FILE pointers that correspond to open file
|
||||
* descriptors. Only fds which are not ttys have FILE * pointers
|
||||
*/
|
||||
FILE *stream[NFILE];
|
||||
char *streammode[NFILE]; /* Mode for each file - used for dup */
|
||||
|
||||
/* The following two buffers are used as */
|
||||
/* part of the translation from virtal */
|
||||
/* absolute filenames to native ones. We */
|
||||
/* only have 2 buffers, so if you call */
|
||||
/* xlate_filename() 3 times, the 1st return */
|
||||
/* value will be destroyed. */
|
||||
static char realfilename[2][2 * MAXPATHLEN];
|
||||
static char *rfn[2];
|
||||
static int whichrfn=0;
|
||||
char *apout_root=NULL; /* Root dir for simulated a.out */
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Debugging flags */
|
||||
int inst_debug= 0, /* Print a line before each instruction */
|
||||
trap_debug= 0, /* Print details of each trap */
|
||||
jsr_debug= 0, /* Print out each jsr */
|
||||
fp_debug= 0; /* Print out each floating-point instruction */
|
||||
FILE *dbg_file = NULL; /* Debugging output file */
|
||||
char *progname = NULL; /* The program's name - used in debugging */
|
||||
#endif
|
||||
|
||||
void usage()
|
||||
{
|
||||
fprintf(stderr, "Usage: apout");
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, " [-inst] [-trap] [-jsr] [-fp]");
|
||||
#endif
|
||||
fprintf(stderr, " pdp11_binary\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Ensure, before we start, that certain types are right */
|
||||
assert(sizeof(int8_t)==1); assert(sizeof(u_int8_t)==1);
|
||||
assert(sizeof(int16_t)==2); assert(sizeof(u_int16_t)==2);
|
||||
assert(sizeof(int32_t)==4); assert(sizeof(u_int32_t)==4);
|
||||
|
||||
if (argc < 2) usage();
|
||||
if (!strcmp(argv[1], "-help")) usage();
|
||||
if (!strcmp(argv[1], "--help")) usage();
|
||||
|
||||
#ifdef DEBUG
|
||||
while (1) {
|
||||
if (!strcmp(argv[1], "-inst"))
|
||||
{ inst_debug = 1; argc--; argv++; continue; }
|
||||
if (!strcmp(argv[1], "-trap"))
|
||||
{ trap_debug = 1; argc--; argv++; continue; }
|
||||
if (!strcmp(argv[1], "-jsr"))
|
||||
{ jsr_debug = 1; argc--; argv++; continue; }
|
||||
if (!strcmp(argv[1], "-fp"))
|
||||
{ fp_debug = 1; argc--; argv++; continue; }
|
||||
break;
|
||||
}
|
||||
if (inst_debug|trap_debug|jsr_debug|fp_debug)
|
||||
dbg_file = fopen("apout.dbg", "w");
|
||||
#endif
|
||||
|
||||
/* Prepare arg list for emulated environment */
|
||||
argc--; argv++;
|
||||
Argc= argc; Envp[0]=NULL;
|
||||
for (i=0; i<argc; i++) Argv[i]= argv[i];
|
||||
|
||||
/* Initialise the stream pointers */
|
||||
for (i=3; i<NFILE; i++) { stream[i]=NULL; streammode[i]=NULL; }
|
||||
stream[0]=stdin; streammode[0]="r";
|
||||
stream[1]=stdout; streammode[1]="w";
|
||||
stream[2]=stderr; streammode[2]="w";
|
||||
|
||||
/* Set the translation to a fictitious */
|
||||
/* root filesystem */
|
||||
if ((apout_root = getenv("APOUT_ROOT"))) {
|
||||
set_apout_root(apout_root);
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"APOUT_ROOT env variable not set before running apout\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Try to load the binary as an a.out */
|
||||
if (load_a_out(argv[0],NULL,1) == -1) {
|
||||
fprintf(stderr, "Apout - couldn't load %s\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Other emulated systems (RT-11) can go here */
|
||||
|
||||
run(); /* Now run the binary */
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Translate from a filename to one which is possibly rooted in $APOUT_ROOT.
|
||||
* Note we return a pointer to one of two buffers. The caller does not
|
||||
* have to free the returned pointer, but successive calls will destroy
|
||||
* calls from >2 calls earlier.
|
||||
*/
|
||||
char * xlate_filename(char *name)
|
||||
{
|
||||
int i=whichrfn;
|
||||
|
||||
if (name == NULL) return (NULL);
|
||||
if (name[0] == '\0') return("."); /* Undocumented, but used in V7 */
|
||||
if (name[0] != '/') return (name); /* Relative, keep it relative */
|
||||
strcpy(rfn[i], name); /* Copy name into buffer */
|
||||
whichrfn= 1 - whichrfn; /* Switch to other buffer next time */
|
||||
return (realfilename[i]);
|
||||
}
|
||||
|
||||
void set_apout_root(char *dirname)
|
||||
{
|
||||
strcpy(realfilename[0], dirname);
|
||||
strcpy(realfilename[1], dirname);
|
||||
rfn[0] = realfilename[0]; rfn[0] += strlen(realfilename[0]);
|
||||
rfn[1] = realfilename[1]; rfn[1] += strlen(realfilename[1]);
|
||||
}
|
||||
528
tools/apout/single.c
Normal file
528
tools/apout/single.c
Normal file
@@ -0,0 +1,528 @@
|
||||
/* single.c - Single operand instructions.
|
||||
*
|
||||
* $Revision: 2.10 $
|
||||
* $Date: 1999/01/05 23:46:04 $
|
||||
*/
|
||||
#include "defines.h"
|
||||
|
||||
/* adc() - Add Carry Instruction. */
|
||||
void
|
||||
adc()
|
||||
{
|
||||
load_dst();
|
||||
|
||||
if (CC_C) { /* do if carry is set */
|
||||
if (dstword == MPI)
|
||||
SET_CC_V();
|
||||
else
|
||||
CLR_CC_V();
|
||||
if (dstword == NEG_1)
|
||||
SET_CC_C();
|
||||
else
|
||||
CLR_CC_C();
|
||||
dstword++; /* add the carry */
|
||||
} else {
|
||||
CLR_CC_V();
|
||||
CLR_CC_C();
|
||||
}
|
||||
|
||||
CHG_CC_N(dstword);
|
||||
CHG_CC_Z(dstword);
|
||||
|
||||
store_dst_2();
|
||||
}
|
||||
|
||||
|
||||
/* asl() - Arithmetic Shift Left Instruction. */
|
||||
void
|
||||
asl()
|
||||
{
|
||||
load_dst();
|
||||
|
||||
if (dstword & SIGN)
|
||||
SET_CC_C();
|
||||
else
|
||||
CLR_CC_C();
|
||||
|
||||
dstword <<= 1;
|
||||
|
||||
CHG_CC_N(dstword);
|
||||
CHG_CC_Z(dstword);
|
||||
CHG_CC_V_XOR_C_N();
|
||||
|
||||
store_dst_2();
|
||||
}
|
||||
|
||||
/* asr() - Arithmetic Shift Right Instruction. */
|
||||
void
|
||||
asr()
|
||||
{
|
||||
load_dst();
|
||||
|
||||
if (dstword & LSBIT)
|
||||
SET_CC_C();
|
||||
else
|
||||
CLR_CC_C();
|
||||
|
||||
dstword = (dstword >> 1) + (dstword & SIGN); /* shift and replicate */
|
||||
|
||||
CHG_CC_N(dstword);
|
||||
CHG_CC_Z(dstword);
|
||||
|
||||
CHG_CC_V_XOR_C_N();
|
||||
|
||||
store_dst_2();
|
||||
}
|
||||
|
||||
/* clr() - Clear Instruction. */
|
||||
void
|
||||
clr()
|
||||
{
|
||||
CLR_CC_ALL(); SET_CC_Z();
|
||||
dstword=0; store_dst();
|
||||
}
|
||||
|
||||
/* com() - Complement Instruction. */
|
||||
void
|
||||
com()
|
||||
{
|
||||
load_dst();
|
||||
|
||||
dstword = ~dstword;
|
||||
|
||||
CHG_CC_N(dstword);
|
||||
CHG_CC_Z(dstword);
|
||||
CLR_CC_V();
|
||||
SET_CC_C();
|
||||
|
||||
store_dst_2();
|
||||
}
|
||||
|
||||
/* dec() - Decrement Instruction. */
|
||||
void
|
||||
dec()
|
||||
{
|
||||
load_dst();
|
||||
|
||||
if (dstword == MNI)
|
||||
SET_CC_V();
|
||||
else
|
||||
CLR_CC_V();
|
||||
|
||||
--dstword;
|
||||
|
||||
CHG_CC_N(dstword);
|
||||
CHG_CC_Z(dstword);
|
||||
|
||||
store_dst_2();
|
||||
}
|
||||
|
||||
/* inc() - Increment Instruction. */
|
||||
void
|
||||
inc()
|
||||
{
|
||||
load_dst();
|
||||
|
||||
if (dstword == MPI)
|
||||
SET_CC_V();
|
||||
else
|
||||
CLR_CC_V();
|
||||
|
||||
++dstword;
|
||||
|
||||
CHG_CC_N(dstword);
|
||||
CHG_CC_Z(dstword);
|
||||
|
||||
store_dst_2();
|
||||
}
|
||||
|
||||
/* neg() - Negate Instruction. */
|
||||
|
||||
void
|
||||
neg()
|
||||
{
|
||||
load_dst();
|
||||
|
||||
dstword = (NEG_1 - dstword) + 1;
|
||||
|
||||
CHG_CC_N(dstword);
|
||||
CHG_CC_Z(dstword);
|
||||
|
||||
if (dstword == MNI)
|
||||
SET_CC_V();
|
||||
else
|
||||
CLR_CC_V();
|
||||
|
||||
if (dstword == 0)
|
||||
CLR_CC_C();
|
||||
else
|
||||
SET_CC_C();
|
||||
|
||||
store_dst_2();
|
||||
}
|
||||
|
||||
/* rol() - Rotate Left Instruction. */
|
||||
void
|
||||
rol()
|
||||
{
|
||||
load_dst();
|
||||
|
||||
tmpword = dstword & SIGN; /* get sign bit */
|
||||
dstword <<= 1; /* shift */
|
||||
|
||||
if (CC_C) /* roll in carry */
|
||||
dstword += LSBIT;
|
||||
|
||||
if (tmpword) /* roll out to carry */
|
||||
SET_CC_C();
|
||||
else
|
||||
CLR_CC_C();
|
||||
|
||||
CHG_CC_N(dstword);
|
||||
CHG_CC_Z(dstword);
|
||||
CHG_CC_V_XOR_C_N();
|
||||
|
||||
store_dst_2();
|
||||
}
|
||||
|
||||
|
||||
/* ror() - Rotate Right Instruction. */
|
||||
void
|
||||
ror()
|
||||
{
|
||||
load_dst();
|
||||
|
||||
tmpword = dstword & LSBIT; /* get low bit */
|
||||
dstword >>= 1; /* shift */
|
||||
|
||||
if (CC_C) /* roll in carry */
|
||||
dstword += SIGN;
|
||||
|
||||
if (tmpword) /* roll out to carry */
|
||||
SET_CC_C();
|
||||
else
|
||||
CLR_CC_C();
|
||||
|
||||
CHG_CC_N(dstword);
|
||||
CHG_CC_Z(dstword);
|
||||
CHG_CC_V_XOR_C_N();
|
||||
|
||||
store_dst_2();
|
||||
}
|
||||
|
||||
/* sbc() - Subtract Carry Instruction. */
|
||||
void
|
||||
sbc()
|
||||
{
|
||||
load_dst();
|
||||
|
||||
if (dstword == MNI)
|
||||
SET_CC_V();
|
||||
else
|
||||
CLR_CC_V();
|
||||
|
||||
if (CC_C) { /* do if carry is set */
|
||||
if (dstword)
|
||||
CLR_CC_C();
|
||||
else
|
||||
SET_CC_C();
|
||||
--dstword; /* subtract carry */
|
||||
} else {
|
||||
CLR_CC_C();
|
||||
}
|
||||
|
||||
CHG_CC_N(dstword);
|
||||
CHG_CC_Z(dstword);
|
||||
|
||||
store_dst_2();
|
||||
}
|
||||
|
||||
/* swabi() - Swap Bytes Instruction. */
|
||||
void
|
||||
swabi()
|
||||
{
|
||||
u_int16_t data2;
|
||||
u_int16_t data3;
|
||||
|
||||
load_dst();
|
||||
|
||||
data2 = (dstword << 8) & 0xff00;
|
||||
data3 = (dstword >> 8) & 0x00ff;
|
||||
dstword = data2 + data3;
|
||||
|
||||
CLR_CC_ALL();
|
||||
CHGB_CC_N(data3); /* cool, negative and zero */
|
||||
CHGB_CC_Z(data3); /* checks done on low byte only */
|
||||
|
||||
store_dst_2();
|
||||
}
|
||||
|
||||
/* sxt() - Sign Extend Instruction. */
|
||||
void
|
||||
sxt()
|
||||
{
|
||||
if (CC_N) {
|
||||
dstword = NEG_1;
|
||||
CLR_CC_Z();
|
||||
} else {
|
||||
dstword = 0;
|
||||
SET_CC_Z();
|
||||
}
|
||||
CLR_CC_V();
|
||||
|
||||
store_dst();
|
||||
}
|
||||
|
||||
/* tst() - Test Instruction. */
|
||||
void
|
||||
tst()
|
||||
{
|
||||
load_dst();
|
||||
|
||||
CLR_CC_ALL();
|
||||
CHG_CC_N(dstword);
|
||||
CHG_CC_Z(dstword);
|
||||
}
|
||||
|
||||
/* tstb() - Test Byte Instruction. */
|
||||
void
|
||||
tstb()
|
||||
{
|
||||
loadb_dst();
|
||||
|
||||
CHGB_CC_N(dstbyte);
|
||||
CHGB_CC_Z(dstbyte);
|
||||
CLR_CC_V();
|
||||
CLR_CC_C();
|
||||
|
||||
}
|
||||
|
||||
/* aslb() - Arithmetic Shift Left Byte Instruction. */
|
||||
void
|
||||
aslb()
|
||||
{
|
||||
loadb_dst();
|
||||
|
||||
if (dstbyte & SIGN_B)
|
||||
SET_CC_C();
|
||||
else
|
||||
CLR_CC_C();
|
||||
|
||||
dstbyte <<= 1;
|
||||
|
||||
CHGB_CC_N(dstbyte);
|
||||
CHGB_CC_Z(dstbyte);
|
||||
CHG_CC_V_XOR_C_N();
|
||||
|
||||
storeb_dst_2();
|
||||
}
|
||||
|
||||
/* asrb() - Arithmetic Shift Right Byte Instruction. */
|
||||
void
|
||||
asrb()
|
||||
{
|
||||
loadb_dst();
|
||||
|
||||
if (dstbyte & LSBIT)
|
||||
SET_CC_C();
|
||||
else
|
||||
CLR_CC_C();
|
||||
|
||||
dstbyte = (dstbyte >> 1) + (dstbyte & SIGN_B); /* shift and replicate */
|
||||
|
||||
CHGB_CC_N(dstbyte);
|
||||
CHGB_CC_Z(dstbyte);
|
||||
CHG_CC_V_XOR_C_N();
|
||||
|
||||
storeb_dst_2();
|
||||
}
|
||||
|
||||
/* clrb() - Clear Byte Instruction. */
|
||||
void
|
||||
clrb()
|
||||
{
|
||||
CLR_CC_ALL(); SET_CC_Z();
|
||||
srcbyte=0; storeb_dst();
|
||||
}
|
||||
|
||||
|
||||
/* comb() - Complement Byte Instruction. */
|
||||
void
|
||||
comb()
|
||||
{
|
||||
loadb_dst();
|
||||
|
||||
dstbyte = ~dstbyte;
|
||||
|
||||
CHGB_CC_N(dstbyte);
|
||||
CHGB_CC_Z(dstbyte);
|
||||
CLR_CC_V();
|
||||
SET_CC_C();
|
||||
|
||||
storeb_dst_2();
|
||||
}
|
||||
|
||||
/* decb() - Decrement Byte Instruction. */
|
||||
void
|
||||
decb()
|
||||
{
|
||||
loadb_dst();
|
||||
|
||||
if (dstbyte == MNI_B)
|
||||
SET_CC_V();
|
||||
else
|
||||
CLR_CC_V();
|
||||
|
||||
--dstbyte;
|
||||
|
||||
CHGB_CC_N(dstbyte);
|
||||
CHGB_CC_Z(dstbyte);
|
||||
|
||||
storeb_dst_2();
|
||||
}
|
||||
|
||||
/* incb() - Increment Byte Instruction. */
|
||||
void
|
||||
incb()
|
||||
{
|
||||
loadb_dst();
|
||||
|
||||
if (dstbyte == MPI_B)
|
||||
SET_CC_V();
|
||||
else
|
||||
CLR_CC_V();
|
||||
|
||||
++dstbyte;
|
||||
|
||||
CHGB_CC_N(dstbyte);
|
||||
CHGB_CC_Z(dstbyte);
|
||||
|
||||
storeb_dst_2();
|
||||
}
|
||||
|
||||
/* negb() - Negate Byte Instruction. */
|
||||
void
|
||||
negb()
|
||||
{
|
||||
loadb_dst();
|
||||
|
||||
dstbyte = (NEG_1_B - dstbyte) + 1;/* hope this is right */
|
||||
|
||||
CHGB_CC_N(dstbyte);
|
||||
CHGB_CC_Z(dstbyte);
|
||||
|
||||
if (dstbyte == MNI_B)
|
||||
SET_CC_V();
|
||||
else
|
||||
CLR_CC_V();
|
||||
|
||||
if (dstbyte)
|
||||
SET_CC_C();
|
||||
else
|
||||
CLR_CC_C();
|
||||
|
||||
storeb_dst_2();
|
||||
}
|
||||
|
||||
/* rolb() - Rotate Left Byte Instruction. */
|
||||
void
|
||||
rolb()
|
||||
{
|
||||
loadb_dst();
|
||||
|
||||
tmpbyte = dstbyte & SIGN_B; /* get top bit */
|
||||
dstbyte <<= 1; /* shift */
|
||||
|
||||
if (CC_C) /* roll in carry */
|
||||
dstbyte = dstbyte + LSBIT;
|
||||
|
||||
if (tmpbyte) /* roll out to carry */
|
||||
SET_CC_C();
|
||||
else
|
||||
CLR_CC_C();
|
||||
|
||||
CHGB_CC_N(dstbyte);
|
||||
CHGB_CC_Z(dstbyte);
|
||||
CHG_CC_V_XOR_C_N();
|
||||
|
||||
storeb_dst_2();
|
||||
}
|
||||
|
||||
/* rorb() - Rotate Right Byte Instruction. */
|
||||
void
|
||||
rorb()
|
||||
{
|
||||
loadb_dst();
|
||||
|
||||
tmpbyte = dstbyte & LSBIT; /* get low bit */
|
||||
dstbyte >>= 1; /* shift */
|
||||
|
||||
if (CC_C) /* roll in carry */
|
||||
dstbyte += SIGN_B;
|
||||
|
||||
if (tmpbyte) /* roll out to carry */
|
||||
SET_CC_C();
|
||||
else
|
||||
CLR_CC_C();
|
||||
|
||||
CHGB_CC_N(dstbyte);
|
||||
CHGB_CC_Z(dstbyte);
|
||||
CHG_CC_V_XOR_C_N();
|
||||
|
||||
storeb_dst_2();
|
||||
}
|
||||
|
||||
/* adcb() - Add Carry Byte Instruction. */
|
||||
void
|
||||
adcb()
|
||||
{
|
||||
loadb_dst();
|
||||
|
||||
if (CC_C) { /* do if carry is set */
|
||||
if (dstbyte == MPI_B)
|
||||
SET_CC_V();
|
||||
else
|
||||
CLR_CC_V();
|
||||
if (dstbyte == NEG_1_B)
|
||||
SET_CC_C();
|
||||
else
|
||||
CLR_CC_C();
|
||||
++dstbyte; /* add the carry */
|
||||
} else {
|
||||
CLR_CC_V();
|
||||
CLR_CC_C();
|
||||
}
|
||||
|
||||
CHGB_CC_N(dstbyte);
|
||||
CHGB_CC_Z(dstbyte);
|
||||
|
||||
storeb_dst_2();
|
||||
}
|
||||
|
||||
/* sbcb() - Subtract Carry Byte Instruction. */
|
||||
void
|
||||
sbcb()
|
||||
{
|
||||
loadb_dst();
|
||||
|
||||
if (CC_C) { /* do if carry is set */
|
||||
if (dstbyte)
|
||||
CLR_CC_C();
|
||||
else
|
||||
SET_CC_C();
|
||||
|
||||
--dstbyte; /* subtract carry */
|
||||
} else {
|
||||
CLR_CC_C();
|
||||
}
|
||||
|
||||
if (dstbyte == MNI_B)
|
||||
SET_CC_V();
|
||||
else
|
||||
CLR_CC_V();
|
||||
|
||||
CHGB_CC_N(dstbyte);
|
||||
CHGB_CC_Z(dstbyte);
|
||||
|
||||
storeb_dst_2();
|
||||
}
|
||||
522
tools/apout/v1trap.c
Normal file
522
tools/apout/v1trap.c
Normal file
@@ -0,0 +1,522 @@
|
||||
/* v1trap.c - Deal with 1st Edition trap instructions.
|
||||
*
|
||||
* $Revision: 1.15 $
|
||||
* $Date: 2002/06/10 11:43:24 $
|
||||
*/
|
||||
#ifdef EMUV1
|
||||
#include "defines.h"
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/wait.h>
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
#include <utime.h>
|
||||
#include "v1trap.h"
|
||||
|
||||
#ifdef __linux__
|
||||
# undef STREAM_BUFFERING /* It seems to work */
|
||||
#else
|
||||
# define STREAM_BUFFERING /* but not for Linux */
|
||||
#endif
|
||||
|
||||
|
||||
/* Forward prototypes */
|
||||
#ifdef __STDC__
|
||||
#define P(s) s
|
||||
#else
|
||||
#define P(s) ()
|
||||
#endif
|
||||
static int v1trap_exec P((void));
|
||||
static int v1open_dir P((char *name));
|
||||
static u_int32_t sectosixty P((time_t tim));
|
||||
|
||||
#undef P
|
||||
|
||||
|
||||
/* V1 keeps some of the arguments to syscalls in registers, and some
|
||||
* after the `sys' instruction itself. The list below gives the number
|
||||
* of words, and the number in registers.
|
||||
*/
|
||||
struct v1sysent {
|
||||
int nwords;
|
||||
int nregs;
|
||||
};
|
||||
static struct v1sysent v1arg[] = {
|
||||
{0, 0}, {0, 0}, {0, 0}, {3, 1}, {3, 1}, {2, 0}, {1, 1}, {1, 1},
|
||||
{2, 0}, {2, 0}, {1, 0}, {2, 0}, {1, 0}, {0, 0}, {2, 0}, {2, 0},
|
||||
{2, 0}, {1, 0}, {2, 0}, {3, 1}, {3, 1}, {2, 0}, {1, 0}, {1, 1},
|
||||
{1, 1}, {0, 0}, {1, 0}, {1, 0}, {2, 1}, {1, 0}, {1, 0}, {2, 1},
|
||||
{2, 1}, {1, 0}
|
||||
};
|
||||
|
||||
/* Seeks on files in /dev are done in 512-byte blocks, not bytes.
|
||||
* If a fd's entry in the following table is 1, then it's a device
|
||||
* and not a file.
|
||||
*/
|
||||
int8_t isdev[NFILE]= {
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
};
|
||||
|
||||
static arglist V1A;
|
||||
|
||||
void v1trap()
|
||||
{
|
||||
extern int32_t AC, MQ; /* in ke11a.c */
|
||||
int i, mode, pid;
|
||||
int status, exitval, errval; /* used in V2 wait */
|
||||
int whence;
|
||||
u_int16_t argbase;
|
||||
int trapnum;
|
||||
long larg;
|
||||
char *buf, *buf2;
|
||||
char *fmode; /* used with fdopen only */
|
||||
|
||||
struct stat stbuf; /* used in STAT */
|
||||
struct tr_v1stat *t1; /* used in STAT */
|
||||
struct timeval tval[2]; /* used in SMTIME */
|
||||
|
||||
|
||||
|
||||
/* Work out the actual trap number, and */
|
||||
/* shift the PC up past any arguments */
|
||||
/* to the syscall. Calculate base of args */
|
||||
trapnum = ir & 077;
|
||||
argbase = regs[PC];
|
||||
regs[PC] += 2 * (v1arg[trapnum].nwords - v1arg[trapnum].nregs);
|
||||
|
||||
/* Move arguments into V1A so we can use them */
|
||||
for (i = 0; i < v1arg[trapnum].nregs; i++) V1A.uarg[i] = regs[i];
|
||||
for (; i < v1arg[trapnum].nwords; i++, argbase += 2)
|
||||
ll_word(argbase, V1A.uarg[i]);
|
||||
|
||||
TrapDebug((dbg_file, "pid %d %s: ", (int) getpid(), v1trap_name[trapnum]));
|
||||
|
||||
switch (trapnum) {
|
||||
|
||||
/* XXX STILL TO DO: V1_GTTY, V1_STTY, V1_TELL */
|
||||
|
||||
/* These syscalls are ignored, and return */
|
||||
/* with no effect on the caller */
|
||||
case V1_BREAK:
|
||||
case V1_CEMT:
|
||||
case V1_ILGINS:
|
||||
case V1_INTR:
|
||||
case V1_QUIT:
|
||||
case V1_RELE: return;
|
||||
|
||||
/* These syscalls are not implemented, and */
|
||||
/* always return no error to the caller */
|
||||
case V1_GTTY:
|
||||
case V1_STTY: i=0; break;
|
||||
/* These syscalls are not implemented, and */
|
||||
/* always return an error to the caller */
|
||||
case V1_MOUNT:
|
||||
case V1_UMOUNT: i = -1; break;
|
||||
|
||||
case V1_EXIT:
|
||||
if (Binary==IS_V1) exit(0);
|
||||
if (Binary==IS_V2) {
|
||||
exitval=regs[0] & 0xff;
|
||||
if (regs[PC]==16790) exitval=0; /* s2-tape /bin/as doesn't set r0 */
|
||||
TrapDebug((dbg_file, " with exitval %d\n", exitval));
|
||||
exit(exitval);
|
||||
}
|
||||
i = -1;
|
||||
break;
|
||||
|
||||
#define EPOCH71 31536000 /* # seconds from 1970 to 1971 */
|
||||
#define EPOCH72 63072000 /* # seconds from 1970 to 1972 */
|
||||
case V1_SMDATE:
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
if (buf[0] == '\0') buf = "."; /* Not documented anywhere */
|
||||
if (uarg1 == 0) buf = "."; /* Who knows? for V1 */
|
||||
i = stat(buf, &stbuf);
|
||||
TrapDebug((dbg_file, " on %s (stat %d) ", buf, i));
|
||||
if (i == -1) break;
|
||||
|
||||
/* Copy access time to preserve it */
|
||||
tval[0].tv_sec= stbuf.st_atime; tval[0].tv_usec=0;
|
||||
larg= (AC << 16) | (MQ & 0xffff); /* Get mod time in 60ths of a second */
|
||||
TrapDebug((dbg_file, " %ld -> ", larg));
|
||||
larg= larg/60 + EPOCH72; /* Convert to seconds since 1970 */
|
||||
TrapDebug((dbg_file, " 0x%lx ", larg));
|
||||
tval[1].tv_sec= larg; tval[1].tv_usec=0;
|
||||
i=utimes(buf, tval);
|
||||
TrapDebug((dbg_file, " and %d for utimes ", i));
|
||||
break;
|
||||
|
||||
case V1_TIME:
|
||||
/* Kludge: treat start of this year as the epoch. */
|
||||
/* Find #seconds from yearstart to now, multiply */
|
||||
/* by 60 so as to be in V1 units */
|
||||
larg = sectosixty(time(NULL));
|
||||
MQ = (int) larg & 0xffff;
|
||||
AC = ((int) larg >> 16) & 0xffff;
|
||||
i = 0; break;
|
||||
case V1_SEEK:
|
||||
/* Work out the args before we do the lseek */
|
||||
whence = uarg3;
|
||||
switch (uarg3) {
|
||||
case 0:
|
||||
larg = uarg2; break;
|
||||
case 1:
|
||||
case 2:
|
||||
larg = sarg2; break;
|
||||
}
|
||||
|
||||
if (ValidFD(sarg1) && isdev[sarg1]) larg*= 512;
|
||||
|
||||
#ifdef STREAM_BUFFERING
|
||||
if (ValidFD(sarg1) && stream[sarg1]) {
|
||||
i = fseek(stream[sarg1], larg, whence);
|
||||
if (i == 0)
|
||||
i = ftell(stream[sarg1]);
|
||||
} else
|
||||
#endif
|
||||
i = lseek(sarg1, larg, whence);
|
||||
|
||||
TrapDebug((dbg_file, " on fd %d amt %ld whence %d return %d ",
|
||||
sarg1, larg, whence, i));
|
||||
if (i != -1) i = 0;
|
||||
regs[0] = i;
|
||||
break;
|
||||
case V1_READ:
|
||||
buf = &dspace[uarg2];
|
||||
#ifdef STREAM_BUFFERING
|
||||
if (ValidFD(sarg1) && stream[sarg1])
|
||||
i = fread(buf, 1, sarg3, stream[sarg1]);
|
||||
else
|
||||
#endif
|
||||
i = read(sarg1, buf, sarg3);
|
||||
TrapDebug((dbg_file, " on fd %d return %d ", sarg1, i));
|
||||
regs[0] = i; break;
|
||||
case V1_LINK:
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
buf2 = xlate_filename(&dspace[uarg2]);
|
||||
i = link(buf, buf2);
|
||||
regs[0] = i; break;
|
||||
case V1_WRITE:
|
||||
buf = &dspace[uarg2];
|
||||
#ifdef STREAM_BUFFERING
|
||||
if (ValidFD(sarg1) && stream[sarg1])
|
||||
i = fwrite(buf, 1, sarg3, stream[sarg1]);
|
||||
else
|
||||
#endif
|
||||
i = write(sarg1, buf, sarg3);
|
||||
TrapDebug((dbg_file, " on fd %d return %d ", sarg1, i));
|
||||
regs[0] = i; break;
|
||||
case V1_CLOSE:
|
||||
#ifdef STREAM_BUFFERING
|
||||
if (ValidFD(sarg1) && stream[sarg1]) {
|
||||
i = fclose(stream[sarg1]);
|
||||
stream[sarg1] = NULL;
|
||||
} else
|
||||
#endif
|
||||
i = close(sarg1);
|
||||
if ((i==0) && ValidFD(sarg1)) isdev[sarg1]=0;
|
||||
TrapDebug((dbg_file, " on fd %d return %d ", sarg1, i));
|
||||
break;
|
||||
case V1_STAT:
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
if (buf[0] == '\0') buf = "."; /* Not documented anywhere */
|
||||
if (uarg1 == 0) buf = "."; /* Who knows? for V1 */
|
||||
buf2 = &dspace[uarg2];
|
||||
i = stat(buf, &stbuf);
|
||||
TrapDebug((dbg_file, " on %s return %d ", buf, i));
|
||||
goto dostat;
|
||||
case V1_FSTAT:
|
||||
buf2 = &dspace[uarg2];
|
||||
i = fstat(sarg1, &stbuf);
|
||||
TrapDebug((dbg_file, " on fd %d return %d ", sarg1, i));
|
||||
|
||||
dostat:
|
||||
if (i == -1) break;
|
||||
t1 = (struct tr_v1stat *) buf2;
|
||||
/* Inode numbers <41 are reserved for */
|
||||
/* device files. Ensure we don't use them */
|
||||
t1->inum = stbuf.st_ino & 0x7fff; if (t1->inum<41) t1->inum+=100;
|
||||
t1->inl = stbuf.st_nlink;
|
||||
t1->iuid = stbuf.st_uid;
|
||||
t1->isize = (u_int16_t) (stbuf.st_size & 0xffff);
|
||||
t1->iflags = (u_int16_t) (V1_ST_USED | V1_ST_MODIFIED);
|
||||
if (stbuf.st_size > 4095) t1->iflags |= V1_ST_LARGE;
|
||||
if (stbuf.st_mode & S_IFDIR) t1->iflags |= V1_ST_ISDIR;
|
||||
if (stbuf.st_mode & S_ISUID) t1->iflags |= V1_ST_SETUID;
|
||||
if (stbuf.st_mode & S_IXUSR) t1->iflags |= V1_ST_EXEC;
|
||||
if (stbuf.st_mode & S_IRUSR) t1->iflags |= V1_ST_OWNREAD;
|
||||
if (stbuf.st_mode & S_IWUSR) t1->iflags |= V1_ST_OWNWRITE;
|
||||
if (stbuf.st_mode & S_IROTH) t1->iflags |= V1_ST_WRLDREAD;
|
||||
if (stbuf.st_mode & S_IWOTH) t1->iflags |= V1_ST_WRLDWRITE;
|
||||
|
||||
larg = sectosixty(stbuf.st_ctime); copylong(t1->ctime, larg);
|
||||
larg = sectosixty(stbuf.st_mtime); copylong(t1->mtime, larg);
|
||||
break;
|
||||
case V1_UNLINK:
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
i = unlink(buf);
|
||||
break;
|
||||
case V1_OPEN:
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
|
||||
i = stat(buf, &stbuf); /* If file is a directory */
|
||||
if (i == 0 && (stbuf.st_mode & S_IFDIR)) {
|
||||
i = v1open_dir(buf);
|
||||
fmode = "w+";
|
||||
TrapDebug((dbg_file, "(dir) on %s return %d ", buf, i));
|
||||
} else {
|
||||
switch (sarg2) {
|
||||
case 0:
|
||||
sarg2 = O_RDONLY; fmode = "r"; break;
|
||||
case 1:
|
||||
sarg2 = O_WRONLY; fmode = "w"; break;
|
||||
default:
|
||||
sarg2 = O_RDWR; fmode = "w+"; break;
|
||||
}
|
||||
i = open(buf, sarg2);
|
||||
TrapDebug((dbg_file, " on %s return %d ", buf, i));
|
||||
}
|
||||
regs[0] = i;
|
||||
|
||||
if (ValidFD(i) && !strncmp(&dspace[uarg1],"/dev/",5)) {
|
||||
TrapDebug((dbg_file, " (device file) "));
|
||||
isdev[i]=1;
|
||||
}
|
||||
|
||||
#ifdef STREAM_BUFFERING
|
||||
if (i==-1) break;
|
||||
#if 0
|
||||
/* Now get its stream pointer if possible */
|
||||
/* Can someone explain why fdopen doesn't work for O_RDWR? */
|
||||
if (ValidFD(i) && !isatty(i) && (sarg2 != O_RDWR)) {
|
||||
stream[i] = fdopen(i, fmode); streammode[i] = fmode;
|
||||
}
|
||||
#endif
|
||||
stream[i] = fdopen(i, fmode); streammode[i] = fmode;
|
||||
#endif
|
||||
break;
|
||||
case V1_CHMOD:
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
mode = 0;
|
||||
if (uarg2 & V1_ST_SETUID) mode |= S_ISUID;
|
||||
if (uarg2 & V1_ST_EXEC) mode |= S_IXUSR | S_IXGRP | S_IXOTH;
|
||||
if (uarg2 & V1_ST_OWNREAD) mode |= S_IRUSR;
|
||||
if (uarg2 & V1_ST_OWNWRITE) mode |= S_IWUSR;
|
||||
if (uarg2 & V1_ST_WRLDREAD) mode |= S_IRGRP | S_IROTH;
|
||||
if (uarg2 & V1_ST_WRLDWRITE) mode |= S_IWGRP | S_IWOTH;
|
||||
i = chmod(buf, mode);
|
||||
break;
|
||||
case V1_MKDIR:
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
mode = 0;
|
||||
if (uarg2 & V1_ST_SETUID) mode |= S_ISUID;
|
||||
if (uarg2 & V1_ST_EXEC) mode |= S_IXUSR | S_IXGRP | S_IXOTH;
|
||||
if (uarg2 & V1_ST_OWNREAD) mode |= S_IRUSR;
|
||||
if (uarg2 & V1_ST_OWNWRITE) mode |= S_IWUSR;
|
||||
if (uarg2 & V1_ST_WRLDREAD) mode |= S_IRGRP | S_IROTH;
|
||||
if (uarg2 & V1_ST_WRLDWRITE) mode |= S_IWGRP | S_IWOTH;
|
||||
i = mkdir(buf, mode);
|
||||
break;
|
||||
case V1_CHOWN:
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
uarg2&= 0x3fff; /* Why are uids > 16384? */
|
||||
i = chown(buf, uarg2, 0);
|
||||
TrapDebug((dbg_file, " %d on %s return %d",uarg2,buf,i));
|
||||
break;
|
||||
case V1_CHDIR:
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
i = chdir(buf);
|
||||
break;
|
||||
case V1_CREAT:
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
mode = 0;
|
||||
if (uarg2 & V1_ST_SETUID) mode |= S_ISUID;
|
||||
if (uarg2 & V1_ST_EXEC) mode |= S_IXUSR | S_IXGRP | S_IXOTH;
|
||||
if (uarg2 & V1_ST_OWNREAD) mode |= S_IRUSR;
|
||||
if (uarg2 & V1_ST_OWNWRITE) mode |= S_IWUSR;
|
||||
if (uarg2 & V1_ST_WRLDREAD) mode |= S_IRGRP | S_IROTH;
|
||||
if (uarg2 & V1_ST_WRLDWRITE) mode |= S_IWGRP | S_IWOTH;
|
||||
i = creat(buf, mode);
|
||||
TrapDebug((dbg_file, " on %s return %d ", buf, i));
|
||||
#ifdef STREAM_BUFFERING
|
||||
if (ValidFD(i)) {
|
||||
stream[i] = fdopen(i, "w");
|
||||
streammode[i] = "w";
|
||||
}
|
||||
#endif
|
||||
regs[0] = i; break;
|
||||
case V1_EXEC:
|
||||
i = v1trap_exec();
|
||||
break;
|
||||
case V1_WAIT:
|
||||
i = wait(&status);
|
||||
if (Binary==IS_V1) break;
|
||||
/* 2nd Edition wait is different */
|
||||
regs[0] = i; /* Save pid found in r0 */
|
||||
if (i==-1) { MQ=0; break; }
|
||||
exitval=WEXITSTATUS(status);
|
||||
TrapDebug((dbg_file, "exitval %d ",exitval));
|
||||
errval=0;
|
||||
if (WIFSIGNALED(status)) {
|
||||
switch(WTERMSIG(status)) {
|
||||
case SIGBUS: errval=1; break;
|
||||
case SIGTRAP: errval=2; break;
|
||||
case SIGILL: errval=3; break;
|
||||
case SIGIOT: errval=4; break;
|
||||
case SIGEMT: errval=6; break;
|
||||
case SIGQUIT: errval=8; break;
|
||||
case SIGINT: errval=9; break;
|
||||
case SIGKILL: errval=10; break;
|
||||
}
|
||||
if (WCOREDUMP(status)) errval+=16;
|
||||
}
|
||||
TrapDebug((dbg_file, "errval %d ",errval));
|
||||
MQ= (exitval & 0xff) | (errval<<16);
|
||||
TrapDebug((dbg_file, "v2 return pid is %d, MQ is 0x%x ",i,MQ));
|
||||
break;
|
||||
case V1_FORK:
|
||||
pid = getpid();
|
||||
i = fork();
|
||||
switch (i) {
|
||||
/* Error, inform the parent */
|
||||
case -1: break;
|
||||
/* Child gets ppid in r0 */
|
||||
case 0:
|
||||
i = pid; break;
|
||||
/* Parent: Skip child `bf', pid into r0 */
|
||||
default:
|
||||
regs[PC] += 2;
|
||||
if (Binary==IS_V2) regs[0]=i;
|
||||
}
|
||||
break;
|
||||
case V1_GETUID:
|
||||
i = getuid();
|
||||
break;
|
||||
regs[0] = i;
|
||||
case V1_SETUID:
|
||||
i = setuid(sarg1);
|
||||
break;
|
||||
default:
|
||||
if (trapnum > V1_ILGINS) {
|
||||
fprintf(stderr, "Apout - unknown syscall %d at PC 0%o\n",
|
||||
trapnum, regs[PC]);
|
||||
} else {
|
||||
fprintf(stderr, "Apout - the %s syscall is not yet implemented\n",
|
||||
v1trap_name[trapnum]);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Clear C bit if no error, or */
|
||||
/* set C bit as there was an error */
|
||||
|
||||
if (i == -1) {
|
||||
SET_CC_C(); TrapDebug((dbg_file, "errno is %s\n", strerror(errno)));
|
||||
} else {
|
||||
CLR_CC_C(); TrapDebug((dbg_file, "return %d\n", i));
|
||||
}
|
||||
#ifdef DEBUG
|
||||
fflush(dbg_file);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static int v1trap_exec(void)
|
||||
{
|
||||
u_int16_t cptr, cptr2;
|
||||
char *buf, *name, *origpath;
|
||||
|
||||
origpath = strdup(&dspace[uarg1]);
|
||||
name = xlate_filename(origpath);
|
||||
TrapDebug((dbg_file, "%s Execing %s ", progname, name));
|
||||
|
||||
cptr = uarg2;
|
||||
|
||||
Argc = 0;
|
||||
while (Argc < MAX_ARGS) {
|
||||
ll_word(cptr, cptr2);
|
||||
if (cptr2 == 0)
|
||||
break;
|
||||
buf = &dspace[cptr2];
|
||||
Argv[Argc++] = strdup(buf);
|
||||
cptr += 2;
|
||||
TrapDebug((dbg_file, "%s ", buf));
|
||||
}
|
||||
Argv[Argc] = NULL;
|
||||
TrapDebug((dbg_file, "\n"));
|
||||
|
||||
if (load_a_out(name, origpath, 0) == -1) {
|
||||
for (Argc--; Argc >= 0; Argc--)
|
||||
free(Argv[Argc]);
|
||||
return (-1);
|
||||
}
|
||||
run(); /* Ok, so it's recursive, I dislike setjmp */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* 1st Edition reads directories as if they were ordinary files.
|
||||
* The solution is to read the directory entries, and build a
|
||||
* real file, which is passed back to the open call.
|
||||
* Limitation: 32-bit inode numbers are truncated to 16-bit ones.
|
||||
*/
|
||||
static int v1open_dir(char *name)
|
||||
{
|
||||
DIR *d;
|
||||
char *tmpname;
|
||||
int i;
|
||||
struct dirent *dent;
|
||||
|
||||
struct v1_direct {
|
||||
int16_t d_ino;
|
||||
int8_t d_name[8];
|
||||
} v1dent;
|
||||
|
||||
d = opendir(name);
|
||||
if (d == NULL) return (-1);
|
||||
tmpname = strdup(TMP_PLATE);
|
||||
i = mkstemp(tmpname);
|
||||
if (i == -1) {
|
||||
fprintf(stderr, "Apout - open_dir couldn't open %s\n", tmpname);
|
||||
exit(1);
|
||||
}
|
||||
unlink(tmpname);
|
||||
free(tmpname);
|
||||
|
||||
while ((dent = readdir(d)) != NULL) {
|
||||
v1dent.d_ino = dent->d_fileno & 0x7fff;
|
||||
if (v1dent.d_ino<41) v1dent.d_ino+=100;
|
||||
strncpy(v1dent.d_name, dent->d_name, 8);
|
||||
write(i, &v1dent, 10);
|
||||
}
|
||||
closedir(d);
|
||||
lseek(i, 0, SEEK_SET);
|
||||
return (i);
|
||||
}
|
||||
|
||||
/* Given a time, work out the number of 1/60ths of seconds since
|
||||
* the start of that time's year
|
||||
*/
|
||||
u_int32_t sectosixty(time_t tim)
|
||||
{
|
||||
time_t epoch;
|
||||
u_int32_t diff;
|
||||
struct tm *T;
|
||||
|
||||
T = gmtime(&tim);
|
||||
T->tm_sec = T->tm_min = T->tm_hour = T->tm_mon = 0;
|
||||
T->tm_mday = 1;
|
||||
|
||||
epoch = timegm(T); /* Find time at start of year */
|
||||
diff = 60 * (tim - epoch);
|
||||
if (diff > 0x71172C00) {
|
||||
fprintf(stderr, "Apout - V1 sectosixty too big by %d\n",diff-0x71172C00);
|
||||
}
|
||||
return (diff);
|
||||
}
|
||||
#endif /* EMUV1 */
|
||||
125
tools/apout/v1trap.h
Normal file
125
tools/apout/v1trap.h
Normal file
@@ -0,0 +1,125 @@
|
||||
/* v1trap.h - Deal with 1st Edition trap instructions.
|
||||
*
|
||||
* $Revision: 1.1 $
|
||||
* $Date: 1999/12/26 08:16:33 $
|
||||
*/
|
||||
|
||||
/* In this file, we list the trap number for each system call,
|
||||
* and the structures associated with several of the systems
|
||||
* calls in 1st Edition UNIX
|
||||
*/
|
||||
|
||||
#define V1_RELE 0
|
||||
#define V1_EXIT 1
|
||||
#define V1_FORK 2
|
||||
#define V1_READ 3
|
||||
#define V1_WRITE 4
|
||||
#define V1_OPEN 5
|
||||
#define V1_CLOSE 6
|
||||
#define V1_WAIT 7
|
||||
#define V1_CREAT 8
|
||||
#define V1_LINK 9
|
||||
#define V1_UNLINK 10
|
||||
#define V1_EXEC 11
|
||||
#define V1_CHDIR 12
|
||||
#define V1_TIME 13
|
||||
#define V1_MKDIR 14
|
||||
#define V1_CHMOD 15
|
||||
#define V1_CHOWN 16
|
||||
#define V1_BREAK 17
|
||||
#define V1_STAT 18
|
||||
#define V1_SEEK 19
|
||||
#define V1_TELL 20
|
||||
#define V1_MOUNT 21
|
||||
#define V1_UMOUNT 22
|
||||
#define V1_SETUID 23
|
||||
#define V1_GETUID 24
|
||||
#define V1_STIME 25
|
||||
#define V1_QUIT 26
|
||||
#define V1_INTR 27
|
||||
#define V1_FSTAT 28
|
||||
#define V1_CEMT 29
|
||||
#define V1_SMDATE 30
|
||||
#define V1_STTY 31
|
||||
#define V1_GTTY 32
|
||||
#define V1_ILGINS 33
|
||||
|
||||
|
||||
char *v1trap_name[]= {
|
||||
"rele",
|
||||
"exit",
|
||||
"fork",
|
||||
"read",
|
||||
"write",
|
||||
"open",
|
||||
"close",
|
||||
"wait",
|
||||
"creat",
|
||||
"link",
|
||||
"unlink",
|
||||
"exec",
|
||||
"chdir",
|
||||
"time",
|
||||
"mkdir",
|
||||
"chmod",
|
||||
"chown",
|
||||
"break",
|
||||
"stat",
|
||||
"seek",
|
||||
"tell",
|
||||
"mount",
|
||||
"umount",
|
||||
"setuid",
|
||||
"getuid",
|
||||
"stime",
|
||||
"quit",
|
||||
"intr",
|
||||
"fstat",
|
||||
"cemt",
|
||||
"smdate",
|
||||
"stty",
|
||||
"gtty",
|
||||
"ilgins"
|
||||
};
|
||||
|
||||
|
||||
struct tr_v1stat {
|
||||
u_int16_t inum;
|
||||
u_int16_t iflags; /* Mode */
|
||||
u_int8_t inl; /* Links */
|
||||
u_int8_t iuid;
|
||||
u_int16_t isize;
|
||||
int16_t iaddr[8]; /* Not used, I hope! */
|
||||
u_int32_t ctime;
|
||||
u_int32_t mtime;
|
||||
u_int16_t unused;
|
||||
};
|
||||
|
||||
/* Values for v1stat iflags */
|
||||
#define V1_ST_USED 0100000
|
||||
#define V1_ST_ISDIR 0040000
|
||||
#define V1_ST_MODIFIED 0020000
|
||||
#define V1_ST_LARGE 0010000
|
||||
#define V1_ST_SETUID 0000040
|
||||
#define V1_ST_EXEC 0000020
|
||||
#define V1_ST_OWNREAD 0000010
|
||||
#define V1_ST_OWNWRITE 0000004
|
||||
#define V1_ST_WRLDREAD 0000002
|
||||
#define V1_ST_WRLDWRITE 0000001
|
||||
|
||||
/* A union which will point at the trap args, so that
|
||||
* we can get at the various args of different types
|
||||
*/
|
||||
typedef union {
|
||||
int16_t sarg[4]; /* Signed 16-bit args */
|
||||
u_int16_t uarg[4]; /* Unsigned 16-bit args */
|
||||
} arglist;
|
||||
|
||||
#define sarg1 V1A.sarg[0]
|
||||
#define sarg2 V1A.sarg[1]
|
||||
#define sarg3 V1A.sarg[2]
|
||||
#define sarg4 V1A.sarg[3]
|
||||
#define uarg1 V1A.uarg[0]
|
||||
#define uarg2 V1A.uarg[1]
|
||||
#define uarg3 V1A.uarg[2]
|
||||
#define uarg4 V1A.uarg[3]
|
||||
709
tools/apout/v7trap.c
Normal file
709
tools/apout/v7trap.c
Normal file
@@ -0,0 +1,709 @@
|
||||
/* v7trap.c - Deal with V7 trap instructions. V5 and V6 syscalls are also
|
||||
* done here, because the syscall interface is nearly the same as V7.
|
||||
*
|
||||
* $Revision: 1.47 $
|
||||
* $Date: 2002/06/10 11:43:24 $
|
||||
*/
|
||||
#include "defines.h"
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/wait.h>
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
#include <utime.h>
|
||||
#include "v7trap.h"
|
||||
|
||||
#ifdef __linux__
|
||||
# undef STREAM_BUFFERING /* It seems to work */
|
||||
#else
|
||||
# define STREAM_BUFFERING /* but not for Linux */
|
||||
#endif
|
||||
|
||||
/* Forward prototypes */
|
||||
#ifdef __STDC__
|
||||
#define P(s) s
|
||||
#else
|
||||
#define P(s) ()
|
||||
#endif
|
||||
static int trap_exec P((int want_env));
|
||||
static int open_dir P((char *name));
|
||||
static int trap_gtty P((u_int16_t fd, u_int16_t ucnt));
|
||||
static int trap_stty P((u_int16_t fd, u_int16_t ucnt));
|
||||
static int v7signal P((int sig, int val));
|
||||
static void fixv6time P((time_t *t));
|
||||
#undef P
|
||||
|
||||
|
||||
/* V7 keeps some of the arguments to syscalls in registers, and some
|
||||
* after the `sys' instruction itself. The list below gives the number
|
||||
* of words, and the number in registers.
|
||||
*/
|
||||
struct v7sysent {
|
||||
int nwords;
|
||||
int nregs;
|
||||
};
|
||||
static struct v7sysent v7arg[] = {
|
||||
{0, 0}, {1, 1}, {0, 0}, {3, 1}, {3, 1}, {2, 0}, {1, 1}, {0, 0},
|
||||
{2, 0}, {2, 0}, {1, 0}, {2, 0}, {1, 0}, {0, 0}, {3, 0}, {2, 0},
|
||||
{3, 0}, {1, 0}, {2, 0}, {4, 1}, {0, 0}, {3, 0}, {1, 0}, {1, 1},
|
||||
{0, 0}, {2, 2}, {4, 1}, {1, 1}, {2, 1}, {0, 0}, {2, 0}, {2, 1},
|
||||
{2, 1}, {2, 0}, {1, 1}, {1, 0}, {0, 0}, {2, 1}, {0, 0}, {0, 0},
|
||||
{1, 1}, {2, 2}, {0, 0}, {1, 0}, {4, 0}, {0, 0}, {1, 1}, {0, 0},
|
||||
{2, 0}, {0, 0}, {0, 0}, {1, 0}, {3, 0}, {1, 0}, {3, 0}, {0, 0},
|
||||
{4, 0}, {0, 0}, {0, 0}, {3, 0}, {1, 0}, {1, 0}, {0, 0}, {0, 0}
|
||||
};
|
||||
|
||||
static arglist V7A;
|
||||
|
||||
|
||||
void
|
||||
v7trap()
|
||||
{
|
||||
int i, pid, pfd[2];
|
||||
int whence;
|
||||
u_int16_t argbase;
|
||||
int trapnum;
|
||||
long larg;
|
||||
char *buf, *buf2;
|
||||
char *fmode; /* used with fdopen only */
|
||||
|
||||
struct stat stbuf; /* used in STAT */
|
||||
struct tr_v7stat *t; /* used in STAT */
|
||||
struct tr_v6stat *t6; /* used in STAT */
|
||||
struct tr_timeb *tb; /* used in FTIME */
|
||||
struct timezone tz; /* used in FTIME */
|
||||
struct timeval tv; /* used in FTIME */
|
||||
struct timeval utv[2]; /* used in UTIME */
|
||||
|
||||
|
||||
|
||||
/* Work out the actual trap number, and */
|
||||
/* shift the PC up past any arguments */
|
||||
/* to the syscall. Calculate base of args */
|
||||
trapnum= ir & 077;
|
||||
if (trapnum==S_INDIR) {
|
||||
lli_word(regs[PC], argbase);
|
||||
ll_word(argbase, ir);
|
||||
trapnum= ir & 077; argbase+=2; regs[PC]+=2;
|
||||
} else {
|
||||
argbase=regs[PC];
|
||||
regs[PC]+= 2* (v7arg[trapnum].nwords - v7arg[trapnum].nregs);
|
||||
|
||||
/* However, V6 seek() has 1 less arg */
|
||||
if ((Binary==IS_A68 || Binary==IS_V6) || (Binary==IS_V5)) {
|
||||
if (trapnum==S_LSEEK) regs[PC]-=2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Move arguments into V7A so we can use them */
|
||||
for (i=0; i<v7arg[trapnum].nregs; i++) V7A.uarg[i]= regs[i];
|
||||
for (;i<v7arg[trapnum].nwords; i++,argbase+=2)
|
||||
ll_word(argbase, V7A.uarg[i]);
|
||||
|
||||
TrapDebug((dbg_file, "pid %d %s: ", (int)getpid(),v7trap_name[trapnum]));
|
||||
|
||||
switch (trapnum) {
|
||||
/* These syscalls are not implemented, and */
|
||||
/* always return EPERM to the caller */
|
||||
case S_PHYS:
|
||||
case S_PROF:
|
||||
case S_PTRACE:
|
||||
case S_ACCT:
|
||||
case S_MOUNT:
|
||||
case S_UMOUNT:
|
||||
case S_TIMES:
|
||||
i=-1; errno=EPERM; break;
|
||||
|
||||
/* These syscalls are ignored, and */
|
||||
/* always return C=0 to the caller */
|
||||
case S_LOCK:
|
||||
case S_STIME:
|
||||
case S_BREAK:
|
||||
i=0; break;
|
||||
case S_SYNC:
|
||||
sync(); i=0; break;
|
||||
|
||||
case S_SIGNAL:
|
||||
i= v7signal(uarg1, uarg2);
|
||||
break;
|
||||
case S_EXIT:
|
||||
exit(regs[0]);
|
||||
i=-1; errno=EPERM; break;
|
||||
case S_NICE:
|
||||
i= nice(regs[0]); break;
|
||||
case S_PAUSE:
|
||||
i = pause(); break;
|
||||
case S_DUP:
|
||||
if (sarg1 > 0100) {
|
||||
sarg1 -= 0100;
|
||||
i = dup2(sarg1, sarg2); /* Check that sarg2, not r1, holds */
|
||||
#ifdef STREAM_BUFFERING
|
||||
if ((i!=-1) && ValidFD(sarg2) && ValidFD(sarg1) && stream[sarg1]) {
|
||||
fmode= streammode[sarg1];
|
||||
stream[sarg2] = fdopen(sarg2, fmode);
|
||||
streammode[sarg2]=fmode;
|
||||
}
|
||||
#endif
|
||||
} else
|
||||
i = dup(sarg1);
|
||||
#ifdef STREAM_BUFFERING
|
||||
if ((i!=-1) && ValidFD(i)&& ValidFD(sarg1) && stream[sarg1]) {
|
||||
fmode= streammode[sarg1];
|
||||
stream[i] = fdopen(i, fmode);
|
||||
streammode[i]=fmode;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case S_TIME:
|
||||
i = time(&larg);
|
||||
|
||||
if ((Binary==IS_A68 || Binary==IS_V6) || (Binary==IS_V5)) {
|
||||
fixv6time(&larg); /* Fix annoying bug in V5/V6 ctime() */
|
||||
}
|
||||
regs[1] = larg & 0xffff;
|
||||
i = larg >> 16;
|
||||
break;
|
||||
case S_ALARM:
|
||||
i = alarm(uarg1); break;
|
||||
case S_UMASK:
|
||||
i = umask(uarg1); break;
|
||||
case S_LSEEK:
|
||||
/* Work out the args before we do the lseek */
|
||||
if ((Binary==IS_A68 || Binary==IS_V6) || (Binary==IS_V5)) {
|
||||
whence=uarg3;
|
||||
switch (uarg3) {
|
||||
case 0: larg= uarg2; break;
|
||||
case 1:
|
||||
case 2: larg= sarg2; break;
|
||||
case 3: whence=0; larg= 512 * uarg2; break;
|
||||
case 4: whence=1; larg= 512 * sarg2; break;
|
||||
case 5: whence=2; larg= 512 * sarg2; break;
|
||||
}
|
||||
} else {
|
||||
larg = (uarg2 << 16) | uarg3;
|
||||
whence= uarg4;
|
||||
}
|
||||
#ifdef STREAM_BUFFERING
|
||||
if (ValidFD(sarg1) && stream[sarg1]) {
|
||||
i = fseek(stream[sarg1], larg, whence);
|
||||
if (i == 0) i = ftell(stream[sarg1]);
|
||||
} else
|
||||
#endif
|
||||
i = lseek(sarg1, larg, whence);
|
||||
|
||||
TrapDebug((dbg_file, " on fd %d amt %ld whence %d return %d ",
|
||||
sarg1, larg, whence, i));
|
||||
if ((Binary==IS_A68 || Binary==IS_V6) || (Binary==IS_V5)) {
|
||||
if (i!=-1) i=0;
|
||||
break;
|
||||
}
|
||||
regs[1] = i & 0xffff;
|
||||
i = i >> 16;
|
||||
break;
|
||||
case S_READ:
|
||||
buf = &dspace[uarg2];
|
||||
#ifdef STREAM_BUFFERING
|
||||
if (ValidFD(sarg1) && stream[sarg1])
|
||||
i = fread(buf, 1, uarg3, stream[sarg1]);
|
||||
else
|
||||
#endif
|
||||
i = read(sarg1, buf, uarg3);
|
||||
TrapDebug((dbg_file, " on fd %d return %d ",sarg1,i));
|
||||
break;
|
||||
case S_LINK:
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
buf2 = xlate_filename(&dspace[uarg2]);
|
||||
if (!strcmp(buf, buf2)) i=0; /* Happens on mkdir(1) */
|
||||
else i = link(buf, buf2);
|
||||
break;
|
||||
case S_ACCESS:
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
i = access(buf, sarg2);
|
||||
break;
|
||||
case S_WRITE:
|
||||
buf = &dspace[uarg2];
|
||||
#ifdef STREAM_BUFFERING
|
||||
if (ValidFD(sarg1) && stream[sarg1])
|
||||
i = fwrite(buf, 1, uarg3, stream[sarg1]);
|
||||
else
|
||||
#endif
|
||||
i = write(sarg1, buf, uarg3);
|
||||
TrapDebug((dbg_file, " on fd %d return %d ",sarg1,i));
|
||||
break;
|
||||
case S_CLOSE:
|
||||
#ifdef STREAM_BUFFERING
|
||||
if (ValidFD(sarg1) && stream[sarg1]) {
|
||||
i = fclose(stream[sarg1]);
|
||||
stream[sarg1] = NULL;
|
||||
} else
|
||||
#endif
|
||||
i = close(sarg1);
|
||||
TrapDebug((dbg_file, " on fd %d return %d ",sarg1,i));
|
||||
break;
|
||||
case S_GTTY:
|
||||
i = trap_gtty(uarg1, uarg2); break;
|
||||
case S_STTY:
|
||||
i = trap_stty(uarg1, uarg2); break;
|
||||
case S_IOCTL:
|
||||
switch (uarg2) {
|
||||
case (('t' << 8) + 8): /* GTTY */
|
||||
i = trap_gtty(uarg1, uarg3); break;
|
||||
case (('t' << 8) + 9): /* STTY */
|
||||
i = trap_stty(uarg1, uarg3); break;
|
||||
default:
|
||||
i=0;
|
||||
}
|
||||
break;
|
||||
case S_FTIME:
|
||||
buf = &dspace[uarg1];
|
||||
tb = (struct tr_timeb *) buf;
|
||||
i = gettimeofday(&tv, &tz);
|
||||
if (i == -1) break;
|
||||
copylong(tb->time, tv.tv_sec);
|
||||
#if 0
|
||||
buf = (char *) &(tb->time);
|
||||
buf2 = (char *) &(tv.tv_sec);
|
||||
buf[0] = buf2[2]; buf[1] = buf2[3]; buf[2] = buf2[0]; buf[3] = buf2[1];
|
||||
#endif
|
||||
tb->millitm = tv.tv_usec / 1000;
|
||||
tb->timezone = tz.tz_minuteswest;
|
||||
tb->dstflag = tz.tz_dsttime;
|
||||
break;
|
||||
case S_STAT:
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
if (buf[0]=='\0') buf="."; /* Not documented anywhere */
|
||||
if (uarg1==0) buf=".";
|
||||
buf2 = &dspace[uarg2];
|
||||
i = stat(buf, &stbuf);
|
||||
TrapDebug((dbg_file, " on %s return %d ",buf,i));
|
||||
goto dostat;
|
||||
case S_FSTAT:
|
||||
buf2 = &dspace[uarg2];
|
||||
i = fstat(sarg1, &stbuf);
|
||||
TrapDebug((dbg_file, " on fd %d return %d ",sarg1,i));
|
||||
|
||||
dostat:
|
||||
if (i == -1) break;
|
||||
/* V6 and V7 have different stats */
|
||||
if ((Binary==IS_A68 || Binary==IS_V6) || (Binary==IS_V5)) {
|
||||
t6 = (struct tr_v6stat *) buf2;
|
||||
t6->idev = stbuf.st_dev;
|
||||
t6->inum = stbuf.st_ino;
|
||||
t6->iflags = stbuf.st_mode;
|
||||
t6->inl = stbuf.st_nlink;
|
||||
t6->iuid = stbuf.st_uid;
|
||||
t6->igid = stbuf.st_gid;
|
||||
t6->isize = (u_int16_t) (stbuf.st_size & 0xffff);
|
||||
t6->isize0 = (u_int8_t) ((stbuf.st_size>>16) & 0xff);
|
||||
/* Fix annoying bug in V5/V6 ctime() */
|
||||
fixv6time(&(stbuf.st_atime));
|
||||
fixv6time(&(stbuf.st_mtime));
|
||||
copylong(t6->atime, stbuf.st_atime);
|
||||
copylong(t6->mtime, stbuf.st_mtime);
|
||||
#if 0
|
||||
buf = (char *) &(t6->atime);
|
||||
buf2 = (char *) &(stbuf.st_atime);
|
||||
buf[0]= buf2[2]; buf[1]= buf2[3]; buf[2]= buf2[0]; buf[3]= buf2[1];
|
||||
buf = (char *) &(t6->mtime);
|
||||
buf2 = (char *) &(stbuf.st_mtime);
|
||||
buf[0]= buf2[2]; buf[1]= buf2[3]; buf[2]= buf2[0]; buf[3]= buf2[1];
|
||||
#endif
|
||||
} else {
|
||||
t = (struct tr_v7stat *) buf2;
|
||||
t->st_dev = stbuf.st_dev;
|
||||
t->st_ino = stbuf.st_ino;
|
||||
t->st_mode = stbuf.st_mode;
|
||||
t->st_nlink = stbuf.st_nlink;
|
||||
t->st_uid = stbuf.st_uid;
|
||||
t->st_gid = stbuf.st_gid;
|
||||
t->st_rdev = stbuf.st_rdev;
|
||||
copylong(t->st_size, stbuf.st_size);
|
||||
copylong(t->st_atim, stbuf.st_atime);
|
||||
copylong(t->st_mtim, stbuf.st_mtime);
|
||||
copylong(t->st_ctim, stbuf.st_ctime);
|
||||
#if 0
|
||||
buf = (char *) &(t->st_size);
|
||||
buf2 = (char *) &(stbuf.st_size);
|
||||
buf[0]= buf2[2]; buf[1]= buf2[3]; buf[2]= buf2[0]; buf[3]= buf2[1];
|
||||
buf = (char *) &(t->st_atim);
|
||||
buf2 = (char *) &(stbuf.st_atime);
|
||||
buf[0]= buf2[2]; buf[1]= buf2[3]; buf[2]= buf2[0]; buf[3]= buf2[1];
|
||||
buf = (char *) &(t->st_mtim);
|
||||
buf2 = (char *) &(stbuf.st_mtime);
|
||||
buf[0]= buf2[2]; buf[1]= buf2[3]; buf[2]= buf2[0]; buf[3]= buf2[1];
|
||||
buf = (char *) &(t->st_ctim);
|
||||
buf2 = (char *) &(stbuf.st_ctime);
|
||||
buf[0]= buf2[2]; buf[1]= buf2[3]; buf[2]= buf2[0]; buf[3]= buf2[1];
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case S_UTIME:
|
||||
utv[0].tv_usec = utv[1].tv_usec = 0;
|
||||
copylong(dspace[uarg2], utv[0].tv_sec);
|
||||
copylong(dspace[uarg2+4], utv[1].tv_sec);
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
#if 0
|
||||
buf2 = &dspace[uarg2];
|
||||
buf3 = (char *) &(utv[0].tv_sec);
|
||||
buf3[0]= buf2[2]; buf3[1]= buf2[3]; buf3[2]= buf2[0]; buf3[3]= buf2[1];
|
||||
|
||||
buf2 += 4;
|
||||
buf3 = (char *) &(utv[1].tv_sec);
|
||||
buf3[0]= buf2[2]; buf3[1]= buf2[3]; buf3[2]= buf2[0]; buf3[3]= buf2[1];
|
||||
#endif
|
||||
|
||||
i = utimes(buf, utv); break;
|
||||
case S_UNLINK:
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
i = unlink(buf); break;
|
||||
case S_OPEN:
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
|
||||
i = stat(buf, &stbuf); /* If file is a directory */
|
||||
if (i == 0 && (stbuf.st_mode & S_IFDIR)) {
|
||||
i = open_dir(buf);
|
||||
fmode = "w+";
|
||||
TrapDebug((dbg_file, "(dir) on %s return %d ",buf,i));
|
||||
} else {
|
||||
switch (sarg2) {
|
||||
case 0: sarg2 = O_RDONLY; fmode = "r"; break;
|
||||
case 1: sarg2 = O_WRONLY; fmode = "w"; break;
|
||||
default: sarg2 = O_RDWR; fmode = "w+"; break;
|
||||
}
|
||||
i = open(buf, sarg2);
|
||||
TrapDebug((dbg_file, " on %s return %d ",buf,i));
|
||||
}
|
||||
|
||||
#ifdef STREAM_BUFFERING
|
||||
if (i==-1) break;
|
||||
#if 0
|
||||
/* Now get its stream pointer if possible */
|
||||
/* Can someone explain why fdopen doesn't work for O_RDWR? */
|
||||
if (ValidFD(i) && !isatty(i) && (sarg2!=O_RDWR)) {
|
||||
stream[i] = fdopen(i, fmode); streammode[i]=fmode;
|
||||
}
|
||||
#endif
|
||||
stream[i] = fdopen(i, fmode); streammode[i]=fmode;
|
||||
#endif
|
||||
break;
|
||||
case S_MKNOD:
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
|
||||
if ((uarg2 & 077000) == 040000) {
|
||||
/* It's a directory creation */
|
||||
i= mkdir(buf, uarg2 & 0777);
|
||||
} else
|
||||
i = mknod(buf, uarg2, sarg3);
|
||||
break;
|
||||
case S_CHMOD:
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
i = chmod(buf, uarg2); break;
|
||||
case S_KILL:
|
||||
i = kill(sarg1, sarg2); break;
|
||||
case S_CHOWN:
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
i = chown(buf, sarg2, sarg3); break;
|
||||
case S_PIPE:
|
||||
i = pipe(pfd);
|
||||
if (i == -1) break;
|
||||
#ifdef STREAM_BUFFERING
|
||||
if (ValidFD(pfd[0])) {
|
||||
stream[pfd[0]] = fdopen(pfd[0], "r");
|
||||
streammode[pfd[0]]= "r";
|
||||
}
|
||||
if (ValidFD(pfd[1])) {
|
||||
stream[pfd[1]] = fdopen(pfd[1], "w");
|
||||
streammode[pfd[1]]= "w";
|
||||
}
|
||||
#endif
|
||||
i = pfd[0]; regs[1] = pfd[1]; break;
|
||||
case S_CHROOT:
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
if (buf == NULL) { i=-1; errno=ENOENT; break; }
|
||||
set_apout_root(buf);
|
||||
i=0; break;
|
||||
case S_CHDIR:
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
i = chdir(buf); break;
|
||||
case S_CREAT:
|
||||
buf = xlate_filename(&dspace[uarg1]);
|
||||
i = creat(buf, sarg2);
|
||||
#ifdef STREAM_BUFFERING
|
||||
if (i==-1) break;
|
||||
if (ValidFD(i)) {
|
||||
stream[i] = fdopen(i, "w");
|
||||
streammode[i]= "w";
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case S_EXECE:
|
||||
i= trap_exec(1); break;
|
||||
|
||||
case S_EXEC:
|
||||
i= trap_exec(0); break;
|
||||
case S_WAIT:
|
||||
i = wait(&pid);
|
||||
if (i == -1) break;
|
||||
regs[1] = pid; break;
|
||||
case S_FORK:
|
||||
pid = getpid();
|
||||
i = fork();
|
||||
switch (i) {
|
||||
/* Error, inform the parent */
|
||||
case -1: break;
|
||||
/* Child gets ppid in r0 */
|
||||
case 0: i = pid; break;
|
||||
/* Parent: Skip child `bf', pid into r0 */
|
||||
default: regs[PC] += 2;
|
||||
}
|
||||
break;
|
||||
case S_GETUID:
|
||||
i = geteuid(); regs[1] = i;
|
||||
i = getuid(); break;
|
||||
case S_GETPID:
|
||||
i = getpid(); break;
|
||||
case S_GETGID:
|
||||
i = getegid(); regs[1] = i;
|
||||
i = getgid(); break;
|
||||
case S_SETUID:
|
||||
i = setuid(sarg1); break;
|
||||
case S_SETGID:
|
||||
i = setgid(sarg1); break;
|
||||
default:
|
||||
if (trapnum>S_CHROOT) {
|
||||
fprintf(stderr,"Apout - unknown syscall %d at PC 0%o\n",
|
||||
trapnum,regs[PC]);
|
||||
} else {
|
||||
fprintf(stderr,"Apout - the %s syscall is not yet implemented\n",
|
||||
v7trap_name[trapnum]);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Set r0 to either errno or i, */
|
||||
/* and clear/set C bit */
|
||||
|
||||
if (i == -1) {
|
||||
SET_CC_C();
|
||||
TrapDebug((dbg_file, "errno is %s\n", strerror(errno)));
|
||||
} else {
|
||||
CLR_CC_C(); regs[0]=i;
|
||||
#ifdef DEBUG
|
||||
if (trap_debug) {
|
||||
fprintf(dbg_file, "return %d\n", i);
|
||||
fflush(dbg_file);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Translate V7 signal value to our value. */
|
||||
static int v7sig[] = {
|
||||
0, SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGIOT, SIGEMT,
|
||||
SIGFPE, SIGKILL, SIGBUS, SIGSEGV, SIGSYS, SIGPIPE, SIGALRM, SIGTERM
|
||||
};
|
||||
|
||||
static int
|
||||
trap_exec(int want_env)
|
||||
{
|
||||
int i;
|
||||
u_int16_t cptr, cptr2;
|
||||
char *buf, *name, *origpath;
|
||||
|
||||
origpath = strdup(&dspace[uarg1]);
|
||||
name = xlate_filename(origpath);
|
||||
TrapDebug((dbg_file, "%s Execing %s ", progname, name));
|
||||
|
||||
for (i=0;i<V7_NSIG;i++) signal(v7sig[i], SIG_DFL);
|
||||
|
||||
cptr=uarg2;
|
||||
|
||||
Argc=0; Envc=0;
|
||||
while (Argc < MAX_ARGS) {
|
||||
ll_word(cptr, cptr2);
|
||||
if (cptr2 == 0)
|
||||
break;
|
||||
buf = &dspace[cptr2];
|
||||
Argv[Argc++] = strdup(buf);
|
||||
cptr += 2;
|
||||
TrapDebug((dbg_file, "%s ", buf));
|
||||
}
|
||||
Argv[Argc] = NULL;
|
||||
TrapDebug((dbg_file, "\n"));
|
||||
|
||||
if (want_env) {
|
||||
cptr=uarg3;
|
||||
while (Envc < MAX_ARGS) {
|
||||
ll_word(cptr, cptr2);
|
||||
if (cptr2 == 0)
|
||||
break;
|
||||
buf = &dspace[cptr2];
|
||||
Envp[Envc++] = strdup(buf);
|
||||
cptr += 2;
|
||||
}
|
||||
}
|
||||
Envp[Envc] = NULL;
|
||||
|
||||
if (load_a_out(name, origpath, want_env) == -1) {
|
||||
for (Argc--; Argc >= 0; Argc--) free(Argv[Argc]);
|
||||
for (Envc--; Envc >= 0; Envc--) free(Envp[Envc]);
|
||||
errno= ENOENT; return(-1);
|
||||
}
|
||||
run(); /* Ok, so it's recursive, I dislike setjmp */
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* 7th Edition reads directories as if they were ordinary files.
|
||||
* The solution is to read the directory entries, and build a
|
||||
* real file, which is passed back to the open call.
|
||||
* Limitation: 32-bit inode numbers are truncated to 16-bit ones.
|
||||
*/
|
||||
static int
|
||||
open_dir(char *name)
|
||||
{
|
||||
DIR *d;
|
||||
char *tmpname;
|
||||
int i;
|
||||
struct dirent *dent;
|
||||
|
||||
struct old_direct {
|
||||
int16_t d_ino;
|
||||
int8_t d_name[14];
|
||||
} odent;
|
||||
|
||||
d = opendir(name);
|
||||
if (d == NULL) return (-1);
|
||||
tmpname= strdup(TMP_PLATE);
|
||||
i= mkstemp(tmpname);
|
||||
if (i == -1) {
|
||||
fprintf(stderr,"Apout - open_dir couldn't open %s\n", tmpname); exit(1);
|
||||
}
|
||||
unlink(tmpname); free(tmpname);
|
||||
|
||||
while ((dent = readdir(d)) != NULL) {
|
||||
odent.d_ino = dent->d_fileno;
|
||||
strncpy(odent.d_name, dent->d_name, 14);
|
||||
write(i, &odent, 16);
|
||||
}
|
||||
closedir(d);
|
||||
lseek(i, 0, SEEK_SET);
|
||||
return (i);
|
||||
}
|
||||
|
||||
static int
|
||||
trap_gtty(u_int16_t fd, u_int16_t ucnt)
|
||||
{
|
||||
struct tr_sgttyb *sgtb; /* used in GTTY/STTY */
|
||||
struct termios tios; /* used in GTTY/STTY */
|
||||
int i;
|
||||
|
||||
i = tcgetattr(fd, &tios);
|
||||
if (i == -1)
|
||||
return i;
|
||||
CLR_CC_C();
|
||||
sgtb = (struct tr_sgttyb *) & dspace[ucnt];
|
||||
sgtb->sg_ispeed = tios.c_ispeed;
|
||||
sgtb->sg_ospeed = tios.c_ospeed;
|
||||
sgtb->sg_erase = tios.c_cc[VERASE];
|
||||
sgtb->sg_kill = tios.c_cc[VKILL];
|
||||
sgtb->sg_flags = 0;
|
||||
if (tios.c_oflag & OXTABS)
|
||||
sgtb->sg_flags |= TR_XTABS;
|
||||
if (tios.c_cflag & PARENB) {
|
||||
if (tios.c_cflag & PARODD)
|
||||
sgtb->sg_flags |= TR_ODDP;
|
||||
else
|
||||
sgtb->sg_flags |= TR_EVENP;
|
||||
} else
|
||||
sgtb->sg_flags |= TR_ANYP;
|
||||
if (tios.c_oflag & ONLCR)
|
||||
sgtb->sg_flags |= TR_CRMOD;
|
||||
if (tios.c_lflag & ECHO)
|
||||
sgtb->sg_flags |= TR_ECHO;
|
||||
if (!(tios.c_lflag & ICANON)) {
|
||||
if (!(tios.c_lflag & ECHO))
|
||||
sgtb->sg_flags |= TR_CBREAK;
|
||||
else
|
||||
sgtb->sg_flags |= TR_RAW;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int
|
||||
trap_stty(u_int16_t fd, u_int16_t ucnt)
|
||||
{
|
||||
struct tr_sgttyb *sgtb; /* used in GTTY/STTY */
|
||||
struct termios tios; /* used in GTTY/STTY */
|
||||
int i;
|
||||
|
||||
if (ucnt != 0) {
|
||||
sgtb = (struct tr_sgttyb *) & dspace[ucnt];
|
||||
tios.c_ispeed = sgtb->sg_ispeed;
|
||||
tios.c_ospeed = sgtb->sg_ospeed;
|
||||
tios.c_cc[VERASE] = sgtb->sg_erase;
|
||||
tios.c_cc[VKILL] = sgtb->sg_kill;
|
||||
if (sgtb->sg_flags & TR_XTABS)
|
||||
tios.c_oflag |= OXTABS;
|
||||
if (sgtb->sg_flags & TR_ODDP) {
|
||||
tios.c_cflag |= PARENB;
|
||||
tios.c_cflag &= ~PARODD;
|
||||
}
|
||||
if (sgtb->sg_flags & TR_EVENP)
|
||||
tios.c_cflag |= PARENB | PARODD;
|
||||
if (sgtb->sg_flags & TR_ANYP)
|
||||
tios.c_cflag &= ~PARENB;
|
||||
if (sgtb->sg_flags & TR_CRMOD)
|
||||
tios.c_oflag |= ONLCR;
|
||||
if (sgtb->sg_flags & TR_ECHO)
|
||||
tios.c_lflag |= ECHO;
|
||||
if (sgtb->sg_flags & TR_RAW) {
|
||||
tios.c_lflag &= (~ICANON) & (~ECHO);
|
||||
for (i = 0; i < NCCS; i++)
|
||||
tios.c_cc[i] = 0;
|
||||
tios.c_cc[VMIN] = 1;
|
||||
}
|
||||
if (sgtb->sg_flags & TR_CBREAK) {
|
||||
tios.c_lflag &= (~ICANON);
|
||||
tios.c_lflag |= ECHO;
|
||||
for (i = 0; i < NCCS; i++)
|
||||
tios.c_cc[i] = 0;
|
||||
tios.c_cc[VMIN] = 1;
|
||||
}
|
||||
i = tcsetattr(fd, TCSANOW, &tios);
|
||||
return (i);
|
||||
} else
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
||||
/* Where possible, deal with signals */
|
||||
static int v7signal(int sig, int val)
|
||||
{
|
||||
if (sig>V7_NSIG) { errno=EINVAL; return(-1); }
|
||||
if (v7sig[sig]==0) return(0);
|
||||
|
||||
switch(val) {
|
||||
case V7_SIG_IGN:
|
||||
return((int)signal(v7sig[sig], SIG_IGN));
|
||||
case V7_SIG_DFL:
|
||||
return((int)signal(v7sig[sig], SIG_DFL));
|
||||
default:
|
||||
return(0); /* No handling of this as yet */
|
||||
}
|
||||
}
|
||||
|
||||
/* Workaround for bug in V5/V6 ctime() */
|
||||
static void fixv6time(time_t *t)
|
||||
{
|
||||
struct tm *T;
|
||||
|
||||
T=gmtime(t);
|
||||
if (T->tm_year>98) T->tm_year=98;
|
||||
*t=timegm(T);
|
||||
}
|
||||
229
tools/apout/v7trap.h
Normal file
229
tools/apout/v7trap.h
Normal file
@@ -0,0 +1,229 @@
|
||||
/* v7trap.h - Deal with V7 trap instructions. Also do V5 and V6 syscalls.
|
||||
*
|
||||
* $Revision: 2.17 $
|
||||
* $Date: 1999/12/26 08:16:33 $
|
||||
*/
|
||||
|
||||
/* In this file, we list the trap number for each system call,
|
||||
* and the structures associated with several of the systems
|
||||
* calls in 7th Edition UNIX
|
||||
*/
|
||||
|
||||
#define S_INDIR 0
|
||||
#define S_EXIT 1
|
||||
#define S_FORK 2
|
||||
#define S_READ 3
|
||||
#define S_WRITE 4
|
||||
#define S_OPEN 5
|
||||
#define S_CLOSE 6
|
||||
#define S_WAIT 7
|
||||
#define S_CREAT 8
|
||||
#define S_LINK 9
|
||||
#define S_UNLINK 10
|
||||
#define S_EXEC 11
|
||||
#define S_CHDIR 12
|
||||
#define S_TIME 13
|
||||
#define S_MKNOD 14
|
||||
#define S_CHMOD 15
|
||||
#define S_CHOWN 16
|
||||
#define S_BREAK 17
|
||||
#define S_STAT 18
|
||||
#define S_LSEEK 19
|
||||
#define S_GETPID 20
|
||||
#define S_MOUNT 21
|
||||
#define S_UMOUNT 22
|
||||
#define S_SETUID 23
|
||||
#define S_GETUID 24
|
||||
#define S_STIME 25
|
||||
#define S_PTRACE 26
|
||||
#define S_ALARM 27
|
||||
#define S_FSTAT 28
|
||||
#define S_PAUSE 29
|
||||
#define S_UTIME 30
|
||||
#define S_STTY 31
|
||||
#define S_GTTY 32
|
||||
#define S_ACCESS 33
|
||||
#define S_NICE 34
|
||||
#define S_FTIME 35
|
||||
#define S_SYNC 36
|
||||
#define S_KILL 37
|
||||
#define S_DUP 41
|
||||
#define S_PIPE 42
|
||||
#define S_TIMES 43
|
||||
#define S_PROF 44
|
||||
#define S_SETGID 46
|
||||
#define S_GETGID 47
|
||||
#define S_SIGNAL 48
|
||||
#define S_ACCT 51
|
||||
#define S_PHYS 52
|
||||
#define S_LOCK 53
|
||||
#define S_IOCTL 54
|
||||
#define S_EXECE 59
|
||||
#define S_UMASK 60
|
||||
#define S_CHROOT 61
|
||||
|
||||
|
||||
char *v7trap_name[]= {
|
||||
"indir",
|
||||
"exit",
|
||||
"fork",
|
||||
"read",
|
||||
"write",
|
||||
"open",
|
||||
"close",
|
||||
"wait",
|
||||
"creat",
|
||||
"link",
|
||||
"unlink",
|
||||
"exec",
|
||||
"chdir",
|
||||
"time",
|
||||
"mknod",
|
||||
"chmod",
|
||||
"chown",
|
||||
"break",
|
||||
"stat",
|
||||
"lseek",
|
||||
"getpid",
|
||||
"mount",
|
||||
"umount",
|
||||
"setuid",
|
||||
"getuid",
|
||||
"stime",
|
||||
"ptrace",
|
||||
"alarm",
|
||||
"fstat",
|
||||
"pause",
|
||||
"utime",
|
||||
"stty",
|
||||
"gtty",
|
||||
"access",
|
||||
"nice",
|
||||
"ftime",
|
||||
"sync",
|
||||
"kill",
|
||||
"unknown",
|
||||
"unknown",
|
||||
"unknown",
|
||||
"dup",
|
||||
"pipe",
|
||||
"times",
|
||||
"prof",
|
||||
"unknown",
|
||||
"setgid",
|
||||
"getgid",
|
||||
"signal",
|
||||
"unknown",
|
||||
"unknown",
|
||||
"acct",
|
||||
"phys",
|
||||
"lock",
|
||||
"ioctl",
|
||||
"unknown",
|
||||
"unknown",
|
||||
"unknown",
|
||||
"unknown",
|
||||
"exece",
|
||||
"umask",
|
||||
"chroot"
|
||||
};
|
||||
|
||||
|
||||
struct tr_v7stat {
|
||||
int16_t st_dev;
|
||||
u_int16_t st_ino;
|
||||
u_int16_t st_mode;
|
||||
int16_t st_nlink;
|
||||
int16_t st_uid;
|
||||
int16_t st_gid;
|
||||
int16_t st_rdev;
|
||||
int8_t st_size[4]; /* Alignment problems */
|
||||
int8_t st_atim[4]; /* Alignment problems */
|
||||
int8_t st_mtim[4]; /* Alignment problems */
|
||||
int8_t st_ctim[4]; /* Alignment problems */
|
||||
};
|
||||
|
||||
struct tr_v6stat {
|
||||
int16_t idev; /* Device */
|
||||
int16_t inum;
|
||||
int16_t iflags; /* Mode */
|
||||
int8_t inl; /* Links */
|
||||
int8_t iuid;
|
||||
int8_t igid;
|
||||
u_int8_t isize0; /* Most significant 8 bits */
|
||||
u_int16_t isize;
|
||||
int16_t iaddr[8]; /* Not used, I hope! */
|
||||
u_int32_t atime; /* Alignment problems */
|
||||
u_int32_t mtime; /* Alignment problems */
|
||||
};
|
||||
|
||||
struct tr_timeb {
|
||||
u_int32_t time;
|
||||
u_int16_t millitm;
|
||||
int16_t timezone;
|
||||
int16_t dstflag;
|
||||
};
|
||||
|
||||
struct tr_sgttyb {
|
||||
int8_t sg_ispeed; /* input speed */
|
||||
int8_t sg_ospeed; /* output speed */
|
||||
int8_t sg_erase; /* erase character */
|
||||
int8_t sg_kill; /* kill character */
|
||||
int16_t sg_flags; /* mode flags */
|
||||
};
|
||||
|
||||
/*
|
||||
* Values for sg_flags
|
||||
*/
|
||||
#define TR_TANDEM 01
|
||||
#define TR_CBREAK 02
|
||||
#define TR_LCASE 04
|
||||
#define TR_ECHO 010
|
||||
#define TR_CRMOD 020
|
||||
#define TR_RAW 040
|
||||
#define TR_ODDP 0100
|
||||
#define TR_EVENP 0200
|
||||
#define TR_ANYP 0300
|
||||
#define TR_XTABS 06000
|
||||
|
||||
/*
|
||||
* Values for signal
|
||||
*/
|
||||
#define V7_SIG_DFL 0
|
||||
#define V7_SIG_IGN 1
|
||||
|
||||
#define V7_NSIG 15
|
||||
|
||||
#define V7_SIGHUP 1 /* hangup */
|
||||
#define V7_SIGINT 2 /* interrupt */
|
||||
#define V7_SIGQUIT 3 /* quit */
|
||||
#define V7_SIGILL 4 /* illegal instruction (not reset when caught) */
|
||||
#define V7_SIGTRAP 5 /* trace trap (not reset when caught) */
|
||||
#define V7_SIGIOT 6 /* IOT instruction */
|
||||
#define V7_SIGEMT 7 /* EMT instruction */
|
||||
#define V7_SIGFPE 8 /* floating point exception */
|
||||
#define V7_SIGKILL 9 /* kill (cannot be caught or ignored) */
|
||||
#define V7_SIGBUS 10 /* bus error */
|
||||
#define V7_SIGSEGV 11 /* segmentation violation */
|
||||
#define V7_SIGSYS 12 /* bad argument to system call */
|
||||
#define V7_SIGPIPE 13 /* write on a pipe with no one to read it */
|
||||
#define V7_SIGALRM 14 /* alarm clock */
|
||||
#define V7_SIGTERM 15 /* software termination signal from kill */
|
||||
|
||||
|
||||
/* A union which will point at the trap args, so that
|
||||
* we can get at the various args of different types
|
||||
*/
|
||||
typedef union {
|
||||
int16_t sarg[4]; /* Signed 16-bit args */
|
||||
u_int16_t uarg[4]; /* Unsigned 16-bit args */
|
||||
} arglist;
|
||||
|
||||
#define sarg1 V7A.sarg[0]
|
||||
#define sarg2 V7A.sarg[1]
|
||||
#define sarg3 V7A.sarg[2]
|
||||
#define sarg4 V7A.sarg[3]
|
||||
#define uarg1 V7A.uarg[0]
|
||||
#define uarg2 V7A.uarg[1]
|
||||
#define uarg3 V7A.uarg[2]
|
||||
#define uarg4 V7A.uarg[3]
|
||||
Reference in New Issue
Block a user