home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD2.mdf
/
c
/
library
/
xplatfrm
/
tierra
/
instruct.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-04-26
|
23KB
|
718 lines
/* instruct.c 28-10-91 instruction set for the Tierra simulator */
/** Tierra Simulator V3.0: Copyright (c) 1991 Thomas S. Ray **/
#include "license.h"
#ifndef lint
static char sccsid[] = "@(#)instruct.c 1.22 9/19/91";
#endif
#include "tierra.h"
#include "extern.h"
void nop(ci)
I32s ci;
{ (cells + ci)->c.fl = 0; }
void or1(ci) /* flip low order bit of destination register */
I32s ci;
{ Pcells ce = cells + ci;
*(is.dreg) ^= (1 + flaw(ci));
if(is.dmod)
{ *(is.dreg) = mo(*(is.dreg),is.dmod);
is.dmod = 0;
}
else if(is.dran && (*(is.dreg) > is.dran || *(is.dreg) < -is.dran))
{ *(is.dreg) = is.dval;
is.dran = 0;
SetFlag(ce); return ;
}
ce->c.fl = 0;
}
void shl(ci)
I32s ci;
{ Pcells ce = cells + ci;
*(is.dreg) <<= (1 + flaw(ci));
if(is.dmod)
{ *(is.dreg) = mo(*(is.dreg),is.dmod);
is.dmod = 0;
}
else if(is.dran && (*(is.dreg) > is.dran || *(is.dreg) < -is.dran))
{ *(is.dreg) = is.dval;
is.dran = 0;
SetFlag(ce); return ;
}
ce->c.fl = 0;
}
void if_cz(ci) /* execute next instruction only if cx == 0 */
I32s ci;
{ Pcells ce = cells + ci;
if(is.sval + flaw(ci))
is.iip = 2;
ce->c.fl = 0;
}
void math(ci)
I32s ci;
{ Pcells ce = cells + ci;
*(is.dreg) = is.sval + is.sval2 + flaw(ci);
if(is.dmod)
{ *(is.dreg) = mo(*(is.dreg),is.dmod);
is.dmod = 0;
}
else if(is.dran && (*(is.dreg) > is.dran || *(is.dreg) < -is.dran))
{ *(is.dreg) = is.dval;
is.dran = 0;
SetFlag(ce); return ;
}
ce->c.fl = 0;
}
void push(ci)
I32s ci;
{ Pcells ce = cells + ci;
ce->c.sp = ++ce->c.sp % STACK_SIZE;
ce->c.st[ce->c.sp] = is.sval; ce->c.fl = 0;
}
void pop(ci)
I32s ci;
{ Pcells ce = cells + ci;
if(is.dran && (ce->c.st[ce->c.sp] > is.dran ||
ce->c.st[ce->c.sp] < -is.dran))
{ is.dran = 0;
SetFlag(ce); return ;
}
*(is.dreg) = ce->c.st[ce->c.sp];
if(!ce->c.sp) ce->c.sp = STACK_SIZE - 1; /* decrement stack pointer */
else --ce->c.sp;
if(is.dmod)
{ *(is.dreg) = mo(*(is.dreg),is.dmod);
is.dmod = 0;
}
ce->c.fl = 0;
}
void tcall(ci) /* call template */
I32s ci;
{ push(ci);
adr(ci);
}
void call(ci) /* call address */
I32s ci;
{ push(ci);
movdd(ci);
}
void mov(ci)
I32s ci;
{ switch(is.mode)
{ case 0: movdd(ci); break; /* direct destination, direct source */
case 1: movdi(ci); break; /* direct destination, indirect source */
case 2: movid(ci); break; /* indirect destination, direct source */
case 3: movii(ci); break; /* indirect destination, indirect source */
}
}
void movdd(ci)
I32s ci;
{ Pcells ce = (cells + ci);
*(is.dreg) = is.sval + flaw(ci);
if(is.dmod)
{ *(is.dreg) = mo(*(is.dreg),is.dmod);
is.dmod = 0;
}
else if(is.dran && (*(is.dreg) > is.dran || *(is.dreg) < -is.dran))
{ *(is.dreg) = is.dval;
is.dran = 0;
SetFlag(ce); return ;
}
ce->c.fl = 0;
}
void movdi(ci)
I32s ci;
{ Pcells ce = (cells + ci);
if((IsInsideCell(ce,is.sval) || !is.sins->read) &&
(0 <= is.sval && is.sval < SoupSize))
{ *(is.dreg) = is.sins->inst + flaw(ci);
ce->c.fl = 0;
}
else { SetFlag(ce); return ; }
if(is.dmod)
{ *(is.dreg) = mo(*(is.dreg),is.dmod);
is.dmod = 0;
}
else if(is.dran && (*(is.dreg) > is.dran || *(is.dreg) < -is.dran))
{ *(is.dreg) = is.dval;
is.dran = 0;
SetFlag(ce); return ;
}
}
void movid(ci)
I32s ci;
{ Pcells ce = (cells + ci);
if((IsInsideCell(ce,is.dval) || !is.dins->write) &&
(0 <= is.dval && is.dval < SoupSize))
{ is.dins->inst = is.sval + flaw(ci);
ce->c.fl = 0;
}
else SetFlag(ce);
}
void movii(ci)
I32s ci;
{ Pcells ce = (cells + ci), ct;
Pgl tgl, ogl;
I32s ti;
I32u who;
if ((!is.dins->write || IsInsideCell(ce,is.dval)) &&
(!is.sins->read || IsInsideCell(ce,is.sval)) &&
(0 <= is.dval && is.dval < SoupSize) &&
(0 <= is.sval && is.sval < SoupSize))
{ if(is.dval >= ce->md.p && is.dval <= ce->md.p + ce->md.s)
ce->d.mov_daught++;
is.dins->inst = is.sins->inst;
if(RateMovMut && ++CountMovMut >= RateMovMut)
{ mut_site(soup + ad(is.dval), is.dtra);
CountMovMut = tlrand() % RateMovMut;
TotMovMut++;
}
ce->c.fl = 0;
if(WatchMov)
GenExMov(ci, is.dval, is.sval);
}
else SetFlag(ce);
}
void adr(ci) /* is.dreg = address of instruction after target template */
I32s ci; /* is.dreg2 = template size */
/* is.sval2 = size of template */
/* is.dval = start address for forward search */
/* is.dval2 = start address for backward search */
/* is.mode = search direction: 0 out, 1 forward, 2 backward */
/* is.mode2 = match style: 0 = complement, 1 = direct */
{ Pcells ce = cells + ci;
Ind adrt;
if(!is.sval2) { SetFlag(ce); return ; } /* source template missing */
if(!is.mode) /* outward search */
adrt = template(is.dval,is.dval2,is.sval2,'o',is.mode2,ci);
if(is.mode == 1) /* forward search */
adrt = template(is.dval,is.dval2,is.sval2,'f',is.mode2,ci);
if(is.mode == 2) /* backward search */
adrt = template(is.dval,is.dval2,is.sval2,'b',is.mode2,ci);
if(adrt < 0) /* target template not found */
{ is.iip = is.sval2 + 1; /* skip ip over source template */
SetFlag(ce); return ;
}
*(is.dreg) = adrt;
*(is.dreg2) = is.sval2;
if(is.dmod)
{ *(is.dreg) = mo(*(is.dreg),is.dmod);
is.dmod = 0;
}
else if(is.dran && (*(is.dreg) > is.dran || *(is.dreg) < -is.dran))
{ *(is.dreg) = is.dval;
is.dran = 0;
SetFlag(ce); return ;
}
if(is.dmod2)
{ *(is.dreg2) = mo(*(is.dreg2),is.dmod2);
is.dmod2 = 0;
}
else if(is.dran2 && (*(is.dreg2) > is.dran2 || *(is.dreg2) < -is.dran2))
{ *(is.dreg2) = is.dval2;
is.dran2 = 0;
SetFlag(ce); return ;
}
ce->c.fl = 0; return ;
}
void mal(ci) /* allocate space for a new cell */
I32s ci;
{ Pcells ce = cells + ci;
Ind p;
I32s size, osize;
if(is.sval <= 0 || is.sval == ce->md.s || is.sval > MaxMalMult*ce->mm.s)
{ ce->c.fl = 1; return ; }
is.sval2 = size = (I32s) is.sval + flaw(ci);
if(!size) return ;
if(ce->md.s)
{
#ifdef ERROR
if(ce->md.p < 0 || ce->md.p >= SoupSize)
{ sprintf(mes[0],"Tierra mal() error 1");
if (!hangup)
FEMessage(1);
else
{ sprintf(mes[1],"system being saved to disk");
FEMessage(2);
}
while(hangup) ;
WriteSoup(1);
exit(0);
}
#endif
MemDealloc(ce->md.p,ce->md.s);
ce->d.mov_daught = 0;
ce->md.s = 0;
}
osize = size;
p = MemAlloc(&size);
while(!size && osize < 3 * AverageSize)
{ reaper(1);
size = osize;
p = MemAlloc(&size);
}
#ifdef ERROR
if(p < 0 || p >= SoupSize)
{ sprintf(mes[0],"Tierra mal error 2");
if (!hangup)
FEMessage(1);
else
{ sprintf(mes[1],"system being saved to disk");
FEMessage(2);
}
while(hangup) ;
WriteSoup(1);
exit(0);
}
#endif
if(!size) { ce->c.fl = 1; return ; }
*(is.dreg) = ce->md.p = ad(p); ce->md.s = size; ce->c.fl = 0;
DownReperIf(ci);
}
void chmode(ci)
I32s ci;
/* is.sval = location of chmoded block */
/* is.sval2 = size of chmoded block */
/* is.dtra = track being chmoded */
/* is.mode = chmod mode, unix notation, e.g. 7 = full protection */
/* 1 bit = execute, 2 bit = write, 4 bit = read */
/* only owner of memory has chmod privelages */
{ Pcells ce = cells + ci;
Ind a = 0, t;
I8s exec, write, read;
exec = IsBit(is.mode,0); write = IsBit(is.mode,1); read =IsBit(is.mode,2);
while(a < is.sval2)
{ t = ad(is.sval + a);
if(IsInsideCell(ce, t))
{ soup[t][is.dtra].exec = exec;
soup[t][is.dtra].write = write;
soup[t][is.dtra].read = read;
}
else SetFlag(ce);
a++;
}
ce->c.fl = 0;
}
void malchm(ci)
I32s ci;
{ /* is.sval = requested size of block, is.sval2 = flawed size of block */
/* is.dreg = location of block */
mal(ci);
is.sval = *(is.dreg);
/* is.sval = location of chmoded block */
/* is.sval2 = size of chmoded block */
/* is.dtra = track being chmoded */
/* is.mode = chmod mode, unix notation, e.g. 7 = full protection */
chmode(ci);
}
void divide(ci)
I32s ci;
{ Pcells ce = (cells+ci);
Pcells nc; /* pointer to the new cell */
I32s ni = 2;
if (ce->md.s < MinCellSize || ce->d.mov_daught < (I32s) (ce->md.s *
MovPropThrDiv) || !ce->d.mov_daught)
{ ce->c.fl = 1; return;}
if (DivSameSiz)
{ if (ce->mm.s != ce->md.s)
{ ce->c.fl = 1; return; }
if (DivSameGen &&
!IsSameGen(ce->mm.s, soup + ce->md.p, soup + ce->mm.p))
{ ce->c.fl = 1; return; }
}
switch(is.mode)
{ case 0: /* create cpu */
{ if(ce->d.ni < 0) /* if there is no cpu (first call to div 0) */
{ if(++NumCells > CellsSize - 2)
{ CheckCells();
ce = cells + ci;
}
while((cells + ni)->ld) /* find unoccupied cell struct */
{ ni++;
#ifdef ERROR
if(ni >= CellsSize)
{ sprintf(mes[0],"Tierra DIV error A0, exiting");
if (!hangup)
FEMessage(1);
else
{ sprintf(mes[1],"system being saved to disk");
FEMessage(2);
}
while(hangup) ;
WriteSoup(1);
exit(0);
}
#endif
}
nc = cells + ni;
InitCell(ni);
nc->ld = 1;
nc->mm = ce->md;
nc->c.ip = nc->mm.p;
nc->d.dm = 1;
ce->d.ni = ni;
}
else /* if there is a cpu (second call to div 0) */
{ ni = ce->d.ni;
nc = cells + ni;
if(nc->d.is) /* call to div 0 after call to div 1 */
{ RmvFrmSlicer(ni);
nc->d.is = 0;
}
else /* two sequential calls to div 0, error */
{ ce->c.fl = 1; return; }
}
break;
}
case 1: /* start cpu */
{ if(ce->d.ni < 0) /* if there is no cpu, div 1 before div 0 */
{ if(++NumCells > CellsSize - 2)
{ CheckCells();
ce = cells + ci;
}
while((cells + ni)->ld) /* find unoccupied cell struct */
{ ni++;
#ifdef ERROR
if(ni >= CellsSize)
{ sprintf(mes[0],"Tierra DIV error B0, exiting");
if (!hangup)
FEMessage(1);
else
{ sprintf(mes[1],"system being saved to disk");
FEMessage(2);
}
while(hangup) ;
WriteSoup(1);
exit(0);
}
#endif
}
nc = cells + ni;
InitCell(ni);
nc->ld = 1;
nc->mm = ce->md;
nc->c.ip = nc->mm.p;
nc->d.dm = 1;
ce->d.ni = ni;
}
else /* if there is already a cpu, make pointers to it */
{ ni = ce->d.ni;
nc = cells + ni;
}
if(nc->d.is) /* 2nd call to div 1, cpu is already started */
{ RmvFrmSlicer(ni);
nc->d.is = 0;
}
else /* not 2nd call to div 1, cpu is not already started */
{ EntBotSlicer(ni);
nc->d.is = 1;
}
break;
}
case 2: /* split */
{ if(ce->d.ni < 0) /* if there is no cpu, div 2 before div 0 */
{ if(++NumCells > CellsSize - 2)
{ CheckCells();
ce = cells + ci;
}
while((cells + ni)->ld) /* find unoccupied cell struct */
{ ni++;
#ifdef ERROR
if(ni >= CellsSize)
{ sprintf(mes[0],"Tierra DIV error C0, exiting");
if (!hangup)
FEMessage(1);
else
{ sprintf(mes[1],"system being saved to disk");
FEMessage(2);
}
while(hangup) ;
WriteSoup(1);
exit(0);
}
#endif
}
nc = cells + ni;
InitCell(ni);
nc->ld = 1;
nc->mm = ce->md;
nc->c.ip = nc->mm.p;
}
else
{ ni = ce->d.ni;
nc = cells + ni;
}
if(!nc->d.is) /* no slicer, div CX before div BX */
{ EntBotSlicer(ni);
nc->d.is = 1;
}
ce->md.s = ce->md.p = 0;
ce->d.ni = -1; /* clean up if AX or BX before CX */
nc->d.dm = 0;
EntBotReaper(ni);
DownReperIf(ci);
DivideBookeep(ci, ni);
}
}
ce->c.fl = 0;
}
void CheckCells() /* check and adjust memory allocation if necessary */
{ I32s j, oCellsSize = CellsSize;
I8s buf[80];
sprintf(mes[0],"in_div CheckCells: realloc, NumCells = %ld", NumCells);
sprintf(buf," old CellsSize = %ld ", CellsSize);
CellsSize = (I32s) CellsSize * 1.6;
if(NumCells > CellsSize - 2) CellsSize += 12;
cells = (Pcells) threalloc((I8s Hp) cells,
(I32u) CellsSize * (I32u) sizeof(struct cell));
if(cells == NULL)
{ sprintf(mes[0],"Tierra instructions realloc error, exiting");
if (!hangup)
FEMessage(1);
else
{ sprintf(mes[1],"system being saved to disk");
FEMessage(2);
}
while(hangup) ;
WriteSoup(1);
exit(0);
}
sprintf(mes[1],"%s new CellsSize = %ld", buf, CellsSize);
FEMessage(2);
#ifdef __TURBOC__
sprintf(mes[0],"coreleft = %lu divide (cells)", coreleft());
FEMessage(1);
#endif
for(j = oCellsSize; j < CellsSize; j++)
InitCell(j);
}
I32s flaw(ci)
I32s ci;
{ CountFlaw++;
if(RateFlaw && CountFlaw >= RateFlaw)
{ CountFlaw = tlrand() % RateFlaw;
TotFlaw++;
(cells + ci)->d.flaw++;
if(tcrand() % 2) return 1;
return -1;
}
return 0;
}
Ind template(f, b, tz, dir, mode, ci) /*search in specified direction for */
/* nop template return address, returns address of instruction following */
/* target template, i.e., target + tz */
/* NOTE: ce->c.ip must point to the instruction (agent) being executed */
Ind f; /* starting address for forward search */
Ind b; /* starting address for backward search */
I32s tz; /* template size */
I8s dir; /* direction of search, f = forward, b = backward, o = out */
I8s mode; /* match mode: 0 = complement, 1 = direct */
I32s ci; /* which cell */
{ Ind o, l = 1, adrt;
I32s i = 0, match;
I8s df, db;
Pgl tgl;
Pcells ce = cells + ci;
if((tz < MinTemplSize) || (tz > SoupSize))
{ adrt = -1;
goto finish;
}
if(dir == 'o') df = db = 1; /* both directions */
if(dir == 'f') { df = 1; db = 0; } /* forward only */
if(dir == 'b') { df = 0; db = 1; } /* backwards only */
o = ad(ce->c.ip + 1);
while(1)
{ while(1)/*this skips sections of codes that are not templates (NOPs)*/
{ /* forward */
if(df && (soup[f][ce->c.tr].inst == 0
|| soup[f][ce->c.tr].inst == 1)) break;
else { f++; f = ad(f); }
/* backward */
if(db && (soup[b][ce->c.tr].inst == 0
|| soup[b][ce->c.tr].inst == 1)) break;
else { b--; b = ad(b); }
}
match = 1; /* forward */
if(df && (soup[f][ce->c.tr].inst == 0
|| soup[f][ce->c.tr].inst == 1)) /* if NOPs */
{ if(!mode) /* compliment match mode */
{ for(i = 0; i < tz; i++) /* over the full template size */
{ if(soup[ad(o + i)][ce->c.tr].inst
+ soup[ad(f + i)][ce->c.tr].inst != 1)
{ match = 0; break; }
}
}
else /* direct match mode */
{ for(i = 0; i < tz; i++) /* over the full template size */
{ if(soup[ad(o + i)][ce->c.tr].inst
- soup[ad(f + i)][ce->c.tr].inst != 0)
{ match = 0; break; }
}
}
if(match)
{ f += flaw(ci);
adrt = ad(f + tz);
goto finish;
}
}
match = 1; /* backward */
if(db && (soup[b][ce->c.tr].inst == 0
|| soup[b][ce->c.tr].inst == 1)) /* if NOPs */
{ if(!mode) /* compliment match mode */
{ for(i = 0; i < tz; i++) /* over the full template size */
{ if(soup[ad(o + i)][ce->c.tr].inst
+ soup[ad(b + i)][ce->c.tr].inst != 1)
{ match = 0; break; }
}
}
else /* direct match mode */
{ for(i = 0; i < tz; i++) /* over the full template size */
{ if(soup[ad(o + i)][ce->c.tr].inst
- soup[ad(b + i)][ce->c.tr].inst != 0)
{ match = 0; break; }
}
}
if(match)
{ b += flaw(ci);
adrt = ad(b + tz);
goto finish;
}
} /* increment search pointers, backward and forward */
if(db) { b--; b = ad(b); } if(df) { f++; f = ad(f); } l++;
if(l > Search_limit) /* if we exceed the search limit abort */
{ adrt = -1;
goto finish;
}
}
finish:
if(1 && WatchTem) tgl = (sl + ce->d.gli.si)->g + ce->d.gli.gi;
if(1 && WatchTem && adrt >= 0 && !ce->d.flaw && !ce->d.mut &&
ce->mm.p <= ce->c.ip && ce->c.ip < (ce->mm.p + ce->mm.s) &&
IsBit(tgl->bits,0))
GenExTemp(ad(adrt - tz), ci, tz);
return adrt; /* address of instruction following target template */
}
Ind btemplate(f, b, tz, dir, mode, ci) /*search in specified direction for */
/* binary template return address, returns address of instruction */
/* following target template, i.e., target + tz */
/* NOTE: ce->c.ip must point to the instruction (agent) being executed */
Ind f; /* starting address for forward search */
Ind b; /* starting address for backward search */
I32s tz; /* template size */
I8s dir; /* direction of search, f = forward, b = backward, o = out */
I8s mode; /* match mode: 0 = complement, 1 = direct */
I32s ci; /* which cell */
{ Ind o, l = 1, adrt;
I32s i = 0, match;
I8s df, db;
Pgl tgl;
Pcells ce = cells + ci;
if((tz < MinTemplSize) || (tz > SoupSize))
{ adrt = -1;
goto finish;
}
if(dir == 'o') df = db = 1; /* both directions */
if(dir == 'f') { df = 1; db = 0; } /* forward only */
if(dir == 'b') { df = 0; db = 1; } /* backwards only */
o = ad(ce->c.ip + 1);
while(1)
{ match = 1;
if(df) /* if direction forwards */
{ if(!mode) /* compliment match mode */
{ for(i = 0; i < tz; i++) /* for full template size */
{ if((soup[ad(o + i)][ce->c.tr].inst
^ soup[ad(f + i)][ce->c.tr].inst) == 31)
{ match = 0; break; }
}
}
else /* direct match mode */
{ for(i = 0; i < tz; i++) /* for full template size */
{ if(soup[ad(o + i)][ce->c.tr].inst
== soup[ad(f + i)][ce->c.tr].inst)
{ match = 0; break; }
}
}
if(match)
{ f += flaw(ci);
adrt = ad(f + tz);
goto finish;
}
}
if(db) /* if direction backwards */
{ match = 1;
if(!mode) /* compliment match mode */
{ for(i = 0; i < tz; i++) /* for full template size */
{ if((soup[ad(o + i)][ce->c.tr].inst
^ soup[ad(b + i)][ce->c.tr].inst) == 31)
{ match = 0; break; }
}
}
else /* direct match mode */
{ for(i = 0; i < tz; i++) /* for full template size */
{ if(soup[ad(o + i)][ce->c.tr].inst
== soup[ad(b + i)][ce->c.tr].inst)
{ match = 0; break; }
}
}
if(match)
{ b += flaw(ci);
adrt = ad(b + tz);
goto finish;
}
} /* increment search pointers, backward and forward */
if(db) { b--; b = ad(b); } if(df) { f++; f = ad(f); } l++;
if(l > Search_limit)
{ adrt = -1;
goto finish;
}
}
finish:
if(1 && WatchTem) tgl = (sl + ce->d.gli.si)->g + ce->d.gli.gi;
if(1 && WatchTem && adrt >= 0 && !ce->d.flaw && !ce->d.mut &&
ce->mm.p <= ce->c.ip && ce->c.ip < (ce->mm.p + ce->mm.s) &&
IsBit(tgl->bits,0))
GenExTemp(ad(adrt - tz), ci, tz);
return adrt; /* address of instruction following target template */
}