diff --git a/apps/zasm/instr.asm b/apps/zasm/instr.asm index ee064ae..f070c93 100644 --- a/apps/zasm/instr.asm +++ b/apps/zasm/instr.asm @@ -615,22 +615,57 @@ getUpcode: ld c, 1 jr .computeBytesWritten .withByte: - ; verify that the MSB in argument is zero inc hl + ; HL points to our number (LSB), with (HL+1) being our MSB which should + ; normally by zero. However, if our instruction is jr or djnz, that + ; number is actually a 2-bytes address that has to be relative to PC, + ; so it's a special case. Let's check for this special case. + bit 7, (ix+3) + jr z, .absoluteValue ; bit not set? regular byte value, + ; Our argument is a relative address ("e" type in djnz and jr). We have + ; to subtract (curOutputOffset) from it. + + ; First, check whether we're on first pass. If we are, skip processing + ; below because not having real symbol value makes relative address + ; verification falsely fail. + ld c, 2 ; this is a two bytes instruction + call zasmIsFirstPass + jr z, .computeBytesWritten + + ; We're on second pass + push de ; Don't let go of this, that's our dest + ld de, (curOutputOffset) + call JUMP_INTOHL + dec hl ; what we write is "e-2" + dec hl + call subDEFromHL + pop de ; Still have it? good + ; HL contains our number and we'll check its bounds. If It's negative, + ; H is going to be 0xff and L has to be >= 0x80. If it's positive, + ; H is going to be 0 and L has to be < 0x80. + ld a, l + cp 0x80 + jr c, .skipHInc ; a < 0x80, H is expected to be 0 + ; A being >= 0x80 is only valid in cases where HL is negative and + ; within bounds. This only happens is H == 0xff. Let's increase it to 0. + inc h +.skipHInc: + ; Let's write our value now even though we haven't checked our bounds + ; yet. This way, we don't have to store A somewhere else. + ld (de), a + ld a, h + or a ; cp 0 + jr nz, .numberTruncated ; if A is anything but zero, we're out + ; of bounds. + jr .computeBytesWritten + +.absoluteValue: + ; verify that the MSB in argument is zero inc hl ; MSB is 2nd byte ld a, (hl) dec hl ; HL now points to LSB or a ; cp 0 jr nz, .numberTruncated - ; HL points to our number - ; one last thing to check. Is the 7th bit on the displacement value set? - ; if yes, we have to decrease our value by 2. Uses for djnz and jr. - bit 7, (ix+3) - jr z, .skipDecrease - ; Yup, it's set. - dec (hl) - dec (hl) -.skipDecrease: ldi ld c, 2 jr .computeBytesWritten diff --git a/apps/zasm/main.asm b/apps/zasm/main.asm index 6f05dce..af5e285 100644 --- a/apps/zasm/main.asm +++ b/apps/zasm/main.asm @@ -25,6 +25,7 @@ ; JUMP_UPCASE ; JUMP_UNSETZ ; JUMP_INTODE +; JUMP_INTOHL ; JUMP_FINDCHAR ; JUMP_BLKSEL ; RAMSTART (where we put our variables in RAM) diff --git a/apps/zasm/tests/test2.asm b/apps/zasm/tests/test2.asm new file mode 100644 index 0000000..744982f --- /dev/null +++ b/apps/zasm/tests/test2.asm @@ -0,0 +1,11 @@ +; Test relative jumps +label1: + jp label1 + jp label2 + jp label2 + jr label2 + jr nc, label1 + +label2: + jr label1 + jr nc, label1 diff --git a/apps/zasm/util.asm b/apps/zasm/util.asm index b0c598d..74a9938 100644 --- a/apps/zasm/util.asm +++ b/apps/zasm/util.asm @@ -22,6 +22,18 @@ cpHLDE: cp e ret ; flags are correct +; HL - DE -> HL +subDEFromHL: + push af + ld a, l + sub e + ld l, a + ld a, h + sbc d + ld h, a + pop af + ret + ; Returns length of string at (HL) in A. strlen: push bc diff --git a/tools/emul/zasm.c b/tools/emul/zasm.c index 891bcf4..d087174 100644 --- a/tools/emul/zasm.c +++ b/tools/emul/zasm.c @@ -33,6 +33,7 @@ #define STDIN_BUFSIZE 0x8000 // When defined, we dump memory instead of dumping expected stdout //#define MEMDUMP +//#define DEBUG static Z80Context cpu; static uint8_t mem[0x10000]; @@ -119,7 +120,9 @@ int main() } #endif fflush(stdout); +#ifdef DEBUG fprintf(stderr, "Ended with A=%d DE=%d\n", cpu.R1.br.A, cpu.R1.wr.DE); +#endif return 0; } diff --git a/tools/emul/zasm_glue.asm b/tools/emul/zasm_glue.asm index 5dce484..c1b48b1 100644 --- a/tools/emul/zasm_glue.asm +++ b/tools/emul/zasm_glue.asm @@ -12,6 +12,7 @@ jp addHL jp upcase jp unsetZ jp intoDE +jp intoHL jp findchar jp parseHexPair jp blkSel diff --git a/tools/emul/zasm_user.asm b/tools/emul/zasm_user.asm index 3224e16..ff78e2f 100644 --- a/tools/emul/zasm_user.asm +++ b/tools/emul/zasm_user.asm @@ -5,9 +5,10 @@ JUMP_ADDHL .equ 0x08 JUMP_UPCASE .equ 0x0b JUMP_UNSETZ .equ 0x0e JUMP_INTODE .equ 0x11 -JUMP_FINDCHAR .equ 0x14 -JUMP_PARSEHEXPAIR .equ 0x17 -JUMP_BLKSEL .equ 0x1a +JUMP_INTOHL .equ 0x14 +JUMP_FINDCHAR .equ 0x17 +JUMP_PARSEHEXPAIR .equ 0x1a +JUMP_BLKSEL .equ 0x1d .equ USER_CODE 0x4800 .equ RAMSTART 0x5800