Add %div support (Anthony Bybell)

This commit is contained in:
steve 2001-10-16 01:26:54 +00:00
parent 42dab181cd
commit a3217db7b2
4 changed files with 267 additions and 6 deletions

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: codes.h,v 1.34 2001/08/26 22:59:32 steve Exp $"
#ident "$Id: codes.h,v 1.35 2001/10/16 01:26:54 steve Exp $"
#endif
@ -49,6 +49,7 @@ extern bool of_CMPZ(vthread_t thr, vvp_code_t code);
extern bool of_DELAY(vthread_t thr, vvp_code_t code);
extern bool of_DELAYX(vthread_t thr, vvp_code_t code);
extern bool of_DISABLE(vthread_t thr, vvp_code_t code);
extern bool of_DIV(vthread_t thr, vvp_code_t code);
extern bool of_END(vthread_t thr, vvp_code_t code);
extern bool of_FORK(vthread_t thr, vvp_code_t code);
extern bool of_INV(vthread_t thr, vvp_code_t code);
@ -140,6 +141,9 @@ extern vvp_code_t codespace_index(vvp_cpoint_t ptr);
/*
* $Log: codes.h,v $
* Revision 1.35 2001/10/16 01:26:54 steve
* Add %div support (Anthony Bybell)
*
* Revision 1.34 2001/08/26 22:59:32 steve
* Add the assign/x0 and set/x opcodes.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: compile.cc,v 1.106 2001/10/14 03:41:58 steve Exp $"
#ident "$Id: compile.cc,v 1.107 2001/10/16 01:26:54 steve Exp $"
#endif
# include "arith.h"
@ -92,6 +92,7 @@ const static struct opcode_table_s opcode_table[] = {
{ "%cmp/z", of_CMPZ, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%delay", of_DELAY, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
{ "%delayx", of_DELAYX, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
{ "%div", of_DIV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%end", of_END, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%inv", of_INV, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%ix/add", of_IX_ADD, 2, {OA_BIT1, OA_NUMBER, OA_NONE} },
@ -1573,6 +1574,9 @@ vvp_ipoint_t debug_lookup_functor(const char*name)
/*
* $Log: compile.cc,v $
* Revision 1.107 2001/10/16 01:26:54 steve
* Add %div support (Anthony Bybell)
*
* Revision 1.106 2001/10/14 03:41:58 steve
* Handle mode-42 functor init.
*

View File

@ -1,7 +1,7 @@
/*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
*
* $Id: opcodes.txt,v 1.29 2001/10/10 04:48:12 steve Exp $
* $Id: opcodes.txt,v 1.30 2001/10/16 01:26:55 steve Exp $
*/
@ -144,6 +144,13 @@ scope. The label identifies the scope in question, and the threads are
the threads that are currently within that scope.
* %div <bit-l>, <bit-r>, <wid>
This instruction arithmetically divides the <bit-l> vector by the
<bit-r> vector, and leaves the result in the <bit-l> vector. IF any of
the bits in either vector are x or z, the entire result is x.
* %fork <code-label>, <scope-label>
This instruction is similar to %jmp, except that it creates a new
@ -256,12 +263,12 @@ destination bit. This function does not do any bounds checking.
* %mod <bit-l>, <bit-r>, <wid>
This instruction calculates the modulus %r of the left operand, and
replaces the left operand with the result. The <wid> gives the width
of the left and the right vectors, and the left vector is completely
replaced with the result.
* %mov <dst>, <src>, <wid>
This instruction copies a vector from one place in register space to

View File

