shithub: scc

Download patch

ref: 827b4cdaa90cabaa1ee149a79ceb4cf7c7813f47
parent: 9a2913311bd77d7075a327854a725d03eff554a2
author: Roberto E. Vargas Caballero <[email protected]>
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.

--- /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;
-		}
-	}
-}