mirror of https://github.com/rusefi/rusefi-1.git
Some bit, unaligned and different endian access helpers (#1436)
* util: add some common macros * util: add unaligned access helpers
This commit is contained in:
parent
7500e44c8c
commit
e7991eacf8
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* @file common.h
|
||||
* @brief Common macros definitions
|
||||
*
|
||||
* @date May, 2019
|
||||
* @author Andrey Gusakov, (c) 2019
|
||||
*
|
||||
* This file is part of rusEfi - see http://rusefi.com
|
||||
*
|
||||
* rusEfi is free software; you can redistribute it and/or modify it under the terms of
|
||||
* the GNU General Public License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* rusEfi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||||
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef COMMON_H_INCLUDED
|
||||
#define COMMON_H_INCLUDED
|
||||
|
||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||
#define MAX(a,b) (((a)>(b))?(a):(b))
|
||||
|
||||
#define CLAMP(x, low, high) ({\
|
||||
__typeof__(x) __x = (x); \
|
||||
__typeof__(low) __low = (low);\
|
||||
__typeof__(high) __high = (high);\
|
||||
(__x > __high) ? __high : ((__x < __low) ? __low : __x);\
|
||||
})
|
||||
|
||||
#endif /* COMMON_H_INCLUDED */
|
|
@ -0,0 +1,113 @@
|
|||
/**
|
||||
* @file unaligned.c
|
||||
* @brief unaligned data access helpers
|
||||
*
|
||||
* @date May, 2019
|
||||
* @author Andrey Gusakov, (c) 2019
|
||||
*
|
||||
* This file is part of rusEfi - see http://rusefi.com
|
||||
*
|
||||
* rusEfi is free software; you can redistribute it and/or modify it under the terms of
|
||||
* the GNU General Public License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* rusEfi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||||
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "unaligned.h"
|
||||
#include "common.h"
|
||||
|
||||
/* generate mask */
|
||||
static inline uint32_t bit_mask(unsigned int from, unsigned int to)
|
||||
{
|
||||
uint32_t mask = 0;
|
||||
uint32_t shift;
|
||||
|
||||
if (to < from)
|
||||
return 0;
|
||||
|
||||
shift = to - from + 1U;
|
||||
|
||||
if ((shift > 0U) && (shift <= 32U) && (from <= 31U)) {
|
||||
if (shift < 32U) {
|
||||
mask = (uint32_t)((1UL << shift) - 1UL);
|
||||
mask = mask << from;
|
||||
} else {
|
||||
mask = 0xFFFFFFFFUL;
|
||||
}
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
/* get upto 32 bits from char array p, from bit position pos, lenght len */
|
||||
uint32_t bits_get(uint8_t *p, unsigned int pos, int len)
|
||||
{
|
||||
int i;
|
||||
unsigned int offset = 0;
|
||||
uint32_t res = 0;
|
||||
|
||||
i = (int)pos / 8;
|
||||
|
||||
while (len > 0) {
|
||||
uint32_t tmp;
|
||||
uint32_t mask;
|
||||
int nbits = 8 - ((int)pos % 8);
|
||||
|
||||
/* get */
|
||||
tmp = (uint32_t)p[i];
|
||||
/* shift */
|
||||
tmp = tmp >> (8U - (uint32_t)nbits);
|
||||
/* mask */
|
||||
mask = bit_mask(0, MIN((uint32_t)len - 1U, (uint32_t)nbits - 1U));
|
||||
tmp = tmp & mask;
|
||||
res = res | ((tmp) << offset);
|
||||
|
||||
/* adjust for the next iteration */
|
||||
offset += (unsigned int)nbits;
|
||||
len -= nbits;
|
||||
pos += (unsigned int)nbits;
|
||||
i++;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/* set upto 32 bits in char array p, from bit position pos, lenght len */
|
||||
void bits_set(uint8_t *p, unsigned int pos, int len, uint32_t val)
|
||||
{
|
||||
int i;
|
||||
unsigned int offset = 0;
|
||||
|
||||
i = (int)pos / 8;
|
||||
|
||||
while (len > 0) {
|
||||
uint32_t tmp;
|
||||
uint32_t mask;
|
||||
|
||||
/* get number of bits to shift to get to the target range */
|
||||
int shift = (int)pos % 8;
|
||||
/* get next byte */
|
||||
tmp = (val >> offset) & 0xffU;
|
||||
/* shift temporary value to the start of the target range */
|
||||
tmp = tmp << (uint8_t)shift;
|
||||
/* calculate mask */
|
||||
mask = bit_mask((uint32_t)shift, MIN(8U - 1U, (unsigned int)shift + (unsigned int)len - 1U));
|
||||
/* clean all bits outside of the target range */
|
||||
tmp &= mask;
|
||||
/* pre-clean all target bits */
|
||||
p[i] = p[i] & ~((uint8_t)mask);
|
||||
/* finally set active bits */
|
||||
p[i] |= (uint8_t)tmp;
|
||||
|
||||
/* adjust for the next iteration */
|
||||
offset += ((uint32_t)8U - (uint32_t)shift);
|
||||
len -= (8 - shift);
|
||||
pos += ((unsigned int)8U - (unsigned int)shift);
|
||||
i++;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/**
|
||||
* @file unaligned.h
|
||||
* @brief unaligned data access helpers header file
|
||||
*
|
||||
* @date May, 2019
|
||||
* @author Andrey Gusakov, (c) 2019
|
||||
*
|
||||
* This file is part of rusEfi - see http://rusefi.com
|
||||
*
|
||||
* rusEfi is free software; you can redistribute it and/or modify it under the terms of
|
||||
* the GNU General Public License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* rusEfi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||||
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef UNALIGNED_H_INCLUDED
|
||||
#define UNALIGNED_H_INCLUDED
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* bit operations */
|
||||
uint32_t bits_get(uint8_t *p, unsigned int pos, int len);
|
||||
void bits_set(uint8_t *p, unsigned int pos, int len, uint32_t val);
|
||||
#define bit_set(p, pos) do {(p)[(pos) / 8] |= (1 << ((pos) % 8));} while(0)
|
||||
#define bit_clr(p, pos) do {(p)[(pos) / 8] &= ~(1 << ((pos) % 8));} while(0)
|
||||
#define bit_get(p, pos) (!!((p)[(pos) / 8] & (1 << ((pos) % 8))))
|
||||
|
||||
/* unaligned access */
|
||||
static inline void put_be8(uint8_t *p, uint8_t v)
|
||||
{
|
||||
p[0] = v;
|
||||
}
|
||||
|
||||
static inline void put_le8(uint8_t *p, uint8_t v)
|
||||
{
|
||||
p[0] = v;
|
||||
}
|
||||
|
||||
static inline void put_be16(uint8_t *p, uint16_t v)
|
||||
{
|
||||
p[0] = (uint8_t)(v >> 8);
|
||||
p[1] = (uint8_t)(v >> 0);
|
||||
}
|
||||
|
||||
static inline void put_le16(uint8_t *p, uint16_t v)
|
||||
{
|
||||
p[0] = (uint8_t)(v >> 0);
|
||||
p[1] = (uint8_t)(v >> 8);
|
||||
}
|
||||
|
||||
static inline void put_be32(uint8_t *p, uint32_t v)
|
||||
{
|
||||
p[0] = (uint8_t)(v >> 24);
|
||||
p[1] = (uint8_t)(v >> 16);
|
||||
p[2] = (uint8_t)(v >> 8);
|
||||
p[3] = (uint8_t)(v >> 0);
|
||||
}
|
||||
|
||||
static inline void put_le32(uint8_t *p, uint32_t v)
|
||||
{
|
||||
p[0] = (uint8_t)(v >> 0);
|
||||
p[1] = (uint8_t)(v >> 8);
|
||||
p[2] = (uint8_t)(v >> 16);
|
||||
p[3] = (uint8_t)(v >> 24);
|
||||
}
|
||||
|
||||
static inline uint8_t get_be8(uint8_t *p)
|
||||
{
|
||||
return p[0];
|
||||
}
|
||||
|
||||
static inline uint8_t get_le8(uint8_t *p)
|
||||
{
|
||||
return p[0];
|
||||
}
|
||||
|
||||
static inline uint16_t get_be16(uint8_t *p)
|
||||
{
|
||||
return ((uint16_t)p[0] << 8) | p[1];
|
||||
}
|
||||
|
||||
static inline uint16_t get_le16(uint8_t *p)
|
||||
{
|
||||
return ((uint16_t)p[1] << 8) | p[0];
|
||||
}
|
||||
|
||||
static inline uint32_t get_be32(uint8_t *p)
|
||||
{
|
||||
return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) |
|
||||
((uint32_t)p[2] << 8) | p[3];
|
||||
}
|
||||
|
||||
static inline uint32_t get_le32(uint8_t *p)
|
||||
{
|
||||
return ((uint32_t)p[3] << 24) | ((uint32_t)p[2] << 16) |
|
||||
((uint32_t)p[1] << 8) | p[0];
|
||||
}
|
||||
|
||||
#endif /* UNALIGNED_H_INCLUDED */
|
|
@ -4,7 +4,8 @@ UTILSRC = \
|
|||
$(UTIL_DIR)/containers/data_buffer.c \
|
||||
$(UTIL_DIR)/math/crc.c \
|
||||
$(UTIL_DIR)/os_util.c \
|
||||
$(UTIL_DIR)/histogram.c
|
||||
$(UTIL_DIR)/histogram.c \
|
||||
$(UTIL_DIR)/unaligned.c
|
||||
|
||||
UTILSRC_CPP = \
|
||||
$(UTIL_DIR)/containers/cyclic_buffer.cpp \
|
||||
|
|
Loading…
Reference in New Issue