mirror of
https://github.com/hsoft/collapseos.git
synced 2024-11-26 10:18:05 +11:00
Compare commits
No commits in common. "68ef686c3c0e1304bd871cac5fb27ac0640ba977" and "c4658591bd0b9767eb60033beeb44568e74a8666" have entirely different histories.
68ef686c3c
...
c4658591bd
@ -248,13 +248,16 @@ parseArg:
|
|||||||
|
|
||||||
; Returns, with Z, whether A is a groupId
|
; Returns, with Z, whether A is a groupId
|
||||||
isGroupId:
|
isGroupId:
|
||||||
or a
|
cp 0xc ; max group id + 1
|
||||||
jp z, unsetZ ; not a group
|
jr nc, .notgroup ; >= 0xc? not a group
|
||||||
cp 0xd ; max group id + 1
|
cp 0
|
||||||
jp nc, unsetZ ; >= 0xd? not a group
|
jr z, .notgroup ; 0? not supposed to happen. something's wrong.
|
||||||
; A is a group. ensure Z is set
|
; A is a group. ensure Z is set
|
||||||
cp a
|
cp a
|
||||||
ret
|
ret
|
||||||
|
.notgroup:
|
||||||
|
call unsetZ
|
||||||
|
ret
|
||||||
|
|
||||||
; Find argspec A in group id H.
|
; Find argspec A in group id H.
|
||||||
; Set Z according to whether we found the argspec
|
; Set Z according to whether we found the argspec
|
||||||
@ -334,7 +337,7 @@ findInGroup:
|
|||||||
; If it's not this, then we check if it's a numerical arg.
|
; If it's not this, then we check if it's a numerical arg.
|
||||||
; If A is a group ID, we do something else: we check that (HL) exists in the
|
; If A is a group ID, we do something else: we check that (HL) exists in the
|
||||||
; groupspec (argGrpTbl). Moreover, we go and write the group's "value" (index)
|
; groupspec (argGrpTbl). Moreover, we go and write the group's "value" (index)
|
||||||
; in (HL+1). This will save us significant processing later in spitUpcode.
|
; in (HL+1). This will save us significant processing later in getUpcode.
|
||||||
; Set Z according to whether we match or not.
|
; Set Z according to whether we match or not.
|
||||||
matchArg:
|
matchArg:
|
||||||
cp (hl)
|
cp (hl)
|
||||||
@ -342,16 +345,11 @@ matchArg:
|
|||||||
; not an exact match. Before we continue: is A zero? Because if it is,
|
; not an exact match. Before we continue: is A zero? Because if it is,
|
||||||
; we have to stop right here: no match possible.
|
; we have to stop right here: no match possible.
|
||||||
or a
|
or a
|
||||||
jr nz, .skip ; not a zero, we can continue
|
jr nz, .checkIfNumber ; not a zero, we can continue
|
||||||
; zero, stop here
|
; zero, stop here
|
||||||
cp 1 ; unset Z
|
call unsetZ
|
||||||
ret
|
ret
|
||||||
.skip:
|
.checkIfNumber:
|
||||||
; Alright, let's start with a special case. Is it part of the special
|
|
||||||
; "BIT" group, 0xc? If yes, we actually expect a number, which will
|
|
||||||
; then be ORed like a regular group index.
|
|
||||||
cp 0xc
|
|
||||||
jr z, .expectsBIT
|
|
||||||
; not an exact match, let's check for numerical constants.
|
; not an exact match, let's check for numerical constants.
|
||||||
call upcase
|
call upcase
|
||||||
call checkNOrM
|
call checkNOrM
|
||||||
@ -365,21 +363,6 @@ matchArg:
|
|||||||
cp (hl)
|
cp (hl)
|
||||||
ret ; whether we match or not, the result of Z is
|
ret ; whether we match or not, the result of Z is
|
||||||
; the good one.
|
; the good one.
|
||||||
.expectsBIT:
|
|
||||||
ld a, (hl)
|
|
||||||
cp 'N'
|
|
||||||
inc hl
|
|
||||||
ld a, (hl)
|
|
||||||
dec hl
|
|
||||||
cp 8
|
|
||||||
jr c, .isBit ; A < 8
|
|
||||||
; not a bit
|
|
||||||
or a ; unset Z
|
|
||||||
ret
|
|
||||||
.isBit:
|
|
||||||
cp a ; set Z
|
|
||||||
ret
|
|
||||||
|
|
||||||
.notNumber:
|
.notNumber:
|
||||||
; A bit of a delicate situation here: we want A to go in H but also
|
; A bit of a delicate situation here: we want A to go in H but also
|
||||||
; (HL) to go in A. If not careful, we overwrite each other. EXX is
|
; (HL) to go in A. If not careful, we overwrite each other. EXX is
|
||||||
@ -424,8 +407,8 @@ matchPrimaryRow:
|
|||||||
; *** Special opcodes ***
|
; *** Special opcodes ***
|
||||||
; The special upcode handling routines below all have the same signature.
|
; 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
|
; Instruction row is at IX and we're expected to perform the same task as
|
||||||
; spitUpcode. The number of bytes, however, must go in C instead of A
|
; 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 spitUpcode already.
|
; 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
|
; Handle like a regular "JP (IX+d)" except that we refuse any displacement: if
|
||||||
; a displacement is specified, we error out.
|
; a displacement is specified, we error out.
|
||||||
@ -461,6 +444,28 @@ handleBIT:
|
|||||||
ld c, 0
|
ld c, 0
|
||||||
jp unsetZ
|
jp unsetZ
|
||||||
|
|
||||||
|
handleBITHL:
|
||||||
|
ld b, 0b01000110
|
||||||
|
jr _handleBITHL
|
||||||
|
handleSETHL:
|
||||||
|
ld b, 0b11000110
|
||||||
|
jr _handleBITHL
|
||||||
|
handleRESHL:
|
||||||
|
ld b, 0b10000110
|
||||||
|
_handleBITHL:
|
||||||
|
call handleBIT
|
||||||
|
ret nz ; error
|
||||||
|
ld a, 0xcb ; first upcode
|
||||||
|
ld (INS_UPCODE), a
|
||||||
|
ld a, (INS_CURARG1+1) ; 0-7
|
||||||
|
rla
|
||||||
|
rla
|
||||||
|
rla
|
||||||
|
or b ; 2nd upcode
|
||||||
|
ld (INS_UPCODE+1), a
|
||||||
|
ld c, 2
|
||||||
|
ret
|
||||||
|
|
||||||
handleBITIX:
|
handleBITIX:
|
||||||
ld a, 0xdd
|
ld a, 0xdd
|
||||||
ld b, 0b01000110
|
ld b, 0b01000110
|
||||||
@ -620,9 +625,11 @@ handleLDrr:
|
|||||||
ret
|
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 to IO.
|
; writes the resulting upcode in INS_UPCODE. A is the number if bytes written
|
||||||
; A is zero, with Z set, on success. A is non-zero, with Z unset, on error.
|
; to INS_UPCODE.
|
||||||
spitUpcode:
|
; A is zero on error. The only thing that can go wrong in this routine is
|
||||||
|
; overflow.
|
||||||
|
getUpcode:
|
||||||
push ix
|
push ix
|
||||||
push de
|
push de
|
||||||
push hl
|
push hl
|
||||||
@ -638,7 +645,7 @@ spitUpcode:
|
|||||||
ld h, (ix+5)
|
ld h, (ix+5)
|
||||||
call callHL
|
call callHL
|
||||||
; We have our result written in INS_UPCODE and C is set.
|
; We have our result written in INS_UPCODE and C is set.
|
||||||
jp .writeIO
|
jp .end
|
||||||
|
|
||||||
.normalInstr:
|
.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
|
||||||
@ -727,7 +734,7 @@ spitUpcode:
|
|||||||
call checknmxy
|
call checknmxy
|
||||||
jr z, .withByte
|
jr z, .withByte
|
||||||
; nope, no number, alright, we're finished here
|
; nope, no number, alright, we're finished here
|
||||||
jr .writeIO
|
jr .end
|
||||||
.withByte:
|
.withByte:
|
||||||
inc hl
|
inc hl
|
||||||
; HL points to our number (LSB), with (HL+1) being our MSB which should
|
; HL points to our number (LSB), with (HL+1) being our MSB which should
|
||||||
@ -744,7 +751,7 @@ spitUpcode:
|
|||||||
; verification falsely fail.
|
; verification falsely fail.
|
||||||
inc c ; one extra byte is written
|
inc c ; one extra byte is written
|
||||||
call zasmIsFirstPass
|
call zasmIsFirstPass
|
||||||
jr z, .writeIO
|
jr z, .end
|
||||||
|
|
||||||
; We're on second pass
|
; We're on second pass
|
||||||
push de ; Don't let go of this, that's our dest
|
push de ; Don't let go of this, that's our dest
|
||||||
@ -774,7 +781,7 @@ spitUpcode:
|
|||||||
or a ; cp 0
|
or a ; cp 0
|
||||||
jr nz, .numberTruncated ; if A is anything but zero, we're out
|
jr nz, .numberTruncated ; if A is anything but zero, we're out
|
||||||
; of bounds.
|
; of bounds.
|
||||||
jr .writeIO
|
jr .end
|
||||||
|
|
||||||
.absoluteValue:
|
.absoluteValue:
|
||||||
; verify that the MSB in argument is zero
|
; verify that the MSB in argument is zero
|
||||||
@ -787,7 +794,7 @@ spitUpcode:
|
|||||||
ldi
|
ldi
|
||||||
pop bc
|
pop bc
|
||||||
inc c
|
inc c
|
||||||
jr .writeIO
|
jr .end
|
||||||
|
|
||||||
.withWord:
|
.withWord:
|
||||||
inc hl ; HL now points to LSB
|
inc hl ; HL now points to LSB
|
||||||
@ -798,28 +805,12 @@ spitUpcode:
|
|||||||
pop bc
|
pop bc
|
||||||
inc c ; two extra bytes are written
|
inc c ; two extra bytes are written
|
||||||
inc c
|
inc c
|
||||||
; to writeIO
|
|
||||||
.writeIO:
|
|
||||||
; Let's write INS_UPCODE to IO
|
|
||||||
ld b, c ; save output byte count
|
|
||||||
ld hl, INS_UPCODE
|
|
||||||
.loopWrite:
|
|
||||||
ld a, (hl)
|
|
||||||
call ioPutB
|
|
||||||
jr nz, .ioError
|
|
||||||
inc hl
|
|
||||||
djnz .loopWrite
|
|
||||||
; Z is set by INC HL
|
|
||||||
jr .end
|
jr .end
|
||||||
.numberTruncated:
|
.numberTruncated:
|
||||||
; Z already unset
|
; problem: not zero, so value is truncated. error
|
||||||
ld a, ERR_OVFL
|
ld c, 0
|
||||||
jr .end
|
|
||||||
.ioError:
|
|
||||||
; Z already unset
|
|
||||||
ld a, SHELL_ERR_IO_ERROR
|
|
||||||
; continue to .end
|
|
||||||
.end:
|
.end:
|
||||||
|
ld a, c
|
||||||
pop bc
|
pop bc
|
||||||
pop hl
|
pop hl
|
||||||
pop de
|
pop de
|
||||||
@ -890,10 +881,26 @@ parseInstruction:
|
|||||||
.match:
|
.match:
|
||||||
; We have our matching instruction row. We're getting pretty near our
|
; We have our matching instruction row. We're getting pretty near our
|
||||||
; goal here!
|
; goal here!
|
||||||
call spitUpcode
|
call getUpcode
|
||||||
jr .end ; Z and A set properly, even on error
|
or a ; is zero?
|
||||||
|
jr z, .overflow
|
||||||
|
ld b, a ; save output byte count
|
||||||
|
ld hl, INS_UPCODE
|
||||||
|
.loopWrite:
|
||||||
|
ld a, (hl)
|
||||||
|
call ioPutB
|
||||||
|
jr nz, .ioError
|
||||||
|
inc hl
|
||||||
|
djnz .loopWrite
|
||||||
|
cp a ; ensure Z
|
||||||
|
jr .end
|
||||||
|
.ioError:
|
||||||
|
ld a, SHELL_ERR_IO_ERROR
|
||||||
|
jr .error
|
||||||
|
.overflow:
|
||||||
|
ld a, ERR_OVFL
|
||||||
|
jr .error
|
||||||
.badfmt:
|
.badfmt:
|
||||||
; Z already unset
|
|
||||||
ld a, ERR_BAD_FMT
|
ld a, ERR_BAD_FMT
|
||||||
.error:
|
.error:
|
||||||
; A is set to error already
|
; A is set to error already
|
||||||
@ -976,10 +983,6 @@ argGrpCC:
|
|||||||
argGrpABCDEHL:
|
argGrpABCDEHL:
|
||||||
.db "BCDEHL_A" ; 0xb
|
.db "BCDEHL_A" ; 0xb
|
||||||
|
|
||||||
; SPECIAL GROUP "BIT": 0xc
|
|
||||||
; When special group "0xc" shows up in argspec, it means: accept a number
|
|
||||||
; between 0 and 7. The value is then treated like a regular group value.
|
|
||||||
|
|
||||||
; Each row is 4 bytes wide, fill with zeroes
|
; Each row is 4 bytes wide, fill with zeroes
|
||||||
instrNames:
|
instrNames:
|
||||||
.db "ADC", 0
|
.db "ADC", 0
|
||||||
@ -1085,7 +1088,7 @@ instrTBl:
|
|||||||
.db I_AND, 'n', 0, 0, 0xe6 , 0 ; AND n
|
.db I_AND, 'n', 0, 0, 0xe6 , 0 ; AND n
|
||||||
.db I_AND, 'x', 0, 0, 0xdd, 0xa6 ; AND (IX+d)
|
.db I_AND, 'x', 0, 0, 0xdd, 0xa6 ; AND (IX+d)
|
||||||
.db I_AND, 'y', 0, 0, 0xfd, 0xa6 ; AND (IY+d)
|
.db I_AND, 'y', 0, 0, 0xfd, 0xa6 ; AND (IY+d)
|
||||||
.db I_BIT, 0xc, 'l', 0x43, 0xcb, 0b01000110 ; BIT b, (HL)
|
.db I_BIT, 'n', 'l', 0x20 \ .dw handleBITHL ; BIT b, (HL)
|
||||||
.db I_BIT, 'n', 'x', 0x20 \ .dw handleBITIX ; BIT b, (IX+d)
|
.db I_BIT, 'n', 'x', 0x20 \ .dw handleBITIX ; BIT b, (IX+d)
|
||||||
.db I_BIT, 'n', 'y', 0x20 \ .dw handleBITIY ; BIT b, (IY+d)
|
.db I_BIT, 'n', 'y', 0x20 \ .dw handleBITIY ; BIT b, (IY+d)
|
||||||
.db I_BIT, 'n', 0xb, 0x20 \ .dw handleBITR ; BIT b, r
|
.db I_BIT, 'n', 0xb, 0x20 \ .dw handleBITR ; BIT b, r
|
||||||
@ -1198,7 +1201,7 @@ instrTBl:
|
|||||||
.db I_PUSH,'X', 0, 0, 0xdd, 0xe5 ; PUSH IX
|
.db I_PUSH,'X', 0, 0, 0xdd, 0xe5 ; PUSH IX
|
||||||
.db I_PUSH,'Y', 0, 0, 0xfd, 0xe5 ; PUSH IY
|
.db I_PUSH,'Y', 0, 0, 0xfd, 0xe5 ; PUSH IY
|
||||||
.db I_PUSH,0x1, 0, 4, 0b11000101 , 0 ; PUSH qq
|
.db I_PUSH,0x1, 0, 4, 0b11000101 , 0 ; PUSH qq
|
||||||
.db I_RES, 0xc, 'l', 0x43, 0xcb, 0b10000110 ; RES b, (HL)
|
.db I_RES, 'n', 'l', 0x20 \ .dw handleRESHL ; RES b, (HL)
|
||||||
.db I_RES, 'n', 'x', 0x20 \ .dw handleRESIX ; RES b, (IX+d)
|
.db I_RES, 'n', 'x', 0x20 \ .dw handleRESIX ; RES b, (IX+d)
|
||||||
.db I_RES, 'n', 'y', 0x20 \ .dw handleRESIY ; RES b, (IY+d)
|
.db I_RES, 'n', 'y', 0x20 \ .dw handleRESIY ; RES b, (IY+d)
|
||||||
.db I_RES, 'n', 0xb, 0x20 \ .dw handleRESR ; RES b, r
|
.db I_RES, 'n', 0xb, 0x20 \ .dw handleRESR ; RES b, r
|
||||||
@ -1218,7 +1221,7 @@ instrTBl:
|
|||||||
.db I_SBC, 'A', 0xb, 0, 0b10011000 , 0 ; SBC A, r
|
.db I_SBC, 'A', 0xb, 0, 0b10011000 , 0 ; SBC A, r
|
||||||
.db I_SBC,'h',0x3,0x44, 0xed, 0b01000010 ; SBC HL, ss
|
.db I_SBC,'h',0x3,0x44, 0xed, 0b01000010 ; SBC HL, ss
|
||||||
.db I_SCF, 0, 0, 0, 0x37 , 0 ; SCF
|
.db I_SCF, 0, 0, 0, 0x37 , 0 ; SCF
|
||||||
.db I_SET, 0xc, 'l', 0x43, 0xcb, 0b11000110 ; SET b, (HL)
|
.db I_SET, 'n', 'l', 0x20 \ .dw handleSETHL ; SET b, (HL)
|
||||||
.db I_SET, 'n', 'x', 0x20 \ .dw handleSETIX ; SET b, (IX+d)
|
.db I_SET, 'n', 'x', 0x20 \ .dw handleSETIX ; SET b, (IX+d)
|
||||||
.db I_SET, 'n', 'y', 0x20 \ .dw handleSETIY ; SET b, (IY+d)
|
.db I_SET, 'n', 'y', 0x20 \ .dw handleSETIY ; SET b, (IY+d)
|
||||||
.db I_SET, 'n', 0xb, 0x20 \ .dw handleSETR ; SET b, r
|
.db I_SET, 'n', 0xb, 0x20 \ .dw handleSETR ; SET b, r
|
||||||
|
@ -88,9 +88,8 @@ ioGetB:
|
|||||||
; We have newline. Increase lineno and return (the rest of the
|
; We have newline. Increase lineno and return (the rest of the
|
||||||
; processing below isn't needed.
|
; processing below isn't needed.
|
||||||
push hl
|
push hl
|
||||||
ld hl, (IO_INC_LINENO)
|
ld hl, IO_INC_LINENO
|
||||||
inc hl
|
inc (hl)
|
||||||
ld (IO_INC_LINENO), hl
|
|
||||||
pop hl
|
pop hl
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user