lib: os: cbprintf: Improvements for sparc
Unified define used for handling sparc case in static and runtime packaging. Reworked macro for storing argument in static packaging. Signed-off-by: Krzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
parent
c26e08a51f
commit
65474d8d67
2 changed files with 55 additions and 45 deletions
|
@ -49,6 +49,22 @@ extern "C" {
|
||||||
#define VA_STACK_ALIGN(type) MAX(VA_STACK_MIN_ALIGN, __alignof__(type))
|
#define VA_STACK_ALIGN(type) MAX(VA_STACK_MIN_ALIGN, __alignof__(type))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(__sparc__)
|
||||||
|
/* The SPARC V8 ABI guarantees that the arguments of a variable argument
|
||||||
|
* list function are stored on the stack at addresses which are 32-bit
|
||||||
|
* aligned. It means that variables of type unit64_t and double may not
|
||||||
|
* be properly aligned on the stack.
|
||||||
|
*
|
||||||
|
* The compiler is aware of the ABI and takes care of this. However,
|
||||||
|
* as we are directly accessing the variable argument list here, we need
|
||||||
|
* to take the alignment into consideration and copy 64-bit arguments
|
||||||
|
* as 32-bit words.
|
||||||
|
*/
|
||||||
|
#define Z_CBPRINTF_VA_STACK_LL_DBL_MEMCPY 1
|
||||||
|
#else
|
||||||
|
#define Z_CBPRINTF_VA_STACK_LL_DBL_MEMCPY 0
|
||||||
|
#endif
|
||||||
|
|
||||||
/** @brief Return 1 if argument is a pointer to char or wchar_t
|
/** @brief Return 1 if argument is a pointer to char or wchar_t
|
||||||
*
|
*
|
||||||
* @param x argument.
|
* @param x argument.
|
||||||
|
@ -114,33 +130,33 @@ extern "C" {
|
||||||
sizeof((v)+0) \
|
sizeof((v)+0) \
|
||||||
)
|
)
|
||||||
|
|
||||||
|
static inline void cbprintf_wcpy(int *dst, int *src, size_t len)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
dst[i] = src[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** @brief Promote and store argument in the buffer.
|
/** @brief Promote and store argument in the buffer.
|
||||||
*
|
*
|
||||||
* @param buf Buffer.
|
* @param buf Buffer.
|
||||||
*
|
*
|
||||||
* @param arg Argument.
|
* @param arg Argument.
|
||||||
*/
|
*/
|
||||||
#ifdef __sparc__
|
#define Z_CBPRINTF_STORE_ARG(buf, arg) do { \
|
||||||
static inline void cbprintf_wcpy(int *dst, int *src, uint32_t len)
|
if (Z_CBPRINTF_VA_STACK_LL_DBL_MEMCPY) { \
|
||||||
{
|
/* If required, copy arguments by word to avoid unaligned access.*/ \
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
dst[i] = src[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Sparc is expecting va_list to be packed but don't support unaligned access.*/
|
|
||||||
#define Z_CBPRINTF_STORE_ARG(buf, arg) do {\
|
|
||||||
__auto_type _v = (arg) + 0; \
|
__auto_type _v = (arg) + 0; \
|
||||||
double _d = _Generic((arg) + 0, \
|
double _d = _Generic((arg) + 0, \
|
||||||
float : (arg) + 0, \
|
float : (arg) + 0, \
|
||||||
default : \
|
default : \
|
||||||
0.0); \
|
0.0); \
|
||||||
uint32_t _wsize = Z_CBPRINTF_ARG_SIZE(arg) / sizeof(int); \
|
size_t arg_size = Z_CBPRINTF_ARG_SIZE(arg); \
|
||||||
|
size_t _wsize = arg_size / sizeof(int); \
|
||||||
cbprintf_wcpy((int *)buf, \
|
cbprintf_wcpy((int *)buf, \
|
||||||
(int *) _Generic((arg) + 0, float : &_d, default : &_v), \
|
(int *) _Generic((arg) + 0, float : &_d, default : &_v), \
|
||||||
_wsize); \
|
_wsize); \
|
||||||
} while (0)
|
} else { \
|
||||||
#else /* __sparc__ */
|
|
||||||
#define Z_CBPRINTF_STORE_ARG(buf, arg) \
|
|
||||||
*_Generic((arg) + 0, \
|
*_Generic((arg) + 0, \
|
||||||
char : (int *)buf, \
|
char : (int *)buf, \
|
||||||
unsigned char: (int *)buf, \
|
unsigned char: (int *)buf, \
|
||||||
|
@ -156,8 +172,9 @@ static inline void cbprintf_wcpy(int *dst, int *src, uint32_t len)
|
||||||
double : (double *)buf, \
|
double : (double *)buf, \
|
||||||
long double : (long double *)buf, \
|
long double : (long double *)buf, \
|
||||||
default : \
|
default : \
|
||||||
(const void **)buf) = arg
|
(const void **)buf) = arg; \
|
||||||
#endif
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
/** @brief Return alignment needed for given argument.
|
/** @brief Return alignment needed for given argument.
|
||||||
*
|
*
|
||||||
|
|
|
@ -189,13 +189,6 @@ static int cbprintf_via_va_list(cbprintf_cb out, void *ctx,
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__sparc__)
|
|
||||||
/* CPU can't do unaligned accesses even though no gaps on the stack.*/
|
|
||||||
#define VA_STACK_LL_DBL_MEMCPY true
|
|
||||||
#else
|
|
||||||
#define VA_STACK_LL_DBL_MEMCPY false
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int cbvprintf_package(void *packaged, size_t len,
|
int cbvprintf_package(void *packaged, size_t len,
|
||||||
const char *fmt, va_list ap)
|
const char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
|
@ -373,7 +366,7 @@ int cbvprintf_package(void *packaged, size_t len,
|
||||||
if (buf - buf0 + size > len) {
|
if (buf - buf0 + size > len) {
|
||||||
return -ENOSPC;
|
return -ENOSPC;
|
||||||
}
|
}
|
||||||
if (VA_STACK_LL_DBL_MEMCPY) {
|
if (Z_CBPRINTF_VA_STACK_LL_DBL_MEMCPY) {
|
||||||
memcpy(buf, &v, size);
|
memcpy(buf, &v, size);
|
||||||
} else if (fmt[-1] == 'L') {
|
} else if (fmt[-1] == 'L') {
|
||||||
*(long double *)buf = v.ld;
|
*(long double *)buf = v.ld;
|
||||||
|
@ -445,7 +438,7 @@ process_string:
|
||||||
long long v = va_arg(ap, long long);
|
long long v = va_arg(ap, long long);
|
||||||
|
|
||||||
if (buf0) {
|
if (buf0) {
|
||||||
if (VA_STACK_LL_DBL_MEMCPY) {
|
if (Z_CBPRINTF_VA_STACK_LL_DBL_MEMCPY) {
|
||||||
memcpy(buf, &v, sizeof(long long));
|
memcpy(buf, &v, sizeof(long long));
|
||||||
} else {
|
} else {
|
||||||
*(long long *)buf = v;
|
*(long long *)buf = v;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue