%option noyywrap %option yylineno %{ #include #include #include char *yylval; %} %% #.* [:] { return(yytext[0]); } [\&\$;\?\*\-A-Za-z0-9_\+-/=><\^!@]* { yylval = yytext; return (256); } . \n %% int memory_size = 1024; #define UCODE_SP(N) (((N) & 3) << 0) #define UCODE_WRITE (1 << 2) #define UCODE_FETCH (1 << 4) #define UCODE_STORE (1 << 5) #define UCODE_ALU(N) ((N) << 7) #define UCODE_IOW (1 << 6) #define UCODE_PRED_NEVER (0 << 11) #define UCODE_PRED_LESS (1 << 11) #define UCODE_PRED_EQUAL (2 << 11) #define UCODE_PRED_LEQUAL (3 << 11) #define UCODE_PRED_GREATER (4 << 11) #define UCODE_PRED_NOTEQUAL (5 << 11) #define UCODE_PRED_GEQUAL (6 << 11) #define UCODE_PRED_ALWAYS (7 << 11) #define UCODE_PRED_NEVER_DROP ((0 << 11) | (1 << 10)) #define UCODE_PRED_LESS_DROP ((1 << 11) | (1 << 10)) #define UCODE_PRED_EQUAL_DROP ((2 << 11) | (1 << 10)) #define UCODE_PRED_LEQUAL_DROP ((3 << 11) | (1 << 10)) #define UCODE_PRED_GREATER_DROP ((4 << 11) | (1 << 10)) #define UCODE_PRED_NOTEQUAL_DROP ((5 << 11) | (1 << 10)) #define UCODE_PRED_GEQUAL_DROP ((6 << 11) | (1 << 10)) #define UCODE_PRED_ALWAYS_DROP ((7 << 11) | (1 << 10)) #define UCODE_LOGIC(N) ((N) << 10) /* logic operations: a b => r */ #define LOGIC_CLEAR (UCODE_ALU(1) | UCODE_LOGIC(0x0)) /* 0 */ #define LOGIC_SET (UCODE_ALU(1) | UCODE_LOGIC(0xF)) /* 1 */ #define LOGIC_COPY (UCODE_ALU(1) | UCODE_LOGIC(0x3)) /* b */ #define LOGIC_COPY_INVERTED (UCODE_ALU(1) | UCODE_LOGIC(0xC)) /* !b */ #define LOGIC_NOOP (UCODE_ALU(1) | UCODE_LOGIC(0x5)) /* a */ #define LOGIC_INVERT (UCODE_ALU(1) | UCODE_LOGIC(0xA)) /* !a */ #define LOGIC_AND (UCODE_ALU(1) | UCODE_LOGIC(0x1)) /* a & b */ #define LOGIC_NAND (UCODE_ALU(1) | UCODE_LOGIC(0xE)) /* !(a & b) */ #define LOGIC_OR (UCODE_ALU(1) | UCODE_LOGIC(0x7)) /* a | b */ #define LOGIC_NOR (UCODE_ALU(1) | UCODE_LOGIC(0x8)) /* !(a | b) */ #define LOGIC_XOR (UCODE_ALU(1) | UCODE_LOGIC(0x6)) /* a ^ b */ #define LOGIC_EQUIV (UCODE_ALU(1) | UCODE_LOGIC(0x9)) /* !(a ^ b) */ #define LOGIC_AND_REVERSE (UCODE_ALU(1) | UCODE_LOGIC(0x2)) /* b & !a */ #define LOGIC_AND_INVERTED (UCODE_ALU(1) | UCODE_LOGIC(0x4)) /* !b & a */ #define LOGIC_OR_REVERSE (UCODE_ALU(1) | UCODE_LOGIC(0xB)) /* b | !a */ #define LOGIC_OR_INVERTED (UCODE_ALU(1) | UCODE_LOGIC(0xD)) /* !b | a */ #define ALU_TOP LOGIC_COPY #define ALU_ST1 LOGIC_NOOP #define OP_IMMED (1 << 14) #define OP_JUMP (2 << 14) #define OP_CALL (3 << 14) #define OP_RETURN (ALU_TOP | 0x0008) #define OP_ADD (UCODE_SP(-1) | UCODE_ALU(0)) #define OP_NOT (UCODE_SP(0) | LOGIC_COPY_INVERTED) #define OP_CLEAR (UCODE_SP(0) | LOGIC_CLEAR) #define OP_SET (UCODE_SP(0) | LOGIC_SET) #define OP_OR (UCODE_SP(-1) | LOGIC_OR) #define OP_XOR (UCODE_SP(-1) | LOGIC_XOR) #define OP_AND (UCODE_SP(-1) | LOGIC_AND) #define OP_NAND (UCODE_SP(-1) | LOGIC_NAND) #define OP_OR (UCODE_SP(-1) | LOGIC_OR) #define OP_NOR (UCODE_SP(-1) | LOGIC_NOR) #define OP_EQUIV (UCODE_SP(-1) | LOGIC_EQUIV) #define OP_AND_REVERSE (UCODE_SP(-1) | LOGIC_AND_REVERSE) #define OP_AND_INVERTED (UCODE_SP(-1) | LOGIC_AND_INVERTED) #define OP_OR_REVERSE (UCODE_SP(-1) | LOGIC_OR_REVERSE) #define OP_OR_INVERTED (UCODE_SP(-1) | LOGIC_OR_INVERTED) #define OP_DUP (UCODE_SP(1) | ALU_TOP | UCODE_WRITE) #define OP_DROP (UCODE_SP(-1) | ALU_ST1) #define OP_OVER (UCODE_SP(1) | ALU_ST1 | UCODE_WRITE) #define OP_SWAP (UCODE_SP(0) | ALU_ST1 | UCODE_WRITE) #define OP_NIP (UCODE_SP(-1) | ALU_TOP) #define OP_DOWN (UCODE_SP(-1) | ALU_TOP) #define OP_UP (UCODE_SP(1) | ALU_TOP) #define OP_FETCH (UCODE_SP(0) | UCODE_ALU(4)) #define OP_STORE (UCODE_SP(-1) | ALU_TOP | UCODE_STORE) #define OP_RSHIFT1 (UCODE_SP(0) | UCODE_ALU(2)) #define OP_OUT_ (UCODE_SP(-1) | ALU_ST1 | UCODE_IOW) #define OP_OUT (UCODE_SP(0) | ALU_TOP | UCODE_IOW) #define OP_STATUS (UCODE_SP(1) | UCODE_ALU(3) | UCODE_WRITE) #define OP_IN (UCODE_SP(0) | UCODE_ALU(7)) #define OP_SWAB (UCODE_SP(0) | UCODE_ALU(4)) #define OP_NOP (UCODE_SP(0) | ALU_TOP) struct ref { int loc; struct ref *tail; int lineno; }; struct symbol { struct symbol *tail; char *name; int v; struct ref *rr; }; static struct symbol *symbol_table; unsigned short store[2048]; static struct symbol *new_symbol(char *name) { struct symbol *ps; for (ps = symbol_table; ps != NULL; ps = ps->tail) { if (strcasecmp(name, ps->name) == 0) break; } if (ps == NULL) { ps = malloc(sizeof(*ps)); ps->tail = symbol_table; symbol_table = ps; ps->name = strdup(name); ps->v = -1; ps->rr = NULL; } return ps; } static void define_symbol(struct symbol *ps, int l) { struct ref *pr; ps->v = l; } static void reference_symbol(char *name, int l) { struct symbol *ps; struct ref *r; ps = new_symbol(name); r = malloc(sizeof(*r)); r->loc = l; r->tail = ps->rr; r->lineno = yylineno; ps->rr = r; } static void resolve_symbols(void) { struct symbol *ps; struct ref *pr; int error = 0; for (ps = symbol_table; ps; ps = ps->tail) { for (pr = ps->rr; pr != NULL; pr = pr->tail) { if (ps->v == -1) { printf("xpumain.sl:%d: undefined symbol `%s'\n", pr->lineno, ps->name); error = 1; } else { //printf("Resolving %s from %x to %x\n", ps->name, ps->v, pr->loc); store[pr->loc] |= ps->v; } } } if (error) exit(1); } static void dump_symbol_table(void) { struct symbol *ps; FILE *symbols; symbols = fopen("symbols", "w"); for (ps = symbol_table; ps; ps = ps->tail) fprintf(symbols, "%04x %-16s\n", ps->v, ps->name); fclose(symbols); } static int next_ip(int ip) { return ip + 1; switch (memory_size) { case 256: return 0xff & ((ip << 1) ^ (1 & (1 ^ ((ip >> 7) ^ (ip >> 5) ^ (ip >> 4) ^ (ip >> 3))))); case 1024: return 0x3ff & ((ip << 1) ^ (1 & (1 ^ ((ip >> 9) ^ (ip >> 6))))); default: assert(0); } } main(int argc, char *argv[]) { int t; int ip; int expect_label; int predicate; char *endptr; memset(store, 0, sizeof(store)); ip = 0; expect_label = 0; predicate = UCODE_PRED_ALWAYS; while (t = yylex()) { if (t < 256) { //printf("%d\n", t); if (t == ':') expect_label = 1; } else { //printf("\"%s\"\n", yylval); strtol(yylval, &endptr, 0); if (expect_label) { struct symbol *ns = new_symbol(yylval); if (ns->v != -1) { printf("main.sl:%d: multiple definition `%s' %s\n", yylineno, ns->name, yylval); exit(1); } define_symbol(ns, ip); expect_label = 0; } else if (endptr == (yylval + strlen(yylval))) { store[ip] = OP_IMMED | (0x3fff & strtol(yylval, NULL, 0)); ip = next_ip(ip); } else if (yylval[0] == '&') { store[ip] = OP_IMMED; reference_symbol(yylval + 1, ip); ip = next_ip(ip); } else if (yylval[0] == '$') { store[ip] = strtol(yylval + 1, NULL, 0); ip = next_ip(ip); } else if (yylval[0] == '>') { store[ip] = OP_JUMP | predicate; predicate = UCODE_PRED_ALWAYS; reference_symbol(yylval + 1, ip); ip = next_ip(ip); } else { if (strcasecmp(yylval, "?LT") == 0) predicate = UCODE_PRED_LESS; else if (strcasecmp(yylval, "?FA") == 0) predicate = UCODE_PRED_NEVER; else if (strcasecmp(yylval, "?EQ") == 0) predicate = UCODE_PRED_EQUAL; else if (strcasecmp(yylval, "?LE") == 0) predicate = UCODE_PRED_LEQUAL; else if (strcasecmp(yylval, "?GT") == 0) predicate = UCODE_PRED_GREATER; else if (strcasecmp(yylval, "?NE") == 0) predicate = UCODE_PRED_NOTEQUAL; else if (strcasecmp(yylval, "?GE") == 0) predicate = UCODE_PRED_GEQUAL; else if (strcasecmp(yylval, "?TR") == 0) predicate = UCODE_PRED_ALWAYS; else if (strcasecmp(yylval, "?FA-") == 0) predicate = UCODE_PRED_NEVER_DROP; else if (strcasecmp(yylval, "?LT-") == 0) predicate = UCODE_PRED_LESS_DROP; else if (strcasecmp(yylval, "?EQ-") == 0) predicate = UCODE_PRED_EQUAL_DROP; else if (strcasecmp(yylval, "?LE-") == 0) predicate = UCODE_PRED_LEQUAL_DROP; else if (strcasecmp(yylval, "?GT-") == 0) predicate = UCODE_PRED_GREATER_DROP; else if (strcasecmp(yylval, "?NE-") == 0) predicate = UCODE_PRED_NOTEQUAL_DROP; else if (strcasecmp(yylval, "?GE-") == 0) predicate = UCODE_PRED_GEQUAL_DROP; else if (strcasecmp(yylval, "?TR-") == 0) predicate = UCODE_PRED_ALWAYS_DROP; else { struct lookup { char *name; unsigned short op; } xlat[] = { "+", OP_ADD, ";", OP_RETURN, "CLEAR", OP_CLEAR, "SET", OP_SET, "NOT", OP_NOT, "OR", OP_OR, "XOR", OP_XOR, "AND", OP_AND, "NAND", OP_NAND, "OR", OP_OR, "NOR", OP_NOR, "EQUIV", OP_EQUIV, "AND_REVERSE", OP_AND_REVERSE, "AND_INVERTED", OP_AND_INVERTED, "OR_REVERSE", OP_OR_REVERSE, "OR_INVERTED", OP_OR_INVERTED, "DUP", OP_DUP, "DROP", OP_DROP, "OVER", OP_OVER, "SWAP", OP_SWAP, "NIP", OP_NIP, "NOP", OP_NOP, "DOWN", OP_DOWN, "UP", OP_UP, "FETCH", OP_FETCH, "STORE", OP_STORE, "RSHIFT1", OP_RSHIFT1, "OUT", OP_OUT, "OUT-", OP_OUT_, "STATUS", OP_STATUS, "IN", OP_IN, "SWAB", OP_SWAB, "@", OP_FETCH, "J!", OP_STORE }; int i; int combined_return; combined_return = 0; if (1 && (1 < strlen(yylval)) && (yylval[strlen(yylval) - 1] == ';')) { combined_return = 0x0008; yylval[strlen(yylval) - 1] = 0; } for (i = 0; i < (sizeof(xlat) / sizeof(xlat[0])); i++) { if (strcasecmp(yylval, xlat[i].name) == 0) break; } if (i < (sizeof(xlat) / sizeof(xlat[0]))) { store[ip] = xlat[i].op | combined_return; ip = next_ip(ip); } else { if (combined_return) printf("main.sl:%d: Can't do combined return\n"); store[ip] = OP_CALL | predicate; predicate = UCODE_PRED_ALWAYS; reference_symbol(yylval, ip); ip = next_ip(ip); } } //printf("%04x\n", store[ip-1]); } } } printf("%d lines, %d locations\n", yylineno - 1, ip); resolve_symbols(); dump_symbol_table(); { FILE *f; f = fopen("xpubinary", "w"); fwrite(store, memory_size, 2, f); fclose(f); } if (memory_size == 256) { FILE *f; int i, j, k; f = fopen("xpu0.inc", "w"); for (j = 0; j < 16; j++) { fprintf(f, "INIT_0%X => X\"", j); for (k = 0; k < 16; k++) { fprintf(f, "%04X", store[(15 - k) + 16 * j]); } fprintf(f, "\"%s\n", (j < 15) ? "," : ""); } } else { char name[20]; FILE *f; int i, j, k; for (i = 0; i < 4; i++) { sprintf(name, "xpu%d.inc", i); f = fopen(name, "w"); for (j = 0; j < 16; j++) { fprintf(f, "INIT_0%X => X\"", j); for (k = 0; k < 64; k++) { unsigned short v = 0xf & (store[(63 - k) + 64 * j] >> (4 * i)); fprintf(f, "%X", v); } fprintf(f, "\"%s\n", (j < 15) ? "," : ""); } fclose(f); } } exit(0); }