1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-06-06 05:21:22 +03:00

Fix pgm_read_float_unaligned macro (#6593)

Fixes #6590

The ASM block that implements the read-uint32-unaligned returns a
uint32_t.  The old code was doing a cast like `(float)(uint32_t ret)
which actually goes and creates a new float of the positive uint value
(approx, of course due to exponent and sign bits) which is not correct.

C and C++ don't have a concise way to convert the bits in a register
from int to float interpretation, so avoid the whole issue by making a
new function which uses the same ASM block as the read-uint32-unaligned,
just make the destination and return values as floats.
This commit is contained in:
Earle F. Philhower, III 2019-10-03 08:21:07 -07:00 committed by GitHub
parent 899893294c
commit fb2cbe36a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -80,6 +80,14 @@ static inline uint16_t pgm_read_word_inlined(const void* addr) {
return (uint16_t) res; /* This masks the lower half-word from the returned word */
}
/* Can't legally cast bits of uint32_t to a float w/o conversion or std::memcpy, which is inefficient. */
/* The ASM block doesn't care the type, so just pass in what C thinks is a float and return in custom fcn. */
static inline float pgm_read_float_unaligned(const void *addr) {
register float res;
pgm_read_with_offset(addr, res);
return res;
}
#define pgm_read_byte(addr) pgm_read_byte_inlined(addr)
#define pgm_read_word_aligned(addr) pgm_read_word_inlined(addr)
#ifdef __cplusplus
@ -98,7 +106,6 @@ static inline uint32_t pgm_read_dword_unaligned(const void *addr) {
return res;
}
#define pgm_read_float_unaligned(addr) ((float)pgm_read_dword_unaligned(addr))
#define pgm_read_ptr_unaligned(addr) ((void*)pgm_read_dword_unaligned(addr))
#define pgm_read_word_unaligned(addr) ((uint16_t)(pgm_read_dword_unaligned(addr) & 0xffff))