--- /dev/null
+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.
--- /dev/null
+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.
+ */
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+# 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
--- /dev/null
+ 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
--- /dev/null
+ 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.
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+.\" 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.
--- /dev/null
+/* 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();
+}
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * Much of this file comes from 2.11BSD's /usr/include/signal.h and is
+ * Copyright (c) 1986 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ *
+ * Code to deal with 2.11BSD signals
+ */
+#include "defines.h"
+#include <signal.h>
+#include "bsdtrap.h"
+
+
+#define NBSDSIG 32
+
+#define BSDSIGHUP 1 /* hangup */
+#define BSDSIGINT 2 /* interrupt */
+#define BSDSIGQUIT 3 /* quit */
+#define BSDSIGILL 4 /* illegal instruct (not reset when caught) */
+#define BSDSIGTRAP 5 /* trace trap (not reset when caught) */
+#define BSDSIGIOT 6 /* IOT instruction */
+#define BSDSIGEMT 7 /* EMT instruction */
+#define BSDSIGFPE 8 /* floating point exception */
+#define BSDSIGKILL 9 /* kill (cannot be caught or ignored) */
+#define BSDSIGBUS 10 /* bus error */
+#define BSDSIGSEGV 11 /* segmentation violation */
+#define BSDSIGSYS 12 /* bad argument to system call */
+#define BSDSIGPIPE 13 /* write on a pipe with no one to read it */
+#define BSDSIGALRM 14 /* alarm clock */
+#define BSDSIGTERM 15 /* software termination signal from kill */
+#define BSDSIGURG 16 /* urgent condition on IO channel */
+#define BSDSIGSTOP 17 /* sendable stop signal not from tty */
+#define BSDSIGTSTP 18 /* stop signal from tty */
+#define BSDSIGCONT 19 /* continue a stopped process */
+#define BSDSIGCHLD 20 /* to parent on child stop or exit */
+#define BSDSIGTTIN 21 /* to readers pgrp upon background tty read */
+#define BSDSIGTTOU 22 /* like TTIN for output if (tp->t_local<OSTOP) */
+#define BSDSIGIO 23 /* input/output possible signal */
+#define BSDSIGXCPU 24 /* exceeded CPU time limit */
+#define BSDSIGXFSZ 25 /* exceeded file size limit */
+#define BSDSIGVTALRM 26 /* virtual time alarm */
+#define BSDSIGPROF 27 /* profiling time alarm */
+#define BSDSIGWINCH 28 /* window size changes */
+#define BSDSIGUSR1 30 /* user defined signal 1 */
+#define BSDSIGUSR2 31 /* user defined signal 2 */
+#define bsdsigismember(set, signo) ((*(set) & (1L << ((signo) - 1))) != 0)
+
+#define BSDSIG_ERR -1
+#define BSDSIG_DFL 0
+#define BSDSIG_IGN 1
+
+/*
+ * Signal vector "template" used in sigaction call.
+ */
+struct bsd_sigaction {
+ int16_t sig_handler; /* signal handler */
+ u_int32_t sa_mask; /* signal mask to apply */
+ int16_t sa_flags; /* see signal options below */
+};
+
+#define BSD_ONSTACK 0x0001 /* take signal on signal stack */
+#define BSD_RESTART 0x0002 /* restart system on signal return */
+#define BSD_DISABLE 0x0004 /* disable taking signals on alternate stack */
+#define BSD_NOCLDSTOP 0x0008 /* do not generate SIGCHLD on child stop */
+
+
+/* Translate 2.11BSD signal value to our value */
+
+static int bsdsig[] = {
+ 0, SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGIOT, SIGEMT,
+ SIGFPE, SIGKILL, SIGBUS, SIGSEGV, SIGSYS, SIGPIPE, SIGALRM,
+ SIGTERM, SIGURG, SIGSTOP, SIGTSTP, SIGCONT, SIGCHLD, SIGTTIN,
+ SIGTTOU, SIGIO, SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, SIGWINCH,
+ SIGUSR1, SIGUSR2
+};
+
+/* We keep a set of struct sigactions
+ * for each 2.11BSD signal
+ */
+struct bsd_sigaction Sigact[NBSDSIG];
+
+
+/* Set all signals to their default value */
+void set_bsdsig_dfl(void)
+{
+ int i;
+
+ for (i=0;i<NBSDSIG;i++) {
+ if (bsdsig[i]) signal(bsdsig[i], SIG_DFL);
+ Sigact[i].sig_handler= BSDSIG_DFL;
+ Sigact[i].sa_mask= Sigact[i].sa_flags= 0;
+ }
+}
+
+int do_sigaction(int sig, int a, int oa)
+{
+ int i;
+ struct bsd_sigaction *act, *oact;
+ struct sigaction ouraction;
+
+ if ((sig<0) || (sig >= NBSDSIG)) return(EINVAL);
+
+ if (oa) {
+ oact= (struct bsd_sigaction *)&dspace[oa];
+ memcpy(oact, &Sigact[sig], sizeof(struct bsd_sigaction));
+ }
+
+ if (a) {
+ act= (struct bsd_sigaction *)&dspace[a];
+
+ /* If required, map mask here */
+ /* Currently, the assumption is a 1-1 match */
+ sigemptyset(&(ouraction.sa_mask));
+ for (i=1; i<NBSDSIG;i++) {
+ if bsdsigismember(&(act->sa_mask), i)
+ sigaddset(&(ouraction.sa_mask), i);
+ }
+ /* If required, map flags here */
+ ouraction.sa_flags= act->sa_flags;
+ ouraction.sa_handler= sigcatcher;
+ }
+
+ i= sigaction(bsdsig[sig], &ouraction, NULL);
+ if (i==-1) return(i);
+
+ /* Else save the new sigaction */
+ act= (struct bsd_sigaction *)&dspace[a];
+ memcpy(&Sigact[sig], act, sizeof(struct bsd_sigaction));
+ return(i);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/* For now, the rest commented out. One day I might
+ * get around to implementing 2.11BSD signals properly
+ */
+
+#if 0
+int (*signal())();
+
+typedef unsigned long sigset_t;
+
+
+/*
+ * Flags for sigprocmask:
+ */
+#define BSDSIG_BLOCK 1 /* block specified signal set */
+#define BSDSIG_UNBLOCK 2 /* unblock specified signal set */
+#define BSDSIG_SETMASK 3 /* set specified signal set */
+
+typedef int (*sig_t)(); /* type of signal function */
+
+/*
+ * Structure used in sigaltstack call.
+ */
+struct sigaltstack {
+ char *ss_base; /* signal stack base */
+ int ss_size; /* signal stack length */
+ int ss_flags; /* SA_DISABLE and/or SA_ONSTACK */
+};
+#define MINBSDSIGSTKSZ 128 /* minimum allowable stack */
+#define BSDSIGSTKSZ (MINBSDSIGSTKSZ + 384) /* recommended stack size */
+
+/*
+ * 4.3 compatibility:
+ * Signal vector "template" used in sigvec call.
+ */
+struct sigvec {
+ int (*sv_handler)(); /* signal handler */
+ long sv_mask; /* signal mask to apply */
+ int sv_flags; /* see signal options below */
+};
+#define SV_ONSTACK SA_ONSTACK /* take signal on signal stack */
+#define SV_INTERRUPT SA_RESTART /* same bit, opposite sense */
+#define sv_onstack sv_flags /* isn't compatibility wonderful! */
+
+/*
+ * 4.3 compatibility:
+ * Structure used in sigstack call.
+ */
+struct sigstack {
+ char *ss_sp; /* signal stack pointer */
+ int ss_onstack; /* current status */
+};
+
+/*
+ * Information pushed on stack when a signal is delivered.
+ * This is used by the kernel to restore state following
+ * execution of the signal handler. It is also made available
+ * to the handler to allow it to properly restore state if
+ * a non-standard exit is performed.
+ */
+struct sigcontext {
+ int sc_onstack; /* sigstack state to restore */
+ long sc_mask; /* signal mask to restore */
+ int sc_sp; /* sp to restore */
+ int sc_fp; /* fp to restore */
+ int sc_r1; /* r1 to restore */
+ int sc_r0; /* r0 to restore */
+ int sc_pc; /* pc to restore */
+ int sc_ps; /* psl to restore */
+ int sc_ovno /* overlay to restore */
+};
+
+/*
+ * Macro for converting signal number to a mask suitable for
+ * sigblock().
+ */
+#define sigmask(m) (1L << ((m)-1))
+#define sigaddset(set, signo) (*(set) |= 1L << ((signo) - 1), 0)
+#define sigdelset(set, signo) (*(set) &= ~(1L << ((signo) - 1)), 0)
+#define sigemptyset(set) (*(set) = (sigset_t)0, (int)0)
+#define sigfillset(set) (*(set) = ~(sigset_t)0, (int)0)
+#define sigismember(set, signo) ((*(set) & (1L << ((signo) - 1))) != 0)
+
+#endif /* 0 */
--- /dev/null
+/* 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 */
--- /dev/null
+/* 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]
--- /dev/null
+/* 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; }
+}
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/* 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();
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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
+};
--- /dev/null
+/* 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 */
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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]);
+}
--- /dev/null
+/* 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();
+}
--- /dev/null
+/* 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 */
--- /dev/null
+/* 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]
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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]