diff --git a/lib/common/cmp_data_types.c b/lib/common/cmp_data_types.c index 42d0831e482c52815daef331c2541ff6f1a194c6..d6283ce2017639cfe97cad88485a4ca1bd27e1d9 100644 --- a/lib/common/cmp_data_types.c +++ b/lib/common/cmp_data_types.c @@ -645,8 +645,12 @@ static void be_to_cpus_16(uint16_t *a, uint32_t samples) { uint32_t i; - for (i = 0; i < samples; ++i) - be16_to_cpus(&a[i]); + for (i = 0; i < samples; ++i) { + uint16_t tmp; + + tmp = be16_to_cpu(get_unaligned(&a[i])); + put_unaligned(tmp, &a[i]); + } } diff --git a/lib/common/compiler.h b/lib/common/compiler.h index 9f4d8b614a3837174c9d564fc196d73784209eea..fea1ca51e460e8ade92c3c0ec5c1df4234e144d2 100644 --- a/lib/common/compiler.h +++ b/lib/common/compiler.h @@ -47,11 +47,71 @@ #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) -/* optimisation barrier */ -#define barrier() __asm__ __volatile__("": : :"memory") +#define bitsizeof(x) (CHAR_BIT * sizeof(x)) -#define cpu_relax() barrier() +#define maximum_signed_value_of_type(a) \ + (INTMAX_MAX >> (bitsizeof(intmax_t) - bitsizeof(a))) + +#define maximum_unsigned_value_of_type(a) \ + (UINTMAX_MAX >> (bitsizeof(uintmax_t) - bitsizeof(a))) + +/* + * Signed integer overflow is undefined in C, so here's a helper macro + * to detect if the sum of two integers will overflow. + * + * Requires: a >= 0, typeof(a) equals typeof(b) + */ +#define signed_add_overflows(a, b) \ + ((b) > maximum_signed_value_of_type(a) - (a)) + +#define unsigned_add_overflows(a, b) \ + ((b) > maximum_unsigned_value_of_type(a) - (a)) + + +#define __get_unaligned_t(type, ptr) ({ \ + const struct { type x; } __attribute__((packed)) *__pptr = (__typeof__(__pptr))(ptr); \ + __pptr->x; \ +}) + +#define __put_unaligned_t(type, val, ptr) do { \ + struct { type x; } __attribute__((packed)) *__pptr = (__typeof__(__pptr))(ptr); \ + __pptr->x = (val); \ +} while (0) + + +/** + * @brief read from an unaligned address + * + * @param ptr pointer to the address to read from (can be unaligned) + * + * @return the value read from the (unaligned) address in system endianness + * @note the size of the value is determined by the pointer type + */ + +#define get_unaligned(ptr) __get_unaligned_t(__typeof__(*(ptr)), (ptr)) + + +/** + * @brief write to an unaligned address + * + * @param val the value to write + * @param ptr pointer to the address to write to (can be unaligned) + * + * @note the size of the value is determined by the pointer type + */ + +#define put_unaligned(val, ptr) __put_unaligned_t(__typeof__(*(ptr)), (val), (ptr)) + + +/** + * @brief mark a variable as unused to suppress compiler warnings. + * + * This macro is used to indicate that a variable is intentionally left unused + * in the code. It helps suppress compiler warnings about unused variables. + * + * @param x The variable to mark as unused. + */ #define UNUSED(x) (void)(x) -#endif +#endif /* COMPILER_H */ diff --git a/lib/icu_compress/cmp_icu.c b/lib/icu_compress/cmp_icu.c index 05a47e77dabed3bdbe91c4e5f4186822f0e2b69b..5ce498c1b9b86caca32c969bbe3733d8d3efb1d6 100644 --- a/lib/icu_compress/cmp_icu.c +++ b/lib/icu_compress/cmp_icu.c @@ -867,7 +867,7 @@ static int compress_imagette(const struct cmp_cfg *cfg, int stream_len) uint16_t *up_model_buf = NULL; if (model_mode_is_used(cfg->cmp_mode)) { - model = model_buf[0]; + model = get_unaligned(&model_buf[0]); next_model_p = &model_buf[1]; up_model_buf = cfg->icu_new_model_buf; } @@ -892,17 +892,18 @@ static int compress_imagette(const struct cmp_cfg *cfg, int stream_len) max_data_bits, cfg); for (i = 0;; i++) { - stream_len = encode_value(data_buf[i], model, stream_len, &setup); + stream_len = encode_value(get_unaligned(&data_buf[i]), + model, stream_len, &setup); if (stream_len <= 0) break; if (up_model_buf) - up_model_buf[i] = cmp_up_model(data_buf[i], model, cfg->model_value, - setup.lossy_par); + up_model_buf[i] = cmp_up_model(get_unaligned(&data_buf[i]), + model, cfg->model_value, setup.lossy_par); if (i >= cfg->samples-1) break; - model = next_model_p[i]; + model = get_unaligned(&next_model_p[i]); } return stream_len; } @@ -2356,7 +2357,6 @@ static int32_t cmp_collection(uint8_t *col, uint8_t *model, uint8_t *updated_mod uint8_t subservice = cmp_col_get_subservice(col_hdr); uint16_t col_data_length = cmp_col_get_data_length(col_hdr); - cfg->data_type = convert_subservice_to_cmp_data_type(subservice); if (!size_of_a_sample(cfg->data_type))