shithub: scc

Download patch

ref: 827b4cdaa90cabaa1ee149a79ceb4cf7c7813f47
parent: 9a2913311bd77d7075a327854a725d03eff554a2
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Wed Jan 20 15:11:09 EST 2016

Move cc2 to cc2.old

We are going to begin with the new backend, and it is better
to begin from scratch, but with an eye in the older.

diff: cannot open b/cc2.old//null: file does not exist: 'b/cc2.old//null' diff: cannot open a/cc2//null: file does not exist: 'a/cc2//null'
--- /dev/null
+++ b/cc2.old/Makefile
@@ -1,0 +1,23 @@
+.POSIX:
+
+include ../config.mk
+
+OBJS = main.o parser.o cgen.o code.o optm.o peep.o
+
+all: cc2
+
+
+$(OBJS): ../inc/cc.h ../inc/sizes.h cc2.h
+main.o: error.h
+
+error.h: cc2.h
+	rm -f $@; trap 'rm -f $$$$.h' EXIT INT QUIT
+	awk -f generror cc2.h > $$$$.h && mv $$$$.h $@
+
+cc2: $(OBJS) ../lib/libcc.a
+	$(CC) $(LDFLAGS) $(OBJS) ../lib/libcc.a -o $@
+
+clean:
+	rm -f $(OBJS)
+	rm -f cc2 error.h
+
--- /dev/null
+++ b/cc2.old/cast.patch
@@ -1,0 +1,61 @@
+diff --git a/cc2/cgen.c b/cc2/cgen.c
+index be4ff41..8839505 100644
+--- a/cc2/cgen.c
++++ b/cc2/cgen.c
+@@ -449,16 +449,50 @@ cast(Node *np)
+ {
+ 	Node *lp = np->left;
+ 	uint8_t reg;
++	int8_t delta;
+ 
+-	if (lp->type.size != np->type.size)
++	swtich (lp->type.size) {
++	case 1:
++		switch (np->type.size) {
++		case 1:
++			break;
++		case 2:
++			if (lp->op != REG)
++				move(lp, np);
++			np->reg = reg = lp->reg;
++			if (lp->sign && np->sign) {
++				code(BIT, lp, imm(7));
++				code(JRZ, .., ..);
++				code(LDI, regs[upper[reg]], imm(-1));
++				code(JR, ..., ...);
++			}
++			reguse[pair[reg]] = reguse[reg] = np;
++			code(LDI, regs[lower[reg]], imm(0));
++			break;
++		default:
++			abort();
++		}
++		break;
++	case 2:
++		switch (np->type.size) {
++		case 1:
++			if (lp->op == REG) {
++				reguse[upper[reg]] = NULL;
++				reg = lower[reg];
++				np->reg = reg;
++				reguse[pair[reg]] = reguse[reg] = np;
++			}
++			break;
++		case 2:
++			break;
++		default:
++			abort();
++		}
++	default:
+ 		abort();
++	}
+ 	lp->used = 1;
+ 	np->sym = lp->sym;
+-	if ((np->op = lp->op) == REG) {
+-		reg = lp->reg;
+-		np->reg = reg;
+-		reguse[pair[reg]] = reguse[reg] = np;
+-	}
+ }
+ 
+ static void (*opnodes[])(Node *) = {
--- /dev/null
+++ b/cc2.old/cc2.h
@@ -1,0 +1,179 @@
+
+#define SIGNF 1
+#define INTF  2
+
+#define NONE       0
+#define AUTO      'A'
+#define REG       'R'
+#define MEM       'T'
+#define PAR       'P'
+#define CONST     '#'
+#define INDEX     'I'
+#define LABEL     'L'
+#define OADD      '+'
+#define OSUB      '-'
+#define OASSIG    ':'
+#define OINC      ';'
+#define OMOD      '%'
+#define ODIV      '/'
+#define OSHL      'l'
+#define OSHR      'r'
+#define OBAND     '&'
+#define OBOR      '|'
+#define OBXOR     '^'
+#define OPTR      '@'
+#define OADDR     'a'
+#define OLT       '<'
+#define OGT       '>'
+#define OGE       ']'
+#define OLE       '['
+#define OEQ       '='
+#define ONE       '!'
+#define OOR       'o'
+#define OAND      'y'
+#define OCAST     'c'
+#define ONEG      '_'
+#define OCPL      '~'
+#define OCOMMA    ','
+#define ORET      'y'
+
+#define ADDABLE 10
+
+
+typedef struct symbol Symbol;
+typedef struct node Node;
+typedef struct inst Inst;
+typedef struct addr Addr;
+typedef struct type Type;
+
+struct type {
+	unsigned short size;
+	uint8_t align;
+	char letter;
+	uint8_t flags;
+};
+
+struct symbol {
+	unsigned short id;
+	char *name;
+	char kind;
+	bool public : 1;
+	bool extrn : 1;
+	bool index : 1;
+	union {
+		/* TODO: Admit inmediate of other type */
+		TINT imm;
+		struct {
+			Type type;
+			char sclass;
+			short off;
+		} v;
+		Inst *pc;
+		struct {
+			short locals;
+			short params;
+			Node **body;
+		} f;
+	} u;
+};
+
+struct node {
+	uint8_t op;
+	uint8_t subop;
+	Type type;
+	uint8_t complex;
+	uint8_t addable;
+	uint8_t reg;
+	Symbol *sym;
+	bool used : 1;
+	struct node *left, *right;
+};
+
+
+struct addr {
+	char kind;
+	union {
+		uint8_t reg;
+		TINT i;
+		Symbol *sym;
+	} u;
+};
+
+struct inst {
+	uint8_t op;
+	Addr from, to;
+	Symbol *label;
+	Inst *next, *prev;
+};
+
+enum nerrors {
+	EINTNUM,       /* too much internal identifiers */
+	EEXTNUM,       /* too much external identifiers */
+	EPARNUM,       /* too much parameters */
+	ENODEOV,       /* node overflow */
+	ESTACKO,       /* stack overflow */
+	ESTACKU,       /* stack underflow */
+	EEXPROV,       /* expression overflow */
+	ETYPERR,       /* incorrect type in expression */
+	EEXPBAL,       /* expression not balanced */
+	ESYNTAX,       /* syntax error */
+	ELNLINE,       /* line too long */
+	EFERROR,       /* error reading from file:%s*/
+	ENUMERR
+};
+
+enum {
+	LDW,
+	LDL,
+	LDH,
+	MOV,
+	LDI,
+	ADD,
+	PUSH,
+	POP,
+	RET,
+	NOP,
+	INC,
+	SUB,
+	DEC,
+	JP,
+	AND,
+	OR,
+	XOR,
+	CPL,
+	NEG
+};
+
+enum {
+	A = 1, B, C, D, E, H, L, IYL, IYH, NREGS,
+	AF = NREGS, HL, DE, BC, IY, NPAIRS,
+	SP = NPAIRS, IX
+};
+
+extern Symbol *curfun;
+extern Inst *prog, *pc;
+
+/* main.c */
+extern void error(unsigned nerror, ...);
+
+/* cgen.c */
+extern void addable(void);
+extern void generate(void);
+extern void apply(Node *(*fun)(Node *));
+
+/* parser.c */
+extern void parse(void);
+extern void prtree(Node *np);
+
+/* code.c */
+extern void code(uint8_t op, Node *to, Node *from);
+extern void inscode(uint8_t op, Addr *to, Addr *from);
+extern void writeout(void);
+extern void delcode(void);
+
+/* optm.c */
+extern void optimize(void);
+extern Node *imm(TINT i);
+
+/* peep.c */
+extern void peephole(void);
--- /dev/null
+++ b/cc2.old/cgen.c
@@ -1,0 +1,602 @@
+
+#include <assert.h>
+#include <inttypes.h>
+#include <stdlib.h>
+
+#include "../inc/cc.h"
+#include "cc2.h"
+
+static Symbol retlabel = {
+	.kind = LABEL
+};
+
+static Node *reguse[NPAIRS];
+static uint8_t upper[] = {[DE] = D, [HL] = H, [BC] = B,  [IY] = IYH};
+static uint8_t lower[] = {[DE] = E, [HL] = L, [BC] = C, [IY] = IYL};
+static uint8_t pair[] = {
+	[A] = A,
+	[H] = HL, [L] = HL, [HL] = HL,
+	[B] = BC, [C] = BC, [BC] = BC,
+	[D] = DE, [E] = DE, [DE] = DE,
+	[IYL] = IY, [IYH] = IY, [IY] = IY
+};
+
+static Node regs[] = {
+	[E] =  {
+		.op = REG,
+		.reg = E
+	},
+	[D] = {
+		.op = REG,
+		.reg = D
+	},
+	[H] = {
+		.op = REG,
+		.reg = H
+	},
+	[L] = {
+		.op = REG,
+		.reg = L
+	},
+	[C] = {
+		.op= REG,
+		.reg = C
+	},
+	[B] = {
+		.op= REG,
+		.reg = B
+	},
+	[A] = {
+		.op= REG,
+		.reg = A
+	},
+	[IYL] = {
+		.op = REG,
+		.reg = IYL
+	},
+	[IYH] = {
+		.op = REG,
+		.reg = IYH
+	},
+	[DE] = {
+		.op = REG,
+		.reg = DE
+	},
+	[HL] = {
+		.op = REG,
+		.reg = HL
+	},
+	[BC] = {
+		.op = REG,
+		.reg = BC
+	},
+	[IX] = {
+		.op = REG,
+		.reg = IX
+	},
+	[IY] = {
+		.op = REG,
+		.reg = IY
+	},
+	[SP] = {
+		.op = REG,
+		.reg = SP
+	}
+};
+
+static void moveto(Node *np, uint8_t reg);
+
+static void
+allocreg(Node *np)
+{
+	static uint8_t reg8[] = {A, B, C, D, E, H, L, IYL, IY, 0};
+	static uint8_t reg16[] = {BC, DE, IY, 0};
+	Node *r;
+	uint8_t *ary, *bp, c;
+
+	switch (np->type.size) {
+	case 1:
+		ary = reg8;
+		break;
+	case 2:
+		ary = reg16;
+		break;
+	default:
+		abort();
+	}
+	for (bp = ary; c = *bp; ++bp) {
+		r = reguse[c];
+		if (!r || r->used) {
+			moveto(np, c);
+			return;
+		}
+	}
+	/* TODO: What to do here? */
+	abort();
+}
+
+static void
+spill(uint8_t reg)
+{
+	Node *np, *r;
+	Symbol *sym;
+	uint8_t p, h, l;
+
+	if ((np = reguse[reg]) == NULL)
+		return;
+	sym = np->sym;
+	r = &regs[reg];
+
+	switch (np->type.size) {
+	case 1:
+		if (sym) {
+			code(LDL, np, r);
+			np->op = sym->kind;
+		} else {
+			allocreg(np);
+		}
+		break;
+	default:
+		abort();
+	}
+
+	reguse[reg] = NULL;
+	p = pair[reg];
+	l = lower[p];
+	h = upper[p];
+	if (reg >= NREGS)
+		reguse[l] = reguse[h] = NULL;
+	else if (!reguse[l] && !reguse[h])
+		reguse[p] = NULL;
+}
+
+static void
+moveto(Node *np, uint8_t reg)
+{
+	Node *r = &regs[reg], *u = reguse[reg];
+	char op = np->op;
+
+	if (u) {
+		Symbol *sym = np->sym;
+		if (sym && sym == u->sym)
+			return;
+		else if (!np->used)
+			spill(reg);
+	}
+
+	switch (np->type.size) {
+	case 1:
+		switch (op) {
+		case MEM:
+		case AUTO:
+			code(LDL, r, np);
+			break;
+		case CONST:
+		case INDEX:
+			code(LDI, r, np);
+			break;
+		case REG:
+			code(MOV, r, np);
+			break;
+		default:
+			abort();
+		}
+		break;
+	case 2:
+		switch (op) {
+		case CONST:
+			code(LDL, r, np);
+			break;
+		case AUTO:
+			code(LDL, &regs[lower[reg]], np);
+			code(LDH, &regs[upper[reg]], np);
+			break;
+		default:
+			abort();
+		}
+		reguse[upper[reg]] = reguse[lower[reg]] =  np;
+		break;
+	default:
+		abort();
+	}
+	reguse[pair[reg]] = reguse[reg] = np;
+	np->op = REG;
+	np->reg = reg;
+}
+
+static void
+accum(Node *np)
+{
+	switch (np->type.size) {
+	case 1:
+		moveto(np, A);
+		break;
+	case 2:
+		moveto(np, HL);
+		break;
+	default:
+		abort();
+	}
+}
+
+static void
+index(Node *np)
+{
+	Node *u = reguse[HL];
+	Symbol *sym;
+
+	if (u && u->sym) {
+		if (u->op == INDEX && np->sym == u->sym) {
+			np->op = INDEX;
+			return;
+		} else {
+			spill(HL);
+		}
+	}
+	code(LDI, &regs[HL], np);
+	if (sym = np->sym)
+		sym->index = 1;
+	np->op = INDEX;
+	reguse[HL] = reguse[H] = reguse[L] = np;
+}
+
+static void
+move(Node *np, Node *parent)
+{
+	assert(np->type.size == 1);
+	switch (parent->op) {
+	case OASSIG:
+		allocreg(np);
+		break;
+	case ONEG:
+	case OCPL:
+		switch (np->op) {
+		case REG:
+			if (np->reg == A)
+				break;
+			/* PASSTHROUGH */
+		case PAR:
+		case AUTO:
+		case CONST:
+		case MEM:
+		case INDEX:
+			accum(np);
+			break;
+		default:
+			abort();
+		}
+		break;
+	case OADD:
+	case OSUB:
+	case OBAND:
+	case OBOR:
+	case OBXOR:
+		switch (np->op) {
+		case PAR:
+		case AUTO:
+		case CONST:
+		case INDEX:
+		case REG:
+			return;
+		case MEM:
+			index(np);
+			break;
+		default:
+			abort();
+		}
+		break;
+	default:
+		abort();
+	}
+}
+
+static void
+conmute(Node *np)
+{
+	Node *p, *q;
+
+	p = np->left;
+	q = np->right;
+	np->left = q;
+	np->right = p;
+}
+
+static void
+add(Node *np)
+{
+	Node *lp = np->left, *rp = np->right, *a;
+	uint8_t op;
+
+	switch (np->type.size) {
+	case 1:
+		a = reguse[A];
+		if (a == lp)
+			goto update_a;
+		if (a == rp)
+			goto conmute1;
+		if (lp->op == CONST) {
+			accum(rp);
+			goto conmute1;
+		}
+		accum(lp);
+		goto update_a;
+	conmute1:
+		conmute(np);
+		lp = np->left, rp = np->right;
+	update_a:
+		move(rp, np);
+		switch (np->op) {
+		case OADD:
+			op = ADD;
+			break;
+		case OSUB:
+			op = SUB;
+			break;
+		case OBAND:
+			op = AND;
+			break;
+		case OBOR:
+			op = OR;
+			break;
+		case OBXOR:
+			op = XOR;
+			break;
+		default:
+			abort();
+		}
+		code(op, lp, rp);
+		lp->used = rp->used = 1;
+		np->op = REG;
+		np->reg = A;
+		reguse[A] = np;
+		break;
+	default:
+		abort();
+	}
+}
+
+static void
+assign(Node *np)
+{
+	Node *lp = np->left, *rp = np->right;
+	Symbol *sym = lp->sym;
+
+	switch (np->type.size) {
+	case 1:
+		switch (lp->op) {
+		case MEM:
+			if (sym && sym->index)
+				lp->op = INDEX;
+			/* PASSTROUGH */
+		case INDEX:
+		case AUTO:
+			if (rp->op != REG)
+				move(rp, np);
+			lp->reg = rp->reg;
+			code(LDL, lp, rp);
+			break;
+		case REG:
+			code(MOV, lp, rp);
+			break;
+		default:
+			abort();
+		}
+		break;
+	default:
+		abort();
+	}
+
+	np->op = REG;
+	np->reg = lp->reg;
+	np->sym = rp->sym = lp->sym;
+	np->used = rp->used = lp->used = 1;
+}
+
+static void
+ret(Node *np)
+{
+	static Node retnode = {
+		.op = LABEL,
+		.sym = &retlabel
+	};
+
+	if (np->left)
+		accum(np->left);
+	code(JP, &retnode, NULL);
+}
+
+static void
+nop(Node *np)
+{
+}
+
+static void
+cpl(Node *np)
+{
+
+	Node *lp = np->left;
+	uint8_t op;
+
+	switch (np->type.size) {
+	case 1:
+		move(lp, np);
+		switch (np->op) {
+		case OCPL:
+			op = CPL;
+			break;
+		case ONEG:
+			op = NEG;
+			break;
+		default:
+			abort();
+		}
+		code(op, lp, NULL);
+		lp->used = 1;
+		np->sym = lp->sym;
+		np->reg = lp->reg;
+		np->op = REG;
+		reguse[A] = np;
+		break;
+	default:
+		abort();
+	}
+}
+
+static void
+cast(Node *np)
+{
+	Node *lp = np->left;
+	uint8_t reg;
+
+	if (lp->type.size != np->type.size)
+		abort();
+	lp->used = 1;
+	np->sym = lp->sym;
+	if ((np->op = lp->op) == REG) {
+		reg = lp->reg;
+		np->reg = reg;
+		reguse[pair[reg]] = reguse[reg] = np;
+	}
+}
+
+static void (*opnodes[])(Node *) = {
+	[OADD] = add,
+	[OSUB] = add,
+	[OASSIG] = assign,
+	[ORET] = ret,
+	[MEM] = nop,
+	[REG] = nop,
+	[AUTO] = nop,
+	[CONST] = nop,
+	[PAR] = nop,
+	[OBOR] = add,
+	[OBAND] = add,
+	[OBXOR] = add,
+	[OCPL] = cpl,
+	[ONEG] = cpl,
+	[OCAST] = cast
+};
+
+static void
+cgen(Node *np)
+{
+	Node *lp, *rp;
+
+	if (!np)
+		return;
+
+	if (np->addable >= ADDABLE)
+		return;
+
+	lp = np->left;
+	rp = np->right;
+	if (!lp) {
+		cgen(rp);
+	} else if (!rp) {
+		cgen(lp);
+	} else {
+		Node *p, *q;
+		if (lp->complex > rp->complex)
+			p = lp, q = rp;
+		else
+			p = rp, q = lp;
+		cgen(p);
+		cgen(q);
+	}
+	(*opnodes[np->op])(np);
+}
+
+void
+generate(void)
+{
+	uint8_t size = curfun->u.f.locals;
+	static short id = 1000;
+	Node **stmt, *np;
+
+	retlabel.id = id++;
+
+	code(PUSH, NULL, &regs[IX]);
+	code(MOV, &regs[IX], &regs[SP]);
+	if (size > 6) {
+		code(MOV, &regs[HL], imm(-size));
+		code(ADD, &regs[HL], &regs[SP]);
+		code(MOV, &regs[SP], &regs[HL]);
+	} else {
+		for (; size != 0; size-= 2)
+			code(PUSH, NULL, &regs[HL]);
+	}
+
+	for (stmt = curfun->u.f.body; np = *stmt; ++stmt)
+		cgen(np);
+
+	code(MOV, &regs[SP], &regs[IX]);
+	retlabel.u.pc = pc;
+	pc->label = &retlabel;
+	code(POP, &regs[IX], NULL);
+	code(RET, NULL, NULL);
+}
+
+/*
+ * This is strongly influenced by
+ * http://plan9.bell-labs.com/sys/doc/compiler.ps (/sys/doc/compiler.ps)
+ * calculate addresability as follows
+ *     AUTO => 11          value+fp
+ *     REGISTER => 13      register
+ *     STATIC => 12        (value)
+ *     CONST => 20         $value
+ */
+Node *
+genaddable(Node *np)
+{
+	Node *lp, *rp;
+
+	if (!np)
+		return np;
+
+	np->complex = 0;
+	np->addable = 0;
+	lp = np->left;
+	rp = np->right;
+	switch (np->op) {
+	case AUTO:
+		np->addable = 11;
+		break;
+	case REG:
+		np->addable = 13;
+		break;
+	case MEM:
+		np->addable = 12;
+		break;
+	case CONST:
+		np->addable = 20;
+		break;
+	default:
+		if (lp)
+			genaddable(lp);
+		if (rp)
+			genaddable(rp);
+		break;
+	}
+
+	if (np->addable > 10)
+		return np;
+	if (lp)
+		np->complex = lp->complex;
+	if (rp) {
+		int8_t d = np->complex - rp->complex;
+
+		if (d == 0)
+			++np->complex;
+		else if (d < 0)
+			np->complex = rp->complex;
+	}
+	if (np->complex == 0)
+		++np->complex;
+	return np;
+}
+
+void
+addable(void)
+{
+	apply(genaddable);
+}
--- /dev/null
+++ b/cc2.old/code.c
@@ -1,0 +1,229 @@
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <stdio.h>
+
+#include "../inc/cc.h"
+#include "cc2.h"
+
+static char *regnames[] = {
+	[AF] = "AF",
+	[HL] = "HL", [DE] = "DE", [BC] = "BC",
+	[IX] = "IX", [IY] = "IY", [SP] = "SP",
+	[A]  = "A",
+	[B]  = "B", [C]  = "C",
+	[D]  = "D",  [E]  = "E",
+	[H]  = "H",  [L]  = "L",
+	[IYL]= "IYL",[IYH]= "IYH"
+};
+
+static void inst0(void), inst1(void), inst2(void);
+
+static void (*instcode[])(void) = {
+	[LDW] = inst2,
+	[LDL] = inst2,
+	[LDH] = inst2,
+	[LDI] = inst2,
+	[MOV] = inst2,
+	[ADD] = inst2,
+	[PUSH] = inst1,
+	[POP] = inst1,
+	[RET] = inst0,
+	[NOP] = inst0,
+	[INC] = inst1,
+	[SUB] = inst2,
+	[DEC] = inst1,
+	[JP] = inst1,
+	[AND] = inst2,
+	[OR] = inst2,
+	[XOR] = inst2,
+	[CPL] = inst1,
+	[NEG] = inst1
+
+};
+
+static char *insttext[] = {
+	[LDW] = "LD",
+	[LDL] = "LD",
+	[LDH] = "LD",
+	[LDI] = "LD",
+	[MOV] = "LD",
+	[ADD] = "ADD",
+	[PUSH] = "PUSH",
+	[POP] = "POP",
+	[RET] = "RET",
+	[NOP] = "NOP",
+	[INC] = "INC",
+	[SUB] = "SUB",
+	[DEC] = "DEC",
+	[JP] = "JP",
+	[AND] = "AND",
+	[OR] = "OR",
+	[XOR] = "XOR",
+	[CPL] = "CPL",
+	[NEG] = "NEG"
+};
+
+Inst *pc, *prog;
+
+static void
+nextpc(void)
+{
+	Inst *new;
+
+	new = xmalloc(sizeof(*new));
+
+	if (!pc) {
+		new->next = NULL;
+		prog = new;
+	} else {
+		new->next = pc->next;
+		pc->next = new;
+	}
+
+	new->prev = pc;
+	new->to.kind = NONE;
+	new->from.kind = NONE;
+	pc = new;
+}
+
+void
+addr(char op, Node *np, Addr *addr)
+{
+	switch (addr->kind = np->op) {
+	case REG:
+		addr->u.reg = np->reg;
+		break;
+	case CONST:
+		addr->u.i = np->sym->u.imm;
+		break;
+	case AUTO:
+		addr->u.i = np->sym->u.v.off;
+		break;
+	case LABEL:
+	case MEM:
+		addr->u.sym = np->sym;
+		break;
+	case INDEX:
+		break;
+	default:
+		abort();
+	}
+}
+
+void
+code(uint8_t op, Node *to, Node *from)
+{
+
+	nextpc();
+	if (from)
+		addr(op, from, &pc->from);
+	if (to)
+		addr(op, to, &pc->to);
+	pc->op = op;
+}
+
+void
+inscode(uint8_t op, Addr *to, Addr *from)
+{
+	nextpc();
+	if (from)
+		pc->from = *from;
+	if (to)
+		pc->to = *to;
+	pc->op = op;
+}
+
+void
+delcode(void)
+{
+	Inst *prev = pc->prev, *next = pc->next;
+
+	free(pc);
+	if (!prev) {
+		pc = next;
+		prog = NULL;
+	} else {
+		pc = prev;
+		prev->next = next;
+		if (next)
+			next->prev = prev;
+	}
+}
+
+void
+writeout(void)
+{
+	if (!prog)
+		return;
+
+	for (pc = prog; pc; pc = pc->next) {
+		if (pc->label)
+			printf("L%d:", pc->label->id);
+		(*instcode[pc->op])();
+	}
+}
+
+static void
+addr2txt(uint8_t op, Addr *a)
+{
+	Symbol *sym;
+
+	switch (a->kind) {
+	case REG:
+		fputs(regnames[a->u.reg], stdout);
+		break;
+	case CONST:
+		printf("%d", a->u.i);
+		break;
+	case PAR:
+	case AUTO:
+		printf("(IX%+d)", a->u.i);
+		break;
+	case LABEL:
+		sym = a->u.sym;
+		printf("L%d", sym->id);
+		break;
+	case INDEX:
+		fputs("(HL)", stdout);
+		break;
+	case MEM:
+		sym = a->u.sym;
+		if (sym->name)
+			printf((op == LDI) ? "%s" : "(%s)", sym->name);
+		else
+			printf((op == LDI) ? "T%u" : "(T%u)", sym->id);
+		break;
+	default:
+		abort();
+	}
+}
+
+static void
+inst0(void)
+{
+	printf("\t%s\n", insttext[pc->op]);
+}
+
+static void
+inst1(void)
+{
+	uint8_t op = pc->op;
+
+	printf("\t%s\t", insttext[op]);
+	addr2txt(op, (pc->to.kind != NONE) ? &pc->to : &pc->from);
+	putchar('\n');
+}
+
+static void
+inst2(void)
+{
+	uint8_t op = pc->op;
+
+	printf("\t%s\t", insttext[op]);
+	addr2txt(op, &pc->to);
+	putchar(',');
+	addr2txt(op, &pc->from);
+	putchar('\n');
+}
--- /dev/null
+++ b/cc2.old/generror
@@ -1,0 +1,19 @@
+
+BEGIN {
+	print "char *errlist[] = {"
+}
+/^enum nerrors \{/ {
+	inhome = 1
+}
+inhome && /E[A-Z]*, / {
+	sub(/,/, "", $1)
+	printf("\t[%s] = \"", $1)
+	for (i = 3; i < NF-1; ++i)
+		printf("%s ", $i)
+	printf("%s\",\n", $(NF-1));
+}
+inhome && /^}/ {
+	print "};"
+	inhome = 0
+}
+
--- /dev/null
+++ b/cc2.old/main.c
@@ -1,0 +1,56 @@
+
+#include <stdarg.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "../inc/cc.h"
+
+#include "cc2.h"
+#include "error.h"
+
+char odebug;
+
+void
+error(unsigned nerror, ...)
+{
+	va_list va;
+	va_start(va, nerror);
+	if (nerror >= ENUMERR)
+		fprintf(stderr, "incorrect error number '%d'", nerror);
+	else
+		vfprintf(stderr, errlist[nerror], va);
+	va_end(va);
+	putc('\n', stderr);
+	exit(1);
+}
+
+bool
+moreinput(void)
+{
+	int c;
+
+repeat:
+	if (feof(stdin))
+		return 0;
+	if ((c = getchar()) == '\n' || c == EOF)
+		goto repeat;
+	ungetc(c, stdin);
+	return 1;
+}
+
+int
+main(void)
+{
+	fputs("cc2 is not updated with the output of cc1", stderr);
+	exit(1);
+	while (moreinput()) {
+		parse();
+		optimize();
+		addable();
+		generate();
+		peephole();
+		writeout();
+	}
+	return 0;
+}
--- /dev/null
+++ b/cc2.old/optm.c
@@ -1,0 +1,51 @@
+
+#include <stddef.h>
+#include <inttypes.h>
+
+#include "../inc/cc.h"
+#include "cc2.h"
+
+
+#include <stdio.h>
+
+static Node *
+optcasts(Node *np, Type *tp)
+{
+	if (!np)
+		return NULL;
+
+repeat:
+	switch (np->op) {
+	case OCAST:
+		/* TODO: be careful with the sign */
+		if (np->type.flags&INTF && np->type.size >= tp->size) {
+			np = np->left;
+			goto repeat;
+		}
+		break;
+	case OASSIG:
+		tp = &np->type;
+		break;
+	default:
+		if (np->type.size > tp->size)
+			np->type = *tp;
+		break;
+	}
+
+	np->left = optcasts(np->left, tp);
+	np->right = optcasts(np->right, tp);
+	return np;
+}
+
+static Node *
+opt(Node *np)
+{
+	np = optcasts(np, &np->type);
+	return np;
+}
+
+void
+optimize(void)
+{
+	apply(opt);
+}
--- /dev/null
+++ b/cc2.old/parser.c
@@ -1,0 +1,603 @@
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../inc/cc.h"
+#include "../inc/sizes.h"
+
+#include "cc2.h"
+
+#define MAXLINE 200
+#define NR_STACKSIZ 32
+#define NR_NODEPOOL 128
+#define NR_EXPRESSIONS 64
+
+enum {
+	LOCAL, GLOBAL, PARAMETER
+};
+
+Symbol *curfun;
+static Node *stack[NR_STACKSIZ], **stackp;
+static Node *listexp[NR_EXPRESSIONS], **listp;
+static Node nodepool[NR_NODEPOOL], *newp;
+
+
+static Type Funct = {
+	.letter = L_FUNCTION,
+};
+
+static Type l_int8 = {
+	.letter = L_INT8,
+	.size = 1,
+	.align = 2,
+	.flags = SIGNF | INTF
+};
+
+static Type l_int16 = {
+	.letter = L_INT16,
+	.size = 2,
+	.align = 2,
+	.flags = SIGNF | INTF
+
+};
+
+static Type l_int32 = {
+	.letter = L_INT32,
+	.size = 4,
+	.align = 4,
+	.flags = SIGNF | INTF
+
+};
+
+static Type l_int64 = {
+	.letter = L_INT64,
+	.size = 8,
+	.align = 8,
+	.flags = SIGNF | INTF
+
+};
+
+static Type l_uint8 = {
+	.letter = L_UINT8,
+	.size = 1,
+	.align = 2,
+	.flags =  INTF
+};
+
+static Type l_uint16 = {
+	.letter = L_UINT16,
+	.size = 2,
+	.align = 2,
+	.flags =  INTF
+};
+
+static Type l_uint32 = {
+	.letter = L_UINT32,
+	.size = 4,
+	.align = 4,
+	.flags =  INTF
+};
+
+static Type l_uint64 = {
+	.letter = L_UINT64,
+	.size = 8,
+	.align = 8,
+	.flags =  INTF
+};
+
+static void cast(char *), operator(char *), assignment(char *), increment(char *),
+            globvar(char *), localvar(char *), paramvar(char *), label(char *),
+            immediate(char *), unary(char *), oreturn(char *);
+
+/*TODO: Remove hardcoded symbols */
+
+static void (*optbl[])(char *) = {
+	[L_INT8] = cast,
+	[L_INT16] = cast,
+	[L_INT32] = cast,
+	[L_INT64] = cast,
+	[L_UINT8] = cast,
+	[L_UINT16] = cast,
+	[L_UINT32] = cast,
+	[L_UINT64] = cast,
+	[L_BOOL] = cast,
+	[L_FLOAT] = cast,
+	[L_DOUBLE] = cast,
+	[L_LDOUBLE] = cast,
+	[L_POINTER] = cast,
+	[L_VOID] = cast,
+	['+'] = operator,
+	['%'] = operator,
+	['-'] = operator,
+	['*'] = operator,
+	['/'] = operator,
+	['l'] = operator,
+	['r'] = operator,
+	['&'] = operator,
+	['|'] = operator,
+	['^'] = operator,
+	[':'] = assignment,
+	[';'] = increment,
+	['Y'] = globvar,
+	['A'] = localvar,
+	['K'] = localvar,
+	['T'] = localvar,
+	['G'] = globvar,
+	['P'] = paramvar,
+	['L'] = label,
+	['#'] = immediate,
+	['@'] = unary,
+	['a'] = unary,
+	['<'] = operator,
+	['>'] = operator,
+	[']'] = operator,
+	['['] = operator,
+	['='] = operator,
+	['!'] = unary,
+	['y'] = oreturn,
+	['j'] = NULL,
+	['o'] = operator,
+	['_'] = unary,
+	['~'] = unary,
+	[','] = operator,
+	['\177'] = NULL
+};
+
+static void
+prnode(Node *np)
+{
+	if (np->left)
+		prnode(np->left);
+	if (np->right)
+		prnode(np->right);
+	fprintf(stderr, "\t%c%c", np->op, np->type.letter);
+}
+
+void
+prtree(Node *np)
+{
+	prnode(np);
+	putc('\n', stderr);
+}
+
+void
+apply(Node *(*fun)(Node *))
+{
+	Node **list, *np;
+
+	for (list = curfun->u.f.body; np = *list; ++list)
+		*list++ = (*fun)(np);
+}
+
+static Symbol *
+parameter(char *num)
+{
+	static Symbol tbl[NR_FUNPARAM];
+	Symbol *sym;
+	unsigned i = atoi(num);
+
+	if (!curfun)
+		error(ESYNTAX);
+	if (i >= NR_FUNPARAM)
+		error(EPARNUM);
+	sym = &tbl[i];
+	sym->id = i;
+	return sym;
+}
+
+static Symbol *
+local(char *num)
+{
+	static Symbol tbl[NR_INT_IDENT];
+	Symbol *sym;
+	unsigned i = atoi(num);
+
+	if (!curfun)
+		error(ESYNTAX);
+	if (i >= NR_INT_IDENT)
+		error(EINTNUM);
+	sym = &tbl[i];
+	sym->id = i;
+	return sym;
+}
+
+static Symbol *
+global(char *num)
+{
+	static Symbol tbl[NR_EXT_IDENT];
+	Symbol *sym;
+	unsigned i = atoi(num);
+
+	if (i >= NR_EXT_IDENT)
+		error(EEXTNUM);
+
+	sym = &tbl[i];
+	sym->id = i;
+	return sym;
+}
+
+static Node *
+newnode(void)
+{
+	if (newp == &nodepool[NR_NODEPOOL])
+		error(ENODEOV);
+	return newp++;
+}
+
+Node *
+imm(TINT i)
+{
+	Node *np = newnode();
+
+	np->op = CONST;
+	np->type = l_int16;
+	/* FIX: memory leak */
+	np->sym = xmalloc(sizeof(Symbol));
+	np->sym->u.imm = i;
+	np->left = np->right = NULL;
+	return np;
+}
+
+static void
+push(Node *np)
+{
+	if (stackp == &stack[NR_STACKSIZ])
+		error(ESTACKO);
+	*stackp++ = np;
+}
+
+static Node *
+pop(void)
+{
+	if (stackp == stack)
+		error(ESTACKU);
+	return *--stackp;
+}
+
+static Type *
+gettype(char *type)
+{
+	switch (type[0]) {
+	case L_INT8:
+		return &l_int8;
+	case L_INT16:
+		return &l_int16;
+	case L_INT32:
+		return &l_int32;
+	case L_INT64:
+		return &l_int64;
+	case L_UINT8:
+		return &l_uint8;
+	case L_UINT16:
+		return &l_uint16;
+	case L_UINT32:
+		return &l_uint32;
+	case L_UINT64:
+		return &l_uint64;
+	case L_FUNCTION:
+		return &Funct;
+	default:
+		error(ETYPERR);
+	}
+}
+
+static Symbol *
+symbol(uint8_t t, char *token)
+{
+	Symbol *sym;
+	static Symbol *(*tbl[3])(char *)= {
+		[LOCAL] = local,
+		[GLOBAL] = global,
+		[PARAMETER] = parameter
+	};
+	sym = (*tbl[t])(token+1);
+	sym->kind = *token;
+	return sym;
+}
+
+static void
+variable(uint8_t t, char *token)
+{
+	Node *np = newnode();
+	Symbol *sym = symbol(t, token);
+
+	np->sym = sym;
+	np->op = sym->u.v.sclass;
+	np->type = sym->u.v.type;
+	np->left = np->right = NULL;
+	push(np);
+}
+
+static void
+localvar(char *token)
+{
+	variable(LOCAL, token);
+}
+
+static void
+globvar(char *token)
+{
+	variable(GLOBAL, token);
+}
+
+static void
+paramvar(char *token)
+{
+	variable(PARAMETER, token);
+}
+
+static void
+immediate(char *token)
+{
+	/* TODO: check type of immediate */
+	push(imm(atoi(token+2)));
+}
+
+static void
+unary(char *token)
+{
+	Node *np = newnode();
+
+	np->right = NULL;
+	np->left = pop();
+	np->type = *gettype(token+1);
+	np->op = token[0];
+	push(np);
+}
+
+static void
+operator(char *token)
+{
+	Node *np = newnode();
+
+	np->right = pop();
+	np->left = pop();
+	np->type = *gettype(token+1);
+	np->op = token[0];
+	push(np);
+}
+
+static void
+label(char *token)
+{
+	Node *np = newnode();
+
+	np->left = np->right = NULL;
+	np->op = LABEL;
+	np->sym = local(token);
+	push(np);
+}
+
+static void
+increment(char *token)
+{
+	Node *np = newnode();
+
+	np->right = pop();
+	np->left = pop();
+	np->type = *gettype(token+2);
+	np->op = token[0];
+	switch (np->subop = token[1]) {
+	case '-': case '+':
+		push(np);
+		break;
+	default:
+		error(ESYNTAX);
+	}
+}
+
+static void
+assignment(char *token)
+{
+	Node *np = newnode();
+
+	np->right = pop();
+	np->left = pop();
+	np->op = *token;
+	switch (*++token) {
+	case OADD: case OSUB: case OINC:  case OMOD: case ODIV:
+	case OSHL: case OSHR: case OBAND: case OBOR: case OBXOR:
+		np->subop = *++token;
+	default:
+		np->type = *gettype(token);
+		break;
+	}
+	push(np);
+}
+
+static void
+cast(char *token)
+{
+	Node *np = newnode();
+
+	np->right = NULL;
+	np->left = pop();
+	np->op = OCAST;
+	np->type = *gettype(token+1);
+	push(np);
+}
+
+static void
+expr(char *token)
+{
+	void (*fun)(char *);
+	unsigned c;
+
+	do {
+		if ((c = token[0]) > 0x7f || (fun = optbl[c]) == NULL)
+			error(ESYNTAX);
+		(*fun)(token);
+	} while (token = strtok(NULL, "\t"));
+}
+
+static void
+expression(char *token)
+{
+	Node *np;
+
+	if (!curfun)
+		error(ESYNTAX);
+
+	expr(token);
+
+	np = pop();
+	if (stackp != stack)
+		error(EEXPBAL);
+	if (listp == &listexp[NR_EXPRESSIONS])
+		error(EEXPROV);
+	*listp++ = np;
+}
+
+static void
+oreturn(char *token)
+{
+	Node *np = newnode(), *lp;
+
+	np->op = token[0];
+
+	if (token = strtok(NULL, "\t")) {
+		expr(token);
+		lp = pop();
+		np->left = lp;
+		np->type = lp->type;
+	} else {
+		np->left = NULL;
+	}
+	np->right = NULL;
+	push(np);
+}
+
+static void
+deflabel(char *token)
+{
+	Symbol *sym;
+
+	if (!curfun)
+		error(ESYNTAX);
+	sym = local(token);
+}
+
+static Symbol *
+declaration(uint8_t t, char class, char *token)
+{
+	Symbol *sym = symbol(t, token);
+	char *s;
+
+	free(sym->name);
+	memset(sym, 0, sizeof(*sym));
+	sym->u.v.sclass = class;
+
+	if ((s = strtok(NULL, "\t")) == NULL)
+		error(ESYNTAX);
+	sym->u.v.type = *gettype(s);
+	if ((s = strtok(NULL, "\t")) != NULL)
+		sym->name = xstrdup(s);
+
+	return sym;
+}
+
+static void
+globdcl(char *token)
+{
+	Symbol *sym = declaration(GLOBAL, MEM, token);
+
+	switch (token[0]) {
+	case 'X':
+		sym->extrn = 1;
+		break;
+	case 'G':
+		sym->public = 1;
+		break;
+	}
+
+	if (sym->u.v.type.letter != L_FUNCTION)
+		return;
+
+	if (curfun)
+		error(ESYNTAX);
+
+	curfun = sym;
+	sym->u.f.body = listp = listexp;
+	newp = nodepool;
+}
+
+static void
+paramdcl(char *token)
+{
+	Symbol *sym = declaration(PARAMETER, AUTO, token);
+	sym->u.v.off = -curfun->u.f.params;
+	curfun->u.f.params += sym->u.v.type.size;
+}
+
+static void
+localdcl(char *token)
+{
+	Symbol *sym = declaration(LOCAL, token[0], token);
+	char sclass = *token;
+
+	if (sclass == 'A' || sclass == 'R') {
+		uint8_t size = sym->u.v.type.size;
+		/* stack elements are 2 byte multiple */
+		if (size == 1)
+			++size;
+		curfun->u.f.locals += size;
+		sym->u.v.off = curfun->u.f.locals;
+	}
+}
+
+void
+parse(void)
+{
+	void (*fun)(char *tok);
+	uint8_t len;
+	int c;
+	char line[MAXLINE];
+
+	curfun = NULL;
+	stackp = stack;
+	listp = listexp;
+	newp = nodepool;
+
+	for (;;) {
+		switch (c = getchar()) {
+		case 'L':
+			fun = deflabel;
+			break;
+		case '\t':
+			fun = expression;
+			break;
+		case 'S':
+			/* TODO: struct */
+			break;
+		case 'P':
+			fun = paramdcl;
+			break;
+		case 'A': case 'R': case 'T':
+			fun = localdcl;
+			break;
+		case 'Y': case 'G':
+			fun = globdcl;
+			break;
+		case '}':
+			if (curfun)
+				return;
+		default:
+			goto syntax_error;
+		}
+
+		ungetc(c, stdin);
+		if (!fgets(line, sizeof(line), stdin))
+			break;
+		len = strlen(line);
+		if (line[len-1] != '\n')
+			error(ELNLINE);
+		line[len-1] = '\0';
+		(*fun)(strtok(line, "\t"));
+	}
+
+syntax_error:
+	error(ESYNTAX);
+}
--- /dev/null
+++ b/cc2.old/peep.c
@@ -1,0 +1,39 @@
+
+#include <inttypes.h>
+#include <stddef.h>
+
+#include "../inc/cc.h"
+#include "cc2.h"
+
+void
+peephole(void)
+{
+	Addr to, from;
+	TINT i;
+	uint8_t op;
+
+	for (pc = prog; pc; pc = pc->next) {
+		to = pc->to;
+		from = pc->from;
+
+		switch (pc->op) {
+		case SUB:
+		case ADD:
+			if (from.kind == CONST) {
+				if ((i = from.u.i) == 0 || i < 4) {
+					delcode();
+					op = (pc->op == ADD) ? INC : DEC;
+
+					while (i--)
+						inscode(op, &to, NULL);
+				}
+			/* TODO: More optimizations (ex: -1) */
+			}
+			break;
+		case JP:
+			if (to.u.sym->u.pc == pc->next)
+				delcode();
+			break;
+		}
+	}
+}
--- a/cc2/Makefile
+++ /dev/null
@@ -1,23 +1,0 @@
-.POSIX:
-
-include ../config.mk
-
-OBJS = main.o parser.o cgen.o code.o optm.o peep.o
-
-all: cc2
-
-
-$(OBJS): ../inc/cc.h ../inc/sizes.h cc2.h
-main.o: error.h
-
-error.h: cc2.h
-	rm -f $@; trap 'rm -f $$$$.h' EXIT INT QUIT
-	awk -f generror cc2.h > $$$$.h && mv $$$$.h $@
-
-cc2: $(OBJS) ../lib/libcc.a
-	$(CC) $(LDFLAGS) $(OBJS) ../lib/libcc.a -o $@
-
-clean:
-	rm -f $(OBJS)
-	rm -f cc2 error.h
-
--- a/cc2/cc2.h
+++ /dev/null
@@ -1,179 +1,0 @@
-
-#define SIGNF 1
-#define INTF  2
-
-#define NONE       0
-#define AUTO      'A'
-#define REG       'R'
-#define MEM       'T'
-#define PAR       'P'
-#define CONST     '#'
-#define INDEX     'I'
-#define LABEL     'L'
-#define OADD      '+'
-#define OSUB      '-'
-#define OASSIG    ':'
-#define OINC      ';'
-#define OMOD      '%'
-#define ODIV      '/'
-#define OSHL      'l'
-#define OSHR      'r'
-#define OBAND     '&'
-#define OBOR      '|'
-#define OBXOR     '^'
-#define OPTR      '@'
-#define OADDR     'a'
-#define OLT       '<'
-#define OGT       '>'
-#define OGE       ']'
-#define OLE       '['
-#define OEQ       '='
-#define ONE       '!'
-#define OOR       'o'
-#define OAND      'y'
-#define OCAST     'c'
-#define ONEG      '_'
-#define OCPL      '~'
-#define OCOMMA    ','
-#define ORET      'y'
-
-#define ADDABLE 10
-
-
-typedef struct symbol Symbol;
-typedef struct node Node;
-typedef struct inst Inst;
-typedef struct addr Addr;
-typedef struct type Type;
-
-struct type {
-	unsigned short size;
-	uint8_t align;
-	char letter;
-	uint8_t flags;
-};
-
-struct symbol {
-	unsigned short id;
-	char *name;
-	char kind;
-	bool public : 1;
-	bool extrn : 1;
-	bool index : 1;
-	union {
-		/* TODO: Admit inmediate of other type */
-		TINT imm;
-		struct {
-			Type type;
-			char sclass;
-			short off;
-		} v;
-		Inst *pc;
-		struct {
-			short locals;
-			short params;
-			Node **body;
-		} f;
-	} u;
-};
-
-struct node {
-	uint8_t op;
-	uint8_t subop;
-	Type type;
-	uint8_t complex;
-	uint8_t addable;
-	uint8_t reg;
-	Symbol *sym;
-	bool used : 1;
-	struct node *left, *right;
-};
-
-
-struct addr {
-	char kind;
-	union {
-		uint8_t reg;
-		TINT i;
-		Symbol *sym;
-	} u;
-};
-
-struct inst {
-	uint8_t op;
-	Addr from, to;
-	Symbol *label;
-	Inst *next, *prev;
-};
-
-enum nerrors {
-	EINTNUM,       /* too much internal identifiers */
-	EEXTNUM,       /* too much external identifiers */
-	EPARNUM,       /* too much parameters */
-	ENODEOV,       /* node overflow */
-	ESTACKO,       /* stack overflow */
-	ESTACKU,       /* stack underflow */
-	EEXPROV,       /* expression overflow */
-	ETYPERR,       /* incorrect type in expression */
-	EEXPBAL,       /* expression not balanced */
-	ESYNTAX,       /* syntax error */
-	ELNLINE,       /* line too long */
-	EFERROR,       /* error reading from file:%s*/
-	ENUMERR
-};
-
-enum {
-	LDW,
-	LDL,
-	LDH,
-	MOV,
-	LDI,
-	ADD,
-	PUSH,
-	POP,
-	RET,
-	NOP,
-	INC,
-	SUB,
-	DEC,
-	JP,
-	AND,
-	OR,
-	XOR,
-	CPL,
-	NEG
-};
-
-enum {
-	A = 1, B, C, D, E, H, L, IYL, IYH, NREGS,
-	AF = NREGS, HL, DE, BC, IY, NPAIRS,
-	SP = NPAIRS, IX
-};
-
-extern Symbol *curfun;
-extern Inst *prog, *pc;
-
-/* main.c */
-extern void error(unsigned nerror, ...);
-
-/* cgen.c */
-extern void addable(void);
-extern void generate(void);
-extern void apply(Node *(*fun)(Node *));
-
-/* parser.c */
-extern void parse(void);
-extern void prtree(Node *np);
-
-/* code.c */
-extern void code(uint8_t op, Node *to, Node *from);
-extern void inscode(uint8_t op, Addr *to, Addr *from);
-extern void writeout(void);
-extern void delcode(void);
-
-/* optm.c */
-extern void optimize(void);
-extern Node *imm(TINT i);
-
-/* peep.c */
-extern void peephole(void);
--- a/cc2/cgen.c
+++ /dev/null
@@ -1,602 +1,0 @@
-
-#include <assert.h>
-#include <inttypes.h>
-#include <stdlib.h>
-
-#include "../inc/cc.h"
-#include "cc2.h"
-
-static Symbol retlabel = {
-	.kind = LABEL
-};
-
-static Node *reguse[NPAIRS];
-static uint8_t upper[] = {[DE] = D, [HL] = H, [BC] = B,  [IY] = IYH};
-static uint8_t lower[] = {[DE] = E, [HL] = L, [BC] = C, [IY] = IYL};
-static uint8_t pair[] = {
-	[A] = A,
-	[H] = HL, [L] = HL, [HL] = HL,
-	[B] = BC, [C] = BC, [BC] = BC,
-	[D] = DE, [E] = DE, [DE] = DE,
-	[IYL] = IY, [IYH] = IY, [IY] = IY
-};
-
-static Node regs[] = {
-	[E] =  {
-		.op = REG,
-		.reg = E
-	},
-	[D] = {
-		.op = REG,
-		.reg = D
-	},
-	[H] = {
-		.op = REG,
-		.reg = H
-	},
-	[L] = {
-		.op = REG,
-		.reg = L
-	},
-	[C] = {
-		.op= REG,
-		.reg = C
-	},
-	[B] = {
-		.op= REG,
-		.reg = B
-	},
-	[A] = {
-		.op= REG,
-		.reg = A
-	},
-	[IYL] = {
-		.op = REG,
-		.reg = IYL
-	},
-	[IYH] = {
-		.op = REG,
-		.reg = IYH
-	},
-	[DE] = {
-		.op = REG,
-		.reg = DE
-	},
-	[HL] = {
-		.op = REG,
-		.reg = HL
-	},
-	[BC] = {
-		.op = REG,
-		.reg = BC
-	},
-	[IX] = {
-		.op = REG,
-		.reg = IX
-	},
-	[IY] = {
-		.op = REG,
-		.reg = IY
-	},
-	[SP] = {
-		.op = REG,
-		.reg = SP
-	}
-};
-
-static void moveto(Node *np, uint8_t reg);
-
-static void
-allocreg(Node *np)
-{
-	static uint8_t reg8[] = {A, B, C, D, E, H, L, IYL, IY, 0};
-	static uint8_t reg16[] = {BC, DE, IY, 0};
-	Node *r;
-	uint8_t *ary, *bp, c;
-
-	switch (np->type.size) {
-	case 1:
-		ary = reg8;
-		break;
-	case 2:
-		ary = reg16;
-		break;
-	default:
-		abort();
-	}
-	for (bp = ary; c = *bp; ++bp) {
-		r = reguse[c];
-		if (!r || r->used) {
-			moveto(np, c);
-			return;
-		}
-	}
-	/* TODO: What to do here? */
-	abort();
-}
-
-static void
-spill(uint8_t reg)
-{
-	Node *np, *r;
-	Symbol *sym;
-	uint8_t p, h, l;
-
-	if ((np = reguse[reg]) == NULL)
-		return;
-	sym = np->sym;
-	r = &regs[reg];
-
-	switch (np->type.size) {
-	case 1:
-		if (sym) {
-			code(LDL, np, r);
-			np->op = sym->kind;
-		} else {
-			allocreg(np);
-		}
-		break;
-	default:
-		abort();
-	}
-
-	reguse[reg] = NULL;
-	p = pair[reg];
-	l = lower[p];
-	h = upper[p];
-	if (reg >= NREGS)
-		reguse[l] = reguse[h] = NULL;
-	else if (!reguse[l] && !reguse[h])
-		reguse[p] = NULL;
-}
-
-static void
-moveto(Node *np, uint8_t reg)
-{
-	Node *r = &regs[reg], *u = reguse[reg];
-	char op = np->op;
-
-	if (u) {
-		Symbol *sym = np->sym;
-		if (sym && sym == u->sym)
-			return;
-		else if (!np->used)
-			spill(reg);
-	}
-
-	switch (np->type.size) {
-	case 1:
-		switch (op) {
-		case MEM:
-		case AUTO:
-			code(LDL, r, np);
-			break;
-		case CONST:
-		case INDEX:
-			code(LDI, r, np);
-			break;
-		case REG:
-			code(MOV, r, np);
-			break;
-		default:
-			abort();
-		}
-		break;
-	case 2:
-		switch (op) {
-		case CONST:
-			code(LDL, r, np);
-			break;
-		case AUTO:
-			code(LDL, &regs[lower[reg]], np);
-			code(LDH, &regs[upper[reg]], np);
-			break;
-		default:
-			abort();
-		}
-		reguse[upper[reg]] = reguse[lower[reg]] =  np;
-		break;
-	default:
-		abort();
-	}
-	reguse[pair[reg]] = reguse[reg] = np;
-	np->op = REG;
-	np->reg = reg;
-}
-
-static void
-accum(Node *np)
-{
-	switch (np->type.size) {
-	case 1:
-		moveto(np, A);
-		break;
-	case 2:
-		moveto(np, HL);
-		break;
-	default:
-		abort();
-	}
-}
-
-static void
-index(Node *np)
-{
-	Node *u = reguse[HL];
-	Symbol *sym;
-
-	if (u && u->sym) {
-		if (u->op == INDEX && np->sym == u->sym) {
-			np->op = INDEX;
-			return;
-		} else {
-			spill(HL);
-		}
-	}
-	code(LDI, &regs[HL], np);
-	if (sym = np->sym)
-		sym->index = 1;
-	np->op = INDEX;
-	reguse[HL] = reguse[H] = reguse[L] = np;
-}
-
-static void
-move(Node *np, Node *parent)
-{
-	assert(np->type.size == 1);
-	switch (parent->op) {
-	case OASSIG:
-		allocreg(np);
-		break;
-	case ONEG:
-	case OCPL:
-		switch (np->op) {
-		case REG:
-			if (np->reg == A)
-				break;
-			/* PASSTHROUGH */
-		case PAR:
-		case AUTO:
-		case CONST:
-		case MEM:
-		case INDEX:
-			accum(np);
-			break;
-		default:
-			abort();
-		}
-		break;
-	case OADD:
-	case OSUB:
-	case OBAND:
-	case OBOR:
-	case OBXOR:
-		switch (np->op) {
-		case PAR:
-		case AUTO:
-		case CONST:
-		case INDEX:
-		case REG:
-			return;
-		case MEM:
-			index(np);
-			break;
-		default:
-			abort();
-		}
-		break;
-	default:
-		abort();
-	}
-}
-
-static void
-conmute(Node *np)
-{
-	Node *p, *q;
-
-	p = np->left;
-	q = np->right;
-	np->left = q;
-	np->right = p;
-}
-
-static void
-add(Node *np)
-{
-	Node *lp = np->left, *rp = np->right, *a;
-	uint8_t op;
-
-	switch (np->type.size) {
-	case 1:
-		a = reguse[A];
-		if (a == lp)
-			goto update_a;
-		if (a == rp)
-			goto conmute1;
-		if (lp->op == CONST) {
-			accum(rp);
-			goto conmute1;
-		}
-		accum(lp);
-		goto update_a;
-	conmute1:
-		conmute(np);
-		lp = np->left, rp = np->right;
-	update_a:
-		move(rp, np);
-		switch (np->op) {
-		case OADD:
-			op = ADD;
-			break;
-		case OSUB:
-			op = SUB;
-			break;
-		case OBAND:
-			op = AND;
-			break;
-		case OBOR:
-			op = OR;
-			break;
-		case OBXOR:
-			op = XOR;
-			break;
-		default:
-			abort();
-		}
-		code(op, lp, rp);
-		lp->used = rp->used = 1;
-		np->op = REG;
-		np->reg = A;
-		reguse[A] = np;
-		break;
-	default:
-		abort();
-	}
-}
-
-static void
-assign(Node *np)
-{
-	Node *lp = np->left, *rp = np->right;
-	Symbol *sym = lp->sym;
-
-	switch (np->type.size) {
-	case 1:
-		switch (lp->op) {
-		case MEM:
-			if (sym && sym->index)
-				lp->op = INDEX;
-			/* PASSTROUGH */
-		case INDEX:
-		case AUTO:
-			if (rp->op != REG)
-				move(rp, np);
-			lp->reg = rp->reg;
-			code(LDL, lp, rp);
-			break;
-		case REG:
-			code(MOV, lp, rp);
-			break;
-		default:
-			abort();
-		}
-		break;
-	default:
-		abort();
-	}
-
-	np->op = REG;
-	np->reg = lp->reg;
-	np->sym = rp->sym = lp->sym;
-	np->used = rp->used = lp->used = 1;
-}
-
-static void
-ret(Node *np)
-{
-	static Node retnode = {
-		.op = LABEL,
-		.sym = &retlabel
-	};
-
-	if (np->left)
-		accum(np->left);
-	code(JP, &retnode, NULL);
-}
-
-static void
-nop(Node *np)
-{
-}
-
-static void
-cpl(Node *np)
-{
-
-	Node *lp = np->left;
-	uint8_t op;
-
-	switch (np->type.size) {
-	case 1:
-		move(lp, np);
-		switch (np->op) {
-		case OCPL:
-			op = CPL;
-			break;
-		case ONEG:
-			op = NEG;
-			break;
-		default:
-			abort();
-		}
-		code(op, lp, NULL);
-		lp->used = 1;
-		np->sym = lp->sym;
-		np->reg = lp->reg;
-		np->op = REG;
-		reguse[A] = np;
-		break;
-	default:
-		abort();
-	}
-}
-
-static void
-cast(Node *np)
-{
-	Node *lp = np->left;
-	uint8_t reg;
-
-	if (lp->type.size != np->type.size)
-		abort();
-	lp->used = 1;
-	np->sym = lp->sym;
-	if ((np->op = lp->op) == REG) {
-		reg = lp->reg;
-		np->reg = reg;
-		reguse[pair[reg]] = reguse[reg] = np;
-	}
-}
-
-static void (*opnodes[])(Node *) = {
-	[OADD] = add,
-	[OSUB] = add,
-	[OASSIG] = assign,
-	[ORET] = ret,
-	[MEM] = nop,
-	[REG] = nop,
-	[AUTO] = nop,
-	[CONST] = nop,
-	[PAR] = nop,
-	[OBOR] = add,
-	[OBAND] = add,
-	[OBXOR] = add,
-	[OCPL] = cpl,
-	[ONEG] = cpl,
-	[OCAST] = cast
-};
-
-static void
-cgen(Node *np)
-{
-	Node *lp, *rp;
-
-	if (!np)
-		return;
-
-	if (np->addable >= ADDABLE)
-		return;
-
-	lp = np->left;
-	rp = np->right;
-	if (!lp) {
-		cgen(rp);
-	} else if (!rp) {
-		cgen(lp);
-	} else {
-		Node *p, *q;
-		if (lp->complex > rp->complex)
-			p = lp, q = rp;
-		else
-			p = rp, q = lp;
-		cgen(p);
-		cgen(q);
-	}
-	(*opnodes[np->op])(np);
-}
-
-void
-generate(void)
-{
-	uint8_t size = curfun->u.f.locals;
-	static short id = 1000;
-	Node **stmt, *np;
-
-	retlabel.id = id++;
-
-	code(PUSH, NULL, &regs[IX]);
-	code(MOV, &regs[IX], &regs[SP]);
-	if (size > 6) {
-		code(MOV, &regs[HL], imm(-size));
-		code(ADD, &regs[HL], &regs[SP]);
-		code(MOV, &regs[SP], &regs[HL]);
-	} else {
-		for (; size != 0; size-= 2)
-			code(PUSH, NULL, &regs[HL]);
-	}
-
-	for (stmt = curfun->u.f.body; np = *stmt; ++stmt)
-		cgen(np);
-
-	code(MOV, &regs[SP], &regs[IX]);
-	retlabel.u.pc = pc;
-	pc->label = &retlabel;
-	code(POP, &regs[IX], NULL);
-	code(RET, NULL, NULL);
-}
-
-/*
- * This is strongly influenced by
- * http://plan9.bell-labs.com/sys/doc/compiler.ps (/sys/doc/compiler.ps)
- * calculate addresability as follows
- *     AUTO => 11          value+fp
- *     REGISTER => 13      register
- *     STATIC => 12        (value)
- *     CONST => 20         $value
- */
-Node *
-genaddable(Node *np)
-{
-	Node *lp, *rp;
-
-	if (!np)
-		return np;
-
-	np->complex = 0;
-	np->addable = 0;
-	lp = np->left;
-	rp = np->right;
-	switch (np->op) {
-	case AUTO:
-		np->addable = 11;
-		break;
-	case REG:
-		np->addable = 13;
-		break;
-	case MEM:
-		np->addable = 12;
-		break;
-	case CONST:
-		np->addable = 20;
-		break;
-	default:
-		if (lp)
-			genaddable(lp);
-		if (rp)
-			genaddable(rp);
-		break;
-	}
-
-	if (np->addable > 10)
-		return np;
-	if (lp)
-		np->complex = lp->complex;
-	if (rp) {
-		int8_t d = np->complex - rp->complex;
-
-		if (d == 0)
-			++np->complex;
-		else if (d < 0)
-			np->complex = rp->complex;
-	}
-	if (np->complex == 0)
-		++np->complex;
-	return np;
-}
-
-void
-addable(void)
-{
-	apply(genaddable);
-}
--- a/cc2/code.c
+++ /dev/null
@@ -1,229 +1,0 @@
-
-#include <stdarg.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <stdio.h>
-
-#include "../inc/cc.h"
-#include "cc2.h"
-
-static char *regnames[] = {
-	[AF] = "AF",
-	[HL] = "HL", [DE] = "DE", [BC] = "BC",
-	[IX] = "IX", [IY] = "IY", [SP] = "SP",
-	[A]  = "A",
-	[B]  = "B", [C]  = "C",
-	[D]  = "D",  [E]  = "E",
-	[H]  = "H",  [L]  = "L",
-	[IYL]= "IYL",[IYH]= "IYH"
-};
-
-static void inst0(void), inst1(void), inst2(void);
-
-static void (*instcode[])(void) = {
-	[LDW] = inst2,
-	[LDL] = inst2,
-	[LDH] = inst2,
-	[LDI] = inst2,
-	[MOV] = inst2,
-	[ADD] = inst2,
-	[PUSH] = inst1,
-	[POP] = inst1,
-	[RET] = inst0,
-	[NOP] = inst0,
-	[INC] = inst1,
-	[SUB] = inst2,
-	[DEC] = inst1,
-	[JP] = inst1,
-	[AND] = inst2,
-	[OR] = inst2,
-	[XOR] = inst2,
-	[CPL] = inst1,
-	[NEG] = inst1
-
-};
-
-static char *insttext[] = {
-	[LDW] = "LD",
-	[LDL] = "LD",
-	[LDH] = "LD",
-	[LDI] = "LD",
-	[MOV] = "LD",
-	[ADD] = "ADD",
-	[PUSH] = "PUSH",
-	[POP] = "POP",
-	[RET] = "RET",
-	[NOP] = "NOP",
-	[INC] = "INC",
-	[SUB] = "SUB",
-	[DEC] = "DEC",
-	[JP] = "JP",
-	[AND] = "AND",
-	[OR] = "OR",
-	[XOR] = "XOR",
-	[CPL] = "CPL",
-	[NEG] = "NEG"
-};
-
-Inst *pc, *prog;
-
-static void
-nextpc(void)
-{
-	Inst *new;
-
-	new = xmalloc(sizeof(*new));
-
-	if (!pc) {
-		new->next = NULL;
-		prog = new;
-	} else {
-		new->next = pc->next;
-		pc->next = new;
-	}
-
-	new->prev = pc;
-	new->to.kind = NONE;
-	new->from.kind = NONE;
-	pc = new;
-}
-
-void
-addr(char op, Node *np, Addr *addr)
-{
-	switch (addr->kind = np->op) {
-	case REG:
-		addr->u.reg = np->reg;
-		break;
-	case CONST:
-		addr->u.i = np->sym->u.imm;
-		break;
-	case AUTO:
-		addr->u.i = np->sym->u.v.off;
-		break;
-	case LABEL:
-	case MEM:
-		addr->u.sym = np->sym;
-		break;
-	case INDEX:
-		break;
-	default:
-		abort();
-	}
-}
-
-void
-code(uint8_t op, Node *to, Node *from)
-{
-
-	nextpc();
-	if (from)
-		addr(op, from, &pc->from);
-	if (to)
-		addr(op, to, &pc->to);
-	pc->op = op;
-}
-
-void
-inscode(uint8_t op, Addr *to, Addr *from)
-{
-	nextpc();
-	if (from)
-		pc->from = *from;
-	if (to)
-		pc->to = *to;
-	pc->op = op;
-}
-
-void
-delcode(void)
-{
-	Inst *prev = pc->prev, *next = pc->next;
-
-	free(pc);
-	if (!prev) {
-		pc = next;
-		prog = NULL;
-	} else {
-		pc = prev;
-		prev->next = next;
-		if (next)
-			next->prev = prev;
-	}
-}
-
-void
-writeout(void)
-{
-	if (!prog)
-		return;
-
-	for (pc = prog; pc; pc = pc->next) {
-		if (pc->label)
-			printf("L%d:", pc->label->id);
-		(*instcode[pc->op])();
-	}
-}
-
-static void
-addr2txt(uint8_t op, Addr *a)
-{
-	Symbol *sym;
-
-	switch (a->kind) {
-	case REG:
-		fputs(regnames[a->u.reg], stdout);
-		break;
-	case CONST:
-		printf("%d", a->u.i);
-		break;
-	case PAR:
-	case AUTO:
-		printf("(IX%+d)", a->u.i);
-		break;
-	case LABEL:
-		sym = a->u.sym;
-		printf("L%d", sym->id);
-		break;
-	case INDEX:
-		fputs("(HL)", stdout);
-		break;
-	case MEM:
-		sym = a->u.sym;
-		if (sym->name)
-			printf((op == LDI) ? "%s" : "(%s)", sym->name);
-		else
-			printf((op == LDI) ? "T%u" : "(T%u)", sym->id);
-		break;
-	default:
-		abort();
-	}
-}
-
-static void
-inst0(void)
-{
-	printf("\t%s\n", insttext[pc->op]);
-}
-
-static void
-inst1(void)
-{
-	uint8_t op = pc->op;
-
-	printf("\t%s\t", insttext[op]);
-	addr2txt(op, (pc->to.kind != NONE) ? &pc->to : &pc->from);
-	putchar('\n');
-}
-
-static void
-inst2(void)
-{
-	uint8_t op = pc->op;
-
-	printf("\t%s\t", insttext[op]);
-	addr2txt(op, &pc->to);
-	putchar(',');
-	addr2txt(op, &pc->from);
-	putchar('\n');
-}
--- a/cc2/generror
+++ /dev/null
@@ -1,19 +1,0 @@
-
-BEGIN {
-	print "char *errlist[] = {"
-}
-/^enum nerrors \{/ {
-	inhome = 1
-}
-inhome && /E[A-Z]*, / {
-	sub(/,/, "", $1)
-	printf("\t[%s] = \"", $1)
-	for (i = 3; i < NF-1; ++i)
-		printf("%s ", $i)
-	printf("%s\",\n", $(NF-1));
-}
-inhome && /^}/ {
-	print "};"
-	inhome = 0
-}
-
--- a/cc2/main.c
+++ /dev/null
@@ -1,56 +1,0 @@
-
-#include <stdarg.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "../inc/cc.h"
-
-#include "cc2.h"
-#include "error.h"
-
-char odebug;
-
-void
-error(unsigned nerror, ...)
-{
-	va_list va;
-	va_start(va, nerror);
-	if (nerror >= ENUMERR)
-		fprintf(stderr, "incorrect error number '%d'", nerror);
-	else
-		vfprintf(stderr, errlist[nerror], va);
-	va_end(va);
-	putc('\n', stderr);
-	exit(1);
-}
-
-bool
-moreinput(void)
-{
-	int c;
-
-repeat:
-	if (feof(stdin))
-		return 0;
-	if ((c = getchar()) == '\n' || c == EOF)
-		goto repeat;
-	ungetc(c, stdin);
-	return 1;
-}
-
-int
-main(void)
-{
-	fputs("cc2 is not updated with the output of cc1", stderr);
-	exit(1);
-	while (moreinput()) {
-		parse();
-		optimize();
-		addable();
-		generate();
-		peephole();
-		writeout();
-	}
-	return 0;
-}
--- a/cc2/optm.c
+++ /dev/null
@@ -1,51 +1,0 @@
-
-#include <stddef.h>
-#include <inttypes.h>
-
-#include "../inc/cc.h"
-#include "cc2.h"
-
-
-#include <stdio.h>
-
-static Node *
-optcasts(Node *np, Type *tp)
-{
-	if (!np)
-		return NULL;
-
-repeat:
-	switch (np->op) {
-	case OCAST:
-		/* TODO: be careful with the sign */
-		if (np->type.flags&INTF && np->type.size >= tp->size) {
-			np = np->left;
-			goto repeat;
-		}
-		break;
-	case OASSIG:
-		tp = &np->type;
-		break;
-	default:
-		if (np->type.size > tp->size)
-			np->type = *tp;
-		break;
-	}
-
-	np->left = optcasts(np->left, tp);
-	np->right = optcasts(np->right, tp);
-	return np;
-}
-
-static Node *
-opt(Node *np)
-{
-	np = optcasts(np, &np->type);
-	return np;
-}
-
-void
-optimize(void)
-{
-	apply(opt);
-}
--- a/cc2/parser.c
+++ /dev/null
@@ -1,603 +1,0 @@
-
-#include <errno.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../inc/cc.h"
-#include "../inc/sizes.h"
-
-#include "cc2.h"
-
-#define MAXLINE 200
-#define NR_STACKSIZ 32
-#define NR_NODEPOOL 128
-#define NR_EXPRESSIONS 64
-
-enum {
-	LOCAL, GLOBAL, PARAMETER
-};
-
-Symbol *curfun;
-static Node *stack[NR_STACKSIZ], **stackp;
-static Node *listexp[NR_EXPRESSIONS], **listp;
-static Node nodepool[NR_NODEPOOL], *newp;
-
-
-static Type Funct = {
-	.letter = L_FUNCTION,
-};
-
-static Type l_int8 = {
-	.letter = L_INT8,
-	.size = 1,
-	.align = 2,
-	.flags = SIGNF | INTF
-};
-
-static Type l_int16 = {
-	.letter = L_INT16,
-	.size = 2,
-	.align = 2,
-	.flags = SIGNF | INTF
-
-};
-
-static Type l_int32 = {
-	.letter = L_INT32,
-	.size = 4,
-	.align = 4,
-	.flags = SIGNF | INTF
-
-};
-
-static Type l_int64 = {
-	.letter = L_INT64,
-	.size = 8,
-	.align = 8,
-	.flags = SIGNF | INTF
-
-};
-
-static Type l_uint8 = {
-	.letter = L_UINT8,
-	.size = 1,
-	.align = 2,
-	.flags =  INTF
-};
-
-static Type l_uint16 = {
-	.letter = L_UINT16,
-	.size = 2,
-	.align = 2,
-	.flags =  INTF
-};
-
-static Type l_uint32 = {
-	.letter = L_UINT32,
-	.size = 4,
-	.align = 4,
-	.flags =  INTF
-};
-
-static Type l_uint64 = {
-	.letter = L_UINT64,
-	.size = 8,
-	.align = 8,
-	.flags =  INTF
-};
-
-static void cast(char *), operator(char *), assignment(char *), increment(char *),
-            globvar(char *), localvar(char *), paramvar(char *), label(char *),
-            immediate(char *), unary(char *), oreturn(char *);
-
-/*TODO: Remove hardcoded symbols */
-
-static void (*optbl[])(char *) = {
-	[L_INT8] = cast,
-	[L_INT16] = cast,
-	[L_INT32] = cast,
-	[L_INT64] = cast,
-	[L_UINT8] = cast,
-	[L_UINT16] = cast,
-	[L_UINT32] = cast,
-	[L_UINT64] = cast,
-	[L_BOOL] = cast,
-	[L_FLOAT] = cast,
-	[L_DOUBLE] = cast,
-	[L_LDOUBLE] = cast,
-	[L_POINTER] = cast,
-	[L_VOID] = cast,
-	['+'] = operator,
-	['%'] = operator,
-	['-'] = operator,
-	['*'] = operator,
-	['/'] = operator,
-	['l'] = operator,
-	['r'] = operator,
-	['&'] = operator,
-	['|'] = operator,
-	['^'] = operator,
-	[':'] = assignment,
-	[';'] = increment,
-	['Y'] = globvar,
-	['A'] = localvar,
-	['K'] = localvar,
-	['T'] = localvar,
-	['G'] = globvar,
-	['P'] = paramvar,
-	['L'] = label,
-	['#'] = immediate,
-	['@'] = unary,
-	['a'] = unary,
-	['<'] = operator,
-	['>'] = operator,
-	[']'] = operator,
-	['['] = operator,
-	['='] = operator,
-	['!'] = unary,
-	['y'] = oreturn,
-	['j'] = NULL,
-	['o'] = operator,
-	['_'] = unary,
-	['~'] = unary,
-	[','] = operator,
-	['\177'] = NULL
-};
-
-static void
-prnode(Node *np)
-{
-	if (np->left)
-		prnode(np->left);
-	if (np->right)
-		prnode(np->right);
-	fprintf(stderr, "\t%c%c", np->op, np->type.letter);
-}
-
-void
-prtree(Node *np)
-{
-	prnode(np);
-	putc('\n', stderr);
-}
-
-void
-apply(Node *(*fun)(Node *))
-{
-	Node **list, *np;
-
-	for (list = curfun->u.f.body; np = *list; ++list)
-		*list++ = (*fun)(np);
-}
-
-static Symbol *
-parameter(char *num)
-{
-	static Symbol tbl[NR_FUNPARAM];
-	Symbol *sym;
-	unsigned i = atoi(num);
-
-	if (!curfun)
-		error(ESYNTAX);
-	if (i >= NR_FUNPARAM)
-		error(EPARNUM);
-	sym = &tbl[i];
-	sym->id = i;
-	return sym;
-}
-
-static Symbol *
-local(char *num)
-{
-	static Symbol tbl[NR_INT_IDENT];
-	Symbol *sym;
-	unsigned i = atoi(num);
-
-	if (!curfun)
-		error(ESYNTAX);
-	if (i >= NR_INT_IDENT)
-		error(EINTNUM);
-	sym = &tbl[i];
-	sym->id = i;
-	return sym;
-}
-
-static Symbol *
-global(char *num)
-{
-	static Symbol tbl[NR_EXT_IDENT];
-	Symbol *sym;
-	unsigned i = atoi(num);
-
-	if (i >= NR_EXT_IDENT)
-		error(EEXTNUM);
-
-	sym = &tbl[i];
-	sym->id = i;
-	return sym;
-}
-
-static Node *
-newnode(void)
-{
-	if (newp == &nodepool[NR_NODEPOOL])
-		error(ENODEOV);
-	return newp++;
-}
-
-Node *
-imm(TINT i)
-{
-	Node *np = newnode();
-
-	np->op = CONST;
-	np->type = l_int16;
-	/* FIX: memory leak */
-	np->sym = xmalloc(sizeof(Symbol));
-	np->sym->u.imm = i;
-	np->left = np->right = NULL;
-	return np;
-}
-
-static void
-push(Node *np)
-{
-	if (stackp == &stack[NR_STACKSIZ])
-		error(ESTACKO);
-	*stackp++ = np;
-}
-
-static Node *
-pop(void)
-{
-	if (stackp == stack)
-		error(ESTACKU);
-	return *--stackp;
-}
-
-static Type *
-gettype(char *type)
-{
-	switch (type[0]) {
-	case L_INT8:
-		return &l_int8;
-	case L_INT16:
-		return &l_int16;
-	case L_INT32:
-		return &l_int32;
-	case L_INT64:
-		return &l_int64;
-	case L_UINT8:
-		return &l_uint8;
-	case L_UINT16:
-		return &l_uint16;
-	case L_UINT32:
-		return &l_uint32;
-	case L_UINT64:
-		return &l_uint64;
-	case L_FUNCTION:
-		return &Funct;
-	default:
-		error(ETYPERR);
-	}
-}
-
-static Symbol *
-symbol(uint8_t t, char *token)
-{
-	Symbol *sym;
-	static Symbol *(*tbl[3])(char *)= {
-		[LOCAL] = local,
-		[GLOBAL] = global,
-		[PARAMETER] = parameter
-	};
-	sym = (*tbl[t])(token+1);
-	sym->kind = *token;
-	return sym;
-}
-
-static void
-variable(uint8_t t, char *token)
-{
-	Node *np = newnode();
-	Symbol *sym = symbol(t, token);
-
-	np->sym = sym;
-	np->op = sym->u.v.sclass;
-	np->type = sym->u.v.type;
-	np->left = np->right = NULL;
-	push(np);
-}
-
-static void
-localvar(char *token)
-{
-	variable(LOCAL, token);
-}
-
-static void
-globvar(char *token)
-{
-	variable(GLOBAL, token);
-}
-
-static void
-paramvar(char *token)
-{
-	variable(PARAMETER, token);
-}
-
-static void
-immediate(char *token)
-{
-	/* TODO: check type of immediate */
-	push(imm(atoi(token+2)));
-}
-
-static void
-unary(char *token)
-{
-	Node *np = newnode();
-
-	np->right = NULL;
-	np->left = pop();
-	np->type = *gettype(token+1);
-	np->op = token[0];
-	push(np);
-}
-
-static void
-operator(char *token)
-{
-	Node *np = newnode();
-
-	np->right = pop();
-	np->left = pop();
-	np->type = *gettype(token+1);
-	np->op = token[0];
-	push(np);
-}
-
-static void
-label(char *token)
-{
-	Node *np = newnode();
-
-	np->left = np->right = NULL;
-	np->op = LABEL;
-	np->sym = local(token);
-	push(np);
-}
-
-static void
-increment(char *token)
-{
-	Node *np = newnode();
-
-	np->right = pop();
-	np->left = pop();
-	np->type = *gettype(token+2);
-	np->op = token[0];
-	switch (np->subop = token[1]) {
-	case '-': case '+':
-		push(np);
-		break;
-	default:
-		error(ESYNTAX);
-	}
-}
-
-static void
-assignment(char *token)
-{
-	Node *np = newnode();
-
-	np->right = pop();
-	np->left = pop();
-	np->op = *token;
-	switch (*++token) {
-	case OADD: case OSUB: case OINC:  case OMOD: case ODIV:
-	case OSHL: case OSHR: case OBAND: case OBOR: case OBXOR:
-		np->subop = *++token;
-	default:
-		np->type = *gettype(token);
-		break;
-	}
-	push(np);
-}
-
-static void
-cast(char *token)
-{
-	Node *np = newnode();
-
-	np->right = NULL;
-	np->left = pop();
-	np->op = OCAST;
-	np->type = *gettype(token+1);
-	push(np);
-}
-
-static void
-expr(char *token)
-{
-	void (*fun)(char *);
-	unsigned c;
-
-	do {
-		if ((c = token[0]) > 0x7f || (fun = optbl[c]) == NULL)
-			error(ESYNTAX);
-		(*fun)(token);
-	} while (token = strtok(NULL, "\t"));
-}
-
-static void
-expression(char *token)
-{
-	Node *np;
-
-	if (!curfun)
-		error(ESYNTAX);
-
-	expr(token);
-
-	np = pop();
-	if (stackp != stack)
-		error(EEXPBAL);
-	if (listp == &listexp[NR_EXPRESSIONS])
-		error(EEXPROV);
-	*listp++ = np;
-}
-
-static void
-oreturn(char *token)
-{
-	Node *np = newnode(), *lp;
-
-	np->op = token[0];
-
-	if (token = strtok(NULL, "\t")) {
-		expr(token);
-		lp = pop();
-		np->left = lp;
-		np->type = lp->type;
-	} else {
-		np->left = NULL;
-	}
-	np->right = NULL;
-	push(np);
-}
-
-static void
-deflabel(char *token)
-{
-	Symbol *sym;
-
-	if (!curfun)
-		error(ESYNTAX);
-	sym = local(token);
-}
-
-static Symbol *
-declaration(uint8_t t, char class, char *token)
-{
-	Symbol *sym = symbol(t, token);
-	char *s;
-
-	free(sym->name);
-	memset(sym, 0, sizeof(*sym));
-	sym->u.v.sclass = class;
-
-	if ((s = strtok(NULL, "\t")) == NULL)
-		error(ESYNTAX);
-	sym->u.v.type = *gettype(s);
-	if ((s = strtok(NULL, "\t")) != NULL)
-		sym->name = xstrdup(s);
-
-	return sym;
-}
-
-static void
-globdcl(char *token)
-{
-	Symbol *sym = declaration(GLOBAL, MEM, token);
-
-	switch (token[0]) {
-	case 'X':
-		sym->extrn = 1;
-		break;
-	case 'G':
-		sym->public = 1;
-		break;
-	}
-
-	if (sym->u.v.type.letter != L_FUNCTION)
-		return;
-
-	if (curfun)
-		error(ESYNTAX);
-
-	curfun = sym;
-	sym->u.f.body = listp = listexp;
-	newp = nodepool;
-}
-
-static void
-paramdcl(char *token)
-{
-	Symbol *sym = declaration(PARAMETER, AUTO, token);
-	sym->u.v.off = -curfun->u.f.params;
-	curfun->u.f.params += sym->u.v.type.size;
-}
-
-static void
-localdcl(char *token)
-{
-	Symbol *sym = declaration(LOCAL, token[0], token);
-	char sclass = *token;
-
-	if (sclass == 'A' || sclass == 'R') {
-		uint8_t size = sym->u.v.type.size;
-		/* stack elements are 2 byte multiple */
-		if (size == 1)
-			++size;
-		curfun->u.f.locals += size;
-		sym->u.v.off = curfun->u.f.locals;
-	}
-}
-
-void
-parse(void)
-{
-	void (*fun)(char *tok);
-	uint8_t len;
-	int c;
-	char line[MAXLINE];
-
-	curfun = NULL;
-	stackp = stack;
-	listp = listexp;
-	newp = nodepool;
-
-	for (;;) {
-		switch (c = getchar()) {
-		case 'L':
-			fun = deflabel;
-			break;
-		case '\t':
-			fun = expression;
-			break;
-		case 'S':
-			/* TODO: struct */
-			break;
-		case 'P':
-			fun = paramdcl;
-			break;
-		case 'A': case 'R': case 'T':
-			fun = localdcl;
-			break;
-		case 'Y': case 'G':
-			fun = globdcl;
-			break;
-		case '}':
-			if (curfun)
-				return;
-		default:
-			goto syntax_error;
-		}
-
-		ungetc(c, stdin);
-		if (!fgets(line, sizeof(line), stdin))
-			break;
-		len = strlen(line);
-		if (line[len-1] != '\n')
-			error(ELNLINE);
-		line[len-1] = '\0';
-		(*fun)(strtok(line, "\t"));
-	}
-
-syntax_error:
-	error(ESYNTAX);
-}
--- a/cc2/peep.c
+++ /dev/null
@@ -1,39 +1,0 @@
-
-#include <inttypes.h>
-#include <stddef.h>
-
-#include "../inc/cc.h"
-#include "cc2.h"
-
-void
-peephole(void)
-{
-	Addr to, from;
-	TINT i;
-	uint8_t op;
-
-	for (pc = prog; pc; pc = pc->next) {
-		to = pc->to;
-		from = pc->from;
-
-		switch (pc->op) {
-		case SUB:
-		case ADD:
-			if (from.kind == CONST) {
-				if ((i = from.u.i) == 0 || i < 4) {
-					delcode();
-					op = (pc->op == ADD) ? INC : DEC;
-
-					while (i--)
-						inscode(op, &to, NULL);
-				}
-			/* TODO: More optimizations (ex: -1) */
-			}
-			break;
-		case JP:
-			if (to.u.sym->u.pc == pc->next)
-				delcode();
-			break;
-		}
-	}
-}