USG_PG3/usr/source/lil/sim.c
#include "common"
binop(p1, p2, p3) struct at *p1, *p2, *p3;
{struct at *pl, *pr, *pt;
int k, op;
if (skip) return;
pl = ref(p1);
op = (pt = ref(p2))->value;
pr = ref(p3);
if (atime || test(pt, CRSF) && !test(p1, PUBF))
/*
during atime:
DCLF we're defining something
PUBF this is what we're defining
outside atime:
DCLF we've defined something
PUBF we've generated machine code
*/
{switch (op) {
case NOP: return;
case GETSNOT:
case GETSMI:
case GETS: set(p1, PUBF | DCLF, TRUE);
if (test(p1, DEFF) || op != GETS && pr->bias) break;
switch (op) {
case GETSNOT: setvb(p3, ~pr->value, 0); break;
case GETSMI: setvb(p3, -pr->value, 0); break;
case GETS: setvb(p3, pr->value, pr->bias); break;
}
define(p1->value, p3->flags & ATTR, p3->type,
p3->value, p3->bias);
return;
case GOESTO: set(p1, DCLF, TRUE);
if (test(p3, DEFF) || !test(pl, DEFF)) break;
define(p3->value, p1->flags & ATTR, p1->type,
pl->value, pl->bias);
return;
case SIZE: set(p1, DCLF, TRUE);
if (con(p3) == NULL) break;
p1->size = pr->value;
return;
default: if (!test(p1, PUBF))
{setvb(p1, pl->value, pl->bias);
set(p1, DCLF, FALSE);
pl = p1; }
switch (op) {
case PLUS: if (pl->bias && pr->bias) break;
pl->value =+ pr->value;
pl->bias =+ pr->bias;
return;
case MINUS: if (pl->bias != pr->bias && pr->bias) break;
pl->value =- pr->value;
pl->bias =- pr->bias;
return;
default: if (pl->bias || pr->bias) break;
switch (op) {
case NOT: pl->value = ~(pl->value ^ pr->value);
return;
case OR: pl->value =| pr->value; return;
case AND: pl->value =& pr->value; return;
case ANDNOT: pl->value =& ~pr->value; return;
case XOR: pl->value =^ pr->value; return;
case SHIFT: pl->value =<< pr->value; return;
case TIMES: pl->value =* pr->value; return;
case DIVIDE: pl->value =/ pr->value; return;
case CAT: pl->value = pl->value & 0377
| (pr->value << 8);
p1->type = CON; return;
}
}
}
error("%s %s %s illegal at compile time", s(p1), s(p2), s(p3));
return; }
else {
set(p1, PUBF, TRUE);
set(p1, BCCF, FALSE);
switch (op) {
case NOP: return;
case GOESTO: pt = p1; p1 = p3; p3 = pt;
pt = pl; pl = pr; pr = pt;
case GETSNOT:
case GETSMI:
case GETS: if (con(p3) && pr->value == 0 && op != GETSNOT)
geninst(byte(p1, NULL) + 005000, NULL, p1);
else if(p1->type == KOND && op != GETSMI &&
p3->type == KOND &&
((k = pr->value) == TRUE || k == FALSE))
{k = (k ^ (op == GETSNOT)) << 4;
switch (pl->value) {
case N: gen(000250 ^ k, 0); return;
case Z: gen(000244 ^ k, 0); return;
case V: gen(000242 ^ k, 0); return;
case C: gen(000241 ^ k, 0); return;
}
}
else if (p3->type == KOND && pr->value == N &&
op == GETS && !test(p1, BYTF))
geninst(006700, NULL, p1);
else if (compat(p1, p3) &&
(op == GETSNOT || op == GETSMI) &&
p1->type == p3->type &&
pl->value == pr->value &&
pl->bias == pr->bias)
geninst(byte(p1, NULL) + (op == GETSNOT ?
005100 : 005400), NULL, p1);
else if (compat(p1, p3) &&
(op == GETS || op == GOESTO))
geninst(byte(p1, p3) + 010000, p3, p1);
else break;
return;
case PLUS: if (con(p3) && pr->value == 1)
geninst(byte(p1) + 005200, NULL, p1);
else if (p3->type == KOND && pr->value == C)
geninst(byte(p1, NULL) + 005500, NULL, p1);
else if (!byte(p1, p3))
geninst(060000, p3, p1);
else break;
return;
case MINUS: if (con(p3) && pr->value == 1)
geninst(byte(p1) + 005300, NULL, p1);
else if (p3->type == KOND && pr->value == C)
geninst(byte(p1, NULL) + 005600, NULL, p1);
else if (!byte(p1, p3))
geninst(0160000, p3, p1);
else break;
return;
case OR: if (!compat(p1, p3)) break;
geninst(byte(p1, p3) + 050000, p3, p1); return;
case AND: if (con(p3) == NULL) break;
setvb(p3, ~pr->value, 0);
case ANDNOT: if (!compat(p1, p3)) break;
geninst(byte(p1, p3) + 040000, p3, p1);
return;
case XOR: if (byte(p1, p3) || p3->type != REG) break;
geninst(074000, p3, p1);
return;
case ROTATE: if (con(p3) == NULL) break;
if (pr->value == 1)
geninst(byte(p1, NULL) + 006100, NULL, p1);
else if (pr->value == -1)
geninst(byte(p1, NULL) + 006000, NULL, p1);
else break;
return;
case SROTATE: if (con(p3) == NULL) break;
if (pr->value == 8 && !test(p1, BYTF))
{set(p1, BCCF, TRUE);
geninst(000300, NULL, p1); }
else if (reg(p1) && pl->value & 1 &&
-16 <= pr->value && pr->value <= 0)
geninst(073000 + (pr->value & 077), p1, NULL);
else break;
return;
case SHIFT: if (con(p3) == NULL) break;
if (pr->value == 1)
geninst(byte(p1, NULL) + 006300, NULL, p1);
else if (pr->value == -1)
geninst(byte(p1, NULL) + 006200, NULL, p1);
else if (reg(p1)) geninst(072000 + (pr->value & 077),
p1, NULL);
else break;
return;
case DSHIFT: if (con(p3) == NULL || reg(p1) == NULL) break;
geninst(073000 + (pr->value & 077), p1, NULL);
return;
case TIMES: if (byte(p1, p3) || reg(p1) == NULL) break;
geninst(070000, p1, p3); return;
case DIVIDE: if (byte(p1, p3) || reg(p1) == NULL) break;
geninst(071000, p1, p3); return;
case TEST: if (!compat(p1, p3)) break;
if (con(p3) && pr->value == 0)
geninst(byte(p1, NULL) + 005700, NULL, p1);
else geninst(byte(p1, p3) + 020000, p1, p3);
return;
case TESTAND: if (!compat(p1, p3)) break;
geninst(byte(p1, p3) + 030000, p3, p1);
return;
case JSR: if (byte(p1) || reg(p3) == NULL) break;
geninst(004037, p3, p1);
return;
}
error("%s %s %s illegal", s(p1), s(p2), s(p3));
}
}