diff --git a/tools/apout/CHANGES b/tools/apout/CHANGES new file mode 100644 index 0000000..792efc5 --- /dev/null +++ b/tools/apout/CHANGES @@ -0,0 +1,173 @@ +2.3 Beta1: to 10th June 2002 +---------------------------- + +Changed debug statements in cpu.c to be TrapDebug statements as I was +seeing output from these in the output file of 2.11BSD /lib/cpp. + +The problem with scripts has also been fixed, finally. I was passing +the wrong path into the shell arguments. + +On a 1.6GHz Pentium 4 running FreeBSD 4.5, a make depend; make of the +2.11BSD GENERIC kernel takes 72 seconds. + +2.3 Alpha3: to 1st June 2001 +---------------------------- + +Added patches from Wilhelm B. Kloke wb@vestein.arb-phys.uni-dortmund.de +to get Apout to run the Algol 68 binaries found which were added into +the Unix Archive. + +A few changes for better Linux compilation. However, stream buffering +doesn't seem to work on Linux, at least RedHat 6.2. + +2.3 Alpha2: to 10th Jan 2000 +---------------------------- + +Added partial support for 0407-magic binaries from 2nd Edition. At +present, this is enough for the C compiler on Dennis Ritchie's s2.tar +archive to work. It's also good enough for the C compiler to recompile +the last1120c compiler, and for the last1120c compiler to recompile itself. + +Added code to support 512-byte block seeks on /dev files for 1st Edition +binaries. This was required to get tap(1) to work. This should really +only force 512-byte seeks on specific /dev/files, not all of them. + +A significant rearrangement of the code in aout.c was done to make it +more logical. I wouldn't say it was much tidier than before, though. + +A redefinition of sigset_t in NetBSD stopped Apout from being compiled +there. Thanks to Soren, bsdsignal.c was modified to fix this problem. + +Some small changes to the output from -inst to make it look better. +Added a WRITEBASE #define to help improve performance just a bit more. + +2.3 Alpha1: to 2nd Jan 2000 +--------------------------- + +Added nearly complete support for 0405-magic binaries from 1st Edition, +including emulating the KE11A extended arithmetic element. Still some +work needed here on both the trap handling and KE11A support. Thanks to +Tim Shoppa (shoppa@trailing-edge.com) for his eae code. The 0407-magic +binaries from Dennis Ritchie's s2.tar archive are not yet supported. I +need the V2/V3 manuals from Norman Wilson for this. + +Some tidying up of the code has been done, using LCLINT and by hand. +I've made a Debug() macro which make the code look a bit cleaner. + +Some memory leaks removed. Natives exec()s now inherit the original +environment, not the emulated one. Some mov() functions split into +separate functions to help improve performance. Added a workaround +for date handling in V5/V6 ctime(): see tail of v7trap.c. + +Stream buffering variables consolidated into main.c and some bugs +removed (e.g "rw" -> "w+"). 2.11BSD emulation now has stream buffering, +but it is turned off by default as it doesn't seem to provide any +improvement in performance. + +2.2 Alpha9: to 2nd Mar 1999 +--------------------------- + +I've added magic numbers for some 2.9BSD binaries: all 2.9 binaries +run in the V7 environment, which seems to work but I'm sure that +2.9 != V7. + +With help from Jonathan Naylor (g4klx@g4klx.demon.co.uk), and some work +myself, I've managed to compile Apout under RedHat Linux 2.2. There are +some 2.11BSD syscalls not implemented as a result, but I can recompile +the V7 and the 2.11BSD kernels, which is a good indicator. + + +2.2 Alpha8: to 15th Jan 1999 +---------------------------- + +These changes came about due to my attempt to compile the UNIX `nsys' +kernel source code, dated 1973, with the 5th Edition development tools. + +Added better detection of some special UNIX a.out binaries: the +environment for these binaries was being incorrectly set by aout.c. +There is now a magic.c which fixes the problem. See also LIMITATIONS +for a note of bugs in some a.out binaries. + +Modified v7trap.c to be much cleaner, and to look a bit more like +bsdtrap.c. Introduced several small bugs in V5/V6/V7 syscall emulation, +notably pipe() and dup(), by the cleanup. These are fixed. + + +2.2 Alpha7: to 11th Jan 1999 +---------------------------- + +Modified the code to handle the syscall differences between +V6 and V7: note that V5 and V6 are syscall identical. V6 has +a different seek() and stat() to V7. + +Added a new file for 2.11BSD ioctls, did many of the terminal +ioctls, and a few more syscalls. Now 2.11 vi runs. However, +longjmp() doesn't work yet, because it requires working signals. + +Changed some types and #ifdefs for NetBSD and OpenBSD: thanks Soren! + + +2.2 Alpha6: to 6th Jan 1999 +--------------------------- + +Bugfixes: none that I can think of. + +Enhancements: tidied the code up somewhat. Changed uint -> u_int +throughout. Added support for execution of native binaries: now I can +run vi from inside 2.11 bin/sh, yay! Finally wrote the long-overdue +manual page. Added RCS tags to all sources. Ensured that it compiled on +FreeBSD 3.x and 2.1.x: I need to take it home for FreeBSD 2.2.x. + + +2.2 Alpha5: to 5th Jan 1999 +--------------------------- + +Bugfixes: fixed malloc bug, which was a too-large blksize from stat/fstat. +Fixed the gtty/stty emulation, which was causing make to break. + +Enhancements: Apout can now run shell scripts. 2.11BSD overlay binaries +are now supported, which is good news. I can now compile the 2.11 GENERIC +kernel with no manual intervention. On a Pentium II 350MHz, this takes +4:16secs with an optimised Apout. + + +2.2 Alpha4: to 2nd Jan 1999 +--------------------------- + +Fixed more deficiencies in the 2.11BSD emulation, in particular +fork(), vfork() and sbrk(). The argv/envp environment is better +but still not totally correct, I think. Finally got the correct +code for 2.11 readdir(). + +We now have a semi-working FP emulation. It's enough to keep 2.11 +happy, but it isn't very good. It will do for now. + +Many of the 2.11BSD syscalls are now implemented. Most are not +verified, but a lot of 2.11BSD commands run, including sh, make, +cc, date, cal. ls(1) goes into an infinite loop when doing ls -l, +the inf. loop is in malloc(3). By substituting malloc(3) from +Minix 1.3, this problem goes away. I don't know if it's a bug +in the emulator, or in the 2.11 malloc() code. + + +2.2 Alpha3 to 5th Dec 1998 +-------------------------- + +Reorganised bsdtrap.[ch], and started work on the +2.11BSD emulated syscalls; this is surprisingly +easy for many of them. + + +Changes from 2.1 to 2.2 +----------------------- + + + General code tidying up and niggling bug removal. + + Code optimisation to speed things up, although + I haven't quantified the improvement yet. + + Separation of the binary loader and trap handlers + from the main program. This doesn't do anything now, + but it will make the emulation of several PDP-11 + environments (e.g 2.11BSD, RT-11) much easier to do. + + Finished getting the stream buffering of I/O to work. + I still don't know why fdopen doesn't work on "rw". + + Some extra trap functionality, e.g basic signal handling. diff --git a/tools/apout/COPYRIGHT b/tools/apout/COPYRIGHT new file mode 100644 index 0000000..087357d --- /dev/null +++ b/tools/apout/COPYRIGHT @@ -0,0 +1,46 @@ +The Apout simulator is copyright Warren Toomey, and is protected by the +following notice. + +/* Apout is a PDP-11 a.out simulator. + * + * For information contact: + * + * Email: wkt@tuhs.org + * FTP: ftp://minnie.tuhs.org/pup/PDP-11/Sims/Apout + * + * Copyright 1995-2002, Warren Toomey + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies. Warren Toomey + * makes no representations about the suitability of this software for any + * purpose. It is provided "as is" without expressed or implied warranty. + */ + +------ + +The parts of Apout that deal with PDP-11 instruction emulation are derived +from the PDP-11 simulator written by Eric A. Edwards, and are protected by +the following notice. + +/* Parts of Apout are derived from 'pdp', a PDP-11 simulator. + * + * For information contact: + * + * Computer Science House + * Attn: Eric Edwards + * Box 861 + * 25 Andrews Memorial Drive + * Rochester, NY 14623 + * + * Email: mag@potter.csh.rit.edu + * FTP: ftp.csh.rit.edu:/pub/csh/mag/pdp.tar.Z + * + * Copyright 1994, Eric A. Edwards + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies. Eric A. Edwards + * makes no representations about the suitability of this software for any + * purpose. It is provided "as is" without expressed or implied warranty. + */ diff --git a/tools/apout/LCLINT b/tools/apout/LCLINT new file mode 100644 index 0000000..3bb43a2 --- /dev/null +++ b/tools/apout/LCLINT @@ -0,0 +1,16 @@ +aout.c Fri Sep 17 13:00:33 EST 1999 +branch.c Fri Sep 17 13:00:33 EST 1999 +bsd_ioctl.c Fri Sep 17 13:03:34 EST 1999 +bsd_signal.c +bsdtrap.c +cpu.c Fri Sep 17 15:04:05 EST 1999 bits to do +debug.c Fri Sep 17 15:04:01 EST 1999 +double.c Fri Sep 17 15:08:46 EST 1999 +ea.c Fri Sep 17 15:10:51 EST 1999 +fp.c +itab.c Fri Sep 17 13:00:33 EST 1999 +ke11a.c +magic.c Fri Sep 17 13:00:33 EST 1999 +main.c +single.c +v7trap.c diff --git a/tools/apout/LIMITATIONS b/tools/apout/LIMITATIONS new file mode 100644 index 0000000..aad676c --- /dev/null +++ b/tools/apout/LIMITATIONS @@ -0,0 +1,155 @@ +Bugs in Binaries +---------------- + +One of the V5 C compiler passes requires -DZERO_MEMORY: it must not +initialise a variable properly. V5 and V6 ar(1) do not close a file +descriptor after writing has finished. If Apout is compiled with +stream buffering, when this file is copied it is truncated. Either +turn off Apout stream buffering (a performance penalty), or patch +ar.s to behave itself. The patch is: + +*** ar.s.orig Thu Jan 14 09:40:46 1999 +--- ar.s Thu Jan 14 09:41:12 1999 +*************** +*** 444,449 **** +--- 444,451 ---- + bes crterr + mov r0,afo + sys write; magic; 2 ++ mov tfo,r0 / need to close before reading ++ sys close + 1: + mov tfi,r0 + sys read; buf; 512. + + +Floating-point Limitations +-------------------------- + +PDP-11 doubles are treated as floats. FEA/FEC don't exist. +FP errors are not dealt with. Mistrust FP results for now. + +Limitations for 7th Edition Emulation in Apout 2.3 +-------------------------------------------------- + +Note that V5 and V6 binaries are considered V7 binaries. Overlay +binaries (type 0405) are not recognised. + +The errno values on the native system are not translated back to +the V7 errno values. There is normally a 1-to-1 mapping, but V7 +only had 32 errno values; native errno values above this are going +to confuse the emulated application. + +The following system calls are not implemented, and return an +EPERM error to the application: phys(2), prof(2), ptrace(2), +acct(2), mount(2), umount(2), times(2). The following system +calls are ignored: lock(2), stime(2). + +The following systems calls are only partially implemented: + + signal(2): Only SIG_DFL and SIG_IGN are implemented. + stty(2), gtty(2): These should work, but V7 stty(1) doesn't work. + ioctl(2): Only enough to emulate stty(2) amd gtty(2). + +The emulated applications use the native filesystem. Native filenames bigger +than 14 characters are truncated to 14 characters before being passed to +the application. In a similar way, inode numbers bigger than 65,536 are +truncated modulo 65,536 before being passed to the application. + +Limitations for 5th & 6th Edition Emulation in Apout 2.3 +-------------------------------------------------------- + +There seems to be a bug in V5/V6 ctime() which stops dates after +November 1999 being displayed correctly. Apout works around this +problem by modifying dates returned from system calls to be in +the year 1998 if they are 1999 or later. + +Limitations for 2.9BSD Emulation in Apout 2.3 +--------------------------------------------- + +At present, 2.9BSD binaries are treated as V7 binaries, so the limitations +above apply. This also means that overlays are not understood, and also the +2.9-specific system calls have not yet been implemented. + +Limitations for 2.11BSD Emulation in Apout 2.3 +---------------------------------------------- + +Flags passed as arguments to the 2.11 syscalls are promoted to 32-bit +ints and passed to the native syscall. The errno values on the native +system are not translated back to the 2.11 errno values. To find out +what syscalls have been implemented, grep for the word DONE in bsdtrap.c. + +The following 2.11 syscalls are not handled: + + S_GETSOCKOPT, S_SETSOCKOPT, S_SELECT, + S_RECVMSG, S_SENDMSG, S_SENDTO, + S_SIGBLOCK, S_SIGPAUSE, S_SIGRETURN, + S_SIGSETMASK, S_SIGSTACK, S_SIGVEC + +Limitations for 1st Edition Emulation in Apout 2.3 +-------------------------------------------------- + +This is still in the experimental stages, with some problems with time +values. The KE11A emulation is also incomplete. However, the following +0405-magic binaries from Dennis Ritchie's s2.tar archive are known to work: + + cat, cp, date, echo, ls, mkdir, sh, wc + +Most of the others seem to work as well, but I haven't tested them completely. +The list of 0405-magic files on the s2 archive is: + + bin/: bin/mv + bin/ar bin/od + bin/bas bin/pr + bin/cat bin/rew + bin/chball bin/rmdir + bin/check bin/roff + bin/chown bin/sh + bin/cmp bin/skip + bin/cp bin/sort + bin/date bin/stat + bin/db bin/stty + bin/dc bin/su + bin/df bin/sum + bin/du bin/tap + bin/echo bin/tm + bin/ed bin/tty + bin/exit bin/wc + bin/form bin/who + bin/goto bin/write + bin/if etc/getty + bin/login etc/glob + bin/ls etc/init + bin/mail etc/msh + bin/mesg /tc/suftab + bin/mkdir + +The following 1st Edition system calls are not yet emulated: GTTY, STTY, TELL. + +Limitations for 2nd Edition Emulation in Apout 2.3 +-------------------------------------------------- + +The few 2nd Edition binaries with 0407-magic on the s2 archive can now +be run with Apout. Essentially, they receive the same environment as +the 1st Edition binaries, with a few small syscall differences. Note +that, at present, I don't have a copy of the V2 manuals, so I can +guarantee that 2nd Edition emulation still needs work. + +However, the emulation is good enough to allow the C compiler on the s2 +archive to compile the last1120c C compiler on Dennis Ritchie's homepage. + +The list of 0407-magic files in the s2 archive is below. I have starred +those binaries that I know work with Apout. + + * bin/as usr/fort/fc1 + * bin/cc usr/fort/fc2 + bin/ds usr/fort/fc3 + bin/fc usr/fort/fc4 + bin/find usr/jack/a.out + * bin/ld usr/jack/x.o + bin/maki * usr/lib/c0 + bin/nm * usr/lib/c1 + * bin/size usr/lib/crt0.o + bin/strip usr/lib/fr0.o + bin/un usr/sys/a.out + * etc/as2 diff --git a/tools/apout/Makefile b/tools/apout/Makefile new file mode 100644 index 0000000..fc1d7a6 --- /dev/null +++ b/tools/apout/Makefile @@ -0,0 +1,78 @@ +# Makefile for Apout PDP-11 application emulator +# +# $Revision: 1.29 $ +# $Date: 2002/06/10 11:49:48 $ +# +# You will need gcc if you choose the optimised compile below +CC=gcc + +# Set the CFLAGS, LDFLAGS for speed or debugging. If you don't want 2.11BSD +# emulation, then remove the -DEMU211 flag. +# Set up the LIBS if required for your system +# +# These flags for doing debugging +CFLAGS= -Wall -g -DEMU211 -DEMUV1 -DNATIVES -DDEBUG -DZERO_MEMORY -DWRITEBASE +LDFLAGS= -static -g + +# These flags for speed +#CFLAGS= -DEMU211 -DNATIVES -DINLINE=inline -O2 -Winline -Wall \ +# -finline-functions -fomit-frame-pointer +#LDFLAGS= + +# Any extra libraries required +LIBS= -lm + +# Install destinations +MANDIR=/usr/local/man/man1 +BINDIR=/usr/local/bin + +VERSION= apout2.3beta1 +SRCS= cpu.c aout.c aout.h branch.c double.c ea.c itab.c main.c ke11a.c \ + single.c fp.c v7trap.c bsdtrap.c defines.h v7trap.h debug.c \ + bsdtrap.h bsd_ioctl.c bsd_signal.c magic.c v1trap.c v1trap.h \ + apout.1 apout.0 README COPYRIGHT CHANGES LIMITATIONS TODO Makefile +OBJS= aout.o branch.o bsd_ioctl.o bsd_signal.o bsdtrap.o cpu.o debug.o \ + double.o ea.o fp.o itab.o ke11a.o magic.o main.o single.o v1trap.o \ + v7trap.o + +apout: $(OBJS) + cc $(LDFLAGS) $(OBJS) -o apout $(LIBS) + +install: apout + cp apout $(BINDIR) + chmod 755 $(BINDIR)/apout + cp apout.1 $(MANDIR) + chmod 644 $(MANDIR)/apout.1 + +clean: + rm -rf apout *core $(OBJS) *.dbg $(VERSION) $(VERSION).tar.gz apout.0 + +apout.0: apout.1 + nroff -man apout.1 > apout.0 + +disttar: clean apout.0 + - mkdir $(VERSION) + cp $(SRCS) $(VERSION) + chmod -R go+rX $(VERSION) + chmod -R u+w $(VERSION) + chown -R wkt $(VERSION) + tar vzcf $(VERSION).tar.gz $(VERSION) + +# Dependencies for object files +aout.o: aout.c defines.h aout.h Makefile +branch.o: branch.c defines.h Makefile +bsd_ioctl.o: bsd_ioctl.c defines.h Makefile +bsd_signal.o: bsd_signal.c defines.h bsdtrap.h Makefile +bsdtrap.o: bsdtrap.c bsdtrap.h defines.h Makefile +cpu.o: cpu.c defines.h Makefile +debug.o: debug.c defines.h Makefile +double.o: double.c defines.h Makefile +ea.o: ea.c defines.h Makefile +fp.o: fp.c defines.h Makefile +itab.o: itab.c defines.h Makefile +ke11a.o: ke11a.c defines.h Makefile +magic.o: magic.c defines.h Makefile +main.o: main.c defines.h Makefile +single.o: single.c defines.h Makefile +v1trap.o: v1trap.c v1trap.h defines.h Makefile +v7trap.o: v7trap.c v7trap.h defines.h Makefile diff --git a/tools/apout/README b/tools/apout/README new file mode 100644 index 0000000..7880b15 --- /dev/null +++ b/tools/apout/README @@ -0,0 +1,140 @@ + Apout -- Simulate PDP-11 Unix a.out binaries + Version 2.3 Beta 1 + + Warren Toomey wkt@tuhs.org + June 2002 + +Introduction +------------ +This program is a user-level simulator for UNIX a.out binaries. Binaries +for V1, V2, V5, V6, V7, 2.9BSD and 2.11BSD can be run with this simulator. +The user-mode PDP-11 instructions are simulated, and TRAP instructions +are emulated by calling equivalent native-mode system calls. + +The advantages of an a.out simulator over a full-blown PDP-11 simulator are: + + + system calls can be done natively, thus speeding up execution + + the simulator is less of a CPU-hog than a full-blown PDP-11 simulator + + you don't need a simulated operating system or a simulated file system + +Apout can be obtained via anonymous ftp at minnie.tuhs.org in the +directory pub/PDP-11/Sims/Apout. The directory pub/PDP-11/Sims/Apout/UnixBins +contains tar archives of a.out binaries from several versions of UNIX. + +Status +------ +The program is now at release 2.3 Alpha2. Most of the binaries from V5, V6 +and V7 run fine. All of the V5/V6/V7 system calls are caught, but some are +ignored and some generate EPERM errors. The V1, V2, 2.9BSD and 2.11BSD +environments are still under construction: see the file LIMITATIONS for +details. Finally, the simulator won't run on a big-endian machine. + +INSTALLATION +------------ +I have only tested this program on FreeBSD 2.x and 3.x, and on RedHat +Linux 2.2. It should compile on a 32-bit little-endian machine with +some form of Unix; you may need to change some header file includes etc. +See `defines.h' for the details. In particular, if your system doesn't have +types for: + + int8_t, int16_t, int32_t, u_int8_t, u_int16_t, u_int32_t + +or if your compiler doesn't have char=1 byte, short= 2 bytes, int=4 bytes, +then alter the relevant typedefs in `defines.h'. + +The Makefile has two sets of CFLAGS/LDFLAGS: one set is for debugging, and +the other set is for speed. If you define the C pre-processor macro `DEBUG', +then this includes debugging code into the program. I use it quite heavily +when trying to fix niggling problems. + +If you remove the -DEMU211 macro definition from the Makefile, the emulation +of 2.11BSD will not be compiled in to the simulator. Similarly, if you remove +the -DEMUV1 macro definition from the Makefile, the emulation of 1st and 2nd +Edition UNIX will not be compiled in to the simulator. By default, EMUV1 +is disabled. + + +Once you have configured apout, now type `make'. Hopefully, things will +compile ok. You will eventually get the `apout' program. + +Now go find an old PDP-11 UNIX binary, e.g 7th Edition cal, and say: + + % setenv APOUT_ROOT / # for now + % apout cal 1970 + +If the simulator is working, the calendar for 1970 will be printed out. +The V7 shell works, and from there, you can run other programs. + + % apout sh + # ls -l + output of ls + # + +Finally, install apout in /usr/local/bin, and the manual page apout.1 in +the appropriate place. If you can't use the man page because of incompatible +macros, then apout.0 is a text file which has the pre-formatted man page. + +DEBUG OPTIONS +------------- +When debugging is compiled in, the program has several options: + + -inst turns on instruction tracing, which is _very_ verbose + -trap turns on TRAP tracing; not all syscalls have debugging code + -jsr prints out the details of each jsr and rts + -fp prints out some details of floating-point instructions + +All debugging output goes out to the file `apout.dbg'. These debugging options +are mainly used for testing apout, and so the output in apout.dbg may not be +very useful to you. + +ENVIRONMENT VARIABLES +--------------------- +Apout has the concept of a simulated root filesystem for the simulated PDP-11 +binaries. When working with filenames, if the filenames are relative, they +stay relative. If the filenames are absolute (i.e /usr/...), then apout +prepends the value of the environment variable APOUT_ROOT to the filename. +This allows you to say: + + # setenv APOUT_ROOT /usr/misc/v7root + +before running apout to set the `root' of the filesystem wherever you want. +You MUST set APOUT_ROOT before running apout. + +TODO +---- +There's lots to do. Here's what I'd like to do, in a somewhat ordered list. + + + Verify that the instruction simulation and high priority + the syscalls all work correctly + + Complete some of the syscalls that are med priority + not fully simulated + + Speed the simulator up med priority + +SOURCE ORGANISATION +------------------- + +main.c parses any arguments, loads the binary and calls run() +cpu.c holds the main instruction decode/execute loop +itab.c holds function lookup tables for all instructions +ea.c holds functions to decode the PDP-11 addressing modes +debug.c holds strings for all emulated opcodes + +single.c single.c, double.c and branch.c hold most of the functions +double.c which perform the PDP-11 user-mode instructions. The code +branch.c in these files comes from a PDP-11 simulator by Eric Edwards +fp.c partially emulates FP instructions + +aout.c determines what type of a.out the binary is, and what UNIX +magic.c environment to set up. If V5/V6/V7, trap instructions fall +v7trap.c into v7trap.c which runs them using native system calls +v7trap.h + +v1trap.c if the binary is a 1st or 2nd Edition binary, traps fall +v1trap.h into v1trap.c, which likewise does the syscalls natively +ke11a.c emulates the KE11A extended arithmetic unit, used by V1/V2 + +bsdtrap.c if the binary is a 2.11BSD binary, trap instructions fall +bsdtrap.h into bsdtrap.c, which likewise does the syscalls natively +bsd_ioctl.c 2.11BSD ioctl calls are handled with this file + +defines.h holds function & typedef prototypes and useful cpp macros diff --git a/tools/apout/TODO b/tools/apout/TODO new file mode 100644 index 0000000..6f0b650 --- /dev/null +++ b/tools/apout/TODO @@ -0,0 +1,72 @@ + Things to do in the Apout Emulator + ---------------------------------- + +Ensure stream buffering works! + + Do some decent testing and code reading to make me happier. + +Speed Apout up + + The biggest bottlenecks are the effective address calculations + in ea.c. After compiling 2.11BSD /sys/GENERIC kernel with a + gprof'd apout, we get: + + % cumulative self self total + time seconds seconds calls ms/call ms/call name + 64.9 3.64 3.64 .mcount (123) + 6.1 3.99 0.34 1609635 0.00 0.00 load_src [5] + 5.6 4.30 0.31 1665976 0.00 0.00 mov [4] + 5.3 4.60 0.30 2 148.44 959.47 run [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. diff --git a/tools/apout/aout.c b/tools/apout/aout.c new file mode 100644 index 0000000..d2d3dd0 --- /dev/null +++ b/tools/apout/aout.c @@ -0,0 +1,609 @@ +/* aout.c - parse and load the contents of a UNIX a.out file, for + * several flavours of PDP-11 UNIX + * + * $Revision: 1.50 $ + * $Date: 2002/06/10 11:43:24 $ + */ +#include "defines.h" +#include "aout.h" + +/* Array of 64K for data and instruction space */ +static u_int8_t darray[PDP_MEM_SIZE], iarray[PDP_MEM_SIZE]; + +#ifdef EMU211 +/* 2.11BSD allows up to 16 8K overlays in the 0430 and 0431 a.out types. + * Each overlay is loaded at the first 8K `click' above the end of the + * main text. The following structures hold the overlays from the current + * a.out, if there are any. Missing overlays have size 0 and pointer NULL. + */ +static struct { + u_int16_t size; + u_int8_t *ovlay; +} ovlist[NOVL] = { + {0, NULL}, {0, NULL}, {0, NULL}, {0, NULL}, {0, NULL}, {0, NULL}, + {0, NULL}, {0, NULL}, {0, NULL}, {0, NULL}, {0, NULL}, {0, NULL}, + {0, NULL}, {0, NULL}, {0, NULL} +}; + +static u_int8_t *ovbase; /* Base address of 2.11BSD overlays */ +u_int32_t ov_changes = 0; /* Number of overlay changes */ +u_int8_t current_ov = 0; /* Current overlay number */ +#endif + +/* Global array of pointers to arguments and environment. This + * allows load_a_out() to modify it when dealing with shell + * scripts, before calling set_arg_env() + */ +char *Argv[MAX_ARGS], *Envp[MAX_ARGS]; +int Argc, Envc; +int Binary; /* Type of binary this a.out is */ + +/* For programs without an environment, we set the environment statically. + * Eventually there will be code to get some environment variables + */ +static char *default_envp[4] = { + "PATH=/bin:/usr/bin:/usr/sbin:/usr/ucb:/usr/games:/usr/local/bin:.", + "HOME=/", + "TERM=vt100", + "USER=root" +}; +static int default_envc = 4; + +/* Prototypes */ +static void set_arg_env(int want_env); + + +/* Load the a.out header from the given file pointer, and return it. + * Also return an integer describing which version of UNIX the a.out + * belongs to. If errors on reading, return -1. + */ +int load_aout_header(FILE * zin, struct exec * E) +{ + char *cptr; + + /* Read the a_magic value first */ + /* This makes it easier to deal with */ + /* parsing any script interpreter below */ + if (fread(E, sizeof(u_int16_t), 1, zin) != 1) return (-1); + + switch (E->a_magic) { + case ANY_SCRIPT: /* Shell script, return now */ + return (IS_UNKNOWN); + case V1_NORMAL: + case ANY_NORMAL: /* These are recognised below */ + case ANY_ROTEXT: + case ANY_SPLITID: + case BSD_OVERLAY: + case BSD_ROVERLAY: + case A68_MAGIC: + break; + + default: /* Unrecognised binary, mark as such */ + E->a_magic = UNKNOWN_AOUT; return (IS_UNKNOWN); + } + + /* We can deal with this a.out, so */ + /* read in the rest of the header */ + cptr = (char *) &(E->a_text); + if (fread(cptr, sizeof(struct exec) - sizeof(u_int16_t), 1, zin) != 1) + return (-1); + + switch (E->a_magic) { + case A68_MAGIC: if (E->a_data==A68_DATA) return(IS_A68); + else { E->a_magic = UNKNOWN_AOUT; return (IS_UNKNOWN); } + case V1_NORMAL: return (IS_V1); + case BSD_OVERLAY: + case BSD_ROVERLAY: return (IS_211BSD); + case ANY_NORMAL: + case ANY_ROTEXT: + case ANY_SPLITID: /* Check crt0.o 2nd magic for V2/V6/V7/2.11BSD */ + if (E->a_magic2 == V2_M2) return (IS_V2); + if (E->a_magic2 == V6_M2) return (IS_V6); + if (E->a_magic2 == V7_M2) return (IS_V7); + if (E->a_magic2 == BSD_M2) return (IS_211BSD); + + /* Still no idea, use checksum to determine */ + return(special_magic((u_int16_t *) E)); + + default: /* Should never get here */ + E->a_magic = UNKNOWN_AOUT; return (IS_UNKNOWN); + } +} + + +/* Read in the executable name and its arguments from the shell script, + * and the re-call load_a_out to load in that binary. Returns 0 on + * success, -1 on error. Input file is always closed by this routine. + */ +int load_script(const char *file, const char *origpath,FILE * zin, int want_env) +{ +#define SCRIPT_LINESIZE 512 /* Max size of 1st line in script */ + char *script_line; + char *script_arg[MAX_ARGS]; + int i, script_cnt = 0; + char **ap; + + for (i=0;i= 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 | 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 diff --git a/tools/apout/aout.h b/tools/apout/aout.h new file mode 100644 index 0000000..e211353 --- /dev/null +++ b/tools/apout/aout.h @@ -0,0 +1,54 @@ +/* aout.h - parse and load the contents of a UNIX a.out file, for + * several flavours of PDP-11 UNIX + * + * $Revision: 1.4 $ + * $Date: 2000/08/11 07:07:35 $ + */ +#include +#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 diff --git a/tools/apout/apout.1 b/tools/apout/apout.1 new file mode 100644 index 0000000..902365b --- /dev/null +++ b/tools/apout/apout.1 @@ -0,0 +1,234 @@ +.\" Copyright Warren Toomey +.\" +.\" $Revision: 1.9 $ +.\" $Date: 2002/06/10 12:08:27 $ +.\" +.Dd December, 2000 +.Dt APOUT 1 +.Os +.Sh NAME +.Nm apout +.Nd run PDP-11 UNIX a.out binaries +.Sh SYNOPSIS +.Nm apout +.Op Fl inst +.Op Fl trap +.Op Fl jsr +.Op Fl fp +.Ar file +.Op Ar arguments ... +.Sh DESCRIPTION +.Nm apout +runs the +.Ar file +which contains a PDP-11 UNIX a.out binary from one of the following +versions of UNIX: 1st Edition, 2nd Edition, 5th Edition, 6th Edition, +7th Edition, 2.9BSD or 2.11BSD. Any arguments after the named +.Ar file +are passed as arguments to the a.out binary. +.Pp +User-mode PDP-11 instructions are interpreted and executed by +.Nm apout, +and system calls made by the interpreted a.out binary are performed +by making real systems calls to the underlying native operating system. +In this way, the interpreted a.out binary can interact with the real +files and processes on the system. +.Pp +If +.Nm apout +has been compiled with debugging enabled, the following options are available: +.Bl -tag -width trap +.It Fl inst +Output a line for each instruction emulated which gives: +the PC in octal, the instruction in octal, the instruction's name, +r0 to r6 in octal, and the values of the N, Z, V and C flags. +.It Fl trap +Output a line for each system call, which gives the name of the system +call, possibly a list of arguments, and the value returned by the system +call. +.It Fl jsr +Output a line for each +.Ar jsr +or +.Ar rts +giving the value of the new PC. For 2.11BSD overlay binaries, also output +a line describing each overlay change. +.It Fl fp +For many of the emulated floating-point instructions, output a line +describing the operation. +.El +.Pp +If +.Nm apout +was not compiled with debugging enabled, none of these options exist. +Any debugging output is directed to the file +.Ar apout.dbg +in the directory where +.Nm apout +was started. The debugging output is primarily designed to aid the +developers of +.Nm apout, +and so it isn't exhaustive for all instructions, traps or floating-point +operations. +.Sh ENVIRONMENT VARIABLES +.Nm apout +requires one environment variable to be set: +.Ev APOUT_ROOT. +This variable names the `root' of the emulated filesystem. +.Pp +When +.Nm apout +works with filenames, if the filenames are relative, then they +stay relative i.e all files on the system can be named, as long as they are +given relative names. However, if the filenames are absolute, i.e they +start with a slash, then +.Nm apout +prepends the value of the environment variable +.Ev APOUT_ROOT +to the filename. Therefore, if you have the 7th Edition files located in +.Ar /usr/misc/v7root +and you do: +.Bd -literal + % setenv APOUT_ROOT /usr/misc/v7root + % apout $APOUT_ROOT/bin/sh + $ +.Ed +.Pp +then you will be greeted with the 7th Edition Bourne shell prompt as shown: +you will still be in the directory where you started +.Nm apout, +but if you cd to /, then you will be taken to +.Ar /usr/misc/v7root +.Pp +Note that you must set +.Ev APOUT_ROOT +before you can run +.Nm apout. +.Sh EMULATED ENVIRONMENT VARIABLES +Initially, PDP-11 binaries run via +.Nm apout +receive the following set of emulated environment variables: +.Bd -literal + PATH /bin:/usr/bin:/usr/sbin:/usr/ucb:/usr/games:/usr/local/bin:. + HOME / + TERM vt100 +.Ed +.Pp +Emulated programs can, of course, change this emulated environment; +they can also fork and exec other PDP-11 binaries, which will inherit the +modified emulated environment. +.Sh INTERACTION WITH NATIVE PROGRAMS +Binaries that are interpreted by +.Nm apout +can interact with native programs in several ways: through files in the +filesystem, and through pipes. For example, you can do the following: +.Bd -literal + % ls -lR | apout $APOUT_ROOT/bin/wc | lpr + % apout $APOUT_ROOT/bin/sort < file | uniq > newfile +.Ed +.Pp +where +.Ar ls, +.Ar lpr +and +.Ar uniq +are native programs. +.Pp +If +.Nm apout +is compiled with the NATIVES preprocessor directive enabled, then native system +binaries can be executed as well as PDP-11 binaries. For example: +.Bd -literal + % cd $APOUT_ROOT + % ln -s `which vi` bin/vi Add vi into the filespace + % apout bin/sh + $ ls -l Run the PDP-11 ls + .... + $ vi kim.c Run the native vi + $ cc -o kim kim.c Compile with the PDP-11 compiler +.Ed +.Pp +Note that native executable receive the same environment variables inherited +by the +.Nm apout +process, and not the emulated environment that +.Nm apout +passes to emulated executables. +.Sh ERROR MESSAGES +So as to distinguish from error messages generated by the interpreted PDP-11 +binaries, +.Nm apout +prepends the word `Apout' to the beginning of its error messages. Below is +the list of error messages that +.Nm apout +can generate: +.Bd -ragged + Apout - V1 sectosixty too big + Apout - can't malloc overlay! + Apout - can't switch to empty overlay %d + Apout - could not read 1st line of script + Apout - couldn't load %s + Apout - open_dir couldn't open %s + Apout - out of argv space in script + Apout - pid %d bad FP register used at PC 0%o + Apout - pid %d bpt instruction at PC 0%o + Apout - pid %d bus error at PC 0%06o + Apout - pid %d emt instruction at PC 0%o + Apout - pid %d halt instruction at PC 0%o + Apout - pid %d illegal instruction %o at PC 0%o + Apout - pid %d iot instruction at PC 0%o + Apout - pid %d mark instruction at PC 0%o + Apout - pid %d mfpd instruction at PC 0%o + Apout - pid %d mtpd instruction at PC 0%o + Apout - pid %d segmentation fault at PC 0%06o + Apout - pid %d trap instruction at PC 0%o + Apout - pid %d unimplemented instruction at PC 0%o + Apout - pid %d unknown KE11 register 0%o + Apout - pid %d waiti instruction at PC 0%o + Apout - the %s syscall is not yet implemented + Apout - the 2.11BSD %s syscall is not yet implemented + Apout - unknown a.out format 0%o + Apout - unknown magic in header: 0x%x + Apout - unknown syscall %d at PC 0%o + Apout cannot set the environment for the a.out %s + Apout not compiled to support 1st Edition binaries + Apout not compiled to support 2nd Edition binaries + Apout not compiled to support 2.11BSD binaries +.Ed +.Sh CAVEATS +As far as is known, the emulation of user-mode integer instructions is correct. +The emulation of floating-point instructions is seriously deficient: +only 32-bit floats are emulated: the extra 32-bits of precision in PDP-11 +doubles goes unused. None of the FP errors are emulated. +.Pp +The emulation of each of the emulated UNIX environments is mostly, +but not fully, complete. Any UNIX system call environment is very +sophisticated, and +.Ar apout +must translate from the emulated UNIX environment to the native one, and +back. For an authorative description of what is missing from, or deficient +in, each of the emulated UNIX environments, see the source files +.Ar v1trap.c, +.Ar v7trap.c +and +.Ar bsdtrap.c +in the source directory for +.Nm apout. +You should also consult the file +.Ar LIMITATIONS +in the source directory for +.Nm apout. +.Sh SEE ALSO +The latest source for +.Nm apout +can be obtained via anonymous ftp at minnie.tuhs.org in the directory +pub/PDP-11/Sims/Apout. The directory pub/PDP-11/Sims/Apout/UnixBins +contains tar archives of a.out binaries from several versions of UNIX. +Information on PDP-11 UNIX can be found on the PUPS web page at +http://minnie.tuhs.org/PUPS/ +.Sh HISTORY +The first version of +.Nm apout +appeared in 1995, and provided support for 6th and 7th Edition +UNIX binaries. In 1998/1999, support was added for 2.11BSD binaries. +In 1999/2000, support was added for 1st and 2nd Edition UNIX binaries. diff --git a/tools/apout/branch.c b/tools/apout/branch.c new file mode 100644 index 0000000..94ab008 --- /dev/null +++ b/tools/apout/branch.c @@ -0,0 +1,387 @@ +/* branch.c - Branch instructions, and instructions which are complex to do + * + * $Revision: 2.22 $ + * $Date: 1999/12/27 04:38:29 $ + */ +#include "defines.h" + +/* We use the following macro for the branch instructions below */ + +#define do_branch() \ + { offset = LOW8(ir); \ + if (offset & SIGN_B) \ + offset += 0177400; \ + regs[PC] += (offset * 2); \ + } \ + +static u_int16_t offset; + +void bne() { + if (CC_Z==0) do_branch(); +} +void beq() { + if (CC_Z==1) do_branch(); +} +void bpl() { + if (CC_N==0) do_branch(); +} +void bmi() { + if (CC_N==1) do_branch(); +} +void bhi() { + if ((CC_Z==0) && (CC_C==0)) do_branch(); +} +void bvc() { + if (CC_V==0) do_branch(); +} +void bvs() { + if (CC_V==1) do_branch(); +} +void bcc() { + if (CC_C==0) do_branch(); +} +void bcs() { + if (CC_C==1) do_branch(); +} + +/* br() - Branch Always. */ +void br() { + do_branch(); +} + + +/* blos() - Branch Lower or Same Instruction. */ +void blos() { + if ((CC_C!=0) || (CC_Z!=0)) do_branch(); +} + +/* bge() - Branch Greater Than or Equal Instruction. */ +void bge() { + if ((CC_N ^ CC_V) == 0) do_branch(); +} + +/* blt() - Branch Less Than Instruction. */ +void blt() { + if ((CC_N ^ CC_V) == 1) do_branch(); +} + +/* ble() - Branch Less Than Or Equal Instruction. */ +void ble() { + if (((CC_N ^ CC_V) == 1) || ((CC_Z)!=0)) do_branch(); +} + +/* bgt() - Branch Greater Than Instruction. */ +void bgt() { + if (((CC_N ^ CC_V) == 0) && ((CC_Z) == 0)) do_branch(); +} + +/* jmp() - Jump Instruction. */ +void jmp() { + load_ea(); regs[PC]=dstword; +} + +/* jsr() - Jump To Subroutine Instruction. */ +void jsr() { + load_ea(); + srcword=regs[SRC_REG]; push(); + regs[SRC_REG] = regs[PC]; + regs[PC] = dstword; + JsrDebug((dbg_file, "jsr to 0%o\n", dstword)); +} + +/* rts() - Return From Subroutine Instruction. */ +void rts() { + regs[PC] = regs[DST_REG]; + pop(); regs[DST_REG] = dstword; + JsrDebug((dbg_file, "rts to 0%o\n", regs[PC])); +} + +void scc() { + if (ir & CC_NBIT) CC_N=1; + if (ir & CC_ZBIT) CC_Z=1; + if (ir & CC_VBIT) CC_V=1; + if (ir & CC_CBIT) CC_C=1; +} +void ccc() { + if (ir & CC_NBIT) CC_N=0; + if (ir & CC_ZBIT) CC_Z=0; + if (ir & CC_VBIT) CC_V=0; + if (ir & CC_CBIT) CC_C=0; +} + +/* sob() - Subtract One and Branch Instruction. */ +void sob() { + regs[SRC_REG] -= 1; + if (regs[SRC_REG]) { + regs[PC] -= (ir & 077) * 2; + } +} + +/* mfps() - Move from Processor Status Instruction. */ +void mfps() { + srcbyte=(u_int8_t)0; + if (CC_N) srcbyte|= CC_NBIT; + if (CC_Z) srcbyte|= CC_ZBIT; + if (CC_V) srcbyte|= CC_VBIT; + if (CC_C) srcbyte|= CC_CBIT; + + CHGB_CC_N(srcbyte); + CHGB_CC_Z(srcbyte); + CLR_CC_V(); + + if (DST_MODE) { + storeb_dst(); + } else { + if (srcbyte & SIGN_B) { + dstword = 0177400; + } else { + dstword = 0; + } + dstword += (u_int16_t)srcbyte; + store_dst(); + } +} + +/* mtps() - Move to Processor Status Instruction. */ +void mtps() { + loadb_dst(); + if (dstbyte & CC_NBIT) CC_N=1; + if (dstbyte & CC_ZBIT) CC_Z=1; + if (dstbyte & CC_VBIT) CC_V=1; + if (dstbyte & CC_CBIT) CC_C=1; +} + +/* mfpi() - Move From Previous Instruction Space Instruction. */ +void mfpi() { + loadp_dst(); push(); +} + + +/* mtpi() - To From Previous Instruction Space Instruction. */ +void mtpi() { + pop(); storep_dst(); +} + +/* ash() - Arithmetic Shift Instruction. */ +void ash() { + u_int16_t temp; + u_int16_t old; + u_int16_t sign; + u_int16_t count; + + temp = regs[SRC_REG]; + load_dst(); + old = temp; + + if ((dstword & 077) == 0) { /* no shift */ + CHG_CC_N(temp); + CHG_CC_Z(temp); + CLR_CC_V(); + return; + } + if (dstword & 040) { /* right shift */ + count = 0100 - (dstword & 077); + sign = temp & SIGN; + while (count--) { + if (temp & LSBIT) { + SET_CC_C(); + } else { + CLR_CC_C(); + } + temp >>= 1; + temp += sign; + } + } else { /* left shift */ + count = dstword & 037; + while (count--) { + if (temp & SIGN) { + SET_CC_C(); + } else { + CLR_CC_C(); + } + temp <<= 1; + } + } + + CHG_CC_N(temp); + CHG_CC_Z(temp); + + if ((old & SIGN) == (temp & SIGN)) { + CLR_CC_V(); + } else { + SET_CC_V(); + } + regs[SRC_REG] = temp; +} + + +/* mul() and divide() - Multiply and Divide Instructions. These work on + * signed values, and we'll do the same. This may not be portable. */ + +union s_u_word { + u_int16_t u_word; + short s_word; +}; + +union s_u_long { + u_int32_t u_long; + long s_long; +}; + +void mul() { + union s_u_word data1; + union s_u_word data2; + union s_u_long tmp; + + data1.u_word = regs[SRC_REG]; + load_dst(); + data2.u_word=dstword; + + tmp.s_long = ((long) data1.s_word) * ((long) data2.s_word); + + regs[SRC_REG] = (u_int16_t)(tmp.u_long >> 16); + regs[(SRC_REG) | 1] = (u_int16_t)(tmp.u_long & 0177777); + + CLR_CC_ALL(); + + if (tmp.u_long == 0) + SET_CC_Z(); + else + CLR_CC_Z(); + + if (tmp.u_long & 0x80000000) + SET_CC_N(); + else + CLR_CC_N(); +} + +void divide() { + union s_u_long tmp; + union s_u_long eql; + union s_u_word data2; + + tmp.u_long = regs[SRC_REG]; + tmp.u_long = tmp.u_long << 16; + tmp.u_long += regs[(SRC_REG) | 1]; + + load_dst(); + data2.u_word=dstword; + + if (data2.u_word == 0) { + SET_CC_C(); + SET_CC_V(); + return; + } else { + CLR_CC_C(); + } + + eql.s_long = tmp.s_long / data2.s_word; + regs[SRC_REG] = (u_int16_t)eql.u_long & 0177777; + + if (eql.u_long == 0) + SET_CC_Z(); + else + CLR_CC_Z(); + + if ((eql.s_long > 077777) || (eql.s_long < -0100000)) + SET_CC_V(); + else + CLR_CC_V(); + + if (eql.s_long < 0) + SET_CC_N(); + else + CLR_CC_N(); + + eql.s_long = tmp.s_long % data2.s_word; + regs[(SRC_REG) | 1] = (u_int16_t)eql.u_long & 0177777; +} + +/* ashc() - Arithmetic Shift Combined Instruction. */ +void ashc() { + u_int32_t temp; + u_int32_t old; + u_int32_t sign; + u_int16_t count; + + temp = regs[SRC_REG]; + temp <<= 16; + temp += regs[(SRC_REG) | 1]; + old = temp; + load_dst(); + + if ((dstword & 077) == 0) { /* no shift */ + + CLR_CC_V(); + + if (temp & 0x80000000) { + SET_CC_N(); + } else { + CLR_CC_N(); + } + + if (temp) { + CLR_CC_Z(); + } else { + SET_CC_Z(); + } + return; + } + if (dstword & 040) { /* right shift */ + count = 0100 - (dstword & 077); + sign = temp & 0x80000000; + while (count--) { + if (temp & LSBIT) { + SET_CC_C(); + } else { + CLR_CC_C(); + } + temp >>= 1; + temp += sign; + } + } else { /* left shift */ + count = dstword & 037; + while (count--) { + if (temp & 0x80000000) { + SET_CC_C(); + } else { + CLR_CC_C(); + } + temp <<= 1; + } + } + + if (temp & 0x80000000) + SET_CC_N(); + else + CLR_CC_N(); + + if (temp) + CLR_CC_Z(); + else + SET_CC_Z(); + + if ((old & 0x80000000) == (temp & 0x80000000)) { + CLR_CC_V(); + } else { + SET_CC_V(); + } + + regs[SRC_REG] = (u_int16_t)(temp >> 16); + regs[(SRC_REG) | 1] = LOW16(temp); +} + +/* xor() - Exclusive Or Instruction */ +void xor() { + tmpword = regs[SRC_REG]; + + load_dst(); + + tmpword = tmpword ^ dstword; + + CHG_CC_N(tmpword); + CHG_CC_Z(tmpword); + CLR_CC_V(); + + dstword=tmpword; store_dst_2(); +} diff --git a/tools/apout/bsd_ioctl.c b/tools/apout/bsd_ioctl.c new file mode 100644 index 0000000..3fd1e0f --- /dev/null +++ b/tools/apout/bsd_ioctl.c @@ -0,0 +1,479 @@ +/* + * bsd_ioctl.c - Deal with 2.11BSD ioctl system calls. + * + * $Revision: 1.13 $ $Date: 1999/12/27 04:38:29 $ + */ +#ifdef EMU211 +#include "defines.h" +#include +#include +#include "bsdtrap.h" +#ifdef __linux__ +#include /* 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 */ diff --git a/tools/apout/bsd_signal.c b/tools/apout/bsd_signal.c new file mode 100644 index 0000000..9e1875f --- /dev/null +++ b/tools/apout/bsd_signal.c @@ -0,0 +1,232 @@ +/* + * Much of this file comes from 2.11BSD's /usr/include/signal.h and is + * Copyright (c) 1986 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + * + * Code to deal with 2.11BSD signals + */ +#include "defines.h" +#include +#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)) 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; isa_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 */ diff --git a/tools/apout/bsdtrap.c b/tools/apout/bsdtrap.c new file mode 100644 index 0000000..0a57b24 --- /dev/null +++ b/tools/apout/bsdtrap.c @@ -0,0 +1,877 @@ +/* bsdtrap.c - Deal with 2.11BSD trap instructions. + * + * $Revision: 1.65 $ + * $Date: 2002/06/10 11:43:24 $ + */ +#ifdef EMU211 + +/* NOTE NOTE NOTE NOTE + * Grep for the word DONE in this file to see the implemented syscalls. + */ + +#define BSDTRAP_NAME +#include "defines.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bsdtrap.h" +#ifdef __linux__ +#include /* 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 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; jMAX_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; j16) { 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; jrlim_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 */ diff --git a/tools/apout/bsdtrap.h b/tools/apout/bsdtrap.h new file mode 100644 index 0000000..3773df5 --- /dev/null +++ b/tools/apout/bsdtrap.h @@ -0,0 +1,429 @@ +/* bsdtrap.h. Definitions for values and structures used in bsdtrap.c + * + * $Revision: 1.30 $ + * $Date: 1999/03/01 19:14:16 $ + */ + +/* In this file, we list the trap number for each system call, + * and the structures associated with several of the systems + * calls in 2.11BSD UNIX + */ + +#define S_INDIR 0 +#define S_EXIT 1 +#define S_FORK 2 +#define S_READ 3 +#define S_WRITE 4 +#define S_OPEN 5 +#define S_CLOSE 6 +#define S_WAIT4 7 +#define S_CREAT 8 +#define S_LINK 9 +#define S_UNLINK 10 +#define S_EXECV 11 +#define S_CHDIR 12 +#define S_FCHDIR 13 +#define S_MKNOD 14 +#define S_CHMOD 15 +#define S_CHOWN 16 +#define S_CHFLAGS 17 +#define S_FCHFLAGS 18 +#define S_LSEEK 19 +#define S_GETPID 20 +#define S_MOUNT 21 +#define S_UMOUNT 22 +#define S_SYSCTL 23 +#define S_GETUID 24 +#define S_GETEUID 25 +#define S_PTRACE 26 +#define S_GETPPID 27 +#define S_STATFS 28 +#define S_FSTATFS 29 +#define S_GETFSSTAT 30 +#define S_SIGACTION 31 +#define S_SIGPROCMASK 32 +#define S_ACCESS 33 +#define S_SIGPENDING 34 +#define S_SIGALTSTACK 35 +#define S_SYNC 36 +#define S_KILL 37 +#define S_STAT 38 +#define S_GETLOGIN 39 +#define S_LSTAT 40 +#define S_DUP 41 +#define S_PIPE 42 +#define S_SETLOGIN 43 +#define S_PROFIL 44 +#define S_SETUID 45 +#define S_SETEUID 46 +#define S_GETGID 47 +#define S_GETEGID 48 +#define S_SETGID 49 +#define S_SETEGID 50 +#define S_ACCT 51 +#define S_OLDPHYS 52 +#define S_OLDLOCK 53 +#define S_IOCTL 54 +#define S_REBOOT 55 +#define S_SYMLINK 57 +#define S_READLINK 58 +#define S_EXECVE 59 +#define S_UMASK 60 +#define S_CHROOT 61 +#define S_FSTAT 62 +#define S_GETPAGESIZE 64 +#define S_VFORK 66 +#define S_SBRK 69 +#define S_VHANGUP 76 +#define S_GETGROUPS 79 +#define S_SETGROUPS 80 +#define S_GETPGRP 81 +#define S_SETPGRP 82 +#define S_SETITIMER 83 +#define S_WAIT 84 +#define S_GETITIMER 86 +#define S_GETHOSTNAME 87 +#define S_SETHOSTNAME 88 +#define S_GETDTABLESIZE 89 +#define S_DUP2 90 +#define S_UNUSED1 91 +#define S_FCNTL 92 +#define S_SELECT 93 +#define S_UNUSED2 94 +#define S_FSYNC 95 +#define S_SETPRIORITY 96 +#define S_SOCKET 97 +#define S_CONNECT 98 +#define S_ACCEPT 99 +#define S_GETPRIORITY 100 +#define S_SEND 101 +#define S_RECV 102 +#define S_SIGRETURN 103 +#define S_BIND 104 +#define S_SETSOCKOPT 105 +#define S_LISTEN 106 +#define S_SIGSUSPEND 107 +#define S_SIGVEC 108 +#define S_SIGBLOCK 109 +#define S_SIGSETMASK 110 +#define S_SIGPAUSE 111 +#define S_SIGSTACK 112 +#define S_RECVMSG 113 +#define S_SENDMSG 114 +#define S_GETTIMEOFDAY 116 +#define S_GETRUSAGE 117 +#define S_GETSOCKOPT 118 +#define S_READV 120 +#define S_WRITEV 121 +#define S_SETTIMEOFDAY 122 +#define S_FCHOWN 123 +#define S_FCHMOD 124 +#define S_RECVFROM 125 +#define S_SETREUID 126 +#define S_SETREGID 127 +#define S_RENAME 128 +#define S_TRUNCATE 129 +#define S_FTRUNCATE 130 +#define S_FLOCK 131 +#define S_SENDTO 133 +#define S_SHUTDOWN 134 +#define S_SOCKETPAIR 135 +#define S_MKDIR 136 +#define S_RMDIR 137 +#define S_UTIMES 138 +#define S_ADJTIME 140 +#define S_GETPEERNAME 141 +#define S_GETHOSTID 142 +#define S_SETHOSTID 143 +#define S_GETRLIMIT 144 +#define S_SETRLIMIT 145 +#define S_KILLPG 146 +#define S_NOSYS147 147 +#define S_SETQUOTA 148 +#define S_QUOTA 149 +#define S_GETSOCKNAME 150 + + +/* + * System call names. + */ +#ifdef BSDTRAP_NAME +char *bsdtrap_name[] = { + "indir", /* 0 = indir */ + "exit", /* 1 = exit */ + "fork", /* 2 = fork */ + "read", /* 3 = read */ + "write", /* 4 = write */ + "open", /* 5 = open */ + "close", /* 6 = close */ + "wait4", /* 7 = wait4 */ + "creat", /* 8 = creat */ + "link", /* 9 = link */ + "unlink", /* 10 = unlink */ + "execv", /* 11 = execv */ + "chdir", /* 12 = chdir */ + "fchdir", /* 13 = fchdir */ + "mknod", /* 14 = mknod */ + "chmod", /* 15 = chmod */ + "chown", /* 16 = chown; now 3 args */ + "chflags", /* 17 = chflags */ + "fchflags", /* 18 = fchflags */ + "lseek", /* 19 = lseek */ + "getpid", /* 20 = getpid */ + "mount", /* 21 = mount */ + "umount", /* 22 = umount */ + "__sysctl", /* 23 = __sysctl */ + "getuid", /* 24 = getuid */ + "geteuid", /* 25 = geteuid */ + "ptrace", /* 26 = ptrace */ + "getppid", /* 27 = getppid */ + "statfs", /* 28 = statfs */ + "fstatfs", /* 29 = fstatfs */ + "getfsstat", /* 30 = getfsstat */ + "sigaction", /* 31 = sigaction */ + "sigprocmask", /* 32 = sigprocmask */ + "access", /* 33 = access */ + "sigpending", /* 34 = sigpending */ + "sigaltstack", /* 35 = sigaltstack */ + "sync", /* 36 = sync */ + "kill", /* 37 = kill */ + "stat", /* 38 = stat */ + "getlogin", /* 39 = getlogin */ + "lstat", /* 40 = lstat */ + "dup", /* 41 = dup */ + "pipe", /* 42 = pipe */ + "setlogin", /* 43 = setlogin */ + "profil", /* 44 = profil */ + "setuid", /* 45 = setuid */ + "seteuid", /* 46 = seteuid */ + "getgid", /* 47 = getgid */ + "getegid", /* 48 = getegid */ + "setgid", /* 49 = setgid */ + "setegid", /* 50 = setegid */ + "acct", /* 51 = turn acct off/on */ + "old phys", /* 52 = old set phys addr */ + "old lock", /* 53 = old lock in core */ + "ioctl", /* 54 = ioctl */ + "reboot", /* 55 = reboot */ + "old mpx - nosys", /* 56 = old mpxchan */ + "symlink", /* 57 = symlink */ + "readlink", /* 58 = readlink */ + "execve", /* 59 = execve */ + "umask", /* 60 = umask */ + "chroot", /* 61 = chroot */ + "fstat", /* 62 = fstat */ + "#63", /* 63 = used internally */ + "getpagesize", /* 64 = getpagesize */ + "4.3 mremap - nosys", /* 65 = mremap */ + "vfork", /* 66 = vfork */ + "old vread - nosys", /* 67 = old vread */ + "old vwrite - nosys", /* 68 = old vwrite */ + "sbrk", /* 69 = sbrk */ + "4.3 sstk - nosys", /* 70 = sstk */ + "4.3 mmap - nosys", /* 71 = mmap */ + "old vadvise - nosys", /* 72 = old vadvise */ + "4.3 munmap - nosys", /* 73 = munmap */ + "4.3 mprotect - nosys", /* 74 = mprotect */ + "4.3 madvise - nosys", /* 75 = madvise */ + "vhangup", /* 76 = vhangup */ + "old vlimit - nosys", /* 77 = old vlimit */ + "4.3 mincore - nosys", /* 78 = mincore */ + "getgroups", /* 79 = getgroups */ + "setgroups", /* 80 = setgroups */ + "getpgrp", /* 81 = getpgrp */ + "setpgrp", /* 82 = setpgrp */ + "setitimer", /* 83 = setitimer */ + "wait", /* 84 = wait */ + "4.3 swapon - nosys", /* 85 = swapon */ + "getitimer", /* 86 = getitimer */ + "gethostname", /* 87 = gethostname */ + "sethostname", /* 88 = sethostname */ + "getdtablesize", /* 89 = getdtablesize */ + "dup2", /* 90 = dup2 */ + "nosys", /* 91 = unused */ + "fcntl", /* 92 = fcntl */ + "select", /* 93 = select */ + "nosys", /* 94 = unused */ + "fsync", /* 95 = fsync */ + "setpriority", /* 96 = setpriority */ + "socket", /* 97 = socket */ + "connect", /* 98 = connect */ + "accept", /* 99 = accept */ + "getpriority", /* 100 = getpriority */ + "send", /* 101 = send */ + "recv", /* 102 = recv */ + "sigreturn", /* 103 = sigreturn */ + "bind", /* 104 = bind */ + "setsockopt", /* 105 = setsockopt */ + "listen", /* 106 = listen */ + "sigsuspend", /* 107 = sigsuspend */ + "sigvec", /* 108 = sigvec */ + "sigblock", /* 109 = sigblock */ + "sigsetmask", /* 110 = sigsetmask */ + "sigpause", /* 111 = sigpause */ + "sigstack", /* 112 = sigstack */ + "recvmsg", /* 113 = recvmsg */ + "sendmsg", /* 114 = sendmsg */ + "old vtrace - nosys", /* 115 = old vtrace */ + "gettimeofday", /* 116 = gettimeofday */ + "getrusage", /* 117 = getrusage */ + "getsockopt", /* 118 = getsockopt */ + "4.3 resuba - nosys", /* 119 = resuba */ + "readv", /* 120 = readv */ + "writev", /* 121 = writev */ + "settimeofday", /* 122 = settimeofday */ + "fchown", /* 123 = fchown */ + "fchmod", /* 124 = fchmod */ + "recvfrom", /* 125 = recvfrom */ + "setreuid", /* 126 = setreuid */ + "setregid", /* 127 = setregid */ + "rename", /* 128 = rename */ + "truncate", /* 129 = truncate */ + "ftruncate", /* 130 = ftruncate */ + "flock", /* 131 = flock */ + "old portal - nosys", /* 132 = old portal */ + "sendto", /* 133 = sendto */ + "shutdown", /* 134 = shutdown */ + "socketpair", /* 135 = socketpair */ + "mkdir", /* 136 = mkdir */ + "rmdir", /* 137 = rmdir */ + "utimes", /* 138 = utimes */ + "4.2 sigreturn - nosys", /* 139 = old 4.2 sigreturn */ + "adjtime", /* 140 = adjtime */ + "getpeername", /* 141 = getpeername */ + "gethostid", /* 142 = gethostid */ + "sethostid", /* 143 = sethostid */ + "getrlimit", /* 144 = getrlimit */ + "setrlimit", /* 145 = setrlimit */ + "killpg", /* 146 = killpg */ + "#147", /* 147 = nosys */ + "setquota", /* 148 = setquota */ + "quota", /* 149 = quota */ + "getsockname", /* 150 = getsockname */ +}; +#endif + +/* fcntl defines used by open */ +#define BSD_RDONLY 0x0000 /* open for reading only */ +#define BSD_WRONLY 0x0001 /* open for writing only */ +#define BSD_RDWR 0x0002 /* open for reading and writing */ +#define BSD_NONBLOCK 0x0004 /* no delay */ +#define BSD_APPEND 0x0008 /* set append mode */ +#define BSD_SHLOCK 0x0010 /* open with shared file lock */ +#define BSD_EXLOCK 0x0020 /* open with exclusive file lock */ +#define BSD_ASYNC 0x0040 /* signal pgrp when data ready */ +#define BSD_FSYNC 0x0080 /* synchronous writes */ +#define BSD_CREAT 0x0200 /* create if nonexistant */ +#define BSD_TRUNC 0x0400 /* truncate to zero length */ +#define BSD_EXCL 0x0800 /* error if already exists */ + + +/* stat struct, used by S_STAT, S_FSTAT, S_LSTAT */ +struct tr_stat +{ + int16_t st_dev; + u_int16_t st_ino; + u_int16_t st_mode; + int16_t st_nlink; + u_int16_t st_uid; + u_int16_t st_gid; + int16_t st_rdev; + int8_t st_size[4]; /* Alignment problems */ + int8_t st_atim[4]; /* Alignment problems */ + int16_t st_spare1; + int8_t st_mtim[4]; /* Alignment problems */ + int16_t st_spare2; + int8_t st_ctim[4]; /* Alignment problems */ + int16_t st_spare3; + int8_t st_blksize[4]; /* Alignment problems */ + int8_t st_blocks[4]; /* Alignment problems */ + u_int16_t st_flags; + u_int16_t st_spare4[3]; +}; + +/* Directory entry */ +#define TR_DIRBLKSIZ 512 +#define TR_MAXNAMLEN 63 +struct tr_direct { + u_int16_t d_ino; /* inode number of entry */ + u_int16_t d_reclen; /* length of this record */ + u_int16_t d_namlen; /* length of string in d_name */ + char d_name[TR_MAXNAMLEN+1]; /* name must be no longer than this */ +}; + +/* used by S_ADJTIME */ +struct tr_timeval { + u_int32_t tv_sec; /* seconds */ + u_int32_t tv_usec; /* and microseconds */ +}; +/* Used by S_GETTIMEOFDAY */ +struct tr_timezone { + int16_t tz_minuteswest; /* minutes west of Greenwich */ + int16_t tz_dsttime; /* type of dst correction */ +}; + +/* used in itimer calls */ +struct tr_itimerval { + struct tr_timeval it_interval; /* timer interval */ + struct tr_timeval it_value; /* current value */ +}; + +/* Used by socket calls */ +struct tr_sockaddr { + u_int16_t sa_family; /* address family */ + char sa_data[14]; /* up to 14 bytes of direct address */ +}; + +/* used in rlimit calls */ +struct tr_rlimit { + int32_t rlim_cur; /* current (soft) limit */ + int32_t rlim_max; /* maximum value for rlim_cur */ +}; + +struct tr_rusage { + struct tr_timeval ru_utime; /* user time used */ + struct tr_timeval ru_stime; /* system time used */ + u_int32_t ru_maxrss; + u_int32_t ru_ixrss; /* integral shared memory size */ + u_int32_t ru_idrss; /* integral unshared data size */ + u_int32_t ru_isrss; /* integral unshared stack size */ + u_int32_t ru_minflt; /* page reclaims */ + u_int32_t ru_majflt; /* page faults */ + u_int32_t ru_ovly; /* overlay changes */ + u_int32_t ru_nswap; /* swaps */ + u_int32_t ru_inblock; /* block input operations */ + u_int32_t ru_oublock; /* block output operations */ + u_int32_t ru_msgsnd; /* messages sent */ + u_int32_t ru_msgrcv; /* messages received */ + u_int32_t ru_nsignals; /* signals received */ + u_int32_t ru_nvcsw; /* voluntary context switches */ + u_int32_t ru_nivcsw; /* involuntary context switches */ +}; + +/* for writev, readv */ +struct tr_iovec { + u_int16_t iov_base; + u_int16_t iov_len; +}; + + +/* A union which will point at the trap args, so that + * we can get at the various args of different types + */ +typedef union { + int16_t sarg[6]; /* Signed 16-bit args */ + u_int16_t uarg[6]; /* Unsigned 16-bit args */ +} arglist; + +#define sarg1 A->sarg[0] +#define sarg2 A->sarg[1] +#define sarg3 A->sarg[2] +#define sarg4 A->sarg[3] +#define sarg5 A->sarg[4] +#define sarg6 A->sarg[5] +#define uarg1 A->uarg[0] +#define uarg2 A->uarg[1] +#define uarg3 A->uarg[2] +#define uarg4 A->uarg[3] +#define uarg5 A->uarg[4] +#define uarg6 A->uarg[5] diff --git a/tools/apout/cpu.c b/tools/apout/cpu.c new file mode 100644 index 0000000..17753f4 --- /dev/null +++ b/tools/apout/cpu.c @@ -0,0 +1,209 @@ +/* cpu.c - this holds the main loop for the emulator, plus generic + * functions to deal with exceptional instructions and events + * + * $Revision: 1.25 $ + * $Date: 2002/06/10 11:41:40 $ + */ +#include "defines.h" +#include + +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; } +} diff --git a/tools/apout/debug.c b/tools/apout/debug.c new file mode 100644 index 0000000..feb081d --- /dev/null +++ b/tools/apout/debug.c @@ -0,0 +1,159 @@ +/* List of names for each instruction + * + * $Revision: 1.5 $ + * $Date: 1999/01/05 22:50:48 $ + */ +#ifdef DEBUG +char *iname0[64] = { + "halt","waiti","illegal","bpt","iot","illegal","illegal","illegal", +"illegal","illegal","illegal","illegal","illegal","illegal","illegal","illegal", +"illegal","illegal","illegal","illegal","illegal","illegal","illegal","illegal", +"illegal","illegal","illegal","illegal","illegal","illegal","illegal","illegal", +"illegal","illegal","illegal","illegal","illegal","illegal","illegal","illegal", +"illegal","illegal","illegal","illegal","illegal","illegal","illegal","illegal", +"illegal","illegal","illegal","illegal","illegal","illegal","illegal","illegal", +"illegal","illegal","illegal","illegal","illegal","illegal","illegal","illegal" +}; + +char *iname1[64] = { + "rts","rts","rts","rts","rts","rts","rts","rts", +"illegal","illegal","illegal","illegal","illegal","illegal","illegal","illegal", +"illegal","illegal","illegal","illegal","illegal","illegal","illegal","illegal", +"illegal","illegal","illegal","illegal","illegal","illegal","illegal","illegal", + "ccc","ccc","ccc","ccc","ccc","ccc","ccc","ccc", + "ccc","ccc","ccc","ccc","ccc","ccc","ccc","ccc", + "scc","scc","scc","scc","scc","scc","scc","scc", + "scc","scc","scc","scc","scc","scc","scc","scc" +}; + +char *iname[1024] = { + "dositab0","jmp","dositab1","swabi","br","br","br","br", + "bne","bne","bne","bne","beq","beq","beq","beq", + "bge","bge","bge","bge","blt","blt","blt","blt", + "bgt","bgt","bgt","bgt","ble","ble","ble","ble", + "jsr","jsr","jsr","jsr","jsr","jsr","jsr","jsr", + "clr","com","inc","dec","neg","adc","sbc","tst", + "ror","rol","asr","asl","mark","mfpi","mtpi","sxt", +"illegal","illegal","illegal","illegal","illegal","illegal","illegal","illegal", + "mov","mov","mov","mov","mov","mov","mov","mov", + "mov","mov","mov","mov","mov","mov","mov","mov", + "mov","mov","mov","mov","mov","mov","mov","mov", + "mov","mov","mov","mov","mov","mov","mov","mov", + "mov","mov","mov","mov","mov","mov","mov","mov", + "mov","mov","mov","mov","mov","mov","mov","mov", + "mov","mov","mov","mov","mov","mov","mov","mov", + "mov","mov","mov","mov","mov","mov","mov","mov", + "cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp", + "cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp", + "cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp", + "cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp", + "cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp", + "cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp", + "cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp", + "cmp","cmp","cmp","cmp","cmp","cmp","cmp","cmp", + "bit","bit","bit","bit","bit","bit","bit","bit", + "bit","bit","bit","bit","bit","bit","bit","bit", + "bit","bit","bit","bit","bit","bit","bit","bit", + "bit","bit","bit","bit","bit","bit","bit","bit", + "bit","bit","bit","bit","bit","bit","bit","bit", + "bit","bit","bit","bit","bit","bit","bit","bit", + "bit","bit","bit","bit","bit","bit","bit","bit", + "bit","bit","bit","bit","bit","bit","bit","bit", + "bic","bic","bic","bic","bic","bic","bic","bic", + "bic","bic","bic","bic","bic","bic","bic","bic", + "bic","bic","bic","bic","bic","bic","bic","bic", + "bic","bic","bic","bic","bic","bic","bic","bic", + "bic","bic","bic","bic","bic","bic","bic","bic", + "bic","bic","bic","bic","bic","bic","bic","bic", + "bic","bic","bic","bic","bic","bic","bic","bic", + "bic","bic","bic","bic","bic","bic","bic","bic", + "bis","bis","bis","bis","bis","bis","bis","bis", + "bis","bis","bis","bis","bis","bis","bis","bis", + "bis","bis","bis","bis","bis","bis","bis","bis", + "bis","bis","bis","bis","bis","bis","bis","bis", + "bis","bis","bis","bis","bis","bis","bis","bis", + "bis","bis","bis","bis","bis","bis","bis","bis", + "bis","bis","bis","bis","bis","bis","bis","bis", + "bis","bis","bis","bis","bis","bis","bis","bis", + "add","add","add","add","add","add","add","add", + "add","add","add","add","add","add","add","add", + "add","add","add","add","add","add","add","add", + "add","add","add","add","add","add","add","add", + "add","add","add","add","add","add","add","add", + "add","add","add","add","add","add","add","add", + "add","add","add","add","add","add","add","add", + "add","add","add","add","add","add","add","add", + "mul","mul","mul","mul","mul","mul","mul","mul", + "divide","divide","divide","divide","divide","divide","divide","divide", + "ash","ash","ash","ash","ash","ash","ash","ash", + "ashc","ashc","ashc","ashc","ashc","ashc","ashc","ashc", + "xor","xor","xor","xor","xor","xor","xor","xor", +"illegal","illegal","illegal","illegal","illegal","illegal","illegal","illegal", +"illegal","illegal","illegal","illegal","illegal","illegal","illegal","illegal", + "sob","sob","sob","sob","sob","sob","sob","sob", + "bpl","bpl","bpl","bpl","bmi","bmi","bmi","bmi", + "bhi","bhi","bhi","bhi","blos","blos","blos","blos", + "bvc","bvc","bvc","bvc","bvs","bvs","bvs","bvs", + "bcc","bcc","bcc","bcc","bcs","bcs","bcs","bcs", + "emt","emt","emt","emt","trap","trap","trap","trap", + "clrb","comb","incb","decb","negb","adcb","sbcb","tstb", + "rorb","rolb","asrb","aslb","mtps","mfpd","mtpd","mfps", +"illegal","illegal","illegal","illegal","illegal","illegal","illegal","illegal", + "movb","movb","movb","movb","movb","movb","movb","movb", + "movb","movb","movb","movb","movb","movb","movb","movb", + "movb","movb","movb","movb","movb","movb","movb","movb", + "movb","movb","movb","movb","movb","movb","movb","movb", + "movb","movb","movb","movb","movb","movb","movb","movb", + "movb","movb","movb","movb","movb","movb","movb","movb", + "movb","movb","movb","movb","movb","movb","movb","movb", + "movb","movb","movb","movb","movb","movb","movb","movb", + "cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb", + "cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb", + "cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb", + "cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb", + "cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb", + "cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb", + "cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb", + "cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb","cmpb", + "bitb","bitb","bitb","bitb","bitb","bitb","bitb","bitb", + "bitb","bitb","bitb","bitb","bitb","bitb","bitb","bitb", + "bitb","bitb","bitb","bitb","bitb","bitb","bitb","bitb", + "bitb","bitb","bitb","bitb","bitb","bitb","bitb","bitb", + "bitb","bitb","bitb","bitb","bitb","bitb","bitb","bitb", + "bitb","bitb","bitb","bitb","bitb","bitb","bitb","bitb", + "bitb","bitb","bitb","bitb","bitb","bitb","bitb","bitb", + "bitb","bitb","bitb","bitb","bitb","bitb","bitb","bitb", + "bicb","bicb","bicb","bicb","bicb","bicb","bicb","bicb", + "bicb","bicb","bicb","bicb","bicb","bicb","bicb","bicb", + "bicb","bicb","bicb","bicb","bicb","bicb","bicb","bicb", + "bicb","bicb","bicb","bicb","bicb","bicb","bicb","bicb", + "bicb","bicb","bicb","bicb","bicb","bicb","bicb","bicb", + "bicb","bicb","bicb","bicb","bicb","bicb","bicb","bicb", + "bicb","bicb","bicb","bicb","bicb","bicb","bicb","bicb", + "bicb","bicb","bicb","bicb","bicb","bicb","bicb","bicb", + "bisb","bisb","bisb","bisb","bisb","bisb","bisb","bisb", + "bisb","bisb","bisb","bisb","bisb","bisb","bisb","bisb", + "bisb","bisb","bisb","bisb","bisb","bisb","bisb","bisb", + "bisb","bisb","bisb","bisb","bisb","bisb","bisb","bisb", + "bisb","bisb","bisb","bisb","bisb","bisb","bisb","bisb", + "bisb","bisb","bisb","bisb","bisb","bisb","bisb","bisb", + "bisb","bisb","bisb","bisb","bisb","bisb","bisb","bisb", + "bisb","bisb","bisb","bisb","bisb","bisb","bisb","bisb", + "sub","sub","sub","sub","sub","sub","sub","sub", + "sub","sub","sub","sub","sub","sub","sub","sub", + "sub","sub","sub","sub","sub","sub","sub","sub", + "sub","sub","sub","sub","sub","sub","sub","sub", + "sub","sub","sub","sub","sub","sub","sub","sub", + "sub","sub","sub","sub","sub","sub","sub","sub", + "sub","sub","sub","sub","sub","sub","sub","sub", + "sub","sub","sub","sub","sub","sub","sub","sub", + "fpset","ldfps","stfps","stst","clrf","tstf","absf","negf", + "mulf","mulf","mulf","mulf","moddf","moddf","moddf","moddf", + "addf","addf","addf","addf","ldf","ldf","ldf","ldf", + "subf","subf","subf","subf","cmpf","cmpf","cmpf","cmpf", + "stf","stf","stf","stf","divf","divf","divf","divf", + "stexp","stexp","stexp","stexp","stcfi","stcfi","stcfi","stcfi", + "stcdf","stcdf","stcdf","stcdf","ldexpp","ldexpp","ldexpp","ldexpp", + "lcdif","lcdif","lcdif","lcdif","ldcdf","ldcdf","ldcdf","ldcdf" +}; +#endif diff --git a/tools/apout/defines.h b/tools/apout/defines.h new file mode 100644 index 0000000..b0d8119 --- /dev/null +++ b/tools/apout/defines.h @@ -0,0 +1,636 @@ +/* defines.h - Definitions of things needed in all C files + * + * $Revision: 2.73 $ + * $Date: 2002/06/10 12:08:27 $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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> 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=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=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=KE11LO) && (addr<=KE11HI)) { \ + kesl_word(addr, word); \ + } else { adptr= (u_int16_t *)&(dspace[addr]); *adptr= word; } \ + } +#else +#define sl_word(addr, word) \ + { if ((Binary=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=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=KE11LO) && (addr<=KE11HI)) { \ + kesl_byte(addr, byte); \ + } else dspace[addr]= byte; \ + } +#else +#define sl_byte(addr, byte) \ + { if ((Binary=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 diff --git a/tools/apout/double.c b/tools/apout/double.c new file mode 100644 index 0000000..4650406 --- /dev/null +++ b/tools/apout/double.c @@ -0,0 +1,280 @@ +/* double.c - Double operand instructions. + * + * $Revision: 2.11 $ + * $Date: 1999/12/27 10:19:40 $ + */ +#include "defines.h" + +static u_int32_t templong; + + +/* mov() - Move Instruction. Move operations with registers as the source + * and/or destination have been inlined. */ +void +mov() +{ + + if (SRC_MODE) { + load_src(); dstword=srcword; + } else { + dstword = regs[SRC_REG]; + } + + CHG_CC_N(dstword); + CHG_CC_Z(dstword); + CLR_CC_V(); + + if (DST_MODE) { + store_dst(); + } else { + regs[DST_REG] = dstword; + } +} + +/* movsreg(), movsreg1() and movsreg1pc() can all be replaced with + * mov() above. I've broken them out in an attempt to improve + * performance. + */ +void +movsreg() +{ + dstword = regs[SRC_REG]; + CHG_CC_N(dstword); + CHG_CC_Z(dstword); + CLR_CC_V(); + + if (DST_MODE) { + store_dst(); + } else { + regs[DST_REG] = dstword; + } +} + +void +movsreg1() +{ + ll_word(regs[SRC_REG], dstword); + CHG_CC_N(dstword); + CHG_CC_Z(dstword); + CLR_CC_V(); + + if (DST_MODE) { + store_dst(); + } else { + regs[DST_REG] = dstword; + } +} + +void +movsreg1pc() +{ + lli_word(regs[PC], dstword) + CHG_CC_N(dstword); + CHG_CC_Z(dstword); + CLR_CC_V(); + + if (DST_MODE) { + store_dst(); + } else { + regs[DST_REG] = dstword; + } +} + + + +/* cmp() - Compare Instruction. */ +void +cmp() +{ + load_src(); + load_dst(); + + tmpword = ~dstword; + templong = ((u_int32_t) srcword) + ((u_int32_t) (tmpword)) + 1; + tmpword = LOW16(templong); + + CHG_CC_N(tmpword); + CHG_CC_Z(tmpword); + CHG_CC_VC(srcword, dstword, tmpword); /* was CHG_CC_V */ + CHG_CC_IC(templong); +} + + +/* add() - Add Instruction. */ +void +add() +{ + load_src(); + load_dst(); + + templong = ((u_int32_t) srcword) + ((u_int32_t) dstword); + tmpword = LOW16(templong); + + CHG_CC_N(tmpword); + CHG_CC_Z(tmpword); + CHG_CC_V(srcword, dstword, tmpword); + CHG_CC_C(templong); + + dstword=tmpword; store_dst_2(); +} + +/* Subtract Instruction. */ +void +sub() +{ + load_src(); + load_dst(); + + tmpword = ~srcword; + templong = ((u_int32_t) dstword) + ((u_int32_t) tmpword) + 1; + tmpword = LOW16(templong); + + CHG_CC_N(tmpword); + CHG_CC_Z(tmpword); + CHG_CC_VS(srcword, dstword, tmpword); /* was CHG_CC_V */ + CHG_CC_IC(templong); + + dstword=tmpword; store_dst_2(); +} + + +/* bit() - Bit Test Instruction. */ +void +bit() +{ + load_src(); + load_dst(); + + dstword = srcword & dstword; + + CHG_CC_N(dstword); + CHG_CC_Z(dstword); + CLR_CC_V(); +} + +/* bic() - Bit Clear Instruction. */ +void +bic() +{ + load_src(); + load_dst(); + + dstword = (~srcword) & dstword; + CHG_CC_N(dstword); + CHG_CC_Z(dstword); + CLR_CC_V(); + + store_dst_2(); +} + + +/* bis() - Bit Set Instruction. */ +void +bis() +{ + load_src(); + load_dst(); + + dstword = srcword | dstword; + + CHG_CC_N(dstword); + CHG_CC_Z(dstword); + CLR_CC_V(); + + store_dst_2(); +} + +/* movb() - Move Byte Instruction. Move operations with registers as the + * source and/or destination have been inlined. */ +void +movb() +{ + if (SRC_MODE) { + loadb_src(); + } else { + srcbyte = LOW8(regs[SRC_REG]); + } + + CHGB_CC_N(srcbyte); + CHGB_CC_Z(srcbyte); + CLR_CC_V(); + + /* move byte to a register causes sign extension */ + + if (DST_MODE) { + storeb_dst(); + } else { + if (srcbyte & SIGN_B) + regs[DST_REG] = (u_int16_t)0177400 + (u_int16_t)srcbyte; + else + regs[DST_REG] = (u_int16_t)srcbyte; + } +} + +/* cmpb() - Compare Byte Instruction. */ +void +cmpb() +{ + u_int8_t data3; + + loadb_src(); + loadb_dst(); + + data3 = (u_int8_t)~dstbyte; + tmpword = ((u_int16_t) srcbyte) + ((u_int16_t) (data3)) + 1; + data3 = LOW8(tmpword); + + CHGB_CC_N(data3); + CHGB_CC_Z(data3); + CHGB_CC_VC(srcbyte, dstbyte, data3); + CHGB_CC_IC(tmpword); +} + + +/* bitb() - Bit Test Byte Instruction. */ +void +bitb() +{ + loadb_src(); + loadb_dst(); + + dstbyte = srcbyte & dstbyte; + + CHGB_CC_N(dstbyte); + CHGB_CC_Z(dstbyte); + CLR_CC_V(); +} + +/* bicb() - Bit Clear Byte Instruction. */ +void +bicb() +{ + loadb_src(); + loadb_dst(); + + dstbyte = (u_int8_t)((~srcbyte) & dstbyte); + + CHGB_CC_N(dstbyte); + CHGB_CC_Z(dstbyte); + CLR_CC_V(); + + storeb_dst_2(); +} + + +/* bisb() - Bit Set Byte Instruction. */ + +void +bisb() +{ + loadb_src(); + loadb_dst(); + + dstbyte = srcbyte | dstbyte; + + CHGB_CC_N(dstbyte); + CHGB_CC_Z(dstbyte); + CLR_CC_V(); + + storeb_dst_2(); +} diff --git a/tools/apout/ea.c b/tools/apout/ea.c new file mode 100644 index 0000000..31c9587 --- /dev/null +++ b/tools/apout/ea.c @@ -0,0 +1,588 @@ +/* ea.c - Calculate, load, and store using the proper effective address as + * specified by the current instruction. Also push and pop stack operations. + * + * $Revision: 2.17 $ + * $Date: 1999/09/17 05:11:10 $ + */ +#include "defines.h" + +void +load_ea(void) +{ + u_int16_t indirect; + + switch (DST_MODE) { + case 0: + illegal(); + return; + case 1: + dstword = regs[DST_REG]; + return; + case 2: + dstword = regs[DST_REG]; /* this is wrong for 11/34 */ + regs[DST_REG] += 2; + return; + case 3: + indirect = regs[DST_REG]; /* this is wrong for 11/34 */ + regs[DST_REG] += 2; + lli_word(indirect, dstword); + return; + case 4: + regs[DST_REG] -= 2; + dstword = regs[DST_REG]; + return; + case 5: + regs[DST_REG] -= 2; + indirect = regs[DST_REG]; + lli_word(indirect, dstword); + return; + case 6: + lli_word(regs[PC], indirect); + regs[PC] += 2; + dstword = regs[DST_REG] + indirect; + return; + case 7: + lli_word(regs[PC], indirect); + regs[PC] += 2; + indirect = regs[DST_REG] + indirect; + ll_word(indirect, dstword); + return; + } + illegal(); +} + + +INLINE void +pop(void) +{ + ll_word(regs[SP], dstword); + regs[SP] += 2; +} + + +INLINE void +push(void) +{ + regs[SP] -= 2; + sl_word(regs[SP], srcword); +} + + +void +loadb_dst(void) +{ + u_int16_t addr, indirect; + + switch (DST_MODE) { + case 0: + dstbyte = (u_int8_t)(regs[DST_REG] & 0377); + return; + case 1: + addr = regs[DST_REG]; + ea_addr = addr; + if (DST_REG == PC) { + lli_byte(addr, dstbyte) + } else { + ll_byte(addr, dstbyte); + } + return; + case 2: + addr = regs[DST_REG]; + ea_addr = addr; + if (DST_REG == PC) { + lli_byte(addr, dstbyte) + } else { + ll_byte(addr, dstbyte); + } + if (DST_REG >= 6) + regs[DST_REG] += 2; + else + regs[DST_REG] += 1; + return; + case 3: + indirect = regs[DST_REG]; + if (DST_REG == PC) { + lli_word(indirect, addr) + } else { + ll_word(indirect, addr); + } + ea_addr = addr; + ll_byte(addr, dstbyte); + regs[DST_REG] += 2; + return; + case 4: + if (DST_REG >= 6) + regs[DST_REG] -= 2; + else + regs[DST_REG] -= 1; + addr = regs[DST_REG]; + ea_addr = addr; + ll_byte(addr, dstbyte); + return; + case 5: + regs[DST_REG] -= 2; + indirect = regs[DST_REG]; + ll_word(indirect, addr); + ea_addr = addr; + ll_byte(addr, dstbyte); + return; + case 6: + lli_word(regs[PC], indirect); + regs[PC] += 2; + addr = regs[DST_REG] + indirect; + ea_addr = addr; + ll_byte(addr, dstbyte); + return; + case 7: + lli_word(regs[PC], indirect); + regs[PC] += 2; + indirect = regs[DST_REG] + indirect; + ll_word(indirect, addr); + ea_addr = addr; + ll_byte(addr, dstbyte); + return; + } + illegal(); +} + + +void +loadb_src(void) +{ + u_int16_t addr, indirect; + + switch (SRC_MODE) { + case 0: + srcbyte = (u_int8_t)(regs[SRC_REG] & 0377); + return; + case 1: + addr = regs[SRC_REG]; + if (SRC_REG == PC) { + lli_byte(addr, srcbyte); + } else { + ll_byte(addr, srcbyte); + } + return; + case 2: + addr = regs[SRC_REG]; + if (SRC_REG == PC) { + lli_byte(addr, srcbyte); + } else { + ll_byte(addr, srcbyte); + } + if (SRC_REG >= 6) + regs[SRC_REG] += 2; + else + regs[SRC_REG] += 1; + return; + case 3: + indirect = regs[SRC_REG]; + if (SRC_REG == PC) { + lli_word(indirect, addr) + } else { + ll_word(indirect, addr); + } + ll_byte(addr, srcbyte); + regs[SRC_REG] += 2; + return; + case 4: + if (SRC_REG >= 6) + regs[SRC_REG] -= 2; + else + regs[SRC_REG] -= 1; + addr = regs[SRC_REG]; + ll_byte(addr, srcbyte); + return; + case 5: + regs[SRC_REG] -= 2; + indirect = regs[SRC_REG]; + ll_word(indirect, addr); + ll_byte(addr, srcbyte); + return; + case 6: + lli_word(regs[PC], indirect); + regs[PC] += 2; + addr = regs[SRC_REG] + indirect; + ll_byte(addr, srcbyte); + return; + case 7: + lli_word(regs[PC], indirect); + regs[PC] += 2; + indirect = regs[SRC_REG] + indirect; + ll_word(indirect, addr); + ll_byte(addr, srcbyte); + return; + } + illegal(); +} + +void +storeb_dst(void) +{ + u_int16_t addr, indirect; + + switch (DST_MODE) { + case 0: + regs[DST_REG]&= 0xff00; + regs[DST_REG]|= srcbyte; + return; + case 1: + addr = regs[DST_REG]; + sl_byte(addr, srcbyte); + return; + case 2: + addr = regs[DST_REG]; + sl_byte(addr, srcbyte); + if (DST_REG >= 6) + regs[DST_REG] += 2; + else + regs[DST_REG] += 1; + return; + case 3: + indirect = regs[DST_REG]; + ll_word(indirect, addr); + sl_byte(addr, srcbyte); + regs[DST_REG] += 2; + return; + case 4: + if (DST_REG >= 6) /* xyz */ + regs[DST_REG] -= 2; + else + regs[DST_REG] -= 1; + addr = regs[DST_REG]; + sl_byte(addr, srcbyte); + return; + case 5: + regs[DST_REG] -= 2; + indirect = regs[DST_REG]; + ll_word(indirect, addr); + sl_byte(addr, srcbyte); + return; + case 6: + lli_word(regs[PC], indirect); + regs[PC] += 2; + addr = regs[DST_REG] + indirect; + sl_byte(addr, srcbyte); + return; + case 7: + lli_word(regs[PC], indirect); + regs[PC] += 2; + indirect = regs[DST_REG] + indirect; + ll_word(indirect, addr); + sl_byte(addr, srcbyte); + return; + } + illegal(); +} + + +INLINE void +storeb_dst_2(void) +{ + if (DST_MODE == 0) { + regs[DST_REG]&= 0xff00; + regs[DST_REG]|= dstbyte; + return; + } + sl_byte(ea_addr, dstbyte); +} + + +void +loadp_dst(void) +{ + u_int16_t addr, indirect; + + switch (DST_MODE) { + case 0: + srcword = regs[DST_REG]; + return; + case 1: + addr = regs[DST_REG]; + ll_word(addr, srcword); + return; + case 2: + addr = regs[DST_REG]; + ll_word(addr, srcword); + regs[DST_REG] += 2; + return; + case 3: + indirect = regs[DST_REG]; + ll_word(indirect, addr); + ll_word(addr, srcword); + regs[DST_REG] += 2; + return; + case 4: + regs[DST_REG] -= 2; + addr = regs[DST_REG]; + ll_word(addr, srcword); + return; + case 5: + regs[DST_REG] -= 2; + indirect = regs[DST_REG]; + ll_word(indirect, addr); + ll_word(addr, srcword); + return; + case 6: + lli_word(regs[PC], indirect); + regs[PC] += 2; + addr = regs[DST_REG] + indirect; + if (DST_REG == PC) + lli_word(addr, srcword) + else + ll_word(addr, srcword); + return; + case 7: + not_impl(); + } + illegal(); +} + + +void +storep_dst(void) +{ + u_int16_t addr, indirect; + + switch (DST_MODE) { + case 0: + regs[DST_REG] = dstword; + return; + case 1: + addr = regs[DST_REG]; + sl_word(addr, dstword); + return; + case 2: + addr = regs[DST_REG]; + sl_word(addr, dstword); + regs[DST_REG] += 2; + return; + case 3: + indirect = regs[DST_REG]; + ll_word(indirect, addr); + sl_word(addr, dstword); + regs[DST_REG] += 2; + return; + case 4: + regs[DST_REG] -= 2; + addr = regs[DST_REG]; + sl_word(addr, dstword); + return; + case 5: + regs[DST_REG] -= 2; + indirect = regs[DST_REG]; + ll_word(indirect, addr); + sl_word(addr, dstword); + return; + case 6: + lli_word(regs[PC], indirect); + regs[PC] += 2; + addr = regs[DST_REG] + indirect; + sl_word(addr, dstword); + return; + case 7: + not_impl(); + } + illegal(); +} + + +void +load_src(void) +{ + u_int16_t addr, indirect; + + switch (SRC_MODE) { + case 0: + srcword = regs[SRC_REG]; + return; + case 1: + addr = regs[SRC_REG]; + if (SRC_REG == PC) { + lli_word(addr, srcword) + } else { + ll_word(addr, srcword); + } + return; + case 2: + addr = regs[SRC_REG]; + if (SRC_REG == PC) { + lli_word(addr, srcword) + } else { + ll_word(addr, srcword); + } + regs[SRC_REG] += 2; + return; + case 3: + indirect = regs[SRC_REG]; + if (SRC_REG == PC) { + lli_word(indirect, addr) + } else { + ll_word(indirect, addr); + } + regs[SRC_REG] += 2; /* is this right ? */ + ll_word(addr, srcword); + return; + case 4: + regs[SRC_REG] -= 2; + addr = regs[SRC_REG]; + ll_word(addr, srcword); + return; + case 5: + regs[SRC_REG] -= 2; + indirect = regs[SRC_REG]; + ll_word(indirect, addr); + ll_word(addr, srcword); + return; + case 6: + lli_word(regs[PC], indirect); + regs[PC] += 2; + addr = regs[SRC_REG] + indirect; + ll_word(addr, srcword); + return; + case 7: + lli_word(regs[PC], indirect); + regs[PC] += 2; + indirect = regs[SRC_REG] + indirect; + ll_word(indirect, addr); + ll_word(addr, srcword); + return; + } + illegal(); +} + + +void +store_dst(void) +{ + u_int16_t addr, indirect; + + switch (DST_MODE) { + case 0: + regs[DST_REG] = dstword; + return; + case 1: + addr = regs[DST_REG]; + sl_word(addr, dstword); + return; + case 2: + addr = regs[DST_REG]; + sl_word(addr, dstword); + regs[DST_REG] += 2; + return; + case 3: + indirect = regs[DST_REG]; + ll_word(indirect, addr); + regs[DST_REG] += 2; /* is this right ? */ + sl_word(addr, dstword); + return; + case 4: + regs[DST_REG] -= 2; + addr = regs[DST_REG]; + sl_word(addr, dstword); + return; + case 5: + regs[DST_REG] -= 2; + indirect = regs[DST_REG]; + ll_word(indirect, addr); + sl_word(addr, dstword); + return; + case 6: + lli_word(regs[PC], indirect); + regs[PC] += 2; + addr = regs[DST_REG] + indirect; + sl_word(addr, dstword); + return; + case 7: + lli_word(regs[PC], indirect); + regs[PC] += 2; + indirect = regs[DST_REG] + indirect; + ll_word(indirect, addr); + sl_word(addr, dstword); + return; + } + illegal(); +} + + +void +load_dst(void) +{ + u_int16_t addr, indirect; + + switch (DST_MODE) { + case 0: + dstword = regs[DST_REG]; + return; + case 1: + addr = regs[DST_REG]; + ea_addr = addr; + if (DST_REG == PC) { + lli_word(addr, dstword) + } else { + ll_word(addr, dstword); + } + return; + case 2: + addr = regs[DST_REG]; + ea_addr = addr; + if (DST_REG == PC) { + lli_word(addr, dstword) + } else { + ll_word(addr, dstword); + } + regs[DST_REG] += 2; + return; + case 3: + indirect = regs[DST_REG]; + if (DST_REG == PC) { + lli_word(indirect, addr) + } else { + ll_word(indirect, addr); + } + ea_addr = addr; + ll_word(addr, dstword); + regs[DST_REG] += 2; + return; + case 4: + regs[DST_REG] -= 2; + addr = regs[DST_REG]; + ea_addr = addr; + ll_word(addr, dstword); + return; + case 5: + regs[DST_REG] -= 2; + indirect = regs[DST_REG]; + ll_word(indirect, addr); + ea_addr = addr; + ll_word(addr, dstword); + return; + case 6: + lli_word(regs[PC], indirect); + regs[PC] += 2; + addr = regs[DST_REG] + indirect; + ea_addr = addr; + ll_word(addr, dstword); + return; + case 7: + lli_word(regs[PC], indirect); + regs[PC] += 2; + indirect = regs[DST_REG] + indirect; + ll_word(indirect, addr); + ea_addr = addr; + ll_word(addr, dstword); + return; + } + illegal(); +} + + +INLINE void +store_dst_2(void) +{ + if (DST_MODE == 0) { + regs[DST_REG] = dstword; + return; + } + sl_word(ea_addr, dstword); +} diff --git a/tools/apout/fp.c b/tools/apout/fp.c new file mode 100644 index 0000000..b3bc85d --- /dev/null +++ b/tools/apout/fp.c @@ -0,0 +1,616 @@ +/* fp.c - PDP-11 floating point operations + * + * $Revision: 2.23 $ + * $Date: 1999/12/30 02:11:16 $ + */ + +/* The floating-point emulation code here is just enough to allow + * 2.11BSD binaries to run. There is only emulation of PDP-11 + * 32-bit floats: the extra 32-bits of precision in PDP-11 doubles + * goes unused. As well, I don't try to emulate any of the FP errors. + * + * If this is a problem, then feel free to correct it. + */ +#include "defines.h" +#include +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); +} diff --git a/tools/apout/itab.c b/tools/apout/itab.c new file mode 100644 index 0000000..1961f5e --- /dev/null +++ b/tools/apout/itab.c @@ -0,0 +1,176 @@ +/* itab.c - Instruction decode table. + * + * $Revision: 2.12 $ + * $Date: 1999/12/27 10:19:40 $ + */ + +#include "defines.h" + +static _itab sitab0[64] = { + halt, waiti, illegal, bpt, iot, illegal, illegal, illegal, + illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal, + illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal, + illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal, + illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal, + illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal, + illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal, + illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal +}; + +static _itab sitab1[64] = { + rts, rts, rts, rts, rts, rts, rts, rts, + illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal, + illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal, + illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal, + ccc, ccc, ccc, ccc, ccc, ccc, ccc, ccc, + ccc, ccc, ccc, ccc, ccc, ccc, ccc, ccc, + scc, scc, scc, scc, scc, scc, scc, scc, + scc, scc, scc, scc, scc, scc, scc, scc +}; + +void +dositab0(void) +{ + sitab0[ir & 077] (); +} + +void +dositab1(void) +{ + sitab1[ir & 077] (); +} + +_itab itab[1024] = { + dositab0, jmp, dositab1, swabi, br, br, br, br, + bne, bne, bne, bne, beq, beq, beq, beq, + bge, bge, bge, bge, blt, blt, blt, blt, + bgt, bgt, bgt, bgt, ble, ble, ble, ble, + jsr, jsr, jsr, jsr, jsr, jsr, jsr, jsr, + clr, com, inc, dec, neg, adc, sbc, tst, + ror, rol, asr, asl, mark, mfpi, mtpi, sxt, + illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal, + movsreg,movsreg,movsreg,movsreg,movsreg,movsreg,movsreg,movsreg, + movsreg1,movsreg1,movsreg1,movsreg1,movsreg1,movsreg1,movsreg1,movsreg1pc, + mov, mov, mov, mov, mov, mov, mov, mov, + mov, mov, mov, mov, mov, mov, mov, mov, + mov, mov, mov, mov, mov, mov, mov, mov, + mov, mov, mov, mov, mov, mov, mov, mov, + mov, mov, mov, mov, mov, mov, mov, mov, + mov, mov, mov, mov, mov, mov, mov, mov, + cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp, + cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp, + cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp, + cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp, + cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp, + cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp, + cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp, + cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp, + bit, bit, bit, bit, bit, bit, bit, bit, + bit, bit, bit, bit, bit, bit, bit, bit, + bit, bit, bit, bit, bit, bit, bit, bit, + bit, bit, bit, bit, bit, bit, bit, bit, + bit, bit, bit, bit, bit, bit, bit, bit, + bit, bit, bit, bit, bit, bit, bit, bit, + bit, bit, bit, bit, bit, bit, bit, bit, + bit, bit, bit, bit, bit, bit, bit, bit, + bic, bic, bic, bic, bic, bic, bic, bic, + bic, bic, bic, bic, bic, bic, bic, bic, + bic, bic, bic, bic, bic, bic, bic, bic, + bic, bic, bic, bic, bic, bic, bic, bic, + bic, bic, bic, bic, bic, bic, bic, bic, + bic, bic, bic, bic, bic, bic, bic, bic, + bic, bic, bic, bic, bic, bic, bic, bic, + bic, bic, bic, bic, bic, bic, bic, bic, + bis, bis, bis, bis, bis, bis, bis, bis, + bis, bis, bis, bis, bis, bis, bis, bis, + bis, bis, bis, bis, bis, bis, bis, bis, + bis, bis, bis, bis, bis, bis, bis, bis, + bis, bis, bis, bis, bis, bis, bis, bis, + bis, bis, bis, bis, bis, bis, bis, bis, + bis, bis, bis, bis, bis, bis, bis, bis, + bis, bis, bis, bis, bis, bis, bis, bis, + add, add, add, add, add, add, add, add, + add, add, add, add, add, add, add, add, + add, add, add, add, add, add, add, add, + add, add, add, add, add, add, add, add, + add, add, add, add, add, add, add, add, + add, add, add, add, add, add, add, add, + add, add, add, add, add, add, add, add, + add, add, add, add, add, add, add, add, + mul, mul, mul, mul, mul, mul, mul, mul, + divide, divide, divide, divide, divide, divide, divide, divide, + ash, ash, ash, ash, ash, ash, ash, ash, + ashc, ashc, ashc, ashc, ashc, ashc, ashc, ashc, + xor, xor, xor, xor, xor, xor, xor, xor, + illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal, + illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal, + sob, sob, sob, sob, sob, sob, sob, sob, + bpl, bpl, bpl, bpl, bmi, bmi, bmi, bmi, + bhi, bhi, bhi, bhi, blos, blos, blos, blos, + bvc, bvc, bvc, bvc, bvs, bvs, bvs, bvs, + bcc, bcc, bcc, bcc, bcs, bcs, bcs, bcs, + + /* emt at itab[544] to itab[547] */ + /* trap at itab[548] to itab[551] */ + + emt, emt, emt, emt, trap, trap, trap, trap, + clrb, comb, incb, decb, negb, adcb, sbcb, tstb, + rorb, rolb, asrb, aslb, mtps, mfpd, mtpd, mfps, + illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal, + movb, movb, movb, movb, movb, movb, movb, movb, + movb, movb, movb, movb, movb, movb, movb, movb, + movb, movb, movb, movb, movb, movb, movb, movb, + movb, movb, movb, movb, movb, movb, movb, movb, + movb, movb, movb, movb, movb, movb, movb, movb, + movb, movb, movb, movb, movb, movb, movb, movb, + movb, movb, movb, movb, movb, movb, movb, movb, + movb, movb, movb, movb, movb, movb, movb, movb, + cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, + cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, + cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, + cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, + cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, + cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, + cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, + cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, + bitb, bitb, bitb, bitb, bitb, bitb, bitb, bitb, + bitb, bitb, bitb, bitb, bitb, bitb, bitb, bitb, + bitb, bitb, bitb, bitb, bitb, bitb, bitb, bitb, + bitb, bitb, bitb, bitb, bitb, bitb, bitb, bitb, + bitb, bitb, bitb, bitb, bitb, bitb, bitb, bitb, + bitb, bitb, bitb, bitb, bitb, bitb, bitb, bitb, + bitb, bitb, bitb, bitb, bitb, bitb, bitb, bitb, + bitb, bitb, bitb, bitb, bitb, bitb, bitb, bitb, + bicb, bicb, bicb, bicb, bicb, bicb, bicb, bicb, + bicb, bicb, bicb, bicb, bicb, bicb, bicb, bicb, + bicb, bicb, bicb, bicb, bicb, bicb, bicb, bicb, + bicb, bicb, bicb, bicb, bicb, bicb, bicb, bicb, + bicb, bicb, bicb, bicb, bicb, bicb, bicb, bicb, + bicb, bicb, bicb, bicb, bicb, bicb, bicb, bicb, + bicb, bicb, bicb, bicb, bicb, bicb, bicb, bicb, + bicb, bicb, bicb, bicb, bicb, bicb, bicb, bicb, + bisb, bisb, bisb, bisb, bisb, bisb, bisb, bisb, + bisb, bisb, bisb, bisb, bisb, bisb, bisb, bisb, + bisb, bisb, bisb, bisb, bisb, bisb, bisb, bisb, + bisb, bisb, bisb, bisb, bisb, bisb, bisb, bisb, + bisb, bisb, bisb, bisb, bisb, bisb, bisb, bisb, + bisb, bisb, bisb, bisb, bisb, bisb, bisb, bisb, + bisb, bisb, bisb, bisb, bisb, bisb, bisb, bisb, + bisb, bisb, bisb, bisb, bisb, bisb, bisb, bisb, + sub, sub, sub, sub, sub, sub, sub, sub, + sub, sub, sub, sub, sub, sub, sub, sub, + sub, sub, sub, sub, sub, sub, sub, sub, + sub, sub, sub, sub, sub, sub, sub, sub, + sub, sub, sub, sub, sub, sub, sub, sub, + sub, sub, sub, sub, sub, sub, sub, sub, + sub, sub, sub, sub, sub, sub, sub, sub, + sub, sub, sub, sub, sub, sub, sub, sub, + fpset, ldfps, stfps, stst, clrf, tstf, absf, negf, + mulf, mulf, mulf, mulf, moddf, moddf, moddf, moddf, + addf, addf, addf, addf, ldf, ldf, ldf, ldf, + subf, subf, subf, subf, cmpf, cmpf, cmpf, cmpf, + stf, stf, stf, stf, divf, divf, divf, divf, + stexp, stexp, stexp, stexp, stcfi, stcfi, stcfi, stcfi, + stcdf, stcdf, stcdf, stcdf, ldexpp, ldexpp, ldexpp, ldexpp, + lcdif, lcdif, lcdif, lcdif, ldcdf, ldcdf, ldcdf, ldcdf +}; diff --git a/tools/apout/ke11a.c b/tools/apout/ke11a.c new file mode 100644 index 0000000..d1db07e --- /dev/null +++ b/tools/apout/ke11a.c @@ -0,0 +1,230 @@ +/* ke11a.c - this holds the emulation of the PDP 11/20 extended + * arithmetic element. We only need this for 1st Edition a.out support. + * Code kindly borrowed from the eae support written by Tim Shoppa + * (shoppa@trailing-edge.com) for Bob Supnik's PDP-11 emulator. + * + * $Revision: 1.7 $ + * $Date: 1999/12/28 03:57:31 $ + */ +#ifdef EMUV1 +#include "defines.h" +#include + +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<>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 */ diff --git a/tools/apout/magic.c b/tools/apout/magic.c new file mode 100644 index 0000000..4a9e59b --- /dev/null +++ b/tools/apout/magic.c @@ -0,0 +1,134 @@ +/* magic.c - determine the environment for certain PDP-11 a.out binaries + * + * Some binaries in V1, V2, V5, V6, V7 and 2.11BSD are not caught with the + * magic numbers in aout.c. If this is the case, we fall into the + * special_magic() function, which calculates a checksum on the + * a.out header. If it matches any of the checksums below, it returns + * the appropriate environment value. Otherwise, it returns IS_UNKNOWN. + * + * $Revision: 1.13 $ + * $Date: 2000/01/10 01:31:48 $ + */ +#include "defines.h" + +struct spec_aout { + u_int32_t cksum; + int environment; +}; + +static struct spec_aout S[]= { + { 0x1042c2, IS_V6 }, /* V6 bin/dc */ + { 0x10f02, IS_V5 }, /* V5 etc/update */ + { 0x11002, IS_V5 }, /* V5 bin/clri */ + { 0x1117c2, IS_V7 }, /* V7 bin/roff */ + { 0x11702, IS_V6 }, /* V6 etc/update */ + { 0x11a82, IS_V5 }, /* V5 bin/sum */ + { 0x1319c2, IS_V5 }, /* V5 usr/fort/fc1 */ + { 0x1332c2, IS_V2 }, /* /lib/c0 dated Jun 30 1973 from s2 tape */ + { 0x13642, IS_V5 }, /* V5 bin/rew */ + { 0x139e02, IS_V5 }, /* V5 bin/dc */ + { 0x13c0, IS_V6 }, /* V6 usr/lib/tmgc */ + { 0x14042, IS_V6 }, /* V6 bin/tty */ + { 0x143c2, IS_V5 }, /* V5 bin/tty */ + { 0x152ac2, IS_V6 }, /* V6 usr/lib/tmg */ + { 0x15f42, IS_V5 }, /* V5 bin/kill */ + { 0x16802, IS_V5 }, /* V5 bin/dsw */ + { 0x16902, IS_V5 }, /* V5 bin/mkdir */ + { 0x1720c2, IS_V6 }, /* V6 bin/cdb */ + { 0x17742, IS_V5 }, /* V5 usr/bin/pfe */ + { 0x17cc2, IS_V5 }, /* V5 usr/bin/mesg */ + { 0x18702, IS_V5 }, /* V5 bin/rmdir */ + { 0x194c2, IS_V6 }, /* V6 bin/chgrp */ + { 0x197c2, IS_V6 }, /* V6 bin/chown */ + { 0x19a42, IS_V5 }, /* V5 bin/chown */ + { 0x19b342, IS_V6 }, /* V6 usr/bin/nroff */ + { 0x19f682, IS_V6 }, /* V6 usr/fort/fc1 */ + { 0x1b102, IS_V5 }, /* V5 bin/strip */ + { 0x1ba02, IS_V6 }, /* V6 bin/strip */ + { 0x1c342, IS_V5 }, /* V5 bin/cat */ + { 0x1c8442, IS_V7 }, /* V7 usr/games/maze */ + { 0x1cc782, IS_V6 }, /* V6 lib/fc0 */ + { 0x1dfc2, IS_V5 }, /* V5 etc/getty */ + { 0x1f9c2, IS_V2 }, /* /bin/nm dated Jun 30 1973 from s2 tape */ + { 0x20202, IS_V5 }, /* V5 usr/games/bj */ + { 0x21e42, IS_V6 }, /* V6 usr/bin/units */ + { 0x23f82, IS_V5 }, /* V5 usr/bin/passwd */ + { 0x260642, IS_V6 }, /* V6 lib/fc1 */ + { 0x262a82, IS_211BSD }, /* 2.11 usr/new/m11 */ + { 0x27e82, IS_V5 }, /* V5 usr/bin/grep */ + { 0x290c2, IS_V7 }, /* V7 usr/games/cubic */ + { 0x299c2, IS_V5 }, /* V5 usr/games/cubic */ + { 0x2f482, IS_V5 }, /* V5 usr/bin/form */ + { 0x3382, IS_V6 }, /* V6 bin/write */ + { 0x326642, IS_V7 }, /* 2.9 awk */ + { 0x33c42, IS_211BSD }, /* 2.11 usr/games/moo */ + { 0x351382, IS_211BSD }, /* 2.11 usr/games/lib/zork */ + { 0x3702, IS_V5 }, /* V5 usr/games/moo */ + { 0x3b402, IS_V5 }, /* V5 bin/ar */ + { 0x3cc02, IS_V2 }, /* /bin/size from from s2 tape */ + { 0x4382, IS_V5 }, /* V5 bin/write */ + { 0x451f42, IS_V7 }, /* 2.9 /lib/c1 */ + { 0x47042, IS_211BSD }, /* 2.11 usr/games/ttt */ + { 0x4fa02, IS_V5 }, /* V5 bin/ld */ + { 0x51342, IS_211BSD }, /* 2.11 usr/games/bj */ + { 0x53302, IS_V6 }, /* V6 usr/lib/suftab */ + { 0x55882, IS_V7 }, /* 2.9 /bin/as */ + { 0x54702, IS_V5 }, /* V5 usr/games/ttt */ + { 0x55702, IS_V7 }, /* V7 bin/as */ + { 0x5c342, IS_V2 }, /* /bin/cc dated Jun 30 1973 from s2 tape */ + { 0x6f742, IS_V6 }, /* V6 usr/bin/sa */ + { 0x7042, IS_V7 }, /* V7 bin/factor */ + { 0x71702, IS_V7 }, /* V7 lib/as2 */ + { 0x7342, IS_V5 }, /* V5 bin/du */ + { 0x73782, IS_V7}, /* 2.9 /lib/as2 */ + { 0x73e00, IS_V2 }, /* /bin/ld from s2 tape */ + { 0x7a242, IS_V6 }, /* V6 lib/as2 */ + { 0x7b102, IS_V6 }, /* V6 bin/as */ + { 0x7d082, IS_V5 }, /* V5 bin/as */ + { 0x7d6844, IS_V1 }, /* bin/cal from s2 tape */ + { 0x7d942, IS_V5 }, /* V5 lib/as2 */ + { 0x8002, IS_V5 }, /* V5 etc/lpd */ + { 0x85842, IS_V5 }, /* V5 bin/ed */ + { 0x8f00, IS_V6 }, /* V6 usr/lib/tmga */ + { 0x915c2, IS_V6 }, /* V6 bin/bas */ + { 0x94542, IS_V5 }, /* V5 bin/db */ + { 0x98442, IS_V6 }, /* V6 usr/bin/ac */ + { 0x9adc2, IS_V6 }, /* V6 bin/db */ + { 0xa242, IS_V7 }, /* V7 bin/primes */ + { 0xa4602, IS_V2 }, /* /bin/as from s2 tape */ + { 0xa702, IS_V5 }, /* V5 bin/time */ + { 0xad882, IS_V7 }, /* V7 bin/bas */ + { 0xadc42, IS_V2 }, /* /usr/lib/c1 from s2 tape */ + { 0xb5a82, IS_V6 }, /* V6 usr/bin/prof */ + { 0xc1e42, IS_V5 }, /* V5 usr/bin/fed */ + { 0xc3102, IS_V6 }, /* V6 bin/tp */ + { 0xc8bc2, IS_V5 }, /* V5 bin/tp */ + { 0xe1642, IS_V6 }, /* V6 usr/bin/roff */ + { 0xe1f42, IS_V5 }, /* V5 usr/bin/roff */ + { 0xec582, IS_V5 }, /* V5 bin/bas */ + { 0xfc2, IS_V6 }, /* V6 usr/bin/typo */ + { 0xfc002, IS_V2 }, /* /bin/as dated Jun 30 1973 from s2 tape */ + { 0x38ec0, IS_V5 }, /* V5 bin/ar, Warrens */ + { 0, 0 } +}; + +/* cptr points at the start of the a.out header */ +int special_magic(u_int16_t *cptr) +{ + u_int32_t cksum=0; + int i; + + if (cptr==NULL) return(IS_UNKNOWN); + /* Calculate the checksum */ + for (i=0;i<8; i++) { cksum ^= cptr[i]; cksum = cksum<<1; } + + /* Try and find a match */ + for (i=0; S[i].cksum!=0; i++) if (S[i].cksum==cksum) { + TrapDebug((dbg_file, "This a.out has special magic %d\n",i)); + return(S[i].environment); + } + + /* None, return 0 */ + (void)printf("Apout - unknown magic in header: 0x%x\n",cksum); + return(IS_UNKNOWN); +} diff --git a/tools/apout/main.c b/tools/apout/main.c new file mode 100644 index 0000000..cd52f6e --- /dev/null +++ b/tools/apout/main.c @@ -0,0 +1,132 @@ +/* Startup for apout. Parse arguments, load the binary, and run it. + * + * $Revision: 1.22 $ + * $Date: 2002/06/10 11:44:21 $ + */ +#include +#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; i2 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]); +} diff --git a/tools/apout/single.c b/tools/apout/single.c new file mode 100644 index 0000000..de7e334 --- /dev/null +++ b/tools/apout/single.c @@ -0,0 +1,528 @@ +/* single.c - Single operand instructions. + * + * $Revision: 2.10 $ + * $Date: 1999/01/05 23:46:04 $ + */ +#include "defines.h" + +/* adc() - Add Carry Instruction. */ +void +adc() +{ + load_dst(); + + if (CC_C) { /* do if carry is set */ + if (dstword == MPI) + SET_CC_V(); + else + CLR_CC_V(); + if (dstword == NEG_1) + SET_CC_C(); + else + CLR_CC_C(); + dstword++; /* add the carry */ + } else { + CLR_CC_V(); + CLR_CC_C(); + } + + CHG_CC_N(dstword); + CHG_CC_Z(dstword); + + store_dst_2(); +} + + +/* asl() - Arithmetic Shift Left Instruction. */ +void +asl() +{ + load_dst(); + + if (dstword & SIGN) + SET_CC_C(); + else + CLR_CC_C(); + + dstword <<= 1; + + CHG_CC_N(dstword); + CHG_CC_Z(dstword); + CHG_CC_V_XOR_C_N(); + + store_dst_2(); +} + +/* asr() - Arithmetic Shift Right Instruction. */ +void +asr() +{ + load_dst(); + + if (dstword & LSBIT) + SET_CC_C(); + else + CLR_CC_C(); + + dstword = (dstword >> 1) + (dstword & SIGN); /* shift and replicate */ + + CHG_CC_N(dstword); + CHG_CC_Z(dstword); + + CHG_CC_V_XOR_C_N(); + + store_dst_2(); +} + +/* clr() - Clear Instruction. */ +void +clr() +{ + CLR_CC_ALL(); SET_CC_Z(); + dstword=0; store_dst(); +} + +/* com() - Complement Instruction. */ +void +com() +{ + load_dst(); + + dstword = ~dstword; + + CHG_CC_N(dstword); + CHG_CC_Z(dstword); + CLR_CC_V(); + SET_CC_C(); + + store_dst_2(); +} + +/* dec() - Decrement Instruction. */ +void +dec() +{ + load_dst(); + + if (dstword == MNI) + SET_CC_V(); + else + CLR_CC_V(); + + --dstword; + + CHG_CC_N(dstword); + CHG_CC_Z(dstword); + + store_dst_2(); +} + +/* inc() - Increment Instruction. */ +void +inc() +{ + load_dst(); + + if (dstword == MPI) + SET_CC_V(); + else + CLR_CC_V(); + + ++dstword; + + CHG_CC_N(dstword); + CHG_CC_Z(dstword); + + store_dst_2(); +} + +/* neg() - Negate Instruction. */ + +void +neg() +{ + load_dst(); + + dstword = (NEG_1 - dstword) + 1; + + CHG_CC_N(dstword); + CHG_CC_Z(dstword); + + if (dstword == MNI) + SET_CC_V(); + else + CLR_CC_V(); + + if (dstword == 0) + CLR_CC_C(); + else + SET_CC_C(); + + store_dst_2(); +} + +/* rol() - Rotate Left Instruction. */ +void +rol() +{ + load_dst(); + + tmpword = dstword & SIGN; /* get sign bit */ + dstword <<= 1; /* shift */ + + if (CC_C) /* roll in carry */ + dstword += LSBIT; + + if (tmpword) /* roll out to carry */ + SET_CC_C(); + else + CLR_CC_C(); + + CHG_CC_N(dstword); + CHG_CC_Z(dstword); + CHG_CC_V_XOR_C_N(); + + store_dst_2(); +} + + +/* ror() - Rotate Right Instruction. */ +void +ror() +{ + load_dst(); + + tmpword = dstword & LSBIT; /* get low bit */ + dstword >>= 1; /* shift */ + + if (CC_C) /* roll in carry */ + dstword += SIGN; + + if (tmpword) /* roll out to carry */ + SET_CC_C(); + else + CLR_CC_C(); + + CHG_CC_N(dstword); + CHG_CC_Z(dstword); + CHG_CC_V_XOR_C_N(); + + store_dst_2(); +} + +/* sbc() - Subtract Carry Instruction. */ +void +sbc() +{ + load_dst(); + + if (dstword == MNI) + SET_CC_V(); + else + CLR_CC_V(); + + if (CC_C) { /* do if carry is set */ + if (dstword) + CLR_CC_C(); + else + SET_CC_C(); + --dstword; /* subtract carry */ + } else { + CLR_CC_C(); + } + + CHG_CC_N(dstword); + CHG_CC_Z(dstword); + + store_dst_2(); +} + +/* swabi() - Swap Bytes Instruction. */ +void +swabi() +{ + u_int16_t data2; + u_int16_t data3; + + load_dst(); + + data2 = (dstword << 8) & 0xff00; + data3 = (dstword >> 8) & 0x00ff; + dstword = data2 + data3; + + CLR_CC_ALL(); + CHGB_CC_N(data3); /* cool, negative and zero */ + CHGB_CC_Z(data3); /* checks done on low byte only */ + + store_dst_2(); +} + +/* sxt() - Sign Extend Instruction. */ +void +sxt() +{ + if (CC_N) { + dstword = NEG_1; + CLR_CC_Z(); + } else { + dstword = 0; + SET_CC_Z(); + } + CLR_CC_V(); + + store_dst(); +} + +/* tst() - Test Instruction. */ +void +tst() +{ + load_dst(); + + CLR_CC_ALL(); + CHG_CC_N(dstword); + CHG_CC_Z(dstword); +} + +/* tstb() - Test Byte Instruction. */ +void +tstb() +{ + loadb_dst(); + + CHGB_CC_N(dstbyte); + CHGB_CC_Z(dstbyte); + CLR_CC_V(); + CLR_CC_C(); + +} + +/* aslb() - Arithmetic Shift Left Byte Instruction. */ +void +aslb() +{ + loadb_dst(); + + if (dstbyte & SIGN_B) + SET_CC_C(); + else + CLR_CC_C(); + + dstbyte <<= 1; + + CHGB_CC_N(dstbyte); + CHGB_CC_Z(dstbyte); + CHG_CC_V_XOR_C_N(); + + storeb_dst_2(); +} + +/* asrb() - Arithmetic Shift Right Byte Instruction. */ +void +asrb() +{ + loadb_dst(); + + if (dstbyte & LSBIT) + SET_CC_C(); + else + CLR_CC_C(); + + dstbyte = (dstbyte >> 1) + (dstbyte & SIGN_B); /* shift and replicate */ + + CHGB_CC_N(dstbyte); + CHGB_CC_Z(dstbyte); + CHG_CC_V_XOR_C_N(); + + storeb_dst_2(); +} + +/* clrb() - Clear Byte Instruction. */ +void +clrb() +{ + CLR_CC_ALL(); SET_CC_Z(); + srcbyte=0; storeb_dst(); +} + + +/* comb() - Complement Byte Instruction. */ +void +comb() +{ + loadb_dst(); + + dstbyte = ~dstbyte; + + CHGB_CC_N(dstbyte); + CHGB_CC_Z(dstbyte); + CLR_CC_V(); + SET_CC_C(); + + storeb_dst_2(); +} + +/* decb() - Decrement Byte Instruction. */ +void +decb() +{ + loadb_dst(); + + if (dstbyte == MNI_B) + SET_CC_V(); + else + CLR_CC_V(); + + --dstbyte; + + CHGB_CC_N(dstbyte); + CHGB_CC_Z(dstbyte); + + storeb_dst_2(); +} + +/* incb() - Increment Byte Instruction. */ +void +incb() +{ + loadb_dst(); + + if (dstbyte == MPI_B) + SET_CC_V(); + else + CLR_CC_V(); + + ++dstbyte; + + CHGB_CC_N(dstbyte); + CHGB_CC_Z(dstbyte); + + storeb_dst_2(); +} + +/* negb() - Negate Byte Instruction. */ +void +negb() +{ + loadb_dst(); + + dstbyte = (NEG_1_B - dstbyte) + 1;/* hope this is right */ + + CHGB_CC_N(dstbyte); + CHGB_CC_Z(dstbyte); + + if (dstbyte == MNI_B) + SET_CC_V(); + else + CLR_CC_V(); + + if (dstbyte) + SET_CC_C(); + else + CLR_CC_C(); + + storeb_dst_2(); +} + +/* rolb() - Rotate Left Byte Instruction. */ +void +rolb() +{ + loadb_dst(); + + tmpbyte = dstbyte & SIGN_B; /* get top bit */ + dstbyte <<= 1; /* shift */ + + if (CC_C) /* roll in carry */ + dstbyte = dstbyte + LSBIT; + + if (tmpbyte) /* roll out to carry */ + SET_CC_C(); + else + CLR_CC_C(); + + CHGB_CC_N(dstbyte); + CHGB_CC_Z(dstbyte); + CHG_CC_V_XOR_C_N(); + + storeb_dst_2(); +} + +/* rorb() - Rotate Right Byte Instruction. */ +void +rorb() +{ + loadb_dst(); + + tmpbyte = dstbyte & LSBIT; /* get low bit */ + dstbyte >>= 1; /* shift */ + + if (CC_C) /* roll in carry */ + dstbyte += SIGN_B; + + if (tmpbyte) /* roll out to carry */ + SET_CC_C(); + else + CLR_CC_C(); + + CHGB_CC_N(dstbyte); + CHGB_CC_Z(dstbyte); + CHG_CC_V_XOR_C_N(); + + storeb_dst_2(); +} + +/* adcb() - Add Carry Byte Instruction. */ +void +adcb() +{ + loadb_dst(); + + if (CC_C) { /* do if carry is set */ + if (dstbyte == MPI_B) + SET_CC_V(); + else + CLR_CC_V(); + if (dstbyte == NEG_1_B) + SET_CC_C(); + else + CLR_CC_C(); + ++dstbyte; /* add the carry */ + } else { + CLR_CC_V(); + CLR_CC_C(); + } + + CHGB_CC_N(dstbyte); + CHGB_CC_Z(dstbyte); + + storeb_dst_2(); +} + +/* sbcb() - Subtract Carry Byte Instruction. */ +void +sbcb() +{ + loadb_dst(); + + if (CC_C) { /* do if carry is set */ + if (dstbyte) + CLR_CC_C(); + else + SET_CC_C(); + + --dstbyte; /* subtract carry */ + } else { + CLR_CC_C(); + } + + if (dstbyte == MNI_B) + SET_CC_V(); + else + CLR_CC_V(); + + CHGB_CC_N(dstbyte); + CHGB_CC_Z(dstbyte); + + storeb_dst_2(); +} diff --git a/tools/apout/v1trap.c b/tools/apout/v1trap.c new file mode 100644 index 0000000..a726f66 --- /dev/null +++ b/tools/apout/v1trap.c @@ -0,0 +1,522 @@ +/* v1trap.c - Deal with 1st Edition trap instructions. + * + * $Revision: 1.15 $ + * $Date: 2002/06/10 11:43:24 $ + */ +#ifdef EMUV1 +#include "defines.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 */ diff --git a/tools/apout/v1trap.h b/tools/apout/v1trap.h new file mode 100644 index 0000000..717efad --- /dev/null +++ b/tools/apout/v1trap.h @@ -0,0 +1,125 @@ +/* v1trap.h - Deal with 1st Edition trap instructions. + * + * $Revision: 1.1 $ + * $Date: 1999/12/26 08:16:33 $ + */ + +/* In this file, we list the trap number for each system call, + * and the structures associated with several of the systems + * calls in 1st Edition UNIX + */ + +#define V1_RELE 0 +#define V1_EXIT 1 +#define V1_FORK 2 +#define V1_READ 3 +#define V1_WRITE 4 +#define V1_OPEN 5 +#define V1_CLOSE 6 +#define V1_WAIT 7 +#define V1_CREAT 8 +#define V1_LINK 9 +#define V1_UNLINK 10 +#define V1_EXEC 11 +#define V1_CHDIR 12 +#define V1_TIME 13 +#define V1_MKDIR 14 +#define V1_CHMOD 15 +#define V1_CHOWN 16 +#define V1_BREAK 17 +#define V1_STAT 18 +#define V1_SEEK 19 +#define V1_TELL 20 +#define V1_MOUNT 21 +#define V1_UMOUNT 22 +#define V1_SETUID 23 +#define V1_GETUID 24 +#define V1_STIME 25 +#define V1_QUIT 26 +#define V1_INTR 27 +#define V1_FSTAT 28 +#define V1_CEMT 29 +#define V1_SMDATE 30 +#define V1_STTY 31 +#define V1_GTTY 32 +#define V1_ILGINS 33 + + +char *v1trap_name[]= { + "rele", + "exit", + "fork", + "read", + "write", + "open", + "close", + "wait", + "creat", + "link", + "unlink", + "exec", + "chdir", + "time", + "mkdir", + "chmod", + "chown", + "break", + "stat", + "seek", + "tell", + "mount", + "umount", + "setuid", + "getuid", + "stime", + "quit", + "intr", + "fstat", + "cemt", + "smdate", + "stty", + "gtty", + "ilgins" +}; + + +struct tr_v1stat { + u_int16_t inum; + u_int16_t iflags; /* Mode */ + u_int8_t inl; /* Links */ + u_int8_t iuid; + u_int16_t isize; + int16_t iaddr[8]; /* Not used, I hope! */ + u_int32_t ctime; + u_int32_t mtime; + u_int16_t unused; +}; + +/* Values for v1stat iflags */ +#define V1_ST_USED 0100000 +#define V1_ST_ISDIR 0040000 +#define V1_ST_MODIFIED 0020000 +#define V1_ST_LARGE 0010000 +#define V1_ST_SETUID 0000040 +#define V1_ST_EXEC 0000020 +#define V1_ST_OWNREAD 0000010 +#define V1_ST_OWNWRITE 0000004 +#define V1_ST_WRLDREAD 0000002 +#define V1_ST_WRLDWRITE 0000001 + +/* A union which will point at the trap args, so that + * we can get at the various args of different types + */ +typedef union { + int16_t sarg[4]; /* Signed 16-bit args */ + u_int16_t uarg[4]; /* Unsigned 16-bit args */ +} arglist; + +#define sarg1 V1A.sarg[0] +#define sarg2 V1A.sarg[1] +#define sarg3 V1A.sarg[2] +#define sarg4 V1A.sarg[3] +#define uarg1 V1A.uarg[0] +#define uarg2 V1A.uarg[1] +#define uarg3 V1A.uarg[2] +#define uarg4 V1A.uarg[3] diff --git a/tools/apout/v7trap.c b/tools/apout/v7trap.c new file mode 100644 index 0000000..0ea142f --- /dev/null +++ b/tools/apout/v7trap.c @@ -0,0 +1,709 @@ +/* v7trap.c - Deal with V7 trap instructions. V5 and V6 syscalls are also + * done here, because the syscall interface is nearly the same as V7. + * + * $Revision: 1.47 $ + * $Date: 2002/06/10 11:43:24 $ + */ +#include "defines.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 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= 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); +} diff --git a/tools/apout/v7trap.h b/tools/apout/v7trap.h new file mode 100644 index 0000000..f8314b9 --- /dev/null +++ b/tools/apout/v7trap.h @@ -0,0 +1,229 @@ +/* v7trap.h - Deal with V7 trap instructions. Also do V5 and V6 syscalls. + * + * $Revision: 2.17 $ + * $Date: 1999/12/26 08:16:33 $ + */ + +/* In this file, we list the trap number for each system call, + * and the structures associated with several of the systems + * calls in 7th Edition UNIX + */ + +#define S_INDIR 0 +#define S_EXIT 1 +#define S_FORK 2 +#define S_READ 3 +#define S_WRITE 4 +#define S_OPEN 5 +#define S_CLOSE 6 +#define S_WAIT 7 +#define S_CREAT 8 +#define S_LINK 9 +#define S_UNLINK 10 +#define S_EXEC 11 +#define S_CHDIR 12 +#define S_TIME 13 +#define S_MKNOD 14 +#define S_CHMOD 15 +#define S_CHOWN 16 +#define S_BREAK 17 +#define S_STAT 18 +#define S_LSEEK 19 +#define S_GETPID 20 +#define S_MOUNT 21 +#define S_UMOUNT 22 +#define S_SETUID 23 +#define S_GETUID 24 +#define S_STIME 25 +#define S_PTRACE 26 +#define S_ALARM 27 +#define S_FSTAT 28 +#define S_PAUSE 29 +#define S_UTIME 30 +#define S_STTY 31 +#define S_GTTY 32 +#define S_ACCESS 33 +#define S_NICE 34 +#define S_FTIME 35 +#define S_SYNC 36 +#define S_KILL 37 +#define S_DUP 41 +#define S_PIPE 42 +#define S_TIMES 43 +#define S_PROF 44 +#define S_SETGID 46 +#define S_GETGID 47 +#define S_SIGNAL 48 +#define S_ACCT 51 +#define S_PHYS 52 +#define S_LOCK 53 +#define S_IOCTL 54 +#define S_EXECE 59 +#define S_UMASK 60 +#define S_CHROOT 61 + + +char *v7trap_name[]= { + "indir", + "exit", + "fork", + "read", + "write", + "open", + "close", + "wait", + "creat", + "link", + "unlink", + "exec", + "chdir", + "time", + "mknod", + "chmod", + "chown", + "break", + "stat", + "lseek", + "getpid", + "mount", + "umount", + "setuid", + "getuid", + "stime", + "ptrace", + "alarm", + "fstat", + "pause", + "utime", + "stty", + "gtty", + "access", + "nice", + "ftime", + "sync", + "kill", + "unknown", + "unknown", + "unknown", + "dup", + "pipe", + "times", + "prof", + "unknown", + "setgid", + "getgid", + "signal", + "unknown", + "unknown", + "acct", + "phys", + "lock", + "ioctl", + "unknown", + "unknown", + "unknown", + "unknown", + "exece", + "umask", + "chroot" +}; + + +struct tr_v7stat { + int16_t st_dev; + u_int16_t st_ino; + u_int16_t st_mode; + int16_t st_nlink; + int16_t st_uid; + int16_t st_gid; + int16_t st_rdev; + int8_t st_size[4]; /* Alignment problems */ + int8_t st_atim[4]; /* Alignment problems */ + int8_t st_mtim[4]; /* Alignment problems */ + int8_t st_ctim[4]; /* Alignment problems */ +}; + +struct tr_v6stat { + int16_t idev; /* Device */ + int16_t inum; + int16_t iflags; /* Mode */ + int8_t inl; /* Links */ + int8_t iuid; + int8_t igid; + u_int8_t isize0; /* Most significant 8 bits */ + u_int16_t isize; + int16_t iaddr[8]; /* Not used, I hope! */ + u_int32_t atime; /* Alignment problems */ + u_int32_t mtime; /* Alignment problems */ +}; + +struct tr_timeb { + u_int32_t time; + u_int16_t millitm; + int16_t timezone; + int16_t dstflag; +}; + +struct tr_sgttyb { + int8_t sg_ispeed; /* input speed */ + int8_t sg_ospeed; /* output speed */ + int8_t sg_erase; /* erase character */ + int8_t sg_kill; /* kill character */ + int16_t sg_flags; /* mode flags */ +}; + +/* + * Values for sg_flags + */ +#define TR_TANDEM 01 +#define TR_CBREAK 02 +#define TR_LCASE 04 +#define TR_ECHO 010 +#define TR_CRMOD 020 +#define TR_RAW 040 +#define TR_ODDP 0100 +#define TR_EVENP 0200 +#define TR_ANYP 0300 +#define TR_XTABS 06000 + +/* + * Values for signal + */ +#define V7_SIG_DFL 0 +#define V7_SIG_IGN 1 + +#define V7_NSIG 15 + +#define V7_SIGHUP 1 /* hangup */ +#define V7_SIGINT 2 /* interrupt */ +#define V7_SIGQUIT 3 /* quit */ +#define V7_SIGILL 4 /* illegal instruction (not reset when caught) */ +#define V7_SIGTRAP 5 /* trace trap (not reset when caught) */ +#define V7_SIGIOT 6 /* IOT instruction */ +#define V7_SIGEMT 7 /* EMT instruction */ +#define V7_SIGFPE 8 /* floating point exception */ +#define V7_SIGKILL 9 /* kill (cannot be caught or ignored) */ +#define V7_SIGBUS 10 /* bus error */ +#define V7_SIGSEGV 11 /* segmentation violation */ +#define V7_SIGSYS 12 /* bad argument to system call */ +#define V7_SIGPIPE 13 /* write on a pipe with no one to read it */ +#define V7_SIGALRM 14 /* alarm clock */ +#define V7_SIGTERM 15 /* software termination signal from kill */ + + +/* A union which will point at the trap args, so that + * we can get at the various args of different types + */ +typedef union { + int16_t sarg[4]; /* Signed 16-bit args */ + u_int16_t uarg[4]; /* Unsigned 16-bit args */ +} arglist; + +#define sarg1 V7A.sarg[0] +#define sarg2 V7A.sarg[1] +#define sarg3 V7A.sarg[2] +#define sarg4 V7A.sarg[3] +#define uarg1 V7A.uarg[0] +#define uarg2 V7A.uarg[1] +#define uarg3 V7A.uarg[2] +#define uarg4 V7A.uarg[3]