home *** CD-ROM | disk | FTP | other *** search
Text File | 1988-01-08 | 38.5 KB | 2,470 lines |
-
- ; UCASM Micro-controller Assembler
- ; copyright (c) 1987, 1988 by J. L. Post
- ; This file MUST be accompanied by UCASM.DOC - Please read it
- ;
- ; Version 1.2 - Dec/21/87
- ; added line number in error reports
- ; Version 1.1 - Dec/18/87
- ; added DB, DW, and DS as equivalents of DEFB, DEFW, and DEFS
- ; added operators <, >, and ^ for shift left, shift right, and
- ; control character definition. Also check for divide by zero.
- ; Version 1.0 - first release Dec/13/87
- ;
- ; Assembles code for the following micro-controllers:
- ;
- ; ROM (E = eprom)
- ; 1K 2K 4K External
- ;-----------------------------------------------
- ; RAM 64 8021 * 8035
- ; (bytes) 8041 *
- ; 8048
- ; 8741 (E) *
- ; 8748 (E)
- ;-----------------------------------------------
- ; 128 8041 * 8049 8039
- ; 8741 (E) *
- ;-----------------------------------------------
- ; 256 8042 8050 8040
- ; 8742 (E)
- ;-----------------------------------------------
- ;
- ; * 8021 is a 28 pin chip that supports a subset of 8035 code.
- ; 8041/8741 are listed twice because the NEC chip has only 64
- ; bytes of internal ram, while the Intel chip has 128 bytes
- ; (at least that's what the spec sheets say.)
- ;
- VER EQU 1 ; Version number
- REV EQU 2 ; Revision number
- ;
- TAB EQU 9
- CR EQU 13
- LF EQU 10
- CTRLZ EQU 1AH ; Control Z
- ESC EQU 1BH ; Escape
- QUOTE EQU 27H ; ASCII single quote (')
- CARAT EQU 5EH ; Control char definition (^)
- ;
- BOOT EQU 0
- BDOS EQU 5
- FCB EQU 5CH
- ;
- ;
- ORG 100H
- ;
- JR START
- ;
- ;
- HEXOPT: DEFB 0 ; 0 if no FILE.HEX output
- LSTOPT: DEFB 0 ; 0 if no FILE.LST output
- LSTTYP: DEFB 'LST' ; Default list file type
- HEXTYP: DEFB 'HEX' ; Default object file type
- MAXERR: DEFB 10 ; Maximum error count before abort
- PAGLEN: DEFB 0 ; List page length (0 if no paging, usually 66)
- DEFB 0 ; Lines printed per page (suggest 60)
- SRCTYP: DEFB 'Z80' ; Default source file type
- ;
- ; HEXOPT and LSTOPT can be modified at run time by the H or L options
- ;
- START: LD SP,STACK
- LD HL,IMSG ; Say hello
- CALL PRINT
- CALL INIT ; Init fcb's and options
- CALL GETSRC ; Read in source file
- JR C,RDERR ; Abort if read error
- CALL ASM ; Do the assembly
- CALL DCRLF
- LD BC,(BYTCNT) ; Show how many bytes in object code
- CALL PDEC
- LD HL,DONMSG ; Points to 'byte' text
- CALL DUALP ; Print to console and/or list file
- LD BC,(BYTCNT)
- LD A,B
- OR A
- JR NZ,END1 ; Go if object byte count > 256
- LD A,C
- DEC A
- JR Z,END2 ; Go if byte count = 1
- ;
- END1: LD A,'s' ; Else append 's'
- CALL DCHR ; Output to console and/or list file
- ;
- END2: LD A,','
- CALL DCHR
- LD A,' '
- CALL DCHR
- LD A,(ERRCNT) ; Show error count
- LD C,A
- LD B,0
- CALL PDEC
- CALL DUALP
- LD A,(ERRCNT)
- DEC A
- JR Z,EXIT
- LD A,'s'
- CALL DCHR
- ;
- EXIT: LD A,(FILFLG) ; Test if any files open
- OR A
- JR Z,EXIT1 ; Go if none opened
- AND 1
- CALL NZ,CLSHEX ; Close open hex file
- LD A,(FILFLG)
- AND 4
- CALL NZ,CLSLST ; Close open list file
- ;
- EXIT1: JP BOOT ; Exit to system
- ;
- RDERR: LD HL,RDERMS ; Source file read error
- CALL PRINT
- JR EXIT
- ;
- CLSHEX: LD A,(HEXFLG) ; Close .HEX object file
- AND 80H
- CALL NZ,HEXDMP ; Clear record buffer
- LD HL,LASTHR ; Set last hex record
- ;
- CLSHX1: LD A,(HL)
- INC HL
- OR A
- JR Z,CLSHX2
- CALL HEXOUT
- JR CLSHX1
- ;
- CLSHX2: LD A,(FILFLG)
- AND 2
- CALL NZ,FLSHEX ; Flush hex buffer
- LD DE,FCB1
- JR CLOSE ; Close file
- ;
- CLSLST: LD A,(FILFLG) ; Close open list file
- AND 8
- CALL NZ,FLSLST ; Flush list buffer
- LD DE,FCB2 ; And close file
- ;
- CLOSE: PUSH HL ; Close open files
- LD C,16
- CALL BDOS
- POP HL
- RET
- ;
- ; Flush data out of open buffers
- ;
- FLSHEX: PUSH HL
- LD DE,(HEXDMA) ; Set transfer address
- CALL SETDMA
- LD HL,(HEXDMA)
- LD DE,FCB1
- LD BC,(HEXOFF) ; Get byte count
- JR FLSLS0
- ;
- FLSLST: PUSH HL
- LD DE,(LSTDMA)
- CALL SETDMA
- LD HL,(LSTDMA)
- LD DE,FCB2
- LD BC,(LSTOFF)
- FLSLS0: ADD HL,BC
- ;
- FLSLS1: BIT 7,C
- JR NZ,WRITE
- LD (HL),CTRLZ ; Fill extra space with control Z
- INC HL
- INC C
- JR FLSLS1
- ;
- WRITE: LD C,21 ; Write record to file
- CALL BDOS
- POP HL
- RET
- ;
- LASTHR: DEFB ':00000001FF',0
- ;
- ; Initialize FCBs and options
- ;
- INIT: LD A,(FCB+9) ; See if file type specified
- CP ' '
- JR NZ,INIT1
- LD HL,SRCTYP ; Set default file type
- LD DE,FCB+9
- LD BC,3
- LDIR
-
- INIT1: LD HL,FCB1
- LD DE,FCB1+1
- LD BC,72
- LD (HL),0 ; Clear output fcbs
- LDIR
- LD HL,FCB
- LD DE,FCB1
- LD BC,9
- LDIR
- LD HL,HEXTYP ; Init object file fcb
- LD BC,3
- LDIR
- LD HL,FCB
- LD DE,FCB2
- LD BC,9
- LDIR
- LD HL,LSTTYP ; Init list file FCB
- LD BC,3
- LDIR
- LD HL,FCB+17 ; Point to auxiliary FCB for options
- ;
- INIT2: LD A,(HL)
- INC HL
- CP 21H
- RET C
- CP 'H'
- JR Z,INIT3
- CP 'L'
- JR NZ,INIT2
- LD (LSTOPT),A ; Set list file option
- JR INIT2
- ;
- INIT3: LD (HEXOPT),A ; Set .HEX file option
- JR INIT2
- ;
- ; Read in source file
- ;
- GETSRC: LD DE,IBFR ; Set DMA address
- LD (IBFRP),DE ; Set input buffer pointer
- LD (IBFEND),DE ; Flag end of input buffer
- CALL SETDMA
- LD DE,FCB ; Attempt to open file
- CALL OPNFIL
- RET C ; Abort if error
- ;
- GTSRC1: LD DE,FCB
- LD C,20
- CALL BDOS ; Read record
- OR A
- JR NZ,GTSRC2 ; Go if done
- LD HL,(IBFEND) ; Else updata DMA address
- LD BC,128
- ADD HL,BC
- LD (IBFEND),HL ; Update buffer end address
- LD D,H
- LD E,L
- CALL SETDMA ; Update transfer address
- JR GTSRC1
- ;
- GTSRC2: LD HL,(IBFEND) ; Test for empty file
- LD DE,IBFR
- INC DE
- SBC HL,DE
- RET C ; Abort with error if file empty
- LD A,(IBFR) ; Get first character
- CP CTRLZ
- JR Z,GTSRC3 ; Error if end of file char
- LD HL,(IBFEND)
- INC HL
- INC HL
- LD (SYMTAB),HL ; Initialize symbol table pointers
- LD (SYMEND),HL
- LD (SYMPTR),HL
- LD (HL),0 ; Disable garbage in symbol table
- OR A ; By setting terminator byte
- RET
- ;
- GTSRC3: SCF ; Flag error and return
- RET
- ;
- HEXOPN: LD A,(FILFLG) ; Open .HEX file, if optioned
- OR 1
- LD (FILFLG),A
- LD DE,FCB1
- LD (FCBTMP),DE
- JR OPEN
- ;
- LSTOPN: LD A,(FILFLG) ; Open list file, if optioned
- OR 4
- LD (FILFLG),A
- LD DE,FCB2
- LD (FCBTMP),DE
- ;
- OPEN: LD DE,(FCBTMP)
- CALL OPNFIL ; Attempt to open file
- JR C,OPEN1 ; Go if doesn't exist
- LD DE,(FCBTMP)
- LD C,19
- CALL BDOS ; Else kill it (ouch!)
- ;
- OPEN1: LD DE,(FCBTMP)
- LD C,22
- CALL BDOS ; Make new file
- INC A ; Z set if error
- RET
- ;
- OPNFIL: LD C,15
- CALL BDOS
- INC A
- JR Z,OPNFL1 ; Go if can't open file
- XOR A
- RET
- ;
- OPNFL1: SCF ; Open file error return
- RET
- ;
- SETDMA: PUSH HL ; Set dma transfer address in DE
- PUSH BC
- LD C,26
- CALL BDOS
- POP BC
- POP HL
- RET
- ;
- ; End of Assembly Pass Processing
- ;
- ASMDON: LD HL,IBFR
- LD (IBFRP),HL ; Reset input buffer pointer
- LD HL,0
- LD (PC),HL ; Reset program counter
- LD (LINUM),HL ; Clear line number
- LD A,(PASS)
- INC A
- LD (PASS),A ; Update pass number
- CP 2
- RET NC
- DEC A
- JR NZ,ASM ; Go if pass 1
- LD A,(HEXOPT)
- OR A
- JR Z,ASMDN1 ; Go if no object file option
- LD HL,(SYMEND)
- INC H
- LD (HEXDMA),HL ; Set address of hex file buffer
- CALL HEXOPN ; Open hex file
- LD HL,HEXTYP
- JR Z,OPNERR ; Go if can't open object file
- ;
- ASMDN1: LD A,(LSTOPT)
- OR A
- JR Z,ASM ; Go if no list file option
- LD HL,(SYMEND)
- INC H
- INC H
- LD (LSTDMA),HL ; Set address of list file buffer
- CALL LSTOPN ; Open list file
- LD HL,LSTTYP
- JR NZ,ASM ; Go if open ok
- ;
- OPNERR: EX DE,HL ; Can't open file
- LD HL,OPNEMS ; Report error
- CALL PRINT
- LD B,3
- ;
- OPNER1: LD A,(DE) ; Show type of file
- CALL CHROUT
- INC DE
- DJNZ OPNER1
- CALL PRINT
- JP EXIT ; Then abort
- ;
- ; Assemble source code
- ;
- ASM: XOR A
- LD (ERRFLG),A ; Clear error flag
- LD (OCLEN),A ; And opcode length
- LD HL,(LINUM)
- INC HL
- LD (LINUM),HL
- CALL GETLIN ; Get next line into buffer
- CP CTRLZ
- JR Z,ASMDON ; Go if end of file
- LD HL,LINBFR
- LD A,(HL)
- CP CTRLZ
- JR Z,ASMDON ; Go if end of file
- CP CR
- JP Z,ASMRET ; Ignore empty line
- CP TAB
- JR Z,ASM1 ; Go if no label
- CP ' '
- JR Z,ASM1 ; Ditto
- CP ';'
- JP Z,ASMRET ; Go if comment line
- LD A,(PASS)
- OR A
- JR NZ,ASM01 ; Go if pass two
- PUSH HL ; Else enter label in symbol table
- CALL FNDSYM ; See if already exists
- EX DE,HL ; Put pointer in DE
- POP HL
- JR NZ,ASM0 ; Go if entry not found
- LD A,3
- LD (ERRFLG),A ; Else flag multi def label error
- EX DE,HL
- ;
- ASM00: DEC HL
- LD A,(HL)
- CP ' '
- JR NC,ASM00 ; Find byte count
- SET 7,(HL) ; Flag as multiple for pass 2
- JP ASMERR
- ;
- ASM0: PUSH HL
- CALL ENTSYM ; Enter into symbol table
- DEC HL ; Point to value
- DEC HL
- LD BC,(PC) ; Get program counter
- LD (HL),C
- INC HL
- LD (HL),B
- POP HL
- ;
- ASM01: CALL SKPLBL ; Skip over label
- ;
- ASM1: CALL NEXTF ; Point to next field
- LD A,1
- LD (ERRFLG),A
- CALL LOOKUP ; Find entry in opcode table
- JR C,ASMER ; Go if not found
- XOR A
- LD (ERRFLG),A
- ;
- ; Opcode entry found in table, DE => opcode in table
- ;
- CALL SKPLBL ; Skip past mnemonic
- CALL NEXTF ; Point HL to next field
- LD A,(DE)
- LD (OPCODE),A ; Set base opcode
- LD A,(MAXTYP)
- LD B,A
- INC DE
- LD A,(DE) ; Get group type
- BIT 7,A
- JR NZ,PSUDO ; Go if pseudo op
- DEC A
- CP B
- JR NC,ASMERR ; Go if error
- LD C,A
- LD B,0
- LD IX,GRPTBL ; Point to routine entry table
- ADD IX,BC
- ADD IX,BC
- LD C,(IX+0) ; Get address of routine
- LD B,(IX+1)
- PUSH BC
- POP IX
- ;
- ASM2: LD IY,ASMRET ; Set return address on stack
- PUSH IY
- JP (IX) ; Execute routine
- ;
- PSUDO: AND 7
- PUSH HL
- LD HL,PSUDTB ; Get pseudo op table entry
- ADD A,A
- LD C,A
- LD B,0
- ADD HL,BC
- LD A,(HL)
- INC HL
- LD H,(HL)
- LD L,A
- PUSH HL
- POP IX
- POP HL
- JR ASM2
- ;
- ASMER:
- ASMERR: LD A,(ERRFLG)
- ADD A,A
- LD C,A
- LD B,0
- XOR A
- LD (ERRFLG),A ; Clear error
- LD A,C
- CP 6
- JR Z,ASMER1 ; Go if multiple label def
- LD A,(PASS)
- OR A
- JR Z,ASMRET ; No error msg or update in pass 1
- ;
- ASMER1: LD HL,ERRMSG
- CALL DUALP
- LD HL,ERRTBL
- ADD HL,BC
- LD A,(HL)
- INC HL
- LD H,(HL)
- LD L,A
- CALL DUALP
- LD HL,LINMSG
- CALL DUALP
- LD BC,(LINUM)
- CALL PDEC
- CALL DCRLF
- LD HL,LINBFR
- CALL PRINT
- CALL UPERCT ; Update error counter
- XOR A
- ;
- ASMRET: JR C,ASMERR ; Go if subroutine error
- LD A,(ERRFLG)
- OR A
- JR NZ,ASMERR
- LD A,(PASS)
- OR A
- JR Z,ASMR1 ; Go if first pass
- LD A,(HEXOPT)
- OR A
- CALL NZ,HEXWR ; Go if hex output required
- LD A,(LSTOPT)
- OR A
- CALL NZ,LSTWR ; Go if list output required
- ;
- ASMR1: LD A,(OCLEN) ; Update program counter
- LD HL,(PC)
- LD C,A
- LD B,0
- ADD HL,BC
- LD (PC),HL
- LD A,(PASS)
- OR A
- JP Z,ASM ; No update byte count on pass 1
- LD HL,(BYTCNT)
- ADD HL,BC
- LD (BYTCNT),HL
- JP ASM
- ;
- ; Find mnemonic in opcode table
- ; On entry HL => start of linebfr opcode
- ; On exit DE => opcode in opcode table, C set if not found
- ;
- LOOKUP: LD DE,OPTBL
- ;
- LOOK1: LD A,(DE)
- AND 7
- JR NZ,LOOK2
- SCF
- RET
- ;
- LOOK2: LD B,A
- PUSH HL
- INC DE
- CALL CPSTRG ; Compare strings
- LD A,(HL) ; Check if source end
- POP HL
- JR Z,LOOK5 ; Go if match
- ;
- LOOK3: INC DE ; Skip to end of mnemonic
- DJNZ LOOK3
- ;
- LOOK4: INC DE ; Skip over code and group
- INC DE
- JR LOOK1
- ;
- LOOK5: CP 21H
- JR NC,LOOK4 ; Go if not full match
- XOR A
- RET
- ;
- CPSTRG: LD A,(DE)
- CP (HL)
- RET NZ
- INC HL
- INC DE
- DJNZ CPSTRG
- RET
- ;
- GETLIN: LD HL,(IBFRP) ; Get input buffer pointer
- LD DE,LINBFR
- LD (LINBFP),DE ; Init line buffer pointer
- LD B,80 ; Max char count per line
- ;
- GTLIN1: LD A,(HL)
- CP CTRLZ
- RET Z ; Done if end of file
- LD (DE),A ; Store in line buffer
- INC DE
- INC HL
- CP LF
- JR Z,GTLIN2 ; Do for entire line
- DJNZ GTLIN1
- ;
- GTLIN2: XOR A
- LD (DE),A ; Flag end of line
- LD (IBFRP),HL ; Update input buffer pointer
- RET
- ;
- ; Print decimal value in BC, suppress leading zeros
- ;
- PDEC: PUSH HL
- PUSH DE
- LD H,B
- LD L,C
- LD C,0
- LD DE,1000
- CALL PDECS
- LD DE,100
- CALL PDECS
- LD DE,10
- CALL PDECS
- LD A,L
- OR 30H
- CALL DCHR
- POP DE
- POP HL
- RET
- ;
- PDECS: LD B,0
- ;
- PDECS1: INC B
- SBC HL,DE
- JR NC,PDECS1
- DEC B
- ADD HL,DE
- LD A,B
- OR A
- JR NZ,PDECS2
- BIT 0,C
- RET Z
- ;
- PDECS2 SET 0,C
- OR 30H
- JR DCHR
- ;
- DUALP: LD A,(PASS)
- OR A
- JR Z,PRINT
- LD A,(LSTOPT)
- OR A
- JR Z,PRINT
- PUSH HL
- PUSH BC
- ;
- DUALP1: LD A,(HL)
- INC HL
- OR A
- JR Z,DUALP2
- CALL PUTLST
- JR DUALP1
- ;
- DUALP2: POP BC
- POP HL
- ;
- PRINT: LD A,(HL)
- INC HL
- OR A
- RET Z
- CALL CHROUT
- JR PRINT
- ;
- DCRLF: LD A,(PASS)
- OR A
- JR Z,CRLF
- LD A,(LSTOPT)
- OR A
- JR Z,CRLF
- PUSH HL
- PUSH BC
- LD A,CR
- CALL PUTLST
- LD A,LF
- CALL PUTLST
- POP BC
- POP HL
- ;
- CRLF: LD A,CR
- CALL CHROUT
- LD A,LF
- ;
- CHROUT: PUSH HL
- PUSH DE
- PUSH BC
- PUSH AF
- LD E,A
- LD C,6
- CALL BDOS
- POP AF
- ;
- SYSRET: POP BC
- POP DE
- POP HL
- RET
- ;
- DCHR: CALL CHROUT
- PUSH AF
- LD A,(PASS)
- OR A
- JR Z,DCHRX
- LD A,(LSTOPT)
- OR A
- JR Z,DCHRX
- POP AF
- PUSH AF
- PUSH HL
- PUSH BC
- CALL PUTLST
- POP BC
- POP HL
- ;
- DCHRX: POP AF
- RET
- ;
- ; Multiply BC * DE, product in BC
- ;
- MULT: PUSH HL
- PUSH DE
- LD HL,0
- LD A,16 ; Loop count
- ;
- MULT1: ADD HL,HL ; Shift partial product
- EX DE,HL
- ADC HL,HL ; Shift partial prod with carry
- EX DE,HL
- JR NC,MULT2
- ADD HL,BC
- JR NC,MULT2
- INC DE
- ;
- MULT2: DEC A
- JR NZ,MULT1
- LD C,L
- LD B,H
- POP DE
- POP HL
- RET
- ;
- ; Divide DE / BC, quotient in DE remainder in BC
- ;
- DIV: LD A,B
- OR C
- JP Z,INVOPD ; Can't divide by 0
- PUSH HL
- LD HL,0
- LD A,16
- ;
- DIV1: EX DE,HL
- ADD HL,HL
- EX DE,HL
- ADC HL,HL
- INC DE
- OR A
- SBC HL,BC
- JR NC,DIV2
- DEC DE
- ADD HL,BC
- ;
- DIV2: DEC A
- JR NZ,DIV1
- LD C,L
- LD B,H
- POP HL
- RET
- ;
- KBSCAN: PUSH HL
- PUSH DE
- PUSH BC
- LD E,0FFH
- LD C,6
- CALL BDOS
- AND 7FH
- JR SYSRET
- ;
- ROTATE: RLCA
- RLCA
- RLCA
- RLCA
- RET
- ;
- ; Skip to next field in line buffer
- ;
- NEXTF: LD A,(HL)
- CP CTRLZ
- RET Z
- CP ' '
- JR Z,NEXTF1
- CP TAB
- RET NZ
- ;
- NEXTF1: INC HL
- JR NEXTF
- ;
- ; Skip to next operand in line buffer
- ;
- NEXTOP: LD A,(HL)
- CP CTRLZ
- RET Z
- CP ' '
- JR Z,NEXTO1
- CP TAB
- JR Z,NEXTO1
- CP ','
- RET NZ
- ;
- NEXTO1: INC HL
- JR NEXTOP
- ;
- UPERCT: LD A,(MAXERR)
- PUSH BC
- LD B,A
- LD A,(ERRCNT)
- INC A
- CP B
- POP BC
- JR NC,UPERC1
- LD (ERRCNT),A
- RET
- ;
- UPERC1: LD HL,AWCRAP
- CALL PRINT
- JP EXIT
- ;
- PSUDTB: DEFW PSEQU
- DEFW PSORG
- DEFW PSDFB
- DEFW PSDFW
- DEFW PSDFS
- DEFW PSEND
- DEFW PSINV
- DEFW PSINV
- ;
- PSINV: SCF ; Invalid pseudo-op
- ;
- PSEND: RET ; Ignore end pseudo-op
- ;
- PSDFB: LD IY,OCLEN
- LD IX,OPCODE
- ;
- PSDB0: LD A,(HL)
- CP QUOTE
- JR Z,PSDB3 ; Go if ASCII literal
- ;
- PSDB1: CALL EXP
- INC (IY+0)
- LD A,(NUMBER)
- LD (IX+0),A
- INC IX
- ;
- PSDB2: LD A,(HL)
- INC HL
- CP ','
- JR Z,PSDB0
- OR A
- RET
- ;
- PSDB3: INC HL
- INC HL
- LD A,(HL)
- DEC HL
- DEC HL
- CP QUOTE
- JR Z,PSDB1 ; Go if single ascii literal
- INC HL ; Else assume it's a string
- ;
- PSDB4: LD A,(HL)
- INC HL
- CP CR
- RET Z
- CP QUOTE
- JR Z,PSDB2
- LD (IX+0),A
- INC IX
- INC (IY+0)
- JR PSDB4
- ;
- PSDFS: CALL EXP
- PUSH HL
- LD HL,(PC)
- LD BC,(NUMBER)
- ADD HL,BC
- LD (PC),HL
- POP HL
- JR PSORGX
- ;
- PSORG: CALL EXP
- LD BC,(NUMBER)
- LD (PC),BC
- ;
- PSORGX: LD A,(HEXFLG)
- OR 40H ; Set bit 6
- LD (HEXFLG),A ; Flag skip in hex record
- XOR A
- LD (OCLEN),A
- RET
- ;
- PSDFW: CALL EXP
- LD BC,(NUMBER)
- LD A,C
- LD C,B ; Reverse order of bytes
- LD B,A
- LD (OPCODE),BC
- LD A,(OCLEN)
- ADD A,2
- LD (OCLEN),A
- OR A
- RET
- ;
- ; EQU - enter label in symbol table
- ;
- PSEQU: LD A,(PASS) ; On first pass only
- OR A
- RET NZ
- CALL EXP
- PUSH HL
- LD HL,(SYMEND) ; Better be last symbol entered
- DEC HL
- DEC HL
- LD BC,(NUMBER)
- LD (HL),C
- INC HL
- LD (HL),B
- POP HL
- OR A
- RET
- ;
- MAXTYP: DEFB 15
- ;
- GRPTBL: DEFW GROUP1 ; Single byte, no options
- DEFW GROUP2 ; Jumps
- DEFW GROUP3 ; Call
- DEFW GROUP4 ; Clr cpl
- DEFW GROUP5 ; En dis
- DEFW GROUP6 ; Sel
- DEFW GROUP7 ; Strt
- DEFW GROUP8 ; Mov
- DEFW GROUP9 ; Dec inc
- DEFW GROUPA ; Movd
- DEFW GROUPB ; Add addc anl anld orl orld xrl
- DEFW GROUPC ; In
- DEFW GROUPD ; Outl
- DEFW GROUPE ; Movx
- DEFW GROUPF ; Xch xchd
- ;
- ; Group 1 - single byte opcodes, no options
- ;
- GROUP1: LD A,1
- LD (OCLEN),A
- OR A
- RET
- ;
- ; Group 2 - double byte opcodes, second byte = address (jumps)
- ;
- GROUP2: LD A,2
- LD (OCLEN),A
- LD A,(OPCODE) ; Get base opcode
- AND 0FH
- CP 2
- JR Z,GRP2A ; Go if jbx
- CP 6
- JR Z,GRP2A ; Go if conditional jumps
- CP 4
- JR Z,GRP2B ; Go if jmp or call
- LD A,(HL) ; Else djnz, get register
- CP 'R'
- JP NZ,INVOPD ; Go if not valid
- INC HL
- LD A,(HL)
- INC HL
- SUB 30H
- JP C,INVOPD
- CP 8
- JP NC,INVOPD
- LD B,A
- LD A,(OPCODE)
- OR B
- LD (OPCODE),A ; Set register in opcode
- LD A,(HL)
- CP ','
- JP NZ,INVOPD
- INC HL
- ;
- GRP2A: CALL EXP ; Conditional jumps & jBX
- LD A,(NUMBER+1)
- LD B,A
- LD A,(PC+1)
- CP B
- JR Z,GRP2X
- LD A,4
- LD (ERRFLG),A
- SCF
- RET
- ;
- GRP2X: LD A,(NUMBER)
- LD (OPCODE+1),A
- OR A
- RET
- ;
- GRP2B: CALL EXP ; Jump
- LD A,(NUMBER+1)
- AND 7
- RRCA
- RRCA
- RRCA
- OR 4
- LD (OPCODE),A
- JR GRP2X
- ;
- ; Group 3 - calls, second byte = A0 - A7
- ;
- GROUP3: LD A,2
- LD (OCLEN),A
- CALL EXP
- LD A,(NUMBER)
- LD (OPCODE+1),A
- LD A,(NUMBER+1)
- AND 7
- RRCA
- RRCA
- RRCA
- OR 14H
- LD (OPCODE),A
- RET
- ;
- ; Group 4 - CLR, CPL
- ;
- GROUP4: LD A,1
- LD (OCLEN),A
- LD A,(HL) ; Get operand
- CP 'A' ; Done if CLR/CPL A
- RET Z
- LD B,70H
- CP 'C'
- JR Z,GRP4A ; Go if carry flag
- CP 'F'
- JP NZ,INVOPD ; Go if invalid operand
- LD B,5EH
- INC HL
- LD A,(HL) ; Better be '0' or '1'
- AND 1
- JR Z,GRP4A
- LD B,7EH
- GRP4A: LD A,(OPCODE) ; Modify opcode for carry flag
- ADD A,B
- LD (OPCODE),A
- RET
- ;
- ; EN DIS
- ;
- GROUP5: LD A,1
- LD (OCLEN),A
- LD A,(HL) ; Get option
- CP 'I'
- RET Z
- CP 'T'
- JP NZ,INVOPD
- LD B,20H
- JR GRP4A
- ;
- ; SEL
- ;
- GROUP6: LD A,1
- LD (OCLEN),A
- LD B,0
- LD A,(HL) ; Get operand
- CP 'R'
- JR Z,GRP6A
- CP 'M'
- JP NZ,INVOPD
- INC B
- INC B
- ;
- GRP6A: INC HL
- LD A,(HL)
- CP 'B'
- JP NZ,INVOPD
- INC HL
- LD A,(HL)
- AND 1
- JR Z,GRP6B
- INC B
- ;
- GRP6B: LD A,B
- CALL ROTATE
- LD B,A
- LD A,(OPCODE)
- ADD A,B
- LD (OPCODE),A
- RET
- ;
- ; STRT
- ;
- GROUP7: LD A,1
- LD (OCLEN),A
- LD A,(HL)
- CP 'C'
- RET Z
- CP 'T'
- JP NZ,INVOPD
- LD A,(OPCODE)
- OR 10H
- LD (OPCODE),A
- RET
- ;
- ; MOV
- ;
- GROUP8: LD A,1
- LD (OCLEN),A
- LD A,(HL)
- INC HL
- CP 'A'
- JR NZ,GRP8B ; Go if not <MOV,A???
- LD A,(HL)
- CP ','
- JP NZ,INVOPD
- INC HL
- LD A,(HL)
- CP '#'
- JR NZ,GRP8A ; Go if not immediate data
- INC HL
- CALL EXP ; Get immed data
- LD A,2
- LD (OCLEN),A
- LD A,(NUMBER)
- LD (OPCODE+1),A
- OR A
- RET
- ;
- GRP8A: LD A,(HL) ; Get operand
- INC HL
- LD B,42H
- CP 'T'
- JR Z,GRP8AX
- LD B,0C7H
- CP 'P'
- JR Z,GRP8AX
- CP 'R'
- JR Z,GRP8A1
- CP '@'
- JP NZ,INVOPD
- LD B,0F0H
- LD A,(HL)
- CP 'R'
- JP NZ,INVOPD
- INC HL
- LD A,(HL)
- CP '0'
- JR Z,GRP8AX
- INC B
- CP '1'
- JP NZ,INVOPD
- GRP8AX: LD A,B
- LD (OPCODE),A
- OR A
- RET
- ;
- GRP8A1: LD A,(HL)
- SUB '0'
- JP C,INVOPD
- CP 8
- JP NC,INVOPD
- OR 0F8H
- LD B,A
- JR GRP8AX
- ;
- GRP8B: LD B,0D7H
- CP 'P'
- JR Z,GRP8AX
- LD B,62H
- CP 'T'
- JR Z,GRP8AX
- LD B,0A0H ; Base for mov r,x or mov @r,x
- CP 'R'
- JR Z,GRP8B2
- CP '@'
- JP NZ,INVOPD
- LD A,(HL)
- CP 'R'
- JP NZ,INVOPD
- INC HL
- LD A,(HL)
- SUB '0'
- JP C,INVOPD
- CP 8
- JP NC,INVOPD
- LD C,A
- INC HL
- LD A,(HL)
- CP ','
- JP NZ,INVOPD
- INC HL
- LD A,(HL)
- INC HL
- CP '#'
- JR Z,GRP8B1
- CP 'A'
- JP NZ,INVOPD
- LD A,C
- CP 2
- JP NC,INVOPD
- OR B
- LD B,A
- ;
- GRP8BX: LD A,B
- LD (OPCODE),A
- OR A
- RET
- ;
- GRP8B1: LD A,0B0H
- OR C
- LD B,A
- CALL EXP
- LD A,(NUMBER)
- LD (OPCODE+1),A
- LD A,2
- LD (OCLEN),A
- JR GRP8BX
- ;
- GRP8B2: LD A,(HL) ; Get register
- SUB 30H
- JP C,INVOPD
- CP 8
- JP NC,INVOPD
- LD C,A ; Save register number
- INC HL
- LD A,(HL)
- CP ','
- JP NZ,INVOPD
- INC HL
- LD A,(HL)
- CP '#'
- JR Z,GRP8B3 ; Go if MOV RX,#data
- LD A,0A8H
- OR C
- LD (OPCODE),A
- RET
- ;
- GRP8B3: INC HL
- LD A,2
- LD (OCLEN),A
- LD A,0B8H
- OR C
- LD (OPCODE),A
- CALL EXP
- LD A,(NUMBER)
- LD (OPCODE+1),A
- OR A
- RET
- ;
- ; DEC INC
- ;
- GROUP9: LD A,1
- LD (OCLEN),A
- LD A,(OPCODE)
- AND 10H
- JR Z,GRP9B ; Go if DEC
- LD A,(HL)
- CP 'A'
- RET Z
- CP '@'
- JR Z,GRP9A
- CP 'R'
- JP NZ,INVOPD
- LD B,18H
- JR GRP9C
- ;
- GRP9A: INC HL
- LD A,(HL)
- CP 'R'
- JP NZ,INVOPD
- LD B,10H
- INC HL
- LD A,(HL)
- SUB 30H
- JP C,INVOPD
- CP 2
- JR GRP9D
- ;
- GRP9B: LD A,(HL) ; Get operand
- CP 'A'
- RET Z
- CP 'R'
- JP NZ,INVOPD
- LD B,0C8H
- ;
- GRP9C: INC HL
- LD A,(HL)
- SUB 30H
- JP C,INVOPD
- CP 8
- ;
- GRP9D: JP NC,INVOPD
- OR B
- LD (OPCODE),A
- RET
- ;
- ; MOVD
- ;
- GROUPA: LD A,1
- LD (OCLEN),A
- LD B,3CH
- LD A,(HL)
- CP 'A'
- JR Z,GRPAA ; Go if MOVD,A port
- ;
- GRPAX: CP 'P'
- JP NZ,INVOPD
- INC HL
- LD A,(HL)
- SUB 30H
- JP C,INVOPD
- CP 2
- JP NC,INVOPD
- OR B
- LD (OPCODE),A
- RET
- ;
- GRPAA: LD B,0CH
- INC HL
- LD A,(HL)
- CP ','
- JP NZ,INVOPD
- INC HL
- LD A,(HL)
- JR GRPAX
- ;
- ; ADD ADDC ANL ANLD CRL ORLD XRL
- ;
- GROUPB: LD A,1
- LD (OCLEN),A
- LD A,(OPCODE)
- CP 53H
- JR Z,GRPBE ; Go if ANL (exceptions)
- CP 43H
- JR Z,GRPBE ; Go if ORL (exceptions)
- ;
- GRPBA: LD A,(HL)
- INC HL
- CP 'A'
- JP NZ,INVOPD
- LD A,(HL)
- INC HL
- CP ','
- JP NZ,INVOPD
- LD A,(HL)
- INC HL
- CP '#'
- JR Z,GRPBC ; Go if immdeiate data
- CP 'R'
- LD C,8
- JR Z,GRPBB ; Go if OP A,RX
- CP '@'
- JP NZ,INVOPD
- LD C,2
- LD A,(HL)
- INC HL
- CP 'R'
- JP NZ,INVOPD
- ;
- GRPBB: LD A,(HL)
- SUB 30H
- JP C,INVOPD
- CP C
- JP NC,INVOPD
- LD B,A
- LD A,(OPCODE)
- AND 0E0H
- JR NZ,GRPBB1
- LD A,(OPCODE)
- AND 0F0H
- ADD A,60H
- LD (OPCODE),A
- ;
- GRPBB1: LD A,(OPCODE)
- BIT 3,C
- JR Z,GRPBB2
- OR 8
- ;
- GRPBB2: OR B
- LD (OPCODE),A
- RET
- ;
- GRPBC: CALL EXP
- LD A,(NUMBER)
- LD (OPCODE+1),A
- LD A,2
- LD (OCLEN),A
- OR A
- RET
- ;
- GRPBE: LD A,(HL)
- CP 'A'
- JR Z,GRPBA ; Go if not an exception
- CP 'B' ; Else ANL,ORL
- JR Z,GRBUS ; Go if BUS, # data
- CP 'P'
- JP NZ,INVOPD
- INC HL
- LD A,(HL)
- SUB 31H
- JP C,INVOPD
- CP 2
- JP NC,INVOPD
- INC A
- LD B,A
- LD A,(OPCODE)
- BIT 7,A
- JR Z,GRBUS1 ; Go if ANL ORL
- OR B
- LD (OPCODE),A ; Else ANLD ORLD
- RET
- ;
- GRBUS: INC HL
- INC HL
- LD B,0
- ;
- GRBUS1: LD A,2
- LD (OCLEN),A
- INC HL
- INC HL
- LD A,(HL)
- CP '#'
- JP NZ,INVOPD
- INC HL
- PUSH BC
- CALL EXP
- POP BC
- LD A,(NUMBER)
- LD (OPCODE+1),A
- LD A,(OPCODE)
- ADD A,45H
- OR B
- LD (OPCODE),A
- RET
- ;
- ; IN
- ;
- GROUPC: LD A,1
- LD (OCLEN),A
- LD A,(HL)
- CP 'A'
- JP NZ,INVOPD
- INC HL
- LD A,(HL)
- CP ','
- JP NZ,INVOPD
- INC HL
- LD A,(HL)
- CP 'P'
- JP NZ,INVOPD
- INC HL
- LD A,(HL)
- SUB 31H
- JP C,INVOPD
- CP 2
- JP NC,INVOPD
- INC A
- OR 8
- LD (OPCODE),A
- RET
- ;
- ; OUTL
- ;
- GROUPD: LD A,1
- LD (OCLEN),A
- LD A,(HL)
- CP 'B'
- RET Z
- CP 'P'
- JP NZ,INVOPD
- INC HL
- LD A,(HL)
- SUB 31H
- JP C,INVOPD
- CP 2
- JP NC,INVOPD
- INC A
- OR 38H
- LD (OPCODE),A
- RET
- ;
- ; MOVX
- ;
- GROUPE: LD A,1
- LD (OCLEN),A
- LD A,(HL)
- INC HL
- CP 'A'
- JR Z,GRPEA ; Go if movx a,@rx
- LD B,90H
- CP '@'
- JP NZ,INVOPD
- LD A,(HL)
- CP 'R'
- JP NZ,INVOPD
- ;
- GRPEX: INC HL
- LD A,(HL)
- SUB 30H
- JP C,INVOPD
- CP 2
- JP NC,INVOPD
- OR B
- LD (OPCODE),A
- RET
- ;
- GRPEA: LD A,(HL)
- CP ','
- JR NZ,INVOPD
- INC HL
- LD A,(HL)
- CP '@'
- JR NZ,INVOPD
- INC HL
- LD A,(HL)
- CP 'R'
- JR NZ,INVOPD
- LD B,80H
- JR GRPEX
- ;
- ; XCH XCHD
- ;
- GROUPF: LD A,1
- LD (OCLEN),A
- LD BC,28H SHL 8 OR 8
- LD A,(HL)
- CP 'A'
- JR NZ,INVOPD
- INC HL
- LD A,(HL)
- INC HL
- CP ','
- JR NZ,INVOPD
- LD A,(OPCODE)
- CP 30H
- JR Z,GRPFC ; Go if XCHD
- LD A,(HL)
- CP '@'
- JR NZ,GRPFB
- LD BC,20H SHL 8 OR 2
- ;
- GRPFA: INC HL
- LD A,(HL)
-
- GRPFB: CP 'R'
- JR NZ,INVOPD
- INC HL
- LD A,(HL)
- SUB 30H
- JR C,INVOPD
- CP C
- JR NC,INVOPD
- OR B
- LD (OPCODE),A
- RET
- ;
- GRPFC: LD BC,30H SHL 8 OR 2
- LD A,(HL)
- CP '@'
- JR Z,GRPFA
- ;
- INVOPD: XOR A
- LD (OCLEN),A
- LD A,2
- LD (ERRFLG),A
- SCF
- RET
- ;
- ; Expression evaluation, on entry HL => text
- ;
- EXP: LD BC,0
- LD (EXPOP),BC ; Clear operation and flags
- LD (NUMBER),BC ; Clear temp result
- LD (TMPVAL),BC
- DEC HL
- ;
- EXPNXT: INC HL
- LD A,(HL)
- CP ' '
- JR Z,EXPNXT ; Skip spaces
- CP ';' ; Done if comment
- RET Z
- CP '$'
- JP Z,EXPC ; Go if PC reference
- CP '<'
- JR Z,EXPO
- CP '>'
- JR Z,EXPO
- CP CARAT
- JR Z,EXPO
- CP '0'
- JR C,EXPO ; Go if operator
- CP '9'+1
- JP C,EXPN ; Go if decimal
- PUSH HL
- CALL FNDSYM ; Else is a symbol
- JR Z,EXPNX1 ; Go if found
- LD A,(PASS)
- OR A
- JR Z,EXPNX1 ; Go if pass 1
- LD A,5
- LD (ERRFLG),A ; Set undefined symbol error
- ;
- EXPNX1: LD C,(HL) ; Get it's value
- INC HL
- LD B,(HL)
- LD (NUMBER),BC
- DEC HL ; Point back to byte count
- ;
- EXPNX2: DEC HL
- LD A,(HL)
- AND 7FH
- CP 7
- JR NC,EXPNX2
- BIT 7,(HL) ; Test for multiple def
- POP HL
- JR Z,EXPNX3
- LD A,3
- LD (ERRFLG),A
- ;
- EXPNX3: CALL SKPLBL
- DEC HL
- JR EXPDO
- ;
- EXPO: CP ','
- RET Z
- INC HL
- CP '+'
- JR Z,EXAD ; Go if addition
- CP '-'
- JR Z,EXSB ; Go if subtraction
- CP '*'
- JR Z,EXML ; Go if multiplication
- CP '/'
- JR Z,EXDV ; Go if division
- CP '&'
- JR Z,EXAND ; Go if logical and
- CP '%'
- JR Z,EXOR ; Go if logical or
- CP '!'
- JR Z,EXEOR ; Go if exclusive or
- CP '<'
- JR Z,EXSHL ; Go if shift left
- CP '>'
- JR Z,EXSHR ; Go if shift right
- CP CARAT
- JR Z,EXCRT ; Go if control char def
- CP QUOTE
- RET NZ ; Go if not ascii literal
- LD A,(HL)
- LD (NUMBER),A ; Set ascii literal
- INC HL
- LD A,(HL)
- CP QUOTE
- JR Z,EXPDO ; Go if ascii terminator
- DEC HL ; Else point back
- JR EXPDO
- ;
- EXCRT: LD A,(HL)
- SUB 40H
- LD (NUMBER),A
- JP EXPNXT
- ;
- EXAD: XOR A
- JR EXOPN
- ;
- EXSB: LD A,1
- JR EXOPN
- ;
- EXML: LD A,2
- JR EXOPN
- ;
- EXDV: LD A,3
- JR EXOPN
- ;
- EXAND: LD A,4
- JR EXOPN
- ;
- EXOR: LD A,5
- JR EXOPN
- ;
- EXEOR: LD A,6
- JR EXOPN
- ;
- EXSHL: LD A,7
- JR EXOPN
- ;
- EXSHR: LD A,8
- ;
- EXOPN: LD (EXPOP),A ; Set operator flag
- LD BC,(NUMBER)
- LD (TMPVAL),BC
- DEC HL
- JP EXPNXT ; And get next
- ;
- EXPC: LD BC,(PC)
- LD (NUMBER),BC ; Set pc value and do operation
- ;
- EXPDO: LD A,(EXPOP)
- OR A
- JR Z,EXPDOA ; Do addition
- DEC A
- JR Z,EXPDOS ; Do subtraction
- DEC A
- JR Z,EXPDOM ; Do multiplication
- DEC A
- JR Z,EXPDOD ; Do division
- DEC A
- JR Z,EXPDAN ; Do logical and
- DEC A
- JR Z,EXPDOR ; Do logical or
- DEC A
- JR Z,EXPDOX ; Do exclusive or
- DEC A
- JR Z,EXPDSL ; Do shift left
- JP EXPDSR ; Else do shift right
- ;
- EXPDOX: LD DE,(TMPVAL)
- LD BC,(NUMBER)
- LD A,D
- XOR B
- LD B,A
- LD A,E
- XOR C
- LD C,A
- LD (NUMBER),BC
- JP EXPNXT
- ;
- EXPDOD: LD DE,(TMPVAL)
- LD BC,(NUMBER)
- CALL DIV
- LD (NUMBER),DE
- JP EXPNXT
- ;
- EXPDOA: PUSH HL
- LD HL,(TMPVAL)
- LD BC,(NUMBER)
- ADD HL,BC
- JR EXPDX1
- ;
- EXPDOS: PUSH HL
- LD HL,(TMPVAL)
- LD BC,(NUMBER)
- OR A
- SBC HL,BC
- ;
- EXPDX1: LD (NUMBER),HL
- POP HL
- JP EXPNXT
- ;
- EXPDOM: LD DE,(TMPVAL)
- LD BC,(NUMBER)
- CALL MULT
- ;
- EXPDX2: LD (NUMBER),BC
- JP EXPNXT
- ;
- EXPDAN: LD BC,(TMPVAL)
- LD DE,(NUMBER)
- LD A,B
- AND D
- LD B,A
- LD A,C
- AND E
- LD C,A
- JR EXPDX2
- ;
- EXPDOR: LD BC,(TMPVAL)
- LD DE,(NUMBER)
- LD A,B
- OR D
- LD B,A
- LD A,C
- OR E
- LD C,A
- JR EXPDX2
- ;
- EXPDSL: LD DE,(TMPVAL)
- LD A,(NUMBER)
- AND 0FH ; No more than 15 counts
- JR Z,EXPSXX ; Done if no shift
- LD B,A ; (else why shift it?)
- EXPSL1: SLA E ; Shift 16 bits left by count
- RL D
- DJNZ EXPSL1
- ;
- EXPSSX: LD (NUMBER),DE
- ;
- EXPSXX: JP EXPNXT
- ;
- EXPDSR: LD DE,(TMPVAL)
- LD A,(NUMBER)
- AND 0FH
- JR Z,EXPSXX
- LD B,A
- ;
- EXPSR1: SRL D ; Shift 16 bits right
- RR E
- DJNZ EXPSR1
- JR EXPSSX
- ;
- EXPN: CALL GETINT ; Get integer value
- BIT 0,C
- JR NZ,EXPN1
- DEC HL
- ;
- EXPN1: DEC HL
- JP EXPDO
- ;
- GETINT: LD BC,0
- LD (NUMBER),BC
- PUSH HL
- ;
- GTNT1: LD A,(HL)
- INC HL
- CP '0'
- JR C,GTNT2
- CP '9'+1
- JR C,GTNT1
- CP 'A'
- JR C,GTNT2
- CP 'F'+1
- JR C,GTNT1
- CP 'H'
- JR NZ,GTNT2
- INC C
- ;
- GTNT2: POP HL
- LD A,(HL)
- INC HL
- SUB 30H
- RET C
- CP 10
- JR C,GTNT3
- BIT 0,C
- RET Z
- SUB 7
- RET C
- CP 16
- RET NC
- ;
- GTNT3: PUSH HL
- LD D,0
- LD E,A
- LD HL,(NUMBER)
- BIT 0,C
- JR Z,GTNT5
- LD B,4
- ;
- GTNT4: SLA L
- RL H ; * 16
- DJNZ GTNT4
- ;
- GTNT4A: ADD HL,DE
- LD (NUMBER),HL
- JR GTNT2
- ;
- GTNT5: ADD HL,HL
- PUSH BC
- LD B,H
- LD C,L
- ADD HL,HL
- ADD HL,HL
- ADD HL,BC
- POP BC
- JR GTNT4A
- ;
- ; Opcode Table
- ; Each entry contains a byte count for the mnemonic, the mnemonic
- ; itself, the default object code, and the group number.
- ;
- OPTBL: DEFB 3,'ADD',3,11
- DEFB 4,'ADDC',13H,11
- DEFB 3,'ANL',53H,11
- DEFB 4,'ANLD',9CH,11
- DEFB 4,'CALL',14H,3
- DEFB 3,'CLR',27H,4
- DEFB 3,'CPL',37H,4
- DEFB 2,'DA',57H,1
- DEFB 3,'DEC',7,9
- DEFB 3,'DIS',15H,5
- DEFB 4,'DJNZ',0E8H,2
- DEFB 2,'EN',5,5
- DEFB 2,'IN',8,12
- DEFB 3,'INC',17H,9
- DEFB 3,'INS',8,1
- DEFB 3,'JB0',12H,2
- DEFB 3,'JB1',32H,2
- DEFB 3,'JB2',52H,2
- DEFB 3,'JB3',72H,2
- DEFB 3,'JB4',92H,2
- DEFB 3,'JB5',0B2H,2
- DEFB 3,'JB6',0D2H,2
- DEFB 3,'JB7',0F2H,2
- DEFB 2,'JC',0F6H,2
- DEFB 3,'JF0',0B6H,2
- DEFB 3,'JF1',76H,2
- DEFB 3,'JMP',4,2
- DEFB 4,'JMPP',0B3H,1
- DEFB 3,'JNC',0E6H,2
- DEFB 3,'JNI',86H,2
- DEFB 4,'JNT0',26H,2
- DEFB 4,'JNT1',46H,2
- DEFB 3,'JNZ',96H,2
- DEFB 3,'JTF',16H,2
- DEFB 3,'JT0',36H,2
- DEFB 3,'JT1',56H,2
- DEFB 2,'JZ'0C6H,2
- DEFB 3,'MOV',23H,8
- DEFB 4,'MOVD',0CH,10
- DEFB 4,'MOVP',0A3H,1
- DEFB 5,'MOVP3',0E3H,1
- DEFB 4,'MOVX',80H,14
- DEFB 3,'NOP',0,1
- DEFB 3,'ORL',43H,11
- DEFB 4,'ORLD',8CH,11
- DEFB 4,'OUTL',2,13
- DEFB 3,'RET',83H,1
- DEFB 4,'RETR',93H,1
- DEFB 2,'RL',0E7H,1
- DEFB 3,'RLC',0F7H,1
- DEFB 2,'RR',77H,1
- DEFB 3,'RRC',67H,1
- DEFB 3,'SEL',0C5H,6
- DEFB 4,'STOP',65H,1
- DEFB 4,'STRT',45H,7
- DEFB 4,'SWAP',47H,1
- DEFB 3,'XCH',20H,15
- DEFB 4,'XCHD',30H,15
- DEFB 3,'XRL',0D3H,11
- ;
- ; Pseudo ops
- ;
- DEFB 3,'EQU',0,80H
- DEFB 3,'ORG',0,81H
- DEFB 4,'DEFB',0,82H
- DEFB 2,'DB',0,82H
- DEFB 4,'DEFW',0,83H
- DEFB 2,'DW',0,83H
- DEFB 4,'DEFS',0,84H
- DEFB 2,'DS',0,84H
- DEFB 3,'END',0,85H ; Just in case some dork puts it in
- ;
- DEFB 0 ; End of table
- ;
- ;
- ; Write byte to hex file (at this point PC has not been updated)
- ; HEXFLG:
- ; Bits 0 - 4 = number of bytes in this record. Write record when
- ; full (32 bytes), and append checksum (in HEXCKS).
- ; Bit 5 =
- ; Bit 6 = 1 if skip has occured (ie: org or defs)
- ; Bit 7 = 1 if hex record has been opened, if = 0 then create header.
- ;
- HEXWR: LD A,(OCLEN)
- OR A
- RET Z ; Done if nothing to output
- LD B,A ; Set loop count
- PUSH HL
- PUSH DE
- LD DE,(PC)
- LD (HEXPC),DE ; Update .HEX file PC
- LD HL,OPCODE
- ;
- HEXWR1: LD A,(HL) ; Get data
- INC HL
- CALL HEXPUT ; Put in hex buffer
- LD DE,(HEXPC)
- INC DE
- LD (HEXPC),DE ; Update file PC
- DJNZ HEXWR1
- POP DE
- POP HL
- RET
- ;
- HEXPUT: PUSH HL
- PUSH DE
- PUSH BC
- LD C,A ; Save .HEX data
- LD A,(HEXFLG) ; Get flags
- AND 0C0H ; Get bits 6 & 7
- CP 80H
- JR C,HEXPTC ; Go if new record
- JR Z,HEXPTB ; Go if no skip & not new record
- PUSH BC
- CALL HEXDMP ; Else flush hexbfr & start new rcrd
- POP BC
- ;
- HEXPTC: LD A,80H ; Create new header
- LD (HEXFLG),A ; Flag new header
- LD DE,(HEXPC)
- LD (RECPC),DE ; Set start adrs of record
- LD A,D
- ADD A,E
- LD (HEXCKS),A ; Initialize checksum
- LD HL,HEXBFR
- LD (HL),':'
- INC HL
- LD (HL),'0' ; For now default byte count to zero
- INC HL
- LD (HL),'0'
- INC HL
- LD A,D ; Set record pc in hex buffer
- CALL PHEX
- LD A,E
- CALL PHEX
- LD (HL),'0' ; Set record type
- INC HL
- LD (HL),'0'
- ;
- HEXPTB: LD A,(HEXFLG) ; Get offset into hexbfr
- AND 1FH
- RLCA
- ADD A,9 ; Skip over record header
- LD E,A
- LD D,0
- LD HL,HEXBFR
- ADD HL,DE
- LD A,(HEXCKS) ; Update checksum
- ADD A,C
- LD (HEXCKS),A
- LD A,C ; Get data
- CALL PHEX
- LD A,(HEXFLG)
- INC A
- LD (HEXFLG),A
- AND 1FH
- CALL Z,HEXDMP ; Write record if full
- POP BC
- POP DE
- POP HL
- RET
- ;
- PHEX: PUSH AF
- CALL ROTATE
- CALL PHEX1
- POP AF
- ;
- PHEX1: AND 0FH
- CP 10
- JR C,PHEX2
- ADD A,7
- ;
- PHEX2: ADD A,30H
- LD (HL),A
- INC HL
- RET
- ;
- ; Dump current record to hex output buffer
- ;
- HEXDMP: LD A,(HEXFLG)
- AND 1FH
- LD B,A ; Set loop count
- JR NZ,HXDMP1 ; Go if not full record
- LD B,32
- ;
- HXDMP1: LD A,(HEXCKS) ; Update checksum
- ADD A,B
- LD (HEXCKS),A
- LD A,B
- LD HL,HEXBFR+1
- CALL PHEX ; Set byte count
- LD A,B
- RLCA
- ADD A,9 ; Add overhead
- LD B,A
- LD HL,HEXBFR
- ;
- HXDMP2: LD A,(HL)
- INC HL
- PUSH BC
- CALL HEXOUT ; Put in file buffer
- POP BC
- DJNZ HXDMP2
- LD A,(HEXCKS) ; Get checksum
- CPL
- INC A
- CALL PHEX
- DEC HL
- DEC HL
- LD A,(HL) ; Send checksum
- CALL HEXOUT
- INC HL
- LD A,(HL)
- CALL HEXOUT
- LD A,CR
- CALL HEXOUT
- LD A,LF
- CALL HEXOUT
- XOR A
- LD (HEXFLG),A
- RET
- ;
- HEXOUT: PUSH HL
- LD HL,(HEXDMA)
- LD BC,(HEXOFF)
- ADD HL,BC
- LD (HL),A
- POP HL
- LD A,(FILFLG)
- OR 2
- LD (FILFLG),A
- INC BC
- LD A,C
- AND 80H
- LD (HEXOFF),BC
- RET Z
- LD A,(FILFLG)
- AND 0FDH
- LD (FILFLG),A
- CALL FLSHEX
- LD BC,0
- LD (HEXOFF),BC
- RET
- ;
- LSTWR: LD A,(PASS) ; No output during pass 1
- OR A
- RET Z
- LD HL,LSTBFR
- LD A,(OCLEN)
- OR A
- JR Z,LSTWR2 ; Go if no code generated
- LD DE,(PC)
- LD A,D
- CALL HEXBUF ; Put pc in list buffer
- LD A,E
- CALL HEXBUF
- LD (HL),':'
- INC HL
- LD (HL),' '
- INC HL
- LD A,(OCLEN)
- CP 3
- JR C,LSTWR0 ; Max of 2 hex in list file
- LD A,2
- ;
- LSTWR0: LD B,A
- LD DE,OPCODE
- ;
- LSTWR1: LD A,(DE)
- INC DE
- CALL HEXBUF ; Put hex in buffer <= HL
- LD (HL),' '
- INC HL
- DJNZ LSTWR1
- LD A,(OCLEN)
- ;
- LSTWR2: LD B,13
- OR A
- JR Z,LSTWR3
- LD B,4
- DEC A
- JR Z,LSTWR3
- LD B,1
- ;
- LSTWR3: LD (HL),' '
- INC HL
- DJNZ LSTWR3
- EX DE,HL ; List buffer -> DE
- LD HL,LINBFR
- LD B,64
- ;
- LSTWR4: LD A,(HL)
- CP TAB
- JR NZ,LSTW4X
- INC HL
- ;
- LSTW4A: LD A,' '
- LD (DE),A
- INC DE
- DEC B
- JR Z,LSTWR5
- LD A,B
- AND 7
- JR NZ,LSTW4A
- JR LSTWR4
- ;
- LSTW4X: LD (DE),A
- INC HL
- INC DE
- CP LF
- JR Z,LSTWR5
- CP CTRLZ
- JR Z,LSTWR5
- DJNZ LSTWR4
- ;
- LSTWR5: EX DE,HL
- LD (HL),CR
- INC HL
- LD (HL),LF
- LD HL,LSTBFR
- LD A,(PAGLEN)
- OR A
- JR Z,LSTWR6
- LD A,(CURLIN)
- INC A
- LD (CURLIN),A
- ;
- LSTWR6: LD A,(HL)
- OR A
- RET Z
- INC HL
- PUSH AF
- CALL PUTLST
- POP AF
- CP LF
- JR Z,LSTWR7
- CP CTRLZ
- JR NZ,LSTWR6
- RET
- ;
- LSTWR7: LD A,(CURLIN)
- OR A
- RET Z
- LD B,A
- LD A,(PAGLEN+1) ; Get max printed line
- CP B
- RET NZ
- XOR A
- LD (CURLIN),A ; Clear line counter
- LD A,(PAGLEN)
- SUB B
- RET Z
- LD B,A
- ;
- LSTWR8: LD A,LF
- PUSH BC
- CALL PUTLST
- POP BC
- DJNZ LSTWR8
- RET
- ;
- ; Write byte to list file
- ;
- PUTLST: PUSH HL
- LD HL,(LSTDMA)
- LD BC,(LSTOFF)
- ADD HL,BC
- LD (HL),A
- POP HL
- LD A,(FILFLG)
- OR 8
- LD (FILFLG),A
- INC BC
- LD A,C
- AND 80H
- LD (LSTOFF),BC
- RET Z
- LD A,(FILFLG)
- AND 0F7H
- LD (FILFLG),A
- CALL FLSLST
- LD BC,0
- LD (LSTOFF),BC
- RET
- ;
- HEXBUF: PUSH AF
- CALL ROTATE
- CALL HEXBF1
- POP AF
- ;
- HEXBF1: AND 0FH
- CP 10
- JR C,HEXBF2
- ADD A,7
- ;
- HEXBF2: ADD A,30H
- LD (HL),A
- INC HL
- RET
- ;
- SKPLBL: LD A,(HL)
- CP ':'
- JR Z,SKPLB1
- CP ' '
- JR Z,SKPLB1
- CP 'A'
- JR NC,SKPLB1
- CP '9'+1
- RET NC
- CP '0'
- RET C
- ;
- SKPLB1: INC HL
- JR SKPLBL
- ;
- ; Find entry in symbol table. On entry HL => label name.
- ; On exit: NZ if not found, else Z and HL => value entry.
- ;
- FNDSYM: PUSH HL ; Get length of new entry
- LD C,0
- ;
- FNDS1: LD A,(HL)
- CP '0'
- JR C,FNDS3 ; Go if end of label
- CP '9'+1
- JR C,FNDS2 ; Go if numeric
- CP 'A'
- JR C,FNDS3 ; Go if end
- CP 'Z'+1
- JR NC,FNDS3 ; Go if end
- ;
- FNDS2: INC HL
- INC C
- LD A,C
- CP 6
- JR NZ,FNDS1
- ;
- ; C = length of label name (6 maximum)
- ;
- FNDS3: POP HL ; Recover pointer to label
- LD DE,(SYMTAB) ; Get pointer to start of table
- ;
- FNDS4: LD A,(DE) ; Get label char count
- AND 7
- JR NZ,FNDS5 ; Go if not end of table
- OR 0FFH ; Else entry not found
- LD HL,(SYMTAB)
- RET
- ;
- FNDS5: CP C
- JR NZ,FNDS8 ; Go if not same length
- PUSH HL ; Save text pointer
- PUSH DE ; And entry pointer
- PUSH BC ; And length
- LD B,A
- ;
- FNDS6: INC DE
- LD A,(DE)
- CP (HL)
- JR NZ,FNDS7 ; Go if no match
- INC HL
- DEC C
- DJNZ FNDS6 ; Do for all
- EX DE,HL ; Else point to value entry in HL
- INC HL
- POP BC
- POP DE ; Clean stack
- POP DE
- RET
- ;
- FNDS7: POP BC
- POP DE ; Restore registers
- POP HL
- LD A,(DE) ; Get length of this entry
- AND 7
- ;
- FNDS8: ADD A,3
- LD B,A
- ;
- FNDS9: INC DE ; Skip this entry
- DJNZ FNDS9
- JR FNDS4 ; Go check next entry
- ;
- ; Enter label into symbol table. On entry HL => label name,
- ; (tmpval) = value of label. Only chars '0'-'9' and 'A'-'F' allowed.
- ; On exit HL => end of table (value entry + 2).
- ;
- ENTSYM: LD DE,(SYMEND) ; Get pointer to end of table
- PUSH HL ; Compute length of entry
- LD C,0
- ;
- ENTSM1: LD A,(HL)
- CP '0'
- JR C,ENTSM3 ; Go if end of label
- CP '9'+1
- JR C,ENTSM2 ; Go if numeric
- CP 'A'
- JR C,ENTSM3 ; Go if end
- CP 'Z'+1
- JR NC,ENTSM3 ; Go if end
- ;
- ENTSM2: INC HL
- INC C
- LD A,C
- CP 6
- JR NZ,ENTSM1 ; 6 char maximum
- ;
- ENTSM3: POP HL
- LD A,C ; No entry if count = 0
- OR A
- RET Z
- LD (DE),A ; Set byte count in table
- INC DE
- LD B,0 ; Transfer label to table
- LDIR
- EX DE,HL
- LD BC,(TMPVAL) ; Get value
- LD (HL),C
- INC HL
- LD (HL),B
- INC HL
- LD (HL),0 ; Flag end of table
- LD (SYMEND),HL ; Update end of table pointer
- RET
- ;
- ; Data area
- ;
- LINUM: DEFW 0 ; Input line number
- PASS: DEFB 0 ; Pass number
- FILFLG: DEFB 0 ; File open flag
- IBFRP: DEFW IBFR ; Source buffer pointer
- FCBTMP: DEFW 0 ; Temp fcb pointer
- FCB1: DEFS 36,0 ; Object file fcb
- HEXDMA: DEFW 0 ; Dma pointer for hex file
- HEXOFF: DEFW 0 ; Offset into hex buffer
- HEXFLG: DEFB 0 ; Hex output flags
- HEXCKS: DEFB 0 ; Hex checksum
- HEXPC: DEFW 0 ; Hex file pc
- RECPC: DEFW 0 ; Hex record pc
- FCB2: DEFS 36,0 ; List file fcb
- CURLIN: DEFW 0 ; Current line in list buffer
- LSTDMA: DEFW 0 ; Dma pointer for list file
- LSTOFF: DEFW 0 ; Offset into list buffer
- BYTCNT: DEFW 0 ; Object code byte count
- ERRCNT: DEFW 0 ; Error count
- DMA1: DEFW 0 ; Dma buffer pointer for object code
- DMA2: DEFW 0 ; Dma bfr ptr for list code
- IBFEND: DEFW 0 ; End of input buffer pointer
- TMPVAL: DEFW 0 ; Temp value storage
- PC: DEFW 0 ; Program counter value
- OPCODE: DEFS 60 ; Current binary opcode
- OCLEN: DEFB 0 ; Opcode length (0 - 2)
- ERRFLG: DEFB 0 ; Error flag
- DEFW 0
- SYMTAB: DEFW 0 ; Pointer to start of symbol table
- SYMEND: DEFW 0 ; Ptr to end of sym tbl
- SYMPTR: DEFW 0 ; Current ptr to sym tbl
- SYMVAL: DEFW 0 ; Pointer to value in sym tbl
- NUMBER: DEFW 0 ; Return value from expression evaluator
- EXPOP: DEFW 0 ; Expression evaluator operator and flags
- ;
- ERRTBL: DEFW ERRM0 ; Pointers to error messages
- DEFW ERRM1
- DEFW ERRM2
- DEFW ERRM3
- DEFW ERRM4
- DEFW ERRM5
- DEFW ERRM6
- ;
- IMSG: DEFB CR,LF,'UCASM Micro-controller Assembler v'
- DEFB VER+30H,'.',REV+30H,CR,LF
- DEFB 'Copyright (c) 1987, 1988 by J. L. Post',CR,LF,0
- ;
- RDERMS: DEFB 'Can''t open source file',0
- AWCRAP: DEFB CR,LF,'Too many errors!',0
- ERRMSG: DEFB CR,LF,'** Error, ',0
- LINMSG: DEFB ' in line number ',0
- ;
- ERRM0: DEFB 'system failure',0 ; Should never happen
- ERRM1: DEFB 'unknown opcode',0 ; Pass 1
- ERRM2: DEFB 'invalid operand',0 ; Pass 1
- ERRM3: DEFB 'multiply defined symbol',0 ; Pass 1
- ERRM4: DEFB 'out of range',0 ; Pass 2
- ERRM5: DEFB 'undefined symbol',0 ; Pass 2
- ERRM6: DEFB 'invalid expression',0 ; Pass 2
- ;
- OPNEMS: DEFB 'Can''t open .',0
- DEFB ' file',0
- ;
- DONMSG: DEFB ' byte',0
- DEFB ' error',0
- ;
- LINBFP: DEFW LINBFR ; Line buffer pointer
- LINBFR EQU $ ; Input line buffer
- LSTBFR EQU LINBFR+100 ; List output buffer
- HEXBFR EQU LSTBFR+100 ; Hex output buffer
- ;
- STACK EQU HEXBFR+200 ; System stack space
- IBFR EQU STACK ; Source code input buffer
- ;
- ;
- ; Symbol table starts at end of input buffer. Entries consist of one
- ; byte for length of symbol name, ascii text of symbol, two bytes for
- ; symbol value (low byte first).
- ;
- END