summary refs log tree commit diff stats
path: root/util/host-utils.c
diff options
context:
space:
mode:
authorTom Musta <tommusta@gmail.com>2014-01-07 10:05:51 -0600
committerAlexander Graf <agraf@suse.de>2014-03-05 03:06:39 +0100
commit98d1eb2748e84f9e3118d1bd2495f0cc917ac18d (patch)
tree7768c567eff4633cb49b55878c29dc4580dc45de /util/host-utils.c
parenta824bc191a90d86980a9ed090cb1d1219faaf8e7 (diff)
downloadfocaccia-qemu-98d1eb2748e84f9e3118d1bd2495f0cc917ac18d.tar.gz
focaccia-qemu-98d1eb2748e84f9e3118d1bd2495f0cc917ac18d.zip
target-ppc: Add ISA2.06 divdeu[o] Instructions
This patch adds the Divide Doubleword Extended Unsigned
instructions.  This instruction requires dividing a 128-bit
value by a 64 bit value.  Since 128 bit integer division is
not supported in TCG, a helper is used.  An architecture
independent 128-bit division routine is added to host-utils.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
[agraf: use ||]
Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'util/host-utils.c')
-rw-r--r--util/host-utils.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/util/host-utils.c b/util/host-utils.c
index f0784d6335..37c1706de6 100644
--- a/util/host-utils.c
+++ b/util/host-utils.c
@@ -86,4 +86,42 @@ 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)
+{
+    uint64_t dhi = *phigh;
+    uint64_t dlo = *plow;
+    unsigned i;
+    uint64_t carry = 0;
+
+    if (divisor == 0) {
+        return 1;
+    } else if (dhi == 0) {
+        *plow  = dlo / divisor;
+        *phigh = dlo % divisor;
+        return 0;
+    } else if (dhi > divisor) {
+        return 1;
+    } else {
+
+        for (i = 0; i < 64; i++) {
+            carry = dhi >> 63;
+            dhi = (dhi << 1) | (dlo >> 63);
+            if (carry || (dhi >= divisor)) {
+                dhi -= divisor;
+                carry = 1;
+            } else {
+                carry = 0;
+            }
+            dlo = (dlo << 1) | carry;
+        }
+
+        *plow = dlo;
+        *phigh = dhi;
+        return 0;
+    }
+}
 #endif /* !CONFIG_INT128 */