#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); }