aboutsummaryrefslogtreecommitdiff
path: root/util/host-utils.c
diff options
context:
space:
mode:
authorLuis Pires <luis.pires@eldorado.org.br>2021-10-25 16:11:36 -0300
committerRichard Henderson <richard.henderson@linaro.org>2021-10-27 17:10:00 -0700
commit9276a31c3484ff236a958a1e2a38beefb0eb7ebb (patch)
treeb686698f674067c8bf3ba8db53ee160f06b5d2ed /util/host-utils.c
parent1c46937358fc27a9e446d08c877389ee84d6767d (diff)
downloadqemu-9276a31c3484ff236a958a1e2a38beefb0eb7ebb.zip
qemu-9276a31c3484ff236a958a1e2a38beefb0eb7ebb.tar.gz
qemu-9276a31c3484ff236a958a1e2a38beefb0eb7ebb.tar.bz2
host-utils: move checks out of divu128/divs128
In preparation for changing the divu128/divs128 implementations to allow for quotients larger than 64 bits, move the div-by-zero and overflow checks to the callers. Signed-off-by: Luis Pires <luis.pires@eldorado.org.br> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20211025191154.350831-2-luis.pires@eldorado.org.br> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'util/host-utils.c')
-rw-r--r--util/host-utils.c40
1 files changed, 18 insertions, 22 deletions
diff --git a/util/host-utils.c b/util/host-utils.c
index a789a11..701a371 100644
--- a/util/host-utils.c
+++ b/util/host-utils.c
@@ -86,24 +86,23 @@ void muls64 (uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b)
*phigh = rh;
}
-/* Unsigned 128x64 division. Returns 1 if overflow (divide by zero or */
-/* quotient exceeds 64 bits). Otherwise returns quotient via plow and */
-/* remainder via phigh. */
-int divu128(uint64_t *plow, uint64_t *phigh, uint64_t divisor)
+/*
+ * Unsigned 128-by-64 division. Returns quotient via plow and
+ * remainder via phigh.
+ * The result must fit in 64 bits (plow) - otherwise, the result
+ * is undefined.
+ * This function will cause a division by zero if passed a zero divisor.
+ */
+void divu128(uint64_t *plow, uint64_t *phigh, uint64_t divisor)
{
uint64_t dhi = *phigh;
uint64_t dlo = *plow;
unsigned i;
uint64_t carry = 0;
- if (divisor == 0) {
- return 1;
- } else if (dhi == 0) {
+ if (divisor == 0 || dhi == 0) {
*plow = dlo / divisor;
*phigh = dlo % divisor;
- return 0;
- } else if (dhi >= divisor) {
- return 1;
} else {
for (i = 0; i < 64; i++) {
@@ -120,15 +119,20 @@ int divu128(uint64_t *plow, uint64_t *phigh, uint64_t divisor)
*plow = dlo;
*phigh = dhi;
- return 0;
}
}
-int divs128(int64_t *plow, int64_t *phigh, int64_t divisor)
+/*
+ * Signed 128-by-64 division. Returns quotient via plow and
+ * remainder via phigh.
+ * The result must fit in 64 bits (plow) - otherwise, the result
+ * is undefined.
+ * This function will cause a division by zero if passed a zero divisor.
+ */
+void divs128(int64_t *plow, int64_t *phigh, int64_t divisor)
{
int sgn_dvdnd = *phigh < 0;
int sgn_divsr = divisor < 0;
- int overflow = 0;
if (sgn_dvdnd) {
*plow = ~(*plow);
@@ -145,19 +149,11 @@ int divs128(int64_t *plow, int64_t *phigh, int64_t divisor)
divisor = 0 - divisor;
}
- overflow = divu128((uint64_t *)plow, (uint64_t *)phigh, (uint64_t)divisor);
+ divu128((uint64_t *)plow, (uint64_t *)phigh, (uint64_t)divisor);
if (sgn_dvdnd ^ sgn_divsr) {
*plow = 0 - *plow;
}
-
- if (!overflow) {
- if ((*plow < 0) ^ (sgn_dvdnd ^ sgn_divsr)) {
- overflow = 1;
- }
- }
-
- return overflow;
}
#endif