#include #define NAKED __attribute__((naked)) #define END_OF(arr) ((arr) + (sizeof((arr)) / sizeof(*(arr)))) #define ATTR_NATIVE (1 << 7) #define ATTR_IMMEDIATE (1 << 6) #define ATTR_LEN (0x3F) #define WORD(name, tname, prev, attr) \ extern const void *name##_body[]; \ struct word_t w_##name = { \ name##_body, prev, attr + sizeof(tname) - 1, tname \ }; \ const void *name##_body[] = { #define LIT(x) push, (void *)(x) #define FTH(w) enter, (w##_body) #define END fexit, }; #define NATIVE(name, tname, prev, attr) \ extern const void *name##_body[]; \ NAKED void name(void); \ struct word_t w_##name = { \ name##_body, prev, \ (attr | ATTR_NATIVE) + sizeof(tname) - 1, tname \ }; \ const void *name##_body[] = { name, fexit }; \ NAKED void name(void) #define W(name, tname, prev) WORD(name, tname, prev, 0) #define I(name, tname, prev) WORD(name, tname, prev, ATTR_IMMEDIATE) #define N(name, tname, prev) NATIVE(name, tname, prev, 0) #define C(name, tname, prev) NATIVE(name, tname, prev, ATTR_IMMEDIATE) #define NEXT { goto *(*++pp); } struct word_t { const void **body; struct word_t *prev; unsigned char attr; char name[]; } __attribute__ ((packed)); static intptr_t dstack[32]; static intptr_t **rstack[32]; static intptr_t dict[8192] = { 0, 10 }; #define state dict[0] #define base dict[1] #define begin dict[2] static intptr_t *here = &begin; static struct word_t *latest; register intptr_t tmp asm("r12"); register intptr_t * sp asm("r13"); // pointer to stack cells register intptr_t *** rp asm("r14"); // stack of pp register intptr_t ** pp asm("r15"); // pointer to ip #define STASH asm("push %r12; push %r13; push %r14; push %r15") #define RESTORE asm("pop %r15; pop %r14; pop %r13; pop %r12") NAKED void dot(void); NAKED void enter(void) { *--rp = ++pp; pp = (intptr_t **)*pp; goto *(*pp); } NAKED void push(void) { *--sp = (intptr_t)*++pp; NEXT; } void fexit(void) { if (rp < END_OF(rstack)) { pp = *rp++; NEXT; } } NAKED void compname(void) { static int ch; STASH; for (;;) { extern int getchar(void); ch = getchar(); if (ch <= 0x20) break; *(unsigned char *)here += 1; ((char *)here)[*(unsigned char *)here] = ch; } here = (intptr_t *)((intptr_t)here + *(unsigned char *)here); RESTORE; NEXT; } N(dup, "dup", 0) { --sp; sp[0] = sp[1]; NEXT; } N(drop, "drop", &w_dup) { ++sp; NEXT; } N(swap, "swap", &w_drop) { tmp = sp[0]; sp[0] = sp[1]; sp[1] = tmp; NEXT; } N(rot, "rot", &w_swap) { tmp = sp[0]; sp[0] = sp[2]; sp[2] = sp[1]; sp[1] = tmp; NEXT; } N(peek, "@", &w_rot) { *sp = *(intptr_t *)*sp; NEXT; } N(poke, "!", &w_peek) { *(intptr_t *)sp[0] = sp[1]; sp += 2; NEXT; } N(cpeek, "c@", &w_poke) { *sp = *(char *)*sp; NEXT; } N(cpoke, "c!", &w_cpeek) { *(char *)sp[0] = (char)sp[1]; sp += 2; NEXT; } N(add, "+", &w_cpoke) { sp[1] += sp[0]; ++sp; NEXT; } N(sub, "-", &w_add) { sp[1] -= sp[0]; ++sp; NEXT; } N(mul, "*", &w_sub) { sp[1] *= sp[0]; ++sp; NEXT; } N(div, "/", &w_mul) { sp[1] /= sp[0]; ++sp; NEXT; } N(mod, "mod", &w_div) { sp[1] %= sp[0]; ++sp; NEXT; } N(and, "and", &w_mod) { sp[1] &= sp[0]; ++sp; NEXT; } N(or, "or", &w_and) { sp[1] |= sp[0]; ++sp; NEXT; } N(xor, "xor", &w_or) { sp[1] ^= sp[0]; ++sp; NEXT; } C(intr, "[", &w_xor) { state = 0; NEXT; } N(comp, "]", &w_intr) { state = -1; NEXT; } N(comma, ",", &w_comp) { *here++ = *sp++; NEXT; } W(cell, "cell", &w_comma) LIT(sizeof(*sp)), END W(cellp, "cell+", &w_cell) FTH(cell), add, END W(cells, "cells", &w_cellp) FTH(cell), mul, END W(dict, "_d", &w_cells) LIT(dict), END W(here, "here", &w_dict) LIT(&here), peek, END W(latest, "latest", &w_here) LIT(&latest), peek, END N(dot, ".", &w_latest) ; W(negate, "negate", &w_dot) LIT(-1), mul, END W(invert, "invert", &w_negate) LIT(-1), xor, END W(dec, "1-", &w_invert) LIT(1), sub, END W(inc, "1+", &w_dec) LIT(1), add, END W(aligned, "aligned", &w_inc) LIT(sizeof(*sp) - 1), add, LIT(~(sizeof(*sp) - 1)), and, END W(align, "align", &w_aligned) FTH(here), FTH(aligned), LIT(&here), poke, END W(colon, ":", &w_align) FTH(here), LIT(0), comma, FTH(latest), comma, compname, FTH(align), dup, FTH(here), swap, poke, comp, END I(semic, ";", &w_colon) LIT(fexit), comma, LIT(&latest), poke, intr, END I(literal, "literal", &w_semic) LIT(push), comma, comma, END #define LATEST &w_literal #include #include #include extern long strtol(char *, char **, int); NAKED void dot() { STASH; printf("%ld ", *sp); RESTORE; ++sp; NEXT; } static void call(void *ptr); static void init(void); int main() char buf[128]; init(); for (;;) { char c; do c = getchar(); while (!isgraph(c)); char *s = buf; do { *s++ = c; c = getchar(); } while (isgraph(c)); *s = '\0'; if (strcmp(buf, "bye") == 0) break; struct word_t *l; for (l = latest; l; l = l->prev) { const int ln = l->attr & ATTR_LEN; if (s - buf == ln && !strncmp(buf, l->name, ln)) break; } if (l == 0) { char *end; long n = strtol(buf, &end, base); if (*end == '\0') { if (state) { *here++ = (intptr_t)push; *here++ = n; } else { *--sp = n; } } else { puts("word not found"); } } else { if (state && !(l->attr & ATTR_IMMEDIATE)) { if (!(l->attr & ATTR_NATIVE)) { *here++ = (intptr_t)enter; *here++ = (intptr_t)l->body; } else { *here++ = (intptr_t)l->body[0]; } } else { call(l->body); } } printf(state ? "compiled <%ld>\n" : "ok <%ld>\n", (END_OF(dstack) - sp)); } return 0; } void init(void) { sp = END_OF(dstack); rp = END_OF(rstack); pp = 0; latest = LATEST; } void call(void *ptr) { pp = ptr; ((void (*)())*pp)(); }