zasm: add support for "special instructions"

Let's not create complex rules for exception cases.
This commit is contained in:
Virgil Dupras 2019-04-21 12:58:28 -04:00
parent ecf7d7fbd6
commit e073fbff79
2 changed files with 61 additions and 5 deletions

View File

@ -121,6 +121,11 @@ def main():
a1 = eval(row[arg1index]) a1 = eval(row[arg1index])
a2 = eval(row[arg1index+1]) a2 = eval(row[arg1index+1])
args1 = genargs(a1) args1 = genargs(a1)
# special case handling
if n == 'JP' and isinstance(a1, str) and a1 in 'xy':
# we don't test the displacements for IX/IY because there can't be
# any.
args1 = args1[:1]
if args1: if args1:
for arg1 in args1: for arg1 in args1:
args2 = genargs(a2) args2 = genargs(a2)

View File

@ -4,7 +4,7 @@
; Number of rows in the argspec table ; Number of rows in the argspec table
ARGSPEC_TBL_CNT .equ 28 ARGSPEC_TBL_CNT .equ 28
; Number of rows in the primary instructions table ; Number of rows in the primary instructions table
INSTR_TBL_CNT .equ 102 INSTR_TBL_CNT .equ 104
; size in bytes of each row in the primary instructions table ; size in bytes of each row in the primary instructions table
INSTR_TBL_ROWSIZE .equ 9 INSTR_TBL_ROWSIZE .equ 9
@ -59,6 +59,10 @@ copy:
pop bc pop bc
ret ret
callHL:
jp (hl)
ret
; If string at (HL) starts with ( and ends with ), "enter" into the parens ; If string at (HL) starts with ( and ends with ), "enter" into the parens
; (advance HL and put a null char at the end of the string) and set Z. ; (advance HL and put a null char at the end of the string) and set Z.
; Otherwise, do nothing and reset Z. ; Otherwise, do nothing and reset Z.
@ -452,6 +456,34 @@ matchPrimaryRow:
pop hl pop hl
ret ret
; *** Special opcodes ***
; The special upcode handling routines below all have the same signature.
; Instruction row is at IX and we're expected to perform the same task as
; getUpcode. The number of bytes, however, must go in C instead of A
; No need to preserve HL, DE, BC and IX: it's handled by getUpcode already.
; Handle like a regular "JP (IX+d)" except that we refuse any displacement: if
; a displacement is specified, we error out.
handleJPIX:
ld a, 0xdd
jr handleJPIXY
handleJPIY:
ld a, 0xfd
jr handleJPIXY
handleJPIXY:
ld (curUpcode), a
ld a, (curArg1+1)
cp 0 ; numerical argument *must* be zero
jr nz, .error
; ok, we're good
ld a, 0xe9 ; second upcode
ld (curUpcode+1), a
ld c, 2
ret
.error:
xor c
ret
; Compute the upcode for argspec row at (DE) and arguments in curArg{1,2} and ; Compute the upcode for argspec row at (DE) and arguments in curArg{1,2} and
; writes the resulting upcode in curUpcode. A is the number if bytes written ; writes the resulting upcode in curUpcode. A is the number if bytes written
; to curUpcode (can be zero if something went wrong). ; to curUpcode (can be zero if something went wrong).
@ -463,6 +495,18 @@ getUpcode:
; First, let's go in IX mode. It's easier to deal with offsets here. ; First, let's go in IX mode. It's easier to deal with offsets here.
ld ixh, d ld ixh, d
ld ixl, e ld ixl, e
; Are we a "special instruction"?
bit 5, (ix+6)
jr z, .normalInstr ; not set: normal instruction
; We are a special instruction. Fetch handler (little endian, remember).
ld l, (ix+7)
ld h, (ix+8)
call callHL
; We have our result written in curUpcode and C is set.
jp .end
.normalInstr:
; we begin by writing our "base upcode", which can be one or two bytes ; we begin by writing our "base upcode", which can be one or two bytes
ld a, (ix+7) ; first upcode ld a, (ix+7) ; first upcode
ld (curUpcode), a ld (curUpcode), a
@ -738,10 +782,15 @@ argGrpABCDEHL:
; 2 bytes for upcode (2nd byte is zero if instr is one byte) ; 2 bytes for upcode (2nd byte is zero if instr is one byte)
; ;
; The displacement bit is split in 2 nibbles: lower nibble is the displacement ; The displacement bit is split in 2 nibbles: lower nibble is the displacement
; value, upper nibble is for flags. There is one flag currently, on bit 7, that ; value, upper nibble is for flags:
; indicates that the numerical argument is of the 'e' type and has to be
; decreased by 2 (djnz, jr). On bit 6, it indicates that the group argument's ; Bit 7: indicates that the numerical argument is of the 'e' type and has to be
; value is to be placed on the second upcode rather than the first. ; decreased by 2 (djnz, jr).
; Bit 6: it indicates that the group argument's value is to be placed on the
; second upcode rather than the first.
; Bit 5: Indicates that this row is handled very specially: the next two bytes
; aren't upcode bytes, but a routine address to call to handle this case with
; custom code.
instrTBl: instrTBl:
.db "ADC", 0, 'A', 'l', 0, 0x8e , 0 ; ADC A, (HL) .db "ADC", 0, 'A', 'l', 0, 0x8e , 0 ; ADC A, (HL)
@ -807,6 +856,8 @@ instrTBl:
.db "JP",0,0, 'l', 0, 0, 0xe9 , 0 ; JP (HL) .db "JP",0,0, 'l', 0, 0, 0xe9 , 0 ; JP (HL)
.db "JP",0,0, 0xa, 'N', 3, 0b11000010 , 0 ; JP cc, NN .db "JP",0,0, 0xa, 'N', 3, 0b11000010 , 0 ; JP cc, NN
.db "JP",0,0, 'N', 0, 0, 0xc3 , 0 ; JP NN .db "JP",0,0, 'N', 0, 0, 0xc3 , 0 ; JP NN
.db "JP",0,0, 'x', 0,0x20 \ .dw handleJPIX ; JP (IX)
.db "JP",0,0, 'y', 0,0x20 \ .dw handleJPIY ; JP (IY)
.db "JR",0,0, 'n', 0,0x80, 0x18 , 0 ; JR e .db "JR",0,0, 'n', 0,0x80, 0x18 , 0 ; JR e
.db "JR",0,0,'C','n',0x80, 0x38 , 0 ; JR C, e .db "JR",0,0,'C','n',0x80, 0x38 , 0 ; JR C, e
.db "JR",0,0,'=','n',0x80, 0x30 , 0 ; JR NC, e .db "JR",0,0,'=','n',0x80, 0x30 , 0 ; JR NC, e