mirror of
https://github.com/hsoft/collapseos.git
synced 2024-11-26 09:38:06 +11:00
Compare commits
No commits in common. "ab578159b725de12eb3a2981d66e1dd106dc0b23" and "33c480a5dd7ae49310ff40b500118639b19fdb1d" have entirely different histories.
ab578159b7
...
33c480a5dd
@ -59,11 +59,8 @@ instrNames:
|
|||||||
.db "BST", 0
|
.db "BST", 0
|
||||||
.db "SBRC", 0
|
.db "SBRC", 0
|
||||||
.db "SBRS", 0
|
.db "SBRS", 0
|
||||||
.equ I_RCALL 42
|
|
||||||
.db "RCALL", 0
|
|
||||||
.db "RJMP", 0
|
|
||||||
; no arg (from here, instrUpMasks2)
|
; no arg (from here, instrUpMasks2)
|
||||||
.equ I_BREAK 44
|
.equ I_BREAK 42
|
||||||
.db "BREAK", 0
|
.db "BREAK", 0
|
||||||
.db "CLC", 0
|
.db "CLC", 0
|
||||||
.db "CLH", 0
|
.db "CLH", 0
|
||||||
@ -91,7 +88,7 @@ instrNames:
|
|||||||
.db "SLEEP", 0
|
.db "SLEEP", 0
|
||||||
.db "WDR", 0
|
.db "WDR", 0
|
||||||
; Rd(5)
|
; Rd(5)
|
||||||
.equ I_ASR 70
|
.equ I_ASR 68
|
||||||
.db "ASR", 0
|
.db "ASR", 0
|
||||||
.db "COM", 0
|
.db "COM", 0
|
||||||
.db "DEC", 0
|
.db "DEC", 0
|
||||||
@ -140,9 +137,6 @@ instrUpMasks1:
|
|||||||
.db 0b11111010 ; BST
|
.db 0b11111010 ; BST
|
||||||
.db 0b11111100 ; SBRC
|
.db 0b11111100 ; SBRC
|
||||||
.db 0b11111110 ; SBRS
|
.db 0b11111110 ; SBRS
|
||||||
; k(12): XXXXkkkk kkkkkkkk
|
|
||||||
.db 0b11010000 ; RCALL
|
|
||||||
.db 0b11000000 ; RJMP
|
|
||||||
|
|
||||||
; 16-bit constant masks associated with each instruction. In the same order as
|
; 16-bit constant masks associated with each instruction. In the same order as
|
||||||
; in instrNames
|
; in instrNames
|
||||||
@ -237,35 +231,33 @@ parseInstruction:
|
|||||||
jr c, .spitRd5Rr5
|
jr c, .spitRd5Rr5
|
||||||
cp I_BLD
|
cp I_BLD
|
||||||
jr c, .spitRdK8
|
jr c, .spitRdK8
|
||||||
cp I_RCALL
|
|
||||||
jr c, .spitRdBit
|
|
||||||
cp I_BREAK
|
cp I_BREAK
|
||||||
jr c, .spitK12
|
jr c, .spitRdBit
|
||||||
cp I_ASR
|
cp I_ASR
|
||||||
jr c, .spitNoArg
|
jr c, .spitNoArg
|
||||||
; spitRd5
|
; spitRd5
|
||||||
ld ix, argSpecs ; 'R', 0
|
call .readR5
|
||||||
call _parseArgs
|
ret nz
|
||||||
ld a, h
|
|
||||||
call .placeRd
|
call .placeRd
|
||||||
; continue to .spitNoArg
|
; continue to .spitNoArg
|
||||||
.spitNoArg:
|
.spitNoArg:
|
||||||
call .getUp2
|
call .getUp2
|
||||||
jp .spit
|
jr .spit
|
||||||
|
|
||||||
.spitRd5Rr5:
|
.spitRd5Rr5:
|
||||||
ld ix, argSpecs+2 ; 'R', 'R'
|
call .readR5
|
||||||
call _parseArgs
|
|
||||||
ret nz
|
ret nz
|
||||||
ld a, h
|
|
||||||
call .placeRd
|
call .placeRd
|
||||||
ld a, l
|
call readComma
|
||||||
|
call .readR5
|
||||||
|
ret nz
|
||||||
|
push af ; --> lvl 1
|
||||||
; let's start with the 4 lower bits
|
; let's start with the 4 lower bits
|
||||||
and 0xf
|
and 0xf
|
||||||
or c
|
or c
|
||||||
; We now have our LSB in A. Let's spit it now.
|
; We now have our LSB in A. Let's spit it now.
|
||||||
call ioPutB
|
call ioPutB
|
||||||
ld a, l
|
pop af ; <-- lvl 1
|
||||||
; and now that last high bit, currently bit 4, which must become bit 1
|
; and now that last high bit, currently bit 4, which must become bit 1
|
||||||
and 0b00010000
|
and 0b00010000
|
||||||
rra \ rra \ rra
|
rra \ rra \ rra
|
||||||
@ -276,18 +268,24 @@ parseInstruction:
|
|||||||
jr .spitMSB
|
jr .spitMSB
|
||||||
|
|
||||||
.spitRdK8:
|
.spitRdK8:
|
||||||
ld ix, argSpecs+6 ; 'r', 8
|
call .readR4
|
||||||
call _parseArgs
|
|
||||||
ret nz
|
ret nz
|
||||||
ld a, h ; Rd
|
|
||||||
call .placeRd
|
call .placeRd
|
||||||
ld a, l ; K
|
call readComma
|
||||||
|
call readWord
|
||||||
|
call parseExpr
|
||||||
|
ret nz
|
||||||
|
ld a, c
|
||||||
|
ld a, 0xff
|
||||||
|
call .IX2A
|
||||||
|
ret nz
|
||||||
|
push af ; --> lvl 1
|
||||||
; let's start with the 4 lower bits
|
; let's start with the 4 lower bits
|
||||||
and 0xf
|
and 0xf
|
||||||
or c
|
or c
|
||||||
; We now have our LSB in A. Let's spit it now.
|
; We now have our LSB in A. Let's spit it now.
|
||||||
call ioPutB
|
call ioPutB
|
||||||
ld a, l
|
pop af ; <-- lvl 1
|
||||||
; and now those high 4 bits
|
; and now those high 4 bits
|
||||||
and 0xf0
|
and 0xf0
|
||||||
rra \ rra \ rra \ rra
|
rra \ rra \ rra \ rra
|
||||||
@ -296,47 +294,18 @@ parseInstruction:
|
|||||||
jr .spitMSB
|
jr .spitMSB
|
||||||
|
|
||||||
.spitRdBit:
|
.spitRdBit:
|
||||||
ld ix, argSpecs+8 ; 'R', 'b'
|
call .readR5
|
||||||
call _parseArgs
|
|
||||||
ret nz
|
ret nz
|
||||||
ld a, h
|
|
||||||
call .placeRd
|
call .placeRd
|
||||||
or l
|
call readComma
|
||||||
|
ret nz
|
||||||
|
call .readBit
|
||||||
|
ret nz
|
||||||
; LSB is in A and is ready to go
|
; LSB is in A and is ready to go
|
||||||
call ioPutB
|
call ioPutB
|
||||||
call .getUp1
|
call .getUp1
|
||||||
jr .spitMSB
|
jr .spitMSB
|
||||||
|
|
||||||
.spitK12:
|
|
||||||
; Let's deal with the upcode constant before we destroy DE below
|
|
||||||
call .getUp1
|
|
||||||
ld b, (hl)
|
|
||||||
call readWord
|
|
||||||
call parseExpr
|
|
||||||
ret nz
|
|
||||||
push ix \ pop hl
|
|
||||||
; We're doing the same dance as in _readk7. See comments there.
|
|
||||||
ld de, 0xfff
|
|
||||||
add hl, de
|
|
||||||
jp c, unsetZ ; Carry? number is way too high.
|
|
||||||
ex de, hl
|
|
||||||
call zasmGetPC ; --> HL
|
|
||||||
inc hl \ inc hl
|
|
||||||
ex de, hl
|
|
||||||
sbc hl, de
|
|
||||||
jp c, unsetZ ; Carry? error
|
|
||||||
ld de, 0xfff
|
|
||||||
sbc hl, de
|
|
||||||
; We're within bounds! Now, divide by 2
|
|
||||||
ld a, l
|
|
||||||
rr h \ rra
|
|
||||||
; LSB in A, spit
|
|
||||||
call ioPutB
|
|
||||||
ld a, h
|
|
||||||
and 0xf
|
|
||||||
or b
|
|
||||||
jp ioPutB
|
|
||||||
|
|
||||||
.spit:
|
.spit:
|
||||||
; LSB is spit *before* MSB
|
; LSB is spit *before* MSB
|
||||||
inc hl
|
inc hl
|
||||||
@ -369,24 +338,39 @@ parseInstruction:
|
|||||||
inc b
|
inc b
|
||||||
.skip1:
|
.skip1:
|
||||||
and 0b111
|
and 0b111
|
||||||
ld c, a ; can't store in H now, (HL) is used
|
ld c, a
|
||||||
ld ix, argSpecs+4 ; 7, 0
|
|
||||||
call _parseArgs
|
|
||||||
ret nz
|
|
||||||
; ok, now we can
|
|
||||||
ld l, h ; k in L
|
|
||||||
ld h, c ; bit in H
|
|
||||||
.spitBR2:
|
.spitBR2:
|
||||||
; bit in H, k in L.
|
call readWord
|
||||||
; Our value in L is the number of relative *bytes*. The value we put
|
ret nz
|
||||||
; there is the number of words. Therefore, relevant bits are 7:1
|
call parseExpr
|
||||||
|
ret nz
|
||||||
|
; IX contains an absolute value. Turn this into a -64/+63 relative
|
||||||
|
; value by subtracting PC from it. However, before we do that, let's
|
||||||
|
; add 0x7f to it, which we'll remove later. This will simplify bounds
|
||||||
|
; checks. (we use 7f instead of 3f because we deal in bytes here, not
|
||||||
|
; in words)
|
||||||
|
push ix \ pop hl
|
||||||
|
ld de, 0x7f
|
||||||
|
add hl, de ; Carry cleared
|
||||||
|
ex de, hl
|
||||||
|
call zasmGetPC ; --> HL
|
||||||
|
; The relative value is actually not relative to current PC, but to
|
||||||
|
; PC after the execution of this branching op. Increase HL by 2.
|
||||||
|
inc hl \ inc hl
|
||||||
|
ex de, hl
|
||||||
|
sbc hl, de
|
||||||
|
jp c, unsetZ ; Carry? error
|
||||||
|
ld de, 0x7f
|
||||||
|
sbc hl, de
|
||||||
|
; We're within bounds! However, our value in L is the number of
|
||||||
|
; relative *bytes*. The value we put there is the number of words.
|
||||||
|
; Thefore, relevant bits are 7:1
|
||||||
ld a, l
|
ld a, l
|
||||||
sla a \ rl b
|
sla a \ rl b
|
||||||
sla a \ rl b
|
sla a \ rl b
|
||||||
and 0b11111000
|
|
||||||
; k is now shifted by 3, two of those bits being in B. Let's OR A and
|
; k is now shifted by 3, two of those bits being in B. Let's OR A and
|
||||||
; H and we have our LSB ready to go.
|
; C and we have our LSB ready to go.
|
||||||
or h
|
or c
|
||||||
call ioPutB
|
call ioPutB
|
||||||
; Good! MSB now. B is already good to go.
|
; Good! MSB now. B is already good to go.
|
||||||
ld a, b
|
ld a, b
|
||||||
@ -396,10 +380,10 @@ parseInstruction:
|
|||||||
; upcode becomes 0b111101
|
; upcode becomes 0b111101
|
||||||
inc b
|
inc b
|
||||||
.rdBRBS:
|
.rdBRBS:
|
||||||
ld ix, argSpecs+10 ; bit + k(7)
|
call .readBit
|
||||||
call _parseArgs
|
ret nz
|
||||||
|
call readComma
|
||||||
ret nz
|
ret nz
|
||||||
; bit in H, k in L.
|
|
||||||
jr .spitBR2
|
jr .spitBR2
|
||||||
|
|
||||||
; local routines
|
; local routines
|
||||||
@ -426,141 +410,8 @@ parseInstruction:
|
|||||||
ld hl, instrUpMasks2
|
ld hl, instrUpMasks2
|
||||||
jp addHL
|
jp addHL
|
||||||
|
|
||||||
; Argspecs: two bytes describing the arguments that are accepted. Possible
|
.readR4:
|
||||||
; values:
|
call .readR5
|
||||||
;
|
|
||||||
; 0 - None
|
|
||||||
; 7 - a k(7) address, relative to PC, *in bytes* (divide by 2 before writing)
|
|
||||||
; 8 - a K(8) value
|
|
||||||
; 'a' - A 5-bit I/O port value
|
|
||||||
; 'A' - A 6-bit I/O port value
|
|
||||||
; 'b' - a 0-7 bit value
|
|
||||||
; 'R' - an r5 value: r0-r31
|
|
||||||
; 'r' - an r4 value: r16-r31
|
|
||||||
;
|
|
||||||
; All arguments accept expressions, even 'r' ones: in 'r' args, we start by
|
|
||||||
; looking if the arg starts with 'r' or 'R'. If yes, it's a simple 'rXX' value,
|
|
||||||
; if not, we try parsing it as an expression and validate that it falls in the
|
|
||||||
; correct 0-31 or 16-31 range
|
|
||||||
argSpecs:
|
|
||||||
.db 'R', 0 ; Rd(5)
|
|
||||||
.db 'R', 'R' ; Rd(5) + Rr(5)
|
|
||||||
.db 7, 0 ; k(7)
|
|
||||||
.db 'r', 8 ; Rd(4) + K(8)
|
|
||||||
.db 'R', 'b' ; Rd(5) + bit
|
|
||||||
.db 'b', 7 ; bit + k(7)
|
|
||||||
|
|
||||||
; Parse arguments in (HL) according to specs in IX
|
|
||||||
; Puts the results in HL (which is not needed anymore after the parsing).
|
|
||||||
; First arg in H, second in L.
|
|
||||||
; This routine is not used in all cases, some ops don't fit this pattern well
|
|
||||||
; and thus parse their args themselves.
|
|
||||||
; Z for success.
|
|
||||||
_parseArgs:
|
|
||||||
; For the duration of the routine, our final value will be in DE, and
|
|
||||||
; then placed in HL at the end.
|
|
||||||
push de
|
|
||||||
call readWord
|
|
||||||
jr nz, .end
|
|
||||||
ld a, (ix)
|
|
||||||
call .parse
|
|
||||||
jr nz, .end
|
|
||||||
ld d, a
|
|
||||||
ld a, (ix+1)
|
|
||||||
or a
|
|
||||||
jr z, .end ; no arg
|
|
||||||
call readComma
|
|
||||||
jr nz, .end
|
|
||||||
call readWord
|
|
||||||
jr nz, .end
|
|
||||||
ld a, (ix+1)
|
|
||||||
call .parse
|
|
||||||
jr nz, .end
|
|
||||||
; we're done with (HL) now
|
|
||||||
ld l, a
|
|
||||||
cp a ; ensure Z
|
|
||||||
.end:
|
|
||||||
ld h, d
|
|
||||||
pop de
|
|
||||||
ret
|
|
||||||
|
|
||||||
; Parse a single arg specified in A and returns its value in A
|
|
||||||
; Z for success
|
|
||||||
.parse:
|
|
||||||
cp 'R'
|
|
||||||
jr z, _readR5
|
|
||||||
cp 'r'
|
|
||||||
jr z, _readR4
|
|
||||||
cp 'b'
|
|
||||||
jr z, _readBit
|
|
||||||
cp 7
|
|
||||||
jr z, _readk7
|
|
||||||
cp 8
|
|
||||||
jr z, _readK8
|
|
||||||
ret ; something's wrong
|
|
||||||
|
|
||||||
_readBit:
|
|
||||||
push ix
|
|
||||||
call parseExpr
|
|
||||||
ld a, 7
|
|
||||||
call _IX2A
|
|
||||||
jr nz, .end
|
|
||||||
or c
|
|
||||||
ld c, a
|
|
||||||
cp a ; ensure Z
|
|
||||||
.end:
|
|
||||||
pop ix
|
|
||||||
ret
|
|
||||||
|
|
||||||
_readk7:
|
|
||||||
push hl
|
|
||||||
push de
|
|
||||||
push ix
|
|
||||||
call parseExpr
|
|
||||||
jr nz, .end
|
|
||||||
; IX contains an absolute value. Turn this into a -64/+63 relative
|
|
||||||
; value by subtracting PC from it. However, before we do that, let's
|
|
||||||
; add 0x7f to it, which we'll remove later. This will simplify bounds
|
|
||||||
; checks. (we use 7f instead of 3f because we deal in bytes here, not
|
|
||||||
; in words)
|
|
||||||
push ix \ pop hl
|
|
||||||
ld de, 0x7f
|
|
||||||
add hl, de ; Carry cleared
|
|
||||||
ex de, hl
|
|
||||||
call zasmGetPC ; --> HL
|
|
||||||
; The relative value is actually not relative to current PC, but to
|
|
||||||
; PC after the execution of this branching op. Increase HL by 2.
|
|
||||||
inc hl \ inc hl
|
|
||||||
ex de, hl
|
|
||||||
sbc hl, de
|
|
||||||
jp c, .err ; Carry? error
|
|
||||||
ld de, 0x7f
|
|
||||||
sbc hl, de
|
|
||||||
; We're within bounds! However, our value in L is the number of
|
|
||||||
; relative *bytes*.
|
|
||||||
ld a, l
|
|
||||||
cp a ; ensure Z
|
|
||||||
.end:
|
|
||||||
pop ix
|
|
||||||
pop de
|
|
||||||
pop hl
|
|
||||||
ret
|
|
||||||
.err:
|
|
||||||
call unsetZ
|
|
||||||
jr .end
|
|
||||||
|
|
||||||
_readK8:
|
|
||||||
push ix
|
|
||||||
call parseExpr
|
|
||||||
jr nz, .end
|
|
||||||
ld a, 0xff
|
|
||||||
call _IX2A
|
|
||||||
.end:
|
|
||||||
pop ix
|
|
||||||
ret
|
|
||||||
|
|
||||||
_readR4:
|
|
||||||
call _readR5
|
|
||||||
ret nz
|
ret nz
|
||||||
; has to be in the 16-31 range
|
; has to be in the 16-31 range
|
||||||
sub 0x10
|
sub 0x10
|
||||||
@ -570,25 +421,34 @@ _readR4:
|
|||||||
|
|
||||||
; read a rXX argument and return register number in A.
|
; read a rXX argument and return register number in A.
|
||||||
; Set Z for success.
|
; Set Z for success.
|
||||||
_readR5:
|
.readR5:
|
||||||
push ix
|
call readWord
|
||||||
ld a, (hl)
|
ld a, (hl)
|
||||||
call upcase
|
call upcase
|
||||||
cp 'R'
|
cp 'R'
|
||||||
jr nz, .end ; not a register
|
ret nz ; not a register
|
||||||
inc hl
|
inc hl
|
||||||
call parseDecimal
|
call parseDecimal
|
||||||
jr nz, .end
|
ret nz
|
||||||
ld a, 31
|
ld a, 31
|
||||||
call _IX2A
|
jr .IX2A
|
||||||
.end:
|
|
||||||
pop ix
|
.readBit:
|
||||||
|
call readWord
|
||||||
|
ret nz
|
||||||
|
call parseExpr
|
||||||
|
ld a, 7
|
||||||
|
call .IX2A
|
||||||
|
ret nz
|
||||||
|
or c
|
||||||
|
ld c, a
|
||||||
|
cp a ; ensure Z
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; Put IX's LSB into A and, additionally, ensure that the new value is <=
|
; Put IX's LSB into A and, additionally, ensure that the new value is <=
|
||||||
; than what was previously in A.
|
; than what was previously in A.
|
||||||
; Z for success.
|
; Z for success.
|
||||||
_IX2A:
|
.IX2A:
|
||||||
push ix \ pop hl
|
push ix \ pop hl
|
||||||
cp l
|
cp l
|
||||||
jp c, unsetZ ; A < L
|
jp c, unsetZ ; A < L
|
||||||
@ -598,5 +458,3 @@ _IX2A:
|
|||||||
ld a, l
|
ld a, l
|
||||||
; Z set from "or a"
|
; Z set from "or a"
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
@ -80,10 +80,8 @@ ioGetB:
|
|||||||
call ioInInclude
|
call ioInInclude
|
||||||
jr z, .normalmode
|
jr z, .normalmode
|
||||||
; We're in "include mode", read from FS
|
; We're in "include mode", read from FS
|
||||||
push ix ; --> lvl 1
|
|
||||||
ld ix, IO_INCLUDE_BLK
|
ld ix, IO_INCLUDE_BLK
|
||||||
call _blkGetB
|
call _blkGetB
|
||||||
pop ix ; <-- lvl 1
|
|
||||||
jr nz, .includeEOF
|
jr nz, .includeEOF
|
||||||
cp 0x0a ; newline
|
cp 0x0a ; newline
|
||||||
ret nz ; not newline? nothing to do
|
ret nz ; not newline? nothing to do
|
||||||
@ -113,11 +111,9 @@ ioGetB:
|
|||||||
; continue on to "normal" reading. We don't want to return our zero
|
; continue on to "normal" reading. We don't want to return our zero
|
||||||
.normalmode:
|
.normalmode:
|
||||||
; normal mode, read from IN stream
|
; normal mode, read from IN stream
|
||||||
push ix ; --> lvl 1
|
|
||||||
ld ix, IO_IN_BLK
|
ld ix, IO_IN_BLK
|
||||||
call _blkGetB
|
call _blkGetB
|
||||||
pop ix ; <-- lvl 1
|
cp 0x0a ; newline
|
||||||
cp LF ; newline
|
|
||||||
ret nz ; not newline? return
|
ret nz ; not newline? return
|
||||||
; inc current lineno
|
; inc current lineno
|
||||||
push hl
|
push hl
|
||||||
@ -134,6 +130,10 @@ ioGetB:
|
|||||||
pop af
|
pop af
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
_callIX:
|
||||||
|
jp (ix)
|
||||||
|
ret
|
||||||
|
|
||||||
; Put back non-zero character A into the "ioGetB stack". The next ioGetB call,
|
; Put back non-zero character A into the "ioGetB stack". The next ioGetB call,
|
||||||
; instead of reading from IO_IN_BLK, will return that character. That's the
|
; instead of reading from IO_IN_BLK, will return that character. That's the
|
||||||
; easiest way I found to handle the readWord/gotoNextLine problem.
|
; easiest way I found to handle the readWord/gotoNextLine problem.
|
||||||
|
@ -155,7 +155,8 @@ readComma:
|
|||||||
cp ','
|
cp ','
|
||||||
ret z
|
ret z
|
||||||
call ioPutBack
|
call ioPutBack
|
||||||
jp unsetZ
|
call unsetZ
|
||||||
|
ret
|
||||||
|
|
||||||
; Read ioGetB until we reach the beginning of next line, skipping comments if
|
; Read ioGetB until we reach the beginning of next line, skipping comments if
|
||||||
; necessary. This skips all whitespace, \n, \r, comments until we reach the
|
; necessary. This skips all whitespace, \n, \r, comments until we reach the
|
||||||
|
@ -9,6 +9,3 @@ bar:
|
|||||||
brbs 6, foo
|
brbs 6, foo
|
||||||
ori r22, 0x34+4
|
ori r22, 0x34+4
|
||||||
sbrs r1, 3
|
sbrs r1, 3
|
||||||
rjmp foo
|
|
||||||
rcall baz
|
|
||||||
baz:
|
|
||||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user