#define EXTERN extern
#include "mc.h"
int arg_offset = 2;
int int_size = 2;
int disp_offset = 0;
int endian = 1;
code_init()
{
}
gexpr(e1)
int e1;
{int e2,e3;
if (chk) return;
e2 = cadr(e1);
switch (car(e1))
{case GVAR:
leaxy(e2);
return;
case RGVAR:
lddy(e2);
return;
case CRGVAR:
ldby(e2);
sex();
return;
case LVAR:
leaxu(e2);
return;
case RLVAR:
lddu(e2);
return;
case CRLVAR:
ldbu(e2);
sex();
return;
case FNAME:
leaxpcr((NMTBL *)e2);
tfrxd();
return;
case CONST:
if (e2) lddim(e2);
else clrd();
return;
case STRING:
string(e1);
return;
case FUNCTION:
function(e1);
return;
case INDIRECT:
indirect(e1);
return;
case RINDIRECT: case CRINDIRECT:
rindirect(e1);
return;
case ADDRESS:
gexpr(e2);
tfrxd();
return;
case MINUS:
gexpr(e2);
printf("\tNEGA\n\tNEGB\n\tSBCA\t#0\n");
return;
case BNOT:
gexpr(e2);
printf("\tCOMA\n\tCOMB\n");
return;
case PREINC:
switch (car(e2))
{case GVAR: case LVAR:
ldd(e2);
adddim(caddr(e1));
std(e2);
return;
default:
gexpr(e2);
lddx();
adddim(caddr(e1));
stdx();
return;
}
case POSTINC:
switch (car(e2))
{case GVAR: case LVAR:
ldd(e2);
adddim(e3 = caddr(e1));
std(e2);
subdim(e3);
return;
default:
gexpr(e2);
lddx();
adddim(e3=caddr(e1));
stdx();
subdim(e3);
return;
}
case CPOSTINC:
gexpr(e2);
ldbx();
incx();
sex();
return;
case CPREINC:
gexpr(e2);
incx();
ldbx();
sex();
return;
case CPOSTDEC:
gexpr(e2);
ldbx();
decx();
sex();
return;
case CPREDEC:
gexpr(e2);
decx();
ldbx();
sex();
return;
case MUL: case UMUL:
if (car(e3=caddr(e1)) == CONST)
{ if (0 < (e3 = cadr(e3)) && e3 <= 10)
{ gexpr(e2);
switch (e3)
{case 8:
asld();
case 4:
asld();
case 2:
asld();
case 1:
return;
case 10:
asld();
case 5:
pushd();
asld();
asld();
addds();
return;
case 6:
asld();
case 3:
pushd();
asld();
addds();
return;
case 9: case 7:
pushd();
asld();
asld();
asld();
if (e3 == 9) addds(); else subds();
return;
}
}
}
case DIV: case UDIV: case MOD: case UMOD:
case LSHIFT: case ULSHIFT: case RSHIFT: case URSHIFT:
binexpr(e1);
return;
case ADD: case SUB: case BAND: case EOR: case BOR:
machinop(e1);
return;
case COND:
e2=fwdlabel();
bexpr(cadr(e1),0,e2);
gexpr(caddr(e1));
jmp(e3=fwdlabel());
fwddef(e2);
gexpr(cadddr(e1));
fwddef(e3);
return;
case ASS: case CASS:
assign(e1);
return;
case ASSOP: case CASSOP:
assop(e1);
return;
case COMMA:
gexpr(e2);
gexpr(caddr(e1));
return;
default:
bexpr(e1,1,e2=fwdlabel());
clrd();
printf("\tBRA\t*+5\n");
fwddef(e2);
lddim(1);
}
}
bexpr(e1,cond,l1)
int e1,l1;
char cond;
{int e2,l2;
if (chk) return;
e2=cadr(e1);
switch(car(e1))
{case LNOT:
bexpr(e2,!cond,l1);
return;
case GT:
rexpr(e1,l1,cond?"GT":"LE");
return;
case UGT:
rexpr(e1,l1,cond?"HI":"LS");
return;
case GE:
rexpr(e1,l1,cond?"GE":"LT");
return;
case UGE:
rexpr(e1,l1,cond?"HS":"LO");
return;
case LT:
rexpr(e1,l1,cond?"LT":"GE");
return;
case ULT:
rexpr(e1,l1,cond?"LO":"HS");
return;
case LE:
rexpr(e1,l1,cond?"LE":"GT");
return;
case ULE:
rexpr(e1,l1,cond?"LS":"HI");
return;
case EQ:
rexpr(e1,l1,cond?"EQ":"NE");
return;
case NEQ:
rexpr(e1,l1,cond?"NE":"EQ");
return;
case LAND:
bexpr(e2,0,cond?(l2=fwdlabel()):l1);
bexpr(caddr(e1),cond,l1);
if(cond) fwddef(l2);
return;
case LOR:
bexpr(e2,1,cond?l1:(l2=fwdlabel()));
bexpr(caddr(e1),cond,l1);
if(!cond) fwddef(l2);
return;
case CRGVAR:
ldby(e2);
jcond(l1,cond);
return;
case CRLVAR:
ldbu(e2);
jcond(l1,cond);
return;
case CONST:
if(cond&&e2||!cond&&!e2) jmp(l1);
return;
case RGVAR:
case RLVAR:
case CRINDIRECT:
gexpr(e1);
jcond(l1,cond);
return;
default:gexpr(e1);
subdim(0);
jcond(l1,cond);
return;
}
}
string(e1)
int e1;
{char *s;
int i,l,lb;
s=(char *)cadr(e1);
lb=fwdlabel();
if ((l = caddr(e1)) < 128)
printf("\tLEAX\t2,PC\n\tBRA\t_%d\n",lb);
else
printf("\tLEAX\t3,PC\n\tLBRA\t_%d\n",lb);
do
{ printf("\tFCB\t%d",*s++);
for (i=8; --l && --i;) printf(",%d",*s++);
printf("\n");
}
while (l);
fwddef(lb);
}
function(e1)
int e1;
{int e2,e3,e4,e5,nargs;
NMTBL *n;
e2 = cadr(e1);
nargs = 0;
for (e3 = caddr(e1); e3; e3 = cadr(e3))
{ n=(NMTBL *)(e5=(cadr(e4 = car(e3))));
switch(car(e4))
{case FNAME:
leaxpcr(n);
pushx();
break;
case ADDRESS:
gexpr(e5);
pushx();
break;
default:gexpr(e4);
pushd();
}
++nargs;
}
if (car(e2) == FNAME)
{ n=(NMTBL *)cadr(e2);
printf("\tLBSR\t%s\n",n->nm);
}
else
{ gexpr(e2);
printf("\tJSR\t,X\n");
}
if (nargs) printf("\tLEAS\t%d,S\n",2*nargs);
}
indirect(e1)
int e1;
{int e2,e3,e4;
e3 = cadr(e2 = cadr(e1));
switch(car(e2))
{case RGVAR: case RLVAR:
ldx(e2);
return;
case ADD:
if(car(e3)==ADDRESS)
{ gexpr(caddr(e2));
gexpr(cadr(e3));
opdx("LEAX");
return;
}
switch(car(e4 = caddr(e2)))
{case RGVAR: case RLVAR:
gexpr(e3);
ldx(e4);
opdx("LEAX");
return;
}
default:
gexpr(e2);
tfrdx();
}
}
machinop(e1)
int e1;
{int e2,e3;
e2 = cadr(e1);
switch (car(e3 = caddr(e1)))
{case RGVAR: case RLVAR: case CONST:
gexpr(e2);
oprt(car(e1),e3);
return;
default:
gexpr(e3);
pushd();
gexpr(e2);
tosop(car(e1));
return;
}
}
rindirect(e1)
int e1;
{char *op;
int e2,e3,e4,byte,l;
op = ((byte = (car(e1) == CRINDIRECT)) ? "LDB" : "LDD");
e3 = cadr(e2 = cadr(e1));
switch (car(e2))
{case RGVAR: case RLVAR:
indir(op,e2);
sextend(byte);
return;
case ADD:
if(car(e3)==ADDRESS)
{ gexpr(caddr(e2));
gexpr(cadr(e3));
opdx(op);
sextend(byte);
return;
}
switch(car(e4=caddr(e2)))
{case RGVAR: case RLVAR:
gexpr(e3);
ldx(e4);
opdx(op);
sextend(byte);
return;
case CONST:
switch (car(e3))
{case RGVAR: case RLVAR:
ldx(e3);
indexx(op,cadr(e4));
sextend(byte);
return;
}
default:
gexpr(e3);
pushd();
gexpr(e4);
pulx();
opdx(op);
sextend(byte);
return;
}
case PREINC:
if ((l = caddr(e2)) == -1 || l == -2)
switch (car(e3))
{case GVAR: case LVAR:
ldx(e3);
predecx(op,l);
stx(e3);
sextend(byte);
return;
}
break;
case POSTINC:
if ((l = caddr(e2)) == 1 || l == 2)
switch (car(e3))
{case GVAR: case LVAR:
ldx(e3);
postincx(op,l);
stx(e3);
sextend(byte);
return;
}
break;
}
gexpr(e2);
tfrdx();
indexx(op,0);
sextend(byte);
}
assign(e1)
int e1;
{char *op;
int e2,e3,e4,e5,l;
op = (car(e1) == CASS ? "STB" : "STD");
e3 = cadr(e2 = cadr(e1));
e4 = caddr(e1);
switch(car(e2))
{case GVAR: case LVAR:
gexpr(e4);
index(op,e2);
return;
case INDIRECT:
switch(car(e3))
{case RGVAR: case RLVAR:
gexpr(e4);
indir(op,e3);
return;
case ADD:
if (car(caddr(e3)) == CONST)
switch (car(e5=cadr(e3)))
{case RGVAR: case RLVAR:
gexpr(e4);
ldx(e5);
indexx(op,cadr(caddr(e3)));
return;
}
break;
case PREINC:
if ((l = caddr(e3)) == -1 || l == -2)
switch (car(e5=cadr(e3)))
{case GVAR: case LVAR:
gexpr(e4);
ldx(e5);
predecx(op,l);
stx(e5);
return;
}
break;
case POSTINC:
if ((l = caddr(e3)) == 1 || l == 2)
switch (car(e5=cadr(e3)))
{case GVAR: case LVAR:
gexpr(e4);
ldx(e5);
postincx(op,l);
stx(e5);
return;
}
break;
}
}
switch (car(e4))
{case RGVAR: case CRGVAR: case RLVAR: case CRLVAR: case CONST:
gexpr(e2);
gexpr(e4);
break;
default:
gexpr(e4);
pushd();
gexpr(e2);
pulld();
}
indexx(op,0);
return;
}
assop(e1)
int e1;
{int e2,e3,byte,op;
char *ldop,*stop;
ldop = ((byte = (car(e1) == CASSOP)) ? "LDB" : "LDD");
stop = (byte ? "STB" : "STD");
e2 = cadr(e1);
e3 = caddr(e1);
op = cadddr(e1);
switch (car(e2))
{case GVAR: case LVAR:
switch (car(e3))
{case RGVAR: case RLVAR: case CONST:
if (simpop(op))
{ index(ldop,e2);
sextend(byte);
oprt(op,e3);
index(stop,e2);
return;
}
default:
gexpr(e3);
pushd();
index(ldop,e2);
sextend(byte);
tosop(op);
index(stop,e2);
return;
}
default:
switch (car(e3))
{case RGVAR: case RLVAR: case CONST:
if (simpop(op))
{ gexpr(e2);
indexx(ldop,0);
sextend(byte);
oprt(op,e3);
indexx(stop,0);
return;
}
default:
gexpr(e3);
pushd();
gexpr(e2);
indexx(ldop,0);
sextend(byte);
tosop(op);
indexx(stop,0);
return;
}
}
}
simpop(op)
int op;
{ return (op == ADD || op == SUB ||
op == BAND || op == EOR || op == BOR);
}
oprt(op,e1)
int op,e1;
{int e2;
e2 = cadr(e1);
switch (car(e1))
{case RGVAR:
oprt1(op,"Y",e2);
return;
case RLVAR:
oprt1(op,"U",e2);
return;
case CONST:
oprtc(op,e2);
return;
}
}
oprt1(op,index,n)
int op,n;
char *index;
{ switch (op)
{case ADD:
printf("\tADDD\t%d,%s\n",n,index);
return;
case SUB:
printf("\tSUBD\t%d,%s\n",n,index);
return;
case BAND: case EOR: case BOR:
dualop(op,index,n);
return;
}
}
dualop(op,index,n)
int op;
char *index;
int n;
{char *ops;
ops = ((op == BAND) ? "AND" :
(op == EOR) ? "EOR" :
(op == BOR) ? "OR" : (char *)DEBUG);
printf("\t%sA\t%d,%s\n\t%sB\t%d+1,%s\n",ops,n,index,ops,n,index);
}
oprtc(op,n)
int op,n;
{ switch (op)
{case ADD:
adddim(n);
return;
case SUB:
subdim(n);
return;
case BAND: case EOR: case BOR:
dualc(op,n);
return;
}
}
dualc(op,n)
int op;
int n;
{char *ops;
ops = ((op == BAND) ? "AND" :
(op == EOR) ? "EOR" :
(op == BOR) ? "OR" : (char *)DEBUG);
printf("\t%sA\t#%d\n\t%sB\t#%d\n",ops,(n >> 8) & 0xff,ops,n & 0xff);
}
tosop(op)
int op;
{ switch (op)
{case ADD:
addds();
return;
case SUB:
subds();
return;
case BAND: case EOR: case BOR:
dualtosop(op);
return;
default:
pulx();
library(op);
}
}
dualtosop(op)
int op;
{char *ops;
ops = ((op == BAND) ? "AND" :
(op == EOR) ? "EOR" :
(op == BOR) ? "OR" : (char *)DEBUG);
printf("\t%sA\t,S+\n\t%sB\t,S+\n",ops,ops);
}
pushd()
{ printf("\tPSHS\tD\n");
}
pushx()
{ printf("\tPSHS\tX\n");
}
pulld()
{ printf("\tPULS\tD\n");
}
pulx()
{ printf("\tPULS\tX\n");
}
tfrdx()
{ printf("\tTFR\tD,X\n");
}
tfrxd()
{ printf("\tTFR\tX,D\n");
}
/*
exgdx()
{ printf("\tEXG\tD,X\n");
}
*/
asld()
{ printf("\tASLB\n\tROLA\n");
}
adddim(n)
{ printf("\tADDD\t#%d\n",n);
}
subdim(n)
{ printf("\tSUBD\t#%d\n",n);
}
cmpdimm(n)
int n;
{ printf("\tCMPD\t#%d\n",n);
}
addds()
{ printf("\tADDD\t,S++\n");
}
subds()
{ printf("\tSUBD\t,S++\n");
}
clrd()
{ printf("\tCLRA\n\tCLRB\n");
}
lddim(n)
int n;
{ printf("\tLDD\t#%d\n",n);
}
ldd(e)
int e;
{ switch (car(e))
{case GVAR:
lddy(cadr(e));
return;
case LVAR:
lddu(cadr(e));
return;
default:
DEBUG;
}
}
lddx()
{ printf("\tLDD\t,X\n");
}
lddy(n)
int n;
{ printf("\tLDD\t%d,Y\n",n);
}
lddu(n)
int n;
{ printf("\tLDD\t%d,U\n",n);
}
std(e)
int e;
{ switch (car(e))
{case GVAR:
stdy(cadr(e));
return;
case LVAR:
stdu(cadr(e));
return;
default:
DEBUG;
}
}
stdx()
{ printf("\tSTD\t,X\n");
}
stdy(n)
int n;
{ printf("\tSTD\t%d,Y\n",n);
}
stdu(n)
int n;
{ printf("\tSTD\t%d,U\n",n);
}
ldbx()
{ printf("\tLDB\t,X\n");
}
/*
stbx()
{ printf("\tSTB\t,X\n");
}
*/
ldby(n)
int n;
{ printf("\tLDB\t%d,Y\n",n);
}
ldbu(n)
int n;
{ printf("\tLDB\t%d,U\n",n);
}
predecx(op,l)
char *op;
int l;
{ printf("\t%s\t,%sX\n",op,(l == -1 ? "-" : "--"));
}
postincx(op,l)
char *op;
int l;
{ printf("\t%s\t,X%s\n",op,(l == 1 ? "+" : "++"));
}
leaxy(n)
int n;
{ printf("\tLEAX\t%d,Y\n",n);
}
leaxu(n)
int n;
{ printf("\tLEAX\t%d,U\n",n);
}
leaxpcr(n)
NMTBL *n;
{ printf("\tLEAX\t%s,PCR\n",n->nm);
}
ldx(e)
int e;
{ switch (car(e))
{case GVAR: case RGVAR:
ldxy(cadr(e));
return;
case LVAR: case RLVAR:
ldxu(cadr(e));
return;
default:
DEBUG;
}
}
ldxy(n)
int n;
{ printf("\tLDX\t%d,Y\n",n);
}
ldxu(n)
int n;
{ printf("\tLDX\t%d,U\n",n);
}
/*
ldxi(n)
int n;
{ printf("\tLDX\t#%d\n",n);
}
*/
stx(e)
int e;
{ switch (car(e))
{case GVAR:
stxy(cadr(e));
return;
case LVAR:
stxu(cadr(e));
return;
default:
DEBUG;
}
}
stxy(n)
int n;
{ printf("\tSTX\t%d,Y\n",n);
}
stxu(n)
int n;
{ printf("\tSTX\t%d,U\n",n);
}
sex()
{ printf("\tSEX\n");
}
incx()
{ printf("\tINC\t,X\n");
}
decx()
{ printf("\tDEC\t,X\n");
}
opdx(op)
char *op;
{ printf("\t%s\tD,X\n",op);
}
indexx(op,n)
char *op;
int n;
{ printf("\t%s\t%d,X\n",op,n);
}
index(op,e)
char *op;
int e;
{ switch (car(e))
{case GVAR:
indexy(op,cadr(e));
return;
case LVAR:
indexu(op,cadr(e));
return;
default:
DEBUG;
}
}
indexy(op,n)
char *op;
int n;
{ printf("\t%s\t%d,Y\n",op,n);
}
indexu(op,n)
char *op;
int n;
{ printf("\t%s\t%d,U\n",op,n);
}
indir(op,e)
char *op;
int e;
{ switch (car(e))
{case RGVAR:
indiry(op,cadr(e));
return;
case RLVAR:
indiru(op,cadr(e));
return;
default:
DEBUG;
}
}
indiry(op,n)
char *op;
int n;
{ printf("\t%s\t[%d,Y]\n",op,n);
}
indiru(op,n)
char *op;
int n;
{ printf("\t%s\t[%d,U]\n",op,n);
}
sextend(byte)
int byte;
{ if (byte) sex();
}
binexpr(e1)
int e1;
{ gexpr(caddr(e1));
pushd();
gexpr(cadr(e1));
pulx();
library(car(e1));
}
library(op)
int op;
{ printf("\tLBSR\t_0000%d\n",
((op == MUL || op == UMUL) ? 1 :
(op == DIV) ? 2 :
(op == UDIV) ? 3 :
(op == MOD) ? 4 :
(op == UMOD) ? 5 :
(op == LSHIFT) ? 6 :
(op == ULSHIFT) ? 7 :
(op == RSHIFT) ? 8 :
(op == URSHIFT) ? 9 : DEBUG));
}
cexpr(e)
int e;
{ if (car(e) != CONST) error(CNERR);
return (cadr(e));
}
ret()
{
char *reg;
switch(lvar)
{case 0:
reg = "";
return;
case 1:
reg = "A,";
return;
case 2:
reg = "X,";
return;
case 3:
reg = "A,X,";
return;
case 4:
reg = "D,X,";
default:
printf("\tLEAS\t,U\n");
reg = "";
}
printf("\tPULS\t%sU,PC\n",reg);
}
opening(filename)
char *filename;
{
printf("\t.file\t\"%s\"\n",filename);
printf(".text\n");
}
closing()
{
printf("_%d\tRTS\n_INITIALIZE\tEQU\t_1\n",ilabel);
printf("_GLOBALS\tEQU\t%u\n\tEND\n",gpc);
}
gen_gdecl(n,gpc)
char *n;
int gpc;
{
printf("%s\tEQU\t%u\n",n,gpc);
}
jmp_label(l)
int l;
{
printf("\tBRA\t_%d\n",l);
}
jmp_eq_label(l)
int l;
{
printf("\tBEQ\t_%d\n",l);
}
rexpr(e1,l1,s)
int e1,l1;
char *s;
{ gexpr(list3(SUB,cadr(e1),caddr(e1)));
printf("\tLB%s\t_%d\n",s,l1);
}
jcond(l,cond)
int l;
char cond;
{ printf("\tLB%s\t_%d\n",cond?"NE":"EQ",l);
}
jmp(l)
int l;
{ control=0;
printf("\tLBRA\t_%d\n",l);
}
fwdlabel()
{ return labelno++;
}
fwddef(l)
int l;
{ control=1;
printf("_%d\n",l);
}
backdef()
{ control=1;
printf("_%d\n",labelno);
return labelno++;
}
def_label(cslabel,dlabel)
int cslabel,dlabel;
{
if(dlabel) printf("_%d\tEQU\t_%d\n",cslabel,dlabel);
}
gen_comment(s)
char *s;
{
printf("* %s",s);
}
gen_source(s)
char *s;
{
printf("%s",s);
}
enter(name)
char *name;
{
printf("%s\n\tPSHS\tU\n\tLEAU\t,S\n",name);
}
enter1(disp)
int disp;
{
if(disp) printf("\tLEAS\t%d,S\n",disp);
}
leave(control,name)
int control;
char *name;
{
if (control)
ret();
}
void
emit_data(e,t)
int e,t;
{
int l;
if(mode==STADECL)
jmp_label(l=fwdlabel());
fwddef(ilabel);
if(car(e)==CONST)
{ lddim(cadr(e));
indexy(t==CHAR?"STB":"STD",gpc);
}
else if(t!=CHAR)
{ if(car(e)==ADDRESS&&car(cadr(e))==GVAR)
leaxy(cadr(cadr(e)));
else if(car(e)==FNAME)
leaxpcr((NMTBL *)cadr(e));
else error(TYERR);
stxy(gpc);
}
jmp(ilabel=fwdlabel());
if(mode==STADECL) fwddef(l);
}