| 1 | /* |
| 2 | * (C) GraÅžvydas "notaz" Ignotas, 2013 |
| 3 | * |
| 4 | * This work is licensed under the terms of GNU GPL version 2 or later. |
| 5 | * See the COPYING file in the top-level directory. |
| 6 | */ |
| 7 | |
| 8 | #include "arm_features.h" |
| 9 | |
| 10 | .text |
| 11 | .align 2 |
| 12 | |
| 13 | @ lr=0x001f001f |
| 14 | @ trashes r11, r12 |
| 15 | .macro bgr555_to_rgb565_one rn |
| 16 | and r11, lr, \rn |
| 17 | and r12, lr, \rn, lsr #5 |
| 18 | and \rn, lr, \rn, lsr #10 |
| 19 | orr r12, r11, lsl #5 |
| 20 | orr \rn, r12, lsl #6 |
| 21 | .endm |
| 22 | |
| 23 | .macro bgr555_to_rgb565_one_i rn1 rn2 |
| 24 | and r12, lr, \rn1, lsr #5 |
| 25 | and \rn1,lr, \rn1, lsr #10 |
| 26 | orr r12, r11, lsl #5 |
| 27 | and r11, lr, \rn2 |
| 28 | orr \rn1,r12, lsl #6 |
| 29 | .endm |
| 30 | |
| 31 | .macro pld_ reg offs=#0 |
| 32 | #ifdef HAVE_ARMV6 |
| 33 | pld [\reg, \offs] |
| 34 | #endif |
| 35 | .endm |
| 36 | |
| 37 | FUNCTION(bgr555_to_rgb565): @ void *dst, const void *src, int bytes |
| 38 | push {r4-r11,lr} |
| 39 | mov lr, #0x001f |
| 40 | subs r2, #4*8 |
| 41 | orr lr, lr, lsl #16 |
| 42 | blt 1f |
| 43 | |
| 44 | @ src can be unaligned, but that's very rare, so just force it. |
| 45 | @ The manual says unaligned ldm should fault, and it does on |
| 46 | @ cortex-a78's 32bit mode, but curiously on cortex-a8 it just |
| 47 | @ works and loads the data correctly. |
| 48 | bic r1, r1, #3 |
| 49 | |
| 50 | 0: |
| 51 | ldmia r1!, {r3-r10} |
| 52 | subs r2, #4*8 |
| 53 | bic r12, r1, #0x1f |
| 54 | pld_ r12, #32*1 |
| 55 | and r11, lr, r3 |
| 56 | bgr555_to_rgb565_one_i r3 r4 |
| 57 | bgr555_to_rgb565_one_i r4 r5 |
| 58 | bgr555_to_rgb565_one_i r5 r6 |
| 59 | bgr555_to_rgb565_one_i r6 r7 |
| 60 | bgr555_to_rgb565_one_i r7 r8 |
| 61 | bgr555_to_rgb565_one_i r8 r9 |
| 62 | bgr555_to_rgb565_one_i r9 r10 |
| 63 | bgr555_to_rgb565_one_i r10 r10 |
| 64 | stmia r0!, {r3-r10} |
| 65 | bge 0b |
| 66 | |
| 67 | 1: |
| 68 | adds r2, #4*8 |
| 69 | popeq {r4-r11,pc} |
| 70 | |
| 71 | 2: |
| 72 | ldr r3, [r1], #4 |
| 73 | subs r2, #4 |
| 74 | bgr555_to_rgb565_one r3 |
| 75 | str r3, [r0], #4 |
| 76 | bgt 2b |
| 77 | |
| 78 | pop {r4-r11,pc} |
| 79 | |
| 80 | |
| 81 | #ifdef HAVE_ARMV6 /* v6-only due to potential misaligned reads */ |
| 82 | |
| 83 | # r1b0g0r0 g2r2b1g1 b3g3r3b2 |
| 84 | FUNCTION(bgr888_to_rgb565): |
| 85 | pld [r1] |
| 86 | push {r4-r10,lr} |
| 87 | |
| 88 | mov r10, #0x001f @ b mask |
| 89 | mov r12, #0x07e0 @ g mask |
| 90 | mov lr, #0xf800 @ r mask |
| 91 | |
| 92 | 0: |
| 93 | ldr r3, [r1], #4 @ may be unaligned |
| 94 | ldr r4, [r1], #4 |
| 95 | ldr r5, [r1], #4 |
| 96 | pld [r1, #32*1] |
| 97 | and r6, r10,r3, lsr #16+3 @ b0 |
| 98 | and r7, r12,r3, lsr #5 @ g0 |
| 99 | and r8, lr, r3, lsl #8 @ r0 |
| 100 | and r9, lr, r3, lsr #16 @ r1 |
| 101 | orr r6, r6, r7 |
| 102 | orr r6, r6, r8 @ r0g0b0 |
| 103 | |
| 104 | and r7, r12,r4, lsl #3 @ g1 |
| 105 | and r8, r10,r4, lsr #11 @ b1 |
| 106 | orr r9, r9, r7 |
| 107 | orr r9, r9, r8 @ r1g1b1 |
| 108 | and r7, lr, r4, lsr #8 @ r2 |
| 109 | and r8, r12,r4, lsr #21 @ g2 |
| 110 | pkhbt r9, r6, r9, lsl #16 |
| 111 | str r9, [r0], #4 |
| 112 | |
| 113 | and r6, r10,r5, lsr #3 @ b2 |
| 114 | orr r7, r7, r8 |
| 115 | orr r6, r6, r7 @ r2g2b2 |
| 116 | and r7, lr, r5 @ r3 |
| 117 | and r8, r12,r5, lsr #13 @ g3 |
| 118 | orr r7, r7, r5, lsr #27 @ r3b3 |
| 119 | orr r7, r7, r8 @ r3g3b3 |
| 120 | pkhbt r7, r6, r7, lsl #16 |
| 121 | str r7, [r0], #4 |
| 122 | subs r2, r2, #12 |
| 123 | bgt 0b |
| 124 | |
| 125 | pop {r4-r10,pc} |
| 126 | |
| 127 | #endif /* HAVE_ARMV6 */ |