From: Bill Haygood [email-masked]

To:	Mr. Charles Lasner
	[email-masked]

Dear Mr. Lasner,

I hereby send the sources for my pdp8e emulator.  It works well on my
AMIGA, but it seems that every time I make any changes to it, I break
it for the IBM PC world.

I defined all functions in accordance with ANSI C.  Hopefully, you have
an ANSI-compliant compiler available.  Globally define AMIGA for use on
an AMIGA system or MS_DOS for a PC/Clone running MS-DOS.

I used quite a different approach than did Doug Jones.  I wanted to use
a high level language to make it portable and I also wanted it to execute
at high speed.  So I execute each pdp8e instruction by vectoring through
an array of function pointers indexed by the 12-bit instruction augmented
by the User Bit.  This requires 8192 array elements in the vector array.
Another 4096 element array vectors the FPP-8/A instruction executions.

When you get a successful compilation, just execute the single command:

	pdp8

Doing this should print the following menu:

Usage: pdp8 [-option [value]] [...]
   -file name          Set pdp8 memory file
                       e.g. -file pdp8.ram
   -init [octal-value [start [#locs]]]
                       e.g. -init 7402 1000 200
   -dep addr value [... value]
                       e.g. -dep 200 7300 1177 7402
   -exam addr [#locs]  Display memory
                       e.g. -exam 0 100
   -clear              Press 'CLEAR' switch
   -cont [octal]       5-digit start addr
                       e.g. -cont 16000
   -count              Count pdp8 inst's executed
   -clock [[type] [ticks]] [out]  Specify clock
                 type = dk8ea pdp8a vt78 vt278 dk8ec
                       e.g. -clock dk8ec 100
   -eae [mode] [out]   EAE emulation in/out
                       e.g. -eae b
   -fpp [out]          FPP-8/A emulation in/out
   -fpp regs [dec]     Display dec FPP registers
   -fpp trace          Trace FPP instructions
   -fpp count          Count FPP inst's executed
   -<reg> octal        Specify register value
                where <reg> = link ac mq sr sc gtf sf
                       e.g. -sr 7777
   -flags octal        Specify FLAGS register value
                       e.g. -flags 5166
   -regs               Display pdp8 registers
   -rk8e pack ...      Specify up to 4 RK8E pack(s)
                       e.g. -rk8e pack0 pack1
   -rk8e regs          Display RK8E registers
   -auxvdu [ioadr] [out]  Set up auxilliary VDU
                       e.g. -auxvdu 75
   -lpt [device]       Lineprinter output file
                       e.g. -lpt lpt.out
   -mask octal         Set breakpoint mask
                       e.g. -mask 77000
   -break [addr][inst] Set breakpoint (5 digit addr)
                       e.g. to break at inst 6046:
                               -break 6046
                            to break at addr 300:
                               -break 00300
   -trace [dec]        Trace dec instructions
                       e.g. -trace 1000
   -dis [dec]          Disassemble dec instructions
                       e.g. -dis 150
   -exec [dec]         Execute dec inst's
                       e.g. -exec 1000000
   -tab [file]         Output inst usage (to file)
                       e.g. -tab pdp8.tab
   -hist [file]        Output PC histogram (to file)
                       e.g. -hist pdp8.hst
   -pause              Pause before exiting
   -diag               Run a MAINDEC diag program
   -conout [file]      Save pdp8 console to file
                       e.g. -conout pdp8.out
   -auxout [file]      Save pdp8 aux console to file
                       e.g. -auxout pdp8.aux
   -boot               Boot from RK8E disk
   -hardware           List 'hardware' status
   -res                List 'hardware' resources
---------------------------------------------------------------------------
I will endeavor to explain the use of options with the pdp8 command.
The user may invoke any number of options up to the limit his UNIX system
will allow on a command line.  I show the actual command line (or fragment)
using six '>' and six '<'.  All the peripheral registers and certain other
information resides in the pdp8e memory file (normally named 'pdp8.ram').
When the user specifies adding a peripheral (e.g. EAE), this information
gets stored in the pdp8e memory file.  The 'pdp8.ram' file I enclose
contains only 91 bytes, but has all the registers for the CPU, EAE, RK8E,
PT8E, FPP-8/A and 32K words of zeroed pdp8e memory!  If the user removes a
peripheral (explained below), that peripheral's registers get removed from
the pdp8e memory file and only a flag remains.  The emulator assumes octal
numbers for most options.
---------------------------------------------------------------------------
   -file name          Set pdp8 memory file
                       e.g. -file pdp8.ram
This option specifies the name of the pdp8e memory file to use.  The
emulator produces a compressed memory file using a very simple, but
effective, compression scheme.  On invocation, the emulator decompresses
the specified memory file.  If the user does not specify this option, the
memory file name defaults to 'pdp8.ram'.

>>>>>>	pdp8 -file pdp8orig.ram  <<<<<<

will cause the emulator to use the file 'pdp8orig.ram' as its pdp8e memory
file.  If no pdp8e memory file exists, do not worry.  Simply invoking:

>>>>>>	pdp8 -regs  <<<<<<

will generate a new one (but with only the CPU, 32K memory, PT8E, LP8E
and RK8E--any other 'hardware' desired gets added by invoking other
options [described below]).
---------------------------------------------------------------------------
   -init [octal-value [start [#locs]]]
                       e.g. -init 7402 1000 200
This option sets a range of pdp8e memory addresses to a specified value.
Follow the option name [-init] with the desired set value.  Follow that
with the (up to 5-digit) beginning address.  Follow that with the number
of consecutive memory address to contain the set value.  If the user omits
this last item, the remainder of memory will contain the set value.  If
the user omits the beginning address, all of memory will contain the set
value.

>>>>>>	pdp8 -init 7402 1000 200  <<<<<<

will cause memory locations 01000 through 01177 to contain the value
7402 (HLT).
---------------------------------------------------------------------------
   -dep addr value [... value]
                       e.g. -dep 200 7300 1177 7402
This option acts as the "DEP" switch on the front panel.  Follow the
option name [-dep] with the (up to 5-digit) pdp8 memory address and
follow that with any number of consecutive address values.  The user may
cross field boundaries with this option.

>>>>>>	pdp8 -dep 200 7300 1177 7402  <<<<<<

will cause locations 200 through 202 to contain the following program:
00200 7300 CLA CLL
00201 1177 TAD	177
00202 7402 HLT

As you can readily see, a user can input whole programs to pdp8e memory via
scripts (laborious, but possible).
---------------------------------------------------------------------------
   -exam addr [#locs]  Display memory
                       e.g. -exam 0 100
This option acts as the "EXAM" switch on the front panel.  Follow the
option name with the (up to 5-digit) pdp8 memory address followed by the
number of consecutive memory locations the user desires to display.
Omitting this last argument causes the display of only the 'octet' in
which the memory location exists.

>>>>>> pdp8 -exam 0 100  <<<<<<

will cause the following display (depending on memory contents, of course):

 Addr    0     1     2     3     4     5     6     7
00000  0003  6232  5001  7200  1053  3033  4500  7705  ........
00010  2222  1722  0000  1004  7773  1723  7523  0000  ........
00020  0000  0000  0200  0200  1200  0211  7607  5372  ........
00030  6203  0000  1630  7605  2125  1124  0000  0000  ........
00040  0035  7610  5046  0004  0034  7777  6233  5450  ........
00050  5601  1664  6544  7605  4000  3700  2020  0070  .......8
00060  0603  0600  0434  0067  6003  0244  0100  0336  ...7.$@^
00070  0334  7001  6670  0212  0215  0403  0010  7700  \.......

>>>>>> pdp8 -exam 1207 <<<<<<

will cause the following display (depending on memory contents, of course):

 Addr    0     1     2     3     4     5     6     7
01200  0404  1163  4423  3020  1160  3013  3017  6031  ........

---------------------------------------------------------------------------
   -clear              Press 'CLEAR' switch
Equivalent to pressing the "CLEAR" switch on pdp8e front panel.

>>>>>> pdp8 -clear <<<<<<

will cause a CLEAR "switch" depression--also equivalent to executing a
'CAF' instruction.
---------------------------------------------------------------------------
   -cont [octal]       5-digit start addr
                       e.g. -cont 16000
Equivalent to pressing the "CONT" switch on pdp8e front panel with the
added capability to specify an optional continuation address.  If the user
specifies no address, execution continues at the address specified by the
current IF and PC.

>>>>>> pdp8 -cont 16000 <<<<<<

causes the emulator to 'continue' execution at address 16000.
---------------------------------------------------------------------------
   -count              Count pdp8 inst's executed
This option directs the emulator to count the number of pdp8e instructions
executed (helpful in certain debug situations).

>>>>>> pdp8 -count [other options] <<<<<<

(obviously used in conjunction with other options).
---------------------------------------------------------------------------
   -clock [[type] [ticks]] [out]  Specify clock
                 type = dk8ea pdp8a vt78 vt278 dk8ec
                       e.g. -clock dk8ec 100
This option allows specification of the desired 8-Family clock with an
added capability to specify the number of ticks per second (which defaults
to 100 if not specified).  If a clock alreadys exists, the 'out' argument
removes it.

>>>>>> pdp8 -clock dk8ea <<<<<<

installs DK8-EA clock and sets the ticks per second at 120
(Line Frequence Clock).

>>>>>> pdp8 -clock out <<<<<<

removes the previously installed clock.

>>>>>> pdp8 -clock dk8ec 200 <<<<<<

causes the DK8-EC clock to install and sets the ticks per second at 200.
Be careful about putting too much confidence in clock resolution.
---------------------------------------------------------------------------
   -eae [mode] [out]   EAE emulation in/out
                       e.g. -eae b
This option installs the EAE or removes it.  Optionally, the user may
specify the starting mode A or B.  I suspect I have lots of errors in the
EAE implementation, but it correctly executes FORTRAN IV programs that use
it.  I refer specifically to the "questionable" opcodes.  When I did not
know how the hardware actually reacted, I guessed.  If anyone finds errors,
PLEASE let me know by email.

>>>>>> pdp8 -eae <<<<<<

installs the EAE with initial mode A in effect and enables EAE
instructions.

>>>>>> pdp8 -eae b <<<<<<

installs EAE with mode B initially set and enables EAE instructions.

>>>>>> pdp8 -eae out <<<<<<

removes the EAE from the emulator's current pdp8e memory file and disables
EAE instructions (except the basic ones that come with the pdp8e).
---------------------------------------------------------------------------
   -fpp [out]          FPP-8/A emulation in/out
This option installs the FPP-8/A or removes it.  I regard much of my
implementation of the FPP-8/A as flaky.  So many questions (some opcodes
not implemented because I could not find any documentation--see the source
code file 'pdp8fpp8.c' for questions to which I need answers).  It seems,
however, to execute FORTRAN IV programs (even with extended precision)
correctly.

>>>>>> pdp8 -fpp <<<<<<

installs the FPP-8/A emulator and enables FPP-8/A instructions.

>>>>>> pdp8 -fpp out <<<<<<

removes the FPP-8/A and disables FPP-8/A instructions.
---------------------------------------------------------------------------
   -fpp regs [dec]     Display dec FPP registers
This option displays the current status of the FPP-8/A emulator.  The
optional decimal argument causes display of that many of the
"base registers".

>>>>>>	pdp8 -fpp regs 2  <<<<<<

caused the following display after I had run OS/8 and just executed:
	.EX FORT6.LD

FPP-8/A: RUN  MODE DATA COMM STAT  APT   FPC  INDEX  BASE OPADR
          NO  LEAV  FP  0400 0000 00037 00225 10002 10023 01317
    COMM = FP UFLOW=0 32K ENA_INT ~OPADR ~NDX ~BASER ~FAC LEAV APTFIELD
   INDEX = 10002/ 0000 0000 0000 0000 0000 0000 0000 0000
     FAC =        0000 0007 0533 =  unnormalized
   OPADR = 01317/ 0000 0000 0000 =  0.
    BASE = 10023/ 0000 0000 0000 =  0.
           10026/ 0000 0000 0000 =  0.

RUN displays the run status of the FPP.  MODE displays the execution mode--
LEAV=interleaved with pdp8e CPU or LOCK=CPU locked out (with certain
exceptions).  DATA displays FP=single precision floating point, EP=
extended precision floating point and DP=double precision integer.  COMM
displays the last command executed, STAT displays FPP status, APT displays
the effective APT address, INDEX displays the address of the base of the
FPP index registers, BASE displays the address of the "base FP registers"
and OPADR displays the last operand address.  The COMM line gives a
bit-by-bit description of the contents of the FPP-8/A command register.
In the event of a non-zero STAT register, a line would also display for
that.  The INDEX line shows the address of the FPP-8/A's index register
set and displays the contents of all 8 registers.  The FAC line displays
the content of the FPP FAC in the mode currently set.  An extended
precision mode would have displayed a 6-word FAC.  The last operand
address and FP contents display on the OPADR line.  The "base registers"
(up to 128) display starting at the BASE address.  Although not apparent
in the above listing, FP values display as octal digits followed by an
equal sign and decimal numbers in floating point format.
---------------------------------------------------------------------------
   -fpp trace          Trace FPP instructions
This option causes all FPP-8/A instructions to output a trace.  Presently,
they display to stdout.  In my Amiga implementation, the emulator uses a
separate window and trace output goes to stdout--therefore no intermixing
of the emulator and trace outputs.  I plan to change this in the future to
allow specification of an output file for FPP trace output.  The command:

>>>>>>	pdp8 -rk8e pack1 -boot -fpp trace <<<<<<

brought up OS/8.  Emulator output to the console VDU:
----------------------------------------------------
.DATE
Tuesday  December 21, 1993

.TYPE FORT6.FT
        DOUBLE PRECISION PI, E, EPI
        PI = 3.14159265358979323846D0
        E = -2.71828182845904523536D0
        EPI = E * PI
        WRITE (4,200)EPI
200     FORMAT (1H1,B17.13)
        STOP
        END

.EX FORT6

 -8.5397342210747

.CLEAR
----------------------------------------------------
and yielded the following FPP trace output:

Soft/pdp8 version 1993.12.21.0050 (c) Bill Haygood, [email-masked]
  FPC                              INDX STAT FAC
 05333 0050 STARTE                      0005 0000 0000 0000 0000 0000 0000
                                             =  0.(EP)
 05334 0000 FEXIT                       0004 0000 0000 0000 0000 0000 0000
                                             =  0.(EP)
 04157 3000 TRAP3 03600                 2000 0000 0000 0000 =  0.(FP)
 04160 3600
 03737 1030 JA 04163                    0001 0000 0000 0000 =  0.(FP)
 03740 4163
 04163 3000 TRAP3 04036                 2000 0000 0000 0000 =  0.(FP)
 04164 4036
 04200 1031 JA 10000                    0001 0000 0000 0000 =  0.(FP)
 04201 0000
 10000 1031 JA 10160                    0001 0000 0000 0000 =  0.(FP)
 10001 0160
 10160 1111 SETB 10023                  0001 0000 0000 0000 =  0.(FP)
 10161 0023
 10162 1101 SETX 10002                  0001 0000 0000 0000 =  0.(FP)
 10163 0002
 10164 0100 LDX 0002,0             0002 0001 0000 0000 0000 =  0.(FP)
 10165 0002
 10166 0100 LDX 0003,0             0003 0001 0000 0000 0000 =  0.(FP)
 10167 0003
 10170 0050 STARTE                      0005 0000 0000 0000 0000 0000 0000
                                             =  0.(EP)
 10171 0235 FLDA BR+35 (10152)          0005 0002 3110 3755 2421 0264 3021
                                             =  3.14159265358979(EP)
 10172 6222 FSTA BR+22 (10111)          0005 0002 3110 3755 2421 0264 3021
                                             =  3.14159265358979(EP)
 10173 0100 LDX 0004,0             0004 0005 0002 3110 3755 2421 0264 3021
 10174 0004                                  =  3.14159265358979(EP)
 10175 0233 FLDA BR+33 (10144)          0005 0002 2557 6052 1305 0535 5124
                                             =  2.71828182845905(EP)
 10176 0003 FNEG                        0005 0002 5220 1725 6472 7242 2654
                                             = -2.71828183032169(EP)
 10177 6216 FSTA BR+16 (10075)          0005 0002 5220 1725 6472 7242 2654
                                             = -2.71828183032169(EP)
 10200 0100 LDX 0005,0             0005 0005 0002 5220 1725 6472 7242 2654
 10201 0005                                  = -2.71828183032169(EP)
 10202 0216 FLDA BR+16 (10075)          0005 0002 5220 1725 6472 7242 2654
                                             = -2.71828183032169(EP)
 10203 4222 FMUL BR+22 (10111)          0005 0004 5672 7237 6461 7636 2500
                                             = -8.53973422852524(EP)
 10204 6220 FSTA BR+20 (10103)          0005 0004 5672 7237 6461 7636 2500
                                             = -8.53973422852524(EP)
 10205 0100 LDX 0006,0             0006 0005 0004 5672 7237 6461 7636 2500
 10206 0006                                  = -8.53973422852524(EP)
 10207 0005 STARTF                      0001 0004 5672 7237 = -8.539736(FP)
 10210 3000 TRAP3 00220                 2000 0004 5672 7237 = -8.539736(FP)
 10211 0220
 00116 0401 FLDA 10136,0 (10136)   0006 0001 0003 2000 0000 =  4.(FP)
 00117 0136
 00120 0000 FEXIT                       0000 0003 2000 0000 =  4.(FP)
 10216 0050 STARTE                      0005 0003 2000 0000 0000 0000 0000
                                             =  4.(EP)
 10217 0220 FLDA BR+20 (10103)          0005 0004 5672 7237 6461 7636 2500
                                             = -8.53973422852524(EP)
 10220 3000 TRAP3 00207                 2004 0004 5672 7237 6461 7636 2500
 10221 0207                                  = -8.53973422852524(EP)
 03353 3400 FDIV 03763,0 (03763)   0006 0005 0000 3324 7400 2174 6551 0500
 03354 3763                                  =  0.85397342210747(EP)
 03355 0000 FEXIT                       0004 0000 3324 7400 2174 6551 0500
                                             =  0.85397342210747(EP)
 03760 6400 FSTA 04566,0 (04566)   0006 0005 0000 3324 7400 2174 6551 0500
 03761 4566                                  =  0.85397342210747(EP)
 03762 0000 FEXIT                       0004 0000 3324 7400 2174 6551 0500
                                             =  0.85397342210747(EP)
 03353 3400 FDIV 03763,0 (03763)   0006 0001 7774 3146 3146 =  0.05(FP)
 03354 3763
 03355 0000 FEXIT                       0000 7774 3146 3146 =  0.05(FP)
 03353 3400 FDIV 03763,0 (03763)   0006 0001 7771 2436 5604 =  0.005(FP)
 03354 3763
 03355 0000 FEXIT                       0000 7771 2436 5604 =  0.005(FP)
 03353 3400 FDIV 03763,0 (03763)   0006 0001 7766 2030 4466 =  0.0005(FP)
 03354 3763
 03355 0000 FEXIT                       0000 7766 2030 4466 =  0.0005(FP)
 03353 3400 FDIV 03763,0 (03763)   0006 0001 7762 3215 5611 =  0.00005(FP)
 03354 3763
 03355 0000 FEXIT                       0000 7762 3215 5611 =  0.00005(FP)
 03353 3400 FDIV 03763,0 (03763)   0006 0001 7757 2476 1324 =  0.000005(FP)
 03354 3763
 03355 0000 FEXIT                       0000 7757 2476 1324 =  0.000005(FP)
 03353 3400 FDIV 03763,0 (03763)   0006 0001 7754 2061 5734 =  0.(FP)
 03354 3763
 03355 0000 FEXIT                       0000 7754 2061 5734 =  0.(FP)
 03353 3400 FDIV 03763,0 (03763)   0006 0001 7750 3265 7706 =  0.(FP)
 03354 3763
 03355 0000 FEXIT                       0000 7750 3265 7706 =  0.(FP)
 03353 3400 FDIV 03763,0 (03763)   0006 0001 7745 2536 3070 =  0.(FP)
 03354 3763
 03355 0000 FEXIT                       0000 7745 2536 3070 =  0.(FP)
 03353 3400 FDIV 03763,0 (03763)   0006 0001 7742 2113 4054 =  0.(FP)
 03354 3763
 03355 0000 FEXIT                       0000 7742 2113 4054 =  0.(FP)
 03353 3400 FDIV 03763,0 (03763)   0006 0001 7736 3337 1571 =  0.(FP)
 03354 3763
 03355 0000 FEXIT                       0000 7736 3337 1571 =  0.(FP)
 03353 3400 FDIV 03763,0 (03763)   0006 0001 7733 2577 2772 =  0.(FP)
 03354 3763
 03355 0000 FEXIT                       0000 7733 2577 2772 =  0.(FP)
 03353 3400 FDIV 03763,0 (03763)   0006 0001 7730 2145 7141 =  0.(FP)
 03354 3763
 03355 0000 FEXIT                       0000 7730 2145 7141 =  0.(FP)
 03353 3400 FDIV 03763,0 (03763)   0006 0001 7724 3411 3401 =  0.(FP)
 03354 3763
 03355 0000 FEXIT                       0000 7724 3411 3401 =  0.(FP)
 03353 3400 FDIV 03763,0 (03763)   0006 0001 7721 2641 1147 =  0.(FP)
 03354 3763
 03355 0000 FEXIT                       0000 7721 2641 1147 =  0.(FP)
 05163 1400 FADD 04566,0 (04566)   0006 0005 0000 3324 7400 2174 6551 6200
 05164 4566                                  =  0.85397342210747(EP)
 05165 0000 FEXIT                       0004 0000 3324 7400 2174 6551 6200
                                             =  0.85397342210747(EP)
 10222 0005 STARTF                      0001 0000 0007 0533 =  unnormalized
 10223 3000 TRAP3 00206                 2000 0000 0007 0533 =  unnormalized
 10224 0206
 10225 0100 LDX 0007,0             0007 0001 0000 0007 0533 =  unnormalized
 10226 0007
 10227 1031 JA 10240                    0001 0000 0007 0533 =  unnormalized
 10230 0240
 10240 0100 LDX 0010,0             0010 0001 0000 0007 0533 =  unnormalized
 10241 0010
 10242 1130 JSR 00223                   0001 0000 0007 0533 =  unnormalized
 10243 0223
 00223 3000 TRAP3 01317                 2000 0000 0007 0533 =  unnormalized
 00224 1317
                                             Runtime = 0:00:30

The FPC, of course, refers to the Floating Program Counter.  The INDX
column datum, if present, displays the contents of the CURRENTLY referenced
FPP index register.  The STAT column displays the FPP status.  The FAC
column displays the FAC in the current mode--single or extended precision.
Everything to the LEFT of the FPP instruction displays the address and
contents BEFORE instruction execution and everything to the RIGHT of the
FPP instruction displays information as it exists AFTER instruction
execution.  The FAC often displays as "unnormalized" because it often gets
used as an indirect address pointer.  Otherwise, it displays as a decimal
number with the current mode displayed in parentheses (FP, EP or DP).
---------------------------------------------------------------------------
   -fpp count          Count FPP inst's executed

>>>>>>	pdp8 -fpp count [other options] <<<<<<

counts FPP-8/A instructions executed.  See above for pdp8 -count .
---------------------------------------------------------------------------
   -<reg> octal        Specify register value
                where <reg> = link ac mq sr sc gtf sf
                       e.g. -sr 7777
This options allows the user to set a register to a specific value without
having to execute pdp8e code to do so.

>>>>>>	pdp8 -link 1 -ac 4567 <<<<<<

cause the L and AC to set as indicated.

>>>>>>	pdp8 -ac 14567 <<<<<<

causes an action identical to the one above.

>>>>>>	pdp8 -mq 7701 -sr 7777 -sc 21 -gtf t -sf 143  <<<<<<

causes sets the MQ/7701, the SR/7777, the step counter SC/21, the
EAE GreaterThanFlag GTF/ON and the Save Field SF/143.
---------------------------------------------------------------------------
   -flags octal        Specify FLAGS register value
                       e.g. -flags 5166
This options allows direct setting of all the bits in the flags register.

>>>>>>	pdp8 -flags 6012 <<<<<<

causes the setting of the LINK (bit 0), the GTF (bit 1), IF/1 and DF/2.
---------------------------------------------------------------------------
   -regs               Display pdp8 registers
This option displays the contents of the pdp8e registers.  For example,
after executing:

>>>>>>	pdp8 >menu -rk8e pack1 -boot -exec 1000000  <<<<<<

caused the following to display:

Soft/pdp8 version 1993.12.21.0050 (c) Bill Haygood, [email-masked]

Flags Bits:  0:Link  1:GTF  2:IReq  3:IInh  4:IEna  5:UF  6-8:IF  9-11:DF
DI PC  Code Instruction  (Dir) ((Indir))    Flags L AC   MQ   SR  EAE SC GTF
001206 3017 DCA 17 (0000)                    1000 00000 0000 0000  A  00
001207 6031 KSF                              Runtime = 0:00:02

This displays shows the Data Field (the D in the DI at the left margin),
the Instruction Field (the I next to the D at the left margin), the PC,
the pdp8e code fetched from that address and the disassembled pdp8e
instruction.  If an direct reference exists, it displays within a single
pair of parentheses.  If an indirect reference exists, its contents display
within a double pair of parentheses.  The CPU registers (FLAGS, L, AC, MQ,
and SR) display.  The individual bit meanings of the FLAGS word display in
the banner.  If EAE installed, its registers display also.  If not, these
headings disappear and no info displays.  The last instruction executed
displays complete with register contents.  The next instruction (not yet
executed) displays for user inspection.
---------------------------------------------------------------------------
   -rk8e pack ...      Specify up to 4 RK8E pack(s)
                       e.g. -rk8e pack0 pack1
This option allows the user to specify which files to use as RK05 packs.
The user may specify up to 4 packs.  One great advantage here: the user
may specify a pack (other than the first) that does not exist and the
emulator will create it--thus making new packs very easy to create.

>>>>>>	pdp8 -rk8e pack0 pack1 pack2 pack3 -boot  <<<<<<

causes the emulator to use files pack0/1/2/3 as if packs inserted into
RK05 drives 0/1/2/3.  The '-boot' option causes the emulator to load the
RK8E boot code into the proper page zero locations and execution to start
at the correct address.  The emulator loads the following for the RK8E:
	00027 6007	CAF
	00030 6743	DLAG
	00031 6741	DSKP
	00032 5031	JMP 31

My emulator emulates the actual RK8E instructions so that a file image of
an OS/8 boot disk set up for the RK8E will boot directly.
---------------------------------------------------------------------------
   -rk8e regs          Display RK8E registers
This option displays the internal registers of the RK8E emulator.
Executing:

>>>>>>	pdp8 -rk8e regs  <<<<<<

displayed the following:

RK8E:    COMM STAT UNIT CURAD BLOCK WDCT LOCK WRIT
         0100 0000   0  00200  1634  128   F    F

COMM displays the contents of the RK8E command register, STAT displays the
status register, UNIT shows RK05 unit number, CURAD displays the next pdp8e
memory address, BLOCK displays the next RK8E block address, WDCT displays
the pdp8e word count (128=half block, 256=full block), LOCK displays the
status of the RK05 front panel LOCK switch (once set, cannot unset) and
WRIT displays whether last access executed as a WRITE access.  All numbers
display as octal except WDCT.
---------------------------------------------------------------------------
   -auxvdu [ioadr] [out]  Set up auxilliary VDU
                       e.g. -auxvdu 75
This option currently works only on the AMIGA implementation.  It opens
a second window for use by a second Video Display Unit.  The user may
specify the start of an I/O address pair for use by the 2nd VDU.  If the
user omits this I/O address, it defaults to 40/41.  If the user specifies
an I/O address where "common" conflicts occur (such as 74 [RK8E disk]),
the emulator will reject the request.

>>>>>>	pdp8 -auxvdu  <<<<<<

opens a second VDU window and enables IOT instructions for this VDU at I/O
addresses 40/41.

>>>>>>	pdp8 -auxvdu 75  <<<<<<

opens a second VDU window and enables IOT instructions for this VDU at I/O
addresses 75/76.

>>>>>>	pdp8 -auxvdu out  <<<<<<

"pulls out the module from the OmniBus" for the 2nd VDU.
---------------------------------------------------------------------------
   -lpt [device]       Lineprinter output file
                       e.g. -lpt lpt.out
This option allows the user to specify a file or device for printer
output.

>>>>>>	pdp8 -lpt lpt.out [other options]  <<<<<<

causes all printer output (via IOT 6666) to go to the specified file.
---------------------------------------------------------------------------
   -mask octal         Set breakpoint mask
                       e.g. -mask 77000
This option set a mask for use with a breakpoint as explained below.
---------------------------------------------------------------------------
   -break [addr][inst] Set breakpoint (5 digit addr)
                       e.g. to break at inst 6046:
                               -break 6046
                            to break at addr 300:
                               -break 00300
This option allows the user to specify where or on what instruction a
breakpoint will exist.  If the user specifies a 4-digit or less argument,
the emulator will break on the first INSTRUCTION it sees with that value.
If the user specifies a 5-digit argument, the emulator will break when
it encounters that ADDRESS.  Thus, "-break 6046" breaks at the first TLS
instruction encountered, but "-break 06046" breaks only if the IF/PC
equals 06046.  The instruction at the breakpoint will NOT execute.  If the
user has also specifed a mask (see above), the emulator applies the mask to
the break instruction or break address (performs an AND operation) first
to see if a match has occurred.  For example, to break on ANY EAE
instruction, the following would do the trick:

>>>>>>	pdp8 -mask 7401 -break 7401 [other options]  <<<<<<

Another example: to break only on the IOT instruction 6747:

>>>>>>	pdp8 -rk8e pack0 pack1 -boot -break 6747  <<<<<<
---------------------------------------------------------------------------
   -trace [dec]        Trace dec instructions
                       e.g. -trace 1000
This option allows the user to specify a CPU/EAE instruction trace (very
handy for pdp8e debug situations--very helpful in implementing the
emulator also!).  The optional argument specifies the number of
instructions to trace.  If the user omits the argument, it defaults to 16.
The following command:

>>>>>>	pdp8 -rk8e pack1 -boot -trace 50

yielded this trace output:

Soft/pdp8 version 1993.12.21.0050 (c) Bill Haygood, [email-masked]
Flags Bits:  0:Link  1:GTF  2:IReq  3:IInh  4:IEna  5:UF  6-8:IF  9-11:DF
DI PC  Code Instruction  (Dir) ((Indir))    Flags L AC   MQ   SR  EAE SC GTF
000027 6007 CAF                              0000 00000 0000 0000  A  00
000030 6743 DLAG                             0000 00000 0000 0000  A  00
000031 5030 JMP 30                           0000 00000 0000 0000  A  00
000030 6741 DSKP                             0000 00000 0000 0000  A  00
000032 0035 AND 35 (0006)                    0000 00000 0000 0000  A  00
000033 3436 DCA I 36 (0342) ((0000))         0000 00000 0000 0000  A  00
000034 5000 JMP 0                            0000 00000 0000 0000  A  00
000000 1412 TAD I 12 (0200) ((4207))         0000 04207 0000 0000  A  00
000001 3413 DCA I 13 (7600) ((4207))         0000 00000 0000 0000  A  00
000002 1414 TAD I 14 (0047) ((7607))         0000 07607 0000 0000  A  00
000003 2016 ISZ 16 (7760)                    0000 07607 0000 0000  A  00
000004 6211 CDF 1                            0001 07607 0000 0000  A  00
100005 3415 DCA I 15 (7647) ((7607))         0001 00000 0000 0000  A  00
100006 6201 CDF 0                            0000 00000 0000 0000  A  00
000007 2017 ISZ 17 (7600)                    0000 00000 0000 0000  A  00
000010 5000 JMP 0                            0000 00000 0000 0000  A  00
000000 1412 TAD I 12 (0201) ((5000))         0000 05000 0000 0000  A  00
000001 3413 DCA I 13 (7601) ((0000))         0000 00000 0000 0000  A  00
000002 1414 TAD I 14 (0050) ((7607))         0000 07607 0000 0000  A  00
000003 2016 ISZ 16 (7761)                    0000 07607 0000 0000  A  00
000004 6211 CDF 1                            0001 07607 0000 0000  A  00
100005 3415 DCA I 15 (7650) ((0000))         0001 00000 0000 0000  A  00
100006 6201 CDF 0                            0000 00000 0000 0000  A  00
000007 2017 ISZ 17 (7601)                    0000 00000 0000 0000  A  00
000010 5000 JMP 0                            0000 00000 0000 0000  A  00
000000 1412 TAD I 12 (0202) ((0000))         0000 00000 0000 0000  A  00
000001 3413 DCA I 13 (7602) ((0000))         0000 00000 0000 0000  A  00
000002 1414 TAD I 14 (0051) ((7607))         0000 07607 0000 0000  A  00
000003 2016 ISZ 16 (7762)                    0000 07607 0000 0000  A  00
000004 6211 CDF 1                            0001 07607 0000 0000  A  00
100005 3415 DCA I 15 (7651) ((0000))         0001 00000 0000 0000  A  00
100006 6201 CDF 0                            0000 00000 0000 0000  A  00
000007 2017 ISZ 17 (7602)                    0000 00000 0000 0000  A  00
000010 5000 JMP 0                            0000 00000 0000 0000  A  00
000000 1412 TAD I 12 (0203) ((0033))         0000 00033 0000 0000  A  00
000001 3413 DCA I 13 (7603) ((0000))         0000 00000 0000 0000  A  00
000002 1414 TAD I 14 (0052) ((7621))         0000 07621 0000 0000  A  00
000003 2016 ISZ 16 (7763)                    0000 07621 0000 0000  A  00
000004 6211 CDF 1                            0001 07621 0000 0000  A  00
100005 3415 DCA I 15 (7652) ((0000))         0001 00000 0000 0000  A  00
100006 6201 CDF 0                            0000 00000 0000 0000  A  00
000007 2017 ISZ 17 (7603)                    0000 00000 0000 0000  A  00
000010 5000 JMP 0                            0000 00000 0000 0000  A  00
000000 1412 TAD I 12 (0204) ((7602))         0000 07602 0000 0000  A  00
000001 3413 DCA I 13 (7604) ((0000))         0000 00000 0000 0000  A  00
000002 1414 TAD I 14 (0053) ((0000))         0000 00000 0000 0000  A  00
000003 2016 ISZ 16 (7764)                    0000 00000 0000 0000  A  00
000004 6211 CDF 1                            0001 00000 0000 0000  A  00
100005 3415 DCA I 15 (7653) ((0000))         0001 00000 0000 0000  A  00
100006 6201 CDF 0                            0000 00000 0000 0000  A  00
000007 2017 ISZ 17                           Runtime = 0:00:00.

---------------------------------------------------------------------------
   -dis [dec]          Disassemble dec instructions
                       e.g. -dis 150
This option allows the user to simply disassemble pdp8e CPU/EAE code.  Code
disassembly starts at the current IF/PC setting.  The optional argument
specifies the number of instructions to disassemble.  If the user omits the
argument, it defaults to 16.  No comparable option exists to disassemble
FPP-8/A code.  I may add that later.

>>>>>>	pdp8 -dis  <<<<<<

yielded the following:

Soft/pdp8 version 1993.12.21.0050 (c) Bill Haygood, [email-masked]
 Addr Inst Program
00007 2017 ISZ 17
00010 5000 JMP 0
00011 5437 JMP I 37
00012 0204 AND 4
00013 7604 CLA OSR
00014 0053 AND 53
00015 7653 CLA SCA SHL 7765
00017 7604 CLA OSR
00021 0000 AND 0
00023 0000 AND 0
00025 0000 AND 0
00027 0000 AND 0
00031 5030 JMP 30
00033 3436 DCA I 36
00035 0006 AND 6
00037 7605 CLA MUY 6741

Since data so often gets located close to instructions, the emulator
disassembles everything it sees as pdp8e code.  Obviously, a disassembled
listing take some interpretation.  Above, for example, an experienced
pdp8e programmer would see that the emulator has mistaken the "instruction"
in location 15 as a wierd EAE instruction.
---------------------------------------------------------------------------
   -exec [dec]         Execute dec inst's
                       e.g. -exec 1000000
This option allows the user to specify that execution stop after some
number of instructions have executed.  If the user omits the argument,
it defaults to 10,000,000 (about 20 seconds on my AMIGA).  I used this
option to determine emulator execution speed.
---------------------------------------------------------------------------
   -tab [file]         Output inst usage (to file)
                       e.g. -tab pdp8.tab
The user may specify a "tab" file in which a count of each of the possible
4,096 pdp8e instructions gets counted.  (Sometimes helpful in some debug
situations--such as emulator implementation.)
---------------------------------------------------------------------------
   -hist [file]        Output PC histogram (to file)
                       e.g. -hist pdp8.hst
The user may specify a "histogram" file to determine where most of the
"work" of the program gets done.
---------------------------------------------------------------------------
   -pause              Pause before exiting
This option causes the emulator to pause before exiting.  Mainly for use
on the AMIGA implementation to allow the user to fully read the text in
the emulator window before it closed.
---------------------------------------------------------------------------
   -diag               Run a MAINDEC diag program
Some MAINDEC diagnostics test for time-critical hardware flags' setting or
clearing.  Since the emulator only checks for a VDU keyboard strike or VDU
output character every 1,000 pdp8e instruction emulations, these
diagnostics will fail.  This option tells the emulator to check on the
I/O characters at the end of EVERY instruction emulation.
---------------------------------------------------------------------------
   -conout [file]      Save pdp8 console to file
                       e.g. -conout pdp8.out
This option allows the user to specify a "capture" file for all emulator
output to the console VDU.  The output also still displays normally when
the emulator runs.
---------------------------------------------------------------------------
   -auxout [file]      Save pdp8 aux console to file
                       e.g. -auxout pdp8.aux
This option allows the user to specify a "capture" file for all emulator
output to the auxilliary VDU.  Presently, only the AMIGA implementation
supports this option.
---------------------------------------------------------------------------
   -boot               Boot from RK8E disk
This option causes the emulator to treat the previously specified system
device file to boot (presently only the RK8E supported).
---------------------------------------------------------------------------
   -hardware           List 'hardware' status
This option causes a 'concise' listing of the 'hardware' status for the
CPU/EAE and all peripherals currently existing in the pdp8e memory file.

>>>>>>	pdp8 -hardware  <<<<<<

caused the following listing:

Soft/pdp8 'hardware' status:
PDP8:  DF/0 IF/0 PC/0007 L/0 AC/0000 MQ/0000 SR/0000
       IB/0 UB/F UF/F SF/000 INTENA/OFF INTINH/OFF DELAY/OFF
       IOFLAGS/RK8E 
       INTENAB/CONIN CONOUT 
       CONOUTCHAR/012
EAE:   MODE/A SC/00 GTF/F
RK8E:  COMM/0000 STAT/0000 CURAD/00400 BLOCK/0
       UNIT/0 WDCT/256 LOCK/F WRITE/F
FPP8:  RUN/NO PAUSE/NO MODE/LEAV DATA/FP COMM/0400 STAT/0000
       APT/00037 FPC/00225 NDX/10002 BASER/10023 OPADR/01317
       FAC/0000 0007 0533 2174 6551 6200

Some registers display as True or False, some as On or Off.  For example,
in the above, the GTF displays as False.
---------------------------------------------------------------------------
   -res                List 'hardware' resources
This option lists the 'hardware' resources presently existing in the pdp8e
memory file.  Using the enclosed 'pdp8.ram' file, executing:

>>>>>>	pdp8 -res  <<<<<<

displayed the following:

Soft/pdp8 Resources:                 (IOADR)
PDP-8/E with 32K memory
KE8-E Extended Arithmetic Element
FPP-8/A Floating Point Processor     (55/56)
RK8-E Hard Disk with 4 drives          (74)
Console Video Display Unit           (03/04)
LP8-E Line Printer                     (66)
PT8-E Paper Tape Reader/Punch        (01/02)

The emulator ALWAYS contains 32K memory.  No provision exists for removing
any memory.  Most pdp8e owners always DREAMED of 32K anyway.  Well, here we
have it!
---------------------------------------------------------------------------

Some notes on my pdp8e emulator implementation:

Originally, the module 'pdp8.c' contained the code that executed the
pdp8e and EAE instructions.  When that module became so large that my
C compiler could not optimize it, I moved it to 'pdp8run.c'.
Interestingly, though, the SAS/C optimizer had no trouble with the
much larger 'pdp8fpp8.c'.

'pdp8run.c' contains several 'run' loops.  The particular option
combination the user invokes determines which 'run' loop executes.  I
probably did not always arrange the logic consistently, but fundamentally
I tried to set up the emulator to invoke a particular 'run' loop that
would cause the least overhead.  The largest 'run' loop (and with the
most overhead) results from invoking an instruction trace.  The least
overhead results from invoking a bare-bones 'hardware' configuration
(EAE, however, causes virtually no overhead) such as no FPP-8/A, no clock,
no breaks, no trace, etc...

I originally made some of the following comments in a README file I sent
to Jim Van Zee.  So they may seem somewhat out of context here.  I just
included them so you could see some of the history of my implmentation.

I made a significant change in the way an AUXVDU gets added to the
'hardware' configuration.  When you specify the option '-auxvdu', you
may follow the option with an octal device address which specifies
the I/O address of the AUXVDU keyboard.  The AUXVDU display screen's
I/O address becomes one greater than that.  E.g. '-auxvdu 60' specifies
an AUXVDU at I/O octal addresses 60 and 61.  The emulator initialization
code 'plugs' the instrution execution vector table entries to reflect the
AUXVDU I/O address you specify so that AUXVDU I/O instructions will
execute correctly.  If you do not specify an AUXVDU I/O address, the
AUXVDU defaults to I/O addresses 40/41.  When you do specify an AUXVDU
I/O address, avoid any conflict with other I/O addresses since
unpredicatable results may occur.  The emulator checks for certain
obvious conflicts such as a clock's presence with an AUXVDU specified at
I/O addresses 12 or 13.

I left in Jim Van Zee's code for IOTs to handle the various clocks (DK8-EA,
DK8-EC, VT-78, VT-278 and PDP8-A), but I left unsupported the DK8-EP
programmable clock.  I MAY look at that later.

I changed the method by which the various 'hardware' registers get stored
in the PDP8.RAM file.  A byte-by-byte store scheme saves a lot of room
and I reduced the space for 'hardware' registers.  All multi-byte data
get stored in big-endian order to make the memory files portable across
differing architectures.  I added a data compression scheme for the
PDP8.RAM file when the pdp8 emulator exits.  Running the program 'CLEAR.SV'
from the emulator will save the OS/8 date word and clear all of memory to
zeroes and cause a pdp8 emulator exit.  This allows the emulator to
compress the PDP8.RAM file to a mere few bytes.  In fact, if all of pdp8e
memory contains a single value (e.g., zero), the pdp8e 32K-word memory
portion of the memory file compresses to just 4 bytes!

The FPP-8/A Floating Point Processor emulator does not emulate the
hardware as closely as the PDP8 CPU emulator.  The emulator carries
out floating point calculations by first converting the pdp8 multi-word
datum to double precision floating point format, performing the
calculation by calling the appropriate library function, then converting
the result back to multi-word, pdp8 format.  This may sound like big time
requirements to do FP calculations.  I tested the more obvious way of doing
the calcs--by manipulating the 3-word and 6-word data directly and this
method required MORE execution time (not to mention having to do multi-
precision arithmetic in software [and yes, I know how to implement software
floating point routines--I wrote Digital Research's floating point routines
in assembly language for both their Motorola and Intel library packages])!
The actual hardware carries 6-word FP calculations to a precision of 60
bits.  The emulator (since it uses double precision to do its work) carries
6-word FP calculations to a precision of around 54 bits.  The emulator
performs a rounding away from zero on every single-precision FP
calculation.  I could not determine from the documentation available to me
the functions of instructions 5100-5177.  I also could not determine the
formats of the instructions IMUL, IMULI, LEA and LEAI.  I implemented these
latter as a "guess".  I would appreciate any information anyone may have
about these gray areas.

I did not implement the FPP feature of "wrapping" around within a single
memory field.  I plan to look at this later.

In those cases where the FPP emulator outputs trace information, please
note the differences compared to trace information output for the PDP8
CPU emulator.  For example, the FPC displays only 5 octal digits which
indicates the 5-digit value (no IF or DF involved).  Some FPP instructions
occupy and trace output displays two 12-bit pdp8 words.  When an INDX
value appears, it represents the content of the currently addressed
FPP index register.  The STAT value displays the FPP status register.
When an FAC value appears, it represents the current contents of the
3-word or 6-word FPP Floating Point Accumulator.  In both the CPU and
FPP trace output cases, all values displayed to the left of the
instruction represent the CPU/FPP status PRIOR to execution of the
instruction and all values displayed to the right of the instruction
represent the CPU/FPP status AFTER execution of the instruction.

The emulator presently runs on my AMIGA 68040 CPU running at 33 MHz at
a best-case speed of 500,000 PDP-8 instruction emulations per second.  I
would guess that a PC or clone running an Intel i486 at the same speed
would do as well.

Jim Van Zee's idea for using IOTs to close the paper tape reader and punch
I have supported.  IOTs 6017 and 6027 close the reader and punch
respectively and IOT 6770 supports the DOS and SHELL commands.  I also
added IOT 6750 (called ZEROMEM) to clear all of PDP8 memory and cause
an emulator exit.  I welcome any ideas of a better way to support special
commands through IOT 6777.  Should the PDP8 AC contain the argument ?
Should the emulator clear the AC on return ?

Once you get OS/8 up and running, executing a .DOS command will cause
the host OS to execute one command (the argument to the .DOS command).

>>>>OS/8>>>>	.DOS ls *.c

will cause the host OS (if UNIX, as in this case) to list all filenames
ending with '.c'.  Executing .SHELL will bring up a shell from the host
OS allowing one to execute commands on the host OS.  Exiting the shell
returns to OS/8.

I would greatly appreciate your mailing me sources and binaries of
ANY device handlers you may have.  I especially need a standard RK05NS
handler, RX01 SYS and NON-SYS, TD8E DTA0-1 SYS and NON-SYS handlers.
Also, I would appreciate ANY pdp8e, EAE or other diagnostics (preferably
in "paper tape" format).

I managed to misplace the RX8E code documentation that Jim Van Zee sent.
I would appreciate your sending me a copy of that, if you have it.

Does anyone know where I can get DEC diagnostics on the following:
	EAE
	FPP-8/A
Help, please!  I would gratefully receive any information available.

The emulator can create a new "rk8e disk" file just by specifying a
non-existent "rk8e disk" file.  It will write only as many cylinders
(blocks of 32 sectors) as needed.  One drawback: if you ask for a
directory of (e.g.) RKB0:, the emulator will write zeroes to all
cylinders between the last one used and the first cylinder of RKB0:.
So, to keep the "rk8e disk" files small, I suggest we use only SYS:,
RKA1:, RKA2: and RKA3:.

I made lots of changes to the AMIGA portion of pdp8loc.c.  Now the PDP8
Console and PDP8 Aux Console windows get refreshed properly when the window
gets resized.  I would not have believed how the process worked until I
read the documentation.  The program never gets told about the window
resizing.  Every so often, the program must ask for the window size by
sending an ESC sequence via the output handler!  When the response ESC
sequence comes into the input (!) handler, then the program knows the
window size.  The program compares this value against the old value and,
if different, refreshes the window itself (no OS function provides
window refresh).  This means, of course, that the program must retain
at least a sufficient number of the output characters somewhere to
refresh the largest possible window.  A new window size smaller than
the previous size means that not all the output characters will have
use in the new window.  So, it does not pay to spend time putting out
characters that will scroll off the top of the window.  So, the emulator
housekeeping routines must calculate the window height and only output
the correct number of lines.  Well, you can read the code, if interested.
I hope I never have to deal with refresh again.

Kindest regards,

Bill Haygood