summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2015-02-23 12:25:32 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-02-25 03:33:01 +0000
commit3227f921e74d0d03424aa16b8ce2c246b7afcb6f (patch)
tree09c5ff162116ca0459566833d87aba47310765de
parent301be83e339f0ec191c1751c650f0f25918afd10 (diff)
downloadchrome-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.S6
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