-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathunupkr.js
186 lines (167 loc) · 2.79 KB
/
unupkr.js
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
;;; -*-asm-*-
; input:
;;; R20 : packed buffer
;;; R21 : output buffer
;;; r30 : return address
;;;
;;; Register usage (destroyed!)
;;; r0-r17,r20,r21
;;;
DST REG 21
SRC REG 20
REGTOP 16
LR_save REG 99
LR_save2 REG 99
GETBIT REG 99
GETLENGTH REG 99
LITERAL REG 99
LOOP REG 99
index REG 99
bit_pos REG 99
state REG 99
prev_was_match REG 99
offset REG 99
prob reg 99
byte REG 99
PROBS reg 99
tmp2 reg 2
tmp1 REG 1
tmp0 REG 0
REGMAP
upkr_probs equ $200
SIZEOF_PROBS EQU 1+255+1+2*32+2*32
unupkr::
move LR,LR_save
moveq #0,tmp0
movei #upkr_probs,PROBS
bset #7,tmp0
movei #SIZEOF_PROBS,tmp2
move PROBS,tmp1
.init storeb tmp0,(tmp1)
subq #1,tmp2
jr pl,.init
addq #1,tmp1
moveq #0,offset
moveq #0,state
movei #getlength,GETLENGTH
movei #getbit,GETBIT
.looppc move PC,LOOP
addq #.loop-.looppc,LOOP
move pc,LITERAL
jr .start
addq #6,LITERAL
.literal
moveq #1,byte
move pc,LR
jr .into
addq #6,LR ; LR = .getbit
.getbit
addc byte,byte
.into
btst #8,byte
jump eq,(GETBIT)
move byte,index
storeb byte,(DST)
addq #1,DST
.start
moveq #0,prev_was_match
.loop
moveq #0,index
BL (GETBIT)
jump cc,(LITERAL)
addq #14,LR
cmpq #1,prev_was_match
jr eq,.newoff
shlq #8,r0
jump (GETBIT)
move r0,index
jr cc,.oldoff
shlq #8,r0
.newoff
addq #1,r0 ; r0 = 257
BL (GETLENGTH)
subq #1,r0
jump eq,(LR_save)
move r0,offset
.oldoff
movei #257+64,r0
BL (GETLENGTH)
move DST,r1
sub offset,r1
.cpymatch1
loadb (r1),r2
subq #1,r0
addqt #1,r1
storeb r2,(DST)
jr ne,.cpymatch1
addq #1,DST
jump (LOOP)
moveq #1,prev_was_match
getlength:
move LR,LR_save2
moveq #0,byte
move r0,index
moveq #0,bit_pos
move pc,LR
jump (GETBIT)
addq #6,LR
.gl
jr cc,.exit
addq #8,LR ; => return to "sh ..."
jump (GETBIT)
nop
sh bit_pos,r0
subq #1,bit_pos ; sh < 0 => shift left!
or r0,byte
jump (GETBIT)
subq #8,LR
.exit
moveq #1,r0
sh bit_pos,r0
jump (LR_save2)
or byte,r0
.newbyte:
loadb (SRC),r2
shlq #8,state
addq #1,SRC
or r2,state
getbit
move state,r2
move PROBS,r1
add index,r1 ; r1 = &probs[index]
shrq #12,r2
loadb (r1),prob
jr eq,.newbyte
move state,r2
move state,r0
shlq #24,r2
shrq #8,r0 ; sh
shrq #24,r2 ; sl
cmp prob,r2
addqt #1,index
jr cs,.one
mult prob,r0
;; state -= ((state >> 8) + 1)*prob
;; prob -= (prob+8)>>4
move prob,r2
add prob,r0
addq #8,r2
sub r0,state
shrq #4,r2
moveq #0,r0
jr .ret
sub r2,prob
.one
;; state = (state >> 8)*prob+(state & 0xff)
;; prob += (256 + 8 - prob) >> 4
move r2,state
movei #256+8,r2
add r0,state
sub prob,r2 ; 256-prob+8
shrq #4,r2
add r2,prob
moveq #3,r0
.ret
storeb prob,(r1)
jump (LR)
shrq #1,r0 ; C = 0, r0 = 1