diff --git a/vvp/arith.cc b/vvp/arith.cc index 8438c6e66..42757b0c6 100644 --- a/vvp/arith.cc +++ b/vvp/arith.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: arith.cc,v 1.11 2001/07/13 00:38:57 steve Exp $" +#ident "$Id: arith.cc,v 1.12 2001/10/14 16:36:43 steve Exp $" #endif # include "arith.h" @@ -56,8 +56,7 @@ vvp_arith_mult::vvp_arith_mult(vvp_ipoint_t b, unsigned w) void vvp_arith_mult::set(vvp_ipoint_t i, functor_t f, bool push) { - assert(wid_ <= 8*sizeof(unsigned long)); - +if(wid_ <= 8*sizeof(unsigned long)) { unsigned long a = 0, b = 0; for (unsigned idx = 0 ; idx < wid_ ; idx += 1) { @@ -96,6 +95,72 @@ void vvp_arith_mult::set(vvp_ipoint_t i, functor_t f, bool push) else schedule_functor(ptr, 0); } +} else { /* long form only used if > machine length long */ + unsigned char *a, *b, *sum; + a = new unsigned char[wid_]; + b = new unsigned char[wid_]; + sum = new unsigned char[wid_]; + + int mxa = -1; + int mxb = -1; + + for (unsigned idx = 0 ; idx < wid_ ; idx += 1) { + vvp_ipoint_t ptr = ipoint_index(base_,idx); + functor_t obj = functor_index(ptr); + + unsigned ival = obj->ival; + if (ival & 0xaa) { + output_x_(push); + delete[]sum; + delete[]b; + delete[]a; + return; + } + + if((a[idx] = ((ival & 0x01) != 0))) mxa=idx; + if((b[idx] = ((ival & 0x04) != 0))) mxb=idx; + sum[idx] = 0; + } + +// do "unsigned ZZ sum = a * b" the hard way.. + for(int i=0;i<=mxb;i++) + { + if(b[i]) + { + unsigned char carry=0; + unsigned char temp; + + for(int j=0;j<=mxa;j++) + { + if(i+j>=(int)wid_) break; + temp=sum[i+j]+a[j]+carry; + sum[i+j]=(temp&1); + carry=(temp>>1); + } + } + } + + for (unsigned idx = 0 ; idx < wid_ ; idx += 1) { + vvp_ipoint_t ptr = ipoint_index(base_,idx); + functor_t obj = functor_index(ptr); + + unsigned oval = sum[idx]; + + if (obj->oval == oval) + continue; + + obj->oval = oval; + if (push) + functor_propagate(ptr); + else + schedule_functor(ptr, 0); + } + +delete[]sum; +delete[]b; +delete[]a; +} + } vvp_arith_sum::vvp_arith_sum(vvp_ipoint_t b, unsigned w) @@ -509,6 +574,9 @@ void vvp_shiftr::set(vvp_ipoint_t i, functor_t f, bool push) /* * $Log: arith.cc,v $ + * Revision 1.12 2001/10/14 16:36:43 steve + * Very wide multiplication (Anthony Bybell) + * * Revision 1.11 2001/07/13 00:38:57 steve * Remove width restriction on subtraction. * diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 956fbac5f..6c4f657b1 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vthread.cc,v 1.55 2001/09/15 18:27:05 steve Exp $" +#ident "$Id: vthread.cc,v 1.56 2001/10/14 16:36:43 steve Exp $" #endif # include "vthread.h" @@ -917,7 +917,7 @@ bool of_MOV(vthread_t thr, vvp_code_t cp) bool of_MUL(vthread_t thr, vvp_code_t cp) { assert(cp->bit_idx1 >= 4); - assert(cp->number <= 8*sizeof(unsigned long)); + if(cp->number <= 8*sizeof(unsigned long)) { unsigned idx1 = cp->bit_idx1; unsigned idx2 = cp->bit_idx2; @@ -946,6 +946,66 @@ bool of_MUL(vthread_t thr, vvp_code_t cp) } return true; + } else { + unsigned idx1 = cp->bit_idx1; + unsigned idx2 = cp->bit_idx2; + + unsigned char *a, *b, *sum; + a = new unsigned char[cp->number]; + b = new unsigned char[cp->number]; + sum = new unsigned char[cp->number]; + + int mxa = -1; + int mxb = -1; + + for (unsigned idx = 0 ; idx < cp->number ; idx += 1) { + unsigned lb = thr_get_bit(thr, idx1); + unsigned rb = thr_get_bit(thr, idx2); + + if ((lb | rb) & 2) + { + delete[]sum; + delete[]b; + delete[]a; + goto x_out; + } + + if((a[idx] = lb)) mxa=idx; + if((b[idx] = rb)) mxb=idx; + sum[idx]=0; + + idx1 += 1; + if (idx2 >= 4) + idx2 += 1; + } + +// do "unsigned ZZ sum = a * b" the hard way.. + for(int i=0;i<=mxb;i++) + { + if(b[i]) + { + unsigned char carry=0; + unsigned char temp; + + for(int j=0;j<=mxa;j++) + { + if(i+j>=(int)cp->number) break; + temp=sum[i+j]+a[j]+carry; + sum[i+j]=(temp&1); + carry=(temp>>1); + } + } + } + + for (unsigned idx = 0 ; idx < cp->number ; idx += 1) { + thr_put_bit(thr, cp->bit_idx1+idx, sum[idx]); + } + + delete[]sum; + delete[]b; + delete[]a; + return true; + } x_out: for (unsigned idx = 0 ; idx < cp->number ; idx += 1) @@ -1356,6 +1416,9 @@ bool of_ZOMBIE(vthread_t thr, vvp_code_t) /* * $Log: vthread.cc,v $ + * Revision 1.56 2001/10/14 16:36:43 steve + * Very wide multiplication (Anthony Bybell) + * * Revision 1.55 2001/09/15 18:27:05 steve * Make configure detect malloc.h *