Add asm source to git repository

It's on the LZ4FHDemo.do disk, but this is more convenient.
This commit is contained in:
Andy McFadden 2015-08-13 16:04:00 -07:00
parent 2b39c5ad5d
commit 7720b2c161
2 changed files with 361 additions and 0 deletions

225
LZ4FH6502.S Normal file
View File

@ -0,0 +1,225 @@
********************************
* *
* LZ4FH uncompression for 6502 *
* By Andy McFadden *
* Version 1.0, August 2015 *
* *
* Developed with Merlin-16 *
* *
********************************
lst off
org $0300
*
* Constants
*
lz4fh_magic equ $66 ;ascii 'f'
tok_empty equ 253
tok_eod equ 254
overrun_check equ 0
*
* Variable storage
*
srcptr equ $3c ;2b a1l
dstptr equ $3e ;2b a1h
copyptr equ $00 ;2b
savmix equ $02 ;1b
savlen equ $03 ;1b
*
* ROM routines
*
bell equ $ff3a
monitor equ $ff69
*
* Parameters, stashed at the top of the text input
* buffer. We use this, rather than just having them
* poked directly into the code, so that the 6502 and
* 65816 implementations work the same way without
* either getting weird.
*
in_src equ $2fc ;2b
in_dst equ $2fe ;2b
entry
lda in_src ;copy source address to zero page
sta srcptr
lda in_src+1
sta srcptr+1
lda in_dst ;copy destination address to zero page
sta dstptr
lda in_dst+1
sta dstptr+1
sta _desthi+1
ldy #$00
lda (srcptr),y
cmp #lz4fh_magic ;does magic match?
beq goodmagic
jmp fail
goodmagic
inc srcptr
bne :nohi
inc srcptr+1
:nohi
mainloop
* Get the mixed-length byte and handle the literal.
ldy #$00
lda (srcptr),y ;get mixed-length byte
sta savmix
lsr A ;get the literal length
lsr A
lsr A
lsr A
beq noliteral
cmp #$0f
bne shortlit
inc srcptr
bne :nohi
inc srcptr+1
:nohi
lda (srcptr),y ;get length extension
clc
adc #15 ;add 15 - will not exceed 255
* At this point, srcptr holds the address of the "mix"
* word or the length extension, and dstptr holds the
* address of the next output location. So we want to
* read from (srcptr),y+1 and write to (dstptr),y.
* We can do this by sticking the DEY between the LDA
* and STA.
*
* We could save a couple of cycles by substituting
* addr,y in place of (dp),y, but the added setup cost
* would only benefit longer literal strings.
shortlit sta savlen
tay
:litloop
lda (srcptr),y ;5
dey ;2 if len is 255, copy 0-254
sta (dstptr),y ;6
bne :litloop ;3 -> 16 cycles/byte
* Advance srcptr by savlen+1, and dstptr by savlen
lda srcptr
sec ;this gets us the +1
adc savlen
sta srcptr
bcc :nohi
inc srcptr+1
clc
:nohi
lda dstptr
adc savlen
sta dstptr
bcc :nohi1
inc dstptr+1
:nohi1
ldy #$ff ;next INY rolls back to zero
* Handle match. Y holds an offset into srcptr such
* that we need to increment it once to get the next
* interesting byte.
noliteral
lda savmix
and #$0f
cmp #$0f
blt :shortmatch ;BCC
iny
lda (srcptr),y ;get length extension
cmp #237 ;"normal" values are 0-236
bge specialmatch ;BCS
adc #15 ;will not exceed 255
* Put the destination address into copyptr.
:shortmatch
adc #4 ;min match; won't exceed 255
sta savlen ;save match len for later
tax ;and keep it in X
iny
lda (srcptr),y ;match offset, lo
sta copyptr
iny
lda (srcptr),y ;match offset, hi
_desthi ora #$00 ;OR in hi-res page
sta copyptr+1
* Advance srcptr past the encoded match while we still
* remember how many bytes it took to encode. Y is
* indexing the last value used, so we want to go
* advance srcptr by Y+1.
tya
sec
adc srcptr
sta srcptr
bcc :nohi
inc srcptr+1
:nohi
* Copy the match. The length is in X. Note this
* must be a forward copy so overlapped data works.
*
* We know the match is at least 4 bytes long, so
* we could save a few cycles by not doing the
* ADC #4 earlier, and unrolling the first 4
* load/store operations here.
ldy #$00
:copyloop
lda (copyptr),y ;5
sta (dstptr),y ;6
iny ;2
dex ;2
bne :copyloop ;3 -> 18 cycles/byte
* advance dstptr past copied data
lda dstptr
clc
adc savlen
sta dstptr
bcc :nohi1
inc dstptr+1
:nohi1
DO overrun_check
LDA dstptr+1
CMP #$60
BLT :OKAY
BRK
BRK
:OKAY
jmp mainloop
ELSE
bne mainloop ;branch always
FIN
* handle "special" match values (value in A)
specialmatch
cmp #tok_empty
bne :notempty
tya ;empty match, advance srcptr
adc srcptr ; past and jump to main loop
sta srcptr
bcc :nohi
inc srcptr+1
clc
:nohi
jmp mainloop
:notempty
cmp #tok_eod
bne fail
rts ;success!
fail
jsr bell
jmp monitor

