Software APIs
math.c
1// Copyright lowRISC contributors (OpenTitan project).
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4
6
7#include <stddef.h>
8
9/**
10 * Extern declaration of inline function.
11 */
12extern size_t ceil_div(size_t a, size_t b);
13
14uint64_t udiv64_slow(uint64_t a, uint64_t b, uint64_t *rem_out) {
15 uint64_t quot = 0, rem = 0;
16
17 // Schoolbook long division in base 2. See
18 // https://en.wikipedia.org/wiki/Long_division to recall precisely how this
19 // works. This algorithm is a bit different from the elementary school base-10
20 // version, since we can use shifts instead of multiplication.
21 //
22 // If `b` is zero, `quot == -1` and `rem == a`. This should not be relied
23 // upon.
24 size_t bits = sizeof(uint64_t) * 8;
25 for (size_t i = 0; i < bits; ++i) {
26 // For the following operations, we are counting on the compiler
27 // not being too dumb and emitting 32-bit shifts instead of calling
28 // __lshrdi3.
29 rem <<= 1;
30 quot <<= 1;
31 if ((a >> 63) & 1) {
32 rem |= 1;
33 }
34 a <<= 1;
35
36 // We need to keep bringing down zeros until `rem`, the running total, is
37 // large enough that we can subtract off `b`; this tells us the value we
38 // would have had to multiply `a` by to produce this current step in the
39 // division.
40 if (rem >= b) {
41 rem -= b;
42 quot |= 1;
43 }
44 }
45
46 if (rem_out != NULL) {
47 *rem_out = rem;
48 }
49 return quot;
50}