unaligned_load: Fix sign extension, add test case for sign extension

H/T to @foogod again for this.
This commit is contained in:
Angus Gratton 2015-09-15 12:00:06 +10:00
parent 7ebebf6d22
commit 7d779389ab
2 changed files with 25 additions and 5 deletions

View file

@ -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

View file

@ -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]);
}
}