diff options
author | Randall Spangler <rspangler@chromium.org> | 2015-02-23 12:25:32 -0800 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2015-02-25 03:33:01 +0000 |
commit | 3227f921e74d0d03424aa16b8ce2c246b7afcb6f (patch) | |
tree | 09c5ff162116ca0459566833d87aba47310765de | |
parent | 301be83e339f0ec191c1751c650f0f25918afd10 (diff) | |
download | chrome-ec-3227f921e74d0d03424aa16b8ce2c246b7afcb6f.tar.gz |
cortex-m0: Fix branch from 64-bit signed to unsigned divide
We put each assembly function in its own section. So the sections for
64-bit signed and unsigned divide end up too far apart for b<cond>
(8-bit delta) or b (11-bit delta). Instead, use bl, which has no such
limit. This is a little less efficient in the case where numerator
and denominator are both positive, but equivalent if either or both is
negative, and is far outweighed by the cost of the unsigned divide
itself.
The other alternative would be to put both uldivmod and ldivmod in the
same section. However, we're often tight on code size on cortex-M0
parts, so that's less desirable.
BUG=chrome-os-partner:26126
BRANCH=minnie
TEST=add the following function
static int command_divtest(int argc, char **argv)
{
int64_t a, b, c;
char *e;
if (argc < 2)
return EC_ERROR_PARAM_COUNT;
a = strtoi(argv[1], &e, 0);
b = strtoi(argv[2], &e, 0);
c = a / b;
ccprintf("%d / %d = %d\n", (int)a, (int)b, (int)c);
return EC_SUCCESS;
}
DECLARE_CONSOLE_COMMAND(dt, command_divtest,
"a b",
"Divide test",
NULL);
and test with divides in all 4 quadrants (+/- 20 divided by +/- 5,
for example)
Change-Id: I2a5e49c4534044c2f509e325f8dd6bdf10b544c4
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/252243
Reviewed-by: Alec Berg <alecaberg@chromium.org>
-rw-r--r-- | core/cortex-m0/ldivmod.S | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/core/cortex-m0/ldivmod.S b/core/cortex-m0/ldivmod.S index 48ebdfcc65..853d85b0d2 100644 --- a/core/cortex-m0/ldivmod.S +++ b/core/cortex-m0/ldivmod.S @@ -73,8 +73,12 @@ L_neg_both: L_num_pos: cmp r3, #0 - bge __aeabi_uldivmod + blt L_den_neg + push {r4, lr} + bl __aeabi_uldivmod @ offset too big for b / bge + pop {r4, pc} +L_den_neg: push {r4, lr} movs r4, #0 @ den = -den rsbs r2, r2, #0 |