home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
cpm
/
debug
/
wadesrc.lbr
/
MONTAB.AZM
/
MONTAB.ASM
Wrap
Assembly Source File
|
1988-06-19
|
26KB
|
1,474 lines
title 'Z80 Assembler/Disassembler Tables'
;
; Last Edited 84-06-24 Wagner
;
; Copyright (c) 1984 by
;
; Thomas Wagner
; Patschkauer Weg 31
; 1000 Berlin 33
; West Germany
;
;
; Released to the public domain 1987
;
maclib z80
maclib monopt
;
cseg
;
public analop
public mnemtab,reg8nam,r16nam,ccnam
public opdesc,jumpmark,jumpaddr,caddress
;
public srchmnemo,translate
;
IF extended
extrn peek,peekbuf
ENDIF
extrn opnd1,opnd2,string
extrn cmderr
;
;------------------------------------------------------------------------------
;
; Table for all mnemonics
;
mnemtab:
DB 'NOP ' ; 0
mnnop equ 0
DB 'LD ' ; 1
mnld equ 1
DB 'INC ' ; 2
mninc equ 2
DB 'DEC ' ; 3
mndec equ 3
DB 'EX ' ; 4
mnex equ 4
DB 'DJNZ' ; 5
mndjnz equ 5
DB 'JR ' ; 6
mnjr equ 6
DB 'RLCA' ; 7
mnrlca equ 7
DB 'RRCA' ; 8
mnrrca equ 8
DB 'RLA ' ; 9
mnrla equ 9
DB 'RRA ' ; 10
mnrra equ 10
DB 'DAA ' ; 11
mndaa equ 11
DB 'CPL ' ; 12
mncpl equ 12
DB 'SCF ' ; 13
mnscf equ 13
DB 'CCF ' ; 14
mnccf equ 14
DB 'HALT' ; 15
mnhalt equ 15
DB 'ADD ' ; 16
mnadd equ 16
DB 'ADC ' ; 17
mnadc equ 17
DB 'SUB ' ; 18
mnsub equ 18
DB 'SBC ' ; 19
mnsbc equ 19
DB 'AND ' ; 20
mnand equ 20
DB 'XOR ' ; 21
mnxor equ 21
DB 'OR ' ; 22
mnor equ 22
DB 'CP ' ; 23
mncp equ 23
DB 'RET ' ; 24
mnret equ 24
DB 'POP ' ; 25
mnpop equ 25
DB 'JP ' ; 26
mnjp equ 26
DB 'CALL' ; 27
mncall equ 27
DB 'PUSH' ; 28
mnpush equ 28
DB 'RST ' ; 29
mnrst equ 29
DB 'OUT ' ; 30
mnout equ 30
DB 'EXX ' ; 31
mnexx equ 31
DB 'IN ' ; 32
mnin equ 32
DB 'DI ' ; 33
mndi equ 33
DB 'EI ' ; 34
mnei equ 34
DB 'RLC ' ; 35
mnrlc equ 35
DB 'RRC ' ; 36
mnrrc equ 36
DB 'RL ' ; 37
mnrl equ 37
DB 'RR ' ; 38
mnrr equ 38
DB 'SLA ' ; 39
mnsla equ 39
DB 'SRA ' ; 40
mnsra equ 40
DB 'NEG ' ; 41
mnneg equ 41
DB 'SRL ' ; 42
mnsrl equ 42
DB 'BIT ' ; 43
mnbit equ 43
DB 'RES ' ; 44
mnres equ 44
DB 'SET ' ; 45
mnset equ 45
DB 'RETN' ; 46
mnretn equ 46
DB 'IM ' ; 47
mnim equ 47
DB 'RETI' ; 48
mnreti equ 48
DB 'RRD ' ; 49
mnrrd equ 49
DB 'RLD ' ; 50
mnrld equ 50
DB 'LDI ' ; 51
mnldi equ 51
DB 'CPI ' ; 52
mncpi equ 52
DB 'INI ' ; 53
mnini equ 53
DB 'OUTI' ; 54
mnouti equ 54
DB 'LDD ' ; 55
mnldd equ 55
DB 'CPD ' ; 56
mncpd equ 56
DB 'IND ' ; 57
mnind equ 57
DB 'OUTD' ; 58
mnoutd equ 58
DB 'LDIR' ; 59
mnldir equ 59
DB 'CPIR' ; 60
mncpir equ 60
DB 'INIR' ; 61
mninir equ 61
DB 'OTIR' ; 62
mnotir equ 62
DB 'LDDR' ; 63
mnlddr equ 63
DB 'CPDR' ; 64
mncpdr equ 64
DB 'INDR' ; 65
mnindr equ 65
DB 'OTDR' ; 66
mnotdr equ 66
DB '??? ' ; 67
mnbadop equ 67
;
;------------------------------------------------------------------------------
;
; Tables for register and condition code names
;
reg8nam DB 'BCDEHLIRAF'
; 0123456789
;
regb equ 10h
regc equ 11h
regd equ 12h
rege equ 13h
regh equ 14h
regl equ 15h
rega equ 18h
regi equ 16h
regr equ 17h
;
;
r16nam: DB 'BCDEHLSPAFIXIY'
; 0 1 2 3 4 5 6
;
regbc equ 20h
regde equ 21h
reghl equ 22h
regsp equ 23h
regaf equ 24h
regix equ 25h
regiy equ 26h
;
atbc equ 30h
atde equ 31h
athl equ 32h
atsp equ 33h
atix equ 34h
atiy equ 35h
atixi equ 3dh
atiyi equ 3eh
;
;
ccnam: DB 'NZZ NCC POPEP M '
; 0 1 2 3 4 5 6 7
;
ccdnz equ 80h
ccdz equ 81h
ccdnc equ 82h
ccdc equ 83h
ccdpo equ 84h
ccdpe equ 85h
ccdp equ 86h
ccdm equ 87h
;
;
opnim8 equ 40h
opnim16 equ 50h
opnbit equ 60h
opnjr equ 70h
opnatc equ 90h
opnafa equ 0b0h
opnad16 equ 0a0h
opnad8 equ 0c0h
opnrst equ 0d0h
;
opnjprg equ 0e0h ; internal use only, not a real operand
opnjp16 equ 052h ; internal use only, becomes 50h
opncl16 equ 051h ; " " " " "
opnjpsp equ 0f0h
;
; jump marks
;
jm16 equ 010h ; jump immediate 16-bit (11 means call immed.)
jmsp equ 020h ; jump stack (ret)
jmreg equ 030h ; jump register
;
;------------------------------------------------------------------------------
;
; Table of legal opcodes after DD/FD-prefix
;
preftab:
DB 09h,19h,21h,22h,23h,29h,2ah,2bh,34h,35h,36h,39h,46h,4eh
DB 56h,5eh,66h,6eh,70h,71h,72h,73h,74h,75h,77h,7eh,86h,8eh
DB 096h,09eh,0a6h,0aeh,0b6h,0beh,0cbh,0e1h,0e3h,0e5h,0e9h,0f9h
lpreftab equ $-preftab
;
;
;------------------------------------------------------------------------------
;
; Table for opcodes 00..3F
;
tab00$3f:
db mnnop,0,0 ; 00
db mnld,regbc,opnim16
db mnld,atbc,rega
db mninc,regbc,0
db mninc,regb,0
db mndec,regb,0
db mnld,regb,opnim8
db mnrlca,0,0
;
db mnex,regaf,opnafa ; 08
db mnadd,reghl,regbc
db mnld,rega,atbc
db mndec,regbc,0
db mninc,regc,0
db mndec,regc,0
db mnld,regc,opnim8
db mnrrca,0,0
;
db mndjnz,opnjr,0 ; 10
db mnld,regde,opnim16
db mnld,atde,rega
db mninc,regde,0
db mninc,regd,0
db mndec,regd,0
db mnld,regd,opnim8
db mnrla,0,0
;
db mnjr,opnjr,0 ; 18
db mnadd,reghl,regde
db mnld,rega,atde
db mndec,regde,0
db mninc,rege,0
db mndec,rege,0
db mnld,rege,opnim8
db mnrra,0,0
;
db mnjr,ccdnz,opnjr ; 20
db mnld,reghl,opnim16
db mnld,opnad16,reghl
db mninc,reghl,0
db mninc,regh,0
db mndec,regh,0
db mnld,regh,opnim8
db mndaa,0,0
;
db mnjr,ccdz,opnjr ; 28
db mnadd,reghl,reghl
db mnld,reghl,opnad16
db mndec,reghl,0
db mninc,regl,0
db mndec,regl,0
db mnld,regl,opnim8
db mncpl,0,0
;
db mnjr,ccdnc,opnjr ; 30
db mnld,regsp,opnim16
db mnld,opnad16,rega
db mninc,regsp,0
db mninc,athl,0
db mndec,athl,0
db mnld,athl,opnim8
db mnscf,0,0
;
db mnjr,ccdc,opnjr ; 38
db mnadd,reghl,regsp
db mnld,rega,opnad16
db mndec,regsp,0
db mninc,rega,0
db mndec,rega,0
db mnld,rega,opnim8
db mnccf,0,0
;
ltab00$3f equ ($-tab00$3f)/3
;
;------------------------------------------------------------------------------
;
; Table for Opcodes 40..BF (Groups of 8)
;
tab40$bf:
db mnld,regb,1fh
db mnld,regc,1fh
db mnld,regd,1fh
db mnld,rege,1fh
db mnld,regh,1fh
db mnld,regl,1fh
db mnld,athl,1fh
db mnld,rega,1fh
db mnadd,rega,1fh
db mnadc,rega,1fh
db mnsub,1fh,0
db mnsbc,rega,1fh
db mnand,1fh,0
db mnxor,1fh,0
db mnor,1fh,0
db mncp,1fh,0
;
ltab40$bf equ ($-tab40$bf)/3
;
;------------------------------------------------------------------------------
;
; Table for Opcodes C0..FF
;
tabc0$ff:
db mnret,ccdnz,opnjpsp ; c0
db mnpop,regbc,0
db mnjp,ccdnz,opnjp16
db mnjp,opnjp16,0
db mncall,ccdnz,opncl16
db mnpush,regbc,0
db mnadd,rega,opnim8
db mnrst,opnrst+0,0
;
db mnret,ccdz,opnjpsp ; c8
db mnret,opnjpsp,0
db mnjp,ccdz,opnjp16
db mnbadop,0,0
db mncall,ccdz,opncl16
db mncall,opncl16,0
db mnadc,rega,opnim8
db mnrst,opnrst+1,0
;
db mnret,ccdnc,opnjpsp ; d0
db mnpop,regde,0
db mnjp,ccdnc,opnjp16
db mnout,opnad8,rega
db mncall,ccdnc,opncl16
db mnpush,regde,0
db mnsub,opnim8,0
db mnrst,opnrst+2,0
;
db mnret,ccdc,opnjpsp ; d8
db mnexx,0,0
db mnjp,ccdc,opnjp16
db mnin,rega,opnad8
db mncall,ccdc,opncl16
db mnbadop,0,0
db mnsbc,rega,opnim8
db mnrst,opnrst+3,0
;
db mnret,ccdpo,opnjpsp ; e0
db mnpop,reghl,0
db mnjp,ccdpo,opnjp16
db mnex,atsp,reghl
db mncall,ccdpo,opncl16
db mnpush,reghl,0
db mnand,opnim8,0
db mnrst,opnrst+4,0
;
db mnret,ccdpe,opnjpsp ; e8
db mnjp,athl,opnjprg
db mnjp,ccdpe,opnjp16
db mnex,regde,reghl
db mncall,ccdpe,opncl16
db mnbadop,0,0
db mnxor,opnim8,0
db mnrst,opnrst+5,0
;
db mnret,ccdp,opnjpsp ; f0
db mnpop,regaf,0
db mnjp,ccdp,opnjp16
db mndi,0,0
db mncall,ccdp,opncl16
db mnpush,regaf,0
db mnor,opnim8,0
db mnrst,opnrst+6,0
;
db mnret,ccdm,opnjpsp ; f8
db mnld,regsp,reghl
db mnjp,ccdm,opnjp16
db mnei,0,0
db mncall,ccdm,opncl16
db mnbadop,0,0
db mncp,opnim8,0
db mnrst,opnrst+7,0
;
ltabc0$ff equ ($-tabc0$ff)/3
;
;------------------------------------------------------------------------------
;
; Table for prefix-codes ED
;
tabedpref:
db 40h,mnin,regb,opnatc
db 41h,mnout,opnatc,regb
db 42h,mnsbc,reghl,regbc
db 43h,mnld,opnad16,regbc
db 44h,mnneg,0,0
db 45h,mnretn,opnjpsp,0
db 46h,mnim,opnbit+0,0
db 47h,mnld,regi,rega
;
db 48h,mnin,regc,opnatc
db 49h,mnout,opnatc,regc
db 4ah,mnadc,reghl,regbc
db 4bh,mnld,regbc,opnad16
db 4dh,mnreti,opnjpsp,0
db 4fh,mnld,regr,rega
;
db 50h,mnin,regd,opnatc
db 51h,mnout,opnatc,regd
db 52h,mnsbc,reghl,regde
db 53h,mnld,opnad16,regde
db 56h,mnim,opnbit+1,0
db 57h,mnld,rega,regi
;
db 58h,mnin,rege,opnatc
db 59h,mnout,opnatc,rege
db 5ah,mnadc,reghl,regde
db 5bh,mnld,regde,opnad16
db 5eh,mnim,opnbit+2,0
db 5fh,mnld,rega,regr
;
db 60h,mnin,regh,opnatc
db 61h,mnout,opnatc,regh
db 62h,mnsbc,reghl,reghl
db 67h,mnrrd,0,0
;
db 68h,mnin,regl,opnatc
db 69h,mnout,opnatc,regl
db 6ah,mnadc,reghl,reghl
db 6fh,mnrld,0,0
;
db 72h,mnsbc,reghl,regsp
db 73h,mnld,opnad16,regsp
;
db 78h,mnin,rega,opnatc
db 79h,mnout,opnatc,rega
db 7ah,mnadc,reghl,regsp
db 7bh,mnld,regsp,opnad16
;
db 0a0h,mnldi,0,0
db 0a1h,mncpi,0,0
db 0a2h,mnini,0,0
db 0a3h,mnouti,0,0
db 0a8h,mnldd,0,0
db 0a9h,mncpd,0,0
db 0aah,mnind,0,0
db 0abh,mnoutd,0,0
;
db 0b0h,mnldir,0,0
db 0b1h,mncpir,0,0
db 0b2h,mninir,0,0
db 0b3h,mnotir,0,0
db 0b8h,mnlddr,0,0
db 0b9h,mncpdr,0,0
db 0bah,mnindr,0,0
db 0bbh,mnotdr,0,0
;
ltabedpref equ ($-tabedpref)/4
;
;
; table entry for HALT opcode
;
tab76:
db mnhalt,0,0
;
;------------------------------------------------------------------------------
;
; Table for CB-Prefix Opcodes (Groups of 8)
;
tabcb00$ff:
db mnrlc,1fh,0 ; 00
db mnrrc,1fh,0 ; 08
db mnrl,1fh,0 ; 10
db mnrr,1fh,0
db mnsla,1fh,0
db mnsra,1fh,0
db mnbadop,0,0
db mnsrl,1fh,0
;
db mnbit,60h,1fh
db mnbit,61h,1fh
db mnbit,62h,1fh
db mnbit,63h,1fh
db mnbit,64h,1fh
db mnbit,65h,1fh
db mnbit,66h,1fh
db mnbit,67h,1fh
;
db mnres,60h,1fh
db mnres,61h,1fh
db mnres,62h,1fh
db mnres,63h,1fh
db mnres,64h,1fh
db mnres,65h,1fh
db mnres,66h,1fh
db mnres,67h,1fh
;
db mnset,60h,1fh
db mnset,61h,1fh
db mnset,62h,1fh
db mnset,63h,1fh
db mnset,64h,1fh
db mnset,65h,1fh
db mnset,66h,1fh
db mnset,67h,1fh
;
ltabcb00$ff equ ($-tabcb00$ff)/3
;
;
;
; Operand description:
;
; 00 no operand
; 1x 8-bit register name
; (x = pointer to 'reg8nam')
; 2x 16-bit register name
; (x = pointer to 'reg16nam')
; 3x memory register, x=pointer to 'reg16nam'
; bit 3 = 1: signed offset follows
; 40 immediate 8-bit follows
; 50 immediate 16-bit follows
; 6x x = bit number/ int-mode-number
; 70 jump offset follows (16-bit immediate value)
; 8x condition code
; (x = pointer to 'ccnam')
; 90 (C)
; A0 address follows
; B0 AF'
; C0 8-bit (port-)address follows
; Dx restart (8-bit immediate value follows)
;
; analop: analyse opcode
;
; entry: A/HL = first opcode byte address
;
; exit: B = opcode length
; C = menmonic table pointer
; HL = next opcode address
; opdesc contains operand description
;
; uses: all regs
;
analop:
shld caddress
IF extended
call peek
push h
lxix peekbuf
ELSE
push h
push h
popix
ENDIF
lxiy opdesc
mvi b,1 ; default length
xra a
sta prefix ; clear prefix
sta condit
sta jumpmark
call analop1 ; analyse
mviy 0,0 ; terminate opdesc
pop h
mov e,b
mvi d,0
dad d
ret
;
;
analop1:
ldx a,0 ; load opcode
mvi c,3 ; offset of IX to HL in "r16nam"
cpi 0ddh
jrz prefx ; IX-prefix
cpi 0fdh ; IY-prefix
jrnz anal10 ; jump if no prefix
inr c
prefx:
mov a,c
sta prefix
ldx a,2 ; get offset
sta offset ; store it
lxi h,preftab
ldx a,1 ; check next byte
lxi b,lpreftab
ccir ; allowed combination ?
jnz operr ; error if not
cpi 0cbh ; shift/bit op ?
jrnz prefx10 ; ok if not
ldx a,3 ; get opcode (byte 2 is offset)
cpi 36h ; 36 is not allowed
jz operr
ani 7
cpi 6 ; only .6/.E allowed
jnz operr ; error if not
prefx10:
mvi b,2 ; 2 bytes opcode
inxix ; get next byte
ldx a,0 ; opcode
;
; next byte can't be dd/fd prefix, so fall through
;
anal10:
cpi 0cbh
jrz exshiftop ; extended shift / bit operation
cpi 0edh
jrz specop ; special operation
lxi h,tab00$3f
cpi 040h
jrc anal20 ; direct table access for 00..3f
cpi 0c0h
jrc anal30 ; branch for 40..bf
lxi h,tabc0$ff ; direct table for c0..ff
sui 0c0h ; offset
;
anal20:
mov e,a
add a
add e ; opcode * 3
mov e,a
mvi d,0
dad d ; table location
anal25:
mov c,m ; mnemonic
inx h
mov a,m ; first operand
ora a
rz ; ready if no operand
call analopnd ; analyse operand
inx h
mov a,m ; second operand
ora a
rz ; ready if no second operand
jmp analopnd ; analyse second operand
;
;
anal30: ; here for opcodes 40..BF
cpi 76h
mvi c,mnhalt ; HALT is a special case
rz
sui 40h
rrc
rrc ; divide opcode by 8
rrc
ani 0fh
lxi h,tab40$bf
jr anal20 ; normal procedure now
;
;
; Opcode prefix CB: Extended shifts, bit operations
;
exshiftop:
inxix ; opcode is next byte
inr b
lda prefix ; prefix ?
ora a
jrz exshif1 ; ok if not
inxix ; skip offset if prefix
exshif1:
ldx a,0 ; load opcode
rrc
rrc ; divide by 8
rrc
ani 1fh
lxi h,tabcb00$ff
jr anal20 ; normal procedure from here
;
;
; Opcode prefix ED: Special operations
;
specop:
inxix ; opcode is next byte
inr b
ldx a,0
mvi c,ltabedpref
lxi h,tabedpref
specoplp:
cmp m
inx h
jrz anal25 ; continue normally if found
inx h
inx h
inx h
dcr c
jrnz specoplp
;
; fall through to operr for undefined ED-opcode
;
operr:
mvi c,mnbadop
mvi b,1 ; length of bad opcode is 1
ret
;
;------------------------------------------------------------------------------
;
; analopnd: analyse operand
;
; entry: A = operand code
;
analopnd:
sty a,0 ; store
inxiy
push psw
rrc
rrc
rrc
rrc
ani 0fh
dcr a
add a
mov e,a
mvi d,0
pop psw
push h
lxi h,analopntab
dad d
mov e,m
inx h
mov d,m
xchg
xthl
aopret:
ret ; enter table
;
analopntab:
dw aopr8 ; 10
dw aopr16 ; 20
dw aopa16 ; 30
dw aopim8 ; 40
dw aopim16 ; 50
dw aopret ; 60
dw aopjr ; 70
dw aopccd ; 80
dw aopret ; 90
dw aopim16 ; a0
dw aopret ; b0
dw aopim8 ; c0
dw aoprst ; d0
dw aopjprg ; e0
dw aopjpsp ; f0
;
;
aopccd:
mvi a,80h
sta condit
ret
;
aopr8:
ani 0fh
cpi 0fh
rnz ; ready if not undetermined
ldx a,0 ; get opcode again
ani 7 ; get register
cpi 7 ; A ?
jrnz aopr81
inr a ; internally, A is 8
aopr81:
ori 10h
sty a,-1 ; replace
cpi 16h ; (HL)
rnz ; ready if not (HL)
mviy 32h,-1 ; replace by (HL)
;
memopnd:
lda prefix
ora a
rz ; ok if no prefix
addy -1 ; else add prefix offset to (HL)
sty a,-1
;
ldx a,0 ; get opcode again
cpi 0e9h ; JP (rr) ?
rz ; no offset for JP (rr)
;
sety 3,-1 ; else mark offset follows
lda offset ; copy offset
sty a,0
inxiy ; point to next
inr b ; offset takes one byte
ret
;
aopjr:
ldx a,0 ; opcode again
cpi 10h ; DJNZ ?
jrnz aopjr1
mvi a,80h
sta condit ; DJNZ is conditional
aopjr1:
ldx a,1
sty a,0
inxiy ; point to next
inr b ; offset takes one byte
push h
lhld caddress ; current addr
inx h
inx h ; +2
mov e,a
mvi d,0 ; calculate absolute jump address
rlc
jrnc aopjr10
mvi d,0ffh ; extend sign
aopjr10:
dad d
xchg
pop h
xra a
jr mkjm16 ; mark as 16-bit jump
;
aopa16:
ani 7
cpi 2
rnz ; ready if not HL
jr memopnd
;
aopr16:
ani 7
cpi 2
rnz ; ready if not HL
lda prefix
addy -1
sty a,-1
ret
;
;
aopim16:
ldx e,1 ; copy value
sty e,0
ldx d,2
sty d,1
inxiy
inxiy
inr b
inr b ; 2 bytes for opcode
ani 7 ; jump ?
rz ; ready if not
push psw
ldy a,-3
ani 0f0h ; clear lower nibble in operand-description
sty a,-3
pop psw
mkjm16:
sded jumpaddr
ori jm16
mkjmp:
push h
lxi h,condit
ora m
sta jumpmark
pop h
ret
;
;
aopim8:
ldx d,1
lda prefix ; prefix ?
ora a
jrz aopim81 ; ok if not
ldx d,2 ; value is in next byte if prefix
aopim81:
sty d,0 ; copy value
inxiy
inr b ; one byte for opcode
ret
;
;
aoprst:
ani 7
mov d,a
inr d
mvi a,-8
aoprstlp:
adi 8
dcr d
jrnz aoprstlp
sty a,0
inxiy
mov e,a
mvi a,1 ; call marker
jr mkjm16 ; go mark jump
;
;
aopjprg:
ldy a,-2 ; previous operand
jr aopjj
;
aopjpsp:
mvi a,jmsp
;
aopjj:
mviy 0,-1 ; clear field, not an operand
jr mkjmp
;
;
;------------------------------------------------------------------------------
;
; Routines for Assembly
;
;------------------------------------------------------------------------------
;
; srchmnemo: search mnemonic
;
; entry: HL = pointer to mnemonic
;
; exit: Carry set if not found
; A = mnemonic index
;
srchmnemo:
lxi d,mnemtab
mvi b,mnbadop ; number of entries
mvi c,0 ; index
srcmnloop:
push b
push h ; save start
mvi b,4
mvi c,0
srcmncmp:
ldax d
sub m
ora c
mov c,a ; all bytes must match
inx h
inx d
djnz srcmncmp
pop h
pop b
ora a
mov a,c
rz ; ready if found
inr c
djnz srcmnloop
stc
ret ; exit with carry set
;
;
;------------------------------------------------------------------------------
;
;
; translate: translate op description into opcode
;
; entry: A = mnemonic index
; IX = opnd1
; IY = opnd2
;
translate:
mov c,a ; mnemo into C
xra a
sta prefix
sta prefix2
dcr a
sta regpref ; registers have preference this time
call trymatch ; try to match mnemo and operands
jrnc transl10
xra a
sta regpref ; no register preference this time
call trymatch
rc ; return if no match
;
; we have a match, now assemble the opcode
;
;
transl10:
mov a,e
cpi 4 ; ED-prefix-table ?
jrnz matchnoed
dcx h ; then opcode is one before mnemo
mov a,m
inx h
sta opcode ; correct opcode
;
matchnoed:
mvi b,1 ; B = length of opcode
lxix string
lda prefix ; is there an IX/IY prefix ?
ora a
jrz match10
stx a,0 ; yes, store & increase length
inxix
inr b
;
match10:
lda prefix2
ora a ; opcode prefix ?
jrz match20
stx a,0
inxix
inr b
;
match20:
lda opcode ; get opcode
stx a,0 ; store it
dcr d ; opcode offset
jrz match25 ; ok if 1
inx h
mov a,m
dcx h
cpi 1fh ; operand 1 undetermined ?
lda opnd1+1
jrz match22
lda opnd2+1 ; else insert reg-num of second opnd into op
match22:
call make8bit
ani 0fh
orx 0
stx a,0
;
match25:
lda prefix ; check again for IX/IY prefix
ora a
jrz match40 ; ok if no prefix
push h
lxi h,preftab
lda string+1 ; opcode
push b ; check opcode against table of allowed codes
lxi b,lpreftab
ccir
pop b
pop h
stc
rnz ; error if prefix with illegal opcode
;
mov a,m ; check mnemo
cpi mnjp ; is it JP (IX/IY) ?
jrz match40 ; then no offset
inx h ; first opnd
lxiy opnd1
mov a,m
inx h ; second opnd
cpi athl
jrz match30
cpi 1fh
jrz match30
mov a,m
cpi athl
jrz match29
cpi 1fh
jrnz match39 ; no offset if not (..)
match29:
lxiy opnd2
match30:
ldy a,2 ; offset marker
ora a
jrz match35 ; use 0 if no offset given
ldy a,3 ; else use specified offset
match35:
mov d,a ; save
lda prefix2
ora a ; another prefix ?
jrz match36 ; ok if not
ldx a,0 ; else copy opcode
stx d,0
mov d,a
match36:
stx d,1
inxix
inr b
;
match39:
dcx h
dcx h
;
match40:
inx h ; first operand
mov a,m
ora a
rz ; ready if no operands
lxiy opnd1
call insopnd
inx h
mov a,m
ora a
rz ; ready if no second operand
lxiy opnd2
call insopnd
ora a ; clear carry
ret
;
; insert operand
;
insopnd:
cpi 40h
rc ; no change if register
jrz insopni8
cpi 60h
jrc insopni16 ; jump if 16-bit immediate
cpi 70h
rc ; ready if IM/BIT
jrz insopnjr ; jump if jump offset
cpi 0a0h
rc ; ready if condition code or (C)
jrz insopni16
cpi 0c0h
rc ; ready if AF'
rnz ; ready if not 8-bit port address
;
insopni8:
ldy a,5 ; lower byte of value
insopnst:
stx a,1 ; store in opcode
inxix
inr b
ret
;
insopni16:
call insopni8
ldy a,6
jr insopnst
;
insopnjr:
lhld caddress ; current address
inx h
inx h ; + 2
ldy e,5
ldy d,6 ; jump address specified
xchg
ora a
dsbc d ; calculate offset
jrc insopnjr1 ; branch if negative offset
mov a,h
ora a
jnz cmderr ; abort if offset > 255
mov a,l
ani 80h
jnz cmderr ; abort if offset > 127
mov a,l
jr insopnst ; go store offset
;
insopnjr1:
inr h
jnz cmderr ; abort if offset < -256
mov a,l
ani 80h
jz cmderr ; abort if offset < -128
mov a,l
jr insopnst ; go store offset
;
;
; make8bit: change operand to conform to 8-bit register
;
make8bit:
ora a
stc
rz ; ret if opnd empty
cpi 20h
jrnc make810 ; branch if 16-bit
cpi 16h
cmc
rnc ; ready if B..L
cpi 18h ; A ?
stc
rnz ; error if I or R
dcr a
ora a
ret ; A is 17h for opcode
;
make810:
cpi 32h ; must be (HL)
stc
rnz ; error if not
mvi a,16h ; (HL) is 16h for opcode
ora a
ret
;
;------------------------------------------------------------------------------
;
; trymatch: try to match mnemo and operands
;
; entry: C = mnemo
; IX = operand 1 description
; IY = operand 2 description
;
trymatch:
mvi e,3 ; E = length of a table element
mvi d,1 ; D = offset of opcodes within table
xra a
sta opcode ; init opcode
sta prefix2 ; init opcode prefix
lxi h,tab00$3f
mvi b,ltab00$3f
call srchtab
rnc
mvi d,8
mvi b,ltab40$bf
call srchtab
rnc
mvi d,1
mvi b,ltabc0$ff
call srchtab
rnc
xra a
sta opcode ; reset opcode
mvi a,0cbh
sta prefix2
mvi d,8
lxi h,tabcb00$ff
mvi b,ltabcb00$ff
call srchtab
rnc
;
mvi a,0edh
sta prefix2
mvi d,1
mvi e,4
lxi h,tabedpref+1
mvi b,ltabedpref
call srchtab
rnc
;
xra a
sta prefix2
mvi a,076h ; HALT opcode
sta opcode
mvi e,3
mvi b,1
lxi h,tab76
;
; return via srchtab
;
srchtab:
mov a,m
cmp c ; compare mnemo
jrnz srcht10
call opmatch ; try to match operands if same
rnc ; ready if match
srcht10:
mov a,d ; else continue: save opcode offset
mvi d,0
dad d ; next table element
mov d,a
push h
lxi h,opcode
add m ; increase opcode
mov m,a
pop h
djnz srchtab ; next
stc ; no match
ret ; return with carry set
;
;
; opmatch: try to match operands
;
; entry: HL = opcode descriptor
; IX, IY = operands
;
opmatch:
xra a
sta prefix
push b
push d
push h ; save everything
pushix
inx h ; first operand
mov b,m
call tryopnd
jrc opmatchret ; return with error if no match
inx h
mov b,m ; second operand
pushiy
popix
call tryopnd
opmatchret:
popix
pop h
pop d
pop b
ret
;
;
; tryopnd: try to match operand
;
; entry: B = operand descriptor byte
; IX = operand
;
tryopnd:
mov a,b
ora a
jrnz tryopnd10
tryopndnull:
orx 1
orx 4
orx 7
rz ; match if no operand
stc
ret ; else no match
;
tryopnd10:
cpi 40h
jrnc tryopnd20 ; branch if not register
cmpx 1 ; compare
jrz tryopndisreg ; ok if match
cpi 1fh
stc
rnz ; no match if not undetermined 8-bit reg
ldx a,1
call make8bit
rc ; error if no 8-bit reg
tryopndisreg:
ldx a,0
ora a
rz ; match if no prefix
sta prefix ; store prefix
ret ; ready
;
tryopnd20:
jrz tryopndimm ; branch if immediate 8-bit (40)
ani 0f0h
cpi 60h
jrc tryopndimm ; branch if immediate 16-bit (5x)
jrz tryopndbitim ; branch if bit/int-mode (6x)
cpi 80h
jrc tryopndimm ; immediate (70)
jrz tryopndcc ; cond-code (8x)
cpi 0a0h ; address ?
jrc tryopndcmp ; (C) (90)
jrz tryopndaddr ; address (A0)
cpi 0c0h ; 8-bit address ?
jrc tryopndcmp ; AF (B0)
jrz tryopndaddr ; 8-bit-address (C0)
cpi 0d0h
mvi a,0
jrnz tryopndnull ; > D0 is no real operand
;
; Dx: restart
;
ldx a,4
cpi 50h ; must be immediate value
stc
rnz
ldx a,6
ora a
stc
rnz ; error if > 255
ldx a,5
mvi c,0
tryopndrst:
sui 8
jrc tryopndrst1
inr c
jr tryopndrst
tryopndrst1:
adi 8
stc
rnz ; error if not divisible by 8
mov a,c
ori 0d0h
cmp b
rz
stc
ret
;
tryopndcc:
ldx a,7
tryopndcc1:
cmp b
rz
stc
ret
;
tryopndcmp:
ldx a,1
jr tryopndcc1
;
tryopndimm:
ldx a,4
cpi 50h
jrz tryopndimrp
stc
ret
;
tryopndaddr:
ldx a,4
cpi 0a0h
jrz tryopndimrp
stc
ret
;
tryopndimrp:
lda regpref ; register preference ?
ora a
rz ; match ok if not
ldx a,1 ; is it a register ?
ora a
rz ; ret with match if not a register
stc
ret ; ret with no match if register operand
;
tryopndbitim:
ldx a,4
cpi 50h
stc
rnz ; must be value
ldx a,6
ora a
stc
rnz ; must be < 255
ldx a,5
cpi 8
cmc
rc ; must be <= 7
ori 60h
jr tryopndcc1
;
;------------------------------------------------------------------------------
;
dseg
;
prefix ds 1
offset ds 1
condit ds 1
caddress ds 2
;
jumpaddr ds 2
jumpmark ds 1
;
opdesc ds 8
;
prefix2 equ offset
opcode equ condit
regpref equ opdesc
;
end