1
0
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:
warren.toomey
2008-05-06 23:25:22 +00:00
parent 7c98a7ab7d
commit 896dbd998a
30 changed files with 9254 additions and 0 deletions

173
tools/apout/CHANGES Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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&LTOSTOP) */
#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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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]