136
LZ4FH65816.S Normal file
View File

@ -0,0 +1,136 @@
*********************************
* *
* LZ4FH uncompression for 65816 *
* By Andy McFadden *
* Version 1.0, August 2015 *
* *
* Developed with Merlin-16 *
* *
*********************************
lst off
org $0300
xc ;allow 65c02 opcodes
xc ;allow 65816 opcodes
*
* Constants
*
lz4fh_magic equ $66 ;ascii 'f'
tok_empty equ 253
tok_eod equ 254
*
* Variable storage
*
savmix equ $00 ;2b
savlen equ $02 ;2b
*
* ROM routines
*
bell equ $ff3a
monitor equ $ff69
*
* Parameters.
*
* in_dst must be $2000 or $4000
*
in_src equ $2fc ;2b
in_dst equ $2fe ;2b
* Main entry point.
entry
clc ;go native
xce
rep #$30 ;16-bit acc/index
mx %00 ; tell Merlin
ldx in_src
ldy in_dst
sty _dstmod+1
lda $0000,x
inx
and #$00ff
cmp #lz4fh_magic
bne fail
mainloop
lda $0000,x
inx
sta savmix
and #$00f0
beq noliteral
lsr A
lsr A
lsr A
lsr A
cmp #$000f
bne shortlit
lda $0000,x ;length >= 15, get next
inx
and #$00ff
clc
adc #15
* At this point, Y holds the address of the next
* compressed data byte, X has the address of the
* next output position, and A has the length of
* the literal.
*
* The MVN instruction moves (A+1) bytes from X
* to Y, advancing X and Y.
shortlit
dec A ;MVN wants length-1
mvn $00,$00 ;7 cycles/byte
* Now handle the match.
noliteral
lda savmix
and #$000f
cmp #$000f
blt :shortmatch ;BCC
lda $0000,x ;add length extension
inx
and #$00ff
cmp #237 ;"normal" values are 0-236
bge specialmatch
adc #15 ;carry clear; won't exceed 255
:shortmatch
adc #3 ;min match, -1 for MVN
sta savlen ;spill A while we get offset
lda $0000,x ;load source buffer offset
inx
inx
phx ;save srcptr for later
_dstmod ora #$ff00 ;OR in hi-res page
tax
lda savlen
mvn $00,$00
plx ;restore srcptr
bra mainloop
* handle "special" match length values (in A)
specialmatch
cmp #tok_empty
beq mainloop ;empty match, just loop
cmp #tok_eod
bne fail
* exit
sec ;return to emulation mode
xce
rts
fail
sec
xce
jsr bell
jmp monitor