diff --git a/devices/pc8080/machine/test/machine.xml b/devices/pc8080/machine/test/machine.xml
index fb2cf1019..34686f2c4 100644
--- a/devices/pc8080/machine/test/machine.xml
+++ b/devices/pc8080/machine/test/machine.xml
@@ -4,8 +4,8 @@
8080 Test Machine
-
-
+
+
-
+
diff --git a/devices/pc8080/rom/test/8080EXER.MAC b/devices/pc8080/rom/test/8080EXER.MAC
new file mode 100644
index 000000000..243fade69
--- /dev/null
+++ b/devices/pc8080/rom/test/8080EXER.MAC
@@ -0,0 +1,1284 @@
+ title 'Z80 instruction set exerciser'
+
+; zexlax.z80 - Z80 instruction set exerciser
+; Copyright (C) 1994 Frank D. Cringle
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation; either version 2
+; of the License, or (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, write to the Free Software
+; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+;
+;******************************************************************************
+;
+; Modified to exercise an 8080 by Ian Bartholomew, February 2009
+;
+; I have made the following changes -
+;
+; Converted all mnemonics to 8080 and rewritten any Z80 code used
+; in the original exerciser. Changes are tagged with a #idb in the
+; source code listing.
+;
+; Removed any test descriptors that are not used.
+;
+; Changed the macro definitions to work in M80
+;
+; The machine state snapshot has been changed to remove the IX/IY registers.
+; They have been replaced by two more copies of HL to obviate the need
+; for major changes in the exerciser code.
+;
+; Changed flag mask in all tests to 0ffh to reflect that the 8080, unlike the 8085
+; and Z80, does define the unused bits in the flag register - [S Z 0 AC 0 P 1 C]
+;
+;******************************************************************************
+
+ .8080
+ aseg
+ org 100h
+
+begin: jmp start
+
+; machine state before test (needs to be at predictably constant address)
+msbt: ds 14
+spbt: ds 2
+
+; For the purposes of this test program, the machine state consists of:
+; a 2 byte memory operand, followed by
+; the registers iy,ix,hl,de,bc,af,sp
+; for a total of 16 bytes.
+
+; The program tests instructions (or groups of similar instructions)
+; by cycling through a sequence of machine states, executing the test
+; instruction for each one and running a 32-bit crc over the resulting
+; machine states. At the end of the sequence the crc is compared to
+; an expected value that was found empirically on a real Z80.
+
+; A test case is defined by a descriptor which consists of:
+; a flag mask byte,
+; the base case,
+; the incement vector,
+; the shift vector,
+; the expected crc,
+; a short descriptive message.
+;
+; The flag mask byte is used to prevent undefined flag bits from
+; influencing the results. Documented flags are as per Mostek Z80
+; Technical Manual.
+;
+; The next three parts of the descriptor are 20 byte vectors
+; corresponding to a 4 byte instruction and a 16 byte machine state.
+; The first part is the base case, which is the first test case of
+; the sequence. This base is then modified according to the next 2
+; vectors. Each 1 bit in the increment vector specifies a bit to be
+; cycled in the form of a binary counter. For instance, if the byte
+; corresponding to the accumulator is set to 0ffh in the increment
+; vector, the test will be repeated for all 256 values of the
+; accumulator. Note that 1 bits don't have to be contiguous. The
+; number of test cases 'caused' by the increment vector is equal to
+; 2^(number of 1 bits). The shift vector is similar, but specifies a
+; set of bits in the test case that are to be successively inverted.
+; Thus the shift vector 'causes' a number of test cases equal to the
+; number of 1 bits in it.
+
+; The total number of test cases is the product of those caused by the
+; counter and shift vectors and can easily become unweildy. Each
+; individual test case can take a few milliseconds to execute, due to
+; the overhead of test setup and crc calculation, so test design is a
+; compromise between coverage and execution time.
+
+; This program is designed to detect differences between
+; implementations and is not ideal for diagnosing the causes of any
+; discrepancies. However, provided a reference implementation (or
+; real system) is available, a failing test case can be isolated by
+; hand using a binary search of the test space.
+
+
+start: lhld 6
+ sphl
+ lxi d,msg1
+ mvi c,9
+ call bdos
+
+ lxi h,tests ; first test case
+loop: mov a,m ; end of list ?
+ inx h
+ ora m
+ jz done
+ dcx h
+ call stt
+ jmp loop
+
+done: lxi d,msg2
+ mvi c,9
+ call bdos
+ jmp 0 ; warm boot
+
+tests:
+ dw add16
+ dw alu8i
+ dw alu8r
+ dw daa
+ dw inca
+ dw incb
+ dw incbc
+ dw incc
+ dw incd
+ dw incde
+ dw ince
+ dw inch
+ dw inchl
+ dw incl
+ dw incm
+ dw incsp
+ dw ld162
+ dw ld166
+ dw ld16im
+ dw ld8bd
+ dw ld8im
+ dw ld8rr
+ dw lda
+ dw rot8080
+ dw stabd
+ dw 0
+
+tstr macro insn,memop,hliy,hlix,hl,de,bc,flags,acc,sp
+ local lab
+lab: db insn
+ ds lab+4-$,0
+ dw memop,hliy,hlix,hl,de,bc
+ db flags
+ db acc
+ dw sp
+ if $-lab ne 20
+ error 'missing parameter'
+ endif
+ endm
+
+tmsg macro m
+ local lab
+lab: db m
+ if $ ge lab+30
+ error 'message too long'
+ else
+ ds lab+30-$,'.'
+ endif
+ db '$'
+ endm
+
+; add hl, (19,456 cycles)
+add16: db 0ffh ; flag mask
+ tstr 9,0c4a5h,0c4c7h,0d226h,0a050h,058eah,08566h,0c6h,0deh,09bc9h
+ tstr 030h,0,0,0,0f821h,0,0,0,0,0 ; (512 cycles)
+ tstr 0,0,0,0,-1,-1,-1,0d7h,0,-1 ; (38 cycles)
+ db 0,0,0,0 ; expected crc
+ tmsg 'dad '
+
+; aluop a,nn (28,672 cycles)
+alu8i: db 0ffh ; flag mask
+ tstr 0c6h,09140h,07e3ch,07a67h,0df6dh,05b61h,00b29h,010h,066h,085b2h
+ tstr 038h,0,0,0,0,0,0,0,-1,0 ; (2048 cycles)
+ tstr <0,-1>,0,0,0,0,0,0,0d7h,0,0 ; (14 cycles)
+ db 0,0,0,0 ; expected crc
+ tmsg 'aluop nn'
+
+; aluop a, (753,664 cycles)
+alu8r: db 0ffh ; flag mask
+ tstr 080h,0c53eh,0573ah,04c4dh,msbt,0e309h,0a666h,0d0h,03bh,0adbbh
+ tstr 03fh,0,0,0,0,0,0,0,-1,0 ; (16,384 cycles)
+ tstr 0,0ffh,0,0,0,-1,-1,0d7h,0,0 ; (46 cycles)
+ db 0,0,0,0 ; expected crc
+ tmsg 'aluop '
+
+;
+daa: db 0ffh ; flag mask
+ tstr 027h,02141h,009fah,01d60h,0a559h,08d5bh,09079h,004h,08eh,0299dh
+ tstr 018h,0,0,0,0,0,0,0d7h,-1,0 ; (65,536 cycles)
+ tstr 0,0,0,0,0,0,0,0,0,0 ; (1 cycle)
+ db 0,0,0,0 ; expected crc
+ tmsg ''
+
+; a (3072 cycles)
+inca: db 0ffh ; flag mask
+ tstr 03ch,04adfh,0d5d8h,0e598h,08a2bh,0a7b0h,0431bh,044h,05ah,0d030h
+ tstr 001h,0,0,0,0,0,0,0,-1,0 ; (512 cycles)
+ tstr 0,0,0,0,0,0,0,0d7h,0,0 ; (6 cycles)
+ db 0,0,0,0 ; expected crc
+ tmsg ' a'
+
+; b (3072 cycles)
+incb: db 0ffh ; flag mask
+ tstr 004h,0d623h,0432dh,07a61h,08180h,05a86h,01e85h,086h,058h,09bbbh
+ tstr 001h,0,0,0,0,0,0ff00h,0,0,0 ; (512 cycles)
+ tstr 0,0,0,0,0,0,0,0d7h,0,0 ; (6 cycles)
+ db 0,0,0,0 ; expected crc
+ tmsg ' b'
+
+; bc (1536 cycles)
+incbc: db 0ffh ; flag mask
+ tstr 003h,0cd97h,044abh,08dc9h,0e3e3h,011cch,0e8a4h,002h,049h,02a4dh
+ tstr 008h,0,0,0,0,0,0f821h,0,0,0 ; (256 cycles)
+ tstr 0,0,0,0,0,0,0,0d7h,0,0 ; (6 cycles)
+ db 0,0,0,0 ; expected crc
+ tmsg ' b'
+
+; c (3072 cycles)
+incc: db 0ffh ; flag mask
+ tstr 00ch,0d789h,00935h,0055bh,09f85h,08b27h,0d208h,095h,005h,00660h
+ tstr 001h,0,0,0,0,0,0ffh,0,0,0 ; (512 cycles)
+ tstr 0,0,0,0,0,0,0,0d7h,0,0 ; (6 cycles)
+ db 0,0,0,0 ; expected crc
+ tmsg ' c'
+
+; d (3072 cycles)
+incd: db 0ffh ; flag mask
+ tstr 014h,0a0eah,05fbah,065fbh,0981ch,038cch,0debch,043h,05ch,003bdh
+ tstr 001h,0,0,0,0,0ff00h,0,0,0,0 ; (512 cycles)
+ tstr 0,0,0,0,0,0,0,0d7h,0,0 ; (6 cycles)
+ db 0,0,0,0 ; expected crc
+ tmsg ' d'
+
+; de (1536 cycles)
+incde: db 0ffh ; flag mask
+ tstr 013h,0342eh,0131dh,028c9h,00acah,09967h,03a2eh,092h,0f6h,09d54h
+ tstr 008h,0,0,0,0,0f821h,0,0,0,0 ; (256 cycles)
+ tstr 0,0,0,0,0,0,0,0d7h,0,0 ; (6 cycles)
+ db 0,0,0,0 ; expected crc
+ tmsg ' d'
+
+; e (3072 cycles)
+ince: db 0ffh ; flag mask
+ tstr 01ch,0602fh,04c0dh,02402h,0e2f5h,0a0f4h,0a10ah,013h,032h,05925h
+ tstr 001h,0,0,0,0,0ffh,0,0,0,0 ; (512 cycles)
+ tstr 0,0,0,0,0,0,0,0d7h,0,0 ; (6 cycles)
+ db 0,0,0,0 ; expected crc
+ tmsg ' e'
+
+; h (3072 cycles)
+inch: db 0ffh ; flag mask
+ tstr 024h,01506h,0f2ebh,0e8ddh,0262bh,011a6h,0bc1ah,017h,006h,02818h
+ tstr 001h,0,0,0,0ff00h,0,0,0,0,0 ; (512 cycles)
+ tstr 0,0,0,0,0,0,0,0d7h,0,0 ; (6 cycles)
+ db 0,0,0,0 ; expected crc
+ tmsg ' h'
+
+; hl (1536 cycles)
+inchl: db 0ffh ; flag mask
+ tstr 023h,0c3f4h,007a5h,01b6dh,04f04h,0e2c2h,0822ah,057h,0e0h,0c3e1h
+ tstr 008h,0,0,0,0f821h,0,0,0,0,0 ; (256 cycles)
+ tstr 0,0,0,0,0,0,0,0d7h,0,0 ; (6 cycles)
+ db 0,0,0,0 ; expected crc
+ tmsg ' h'
+
+; l (3072 cycles)
+incl: db 0ffh ; flag mask
+ tstr 02ch,08031h,0a520h,04356h,0b409h,0f4c1h,0dfa2h,0d1h,03ch,03ea2h
+ tstr 001h,0,0,0,0ffh,0,0,0,0,0 ; (512 cycles)
+ tstr 0,0,0,0,0,0,0,0d7h,0,0 ; (6 cycles)
+ db 0,0,0,0 ; expected crc
+ tmsg ' l'
+
+; (hl) (3072 cycles)
+incm: db 0ffh ; flag mask
+ tstr 034h,0b856h,00c7ch,0e53eh,msbt,0877eh,0da58h,015h,05ch,01f37h
+ tstr 001h,0ffh,0,0,0,0,0,0,0,0 ; (512 cycles)
+ tstr 0,0,0,0,0,0,0,0d7h,0,0 ; (6 cycles)
+ db 0,0,0,0 ; expected crc
+ tmsg ' m'
+
+; sp (1536 cycles)
+incsp: db 0ffh ; flag mask
+ tstr 033h,0346fh,0d482h,0d169h,0deb6h,0a494h,0f476h,053h,002h,0855bh
+ tstr 008h,0,0,0,0,0,0,0,0,0f821h ; (256 cycles)
+ tstr 0,0,0,0,0,0,0,0d7h,0,0 ; (6 cycles)
+ db 0,0,0,0 ; expected crc
+ tmsg ' sp'
+
+; ld hl,(nnnn) (16 cycles)
+ld162: db 0ffh ; flag mask
+ tstr <02ah,low msbt,high msbt>,09863h,07830h,02077h,0b1feh,0b9fah,0abb8h,004h,006h,06015h
+ tstr 0,0,0,0,0,0,0,0,0,0 ; (1 cycle)
+ tstr 0,-1,0,0,0,0,0,0,0,0 ; (16 cycles)
+ db 0,0,0,0 ; expected crc
+ tmsg 'lhld nnnn'
+
+; ld (nnnn),hl (16 cycles)
+ld166: db 0ffh ; flag mask
+ tstr <022h,low msbt,high msbt>,0d003h,07772h,07f53h,03f72h,064eah,0e180h,010h,02dh,035e9h
+ tstr 0,0,0,0,0,0,0,0,0,0 ; (1 cycle)
+ tstr 0,0,0,0,-1,0,0,0,0,0 ; (16 cycles)
+ db 0,0,0,0 ; expected crc
+ tmsg 'shld nnnn'
+
+; ld ,nnnn (64 cycles)
+ld16im: db 0ffh ; flag mask
+ tstr 1,05c1ch,02d46h,08eb9h,06078h,074b1h,0b30eh,046h,0d1h,030cch
+ tstr 030h,0,0,0,0,0,0,0,0,0 ; (4 cycles)
+ tstr <0,0ffh,0ffh>,0,0,0,0,0,0,0,0,0 ; (16 cycles)
+ db 0,0,0,0 ; expected crc
+ tmsg 'lxi ,nnnn'
+
+; ld a,<(bc),(de)> (44 cycles)
+ld8bd: db 0ffh ; flag mask
+ tstr 00ah,0b3a8h,01d2ah,07f8eh,042ach,msbt,msbt,0c6h,0b1h,0ef8eh
+ tstr 010h,0,0,0,0,0,0,0,0,0 ; (2 cycles)
+ tstr 0,0ffh,0,0,0,0,0,0d7h,-1,0 ; (22 cycles)
+ db 0,0,0,0 ; expected crc
+ tmsg 'ldax '
+
+; ld ,nn (64 cycles)
+ld8im: db 0ffh ; flag mask
+ tstr 6,0c407h,0f49dh,0d13dh,00339h,0de89h,07455h,053h,0c0h,05509h
+ tstr 038h,0,0,0,0,0,0,0,0,0 ; (8 cycles)
+ tstr 0,0,0,0,0,0,0,0,-1,0 ; (8 cycles)
+ db 0,0,0,0 ; expected crc
+ tmsg 'mvi ,nn'
+
+; ld , (3456 cycles)
+ld8rr: db 0ffh ; flag mask
+ tstr 040h,072a4h,0a024h,061ach,msbt,082c7h,0718fh,097h,08fh,0ef8eh
+ tstr 03fh,0,0,0,0,0,0,0,0,0 ; (64 cycles)
+ tstr 0,0ffh,0,0,0,-1,-1,0d7h,-1,0 ; (54 cycles)
+ db 0,0,0,0 ; expected crc
+ tmsg 'mov ,'
+
+; ld a,(nnnn) / ld (nnnn),a (44 cycles)
+lda: db 0ffh ; flag mask
+ tstr <032h,low msbt,high msbt>,0fd68h,0f4ech,044a0h,0b543h,00653h,0cdbah,0d2h,04fh,01fd8h
+ tstr 008h,0,0,0,0,0,0,0,0,0 ; (2 cycle)
+ tstr 0,0ffh,0,0,0,0,0,0d7h,-1,0 ; (22 cycles)
+ db 0,0,0,0 ; expected crc
+ tmsg 'sta nnnn / lda nnnn'
+
+; (6144 cycles)
+rot8080: db 0ffh ; flag mask
+ tstr 7,0cb92h,06d43h,00a90h,0c284h,00c53h,0f50eh,091h,0ebh,040fch
+ tstr 018h,0,0,0,0,0,0,0,-1,0 ; (1024 cycles)
+ tstr 0,0,0,0,0,0,0,0d7h,0,0 ; (6 cycles)
+ db 0,0,0,0 ; expected crc
+ tmsg ''
+
+; ld (),a (96 cycles)
+stabd: db 0ffh ; flag mask
+ tstr 2,00c3bh,0b592h,06cffh,0959eh,msbt,msbt+1,0c1h,021h,0bde7h
+ tstr 018h,0,0,0,0,0,0,0,0,0 ; (4 cycles)
+ tstr 0,-1,0,0,0,0,0,0,-1,0 ; (24 cycles)
+ db 0,0,0,0 ; expected crc
+ tmsg 'stax '
+
+; start test pointed to by (hl)
+stt: push h
+ mov a,m ; get pointer to test
+ inx h
+ mov h,m
+ mov l,a
+ mov a,m ; flag mask
+ sta flgmsk+1
+ inx h
+ push h
+ lxi d,20
+ dad d ; point to incmask
+ lxi d,counter
+ call initmask
+ pop h
+ push h
+ lxi d,20+20
+ dad d ; point to scanmask
+ lxi d,shifter
+ call initmask
+ lxi h,shifter
+ mvi m,1 ; first bit
+ pop h
+ push h
+ lxi d,iut ; copy initial instruction under test
+ lxi b,4
+
+;#idb ldir replaced with following code
+ldir1: mov a,m
+ stax d
+ inx h
+ inx d
+ dcx b
+ mov a,b
+ ora c
+ jnz ldir1
+;#idb
+
+ lxi d,msbt ; copy initial machine state
+ lxi b,16
+
+;#idb ldir replaced with following code
+ldir2: mov a,m
+ stax d
+ inx h
+ inx d
+ dcx b
+ mov a,b
+ ora c
+ jnz ldir2
+;#idb
+
+ lxi d,20+20+4 ; skip incmask, scanmask and expcrc
+ dad d
+ xchg
+ mvi c,9
+ call bdos ; show test name
+ call initcrc ; initialise crc
+; test loop
+tlp: lda iut
+ cpi 076h ; pragmatically avoid halt intructions
+ jz tlp2
+ ani 0dfh
+ cpi 0ddh
+ jnz tlp1
+ lda iut+1
+ cpi 076h
+tlp1: cnz test ; execute the test instruction
+tlp2: call count ; increment the counter
+ cnz shift ; shift the scan bit
+ pop h ; pointer to test case
+ jz tlp3 ; done if shift returned NZ
+ lxi d,20+20+20
+ dad d ; point to expected crc
+ call cmpcrc
+ lxi d,okmsg
+ jz tlpok
+ lxi d,ermsg1
+ mvi c,9
+ call bdos
+ call phex8
+ lxi d,ermsg2
+ mvi c,9
+ call bdos
+ lxi h,crcval
+ call phex8
+ lxi d,crlf
+tlpok: mvi c,9
+ call bdos
+ pop h
+ inx h
+ inx h
+ ret
+
+tlp3: push h
+ mvi a,1 ; initialise count and shift scanners
+ sta cntbit
+ sta shfbit
+ lxi h,counter
+ shld cntbyt
+ lxi h,shifter
+ shld shfbyt
+
+ mvi b,4 ; bytes in iut field
+ pop h ; pointer to test case
+ push h
+ lxi d,iut
+ call setup ; setup iut
+ mvi b,16 ; bytes in machine state
+ lxi d,msbt
+ call setup ; setup machine state
+ jmp tlp
+
+; setup a field of the test case
+; b = number of bytes
+; hl = pointer to base case
+; de = destination
+setup: call subyte
+ inx h
+ dcr b
+ jnz setup
+ ret
+
+subyte: push b
+ push d
+ push h
+ mov c,m ; get base byte
+ lxi d,20
+ dad d ; point to incmask
+ mov a,m
+ cpi 0
+ jz subshf
+ mvi b,8 ; 8 bits
+subclp: rrc
+ push psw
+ mvi a,0
+ cc nxtcbit ; get next counter bit if mask bit was set
+ xra c ; flip bit if counter bit was set
+ rrc
+ mov c,a
+ pop psw
+ dcr b
+ jnz subclp
+ mvi b,8
+subshf: lxi d,20
+ dad d ; point to shift mask
+ mov a,m
+ cpi 0
+ jz substr
+ mvi b,8 ; 8 bits
+sbshf1: rrc
+ push psw
+ mvi a,0
+ cc nxtsbit ; get next shifter bit if mask bit was set
+ xra c ; flip bit if shifter bit was set
+ rrc
+ mov c,a
+ pop psw
+ dcr b
+ jnz sbshf1
+substr: pop h
+ pop d
+ mov a,c
+ stax d ; mangled byte to destination
+ inx d
+ pop b
+ ret
+
+; get next counter bit in low bit of a
+cntbit: ds 1
+cntbyt: ds 2
+
+nxtcbit: push b
+ push h
+ lhld cntbyt
+ mov b,m
+ lxi h,cntbit
+ mov a,m
+ mov c,a
+ rlc
+ mov m,a
+ cpi 1
+ jnz ncb1
+ lhld cntbyt
+ inx h
+ shld cntbyt
+ncb1: mov a,b
+ ana c
+ pop h
+ pop b
+ rz
+ mvi a,1
+ ret
+
+; get next shifter bit in low bit of a
+shfbit: ds 1
+shfbyt: ds 2
+
+nxtsbit: push b
+ push h
+ lhld shfbyt
+ mov b,m
+ lxi h,shfbit
+ mov a,m
+ mov c,a
+ rlc
+ mov m,a
+ cpi 1
+ jnz nsb1
+ lhld shfbyt
+ inx h
+ shld shfbyt
+nsb1: mov a,b
+ ana c
+ pop h
+ pop b
+ rz
+ mvi a,1
+ ret
+
+
+; clear memory at hl, bc bytes
+clrmem: push psw
+ push b
+ push d
+ push h
+ mvi m,0
+ mov d,h
+ mov e,l
+ inx d
+ dcx b
+
+;#idb ldir replaced with following code
+ldir3: mov a,m
+ stax d
+ inx h
+ inx d
+ dcx b
+ mov a,b
+ ora c
+ jnz ldir3
+;#idb
+
+ pop h
+ pop d
+ pop b
+ pop psw
+ ret
+
+; initialise counter or shifter
+; de = pointer to work area for counter or shifter
+; hl = pointer to mask
+initmask:
+ push d
+ xchg
+ lxi b,20+20
+ call clrmem ; clear work area
+ xchg
+ mvi b,20 ; byte counter
+ mvi c,1 ; first bit
+ mvi d,0 ; bit counter
+imlp: mov e,m
+imlp1: mov a,e
+ ana c
+ jz imlp2
+ inr d
+imlp2: mov a,c
+ rlc
+ mov c,a
+ cpi 1
+ jnz imlp1
+ inx h
+ dcr b
+ jnz imlp
+; got number of 1-bits in mask in reg d
+ mov a,d
+ ani 0f8h
+ rrc
+ rrc
+ rrc ; divide by 8 (get byte offset)
+ mov l,a
+ mvi h,0
+ mov a,d
+ ani 7 ; bit offset
+ inr a
+ mov b,a
+ mvi a,080h
+imlp3: rlc
+ dcr b
+ jnz imlp3
+ pop d
+ dad d
+ lxi d,20
+ dad d
+ mov m,a
+ ret
+
+; multi-byte counter
+count: push b
+ push d
+ push h
+ lxi h,counter ; 20 byte counter starts here
+ lxi d,20 ; somewhere in here is the stop bit
+ xchg
+ dad d
+ xchg
+cntlp: inr m
+ mov a,m
+ cpi 0
+ jz cntlp1 ; overflow to next byte
+ mov b,a
+ ldax d
+ ana b ; test for terminal value
+ jz cntend
+ mvi m,0 ; reset to zero
+cntend: pop b
+ pop d
+ pop h
+ ret
+
+cntlp1: inx h
+ inx d
+ jmp cntlp
+
+
+; multi-byte shifter
+shift: push b
+ push d
+ push h
+ lxi h,shifter ; 20 byte shift register starts here
+ lxi d,20 ; somewhere in here is the stop bit
+ xchg
+ dad d
+ xchg
+shflp: mov a,m
+ ora a
+ jz shflp1
+ mov b,a
+ ldax d
+ ana b
+ jnz shlpe
+ mov a,b
+ rlc
+ cpi 1
+ jnz shflp2
+ mvi m,0
+ inx h
+ inx d
+shflp2: mov m,a
+ xra a ; set Z
+shlpe: pop h
+ pop d
+ pop b
+ ret
+shflp1: inx h
+ inx d
+ jmp shflp
+
+counter: ds 2*20
+shifter: ds 2*20
+
+; test harness
+test: push psw
+ push b
+ push d
+ push h
+ if 0
+ lxi d,crlf
+ mvi c,9
+ call bdos
+ lxi h,iut
+ mvi b,4
+ call hexstr
+ mvi e,' '
+ mvi c,2
+ call bdos
+ mvi b,16
+ lxi h,msbt
+ call hexstr
+ endif
+ di ; disable interrupts
+
+;#idb ld (spsav),sp replaced by following code
+;#idb All registers and flages are immediately overwritten so
+;#idb no need to preserve any state.
+ lxi h,0 ; save stack pointer
+ dad sp
+ shld spsav
+;#idb
+
+ lxi sp,msbt+2 ; point to test-case machine state
+
+;#idb pop iy
+;#idb pop ix both replaced by following code
+;#idb Just dummy out ix/iy with copies of hl
+ pop h ; and load all regs
+ pop h
+;#idb
+
+ pop h
+ pop d
+ pop b
+ pop psw
+
+;#idb ld sp,(spbt) replaced with the following code
+;#idb HL is copied/restored before/after load so no state changed
+ shld temp
+ lhld spbt
+ sphl
+ lhld temp
+;#idb
+
+iut: ds 4 ; max 4 byte instruction under test
+
+;#idb ld (spat),sp replaced with the following code
+;#idb Must be very careful to preserve registers and flag
+;#idb state resulting from the test. The temptation is to use the
+;#idb stack - but that doesn't work because of the way the app
+;#idb uses SP as a quick way of pointing to memory.
+;#idb Bit of a code smell, but I can't think of an easier way.
+ shld temp
+ lxi h,0
+ jc temp1 ;jump on the state of the C flag set in the test
+
+ dad sp ;this code will clear the C flag (0 + nnnn = nc)
+ jmp temp2 ;C flag is same state as before
+
+temp1: dad sp ;this code will clear the C flag (0 + nnnn = nc)
+ stc ;C flage needs re-setting to preserve state
+
+temp2: shld spat
+ lhld temp
+;#idb
+
+ lxi sp,spat
+ push psw ; save other registers
+ push b
+ push d
+ push h
+
+;#idb push ix
+;#idb push iy both replaced by following code
+;#idb Must match change made to pops made before test
+ push h
+ push h
+;#idb
+
+;#idb ld sp,(spsav) replaced with following code
+;#idb No need to preserve state
+ lhld spsav ; restore stack pointer
+ sphl
+;#idb
+
+ ei ; enable interrupts
+ lhld msbt ; copy memory operand
+ shld msat
+ lxi h,flgsat ; flags after test
+ mov a,m
+flgmsk: ani 0ffh ; mask-out irrelevant bits (self-modified code!)
+ mov m,a
+ mvi b,16 ; total of 16 bytes of state
+ lxi d,msat
+ lxi h,crcval
+tcrc: ldax d
+ inx d
+ call updcrc ; accumulate crc of this test case
+ dcr b
+ jnz tcrc
+ if 0
+ mvi e,' '
+ mvi c,2
+ call bdos
+ lxi h,crcval
+ call phex8
+ lxi d,crlf
+ mvi c,9
+ call bdos
+ lxi h,msat
+ mvi b,16
+ call hexstr
+ lxi d,crlf
+ mvi c,9
+ call bdos
+ endif
+ pop h
+ pop d
+ pop b
+ pop psw
+ ret
+
+;#idb Added to store HL state
+temp: ds 2
+;#idb
+
+; machine state after test
+msat: ds 14 ; memop,iy,ix,hl,de,bc,af
+spat: ds 2 ; stack pointer after test
+flgsat equ spat-2 ; flags
+
+spsav: ds 2 ; saved stack pointer
+
+; display hex string (pointer in hl, byte count in b)
+hexstr: mov a,m
+ call phex2
+ inx h
+ dcr b
+ jnz hexstr
+ ret
+
+; display hex
+; display the big-endian 32-bit value pointed to by hl
+phex8: push psw
+ push b
+ push h
+ mvi b,4
+ph8lp: mov a,m
+ call phex2
+ inx h
+ dcr b
+ jnz ph8lp
+ pop h
+ pop b
+ pop psw
+ ret
+
+; display byte in a
+phex2: push psw
+ rrc
+ rrc
+ rrc
+ rrc
+ call phex1
+ pop psw
+; fall through
+
+; display low nibble in a
+phex1: push psw
+ push b
+ push d
+ push h
+ ani 0fh
+ cpi 10
+ jc ph11
+ adi 'a'-'9'-1
+ph11: adi '0'
+ mov e,a
+ mvi c,2
+ call bdos
+ pop h
+ pop d
+ pop b
+ pop psw
+ ret
+
+bdos: push psw
+ push b
+ push d
+ push h
+ call 5
+ pop h
+ pop d
+ pop b
+ pop psw
+ ret
+
+msg1: db '8080 instruction exerciser',10,13,'$'
+msg2: db 'Tests complete$'
+okmsg: db ' OK',10,13,'$'
+ermsg1: db ' ERROR **** crc expected:$'
+ermsg2: db ' found:$'
+crlf: db 10,13,'$'
+
+; compare crc
+; hl points to value to compare to crcval
+cmpcrc: push b
+ push d
+ push h
+ lxi d,crcval
+ mvi b,4
+cclp: ldax d
+ cmp m
+ jnz cce
+ inx h
+ inx d
+ dcr b
+ jnz cclp
+cce: pop h
+ pop d
+ pop b
+ ret
+
+; 32-bit crc routine
+; entry: a contains next byte, hl points to crc
+; exit: crc updated
+updcrc: push psw
+ push b
+ push d
+ push h
+ push h
+ lxi d,3
+ dad d ; point to low byte of old crc
+ xra m ; xor with new byte
+ mov l,a
+ mvi h,0
+ dad h ; use result as index into table of 4 byte entries
+ dad h
+ xchg
+ lxi h,crctab
+ dad d ; point to selected entry in crctab
+ xchg
+ pop h
+ lxi b,4 ; c = byte count, b = accumulator
+crclp: ldax d
+ xra b
+ mov b,m
+ mov m,a
+ inx d
+ inx h
+ dcr c
+ jnz crclp
+ if 0
+ lxi h,crcval
+ call phex8
+ lxi d,crlf
+ mvi c,9
+ call bdos
+ endif
+ pop h
+ pop d
+ pop b
+ pop psw
+ ret
+
+initcrc:push psw
+ push b
+ push h
+ lxi h,crcval
+ mvi a,0ffh
+ mvi b,4
+icrclp: mov m,a
+ inx h
+ dcr b
+ jnz icrclp
+ pop h
+ pop b
+ pop psw
+ ret
+
+crcval: ds 4
+
+crctab: db 000h,000h,000h,000h
+ db 077h,007h,030h,096h
+ db 0eeh,00eh,061h,02ch
+ db 099h,009h,051h,0bah
+ db 007h,06dh,0c4h,019h
+ db 070h,06ah,0f4h,08fh
+ db 0e9h,063h,0a5h,035h
+ db 09eh,064h,095h,0a3h
+ db 00eh,0dbh,088h,032h
+ db 079h,0dch,0b8h,0a4h
+ db 0e0h,0d5h,0e9h,01eh
+ db 097h,0d2h,0d9h,088h
+ db 009h,0b6h,04ch,02bh
+ db 07eh,0b1h,07ch,0bdh
+ db 0e7h,0b8h,02dh,007h
+ db 090h,0bfh,01dh,091h
+ db 01dh,0b7h,010h,064h
+ db 06ah,0b0h,020h,0f2h
+ db 0f3h,0b9h,071h,048h
+ db 084h,0beh,041h,0deh
+ db 01ah,0dah,0d4h,07dh
+ db 06dh,0ddh,0e4h,0ebh
+ db 0f4h,0d4h,0b5h,051h
+ db 083h,0d3h,085h,0c7h
+ db 013h,06ch,098h,056h
+ db 064h,06bh,0a8h,0c0h
+ db 0fdh,062h,0f9h,07ah
+ db 08ah,065h,0c9h,0ech
+ db 014h,001h,05ch,04fh
+ db 063h,006h,06ch,0d9h
+ db 0fah,00fh,03dh,063h
+ db 08dh,008h,00dh,0f5h
+ db 03bh,06eh,020h,0c8h
+ db 04ch,069h,010h,05eh
+ db 0d5h,060h,041h,0e4h
+ db 0a2h,067h,071h,072h
+ db 03ch,003h,0e4h,0d1h
+ db 04bh,004h,0d4h,047h
+ db 0d2h,00dh,085h,0fdh
+ db 0a5h,00ah,0b5h,06bh
+ db 035h,0b5h,0a8h,0fah
+ db 042h,0b2h,098h,06ch
+ db 0dbh,0bbh,0c9h,0d6h
+ db 0ach,0bch,0f9h,040h
+ db 032h,0d8h,06ch,0e3h
+ db 045h,0dfh,05ch,075h
+ db 0dch,0d6h,00dh,0cfh
+ db 0abh,0d1h,03dh,059h
+ db 026h,0d9h,030h,0ach
+ db 051h,0deh,000h,03ah
+ db 0c8h,0d7h,051h,080h
+ db 0bfh,0d0h,061h,016h
+ db 021h,0b4h,0f4h,0b5h
+ db 056h,0b3h,0c4h,023h
+ db 0cfh,0bah,095h,099h
+ db 0b8h,0bdh,0a5h,00fh
+ db 028h,002h,0b8h,09eh
+ db 05fh,005h,088h,008h
+ db 0c6h,00ch,0d9h,0b2h
+ db 0b1h,00bh,0e9h,024h
+ db 02fh,06fh,07ch,087h
+ db 058h,068h,04ch,011h
+ db 0c1h,061h,01dh,0abh
+ db 0b6h,066h,02dh,03dh
+ db 076h,0dch,041h,090h
+ db 001h,0dbh,071h,006h
+ db 098h,0d2h,020h,0bch
+ db 0efh,0d5h,010h,02ah
+ db 071h,0b1h,085h,089h
+ db 006h,0b6h,0b5h,01fh
+ db 09fh,0bfh,0e4h,0a5h
+ db 0e8h,0b8h,0d4h,033h
+ db 078h,007h,0c9h,0a2h
+ db 00fh,000h,0f9h,034h
+ db 096h,009h,0a8h,08eh
+ db 0e1h,00eh,098h,018h
+ db 07fh,06ah,00dh,0bbh
+ db 008h,06dh,03dh,02dh
+ db 091h,064h,06ch,097h
+ db 0e6h,063h,05ch,001h
+ db 06bh,06bh,051h,0f4h
+ db 01ch,06ch,061h,062h
+ db 085h,065h,030h,0d8h
+ db 0f2h,062h,000h,04eh
+ db 06ch,006h,095h,0edh
+ db 01bh,001h,0a5h,07bh
+ db 082h,008h,0f4h,0c1h
+ db 0f5h,00fh,0c4h,057h
+ db 065h,0b0h,0d9h,0c6h
+ db 012h,0b7h,0e9h,050h
+ db 08bh,0beh,0b8h,0eah
+ db 0fch,0b9h,088h,07ch
+ db 062h,0ddh,01dh,0dfh
+ db 015h,0dah,02dh,049h
+ db 08ch,0d3h,07ch,0f3h
+ db 0fbh,0d4h,04ch,065h
+ db 04dh,0b2h,061h,058h
+ db 03ah,0b5h,051h,0ceh
+ db 0a3h,0bch,000h,074h
+ db 0d4h,0bbh,030h,0e2h
+ db 04ah,0dfh,0a5h,041h
+ db 03dh,0d8h,095h,0d7h
+ db 0a4h,0d1h,0c4h,06dh
+ db 0d3h,0d6h,0f4h,0fbh
+ db 043h,069h,0e9h,06ah
+ db 034h,06eh,0d9h,0fch
+ db 0adh,067h,088h,046h
+ db 0dah,060h,0b8h,0d0h
+ db 044h,004h,02dh,073h
+ db 033h,003h,01dh,0e5h
+ db 0aah,00ah,04ch,05fh
+ db 0ddh,00dh,07ch,0c9h
+ db 050h,005h,071h,03ch
+ db 027h,002h,041h,0aah
+ db 0beh,00bh,010h,010h
+ db 0c9h,00ch,020h,086h
+ db 057h,068h,0b5h,025h
+ db 020h,06fh,085h,0b3h
+ db 0b9h,066h,0d4h,009h
+ db 0ceh,061h,0e4h,09fh
+ db 05eh,0deh,0f9h,00eh
+ db 029h,0d9h,0c9h,098h
+ db 0b0h,0d0h,098h,022h
+ db 0c7h,0d7h,0a8h,0b4h
+ db 059h,0b3h,03dh,017h
+ db 02eh,0b4h,00dh,081h
+ db 0b7h,0bdh,05ch,03bh
+ db 0c0h,0bah,06ch,0adh
+ db 0edh,0b8h,083h,020h
+ db 09ah,0bfh,0b3h,0b6h
+ db 003h,0b6h,0e2h,00ch
+ db 074h,0b1h,0d2h,09ah
+ db 0eah,0d5h,047h,039h
+ db 09dh,0d2h,077h,0afh
+ db 004h,0dbh,026h,015h
+ db 073h,0dch,016h,083h
+ db 0e3h,063h,00bh,012h
+ db 094h,064h,03bh,084h
+ db 00dh,06dh,06ah,03eh
+ db 07ah,06ah,05ah,0a8h
+ db 0e4h,00eh,0cfh,00bh
+ db 093h,009h,0ffh,09dh
+ db 00ah,000h,0aeh,027h
+ db 07dh,007h,09eh,0b1h
+ db 0f0h,00fh,093h,044h
+ db 087h,008h,0a3h,0d2h
+ db 01eh,001h,0f2h,068h
+ db 069h,006h,0c2h,0feh
+ db 0f7h,062h,057h,05dh
+ db 080h,065h,067h,0cbh
+ db 019h,06ch,036h,071h
+ db 06eh,06bh,006h,0e7h
+ db 0feh,0d4h,01bh,076h
+ db 089h,0d3h,02bh,0e0h
+ db 010h,0dah,07ah,05ah
+ db 067h,0ddh,04ah,0cch
+ db 0f9h,0b9h,0dfh,06fh
+ db 08eh,0beh,0efh,0f9h
+ db 017h,0b7h,0beh,043h
+ db 060h,0b0h,08eh,0d5h
+ db 0d6h,0d6h,0a3h,0e8h
+ db 0a1h,0d1h,093h,07eh
+ db 038h,0d8h,0c2h,0c4h
+ db 04fh,0dfh,0f2h,052h
+ db 0d1h,0bbh,067h,0f1h
+ db 0a6h,0bch,057h,067h
+ db 03fh,0b5h,006h,0ddh
+ db 048h,0b2h,036h,04bh
+ db 0d8h,00dh,02bh,0dah
+ db 0afh,00ah,01bh,04ch
+ db 036h,003h,04ah,0f6h
+ db 041h,004h,07ah,060h
+ db 0dfh,060h,0efh,0c3h
+ db 0a8h,067h,0dfh,055h
+ db 031h,06eh,08eh,0efh
+ db 046h,069h,0beh,079h
+ db 0cbh,061h,0b3h,08ch
+ db 0bch,066h,083h,01ah
+ db 025h,06fh,0d2h,0a0h
+ db 052h,068h,0e2h,036h
+ db 0cch,00ch,077h,095h
+ db 0bbh,00bh,047h,003h
+ db 022h,002h,016h,0b9h
+ db 055h,005h,026h,02fh
+ db 0c5h,0bah,03bh,0beh
+ db 0b2h,0bdh,00bh,028h
+ db 02bh,0b4h,05ah,092h
+ db 05ch,0b3h,06ah,004h
+ db 0c2h,0d7h,0ffh,0a7h
+ db 0b5h,0d0h,0cfh,031h
+ db 02ch,0d9h,09eh,08bh
+ db 05bh,0deh,0aeh,01dh
+ db 09bh,064h,0c2h,0b0h
+ db 0ech,063h,0f2h,026h
+ db 075h,06ah,0a3h,09ch
+ db 002h,06dh,093h,00ah
+ db 09ch,009h,006h,0a9h
+ db 0ebh,00eh,036h,03fh
+ db 072h,007h,067h,085h
+ db 005h,000h,057h,013h
+ db 095h,0bfh,04ah,082h
+ db 0e2h,0b8h,07ah,014h
+ db 07bh,0b1h,02bh,0aeh
+ db 00ch,0b6h,01bh,038h
+ db 092h,0d2h,08eh,09bh
+ db 0e5h,0d5h,0beh,00dh
+ db 07ch,0dch,0efh,0b7h
+ db 00bh,0dbh,0dfh,021h
+ db 086h,0d3h,0d2h,0d4h
+ db 0f1h,0d4h,0e2h,042h
+ db 068h,0ddh,0b3h,0f8h
+ db 01fh,0dah,083h,06eh
+ db 081h,0beh,016h,0cdh
+ db 0f6h,0b9h,026h,05bh
+ db 06fh,0b0h,077h,0e1h
+ db 018h,0b7h,047h,077h
+ db 088h,008h,05ah,0e6h
+ db 0ffh,00fh,06ah,070h
+ db 066h,006h,03bh,0cah
+ db 011h,001h,00bh,05ch
+ db 08fh,065h,09eh,0ffh
+ db 0f8h,062h,0aeh,069h
+ db 061h,06bh,0ffh,0d3h
+ db 016h,06ch,0cfh,045h
+ db 0a0h,00ah,0e2h,078h
+ db 0d7h,00dh,0d2h,0eeh
+ db 04eh,004h,083h,054h
+ db 039h,003h,0b3h,0c2h
+ db 0a7h,067h,026h,061h
+ db 0d0h,060h,016h,0f7h
+ db 049h,069h,047h,04dh
+ db 03eh,06eh,077h,0dbh
+ db 0aeh,0d1h,06ah,04ah
+ db 0d9h,0d6h,05ah,0dch
+ db 040h,0dfh,00bh,066h
+ db 037h,0d8h,03bh,0f0h
+ db 0a9h,0bch,0aeh,053h
+ db 0deh,0bbh,09eh,0c5h
+ db 047h,0b2h,0cfh,07fh
+ db 030h,0b5h,0ffh,0e9h
+ db 0bdh,0bdh,0f2h,01ch
+ db 0cah,0bah,0c2h,08ah
+ db 053h,0b3h,093h,030h
+ db 024h,0b4h,0a3h,0a6h
+ db 0bah,0d0h,036h,005h
+ db 0cdh,0d7h,006h,093h
+ db 054h,0deh,057h,029h
+ db 023h,0d9h,067h,0bfh
+ db 0b3h,066h,07ah,02eh
+ db 0c4h,061h,04ah,0b8h
+ db 05dh,068h,01bh,002h
+ db 02ah,06fh,02bh,094h
+ db 0b4h,00bh,0beh,037h
+ db 0c3h,00ch,08eh,0a1h
+ db 05ah,005h,0dfh,01bh
+ db 02dh,002h,0efh,08dh
+
+ end
+
\ No newline at end of file
diff --git a/devices/pc8080/rom/test/8080EXER.json b/devices/pc8080/rom/test/8080EXER.json
new file mode 100644
index 000000000..e29308c6c
--- /dev/null
+++ b/devices/pc8080/rom/test/8080EXER.json
@@ -0,0 +1,290 @@
+{"bytes":[
+195,19,1,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,42,6,0,249,17,246,13,14,9,205,234,13,33,
+58,1,126,35,182,202,47,1,43,205,206,10,195,34,1,17,
+19,14,14,9,205,234,13,195,0,0,110,1,206,1,46,2,
+142,2,238,2,78,3,174,3,14,4,110,4,206,4,46,5,
+142,5,238,5,78,6,174,6,14,7,110,7,206,7,46,8,
+142,8,238,8,78,9,174,9,14,10,110,10,0,0,255,9,
+0,0,0,165,196,199,196,38,210,80,160,234,88,102,133,198,
+222,201,155,48,0,0,0,0,0,0,0,0,0,33,248,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,255,255,255,255,255,255,215,0,255,255,0,0,0,0,100,
+97,100,32,60,98,44,100,44,104,44,115,112,62,46,46,46,
+46,46,46,46,46,46,46,46,46,46,46,46,46,36,255,198,
+0,0,0,64,145,60,126,103,122,109,223,97,91,41,11,16,
+102,178,133,56,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,255,0,0,0,255,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,215,0,0,0,0,0,0,0,97,
+108,117,111,112,32,110,110,46,46,46,46,46,46,46,46,46,
+46,46,46,46,46,46,46,46,46,46,46,46,46,36,255,128,
+0,0,0,62,197,58,87,77,76,3,1,9,227,102,166,208,
+59,187,173,63,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,255,0,0,0,0,0,0,255,0,0,0,0,
+0,0,0,255,255,255,255,215,0,0,0,0,0,0,0,97,
+108,117,111,112,32,60,98,44,99,44,100,44,101,44,104,44,
+108,44,109,44,97,62,46,46,46,46,46,46,46,36,255,39,
+0,0,0,65,33,250,9,96,29,89,165,91,141,121,144,4,
+142,157,41,24,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,215,255,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,60,
+100,97,97,44,99,109,97,44,115,116,99,44,99,109,99,62,
+46,46,46,46,46,46,46,46,46,46,46,46,46,36,255,60,
+0,0,0,223,74,216,213,152,229,43,138,176,167,27,67,68,
+90,48,208,1,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,215,0,0,0,0,0,0,0,60,
+105,110,114,44,100,99,114,62,32,97,46,46,46,46,46,46,
+46,46,46,46,46,46,46,46,46,46,46,46,46,36,255,4,
+0,0,0,35,214,45,67,97,122,128,129,134,90,133,30,134,
+88,187,155,1,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,215,0,0,0,0,0,0,0,60,
+105,110,114,44,100,99,114,62,32,98,46,46,46,46,46,46,
+46,46,46,46,46,46,46,46,46,46,46,46,46,36,255,3,
+0,0,0,151,205,171,68,201,141,227,227,204,17,164,232,2,
+73,77,42,8,0,0,0,0,0,0,0,0,0,0,0,0,
+0,33,248,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,215,0,0,0,0,0,0,0,60,
+105,110,120,44,100,99,120,62,32,98,46,46,46,46,46,46,
+46,46,46,46,46,46,46,46,46,46,46,46,46,36,255,12,
+0,0,0,137,215,53,9,91,5,133,159,39,139,8,210,149,
+5,96,6,1,0,0,0,0,0,0,0,0,0,0,0,0,
+0,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,215,0,0,0,0,0,0,0,60,
+105,110,114,44,100,99,114,62,32,99,46,46,46,46,46,46,
+46,46,46,46,46,46,46,46,46,46,46,46,46,36,255,20,
+0,0,0,234,160,186,95,251,101,28,152,204,56,188,222,67,
+92,189,3,1,0,0,0,0,0,0,0,0,0,0,0,0,
+255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,215,0,0,0,0,0,0,0,60,
+105,110,114,44,100,99,114,62,32,100,46,46,46,46,46,46,
+46,46,46,46,46,46,46,46,46,46,46,46,46,36,255,19,
+0,0,0,46,52,29,19,201,40,202,10,103,153,46,58,146,
+246,84,157,8,0,0,0,0,0,0,0,0,0,0,0,33,
+248,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,215,0,0,0,0,0,0,0,60,
+105,110,120,44,100,99,120,62,32,100,46,46,46,46,46,46,
+46,46,46,46,46,46,46,46,46,46,46,46,46,36,255,28,
+0,0,0,47,96,13,76,2,36,245,226,244,160,10,161,19,
+50,37,89,1,0,0,0,0,0,0,0,0,0,0,0,255,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,215,0,0,0,0,0,0,0,60,
+105,110,114,44,100,99,114,62,32,101,46,46,46,46,46,46,
+46,46,46,46,46,46,46,46,46,46,46,46,46,36,255,36,
+0,0,0,6,21,235,242,221,232,43,38,166,17,26,188,23,
+6,24,40,1,0,0,0,0,0,0,0,0,0,0,255,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,215,0,0,0,0,0,0,0,60,
+105,110,114,44,100,99,114,62,32,104,46,46,46,46,46,46,
+46,46,46,46,46,46,46,46,46,46,46,46,46,36,255,35,
+0,0,0,244,195,165,7,109,27,4,79,194,226,42,130,87,
+224,225,195,8,0,0,0,0,0,0,0,0,0,33,248,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,215,0,0,0,0,0,0,0,60,
+105,110,120,44,100,99,120,62,32,104,46,46,46,46,46,46,
+46,46,46,46,46,46,46,46,46,46,46,46,46,36,255,44,
+0,0,0,49,128,32,165,86,67,9,180,193,244,162,223,209,
+60,162,62,1,0,0,0,0,0,0,0,0,0,255,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,215,0,0,0,0,0,0,0,60,
+105,110,114,44,100,99,114,62,32,108,46,46,46,46,46,46,
+46,46,46,46,46,46,46,46,46,46,46,46,46,36,255,52,
+0,0,0,86,184,124,12,62,229,3,1,126,135,88,218,21,
+92,55,31,1,0,0,0,255,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,215,0,0,0,0,0,0,0,60,
+105,110,114,44,100,99,114,62,32,109,46,46,46,46,46,46,
+46,46,46,46,46,46,46,46,46,46,46,46,46,36,255,51,
+0,0,0,111,52,130,212,105,209,182,222,148,164,118,244,83,
+2,91,133,8,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,33,248,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,215,0,0,0,0,0,0,0,60,
+105,110,120,44,100,99,120,62,32,115,112,46,46,46,46,46,
+46,46,46,46,46,46,46,46,46,46,46,46,46,36,255,42,
+3,1,0,99,152,48,120,119,32,254,177,250,185,184,171,4,
+6,21,96,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,255,255,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,108,
+104,108,100,32,110,110,110,110,46,46,46,46,46,46,46,46,
+46,46,46,46,46,46,46,46,46,46,46,46,46,36,255,34,
+3,1,0,3,208,114,119,83,127,114,63,234,100,128,225,16,
+45,233,53,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,255,255,0,0,0,0,0,0,0,0,0,0,0,0,115,
+104,108,100,32,110,110,110,110,46,46,46,46,46,46,46,46,
+46,46,46,46,46,46,46,46,46,46,46,46,46,36,255,1,
+0,0,0,28,92,70,45,185,142,120,96,177,116,14,179,70,
+209,204,48,48,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,255,255,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,108,
+120,105,32,60,98,44,100,44,104,44,115,112,62,44,110,110,
+110,110,46,46,46,46,46,46,46,46,46,46,46,36,255,10,
+0,0,0,168,179,42,29,142,127,172,66,3,1,3,1,198,
+177,142,239,16,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,
+0,0,0,0,0,0,0,215,255,0,0,0,0,0,0,108,
+100,97,120,32,60,98,44,100,62,46,46,46,46,46,46,46,
+46,46,46,46,46,46,46,46,46,46,46,46,46,36,255,6,
+0,0,0,7,196,157,244,61,209,57,3,137,222,85,116,83,
+192,9,85,56,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,109,
+118,105,32,60,98,44,99,44,100,44,101,44,104,44,108,44,
+109,44,97,62,44,110,110,46,46,46,46,46,46,36,255,64,
+0,0,0,164,114,36,160,172,97,3,1,199,130,143,113,151,
+143,142,239,63,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,
+0,0,0,255,255,255,255,215,255,0,0,0,0,0,0,109,
+111,118,32,60,98,99,100,101,104,108,97,62,44,60,98,99,
+100,101,104,108,97,62,46,46,46,46,46,46,46,36,255,50,
+3,1,0,104,253,236,244,160,68,67,181,83,6,186,205,210,
+79,216,31,8,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,
+0,0,0,0,0,0,0,215,255,0,0,0,0,0,0,115,
+116,97,32,110,110,110,110,32,47,32,108,100,97,32,110,110,
+110,110,46,46,46,46,46,46,46,46,46,46,46,36,255,7,
+0,0,0,146,203,67,109,144,10,132,194,83,12,14,245,145,
+235,252,64,24,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,255,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,215,0,0,0,0,0,0,0,60,
+114,108,99,44,114,114,99,44,114,97,108,44,114,97,114,62,
+46,46,46,46,46,46,46,46,46,46,46,46,46,36,255,2,
+0,0,0,59,12,146,181,255,108,158,149,3,1,4,1,193,
+33,231,189,24,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,255,255,0,0,0,
+0,0,0,0,0,0,0,0,255,0,0,0,0,0,0,115,
+116,97,120,32,60,98,44,100,62,46,46,46,46,46,46,46,
+46,46,46,46,46,46,46,46,46,46,46,46,46,36,229,126,
+35,102,111,126,50,127,13,35,229,17,20,0,25,17,222,12,
+205,77,12,225,229,17,40,0,25,17,6,13,205,77,12,33,
+6,13,54,1,225,229,17,77,13,1,4,0,126,18,35,19,
+11,120,177,194,252,10,17,3,1,1,16,0,126,18,35,19,
+11,120,177,194,12,11,17,44,0,25,235,14,9,205,234,13,
+205,142,14,58,77,13,254,118,202,58,11,230,223,254,221,194,
+55,11,58,78,13,254,118,196,46,13,205,141,12,196,177,12,
+225,202,118,11,17,60,0,25,205,79,14,17,34,14,202,109,
+11,17,41,14,14,9,205,234,13,205,181,13,17,68,14,14,
+9,205,234,13,33,162,14,205,181,13,17,76,14,14,9,205,
+234,13,225,35,35,201,229,62,1,50,236,11,50,16,12,33,
+222,12,34,237,11,33,6,13,34,17,12,6,4,225,229,17,
+77,13,205,160,11,6,16,17,3,1,205,160,11,195,35,11,
+205,169,11,35,5,194,160,11,201,197,213,229,78,17,20,0,
+25,126,254,0,202,202,11,6,8,15,245,62,0,220,239,11,
+169,15,79,241,5,194,185,11,6,8,17,20,0,25,126,254,
+0,202,229,11,6,8,15,245,62,0,220,19,12,169,15,79,
+241,5,194,214,11,225,209,121,18,19,193,201,0,0,0,197,
+229,42,237,11,70,33,236,11,126,79,7,119,254,1,194,8,
+12,42,237,11,35,34,237,11,120,161,225,193,200,62,1,201,
+0,0,0,197,229,42,17,12,70,33,16,12,126,79,7,119,
+254,1,194,44,12,42,17,12,35,34,17,12,120,161,225,193,
+200,62,1,201,245,197,213,229,54,0,84,93,19,11,126,18,
+35,19,11,120,177,194,62,12,225,209,193,241,201,213,235,1,
+40,0,205,52,12,235,6,20,14,1,22,0,94,123,161,202,
+99,12,20,121,7,79,254,1,194,93,12,35,5,194,92,12,
+122,230,248,15,15,15,111,38,0,122,230,7,60,71,62,128,
+7,5,194,128,12,209,25,17,20,0,25,119,201,197,213,229,
+33,222,12,17,20,0,235,25,235,52,126,254,0,202,172,12,
+71,26,160,202,168,12,54,0,193,209,225,201,35,19,195,153,
+12,197,213,229,33,6,13,17,20,0,235,25,235,126,183,202,
+217,12,71,26,160,194,213,12,120,7,254,1,194,211,12,54,
+0,35,19,119,175,225,209,193,201,35,19,195,189,12,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,245,197,
+213,229,243,33,0,0,57,34,169,13,49,5,1,225,225,225,
+209,193,241,34,151,13,42,17,1,249,42,151,13,0,0,0,
+0,34,151,13,33,0,0,218,94,13,57,195,96,13,57,55,
+34,167,13,42,151,13,49,167,13,245,197,213,229,229,229,42,
+169,13,249,251,42,3,1,34,153,13,33,165,13,126,230,255,
+119,6,16,17,153,13,33,162,14,26,19,205,102,14,5,194,
+137,13,225,209,193,241,201,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,126,205,199,13,35,
+5,194,171,13,201,245,197,229,6,4,126,205,199,13,35,5,
+194,186,13,225,193,241,201,245,15,15,15,15,205,208,13,241,
+245,197,213,229,230,15,254,10,218,221,13,198,39,198,48,95,
+14,2,205,234,13,225,209,193,241,201,245,197,213,229,205,5,
+0,225,209,193,241,201,56,48,56,48,32,105,110,115,116,114,
+117,99,116,105,111,110,32,101,120,101,114,99,105,115,101,114,
+10,13,36,84,101,115,116,115,32,99,111,109,112,108,101,116,
+101,36,32,32,79,75,10,13,36,32,32,69,82,82,79,82,
+32,42,42,42,42,32,99,114,99,32,101,120,112,101,99,116,
+101,100,58,36,32,102,111,117,110,100,58,36,10,13,36,197,
+213,229,17,162,14,6,4,26,190,194,98,14,35,19,5,194,
+87,14,225,209,193,201,245,197,213,229,229,17,3,0,25,174,
+111,38,0,41,41,235,33,166,14,25,235,225,1,4,0,26,
+168,70,119,19,35,13,194,127,14,225,209,193,241,201,245,197,
+229,33,162,14,62,255,6,4,119,35,5,194,152,14,225,193,
+241,201,0,0,0,0,0,0,0,0,119,7,48,150,238,14,
+97,44,153,9,81,186,7,109,196,25,112,106,244,143,233,99,
+165,53,158,100,149,163,14,219,136,50,121,220,184,164,224,213,
+233,30,151,210,217,136,9,182,76,43,126,177,124,189,231,184,
+45,7,144,191,29,145,29,183,16,100,106,176,32,242,243,185,
+113,72,132,190,65,222,26,218,212,125,109,221,228,235,244,212,
+181,81,131,211,133,199,19,108,152,86,100,107,168,192,253,98,
+249,122,138,101,201,236,20,1,92,79,99,6,108,217,250,15,
+61,99,141,8,13,245,59,110,32,200,76,105,16,94,213,96,
+65,228,162,103,113,114,60,3,228,209,75,4,212,71,210,13,
+133,253,165,10,181,107,53,181,168,250,66,178,152,108,219,187,
+201,214,172,188,249,64,50,216,108,227,69,223,92,117,220,214,
+13,207,171,209,61,89,38,217,48,172,81,222,0,58,200,215,
+81,128,191,208,97,22,33,180,244,181,86,179,196,35,207,186,
+149,153,184,189,165,15,40,2,184,158,95,5,136,8,198,12,
+217,178,177,11,233,36,47,111,124,135,88,104,76,17,193,97,
+29,171,182,102,45,61,118,220,65,144,1,219,113,6,152,210,
+32,188,239,213,16,42,113,177,133,137,6,182,181,31,159,191,
+228,165,232,184,212,51,120,7,201,162,15,0,249,52,150,9,
+168,142,225,14,152,24,127,106,13,187,8,109,61,45,145,100,
+108,151,230,99,92,1,107,107,81,244,28,108,97,98,133,101,
+48,216,242,98,0,78,108,6,149,237,27,1,165,123,130,8,
+244,193,245,15,196,87,101,176,217,198,18,183,233,80,139,190,
+184,234,252,185,136,124,98,221,29,223,21,218,45,73,140,211,
+124,243,251,212,76,101,77,178,97,88,58,181,81,206,163,188,
+0,116,212,187,48,226,74,223,165,65,61,216,149,215,164,209,
+196,109,211,214,244,251,67,105,233,106,52,110,217,252,173,103,
+136,70,218,96,184,208,68,4,45,115,51,3,29,229,170,10,
+76,95,221,13,124,201,80,5,113,60,39,2,65,170,190,11,
+16,16,201,12,32,134,87,104,181,37,32,111,133,179,185,102,
+212,9,206,97,228,159,94,222,249,14,41,217,201,152,176,208,
+152,34,199,215,168,180,89,179,61,23,46,180,13,129,183,189,
+92,59,192,186,108,173,237,184,131,32,154,191,179,182,3,182,
+226,12,116,177,210,154,234,213,71,57,157,210,119,175,4,219,
+38,21,115,220,22,131,227,99,11,18,148,100,59,132,13,109,
+106,62,122,106,90,168,228,14,207,11,147,9,255,157,10,0,
+174,39,125,7,158,177,240,15,147,68,135,8,163,210,30,1,
+242,104,105,6,194,254,247,98,87,93,128,101,103,203,25,108,
+54,113,110,107,6,231,254,212,27,118,137,211,43,224,16,218,
+122,90,103,221,74,204,249,185,223,111,142,190,239,249,23,183,
+190,67,96,176,142,213,214,214,163,232,161,209,147,126,56,216,
+194,196,79,223,242,82,209,187,103,241,166,188,87,103,63,181,
+6,221,72,178,54,75,216,13,43,218,175,10,27,76,54,3,
+74,246,65,4,122,96,223,96,239,195,168,103,223,85,49,110,
+142,239,70,105,190,121,203,97,179,140,188,102,131,26,37,111,
+210,160,82,104,226,54,204,12,119,149,187,11,71,3,34,2,
+22,185,85,5,38,47,197,186,59,190,178,189,11,40,43,180,
+90,146,92,179,106,4,194,215,255,167,181,208,207,49,44,217,
+158,139,91,222,174,29,155,100,194,176,236,99,242,38,117,106,
+163,156,2,109,147,10,156,9,6,169,235,14,54,63,114,7,
+103,133,5,0,87,19,149,191,74,130,226,184,122,20,123,177,
+43,174,12,182,27,56,146,210,142,155,229,213,190,13,124,220,
+239,183,11,219,223,33,134,211,210,212,241,212,226,66,104,221,
+179,248,31,218,131,110,129,190,22,205,246,185,38,91,111,176,
+119,225,24,183,71,119,136,8,90,230,255,15,106,112,102,6,
+59,202,17,1,11,92,143,101,158,255,248,98,174,105,97,107,
+255,211,22,108,207,69,160,10,226,120,215,13,210,238,78,4,
+131,84,57,3,179,194,167,103,38,97,208,96,22,247,73,105,
+71,77,62,110,119,219,174,209,106,74,217,214,90,220,64,223,
+11,102,55,216,59,240,169,188,174,83,222,187,158,197,71,178,
+207,127,48,181,255,233,189,189,242,28,202,186,194,138,83,179,
+147,48,36,180,163,166,186,208,54,5,205,215,6,147,84,222,
+87,41,35,217,103,191,179,102,122,46,196,97,74,184,93,104,
+27,2,42,111,43,148,180,11,190,55,195,12,142,161,90,5,
+223,27,45,2,239,141,160,10,226,120,215,13,210,238,78,4,
+131,84,57,3,179,194,167,103,38,97,208,96,22,247,73,105,
+71,77,62,110,119,219,174,209,106,74,217,214,90,220,64,223,
+11,102,55,216,59,240,169,188,174,83,222,187,158,197,71,178,
+207,127,48,181,255,233,189,189,242,28,202,186,194,138,83,179,
+147,48,36,180,163,166,186,208,54,5,205,215,6,147,84,222]
+}
\ No newline at end of file
diff --git a/devices/pc8080/rom/test/8080PRE.MAC b/devices/pc8080/rom/test/8080PRE.MAC
new file mode 100644
index 000000000..147dfe8ae
--- /dev/null
+++ b/devices/pc8080/rom/test/8080PRE.MAC
@@ -0,0 +1,291 @@
+ title 'Preliminary Z80 tests'
+
+; prelim.z80 - Preliminary Z80 tests
+; Copyright (C) 1994 Frank D. Cringle
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation; either version 2
+; of the License, or (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, write to the Free Software
+; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+; These tests have two goals. To start with, we assume the worst and
+; successively test the instructions needed to continue testing.
+; Then we try to test all instructions which cannot be handled by
+; zexlax - the crc-based instruction exerciser.
+
+; Initially errors are 'reported' by jumping to 0. This should reboot
+; cp/m, so if the program terminates without any output one of the
+; early tests failed. Later errors are reported by outputting an
+; address via the bdos conout routine. The address can be located in
+; a listing of this program.
+
+; If the program runs to completion it displays a suitable message.
+
+;******************************************************************************
+;
+; Modified by Ian Bartholomew to run a preliminary test on an 8080 CPU
+;
+; Assemble using M80
+;
+;******************************************************************************
+
+ .8080
+ aseg
+ org 100h
+
+start: mvi a,1 ; test simple compares and z/nz jumps
+ cpi 2
+ jz 0
+ cpi 1
+ jnz 0
+ jmp lab0
+ hlt ; emergency exit
+ db 0ffh
+
+lab0: call lab2 ; does a simple call work?
+lab1: jmp 0 ; fail
+
+lab2: pop h ; check return address
+ mov a,h
+ cpi high lab1
+ jz lab3
+ jmp 0
+lab3: mov a,l
+ cpi low lab1
+ jz lab4
+ jmp 0
+
+; test presence and uniqueness of all machine registers
+; (except ir)
+lab4: lxi sp,regs1
+ pop psw
+ pop b
+ pop d
+ pop h
+ lxi sp,regs2+8
+ push h
+ push d
+ push b
+ push psw
+
+v defl 0
+ rept 8
+ lda regs2+v/2
+v defl v+2
+ cpi v
+ jnz 0
+ endm
+
+; test access to memory via (hl)
+ lxi h,hlval
+ mov a,m
+ cpi 0a5h
+ jnz 0
+ lxi h,hlval+1
+ mov a,m
+ cpi 03ch
+ jnz 0
+
+; test unconditional return
+ lxi sp,stack
+ lxi h,reta
+ push h
+ ret
+ jmp 0
+
+; test instructions needed for hex output
+reta: mvi a,0ffh
+ ani 0fh
+ cpi 0fh
+ jnz 0
+ mvi a,05ah
+ ani 0fh
+ cpi 0ah
+ jnz 0
+ rrc
+ cpi 05h
+ jnz 0
+ rrc
+ cpi 82h
+ jnz 0
+ rrc
+ cpi 41h
+ jnz 0
+ rrc
+ cpi 0a0h
+ jnz 0
+ lxi h,01234h
+ push h
+ pop b
+ mov a,b
+ cpi 12h
+ jnz 0
+ mov a,c
+ cpi 34h
+ jnz 0
+
+; from now on we can report errors by displaying an address
+
+; test conditional call, ret, jp, jr
+tcond macro flag,pcond,ncond,rel
+ lxi h,&flag
+ push h
+ pop psw
+ c&pcond lab1&pcond
+ jmp error
+lab1&pcond: pop h
+ lxi h,0d7h xor &flag
+ push h
+ pop psw
+ c&ncond lab2&pcond
+ jmp error
+lab2&pcond: pop h
+ lxi h,lab3&pcond
+ push h
+ lxi h,&flag
+ push h
+ pop psw
+ r&pcond
+ call error
+lab3&pcond: lxi h,lab4&pcond
+ push h
+ lxi h,0d7h xor &flag
+ push h
+ pop psw
+ r&ncond
+ call error
+lab4&pcond: lxi h,&flag
+ push h
+ pop psw
+ j&pcond lab5&pcond
+ call error
+lab5&pcond: lxi h,0d7h xor &flag
+ push h
+ pop psw
+ j&ncond lab6&pcond
+ call error
+lab6&pcond:
+ endm
+
+ tcond 1,c,nc,1
+ tcond 4,pe,po,0
+ tcond 040h,z,nz,1
+ tcond 080h,m,p,0
+
+; test indirect jumps
+ lxi h,lab7
+ pchl
+ call error
+
+; djnz (and (partially) inc a, inc hl)
+lab7: mvi a,0a5h
+ mvi b,4
+lab8: rrc
+ dcr b
+ jnz lab8
+ cpi 05ah
+ cnz error
+ mvi b,16
+lab9: inr a
+ dcr b
+ jnz lab9
+ cpi 06ah
+ cnz error
+ mvi b,0
+ lxi h,0
+lab10: inx h
+ dcr b
+ jnz lab10
+ mov a,h
+ cpi 1
+ cnz error
+ mov a,l
+ cpi 0
+ cnz error
+
+allok: lxi d,okmsg
+ mvi c,9
+ call 5
+ jmp 0
+
+okmsg: db '8080 Preliminary tests complete$'
+
+; display address at top of stack and exit
+error: pop b
+ mvi h,high hextab
+ mov a,b
+ rrc
+ rrc
+ rrc
+ rrc
+ ani 15
+ mov l,a
+ mov a,m
+ call conout
+ mov a,b
+ ani 15
+ mov l,a
+ mov a,m
+ call conout
+ mov a,c
+ rrc
+ rrc
+ rrc
+ rrc
+ ani 15
+ mov l,a
+ mov a,m
+ call conout
+ mov a,c
+ ani 15
+ mov l,a
+ mov a,m
+ call conout
+ mvi a,13
+ call conout
+ mvi a,10
+ call conout
+ jmp 0
+
+conout: push psw
+ push b
+ push d
+ push h
+ mvi c,2
+ mov e,a
+ call 5
+ pop h
+ pop d
+ pop b
+ pop psw
+ ret
+
+v defl 0
+regs1: rept 8
+v defl v+2
+ db v
+ endm
+
+regs2: ds 8,0
+
+hlval: db 0a5h,03ch
+
+; skip to next page boundary
+ org (($+255)/256)*256
+hextab: db '0123456789abcdef'
+ ds 240
+
+stack equ $
+
+ end start
+
\ No newline at end of file
diff --git a/modules/pc8080/lib/cpuops.js b/modules/pc8080/lib/cpuops.js
index 5a4304610..ed0906baa 100644
--- a/modules/pc8080/lib/cpuops.js
+++ b/modules/pc8080/lib/cpuops.js
@@ -628,7 +628,7 @@ CPUDef.opSTC = function()
CPUDef.opDADSP = function()
{
var w;
- this.setSP(w = this.getHL() + this.getSP());
+ this.setHL(w = this.getHL() + this.getSP());
this.resultZeroCarry = (this.resultZeroCarry & 0xff) | ((w >> 8) & 0x100);
this.nStepCycles -= 10;
};
diff --git a/modules/pc8080/lib/debugger.js b/modules/pc8080/lib/debugger.js
index 58214740e..6fd62ea4f 100644
--- a/modules/pc8080/lib/debugger.js
+++ b/modules/pc8080/lib/debugger.js
@@ -3707,6 +3707,7 @@ if (DEBUGGER) {
sMsg = "halting";
this.stopCPU();
} else {
+ if (this.isBusy(true)) return;
sMsg = "already halted";
}
if (!fQuiet) this.println(sMsg);
diff --git a/modules/pc8080/lib/rom.js b/modules/pc8080/lib/rom.js
index ec231a43c..6ac3e4a2d 100644
--- a/modules/pc8080/lib/rom.js
+++ b/modules/pc8080/lib/rom.js
@@ -115,7 +115,29 @@ function ROM(parmsROM)
Component.subclass(ROM);
-ROM.CPM_VECTORS = [0x0000, 0x0005];
+ROM.CPM = {
+ BIOS: {
+ VECTOR: 0x0000
+ },
+ BDOS: {
+ VECTOR: 0x0005,
+ FUNC: { // function number (specified in regC)
+ RESET: 0x00,
+ CON_READ: 0x01, // output: A = L = ASCII character
+ CON_WRITE: 0x02, // input: E = ASCII character
+ AUX_READ: 0x03, // output: A = L = ASCII character
+ AUX_WRITE: 0x04, // input: E = ASCII character
+ PRN_WRITE: 0x05, // input: E = ASCII character
+ MEM_SIZE: 0x06, // output: base address of CCP (Console Command Processor), but which register? (perhaps moot if this was CP/M 1.3 only...)
+ CON_IO: 0x06, // input: E = ASCII character (or 0xFF to return ASCII character in A)
+ GET_IOBYTE: 0x07,
+ SET_IOBYTE: 0x08,
+ STR_WRITE: 0x09 // input: DE = address of string
+ }
+ }
+};
+
+ROM.CPM.VECTORS = [ROM.CPM.BIOS.VECTOR, ROM.CPM.BDOS.VECTOR];
/*
* NOTE: There's currently no need for this component to have a reset() function, since
@@ -344,12 +366,14 @@ ROM.prototype.addROM = function(addr)
* (namely, 0x0000, which is the CP/M reset vector, and 0x0005, which is the CP/M system call vector) and
* then telling the CPU to call us whenever a HLT occurs, so we can check PC for one of these addresses.
*/
- for (i = 0; i < ROM.CPM_VECTORS.length; i++) {
- this.bus.setByteDirect(ROM.CPM_VECTORS[i], CPUDef.OPCODE.HLT);
+ for (i = 0; i < ROM.CPM.VECTORS.length; i++) {
+ this.bus.setByteDirect(ROM.CPM.VECTORS[i], CPUDef.OPCODE.HLT);
}
this.cpu.addHaltCheck(function(rom) {
- return function(addr) {rom.checkCPMVector(addr)};
+ return function(addr) {
+ return rom.checkCPMVector(addr)
+ };
}(this));
this.cpu.setReset(addr);
@@ -371,18 +395,88 @@ ROM.prototype.addROM = function(addr)
*/
ROM.prototype.checkCPMVector = function(addr)
{
- var i = ROM.CPM_VECTORS.indexOf(addr);
+ var i = ROM.CPM.VECTORS.indexOf(addr);
if (i >= 0) {
- if (this.dbg) {
- this.println("CP/M vector " + str.toHexWord(addr));
- this.cpu.setPC(addr); // this is purely for the Debugger's benefit, to show the HLT
- this.dbg.stopCPU();
+ var fCPM = false;
+ var cpu = this.cpu;
+ var dbg = this.dbg;
+ if (addr == ROM.CPM.BDOS.VECTOR) {
+ fCPM = true;
+ switch(cpu.regC) {
+ case ROM.CPM.BDOS.FUNC.CON_WRITE:
+ this.writeCPMString(this.getCPMChar(cpu.regE));
+ break;
+ case ROM.CPM.BDOS.FUNC.STR_WRITE:
+ this.writeCPMString(this.getCPMString(cpu.getDE(), '$'));
+ break;
+ default:
+ fCPM = false;
+ break;
+ }
+ }
+ if (fCPM) {
+ CPUDef.opRET.call(cpu); // for recognized calls, automatically return
+ }
+ else if (dbg) {
+ this.println("\nCP/M vector " + str.toHexWord(addr));
+ cpu.setPC(addr); // this is purely for the Debugger's benefit, to show the HLT
+ dbg.stopCPU();
}
return true;
}
return false;
};
+
+/**
+ * getCPMChar(ch)
+ *
+ * @this {ROM}
+ * @param {number} ch
+ * @return {string}
+ */
+ROM.prototype.getCPMChar = function(ch)
+{
+ return String.fromCharCode(ch);
+};
+
+/**
+ * getCPMString(addr, chEnd)
+ *
+ * @this {ROM}
+ * @param {number} addr (of a string)
+ * @param {string|number} [chEnd] (terminating character, default is 0)
+ * @return {string}
+ */
+ROM.prototype.getCPMString = function(addr, chEnd)
+{
+ var s = "";
+ var cchMax = 255;
+ var bEnd = chEnd && chEnd.length && chEnd.charCodeAt(0) || chEnd || 0;
+ while (cchMax--) {
+ var b = this.cpu.getByte(addr++);
+ if (b == bEnd) break;
+ s += String.fromCharCode(b);
+ }
+ return s;
+};
+
+/**
+ * writeCPMString(s)
+ *
+ * @this {ROM}
+ * @param {string} s
+ */
+ROM.prototype.writeCPMString = function(s)
+{
+ s = s.replace(/\r/g, '');
+ if (this.controlPrint) {
+ this.controlPrint.value += s;
+ this.controlPrint.scrollTop = this.controlPrint.scrollHeight;
+ }
+ this.log(s);
+};
+
/**
* cloneROM(addr)
*
diff --git a/modules/pcjs/lib/debugger.js b/modules/pcjs/lib/debugger.js
index 061401127..90496c286 100644
--- a/modules/pcjs/lib/debugger.js
+++ b/modules/pcjs/lib/debugger.js
@@ -6663,6 +6663,7 @@ if (DEBUGGER) {
sMsg = "halting";
this.stopCPU();
} else {
+ if (this.isBusy(true)) return;
sMsg = "already halted";
}
if (!fQuiet) this.println(sMsg);