unaligned_load: Fix sign extension, add test case for sign extension
H/T to @foogod again for this.
This commit is contained in:
parent
7ebebf6d22
commit
7d779389ab
2 changed files with 25 additions and 5 deletions
|
@ -138,7 +138,7 @@ DoubleExceptionLoadStoreHandler:
|
||||||
a3 holds raw value, a4 holds masked */
|
a3 holds raw value, a4 holds masked */
|
||||||
bbsi a5, 15, .Lafter_extend_sign /* 16-bit unsigned, no sign extension */
|
bbsi a5, 15, .Lafter_extend_sign /* 16-bit unsigned, no sign extension */
|
||||||
bbci a3, 15, .Lafter_extend_sign /* sign bit not set, no sign extension */
|
bbci a3, 15, .Lafter_extend_sign /* sign bit not set, no sign extension */
|
||||||
movi a3, 0xFFFF0000
|
movi a3, 0xFFFF8000
|
||||||
or a4, a3, a4 /* set 32-bit sign bits */
|
or a4, a3, a4 /* set 32-bit sign bits */
|
||||||
j .Lafter_extend_sign
|
j .Lafter_extend_sign
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,11 @@ void test_naive_strcpy(const char *string)
|
||||||
void test_l16si(const char *string)
|
void test_l16si(const char *string)
|
||||||
{
|
{
|
||||||
/* This follows most of the l16si path, but as the
|
/* This follows most of the l16si path, but as the
|
||||||
values in the string are all 7 bit none of them get sign extended */
|
values in the string are all 7 bit none of them get sign extended.
|
||||||
|
|
||||||
|
See separate test_sign_extension function which validates
|
||||||
|
sign extension works as expected.
|
||||||
|
*/
|
||||||
int16_t *src_int16 = (int16_t *)string;
|
int16_t *src_int16 = (int16_t *)string;
|
||||||
int32_t *dst_int32 = (int32_t *)buf;
|
int32_t *dst_int32 = (int32_t *)buf;
|
||||||
dst_int32[0] = src_int16[0];
|
dst_int32[0] = src_int16[0];
|
||||||
|
@ -119,7 +123,8 @@ void test_string(const char *string, char *label, bool evict_cache)
|
||||||
run_test(string, test_l16si, "load as l16si", nullvalue, evict_cache);
|
run_test(string, test_l16si, "load as l16si", nullvalue, evict_cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_doubleexceptions();
|
static void test_doubleexception();
|
||||||
|
static void test_sign_extension();
|
||||||
|
|
||||||
void user_init(void)
|
void user_init(void)
|
||||||
{
|
{
|
||||||
|
@ -134,7 +139,8 @@ void user_init(void)
|
||||||
test_string(iromtest, "Cached flash", 0);
|
test_string(iromtest, "Cached flash", 0);
|
||||||
test_string(iromtest, "'Uncached' flash", 1);
|
test_string(iromtest, "'Uncached' flash", 1);
|
||||||
|
|
||||||
test_doubleexceptions();
|
test_doubleexception();
|
||||||
|
test_sign_extension();
|
||||||
}
|
}
|
||||||
|
|
||||||
static volatile bool frc1_ran;
|
static volatile bool frc1_ran;
|
||||||
|
@ -149,7 +155,7 @@ static void frc1_interrupt_handler(void)
|
||||||
frc1_finished = true;
|
frc1_finished = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_doubleexceptions()
|
static void test_doubleexception()
|
||||||
{
|
{
|
||||||
printf("Testing DoubleException behaviour...\r\n");
|
printf("Testing DoubleException behaviour...\r\n");
|
||||||
timer_set_interrupts(FRC1, false);
|
timer_set_interrupts(FRC1, false);
|
||||||
|
@ -169,3 +175,17 @@ static void test_doubleexceptions()
|
||||||
else
|
else
|
||||||
printf("PASSED\r\n");
|
printf("PASSED\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const volatile __attribute__((section(".iram1.notliterals"))) int16_t unsigned_shorts[] = { -3, -4, -5, -32767, 44 };
|
||||||
|
|
||||||
|
static void test_sign_extension()
|
||||||
|
{
|
||||||
|
/* this step seems to be necessary so the compiler will actually generate l16si */
|
||||||
|
int16_t *shorts_p = (int16_t *)unsigned_shorts;
|
||||||
|
if(shorts_p[0] == -3 && shorts_p[1] == -4 && shorts_p[2] == -5 && shorts_p[3] == -32767 && shorts_p[4] == 44)
|
||||||
|
{
|
||||||
|
printf("l16si sign extension worked as expected.\r\n");
|
||||||
|
} else {
|
||||||
|
printf("l16si sign extension failed. Got values %d %d %d %d %d\r\n", shorts_p[0], shorts_p[1], shorts_p[2], shorts_p[3], shorts_p[4]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue