************************************************************************* * * * This file contains the special Z-80 simulation routines and * * the Morrow HDC/DMA support routines. * * * ************************************************************************* globl preED,outspec xdef mloop,illegl return equ @16,r ; JMP (return) is fast return to MLOOP. pseudopc equ @15,r ; 8080's PC is register A5. opptr equ @14,r ; Pointer to opcode dispatch table. pseudosp equ @13,r ; 8080's SP is register A3. flagptr equ @12,r ; Pointer to 8080's flag lookup table is A2. targbase equ @11,r ; Pointer to 8080's address space is A1. regs equ @11,r ; Base pointer to 8080's registers is A1. regcon0e equ 7,r ; Register based constant #$E (for speed). regcon01 equ 6,r ; Register based constant #$1. regcon0f equ 5,r ; Register based constant #$F. regcondd equ 4,r ; Register based constant #$FF. regf equ 3,r ; 8080's Flags rega equ 2,r ; 8080's Accumulator regb equ -8 ; Offsets from register base pointer for regc equ -7 ; 8080's pseudo-registers. regd equ -6 ; A & F are in Data Registers. rege equ -5 ; Pseudo-PC is kept in an Address Register. regh equ -4 regl equ -3 regop1 equ -2 ; Operand 1 for DAA storage regop2 equ -1 ; " 2 " " " data page ************************************************************************* * * * Opcode dispatch table. One longword entry per opcode of the * * target (Z-80) processor, including illegals. * * * ************************************************************************* * * * Only a few of the most popular instructions are simulated. * * Support for the Z-80 Block move instructions is provided * * as the flags for this simulation resemble those of the Z-80 * * rather than the 8080. Certain packages (notably BDS-C) check * * the flags and mistakenly assume a Z-80, then use LDIR/LDDR. * * Therefore, minimal Z-80 support is provided for these * * instructions. By no means is this a complete simulation * * of the Z-80. * * * ************************************************************************* even EDoptab dc.l 0,0,0,0,0,0,0,0 ; ED00 dc.l 0,0,0,0,0,0,0,0 dc.l 0,0,0,0,0,0,0,0 ; ED10 dc.l 0,0,0,0,0,0,0,0 dc.l 0,0,0,0,0,0,0,0 ; ED20 dc.l 0,0,0,0,0,0,0,0 dc.l 0,0,0,0,0,0,0,0 ; ED30 dc.l 0,0,0,0,0,0,0,0 dc.l 0,0,0,0,0,0,0,0 ; ED40 dc.l 0,0,0,0,0,0,0,0 dc.l 0,0,0,0,0,0,0,0 ; ED50 dc.l 0,0,0,0,0,0,0,0 dc.l 0,0,0,0,0,0,0,0 ; ED60 dc.l 0,0,0,0,0,0,0,0 dc.l 0,0,0,0,0,0,0,0 ; ED70 dc.l 0,0,0,0,0,0,0,0 dc.l 0,0,0,0,0,0,0,0 ; ED80 dc.l 0,0,0,0,0,0,0,0 dc.l 0,0,0,0,0,0,0,0 ; ED90 dc.l 0,0,0,0,0,0,0,0 dc.l 0,0,0,0,0,0,0,0 ; EDA0 dc.l 0,0,0,0,0,0,0,0 dc.l ldir,cpir,0,0,0,0,0,0 ; EDB0 dc.l lddr,0,0,0,0,0,0,0 dc.l 0,0,0,0,0,0,0,0 ; EDC0 dc.l 0,0,0,0,0,0,0,0 dc.l 0,0,0,0,0,0,0,0 ; EDD0 dc.l 0,0,0,0,0,0,0,0 dc.l 0,0,0,0,0,0,0,0 ; EDE0 dc.l 0,0,0,0,0,0,0,0 dc.l 0,0,0,0,0,0,0,0 ; EDF0 dc.l 0,0,0,0,0,0,0,0 page text preED moveq #0,d1 ; Zero-fill high bits. move.b (pseudopc)+,d1 ; Grab next opcode. asl #2,d1 lea.l EDoptab,a0 move.l 0(a0,d1.w),-(sp) ; Do the operation. beq illgED rts illgED move.l (sp)+,d1 ; Trash the address, dec.l pseudopc ; fix PPC for ILLEGAL. bra illegl page ************************************************************************* * * * Z-80 opcode simulation routines. * * * ************************************************************************* ldir move.l d2,-(sp) move.w regb(regs),d0 ; Grab count, dec.w d0 ; adjust for DBRA later. moveq #0,d1 moveq #0,d2 move.w regh(regs),d1 ; Grab source. move.w regd(regs),d2 ; Grab dest. move.l a5,-(sp) ; Need an address reg. lea.l 0(targbase,d2.l),a5 lea.l 0(targbase,d1.l),a0 ldirlop move.b (a0)+,(a5)+ inc.w d1 inc.w d2 dbra d0,ldirlop move.l (sp)+,a5 move.w d1,regh(regs) ; Restore result registers. move.w d2,regd(regs) move.w #0,regb(regs) moveq #0,regf move.l (sp)+,d2 jmp (return) lddr move.l d2,-(sp) move.w regb(regs),d0 ; Grab count, dec.w d0 ; adjust for DBRA later. moveq #0,d1 moveq #0,d2 move.w regh(regs),d1 ; Grab source. move.w regd(regs),d2 ; Grab dest. move.l a5,-(sp) ; Need an address reg. lea.l 1(targbase,d2.l),a5 lea.l 1(targbase,d1.l),a0 lddrlop move.b -(a0),-(a5) dec.w d1 dec.w d2 dbra d0,lddrlop move.l (sp)+,a5 move.w d1,regh(regs) ; Restore result registers. move.w d2,regd(regs) move.w #0,regb(regs) moveq #0,regf move.l (sp)+,d2 jmp (return) page cpir move.w regb(regs),d0 ; Grab count, dec.w d0 ; adjust for DBRA later. moveq #0,d1 move.w regh(regs),d1 ; Grab source. lea.l 0(targbase,d1.l),a0 cpirlop inc.w d1 cmp.b (a0)+,rega dbeq d0,cpirlop seq regf move.w d1,regh(regs) ; Restore result registers. inc.w d0 move.w d0,regb(regs) tst.b regf bne cpir1 moveq #0,regf ; Not found. jmp (return) cpir1 tst d0 beq cpir2 moveq #$44,regf ; Found, in the string. jmp (return) cpir2 moveq #$40,regf ; Found, but at last place. jmp (return) page ************************************************************************* * * * Output instruction simulator for Morrow HDDMA * * * ************************************************************************* outspec move.l d3,-(sp) cmp.b #$55,d0 beq hdstart ; Start command? Do it, move.l #hdbuf,d1 ; else build first link to host buffer move.l #$50,a0 ; if it's a HDRESET command. move.b d1,(a0)+ ror.l #8,d1 move.b d1,(a0)+ ror.l #8,d1 move.b d1,(a0)+ move.l #$ff0000,a0 ; Do the output to HDDMA. adda.l d0,a0 move.b rega,(a0) move.l (sp)+,d3 jmp (return) hdstart move.l dmalink,a0 ; Move target buffer to host buffer, do adda.l targbase,a0 ; all appropriate patching of addresses. moveq #0,d1 move.b (a0)+,d1 ; Get link address. ror.l #8,d1 move.b (a0)+,d1 ror.l #8,d1 move.b (a0)+,d1 rol.l #8,d1 rol.l #8,d1 move.l d1,a0 adda.l targbase,a0 move.l a6,-(sp) lea.l hdbuf,a6 move.w #3,d1 hdloop move.b (a0)+,(a6)+ dbra d1,hdloop moveq #0,d3 ; Fix DMA address to -> target area. move.b (a0)+,d3 ror.l #8,d3 move.b (a0)+,d3 ror.l #8,d3 move.b (a0)+,d3 rol.l #8,d3 rol.l #8,d3 add.l targbase,d3 move.b d3,(a6)+ ror.l #8,d3 move.b d3,(a6)+ ror.l #8,d3 move.b d3,(a6)+ move.w #5,d1 ; Move rest of command buffer. hdloop2 move.b (a0)+,(a6)+ dbra d1,hdloop2 move.l #hdbuf,d1 move.b d1,(a6)+ ; Point host buffer to self. ror.l #8,d1 move.b d1,(a6)+ ror.l #8,d1 move.b d1,(a6)+ move.l (sp)+,a6 move.l a0,-(sp) ; Save STATUS address for return val. suba.l targbase,a0 move.l a0,dmalink ; Stash new target link address. move.l #$ff0000,a0 ; Do the output to HDDMA. adda.l d0,a0 move.b rega,(a0) move.l #hdbuf+12,a0 ; Wait for completion hdloop3 tst.b (a0) beq hdloop3 ; Fragile, but what do you want for $1.00? move.b (a0),d1 move.l (sp)+,a0 ; Grab the STATUS address in target space. move.b d1,-(a0) ; And stash status for it. move.l (sp)+,d3 jmp (return) ; Return to simulation. data even dmalink dc.l $50 ; Storage for current HDDMA command buffer. hdbuf ds.b 16 end