From 6719bdf3edef357c1a81e8ed48728b68e0ec0431 Mon Sep 17 00:00:00 2001 From: Allen Webb Date: Thu, 22 Feb 2018 11:13:03 -0800 Subject: Cr50: Add LLSR (long long shift right) support. Cr50 lacks native instructions for 64-bit integers and an ABI function can be used by the compiler to take the place of the needed instructions. This CL adds support for a right bitwise shift of 64-bit integers. BRANCH=none BUG=chromium:794010 TEST=Set CONFIG_LLSR_TEST, build, update cr50, and run llsrtest on the console. Change-Id: Iae66c86720c531454ba29f15b3cc6a07959f5ef2 Signed-off-by: Allen Webb Reviewed-on: https://chromium-review.googlesource.com/931932 Reviewed-by: Vadim Bendebury --- core/cortex-m/build.mk | 2 +- core/cortex-m/llsr.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 core/cortex-m/llsr.c (limited to 'core') diff --git a/core/cortex-m/build.mk b/core/cortex-m/build.mk index cc323a2dca..5d035a43cd 100644 --- a/core/cortex-m/build.mk +++ b/core/cortex-m/build.mk @@ -22,7 +22,7 @@ CFLAGS_CPU+=-flto LDFLAGS_EXTRA+=-flto endif -core-y=cpu.o init.o ldivmod.o uldivmod.o +core-y=cpu.o init.o ldivmod.o llsr.o uldivmod.o core-$(CONFIG_COMMON_PANIC_OUTPUT)+=panic.o core-$(CONFIG_COMMON_RUNTIME)+=switch.o task.o core-$(CONFIG_WATCHDOG)+=watchdog.o diff --git a/core/cortex-m/llsr.c b/core/cortex-m/llsr.c new file mode 100644 index 0000000000..5a43dc1f08 --- /dev/null +++ b/core/cortex-m/llsr.c @@ -0,0 +1,65 @@ +/* Copyright 2018 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Enable the use of right shift for uint64_t. */ + +#include +#include +#include + +union words { + uint64_t u64; + uint32_t w[2]; +}; + +uint64_t __aeabi_llsr(uint64_t v, uint32_t shift) +{ + union words val; + union words res; + + val.u64 = v; + res.w[1] = val.w[1] >> shift; + res.w[0] = val.w[0] >> shift; + res.w[0] |= val.w[1] >> (shift - 32); /* Handle shift >= 32*/ + res.w[0] |= val.w[1] << (32 - shift); /* Handle shift <= 32*/ + return res.u64; +} + +#ifdef CONFIG_LLSR_TEST + +static int command_llsr(int argc, char **argv) +{ + /* Volatile to prevent compilier optimization from interfering. */ + volatile uint64_t start = 0x123456789ABCDEF0ull; + uint32_t x; + + const struct { + uint32_t shift_by; + uint64_t result; + } cases[] = { + {0, start}, + {16, 0x123456789ABCull}, + {32, 0x12345678u}, + {48, 0x1234u}, + {64, 0u} + }; + + for (x = 0; x < ARRAY_SIZE(cases); ++x) { + if ((start >> cases[x].shift_by) != cases[x].result) { + ccprintf("FAILED %d\n", cases[x].shift_by); + return EC_ERROR_UNKNOWN; + } + } + + ccprintf("SUCCESS\n"); + return EC_SUCCESS; +} + +DECLARE_CONSOLE_COMMAND( + llsrtest, command_llsr, + "", + "Run tests against the LLSR ABI. Prints SUCCESS or FAILURE."); + +#endif /* CONFIG_LLSR_TEST */ -- cgit v1.2.1