1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
13 * This is a generic framework to display up to 33 shades of grey
14 * on low-depth bitmap LCDs (Archos b&w, Iriver 4-grey, iPod 4-grey)
17 * Copyright (C) 2004-2006 Jens Arnold
19 * All files in this archive are subject to the GNU General Public License.
20 * See the file COPYING in the source tree root for full license agreement.
22 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
23 * KIND, either express or implied.
25 ****************************************************************************/
29 #ifdef HAVE_LCD_BITMAP
32 /*** low-level drawing functions ***/
34 static void setpixel(unsigned char *address
)
36 *address
= _gray_info
.fg_index
;
39 static void clearpixel(unsigned char *address
)
41 *address
= _gray_info
.bg_index
;
44 static void flippixel(unsigned char *address
)
46 *address
= _gray_info
.depth
- *address
;
49 static void nopixel(unsigned char *address
)
54 void (* const _gray_pixelfuncs
[8])(unsigned char *address
) = {
55 flippixel
, nopixel
, setpixel
, setpixel
,
56 nopixel
, clearpixel
, nopixel
, clearpixel
59 /*** Drawing functions ***/
61 /* Clear the whole display */
62 void gray_clear_display(void)
64 int brightness
= (_gray_info
.drawmode
& DRMODE_INVERSEVID
) ?
65 _gray_info
.fg_index
: _gray_info
.bg_index
;
67 _gray_rb
->memset(_gray_info
.cur_buffer
, brightness
,
68 _GRAY_MULUQ(_gray_info
.width
, _gray_info
.height
));
71 /* Set a single pixel */
72 void gray_drawpixel(int x
, int y
)
74 if (((unsigned)x
< (unsigned)_gray_info
.width
)
75 && ((unsigned)y
< (unsigned)_gray_info
.height
))
76 #if LCD_PIXELFORMAT == HORIZONTAL_PACKING
77 _gray_pixelfuncs
[_gray_info
.drawmode
](&_gray_info
.cur_buffer
[_GRAY_MULUQ(y
,
78 _gray_info
.width
) + x
]);
80 _gray_pixelfuncs
[_gray_info
.drawmode
](&_gray_info
.cur_buffer
[_GRAY_MULUQ(x
,
81 _gray_info
.height
) + y
]);
86 void gray_drawline(int x1
, int y1
, int x2
, int y2
)
94 void (*pfunc
)(unsigned char *address
) = _gray_pixelfuncs
[_gray_info
.drawmode
];
96 deltax
= abs(x2
- x1
);
97 deltay
= abs(y2
- y1
);
101 if (deltax
>= deltay
)
104 d
= 2 * deltay
- deltax
;
106 dinc2
= (deltay
- deltax
) * 2;
113 d
= 2 * deltax
- deltay
;
115 dinc2
= (deltax
- deltay
) * 2;
119 numpixels
++; /* include endpoints */
136 for (i
= 0; i
< numpixels
; i
++)
138 if (((unsigned)x
< (unsigned)_gray_info
.width
)
139 && ((unsigned)y
< (unsigned)_gray_info
.height
))
140 #if LCD_PIXELFORMAT == HORIZONTAL_PACKING
141 pfunc(&_gray_info
.cur_buffer
[_GRAY_MULUQ(y
, _gray_info
.width
) + x
]);
143 pfunc(&_gray_info
.cur_buffer
[_GRAY_MULUQ(x
, _gray_info
.height
) + y
]);
161 #if LCD_PIXELFORMAT == HORIZONTAL_PACKING
163 /* Draw a horizontal line (optimised) */
164 void gray_hline(int x1
, int x2
, int y
)
169 bool fillopt
= false;
170 void (*pfunc
)(unsigned char *address
);
180 /* nothing to draw? */
181 if (((unsigned)y
>= (unsigned)_gray_info
.height
)
182 || (x1
>= _gray_info
.width
) || (x2
< 0))
188 if (x2
>= _gray_info
.width
)
189 x2
= _gray_info
.width
- 1;
191 if (_gray_info
.drawmode
& DRMODE_INVERSEVID
)
193 if (_gray_info
.drawmode
& DRMODE_BG
)
196 bits
= _gray_info
.bg_index
;
201 if (_gray_info
.drawmode
& DRMODE_FG
)
204 bits
= _gray_info
.fg_index
;
207 pfunc
= _gray_pixelfuncs
[_gray_info
.drawmode
];
208 dst
= &_gray_info
.cur_buffer
[_GRAY_MULUQ(y
, _gray_info
.width
) + x1
];
211 _gray_rb
->memset(dst
, bits
, x2
- x1
+ 1);
214 unsigned char *dst_end
= dst
+ x2
- x1
;
217 while (dst
<= dst_end
);
221 /* Draw a vertical line (optimised) */
222 void gray_vline(int x
, int y1
, int y2
)
225 unsigned char *dst
, *dst_end
;
226 void (*pfunc
)(unsigned char *address
);
236 /* nothing to draw? */
237 if (((unsigned)x
>= (unsigned)_gray_info
.width
)
238 || (y1
>= _gray_info
.height
) || (y2
< 0))
244 if (y2
>= _gray_info
.height
)
245 y2
= _gray_info
.height
- 1;
247 pfunc
= _gray_pixelfuncs
[_gray_info
.drawmode
];
248 dst
= &_gray_info
.cur_buffer
[_GRAY_MULUQ(y1
, _gray_info
.width
) + x
];
250 dst_end
= dst
+ _GRAY_MULUQ(y2
- y1
, _gray_info
.width
);
254 dst
+= _gray_info
.width
;
256 while (dst
<= dst_end
);
259 /* Draw a filled triangle */
260 void gray_filltriangle(int x1
, int y1
, int x2
, int y2
, int x3
, int y3
)
263 long fp_x1
, fp_x2
, fp_dx1
, fp_dx2
;
265 /* sort vertices by increasing y value */
268 if (y2
< y3
) /* y2 < y3 < y1 */
270 x
= x1
; x1
= x2
; x2
= x3
; x3
= x
;
271 y
= y1
; y1
= y2
; y2
= y3
; y3
= y
;
273 else if (y2
> y1
) /* y3 < y1 < y2 */
275 x
= x1
; x1
= x3
; x3
= x2
; x2
= x
;
276 y
= y1
; y1
= y3
; y3
= y2
; y2
= y
;
278 else /* y3 <= y2 <= y1 */
280 x
= x1
; x1
= x3
; x3
= x
;
281 y
= y1
; y1
= y3
; y3
= y
;
286 if (y2
< y1
) /* y2 < y1 <= y3 */
288 x
= x1
; x1
= x2
; x2
= x
;
289 y
= y1
; y1
= y2
; y2
= y
;
291 else if (y2
> y3
) /* y1 <= y3 < y2 */
293 x
= x2
; x2
= x3
; x3
= x
;
294 y
= y2
; y2
= y3
; y3
= y
;
296 /* else already sorted */
299 if (y1
< y3
) /* draw */
301 fp_dx1
= ((x3
- x1
) << 16) / (y3
- y1
);
302 fp_x1
= (x1
<< 16) + (1<<15) + (fp_dx1
>> 1);
304 if (y1
< y2
) /* first part */
306 fp_dx2
= ((x2
- x1
) << 16) / (y2
- y1
);
307 fp_x2
= (x1
<< 16) + (1<<15) + (fp_dx2
>> 1);
308 for (y
= y1
; y
< y2
; y
++)
310 gray_hline(fp_x1
>> 16, fp_x2
>> 16, y
);
315 if (y2
< y3
) /* second part */
317 fp_dx2
= ((x3
- x2
) << 16) / (y3
- y2
);
318 fp_x2
= (x2
<< 16) + (1<<15) + (fp_dx2
>> 1);
319 for (y
= y2
; y
< y3
; y
++)
321 gray_hline(fp_x1
>> 16, fp_x2
>> 16, y
);
328 #else /* LCD_PIXELFORMAT == VERTICAL_PACKING */
330 /* Draw a horizontal line (optimised) */
331 void gray_hline(int x1
, int x2
, int y
)
334 unsigned char *dst
, *dst_end
;
335 void (*pfunc
)(unsigned char *address
);
345 /* nothing to draw? */
346 if (((unsigned)y
>= (unsigned)_gray_info
.height
)
347 || (x1
>= _gray_info
.width
) || (x2
< 0))
353 if (x2
>= _gray_info
.width
)
354 x2
= _gray_info
.width
- 1;
356 pfunc
= _gray_pixelfuncs
[_gray_info
.drawmode
];
357 dst
= &_gray_info
.cur_buffer
[_GRAY_MULUQ(x1
, _gray_info
.height
) + y
];
359 dst_end
= dst
+ _GRAY_MULUQ(x2
- x1
, _gray_info
.height
);
363 dst
+= _gray_info
.height
;
365 while (dst
<= dst_end
);
368 /* Draw a vertical line (optimised) */
369 void gray_vline(int x
, int y1
, int y2
)
374 bool fillopt
= false;
375 void (*pfunc
)(unsigned char *address
);
385 /* nothing to draw? */
386 if (((unsigned)x
>= (unsigned)_gray_info
.width
)
387 || (y1
>= _gray_info
.height
) || (y2
< 0))
393 if (y2
>= _gray_info
.height
)
394 y2
= _gray_info
.height
- 1;
396 if (_gray_info
.drawmode
& DRMODE_INVERSEVID
)
398 if (_gray_info
.drawmode
& DRMODE_BG
)
401 bits
= _gray_info
.bg_index
;
406 if (_gray_info
.drawmode
& DRMODE_FG
)
409 bits
= _gray_info
.fg_index
;
412 pfunc
= _gray_pixelfuncs
[_gray_info
.drawmode
];
413 dst
= &_gray_info
.cur_buffer
[_GRAY_MULUQ(x
, _gray_info
.height
) + y1
];
416 _gray_rb
->memset(dst
, bits
, y2
- y1
+ 1);
419 unsigned char *dst_end
= dst
+ y2
- y1
;
422 while (dst
<= dst_end
);
426 /* Draw a filled triangle */
427 void gray_filltriangle(int x1
, int y1
, int x2
, int y2
, int x3
, int y3
)
430 long fp_y1
, fp_y2
, fp_dy1
, fp_dy2
;
432 /* sort vertices by increasing x value */
435 if (x2
< x3
) /* x2 < x3 < x1 */
437 x
= x1
; x1
= x2
; x2
= x3
; x3
= x
;
438 y
= y1
; y1
= y2
; y2
= y3
; y3
= y
;
440 else if (x2
> x1
) /* x3 < x1 < x2 */
442 x
= x1
; x1
= x3
; x3
= x2
; x2
= x
;
443 y
= y1
; y1
= y3
; y3
= y2
; y2
= y
;
445 else /* x3 <= x2 <= x1 */
447 x
= x1
; x1
= x3
; x3
= x
;
448 y
= y1
; y1
= y3
; y3
= y
;
453 if (x2
< x1
) /* x2 < x1 <= x3 */
455 x
= x1
; x1
= x2
; x2
= x
;
456 y
= y1
; y1
= y2
; y2
= y
;
458 else if (x2
> x3
) /* x1 <= x3 < x2 */
460 x
= x2
; x2
= x3
; x3
= x
;
461 y
= y2
; y2
= y3
; y3
= y
;
463 /* else already sorted */
466 if (x1
< x3
) /* draw */
468 fp_dy1
= ((y3
- y1
) << 16) / (x3
- x1
);
469 fp_y1
= (y1
<< 16) + (1<<15) + (fp_dy1
>> 1);
471 if (x1
< x2
) /* first part */
473 fp_dy2
= ((y2
- y1
) << 16) / (x2
- x1
);
474 fp_y2
= (y1
<< 16) + (1<<15) + (fp_dy2
>> 1);
475 for (x
= x1
; x
< x2
; x
++)
477 gray_vline(x
, fp_y1
>> 16, fp_y2
>> 16);
482 if (x2
< x3
) /* second part */
484 fp_dy2
= ((y3
- y2
) << 16) / (x3
- x2
);
485 fp_y2
= (y2
<< 16) + (1<<15) + (fp_dy2
>> 1);
486 for (x
= x2
; x
< x3
; x
++)
488 gray_vline(x
, fp_y1
>> 16, fp_y2
>> 16);
495 #endif /* LCD_PIXELFORMAT */
497 /* Draw a rectangular box */
498 void gray_drawrect(int x
, int y
, int width
, int height
)
500 if ((width
<= 0) || (height
<= 0))
503 int x2
= x
+ width
- 1;
504 int y2
= y
+ height
- 1;
506 gray_vline(x
, y
, y2
);
507 gray_vline(x2
, y
, y2
);
508 gray_hline(x
, x2
, y
);
509 gray_hline(x
, x2
, y2
);
512 /* Fill a rectangular area */
513 void gray_fillrect(int x
, int y
, int width
, int height
)
516 unsigned char *dst
, *dst_end
;
517 bool fillopt
= false;
518 void (*pfunc
)(unsigned char *address
);
520 /* nothing to draw? */
521 if ((width
<= 0) || (height
<= 0) || (x
>= _gray_info
.width
)
522 || (y
>= _gray_info
.height
) || (x
+ width
<= 0) || (y
+ height
<= 0))
536 if (x
+ width
> _gray_info
.width
)
537 width
= _gray_info
.width
- x
;
538 if (y
+ height
> _gray_info
.height
)
539 height
= _gray_info
.height
- y
;
541 if (_gray_info
.drawmode
& DRMODE_INVERSEVID
)
543 if (_gray_info
.drawmode
& DRMODE_BG
)
546 bits
= _gray_info
.bg_index
;
551 if (_gray_info
.drawmode
& DRMODE_FG
)
554 bits
= _gray_info
.fg_index
;
557 pfunc
= _gray_pixelfuncs
[_gray_info
.drawmode
];
558 #if LCD_PIXELFORMAT == HORIZONTAL_PACKING
559 dst
= &_gray_info
.cur_buffer
[_GRAY_MULUQ(y
, _gray_info
.width
) + x
];
560 dst_end
= dst
+ _GRAY_MULUQ(height
, _gray_info
.width
);
565 _gray_rb
->memset(dst
, bits
, width
);
568 unsigned char *dst_row
= dst
;
569 unsigned char *row_end
= dst_row
+ width
;
573 while (dst_row
< row_end
);
575 dst
+= _gray_info
.width
;
577 while (dst
< dst_end
);
579 dst
= &_gray_info
.cur_buffer
[_GRAY_MULUQ(x
, _gray_info
.height
) + y
];
580 dst_end
= dst
+ _GRAY_MULUQ(width
, _gray_info
.height
);
585 _gray_rb
->memset(dst
, bits
, height
);
588 unsigned char *dst_col
= dst
;
589 unsigned char *col_end
= dst_col
+ height
;
593 while (dst_col
< col_end
);
595 dst
+= _gray_info
.height
;
597 while (dst
< dst_end
);
601 /* About Rockbox' internal monochrome bitmap format:
603 * A bitmap contains one bit for every pixel that defines if that pixel is
604 * foreground (1) or background (0). Bits within a byte are arranged
605 * vertically, LSB at top.
606 * The bytes are stored in row-major order, with byte 0 being top left,
607 * byte 1 2nd from left etc. The first row of bytes defines pixel rows
608 * 0..7, the second row defines pixel row 8..15 etc. */
610 /* Draw a partial monochrome bitmap */
611 void gray_mono_bitmap_part(const unsigned char *src
, int src_x
, int src_y
,
612 int stride
, int x
, int y
, int width
, int height
)
614 const unsigned char *src_end
;
615 unsigned char *dst
, *dst_end
;
616 void (*fgfunc
)(unsigned char *address
);
617 void (*bgfunc
)(unsigned char *address
);
619 /* nothing to draw? */
620 if ((width
<= 0) || (height
<= 0) || (x
>= _gray_info
.width
)
621 || (y
>= _gray_info
.height
) || (x
+ width
<= 0) || (y
+ height
<= 0))
637 if (x
+ width
> _gray_info
.width
)
638 width
= _gray_info
.width
- x
;
639 if (y
+ height
> _gray_info
.height
)
640 height
= _gray_info
.height
- y
;
642 src
+= _GRAY_MULUQ(stride
, src_y
>> 3) + src_x
; /* move starting point */
644 src_end
= src
+ width
;
646 fgfunc
= _gray_pixelfuncs
[_gray_info
.drawmode
];
647 bgfunc
= _gray_pixelfuncs
[_gray_info
.drawmode
^ DRMODE_INVERSEVID
];
648 #if LCD_PIXELFORMAT == HORIZONTAL_PACKING
649 dst
= &_gray_info
.cur_buffer
[_GRAY_MULUQ(y
, _gray_info
.width
) + x
];
653 const unsigned char *src_col
= src
++;
654 unsigned char *dst_col
= dst
++;
655 unsigned data
= *src_col
>> src_y
;
656 int numbits
= 8 - src_y
;
658 dst_end
= dst_col
+ _GRAY_MULUQ(height
, _gray_info
.width
);
666 dst_col
+= _gray_info
.width
;
676 while (dst_col
< dst_end
);
678 while (src
< src_end
);
679 #else /* LCD_PIXELFORMAT == VERTICAL_PACKING */
680 dst
= &_gray_info
.cur_buffer
[_GRAY_MULUQ(x
, _gray_info
.height
) + y
];
684 const unsigned char *src_col
= src
++;
685 unsigned char *dst_col
= dst
;
686 unsigned data
= *src_col
>> src_y
;
687 int numbits
= 8 - src_y
;
689 dst_end
= dst_col
+ height
;
705 while (dst_col
< dst_end
);
707 dst
+= _gray_info
.height
;
709 while (src
< src_end
);
710 #endif /* LCD_PIXELFORMAT */
713 /* Draw a full monochrome bitmap */
714 void gray_mono_bitmap(const unsigned char *src
, int x
, int y
, int width
, int height
)
716 gray_mono_bitmap_part(src
, 0, 0, width
, x
, y
, width
, height
);
719 /* Draw a partial greyscale bitmap, canonical format */
720 void gray_gray_bitmap_part(const unsigned char *src
, int src_x
, int src_y
,
721 int stride
, int x
, int y
, int width
, int height
)
723 unsigned char *dst
, *dst_end
;
725 /* nothing to draw? */
726 if ((width
<= 0) || (height
<= 0) || (x
>= _gray_info
.width
)
727 || (y
>= _gray_info
.height
) || (x
+ width
<= 0) || (y
+ height
<= 0))
743 if (x
+ width
> _gray_info
.width
)
744 width
= _gray_info
.width
- x
;
745 if (y
+ height
> _gray_info
.height
)
746 height
= _gray_info
.height
- y
;
748 src
+= _GRAY_MULUQ(stride
, src_y
) + src_x
; /* move starting point */
749 #if LCD_PIXELFORMAT == HORIZONTAL_PACKING
750 dst
= &_gray_info
.cur_buffer
[_GRAY_MULUQ(y
, _gray_info
.width
) + x
];
751 dst_end
= dst
+ _GRAY_MULUQ(height
, _gray_info
.width
);
755 const unsigned char *src_row
= src
;
756 unsigned char *dst_row
= dst
;
757 unsigned char *row_end
= dst_row
+ width
;
760 *dst_row
++ = _gray_info
.idxtable
[*src_row
++];
761 while (dst_row
< row_end
);
764 dst
+= _gray_info
.width
;
766 while (dst
< dst_end
);
767 #else /* LCD_PIXELFORMAT == VERTICAL_PACKING */
768 dst
= &_gray_info
.cur_buffer
[_GRAY_MULUQ(x
, _gray_info
.height
) + y
];
769 dst_end
= dst
+ height
;
773 const unsigned char *src_row
= src
;
774 unsigned char *dst_row
= dst
++;
775 unsigned char *row_end
= dst_row
+ _GRAY_MULUQ(width
, _gray_info
.height
);
779 *dst_row
= _gray_info
.idxtable
[*src_row
++];
780 dst_row
+= _gray_info
.height
;
782 while (dst_row
< row_end
);
786 while (dst
< dst_end
);
787 #endif /* LCD_PIXELFORMAT */
790 /* Draw a full greyscale bitmap, canonical format */
791 void gray_gray_bitmap(const unsigned char *src
, int x
, int y
, int width
,
794 gray_gray_bitmap_part(src
, 0, 0, width
, x
, y
, width
, height
);
797 /* Put a string at a given pixel position, skipping first ofs pixel columns */
798 void gray_putsxyofs(int x
, int y
, int ofs
, const unsigned char *str
)
801 struct font
* pf
= _gray_rb
->font_get(_gray_info
.curfont
);
803 while ((ch
= *str
++) != '\0' && x
< _gray_info
.width
)
806 const unsigned char *bits
;
808 /* check input range */
809 if (ch
< pf
->firstchar
|| ch
>= pf
->firstchar
+pf
->size
)
810 ch
= pf
->defaultchar
;
813 /* get proportional width and glyph bits */
814 width
= pf
->width
? pf
->width
[ch
] : pf
->maxwidth
;
822 bits
= pf
->bits
+ (pf
->offset
?
823 pf
->offset
[ch
] : ((pf
->height
+ 7) / 8 * pf
->maxwidth
* ch
));
825 gray_mono_bitmap_part(bits
, ofs
, 0, width
, x
, y
, width
- ofs
, pf
->height
);
832 /* Put a string at a given pixel position */
833 void gray_putsxy(int x
, int y
, const unsigned char *str
)
835 gray_putsxyofs(x
, y
, 0, str
);
838 /*** Unbuffered drawing functions ***/
842 /* Clear the greyscale display (sets all pixels to white) */
843 void gray_ub_clear_display(void)
845 _gray_rb
->memset(_gray_info
.cur_buffer
, _gray_info
.depth
,
846 _GRAY_MULUQ(_gray_info
.width
, _gray_info
.height
));
850 /* Draw a partial greyscale bitmap, canonical format */
851 void gray_ub_gray_bitmap_part(const unsigned char *src
, int src_x
, int src_y
,
852 int stride
, int x
, int y
, int width
, int height
)
854 gray_gray_bitmap_part(src
, src_x
, src_y
, stride
, x
, y
, width
, height
);
855 gray_update_rect(x
, y
, width
, height
);
858 #else /* !SIMULATOR */
860 /* Clear the greyscale display (sets all pixels to white) */
861 void gray_ub_clear_display(void)
863 _gray_rb
->memset(_gray_info
.plane_data
, 0, _GRAY_MULUQ(_gray_info
.depth
,
864 _gray_info
.plane_size
));
867 #if LCD_PIXELFORMAT == HORIZONTAL_PACKING
869 /* Write a pixel block, defined by their brightnesses in a greymap.
870 Address is the byte in the first bitplane, src is the greymap start address,
871 mask determines which pixels of the destination block are changed. */
872 static void _writearray(unsigned char *address
, const unsigned char *src
,
875 unsigned long pat_stack
[8];
876 unsigned long *pat_ptr
= &pat_stack
[8];
879 const unsigned char *_src
;
880 unsigned _mask
, depth
, trash
;
885 /* precalculate the bit patterns with random shifts
886 for all 8 pixels and put them on an extra "stack" */
889 "mov %[mask], %[mask], lsl #24 \n" /* shift mask to upper byte */
890 "mov r3, #8 \n" /* loop count */
892 ".wa_loop: \n" /** load pattern for pixel **/
893 "mov r2, #0 \n" /* pattern for skipped pixel must be 0 */
894 "movs %[mask], %[mask], lsl #1 \n" /* shift out msb of mask */
895 "bcc .wa_skip \n" /* skip this pixel */
897 "ldrb r0, [%[src]] \n" /* load src byte */
898 "ldrb r0, [%[trns], r0] \n" /* idxtable into pattern index */
899 "ldr r2, [%[bpat], r0, lsl #2] \n" /* r2 = bitpattern[byte]; */
901 "add %[rnd], %[rnd], %[rnd], lsl #2 \n" /* multiply by 75 */
902 "rsb %[rnd], %[rnd], %[rnd], lsl #4 \n"
903 "add %[rnd], %[rnd], #74 \n" /* add another 74 */
904 /* Since the lower bits are not very random: get bits 8..15 (need max. 5) */
905 "and r1, %[rmsk], %[rnd], lsr #8 \n" /* ..and mask out unneeded bits */
907 "cmp r1, %[dpth] \n" /* random >= depth ? */
908 "subhs r1, r1, %[dpth] \n" /* yes: random -= depth */
910 "mov r0, r2, lsl r1 \n" /** rotate pattern **/
911 "sub r1, %[dpth], r1 \n"
912 "orr r2, r0, r2, lsr r1 \n"
915 "str r2, [%[patp], #-4]! \n" /* push on pattern stack */
917 "add %[src], %[src], #1 \n" /* src++; */
918 "subs r3, r3, #1 \n" /* loop 8 times (pixel block) */
923 [rnd
] "+r"(_gray_random_buffer
),
926 [bpat
]"r"(_gray_info
.bitpattern
),
927 [trns
]"r"(_gray_info
.idxtable
),
928 [dpth
]"r"(_gray_info
.depth
),
929 [rmsk
]"r"(_gray_info
.randmask
)
931 "r0", "r1", "r2", "r3"
936 depth
= _gray_info
.depth
;
938 /* set the bits for all 8 pixels in all bytes according to the
939 * precalculated patterns on the pattern stack */
942 "ldmia %[patp], {r1 - r8} \n" /* pop all 8 patterns */
944 /** Rotate the four 8x8 bit "blocks" within r1..r8 **/
946 "mov %[rx], #0xF0 \n" /** Stage 1: 4 bit "comb" **/
947 "orr %[rx], %[rx], %[rx], lsl #8 \n"
948 "orr %[rx], %[rx], %[rx], lsl #16\n" /* bitmask = ...11110000 */
949 "eor r0, r1, r5, lsl #4 \n"
950 "and r0, r0, %[rx] \n"
951 "eor r1, r1, r0 \n" /* r1 = ...e3e2e1e0a3a2a1a0 */
952 "eor r5, r5, r0, lsr #4 \n" /* r5 = ...e7e6e5e4a7a6a5a4 */
953 "eor r0, r2, r6, lsl #4 \n"
954 "and r0, r0, %[rx] \n"
955 "eor r2, r2, r0 \n" /* r2 = ...f3f2f1f0b3b2b1b0 */
956 "eor r6, r6, r0, lsr #4 \n" /* r6 = ...f7f6f5f4f7f6f5f4 */
957 "eor r0, r3, r7, lsl #4 \n"
958 "and r0, r0, %[rx] \n"
959 "eor r3, r3, r0 \n" /* r3 = ...g3g2g1g0c3c2c1c0 */
960 "eor r7, r7, r0, lsr #4 \n" /* r7 = ...g7g6g5g4c7c6c5c4 */
961 "eor r0, r4, r8, lsl #4 \n"
962 "and r0, r0, %[rx] \n"
963 "eor r4, r4, r0 \n" /* r4 = ...h3h2h1h0d3d2d1d0 */
964 "eor r8, r8, r0, lsr #4 \n" /* r8 = ...h7h6h5h4d7d6d5d4 */
966 "mov %[rx], #0xCC \n" /** Stage 2: 2 bit "comb" **/
967 "orr %[rx], %[rx], %[rx], lsl #8 \n"
968 "orr %[rx], %[rx], %[rx], lsl #16\n" /* bitmask = ...11001100 */
969 "eor r0, r1, r3, lsl #2 \n"
970 "and r0, r0, %[rx] \n"
971 "eor r1, r1, r0 \n" /* r1 = ...g1g0e1e0c1c0a1a0 */
972 "eor r3, r3, r0, lsr #2 \n" /* r3 = ...g3g2e3e2c3c2a3a2 */
973 "eor r0, r2, r4, lsl #2 \n"
974 "and r0, r0, %[rx] \n"
975 "eor r2, r2, r0 \n" /* r2 = ...h1h0f1f0d1d0b1b0 */
976 "eor r4, r4, r0, lsr #2 \n" /* r4 = ...h3h2f3f2d3d2b3b2 */
977 "eor r0, r5, r7, lsl #2 \n"
978 "and r0, r0, %[rx] \n"
979 "eor r5, r5, r0 \n" /* r5 = ...g5g4e5e4c5c4a5a4 */
980 "eor r7, r7, r0, lsr #2 \n" /* r7 = ...g7g6e7e6c7c6a7a6 */
981 "eor r0, r6, r8, lsl #2 \n"
982 "and r0, r0, %[rx] \n"
983 "eor r6, r6, r0 \n" /* r6 = ...h5h4f5f4d5d4b5b4 */
984 "eor r8, r8, r0, lsr #2 \n" /* r8 = ...h7h6f7f6d7d6b7b6 */
986 "mov %[rx], #0xAA \n" /** Stage 3: 1 bit "comb" **/
987 "orr %[rx], %[rx], %[rx], lsl #8 \n"
988 "orr %[rx], %[rx], %[rx], lsl #16\n" /* bitmask = ...10101010 */
989 "eor r0, r1, r2, lsl #1 \n"
990 "and r0, r0, %[rx] \n"
991 "eor r1, r1, r0 \n" /* r1 = ...h0g0f0e0d0c0b0a0 */
992 "eor r2, r2, r0, lsr #1 \n" /* r2 = ...h1g1f1e1d1c1b1a1 */
993 "eor r0, r3, r4, lsl #1 \n"
994 "and r0, r0, %[rx] \n"
995 "eor r3, r3, r0 \n" /* r3 = ...h2g2f2e2d2c2b2a2 */
996 "eor r4, r4, r0, lsr #1 \n" /* r4 = ...h3g3f3e3d3c3b3a3 */
997 "eor r0, r5, r6, lsl #1 \n"
998 "and r0, r0, %[rx] \n"
999 "eor r5, r5, r0 \n" /* r5 = ...h4g4f4e4d4c4b4a4 */
1000 "eor r6, r6, r0, lsr #1 \n" /* r6 = ...h5g5f5e5d5c5b5a5 */
1001 "eor r0, r7, r8, lsl #1 \n"
1002 "and r0, r0, %[rx] \n"
1003 "eor r7, r7, r0 \n" /* r7 = ...h6g6f6e6d6c6b6a6 */
1004 "eor r8, r8, r0, lsr #1 \n" /* r8 = ...h7g7f7e7d7c7b7a7 */
1006 "sub r0, %[dpth], #1 \n" /** shift out unused low bytes **/
1008 "add pc, pc, r0, lsl #2 \n" /* jump into shift streak */
1009 "mov r8, r8, lsr #8 \n" /* r8: never reached */
1010 "mov r7, r7, lsr #8 \n"
1011 "mov r6, r6, lsr #8 \n"
1012 "mov r5, r5, lsr #8 \n"
1013 "mov r4, r4, lsr #8 \n"
1014 "mov r3, r3, lsr #8 \n"
1015 "mov r2, r2, lsr #8 \n"
1016 "mov r1, r1, lsr #8 \n"
1018 "mvn %[mask], %[mask] \n" /* "set" mask -> "keep" mask */
1019 "ands %[mask], %[mask], #0xff \n"
1020 "beq .wa_sstart \n" /* short loop if no bits to keep */
1022 "ldrb r0, [pc, r0] \n" /* jump into full loop */
1025 ".byte .wa_f1 - .wa_ftable - 4 \n" /* [jump tables are tricky] */
1026 ".byte .wa_f2 - .wa_ftable - 4 \n"
1027 ".byte .wa_f3 - .wa_ftable - 4 \n"
1028 ".byte .wa_f4 - .wa_ftable - 4 \n"
1029 ".byte .wa_f5 - .wa_ftable - 4 \n"
1030 ".byte .wa_f6 - .wa_ftable - 4 \n"
1031 ".byte .wa_f7 - .wa_ftable - 4 \n"
1032 ".byte .wa_f8 - .wa_ftable - 4 \n"
1034 ".wa_floop: \n" /** full loop (bits to keep)**/
1036 "ldrb r0, [%[addr]] \n" /* load old byte */
1037 "and r0, r0, %[mask] \n" /* mask out replaced bits */
1038 "orr r0, r0, r1 \n" /* set new bits */
1039 "strb r0, [%[addr]], %[psiz] \n" /* store byte */
1040 "mov r1, r1, lsr #8 \n" /* shift out used-up byte */
1042 "ldrb r0, [%[addr]] \n"
1043 "and r0, r0, %[mask] \n"
1045 "strb r0, [%[addr]], %[psiz] \n"
1046 "mov r2, r2, lsr #8 \n"
1048 "ldrb r0, [%[addr]] \n"
1049 "and r0, r0, %[mask] \n"
1051 "strb r0, [%[addr]], %[psiz] \n"
1052 "mov r3, r3, lsr #8 \n"
1054 "ldrb r0, [%[addr]] \n"
1055 "and r0, r0, %[mask] \n"
1057 "strb r0, [%[addr]], %[psiz] \n"
1058 "mov r4, r4, lsr #8 \n"
1060 "ldrb r0, [%[addr]] \n"
1061 "and r0, r0, %[mask] \n"
1063 "strb r0, [%[addr]], %[psiz] \n"
1064 "mov r5, r5, lsr #8 \n"
1066 "ldrb r0, [%[addr]] \n"
1067 "and r0, r0, %[mask] \n"
1069 "strb r0, [%[addr]], %[psiz] \n"
1070 "mov r6, r6, lsr #8 \n"
1072 "ldrb r0, [%[addr]] \n"
1073 "and r0, r0, %[mask] \n"
1075 "strb r0, [%[addr]], %[psiz] \n"
1076 "mov r7, r7, lsr #8 \n"
1078 "ldrb r0, [%[addr]] \n"
1079 "and r0, r0, %[mask] \n"
1081 "strb r0, [%[addr]], %[psiz] \n"
1082 "mov r8, r8, lsr #8 \n"
1084 "subs %[dpth], %[dpth], #8 \n" /* next round if anything left */
1090 "ldrb r0, [pc, r0] \n" /* jump into short loop*/
1093 ".byte .wa_s1 - .wa_stable - 4 \n"
1094 ".byte .wa_s2 - .wa_stable - 4 \n"
1095 ".byte .wa_s3 - .wa_stable - 4 \n"
1096 ".byte .wa_s4 - .wa_stable - 4 \n"
1097 ".byte .wa_s5 - .wa_stable - 4 \n"
1098 ".byte .wa_s6 - .wa_stable - 4 \n"
1099 ".byte .wa_s7 - .wa_stable - 4 \n"
1100 ".byte .wa_s8 - .wa_stable - 4 \n"
1102 ".wa_sloop: \n" /** short loop (nothing to keep) **/
1104 "strb r1, [%[addr]], %[psiz] \n" /* store byte */
1105 "mov r1, r1, lsr #8 \n" /* shift out used-up byte */
1107 "strb r2, [%[addr]], %[psiz] \n"
1108 "mov r2, r2, lsr #8 \n"
1110 "strb r3, [%[addr]], %[psiz] \n"
1111 "mov r3, r3, lsr #8 \n"
1113 "strb r4, [%[addr]], %[psiz] \n"
1114 "mov r4, r4, lsr #8 \n"
1116 "strb r5, [%[addr]], %[psiz] \n"
1117 "mov r5, r5, lsr #8 \n"
1119 "strb r6, [%[addr]], %[psiz] \n"
1120 "mov r6, r6, lsr #8 \n"
1122 "strb r7, [%[addr]], %[psiz] \n"
1123 "mov r7, r7, lsr #8 \n"
1125 "strb r8, [%[addr]], %[psiz] \n"
1126 "mov r8, r8, lsr #8 \n"
1128 "subs %[dpth], %[dpth], #8 \n" /* next round if anything left */
1138 [psiz
]"r"(_gray_info
.plane_size
),
1139 [patp
]"[rx]"(pat_ptr
)
1141 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8"
1143 #else /* C version, for reference*/
1144 #warning C version of _writearray() used
1146 unsigned test
= 0x80;
1149 /* precalculate the bit patterns with random shifts
1150 * for all 8 pixels and put them on an extra "stack" */
1151 for (i
= 7; i
>= 0; i
--)
1159 pat
= _gray_info
.bitpattern
[_gray_info
.idxtable
[*src
]];
1161 /* shift pattern pseudo-random, simple & fast PRNG */
1162 _gray_random_buffer
= 75 * _gray_random_buffer
+ 74;
1163 shift
= (_gray_random_buffer
>> 8) & _gray_info
.randmask
;
1164 if (shift
>= _gray_info
.depth
)
1165 shift
-= _gray_info
.depth
;
1167 pat
= (pat
<< shift
) | (pat
>> (_gray_info
.depth
- shift
));
1175 end
= addr
+ _GRAY_MULUQ(_gray_info
.depth
, _gray_info
.plane_size
);
1177 /* set the bits for all 8 pixels in all bytes according to the
1178 * precalculated patterns on the pattern stack */
1179 test
= 1 << ((-_gray_info
.depth
) & 7);
1180 mask
= (~mask
& 0xff);
1187 for (i
= 7; i
>= 0; i
--)
1188 data
= (data
<< 1) | ((pat_stack
[i
] & test
) ? 1 : 0);
1191 addr
+= _gray_info
.plane_size
;
1202 for (i
= 7; i
>= 0; i
--)
1203 data
= (data
<< 1) | ((pat_stack
[i
] & test
) ? 1 : 0);
1205 *addr
= (*addr
& mask
) | data
;
1206 addr
+= _gray_info
.plane_size
;
1214 /* Draw a partial greyscale bitmap, canonical format */
1215 void gray_ub_gray_bitmap_part(const unsigned char *src
, int src_x
, int src_y
,
1216 int stride
, int x
, int y
, int width
, int height
)
1219 unsigned char *dst
, *dst_end
;
1220 unsigned mask
, mask_right
;
1222 /* nothing to draw? */
1223 if ((width
<= 0) || (height
<= 0) || (x
>= _gray_info
.width
)
1224 || (y
>= _gray_info
.height
) || (x
+ width
<= 0) || (y
+ height
<= 0))
1240 if (x
+ width
> _gray_info
.width
)
1241 width
= _gray_info
.width
- x
;
1242 if (y
+ height
> _gray_info
.height
)
1243 height
= _gray_info
.height
- y
;
1246 src
+= _GRAY_MULUQ(stride
, src_y
) + src_x
- shift
;
1247 dst
= _gray_info
.plane_data
+ (x
>> 3) + _GRAY_MULUQ(_gray_info
.bwidth
, y
);
1248 nx
= width
- 1 + shift
;
1250 mask
= 0xFFu
>> shift
;
1251 mask_right
= 0xFFu
<< (~nx
& 7);
1253 dst_end
= dst
+ _GRAY_MULUQ(_gray_info
.bwidth
, height
);
1256 const unsigned char *src_row
= src
;
1257 unsigned char *dst_row
= dst
;
1258 unsigned mask_row
= mask
;
1260 for (x
= nx
; x
>= 8; x
-= 8)
1262 _writearray(dst_row
++, src_row
, mask_row
);
1266 _writearray(dst_row
, src_row
, mask_row
& mask_right
);
1269 dst
+= _gray_info
.bwidth
;
1271 while (dst
< dst_end
);
1273 #else /* LCD_PIXELFORMAT == VERTICAL_PACKING */
1275 /* Write a pixel block, defined by their brightnesses in a greymap.
1276 Address is the byte in the first bitplane, src is the greymap start address,
1277 stride is the increment for the greymap to get to the next pixel, mask
1278 determines which pixels of the destination block are changed. */
1279 static void _writearray(unsigned char *address
, const unsigned char *src
,
1280 int stride
, unsigned mask
) __attribute__((noinline
));
1281 static void _writearray(unsigned char *address
, const unsigned char *src
,
1282 int stride
, unsigned mask
)
1284 unsigned long pat_stack
[8];
1285 unsigned long *pat_ptr
= &pat_stack
[8];
1286 unsigned char *addr
;
1287 #if CONFIG_CPU == SH7034
1288 const unsigned char *_src
;
1289 unsigned _mask
, depth
, trash
;
1294 /* precalculate the bit patterns with random shifts
1295 for all 8 pixels and put them on an extra "stack" */
1298 "mov #8, r3 \n" /* loop count */
1300 ".wa_loop: \n" /** load pattern for pixel **/
1301 "mov #0, r0 \n" /* pattern for skipped pixel must be 0 */
1302 "shlr %[mask] \n" /* shift out lsb of mask */
1303 "bf .wa_skip \n" /* skip this pixel */
1305 "mov.b @%[src], r0 \n" /* load src byte */
1307 "extu.b r0, r0 \n" /* extend unsigned */
1308 "mov.b @(r0,%[trns]), r0 \n" /* idxtable into pattern index */
1309 "mulu r1, %[rnd] \n" /* multiply by 75 */
1310 "extu.b r0, r0 \n" /* extend unsigned */
1312 "mov.l @(r0,%[bpat]), r4 \n" /* r4 = bitpattern[byte]; */
1313 "sts macl, %[rnd] \n"
1314 "add #74, %[rnd] \n" /* add another 74 */
1315 /* Since the lower bits are not very random: */
1316 "swap.b %[rnd], r1 \n" /* get bits 8..15 (need max. 5) */
1317 "and %[rmsk], r1 \n" /* mask out unneeded bits */
1319 "cmp/hs %[dpth], r1 \n" /* random >= depth ? */
1321 "sub %[dpth], r1 \n" /* yes: random -= depth; */
1324 "mov.l .ashlsi3, r0 \n" /** rotate pattern **/
1325 "jsr @r0 \n" /* r4 -> r0, shift left by r5 */
1328 "mov %[dpth], r5 \n"
1329 "sub r1, r5 \n" /* r5 = depth - r1 */
1330 "mov.l .lshrsi3, r1 \n"
1331 "jsr @r1 \n" /* r4 -> r0, shift right by r5 */
1332 "mov r0, r1 \n" /* store previous result in r1 */
1334 "or r1, r0 \n" /* rotated_pattern = r0 | r1 */
1337 "mov.l r0, @-%[patp] \n" /* push on pattern stack */
1339 "add %[stri], %[src] \n" /* src += stride; */
1340 "add #-1, r3 \n" /* loop 8 times (pixel block) */
1345 [rnd
] "+r"(_gray_random_buffer
),
1346 [patp
]"+r"(pat_ptr
),
1350 [dpth
]"r"(_gray_info
.depth
),
1351 [bpat
]"r"(_gray_info
.bitpattern
),
1352 [rmsk
]"r"(_gray_info
.randmask
),
1353 [trns
]"r"(_gray_info
.idxtable
)
1355 "r0", "r1", "r3", "r4", "r5", "macl", "pr"
1360 depth
= _gray_info
.depth
;
1362 /* set the bits for all 8 pixels in all bytes according to the
1363 * precalculated patterns on the pattern stack */
1366 "mov.l @%[patp]+, r8 \n" /* pop all 8 patterns */
1367 "mov.l @%[patp]+, r7 \n"
1368 "mov.l @%[patp]+, r6 \n"
1369 "mov.l @%[patp]+, r5 \n"
1370 "mov.l @%[patp]+, r4 \n"
1371 "mov.l @%[patp]+, r3 \n"
1372 "mov.l @%[patp]+, r2 \n"
1373 "mov.l @%[patp], r1 \n"
1375 /** Rotate the four 8x8 bit "blocks" within r1..r8 **/
1377 "mov.l .wa_mask4, %[rx] \n" /* bitmask = ...11110000 */
1378 "mov r5, r0 \n" /** Stage 1: 4 bit "comb" **/
1383 "xor r0, r1 \n" /* r1 = ...e3e2e1e0a3a2a1a0 */
1386 "xor r0, r5 \n" /* r5 = ...e7e6e5e4a7a6a5a4 */
1392 "xor r0, r2 \n" /* r2 = ...f3f2f1f0b3b2b1b0 */
1395 "xor r0, r6 \n" /* r6 = ...f7f6f5f4f7f6f5f4 */
1401 "xor r0, r3 \n" /* r3 = ...g3g2g1g0c3c2c1c0 */
1404 "xor r0, r7 \n" /* r7 = ...g7g6g5g4c7c6c5c4 */
1410 "xor r0, r4 \n" /* r4 = ...h3h2h1h0d3d2d1d0 */
1413 "xor r0, r8 \n" /* r8 = ...h7h6h5h4d7d6d5d4 */
1415 "mov.l .wa_mask2, %[rx] \n" /* bitmask = ...11001100 */
1416 "mov r3, r0 \n" /** Stage 2: 2 bit "comb" **/
1420 "xor r0, r1 \n" /* r1 = ...g1g0e1e0c1c0a1a0 */
1422 "xor r0, r3 \n" /* r3 = ...g3g2e3e2c3c2a3a2 */
1427 "xor r0, r2 \n" /* r2 = ...h1h0f1f0d1d0b1b0 */
1429 "xor r0, r4 \n" /* r4 = ...h3h2f3f2d3d2b3b2 */
1434 "xor r0, r5 \n" /* r5 = ...g5g4e5e4c5c4a5a4 */
1436 "xor r0, r7 \n" /* r7 = ...g7g6e7e6c7c6a7a6 */
1441 "xor r0, r6 \n" /* r6 = ...h5h4f5f4d5d4b5b4 */
1443 "xor r0, r8 \n" /* r8 = ...h7h6f7f6d7d6b7b6 */
1445 "mov.l .wa_mask1, %[rx] \n" /* bitmask = ...10101010 */
1446 "mov r2, r0 \n" /** Stage 3: 1 bit "comb" **/
1450 "xor r0, r1 \n" /* r1 = ...h0g0f0e0d0c0b0a0 */
1452 "xor r0, r2 \n" /* r2 = ...h1g1f1e1d1c1b1a1 */
1457 "xor r0, r3 \n" /* r3 = ...h2g2f2e2d2c2b2a2 */
1459 "xor r0, r4 \n" /* r4 = ...h3g3f3e3d3c3b3a3 */
1464 "xor r0, r5 \n" /* r5 = ...h4g4f4e4d4c4b4a4 */
1466 "xor r0, r6 \n" /* r6 = ...h5g5f5e5d5c5b5a5 */
1471 "xor r0, r7 \n" /* r7 = ...h6g6f6e6d6c6b6a6 */
1473 "xor r0, r8 \n" /* r8 = ...h7g7f7e7d7c7b7a7 */
1475 "mov %[dpth], %[rx] \n" /** shift out unused low bytes **/
1479 "mova .wa_pshift, r0 \n"
1482 "jmp @r0 \n" /* jump into shift streak */
1495 "not %[mask], %[mask] \n" /* "set" mask -> "keep" mask */
1496 "extu.b %[mask], %[mask] \n" /* mask out high bits */
1497 "tst %[mask], %[mask] \n"
1498 "bt .wa_sstart \n" /* short loop if nothing to keep */
1500 "mova .wa_ftable, r0 \n" /* jump into full loop */
1501 "mov.b @(r0, %[rx]), %[rx] \n"
1508 ".byte .wa_f1 - .wa_ftable \n"
1509 ".byte .wa_f2 - .wa_ftable \n"
1510 ".byte .wa_f3 - .wa_ftable \n"
1511 ".byte .wa_f4 - .wa_ftable \n"
1512 ".byte .wa_f5 - .wa_ftable \n"
1513 ".byte .wa_f6 - .wa_ftable \n"
1514 ".byte .wa_f7 - .wa_ftable \n"
1515 ".byte .wa_f8 - .wa_ftable \n"
1517 ".wa_floop: \n" /** full loop (there are bits to keep)**/
1519 "mov.b @%[addr], r0 \n" /* load old byte */
1520 "and %[mask], r0 \n" /* mask out replaced bits */
1521 "or r1, r0 \n" /* set new bits */
1522 "mov.b r0, @%[addr] \n" /* store byte */
1523 "add %[psiz], %[addr] \n"
1524 "shlr8 r1 \n" /* shift out used-up byte */
1526 "mov.b @%[addr], r0 \n"
1527 "and %[mask], r0 \n"
1529 "mov.b r0, @%[addr] \n"
1530 "add %[psiz], %[addr] \n"
1533 "mov.b @%[addr], r0 \n"
1534 "and %[mask], r0 \n"
1536 "mov.b r0, @%[addr] \n"
1537 "add %[psiz], %[addr] \n"
1540 "mov.b @%[addr], r0 \n"
1541 "and %[mask], r0 \n"
1543 "mov.b r0, @%[addr] \n"
1544 "add %[psiz], %[addr] \n"
1547 "mov.b @%[addr], r0 \n"
1548 "and %[mask], r0 \n"
1550 "mov.b r0, @%[addr] \n"
1551 "add %[psiz], %[addr] \n"
1554 "mov.b @%[addr], r0 \n"
1555 "and %[mask], r0 \n"
1557 "mov.b r0, @%[addr] \n"
1558 "add %[psiz], %[addr] \n"
1561 "mov.b @%[addr], r0 \n"
1562 "and %[mask], r0 \n"
1564 "mov.b r0, @%[addr] \n"
1565 "add %[psiz], %[addr] \n"
1568 "mov.b @%[addr], r0 \n"
1569 "and %[mask], r0 \n"
1571 "mov.b r0, @%[addr] \n"
1572 "add %[psiz], %[addr] \n"
1575 "add #-8, %[dpth] \n"
1576 "cmp/pl %[dpth] \n" /* next round if anything left */
1582 /* References to C library routines used in the precalc block */
1584 ".ashlsi3: \n" /* C library routine: */
1585 ".long ___ashlsi3 \n" /* shift r4 left by r5, result in r0 */
1586 ".lshrsi3: \n" /* C library routine: */
1587 ".long ___lshrsi3 \n" /* shift r4 right by r5, result in r0 */
1588 /* both routines preserve r4, destroy r5 and take ~16 cycles */
1590 /* Bitmasks for the bit block rotation */
1592 ".long 0xF0F0F0F0 \n"
1594 ".long 0xCCCCCCCC \n"
1596 ".long 0xAAAAAAAA \n"
1599 "mova .wa_stable, r0 \n" /* jump into short loop */
1600 "mov.b @(r0, %[rx]), %[rx] \n"
1607 ".byte .wa_s1 - .wa_stable \n"
1608 ".byte .wa_s2 - .wa_stable \n"
1609 ".byte .wa_s3 - .wa_stable \n"
1610 ".byte .wa_s4 - .wa_stable \n"
1611 ".byte .wa_s5 - .wa_stable \n"
1612 ".byte .wa_s6 - .wa_stable \n"
1613 ".byte .wa_s7 - .wa_stable \n"
1614 ".byte .wa_s8 - .wa_stable \n"
1616 ".wa_sloop: \n" /** short loop (nothing to keep) **/
1618 "mov.b r1, @%[addr] \n" /* store byte */
1619 "add %[psiz], %[addr] \n"
1620 "shlr8 r1 \n" /* shift out used-up byte */
1622 "mov.b r2, @%[addr] \n"
1623 "add %[psiz], %[addr] \n"
1626 "mov.b r3, @%[addr] \n"
1627 "add %[psiz], %[addr] \n"
1630 "mov.b r4, @%[addr] \n"
1631 "add %[psiz], %[addr] \n"
1634 "mov.b r5, @%[addr] \n"
1635 "add %[psiz], %[addr] \n"
1638 "mov.b r6, @%[addr] \n"
1639 "add %[psiz], %[addr] \n"
1642 "mov.b r7, @%[addr] \n"
1643 "add %[psiz], %[addr] \n"
1646 "mov.b r8, @%[addr] \n"
1647 "add %[psiz], %[addr] \n"
1650 "add #-8, %[dpth] \n"
1651 "cmp/pl %[dpth] \n" /* next round if anything left */
1661 [psiz
]"r"(_gray_info
.plane_size
),
1662 [patp
]"[rx]"(pat_ptr
)
1664 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "macl"
1666 #elif defined(CPU_COLDFIRE)
1667 const unsigned char *_src
;
1668 unsigned _mask
, depth
, trash
;
1673 /* precalculate the bit patterns with random shifts
1674 for all 8 pixels and put them on an extra "stack" */
1677 "moveq.l #8, %%d3 \n" /* loop count */
1679 ".wa_loop: \n" /** load pattern for pixel **/
1680 "clr.l %%d2 \n" /* pattern for skipped pixel must be 0 */
1681 "lsr.l #1, %[mask] \n" /* shift out lsb of mask */
1682 "bcc.b .wa_skip \n" /* skip this pixel */
1685 "move.b (%[src]), %%d0 \n" /* load src byte */
1686 "move.b (%%d0:l:1, %[trns]), %%d0 \n" /* idxtable into pattern index */
1687 "move.l (%%d0:l:4, %[bpat]), %%d2 \n" /* d2 = bitpattern[byte]; */
1689 "mulu.w #75, %[rnd] \n" /* multiply by 75 */
1690 "add.l #74, %[rnd] \n" /* add another 74 */
1691 /* Since the lower bits are not very random: */
1692 "move.l %[rnd], %%d1 \n"
1693 "lsr.l #8, %%d1 \n" /* get bits 8..15 (need max. 5) */
1694 "and.l %[rmsk], %%d1 \n" /* mask out unneeded bits */
1696 "cmp.l %[dpth], %%d1 \n" /* random >= depth ? */
1697 "blo.b .wa_ntrim \n"
1698 "sub.l %[dpth], %%d1 \n" /* yes: random -= depth; */
1701 "move.l %%d2, %%d0 \n" /** rotate pattern **/
1702 "lsl.l %%d1, %%d0 \n"
1703 "sub.l %[dpth], %%d1 \n"
1704 "neg.l %%d1 \n" /* d1 = depth - d1 */
1705 "lsr.l %%d1, %%d2 \n"
1706 "or.l %%d0, %%d2 \n"
1709 "move.l %%d2, -(%[patp]) \n" /* push on pattern stack */
1711 "add.l %[stri], %[src] \n" /* src += stride; */
1712 "subq.l #1, %%d3 \n" /* loop 8 times (pixel block) */
1716 [patp
]"+a"(pat_ptr
),
1717 [rnd
] "+d"(_gray_random_buffer
),
1721 [bpat
]"a"(_gray_info
.bitpattern
),
1722 [trns
]"a"(_gray_info
.idxtable
),
1723 [dpth
]"d"(_gray_info
.depth
),
1724 [rmsk
]"d"(_gray_info
.randmask
)
1726 "d0", "d1", "d2", "d3"
1730 _mask
= ~mask
& 0xff;
1731 depth
= _gray_info
.depth
;
1733 /* set the bits for all 8 pixels in all bytes according to the
1734 * precalculated patterns on the pattern stack */
1737 "movem.l (%[patp]), %%d1-%%d7/%%a0 \n" /* pop all 8 patterns */
1738 /* move.l %%d5, %[ax] */ /* need %%d5 as workspace, but not yet */
1740 /** Rotate the four 8x8 bit "blocks" within r1..r8 **/
1742 "move.l %%d1, %%d0 \n" /** Stage 1: 4 bit "comb" **/
1744 /* move.l %[ax], %%d5 */ /* already in d5 */
1745 "eor.l %%d5, %%d0 \n"
1746 "and.l #0xF0F0F0F0, %%d0 \n" /* bitmask = ...11110000 */
1747 "eor.l %%d0, %%d5 \n"
1748 "move.l %%d5, %[ax] \n" /* ax = ...h3h2h1h0d3d2d1d0 */
1750 "eor.l %%d0, %%d1 \n" /* d1 = ...h7h6h5h4d7d6d5d4 */
1751 "move.l %%d2, %%d0 \n"
1753 "eor.l %%d6, %%d0 \n"
1754 "and.l #0xF0F0F0F0, %%d0 \n"
1755 "eor.l %%d0, %%d6 \n" /* d6 = ...g3g2g1g0c3c2c1c0 */
1757 "eor.l %%d0, %%d2 \n" /* d2 = ...g7g6g5g4c7c6c5c4 */
1758 "move.l %%d3, %%d0 \n"
1760 "eor.l %%d7, %%d0 \n"
1761 "and.l #0xF0F0F0F0, %%d0 \n"
1762 "eor.l %%d0, %%d7 \n" /* d7 = ...f3f2f1f0b3b2b1b0 */
1764 "eor.l %%d0, %%d3 \n" /* d3 = ...f7f6f5f4f7f6f5f4 */
1765 "move.l %%d4, %%d0 \n"
1767 "move.l %%a0, %%d5 \n"
1768 "eor.l %%d5, %%d0 \n"
1769 "and.l #0xF0F0F0F0, %%d0 \n"
1770 "eor.l %%d0, %%d5 \n" /* (a0 = ...e3e2e1e0a3a2a1a0) */
1771 /* move.l %%d5, %%a0 */ /* but d5 is kept until next usage */
1773 "eor.l %%d0, %%d4 \n" /* d4 = ...e7e6e5e4a7a6a5a4 */
1775 "move.l %%d6, %%d0 \n" /** Stage 2: 2 bit "comb" **/
1777 /* move.l %%a0, %%d5 */ /* still in d5 */
1778 "eor.l %%d5, %%d0 \n"
1779 "and.l #0xCCCCCCCC, %%d0 \n" /* bitmask = ...11001100 */
1780 "eor.l %%d0, %%d5 \n"
1781 "move.l %%d5, %%a0 \n" /* a0 = ...g1g0e1e0c1c0a1a0 */
1783 "eor.l %%d0, %%d6 \n" /* d6 = ...g3g2e3e2c3c2a3a2 */
1784 "move.l %[ax], %%d5 \n"
1785 "move.l %%d5, %%d0 \n"
1787 "eor.l %%d7, %%d0 \n"
1788 "and.l #0xCCCCCCCC, %%d0 \n"
1789 "eor.l %%d0, %%d7 \n" /* r2 = ...h1h0f1f0d1d0b1b0 */
1791 "eor.l %%d0, %%d5 \n" /* (ax = ...h3h2f3f2d3d2b3b2) */
1792 /* move.l %%d5, %[ax] */ /* but d5 is kept until next usage */
1793 "move.l %%d2, %%d0 \n"
1795 "eor.l %%d4, %%d0 \n"
1796 "and.l #0xCCCCCCCC, %%d0 \n"
1797 "eor.l %%d0, %%d4 \n" /* d4 = ...g5g4e5e4c5c4a5a4 */
1799 "eor.l %%d0, %%d2 \n" /* d2 = ...g7g6e7e6c7c6a7a6 */
1800 "move.l %%d1, %%d0 \n"
1802 "eor.l %%d3, %%d0 \n"
1803 "and.l #0xCCCCCCCC, %%d0 \n"
1804 "eor.l %%d0, %%d3 \n" /* d3 = ...h5h4f5f4d5d4b5b4 */
1806 "eor.l %%d0, %%d1 \n" /* d1 = ...h7h6f7f6d7d6b7b6 */
1808 "move.l %%d1, %%d0 \n" /** Stage 3: 1 bit "comb" **/
1810 "eor.l %%d2, %%d0 \n"
1811 "and.l #0xAAAAAAAA, %%d0 \n" /* bitmask = ...10101010 */
1812 "eor.l %%d0, %%d2 \n" /* d2 = ...h6g6f6e6d6c6b6a6 */
1814 "eor.l %%d0, %%d1 \n" /* d1 = ...h7g7f7e7d7c7b7a7 */
1815 "move.l %%d3, %%d0 \n"
1817 "eor.l %%d4, %%d0 \n"
1818 "and.l #0xAAAAAAAA, %%d0 \n"
1819 "eor.l %%d0, %%d4 \n" /* d4 = ...h4g4f4e4d4c4b4a4 */
1821 "eor.l %%d0, %%d3 \n" /* d3 = ...h5g5f5e5d5c5b5a5 */
1822 /* move.l %[ax], %%d5 */ /* still in d5 */
1823 "move.l %%d5, %%d0 \n"
1825 "eor.l %%d6, %%d0 \n"
1826 "and.l #0xAAAAAAAA, %%d0 \n"
1827 "eor.l %%d0, %%d6 \n" /* d6 = ...h2g2f2e2d2c2b2a2 */
1829 "eor.l %%d0, %%d5 \n"
1830 "move.l %%d5, %[ax] \n" /* ax = ...h3g3f3e3d3c3b3a3 */
1831 "move.l %%d7, %%d0 \n"
1833 "move.l %%a0, %%d5 \n"
1834 "eor.l %%d5, %%d0 \n"
1835 "and.l #0xAAAAAAAA, %%d0 \n"
1836 "eor.l %%d0, %%d5 \n" /* (a0 = ...h0g0f0e0d0c0b0a0) */
1837 /* move.l %%d5, %%a0 */ /* but keep in d5 for shift streak */
1839 "eor.l %%d0, %%d7 \n" /* d7 = ...h1g1f1e1d1c1b1a1 */
1841 "move.l %[dpth], %%d0 \n" /** shift out unused low bytes **/
1842 "subq.l #1, %%d0 \n"
1844 "move.l %%d0, %%a0 \n"
1845 "move.l %[ax], %%d0 \n" /* all data in D registers */
1846 "jmp (2, %%pc, %%a0:l:2) \n" /* jump into shift streak */
1854 "move.l %%d0, %[ax] \n" /* put the 2 extra words back.. */
1855 "move.l %%a0, %%d0 \n" /* keep the value for later */
1856 "move.l %%d5, %%a0 \n" /* ..into their A registers */
1859 "jeq .wa_sstart \n" /* short loop if nothing to keep */
1861 "move.l %[mask], %%d5 \n" /* need mask in data reg. */
1862 "move.l %%d1, %[mask] \n" /* free d1 as working reg. */
1864 "jmp (2, %%pc, %%d0:l:2) \n" /* jump into full loop */
1872 /* bra.s .wa_f8 */ /* identical with target */
1874 ".wa_floop: \n" /** full loop (there are bits to keep)**/
1876 "move.b (%[addr]), %%d0 \n" /* load old byte */
1877 "and.l %%d5, %%d0 \n" /* mask out replaced bits */
1878 "move.l %%a0, %%d1 \n"
1879 "or.l %%d1, %%d0 \n" /* set new bits */
1880 "move.b %%d0, (%[addr]) \n" /* store byte */
1881 "add.l %[psiz], %[addr] \n"
1882 "lsr.l #8, %%d1 \n" /* shift out used-up byte */
1883 "move.l %%d1, %%a0 \n"
1885 "move.b (%[addr]), %%d0 \n"
1886 "and.l %%d5, %%d0 \n"
1887 "or.l %%d7, %%d0 \n"
1888 "move.b %%d0, (%[addr]) \n"
1889 "add.l %[psiz], %[addr] \n"
1892 "move.b (%[addr]), %%d0 \n"
1893 "and.l %%d5, %%d0 \n"
1894 "or.l %%d6, %%d0 \n"
1895 "move.b %%d0, (%[addr]) \n"
1896 "add.l %[psiz], %[addr] \n"
1899 "move.b (%[addr]), %%d0 \n"
1900 "and.l %%d5, %%d0 \n"
1901 "move.l %[ax], %%d1 \n"
1902 "or.l %%d1, %%d0 \n"
1903 "move.b %%d0, (%[addr]) \n"
1904 "add.l %[psiz], %[addr] \n"
1906 "move.l %%d1, %[ax] \n"
1908 "move.b (%[addr]), %%d0 \n"
1909 "and.l %%d5, %%d0 \n"
1910 "or.l %%d4, %%d0 \n"
1911 "move.b %%d0, (%[addr]) \n"
1912 "add.l %[psiz], %[addr] \n"
1915 "move.b (%[addr]), %%d0 \n"
1916 "and.l %%d5, %%d0 \n"
1917 "or.l %%d3, %%d0 \n"
1918 "move.b %%d0, (%[addr]) \n"
1919 "add.l %[psiz], %[addr] \n"
1922 "move.b (%[addr]), %%d0 \n"
1923 "and.l %%d5, %%d0 \n"
1924 "or.l %%d2, %%d0 \n"
1925 "move.b %%d0, (%[addr]) \n"
1926 "add.l %[psiz], %[addr] \n"
1929 "move.b (%[addr]), %%d0 \n"
1930 "and.l %%d5, %%d0 \n"
1931 "move.l %[mask], %%d1 \n"
1932 "or.l %%d1, %%d0 \n"
1933 "move.b %%d0, (%[addr]) \n"
1934 "add.l %[psiz], %[addr] \n"
1936 "move.l %%d1, %[mask] \n"
1938 "subq.l #8, %[dpth] \n"
1939 "tst.l %[dpth] \n" /* subq doesn't set flags for A reg */
1940 "jgt .wa_floop \n" /* next round if anything left */
1945 "jmp (2, %%pc, %%d0:l:2) \n" /* jump into short loop */
1953 /* bra.s .wa_s8 */ /* identical with target */
1955 ".wa_sloop: \n" /** short loop (nothing to keep) **/
1957 "move.l %%a0, %%d5 \n"
1958 "move.b %%d5, (%[addr]) \n" /* store byte */
1959 "add.l %[psiz], %[addr] \n"
1960 "lsr.l #8, %%d5 \n" /* shift out used-up byte */
1961 "move.l %%d5, %%a0 \n"
1963 "move.b %%d7, (%[addr]) \n"
1964 "add.l %[psiz], %[addr] \n"
1967 "move.b %%d6, (%[addr]) \n"
1968 "add.l %[psiz], %[addr] \n"
1971 "move.l %[ax], %%d5 \n"
1972 "move.b %%d5, (%[addr]) \n"
1973 "add.l %[psiz], %[addr] \n"
1975 "move.l %%d5, %[ax] \n"
1977 "move.b %%d4, (%[addr]) \n"
1978 "add.l %[psiz], %[addr] \n"
1981 "move.b %%d3, (%[addr]) \n"
1982 "add.l %[psiz], %[addr] \n"
1985 "move.b %%d2, (%[addr]) \n"
1986 "add.l %[psiz], %[addr] \n"
1989 "move.b %%d1, (%[addr]) \n"
1990 "add.l %[psiz], %[addr] \n"
1993 "subq.l #8, %[dpth] \n"
1994 "tst.l %[dpth] \n" /* subq doesn't set flags for A reg */
1995 "jgt .wa_sloop \n" /* next round if anything left */
2004 [psiz
]"a"(_gray_info
.plane_size
),
2005 [patp
]"[ax]"(pat_ptr
)
2007 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "a0"
2009 #elif defined(CPU_ARM)
2010 const unsigned char *_src
;
2011 unsigned _mask
, depth
, trash
;
2016 pat_ptr
= &pat_stack
[0];
2018 /* precalculate the bit patterns with random shifts
2019 for all 8 pixels and put them on an extra "stack" */
2022 "mov r3, #8 \n" /* loop count */
2024 ".wa_loop: \n" /** load pattern for pixel **/
2025 "mov r2, #0 \n" /* pattern for skipped pixel must be 0 */
2026 "movs %[mask], %[mask], lsr #1 \n" /* shift out msb of mask */
2027 "bcc .wa_skip \n" /* skip this pixel */
2029 "ldrb r0, [%[src]] \n" /* load src byte */
2030 "ldrb r0, [%[trns], r0] \n" /* idxtable into pattern index */
2031 "ldr r2, [%[bpat], r0, lsl #2] \n" /* r2 = bitpattern[byte]; */
2033 "add %[rnd], %[rnd], %[rnd], lsl #2 \n" /* multiply by 75 */
2034 "rsb %[rnd], %[rnd], %[rnd], lsl #4 \n"
2035 "add %[rnd], %[rnd], #74 \n" /* add another 74 */
2036 /* Since the lower bits are not very random: get bits 8..15 (need max. 5) */
2037 "and r1, %[rmsk], %[rnd], lsr #8 \n" /* ..and mask out unneeded bits */
2039 "cmp r1, %[dpth] \n" /* random >= depth ? */
2040 "subhs r1, r1, %[dpth] \n" /* yes: random -= depth */
2042 "mov r0, r2, lsl r1 \n" /** rotate pattern **/
2043 "sub r1, %[dpth], r1 \n"
2044 "orr r2, r0, r2, lsr r1 \n"
2047 "str r2, [%[patp]], #4 \n" /* push on pattern stack */
2049 "add %[src], %[src], %[stri] \n" /* src += stride; */
2050 "subs r3, r3, #1 \n" /* loop 8 times (pixel block) */
2054 [patp
]"+r"(pat_ptr
),
2055 [rnd
] "+r"(_gray_random_buffer
),
2059 [bpat
]"r"(_gray_info
.bitpattern
),
2060 [trns
]"r"(_gray_info
.idxtable
),
2061 [dpth
]"r"(_gray_info
.depth
),
2062 [rmsk
]"r"(_gray_info
.randmask
)
2064 "r0", "r1", "r2", "r3"
2069 depth
= _gray_info
.depth
;
2071 /* set the bits for all 8 pixels in all bytes according to the
2072 * precalculated patterns on the pattern stack */
2075 "ldmdb %[patp], {r1 - r8} \n" /* pop all 8 patterns */
2077 /** Rotate the four 8x8 bit "blocks" within r1..r8 **/
2079 "mov %[rx], #0xF0 \n" /** Stage 1: 4 bit "comb" **/
2080 "orr %[rx], %[rx], %[rx], lsl #8 \n"
2081 "orr %[rx], %[rx], %[rx], lsl #16\n" /* bitmask = ...11110000 */
2082 "eor r0, r1, r5, lsl #4 \n"
2083 "and r0, r0, %[rx] \n"
2084 "eor r1, r1, r0 \n" /* r1 = ...e3e2e1e0a3a2a1a0 */
2085 "eor r5, r5, r0, lsr #4 \n" /* r5 = ...e7e6e5e4a7a6a5a4 */
2086 "eor r0, r2, r6, lsl #4 \n"
2087 "and r0, r0, %[rx] \n"
2088 "eor r2, r2, r0 \n" /* r2 = ...f3f2f1f0b3b2b1b0 */
2089 "eor r6, r6, r0, lsr #4 \n" /* r6 = ...f7f6f5f4f7f6f5f4 */
2090 "eor r0, r3, r7, lsl #4 \n"
2091 "and r0, r0, %[rx] \n"
2092 "eor r3, r3, r0 \n" /* r3 = ...g3g2g1g0c3c2c1c0 */
2093 "eor r7, r7, r0, lsr #4 \n" /* r7 = ...g7g6g5g4c7c6c5c4 */
2094 "eor r0, r4, r8, lsl #4 \n"
2095 "and r0, r0, %[rx] \n"
2096 "eor r4, r4, r0 \n" /* r4 = ...h3h2h1h0d3d2d1d0 */
2097 "eor r8, r8, r0, lsr #4 \n" /* r8 = ...h7h6h5h4d7d6d5d4 */
2099 "mov %[rx], #0xCC \n" /** Stage 2: 2 bit "comb" **/
2100 "orr %[rx], %[rx], %[rx], lsl #8 \n"
2101 "orr %[rx], %[rx], %[rx], lsl #16\n" /* bitmask = ...11001100 */
2102 "eor r0, r1, r3, lsl #2 \n"
2103 "and r0, r0, %[rx] \n"
2104 "eor r1, r1, r0 \n" /* r1 = ...g1g0e1e0c1c0a1a0 */
2105 "eor r3, r3, r0, lsr #2 \n" /* r3 = ...g3g2e3e2c3c2a3a2 */
2106 "eor r0, r2, r4, lsl #2 \n"
2107 "and r0, r0, %[rx] \n"
2108 "eor r2, r2, r0 \n" /* r2 = ...h1h0f1f0d1d0b1b0 */
2109 "eor r4, r4, r0, lsr #2 \n" /* r4 = ...h3h2f3f2d3d2b3b2 */
2110 "eor r0, r5, r7, lsl #2 \n"
2111 "and r0, r0, %[rx] \n"
2112 "eor r5, r5, r0 \n" /* r5 = ...g5g4e5e4c5c4a5a4 */
2113 "eor r7, r7, r0, lsr #2 \n" /* r7 = ...g7g6e7e6c7c6a7a6 */
2114 "eor r0, r6, r8, lsl #2 \n"
2115 "and r0, r0, %[rx] \n"
2116 "eor r6, r6, r0 \n" /* r6 = ...h5h4f5f4d5d4b5b4 */
2117 "eor r8, r8, r0, lsr #2 \n" /* r8 = ...h7h6f7f6d7d6b7b6 */
2119 "mov %[rx], #0xAA \n" /** Stage 3: 1 bit "comb" **/
2120 "orr %[rx], %[rx], %[rx], lsl #8 \n"
2121 "orr %[rx], %[rx], %[rx], lsl #16\n" /* bitmask = ...10101010 */
2122 "eor r0, r1, r2, lsl #1 \n"
2123 "and r0, r0, %[rx] \n"
2124 "eor r1, r1, r0 \n" /* r1 = ...h0g0f0e0d0c0b0a0 */
2125 "eor r2, r2, r0, lsr #1 \n" /* r2 = ...h1g1f1e1d1c1b1a1 */
2126 "eor r0, r3, r4, lsl #1 \n"
2127 "and r0, r0, %[rx] \n"
2128 "eor r3, r3, r0 \n" /* r3 = ...h2g2f2e2d2c2b2a2 */
2129 "eor r4, r4, r0, lsr #1 \n" /* r4 = ...h3g3f3e3d3c3b3a3 */
2130 "eor r0, r5, r6, lsl #1 \n"
2131 "and r0, r0, %[rx] \n"
2132 "eor r5, r5, r0 \n" /* r5 = ...h4g4f4e4d4c4b4a4 */
2133 "eor r6, r6, r0, lsr #1 \n" /* r6 = ...h5g5f5e5d5c5b5a5 */
2134 "eor r0, r7, r8, lsl #1 \n"
2135 "and r0, r0, %[rx] \n"
2136 "eor r7, r7, r0 \n" /* r7 = ...h6g6f6e6d6c6b6a6 */
2137 "eor r8, r8, r0, lsr #1 \n" /* r8 = ...h7g7f7e7d7c7b7a7 */
2139 "sub r0, %[dpth], #1 \n" /** shift out unused low bytes **/
2141 "add pc, pc, r0, lsl #2 \n" /* jump into shift streak */
2142 "mov r8, r8, lsr #8 \n" /* r8: never reached */
2143 "mov r7, r7, lsr #8 \n"
2144 "mov r6, r6, lsr #8 \n"
2145 "mov r5, r5, lsr #8 \n"
2146 "mov r4, r4, lsr #8 \n"
2147 "mov r3, r3, lsr #8 \n"
2148 "mov r2, r2, lsr #8 \n"
2149 "mov r1, r1, lsr #8 \n"
2151 "mvn %[mask], %[mask] \n" /* "set" mask -> "keep" mask */
2152 "ands %[mask], %[mask], #0xff \n"
2153 "beq .wa_sstart \n" /* short loop if no bits to keep */
2155 "ldrb r0, [pc, r0] \n" /* jump into full loop */
2158 ".byte .wa_f1 - .wa_ftable - 4 \n" /* [jump tables are tricky] */
2159 ".byte .wa_f2 - .wa_ftable - 4 \n"
2160 ".byte .wa_f3 - .wa_ftable - 4 \n"
2161 ".byte .wa_f4 - .wa_ftable - 4 \n"
2162 ".byte .wa_f5 - .wa_ftable - 4 \n"
2163 ".byte .wa_f6 - .wa_ftable - 4 \n"
2164 ".byte .wa_f7 - .wa_ftable - 4 \n"
2165 ".byte .wa_f8 - .wa_ftable - 4 \n"
2167 ".wa_floop: \n" /** full loop (bits to keep)**/
2169 "ldrb r0, [%[addr]] \n" /* load old byte */
2170 "and r0, r0, %[mask] \n" /* mask out replaced bits */
2171 "orr r0, r0, r1 \n" /* set new bits */
2172 "strb r0, [%[addr]], %[psiz] \n" /* store byte */
2173 "mov r1, r1, lsr #8 \n" /* shift out used-up byte */
2175 "ldrb r0, [%[addr]] \n"
2176 "and r0, r0, %[mask] \n"
2178 "strb r0, [%[addr]], %[psiz] \n"
2179 "mov r2, r2, lsr #8 \n"
2181 "ldrb r0, [%[addr]] \n"
2182 "and r0, r0, %[mask] \n"
2184 "strb r0, [%[addr]], %[psiz] \n"
2185 "mov r3, r3, lsr #8 \n"
2187 "ldrb r0, [%[addr]] \n"
2188 "and r0, r0, %[mask] \n"
2190 "strb r0, [%[addr]], %[psiz] \n"
2191 "mov r4, r4, lsr #8 \n"
2193 "ldrb r0, [%[addr]] \n"
2194 "and r0, r0, %[mask] \n"
2196 "strb r0, [%[addr]], %[psiz] \n"
2197 "mov r5, r5, lsr #8 \n"
2199 "ldrb r0, [%[addr]] \n"
2200 "and r0, r0, %[mask] \n"
2202 "strb r0, [%[addr]], %[psiz] \n"
2203 "mov r6, r6, lsr #8 \n"
2205 "ldrb r0, [%[addr]] \n"
2206 "and r0, r0, %[mask] \n"
2208 "strb r0, [%[addr]], %[psiz] \n"
2209 "mov r7, r7, lsr #8 \n"
2211 "ldrb r0, [%[addr]] \n"
2212 "and r0, r0, %[mask] \n"
2214 "strb r0, [%[addr]], %[psiz] \n"
2215 "mov r8, r8, lsr #8 \n"
2217 "subs %[dpth], %[dpth], #8 \n" /* next round if anything left */
2223 "ldrb r0, [pc, r0] \n" /* jump into short loop*/
2226 ".byte .wa_s1 - .wa_stable - 4 \n"
2227 ".byte .wa_s2 - .wa_stable - 4 \n"
2228 ".byte .wa_s3 - .wa_stable - 4 \n"
2229 ".byte .wa_s4 - .wa_stable - 4 \n"
2230 ".byte .wa_s5 - .wa_stable - 4 \n"
2231 ".byte .wa_s6 - .wa_stable - 4 \n"
2232 ".byte .wa_s7 - .wa_stable - 4 \n"
2233 ".byte .wa_s8 - .wa_stable - 4 \n"
2235 ".wa_sloop: \n" /** short loop (nothing to keep) **/
2237 "strb r1, [%[addr]], %[psiz] \n" /* store byte */
2238 "mov r1, r1, lsr #8 \n" /* shift out used-up byte */
2240 "strb r2, [%[addr]], %[psiz] \n"
2241 "mov r2, r2, lsr #8 \n"
2243 "strb r3, [%[addr]], %[psiz] \n"
2244 "mov r3, r3, lsr #8 \n"
2246 "strb r4, [%[addr]], %[psiz] \n"
2247 "mov r4, r4, lsr #8 \n"
2249 "strb r5, [%[addr]], %[psiz] \n"
2250 "mov r5, r5, lsr #8 \n"
2252 "strb r6, [%[addr]], %[psiz] \n"
2253 "mov r6, r6, lsr #8 \n"
2255 "strb r7, [%[addr]], %[psiz] \n"
2256 "mov r7, r7, lsr #8 \n"
2258 "strb r8, [%[addr]], %[psiz] \n"
2259 "mov r8, r8, lsr #8 \n"
2261 "subs %[dpth], %[dpth], #8 \n" /* next round if anything left */
2271 [psiz
]"r"(_gray_info
.plane_size
),
2272 [patp
]"[rx]"(pat_ptr
)
2274 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8"
2276 #else /* C version, for reference*/
2277 #warning C version of _writearray() used
2282 /* precalculate the bit patterns with random shifts
2283 * for all 8 pixels and put them on an extra "stack" */
2284 for (i
= 7; i
>= 0; i
--)
2292 pat
= _gray_info
.bitpattern
[_gray_info
.idxtable
[*src
]];
2294 /* shift pattern pseudo-random, simple & fast PRNG */
2295 _gray_random_buffer
= 75 * _gray_random_buffer
+ 74;
2296 shift
= (_gray_random_buffer
>> 8) & _gray_info
.randmask
;
2297 if (shift
>= _gray_info
.depth
)
2298 shift
-= _gray_info
.depth
;
2300 pat
= (pat
<< shift
) | (pat
>> (_gray_info
.depth
- shift
));
2308 end
= addr
+ _GRAY_MULUQ(_gray_info
.depth
, _gray_info
.plane_size
);
2310 /* set the bits for all 8 pixels in all bytes according to the
2311 * precalculated patterns on the pattern stack */
2312 test
= 1 << ((-_gray_info
.depth
) & 7);
2313 mask
= (~mask
& 0xff);
2320 for (i
= 0; i
< 8; i
++)
2321 data
= (data
<< 1) | ((pat_stack
[i
] & test
) ? 1 : 0);
2324 addr
+= _gray_info
.plane_size
;
2335 for (i
= 0; i
< 8; i
++)
2336 data
= (data
<< 1) | ((pat_stack
[i
] & test
) ? 1 : 0);
2338 *addr
= (*addr
& mask
) | data
;
2339 addr
+= _gray_info
.plane_size
;
2347 /* Draw a partial greyscale bitmap, canonical format */
2348 void gray_ub_gray_bitmap_part(const unsigned char *src
, int src_x
, int src_y
,
2349 int stride
, int x
, int y
, int width
, int height
)
2352 unsigned char *dst
, *dst_end
;
2353 unsigned mask
, mask_bottom
;
2355 /* nothing to draw? */
2356 if ((width
<= 0) || (height
<= 0) || (x
>= _gray_info
.width
)
2357 || (y
>= _gray_info
.height
) || (x
+ width
<= 0) || (y
+ height
<= 0))
2373 if (x
+ width
> _gray_info
.width
)
2374 width
= _gray_info
.width
- x
;
2375 if (y
+ height
> _gray_info
.height
)
2376 height
= _gray_info
.height
- y
;
2379 src
+= _GRAY_MULUQ(stride
, src_y
) + src_x
- _GRAY_MULUQ(stride
, shift
);
2380 dst
= _gray_info
.plane_data
+ x
2381 + _GRAY_MULUQ(_gray_info
.width
, y
>> 3);
2382 ny
= height
- 1 + shift
;
2384 mask
= 0xFFu
<< shift
;
2385 mask_bottom
= 0xFFu
>> (~ny
& 7);
2387 for (; ny
>= 8; ny
-= 8)
2389 const unsigned char *src_row
= src
;
2390 unsigned char *dst_row
= dst
;
2392 dst_end
= dst_row
+ width
;
2394 _writearray(dst_row
++, src_row
++, stride
, mask
);
2395 while (dst_row
< dst_end
);
2398 dst
+= _gray_info
.width
;
2401 mask
&= mask_bottom
;
2402 dst_end
= dst
+ width
;
2404 _writearray(dst
++, src
++, stride
, mask
);
2405 while (dst
< dst_end
);
2407 #endif /* LCD_PIXELFORMAT */
2409 #endif /* !SIMULATOR */
2411 /* Draw a full greyscale bitmap, canonical format */
2412 void gray_ub_gray_bitmap(const unsigned char *src
, int x
, int y
, int width
,
2415 gray_ub_gray_bitmap_part(src
, 0, 0, width
, x
, y
, width
, height
);
2418 #endif /* HAVE_LCD_BITMAP */