xref: /aosp_15_r20/external/libjpeg-turbo/simd/arm/jchuff.h (revision dfc6aa5c1cfd4bc4e2018dc74aa96e29ee49c6da)
1*dfc6aa5cSAndroid Build Coastguard Worker /*
2*dfc6aa5cSAndroid Build Coastguard Worker  * jchuff.h
3*dfc6aa5cSAndroid Build Coastguard Worker  *
4*dfc6aa5cSAndroid Build Coastguard Worker  * This file was part of the Independent JPEG Group's software:
5*dfc6aa5cSAndroid Build Coastguard Worker  * Copyright (C) 1991-1997, Thomas G. Lane.
6*dfc6aa5cSAndroid Build Coastguard Worker  * libjpeg-turbo Modifications:
7*dfc6aa5cSAndroid Build Coastguard Worker  * Copyright (C) 2009, 2018, 2021, D. R. Commander.
8*dfc6aa5cSAndroid Build Coastguard Worker  * Copyright (C) 2018, Matthias Räncker.
9*dfc6aa5cSAndroid Build Coastguard Worker  * Copyright (C) 2020-2021, Arm Limited.
10*dfc6aa5cSAndroid Build Coastguard Worker  * For conditions of distribution and use, see the accompanying README.ijg
11*dfc6aa5cSAndroid Build Coastguard Worker  * file.
12*dfc6aa5cSAndroid Build Coastguard Worker  */
13*dfc6aa5cSAndroid Build Coastguard Worker 
14*dfc6aa5cSAndroid Build Coastguard Worker /* Expanded entropy encoder object for Huffman encoding.
15*dfc6aa5cSAndroid Build Coastguard Worker  *
16*dfc6aa5cSAndroid Build Coastguard Worker  * The savable_state subrecord contains fields that change within an MCU,
17*dfc6aa5cSAndroid Build Coastguard Worker  * but must not be updated permanently until we complete the MCU.
18*dfc6aa5cSAndroid Build Coastguard Worker  */
19*dfc6aa5cSAndroid Build Coastguard Worker 
20*dfc6aa5cSAndroid Build Coastguard Worker #if defined(__aarch64__) || defined(_M_ARM64)
21*dfc6aa5cSAndroid Build Coastguard Worker #define BIT_BUF_SIZE  64
22*dfc6aa5cSAndroid Build Coastguard Worker #else
23*dfc6aa5cSAndroid Build Coastguard Worker #define BIT_BUF_SIZE  32
24*dfc6aa5cSAndroid Build Coastguard Worker #endif
25*dfc6aa5cSAndroid Build Coastguard Worker 
26*dfc6aa5cSAndroid Build Coastguard Worker typedef struct {
27*dfc6aa5cSAndroid Build Coastguard Worker   size_t put_buffer;                    /* current bit accumulation buffer */
28*dfc6aa5cSAndroid Build Coastguard Worker   int free_bits;                        /* # of bits available in it */
29*dfc6aa5cSAndroid Build Coastguard Worker   int last_dc_val[MAX_COMPS_IN_SCAN];   /* last DC coef for each component */
30*dfc6aa5cSAndroid Build Coastguard Worker } savable_state;
31*dfc6aa5cSAndroid Build Coastguard Worker 
32*dfc6aa5cSAndroid Build Coastguard Worker typedef struct {
33*dfc6aa5cSAndroid Build Coastguard Worker   JOCTET *next_output_byte;     /* => next byte to write in buffer */
34*dfc6aa5cSAndroid Build Coastguard Worker   size_t free_in_buffer;        /* # of byte spaces remaining in buffer */
35*dfc6aa5cSAndroid Build Coastguard Worker   savable_state cur;            /* Current bit buffer & DC state */
36*dfc6aa5cSAndroid Build Coastguard Worker   j_compress_ptr cinfo;         /* dump_buffer needs access to this */
37*dfc6aa5cSAndroid Build Coastguard Worker   int simd;
38*dfc6aa5cSAndroid Build Coastguard Worker } working_state;
39*dfc6aa5cSAndroid Build Coastguard Worker 
40*dfc6aa5cSAndroid Build Coastguard Worker /* Outputting bits to the file */
41*dfc6aa5cSAndroid Build Coastguard Worker 
42*dfc6aa5cSAndroid Build Coastguard Worker /* Output byte b and, speculatively, an additional 0 byte. 0xFF must be encoded
43*dfc6aa5cSAndroid Build Coastguard Worker  * as 0xFF 0x00, so the output buffer pointer is advanced by 2 if the byte is
44*dfc6aa5cSAndroid Build Coastguard Worker  * 0xFF.  Otherwise, the output buffer pointer is advanced by 1, and the
45*dfc6aa5cSAndroid Build Coastguard Worker  * speculative 0 byte will be overwritten by the next byte.
46*dfc6aa5cSAndroid Build Coastguard Worker  */
47*dfc6aa5cSAndroid Build Coastguard Worker #define EMIT_BYTE(b) { \
48*dfc6aa5cSAndroid Build Coastguard Worker   buffer[0] = (JOCTET)(b); \
49*dfc6aa5cSAndroid Build Coastguard Worker   buffer[1] = 0; \
50*dfc6aa5cSAndroid Build Coastguard Worker   buffer -= -2 + ((JOCTET)(b) < 0xFF); \
51*dfc6aa5cSAndroid Build Coastguard Worker }
52*dfc6aa5cSAndroid Build Coastguard Worker 
53*dfc6aa5cSAndroid Build Coastguard Worker /* Output the entire bit buffer.  If there are no 0xFF bytes in it, then write
54*dfc6aa5cSAndroid Build Coastguard Worker  * directly to the output buffer.  Otherwise, use the EMIT_BYTE() macro to
55*dfc6aa5cSAndroid Build Coastguard Worker  * encode 0xFF as 0xFF 0x00.
56*dfc6aa5cSAndroid Build Coastguard Worker  */
57*dfc6aa5cSAndroid Build Coastguard Worker #if defined(__aarch64__) || defined(_M_ARM64)
58*dfc6aa5cSAndroid Build Coastguard Worker 
59*dfc6aa5cSAndroid Build Coastguard Worker #define FLUSH() { \
60*dfc6aa5cSAndroid Build Coastguard Worker   if (put_buffer & 0x8080808080808080 & ~(put_buffer + 0x0101010101010101)) { \
61*dfc6aa5cSAndroid Build Coastguard Worker     EMIT_BYTE(put_buffer >> 56) \
62*dfc6aa5cSAndroid Build Coastguard Worker     EMIT_BYTE(put_buffer >> 48) \
63*dfc6aa5cSAndroid Build Coastguard Worker     EMIT_BYTE(put_buffer >> 40) \
64*dfc6aa5cSAndroid Build Coastguard Worker     EMIT_BYTE(put_buffer >> 32) \
65*dfc6aa5cSAndroid Build Coastguard Worker     EMIT_BYTE(put_buffer >> 24) \
66*dfc6aa5cSAndroid Build Coastguard Worker     EMIT_BYTE(put_buffer >> 16) \
67*dfc6aa5cSAndroid Build Coastguard Worker     EMIT_BYTE(put_buffer >>  8) \
68*dfc6aa5cSAndroid Build Coastguard Worker     EMIT_BYTE(put_buffer      ) \
69*dfc6aa5cSAndroid Build Coastguard Worker   } else { \
70*dfc6aa5cSAndroid Build Coastguard Worker     *((uint64_t *)buffer) = BUILTIN_BSWAP64(put_buffer); \
71*dfc6aa5cSAndroid Build Coastguard Worker     buffer += 8; \
72*dfc6aa5cSAndroid Build Coastguard Worker   } \
73*dfc6aa5cSAndroid Build Coastguard Worker }
74*dfc6aa5cSAndroid Build Coastguard Worker 
75*dfc6aa5cSAndroid Build Coastguard Worker #else
76*dfc6aa5cSAndroid Build Coastguard Worker 
77*dfc6aa5cSAndroid Build Coastguard Worker #if defined(_MSC_VER) && !defined(__clang__)
78*dfc6aa5cSAndroid Build Coastguard Worker #define SPLAT() { \
79*dfc6aa5cSAndroid Build Coastguard Worker   buffer[0] = (JOCTET)(put_buffer >> 24); \
80*dfc6aa5cSAndroid Build Coastguard Worker   buffer[1] = (JOCTET)(put_buffer >> 16); \
81*dfc6aa5cSAndroid Build Coastguard Worker   buffer[2] = (JOCTET)(put_buffer >>  8); \
82*dfc6aa5cSAndroid Build Coastguard Worker   buffer[3] = (JOCTET)(put_buffer      ); \
83*dfc6aa5cSAndroid Build Coastguard Worker   buffer += 4; \
84*dfc6aa5cSAndroid Build Coastguard Worker }
85*dfc6aa5cSAndroid Build Coastguard Worker #else
86*dfc6aa5cSAndroid Build Coastguard Worker #define SPLAT() { \
87*dfc6aa5cSAndroid Build Coastguard Worker   put_buffer = __builtin_bswap32(put_buffer); \
88*dfc6aa5cSAndroid Build Coastguard Worker   __asm__("str %1, [%0], #4" : "+r" (buffer) : "r" (put_buffer)); \
89*dfc6aa5cSAndroid Build Coastguard Worker }
90*dfc6aa5cSAndroid Build Coastguard Worker #endif
91*dfc6aa5cSAndroid Build Coastguard Worker 
92*dfc6aa5cSAndroid Build Coastguard Worker #define FLUSH() { \
93*dfc6aa5cSAndroid Build Coastguard Worker   if (put_buffer & 0x80808080 & ~(put_buffer + 0x01010101)) { \
94*dfc6aa5cSAndroid Build Coastguard Worker     EMIT_BYTE(put_buffer >> 24) \
95*dfc6aa5cSAndroid Build Coastguard Worker     EMIT_BYTE(put_buffer >> 16) \
96*dfc6aa5cSAndroid Build Coastguard Worker     EMIT_BYTE(put_buffer >>  8) \
97*dfc6aa5cSAndroid Build Coastguard Worker     EMIT_BYTE(put_buffer      ) \
98*dfc6aa5cSAndroid Build Coastguard Worker   } else { \
99*dfc6aa5cSAndroid Build Coastguard Worker     SPLAT(); \
100*dfc6aa5cSAndroid Build Coastguard Worker   } \
101*dfc6aa5cSAndroid Build Coastguard Worker }
102*dfc6aa5cSAndroid Build Coastguard Worker 
103*dfc6aa5cSAndroid Build Coastguard Worker #endif
104*dfc6aa5cSAndroid Build Coastguard Worker 
105*dfc6aa5cSAndroid Build Coastguard Worker /* Fill the bit buffer to capacity with the leading bits from code, then output
106*dfc6aa5cSAndroid Build Coastguard Worker  * the bit buffer and put the remaining bits from code into the bit buffer.
107*dfc6aa5cSAndroid Build Coastguard Worker  */
108*dfc6aa5cSAndroid Build Coastguard Worker #define PUT_AND_FLUSH(code, size) { \
109*dfc6aa5cSAndroid Build Coastguard Worker   put_buffer = (put_buffer << (size + free_bits)) | (code >> -free_bits); \
110*dfc6aa5cSAndroid Build Coastguard Worker   FLUSH() \
111*dfc6aa5cSAndroid Build Coastguard Worker   free_bits += BIT_BUF_SIZE; \
112*dfc6aa5cSAndroid Build Coastguard Worker   put_buffer = code; \
113*dfc6aa5cSAndroid Build Coastguard Worker }
114*dfc6aa5cSAndroid Build Coastguard Worker 
115*dfc6aa5cSAndroid Build Coastguard Worker /* Insert code into the bit buffer and output the bit buffer if needed.
116*dfc6aa5cSAndroid Build Coastguard Worker  * NOTE: We can't flush with free_bits == 0, since the left shift in
117*dfc6aa5cSAndroid Build Coastguard Worker  * PUT_AND_FLUSH() would have undefined behavior.
118*dfc6aa5cSAndroid Build Coastguard Worker  */
119*dfc6aa5cSAndroid Build Coastguard Worker #define PUT_BITS(code, size) { \
120*dfc6aa5cSAndroid Build Coastguard Worker   free_bits -= size; \
121*dfc6aa5cSAndroid Build Coastguard Worker   if (free_bits < 0) \
122*dfc6aa5cSAndroid Build Coastguard Worker     PUT_AND_FLUSH(code, size) \
123*dfc6aa5cSAndroid Build Coastguard Worker   else \
124*dfc6aa5cSAndroid Build Coastguard Worker     put_buffer = (put_buffer << size) | code; \
125*dfc6aa5cSAndroid Build Coastguard Worker }
126*dfc6aa5cSAndroid Build Coastguard Worker 
127*dfc6aa5cSAndroid Build Coastguard Worker #define PUT_CODE(code, size, diff) { \
128*dfc6aa5cSAndroid Build Coastguard Worker   diff |= code << nbits; \
129*dfc6aa5cSAndroid Build Coastguard Worker   nbits += size; \
130*dfc6aa5cSAndroid Build Coastguard Worker   PUT_BITS(diff, nbits) \
131*dfc6aa5cSAndroid Build Coastguard Worker }
132