diff --git a/src/dsp/dec.c b/src/dsp/dec.c index 77a00381..a7872064 100644 --- a/src/dsp/dec.c +++ b/src/dsp/dec.c @@ -261,10 +261,10 @@ static void HE4(uint8_t* dst) { // horizontal const int C = dst[-1 + BPS]; const int D = dst[-1 + 2 * BPS]; const int E = dst[-1 + 3 * BPS]; - *(uint32_t*)(dst + 0 * BPS) = 0x01010101U * AVG3(A, B, C); - *(uint32_t*)(dst + 1 * BPS) = 0x01010101U * AVG3(B, C, D); - *(uint32_t*)(dst + 2 * BPS) = 0x01010101U * AVG3(C, D, E); - *(uint32_t*)(dst + 3 * BPS) = 0x01010101U * AVG3(D, E, E); + WebPUint32ToMem(dst + 0 * BPS, 0x01010101U * AVG3(A, B, C)); + WebPUint32ToMem(dst + 1 * BPS, 0x01010101U * AVG3(B, C, D)); + WebPUint32ToMem(dst + 2 * BPS, 0x01010101U * AVG3(C, D, E)); + WebPUint32ToMem(dst + 3 * BPS, 0x01010101U * AVG3(D, E, E)); } static void DC4(uint8_t* dst) { // DC diff --git a/src/dsp/dec_sse2.c b/src/dsp/dec_sse2.c index d4838b92..935bf02e 100644 --- a/src/dsp/dec_sse2.c +++ b/src/dsp/dec_sse2.c @@ -207,10 +207,10 @@ static void Transform(const int16_t* in, uint8_t* dst, int do_two) { dst3 = _mm_loadl_epi64((__m128i*)(dst + 3 * BPS)); } else { // Load four bytes/pixels per line. - dst0 = _mm_cvtsi32_si128(*(int*)(dst + 0 * BPS)); - dst1 = _mm_cvtsi32_si128(*(int*)(dst + 1 * BPS)); - dst2 = _mm_cvtsi32_si128(*(int*)(dst + 2 * BPS)); - dst3 = _mm_cvtsi32_si128(*(int*)(dst + 3 * BPS)); + dst0 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 0 * BPS)); + dst1 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 1 * BPS)); + dst2 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 2 * BPS)); + dst3 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 3 * BPS)); } // Convert to 16b. dst0 = _mm_unpacklo_epi8(dst0, zero); @@ -236,10 +236,10 @@ static void Transform(const int16_t* in, uint8_t* dst, int do_two) { _mm_storel_epi64((__m128i*)(dst + 3 * BPS), dst3); } else { // Store four bytes/pixels per line. - *(int*)(dst + 0 * BPS) = _mm_cvtsi128_si32(dst0); - *(int*)(dst + 1 * BPS) = _mm_cvtsi128_si32(dst1); - *(int*)(dst + 2 * BPS) = _mm_cvtsi128_si32(dst2); - *(int*)(dst + 3 * BPS) = _mm_cvtsi128_si32(dst3); + WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(dst0)); + WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(dst1)); + WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(dst2)); + WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(dst3)); } } } @@ -262,10 +262,10 @@ static void TransformAC3(const int16_t* in, uint8_t* dst) { const __m128i m3 = _mm_subs_epi16(B, d4); const __m128i zero = _mm_setzero_si128(); // Load the source pixels. - __m128i dst0 = _mm_cvtsi32_si128(*(int*)(dst + 0 * BPS)); - __m128i dst1 = _mm_cvtsi32_si128(*(int*)(dst + 1 * BPS)); - __m128i dst2 = _mm_cvtsi32_si128(*(int*)(dst + 2 * BPS)); - __m128i dst3 = _mm_cvtsi32_si128(*(int*)(dst + 3 * BPS)); + __m128i dst0 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 0 * BPS)); + __m128i dst1 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 1 * BPS)); + __m128i dst2 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 2 * BPS)); + __m128i dst3 = _mm_cvtsi32_si128(WebPMemToUint32(dst + 3 * BPS)); // Convert to 16b. dst0 = _mm_unpacklo_epi8(dst0, zero); dst1 = _mm_unpacklo_epi8(dst1, zero); @@ -282,10 +282,10 @@ static void TransformAC3(const int16_t* in, uint8_t* dst) { dst2 = _mm_packus_epi16(dst2, dst2); dst3 = _mm_packus_epi16(dst3, dst3); // Store the results. - *(int*)(dst + 0 * BPS) = _mm_cvtsi128_si32(dst0); - *(int*)(dst + 1 * BPS) = _mm_cvtsi128_si32(dst1); - *(int*)(dst + 2 * BPS) = _mm_cvtsi128_si32(dst2); - *(int*)(dst + 3 * BPS) = _mm_cvtsi128_si32(dst3); + WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(dst0)); + WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(dst1)); + WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(dst2)); + WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(dst3)); } #undef MUL #endif // USE_TRANSFORM_AC3 @@ -517,24 +517,17 @@ static WEBP_INLINE void DoFilter6(__m128i* const p2, __m128i* const p1, } } -// memcpy() is the safe way of moving potentially unaligned 32b memory. -static WEBP_INLINE uint32_t MemToUint32(const uint8_t* const ptr) { - uint32_t A; - memcpy(&A, (const int*)ptr, sizeof(A)); - return A; -} - // reads 8 rows across a vertical edge. static WEBP_INLINE void Load8x4(const uint8_t* const b, int stride, __m128i* const p, __m128i* const q) { // A0 = 63 62 61 60 23 22 21 20 43 42 41 40 03 02 01 00 // A1 = 73 72 71 70 33 32 31 30 53 52 51 50 13 12 11 10 const __m128i A0 = _mm_set_epi32( - MemToUint32(&b[6 * stride]), MemToUint32(&b[2 * stride]), - MemToUint32(&b[4 * stride]), MemToUint32(&b[0 * stride])); + WebPMemToUint32(&b[6 * stride]), WebPMemToUint32(&b[2 * stride]), + WebPMemToUint32(&b[4 * stride]), WebPMemToUint32(&b[0 * stride])); const __m128i A1 = _mm_set_epi32( - MemToUint32(&b[7 * stride]), MemToUint32(&b[3 * stride]), - MemToUint32(&b[5 * stride]), MemToUint32(&b[1 * stride])); + WebPMemToUint32(&b[7 * stride]), WebPMemToUint32(&b[3 * stride]), + WebPMemToUint32(&b[5 * stride]), WebPMemToUint32(&b[1 * stride])); // B0 = 53 43 52 42 51 41 50 40 13 03 12 02 11 01 10 00 // B1 = 73 63 72 62 71 61 70 60 33 23 32 22 31 21 30 20 @@ -592,7 +585,7 @@ static WEBP_INLINE void Load16x4(const uint8_t* const r0, static WEBP_INLINE void Store4x4(__m128i* const x, uint8_t* dst, int stride) { int i; for (i = 0; i < 4; ++i, dst += stride) { - *((int32_t*)dst) = _mm_cvtsi128_si32(*x); + WebPUint32ToMem(dst, _mm_cvtsi128_si32(*x)); *x = _mm_srli_si128(*x, 4); } } @@ -963,7 +956,7 @@ static void VE4(uint8_t* dst) { // vertical const uint32_t vals = _mm_cvtsi128_si32(avg); int i; for (i = 0; i < 4; ++i) { - *(uint32_t*)(dst + i * BPS) = vals; + WebPUint32ToMem(dst + i * BPS, vals); } } @@ -977,10 +970,10 @@ static void LD4(uint8_t* dst) { // Down-Left const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGHH0), one); const __m128i avg2 = _mm_subs_epu8(avg1, lsb); const __m128i abcdefg = _mm_avg_epu8(avg2, BCDEFGH0); - *(uint32_t*)(dst + 0 * BPS) = _mm_cvtsi128_si32( abcdefg ); - *(uint32_t*)(dst + 1 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1)); - *(uint32_t*)(dst + 2 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2)); - *(uint32_t*)(dst + 3 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3)); + WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcdefg )); + WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1))); + WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2))); + WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3))); } static void VR4(uint8_t* dst) { // Vertical-Right @@ -998,10 +991,10 @@ static void VR4(uint8_t* dst) { // Vertical-Right const __m128i lsb = _mm_and_si128(_mm_xor_si128(IXABCD, ABCD0), one); const __m128i avg2 = _mm_subs_epu8(avg1, lsb); const __m128i efgh = _mm_avg_epu8(avg2, XABCD); - *(uint32_t*)(dst + 0 * BPS) = _mm_cvtsi128_si32( abcd ); - *(uint32_t*)(dst + 1 * BPS) = _mm_cvtsi128_si32( efgh ); - *(uint32_t*)(dst + 2 * BPS) = _mm_cvtsi128_si32(_mm_slli_si128(abcd, 1)); - *(uint32_t*)(dst + 3 * BPS) = _mm_cvtsi128_si32(_mm_slli_si128(efgh, 1)); + WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcd )); + WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( efgh )); + WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(abcd, 1))); + WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(efgh, 1))); // these two are hard to implement in SSE2, so we keep the C-version: DST(0, 2) = AVG3(J, I, X); @@ -1023,10 +1016,10 @@ static void VL4(uint8_t* dst) { // Vertical-Left const __m128i lsb2 = _mm_and_si128(abbc, lsb1); const __m128i avg4 = _mm_subs_epu8(avg3, lsb2); const uint32_t extra_out = _mm_cvtsi128_si32(_mm_srli_si128(avg4, 4)); - *(uint32_t*)(dst + 0 * BPS) = _mm_cvtsi128_si32( avg1 ); - *(uint32_t*)(dst + 1 * BPS) = _mm_cvtsi128_si32( avg4 ); - *(uint32_t*)(dst + 2 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(avg1, 1)); - *(uint32_t*)(dst + 3 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(avg4, 1)); + WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( avg1 )); + WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( avg4 )); + WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg1, 1))); + WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg4, 1))); // these two are hard to get and irregular DST(3, 2) = (extra_out >> 0) & 0xff; @@ -1050,10 +1043,10 @@ static void RD4(uint8_t* dst) { // Down-right const __m128i lsb = _mm_and_si128(_mm_xor_si128(JIXABCD__, LKJIXABCD), one); const __m128i avg2 = _mm_subs_epu8(avg1, lsb); const __m128i abcdefg = _mm_avg_epu8(avg2, KJIXABCD_); - *(uint32_t*)(dst + 3 * BPS) = _mm_cvtsi128_si32( abcdefg ); - *(uint32_t*)(dst + 2 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1)); - *(uint32_t*)(dst + 1 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2)); - *(uint32_t*)(dst + 0 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3)); + WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32( abcdefg )); + WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1))); + WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2))); + WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3))); } #undef DST @@ -1067,13 +1060,13 @@ static WEBP_INLINE void TrueMotion(uint8_t* dst, int size) { const __m128i zero = _mm_setzero_si128(); int y; if (size == 4) { - const __m128i top_values = _mm_cvtsi32_si128(MemToUint32(top)); + const __m128i top_values = _mm_cvtsi32_si128(WebPMemToUint32(top)); const __m128i top_base = _mm_unpacklo_epi8(top_values, zero); for (y = 0; y < 4; ++y, dst += BPS) { const int val = dst[-1] - top[-1]; const __m128i base = _mm_set1_epi16(val); const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero); - *(int*)dst = _mm_cvtsi128_si32(out); + WebPUint32ToMem(dst, _mm_cvtsi128_si32(out)); } } else if (size == 8) { const __m128i top_values = _mm_loadl_epi64((const __m128i*)top); diff --git a/src/dsp/dec_sse41.c b/src/dsp/dec_sse41.c index dc1e7042..224c6f89 100644 --- a/src/dsp/dec_sse41.c +++ b/src/dsp/dec_sse41.c @@ -22,7 +22,7 @@ static void HE16(uint8_t* dst) { // horizontal int j; const __m128i kShuffle3 = _mm_set1_epi8(3); for (j = 16; j > 0; --j) { - const __m128i in = _mm_cvtsi32_si128(*(int*)(dst - 4)); + const __m128i in = _mm_cvtsi32_si128(WebPMemToUint32(dst - 4)); const __m128i values = _mm_shuffle_epi8(in, kShuffle3); _mm_storeu_si128((__m128i*)dst, values); dst += BPS; diff --git a/src/dsp/dsp.h b/src/dsp/dsp.h index 8395df40..95f1ce0f 100644 --- a/src/dsp/dsp.h +++ b/src/dsp/dsp.h @@ -14,11 +14,8 @@ #ifndef WEBP_DSP_DSP_H_ #define WEBP_DSP_DSP_H_ -#ifdef HAVE_CONFIG_H -#include "../webp/config.h" -#endif - #include "../webp/types.h" +#include "../utils/utils.h" #ifdef __cplusplus extern "C" { diff --git a/src/dsp/enc.c b/src/dsp/enc.c index 95e63f89..8899d500 100644 --- a/src/dsp/enc.c +++ b/src/dsp/enc.c @@ -357,10 +357,10 @@ static void HE4(uint8_t* dst, const uint8_t* top) { // horizontal const int J = top[-3]; const int K = top[-4]; const int L = top[-5]; - *(uint32_t*)(dst + 0 * BPS) = 0x01010101U * AVG3(X, I, J); - *(uint32_t*)(dst + 1 * BPS) = 0x01010101U * AVG3(I, J, K); - *(uint32_t*)(dst + 2 * BPS) = 0x01010101U * AVG3(J, K, L); - *(uint32_t*)(dst + 3 * BPS) = 0x01010101U * AVG3(K, L, L); + WebPUint32ToMem(dst + 0 * BPS, 0x01010101U * AVG3(X, I, J)); + WebPUint32ToMem(dst + 1 * BPS, 0x01010101U * AVG3(I, J, K)); + WebPUint32ToMem(dst + 2 * BPS, 0x01010101U * AVG3(J, K, L)); + WebPUint32ToMem(dst + 3 * BPS, 0x01010101U * AVG3(K, L, L)); } static void DC4(uint8_t* dst, const uint8_t* top) { diff --git a/src/dsp/enc_sse2.c b/src/dsp/enc_sse2.c index 63d9cecd..96424569 100644 --- a/src/dsp/enc_sse2.c +++ b/src/dsp/enc_sse2.c @@ -19,7 +19,6 @@ #include "../enc/cost.h" #include "../enc/vp8enci.h" -#include "../utils/utils.h" //------------------------------------------------------------------------------ // Quite useful macro for debugging. Left here for convenience. @@ -50,16 +49,6 @@ static void PrintReg(const __m128i r, const char* const name, int size) { } #endif -//------------------------------------------------------------------------------ -// util for unaligned loads. - -// memcpy() is the safe way of moving potentially unaligned 32b memory. -static WEBP_INLINE uint32_t MemToUint32(const uint8_t* const ptr) { - uint32_t A; - memcpy(&A, (const int*)ptr, sizeof(A)); - return A; -} - //------------------------------------------------------------------------------ // Transforms (Paragraph 14.4) @@ -247,10 +236,10 @@ static void ITransform(const uint8_t* ref, const int16_t* in, uint8_t* dst, ref3 = _mm_loadl_epi64((const __m128i*)&ref[3 * BPS]); } else { // Load four bytes/pixels per line. - ref0 = _mm_cvtsi32_si128(MemToUint32(&ref[0 * BPS])); - ref1 = _mm_cvtsi32_si128(MemToUint32(&ref[1 * BPS])); - ref2 = _mm_cvtsi32_si128(MemToUint32(&ref[2 * BPS])); - ref3 = _mm_cvtsi32_si128(MemToUint32(&ref[3 * BPS])); + ref0 = _mm_cvtsi32_si128(WebPMemToUint32(&ref[0 * BPS])); + ref1 = _mm_cvtsi32_si128(WebPMemToUint32(&ref[1 * BPS])); + ref2 = _mm_cvtsi32_si128(WebPMemToUint32(&ref[2 * BPS])); + ref3 = _mm_cvtsi32_si128(WebPMemToUint32(&ref[3 * BPS])); } // Convert to 16b. ref0 = _mm_unpacklo_epi8(ref0, zero); @@ -276,10 +265,10 @@ static void ITransform(const uint8_t* ref, const int16_t* in, uint8_t* dst, _mm_storel_epi64((__m128i*)&dst[3 * BPS], ref3); } else { // Store four bytes/pixels per line. - *((int32_t *)&dst[0 * BPS]) = _mm_cvtsi128_si32(ref0); - *((int32_t *)&dst[1 * BPS]) = _mm_cvtsi128_si32(ref1); - *((int32_t *)&dst[2 * BPS]) = _mm_cvtsi128_si32(ref2); - *((int32_t *)&dst[3 * BPS]) = _mm_cvtsi128_si32(ref3); + WebPUint32ToMem(&dst[0 * BPS], _mm_cvtsi128_si32(ref0)); + WebPUint32ToMem(&dst[1 * BPS], _mm_cvtsi128_si32(ref1)); + WebPUint32ToMem(&dst[2 * BPS], _mm_cvtsi128_si32(ref2)); + WebPUint32ToMem(&dst[3 * BPS], _mm_cvtsi128_si32(ref3)); } } } @@ -821,7 +810,7 @@ static WEBP_INLINE void VE4(uint8_t* dst, const uint8_t* top) { // vertical const uint32_t vals = _mm_cvtsi128_si32(avg); int i; for (i = 0; i < 4; ++i) { - *(uint32_t*)(dst + i * BPS) = vals; + WebPUint32ToMem(dst + i * BPS, vals); } } @@ -831,10 +820,10 @@ static WEBP_INLINE void HE4(uint8_t* dst, const uint8_t* top) { // horizontal const int J = top[-3]; const int K = top[-4]; const int L = top[-5]; - *(uint32_t*)(dst + 0 * BPS) = 0x01010101U * AVG3(X, I, J); - *(uint32_t*)(dst + 1 * BPS) = 0x01010101U * AVG3(I, J, K); - *(uint32_t*)(dst + 2 * BPS) = 0x01010101U * AVG3(J, K, L); - *(uint32_t*)(dst + 3 * BPS) = 0x01010101U * AVG3(K, L, L); + WebPUint32ToMem(dst + 0 * BPS, 0x01010101U * AVG3(X, I, J)); + WebPUint32ToMem(dst + 1 * BPS, 0x01010101U * AVG3(I, J, K)); + WebPUint32ToMem(dst + 2 * BPS, 0x01010101U * AVG3(J, K, L)); + WebPUint32ToMem(dst + 3 * BPS, 0x01010101U * AVG3(K, L, L)); } static WEBP_INLINE void DC4(uint8_t* dst, const uint8_t* top) { @@ -854,10 +843,10 @@ static WEBP_INLINE void LD4(uint8_t* dst, const uint8_t* top) { // Down-Left const __m128i lsb = _mm_and_si128(_mm_xor_si128(ABCDEFGH, CDEFGHH0), one); const __m128i avg2 = _mm_subs_epu8(avg1, lsb); const __m128i abcdefg = _mm_avg_epu8(avg2, BCDEFGH0); - *(uint32_t*)(dst + 0 * BPS) = _mm_cvtsi128_si32( abcdefg ); - *(uint32_t*)(dst + 1 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1)); - *(uint32_t*)(dst + 2 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2)); - *(uint32_t*)(dst + 3 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3)); + WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcdefg )); + WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1))); + WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2))); + WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3))); } static WEBP_INLINE void VR4(uint8_t* dst, @@ -876,10 +865,10 @@ static WEBP_INLINE void VR4(uint8_t* dst, const __m128i lsb = _mm_and_si128(_mm_xor_si128(IXABCD, ABCD0), one); const __m128i avg2 = _mm_subs_epu8(avg1, lsb); const __m128i efgh = _mm_avg_epu8(avg2, XABCD); - *(uint32_t*)(dst + 0 * BPS) = _mm_cvtsi128_si32( abcd ); - *(uint32_t*)(dst + 1 * BPS) = _mm_cvtsi128_si32( efgh ); - *(uint32_t*)(dst + 2 * BPS) = _mm_cvtsi128_si32(_mm_slli_si128(abcd, 1)); - *(uint32_t*)(dst + 3 * BPS) = _mm_cvtsi128_si32(_mm_slli_si128(efgh, 1)); + WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( abcd )); + WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( efgh )); + WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(abcd, 1))); + WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_slli_si128(efgh, 1))); // these two are hard to implement in SSE2, so we keep the C-version: DST(0, 2) = AVG3(J, I, X); @@ -902,10 +891,10 @@ static WEBP_INLINE void VL4(uint8_t* dst, const __m128i lsb2 = _mm_and_si128(abbc, lsb1); const __m128i avg4 = _mm_subs_epu8(avg3, lsb2); const uint32_t extra_out = _mm_cvtsi128_si32(_mm_srli_si128(avg4, 4)); - *(uint32_t*)(dst + 0 * BPS) = _mm_cvtsi128_si32( avg1 ); - *(uint32_t*)(dst + 1 * BPS) = _mm_cvtsi128_si32( avg4 ); - *(uint32_t*)(dst + 2 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(avg1, 1)); - *(uint32_t*)(dst + 3 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(avg4, 1)); + WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32( avg1 )); + WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32( avg4 )); + WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg1, 1))); + WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(avg4, 1))); // these two are hard to get and irregular DST(3, 2) = (extra_out >> 0) & 0xff; @@ -922,10 +911,10 @@ static WEBP_INLINE void RD4(uint8_t* dst, const uint8_t* top) { // Down-right const __m128i lsb = _mm_and_si128(_mm_xor_si128(JIXABCD__, LKJIXABCD), one); const __m128i avg2 = _mm_subs_epu8(avg1, lsb); const __m128i abcdefg = _mm_avg_epu8(avg2, KJIXABCD_); - *(uint32_t*)(dst + 3 * BPS) = _mm_cvtsi128_si32( abcdefg ); - *(uint32_t*)(dst + 2 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1)); - *(uint32_t*)(dst + 1 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2)); - *(uint32_t*)(dst + 0 * BPS) = _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3)); + WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32( abcdefg )); + WebPUint32ToMem(dst + 2 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 1))); + WebPUint32ToMem(dst + 1 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 2))); + WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3))); } static WEBP_INLINE void HU4(uint8_t* dst, const uint8_t* top) { @@ -968,14 +957,14 @@ static WEBP_INLINE void HD4(uint8_t* dst, const uint8_t* top) { static WEBP_INLINE void TM4(uint8_t* dst, const uint8_t* top) { const __m128i zero = _mm_setzero_si128(); - const __m128i top_values = _mm_cvtsi32_si128(MemToUint32(top)); + const __m128i top_values = _mm_cvtsi32_si128(WebPMemToUint32(top)); const __m128i top_base = _mm_unpacklo_epi8(top_values, zero); int y; for (y = 0; y < 4; ++y, dst += BPS) { const int val = top[-2 - y] - top[-1]; const __m128i base = _mm_set1_epi16(val); const __m128i out = _mm_packus_epi16(_mm_add_epi16(base, top_base), zero); - *(int*)dst = _mm_cvtsi128_si32(out); + WebPUint32ToMem(dst, _mm_cvtsi128_si32(out)); } } diff --git a/src/dsp/lossless.c b/src/dsp/lossless.c index 5702eb3b..71ae9d4a 100644 --- a/src/dsp/lossless.c +++ b/src/dsp/lossless.c @@ -490,7 +490,7 @@ static void CopyOrSwap(const uint32_t* src, int num_pixels, uint8_t* dst, #if !defined(WORDS_BIGENDIAN) #if !defined(WEBP_REFERENCE_IMPLEMENTATION) - *(uint32_t*)dst = BSwap32(argb); + WebPUint32ToMem(dst, BSwap32(argb)); #else // WEBP_REFERENCE_IMPLEMENTATION dst[0] = (argb >> 24) & 0xff; dst[1] = (argb >> 16) & 0xff; diff --git a/src/dsp/rescaler_sse2.c b/src/dsp/rescaler_sse2.c index 186edb65..5ea4ddb2 100644 --- a/src/dsp/rescaler_sse2.c +++ b/src/dsp/rescaler_sse2.c @@ -84,7 +84,8 @@ static void RescalerImportRowExpandSSE2(WebPRescaler* const wrk, while (1) { const __m128i mult = _mm_cvtsi32_si128(((x_add - accum) << 16) | accum); const __m128i out = _mm_madd_epi16(cur_pixels, mult); - *(uint32_t*)frow = _mm_cvtsi128_si32(out); + assert(sizeof(*frow) == sizeof(uint32_t)); + WebPUint32ToMem((uint8_t*)frow, _mm_cvtsi128_si32(out)); frow += 1; if (frow >= frow_end) break; accum -= wrk->x_sub; @@ -131,7 +132,7 @@ static void RescalerImportRowShrinkSSE2(WebPRescaler* const wrk, __m128i base = zero; accum += wrk->x_add; while (accum > 0) { - const __m128i A = _mm_cvtsi32_si128(*(int*)src); + const __m128i A = _mm_cvtsi32_si128(WebPMemToUint32(src)); src += 4; base = _mm_unpacklo_epi8(A, zero); // To avoid overflow, we need: base * x_add / x_sub < 32768 diff --git a/src/enc/vp8l.c b/src/enc/vp8l.c index 047c9032..7809af1a 100644 --- a/src/enc/vp8l.c +++ b/src/enc/vp8l.c @@ -33,8 +33,8 @@ // Palette reordering for smaller sum of deltas (and for smaller storage). static int PaletteCompareColorsForQsort(const void* p1, const void* p2) { - const uint32_t a = *(const uint32_t*)p1; - const uint32_t b = *(const uint32_t*)p2; + const uint32_t a = WebPMemToUint32(p1); + const uint32_t b = WebPMemToUint32(p2); assert(a != b); return (a < b) ? -1 : 1; } diff --git a/src/utils/bit_reader.c b/src/utils/bit_reader.c index cd265321..45198e15 100644 --- a/src/utils/bit_reader.c +++ b/src/utils/bit_reader.c @@ -199,7 +199,7 @@ void VP8LDoFillBitWindow(VP8LBitReader* const br) { br->bit_pos_ -= VP8L_WBITS; // The expression below needs a little-endian arch to work correctly. // This gives a large speedup for decoding speed. - br->val_ |= (vp8l_val_t)*(const uint32_t*)(br->buf_ + br->pos_) << + br->val_ |= (vp8l_val_t)WebPMemToUint32(br->buf_ + br->pos_) << (VP8L_LBITS - VP8L_WBITS); br->pos_ += VP8L_LOG8_WBITS; return; diff --git a/src/utils/utils.h b/src/utils/utils.h index fcdb7e13..f506d668 100644 --- a/src/utils/utils.h +++ b/src/utils/utils.h @@ -15,6 +15,10 @@ #ifndef WEBP_UTILS_UTILS_H_ #define WEBP_UTILS_UTILS_H_ +#ifdef HAVE_CONFIG_H +#include "../webp/config.h" +#endif + #include #include "../webp/types.h" @@ -49,6 +53,26 @@ WEBP_EXTERN(void) WebPSafeFree(void* const ptr); #define WEBP_ALIGN_CST 31 #define WEBP_ALIGN(PTR) ((uintptr_t)((PTR) + WEBP_ALIGN_CST) & ~WEBP_ALIGN_CST) +#if defined(WEBP_FORCE_ALIGNED) +#include +// memcpy() is the safe way of moving potentially unaligned 32b memory. +static WEBP_INLINE uint32_t WebPMemToUint32(const uint8_t* const ptr) { + uint32_t A; + memcpy(&A, (const int*)ptr, sizeof(A)); + return A; +} +static WEBP_INLINE void WebPUint32ToMem(uint8_t* const ptr, uint32_t val) { + memcpy(ptr, &val, sizeof(val)); +} +#else +static WEBP_INLINE uint32_t WebPMemToUint32(const uint8_t* const ptr) { + return *(const uint32_t*)ptr; +} +static WEBP_INLINE void WebPUint32ToMem(uint8_t* const ptr, uint32_t val) { + *(uint32_t*)ptr = val; +} +#endif + //------------------------------------------------------------------------------ // Reading/writing data.