diff options
author | Jens Arnold <amiconn@rockbox.org> | 2006-11-04 00:42:18 +0000 |
---|---|---|
committer | Jens Arnold <amiconn@rockbox.org> | 2006-11-04 00:42:18 +0000 |
commit | f8b1da2f7bddebc9c7026bd5d106dec118ce70a9 (patch) | |
tree | 474e99488c568355dcd07c497181a11afa0245f9 /firmware/target/coldfire/iriver/h300/lcd-as-h300.S | |
parent | 0d8781e2f99ea11298b6a290a979417647a5ce37 (diff) | |
download | rockbox-f8b1da2f7bddebc9c7026bd5d106dec118ce70a9.tar.gz rockbox-f8b1da2f7bddebc9c7026bd5d106dec118ce70a9.zip |
H300, X5: Faster lcd_yuv_blit() using EMAC. Speedup of the function itself at 124MHz: 10.5% on X5, 16.5% on H300. mpegplayer speedup 3..4%
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11429 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/coldfire/iriver/h300/lcd-as-h300.S')
-rwxr-xr-x | firmware/target/coldfire/iriver/h300/lcd-as-h300.S | 346 |
1 files changed, 120 insertions, 226 deletions
diff --git a/firmware/target/coldfire/iriver/h300/lcd-as-h300.S b/firmware/target/coldfire/iriver/h300/lcd-as-h300.S index ae55dfb224..1873b905c6 100755 --- a/firmware/target/coldfire/iriver/h300/lcd-as-h300.S +++ b/firmware/target/coldfire/iriver/h300/lcd-as-h300.S | |||
@@ -22,7 +22,7 @@ | |||
22 | 22 | ||
23 | .section .icode, "ax", @progbits | 23 | .section .icode, "ax", @progbits |
24 | 24 | ||
25 | /* lcd_write_yuv420_lines(), based on lcd-as-x5.S | 25 | /* lcd_write_yuv420_lines() |
26 | * | 26 | * |
27 | * See http://en.wikipedia.org/wiki/YCbCr | 27 | * See http://en.wikipedia.org/wiki/YCbCr |
28 | * ITU-R BT.601 (formerly CCIR 601): | 28 | * ITU-R BT.601 (formerly CCIR 601): |
@@ -38,252 +38,146 @@ | |||
38 | * |R| |1.000000 0.000000 1.402000| |Y'| | 38 | * |R| |1.000000 0.000000 1.402000| |Y'| |
39 | * |G| = |1.000000 -0.334136 -0.714136| |Pb| | 39 | * |G| = |1.000000 -0.334136 -0.714136| |Pb| |
40 | * |B| |1.000000 1.772000 0.000000| |Pr| | 40 | * |B| |1.000000 1.772000 0.000000| |Pr| |
41 | * Scaled, normalized, rounded and tweaked to yield RGB666, as converting | 41 | * Scaled, normalized, rounded and tweaked to yield RGB565: |
42 | * directly to RGB565 gives too much roundoff error: | 42 | * |R| |19611723 0 26881894| |Y' - 16| >> 27 |
43 | * |R| |74 0 101| |Y' - 16| / 256 | 43 | * |G| = |19611723 -6406711 -13692816| |Cb - 128| >> 26 |
44 | * |G| = |74 -24 -51| |Cb - 128| / 256 | 44 | * |B| |19611723 33976259 0| |Cr - 128| >> 27 |
45 | * |B| |74 128 0| |Cr - 128| / 256 | 45 | * |
46 | * Needs EMAC set to saturated, signed integer mode. | ||
46 | */ | 47 | */ |
47 | |||
48 | .align 2 | 48 | .align 2 |
49 | .global lcd_write_yuv420_lines | 49 | .global lcd_write_yuv420_lines |
50 | .type lcd_write_yuv420_lines, @function | 50 | .type lcd_write_yuv420_lines, @function |
51 | 51 | ||
52 | lcd_write_yuv420_lines: | 52 | lcd_write_yuv420_lines: |
53 | lea.l (-36, %sp), %sp /* free up some registers */ | 53 | lea.l (-44, %sp), %sp /* free up some registers */ |
54 | movem.l %d2-%d6/%a2-%a5, (%sp) | 54 | movem.l %d2-%d7/%a2-%a6, (%sp) |
55 | 55 | ||
56 | lea.l 0xf0000002, %a0 /* LCD data port */ | 56 | lea.l 0xf0000002, %a0 /* LCD data port */ |
57 | movem.l (36+4, %sp), %a1-%a5 /* Y data, Cb data, guv storage, Cr data, width */ | 57 | movem.l (44+4, %sp), %a1-%a4 /* Y data, Cb data, Cr data, width */ |
58 | lea.l (%a1, %a5), %a5 /* end address */ | 58 | lea.l (%a1, %a4), %a4 /* end address */ |
59 | 59 | ||
60 | .yuv_line_loop1: | 60 | move.l #19611723, %a5 /* y factor */ |
61 | /* chroma for first & second pixel */ | 61 | move.l #33976259, %a6 /* bu factor */ |
62 | clr.l %d1 /* load bu component */ | 62 | move.l #-6406711, %d5 /* gu factor */ |
63 | move.b (%a2), %d1 | 63 | move.l #-13692816, %d6 /* gv factor */ |
64 | clr.l %d3 /* load rv component */ | 64 | move.l #0x8410, %d7 /* bitmask for signed->unsigned conversion |
65 | move.b (%a4), %d3 | 65 | * of R, G and B within RGB565 at once */ |
66 | |||
67 | /* chroma for (very) first & second pixel */ | ||
68 | clr.l %d2 /* load u component */ | ||
69 | move.b (%a2)+, %d2 | ||
70 | clr.l %d3 /* load v component */ | ||
71 | move.b (%a3)+, %d3 | ||
66 | moveq.l #-128, %d0 | 72 | moveq.l #-128, %d0 |
67 | add.l %d0, %d1 | 73 | add.l %d0, %d2 |
68 | add.l %d0, %d3 | 74 | add.l %d0, %d3 |
69 | 75 | ||
70 | move.l %d1, %d2 /* %d2 = cb component for guv */ | 76 | mac.l %a6, %d2, %acc0 /* bu */ |
71 | asr.l #1, %d1 /* %d1 = 128 * (Cb - 128) / 256 */ | 77 | mac.l %d5, %d2, %acc1 /* gu */ |
72 | move.b %d1, (%a2)+ /* save bu for next line */ | 78 | mac.l %d6, %d3, %acc1 /* gv */ |
73 | moveq.l #-24, %d0 | 79 | move.l #26881894, %d0 /* rv factor */ |
74 | muls.w %d0, %d2 /* %d2 = -24 * (Cb - 128)*/ | 80 | mac.l %d0, %d3, %acc2 /* rv */ |
75 | moveq.l #-51, %d0 | ||
76 | muls.w %d3, %d0 | ||
77 | add.l %d0, %d2 /* %d2 = -24 * (Cb - 128) - 51 * (Cr - 128) */ | ||
78 | asr.l #8, %d2 | ||
79 | move.b %d2, (%a3)+ /* save guv for next line */ | ||
80 | moveq.l #101, %d0 | ||
81 | muls.w %d0, %d3 /* %d3 = 101 * (Cr - 128) */ | ||
82 | asr.l #8, %d3 | ||
83 | move.b %d3, (%a4)+ /* save rv for next line */ | ||
84 | 81 | ||
85 | /* luma for first pixel */ | 82 | /* luma for (very) first pixel */ |
86 | clr.l %d4 /* load y component */ | 83 | clr.l %d1 |
87 | move.b (%a1)+, %d4 | 84 | move.b (%a1)+, %d1 |
88 | moveq.l #74, %d0 | 85 | moveq.l #-126, %d0 |
89 | muls.w %d0, %d4 /* %d4 = 36 * Y */ | 86 | add.l %d1, %d0 /* y' (-0.5 ... +0.5) */ |
90 | asr.l #8, %d4 | 87 | mac.l %a5, %d0, %acc0 |
91 | subq.l #4, %d4 /* correction for (Y - 16) and rounding */ | 88 | mac.l %a5, %d0, %acc1 |
92 | move.l %d4, %d5 | 89 | mac.l %a5, %d0, %acc2 |
93 | move.l %d4, %d6 | ||
94 | |||
95 | /* combine & write first pixel */ | ||
96 | add.l %d1, %d4 /* %d4 = blue */ | ||
97 | add.l %d2, %d5 /* %d5 = green */ | ||
98 | add.l %d3, %d6 /* %d6 = red */ | ||
99 | |||
100 | move.l %d4, %d0 /* clamping */ | ||
101 | or.l %d5, %d0 | ||
102 | or.l %d6, %d0 | ||
103 | asr.l #6, %d0 | ||
104 | beq.s .yuv_all_ok1 | ||
105 | moveq.l #63, %d0 | ||
106 | cmp.l %d0, %d4 | ||
107 | bls.s .yuv_blue_ok1 | ||
108 | spl.b %d4 | ||
109 | and.l %d0, %d4 | ||
110 | .yuv_blue_ok1: | ||
111 | cmp.l %d0, %d5 | ||
112 | bls.s .yuv_green_ok1 | ||
113 | spl.b %d5 | ||
114 | and.l %d0, %d5 | ||
115 | .yuv_green_ok1: | ||
116 | cmp.l %d0, %d6 | ||
117 | bls.s .yuv_red_ok1 | ||
118 | spl.b %d6 | ||
119 | and.l %d0, %d6 | ||
120 | .yuv_red_ok1: | ||
121 | .yuv_all_ok1: | ||
122 | |||
123 | lsr.l #1, %d6 /* pack, convert to RGB565 and output */ | ||
124 | lsr.l #1, %d4 | ||
125 | lsl.l #6, %d6 | ||
126 | or.l %d6, %d5 | ||
127 | lsl.l #5, %d5 | ||
128 | or.l %d5, %d4 | ||
129 | move.w %d4, (%a0) | ||
130 | |||
131 | /* luma for second pixel */ | ||
132 | clr.l %d4 /* load y component */ | ||
133 | move.b (%a1)+, %d4 | ||
134 | moveq.l #74, %d0 | ||
135 | muls.w %d0, %d4 /* %d4 = 36 * Y */ | ||
136 | asr.l #8, %d4 | ||
137 | subq.l #4, %d4 /* correction for (Y - 16) and rounding */ | ||
138 | |||
139 | /* combine & write second pixel */ | ||
140 | add.l %d4, %d1 /* %d1 = blue */ | ||
141 | add.l %d4, %d2 /* %d2 = green */ | ||
142 | add.l %d4, %d3 /* %d3 = red */ | ||
143 | |||
144 | move.l %d1, %d0 /* clamping */ | ||
145 | or.l %d2, %d0 | ||
146 | or.l %d3, %d0 | ||
147 | asr.l #6, %d0 | ||
148 | beq.s .yuv_all_ok2 | ||
149 | moveq.l #63, %d0 | ||
150 | cmp.l %d0, %d1 | ||
151 | bls.s .yuv_blue_ok2 | ||
152 | spl.b %d1 | ||
153 | and.l %d0, %d1 | ||
154 | .yuv_blue_ok2: | ||
155 | cmp.l %d0, %d2 | ||
156 | bls.s .yuv_green_ok2 | ||
157 | spl.b %d2 | ||
158 | and.l %d0, %d2 | ||
159 | .yuv_green_ok2: | ||
160 | cmp.l %d0, %d3 | ||
161 | bls.s .yuv_red_ok2 | ||
162 | spl.b %d3 | ||
163 | and.l %d0, %d3 | ||
164 | .yuv_red_ok2: | ||
165 | .yuv_all_ok2: | ||
166 | 90 | ||
167 | lsr.l #1, %d3 /* pack, convert to RGB565 and output */ | 91 | bra.b .yuv_line_entry |
168 | lsr.l #1, %d1 | ||
169 | lsl.l #6, %d3 | ||
170 | or.l %d3, %d2 | ||
171 | lsl.l #5, %d2 | ||
172 | or.l %d2, %d1 | ||
173 | move.w %d1, (%a0) | ||
174 | 92 | ||
175 | cmp.l %a1,%a5 /* run %a1 up to end of line */ | 93 | .yuv_line_loop: |
176 | bhi.w .yuv_line_loop1 | 94 | /* chroma for first & second pixel */ |
177 | 95 | clr.l %d2 /* load u component */ | |
178 | /* Rewind chroma pointers */ | 96 | move.b (%a2)+, %d2 |
179 | movem.l (36+8, %sp), %a2-%a5 /* bu data, guv data, rv data, width */ | 97 | clr.l %d3 /* load v component */ |
180 | lea.l (%a1, %a5), %a5 /* next end address */ | 98 | move.b (%a3)+, %d3 |
99 | moveq.l #-128, %d0 | ||
100 | add.l %d0, %d2 | ||
101 | add.l %d0, %d3 | ||
181 | 102 | ||
182 | .yuv_line_loop2: | 103 | mac.l %a6, %d2, %acc0 /* bu */ |
183 | /* read saved chromas and sign extend */ | 104 | mac.l %d5, %d2, %acc1 /* gu */ |
184 | move.b (%a2)+, %d1 | 105 | mac.l %d6, %d3, %acc1 /* gv */ |
185 | extb.l %d1 | 106 | move.l #26881894, %d0 /* rv factor */ |
186 | move.b (%a3)+, %d2 | 107 | mac.l %d0, %d3, %acc2 /* rv */ |
187 | extb.l %d2 | ||
188 | move.b (%a4)+, %d3 | ||
189 | extb.l %d3 | ||
190 | 108 | ||
191 | /* luma for first pixel */ | 109 | /* luma for first pixel */ |
192 | clr.l %d4 /* load y component */ | 110 | clr.l %d1 |
193 | move.b (%a1)+, %d4 | 111 | move.b (%a1)+, %d1 |
194 | moveq.l #74, %d0 | 112 | moveq.l #-126, %d0 |
195 | muls.w %d0, %d4 /* %d4 = 36 * Y */ | 113 | add.l %d1, %d0 /* y' (-0.5 ... +0.5) */ |
196 | asr.l #8, %d4 | 114 | mac.l %a5, %d0, %acc0 |
197 | subq.l #4, %d4 /* correction for (Y - 16) and rounding */ | 115 | mac.l %a5, %d0, %acc1 |
198 | move.l %d4, %d5 | 116 | mac.l %a5, %d0, %acc2 |
199 | move.l %d4, %d6 | ||
200 | 117 | ||
201 | /* combine & write first pixel */ | 118 | move.w %d4, (%a0) |
202 | add.l %d1, %d4 /* %d4 = blue */ | 119 | /* LCD write is delayed one pixel to use it for filling the EMAC latency */ |
203 | add.l %d2, %d5 /* %d5 = green */ | 120 | |
204 | add.l %d3, %d6 /* %d6 = red */ | 121 | /* convert to RGB565, pack and output */ |
122 | .yuv_line_entry: | ||
123 | moveq.l #27, %d0 | ||
124 | move.l %acc0, %d2 | ||
125 | move.l %acc1, %d3 | ||
126 | move.l %acc2, %d4 | ||
127 | lsr.l %d0, %d2 | ||
128 | lsr.l %d0, %d4 | ||
129 | moveq.l #26, %d0 | ||
130 | lsr.l %d0, %d3 | ||
131 | lsl.l #6, %d4 | ||
132 | or.l %d3, %d4 | ||
133 | lsl.l #5, %d4 | ||
134 | or.l %d2, %d4 | ||
135 | eor.l %d7, %d4 | ||
136 | |||
137 | /* luma for second pixel as delta from the first */ | ||
138 | clr.l %d0 | ||
139 | move.b (%a1)+, %d0 | ||
140 | sub.l %d1, %d0 | ||
141 | mac.l %a5, %d0, %acc0 | ||
142 | mac.l %a5, %d0, %acc1 | ||
143 | mac.l %a5, %d0, %acc2 | ||
144 | |||
145 | move.w %d4, (%a0) | ||
146 | /* LCD write is delayed one pixel to use it for filling the EMAC latency */ | ||
147 | |||
148 | /* convert to RGB565, pack and output */ | ||
149 | moveq.l #27, %d0 | ||
150 | movclr.l %acc0, %d2 | ||
151 | movclr.l %acc1, %d3 | ||
152 | movclr.l %acc2, %d4 | ||
153 | lsr.l %d0, %d2 | ||
154 | lsr.l %d0, %d4 | ||
155 | moveq.l #26, %d0 | ||
156 | lsr.l %d0, %d3 | ||
157 | lsl.l #6, %d4 | ||
158 | or.l %d3, %d4 | ||
159 | lsl.l #5, %d4 | ||
160 | or.l %d2, %d4 | ||
161 | eor.l %d7, %d4 | ||
162 | |||
163 | cmp.l %a1, %a4 /* run %a1 up to end of line */ | ||
164 | bhi.w .yuv_line_loop | ||
205 | 165 | ||
206 | move.l %d4, %d0 /* clamping */ | 166 | tst.l (44+4, %sp) /* use original Y pointer as a flag to */ |
207 | or.l %d5, %d0 | 167 | beq.b .yuv_exit /* distinguish between first and second */ |
208 | or.l %d6, %d0 | 168 | clr.l (44+4, %sp) /* pixel line */ |
209 | asr.l #6, %d0 | ||
210 | beq.s .yuv_all_ok3 | ||
211 | moveq.l #63, %d0 | ||
212 | cmp.l %d0, %d4 | ||
213 | bls.s .yuv_blue_ok3 | ||
214 | spl.b %d4 | ||
215 | and.l %d0, %d4 | ||
216 | .yuv_blue_ok3: | ||
217 | cmp.l %d0, %d5 | ||
218 | bls.s .yuv_green_ok3 | ||
219 | spl.b %d5 | ||
220 | and.l %d0, %d5 | ||
221 | .yuv_green_ok3: | ||
222 | cmp.l %d0, %d6 | ||
223 | bls.s .yuv_red_ok3 | ||
224 | spl.b %d6 | ||
225 | and.l %d0, %d6 | ||
226 | .yuv_red_ok3: | ||
227 | .yuv_all_ok3: | ||
228 | 169 | ||
229 | lsr.l #1, %d6 /* pack, convert to RGB565 and output */ | 170 | /* Rewind chroma pointers */ |
230 | lsr.l #1, %d4 | 171 | movem.l (44+8, %sp), %a2-%a4 /* Cb data, Cr data, width */ |
231 | lsl.l #6, %d6 | 172 | lea.l (%a1, %a4), %a4 /* end address */ |
232 | or.l %d6, %d5 | 173 | bra.w .yuv_line_loop |
233 | lsl.l #5, %d5 | ||
234 | or.l %d5, %d4 | ||
235 | move.w %d4, (%a0) | ||
236 | |||
237 | /* luma for second pixel */ | ||
238 | clr.l %d4 /* load y component */ | ||
239 | move.b (%a1)+, %d4 | ||
240 | moveq.l #74, %d0 | ||
241 | muls.w %d0, %d4 /* %d4 = 36 * Y */ | ||
242 | asr.l #8, %d4 | ||
243 | subq.l #4, %d4 /* correction for (Y - 16) and rounding */ | ||
244 | |||
245 | /* combine & write second pixel */ | ||
246 | add.l %d4, %d1 /* %d1 = blue */ | ||
247 | add.l %d4, %d2 /* %d2 = green */ | ||
248 | add.l %d4, %d3 /* %d3 = red */ | ||
249 | 174 | ||
250 | move.l %d1, %d0 /* clamping */ | 175 | .yuv_exit: |
251 | or.l %d2, %d0 | 176 | move.w %d4, (%a0) /* write (very) last pixel */ |
252 | or.l %d3, %d0 | ||
253 | asr.l #6, %d0 | ||
254 | beq.s .yuv_all_ok4 | ||
255 | moveq.l #63, %d0 | ||
256 | cmp.l %d0, %d1 | ||
257 | bls.s .yuv_blue_ok4 | ||
258 | spl.b %d1 | ||
259 | and.l %d0, %d1 | ||
260 | .yuv_blue_ok4: | ||
261 | cmp.l %d0, %d2 | ||
262 | bls.s .yuv_green_ok4 | ||
263 | spl.b %d2 | ||
264 | and.l %d0, %d2 | ||
265 | .yuv_green_ok4: | ||
266 | cmp.l %d0, %d3 | ||
267 | bls.s .yuv_red_ok4 | ||
268 | spl.b %d3 | ||
269 | and.l %d0, %d3 | ||
270 | .yuv_red_ok4: | ||
271 | .yuv_all_ok4: | ||
272 | |||
273 | lsr.l #1, %d3 /* pack, convert to RGB565 and output */ | ||
274 | lsr.l #1, %d1 | ||
275 | lsl.l #6, %d3 | ||
276 | or.l %d3, %d2 | ||
277 | lsl.l #5, %d2 | ||
278 | or.l %d2, %d1 | ||
279 | move.w %d1, (%a0) | ||
280 | |||
281 | cmp.l %a1, %a5 /* run %a1 up to end of line */ | ||
282 | bhi.w .yuv_line_loop2 | ||
283 | 177 | ||
284 | movem.l (%sp), %d2-%d6/%a2-%a5 | 178 | movem.l (%sp), %d2-%d7/%a2-%a6 |
285 | lea.l (36, %sp), %sp /* restore registers */ | 179 | lea.l (44, %sp), %sp /* restore registers */ |
286 | 180 | ||
287 | rts | 181 | rts |
288 | .lcd_write_yuv420_lines_end: | 182 | .yuv_end: |
289 | .size lcd_write_yuv420_lines, .lcd_write_yuv420_lines_end - lcd_write_yuv420_lines | 183 | .size lcd_write_yuv420_lines, .yuv_end - lcd_write_yuv420_lines |