; Z80 to 8086 Translator version 1.0 ; Runs on the Z80 under CP/M ; by Tim Paterson ; ORG 100H EOF: EQU 1AH ;End of file EOL: EQU 0DH FCB: EQU 5CH SYSTEM: EQU 5 OPEN: EQU 15 CLOSE: EQU 16 SETDMA: EQU 26 CREATE: EQU 22 DELETE: EQU 19 READ: EQU 20 WRITE: EQU 21 PRNBUF: EQU 9 LD SP,STACK LD DE,HEADER LD C,9 CALL SYSTEM LD HL,FCB+12 XOR A LD B,4 CLRFCB: LD (HL),A INC HL DJNZ CLRFCB LD (FCB+32),A LD HL,FCB LD DE,PUTFCB LD BC,16 LDIR LD (PUTFCB+32),A LD HL,'A'+3800H ;"A8" LD (PUTFCB+9),HL LD A,'6' LD (PUTFCB+11),A LD DE,FCB LD C,OPEN CALL SYSTEM INC A LD DE,NOFILE JR Z,ABORTJ LD DE,PUTFCB LD C,DELETE CALL SYSTEM LD DE,PUTFCB LD C,CREATE CALL SYSTEM INC A LD DE,NOROOM ABORTJ: JR Z,ABORT LD DE,PUTFCB LD C,OPEN CALL SYSTEM LD HL,PUTBUF LD (PUTPT),HL LD HL,GETBUF+80H LD (GETPT),HL TRANLN: XOR A LD (OP1),A LD (OP2),A LD HL,OPCODE CALL LOAD LD HL,OP1 CALL GETOP LD (HL),0 LD HL,OP2 CALL GETOP DOLIN: LD (HL),0 CALL FINDOP ENLIN: LD SP,STACK LD A,(CHAR) CP ';' JR NZ,NOCOM LD A,9 CALL PUTCH LD A,';' NOCOM: CALL PUTCH PUTLIN: CP EOF JR Z,END CALL GETCH CALL PUTCH CP 10 JR NZ,PUTLIN JR TRANLN END: LD B,127 LD A,1AH FILL: CALL PUTCH DJNZ FILL LD DE,PUTFCB LD C,CLOSE CALL SYSTEM LD DE,ENDMES ABORT: LD C,PRNBUF CALL SYSTEM JP 0 DELIM: CALL GETCH DELCHK: CP EOL JR Z,DOLIN CP EOF JR Z,DOLIN CP ';' JR Z,DOLIN CP ' ' RET Z CP ':' RET Z CP ',' RET Z CP 9 RET HEX: AND 0FH ADD A,90H DAA ADC A,40H DAA PUTCH: PUSH HL PUSH DE PUSH BC PUSH AF AND 7FH LD HL,(PUTPT) LD (HL),A INC HL LD (PUTPT),HL PUSH DE PUSH HL LD DE,PUTBUF+80H OR A SBC HL,DE POP HL POP DE JR NZ,POPRET LD DE,PUTBUF LD (PUTPT),DE LD C,SETDMA CALL SYSTEM LD DE,PUTFCB LD C,WRITE CALL SYSTEM OR A LD DE,WRTERR JR NZ,ABORT POPRET: POP AF NOTAF: POP BC POP DE POP HL RET ; ; Get character from source file. ; GETCH: PUSH HL PUSH DE PUSH BC LD HL,(GETPT) ; Get buffer pointer. PUSH DE PUSH HL LD DE,GETBUF+80H OR A SBC HL,DE ; Past end-of-buffer? POP HL POP DE JR NZ,GETIT ; Jump if not. LD DE,GETBUF ; Set `DMA address'. LD C,SETDMA CALL SYSTEM LD DE,FCB ; Read the next record from source file. LD C,READ CALL SYSTEM OR A ; Entire record read OK? LD A,EOF ; Force end-of-file character in case JR NZ,TESEND ; there is nothing in the record. LD HL,GETBUF ; Reset buffer pointer. GETIT: LD A,(HL) ; Get next character from buffer. INC HL ; Point to next character. LD (GETPT),HL ; Save new pointer. TESEND: LD (CHAR),A JR NOTAF ; Pop registers and return. LOAD: CALL DELIM JR Z,LOADOP EATLAB: CALL PUTCH CALL DELIM JR NZ,EATLAB ENLAB: LD A,':' CALL PUTCH LOADOP: LD HL,OPCODE EATEM: CALL DELIM JR Z,EATEM LOADLP: CALL IDCHK JP C,OPERR LD (HL),A INC HL CALL DELIM JR NZ,LOADLP LD (HL),0 CP ':' RET NZ LD HL,OPCODE CALL TRANS JR ENLAB GETOP: XOR A EX AF,AF' GETLP: CALL DELIM JR Z,GETLP OPCHAR: CP '(' JR NZ,NOTLEF EX AF,AF' INC A EX AF,AF' LD (HL),'[' JR NEXCH NOTLEF: CP ')' JR NZ,NOTRIT EX AF,AF' DEC A EX AF,AF' LD (HL),']' JR NEXCH NOTRIT: LD (HL),A CP '''' JR Z,EATQUO CALL IDCHK JR NC,GETID NEXCH: INC HL CALL GETCH IDRET: CALL DELCHK JR NZ,OPCHAR CP ' ' JR Z,OPCHAR RET EATQUO: INC HL CALL GETCH LD (HL),A CP ';' CALL NZ,DELCHK CP '''' JR NZ,EATQUO JR NEXCH IDCHK: CP '0' RET C CP '9'+1 CCF RET NC CP 40H RET C AND 5FH CP 'A' RET C CP 'Z'+1 CCF RET GETID: LD (HL),A LD B,1 LODID: INC HL CALL GETCH CALL IDCHK JR C,RWCHK LD (HL),A INC B JR LODID RWCHK: PUSH AF PUSH HL DEC HL DEC B LD E,B JR Z,LOOKRW LD E,(HL) DEC HL DJNZ NORW LOOKRW: LD A,(HL) LD D,A PUSH HL LD HL,RWTAB LD BC,LENRW RWLK: CPIR JR NZ,NOTRW PUSH HL PUSH BC LD BC,LENRW-1 ADD HL,BC LD A,(HL) POP BC POP HL CP E JR Z,HAVRW LD A,C OR A LD A,D JR NZ,RWLK NOTRW: POP HL NORW: POP HL ENDRW: POP AF JR IDRET HAVRW: POP HL INC C LD (HL),C INC HL POP DE PUSH HL LD A,C LD HL,IXSI CP RSI JR Z,IXIY LD HL,IYDI CP RDI JR NZ,NORW IXIY: EX AF,AF' JR Z,NOTENC EX AF,AF' CALL OUTSTR JR NORW NOTENC: EX AF,AF' POP HL DEC HL LD (HL),'[' INC HL ADD A,RIX-1 LD (HL),A INC HL LD (HL),']' INC HL JR ENDRW RET FINDOP: LD HL,OPCODE LD BC,5 XOR A CPIR JR NZ,OPERR LD A,4 SUB C RET Z DEC A JR Z,OPERR LD C,A DEC HL DEC HL SET 7,(HL) LD A,(OPCODE) SUB 'A' JR C,OPERR ADD A,A LD E,A LD D,0 LD HL,OPTAB ADD HL,DE LD E,(HL) INC HL LD D,(HL) EX DE,HL LD A,9 CALL PUTCH LOOKOP: LD A,(HL) OR A JR Z,OPERR LD DE,OPCODE+1 LD B,C LOOKLP: LD A,(DE) CP (HL) JR NZ,NEXOP INC DE INC HL DJNZ LOOKLP LD E,(HL) INC HL LD D,(HL) INC HL PUSH DE LD E,(HL) INC HL LD D,(HL) LD H,D LD L,E POP DE PUSH DE POP IX JP (IX) NEXOP: BIT 7,(HL) INC HL JR Z,NEXOP LD DE,4 ADD HL,DE JR LOOKOP OPERR: LD HL,OPCODE CALL OUTSTR CALL TWOOPS LD HL,OPCDER CALL OUTSTR JP ENLIN LD: CALL OUTSTR LD HL,OP1 LD DE,OP2+1 CALL LCHECK JP Z,LDAX EX DE,HL DEC HL INC DE CALL LCHECK JP Z,STAX ;If immediate move, check for byte memory reference LD A,(OP1) CP '[' ;Memory reference? JR NZ,TWOOPS LD A,(OP1+1) ;Referencing IX as a word? CP RIX JR Z,TWOOPS CP RIY JR Z,TWOOPS LD A,(OP2) CP 20H ;Could be immediate? LD A,9 CALL NC,BFLAG ;Add "B," CALL TRAN1 JR TRNOP2 TWOOPS: CALL TRNOP1 TRNOP2: LD A,',' TRAN2: LD HL,OP2 PTRANS: CALL PUTCH TRANS: LD A,(HL) INC HL OR A RET Z CALL TRNTOK JR TRANS LCHECK: LD A,(HL) CP RAL RET NZ LD A,(DE) CP RCX RET Z CP RDX RET ONEOP: CALL OUTSTR TRNOP1: LD A,9 TRAN1: LD HL,OP1 JR PTRANS IN: LD A,(OP1) CP RAL EX DE,HL LD HL,OP2 JR Z,GETPORT LD HL,SAVEAX CALL OUTSTR CALL OUTSTR LD HL,OP2 CALL GETPORT LD HL,MOV0 CALL ONEOP LD A,',' CALL PUTCH LD A,RAL CALL TRNTOK IODONE: LD HL,RESTAX JP OUTSTR OUT: LD A,(OP2) EX DE,HL LD HL,OP1 CP RAL JR Z,GETOUT LD HL,SAVEAX CALL OUTSTR LD HL,MOVAL CALL OUTSTR CALL TRNOP2 LD HL,CRLFTB CALL OUTSTR LD HL,OP1 CALL GETOUT JR IODONE GETPORT: LD A,(HL) CP '[' JR NZ,NOBRAK INC HL PUSH HL LD BC,80 LD A,']' CPIR DEC HL LD (HL),0 POP HL NOBRAK: LD A,(HL) CP RGCL JR NZ,FIXPOR LD HL,IO1 CALL OUTSTR EX DE,HL CALL OUTSTR LD A,RDX CALL TRNTOK LD HL,IO2 JR OUTSTR GETOUT: CALL GETPORT RET NC LD HL,BADIO JR OUTSTR FIXPOR: EX DE,HL CALL OUTSTR EX DE,HL JP TRANS LDAX: LD HL,LDAX1 LSAX: CALL OUTSTR LD A,(DE) CALL TRNTOK JR OUTSTR STAX: LD HL,STAX1 JR LSAX TRNTOK: CP ' ' JP NC,PUTCH PUSH HL PUSH BC LD C,A LD B,0 LD HL,TOKTAB-2 ADD HL,BC ADD HL,BC LD A,(HL) CALL PUTCH INC HL LD A,(HL) POP BC POP HL OR A RET Z JP PUTCH PUSH: LD DE,PUSHAF JR AFCHK POP: LD DE,POPAF AFCHK: LD A,(OP1) CP RAX JP NZ,ONEOP EX DE,HL OUTSTR: LD A,(HL) OR A CALL Z,NEWOP CALL PUTCH INC HL ADD A,A JR NC,OUTSTR RET NEWOP: LD A,13 CALL PUTCH LD A,10 CALL PUTCH LD A,9 RET LDDR: CALL OUTSTR LD HL,BLMOVE JR OUTSTR CPDR: CALL OUTSTR LD HL,CMPREP JR OUTSTR ADD: LD A,(OP1) CP RBX JR Z,DAD ARITH: CALL OUTSTR LD A,(OP2) OR A JP NZ,TWOOPS LD A,9 CALL PUTCH LD A,RAL CALL TRNTOK LD A,',' JP TRAN1 ACCUM: CALL OUTSTR LD A,9 CALL PUTCH LD A,RAL JP TRNTOK JP ONEOP DAD: LD HL,DAD1 CALL OUTSTR CALL TWOOPS LD HL,DAD2 JR OUTSTR INCDEC: LD A,(OP1) CP RCX+1 ;16-bit? JP NC,ONEOP LD HL,LAHF CALL OUTSTR EX DE,HL LD HL,OPCODE-1 CALL ONEOP EX DE,HL JR OUTSTR JUMP: LD A,(OP1) CP '[' JR NZ,DIRECT LD A,(OP1+1) LD (OP1),A XOR A LD (OP1+1),A DIRECT: LD A,(OP2) OR A JP Z,ONEOP CALL FIXCON LD HL,OP2 OUTCON: LD B,A LD A,'J' CALL PUTCH LD A,B CALL TRNTOK LD A,9 CALL PTRANS LD A,B CP ODDPAR LD HL,WARNPA JP Z,OUTSTR CP EVEPAR JP Z,OUTSTR RET FIXCON: LD A,(OP1) CP RGCL RET NZ LD A,CY RET RETURN: LD A,(OP1) OR A JP Z,OUTSTR LD HL,'R'+4500H ;"RE" LD (OP2),HL LD HL,'T' LD (OP2+2),HL JR DIRECT JP ONEOP DOCALL: LD A,(OP2) OR A JP Z,ONEOP CALL FIXCON DEC A XOR 1 INC A LD HL,LABEL CALL OUTCON LD HL,OPCODE-1 CALL OUTSTR LD A,(OP2) OR A LD A,9 LD HL,OP2 CALL NZ,PTRANS LD HL,CRLF CALL OUTSTR CALL TRANS CALL OUTSTR LD HL,LABEL+4 NEXLAB: INC (HL) LD A,(HL) CP '9'+1 RET NZ LD (HL),'0' DEC HL JR NEXLAB EX: LD A,(OP1) CP RAX JP Z,OUTSTR LD A,(OP1+1) CP STP JR Z,XTHL LD HL,XCHG CALL OUTSTR JP TWOOPS XTHL: LD HL,XTHL1 CALL OUTSTR CALL TRNOP2 LD HL,XTHL2 JP OUTSTR PSEUDO: CALL ONEOP LD A,(OP2) OR A RET Z JP TRNOP2 RET BITSET: LD C,0 JR SETRES RES: LD C,-1 SETRES: CALL OUTSTR PUSH HL LD A,(OP2) CP '[' LD A,9 CALL Z,BFLAG CALL TRAN2 LD A,',' CALL PUTCH CALL GETBIT LD HL,BITERR CALL C,OUTSTR POP HL JP OUTSTR BFLAG: CALL PUTCH LD A,'B' CALL PUTCH LD A,',' RET GETBIT: LD A,(OP1+1) OR A SCF RET NZ LD A,(OP1) SUB '0' RET C CP 8 CCF RET C LD B,A INC B XOR A SCF SHFT: RLA DJNZ SHFT XOR C LD B,A LD A,'0' CALL PUTCH LD A,B RRA RRA RRA RRA CALL HEX LD A,B CALL HEX LD A,'H' JP PUTCH OPTAB: DW AOPS,BOPS,COPS,DOPS,EOPS DW FOPS,GOPS,HOPS,IOPS,JOPS DW KOPS,LOPS,MOPS,NOPS,OOPS DW POPS,QOPS,ROPS,SOPS,TOPS DW UOPS,VOPS,WOPS,XOPS,YOPS DW ZOPS AOPS: DM 'DD' DW ADD,OPCODE DM 'DC' DW ARITH,OPCODE DM 'ND' DW ARITH,OPCODE DB 0 BOPS: DM 'IT' DW BITSET,TESBIT DB 0 COPS: DM 'ALL' DW DOCALL,OPCODE DM 'P' DW ARITH,CMP DM 'PL' DW ACCUM,NOT DM 'PIR' DW OUTSTR,CPIR DM 'PDR' DW CPDR,DOWN DM 'CF' DW OUTSTR,CMC DB 0 DOPS: DM 'EC' DW INCDEC,OPCODE DM 'JNZ' DW ONEOP,DJNZ DM 'AA' DW OUTSTR,OPCODE DM 'I' DW OUTSTR,OPCODE DM 'W' DW PSEUDO,OPCODE DM 'B' DW PSEUDO,OPCODE DM 'M' DW PSEUDO,OPCODE DM 'S' DW ONEOP,OPCODE DB 0 EOPS: DM 'X' DW EX,EXAF DM 'I' DW OUTSTR,OPCODE DM 'XX' DW OUTSTR,EXX DM 'QU' DW ONEOP,OPCODE DM 'NDIF' DW OUTSTR,OPCODE DB 0 FOPS: DB 0 GOPS: DB 0 HOPS: DM 'ALT' DW OUTSTR,HLT DB 0 IOPS: DM 'NC' DW INCDEC,OPCODE DM 'N' DW IN,INB DM 'F' DW ONEOP,OPCODE DB 0 JOPS: DM 'R' DW JUMP,JR DM 'P' DW JUMP,JMP DB 0 KOPS: DB 0 LOPS: DM 'D' DW LD,MOV DM 'DIR' DW OUTSTR,UP DM 'DDR' DW LDDR,DOWN DB 0 MOPS: DB 0 NOPS: DM 'EG' DW ACCUM,OPCODE DB 0 OOPS: DM 'R' DW ARITH,OPCODE DM 'UT' DW OUT,OUTB DM 'RG' DW ONEOP,OPCODE DB 0 POPS: DM 'OP' DW POP,OPCODE DM 'USH' DW PUSH,OPCODE DB 0 QOPS: DB 0 ROPS: DM 'ET' DW RETURN,OPCODE DM 'LA' DW ACCUM,RCL DM 'RA' DW ACCUM,RCR DM 'LCA' DW ACCUM,ROL DM 'RCA' DW ACCUM,ROR DM 'L' DW ONEOP,RCL DM 'R' DW ONEOP,RCR DM 'LC' DW ONEOP,ROL DM 'RC' DW ONEOP,ROR DM 'ES' DW RES,RESBIT DM 'ETI' DW OUTSTR,IRET DM 'ETN' DW OUTSTR,IRET DM 'ST' DW ONEOP,CALL DB 0 SOPS: DM 'UB' DW ARITH,OPCODE DM 'BC' DW ARITH,SBB DM 'LA' DW ONEOP,SAL DM 'RA' DW ONEOP,SAR DM 'RL' DW ONEOP,SHR DM 'CF' DW OUTSTR,STC DM 'ET' DW BITSET,SETBIT DB 0 TOPS: DB 0 UOPS: DB 0 VOPS: DB 0 WOPS: DB 0 XOPS: DM 'OR' DW ARITH,OPCODE DB 0 YOPS: DB 0 ZOPS: DB 0 LDAX1: DM 9,'SI,' DM 0,'LODB' STAX1: DM 9,'DI,' DM 0,'STOB' PUSHAF: DB 'LAHF',0,'XCHG',9,'AH,AL',0,'PUSH',9,'AX',0 DM 'XCHG',9,'AH,AL' POPAF: DM 'POP',9,'AX',0,'XCHG',9,'AH,AL',0,'SAHF' DOWN: DM 'DOWN' UP: DB 'UP' BLMOVE: DB 0,'MOV',9,'SI,BX',0,'MOV',9,'DI,DX' DB 0,'REP',0,'MOVB',0,'MOV',9,'DX,DI' DM 0,'MOV',9,'BX,SI' CPIR: DB 'UP' CMPREP: DB 0,'MOV',9,'DI,BX',0,'REPNZ',0,'SCAB' DM 0,'MOV',9,'BX,DI' DAD1: DM 'LAHF',0,'ADD' DAD2: DM 0,'RCR',9,'SI',0,'SAHF',0,'RCL',9,'SI' LAHF: DM 'LAHF' DM 0,'SAHF' DJNZ: DB 'DEC',9,'CH',13,10 DB '; *** WARNING: DJNZ does not affect flags - DEC does.',0 DM 'JNZ' WARNPA: DM 13,10,'; *** WARNING: Parity flag not always same as Z80.' IO1: DB 'MOV',9,'DI,DX',0,'MOV',9,'DL,CL',0 DM 'XOR',9,'DH,DH',13,10,9 IO2: DM 0,'MOV',9,'DX,DI' BADIO: DM 13,10,'; *** WARNING: Flags not same as Z80.' BITERR: DM 13,10,' *** ERROR: Cannot determine bit number.' SETBIT: DM 'LAHF',0,'OR' DM 0,'SAHF' RESBIT: DM 'LAHF',0,'AND' DM 0,'SAHF' TESBIT: DM 'RCR',9,'SI',0,'TEST' DM 0,'RCL',9,'SI' XTHL1: DM 'POP',9,'SI',0,'XCHG',9,'SI' XTHL2: DM 0,'PUSH',9,'SI' EXX: DB 'XCHG',9,'BX,[HL]',0,'XCHG',9,'DX,[DE]',0 DM 'XCHG',9,'CX,[BC]' EXAF: DM 'LAHF',0,'XCHG',9,'AX,BP',0,'SAHF' MOVAL: DM 0,'MOV',9,'AL' IXSI: DM 9,'MOV',9,'SI,[IX]',13,10 IYDI: DM 9,'MOV',9,'DI,[IY]',13,10 RESTAX: DB 0 SAVEAX: DM 'XCHG',9,'AX,SI' CRLFTB: DM 13,10,9 INB: DM 'INB',9 OUTB: DM 'OUTB',9 XCHG: DM 'XCHG' JMP: DM 'JMP' JR: DM 'JP' RCL: DM 'RCL' RCR: DM 'RCR' ROL: DM 'ROL' ROR: DM 'ROR' SAL: DM 'SAL' SAR: DM 'SAR' SHR: DM 'SHR' STC: DM 'STC' IRET: DM 'IRET' HLT: DM 'HLT' CMC: DM 'CMC' NOT: DM 'NOT' MOV0: DB 0 MOV: DM 'MOV' CMP: DM 'CMP' SBB: DM 'SBB' CALL: DM 'CALL' TOKTAB: DB 'SIDI' DB 'PEPOS',0,'NSNZZ',0,'NCC',0 DB 'AXSPBXDXCX' DB 'BLBHDLDHCLCHALIXIY' RWTAB: DB 'ABCDEHLBDHSACNZNPMPPII' LENRW: EQU $-RWTAB DB 0,0,0,0,0,0,0,'CELPF',0,'C',0,'Z',0,0,'OEYX' HEADER: DB 13,10,'Z80 to 8086 Translator version 1.0',13,10,'$' NOROOM: DB 13,10,'Insufficient directory space to create file',13,10,'$' NOFILE: DB 13,10,'File not found',13,10,'$' ENDMES: DB 13,10,'Translation complete',13,10,'$' WRTERR: DB 13,10,'Out of disk space',13,10,'$' OPCDER: DM 13,10,'*** Opcode Error ' CRLF: DM 13,10 LABEL: DB 'L0000',0 DM ':',9 PUTPT: DS 2 GETPT: DS 2 CHAR: DS 1 DB 0 OPCODE: DS 80 OP1: DS 80 OP2: DS 80 PUTBUF: DS 128 GETBUF: DS 128 PUTFCB: DS 33 DS 50 STACK: EQU $ ORG 1 ;This is really just for equates without EQU RSI: DS 1 RDI: DS 1 ODDPAR: DS 1 EVEPAR: DS 1 DS 5 ;MINUS,PLUS,NOT ZERO,ZERO,NOT CARRY CY: DS 1 RAX: DS 1 STP: DS 1 RBX: DS 1 RDX: DS 1 RCX: DS 1 RBL: DS 1 RBH: DS 1 RDL: DS 1 RDH: DS 1 RGCL: DS 1 RCH: DS 1 RAL: DS 1 RIX: DS 1 RIY: DS 1