home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
simtel
/
sigm
/
vols000
/
vol091
/
xlate2.mac
< prev
Wrap
Text File
|
1984-04-29
|
35KB
|
1,672 lines
;
; Program: XLATE2
; Author: Richard Conn
; Derivation: Disassembled XLATE.COM of Cromemco's CDOS and Modified
; into XLATE2; XLATE.COM was Version 2.40
; Version: 1.1
; Date: 21 July 82
; Previous Versions: 1.0 (3 May 82)
;
; XLATE2 inputs an Intel-Standard 8080 Assembly Language Source File
; and converts it into a Zilog-Standard Z80 Assembly Language Source File.
;
VERS EQU 11 ;VERSION NUMBER
;
; USE ZILOG MNEMONICS AND ABSOLUTE SEGMENTS
;
.Z80
ASEG
;
; CP/M CONSTANTS
;
WBOOT EQU 0
BDOS EQU 5
DEFFCB EQU 5CH
FCB2 EQU 6CH
;
; START OF PROGRAM
;
ORG 100H
CALL HCHECK ;CHECK FOR HELP REQUEST
LD SP,OBUFLPOS ;INIT STACK PTR
CALL INIT ;INIT THE PROGRAM
LOOP:
CALL BUILDLINE ;BUILD THE NEXT INPUT LINE
CALL PROCESSOPS ;CONVERT THE OP CODES
JR LOOP
;
; MAIN PROCESSING MODULE
;
PROCESSOPS:
CALL GETOP ;EXTRACT THE NEXT OP CODE
JP Z,FLUSHLINE ;IF NONE, FLUSH
;
LD HL,OCS1 ;PROCESS OP CODE SET 1
LD BC,10 ;10 CHARS/DUAL ENTRY (OLD OP = 5, NEW OP = 5)
CALL CMPOP ;SCAN FOR MATCH IN INLN BUFFER
JP Z,DOOCS1 ;PROCESS IF FOUND
;
LD HL,OCS2 ;PROCESS OP CODE SET 2
LD BC,10 ;10 CHARS/DUAL ENTRY
CALL CMPOP ;SCAN FOR MATCH
JP Z,DOOCS2 ;PROCESS
;
LD HL,OCS3 ;PROCESS OP CODE SET 3
LD BC,10 ;10 CHARS/DUAL ENTRY
CALL CMPOP ;SCAN FOR MATCH
JP Z,DOOCS3 ;PROCESS
;
LD HL,OCS4 ;PROCESS (EXTENDED RET) OP CODE SET 4
LD BC,5 ;5 CHARS/SINGLE ENTRY
CALL CMPOP ;SCAN FOR MATCH
CALL Z,DOOCS4 ;CONVERT INTO STANDARD RET FORMS IF MATCH
;
LD HL,RETS ;PROCESS (NORMAL RET) OP CODE SET 5
LD BC,5 ;5 CHARS/SINGLE ENTRY
CALL CMPOP ;SCAN FOR MATCH
JP Z,DORETS ;PROCESS
;
LD HL,CALLS ;PROCESS (CALL) OP CODE SET 6
LD BC,5 ;5 CHARS/SINGLE ENTRY
CALL CMPOP ;SCAN FOR MATCH
JP Z,DOCALLS ;PROCESS
;
LD HL,JMPS ;PROCESS (JMP) OP CODE SET 7
LD BC,5 ;5 CHARS/SINGLE ENTRY
CALL CMPOP ;SCAN FOR MATCH
JP Z,DOJMPS ;PROCESS
;
LD HL,OCS8 ;PROCESS OP CODE SET 8
LD BC,12 ;12 CHARS/DUAL ENTRY
CALL CMPOP ;SCAN FOR MATCH
JP Z,DOOCS8 ;PROCESS
;
; NO MATCH IN OP CODE SETS -- PASS TARGET OP CODE AS IS
;
LD B,5 ;5 CHARS IN TARGET
LD HL,TARGOP ;POINT TO TARGET
POPS1:
LD A,(HL) ;GET CHAR
CP ' ' ;END OF OP?
JR Z,POPS2 ;OUTPUT TAB CHAR IF SO
CP 9 ;END OF OP?
JR Z,POPS2 ;OUTPUT TAB CHAR IF SO
CALL DOUTCHAR ;OUTPUT OP CHAR
INC HL ;PT TO NEXT
DJNZ POPS1 ;CONTINUE FOR 5 CHARS MAX
POPS2:
LD A,9 ;END OP WITH <TAB>
CALL DOUTCHAR ;OUTPUT TO DISK
;
; COPY REST OF INPUT LINE AS-IS
;
COPYARGS:
LD HL,(INLNPTR) ;PT TO NEXT CHAR
CARGS1:
LD C,0
CARGS2:
LD A,(HL) ;GET CHAR
CP ' ' ;END OF OPERANDS?
JR Z,CARGS4 ;SKIP WHITE SPACE AND OUTPUT REST IF SO
CP 9 ;END OF OPERANDS?
JR Z,CARGS4 ;SKIP WHITE SPACE AND OUTPUT REST IF SO
CP 0DH ;END OF LINE?
JR Z,FLUSHLINE ;FLUSH IF SO
CP ';' ;BEGINNING OF COMMENT = END OF OPERANDS?
JR Z,CARGS5 ;COPY REST IF SO
CP '''' ;SINGLE QUOTE?
JR NZ,CARGS3
DEC C
JR Z,CARGS3
LD C,1
CARGS3:
CALL DOUTCHAR ;OUTPUT CHAR IN A TO DISK
INC HL ;PT TO NEXT
JR CARGS2
CARGS4:
PUSH HL
CALL SKIPWHITE ;SKIP TO NEXT NON-WHITE CHAR
POP HL
CP 0DH ;END OF LINE?
JR Z,FLUSHLINE ;FLUSH IF SO
CP ';' ;COMMENT?
JR Z,CARGS5 ;PROCESS COMMENT IF SO
CALL OUTWHITE ;OUTPUT A TAB
JR CARGS2 ;RESTART PROCESSING
CARGS5:
DEC C
INC C
JR NZ,CARGS3
CALL SKIPWHITE
LD B,41
CARGS6:
LD A,(OBUFLPOS) ;CHECK POSITION IN OUTPUT LINE
CP B
JR NC,FLUSHLINE
DEC A ;BACK UP IN OUTPUT LINE
AND 0F8H ;ARTIFICALLY TAB
ADD A,9
CP B
JR Z,FLUSHLINE
JR C,CARGS7
LD A,' '
JR CARGS8
CARGS7:
LD A,9
CARGS8:
CALL DOUTCHAR
JR CARGS6
;
; WRITE REST OF INLN TO DISK
;
FLUSHLINE:
CALL OUTSTR
LD A,1 ;RESET POSITION COUNTER
LD (OBUFLPOS),A
RET
;
; PRINT PDOT FOR EVERY TEN LINES
;
PDOT:
LD A,(LCOUNT) ;GET LINE COUNT
DEC A ;COUNT DOWN
LD (LCOUNT),A ;PUT LINE COUNT
RET NZ ;DONE IF NOT ZERO
LD A,'.' ;PRINT PDOT
CALL PCHAR
LD A,10 ;RESET COUNT
LD (LCOUNT),A
LD A,(NLCOUNT) ;NEW LINE?
DEC A
LD (NLCOUNT),A
RET NZ
LD DE,CRLFSTR ;PRINT NEW LINE
CALL PMSG
LD A,60 ;RESET COUNTER
LD (NLCOUNT),A
RET
;
; OUTPUT STRING PTED TO BY HL TO DISK (STRING ENDS IN 0)
;
OUTSTR:
LD A,(HL) ;GET CHAR
AND A ;DONE?
RET Z ;RET IF SO
CALL DOUTCHAR
INC HL ;PT TO NEXT CHAR
JR OUTSTR
;
; OUTPUT ALL <SP> AND <TAB> CHARS FOUND UNTIL A NON-<SP> AND NON-<TAB>
; ENCOUNTERED
;
OUTWHITE:
LD A,(HL) ;GET CHAR
CP ' ' ;<SP>?
JR Z,OW1 ;OUTPUT IT
CP 9 ;<TAB>?
RET NZ ;DONE IF NOT
OW1:
CALL DOUTCHAR ;OUTPUT CHAR IN A TO DISK
INC HL ;PT TO NEXT CHAR
JR OUTWHITE ;CONTINUE
;
; EXTRACT OP CODE FOR INPUT LINE AND PLACE IN BUFFER
;
GETOP:
LD HL,INLN ;PT TO INPUT LINE
LD A,(HL) ;GET 1ST CHAR IN LINE
CP ' ' ;NO LABEL?
JR Z,GOP3 ;SKIP TO OP CODE
CP 9 ;NO LABEL?
JR Z,GOP3 ;SKIP TO OP CODE
CP ';' ;COMMENT?
RET Z ;DONE IF SO
;
; LINE BEGINS WITH A LABEL -- PROCESS IT
;
GOP1:
LD C,0 ;SET LABEL CHAR CNT
GOP2:
LD A,(HL) ;GET NEXT CHAR OF LABEL
CP ':' ;END OF LABEL?
JR Z,GOP4
CP 9 ;END OF LABEL?
JR Z,GOP5
CP 0DH ;END OF LABEL AND NO FURTHER PROCESSING?
JR Z,GOP5
CP ';' ;END OF LABEL AND NO FURTHER PROCESSING?
JR Z,GOP5
CP ' ' ;END OF LABEL?
JR Z,GOP5
CALL DOUTCHAR ;OUTPUT LABEL CHAR TO DISK
INC HL ;PT TO NEXT CHAR
INC C ;INCR LABEL CHAR CNT
JR GOP2
;
; NO LABEL -- SKIP TO OP CODE
;
GOP3:
CALL SKIPWHITE ;SKIP OVER WHITE SPACE
PUSH HL
CALL FTODLM
CP ':'
POP HL
JR Z,GOP1
JR GOP7
;
; END OF LABEL BY ':' CHAR
;
GOP4:
INC HL ;SKIP ':'
CALL DOUTCHAR ;OUTPUT THE ':'
LD A,(HL) ;CHECK FOR EOL
CP 0DH ;DON'T DOUBLE NEW LINE (SKIP NEW LINE AFTER GOP6)
JR Z,GOP8 ;JUST CONTINUE PROCESSING WITH NO TAB
JR GOP6 ;NOT NEW LINE, SO PROCESS FOR NEW LINE IF LONG LABEL
;
; OUTPUT ':' AT END OF LABEL
;
GOP5:
LD A,':' ;OUTPUT THE ':'
CALL DOUTCHAR
;
; SEE IF LABEL IS LESS THAN 7 CHARS LONG
; IF <7, THEN TERMINATE WITH <TAB>; IF >6, THEN NEW LINE AND <TAB>
;
GOP6:
LD A,C ;GET LABEL CHAR CNT
CP 7 ;LESS THAN 7?
JR C,GOP7 ;JUST TAB IF LESS THAN 7
LD A,0DH ;<CR>
CALL DOUTCHAR
LD A,0AH ;<LF>
CALL DOUTCHAR
;
; OUTPUT <TAB> AFTER LABEL TO DISK
;
GOP7:
LD A,9 ;<TAB>
CALL DOUTCHAR
;
; SKIP TO OP CODE FIELD AND EXTRACT IT IF PRESENT
;
GOP8:
CALL SKIPWHITE ;SKIP TO OP CODE FIELD
LD A,(HL) ;GET FIRST NON-WHITE CHAR
CP ';' ;NO OP CODE IF COMMENT
RET Z ;DONE IF COMMENT
CP 0DH ;NO OP CODE IF EOL
RET Z ;DONE IF EOL
LD (ILTOP),HL ;SAVE PTR TO TARGET OP CODE
LD B,5 ;5 CHARS MAX IN OP CODE
LD DE,TARGOP ;COPY TO TARGOP BUFFER
CALL COPYTODELIM ;COPY UNTIL DELIMITER ENCOUNTERED
CALL SKIPWHITE ;SKIP OVER WHITE SPACE WHICH FOLLOWS
LD (INLNPTR),HL ;SAVE PTR
SUB A
INC A ;A=1 AND NZ
RET
;
; COMPARE OP CODE PTED TO BY HL WITH TARGET OP CODE; RET WITH Z SET IF
; MATCH, NZ IF NO MATCH
;
CMPOP:
LD A,(HL) ;NO OP CODE TO COMPARE?
AND A ;A=0 IF SO
JR Z,CMPOP1 ;FAILURE IF SO
PUSH BC
LD B,5 ;COMPARE 5 BYTES
LD DE,TARGOP ;PT TO TARGET OP CODE
CALL COMPHLDE ;COMPARE
POP BC
RET Z ;DONE IF MATCH
ADD HL,BC ;PT TO NEXT OP CODE IN TABLE
JR CMPOP
CMPOP1:
INC A ;A=1 AND NZ
RET
;
; PROCESS OP CODES IN SET 1 -- OPERAND AND COMMENTS FIELDS ARE UNCHANGED
; HL PTS TO OP CODE TABLE ENTRY, 2ND ELT OF WHICH IS TO BE OUTPUT TO DISK
;
DOOCS1:
CALL OUTNEWOP5CH ;OUTPUT NEW OP CODE
JP COPYARGS ;COPY OPERAND AND COMMENT FIELDS AS-IS
;
; OUTPUT 2ND 5-CHAR-MAX OP CODE FIELD PTED TO BY HL TO DISK AND END IN <TAB>
;
OUTNEWOP5CH:
LD BC,5 ;SKIP FIRST 5 CHARS
ADD HL,BC ;PT TO 2ND 5-CHAR FIELD
;
; ENTRY PT TO COPY 5-CHAR-MAX FIELD PTED TO BY HL
;
ONO5C0:
LD B,5
ONO5C1:
LD A,(HL) ;GET NEXT CHAR
CP ' ' ;<SP>?
JR Z,ONO5C2 ;DONE IF SO
CP 9 ;<TAB>?
JR Z,ONO5C2 ;DONE IF SO
CALL DOUTCHAR ;OUTPUT CHAR TO DISK
INC HL ;PT TO NEXT
DJNZ ONO5C1 ;COUNT DOWN
ONO5C2:
LD A,9 ;OUTPUT <TAB> TO DISK
JP DOUTCHAR ;OUTPUT TO DISK
;
; PROCESS OP CODES IN SET 2 - OPERAND IS 1 REG OR '(HL)'
; HL PTS TO OP CODE TABLE ENTRY, 2ND ELT OF WHICH IS TO BE OUTPUT TO DISK
;
DOOCS2:
CALL OUTNEWOP5CH ;OUTPUT NEW 5-CHAR-MAX OP CODE
LD HL,(INLNPTR) ;PT TO OPERAND FIELD
ATHLCHECK:
LD A,(HL) ;CHECK FOR '(HL)' REFERENCE
CP 'M' ;TAKES THE FORM OF 'M' IN 8080 MNEMONICS
JP NZ,CARGS1 ;OUTPUT NORMALLY IF NOT
INC HL ;PT TO CHAR AFTER
PUSH HL ;SAVE PTR
LD HL,ATHL ;OUTPUT '(HL)'
CALL OUTSTR ;OUTPUT TO DISK
POP HL ;GET PTR
JP CARGS1 ;PROCESS REST OF LINE NORMALLY
ATHL:
DB '(HL)',0
;
; PROCESS OP CODES IN SET 3 - OPERAND IS BC, DE, HL, OR PSW REG PAIR
; HL PTS TO OP CODE TABLE ENTRY, 2ND ELT OF WHICH IS TO BE OUTPUT TO DISK
;
DOOCS3:
CALL OUTNEWOP5CH ;OUTPUT NEW OP CODE
RPCHECK:
LD HL,(INLNPTR) ;PT TO OPERAND FIELD
PUSH HL ;SAVE PTR
LD A,(HL) ;GET OPERAND
CP 'B' ;FOR BC?
JR Z,PRBC ;OUTPUT BC IF SO
CP 'D' ;FOR DE?
JR Z,PRDE ;OUTPUT DE IF SO
CP 'H' ;FOR HL?
JR Z,PRHL ;OUTPUT HL IF SO
CP 'P' ;FOR PSW?
JR NZ,L0309 ;OUTPUT WHATEVER'S THERE IF NOT
INC HL ;MAKE SURE IT IS 'PSW'
LD A,(HL)
CP 'S'
JR NZ,L0309 ;OUTPUT WHAT'S THERE IF NOT
INC HL
LD A,(HL)
CP 'W'
JR NZ,L0309 ;OUTPUT WHAT'S THERE IF NOT
POP HL ;IT IS 'PSW', SO CLEAR STACK AND PT
INC HL ; ... TO CHAR AFTER 'PSW'
INC HL
PUSH HL
LD HL,AFSTR ;PRINT 'AF'
JR PRREGPAIR ;DO PRINT
PRBC:
LD HL,BCSTR ;PRINT 'BC'
JR PRREGPAIR
PRDE:
LD HL,DESTR ;PRINT 'DE'
JR PRREGPAIR
PRHL:
LD HL,HLSTR ;PRINT 'HL'
PRREGPAIR:
CALL OUTSTR ;PRINT STRING PTED TO BY HL AND MAKE HL ON STACK
POP HL ; ... PT TO NEXT CHAR
INC HL
PUSH HL
L0309:
POP HL ;PRINT WHATEVER OTHER OPERAND IT IS
JP CARGS1 ;PRINT THE OPERAND
AFSTR:
DB 'AF',0
BCSTR:
DB 'BC',0
DESTR:
DB 'DE',0
HLSTR:
DB 'HL',0
;
; PROCESS OP CODE SET 4 - EQ, NE, LT, GE RETS, CALLS, AND JMPS
; HL PTS TO OP CODE TABLE ENTRY, 2ND ELT OF WHICH IS TO BE OUTPUT TO DISK
;
DOOCS4:
LD A,(TARGOP+1) ;LOOK AT 2ND LETTER OF TARGET OP
LD HL,ZFLG ;PREP FOR ZERO
CP 'E' ;IF 'E', THEN FORM IS 'EQ'
JR Z,ZCPUT ;CHANGE FORM TO 'XZ ', WHERE X=R,C,J
LD HL,NZFLG ;PREP FOR NOT ZERO
CP 'N' ;IF 'N', THEN FORM IS 'NE'
JR Z,ZCPUT
LD HL,CFLG ;PREP FOR CARRY
CP 'L' ;IF 'L', THEN FORM IS 'LT'
JR Z,ZCPUT
LD HL,NCFLG ;FORM MUST BE 'GE', SO NO CARRY
ZCPUT:
LD A,(HL) ;GET FIRST CHAR
LD (TARGOP+1),A ;STORE IT
INC HL ;PT TO 2ND CHAR
LD A,(HL) ;GET IT
LD (TARGOP+2),A ;STORE IT
RET
ZFLG:
DB 'Z '
NZFLG:
DB 'NZ'
CFLG:
DB 'C '
NCFLG:
DB 'NC'
;
; PROCESS OP CODE SET 5 -- RETURN FORMS
; HL PTS TO OP CODE TABLE ENTRY, 2ND ELT OF WHICH IS TO BE OUTPUT TO DISK
;
DORETS:
LD HL,RETSTR ;PT TO STR TO COPY
CALL COPY5 ;COPY WITH OPTIONAL COND
JP COPYARGS ;COPY REST OF OPERAND FIELD AND COMMENTS AS-IS
RETSTR:
DB 'RET ',0
DOCALLS:
LD HL,CALLSTR
JR CP5WITHCOMMA ;COPY AND FOLLOW WITH COMMA
CALLSTR:
DB 'CALL ',0
DOJMPS:
LD HL,JPSTR ;FALL THRU TO DO JP FORMS
;
; COPY STRING AT HL FOLLOWED BY CONDITION CODE, A COMMA, AND REST OF
; OPERAND FIELD
;
CP5WITHCOMMA:
CALL COPY5
LD A,','
CALL DOUTCHAR ;OUTPUT COMMA TO DISK
JP COPYARGS ;COPY REST OF OPERAND FIELD
JPSTR:
DB 'JP ',0
;
; COPY 5-CHAR-MAX STRING PTED TO BY HL FOLLOWED BY <TAB> AND 2-CHAR COND
;
COPY5:
CALL ONO5C0 ;COPY 5-CHAR-MAX STRING PTED TO BY HL
LD A,(TARGOP+1) ;OUTPUT FIRST CHAR OF COND
CALL DOUTCHAR
LD A,(TARGOP+2) ;OUTPUT 2ND CHAR OF COND IF NOT <SP>
CP ' '
RET Z
JP DOUTCHAR
;
; PROCESS OP CODE SET 8 - THIS TABLE CONTAINS THE SERVICE ROUTINE ADR
; EMBEDDED IN IT AFTER EACH OP CODE PAIR;
; HL PTS TO OP CODE TABLE ENTRY, 2ND ELT OF WHICH IS TO BE OUTPUT TO DISK
;
DOOCS8:
PUSH HL ;SAVE PTR TO OLD (1ST) OP
LD BC,10 ;PT TO ADR OF SERVICE ROUTINE
ADD HL,BC
LD C,(HL) ;BC=ROUTINE ADDRESS
INC HL
LD B,(HL)
POP HL ;PT TO OLD (1ST) OP
PUSH BC ;ROUTINE ADDRESS ON STACK
RET ;JMP TO ROUTINE
;
; THIS CONVERTS 'DAD <RP>' TO 'ADD HL,<RP>'
;
DO81:
CALL OUTNEWOP5CH ;OUTPUT 'ADD<TAB>'
LD HL,DO81S ;OUTPUT 'HL,'
CALL OUTSTR
JP RPCHECK ;OUTPUT <REG PAIR>
DO81S:
DB 'HL,',0
;
; THIS CONVERTS 'ADD R' TO 'ADD A,R'
; AND 'ADC R' TO 'ADC A,R'
; AND 'SBC R' TO 'SBC A,R'
;
DO82:
CALL OUTNEWOP5CH ;OUTPUT THE 'IN<TAB>'
LD HL,DO82S ;OUTPUT 'A,'
JP DO8F1 ;04C7H
DO82S:
DB 'A,',0
;
; THIS CONVERTS 'LDA <ADR>' TO 'LD A,(<ADR>)'
; AND 'IN <ADR>' TO 'IN A,(<ADR>)'
;
DO83:
CALL OUTNEWOP5CH
LD HL,DO83S
JR OUTCLP
DO83S:
DB 'A,(',0
;
; THIS CONVERTS 'LDAX <RP>' TO 'LD A,(<RP>)'
;
DO84:
CALL OUTNEWOP5CH ;OUTPUT OP CODE
LD HL,(INLNPTR) ;PT TO OPERAND
LD A,(HL) ;GET 1ST CHAR OF OPERAND
CP 'B' ;BC REG PAIR?
JR Z,DO841 ;PROCESS IT
CP 'D' ;DE REG PAIR?
JR Z,DO842 ;PROCESS IT
JP CARGS1 ;SOMETHING FUNNY -- PROCESS NORMALLY
DO841:
LD HL,DO841S
JP DO8D3
DO842:
LD HL,DO842S
JP DO8D3
DO841S:
DB 'A,(BC)',0
DO842S:
DB 'A,(DE)',0
;
; THIS CONVERTS 'LHLD <ADR>' TO 'LD HL,(<ADR>)'
;
DO85:
CALL OUTNEWOP5CH
LD HL,DO85S
;
; THIS OUTPUTS THE STRING PTED TO BY HL, OUTPUTS THE REST OF THE OPERAND
; FIELD, OUTPUTS A CLOSING ')', AND OUTPUTS THE REST OF THE INPUT LINE
;
OUTCLP:
CALL OUTSTR ;01F9H
CALL OUTOPER ;04D5H
LD A,')' ;29H
CALL DOUTCHAR ;0631H
JP CARGS1 ;0198H
DO85S:
DB 'HL,(',0
;
; THIS CONVERTS 'MOV R,R' TO 'LD R,R'
;
DO86:
CALL OUTNEWOP5CH
LD HL,(INLNPTR) ;PT TO 1ST CHAR OF OPERAND FIELD
LD A,(HL) ;GET IT
CP 'M' ;CONVERT 'M' TO '(HL)'?
JR NZ,DO862 ;NO CONVERSION NECESSARY
PUSH HL
LD HL,ATHL ;OUTPUT '(HL)'
CALL OUTSTR
POP HL
;
; OUTPUT ',' FOLLOWED BY '(HL)' OR 'R'
;
DO861:
INC HL ;OUTPUT COMMA AND THEN 2ND R
LD A,(HL) ;GET COMMA
CALL DOUTCHAR
INC HL ;PT TO 2ND R
JP ATHLCHECK ;OUTPUT '(HL)' OR R
;
; OUTPUT 'R,' FOLLOWED BY '(HL)' OR 'R'
;
DO862:
CALL DOUTCHAR ;OUTPUT 'R'
JR DO861 ;OUTPUT REST
;
; THIS CONVERTS 'PCHL' TO 'JP<TAB>(HL)'
;
DO88:
CALL OUTNEWOP5CH
LD HL,ATHL ;OUTPUT THE '(HL)'
JP DO8F1
;
; THIS CONVERTS 'RST N' TO 'RST NNH'
;
DO89:
CALL OUTNEWOP5CH
LD HL,DO89S
JP DO8F1
DO89S:
DB '8*',0 ;MULTIPLY RESTART NUMBER BY 8 FOR Z80
;
; THIS CONVERTS 'SHLD <ADR>' TO 'LD (<ADR>),HL'
;
DO8A:
CALL OUTNEWOP5CH
LD A,'(' ;OUTPUT OPENING '('
CALL DOUTCHAR
CALL OUTOPER ;OUTPUT OPERAND
PUSH HL
LD HL,DO8AS ;OUTPUT '),HL'
JR DO8C2
DO8AS:
DB '),HL',0
;
; THIS CONVERTS 'SPHL' TO 'LD SP,HL'
;
DO8B:
CALL OUTNEWOP5CH
LD HL,DO8BS
JR DO8F1
DO8BS:
DB 'SP,HL',0
;
; THIS CONVERTS 'STA <ADR>' TO 'LD (<ADR>),A'
; AND 'OUT <ADR>' TO 'OUT (<ADR>),A'
;
DO8C:
CALL OUTNEWOP5CH
LD A,'(' ;OUTPUT '('
;
; THIS OUTPUTS '<OPERAND>),A'
;
DO8C1:
CALL DOUTCHAR ;OUTPUT CHAR IN A
CALL OUTOPER ;OUTPUT OPERAND FIELD
PUSH HL
LD HL,DO8CS ;OUTPUT '),A'
DO8C2:
CALL OUTSTR ;OUTPUT STRING PTED TO BY HL
POP HL ;CLEAR STACK
JP CARGS1 ;OUTPUT REST OF INPUT LINE
DO8CS:
DB '),A',0
;
; THIS CONVERTS 'STAX <RP>' TO 'LD (<RP>),A'
;
DO8D:
CALL OUTNEWOP5CH
LD HL,(INLNPTR) ;PT TO 1ST CHAR OF OPERAND
LD A,(HL) ;GET IT
CP 'B' ;BC REG PAIR?
JR Z,DO8D1 ;OUTPUT IT IF SO
CP 'D' ;DE REG PAIR?
JR Z,DO8D2 ;OUTPUT IT IF SO
JP CARGS1 ;ELSE, OUTPUT WHAT'S THERE
DO8D1:
LD HL,DO8D1S
JR DO8D3
DO8D2:
LD HL,DO8D2S
DO8D3:
CALL OUTSTR
LD HL,(INLNPTR) ;PT TO AFTER 'B' OR 'D'
INC HL
JP CARGS1
DO8D1S:
DB '(BC),A',0
DO8D2S:
DB '(DE),A',0
;
; THIS CONVERTS 'XCHG' TO 'EX DE,HL'
;
DO8E:
CALL OUTNEWOP5CH
LD HL,DO8ES
JR DO8F1
DO8ES:
DB 'DE,HL',0
;
; THIS CONVERTS 'XTHL' TO 'EX (SP),HL'
;
DO8F:
CALL OUTNEWOP5CH
LD HL,DO8FS
DO8F1:
CALL OUTSTR ;01F9H
JP COPYARGS ;0195H
DO8FS:
DB '(SP),HL',0
;
; OUTPUT REST OF OPERAND FIELD UP TO WHITE SPACE BEFORE ENDING COMMENT
; OR END OF LINE
;
OUTOPER:
LD HL,(INLNPTR) ;PT TO NEXT CHAR IN INPUT LINE BUFFER
OOL1:
LD A,(HL) ;GET NEXT CHAR
CP ';' ;BEGINNING OF COMMENT?
JR Z,OOL2 ;CHECK FOR REST OF OPERAND
CP 0DH ;END OF LINE?
JR Z,OOL2 ;CHECK FOR REST OF OPERAND
INC HL ;CONTINUE UNTIL EITHER COMMENT OR EOL FOUND
JR OOL1
OOL2:
DEC HL ;BACK UP (OVER WHITE SPACE?)
LD A,(HL) ;GET CHAR
CP ' ' ;WHITE?
JR Z,OOL2 ;CONTINUE BACKING
CP 9 ;WHITE?
JR Z,OOL2 ;CONTINUE BACKING
INC HL ;PT TO FIRST WHITE CHAR
EX DE,HL ;SAVE PTR IN DE
LD HL,(INLNPTR) ;PT TO START OF SCAN
OOL3:
LD A,D ;ALL OF OPERAND FIELD FLUSHED?
CP H ;CHECK FOR PTR MATCH
JR NZ,OOL4 ;NO MATCH, SO FLUSH NEXT CHAR
LD A,E ;REST OF MATCH?
CP L
RET Z ;DONE IF ALL MATCH
OOL4:
LD A,(HL) ;OUTPUT OPERAND CHAR TO DISK
CALL DOUTCHAR
INC HL ;PT TO NEXT OPERAND CHAR
JR OOL3 ;CONTINUE UNTIL OPERAND ALL OUT
;
; THE FOLLOWING TURNS ON VARIOUS MESSAGES FOR MANUAL TRANSLATION
;
DO91:
LD A,9 ;ENDIFS
LD (XLT1ON),A ;STORE <TAB> TO ENABLE
JR DO941
DO92:
LD A,9 ;INCLUDES
LD (XLT2ON),A
JR DO941
DO93:
LD A,9 ;LISTS
LD (XLT3ON),A
JR DO941
DO94:
LD A,9 ;MACROS
LD (XLT4ON),A
DO941:
CALL OUTNEWOP5CH ;OUTPUT NEW CODE
LD A,0DH ;TURN ON PRINTED ERR MESSAGE
LD (ERR5ON),A ;TURN ON FLAG BY STARTING WITH <CR>
JP COPYARGS ;COPY REST OF CODE
;
; THE FOLLOWING CHECKS FOR THE SPECIFICATION OF A HELP OPTION AND
; PRINTS THE HELP MESSAGE IF SO
;
HCHECK:
LD A,(DEFFCB+1) ;GET FIRST CHAR OF FILE NAME
CP '/' ;OPTION?
RET NZ ;NO HELP REQUESTED IF NOT OPTION
LD DE,HEADER ;PRINT PROGRAM BANNER
CALL PMSG
LD DE,HMSG1 ;PRINT HELP MESSAGE
CALL PMSG
LD C,1 ;GET ANY CHAR
CALL BDOS
LD DE,HMSG2 ;PRINT REST OF HELP MESSAGE
CALL PMSG
POP DE ;CLEAR STACK
RET ;RETURN TO CP/M
;
; THE FOLLOWING INITIALIZES THE PROGRAM FOR EXECUTION
;
INIT:
LD DE,HEADER ;PRINT PROGRAM BANNER
CALL PMSG
LD A,10 ;INIT PDOT PRINT (LINE) COUNT
LD (LCOUNT),A
LD A,60 ;INIT NEW LINE PRINT COUNT
LD (NLCOUNT),A
LD A,1 ;INITIALIZE OUTPUT BUFFER LINE POSITION
LD (OBUFLPOS),A
CALL MAKEFNS ;SET UP FILE NAMES
CALL OPENIN ;OPEN INPUT FILE
CALL OPENOUT ;OPEN OUTPUT FILE
LD HL,FHDR ;OUTPUT '.Z80' AND 'ASEG' TO MAC FILE
INIT1:
LD A,(HL) ;GET CHAR
OR A ;DONE?
JR Z,INIT2
CALL DOUTCHAR ;OUTPUT TO DISK
INC HL ;PT TO NEXT
JR INIT1
INIT2:
LD A,(FCB2+1) ;2ND FILE NAME PRESENT?
CP ' ' ;<SP> IF NOT
RET NZ ;DONE IF SO
XOR A ;A=0
LD (OCS4),A ;TURN OFF WEIRD OP CODE SCAN (REQ, ETC)
LD (NOXLT),A ;TURN OFF SCAN FOR ENT, NAME, RAM, ROG
LD (NOXLT2),A ;TURN OFF SCAN FOR IFC, ICL, MAC, LST
RET
;
; SET UP FILE NAMES
;
MAKEFNS:
LD HL,DEFFCB ;COPY INPUT FILE NAME FROM COMMAND
LD DE,FCBASM ;INTO THIS FCB FOR USE
LD BC,9 ;9 BYTES
LDIR ;COPY
LD A,(HL) ;FILE TYPE SPECIFIED?
CP ' ' ;NONE IF <SP>
JR Z,MFN1
LD BC,3 ;3 MORE BYTES
LDIR
MFN1:
LD HL,FCB2+1 ;2ND FILE SPECIFIED?
LD A,(HL) ;GET FIRST BYTE OF FILE NAME
DEC HL ;PT TO FIRST BYTE OF FCB
CP ' ' ;NO 2ND FILE NAME?
JR NZ,MFN2 ;SKIP RELOAD OF HL IF THERE IS A 2ND FILE NAME
LD HL,DEFFCB ;COPY FILE NAME INTO OUTPUT FCB
MFN2:
LD DE,FCBZ80 ;OUTPUT FCB
LD BC,9 ;9 BYTES
LDIR ;COPY
LD HL,FCB2+9 ;PT TO FILE TYPE
LD A,(HL) ;CHECK FOR A FILE TYPE
CP ' ' ;NONE IF <SP>
JR Z,MFN3
LD BC,3 ;THERE IS ONE, SO COPY IT OVER
LDIR
MFN3:
LD DE,PRFNM1 ;PRINT PART 1 OF FILE NAME MESSAGE
CALL PMSG
LD HL,FCBASM ;PRINT NAME OF SOURCE FILE
CALL PRFNAME
LD DE,PRFNM2 ;PRINT PART 2 OF FILE NAME MESSAGE
CALL PMSG
LD HL,FCBZ80 ;PRINT NAME OF DESTINATION FILE
CALL PRFNAME
LD DE,CRLFSTR ;END LINE
CALL PMSG
RET
;
; PRINT FILE NAME MESSAGE
;
PRFNAME:
LD A,(HL) ;GET DISK NUMBER
ADD A,'@' ;ADD IN ASCII BIAS
CALL PCHAR
LD A,':' ;PRINT COLON
CALL PCHAR
INC HL ;PT TO FIRST CHAR OF FILE NAME
LD B,8 ;8 CHARS
CALL PRFNC
LD A,'.' ;DOT
CALL PCHAR
LD B,3 ;3 CHARS
CALL PRFNC
RET
PRFNC:
LD A,(HL) ;GET NEXT CHAR
INC HL ;PT TO NEXT
CALL PCHAR ;PRINT CHAR
DJNZ PRFNC
RET
;
; OPEN INPUT FILE FOR PROCESSING
;
OPENIN:
LD DE,FCBASM ;OPEN FILE FOR INPUT
LD C,0FH
CALL BDOS
CP 0FFH ;ERROR?
JR Z,OIERR ;ABORT WITH ERROR MESSAGE IF SO
LD A,80H ;INIT CHAR COUNT FOR BUFFER
LD (IBUFCNT),A
RET
OIERR:
LD DE,ERR2 ;INPUT FILE ERROR MESSAGE
JP ENDERR ;ABORT
;
; OPEN FILE FOR OUTPUT
;
OPENOUT:
LD DE,FCBZ80 ;OPEN OUTPUT FILE
LD C,0FH
CALL BDOS
CP 0FFH ;ERROR?
JR NZ,OOERR2 ;ABORT IF NO ERROR (OVERWRITE OLD FILE)
OPENO1:
LD DE,FCBZ80 ;ELSE CREATE OUTPUT FILE
LD C,16H
CALL BDOS
CP 0FFH ;ERROR?
JR Z,OOERR1
LD DE,FCBZ80 ;NOW OPEN OUTPUT FILE (REDUNDANT WITH MAKE)
LD C,0FH
CALL BDOS
LD A,80H ;INIT COUNT OF BYTES REMAINING
LD (OBUFBACKCNT),A ;SET COUNT
LD HL,OBUF ;INIT ADDRESS OF NEXT BYTE
LD (OBUFPTR),HL ;SET PTR
RET
OOERR1:
LD DE,ERR3 ;DISK FULL
JP ENDERR ;ABORT ERROR
OOERR2:
LD DE,ERR4 ;ATTEMPT TO OVERWRITE EXISTING FILE
CALL PMSG
LD C,1 ;GET RESPONSE
CALL BDOS
CALL CAPS ;CAPITALIZE
CP 'Y' ;CONTINUE IF YES
LD DE,ERR4A ;PREP FOR ABORT
JP NZ,ENDERR ;ABORT ERROR
LD DE,CRLFSTR ;NEW LINE
CALL PMSG
LD DE,FCBZ80 ;DELETE OLD FILE
LD C,19 ;BDOS DELETE FILE
CALL BDOS
JR OPENO1 ;CREATE NEW FILE AND CONTINUE
;
; CHECK TO SEE IF CHAR PTED TO BY HL IS A DELIMITER AND FLUSH CHARS UNTIL
; IT IS; RET WITH ZERO FLAG SET WHEN DONE
;
FTODLM: ;Flush TO DeLiMiter
PUSH BC
CALL DLIMSCAN ;DO SCAN
POP BC
RET Z ;MATCH, SO ABORT
INC HL ;PT TO NEXT CHAR
JR FTODLM ;CONTINUE SCAN
;
; COPY (HL) TO (DE) FOR B BYTES OR UNTIL A DELIMITER IS ENCOUNTERED
;
COPYTODELIM:
LD C,B ;LET BC=OLD B (FOR LDI INSTR)
LD B,0
PUSH BC ;SAVE REGS
PUSH DE
PUSH HL
CALL SPFILL ;FILL DESTINATION BUFFER WITH SPACES (PTED TO BY DE)
POP HL ; ... AND C BYTES LONG
POP DE
POP BC
CTD1:
PUSH BC ;SAVE COUNT
CALL DLIMSCAN ;SCAN FOR DELIMITER IF ENCOUNTERED
POP BC
RET Z ;DONE IF SO
LDI ;COPY NEXT CHAR INTO DESTINATION BUFFER
JP PO,DLIMSCAN ;FINAL DELIMITER SCAN IF DONE
JR CTD1
;
; ADVANCE BUFFER POINTER HL UNTIL NON-WHITE (NON-<SP>, NON-<TAB>)
; ENCOUNTERED
;
SKIPWHITE:
LD A,(HL) ;GET CHAR
CP ' ' ;<SP>?
JR Z,SKPWH1 ;SKIP IF SO
CP 9 ;<TAB>?
RET NZ ;DONE IF NOT
SKPWH1:
INC HL ;PT TO NEXT CHAR
JR SKIPWHITE
;
; CHECK TO SEE IF CHAR PTED TO BY HL IS A DELIMITER
;
DLIMSCAN:
PUSH DE
EX DE,HL ;PT TO CHAR WITH DE
LD HL,DLIMS ;PT TO TABLE OF DELIMITERS
CALL DELIMCHS ;DO SCAN IN GENERAL
EX DE,HL ;PT TO CHAR WITH HL
LD A,(HL) ;GET CHAR IN A
POP DE
RET
;
; TABLE OF VALID DELIMITERS
;
DLIMS:
DB 1,1 ;SCAN 1 BYTE AT A TIME, AND SKIP 1 BYTE IF NO MATCH
DB ',' ;DELIMITERS ...
DB ':'
DB '+'
DB '-'
DB '/'
DB '*'
DB ' '
DB ')'
DB ';'
DB 0DH
DB 9 ; ... TO HERE
DB 0 ;END OF TABLE
;
; SCAN FOR DELIMITER -- RETURN WITH NZ IF NOT FOUND OR PT TO DELIMITER
; WITH Z IF FOUND; ON INPUT, TABLE PTED TO BY HL WITH 1ST 2 BYTES
; GIVING NUMBER OF BYTES TO CHECK AND NUMBER OF BYTES TO SKIP, RESP,
; ON EACH PARTIAL SCAN
;
DELIMCHS:
CALL SPCHSCAN ;DO SCAN OF TABLE
RET NZ ;NOT FOUND
LD C,B ;CHAR OFFSET COUNT IN BC
LD B,0
ADD HL,BC ;PT TO CHAR
SUB A ;SET ZERO FLAG
RET
;
; SCAN SPECIAL CHAR TABLE PTED TO BY HL FOR STRING PTED TO BY DE;
; NUMBER OF SIGNIFICANT BYTES TO SCAN AS FIRST ENTRY IN TABLE,
; NUMBER OF BYTES TO SKIP ON FAILURE AS 2ND ENTRY IN TABLE;
; TABLE ENDS IN A BINARY 0
;
SPCHSCAN:
LD B,(HL) ;B=NUMBER OF BYTES TO SCAN
INC HL
LD C,(HL) ;C=NUMBER OF BYTES TO SKIP ON FAILURE
INC HL ;PT TO FIRST VALID BYTE IN TABLE
;
; MAIN SCANNING LOOP
;
SPCH1:
LD A,(HL) ;CHECK FOR END OF TABLE
AND A ;ZERO?
JR Z,SPCH2 ;DONE IF SO
CALL COMPHLDE ;DO COMPARE
RET Z ;RETURN IF MATCH
LD A,C ;POINT TO NEXT TABLE ENTRY
CALL ADDHLA ;HL=HL+(SIZE OF TABLE ENTRY)
JR SPCH1
;
; NO MATCH -- RETURN NZ
;
SPCH2:
INC A ;A=1 AND NZ
RET
;
; COMPARE CHARS PTED TO BY DE WITH THAT PTED TO BY HL FOR B BYTES
; RET WITH ZERO FLAG SET IF COMPLETE MATCH, NZ IF NO MATCH;
; HL, DE, BC NOT AFFECTED
;
COMPHLDE:
PUSH HL ;SAVE REGS
PUSH DE
PUSH BC
CMPHD1:
LD A,(DE) ;GET DE CHAR
CP (HL) ;COMPARE TO HL CHAR
JR NZ,CMPHD2 ;NO MATCH
INC HL ;PT TO NEXT
INC DE
DJNZ CMPHD1 ;COUNT DOWN -- ZERO FLAG SET ON END
CMPHD2:
POP BC ;RESTORE REGS
POP DE
POP HL
RET
;
; HL=HL+A
;
ADDHLA:
ADD A,L ;DO IT
LD L,A
RET NC
INC HL
RET
;
; FILL MEMORY PTED TO BY DE WITH SPACES FOR BC BYTES
;
SPFILL:
LD A,' ' ;<SP>
LD (DE),A ;STORE FIRST <SP>
LD H,D ;MAKE HL PT TO 1ST <SP>
LD L,E
INC DE ;DE PTS TO NEXT BYTE
DEC BC ;BC IS 1 BYTE LESS
LDIR ;COPY USING LDIR
RET
;
; OUTPUT CHAR IN A TO DISK FILE
;
DOUTCHAR:
PUSH HL ;SAVE REGS
PUSH DE
PUSH BC
PUSH AF
LD HL,(OBUFPTR) ;GET ADDRESS OF NEXT CHAR POS IN OUT BUFFER
LD (HL),A ;STORE CHAR INTO OUT BUFFER
CP 9 ;CHECK FOR TAB
JR NZ,NOTABOUT ;NOT TAB -- DON'T UPDATE COUNT
LD A,(OBUFLPOS) ;TAB -- UPDATE LOCATION IN LINE
DEC A ;A=OUT BUFFER LINE POSITION - 1
AND 0F8H ;MASK FOR TAB
ADD A,9 ;AND ADD 9
JR DOUT1
; NOT A TAB -- JUST INCR POSITION COUNT
NOTABOUT:
LD A,(OBUFLPOS) ;GET ADDRESS OF NEXT CHAR POS IN OUT BUFFER
INC A ;ADD 1 TO IT
DOUT1:
LD (OBUFLPOS),A ;UPDATE OUT BUFFER LINE POSITION
INC HL ;INCREMENT BUFFER PTR
LD A,(OBUFBACKCNT) ;GET BUFFER BYTE COUNT
DEC A ;BUFFER NOW FULL?
JR NZ,DOUT2 ;CONTINUE IF NOT
LD DE,OBUF ;WRITE BUFFER TO DISK IF SO
LD C,1AH ;SET DMA ADDRESS
CALL BDOS
LD DE,FCBZ80 ;WRITE BLOCK
CALL WRITEBLK
LD HL,OBUF ;RESET OUTPUT BUFFER PTR TO 1ST BYTE
LD A,80H ;RESET BUFFER BYTE COUNT
DOUT2:
LD (OBUFPTR),HL ;UPDATE OUTPUT BUFFER PTR
LD (OBUFBACKCNT),A ;UPDATE BUFFER BYTE COUNT
POP AF ;RESTORE REGS
POP BC
POP DE
POP HL
RET
;
; WRITE BLOCK WHOSE FCB IS PTED TO BY DE TO DISK
;
WRITEBLK:
LD C,15H ;CP/M BDOS WRITE BLOCK
CALL BDOS
AND A ;ERROR?
RET Z ;OK IF NONE
LD DE,ERR1 ;ELSE PRINT ERROR MESSAGE AND ABORT
JP ENDERR
;
; FILL LAST BLOCK WITH ^Z AND CLOSE OUTPUT FILE
;
CTRLZFILL:
LD A,(OBUFBACKCNT) ;GET REMAINING COUNT
CP 80H ;FULL?
JR Z,CLOSEOUT ;CLOSE FILE THEN
LD A,1AH ;ELSE WRITE ^Z
CALL DOUTCHAR
JR CTRLZFILL
;
; CLOSE OUTPUT FILE
;
CLOSEOUT:
LD DE,FCBZ80 ;OUTPUT FCB
LD C,10H ;CLOSE FILE
JP BDOS
;
; EXTRACT NEXT INPUT LINE FOR DISK FILE AND PLACE IT AS A 0-TERMINATED
; STRING IN BUFFER 'INLN'
;
BUILDLINE:
CALL PDOT ;PRINT ACTIVITY DOT
XOR A ;A=FALSE OR 0
LD (INCMT),A ;TURN IN COMMENT FLAG OFF
LD (INQUOTE),A ;TURN IN QUOTE FLAG OFF
LD HL,INLN ;PT TO INLN BUFFER
LD B,80 ;80 CHARS MAX
;
; MAIN BUILD LOOP
;
NXTLCHAR:
LD DE,(IBUFPTR) ;PT TO NEXT CHAR IN FILE
LD A,(IBUFCNT) ;CHECK TO SEE IF BUFFER EMPTY
CP 80H ;80H IF SO
JR NZ,PUTCHAR ;NOT EMPTY, SO PLACE CHAR IN LINE
EXX ;SAVE REGS
LD DE,IBUFFER ;READ NEXT BLOCK FROM INPUT FILE
LD C,1AH ;SET DMA ADDRESS
CALL BDOS
LD DE,FCBASM ;READ THE BLOCK
LD C,14H
CALL BDOS
DEC A ;ERROR?
JP Z,ENDALL ;DONE IF SO (ASSUME EOF)
EXX ;GET REGS BACK
LD DE,IBUFFER ;SET PTR TO 1ST BYTE OF BLOCK
SUB A ;CHAR COUNT = 0
;
; PLACE CHAR PTED TO BE DE INTO INLN
;
PUTCHAR:
LD (IBUFCNT),A ;SAVE CHAR COUNT
LD A,(DE) ;GET CHAR
INC DE ;PT TO NEXT
LD (IBUFPTR),DE ;SAVE PTR
PUSH HL
LD HL,IBUFCNT ;INCR CHAR COUNT
INC (HL)
POP HL
CALL PCAPS ;CAPITALIZE CHAR OPTIONALLY
LD (HL),A ;SAVE CHAR FROM FILE INTO INLN
CP 0DH ;END OF LINE?
JR Z,ENDBLINE ;DONE IF SO
CP 9 ;TAB EXPAND?
JR Z,CONTBLINE ;PROCESS AS NORMAL CHAR IF SO
CP ' ' ;LESS THAN <SP>?
JR C,NXTLCHAR ;DON'T PROCESS IF SO
CONTBLINE:
DEC B ;IS BUFFER FULL?
INC HL ;PT TO NEXT CHAR IN INLN BUFFER
JR NZ,NXTLCHAR ;CONTINUE PROCESSING IF NOT FULL
INC B ;WRITE OVER LAST CHAR FOR REST OF LINE
DEC HL
JR NXTLCHAR ;CONTINUE
;
; OPTIONALLY CAPITALIZE CHAR IN A
;
PCAPS:
PUSH AF ;SAVE CHAR
LD A,(INCMT) ;IN A COMMENT?
OR A ;0=NO
JR NZ,PCAPS5 ;DONE IF SO AND DON'T CAPITALIZE
LD A,(INQUOTE) ;IN A QUOTE?
OR A ;0=NO
JR NZ,PCAPS1 ;DON'T CAPITALIZE IF SO
POP AF ;NOT IN COMMENT OR QUOTE, SO CAPITALIZE
CALL CAPS
JR PCAPS2
PCAPS1:
POP AF ;GET CHAR
PCAPS2:
CP ';' ;COMING INTO A COMMENT?
JR NZ,PCAPS3
PUSH AF ;SAVE CHAR
LD A,0FFH ;SET INCMT FLAG
LD (INCMT),A
JR PCAPS5 ;DONE
PCAPS3:
PUSH AF ;SAVE CHAR
LD A,(INQUOTE) ;IN A QUOTE?
OR A ;0=NO
JR Z,PCAPS4
POP AF ;GET CHAR -- WE ARE IN A QUOTE
PUSH AF ;SAVE IT AGAIN
CP '''' ;ARE WE LEAVING THE QUOTE?
JR NZ,PCAPS5
XOR A ;A=0
LD (INQUOTE),A ;YES, SO SET NOT IN QUOTE
JR PCAPS5
PCAPS4:
POP AF ;GET CHAR
PUSH AF ;SAVE CHAR ONE LAST TIME
CP '''' ;COMING INTO A QUOTE?
JR NZ,PCAPS5
LD A,0FFH ;SET INQUOTE FLAG
LD (INQUOTE),A
PCAPS5:
POP AF ;GET CHAR
RET ;DONE
;
; STORE ENDING <LF> AND <NULL>
;
ENDBLINE:
INC HL ;PT TO NEXT POSITION
LD (HL),0AH ;STORE <LF>
INC HL
LD (HL),0 ;STORE <NULL>
LD (IBUFPTR),DE ;SAVE INPUT FILE PTR
;
; IF LINE STARTS WITH AN ASTERISK (COMMENT LINE), MAKE IT START WITH A
; SEMICOLON
;
LD A,(INLN) ;LOOK AT FIRST CHAR
CP '*' ;ASTERISK?
JR NZ,ENDBL1
LD A,';' ;REPLACE WITH SEMICOLON
LD (INLN),A
;
; CHECK FOR EMPTY LINE AND JUST OUTPUT NEW LINE IF SO; ELSE RETURN
;
ENDBL1:
LD A,B ;LINE EMPTY?
SUB 80 ;START OVER IF SO
RET NZ ;DONE IF NOT EMPTY
LD A,0DH ;OUTPUT <CR> <LF> TO FILE FOR EMPTY LINE
CALL DOUTCHAR
LD A,0AH
CALL DOUTCHAR
JP BUILDLINE ;DO NEXT LINE
;
; CAPITALIZE CHAR IN A
;
CAPS:
AND 7FH ;MASK OUT MSB
CP 61H ;DO NOTHING IF LESS THAN SMALL A
RET C
CP 7AH+1 ;CAP IF BETWEEN SMALL A AND Z, RESP
RET NC
AND 5FH ;CAPITALIZE
RET
;
; END OF PROCESSING
;
ENDALL:
CALL CTRLZFILL ;FILL BUFFER WITH ^Z
LD DE,ERR5ON ;OPTIONALLY PRINT EACH ERROR MESSAGE IF SET
CALL PMSG
LD DE,XLT1ON
CALL PMSG
LD DE,XLT2ON
CALL PMSG
LD DE,XLT3ON
CALL PMSG
LD DE,XLT4ON
CALL PMSG
LD DE,MSG2
;
; PRINT MESSAGE PTED TO BY DE WITH PRECEEDING <CRLF> AND FINISH UP
;
ENDERR:
PUSH DE ;SAVE PTR
LD DE,CRLFSTR ;PRINT <CRLF>
CALL PMSG
POP DE
CALL PMSG ;PRINT MESSAGE
JP WBOOT ;DONE
;
; PRINT STRING PTED TO BY DE AND ENDING IN 0
;
PMSG:
LD A,(DE) ;GET CHAR
AND A ;ENDING 0?
RET Z ;DONE IF SO
CALL PCHAR ;OUTPUT CHAR IN A
INC DE ;PT TO NEXT CHAR
JR PMSG ;CONTINUE
;
; PRINT CHAR IN A ON CON:
;
PCHAR:
PUSH AF ;SAVE REGS
PUSH BC
PUSH DE
PUSH HL
LD E,A ;CHAR IN E
LD C,2 ;CON: OUTPUT
CALL BDOS
POP HL ;RESTORE REGS
POP DE
POP BC
POP AF
RET
;
; **** OP CODE TABLE, MESSAGE, AND BUFFER AREA ****
;
;
; OP CODE TABLES
;
OCS1:
DB 'ANI AND '
DB 'CMA CPL '
DB 'CMC CCF '
DB 'CPI CP '
DB 'HLT HALT '
DB 'JMP JP '
DB 'ORI OR '
DB 'RAL RLA '
DB 'RAR RRA '
DB 'RLC RLCA '
DB 'RRC RRCA '
DB 'STC SCF '
DB 'SUI SUB '
DB 'XRI XOR '
POPS:
DB 'DB DEFB '
DB 'DS DEFS '
DB 'DW DEFW '
DB 'SET DEFL '
NOXLT:
DB 'ENT ENTRY'
DB 'NAM NAME '
DB 'RAM DATA '
DB 'ROG REL '
DB 0 ;END OF TABLE FOR OCS 1
OCS2:
DB 'ANA AND '
DB 'CMP CP '
DB 'DCR DEC '
DB 'INR INC '
DB 'MVI LD '
DB 'ORA OR '
DB 'SUB SUB '
DB 'XRA XOR '
DB 0 ;END OF TABLE FOR OCS 2
OCS3:
DB 'DCX DEC '
DB 'INX INC '
DB 'LXI LD '
DB 'POP POP '
DB 'PUSH PUSH '
DB 0 ;END OF TABLE FOR OCS 3
OCS4:
DB 'REQ RNE RLT RGE CEQ '
DB ' CNE CLT CGE JEQ JNE '
DB ' JLT JGE '
DB 0 ;END OF TABLE FOR OCS 4
RETS:
DB 'RC RNC RZ RNZ RP '
DB ' RM RPE RPO '
DB 0 ;END OF TABLE FOR RETS
CALLS:
DB 'CC CNC CZ CNZ CP '
DB ' CM CPE CPO '
DB 0 ;END OF TABLE FOR CALLS
JMPS:
DB 'JC JNC JZ JNZ JP '
DB ' JM JPE JPO '
DB 0 ;END OF TABLE FOR JMPS
OCS8:
DB 'DAD ADD '
DW DO81
DB 'ADD ADD '
DW DO82
DB 'ADC ADC '
DW DO82
DB 'SBB SBC '
DW DO82
DB 'ADI ADD '
DW DO82
DB 'ACI ADC '
DW DO82
DB 'SBI SBC '
DW DO82
DB 'IN IN '
DW DO83
DB 'LDA LD '
DW DO83
DB 'LDAX LD '
DW DO84
DB 'LHLD LD '
DW DO85
DB 'MOV LD '
DW DO86
DB 'PCHL JP '
DW DO88
DB 'RST RST '
DW DO89
DB 'SHLD LD '
DW DO8A
DB 'SPHL LD '
DW DO8B
DB 'STA LD '
DW DO8C
DB 'OUT OUT '
DW DO8C
DB 'STAX LD '
DW DO8D
DB 'XCHG EX '
DW DO8E
DB 'XTHL EX '
DW DO8F
NOXLT2:
DB 'IFC IF '
DW DO91
DB 'ICL *INCL'
DW DO92
DB 'LST LIST '
DW DO93
DB 'MAC MACRO'
DW DO94
DB 0 ;END OF TABLE FOR OCS8 AND NOXLT2
;
; VARIOUS MESSAGES AND PROGRAM HEADER
;
HEADER:
DB 'XLATE2 -- 8080-to-Z80 Translator, Version '
DB VERS/10+'0','.',(VERS MOD 10)+'0'
DB 0DH,0AH,0
; HELP MESSAGES
HMSG1:
DB 0DH,0AH,0AH
DB ' XLATE2 translates 8080 assembly language source',0DH,0AH
DB 'code into Zilog-Standard Z80 assembly language',0DH,0AH
DB 'source code. It is invoked by a command of the',0DH,0AH
DB 'following form:',0DH,0AH,0AH
DB ' XLATE2 d:SRCFILE.typ d:destfile.typ',0DH,0AH,0AH
DB ' All characters in lower case are optional, and,',0DH,0AH
DB 'if omitted, the following values are assumed:',0DH,0AH,0AH
DB ' . The Source File will have a type of ASM',0DH,0AH
DB ' . The Destination File will have the same name',0DH,0AH
DB ' as the Source File',0DH,0AH
DB ' . The Destination File will have a type of MAC',0DH,0AH,0AH
DB 'Type <RETURN> to Continue - ',0
HMSG2:
DB 0DH,0AH,0AH
DB 'The following are examples of its use:',0DH,0AH,0AH
DB ' XLATE2 DEMO1 <-- Translates DEMO1.ASM to DEMO1.MAC'
DB 0DH,0AH
DB ' XLATE2 DEMO1 DEMO2 <-- DEMO1.ASM to DEMO2.MAC'
DB 0DH,0AH
DB ' XLATE2 DEMO1.TXT DEMO2.GGG <-- DEMO1.TXT to DEMO2.GGG'
DB 0DH,0AH,0AH
DB 'The following functions are also performed by XLATE2:'
DB 0DH,0AH,0AH
DB ' . The M80 Pseudo-Ops .Z80 and ASEG will be inserted '
DB 'at the front',0DH,0AH
DB ' of the MAC File',0DH,0AH
DB ' . The text in the Destination File will be '
DB 'capitalized',0DH,0AH
DB ' . All comment lines beginning with an asterisk will '
DB 'begin with',0DH,0AH
DB ' a semicolon instead',0DH,0AH,0AH
DB 0
; FILE NAME MESSAGES
PRFNM1:
DB 'Source File: ',0
PRFNM2:
DB ' Destination File: ',0
; FIRST TWO LINES OF MAC FILE
FHDR:
DB 9,'.Z80',0DH,0AH ;USE ZILOG MNEMONICS
DB 9,'ASEG',0DH,0AH ;USE ABSOLUTE SEGMENTS
DB 0
ERR1:
DB 'Output File Write Error',0DH,0AH,7,0
ERR2:
DB 'No Source File Found',0DH,0AH,7,0
ERR3:
DB 'No Directory Space',0DH,0AH,7,0
ERR4:
DB 'Output File Already Exists -- Delete It and Continue (Y/N)? '
DB 0
ERR4A:
DB 'XLATE2 Aborting to CP/M',0
MSG2:
DB 'XLATE2 Processing Complete',0
CRLFSTR:
DB 0DH,0AH,0
;
; VARIOUS ERROR MESSAGES
;
ERR5ON:
DB 0 ;THIS BYTE IS SET TO <CR> IF STRING ENABLED
ERR5:
DB 0AH
DB 'The following pseudo-ops '
DB 'have been used in your source '
DB 'and have not',0DH,0AH
DB 'been '
DB 'fully translated. You must '
DB 'complete the translation '
DB 'using an editor.',0DH,0AH
DB 9,'Original:',9,9,'Must Be Translated To:',0DH,0AH
DB 0 ;END OF STRING
XLT1ON:
DB 0 ;THIS BYTE IS SET TO <TAB> IF STRING ENABLED
XLT1:
DB '#ENDIF',9,9,9,'ENDIF',0DH,0AH,0
XLT2ON:
DB 0 ;THIS BYTE IS SET TO <TAB> IF STRINGENABLED
XLT2:
DB 'ICL',9,9,9,'*INCLUDE',0DH,0AH,0
XLT3ON:
DB 0 ;THIS BYTE IS SET TO <TAB> IF STRING ENABLED
XLT3:
DB 'LST <operands>',9,9,'LIST <valid ASMB operands>'
DB 0DH,0AH,0
XLT4ON:
DB 0 ;THIS BYTE IS SET TO <TAB> IF STRING ENABLED
XLT4:
DB 'MAC <$parameters>',9,'MACRO <#parameters>',0DH,0AH
DB 9,'[ ... ]',9,9,9,'MEND',0DH,0AH
DB 9,'#macro-call',9,9,'macro-call',0DH,0AH,0
;
; INPUT FILE FCB
;
FCBASM:
DB 0,0,0,0,0,0,0,0,0,'ASM',0
DB 0,0,0,0,0,0,0,0,0,0,0,0,0
DB 0,0,0,0,0,0,0
;
; OUTPUT FILE FCB
;
FCBZ80:
DB 0,0,0,0,0,0,0,0,0,'MAC',0
DB 0,0,0,0,0,0,0,0,0,0,0,0,0
DB 0,0,0,0,0,0,0
;
; BUFFERS
;
; STACK AREA
DS 128
; CURRENT POSITION IN LINE OF OUTPUT BUFFER
OBUFLPOS:
DS 1
; COUNTER FOR EVERY 10 LINES
LCOUNT:
DS 1
; COUNTER FOR EVERY 60*10 LINES
NLCOUNT:
DS 1
; IN COMMENT FLAG -- 0 MEANS NOT
INCMT:
DS 1
; IN QUOTE FLAG -- 0 MEANS NOT
INQUOTE:
DS 1
; PTR TO TARGET OP CODE IN INPUT LINE
ILTOP:
DS 2
; OP CODE TO MATCH AGAINST
TARGOP:
DS 5
; PTR TO CURRENT POSITION IN CURRENT INPUT LINE
INLNPTR:
DS 2
; PTR TO CURRENT POSITION IN OUTPUT BUFFER (BLOCK)
OBUFPTR:
DS 2
; COUNT OF CHARS REMAINING IN OUTPUT BUFFER
OBUFBACKCNT:
DS 1
; OUTPUT BUFFER (BLOCK)
OBUF:
DS 128
; CURRENT INPUT LINE BUFFER
INLN:
DS 80 ;80 CHARS IN LINE
DS 3 ;3 EXTRA FOR <CR> <LF> <NULL>
; PTR TO CURRENT POSITION IN INPUT BUFFER
IBUFPTR:
DS 2
; COUNT OF NUMBER OF CHARS LEFT IN INPUT BUFFER
IBUFCNT:
DS 1
; INPUT BUFFER (BLOCK)
IBUFFER:
DS 128
END