static unsigned emitasm(Node p, int nt) { int rulenum; short *nts; char *fmt; Node kids[10]; p = reuse(p, nt); rulenum = getrule(p, nt); nts = IR->x._nts[rulenum]; fmt = IR->x._templates[rulenum]; assert(fmt); if (IR->x._isinstruction[rulenum] && p->x.emitted) print("%s", p->syms[RX]->x.name); else if (*fmt == '#') (*IR->x.emit2)(p); else { if (*fmt == '?') { fmt++; assert(p->kids[0]); if (p->syms[RX] == p->x.kids[0]->syms[RX]) while (*fmt++ != '\n') ; } for ((*IR->x._kids)(p, rulenum, kids); *fmt; fmt++) if (*fmt != '%') (void)putchar(*fmt); else if (*++fmt == 'F') print("%d", framesize); else if (*fmt >= '0' && *fmt <= '9') emitasm(kids[*fmt - '0'], nts[*fmt - '0']); else if (*fmt >= 'a' && *fmt < 'a' + NELEMS(p->syms)) fputs(p->syms[*fmt - 'a']->x.name, stdout); else (void)putchar(*fmt); } return 0; }
static void emit2(Node p) { char* name; char* offset; int localoffset; int argoffset; long intval; long double fltval; int op = specific(p->op); int opsz = opsize(p->op); int i, j, k; Symbol s; switch (op) { case CNST + F: fltval = p->syms[0]->u.c.v.d; if (fltval < 0) emithex((short) (fltval * 256)); else printf("%d", (short) (fltval * 256)); break; case CNST + I: intval = p->syms[0]->u.c.v.i; if (intval < 0) emithex((short) intval); else print("%d", intval); break; case ARG + F: case ARG + I: case ARG + U: case ARG + P: if (p->x.argno > 2) { assert(maxargoffset); if (p->x.argno == 3) print("SET PEEK, "); else print("SET I, SP\nSET [%d+I], ", p->x.argno - 3); emitasm(p->kids[0], _bval_NT); print("\n"); } break; case CALL + F: case CALL + I: case CALL + U: case CALL + P: case CALL + V: assert(p->kids[0]); argoffset = p->syms[0]->u.c.v.i; print("JSR "); emitasm(p->kids[0], _addr_NT); print("\n"); if (argoffset > 3) popstack(argoffset - 3, "popping arguments from stack"); break; case ADDRL + P: localoffset = p->syms[0]->x.offset + maxoffset; if (p->x.inst) { if (localoffset) print("SET %s, %d\nADD %s, J\n", p->syms[RX]->name, localoffset, p->syms[RX]->name); else print("SET %s, J\n", p->syms[RX]->name); } else { if (localoffset) print("%d+J", localoffset); else print("J"); } break; case ADDRF + P: if (p->syms[0]->x.offset) print("%d+J", p->syms[0]->x.offset); else print("J"); break; case ASGN + B: assert(p->kids[0]); assert(p->kids[1]); assert(p->kids[1]->kids[0]); print(";starting block copy (%s %s %d)\n", p->kids[0]->syms[RX]->x.name, p->kids[1]->kids[0]->syms[RX]->x.name, p->syms[0]->u.c.v.i); for (i = 0; i < p->syms[0]->u.c.v.i; i++) { if (i == 0) print("SET [%s], [%s]\n", p->kids[0]->syms[RX]->x.name, p->kids[1]->kids[0]->syms[RX]->x.name); else print("SET [%d+%s], [%d+%s]\n", i, p->kids[0]->syms[RX]->x.name, i, p->kids[1]->kids[0]->syms[RX]->x.name); } break; /* case INDIR+P: if (p->kids[0]) { s = p->kids[0]->syms[0]; } else { s = p->syms[0]; } assert(s->x.name); debug(fprintf(stderr, "addrg emit2 %s->%s\n", s->x.name, p->syms[RX]->name)); name = (char*)malloc(strlen(s->x.name)); offset = (char*)malloc(strlen(s->x.name)); for( i = 0; s->x.name[i]; i++ ) { if ( s->x.name[i] == '+' ) break; name[i] = s->x.name[i]; } name[i+1] = 0; if (s->x.name[i] == '+') { i++; for( j = 0; s->x.name[i+j]; j++ ) { offset[j] = s->x.name[i+j]; } offset[i+j+1] = 0; print("SET %s, %s\nADD %s, %s\nSET %s, [%s]\n", p->syms[RX]->name, name, p->syms[RX]->name, offset, p->syms[RX]->name, p->syms[RX]->name); } else { print("SET %s, [", p->syms[RX]->name); emithex(atoi(s->x.name)); print("]\n"); } break; */ } }