diff options
author | Christopher Celio <celio@eecs.berkeley.edu> | 2012-09-10 19:11:55 -0700 |
---|---|---|
committer | Christopher Celio <celio@eecs.berkeley.edu> | 2012-09-10 19:11:55 -0700 |
commit | 93f6f1ff134333a61580677a685ad61718ad0726 (patch) | |
tree | 15596604a098f042879a836125a14f2f41533c43 | |
parent | 79e238eff793adf04017519e10b30cc212f4c4bb (diff) | |
download | pk-93f6f1ff134333a61580677a685ad61718ad0726.zip pk-93f6f1ff134333a61580677a685ad61718ad0726.tar.gz pk-93f6f1ff134333a61580677a685ad61718ad0726.tar.bz2 |
Cleanup of div/divu/rem/remu.
-rw-r--r-- | pk/int.c | 8 | ||||
-rwxr-xr-x | softint/divu.c | 65 | ||||
-rwxr-xr-x | softint/remu.c | 56 | ||||
-rwxr-xr-x | softint/softint.h | 4 | ||||
-rw-r--r-- | softint/softint.mk.in | 3 | ||||
-rwxr-xr-x | softint/udivrem.c | 29 |
6 files changed, 36 insertions, 129 deletions
@@ -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;
+}
+
|