#include <u.h>
#include <libc.h>
#include <ctype.h>
#include <bio.h>
#include <avl.h>
#include "mix.h"
#include "y.tab.h"
struct Resvd {
char *name;
long lex;
int c;
int f;
} res[] = {
{ "NOP", LOP, 0, F(0, 5) },
{ "ADD", LOP, 1, F(0, 5) },
{ "FADD", LOP, 1, 6 },
{ "SUB", LOP, 2, F(0, 5) },
{ "FSUB", LOP, 2, 6 },
{ "MUL", LOP, 3, F(0, 5) },
{ "FMUL", LOP, 3, 6 },
{ "DIV", LOP, 4, F(0, 5) },
{ "FDIV", LOP, 4, 6 },
{ "NUM", LOP, 5, 0 },
{ "CHAR", LOP, 5, 1 },
{ "HLT", LOP, 5, 2 },
{ "SLA", LOP, 6, 0 },
{ "SRA", LOP, 6, 1 },
{ "SLAX", LOP, 6, 2 },
{ "SRAX", LOP, 6, 3 },
{ "SLC", LOP, 6, 4 },
{ "SRC", LOP, 6, 5 },
{ "MOVE", LOP, 7, 1 },
{ "LDA", LOP, 8, F(0, 5) },
{ "LD1", LOP, 9, F(0, 5) },
{ "LD2", LOP, 10, F(0, 5) },
{ "LD3", LOP, 11, F(0, 5) },
{ "LD4", LOP, 12, F(0, 5) },
{ "LD5", LOP, 13, F(0, 5) },
{ "LD6", LOP, 14, F(0, 5) },
{ "LDX", LOP, 15, F(0, 5) },
{ "LDAN", LOP, 16, F(0, 5) },
{ "LD1N", LOP, 17, F(0, 5) },
{ "LD2N", LOP, 18, F(0, 5) },
{ "LD3N", LOP, 19, F(0, 5) },
{ "LD4N", LOP, 20, F(0, 5) },
{ "LD5N", LOP, 21, F(0, 5) },
{ "LD6N", LOP, 22, F(0, 5) },
{ "LDXN", LOP, 23, F(0, 5) },
{ "STA", LOP, 24, F(0, 5) },
{ "ST1", LOP, 25, F(0, 5) },
{ "ST2", LOP, 26, F(0, 5) },
{ "ST3", LOP, 27, F(0, 5) },
{ "ST4", LOP, 28, F(0, 5) },
{ "ST5", LOP, 29, F(0, 5) },
{ "ST6", LOP, 30, F(0, 5) },
{ "STX", LOP, 31, F(0, 5) },
{ "STJ", LOP, 32, F(0, 2) },
{ "STZ", LOP, 33, F(0, 5) },
{ "JBUS", LOP, 34, 0 },
{ "IOC", LOP, 35, 0 },
{ "IN", LOP, 36, 0 },
{ "OUT", LOP, 37, 0 },
{ "JRED", LOP, 38, 0 },
{ "JMP", LOP, 39, 0 },
{ "JSJ", LOP, 39, 1 },
{ "JOV", LOP, 39, 2 },
{ "JNOV", LOP, 39, 3 },
{ "JL", LOP, 39, 4 },
{ "JE", LOP, 39, 5 },
{ "JG", LOP, 39, 6 },
{ "JGE", LOP, 39, 7 },
{ "JNE", LOP, 39, 8 },
{ "JLE", LOP, 39, 9 },
{ "JAN", LOP, 40, 0 },
{ "JAZ", LOP, 40, 1 },
{ "JAP", LOP, 40, 2 },
{ "JANN", LOP, 40, 3 },
{ "JANZ", LOP, 40, 4 },
{ "JANP", LOP, 40, 5 },
{ "J1N", LOP, 41, 0 },
{ "J1Z", LOP, 41, 1 },
{ "J1P", LOP, 41, 2 },
{ "J1NN", LOP, 41, 3 },
{ "J1NZ", LOP, 41, 4 },
{ "J1NP", LOP, 41, 5 },
{ "J2N", LOP, 42, 0 },
{ "J2Z", LOP, 42, 1 },
{ "J2P", LOP, 42, 2 },
{ "J2NN", LOP, 42, 3 },
{ "J2NZ", LOP, 42, 4 },
{ "J2NP", LOP, 42, 5 },
{ "J3N", LOP, 43, 0 },
{ "J3Z", LOP, 43, 1 },
{ "J3P", LOP, 43, 2 },
{ "J3NN", LOP, 43, 3 },
{ "J3NZ", LOP, 43, 4 },
{ "J3NP", LOP, 43, 5 },
{ "J4N", LOP, 44, 0 },
{ "J4Z", LOP, 44, 1 },
{ "J4P", LOP, 44, 2 },
{ "J4NN", LOP, 44, 3 },
{ "J4NZ", LOP, 44, 4 },
{ "J4NP", LOP, 44, 5 },
{ "J5N", LOP, 45, 0 },
{ "J5Z", LOP, 45, 1 },
{ "J5P", LOP, 45, 2 },
{ "J5NN", LOP, 45, 3 },
{ "J5NZ", LOP, 45, 4 },
{ "J5NP", LOP, 45, 5 },
{ "J6N", LOP, 46, 0 },
{ "J6Z", LOP, 46, 1 },
{ "J6P", LOP, 46, 2 },
{ "J6NN", LOP, 46, 3 },
{ "J6NZ", LOP, 46, 4 },
{ "J6NP", LOP, 46, 5 },
{ "JXN", LOP, 47, 0 },
{ "JXZ", LOP, 47, 1 },
{ "JXP", LOP, 47, 2 },
{ "JXNN", LOP, 47, 3 },
{ "JXNZ", LOP, 47, 4 },
{ "JXNP", LOP, 47, 5 },
{ "INCA", LOP, 48, 0 },
{ "DECA", LOP, 48, 1 },
{ "ENTA", LOP, 48, 2 },
{ "ENNA", LOP, 48, 3 },
{ "INC1", LOP, 49, 0 },
{ "DEC1", LOP, 49, 1 },
{ "ENT1", LOP, 49, 2 },
{ "ENN1", LOP, 49, 3 },
{ "INC2", LOP, 50, 0 },
{ "DEC2", LOP, 50, 1 },
{ "ENT2", LOP, 50, 2 },
{ "ENN2", LOP, 50, 3 },
{ "INC3", LOP, 51, 0 },
{ "DEC3", LOP, 51, 1 },
{ "ENT3", LOP, 51, 2 },
{ "ENN3", LOP, 51, 3 },
{ "INC4", LOP, 52, 0 },
{ "DEC4", LOP, 52, 1 },
{ "ENT4", LOP, 52, 2 },
{ "ENN4", LOP, 52, 3 },
{ "INC5", LOP, 53, 0 },
{ "DEC5", LOP, 53, 1 },
{ "ENT5", LOP, 53, 2 },
{ "ENN5", LOP, 53, 3 },
{ "INC6", LOP, 54, 0 },
{ "DEC6", LOP, 54, 1 },
{ "ENT6", LOP, 54, 2 },
{ "ENN6", LOP, 54, 3 },
{ "INCX", LOP, 55, 0 },
{ "DECX", LOP, 55, 1 },
{ "ENTX", LOP, 55, 2 },
{ "ENNX", LOP, 55, 3 },
{ "CMPA", LOP, 56, F(0, 5) },
{ "FCMP", LOP, 56, 6 },
{ "CMP1", LOP, 57, F(0, 5) },
{ "CMP2", LOP, 58, F(0, 5) },
{ "CMP3", LOP, 59, F(0, 5) },
{ "CMP4", LOP, 60, F(0, 5) },
{ "CMP5", LOP, 61, F(0, 5) },
{ "CMP6", LOP, 62, F(0, 5) },
{ "CMPX", LOP, 63, F(0, 5) },
{ "EQU", LEQU, -1, -1 },
{ "ORIG", LORIG, -1, -1 },
{ "CON", LCON, -1, -1 },
{ "ALF", LALF, -1, -1 },
{ "END", LEND, -1, -1 },
{ "0H", LHERE, 0, -1 },
{ "1H", LHERE, 1, -1 },
{ "2H", LHERE, 2, -1 },
{ "3H", LHERE, 3, -1 },
{ "4H", LHERE, 4, -1 },
{ "5H", LHERE, 5, -1 },
{ "6H", LHERE, 6, -1 },
{ "7H", LHERE, 7, -1 },
{ "8H", LHERE, 8, -1 },
{ "9H", LHERE, 9, -1 },
{ "0B", LBACK, 0, -1 },
{ "1B", LBACK, 1, -1 },
{ "2B", LBACK, 2, -1 },
{ "3B", LBACK, 3, -1 },
{ "4B", LBACK, 4, -1 },
{ "5B", LBACK, 5, -1 },
{ "6B", LBACK, 6, -1 },
{ "7B", LBACK, 7, -1 },
{ "8B", LBACK, 8, -1 },
{ "9B", LBACK, 9, -1 },
{ "0F", LFORW, 0, -1 },
{ "1F", LFORW, 1, -1 },
{ "2F", LFORW, 2, -1 },
{ "3F", LFORW, 3, -1 },
{ "4F", LFORW, 4, -1 },
{ "5F", LFORW, 5, -1 },
{ "6F", LFORW, 6, -1 },
{ "7F", LFORW, 7, -1 },
{ "8F", LFORW, 8, -1 },
{ "9F", LFORW, 9, -1 },
};
int mask[] = {
MASK1,
MASK2,
MASK3,
MASK4,
MASK5
};
int symcmp(Avl*, Avl*);
Sym *sym(char*);
void
main(int argc, char **argv)
{
int go;
char **ap;
go = 0;
ARGBEGIN {
case 'g': go++; break;
} ARGEND
cinit();
sinit();
fmtinstall('I', Ifmt);
vmstart = -1;
for(ap = argv; ap < argv+argc; ap++)
asmfile(*ap);
repl(go);
exits(nil);
}
void
sinit(void)
{
struct Resvd *r;
Sym *s;
syms = avlcreate(symcmp);
for(r = res; r < res + nelem(res); r++) {
s = sym(r->name);
s->lex = r->lex;
s->opc = r->c;
s->f = r->f;
avlinsert(syms, s);
}
}
int
asmfile(char *file)
{
int fd;
if((fd = open(file, OREAD)) == -1)
return -1;
Binit(&bin, fd, OREAD);
line = 1;
filename = file;
if(setjmp(errjmp) == 0)
yyparse();
Bterm(&bin);
close(fd);
return 0;
}
int
unpack(u32int inst, int *apart, int *ipart, int *fpart)
{
int opc;
opc = V(inst, F(5, 5));
*fpart = V(inst, F(4, 4));
*ipart = V(inst, F(3, 3));
*apart = V(inst, F(0, 2));
return opc;
}
int
Ifmt(Fmt *f)
{
u32int inst;
int i, apart, ipart, fpart, opc, a, b;
inst = va_arg(f->args, u32int);
opc = unpack(inst, &apart, &ipart, &fpart);
for(i = 0; i < nelem(res); i++) {
if(res[i].c == opc)
break;
}
UNF(a, b, fpart);
if(res[i+1].c != opc || opc == 56)
return fmtprint(f, "%s\t%d,%d(%d | %d:%d)", res[i].name, apart, ipart, fpart, a, b);
while(res[i].c == opc && i < nelem(res)) {
if(res[i].f == fpart)
return fmtprint(f, "%s\t%d,%d(%d | %d:%d)", res[i].name, apart, ipart, fpart, a, b);
i++;
}
return fmtprint(f, "%d\t%d,%d(%d | %d:%d)", opc, apart, ipart, fpart, a, b);
}
Rune
getr(void)
{
static int bol = 1;
Rune r;
r = Bgetrune(&bin);
switch(r) {
case '*':
if(!bol)
break;
case '#':
skipto('\n');
case '\n':
line++;
bol = 1;
return '\n';
}
bol = 0;
return r;
}
void
ungetr(Rune r)
{
if(r == '\n')
line--;
Bungetrune(&bin);
}
long
yylex(void)
{
static Rune buf[11];
Rune r, *bp, *ep;
static char cbuf[100];
int isnum;
if(yydone)
return -1;
Loop:
r = getr();
switch(r) {
case Beof:
return -1;
case '\t':
case ' ':
goto Loop;
case '\n': case '*': case '+':
case '-': case ':': case ',':
case '(': case ')': case '=':
return r;
case '/':
r = getr();
if(r == '/')
return LSS;
else
ungetr(r);
return '/';
case '"':
for(bp = buf; bp < buf+5; bp++) {
*bp = getr();
}
if(getr() != '"')
yyerror("Bad string literal\n");
yylval.rbuf = buf;
return LSTR;
}
bp = buf;
ep = buf+nelem(buf)-1;
isnum = 1;
for(;;) {
if(runetomix(r) == -1)
yyerror("Invalid character %C", r);
if(bp == ep)
yyerror("Symbol or number too long");
*bp++ = r;
if(isnum && (r >= Runeself || !isdigit(r)))
isnum = 0;
switch(r = getr()) {
case Beof: case '\t': case '\n':
case '+': case '-': case '*':
case ':': case ',': case '(':
case ')': case '=': case ' ':
case '/': case '#':
ungetr(r);
*bp = '\0';
goto End;
}
}
End:
seprint(cbuf, cbuf+100, "%S", buf);
if(isnum) {
yylval.lval = strtol(cbuf, nil, 10);
return LNUM;
}
yylval.sym = sym(cbuf);
return yylval.sym->lex;
}
Sym*
getsym(char *name)
{
Sym *s;
s = emallocz(sizeof(*s) + strlen(name));
strcpy(s->nbuf, name);
s->name = s->nbuf;
s->lex = LSYMREF;
return s;
}
Sym*
sym(char *name)
{
Sym *s, l;
l.name = name;
s = (Sym*)avllookup(syms, &l, 0);
if(s != nil)
return s;
s = getsym(name);
avlinsert(syms, s);
return s;
}
int
symcmp(Avl *a, Avl *b)
{
Sym *sa, *sb;
sa = (Sym*)a;
sb = (Sym*)b;
return strcmp(sa->name, sb->name);
}
void
skipto(char c)
{
Rune r;
for(;;) {
r = Bgetrune(&bin);
if(r != c && r != Beof)
continue;
return;
}
}
int
mval(u32int a, int s, u32int m)
{
int sign, val;
sign = a >> 31;
val = a>>s*BITS & m;
if(sign)
return -val;
return val;
}
int
V(u32int w, int f)
{
int a, b, d;
if(f == 0)
return 0;
UNF(a, b, f);
if(a > 0)
w &= ~SIGNB;
else
a++;
d = b - a;
if(a > 5 || b > 5 || d < 0 || d > 4)
vmerror("Invalid fpart %d", f);
return mval(w, 5-b, mask[d]);
}
int
M(int a, int i)
{
int off, r;
r = ri[i] & ~(MASK3<<2*BITS);
off = i == 0 ? 0 : mval(r, 0, MASK2);
return a + off;
}
void mixfadd(int){}
void
mixadd(int m, int f)
{
int rval;
rval = mval(ra, 0, MASK5);
rval += V(cells[m], f);
ra = rval < 0 ? -rval|SIGNB : rval;
if(ra & OVERB) {
ra &= ~OVERB;
ot = 1;
}
}
void mixfsub(int){}
void
mixsub(int m, int f)
{
int rval;
rval = mval(ra, 0, MASK5);
rval -= V(cells[m], f);
ra = rval < 0 ? -rval|SIGNB : rval;
if(ra & OVERB) {
ra &= ~OVERB;
ot = 1;
}
}
void mixfmul(int){}
void
mixmul(int m, int f)
{
vlong rval;
int signb;
rval = mval(ra, 0, MASK5);
rval *= V(cells[m], f);
if(rval < 0) {
rval = -rval;
signb = SIGNB;
} else
signb = 0;
ra = rval>>5*BITS & MASK5 | signb;
rx = rval & MASK5 | signb;
}
void mixfdiv(int){}
void
mixdiv(int m, int f)
{
vlong rax, quot;
u32int xsignb, asignb;
int rem, v;
v = V(cells[m], f);
if(v == 0) {
ot = 1;
return;
}
rax = ra & MASK5;
rax <<= 5 * BITS;
rax |= rx & MASK5;
if(ra >> 31)
rax = -rax;
quot = rax / v;
rem = rax % v;
if(quot < 0) {
quot = -quot;
asignb = SIGNB;
} else
asignb = 0;
if(rem < 0) {
rem = -rem;
xsignb = SIGNB;
} else
xsignb = 0;
if(quot & ~MASK5)
ot = 1;
ra = quot & MASK5 | asignb;
rx = rem & MASK5 | xsignb;
}
void
mixnum(void)
{
int i, b;
u32int n;
n = 0;
for(i = 0; i < 5; i++) {
b = ra>>(4-i)*BITS & MASK1;
b %= 10;
n = 10*n + b;
}
for(i = 0; i < 5; i++) {
b = rx>>(4-i)*BITS & MASK1;
b %= 10;
n = 10*n + b;
}
ra &= ~MASK5;
ra |= n & MASK5;
}
void
mixchar(void)
{
int i;
u32int a, val;
val = ra & ~SIGNB;
for(i = 0; i < 5; i++) {
a = val % 10;
a += 30;
rx &= ~(MASK1 << i*BITS);
rx |= a << i*BITS;
val /= 10;
}
for(i = 0; i < 5; i++) {
a = val % 10;
a += 30;
ra &= ~(MASK1 << i*BITS);
ra |= a << i*BITS;
val /= 10;
}
}
void
mixslra(int m, int left)
{
u32int val;
if(m < 0)
vmerror("Bad shift A %d", m);
if(m > 4) {
ra &= ~MASK5;
return;
}
val = ra & MASK5;
ra &= ~MASK5;
if(left)
val <<= m * BITS;
else
val >>= m * BITS;
ra |= val & MASK5;
}
void
mixslrax(int m, int left)
{
u64int rax;
if(m < 0)
vmerror("Bad shift AX %d", m);
if(m > 9) {
ra &= ~MASK5;
rx &= ~MASK5;
return;
}
rax = ra & MASK5;
ra &= ~MASK5;
rax <<= 5 * BITS;
rax |= rx & MASK5;
rx &= ~MASK5;
if(left)
rax <<= m;
else
rax >>= m;
rx |= rax & MASK5;
ra |= rax>>5*BITS & MASK5;
}
void
mixslc(int m)
{
u64int rax, s;
if(m < 0)
vmerror("Bad shift SLC %d", m);
m %= 10;
rax = ra & MASK5;
ra &= ~MASK5;
rax <<= 5 * BITS;
rax |= rx & MASK5;
rx &= ~MASK5;
s = rax & mask[m]<<10-m;
rax <<= m;
rax &= ~mask[m];
rax |= s;
rx |= rax & MASK5;
ra |= rax>>5*BITS & MASK5;
}
void
mixsrc(int m)
{
u64int rax, s;
if(m < 0)
vmerror("Bad shift SRC %d", m);
m %= 10;
rax = ra & MASK5;
ra &= ~MASK5;
rax <<= 5 * BITS;
rax |= rx & MASK5;
rx &= ~MASK5;
s = rax & mask[m];
rax >>= m;
rax &= ~mask[m] << 10-m;
rax |= s<<10-m;
rx |= rax & MASK5;
ra |= rax>>5*BITS & MASK5;
}
void
mixmove(int s, int f)
{
int d;
if(f == 0)
return;
d = mval(ri[1], 0, MASK2);
if(d < 0 || d > 4000)
vmerror("Bad address MOVE %d", d);
memcpy(cells+d, cells+s, f*sizeof(u32int));
d += f;
d &= MASK2;
ri[1] = d < 0 ? -d|SIGNB : d;
}
u32int
mixld(u32int v, int f)
{
u32int w;
int a, b, d;
if(f == 5)
return v;
UNF(a, b, f);
w = 0;
if(a == 0) {
if(v >> 31)
w = SIGNB;
if(b == 0)
return w;
a++;
}
d = b - a;
if(a > 5 || b > 5 || d < 0 || d > 4)
vmerror("Bad fpart (%d:%d)", a, b);
v &= mask[d] << (5-b) * BITS;
v >>= (5-b) * BITS;
return w | v;
}
u32int
mixst(u32int w, u32int v, int f)
{
int a, b, d;
if(f == 5)
return v;
UNF(a, b, f);
if(a == 0) {
w = v>>31 ? w|SIGNB : w&~SIGNB;
if(b == 0)
return w;
a++;
}
d = b - a;
if(a > 5 || b > 5 || d < 0 || d > 4)
vmerror("Bad fpart (%d:%d)", a, b);
v &= mask[d];
v <<= (5-b) * BITS;
w &= ~(mask[d] << (5-b)*BITS);
return w | v;
}
int
mixjbus(int /*m*/, int /*f*/, int ip)
{
return ip+1;
}
void
mixioc(int, int f)
{
switch(f) {
case 18:
case 19:
print("\n");
break;
}
}
void mixin(int, int){}
void
mixout(int m, int f)
{
switch(f) {
case 18:
mixprint(m, 24);
break;
case 19:
mixprint(m, 14);
break;
}
}
int
mixjred(int m, int /*f*/, int /*ip*/)
{
return m;
}
int
mixjmp(int m, int ip)
{
ri[0] = ip+1 & MASK2;
return m;
}
int
mixjov(int m, int ip)
{
if(ot) {
ot = 0;
ri[0] = ip+1 & MASK2;
return m;
}
return ip + 1;
}
int
mixjnov(int m, int ip)
{
if(ot) {
ot = 0;
return ip + 1;
}
ri[0] = ip+1 & MASK2;
return m;
}
int
mixjc(int m, int ip, int c1, int c2)
{
if(c1 || c2) {
ri[0] = ip+1 & MASK2;
return m;
}
return ip + 1;
}
int
mixjaxic(int m, int ip, u32int r, u32int msk, int f)
{
int v, c;
v = mval(r, 0, msk);
switch(f) {
default: vmerror("Bad instruction JA condition: %d", f);
case 0: c = v < 0; break;
case 1: c = v == 0; break;
case 2: c = v > 0; break;
case 3: c = v >= 0; break;
case 4: c = v != 0; break;
case 5: c = v <= 0; break;
}
if(c) {
ri[0] = ip+1 & MASK2;
return m;
}
return ip + 1;
}
void
mixinc(int m, u32int *r)
{
int v;
v = mval(*r, 0, MASK5);
v += m;
*r = v < 0 ? -v|SIGNB : v;
}
void mixfcmp(void){}
void
mixcmp(int m, int f, u32int r)
{
int v1, v2;
ce = cg = cl = 0;
v1 = V(r, f);
v2 = V(cells[m], f);
if(v1 < v2)
cl = 1;
else if(v1 > v2)
cg = 1;
else
ce = 1;
}
int
mixvm(int ip, int once)
{
u32int r;
int a, i, f, c, m, inst;
curpc = ip;
for (;;) {
if(curpc < 0 || curpc > 4000)
vmerror("Bad PC %d", curpc);
if(bp[curpc] && !once)
return curpc;
inst = cells[curpc];
a = V(inst, F(0, 2));
i = V(inst, F(3, 3));
f = V(inst, F(4, 4));
c = V(inst, F(5, 5));
m = M(a, i);
switch(c) {
default:
fprint(2, "Bad op!\n");
exits("error");
case 0:
break;
case 1:
if(f == 6)
mixfadd(inst);
else
mixadd(m, f);
break;
case 2:
if(f == 6)
mixfsub(inst);
else
mixsub(m, f);
break;
case 3:
if(f == 6)
mixfmul(inst);
else
mixmul(m, f);
break;
case 4:
if(f == 6)
mixfdiv(inst);
else
mixdiv(m, f);
break;
case 5:
switch(f) {
default:
vmerror("Bad instruction NUM or CHAR: %d", f);
case 0:
mixnum();
break;
case 1:
mixchar();
break;
case 2:
return -1; /* HLT */
}
break;
case 6:
switch(f) {
default: vmerror("Bad instruction shift: %d", f);
case 0: mixslra(m, 1); break;
case 1: mixslra(m, 0); break;
case 2: mixslrax(m, 1); break;
case 4: mixslrax(m, 0); break;
case 5: mixslc(m); break;
case 6: mixsrc(m); break;
}
break;
case 7:
mixmove(m, f);
break;
case 8:
ra = mixld(cells[m], f);
break;
case 9: case 10: case 11:
case 12: case 13: case 14:
ri[c-8] = mixld(cells[m], f);
break;
case 15:
rx = mixld(cells[m], f);
break;
case 16:
ra = mixld(cells[m], f) ^ SIGNB;
break;
case 17: case 18: case 19:
case 20: case 21: case 22:
ri[c-16] = mixld(cells[m], f) ^ SIGNB;
break;
case 23:
rx = mixld(cells[m], f) ^ SIGNB;
break;
case 24:
cells[m] = mixst(cells[m], ra, f);
break;
case 25: case 26: case 27:
case 28: case 29: case 30:
r = ri[c-24] & ~(MASK3 << 2*BITS);
cells[m] = mixst(cells[m], r, f);
break;
case 31:
cells[m] = mixst(cells[m], rx, f);
break;
case 32:
r = ri[0] & ~(MASK3 << 2*BITS);
cells[m] = mixst(cells[m], r, f);
break;
case 33:
cells[m] = mixst(cells[m], 0, f);
break;
case 34:
curpc = mixjbus(m, f, curpc);
goto Again;
case 35:
mixioc(m, f);
break;
case 36:
mixin(m, f);
break;
case 37:
mixout(m, f);
break;
case 38:
curpc = mixjred(m, f, curpc);
break;
case 39:
switch(f) {
default: vmerror("Bad jmp instruction: %d", f);
case 0: curpc = mixjmp(m, curpc); break;
case 1: curpc = m; break; /* JSJ */
case 2: curpc = mixjov(m, curpc); break;
case 3: curpc = mixjnov(m, curpc); break;
case 4: curpc = mixjc(m, curpc, cl, 0); break;
case 5: curpc = mixjc(m, curpc, ce, 0); break;
case 6: curpc = mixjc(m, curpc, cg, 0); break;
case 7: curpc = mixjc(m, curpc, cg, ce); break;
case 8: curpc = mixjc(m, curpc, cl, cg); break;
case 9: curpc = mixjc(m, curpc, cl, ce); break;
}
goto Again;
case 40:
curpc = mixjaxic(m, curpc, ra, MASK5, f);
goto Again;
case 41: case 42: case 43:
case 44: case 45: case 46:
curpc = mixjaxic(m, curpc, ri[c-40], MASK2, f);
goto Again;
case 47:
curpc = mixjaxic(m, curpc, rx, MASK5, f);
goto Again;
case 48:
switch(f) {
case 0: mixinc(m, &ra); break;
case 1: mixinc(-m, &ra); break;
case 2:
ra = m == 0
? inst & SIGNB
: m < 0 ? -m|SIGNB : m;
break; /* ENTA */
case 3:
ra = m == 0
? ~inst & SIGNB
: m > 0 ? m|SIGNB : -m;
break; /* ENNA */
}
break;
case 49: case 50: case 51:
case 52: case 53: case 54:
switch(f) {
case 0: mixinc(m, ri+(c-48)); break;
case 1: mixinc(-m, ri+(c-48)); break;
case 2:
ri[c-48] = m == 0
? inst & SIGNB
: m < 0 ? -m|SIGNB : m;
break; /* ENT[1-6] */
case 3:
ri[c-48] = m == 0
? ~inst & SIGNB
: m > 0 ? m|SIGNB : -m;
break; /* ENN[1-6] */
}
break;
case 55:
switch(f) {
case 0: mixinc(m, &rx); break;
case 1: mixinc(-m, &rx); break;
case 2: rx = m == 0
? inst & SIGNB
: m < 0 ? -m|SIGNB : m;
break; /* ENTX */
case 3: rx = m == 0
? ~inst & SIGNB
: m > 0 ? m|SIGNB : -m;
break; /* ENNX */
}
break;
case 56:
if(f == 6)
mixfcmp();
else
mixcmp(m, f, ra);
break;
case 57: case 58: case 59:
case 60: case 61: case 62:
mixcmp(m, f, ri[c-56] & ~(MASK3<<2*BITS));
break;
case 63:
mixcmp(m, f, rx);
break;
}
curpc++;
Again:
if(once)
return curpc;
}
}