Well, I wrote a program that should allow you to test any sequence of ALU operations you want, if someone wants to figure out how to assemble, burn and test it (don't forget the screwy bit order the '7720 needs for its program ROM) The command protocol is heavily based on the DSP-1, including the need to input a dummy operand for no-operand commands. It doesn't use serial I/O, DMA, or anything else fancy. It also doesn't use the data ROM at all.
Protocol:
Wait for RQM to go high, write 8 bit opcode/carry selector:
Code: Select all
000CPPPP
000 = must be zero
C = incoming carry B flag
PPPP = opcode (same order as native instruction encoding--0001 is OR, etc.)
Wait for RQM to go high, write 16-bit right-side operand (LSB first). You have to do this even for unary opcodes like the shifts (the operand value is ignored).
Wait for RQM to go high, read 16-bit result (value in accumulator A after executing opcode).
Wait for RQM to go high, read 8-bit flags as follows:
Code: Select all
11SsczVv
11 = always 1
S = SA1
s = SA0
c = CA
z = ZA
V = OVA1
v = OVA0
Accumulator A and its flags (should be) preserved between operations, i.e. you should be able to do a sequence of additions/subtractions and look at the flags after each step.
Code: Select all
: ld 0400,sr ; 8-bit
: ld 00c0,dr
; === main loop ===
loop : ld 00e0,b
: jrqm * ; wait for (8-bit) read or write (read flags or write opcode)
: mov dr,tr | and dr,b ; get opcode and carry-in
: jnzb loop
; === decode opcode ===
: ld 0000,sr ; 16-bit
: or tr,b
: jrqm * ; wait for (16-bit) write (operand)
: mov drnf,tr | shr1 b ; get operand
: jcb opxxx1
opxxx0 : shr1 b
: jcb opxx10
opxx00 : shr1 b
: jcb opx100
opx000 : shr1 b
: jncb afterop ; 0000 = nop
: jcb op1000
opx100 : shr1 b
: jncb op0100
: jcb op1100
opxx10 : shr1 b
: jcb opx110
opx010 : shr1 b
: jncb op0010
: jcb op1010
opx110 : shr1 b
: jncb op0110
: jcb op1110
opxxx1 : shr1 b
: jcb opxx11
opxx01 : shr1 b
: jcb opx101
opx001 : shr1 b
: jncb op0001
: jcb op1001
opx101 : shr1 b
: jncb op0101
: jcb op1101
opxx11 : shr1 b
: jcb opx111
opx011 : shr1 b
: jncb op0011
: jcb op1011
opx111 : shr1 b
: jncb op0111
: jcb op1111
; === execute opcode ===
op0001 : shr1 b
: or tr,a
: jmp afterop
op0010 : shr1 b
: and tr,a
: jmp afterop
op0011 : shr1 b
: xor tr,a
: jmp afterop
op0100 : shr1 b
: sub tr,a
: jmp afterop
op0101 : shr1 b
: add tr,a
: jmp afterop
op0110 : shr1 b
: sbb tr,a
: jmp afterop
op0111 : shr1 b
: adc tr,a
: jmp afterop
op1000 : shr1 b
: dec a
: jmp afterop
op1001 : shr1 b
: inc a
: jmp afterop
op1010 : shr1 b
: cmp a
: jmp afterop
op1011 : shr1 b
: shr1 a
: jmp afterop
op1100 : shr1 b
: shl1 a
: jmp afterop
op1101 : shr1 b
: shl2 a
: jmp afterop
op1110 : shr1 b
: shl4 a
: jmp afterop
op1111 : shr1 b
: xchg a
; === output result and flags ===
afterop: mov a,dr ; send result
: ld 00c0,b
: jnsa1 nosa1
: ld 0020,tr
: or tr,b
nosa1 : jnsa0 nosa0
: ld 0010,tr
: or tr,b
nosa0 : jnca noca
: ld 0008,tr
: or tr,b
noca : jnza noza
: ld 0004,tr
: or tr,b
noza : jnova1 noova1
: ld 0002,tr
: or tr,b
noova1 : jnova0 noova0
: ld 0001,tr
: or tr,b
noova0 : jrqm * ; wait for (16-bit) read (result)
: ld 0400,sr ; 8-bit
: mov b,dr ; send flags
: jmp loop ; back to the top
Someone should eyeball my code before using up rare chips, especially the rats' nest of branches that is the command decoding (also based on the DSP1 code--and there really isn't any better way to do it as far as I can tell)
I'm trying to figure out in what circumstances the " if (!flag.ov1) flag.s1 = flag.s0;" should run.
The docs say that S1 is "indeterminate" after any ALU operation other than addition/subtraction or NOP. LD and JMP instructions definitely shouldn't affect any flags at all (there's no accumulator/flag select field in those instructions, and somewhere one of the docs explicitly clarifies that loading a value into one of the accumulators via MOV or LD doesn't update its sign or zero flags)