@ -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.57 2001/10/14 17:36:19 steve Exp $"
#ident "$Id: vthread.cc,v 1.58 2001/10/16 01:26:55 steve Exp $"
#endif
# include "vthread.h"
@ -616,6 +616,148 @@ bool of_DISABLE(vthread_t thr, vvp_code_t cp)
return true;
}
bool of_DIV(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx1 >= 4);
if(cp->number <= 8*sizeof(unsigned long)) {
unsigned idx1 = cp->bit_idx1;
unsigned idx2 = cp->bit_idx2;
unsigned long lv = 0, rv = 0;
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)
goto x_out;
lv |= lb << idx;
rv |= rb << idx;
idx1 += 1;
if (idx2 >= 4)
idx2 += 1;
}
lv /= rv;
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
thr_put_bit(thr, cp->bit_idx1+idx, (lv&1) ? 1 : 0);
lv >>= 1;
}
return true;
} else {
int len=cp->number;
unsigned char *a, *b, *z, *t;
a = new unsigned char[len+1];
b = new unsigned char[len+1];
z = new unsigned char[len+1];
t = new unsigned char[len+1];
unsigned char carry;
unsigned char temp;
int mxa = -1, mxz = -1;
int i;
int current, copylen;
unsigned idx1 = cp->bit_idx1;
unsigned idx2 = cp->bit_idx2;
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 []t;
delete []z;
delete []b;
delete []a;
goto x_out;
}
z[idx]=lb;
a[idx]=1-rb; // for 2s complement add..
idx1 += 1;
if (idx2 >= 4)
idx2 += 1;
}
z[len]=0;
a[len]=1;
for(i=0;i<len+1;i++) {
b[i]=0;
}
for(i=len-1;i>=0;i--) {
if(!a[i]) {
mxa=i;
break;
}
}
for(i=len-1;i>=0;i--) {
if(z[i]) {
mxz=i;
break;
}
}
if((mxa>mxz)||(mxa==-1)) {
if(mxa==-1) {
fprintf(stderr, "Division By Zero error, exiting.\n");
exit(255);
}
goto tally;
}
copylen = mxa + 2;
current = mxz - mxa;
while(current > -1) {
carry = 1;
for(i=0;i<copylen;i++) {
temp = z[i+current] + a[i] + carry;
t[i] = (temp&1);
carry = (temp>>1);
}
if(carry) {
for(i=0;i<copylen;i++) {
z[i+current] = t[i];
}
b[current] = 1;
}
current--;
}
tally:
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
// n.b., z[] has the remainder...
thr_put_bit(thr, cp->bit_idx1+idx, b[idx]);
}
delete []t;
delete []z;
delete []b;
delete []a;
return true;
}
x_out:
for (unsigned idx = 0 ; idx < cp->number ; idx += 1)
thr_put_bit(thr, cp->bit_idx1+idx, 2);
return true;
}
/*
* This terminates the current thread. If there is a parent who is
* waiting for me to die, then I schedule it. At any rate, I mark
@ -859,8 +1001,8 @@ bool of_LOAD_X(vthread_t thr, vvp_code_t cp)
bool of_MOD(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;
unsigned long lv = 0, rv = 0;
@ -889,6 +1031,107 @@ bool of_MOD(vthread_t thr, vvp_code_t cp)
return true;
} else {
int len=cp->number;
unsigned char *a, *z, *t;
a = new unsigned char[len+1];
z = new unsigned char[len+1];
t = new unsigned char[len+1];
unsigned char carry;
unsigned char temp;
int mxa = -1, mxz = -1;
int i;
int current, copylen;
unsigned idx1 = cp->bit_idx1;
unsigned idx2 = cp->bit_idx2;
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 []t;
delete []z;
delete []a;
goto x_out;
}
z[idx]=lb;
a[idx]=1-rb; // for 2s complement add..
idx1 += 1;
if (idx2 >= 4)
idx2 += 1;
}
z[len]=0;
a[len]=1;
for(i=len-1;i>=0;i--)
{
if(!a[i])
{
mxa=i; break;
}
}
for(i=len-1;i>=0;i--)
{
if(z[i])
{
mxz=i; break;
}
}
if((mxa>mxz)||(mxa==-1))
{
if(mxa==-1)
{
fprintf(stderr, "Division By Zero error, exiting.\n");
exit(255);
}
goto tally;
}
copylen = mxa + 2;
current = mxz - mxa;
while(current > -1)
{
carry = 1;
for(i=0;i<copylen;i++)
{
temp = z[i+current] + a[i] + carry;
t[i] = (temp&1);
carry = (temp>>1);
}
if(carry)
{
for(i=0;i<copylen;i++)
{
z[i+current] = t[i];
}
}
current--;
}
tally:
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
thr_put_bit(thr, cp->bit_idx1+idx, z[idx]);
}
delete []t;
delete []z;
delete []a;
return true;
}
x_out:
for (unsigned idx = 0 ; idx < cp->number ; idx += 1)
thr_put_bit(thr, cp->bit_idx1+idx, 2);
@ -1416,6 +1659,9 @@ bool of_ZOMBIE(vthread_t thr, vvp_code_t)
/*
* $Log: vthread.cc,v $
* Revision 1.58 2001/10/16 01:26:55 steve
* Add %div support (Anthony Bybell)
*
* Revision 1.57 2001/10/14 17:36:19 steve
* Forgot to propagate carry.
*