aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Celio <celio@eecs.berkeley.edu>2012-09-10 19:11:55 -0700
committerChristopher Celio <celio@eecs.berkeley.edu>2012-09-10 19:11:55 -0700
commit93f6f1ff134333a61580677a685ad61718ad0726 (patch)
tree15596604a098f042879a836125a14f2f41533c43
parent79e238eff793adf04017519e10b30cc212f4c4bb (diff)
downloadriscv-pk-93f6f1ff134333a61580677a685ad61718ad0726.zip
riscv-pk-93f6f1ff134333a61580677a685ad61718ad0726.tar.gz
riscv-pk-93f6f1ff134333a61580677a685ad61718ad0726.tar.bz2
Cleanup of div/divu/rem/remu.
-rw-r--r--pk/int.c8
-rwxr-xr-xsoftint/divu.c65
-rwxr-xr-xsoftint/remu.c56
-rwxr-xr-xsoftint/softint.h4
-rw-r--r--softint/softint.mk.in3
-rwxr-xr-xsoftint/udivrem.c29
6 files changed, 36 insertions, 129 deletions
diff --git a/pk/int.c b/pk/int.c
index d7ced91..8759a46 100644
--- a/pk/int.c
+++ b/pk/int.c
@@ -46,7 +46,7 @@ int emulate_int(trapframe_t* tf)
num_negative++;
}
- unsigned long res = softint_divu(xrs1, xrs2);
+ unsigned long res = softint_udivrem(xrs1, xrs2, 0);
if (num_negative == 1)
XRD = -res;
else
@@ -56,7 +56,7 @@ int emulate_int(trapframe_t* tf)
{
if(noisy)
printk("emulating divu\n");
- XRD = softint_divu( xrs1, xrs2);
+ XRD = softint_udivrem( xrs1, xrs2, 0);
}
else if(IS_INSN(MUL))
{
@@ -72,13 +72,13 @@ int emulate_int(trapframe_t* tf)
if ((signed long) xrs1 < 0) {xrs1 = -xrs1;}
if ((signed long) xrs2 < 0) {xrs2 = -xrs2;}
- XRD = softint_remu(xrs1, xrs2);
+ XRD = softint_udivrem(xrs1, xrs2, 1);
}
else if(IS_INSN(REMU))
{
if(noisy)
printk("emulating remu\n");
- XRD = softint_remu(xrs1, xrs2);
+ XRD = softint_udivrem(xrs1, xrs2, 1);
}
else
return -1;
diff --git a/softint/divu.c b/softint/divu.c
deleted file mode 100755
index cf74876..0000000
--- a/softint/divu.c
+++ /dev/null
@@ -1,65 +0,0 @@
-
-#include <stdint.h>
-
-long
- softint_divu( long rs1, long rs2 )
-{
- // quotient = dividend / divisor + remainder
- unsigned long dividend = rs1;
- unsigned long divisor = rs2;
-
- int msb = (sizeof(long) << 3) - 1;
-
- if (divisor == 0) return -1;
-
- unsigned long temp_dividend = dividend;
- unsigned long temp_divisor = divisor;
-
- unsigned long quotient = 0;
-
-
- for (int i=0; i <= msb; i++)
- {
- unsigned long temp_quotient = 1;
-
- if (temp_divisor == temp_dividend) { quotient += 1; break;}
- else if (temp_dividend < temp_divisor) { quotient += 0; break; }
-
-
- // check for corner-case when (msb of dividend)==1
- if ((temp_dividend & (1 << msb)) == (1 << msb))
- {
- int hi = msb, lo = 0;
- for (int i=msb; i >= 0; i--)
- {
- unsigned int mask = 1 << i;
- if ((mask & temp_divisor) == mask)
- {
- lo = i;
- break;
- }
- }
- temp_divisor = temp_divisor << (hi - lo - 1);
- temp_quotient = temp_quotient << (hi - lo - 1);
- }
- else
- {
- while (temp_divisor <= temp_dividend)
- {
- temp_divisor = temp_divisor << 1;
- temp_quotient = temp_quotient << 1;
- }
-
- temp_divisor = temp_divisor >> 1;
- temp_quotient = temp_quotient >> 1;
- }
-
-
- temp_dividend = temp_dividend - temp_divisor;
- temp_divisor = divisor;
- quotient += temp_quotient;
- }
-
- return quotient;
-}
-
diff --git a/softint/remu.c b/softint/remu.c
deleted file mode 100755
index eca4781..0000000
--- a/softint/remu.c
+++ /dev/null
@@ -1,56 +0,0 @@
-
-#include <stdint.h>
-
-long
- softint_remu( long rs1, long rs2 )
-{
- // quotient = dividend / divisor + remainder
- unsigned long dividend = rs1;
- unsigned long divisor = rs2;
-
- int msb = (sizeof(long) << 3) - 1;
-
- if (divisor == 0) { return dividend; }
-
- unsigned long temp_dividend = dividend;
- unsigned long temp_divisor = divisor;
-
- for (int i=0; i <= msb; i++)
- {
- if (temp_divisor == temp_dividend) { return 0; }
- else if (temp_dividend < temp_divisor) { return temp_dividend; }
-
-
- // check for corner-case when (msb of dividend)==1
- if ((temp_dividend & (1 << msb)) == (1 << msb))
- {
- int hi = msb, lo = 0;
- for (int i=msb; i >= 0; i--)
- {
- unsigned int mask = 1 << i;
- if ((mask & temp_divisor) == mask)
- {
- lo = i;
- break;
- }
- }
- temp_divisor = temp_divisor << (hi - lo - 1);
- }
- else
- {
- while ( (unsigned long) temp_divisor <= (unsigned long) temp_dividend)
- {
- temp_divisor = temp_divisor << 1;
- }
-
- temp_divisor = temp_divisor >> 1;
- }
-
-
- temp_dividend = temp_dividend - temp_divisor;
- temp_divisor = divisor;
- }
-
- return temp_dividend;
-}
-
diff --git a/softint/softint.h b/softint/softint.h
index de40355..69ca31a 100755
--- a/softint/softint.h
+++ b/softint/softint.h
@@ -11,8 +11,8 @@ extern "C" {
| Integer Operations.
*----------------------------------------------------------------------------*/
-long softint_divu( long, long );
-long softint_remu( long, long );
+long softint_mul( long, long );
+long softint_udivrem( long, long, int );
#ifdef __cplusplus
diff --git a/softint/softint.mk.in b/softint/softint.mk.in
index 4c312cf..a2b632f 100644
--- a/softint/softint.mk.in
+++ b/softint/softint.mk.in
@@ -4,9 +4,8 @@ softint_hdrs = \
softint.h \
softint_c_srcs = \
- divu.c \
+ udivrem.c \
mul.c \
- remu.c \
softint_test_srcs =
diff --git a/softint/udivrem.c b/softint/udivrem.c
new file mode 100755
index 0000000..906c665
--- /dev/null
+++ b/softint/udivrem.c
@@ -0,0 +1,29 @@
+
+#include <stdint.h>
+
+
+unsigned long
+softint_udivrem(unsigned long num, unsigned long den, int modwanted)
+{
+ unsigned long bit = 1;
+ unsigned long res = 0;
+
+ while (den < num && bit && ((signed long) den >= 0))
+ {
+ den <<=1;
+ bit <<=1;
+ }
+ while (bit)
+ {
+ if (num >= den)
+ {
+ num -= den;
+ res |= bit;
+ }
+ bit >>=1;
+ den >>=1;
+ }
+ if (modwanted) return num;
+ return res;
+}
+