├── .gitignore ├── LCLINT ├── COPYRIGHT ├── aout.h ├── Makefile ├── v1trap.h ├── TODO ├── main.c ├── double.c ├── v7trap.h ├── LIMITATIONS ├── README ├── magic.c ├── CHANGES ├── bsd_signal.c ├── itab.c ├── apout.1 ├── ke11a.c ├── cpu.c ├── branch.c ├── debug.c ├── single.c ├── bsdtrap.h ├── ea.c ├── defines.h ├── fp.c └── v1trap.c /.gitignore: -------------------------------------------------------------------------------- 1 | # Objects 2 | *.o 3 | apout 4 | 5 | # Vim 6 | *.un~ 7 | *.swp 8 | -------------------------------------------------------------------------------- /LCLINT: -------------------------------------------------------------------------------- 1 | aout.c Fri Sep 17 13:00:33 EST 1999 2 | branch.c Fri Sep 17 13:00:33 EST 1999 3 | bsd_ioctl.c Fri Sep 17 13:03:34 EST 1999 4 | bsd_signal.c 5 | bsdtrap.c 6 | cpu.c Fri Sep 17 15:04:05 EST 1999 bits to do 7 | debug.c Fri Sep 17 15:04:01 EST 1999 8 | double.c Fri Sep 17 15:08:46 EST 1999 9 | ea.c Fri Sep 17 15:10:51 EST 1999 10 | fp.c 11 | itab.c Fri Sep 17 13:00:33 EST 1999 12 | ke11a.c 13 | magic.c Fri Sep 17 13:00:33 EST 1999 14 | main.c 15 | single.c 16 | v7trap.c 17 | -------------------------------------------------------------------------------- /COPYRIGHT: -------------------------------------------------------------------------------- 1 | The Apout simulator is copyright Warren Toomey, and is protected by the 2 | following notice. 3 | 4 | /* Apout is a PDP-11 a.out simulator. 5 | * 6 | * For information contact: 7 | * 8 | * Email: wkt@tuhs.org 9 | * FTP: ftp://minnie.tuhs.org/pup/PDP-11/Sims/Apout 10 | * 11 | * Copyright 1995-2002, Warren Toomey 12 | * 13 | * Permission to use, copy, modify, and distribute this software and its 14 | * documentation for any purpose and without fee is hereby granted, provided 15 | * that the above copyright notice appear in all copies. Warren Toomey 16 | * makes no representations about the suitability of this software for any 17 | * purpose. It is provided "as is" without expressed or implied warranty. 18 | */ 19 | 20 | ------ 21 | 22 | The parts of Apout that deal with PDP-11 instruction emulation are derived 23 | from the PDP-11 simulator written by Eric A. Edwards, and are protected by 24 | the following notice. 25 | 26 | /* Parts of Apout are derived from 'pdp', a PDP-11 simulator. 27 | * 28 | * For information contact: 29 | * 30 | * Computer Science House 31 | * Attn: Eric Edwards 32 | * Box 861 33 | * 25 Andrews Memorial Drive 34 | * Rochester, NY 14623 35 | * 36 | * Email: mag@potter.csh.rit.edu 37 | * FTP: ftp.csh.rit.edu:/pub/csh/mag/pdp.tar.Z 38 | * 39 | * Copyright 1994, Eric A. Edwards 40 | * 41 | * Permission to use, copy, modify, and distribute this software and its 42 | * documentation for any purpose and without fee is hereby granted, provided 43 | * that the above copyright notice appear in all copies. Eric A. Edwards 44 | * makes no representations about the suitability of this software for any 45 | * purpose. It is provided "as is" without expressed or implied warranty. 46 | */ 47 | -------------------------------------------------------------------------------- /aout.h: -------------------------------------------------------------------------------- 1 | /* aout.h - parse and load the contents of a UNIX a.out file, for 2 | * several flavours of PDP-11 UNIX 3 | * 4 | * $Revision: 1.5 $ 5 | * $Date: 2008/05/19 13:42:39 $ 6 | */ 7 | #include 8 | #define EIGHT_K 8192 9 | 10 | /* UNIX magic numbers for the a.out header */ 11 | #define V1_NORMAL 0405 /* normal: 1st Edition, six words long */ 12 | #define ANY_NORMAL 0407 /* normal: V5,V6,V7,2.11BSD */ 13 | #define ANY_ROTEXT 0410 /* read-only text: V5,V6,V7,2.11BSD */ 14 | #define ANY_SPLITID 0411 /* seperated I&D: V5,V6,V7,2.11BSD */ 15 | #define BSD_OVERLAY 0430 /* 2.11BSD overlay, non-separate */ 16 | #define BSD_ROVERLAY 0431 /* 2.11BSD overlay, separate */ 17 | #define ANY_SCRIPT 020443 /* Shell script, i.e #! */ 18 | #define A68_MAGIC 0 /* Algol68 binaries have these magic nums */ 19 | #define A68_DATA 0107116 /* Algol68 binaries have these magic nums */ 20 | #define V1_RAW 0104421 /* V1 'raw' binary: rm, ln, chmod from s2 21 | archive. */ 22 | 23 | #define UNKNOWN_AOUT 034567 /* An unknown a.out header */ 24 | 25 | /* a.out header for nearly all UNIX flavours */ 26 | struct exec { 27 | u_int16_t a_magic; /* magic number */ 28 | u_int16_t a_text; /* size of text segment */ 29 | u_int16_t a_data; /* size of initialised data */ 30 | u_int16_t a_bss; /* size of initialised bss */ 31 | u_int16_t a_syms; /* size of symbol table */ 32 | u_int16_t a_entry; /* entry point */ 33 | u_int16_t a_unused; /* unused */ 34 | u_int16_t a_flag; /* relocation info stripped */ 35 | /* 16 bytes up to here */ 36 | 37 | /* 2.11BSD overlay files have the following */ 38 | #define NOVL 15 39 | int16_t max_ovl; /* maximum overlay size */ 40 | u_int16_t ov_siz[NOVL]; /* size of the i'th overlay */ 41 | /* Note that if the file isn't a 2.11BSD */ 42 | /* overlay, we have to rewind to undo */ 43 | /* the read of this section */ 44 | }; 45 | 46 | /* Because V5, V6, V7 and 2.11BSD share several magic numbers 47 | * in their a.out headers, we must distinguish them so as to 48 | * set up the correct emulated environment. This is done by 49 | * observing the differences in their crt0.s code: they all 50 | * differ at position 021 51 | */ 52 | #define a_magic2 ov_siz[0] 53 | #define V2_M2 0177304 /* Doesn't apply to all, tho */ 54 | #define V6_M2 0010600 55 | #define V7_M2 0016600 56 | #define BSD_M2 0162706 57 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Apout PDP-11 application emulator 2 | # 3 | # $Revision: 1.31 $ 4 | # $Date: 2008/05/19 13:42:39 $ 5 | # 6 | # You will need gcc if you choose the optimised compile below 7 | CC?=gcc 8 | 9 | # Set the CFLAGS, LDFLAGS for speed or debugging. If you don't want 2.11BSD 10 | # emulation, then remove the -DEMU211 flag. 11 | # Set up the LIBS if required for your system 12 | # 13 | # These flags for doing debugging 14 | #APOUT_OPTIONS?= -DEMU211 -DEMUV1 -DNATIVES -DRUN_V1_RAW \ 15 | -DDEBUG -DZERO_MEMORY -DWRITEBASE 16 | # These flags should be fine for most cases 17 | APOUT_OPTIONS?= -DEMU211 -DEMUv1 -DNATIVES 18 | 19 | # These flags for speed 20 | #CFLAGS+= -DEMU211 -DNATIVES -DINLINE=inline -O2 -Winline -Wall \ 21 | # -finline-functions -fomit-frame-pointer 22 | #LDFLAGS?= 23 | 24 | # Assemble CFLAGS 25 | CFLAGS?= -O2 -DINLINE=inline -finline-functions -fomit-frame-pointer 26 | CFLAGS+=-Winline -Wunused-result # silence warnings 27 | CFLAGS+= $(APOUT_OPTIONS) 28 | 29 | # Any extra libraries required 30 | LIBS= -lm 31 | 32 | # Install destinations 33 | PREFIX?=/usr/local 34 | MANDIR=$(PREFIX)/man/man1 35 | BINDIR=$(PREFIX)/bin 36 | 37 | VERSION= apout2.3beta1 38 | SRCS= cpu.c aout.c aout.h branch.c double.c ea.c itab.c main.c ke11a.c \ 39 | single.c fp.c v7trap.c bsdtrap.c defines.h v7trap.h debug.c \ 40 | bsdtrap.h bsd_ioctl.c bsd_signal.c magic.c v1trap.c v1trap.h 41 | OBJS= aout.o branch.o bsd_ioctl.o bsd_signal.o bsdtrap.o cpu.o debug.o \ 42 | double.o ea.o fp.o itab.o ke11a.o magic.o main.o single.o v1trap.o \ 43 | v7trap.o 44 | 45 | apout: $(OBJS) 46 | $(CC) $(LDFLAGS) $(OBJS) -o apout $(LIBS) 47 | 48 | install: apout apout.1 49 | cp apout $(BINDIR) 50 | chmod 755 $(BINDIR)/apout 51 | cp apout.1 $(MANDIR) 52 | chmod 644 $(MANDIR)/apout.1 53 | 54 | clean: 55 | rm -rf apout *core $(OBJS) *.dbg $(VERSION) $(VERSION).tar.gz apout.0 56 | 57 | apout.0: apout.1 58 | nroff -man apout.1 > apout.0 59 | 60 | indent: $(SRCS) 61 | astyle --style=kr $(SRCS) 62 | 63 | disttar: clean apout.0 64 | - mkdir $(VERSION) 65 | cp $(SRCS) $(VERSION) 66 | chmod -R go+rX $(VERSION) 67 | chmod -R u+w $(VERSION) 68 | chown -R wkt $(VERSION) 69 | tar vzcf $(VERSION).tar.gz $(VERSION) 70 | 71 | # Dependencies for object files 72 | aout.o: aout.c defines.h aout.h Makefile 73 | branch.o: branch.c defines.h Makefile 74 | bsd_ioctl.o: bsd_ioctl.c defines.h Makefile 75 | bsd_signal.o: bsd_signal.c defines.h bsdtrap.h Makefile 76 | bsdtrap.o: bsdtrap.c bsdtrap.h defines.h Makefile 77 | cpu.o: cpu.c defines.h Makefile 78 | debug.o: debug.c defines.h Makefile 79 | double.o: double.c defines.h Makefile 80 | ea.o: ea.c defines.h Makefile 81 | fp.o: fp.c defines.h Makefile 82 | itab.o: itab.c defines.h Makefile 83 | ke11a.o: ke11a.c defines.h Makefile 84 | magic.o: magic.c defines.h Makefile 85 | main.o: main.c defines.h Makefile 86 | single.o: single.c defines.h Makefile 87 | v1trap.o: v1trap.c v1trap.h defines.h Makefile 88 | v7trap.o: v7trap.c v7trap.h defines.h Makefile 89 | -------------------------------------------------------------------------------- /v1trap.h: -------------------------------------------------------------------------------- 1 | /* v1trap.h - Deal with 1st Edition trap instructions. 2 | * 3 | * $Revision: 1.1 $ 4 | * $Date: 1999/12/26 08:16:33 $ 5 | */ 6 | 7 | /* In this file, we list the trap number for each system call, 8 | * and the structures associated with several of the systems 9 | * calls in 1st Edition UNIX 10 | */ 11 | 12 | #define V1_RELE 0 13 | #define V1_EXIT 1 14 | #define V1_FORK 2 15 | #define V1_READ 3 16 | #define V1_WRITE 4 17 | #define V1_OPEN 5 18 | #define V1_CLOSE 6 19 | #define V1_WAIT 7 20 | #define V1_CREAT 8 21 | #define V1_LINK 9 22 | #define V1_UNLINK 10 23 | #define V1_EXEC 11 24 | #define V1_CHDIR 12 25 | #define V1_TIME 13 26 | #define V1_MKDIR 14 27 | #define V1_CHMOD 15 28 | #define V1_CHOWN 16 29 | #define V1_BREAK 17 30 | #define V1_STAT 18 31 | #define V1_SEEK 19 32 | #define V1_TELL 20 33 | #define V1_MOUNT 21 34 | #define V1_UMOUNT 22 35 | #define V1_SETUID 23 36 | #define V1_GETUID 24 37 | #define V1_STIME 25 38 | #define V1_QUIT 26 39 | #define V1_INTR 27 40 | #define V1_FSTAT 28 41 | #define V1_CEMT 29 42 | #define V1_SMDATE 30 43 | #define V1_STTY 31 44 | #define V1_GTTY 32 45 | #define V1_ILGINS 33 46 | 47 | 48 | char *v1trap_name[] = { 49 | "rele", 50 | "exit", 51 | "fork", 52 | "read", 53 | "write", 54 | "open", 55 | "close", 56 | "wait", 57 | "creat", 58 | "link", 59 | "unlink", 60 | "exec", 61 | "chdir", 62 | "time", 63 | "mkdir", 64 | "chmod", 65 | "chown", 66 | "break", 67 | "stat", 68 | "seek", 69 | "tell", 70 | "mount", 71 | "umount", 72 | "setuid", 73 | "getuid", 74 | "stime", 75 | "quit", 76 | "intr", 77 | "fstat", 78 | "cemt", 79 | "smdate", 80 | "stty", 81 | "gtty", 82 | "ilgins" 83 | }; 84 | 85 | 86 | struct tr_v1stat { 87 | u_int16_t inum; 88 | u_int16_t iflags; /* Mode */ 89 | u_int8_t inl; /* Links */ 90 | u_int8_t iuid; 91 | u_int16_t isize; 92 | int16_t iaddr[8]; /* Not used, I hope! */ 93 | u_int32_t ctime; 94 | u_int32_t mtime; 95 | u_int16_t unused; 96 | }; 97 | 98 | /* Values for v1stat iflags */ 99 | #define V1_ST_USED 0100000 100 | #define V1_ST_ISDIR 0040000 101 | #define V1_ST_MODIFIED 0020000 102 | #define V1_ST_LARGE 0010000 103 | #define V1_ST_SETUID 0000040 104 | #define V1_ST_EXEC 0000020 105 | #define V1_ST_OWNREAD 0000010 106 | #define V1_ST_OWNWRITE 0000004 107 | #define V1_ST_WRLDREAD 0000002 108 | #define V1_ST_WRLDWRITE 0000001 109 | 110 | /* A union which will point at the trap args, so that 111 | * we can get at the various args of different types 112 | */ 113 | typedef union { 114 | int16_t sarg[4]; /* Signed 16-bit args */ 115 | u_int16_t uarg[4]; /* Unsigned 16-bit args */ 116 | } arglist; 117 | 118 | #define sarg1 V1A.sarg[0] 119 | #define sarg2 V1A.sarg[1] 120 | #define sarg3 V1A.sarg[2] 121 | #define sarg4 V1A.sarg[3] 122 | #define uarg1 V1A.uarg[0] 123 | #define uarg2 V1A.uarg[1] 124 | #define uarg3 V1A.uarg[2] 125 | #define uarg4 V1A.uarg[3] 126 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | Things to do in the Apout Emulator 2 | ---------------------------------- 3 | 4 | Ensure stream buffering works! 5 | 6 | Do some decent testing and code reading to make me happier. 7 | 8 | Speed Apout up 9 | 10 | The biggest bottlenecks are the effective address calculations 11 | in ea.c. After compiling 2.11BSD /sys/GENERIC kernel with a 12 | gprof'd apout, we get: 13 | 14 | % cumulative self self total 15 | time seconds seconds calls ms/call ms/call name 16 | 64.9 3.64 3.64 .mcount (123) 17 | 6.1 3.99 0.34 1609635 0.00 0.00 load_src [5] 18 | 5.6 4.30 0.31 1665976 0.00 0.00 mov [4] 19 | 5.3 4.60 0.30 2 148.44 959.47 run [3] 20 | 3.4 4.79 0.19 1238127 0.00 0.00 load_dst [7] 21 | 2.2 4.91 0.12 602275 0.00 0.00 store_dst [10] 22 | 1.3 4.98 0.08 374121 0.00 0.00 loadb_src [12] 23 | 1.3 5.05 0.07 672481 0.00 0.00 store_dst_2 [13] 24 | 1.2 5.12 0.07 365911 0.00 0.00 cmp [6] 25 | 1.1 5.18 0.06 323386 0.00 0.00 movb [8] 26 | 1.1 5.24 0.06 515335 0.00 0.00 bne [15] 27 | 28 | Everything else is below 1%. It doesn't look like there is 29 | much room for improvement, maybe 10% worth? 30 | 31 | We could go to having 65,536 separate functions, one for 32 | each possible instruction. That would mean a large reorganisation 33 | of the source, and would result in a significantly larger 34 | binary for apout. 35 | 36 | I've broken open some of the mov() functions which has improved 37 | things a few percent. I did expand itab[] to 64K entries, but 38 | the improvement was negligible. However, I should come back & 39 | revisit this sometime. 40 | 41 | Would it be worth adding STREAM_BUFFERING into bsdtrap.c? Possibly. 42 | After a GENERIC kernel compile, I found that reads averaged 580 43 | chars/read, writes averaged 115 chars/write. However, after getting 44 | buffering to work in bsdtrap.c, I found that it actually slowed down 45 | the GENERIC kernel compile, so I've left the code in but disabled it. 46 | 47 | Finish off 2.11BSD emulation 48 | 49 | Finish off all the missing syscalls. This means I will have to 50 | learn how the new signal stuff actually works. Emulating signals 51 | is going to be really interesting, I can see! 52 | 53 | Enumerate and write all of the ioctls: yucko. That means all of 54 | the terminal stuff, blah! 55 | 56 | Fix up the floating-point 57 | 58 | If the UNIX binaries never use the FP error handling, then don't 59 | bother to implement it. We should, however, implement doubles. 60 | We should spend some time to ensure that the FP operations are 61 | accurate, both in terms of FP accuracy, and in giving results 62 | as if they were on a real PDP-11. 63 | 64 | Make it work on big-endian machines 65 | 66 | This would cause a lot of heartache in the code. It's not that 67 | pretty now, but can you imagine the #ifdefs once big-endian 68 | support is added? I guess some well-written macros could help. 69 | 70 | Tidy up the code 71 | 72 | In particular, aout.c is a mess. Should be more modular. 73 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* Startup for apout. Parse arguments, load the binary, and run it. 2 | * 3 | * $Revision: 1.23 $ 4 | * $Date: Mon 31 Oct 2016 03:46:15 AM CET $ 5 | */ 6 | #include 7 | #include "defines.h" 8 | 9 | /* The following array holds the FILE pointers that correspond to open file 10 | * descriptors. Only fds which are not ttys have FILE * pointers 11 | */ 12 | FILE *stream[NFILE]; 13 | char *streammode[NFILE]; /* Mode for each file - used for dup */ 14 | 15 | /* The following two buffers are used as */ 16 | /* part of the translation from virtal */ 17 | /* absolute filenames to native ones. We */ 18 | /* only have 2 buffers, so if you call */ 19 | /* xlate_filename() 3 times, the 1st return */ 20 | /* value will be destroyed. */ 21 | static char realfilename[2][2 * MAXPATHLEN]; 22 | static char *rfn[2]; 23 | static int whichrfn = 0; 24 | char *apout_root = NULL; /* Root dir for simulated a.out */ 25 | 26 | #ifdef DEBUG 27 | /* Debugging flags */ 28 | int inst_debug = 0, /* Print a line before each instruction */ 29 | trap_debug = 0, /* Print details of each trap */ 30 | jsr_debug = 0, /* Print out each jsr */ 31 | fp_debug = 0; /* Print out each floating-point instruction */ 32 | FILE *dbg_file = NULL; /* Debugging output file */ 33 | char *progname = NULL; /* The program's name - used in debugging */ 34 | #endif 35 | 36 | void usage() 37 | { 38 | fprintf(stderr, "Usage: apout"); 39 | #ifdef DEBUG 40 | fprintf(stderr, " [-inst] [-trap] [-jsr] [-fp]"); 41 | #endif 42 | fprintf(stderr, " pdp11_binary\n"); 43 | exit(1); 44 | } 45 | 46 | int main(int argc, char **argv) 47 | { 48 | int i; 49 | 50 | /* Ensure, before we start, that certain types are right */ 51 | assert(sizeof(int8_t) == 1); 52 | assert(sizeof(u_int8_t) == 1); 53 | assert(sizeof(int16_t) == 2); 54 | assert(sizeof(u_int16_t) == 2); 55 | assert(sizeof(int32_t) == 4); 56 | assert(sizeof(u_int32_t) == 4); 57 | 58 | if (argc < 2) 59 | usage(); 60 | if (!strcmp(argv[1], "-help")) 61 | usage(); 62 | if (!strcmp(argv[1], "--help")) 63 | usage(); 64 | 65 | #ifdef DEBUG 66 | while (1) { 67 | if (!strcmp(argv[1], "-inst")) { 68 | inst_debug = 1; 69 | argc--; 70 | argv++; 71 | continue; 72 | } 73 | if (!strcmp(argv[1], "-trap")) { 74 | trap_debug = 1; 75 | argc--; 76 | argv++; 77 | continue; 78 | } 79 | if (!strcmp(argv[1], "-jsr")) { 80 | jsr_debug = 1; 81 | argc--; 82 | argv++; 83 | continue; 84 | } 85 | if (!strcmp(argv[1], "-fp")) { 86 | fp_debug = 1; 87 | argc--; 88 | argv++; 89 | continue; 90 | } 91 | break; 92 | } 93 | if (inst_debug | trap_debug | jsr_debug | fp_debug) 94 | dbg_file = fopen("apout.dbg", "w"); 95 | #endif 96 | 97 | /* Prepare arg list for emulated environment */ 98 | argc--; 99 | argv++; 100 | Argc = argc; 101 | Envp[0] = NULL; 102 | for (i = 0; i < argc; i++) 103 | Argv[i] = argv[i]; 104 | 105 | /* Initialise the stream pointers */ 106 | for (i = 3; i < NFILE; i++) { 107 | stream[i] = NULL; 108 | streammode[i] = NULL; 109 | } 110 | stream[0] = stdin; 111 | streammode[0] = "r"; 112 | stream[1] = stdout; 113 | streammode[1] = "w"; 114 | stream[2] = stderr; 115 | streammode[2] = "w"; 116 | 117 | /* Set the translation to a fictitious */ 118 | /* root filesystem */ 119 | if ((apout_root = getenv("APOUT_ROOT"))) { 120 | set_apout_root(apout_root); 121 | } else { 122 | #ifdef APOUT_DONT_ASSUME_ROOT 123 | fprintf(stderr, 124 | "APOUT_ROOT env variable not set before running apout\n"); 125 | exit(1); 126 | #else 127 | set_apout_root("/"); 128 | #endif 129 | } 130 | 131 | /* Try to load the binary as an a.out */ 132 | if (load_a_out(argv[0], NULL, 1) == -1) { 133 | fprintf(stderr, "Apout - couldn't load %s\n", argv[0]); 134 | exit(1); 135 | } 136 | 137 | /* Other emulated systems (RT-11) can go here */ 138 | 139 | run(); /* Now run the binary */ 140 | exit(0); 141 | } 142 | 143 | /* Translate from a filename to one which is possibly rooted in $APOUT_ROOT. 144 | * Note we return a pointer to one of two buffers. The caller does not 145 | * have to free the returned pointer, but successive calls will destroy 146 | * calls from >2 calls earlier. 147 | */ 148 | char *xlate_filename(char *name) 149 | { 150 | int i = whichrfn; 151 | 152 | if (name == NULL) 153 | return (NULL); 154 | if (name[0] == '\0') 155 | return ("."); /* Undocumented, but used in V7 */ 156 | if (name[0] != '/') 157 | return (name); /* Relative, keep it relative */ 158 | strcpy(rfn[i], name); /* Copy name into buffer */ 159 | whichrfn = 1 - whichrfn; /* Switch to other buffer next time */ 160 | return (realfilename[i]); 161 | } 162 | 163 | void set_apout_root(char *dirname) 164 | { 165 | strcpy(realfilename[0], dirname); 166 | strcpy(realfilename[1], dirname); 167 | rfn[0] = realfilename[0]; 168 | rfn[0] += strlen(realfilename[0]); 169 | rfn[1] = realfilename[1]; 170 | rfn[1] += strlen(realfilename[1]); 171 | } 172 | -------------------------------------------------------------------------------- /double.c: -------------------------------------------------------------------------------- 1 | /* double.c - Double operand instructions. 2 | * 3 | * $Revision: 2.11 $ 4 | * $Date: 1999/12/27 10:19:40 $ 5 | */ 6 | #include "defines.h" 7 | 8 | static u_int32_t templong; 9 | 10 | 11 | /* mov() - Move Instruction. Move operations with registers as the source 12 | * and/or destination have been inlined. */ 13 | void mov() 14 | { 15 | 16 | if (SRC_MODE) { 17 | load_src(); 18 | dstword = srcword; 19 | } else { 20 | dstword = regs[SRC_REG]; 21 | } 22 | 23 | CHG_CC_N(dstword); 24 | CHG_CC_Z(dstword); 25 | CLR_CC_V(); 26 | 27 | if (DST_MODE) { 28 | store_dst(); 29 | } else { 30 | regs[DST_REG] = dstword; 31 | } 32 | } 33 | 34 | /* movsreg(), movsreg1() and movsreg1pc() can all be replaced with 35 | * mov() above. I've broken them out in an attempt to improve 36 | * performance. 37 | */ 38 | void movsreg() 39 | { 40 | dstword = regs[SRC_REG]; 41 | CHG_CC_N(dstword); 42 | CHG_CC_Z(dstword); 43 | CLR_CC_V(); 44 | 45 | if (DST_MODE) { 46 | store_dst(); 47 | } else { 48 | regs[DST_REG] = dstword; 49 | } 50 | } 51 | 52 | void movsreg1() 53 | { 54 | ll_word(regs[SRC_REG], dstword); 55 | CHG_CC_N(dstword); 56 | CHG_CC_Z(dstword); 57 | CLR_CC_V(); 58 | 59 | if (DST_MODE) { 60 | store_dst(); 61 | } else { 62 | regs[DST_REG] = dstword; 63 | } 64 | } 65 | 66 | void movsreg1pc() 67 | { 68 | lli_word(regs[PC], dstword) 69 | CHG_CC_N(dstword); 70 | CHG_CC_Z(dstword); 71 | CLR_CC_V(); 72 | 73 | if (DST_MODE) { 74 | store_dst(); 75 | } else { 76 | regs[DST_REG] = dstword; 77 | } 78 | } 79 | 80 | 81 | 82 | /* cmp() - Compare Instruction. */ 83 | void cmp() 84 | { 85 | load_src(); 86 | load_dst(); 87 | 88 | tmpword = ~dstword; 89 | templong = ((u_int32_t) srcword) + ((u_int32_t) (tmpword)) + 1; 90 | tmpword = LOW16(templong); 91 | 92 | CHG_CC_N(tmpword); 93 | CHG_CC_Z(tmpword); 94 | CHG_CC_VC(srcword, dstword, tmpword); /* was CHG_CC_V */ 95 | CHG_CC_IC(templong); 96 | } 97 | 98 | 99 | /* add() - Add Instruction. */ 100 | void add() 101 | { 102 | load_src(); 103 | load_dst(); 104 | 105 | templong = ((u_int32_t) srcword) + ((u_int32_t) dstword); 106 | tmpword = LOW16(templong); 107 | 108 | CHG_CC_N(tmpword); 109 | CHG_CC_Z(tmpword); 110 | CHG_CC_V(srcword, dstword, tmpword); 111 | CHG_CC_C(templong); 112 | 113 | dstword = tmpword; 114 | store_dst_2(); 115 | } 116 | 117 | /* Subtract Instruction. */ 118 | void sub() 119 | { 120 | load_src(); 121 | load_dst(); 122 | 123 | tmpword = ~srcword; 124 | templong = ((u_int32_t) dstword) + ((u_int32_t) tmpword) + 1; 125 | tmpword = LOW16(templong); 126 | 127 | CHG_CC_N(tmpword); 128 | CHG_CC_Z(tmpword); 129 | CHG_CC_VS(srcword, dstword, tmpword); /* was CHG_CC_V */ 130 | CHG_CC_IC(templong); 131 | 132 | dstword = tmpword; 133 | store_dst_2(); 134 | } 135 | 136 | 137 | /* bit() - Bit Test Instruction. */ 138 | void bit() 139 | { 140 | load_src(); 141 | load_dst(); 142 | 143 | dstword = srcword & dstword; 144 | 145 | CHG_CC_N(dstword); 146 | CHG_CC_Z(dstword); 147 | CLR_CC_V(); 148 | } 149 | 150 | /* bic() - Bit Clear Instruction. */ 151 | void bic() 152 | { 153 | load_src(); 154 | load_dst(); 155 | 156 | dstword = (~srcword) & dstword; 157 | CHG_CC_N(dstword); 158 | CHG_CC_Z(dstword); 159 | CLR_CC_V(); 160 | 161 | store_dst_2(); 162 | } 163 | 164 | 165 | /* bis() - Bit Set Instruction. */ 166 | void bis() 167 | { 168 | load_src(); 169 | load_dst(); 170 | 171 | dstword = srcword | dstword; 172 | 173 | CHG_CC_N(dstword); 174 | CHG_CC_Z(dstword); 175 | CLR_CC_V(); 176 | 177 | store_dst_2(); 178 | } 179 | 180 | /* movb() - Move Byte Instruction. Move operations with registers as the 181 | * source and/or destination have been inlined. */ 182 | void movb() 183 | { 184 | if (SRC_MODE) { 185 | loadb_src(); 186 | } else { 187 | srcbyte = LOW8(regs[SRC_REG]); 188 | } 189 | 190 | CHGB_CC_N(srcbyte); 191 | CHGB_CC_Z(srcbyte); 192 | CLR_CC_V(); 193 | 194 | /* move byte to a register causes sign extension */ 195 | 196 | if (DST_MODE) { 197 | storeb_dst(); 198 | } else { 199 | if (srcbyte & SIGN_B) 200 | regs[DST_REG] = (u_int16_t) 0177400 + (u_int16_t) srcbyte; 201 | else 202 | regs[DST_REG] = (u_int16_t) srcbyte; 203 | } 204 | } 205 | 206 | /* cmpb() - Compare Byte Instruction. */ 207 | void cmpb() 208 | { 209 | u_int8_t data3; 210 | 211 | loadb_src(); 212 | loadb_dst(); 213 | 214 | data3 = (u_int8_t) ~ dstbyte; 215 | tmpword = ((u_int16_t) srcbyte) + ((u_int16_t) (data3)) + 1; 216 | data3 = LOW8(tmpword); 217 | 218 | CHGB_CC_N(data3); 219 | CHGB_CC_Z(data3); 220 | CHGB_CC_VC(srcbyte, dstbyte, data3); 221 | CHGB_CC_IC(tmpword); 222 | } 223 | 224 | 225 | /* bitb() - Bit Test Byte Instruction. */ 226 | void bitb() 227 | { 228 | loadb_src(); 229 | loadb_dst(); 230 | 231 | dstbyte = srcbyte & dstbyte; 232 | 233 | CHGB_CC_N(dstbyte); 234 | CHGB_CC_Z(dstbyte); 235 | CLR_CC_V(); 236 | } 237 | 238 | /* bicb() - Bit Clear Byte Instruction. */ 239 | void bicb() 240 | { 241 | loadb_src(); 242 | loadb_dst(); 243 | 244 | dstbyte = (u_int8_t) ((~srcbyte) & dstbyte); 245 | 246 | CHGB_CC_N(dstbyte); 247 | CHGB_CC_Z(dstbyte); 248 | CLR_CC_V(); 249 | 250 | storeb_dst_2(); 251 | } 252 | 253 | 254 | /* bisb() - Bit Set Byte Instruction. */ 255 | 256 | void bisb() 257 | { 258 | loadb_src(); 259 | loadb_dst(); 260 | 261 | dstbyte = srcbyte | dstbyte; 262 | 263 | CHGB_CC_N(dstbyte); 264 | CHGB_CC_Z(dstbyte); 265 | CLR_CC_V(); 266 | 267 | storeb_dst_2(); 268 | } 269 | -------------------------------------------------------------------------------- /v7trap.h: -------------------------------------------------------------------------------- 1 | /* v7trap.h - Deal with V7 trap instructions. Also do V5 and V6 syscalls. 2 | * 3 | * $Revision: 2.17 $ 4 | * $Date: 1999/12/26 08:16:33 $ 5 | */ 6 | 7 | /* In this file, we list the trap number for each system call, 8 | * and the structures associated with several of the systems 9 | * calls in 7th Edition UNIX 10 | */ 11 | 12 | #define S_INDIR 0 13 | #define S_EXIT 1 14 | #define S_FORK 2 15 | #define S_READ 3 16 | #define S_WRITE 4 17 | #define S_OPEN 5 18 | #define S_CLOSE 6 19 | #define S_WAIT 7 20 | #define S_CREAT 8 21 | #define S_LINK 9 22 | #define S_UNLINK 10 23 | #define S_EXEC 11 24 | #define S_CHDIR 12 25 | #define S_TIME 13 26 | #define S_MKNOD 14 27 | #define S_CHMOD 15 28 | #define S_CHOWN 16 29 | #define S_BREAK 17 30 | #define S_STAT 18 31 | #define S_LSEEK 19 32 | #define S_GETPID 20 33 | #define S_MOUNT 21 34 | #define S_UMOUNT 22 35 | #define S_SETUID 23 36 | #define S_GETUID 24 37 | #define S_STIME 25 38 | #define S_PTRACE 26 39 | #define S_ALARM 27 40 | #define S_FSTAT 28 41 | #define S_PAUSE 29 42 | #define S_UTIME 30 43 | #define S_STTY 31 44 | #define S_GTTY 32 45 | #define S_ACCESS 33 46 | #define S_NICE 34 47 | #define S_FTIME 35 48 | #define S_SYNC 36 49 | #define S_KILL 37 50 | #define S_DUP 41 51 | #define S_PIPE 42 52 | #define S_TIMES 43 53 | #define S_PROF 44 54 | #define S_SETGID 46 55 | #define S_GETGID 47 56 | #define S_SIGNAL 48 57 | #define S_ACCT 51 58 | #define S_PHYS 52 59 | #define S_LOCK 53 60 | #define S_IOCTL 54 61 | #define S_EXECE 59 62 | #define S_UMASK 60 63 | #define S_CHROOT 61 64 | 65 | 66 | char *v7trap_name[] = { 67 | "indir", 68 | "exit", 69 | "fork", 70 | "read", 71 | "write", 72 | "open", 73 | "close", 74 | "wait", 75 | "creat", 76 | "link", 77 | "unlink", 78 | "exec", 79 | "chdir", 80 | "time", 81 | "mknod", 82 | "chmod", 83 | "chown", 84 | "break", 85 | "stat", 86 | "lseek", 87 | "getpid", 88 | "mount", 89 | "umount", 90 | "setuid", 91 | "getuid", 92 | "stime", 93 | "ptrace", 94 | "alarm", 95 | "fstat", 96 | "pause", 97 | "utime", 98 | "stty", 99 | "gtty", 100 | "access", 101 | "nice", 102 | "ftime", 103 | "sync", 104 | "kill", 105 | "unknown", 106 | "unknown", 107 | "unknown", 108 | "dup", 109 | "pipe", 110 | "times", 111 | "prof", 112 | "unknown", 113 | "setgid", 114 | "getgid", 115 | "signal", 116 | "unknown", 117 | "unknown", 118 | "acct", 119 | "phys", 120 | "lock", 121 | "ioctl", 122 | "unknown", 123 | "unknown", 124 | "unknown", 125 | "unknown", 126 | "exece", 127 | "umask", 128 | "chroot" 129 | }; 130 | 131 | 132 | struct tr_v7stat { 133 | int16_t st_dev; 134 | u_int16_t st_ino; 135 | u_int16_t st_mode; 136 | int16_t st_nlink; 137 | int16_t st_uid; 138 | int16_t st_gid; 139 | int16_t st_rdev; 140 | int8_t st_size[4]; /* Alignment problems */ 141 | int8_t st_atim[4]; /* Alignment problems */ 142 | int8_t st_mtim[4]; /* Alignment problems */ 143 | int8_t st_ctim[4]; /* Alignment problems */ 144 | }; 145 | 146 | struct tr_v6stat { 147 | int16_t idev; /* Device */ 148 | int16_t inum; 149 | int16_t iflags; /* Mode */ 150 | int8_t inl; /* Links */ 151 | int8_t iuid; 152 | int8_t igid; 153 | u_int8_t isize0; /* Most significant 8 bits */ 154 | u_int16_t isize; 155 | int16_t iaddr[8]; /* Not used, I hope! */ 156 | u_int32_t atime; /* Alignment problems */ 157 | u_int32_t mtime; /* Alignment problems */ 158 | }; 159 | 160 | struct tr_timeb { 161 | u_int32_t time; 162 | u_int16_t millitm; 163 | int16_t timezone; 164 | int16_t dstflag; 165 | }; 166 | 167 | struct tr_sgttyb { 168 | int8_t sg_ispeed; /* input speed */ 169 | int8_t sg_ospeed; /* output speed */ 170 | int8_t sg_erase; /* erase character */ 171 | int8_t sg_kill; /* kill character */ 172 | int16_t sg_flags; /* mode flags */ 173 | }; 174 | 175 | /* 176 | * Values for sg_flags 177 | */ 178 | #define TR_TANDEM 01 179 | #define TR_CBREAK 02 180 | #define TR_LCASE 04 181 | #define TR_ECHO 010 182 | #define TR_CRMOD 020 183 | #define TR_RAW 040 184 | #define TR_ODDP 0100 185 | #define TR_EVENP 0200 186 | #define TR_ANYP 0300 187 | #define TR_XTABS 06000 188 | 189 | /* 190 | * Values for signal 191 | */ 192 | #define V7_SIG_DFL 0 193 | #define V7_SIG_IGN 1 194 | 195 | #define V7_NSIG 15 196 | 197 | #define V7_SIGHUP 1 /* hangup */ 198 | #define V7_SIGINT 2 /* interrupt */ 199 | #define V7_SIGQUIT 3 /* quit */ 200 | #define V7_SIGILL 4 /* illegal instruction (not reset when caught) */ 201 | #define V7_SIGTRAP 5 /* trace trap (not reset when caught) */ 202 | #define V7_SIGIOT 6 /* IOT instruction */ 203 | #define V7_SIGEMT 7 /* EMT instruction */ 204 | #define V7_SIGFPE 8 /* floating point exception */ 205 | #define V7_SIGKILL 9 /* kill (cannot be caught or ignored) */ 206 | #define V7_SIGBUS 10 /* bus error */ 207 | #define V7_SIGSEGV 11 /* segmentation violation */ 208 | #define V7_SIGSYS 12 /* bad argument to system call */ 209 | #define V7_SIGPIPE 13 /* write on a pipe with no one to read it */ 210 | #define V7_SIGALRM 14 /* alarm clock */ 211 | #define V7_SIGTERM 15 /* software termination signal from kill */ 212 | 213 | 214 | /* A union which will point at the trap args, so that 215 | * we can get at the various args of different types 216 | */ 217 | typedef union { 218 | int16_t sarg[4]; /* Signed 16-bit args */ 219 | u_int16_t uarg[4]; /* Unsigned 16-bit args */ 220 | } arglist; 221 | 222 | #define sarg1 V7A.sarg[0] 223 | #define sarg2 V7A.sarg[1] 224 | #define sarg3 V7A.sarg[2] 225 | #define sarg4 V7A.sarg[3] 226 | #define uarg1 V7A.uarg[0] 227 | #define uarg2 V7A.uarg[1] 228 | #define uarg3 V7A.uarg[2] 229 | #define uarg4 V7A.uarg[3] 230 | -------------------------------------------------------------------------------- /LIMITATIONS: -------------------------------------------------------------------------------- 1 | Bugs in Binaries 2 | ---------------- 3 | 4 | One of the V5 C compiler passes requires -DZERO_MEMORY: it must not 5 | initialise a variable properly. V5 and V6 ar(1) do not close a file 6 | descriptor after writing has finished. If Apout is compiled with 7 | stream buffering, when this file is copied it is truncated. Either 8 | turn off Apout stream buffering (a performance penalty), or patch 9 | ar.s to behave itself. The patch is: 10 | 11 | *** ar.s.orig Thu Jan 14 09:40:46 1999 12 | --- ar.s Thu Jan 14 09:41:12 1999 13 | *************** 14 | *** 444,449 **** 15 | --- 444,451 ---- 16 | bes crterr 17 | mov r0,afo 18 | sys write; magic; 2 19 | + mov tfo,r0 / need to close before reading 20 | + sys close 21 | 1: 22 | mov tfi,r0 23 | sys read; buf; 512. 24 | 25 | 26 | Floating-point Limitations 27 | -------------------------- 28 | 29 | PDP-11 doubles are treated as floats. FEA/FEC don't exist. 30 | FP errors are not dealt with. Mistrust FP results for now. 31 | 32 | Limitations for 7th Edition Emulation in Apout 2.3 33 | -------------------------------------------------- 34 | 35 | Note that V5 and V6 binaries are considered V7 binaries. Overlay 36 | binaries (type 0405) are not recognised. 37 | 38 | The errno values on the native system are not translated back to 39 | the V7 errno values. There is normally a 1-to-1 mapping, but V7 40 | only had 32 errno values; native errno values above this are going 41 | to confuse the emulated application. 42 | 43 | The following system calls are not implemented, and return an 44 | EPERM error to the application: phys(2), prof(2), ptrace(2), 45 | acct(2), mount(2), umount(2), times(2). The following system 46 | calls are ignored: lock(2), stime(2). 47 | 48 | The following systems calls are only partially implemented: 49 | 50 | signal(2): Only SIG_DFL and SIG_IGN are implemented. 51 | stty(2), gtty(2): These should work, but V7 stty(1) doesn't work. 52 | ioctl(2): Only enough to emulate stty(2) amd gtty(2). 53 | 54 | The emulated applications use the native filesystem. Native filenames bigger 55 | than 14 characters are truncated to 14 characters before being passed to 56 | the application. In a similar way, inode numbers bigger than 65,536 are 57 | truncated modulo 65,536 before being passed to the application. 58 | 59 | Limitations for 5th & 6th Edition Emulation in Apout 2.3 60 | -------------------------------------------------------- 61 | 62 | There seems to be a bug in V5/V6 ctime() which stops dates after 63 | November 1999 being displayed correctly. Apout works around this 64 | problem by modifying dates returned from system calls to be in 65 | the year 1998 if they are 1999 or later. 66 | 67 | Limitations for 2.9BSD Emulation in Apout 2.3 68 | --------------------------------------------- 69 | 70 | At present, 2.9BSD binaries are treated as V7 binaries, so the limitations 71 | above apply. This also means that overlays are not understood, and also the 72 | 2.9-specific system calls have not yet been implemented. 73 | 74 | Limitations for 2.11BSD Emulation in Apout 2.3 75 | ---------------------------------------------- 76 | 77 | Flags passed as arguments to the 2.11 syscalls are promoted to 32-bit 78 | ints and passed to the native syscall. The errno values on the native 79 | system are not translated back to the 2.11 errno values. To find out 80 | what syscalls have been implemented, grep for the word DONE in bsdtrap.c. 81 | 82 | The following 2.11 syscalls are not handled: 83 | 84 | S_GETSOCKOPT, S_SETSOCKOPT, S_SELECT, 85 | S_RECVMSG, S_SENDMSG, S_SENDTO, 86 | S_SIGBLOCK, S_SIGPAUSE, S_SIGRETURN, 87 | S_SIGSETMASK, S_SIGSTACK, S_SIGVEC 88 | 89 | Limitations for 1st Edition Emulation in Apout 2.3 90 | -------------------------------------------------- 91 | 92 | This is still in the experimental stages, with some problems with time 93 | values. The KE11A emulation is also incomplete. However, the following 94 | 0405-magic binaries from Dennis Ritchie's s2.tar archive are known to work: 95 | 96 | cat, cp, date, echo, ls, mkdir, sh, wc 97 | 98 | Most of the others seem to work as well, but I haven't tested them completely. 99 | The list of 0405-magic files on the s2 archive is: 100 | 101 | bin/: bin/mv 102 | bin/ar bin/od 103 | bin/bas bin/pr 104 | bin/cat bin/rew 105 | bin/chball bin/rmdir 106 | bin/check bin/roff 107 | bin/chown bin/sh 108 | bin/cmp bin/skip 109 | bin/cp bin/sort 110 | bin/date bin/stat 111 | bin/db bin/stty 112 | bin/dc bin/su 113 | bin/df bin/sum 114 | bin/du bin/tap 115 | bin/echo bin/tm 116 | bin/ed bin/tty 117 | bin/exit bin/wc 118 | bin/form bin/who 119 | bin/goto bin/write 120 | bin/if etc/getty 121 | bin/login etc/glob 122 | bin/ls etc/init 123 | bin/mail etc/msh 124 | bin/mesg /tc/suftab 125 | bin/mkdir 126 | 127 | The following 1st Edition system calls are not yet emulated: GTTY, STTY, TELL. 128 | 129 | Limitations for 2nd Edition Emulation in Apout 2.3 130 | -------------------------------------------------- 131 | 132 | The few 2nd Edition binaries with 0407-magic on the s2 archive can now 133 | be run with Apout. Essentially, they receive the same environment as 134 | the 1st Edition binaries, with a few small syscall differences. Note 135 | that, at present, I don't have a copy of the V2 manuals, so I can 136 | guarantee that 2nd Edition emulation still needs work. 137 | 138 | However, the emulation is good enough to allow the C compiler on the s2 139 | archive to compile the last1120c C compiler on Dennis Ritchie's homepage. 140 | 141 | The list of 0407-magic files in the s2 archive is below. I have starred 142 | those binaries that I know work with Apout. 143 | 144 | * bin/as usr/fort/fc1 145 | * bin/cc usr/fort/fc2 146 | bin/ds usr/fort/fc3 147 | bin/fc usr/fort/fc4 148 | bin/find usr/jack/a.out 149 | * bin/ld usr/jack/x.o 150 | bin/maki * usr/lib/c0 151 | bin/nm * usr/lib/c1 152 | * bin/size usr/lib/crt0.o 153 | bin/strip usr/lib/fr0.o 154 | bin/un usr/sys/a.out 155 | * etc/as2 156 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Apout -- Simulate PDP-11 Unix a.out binaries 2 | Version 2.3 Beta 1 3 | 4 | Warren Toomey wkt@tuhs.org 5 | June 2002 6 | 7 | Introduction 8 | ------------ 9 | This program is a user-level simulator for UNIX a.out binaries. Binaries 10 | for V1, V2, V5, V6, V7, 2.9BSD and 2.11BSD can be run with this simulator. 11 | The user-mode PDP-11 instructions are simulated, and TRAP instructions 12 | are emulated by calling equivalent native-mode system calls. 13 | 14 | The advantages of an a.out simulator over a full-blown PDP-11 simulator are: 15 | 16 | + system calls can be done natively, thus speeding up execution 17 | + the simulator is less of a CPU-hog than a full-blown PDP-11 simulator 18 | + you don't need a simulated operating system or a simulated file system 19 | 20 | Apout can be obtained via anonymous ftp at minnie.tuhs.org in the 21 | directory pub/PDP-11/Sims/Apout. The directory pub/PDP-11/Sims/Apout/UnixBins 22 | contains tar archives of a.out binaries from several versions of UNIX. 23 | 24 | Status 25 | ------ 26 | The program is now at release 2.3 Alpha2. Most of the binaries from V5, V6 27 | and V7 run fine. All of the V5/V6/V7 system calls are caught, but some are 28 | ignored and some generate EPERM errors. The V1, V2, 2.9BSD and 2.11BSD 29 | environments are still under construction: see the file LIMITATIONS for 30 | details. Finally, the simulator won't run on a big-endian machine. 31 | 32 | INSTALLATION 33 | ------------ 34 | I have only tested this program on FreeBSD 2.x and 3.x, and on RedHat 35 | Linux 2.2. It should compile on a 32-bit little-endian machine with 36 | some form of Unix; you may need to change some header file includes etc. 37 | See `defines.h' for the details. In particular, if your system doesn't have 38 | types for: 39 | 40 | int8_t, int16_t, int32_t, u_int8_t, u_int16_t, u_int32_t 41 | 42 | or if your compiler doesn't have char=1 byte, short= 2 bytes, int=4 bytes, 43 | then alter the relevant typedefs in `defines.h'. 44 | 45 | The Makefile has two sets of CFLAGS/LDFLAGS: one set is for debugging, and 46 | the other set is for speed. If you define the C pre-processor macro `DEBUG', 47 | then this includes debugging code into the program. I use it quite heavily 48 | when trying to fix niggling problems. 49 | 50 | If you remove the -DEMU211 macro definition from the Makefile, the emulation 51 | of 2.11BSD will not be compiled in to the simulator. Similarly, if you remove 52 | the -DEMUV1 macro definition from the Makefile, the emulation of 1st and 2nd 53 | Edition UNIX will not be compiled in to the simulator. By default, EMUV1 54 | is disabled. 55 | 56 | 57 | Once you have configured apout, now type `make'. Hopefully, things will 58 | compile ok. You will eventually get the `apout' program. 59 | 60 | Now go find an old PDP-11 UNIX binary, e.g 7th Edition cal, and say: 61 | 62 | % setenv APOUT_ROOT / # for now 63 | % apout cal 1970 64 | 65 | If the simulator is working, the calendar for 1970 will be printed out. 66 | The V7 shell works, and from there, you can run other programs. 67 | 68 | % apout sh 69 | # ls -l 70 | output of ls 71 | # 72 | 73 | Finally, install apout in /usr/local/bin, and the manual page apout.1 in 74 | the appropriate place. If you can't use the man page because of incompatible 75 | macros, then apout.0 is a text file which has the pre-formatted man page. 76 | 77 | DEBUG OPTIONS 78 | ------------- 79 | When debugging is compiled in, the program has several options: 80 | 81 | -inst turns on instruction tracing, which is _very_ verbose 82 | -trap turns on TRAP tracing; not all syscalls have debugging code 83 | -jsr prints out the details of each jsr and rts 84 | -fp prints out some details of floating-point instructions 85 | 86 | All debugging output goes out to the file `apout.dbg'. These debugging options 87 | are mainly used for testing apout, and so the output in apout.dbg may not be 88 | very useful to you. 89 | 90 | ENVIRONMENT VARIABLES 91 | --------------------- 92 | Apout has the concept of a simulated root filesystem for the simulated PDP-11 93 | binaries. When working with filenames, if the filenames are relative, they 94 | stay relative. If the filenames are absolute (i.e /usr/...), then apout 95 | prepends the value of the environment variable APOUT_ROOT to the filename. 96 | This allows you to say: 97 | 98 | # setenv APOUT_ROOT /usr/misc/v7root 99 | 100 | before running apout to set the `root' of the filesystem wherever you want. 101 | You MUST set APOUT_ROOT before running apout. 102 | 103 | TODO 104 | ---- 105 | There's lots to do. Here's what I'd like to do, in a somewhat ordered list. 106 | 107 | + Verify that the instruction simulation and high priority 108 | the syscalls all work correctly 109 | + Complete some of the syscalls that are med priority 110 | not fully simulated 111 | + Speed the simulator up med priority 112 | 113 | SOURCE ORGANISATION 114 | ------------------- 115 | 116 | main.c parses any arguments, loads the binary and calls run() 117 | cpu.c holds the main instruction decode/execute loop 118 | itab.c holds function lookup tables for all instructions 119 | ea.c holds functions to decode the PDP-11 addressing modes 120 | debug.c holds strings for all emulated opcodes 121 | 122 | single.c single.c, double.c and branch.c hold most of the functions 123 | double.c which perform the PDP-11 user-mode instructions. The code 124 | branch.c in these files comes from a PDP-11 simulator by Eric Edwards 125 | fp.c partially emulates FP instructions 126 | 127 | aout.c determines what type of a.out the binary is, and what UNIX 128 | magic.c environment to set up. If V5/V6/V7, trap instructions fall 129 | v7trap.c into v7trap.c which runs them using native system calls 130 | v7trap.h 131 | 132 | v1trap.c if the binary is a 1st or 2nd Edition binary, traps fall 133 | v1trap.h into v1trap.c, which likewise does the syscalls natively 134 | ke11a.c emulates the KE11A extended arithmetic unit, used by V1/V2 135 | 136 | bsdtrap.c if the binary is a 2.11BSD binary, trap instructions fall 137 | bsdtrap.h into bsdtrap.c, which likewise does the syscalls natively 138 | bsd_ioctl.c 2.11BSD ioctl calls are handled with this file 139 | 140 | defines.h holds function & typedef prototypes and useful cpp macros 141 | -------------------------------------------------------------------------------- /magic.c: -------------------------------------------------------------------------------- 1 | /* magic.c - determine the environment for certain PDP-11 a.out binaries 2 | * 3 | * Some binaries in V1, V2, V5, V6, V7 and 2.11BSD are not caught with the 4 | * magic numbers in aout.c. If this is the case, we fall into the 5 | * special_magic() function, which calculates a checksum on the 6 | * a.out header. If it matches any of the checksums below, it returns 7 | * the appropriate environment value. Otherwise, it returns IS_UNKNOWN. 8 | * 9 | * $Revision: 1.15 $ 10 | * $Date: 2008/05/15 03:20:52 $ 11 | */ 12 | #include "defines.h" 13 | 14 | struct spec_aout { 15 | u_int32_t cksum; 16 | int environment; 17 | }; 18 | 19 | static struct spec_aout S[] = { 20 | {0x1042c2, IS_V6}, /* V6 bin/dc */ 21 | {0x10f02, IS_V5}, /* V5 etc/update */ 22 | {0x11002, IS_V5}, /* V5 bin/clri */ 23 | {0x1117c2, IS_V7}, /* V7 bin/roff */ 24 | {0x11702, IS_V6}, /* V6 etc/update */ 25 | {0x11a82, IS_V5}, /* V5 bin/sum */ 26 | {0x1319c2, IS_V5}, /* V5 usr/fort/fc1 */ 27 | {0x1332c2, IS_V2}, /* /lib/c0 dated Jun 30 1973 from s2 tape */ 28 | {0x13642, IS_V5}, /* V5 bin/rew */ 29 | {0x139e02, IS_V5}, /* V5 bin/dc */ 30 | {0x13c0, IS_V6}, /* V6 usr/lib/tmgc */ 31 | {0x14042, IS_V6}, /* V6 bin/tty */ 32 | {0x143c2, IS_V5}, /* V5 bin/tty */ 33 | {0x152ac2, IS_V6}, /* V6 usr/lib/tmg */ 34 | {0x15f42, IS_V5}, /* V5 bin/kill */ 35 | {0x16802, IS_V5}, /* V5 bin/dsw */ 36 | {0x16902, IS_V5}, /* V5 bin/mkdir */ 37 | {0x1720c2, IS_V6}, /* V6 bin/cdb */ 38 | {0x17742, IS_V5}, /* V5 usr/bin/pfe */ 39 | {0x17cc2, IS_V5}, /* V5 usr/bin/mesg */ 40 | {0x18702, IS_V5}, /* V5 bin/rmdir */ 41 | {0x194c2, IS_V6}, /* V6 bin/chgrp */ 42 | {0x197c2, IS_V6}, /* V6 bin/chown */ 43 | {0x19a42, IS_V5}, /* V5 bin/chown */ 44 | {0x19b342, IS_V6}, /* V6 usr/bin/nroff */ 45 | {0x19f682, IS_V6}, /* V6 usr/fort/fc1 */ 46 | {0x1ae00, IS_V2}, /* V2 bin/strip */ 47 | {0x1b102, IS_V5}, /* V5 bin/strip */ 48 | {0x1ba02, IS_V6}, /* V6 bin/strip */ 49 | {0x1c342, IS_V5}, /* V5 bin/cat */ 50 | {0x1c8442, IS_V7}, /* V7 usr/games/maze */ 51 | {0x1cc782, IS_V6}, /* V6 lib/fc0 */ 52 | {0x1dfc2, IS_V5}, /* V5 etc/getty */ 53 | {0x1f9c2, IS_V2}, /* /bin/nm dated Jun 30 1973 from s2 tape */ 54 | {0x20202, IS_V5}, /* V5 usr/games/bj */ 55 | {0x21e42, IS_V6}, /* V6 usr/bin/units */ 56 | {0x23f82, IS_V5}, /* V5 usr/bin/passwd */ 57 | {0x260642, IS_V6}, /* V6 lib/fc1 */ 58 | {0x262a82, IS_211BSD}, /* 2.11 usr/new/m11 */ 59 | {0x27e82, IS_V5}, /* V5 usr/bin/grep */ 60 | {0x290c2, IS_V7}, /* V7 usr/games/cubic */ 61 | {0x299c2, IS_V5}, /* V5 usr/games/cubic */ 62 | {0x2f482, IS_V5}, /* V5 usr/bin/form */ 63 | {0x3382, IS_V6}, /* V6 bin/write */ 64 | {0x326642, IS_V7}, /* 2.9 awk */ 65 | {0x33c42, IS_211BSD}, /* 2.11 usr/games/moo */ 66 | {0x351382, IS_211BSD}, /* 2.11 usr/games/lib/zork */ 67 | {0x3702, IS_V5}, /* V5 usr/games/moo */ 68 | {0x3b402, IS_V5}, /* V5 bin/ar */ 69 | {0x3cc02, IS_V2}, /* /bin/size from from s2 tape */ 70 | {0x4382, IS_V5}, /* V5 bin/write */ 71 | {0x451f42, IS_V7}, /* 2.9 /lib/c1 */ 72 | {0x47042, IS_211BSD}, /* 2.11 usr/games/ttt */ 73 | {0x4fa02, IS_V5}, /* V5 bin/ld */ 74 | {0x51342, IS_211BSD}, /* 2.11 usr/games/bj */ 75 | {0x53302, IS_V6}, /* V6 usr/lib/suftab */ 76 | {0x55882, IS_V7}, /* 2.9 /bin/as */ 77 | {0x54702, IS_V5}, /* V5 usr/games/ttt */ 78 | {0x55702, IS_V7}, /* V7 bin/as */ 79 | {0x5c342, IS_V2}, /* /bin/cc dated Jun 30 1973 from s2 tape */ 80 | {0x6f742, IS_V6}, /* V6 usr/bin/sa */ 81 | {0x7042, IS_V7}, /* V7 bin/factor */ 82 | {0x71702, IS_V7}, /* V7 lib/as2 */ 83 | {0x7342, IS_V5}, /* V5 bin/du */ 84 | {0x73782, IS_V7}, /* 2.9 /lib/as2 */ 85 | {0x73e00, IS_V2}, /* /bin/ld from s2 tape */ 86 | {0x7a242, IS_V6}, /* V6 lib/as2 */ 87 | {0x7b102, IS_V6}, /* V6 bin/as */ 88 | {0x7d082, IS_V5}, /* V5 bin/as */ 89 | {0x7d6844, IS_V1}, /* bin/cal from s2 tape */ 90 | {0x7d942, IS_V5}, /* V5 lib/as2 */ 91 | {0x8002, IS_V5}, /* V5 etc/lpd */ 92 | {0x85842, IS_V5}, /* V5 bin/ed */ 93 | {0x8f00, IS_V6}, /* V6 usr/lib/tmga */ 94 | {0x915c2, IS_V6}, /* V6 bin/bas */ 95 | {0x94542, IS_V5}, /* V5 bin/db */ 96 | {0x98442, IS_V6}, /* V6 usr/bin/ac */ 97 | {0x9adc2, IS_V6}, /* V6 bin/db */ 98 | {0xa242, IS_V7}, /* V7 bin/primes */ 99 | {0xa4602, IS_V2}, /* /bin/as from s2 tape */ 100 | {0xa702, IS_V5}, /* V5 bin/time */ 101 | {0xad882, IS_V7}, /* V7 bin/bas */ 102 | {0xadc42, IS_V2}, /* /usr/lib/c1 from s2 tape */ 103 | {0xb5a82, IS_V6}, /* V6 usr/bin/prof */ 104 | {0xc1e42, IS_V5}, /* V5 usr/bin/fed */ 105 | {0xc3102, IS_V6}, /* V6 bin/tp */ 106 | {0xc8bc2, IS_V5}, /* V5 bin/tp */ 107 | {0xe1642, IS_V6}, /* V6 usr/bin/roff */ 108 | {0xe1f42, IS_V5}, /* V5 usr/bin/roff */ 109 | {0xec582, IS_V5}, /* V5 bin/bas */ 110 | {0xfc2, IS_V6}, /* V6 usr/bin/typo */ 111 | {0xfc002, IS_V2}, /* /bin/as dated Jun 30 1973 from s2 tape */ 112 | {0x38ec0, IS_V5}, /* V5 bin/ar, Warrens */ 113 | {0, 0} 114 | }; 115 | 116 | /* cptr points at the start of the a.out header */ 117 | int special_magic(u_int16_t * cptr) 118 | { 119 | u_int32_t cksum = 0; 120 | int i; 121 | char *unix_version; 122 | 123 | if (cptr == NULL) 124 | return (IS_UNKNOWN); 125 | /* Calculate the checksum */ 126 | for (i = 0; i < 8; i++) { 127 | cksum ^= cptr[i]; 128 | cksum = cksum << 1; 129 | } 130 | 131 | /* Try and find a match */ 132 | for (i = 0; S[i].cksum != 0; i++) 133 | if (S[i].cksum == cksum) { 134 | TrapDebug((dbg_file, "This a.out has special magic %d\n", i)); 135 | return (S[i].environment); 136 | } 137 | 138 | /* See if user tells us what version to use */ 139 | if ((unix_version = getenv("APOUT_UNIX_VERSION"))) { 140 | if (!strcmp(unix_version, "V1")) 141 | return (IS_V1); 142 | if (!strcmp(unix_version, "V2")) 143 | return (IS_V2); 144 | if (!strcmp(unix_version, "V3")) 145 | return (IS_V3); 146 | if (!strcmp(unix_version, "V4")) 147 | return (IS_V4); 148 | if (!strcmp(unix_version, "V5")) 149 | return (IS_V5); 150 | if (!strcmp(unix_version, "V6")) 151 | return (IS_V6); 152 | if (!strcmp(unix_version, "V7")) 153 | return (IS_V7); 154 | if (!strcmp(unix_version, "2.9BSD")) 155 | return (IS_29BSD); 156 | if (!strcmp(unix_version, "2.11BSD")) 157 | return (IS_211BSD); 158 | } 159 | 160 | /* We can't tell what version of Unix, give up */ 161 | (void) printf("Apout - unknown magic in header: 0x%x\n", cksum); 162 | return (IS_UNKNOWN); 163 | } 164 | -------------------------------------------------------------------------------- /CHANGES: -------------------------------------------------------------------------------- 1 | 2.3 Beta1: to 10th June 2002 2 | ---------------------------- 3 | 4 | Changed debug statements in cpu.c to be TrapDebug statements as I was 5 | seeing output from these in the output file of 2.11BSD /lib/cpp. 6 | 7 | The problem with scripts has also been fixed, finally. I was passing 8 | the wrong path into the shell arguments. 9 | 10 | On a 1.6GHz Pentium 4 running FreeBSD 4.5, a make depend; make of the 11 | 2.11BSD GENERIC kernel takes 72 seconds. 12 | 13 | 2.3 Alpha3: to 1st June 2001 14 | ---------------------------- 15 | 16 | Added patches from Wilhelm B. Kloke wb@vestein.arb-phys.uni-dortmund.de 17 | to get Apout to run the Algol 68 binaries found which were added into 18 | the Unix Archive. 19 | 20 | A few changes for better Linux compilation. However, stream buffering 21 | doesn't seem to work on Linux, at least RedHat 6.2. 22 | 23 | 2.3 Alpha2: to 10th Jan 2000 24 | ---------------------------- 25 | 26 | Added partial support for 0407-magic binaries from 2nd Edition. At 27 | present, this is enough for the C compiler on Dennis Ritchie's s2.tar 28 | archive to work. It's also good enough for the C compiler to recompile 29 | the last1120c compiler, and for the last1120c compiler to recompile itself. 30 | 31 | Added code to support 512-byte block seeks on /dev files for 1st Edition 32 | binaries. This was required to get tap(1) to work. This should really 33 | only force 512-byte seeks on specific /dev/files, not all of them. 34 | 35 | A significant rearrangement of the code in aout.c was done to make it 36 | more logical. I wouldn't say it was much tidier than before, though. 37 | 38 | A redefinition of sigset_t in NetBSD stopped Apout from being compiled 39 | there. Thanks to Soren, bsdsignal.c was modified to fix this problem. 40 | 41 | Some small changes to the output from -inst to make it look better. 42 | Added a WRITEBASE #define to help improve performance just a bit more. 43 | 44 | 2.3 Alpha1: to 2nd Jan 2000 45 | --------------------------- 46 | 47 | Added nearly complete support for 0405-magic binaries from 1st Edition, 48 | including emulating the KE11A extended arithmetic element. Still some 49 | work needed here on both the trap handling and KE11A support. Thanks to 50 | Tim Shoppa (shoppa@trailing-edge.com) for his eae code. The 0407-magic 51 | binaries from Dennis Ritchie's s2.tar archive are not yet supported. I 52 | need the V2/V3 manuals from Norman Wilson for this. 53 | 54 | Some tidying up of the code has been done, using LCLINT and by hand. 55 | I've made a Debug() macro which make the code look a bit cleaner. 56 | 57 | Some memory leaks removed. Natives exec()s now inherit the original 58 | environment, not the emulated one. Some mov() functions split into 59 | separate functions to help improve performance. Added a workaround 60 | for date handling in V5/V6 ctime(): see tail of v7trap.c. 61 | 62 | Stream buffering variables consolidated into main.c and some bugs 63 | removed (e.g "rw" -> "w+"). 2.11BSD emulation now has stream buffering, 64 | but it is turned off by default as it doesn't seem to provide any 65 | improvement in performance. 66 | 67 | 2.2 Alpha9: to 2nd Mar 1999 68 | --------------------------- 69 | 70 | I've added magic numbers for some 2.9BSD binaries: all 2.9 binaries 71 | run in the V7 environment, which seems to work but I'm sure that 72 | 2.9 != V7. 73 | 74 | With help from Jonathan Naylor (g4klx@g4klx.demon.co.uk), and some work 75 | myself, I've managed to compile Apout under RedHat Linux 2.2. There are 76 | some 2.11BSD syscalls not implemented as a result, but I can recompile 77 | the V7 and the 2.11BSD kernels, which is a good indicator. 78 | 79 | 80 | 2.2 Alpha8: to 15th Jan 1999 81 | ---------------------------- 82 | 83 | These changes came about due to my attempt to compile the UNIX `nsys' 84 | kernel source code, dated 1973, with the 5th Edition development tools. 85 | 86 | Added better detection of some special UNIX a.out binaries: the 87 | environment for these binaries was being incorrectly set by aout.c. 88 | There is now a magic.c which fixes the problem. See also LIMITATIONS 89 | for a note of bugs in some a.out binaries. 90 | 91 | Modified v7trap.c to be much cleaner, and to look a bit more like 92 | bsdtrap.c. Introduced several small bugs in V5/V6/V7 syscall emulation, 93 | notably pipe() and dup(), by the cleanup. These are fixed. 94 | 95 | 96 | 2.2 Alpha7: to 11th Jan 1999 97 | ---------------------------- 98 | 99 | Modified the code to handle the syscall differences between 100 | V6 and V7: note that V5 and V6 are syscall identical. V6 has 101 | a different seek() and stat() to V7. 102 | 103 | Added a new file for 2.11BSD ioctls, did many of the terminal 104 | ioctls, and a few more syscalls. Now 2.11 vi runs. However, 105 | longjmp() doesn't work yet, because it requires working signals. 106 | 107 | Changed some types and #ifdefs for NetBSD and OpenBSD: thanks Soren! 108 | 109 | 110 | 2.2 Alpha6: to 6th Jan 1999 111 | --------------------------- 112 | 113 | Bugfixes: none that I can think of. 114 | 115 | Enhancements: tidied the code up somewhat. Changed uint -> u_int 116 | throughout. Added support for execution of native binaries: now I can 117 | run vi from inside 2.11 bin/sh, yay! Finally wrote the long-overdue 118 | manual page. Added RCS tags to all sources. Ensured that it compiled on 119 | FreeBSD 3.x and 2.1.x: I need to take it home for FreeBSD 2.2.x. 120 | 121 | 122 | 2.2 Alpha5: to 5th Jan 1999 123 | --------------------------- 124 | 125 | Bugfixes: fixed malloc bug, which was a too-large blksize from stat/fstat. 126 | Fixed the gtty/stty emulation, which was causing make to break. 127 | 128 | Enhancements: Apout can now run shell scripts. 2.11BSD overlay binaries 129 | are now supported, which is good news. I can now compile the 2.11 GENERIC 130 | kernel with no manual intervention. On a Pentium II 350MHz, this takes 131 | 4:16secs with an optimised Apout. 132 | 133 | 134 | 2.2 Alpha4: to 2nd Jan 1999 135 | --------------------------- 136 | 137 | Fixed more deficiencies in the 2.11BSD emulation, in particular 138 | fork(), vfork() and sbrk(). The argv/envp environment is better 139 | but still not totally correct, I think. Finally got the correct 140 | code for 2.11 readdir(). 141 | 142 | We now have a semi-working FP emulation. It's enough to keep 2.11 143 | happy, but it isn't very good. It will do for now. 144 | 145 | Many of the 2.11BSD syscalls are now implemented. Most are not 146 | verified, but a lot of 2.11BSD commands run, including sh, make, 147 | cc, date, cal. ls(1) goes into an infinite loop when doing ls -l, 148 | the inf. loop is in malloc(3). By substituting malloc(3) from 149 | Minix 1.3, this problem goes away. I don't know if it's a bug 150 | in the emulator, or in the 2.11 malloc() code. 151 | 152 | 153 | 2.2 Alpha3 to 5th Dec 1998 154 | -------------------------- 155 | 156 | Reorganised bsdtrap.[ch], and started work on the 157 | 2.11BSD emulated syscalls; this is surprisingly 158 | easy for many of them. 159 | 160 | 161 | Changes from 2.1 to 2.2 162 | ----------------------- 163 | 164 | + General code tidying up and niggling bug removal. 165 | + Code optimisation to speed things up, although 166 | I haven't quantified the improvement yet. 167 | + Separation of the binary loader and trap handlers 168 | from the main program. This doesn't do anything now, 169 | but it will make the emulation of several PDP-11 170 | environments (e.g 2.11BSD, RT-11) much easier to do. 171 | + Finished getting the stream buffering of I/O to work. 172 | I still don't know why fdopen doesn't work on "rw". 173 | + Some extra trap functionality, e.g basic signal handling. 174 | -------------------------------------------------------------------------------- /bsd_signal.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Much of this file comes from 2.11BSD's /usr/include/signal.h and is 3 | * Copyright (c) 1986 Regents of the University of California. 4 | * All rights reserved. The Berkeley software License Agreement 5 | * specifies the terms and conditions for redistribution. 6 | * 7 | * Code to deal with 2.11BSD signals 8 | */ 9 | #include "defines.h" 10 | #include 11 | #include "bsdtrap.h" 12 | 13 | 14 | #define NBSDSIG 32 15 | 16 | #define BSDSIGHUP 1 /* hangup */ 17 | #define BSDSIGINT 2 /* interrupt */ 18 | #define BSDSIGQUIT 3 /* quit */ 19 | #define BSDSIGILL 4 /* illegal instruct (not reset when caught) */ 20 | #define BSDSIGTRAP 5 /* trace trap (not reset when caught) */ 21 | #define BSDSIGIOT 6 /* IOT instruction */ 22 | #define BSDSIGEMT 7 /* EMT instruction */ 23 | #define BSDSIGFPE 8 /* floating point exception */ 24 | #define BSDSIGKILL 9 /* kill (cannot be caught or ignored) */ 25 | #define BSDSIGBUS 10 /* bus error */ 26 | #define BSDSIGSEGV 11 /* segmentation violation */ 27 | #define BSDSIGSYS 12 /* bad argument to system call */ 28 | #define BSDSIGPIPE 13 /* write on a pipe with no one to read it */ 29 | #define BSDSIGALRM 14 /* alarm clock */ 30 | #define BSDSIGTERM 15 /* software termination signal from kill */ 31 | #define BSDSIGURG 16 /* urgent condition on IO channel */ 32 | #define BSDSIGSTOP 17 /* sendable stop signal not from tty */ 33 | #define BSDSIGTSTP 18 /* stop signal from tty */ 34 | #define BSDSIGCONT 19 /* continue a stopped process */ 35 | #define BSDSIGCHLD 20 /* to parent on child stop or exit */ 36 | #define BSDSIGTTIN 21 /* to readers pgrp upon background tty read */ 37 | #define BSDSIGTTOU 22 /* like TTIN for output if (tp->t_local<OSTOP) */ 38 | #define BSDSIGIO 23 /* input/output possible signal */ 39 | #define BSDSIGXCPU 24 /* exceeded CPU time limit */ 40 | #define BSDSIGXFSZ 25 /* exceeded file size limit */ 41 | #define BSDSIGVTALRM 26 /* virtual time alarm */ 42 | #define BSDSIGPROF 27 /* profiling time alarm */ 43 | #define BSDSIGWINCH 28 /* window size changes */ 44 | #define BSDSIGUSR1 30 /* user defined signal 1 */ 45 | #define BSDSIGUSR2 31 /* user defined signal 2 */ 46 | #define bsdsigismember(set, signo) ((*(set) & (1L << ((signo) - 1))) != 0) 47 | 48 | #define BSDSIG_ERR -1 49 | #define BSDSIG_DFL 0 50 | #define BSDSIG_IGN 1 51 | 52 | /* 53 | * Signal vector "template" used in sigaction call. 54 | */ 55 | struct bsd_sigaction { 56 | int16_t sig_handler; /* signal handler */ 57 | u_int32_t sa_mask; /* signal mask to apply */ 58 | int16_t sa_flags; /* see signal options below */ 59 | }; 60 | 61 | #define BSD_ONSTACK 0x0001 /* take signal on signal stack */ 62 | #define BSD_RESTART 0x0002 /* restart system on signal return */ 63 | #define BSD_DISABLE 0x0004 /* disable taking signals on alternate stack */ 64 | #define BSD_NOCLDSTOP 0x0008 /* do not generate SIGCHLD on child stop */ 65 | 66 | 67 | /* Translate 2.11BSD signal value to our value */ 68 | 69 | static int bsdsig[] = { 70 | 0, SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGIOT, SIGEMT, 71 | SIGFPE, SIGKILL, SIGBUS, SIGSEGV, SIGSYS, SIGPIPE, SIGALRM, 72 | SIGTERM, SIGURG, SIGSTOP, SIGTSTP, SIGCONT, SIGCHLD, SIGTTIN, 73 | SIGTTOU, SIGIO, SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, SIGWINCH, 74 | SIGUSR1, SIGUSR2 75 | }; 76 | 77 | /* We keep a set of struct sigactions 78 | * for each 2.11BSD signal 79 | */ 80 | struct bsd_sigaction Sigact[NBSDSIG]; 81 | 82 | 83 | /* Set all signals to their default value */ 84 | void set_bsdsig_dfl(void) 85 | { 86 | int i; 87 | 88 | for (i = 0; i < NBSDSIG; i++) { 89 | if (bsdsig[i]) 90 | signal(bsdsig[i], SIG_DFL); 91 | Sigact[i].sig_handler = BSDSIG_DFL; 92 | Sigact[i].sa_mask = Sigact[i].sa_flags = 0; 93 | } 94 | } 95 | 96 | int do_sigaction(int sig, int a, int oa) 97 | { 98 | int i; 99 | struct bsd_sigaction *act, *oact; 100 | struct sigaction ouraction; 101 | 102 | if ((sig < 0) || (sig >= NBSDSIG)) 103 | return (EINVAL); 104 | 105 | if (oa) { 106 | oact = (struct bsd_sigaction *) &dspace[oa]; 107 | memcpy(oact, &Sigact[sig], sizeof(struct bsd_sigaction)); 108 | } 109 | 110 | if (a) { 111 | act = (struct bsd_sigaction *) &dspace[a]; 112 | 113 | /* If required, map mask here */ 114 | /* Currently, the assumption is a 1-1 match */ 115 | sigemptyset(&(ouraction.sa_mask)); 116 | for (i = 1; i < NBSDSIG; i++) { 117 | if bsdsigismember 118 | (&(act->sa_mask), i) 119 | sigaddset(&(ouraction.sa_mask), i); 120 | } 121 | /* If required, map flags here */ 122 | ouraction.sa_flags = act->sa_flags; 123 | ouraction.sa_handler = sigcatcher; 124 | } 125 | 126 | i = sigaction(bsdsig[sig], &ouraction, NULL); 127 | if (i == -1) 128 | return (i); 129 | 130 | /* Else save the new sigaction */ 131 | act = (struct bsd_sigaction *) &dspace[a]; 132 | memcpy(&Sigact[sig], act, sizeof(struct bsd_sigaction)); 133 | return (i); 134 | } 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | /* For now, the rest commented out. One day I might 155 | * get around to implementing 2.11BSD signals properly 156 | */ 157 | 158 | #if 0 159 | int (*signal()) (); 160 | 161 | typedef unsigned long sigset_t; 162 | 163 | 164 | /* 165 | * Flags for sigprocmask: 166 | */ 167 | #define BSDSIG_BLOCK 1 /* block specified signal set */ 168 | #define BSDSIG_UNBLOCK 2 /* unblock specified signal set */ 169 | #define BSDSIG_SETMASK 3 /* set specified signal set */ 170 | 171 | typedef int (*sig_t) (); /* type of signal function */ 172 | 173 | /* 174 | * Structure used in sigaltstack call. 175 | */ 176 | struct sigaltstack { 177 | char *ss_base; /* signal stack base */ 178 | int ss_size; /* signal stack length */ 179 | int ss_flags; /* SA_DISABLE and/or SA_ONSTACK */ 180 | }; 181 | #define MINBSDSIGSTKSZ 128 /* minimum allowable stack */ 182 | #define BSDSIGSTKSZ (MINBSDSIGSTKSZ + 384) /* recommended stack size */ 183 | 184 | /* 185 | * 4.3 compatibility: 186 | * Signal vector "template" used in sigvec call. 187 | */ 188 | struct sigvec { 189 | int (*sv_handler) (); /* signal handler */ 190 | long sv_mask; /* signal mask to apply */ 191 | int sv_flags; /* see signal options below */ 192 | }; 193 | #define SV_ONSTACK SA_ONSTACK /* take signal on signal stack */ 194 | #define SV_INTERRUPT SA_RESTART /* same bit, opposite sense */ 195 | #define sv_onstack sv_flags /* isn't compatibility wonderful! */ 196 | 197 | /* 198 | * 4.3 compatibility: 199 | * Structure used in sigstack call. 200 | */ 201 | struct sigstack { 202 | char *ss_sp; /* signal stack pointer */ 203 | int ss_onstack; /* current status */ 204 | }; 205 | 206 | /* 207 | * Information pushed on stack when a signal is delivered. 208 | * This is used by the kernel to restore state following 209 | * execution of the signal handler. It is also made available 210 | * to the handler to allow it to properly restore state if 211 | * a non-standard exit is performed. 212 | */ 213 | struct sigcontext { 214 | int sc_onstack; /* sigstack state to restore */ 215 | long sc_mask; /* signal mask to restore */ 216 | int sc_sp; /* sp to restore */ 217 | int sc_fp; /* fp to restore */ 218 | int sc_r1; /* r1 to restore */ 219 | int sc_r0; /* r0 to restore */ 220 | int sc_pc; /* pc to restore */ 221 | int sc_ps; /* psl to restore */ 222 | int sc_ovno /* overlay to restore */ 223 | }; 224 | 225 | /* 226 | * Macro for converting signal number to a mask suitable for 227 | * sigblock(). 228 | */ 229 | #define sigmask(m) (1L << ((m)-1)) 230 | #define sigaddset(set, signo) (*(set) |= 1L << ((signo) - 1), 0) 231 | #define sigdelset(set, signo) (*(set) &= ~(1L << ((signo) - 1)), 0) 232 | #define sigemptyset(set) (*(set) = (sigset_t)0, (int)0) 233 | #define sigfillset(set) (*(set) = ~(sigset_t)0, (int)0) 234 | #define sigismember(set, signo) ((*(set) & (1L << ((signo) - 1))) != 0) 235 | 236 | #endif /* 0 */ 237 | -------------------------------------------------------------------------------- /itab.c: -------------------------------------------------------------------------------- 1 | /* itab.c - Instruction decode table. 2 | * 3 | * $Revision: 2.12 $ 4 | * $Date: 1999/12/27 10:19:40 $ 5 | */ 6 | 7 | #include "defines.h" 8 | 9 | static _itab sitab0[64] = { 10 | halt, waiti, illegal, bpt, iot, illegal, illegal, illegal, 11 | illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal, 12 | illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal, 13 | illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal, 14 | illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal, 15 | illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal, 16 | illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal, 17 | illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal 18 | }; 19 | 20 | static _itab sitab1[64] = { 21 | rts, rts, rts, rts, rts, rts, rts, rts, 22 | illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal, 23 | illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal, 24 | illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal, 25 | ccc, ccc, ccc, ccc, ccc, ccc, ccc, ccc, 26 | ccc, ccc, ccc, ccc, ccc, ccc, ccc, ccc, 27 | scc, scc, scc, scc, scc, scc, scc, scc, 28 | scc, scc, scc, scc, scc, scc, scc, scc 29 | }; 30 | 31 | void dositab0(void) 32 | { 33 | sitab0[ir & 077] (); 34 | } 35 | 36 | void dositab1(void) 37 | { 38 | sitab1[ir & 077] (); 39 | } 40 | 41 | _itab itab[1024] = { 42 | dositab0, jmp, dositab1, swabi, br, br, br, br, 43 | bne, bne, bne, bne, beq, beq, beq, beq, 44 | bge, bge, bge, bge, blt, blt, blt, blt, 45 | bgt, bgt, bgt, bgt, ble, ble, ble, ble, 46 | jsr, jsr, jsr, jsr, jsr, jsr, jsr, jsr, 47 | clr, com, inc, dec, neg, adc, sbc, tst, 48 | ror, rol, asr, asl, mark, mfpi, mtpi, sxt, 49 | illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal, 50 | movsreg, movsreg, movsreg, movsreg, movsreg, movsreg, movsreg, movsreg, 51 | movsreg1, movsreg1, movsreg1, movsreg1, movsreg1, movsreg1, movsreg1, 52 | movsreg1pc, 53 | mov, mov, mov, mov, mov, mov, mov, mov, 54 | mov, mov, mov, mov, mov, mov, mov, mov, 55 | mov, mov, mov, mov, mov, mov, mov, mov, 56 | mov, mov, mov, mov, mov, mov, mov, mov, 57 | mov, mov, mov, mov, mov, mov, mov, mov, 58 | mov, mov, mov, mov, mov, mov, mov, mov, 59 | cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp, 60 | cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp, 61 | cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp, 62 | cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp, 63 | cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp, 64 | cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp, 65 | cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp, 66 | cmp, cmp, cmp, cmp, cmp, cmp, cmp, cmp, 67 | bit, bit, bit, bit, bit, bit, bit, bit, 68 | bit, bit, bit, bit, bit, bit, bit, bit, 69 | bit, bit, bit, bit, bit, bit, bit, bit, 70 | bit, bit, bit, bit, bit, bit, bit, bit, 71 | bit, bit, bit, bit, bit, bit, bit, bit, 72 | bit, bit, bit, bit, bit, bit, bit, bit, 73 | bit, bit, bit, bit, bit, bit, bit, bit, 74 | bit, bit, bit, bit, bit, bit, bit, bit, 75 | bic, bic, bic, bic, bic, bic, bic, bic, 76 | bic, bic, bic, bic, bic, bic, bic, bic, 77 | bic, bic, bic, bic, bic, bic, bic, bic, 78 | bic, bic, bic, bic, bic, bic, bic, bic, 79 | bic, bic, bic, bic, bic, bic, bic, bic, 80 | bic, bic, bic, bic, bic, bic, bic, bic, 81 | bic, bic, bic, bic, bic, bic, bic, bic, 82 | bic, bic, bic, bic, bic, bic, bic, bic, 83 | bis, bis, bis, bis, bis, bis, bis, bis, 84 | bis, bis, bis, bis, bis, bis, bis, bis, 85 | bis, bis, bis, bis, bis, bis, bis, bis, 86 | bis, bis, bis, bis, bis, bis, bis, bis, 87 | bis, bis, bis, bis, bis, bis, bis, bis, 88 | bis, bis, bis, bis, bis, bis, bis, bis, 89 | bis, bis, bis, bis, bis, bis, bis, bis, 90 | bis, bis, bis, bis, bis, bis, bis, bis, 91 | add, add, add, add, add, add, add, add, 92 | add, add, add, add, add, add, add, add, 93 | add, add, add, add, add, add, add, add, 94 | add, add, add, add, add, add, add, add, 95 | add, add, add, add, add, add, add, add, 96 | add, add, add, add, add, add, add, add, 97 | add, add, add, add, add, add, add, add, 98 | add, add, add, add, add, add, add, add, 99 | mul, mul, mul, mul, mul, mul, mul, mul, 100 | divide, divide, divide, divide, divide, divide, divide, divide, 101 | ash, ash, ash, ash, ash, ash, ash, ash, 102 | ashc, ashc, ashc, ashc, ashc, ashc, ashc, ashc, 103 | xor, xor, xor, xor, xor, xor, xor, xor, 104 | illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal, 105 | illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal, 106 | sob, sob, sob, sob, sob, sob, sob, sob, 107 | bpl, bpl, bpl, bpl, bmi, bmi, bmi, bmi, 108 | bhi, bhi, bhi, bhi, blos, blos, blos, blos, 109 | bvc, bvc, bvc, bvc, bvs, bvs, bvs, bvs, 110 | bcc, bcc, bcc, bcc, bcs, bcs, bcs, bcs, 111 | 112 | /* emt at itab[544] to itab[547] */ 113 | /* trap at itab[548] to itab[551] */ 114 | 115 | emt, emt, emt, emt, trap, trap, trap, trap, 116 | clrb, comb, incb, decb, negb, adcb, sbcb, tstb, 117 | rorb, rolb, asrb, aslb, mtps, mfpd, mtpd, mfps, 118 | illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal, 119 | movb, movb, movb, movb, movb, movb, movb, movb, 120 | movb, movb, movb, movb, movb, movb, movb, movb, 121 | movb, movb, movb, movb, movb, movb, movb, movb, 122 | movb, movb, movb, movb, movb, movb, movb, movb, 123 | movb, movb, movb, movb, movb, movb, movb, movb, 124 | movb, movb, movb, movb, movb, movb, movb, movb, 125 | movb, movb, movb, movb, movb, movb, movb, movb, 126 | movb, movb, movb, movb, movb, movb, movb, movb, 127 | cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, 128 | cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, 129 | cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, 130 | cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, 131 | cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, 132 | cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, 133 | cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, 134 | cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, cmpb, 135 | bitb, bitb, bitb, bitb, bitb, bitb, bitb, bitb, 136 | bitb, bitb, bitb, bitb, bitb, bitb, bitb, bitb, 137 | bitb, bitb, bitb, bitb, bitb, bitb, bitb, bitb, 138 | bitb, bitb, bitb, bitb, bitb, bitb, bitb, bitb, 139 | bitb, bitb, bitb, bitb, bitb, bitb, bitb, bitb, 140 | bitb, bitb, bitb, bitb, bitb, bitb, bitb, bitb, 141 | bitb, bitb, bitb, bitb, bitb, bitb, bitb, bitb, 142 | bitb, bitb, bitb, bitb, bitb, bitb, bitb, bitb, 143 | bicb, bicb, bicb, bicb, bicb, bicb, bicb, bicb, 144 | bicb, bicb, bicb, bicb, bicb, bicb, bicb, bicb, 145 | bicb, bicb, bicb, bicb, bicb, bicb, bicb, bicb, 146 | bicb, bicb, bicb, bicb, bicb, bicb, bicb, bicb, 147 | bicb, bicb, bicb, bicb, bicb, bicb, bicb, bicb, 148 | bicb, bicb, bicb, bicb, bicb, bicb, bicb, bicb, 149 | bicb, bicb, bicb, bicb, bicb, bicb, bicb, bicb, 150 | bicb, bicb, bicb, bicb, bicb, bicb, bicb, bicb, 151 | bisb, bisb, bisb, bisb, bisb, bisb, bisb, bisb, 152 | bisb, bisb, bisb, bisb, bisb, bisb, bisb, bisb, 153 | bisb, bisb, bisb, bisb, bisb, bisb, bisb, bisb, 154 | bisb, bisb, bisb, bisb, bisb, bisb, bisb, bisb, 155 | bisb, bisb, bisb, bisb, bisb, bisb, bisb, bisb, 156 | bisb, bisb, bisb, bisb, bisb, bisb, bisb, bisb, 157 | bisb, bisb, bisb, bisb, bisb, bisb, bisb, bisb, 158 | bisb, bisb, bisb, bisb, bisb, bisb, bisb, bisb, 159 | sub, sub, sub, sub, sub, sub, sub, sub, 160 | sub, sub, sub, sub, sub, sub, sub, sub, 161 | sub, sub, sub, sub, sub, sub, sub, sub, 162 | sub, sub, sub, sub, sub, sub, sub, sub, 163 | sub, sub, sub, sub, sub, sub, sub, sub, 164 | sub, sub, sub, sub, sub, sub, sub, sub, 165 | sub, sub, sub, sub, sub, sub, sub, sub, 166 | sub, sub, sub, sub, sub, sub, sub, sub, 167 | fpset, ldfps, stfps, stst, clrf, tstf, absf, negf, 168 | mulf, mulf, mulf, mulf, moddf, moddf, moddf, moddf, 169 | addf, addf, addf, addf, ldf, ldf, ldf, ldf, 170 | subf, subf, subf, subf, cmpf, cmpf, cmpf, cmpf, 171 | stf, stf, stf, stf, divf, divf, divf, divf, 172 | stexp, stexp, stexp, stexp, stcfi, stcfi, stcfi, stcfi, 173 | stcdf, stcdf, stcdf, stcdf, ldexpp, ldexpp, ldexpp, ldexpp, 174 | lcdif, lcdif, lcdif, lcdif, ldcdf, ldcdf, ldcdf, ldcdf 175 | }; 176 | -------------------------------------------------------------------------------- /apout.1: -------------------------------------------------------------------------------- 1 | .\" Copyright Warren Toomey 2 | .\" 3 | .\" $Revision: 1.10 $ 4 | .\" $Date: 2008/05/15 03:20:52 $ 5 | .\" 6 | .Dd December, 2000 7 | .Dt APOUT 1 8 | .Os 9 | .Sh NAME 10 | .Nm apout 11 | .Nd run PDP-11 UNIX a.out binaries 12 | .Sh SYNOPSIS 13 | .Nm apout 14 | .Op Fl inst 15 | .Op Fl trap 16 | .Op Fl jsr 17 | .Op Fl fp 18 | .Ar file 19 | .Op Ar arguments ... 20 | .Sh DESCRIPTION 21 | .Nm apout 22 | runs the 23 | .Ar file 24 | which contains a PDP-11 UNIX a.out binary from one of the following 25 | versions of UNIX: 1st Edition, 2nd Edition, 5th Edition, 6th Edition, 26 | 7th Edition, 2.9BSD or 2.11BSD. Any arguments after the named 27 | .Ar file 28 | are passed as arguments to the a.out binary. 29 | .Pp 30 | User-mode PDP-11 instructions are interpreted and executed by 31 | .Nm apout, 32 | and system calls made by the interpreted a.out binary are performed 33 | by making real systems calls to the underlying native operating system. 34 | In this way, the interpreted a.out binary can interact with the real 35 | files and processes on the system. 36 | .Pp 37 | If 38 | .Nm apout 39 | has been compiled with debugging enabled, the following options are available: 40 | .Bl -tag -width trap 41 | .It Fl inst 42 | Output a line for each instruction emulated which gives: 43 | the PC in octal, the instruction in octal, the instruction's name, 44 | r0 to r6 in octal, and the values of the N, Z, V and C flags. 45 | .It Fl trap 46 | Output a line for each system call, which gives the name of the system 47 | call, possibly a list of arguments, and the value returned by the system 48 | call. 49 | .It Fl jsr 50 | Output a line for each 51 | .Ar jsr 52 | or 53 | .Ar rts 54 | giving the value of the new PC. For 2.11BSD overlay binaries, also output 55 | a line describing each overlay change. 56 | .It Fl fp 57 | For many of the emulated floating-point instructions, output a line 58 | describing the operation. 59 | .El 60 | .Pp 61 | If 62 | .Nm apout 63 | was not compiled with debugging enabled, none of these options exist. 64 | Any debugging output is directed to the file 65 | .Ar apout.dbg 66 | in the directory where 67 | .Nm apout 68 | was started. The debugging output is primarily designed to aid the 69 | developers of 70 | .Nm apout, 71 | and so it isn't exhaustive for all instructions, traps or floating-point 72 | operations. 73 | .Sh ENVIRONMENT VARIABLES 74 | .Nm apout 75 | requires one environment variable to be set: 76 | .Ev APOUT_ROOT. 77 | This variable names the `root' of the emulated filesystem. 78 | .Pp 79 | When 80 | .Nm apout 81 | works with filenames, if the filenames are relative, then they 82 | stay relative i.e all files on the system can be named, as long as they are 83 | given relative names. However, if the filenames are absolute, i.e they 84 | start with a slash, then 85 | .Nm apout 86 | prepends the value of the environment variable 87 | .Ev APOUT_ROOT 88 | to the filename. Therefore, if you have the 7th Edition files located in 89 | .Ar /usr/misc/v7root 90 | and you do: 91 | .Bd -literal 92 | % setenv APOUT_ROOT /usr/misc/v7root 93 | % apout $APOUT_ROOT/bin/sh 94 | $ 95 | .Ed 96 | .Pp 97 | then you will be greeted with the 7th Edition Bourne shell prompt as shown: 98 | you will still be in the directory where you started 99 | .Nm apout, 100 | but if you cd to /, then you will be taken to 101 | .Ar /usr/misc/v7root 102 | .Pp 103 | Note that you must set 104 | .Ev APOUT_ROOT 105 | before you can run 106 | .Nm apout. 107 | .Pp 108 | There is one other optional environment variable: 109 | .Ev APOUT_UNIX_VERSION. 110 | This is mainly required for UNIX binaries that use the 0407 header, 111 | which was used across several versions of UNIX, each with a different set 112 | of system calls. If APOUT_UNIX_VERSION is set, 113 | .Nm apout 114 | will use the given version when it cannot determine which version of UNIX a 115 | binary belongs to. The available values are "V1", "V2", "V3", "V4", "V5", "V6", 116 | "V7", "2.9BSD" and "2.11BSD". 117 | .Pp 118 | .Sh EMULATED ENVIRONMENT VARIABLES 119 | Initially, PDP-11 binaries run via 120 | .Nm apout 121 | receive the following set of emulated environment variables: 122 | .Bd -literal 123 | PATH /bin:/usr/bin:/usr/sbin:/usr/ucb:/usr/games:/usr/local/bin:. 124 | HOME / 125 | TERM vt100 126 | .Ed 127 | .Pp 128 | Emulated programs can, of course, change this emulated environment; 129 | they can also fork and exec other PDP-11 binaries, which will inherit the 130 | modified emulated environment. 131 | .Sh INTERACTION WITH NATIVE PROGRAMS 132 | Binaries that are interpreted by 133 | .Nm apout 134 | can interact with native programs in several ways: through files in the 135 | filesystem, and through pipes. For example, you can do the following: 136 | .Bd -literal 137 | % ls -lR | apout $APOUT_ROOT/bin/wc | lpr 138 | % apout $APOUT_ROOT/bin/sort < file | uniq > newfile 139 | .Ed 140 | .Pp 141 | where 142 | .Ar ls, 143 | .Ar lpr 144 | and 145 | .Ar uniq 146 | are native programs. 147 | .Pp 148 | If 149 | .Nm apout 150 | is compiled with the NATIVES preprocessor directive enabled, then native system 151 | binaries can be executed as well as PDP-11 binaries. For example: 152 | .Bd -literal 153 | % cd $APOUT_ROOT 154 | % ln -s `which vi` bin/vi Add vi into the filespace 155 | % apout bin/sh 156 | $ ls -l Run the PDP-11 ls 157 | .... 158 | $ vi kim.c Run the native vi 159 | $ cc -o kim kim.c Compile with the PDP-11 compiler 160 | .Ed 161 | .Pp 162 | Note that native executable receive the same environment variables inherited 163 | by the 164 | .Nm apout 165 | process, and not the emulated environment that 166 | .Nm apout 167 | passes to emulated executables. 168 | .Sh ERROR MESSAGES 169 | So as to distinguish from error messages generated by the interpreted PDP-11 170 | binaries, 171 | .Nm apout 172 | prepends the word `Apout' to the beginning of its error messages. Below is 173 | the list of error messages that 174 | .Nm apout 175 | can generate: 176 | .Bd -ragged 177 | Apout - V1 sectosixty too big 178 | Apout - can't malloc overlay! 179 | Apout - can't switch to empty overlay %d 180 | Apout - could not read 1st line of script 181 | Apout - couldn't load %s 182 | Apout - open_dir couldn't open %s 183 | Apout - out of argv space in script 184 | Apout - pid %d bad FP register used at PC 0%o 185 | Apout - pid %d bpt instruction at PC 0%o 186 | Apout - pid %d bus error at PC 0%06o 187 | Apout - pid %d emt instruction at PC 0%o 188 | Apout - pid %d halt instruction at PC 0%o 189 | Apout - pid %d illegal instruction %o at PC 0%o 190 | Apout - pid %d iot instruction at PC 0%o 191 | Apout - pid %d mark instruction at PC 0%o 192 | Apout - pid %d mfpd instruction at PC 0%o 193 | Apout - pid %d mtpd instruction at PC 0%o 194 | Apout - pid %d segmentation fault at PC 0%06o 195 | Apout - pid %d trap instruction at PC 0%o 196 | Apout - pid %d unimplemented instruction at PC 0%o 197 | Apout - pid %d unknown KE11 register 0%o 198 | Apout - pid %d waiti instruction at PC 0%o 199 | Apout - the %s syscall is not yet implemented 200 | Apout - the 2.11BSD %s syscall is not yet implemented 201 | Apout - unknown a.out format 0%o 202 | Apout - unknown magic in header: 0x%x 203 | Apout - unknown syscall %d at PC 0%o 204 | Apout cannot set the environment for the a.out %s 205 | Apout not compiled to support 1st Edition binaries 206 | Apout not compiled to support 2nd Edition binaries 207 | Apout not compiled to support 2.11BSD binaries 208 | .Ed 209 | .Sh CAVEATS 210 | As far as is known, the emulation of user-mode integer instructions is correct. 211 | The emulation of floating-point instructions is seriously deficient: 212 | only 32-bit floats are emulated: the extra 32-bits of precision in PDP-11 213 | doubles goes unused. None of the FP errors are emulated. 214 | .Pp 215 | The emulation of each of the emulated UNIX environments is mostly, 216 | but not fully, complete. Any UNIX system call environment is very 217 | sophisticated, and 218 | .Ar apout 219 | must translate from the emulated UNIX environment to the native one, and 220 | back. For an authorative description of what is missing from, or deficient 221 | in, each of the emulated UNIX environments, see the source files 222 | .Ar v1trap.c, 223 | .Ar v7trap.c 224 | and 225 | .Ar bsdtrap.c 226 | in the source directory for 227 | .Nm apout. 228 | You should also consult the file 229 | .Ar LIMITATIONS 230 | in the source directory for 231 | .Nm apout. 232 | .Sh SEE ALSO 233 | The latest source for 234 | .Nm apout 235 | can be obtained via anonymous ftp at minnie.tuhs.org in the directory 236 | pub/PDP-11/Sims/Apout. The directory pub/PDP-11/Sims/Apout/UnixBins 237 | contains tar archives of a.out binaries from several versions of UNIX. 238 | Information on PDP-11 UNIX can be found on the PUPS web page at 239 | http://minnie.tuhs.org/PUPS/ 240 | .Sh HISTORY 241 | The first version of 242 | .Nm apout 243 | appeared in 1995, and provided support for 6th and 7th Edition 244 | UNIX binaries. In 1998/1999, support was added for 2.11BSD binaries. 245 | In 1999/2000, support was added for 1st and 2nd Edition UNIX binaries. 246 | -------------------------------------------------------------------------------- /ke11a.c: -------------------------------------------------------------------------------- 1 | /* ke11a.c - this holds the emulation of the PDP 11/20 extended 2 | * arithmetic element. We only need this for 1st Edition a.out support. 3 | * Code kindly borrowed from the eae support written by Tim Shoppa 4 | * (shoppa@trailing-edge.com) for Bob Supnik's PDP-11 emulator. 5 | * 6 | * $Revision: 1.7 $ 7 | * $Date: 1999/12/28 03:57:31 $ 8 | */ 9 | #ifdef EMUV1 10 | #include "defines.h" 11 | #include 12 | 13 | void eae_wr(u_int16_t data, u_int16_t PA, int32_t access); 14 | void set_SR(void); 15 | 16 | /* I/O dispatch routine, I/O addresses 177300 - 177316 */ 17 | 18 | #define eae_DIV 0177300 /* Divide */ 19 | #define eae_AC 0177302 /* Accumulator */ 20 | #define eae_MQ 0177304 /* MQ */ 21 | #define eae_MUL 0177306 /* Multiply */ 22 | #define eae_SC 0177310 /* Step counter */ 23 | #define eae_SR 0177311 /* Status register */ 24 | #define eae_NOR 0177312 /* Normalize */ 25 | #define eae_LSH 0177314 /* Logical shift */ 26 | #define eae_ASH 0177316 /* Arithmetic shift */ 27 | #define WRITEB 1 /* Write of a byte */ 28 | #define WRITEW 2 /* Write of a word */ 29 | 30 | /* The MQ, AC, SC, and SR registers specify the state of the EAE */ 31 | /* Here we define them as int32's, though in real life the MQ and AC */ 32 | /* are 16 bits and the SC and SR are 8 bits */ 33 | 34 | int32_t MQ; /* Multiply quotient */ 35 | int32_t AC; /* Accumulator */ 36 | int32_t SC = 0; /* Shift counter */ 37 | int32_t SR; /* Status register */ 38 | 39 | 40 | /* Load a word from one of the KE11 registers */ 41 | int16_t kell_word(u_int16_t addr) 42 | { 43 | int16_t data; 44 | int pid; 45 | 46 | switch (addr) { 47 | case eae_DIV: 48 | data = 0; 49 | break; 50 | case eae_MQ: 51 | data = MQ; 52 | break; 53 | case eae_AC: /* high 16 bits of MQ */ 54 | data = AC; 55 | break; 56 | case eae_SC: 57 | set_SR(); 58 | data = (SR << 8) | SC; 59 | break; 60 | case eae_SR: 61 | set_SR(); 62 | data = (SR << 8); 63 | break; 64 | case eae_NOR: 65 | data = SC; 66 | break; 67 | case eae_LSH: 68 | case eae_ASH: 69 | case eae_MUL: 70 | data = 0; 71 | break; 72 | default: 73 | pid = getpid(); 74 | (void) fprintf(stderr, 75 | "Apout - pid %d unknown KE11 register 0%o\n", 76 | pid, addr); 77 | exit(EXIT_FAILURE); 78 | } 79 | return data; 80 | } 81 | 82 | /* Load a byte from one of the KE11 registers */ 83 | int8_t kell_byte(u_int16_t addr) 84 | { 85 | if (addr & 1) 86 | printf("Hmm, KE11 access on 0%o\n", addr); 87 | return ((int8_t) kell_word(addr)); 88 | } 89 | 90 | /* Save a word to one of the KE11 registers */ 91 | void kesl_word(u_int16_t addr, u_int16_t word) 92 | { 93 | eae_wr(word, addr, WRITEW); 94 | } 95 | 96 | /* Save a byte to one of the KE11 registers */ 97 | void kesl_byte(u_int16_t addr, u_int8_t byte) 98 | { 99 | eae_wr(byte, addr, WRITEB); 100 | } 101 | 102 | void eae_wr(u_int16_t data, u_int16_t PA, int32_t access) 103 | { 104 | int32_t divisor, quotient, remainder; 105 | int32_t dividend, product; 106 | int32_t oldMQ; 107 | int pid; 108 | 109 | switch (PA) { 110 | case eae_DIV: 111 | SC = 0; 112 | dividend = (AC << 16) | MQ; 113 | divisor = data; 114 | if (divisor >> 15) 115 | divisor = divisor | ~077777; 116 | quotient = dividend / divisor; 117 | MQ = quotient & 0177777; 118 | remainder = dividend % divisor; 119 | AC = remainder & 0177777; 120 | SR = SR & 076; 121 | if ((quotient > 32767) || (quotient < -32768)) { /* did we overflow? */ 122 | if (dividend < 0) 123 | SR = SR | 0100; 124 | else 125 | SR = SR | 0200; 126 | } else { 127 | if (quotient < 0) 128 | SR = SR | 0300; 129 | } 130 | return; 131 | case eae_AC: 132 | AC = data; 133 | if ((access == WRITEB) & (data >> 7)) 134 | AC = AC | 0177400; 135 | return; 136 | case eae_AC + 1: 137 | printf("write to AC+1; data=%o", data); 138 | AC = (AC & 0377) | (data << 8); 139 | return; 140 | case eae_MQ: 141 | MQ = data; 142 | if ((access == WRITEB) & (data >> 7)) 143 | MQ = MQ | 0177400; 144 | if (MQ >> 15) 145 | AC = 0177777; 146 | else 147 | AC = 0; 148 | return; 149 | case eae_MQ + 1: 150 | printf("write to MQ+1; data=%o", data); 151 | MQ = (MQ & 0377) | (data << 8); 152 | if (MQ >> 15) 153 | AC = 0177777; 154 | else 155 | AC = 0; 156 | return; 157 | case eae_MUL: 158 | SC = 0; 159 | if (data >> 15) 160 | data = data | ~077777; 161 | if (MQ >> 15) 162 | MQ = MQ | ~077777; 163 | product = MQ * data; 164 | MQ = product & 0177777; 165 | AC = (product >> 16) & 0177777; 166 | SR = SR & 076; 167 | if (AC >> 15) 168 | SR = SR | 0300; /* set sign bit if necessary */ 169 | return; 170 | case eae_SC: 171 | if (access == WRITEB) 172 | return; /* byte writes are no-ops */ 173 | SR = (data >> 8) & 0177777; 174 | SC = data & 0000077; 175 | return; 176 | case eae_SR: 177 | return; /* this is a No-op */ 178 | case eae_NOR: /* Normalize */ 179 | MQ = (AC << 16) | MQ; /* 32-bit number to normalize in MQ */ 180 | for (SC = 0; SC < 31; SC++) { 181 | if (MQ == (0140000 << 16)) 182 | break; 183 | if ((((MQ >> 30) & 3) == 1) || (((MQ >> 30) & 3) == 2)) 184 | break; 185 | MQ = MQ << 1; 186 | } 187 | printf("SC = %o\r\n", SC); 188 | AC = (MQ >> 16) & 0177777; 189 | MQ = MQ & 0177777; 190 | return; 191 | case eae_LSH: /* Logical shift */ 192 | MQ = (AC << 16) | MQ; /* Form a temporary 32-bit entity */ 193 | oldMQ = MQ & 0x80000000; /* Save the sign bit for later */ 194 | SR = SR & 0176; /* Clear overflow & carry bits */ 195 | data = data & 077; /* Convert data from 6-bit */ 196 | if (data > 31) { 197 | data = 64 - data; /* Shift in a -ve direction */ 198 | SR = SR | ((MQ >> (data - 1)) & 1); /* Get the bit that went off the end */ 199 | MQ = MQ >> data; /* and do the right shift */ 200 | } else { /* Else left shift */ 201 | if ((MQ << (data - 1)) & 0x80000000) 202 | SR |= 1; /* Get the bit off the end */ 203 | MQ = MQ << data; /* and do the left shift */ 204 | } 205 | oldMQ = oldMQ ^ MQ; /* Any difference in sign bit? */ 206 | if (oldMQ & 0x80000000) 207 | SR |= 0200; /* Yes, set the overflow bit */ 208 | AC = (MQ >> 16) & 0177777; /* Save result in AC and MQ */ 209 | MQ = MQ & 0177777; 210 | set_SR(); 211 | return; 212 | 213 | case eae_ASH: /* Arithmetic shift */ 214 | MQ = (AC << 16) | MQ; /* Form a temporary 32-bit entity */ 215 | oldMQ = MQ & 0x80000000; /* Save the sign bit for later */ 216 | SR = SR & 0176; /* Clear overflow & carry bits */ 217 | data = data & 077; /* Convert data from 6-bit */ 218 | if (data > 31) { 219 | data = 64 - data; /* Shift in a -ve direction */ 220 | divisor = 1 << data; /* Work out the dividing factor */ 221 | SR = SR | ((MQ >> (data - 1)) & 1); /* Get the bit that went off the end */ 222 | MQ = MQ / divisor; /* and do the right shift */ 223 | } else { /* Else left shift */ 224 | product = 1 << data; /* Work out the multiplying factor */ 225 | if ((MQ << (data - 1)) & 0x80000000) 226 | SR |= 1; /* Get the bit off the end */ 227 | MQ = MQ * product; /* and do the left shift */ 228 | } 229 | oldMQ = oldMQ ^ MQ; /* Any difference in sign bit? */ 230 | if (oldMQ & 0x80000000) 231 | SR |= 0200; /* Yes, set the overflow bit */ 232 | AC = (MQ >> 16) & 0177777; /* Save result in AC and MQ */ 233 | MQ = MQ & 0177777; 234 | set_SR(); 235 | return; 236 | 237 | default: 238 | pid = getpid(); 239 | (void) fprintf(stderr, 240 | "Apout - pid %d unknown KE11 register 0%o\n", 241 | pid, PA); 242 | exit(EXIT_FAILURE); 243 | } 244 | } 245 | 246 | void set_SR(void) 247 | { 248 | SR = SR & 0301; /* clear the result bits we can set here */ 249 | if (((MQ & 0100000) == 0) && (AC == 0)) 250 | SR = SR | 002; 251 | if (((MQ & 0100000) == 0100000) && (AC == 0177777)) 252 | SR = SR | 002; 253 | 254 | if ((AC == 0) && (MQ == 0)) 255 | SR = SR | 0004; 256 | if (MQ == 0) 257 | SR = SR | 0010; 258 | if (AC == 0) 259 | SR = SR | 0020; 260 | if (AC == 0177777) 261 | SR = SR | 0040; 262 | } 263 | #endif /* EMUV1 */ 264 | -------------------------------------------------------------------------------- /cpu.c: -------------------------------------------------------------------------------- 1 | /* cpu.c - this holds the main loop for the emulator, plus generic 2 | * functions to deal with exceptional instructions and events 3 | * 4 | * $Revision: 1.26 $ 5 | * $Date: 2008/05/15 07:52:45 $ 6 | */ 7 | #include "defines.h" 8 | #include 9 | 10 | u_int8_t *ispace, *dspace; /* Instruction and Data spaces */ 11 | u_int16_t dwrite_base = 2; /* Lowest addr where dspace writes can occur */ 12 | 13 | u_int16_t regs[8]; /* general registers */ 14 | u_int16_t ir; /* current instruction register */ 15 | u_int16_t *adptr; /* used in memory access macros */ 16 | u_int16_t ea_addr; /* stored address for dest modifying insts */ 17 | 18 | int CC_N = 0; /* The processor status word is represented */ 19 | int CC_Z = 0; /* by these four values. On some */ 20 | int CC_V = 0; /* architectures, you may get a performance */ 21 | int CC_C = 0; /* increase by using shorts or bytes */ 22 | 23 | u_int16_t dstword; /* These globals are used in the effective */ 24 | u_int16_t srcword; /* address calculations, mainly to save */ 25 | u_int16_t tmpword; /* parameter passing overheads in */ 26 | u_int8_t dstbyte; /* function calls */ 27 | u_int8_t srcbyte; 28 | u_int8_t tmpbyte; 29 | struct our_siglist *Sighead = NULL; /* List of pending signals */ 30 | struct our_siglist *Sigtail = NULL; /* List of pending signals */ 31 | void (*sigrunner) (void) = NULL; /* F'n that will run the signal */ 32 | 33 | #ifdef DEBUG 34 | extern char *iname[1024]; 35 | extern char *iname0[64]; /* Name of each instruction */ 36 | extern char *iname1[64]; 37 | char *name; 38 | #endif 39 | 40 | 41 | /* Run until told to stop. */ 42 | void run() 43 | { 44 | #ifdef DEBUG 45 | int i; 46 | 47 | if (trap_debug) { 48 | TrapDebug((dbg_file, "Just starting to run pid %d\n", 49 | (int) getpid())); 50 | TrapDebug((dbg_file, "Regs are ")); 51 | for (i = 0; i <= PC; i++) 52 | TrapDebug((dbg_file, "%06o ", regs[i])); 53 | TrapDebug((dbg_file, "\n")); 54 | } 55 | #endif 56 | 57 | while (1) { 58 | 59 | /* Fetch and execute the instruction. */ 60 | 61 | #ifdef DEBUG 62 | lli_word(regs[PC], ir); 63 | if (inst_debug) { 64 | i = ir >> 6; 65 | switch (i) { 66 | case 0: 67 | name = iname0[ir & 077]; 68 | break; 69 | case 2: 70 | name = iname1[ir & 077]; 71 | break; 72 | default: 73 | name = iname[i]; 74 | } 75 | TrapDebug((dbg_file, "%06o %06o %4s ", regs[7], ir, name)); 76 | TrapDebug((dbg_file, "%06o %06o %06o %06o %06o %06o %06o ", 77 | regs[0], regs[1], regs[2], regs[3], 78 | regs[4], regs[5], regs[6])); 79 | TrapDebug((dbg_file, "NZVC1 %d%d%d%d\n", CC_N, CC_Z, CC_V, 80 | CC_C)); 81 | fflush(dbg_file); 82 | } 83 | regs[PC] += 2; 84 | itab[ir >> 6] (); 85 | if ((Sighead != NULL) && (sigrunner != NULL)) 86 | (void) (*sigrunner) (); 87 | #else 88 | /* When not debugging, we can manually unroll this inner loop */ 89 | lli_word(regs[PC], ir); 90 | regs[PC] += 2; 91 | itab[ir >> 6] (); 92 | lli_word(regs[PC], ir); 93 | regs[PC] += 2; 94 | itab[ir >> 6] (); 95 | lli_word(regs[PC], ir); 96 | regs[PC] += 2; 97 | itab[ir >> 6] (); 98 | lli_word(regs[PC], ir); 99 | regs[PC] += 2; 100 | itab[ir >> 6] (); 101 | lli_word(regs[PC], ir); 102 | regs[PC] += 2; 103 | itab[ir >> 6] (); 104 | lli_word(regs[PC], ir); 105 | regs[PC] += 2; 106 | itab[ir >> 6] (); 107 | lli_word(regs[PC], ir); 108 | regs[PC] += 2; 109 | itab[ir >> 6] (); 110 | lli_word(regs[PC], ir); 111 | regs[PC] += 2; 112 | itab[ir >> 6] (); 113 | lli_word(regs[PC], ir); 114 | regs[PC] += 2; 115 | itab[ir >> 6] (); 116 | lli_word(regs[PC], ir); 117 | regs[PC] += 2; 118 | itab[ir >> 6] (); 119 | lli_word(regs[PC], ir); 120 | regs[PC] += 2; 121 | itab[ir >> 6] (); 122 | lli_word(regs[PC], ir); 123 | regs[PC] += 2; 124 | itab[ir >> 6] (); 125 | lli_word(regs[PC], ir); 126 | regs[PC] += 2; 127 | itab[ir >> 6] (); 128 | lli_word(regs[PC], ir); 129 | regs[PC] += 2; 130 | itab[ir >> 6] (); 131 | lli_word(regs[PC], ir); 132 | regs[PC] += 2; 133 | itab[ir >> 6] (); 134 | lli_word(regs[PC], ir); 135 | regs[PC] += 2; 136 | itab[ir >> 6] (); 137 | lli_word(regs[PC], ir); 138 | regs[PC] += 2; 139 | itab[ir >> 6] (); 140 | lli_word(regs[PC], ir); 141 | regs[PC] += 2; 142 | itab[ir >> 6] (); 143 | lli_word(regs[PC], ir); 144 | regs[PC] += 2; 145 | itab[ir >> 6] (); 146 | lli_word(regs[PC], ir); 147 | regs[PC] += 2; 148 | itab[ir >> 6] (); 149 | if ((Sighead != NULL) && (sigrunner != NULL)) 150 | (void) (*sigrunner) (); 151 | #endif 152 | } 153 | } 154 | 155 | /* sim_init() - Initialize the cpu registers. */ 156 | void sim_init() 157 | { 158 | int x; 159 | 160 | for (x = 0; x < 8; ++x) { 161 | regs[x] = 0; 162 | } 163 | ir = 0; 164 | CLR_CC_ALL(); 165 | } 166 | 167 | void bus_error(int signo) 168 | { 169 | TrapDebug((dbg_file, "Apout - pid %d bus error at PC 0%06o\n", 170 | (int) getpid(), regs[PC])); 171 | TrapDebug((dbg_file, "%06o ", ir)); 172 | TrapDebug((dbg_file, "%o %o %o %o %o %o %o %o ", 173 | regs[0], regs[1], regs[2], regs[3], 174 | regs[4], regs[5], regs[6], regs[7])); 175 | TrapDebug((dbg_file, "NZVC2 are %d%d%d%d\n", CC_N, CC_Z, CC_V, CC_C)); 176 | exit(EXIT_FAILURE); 177 | } 178 | 179 | void seg_fault() 180 | { 181 | TrapDebug((dbg_file, "Apout - pid %d segmentation fault at PC 0%06o\n", 182 | (int) getpid(), regs[PC])); 183 | TrapDebug((dbg_file, "%06o ", ir)); 184 | TrapDebug((dbg_file, "%o %o %o %o %o %o %o %o ", 185 | regs[0], regs[1], regs[2], regs[3], 186 | regs[4], regs[5], regs[6], regs[7])); 187 | TrapDebug((dbg_file, "NZVC3 are %d%d%d%d\n", CC_N, CC_Z, CC_V, CC_C)); 188 | exit(EXIT_FAILURE); 189 | } 190 | 191 | void waiti() 192 | { 193 | TrapDebug((stderr, "Apout - pid %d waiti instruction at PC 0%o\n", 194 | (int) getpid(), regs[PC])); 195 | exit(EXIT_FAILURE); 196 | } 197 | 198 | void halt() 199 | { 200 | TrapDebug((stderr, "Apout - pid %d halt instruction at PC 0%o\n", 201 | (int) getpid(), regs[PC])); 202 | exit(EXIT_FAILURE); 203 | } 204 | 205 | void iot() 206 | { 207 | TrapDebug((stderr, "Apout - pid %d iot instruction at PC 0%o\n", 208 | (int) getpid(), regs[PC])); 209 | exit(EXIT_FAILURE); 210 | } 211 | 212 | void emt() 213 | { 214 | TrapDebug((stderr, "Apout - pid %d emt instruction at PC 0%o\n", 215 | (int) getpid(), regs[PC])); 216 | exit(EXIT_FAILURE); 217 | } 218 | 219 | void bpt() 220 | { 221 | TrapDebug((stderr, "Apout - pid %d bpt instruction at PC 0%o\n", 222 | (int) getpid(), regs[PC])); 223 | exit(EXIT_FAILURE); 224 | } 225 | 226 | void illegal() 227 | { 228 | TrapDebug((stderr, "Apout - pid %d illegal instruction %o at PC 0%o\n", 229 | (int) getpid(), ir, regs[PC])); 230 | exit(EXIT_FAILURE); 231 | } 232 | 233 | void not_impl() 234 | { 235 | TrapDebug((stderr, 236 | "Apout - pid %d unimplemented instruction at PC 0%o\n", 237 | (int) getpid(), regs[PC])); 238 | exit(EXIT_FAILURE); 239 | } 240 | 241 | void mark() 242 | { 243 | TrapDebug((stderr, "Apout - pid %d mark instruction at PC 0%o\n", 244 | (int) getpid(), regs[PC])); 245 | exit(EXIT_FAILURE); 246 | } 247 | 248 | void mfpd() 249 | { 250 | TrapDebug((stderr, "Apout - pid %d mfpd instruction at PC 0%o\n", 251 | (int) getpid(), regs[PC])); 252 | exit(EXIT_FAILURE); 253 | } 254 | 255 | void mtpd() 256 | { 257 | TrapDebug((stderr, "Apout - pid %d mtpd instruction at PC 0%o\n", 258 | (int) getpid(), regs[PC])); 259 | exit(EXIT_FAILURE); 260 | } 261 | 262 | void trap() 263 | { 264 | TrapDebug((stderr, "Apout - pid %d trap instruction at PC 0%o\n", 265 | (int) getpid(), regs[PC])); 266 | exit(EXIT_FAILURE); 267 | } 268 | 269 | void bad_FP_reg() 270 | { 271 | TrapDebug((stderr, "Apout - pid %d bad FP register used at PC 0%o\n", 272 | (int) getpid(), regs[PC])); 273 | exit(EXIT_FAILURE); 274 | } 275 | 276 | /* This is the generic function which catches 277 | * a signal, and appends it to the queue. 278 | */ 279 | void sigcatcher(int sig) 280 | { 281 | struct our_siglist *this; 282 | 283 | this = (struct our_siglist *) malloc(sizeof(struct our_siglist)); 284 | if (this == NULL) 285 | return; 286 | 287 | TrapDebug((dbg_file, "Caught signal %d\n", sig)); 288 | 289 | this->sig = sig; 290 | this->next = NULL; 291 | if (Sighead == NULL) { 292 | Sighead = Sigtail = this; 293 | } else { 294 | Sigtail->next = this; 295 | Sigtail = this; 296 | } 297 | } 298 | -------------------------------------------------------------------------------- /branch.c: -------------------------------------------------------------------------------- 1 | /* branch.c - Branch instructions, and instructions which are complex to do 2 | * 3 | * $Revision: 2.22 $ 4 | * $Date: 1999/12/27 04:38:29 $ 5 | */ 6 | #include "defines.h" 7 | 8 | /* We use the following macro for the branch instructions below */ 9 | 10 | #define do_branch() \ 11 | { offset = LOW8(ir); \ 12 | if (offset & SIGN_B) \ 13 | offset += 0177400; \ 14 | regs[PC] += (offset * 2); \ 15 | } \ 16 | 17 | static u_int16_t offset; 18 | 19 | void bne() 20 | { 21 | if (CC_Z == 0) 22 | do_branch(); 23 | } 24 | 25 | void beq() 26 | { 27 | if (CC_Z == 1) 28 | do_branch(); 29 | } 30 | 31 | void bpl() 32 | { 33 | if (CC_N == 0) 34 | do_branch(); 35 | } 36 | 37 | void bmi() 38 | { 39 | if (CC_N == 1) 40 | do_branch(); 41 | } 42 | 43 | void bhi() 44 | { 45 | if ((CC_Z == 0) && (CC_C == 0)) 46 | do_branch(); 47 | } 48 | 49 | void bvc() 50 | { 51 | if (CC_V == 0) 52 | do_branch(); 53 | } 54 | 55 | void bvs() 56 | { 57 | if (CC_V == 1) 58 | do_branch(); 59 | } 60 | 61 | void bcc() 62 | { 63 | if (CC_C == 0) 64 | do_branch(); 65 | } 66 | 67 | void bcs() 68 | { 69 | if (CC_C == 1) 70 | do_branch(); 71 | } 72 | 73 | /* br() - Branch Always. */ 74 | void br() 75 | { 76 | do_branch(); 77 | } 78 | 79 | 80 | /* blos() - Branch Lower or Same Instruction. */ 81 | void blos() 82 | { 83 | if ((CC_C != 0) || (CC_Z != 0)) 84 | do_branch(); 85 | } 86 | 87 | /* bge() - Branch Greater Than or Equal Instruction. */ 88 | void bge() 89 | { 90 | if ((CC_N ^ CC_V) == 0) 91 | do_branch(); 92 | } 93 | 94 | /* blt() - Branch Less Than Instruction. */ 95 | void blt() 96 | { 97 | if ((CC_N ^ CC_V) == 1) 98 | do_branch(); 99 | } 100 | 101 | /* ble() - Branch Less Than Or Equal Instruction. */ 102 | void ble() 103 | { 104 | if (((CC_N ^ CC_V) == 1) || ((CC_Z) != 0)) 105 | do_branch(); 106 | } 107 | 108 | /* bgt() - Branch Greater Than Instruction. */ 109 | void bgt() 110 | { 111 | if (((CC_N ^ CC_V) == 0) && ((CC_Z) == 0)) 112 | do_branch(); 113 | } 114 | 115 | /* jmp() - Jump Instruction. */ 116 | void jmp() 117 | { 118 | load_ea(); 119 | regs[PC] = dstword; 120 | } 121 | 122 | /* jsr() - Jump To Subroutine Instruction. */ 123 | void jsr() 124 | { 125 | load_ea(); 126 | srcword = regs[SRC_REG]; 127 | push(); 128 | regs[SRC_REG] = regs[PC]; 129 | regs[PC] = dstword; 130 | JsrDebug((dbg_file, "jsr to 0%o\n", dstword)); 131 | } 132 | 133 | /* rts() - Return From Subroutine Instruction. */ 134 | void rts() 135 | { 136 | regs[PC] = regs[DST_REG]; 137 | pop(); 138 | regs[DST_REG] = dstword; 139 | JsrDebug((dbg_file, "rts to 0%o\n", regs[PC])); 140 | } 141 | 142 | void scc() 143 | { 144 | if (ir & CC_NBIT) 145 | CC_N = 1; 146 | if (ir & CC_ZBIT) 147 | CC_Z = 1; 148 | if (ir & CC_VBIT) 149 | CC_V = 1; 150 | if (ir & CC_CBIT) 151 | CC_C = 1; 152 | } 153 | 154 | void ccc() 155 | { 156 | if (ir & CC_NBIT) 157 | CC_N = 0; 158 | if (ir & CC_ZBIT) 159 | CC_Z = 0; 160 | if (ir & CC_VBIT) 161 | CC_V = 0; 162 | if (ir & CC_CBIT) 163 | CC_C = 0; 164 | } 165 | 166 | /* sob() - Subtract One and Branch Instruction. */ 167 | void sob() 168 | { 169 | regs[SRC_REG] -= 1; 170 | if (regs[SRC_REG]) { 171 | regs[PC] -= (ir & 077) * 2; 172 | } 173 | } 174 | 175 | /* mfps() - Move from Processor Status Instruction. */ 176 | void mfps() 177 | { 178 | srcbyte = (u_int8_t) 0; 179 | if (CC_N) 180 | srcbyte |= CC_NBIT; 181 | if (CC_Z) 182 | srcbyte |= CC_ZBIT; 183 | if (CC_V) 184 | srcbyte |= CC_VBIT; 185 | if (CC_C) 186 | srcbyte |= CC_CBIT; 187 | 188 | CHGB_CC_N(srcbyte); 189 | CHGB_CC_Z(srcbyte); 190 | CLR_CC_V(); 191 | 192 | if (DST_MODE) { 193 | storeb_dst(); 194 | } else { 195 | if (srcbyte & SIGN_B) { 196 | dstword = 0177400; 197 | } else { 198 | dstword = 0; 199 | } 200 | dstword += (u_int16_t) srcbyte; 201 | store_dst(); 202 | } 203 | } 204 | 205 | /* mtps() - Move to Processor Status Instruction. */ 206 | void mtps() 207 | { 208 | loadb_dst(); 209 | if (dstbyte & CC_NBIT) 210 | CC_N = 1; 211 | if (dstbyte & CC_ZBIT) 212 | CC_Z = 1; 213 | if (dstbyte & CC_VBIT) 214 | CC_V = 1; 215 | if (dstbyte & CC_CBIT) 216 | CC_C = 1; 217 | } 218 | 219 | /* mfpi() - Move From Previous Instruction Space Instruction. */ 220 | void mfpi() 221 | { 222 | loadp_dst(); 223 | push(); 224 | } 225 | 226 | 227 | /* mtpi() - To From Previous Instruction Space Instruction. */ 228 | void mtpi() 229 | { 230 | pop(); 231 | storep_dst(); 232 | } 233 | 234 | /* ash() - Arithmetic Shift Instruction. */ 235 | void ash() 236 | { 237 | u_int16_t temp; 238 | u_int16_t old; 239 | u_int16_t sign; 240 | u_int16_t count; 241 | 242 | temp = regs[SRC_REG]; 243 | load_dst(); 244 | old = temp; 245 | 246 | if ((dstword & 077) == 0) { /* no shift */ 247 | CHG_CC_N(temp); 248 | CHG_CC_Z(temp); 249 | CLR_CC_V(); 250 | return; 251 | } 252 | if (dstword & 040) { /* right shift */ 253 | count = 0100 - (dstword & 077); 254 | sign = temp & SIGN; 255 | while (count--) { 256 | if (temp & LSBIT) { 257 | SET_CC_C(); 258 | } else { 259 | CLR_CC_C(); 260 | } 261 | temp >>= 1; 262 | temp += sign; 263 | } 264 | } else { /* left shift */ 265 | count = dstword & 037; 266 | while (count--) { 267 | if (temp & SIGN) { 268 | SET_CC_C(); 269 | } else { 270 | CLR_CC_C(); 271 | } 272 | temp <<= 1; 273 | } 274 | } 275 | 276 | CHG_CC_N(temp); 277 | CHG_CC_Z(temp); 278 | 279 | if ((old & SIGN) == (temp & SIGN)) { 280 | CLR_CC_V(); 281 | } else { 282 | SET_CC_V(); 283 | } 284 | regs[SRC_REG] = temp; 285 | } 286 | 287 | 288 | /* mul() and divide() - Multiply and Divide Instructions. These work on 289 | * signed values, and we'll do the same. This may not be portable. */ 290 | 291 | union s_u_word { 292 | u_int16_t u_word; 293 | short s_word; 294 | }; 295 | 296 | union s_u_long { 297 | u_int32_t u_long; 298 | long s_long; 299 | }; 300 | 301 | void mul() 302 | { 303 | union s_u_word data1; 304 | union s_u_word data2; 305 | union s_u_long tmp; 306 | 307 | data1.u_word = regs[SRC_REG]; 308 | load_dst(); 309 | data2.u_word = dstword; 310 | 311 | tmp.s_long = ((long) data1.s_word) * ((long) data2.s_word); 312 | 313 | regs[SRC_REG] = (u_int16_t) (tmp.u_long >> 16); 314 | regs[(SRC_REG) | 1] = (u_int16_t) (tmp.u_long & 0177777); 315 | 316 | CLR_CC_ALL(); 317 | 318 | if (tmp.u_long == 0) 319 | SET_CC_Z(); 320 | else 321 | CLR_CC_Z(); 322 | 323 | if (tmp.u_long & 0x80000000) 324 | SET_CC_N(); 325 | else 326 | CLR_CC_N(); 327 | } 328 | 329 | void divide() 330 | { 331 | union s_u_long tmp; 332 | union s_u_long eql; 333 | union s_u_word data2; 334 | 335 | tmp.u_long = regs[SRC_REG]; 336 | tmp.u_long = tmp.u_long << 16; 337 | tmp.u_long += regs[(SRC_REG) | 1]; 338 | 339 | load_dst(); 340 | data2.u_word = dstword; 341 | 342 | if (data2.u_word == 0) { 343 | SET_CC_C(); 344 | SET_CC_V(); 345 | return; 346 | } else { 347 | CLR_CC_C(); 348 | } 349 | 350 | eql.s_long = tmp.s_long / data2.s_word; 351 | regs[SRC_REG] = (u_int16_t) eql.u_long & 0177777; 352 | 353 | if (eql.u_long == 0) 354 | SET_CC_Z(); 355 | else 356 | CLR_CC_Z(); 357 | 358 | if ((eql.s_long > 077777) || (eql.s_long < -0100000)) 359 | SET_CC_V(); 360 | else 361 | CLR_CC_V(); 362 | 363 | if (eql.s_long < 0) 364 | SET_CC_N(); 365 | else 366 | CLR_CC_N(); 367 | 368 | eql.s_long = tmp.s_long % data2.s_word; 369 | regs[(SRC_REG) | 1] = (u_int16_t) eql.u_long & 0177777; 370 | } 371 | 372 | /* ashc() - Arithmetic Shift Combined Instruction. */ 373 | void ashc() 374 | { 375 | u_int32_t temp; 376 | u_int32_t old; 377 | u_int32_t sign; 378 | u_int16_t count; 379 | 380 | temp = regs[SRC_REG]; 381 | temp <<= 16; 382 | temp += regs[(SRC_REG) | 1]; 383 | old = temp; 384 | load_dst(); 385 | 386 | if ((dstword & 077) == 0) { /* no shift */ 387 | 388 | CLR_CC_V(); 389 | 390 | if (temp & 0x80000000) { 391 | SET_CC_N(); 392 | } else { 393 | CLR_CC_N(); 394 | } 395 | 396 | if (temp) { 397 | CLR_CC_Z(); 398 | } else { 399 | SET_CC_Z(); 400 | } 401 | return; 402 | } 403 | if (dstword & 040) { /* right shift */ 404 | count = 0100 - (dstword & 077); 405 | sign = temp & 0x80000000; 406 | while (count--) { 407 | if (temp & LSBIT) { 408 | SET_CC_C(); 409 | } else { 410 | CLR_CC_C(); 411 | } 412 | temp >>= 1; 413 | temp += sign; 414 | } 415 | } else { /* left shift */ 416 | count = dstword & 037; 417 | while (count--) { 418 | if (temp & 0x80000000) { 419 | SET_CC_C(); 420 | } else { 421 | CLR_CC_C(); 422 | } 423 | temp <<= 1; 424 | } 425 | } 426 | 427 | if (temp & 0x80000000) 428 | SET_CC_N(); 429 | else 430 | CLR_CC_N(); 431 | 432 | if (temp) 433 | CLR_CC_Z(); 434 | else 435 | SET_CC_Z(); 436 | 437 | if ((old & 0x80000000) == (temp & 0x80000000)) { 438 | CLR_CC_V(); 439 | } else { 440 | SET_CC_V(); 441 | } 442 | 443 | regs[SRC_REG] = (u_int16_t) (temp >> 16); 444 | regs[(SRC_REG) | 1] = LOW16(temp); 445 | } 446 | 447 | /* xor() - Exclusive Or Instruction */ 448 | void xor() 449 | { 450 | tmpword = regs[SRC_REG]; 451 | 452 | load_dst(); 453 | 454 | tmpword = tmpword ^ dstword; 455 | 456 | CHG_CC_N(tmpword); 457 | CHG_CC_Z(tmpword); 458 | CLR_CC_V(); 459 | 460 | dstword = tmpword; 461 | store_dst_2(); 462 | } 463 | -------------------------------------------------------------------------------- /debug.c: -------------------------------------------------------------------------------- 1 | /* List of names for each instruction 2 | * 3 | * $Revision: 1.5 $ 4 | * $Date: 1999/01/05 22:50:48 $ 5 | */ 6 | #ifdef DEBUG 7 | char *iname0[64] = { 8 | "halt", "waiti", "illegal", "bpt", "iot", "illegal", "illegal", 9 | "illegal", 10 | "illegal", "illegal", "illegal", "illegal", "illegal", "illegal", 11 | "illegal", "illegal", 12 | "illegal", "illegal", "illegal", "illegal", "illegal", "illegal", 13 | "illegal", "illegal", 14 | "illegal", "illegal", "illegal", "illegal", "illegal", "illegal", 15 | "illegal", "illegal", 16 | "illegal", "illegal", "illegal", "illegal", "illegal", "illegal", 17 | "illegal", "illegal", 18 | "illegal", "illegal", "illegal", "illegal", "illegal", "illegal", 19 | "illegal", "illegal", 20 | "illegal", "illegal", "illegal", "illegal", "illegal", "illegal", 21 | "illegal", "illegal", 22 | "illegal", "illegal", "illegal", "illegal", "illegal", "illegal", 23 | "illegal", "illegal" 24 | }; 25 | 26 | char *iname1[64] = { 27 | "rts", "rts", "rts", "rts", "rts", "rts", "rts", "rts", 28 | "illegal", "illegal", "illegal", "illegal", "illegal", "illegal", 29 | "illegal", "illegal", 30 | "illegal", "illegal", "illegal", "illegal", "illegal", "illegal", 31 | "illegal", "illegal", 32 | "illegal", "illegal", "illegal", "illegal", "illegal", "illegal", 33 | "illegal", "illegal", 34 | "ccc", "ccc", "ccc", "ccc", "ccc", "ccc", "ccc", "ccc", 35 | "ccc", "ccc", "ccc", "ccc", "ccc", "ccc", "ccc", "ccc", 36 | "scc", "scc", "scc", "scc", "scc", "scc", "scc", "scc", 37 | "scc", "scc", "scc", "scc", "scc", "scc", "scc", "scc" 38 | }; 39 | 40 | char *iname[1024] = { 41 | "dositab0", "jmp", "dositab1", "swabi", "br", "br", "br", "br", 42 | "bne", "bne", "bne", "bne", "beq", "beq", "beq", "beq", 43 | "bge", "bge", "bge", "bge", "blt", "blt", "blt", "blt", 44 | "bgt", "bgt", "bgt", "bgt", "ble", "ble", "ble", "ble", 45 | "jsr", "jsr", "jsr", "jsr", "jsr", "jsr", "jsr", "jsr", 46 | "clr", "com", "inc", "dec", "neg", "adc", "sbc", "tst", 47 | "ror", "rol", "asr", "asl", "mark", "mfpi", "mtpi", "sxt", 48 | "illegal", "illegal", "illegal", "illegal", "illegal", "illegal", 49 | "illegal", "illegal", 50 | "mov", "mov", "mov", "mov", "mov", "mov", "mov", "mov", 51 | "mov", "mov", "mov", "mov", "mov", "mov", "mov", "mov", 52 | "mov", "mov", "mov", "mov", "mov", "mov", "mov", "mov", 53 | "mov", "mov", "mov", "mov", "mov", "mov", "mov", "mov", 54 | "mov", "mov", "mov", "mov", "mov", "mov", "mov", "mov", 55 | "mov", "mov", "mov", "mov", "mov", "mov", "mov", "mov", 56 | "mov", "mov", "mov", "mov", "mov", "mov", "mov", "mov", 57 | "mov", "mov", "mov", "mov", "mov", "mov", "mov", "mov", 58 | "cmp", "cmp", "cmp", "cmp", "cmp", "cmp", "cmp", "cmp", 59 | "cmp", "cmp", "cmp", "cmp", "cmp", "cmp", "cmp", "cmp", 60 | "cmp", "cmp", "cmp", "cmp", "cmp", "cmp", "cmp", "cmp", 61 | "cmp", "cmp", "cmp", "cmp", "cmp", "cmp", "cmp", "cmp", 62 | "cmp", "cmp", "cmp", "cmp", "cmp", "cmp", "cmp", "cmp", 63 | "cmp", "cmp", "cmp", "cmp", "cmp", "cmp", "cmp", "cmp", 64 | "cmp", "cmp", "cmp", "cmp", "cmp", "cmp", "cmp", "cmp", 65 | "cmp", "cmp", "cmp", "cmp", "cmp", "cmp", "cmp", "cmp", 66 | "bit", "bit", "bit", "bit", "bit", "bit", "bit", "bit", 67 | "bit", "bit", "bit", "bit", "bit", "bit", "bit", "bit", 68 | "bit", "bit", "bit", "bit", "bit", "bit", "bit", "bit", 69 | "bit", "bit", "bit", "bit", "bit", "bit", "bit", "bit", 70 | "bit", "bit", "bit", "bit", "bit", "bit", "bit", "bit", 71 | "bit", "bit", "bit", "bit", "bit", "bit", "bit", "bit", 72 | "bit", "bit", "bit", "bit", "bit", "bit", "bit", "bit", 73 | "bit", "bit", "bit", "bit", "bit", "bit", "bit", "bit", 74 | "bic", "bic", "bic", "bic", "bic", "bic", "bic", "bic", 75 | "bic", "bic", "bic", "bic", "bic", "bic", "bic", "bic", 76 | "bic", "bic", "bic", "bic", "bic", "bic", "bic", "bic", 77 | "bic", "bic", "bic", "bic", "bic", "bic", "bic", "bic", 78 | "bic", "bic", "bic", "bic", "bic", "bic", "bic", "bic", 79 | "bic", "bic", "bic", "bic", "bic", "bic", "bic", "bic", 80 | "bic", "bic", "bic", "bic", "bic", "bic", "bic", "bic", 81 | "bic", "bic", "bic", "bic", "bic", "bic", "bic", "bic", 82 | "bis", "bis", "bis", "bis", "bis", "bis", "bis", "bis", 83 | "bis", "bis", "bis", "bis", "bis", "bis", "bis", "bis", 84 | "bis", "bis", "bis", "bis", "bis", "bis", "bis", "bis", 85 | "bis", "bis", "bis", "bis", "bis", "bis", "bis", "bis", 86 | "bis", "bis", "bis", "bis", "bis", "bis", "bis", "bis", 87 | "bis", "bis", "bis", "bis", "bis", "bis", "bis", "bis", 88 | "bis", "bis", "bis", "bis", "bis", "bis", "bis", "bis", 89 | "bis", "bis", "bis", "bis", "bis", "bis", "bis", "bis", 90 | "add", "add", "add", "add", "add", "add", "add", "add", 91 | "add", "add", "add", "add", "add", "add", "add", "add", 92 | "add", "add", "add", "add", "add", "add", "add", "add", 93 | "add", "add", "add", "add", "add", "add", "add", "add", 94 | "add", "add", "add", "add", "add", "add", "add", "add", 95 | "add", "add", "add", "add", "add", "add", "add", "add", 96 | "add", "add", "add", "add", "add", "add", "add", "add", 97 | "add", "add", "add", "add", "add", "add", "add", "add", 98 | "mul", "mul", "mul", "mul", "mul", "mul", "mul", "mul", 99 | "divide", "divide", "divide", "divide", "divide", "divide", "divide", 100 | "divide", 101 | "ash", "ash", "ash", "ash", "ash", "ash", "ash", "ash", 102 | "ashc", "ashc", "ashc", "ashc", "ashc", "ashc", "ashc", "ashc", 103 | "xor", "xor", "xor", "xor", "xor", "xor", "xor", "xor", 104 | "illegal", "illegal", "illegal", "illegal", "illegal", "illegal", 105 | "illegal", "illegal", 106 | "illegal", "illegal", "illegal", "illegal", "illegal", "illegal", 107 | "illegal", "illegal", 108 | "sob", "sob", "sob", "sob", "sob", "sob", "sob", "sob", 109 | "bpl", "bpl", "bpl", "bpl", "bmi", "bmi", "bmi", "bmi", 110 | "bhi", "bhi", "bhi", "bhi", "blos", "blos", "blos", "blos", 111 | "bvc", "bvc", "bvc", "bvc", "bvs", "bvs", "bvs", "bvs", 112 | "bcc", "bcc", "bcc", "bcc", "bcs", "bcs", "bcs", "bcs", 113 | "emt", "emt", "emt", "emt", "trap", "trap", "trap", "trap", 114 | "clrb", "comb", "incb", "decb", "negb", "adcb", "sbcb", "tstb", 115 | "rorb", "rolb", "asrb", "aslb", "mtps", "mfpd", "mtpd", "mfps", 116 | "illegal", "illegal", "illegal", "illegal", "illegal", "illegal", 117 | "illegal", "illegal", 118 | "movb", "movb", "movb", "movb", "movb", "movb", "movb", "movb", 119 | "movb", "movb", "movb", "movb", "movb", "movb", "movb", "movb", 120 | "movb", "movb", "movb", "movb", "movb", "movb", "movb", "movb", 121 | "movb", "movb", "movb", "movb", "movb", "movb", "movb", "movb", 122 | "movb", "movb", "movb", "movb", "movb", "movb", "movb", "movb", 123 | "movb", "movb", "movb", "movb", "movb", "movb", "movb", "movb", 124 | "movb", "movb", "movb", "movb", "movb", "movb", "movb", "movb", 125 | "movb", "movb", "movb", "movb", "movb", "movb", "movb", "movb", 126 | "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", 127 | "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", 128 | "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", 129 | "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", 130 | "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", 131 | "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", 132 | "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", 133 | "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", "cmpb", 134 | "bitb", "bitb", "bitb", "bitb", "bitb", "bitb", "bitb", "bitb", 135 | "bitb", "bitb", "bitb", "bitb", "bitb", "bitb", "bitb", "bitb", 136 | "bitb", "bitb", "bitb", "bitb", "bitb", "bitb", "bitb", "bitb", 137 | "bitb", "bitb", "bitb", "bitb", "bitb", "bitb", "bitb", "bitb", 138 | "bitb", "bitb", "bitb", "bitb", "bitb", "bitb", "bitb", "bitb", 139 | "bitb", "bitb", "bitb", "bitb", "bitb", "bitb", "bitb", "bitb", 140 | "bitb", "bitb", "bitb", "bitb", "bitb", "bitb", "bitb", "bitb", 141 | "bitb", "bitb", "bitb", "bitb", "bitb", "bitb", "bitb", "bitb", 142 | "bicb", "bicb", "bicb", "bicb", "bicb", "bicb", "bicb", "bicb", 143 | "bicb", "bicb", "bicb", "bicb", "bicb", "bicb", "bicb", "bicb", 144 | "bicb", "bicb", "bicb", "bicb", "bicb", "bicb", "bicb", "bicb", 145 | "bicb", "bicb", "bicb", "bicb", "bicb", "bicb", "bicb", "bicb", 146 | "bicb", "bicb", "bicb", "bicb", "bicb", "bicb", "bicb", "bicb", 147 | "bicb", "bicb", "bicb", "bicb", "bicb", "bicb", "bicb", "bicb", 148 | "bicb", "bicb", "bicb", "bicb", "bicb", "bicb", "bicb", "bicb", 149 | "bicb", "bicb", "bicb", "bicb", "bicb", "bicb", "bicb", "bicb", 150 | "bisb", "bisb", "bisb", "bisb", "bisb", "bisb", "bisb", "bisb", 151 | "bisb", "bisb", "bisb", "bisb", "bisb", "bisb", "bisb", "bisb", 152 | "bisb", "bisb", "bisb", "bisb", "bisb", "bisb", "bisb", "bisb", 153 | "bisb", "bisb", "bisb", "bisb", "bisb", "bisb", "bisb", "bisb", 154 | "bisb", "bisb", "bisb", "bisb", "bisb", "bisb", "bisb", "bisb", 155 | "bisb", "bisb", "bisb", "bisb", "bisb", "bisb", "bisb", "bisb", 156 | "bisb", "bisb", "bisb", "bisb", "bisb", "bisb", "bisb", "bisb", 157 | "bisb", "bisb", "bisb", "bisb", "bisb", "bisb", "bisb", "bisb", 158 | "sub", "sub", "sub", "sub", "sub", "sub", "sub", "sub", 159 | "sub", "sub", "sub", "sub", "sub", "sub", "sub", "sub", 160 | "sub", "sub", "sub", "sub", "sub", "sub", "sub", "sub", 161 | "sub", "sub", "sub", "sub", "sub", "sub", "sub", "sub", 162 | "sub", "sub", "sub", "sub", "sub", "sub", "sub", "sub", 163 | "sub", "sub", "sub", "sub", "sub", "sub", "sub", "sub", 164 | "sub", "sub", "sub", "sub", "sub", "sub", "sub", "sub", 165 | "sub", "sub", "sub", "sub", "sub", "sub", "sub", "sub", 166 | "fpset", "ldfps", "stfps", "stst", "clrf", "tstf", "absf", "negf", 167 | "mulf", "mulf", "mulf", "mulf", "moddf", "moddf", "moddf", "moddf", 168 | "addf", "addf", "addf", "addf", "ldf", "ldf", "ldf", "ldf", 169 | "subf", "subf", "subf", "subf", "cmpf", "cmpf", "cmpf", "cmpf", 170 | "stf", "stf", "stf", "stf", "divf", "divf", "divf", "divf", 171 | "stexp", "stexp", "stexp", "stexp", "stcfi", "stcfi", "stcfi", "stcfi", 172 | "stcdf", "stcdf", "stcdf", "stcdf", "ldexpp", "ldexpp", "ldexpp", 173 | "ldexpp", 174 | "lcdif", "lcdif", "lcdif", "lcdif", "ldcdf", "ldcdf", "ldcdf", "ldcdf" 175 | }; 176 | #endif 177 | -------------------------------------------------------------------------------- /single.c: -------------------------------------------------------------------------------- 1 | /* single.c - Single operand instructions. 2 | * 3 | * $Revision: 2.10 $ 4 | * $Date: 1999/01/05 23:46:04 $ 5 | */ 6 | #include "defines.h" 7 | 8 | /* adc() - Add Carry Instruction. */ 9 | void adc() 10 | { 11 | load_dst(); 12 | 13 | if (CC_C) { /* do if carry is set */ 14 | if (dstword == MPI) 15 | SET_CC_V(); 16 | else 17 | CLR_CC_V(); 18 | if (dstword == NEG_1) 19 | SET_CC_C(); 20 | else 21 | CLR_CC_C(); 22 | dstword++; /* add the carry */ 23 | } else { 24 | CLR_CC_V(); 25 | CLR_CC_C(); 26 | } 27 | 28 | CHG_CC_N(dstword); 29 | CHG_CC_Z(dstword); 30 | 31 | store_dst_2(); 32 | } 33 | 34 | 35 | /* asl() - Arithmetic Shift Left Instruction. */ 36 | void asl() 37 | { 38 | load_dst(); 39 | 40 | if (dstword & SIGN) 41 | SET_CC_C(); 42 | else 43 | CLR_CC_C(); 44 | 45 | dstword <<= 1; 46 | 47 | CHG_CC_N(dstword); 48 | CHG_CC_Z(dstword); 49 | CHG_CC_V_XOR_C_N(); 50 | 51 | store_dst_2(); 52 | } 53 | 54 | /* asr() - Arithmetic Shift Right Instruction. */ 55 | void asr() 56 | { 57 | load_dst(); 58 | 59 | if (dstword & LSBIT) 60 | SET_CC_C(); 61 | else 62 | CLR_CC_C(); 63 | 64 | dstword = (dstword >> 1) + (dstword & SIGN); /* shift and replicate */ 65 | 66 | CHG_CC_N(dstword); 67 | CHG_CC_Z(dstword); 68 | 69 | CHG_CC_V_XOR_C_N(); 70 | 71 | store_dst_2(); 72 | } 73 | 74 | /* clr() - Clear Instruction. */ 75 | void clr() 76 | { 77 | CLR_CC_ALL(); 78 | SET_CC_Z(); 79 | dstword = 0; 80 | store_dst(); 81 | } 82 | 83 | /* com() - Complement Instruction. */ 84 | void com() 85 | { 86 | load_dst(); 87 | 88 | dstword = ~dstword; 89 | 90 | CHG_CC_N(dstword); 91 | CHG_CC_Z(dstword); 92 | CLR_CC_V(); 93 | SET_CC_C(); 94 | 95 | store_dst_2(); 96 | } 97 | 98 | /* dec() - Decrement Instruction. */ 99 | void dec() 100 | { 101 | load_dst(); 102 | 103 | if (dstword == MNI) 104 | SET_CC_V(); 105 | else 106 | CLR_CC_V(); 107 | 108 | --dstword; 109 | 110 | CHG_CC_N(dstword); 111 | CHG_CC_Z(dstword); 112 | 113 | store_dst_2(); 114 | } 115 | 116 | /* inc() - Increment Instruction. */ 117 | void inc() 118 | { 119 | load_dst(); 120 | 121 | if (dstword == MPI) 122 | SET_CC_V(); 123 | else 124 | CLR_CC_V(); 125 | 126 | ++dstword; 127 | 128 | CHG_CC_N(dstword); 129 | CHG_CC_Z(dstword); 130 | 131 | store_dst_2(); 132 | } 133 | 134 | /* neg() - Negate Instruction. */ 135 | 136 | void neg() 137 | { 138 | load_dst(); 139 | 140 | dstword = (NEG_1 - dstword) + 1; 141 | 142 | CHG_CC_N(dstword); 143 | CHG_CC_Z(dstword); 144 | 145 | if (dstword == MNI) 146 | SET_CC_V(); 147 | else 148 | CLR_CC_V(); 149 | 150 | if (dstword == 0) 151 | CLR_CC_C(); 152 | else 153 | SET_CC_C(); 154 | 155 | store_dst_2(); 156 | } 157 | 158 | /* rol() - Rotate Left Instruction. */ 159 | void rol() 160 | { 161 | load_dst(); 162 | 163 | tmpword = dstword & SIGN; /* get sign bit */ 164 | dstword <<= 1; /* shift */ 165 | 166 | if (CC_C) /* roll in carry */ 167 | dstword += LSBIT; 168 | 169 | if (tmpword) /* roll out to carry */ 170 | SET_CC_C(); 171 | else 172 | CLR_CC_C(); 173 | 174 | CHG_CC_N(dstword); 175 | CHG_CC_Z(dstword); 176 | CHG_CC_V_XOR_C_N(); 177 | 178 | store_dst_2(); 179 | } 180 | 181 | 182 | /* ror() - Rotate Right Instruction. */ 183 | void ror() 184 | { 185 | load_dst(); 186 | 187 | tmpword = dstword & LSBIT; /* get low bit */ 188 | dstword >>= 1; /* shift */ 189 | 190 | if (CC_C) /* roll in carry */ 191 | dstword += SIGN; 192 | 193 | if (tmpword) /* roll out to carry */ 194 | SET_CC_C(); 195 | else 196 | CLR_CC_C(); 197 | 198 | CHG_CC_N(dstword); 199 | CHG_CC_Z(dstword); 200 | CHG_CC_V_XOR_C_N(); 201 | 202 | store_dst_2(); 203 | } 204 | 205 | /* sbc() - Subtract Carry Instruction. */ 206 | void sbc() 207 | { 208 | load_dst(); 209 | 210 | if (dstword == MNI) 211 | SET_CC_V(); 212 | else 213 | CLR_CC_V(); 214 | 215 | if (CC_C) { /* do if carry is set */ 216 | if (dstword) 217 | CLR_CC_C(); 218 | else 219 | SET_CC_C(); 220 | --dstword; /* subtract carry */ 221 | } else { 222 | CLR_CC_C(); 223 | } 224 | 225 | CHG_CC_N(dstword); 226 | CHG_CC_Z(dstword); 227 | 228 | store_dst_2(); 229 | } 230 | 231 | /* swabi() - Swap Bytes Instruction. */ 232 | void swabi() 233 | { 234 | u_int16_t data2; 235 | u_int16_t data3; 236 | 237 | load_dst(); 238 | 239 | data2 = (dstword << 8) & 0xff00; 240 | data3 = (dstword >> 8) & 0x00ff; 241 | dstword = data2 + data3; 242 | 243 | CLR_CC_ALL(); 244 | CHGB_CC_N(data3); /* cool, negative and zero */ 245 | CHGB_CC_Z(data3); /* checks done on low byte only */ 246 | 247 | store_dst_2(); 248 | } 249 | 250 | /* sxt() - Sign Extend Instruction. */ 251 | void sxt() 252 | { 253 | if (CC_N) { 254 | dstword = NEG_1; 255 | CLR_CC_Z(); 256 | } else { 257 | dstword = 0; 258 | SET_CC_Z(); 259 | } 260 | CLR_CC_V(); 261 | 262 | store_dst(); 263 | } 264 | 265 | /* tst() - Test Instruction. */ 266 | void tst() 267 | { 268 | load_dst(); 269 | 270 | CLR_CC_ALL(); 271 | CHG_CC_N(dstword); 272 | CHG_CC_Z(dstword); 273 | } 274 | 275 | /* tstb() - Test Byte Instruction. */ 276 | void tstb() 277 | { 278 | loadb_dst(); 279 | 280 | CHGB_CC_N(dstbyte); 281 | CHGB_CC_Z(dstbyte); 282 | CLR_CC_V(); 283 | CLR_CC_C(); 284 | 285 | } 286 | 287 | /* aslb() - Arithmetic Shift Left Byte Instruction. */ 288 | void aslb() 289 | { 290 | loadb_dst(); 291 | 292 | if (dstbyte & SIGN_B) 293 | SET_CC_C(); 294 | else 295 | CLR_CC_C(); 296 | 297 | dstbyte <<= 1; 298 | 299 | CHGB_CC_N(dstbyte); 300 | CHGB_CC_Z(dstbyte); 301 | CHG_CC_V_XOR_C_N(); 302 | 303 | storeb_dst_2(); 304 | } 305 | 306 | /* asrb() - Arithmetic Shift Right Byte Instruction. */ 307 | void asrb() 308 | { 309 | loadb_dst(); 310 | 311 | if (dstbyte & LSBIT) 312 | SET_CC_C(); 313 | else 314 | CLR_CC_C(); 315 | 316 | dstbyte = (dstbyte >> 1) + (dstbyte & SIGN_B); /* shift and replicate */ 317 | 318 | CHGB_CC_N(dstbyte); 319 | CHGB_CC_Z(dstbyte); 320 | CHG_CC_V_XOR_C_N(); 321 | 322 | storeb_dst_2(); 323 | } 324 | 325 | /* clrb() - Clear Byte Instruction. */ 326 | void clrb() 327 | { 328 | CLR_CC_ALL(); 329 | SET_CC_Z(); 330 | srcbyte = 0; 331 | storeb_dst(); 332 | } 333 | 334 | 335 | /* comb() - Complement Byte Instruction. */ 336 | void comb() 337 | { 338 | loadb_dst(); 339 | 340 | dstbyte = ~dstbyte; 341 | 342 | CHGB_CC_N(dstbyte); 343 | CHGB_CC_Z(dstbyte); 344 | CLR_CC_V(); 345 | SET_CC_C(); 346 | 347 | storeb_dst_2(); 348 | } 349 | 350 | /* decb() - Decrement Byte Instruction. */ 351 | void decb() 352 | { 353 | loadb_dst(); 354 | 355 | if (dstbyte == MNI_B) 356 | SET_CC_V(); 357 | else 358 | CLR_CC_V(); 359 | 360 | --dstbyte; 361 | 362 | CHGB_CC_N(dstbyte); 363 | CHGB_CC_Z(dstbyte); 364 | 365 | storeb_dst_2(); 366 | } 367 | 368 | /* incb() - Increment Byte Instruction. */ 369 | void incb() 370 | { 371 | loadb_dst(); 372 | 373 | if (dstbyte == MPI_B) 374 | SET_CC_V(); 375 | else 376 | CLR_CC_V(); 377 | 378 | ++dstbyte; 379 | 380 | CHGB_CC_N(dstbyte); 381 | CHGB_CC_Z(dstbyte); 382 | 383 | storeb_dst_2(); 384 | } 385 | 386 | /* negb() - Negate Byte Instruction. */ 387 | void negb() 388 | { 389 | loadb_dst(); 390 | 391 | dstbyte = (NEG_1_B - dstbyte) + 1; /* hope this is right */ 392 | 393 | CHGB_CC_N(dstbyte); 394 | CHGB_CC_Z(dstbyte); 395 | 396 | if (dstbyte == MNI_B) 397 | SET_CC_V(); 398 | else 399 | CLR_CC_V(); 400 | 401 | if (dstbyte) 402 | SET_CC_C(); 403 | else 404 | CLR_CC_C(); 405 | 406 | storeb_dst_2(); 407 | } 408 | 409 | /* rolb() - Rotate Left Byte Instruction. */ 410 | void rolb() 411 | { 412 | loadb_dst(); 413 | 414 | tmpbyte = dstbyte & SIGN_B; /* get top bit */ 415 | dstbyte <<= 1; /* shift */ 416 | 417 | if (CC_C) /* roll in carry */ 418 | dstbyte = dstbyte + LSBIT; 419 | 420 | if (tmpbyte) /* roll out to carry */ 421 | SET_CC_C(); 422 | else 423 | CLR_CC_C(); 424 | 425 | CHGB_CC_N(dstbyte); 426 | CHGB_CC_Z(dstbyte); 427 | CHG_CC_V_XOR_C_N(); 428 | 429 | storeb_dst_2(); 430 | } 431 | 432 | /* rorb() - Rotate Right Byte Instruction. */ 433 | void rorb() 434 | { 435 | loadb_dst(); 436 | 437 | tmpbyte = dstbyte & LSBIT; /* get low bit */ 438 | dstbyte >>= 1; /* shift */ 439 | 440 | if (CC_C) /* roll in carry */ 441 | dstbyte += SIGN_B; 442 | 443 | if (tmpbyte) /* roll out to carry */ 444 | SET_CC_C(); 445 | else 446 | CLR_CC_C(); 447 | 448 | CHGB_CC_N(dstbyte); 449 | CHGB_CC_Z(dstbyte); 450 | CHG_CC_V_XOR_C_N(); 451 | 452 | storeb_dst_2(); 453 | } 454 | 455 | /* adcb() - Add Carry Byte Instruction. */ 456 | void adcb() 457 | { 458 | loadb_dst(); 459 | 460 | if (CC_C) { /* do if carry is set */ 461 | if (dstbyte == MPI_B) 462 | SET_CC_V(); 463 | else 464 | CLR_CC_V(); 465 | if (dstbyte == NEG_1_B) 466 | SET_CC_C(); 467 | else 468 | CLR_CC_C(); 469 | ++dstbyte; /* add the carry */ 470 | } else { 471 | CLR_CC_V(); 472 | CLR_CC_C(); 473 | } 474 | 475 | CHGB_CC_N(dstbyte); 476 | CHGB_CC_Z(dstbyte); 477 | 478 | storeb_dst_2(); 479 | } 480 | 481 | /* sbcb() - Subtract Carry Byte Instruction. */ 482 | void sbcb() 483 | { 484 | loadb_dst(); 485 | 486 | if (CC_C) { /* do if carry is set */ 487 | if (dstbyte) 488 | CLR_CC_C(); 489 | else 490 | SET_CC_C(); 491 | 492 | --dstbyte; /* subtract carry */ 493 | } else { 494 | CLR_CC_C(); 495 | } 496 | 497 | if (dstbyte == MNI_B) 498 | SET_CC_V(); 499 | else 500 | CLR_CC_V(); 501 | 502 | CHGB_CC_N(dstbyte); 503 | CHGB_CC_Z(dstbyte); 504 | 505 | storeb_dst_2(); 506 | } 507 | -------------------------------------------------------------------------------- /bsdtrap.h: -------------------------------------------------------------------------------- 1 | /* bsdtrap.h. Definitions for values and structures used in bsdtrap.c 2 | * 3 | * $Revision: 1.30 $ 4 | * $Date: 1999/03/01 19:14:16 $ 5 | */ 6 | 7 | /* In this file, we list the trap number for each system call, 8 | * and the structures associated with several of the systems 9 | * calls in 2.11BSD UNIX 10 | */ 11 | 12 | #define S_INDIR 0 13 | #define S_EXIT 1 14 | #define S_FORK 2 15 | #define S_READ 3 16 | #define S_WRITE 4 17 | #define S_OPEN 5 18 | #define S_CLOSE 6 19 | #define S_WAIT4 7 20 | #define S_CREAT 8 21 | #define S_LINK 9 22 | #define S_UNLINK 10 23 | #define S_EXECV 11 24 | #define S_CHDIR 12 25 | #define S_FCHDIR 13 26 | #define S_MKNOD 14 27 | #define S_CHMOD 15 28 | #define S_CHOWN 16 29 | #define S_CHFLAGS 17 30 | #define S_FCHFLAGS 18 31 | #define S_LSEEK 19 32 | #define S_GETPID 20 33 | #define S_MOUNT 21 34 | #define S_UMOUNT 22 35 | #define S_SYSCTL 23 36 | #define S_GETUID 24 37 | #define S_GETEUID 25 38 | #define S_PTRACE 26 39 | #define S_GETPPID 27 40 | #define S_STATFS 28 41 | #define S_FSTATFS 29 42 | #define S_GETFSSTAT 30 43 | #define S_SIGACTION 31 44 | #define S_SIGPROCMASK 32 45 | #define S_ACCESS 33 46 | #define S_SIGPENDING 34 47 | #define S_SIGALTSTACK 35 48 | #define S_SYNC 36 49 | #define S_KILL 37 50 | #define S_STAT 38 51 | #define S_GETLOGIN 39 52 | #define S_LSTAT 40 53 | #define S_DUP 41 54 | #define S_PIPE 42 55 | #define S_SETLOGIN 43 56 | #define S_PROFIL 44 57 | #define S_SETUID 45 58 | #define S_SETEUID 46 59 | #define S_GETGID 47 60 | #define S_GETEGID 48 61 | #define S_SETGID 49 62 | #define S_SETEGID 50 63 | #define S_ACCT 51 64 | #define S_OLDPHYS 52 65 | #define S_OLDLOCK 53 66 | #define S_IOCTL 54 67 | #define S_REBOOT 55 68 | #define S_SYMLINK 57 69 | #define S_READLINK 58 70 | #define S_EXECVE 59 71 | #define S_UMASK 60 72 | #define S_CHROOT 61 73 | #define S_FSTAT 62 74 | #define S_GETPAGESIZE 64 75 | #define S_VFORK 66 76 | #define S_SBRK 69 77 | #define S_VHANGUP 76 78 | #define S_GETGROUPS 79 79 | #define S_SETGROUPS 80 80 | #define S_GETPGRP 81 81 | #define S_SETPGRP 82 82 | #define S_SETITIMER 83 83 | #define S_WAIT 84 84 | #define S_GETITIMER 86 85 | #define S_GETHOSTNAME 87 86 | #define S_SETHOSTNAME 88 87 | #define S_GETDTABLESIZE 89 88 | #define S_DUP2 90 89 | #define S_UNUSED1 91 90 | #define S_FCNTL 92 91 | #define S_SELECT 93 92 | #define S_UNUSED2 94 93 | #define S_FSYNC 95 94 | #define S_SETPRIORITY 96 95 | #define S_SOCKET 97 96 | #define S_CONNECT 98 97 | #define S_ACCEPT 99 98 | #define S_GETPRIORITY 100 99 | #define S_SEND 101 100 | #define S_RECV 102 101 | #define S_SIGRETURN 103 102 | #define S_BIND 104 103 | #define S_SETSOCKOPT 105 104 | #define S_LISTEN 106 105 | #define S_SIGSUSPEND 107 106 | #define S_SIGVEC 108 107 | #define S_SIGBLOCK 109 108 | #define S_SIGSETMASK 110 109 | #define S_SIGPAUSE 111 110 | #define S_SIGSTACK 112 111 | #define S_RECVMSG 113 112 | #define S_SENDMSG 114 113 | #define S_GETTIMEOFDAY 116 114 | #define S_GETRUSAGE 117 115 | #define S_GETSOCKOPT 118 116 | #define S_READV 120 117 | #define S_WRITEV 121 118 | #define S_SETTIMEOFDAY 122 119 | #define S_FCHOWN 123 120 | #define S_FCHMOD 124 121 | #define S_RECVFROM 125 122 | #define S_SETREUID 126 123 | #define S_SETREGID 127 124 | #define S_RENAME 128 125 | #define S_TRUNCATE 129 126 | #define S_FTRUNCATE 130 127 | #define S_FLOCK 131 128 | #define S_SENDTO 133 129 | #define S_SHUTDOWN 134 130 | #define S_SOCKETPAIR 135 131 | #define S_MKDIR 136 132 | #define S_RMDIR 137 133 | #define S_UTIMES 138 134 | #define S_ADJTIME 140 135 | #define S_GETPEERNAME 141 136 | #define S_GETHOSTID 142 137 | #define S_SETHOSTID 143 138 | #define S_GETRLIMIT 144 139 | #define S_SETRLIMIT 145 140 | #define S_KILLPG 146 141 | #define S_NOSYS147 147 142 | #define S_SETQUOTA 148 143 | #define S_QUOTA 149 144 | #define S_GETSOCKNAME 150 145 | 146 | 147 | /* 148 | * System call names. 149 | */ 150 | #ifdef BSDTRAP_NAME 151 | char *bsdtrap_name[] = { 152 | "indir", /* 0 = indir */ 153 | "exit", /* 1 = exit */ 154 | "fork", /* 2 = fork */ 155 | "read", /* 3 = read */ 156 | "write", /* 4 = write */ 157 | "open", /* 5 = open */ 158 | "close", /* 6 = close */ 159 | "wait4", /* 7 = wait4 */ 160 | "creat", /* 8 = creat */ 161 | "link", /* 9 = link */ 162 | "unlink", /* 10 = unlink */ 163 | "execv", /* 11 = execv */ 164 | "chdir", /* 12 = chdir */ 165 | "fchdir", /* 13 = fchdir */ 166 | "mknod", /* 14 = mknod */ 167 | "chmod", /* 15 = chmod */ 168 | "chown", /* 16 = chown; now 3 args */ 169 | "chflags", /* 17 = chflags */ 170 | "fchflags", /* 18 = fchflags */ 171 | "lseek", /* 19 = lseek */ 172 | "getpid", /* 20 = getpid */ 173 | "mount", /* 21 = mount */ 174 | "umount", /* 22 = umount */ 175 | "__sysctl", /* 23 = __sysctl */ 176 | "getuid", /* 24 = getuid */ 177 | "geteuid", /* 25 = geteuid */ 178 | "ptrace", /* 26 = ptrace */ 179 | "getppid", /* 27 = getppid */ 180 | "statfs", /* 28 = statfs */ 181 | "fstatfs", /* 29 = fstatfs */ 182 | "getfsstat", /* 30 = getfsstat */ 183 | "sigaction", /* 31 = sigaction */ 184 | "sigprocmask", /* 32 = sigprocmask */ 185 | "access", /* 33 = access */ 186 | "sigpending", /* 34 = sigpending */ 187 | "sigaltstack", /* 35 = sigaltstack */ 188 | "sync", /* 36 = sync */ 189 | "kill", /* 37 = kill */ 190 | "stat", /* 38 = stat */ 191 | "getlogin", /* 39 = getlogin */ 192 | "lstat", /* 40 = lstat */ 193 | "dup", /* 41 = dup */ 194 | "pipe", /* 42 = pipe */ 195 | "setlogin", /* 43 = setlogin */ 196 | "profil", /* 44 = profil */ 197 | "setuid", /* 45 = setuid */ 198 | "seteuid", /* 46 = seteuid */ 199 | "getgid", /* 47 = getgid */ 200 | "getegid", /* 48 = getegid */ 201 | "setgid", /* 49 = setgid */ 202 | "setegid", /* 50 = setegid */ 203 | "acct", /* 51 = turn acct off/on */ 204 | "old phys", /* 52 = old set phys addr */ 205 | "old lock", /* 53 = old lock in core */ 206 | "ioctl", /* 54 = ioctl */ 207 | "reboot", /* 55 = reboot */ 208 | "old mpx - nosys", /* 56 = old mpxchan */ 209 | "symlink", /* 57 = symlink */ 210 | "readlink", /* 58 = readlink */ 211 | "execve", /* 59 = execve */ 212 | "umask", /* 60 = umask */ 213 | "chroot", /* 61 = chroot */ 214 | "fstat", /* 62 = fstat */ 215 | "#63", /* 63 = used internally */ 216 | "getpagesize", /* 64 = getpagesize */ 217 | "4.3 mremap - nosys", /* 65 = mremap */ 218 | "vfork", /* 66 = vfork */ 219 | "old vread - nosys", /* 67 = old vread */ 220 | "old vwrite - nosys", /* 68 = old vwrite */ 221 | "sbrk", /* 69 = sbrk */ 222 | "4.3 sstk - nosys", /* 70 = sstk */ 223 | "4.3 mmap - nosys", /* 71 = mmap */ 224 | "old vadvise - nosys", /* 72 = old vadvise */ 225 | "4.3 munmap - nosys", /* 73 = munmap */ 226 | "4.3 mprotect - nosys", /* 74 = mprotect */ 227 | "4.3 madvise - nosys", /* 75 = madvise */ 228 | "vhangup", /* 76 = vhangup */ 229 | "old vlimit - nosys", /* 77 = old vlimit */ 230 | "4.3 mincore - nosys", /* 78 = mincore */ 231 | "getgroups", /* 79 = getgroups */ 232 | "setgroups", /* 80 = setgroups */ 233 | "getpgrp", /* 81 = getpgrp */ 234 | "setpgrp", /* 82 = setpgrp */ 235 | "setitimer", /* 83 = setitimer */ 236 | "wait", /* 84 = wait */ 237 | "4.3 swapon - nosys", /* 85 = swapon */ 238 | "getitimer", /* 86 = getitimer */ 239 | "gethostname", /* 87 = gethostname */ 240 | "sethostname", /* 88 = sethostname */ 241 | "getdtablesize", /* 89 = getdtablesize */ 242 | "dup2", /* 90 = dup2 */ 243 | "nosys", /* 91 = unused */ 244 | "fcntl", /* 92 = fcntl */ 245 | "select", /* 93 = select */ 246 | "nosys", /* 94 = unused */ 247 | "fsync", /* 95 = fsync */ 248 | "setpriority", /* 96 = setpriority */ 249 | "socket", /* 97 = socket */ 250 | "connect", /* 98 = connect */ 251 | "accept", /* 99 = accept */ 252 | "getpriority", /* 100 = getpriority */ 253 | "send", /* 101 = send */ 254 | "recv", /* 102 = recv */ 255 | "sigreturn", /* 103 = sigreturn */ 256 | "bind", /* 104 = bind */ 257 | "setsockopt", /* 105 = setsockopt */ 258 | "listen", /* 106 = listen */ 259 | "sigsuspend", /* 107 = sigsuspend */ 260 | "sigvec", /* 108 = sigvec */ 261 | "sigblock", /* 109 = sigblock */ 262 | "sigsetmask", /* 110 = sigsetmask */ 263 | "sigpause", /* 111 = sigpause */ 264 | "sigstack", /* 112 = sigstack */ 265 | "recvmsg", /* 113 = recvmsg */ 266 | "sendmsg", /* 114 = sendmsg */ 267 | "old vtrace - nosys", /* 115 = old vtrace */ 268 | "gettimeofday", /* 116 = gettimeofday */ 269 | "getrusage", /* 117 = getrusage */ 270 | "getsockopt", /* 118 = getsockopt */ 271 | "4.3 resuba - nosys", /* 119 = resuba */ 272 | "readv", /* 120 = readv */ 273 | "writev", /* 121 = writev */ 274 | "settimeofday", /* 122 = settimeofday */ 275 | "fchown", /* 123 = fchown */ 276 | "fchmod", /* 124 = fchmod */ 277 | "recvfrom", /* 125 = recvfrom */ 278 | "setreuid", /* 126 = setreuid */ 279 | "setregid", /* 127 = setregid */ 280 | "rename", /* 128 = rename */ 281 | "truncate", /* 129 = truncate */ 282 | "ftruncate", /* 130 = ftruncate */ 283 | "flock", /* 131 = flock */ 284 | "old portal - nosys", /* 132 = old portal */ 285 | "sendto", /* 133 = sendto */ 286 | "shutdown", /* 134 = shutdown */ 287 | "socketpair", /* 135 = socketpair */ 288 | "mkdir", /* 136 = mkdir */ 289 | "rmdir", /* 137 = rmdir */ 290 | "utimes", /* 138 = utimes */ 291 | "4.2 sigreturn - nosys", /* 139 = old 4.2 sigreturn */ 292 | "adjtime", /* 140 = adjtime */ 293 | "getpeername", /* 141 = getpeername */ 294 | "gethostid", /* 142 = gethostid */ 295 | "sethostid", /* 143 = sethostid */ 296 | "getrlimit", /* 144 = getrlimit */ 297 | "setrlimit", /* 145 = setrlimit */ 298 | "killpg", /* 146 = killpg */ 299 | "#147", /* 147 = nosys */ 300 | "setquota", /* 148 = setquota */ 301 | "quota", /* 149 = quota */ 302 | "getsockname", /* 150 = getsockname */ 303 | }; 304 | #endif 305 | 306 | /* fcntl defines used by open */ 307 | #define BSD_RDONLY 0x0000 /* open for reading only */ 308 | #define BSD_WRONLY 0x0001 /* open for writing only */ 309 | #define BSD_RDWR 0x0002 /* open for reading and writing */ 310 | #define BSD_NONBLOCK 0x0004 /* no delay */ 311 | #define BSD_APPEND 0x0008 /* set append mode */ 312 | #define BSD_SHLOCK 0x0010 /* open with shared file lock */ 313 | #define BSD_EXLOCK 0x0020 /* open with exclusive file lock */ 314 | #define BSD_ASYNC 0x0040 /* signal pgrp when data ready */ 315 | #define BSD_FSYNC 0x0080 /* synchronous writes */ 316 | #define BSD_CREAT 0x0200 /* create if nonexistant */ 317 | #define BSD_TRUNC 0x0400 /* truncate to zero length */ 318 | #define BSD_EXCL 0x0800 /* error if already exists */ 319 | 320 | 321 | /* stat struct, used by S_STAT, S_FSTAT, S_LSTAT */ 322 | struct tr_stat { 323 | int16_t st_dev; 324 | u_int16_t st_ino; 325 | u_int16_t st_mode; 326 | int16_t st_nlink; 327 | u_int16_t st_uid; 328 | u_int16_t st_gid; 329 | int16_t st_rdev; 330 | int8_t st_size[4]; /* Alignment problems */ 331 | int8_t st_atim[4]; /* Alignment problems */ 332 | int16_t st_spare1; 333 | int8_t st_mtim[4]; /* Alignment problems */ 334 | int16_t st_spare2; 335 | int8_t st_ctim[4]; /* Alignment problems */ 336 | int16_t st_spare3; 337 | int8_t st_blksize[4]; /* Alignment problems */ 338 | int8_t st_blocks[4]; /* Alignment problems */ 339 | u_int16_t st_flags; 340 | u_int16_t st_spare4[3]; 341 | }; 342 | 343 | /* Directory entry */ 344 | #define TR_DIRBLKSIZ 512 345 | #define TR_MAXNAMLEN 63 346 | struct tr_direct { 347 | u_int16_t d_ino; /* inode number of entry */ 348 | u_int16_t d_reclen; /* length of this record */ 349 | u_int16_t d_namlen; /* length of string in d_name */ 350 | char d_name[TR_MAXNAMLEN + 1]; /* name must be no longer than this */ 351 | }; 352 | 353 | /* used by S_ADJTIME */ 354 | struct tr_timeval { 355 | u_int32_t tv_sec; /* seconds */ 356 | u_int32_t tv_usec; /* and microseconds */ 357 | }; 358 | /* Used by S_GETTIMEOFDAY */ 359 | struct tr_timezone { 360 | int16_t tz_minuteswest; /* minutes west of Greenwich */ 361 | int16_t tz_dsttime; /* type of dst correction */ 362 | }; 363 | 364 | /* used in itimer calls */ 365 | struct tr_itimerval { 366 | struct tr_timeval it_interval; /* timer interval */ 367 | struct tr_timeval it_value; /* current value */ 368 | }; 369 | 370 | /* Used by socket calls */ 371 | struct tr_sockaddr { 372 | u_int16_t sa_family; /* address family */ 373 | char sa_data[14]; /* up to 14 bytes of direct address */ 374 | }; 375 | 376 | /* used in rlimit calls */ 377 | struct tr_rlimit { 378 | int32_t rlim_cur; /* current (soft) limit */ 379 | int32_t rlim_max; /* maximum value for rlim_cur */ 380 | }; 381 | 382 | struct tr_rusage { 383 | struct tr_timeval ru_utime; /* user time used */ 384 | struct tr_timeval ru_stime; /* system time used */ 385 | u_int32_t ru_maxrss; 386 | u_int32_t ru_ixrss; /* integral shared memory size */ 387 | u_int32_t ru_idrss; /* integral unshared data size */ 388 | u_int32_t ru_isrss; /* integral unshared stack size */ 389 | u_int32_t ru_minflt; /* page reclaims */ 390 | u_int32_t ru_majflt; /* page faults */ 391 | u_int32_t ru_ovly; /* overlay changes */ 392 | u_int32_t ru_nswap; /* swaps */ 393 | u_int32_t ru_inblock; /* block input operations */ 394 | u_int32_t ru_oublock; /* block output operations */ 395 | u_int32_t ru_msgsnd; /* messages sent */ 396 | u_int32_t ru_msgrcv; /* messages received */ 397 | u_int32_t ru_nsignals; /* signals received */ 398 | u_int32_t ru_nvcsw; /* voluntary context switches */ 399 | u_int32_t ru_nivcsw; /* involuntary context switches */ 400 | }; 401 | 402 | /* for writev, readv */ 403 | struct tr_iovec { 404 | u_int16_t iov_base; 405 | u_int16_t iov_len; 406 | }; 407 | 408 | 409 | /* A union which will point at the trap args, so that 410 | * we can get at the various args of different types 411 | */ 412 | typedef union { 413 | int16_t sarg[6]; /* Signed 16-bit args */ 414 | u_int16_t uarg[6]; /* Unsigned 16-bit args */ 415 | } arglist; 416 | 417 | #define sarg1 A->sarg[0] 418 | #define sarg2 A->sarg[1] 419 | #define sarg3 A->sarg[2] 420 | #define sarg4 A->sarg[3] 421 | #define sarg5 A->sarg[4] 422 | #define sarg6 A->sarg[5] 423 | #define uarg1 A->uarg[0] 424 | #define uarg2 A->uarg[1] 425 | #define uarg3 A->uarg[2] 426 | #define uarg4 A->uarg[3] 427 | #define uarg5 A->uarg[4] 428 | #define uarg6 A->uarg[5] 429 | -------------------------------------------------------------------------------- /ea.c: -------------------------------------------------------------------------------- 1 | /* ea.c - Calculate, load, and store using the proper effective address as 2 | * specified by the current instruction. Also push and pop stack operations. 3 | * 4 | * $Revision: 2.17 $ 5 | * $Date: 1999/09/17 05:11:10 $ 6 | */ 7 | #include "defines.h" 8 | 9 | void load_ea(void) 10 | { 11 | u_int16_t indirect; 12 | 13 | switch (DST_MODE) { 14 | case 0: 15 | illegal(); 16 | return; 17 | case 1: 18 | dstword = regs[DST_REG]; 19 | return; 20 | case 2: 21 | dstword = regs[DST_REG]; /* this is wrong for 11/34 */ 22 | regs[DST_REG] += 2; 23 | return; 24 | case 3: 25 | indirect = regs[DST_REG]; /* this is wrong for 11/34 */ 26 | regs[DST_REG] += 2; 27 | lli_word(indirect, dstword); 28 | return; 29 | case 4: 30 | regs[DST_REG] -= 2; 31 | dstword = regs[DST_REG]; 32 | return; 33 | case 5: 34 | regs[DST_REG] -= 2; 35 | indirect = regs[DST_REG]; 36 | lli_word(indirect, dstword); 37 | return; 38 | case 6: 39 | lli_word(regs[PC], indirect); 40 | regs[PC] += 2; 41 | dstword = regs[DST_REG] + indirect; 42 | return; 43 | case 7: 44 | lli_word(regs[PC], indirect); 45 | regs[PC] += 2; 46 | indirect = regs[DST_REG] + indirect; 47 | ll_word(indirect, dstword); 48 | return; 49 | } 50 | illegal(); 51 | } 52 | 53 | 54 | INLINE void pop(void) 55 | { 56 | ll_word(regs[SP], dstword); 57 | regs[SP] += 2; 58 | } 59 | 60 | 61 | INLINE void push(void) 62 | { 63 | regs[SP] -= 2; 64 | sl_word(regs[SP], srcword); 65 | } 66 | 67 | 68 | void loadb_dst(void) 69 | { 70 | u_int16_t addr, indirect; 71 | 72 | switch (DST_MODE) { 73 | case 0: 74 | dstbyte = (u_int8_t) (regs[DST_REG] & 0377); 75 | return; 76 | case 1: 77 | addr = regs[DST_REG]; 78 | ea_addr = addr; 79 | if (DST_REG == PC) { 80 | lli_byte(addr, dstbyte) 81 | } else { 82 | ll_byte(addr, dstbyte); 83 | } 84 | return; 85 | case 2: 86 | addr = regs[DST_REG]; 87 | ea_addr = addr; 88 | if (DST_REG == PC) { 89 | lli_byte(addr, dstbyte) 90 | } else { 91 | ll_byte(addr, dstbyte); 92 | } 93 | if (DST_REG >= 6) 94 | regs[DST_REG] += 2; 95 | else 96 | regs[DST_REG] += 1; 97 | return; 98 | case 3: 99 | indirect = regs[DST_REG]; 100 | if (DST_REG == PC) { 101 | lli_word(indirect, addr) 102 | } else { 103 | ll_word(indirect, addr); 104 | } 105 | ea_addr = addr; 106 | ll_byte(addr, dstbyte); 107 | regs[DST_REG] += 2; 108 | return; 109 | case 4: 110 | if (DST_REG >= 6) 111 | regs[DST_REG] -= 2; 112 | else 113 | regs[DST_REG] -= 1; 114 | addr = regs[DST_REG]; 115 | ea_addr = addr; 116 | ll_byte(addr, dstbyte); 117 | return; 118 | case 5: 119 | regs[DST_REG] -= 2; 120 | indirect = regs[DST_REG]; 121 | ll_word(indirect, addr); 122 | ea_addr = addr; 123 | ll_byte(addr, dstbyte); 124 | return; 125 | case 6: 126 | lli_word(regs[PC], indirect); 127 | regs[PC] += 2; 128 | addr = regs[DST_REG] + indirect; 129 | ea_addr = addr; 130 | ll_byte(addr, dstbyte); 131 | return; 132 | case 7: 133 | lli_word(regs[PC], indirect); 134 | regs[PC] += 2; 135 | indirect = regs[DST_REG] + indirect; 136 | ll_word(indirect, addr); 137 | ea_addr = addr; 138 | ll_byte(addr, dstbyte); 139 | return; 140 | } 141 | illegal(); 142 | } 143 | 144 | 145 | void loadb_src(void) 146 | { 147 | u_int16_t addr, indirect; 148 | 149 | switch (SRC_MODE) { 150 | case 0: 151 | srcbyte = (u_int8_t) (regs[SRC_REG] & 0377); 152 | return; 153 | case 1: 154 | addr = regs[SRC_REG]; 155 | if (SRC_REG == PC) { 156 | lli_byte(addr, srcbyte); 157 | } else { 158 | ll_byte(addr, srcbyte); 159 | } 160 | return; 161 | case 2: 162 | addr = regs[SRC_REG]; 163 | if (SRC_REG == PC) { 164 | lli_byte(addr, srcbyte); 165 | } else { 166 | ll_byte(addr, srcbyte); 167 | } 168 | if (SRC_REG >= 6) 169 | regs[SRC_REG] += 2; 170 | else 171 | regs[SRC_REG] += 1; 172 | return; 173 | case 3: 174 | indirect = regs[SRC_REG]; 175 | if (SRC_REG == PC) { 176 | lli_word(indirect, addr) 177 | } else { 178 | ll_word(indirect, addr); 179 | } 180 | ll_byte(addr, srcbyte); 181 | regs[SRC_REG] += 2; 182 | return; 183 | case 4: 184 | if (SRC_REG >= 6) 185 | regs[SRC_REG] -= 2; 186 | else 187 | regs[SRC_REG] -= 1; 188 | addr = regs[SRC_REG]; 189 | ll_byte(addr, srcbyte); 190 | return; 191 | case 5: 192 | regs[SRC_REG] -= 2; 193 | indirect = regs[SRC_REG]; 194 | ll_word(indirect, addr); 195 | ll_byte(addr, srcbyte); 196 | return; 197 | case 6: 198 | lli_word(regs[PC], indirect); 199 | regs[PC] += 2; 200 | addr = regs[SRC_REG] + indirect; 201 | ll_byte(addr, srcbyte); 202 | return; 203 | case 7: 204 | lli_word(regs[PC], indirect); 205 | regs[PC] += 2; 206 | indirect = regs[SRC_REG] + indirect; 207 | ll_word(indirect, addr); 208 | ll_byte(addr, srcbyte); 209 | return; 210 | } 211 | illegal(); 212 | } 213 | 214 | void storeb_dst(void) 215 | { 216 | u_int16_t addr, indirect; 217 | 218 | switch (DST_MODE) { 219 | case 0: 220 | regs[DST_REG] &= 0xff00; 221 | regs[DST_REG] |= srcbyte; 222 | return; 223 | case 1: 224 | addr = regs[DST_REG]; 225 | sl_byte(addr, srcbyte); 226 | return; 227 | case 2: 228 | addr = regs[DST_REG]; 229 | sl_byte(addr, srcbyte); 230 | if (DST_REG >= 6) 231 | regs[DST_REG] += 2; 232 | else 233 | regs[DST_REG] += 1; 234 | return; 235 | case 3: 236 | indirect = regs[DST_REG]; 237 | ll_word(indirect, addr); 238 | sl_byte(addr, srcbyte); 239 | regs[DST_REG] += 2; 240 | return; 241 | case 4: 242 | if (DST_REG >= 6) /* xyz */ 243 | regs[DST_REG] -= 2; 244 | else 245 | regs[DST_REG] -= 1; 246 | addr = regs[DST_REG]; 247 | sl_byte(addr, srcbyte); 248 | return; 249 | case 5: 250 | regs[DST_REG] -= 2; 251 | indirect = regs[DST_REG]; 252 | ll_word(indirect, addr); 253 | sl_byte(addr, srcbyte); 254 | return; 255 | case 6: 256 | lli_word(regs[PC], indirect); 257 | regs[PC] += 2; 258 | addr = regs[DST_REG] + indirect; 259 | sl_byte(addr, srcbyte); 260 | return; 261 | case 7: 262 | lli_word(regs[PC], indirect); 263 | regs[PC] += 2; 264 | indirect = regs[DST_REG] + indirect; 265 | ll_word(indirect, addr); 266 | sl_byte(addr, srcbyte); 267 | return; 268 | } 269 | illegal(); 270 | } 271 | 272 | 273 | INLINE void storeb_dst_2(void) 274 | { 275 | if (DST_MODE == 0) { 276 | regs[DST_REG] &= 0xff00; 277 | regs[DST_REG] |= dstbyte; 278 | return; 279 | } 280 | sl_byte(ea_addr, dstbyte); 281 | } 282 | 283 | 284 | void loadp_dst(void) 285 | { 286 | u_int16_t addr, indirect; 287 | 288 | switch (DST_MODE) { 289 | case 0: 290 | srcword = regs[DST_REG]; 291 | return; 292 | case 1: 293 | addr = regs[DST_REG]; 294 | ll_word(addr, srcword); 295 | return; 296 | case 2: 297 | addr = regs[DST_REG]; 298 | ll_word(addr, srcword); 299 | regs[DST_REG] += 2; 300 | return; 301 | case 3: 302 | indirect = regs[DST_REG]; 303 | ll_word(indirect, addr); 304 | ll_word(addr, srcword); 305 | regs[DST_REG] += 2; 306 | return; 307 | case 4: 308 | regs[DST_REG] -= 2; 309 | addr = regs[DST_REG]; 310 | ll_word(addr, srcword); 311 | return; 312 | case 5: 313 | regs[DST_REG] -= 2; 314 | indirect = regs[DST_REG]; 315 | ll_word(indirect, addr); 316 | ll_word(addr, srcword); 317 | return; 318 | case 6: 319 | lli_word(regs[PC], indirect); 320 | regs[PC] += 2; 321 | addr = regs[DST_REG] + indirect; 322 | if (DST_REG == PC) 323 | lli_word(addr, srcword) 324 | else 325 | ll_word(addr, srcword); 326 | return; 327 | case 7: 328 | not_impl(); 329 | } 330 | illegal(); 331 | } 332 | 333 | 334 | void storep_dst(void) 335 | { 336 | u_int16_t addr, indirect; 337 | 338 | switch (DST_MODE) { 339 | case 0: 340 | regs[DST_REG] = dstword; 341 | return; 342 | case 1: 343 | addr = regs[DST_REG]; 344 | sl_word(addr, dstword); 345 | return; 346 | case 2: 347 | addr = regs[DST_REG]; 348 | sl_word(addr, dstword); 349 | regs[DST_REG] += 2; 350 | return; 351 | case 3: 352 | indirect = regs[DST_REG]; 353 | ll_word(indirect, addr); 354 | sl_word(addr, dstword); 355 | regs[DST_REG] += 2; 356 | return; 357 | case 4: 358 | regs[DST_REG] -= 2; 359 | addr = regs[DST_REG]; 360 | sl_word(addr, dstword); 361 | return; 362 | case 5: 363 | regs[DST_REG] -= 2; 364 | indirect = regs[DST_REG]; 365 | ll_word(indirect, addr); 366 | sl_word(addr, dstword); 367 | return; 368 | case 6: 369 | lli_word(regs[PC], indirect); 370 | regs[PC] += 2; 371 | addr = regs[DST_REG] + indirect; 372 | sl_word(addr, dstword); 373 | return; 374 | case 7: 375 | not_impl(); 376 | } 377 | illegal(); 378 | } 379 | 380 | 381 | void load_src(void) 382 | { 383 | u_int16_t addr, indirect; 384 | 385 | switch (SRC_MODE) { 386 | case 0: 387 | srcword = regs[SRC_REG]; 388 | return; 389 | case 1: 390 | addr = regs[SRC_REG]; 391 | if (SRC_REG == PC) { 392 | lli_word(addr, srcword) 393 | } else { 394 | ll_word(addr, srcword); 395 | } 396 | return; 397 | case 2: 398 | addr = regs[SRC_REG]; 399 | if (SRC_REG == PC) { 400 | lli_word(addr, srcword) 401 | } else { 402 | ll_word(addr, srcword); 403 | } 404 | regs[SRC_REG] += 2; 405 | return; 406 | case 3: 407 | indirect = regs[SRC_REG]; 408 | if (SRC_REG == PC) { 409 | lli_word(indirect, addr) 410 | } else { 411 | ll_word(indirect, addr); 412 | } 413 | regs[SRC_REG] += 2; /* is this right ? */ 414 | ll_word(addr, srcword); 415 | return; 416 | case 4: 417 | regs[SRC_REG] -= 2; 418 | addr = regs[SRC_REG]; 419 | ll_word(addr, srcword); 420 | return; 421 | case 5: 422 | regs[SRC_REG] -= 2; 423 | indirect = regs[SRC_REG]; 424 | ll_word(indirect, addr); 425 | ll_word(addr, srcword); 426 | return; 427 | case 6: 428 | lli_word(regs[PC], indirect); 429 | regs[PC] += 2; 430 | addr = regs[SRC_REG] + indirect; 431 | ll_word(addr, srcword); 432 | return; 433 | case 7: 434 | lli_word(regs[PC], indirect); 435 | regs[PC] += 2; 436 | indirect = regs[SRC_REG] + indirect; 437 | ll_word(indirect, addr); 438 | ll_word(addr, srcword); 439 | return; 440 | } 441 | illegal(); 442 | } 443 | 444 | 445 | void store_dst(void) 446 | { 447 | u_int16_t addr, indirect; 448 | 449 | switch (DST_MODE) { 450 | case 0: 451 | regs[DST_REG] = dstword; 452 | return; 453 | case 1: 454 | addr = regs[DST_REG]; 455 | sl_word(addr, dstword); 456 | return; 457 | case 2: 458 | addr = regs[DST_REG]; 459 | sl_word(addr, dstword); 460 | regs[DST_REG] += 2; 461 | return; 462 | case 3: 463 | indirect = regs[DST_REG]; 464 | ll_word(indirect, addr); 465 | regs[DST_REG] += 2; /* is this right ? */ 466 | sl_word(addr, dstword); 467 | return; 468 | case 4: 469 | regs[DST_REG] -= 2; 470 | addr = regs[DST_REG]; 471 | sl_word(addr, dstword); 472 | return; 473 | case 5: 474 | regs[DST_REG] -= 2; 475 | indirect = regs[DST_REG]; 476 | ll_word(indirect, addr); 477 | sl_word(addr, dstword); 478 | return; 479 | case 6: 480 | lli_word(regs[PC], indirect); 481 | regs[PC] += 2; 482 | addr = regs[DST_REG] + indirect; 483 | sl_word(addr, dstword); 484 | return; 485 | case 7: 486 | lli_word(regs[PC], indirect); 487 | regs[PC] += 2; 488 | indirect = regs[DST_REG] + indirect; 489 | ll_word(indirect, addr); 490 | sl_word(addr, dstword); 491 | return; 492 | } 493 | illegal(); 494 | } 495 | 496 | 497 | void load_dst(void) 498 | { 499 | u_int16_t addr, indirect; 500 | 501 | switch (DST_MODE) { 502 | case 0: 503 | dstword = regs[DST_REG]; 504 | return; 505 | case 1: 506 | addr = regs[DST_REG]; 507 | ea_addr = addr; 508 | if (DST_REG == PC) { 509 | lli_word(addr, dstword) 510 | } else { 511 | ll_word(addr, dstword); 512 | } 513 | return; 514 | case 2: 515 | addr = regs[DST_REG]; 516 | ea_addr = addr; 517 | if (DST_REG == PC) { 518 | lli_word(addr, dstword) 519 | } else { 520 | ll_word(addr, dstword); 521 | } 522 | regs[DST_REG] += 2; 523 | return; 524 | case 3: 525 | indirect = regs[DST_REG]; 526 | if (DST_REG == PC) { 527 | lli_word(indirect, addr) 528 | } else { 529 | ll_word(indirect, addr); 530 | } 531 | ea_addr = addr; 532 | ll_word(addr, dstword); 533 | regs[DST_REG] += 2; 534 | return; 535 | case 4: 536 | regs[DST_REG] -= 2; 537 | addr = regs[DST_REG]; 538 | ea_addr = addr; 539 | ll_word(addr, dstword); 540 | return; 541 | case 5: 542 | regs[DST_REG] -= 2; 543 | indirect = regs[DST_REG]; 544 | ll_word(indirect, addr); 545 | ea_addr = addr; 546 | ll_word(addr, dstword); 547 | return; 548 | case 6: 549 | lli_word(regs[PC], indirect); 550 | regs[PC] += 2; 551 | addr = regs[DST_REG] + indirect; 552 | ea_addr = addr; 553 | ll_word(addr, dstword); 554 | return; 555 | case 7: 556 | lli_word(regs[PC], indirect); 557 | regs[PC] += 2; 558 | indirect = regs[DST_REG] + indirect; 559 | ll_word(indirect, addr); 560 | ea_addr = addr; 561 | ll_word(addr, dstword); 562 | return; 563 | } 564 | illegal(); 565 | } 566 | 567 | 568 | INLINE void store_dst_2(void) 569 | { 570 | if (DST_MODE == 0) { 571 | regs[DST_REG] = dstword; 572 | return; 573 | } 574 | sl_word(ea_addr, dstword); 575 | } 576 | -------------------------------------------------------------------------------- /defines.h: -------------------------------------------------------------------------------- 1 | /* defines.h - Definitions of things needed in all C files 2 | * 3 | * $Revision: 2.75 $ 4 | * $Date: 2008/05/19 13:42:39 $ 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | /* Defines for ifdef'd code -- define them in the Makefile */ 18 | 19 | /* #define DEBUG adds in debugging code */ 20 | /* #define ZERO_MEMORY zeros all of process memory before 21 | it starts to run */ 22 | /* #define NATIVES allows native binaries and PDP-11 23 | binaries in the filespace */ 24 | /* #define EMU211 add 2.11BSD emulation */ 25 | /* #define EMUV1 add 1st Edition emulation */ 26 | /* #define INLINE inline inlines some functions (needs gcc) */ 27 | 28 | 29 | /* Optimisation defines */ 30 | #ifndef INLINE 31 | #define INLINE 32 | #endif 33 | 34 | /* Special defines to enable/disable certain 35 | * functionality. These are added as required 36 | * to port to new platforms. Please send in new 37 | * defines, please! 38 | */ 39 | 40 | #if defined(__FreeBSD__) && __FreeBSD__ < 3 41 | #define NO_GETPGID 42 | #endif 43 | 44 | #ifdef __FreeBSD__ 45 | #define Reboot(x) reboot(x) 46 | #endif 47 | 48 | #ifdef __linux__ 49 | #define NO_CHFLAGS 50 | #define NO_STFLAGS 51 | #define NO_GETPGID 52 | #define NEED_MAP_FCNTL 53 | #define SIGEMT 0 54 | #ifndef SIGSYS 55 | #define SIGSYS 0 56 | #endif 57 | #define OXTABS XTABS 58 | #define VDSUSP VSUSP /* I don't think these are equivalent */ 59 | #define O_SHLOCK 0 60 | #define O_EXLOCK 0 61 | #endif 62 | 63 | #if defined(__NetBSD__) || defined(__OpenBSD__) 64 | #define Reboot(x) reboot(x,NULL) 65 | #endif 66 | 67 | #ifndef Reboot 68 | #define Reboot(x) exit(0) 69 | #endif 70 | 71 | #if !defined(__FreeBSD__) && !defined(__NetBSD__) && \ 72 | !defined(__OpenBSD__) && !defined(__linux__) && !defined(__APPLE__) 73 | #define NEED_INT_N 74 | #endif 75 | 76 | /* Type definitions for PDP data types. You may need to 77 | * define NEED_INT_N if your system doesn't provide the 78 | * types defined below. If you do this, the best way is 79 | * to add some #if .. #define .. #endif lines above, 80 | * rather then modifying the ones below. If you make 81 | * changes to the #if's above, then I would be very 82 | * happy to include them. 83 | * 84 | * Warren Toomey: wkt@tuhs.org 85 | */ 86 | 87 | #ifdef NEED_INT_N 88 | typedef char int8_t; 89 | typedef short int16_t; 90 | typedef long int32_t; 91 | typedef unsigned char u_int8_t; 92 | typedef unsigned short u_int16_t; 93 | typedef unsigned long u_int32_t; 94 | #endif 95 | 96 | /* Macro defines for debug output, makes 97 | * the code look somewhat cleaner 98 | */ 99 | 100 | #ifdef DEBUG 101 | #define TrapDebug(x) if (trap_debug) (void)fprintf x 102 | #define InstDebug(x) if (inst_debug) (void)fprintf x 103 | #define JsrDebug(x) if (jsr_debug) (void)fprintf x 104 | #define FpDebug(x) if (fp_debug) (void)fprintf x 105 | #else 106 | #define TrapDebug(x) 107 | #define InstDebug(x) 108 | #define JsrDebug(x) 109 | #define FpDebug(x) 110 | #endif 111 | 112 | /* Defines for -DSTREAM_BUFFERING */ 113 | #define NFILE 40 /* Number of file pointers we can buffer */ 114 | #define ValidFD(x) ((x>=0) && (x> 9 ) 234 | #define SRC_REG (( ir & 0700 ) >> 6 ) 235 | #define DST_MODE (( ir & 070 ) >> 3 ) 236 | #define DST_REG ( ir & 07 ) 237 | 238 | #define LSBIT 1 /* least significant bit */ 239 | 240 | #define MPI 0077777 /* most positive integer */ 241 | #define MNI 0100000 /* most negative integer */ 242 | #define NEG_1 0177777 /* negative one */ 243 | #define SIGN 0100000 /* sign bit */ 244 | #define CARRY 0200000 /* set if carry out */ 245 | 246 | #define MPI_B 0177 /* most positive integer (byte) */ 247 | #define MNI_B 0200 /* most negative integer (byte) */ 248 | #define NEG_1_B 0377 /* negative one (byte) */ 249 | #define SIGN_B 0200 /* sign bit (byte) */ 250 | #define CARRY_B 0400 /* set if carry out (byte) */ 251 | 252 | #define LOW16( data ) (u_int16_t)(( data ) & 0177777 ) /* mask the lower 16 bits */ 253 | #define LOW8( data ) (u_int8_t)(( data ) & 0377 ) /* mask the lower 8 bits */ 254 | 255 | #define CHG_CC_N( d ) if ((d) & SIGN ) \ 256 | SET_CC_N(); \ 257 | else \ 258 | CLR_CC_N() 259 | 260 | #define CHGB_CC_N( d ) if ((d) & SIGN_B ) \ 261 | SET_CC_N(); \ 262 | else \ 263 | CLR_CC_N() 264 | 265 | #define CHG_CC_Z( d ) if ( d ) \ 266 | CLR_CC_Z(); \ 267 | else \ 268 | SET_CC_Z() 269 | 270 | #define CHGB_CC_Z( d ) if ( LOW8( d )) \ 271 | CLR_CC_Z(); \ 272 | else \ 273 | SET_CC_Z() 274 | 275 | #define CHG_CC_C( d ) if ((d) & CARRY ) \ 276 | SET_CC_C(); \ 277 | else \ 278 | CLR_CC_C() 279 | 280 | #define CHG_CC_IC( d ) if ((d) & CARRY ) \ 281 | CLR_CC_C(); \ 282 | else \ 283 | SET_CC_C() 284 | 285 | #define CHGB_CC_IC( d ) if ((d) & CARRY_B ) \ 286 | CLR_CC_C(); \ 287 | else \ 288 | SET_CC_C() 289 | 290 | #define CHG_CC_V( d1, d2, d3 ) \ 291 | if ((( d1 & SIGN ) == ( d2 & SIGN )) \ 292 | && (( d1 & SIGN ) != ( d3 & SIGN ))) \ 293 | SET_CC_V(); \ 294 | else \ 295 | CLR_CC_V() 296 | 297 | #define CHG_CC_VC( d1, d2, d3 ) \ 298 | if ((( d1 & SIGN ) != ( d2 & SIGN )) \ 299 | && (( d2 & SIGN ) == ( d3 & SIGN ))) \ 300 | SET_CC_V(); \ 301 | else \ 302 | CLR_CC_V() 303 | 304 | #define CHG_CC_VS( d1, d2, d3 ) \ 305 | if ((( d1 & SIGN ) != ( d2 & SIGN )) \ 306 | && (( d1 & SIGN ) == ( d3 & SIGN ))) \ 307 | SET_CC_V(); \ 308 | else \ 309 | CLR_CC_V() 310 | 311 | #define CHGB_CC_V( d1, d2, d3 ) \ 312 | if ((( d1 & SIGN_B ) == ( d2 & SIGN_B )) \ 313 | && (( d1 & SIGN_B ) != ( d3 & SIGN_B ))) \ 314 | SET_CC_V(); \ 315 | else \ 316 | CLR_CC_V() 317 | 318 | #define CHGB_CC_VC(d1,d2,d3) \ 319 | if ((( d1 & SIGN_B ) != ( d2 & SIGN_B )) \ 320 | && (( d2 & SIGN_B ) == ( d3 & SIGN_B ))) \ 321 | SET_CC_V(); \ 322 | else \ 323 | CLR_CC_V() 324 | 325 | #define CHG_CC_V_XOR_C_N() \ 326 | if ((( CC_C ) && \ 327 | ( CC_N )) \ 328 | || ((!( CC_C )) && \ 329 | ( ! ( CC_N )))) \ 330 | CLR_CC_V(); \ 331 | else \ 332 | SET_CC_V() 333 | 334 | 335 | /* Macros to read and write loctions in 336 | * main memory. 337 | */ 338 | 339 | extern u_int16_t *adptr; 340 | 341 | #define copylong(to,from) \ 342 | buf = (char *) &(to); buf2 = (char *) &(from); \ 343 | buf[0]=buf2[2]; buf[1]=buf2[3]; buf[2]=buf2[0]; buf[3]=buf2[1] 344 | 345 | #ifndef EMUV1 346 | /* lli_word() - Load a word from the given ispace logical address. */ 347 | #define lli_word(addr, word) \ 348 | { adptr= (u_int16_t *)&(ispace[addr]); word= *adptr; } 349 | 350 | /* ll_word() - Load a word from the given logical address. */ 351 | #define ll_word(addr, word) \ 352 | { adptr= (u_int16_t *)&(dspace[addr]); word= *adptr; } 353 | 354 | /* sl_word() - Store a word at the given logical address. */ 355 | #ifdef WRITEBASE 356 | #define sl_word(addr, word) \ 357 | { if ((u_int16_t)addr < dwrite_base) seg_fault(); \ 358 | adptr= (u_int16_t *)&(dspace[addr]); *adptr= word; } 359 | #else 360 | #define sl_word(addr, word) \ 361 | { adptr= (u_int16_t *)&(dspace[addr]); *adptr= word; } 362 | #endif 363 | 364 | /* lli_byte() - Load a byte from the given logical ispace address. */ 365 | #define lli_byte(addr, byte) \ 366 | byte = ispace[addr]; 367 | 368 | /* ll_byte() - Load a byte from the given logical address. */ 369 | #define ll_byte(addr, byte) \ 370 | byte = dspace[addr]; 371 | 372 | /* sl_byte() - Store a byte at the given logical address. */ 373 | #ifdef WRITEBASE 374 | #define sl_byte(addr, byte) \ 375 | { if (addr < dwrite_base) seg_fault(); \ 376 | dspace[addr]= byte; } 377 | #else 378 | #define sl_byte(addr, byte) \ 379 | { dspace[addr]= byte; } 380 | #endif 381 | #else 382 | /* These versions of the macros are required */ 383 | /* because the KE11-A module is mapped into */ 384 | /* a process' memory space in 1st Edition */ 385 | #define KE11LO 0177300 386 | #define KE11HI 0177317 387 | 388 | /* lli_word() - Load a word from the given ispace logical address. */ 389 | #define lli_word(addr, word) \ 390 | { if ((Binary=KE11LO) && (addr<=KE11HI)) { \ 391 | word= kell_word(addr); \ 392 | } else { adptr= (u_int16_t *)&(ispace[addr]); word= *adptr; } \ 393 | } 394 | 395 | /* ll_word() - Load a word from the given logical address. */ 396 | #define ll_word(addr, word) \ 397 | { if ((Binary=KE11LO) && (addr<=KE11HI)) { \ 398 | word= kell_word(addr); \ 399 | } else { adptr= (u_int16_t *)&(dspace[addr]); word= *adptr; } \ 400 | } 401 | 402 | /* sl_word() - Store a word at the given logical address. */ 403 | #ifdef WRITEBASE 404 | #define sl_word(addr, word) \ 405 | { if ((u_int16_t)addr < dwrite_base) seg_fault(); \ 406 | if ((Binary=KE11LO) && (addr<=KE11HI)) { \ 407 | kesl_word(addr, word); \ 408 | } else { adptr= (u_int16_t *)&(dspace[addr]); *adptr= word; } \ 409 | } 410 | #else 411 | #define sl_word(addr, word) \ 412 | { if ((Binary=KE11LO) && (addr<=KE11HI)) { \ 413 | kesl_word(addr, word); \ 414 | } else { adptr= (u_int16_t *)&(dspace[addr]); *adptr= word; } \ 415 | } 416 | #endif 417 | 418 | /* lli_byte() - Load a byte from the given logical ispace address. */ 419 | #define lli_byte(addr, byte) \ 420 | byte = ispace[addr]; 421 | 422 | /* ll_byte() - Load a byte from the given logical address. */ 423 | #define ll_byte(addr, byte) \ 424 | { if ((Binary=KE11LO) && (addr<=KE11HI)) { \ 425 | byte= kell_byte(addr); \ 426 | } else byte = dspace[addr]; \ 427 | } 428 | 429 | /* sl_byte() - Store a byte at the given logical address. */ 430 | #ifdef WRITEBASE 431 | #define sl_byte(addr, byte) \ 432 | { if (addr < dwrite_base) seg_fault(); \ 433 | if ((Binary=KE11LO) && (addr<=KE11HI)) { \ 434 | kesl_byte(addr, byte); \ 435 | } else dspace[addr]= byte; \ 436 | } 437 | #else 438 | #define sl_byte(addr, byte) \ 439 | { if ((Binary=KE11LO) && (addr<=KE11HI)) { \ 440 | kesl_byte(addr, byte); \ 441 | } else dspace[addr]= byte; \ 442 | } 443 | #endif 444 | #endif 445 | 446 | 447 | 448 | 449 | /* Function prototypes */ 450 | 451 | /* aout.c */ 452 | int load_a_out P((const char *file, const char *origpath, int want_env)) 453 | /*@globals errno,stdout,stderr; @ */ ; 454 | #ifdef EMU211 455 | void do_bsd_overlay P((void)); 456 | #endif 457 | 458 | /* branch.c */ 459 | void br P((void)); 460 | void blos P((void)); 461 | void bge P((void)); 462 | void blt P((void)); 463 | void ble P((void)); 464 | void bgt P((void)); 465 | void jmp P((void)); 466 | void jsr P((void)); 467 | void rts P((void)); 468 | void bne P((void)); 469 | void beq P((void)); 470 | void bpl P((void)); 471 | void bmi P((void)); 472 | void bhi P((void)); 473 | void bvc P((void)); 474 | void bvs P((void)); 475 | void bcc P((void)); 476 | void bcs P((void)); 477 | void scc P((void)); 478 | void ccc P((void)); 479 | void sob P((void)); 480 | void mfps P((void)); 481 | void mtps P((void)); 482 | void mfpi P((void)); 483 | void mtpi P((void)); 484 | void ash P((void)); 485 | void mul P((void)); 486 | void divide P((void)); 487 | void ashc P((void)); 488 | void xor P((void)); 489 | 490 | /* double.c */ 491 | void mov P((void)); 492 | void movsreg P((void)); 493 | void movsreg1 P((void)); 494 | void movsreg1pc P((void)); 495 | void cmp P((void)); 496 | void add P((void)); 497 | void sub P((void)); 498 | void bit P((void)); 499 | void bic P((void)); 500 | void bis P((void)); 501 | void movb P((void)); 502 | void cmpb P((void)); 503 | void bitb P((void)); 504 | void bicb P((void)); 505 | void bisb P((void)); 506 | 507 | /* cpu.c */ 508 | void run P((void)); 509 | void sim_init P((void)); 510 | void bus_error P((int)); 511 | void seg_fault P((void)); 512 | void waiti P((void)); 513 | void halt P((void)); 514 | void iot P((void)); 515 | void emt P((void)); 516 | void bpt P((void)); 517 | void fis P((void)); 518 | void illegal P((void)); 519 | void not_impl P((void)); 520 | void mark P((void)); 521 | void mfpd P((void)); 522 | void mtpd P((void)); 523 | void trap P((void)); 524 | void bad_FP_reg P((void)); 525 | void sigcatcher P((int sig)); 526 | 527 | /* ea.c */ 528 | void load_ea P((void)); 529 | void pop P((void)); 530 | void push P((void)); 531 | void loadb_dst P((void)); 532 | void loadb_src P((void)); 533 | void storeb_dst P((void)); 534 | void storeb_dst_2 P((void)); 535 | void loadp_dst P((void)); 536 | void storep_dst P((void)); 537 | void load_src P((void)); 538 | void store_dst P((void)); 539 | void load_dst P((void)); 540 | void store_dst_2 P((void)); 541 | 542 | /* fp.c */ 543 | void fpset P((void)); 544 | void ldf P((void)); 545 | void stf P((void)); 546 | void clrf P((void)); 547 | void addf P((void)); 548 | void subf P((void)); 549 | void negf P((void)); 550 | void absf P((void)); 551 | void mulf P((void)); 552 | void moddf P((void)); 553 | void divf P((void)); 554 | void cmpf P((void)); 555 | void tstf P((void)); 556 | void ldfps P((void)); 557 | void stfps P((void)); 558 | void lcdif P((void)); 559 | void stcfi P((void)); 560 | void stexp P((void)); 561 | void stcdf P((void)); 562 | void ldcdf P((void)); 563 | void stst P((void)); 564 | void ldexpp P((void)); 565 | 566 | /* itab.c */ 567 | void dositab0 P((void)); 568 | void dositab1 P((void)); 569 | 570 | /* main.c */ 571 | int main P((int argc, char **argv)); 572 | void usage P((void)); 573 | char *xlate_filename P((char *name)); 574 | void set_apout_root P((char *dirname)); 575 | 576 | /* magic.c */ 577 | int special_magic P((u_int16_t * cptr)); 578 | 579 | /* single.c */ 580 | void adc P((void)); 581 | void asl P((void)); 582 | void asr P((void)); 583 | void clr P((void)); 584 | void com P((void)); 585 | void dec P((void)); 586 | void inc P((void)); 587 | void neg P((void)); 588 | void rol P((void)); 589 | void ror P((void)); 590 | void sbc P((void)); 591 | void swabi P((void)); 592 | void sxt P((void)); 593 | void tst P((void)); 594 | void tstb P((void)); 595 | void aslb P((void)); 596 | void asrb P((void)); 597 | void clrb P((void)); 598 | void comb P((void)); 599 | void decb P((void)); 600 | void incb P((void)); 601 | void negb P((void)); 602 | void rolb P((void)); 603 | void rorb P((void)); 604 | void adcb P((void)); 605 | void sbcb P((void)); 606 | 607 | /* v6trap.c */ 608 | void v6trap P((void)); 609 | 610 | /* v7trap.c */ 611 | void v7trap P((void)); 612 | 613 | /* v1trap.c */ 614 | void v1trap P((void)); 615 | 616 | /* bsdtrap.c */ 617 | #ifdef EMU211 618 | void bsdtrap P((void)) /*@globals errno,stdout,stderr; @ */ ; 619 | 620 | /* bsd_ioctl.h */ 621 | int trap_ioctl P((void)); 622 | 623 | /* bsd_signal.c */ 624 | void set_bsdsig_dfl P((void)); 625 | int do_sigaction P((int sig, int a, int oa)); 626 | #endif 627 | 628 | /* ke11a.c */ 629 | #ifdef EMUV1 630 | int16_t kell_word P((u_int16_t addr)); 631 | void kesl_word P((u_int16_t addr, u_int16_t word)); 632 | int8_t kell_byte P((u_int16_t addr)); 633 | void kesl_byte P((u_int16_t addr, u_int8_t byte)); 634 | void set_SR P((void)); 635 | #endif 636 | 637 | #undef P 638 | -------------------------------------------------------------------------------- /fp.c: -------------------------------------------------------------------------------- 1 | /* fp.c - PDP-11 floating point operations 2 | * 3 | * $Revision: 2.24 $ 4 | * $Date: 2008/05/15 07:52:45 $ 5 | */ 6 | 7 | /* The floating-point emulation code here is just enough to allow 8 | * 2.11BSD binaries to run. There is only emulation of PDP-11 9 | * 32-bit floats: the extra 32-bits of precision in PDP-11 doubles 10 | * goes unused. As well, I don't try to emulate any of the FP errors. 11 | * 12 | * If this is a problem, then feel free to correct it. 13 | */ 14 | #include "defines.h" 15 | #include 16 | #ifdef HAVE_POWF 17 | float powf(float x, float y); /* FreeBSD 3.X no longer defines this */ 18 | #else 19 | #define powf(x,y) (float)pow((double)x, (double)y) 20 | #endif 21 | 22 | #define XUL 170141163178059628080016879768632819712.0 /* Biggest float */ 23 | 24 | typedef struct { 25 | unsigned frac1:7; /* Fractional part of number */ 26 | unsigned exp:8; /* Excess 128 notation: exponenents -128 to +127 */ 27 | /* become 0 to 255 */ 28 | unsigned sign:1; /* If 1, float is negative */ 29 | unsigned frac2:16; /* Fractional part of number */ 30 | } pdpfloat; 31 | 32 | 33 | /* Internal variables */ 34 | FLOAT fregs[8]; /* Yes, I know there are only 6, it makes it easier */ 35 | int FPC = 0; /* Status flags */ 36 | int FPZ = 0; 37 | int FPN = 0; 38 | int FPV = 0; 39 | int FPMODE = 0; /* 0 = float, 1 = doubles */ 40 | int INTMODE = 0; /* 0 = integers, 1 = longs */ 41 | 42 | /* Temporary variables */ 43 | FLOAT Srcflt; /* Float specified by FSRC field */ 44 | pdpfloat *fladdr; /* Address of float in dspace */ 45 | int AC; /* Accumulator field in ir */ 46 | int32_t srclong; /* Longword from source address */ 47 | int32_t dstlong; /* Longword for destination address */ 48 | static char *buf, *buf2; /* for copylong */ 49 | 50 | 51 | 52 | 53 | /* Convert from PDP-11 float representation to native representation */ 54 | static void from11float(FLOAT * out, pdpfloat * in) 55 | { 56 | int32_t exponent; 57 | u_int32_t fraction; 58 | FLOAT z; 59 | 60 | exponent = in->exp - 128 - 24; /* 24 so as to shift the radix point left */ 61 | /* Add in the missing significant bit */ 62 | fraction = (in->frac1 << 16) + in->frac2 + 8388608; 63 | 64 | z = powf(2.0, (float) exponent); 65 | *out = (float) fraction *z; 66 | if (in->sign) 67 | *out = -(*out); 68 | FpDebug((dbg_file, "\t0%o from11float out is %f\n", regs[7], *out)); 69 | } 70 | 71 | /* Convert from native representation to PDP-11 float representation */ 72 | static void to11float(FLOAT * in, pdpfloat * out) 73 | { 74 | int32_t exponent = 129; 75 | u_int32_t fraction; 76 | FLOAT infloat = *in; 77 | 78 | FpDebug((dbg_file, "\t0%o to11float in is %f\n", regs[7], infloat)); 79 | if (infloat < 0.0) { 80 | out->sign = 1; 81 | infloat = -infloat; 82 | } else 83 | out->sign = 0; 84 | 85 | if (infloat == 0.0) { 86 | out->frac1 = 0; 87 | out->frac2 = 0; 88 | out->exp = 0; 89 | return; 90 | } 91 | 92 | /* We want the float's fraction to start with 1.0 (in binary) */ 93 | /* Therefore it must be < 2.0 and >= 1.0 */ 94 | while (infloat >= 2.0) { 95 | infloat *= 0.5; 96 | exponent++; 97 | } 98 | while (infloat < 1.0) { 99 | infloat *= 2.0; 100 | exponent--; 101 | } 102 | 103 | infloat = infloat - 1.0; /* Remove significant bit */ 104 | fraction = (int) (infloat * 8388608.0); /* Multiply fraction by 2^24 */ 105 | out->frac2 = fraction & 0xffff; 106 | out->frac1 = (fraction >> 16); 107 | out->exp = exponent; 108 | } 109 | 110 | static struct { 111 | u_int16_t lo; 112 | u_int16_t hi; 113 | } intpair; 114 | /* Load (and convert if necessary) the float described by the source */ 115 | /* address into Srcflt. */ 116 | static void load_flt(void) 117 | { 118 | u_int16_t indirect, addr; 119 | u_int16_t *intptr; 120 | 121 | FpDebug((dbg_file, "\tload_flt mode %d\n", DST_MODE)); 122 | switch (DST_MODE) { 123 | case 0: 124 | Srcflt = fregs[DST_REG]; 125 | fladdr = NULL; 126 | return; 127 | case 1: 128 | if (DST_REG == PC) { 129 | intptr = (u_int16_t *) & ispace[regs[DST_REG]]; 130 | intpair.lo = *intptr; 131 | intpair.hi = 0; 132 | fladdr = (pdpfloat *) & intpair; 133 | } else 134 | fladdr = (pdpfloat *) & dspace[regs[DST_REG]]; 135 | from11float(&Srcflt, fladdr); 136 | return; 137 | case 2: 138 | if (DST_REG == PC) { 139 | intptr = (u_int16_t *) & ispace[regs[DST_REG]]; 140 | intpair.lo = *intptr; 141 | intpair.hi = 0; 142 | fladdr = (pdpfloat *) & intpair; 143 | from11float(&Srcflt, fladdr); 144 | regs[DST_REG] += 2; 145 | } else { 146 | fladdr = (pdpfloat *) & dspace[regs[DST_REG]]; 147 | from11float(&Srcflt, fladdr); 148 | if (FPMODE) 149 | regs[DST_REG] += 8; 150 | else 151 | regs[DST_REG] += 4; 152 | } 153 | return; 154 | case 3: 155 | ll_word(regs[DST_REG], indirect); 156 | if (DST_REG == PC) { 157 | intptr = (u_int16_t *) & ispace[indirect]; 158 | intpair.lo = *intptr; 159 | intpair.hi = 0; 160 | fladdr = (pdpfloat *) & intpair; 161 | from11float(&Srcflt, fladdr); 162 | regs[DST_REG] += 2; 163 | } else { 164 | fladdr = (pdpfloat *) & dspace[indirect]; 165 | from11float(&Srcflt, fladdr); 166 | if (FPMODE) 167 | regs[DST_REG] += 8; 168 | else 169 | regs[DST_REG] += 4; 170 | } 171 | return; 172 | case 4: 173 | if (FPMODE) 174 | regs[DST_REG] -= 8; 175 | else 176 | regs[DST_REG] -= 4; 177 | fladdr = (pdpfloat *) & dspace[regs[DST_REG]]; 178 | from11float(&Srcflt, fladdr); 179 | return; 180 | case 5: 181 | if (FPMODE) 182 | regs[DST_REG] -= 8; 183 | else 184 | regs[DST_REG] -= 4; 185 | ll_word(regs[DST_REG], indirect); 186 | fladdr = (pdpfloat *) & dspace[indirect]; 187 | from11float(&Srcflt, fladdr); 188 | return; 189 | case 6: 190 | lli_word(regs[PC], indirect); 191 | regs[PC] += 2; 192 | indirect = regs[DST_REG] + indirect; 193 | fladdr = (pdpfloat *) & dspace[indirect]; 194 | from11float(&Srcflt, fladdr); 195 | return; 196 | case 7: 197 | lli_word(regs[PC], indirect); 198 | regs[PC] += 2; 199 | indirect = regs[DST_REG] + indirect; 200 | ll_word(indirect, addr); 201 | fladdr = (pdpfloat *) & dspace[addr]; 202 | from11float(&Srcflt, fladdr); 203 | return; 204 | } 205 | illegal(); 206 | } 207 | 208 | /* Save (and convert if necessary) Srcflt into the float described by the 209 | * destination address */ 210 | static void save_flt(void) 211 | { 212 | u_int16_t indirect; 213 | u_int16_t addr; 214 | pdpfloat *fladdr; 215 | 216 | FpDebug((dbg_file, "\tsave_flt mode %d\n", DST_MODE)); 217 | switch (DST_MODE) { 218 | case 0: 219 | fregs[DST_REG] = Srcflt; 220 | return; 221 | case 1: 222 | fladdr = (pdpfloat *) & dspace[regs[DST_REG]]; 223 | to11float(&Srcflt, fladdr); 224 | return; 225 | case 2: 226 | fladdr = (pdpfloat *) & dspace[regs[DST_REG]]; 227 | to11float(&Srcflt, fladdr); 228 | if (DST_REG == PC) 229 | regs[DST_REG] += 2; 230 | else if (FPMODE) 231 | regs[DST_REG] += 8; 232 | else 233 | regs[DST_REG] += 4; 234 | return; 235 | case 3: 236 | ll_word(regs[DST_REG], indirect); 237 | fladdr = (pdpfloat *) & dspace[indirect]; 238 | to11float(&Srcflt, fladdr); 239 | if (DST_REG == PC) 240 | regs[DST_REG] += 2; 241 | else if (FPMODE) 242 | regs[DST_REG] += 8; 243 | else 244 | regs[DST_REG] += 4; 245 | return; 246 | case 4: 247 | if (FPMODE) 248 | regs[DST_REG] -= 8; 249 | else 250 | regs[DST_REG] -= 4; 251 | fladdr = (pdpfloat *) & dspace[regs[DST_REG]]; 252 | to11float(&Srcflt, fladdr); 253 | return; 254 | case 5: 255 | if (FPMODE) 256 | regs[DST_REG] -= 8; 257 | else 258 | regs[DST_REG] -= 4; 259 | ll_word(regs[DST_REG], indirect); 260 | fladdr = (pdpfloat *) & dspace[indirect]; 261 | to11float(&Srcflt, fladdr); 262 | return; 263 | case 6: 264 | lli_word(regs[PC], indirect); 265 | regs[PC] += 2; 266 | indirect = regs[DST_REG] + indirect; 267 | fladdr = (pdpfloat *) & dspace[indirect]; 268 | to11float(&Srcflt, fladdr); 269 | return; 270 | case 7: 271 | lli_word(regs[PC], indirect); 272 | regs[PC] += 2; 273 | indirect = regs[DST_REG] + indirect; 274 | ll_word(indirect, addr); 275 | fladdr = (pdpfloat *) & dspace[addr]; 276 | to11float(&Srcflt, fladdr); 277 | return; 278 | } 279 | illegal(); 280 | } 281 | 282 | /* lli_long() - Load a long from the given ispace logical address. */ 283 | #define lli_long(addr, word) \ 284 | { adptr= (u_int16_t *)&(ispace[addr]); copylong(word, *adptr); } \ 285 | 286 | /* ll_long() - Load a long from the given logical address. */ 287 | #define ll_long(addr, word) \ 288 | { adptr= (u_int16_t *)&(dspace[addr]); copylong(word, *adptr); } \ 289 | 290 | /* sl_long() - Store a long from the given logical address. */ 291 | #define sl_long(addr, word) \ 292 | { adptr= (u_int16_t *)&(dspace[addr]); copylong(*adptr, word); } \ 293 | 294 | static void load_long(void) 295 | { 296 | u_int16_t addr, indirect; 297 | 298 | switch (DST_MODE) { 299 | case 0: 300 | srclong = regs[DST_REG]; 301 | return; 302 | case 1: 303 | addr = regs[DST_REG]; 304 | if (DST_REG == PC) { 305 | lli_long(addr, srclong) 306 | } else { 307 | ll_long(addr, srclong); 308 | } 309 | return; 310 | case 2: 311 | addr = regs[DST_REG]; 312 | if (DST_REG == PC) { 313 | lli_long(addr, srclong) 314 | } else { 315 | ll_long(addr, srclong); 316 | } 317 | regs[DST_REG] += 4; 318 | return; 319 | case 3: 320 | indirect = regs[DST_REG]; 321 | if (DST_REG == PC) { 322 | lli_word(indirect, addr) 323 | } else { 324 | ll_word(indirect, addr); 325 | } 326 | regs[DST_REG] += 4; 327 | ll_long(addr, srclong); 328 | return; 329 | case 4: 330 | regs[DST_REG] -= 4; 331 | addr = regs[DST_REG]; 332 | ll_long(addr, srclong); 333 | return; 334 | case 5: 335 | regs[DST_REG] -= 4; 336 | indirect = regs[DST_REG]; 337 | ll_word(indirect, addr); 338 | ll_long(addr, srclong); 339 | return; 340 | case 6: 341 | lli_word(regs[PC], indirect); 342 | regs[PC] += 2; 343 | addr = regs[DST_REG] + indirect; 344 | ll_long(addr, srclong); 345 | return; 346 | case 7: 347 | lli_word(regs[PC], indirect); 348 | regs[PC] += 2; 349 | indirect = regs[DST_REG] + indirect; 350 | ll_word(indirect, addr); 351 | ll_long(addr, srclong); 352 | return; 353 | } 354 | illegal(); 355 | } 356 | 357 | 358 | static void store_long(void) 359 | { 360 | u_int16_t addr, indirect; 361 | 362 | switch (DST_MODE) { 363 | case 0: 364 | regs[DST_REG] = dstlong; 365 | return; 366 | case 1: 367 | addr = regs[DST_REG]; 368 | sl_long(addr, dstlong) 369 | return; 370 | case 2: 371 | addr = regs[DST_REG]; 372 | sl_long(addr, dstlong) 373 | regs[DST_REG] += 4; 374 | return; 375 | case 3: 376 | indirect = regs[DST_REG]; 377 | ll_word(indirect, addr); 378 | regs[DST_REG] += 4; 379 | sl_long(addr, dstlong); 380 | return; 381 | case 4: 382 | regs[DST_REG] -= 4; 383 | addr = regs[DST_REG]; 384 | sl_long(addr, dstlong); 385 | return; 386 | case 5: 387 | regs[DST_REG] -= 4; 388 | indirect = regs[DST_REG]; 389 | ll_word(indirect, addr); 390 | sl_long(addr, dstlong); 391 | return; 392 | case 6: 393 | lli_word(regs[PC], indirect); 394 | regs[PC] += 2; 395 | addr = regs[DST_REG] + indirect; 396 | sl_long(addr, dstlong); 397 | return; 398 | case 7: 399 | lli_word(regs[PC], indirect); 400 | regs[PC] += 2; 401 | indirect = regs[DST_REG] + indirect; 402 | ll_word(indirect, addr); 403 | sl_long(addr, dstlong); 404 | return; 405 | } 406 | illegal(); 407 | } 408 | 409 | 410 | /* Instruction handlers */ 411 | void fpset() 412 | { 413 | switch (ir) { 414 | case 0170000: /* CFCC */ 415 | CC_C = FPC; 416 | CC_V = FPV; 417 | CC_Z = FPZ; 418 | CC_N = FPN; 419 | return; 420 | case 0170001: /* SETF */ 421 | FPMODE = 0; 422 | return; 423 | case 0170002: /* SETI */ 424 | INTMODE = 0; 425 | return; 426 | case 0170011: /* SETD */ 427 | FPMODE = 1; 428 | return; 429 | case 0170012: /* SETL */ 430 | INTMODE = 1; 431 | return; 432 | default: 433 | not_impl(); 434 | } 435 | } 436 | 437 | void ldf() 438 | { 439 | /* Load float */ 440 | AC = (ir >> 6) & 3; 441 | load_flt(); 442 | fregs[AC] = Srcflt; 443 | FPC = 0; 444 | FPV = 0; 445 | if (fregs[AC] == 0.0) 446 | FPZ = 1; 447 | else 448 | FPZ = 0; 449 | if (fregs[AC] < 0.0) 450 | FPN = 1; 451 | else 452 | FPN = 0; 453 | } 454 | 455 | void stf() 456 | { 457 | /* Store float */ 458 | AC = (ir >> 6) & 3; 459 | Srcflt = fregs[AC]; 460 | save_flt(); 461 | } 462 | 463 | 464 | void clrf() 465 | { 466 | /* Store float */ 467 | AC = (ir >> 6) & 3; 468 | Srcflt = 0.0; 469 | save_flt(); 470 | FPC = FPZ = FPV = 0; 471 | FPZ = 1; 472 | } 473 | 474 | void addf() 475 | { 476 | /* Add float */ 477 | AC = (ir >> 6) & 3; 478 | load_flt(); 479 | fregs[AC] += Srcflt; 480 | FPC = 0; 481 | if (fregs[AC] > XUL) 482 | FPV = 1; 483 | else 484 | FPV = 0; 485 | if (fregs[AC] == 0.0) 486 | FPZ = 1; 487 | else 488 | FPZ = 0; 489 | if (fregs[AC] < 0.0) 490 | FPN = 1; 491 | else 492 | FPN = 0; 493 | } 494 | 495 | void subf() 496 | { 497 | /* Subtract float */ 498 | AC = (ir >> 6) & 3; 499 | load_flt(); 500 | fregs[AC] -= Srcflt; 501 | FPC = 0; 502 | if (fregs[AC] > XUL) 503 | FPV = 1; 504 | else 505 | FPV = 0; 506 | if (fregs[AC] == 0.0) 507 | FPZ = 1; 508 | else 509 | FPZ = 0; 510 | if (fregs[AC] < 0.0) 511 | FPN = 1; 512 | else 513 | FPN = 0; 514 | } 515 | 516 | void negf() 517 | { 518 | /* Negate float */ 519 | load_flt(); 520 | fladdr->sign = -(fladdr->sign); 521 | FPC = 0; 522 | FPV = 0; 523 | if (Srcflt == 0.0) 524 | FPZ = 1; 525 | else 526 | FPZ = 0; 527 | if (Srcflt < 0.0) 528 | FPN = 1; 529 | else 530 | FPN = 0; 531 | } 532 | 533 | 534 | void absf() 535 | { 536 | /* Absolute float */ 537 | load_flt(); 538 | fladdr->sign = 0; 539 | FPC = 0; 540 | FPV = 0; 541 | FPN = 0; 542 | if (Srcflt == 0.0) 543 | FPZ = 1; 544 | else 545 | FPZ = 0; 546 | } 547 | 548 | void mulf() 549 | { 550 | /* Multiply float */ 551 | AC = (ir >> 6) & 3; 552 | load_flt(); 553 | fregs[AC] *= Srcflt; 554 | FPC = 0; 555 | if (fregs[AC] > XUL) 556 | FPV = 1; 557 | else 558 | FPV = 0; 559 | if (fregs[AC] == 0.0) 560 | FPZ = 1; 561 | else 562 | FPZ = 0; 563 | if (fregs[AC] < 0.0) 564 | FPN = 1; 565 | else 566 | FPN = 0; 567 | } 568 | 569 | 570 | void moddf() 571 | { 572 | /* Multiply and integerise float */ 573 | FLOAT x, y; 574 | 575 | AC = (ir >> 6) & 3; 576 | load_flt(); 577 | fregs[AC] *= Srcflt; 578 | y = fregs[AC]; 579 | if (y > 0.0) 580 | x = (FLOAT) floor((double) y); 581 | else 582 | x = (FLOAT) ceil((double) y); 583 | fregs[AC | 1] = x; 584 | 585 | y = y - x; 586 | fregs[AC] = y; 587 | 588 | FPC = 0; 589 | if (fregs[AC] > XUL) 590 | FPV = 1; 591 | else 592 | FPV = 0; 593 | if (fregs[AC] == 0.0) 594 | FPZ = 1; 595 | else 596 | FPZ = 0; 597 | if (fregs[AC] < 0.0) 598 | FPN = 1; 599 | else 600 | FPN = 0; 601 | } 602 | 603 | void divf() 604 | { 605 | /* Divide float */ 606 | AC = (ir >> 6) & 3; 607 | load_flt(); 608 | fregs[AC] /= Srcflt; 609 | FPC = 0; 610 | if (fregs[AC] > XUL) 611 | FPV = 1; 612 | else 613 | FPV = 0; 614 | if (fregs[AC] == 0.0) 615 | FPZ = 1; 616 | else 617 | FPZ = 0; 618 | if (fregs[AC] < 0.0) 619 | FPN = 1; 620 | else 621 | FPN = 0; 622 | } 623 | 624 | void cmpf() 625 | { 626 | /* Compare float */ 627 | AC = (ir >> 6) & 3; 628 | load_flt(); 629 | FPC = 0; 630 | FPV = 0; 631 | if (fregs[AC] > Srcflt) 632 | FPN = 1; 633 | else 634 | FPN = 0; 635 | if (fregs[AC] == Srcflt) 636 | FPZ = 1; 637 | else 638 | FPZ = 0; 639 | } 640 | 641 | void tstf() 642 | { 643 | /* Test float */ 644 | AC = (ir >> 6) & 3; 645 | load_flt(); 646 | FPC = 0; 647 | FPV = 0; 648 | if (Srcflt < 0.0) 649 | FPN = 1; 650 | else 651 | FPN = 0; 652 | if (Srcflt == 0.0) 653 | FPZ = 1; 654 | else 655 | FPZ = 0; 656 | } 657 | 658 | void ldfps() 659 | { 660 | /* Load FPP status */ 661 | load_dst(); 662 | if (dstword & CC_NBIT) 663 | CC_N = 1; 664 | if (dstword & CC_ZBIT) 665 | CC_Z = 1; 666 | if (dstword & CC_VBIT) 667 | CC_V = 1; 668 | if (dstword & CC_CBIT) 669 | CC_C = 1; 670 | } 671 | 672 | void stfps() 673 | { 674 | /* Store FPP status */ 675 | srcword = 0; 676 | if (CC_N) 677 | srcword |= CC_NBIT; 678 | if (CC_Z) 679 | srcword |= CC_ZBIT; 680 | if (CC_V) 681 | srcword |= CC_VBIT; 682 | if (CC_C) 683 | srcword |= CC_CBIT; 684 | store_dst(); 685 | } 686 | 687 | void lcdif() 688 | { 689 | /* Convert int to float */ 690 | AC = (ir >> 6) & 3; 691 | if (INTMODE == 0) { /* ints */ 692 | load_src(); 693 | fregs[AC] = (float) srcword; 694 | } else { 695 | load_long(); 696 | fregs[AC] = (float) srclong; 697 | } 698 | } 699 | 700 | void stcfi() 701 | { 702 | /* Convert int to float */ 703 | AC = (ir >> 6) & 3; 704 | if (INTMODE == 0) { /* ints */ 705 | dstword = (int16_t) fregs[AC]; 706 | store_dst(); 707 | } else { 708 | dstlong = (int32_t) fregs[AC]; 709 | store_long(); 710 | } 711 | } 712 | 713 | void stexp() 714 | { 715 | /* Store exponent */ 716 | pdpfloat pdptmp; 717 | 718 | AC = (ir >> 6) & 3; 719 | to11float(&fregs[AC], &pdptmp); 720 | dstword = pdptmp.exp - 128; 721 | store_dst(); 722 | } 723 | 724 | void stcdf() 725 | { 726 | /* Switch FPMODE just while we're saving */ 727 | FPMODE = 1 - FPMODE; 728 | stf(); 729 | FPMODE = 1 - FPMODE; 730 | } 731 | 732 | void ldcdf() 733 | { 734 | ldf(); 735 | } 736 | 737 | void stst() 738 | { 739 | /* For now */ 740 | } 741 | 742 | void ldexpp() 743 | { 744 | pdpfloat pdptmp; 745 | 746 | AC = (ir >> 6) & 3; 747 | to11float(&fregs[AC], &pdptmp); 748 | load_src(); /* srcword now holds new exponent */ 749 | srcword += 128; /* Convert to required exponent */ 750 | srcword &= 0xff; 751 | pdptmp.exp = srcword; 752 | from11float(&fregs[AC], &pdptmp); 753 | } 754 | -------------------------------------------------------------------------------- /v1trap.c: -------------------------------------------------------------------------------- 1 | /* v1trap.c - Deal with 1st Edition trap instructions. 2 | * 3 | * $Revision: 1.16 $ 4 | * $Date: 2008/05/19 13:26:42 $ 5 | */ 6 | #ifdef EMUV1 7 | #include "defines.h" 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include "v1trap.h" 20 | 21 | #ifdef __linux__ 22 | #undef STREAM_BUFFERING /* It seems to work */ 23 | #else 24 | #define STREAM_BUFFERING /* but not for Linux */ 25 | #endif 26 | 27 | 28 | /* Forward prototypes */ 29 | #ifdef __STDC__ 30 | #define P(s) s 31 | #else 32 | #define P(s) () 33 | #endif 34 | static int v1trap_exec P((void)); 35 | static int v1open_dir P((char *name)); 36 | static u_int32_t sectosixty P((time_t tim)); 37 | 38 | #undef P 39 | 40 | 41 | /* V1 keeps some of the arguments to syscalls in registers, and some 42 | * after the `sys' instruction itself. The list below gives the number 43 | * of words, and the number in registers. 44 | */ 45 | struct v1sysent { 46 | int nwords; 47 | int nregs; 48 | }; 49 | static struct v1sysent v1arg[] = { 50 | {0, 0}, {0, 0}, {0, 0}, {3, 1}, {3, 1}, {2, 0}, {1, 1}, {1, 1}, 51 | {2, 0}, {2, 0}, {1, 0}, {2, 0}, {1, 0}, {0, 0}, {2, 0}, {2, 0}, 52 | {2, 0}, {1, 0}, {2, 0}, {3, 1}, {3, 1}, {2, 0}, {1, 0}, {1, 1}, 53 | {1, 1}, {0, 0}, {1, 0}, {1, 0}, {2, 1}, {1, 0}, {1, 0}, {2, 1}, 54 | {2, 1}, {1, 0} 55 | }; 56 | 57 | /* Seeks on files in /dev are done in 512-byte blocks, not bytes. 58 | * If a fd's entry in the following table is 1, then it's a device 59 | * and not a file. 60 | */ 61 | int8_t isdev[NFILE] = { 62 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 64 | }; 65 | 66 | static arglist V1A; 67 | 68 | void v1trap() 69 | { 70 | extern int32_t AC, MQ; /* in ke11a.c */ 71 | int i, mode, pid; 72 | int status, exitval, errval; /* used in V2 wait */ 73 | int whence; 74 | u_int16_t argbase; 75 | int trapnum; 76 | long larg; 77 | char *buf, *buf2; 78 | char *fmode; /* used with fdopen only */ 79 | 80 | struct stat stbuf; /* used in STAT */ 81 | struct tr_v1stat *t1; /* used in STAT */ 82 | struct timeval tval[2]; /* used in SMTIME */ 83 | 84 | 85 | 86 | /* Work out the actual trap number, and */ 87 | /* shift the PC up past any arguments */ 88 | /* to the syscall. Calculate base of args */ 89 | trapnum = ir & 077; 90 | argbase = regs[PC]; 91 | regs[PC] += 2 * (v1arg[trapnum].nwords - v1arg[trapnum].nregs); 92 | 93 | /* Move arguments into V1A so we can use them */ 94 | for (i = 0; i < v1arg[trapnum].nregs; i++) 95 | V1A.uarg[i] = regs[i]; 96 | for (; i < v1arg[trapnum].nwords; i++, argbase += 2) 97 | ll_word(argbase, V1A.uarg[i]); 98 | 99 | TrapDebug((dbg_file, "pid %d %s: ", (int) getpid(), 100 | v1trap_name[trapnum])); 101 | 102 | switch (trapnum) { 103 | 104 | /* XXX STILL TO DO: V1_GTTY, V1_STTY, V1_TELL */ 105 | 106 | /* These syscalls are ignored, and return */ 107 | /* with no effect on the caller */ 108 | case V1_BREAK: 109 | case V1_CEMT: 110 | case V1_ILGINS: 111 | case V1_INTR: 112 | case V1_QUIT: 113 | case V1_RELE: 114 | return; 115 | 116 | /* These syscalls are not implemented, and */ 117 | /* always return no error to the caller */ 118 | case V1_GTTY: 119 | case V1_STTY: 120 | i = 0; 121 | break; 122 | /* These syscalls are not implemented, and */ 123 | /* always return an error to the caller */ 124 | case V1_MOUNT: 125 | case V1_UMOUNT: 126 | i = -1; 127 | break; 128 | 129 | case V1_EXIT: 130 | if (Binary == IS_V1) 131 | exit(0); 132 | if (Binary == IS_V2) { 133 | exitval = regs[0] & 0xff; 134 | if (regs[PC] == 16790) 135 | exitval = 0; /* s2-tape /bin/as doesn't set r0 */ 136 | TrapDebug((dbg_file, " with exitval %d\n", exitval)); 137 | exit(exitval); 138 | } 139 | i = -1; 140 | break; 141 | 142 | #define EPOCH71 31536000 /* # seconds from 1970 to 1971 */ 143 | #define EPOCH72 63072000 /* # seconds from 1970 to 1972 */ 144 | case V1_SMDATE: 145 | buf = xlate_filename((char *) &dspace[uarg1]); 146 | if (buf[0] == '\0') 147 | buf = "."; /* Not documented anywhere */ 148 | if (uarg1 == 0) 149 | buf = "."; /* Who knows? for V1 */ 150 | i = stat(buf, &stbuf); 151 | TrapDebug((dbg_file, " on %s (stat %d) ", buf, i)); 152 | if (i == -1) 153 | break; 154 | 155 | /* Copy access time to preserve it */ 156 | tval[0].tv_sec = stbuf.st_atime; 157 | tval[0].tv_usec = 0; 158 | larg = (AC << 16) | (MQ & 0xffff); /* Get mod time in 60ths of a second */ 159 | TrapDebug((dbg_file, " %ld -> ", larg)); 160 | larg = larg / 60 + EPOCH72; /* Convert to seconds since 1970 */ 161 | TrapDebug((dbg_file, " 0x%lx ", larg)); 162 | tval[1].tv_sec = larg; 163 | tval[1].tv_usec = 0; 164 | i = utimes(buf, tval); 165 | TrapDebug((dbg_file, " and %d for utimes ", i)); 166 | break; 167 | 168 | case V1_TIME: 169 | /* Kludge: treat start of this year as the epoch. */ 170 | /* Find #seconds from yearstart to now, multiply */ 171 | /* by 60 so as to be in V1 units */ 172 | larg = sectosixty(time(NULL)); 173 | MQ = (int) larg & 0xffff; 174 | AC = ((int) larg >> 16) & 0xffff; 175 | i = 0; 176 | break; 177 | case V1_SEEK: 178 | /* Work out the args before we do the lseek */ 179 | whence = uarg3; 180 | switch (uarg3) { 181 | case 0: 182 | larg = uarg2; 183 | break; 184 | case 1: 185 | case 2: 186 | larg = sarg2; 187 | break; 188 | } 189 | 190 | if (ValidFD(sarg1) && isdev[sarg1]) 191 | larg *= 512; 192 | 193 | #ifdef STREAM_BUFFERING 194 | if (ValidFD(sarg1) && stream[sarg1]) { 195 | i = fseek(stream[sarg1], larg, whence); 196 | if (i == 0) 197 | i = ftell(stream[sarg1]); 198 | } else 199 | #endif 200 | i = lseek(sarg1, larg, whence); 201 | 202 | TrapDebug((dbg_file, " on fd %d amt %ld whence %d return %d ", 203 | sarg1, larg, whence, i)); 204 | if (i != -1) 205 | i = 0; 206 | regs[0] = i; 207 | break; 208 | case V1_READ: 209 | buf = (char *) &dspace[uarg2]; 210 | #ifdef STREAM_BUFFERING 211 | if (ValidFD(sarg1) && stream[sarg1]) 212 | i = fread(buf, 1, sarg3, stream[sarg1]); 213 | else 214 | #endif 215 | i = read(sarg1, buf, sarg3); 216 | TrapDebug((dbg_file, " on fd %d return %d ", sarg1, i)); 217 | regs[0] = i; 218 | break; 219 | case V1_LINK: 220 | buf = xlate_filename((char *) &dspace[uarg1]); 221 | buf2 = xlate_filename((char *) &dspace[uarg2]); 222 | i = link(buf, buf2); 223 | regs[0] = i; 224 | break; 225 | case V1_WRITE: 226 | buf = (char *) &dspace[uarg2]; 227 | #ifdef STREAM_BUFFERING 228 | if (ValidFD(sarg1) && stream[sarg1]) 229 | i = fwrite(buf, 1, sarg3, stream[sarg1]); 230 | else 231 | #endif 232 | i = write(sarg1, buf, sarg3); 233 | TrapDebug((dbg_file, " on fd %d return %d ", sarg1, i)); 234 | regs[0] = i; 235 | break; 236 | case V1_CLOSE: 237 | #ifdef STREAM_BUFFERING 238 | if (ValidFD(sarg1) && stream[sarg1]) { 239 | i = fclose(stream[sarg1]); 240 | stream[sarg1] = NULL; 241 | } else 242 | #endif 243 | i = close(sarg1); 244 | if ((i == 0) && ValidFD(sarg1)) 245 | isdev[sarg1] = 0; 246 | TrapDebug((dbg_file, " on fd %d return %d ", sarg1, i)); 247 | break; 248 | case V1_STAT: 249 | buf = xlate_filename((char *) &dspace[uarg1]); 250 | if (buf[0] == '\0') 251 | buf = "."; /* Not documented anywhere */ 252 | if (uarg1 == 0) 253 | buf = "."; /* Who knows? for V1 */ 254 | buf2 = (char *) &dspace[uarg2]; 255 | i = stat(buf, &stbuf); 256 | TrapDebug((dbg_file, " on %s return %d ", buf, i)); 257 | goto dostat; 258 | case V1_FSTAT: 259 | buf2 = (char *) &dspace[uarg2]; 260 | i = fstat(sarg1, &stbuf); 261 | TrapDebug((dbg_file, " on fd %d return %d ", sarg1, i)); 262 | 263 | dostat: 264 | if (i == -1) 265 | break; 266 | t1 = (struct tr_v1stat *) buf2; 267 | /* Inode numbers <41 are reserved for */ 268 | /* device files. Ensure we don't use them */ 269 | t1->inum = stbuf.st_ino & 0x7fff; 270 | if (t1->inum < 41) 271 | t1->inum += 100; 272 | t1->inl = stbuf.st_nlink; 273 | t1->iuid = stbuf.st_uid; 274 | t1->isize = (u_int16_t) (stbuf.st_size & 0xffff); 275 | t1->iflags = (u_int16_t) (V1_ST_USED | V1_ST_MODIFIED); 276 | if (stbuf.st_size > 4095) 277 | t1->iflags |= V1_ST_LARGE; 278 | if (stbuf.st_mode & S_IFDIR) 279 | t1->iflags |= V1_ST_ISDIR; 280 | if (stbuf.st_mode & S_ISUID) 281 | t1->iflags |= V1_ST_SETUID; 282 | if (stbuf.st_mode & S_IXUSR) 283 | t1->iflags |= V1_ST_EXEC; 284 | if (stbuf.st_mode & S_IRUSR) 285 | t1->iflags |= V1_ST_OWNREAD; 286 | if (stbuf.st_mode & S_IWUSR) 287 | t1->iflags |= V1_ST_OWNWRITE; 288 | if (stbuf.st_mode & S_IROTH) 289 | t1->iflags |= V1_ST_WRLDREAD; 290 | if (stbuf.st_mode & S_IWOTH) 291 | t1->iflags |= V1_ST_WRLDWRITE; 292 | 293 | larg = sectosixty(stbuf.st_ctime); 294 | copylong(t1->ctime, larg); 295 | larg = sectosixty(stbuf.st_mtime); 296 | copylong(t1->mtime, larg); 297 | break; 298 | case V1_UNLINK: 299 | buf = xlate_filename((char *) &dspace[uarg1]); 300 | i = unlink(buf); 301 | break; 302 | case V1_OPEN: 303 | buf = xlate_filename((char *) &dspace[uarg1]); 304 | 305 | i = stat(buf, &stbuf); /* If file is a directory */ 306 | if (i == 0 && (stbuf.st_mode & S_IFDIR)) { 307 | i = v1open_dir(buf); 308 | fmode = "w+"; 309 | TrapDebug((dbg_file, "(dir) on %s return %d ", buf, i)); 310 | } else { 311 | switch (sarg2) { 312 | case 0: 313 | sarg2 = O_RDONLY; 314 | fmode = "r"; 315 | break; 316 | case 1: 317 | sarg2 = O_WRONLY; 318 | fmode = "w"; 319 | break; 320 | default: 321 | sarg2 = O_RDWR; 322 | fmode = "w+"; 323 | break; 324 | } 325 | i = open(buf, sarg2); 326 | TrapDebug((dbg_file, " on %s return %d ", buf, i)); 327 | } 328 | regs[0] = i; 329 | 330 | if (ValidFD(i) 331 | && !strncmp((char *) &dspace[uarg1], "/dev/", 5)) { 332 | TrapDebug((dbg_file, " (device file) ")); 333 | isdev[i] = 1; 334 | } 335 | #ifdef STREAM_BUFFERING 336 | if (i == -1) 337 | break; 338 | #if 0 339 | /* Now get its stream pointer if possible */ 340 | /* Can someone explain why fdopen doesn't work for O_RDWR? */ 341 | if (ValidFD(i) && !isatty(i) && (sarg2 != O_RDWR)) { 342 | stream[i] = fdopen(i, fmode); 343 | streammode[i] = fmode; 344 | } 345 | #endif 346 | stream[i] = fdopen(i, fmode); 347 | streammode[i] = fmode; 348 | #endif 349 | break; 350 | case V1_CHMOD: 351 | buf = xlate_filename((char *) &dspace[uarg1]); 352 | mode = 0; 353 | if (uarg2 & V1_ST_SETUID) 354 | mode |= S_ISUID; 355 | if (uarg2 & V1_ST_EXEC) 356 | mode |= S_IXUSR | S_IXGRP | S_IXOTH; 357 | if (uarg2 & V1_ST_OWNREAD) 358 | mode |= S_IRUSR; 359 | if (uarg2 & V1_ST_OWNWRITE) 360 | mode |= S_IWUSR; 361 | if (uarg2 & V1_ST_WRLDREAD) 362 | mode |= S_IRGRP | S_IROTH; 363 | if (uarg2 & V1_ST_WRLDWRITE) 364 | mode |= S_IWGRP | S_IWOTH; 365 | i = chmod(buf, mode); 366 | break; 367 | case V1_MKDIR: 368 | buf = xlate_filename((char *) &dspace[uarg1]); 369 | mode = 0; 370 | if (uarg2 & V1_ST_SETUID) 371 | mode |= S_ISUID; 372 | if (uarg2 & V1_ST_EXEC) 373 | mode |= S_IXUSR | S_IXGRP | S_IXOTH; 374 | if (uarg2 & V1_ST_OWNREAD) 375 | mode |= S_IRUSR; 376 | if (uarg2 & V1_ST_OWNWRITE) 377 | mode |= S_IWUSR; 378 | if (uarg2 & V1_ST_WRLDREAD) 379 | mode |= S_IRGRP | S_IROTH; 380 | if (uarg2 & V1_ST_WRLDWRITE) 381 | mode |= S_IWGRP | S_IWOTH; 382 | i = mkdir(buf, mode); 383 | break; 384 | case V1_CHOWN: 385 | buf = xlate_filename((char *) &dspace[uarg1]); 386 | uarg2 &= 0x3fff; /* Why are uids > 16384? */ 387 | i = chown(buf, uarg2, 0); 388 | TrapDebug((dbg_file, " %d on %s return %d", uarg2, buf, i)); 389 | break; 390 | case V1_CHDIR: 391 | buf = xlate_filename((char *) &dspace[uarg1]); 392 | i = chdir(buf); 393 | break; 394 | case V1_CREAT: 395 | buf = xlate_filename((char *) &dspace[uarg1]); 396 | mode = 0; 397 | if (uarg2 & V1_ST_SETUID) 398 | mode |= S_ISUID; 399 | if (uarg2 & V1_ST_EXEC) 400 | mode |= S_IXUSR | S_IXGRP | S_IXOTH; 401 | if (uarg2 & V1_ST_OWNREAD) 402 | mode |= S_IRUSR; 403 | if (uarg2 & V1_ST_OWNWRITE) 404 | mode |= S_IWUSR; 405 | if (uarg2 & V1_ST_WRLDREAD) 406 | mode |= S_IRGRP | S_IROTH; 407 | if (uarg2 & V1_ST_WRLDWRITE) 408 | mode |= S_IWGRP | S_IWOTH; 409 | i = creat(buf, mode); 410 | TrapDebug((dbg_file, " on %s return %d ", buf, i)); 411 | #ifdef STREAM_BUFFERING 412 | if (ValidFD(i)) { 413 | stream[i] = fdopen(i, "w"); 414 | streammode[i] = "w"; 415 | } 416 | #endif 417 | regs[0] = i; 418 | break; 419 | case V1_EXEC: 420 | i = v1trap_exec(); 421 | break; 422 | case V1_WAIT: 423 | i = wait(&status); 424 | if (Binary == IS_V1) 425 | break; 426 | /* 2nd Edition wait is different */ 427 | regs[0] = i; /* Save pid found in r0 */ 428 | if (i == -1) { 429 | MQ = 0; 430 | break; 431 | } 432 | exitval = WEXITSTATUS(status); 433 | TrapDebug((dbg_file, "exitval %d ", exitval)); 434 | errval = 0; 435 | if (WIFSIGNALED(status)) { 436 | switch (WTERMSIG(status)) { 437 | case SIGBUS: 438 | errval = 1; 439 | break; 440 | case SIGTRAP: 441 | errval = 2; 442 | break; 443 | case SIGILL: 444 | errval = 3; 445 | break; 446 | case SIGIOT: 447 | errval = 4; 448 | break; 449 | case SIGEMT: 450 | errval = 6; 451 | break; 452 | case SIGQUIT: 453 | errval = 8; 454 | break; 455 | case SIGINT: 456 | errval = 9; 457 | break; 458 | case SIGKILL: 459 | errval = 10; 460 | break; 461 | } 462 | if (WCOREDUMP(status)) 463 | errval += 16; 464 | } 465 | TrapDebug((dbg_file, "errval %d ", errval)); 466 | MQ = (exitval & 0xff) | (errval << 16); 467 | TrapDebug((dbg_file, "v2 return pid is %d, MQ is 0x%x ", i, 468 | MQ)); 469 | break; 470 | case V1_FORK: 471 | pid = getpid(); 472 | i = fork(); 473 | switch (i) { 474 | /* Error, inform the parent */ 475 | case -1: 476 | break; 477 | /* Child gets ppid in r0 */ 478 | case 0: 479 | i = pid; 480 | break; 481 | /* Parent: Skip child `bf', pid into r0 */ 482 | default: 483 | regs[PC] += 2; 484 | if (Binary == IS_V2) 485 | regs[0] = i; 486 | } 487 | break; 488 | case V1_GETUID: 489 | i = getuid(); 490 | break; 491 | regs[0] = i; 492 | case V1_SETUID: 493 | i = setuid(sarg1); 494 | break; 495 | default: 496 | if (trapnum > V1_ILGINS) { 497 | fprintf(stderr, "Apout - unknown syscall %d at PC 0%o\n", 498 | trapnum, regs[PC]); 499 | } else { 500 | fprintf(stderr, 501 | "Apout - the %s syscall is not yet implemented\n", 502 | v1trap_name[trapnum]); 503 | } 504 | exit(1); 505 | } 506 | 507 | /* Clear C bit if no error, or */ 508 | /* set C bit as there was an error */ 509 | 510 | if (i == -1) { 511 | SET_CC_C(); 512 | TrapDebug((dbg_file, "errno is %s\n", strerror(errno))); 513 | } else { 514 | CLR_CC_C(); 515 | TrapDebug((dbg_file, "return %d\n", i)); 516 | } 517 | #ifdef DEBUG 518 | fflush(dbg_file); 519 | #endif 520 | return; 521 | } 522 | 523 | 524 | static int v1trap_exec(void) 525 | { 526 | u_int16_t cptr, cptr2; 527 | char *buf, *name, *origpath; 528 | 529 | origpath = strdup((char *) &dspace[uarg1]); 530 | name = xlate_filename(origpath); 531 | TrapDebug((dbg_file, "%s Execing %s ", progname, name)); 532 | 533 | cptr = uarg2; 534 | 535 | Argc = 0; 536 | while (Argc < MAX_ARGS) { 537 | ll_word(cptr, cptr2); 538 | if (cptr2 == 0) 539 | break; 540 | buf = (char *) &dspace[cptr2]; 541 | Argv[Argc++] = strdup(buf); 542 | cptr += 2; 543 | TrapDebug((dbg_file, "%s ", buf)); 544 | } 545 | Argv[Argc] = NULL; 546 | TrapDebug((dbg_file, "\n")); 547 | 548 | if (load_a_out(name, origpath, 0) == -1) { 549 | for (Argc--; Argc >= 0; Argc--) 550 | free(Argv[Argc]); 551 | return (-1); 552 | } 553 | run(); /* Ok, so it's recursive, I dislike setjmp */ 554 | return (0); 555 | } 556 | 557 | /* 1st Edition reads directories as if they were ordinary files. 558 | * The solution is to read the directory entries, and build a 559 | * real file, which is passed back to the open call. 560 | * Limitation: 32-bit inode numbers are truncated to 16-bit ones. 561 | */ 562 | static int v1open_dir(char *name) 563 | { 564 | DIR *d; 565 | char *tmpname; 566 | int i; 567 | struct dirent *dent; 568 | 569 | struct v1_direct { 570 | int16_t d_ino; 571 | int8_t d_name[8]; 572 | } v1dent; 573 | 574 | d = opendir(name); 575 | if (d == NULL) 576 | return (-1); 577 | tmpname = strdup(TMP_PLATE); 578 | i = mkstemp(tmpname); 579 | if (i == -1) { 580 | fprintf(stderr, "Apout - open_dir couldn't open %s\n", tmpname); 581 | exit(1); 582 | } 583 | unlink(tmpname); 584 | free(tmpname); 585 | 586 | while ((dent = readdir(d)) != NULL) { 587 | v1dent.d_ino = dent->d_fileno & 0x7fff; 588 | if (v1dent.d_ino < 41) 589 | v1dent.d_ino += 100; 590 | strncpy((char *) v1dent.d_name, dent->d_name, 8); 591 | write(i, &v1dent, 10); 592 | } 593 | closedir(d); 594 | lseek(i, 0, SEEK_SET); 595 | return (i); 596 | } 597 | 598 | /* Given a time, work out the number of 1/60ths of seconds since 599 | * the start of that time's year 600 | */ 601 | u_int32_t sectosixty(time_t tim) 602 | { 603 | time_t epoch; 604 | u_int32_t diff; 605 | struct tm *T; 606 | 607 | T = gmtime(&tim); 608 | T->tm_sec = T->tm_min = T->tm_hour = T->tm_mon = 0; 609 | T->tm_mday = 1; 610 | 611 | epoch = timegm(T); /* Find time at start of year */ 612 | diff = 60 * (tim - epoch); 613 | if (diff > 0x71172C00) { 614 | fprintf(stderr, "Apout - V1 sectosixty too big by %d\n", 615 | diff - 0x71172C00); 616 | } 617 | return (diff); 618 | } 619 | #endif /* EMUV1 */ 620 | --------------------------------------------------------------------------------