|  | // Copyright lowRISC contributors. | 
|  | // Licensed under the Apache License, Version 2.0, see LICENSE for details. | 
|  | // SPDX-License-Identifier: Apache-2.0 | 
|  |  | 
|  | #include "sw/device/lib/base/math.h" | 
|  |  | 
|  | #include <stddef.h> | 
|  |  | 
|  | uint64_t udiv64_slow(uint64_t a, uint64_t b, uint64_t *rem_out) { | 
|  | uint64_t quot = 0, rem = 0; | 
|  |  | 
|  | // Schoolbook long division in base 2. See | 
|  | // https://en.wikipedia.org/wiki/Long_division to recall precisely how this | 
|  | // works. This algorithm is a bit different from the elementary school base-10 | 
|  | // version, since we can use shifts instead of multiplication. | 
|  | // | 
|  | // If `b` is zero, `quot == -1` and `rem == a`. This should not be relied | 
|  | // upon. | 
|  | size_t bits = sizeof(uint64_t) * 8; | 
|  | for (size_t i = 0; i < bits; ++i) { | 
|  | rem <<= 1; | 
|  | quot <<= 1; | 
|  | rem |= (a >> (bits - i - 1)) & 1; | 
|  |  | 
|  | // We need to keep bringing down zeros until `rem`, the running total, is | 
|  | // large enough that we can subtract off `b`; this tells us the value we | 
|  | // would have had to multiply `a` by to produce this current step in the | 
|  | // division. | 
|  | if (rem >= b) { | 
|  | rem -= b; | 
|  | quot |= 1; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (rem_out != NULL) { | 
|  | *rem_out = rem; | 
|  | } | 
|  | return quot; | 
|  | } |