From 8a088f73db73c0cc529db5d312a368e0ce2a07df Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 15 Sep 2015 12:00:06 +1000 Subject: [PATCH] unaligned_load: Fix sign extension, add test case for sign extension H/T to @foogod again for this. --- core/exception_unaligned_load.S.inc | 2 +- .../unaligned_load/unaligned_load.c | 28 ++++++++++++++++--- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/core/exception_unaligned_load.S.inc b/core/exception_unaligned_load.S.inc index 5963746..553fe84 100644 --- a/core/exception_unaligned_load.S.inc +++ b/core/exception_unaligned_load.S.inc @@ -138,7 +138,7 @@ DoubleExceptionLoadStoreHandler: a3 holds raw value, a4 holds masked */ 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 */ - movi a3, 0xFFFF0000 + movi a3, 0xFFFF8000 or a4, a3, a4 /* set 32-bit sign bits */ j .Lafter_extend_sign diff --git a/examples/experiments/unaligned_load/unaligned_load.c b/examples/experiments/unaligned_load/unaligned_load.c index e70538b..ddf251b 100644 --- a/examples/experiments/unaligned_load/unaligned_load.c +++ b/examples/experiments/unaligned_load/unaligned_load.c @@ -68,7 +68,11 @@ void test_naive_strcpy(const char *string) void test_l16si(const char *string) { /* 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; int32_t *dst_int32 = (int32_t *)buf; 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); } -static void test_doubleexceptions(); +static void test_doubleexception(); +static void test_sign_extension(); void user_init(void) { @@ -134,7 +139,8 @@ void user_init(void) test_string(iromtest, "Cached flash", 0); test_string(iromtest, "'Uncached' flash", 1); - test_doubleexceptions(); + test_doubleexception(); + test_sign_extension(); } static volatile bool frc1_ran; @@ -149,7 +155,7 @@ static void frc1_interrupt_handler(void) frc1_finished = true; } -static void test_doubleexceptions() +static void test_doubleexception() { printf("Testing DoubleException behaviour...\r\n"); timer_set_interrupts(FRC1, false); @@ -169,3 +175,17 @@ static void test_doubleexceptions() else 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]); + } +}