diff --git a/apps/zasm/tests/geninstrs.py b/apps/zasm/tests/geninstrs.py index 75634f9..f7ab9a3 100755 --- a/apps/zasm/tests/geninstrs.py +++ b/apps/zasm/tests/geninstrs.py @@ -121,6 +121,11 @@ def main(): a1 = eval(row[arg1index]) a2 = eval(row[arg1index+1]) 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: for arg1 in args1: args2 = genargs(a2) diff --git a/apps/zasm/zasm.asm b/apps/zasm/zasm.asm index 99d6ad2..d81c877 100644 --- a/apps/zasm/zasm.asm +++ b/apps/zasm/zasm.asm @@ -4,7 +4,7 @@ ; Number of rows in the argspec table ARGSPEC_TBL_CNT .equ 28 ; 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 INSTR_TBL_ROWSIZE .equ 9 @@ -59,6 +59,10 @@ copy: pop bc ret +callHL: + jp (hl) + ret + ; 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. ; Otherwise, do nothing and reset Z. @@ -452,6 +456,34 @@ matchPrimaryRow: pop hl 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 ; writes the resulting upcode in curUpcode. A is the number if bytes written ; 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. ld ixh, d 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 ld a, (ix+7) ; first upcode ld (curUpcode), a @@ -738,10 +782,15 @@ argGrpABCDEHL: ; 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 -; value, upper nibble is for flags. There is one flag currently, on bit 7, that -; 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 -; value is to be placed on the second upcode rather than the first. +; value, upper nibble is for flags: + +; Bit 7: indicates that the numerical argument is of the 'e' type and has to be +; 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: .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, 0xa, 'N', 3, 0b11000010 , 0 ; JP cc, 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,'C','n',0x80, 0x38 , 0 ; JR C, e .db "JR",0,0,'=','n',0x80, 0x30 , 0 ; JR NC, e