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);