aboutsummaryrefslogtreecommitdiff
path: root/tools/apultra/asm/6809/unaplib_6309.s
blob: 9e8ed711c52f8866fcc8dbd7c1671e70d15fe22a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
;  unaplib_6309.s - aPLib decompressor for H6309 - 131 bytes
;
;  in:  x = start of compressed data
;       y = start of decompression buffer
;  out: y = end of decompression buffer + 1
;
;  Copyright (C) 2020 Emmanuel Marty
;
;  This software is provided 'as-is', without any express or implied
;  warranty.  In no event will the authors be held liable for any damages
;  arising from the use of this software.
;
;  Permission is granted to anyone to use this software for any purpose,
;  including commercial applications, and to alter it and redistribute it
;  freely, subject to the following restrictions:
;
;  1. The origin of this software must not be misrepresented; you must not
;     claim that you wrote the original software. If you use this software
;     in a product, an acknowledgment in the product documentation would be
;     appreciated but is not required.
;  2. Altered source versions must be plainly marked as such, and must not be
;     misrepresented as being the original software.
;  3. This notice may not be removed or altered from any source distribution.


; Original M6809 version written by Emmanuel Marty with Hitachi 6309 enhancements
; added by Doug Masten.
;
; Main advantage of H6309 CPU is the "TFM" instruction which can copy one
; byte of memory in 3 clock cycles vs a traditional copy loop that takes
; 20 clock cycles.

; Options:
;   APLIB_VAR
;     Define variable to point to a DP memory location for a memory space
;     and speed optimization.
;     ex. APLIB_VAR equ <memory location>
;
;   APLIB_LONG_OFFSET_DISABLE
;     Defined variable to disable long offsets >= 32000 for a speed and space
;     optimization. Only enable this if you know what you are doing.
;     ex. APLIB_LONG_OFFSET_DISABLE equ 1


; define options
         ifdef APLIB_VAR
apbitbuf equ APLIB_VAR     ; bit queue (use DP memory for mem & space optimization)
         else
apbitbuf fcb 0             ; bit queue (DEFAULT - use extended memory)
         endc


apl_decompress
         lda #$80          ; initialize empty bit queue
         sta apbitbuf      ; plus bit to roll into carry
         tfr x,u

apcplit  ldb ,u+           ; copy literal byte
apwtlit  stb ,y+

         ldb #3            ; set 'follows literal' flag

aptoken  bsr apgetbit      ; read 'literal or match' bit
         bcc apcplit       ; if 0: literal

         bsr apgetbit      ; read '8+n bits or other type' bit
         bcs apother       ; if 11x: other type of match

         bsr apgamma2      ; 10: read gamma2-coded high offset bits
         clra
         subr d,w          ; high offset bits == 2 when follows_literal == 3 ?
         bcc apnorep       ; if not, not a rep-match

         bsr apgamma2      ; read repmatch length
         bra apgotlen      ; go copy large match

apnorep  tfr f,a           ; transfer high offset bits to A
         ldb ,u+           ; read low offset byte in B
         tfr d,x           ; save match offset

         bsr apgamma2      ; read match length

         ifndef APLIB_LONG_OFFSET_DISABLE
         cmpx #$7D00       ; offset >= 32000 ?
         bge apincby2      ; if so, increase match len by 2
         endc
         cmpx #$0500       ; offset >= 1280 ?
         bge apincby1      ; if so, increase match len by 1
         cmpx #$80         ; offset < 128 ?
         bge apgotlen      ; if so, increase match len by 2
apincby2 incw
apincby1 incw

apgotlen tfr y,d           ; transfer dst to D
         subr x,d          ; put backreference start address in D (dst + offset)
         tfm d+,y+         ; copy matched bytes

         ldb #2            ; clear 'follows literal' flag
         bra aptoken

apgamma2 ldw #1            ; init to 1 so it gets shifted to 2 below
loop@    bsr apgetbit      ; read data bit
         rolw              ; shift into W
         bsr apgetbit      ; read continuation bit
         bcs loop@         ; loop until a zero continuation bit is read
         rts

apdibits bsr apgetbit      ; read bit
         rolb              ; push into B
apgetbit lsl apbitbuf      ; shift bit queue, and high bit into carry
         bne aprts         ; queue not empty, bits remain
         lda ,u+           ; read 8 new bits
         rola              ; shift bit queue, and high bit into carry
         sta apbitbuf      ; save bit queue
aprts    rts

apshort  clrb
         bsr apdibits      ; read 2 offset bits
         rolb
         bsr apdibits      ; read 4 offset bits
         rolb
         beq apwtlit       ; if zero, go write it

         negb              ; reverse offset in D
         ldb b,y           ; load backreferenced byte from dst+offset
         bra apwtlit       ; go write it

apother  bsr apgetbit      ; read '7+1 match or short literal' bit
         bcs apshort       ; if 111: 4 bit offset for 1-byte copy

         ldb ,u+           ; read low bits of offset + length bit in B
         beq aprts         ; check for EOD and exit if so
         clra              ; clear high bits in A
         lsrb              ; shift offset in place, shift length bit into carry
         tfr d,x           ; save match offset
         ldb #1            ; len in B will be 2*1+carry:
         rolb              ; shift length, and carry into B
         tfr d,w
         bra apgotlen      ; go copy match