shithub: scc

Download patch

ref: 8c20e677d7728c5120feb182e4d4195a7571fa71
parent: 1ce079ecedd0b95c5c367572b5872a78d2a309ba
author: Roberto E. Vargas Caballero <[email protected]>
date: Sun Oct 6 09:54:31 EDT 2019

[scc] Rename scc directory to cc

This makes the directory layout more orthogonal and similar to classical unix layout.

--- a/src/cmd/Makefile
+++ b/src/cmd/Makefile
@@ -13,7 +13,7 @@
 	$(BINDIR)/objcopy\
 	$(BINDIR)/addr2line\
 
-DIRS   = ld as scc
+DIRS   = ld as cc
 
 LIBMACH = $(LIBDIR)/libmach.a
 LIBSCC  = $(LIBDIR)/libscc.a
--- /dev/null
+++ b/src/cmd/cc/Makefile
@@ -1,0 +1,14 @@
+.POSIX:
+
+PROJECTDIR = ../../..
+include $(PROJECTDIR)/scripts/rules.mk
+
+DIRS = cc1 cc2 $(DRIVER)
+
+all: $(DIRS)
+
+$(DIRS): FORCE
+	+@cd $@ && $(MAKE)
+
+dep clean:
+	$(FORALL)
--- /dev/null
+++ b/src/cmd/cc/cc1/Makefile
@@ -1,0 +1,38 @@
+.POSIX:
+
+PROJECTDIR = ../../../..
+include $(PROJECTDIR)/scripts/rules.mk
+
+OBJS = types.o \
+       decl.o \
+       lex.o \
+       error.o \
+       symbol.o \
+       main.o \
+       expr.o \
+       code.o \
+       stmt.o \
+       cpp.o \
+       fold.o \
+       init.o \
+       builtin.o \
+
+TARGET   = $(LIBEXEC)/cc1-amd64-sysv \
+           $(LIBEXEC)/cc1-arm64-sysv \
+           $(LIBEXEC)/cc1-i386-sysv \
+           $(LIBEXEC)/cc1-z80-scc \
+
+all: $(TARGET)
+
+$(TARGET): $(LIBDIR)/libscc.a
+
+dep: inc-dep
+
+clean:
+	rm -f target/*/*.o
+
+include target/amd64-sysv/arch.mk
+include target/arm64-sysv/arch.mk
+include target/i386-sysv/arch.mk
+include target/z80-scc/arch.mk
+include deps.mk
--- /dev/null
+++ b/src/cmd/cc/cc1/TODO
@@ -1,0 +1,14 @@
+* Implement bitfields
+* Rewrite error recovery code, and ensure correct state after recovery
+* Parse correctly all integer and float constants
+* Add C99 features (almost all the new features of C99 are missed)
+* Add correct emit for any kind of constant
+* Add warning when some ANSI limit is violated.
+* Free memory in emit after some error happened.
+* Rewrite initializers to deal with the idea of  "current object"
+* Add some test about pointer airthmetic.
+* Merge all the definitions of the same string
+* Do not assign identifierss until symbols are emitted. This change will
+  avoid identifiers that are not emitted.
+* Fix assignation abbreviations. They fail whe lhs type is smaller than
+  the type in rhs
--- /dev/null
+++ b/src/cmd/cc/cc1/builtin.c
@@ -1,0 +1,119 @@
+#include <stdio.h>
+
+#include <scc/scc.h>
+#include "cc1.h"
+
+static Node *
+builtin_va_arg(Symbol *sym)
+{
+	Node *np, *ap;
+	Type *tp;
+
+	ap = assign();
+	expect(',');
+	tp = typename();
+
+	if (!valid_va_list(ap->type)) {
+		errorp("incorrect parameters for va_arg");
+		goto error;
+	}
+	if (tp == booltype ||
+	    tp == chartype || tp == uchartype || tp == schartype ||
+	    tp == shortype || tp == ushortype) {
+		warn("bool, char and short are promoted to int when passed through '...'");
+		tp = (tp->prop & TSIGNED) ? inttype : uinttype;
+	}
+
+	np = node(OBUILTIN, tp, ap, NULL);
+	np->sym = sym;
+	return np;
+
+error:
+	return constnode(zero);
+}
+
+static Node *
+builtin_va_copy(Symbol *sym)
+{
+	Node *np, *src, *dst;
+
+	dst = assign();
+	expect(',');
+	src = assign();
+
+	if (!valid_va_list(dst->type) || !valid_va_list(src->type)) {
+		errorp("incorrect parameters for va_copy");
+		return constnode(zero);
+	}
+
+	np = node(OBUILTIN, voidtype, dst, src);
+	np->sym = sym;
+	return np;
+}
+
+static Node *
+builtin_va_start(Symbol *sym)
+{
+	Node *np, *ap, *last;
+	Symbol **p;
+	Type *tp;
+
+	ap = assign();
+	expect(',');
+	last = assign();
+	if (last->op != OSYM)
+		goto error;
+
+	if (!valid_va_list(ap->type) || !(last->sym->flags&SDECLARED))
+		 goto error;
+
+	for (p = curfun->u.pars; p && *p != last->sym; ++p)
+		;
+	if (!p || *p == NULL || p[1] == NULL || p[1]->type != ellipsistype)
+		warn("second parameter of 'va_start' not last named argument");
+
+	tp = last->type;
+	if (tp == booltype ||
+	    tp == chartype || tp == uchartype || tp == schartype ||
+	    tp == shortype || tp == ushortype) {
+		warn("last parameter before '...' must not be bool, char or short");
+	}
+
+	np = node(OBUILTIN, voidtype, ap, last);
+	np->sym = sym;
+	return np;
+
+error:
+	errorp("incorrect parameters for va_start");
+	return constnode(zero);
+}
+
+static Node *
+builtin_va_end(Symbol *sym)
+{
+	Node *ap, *np;
+
+	ap = assign();
+
+	if (!valid_va_list(ap->type)) {
+		errorp("incorrect parameters for va_end");
+		return constnode(zero);
+	}
+
+	np = node(OBUILTIN, voidtype, ap, NULL);
+	np->sym = sym;
+	return np;
+}
+
+void
+ibuilts(void)
+{
+	struct builtin built[] = {
+		{"__builtin_va_arg", builtin_va_arg},
+		{"__builtin_va_copy", builtin_va_copy},
+		{"__builtin_va_start", builtin_va_start},
+		{"__builtin_va_end", builtin_va_end},
+		{NULL}
+	};
+	builtins(built);
+}
--- /dev/null
+++ b/src/cmd/cc/cc1/cc1.h
@@ -1,0 +1,496 @@
+#define INPUTSIZ LINESIZ
+
+#define GLOBALCTX 0
+#define PARAMCTX  1
+
+#define NR_USWITCHES 20
+
+/*
+ * Definition of enumerations
+ */
+enum {
+	NOALLOC,
+	ALLOC
+};
+
+enum typeprops {
+	TDEFINED = 1 << 0,    /* type defined */
+	TSIGNED  = 1 << 1,    /* signedness of the type */
+	TINTEGER = 1 << 2,    /* the type is INT of enum */
+	TARITH   = 1 << 3,    /* the type is INT, ENUM or FLOAT */
+	TAGGREG  = 1 << 4,    /* the type is struct or union */
+	TK_R     = 1 << 5,    /* this is a K&R-function */
+	TELLIPSIS= 1 << 6,    /* this function has an ellipsis par */
+	TFUNDEF  = 1 << 7,    /* function definition */
+};
+
+enum inputtype {
+	IMACRO = 1 << 0,      /* macro expansion type */
+	IFILE  = 1 << 1,      /* input file type */
+	ISTDIN = 1 << 2,      /* stdin type */
+	IEOF   = 1 << 3,      /* EOF mark */
+	ITYPE  = IMACRO | IFILE | ISTDIN,
+};
+
+/* data type letters */
+enum ns {
+	L_INT8      = 'C',
+	L_INT16     = 'I',
+	L_INT32     = 'W',
+	L_INT64     = 'Q',
+	L_UINT8     = 'K',
+	L_UINT16    = 'N',
+	L_UINT32    = 'Z',
+	L_UINT64    = 'O',
+	L_BOOL      = 'B',
+
+	L_FLOAT     = 'J',
+	L_DOUBLE    = 'D',
+	L_LDOUBLE   = 'H',
+
+	L_ELLIPSIS  = 'E',
+	L_VOID      = '0',
+	L_POINTER   = 'P',
+	L_FUNCTION  = 'F',
+	L_ARRAY     = 'V',
+	L_UNION     = 'U',
+	L_STRUCT    = 'S',
+	L_VA_ARG    = '1',
+};
+
+/* recovery points */
+enum {
+	END_DECL,
+	END_LDECL,
+	END_COMP,
+	END_COND
+};
+
+/* type constructors */
+enum typeop {
+	FTN = 1,
+	PTR,
+	ARY,
+	KRFTN
+};
+
+/* namespaces */
+enum namespaces {
+	NS_DUMMY,
+	NS_IDEN,
+	NS_TAG,
+	NS_LABEL,
+	NS_CPP,
+	NS_KEYWORD,
+	NS_CPPCLAUSES,
+	NS_STRUCTS
+};
+
+/* symbol flags */
+enum {
+	SAUTO     = 1 << 0,
+	SREGISTER = 1 << 1,
+	SDECLARED = 1 << 2,
+	SFIELD    = 1 << 3,
+	SEXTERN   = 1 << 4,
+	SUSED     = 1 << 5,
+	SCONSTANT = 1 << 6,
+	SGLOBAL   = 1 << 7,
+	SPRIVATE  = 1 << 8,
+	SLOCAL    = 1 << 9,
+	SEMITTED  = 1 << 10,
+	SDEFINED  = 1 << 11,
+	SSTRING   = 1 << 12,
+	STYPEDEF  = 1 << 13,
+	SINITLST  = 1 << 14,
+	SHASINIT  = 1 << 15
+};
+
+/* node flags */
+enum {
+	NLVAL   = 1 << 0,
+	NCONST  = 1 << 1,
+	NEFFECT = 1 << 2
+};
+
+/* lexer mode, compiler or preprocessor directive */
+enum {
+	CCMODE,
+	CPPMODE
+};
+
+/* input tokens */
+enum tokens {
+	CONST      = 1 << 0,      /* type qualifier tokens are used as flags */
+	RESTRICT   = 1 << 1,
+	VOLATILE   = 1 << 2,
+	INLINE     = 1 << 3,
+	TQUALIFIER = 1 << 7,      /* this value is picked outside of ASCII range */
+	TYPE,
+	IDEN,
+	SCLASS,
+	CONSTANT,
+	STRING,
+	SIZEOF,
+	INDIR,
+	INC,
+	DEC,
+	SHL,
+	SHR,
+	LE,
+	GE,
+	EQ,
+	NE,
+	AND,
+	OR,
+	MUL_EQ,
+	DIV_EQ,
+	MOD_EQ,
+	ADD_EQ,
+	SUB_EQ,
+	AND_EQ,
+	XOR_EQ,
+	OR_EQ,
+	SHL_EQ,
+	SHR_EQ,
+	ELLIPSIS,
+	CASE,
+	DEFAULT,
+	IF,
+	ELSE,
+	SWITCH,
+	WHILE,
+	DO,
+	FOR,
+	GOTO,
+	VOID,
+	FLOAT,
+	INT,
+	BOOL,
+	VA_LIST,
+	STRUCT,
+	UNION,
+	CHAR,
+	DOUBLE,
+	SHORT,
+	LONG,
+	LLONG,
+	COMPLEX,
+	TYPEDEF,
+	EXTERN,
+	STATIC,
+	AUTO,
+	REGISTER,
+	ENUM,
+	TYPEIDEN,
+	UNSIGNED,
+	SIGNED,
+	CONTINUE,
+	BREAK,
+	RETURN,
+	DEFINE,
+	INCLUDE,
+	LINE,
+	PRAGMA,
+	ERROR,
+	IFDEF,
+	ELIF,
+	IFNDEF,
+	UNDEF,
+	ENDIF,
+	BUILTIN,
+	EOFTOK
+};
+
+/* operations */
+enum op {
+	OADD,
+	OMUL,
+	OSUB,
+	OINC,
+	ODEC,
+	ODIV,
+	OMOD,
+	OSHL,
+	OSHR,
+	OBAND,
+	OBXOR,
+	OBOR,
+	OSNEG,
+	ONEG,
+	OCPL,
+	OAND,
+	OOR,
+	OEQ,
+	ONE,
+	OLT,
+	OGE,
+	OLE,
+	OGT,
+	OASSIGN,
+	OA_MUL,
+	OA_DIV,
+	OA_MOD,
+	OA_ADD,
+	OA_SUB,
+	OA_SHL,
+	OA_SHR,
+	OA_AND,
+	OA_XOR,
+	OA_OR,
+	OADDR,
+	OCOMMA,
+	OCAST,
+	OPTR,
+	OSYM,
+	OASK,
+	OCOLON,
+	OFIELD,
+	OLABEL,
+	ODEFAULT,
+	OCASE,
+	OJUMP,
+	OBRANCH,
+	OEXPR,
+	OEFUN,
+	OELOOP,
+	OBLOOP,
+	OFUN,
+	OPAR,
+	OCALL,
+	OCALLE,
+	ORET,
+	ODECL,
+	OBSWITCH,
+	OESWITCH,
+	OINIT,
+	OBUILTIN,
+	OTYP,
+};
+
+/*
+ * Definition of structures
+ */
+typedef struct type Type;
+typedef struct symbol Symbol;
+typedef struct swtch Switch;
+typedef struct node Node;
+typedef struct input Input;
+
+struct limits {
+	union {
+		TUINT i;
+		TFLOAT f;
+	} max;
+	union {
+		TUINT i;
+		TFLOAT f;
+	} min;
+};
+
+struct builtin {
+	char *str;
+	Node *(*fun)(Symbol *);
+};
+
+struct keyword {
+	char *str;
+	unsigned char token, value;
+};
+
+struct type {
+	unsigned char op;           /* type builder operator */
+	unsigned char ns;           /* namespace for struct members */
+	short id;                   /* type id, used in dcls */
+	char letter;                /* letter of the type */
+	unsigned char prop;         /* type properties */
+	unsigned char align;        /* align of the type */
+	unsigned long size;         /* sizeof the type */
+	Type *type;                 /* base type */
+	Symbol *tag;                /* symbol of the strug tag */
+	union {
+		Type **pars;            /* Function type parameters */
+		Symbol **fields;        /* fields of aggregate type */
+	} p;
+	union {
+		unsigned char rank;     /* convertion rank */
+		TINT elem;              /* number of type parameters */
+	} n;
+	Type *next;                 /* local list pointer */
+	Type *h_next;               /* hash collision list */
+};
+
+struct symbol {
+	unsigned char ctx;
+	unsigned char hide;
+	char ns;
+	unsigned short id;
+	unsigned short flags;
+	char *name;
+	Type *type;
+	unsigned char token;
+	union {
+		TINT i;
+		TUINT u;
+		TFLOAT f;
+		char *s;
+		unsigned char token;
+		Node **init;
+		Symbol **pars;
+		Node *(*fun)(Symbol *);
+	} u;
+	struct symbol *next;
+	struct symbol *hash;
+};
+
+struct node {
+	unsigned char op;
+	unsigned char flags;
+	Type *type;
+	Symbol *sym;
+	struct node *left, *right;
+};
+
+struct swtch {
+	short nr;
+	char hasdef;
+};
+
+struct yystype {
+	Symbol *sym;
+	unsigned char token;
+};
+
+#ifdef stdin
+struct input {
+	char flags;
+	unsigned lineno;
+	char *filenam;
+	FILE *fp;
+	Symbol *hide;
+	char *line, *begin, *p;
+	struct input *next;
+};
+#endif
+
+/* error.c */
+extern void error(char *fmt, ...);
+extern void warn(char *fmt, ...);
+extern void unexpected(void);
+extern void errorp(char *fmt, ...);
+extern void cpperror(char *fmt, ...);
+extern Type *deftype(Type *tp);
+
+/* types.c */
+extern int eqtype(Type *tp1, Type *tp2, int eqflag);
+extern Type *ctype(int type, int sign, int size);
+extern Type *mktype(Type *tp, int op, TINT nelem, Type *data[]);
+extern Type *duptype(Type *base);
+extern struct limits *getlimits(Type *tp);
+extern void typesize(Type *tp);
+extern void flushtypes(void);
+
+/* symbol.c */
+extern void dumpstab(Symbol **tbl, char *msg);
+extern Symbol *lookup(int ns, char *name, int alloc);
+extern Symbol *nextsym(Symbol *sym, int ns);
+extern Symbol *install(int ns, Symbol *sym);
+extern Symbol *newsym(int ns, char *name);
+extern void pushctx(void), popctx(void);
+extern void killsym(Symbol *sym);
+extern Symbol *newlabel(void);
+extern void keywords(struct keyword *key, int ns);
+extern void builtins(struct builtin *builts);
+extern Symbol *newstring(char *s, size_t len);
+extern unsigned newid(void);
+
+/* stmt.c */
+extern void compound(Symbol *lbreak, Symbol *lcont, Switch *sw);
+
+/* decl.c */
+extern Type *typename(void);
+extern void decl(void);
+
+/* lex.c */
+extern int ahead(void);
+extern int next(void);
+extern void expect(int tok);
+extern void discard(void);
+extern void addinput(char *fname, Symbol *hide, char *buffer);
+extern void delinput(void);
+extern void setsafe(int type);
+extern void ilex(void);
+extern void setloc(char *fname, unsigned line);
+#define accept(t) ((yytoken == (t)) ? next() : 0)
+
+/* code.c */
+extern void prtree(Node *np);
+extern void emit(int, void *);
+extern Node *node(int op, Type *tp, Node *left, Node *rigth);
+extern Node *varnode(Symbol *sym);
+extern Node *constnode(Symbol *sym);
+extern Node *sizeofnode(Type *tp);
+extern void freetree(Node *np);
+extern void icode(void);
+#define BTYPE(np) ((np)->type->op)
+
+/* fold.c */
+extern Node *simplify(Node *np);
+extern TUINT ones(int nbytes);
+
+/* expr.c */
+extern Node *decay(Node *), *negate(Node *np), *assign(void);
+extern Node *convert(Node *np, Type *tp1, int iscast);
+extern Node *constexpr(void), *condexpr(int neg), *expr(void);
+extern int isnodecmp(int op);
+extern int negop(int op);
+extern int cmpnode(Node *np, TUINT val);
+
+/* init.c */
+extern void initializer(Symbol *sym, Type *tp);
+extern Node *initlist(Type *tp);
+
+/* cpp.c */
+extern void icpp(void);
+extern int cpp(void);
+extern int expand(char *begin, Symbol *sym);
+extern void incdir(char *dir);
+extern void outcpp(void);
+extern void defdefine(char *macro, char *val, char *source);
+extern void undefmacro(char *s);
+extern void ppragmaln(void);
+
+/* builtin.c */
+extern void ibuilts(void);
+
+/* arch.c */
+extern void iarch(void);
+extern int valid_va_list(Type *tp);
+
+/*
+ * Definition of global variables
+ */
+extern struct yystype yylval;
+extern char yytext[];
+extern int yytoken;
+extern unsigned short yylen;
+extern int disexpand;
+extern unsigned cppctx;
+extern Input *input;
+extern int lexmode, namespace;
+extern int onlycpp, onlyheader;
+extern unsigned curctx;
+extern Symbol *curfun, *zero, *one;
+extern char *infile;
+extern unsigned lineno;
+extern char filenam[];
+
+extern Type *voidtype, *pvoidtype, *booltype,
+            *uchartype,   *chartype, *schartype,
+            *uinttype,    *inttype,
+            *sizettype, *pdifftype,
+            *ushortype,   *shortype,
+            *longtype,    *ulongtype,
+            *ullongtype,  *llongtype,
+            *floattype,   *doubletype,  *ldoubletype,
+            *ellipsistype, *va_list_type, *va_type;
--- /dev/null
+++ b/src/cmd/cc/cc1/code.c
@@ -1,0 +1,549 @@
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include <scc/scc.h>
+#include "cc1.h"
+
+static void emitbin(int, void *),
+            emitcast(int, void *),
+            emitsym(int, void *),
+            emitexp(int, void *),
+            emitsymid(int, void *),
+            emittext(int, void *),
+            emitfun(int, void *),
+            emitdcl(int, void *),
+            emitinit(int, void *),
+            emittype(int, void *),
+            emitbuilt(int, void *);
+
+char *optxt[] = {
+	[OADD] = "+",
+	[OSUB] = "-",
+	[OMUL] = "*",
+	[OINC] = ":i",
+	[ODEC] =  ":d",
+	[OPTR] = "@",
+	[OMOD] = "%",
+	[ODIV] = "/",
+	[OSHL] = "l",
+	[OSHR]  = "r",
+	[OLT] = "<",
+	[OGT] = ">",
+	[OGE] = "]",
+	[OLE] =  "[",
+	[OEQ] = "=",
+	[ONE] = "!",
+	[OBAND] = "&",
+	[OBXOR]  = "^",
+	[OBOR] = "|",
+	[OASSIGN] = ":",
+	[OA_MUL] = ":*",
+	[OA_DIV] = ":/",
+	[OA_MOD] = ":%",
+	[OA_ADD] = ":+",
+	[OA_SUB] = ":-",
+	[OA_SHL] = ":l",
+	[OA_SHR] = ":r",
+	[OA_AND] = ":&",
+	[OA_XOR] = ":^",
+	[OA_OR] = ":|",
+	[OADDR] = "'",
+	[OSNEG] = "_",
+	[ONEG] = "n",
+	[OCPL] = "~",
+	[OAND] = "a",
+	[OOR] = "o",
+	[OASK] = "?",
+	[OCOMMA] = ",",
+	[OLABEL] = "L%d\n",
+	[ODEFAULT] = "\tf\tL%d\n",
+	[OBSWITCH] = "\ts",
+	[OESWITCH] = "\tt\tL%d\n",
+	[OCASE] = "\tv\tL%d",
+	[OJUMP] = "\tj\tL%d\n",
+	[OBRANCH] = "\ty\tL%d",
+	[OEFUN] = "}\n",
+	[OELOOP] = "\tb\n",
+	[OBLOOP] = "\te\n",
+	[ORET] = "\th",
+	[OPAR] = "p",
+	[OCALL] = "c",
+	[OCALLE] = "z",
+	[OFIELD] = "."
+};
+
+void (*opcode[])(int, void *) = {
+	[OADD] = emitbin,
+	[OSUB] = emitbin,
+	[OMUL] = emitbin,
+	[OINC] = emitbin,
+	[ODEC] =  emitbin,
+	[OPTR] = emitbin,
+	[OMOD] = emitbin,
+	[ODIV] = emitbin,
+	[OSHL] = emitbin,
+	[OSHR]  = emitbin,
+	[OLT] = emitbin,
+	[OGT] = emitbin,
+	[OGE] = emitbin,
+	[OLE] =  emitbin,
+	[OEQ] = emitbin,
+	[ONE] = emitbin,
+	[OBAND] = emitbin,
+	[OBXOR]  = emitbin,
+	[OBOR] = emitbin,
+	[OASSIGN] = emitbin,
+	[OA_MUL] = emitbin,
+	[OA_DIV] = emitbin,
+	[OA_MOD] = emitbin,
+	[OA_ADD] = emitbin,
+	[OA_SUB] = emitbin,
+	[OA_SHL] = emitbin,
+	[OA_SHR] = emitbin,
+	[OA_AND] = emitbin,
+	[OA_XOR] = emitbin,
+	[OA_OR] = emitbin,
+	[OADDR] = emitbin,
+	[OSNEG] = emitbin,
+	[ONEG] = emitbin,
+	[OCPL] = emitbin,
+	[OAND] = emitbin,
+	[OOR] = emitbin,
+	[OCOMMA] = emitbin,
+	[OCAST] = emitcast,
+	[OSYM] = emitsym,
+	[OASK] = emitbin,
+	[OCOLON] = emitbin,
+	[OFIELD]= emitbin,
+	[OEXPR] = emitexp,
+	[OLABEL] = emitsymid,
+	[ODEFAULT] = emitsymid,
+	[OCASE] = emitsymid,
+	[OJUMP] = emitsymid,
+	[OBRANCH] = emitsymid,
+	[OEFUN] = emittext,
+	[OELOOP] = emittext,
+	[OBLOOP] = emittext,
+	[OFUN] = emitfun,
+	[ORET] = emittext,
+	[ODECL] = emitdcl,
+	[OBSWITCH] = emittext,
+	[OESWITCH] = emitsymid,
+	[OPAR] = emitbin,
+	[OCALL] = emitbin,
+	[OCALLE] = emitbin,
+	[OINIT] = emitinit,
+	[OBUILTIN] = emitbuilt,
+	[OTYP] = emittype,
+};
+
+static FILE *outfp;
+
+void
+icode(void)
+{
+	outfp = stdout;
+}
+
+void
+freetree(Node *np)
+{
+	if (!np)
+		return;
+	freetree(np->left);
+	freetree(np->right);
+	free(np);
+}
+
+static void
+emitnode(Node *np)
+{
+	if (np)
+		(*opcode[np->op])(np->op, np);
+}
+
+void
+prtree(Node *np)
+{
+	outfp = stderr;
+	fputs("DBG prtree", outfp);
+	emitnode(np);
+	putc('\n', outfp);
+	outfp = stdout;
+}
+
+void
+emit(int op, void *arg)
+{
+	extern int failure;
+
+	if (failure || onlycpp || onlyheader)
+		return;
+	(*opcode[op])(op, arg);
+}
+
+static void
+emitvar(Symbol *sym)
+{
+	int c;
+	short flags = sym->flags;
+
+	if (flags & SLOCAL)
+		c = 'T';
+	else if (flags & SPRIVATE)
+		c =  'Y';
+	else if (flags & SGLOBAL)
+		c = 'G';
+	else if (flags & SREGISTER)
+		c = 'R';
+	else if (flags & SFIELD)
+		c = 'M';
+	else if (flags & SEXTERN)
+		c = 'X';
+	else
+		c = 'A';
+	fprintf(outfp, "%c%u", c, sym->id);
+}
+
+static void
+emitconst(Node *np)
+{
+	Symbol *sym = np->sym;
+	Type *tp = np->type;
+	TUINT u;
+
+	switch (tp->op) {
+	case PTR:
+	case INT:
+	case ENUM:
+		u = (tp->prop & TSIGNED) ? (TUINT) sym->u.i : sym->u.u;
+		fprintf(outfp,
+		        "#%c%llX",
+		        np->type->letter,
+		        (long long) u & ones(tp->size));
+		break;
+	default:
+		abort();
+	}
+}
+
+static void
+emitsym(int op, void *arg)
+{
+	Node *np = arg;
+
+	if ((np->sym->flags & SINITLST) == 0) {
+		/*
+		 * When we have a compound literal we are going
+		 * to call to emitnode for every element of it,
+		 * and it means that we will have two '\t'
+		 * for the first element
+		 */
+		putc('\t', outfp);
+	}
+	(np->flags & NCONST) ? emitconst(np) : emitvar(np->sym);
+}
+
+static void
+emitletter(Type *tp)
+{
+	int letter;
+
+	letter = (tp->prop&TELLIPSIS) ? 'E' : tp->letter;
+	putc(letter, outfp);
+	switch (tp->op) {
+	case ARY:
+	case STRUCT:
+	case UNION:
+		fprintf(outfp, "%u", tp->id);
+	}
+}
+
+static void
+emittype(int op, void *arg)
+{
+	TINT n;
+	Symbol **sp;
+	char *tag;
+	Type *tp = arg;
+
+	if (!(tp->prop & TDEFINED))
+		return;
+
+	switch (tp->op) {
+	case ARY:
+		emitletter(tp);
+		putc('\t', outfp);
+		emitletter(tp->type);
+		fprintf(outfp,
+		        "\t#%c%llX\n",
+		        sizettype->letter, (long long) tp->n.elem);
+		return;
+	case UNION:
+	case STRUCT:
+		emitletter(tp);
+		tag = tp->tag->name;
+		fprintf(outfp,
+		       "\t\"%s\t#%c%lX\t#%c%X\n",
+		       (tag) ? tag : "",
+		       sizettype->letter,
+		       tp->size,
+		       sizettype->letter,
+		       tp->align);
+		n = tp->n.elem;
+		for (sp = tp->p.fields; n-- > 0; ++sp)
+			emit(ODECL, *sp);
+		break;
+	case PTR:
+	case FTN:
+	case ENUM:
+		return;
+	default:
+		abort();
+	}
+}
+
+static void
+emitstring(Symbol *sym, Type *tp)
+{
+	char *bp, *s, *lim;
+	int n;
+
+	bp = sym->u.s;
+	lim = &sym->u.s[tp->n.elem];
+	while (bp < lim) {
+		s = bp;
+		while (bp < lim && isprint(*bp))
+			++bp;
+		if ((n = bp - s) > 1)
+			fprintf(outfp, "\t#\"%.*s\n", n, s);
+		else
+			bp = s;
+		if (bp == lim)
+			break;
+		do {
+			fprintf(outfp,
+			        "\t#%c%02X\n",
+			        chartype->letter, (*bp++) & 0xFF);
+		} while (bp < lim && !isprint(*bp));
+	}
+}
+
+static void
+emitdesig(Node *np, Type *tp)
+{
+	Symbol *sym;
+	size_t n; /* TODO: This should be SIZET */
+	Node *aux;
+	Type *p;
+
+	if (!np) {
+		sym = NULL;
+	} else {
+		if (!np->sym)
+			goto emit_expression;
+		sym = np->sym;
+		if (sym->flags & SSTRING) {
+			emitstring(sym, tp);
+			return;
+		}
+		if ((sym->flags & SINITLST) == 0)
+			goto emit_expression;
+	}
+
+	switch (tp->op) {
+	case PTR:
+	case INT:
+	case ENUM:
+		aux = (sym) ? *sym->u.init : convert(constnode(zero), tp, 0);
+		emitexp(OEXPR, aux);
+		break;
+	case UNION:
+		n = tp->n.elem-1;
+		aux = (sym) ? sym->u.init[0] : NULL;
+		emitdesig(aux, aux->type);
+		break;
+	case STRUCT:
+	case ARY:
+		for (n = 0; n < tp->n.elem; ++n) {
+			aux = (sym) ? sym->u.init[n] : NULL;
+			p = (tp->op == ARY) ? tp->type : tp->p.fields[n]->type;
+			emitdesig(aux, p);
+		}
+		break;
+	default:
+		abort();
+	}
+
+	if (sym) {
+		free(sym->u.init);
+		sym->u.init = NULL;
+	}
+	freetree(np);
+	return;
+
+emit_expression:
+	emitexp(OEXPR, np);
+}
+
+static void
+emitinit(int op, void *arg)
+{
+	Node *np = arg;
+
+	fputs("\t(\n", outfp);
+	emitdesig(np, np->type);
+	fputs(")\n", outfp);
+}
+
+static void
+emitdcl(int op, void *arg)
+{
+	Symbol *sym = arg;
+
+	if (sym->flags & SEMITTED)
+		return;
+	emitvar(sym);
+	putc('\t', outfp);
+	if (sym->type->op == FTN) {
+		emitletter(sym->type->type);
+		putc('\t', outfp);
+	}
+	emitletter(sym->type);
+	fprintf(outfp, "\t\"%s", (sym->name) ? sym->name : "");
+	if (sym->flags & SFIELD)
+		fprintf(outfp, "\t#%c%llX", sizettype->letter, sym->u.i);
+	sym->flags |= SEMITTED;
+	if ((sym->flags & SHASINIT) == 0)
+		putc('\n', outfp);
+}
+
+static void
+emitcast(int op, void *arg)
+{
+	Node *np = arg, *lp = np->left;
+
+	emitnode(lp);
+	if (np->type != voidtype)
+		fprintf(outfp, "\tg%c", np->type->letter);
+}
+
+static void
+emitbin(int op, void *arg)
+{
+	Node *np = arg;
+	char *s;
+
+	emitnode(np->left);
+	emitnode(np->right);
+	if ((s = optxt[op]) != NULL)  {      /* do not print in OCOLON case */
+		fprintf(outfp, "\t%s", s);
+		emitletter(np->type);
+	}
+}
+
+static void
+emitbuilt(int op, void *arg)
+{
+	Node *np = arg;
+
+	emitnode(np->left);
+	emitnode(np->right);
+	fprintf(outfp, "\t\"%s\tm", np->sym->name);
+	emitletter(np->type);
+}
+
+
+static void
+emitexp(int op, void *arg)
+{
+	Node *np = arg;
+
+	emitnode(np);
+	putc('\n', outfp);
+	freetree(np);
+}
+
+static void
+emitfun(int op, void *arg)
+{
+	Symbol *sym = arg, **sp;
+
+	emitdcl(op, arg);
+	fputs("{\n", outfp);
+
+	for (sp = sym->u.pars; sp && *sp; ++sp)
+		emit(ODECL, *sp);
+	fputs("\\\n", outfp);
+}
+
+static void
+emittext(int op, void *arg)
+{
+	fputs(optxt[op], outfp);
+}
+
+static void
+emitsymid(int op, void *arg)
+{
+	Symbol *sym = arg;
+	fprintf(outfp, optxt[op], sym->id);
+}
+
+Node *
+node(int op, Type *tp, Node *lp, Node *rp)
+{
+	Node *np;
+
+	np = xmalloc(sizeof(*np));
+	np->op = op;
+	np->type = tp;
+	np->sym = NULL;
+	np->flags = 0;
+	np->left = lp;
+	np->right = rp;
+
+	if (lp)
+		np->flags |= lp->flags & NEFFECT;
+	if (rp)
+		np->flags |= rp->flags & NEFFECT;
+	return np;
+}
+
+Node *
+varnode(Symbol *sym)
+{
+	Node *np;
+	Type *tp = sym->type;
+
+	np = node(OSYM, sym->type, NULL, NULL);
+	np->type = sym->type;
+	np->flags = (tp->op != FTN && tp->op != ARY) ? NLVAL : 0;
+	np->sym = sym;
+	return np;
+}
+
+Node *
+constnode(Symbol *sym)
+{
+	Node *np;
+
+	np = node(OSYM, sym->type, NULL, NULL);
+	np->type = sym->type;
+	np->flags = NCONST;
+	np->sym = sym;
+	return np;
+}
+
+Node *
+sizeofnode(Type *tp)
+{
+	Symbol *sym;
+
+	sym = newsym(NS_IDEN, NULL);
+	sym->type = sizettype;
+	sym->u.i = tp->size;
+	return constnode(sym);
+}
--- /dev/null
+++ b/src/cmd/cc/cc1/cpp.c
@@ -1,0 +1,838 @@
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+#include "cc1.h"
+
+static char *argp, *macroname;
+static unsigned arglen;
+static unsigned ncmdlines;
+static Symbol *symline, *symfile;
+static unsigned char ifstatus[NR_COND];
+static int cppoff;
+static struct items dirinclude;
+
+unsigned cppctx;
+int disexpand;
+
+void
+defdefine(char *macro, char *val, char *source)
+{
+	char *def, *fmt = "#define %s %s\n";
+	Symbol dummy = {.flags = SDECLARED};
+
+	if (!val)
+		val = "";
+	def = xmalloc(strlen(fmt) + strlen(macro) + strlen(val));
+
+	sprintf(def, fmt, macro, val);
+	lineno = ++ncmdlines;
+	addinput(source, &dummy, def);
+	cpp();
+	delinput();
+}
+
+void
+undefmacro(char *s)
+{
+	killsym(lookup(NS_CPP, s, NOALLOC));
+}
+
+void
+icpp(void)
+{
+	static char sdate[14], stime[11];
+	struct tm *tm;
+	time_t t;
+	static char **bp, *list[] = {
+		"__STDC__",
+		"__STDC_HOSTED__",
+		"__SCC__",
+		NULL
+	};
+	static struct keyword keys[] = {
+		{"define", DEFINE, DEFINE},
+		{"include", INCLUDE, INCLUDE},
+		{"line", LINE, LINE},
+		{"ifdef", IFDEF, IFDEF},
+		{"if", IF, IF},
+		{"elif", ELIF, ELIF},
+		{"else", ELSE, ELSE},
+		{"ifndef", IFNDEF, IFNDEF},
+		{"endif", ENDIF, ENDIF},
+		{"undef", UNDEF, UNDEF},
+		{"pragma", PRAGMA, PRAGMA},
+		{"error", ERROR, ERROR},
+		{NULL, 0, 0}
+	};
+
+	keywords(keys, NS_CPPCLAUSES);
+
+	t = time(NULL);
+	tm = localtime(&t);
+	strftime(sdate, sizeof(sdate), "\"%b %d %Y\"", tm);
+	strftime(stime, sizeof(stime), "\"%H:%M:%S\"", tm);
+	defdefine("__DATE__", sdate, "built-in");
+	defdefine("__TIME__", stime, "built-in");
+	defdefine("__STDC_VERSION__", STDC_VERSION, "built-in");
+	defdefine("__LINE__", NULL, "built-in");
+	defdefine("__FILE__", NULL, "built-in");
+
+	symline = lookup(NS_CPP, "__LINE__", ALLOC);
+	symfile = lookup(NS_CPP, "__FILE__", ALLOC);
+
+	for (bp = list; *bp; ++bp)
+		defdefine(*bp, "1", "built-in");
+
+	ncmdlines = 0;
+}
+
+static void
+nextcpp(void)
+{
+	next();
+	if (yytoken == EOFTOK)
+		error("unterminated argument list invoking macro \"%s\"",
+		      macroname);
+	if (yylen + 1 > arglen)
+		error("argument overflow invoking macro \"%s\"",
+		      macroname);
+	if (yytoken == IDEN)
+		yylval.sym->flags |= SUSED;
+	memcpy(argp, yytext, yylen);
+	argp += yylen;
+	*argp++ = ' ';
+	arglen -= yylen + 1;
+}
+
+static void
+paren(void)
+{
+	for (;;) {
+		nextcpp();
+		switch (yytoken) {
+		case ')':
+			return;
+		case '(':
+			paren();
+			break;
+		}
+	}
+}
+
+static void
+parameter(void)
+{
+	for (;;) {
+		nextcpp();
+		switch (yytoken) {
+		case ')':
+		case ',':
+			argp -= 3;  /* remove " , "  or " ) "*/
+			*argp++ = '\0';
+			return;
+		case '(':
+			paren();
+			break;
+		}
+	}
+}
+
+static int
+parsepars(char *buffer, char **listp, int nargs)
+{
+	int n;
+
+	if (nargs == -1)
+		return -1;
+	if (ahead() != '(' && nargs > 0)
+		return 0;
+
+	disexpand = 1;
+	next();
+	n = 0;
+	argp = buffer;
+	arglen = INPUTSIZ;
+	if (ahead() == ')') {
+		next();
+	} else {
+		do {
+			*listp++ = argp;
+			parameter();
+		} while (++n < NR_MACROARG && yytoken == ',');
+	}
+	if (yytoken != ')')
+		error("incorrect macro function-alike invocation");
+	disexpand = 0;
+
+	if (n == NR_MACROARG)
+		error("too many parameters in macro \"%s\"", macroname);
+	if (n != nargs) {
+		error("macro \"%s\" received %d arguments, but it takes %d",
+		      macroname, n, nargs);
+	}
+
+	return 1;
+}
+
+static size_t
+copymacro(char *buffer, char *s, size_t bufsiz, char *arglist[])
+{
+	int delim, prevc, c;
+	char *p, *arg, *bp = buffer;
+	size_t size;
+
+	for (prevc = '\0'; c = *s; prevc = c, ++s) {
+		switch (c) {
+		case '$':
+			while (bp[-1] == ' ')
+				--bp, ++bufsiz;
+			while (s[1] == ' ')
+				++s;
+		case '#':
+			break;
+		case '\'':
+			delim = '\'';
+			goto search_delim;
+		case '\"':
+			delim = '"';
+		search_delim:
+			for (p = s; *++s != delim; )
+				;
+			size = s - p + 1;
+			if (size > bufsiz)
+				goto expansion_too_long;
+			memcpy(bp, p, size);
+			bufsiz -= size;
+			bp += size;
+			break;
+		case '@':
+			if (prevc == '#')
+				bufsiz -= 2;
+			arg = arglist[atoi(++s)];
+			size = strlen(arg);
+			if (size > bufsiz)
+				goto expansion_too_long;
+			if (prevc == '#')
+				*bp++ = '"';
+			memcpy(bp, arg, size);
+			bp += size;
+			if (prevc == '#')
+				*bp++ = '"';
+			bufsiz -= size;
+			s += 2;
+			break;
+		default:
+			if (bufsiz-- == 0)
+				goto expansion_too_long;
+			*bp++ = c;
+			break;
+		}
+	}
+	*bp = '\0';
+
+	return bp - buffer;
+
+expansion_too_long:
+	error("macro expansion of \"%s\" too long", macroname);
+}
+
+int
+expand(char *begin, Symbol *sym)
+{
+	size_t elen;
+	int n, i;
+	char *s = sym->u.s;
+	char *arglist[NR_MACROARG], arguments[INPUTSIZ], buffer[INPUTSIZ];
+
+	macroname = sym->name;
+	if (sym == symfile) {
+		elen = sprintf(buffer, "\"%s\" ", filenam);
+		goto substitute;
+	}
+	if (sym == symline) {
+		elen = sprintf(buffer, "%d ", lineno);
+		goto substitute;
+	}
+	if (!s)
+		return 1;
+
+	n = atoi(s);
+	if (!parsepars(arguments, arglist, n))
+		return 0;
+	for (i = 0; i < n; ++i)
+		DBG("MACRO par%d:%s", i, arglist[i]);
+
+	elen = copymacro(buffer, s+3, INPUTSIZ-1, arglist);
+
+substitute:
+	DBG("MACRO '%s' expanded to :'%s'", macroname, buffer);
+	buffer[elen] = '\0';
+	addinput(filenam, sym, xstrdup(buffer));
+
+	return 1;
+}
+
+static int
+getpars(Symbol *args[NR_MACROARG])
+{
+	int n, c;
+	Symbol *sym;
+
+	c = *input->p;
+	next();
+	if (c != '(')
+		return -1;
+	next(); /* skip the '(' */
+	if (accept(')'))
+		return 0;
+
+	n = 0;
+	do {
+		if (n == NR_MACROARG) {
+			cpperror("too many parameters in macro");
+			return NR_MACROARG;
+		}
+		if (accept(ELLIPSIS)) {
+			args[n++] = NULL;
+			break;
+		}
+		if (yytoken != IDEN) {
+			cpperror("macro arguments must be identifiers");
+			return NR_MACROARG;
+		}
+		sym = install(NS_IDEN, yylval.sym);
+		sym->flags |= SUSED;
+		args[n++] = sym;
+		next();
+	} while (accept(','));
+	expect(')');
+
+	return n;
+}
+
+static int
+getdefs(Symbol *args[NR_MACROARG], int nargs, char *bp, size_t bufsiz)
+{
+	Symbol **argp;
+	size_t len;
+	int prevc = 0, ispar;
+
+	if (yytoken == '$') {
+		cpperror("'##' cannot appear at either ends of a macro expansion");
+		return 0;
+	}
+
+	for (;;) {
+		ispar = 0;
+		if (yytoken == IDEN && nargs >= 0) {
+			for (argp = args; argp < &args[nargs]; ++argp) {
+				if (*argp == yylval.sym)
+					break;
+			}
+			if (argp != &args[nargs]) {
+				sprintf(yytext, "@%02d@", (int) (argp - args));
+				ispar = 1;
+			}
+		}
+		if (prevc == '#' && !ispar) {
+			cpperror("'#' is not followed by a macro parameter");
+			return 0;
+		}
+		if (yytoken == '\n')
+			break;
+
+		if ((len = strlen(yytext)) >= bufsiz) {
+			cpperror("macro too long");
+			return 0;
+		}
+		if (yytoken == '$') {
+			*bp++ = '$';
+			 --bufsiz;
+		} else {
+			memcpy(bp, yytext, len);
+			bp += len;
+			bufsiz -= len;
+		}
+		if ((prevc = yytoken) != '#') {
+			*bp++ = ' ';
+			--bufsiz;
+		}
+		next();
+	}
+	*bp = '\0';
+	return 1;
+}
+
+static void
+define(void)
+{
+	Symbol *sym,*args[NR_MACROARG];
+	char buff[LINESIZ+1];
+	int n;
+
+	if (cppoff)
+		return;
+
+	namespace = NS_CPP;
+	next();
+
+	if (yytoken != IDEN) {
+		cpperror("macro names must be identifiers");
+		return;
+	}
+	sym = yylval.sym;
+	if (sym->flags & SDECLARED) {
+		warn("'%s' redefined", yytext);
+		free(sym->u.s);
+	} else {
+		sym = install(NS_CPP, sym);
+		sym->flags |= SDECLARED|SSTRING;
+	}
+
+	namespace = NS_IDEN;       /* Avoid polution in NS_CPP */
+	if ((n = getpars(args)) == NR_MACROARG)
+		goto delete;
+	if (n > 0 && !args[n-1])  /* it is a variadic function */
+		--n;
+	sprintf(buff, "%02d#", n);
+	if (!getdefs(args, n, buff+3, LINESIZ-3))
+		goto delete;
+	sym->u.s = xstrdup(buff);
+	DBG("MACRO '%s' defined as '%s'", sym->name, buff);
+	return;
+
+delete:
+	killsym(sym);
+}
+
+void
+incdir(char *dir)
+{
+	if (!dir || *dir == '\0')
+		die("cc1: incorrect -I flag");
+	newitem(&dirinclude, dir);
+}
+
+static int
+includefile(char *dir, char *file, size_t filelen)
+{
+	size_t dirlen;
+	char path[FILENAME_MAX];
+
+	if (!dir) {
+		dirlen = 0;
+		if (filelen > FILENAME_MAX-1)
+			return 0;
+	} else {
+		dirlen = strlen(dir);
+		if (dirlen + filelen > FILENAME_MAX-2)
+			return 0;
+		memcpy(path, dir, dirlen);
+		if (dir[dirlen-1] != '/')
+			path[dirlen++] = '/';
+	}
+	memcpy(path+dirlen, file, filelen);
+	path[dirlen + filelen] = '\0';
+
+	addinput(path, NULL, NULL);
+	return 1;
+}
+
+static char *
+cwd(char *buf)
+{
+	char *p, *s = filenam;
+	size_t len;
+
+	if ((p = strrchr(s, '/')) == NULL)
+		return NULL;
+	if ((len = p - s) >= FILENAME_MAX)
+		die("cc1: current work directory too long");
+	memcpy(buf, s, len);
+	buf[len] = '\0';
+	return buf;
+}
+
+static void
+include(void)
+{
+	char dir[FILENAME_MAX], file[FILENAME_MAX], *p, **bp;
+	size_t filelen;
+	int n;
+
+	if (cppoff)
+		return;
+
+	namespace = NS_IDEN;
+	next();
+
+	switch (*yytext) {
+	case '<':
+		if ((p = strchr(input->begin, '>')) == NULL || p[-1] == '<')
+			goto bad_include;
+		filelen = p - input->begin;
+		if (filelen >= FILENAME_MAX)
+			goto too_long;
+		memcpy(file, input->begin, filelen);
+		file[filelen] = '\0';
+
+		input->begin = input->p = p+1;
+		if (next() != '\n')
+			goto trailing_characters;
+
+		break;
+	case '"':
+		if (yylen < 3)
+			goto bad_include;
+		filelen = yylen-2;
+		if (filelen >= FILENAME_MAX)
+			goto too_long;
+		memcpy(file, yytext+1, filelen);
+		file[filelen] = '\0';
+
+		if (next() != '\n')
+			goto trailing_characters;
+
+		if (includefile(cwd(dir), file, filelen))
+			goto its_done;
+		break;
+	default:
+		goto bad_include;
+	}
+
+	n = dirinclude.n;
+	for (bp = dirinclude.s; n--; ++bp) {
+		if (includefile(*bp, file, filelen))
+			goto its_done;
+	}
+	cpperror("included file '%s' not found", file);
+
+its_done:
+	return;
+
+trailing_characters:
+	cpperror("trailing characters after preprocessor directive");
+	return;
+
+too_long:
+	cpperror("too long file name in #include");
+	return;
+
+bad_include:
+	cpperror("#include expects \"FILENAME\" or <FILENAME>");
+	return;
+}
+
+static void
+line(void)
+{
+	long n;
+	char *endp, *fname;
+
+	if (cppoff)
+		return;
+
+	disexpand = 0;
+	next();
+	n = strtol(yytext, &endp, 10);
+	if (n <= 0 || n > USHRT_MAX || *endp != '\0') {
+		cpperror("first parameter of #line is not a positive integer");
+		return;
+	}
+
+	next();
+	if (yytoken == '\n') {
+		fname = NULL;
+	} else {
+		if (*yytext != '\"' || yylen == 1) {
+			cpperror("second parameter of #line is not a valid filename");
+			return;
+		}
+		fname = yylval.sym->u.s;
+	}
+	setloc(fname, n - 1);
+	if (yytoken != '\n')
+		next();
+}
+
+static void
+pragma(void)
+{
+	if (cppoff)
+		return;
+	next();
+	warn("ignoring pragma '%s'", yytext);
+	*input->p = '\0';
+	next();
+}
+
+static void
+usererr(void)
+{
+	if (cppoff)
+		return;
+	cpperror("#error %s", input->p);
+	*input->p = '\0';
+	next();
+}
+
+static void
+ifclause(int negate, int isifdef)
+{
+	Symbol *sym;
+	unsigned n;
+	int status;
+	Node *expr;
+
+	if (cppctx == NR_COND-1)
+		error("too many nesting levels of conditional inclusion");
+
+	n = cppctx++;
+	namespace = NS_CPP;
+	next();
+
+	if (isifdef) {
+		if (yytoken != IDEN) {
+			cpperror("no macro name given in #%s directive",
+			         (negate) ? "ifndef" : "ifdef");
+			return;
+		}
+		sym = yylval.sym;
+		next();
+		status = (sym->flags & SDECLARED) != 0;
+		if (!status)
+			killsym(sym);
+	} else {
+		/* TODO: catch recovery here */
+		if ((expr = constexpr()) == NULL) {
+			cpperror("parameter of #if is not an integer constant expression");
+			return;
+		}
+		status = expr->sym->u.i != 0;
+		freetree(expr);
+	}
+
+	if (negate)
+		status = !status;
+	if ((ifstatus[n] = status) == 0)
+		++cppoff;
+}
+
+static void
+cppif(void)
+{
+	disexpand = 0;
+	ifclause(0, 0);
+}
+
+static void
+ifdef(void)
+{
+	ifclause(0, 1);
+}
+
+static void
+ifndef(void)
+{
+	ifclause(1, 1);
+}
+
+static void
+elseclause(void)
+{
+	int status;
+
+	if (cppctx == 0) {
+		cpperror("#else without #ifdef/ifndef");
+		return;
+	}
+
+	status = ifstatus[cppctx-1];
+	ifstatus[cppctx-1] = !status;
+	cppoff += (status) ? 1 : -1;
+}
+
+static void
+cppelse(void)
+{
+	elseclause();
+	next();
+}
+
+static void
+elif(void)
+{
+	elseclause();
+	if (ifstatus[cppctx-1]) {
+		--cppctx;
+		cppif();
+	}
+}
+
+static void
+endif(void)
+{
+	if (cppctx == 0)
+		error("#endif without #if");
+	if (!ifstatus[--cppctx])
+		--cppoff;
+	next();
+}
+
+static void
+undef(void)
+{
+	if (cppoff)
+		return;
+
+	namespace = NS_CPP;
+	next();
+	if (yytoken != IDEN) {
+		error("no macro name given in #undef directive");
+		return;
+	}
+	killsym(yylval.sym);
+	next();
+}
+
+int
+cpp(void)
+{
+	static struct {
+		unsigned char token;
+		void (*fun)(void);
+	} *bp, clauses [] = {
+		{DEFINE, define},
+		{INCLUDE, include},
+		{LINE, line},
+		{IFDEF, ifdef},
+		{IF, cppif},
+		{ELIF, elif},
+		{IFNDEF, ifndef},
+		{ELSE, cppelse},
+		{ENDIF, endif},
+		{UNDEF, undef},
+		{PRAGMA, pragma},
+		{ERROR, usererr},
+		{0, NULL}
+	};
+	int ns;
+	char *p;
+
+	for (p = input->p; isspace(*p); ++p)
+		;
+
+	if (*p != '#')
+		return cppoff;
+	input->p = p+1;
+
+	disexpand = 1;
+	lexmode = CPPMODE;
+	ns = namespace;
+	namespace = NS_CPPCLAUSES;
+	next();
+	namespace = NS_IDEN;
+
+	for (bp = clauses; bp->token && bp->token != yytoken; ++bp)
+		;
+	if (!bp->token) {
+		errorp("incorrect preprocessor directive '%s'", yytext);
+		goto error;
+	}
+
+	DBG("CPP %s", yytext);
+
+	pushctx();              /* create a new context to avoid polish */
+	(*bp->fun)();           /* the current context, and to get all  */
+	popctx();               /* the symbols freed at the  end        */
+
+	/*
+	 * #include changes the content of input->line, so the correctness
+	 * of the line must be checked in the own include(), and we have
+	 * to skip this tests. For the same reason include() is the only
+	 * function which does not prepare the next token
+	 */
+	if (yytoken != '\n' && !cppoff && bp->token != INCLUDE)
+		errorp("trailing characters after preprocessor directive");
+
+error:
+	disexpand = 0;
+	lexmode = CCMODE;
+	namespace = ns;
+
+	return 1;
+}
+
+void
+ppragmaln(void)
+{
+	static char file[FILENAME_MAX];
+	static unsigned nline;
+	char *s;
+
+	putchar('\n');
+	if (strcmp(file, filenam)) {
+		strcpy(file, filenam);
+		s = "#line %u \"%s\"\n";
+	} else if (nline+1 != lineno) {
+		s = "#line %u\n";
+	} else {
+		s = "";
+	}
+	nline = lineno;
+	printf(s, nline, file);
+}
+
+void
+outcpp(void)
+{
+	int c;
+	char *s, *t;
+
+	for (next(); yytoken != EOFTOK; next()) {
+		if (onlyheader)
+			continue;
+		if (yytoken != STRING) {
+			printf("%s ", yytext);
+			continue;
+		}
+		for (s = yytext; c = *s; ++s) {
+			switch (c) {
+			case '\n':
+				t = "\\n";
+				goto print_str;
+			case '\v':
+				t = "\\v";
+				goto print_str;
+			case '\b':
+				t = "\\b";
+				goto print_str;
+			case '\t':
+				t = "\\t";
+				goto print_str;
+			case '\a':
+				t = "\\a";
+			print_str:
+				fputs(t, stdout);
+				break;
+			case '\\':
+				putchar('\\');
+			default:
+				if (!isprint(c))
+					printf("\\x%x", c);
+				else
+					putchar(c);
+				break;
+			}
+		}
+		putchar(' ');
+	}
+	putchar('\n');
+}
+
--- /dev/null
+++ b/src/cmd/cc/cc1/decl.c
@@ -1,0 +1,966 @@
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+#include "cc1.h"
+
+#define NOSCLASS  0
+
+#define NOREP 0
+#define REP 1
+#define QUIET   1
+#define NOQUIET 0
+
+#define NR_DCL_TYP (NR_DECLARATORS+NR_FUNPARAM)
+#define NR_DCL_SYM (NR_DECLARATORS+NR_FUNPARAM+1)
+
+struct declarators {
+	unsigned nr;
+	unsigned ns;
+	struct decl *dcl;
+	unsigned nr_types;
+	Type **tpars;
+	Symbol **pars;
+	struct declarator {
+		unsigned char op;
+		TINT  nelem;
+		Symbol *sym;
+		Type **tpars;
+		Symbol **pars;
+	} d [NR_DECLARATORS];
+};
+
+struct decl {
+	unsigned ns;
+	int sclass;
+	int qualifier;
+	Symbol *sym;
+	Type *type;
+	Type *parent;
+	Symbol **pars;
+	Symbol *bufpars[NR_DCL_SYM];
+	Type *buftpars[NR_DCL_TYP];
+};
+
+
+static void
+endfundcl(Type *tp, Symbol **pars)
+{
+	if (tp->prop&TK_R && *pars)
+		warn("parameter names (without types) in function declaration");
+	/*
+	 * avoid non used warnings in prototypes
+	 */
+	while (*pars)
+		(*pars++)->flags |= SUSED;
+	popctx();
+}
+
+static void
+push(struct declarators *dp, int op, ...)
+{
+	va_list va;
+	unsigned n;
+	struct declarator *p;
+
+	va_start(va, op);
+	if ((n = dp->nr++) == NR_DECLARATORS)
+		error("too many declarators");
+
+	p = &dp->d[n];
+	p->op = op;
+	p->tpars = NULL;
+
+	switch (op) {
+	case ARY:
+		p->nelem = va_arg(va, TINT);
+		break;
+	case KRFTN:
+	case FTN:
+		p->nelem = va_arg(va, unsigned);
+		p->tpars = va_arg(va, Type **);
+		p->pars = va_arg(va, Symbol **);
+		break;
+	case IDEN:
+		p->sym = va_arg(va, Symbol *);
+		break;
+	}
+	va_end(va);
+}
+
+static int
+pop(struct declarators *dp, struct decl *dcl)
+{
+	struct declarator *p;
+
+	if (dp->nr == 0)
+		return 0;
+
+	p = &dp->d[--dp->nr];
+	if (p->op == IDEN) {
+		dcl->sym = p->sym;
+		return 1;
+	}
+
+	if (dcl->type->op == FTN)
+		endfundcl(dcl->type, dcl->pars);
+	dcl->pars = p->pars;
+
+	dcl->type = mktype(dcl->type, p->op, p->nelem, p->tpars);
+	return 1;
+}
+
+static void
+arydcl(struct declarators *dp)
+{
+	Node *np = NULL;
+	TINT n = 0;
+
+	expect('[');
+	if (yytoken != ']') {
+		if ((np = constexpr()) == NULL) {
+			errorp("invalid storage size");
+		} else {
+			if ((n = np->sym->u.i) <= 0) {
+				errorp("array size is not a positive number");
+				n = 1;
+			}
+			freetree(np);
+		}
+	}
+	expect(']');
+
+	push(dp, ARY, n);
+}
+
+static int
+empty(Symbol *sym, Type *tp, int param)
+{
+	if (!sym->name) {
+		sym->type = tp;
+		switch (tp->op) {
+		default:
+			 /* warn if it is not a parameter */
+			if (!param)
+				warn("empty declaration");
+		case STRUCT:
+		case UNION:
+		case ENUM:
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static void
+bad_storage(Type *tp, char *name)
+{
+	if (tp->op != FTN)
+		errorp("incorrect storage class for file-scope declaration");
+	else
+		errorp("invalid storage class for function '%s'", name);
+}
+
+static Symbol *
+redcl(Symbol *sym, Type *tp, int sclass)
+{
+	int flags;
+	char *name = sym->name;
+
+	if (!eqtype(sym->type, tp, 1)) {
+		errorp("conflicting types for '%s'", name);
+		return sym;
+	}
+
+	if (sym->token == TYPEIDEN && sclass != TYPEDEF ||
+	    sym->token != TYPEIDEN && sclass == TYPEDEF) {
+		goto redeclaration;
+	}
+	if (curctx != GLOBALCTX && tp->op != FTN) {
+		/* is it the redeclaration of a local variable? */
+		if ((sym->flags & SEXTERN) && sclass == EXTERN)
+			return sym;
+		goto redeclaration;
+	}
+
+	flags = sym->flags;
+	switch (sclass) {
+	case REGISTER:
+	case AUTO:
+		bad_storage(tp, name);
+		break;
+	case NOSCLASS:
+		if ((flags & SPRIVATE) == 0) {
+			if (flags & SEXTERN)
+				flags &= ~(SEXTERN|SEMITTED);
+			flags |= SGLOBAL;
+			break;
+		}
+		errorp("non-static declaration of '%s' follows static declaration",
+		       name);
+		break;
+	case TYPEDEF:
+		/* Only C11 allows multiple definitions of a typedef. */
+		goto redeclaration;
+	case EXTERN:
+		break;
+	case STATIC:
+		if ((flags & (SGLOBAL|SEXTERN)) == 0) {
+			flags |= SPRIVATE;
+			break;
+		}
+		errorp("static declaration of '%s' follows non-static declaration",
+		       name);
+		break;
+	}
+	sym->flags = flags;
+
+	return sym;
+
+redeclaration:
+	errorp("redeclaration of '%s'", name);
+	return sym;
+}
+
+static Symbol *
+identifier(struct decl *dcl)
+{
+	Symbol *sym = dcl->sym;
+	Type *tp = dcl->type;
+	int sclass = dcl->sclass;
+	char *name = sym->name;
+
+	if (empty(sym, tp, 0))
+		return sym;
+
+	/* TODO: Add warning about ANSI limits */
+	if (!(tp->prop & TDEFINED)                &&
+	    sclass != EXTERN && sclass != TYPEDEF &&
+	    !(tp->op == ARY && yytoken == '=')) {
+		errorp("declared variable '%s' of incomplete type", name);
+	}
+
+	if (tp->op == FTN) {
+		if (sclass == NOSCLASS)
+			sclass = EXTERN;
+		if (!strcmp(name, "main") && tp->type != inttype) {
+			errorp("main shall be defined with a return type of int");
+			errorp("please contact __20h__ on irc.freenode.net (#bitreich-en) via IRC");
+		}
+	}
+
+	if (sym->flags & SDECLARED) {
+		sym = redcl(dcl->sym, tp, sclass);
+	} else {
+		int flags = sym->flags | SDECLARED;
+
+		sym->type = tp;
+
+		switch (sclass) {
+		case REGISTER:
+		case AUTO:
+			if (curctx != GLOBALCTX && tp->op != FTN) {
+				flags |= (sclass == REGISTER) ? SREGISTER : SAUTO;
+				break;
+			}
+			bad_storage(tp, name);
+		case NOSCLASS:
+			if (tp->op == FTN)
+				flags |= SEXTERN;
+			else
+				flags |= (curctx == GLOBALCTX) ? SGLOBAL : SAUTO;
+			break;
+		case EXTERN:
+			flags |= SEXTERN;
+			break;
+		case STATIC:
+			flags |= (curctx == GLOBALCTX) ? SPRIVATE : SLOCAL;
+			break;
+		case TYPEDEF:
+			flags |= STYPEDEF;
+			sym->u.token = sym->token = TYPEIDEN;
+			break;
+		}
+		sym->flags = flags;
+	}
+
+	if (accept('='))
+		initializer(sym, sym->type);
+	if (!(sym->flags & (SGLOBAL|SEXTERN)) && tp->op != FTN)
+		sym->flags |= SDEFINED;
+	if (sym->token == IDEN && tp->op != FTN)
+		emit(ODECL, sym);
+	return sym;
+}
+
+static Symbol *
+parameter(struct decl *dcl)
+{
+	Symbol *sym = dcl->sym;
+	Type *funtp = dcl->parent, *tp = dcl->type;
+	char *name = sym->name;
+	int flags;
+
+	flags = 0;
+	switch (dcl->sclass) {
+	case STATIC:
+	case EXTERN:
+	case AUTO:
+		errorp("bad storage class in function parameter");
+		break;
+	case REGISTER:
+		flags |= SREGISTER;
+		break;
+	case NOSCLASS:
+		flags |= SAUTO;
+		break;
+	}
+
+	switch (tp->op) {
+	case VOID:
+		funtp->n.elem = 1;
+		if (dcl->sclass)
+			errorp("void as unique parameter may not be qualified");
+		return NULL;
+	case ARY:
+		tp = mktype(tp->type, PTR, 0, NULL);
+		break;
+	case FTN:
+		errorp("incorrect function type for a function parameter");
+		return NULL;
+	}
+	if (!empty(sym, tp, 1)) {
+		int isdcl = sym->flags&SDECLARED, isk_r = funtp->prop & TK_R;
+		if (isdcl && !isk_r) {
+			errorp("redefinition of parameter '%s'", name);
+			return NULL;
+		}
+		if (!isdcl && isk_r) {
+			errorp("declaration for parameter '%s' but no such parameter",
+			       sym->name);
+			return NULL;
+		}
+		sym->flags |= SDECLARED;
+	}
+
+	sym->type = tp;
+	sym->flags &= ~(SAUTO|SREGISTER);
+	sym->flags |= flags;
+	return sym;
+}
+
+static Symbol *dodcl(int rep,
+                     Symbol *(*fun)(struct decl *),
+                     unsigned ns,
+                     Type *type);
+
+static int
+krpars(struct declarators *dp)
+{
+	Symbol *sym;
+	int toomany = 0;
+	unsigned npars = 0;
+
+	do {
+		sym = yylval.sym;
+		expect(IDEN);
+		sym->flags |= SAUTO;
+		if ((sym = install(NS_IDEN, sym)) == NULL) {
+			errorp("redefinition of parameter '%s'",
+			       yylval.sym->name);
+			continue;
+		}
+		if (npars < NR_FUNPARAM) {
+			++npars;
+			*dp->pars++ = sym;
+			continue;
+		}
+		if (!toomany)
+		toomany = 1;
+	} while (accept(','));
+
+	return toomany;
+}
+
+static unsigned
+krfun(struct declarators *dp)
+{
+	int toomany = 0;
+
+
+	if (yytoken != ')')
+		toomany = krpars(dp);
+
+	if (dp->nr_types == NR_DCL_TYP) {
+		toomany = 1;
+	} else {
+		++dp->nr_types;
+		*dp->tpars++ = ellipsistype;
+	}
+
+	if (toomany)
+		errorp("too many parameters in function definition");
+	return 1;
+}
+
+static unsigned
+ansifun(struct declarators *dp)
+{
+	Symbol *sym;
+	unsigned npars, ntype, toomany, distoomany, voidpar;
+	Type type, *tp;
+
+	type.n.elem = 0;
+	type.prop = 0;
+	npars = ntype = toomany = distoomany = voidpar = 0;
+
+	do {
+		if (accept(ELLIPSIS)) {
+			if (ntype < 1)
+				errorp("a named argument is requiered before '...'");
+			if (yytoken != ')')
+				errorp("... must be the last parameter");
+			sym = NULL;
+			tp = ellipsistype;
+		} else if ((sym = dodcl(NOREP, parameter, NS_IDEN, &type)) == NULL) {
+			if (type.n.elem == 1 && ntype > 1)
+				voidpar = 1;
+			sym = NULL;
+			tp = NULL;
+		} else {
+			tp = sym->type;
+		}
+
+		if (sym) {
+			if (npars == NR_FUNPARAM) {
+				toomany = 1;
+			} else {
+				npars++;
+				*dp->pars++ = sym;
+			}
+		}
+
+		if (tp) {
+			if (dp->nr_types == NR_DCL_TYP) {
+				toomany = 1;
+			} else {
+				ntype++;
+				dp->nr_types++;
+				*dp->tpars++ = tp;
+			}
+		}
+
+	} while (accept(','));
+
+	if (toomany == 1)
+		errorp("too many parameters in function definition");
+	if (voidpar && ntype > 1)
+		errorp("'void' must be the only parameter");
+	return ntype;
+}
+
+static int
+funbody(Symbol *sym, Symbol *pars[])
+{
+	Type *tp;
+	Symbol **bp, *p;
+
+	if (!sym)
+		return 0;
+	tp = sym->type;
+	if (tp->op != FTN)
+		return 0;
+
+	switch (yytoken) {
+	case '{':
+	case TYPE:
+	case TYPEIDEN:
+		if (curctx != PARAMCTX)
+			errorp("nested function declaration");
+		if (sym && sym->ns == NS_IDEN)
+			break;
+	default:
+		emit(ODECL, sym);
+		endfundcl(tp, pars);
+		return  0;
+	}
+
+	tp->prop |= TFUNDEF;
+	curfun = sym;
+	if (sym->type->prop & TK_R) {
+		while (yytoken != '{') {
+			dodcl(REP, parameter, NS_IDEN, sym->type);
+			expect(';');
+		}
+		for (bp = pars; p = *bp; ++bp) {
+			if (p->type == NULL) {
+				warn("type of '%s' defaults to int", p->name);
+				p->type = inttype;
+			}
+		}
+	}
+	if (sym->flags & STYPEDEF)
+		errorp("function definition declared 'typedef'");
+	if (sym->flags & SDEFINED)
+		errorp("redefinition of '%s'", sym->name);
+	if (sym->flags & SEXTERN) {
+		sym->flags &= ~SEXTERN;
+		sym->flags |= SGLOBAL;
+	}
+	sym->flags |= SDEFINED;
+	sym->flags &= ~SEMITTED;
+	sym->u.pars = pars;
+	emit(OFUN, sym);
+	compound(NULL, NULL, NULL);
+	emit(OEFUN, NULL);
+	popctx();
+	flushtypes();
+	curfun = NULL;
+	return 1;
+}
+
+static void
+fundcl(struct declarators *dp)
+{
+	Type **types = dp->tpars;
+	unsigned ntypes, typefun;
+	Symbol **pars = dp->pars;
+	unsigned (*fun)(struct declarators *);
+
+	pushctx();
+	expect('(');
+	if (yytoken == ')' || yytoken == IDEN) {
+		typefun = KRFTN;
+		fun = krfun;
+	} else {
+		typefun = FTN;
+		fun = ansifun;
+	}
+	ntypes = (*fun)(dp);
+	*dp->pars++= NULL;
+	expect(')');
+
+	push(dp, typefun, ntypes, types, pars);
+}
+
+static void declarator(struct declarators *dp);
+
+static void
+directdcl(struct declarators *dp)
+{
+	Symbol *p, *sym;
+	static int nested;
+
+	if (accept('(')) {
+		if (nested == NR_SUBTYPE)
+			error("too many declarators nested by parentheses");
+		++nested;
+		declarator(dp);
+		--nested;
+		expect(')');
+	} else {
+		if (yytoken == IDEN || yytoken == TYPEIDEN) {
+			sym = yylval.sym;
+			if (p = install(dp->ns, sym)) {
+				sym = p;
+				sym->flags &= ~SDECLARED;
+			}
+			next();
+		} else {
+			sym = newsym(dp->ns, NULL);
+		}
+		push(dp, IDEN, sym);
+	}
+
+	for (;;) {
+		switch (yytoken) {
+		case '(':  fundcl(dp); break;
+		case '[':  arydcl(dp); break;
+		default:   return;
+		}
+	}
+}
+
+static void
+declarator(struct declarators *dp)
+{
+	unsigned  n;
+
+	for (n = 0; accept('*'); ++n) {
+		while (accept(TQUALIFIER))
+			;
+	}
+
+	directdcl(dp);
+
+	while (n--)
+		push(dp, PTR);
+}
+
+static Type *structdcl(void), *enumdcl(void);
+
+static Type *
+specifier(int *sclass, int *qualifier)
+{
+	Type *tp = NULL;
+	unsigned spec, qlf, sign, type, cls, size;
+
+	spec = qlf = sign = type = cls = size = 0;
+
+	for (;;) {
+		unsigned *p = NULL;
+		Type *(*dcl)(void) = NULL;
+
+		switch (yytoken) {
+		case SCLASS:
+			p = &cls;
+			break;
+		case TQUALIFIER:
+			qlf |= yylval.token;
+			next();
+			continue;
+		case TYPEIDEN:
+			if (type)
+				goto return_type;
+			tp = yylval.sym->type;
+			p = &type;
+			break;
+		case TYPE:
+			switch (yylval.token) {
+			case ENUM:
+				dcl = enumdcl;
+				p = &type;
+				break;
+			case STRUCT:
+			case UNION:
+				dcl = structdcl;
+				p = &type;
+				break;
+			case VA_LIST:
+			case VOID:
+			case BOOL:
+			case CHAR:
+			case INT:
+			case FLOAT:
+			case DOUBLE:
+				p = &type;
+				break;
+			case SIGNED:
+			case UNSIGNED:
+				p = &sign;
+				break;
+			case LONG:
+				if (size == LONG) {
+					yylval.token = LLONG;
+					size = 0;
+				}
+			case SHORT:
+				p = &size;
+				break;
+			}
+			break;
+		default:
+			goto return_type;
+		}
+		if (*p)
+			errorp("invalid type specification");
+		*p = yylval.token;
+		if (dcl) {
+			if (size || sign)
+				errorp("invalid type specification");
+			tp = (*dcl)();
+			goto return_type;
+		} else {
+			next();
+		}
+		spec = 1;
+	}
+
+return_type:
+	*sclass = cls;
+	*qualifier = qlf;
+	if (!tp) {
+		if (spec) {
+			tp = ctype(type, sign, size);
+		} else {
+			if (curctx != GLOBALCTX)
+				unexpected();
+			warn("type defaults to 'int' in declaration");
+			tp = inttype;
+		}
+	}
+	return tp;
+}
+
+static Symbol *
+newtag(void)
+{
+	Symbol *sym;
+	int ns, op, tag = yylval.token;
+	static unsigned tpns = NS_STRUCTS;
+
+	ns = namespace;
+	namespace = NS_TAG;
+	next();
+	namespace = ns;
+
+	switch (yytoken) {
+	case IDEN:
+	case TYPEIDEN:
+		sym = yylval.sym;
+		if ((sym->flags & SDECLARED) == 0)
+			install(NS_TAG, yylval.sym);
+		next();
+		break;
+	default:
+		sym = newsym(NS_TAG, NULL);
+		break;
+	}
+	if (!sym->type) {
+		Type *tp;
+
+		if (tpns == NS_STRUCTS + NR_MAXSTRUCTS)
+			error("too many tags declared");
+		tp = mktype(NULL, tag, 0, NULL);
+		tp->ns = tpns++;
+		sym->type = tp;
+		tp->tag = sym;
+		DBG("declared tag '%s' with ns = %d\n",
+		    (sym->name) ? sym->name : "anonymous", tp->ns);
+	}
+
+	if ((op = sym->type->op) != tag &&  op != INT)
+		error("'%s' defined as wrong kind of tag", sym->name);
+	return sym;
+}
+
+static void fieldlist(Type *tp);
+
+static Type *
+structdcl(void)
+{
+	Symbol *sym;
+	Type *tp;
+	static int nested;
+	int ns;
+
+	sym = newtag();
+	tp = sym->type;
+
+	if (!accept('{'))
+		return tp;
+
+	ns = namespace;
+	namespace = tp->ns;
+
+	if (tp->prop & TDEFINED && sym->ctx == curctx)
+		error("redefinition of struct/union '%s'", sym->name);
+
+	if (nested == NR_STRUCT_LEVEL)
+		error("too many levels of nested structure or union definitions");
+
+	++nested;
+	while (yytoken != '}') {
+		fieldlist(tp);
+	}
+	--nested;
+
+	deftype(tp);
+	namespace = ns;
+	expect('}');
+	return tp;
+}
+
+static Type *
+enumdcl(void)
+{
+	Type *tp;
+	Symbol *sym, *tagsym;
+	int ns, val, toomany;
+	unsigned nctes;
+
+	ns = namespace;
+	tagsym = newtag();
+	tp = tagsym->type;
+
+	if (!accept('{'))
+		goto restore_name;
+	if (tp->prop & TDEFINED)
+		errorp("redefinition of enumeration '%s'", tagsym->name);
+	deftype(tp);
+	namespace = NS_IDEN;
+
+	/* TODO: check incorrect values in val */
+	for (nctes = val = 0; yytoken != '}'; ++nctes, ++val) {
+		if (yytoken != IDEN)
+			unexpected();
+		sym = yylval.sym;
+		next();
+		if (nctes == NR_ENUM_CTES && !toomany) {
+			errorp("too many enum constants in a single enum");
+			toomany = 1;
+		}
+		if (accept('=')) {
+			Node *np = constexpr();
+
+			if (np == NULL)
+				errorp("invalid enumeration value");
+			else
+				val = np->sym->u.i;
+			freetree(np);
+		}
+		if ((sym = install(NS_IDEN, sym)) == NULL) {
+			errorp("'%s' redeclared as different kind of symbol",
+			       yytext);
+		} else {
+			sym->u.i = val;
+			sym->flags |= SCONSTANT;
+			sym->type = inttype;
+		}
+		if (!accept(','))
+			break;
+	}
+	expect('}');
+
+restore_name:
+	namespace = ns;
+	return tp;
+}
+
+static Symbol *
+type(struct decl *dcl)
+{
+	Symbol *sym = dcl->sym;
+
+	if (dcl->sclass)
+		error("class storage in type name");
+	if (sym->name)
+		error("unexpected identifier in type name");
+	sym->type = dcl->type;
+
+	return sym;
+}
+
+static Symbol *
+field(struct decl *dcl)
+{
+	static char *anon = "<anonymous>";
+	Symbol *sym = dcl->sym;
+	char *name = (sym->name) ? sym->name : anon;
+	Type *structp = dcl->parent, *tp = dcl->type;
+	TINT n = structp->n.elem;
+	int err = 0;
+
+	if (accept(':')) {
+		Node *np;
+		TINT n;
+
+		if ((np = constexpr()) == NULL) {
+			unexpected();
+			n = 0;
+		} else {
+			n = np->sym->u.i;
+			freetree(np);
+		}
+		if (n == 0 && name != anon)
+			errorp("zero width for bit-field '%s'", name);
+		if (tp != booltype && tp != inttype && tp != uinttype)
+			errorp("bit-field '%s' has invalid type", name);
+		if (n < 0)
+			errorp("negative width in bit-field '%s'", name);
+		else if (n > tp->size*8)
+			errorp("width of '%s' exceeds its type", name);
+	} else if (empty(sym, tp, 0)) {
+		return sym;
+	}
+
+	if (tp->op == FTN) {
+		errorp("invalid type '%s' in struct/union", name);
+		err = 1;
+	}
+	if (dcl->sclass) {
+		errorp("storage class in struct/union field '%s'", name);
+		err = 1;
+	}
+	if (!(tp->prop & TDEFINED)) {
+		error("field '%s' has incomplete type", name);
+		err = 1;
+	}
+	if (err)
+		return sym;
+
+	if (sym->flags & SDECLARED)
+		error("duplicated member '%s'", name);
+	sym->flags |= SFIELD|SDECLARED;
+	sym->type = tp;
+
+	if (n == NR_FIELDS)
+		error("too many fields in struct/union");
+	DBG("New field '%s' in namespace %d\n", name, structp->ns);
+	structp->p.fields = xrealloc(structp->p.fields, ++n * sizeof(*sym));
+	structp->p.fields[n-1] = sym;
+	structp->n.elem = n;
+
+	return sym;
+}
+
+static Symbol *
+dodcl(int rep, Symbol *(*fun)(struct decl *), unsigned ns, Type *parent)
+{
+	Symbol *sym;
+	Type *base;
+	struct decl dcl;
+	struct declarators stack;
+
+	dcl.ns = ns;
+	dcl.parent = parent;
+	base = specifier(&dcl.sclass, &dcl.qualifier);
+
+	do {
+		dcl.type = base;
+		stack.nr_types = stack.nr = 0;
+		stack.tpars = dcl.buftpars;
+		stack.pars = dcl.bufpars;
+		stack.dcl = &dcl;
+		stack.ns = ns;
+
+		declarator(&stack);
+
+		while (pop(&stack, &dcl))
+			;
+		sym = (*fun)(&dcl);
+		if (funbody(sym, dcl.pars))
+			return sym;
+	} while (rep && accept(','));
+
+	return sym;
+}
+
+void
+decl(void)
+{
+	Symbol *sym;
+
+	if (accept(';'))
+		return;
+	sym = dodcl(REP, identifier, NS_IDEN, NULL);
+	if (sym->type->prop & TFUNDEF)
+		return;
+	expect(';');
+}
+
+static void
+fieldlist(Type *tp)
+{
+	if (yytoken != ';')
+		dodcl(REP, field, tp->ns, tp);
+	expect(';');
+}
+
+Type *
+typename(void)
+{
+	return dodcl(NOREP, type, NS_DUMMY, NULL)->type;
+}
--- /dev/null
+++ b/src/cmd/cc/cc1/deps.mk
@@ -1,0 +1,44 @@
+#deps
+./builtin.o: $(INCDIR)/scc/scc/scc.h
+./builtin.o: ./cc1.h
+./code.o: $(INCDIR)/scc/scc/scc.h
+./code.o: ./cc1.h
+./cpp.o: $(INCDIR)/scc/scc/cstd.h
+./cpp.o: $(INCDIR)/scc/scc/scc.h
+./cpp.o: ./cc1.h
+./decl.o: $(INCDIR)/scc/scc/cstd.h
+./decl.o: $(INCDIR)/scc/scc/scc.h
+./decl.o: ./cc1.h
+./error.o: $(INCDIR)/scc/scc/scc.h
+./error.o: ./cc1.h
+./expr.o: $(INCDIR)/scc/scc/cstd.h
+./expr.o: $(INCDIR)/scc/scc/scc.h
+./expr.o: ./cc1.h
+./fold.o: $(INCDIR)/scc/scc/scc.h
+./fold.o: ./cc1.h
+./init.o: $(INCDIR)/scc/scc/cstd.h
+./init.o: $(INCDIR)/scc/scc/scc.h
+./init.o: ./cc1.h
+./lex.o: $(INCDIR)/scc/scc/cstd.h
+./lex.o: $(INCDIR)/scc/scc/scc.h
+./lex.o: ./cc1.h
+./main.o: $(INCDIR)/scc/scc/arg.h
+./main.o: $(INCDIR)/scc/scc/scc.h
+./main.o: ./cc1.h
+./stmt.o: $(INCDIR)/scc/scc/cstd.h
+./stmt.o: $(INCDIR)/scc/scc/scc.h
+./stmt.o: ./cc1.h
+./symbol.o: $(INCDIR)/scc/scc/cstd.h
+./symbol.o: $(INCDIR)/scc/scc/scc.h
+./symbol.o: ./cc1.h
+./target/amd64-sysv/arch.o: $(INCDIR)/scc/scc/scc.h
+./target/amd64-sysv/arch.o: ./target/amd64-sysv/../../cc1.h
+./target/arm64-sysv/arch.o: $(INCDIR)/scc/scc/scc.h
+./target/arm64-sysv/arch.o: ./target/arm64-sysv/../../cc1.h
+./target/i386-sysv/arch.o: $(INCDIR)/scc/scc/scc.h
+./target/i386-sysv/arch.o: ./target/i386-sysv/../../cc1.h
+./target/z80-scc/arch.o: $(INCDIR)/scc/scc/scc.h
+./target/z80-scc/arch.o: ./target/z80-scc/../../cc1.h
+./types.o: $(INCDIR)/scc/scc/cstd.h
+./types.o: $(INCDIR)/scc/scc/scc.h
+./types.o: ./cc1.h
--- /dev/null
+++ b/src/cmd/cc/cc1/error.c
@@ -1,0 +1,84 @@
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <scc/scc.h>
+#include "cc1.h"
+
+#define MAXERRNUM 10
+
+extern int failure;
+static unsigned nerrors;
+
+static void
+warn_error(int flag, char *fmt, va_list va)
+{
+	if (flag == 0)
+		return;
+	fprintf(stderr, "%s:%u: %s: ",
+	       filenam, lineno,
+	       (flag < 0) ? "error" : "warning");
+	vfprintf(stderr, fmt, va);
+	putc('\n', stderr);
+
+	if (flag < 0) {
+		if (!failure)
+			fclose(stdout);
+		failure = 1;
+		if (++nerrors == MAXERRNUM) {
+			fputs("too many errors\n", stderr);
+			exit(1);
+		}
+	}
+}
+
+void
+warn(char *fmt, ...)
+{
+	extern int warnings;
+
+	va_list va;
+	va_start(va, fmt);
+	warn_error(warnings, fmt, va);
+	va_end(va);
+}
+
+void
+error(char *fmt, ...)
+{
+	va_list va;
+
+	va_start(va, fmt);
+	warn_error(-1, fmt, va);
+	va_end(va);
+	exit(1);
+	discard();
+}
+
+void
+errorp(char *fmt, ...)
+{
+	va_list va;
+	va_start(va, fmt);
+	warn_error(-1, fmt, va);
+	va_end(va);
+}
+
+void
+cpperror(char *fmt, ...)
+{
+	va_list va;
+	va_start(va, fmt);
+	warn_error(-1, fmt, va);
+	va_end(va);
+
+	/* discard input until the end of the line */
+	*input->p = '\0';
+	next();
+}
+
+void
+unexpected(void)
+{
+	error("unexpected '%s'", yytext);
+}
--- /dev/null
+++ b/src/cmd/cc/cc1/expr.c
@@ -1,0 +1,1184 @@
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+#include "cc1.h"
+
+#define XCHG(lp, rp, np) (np = lp, lp = rp, rp = np)
+
+static Node *xexpr(void), *xassign(void);
+
+int
+cmpnode(Node *np, TUINT val)
+{
+	Symbol *sym;
+	Type *tp;
+	TUINT mask, nodeval;
+
+	if (!np || !(np->flags & NCONST) || !np->sym)
+		return 0;
+	sym = np->sym;
+	tp = sym->type;
+
+	switch (tp->op) {
+	case PTR:
+	case INT:
+		mask = (val > 1) ? ones(np->type->size) : -1;
+		nodeval = (tp->prop & TSIGNED) ? sym->u.i : sym->u.u;
+		return (nodeval & mask) == (val & mask);
+	case FLOAT:
+		return sym->u.f == val;
+	}
+	return 0;
+}
+
+static Node *
+promote(Node *np)
+{
+	Type *tp;
+	Node *new;
+	struct limits *lim, *ilim;
+
+	tp = np->type;
+
+	switch (tp->op) {
+	case ENUM:
+	case INT:
+		if (tp->n.rank >= inttype->n.rank)
+			return np;
+		lim = getlimits(tp);
+		ilim = getlimits(inttype);
+		tp = (lim->max.i <= ilim->max.i) ? inttype : uinttype;
+		break;
+	case FLOAT:
+		/* TODO: Add support for C99 float math */
+		tp = doubletype;
+		break;
+	default:
+		abort();
+	}
+	if ((new = convert(np, tp, 1)) != NULL)
+		return new;
+	return np;
+}
+
+static void
+arithconv(Node **p1, Node **p2)
+{
+	int to = 0, s1, s2;
+	unsigned r1, r2;
+	Type *tp1, *tp2;
+	Node *np1, *np2;
+	struct limits *lp1, *lp2;
+
+	np1 = promote(*p1);
+	np2 = promote(*p2);
+
+	tp1 = np1->type;
+	tp2 = np2->type;
+
+	if (tp1 == tp2)
+		goto set_p1_p2;
+
+	s1 = (tp1->prop & TSIGNED) != 0;
+	r1 = tp1->n.rank;
+	lp1 = getlimits(tp1);
+
+	s2 = (tp2->prop & TSIGNED) != 0;
+	r2 = tp2->n.rank;
+	lp2 = getlimits(tp2);
+
+	if (s1 == s2 || tp1->op == FLOAT || tp2->op == FLOAT) {
+		to = r1 - r2;
+	} else if (!s1) {
+		if (r1 >= r2 || lp1->max.i >= lp2->max.i)
+			to = 1;
+		else
+			to = -1;
+	} else {
+		if (r2 >= r1 || lp2->max.i >= lp1->max.i)
+			to = -1;
+		else
+			to = 1;
+	}
+
+	if (to > 0)
+		np2 = convert(np2, tp1, 1);
+	else if (to < 0)
+		np1 = convert(np1, tp2, 1);
+		
+set_p1_p2:
+	*p1 = np1;
+	*p2 = np2;
+}
+
+static int
+null(Node *np)
+{
+	if (np->type != pvoidtype || np->op != OCAST)
+		return 0;
+
+	np = np->left;
+	if (np->type != inttype)
+		return 0;
+
+	return cmpnode(np, 0);
+}
+
+static Node *
+chkternary(Node *yes, Node *no)
+{
+	/*
+	 * FIXME:
+	 * We are ignoring type qualifiers here,
+	 * but the standard has strong rules about this.
+	 * take a look to 6.5.15
+	 */
+
+	if (!eqtype(yes->type, no->type, 1)) {
+		if ((yes->type->prop & TARITH) && (no->type->prop & TARITH)) {
+			arithconv(&yes, &no);
+		} else if (yes->type->op != PTR && no->type->op != PTR) {
+			goto wrong_type;
+		} else {
+			/* convert integer 0 to NULL */
+			if ((yes->type->prop & TINTEGER) && cmpnode(yes, 0))
+				yes = convert(yes, pvoidtype, 0);
+			if ((no->type->prop & TINTEGER) && cmpnode(no, 0))
+				no = convert(no, pvoidtype, 0);
+			/*
+			 * At this point the type of both should be
+			 * a pointer to something, or we have don't
+			 * compatible types
+			 */
+			if (yes->type->op != PTR || no->type->op != PTR)
+				goto wrong_type;
+			/*
+			 * If we have a null pointer constant then
+			 * convert to the another type
+			 */
+			if (null(yes))
+				yes = convert(yes, no->type, 0);
+			if (null(no))
+				no = convert(no, yes->type, 0);
+
+			if (!eqtype(yes->type, no->type, 1))
+				goto wrong_type;
+		}
+	}
+	return node(OCOLON, yes->type, yes, no);
+
+wrong_type:
+	errorp("type mismatch in conditional expression");
+	freetree(yes);
+	freetree(no);
+	return constnode(zero);
+}
+
+static void
+chklvalue(Node *np)
+{
+	if (!(np->flags & NLVAL))
+		errorp("lvalue required in operation");
+	if (np->type == voidtype)
+		errorp("invalid use of void expression");
+}
+
+Node *
+decay(Node *np)
+{
+	Node *new;
+	Type *tp = np->type;
+
+	switch (tp->op) {
+	case ARY:
+		tp = tp->type;
+		if (np->op == OPTR) {
+			new = np->left;
+			free(np);
+			new->type = mktype(tp, PTR, 0, NULL);
+			return new;
+		}
+	case FTN:
+		new = node(OADDR, mktype(tp, PTR, 0, NULL), np, NULL);
+		if (np->sym && np->sym->flags & (SGLOBAL|SLOCAL|SPRIVATE))
+			new->flags |= NCONST;
+		return new;
+	default:
+		return np;
+	}
+}
+
+static Node *
+integerop(int op, Node *lp, Node *rp)
+{
+	if (!(lp->type->prop & TINTEGER) || !(rp->type->prop & TINTEGER))
+		error("operator requires integer operands");
+	arithconv(&lp, &rp);
+	return node(op, lp->type, lp, rp);
+}
+
+static Node *
+integeruop(int op, Node *np)
+{
+	if (!(np->type->prop & TINTEGER))
+		error("unary operator requires integer operand");
+	np = promote(np);
+	return node(op, np->type, np, NULL);
+}
+
+static Node *
+numericaluop(int op, Node *np)
+{
+	if (!(np->type->prop & TARITH))
+		error("unary operator requires numerical operand");
+	np = promote(np);
+	return node(op, np->type, np, NULL);
+}
+
+Node *
+convert(Node *np, Type *newtp, int iscast)
+{
+	Type *oldtp = np->type;
+
+	if (eqtype(newtp, oldtp, 0))
+		return np;
+
+	switch (oldtp->op) {
+	case ENUM:
+	case INT:
+	case FLOAT:
+		switch (newtp->op) {
+		case PTR:
+			if (oldtp->op == FLOAT || !cmpnode(np, 0) && !iscast)
+				return NULL;
+		case INT:
+		case FLOAT:
+		case ENUM:
+			break;
+		default:
+			return NULL;
+		}
+		break;
+	case PTR:
+		switch (newtp->op) {
+		case ENUM:
+		case INT:
+		case VOID:
+			if (!iscast)
+				return NULL;
+			break;
+		case PTR:
+			if (eqtype(newtp, oldtp, 1) ||
+			    iscast ||
+			    newtp == pvoidtype || oldtp == pvoidtype) {
+				np->type = newtp;
+				return np;
+			}
+		default:
+			return NULL;
+		}
+		break;
+	default:
+		return NULL;
+	}
+	return node(OCAST, newtp, np, NULL);
+}
+
+static Node *
+parithmetic(int op, Node *lp, Node *rp)
+{
+	Type *tp;
+	Node *size, *np;
+
+	if (lp->type->op != PTR)
+		XCHG(lp, rp, np);
+
+	tp = rp->type;
+	if (tp->op == PTR && !(tp->type->prop & TDEFINED))
+		goto incomplete;
+	tp = lp->type;
+	if (!(tp->type->prop & TDEFINED))
+		goto incomplete;
+	size = sizeofnode(tp->type);
+
+	if (op == OSUB && BTYPE(rp) == PTR) {
+		if ((rp = convert(rp, lp->type, 0)) == NULL)
+			goto incorrect;
+		lp = node(OSUB, pdifftype, lp, rp);
+		return node(ODIV, inttype, lp, size);
+	}
+	if (!(rp->type->prop & TINTEGER))
+		goto incorrect;
+
+	rp = convert(promote(rp), sizettype, 0);
+	rp = node(OMUL, sizettype, rp, size);
+	rp = convert(rp, tp, 1);
+
+	return node(op, tp, lp, rp);
+
+incomplete:
+	errorp("invalid use of undefined type");
+	return lp;
+incorrect:
+	errorp("incorrect arithmetic operands");
+	return lp;
+
+}
+
+static Node *
+arithmetic(int op, Node *lp, Node *rp)
+{
+	Type *ltp = lp->type, *rtp = rp->type;
+
+	if ((ltp->prop & TARITH) && (rtp->prop & TARITH)) {
+		arithconv(&lp, &rp);
+		return node(op, lp->type, lp, rp);
+	} else if ((ltp->op == PTR || rtp->op == PTR)) {
+		switch (op) {
+		case OADD:
+		case OSUB:
+		case OA_ADD:
+		case OA_SUB:
+		case OINC:
+		case ODEC:
+			return parithmetic(op, lp, rp);
+		}
+	}
+	errorp("incorrect arithmetic operands");
+}
+
+static Node *
+pcompare(int op, Node *lp, Node *rp)
+{
+	Node *np;
+
+	if (lp->type->prop & TINTEGER)
+		XCHG(lp, rp, np);
+	else if (eqtype(lp->type, pvoidtype, 1))
+		XCHG(lp, rp, np);
+
+	if ((np = convert(rp, lp->type, 0)) != NULL)
+		rp = np;
+	else
+		errorp("incompatible types in comparison");
+	return convert(node(op, pvoidtype, lp, rp), inttype, 1);
+}
+
+static Node *
+compare(int op, Node *lp, Node *rp)
+{
+	Type *ltp, *rtp;
+
+	ltp = lp->type;
+	rtp = rp->type;
+
+	if (ltp->op == PTR || rtp->op == PTR) {
+		return pcompare(op, rp, lp);
+	} else if ((ltp->prop & TARITH) && (rtp->prop & TARITH)) {
+		arithconv(&lp, &rp);
+		return convert(node(op, lp->type, lp, rp), inttype, 1);;
+	} else {
+		errorp("incompatible types in comparison");
+		freetree(lp);
+		freetree(rp);
+		return constnode(zero);
+	}
+}
+
+int
+negop(int op)
+{
+	switch (op) {
+	case OEQ:  return ONE;
+	case ONE:  return OEQ;
+	case OLT:  return OGE;
+	case OGE:  return OLT;
+	case OLE:  return OGT;
+	case OGT:  return OLE;
+	default:   abort();
+	}
+	return op;
+}
+
+static Node *
+exp2cond(Node *np, int neg)
+{
+	if (np->type->prop & TAGGREG) {
+		errorp("used struct/union type value where scalar is required");
+		return constnode(zero);
+	}
+	switch (np->op) {
+	case ONEG:
+	case OOR:
+	case OAND:
+		return (neg) ? node(ONEG, inttype, np, NULL) : np;
+	case OEQ:
+	case ONE:
+	case OLT:
+	case OGE:
+	case OLE:
+	case OGT:
+		if (neg)
+			np->op = negop(np->op);
+		return np;
+	default:
+		return compare((neg) ?  OEQ : ONE, np, constnode(zero));
+	}
+}
+
+static Node *
+logic(int op, Node *lp, Node *rp)
+{
+	lp = exp2cond(lp, 0);
+	rp = exp2cond(rp, 0);
+	return node(op, inttype, lp, rp);
+}
+
+static Node *
+field(Node *np)
+{
+	Symbol *sym;
+
+	namespace = np->type->ns;
+	next();
+	namespace = NS_IDEN;
+
+	sym = yylval.sym;
+	if (yytoken != IDEN)
+		unexpected();
+	next();
+
+	if (!(np->type->prop & TAGGREG)) {
+		errorp("request for member '%s' in something not a structure or union",
+		      yylval.sym->name);
+		goto free_np;
+	}
+	if ((sym->flags & SDECLARED) == 0) {
+		errorp("incorrect field in struct/union");
+		goto free_np;
+	}
+	np = node(OFIELD, sym->type, np, varnode(sym));
+	np->flags |= NLVAL;
+	return np;
+
+free_np:
+	freetree(np);
+	return constnode(zero);
+}
+
+static Node *
+content(int op, Node *np)
+{
+	if (BTYPE(np) != PTR) {
+		errorp("invalid argument of memory indirection");
+	} else {
+		if (np->op == OADDR) {
+			Node *new = np->left;
+			new->type = np->type->type;
+			free(np);
+			np = new;
+		} else {
+			np = node(op, np->type->type, np, NULL);
+		}
+		np->flags |= NLVAL;
+	}
+	return np;
+}
+
+static Node *
+array(Node *lp, Node *rp)
+{
+	Type *tp;
+	Node *np;
+
+	if (!(lp->type->prop & TINTEGER) && !(rp->type->prop & TINTEGER))
+		error("array subscript is not an integer");
+	np = arithmetic(OADD, lp, rp);
+	tp = np->type;
+	if (tp->op != PTR)
+		errorp("subscripted value is neither array nor pointer");
+	return content(OPTR, np);
+}
+
+static Node *
+assignop(int op, Node *lp, Node *rp)
+{
+	if ((rp = convert(rp, lp->type, 0)) == NULL) {
+		errorp("incompatible types when assigning");
+		return lp;
+	}
+
+	return node(op, lp->type, lp, rp);
+}
+
+static Node *
+incdec(Node *np, int op)
+{
+	Type *tp = np->type;
+	Node *inc;
+
+	chklvalue(np);
+	np->flags |= NEFFECT;
+
+	if (!(tp->prop & TDEFINED)) {
+		errorp("invalid use of undefined type");
+		return np;
+	} else if (tp->op == PTR && !(tp->type->prop & TDEFINED)) {
+		errorp("%s of pointer to an incomplete type",
+		       (op == OINC || op == OA_ADD) ? "increment" : "decrement");
+		return np;
+	} else if (tp->op == PTR || (tp->prop & TARITH)) {
+		inc = constnode(one);
+	} else {
+		errorp("wrong type argument to increment or decrement");
+		return np;
+	}
+	return arithmetic(op, np, inc);
+}
+
+static Node *
+address(int op, Node *np)
+{
+	Node *new;
+
+	/*
+	 * ansi c accepts & applied to a function name, and it generates
+	 * a function pointer
+	 */
+	if (np->op == OSYM) {
+		if (np->type->op == FTN)
+			return decay(np);
+		if (np->type->op == ARY)
+			goto dont_check_lvalue;
+	}
+	chklvalue(np);
+
+dont_check_lvalue:
+	if (np->sym && (np->sym->flags & SREGISTER))
+		errorp("address of register variable '%s' requested", yytext);
+	new = node(op, mktype(np->type, PTR, 0, NULL), np, NULL);
+	if (np->sym && np->sym->flags & (SGLOBAL|SLOCAL|SPRIVATE))
+		new->flags |= NCONST;
+	return new;
+}
+
+static Node *
+negation(int op, Node *np)
+{
+	if (!(np->type->prop & TARITH) && np->type->op != PTR) {
+		errorp("invalid argument of unary '!'");
+		return constnode(zero);
+	}
+	return exp2cond(np, 1);
+}
+
+static Symbol *
+notdefined(Symbol *sym)
+{
+	int isdef;
+
+	if (namespace == NS_CPP && !strcmp(sym->name, "defined")) {
+		disexpand = 1;
+		next();
+		expect('(');
+		sym = yylval.sym;
+		expect(IDEN);
+		expect(')');
+
+		isdef = (sym->flags & SDECLARED) != 0;
+		sym = newsym(NS_IDEN, NULL);
+		sym->type = inttype;
+		sym->flags |= SCONSTANT;
+		sym->u.i = isdef;
+		disexpand = 0;
+		return sym;
+	}
+	errorp("'%s' undeclared", yytext);
+	sym->type = inttype;
+	return install(sym->ns, yylval.sym);
+}
+
+static Symbol *
+adjstrings(Symbol *sym)
+{
+	char *s, *t;
+	size_t len, n;
+	Type *tp;
+
+	tp = sym->type;
+	s = sym->u.s;
+	for (len = strlen(s);; len += n) {
+		next();
+		if (yytoken != STRING)
+			break;
+		t = yylval.sym->u.s;
+		n = strlen(t);
+		s = xrealloc(s, len + n + 1);
+		memcpy(s+len, t, n);
+		s[len + n] = '\0';
+		killsym(yylval.sym);
+	}
+	++len;
+	if (tp->n.elem != len) {
+		sym->type = mktype(chartype, ARY, len, NULL);
+		sym->u.s = s;
+	}
+	return sym;
+}
+
+/*************************************************************
+ * grammar functions                                         *
+ *************************************************************/
+static Node *
+primary(void)
+{
+	Node *np;
+	Symbol *sym;
+	Node *(*fun)(Symbol *);
+
+	sym = yylval.sym;
+	switch (yytoken) {
+	case STRING:
+		np = constnode(adjstrings(sym));
+		sym->flags |= SHASINIT;
+		emit(ODECL, sym);
+		emit(OINIT, np);
+		return varnode(sym);
+	case BUILTIN:
+		fun = sym->u.fun;
+		next();
+		expect('(');
+		np = (*fun)(sym);
+		expect(')');
+
+		/* do not call to next */
+		return np;
+	case CONSTANT:
+		np = constnode(sym);
+		break;
+	case IDEN:
+		assert((sym->flags & SCONSTANT) == 0);
+		if ((sym->flags & SDECLARED) == 0) {
+			if (namespace == NS_CPP) {
+				np = constnode(zero);
+				break;
+			}
+			sym = notdefined(sym);
+		}
+		sym->flags |= SUSED;
+		np = varnode(sym);
+		break;
+	default:
+		unexpected();
+	}
+	next();
+
+	return np;
+}
+
+static Node *
+arguments(Node *np)
+{
+	int toomany, n, op;
+	Node *par = NULL, *arg;
+	Type *argtype, **targs, *tp = np->type, *rettype;
+
+	if (tp->op == PTR && tp->type->op == FTN) {
+		np = content(OPTR, np);
+		tp = np->type;
+	}
+	if (tp->op != FTN) {
+		targs = (Type *[]) {ellipsistype};
+		n = 1;
+		rettype = inttype;
+		errorp("function or function pointer expected");
+	} else {
+		targs = tp->p.pars;
+		n = tp->n.elem;
+		rettype = tp->type;
+	}
+
+	expect('(');
+	if (yytoken == ')')
+		goto no_pars;
+	toomany = 0;
+
+	do {
+		arg = xassign();
+		argtype = *targs;
+		if (argtype == ellipsistype) {
+			n = 0;
+			switch (arg->type->op) {
+			case INT:
+				arg = promote(arg);
+				break;
+			case FLOAT:
+				if (arg->type == floattype)
+					arg = convert(arg, doubletype, 1);
+				break;
+			}
+			par = node(OPAR, arg->type, par, arg);
+			continue;
+		}
+		if (--n < 0) {
+			if (!toomany)
+				errorp("too many arguments in function call");
+			toomany = 1;
+			continue;
+		}
+		++targs;
+		if ((arg = convert(arg, argtype, 0)) != NULL) {
+			par = node(OPAR, arg->type, par, arg);
+			continue;
+		}
+		errorp("incompatible type for argument %d in function call",
+		       tp->n.elem - n + 1);
+	} while (accept(','));
+
+no_pars:
+	expect(')');
+	if (n > 0 && *targs != ellipsistype)
+		errorp("too few arguments in function call");
+
+	op = (tp->prop&TELLIPSIS) ? OCALLE : OCALL;
+	return node(op, rettype, np, par);
+}
+
+static Node *unary(int);
+
+static Type *
+typeof(Node *np)
+{
+	Type *tp;
+
+	if (np == NULL)
+		unexpected();
+	tp = np->type;
+	freetree(np);
+	return tp;
+}
+
+static Type *
+sizeexp(void)
+{
+	Type *tp;
+
+	expect('(');
+	switch (yytoken) {
+	case TYPE:
+	case TYPEIDEN:
+		tp = typename();
+		break;
+	default:
+		tp = typeof(unary(0));
+		break;
+	}
+	expect(')');
+	return tp;
+}
+
+static Node *
+postfix(Node *lp)
+{
+	Node *rp;
+
+	for (;;) {
+		switch (yytoken) {
+		case '[':
+		case DEC:
+		case INC:
+		case INDIR:
+		case '.':
+		case '(':
+			lp = decay(lp);
+			switch (yytoken) {
+			case '[':
+				next();
+				rp = xexpr();
+				expect(']');
+				lp = array(lp, rp);
+				break;
+			case DEC:
+			case INC:
+				lp = incdec(lp, (yytoken == INC) ? OINC : ODEC);
+				next();
+				break;
+			case INDIR:
+				lp = content(OPTR, lp);
+			case '.':
+				lp = field(lp);
+				break;
+			case '(':
+				lp = arguments(lp);
+				lp->flags |= NEFFECT;
+				break;
+			}
+			break;
+		default:
+			return lp;
+		}
+	}
+}
+
+static Node *
+defined(void)
+{
+	Symbol *sym;
+	int paren;
+
+	disexpand = 1;
+	next();
+	paren = accept('(');
+	if (yytoken != IDEN && yytoken != TYPEIDEN)
+		cpperror("operator 'defined' requires an identifier");
+	if (yytoken == TYPEIDEN || !(yylval.sym->flags & SDECLARED))
+		sym = zero;
+	else
+		sym = one;
+	disexpand = 0;
+	next();
+	if (paren)
+		expect(')');
+	return constnode(sym);
+}
+
+static Node *cast(int);
+
+static Node *
+unary(int needdecay)
+{
+	Node *(*fun)(int, Node *), *np;
+	int op;
+	Type *tp;
+
+	switch (yytoken) {
+	case '!': op = 0;     fun = negation;     break;
+	case '+': op = OADD;  fun = numericaluop; break;
+	case '-': op = OSNEG; fun = numericaluop; break;
+	case '~': op = OCPL;  fun = integeruop;   break;
+	case '&': op = OADDR; fun = address;      break;
+	case '*': op = OPTR;  fun = content;      break;
+	case SIZEOF:
+		next();
+		tp = (yytoken == '(') ? sizeexp() : typeof(unary(0));
+		if (!(tp->prop & TDEFINED))
+			errorp("sizeof applied to an incomplete type");
+		return sizeofnode(tp);
+	case INC:
+	case DEC:
+		op = (yytoken == INC) ? OA_ADD : OA_SUB;
+		next();
+		np = incdec(unary(1), op);
+		goto chk_decay;
+	case IDEN:
+	case TYPEIDEN:
+		if (lexmode == CPPMODE && !strcmp(yylval.sym->name, "defined"))
+			return defined();
+	default:
+		np = postfix(primary());
+		goto chk_decay;
+	}
+
+	next();
+	np = (*fun)(op, cast(op != OADDR));
+
+chk_decay:
+	if (needdecay)
+		np = decay(np);
+	return np;
+}
+
+static Node *
+cast(int needdecay)
+{
+	Node *lp, *rp;
+	Type *tp;
+	static int nested;
+
+	if (!accept('('))
+		return unary(needdecay);
+
+	switch (yytoken) {
+	case TQUALIFIER:
+	case TYPE:
+	case TYPEIDEN:
+		tp = typename();
+		expect(')');
+
+		if (yytoken == '{')
+			return initlist(tp);
+
+		switch (tp->op) {
+		case ARY:
+			error("cast specifies an array type");
+		default:
+			lp = cast(needdecay);
+			if ((rp = convert(lp,  tp, 1)) == NULL)
+				error("bad type conversion requested");
+			rp->flags &= ~NLVAL;
+			rp->flags |= lp->flags & NLVAL;
+		}
+		break;
+	default:
+		if (nested == NR_SUBEXPR)
+			error("too many expressions nested by parentheses");
+		++nested;
+		rp = xexpr();
+		--nested;
+		expect(')');
+		rp = postfix(rp);
+		break;
+	}
+
+	return rp;
+}
+
+static Node *
+mul(void)
+{
+	Node *np, *(*fun)(int, Node *, Node *);
+	int op;
+
+	np = cast(1);
+	for (;;) {
+		switch (yytoken) {
+		case '*': op = OMUL; fun = arithmetic; break;
+		case '/': op = ODIV; fun = arithmetic; break;
+		case '%': op = OMOD; fun = integerop;  break;
+		default: return np;
+		}
+		next();
+		np = (*fun)(op, np, cast(1));
+	}
+}
+
+static Node *
+add(void)
+{
+	int op;
+	Node *np;
+
+	np = mul();
+	for (;;) {
+		switch (yytoken) {
+		case '+': op = OADD; break;
+		case '-': op = OSUB; break;
+		default:  return np;
+		}
+		next();
+		np = arithmetic(op, np, mul());
+	}
+}
+
+static Node *
+shift(void)
+{
+	int op;
+	Node *np;
+
+	np = add();
+	for (;;) {
+		switch (yytoken) {
+		case SHL: op = OSHL; break;
+		case SHR: op = OSHR; break;
+		default:  return np;
+		}
+		next();
+		np = integerop(op, np, add());
+	}
+}
+
+static Node *
+relational(void)
+{
+	int op;
+	Node *np;
+
+	np = shift();
+	for (;;) {
+		switch (yytoken) {
+		case '<': op = OLT; break;
+		case '>': op = OGT; break;
+		case GE:  op = OGE; break;
+		case LE:  op = OLE; break;
+		default:  return np;
+		}
+		next();
+		np = compare(op, np, shift());
+	}
+}
+
+static Node *
+eq(void)
+{
+	int op;
+	Node *np;
+
+	np = relational();
+	for (;;) {
+		switch (yytoken) {
+		case EQ: op = OEQ; break;
+		case NE: op = ONE; break;
+		default: return np;
+		}
+		next();
+		np = compare(op, np, relational());
+	}
+}
+
+static Node *
+bit_and(void)
+{
+	Node *np;
+
+	np = eq();
+	while (accept('&'))
+		np = integerop(OBAND, np, eq());
+	return np;
+}
+
+static Node *
+bit_xor(void)
+{
+	Node *np;
+
+	np = bit_and();
+	while (accept('^'))
+		np = integerop(OBXOR,  np, bit_and());
+	return np;
+}
+
+static Node *
+bit_or(void)
+{
+	Node *np;
+
+	np = bit_xor();
+	while (accept('|'))
+		np = integerop(OBOR, np, bit_xor());
+	return np;
+}
+
+static Node *
+and(void)
+{
+	Node *np;
+
+	np = bit_or();
+	while (accept(AND))
+		np = logic(OAND, np, bit_or());
+	return np;
+}
+
+static Node *
+or(void)
+{
+	Node *np;
+
+	np = and();
+	while (accept(OR))
+		np = logic(OOR, np, and());
+	return np;
+}
+
+static Node *
+ternary(void)
+{
+	Node *cond;
+
+	cond = or();
+	while (accept('?')) {
+		Node *ifyes, *ifno, *np;
+
+		cond = exp2cond(cond, 0);
+		ifyes = xexpr();
+		expect(':');
+		ifno = ternary();
+		np = chkternary(ifyes, ifno);
+		cond = node(OASK, np->type, cond, np);
+	}
+	return cond;
+}
+
+static Node *
+xassign(void)
+{
+	Node *np, *(*fun)(int , Node *, Node *);
+	int op;
+
+	np = ternary();
+	for (;;) {
+		switch (yytoken) {
+		case '=':    op = OASSIGN; fun = assignop;   break;
+		case MUL_EQ: op = OA_MUL;  fun = arithmetic; break;
+		case DIV_EQ: op = OA_DIV;  fun = arithmetic; break;
+		case MOD_EQ: op = OA_MOD;  fun = integerop;  break;
+		case ADD_EQ: op = OA_ADD;  fun = arithmetic; break;
+		case SUB_EQ: op = OA_SUB;  fun = arithmetic; break;
+		case SHL_EQ: op = OA_SHL;  fun = integerop;  break;
+		case SHR_EQ: op = OA_SHR;  fun = integerop;  break;
+		case AND_EQ: op = OA_AND;  fun = integerop;  break;
+		case XOR_EQ: op = OA_XOR;  fun = integerop;  break;
+		case OR_EQ:  op = OA_OR;   fun = integerop;  break;
+		default: return np;
+		}
+		chklvalue(np);
+		np->flags |= NEFFECT;
+		next();
+		np = (fun)(op, np, assign());
+	}
+}
+
+static Node *
+xexpr(void)
+{
+	Node *lp, *rp;
+
+	lp = xassign();
+	while (accept(',')) {
+		rp = xassign();
+		lp = node(OCOMMA, rp->type, lp, rp);
+	}
+	return lp;
+}
+
+Node *
+assign(void)
+{
+	return simplify(xassign());
+}
+
+Node *
+constexpr(void)
+{
+	Node *np;
+
+	np = ternary();
+	if (np && np->type->op == INT) {
+		np = simplify(convert(np, inttype, 0));
+		if (np->flags & NCONST)
+			return np;
+	}
+	freetree(np);
+	return NULL;
+}
+
+Node *
+expr(void)
+{
+	return simplify(xexpr());
+}
+
+Node *
+condexpr(int neg)
+{
+	Node *np;
+
+	np = exp2cond(xexpr(), neg);
+	if (np->flags & NCONST)
+		warn("conditional expression is constant");
+	return simplify(np);
+}
--- /dev/null
+++ b/src/cmd/cc/cc1/fold.c
@@ -1,0 +1,684 @@
+#include <assert.h>
+#include <stdlib.h>
+
+#include <scc/scc.h>
+#include "cc1.h"
+
+
+TUINT
+ones(int nbytes)
+{
+	return (nbytes == 8) ? -1 : ~(-1ull << nbytes * 8);
+}
+
+static int
+addi(TINT l, TINT r, Type *tp)
+{
+	struct limits *lim = getlimits(tp);
+	TINT max = lim->max.i, min = -lim->min.i;
+
+	if (l < 0 && r < 0 && l >= min - r ||
+	    l == 0 ||
+	    r == 0 ||
+	    l < 0 && r > 0 ||
+	    l > 0 && r < 0 ||
+	    l > 0 && r > 0 && l <= max - r) {
+		return 1;
+	}
+	warn("overflow in constant expression");
+	return 0;
+}
+
+static int
+addf(TFLOAT l, TFLOAT r, Type *tp)
+{
+	struct limits *lim = getlimits(tp);
+	TFLOAT max = lim->max.f, min = lim->min.f;
+
+	if (l < 0 && r < 0 && l >= min - r ||
+	    l == 0 ||
+	    r == 0 ||
+	    l < 0 && r > 0 ||
+	    l > 0 && r < 0 ||
+	    l > 0 && r > 0 && l <= max - r) {
+		return 1;
+	}
+	warn("overflow in constant expression");
+	return 0;
+}
+
+static int
+subi(TINT l, TINT r, Type *tp)
+{
+	return addi(l, -r, tp);
+}
+
+static int
+subf(TFLOAT l, TFLOAT r, Type *tp)
+{
+	return addf(l, -r, tp);
+}
+
+static int
+muli(TINT l, TINT r, Type *tp)
+{
+	struct limits *lim = getlimits(tp);
+	TINT max = lim->max.i, min = -lim->min.i;
+
+	if (l > -1 && l <= 1 ||
+	    r > -1 && r <= 1 ||
+	    l < 0 && r < 0 && -l <= max/-r ||
+	    l < 0 && r > 0 &&  l >= min/r  ||
+	    l > 0 && r < 0 &&  r >= min/l  ||
+	    l > 0 && r > 0 &&  l <= max/r) {
+			return 1;
+	}
+	warn("overflow in constant expression");
+	return 0;
+}
+
+static int
+mulf(TFLOAT l, TFLOAT r, Type *tp)
+{
+	struct limits *lim = getlimits(tp);
+	TFLOAT max = lim->max.f, min = lim->min.f;
+
+	if (l > -1 && l <= 1 ||
+	    r > -1 && r <= 1 ||
+	    l < 0 && r < 0 && -l <= max/-r ||
+	    l < 0 && r > 0 &&  l >= min/r  ||
+	    l > 0 && r < 0 &&  r >= min/l  ||
+	    l > 0 && r > 0 &&  l <= max/r) {
+			return 1;
+	}
+	warn("overflow in constant expression");
+	return 0;
+}
+
+static int
+divi(TINT l, TINT r,  Type *tp)
+{
+	struct limits *lim = getlimits(tp);
+
+	if (r == 0 || l == -lim->min.i && r == -1) {
+		warn("overflow in constant expression");
+		return 0;
+	}
+	return 1;
+}
+
+static int
+divf(TFLOAT l, TFLOAT r,  Type *tp)
+{
+	struct limits *lim = getlimits(tp);
+
+	if (l < 0) l = -l;
+	if (r < 0) r = -r;
+
+	if (r == 0.0 || r < 1.0 && l > lim->max.f * r) {
+		warn("overflow in constant expression");
+		return 0;
+	}
+	return 1;
+}
+
+static int
+lshi(TINT l, TINT r, Type *tp)
+{
+	if (r < 0 || r >= tp->size * 8) {
+		warn("shifting %d bits is undefined", r);
+		return 0;
+	}
+	return muli(l, 1 << r, tp);
+}
+
+static int
+rshi(TINT l, TINT r, Type *tp)
+{
+	if (r < 0 || r >= tp->size * 8) {
+		warn("shifting %d bits is undefined", r);
+		return 0;
+	}
+	return 1;
+}
+
+static int
+foldint(int op, Symbol *res, TINT l, TINT r)
+{
+	TINT i;
+	Type *tp = res->type;
+	int (*validate)(TINT, TINT, Type *tp);
+
+	switch (op) {
+	case OADD: validate = addi; break;
+	case OSUB: validate = subi; break;
+	case OMUL: validate = muli; break;
+	case ODIV: validate = divi; break;
+	case OSHL: validate = lshi; break;
+	case OSHR: validate = rshi; break;
+	case OMOD: validate = divi; break;
+	default:   validate = NULL; break;
+	}
+
+	if (validate && !(*validate)(l, r, tp))
+		return 0;
+
+	switch (op) {
+	case OADD:  i = l + r;  break;
+	case OSUB:  i = l - r;  break;
+	case OMUL:  i = l * r;  break;
+	case ODIV:  i = l / r;  break;
+	case OMOD:  i = l % r;  break;
+	case OSHL:  i = l << r; break;
+	case OSHR:  i = l >> r; break;
+	case OBAND: i = l & r;  break;
+	case OBXOR: i = l ^ r;  break;
+	case OBOR:  i = l | r;  break;
+	case OAND:  i = l && r; break;
+	case OOR:   i = l || r; break;
+	case OLT:   i = l < r;  break;
+	case OGT:   i = l > r;  break;
+	case OGE:   i = l >= r; break;
+	case OLE:   i = l <= r; break;
+	case OEQ:   i = l == r; break;
+	case ONE:   i = l != r; break;
+	case ONEG:  i = !l;     break;
+	case OSNEG: i = -l;     break;
+	case OCPL:  i = ~l;     break;
+	default:    return 0;
+	}
+	res->u.i = i;
+
+	DBG("FOLD i l=%lld %d r=%lld = %lld", l, op, r, i);
+	return 1;
+}
+
+static int
+folduint(int op, Symbol *res, TUINT l, TUINT r)
+{
+	TINT i;
+	TUINT u;
+
+	switch (op) {
+	case OADD:  u = l + r;  break;
+	case OSUB:  u = l - r;  break;
+	case OMUL:  u = l * r;  break;
+	case ODIV:  u = l / r;  break;
+	case OMOD:  u = l % r;  break;
+	case OSHL:  u = l << r; break;
+	case OSHR:  u = l >> r; break;
+	case OBAND: u = l & r;  break;
+	case OBXOR: u = l ^ r;  break;
+	case OBOR:  u = l | r;  break;
+	case ONEG:  u = !l;     break;
+	case OSNEG: u = -l;     break;
+	case OCPL:  u = ~l;     break;
+	case OAND:  i = l && r; goto sign;
+	case OOR:   i = l || r; goto sign;
+	case OLT:   i = l < r;  goto sign;
+	case OGT:   i = l > r;  goto sign;
+	case OGE:   i = l >= r; goto sign;
+	case OLE:   i = l <= r; goto sign;
+	case OEQ:   i = l == r; goto sign;
+	case ONE:   i = l != r; goto sign;
+	default:    return 0;
+	}
+	res->u.u = u & ones(res->type->size);
+
+	DBG("FOLD ui l=%llu %d r=%llu = %llu", l, op, r, u);
+	return 1;
+
+sign:
+	res->u.i = i;
+
+	DBG("FOLD sui %llu %d %llu = %llu", l, op, r, i);
+	return 1;
+}
+
+static int
+foldfloat(int op, Symbol *res, TFLOAT l, TFLOAT r)
+{
+	TFLOAT f;
+	TINT i;
+	int (*validate)(TFLOAT, TFLOAT, Type *tp);
+
+	switch (op) {
+	case OADD: validate = addf; break;
+	case OSUB: validate = subf; break;
+	case OMUL: validate = mulf; break;
+	case ODIV: validate = divf; break;
+	default:   validate = NULL; break;
+	}
+
+	if (validate && !(*validate)(l, r, res->type))
+		return 0;
+
+	switch (op) {
+	case OADD: f = l + r;  break;
+	case OSUB: f = l - r;  break;
+	case OMUL: f = l * r;  break;
+	case ODIV: f = l / r;  break;
+	case OLT:  i = l < r;  goto comparison;
+	case OGT:  i = l > r;  goto comparison;
+	case OGE:  i = l >= r; goto comparison;
+	case OLE:  i = l <= r; goto comparison;
+	case OEQ:  i = l == r; goto comparison;
+	case ONE:  i = l != r; goto comparison;
+	default:   return 0;
+	}
+	res->u.f = f;
+
+	DBG("FOLD f l=%lf %d r=%lf = %lf", l, op, r, f);
+	return 1;
+
+comparison:
+	res->u.i = i;
+
+	DBG("FOLD if l=%lf %d r=%lf = %lld", l, op, r, i);
+	return 1;
+}
+
+static Node *
+foldconst(int type, int op, Type *tp, Symbol *ls, Symbol *rs)
+{
+	Symbol *sym, aux;
+	TINT i;
+	TUINT u;
+	TFLOAT f;
+
+	aux.type = tp;
+	switch (type) {
+	case INT:
+		i = (rs) ? rs->u.i : 0;
+		if (!foldint(op, &aux, ls->u.i, i))
+			return NULL;
+		break;
+	case UNSIGNED:
+		u = (rs) ? rs->u.u : 0u;
+		if (!folduint(op, &aux, ls->u.u, u))
+			return NULL;
+		break;
+	case FLOAT:
+		f = (rs) ? rs->u.f : 0.0;
+		if (!foldfloat(op, &aux, ls->u.f, f))
+			return NULL;
+		break;
+	}
+	sym = newsym(NS_IDEN, NULL);
+	sym->flags |= SCONSTANT;
+	sym->type = tp;
+	sym->u = aux.u;
+	return constnode(sym);
+}
+
+static Node *
+foldcast(Node *np, Node *l)
+{
+	TUINT negmask, mask, u;
+	Type *newtp = np->type, *oldtp = l->type;
+	Symbol aux, *sym, *osym = l->sym;
+
+	if (!(l->flags & NCONST))
+		return np;
+
+	switch (newtp->op) {
+	case PTR:
+	case INT:
+	case ENUM:
+		switch (oldtp->op) {
+		case PTR:
+		case INT:
+		case ENUM:
+			u = (oldtp->prop & TSIGNED) ? osym->u.i : osym->u.u;
+			break;
+		case FLOAT:
+			oldtp = newtp;
+			u = osym->u.f;
+			break;
+		default:
+			return  np;
+		}
+		mask = ones(newtp->size);
+		if (newtp->prop & TSIGNED) {
+			negmask = ~mask;
+			if (u & (negmask >> 1) & mask)
+				u |= negmask;
+			aux.u.i = u;
+		} else {
+			aux.u.u = u & mask;
+		}
+		break;
+	case FLOAT:
+		/* FIXME: The cast can be from another float type */
+		aux.u.f = (oldtp->prop & TSIGNED) ? osym->u.i : osym->u.u;
+		break;
+	default:
+		return np;
+	}
+	DBG("FOLD cast %c->%c", oldtp->letter, newtp->letter);
+	freetree(np);
+	sym = newsym(NS_IDEN, NULL);
+	sym->flags |= SCONSTANT;
+	sym->type = newtp;
+	sym->u = aux.u;
+	return constnode(sym);
+}
+
+static Node *
+foldunary(Node *np, Node *l)
+{
+	int op = l->op;
+	Node *aux;
+
+	switch (np->op) {
+	case ONEG:
+		if (l->op == ONEG)
+			break;
+		return NULL;
+	case OADD:
+		DBG("FOLD unary delete %d", np->op);
+		np->left = NULL;
+		freetree(np);
+		return l;
+	case OCAST:
+		if (op != OCAST)
+			return foldcast(np, l);
+		/* TODO: This is wrong: (float)(int) 7.2 */
+		DBG("FOLD unary collapse %d", np->op);
+		np->left = l->left;
+		l->left = NULL;
+		freetree(l);
+		return np;
+	case OSNEG:
+	case OCPL:
+		if (op != np->op)
+			return NULL;
+		break;
+	case OPTR:
+		if (op != OADDR || np->type != l->left->type)
+			return NULL;
+		break;
+	case OADDR:
+		if (op != OPTR)
+			return NULL;
+		break;
+	default:
+		return NULL;
+	}
+	DBG("FOLD unary cancel %d", np->op);
+	aux = l->left;
+	l->left = NULL;
+	freetree(np);
+	return aux;
+}
+
+static Node *
+fold(Node *np)
+{
+	Symbol *rs, *ls;
+	Type *optype;
+	int type;
+	int op = np->op;
+	Node *p, *lp = np->left, *rp = np->right;
+	Type *tp = np->type;
+
+	assert(lp && rp);
+	if ((op == ODIV || op == OMOD) && cmpnode(rp, 0)) {
+		warn("division by 0");
+		return NULL;
+	}
+	/*
+	 * Return if any of the children is no constant,
+	 * or it is a constant generated when
+	 * the address of a static variable is taken
+	 * (when we don't know the physical address so
+	 * we cannot fold it)
+	 */
+	if (!rp) {
+		rs = NULL;
+	} else {
+		if (!(rp->flags & NCONST) || !rp->sym)
+			return NULL;
+		rs = rp->sym;
+	}
+
+	if (!(lp->flags & NCONST) || !lp->sym)
+		return NULL;
+	optype = lp->type;
+	ls = lp->sym;
+
+	switch (type = optype->op) {
+	case ENUM:
+	case INT:
+		if (!(optype->prop & TSIGNED))
+			type = UNSIGNED;
+	case PTR:
+	case FLOAT:
+		if ((p = foldconst(type, op, tp, ls, rs)) == NULL)
+			return NULL;
+		freetree(np);
+		return p;
+	default:
+		return NULL;
+	}
+}
+
+static void
+commutative(Node *np, Node *l, Node *r)
+{
+	int op = np->op;
+
+	if (r == NULL || r->flags&NCONST || !(l->flags&NCONST))
+		return;
+
+	switch (op) {
+	case OLT:
+	case OGT:
+	case OGE:
+	case OLE:
+		DBG("FOLD neg commutative %d", np->op);
+		np->op = negop(op);
+	case OEQ:
+	case ONE:
+	case OADD:
+	case OMUL:
+	case OBAND:
+	case OBXOR:
+	case OBOR:
+		DBG("FOLD commutative %d", np->op);
+		np->left = r;
+		np->right = l;
+		break;
+	}
+}
+
+static Node *
+identity(Node *np)
+{
+	int iszeror, isoner;
+	int iszerol, isonel;
+	Node *lp = np->left, *rp = np->right;
+
+	if (!rp)
+		return NULL;
+
+	iszeror = cmpnode(rp, 0);
+	isoner = cmpnode(rp, 1),
+	iszerol = cmpnode(lp, 0);
+	isonel = cmpnode(lp, 1);
+
+	switch (np->op) {
+	case OOR:
+		/*
+		 * 1 || i => 1    (free right)
+		 * i || 0 => i    (free right)
+		 * 0 || i => i    (free left)
+		 * i || 1 => i,1  (comma)
+		 */
+		if (isonel | iszeror)
+			goto free_right;
+		if (iszerol)
+			goto free_left;
+		if (isoner)
+			goto change_to_comma;
+		return NULL;
+	case OAND:
+		/*
+		 * 0 && i => 0    (free right)
+		 * i && 1 => i    (free right)
+		 * 1 && i => i    (free left)
+		 * i && 0 => i,0  (comma)
+		 */
+		if (iszerol | isoner)
+			goto free_right;
+		if (isonel)
+			goto free_left;
+		if (iszeror)
+			goto change_to_comma;
+		return NULL;
+	case OSHL:
+	case OSHR:
+		/*
+		 * i >> 0 => i    (free right)
+		 * i << 0 => i    (free right)
+		 * 0 >> i => 0    (free right)
+		 * 0 << i => 0    (free right)
+		 */
+		if (iszeror | iszerol)
+			goto free_right;
+		return NULL;
+	case OBXOR:
+	case OADD:
+	case OBOR:
+	case OSUB:
+		/*
+		 * i + 0  => i
+		 * i - 0  => i
+		 * i | 0  => i
+		 * i ^ 0  => i
+		 */
+		if (iszeror)
+			goto free_right;
+		return NULL;
+	case OMUL:
+		/*
+		 * i * 0  => i,0
+		 * i * 1  => i
+		 */
+		if (iszeror)
+			goto change_to_comma;
+		if (isoner)
+			goto free_right;
+		return NULL;
+	case ODIV:
+		/* i / 1  => i */
+		if (isoner)
+			goto free_right;
+		return NULL;
+	case OBAND:
+		/* i & ~0 => i */
+		if (cmpnode(rp, -1))
+			goto free_right;
+		return NULL;
+	case OMOD:
+		/* i % 1  => i,1 */
+		/* TODO: i % 2^n => i & n-1 */
+		if (isoner)
+			goto change_to_comma;
+	default:
+		return NULL;
+	}
+
+free_right:
+	DBG("FOLD identity %d", np->op);
+	np->left = NULL;
+	freetree(np);
+	return lp;
+
+free_left:
+	DBG("FOLD identity %d", np->op);
+	np->right = NULL;
+	freetree(np);
+	return rp;
+
+change_to_comma:
+	DBG("FOLD identity %d", np->op);
+	np->op = OCOMMA;
+	return np;
+}
+
+static Node *
+foldternary(Node *np, Node *cond, Node *body)
+{
+	if (!(cond->flags & NCONST))
+		return np;
+	if (cmpnode(cond, 0)) {
+		np = body->right;
+		freetree(body->left);
+	} else {
+		np = body->left;
+		freetree(body->right);
+	}
+
+	DBG("FOLD ternary");
+	body->left = NULL;
+	body->right = NULL;
+	freetree(cond);
+	free(body);
+	return np;
+}
+
+/* TODO: fold OCOMMA */
+
+Node *
+simplify(Node *np)
+{
+	Node *p, *l, *r;
+
+	if (!np)
+		return NULL;
+	if (enadebug)
+		prtree(np);
+
+	l = np->left = simplify(np->left);
+	r = np->right = simplify(np->right);
+
+	switch (np->op) {
+	case OASK:
+		return foldternary(np, l, r);
+	case OCALL:
+	case OPAR:
+	case OSYM:
+	case OASSIGN:
+	case OA_MUL:
+	case OA_DIV:
+	case OA_MOD:
+	case OA_ADD:
+	case OA_SUB:
+	case OA_SHL:
+	case OA_SHR:
+	case OA_AND:
+	case OA_XOR:
+	case OA_OR:
+		return np;
+	case OSNEG:
+	case OCPL:
+	case OADDR:
+	case OPTR:
+	case INC:
+	case DEC:
+	case OCAST:
+	case ONEG:
+		assert(!r);
+		if ((p = foldunary(np, l)) != NULL)
+			return p;
+		return np;
+	default:
+		commutative(np, l, r);
+		if ((p = fold(np)) != NULL)
+			return p;
+		if ((p = identity(np)) != NULL)
+			return p;
+		return np;
+	}
+}
--- /dev/null
+++ b/src/cmd/cc/cc1/init.c
@@ -1,0 +1,377 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+#include "cc1.h"
+
+
+typedef struct init Init;
+
+struct designator {
+	TINT pos;
+	Node *expr;
+	struct designator *next;
+};
+
+struct init {
+	TUINT pos;
+	TUINT max;
+	struct designator *tail;
+	struct designator *head;
+};
+
+static TINT
+arydesig(Type *tp, Init *ip)
+{
+	TINT npos;
+	Node *np;
+
+	if (tp->op != ARY)
+		errorp("array index in non-array initializer");
+	next();
+	np = constexpr();
+	npos = np->sym->u.i;
+	if (npos < 0 || (tp->prop & TDEFINED) && npos >= tp->n.elem) {
+		errorp("array index in initializer exceeds array bounds");
+		npos = 0;
+	}
+	freetree(np);
+	expect(']');
+	return npos;
+}
+
+static TINT
+fielddesig(Type *tp, Init *ip)
+{
+	int ons;
+	Symbol *sym, **p;
+
+	if (!(tp->prop & TAGGREG))
+		errorp("field name not in record or union initializer");
+	ons = namespace;
+	namespace = tp->ns;
+	next();
+	namespace = ons;
+	if (yytoken != IDEN)
+		unexpected();
+	sym = yylval.sym;
+	next();
+	if ((sym->flags & SDECLARED) == 0) {
+		errorp("unknown field '%s' specified in initializer",
+		      sym->name);
+		return 0;
+	}
+	for (p = tp->p.fields; *p != sym; ++p)
+		;
+	return p - tp->p.fields;
+}
+
+static Init *
+init(Init *ip)
+{
+	ip->tail = ip->head = NULL;
+	ip->pos = ip->max = 0;
+	return ip;
+}
+
+static Node *
+str2ary(Type *tp)
+{
+	Node *np;
+	Type *btp = tp->type;;
+	Symbol *sym;
+	size_t len;
+	char *s;
+
+	np = assign();
+	sym = np->left->sym;
+	if (btp != chartype && btp != uchartype && btp != schartype) {
+		errorp("array of inappropriate type initialized from string constant");
+		return constnode(zero);
+	}
+
+	len = sym->type->n.elem-1;
+	if (!(tp->prop & TDEFINED)) {
+		tp->n.elem = len+1;
+		deftype(tp);
+	} else if (tp->n.elem < len) {
+		warn("initializer-string for array of chars is too long");
+	}
+
+	len = tp->n.elem;
+	s = sym->u.s;
+	sym = newstring(NULL, len);
+	strncpy(sym->u.s, s, len);
+	np->sym = sym;
+	np->type = sym->type;
+
+	return np;
+}
+
+static Node *
+initialize(Type *tp)
+{
+	Node *np;
+	Symbol *sym;
+
+	if (tp->op == ARY && yytoken == STRING)
+		return str2ary(tp);
+
+	if (yytoken == '{' || tp->op == STRUCT || tp->op == ARY)
+		return initlist(tp);
+
+	np = assign();
+	if (eqtype(tp, np->type, 1))
+		return np;
+
+	np = convert(decay(np), tp, 0);
+	if (!np) {
+		errorp("incorrect initializer");
+		return constnode(zero);
+	}
+
+	return simplify(np);
+}
+
+static Node *
+mkcompound(Init *ip, Type *tp)
+{
+	Node **v, **p;
+	size_t n;
+	struct designator *dp, *next;
+	Symbol *sym;
+
+	if (tp->op == UNION) {
+		Node *np = NULL;
+
+		v = xmalloc(sizeof(*v));
+		for (dp = ip->head; dp; dp = next) {
+			freetree(np);
+			np = dp->expr;
+			next = dp->next;
+			free(dp);
+		}
+		*v = np;
+	} else {
+		n = (tp->prop&TDEFINED) ? tp->n.elem : ip->max;
+		if (n == 0) {
+			v = NULL;
+		} else if (n > SIZE_MAX / sizeof(*v)) {
+			errorp("compound literal too big");
+			return constnode(zero);
+		} else {
+			n *= sizeof(*v);
+			v = memset(xmalloc(n), 0, n);
+
+			for (dp = ip->head; dp; dp = next) {
+				p = &v[dp->pos];
+				freetree(*p);
+				*p = dp->expr;
+				next = dp->next;
+				free(dp);
+			}
+		}
+	}
+
+	sym = newsym(NS_IDEN, NULL);
+	sym->u.init = v;
+	sym->type = tp;
+	sym->flags |= SINITLST;
+
+	return constnode(sym);
+}
+
+static void
+newdesig(Init *ip, Node *np)
+{
+	struct designator *dp;
+
+	dp = xmalloc(sizeof(*dp));
+	dp->pos = ip->pos;
+	dp->expr = np;
+	dp->next = NULL;
+
+	if (ip->head == NULL) {
+		ip->head = ip->tail = dp;
+	} else {
+		ip->tail->next = dp;
+		ip->tail = dp;
+	}
+
+	if (ip->pos+1 > ip->max)
+		ip->max = ip->pos+1;
+}
+
+Node *
+initlist(Type *tp)
+{
+	Init in;
+	Node *np;
+	Type *curtp;
+	int braces, scalar, toomany, outbound;
+	TINT nelem = tp->n.elem;
+	static int depth;
+
+	if (depth == NR_SUBTYPE)
+		error("too many nested initializers");
+	++depth;
+	init(&in);
+	braces = scalar = toomany = 0;
+
+	if (accept('{'))
+		braces = 1;
+
+	do {
+		curtp = inttype;
+		switch (yytoken) {
+		case '[':
+			in.pos = arydesig(tp, &in);
+			curtp = tp->type;
+			goto desig_list;
+		case '.':
+			in.pos = fielddesig(tp, &in);
+			if (in.pos < nelem)
+				curtp = tp->p.fields[in.pos]->type;
+		desig_list:
+			if (yytoken == '[' || yytoken == '.') {
+				np = initlist(curtp);
+				goto new_desig;
+			}
+			expect('=');
+		default:
+			outbound = 0;
+
+			switch (tp->op) {
+			case ARY:
+				curtp = tp->type;
+				if (!(tp->prop & TDEFINED) || in.pos < tp->n.elem)
+					break;
+				if (!toomany)
+					warn("excess elements in array initializer");
+				toomany = 1;
+				outbound = 1;
+				break;
+			case UNION:
+			case STRUCT:
+				if (in.pos < nelem) {
+					curtp = tp->p.fields[in.pos]->type;
+					break;
+				}
+				if (!toomany)
+					warn("excess elements in struct initializer");
+				toomany = 1;
+				outbound = 1;
+				break;
+			default:
+				curtp = tp;
+				if (!scalar)
+					warn("braces around scalar initializer");
+				scalar = 1;
+				if (in.pos == 0)
+					break;
+				if (!toomany)
+					warn("excess elements in scalar initializer");
+				toomany = 1;
+				outbound = 1;
+				break;
+			}
+			np = initialize(curtp);
+			if (outbound) {
+				freetree(np);
+				np = NULL;
+			}
+		}
+
+new_desig:
+		if (np)
+			newdesig(&in, np);
+		if (++in.pos == 0)
+			errorp("compound literal too big");
+		if (nelem == in.pos && !braces)
+			break;
+	} while (accept(','));
+
+	if (braces)
+		expect('}');
+
+
+	if (tp->op == ARY && !(tp->prop & TDEFINED)) {
+		tp->n.elem = in.max;
+		deftype(tp);
+	}
+	if (in.max == 0) {
+		errorp("empty braced initializer");
+		return constnode(zero);
+	}
+
+	return mkcompound(&in, tp);
+}
+
+static void
+autoinit(Symbol *sym, Node *np)
+{
+	Symbol *hidden;
+	Type *tp = sym->type;
+	size_t n; /* FIXME: It should be SIZET */
+
+repeat:
+	switch (tp->op) {
+	case UNION:
+		np = np->sym->u.init[0];
+		tp = np->type;
+		goto repeat;
+	case ARY:
+	case STRUCT:
+		if (!(np->flags & NCONST))
+			abort(); /* TODO */
+		hidden = newsym(NS_IDEN, NULL);
+		hidden->type = sym->type;
+		hidden->flags |= SLOCAL | SHASINIT;
+		emit(ODECL, hidden);
+		emit(OINIT, np);
+		emit(ODECL, sym);
+		emit(OEXPR,
+		     node(OASSIGN, tp, varnode(sym), varnode(hidden)));
+		break;
+	default:
+		emit(ODECL, sym);
+		np = node(OASSIGN, tp, varnode(sym), np);
+		emit(OEXPR, np);
+		break;
+	}
+}
+
+void
+initializer(Symbol *sym, Type *tp)
+{
+	Node *np;
+	int flags = sym->flags;
+
+	if (tp->op == FTN) {
+		errorp("function '%s' initialized like a variable",
+		       sym->name);
+		tp = inttype;
+	}
+	np = initialize(tp);
+
+	if (flags & SDEFINED) {
+		errorp("redeclaration of '%s'", sym->name);
+	} else if ((flags & (SGLOBAL|SLOCAL|SPRIVATE)) != 0) {
+		if (!(np->flags & NCONST)) {
+			errorp("initializer element is not constant");
+			return;
+		}
+		sym->flags |= SHASINIT;
+		sym->flags &= ~SEMITTED;
+		emit(ODECL, sym);
+		emit(OINIT, np);
+		sym->flags |= SDEFINED;
+	} else if ((flags & (SEXTERN|STYPEDEF)) != 0) {
+		errorp("'%s' has both '%s' and initializer",
+		       sym->name, (flags&SEXTERN) ? "extern" : "typedef");
+	} else {
+		autoinit(sym, np);
+	}
+}
--- /dev/null
+++ b/src/cmd/cc/cc1/ir.md
@@ -1,0 +1,443 @@
+# scc intermediate representation #
+
+The scc IR tries to be be a simple and easily parseable intermediate
+representation, and it makes it a bit terse and cryptic. The main
+characteristic of the IR is that all the types and operations are
+represented with only one letter, so parsing tables can be used
+to parse it.
+
+The language is composed of lines, representing statements.
+Each statement is composed of tab-separated fields.
+Declaration statements begin in column 0, expressions and
+control flow begin with a tabulator.
+When the frontend detects an error, it closes the output stream.
+
+## Types ##
+
+Types are represented with uppercase letters:
+
+* C -- signed    8-Bit integer
+* I -- signed   16-Bit integer
+* W -- signed   32-Bit integer
+* Q -- signed   64-Bit integer
+* K -- unsigned  8-Bit integer
+* N -- unsigned 16-Bit integer
+* Z -- unsigned 32-Bit integer
+* O -- unsigned 64-Bit integer
+* 0 -- void
+* P -- pointer
+* F -- function
+* V -- vector
+* U -- union
+* S -- struct
+* B -- bool
+* J -- float
+* D -- double
+* H -- long double
+
+This list has been built for the original Z80 backend, where 'int'
+has the same size as 'short'. Several types (S, F, V, U and others) need
+an identifier after the type letter for better differentiation
+between multiple structs, functions, vectors and unions (S1, V12 ...)
+naturally occuring in a C-program.
+
+## Storage classes ##
+
+The storage classes are represented using uppercase letters:
+
+* A -- automatic
+* R -- register
+* G -- public (global variable declared in the module)
+* X -- extern (global variable declared in another module)
+* Y -- private (variable in file-scope)
+* T -- local (static variable in function-scope)
+* M -- member (struct/union member)
+* L -- label
+
+## Declarations/definitions ##
+
+Variable names are composed of a storage class and an identifier
+(e.g. A1, R2, T3).
+Declarations and definitions are composed of a variable
+name, a type and the name of the variable:
+
+	A1	I	maxweight
+	R2	C	flag
+	A3	S4	statstruct
+
+### Type declarations ###
+
+Some declarations (e.g. structs) involve the declaration of member
+variables.
+Struct members are declared normally after the type declaration in
+parentheses.
+
+For example the struct declaration
+
+	struct foo {
+		int i;
+		long c;
+	} var1;
+
+generates
+
+	S2      foo     (
+	M3      I       i
+	M4      W       c
+	)
+	G5      S2      var1
+
+## Functions ##
+
+A function prototype
+
+	int printf(char *cmd, int flag, void *data);
+
+will generate a type declaration and a variable declaration
+
+	F5	P	I	P
+	X1	F5	printf
+
+The first line gives the function-type specification 'F' with
+an identifier '5' and subsequently lists the types of the
+function parameters.
+The second line declares the 'printf' function as a publicly
+scoped variable.
+
+Analogously, a statically declared function in file scope
+
+	static int printf(char *cmd, int flag, void *data);
+
+generates
+
+	F5      P       I       P
+	T1      F5      printf
+
+Thus, the 'printf' variable  went into local scope ('T').
+
+A '{' in the first column starts the body of the previously
+declared function:
+
+	int printf(char *cmd, int flag, void *data) {}
+
+generates
+
+	F5      P       I       P
+	G1      F5      printf
+	{
+	A2      P       cmd
+	A3      I       flag
+	A4      P       data
+	-
+	}
+
+Again, the frontend must ensure that '{' appears only after the
+declaration of a function. The character '-' marks the separation
+between parameters and local variables:
+
+	int printf(register char *cmd, int flag, void *data) {int i;};
+
+generates
+
+	F5      P       I       P
+	G1      F5      printf
+	{
+	R2      P       cmd
+	A3      I       flag
+	A4      P       data
+	-
+	A6      I       i
+	}
+
+### Expressions ###
+
+Expressions are emitted in reverse polish notation, simplifying
+parsing and converting into a tree representation.
+
+#### Operators ####
+
+Operators allowed in expressions are:
+
+* \+ -- addition
+* \- -- substraction
+* \* -- multiplication
+* % -- modulo
+* / -- division
+* l -- left shift
+* r -- right shift
+* < -- less than
+* > -- greather than
+* ] -- greather or equal than
+* [ -- less or equal than
+* = -- equal than
+* ! -- different than
+* & -- bitwise and
+* | -- bitwise or
+* ^ -- bitwise xor
+* ~ -- bitwise complement
+* : -- asignation
+* _ -- unary negation
+* c -- function call
+* p -- parameter
+* . -- field
+* , -- comma operator
+* ? -- ternary operator
+* ' -- take address
+* a -- logical shortcut and
+* o -- logical shortcut or
+* @ -- content of pointer
+
+Assignation has some suboperators:
+
+* :/ -- divide and assign
+* :% -- modulo and assign
+* :+ -- addition and assign
+* :- -- substraction and assign
+* :l -- left shift and assign
+* :r -- right shift and assign
+* :& -- bitwise and and assign
+* :^ -- bitwise xor and assign
+* :| -- bitwise or and assign
+* :i -- post increment
+* :d -- post decrement
+
+Every operator in an expression has a type descriptor.
+
+#### Constants ####
+
+Constants are introduced with the character '#'. For instance, 10 is
+translated to #IA (all constants are emitted in hexadecimal),
+where I indicates that it is an integer constant.
+Strings are a special case because they are represented with
+the " character.
+The constant "hello" is emitted as "68656C6C6F. For example
+
+	int
+	main(void)
+	{
+		int i, j;
+
+		i = j+2*3;
+	}
+
+generates
+
+	F1
+	G1	F1	main
+	{
+	-
+	A2      I	i
+	A3      I	j
+		A2	A3	#I6	+I	:I
+	}
+
+Type casts are expressed with a tuple denoting the
+type conversion
+
+        int
+	main(void)
+	{
+		int i;
+		long j;
+
+		j = (long)i;
+	}
+
+generates
+
+	F1
+	G1      F1      main
+	{
+	-
+	A2      I       i
+	A3      W       j
+	        A2      A3      WI      :I
+	}
+
+### Statements ###
+#### Jumps #####
+
+Jumps have the following form:
+
+	j	L#	[expression]
+
+the optional expression field indicates some condition which
+must be satisfied to jump. Example:
+
+	int
+	main(void)
+	{
+		int i;
+
+		goto    label;
+	label:
+		i -= i;
+	}
+
+generates
+
+	F1
+	G1      F1      main
+	{
+	-
+	A2	I	i
+		j	L3
+	L3
+		A2	A2	:-I
+	}
+
+Another form of jump is the return statement, which uses the
+letter 'y' followed by a type identifier.
+Depending on the type, an optional expression follows.
+
+	int
+	main(void)
+	{
+		return 16;
+	}
+
+generates
+
+	F1
+	G1	F1	main
+	{
+	-
+		yI	#I10
+	}
+
+
+#### Loops ####
+
+There are two special characters that are used to indicate
+to the backend that the following statements are part of
+a loop body.
+
+* b -- beginning of loop
+* e -- end of loop
+
+#### Switch statement ####
+
+Switches are represented using a table, in which the labels
+where to jump for each case are indicated. Common cases are
+represented with 'v' and default with 'f'.
+The switch statement itself is represented with 's' followed
+by the label where the jump table is located, and the
+expression of the switch:
+
+	int
+	func(int n)
+	{
+		switch (n+1) {
+		case 1:
+		case 2:
+		case 3:
+		default:
+			++n;
+		}
+	}
+
+generates
+
+	F2	I
+	G1	F2	func
+	{
+	A1	I	n
+	-
+		s	L4	A1	#I1	+I
+	L5
+	L6
+	L7
+	L8
+		A1	#I1	:+I
+		j	L3
+	L4
+		t	#4
+		v	L7	#I3
+		v	L6	#I2
+		v	L5	#I1
+		f	L8
+	L3
+	}
+
+The beginning of the jump table is indicated by the the letter 't',
+followed by the number of cases (including default case) of the
+switch.
+
+## Resumen ##
+
+* C -- signed    8-Bit integer
+* I -- signed   16-Bit integer
+* W -- signed   32-Bit integer
+* O -- signed   64-Bit integer
+* M -- unsigned  8-Bit integer
+* N -- unsigned 16-Bit integer
+* Z -- unsigned 32-Bit integer
+* Q -- unsigned 64-Bit integer
+* 0 -- void
+* P -- pointer
+* F -- function
+* V -- vector
+* U -- union
+* S -- struct
+* B -- bool
+* J -- float
+* D -- double
+* H -- long double
+* A -- automatic
+* R -- register
+* G -- public (global variable declared in the module)
+* X -- extern (global variable declared in another module)
+* Y -- private (variable in file-scope)
+* T -- local (static variable in function-scope)
+* M -- member (struct/union member)
+* L -- label
+* { -- beginning of function body
+* } -- end of function body
+* \\ -- end of function parameters
+* \+ -- addition
+* \- -- substraction
+* \* -- multiplication
+* % -- modulo
+* / -- division
+* l -- left shift
+* r -- right shift
+* < -- less than
+* > -- greather than
+* ] -- greather or equal than
+* [ -- less or equal than
+* = -- equal than
+* ! -- different than
+* & -- bitwise and
+* | -- bitwise or
+* ^ -- bitwise xor
+* ~ -- bitwise complement
+* : -- asignation
+* _ -- unary negation
+* c -- function call
+* p -- parameter
+* . -- field
+* , -- comma operator
+* ? -- ternary operator
+* ' -- take address
+* a -- logical shortcut and
+* o -- logical shortcut or
+* @ -- content of pointer
+* :/ -- divide and assign
+* :% -- modulo and assign
+* :+ -- addition and assign
+* :- -- substraction and assign
+* :l -- left shift and assign
+* :r -- right shift and assign
+* :& -- bitwise and and assign
+* :^ -- bitwise xor and assign
+* :| -- bitwise or and assign
+* ;+ -- post increment
+* ;- -- post decrement
+* j -- jump
+* y -- return
+* b -- begin of loop
+* d -- end of loop
+* s -- switch statement
+* t -- switch table
+* v -- case entry in switch table
+* f -- default entry in switch table
--- /dev/null
+++ b/src/cmd/cc/cc1/lex.c
@@ -1,0 +1,800 @@
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+#include "cc1.h"
+
+int yytoken;
+struct yystype yylval;
+char yytext[STRINGSIZ+3];
+unsigned short yylen;
+int lexmode = CCMODE;
+unsigned lineno;
+char filenam[FILENAME_MAX];
+
+int namespace = NS_IDEN;
+static int safe;
+Input *input;
+
+void
+ilex(void)
+{
+	static struct keyword keys[] = {
+		{"auto", SCLASS, AUTO},
+		{"break", BREAK, BREAK},
+		{"_Bool", TYPE, BOOL},
+		{"__builtin_va_list", TYPE, VA_LIST},
+		{"case", CASE, CASE},
+		{"char", TYPE, CHAR},
+		{"const", TQUALIFIER, CONST},
+		{"continue", CONTINUE, CONTINUE},
+		{"default", DEFAULT, DEFAULT},
+		{"do", DO, DO},
+		{"double", TYPE, DOUBLE},
+		{"else", ELSE, ELSE},
+		{"enum", TYPE, ENUM},
+		{"extern", SCLASS, EXTERN},
+		{"float", TYPE, FLOAT},
+		{"for", FOR, FOR},
+		{"goto", GOTO, GOTO},
+		{"if", IF, IF},
+		{"inline", TQUALIFIER, INLINE},
+		{"int", TYPE, INT},
+		{"long", TYPE, LONG},
+		{"register", SCLASS, REGISTER},
+		{"restrict", TQUALIFIER, RESTRICT},
+		{"return", RETURN, RETURN},
+		{"short", TYPE, SHORT},
+		{"signed", TYPE, SIGNED},
+		{"sizeof", SIZEOF, SIZEOF},
+		{"static", SCLASS, STATIC},
+		{"struct", TYPE, STRUCT},
+		{"switch", SWITCH, SWITCH},
+		{"typedef", SCLASS, TYPEDEF},
+		{"union", TYPE, UNION},
+		{"unsigned", TYPE, UNSIGNED},
+		{"void", TYPE, VOID},
+		{"volatile", TQUALIFIER, VOLATILE},
+		{"while", WHILE, WHILE},
+		{NULL, 0, 0},
+	};
+	keywords(keys, NS_KEYWORD);
+}
+
+void
+setloc(char *fname, unsigned line)
+{
+	size_t len;
+
+	if ((len = strlen(fname)) >= FILENAME_MAX)
+		die("cc1: %s: file name too long", fname);
+	memmove(filenam, fname, len);
+	filenam[len] = '\0';
+
+	free(input->filenam);
+	input->filenam = xstrdup(fname);
+	lineno = input->lineno = line;
+}
+
+void
+addinput(char *fname, Symbol *hide, char *buffer)
+{
+	FILE *fp;
+	char *extp;
+	unsigned flags;
+	int infileln;
+	Input *newip, *curip = input;
+
+	if (hide) {
+		/* this is a macro expansion */
+		fp = NULL;
+		if (hide->hide == UCHAR_MAX)
+			die("cc1: too many macro expansions");
+		++hide->hide;
+		flags = IMACRO;
+	} else  if (fname) {
+		/* a new file */
+		if ((fp = fopen(fname, "r")) == NULL)
+			die("cc1: %s: %s", fname, strerror(errno));
+		flags = IFILE;
+		if (curip && onlyheader) {
+			infileln = strlen(infile);
+			if (extp = strrchr(infile, '.'))
+				infileln -= strlen(extp);
+			printf("%.*s.o: %s %s\n",
+			       infileln, infile, infile, fname);
+		}
+	} else {
+		/* reading from stdin */
+		fp = stdin;
+		fname = "<stdin>";
+		flags = ISTDIN;
+	}
+
+	newip = xmalloc(sizeof(*newip));
+
+	if (!buffer) {
+		buffer = xmalloc(INPUTSIZ);
+		buffer[0] = '\0';
+	}
+
+	if (curip)
+		curip->lineno = lineno;
+
+	newip->p = newip->begin = newip->line = buffer;
+	newip->filenam = NULL;
+	newip->lineno = 0;
+	newip->next = curip;
+	newip->fp = fp;
+	newip->hide = hide;
+	newip->flags = flags;
+	input = newip;
+
+	setloc(fname, (curip) ? curip->lineno : newip->lineno);
+}
+
+void
+delinput(void)
+{
+	Input *ip = input;
+	Symbol *hide = ip->hide;
+
+	switch (ip->flags & ITYPE) {
+	case IFILE:
+		if (fclose(ip->fp))
+			die("cc1: %s: %s", ip->filenam, strerror(errno));
+		break;
+	case IMACRO:
+		assert(hide->hide == 1);
+		--hide->hide;
+		break;
+	}
+	input = ip->next;
+	free(ip->filenam);
+	free(ip->line);
+	if (input) {
+		lineno = input->lineno;
+		strcpy(filenam, input->filenam);
+	}
+}
+
+static void
+newline(void)
+{
+	if (++lineno == 0)
+		die("cc1: %s: file too long", filenam);
+}
+
+/*
+ * Read the next character from the input file, counting number of lines
+ * and joining lines escaped with \
+ */
+static int
+readchar(void)
+{
+	FILE *fp = input->fp;
+	int c;
+
+repeat:
+	switch (c = getc(fp)) {
+	case '\\':
+		if ((c = getc(fp)) == '\n') {
+			newline();
+			goto repeat;
+		}
+		ungetc(c, fp);
+		c = '\\';
+		break;
+	case '\n':
+		newline();
+		break;
+	default:
+		if (!isprint(c) && !ispunct(c) && !isspace(c))
+			warn("invalid input character. The shame of UB is yours");
+		break;
+	}
+
+	return c;
+}
+
+/*
+ * discard a C comment. This function is only called from readline
+ * because it is impossible to have a comment in a macro, because
+ * comments are always discarded before processing any cpp directive
+ */
+static void
+comment(int type)
+{
+	int c;
+
+repeat:
+	while ((c = readchar()) != EOF && c != type)
+		;
+
+	if (c == EOF) {
+		errorp("unterminated comment");
+		return;
+	}
+
+	if (type == '*' && (c = readchar()) != '/')
+		goto repeat;
+}
+
+/*
+ * readline is used to read a full logic line from a file.
+ * It discards comments and check that the line fits in
+ * the input buffer
+ */
+static int
+readline(void)
+{
+	char *bp, *lim;
+	int c, peekc = 0;
+
+	if (feof(input->fp)) {
+		input->flags |= IEOF;
+		return 0;
+	}
+
+	*input->line = '\0';
+	lim = &input->line[INPUTSIZ-1];
+	for (bp = input->line; bp < lim-1; *bp++ = c) {
+		c = (peekc) ? peekc : readchar();
+		peekc = 0;
+		if (c == '\n' || c == EOF)
+			break;
+		if (c != '/')
+			continue;
+
+		/* check for /* or // */
+		peekc = readchar();
+		if (peekc != '*' && peekc != '/')
+			continue;
+		comment((peekc == '/') ? '\n' : '*');
+		peekc = 0;
+		c = ' ';
+	}
+
+	input->begin = input->p = input->line;
+	if (bp == lim-1) {
+		errorp("line too long");
+		--bp;
+	}
+	*bp++ = '\n';
+	*bp = '\0';
+
+	return 1;
+}
+
+/*
+ * moreinput gets more bytes to be passed to the lexer.
+ * It can take more bytes from macro expansions or
+ * directly reading from files. When a cpp directive
+ * is processed the line is discarded because it must not
+ * be passed to the lexer
+ */
+static int
+moreinput(void)
+{
+	int wasexpand = 0;
+
+repeat:
+	if (!input)
+		return 0;
+
+	if (*input->p == '\0') {
+		if ((input->flags&ITYPE) == IMACRO) {
+			wasexpand = 1;
+			input->flags |= IEOF;
+		}
+		if (input->flags & IEOF) {
+			delinput();
+			goto repeat;
+		}
+		if (!readline() || cpp()) {
+			*input->p = '\0';
+			goto repeat;
+		}
+	}
+
+	if (onlycpp && !wasexpand)
+		ppragmaln();
+	return 1;
+}
+
+static void
+tok2str(void)
+{
+	if ((yylen = input->p - input->begin) > INTIDENTSIZ)
+		error("token too big");
+	memcpy(yytext, input->begin, yylen);
+	yytext[yylen] = '\0';
+	input->begin = input->p;
+}
+
+static Symbol *
+readint(char *s, int base, int sign, Symbol *sym)
+{
+	Type *tp = sym->type;
+	struct limits *lim;
+	TUINT u, val, max;
+	int c;
+
+	lim = getlimits(tp);
+	max = lim->max.i;
+	if (*s == '0')
+		++s;
+	if (toupper(*s) == 'X')
+		++s;
+
+	for (u = 0; isxdigit(c = *s++); u = u*base + val) {
+		static char letters[] = "0123456789ABCDEF";
+		val = strchr(letters, toupper(c)) - letters;
+	repeat:
+		if (u <= max/base && u*base <= max - val)
+			continue;
+		if (tp->prop & TSIGNED) {
+			if (tp == inttype)
+				tp = (base==10) ? longtype : uinttype;
+			else if (tp == longtype)
+				tp = (base==10) ? llongtype : ulongtype;
+			else
+				goto overflow;
+		} else {
+			if (tp == uinttype)
+				tp = (sign==UNSIGNED) ? ulongtype : longtype;
+			else if (tp == ulongtype)
+				tp = (sign==UNSIGNED) ? ullongtype : llongtype;
+			else
+				goto overflow;
+		}
+		sym->type = tp;
+		lim = getlimits(tp);
+		max = lim->max.i;
+		goto repeat;
+	}
+
+	if (tp->prop & TSIGNED)
+		sym->u.i = u;
+	else
+		sym->u.u = u;
+
+	return sym;
+
+overflow:
+	errorp("overflow in integer constant");
+	return sym;
+}
+
+static int
+integer(char *s, int base)
+{
+	Type *tp;
+	Symbol *sym;
+	unsigned size, sign;
+
+	for (size = sign = 0; ; ++input->p) {
+		switch (toupper(*input->p)) {
+		case 'L':
+			if (size == LLONG)
+				goto wrong_type;
+			size = (size == LONG) ? LLONG : LONG;
+			continue;
+		case 'U':
+			if (sign == UNSIGNED)
+				goto wrong_type;
+			sign = UNSIGNED;
+			continue;
+		default:
+			goto convert;
+		wrong_type:
+			error("invalid suffix in integer constant");
+		}
+	}
+
+convert:
+	tp = ctype(INT, sign, size);
+	sym = newsym(NS_IDEN, NULL);
+	sym->type = tp;
+	sym->flags |= SCONSTANT;
+	yylval.sym = readint(s, base, sign, sym);
+	return CONSTANT;
+}
+
+static char *
+digits(int base)
+{
+	char *p;
+	int c;
+
+	for (p = input->p; c = *p; ++p) {
+		switch (base) {
+		case 8:
+			if (!strchr("01234567", c))
+				goto end;
+			break;
+		case 10:
+			if (!isdigit(c))
+				goto end;
+			break;
+		case 16:
+			if (!isxdigit(c))
+				goto end;
+			break;
+		}
+	}
+end:
+	input->p = p;
+	tok2str();
+	return yytext;
+}
+
+static int
+number(void)
+{
+	int base;
+
+	if (*input->p != '0') {
+		base = 10;
+	} else {
+		if (toupper(*++input->p) == 'X') {
+			++input->p;
+			base = 16;
+		} else {
+			base = 8;
+		}
+	}
+
+	return integer(digits(base), base);
+}
+
+static int
+escape(void)
+{
+	int c, base;
+
+	switch (*++input->p) {
+	case 'a':  return '\a';
+	case 'f':  return '\f';
+	case 'n':  return '\n';
+	case 'r':  return '\r';
+	case 't':  return '\t';
+	case 'v':  return '\v';
+	case '"':  return '"';
+	case '\'': return '\'';
+	case '\\': return '\\';
+	case '\?': return '\?';
+	case 'u':
+		/*
+		 * FIXME: universal constants are not correctly handled
+		 */
+		if (!isdigit(*++input->p))
+			warn("incorrect digit for numerical character constant");
+		base = 10;
+		break;
+	case 'x':
+		if (!isxdigit(*++input->p))
+			warn("\\x used with no following hex digits");
+		base = 16;
+		break;
+	case '0':
+		if (!strchr("01234567", *++input->p))
+			warn("\\0 used with no following octal digits");
+		base = 8;
+		break;
+	default:
+		warn("unknown escape sequence");
+		return ' ';
+	}
+	errno = 0;
+	c = strtoul(input->p, &input->p, base);
+	if (errno || c > 255)
+		warn("character constant out of range");
+	--input->p;
+	return c;
+}
+
+static int
+character(void)
+{
+	int c;
+	Symbol *sym;
+
+	if ((c = *++input->p) == '\\')
+		c = escape();
+	else
+		c = *input->p;
+	++input->p;
+	if (*input->p != '\'')
+		errorp("invalid character constant");
+	else
+		++input->p;
+
+	sym = newsym(NS_IDEN, NULL);
+	sym->u.i = c;
+	sym->type = inttype;
+	yylval.sym = sym;
+	tok2str();
+	return CONSTANT;
+}
+
+static int
+string(void)
+{
+	char *bp = yytext;
+	int c;
+
+	*bp++ = '"';
+	for (++input->p; (c = *input->p) != '"'; ++input->p) {
+		if (c == '\0') {
+			errorp("missing terminating '\"' character");
+			break;
+		}
+		if (c == '\\')
+			c = escape();
+		if (bp == &yytext[STRINGSIZ+1]) {
+			/* TODO: proper error handling here */
+			error("string too long");
+		}
+		*bp++ = c;
+	}
+
+	input->begin = ++input->p;
+	*bp = '\0';
+
+	yylen = bp - yytext + 1;
+	yylval.sym = newstring(yytext+1, yylen-1);
+	*bp++ = '"';
+	*bp = '\0';
+	return STRING;
+}
+
+static int
+iden(void)
+{
+	Symbol *sym;
+	char *p, *begin;
+
+	begin = input->p;
+	for (p = begin; isalnum(*p) || *p == '_'; ++p)
+		;
+	input->p = p;
+	tok2str();
+	if ((sym = lookup(NS_CPP, yytext, NOALLOC)) != NULL) {
+		if (!disexpand && !sym->hide && expand(begin, sym))
+			return next();
+	}
+	sym = lookup(namespace, yytext, ALLOC);
+	yylval.sym = sym;
+	if (sym->flags & SCONSTANT)
+		return CONSTANT;
+	if (sym->token != IDEN)
+		yylval.token = sym->u.token;
+	return sym->token;
+}
+
+static int
+follow(int expect, int ifyes, int ifno)
+{
+	if (*input->p++ == expect)
+		return ifyes;
+	--input->p;
+	return ifno;
+}
+
+static int
+minus(void)
+{
+	switch (*input->p++) {
+	case '-': return DEC;
+	case '>': return INDIR;
+	case '=': return SUB_EQ;
+	default: --input->p; return '-';
+	}
+}
+
+static int
+plus(void)
+{
+	switch (*input->p++) {
+	case '+': return INC;
+	case '=': return ADD_EQ;
+	default: --input->p; return '+';
+	}
+}
+
+static int
+relational(int op, int equal, int shift, int assig)
+{
+	int c;
+
+	if ((c = *input->p++) == '=')
+		return equal;
+	if (c == op)
+		return follow('=', assig, shift);
+	--input->p;
+	return op;
+}
+
+static int
+logic(int op, int equal, int logic)
+{
+	int c;
+
+	if ((c = *input->p++) == '=')
+		return equal;
+	if (c == op)
+		return logic;
+	--input->p;
+	return op;
+}
+
+static int
+dot(void)
+{
+	int c;
+
+	if ((c = *input->p) != '.')
+		return '.';
+	if ((c = *++input->p) != '.')
+		error("incorrect token '..'");
+	++input->p;
+	return ELLIPSIS;
+}
+
+static int
+operator(void)
+{
+	int t;
+
+	switch (t = *input->p++) {
+	case '<': t = relational('<', LE, SHL, SHL_EQ); break;
+	case '>': t = relational('>', GE, SHR, SHR_EQ); break;
+	case '&': t = logic('&', AND_EQ, AND); break;
+	case '|': t = logic('|', OR_EQ, OR); break;
+	case '=': t = follow('=', EQ, '='); break;
+	case '^': t = follow('=', XOR_EQ, '^'); break;
+	case '*': t = follow('=', MUL_EQ, '*'); break;
+	case '/': t = follow('=', DIV_EQ, '/'); break;
+	case '!': t = follow('=', NE, '!'); break;
+	case '#': t = follow('#', '$', '#'); break;
+	case '-': t = minus(); break;
+	case '+': t = plus(); break;
+	case '.': t = dot(); break;
+	}
+	tok2str();
+	return t;
+}
+
+/* TODO: Ensure that namespace is NS_IDEN after a recovery */
+
+/*
+ * skip all the spaces until the next token. When we are in
+ * CPPMODE \n is not considered a whitespace
+ */
+static int
+skipspaces(void)
+{
+	int c;
+
+	for (;;) {
+		switch (c = *input->p) {
+		case '\n':
+			if (lexmode == CPPMODE)
+				goto return_byte;
+			++input->p;
+		case '\0':
+			if (!moreinput())
+				return EOF;
+			break;
+		case ' ':
+		case '\t':
+		case '\v':
+		case '\r':
+		case '\f':
+			++input->p;
+			break;
+		default:
+			goto return_byte;
+		}
+	}
+
+return_byte:
+	input->begin = input->p;
+	return c;
+}
+
+int
+next(void)
+{
+	int c;
+
+	if ((c = skipspaces()) == EOF)
+		yytoken = EOFTOK;
+	else if (isalpha(c) || c == '_')
+		yytoken = iden();
+	else if (isdigit(c))
+		yytoken = number();
+	else if (c == '"')
+		yytoken = string();
+	else if (c == '\'')
+		yytoken = character();
+	else
+		yytoken = operator();
+
+	if (yytoken == EOF) {
+		strcpy(yytext, "<EOF>");
+		if (cppctx)
+			errorp("#endif expected");
+	}
+
+	DBG("TOKEN %s", yytext);
+	return yytoken;
+}
+
+void
+expect(int tok)
+{
+	if (yytoken != tok) {
+		if (isgraph(tok))
+			errorp("expected '%c' before '%s'", tok, yytext);
+		else
+			errorp("unexpected '%s'", yytext);
+	} else {
+		next();
+	}
+}
+
+int
+ahead(void)
+{
+	skipspaces();
+	return *input->begin;
+}
+
+void
+setsafe(int type)
+{
+	safe = type;
+}
+
+void
+discard(void)
+{
+	extern jmp_buf recover;
+	int c;
+
+	input->begin = input->p;
+	for (c = yytoken; ; c = *input->begin++) {
+		switch (safe) {
+		case END_COMP:
+			if (c == '}')
+				goto jump;
+			goto semicolon;
+		case END_COND:
+			if (c == ')')
+				goto jump;
+			break;
+		case END_LDECL:
+			if (c == ',')
+				goto jump;
+		case END_DECL:
+		semicolon:
+			if (c == ';')
+				goto jump;
+			break;
+		}
+		if (c == '\0' && !moreinput())
+			exit(1);
+	}
+jump:
+	yytoken = c;
+	longjmp(recover, 1);
+}
--- /dev/null
+++ b/src/cmd/cc/cc1/main.c
@@ -1,0 +1,101 @@
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <scc/arg.h>
+#include <scc/scc.h>
+#include "cc1.h"
+
+char *argv0, *infile;
+
+int warnings;
+jmp_buf recover;
+
+static struct items uflags;
+int onlycpp, onlyheader;
+
+
+extern int failure;
+
+static void
+defmacro(char *macro)
+{
+	char *p = strchr(macro, '=');
+
+	if (p)
+		*p++ = '\0';
+	else
+		p = "1";
+
+	defdefine(macro, p, "command-line");
+}
+
+static void
+usage(void)
+{
+	fputs("usage: cc1 [-Ewd] [-D def[=val]]... [-U def]... "
+	      "[-I dir]... [-o output] [input]\n", stderr);
+	exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+	int i;
+
+	ilex();
+	icpp();
+	icode();
+	ibuilts();
+
+	ARGBEGIN {
+	case 'D':
+		defmacro(EARGF(usage()));
+		break;
+	case 'M':
+		onlyheader = 1;
+		break;
+	case 'E':
+		onlycpp = 1;
+		break;
+	case 'I':
+		incdir(EARGF(usage()));
+		break;
+	case 'U':
+		newitem(&uflags, EARGF(usage()));
+		break;
+	case 'd':
+		DBGON();
+		break;
+	case 'w':
+		warnings = 1;
+		break;
+	default:
+		usage();
+	} ARGEND
+
+	if (argc > 1)
+		usage();
+
+	for (i = 0; i < uflags.n; ++i)
+		undefmacro(uflags.s[i]);
+
+	infile = (*argv) ? *argv : "<stdin>";
+	addinput(*argv, NULL, NULL);
+
+	/*
+	 * we cannot initialize arch until we have an
+	 * output stream, because we maybe want to emit new types
+	 */
+	iarch();
+	if (onlycpp || onlyheader) {
+		outcpp();
+	} else {
+		for (next(); yytoken != EOFTOK; decl())
+			;
+	}
+
+	return failure;
+}
--- /dev/null
+++ b/src/cmd/cc/cc1/stmt.c
@@ -1,0 +1,385 @@
+#include <stddef.h>
+#include <setjmp.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+#include "cc1.h"
+
+#define NEGATE   1
+#define NONEGATE 0
+
+Symbol *curfun;
+
+static void stmt(Symbol *lbreak, Symbol *lcont, Switch *lswitch);
+
+static void
+label(void)
+{
+	Symbol *sym;
+
+	switch (yytoken) {
+	case IDEN:
+	case TYPEIDEN:
+		sym = lookup(NS_LABEL, yytext, ALLOC);
+		if (sym->flags & SDEFINED)
+			error("label '%s' already defined", yytext);
+		if ((sym->flags & SDECLARED) == 0)
+			sym = install(NS_LABEL, sym);
+		sym->flags |= SDEFINED;
+		emit(OLABEL, sym);
+		next();
+		expect(':');
+		break;
+	default:
+		unexpected();
+	}
+}
+
+static void
+stmtexp(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
+{
+	Node *np;
+
+	if (accept(';'))
+		return;
+	if (yytoken == IDEN && ahead() == ':') {
+		label();
+		stmt(lbreak, lcont, lswitch);
+		return;
+	}
+	np = expr();
+	if ((np->flags & NEFFECT) == 0)
+		warn("expression without side effects");
+	emit(OEXPR, np);
+	expect(';');
+}
+
+static Node *
+condition(int neg)
+{
+	Node *np;
+
+	expect('(');
+	np = condexpr(neg);
+	expect(')');
+
+	return np;
+}
+
+static void
+While(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
+{
+	Symbol *begin;
+	Node *np;
+
+	begin = newlabel();
+	lcont = newlabel();
+	lbreak = newlabel();
+
+	expect(WHILE);
+	np = condition(NONEGATE);
+
+	emit(OJUMP, lcont);
+
+	emit(OBLOOP, NULL);
+	emit(OLABEL, begin);
+	stmt(lbreak, lcont, lswitch);
+	emit(OLABEL, lcont);
+	emit(OBRANCH, begin);
+	emit(OEXPR, np);
+	emit(OELOOP, NULL);
+
+	emit(OLABEL, lbreak);
+}
+
+static void
+For(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
+{
+	Symbol *begin, *cond;
+	Node *econd, *einc;
+
+	begin = newlabel();
+	lcont = newlabel();
+	cond = newlabel();
+	lbreak = newlabel();
+
+	pushctx();
+
+	expect(FOR);
+	expect('(');
+	switch (yytoken) {
+	case TYPE:
+	case TYPEIDEN:
+	case TQUALIFIER:
+	case SCLASS:
+		decl();
+		break;
+	default:
+		emit(OEXPR, expr());
+	case ';':
+		expect(';');
+		break;
+	}
+	econd = (yytoken != ';') ? condexpr(NONEGATE) : NULL;
+	expect(';');
+	einc = (yytoken != ')') ? expr() : NULL;
+	expect(')');
+
+	emit(OJUMP, cond);
+
+	emit(OBLOOP, NULL);
+	emit(OLABEL, begin);
+	stmt(lbreak, lcont, lswitch);
+	emit(OLABEL, lcont);
+	emit(OEXPR, einc);
+	emit(OLABEL, cond);
+	emit((econd) ? OBRANCH : OJUMP, begin);
+	emit(OEXPR, econd);
+	emit(OELOOP, NULL);
+
+	emit(OLABEL, lbreak);
+
+	popctx();
+}
+
+static void
+Dowhile(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
+{
+	Symbol *begin;
+	Node *np;
+
+	begin = newlabel();
+	lcont = newlabel();
+	lbreak = newlabel();
+
+	expect(DO);
+
+	emit(OBLOOP, NULL);
+	emit(OLABEL, begin);
+	stmt(lbreak, lcont, lswitch);
+	expect(WHILE);
+	np = condition(NONEGATE);
+	emit(OLABEL, lcont);
+	emit(OBRANCH, begin);
+	emit(OEXPR, np);
+	emit(OELOOP, NULL);
+
+	emit(OLABEL, lbreak);
+}
+
+static void
+Return(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
+{
+	Node *np;
+	Type *tp = curfun->type->type;
+
+	expect(RETURN);
+	np = (yytoken != ';') ? decay(expr()) : NULL;
+	expect(';');
+	if (!np) {
+		if (tp != voidtype)
+			warn("function returning non void returns no value");
+		tp = voidtype;
+	} else if (np->type != tp) {
+		if (tp == voidtype)
+			warn("function returning void returns a value");
+		else if ((np = convert(np, tp, 0)) == NULL)
+			errorp("incorrect type in return");
+	}
+	emit(ORET, NULL);
+	emit(OEXPR, np);
+}
+
+static void
+Break(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
+{
+	expect(BREAK);
+	if (!lbreak) {
+		errorp("break statement not within loop or switch");
+	} else {
+		emit(OJUMP, lbreak);
+		expect(';');
+	}
+}
+
+static void
+Continue(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
+{
+	expect(CONTINUE);
+	if (!lcont) {
+		errorp("continue statement not within loop");
+	} else {
+		emit(OJUMP, lcont);
+		expect(';');
+	}
+}
+
+static void
+Goto(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
+{
+	Symbol *sym;
+
+	namespace = NS_LABEL;
+	next();
+	namespace = NS_IDEN;
+
+	if (yytoken != IDEN)
+		unexpected();
+	sym = yylval.sym;
+	if ((sym->flags & SDECLARED) == 0)
+		sym = install(NS_LABEL, sym);
+	sym->flags |= SUSED;
+	emit(OJUMP, sym);
+	next();
+	expect(';');
+}
+
+static void
+Swtch(Symbol *obr, Symbol *lcont, Switch *osw)
+{
+	Switch sw = {0};
+	Node *cond;
+	Symbol *lbreak;
+
+	expect(SWITCH);
+
+	expect ('(');
+	if ((cond = convert(expr(), inttype, 0)) == NULL) {
+		errorp("incorrect type in switch statement");
+		cond = constnode(zero);
+	}
+	expect (')');
+
+	lbreak = newlabel();
+	emit(OBSWITCH, NULL);
+	emit(OEXPR, cond);
+	stmt(lbreak, lcont, &sw);
+	emit(OESWITCH, lbreak);
+	emit(OLABEL, lbreak);
+}
+
+static void
+Case(Symbol *lbreak, Symbol *lcont, Switch *sw)
+{
+	Node *np;
+	Symbol *label;
+
+	expect(CASE);
+	if ((np = constexpr()) == NULL)
+		errorp("case label does not reduce to an integer constant");
+	if (!sw) {
+		errorp("case label not within a switch statement");
+	} else if (sw->nr >= 0 && ++sw->nr == NR_SWITCH) {
+		errorp("too many case labels for a switch statement");
+		sw->nr = -1;
+	}
+	expect(':');
+
+	label = newlabel();
+	emit(OCASE, label);
+	emit(OEXPR, np);
+	emit(OLABEL, label);
+	stmt(lbreak, lcont, sw);
+}
+
+static void
+Default(Symbol *lbreak, Symbol *lcont, Switch *sw)
+{
+	Symbol *label = newlabel();
+
+	if (sw->hasdef)
+		errorp("multiple default labels in one switch");
+	sw->hasdef = 1;
+	expect(DEFAULT);
+	expect(':');
+	emit(ODEFAULT, label);
+	emit(OLABEL, label);
+	stmt(lbreak, lcont, sw);
+}
+
+static void
+If(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
+{
+	Symbol *end, *lelse;
+	Node *np;
+
+	lelse = newlabel();
+	expect(IF);
+	np = condition(NEGATE);
+	emit(OBRANCH, lelse);
+	emit(OEXPR, np);
+	stmt(lbreak, lcont, lswitch);
+	if (accept(ELSE)) {
+		end = newlabel();
+		emit(OJUMP, end);
+		emit(OLABEL, lelse);
+		stmt(lbreak, lcont, lswitch);
+		emit(OLABEL, end);
+	} else {
+		emit(OLABEL, lelse);
+	}
+}
+
+static void
+blockit(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
+{
+	switch (yytoken) {
+	case TYPEIDEN:
+		if (ahead() == ':')
+			goto parse_stmt;
+	case TYPE:
+	case TQUALIFIER:
+	case SCLASS:
+		decl();
+		return;
+	default:
+	parse_stmt:
+		stmt(lbreak, lcont, lswitch);
+	}
+}
+
+void
+compound(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
+{
+	static int nested;
+
+	pushctx();
+	expect('{');
+
+	if (nested == NR_BLOCK)
+		error("too many nesting levels of compound statements");
+
+	++nested;
+	for (;;) {
+		if (yytoken == '}')
+			break;
+		blockit(lbreak, lcont, lswitch);
+	}
+	--nested;
+
+	popctx();
+	expect('}');
+}
+
+static void
+stmt(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
+{
+	void (*fun)(Symbol *, Symbol *, Switch *);
+
+	switch (yytoken) {
+	case '{':      fun = compound; break;
+	case RETURN:   fun = Return;   break;
+	case WHILE:    fun = While;    break;
+	case FOR:      fun = For;      break;
+	case DO:       fun = Dowhile;  break;
+	case IF:       fun = If;       break;
+	case BREAK:    fun = Break;    break;
+	case CONTINUE: fun = Continue; break;
+	case GOTO:     fun = Goto;     break;
+	case SWITCH:   fun = Swtch;    break;
+	case CASE:     fun = Case;     break;
+	case DEFAULT:  fun = Default;  break;
+	default:       fun = stmtexp;  break;
+	}
+	(*fun)(lbreak, lcont, lswitch);
+}
--- /dev/null
+++ b/src/cmd/cc/cc1/symbol.c
@@ -1,0 +1,351 @@
+#include <assert.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+#include "cc1.h"
+
+#define NR_SYM_HASH 64
+#define NR_CPP_HASH 32
+#define NR_LBL_HASH 16
+
+unsigned curctx;
+static unsigned short counterid;
+
+static Symbol *head, *labels;
+static Symbol *htab[NR_SYM_HASH];
+static Symbol *htabcpp[NR_CPP_HASH];
+static Symbol *htablbl[NR_LBL_HASH];
+
+#ifndef NDEBUG
+void
+dumpstab(Symbol **tbl, char *msg)
+{
+	Symbol **bp, *sym;
+	unsigned size;
+
+	fprintf(stderr, "Symbol Table dump at ctx=%u\n%s\n", curctx, msg);
+	if (tbl == htab)
+		size = NR_SYM_HASH;
+	else if (tbl == htabcpp)
+		size = NR_CPP_HASH;
+	else if (tbl == htablbl)
+		size = NR_LBL_HASH;
+	else
+		abort();
+
+	for (bp = tbl; bp < &tbl[size]; ++bp) {
+		if (*bp == NULL)
+			continue;
+		fprintf(stderr, "%d", (int) (bp - htab));
+		for (sym = *bp; sym; sym = sym->hash)
+			fprintf(stderr, "->[%d,%d:'%s'=%p]",
+			        sym->ns, sym->ctx, sym->name, (void *) sym);
+		putc('\n', stderr);
+	}
+	fputs("head:", stderr);
+	for (sym = head; sym; sym = sym->next) {
+		fprintf(stderr, "->[%d,%d:'%s'=%p]",
+		        sym->ns, sym->ctx,
+		        (sym->name) ? sym->name : "", (void *) sym);
+	}
+	fputs("\nlabels:", stderr);
+	for (sym = labels; sym; sym = sym->next) {
+		fprintf(stderr, "->[%d,%d:'%s'=%p]",
+		        sym->ns, sym->ctx,
+		        (sym->name) ? sym->name : "", (void *) sym);
+	}
+	putc('\n', stderr);
+}
+#endif
+
+static Symbol **
+hash(char *s, int ns)
+{
+	unsigned h, size;
+	Symbol **tab;
+
+	h = genhash(s);
+
+	switch (ns) {
+	case NS_CPP:
+		tab = htabcpp;
+		size = NR_CPP_HASH-1;
+		break;
+	case NS_LABEL:
+		tab = htablbl;
+		size = NR_LBL_HASH-1;
+		break;
+	default:
+		tab = htab;
+		size = NR_SYM_HASH-1;
+		break;
+	}
+	return &tab[h & size];
+}
+
+static void
+unlinkhash(Symbol *sym)
+{
+	Symbol **h;
+
+	if ((sym->flags & SDECLARED) == 0)
+		return;
+	h = hash(sym->name, sym->ns);
+	assert(sym->ns == NS_CPP || *h == sym);
+	while (*h != sym)
+		h = &(*h)->hash;
+	*h = sym->hash;
+}
+
+void
+pushctx(void)
+{
+	DBG("SYM: pushed context %d", curctx+1);
+	if (++curctx == NR_BLOCK+1)
+		error("too many nested blocks");
+}
+
+void
+killsym(Symbol *sym)
+{
+	short f;
+	char *name;
+
+	if (!sym)
+		return;
+	f = sym->flags;
+	if (f & SSTRING)
+		free(sym->u.s);
+	if (sym->ns == NS_TAG)
+		sym->type->prop &= ~TDEFINED;
+	unlinkhash(sym);
+	if ((name = sym->name) != NULL) {
+		switch (sym->ns) {
+		case NS_LABEL:
+			if ((f & SDEFINED) == 0)
+				errorp("label '%s' is not defined", name);
+		case NS_IDEN:
+			if ((f & (SUSED|SGLOBAL|SDECLARED)) == SDECLARED)
+				warn("'%s' defined but not used", name);
+			break;
+		}
+	}
+	free(name);
+	free(sym);
+}
+
+void
+popctx(void)
+{
+	Symbol *next, *sym;
+	int ns, dangling = 0;
+
+	DBG("SYM: poped context %d", curctx);
+	/*
+	 * we have to be careful before popping the current
+	 * context, because since the parser is one token
+	 * ahead it may already have read an identifier at
+	 * this point, and yylval.sym is a pointer to
+	 * the symbol associated to such token. If that
+	 * symbol is from the context that we are popping
+	 * then we are going to generate a dangling pointer.
+	 * We can detect this situation and call again to
+	 * lookup.
+	 */
+	if ((yytoken == IDEN || yytoken == TYPEIDEN) &&
+	    yylval.sym->ctx == curctx) {
+		ns = yylval.sym->ns;
+		dangling = 1;
+	}
+
+	for (sym = head; sym && sym->ctx == curctx; sym = next) {
+		/*
+		 * Since we are unlinking them in the inverse order
+		 * we do know that sym is always the head of the
+		 * collision list
+		 */
+		next = sym->next;
+		killsym(sym);
+	}
+	head = sym;
+
+	if (--curctx == GLOBALCTX) {
+		for (sym = labels; sym; sym = next) {
+			next = sym->next;
+			killsym(sym);
+		}
+		labels = NULL;
+	}
+
+	if (dangling) {
+		yylval.sym = lookup(ns, yytext, ALLOC);
+		yytoken = yylval.sym->token;
+	}
+}
+
+unsigned
+newid(void)
+{
+	unsigned short id;
+
+	if (lexmode == CPPMODE)
+		return 0;
+	id = ++counterid;
+	if (id == 0) {
+		die("cc1: overflow in %s identifiers",
+		    (curctx) ? "internal" : "external");
+	}
+	return id;
+}
+
+Symbol *
+newsym(int ns, char *name)
+{
+	Symbol *sym;
+
+	sym = xmalloc(sizeof(*sym));
+	if (name)
+		name = xstrdup(name);
+	sym->name = name;
+	sym->id = 0;
+	sym->hide = 0;
+	sym->ns = ns;
+	sym->ctx = curctx;
+	sym->token = IDEN;
+	sym->flags = 0;
+	sym->u.s = NULL;
+	sym->type = NULL;
+	sym->hash = NULL;
+
+	if (ns == NS_LABEL) {
+		sym->next = labels;
+		labels = sym;
+	} else if (ns != NS_CPP) {
+		sym->next = head;
+		head = sym;
+	}
+	return sym;
+}
+
+static Symbol *
+linkhash(Symbol *sym)
+{
+	Symbol **h;
+
+	h = hash(sym->name, sym->ns);
+	sym->hash = *h;
+	*h = sym;
+
+	if (sym->ns != NS_CPP)
+		sym->id = newid();
+	sym->flags |= SDECLARED;
+	return sym;
+}
+
+Symbol *
+newstring(char *s, size_t len)
+{
+	Symbol *sym = newsym(NS_IDEN, NULL);
+
+	if (lexmode != CPPMODE)
+		sym->type = mktype(chartype, ARY, len, NULL);
+	sym->id = newid();
+	sym->flags |= SSTRING | SCONSTANT | SPRIVATE;
+	sym->u.s = xmalloc(len);
+	if (s)
+		memcpy(sym->u.s, s, len);
+
+	return sym;
+}
+
+Symbol *
+newlabel(void)
+{
+	Symbol *sym = newsym(NS_LABEL, NULL);
+	sym->id = newid();
+	return sym;
+}
+
+Symbol *
+lookup(int ns, char *name, int alloc)
+{
+	Symbol *sym;
+	int sns, c;
+	char *t;
+
+	c = *name;
+	for (sym = *hash(name, ns); sym; sym = sym->hash) {
+		t = sym->name;
+		if (*t != c || strcmp(t, name))
+			continue;
+		sns = sym->ns;
+		if (sns == ns)
+			return sym;
+		/*
+		 * When a lookup is done in a namespace associated
+		 * to a struct we also want symbols of NS_IDEN which
+		 * are typedef, because in other case we cannot declare
+		 * fields of such types.
+		 * TODO: Remove this trick
+		 */
+		if (sns == NS_KEYWORD ||
+		    (sym->flags & STYPEDEF) && ns >= NS_STRUCTS) {
+			return sym;
+		}
+	}
+	return (alloc == ALLOC) ? newsym(ns, name) : NULL;
+}
+
+Symbol *
+install(int ns, Symbol *sym)
+{
+	if (sym->flags & SDECLARED || sym->ctx != curctx) {
+		if (sym->ctx == curctx && ns == sym->ns)
+			return NULL;
+		sym = newsym(ns, sym->name);
+	}
+	return linkhash(sym);
+}
+
+void
+keywords(struct keyword *key, int ns)
+{
+	Symbol *sym;
+
+	for ( ; key->str; ++key) {
+		sym = linkhash(newsym(ns, key->str));
+		sym->token = key->token;
+		sym->u.token = key->value;
+	}
+	/*
+	 * Remove all the predefined symbols from * the symbol list. It
+	 * will make faster some operations. There is no problem of memory
+	 * leakeage because this memory is not ever freed
+	 */
+	counterid = 0;
+	head = NULL;
+}
+
+void
+builtins(struct builtin *built)
+{
+	Symbol *sym;
+	struct builtin *bp;
+
+	for (bp = built; bp->str; ++bp) {
+		sym = linkhash(newsym(NS_KEYWORD, bp->str));
+		sym->token = BUILTIN;
+		sym->u.fun = bp->fun;
+	}
+	/*
+	 * Remove all the predefined symbols from * the symbol list. It
+	 * will make faster some operations. There is no problem of memory
+	 * leakeage because this memory is not ever freed
+	 */
+	counterid = 0;
+	head = NULL;
+}
--- /dev/null
+++ b/src/cmd/cc/cc1/target/amd64-sysv/arch.c
@@ -1,0 +1,218 @@
+#include <scc/scc.h>
+#include "../../cc1.h"
+
+#define RANK_BOOL    0
+#define RANK_SCHAR   1
+#define RANK_UCHAR   1
+#define RANK_CHAR    1
+#define RANK_SHORT   2
+#define RANK_USHORT  2
+#define RANK_INT     3
+#define RANK_UINT    3
+#define RANK_LONG    4
+#define RANK_ULONG   4
+#define RANK_LLONG   5
+#define RANK_ULLONG  5
+#define RANK_FLOAT   6
+#define RANK_DOUBLE  7
+#define RANK_LDOUBLE 8
+
+/*
+ * Initializaion of type pointers were done with
+ * a C99 initilizator '... = &(Type) {...', but
+ * c compiler in Plan9 gives error with this
+ * syntax, so I have switched it to this ugly form
+ * I hope I will change it again in the future
+ */
+
+static Type types[] = {
+	{       /* 0 = voidtype */
+		.op = VOID,
+		.letter = L_VOID,
+	},
+	{       /* 1 = pvoidtype */
+		.op = PTR,
+		.letter = L_POINTER,
+		.prop = TDEFINED,
+		.type = &types[5],  /* chartype */
+		.size = 8,
+		.align = 8,
+	},
+	{      /* 2 = booltype */
+		.op = INT,
+		.letter = L_BOOL,
+		.prop = TDEFINED | TINTEGER | TARITH,
+		.size = 1,
+		.align = 1,
+		.n.rank = RANK_BOOL,
+	},
+	{       /* 3 = schartype */
+		.op = INT,
+		.letter = L_INT8,
+		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+		.size = 1,
+		.align = 1,
+		.n.rank = RANK_SCHAR,
+	},
+	{      /* 4 = uchartype */
+		.op = INT,
+		.letter = L_UINT8,
+		.prop = TDEFINED | TINTEGER | TARITH,
+		.size = 1,
+		.align = 1,
+		.n.rank = RANK_UCHAR,
+	},
+	{      /* 5 = chartype */
+		.op = INT,
+		.letter = L_INT8,
+		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+		.size = 1,
+		.align = 1,
+		.n.rank = RANK_CHAR,
+	},
+	{       /* 6 = ushortype */
+		.op = INT,
+		.letter = L_UINT16,
+		.prop = TDEFINED | TINTEGER | TARITH,
+		.size = 2,
+		.align = 2,
+		.n.rank = RANK_USHORT,
+	},
+	{       /* 7 = shortype */
+		.op = INT,
+		.letter = L_INT16,
+		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+		.size = 2,
+		.align = 2,
+		.n.rank = RANK_SHORT,
+	},
+	{       /* 8 = uinttype */
+		.op = INT,
+		.letter = L_UINT32,
+		.prop = TDEFINED | TINTEGER | TARITH,
+		.size = 4,
+		.align = 4,
+		.n.rank = RANK_UINT,
+	},
+	{       /* 9 = inttype */
+		.op = INT,
+		.letter = L_INT32,
+		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+		.size = 4,
+		.align = 4,
+		.n.rank = RANK_INT,
+	},
+	{      /* 10 = longtype */
+		.op = INT,
+		.letter = L_INT64,
+		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+		.size = 8,
+		.align = 8,
+		.n.rank = RANK_LONG,
+	},
+	{       /* 11 = ulongtype */
+		.op = INT,
+		.letter = L_UINT64,
+		.prop = TDEFINED | TINTEGER | TARITH,
+		.size = 8,
+		.align = 8,
+		.n.rank = RANK_ULONG,
+	},
+	{	/* 12 = ullongtype */
+		.op = INT,
+		.letter = L_UINT64,
+		.prop = TDEFINED | TINTEGER | TARITH,
+		.size = 8,
+		.align = 8,
+		.n.rank = RANK_ULLONG,
+	},
+	{       /* 13 = llongtype */
+		.op = INT,
+		.letter = L_INT64,
+		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+		.size = 8,
+		.align = 8,
+		.n.rank = RANK_LLONG,
+	},
+	{       /* 14 = floattype */
+		.op = FLOAT,
+		.letter = L_FLOAT,
+		.prop = TDEFINED | TARITH,
+		.size = 4,
+		.align = 4,
+		.n.rank = RANK_FLOAT,
+	},
+	{       /* 15 = doubletype */
+		.op = FLOAT,
+		.letter = L_DOUBLE,
+		.prop = TDEFINED | TARITH,
+		.size = 8,
+		.align = 8,
+		.n.rank = RANK_DOUBLE,
+	},
+	{       /* 16 = ldoubletype */
+		.op = FLOAT,
+		.letter = L_LDOUBLE,
+		.prop = TDEFINED | TARITH,
+		.size = 16,
+		.align = 16,
+		.n.rank = RANK_LDOUBLE,
+	},
+	{       /* 17 = sizettype */
+		.op = INT,
+		.letter = L_UINT64,
+		.prop = TDEFINED | TINTEGER | TARITH,
+		.size = 8,
+		.align = 8,
+		.n.rank = RANK_UINT,
+	},
+	{      /* 18 = ellipsis */
+		.op = ELLIPSIS,
+		.letter = L_ELLIPSIS,
+		.prop = TDEFINED,
+	},
+	{      /* 19 = pdifftype */
+		.op = INT,
+		.letter = L_INT64,
+		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+		.size = 8,
+		.align = 8,
+		.n.rank = RANK_LONG,
+	},
+	{      /* 20 = va_type */
+		.op = STRUCT,
+		.letter = L_VA_ARG,
+		.prop = TDEFINED,
+		.size = 24,
+		.align = 8,
+	},
+};
+
+Type *voidtype = &types[0], *pvoidtype = &types[1],
+     *booltype = &types[2], *schartype = &types[3],
+     *uchartype = &types[4], *chartype = &types[5],
+     *ushortype = &types[6], *shortype = &types[7],
+     *uinttype = &types[8], *inttype = &types[9],
+     *longtype = &types[10], *ulongtype = &types[11],
+     *ullongtype = &types[12], *llongtype = &types[13],
+     *floattype = &types[14], *doubletype = &types[15],
+     *ldoubletype = &types[16],
+     *sizettype = &types[17], *pdifftype = &types[19],
+     *ellipsistype = &types[18], *va_type = &types[20],
+     *va_list_type;
+
+static Symbol dummy0 = {.u.i = 0, .type = &types[9]},
+              dummy1 = {.u.i = 1, .type = &types[9]};
+Symbol *zero = &dummy0, *one = &dummy1;
+
+void
+iarch(void)
+{
+	va_list_type = mktype(va_type, ARY, 1, NULL);
+}
+
+int
+valid_va_list(Type *tp)
+{
+	return tp->op == PTR && eqtype(tp->type, va_type, 1);
+}
--- /dev/null
+++ b/src/cmd/cc/cc1/target/amd64-sysv/arch.mk
@@ -1,0 +1,4 @@
+OBJ-amd64-sysv= $(OBJS)  target/amd64-sysv/arch.o
+
+$(LIBEXEC)/cc1-amd64-sysv: $(OBJ-amd64-sysv)
+	$(CC) $(SCC_LDFLAGS) $(OBJ-amd64-sysv) -lscc -o $@
--- /dev/null
+++ b/src/cmd/cc/cc1/target/arm64-sysv/arch.c
@@ -1,0 +1,218 @@
+#include <scc/scc.h>
+#include "../../cc1.h"
+
+#define RANK_BOOL    0
+#define RANK_SCHAR   1
+#define RANK_UCHAR   1
+#define RANK_CHAR    1
+#define RANK_SHORT   2
+#define RANK_USHORT  2
+#define RANK_INT     3
+#define RANK_UINT    3
+#define RANK_LONG    4
+#define RANK_ULONG   4
+#define RANK_LLONG   5
+#define RANK_ULLONG  5
+#define RANK_FLOAT   6
+#define RANK_DOUBLE  7
+#define RANK_LDOUBLE 8
+
+/*
+ * Initializaion of type pointers were done with
+ * a C99 initilizator '... = &(Type) {...', but
+ * c compiler in Plan9 gives error with this
+ * syntax, so I have switched it to this ugly form
+ * I hope I will change it again in the future
+ */
+
+static Type types[] = {
+	{       /* 0 = voidtype */
+		.op = VOID,
+		.letter = L_VOID,
+	},
+	{       /* 1 = pvoidtype */
+		.op = PTR,
+		.letter = L_POINTER,
+		.prop = TDEFINED,
+		.type = &types[5],  /* chartype */
+		.size = 8,
+		.align = 8,
+	},
+	{      /* 2 = booltype */
+		.op = INT,
+		.letter = L_BOOL,
+		.prop = TDEFINED | TINTEGER | TARITH,
+		.size = 1,
+		.align = 1,
+		.n.rank = RANK_BOOL,
+	},
+	{       /* 3 = schartype */
+		.op = INT,
+		.letter = L_INT8,
+		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+		.size = 1,
+		.align = 1,
+		.n.rank = RANK_SCHAR,
+	},
+	{      /* 4 = uchartype */
+		.op = INT,
+		.letter = L_UINT8,
+		.prop = TDEFINED | TINTEGER | TARITH,
+		.size = 1,
+		.align = 1,
+		.n.rank = RANK_UCHAR,
+	},
+	{      /* 5 = chartype */
+		.op = INT,
+		.letter = L_INT8,
+		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+		.size = 1,
+		.align = 1,
+		.n.rank = RANK_CHAR,
+	},
+	{       /* 6 = ushortype */
+		.op = INT,
+		.letter = L_UINT16,
+		.prop = TDEFINED | TINTEGER | TARITH,
+		.size = 2,
+		.align = 2,
+		.n.rank = RANK_USHORT,
+	},
+	{       /* 7 = shortype */
+		.op = INT,
+		.letter = L_INT16,
+		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+		.size = 2,
+		.align = 2,
+		.n.rank = RANK_SHORT,
+	},
+	{       /* 8 = uinttype */
+		.op = INT,
+		.letter = L_UINT32,
+		.prop = TDEFINED | TINTEGER | TARITH,
+		.size = 4,
+		.align = 4,
+		.n.rank = RANK_UINT,
+	},
+	{       /* 9 = inttype */
+		.op = INT,
+		.letter = L_INT32,
+		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+		.size = 4,
+		.align = 4,
+		.n.rank = RANK_INT,
+	},
+	{      /* 10 = longtype */
+		.op = INT,
+		.letter = L_INT64,
+		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+		.size = 8,
+		.align = 8,
+		.n.rank = RANK_LONG,
+	},
+	{       /* 11 = ulongtype */
+		.op = INT,
+		.letter = L_UINT64,
+		.prop = TDEFINED | TINTEGER | TARITH,
+		.size = 8,
+		.align = 8,
+		.n.rank = RANK_ULONG,
+	},
+	{	/* 12 = ullongtype */
+		.op = INT,
+		.letter = L_UINT64,
+		.prop = TDEFINED | TINTEGER | TARITH,
+		.size = 8,
+		.align = 8,
+		.n.rank = RANK_ULLONG,
+	},
+	{       /* 13 = llongtype */
+		.op = INT,
+		.letter = L_INT64,
+		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+		.size = 8,
+		.align = 8,
+		.n.rank = RANK_LLONG,
+	},
+	{       /* 14 = floattype */
+		.op = FLOAT,
+		.letter = L_FLOAT,
+		.prop = TDEFINED | TARITH,
+		.size = 4,
+		.align = 4,
+		.n.rank = RANK_FLOAT,
+	},
+	{       /* 15 = doubletype */
+		.op = FLOAT,
+		.letter = L_DOUBLE,
+		.prop = TDEFINED | TARITH,
+		.size = 8,
+		.align = 8,
+		.n.rank = RANK_DOUBLE,
+	},
+	{       /* 16 = ldoubletype */
+		.op = FLOAT,
+		.letter = L_LDOUBLE,
+		.prop = TDEFINED | TARITH,
+		.size = 16,
+		.align = 16,
+		.n.rank = RANK_LDOUBLE,
+	},
+	{       /* 17 = sizettype */
+		.op = INT,
+		.letter = L_UINT64,
+		.prop = TDEFINED | TINTEGER | TARITH,
+		.size = 8,
+		.align = 8,
+		.n.rank = RANK_UINT,
+	},
+	{      /* 18 = ellipsis */
+		.op = ELLIPSIS,
+		.letter = L_ELLIPSIS,
+		.prop = TDEFINED,
+	},
+	{      /* 19 = pdifftype */
+		.op = INT,
+		.letter = L_INT64,
+		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+		.size = 8,
+		.align = 8,
+		.n.rank = RANK_LONG,
+	},
+	{      /* 20 = va_type */
+		.op = STRUCT,
+		.letter = L_VA_ARG,
+		.prop = TDEFINED,
+		.size = 24,
+		.align = 8,
+	},
+};
+
+Type *voidtype = &types[0], *pvoidtype = &types[1],
+     *booltype = &types[2], *schartype = &types[3],
+     *uchartype = &types[4], *chartype = &types[5],
+     *ushortype = &types[6], *shortype = &types[7],
+     *uinttype = &types[8], *inttype = &types[9],
+     *longtype = &types[10], *ulongtype = &types[11],
+     *ullongtype = &types[12], *llongtype = &types[13],
+     *floattype = &types[14], *doubletype = &types[15],
+     *ldoubletype = &types[16],
+     *sizettype = &types[17], *pdifftype = &types[19],
+     *ellipsistype = &types[18], *va_type = &types[20],
+     *va_list_type;
+
+static Symbol dummy0 = {.u.i = 0, .type = &types[9]},
+              dummy1 = {.u.i = 1, .type = &types[9]};
+Symbol *zero = &dummy0, *one = &dummy1;
+
+void
+iarch(void)
+{
+	va_list_type = mktype(va_type, ARY, 1, NULL);
+}
+
+int
+valid_va_list(Type *tp)
+{
+	return tp->op == PTR && eqtype(tp->type, va_type, 1);
+}
--- /dev/null
+++ b/src/cmd/cc/cc1/target/arm64-sysv/arch.mk
@@ -1,0 +1,4 @@
+OBJ-arm64-sysv= $(OBJS)  target/arm64-sysv/arch.o
+
+$(LIBEXEC)/cc1-arm64-sysv: $(OBJ-arm64-sysv)
+	$(CC) $(SCC_LDFLAGS) $(OBJ-arm64-sysv) -lscc -o $@
--- /dev/null
+++ b/src/cmd/cc/cc1/target/i386-sysv/arch.c
@@ -1,0 +1,219 @@
+#include <scc/scc.h>
+#include "../../cc1.h"
+
+#define RANK_BOOL    0
+#define RANK_SCHAR   1
+#define RANK_UCHAR   1
+#define RANK_CHAR    1
+#define RANK_SHORT   2
+#define RANK_USHORT  2
+#define RANK_INT     3
+#define RANK_UINT    3
+#define RANK_LONG    4
+#define RANK_ULONG   4
+#define RANK_LLONG   5
+#define RANK_ULLONG  5
+#define RANK_FLOAT   6
+#define RANK_DOUBLE  7
+#define RANK_LDOUBLE 8
+
+/*
+ * Initializaion of type pointers were done with
+ * a C99 initilizator '... = &(Type) {...', but
+ * c compiler in Plan9 gives error with this
+ * syntax, so I have switched it to this ugly form
+ * I hope I will change it again in the future
+ */
+
+static Type types[] = {
+	{       /* 0 = voidtype */
+		.op = VOID,
+		.letter = L_VOID,
+	},
+	{       /* 1 = pvoidtype */
+		.op = PTR,
+		.letter = L_POINTER,
+		.prop = TDEFINED,
+		.type = &types[5],  /* chartype */
+		.size = 4,
+		.align = 4,
+	},
+	{      /* 2 = booltype */
+		.op = INT,
+		.letter = L_BOOL,
+		.prop = TDEFINED | TINTEGER | TARITH,
+		.size = 1,
+		.align = 1,
+		.n.rank = RANK_BOOL,
+	},
+	{       /* 3 = schartype */
+		.op = INT,
+		.letter = L_INT8,
+		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+		.size = 1,
+		.align = 1,
+		.n.rank = RANK_SCHAR,
+	},
+	{      /* 4 = uchartype */
+		.op = INT,
+		.letter = L_UINT8,
+		.prop = TDEFINED | TINTEGER | TARITH,
+		.size = 1,
+		.align = 1,
+		.n.rank = RANK_UCHAR,
+	},
+	{      /* 5 = chartype */
+		.op = INT,
+		.letter = L_INT8,
+		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+		.size = 1,
+		.align = 1,
+		.n.rank = RANK_CHAR,
+	},
+	{       /* 6 = ushortype */
+		.op = INT,
+		.letter = L_UINT16,
+		.prop = TDEFINED | TINTEGER | TARITH,
+		.size = 2,
+		.align = 2,
+		.n.rank = RANK_USHORT,
+	},
+	{       /* 7 = shortype */
+		.op = INT,
+		.letter = L_INT16,
+		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+		.size = 2,
+		.align = 2,
+		.n.rank = RANK_SHORT,
+	},
+	{       /* 8 = uinttype */
+		.op = INT,
+		.letter = L_UINT32,
+		.prop = TDEFINED | TINTEGER | TARITH,
+		.size = 4,
+		.align = 4,
+		.n.rank = RANK_UINT,
+	},
+	{       /* 9 = inttype */
+		.op = INT,
+		.letter = L_INT32,
+		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+		.size = 4,
+		.align = 4,
+		.n.rank = RANK_INT,
+	},
+	{      /* 10 = longtype */
+		.op = INT,
+		.letter = L_INT32,
+		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+		.size = 4,
+		.align = 4,
+		.n.rank = RANK_LONG,
+	},
+	{       /* 11 = ulongtype */
+		.op = INT,
+		.letter = L_UINT32,
+		.prop = TDEFINED | TINTEGER | TARITH,
+		.size = 4,
+		.align = 4,
+		.n.rank = RANK_ULONG,
+	},
+	{	/* 12 = ullongtype */
+		.op = INT,
+		.letter = L_UINT64,
+		.prop = TDEFINED | TINTEGER | TARITH,
+		.size = 8,
+		.align = 4,
+		.n.rank = RANK_ULLONG,
+	},
+	{       /* 13 = llongtype */
+		.op = INT,
+		.letter = L_INT64,
+		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+		.size = 8,
+		.align = 4,
+		.n.rank = RANK_LLONG,
+	},
+	{       /* 14 = floattype */
+		.op = FLOAT,
+		.letter = L_FLOAT,
+		.prop = TDEFINED | TARITH,
+		.size = 4,
+		.align = 4,
+		.n.rank = RANK_FLOAT,
+	},
+	{       /* 15 = doubletype */
+		.op = FLOAT,
+		.letter = L_DOUBLE,
+		.prop = TDEFINED | TARITH,
+		.size = 8,
+		.align = 4,
+		.n.rank = RANK_DOUBLE,
+	},
+	{       /* 16 = ldoubletype */
+		.op = FLOAT,
+		.letter = L_LDOUBLE,
+		.prop = TDEFINED | TARITH,
+		.size = 12,
+		.align = 4,
+		.n.rank = RANK_LDOUBLE,
+	},
+	{       /* 17 = sizettype */
+		.op = INT,
+		.letter = L_UINT32,
+		.prop = TDEFINED | TINTEGER | TARITH,
+		.size = 4,
+		.align = 4,
+		.n.rank = RANK_UINT,
+	},
+	{      /* 18 = ellipsis */
+		.op = ELLIPSIS,
+		.letter = L_ELLIPSIS,
+		.prop = TDEFINED,
+	},
+	{       /* 19 = pdifftype */
+		.op = INT,
+		.letter = L_INT32,
+		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+		.size = 4,
+		.align = 4,
+		.n.rank = RANK_INT,
+	},
+	{      /* 20 = va_list_type */
+		.op = PTR,
+		.letter = L_POINTER,
+		.prop = TDEFINED,
+		.size = 4,
+		.align = 4,
+	},
+};
+
+
+Type *voidtype = &types[0], *pvoidtype = &types[1],
+     *booltype = &types[2], *schartype = &types[3],
+     *uchartype = &types[4], *chartype = &types[5],
+     *ushortype = &types[6], *shortype = &types[7],
+     *uinttype = &types[8], *inttype = &types[9],
+     *longtype = &types[10], *ulongtype = &types[11],
+     *ullongtype = &types[12], *llongtype = &types[13],
+     *floattype = &types[14], *doubletype = &types[15],
+     *ldoubletype = &types[16],
+     *sizettype = &types[17], *pdifftype = &types[19],
+     *ellipsistype = &types[18], *va_list_type = &types[20];
+
+
+
+static Symbol dummy0 = {.u.i = 0, .type = &types[9]},
+              dummy1 = {.u.i = 1, .type = &types[9]};
+Symbol *zero = &dummy0, *one = &dummy1;
+
+void
+iarch(void)
+{
+}
+
+int
+valid_va_list(Type *tp)
+{
+	return eqtype(tp, va_list_type, 1);
+}
--- /dev/null
+++ b/src/cmd/cc/cc1/target/i386-sysv/arch.mk
@@ -1,0 +1,4 @@
+OBJ-i386-sysv= $(OBJS)  target/i386-sysv/arch.o
+
+$(LIBEXEC)/cc1-i386-sysv: $(OBJ-i386-sysv)
+	$(CC) $(SCC_LDFLAGS) $(OBJ-i386-sysv) -lscc -o $@
--- /dev/null
+++ b/src/cmd/cc/cc1/target/z80-scc/arch.c
@@ -1,0 +1,217 @@
+#include <scc/scc.h>
+#include "../../cc1.h"
+
+#define RANK_BOOL    0
+#define RANK_SCHAR   1
+#define RANK_UCHAR   1
+#define RANK_CHAR    1
+#define RANK_SHORT   2
+#define RANK_USHORT  2
+#define RANK_INT     3
+#define RANK_UINT    3
+#define RANK_LONG    4
+#define RANK_ULONG   4
+#define RANK_LLONG   5
+#define RANK_ULLONG  5
+#define RANK_FLOAT   6
+#define RANK_DOUBLE  7
+#define RANK_LDOUBLE 8
+
+/*
+ * Initializaion of type pointers were done with
+ * a C99 initilizator '... = &(Type) {...', but
+ * c compiler in Plan9 gives error with this
+ * syntax, so I have switched it to this ugly form
+ * I hope I will change it again in the future
+ */
+
+static Type types[] = {
+	{       /* 0 = voidtype */
+		.op = VOID,
+		.letter = L_VOID,
+	},
+	{       /* 1 = pvoidtype */
+		.op = PTR,
+		.letter = L_POINTER,
+		.prop = TDEFINED,
+		.type = &types[5], /* char type */
+		.size = 2,
+		.align = 2,
+	},
+	{      /* 2 = booltype */
+		.op = INT,
+		.letter = L_BOOL,
+		.prop = TDEFINED | TINTEGER | TARITH,
+		.size = 1,
+		.align = 1,
+		.n.rank = RANK_BOOL,
+	},
+	{       /* 3 = schartype */
+		.op = INT,
+		.letter = L_INT8,
+		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+		.size = 1,
+		.align = 1,
+		.n.rank = RANK_SCHAR,
+	},
+	{      /* 4 = uchartype */
+		.op = INT,
+		.letter = L_UINT8,
+		.prop = TDEFINED | TINTEGER | TARITH,
+		.size = 1,
+		.align = 1,
+		.n.rank = RANK_UCHAR,
+	},
+	{      /* 5 = chartype */
+		.op = INT,
+		.letter = L_UINT8,
+		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+		.size = 1,
+		.align = 1,
+		.n.rank = RANK_CHAR,
+	},
+	{       /* 6 = ushortype */
+		.op = INT,
+		.letter = L_UINT16,
+		.prop = TDEFINED | TINTEGER | TARITH,
+		.size = 2,
+		.align = 1,
+		.n.rank = RANK_USHORT,
+	},
+	{       /* 7 = shortype */
+		.op = INT,
+		.letter = L_INT16,
+		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+		.size = 2,
+		.align = 1,
+		.n.rank = RANK_SHORT,
+	},
+	{       /* 8 = uinttype */
+		.op = INT,
+		.letter = L_UINT16,
+		.prop = TDEFINED | TINTEGER | TARITH,
+		.size = 2,
+		.align = 1,
+		.n.rank = RANK_UINT,
+	},
+	{       /* 9 = inttype */
+		.op = INT,
+		.letter = L_INT16,
+		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+		.size = 2,
+		.align = 1,
+		.n.rank = RANK_INT,
+	},
+	{      /* 10 = longtype */
+		.op = INT,
+		.letter = L_INT32,
+		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+		.size = 4,
+		.align = 1,
+		.n.rank = RANK_LONG,
+	},
+	{       /* 11 = ulongtype */
+		.op = INT,
+		.letter = L_UINT32,
+		.prop = TDEFINED | TINTEGER | TARITH,
+		.size = 4,
+		.align = 1,
+		.n.rank = RANK_ULONG,
+	},
+	{	/* 12 = ullongtype */
+		.op = INT,
+		.letter = L_UINT64,
+		.prop = TDEFINED | TINTEGER | TARITH,
+		.size = 8,
+		.align = 1,
+		.n.rank = RANK_ULLONG,
+	},
+	{       /* 13 = llongtype */
+		.op = INT,
+		.letter = L_INT64,
+		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+		.size = 8,
+		.align = 1,
+		.n.rank = RANK_LLONG,
+	},
+	{       /* 14 = floattype */
+		.op = FLOAT,
+		.letter = L_FLOAT,
+		.prop = TDEFINED | TARITH,
+		.size = 4,
+		.align = 1,
+		.n.rank = RANK_FLOAT,
+	},
+	{       /* 15 = doubletype */
+		.op = FLOAT,
+		.letter = L_DOUBLE,
+		.prop = TDEFINED | TARITH,
+		.size = 8,
+		.align = 1,
+		.n.rank = RANK_DOUBLE,
+	},
+	{       /* 16 = ldoubletype */
+		.op = FLOAT,
+		.letter = L_LDOUBLE,
+		.prop = TDEFINED | TARITH,
+		.size = 16,
+		.align = 1,
+		.n.rank = RANK_LDOUBLE,
+	},
+	{       /* 17 = sizettype */
+		.op = INT,
+		.letter = L_UINT16,
+		.prop = TDEFINED | TINTEGER | TARITH,
+		.size = 2,
+		.align = 1,
+		.n.rank = RANK_UINT,
+	},
+	{      /* 18 = ellipsis */
+		.op = ELLIPSIS,
+		.letter = L_ELLIPSIS,
+		.prop = TDEFINED,
+	},
+	{       /* 7 = pdifftype */
+		.op = INT,
+		.letter = L_INT16,
+		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
+		.size = 2,
+		.align = 1,
+		.n.rank = RANK_SHORT,
+	},
+	{       /* 20 = va_list_type */
+		.op = PTR,
+		.letter = L_POINTER,
+		.prop = TDEFINED,
+		.size = 2,
+		.align = 1,
+	}
+};
+
+Type *voidtype = &types[0], *pvoidtype = &types[1],
+     *booltype = &types[2], *schartype = &types[3],
+     *uchartype = &types[4], *chartype = &types[5],
+     *ushortype = &types[6], *shortype = &types[7],
+     *uinttype = &types[8], *inttype = &types[9],
+     *longtype = &types[10], *ulongtype = &types[11],
+     *ullongtype = &types[12], *llongtype = &types[13],
+     *floattype = &types[14], *doubletype = &types[15],
+     *ldoubletype = &types[16],
+     *sizettype = &types[17], *pdifftype = &types[19],
+     *ellipsistype = &types[18], *va_list_type = &types[20];
+
+
+static Symbol dummy0 = {.u.i = 0, .type = &types[9]},
+              dummy1 = {.u.i = 1, .type = &types[9]};
+Symbol *zero = &dummy0, *one = &dummy1;
+
+void
+iarch(void)
+{
+}
+
+int
+valid_va_list(Type *tp)
+{
+	return eqtype(tp, va_list_type, 1);
+}
--- /dev/null
+++ b/src/cmd/cc/cc1/target/z80-scc/arch.mk
@@ -1,0 +1,4 @@
+OBJ-z80-scc= $(OBJS) target/z80-scc/arch.o
+
+$(LIBEXEC)/cc1-z80-scc: $(OBJ-z80-scc)
+	$(CC) $(SCC_LDFLAGS) $(OBJ-z80-scc) -lscc -o $@
--- /dev/null
+++ b/src/cmd/cc/cc1/types.c
@@ -1,0 +1,437 @@
+#include <assert.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+#include "cc1.h"
+
+#define NR_TYPE_HASH 16
+#define HASH(t) (((t)->op ^ (uintptr_t) (t)->type>>3) & NR_TYPE_HASH-1)
+
+static Type *typetab[NR_TYPE_HASH], *localtypes;
+
+/* FIXME:
+ * Compiler can generate warnings here if the ranges of TINT,
+ * TUINT and TFLOAT are smaller than any of the constants in this
+ * array. Ignore them if you know that the target types are correct
+ */
+static struct limits limits[][4] = {
+	{
+		{	/* 0 = unsigned 1 byte */
+			.min.i = 0,
+			.max.i = 0xff
+		},
+		{	/* 1 = unsigned 2 bytes */
+			.min.i = 0,
+			.max.i = 0xffff
+		},
+		{	/* 2 = unsigned 4 bytes */
+			.min.i = 0,
+			.max.i = 0xffffffff
+		},
+		{	/* 3 = unsigned 8 bytes */
+			.min.i = 0,
+			.max.i = 0xffffffffffffffff
+		}
+	},
+	{
+		{	/* 0 = signed 1 byte */
+			.min.i = -0x7f-1,
+			.max.i = 0x7f
+		},
+		{	/* 1 = signed 2 byte */
+			.min.i = -0x7fff-1,
+			.max.i = 0x7fff
+		},
+		{	/* 2 = signed 4 byte */
+			.min.i = -0x7fffffff-1,
+			.max.i = 0x7fffffff
+		},
+		{	/* 3 = signed 8 byte */
+			.min.i = -0x7fffffffffffffff-1,
+			.max.i = 0x7fffffffffffffff,
+		}
+	},
+	{
+		{
+			/* 0 = float 4 bytes */
+			.min.f = -1,
+			.max.f = 2
+		},
+		{
+			/* 1 = float 8 bytes */
+			.min.f = -1,
+			.max.f = 2,
+		},
+		{
+			/* 2 = float 16 bytes */
+			.min.f = -1,
+			.max.f = 2,
+		}
+	}
+};
+
+struct limits *
+getlimits(Type *tp)
+{
+	int ntable, ntype;
+
+	switch (tp->op) {
+	case ENUM:
+	case INT:
+		ntable = ((tp->prop & TSIGNED) != 0);
+		switch (tp->size) {
+		case 1: ntype = 0; break;
+		case 2: ntype = 1; break;
+		case 4: ntype = 2; break;
+		case 8: ntype = 3; break;
+		}
+		break;
+	case FLOAT:
+		ntable = 2;
+		switch (tp->size) {
+		case 4:  ntype = 0; break;
+		case 8:  ntype = 1; break;
+		case 16: ntype = 2; break;
+		}
+		break;
+	default:
+		abort();
+	}
+
+	return &limits[ntable][ntype];
+}
+
+Type *
+ctype(int type, int sign, int size)
+{
+	switch (type) {
+	case CHAR:
+		if (size)
+			goto invalid_type;
+		switch (sign) {
+		case 0:
+			return chartype;
+		case SIGNED:
+			return schartype;
+		case UNSIGNED:
+			return uchartype;
+		}
+		break;
+	case VA_LIST:
+		if (size || sign)
+			goto invalid_type;
+		return va_list_type;
+	case VOID:
+		if (size || sign)
+			goto invalid_type;
+		return voidtype;
+	case BOOL:
+		if (size || sign)
+			goto invalid_type;
+		return booltype;
+	case 0:
+	case INT:
+		switch (size) {
+		case 0:
+			return (sign == UNSIGNED) ? uinttype   : inttype;
+		case SHORT:
+			return (sign == UNSIGNED) ? ushortype  : shortype;
+		case LONG:
+			return (sign == UNSIGNED) ? ulongtype  : longtype;
+		case LLONG:
+			return (sign == UNSIGNED) ? ullongtype : llongtype;
+		}
+		break;
+	case DOUBLE:
+		if (size == LLONG)
+			goto invalid_type;
+		if (size == LONG)
+			size = LLONG;
+		else
+			size = LONG;
+		goto floating;
+	case FLOAT:
+		if (size == LLONG)
+			goto invalid_type;
+	floating:
+		if (sign)
+			goto invalid_type;
+		switch (size) {
+		case 0:
+			return floattype;
+		case LONG:
+			return doubletype;
+		case LLONG:
+			return ldoubletype;
+		}
+		break;
+	}
+
+invalid_type:
+	error("invalid type specification");
+}
+
+void
+typesize(Type *tp)
+{
+	Symbol **sp;
+	Type *type;
+	unsigned long size, offset;
+	int align, a;
+	TINT n;
+
+	switch (tp->op) {
+	case ARY:
+		/* FIXME: Control overflow */
+		tp->size = tp->n.elem * tp->type->size;
+		tp->align = tp->type->align;
+		return;
+	case PTR:
+		tp->size = pvoidtype->size;
+		tp->align = pvoidtype->align;
+		return;
+	case STRUCT:
+	case UNION:
+		/* FIXME: Control overflow */
+		/*
+		 * The alignment of the struct/union is
+		 * he alignment of the largest included type.
+		 * The size of an union is the size of the largest
+		 * field, and the size of a struct is the sum
+		 * of the size of every field plus padding bits.
+		 */
+		offset = align = size = 0;
+		n = tp->n.elem;
+		for (sp = tp->p.fields; n--; ++sp) {
+			(*sp)->u.i = offset;
+			type = (*sp)->type;
+			a = type->align;
+			if (a > align)
+				align = a;
+			if (tp->op == STRUCT) {
+				if (--a != 0)
+					size = (size + a) & ~a;
+				size += type->size;
+				offset = size;
+			} else {
+				if (type->size > size)
+					size = type->size;
+			}
+		}
+
+		tp->align = align;
+		/*
+		 * We have to add the padding bits to
+		 * ensure next struct in an array is well
+		 * alignment.
+		 */
+		if (tp->op == STRUCT && align-- > 1)
+			size += size+align & ~align;
+		tp->size = size;
+		return;
+	case ENUM:
+		tp->size = inttype->size;
+		tp->align = inttype->align;
+		return;
+	case FTN:
+		return;
+	default:
+		abort();
+	}
+}
+
+Type *
+deftype(Type *tp)
+{
+	tp->prop |= TDEFINED;
+	typesize(tp);
+	emit(OTYP, tp);
+	return tp;
+}
+
+static Type *
+newtype(Type *base)
+{
+	Type *tp;
+	size_t siz;
+
+	tp = xmalloc(sizeof(*tp));
+	*tp = *base;
+	tp->id = newid();
+
+	if (tp->op == FTN) {
+		siz = tp->n.elem * sizeof(Type *);
+		tp->p.pars = memcpy(xmalloc(siz), tp->p.pars, siz);
+	}
+
+	if (curfun) {
+		/* it is a type defined in the body of a function */
+		tp->next = localtypes;
+		localtypes = tp;
+	}
+	if (tp->prop & TDEFINED)
+		deftype(tp);
+	return tp;
+}
+
+Type *
+mktype(Type *tp, int op, TINT nelem, Type *pars[])
+{
+	Type **tbl, type;
+	Type *bp;
+
+	if (op == PTR && tp == voidtype)
+		return pvoidtype;
+
+	memset(&type, 0, sizeof(type));
+	type.type = tp;
+	type.op = op;
+	type.p.pars = pars;
+	type.n.elem = nelem;
+
+	switch (op) {
+	case ARY:
+		if (tp == voidtype) {
+			errorp("declaration of array of voids type");
+			tp = inttype;
+		}
+		type.letter = L_ARRAY;
+		if (nelem != 0)
+			type.prop |= TDEFINED;
+		break;
+	case KRFTN:
+		type.prop |= TDEFINED | TK_R;
+		type.op = FTN;
+		type.letter = L_FUNCTION;
+		break;
+	case FTN:
+		if (nelem > 0 && pars[nelem-1] == ellipsistype)
+			type.prop |= TELLIPSIS;
+		type.letter = L_FUNCTION;
+		type.prop |= TDEFINED;
+		break;
+	case PTR:
+	        type.letter = L_POINTER;
+		type.prop |= TDEFINED;
+		break;
+	case ENUM:
+		type.letter = inttype->letter;
+		type.prop |= TINTEGER | TARITH;
+		type.n.rank = inttype->n.rank;
+		goto create_type;
+	case STRUCT:
+		type.letter = L_STRUCT;
+		type.prop |= TAGGREG;
+		goto create_type;
+	case UNION:
+		type.letter = L_UNION;
+		type.prop |= TAGGREG;
+	create_type:
+		return newtype(&type);
+	default:
+		abort();
+	}
+
+	tbl = &typetab[HASH(&type)];
+	for (bp = *tbl; bp; bp = bp->h_next) {
+		if (eqtype(bp, &type, 0))
+			return bp;
+	}
+
+	bp = newtype(&type);
+	bp->h_next = *tbl;
+	*tbl = bp;
+
+	return bp;
+}
+
+int
+eqtype(Type *tp1, Type *tp2, int equiv)
+{
+	TINT n;
+	Type **p1, **p2;
+	Symbol **s1, **s2;
+
+	if (tp1 == tp2)
+		return 1;
+	if (!tp1 || !tp2)
+		return 0;
+	if (tp1->op != tp2->op)
+		return 0;
+
+	switch (tp1->op) {
+	case UNION:
+	case STRUCT:
+		if (tp1->letter != tp2->letter)
+			return 0;
+		if (tp1->tag->name || tp2->tag->name)
+			return tp1->tag == tp2->tag;
+		if (tp1->n.elem != tp2->n.elem)
+			return 0;
+		s1 = tp1->p.fields, s2 = tp2->p.fields;
+		for (n = tp1->n.elem; n > 0; --n, ++s1, ++s2) {
+			if (strcmp((*s1)->name, (*s2)->name))
+				return 0;
+			if (!eqtype((*s1)->type, (*s2)->type, equiv))
+				return 0;
+		}
+		return 1;
+	case FTN:
+		if (tp1->n.elem != tp2->n.elem)
+			return 0;
+		p1 = tp1->p.pars, p2 = tp2->p.pars;
+		for (n = tp1->n.elem; n > 0; --n) {
+			if (!eqtype(*p1++, *p2++, equiv))
+				return 0;
+		}
+		goto check_base;
+	case ARY:
+		if (equiv && (tp1->n.elem == 0 || tp2->n.elem == 0))
+			goto check_base;
+		if (tp1->n.elem != tp2->n.elem)
+			return 0;
+	case PTR:
+	check_base:
+		return eqtype(tp1->type, tp2->type, equiv);
+	case VOID:
+	case ENUM:
+		return 0;
+	case INT:
+	case FLOAT:
+		return tp1->letter == tp2->letter;
+	default:
+		abort();
+	}
+}
+
+void
+flushtypes(void)
+{
+	Type *tp, *next, **h;
+
+	for (tp = localtypes; tp; tp = next) {
+		next = tp->next;
+		switch (tp->op) {
+		default:
+			/*
+			 * All the local types are linked after
+			 * global types, and since we are
+			 * unlinking them in the inverse order
+			 * we do know that tp is always the head
+			 * of the collision list
+			 */
+			h = &typetab[HASH(tp)];
+			assert(*h == tp);
+			*h = tp->h_next;
+		case STRUCT:
+		case UNION:
+		case ENUM:
+			free(tp);
+			break;
+		}
+	}
+	localtypes = NULL;
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/.gitignore
@@ -1,0 +1,1 @@
+error.h
--- /dev/null
+++ b/src/cmd/cc/cc2/Makefile
@@ -1,0 +1,40 @@
+.POSIX:
+
+PROJECTDIR = ../../../..
+include $(PROJECTDIR)/scripts/rules.mk
+
+MORECFLAGS = -I$(INCDIR)/$(STD)
+
+OBJS = main.o \
+       parser.o \
+       peep.o \
+       symbol.o \
+       node.o \
+       code.o \
+       optm.o \
+
+TARGET  = $(LIBEXEC)/cc2-amd64-sysv \
+          $(LIBEXEC)/cc2-i386-sysv \
+          $(LIBEXEC)/cc2-qbe_amd64-sysv \
+          $(LIBEXEC)/cc2-z80-scc \
+
+all: $(TARGET)
+
+$(TARGET): error.h
+
+error.h: cc2.h
+	rm -f $@;\
+	trap 'r=$?;rm -f $$$$.h;exit $r' EXIT INT QUIT ;\
+	awk -f generror.awk cc2.h > $$$$.h && mv $$$$.h $@
+
+dep: inc-dep
+
+clean:
+	rm -f target/*/*.o error.h
+
+include target/amd64-sysv/target.mk
+include target/i386-sysv/target.mk
+include target/qbe_amd64-sysv/target.mk
+include target/qbe_arm64-sysv/target.mk
+include target/z80-scc/target.mk
+include deps.mk
--- /dev/null
+++ b/src/cmd/cc/cc2/cc2.h
@@ -1,0 +1,256 @@
+enum iflags {
+	BBENTRY =    1,        /* basic block entry */
+};
+
+enum tflags {
+	SIGNF   =     1 << 0,  /* Signed type */
+	INTF    =     1 << 1,  /* integer type */
+	FLOATF  =     1 << 2,  /* float type */
+	STRF    =     1 << 3,  /* string */
+	AGGRF   =     1 << 4,  /* aggregate */
+	FUNF    =     1 << 5,  /* function */
+	PARF    =     1 << 6,  /* parameter */
+	INITF   =     1 << 7,  /* initializer flag */
+	ELLIPS  =     1 << 8,  /* vararg function */
+};
+
+enum sclass {
+	SAUTO     = 'A',
+	SREG      = 'R',
+	SLABEL    = 'L',
+	SINDEX    = 'I',
+	STMP      = 'N',
+	SGLOB     = 'G',
+	SEXTRN    = 'X',
+	SPRIV     = 'Y',
+	SLOCAL    = 'T',
+	SMEMB     = 'M',
+	SCONST    = '#',
+	STRING    = '"',
+	SNONE     = 0 /* cc2 relies on SNONE being 0 in nextpc() */
+};
+
+enum types {
+	ELLIPSIS = 'E',
+	INT8     = 'C',
+	INT16    = 'I',
+	INT32    = 'W',
+	INT64    = 'Q',
+	UINT8    = 'K',
+	UINT16   = 'N',
+	UINT32   = 'Z',
+	UINT64   = 'O',
+	POINTER  = 'P',
+	FUNCTION = 'F',
+	VECTOR   = 'V',
+	UNION    = 'U',
+	STRUCT   = 'S',
+	BOOL     = 'B',
+	FLOAT    = 'J',
+	DOUBLE   = 'D',
+	LDOUBLE  = 'H',
+	VOID     = '0'
+};
+
+enum op {
+	/* kind of operand */
+	/* operands */
+	OMEM     = 'M',
+	OTMP     = 'N',
+	OAUTO    = 'A',
+	OREG     = 'R',
+	OCONST   = '#',
+	OSTRING  = '"',
+	OLOAD    = 'D',
+	OLABEL   = 'L',
+	OADD     = '+',
+	OSUB     = '-',
+	OMUL     = '*',
+	OMOD     = '%',
+	ODIV     = '/',
+	OSHL     = 'l',
+	OSHR     = 'r',
+	OLT      = '<',
+	OGT      = '>',
+	OLE      = '[',
+	OGE      = ']',
+	OEQ      = '=',
+	ONE      = '!',
+	OBAND    = '&',
+	OBOR     = '|',
+	OBXOR    = '^',
+	OCPL     = '~',
+	OASSIG   = ':',
+	OSNEG    = '_',
+	OCALL    = 'c',
+	OCALLE   = 'z',
+	OPAR     = 'p',
+	OFIELD   = '.',
+	OCOMMA   = ',',
+	OASK     = '?',
+	OCOLON   = ' ',
+	OADDR    = '\'',
+	OAND     = 'a',
+	OOR      = 'o',
+	ONEG     = 'n',
+	OPTR     = '@',
+	OCAST    = 'g',
+	OINC     = 'i',
+	ODEC     = 'd',
+	OBUILTIN = 'm',
+	/*statements */
+	ONOP     = 'q',
+	OJMP     = 'j',
+	OBRANCH  = 'y',
+	ORET     = 'h',
+	OBLOOP   = 'b',
+	OELOOP   = 'e',
+	OCASE    = 'v',
+	ODEFAULT = 'f',
+	OBSWITCH = 's',
+	OESWITCH = 't',
+	OBFUN    = 'x',
+	OEFUN    = 'k',
+};
+
+enum builtins {
+	BVA_START = 's',
+	BVA_END   = 'e',
+	BVA_ARG   = 'a',
+	BVA_COPY  = 'c',
+};
+
+enum nerrors {
+	EEOFFUN,       /* EOF while parsing function */
+	ENLABEL,       /* label without statement */
+	EIDOVER,       /* identifier overflow */
+	EOUTPAR,       /* out pf params */
+	ESYNTAX,       /* syntax error */
+	ESTACKA,       /* stack unaligned */
+	ESTACKO,       /* stack overflow */
+	ESTACKU,       /* stack underflow */
+	ELNLINE,       /* line too long */
+	ELNBLNE,       /* line without new line */
+	EFERROR,       /* error reading from file:%s */
+	EBADID,        /* incorrect symbol id */
+	EWTACKO,       /* switch stack overflow */
+	EWTACKU,       /* switch stack underflow */
+	ENOSWTC,       /* Out of switch statement */
+	EBBUILT,       /* Unknown builtin */
+	ENUMERR
+};
+
+typedef struct node Node;
+typedef struct type Type;
+typedef struct symbol Symbol;
+typedef struct addr Addr;
+typedef struct inst Inst;
+
+struct type {
+	unsigned long size;
+	unsigned long align;
+	short flags;
+};
+
+struct symbol {
+	Type type;
+	Type rtype;
+	unsigned short id;
+	unsigned short numid;
+	char *name;
+	char kind;
+	union {
+		unsigned long off;
+		Node *stmt;
+		Inst *inst;
+	} u;
+	Symbol *next;
+	Symbol *h_next;
+};
+
+struct node {
+	char op;
+	Type type;
+	char complex;
+	char address;
+	unsigned char flags;
+	union {
+		TUINT i;
+		TFLOAT f;
+		char reg;
+		char *s;
+		Symbol *sym;
+		char subop;
+	} u;
+	Symbol *label;
+	Node *left, *right;
+	Node *next, *prev;
+};
+
+struct addr {
+        char kind;
+        union {
+                char reg;
+                TUINT i;
+                Symbol *sym;
+        } u;
+};
+
+struct inst {
+	unsigned char op;
+	unsigned char flags;
+	Symbol *label;
+	Inst *next, *prev;
+	Addr from1, from2, to;
+};
+
+/* main.c */
+extern void error(unsigned nerror, ...);
+
+/* parse.c */
+extern void parse(void);
+
+/* optm.c */
+extern Node *optm_dep(Node *np), *optm_ind(Node *np);
+
+/* cgen.c */
+extern Node *sethi(Node *np);
+extern Node *cgen(Node *np);
+
+/* peep.c */
+extern void peephole(void);
+
+/* code.c */
+extern void data(Node *np);
+extern void writeout(void), endinit(void), newfun(void);
+extern void code(int op, Node *to, Node *from1, Node *from2);
+extern void defvar(Symbol *), defpar(Symbol *), defglobal(Symbol *);
+extern void setlabel(Symbol *sym), getbblocks(void);
+extern Node *label2node(Node *np, Symbol *sym);
+extern Node *constnode(Node *np, TUINT n, Type *tp);
+extern Symbol *newlabel(void);
+
+/* node.c */
+#define SETCUR  1
+#define KEEPCUR 0
+extern void apply(Node *(*fun)(Node *));
+extern void cleannodes(void);
+extern void delnode(Node *np);
+extern void deltree(Node *np);
+extern void prtree(Node *np), prforest(char *msg);
+extern Node *node(int op);
+extern Node *addstmt(Node *np, int flags);
+extern Node *delstmt(void);
+extern Node *nextstmt(void);
+
+/* symbol.c */
+#define TMPSYM  0
+extern Symbol *getsym(unsigned id);
+extern void popctx(void);
+extern void pushctx(void);
+extern void freesym(Symbol *sym);
+
+/* globals */
+extern Symbol *curfun;
+extern Symbol *locals;
+extern Inst *pc, *prog;
--- /dev/null
+++ b/src/cmd/cc/cc2/code.c
@@ -1,0 +1,132 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/scc.h>
+#include "cc2.h"
+
+Inst *pc, *prog;
+
+static void
+nextpc(void)
+{
+        Inst *new;
+
+        new = xcalloc(1, sizeof(*new)); /* TODO: create an arena */
+
+        if (!pc) {
+                prog = new;
+        } else {
+                new->next = pc->next;
+                pc->next = new;
+        }
+
+	/* SNONE being 0, calloc initialized {from1,from2,to}.kind for us */
+        new->prev = pc;
+        pc = new;
+}
+
+static void
+addr(Node *np, Addr *addr)
+{
+	Symbol *sym;
+
+	switch (np->op) {
+	case OREG:
+		/* TODO:
+		 * At this moment this op is used also for register variables
+		 */
+		addr->kind = SREG;
+		addr->u.reg = np->u.reg;
+		break;
+	case OCONST:
+		addr->kind = SCONST;
+		/* TODO: Add support for more type of constants */
+		addr->u.i = np->u.i;
+		break;
+	case OTMP:
+	case OLABEL:
+	case OAUTO:
+	case OMEM:
+		sym = np->u.sym;
+		addr->kind = sym->kind;
+		addr->u.sym = sym;
+		break;
+	default:
+		abort();
+	}
+}
+
+Symbol *
+newlabel(void)
+{
+	Symbol *sym = getsym(TMPSYM);
+
+	sym->kind = SLABEL;
+	return sym;
+}
+
+Node *
+label2node(Node *np, Symbol *sym)
+{
+	if(!sym)
+		sym = newlabel();
+	if (!np)
+		np = node(OLABEL);
+	np->op = OLABEL;
+	np->u.sym = sym;
+
+	return np;
+}
+
+Node *
+constnode(Node *np, TUINT n, Type *tp)
+{
+	if (!np)
+		np = node(OCONST);
+	np->op = OCONST;
+	np->left = NULL;
+	np->right = NULL;
+	np->type = *tp;
+	np->u.i = n;
+	return np;
+}
+
+void
+setlabel(Symbol *sym)
+{
+	if (!sym)
+		return;
+	code(0, NULL, NULL, NULL);
+	pc->label = sym;
+	sym->u.inst = pc;
+}
+
+void
+code(int op, Node *to, Node *from1, Node *from2)
+{
+	nextpc();
+	if (from1)
+		addr(from1, &pc->from1);
+	if (from2)
+		addr(from2, &pc->from2);
+	if (to)
+		addr(to, &pc->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;
+        }
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/deps.mk
@@ -1,0 +1,61 @@
+#deps
+./code.o: $(INCDIR)/scc/scc/scc.h
+./code.o: ./cc2.h
+./main.o: $(INCDIR)/scc/scc/arg.h
+./main.o: $(INCDIR)/scc/scc/scc.h
+./main.o: ./cc2.h
+./main.o: ./error.h
+./node.o: $(INCDIR)/scc/scc/scc.h
+./node.o: ./cc2.h
+./optm.o: $(INCDIR)/scc/scc/scc.h
+./optm.o: ./cc2.h
+./parser.o: $(INCDIR)/scc/scc/cstd.h
+./parser.o: $(INCDIR)/scc/scc/scc.h
+./parser.o: ./cc2.h
+./peep.o: $(INCDIR)/scc/scc/scc.h
+./peep.o: ./cc2.h
+./symbol.o: $(INCDIR)/scc/scc/scc.h
+./symbol.o: ./cc2.h
+./target/amd64-sysv/cgen.o: $(INCDIR)/scc/scc/scc.h
+./target/amd64-sysv/cgen.o: ./target/amd64-sysv/../../cc2.h
+./target/amd64-sysv/cgen.o: ./target/amd64-sysv/arch.h
+./target/amd64-sysv/code.o: $(INCDIR)/scc/scc/cstd.h
+./target/amd64-sysv/code.o: $(INCDIR)/scc/scc/scc.h
+./target/amd64-sysv/code.o: ./target/amd64-sysv/../../cc2.h
+./target/amd64-sysv/code.o: ./target/amd64-sysv/arch.h
+./target/amd64-sysv/optm.o: $(INCDIR)/scc/scc/scc.h
+./target/amd64-sysv/optm.o: ./target/amd64-sysv/../../cc2.h
+./target/amd64-sysv/types.o: $(INCDIR)/scc/scc/scc.h
+./target/amd64-sysv/types.o: ./target/amd64-sysv/../../cc2.h
+./target/i386-sysv/cgen.o: $(INCDIR)/scc/scc/scc.h
+./target/i386-sysv/cgen.o: ./target/i386-sysv/../../cc2.h
+./target/i386-sysv/cgen.o: ./target/i386-sysv/arch.h
+./target/i386-sysv/code.o: $(INCDIR)/scc/scc/cstd.h
+./target/i386-sysv/code.o: $(INCDIR)/scc/scc/scc.h
+./target/i386-sysv/code.o: ./target/i386-sysv/../../cc2.h
+./target/i386-sysv/code.o: ./target/i386-sysv/arch.h
+./target/i386-sysv/optm.o: $(INCDIR)/scc/scc/scc.h
+./target/i386-sysv/optm.o: ./target/i386-sysv/../../cc2.h
+./target/i386-sysv/types.o: $(INCDIR)/scc/scc/scc.h
+./target/i386-sysv/types.o: ./target/i386-sysv/../../cc2.h
+./target/qbe/cgen.o: $(INCDIR)/scc/scc/cstd.h
+./target/qbe/cgen.o: $(INCDIR)/scc/scc/scc.h
+./target/qbe/cgen.o: ./target/qbe/../../cc2.h
+./target/qbe/cgen.o: ./target/qbe/arch.h
+./target/qbe/code.o: $(INCDIR)/scc/scc/cstd.h
+./target/qbe/code.o: $(INCDIR)/scc/scc/scc.h
+./target/qbe/code.o: ./target/qbe/../../cc2.h
+./target/qbe/code.o: ./target/qbe/arch.h
+./target/qbe/optm.o: $(INCDIR)/scc/scc/scc.h
+./target/qbe/optm.o: ./target/qbe/../../cc2.h
+./target/z80-scc/cgen.o: $(INCDIR)/scc/scc/scc.h
+./target/z80-scc/cgen.o: ./target/z80-scc/../../cc2.h
+./target/z80-scc/cgen.o: ./target/z80-scc/arch.h
+./target/z80-scc/code.o: $(INCDIR)/scc/scc/cstd.h
+./target/z80-scc/code.o: $(INCDIR)/scc/scc/scc.h
+./target/z80-scc/code.o: ./target/z80-scc/../../cc2.h
+./target/z80-scc/code.o: ./target/z80-scc/arch.h
+./target/z80-scc/optm.o: $(INCDIR)/scc/scc/scc.h
+./target/z80-scc/optm.o: ./target/z80-scc/../../cc2.h
+./target/z80-scc/types.o: $(INCDIR)/scc/scc/scc.h
+./target/z80-scc/types.o: ./target/z80-scc/../../cc2.h
--- /dev/null
+++ b/src/cmd/cc/cc2/generror.awk
@@ -1,0 +1,9 @@
+/^enum nerrors \{/     {print "char *errlist[] = {"; inhome = 1}
+
+inhome && /E[A-Z]*, /  {sub(/,/, "", $1)
+                        printf("\t[%s] = \"", $1)
+                        for (i = 3; i <= NF-1; ++i)
+				printf("%s%s", $i, (i == NF-1) ? "\"" : " ")
+			print ","}
+
+inhome && /^}/          {print "};" ; inhome = 0}
--- /dev/null
+++ b/src/cmd/cc/cc2/main.c
@@ -1,0 +1,68 @@
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/arg.h>
+#include <scc/scc.h>
+#include "cc2.h"
+#include "error.h"
+
+char *argv0;
+
+void
+error(unsigned nerror, ...)
+{
+	va_list va;
+	va_start(va, nerror);
+	vfprintf(stderr, errlist[nerror], va);
+	va_end(va);
+	putc('\n', stderr);
+	exit(1);
+}
+
+static int
+moreinput(void)
+{
+	int c;
+
+repeat:
+	if (feof(stdin))
+		return 0;
+	if ((c = getchar()) == '\n' || c == EOF)
+		goto repeat;
+	ungetc(c, stdin);
+	return 1;
+}
+
+static void
+usage(void)
+{
+	fputs("usage: cc2 [irfile]\n", stderr);
+	exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+	ARGBEGIN {
+	default:
+		usage();
+	} ARGEND
+
+	if (argv[0] && !freopen(argv[0], "r", stdin))
+		die("cc2: %s: %s", argv[0], strerror(errno));
+
+	while (moreinput()) {
+		parse();
+		apply(optm_ind);
+		apply(optm_dep);
+		apply(sethi);
+		apply(cgen);
+		getbblocks();  /* TODO: run apply over asm ins too */
+		peephole();
+		writeout();
+	}
+	return 0;
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/node.c
@@ -1,0 +1,141 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/scc.h>
+
+#include "cc2.h"
+
+#define NNODES   32
+
+Node *curstmt;
+Symbol *curfun;
+
+static Alloc *arena;
+
+
+Node *
+node(int op)
+{
+	struct arena *ap;
+	Node *np;
+
+	if (!arena)
+		arena = alloc(sizeof(Node), NNODES);
+	np = memset(new(arena), 0, sizeof(*np));
+	np->op = op;
+
+	return np;
+}
+
+#ifndef NDEBUG
+#include <stdio.h>
+
+static void
+prnode(Node *np)
+{
+	if (np->left)
+		prnode(np->left);
+	if (np->right)
+		prnode(np->right);
+	fprintf(stderr, "\t%c%lu", np->op, np->type.size);
+}
+
+void
+prtree(Node *np)
+{
+	prnode(np);
+	putc('\n', stderr);
+}
+
+void
+prforest(char *msg)
+{
+	Node *np;
+
+	if (!curfun)
+		return;
+
+	fprintf(stderr, "%s {\n", msg);
+	for (np = curfun->u.stmt; np; np = np->next)
+		prtree(np);
+	fputs("}\n", stderr);
+}
+#endif
+
+Node *
+addstmt(Node *np, int flag)
+{
+	if (curstmt)
+		np->next = curstmt->next;
+	np->prev = curstmt;
+
+	if (!curfun->u.stmt)
+		curfun->u.stmt = np;
+	else
+		curstmt->next = np;
+
+	if (flag == SETCUR)
+		curstmt = np;
+
+	return np;
+}
+
+Node *
+delstmt(void)
+{
+	Node *next, *prev;
+
+	next = curstmt->next;
+	prev = curstmt->prev;
+	if (next)
+		next->prev = prev;
+	if (prev)
+		prev->next = next;
+	else
+		curfun->u.stmt = next;
+	deltree(curstmt);
+
+	return curstmt = next;
+}
+
+Node *
+nextstmt(void)
+{
+	return curstmt = curstmt->next;
+}
+
+void
+delnode(Node *np)
+{
+	delete(arena, np);
+}
+
+void
+deltree(Node *np)
+{
+	if (!np)
+		return;
+	deltree(np->left);
+	deltree(np->right);
+	delnode(np);
+}
+
+void
+cleannodes(void)
+{
+	if (arena) {
+		dealloc(arena);
+		arena = NULL;
+	}
+	curstmt = NULL;
+}
+
+void
+apply(Node *(*fun)(Node *))
+{
+	if (!curfun)
+		return;
+	curstmt = curfun->u.stmt;
+	while (curstmt)
+		(*fun)(curstmt) ? nextstmt() : delstmt();
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/optm.c
@@ -1,0 +1,9 @@
+#include <scc/scc.h>
+#include "cc2.h"
+
+Node *
+optm_ind(Node *np)
+{
+	return np;
+}
+
--- /dev/null
+++ b/src/cmd/cc/cc2/parser.c
@@ -1,0 +1,721 @@
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+
+#include "cc2.h"
+
+#define STACKSIZ     50
+
+extern Type int8type, int16type, int32type, int64type,
+            uint8type, uint16type, uint32type, uint64type,
+            float32type, float64type, float80type,
+            booltype,
+            ptrtype,
+            voidtype,
+            arg_type;
+
+Type funetype = {
+	.flags = FUNF | ELLIPS
+};
+
+Type funtype = {
+	.flags = FUNF
+};
+
+union tokenop {
+	void *arg;
+	unsigned op;
+};
+
+struct swtch {
+	int nr;
+	Node *first;
+	Node *last;
+};
+
+static struct swtch swtbl[NR_BLOCK], *swp = swtbl;
+static Symbol *lastfun;
+
+typedef void parsefun(char *, union tokenop);
+static parsefun type, symbol, getname, unary, binary, ternary, call,
+                constant, composed, binit, einit,
+                jump, oreturn, loop, assign,
+                ocase, bswitch, eswitch, builtin;
+
+typedef void evalfun(void);
+static evalfun vardecl, beginfun, endfun, endpars, stmt,
+               array, aggregate, flddecl, labeldcl;
+
+static struct decoc {
+	void (*eval)(void);
+	void (*parse)(char *token, union tokenop);
+	union tokenop u;
+} optbl[] = {      /*  eval     parse           args */
+	['A']   = {  vardecl,  symbol, .u.op  =  SAUTO<<8 | OAUTO},
+	['R']   = {  vardecl,  symbol, .u.op  =   SREG<<8 |  OREG},
+	['G']   = {  vardecl,  symbol, .u.op  =  SGLOB<<8 |  OMEM},
+	['X']   = {  vardecl,  symbol, .u.op  = SEXTRN<<8 |  OMEM},
+	['Y']   = {  vardecl,  symbol, .u.op  =  SPRIV<<8 |  OMEM},
+	['T']   = {  vardecl,  symbol, .u.op  = SLOCAL<<8 |  OMEM},
+	['M']   = {  flddecl,  symbol, .u.op  =  SMEMB<<8 |  OMEM},
+	['L']   = { labeldcl,  symbol, .u.op  = SLABEL<<8 | OLABEL},
+
+	['C']   = {     NULL,    type, .u.arg =    &int8type},
+	['I']   = {     NULL,    type, .u.arg =   &int16type},
+	['W']   = {     NULL,    type, .u.arg =   &int32type},
+	['Q']   = {     NULL,    type, .u.arg =   &int64type},
+	['K']   = {     NULL,    type, .u.arg =   &uint8type},
+	['N']   = {     NULL,    type, .u.arg =  &uint16type},
+	['Z']   = {     NULL,    type, .u.arg =  &uint32type},
+	['O']   = {     NULL,    type, .u.arg =  &uint64type},
+	['J']   = {     NULL,    type, .u.arg = &float32type},
+	['D']   = {     NULL,    type, .u.arg = &float64type},
+	['H']   = {     NULL,    type, .u.arg = &float80type},
+	['0']   = {     NULL,    type, .u.arg =    &voidtype},
+	['B']   = {     NULL,    type, .u.arg =    &booltype},
+	['P']   = {     NULL,    type, .u.arg =     &ptrtype},
+	['E']   = {     NULL,    type, .u.arg =    &funetype},
+	['1']	= {     NULL,    type, .u.arg =    &arg_type},
+
+	['F']   = {     NULL,    type, .u.arg =     &funtype},
+	['V']   = {    array,composed,                     0},
+	['U']   = {aggregate,composed,                     0},
+	['S']   = {aggregate,composed,                     0},
+
+	['"']   = {     NULL, getname,                     0},
+	['{']   = { beginfun,    NULL,                     0},
+	['}']   = {   endfun,    NULL,                     0},
+	['(']   = {     NULL,   binit,                     0},
+	[')']   = {     NULL,   einit,                     0},
+	['\\']  = {  endpars,    NULL,                     0},
+	['\t']  = {     stmt,    NULL,                     0},
+
+	['~']   = {     NULL,   unary, .u.op =          OCPL},
+	['_']   = {     NULL,   unary, .u.op =         OSNEG},
+	['\'']  = {     NULL,   unary, .u.op =         OADDR},
+	['@']   = {     NULL,   unary, .u.op =          OPTR},
+	['g']   = {     NULL,   unary, .u.op =         OCAST},
+	['p']   = {     NULL,   unary, .u.op =          OPAR},
+	['n']   = {     NULL,   unary, .u.op =          ONEG},
+
+	['a']   = {     NULL,  binary, .u.op =          OAND},
+	['o']   = {     NULL,  binary, .u.op =           OOR},
+	['.']   = {     NULL,  binary, .u.op =        OFIELD},
+	['+']   = {     NULL,  binary, .u.op =          OADD},
+	['-']   = {     NULL,  binary, .u.op =          OSUB},
+	['*']   = {     NULL,  binary, .u.op =          OMUL},
+	['%']   = {     NULL,  binary, .u.op =          OMOD},
+	['/']   = {     NULL,  binary, .u.op =          ODIV},
+	['l']   = {     NULL,  binary, .u.op =          OSHL},
+	['r']   = {     NULL,  binary, .u.op =          OSHR},
+	['<']   = {     NULL,  binary, .u.op =           OLT},
+	['>']   = {     NULL,  binary, .u.op =           OGT},
+	['[']   = {     NULL,  binary, .u.op =           OLE},
+	[']']   = {     NULL,  binary, .u.op =           OGE},
+	['=']   = {     NULL,  binary, .u.op =           OEQ},
+	['!']   = {     NULL,  binary, .u.op =           ONE},
+	['&']   = {     NULL,  binary, .u.op =         OBAND},
+	['|']   = {     NULL,  binary, .u.op =          OBOR},
+	['^']   = {     NULL,  binary, .u.op =         OBXOR},
+	[',']   = {     NULL,  binary, .u.op =        OCOMMA},
+	['m']   = {     NULL,  builtin,.u.op =      OBUILTIN},
+
+	[':']   = {     NULL,  assign, .u.op =        OASSIG},
+	['?']   = {     NULL, ternary, .u.op =          OASK},
+	['c']   = {     NULL,    call, .u.op =         OCALL},
+	['z']   = {     NULL,    call, .u.op =        OCALLE},
+
+	['#']   = {     NULL,constant, .u.op =        OCONST},
+
+	['j']   = {     NULL,    jump, .u.op =          OJMP},
+	['y']   = {     NULL,    jump, .u.op =       OBRANCH},
+	['h']   = {     NULL, oreturn, .u.op =          ORET},
+	['i']   = {     NULL,    NULL, .u.op =          OINC},
+	['d']   = {     NULL,    NULL, .u.op =          ODEC},
+
+	['b']   = {     NULL,    loop, .u.op =        OBLOOP},
+	['e']   = {     NULL,    loop, .u.op =        OELOOP},
+
+	['v']   = {     NULL,   ocase, .u.op =         OCASE},
+	['f']   = {     NULL,   ocase, .u.op =      ODEFAULT},
+	['t']   = {     NULL, eswitch, .u.op =      OESWITCH},
+	['s']   = {     NULL, bswitch, .u.op =      OBSWITCH},
+};
+
+static int sclass, inpars, ininit, endf, lineno;
+static void *stack[STACKSIZ], **sp = stack;
+
+static Node *
+push(void *elem)
+{
+	if (sp == &stack[STACKSIZ])
+		error(ESTACKO);
+	return *sp++ = elem;
+}
+
+static void *
+pop(void)
+{
+	if (sp == stack)
+		error(ESTACKU);
+	return *--sp;
+}
+
+static int
+empty(void)
+{
+	return sp == stack;
+}
+
+static void
+type(char *token, union tokenop u)
+{
+	push(u.arg);
+}
+
+static void
+composed(char *token, union tokenop u)
+{
+	Symbol *sym;
+
+	sym = getsym(atoi(token+1));
+	push(&sym->type);
+}
+
+static void
+getname(char *t, union tokenop u)
+{
+	push((*++t) ? xstrdup(t) : NULL);
+}
+
+static void
+symbol(char *token, union tokenop u)
+{
+	Node *np = node(u.op & 0xFF);
+	Symbol *sym = getsym(atoi(token+1));
+
+	sclass = u.op >> 8;
+	np->u.sym = sym;
+	np->type = sym->type;
+	push(np);
+}
+
+static Type *
+gettype(char *token)
+{
+	struct decoc *dp;
+
+	dp = &optbl[*token];
+	if (!dp->parse)
+		error(ESYNTAX);
+	(*dp->parse)(token, dp->u);
+	return pop();
+}
+
+static void
+constant(char *token, union tokenop u)
+{
+	static char letters[] = "0123456789ABCDEF";
+	Node *np;
+	TUINT v;
+	unsigned c;
+
+	++token;
+	if (*token == '"') {
+		++token;
+		np = node(OSTRING);
+		np->type.flags = STRF;
+		np->type.size = strlen(token);
+		np->type.align = int8type.align;
+		np->u.s = xstrdup(token);
+	} else {
+		np = node(OCONST);
+		np->type = *gettype(token++);
+		for (v = 0; c = *token++; v += c) {
+			v <<= 4;
+			c = strchr(letters, c) - letters;
+		}
+		np->u.i = v;
+	}
+	push(np);
+}
+
+static void
+assign(char *token, union tokenop u)
+{
+	int subop;
+	Node *np = node(u.op);
+
+	switch (subop = *++token) {
+	case '+':
+	case '-':
+	case '*':
+	case '%':
+	case '/':
+	case 'l':
+	case 'r':
+	case '&':
+	case '|':
+	case '^':
+	case 'i':
+	case 'd':
+		++token;
+		subop = optbl[subop].u.op;
+		break;
+	default:
+		subop = 0;
+		break;
+	}
+
+	np->u.subop = subop;
+	np->type = *gettype(token);
+	np->right = pop();
+	np->left = pop();
+	push(np);
+}
+
+static void
+ternary(char *token, union tokenop u)
+{
+	Node *ask = node(OASK), *colon = node(OCOLON);
+	Type *tp = gettype(token+1);
+
+	colon->right = pop();
+	colon->left = pop();
+
+	ask->type = *tp;
+	ask->left = pop();
+	ask->right = colon;
+	push(ask);
+}
+
+static void
+eval(char *tok)
+{
+	struct decoc *dp;
+
+	do {
+		dp = &optbl[*tok];
+		if (!dp->parse)
+			break;
+		(*dp->parse)(tok, dp->u);
+	} while (tok = strtok(NULL, "\t\n"));
+}
+
+static int
+nextline(void)
+{
+	static char line[LINESIZ];
+	size_t len;
+	int c;
+	void (*fun)(void);
+
+repeat:
+	++lineno;
+	if (!fgets(line, sizeof(line), stdin))
+		return 0;
+	if ((len = strlen(line)) == 0 || line[0] == '\n')
+		goto repeat;
+	if (line[len-1] != '\n')
+		error(len < sizeof(line)-1 ? ELNBLNE : ELNLINE);
+	line[len-1] = '\0';
+
+	c = *line;
+	eval(strtok(line, "\t\n"));
+	if ((fun = *optbl[c].eval) != NULL)
+		(*fun)();
+	if (sp != stack)
+		error(ESTACKA);
+	return 1;
+}
+
+static void
+oreturn(char *token, union tokenop u)
+{
+	Node *np = node(u.op);
+
+	if (token = strtok(NULL, "\t\n"))
+		eval(token);
+	if (!empty())
+		np->left = pop();
+	push(np);
+}
+
+/*
+ * Move np (which is a OCASE/ODEFAULT/OESWITCH) to be contigous with
+ * the last switch table. It is a bit ugly to touch directly curstmt
+ * here, but moving this function to node.c is worse, because we are
+ * putting knowledge of how the text is parsed into the node
+ * represtation module.
+ */
+static void
+waft(Node *np)
+{
+	Node *lastcase, *next;;
+	struct swtch *cur;
+	extern Node *curstmt;
+
+	if (swp == swtbl)
+		error(EWTACKU);
+
+	cur = swp - 1;
+	lastcase = cur->last;
+	next = lastcase->next;
+
+	np->next = next;
+	np->prev = lastcase;
+
+	if (next)
+		next->prev = np;
+	lastcase->next = np;
+
+	if (curstmt == cur->last)
+		curstmt = np;
+	cur->last = np;
+	cur->nr++;
+}
+
+static void
+bswitch(char *token, union tokenop u)
+{
+	struct swtch *cur;
+	Node *np = node(u.op);
+
+	if (swp == &swtbl[NR_BLOCK])
+		error(EWTACKO);
+	cur = swp++;
+	cur->nr = 0;
+
+	eval(strtok(NULL, "\t\n"));
+	np->left = pop();
+
+	push(cur->first = cur->last = np);
+}
+
+static void
+eswitch(char *token, union tokenop u)
+{
+	struct swtch *cur;
+
+	if (swp == swtbl)
+		error(EWTACKU);
+	jump(token, u);
+	waft(pop());
+	cur = --swp;
+	cur->first->u.i = cur->nr;
+}
+
+static void
+ocase(char *token, union tokenop u)
+{
+	jump(token, u);
+	waft(pop());
+}
+
+static void
+jump(char *token, union tokenop u)
+{
+	Node *aux, *np = node(u.op);
+
+	eval(strtok(NULL, "\t\n"));
+
+	if (u.op == OBRANCH || u.op == OCASE)
+		np->left = pop();
+	aux = pop();
+	np->u.sym = aux->u.sym;
+	delnode(aux);
+	push(np);
+}
+
+static void
+loop(char *token, union tokenop u)
+{
+	push(node(u.op));
+}
+
+static void
+unary(char *token, union tokenop u)
+{
+	Node *np = node(u.op);
+
+	np->type = *gettype(token+1);
+	np->left = pop();
+	np->right = NULL;
+	push(np);
+}
+
+static void
+call(char *token, union tokenop u)
+{
+	Node *np, *par, *fun = node(u.op);
+
+	for (par = NULL;; par = np) {
+		np = pop();
+		if (np->op != OPAR)
+			break;
+		np->right = par;
+	}
+
+	fun->type = *gettype(token+1);
+	fun->left = np;
+	fun->right = par;
+	push(fun);
+}
+
+static void
+builtin(char *token, union tokenop u)
+{
+	Node *np = node(u.op);
+	char *name;
+	unsigned subop, nchilds;
+
+	np->type = *gettype(token+1);
+	name = pop();
+
+	if (!strcmp("__builtin_va_arg", name)) {
+		nchilds = 1;
+		subop = BVA_ARG;
+	} else if (!strcmp("__builtin_va_start", name)) {
+		nchilds = 2;
+		subop = BVA_START;
+	} else if (!strcmp("__builtin_va_end", name)) {
+		nchilds = 1;
+		subop = BVA_END;
+	} else if (!strcmp("__builtin_va_copy", name)) {
+		nchilds = 2;
+		subop = BVA_COPY;
+	} else {
+		error(EBBUILT);;
+	}
+
+	np->u.subop = subop;
+	np->right = (nchilds == 2) ? pop() : NULL;
+	np->left = (nchilds != 0) ? pop() : NULL;
+
+	free(name);
+	push(np);
+}
+
+static void
+binary(char *token, union tokenop u)
+{
+	Node *np = node(u.op);
+
+	np->type = *gettype(token+1);
+	np->right = pop();
+	np->left = pop();
+	push(np);
+}
+
+static void
+binit(char *token, union tokenop u)
+{
+	ininit = 1;
+}
+
+static void
+einit(char *token, union tokenop u)
+{
+	ininit = 0;
+	endinit();
+}
+
+static void
+endpars(void)
+{
+	if (!curfun || !inpars)
+		error(ESYNTAX);
+	inpars = 0;
+}
+
+static void
+aggregate(void)
+{
+	Node *align, *size;
+	char *name;
+	Type *tp;
+	Symbol *sym;
+
+	align = pop();
+	size = pop();
+	name = pop();
+	tp = pop();
+
+	tp->size = size->u.i;
+	tp->align = align->u.i;
+	tp->flags = AGGRF;
+	/*
+	 * type is the first field of Symbol so we can obtain the
+	 * address of the symbol from the address of the type.
+	 * We have to do this because composed returns the pointer
+	 * to the type, but in this function we also need the
+	 * symbol to store the name.
+	 */
+	sym = (Symbol *) tp;
+	sym->name = name;
+
+	delnode(align);
+	delnode(size);
+}
+
+static void
+array(void)
+{
+	Type *tp, *base;
+	Node *size;
+
+	size = pop();
+	base = pop();
+	tp = pop();
+	tp->size = size->u.i * base->size; /* FIXME check for overflow */
+	tp->align = base->align;
+
+	delnode(size);
+}
+
+static void
+decl(Symbol *sym)
+{
+	Type *tp = &sym->type;
+
+	if (tp->flags & FUNF) {
+		lastfun = sym;
+	} else {
+		switch (sym->kind) {
+		case SEXTRN:
+		case SGLOB:
+		case SPRIV:
+		case SLOCAL:
+			defglobal(sym);
+			break;
+		case SAUTO:
+		case SREG:
+			if (!curfun)
+				error(ESYNTAX);
+			((inpars) ? defpar : defvar)(sym);
+			break;
+		default:
+			abort();
+		}
+	}
+}
+
+static void
+vardecl(void)
+{
+	Type *tp, *rp;
+	Node *np;
+	Symbol *sym;
+	char *name;
+
+	name = pop();
+	tp = pop();
+	if (tp->flags & FUNF)
+		rp = pop();
+	np = pop();
+
+	sym = np->u.sym;
+	/*
+	 * We have to free sym->name because in tentative declarations
+	 * we can have multiple declarations of the same symbol, and in
+	 * this case our parser will allocate twice the memory
+	 */
+	free(sym->name);
+	sym->name = name;
+	sym->type = *tp;
+	if (tp->flags & FUNF)
+		sym->rtype = *rp;
+	sym->kind = sclass;
+
+	if (ininit)
+		sym->type.flags |= INITF;
+	decl(sym);
+	delnode(np);
+}
+
+static void
+flddecl(void)
+{
+	Node *off, *np;
+	char *name;
+	Type *tp;
+	Symbol *sym;
+
+	off = pop();
+	name = pop();
+	tp = pop();
+	np = pop();
+
+	sym = np->u.sym;
+	sym->u.off = off->u.i;
+	sym->name = name;
+	sym->type = *tp;
+
+	delnode(np);
+	delnode(off);
+}
+
+static void
+labeldcl(void)
+{
+	Node *np;
+	Symbol *sym;
+
+	np = pop();
+	np->op = ONOP;
+	sym = np->u.sym;
+	sym->kind = SLABEL;
+	sym->u.stmt = np;
+	np->label = sym;
+	addstmt(np, SETCUR);
+}
+
+static void
+stmt(void)
+{
+	Node *np;
+
+	if (empty())
+		return;
+	np = pop();
+	if (ininit) {
+		data(np);
+		deltree(np);
+		return;
+	}
+	addstmt(np, SETCUR);
+}
+
+static void
+beginfun(void)
+{
+	curfun = lastfun;
+	inpars = 1;
+	pushctx();
+	addstmt(node(OBFUN), SETCUR);
+}
+
+static void
+endfun(void)
+{
+	endf = 1;
+	addstmt(node(OEFUN), SETCUR);
+}
+
+void
+parse(void)
+{
+	cleannodes();  /* remove code of previous function */
+	popctx();  /* remove context of previous function */
+	curfun = NULL;
+	endf = 0;
+
+	while (!endf && nextline())
+		;
+	if (ferror(stdin))
+		error(EFERROR, strerror(errno));
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/peep.c
@@ -1,0 +1,7 @@
+#include <scc/scc.h>
+#include "cc2.h"
+
+void
+peephole(void)
+{
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/symbol.c
@@ -1,0 +1,91 @@
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/scc.h>
+
+#include "cc2.h"
+
+#define NR_SYMHASH  64
+
+Symbol *locals;
+
+static Symbol *symtab[NR_SYMHASH], *curlocal;
+static int infunction;
+
+
+void
+freesym(Symbol *sym)
+{
+	free(sym->name);
+	free(sym);
+}
+
+void
+pushctx(void)
+{
+	infunction = 1;
+}
+
+void
+popctx(void)
+{
+	Symbol *sym, *next;
+
+	infunction = 0;
+	for (sym = locals; sym; sym = next) {
+		next = sym->next;
+		/*
+		 * Symbols are inserted in the hash in the inverted
+		 * order they are found in locals and it is impossible
+		 * to have a global over a local, because a local is
+		 * any symbol defined in the body of a function,
+		 * even if it has extern linkage.
+		 * For this reason when we reach a symbol in the
+		 * locals list we know that it is the head of it
+		 * collision list and we can remove it assigning
+		 * it h_next to the hash table position
+		 */
+		if (sym->id != TMPSYM)
+			symtab[sym->id & NR_SYMHASH-1] = sym->h_next;
+		freesym(sym);
+	}
+	curlocal = locals = NULL;
+}
+
+Symbol *
+getsym(unsigned id)
+{
+	Symbol **htab, *sym;
+	static unsigned short num;
+
+	if (id >= USHRT_MAX)
+		error(EBADID);
+
+	if (id != TMPSYM) {
+		htab = &symtab[id & NR_SYMHASH-1];
+		for (sym = *htab; sym; sym = sym->h_next) {
+			if (sym->id == id)
+				return sym;
+		}
+	}
+
+	sym = xcalloc(1, sizeof(*sym));
+	sym->id = id;
+	if (infunction) {
+		if (!locals)
+			locals = sym;
+		if (curlocal)
+			curlocal->next = sym;
+		curlocal = sym;
+	}
+	if (id != TMPSYM) {
+		sym->h_next = *htab;
+		*htab = sym;
+	}
+	if ((sym->numid = ++num) == 0)
+		error(EIDOVER);
+
+	return sym;
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/target/amd64-sysv/cgen.c
@@ -1,0 +1,13 @@
+#include "arch.h"
+#include <scc/scc.h>
+#include "../../cc2.h"
+
+Node *
+cgen(Node *np)
+{
+}
+
+Node *
+sethi(Node *np)
+{
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/target/amd64-sysv/code.c
@@ -1,0 +1,209 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+
+#include "arch.h"
+#include "../../cc2.h"
+
+enum segment {
+	CODESEG,
+	DATASEG,
+	BSSSEG,
+	NOSEG
+};
+
+static int curseg = NOSEG;
+
+static void
+segment(int seg)
+{
+	static char *txt[] = {
+		[CODESEG] = "\t.text\n",
+		[DATASEG] = "\t.data\n",
+		[BSSSEG] = "\t.bss\n",
+	};
+
+	if (seg == curseg)
+		return;
+	fputs(txt[seg], stdout);
+	curseg = seg;
+}
+
+static char *
+symname(Symbol *sym)
+{
+	static char name[INTIDENTSIZ+1];
+
+	if (sym->name) {
+		switch (sym->kind) {
+		case SEXTRN:
+		case SGLOB:
+		case SPRIV:
+			return sym->name;
+		}
+	}
+
+	sprintf(name, ".L%d", sym->numid);
+
+	return name;
+}
+
+static void
+emitconst(Node *np)
+{
+	switch (np->type.size) {
+	case 1:
+		printf("%d", (int) np->u.i & 0xFF);
+		break;
+	case 2:
+		printf("%d", (int) np->u.i & 0xFFFF);
+		break;
+	case 4:
+		printf("%ld", (long) np->u.i & 0xFFFFFFFF);
+		break;
+	case 8:
+		printf("%lld", (long long) np->u.i & 0xFFFFFFFF);
+		break;
+	default:
+		abort();
+	}
+}
+
+static void
+emittree(Node *np)
+{
+	if (!np)
+		return;
+
+	switch (np->op) {
+	case OSTRING:
+		printf("\"%s\"", np->u.s);
+		free(np->u.s);
+		np->u.s = NULL;
+		break;
+	case OCONST:
+		emitconst(np);
+		break;
+	case OADDR:
+		emittree(np->left);
+		break;
+	case OMEM:
+		fputs(symname(np->u.sym), stdout);
+		break;
+	default:
+		emittree(np->left);
+		printf(" %c ", np->op);
+		emittree(np->right);
+		break;
+	}
+}
+static void
+size2asm(Type *tp)
+{
+	char *s;
+
+	if (tp->flags & STRF) {
+		s = "\t.ascii\t";
+	} else {
+		switch (tp->size) {
+		case 1:
+			s = "\t.byte\t";
+			break;
+		case 2:
+			s = "\t.short\t";
+			break;
+		case 4:
+			s = "\t.long\t";
+			break;
+		case 8:
+			s = "\t.quad\t";
+			break;
+		default:
+			s = "\t.space\t%lu,";
+			break;
+		}
+	}
+	printf(s, tp->size);
+}
+
+
+void
+data(Node *np)
+{
+	size2asm(&np->type);
+	emittree(np);
+	putchar('\n');
+}
+
+static void
+label(Symbol *sym)
+{
+	int seg;
+	char *name = symname(sym);
+	Type *tp = &sym->type;
+
+	if (sym->type.flags & FUNF)
+		seg = CODESEG;
+	else if (sym->type.flags & INITF)
+		seg = DATASEG;
+	else
+		seg = BSSSEG;
+	segment(seg);
+
+	switch (sym->kind) {
+	case SEXTRN:
+		printf("\t.extern\t%s\n", name);
+	case SLOCAL:
+		return;
+	case SGLOB:
+		printf("\t.global\t%s\n", name);
+		if (seg == BSSSEG)
+			printf("\t.comm\t%s,%lu\n", name, tp->size);
+		break;
+	}
+	if (sym->type.align != 1)
+		printf("\t.align\t%lu\n", sym->type.align );
+	printf("%s:\n", name);
+}
+
+void
+defglobal(Symbol *sym)
+{
+	label(sym);
+	if (sym->kind == SEXTRN || (sym->type.flags & INITF))
+		return;
+	size2asm(&sym->type);
+	puts("0");
+}
+
+void
+defvar(Symbol *sym)
+{
+}
+
+void
+defpar(Symbol *sym)
+{
+}
+
+void
+newfun(void)
+{
+}
+
+void
+writeout(void)
+{
+}
+
+void
+endinit(void)
+{
+}
+
+void
+getbblocks(void)
+{
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/target/amd64-sysv/optm.c
@@ -1,0 +1,9 @@
+#include <scc/scc.h>
+
+#include "../../cc2.h"
+
+Node *
+optm_dep(Node *np)
+{
+	return np;
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/target/amd64-sysv/target.mk
@@ -1,0 +1,8 @@
+OBJ-amd64-sysv = $(OBJS)  \
+        target/amd64-sysv/cgen.o \
+        target/amd64-sysv/optm.o \
+        target/amd64-sysv/code.o \
+        target/amd64-sysv/types.o
+
+$(LIBEXEC)/cc2-amd64-sysv: $(OBJ-amd64-sysv)
+	$(CC) $(SCC_LDFLAGS) $(OBJ-amd64-sysv) -lscc -o $@
--- /dev/null
+++ b/src/cmd/cc/cc2/target/amd64-sysv/types.c
@@ -1,0 +1,92 @@
+#include <scc/scc.h>
+
+#include "../../cc2.h"
+
+
+Type int8type = {
+	.flags  = SIGNF | INTF,
+	.size   = 1,
+	.align  = 1
+};
+
+Type int16type = {
+	.flags  = SIGNF | INTF,
+	.size   = 2,
+	.align  = 2
+};
+
+Type int32type = {
+	.flags  = SIGNF | INTF,
+	.size   = 4,
+	.align  = 4
+};
+
+Type int64type = {
+	.flags  = SIGNF | INTF,
+	.size   = 8,
+	.align  = 8
+};
+
+Type uint8type = {
+	.flags  = INTF,
+	.size   = 1,
+	.align  = 1
+};
+
+Type uint16type = {
+	.flags  = INTF,
+	.size   = 2,
+	.align  = 2
+};
+
+Type uint32type = {
+	.flags  = INTF,
+	.size   = 4,
+	.align  = 4
+};
+
+Type uint64type = {
+	.flags  = INTF,
+	.size   = 8,
+	.align  = 2
+};
+
+Type ptrtype = {
+	.flags  = INTF,
+	.size   = 8,
+	.align  = 8
+};
+
+Type booltype = {
+	.flags  = INTF,
+	.size   = 1,
+	.align  = 1
+};
+
+Type float32type = {
+	.flags  = FLOATF,
+	.size   = 4,
+	.align  = 4
+};
+
+Type float64type = {
+	.flags  = FLOATF,
+	.size   = 8,
+	.align  = 8
+};
+
+Type float80type = {
+	.flags  = FLOATF,
+	.size   = 16,
+	.align  = 16
+};
+
+Type voidtype = {
+	.size = 0,
+	.align = 0
+};
+
+Type arg_type = {
+	.size = 24,
+	.align = 8
+};
--- /dev/null
+++ b/src/cmd/cc/cc2/target/i386-sysv/cgen.c
@@ -1,0 +1,14 @@
+#include <scc/scc.h>
+
+#include "arch.h"
+#include "../../cc2.h"
+
+Node *
+cgen(Node *np)
+{
+}
+
+Node *
+sethi(Node *np)
+{
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/target/i386-sysv/code.c
@@ -1,0 +1,208 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+
+#include "arch.h"
+#include "../../cc2.h"
+
+enum segment {
+	CODESEG,
+	DATASEG,
+	BSSSEG,
+	NOSEG
+};
+
+static int curseg = NOSEG;
+
+static void
+segment(int seg)
+{
+	static char *txt[] = {
+		[CODESEG] = "\t.text\n",
+		[DATASEG] = "\t.data\n",
+		[BSSSEG] = "\t.bss\n",
+	};
+
+	if (seg == curseg)
+		return;
+	fputs(txt[seg], stdout);
+	curseg = seg;
+}
+
+static char *
+symname(Symbol *sym)
+{
+	static char name[INTIDENTSIZ+1];
+
+	if (sym->name) {
+		switch (sym->kind) {
+		case SEXTRN:
+		case SGLOB:
+		case SPRIV:
+			return sym->name;
+		}
+	}
+
+	sprintf(name, ".L%d", sym->numid);
+
+	return name;
+}
+
+static void
+emitconst(Node *np)
+{
+	switch (np->type.size) {
+	case 1:
+		printf("%d", (int) np->u.i & 0xFF);
+		break;
+	case 2:
+		printf("%d", (int) np->u.i & 0xFFFF);
+		break;
+	case 4:
+		printf("%ld", (long) np->u.i & 0xFFFFFFFF);
+		break;
+	case 8:
+		printf("%lld", (long long) np->u.i & 0xFFFFFFFF);
+		break;
+	default:
+		abort();
+	}
+}
+
+static void
+emittree(Node *np)
+{
+	if (!np)
+		return;
+
+	switch (np->op) {
+	case OSTRING:
+		printf("\"%s\"", np->u.s);
+		free(np->u.s);
+		np->u.s = NULL;
+		break;
+	case OCONST:
+		emitconst(np);
+		break;
+	case OADDR:
+		emittree(np->left);
+		break;
+	case OMEM:
+		fputs(symname(np->u.sym), stdout);
+		break;
+	default:
+		emittree(np->left);
+		printf(" %c ", np->op);
+		emittree(np->right);
+		break;
+	}
+}
+static void
+size2asm(Type *tp)
+{
+	char *s;
+
+	if (tp->flags & STRF) {
+		s = "\t.ascii\t";
+	} else {
+		switch (tp->size) {
+		case 1:
+			s = "\t.byte\t";
+			break;
+		case 2:
+			s = "\t.short\t";
+			break;
+		case 4:
+			s = "\t.long\t";
+			break;
+		case 8:
+			s = "\t.quad\t";
+			break;
+		default:
+			s = "\t.space\t%lu,";
+			break;
+		}
+	}
+	printf(s, tp->size);
+}
+
+void
+data(Node *np)
+{
+	size2asm(&np->type);
+	emittree(np);
+	putchar('\n');
+}
+
+static void
+label(Symbol *sym)
+{
+	int seg;
+	char *name = symname(sym);
+	Type *tp = &sym->type;
+
+	if (sym->type.flags & FUNF)
+		seg = CODESEG;
+	else if (sym->type.flags & INITF)
+		seg = DATASEG;
+	else
+		seg = BSSSEG;
+	segment(seg);
+
+	switch (sym->kind) {
+	case SEXTRN:
+		printf("\t.extern\t%s\n", name);
+	case SLOCAL:
+		return;
+	case SGLOB:
+		printf("\t.global\t%s\n", name);
+		if (seg == BSSSEG)
+			printf("\t.comm\t%s,%lu\n", name, tp->size);
+		break;
+	}
+	if (sym->type.align != 1)
+		printf("\t.align\t%lu\n", sym->type.align );
+	printf("%s:\n", name);
+}
+
+void
+defglobal(Symbol *sym)
+{
+	label(sym);
+	if (sym->kind == SEXTRN || (sym->type.flags & INITF))
+		return;
+	size2asm(&sym->type);
+	puts("0");
+}
+
+void
+defpar(Symbol *sym)
+{
+}
+
+void
+defvar(Symbol *sym)
+{
+}
+
+void
+newfun(void)
+{
+}
+
+void
+writeout(void)
+{
+}
+
+void
+endinit(void)
+{
+}
+
+void
+getbblocks(void)
+{
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/target/i386-sysv/optm.c
@@ -1,0 +1,9 @@
+#include <scc/scc.h>
+
+#include "../../cc2.h"
+
+Node *
+optm_dep(Node *np)
+{
+	return np;
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/target/i386-sysv/target.mk
@@ -1,0 +1,8 @@
+OBJ-i386-sysv = $(OBJS)  \
+        target/i386-sysv/cgen.o \
+        target/i386-sysv/optm.o \
+        target/i386-sysv/code.o \
+        target/i386-sysv/types.o
+
+$(LIBEXEC)/cc2-i386-sysv: $(OBJ-i386-sysv)
+	$(CC) $(SCC_LDFLAGS) $(OBJ-i386-sysv) -lscc -o $@
--- /dev/null
+++ b/src/cmd/cc/cc2/target/i386-sysv/types.c
@@ -1,0 +1,93 @@
+#include <scc/scc.h>
+
+#include "../../cc2.h"
+
+
+Type int8type = {
+	.flags  = SIGNF | INTF,
+	.size   = 1,
+	.align  = 1
+};
+
+Type int16type = {
+	.flags  = SIGNF | INTF,
+	.size   = 2,
+	.align  = 2
+};
+
+Type int32type = {
+	.flags  = SIGNF | INTF,
+	.size   = 4,
+	.align  = 4
+};
+
+Type int64type = {
+	.flags  = SIGNF | INTF,
+	.size   = 8,
+	.align  = 4
+};
+
+Type uint8type = {
+	.flags  = INTF,
+	.size   = 1,
+	.align  = 1
+};
+
+Type uint16type = {
+	.flags  = INTF,
+	.size   = 2,
+	.align  = 2
+};
+
+Type uint32type = {
+	.flags  = INTF,
+	.size   = 4,
+	.align  = 2
+};
+
+Type uint64type = {
+	.flags  = INTF,
+	.size   = 8,
+	.align  = 4
+};
+
+Type ptrtype = {
+	.flags  = INTF,
+	.size   = 4,
+	.align  = 4
+};
+
+Type booltype = {
+	.flags  = INTF,
+	.size   = 1,
+	.align  = 1
+};
+
+Type float32type = {
+	.flags  = FLOATF,
+	.size   = 4,
+	.align  = 4
+};
+
+Type float64type = {
+	.flags  = FLOATF,
+	.size   = 8,
+	.align  = 4
+};
+
+Type float80type = {
+	.flags  = FLOATF,
+	.size   = 12,
+	.align  =  4
+};
+
+Type voidtype = {
+	.size = 0,
+	.align = 0
+};
+
+/* this type is not used in this architecture */
+Type arg_type = {
+        .size = 0,
+        .align = 0
+};
--- /dev/null
+++ b/src/cmd/cc/cc2/target/qbe/arch.h
@@ -1,0 +1,135 @@
+enum asmop {
+	ASNOP = 0,
+	ASSTB,
+	ASSTH,
+	ASSTW,
+	ASSTL,
+	ASSTM,
+	ASSTS,
+	ASSTD,
+
+	ASLDSB,
+	ASLDUB,
+	ASLDSH,
+	ASLDUH,
+	ASLDSW,
+	ASLDUW,
+	ASLDL,
+	ASLDS,
+	ASLDD,
+
+	ASADDW,
+	ASSUBW,
+	ASMULW,
+	ASMODW,
+	ASUMODW,
+	ASDIVW,
+	ASUDIVW,
+	ASSHLW,
+	ASSHRW,
+	ASUSHRW,
+	ASLTW,
+	ASULTW,
+	ASGTW,
+	ASUGTW,
+	ASLEW,
+	ASULEW,
+	ASGEW,
+	ASUGEW,
+	ASEQW,
+	ASNEW,
+	ASBANDW,
+	ASBORW,
+	ASBXORW,
+
+	ASADDL,
+	ASSUBL,
+	ASMULL,
+	ASMODL,
+	ASUMODL,
+	ASDIVL,
+	ASUDIVL,
+	ASSHLL,
+	ASSHRL,
+	ASUSHRL,
+	ASLTL,
+	ASULTL,
+	ASGTL,
+	ASUGTL,
+	ASLEL,
+	ASULEL,
+	ASGEL,
+	ASUGEL,
+	ASEQL,
+	ASNEL,
+	ASBANDL,
+	ASBORL,
+	ASBXORL,
+
+	ASADDS,
+	ASSUBS,
+	ASMULS,
+	ASDIVS,
+	ASLTS,
+	ASGTS,
+	ASLES,
+	ASGES,
+	ASEQS,
+	ASNES,
+
+	ASADDD,
+	ASSUBD,
+	ASMULD,
+	ASDIVD,
+	ASLTD,
+	ASGTD,
+	ASLED,
+	ASGED,
+	ASEQD,
+	ASNED,
+
+	ASEXTBW,
+	ASUEXTBW,
+	ASEXTBL,
+	ASUEXTBL,
+	ASEXTHW,
+	ASUEXTHW,
+	ASEXTHL,
+	ASUEXTHL,
+	ASEXTWL,
+	ASUEXTWL,
+
+	ASSTOL,
+	ASSTOW,
+	ASDTOL,
+	ASDTOW,
+
+	ASSWTOD,
+	ASSWTOS,
+	ASSLTOD,
+	ASSLTOS,
+
+	ASEXTS,
+	ASTRUNCD,
+
+	ASJMP,
+	ASBRANCH,
+	ASRET,
+	ASCALL,
+	ASCALLE,
+	ASCALLEX,
+	ASPAR,
+	ASPARE,
+	ASALLOC,
+	ASFORM,
+
+	ASCOPYB,
+	ASCOPYH,
+	ASCOPYW,
+	ASCOPYL,
+	ASCOPYS,
+	ASCOPYD,
+
+	ASVSTAR,
+	ASVARG,
+};
--- /dev/null
+++ b/src/cmd/cc/cc2/target/qbe/cgen.c
@@ -1,0 +1,727 @@
+#include <assert.h>
+#include <stdlib.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+
+#include "arch.h"
+#include "../../cc2.h"
+
+enum sflags {
+	ISTMP  = 1,
+	ISCONS = 2
+};
+
+static char opasmw[] = {
+	[OADD] = ASADDW,
+	[OSUB] = ASSUBW,
+	[OMUL] = ASMULW,
+	[OMOD] = ASMODW,
+	[ODIV] = ASDIVW,
+	[OSHL] = ASSHLW,
+	[OSHR] = ASSHRW,
+	[OLT] = ASLTW,
+	[OGT] = ASGTW,
+	[OLE] = ASLEW,
+	[OGE] = ASGEW,
+	[OEQ] = ASEQW,
+	[ONE] = ASNEW,
+	[OBAND] = ASBANDW,
+	[OBOR] = ASBORW,
+	[OBXOR] = ASBXORW,
+};
+
+static char opasml[] = {
+	[OADD] = ASADDL,
+	[OSUB] = ASSUBL,
+	[OMUL] = ASMULL,
+	[OMOD] = ASMODL,
+	[ODIV] = ASDIVL,
+	[OSHL] = ASSHLL,
+	[OSHR] = ASSHRL,
+	[OLT] = ASLTL,
+	[OGT] = ASGTL,
+	[OLE] = ASLEL,
+	[OGE] = ASGEL,
+	[OEQ] = ASEQL,
+	[ONE] = ASNEL,
+	[OBAND] = ASBANDL,
+	[OBOR] = ASBORL,
+	[OBXOR] = ASBXORL,
+};
+
+static char opasms[] = {
+	[OADD] = ASADDS,
+	[OSUB] = ASSUBS,
+	[OMUL] = ASMULS,
+	[ODIV] = ASDIVS,
+	[OLT] = ASLTS,
+	[OGT] = ASGTS,
+	[OLE] = ASLES,
+	[OGE] = ASGES,
+	[OEQ] = ASEQS,
+	[ONE] = ASNES,
+};
+static char opasmd[] = {
+	[OADD] = ASADDD,
+	[OSUB] = ASSUBD,
+	[OMUL] = ASMULD,
+	[ODIV] = ASDIVD,
+	[OLT] = ASLTD,
+	[OGT] = ASGTD,
+	[OLE] = ASLED,
+	[OGE] = ASGED,
+	[OEQ] = ASEQD,
+	[ONE] = ASNED,
+};
+
+extern Type int32type, uint32type, ptrtype;
+
+static Node *
+tmpnode(Node *np, Type *tp)
+{
+	char flags;
+	Symbol *sym;
+
+	if (!np)
+		np = node(OTMP);
+	sym = getsym(TMPSYM);
+	sym->type = np->type = *tp;
+	flags = tp->flags & ~(PARF|INITF);
+	sym->type.flags = np->type.flags = flags;
+	sym->kind = STMP;
+	np->left = np->right = NULL;
+	np->u.sym = sym;
+	np->op = OTMP;
+	np->flags |= ISTMP;
+	return np;
+}
+
+static Node *
+load(Type *tp, Node *np, Node *new)
+{
+	int op;
+	int flags = tp->flags;
+
+	if (flags & (AGGRF|FUNF)) {
+		*new = *np;
+		return new;
+	}
+	switch (tp->size) {
+	case 1:
+		op = ASLDSB;
+		break;
+	case 2:
+		op = ASLDSH;
+		break;
+	case 4:
+		op = (flags & FLOATF) ? ASLDS : ASLDSW;
+		break;
+	case 8:
+		op = (flags & FLOATF) ? ASLDD : ASLDL;
+		break;
+	default:
+		abort();
+	}
+	/*
+	 * unsigned version of operations are always +1 the
+	 * signed version
+	 */
+	if ((flags & (INTF|SIGNF)) == INTF && tp->size < 8)
+		++op;
+
+	code(op, tmpnode(new, tp), np, NULL);
+
+	return new;
+}
+
+static Node *rhs(Node *np, Node *new);
+
+static Node *
+cast(Type *td, Node *ns, Node *nd)
+{
+	Type *ts;
+	Node aux1, aux2;
+	int op, d_isint, s_isint;
+
+	ts = &ns->type;
+	d_isint = (td->flags & INTF) != 0;
+	s_isint = (ts->flags & INTF) != 0;
+
+	if (d_isint && s_isint) {
+		if (td->size <= ts->size) {
+			*nd = *ns;
+			return nd;
+		}
+		assert(td->size == 4 || td->size == 8);
+		switch (ts->size) {
+		case 1:
+			op = (td->size == 4) ? ASEXTBW : ASEXTBL;
+			break;
+		case 2:
+			op = (td->size == 4) ? ASEXTHW : ASEXTHL;
+			break;
+		case 4:
+			op = ASEXTWL;
+			break;
+		default:
+			abort();
+		}
+		/*
+		 * unsigned version of operations are always +1 the
+		 * signed version
+		 */
+		op += (ts->flags & SIGNF) == 0;
+	} else if (d_isint) {
+		/* conversion from float to int */
+		switch (ts->size) {
+		case 4:
+			op = (td->size == 8) ? ASSTOL : ASSTOW;
+			break;
+		case 8:
+			op = (td->size == 8) ? ASDTOL : ASDTOW;
+			break;
+		default:
+			abort();
+		}
+		/* TODO: Add signess */
+	} else if (s_isint) {
+		/* conversion from int to float */
+		switch (ts->size) {
+		case 1:
+		case 2:
+			ts = (ts->flags&SIGNF) ? &int32type : &uint32type;
+			ns = cast(ts, ns, tmpnode(&aux2, ts));
+		case 4:
+			op = (td->size == 8) ? ASSWTOD : ASSWTOS;
+			break;
+		case 8:
+			op = (td->size == 8) ? ASSLTOD : ASSLTOS;
+			break;
+		default:
+			abort();
+		}
+		/* TODO: Add signess */
+	} else {
+		/* conversion from float to float */
+		op = (td->size == 4) ? ASEXTS : ASTRUNCD;
+	}
+
+	code(op, tmpnode(nd, td), ns, NULL);
+	return nd;
+}
+
+static Node *
+call(Node *np, Node *fun, Node *ret)
+{
+	int n, op;
+	Type *tp;
+	Node aux, **q, *p, *pars[NR_FUNPARAM];
+
+	for (n = 0, p = np->right; p; p = p->right)
+		pars[n++] = rhs(p->left, node(OTMP));
+
+	tp = &np->type;
+	code(ASCALL, tmpnode(ret, tp), fun, NULL);
+
+	for (q = pars; q < &pars[n]; ++q) {
+		op = (q == &pars[n-1]) ? ASPARE : ASPAR;
+		tmpnode(&aux, &(*q)->type);
+		code(op, NULL, *q, &aux);
+	}
+	code((np->op == OCALL) ? ASCALLE : ASCALLEX, NULL, NULL, NULL);
+
+	return ret;
+}
+
+static Node *
+assign(Type *tp, Node *to, Node *from)
+{
+	int op;
+
+	switch (tp->size) {
+	case 1:
+		op = ASSTB;
+		break;
+	case 2:
+		op = ASSTH;
+		break;
+	case 4:
+		op = (tp->flags & FLOATF) ? ASSTS : ASSTW;
+		break;
+	case 8:
+		op = (tp->flags & FLOATF) ? ASSTD : ASSTL;
+		break;
+	default:
+		op = ASSTM;
+		break;
+	}
+	code(op, to, from, NULL);
+	return from;
+}
+
+static Node *
+copy(Type *tp, Node *to, Node *from)
+{
+	int op;
+
+	switch (tp->size) {
+	case 1:
+		op = ASCOPYB;
+		break;
+	case 2:
+		op = ASCOPYH;
+		break;
+	case 4:
+		op = (tp->flags & FLOATF) ? ASCOPYS : ASCOPYW;
+		break;
+	case 8:
+		op = (tp->flags & FLOATF) ? ASCOPYD : ASCOPYL;
+		break;
+	default:
+		/* TODO: Need to handle the general case */
+		abort();
+	}
+	code(op, to, from, NULL);
+	return from;
+}
+
+/* TODO: Do field() transformation in sethi */
+
+static Node *
+field(Node *np, Node *ret, int islhs)
+{
+	Node base, node, off, add, *addr;
+	TUINT offset = np->right->u.sym->u.off;
+
+	addr = rhs(np->left, &base);
+
+	if (offset != 0) {
+		node.op = OADD;
+		node.type = ptrtype;
+		node.left = addr;
+		node.right = constnode(&off, offset, &ptrtype);
+		addr = rhs(&node, &add);
+	}
+
+	if (islhs)
+		*ret = *addr;
+	else
+		load(&np->type, addr, ret);
+
+	return ret;
+}
+
+static Node *
+lhs(Node *np, Node *new)
+{
+	switch (np->op) {
+	case OMEM:
+	case OAUTO:
+		*new = *np;
+		return new;
+	case OPTR:
+		return rhs(np->left, new);
+	case OFIELD:
+		return field(np, new, 1);
+	default:
+		abort();
+	}
+}
+
+static void
+bool(Node *np, Symbol *true, Symbol *false)
+{
+	Node *l = np->left, *r = np->right;
+	Node ret, ifyes, ifno;
+	Symbol *label;
+
+	switch (np->op) {
+	case ONEG:
+		bool(l, false, true);
+		break;
+	case OAND:
+		label = newlabel();
+		bool(l, label, false);
+		setlabel(label);
+		bool(r, true, false);
+		break;
+	case OOR:
+		label = newlabel();
+		bool(l, true, label);
+		setlabel(label);
+		bool(r, true, false);
+		break;
+	default:
+		label2node(&ifyes, true);
+		label2node(&ifno, false);
+		code(ASBRANCH, rhs(np, &ret), &ifyes, &ifno);
+		break;
+	}
+}
+
+static Node *
+ternary(Node *np, Node *ret)
+{
+	Node ifyes, ifno, phi, *colon, aux1, aux2, aux3;
+
+	tmpnode(ret, &np->type);
+	label2node(&ifyes, NULL);
+	label2node(&ifno, NULL);
+	label2node(&phi, NULL);
+
+	colon = np->right;
+	code(ASBRANCH, rhs(np->left, &aux1), &ifyes, &ifno);
+
+	setlabel(ifyes.u.sym);
+	copy(&ret->type, ret, rhs(colon->left, &aux2));
+	code(ASJMP, NULL, &phi, NULL);
+
+	setlabel(ifno.u.sym);
+	copy(&ret->type, ret, rhs(colon->right, &aux3));
+	setlabel(phi.u.sym);
+
+	return ret;
+}
+
+static Node *
+function(void)
+{
+	Node aux;
+	Symbol *p;
+
+	/* allocate stack space for parameters */
+	for (p = locals; p && (p->type.flags & PARF) != 0; p = p->next)
+		code(ASALLOC, label2node(&aux, p), NULL, NULL);
+
+	/* allocate stack space for local variables) */
+	for ( ; p && p->id != TMPSYM; p = p->next) {
+		if (p->kind != SAUTO)
+			continue;
+		code(ASALLOC, label2node(&aux, p), NULL, NULL);
+	}
+	/* store formal parameters in parameters */
+	for (p = locals; p; p = p->next) {
+		if ((p->type.flags & PARF) == 0)
+			break;
+		code(ASFORM, label2node(&aux, p), NULL, NULL);
+	}
+	return NULL;
+}
+
+static void
+swtch_if(Node *idx)
+{
+	Node aux1, aux2, *np;
+	Symbol *deflabel = NULL;
+
+	for (;;) {
+		np = delstmt();
+		setlabel(np->label);
+
+		switch (np->op) {
+		case OESWITCH:
+			if (!deflabel)
+				deflabel = np->u.sym;
+			aux1.op = OJMP;
+			aux1.label = NULL;
+			aux1.u.sym = deflabel;
+			cgen(&aux1);
+			return;
+		case OCASE:
+			aux1 = *np;
+			aux1.op = OBRANCH;
+			aux1.label = NULL;
+			aux1.left = &aux2;
+
+			aux2.op = OEQ;
+			aux2.type = idx->type;
+			aux2.left = np->left;
+			aux2.right = idx;
+
+			cgen(&aux1);
+			break;
+		case ODEFAULT:
+			deflabel = np->u.sym;
+			break;
+		default:
+			abort();
+		}
+	}
+}
+
+static Node *
+rhs(Node *np, Node *ret)
+{
+	Node aux1, aux2, *phi, *l = np->left, *r = np->right;
+	Type *tp;
+	int off, op;
+	char *tbl;
+	Symbol *true, *false;
+
+	tp = &np->type;
+
+	switch (np->op) {
+	case OBFUN:
+		return function();
+	case ONOP:
+	case OBLOOP:
+	case OELOOP:
+	case OEFUN:
+		return NULL;
+	case OTMP:
+	case OCONST:
+		*ret = *np;
+		return np;
+	case OMEM:
+	case OAUTO:
+		return load(tp, np, ret);
+	case ONEG:
+	case OAND:
+	case OOR:
+		true = newlabel();
+		false = newlabel();
+		phi = label2node(&aux1, NULL);
+		tmpnode(ret, &int32type);
+
+		bool(np, true, false);
+
+		setlabel(true);
+		code(ASCOPYW, ret, constnode(&aux2, 1, &int32type), NULL);
+		code(ASJMP, NULL, phi, NULL);
+
+		setlabel(false);
+		code(ASCOPYW, ret, constnode(&aux2, 0, &int32type), NULL);
+
+		setlabel(phi->u.sym);
+		return ret;
+        case OMOD:
+        case OSHR:
+		assert(tp->flags & INTF);
+        case ODIV:
+        case OLT:
+        case OGT:
+        case OLE:
+        case OGE:
+                /*
+                 * unsigned version of operations are always +1 the
+                 * signed version
+                 */
+                off = (tp->flags & SIGNF) == 0;
+                goto binary;
+        case OSHL:
+        case OBAND:
+        case OBOR:
+        case OBXOR:
+		assert(tp->flags & INTF);
+        case OADD:
+        case OSUB:
+        case OMUL:
+        case OEQ:
+        case ONE:
+                off = 0;
+        binary:
+		if (l->complex >= r->complex) {
+			rhs(l, &aux1);
+			rhs(r, &aux2);
+		} else {
+			rhs(r, &aux2);
+			rhs(l, &aux1);
+		}
+                switch (tp->size) {
+                case 4:
+                        tbl = (tp->flags & FLOATF) ? opasms : opasmw;
+                        break;
+                case 8:
+                        tbl = (tp->flags & FLOATF) ? opasmd : opasml;
+                        break;
+                default:
+                        abort();
+                }
+                op = tbl[np->op] + off;
+		tmpnode(ret, tp);
+                code(op, ret, &aux1, &aux2);
+                return ret;
+	case OCALL:
+	case OCALLE:
+		if (l->op == OPTR)
+			l = rhs(l, &aux1);
+		return call(np, l, ret);
+	case OCAST:
+		return cast(tp, rhs(l, &aux1), ret);
+	case OASSIG:
+		/* TODO: Do this transformations in sethi */
+		switch (np->u.subop) {
+		case OINC:
+			op = OADD;
+			goto post_oper;
+		case ODEC:
+			op = OSUB;
+		post_oper:
+			aux1.op = op;
+			aux1.left = rhs(l, ret);
+			aux1.right = r;
+			aux1.type = np->type;
+			rhs(&aux1, &aux2);
+			lhs(l, &aux1);
+			assign(tp, &aux1, &aux2);
+			break;
+		default:
+			aux2.type = np->type;
+			aux2.op = np->u.subop;
+			aux2.right = np->right;
+			aux2.left = np->left;
+			r = rhs(&aux2, &aux1);
+			Node aux3;
+			if (l->op == OCAST) {
+				aux3.type = l->left->type;
+				aux3.op = OCAST;
+				aux3.left = r;
+				aux3.right = NULL;
+				r = &aux3;
+				l = l->left;
+			}
+		case 0:
+			/* TODO: see what is the most difficult */
+			lhs(l, &aux2);
+			rhs(r, ret);
+			return assign(tp, &aux2, ret);
+		}
+		return ret;
+	case OASK:
+		return ternary(np, ret);
+	case OCOMMA:
+		rhs(l, &aux1);
+		return rhs(r, ret);
+	case OPTR:
+		return load(tp, rhs(l, &aux1), ret);
+	case OADDR:
+		lhs(l, ret);
+		ret->type = *tp;
+		return ret;
+	case OFIELD:
+		return field(np, ret, 0);
+	case OBUILTIN:
+		switch (np->u.subop) {
+		case BVA_START:
+			l = rhs(l, &aux1);
+			code(ASVSTAR, NULL, l, NULL);
+			return NULL;
+		case BVA_END:
+			return NULL;
+		case BVA_ARG:
+			l = rhs(l, &aux1);
+			code(ASVARG, tmpnode(ret, tp), l, NULL);
+			return ret;
+		case BVA_COPY:
+			/* TODO */
+		default:
+			abort();
+		}
+	default:
+		abort();
+	}
+	abort();
+}
+
+Node *
+cgen(Node *np)
+{
+	Node aux, *p, *next;
+
+	setlabel(np->label);
+	switch (np->op) {
+	case OJMP:
+		label2node(&aux, np->u.sym);
+		code(ASJMP, NULL, &aux, NULL);
+		break;
+	case OBRANCH:
+		next = np->next;
+		if (!next->label)
+			next->label = newlabel();
+		bool(np->left, np->u.sym, next->label);
+		break;
+	case ORET:
+		p = (np->left) ? rhs(np->left, &aux) : NULL;
+		code(ASRET, NULL, p, NULL);
+		break;
+	case OBSWITCH:
+		p = rhs(np->left, &aux);
+		swtch_if(p);
+		break;
+	default:
+		rhs(np, &aux);
+		break;
+	}
+	return 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
+ *     REG => 11           reg
+ *     STATIC => 11        (value)
+ *     CONST => 11         $value
+ * These values of addressability are not used in the code generation.
+ * They are only used to calculate the Sethi-Ullman numbers. Since
+ * QBE is AMD64 targered we could do a better job there, and try to
+ * detect some of the complex addressing modes of these processors.
+ */
+Node *
+sethi(Node *np)
+{
+	Node *lp, *rp;
+
+	if (!np)
+		return np;
+
+	np->complex = 0;
+	np->address = 0;
+	lp = np->left;
+	rp = np->right;
+
+	switch (np->op) {
+	case OAUTO:
+	case OREG:
+	case OMEM:
+	case OCONST:
+		np->address = 11;
+		break;
+	case OCPL:
+		assert(np->type.flags & INTF);
+		np->op = OBXOR;
+		rp = constnode(NULL, ~(TUINT) 0, &np->type);
+		goto binary;
+	case OSNEG:
+		np->op = OSUB;
+		rp = lp;
+		lp = constnode(NULL, 0, &np->type);
+		if ((np->type.flags & INTF) == 0)
+			lp->u.f = 0.0;
+	default:
+	binary:
+		lp = sethi(lp);
+		rp = sethi(rp);
+		break;
+	}
+	np->left = lp;
+	np->right = rp;
+
+	if (np->address > 10)
+		return np;
+	if (lp)
+		np->complex = lp->complex;
+	if (rp) {
+		int 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;
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/target/qbe/code.c
@@ -1,0 +1,567 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+
+#include "arch.h"
+#include "../../cc2.h"
+
+#define ADDR_LEN (INTIDENTSIZ+64)
+
+static void binary(void), unary(void), store(void), jmp(void), ret(void),
+            branch(void), call(void), ecall(void), param(void),
+            asalloc(void), form2local(void), ldir(void), vastart(void),
+            vaarg(void);
+
+static struct opdata {
+	void (*fun)(void);
+	char *txt;
+	char letter;
+} optbl [] = {
+	[ASLDSB]  =  {.fun = unary,  .txt = "loadsb", .letter = 'w'},
+	[ASLDUB]  =  {.fun = unary,  .txt = "loadub", .letter = 'w'},
+	[ASLDSH]  =  {.fun = unary,  .txt = "loadsh", .letter = 'w'},
+	[ASLDUH]  =  {.fun = unary,  .txt = "loaduh", .letter = 'w'},
+	[ASLDSW]  =  {.fun = unary,  .txt = "loadsw", .letter = 'w'},
+	[ASLDUW]  =  {.fun = unary,  .txt = "loaduw", .letter = 'w'},
+	[ASLDL]   =  {.fun = unary,  .txt = "loadl", .letter = 'l'},
+	[ASLDS]   =  {.fun = unary,  .txt = "loads", .letter = 's'},
+	[ASLDD]   =  {.fun = unary,  .txt = "loadd", .letter = 'd'},
+
+	[ASCOPYB] =  {.fun = unary,  .txt = "copy", .letter = 'b'},
+	[ASCOPYH] =  {.fun = unary,  .txt = "copy", .letter = 'h'},
+	[ASCOPYW] =  {.fun = unary,  .txt = "copy", .letter = 'w'},
+	[ASCOPYL] =  {.fun = unary,  .txt = "copy", .letter = 'l'},
+	[ASCOPYS] =  {.fun = unary,  .txt = "copy", .letter = 's'},
+	[ASCOPYD] =  {.fun = unary,  .txt = "copy", .letter = 'd'},
+
+	[ASSTB]   =  {.fun = store,  .txt = "store", .letter = 'b'},
+	[ASSTH]   =  {.fun = store,  .txt = "store", .letter = 'h'},
+	[ASSTW]   =  {.fun = store,  .txt = "store", .letter = 'w'},
+	[ASSTL]   =  {.fun = store,  .txt = "store", .letter = 'l'},
+	[ASSTM]   =  {.fun = ldir},
+	[ASSTS]   =  {.fun = store,  .txt = "store", .letter = 's'},
+	[ASSTD]   =  {.fun = store,  .txt = "store", .letter = 'd'},
+
+	[ASADDW]  =  {.fun = binary, .txt = "add", .letter = 'w'},
+	[ASSUBW]  =  {.fun = binary, .txt = "sub", .letter = 'w'},
+	[ASMULW]  =  {.fun = binary, .txt = "mul", .letter = 'w'},
+	[ASMODW]  =  {.fun = binary, .txt = "rem", .letter = 'w'},
+	[ASUMODW] =  {.fun = binary, .txt = "urem", .letter = 'w'},
+	[ASDIVW]  =  {.fun = binary, .txt = "div", .letter = 'w'},
+	[ASUDIVW] =  {.fun = binary, .txt = "udiv", .letter = 'w'},
+	[ASSHLW]  =  {.fun = binary, .txt = "shl", .letter = 'w'},
+	[ASSHRW]  =  {.fun = binary, .txt = "sar", .letter = 'w'},
+	[ASUSHRW] =  {.fun = binary, .txt = "shr", .letter = 'w'},
+	[ASLTW]   =  {.fun = binary, .txt = "csltw", .letter = 'w'},
+	[ASULTW]  =  {.fun = binary, .txt = "cultw", .letter = 'w'},
+	[ASGTW]   =  {.fun = binary, .txt = "csgtw", .letter = 'w'},
+	[ASUGTW]  =  {.fun = binary, .txt = "cugtw", .letter = 'w'},
+	[ASLEW]   =  {.fun = binary, .txt = "cslew", .letter = 'w'},
+	[ASULEW]  =  {.fun = binary, .txt = "culew", .letter = 'w'},
+	[ASGEW]   =  {.fun = binary, .txt = "csgew", .letter = 'w'},
+	[ASUGEW]  =  {.fun = binary, .txt = "cugew", .letter = 'w'},
+	[ASEQW]   =  {.fun = binary, .txt = "ceqw", .letter = 'w'},
+	[ASNEW]   =  {.fun = binary, .txt = "cnew", .letter = 'w'},
+	[ASBANDW] =  {.fun = binary, .txt = "and", .letter = 'w'},
+	[ASBORW]  =  {.fun = binary, .txt = "or", .letter = 'w'},
+	[ASBXORW] =  {.fun = binary, .txt = "xor", .letter = 'w'},
+
+	[ASADDL]  =  {.fun = binary, .txt = "add", .letter = 'l'},
+	[ASSUBL]  =  {.fun = binary, .txt = "sub", .letter = 'l'},
+	[ASMULL]  =  {.fun = binary, .txt = "mul", .letter = 'l'},
+	[ASMODL]  =  {.fun = binary, .txt = "rem", .letter = 'l'},
+	[ASUMODL] =  {.fun = binary, .txt = "urem", .letter = 'l'},
+	[ASDIVL]  =  {.fun = binary, .txt = "div", .letter = 'l'},
+	[ASUDIVL] =  {.fun = binary, .txt = "udiv", .letter = 'l'},
+	[ASSHLL]  =  {.fun = binary, .txt = "shl", .letter = 'l'},
+	[ASSHRL]  =  {.fun = binary, .txt = "sar", .letter = 'l'},
+	[ASUSHRL] =  {.fun = binary, .txt = "shr", .letter = 'l'},
+	[ASLTL]   =  {.fun = binary, .txt = "csltl", .letter = 'w'},
+	[ASULTL]  =  {.fun = binary, .txt = "cultl", .letter = 'w'},
+	[ASGTL]   =  {.fun = binary, .txt = "csgtl", .letter = 'w'},
+	[ASUGTL]  =  {.fun = binary, .txt = "cugtl", .letter = 'w'},
+	[ASLEL]   =  {.fun = binary, .txt = "cslel", .letter = 'w'},
+	[ASULEL]  =  {.fun = binary, .txt = "culel", .letter = 'w'},
+	[ASGEL]   =  {.fun = binary, .txt = "csgel", .letter = 'w'},
+	[ASUGEL]  =  {.fun = binary, .txt = "cugel", .letter = 'w'},
+	[ASEQL]   =  {.fun = binary, .txt = "ceql", .letter = 'w'},
+	[ASNEL]   =  {.fun = binary, .txt = "cnel", .letter = 'w'},
+	[ASBANDL] =  {.fun = binary, .txt = "and", .letter = 'l'},
+	[ASBORL]  =  {.fun = binary, .txt = "or", .letter = 'l'},
+	[ASBXORL] =  {.fun = binary, .txt = "xor", .letter = 'l'},
+
+	[ASADDS]  =  {.fun = binary, .txt = "add", .letter = 's'},
+	[ASSUBS]  =  {.fun = binary, .txt = "sub", .letter = 's'},
+	[ASMULS]  =  {.fun = binary, .txt = "mul", .letter = 's'},
+	[ASDIVS]  =  {.fun = binary, .txt = "div", .letter = 's'},
+	[ASLTS]   =  {.fun = binary, .txt = "clts", .letter = 'w'},
+	[ASGTS]   =  {.fun = binary, .txt = "cgts", .letter = 'w'},
+	[ASLES]   =  {.fun = binary, .txt = "cles", .letter = 'w'},
+	[ASGES]   =  {.fun = binary, .txt = "cges", .letter = 'w'},
+	[ASEQS]   =  {.fun = binary, .txt = "ceqs", .letter = 'w'},
+	[ASNES]   =  {.fun = binary, .txt = "cnes", .letter = 'w'},
+
+	[ASADDD]  =  {.fun = binary, .txt = "add", .letter = 'd'},
+	[ASSUBD]  =  {.fun = binary, .txt = "sub", .letter = 'd'},
+	[ASMULD]  =  {.fun = binary, .txt = "mul", .letter = 'd'},
+	[ASDIVD]  =  {.fun = binary, .txt = "div", .letter = 'd'},
+	[ASLTD]   =  {.fun = binary, .txt = "cltd", .letter = 'w'},
+	[ASGTD]   =  {.fun = binary, .txt = "cgtd", .letter = 'w'},
+	[ASLED]   =  {.fun = binary, .txt = "cled", .letter = 'w'},
+	[ASGED]   =  {.fun = binary, .txt = "cged", .letter = 'w'},
+	[ASEQD]   =  {.fun = binary, .txt = "ceqd", .letter = 'w'},
+	[ASNED]   =  {.fun = binary, .txt = "cned", .letter = 'w'},
+
+	[ASEXTBW] =  {.fun = unary, .txt = "extsb", .letter = 'w'},
+	[ASUEXTBW]=  {.fun = unary, .txt = "extub", .letter = 'w'},
+	[ASEXTBL] =  {.fun = unary, .txt = "extsb", .letter = 'l'},
+	[ASUEXTBL]=  {.fun = unary, .txt = "extub", .letter = 'l'},
+	[ASEXTHW] =  {.fun = unary, .txt = "extsh", .letter = 'w'},
+	[ASUEXTHW]=  {.fun = unary, .txt = "extuh", .letter = 'w'},
+	[ASEXTWL] =  {.fun = unary, .txt = "extsw", .letter = 'l'},
+	[ASUEXTWL]=  {.fun = unary, .txt = "extuw", .letter = 'l'},
+
+	[ASSTOL] = {.fun = unary, .txt = "stosi", .letter = 'l'},
+	[ASSTOW] = {.fun = unary, .txt = "stosi", .letter = 'w'},
+	[ASDTOL] = {.fun = unary, .txt = "dtosi", .letter = 'l'},
+	[ASDTOW] = {.fun = unary, .txt = "dtosi", .letter = 'w'},
+
+	[ASSWTOD] = {.fun = unary, .txt = "swtof", .letter = 'd'},
+	[ASSWTOS] = {.fun = unary, .txt = "swtof", .letter = 's'},
+	[ASSLTOD] = {.fun = unary, .txt = "sltof", .letter = 'd'},
+	[ASSLTOS] = {.fun = unary, .txt = "sltof", .letter = 's'},
+
+	[ASEXTS] = {.fun = unary, .txt = "exts", .letter = 'd'},
+	[ASTRUNCD] = {.fun = unary, .txt = "truncd", .letter = 's'},
+
+	[ASBRANCH] = {.fun = branch},
+	[ASJMP]  = {.fun = jmp},
+	[ASRET]  = {.fun = ret},
+	[ASCALL] = {.fun = call},
+	[ASCALLE] = {.fun = ecall, .txt = ")"},
+	[ASCALLEX] = {.fun = ecall, .txt = ", ...)"},
+	[ASPAR] = {.fun = param, .txt = "%s %s, "},
+	[ASPARE] = {.fun = param, .txt = "%s %s"},
+	[ASALLOC] = {.fun = asalloc},
+	[ASFORM] = {.fun = form2local},
+
+	[ASVSTAR] = {.fun = vastart},
+	[ASVARG] = {.fun = vaarg},
+};
+
+static char buff[ADDR_LEN];
+/*
+ * : is for user-defined Aggregate Types
+ * $ is for globals (represented by a pointer)
+ * % is for function-scope temporaries
+ * @ is for block labels
+ */
+static char
+sigil(Symbol *sym)
+{
+	switch (sym->kind) {
+	case SEXTRN:
+	case SGLOB:
+	case SPRIV:
+	case SLOCAL:
+		return '$';
+	case SAUTO:
+	case STMP:
+		return '%';
+	case SLABEL:
+		return '@';
+	default:
+		abort();
+	}
+}
+
+static char *
+symname(Symbol *sym)
+{
+	char c = sigil(sym);
+
+	if (sym->name) {
+		switch (sym->kind) {
+		case SEXTRN:
+		case SGLOB:
+			sprintf(buff, "%c%s", c, sym->name);
+			return buff;
+		case SLOCAL:
+		case SPRIV:
+		case SAUTO:
+			sprintf(buff, "%c%s.%u", c, sym->name, sym->id);
+			return buff;
+		default:
+			abort();
+		}
+	}
+	sprintf(buff, "%c.%u", c, sym->numid);
+
+	return buff;
+}
+
+static void
+emitconst(Node *np)
+{
+	switch (np->type.size) {
+	case 1:
+		printf("%d", (int) np->u.i & 0xFF);
+		break;
+	case 2:
+		printf("%d", (int) np->u.i & 0xFFFF);
+		break;
+	case 4:
+		printf("%ld", (long) np->u.i & 0xFFFFFFFF);
+		break;
+        case 8:
+                printf("%lld", (long long) np->u.i);
+                break;
+	default:
+		abort();
+	}
+}
+
+static void
+emittree(Node *np)
+{
+	if (!np)
+		return;
+
+	switch (np->op) {
+	case OSTRING:
+		printf("\"%s\"", np->u.s);
+		free(np->u.s);
+		np->u.s = NULL;
+		break;
+	case OCONST:
+		emitconst(np);
+		break;
+	case OADDR:
+		emittree(np->left);
+		break;
+	case OMEM:
+		fputs(symname(np->u.sym), stdout);
+		break;
+	default:
+		emittree(np->left);
+		printf(" %c ", np->op);
+		emittree(np->right);
+		break;
+	}
+}
+
+static char *
+size2asm(Type *tp)
+{
+	if (tp->flags & STRF) {
+		return "b";
+	} else if (tp->flags & INTF) {
+		switch (tp->size) {
+		case 1:
+			return "b";
+		case 2:
+			return "h";
+		case 4:
+			return "w";
+		case 8:
+			return "l";
+		}
+	} else if (tp->flags & FLOATF) {
+		if (tp->size == 4)
+			return "s";
+		else if (tp->size == 8)
+			return "d";
+	}
+	abort();
+}
+
+void
+defglobal(Symbol *sym)
+{
+	if (sym->kind == SEXTRN)
+		return;
+	if (sym->kind == SGLOB)
+		fputs("export ", stdout);
+	printf("data %s = {\n", symname(sym));
+	if (sym->type.flags & INITF)
+		return;
+	printf("\tz\t%lu\n}\n", sym->type.size);
+}
+
+void
+defpar(Symbol *sym)
+{
+	sym->type.flags |= PARF;
+}
+
+void
+defvar(Symbol *sym)
+{
+	if (sym->kind == SREG)
+		sym->kind = SAUTO;
+}
+
+void
+data(Node *np)
+{
+	printf("\t%s\t", size2asm(&np->type));
+	emittree(np);
+	putchar(',');
+	putchar('\n');
+}
+
+static char *
+size2stack(Type *tp)
+{
+	if (tp->flags & INTF) {
+		switch (tp->size) {
+		case 1:
+		case 2:
+		case 4:
+			return "w";
+		case 8:
+			return "l";
+		}
+	} else if (tp->flags & FLOATF) {
+		if (tp->size == 4)
+			return "s";
+		else if (tp->size == 8)
+			return "d";
+	} else if (tp->size == 0) {
+		return "w";
+	}
+	abort();
+}
+
+void
+writeout(void)
+{
+	Symbol *p;
+	Type *tp;
+	char *sep, *name;
+	int haslabel = 0;
+
+	if (!curfun)
+		return;
+	if (curfun->kind == SGLOB)
+		fputs("export ", stdout);
+	printf("function %s %s(", size2stack(&curfun->rtype), symname(curfun));
+
+	/* declare formal parameters */
+	for (sep = "", p = locals; p; p = p->next, sep = ",") {
+		if ((p->type.flags & PARF) == 0)
+			break;
+		printf("%s%s %s.val", sep, size2stack(&p->type), symname(p));
+	}
+	printf("%s)\n{\n", (curfun->type.flags&ELLIPS) ? ", ..." : "");
+
+	/* emit assembler instructions */
+	for (pc = prog; pc; pc = pc->next) {
+		if (pc->label) {
+			haslabel = 1;
+			printf("%s\n", symname(pc->label));
+		}
+		if (!pc->op)
+			continue;
+		if (pc->flags&BBENTRY && !haslabel)
+			printf("%s\n", symname(newlabel()));
+		(*optbl[pc->op].fun)();
+		if (!pc->label)
+			haslabel = 0;
+	}
+
+	puts("}");
+}
+
+static char *
+addr2txt(Addr *a)
+{
+	switch (a->kind) {
+	case SCONST:
+		sprintf(buff, "%llu", (unsigned long long) a->u.i);
+		return buff;
+	case SAUTO:
+	case SLABEL:
+	case STMP:
+	case SGLOB:
+	case SEXTRN:
+	case SPRIV:
+	case SLOCAL:
+		return symname(a->u.sym);
+	default:
+		abort();
+	}
+}
+
+static void
+binary(void)
+{
+	struct opdata *p = &optbl[pc->op];
+	char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN];
+
+	strcpy(to, addr2txt(&pc->to));
+	strcpy(from1, addr2txt(&pc->from1));
+	strcpy(from2, addr2txt(&pc->from2));
+	printf("\t%s =%c\t%s\t%s,%s\n", to, p->letter, p->txt, from1, from2);
+}
+
+static void
+ldir(void)
+{
+	struct opdata *p = &optbl[pc->op];
+	char to[ADDR_LEN], from[ADDR_LEN];
+	/* TODO: what type do we use for the size? */
+
+	/* TODO: it is pending */
+}
+
+static void
+store(void)
+{
+	struct opdata *p = &optbl[pc->op];
+	char to[ADDR_LEN], from[ADDR_LEN];
+
+	strcpy(to, addr2txt(&pc->to));
+	strcpy(from, addr2txt(&pc->from1));
+	printf("\t\t%s%c\t%s,%s\n", p->txt, p->letter, from, to);
+}
+
+static void
+unary(void)
+{
+	struct opdata *p = &optbl[pc->op];
+	char to[ADDR_LEN], from[ADDR_LEN];
+
+	strcpy(to, addr2txt(&pc->to));
+	strcpy(from, addr2txt(&pc->from1));
+	printf("\t%s =%c\t%s\t%s\n", to, p->letter, p->txt, from);
+}
+
+static void
+call(void)
+{
+	struct opdata *p = &optbl[pc->op];
+	char to[ADDR_LEN], from[ADDR_LEN];
+	Symbol *sym = pc->to.u.sym;
+
+	strcpy(to, addr2txt(&pc->to));
+	strcpy(from, addr2txt(&pc->from1));
+	printf("\t%s =%s\tcall\t%s(",
+	       to, size2stack(&sym->type), from);
+}
+
+static void
+param(void)
+{
+	Symbol *sym = pc->from2.u.sym;
+
+	printf(optbl[pc->op].txt,
+	       size2stack(&sym->type), addr2txt(&pc->from1));
+}
+
+static void
+ecall(void)
+{
+	struct opdata *p = &optbl[pc->op];
+
+	puts(p->txt);
+}
+
+static void
+ret(void)
+{
+	if (pc->from1.kind == SNONE)
+		puts("\t\tret");
+	else
+		printf("\t\tret\t%s\n", addr2txt(&pc->from1));
+}
+
+static void
+jmp(void)
+{
+	printf("\t\tjmp\t%s\n", addr2txt(&pc->from1));
+}
+
+static void
+branch(void)
+{
+	char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN];
+
+	strcpy(to, addr2txt(&pc->to));
+	strcpy(from1, addr2txt(&pc->from1));
+	strcpy(from2, addr2txt(&pc->from2));
+	printf("\t\tjnz\t%s,%s,%s\n", to, from1, from2);
+}
+
+static void
+vastart(void)
+{
+	printf("\t\tvastart %s\n", addr2txt(&pc->from1));
+}
+
+static void
+vaarg(void)
+{
+	Symbol *sym = pc->to.u.sym;
+	Type *tp = &sym->type;
+	char to[ADDR_LEN], from[ADDR_LEN];
+
+	strcpy(to, addr2txt(&pc->to));
+	strcpy(from, addr2txt(&pc->from1));
+	printf("\t\t%s =%s vaarg %s\n", to, size2asm(tp), from);
+}
+
+static void
+asalloc(void)
+{
+	Symbol *sym = pc->to.u.sym;
+	Type *tp = &sym->type;
+	extern Type ptrtype;
+
+	printf("\t%s =%s\talloc%lu\t%lu\n",
+	       symname(sym), size2asm(&ptrtype), tp->align+3 & ~3, tp->size);
+}
+
+static void
+form2local(void)
+{
+	Symbol *sym = pc->to.u.sym;
+	Type *tp = &sym->type;
+	char *name = symname(sym);
+
+	printf("\t\tstore%s\t%s.val,%s\n", size2asm(tp), name, name);
+}
+
+void
+endinit(void)
+{
+	puts("}");
+}
+
+void
+getbblocks(void)
+{
+	Inst *i;
+
+	if (!prog)
+		return;
+
+	prog->flags |= BBENTRY;
+	for (pc = prog; pc; pc = pc->next) {
+		switch (pc->op) {
+		case ASBRANCH:
+			i = pc->from2.u.sym->u.inst;
+			i->flags |= BBENTRY;
+		case ASJMP:
+			i = pc->from1.u.sym->u.inst;
+			i->flags |= BBENTRY;
+		case ASRET:
+			if (pc->next)
+				pc->next->flags |= BBENTRY;
+			break;
+		}
+	}
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/target/qbe/optm.c
@@ -1,0 +1,56 @@
+#include <stddef.h>
+
+#include <scc/scc.h>
+
+#include "../../cc2.h"
+
+Node *
+optm_dep(Node *np)
+{
+	int op = np->op;
+	Node *p, *dst, *next = np->next;
+	Symbol *sym, *osym;
+
+	switch (op) {
+	case OEFUN:
+		/*
+		 * In QBE we need at the end of a basic block
+		 * a jump, so we have to ensure that the last
+		 * statement of the function is a ret, a jmp
+		 * or a branch. In the same way, QBE does
+		 * not accept labels at the end of a function
+		 * (ONOP is used for labels) so we have to add
+		 * a ret there, and in the case of branches
+		 * we need a label for the next statement
+		 */
+		op = (np->prev) ? np->prev->op : 0;
+		if (!op || op == ONOP || op == OBRANCH || (op != ORET && op != OJMP))
+			addstmt(node(ORET), KEEPCUR);
+		break;
+	case OBRANCH:
+		if (!next->label) {
+			sym = getsym(TMPSYM);
+			sym->kind = SLABEL;
+			next->label = sym;
+		}
+	case OJMP:
+		for (;;) {
+			dst = np->u.sym->u.stmt;
+			if (dst->op != OJMP)
+				break;
+			np->u.sym = dst->u.sym;
+		}
+		for (p = np->next; p; p = p->next) {
+			if (p == dst)
+				return NULL;
+			if (p->op == ONOP ||
+			    p->op == OBLOOP ||
+			    p->op == OELOOP) {
+				continue;
+			}
+			break;
+		}
+		break;
+	}
+	return np;
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/target/qbe_amd64-sysv/target.mk
@@ -1,0 +1,8 @@
+OBJ-qbe_amd64-sysv = $(OBJS)  \
+        target/qbe/cgen.o \
+        target/qbe/optm.o \
+        target/qbe/code.o \
+        target/amd64-sysv/types.o
+
+$(LIBEXEC)/cc2-qbe_amd64-sysv: $(OBJ-qbe_amd64-sysv)
+	$(CC) $(SCC_LDFLAGS) $(OBJ-qbe_amd64-sysv) -lscc -o $@
--- /dev/null
+++ b/src/cmd/cc/cc2/target/qbe_arm64-sysv/target.mk
@@ -1,0 +1,5 @@
+OBJ-qbe_arm64-sysv = $(OBJS)  \
+        target/qbe/cgen.o \
+        target/qbe/optm.o \
+        target/qbe/code.o \
+        target/arm64-sysv/types.o \
--- /dev/null
+++ b/src/cmd/cc/cc2/target/z80-scc/arch.h
@@ -1,0 +1,5 @@
+enum asmop {
+	ASJMP = 0,
+	ASRET,
+	ASBRANCH,
+};
--- /dev/null
+++ b/src/cmd/cc/cc2/target/z80-scc/cgen.c
@@ -1,0 +1,159 @@
+#include <stdlib.h>
+
+#include <scc/scc.h>
+
+#include "arch.h"
+#include "../../cc2.h"
+
+static void
+swtch(Node *idx)
+{
+}
+
+static Node *
+rhs(Node *np, Node *ret)
+{
+}
+
+static Node *
+field(Node *np, Node *ret, int islhs)
+{
+}
+
+static Node *
+lhs(Node *np, Node *new)
+{
+	switch (np->op) {
+	case OMEM:
+	case OAUTO:
+		*new = *np;
+		return new;
+	case OPTR:
+		return rhs(np->left, new);
+	case OFIELD:
+		return field(np, new, 1);
+	default:
+		abort();
+	}
+}
+
+static void
+bool(Node *np, Symbol *true, Symbol *false)
+{
+	Node *l = np->left, *r = np->right;
+	Node ret, ifyes, ifno;
+	Symbol *label;
+
+	switch (np->op) {
+	case ONEG:
+		bool(l, false, true);
+		break;
+	case OAND:
+		label = newlabel();
+		bool(l, label, false);
+		setlabel(label);
+		bool(r, true, false);
+		break;
+	case OOR:
+		label = newlabel();
+		bool(l, true, label);
+		setlabel(label);
+		bool(r, true, false);
+		break;
+	default:
+		label2node(&ifyes, true);
+		label2node(&ifno, false);
+		code(ASBRANCH, rhs(np, &ret), &ifyes, &ifno);
+		break;
+	}
+}
+
+Node *
+cgen(Node *np)
+{
+	Node aux, *p, *next;
+
+	setlabel(np->label);
+	switch (np->op) {
+	case OJMP:
+		label2node(&aux, np->u.sym);
+		code(ASJMP, NULL, &aux, NULL);
+		break;
+	case OBRANCH:
+		next = np->next;
+		if (!next->label)
+			next->label = newlabel();
+		bool(np->left, np->u.sym, next->label);
+		break;
+	case ORET:
+		p = np->left;
+		if (p)
+			p = rhs(np->left, &aux);
+		code(ASRET, NULL, p, NULL);
+		break;
+	case OBSWITCH:
+		swtch(rhs(np->left, &aux));
+		break;
+	default:
+		rhs(np, &aux);
+		break;
+	}
+	return 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
+ *     REG => 13           reg
+ *     STATIC => 12        (value)
+ *     CONST => 20         $value
+ */
+Node *
+sethi(Node *np)
+{
+	Node *lp, *rp;
+
+	if (!np)
+		return np;
+
+	np->complex = 0;
+	np->address = 0;
+	lp = np->left;
+	rp = np->right;
+	switch (np->op) {
+	case OAUTO:
+		np->address = 11;
+		break;
+	case OREG:
+		np->address = 13;
+		break;
+	case OMEM:
+		np->address = 12;
+		break;
+	case OCONST:
+		np->address = 20;
+		break;
+	default:
+		sethi(lp);
+		sethi(rp);
+		break;
+	}
+
+	if (np->address > 10)
+		return np;
+	if (lp)
+		np->complex = lp->complex;
+	if (rp) {
+		int 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;
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/target/z80-scc/code.c
@@ -1,0 +1,227 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <scc/cstd.h>
+#include <scc/scc.h>
+
+#include "arch.h"
+#include "../../cc2.h"
+
+enum segment {
+	CODESEG,
+	DATASEG,
+	BSSSEG,
+	NOSEG
+};
+
+static int curseg = NOSEG;
+static unsigned long offpar, offvar;
+
+static void
+segment(int seg)
+{
+	static char *txt[] = {
+		[CODESEG] = "\tCSEG\n",
+		[DATASEG] = "\tDSEG\n",
+		[BSSSEG] = "\tASEG\n",
+	};
+
+	if (seg == curseg)
+		return;
+	fputs(txt[seg], stdout);
+	curseg = seg;
+}
+
+static char *
+symname(Symbol *sym)
+{
+	static char name[INTIDENTSIZ+1];
+
+	if (sym->name) {
+		switch (sym->kind) {
+		case SGLOB:
+		case SEXTRN:
+			snprintf(name, sizeof(name), "_%s", sym->name);
+			return name;
+		case SPRIV:
+			return sym->name;
+		}
+	}
+
+	sprintf(name, ".%d", sym->numid);
+
+	return name;
+}
+
+static void
+label(Symbol *sym)
+{
+	int seg;
+	char *name = symname(sym);
+
+	if (sym->type.flags & FUNF)
+		seg = CODESEG;
+	else if (sym->type.flags & INITF)
+		seg = DATASEG;
+	else
+		seg = BSSSEG;
+	segment(seg);
+
+	switch (sym->kind) {
+	case SEXTRN:
+		printf("\tEXTRN\t%s\n", name);
+		return;
+	case SGLOB:
+		printf("\tPUBLIC\t%s\n", name);
+		break;
+	}
+
+	printf("%s:\n", name);
+}
+
+static void
+emitconst(Node *np)
+{
+	switch (np->type.size) {
+	case 1:
+		printf("%d", (int) np->u.i & 0xFF);
+		break;
+	case 2:
+		printf("%d", (int) np->u.i & 0xFFFF);
+		break;
+	case 4:
+		printf("%ld", (long) np->u.i & 0xFFFFFFFF);
+		break;
+	default:
+		abort();
+	}
+}
+
+static void
+emittree(Node *np)
+{
+	if (!np)
+		return;
+
+	switch (np->op) {
+	case OSTRING:
+		printf("\"%s\"", np->u.s);
+		free(np->u.s);
+		np->u.s = NULL;
+		break;
+	case OCONST:
+		emitconst(np);
+		break;
+	case OADDR:
+		emittree(np->left);
+		break;
+	case OMEM:
+		fputs(symname(np->u.sym), stdout);
+		break;
+	default:
+		emittree(np->left);
+		printf(" %c ", np->op);
+		emittree(np->right);
+		break;
+	}
+}
+
+static void
+size2asm(Type *tp)
+{
+	char *s;
+
+	/*
+	 * In z80 we can ignore the alignment
+	 */
+	if (tp->flags & STRF) {
+		s = "\tDB\t";
+	} else {
+		switch (tp->size) {
+		case 1:
+			s = "\tDB\t";
+			break;
+		case 2:
+			s = "\tDW\t";
+			break;
+		case 4:
+			s = "\tDD\t";
+			break;
+		default:
+			s = "\tDS\t%lu,";
+			break;
+		}
+	}
+	printf(s, tp->size);
+}
+
+void
+newfun()
+{
+	offpar = offvar = 0;
+}
+
+void
+defpar(Symbol *sym)
+{
+	unsigned long align, size;
+
+	if (sym->kind != SREG && sym->kind != SAUTO)
+		return;
+	align = sym->type.align;
+	size = sym->type.size;
+
+	offpar -= align-1 & ~align;
+	sym->u.off = offpar;
+	offpar -= size;
+	sym->kind = SAUTO;
+}
+
+void
+defvar(Symbol *sym)
+{
+	unsigned long align, size;
+
+	if (sym->kind != SREG && sym->kind != SAUTO)
+		return;
+	align = sym->type.align;
+	size = sym->type.size;
+
+	offvar += align-1 & ~align;
+	sym->u.off = offvar;
+	offvar += size;
+	sym->kind = SAUTO;
+}
+
+void
+defglobal(Symbol *sym)
+{
+	label(sym);
+	if (sym->kind == SEXTRN || (sym->type.flags & INITF))
+		return;
+	size2asm(&sym->type);
+	puts("0");
+}
+
+void
+data(Node *np)
+{
+	size2asm(&np->type);
+	emittree(np);
+	putchar('\n');
+}
+
+void
+writeout(void)
+{
+}
+
+void
+endinit(void)
+{
+}
+
+void
+getbblocks(void)
+{
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/target/z80-scc/optm.c
@@ -1,0 +1,9 @@
+#include <scc/scc.h>
+
+#include "../../cc2.h"
+
+Node *
+optm_dep(Node *np)
+{
+	return np;
+}
--- /dev/null
+++ b/src/cmd/cc/cc2/target/z80-scc/target.mk
@@ -1,0 +1,8 @@
+OBJ-z80-scc = $(OBJS)  \
+        target/z80-scc/cgen.o \
+        target/z80-scc/optm.o \
+        target/z80-scc/code.o \
+        target/z80-scc/types.o \
+
+$(LIBEXEC)/cc2-z80-scc: $(OBJ-z80-scc)
+	$(CC) $(SCC_LDFLAGS) $(OBJ-z80-scc) -lscc -o $@
--- /dev/null
+++ b/src/cmd/cc/cc2/target/z80-scc/types.c
@@ -1,0 +1,93 @@
+#include <scc/scc.h>
+
+#include "../../cc2.h"
+
+
+Type int8type = {
+	.flags  = SIGNF | INTF,
+	.size   = 1,
+	.align  = 1
+};
+
+Type int16type = {
+	.flags  = SIGNF | INTF,
+	.size   = 2,
+	.align  = 1
+};
+
+Type int32type = {
+	.flags  = SIGNF | INTF,
+	.size   = 4,
+	.align  = 1
+};
+
+Type int64type = {
+	.flags  = SIGNF | INTF,
+	.size   = 8,
+	.align  = 1
+};
+
+Type uint8type = {
+	.flags  = INTF,
+	.size   = 1,
+	.align  = 1
+};
+
+Type uint16type = {
+	.flags  = INTF,
+	.size   = 2,
+	.align  = 1
+};
+
+Type uint32type = {
+	.flags  = INTF,
+	.size   = 4,
+	.align  = 1
+};
+
+Type uint64type = {
+	.flags  = INTF,
+	.size   = 8,
+	.align  = 1
+};
+
+Type ptrtype = {
+	.flags  = INTF,
+	.size   = 2,
+	.align  = 1
+};
+
+Type booltype = {
+	.flags  = INTF,
+	.size   = 1,
+	.align  = 1
+};
+
+Type float32type = {
+	.flags  = FLOATF,
+	.size   = 4,
+	.align  = 1
+};
+
+Type float64type = {
+	.flags  = FLOATF,
+	.size   = 4,
+	.align  = 1
+};
+
+Type float80type = {
+	.flags  = FLOATF,
+	.size   = 4,
+	.align  = 1
+};
+
+Type voidtype = {
+	.size = 0,
+	.align = 0
+};
+
+/* this types is not going to be used in this arch */
+Type arg_type = {
+        .size = 0,
+        .align = 0
+};
--- /dev/null
+++ b/src/cmd/cc/posix/.gitignore
@@ -1,0 +1,1 @@
+config.h
--- /dev/null
+++ b/src/cmd/cc/posix/Makefile
@@ -1,0 +1,38 @@
+.POSIX:
+
+PROJECTDIR = ../../../..
+include $(PROJECTDIR)/scripts/rules.mk
+
+# SYSLST is a list of backend-arch-abi-sys. First
+# element of the list becomes the default target
+
+SYSLST  = amd64-sysv-linux-elf z80-scc-none-none \
+          i386-sysv-linux-elf amd64-sysv-openbsd-elf
+
+STDCFLAGS =
+
+TARGETS = $(BINDIR)/scc $(BINDIR)/scpp
+
+all: $(TARGETS)
+
+$(BINDIR)/scc: scc.o
+	$(CC) $(SCC_LDFLAGS) scc.o -lscc -o $@
+
+$(BINDIR)/scpp: cpp.sh
+	trap "rm -f $$$$.sh" 0 2 3;\
+	rm -f $@ ;\
+	sed "s%@PREFIX@%$(PREFIX)%" < cpp.sh > $$$$.sh && \
+	chmod +x $$$$.sh && \
+	mv $$$$.sh $@
+
+config.h:
+	PREFIX=$(PREFIX) mkconf $(SYSLST)
+
+dep: inc-dep
+
+clean:
+	rm -f scc scpp *.o
+	rm -f $(TARGETS)
+	rm -f config.h
+
+include deps.mk
--- /dev/null
+++ b/src/cmd/cc/posix/cpp.sh
@@ -1,0 +1,4 @@
+#!/bin/sh
+
+SCCPREFIX=${SCCPREFIX:-@PREFIX@}
+${SCCPREFIX}/bin/scc -E $@
--- /dev/null
+++ b/src/cmd/cc/posix/deps.mk
@@ -1,0 +1,8 @@
+#deps
+./scc.o: $(INCDIR)/scc/scc/arg.h
+./scc.o: $(INCDIR)/scc/scc/ldflags.h
+./scc.o: $(INCDIR)/scc/scc/scc.h
+./scc.o: $(INCDIR)/scc/scc/syscrts.h
+./scc.o: $(INCDIR)/scc/scc/sysincludes.h
+./scc.o: $(INCDIR)/scc/scc/syslibs.h
+./scc.o: ./config.h
--- /dev/null
+++ b/src/cmd/cc/posix/mkconf
@@ -1,0 +1,16 @@
+#!/bin/sh
+
+set -e
+
+rm -f config.h
+trap "rm -f $$.h" 0 2 3
+
+PREFIX=${PREFIX-$HOME}
+
+echo $@ |
+(IFS='- 	' read arch abi sys format r
+echo \#define PREFIX \"$PREFIX\"
+echo \#define ARCH \"$arch\"
+echo \#define SYS  \"$sys\"
+echo \#define ABI  \"$abi\"
+echo \#define FORMAT \"$format\") > $$.h && mv $$.h config.h
--- /dev/null
+++ b/src/cmd/cc/posix/scc.c
@@ -1,0 +1,620 @@
+#define _POSIX_SOURCE
+#define _XOPEN_SOURCE 500
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+#include <scc/arg.h>
+#include <scc/scc.h>
+#include <scc/syscrts.h>
+#include <scc/sysincludes.h>
+#include <scc/syslibs.h>
+#include <scc/ldflags.h>
+
+enum {
+	CC1,
+	TEEIR,
+	CC2,
+	TEEQBE,
+	QBE,
+	TEEAS,
+	AS,
+	LD,
+	STRIP,
+	LAST_TOOL,
+};
+
+static struct tool {
+	char   cmd[PATH_MAX];
+	char   bin[32];
+	char  *outfile;
+	struct items args;
+	unsigned nparams;
+	int    in, out, init;
+	pid_t  pid;
+} tools[] = {
+	[CC1]    = { .cmd = "cc1" },
+	[TEEIR]  = { .bin = "tee",   .cmd = "tee", },
+	[CC2]    = { .cmd = "cc2" },
+	[TEEQBE] = { .bin = "tee",   .cmd = "tee", },
+	[QBE]    = { .bin = "qbe",   .cmd = "qbe", },
+	[TEEAS]  = { .bin = "tee",   .cmd = "tee", },
+	[AS]     = { .bin = "as",    .cmd = "as", },
+	[LD]     = { .bin = "ld",    .cmd = "ld", },
+	[STRIP]  = { .bin = "strip", .cmd = "strip", },
+};
+
+char *argv0;
+static char *arch, *sys, *abi, *format;
+static char *prefix, *objfile, *outfile;
+static char *tmpdir;
+static size_t tmpdirln;
+static struct items objtmp, objout;
+static int Mflag, Eflag, Sflag, Wflag,
+           cflag, dflag, kflag, sflag, Qflag = 1; /* TODO: Remove Qflag */
+static int devnullfd = -1;
+
+extern int failure;
+
+static void
+terminate(void)
+{
+	unsigned i;
+
+	if (!kflag) {
+		for (i = 0; i < objtmp.n; ++i)
+			unlink(objtmp.s[i]);
+	}
+}
+
+static void
+addarg(int tool, char *arg)
+{
+	struct tool *t = &tools[tool];
+
+	if (t->args.n < 1)
+		t->args.n = 1;
+
+	newitem(&t->args, arg);
+}
+
+static void
+setargv0(int tool, char *arg)
+{
+	struct tool *t = &tools[tool];
+
+	if (t->args.n > 0)
+		t->args.s[0] = arg;
+	else
+		newitem(&t->args, arg);
+}
+
+static int
+qbe(int tool)
+{
+	if (tool != CC2 || !Qflag)
+		return 0;
+	if (!strcmp(arch, "amd64") && !strcmp(abi, "sysv"))
+		return 1;
+	return 0;
+}
+
+static int
+inittool(int tool)
+{
+	struct tool *t = &tools[tool];
+	char *crt, *fmt;
+	int n;
+
+	if (t->init)
+		return tool;
+
+	switch (tool) {
+	case CC1:
+		if (Wflag)
+			addarg(tool, "-w");
+		for (n = 0; sysincludes[n]; ++n) {
+			addarg(tool, "-I");
+			addarg(tool, sysincludes[n]);
+		}
+	case CC2:
+		fmt = (qbe(tool)) ? "%s-qbe_%s-%s" : "%s-%s-%s";
+		n = snprintf(t->bin, sizeof(t->bin), fmt, t->cmd, arch, abi);
+		if (n < 0 || n >= sizeof(t->bin))
+			die("scc: target tool name too long");
+
+		n = snprintf(t->cmd, sizeof(t->cmd),
+		             "%s/libexec/scc/%s", prefix, t->bin);
+		if (n < 0 || n >= sizeof(t->cmd))
+			die("scc: target tool path too long");
+		break;
+	case LD:
+		for (n = 0; ldflags[n]; ++n)
+			addarg(tool, ldflags[n]);
+		addarg(tool, "-o");
+		t->outfile = outfile ? outfile : xstrdup("a.out");
+		addarg(tool, t->outfile);
+		for (n = 0; syslibs[n]; ++n) {
+			addarg(tool, "-L");
+			addarg(tool, syslibs[n]);
+		}
+		if (syscrts[0]) {
+			for (n = 0; syscrts[n]; ++n)
+				addarg(tool, syscrts[n]);
+			break;
+		}
+		n = snprintf(NULL, 0,
+		             "%s/lib/scc/%s-%s-%s/crt.o",
+		             prefix, arch, abi, sys);
+		if (n < 0)
+			die("scc: wrong crt file name");
+		crt = xmalloc(++n);
+		sprintf(crt,
+		        "%s/lib/scc/%s-%s-%s/crt.o",
+		        prefix, arch, abi, sys);
+		addarg(tool, crt);
+		break;
+	case AS:
+		addarg(tool, "-o");
+		break;
+	default:
+		break;
+	}
+
+	setargv0(tool, t->bin);
+	t->nparams = t->args.n;
+	t->init = 1;
+
+	return tool;
+}
+
+static char *
+outfname(char *path, char *type)
+{
+	char *new, sep, *p;
+	size_t newsz, pathln;
+	int tmpfd, n;
+
+	if (path) {
+		sep = '.';
+		if (p = strrchr(path, '/'))
+			path = p + 1;
+		pathln = strlen(path);
+		if (p = strrchr(path, '.'))
+			pathln -= strlen(p);
+	} else {
+		sep = '/';
+		type = "scc-XXXXXX";
+		path = tmpdir;
+		pathln = tmpdirln;
+	}
+
+	newsz = pathln + 1 + strlen(type) + 1;
+	new = xmalloc(newsz);
+	n = snprintf(new, newsz, "%.*s%c%s", (int)pathln, path, sep, type);
+	if (n < 0 || n >= newsz)
+		die("scc: wrong output filename");
+	if (sep == '/') {
+		if ((tmpfd = mkstemp(new)) < 0)
+			die("scc: could not create output file '%s': %s",
+			    new, strerror(errno));
+		close(tmpfd);
+	}
+
+	return new;
+}
+
+static int
+settool(int tool, char *infile, int nexttool)
+{
+	struct tool *t = &tools[tool];
+	unsigned i;
+	int fds[2];
+	static int fdin = -1;
+
+	switch (tool) {
+	case TEEIR:
+		t->outfile = outfname(infile, "ir");
+		addarg(tool, t->outfile);
+		break;
+	case TEEQBE:
+		t->outfile = outfname(infile, "qbe");
+		addarg(tool, t->outfile);
+		break;
+	case TEEAS:
+		t->outfile = outfname(infile, "s");
+		addarg(tool, t->outfile);
+		break;
+	case AS:
+		if (cflag && outfile) {
+			objfile = outfile;
+		} else {
+			objfile = (cflag || kflag) ? infile : NULL;
+			objfile = outfname(objfile, "o");
+		}
+		t->outfile = xstrdup(objfile);
+		addarg(tool, t->outfile);
+		break;
+	case STRIP:
+		if (cflag || kflag) {
+			for (i = 0; i < objout.n; ++i)
+				addarg(tool, xstrdup(objout.s[i]));
+		}
+		if (!cflag && tools[LD].outfile)
+			addarg(tool, tools[LD].outfile);
+		break;
+	default:
+		break;
+	}
+
+	if (fdin > -1) {
+		t->in = fdin;
+		fdin = -1;
+	} else {
+		t->in = -1;
+		if (infile)
+			addarg(tool, xstrdup(infile));
+	}
+
+	if (nexttool < LAST_TOOL) {
+		if (pipe(fds))
+			die("scc: pipe: %s", strerror(errno));
+		t->out = fds[1];
+		fdin = fds[0];
+	} else {
+		t->out = -1;
+	}
+
+	addarg(tool, NULL);
+
+	return tool;
+}
+
+static void
+spawn(int tool)
+{
+	struct tool *t = &tools[tool];
+
+	switch (t->pid = fork()) {
+	case -1:
+		die("scc: %s: %s", t->bin, strerror(errno));
+	case 0:
+		if (t->out > -1)
+			dup2(t->out, 1);
+		if (t->in > -1)
+			dup2(t->in, 0);
+		if (!dflag && tool != CC1 && tool != LD)
+			dup2(devnullfd, 2);
+		execvp(t->cmd, t->args.s);
+		if (dflag) {
+			fprintf(stderr,
+			        "scc: execvp %s: %s\n",
+				t->cmd,
+			        strerror(errno));
+		}
+		abort();
+	default:
+		if (t->in > -1)
+			close(t->in);
+		if (t->out > -1)
+			close(t->out);
+		break;
+	}
+}
+
+static int
+toolfor(char *file)
+{
+	char *dot = strrchr(file, '.');
+
+	if (dot) {
+		if (!strcmp(dot, ".c"))
+			return CC1;
+		if (!strcmp(dot, ".ir"))
+			return CC2;
+		if (!strcmp(dot, ".qbe"))
+			return QBE;
+		if (!strcmp(dot, ".s"))
+			return AS;
+		if (!strcmp(dot, ".o"))
+			return LD;
+		if (!strcmp(dot, ".a"))
+			return LD;
+	} else if (!strcmp(file, "-")) {
+		return CC1;
+	}
+
+	die("scc: do not recognize filetype of %s", file);
+}
+
+static int
+valid(int tool, struct tool *t)
+{
+	int st;
+
+	if (waitpid(t->pid, &st, 0) == -1 || WIFSIGNALED(st))
+		goto internal;
+	if (WIFEXITED(st) && WEXITSTATUS(st) == 0)
+		return 1;
+	if (!failure && (tool == CC1 || tool == LD))
+		goto fail;
+
+internal:
+	fprintf(stderr, "scc:%s: internal error\n", t->bin);
+fail:
+	failure = 1;
+	return 0;
+}
+
+static int
+validatetools(void)
+{
+	struct tool *t;
+	unsigned i;
+	int tool, st, failed = LAST_TOOL;
+
+	for (tool = 0; tool < LAST_TOOL; ++tool) {
+		t = &tools[tool];
+		if (!t->pid)
+			continue;
+		if (!valid(tool, t))
+			failed = tool;
+		if (tool >= failed && t->outfile)
+			unlink(t->outfile);
+		for (i = t->nparams; i < t->args.n; ++i)
+			free(t->args.s[i]);
+		t->args.n = t->nparams;
+		t->pid = 0;
+	}
+	if (failed < LAST_TOOL) {
+		unlink(objfile);
+		free(objfile);
+		objfile = NULL;
+		return 0;
+	}
+
+	return 1;
+}
+
+static int
+buildfile(char *file, int tool)
+{
+	int nexttool;
+
+	for (; tool < LAST_TOOL; tool = nexttool) {
+		switch (tool) {
+		case CC1:
+			if (Eflag || Mflag)
+				nexttool = LAST_TOOL;
+			else
+				nexttool = kflag ? TEEIR : CC2;
+			break;
+		case TEEIR:
+			nexttool = CC2;
+			break;
+		case CC2:
+			if (Qflag)
+				nexttool = kflag ? TEEQBE : QBE;
+			else
+				nexttool = (Sflag || kflag) ? TEEAS : AS;
+			break;
+		case TEEQBE:
+			nexttool = QBE;
+			break;
+		case QBE:
+			nexttool = (Sflag || kflag) ? TEEAS : AS;
+			break;
+		case TEEAS:
+			nexttool = Sflag ? LAST_TOOL : AS;
+			break;
+		case AS:
+			nexttool = LAST_TOOL;
+			break;
+		default:
+			nexttool = LAST_TOOL;
+			continue;
+		}
+
+		spawn(settool(inittool(tool), file, nexttool));
+	}
+
+	return validatetools();
+}
+
+static void
+build(struct items *chain, int link)
+{
+	int i, tool;
+
+	if (link)
+		inittool(LD);
+
+	for (i = 0; i < chain->n; ++i) {
+		if (!strcmp(chain->s[i], "-l")) {
+			if (link) {
+				addarg(LD, xstrdup(chain->s[i++]));
+				addarg(LD, xstrdup(chain->s[i]));
+			} else {
+				++i;
+			}
+			continue;
+		}
+		tool = toolfor(chain->s[i]);
+		if (tool == LD) {
+			if (link)
+				addarg(LD, xstrdup(chain->s[i]));
+			continue;
+		}
+		if (buildfile(chain->s[i], tool)) {
+			if (link)
+				addarg(LD, xstrdup(objfile));
+			newitem((!link || kflag) ? &objout : &objtmp, objfile);
+		}
+	}
+}
+
+static void
+usage(void)
+{
+	fputs("usage: scc [-D def[=val]]... [-U def]... [-I dir]... "
+	       "[-L dir]... [-l dir]...\n"
+	       "           [-dgksw] [-m arch] [-M|-E|-S] [-o outfile] file...\n"
+	       "       scc [-D def[=val]]... [-U def]... [-I dir]... "
+	       "[-L dir]... [-l dir]...\n"
+	       "           [-dgksw] [-m arch] [-M|-E|-S] -c file...\n"
+	       "       scc [-D def[=val]]... [-U def]... [-I dir]... "
+	       "[-L dir]... [-l dir]...\n"
+	       "           [-dgksw] [-m arch] -c -o outfile file\n", stderr);
+	exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+	struct items linkchain = { .n = 0, };
+	int link;
+
+	atexit(terminate);
+
+	if (!(arch = getenv("ARCH")))
+		arch = ARCH;
+	if (!(sys = getenv("SYS")))
+		sys = SYS;
+	if (!(abi = getenv("ABI")))
+		abi = ABI;
+	if (!(format = getenv("FORMAT")))
+		format = FORMAT;
+	if (!(prefix = getenv("SCCPREFIX")))
+		prefix = PREFIX;
+
+	ARGBEGIN {
+	case 'D':
+		addarg(CC1, "-D");
+		addarg(CC1, EARGF(usage()));
+		break;
+	case 'M':
+		Mflag = 1;
+		addarg(CC1, "-M");
+		break;
+	case 'E':
+		Eflag = 1;
+		addarg(CC1, "-E");
+		break;
+	case 'I':
+		addarg(CC1, "-I");
+		addarg(CC1, EARGF(usage()));
+		break;
+	case 'L':
+		addarg(LD, "-L");
+		addarg(LD, EARGF(usage()));
+		break;
+	case 'O':
+		EARGF(usage());
+		break;
+	case 'S':
+		Sflag = 1;
+		break;
+	case 'U':
+		addarg(CC1, "-U");
+		addarg(CC1, EARGF(usage()));
+		break;
+	case 'c':
+		cflag = 1;
+		break;
+	case 'd':
+		dflag = 1;
+		break;
+	case 'g':
+		addarg(AS, "-g");
+		addarg(LD, "-g");
+		break;
+	case 'k':
+		kflag = 1;
+		break;
+	case 'l':
+		newitem(&linkchain, "-l");
+		newitem(&linkchain, EARGF(usage()));
+		break;
+	case 'm':
+		arch = EARGF(usage());
+		break;
+	case 'o':
+		outfile = xstrdup(EARGF(usage()));
+		break;
+	case 's':
+		sflag = 1;
+		break;
+	case 't':
+		sys = EARGF(usage());
+		break;
+	case 'w':
+		Wflag = 0;
+		break;
+	case 'W':
+		Wflag = 1;
+		break;
+	case 'q':
+		Qflag = 0;
+		break;
+	case 'Q':
+		Qflag = 1;
+		break;
+	case '-':
+		fprintf(stderr,
+		        "scc: ignored parameter --%s\n", EARGF(usage()));
+		break;
+	default:
+		usage();
+	} ARGOPERAND {
+operand:
+		newitem(&linkchain, ARGOP());
+	} ARGEND
+
+	for (; *argv; --argc, ++argv)
+		goto operand;
+
+	if (Eflag && linkchain.n == 0)
+		newitem(&linkchain, "-");
+
+	if (Eflag && Mflag ||
+            (Eflag || Mflag) && (Sflag || kflag) ||
+	    linkchain.n == 0 ||
+	    linkchain.n > 1 && cflag && outfile)
+		usage();
+
+	if (!dflag) {
+		if ((devnullfd = open("/dev/null", O_WRONLY)) < 0)
+			fputs("scc: could not open /dev/null\n", stderr);
+	}
+
+	if (!(tmpdir = getenv("TMPDIR")) || !tmpdir[0])
+		tmpdir = ".";
+	tmpdirln = strlen(tmpdir);
+
+	build(&linkchain, (link = !(Mflag || Eflag || Sflag || cflag)));
+
+	if (!(link || cflag))
+		return failure;
+
+	if (link && !failure) {
+		addarg(LD, xstrdup("-lc"));
+		spawn(settool(LD, NULL, LAST_TOOL));
+		validatetools();
+	}
+
+	if (sflag) {
+		spawn(settool(inittool(STRIP), NULL, LAST_TOOL));
+		validatetools();
+	}
+
+	return failure;
+}
--- a/src/cmd/scc/Makefile
+++ /dev/null
@@ -1,14 +1,0 @@
-.POSIX:
-
-PROJECTDIR = ../../..
-include $(PROJECTDIR)/scripts/rules.mk
-
-DIRS = cc1 cc2 $(DRIVER)
-
-all: $(DIRS)
-
-$(DIRS): FORCE
-	+@cd $@ && $(MAKE)
-
-dep clean:
-	$(FORALL)
--- a/src/cmd/scc/cc1/Makefile
+++ /dev/null
@@ -1,38 +1,0 @@
-.POSIX:
-
-PROJECTDIR = ../../../..
-include $(PROJECTDIR)/scripts/rules.mk
-
-OBJS = types.o \
-       decl.o \
-       lex.o \
-       error.o \
-       symbol.o \
-       main.o \
-       expr.o \
-       code.o \
-       stmt.o \
-       cpp.o \
-       fold.o \
-       init.o \
-       builtin.o \
-
-TARGET   = $(LIBEXEC)/cc1-amd64-sysv \
-           $(LIBEXEC)/cc1-arm64-sysv \
-           $(LIBEXEC)/cc1-i386-sysv \
-           $(LIBEXEC)/cc1-z80-scc \
-
-all: $(TARGET)
-
-$(TARGET): $(LIBDIR)/libscc.a
-
-dep: inc-dep
-
-clean:
-	rm -f target/*/*.o
-
-include target/amd64-sysv/arch.mk
-include target/arm64-sysv/arch.mk
-include target/i386-sysv/arch.mk
-include target/z80-scc/arch.mk
-include deps.mk
--- a/src/cmd/scc/cc1/TODO
+++ /dev/null
@@ -1,14 +1,0 @@
-* Implement bitfields
-* Rewrite error recovery code, and ensure correct state after recovery
-* Parse correctly all integer and float constants
-* Add C99 features (almost all the new features of C99 are missed)
-* Add correct emit for any kind of constant
-* Add warning when some ANSI limit is violated.
-* Free memory in emit after some error happened.
-* Rewrite initializers to deal with the idea of  "current object"
-* Add some test about pointer airthmetic.
-* Merge all the definitions of the same string
-* Do not assign identifierss until symbols are emitted. This change will
-  avoid identifiers that are not emitted.
-* Fix assignation abbreviations. They fail whe lhs type is smaller than
-  the type in rhs
--- a/src/cmd/scc/cc1/builtin.c
+++ /dev/null
@@ -1,119 +1,0 @@
-#include <stdio.h>
-
-#include <scc/scc.h>
-#include "cc1.h"
-
-static Node *
-builtin_va_arg(Symbol *sym)
-{
-	Node *np, *ap;
-	Type *tp;
-
-	ap = assign();
-	expect(',');
-	tp = typename();
-
-	if (!valid_va_list(ap->type)) {
-		errorp("incorrect parameters for va_arg");
-		goto error;
-	}
-	if (tp == booltype ||
-	    tp == chartype || tp == uchartype || tp == schartype ||
-	    tp == shortype || tp == ushortype) {
-		warn("bool, char and short are promoted to int when passed through '...'");
-		tp = (tp->prop & TSIGNED) ? inttype : uinttype;
-	}
-
-	np = node(OBUILTIN, tp, ap, NULL);
-	np->sym = sym;
-	return np;
-
-error:
-	return constnode(zero);
-}
-
-static Node *
-builtin_va_copy(Symbol *sym)
-{
-	Node *np, *src, *dst;
-
-	dst = assign();
-	expect(',');
-	src = assign();
-
-	if (!valid_va_list(dst->type) || !valid_va_list(src->type)) {
-		errorp("incorrect parameters for va_copy");
-		return constnode(zero);
-	}
-
-	np = node(OBUILTIN, voidtype, dst, src);
-	np->sym = sym;
-	return np;
-}
-
-static Node *
-builtin_va_start(Symbol *sym)
-{
-	Node *np, *ap, *last;
-	Symbol **p;
-	Type *tp;
-
-	ap = assign();
-	expect(',');
-	last = assign();
-	if (last->op != OSYM)
-		goto error;
-
-	if (!valid_va_list(ap->type) || !(last->sym->flags&SDECLARED))
-		 goto error;
-
-	for (p = curfun->u.pars; p && *p != last->sym; ++p)
-		;
-	if (!p || *p == NULL || p[1] == NULL || p[1]->type != ellipsistype)
-		warn("second parameter of 'va_start' not last named argument");
-
-	tp = last->type;
-	if (tp == booltype ||
-	    tp == chartype || tp == uchartype || tp == schartype ||
-	    tp == shortype || tp == ushortype) {
-		warn("last parameter before '...' must not be bool, char or short");
-	}
-
-	np = node(OBUILTIN, voidtype, ap, last);
-	np->sym = sym;
-	return np;
-
-error:
-	errorp("incorrect parameters for va_start");
-	return constnode(zero);
-}
-
-static Node *
-builtin_va_end(Symbol *sym)
-{
-	Node *ap, *np;
-
-	ap = assign();
-
-	if (!valid_va_list(ap->type)) {
-		errorp("incorrect parameters for va_end");
-		return constnode(zero);
-	}
-
-	np = node(OBUILTIN, voidtype, ap, NULL);
-	np->sym = sym;
-	return np;
-}
-
-void
-ibuilts(void)
-{
-	struct builtin built[] = {
-		{"__builtin_va_arg", builtin_va_arg},
-		{"__builtin_va_copy", builtin_va_copy},
-		{"__builtin_va_start", builtin_va_start},
-		{"__builtin_va_end", builtin_va_end},
-		{NULL}
-	};
-	builtins(built);
-}
--- a/src/cmd/scc/cc1/cc1.h
+++ /dev/null
@@ -1,496 +1,0 @@
-#define INPUTSIZ LINESIZ
-
-#define GLOBALCTX 0
-#define PARAMCTX  1
-
-#define NR_USWITCHES 20
-
-/*
- * Definition of enumerations
- */
-enum {
-	NOALLOC,
-	ALLOC
-};
-
-enum typeprops {
-	TDEFINED = 1 << 0,    /* type defined */
-	TSIGNED  = 1 << 1,    /* signedness of the type */
-	TINTEGER = 1 << 2,    /* the type is INT of enum */
-	TARITH   = 1 << 3,    /* the type is INT, ENUM or FLOAT */
-	TAGGREG  = 1 << 4,    /* the type is struct or union */
-	TK_R     = 1 << 5,    /* this is a K&R-function */
-	TELLIPSIS= 1 << 6,    /* this function has an ellipsis par */
-	TFUNDEF  = 1 << 7,    /* function definition */
-};
-
-enum inputtype {
-	IMACRO = 1 << 0,      /* macro expansion type */
-	IFILE  = 1 << 1,      /* input file type */
-	ISTDIN = 1 << 2,      /* stdin type */
-	IEOF   = 1 << 3,      /* EOF mark */
-	ITYPE  = IMACRO | IFILE | ISTDIN,
-};
-
-/* data type letters */
-enum ns {
-	L_INT8      = 'C',
-	L_INT16     = 'I',
-	L_INT32     = 'W',
-	L_INT64     = 'Q',
-	L_UINT8     = 'K',
-	L_UINT16    = 'N',
-	L_UINT32    = 'Z',
-	L_UINT64    = 'O',
-	L_BOOL      = 'B',
-
-	L_FLOAT     = 'J',
-	L_DOUBLE    = 'D',
-	L_LDOUBLE   = 'H',
-
-	L_ELLIPSIS  = 'E',
-	L_VOID      = '0',
-	L_POINTER   = 'P',
-	L_FUNCTION  = 'F',
-	L_ARRAY     = 'V',
-	L_UNION     = 'U',
-	L_STRUCT    = 'S',
-	L_VA_ARG    = '1',
-};
-
-/* recovery points */
-enum {
-	END_DECL,
-	END_LDECL,
-	END_COMP,
-	END_COND
-};
-
-/* type constructors */
-enum typeop {
-	FTN = 1,
-	PTR,
-	ARY,
-	KRFTN
-};
-
-/* namespaces */
-enum namespaces {
-	NS_DUMMY,
-	NS_IDEN,
-	NS_TAG,
-	NS_LABEL,
-	NS_CPP,
-	NS_KEYWORD,
-	NS_CPPCLAUSES,
-	NS_STRUCTS
-};
-
-/* symbol flags */
-enum {
-	SAUTO     = 1 << 0,
-	SREGISTER = 1 << 1,
-	SDECLARED = 1 << 2,
-	SFIELD    = 1 << 3,
-	SEXTERN   = 1 << 4,
-	SUSED     = 1 << 5,
-	SCONSTANT = 1 << 6,
-	SGLOBAL   = 1 << 7,
-	SPRIVATE  = 1 << 8,
-	SLOCAL    = 1 << 9,
-	SEMITTED  = 1 << 10,
-	SDEFINED  = 1 << 11,
-	SSTRING   = 1 << 12,
-	STYPEDEF  = 1 << 13,
-	SINITLST  = 1 << 14,
-	SHASINIT  = 1 << 15
-};
-
-/* node flags */
-enum {
-	NLVAL   = 1 << 0,
-	NCONST  = 1 << 1,
-	NEFFECT = 1 << 2
-};
-
-/* lexer mode, compiler or preprocessor directive */
-enum {
-	CCMODE,
-	CPPMODE
-};
-
-/* input tokens */
-enum tokens {
-	CONST      = 1 << 0,      /* type qualifier tokens are used as flags */
-	RESTRICT   = 1 << 1,
-	VOLATILE   = 1 << 2,
-	INLINE     = 1 << 3,
-	TQUALIFIER = 1 << 7,      /* this value is picked outside of ASCII range */
-	TYPE,
-	IDEN,
-	SCLASS,
-	CONSTANT,
-	STRING,
-	SIZEOF,
-	INDIR,
-	INC,
-	DEC,
-	SHL,
-	SHR,
-	LE,
-	GE,
-	EQ,
-	NE,
-	AND,
-	OR,
-	MUL_EQ,
-	DIV_EQ,
-	MOD_EQ,
-	ADD_EQ,
-	SUB_EQ,
-	AND_EQ,
-	XOR_EQ,
-	OR_EQ,
-	SHL_EQ,
-	SHR_EQ,
-	ELLIPSIS,
-	CASE,
-	DEFAULT,
-	IF,
-	ELSE,
-	SWITCH,
-	WHILE,
-	DO,
-	FOR,
-	GOTO,
-	VOID,
-	FLOAT,
-	INT,
-	BOOL,
-	VA_LIST,
-	STRUCT,
-	UNION,
-	CHAR,
-	DOUBLE,
-	SHORT,
-	LONG,
-	LLONG,
-	COMPLEX,
-	TYPEDEF,
-	EXTERN,
-	STATIC,
-	AUTO,
-	REGISTER,
-	ENUM,
-	TYPEIDEN,
-	UNSIGNED,
-	SIGNED,
-	CONTINUE,
-	BREAK,
-	RETURN,
-	DEFINE,
-	INCLUDE,
-	LINE,
-	PRAGMA,
-	ERROR,
-	IFDEF,
-	ELIF,
-	IFNDEF,
-	UNDEF,
-	ENDIF,
-	BUILTIN,
-	EOFTOK
-};
-
-/* operations */
-enum op {
-	OADD,
-	OMUL,
-	OSUB,
-	OINC,
-	ODEC,
-	ODIV,
-	OMOD,
-	OSHL,
-	OSHR,
-	OBAND,
-	OBXOR,
-	OBOR,
-	OSNEG,
-	ONEG,
-	OCPL,
-	OAND,
-	OOR,
-	OEQ,
-	ONE,
-	OLT,
-	OGE,
-	OLE,
-	OGT,
-	OASSIGN,
-	OA_MUL,
-	OA_DIV,
-	OA_MOD,
-	OA_ADD,
-	OA_SUB,
-	OA_SHL,
-	OA_SHR,
-	OA_AND,
-	OA_XOR,
-	OA_OR,
-	OADDR,
-	OCOMMA,
-	OCAST,
-	OPTR,
-	OSYM,
-	OASK,
-	OCOLON,
-	OFIELD,
-	OLABEL,
-	ODEFAULT,
-	OCASE,
-	OJUMP,
-	OBRANCH,
-	OEXPR,
-	OEFUN,
-	OELOOP,
-	OBLOOP,
-	OFUN,
-	OPAR,
-	OCALL,
-	OCALLE,
-	ORET,
-	ODECL,
-	OBSWITCH,
-	OESWITCH,
-	OINIT,
-	OBUILTIN,
-	OTYP,
-};
-
-/*
- * Definition of structures
- */
-typedef struct type Type;
-typedef struct symbol Symbol;
-typedef struct swtch Switch;
-typedef struct node Node;
-typedef struct input Input;
-
-struct limits {
-	union {
-		TUINT i;
-		TFLOAT f;
-	} max;
-	union {
-		TUINT i;
-		TFLOAT f;
-	} min;
-};
-
-struct builtin {
-	char *str;
-	Node *(*fun)(Symbol *);
-};
-
-struct keyword {
-	char *str;
-	unsigned char token, value;
-};
-
-struct type {
-	unsigned char op;           /* type builder operator */
-	unsigned char ns;           /* namespace for struct members */
-	short id;                   /* type id, used in dcls */
-	char letter;                /* letter of the type */
-	unsigned char prop;         /* type properties */
-	unsigned char align;        /* align of the type */
-	unsigned long size;         /* sizeof the type */
-	Type *type;                 /* base type */
-	Symbol *tag;                /* symbol of the strug tag */
-	union {
-		Type **pars;            /* Function type parameters */
-		Symbol **fields;        /* fields of aggregate type */
-	} p;
-	union {
-		unsigned char rank;     /* convertion rank */
-		TINT elem;              /* number of type parameters */
-	} n;
-	Type *next;                 /* local list pointer */
-	Type *h_next;               /* hash collision list */
-};
-
-struct symbol {
-	unsigned char ctx;
-	unsigned char hide;
-	char ns;
-	unsigned short id;
-	unsigned short flags;
-	char *name;
-	Type *type;
-	unsigned char token;
-	union {
-		TINT i;
-		TUINT u;
-		TFLOAT f;
-		char *s;
-		unsigned char token;
-		Node **init;
-		Symbol **pars;
-		Node *(*fun)(Symbol *);
-	} u;
-	struct symbol *next;
-	struct symbol *hash;
-};
-
-struct node {
-	unsigned char op;
-	unsigned char flags;
-	Type *type;
-	Symbol *sym;
-	struct node *left, *right;
-};
-
-struct swtch {
-	short nr;
-	char hasdef;
-};
-
-struct yystype {
-	Symbol *sym;
-	unsigned char token;
-};
-
-#ifdef stdin
-struct input {
-	char flags;
-	unsigned lineno;
-	char *filenam;
-	FILE *fp;
-	Symbol *hide;
-	char *line, *begin, *p;
-	struct input *next;
-};
-#endif
-
-/* error.c */
-extern void error(char *fmt, ...);
-extern void warn(char *fmt, ...);
-extern void unexpected(void);
-extern void errorp(char *fmt, ...);
-extern void cpperror(char *fmt, ...);
-extern Type *deftype(Type *tp);
-
-/* types.c */
-extern int eqtype(Type *tp1, Type *tp2, int eqflag);
-extern Type *ctype(int type, int sign, int size);
-extern Type *mktype(Type *tp, int op, TINT nelem, Type *data[]);
-extern Type *duptype(Type *base);
-extern struct limits *getlimits(Type *tp);
-extern void typesize(Type *tp);
-extern void flushtypes(void);
-
-/* symbol.c */
-extern void dumpstab(Symbol **tbl, char *msg);
-extern Symbol *lookup(int ns, char *name, int alloc);
-extern Symbol *nextsym(Symbol *sym, int ns);
-extern Symbol *install(int ns, Symbol *sym);
-extern Symbol *newsym(int ns, char *name);
-extern void pushctx(void), popctx(void);
-extern void killsym(Symbol *sym);
-extern Symbol *newlabel(void);
-extern void keywords(struct keyword *key, int ns);
-extern void builtins(struct builtin *builts);
-extern Symbol *newstring(char *s, size_t len);
-extern unsigned newid(void);
-
-/* stmt.c */
-extern void compound(Symbol *lbreak, Symbol *lcont, Switch *sw);
-
-/* decl.c */
-extern Type *typename(void);
-extern void decl(void);
-
-/* lex.c */
-extern int ahead(void);
-extern int next(void);
-extern void expect(int tok);
-extern void discard(void);
-extern void addinput(char *fname, Symbol *hide, char *buffer);
-extern void delinput(void);
-extern void setsafe(int type);
-extern void ilex(void);
-extern void setloc(char *fname, unsigned line);
-#define accept(t) ((yytoken == (t)) ? next() : 0)
-
-/* code.c */
-extern void prtree(Node *np);
-extern void emit(int, void *);
-extern Node *node(int op, Type *tp, Node *left, Node *rigth);
-extern Node *varnode(Symbol *sym);
-extern Node *constnode(Symbol *sym);
-extern Node *sizeofnode(Type *tp);
-extern void freetree(Node *np);
-extern void icode(void);
-#define BTYPE(np) ((np)->type->op)
-
-/* fold.c */
-extern Node *simplify(Node *np);
-extern TUINT ones(int nbytes);
-
-/* expr.c */
-extern Node *decay(Node *), *negate(Node *np), *assign(void);
-extern Node *convert(Node *np, Type *tp1, int iscast);
-extern Node *constexpr(void), *condexpr(int neg), *expr(void);
-extern int isnodecmp(int op);
-extern int negop(int op);
-extern int cmpnode(Node *np, TUINT val);
-
-/* init.c */
-extern void initializer(Symbol *sym, Type *tp);
-extern Node *initlist(Type *tp);
-
-/* cpp.c */
-extern void icpp(void);
-extern int cpp(void);
-extern int expand(char *begin, Symbol *sym);
-extern void incdir(char *dir);
-extern void outcpp(void);
-extern void defdefine(char *macro, char *val, char *source);
-extern void undefmacro(char *s);
-extern void ppragmaln(void);
-
-/* builtin.c */
-extern void ibuilts(void);
-
-/* arch.c */
-extern void iarch(void);
-extern int valid_va_list(Type *tp);
-
-/*
- * Definition of global variables
- */
-extern struct yystype yylval;
-extern char yytext[];
-extern int yytoken;
-extern unsigned short yylen;
-extern int disexpand;
-extern unsigned cppctx;
-extern Input *input;
-extern int lexmode, namespace;
-extern int onlycpp, onlyheader;
-extern unsigned curctx;
-extern Symbol *curfun, *zero, *one;
-extern char *infile;
-extern unsigned lineno;
-extern char filenam[];
-
-extern Type *voidtype, *pvoidtype, *booltype,
-            *uchartype,   *chartype, *schartype,
-            *uinttype,    *inttype,
-            *sizettype, *pdifftype,
-            *ushortype,   *shortype,
-            *longtype,    *ulongtype,
-            *ullongtype,  *llongtype,
-            *floattype,   *doubletype,  *ldoubletype,
-            *ellipsistype, *va_list_type, *va_type;
--- a/src/cmd/scc/cc1/code.c
+++ /dev/null
@@ -1,549 +1,0 @@
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-
-#include <scc/scc.h>
-#include "cc1.h"
-
-static void emitbin(int, void *),
-            emitcast(int, void *),
-            emitsym(int, void *),
-            emitexp(int, void *),
-            emitsymid(int, void *),
-            emittext(int, void *),
-            emitfun(int, void *),
-            emitdcl(int, void *),
-            emitinit(int, void *),
-            emittype(int, void *),
-            emitbuilt(int, void *);
-
-char *optxt[] = {
-	[OADD] = "+",
-	[OSUB] = "-",
-	[OMUL] = "*",
-	[OINC] = ":i",
-	[ODEC] =  ":d",
-	[OPTR] = "@",
-	[OMOD] = "%",
-	[ODIV] = "/",
-	[OSHL] = "l",
-	[OSHR]  = "r",
-	[OLT] = "<",
-	[OGT] = ">",
-	[OGE] = "]",
-	[OLE] =  "[",
-	[OEQ] = "=",
-	[ONE] = "!",
-	[OBAND] = "&",
-	[OBXOR]  = "^",
-	[OBOR] = "|",
-	[OASSIGN] = ":",
-	[OA_MUL] = ":*",
-	[OA_DIV] = ":/",
-	[OA_MOD] = ":%",
-	[OA_ADD] = ":+",
-	[OA_SUB] = ":-",
-	[OA_SHL] = ":l",
-	[OA_SHR] = ":r",
-	[OA_AND] = ":&",
-	[OA_XOR] = ":^",
-	[OA_OR] = ":|",
-	[OADDR] = "'",
-	[OSNEG] = "_",
-	[ONEG] = "n",
-	[OCPL] = "~",
-	[OAND] = "a",
-	[OOR] = "o",
-	[OASK] = "?",
-	[OCOMMA] = ",",
-	[OLABEL] = "L%d\n",
-	[ODEFAULT] = "\tf\tL%d\n",
-	[OBSWITCH] = "\ts",
-	[OESWITCH] = "\tt\tL%d\n",
-	[OCASE] = "\tv\tL%d",
-	[OJUMP] = "\tj\tL%d\n",
-	[OBRANCH] = "\ty\tL%d",
-	[OEFUN] = "}\n",
-	[OELOOP] = "\tb\n",
-	[OBLOOP] = "\te\n",
-	[ORET] = "\th",
-	[OPAR] = "p",
-	[OCALL] = "c",
-	[OCALLE] = "z",
-	[OFIELD] = "."
-};
-
-void (*opcode[])(int, void *) = {
-	[OADD] = emitbin,
-	[OSUB] = emitbin,
-	[OMUL] = emitbin,
-	[OINC] = emitbin,
-	[ODEC] =  emitbin,
-	[OPTR] = emitbin,
-	[OMOD] = emitbin,
-	[ODIV] = emitbin,
-	[OSHL] = emitbin,
-	[OSHR]  = emitbin,
-	[OLT] = emitbin,
-	[OGT] = emitbin,
-	[OGE] = emitbin,
-	[OLE] =  emitbin,
-	[OEQ] = emitbin,
-	[ONE] = emitbin,
-	[OBAND] = emitbin,
-	[OBXOR]  = emitbin,
-	[OBOR] = emitbin,
-	[OASSIGN] = emitbin,
-	[OA_MUL] = emitbin,
-	[OA_DIV] = emitbin,
-	[OA_MOD] = emitbin,
-	[OA_ADD] = emitbin,
-	[OA_SUB] = emitbin,
-	[OA_SHL] = emitbin,
-	[OA_SHR] = emitbin,
-	[OA_AND] = emitbin,
-	[OA_XOR] = emitbin,
-	[OA_OR] = emitbin,
-	[OADDR] = emitbin,
-	[OSNEG] = emitbin,
-	[ONEG] = emitbin,
-	[OCPL] = emitbin,
-	[OAND] = emitbin,
-	[OOR] = emitbin,
-	[OCOMMA] = emitbin,
-	[OCAST] = emitcast,
-	[OSYM] = emitsym,
-	[OASK] = emitbin,
-	[OCOLON] = emitbin,
-	[OFIELD]= emitbin,
-	[OEXPR] = emitexp,
-	[OLABEL] = emitsymid,
-	[ODEFAULT] = emitsymid,
-	[OCASE] = emitsymid,
-	[OJUMP] = emitsymid,
-	[OBRANCH] = emitsymid,
-	[OEFUN] = emittext,
-	[OELOOP] = emittext,
-	[OBLOOP] = emittext,
-	[OFUN] = emitfun,
-	[ORET] = emittext,
-	[ODECL] = emitdcl,
-	[OBSWITCH] = emittext,
-	[OESWITCH] = emitsymid,
-	[OPAR] = emitbin,
-	[OCALL] = emitbin,
-	[OCALLE] = emitbin,
-	[OINIT] = emitinit,
-	[OBUILTIN] = emitbuilt,
-	[OTYP] = emittype,
-};
-
-static FILE *outfp;
-
-void
-icode(void)
-{
-	outfp = stdout;
-}
-
-void
-freetree(Node *np)
-{
-	if (!np)
-		return;
-	freetree(np->left);
-	freetree(np->right);
-	free(np);
-}
-
-static void
-emitnode(Node *np)
-{
-	if (np)
-		(*opcode[np->op])(np->op, np);
-}
-
-void
-prtree(Node *np)
-{
-	outfp = stderr;
-	fputs("DBG prtree", outfp);
-	emitnode(np);
-	putc('\n', outfp);
-	outfp = stdout;
-}
-
-void
-emit(int op, void *arg)
-{
-	extern int failure;
-
-	if (failure || onlycpp || onlyheader)
-		return;
-	(*opcode[op])(op, arg);
-}
-
-static void
-emitvar(Symbol *sym)
-{
-	int c;
-	short flags = sym->flags;
-
-	if (flags & SLOCAL)
-		c = 'T';
-	else if (flags & SPRIVATE)
-		c =  'Y';
-	else if (flags & SGLOBAL)
-		c = 'G';
-	else if (flags & SREGISTER)
-		c = 'R';
-	else if (flags & SFIELD)
-		c = 'M';
-	else if (flags & SEXTERN)
-		c = 'X';
-	else
-		c = 'A';
-	fprintf(outfp, "%c%u", c, sym->id);
-}
-
-static void
-emitconst(Node *np)
-{
-	Symbol *sym = np->sym;
-	Type *tp = np->type;
-	TUINT u;
-
-	switch (tp->op) {
-	case PTR:
-	case INT:
-	case ENUM:
-		u = (tp->prop & TSIGNED) ? (TUINT) sym->u.i : sym->u.u;
-		fprintf(outfp,
-		        "#%c%llX",
-		        np->type->letter,
-		        (long long) u & ones(tp->size));
-		break;
-	default:
-		abort();
-	}
-}
-
-static void
-emitsym(int op, void *arg)
-{
-	Node *np = arg;
-
-	if ((np->sym->flags & SINITLST) == 0) {
-		/*
-		 * When we have a compound literal we are going
-		 * to call to emitnode for every element of it,
-		 * and it means that we will have two '\t'
-		 * for the first element
-		 */
-		putc('\t', outfp);
-	}
-	(np->flags & NCONST) ? emitconst(np) : emitvar(np->sym);
-}
-
-static void
-emitletter(Type *tp)
-{
-	int letter;
-
-	letter = (tp->prop&TELLIPSIS) ? 'E' : tp->letter;
-	putc(letter, outfp);
-	switch (tp->op) {
-	case ARY:
-	case STRUCT:
-	case UNION:
-		fprintf(outfp, "%u", tp->id);
-	}
-}
-
-static void
-emittype(int op, void *arg)
-{
-	TINT n;
-	Symbol **sp;
-	char *tag;
-	Type *tp = arg;
-
-	if (!(tp->prop & TDEFINED))
-		return;
-
-	switch (tp->op) {
-	case ARY:
-		emitletter(tp);
-		putc('\t', outfp);
-		emitletter(tp->type);
-		fprintf(outfp,
-		        "\t#%c%llX\n",
-		        sizettype->letter, (long long) tp->n.elem);
-		return;
-	case UNION:
-	case STRUCT:
-		emitletter(tp);
-		tag = tp->tag->name;
-		fprintf(outfp,
-		       "\t\"%s\t#%c%lX\t#%c%X\n",
-		       (tag) ? tag : "",
-		       sizettype->letter,
-		       tp->size,
-		       sizettype->letter,
-		       tp->align);
-		n = tp->n.elem;
-		for (sp = tp->p.fields; n-- > 0; ++sp)
-			emit(ODECL, *sp);
-		break;
-	case PTR:
-	case FTN:
-	case ENUM:
-		return;
-	default:
-		abort();
-	}
-}
-
-static void
-emitstring(Symbol *sym, Type *tp)
-{
-	char *bp, *s, *lim;
-	int n;
-
-	bp = sym->u.s;
-	lim = &sym->u.s[tp->n.elem];
-	while (bp < lim) {
-		s = bp;
-		while (bp < lim && isprint(*bp))
-			++bp;
-		if ((n = bp - s) > 1)
-			fprintf(outfp, "\t#\"%.*s\n", n, s);
-		else
-			bp = s;
-		if (bp == lim)
-			break;
-		do {
-			fprintf(outfp,
-			        "\t#%c%02X\n",
-			        chartype->letter, (*bp++) & 0xFF);
-		} while (bp < lim && !isprint(*bp));
-	}
-}
-
-static void
-emitdesig(Node *np, Type *tp)
-{
-	Symbol *sym;
-	size_t n; /* TODO: This should be SIZET */
-	Node *aux;
-	Type *p;
-
-	if (!np) {
-		sym = NULL;
-	} else {
-		if (!np->sym)
-			goto emit_expression;
-		sym = np->sym;
-		if (sym->flags & SSTRING) {
-			emitstring(sym, tp);
-			return;
-		}
-		if ((sym->flags & SINITLST) == 0)
-			goto emit_expression;
-	}
-
-	switch (tp->op) {
-	case PTR:
-	case INT:
-	case ENUM:
-		aux = (sym) ? *sym->u.init : convert(constnode(zero), tp, 0);
-		emitexp(OEXPR, aux);
-		break;
-	case UNION:
-		n = tp->n.elem-1;
-		aux = (sym) ? sym->u.init[0] : NULL;
-		emitdesig(aux, aux->type);
-		break;
-	case STRUCT:
-	case ARY:
-		for (n = 0; n < tp->n.elem; ++n) {
-			aux = (sym) ? sym->u.init[n] : NULL;
-			p = (tp->op == ARY) ? tp->type : tp->p.fields[n]->type;
-			emitdesig(aux, p);
-		}
-		break;
-	default:
-		abort();
-	}
-
-	if (sym) {
-		free(sym->u.init);
-		sym->u.init = NULL;
-	}
-	freetree(np);
-	return;
-
-emit_expression:
-	emitexp(OEXPR, np);
-}
-
-static void
-emitinit(int op, void *arg)
-{
-	Node *np = arg;
-
-	fputs("\t(\n", outfp);
-	emitdesig(np, np->type);
-	fputs(")\n", outfp);
-}
-
-static void
-emitdcl(int op, void *arg)
-{
-	Symbol *sym = arg;
-
-	if (sym->flags & SEMITTED)
-		return;
-	emitvar(sym);
-	putc('\t', outfp);
-	if (sym->type->op == FTN) {
-		emitletter(sym->type->type);
-		putc('\t', outfp);
-	}
-	emitletter(sym->type);
-	fprintf(outfp, "\t\"%s", (sym->name) ? sym->name : "");
-	if (sym->flags & SFIELD)
-		fprintf(outfp, "\t#%c%llX", sizettype->letter, sym->u.i);
-	sym->flags |= SEMITTED;
-	if ((sym->flags & SHASINIT) == 0)
-		putc('\n', outfp);
-}
-
-static void
-emitcast(int op, void *arg)
-{
-	Node *np = arg, *lp = np->left;
-
-	emitnode(lp);
-	if (np->type != voidtype)
-		fprintf(outfp, "\tg%c", np->type->letter);
-}
-
-static void
-emitbin(int op, void *arg)
-{
-	Node *np = arg;
-	char *s;
-
-	emitnode(np->left);
-	emitnode(np->right);
-	if ((s = optxt[op]) != NULL)  {      /* do not print in OCOLON case */
-		fprintf(outfp, "\t%s", s);
-		emitletter(np->type);
-	}
-}
-
-static void
-emitbuilt(int op, void *arg)
-{
-	Node *np = arg;
-
-	emitnode(np->left);
-	emitnode(np->right);
-	fprintf(outfp, "\t\"%s\tm", np->sym->name);
-	emitletter(np->type);
-}
-
-
-static void
-emitexp(int op, void *arg)
-{
-	Node *np = arg;
-
-	emitnode(np);
-	putc('\n', outfp);
-	freetree(np);
-}
-
-static void
-emitfun(int op, void *arg)
-{
-	Symbol *sym = arg, **sp;
-
-	emitdcl(op, arg);
-	fputs("{\n", outfp);
-
-	for (sp = sym->u.pars; sp && *sp; ++sp)
-		emit(ODECL, *sp);
-	fputs("\\\n", outfp);
-}
-
-static void
-emittext(int op, void *arg)
-{
-	fputs(optxt[op], outfp);
-}
-
-static void
-emitsymid(int op, void *arg)
-{
-	Symbol *sym = arg;
-	fprintf(outfp, optxt[op], sym->id);
-}
-
-Node *
-node(int op, Type *tp, Node *lp, Node *rp)
-{
-	Node *np;
-
-	np = xmalloc(sizeof(*np));
-	np->op = op;
-	np->type = tp;
-	np->sym = NULL;
-	np->flags = 0;
-	np->left = lp;
-	np->right = rp;
-
-	if (lp)
-		np->flags |= lp->flags & NEFFECT;
-	if (rp)
-		np->flags |= rp->flags & NEFFECT;
-	return np;
-}
-
-Node *
-varnode(Symbol *sym)
-{
-	Node *np;
-	Type *tp = sym->type;
-
-	np = node(OSYM, sym->type, NULL, NULL);
-	np->type = sym->type;
-	np->flags = (tp->op != FTN && tp->op != ARY) ? NLVAL : 0;
-	np->sym = sym;
-	return np;
-}
-
-Node *
-constnode(Symbol *sym)
-{
-	Node *np;
-
-	np = node(OSYM, sym->type, NULL, NULL);
-	np->type = sym->type;
-	np->flags = NCONST;
-	np->sym = sym;
-	return np;
-}
-
-Node *
-sizeofnode(Type *tp)
-{
-	Symbol *sym;
-
-	sym = newsym(NS_IDEN, NULL);
-	sym->type = sizettype;
-	sym->u.i = tp->size;
-	return constnode(sym);
-}
--- a/src/cmd/scc/cc1/cpp.c
+++ /dev/null
@@ -1,838 +1,0 @@
-#include <ctype.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-#include "cc1.h"
-
-static char *argp, *macroname;
-static unsigned arglen;
-static unsigned ncmdlines;
-static Symbol *symline, *symfile;
-static unsigned char ifstatus[NR_COND];
-static int cppoff;
-static struct items dirinclude;
-
-unsigned cppctx;
-int disexpand;
-
-void
-defdefine(char *macro, char *val, char *source)
-{
-	char *def, *fmt = "#define %s %s\n";
-	Symbol dummy = {.flags = SDECLARED};
-
-	if (!val)
-		val = "";
-	def = xmalloc(strlen(fmt) + strlen(macro) + strlen(val));
-
-	sprintf(def, fmt, macro, val);
-	lineno = ++ncmdlines;
-	addinput(source, &dummy, def);
-	cpp();
-	delinput();
-}
-
-void
-undefmacro(char *s)
-{
-	killsym(lookup(NS_CPP, s, NOALLOC));
-}
-
-void
-icpp(void)
-{
-	static char sdate[14], stime[11];
-	struct tm *tm;
-	time_t t;
-	static char **bp, *list[] = {
-		"__STDC__",
-		"__STDC_HOSTED__",
-		"__SCC__",
-		NULL
-	};
-	static struct keyword keys[] = {
-		{"define", DEFINE, DEFINE},
-		{"include", INCLUDE, INCLUDE},
-		{"line", LINE, LINE},
-		{"ifdef", IFDEF, IFDEF},
-		{"if", IF, IF},
-		{"elif", ELIF, ELIF},
-		{"else", ELSE, ELSE},
-		{"ifndef", IFNDEF, IFNDEF},
-		{"endif", ENDIF, ENDIF},
-		{"undef", UNDEF, UNDEF},
-		{"pragma", PRAGMA, PRAGMA},
-		{"error", ERROR, ERROR},
-		{NULL, 0, 0}
-	};
-
-	keywords(keys, NS_CPPCLAUSES);
-
-	t = time(NULL);
-	tm = localtime(&t);
-	strftime(sdate, sizeof(sdate), "\"%b %d %Y\"", tm);
-	strftime(stime, sizeof(stime), "\"%H:%M:%S\"", tm);
-	defdefine("__DATE__", sdate, "built-in");
-	defdefine("__TIME__", stime, "built-in");
-	defdefine("__STDC_VERSION__", STDC_VERSION, "built-in");
-	defdefine("__LINE__", NULL, "built-in");
-	defdefine("__FILE__", NULL, "built-in");
-
-	symline = lookup(NS_CPP, "__LINE__", ALLOC);
-	symfile = lookup(NS_CPP, "__FILE__", ALLOC);
-
-	for (bp = list; *bp; ++bp)
-		defdefine(*bp, "1", "built-in");
-
-	ncmdlines = 0;
-}
-
-static void
-nextcpp(void)
-{
-	next();
-	if (yytoken == EOFTOK)
-		error("unterminated argument list invoking macro \"%s\"",
-		      macroname);
-	if (yylen + 1 > arglen)
-		error("argument overflow invoking macro \"%s\"",
-		      macroname);
-	if (yytoken == IDEN)
-		yylval.sym->flags |= SUSED;
-	memcpy(argp, yytext, yylen);
-	argp += yylen;
-	*argp++ = ' ';
-	arglen -= yylen + 1;
-}
-
-static void
-paren(void)
-{
-	for (;;) {
-		nextcpp();
-		switch (yytoken) {
-		case ')':
-			return;
-		case '(':
-			paren();
-			break;
-		}
-	}
-}
-
-static void
-parameter(void)
-{
-	for (;;) {
-		nextcpp();
-		switch (yytoken) {
-		case ')':
-		case ',':
-			argp -= 3;  /* remove " , "  or " ) "*/
-			*argp++ = '\0';
-			return;
-		case '(':
-			paren();
-			break;
-		}
-	}
-}
-
-static int
-parsepars(char *buffer, char **listp, int nargs)
-{
-	int n;
-
-	if (nargs == -1)
-		return -1;
-	if (ahead() != '(' && nargs > 0)
-		return 0;
-
-	disexpand = 1;
-	next();
-	n = 0;
-	argp = buffer;
-	arglen = INPUTSIZ;
-	if (ahead() == ')') {
-		next();
-	} else {
-		do {
-			*listp++ = argp;
-			parameter();
-		} while (++n < NR_MACROARG && yytoken == ',');
-	}
-	if (yytoken != ')')
-		error("incorrect macro function-alike invocation");
-	disexpand = 0;
-
-	if (n == NR_MACROARG)
-		error("too many parameters in macro \"%s\"", macroname);
-	if (n != nargs) {
-		error("macro \"%s\" received %d arguments, but it takes %d",
-		      macroname, n, nargs);
-	}
-
-	return 1;
-}
-
-static size_t
-copymacro(char *buffer, char *s, size_t bufsiz, char *arglist[])
-{
-	int delim, prevc, c;
-	char *p, *arg, *bp = buffer;
-	size_t size;
-
-	for (prevc = '\0'; c = *s; prevc = c, ++s) {
-		switch (c) {
-		case '$':
-			while (bp[-1] == ' ')
-				--bp, ++bufsiz;
-			while (s[1] == ' ')
-				++s;
-		case '#':
-			break;
-		case '\'':
-			delim = '\'';
-			goto search_delim;
-		case '\"':
-			delim = '"';
-		search_delim:
-			for (p = s; *++s != delim; )
-				;
-			size = s - p + 1;
-			if (size > bufsiz)
-				goto expansion_too_long;
-			memcpy(bp, p, size);
-			bufsiz -= size;
-			bp += size;
-			break;
-		case '@':
-			if (prevc == '#')
-				bufsiz -= 2;
-			arg = arglist[atoi(++s)];
-			size = strlen(arg);
-			if (size > bufsiz)
-				goto expansion_too_long;
-			if (prevc == '#')
-				*bp++ = '"';
-			memcpy(bp, arg, size);
-			bp += size;
-			if (prevc == '#')
-				*bp++ = '"';
-			bufsiz -= size;
-			s += 2;
-			break;
-		default:
-			if (bufsiz-- == 0)
-				goto expansion_too_long;
-			*bp++ = c;
-			break;
-		}
-	}
-	*bp = '\0';
-
-	return bp - buffer;
-
-expansion_too_long:
-	error("macro expansion of \"%s\" too long", macroname);
-}
-
-int
-expand(char *begin, Symbol *sym)
-{
-	size_t elen;
-	int n, i;
-	char *s = sym->u.s;
-	char *arglist[NR_MACROARG], arguments[INPUTSIZ], buffer[INPUTSIZ];
-
-	macroname = sym->name;
-	if (sym == symfile) {
-		elen = sprintf(buffer, "\"%s\" ", filenam);
-		goto substitute;
-	}
-	if (sym == symline) {
-		elen = sprintf(buffer, "%d ", lineno);
-		goto substitute;
-	}
-	if (!s)
-		return 1;
-
-	n = atoi(s);
-	if (!parsepars(arguments, arglist, n))
-		return 0;
-	for (i = 0; i < n; ++i)
-		DBG("MACRO par%d:%s", i, arglist[i]);
-
-	elen = copymacro(buffer, s+3, INPUTSIZ-1, arglist);
-
-substitute:
-	DBG("MACRO '%s' expanded to :'%s'", macroname, buffer);
-	buffer[elen] = '\0';
-	addinput(filenam, sym, xstrdup(buffer));
-
-	return 1;
-}
-
-static int
-getpars(Symbol *args[NR_MACROARG])
-{
-	int n, c;
-	Symbol *sym;
-
-	c = *input->p;
-	next();
-	if (c != '(')
-		return -1;
-	next(); /* skip the '(' */
-	if (accept(')'))
-		return 0;
-
-	n = 0;
-	do {
-		if (n == NR_MACROARG) {
-			cpperror("too many parameters in macro");
-			return NR_MACROARG;
-		}
-		if (accept(ELLIPSIS)) {
-			args[n++] = NULL;
-			break;
-		}
-		if (yytoken != IDEN) {
-			cpperror("macro arguments must be identifiers");
-			return NR_MACROARG;
-		}
-		sym = install(NS_IDEN, yylval.sym);
-		sym->flags |= SUSED;
-		args[n++] = sym;
-		next();
-	} while (accept(','));
-	expect(')');
-
-	return n;
-}
-
-static int
-getdefs(Symbol *args[NR_MACROARG], int nargs, char *bp, size_t bufsiz)
-{
-	Symbol **argp;
-	size_t len;
-	int prevc = 0, ispar;
-
-	if (yytoken == '$') {
-		cpperror("'##' cannot appear at either ends of a macro expansion");
-		return 0;
-	}
-
-	for (;;) {
-		ispar = 0;
-		if (yytoken == IDEN && nargs >= 0) {
-			for (argp = args; argp < &args[nargs]; ++argp) {
-				if (*argp == yylval.sym)
-					break;
-			}
-			if (argp != &args[nargs]) {
-				sprintf(yytext, "@%02d@", (int) (argp - args));
-				ispar = 1;
-			}
-		}
-		if (prevc == '#' && !ispar) {
-			cpperror("'#' is not followed by a macro parameter");
-			return 0;
-		}
-		if (yytoken == '\n')
-			break;
-
-		if ((len = strlen(yytext)) >= bufsiz) {
-			cpperror("macro too long");
-			return 0;
-		}
-		if (yytoken == '$') {
-			*bp++ = '$';
-			 --bufsiz;
-		} else {
-			memcpy(bp, yytext, len);
-			bp += len;
-			bufsiz -= len;
-		}
-		if ((prevc = yytoken) != '#') {
-			*bp++ = ' ';
-			--bufsiz;
-		}
-		next();
-	}
-	*bp = '\0';
-	return 1;
-}
-
-static void
-define(void)
-{
-	Symbol *sym,*args[NR_MACROARG];
-	char buff[LINESIZ+1];
-	int n;
-
-	if (cppoff)
-		return;
-
-	namespace = NS_CPP;
-	next();
-
-	if (yytoken != IDEN) {
-		cpperror("macro names must be identifiers");
-		return;
-	}
-	sym = yylval.sym;
-	if (sym->flags & SDECLARED) {
-		warn("'%s' redefined", yytext);
-		free(sym->u.s);
-	} else {
-		sym = install(NS_CPP, sym);
-		sym->flags |= SDECLARED|SSTRING;
-	}
-
-	namespace = NS_IDEN;       /* Avoid polution in NS_CPP */
-	if ((n = getpars(args)) == NR_MACROARG)
-		goto delete;
-	if (n > 0 && !args[n-1])  /* it is a variadic function */
-		--n;
-	sprintf(buff, "%02d#", n);
-	if (!getdefs(args, n, buff+3, LINESIZ-3))
-		goto delete;
-	sym->u.s = xstrdup(buff);
-	DBG("MACRO '%s' defined as '%s'", sym->name, buff);
-	return;
-
-delete:
-	killsym(sym);
-}
-
-void
-incdir(char *dir)
-{
-	if (!dir || *dir == '\0')
-		die("cc1: incorrect -I flag");
-	newitem(&dirinclude, dir);
-}
-
-static int
-includefile(char *dir, char *file, size_t filelen)
-{
-	size_t dirlen;
-	char path[FILENAME_MAX];
-
-	if (!dir) {
-		dirlen = 0;
-		if (filelen > FILENAME_MAX-1)
-			return 0;
-	} else {
-		dirlen = strlen(dir);
-		if (dirlen + filelen > FILENAME_MAX-2)
-			return 0;
-		memcpy(path, dir, dirlen);
-		if (dir[dirlen-1] != '/')
-			path[dirlen++] = '/';
-	}
-	memcpy(path+dirlen, file, filelen);
-	path[dirlen + filelen] = '\0';
-
-	addinput(path, NULL, NULL);
-	return 1;
-}
-
-static char *
-cwd(char *buf)
-{
-	char *p, *s = filenam;
-	size_t len;
-
-	if ((p = strrchr(s, '/')) == NULL)
-		return NULL;
-	if ((len = p - s) >= FILENAME_MAX)
-		die("cc1: current work directory too long");
-	memcpy(buf, s, len);
-	buf[len] = '\0';
-	return buf;
-}
-
-static void
-include(void)
-{
-	char dir[FILENAME_MAX], file[FILENAME_MAX], *p, **bp;
-	size_t filelen;
-	int n;
-
-	if (cppoff)
-		return;
-
-	namespace = NS_IDEN;
-	next();
-
-	switch (*yytext) {
-	case '<':
-		if ((p = strchr(input->begin, '>')) == NULL || p[-1] == '<')
-			goto bad_include;
-		filelen = p - input->begin;
-		if (filelen >= FILENAME_MAX)
-			goto too_long;
-		memcpy(file, input->begin, filelen);
-		file[filelen] = '\0';
-
-		input->begin = input->p = p+1;
-		if (next() != '\n')
-			goto trailing_characters;
-
-		break;
-	case '"':
-		if (yylen < 3)
-			goto bad_include;
-		filelen = yylen-2;
-		if (filelen >= FILENAME_MAX)
-			goto too_long;
-		memcpy(file, yytext+1, filelen);
-		file[filelen] = '\0';
-
-		if (next() != '\n')
-			goto trailing_characters;
-
-		if (includefile(cwd(dir), file, filelen))
-			goto its_done;
-		break;
-	default:
-		goto bad_include;
-	}
-
-	n = dirinclude.n;
-	for (bp = dirinclude.s; n--; ++bp) {
-		if (includefile(*bp, file, filelen))
-			goto its_done;
-	}
-	cpperror("included file '%s' not found", file);
-
-its_done:
-	return;
-
-trailing_characters:
-	cpperror("trailing characters after preprocessor directive");
-	return;
-
-too_long:
-	cpperror("too long file name in #include");
-	return;
-
-bad_include:
-	cpperror("#include expects \"FILENAME\" or <FILENAME>");
-	return;
-}
-
-static void
-line(void)
-{
-	long n;
-	char *endp, *fname;
-
-	if (cppoff)
-		return;
-
-	disexpand = 0;
-	next();
-	n = strtol(yytext, &endp, 10);
-	if (n <= 0 || n > USHRT_MAX || *endp != '\0') {
-		cpperror("first parameter of #line is not a positive integer");
-		return;
-	}
-
-	next();
-	if (yytoken == '\n') {
-		fname = NULL;
-	} else {
-		if (*yytext != '\"' || yylen == 1) {
-			cpperror("second parameter of #line is not a valid filename");
-			return;
-		}
-		fname = yylval.sym->u.s;
-	}
-	setloc(fname, n - 1);
-	if (yytoken != '\n')
-		next();
-}
-
-static void
-pragma(void)
-{
-	if (cppoff)
-		return;
-	next();
-	warn("ignoring pragma '%s'", yytext);
-	*input->p = '\0';
-	next();
-}
-
-static void
-usererr(void)
-{
-	if (cppoff)
-		return;
-	cpperror("#error %s", input->p);
-	*input->p = '\0';
-	next();
-}
-
-static void
-ifclause(int negate, int isifdef)
-{
-	Symbol *sym;
-	unsigned n;
-	int status;
-	Node *expr;
-
-	if (cppctx == NR_COND-1)
-		error("too many nesting levels of conditional inclusion");
-
-	n = cppctx++;
-	namespace = NS_CPP;
-	next();
-
-	if (isifdef) {
-		if (yytoken != IDEN) {
-			cpperror("no macro name given in #%s directive",
-			         (negate) ? "ifndef" : "ifdef");
-			return;
-		}
-		sym = yylval.sym;
-		next();
-		status = (sym->flags & SDECLARED) != 0;
-		if (!status)
-			killsym(sym);
-	} else {
-		/* TODO: catch recovery here */
-		if ((expr = constexpr()) == NULL) {
-			cpperror("parameter of #if is not an integer constant expression");
-			return;
-		}
-		status = expr->sym->u.i != 0;
-		freetree(expr);
-	}
-
-	if (negate)
-		status = !status;
-	if ((ifstatus[n] = status) == 0)
-		++cppoff;
-}
-
-static void
-cppif(void)
-{
-	disexpand = 0;
-	ifclause(0, 0);
-}
-
-static void
-ifdef(void)
-{
-	ifclause(0, 1);
-}
-
-static void
-ifndef(void)
-{
-	ifclause(1, 1);
-}
-
-static void
-elseclause(void)
-{
-	int status;
-
-	if (cppctx == 0) {
-		cpperror("#else without #ifdef/ifndef");
-		return;
-	}
-
-	status = ifstatus[cppctx-1];
-	ifstatus[cppctx-1] = !status;
-	cppoff += (status) ? 1 : -1;
-}
-
-static void
-cppelse(void)
-{
-	elseclause();
-	next();
-}
-
-static void
-elif(void)
-{
-	elseclause();
-	if (ifstatus[cppctx-1]) {
-		--cppctx;
-		cppif();
-	}
-}
-
-static void
-endif(void)
-{
-	if (cppctx == 0)
-		error("#endif without #if");
-	if (!ifstatus[--cppctx])
-		--cppoff;
-	next();
-}
-
-static void
-undef(void)
-{
-	if (cppoff)
-		return;
-
-	namespace = NS_CPP;
-	next();
-	if (yytoken != IDEN) {
-		error("no macro name given in #undef directive");
-		return;
-	}
-	killsym(yylval.sym);
-	next();
-}
-
-int
-cpp(void)
-{
-	static struct {
-		unsigned char token;
-		void (*fun)(void);
-	} *bp, clauses [] = {
-		{DEFINE, define},
-		{INCLUDE, include},
-		{LINE, line},
-		{IFDEF, ifdef},
-		{IF, cppif},
-		{ELIF, elif},
-		{IFNDEF, ifndef},
-		{ELSE, cppelse},
-		{ENDIF, endif},
-		{UNDEF, undef},
-		{PRAGMA, pragma},
-		{ERROR, usererr},
-		{0, NULL}
-	};
-	int ns;
-	char *p;
-
-	for (p = input->p; isspace(*p); ++p)
-		;
-
-	if (*p != '#')
-		return cppoff;
-	input->p = p+1;
-
-	disexpand = 1;
-	lexmode = CPPMODE;
-	ns = namespace;
-	namespace = NS_CPPCLAUSES;
-	next();
-	namespace = NS_IDEN;
-
-	for (bp = clauses; bp->token && bp->token != yytoken; ++bp)
-		;
-	if (!bp->token) {
-		errorp("incorrect preprocessor directive '%s'", yytext);
-		goto error;
-	}
-
-	DBG("CPP %s", yytext);
-
-	pushctx();              /* create a new context to avoid polish */
-	(*bp->fun)();           /* the current context, and to get all  */
-	popctx();               /* the symbols freed at the  end        */
-
-	/*
-	 * #include changes the content of input->line, so the correctness
-	 * of the line must be checked in the own include(), and we have
-	 * to skip this tests. For the same reason include() is the only
-	 * function which does not prepare the next token
-	 */
-	if (yytoken != '\n' && !cppoff && bp->token != INCLUDE)
-		errorp("trailing characters after preprocessor directive");
-
-error:
-	disexpand = 0;
-	lexmode = CCMODE;
-	namespace = ns;
-
-	return 1;
-}
-
-void
-ppragmaln(void)
-{
-	static char file[FILENAME_MAX];
-	static unsigned nline;
-	char *s;
-
-	putchar('\n');
-	if (strcmp(file, filenam)) {
-		strcpy(file, filenam);
-		s = "#line %u \"%s\"\n";
-	} else if (nline+1 != lineno) {
-		s = "#line %u\n";
-	} else {
-		s = "";
-	}
-	nline = lineno;
-	printf(s, nline, file);
-}
-
-void
-outcpp(void)
-{
-	int c;
-	char *s, *t;
-
-	for (next(); yytoken != EOFTOK; next()) {
-		if (onlyheader)
-			continue;
-		if (yytoken != STRING) {
-			printf("%s ", yytext);
-			continue;
-		}
-		for (s = yytext; c = *s; ++s) {
-			switch (c) {
-			case '\n':
-				t = "\\n";
-				goto print_str;
-			case '\v':
-				t = "\\v";
-				goto print_str;
-			case '\b':
-				t = "\\b";
-				goto print_str;
-			case '\t':
-				t = "\\t";
-				goto print_str;
-			case '\a':
-				t = "\\a";
-			print_str:
-				fputs(t, stdout);
-				break;
-			case '\\':
-				putchar('\\');
-			default:
-				if (!isprint(c))
-					printf("\\x%x", c);
-				else
-					putchar(c);
-				break;
-			}
-		}
-		putchar(' ');
-	}
-	putchar('\n');
-}
-
--- a/src/cmd/scc/cc1/decl.c
+++ /dev/null
@@ -1,966 +1,0 @@
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-#include "cc1.h"
-
-#define NOSCLASS  0
-
-#define NOREP 0
-#define REP 1
-#define QUIET   1
-#define NOQUIET 0
-
-#define NR_DCL_TYP (NR_DECLARATORS+NR_FUNPARAM)
-#define NR_DCL_SYM (NR_DECLARATORS+NR_FUNPARAM+1)
-
-struct declarators {
-	unsigned nr;
-	unsigned ns;
-	struct decl *dcl;
-	unsigned nr_types;
-	Type **tpars;
-	Symbol **pars;
-	struct declarator {
-		unsigned char op;
-		TINT  nelem;
-		Symbol *sym;
-		Type **tpars;
-		Symbol **pars;
-	} d [NR_DECLARATORS];
-};
-
-struct decl {
-	unsigned ns;
-	int sclass;
-	int qualifier;
-	Symbol *sym;
-	Type *type;
-	Type *parent;
-	Symbol **pars;
-	Symbol *bufpars[NR_DCL_SYM];
-	Type *buftpars[NR_DCL_TYP];
-};
-
-
-static void
-endfundcl(Type *tp, Symbol **pars)
-{
-	if (tp->prop&TK_R && *pars)
-		warn("parameter names (without types) in function declaration");
-	/*
-	 * avoid non used warnings in prototypes
-	 */
-	while (*pars)
-		(*pars++)->flags |= SUSED;
-	popctx();
-}
-
-static void
-push(struct declarators *dp, int op, ...)
-{
-	va_list va;
-	unsigned n;
-	struct declarator *p;
-
-	va_start(va, op);
-	if ((n = dp->nr++) == NR_DECLARATORS)
-		error("too many declarators");
-
-	p = &dp->d[n];
-	p->op = op;
-	p->tpars = NULL;
-
-	switch (op) {
-	case ARY:
-		p->nelem = va_arg(va, TINT);
-		break;
-	case KRFTN:
-	case FTN:
-		p->nelem = va_arg(va, unsigned);
-		p->tpars = va_arg(va, Type **);
-		p->pars = va_arg(va, Symbol **);
-		break;
-	case IDEN:
-		p->sym = va_arg(va, Symbol *);
-		break;
-	}
-	va_end(va);
-}
-
-static int
-pop(struct declarators *dp, struct decl *dcl)
-{
-	struct declarator *p;
-
-	if (dp->nr == 0)
-		return 0;
-
-	p = &dp->d[--dp->nr];
-	if (p->op == IDEN) {
-		dcl->sym = p->sym;
-		return 1;
-	}
-
-	if (dcl->type->op == FTN)
-		endfundcl(dcl->type, dcl->pars);
-	dcl->pars = p->pars;
-
-	dcl->type = mktype(dcl->type, p->op, p->nelem, p->tpars);
-	return 1;
-}
-
-static void
-arydcl(struct declarators *dp)
-{
-	Node *np = NULL;
-	TINT n = 0;
-
-	expect('[');
-	if (yytoken != ']') {
-		if ((np = constexpr()) == NULL) {
-			errorp("invalid storage size");
-		} else {
-			if ((n = np->sym->u.i) <= 0) {
-				errorp("array size is not a positive number");
-				n = 1;
-			}
-			freetree(np);
-		}
-	}
-	expect(']');
-
-	push(dp, ARY, n);
-}
-
-static int
-empty(Symbol *sym, Type *tp, int param)
-{
-	if (!sym->name) {
-		sym->type = tp;
-		switch (tp->op) {
-		default:
-			 /* warn if it is not a parameter */
-			if (!param)
-				warn("empty declaration");
-		case STRUCT:
-		case UNION:
-		case ENUM:
-			return 1;
-		}
-	}
-	return 0;
-}
-
-static void
-bad_storage(Type *tp, char *name)
-{
-	if (tp->op != FTN)
-		errorp("incorrect storage class for file-scope declaration");
-	else
-		errorp("invalid storage class for function '%s'", name);
-}
-
-static Symbol *
-redcl(Symbol *sym, Type *tp, int sclass)
-{
-	int flags;
-	char *name = sym->name;
-
-	if (!eqtype(sym->type, tp, 1)) {
-		errorp("conflicting types for '%s'", name);
-		return sym;
-	}
-
-	if (sym->token == TYPEIDEN && sclass != TYPEDEF ||
-	    sym->token != TYPEIDEN && sclass == TYPEDEF) {
-		goto redeclaration;
-	}
-	if (curctx != GLOBALCTX && tp->op != FTN) {
-		/* is it the redeclaration of a local variable? */
-		if ((sym->flags & SEXTERN) && sclass == EXTERN)
-			return sym;
-		goto redeclaration;
-	}
-
-	flags = sym->flags;
-	switch (sclass) {
-	case REGISTER:
-	case AUTO:
-		bad_storage(tp, name);
-		break;
-	case NOSCLASS:
-		if ((flags & SPRIVATE) == 0) {
-			if (flags & SEXTERN)
-				flags &= ~(SEXTERN|SEMITTED);
-			flags |= SGLOBAL;
-			break;
-		}
-		errorp("non-static declaration of '%s' follows static declaration",
-		       name);
-		break;
-	case TYPEDEF:
-		/* Only C11 allows multiple definitions of a typedef. */
-		goto redeclaration;
-	case EXTERN:
-		break;
-	case STATIC:
-		if ((flags & (SGLOBAL|SEXTERN)) == 0) {
-			flags |= SPRIVATE;
-			break;
-		}
-		errorp("static declaration of '%s' follows non-static declaration",
-		       name);
-		break;
-	}
-	sym->flags = flags;
-
-	return sym;
-
-redeclaration:
-	errorp("redeclaration of '%s'", name);
-	return sym;
-}
-
-static Symbol *
-identifier(struct decl *dcl)
-{
-	Symbol *sym = dcl->sym;
-	Type *tp = dcl->type;
-	int sclass = dcl->sclass;
-	char *name = sym->name;
-
-	if (empty(sym, tp, 0))
-		return sym;
-
-	/* TODO: Add warning about ANSI limits */
-	if (!(tp->prop & TDEFINED)                &&
-	    sclass != EXTERN && sclass != TYPEDEF &&
-	    !(tp->op == ARY && yytoken == '=')) {
-		errorp("declared variable '%s' of incomplete type", name);
-	}
-
-	if (tp->op == FTN) {
-		if (sclass == NOSCLASS)
-			sclass = EXTERN;
-		if (!strcmp(name, "main") && tp->type != inttype) {
-			errorp("main shall be defined with a return type of int");
-			errorp("please contact __20h__ on irc.freenode.net (#bitreich-en) via IRC");
-		}
-	}
-
-	if (sym->flags & SDECLARED) {
-		sym = redcl(dcl->sym, tp, sclass);
-	} else {
-		int flags = sym->flags | SDECLARED;
-
-		sym->type = tp;
-
-		switch (sclass) {
-		case REGISTER:
-		case AUTO:
-			if (curctx != GLOBALCTX && tp->op != FTN) {
-				flags |= (sclass == REGISTER) ? SREGISTER : SAUTO;
-				break;
-			}
-			bad_storage(tp, name);
-		case NOSCLASS:
-			if (tp->op == FTN)
-				flags |= SEXTERN;
-			else
-				flags |= (curctx == GLOBALCTX) ? SGLOBAL : SAUTO;
-			break;
-		case EXTERN:
-			flags |= SEXTERN;
-			break;
-		case STATIC:
-			flags |= (curctx == GLOBALCTX) ? SPRIVATE : SLOCAL;
-			break;
-		case TYPEDEF:
-			flags |= STYPEDEF;
-			sym->u.token = sym->token = TYPEIDEN;
-			break;
-		}
-		sym->flags = flags;
-	}
-
-	if (accept('='))
-		initializer(sym, sym->type);
-	if (!(sym->flags & (SGLOBAL|SEXTERN)) && tp->op != FTN)
-		sym->flags |= SDEFINED;
-	if (sym->token == IDEN && tp->op != FTN)
-		emit(ODECL, sym);
-	return sym;
-}
-
-static Symbol *
-parameter(struct decl *dcl)
-{
-	Symbol *sym = dcl->sym;
-	Type *funtp = dcl->parent, *tp = dcl->type;
-	char *name = sym->name;
-	int flags;
-
-	flags = 0;
-	switch (dcl->sclass) {
-	case STATIC:
-	case EXTERN:
-	case AUTO:
-		errorp("bad storage class in function parameter");
-		break;
-	case REGISTER:
-		flags |= SREGISTER;
-		break;
-	case NOSCLASS:
-		flags |= SAUTO;
-		break;
-	}
-
-	switch (tp->op) {
-	case VOID:
-		funtp->n.elem = 1;
-		if (dcl->sclass)
-			errorp("void as unique parameter may not be qualified");
-		return NULL;
-	case ARY:
-		tp = mktype(tp->type, PTR, 0, NULL);
-		break;
-	case FTN:
-		errorp("incorrect function type for a function parameter");
-		return NULL;
-	}
-	if (!empty(sym, tp, 1)) {
-		int isdcl = sym->flags&SDECLARED, isk_r = funtp->prop & TK_R;
-		if (isdcl && !isk_r) {
-			errorp("redefinition of parameter '%s'", name);
-			return NULL;
-		}
-		if (!isdcl && isk_r) {
-			errorp("declaration for parameter '%s' but no such parameter",
-			       sym->name);
-			return NULL;
-		}
-		sym->flags |= SDECLARED;
-	}
-
-	sym->type = tp;
-	sym->flags &= ~(SAUTO|SREGISTER);
-	sym->flags |= flags;
-	return sym;
-}
-
-static Symbol *dodcl(int rep,
-                     Symbol *(*fun)(struct decl *),
-                     unsigned ns,
-                     Type *type);
-
-static int
-krpars(struct declarators *dp)
-{
-	Symbol *sym;
-	int toomany = 0;
-	unsigned npars = 0;
-
-	do {
-		sym = yylval.sym;
-		expect(IDEN);
-		sym->flags |= SAUTO;
-		if ((sym = install(NS_IDEN, sym)) == NULL) {
-			errorp("redefinition of parameter '%s'",
-			       yylval.sym->name);
-			continue;
-		}
-		if (npars < NR_FUNPARAM) {
-			++npars;
-			*dp->pars++ = sym;
-			continue;
-		}
-		if (!toomany)
-		toomany = 1;
-	} while (accept(','));
-
-	return toomany;
-}
-
-static unsigned
-krfun(struct declarators *dp)
-{
-	int toomany = 0;
-
-
-	if (yytoken != ')')
-		toomany = krpars(dp);
-
-	if (dp->nr_types == NR_DCL_TYP) {
-		toomany = 1;
-	} else {
-		++dp->nr_types;
-		*dp->tpars++ = ellipsistype;
-	}
-
-	if (toomany)
-		errorp("too many parameters in function definition");
-	return 1;
-}
-
-static unsigned
-ansifun(struct declarators *dp)
-{
-	Symbol *sym;
-	unsigned npars, ntype, toomany, distoomany, voidpar;
-	Type type, *tp;
-
-	type.n.elem = 0;
-	type.prop = 0;
-	npars = ntype = toomany = distoomany = voidpar = 0;
-
-	do {
-		if (accept(ELLIPSIS)) {
-			if (ntype < 1)
-				errorp("a named argument is requiered before '...'");
-			if (yytoken != ')')
-				errorp("... must be the last parameter");
-			sym = NULL;
-			tp = ellipsistype;
-		} else if ((sym = dodcl(NOREP, parameter, NS_IDEN, &type)) == NULL) {
-			if (type.n.elem == 1 && ntype > 1)
-				voidpar = 1;
-			sym = NULL;
-			tp = NULL;
-		} else {
-			tp = sym->type;
-		}
-
-		if (sym) {
-			if (npars == NR_FUNPARAM) {
-				toomany = 1;
-			} else {
-				npars++;
-				*dp->pars++ = sym;
-			}
-		}
-
-		if (tp) {
-			if (dp->nr_types == NR_DCL_TYP) {
-				toomany = 1;
-			} else {
-				ntype++;
-				dp->nr_types++;
-				*dp->tpars++ = tp;
-			}
-		}
-
-	} while (accept(','));
-
-	if (toomany == 1)
-		errorp("too many parameters in function definition");
-	if (voidpar && ntype > 1)
-		errorp("'void' must be the only parameter");
-	return ntype;
-}
-
-static int
-funbody(Symbol *sym, Symbol *pars[])
-{
-	Type *tp;
-	Symbol **bp, *p;
-
-	if (!sym)
-		return 0;
-	tp = sym->type;
-	if (tp->op != FTN)
-		return 0;
-
-	switch (yytoken) {
-	case '{':
-	case TYPE:
-	case TYPEIDEN:
-		if (curctx != PARAMCTX)
-			errorp("nested function declaration");
-		if (sym && sym->ns == NS_IDEN)
-			break;
-	default:
-		emit(ODECL, sym);
-		endfundcl(tp, pars);
-		return  0;
-	}
-
-	tp->prop |= TFUNDEF;
-	curfun = sym;
-	if (sym->type->prop & TK_R) {
-		while (yytoken != '{') {
-			dodcl(REP, parameter, NS_IDEN, sym->type);
-			expect(';');
-		}
-		for (bp = pars; p = *bp; ++bp) {
-			if (p->type == NULL) {
-				warn("type of '%s' defaults to int", p->name);
-				p->type = inttype;
-			}
-		}
-	}
-	if (sym->flags & STYPEDEF)
-		errorp("function definition declared 'typedef'");
-	if (sym->flags & SDEFINED)
-		errorp("redefinition of '%s'", sym->name);
-	if (sym->flags & SEXTERN) {
-		sym->flags &= ~SEXTERN;
-		sym->flags |= SGLOBAL;
-	}
-	sym->flags |= SDEFINED;
-	sym->flags &= ~SEMITTED;
-	sym->u.pars = pars;
-	emit(OFUN, sym);
-	compound(NULL, NULL, NULL);
-	emit(OEFUN, NULL);
-	popctx();
-	flushtypes();
-	curfun = NULL;
-	return 1;
-}
-
-static void
-fundcl(struct declarators *dp)
-{
-	Type **types = dp->tpars;
-	unsigned ntypes, typefun;
-	Symbol **pars = dp->pars;
-	unsigned (*fun)(struct declarators *);
-
-	pushctx();
-	expect('(');
-	if (yytoken == ')' || yytoken == IDEN) {
-		typefun = KRFTN;
-		fun = krfun;
-	} else {
-		typefun = FTN;
-		fun = ansifun;
-	}
-	ntypes = (*fun)(dp);
-	*dp->pars++= NULL;
-	expect(')');
-
-	push(dp, typefun, ntypes, types, pars);
-}
-
-static void declarator(struct declarators *dp);
-
-static void
-directdcl(struct declarators *dp)
-{
-	Symbol *p, *sym;
-	static int nested;
-
-	if (accept('(')) {
-		if (nested == NR_SUBTYPE)
-			error("too many declarators nested by parentheses");
-		++nested;
-		declarator(dp);
-		--nested;
-		expect(')');
-	} else {
-		if (yytoken == IDEN || yytoken == TYPEIDEN) {
-			sym = yylval.sym;
-			if (p = install(dp->ns, sym)) {
-				sym = p;
-				sym->flags &= ~SDECLARED;
-			}
-			next();
-		} else {
-			sym = newsym(dp->ns, NULL);
-		}
-		push(dp, IDEN, sym);
-	}
-
-	for (;;) {
-		switch (yytoken) {
-		case '(':  fundcl(dp); break;
-		case '[':  arydcl(dp); break;
-		default:   return;
-		}
-	}
-}
-
-static void
-declarator(struct declarators *dp)
-{
-	unsigned  n;
-
-	for (n = 0; accept('*'); ++n) {
-		while (accept(TQUALIFIER))
-			;
-	}
-
-	directdcl(dp);
-
-	while (n--)
-		push(dp, PTR);
-}
-
-static Type *structdcl(void), *enumdcl(void);
-
-static Type *
-specifier(int *sclass, int *qualifier)
-{
-	Type *tp = NULL;
-	unsigned spec, qlf, sign, type, cls, size;
-
-	spec = qlf = sign = type = cls = size = 0;
-
-	for (;;) {
-		unsigned *p = NULL;
-		Type *(*dcl)(void) = NULL;
-
-		switch (yytoken) {
-		case SCLASS:
-			p = &cls;
-			break;
-		case TQUALIFIER:
-			qlf |= yylval.token;
-			next();
-			continue;
-		case TYPEIDEN:
-			if (type)
-				goto return_type;
-			tp = yylval.sym->type;
-			p = &type;
-			break;
-		case TYPE:
-			switch (yylval.token) {
-			case ENUM:
-				dcl = enumdcl;
-				p = &type;
-				break;
-			case STRUCT:
-			case UNION:
-				dcl = structdcl;
-				p = &type;
-				break;
-			case VA_LIST:
-			case VOID:
-			case BOOL:
-			case CHAR:
-			case INT:
-			case FLOAT:
-			case DOUBLE:
-				p = &type;
-				break;
-			case SIGNED:
-			case UNSIGNED:
-				p = &sign;
-				break;
-			case LONG:
-				if (size == LONG) {
-					yylval.token = LLONG;
-					size = 0;
-				}
-			case SHORT:
-				p = &size;
-				break;
-			}
-			break;
-		default:
-			goto return_type;
-		}
-		if (*p)
-			errorp("invalid type specification");
-		*p = yylval.token;
-		if (dcl) {
-			if (size || sign)
-				errorp("invalid type specification");
-			tp = (*dcl)();
-			goto return_type;
-		} else {
-			next();
-		}
-		spec = 1;
-	}
-
-return_type:
-	*sclass = cls;
-	*qualifier = qlf;
-	if (!tp) {
-		if (spec) {
-			tp = ctype(type, sign, size);
-		} else {
-			if (curctx != GLOBALCTX)
-				unexpected();
-			warn("type defaults to 'int' in declaration");
-			tp = inttype;
-		}
-	}
-	return tp;
-}
-
-static Symbol *
-newtag(void)
-{
-	Symbol *sym;
-	int ns, op, tag = yylval.token;
-	static unsigned tpns = NS_STRUCTS;
-
-	ns = namespace;
-	namespace = NS_TAG;
-	next();
-	namespace = ns;
-
-	switch (yytoken) {
-	case IDEN:
-	case TYPEIDEN:
-		sym = yylval.sym;
-		if ((sym->flags & SDECLARED) == 0)
-			install(NS_TAG, yylval.sym);
-		next();
-		break;
-	default:
-		sym = newsym(NS_TAG, NULL);
-		break;
-	}
-	if (!sym->type) {
-		Type *tp;
-
-		if (tpns == NS_STRUCTS + NR_MAXSTRUCTS)
-			error("too many tags declared");
-		tp = mktype(NULL, tag, 0, NULL);
-		tp->ns = tpns++;
-		sym->type = tp;
-		tp->tag = sym;
-		DBG("declared tag '%s' with ns = %d\n",
-		    (sym->name) ? sym->name : "anonymous", tp->ns);
-	}
-
-	if ((op = sym->type->op) != tag &&  op != INT)
-		error("'%s' defined as wrong kind of tag", sym->name);
-	return sym;
-}
-
-static void fieldlist(Type *tp);
-
-static Type *
-structdcl(void)
-{
-	Symbol *sym;
-	Type *tp;
-	static int nested;
-	int ns;
-
-	sym = newtag();
-	tp = sym->type;
-
-	if (!accept('{'))
-		return tp;
-
-	ns = namespace;
-	namespace = tp->ns;
-
-	if (tp->prop & TDEFINED && sym->ctx == curctx)
-		error("redefinition of struct/union '%s'", sym->name);
-
-	if (nested == NR_STRUCT_LEVEL)
-		error("too many levels of nested structure or union definitions");
-
-	++nested;
-	while (yytoken != '}') {
-		fieldlist(tp);
-	}
-	--nested;
-
-	deftype(tp);
-	namespace = ns;
-	expect('}');
-	return tp;
-}
-
-static Type *
-enumdcl(void)
-{
-	Type *tp;
-	Symbol *sym, *tagsym;
-	int ns, val, toomany;
-	unsigned nctes;
-
-	ns = namespace;
-	tagsym = newtag();
-	tp = tagsym->type;
-
-	if (!accept('{'))
-		goto restore_name;
-	if (tp->prop & TDEFINED)
-		errorp("redefinition of enumeration '%s'", tagsym->name);
-	deftype(tp);
-	namespace = NS_IDEN;
-
-	/* TODO: check incorrect values in val */
-	for (nctes = val = 0; yytoken != '}'; ++nctes, ++val) {
-		if (yytoken != IDEN)
-			unexpected();
-		sym = yylval.sym;
-		next();
-		if (nctes == NR_ENUM_CTES && !toomany) {
-			errorp("too many enum constants in a single enum");
-			toomany = 1;
-		}
-		if (accept('=')) {
-			Node *np = constexpr();
-
-			if (np == NULL)
-				errorp("invalid enumeration value");
-			else
-				val = np->sym->u.i;
-			freetree(np);
-		}
-		if ((sym = install(NS_IDEN, sym)) == NULL) {
-			errorp("'%s' redeclared as different kind of symbol",
-			       yytext);
-		} else {
-			sym->u.i = val;
-			sym->flags |= SCONSTANT;
-			sym->type = inttype;
-		}
-		if (!accept(','))
-			break;
-	}
-	expect('}');
-
-restore_name:
-	namespace = ns;
-	return tp;
-}
-
-static Symbol *
-type(struct decl *dcl)
-{
-	Symbol *sym = dcl->sym;
-
-	if (dcl->sclass)
-		error("class storage in type name");
-	if (sym->name)
-		error("unexpected identifier in type name");
-	sym->type = dcl->type;
-
-	return sym;
-}
-
-static Symbol *
-field(struct decl *dcl)
-{
-	static char *anon = "<anonymous>";
-	Symbol *sym = dcl->sym;
-	char *name = (sym->name) ? sym->name : anon;
-	Type *structp = dcl->parent, *tp = dcl->type;
-	TINT n = structp->n.elem;
-	int err = 0;
-
-	if (accept(':')) {
-		Node *np;
-		TINT n;
-
-		if ((np = constexpr()) == NULL) {
-			unexpected();
-			n = 0;
-		} else {
-			n = np->sym->u.i;
-			freetree(np);
-		}
-		if (n == 0 && name != anon)
-			errorp("zero width for bit-field '%s'", name);
-		if (tp != booltype && tp != inttype && tp != uinttype)
-			errorp("bit-field '%s' has invalid type", name);
-		if (n < 0)
-			errorp("negative width in bit-field '%s'", name);
-		else if (n > tp->size*8)
-			errorp("width of '%s' exceeds its type", name);
-	} else if (empty(sym, tp, 0)) {
-		return sym;
-	}
-
-	if (tp->op == FTN) {
-		errorp("invalid type '%s' in struct/union", name);
-		err = 1;
-	}
-	if (dcl->sclass) {
-		errorp("storage class in struct/union field '%s'", name);
-		err = 1;
-	}
-	if (!(tp->prop & TDEFINED)) {
-		error("field '%s' has incomplete type", name);
-		err = 1;
-	}
-	if (err)
-		return sym;
-
-	if (sym->flags & SDECLARED)
-		error("duplicated member '%s'", name);
-	sym->flags |= SFIELD|SDECLARED;
-	sym->type = tp;
-
-	if (n == NR_FIELDS)
-		error("too many fields in struct/union");
-	DBG("New field '%s' in namespace %d\n", name, structp->ns);
-	structp->p.fields = xrealloc(structp->p.fields, ++n * sizeof(*sym));
-	structp->p.fields[n-1] = sym;
-	structp->n.elem = n;
-
-	return sym;
-}
-
-static Symbol *
-dodcl(int rep, Symbol *(*fun)(struct decl *), unsigned ns, Type *parent)
-{
-	Symbol *sym;
-	Type *base;
-	struct decl dcl;
-	struct declarators stack;
-
-	dcl.ns = ns;
-	dcl.parent = parent;
-	base = specifier(&dcl.sclass, &dcl.qualifier);
-
-	do {
-		dcl.type = base;
-		stack.nr_types = stack.nr = 0;
-		stack.tpars = dcl.buftpars;
-		stack.pars = dcl.bufpars;
-		stack.dcl = &dcl;
-		stack.ns = ns;
-
-		declarator(&stack);
-
-		while (pop(&stack, &dcl))
-			;
-		sym = (*fun)(&dcl);
-		if (funbody(sym, dcl.pars))
-			return sym;
-	} while (rep && accept(','));
-
-	return sym;
-}
-
-void
-decl(void)
-{
-	Symbol *sym;
-
-	if (accept(';'))
-		return;
-	sym = dodcl(REP, identifier, NS_IDEN, NULL);
-	if (sym->type->prop & TFUNDEF)
-		return;
-	expect(';');
-}
-
-static void
-fieldlist(Type *tp)
-{
-	if (yytoken != ';')
-		dodcl(REP, field, tp->ns, tp);
-	expect(';');
-}
-
-Type *
-typename(void)
-{
-	return dodcl(NOREP, type, NS_DUMMY, NULL)->type;
-}
--- a/src/cmd/scc/cc1/deps.mk
+++ /dev/null
@@ -1,44 +1,0 @@
-#deps
-./builtin.o: $(INCDIR)/scc/scc/scc.h
-./builtin.o: ./cc1.h
-./code.o: $(INCDIR)/scc/scc/scc.h
-./code.o: ./cc1.h
-./cpp.o: $(INCDIR)/scc/scc/cstd.h
-./cpp.o: $(INCDIR)/scc/scc/scc.h
-./cpp.o: ./cc1.h
-./decl.o: $(INCDIR)/scc/scc/cstd.h
-./decl.o: $(INCDIR)/scc/scc/scc.h
-./decl.o: ./cc1.h
-./error.o: $(INCDIR)/scc/scc/scc.h
-./error.o: ./cc1.h
-./expr.o: $(INCDIR)/scc/scc/cstd.h
-./expr.o: $(INCDIR)/scc/scc/scc.h
-./expr.o: ./cc1.h
-./fold.o: $(INCDIR)/scc/scc/scc.h
-./fold.o: ./cc1.h
-./init.o: $(INCDIR)/scc/scc/cstd.h
-./init.o: $(INCDIR)/scc/scc/scc.h
-./init.o: ./cc1.h
-./lex.o: $(INCDIR)/scc/scc/cstd.h
-./lex.o: $(INCDIR)/scc/scc/scc.h
-./lex.o: ./cc1.h
-./main.o: $(INCDIR)/scc/scc/arg.h
-./main.o: $(INCDIR)/scc/scc/scc.h
-./main.o: ./cc1.h
-./stmt.o: $(INCDIR)/scc/scc/cstd.h
-./stmt.o: $(INCDIR)/scc/scc/scc.h
-./stmt.o: ./cc1.h
-./symbol.o: $(INCDIR)/scc/scc/cstd.h
-./symbol.o: $(INCDIR)/scc/scc/scc.h
-./symbol.o: ./cc1.h
-./target/amd64-sysv/arch.o: $(INCDIR)/scc/scc/scc.h
-./target/amd64-sysv/arch.o: ./target/amd64-sysv/../../cc1.h
-./target/arm64-sysv/arch.o: $(INCDIR)/scc/scc/scc.h
-./target/arm64-sysv/arch.o: ./target/arm64-sysv/../../cc1.h
-./target/i386-sysv/arch.o: $(INCDIR)/scc/scc/scc.h
-./target/i386-sysv/arch.o: ./target/i386-sysv/../../cc1.h
-./target/z80-scc/arch.o: $(INCDIR)/scc/scc/scc.h
-./target/z80-scc/arch.o: ./target/z80-scc/../../cc1.h
-./types.o: $(INCDIR)/scc/scc/cstd.h
-./types.o: $(INCDIR)/scc/scc/scc.h
-./types.o: ./cc1.h
--- a/src/cmd/scc/cc1/error.c
+++ /dev/null
@@ -1,84 +1,0 @@
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <scc/scc.h>
-#include "cc1.h"
-
-#define MAXERRNUM 10
-
-extern int failure;
-static unsigned nerrors;
-
-static void
-warn_error(int flag, char *fmt, va_list va)
-{
-	if (flag == 0)
-		return;
-	fprintf(stderr, "%s:%u: %s: ",
-	       filenam, lineno,
-	       (flag < 0) ? "error" : "warning");
-	vfprintf(stderr, fmt, va);
-	putc('\n', stderr);
-
-	if (flag < 0) {
-		if (!failure)
-			fclose(stdout);
-		failure = 1;
-		if (++nerrors == MAXERRNUM) {
-			fputs("too many errors\n", stderr);
-			exit(1);
-		}
-	}
-}
-
-void
-warn(char *fmt, ...)
-{
-	extern int warnings;
-
-	va_list va;
-	va_start(va, fmt);
-	warn_error(warnings, fmt, va);
-	va_end(va);
-}
-
-void
-error(char *fmt, ...)
-{
-	va_list va;
-
-	va_start(va, fmt);
-	warn_error(-1, fmt, va);
-	va_end(va);
-	exit(1);
-	discard();
-}
-
-void
-errorp(char *fmt, ...)
-{
-	va_list va;
-	va_start(va, fmt);
-	warn_error(-1, fmt, va);
-	va_end(va);
-}
-
-void
-cpperror(char *fmt, ...)
-{
-	va_list va;
-	va_start(va, fmt);
-	warn_error(-1, fmt, va);
-	va_end(va);
-
-	/* discard input until the end of the line */
-	*input->p = '\0';
-	next();
-}
-
-void
-unexpected(void)
-{
-	error("unexpected '%s'", yytext);
-}
--- a/src/cmd/scc/cc1/expr.c
+++ /dev/null
@@ -1,1184 +1,0 @@
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-#include "cc1.h"
-
-#define XCHG(lp, rp, np) (np = lp, lp = rp, rp = np)
-
-static Node *xexpr(void), *xassign(void);
-
-int
-cmpnode(Node *np, TUINT val)
-{
-	Symbol *sym;
-	Type *tp;
-	TUINT mask, nodeval;
-
-	if (!np || !(np->flags & NCONST) || !np->sym)
-		return 0;
-	sym = np->sym;
-	tp = sym->type;
-
-	switch (tp->op) {
-	case PTR:
-	case INT:
-		mask = (val > 1) ? ones(np->type->size) : -1;
-		nodeval = (tp->prop & TSIGNED) ? sym->u.i : sym->u.u;
-		return (nodeval & mask) == (val & mask);
-	case FLOAT:
-		return sym->u.f == val;
-	}
-	return 0;
-}
-
-static Node *
-promote(Node *np)
-{
-	Type *tp;
-	Node *new;
-	struct limits *lim, *ilim;
-
-	tp = np->type;
-
-	switch (tp->op) {
-	case ENUM:
-	case INT:
-		if (tp->n.rank >= inttype->n.rank)
-			return np;
-		lim = getlimits(tp);
-		ilim = getlimits(inttype);
-		tp = (lim->max.i <= ilim->max.i) ? inttype : uinttype;
-		break;
-	case FLOAT:
-		/* TODO: Add support for C99 float math */
-		tp = doubletype;
-		break;
-	default:
-		abort();
-	}
-	if ((new = convert(np, tp, 1)) != NULL)
-		return new;
-	return np;
-}
-
-static void
-arithconv(Node **p1, Node **p2)
-{
-	int to = 0, s1, s2;
-	unsigned r1, r2;
-	Type *tp1, *tp2;
-	Node *np1, *np2;
-	struct limits *lp1, *lp2;
-
-	np1 = promote(*p1);
-	np2 = promote(*p2);
-
-	tp1 = np1->type;
-	tp2 = np2->type;
-
-	if (tp1 == tp2)
-		goto set_p1_p2;
-
-	s1 = (tp1->prop & TSIGNED) != 0;
-	r1 = tp1->n.rank;
-	lp1 = getlimits(tp1);
-
-	s2 = (tp2->prop & TSIGNED) != 0;
-	r2 = tp2->n.rank;
-	lp2 = getlimits(tp2);
-
-	if (s1 == s2 || tp1->op == FLOAT || tp2->op == FLOAT) {
-		to = r1 - r2;
-	} else if (!s1) {
-		if (r1 >= r2 || lp1->max.i >= lp2->max.i)
-			to = 1;
-		else
-			to = -1;
-	} else {
-		if (r2 >= r1 || lp2->max.i >= lp1->max.i)
-			to = -1;
-		else
-			to = 1;
-	}
-
-	if (to > 0)
-		np2 = convert(np2, tp1, 1);
-	else if (to < 0)
-		np1 = convert(np1, tp2, 1);
-		
-set_p1_p2:
-	*p1 = np1;
-	*p2 = np2;
-}
-
-static int
-null(Node *np)
-{
-	if (np->type != pvoidtype || np->op != OCAST)
-		return 0;
-
-	np = np->left;
-	if (np->type != inttype)
-		return 0;
-
-	return cmpnode(np, 0);
-}
-
-static Node *
-chkternary(Node *yes, Node *no)
-{
-	/*
-	 * FIXME:
-	 * We are ignoring type qualifiers here,
-	 * but the standard has strong rules about this.
-	 * take a look to 6.5.15
-	 */
-
-	if (!eqtype(yes->type, no->type, 1)) {
-		if ((yes->type->prop & TARITH) && (no->type->prop & TARITH)) {
-			arithconv(&yes, &no);
-		} else if (yes->type->op != PTR && no->type->op != PTR) {
-			goto wrong_type;
-		} else {
-			/* convert integer 0 to NULL */
-			if ((yes->type->prop & TINTEGER) && cmpnode(yes, 0))
-				yes = convert(yes, pvoidtype, 0);
-			if ((no->type->prop & TINTEGER) && cmpnode(no, 0))
-				no = convert(no, pvoidtype, 0);
-			/*
-			 * At this point the type of both should be
-			 * a pointer to something, or we have don't
-			 * compatible types
-			 */
-			if (yes->type->op != PTR || no->type->op != PTR)
-				goto wrong_type;
-			/*
-			 * If we have a null pointer constant then
-			 * convert to the another type
-			 */
-			if (null(yes))
-				yes = convert(yes, no->type, 0);
-			if (null(no))
-				no = convert(no, yes->type, 0);
-
-			if (!eqtype(yes->type, no->type, 1))
-				goto wrong_type;
-		}
-	}
-	return node(OCOLON, yes->type, yes, no);
-
-wrong_type:
-	errorp("type mismatch in conditional expression");
-	freetree(yes);
-	freetree(no);
-	return constnode(zero);
-}
-
-static void
-chklvalue(Node *np)
-{
-	if (!(np->flags & NLVAL))
-		errorp("lvalue required in operation");
-	if (np->type == voidtype)
-		errorp("invalid use of void expression");
-}
-
-Node *
-decay(Node *np)
-{
-	Node *new;
-	Type *tp = np->type;
-
-	switch (tp->op) {
-	case ARY:
-		tp = tp->type;
-		if (np->op == OPTR) {
-			new = np->left;
-			free(np);
-			new->type = mktype(tp, PTR, 0, NULL);
-			return new;
-		}
-	case FTN:
-		new = node(OADDR, mktype(tp, PTR, 0, NULL), np, NULL);
-		if (np->sym && np->sym->flags & (SGLOBAL|SLOCAL|SPRIVATE))
-			new->flags |= NCONST;
-		return new;
-	default:
-		return np;
-	}
-}
-
-static Node *
-integerop(int op, Node *lp, Node *rp)
-{
-	if (!(lp->type->prop & TINTEGER) || !(rp->type->prop & TINTEGER))
-		error("operator requires integer operands");
-	arithconv(&lp, &rp);
-	return node(op, lp->type, lp, rp);
-}
-
-static Node *
-integeruop(int op, Node *np)
-{
-	if (!(np->type->prop & TINTEGER))
-		error("unary operator requires integer operand");
-	np = promote(np);
-	return node(op, np->type, np, NULL);
-}
-
-static Node *
-numericaluop(int op, Node *np)
-{
-	if (!(np->type->prop & TARITH))
-		error("unary operator requires numerical operand");
-	np = promote(np);
-	return node(op, np->type, np, NULL);
-}
-
-Node *
-convert(Node *np, Type *newtp, int iscast)
-{
-	Type *oldtp = np->type;
-
-	if (eqtype(newtp, oldtp, 0))
-		return np;
-
-	switch (oldtp->op) {
-	case ENUM:
-	case INT:
-	case FLOAT:
-		switch (newtp->op) {
-		case PTR:
-			if (oldtp->op == FLOAT || !cmpnode(np, 0) && !iscast)
-				return NULL;
-		case INT:
-		case FLOAT:
-		case ENUM:
-			break;
-		default:
-			return NULL;
-		}
-		break;
-	case PTR:
-		switch (newtp->op) {
-		case ENUM:
-		case INT:
-		case VOID:
-			if (!iscast)
-				return NULL;
-			break;
-		case PTR:
-			if (eqtype(newtp, oldtp, 1) ||
-			    iscast ||
-			    newtp == pvoidtype || oldtp == pvoidtype) {
-				np->type = newtp;
-				return np;
-			}
-		default:
-			return NULL;
-		}
-		break;
-	default:
-		return NULL;
-	}
-	return node(OCAST, newtp, np, NULL);
-}
-
-static Node *
-parithmetic(int op, Node *lp, Node *rp)
-{
-	Type *tp;
-	Node *size, *np;
-
-	if (lp->type->op != PTR)
-		XCHG(lp, rp, np);
-
-	tp = rp->type;
-	if (tp->op == PTR && !(tp->type->prop & TDEFINED))
-		goto incomplete;
-	tp = lp->type;
-	if (!(tp->type->prop & TDEFINED))
-		goto incomplete;
-	size = sizeofnode(tp->type);
-
-	if (op == OSUB && BTYPE(rp) == PTR) {
-		if ((rp = convert(rp, lp->type, 0)) == NULL)
-			goto incorrect;
-		lp = node(OSUB, pdifftype, lp, rp);
-		return node(ODIV, inttype, lp, size);
-	}
-	if (!(rp->type->prop & TINTEGER))
-		goto incorrect;
-
-	rp = convert(promote(rp), sizettype, 0);
-	rp = node(OMUL, sizettype, rp, size);
-	rp = convert(rp, tp, 1);
-
-	return node(op, tp, lp, rp);
-
-incomplete:
-	errorp("invalid use of undefined type");
-	return lp;
-incorrect:
-	errorp("incorrect arithmetic operands");
-	return lp;
-
-}
-
-static Node *
-arithmetic(int op, Node *lp, Node *rp)
-{
-	Type *ltp = lp->type, *rtp = rp->type;
-
-	if ((ltp->prop & TARITH) && (rtp->prop & TARITH)) {
-		arithconv(&lp, &rp);
-		return node(op, lp->type, lp, rp);
-	} else if ((ltp->op == PTR || rtp->op == PTR)) {
-		switch (op) {
-		case OADD:
-		case OSUB:
-		case OA_ADD:
-		case OA_SUB:
-		case OINC:
-		case ODEC:
-			return parithmetic(op, lp, rp);
-		}
-	}
-	errorp("incorrect arithmetic operands");
-}
-
-static Node *
-pcompare(int op, Node *lp, Node *rp)
-{
-	Node *np;
-
-	if (lp->type->prop & TINTEGER)
-		XCHG(lp, rp, np);
-	else if (eqtype(lp->type, pvoidtype, 1))
-		XCHG(lp, rp, np);
-
-	if ((np = convert(rp, lp->type, 0)) != NULL)
-		rp = np;
-	else
-		errorp("incompatible types in comparison");
-	return convert(node(op, pvoidtype, lp, rp), inttype, 1);
-}
-
-static Node *
-compare(int op, Node *lp, Node *rp)
-{
-	Type *ltp, *rtp;
-
-	ltp = lp->type;
-	rtp = rp->type;
-
-	if (ltp->op == PTR || rtp->op == PTR) {
-		return pcompare(op, rp, lp);
-	} else if ((ltp->prop & TARITH) && (rtp->prop & TARITH)) {
-		arithconv(&lp, &rp);
-		return convert(node(op, lp->type, lp, rp), inttype, 1);;
-	} else {
-		errorp("incompatible types in comparison");
-		freetree(lp);
-		freetree(rp);
-		return constnode(zero);
-	}
-}
-
-int
-negop(int op)
-{
-	switch (op) {
-	case OEQ:  return ONE;
-	case ONE:  return OEQ;
-	case OLT:  return OGE;
-	case OGE:  return OLT;
-	case OLE:  return OGT;
-	case OGT:  return OLE;
-	default:   abort();
-	}
-	return op;
-}
-
-static Node *
-exp2cond(Node *np, int neg)
-{
-	if (np->type->prop & TAGGREG) {
-		errorp("used struct/union type value where scalar is required");
-		return constnode(zero);
-	}
-	switch (np->op) {
-	case ONEG:
-	case OOR:
-	case OAND:
-		return (neg) ? node(ONEG, inttype, np, NULL) : np;
-	case OEQ:
-	case ONE:
-	case OLT:
-	case OGE:
-	case OLE:
-	case OGT:
-		if (neg)
-			np->op = negop(np->op);
-		return np;
-	default:
-		return compare((neg) ?  OEQ : ONE, np, constnode(zero));
-	}
-}
-
-static Node *
-logic(int op, Node *lp, Node *rp)
-{
-	lp = exp2cond(lp, 0);
-	rp = exp2cond(rp, 0);
-	return node(op, inttype, lp, rp);
-}
-
-static Node *
-field(Node *np)
-{
-	Symbol *sym;
-
-	namespace = np->type->ns;
-	next();
-	namespace = NS_IDEN;
-
-	sym = yylval.sym;
-	if (yytoken != IDEN)
-		unexpected();
-	next();
-
-	if (!(np->type->prop & TAGGREG)) {
-		errorp("request for member '%s' in something not a structure or union",
-		      yylval.sym->name);
-		goto free_np;
-	}
-	if ((sym->flags & SDECLARED) == 0) {
-		errorp("incorrect field in struct/union");
-		goto free_np;
-	}
-	np = node(OFIELD, sym->type, np, varnode(sym));
-	np->flags |= NLVAL;
-	return np;
-
-free_np:
-	freetree(np);
-	return constnode(zero);
-}
-
-static Node *
-content(int op, Node *np)
-{
-	if (BTYPE(np) != PTR) {
-		errorp("invalid argument of memory indirection");
-	} else {
-		if (np->op == OADDR) {
-			Node *new = np->left;
-			new->type = np->type->type;
-			free(np);
-			np = new;
-		} else {
-			np = node(op, np->type->type, np, NULL);
-		}
-		np->flags |= NLVAL;
-	}
-	return np;
-}
-
-static Node *
-array(Node *lp, Node *rp)
-{
-	Type *tp;
-	Node *np;
-
-	if (!(lp->type->prop & TINTEGER) && !(rp->type->prop & TINTEGER))
-		error("array subscript is not an integer");
-	np = arithmetic(OADD, lp, rp);
-	tp = np->type;
-	if (tp->op != PTR)
-		errorp("subscripted value is neither array nor pointer");
-	return content(OPTR, np);
-}
-
-static Node *
-assignop(int op, Node *lp, Node *rp)
-{
-	if ((rp = convert(rp, lp->type, 0)) == NULL) {
-		errorp("incompatible types when assigning");
-		return lp;
-	}
-
-	return node(op, lp->type, lp, rp);
-}
-
-static Node *
-incdec(Node *np, int op)
-{
-	Type *tp = np->type;
-	Node *inc;
-
-	chklvalue(np);
-	np->flags |= NEFFECT;
-
-	if (!(tp->prop & TDEFINED)) {
-		errorp("invalid use of undefined type");
-		return np;
-	} else if (tp->op == PTR && !(tp->type->prop & TDEFINED)) {
-		errorp("%s of pointer to an incomplete type",
-		       (op == OINC || op == OA_ADD) ? "increment" : "decrement");
-		return np;
-	} else if (tp->op == PTR || (tp->prop & TARITH)) {
-		inc = constnode(one);
-	} else {
-		errorp("wrong type argument to increment or decrement");
-		return np;
-	}
-	return arithmetic(op, np, inc);
-}
-
-static Node *
-address(int op, Node *np)
-{
-	Node *new;
-
-	/*
-	 * ansi c accepts & applied to a function name, and it generates
-	 * a function pointer
-	 */
-	if (np->op == OSYM) {
-		if (np->type->op == FTN)
-			return decay(np);
-		if (np->type->op == ARY)
-			goto dont_check_lvalue;
-	}
-	chklvalue(np);
-
-dont_check_lvalue:
-	if (np->sym && (np->sym->flags & SREGISTER))
-		errorp("address of register variable '%s' requested", yytext);
-	new = node(op, mktype(np->type, PTR, 0, NULL), np, NULL);
-	if (np->sym && np->sym->flags & (SGLOBAL|SLOCAL|SPRIVATE))
-		new->flags |= NCONST;
-	return new;
-}
-
-static Node *
-negation(int op, Node *np)
-{
-	if (!(np->type->prop & TARITH) && np->type->op != PTR) {
-		errorp("invalid argument of unary '!'");
-		return constnode(zero);
-	}
-	return exp2cond(np, 1);
-}
-
-static Symbol *
-notdefined(Symbol *sym)
-{
-	int isdef;
-
-	if (namespace == NS_CPP && !strcmp(sym->name, "defined")) {
-		disexpand = 1;
-		next();
-		expect('(');
-		sym = yylval.sym;
-		expect(IDEN);
-		expect(')');
-
-		isdef = (sym->flags & SDECLARED) != 0;
-		sym = newsym(NS_IDEN, NULL);
-		sym->type = inttype;
-		sym->flags |= SCONSTANT;
-		sym->u.i = isdef;
-		disexpand = 0;
-		return sym;
-	}
-	errorp("'%s' undeclared", yytext);
-	sym->type = inttype;
-	return install(sym->ns, yylval.sym);
-}
-
-static Symbol *
-adjstrings(Symbol *sym)
-{
-	char *s, *t;
-	size_t len, n;
-	Type *tp;
-
-	tp = sym->type;
-	s = sym->u.s;
-	for (len = strlen(s);; len += n) {
-		next();
-		if (yytoken != STRING)
-			break;
-		t = yylval.sym->u.s;
-		n = strlen(t);
-		s = xrealloc(s, len + n + 1);
-		memcpy(s+len, t, n);
-		s[len + n] = '\0';
-		killsym(yylval.sym);
-	}
-	++len;
-	if (tp->n.elem != len) {
-		sym->type = mktype(chartype, ARY, len, NULL);
-		sym->u.s = s;
-	}
-	return sym;
-}
-
-/*************************************************************
- * grammar functions                                         *
- *************************************************************/
-static Node *
-primary(void)
-{
-	Node *np;
-	Symbol *sym;
-	Node *(*fun)(Symbol *);
-
-	sym = yylval.sym;
-	switch (yytoken) {
-	case STRING:
-		np = constnode(adjstrings(sym));
-		sym->flags |= SHASINIT;
-		emit(ODECL, sym);
-		emit(OINIT, np);
-		return varnode(sym);
-	case BUILTIN:
-		fun = sym->u.fun;
-		next();
-		expect('(');
-		np = (*fun)(sym);
-		expect(')');
-
-		/* do not call to next */
-		return np;
-	case CONSTANT:
-		np = constnode(sym);
-		break;
-	case IDEN:
-		assert((sym->flags & SCONSTANT) == 0);
-		if ((sym->flags & SDECLARED) == 0) {
-			if (namespace == NS_CPP) {
-				np = constnode(zero);
-				break;
-			}
-			sym = notdefined(sym);
-		}
-		sym->flags |= SUSED;
-		np = varnode(sym);
-		break;
-	default:
-		unexpected();
-	}
-	next();
-
-	return np;
-}
-
-static Node *
-arguments(Node *np)
-{
-	int toomany, n, op;
-	Node *par = NULL, *arg;
-	Type *argtype, **targs, *tp = np->type, *rettype;
-
-	if (tp->op == PTR && tp->type->op == FTN) {
-		np = content(OPTR, np);
-		tp = np->type;
-	}
-	if (tp->op != FTN) {
-		targs = (Type *[]) {ellipsistype};
-		n = 1;
-		rettype = inttype;
-		errorp("function or function pointer expected");
-	} else {
-		targs = tp->p.pars;
-		n = tp->n.elem;
-		rettype = tp->type;
-	}
-
-	expect('(');
-	if (yytoken == ')')
-		goto no_pars;
-	toomany = 0;
-
-	do {
-		arg = xassign();
-		argtype = *targs;
-		if (argtype == ellipsistype) {
-			n = 0;
-			switch (arg->type->op) {
-			case INT:
-				arg = promote(arg);
-				break;
-			case FLOAT:
-				if (arg->type == floattype)
-					arg = convert(arg, doubletype, 1);
-				break;
-			}
-			par = node(OPAR, arg->type, par, arg);
-			continue;
-		}
-		if (--n < 0) {
-			if (!toomany)
-				errorp("too many arguments in function call");
-			toomany = 1;
-			continue;
-		}
-		++targs;
-		if ((arg = convert(arg, argtype, 0)) != NULL) {
-			par = node(OPAR, arg->type, par, arg);
-			continue;
-		}
-		errorp("incompatible type for argument %d in function call",
-		       tp->n.elem - n + 1);
-	} while (accept(','));
-
-no_pars:
-	expect(')');
-	if (n > 0 && *targs != ellipsistype)
-		errorp("too few arguments in function call");
-
-	op = (tp->prop&TELLIPSIS) ? OCALLE : OCALL;
-	return node(op, rettype, np, par);
-}
-
-static Node *unary(int);
-
-static Type *
-typeof(Node *np)
-{
-	Type *tp;
-
-	if (np == NULL)
-		unexpected();
-	tp = np->type;
-	freetree(np);
-	return tp;
-}
-
-static Type *
-sizeexp(void)
-{
-	Type *tp;
-
-	expect('(');
-	switch (yytoken) {
-	case TYPE:
-	case TYPEIDEN:
-		tp = typename();
-		break;
-	default:
-		tp = typeof(unary(0));
-		break;
-	}
-	expect(')');
-	return tp;
-}
-
-static Node *
-postfix(Node *lp)
-{
-	Node *rp;
-
-	for (;;) {
-		switch (yytoken) {
-		case '[':
-		case DEC:
-		case INC:
-		case INDIR:
-		case '.':
-		case '(':
-			lp = decay(lp);
-			switch (yytoken) {
-			case '[':
-				next();
-				rp = xexpr();
-				expect(']');
-				lp = array(lp, rp);
-				break;
-			case DEC:
-			case INC:
-				lp = incdec(lp, (yytoken == INC) ? OINC : ODEC);
-				next();
-				break;
-			case INDIR:
-				lp = content(OPTR, lp);
-			case '.':
-				lp = field(lp);
-				break;
-			case '(':
-				lp = arguments(lp);
-				lp->flags |= NEFFECT;
-				break;
-			}
-			break;
-		default:
-			return lp;
-		}
-	}
-}
-
-static Node *
-defined(void)
-{
-	Symbol *sym;
-	int paren;
-
-	disexpand = 1;
-	next();
-	paren = accept('(');
-	if (yytoken != IDEN && yytoken != TYPEIDEN)
-		cpperror("operator 'defined' requires an identifier");
-	if (yytoken == TYPEIDEN || !(yylval.sym->flags & SDECLARED))
-		sym = zero;
-	else
-		sym = one;
-	disexpand = 0;
-	next();
-	if (paren)
-		expect(')');
-	return constnode(sym);
-}
-
-static Node *cast(int);
-
-static Node *
-unary(int needdecay)
-{
-	Node *(*fun)(int, Node *), *np;
-	int op;
-	Type *tp;
-
-	switch (yytoken) {
-	case '!': op = 0;     fun = negation;     break;
-	case '+': op = OADD;  fun = numericaluop; break;
-	case '-': op = OSNEG; fun = numericaluop; break;
-	case '~': op = OCPL;  fun = integeruop;   break;
-	case '&': op = OADDR; fun = address;      break;
-	case '*': op = OPTR;  fun = content;      break;
-	case SIZEOF:
-		next();
-		tp = (yytoken == '(') ? sizeexp() : typeof(unary(0));
-		if (!(tp->prop & TDEFINED))
-			errorp("sizeof applied to an incomplete type");
-		return sizeofnode(tp);
-	case INC:
-	case DEC:
-		op = (yytoken == INC) ? OA_ADD : OA_SUB;
-		next();
-		np = incdec(unary(1), op);
-		goto chk_decay;
-	case IDEN:
-	case TYPEIDEN:
-		if (lexmode == CPPMODE && !strcmp(yylval.sym->name, "defined"))
-			return defined();
-	default:
-		np = postfix(primary());
-		goto chk_decay;
-	}
-
-	next();
-	np = (*fun)(op, cast(op != OADDR));
-
-chk_decay:
-	if (needdecay)
-		np = decay(np);
-	return np;
-}
-
-static Node *
-cast(int needdecay)
-{
-	Node *lp, *rp;
-	Type *tp;
-	static int nested;
-
-	if (!accept('('))
-		return unary(needdecay);
-
-	switch (yytoken) {
-	case TQUALIFIER:
-	case TYPE:
-	case TYPEIDEN:
-		tp = typename();
-		expect(')');
-
-		if (yytoken == '{')
-			return initlist(tp);
-
-		switch (tp->op) {
-		case ARY:
-			error("cast specifies an array type");
-		default:
-			lp = cast(needdecay);
-			if ((rp = convert(lp,  tp, 1)) == NULL)
-				error("bad type conversion requested");
-			rp->flags &= ~NLVAL;
-			rp->flags |= lp->flags & NLVAL;
-		}
-		break;
-	default:
-		if (nested == NR_SUBEXPR)
-			error("too many expressions nested by parentheses");
-		++nested;
-		rp = xexpr();
-		--nested;
-		expect(')');
-		rp = postfix(rp);
-		break;
-	}
-
-	return rp;
-}
-
-static Node *
-mul(void)
-{
-	Node *np, *(*fun)(int, Node *, Node *);
-	int op;
-
-	np = cast(1);
-	for (;;) {
-		switch (yytoken) {
-		case '*': op = OMUL; fun = arithmetic; break;
-		case '/': op = ODIV; fun = arithmetic; break;
-		case '%': op = OMOD; fun = integerop;  break;
-		default: return np;
-		}
-		next();
-		np = (*fun)(op, np, cast(1));
-	}
-}
-
-static Node *
-add(void)
-{
-	int op;
-	Node *np;
-
-	np = mul();
-	for (;;) {
-		switch (yytoken) {
-		case '+': op = OADD; break;
-		case '-': op = OSUB; break;
-		default:  return np;
-		}
-		next();
-		np = arithmetic(op, np, mul());
-	}
-}
-
-static Node *
-shift(void)
-{
-	int op;
-	Node *np;
-
-	np = add();
-	for (;;) {
-		switch (yytoken) {
-		case SHL: op = OSHL; break;
-		case SHR: op = OSHR; break;
-		default:  return np;
-		}
-		next();
-		np = integerop(op, np, add());
-	}
-}
-
-static Node *
-relational(void)
-{
-	int op;
-	Node *np;
-
-	np = shift();
-	for (;;) {
-		switch (yytoken) {
-		case '<': op = OLT; break;
-		case '>': op = OGT; break;
-		case GE:  op = OGE; break;
-		case LE:  op = OLE; break;
-		default:  return np;
-		}
-		next();
-		np = compare(op, np, shift());
-	}
-}
-
-static Node *
-eq(void)
-{
-	int op;
-	Node *np;
-
-	np = relational();
-	for (;;) {
-		switch (yytoken) {
-		case EQ: op = OEQ; break;
-		case NE: op = ONE; break;
-		default: return np;
-		}
-		next();
-		np = compare(op, np, relational());
-	}
-}
-
-static Node *
-bit_and(void)
-{
-	Node *np;
-
-	np = eq();
-	while (accept('&'))
-		np = integerop(OBAND, np, eq());
-	return np;
-}
-
-static Node *
-bit_xor(void)
-{
-	Node *np;
-
-	np = bit_and();
-	while (accept('^'))
-		np = integerop(OBXOR,  np, bit_and());
-	return np;
-}
-
-static Node *
-bit_or(void)
-{
-	Node *np;
-
-	np = bit_xor();
-	while (accept('|'))
-		np = integerop(OBOR, np, bit_xor());
-	return np;
-}
-
-static Node *
-and(void)
-{
-	Node *np;
-
-	np = bit_or();
-	while (accept(AND))
-		np = logic(OAND, np, bit_or());
-	return np;
-}
-
-static Node *
-or(void)
-{
-	Node *np;
-
-	np = and();
-	while (accept(OR))
-		np = logic(OOR, np, and());
-	return np;
-}
-
-static Node *
-ternary(void)
-{
-	Node *cond;
-
-	cond = or();
-	while (accept('?')) {
-		Node *ifyes, *ifno, *np;
-
-		cond = exp2cond(cond, 0);
-		ifyes = xexpr();
-		expect(':');
-		ifno = ternary();
-		np = chkternary(ifyes, ifno);
-		cond = node(OASK, np->type, cond, np);
-	}
-	return cond;
-}
-
-static Node *
-xassign(void)
-{
-	Node *np, *(*fun)(int , Node *, Node *);
-	int op;
-
-	np = ternary();
-	for (;;) {
-		switch (yytoken) {
-		case '=':    op = OASSIGN; fun = assignop;   break;
-		case MUL_EQ: op = OA_MUL;  fun = arithmetic; break;
-		case DIV_EQ: op = OA_DIV;  fun = arithmetic; break;
-		case MOD_EQ: op = OA_MOD;  fun = integerop;  break;
-		case ADD_EQ: op = OA_ADD;  fun = arithmetic; break;
-		case SUB_EQ: op = OA_SUB;  fun = arithmetic; break;
-		case SHL_EQ: op = OA_SHL;  fun = integerop;  break;
-		case SHR_EQ: op = OA_SHR;  fun = integerop;  break;
-		case AND_EQ: op = OA_AND;  fun = integerop;  break;
-		case XOR_EQ: op = OA_XOR;  fun = integerop;  break;
-		case OR_EQ:  op = OA_OR;   fun = integerop;  break;
-		default: return np;
-		}
-		chklvalue(np);
-		np->flags |= NEFFECT;
-		next();
-		np = (fun)(op, np, assign());
-	}
-}
-
-static Node *
-xexpr(void)
-{
-	Node *lp, *rp;
-
-	lp = xassign();
-	while (accept(',')) {
-		rp = xassign();
-		lp = node(OCOMMA, rp->type, lp, rp);
-	}
-	return lp;
-}
-
-Node *
-assign(void)
-{
-	return simplify(xassign());
-}
-
-Node *
-constexpr(void)
-{
-	Node *np;
-
-	np = ternary();
-	if (np && np->type->op == INT) {
-		np = simplify(convert(np, inttype, 0));
-		if (np->flags & NCONST)
-			return np;
-	}
-	freetree(np);
-	return NULL;
-}
-
-Node *
-expr(void)
-{
-	return simplify(xexpr());
-}
-
-Node *
-condexpr(int neg)
-{
-	Node *np;
-
-	np = exp2cond(xexpr(), neg);
-	if (np->flags & NCONST)
-		warn("conditional expression is constant");
-	return simplify(np);
-}
--- a/src/cmd/scc/cc1/fold.c
+++ /dev/null
@@ -1,684 +1,0 @@
-#include <assert.h>
-#include <stdlib.h>
-
-#include <scc/scc.h>
-#include "cc1.h"
-
-
-TUINT
-ones(int nbytes)
-{
-	return (nbytes == 8) ? -1 : ~(-1ull << nbytes * 8);
-}
-
-static int
-addi(TINT l, TINT r, Type *tp)
-{
-	struct limits *lim = getlimits(tp);
-	TINT max = lim->max.i, min = -lim->min.i;
-
-	if (l < 0 && r < 0 && l >= min - r ||
-	    l == 0 ||
-	    r == 0 ||
-	    l < 0 && r > 0 ||
-	    l > 0 && r < 0 ||
-	    l > 0 && r > 0 && l <= max - r) {
-		return 1;
-	}
-	warn("overflow in constant expression");
-	return 0;
-}
-
-static int
-addf(TFLOAT l, TFLOAT r, Type *tp)
-{
-	struct limits *lim = getlimits(tp);
-	TFLOAT max = lim->max.f, min = lim->min.f;
-
-	if (l < 0 && r < 0 && l >= min - r ||
-	    l == 0 ||
-	    r == 0 ||
-	    l < 0 && r > 0 ||
-	    l > 0 && r < 0 ||
-	    l > 0 && r > 0 && l <= max - r) {
-		return 1;
-	}
-	warn("overflow in constant expression");
-	return 0;
-}
-
-static int
-subi(TINT l, TINT r, Type *tp)
-{
-	return addi(l, -r, tp);
-}
-
-static int
-subf(TFLOAT l, TFLOAT r, Type *tp)
-{
-	return addf(l, -r, tp);
-}
-
-static int
-muli(TINT l, TINT r, Type *tp)
-{
-	struct limits *lim = getlimits(tp);
-	TINT max = lim->max.i, min = -lim->min.i;
-
-	if (l > -1 && l <= 1 ||
-	    r > -1 && r <= 1 ||
-	    l < 0 && r < 0 && -l <= max/-r ||
-	    l < 0 && r > 0 &&  l >= min/r  ||
-	    l > 0 && r < 0 &&  r >= min/l  ||
-	    l > 0 && r > 0 &&  l <= max/r) {
-			return 1;
-	}
-	warn("overflow in constant expression");
-	return 0;
-}
-
-static int
-mulf(TFLOAT l, TFLOAT r, Type *tp)
-{
-	struct limits *lim = getlimits(tp);
-	TFLOAT max = lim->max.f, min = lim->min.f;
-
-	if (l > -1 && l <= 1 ||
-	    r > -1 && r <= 1 ||
-	    l < 0 && r < 0 && -l <= max/-r ||
-	    l < 0 && r > 0 &&  l >= min/r  ||
-	    l > 0 && r < 0 &&  r >= min/l  ||
-	    l > 0 && r > 0 &&  l <= max/r) {
-			return 1;
-	}
-	warn("overflow in constant expression");
-	return 0;
-}
-
-static int
-divi(TINT l, TINT r,  Type *tp)
-{
-	struct limits *lim = getlimits(tp);
-
-	if (r == 0 || l == -lim->min.i && r == -1) {
-		warn("overflow in constant expression");
-		return 0;
-	}
-	return 1;
-}
-
-static int
-divf(TFLOAT l, TFLOAT r,  Type *tp)
-{
-	struct limits *lim = getlimits(tp);
-
-	if (l < 0) l = -l;
-	if (r < 0) r = -r;
-
-	if (r == 0.0 || r < 1.0 && l > lim->max.f * r) {
-		warn("overflow in constant expression");
-		return 0;
-	}
-	return 1;
-}
-
-static int
-lshi(TINT l, TINT r, Type *tp)
-{
-	if (r < 0 || r >= tp->size * 8) {
-		warn("shifting %d bits is undefined", r);
-		return 0;
-	}
-	return muli(l, 1 << r, tp);
-}
-
-static int
-rshi(TINT l, TINT r, Type *tp)
-{
-	if (r < 0 || r >= tp->size * 8) {
-		warn("shifting %d bits is undefined", r);
-		return 0;
-	}
-	return 1;
-}
-
-static int
-foldint(int op, Symbol *res, TINT l, TINT r)
-{
-	TINT i;
-	Type *tp = res->type;
-	int (*validate)(TINT, TINT, Type *tp);
-
-	switch (op) {
-	case OADD: validate = addi; break;
-	case OSUB: validate = subi; break;
-	case OMUL: validate = muli; break;
-	case ODIV: validate = divi; break;
-	case OSHL: validate = lshi; break;
-	case OSHR: validate = rshi; break;
-	case OMOD: validate = divi; break;
-	default:   validate = NULL; break;
-	}
-
-	if (validate && !(*validate)(l, r, tp))
-		return 0;
-
-	switch (op) {
-	case OADD:  i = l + r;  break;
-	case OSUB:  i = l - r;  break;
-	case OMUL:  i = l * r;  break;
-	case ODIV:  i = l / r;  break;
-	case OMOD:  i = l % r;  break;
-	case OSHL:  i = l << r; break;
-	case OSHR:  i = l >> r; break;
-	case OBAND: i = l & r;  break;
-	case OBXOR: i = l ^ r;  break;
-	case OBOR:  i = l | r;  break;
-	case OAND:  i = l && r; break;
-	case OOR:   i = l || r; break;
-	case OLT:   i = l < r;  break;
-	case OGT:   i = l > r;  break;
-	case OGE:   i = l >= r; break;
-	case OLE:   i = l <= r; break;
-	case OEQ:   i = l == r; break;
-	case ONE:   i = l != r; break;
-	case ONEG:  i = !l;     break;
-	case OSNEG: i = -l;     break;
-	case OCPL:  i = ~l;     break;
-	default:    return 0;
-	}
-	res->u.i = i;
-
-	DBG("FOLD i l=%lld %d r=%lld = %lld", l, op, r, i);
-	return 1;
-}
-
-static int
-folduint(int op, Symbol *res, TUINT l, TUINT r)
-{
-	TINT i;
-	TUINT u;
-
-	switch (op) {
-	case OADD:  u = l + r;  break;
-	case OSUB:  u = l - r;  break;
-	case OMUL:  u = l * r;  break;
-	case ODIV:  u = l / r;  break;
-	case OMOD:  u = l % r;  break;
-	case OSHL:  u = l << r; break;
-	case OSHR:  u = l >> r; break;
-	case OBAND: u = l & r;  break;
-	case OBXOR: u = l ^ r;  break;
-	case OBOR:  u = l | r;  break;
-	case ONEG:  u = !l;     break;
-	case OSNEG: u = -l;     break;
-	case OCPL:  u = ~l;     break;
-	case OAND:  i = l && r; goto sign;
-	case OOR:   i = l || r; goto sign;
-	case OLT:   i = l < r;  goto sign;
-	case OGT:   i = l > r;  goto sign;
-	case OGE:   i = l >= r; goto sign;
-	case OLE:   i = l <= r; goto sign;
-	case OEQ:   i = l == r; goto sign;
-	case ONE:   i = l != r; goto sign;
-	default:    return 0;
-	}
-	res->u.u = u & ones(res->type->size);
-
-	DBG("FOLD ui l=%llu %d r=%llu = %llu", l, op, r, u);
-	return 1;
-
-sign:
-	res->u.i = i;
-
-	DBG("FOLD sui %llu %d %llu = %llu", l, op, r, i);
-	return 1;
-}
-
-static int
-foldfloat(int op, Symbol *res, TFLOAT l, TFLOAT r)
-{
-	TFLOAT f;
-	TINT i;
-	int (*validate)(TFLOAT, TFLOAT, Type *tp);
-
-	switch (op) {
-	case OADD: validate = addf; break;
-	case OSUB: validate = subf; break;
-	case OMUL: validate = mulf; break;
-	case ODIV: validate = divf; break;
-	default:   validate = NULL; break;
-	}
-
-	if (validate && !(*validate)(l, r, res->type))
-		return 0;
-
-	switch (op) {
-	case OADD: f = l + r;  break;
-	case OSUB: f = l - r;  break;
-	case OMUL: f = l * r;  break;
-	case ODIV: f = l / r;  break;
-	case OLT:  i = l < r;  goto comparison;
-	case OGT:  i = l > r;  goto comparison;
-	case OGE:  i = l >= r; goto comparison;
-	case OLE:  i = l <= r; goto comparison;
-	case OEQ:  i = l == r; goto comparison;
-	case ONE:  i = l != r; goto comparison;
-	default:   return 0;
-	}
-	res->u.f = f;
-
-	DBG("FOLD f l=%lf %d r=%lf = %lf", l, op, r, f);
-	return 1;
-
-comparison:
-	res->u.i = i;
-
-	DBG("FOLD if l=%lf %d r=%lf = %lld", l, op, r, i);
-	return 1;
-}
-
-static Node *
-foldconst(int type, int op, Type *tp, Symbol *ls, Symbol *rs)
-{
-	Symbol *sym, aux;
-	TINT i;
-	TUINT u;
-	TFLOAT f;
-
-	aux.type = tp;
-	switch (type) {
-	case INT:
-		i = (rs) ? rs->u.i : 0;
-		if (!foldint(op, &aux, ls->u.i, i))
-			return NULL;
-		break;
-	case UNSIGNED:
-		u = (rs) ? rs->u.u : 0u;
-		if (!folduint(op, &aux, ls->u.u, u))
-			return NULL;
-		break;
-	case FLOAT:
-		f = (rs) ? rs->u.f : 0.0;
-		if (!foldfloat(op, &aux, ls->u.f, f))
-			return NULL;
-		break;
-	}
-	sym = newsym(NS_IDEN, NULL);
-	sym->flags |= SCONSTANT;
-	sym->type = tp;
-	sym->u = aux.u;
-	return constnode(sym);
-}
-
-static Node *
-foldcast(Node *np, Node *l)
-{
-	TUINT negmask, mask, u;
-	Type *newtp = np->type, *oldtp = l->type;
-	Symbol aux, *sym, *osym = l->sym;
-
-	if (!(l->flags & NCONST))
-		return np;
-
-	switch (newtp->op) {
-	case PTR:
-	case INT:
-	case ENUM:
-		switch (oldtp->op) {
-		case PTR:
-		case INT:
-		case ENUM:
-			u = (oldtp->prop & TSIGNED) ? osym->u.i : osym->u.u;
-			break;
-		case FLOAT:
-			oldtp = newtp;
-			u = osym->u.f;
-			break;
-		default:
-			return  np;
-		}
-		mask = ones(newtp->size);
-		if (newtp->prop & TSIGNED) {
-			negmask = ~mask;
-			if (u & (negmask >> 1) & mask)
-				u |= negmask;
-			aux.u.i = u;
-		} else {
-			aux.u.u = u & mask;
-		}
-		break;
-	case FLOAT:
-		/* FIXME: The cast can be from another float type */
-		aux.u.f = (oldtp->prop & TSIGNED) ? osym->u.i : osym->u.u;
-		break;
-	default:
-		return np;
-	}
-	DBG("FOLD cast %c->%c", oldtp->letter, newtp->letter);
-	freetree(np);
-	sym = newsym(NS_IDEN, NULL);
-	sym->flags |= SCONSTANT;
-	sym->type = newtp;
-	sym->u = aux.u;
-	return constnode(sym);
-}
-
-static Node *
-foldunary(Node *np, Node *l)
-{
-	int op = l->op;
-	Node *aux;
-
-	switch (np->op) {
-	case ONEG:
-		if (l->op == ONEG)
-			break;
-		return NULL;
-	case OADD:
-		DBG("FOLD unary delete %d", np->op);
-		np->left = NULL;
-		freetree(np);
-		return l;
-	case OCAST:
-		if (op != OCAST)
-			return foldcast(np, l);
-		/* TODO: This is wrong: (float)(int) 7.2 */
-		DBG("FOLD unary collapse %d", np->op);
-		np->left = l->left;
-		l->left = NULL;
-		freetree(l);
-		return np;
-	case OSNEG:
-	case OCPL:
-		if (op != np->op)
-			return NULL;
-		break;
-	case OPTR:
-		if (op != OADDR || np->type != l->left->type)
-			return NULL;
-		break;
-	case OADDR:
-		if (op != OPTR)
-			return NULL;
-		break;
-	default:
-		return NULL;
-	}
-	DBG("FOLD unary cancel %d", np->op);
-	aux = l->left;
-	l->left = NULL;
-	freetree(np);
-	return aux;
-}
-
-static Node *
-fold(Node *np)
-{
-	Symbol *rs, *ls;
-	Type *optype;
-	int type;
-	int op = np->op;
-	Node *p, *lp = np->left, *rp = np->right;
-	Type *tp = np->type;
-
-	assert(lp && rp);
-	if ((op == ODIV || op == OMOD) && cmpnode(rp, 0)) {
-		warn("division by 0");
-		return NULL;
-	}
-	/*
-	 * Return if any of the children is no constant,
-	 * or it is a constant generated when
-	 * the address of a static variable is taken
-	 * (when we don't know the physical address so
-	 * we cannot fold it)
-	 */
-	if (!rp) {
-		rs = NULL;
-	} else {
-		if (!(rp->flags & NCONST) || !rp->sym)
-			return NULL;
-		rs = rp->sym;
-	}
-
-	if (!(lp->flags & NCONST) || !lp->sym)
-		return NULL;
-	optype = lp->type;
-	ls = lp->sym;
-
-	switch (type = optype->op) {
-	case ENUM:
-	case INT:
-		if (!(optype->prop & TSIGNED))
-			type = UNSIGNED;
-	case PTR:
-	case FLOAT:
-		if ((p = foldconst(type, op, tp, ls, rs)) == NULL)
-			return NULL;
-		freetree(np);
-		return p;
-	default:
-		return NULL;
-	}
-}
-
-static void
-commutative(Node *np, Node *l, Node *r)
-{
-	int op = np->op;
-
-	if (r == NULL || r->flags&NCONST || !(l->flags&NCONST))
-		return;
-
-	switch (op) {
-	case OLT:
-	case OGT:
-	case OGE:
-	case OLE:
-		DBG("FOLD neg commutative %d", np->op);
-		np->op = negop(op);
-	case OEQ:
-	case ONE:
-	case OADD:
-	case OMUL:
-	case OBAND:
-	case OBXOR:
-	case OBOR:
-		DBG("FOLD commutative %d", np->op);
-		np->left = r;
-		np->right = l;
-		break;
-	}
-}
-
-static Node *
-identity(Node *np)
-{
-	int iszeror, isoner;
-	int iszerol, isonel;
-	Node *lp = np->left, *rp = np->right;
-
-	if (!rp)
-		return NULL;
-
-	iszeror = cmpnode(rp, 0);
-	isoner = cmpnode(rp, 1),
-	iszerol = cmpnode(lp, 0);
-	isonel = cmpnode(lp, 1);
-
-	switch (np->op) {
-	case OOR:
-		/*
-		 * 1 || i => 1    (free right)
-		 * i || 0 => i    (free right)
-		 * 0 || i => i    (free left)
-		 * i || 1 => i,1  (comma)
-		 */
-		if (isonel | iszeror)
-			goto free_right;
-		if (iszerol)
-			goto free_left;
-		if (isoner)
-			goto change_to_comma;
-		return NULL;
-	case OAND:
-		/*
-		 * 0 && i => 0    (free right)
-		 * i && 1 => i    (free right)
-		 * 1 && i => i    (free left)
-		 * i && 0 => i,0  (comma)
-		 */
-		if (iszerol | isoner)
-			goto free_right;
-		if (isonel)
-			goto free_left;
-		if (iszeror)
-			goto change_to_comma;
-		return NULL;
-	case OSHL:
-	case OSHR:
-		/*
-		 * i >> 0 => i    (free right)
-		 * i << 0 => i    (free right)
-		 * 0 >> i => 0    (free right)
-		 * 0 << i => 0    (free right)
-		 */
-		if (iszeror | iszerol)
-			goto free_right;
-		return NULL;
-	case OBXOR:
-	case OADD:
-	case OBOR:
-	case OSUB:
-		/*
-		 * i + 0  => i
-		 * i - 0  => i
-		 * i | 0  => i
-		 * i ^ 0  => i
-		 */
-		if (iszeror)
-			goto free_right;
-		return NULL;
-	case OMUL:
-		/*
-		 * i * 0  => i,0
-		 * i * 1  => i
-		 */
-		if (iszeror)
-			goto change_to_comma;
-		if (isoner)
-			goto free_right;
-		return NULL;
-	case ODIV:
-		/* i / 1  => i */
-		if (isoner)
-			goto free_right;
-		return NULL;
-	case OBAND:
-		/* i & ~0 => i */
-		if (cmpnode(rp, -1))
-			goto free_right;
-		return NULL;
-	case OMOD:
-		/* i % 1  => i,1 */
-		/* TODO: i % 2^n => i & n-1 */
-		if (isoner)
-			goto change_to_comma;
-	default:
-		return NULL;
-	}
-
-free_right:
-	DBG("FOLD identity %d", np->op);
-	np->left = NULL;
-	freetree(np);
-	return lp;
-
-free_left:
-	DBG("FOLD identity %d", np->op);
-	np->right = NULL;
-	freetree(np);
-	return rp;
-
-change_to_comma:
-	DBG("FOLD identity %d", np->op);
-	np->op = OCOMMA;
-	return np;
-}
-
-static Node *
-foldternary(Node *np, Node *cond, Node *body)
-{
-	if (!(cond->flags & NCONST))
-		return np;
-	if (cmpnode(cond, 0)) {
-		np = body->right;
-		freetree(body->left);
-	} else {
-		np = body->left;
-		freetree(body->right);
-	}
-
-	DBG("FOLD ternary");
-	body->left = NULL;
-	body->right = NULL;
-	freetree(cond);
-	free(body);
-	return np;
-}
-
-/* TODO: fold OCOMMA */
-
-Node *
-simplify(Node *np)
-{
-	Node *p, *l, *r;
-
-	if (!np)
-		return NULL;
-	if (enadebug)
-		prtree(np);
-
-	l = np->left = simplify(np->left);
-	r = np->right = simplify(np->right);
-
-	switch (np->op) {
-	case OASK:
-		return foldternary(np, l, r);
-	case OCALL:
-	case OPAR:
-	case OSYM:
-	case OASSIGN:
-	case OA_MUL:
-	case OA_DIV:
-	case OA_MOD:
-	case OA_ADD:
-	case OA_SUB:
-	case OA_SHL:
-	case OA_SHR:
-	case OA_AND:
-	case OA_XOR:
-	case OA_OR:
-		return np;
-	case OSNEG:
-	case OCPL:
-	case OADDR:
-	case OPTR:
-	case INC:
-	case DEC:
-	case OCAST:
-	case ONEG:
-		assert(!r);
-		if ((p = foldunary(np, l)) != NULL)
-			return p;
-		return np;
-	default:
-		commutative(np, l, r);
-		if ((p = fold(np)) != NULL)
-			return p;
-		if ((p = identity(np)) != NULL)
-			return p;
-		return np;
-	}
-}
--- a/src/cmd/scc/cc1/init.c
+++ /dev/null
@@ -1,377 +1,0 @@
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-#include "cc1.h"
-
-
-typedef struct init Init;
-
-struct designator {
-	TINT pos;
-	Node *expr;
-	struct designator *next;
-};
-
-struct init {
-	TUINT pos;
-	TUINT max;
-	struct designator *tail;
-	struct designator *head;
-};
-
-static TINT
-arydesig(Type *tp, Init *ip)
-{
-	TINT npos;
-	Node *np;
-
-	if (tp->op != ARY)
-		errorp("array index in non-array initializer");
-	next();
-	np = constexpr();
-	npos = np->sym->u.i;
-	if (npos < 0 || (tp->prop & TDEFINED) && npos >= tp->n.elem) {
-		errorp("array index in initializer exceeds array bounds");
-		npos = 0;
-	}
-	freetree(np);
-	expect(']');
-	return npos;
-}
-
-static TINT
-fielddesig(Type *tp, Init *ip)
-{
-	int ons;
-	Symbol *sym, **p;
-
-	if (!(tp->prop & TAGGREG))
-		errorp("field name not in record or union initializer");
-	ons = namespace;
-	namespace = tp->ns;
-	next();
-	namespace = ons;
-	if (yytoken != IDEN)
-		unexpected();
-	sym = yylval.sym;
-	next();
-	if ((sym->flags & SDECLARED) == 0) {
-		errorp("unknown field '%s' specified in initializer",
-		      sym->name);
-		return 0;
-	}
-	for (p = tp->p.fields; *p != sym; ++p)
-		;
-	return p - tp->p.fields;
-}
-
-static Init *
-init(Init *ip)
-{
-	ip->tail = ip->head = NULL;
-	ip->pos = ip->max = 0;
-	return ip;
-}
-
-static Node *
-str2ary(Type *tp)
-{
-	Node *np;
-	Type *btp = tp->type;;
-	Symbol *sym;
-	size_t len;
-	char *s;
-
-	np = assign();
-	sym = np->left->sym;
-	if (btp != chartype && btp != uchartype && btp != schartype) {
-		errorp("array of inappropriate type initialized from string constant");
-		return constnode(zero);
-	}
-
-	len = sym->type->n.elem-1;
-	if (!(tp->prop & TDEFINED)) {
-		tp->n.elem = len+1;
-		deftype(tp);
-	} else if (tp->n.elem < len) {
-		warn("initializer-string for array of chars is too long");
-	}
-
-	len = tp->n.elem;
-	s = sym->u.s;
-	sym = newstring(NULL, len);
-	strncpy(sym->u.s, s, len);
-	np->sym = sym;
-	np->type = sym->type;
-
-	return np;
-}
-
-static Node *
-initialize(Type *tp)
-{
-	Node *np;
-	Symbol *sym;
-
-	if (tp->op == ARY && yytoken == STRING)
-		return str2ary(tp);
-
-	if (yytoken == '{' || tp->op == STRUCT || tp->op == ARY)
-		return initlist(tp);
-
-	np = assign();
-	if (eqtype(tp, np->type, 1))
-		return np;
-
-	np = convert(decay(np), tp, 0);
-	if (!np) {
-		errorp("incorrect initializer");
-		return constnode(zero);
-	}
-
-	return simplify(np);
-}
-
-static Node *
-mkcompound(Init *ip, Type *tp)
-{
-	Node **v, **p;
-	size_t n;
-	struct designator *dp, *next;
-	Symbol *sym;
-
-	if (tp->op == UNION) {
-		Node *np = NULL;
-
-		v = xmalloc(sizeof(*v));
-		for (dp = ip->head; dp; dp = next) {
-			freetree(np);
-			np = dp->expr;
-			next = dp->next;
-			free(dp);
-		}
-		*v = np;
-	} else {
-		n = (tp->prop&TDEFINED) ? tp->n.elem : ip->max;
-		if (n == 0) {
-			v = NULL;
-		} else if (n > SIZE_MAX / sizeof(*v)) {
-			errorp("compound literal too big");
-			return constnode(zero);
-		} else {
-			n *= sizeof(*v);
-			v = memset(xmalloc(n), 0, n);
-
-			for (dp = ip->head; dp; dp = next) {
-				p = &v[dp->pos];
-				freetree(*p);
-				*p = dp->expr;
-				next = dp->next;
-				free(dp);
-			}
-		}
-	}
-
-	sym = newsym(NS_IDEN, NULL);
-	sym->u.init = v;
-	sym->type = tp;
-	sym->flags |= SINITLST;
-
-	return constnode(sym);
-}
-
-static void
-newdesig(Init *ip, Node *np)
-{
-	struct designator *dp;
-
-	dp = xmalloc(sizeof(*dp));
-	dp->pos = ip->pos;
-	dp->expr = np;
-	dp->next = NULL;
-
-	if (ip->head == NULL) {
-		ip->head = ip->tail = dp;
-	} else {
-		ip->tail->next = dp;
-		ip->tail = dp;
-	}
-
-	if (ip->pos+1 > ip->max)
-		ip->max = ip->pos+1;
-}
-
-Node *
-initlist(Type *tp)
-{
-	Init in;
-	Node *np;
-	Type *curtp;
-	int braces, scalar, toomany, outbound;
-	TINT nelem = tp->n.elem;
-	static int depth;
-
-	if (depth == NR_SUBTYPE)
-		error("too many nested initializers");
-	++depth;
-	init(&in);
-	braces = scalar = toomany = 0;
-
-	if (accept('{'))
-		braces = 1;
-
-	do {
-		curtp = inttype;
-		switch (yytoken) {
-		case '[':
-			in.pos = arydesig(tp, &in);
-			curtp = tp->type;
-			goto desig_list;
-		case '.':
-			in.pos = fielddesig(tp, &in);
-			if (in.pos < nelem)
-				curtp = tp->p.fields[in.pos]->type;
-		desig_list:
-			if (yytoken == '[' || yytoken == '.') {
-				np = initlist(curtp);
-				goto new_desig;
-			}
-			expect('=');
-		default:
-			outbound = 0;
-
-			switch (tp->op) {
-			case ARY:
-				curtp = tp->type;
-				if (!(tp->prop & TDEFINED) || in.pos < tp->n.elem)
-					break;
-				if (!toomany)
-					warn("excess elements in array initializer");
-				toomany = 1;
-				outbound = 1;
-				break;
-			case UNION:
-			case STRUCT:
-				if (in.pos < nelem) {
-					curtp = tp->p.fields[in.pos]->type;
-					break;
-				}
-				if (!toomany)
-					warn("excess elements in struct initializer");
-				toomany = 1;
-				outbound = 1;
-				break;
-			default:
-				curtp = tp;
-				if (!scalar)
-					warn("braces around scalar initializer");
-				scalar = 1;
-				if (in.pos == 0)
-					break;
-				if (!toomany)
-					warn("excess elements in scalar initializer");
-				toomany = 1;
-				outbound = 1;
-				break;
-			}
-			np = initialize(curtp);
-			if (outbound) {
-				freetree(np);
-				np = NULL;
-			}
-		}
-
-new_desig:
-		if (np)
-			newdesig(&in, np);
-		if (++in.pos == 0)
-			errorp("compound literal too big");
-		if (nelem == in.pos && !braces)
-			break;
-	} while (accept(','));
-
-	if (braces)
-		expect('}');
-
-
-	if (tp->op == ARY && !(tp->prop & TDEFINED)) {
-		tp->n.elem = in.max;
-		deftype(tp);
-	}
-	if (in.max == 0) {
-		errorp("empty braced initializer");
-		return constnode(zero);
-	}
-
-	return mkcompound(&in, tp);
-}
-
-static void
-autoinit(Symbol *sym, Node *np)
-{
-	Symbol *hidden;
-	Type *tp = sym->type;
-	size_t n; /* FIXME: It should be SIZET */
-
-repeat:
-	switch (tp->op) {
-	case UNION:
-		np = np->sym->u.init[0];
-		tp = np->type;
-		goto repeat;
-	case ARY:
-	case STRUCT:
-		if (!(np->flags & NCONST))
-			abort(); /* TODO */
-		hidden = newsym(NS_IDEN, NULL);
-		hidden->type = sym->type;
-		hidden->flags |= SLOCAL | SHASINIT;
-		emit(ODECL, hidden);
-		emit(OINIT, np);
-		emit(ODECL, sym);
-		emit(OEXPR,
-		     node(OASSIGN, tp, varnode(sym), varnode(hidden)));
-		break;
-	default:
-		emit(ODECL, sym);
-		np = node(OASSIGN, tp, varnode(sym), np);
-		emit(OEXPR, np);
-		break;
-	}
-}
-
-void
-initializer(Symbol *sym, Type *tp)
-{
-	Node *np;
-	int flags = sym->flags;
-
-	if (tp->op == FTN) {
-		errorp("function '%s' initialized like a variable",
-		       sym->name);
-		tp = inttype;
-	}
-	np = initialize(tp);
-
-	if (flags & SDEFINED) {
-		errorp("redeclaration of '%s'", sym->name);
-	} else if ((flags & (SGLOBAL|SLOCAL|SPRIVATE)) != 0) {
-		if (!(np->flags & NCONST)) {
-			errorp("initializer element is not constant");
-			return;
-		}
-		sym->flags |= SHASINIT;
-		sym->flags &= ~SEMITTED;
-		emit(ODECL, sym);
-		emit(OINIT, np);
-		sym->flags |= SDEFINED;
-	} else if ((flags & (SEXTERN|STYPEDEF)) != 0) {
-		errorp("'%s' has both '%s' and initializer",
-		       sym->name, (flags&SEXTERN) ? "extern" : "typedef");
-	} else {
-		autoinit(sym, np);
-	}
-}
--- a/src/cmd/scc/cc1/ir.md
+++ /dev/null
@@ -1,443 +1,0 @@
-# scc intermediate representation #
-
-The scc IR tries to be be a simple and easily parseable intermediate
-representation, and it makes it a bit terse and cryptic. The main
-characteristic of the IR is that all the types and operations are
-represented with only one letter, so parsing tables can be used
-to parse it.
-
-The language is composed of lines, representing statements.
-Each statement is composed of tab-separated fields.
-Declaration statements begin in column 0, expressions and
-control flow begin with a tabulator.
-When the frontend detects an error, it closes the output stream.
-
-## Types ##
-
-Types are represented with uppercase letters:
-
-* C -- signed    8-Bit integer
-* I -- signed   16-Bit integer
-* W -- signed   32-Bit integer
-* Q -- signed   64-Bit integer
-* K -- unsigned  8-Bit integer
-* N -- unsigned 16-Bit integer
-* Z -- unsigned 32-Bit integer
-* O -- unsigned 64-Bit integer
-* 0 -- void
-* P -- pointer
-* F -- function
-* V -- vector
-* U -- union
-* S -- struct
-* B -- bool
-* J -- float
-* D -- double
-* H -- long double
-
-This list has been built for the original Z80 backend, where 'int'
-has the same size as 'short'. Several types (S, F, V, U and others) need
-an identifier after the type letter for better differentiation
-between multiple structs, functions, vectors and unions (S1, V12 ...)
-naturally occuring in a C-program.
-
-## Storage classes ##
-
-The storage classes are represented using uppercase letters:
-
-* A -- automatic
-* R -- register
-* G -- public (global variable declared in the module)
-* X -- extern (global variable declared in another module)
-* Y -- private (variable in file-scope)
-* T -- local (static variable in function-scope)
-* M -- member (struct/union member)
-* L -- label
-
-## Declarations/definitions ##
-
-Variable names are composed of a storage class and an identifier
-(e.g. A1, R2, T3).
-Declarations and definitions are composed of a variable
-name, a type and the name of the variable:
-
-	A1	I	maxweight
-	R2	C	flag
-	A3	S4	statstruct
-
-### Type declarations ###
-
-Some declarations (e.g. structs) involve the declaration of member
-variables.
-Struct members are declared normally after the type declaration in
-parentheses.
-
-For example the struct declaration
-
-	struct foo {
-		int i;
-		long c;
-	} var1;
-
-generates
-
-	S2      foo     (
-	M3      I       i
-	M4      W       c
-	)
-	G5      S2      var1
-
-## Functions ##
-
-A function prototype
-
-	int printf(char *cmd, int flag, void *data);
-
-will generate a type declaration and a variable declaration
-
-	F5	P	I	P
-	X1	F5	printf
-
-The first line gives the function-type specification 'F' with
-an identifier '5' and subsequently lists the types of the
-function parameters.
-The second line declares the 'printf' function as a publicly
-scoped variable.
-
-Analogously, a statically declared function in file scope
-
-	static int printf(char *cmd, int flag, void *data);
-
-generates
-
-	F5      P       I       P
-	T1      F5      printf
-
-Thus, the 'printf' variable  went into local scope ('T').
-
-A '{' in the first column starts the body of the previously
-declared function:
-
-	int printf(char *cmd, int flag, void *data) {}
-
-generates
-
-	F5      P       I       P
-	G1      F5      printf
-	{
-	A2      P       cmd
-	A3      I       flag
-	A4      P       data
-	-
-	}
-
-Again, the frontend must ensure that '{' appears only after the
-declaration of a function. The character '-' marks the separation
-between parameters and local variables:
-
-	int printf(register char *cmd, int flag, void *data) {int i;};
-
-generates
-
-	F5      P       I       P
-	G1      F5      printf
-	{
-	R2      P       cmd
-	A3      I       flag
-	A4      P       data
-	-
-	A6      I       i
-	}
-
-### Expressions ###
-
-Expressions are emitted in reverse polish notation, simplifying
-parsing and converting into a tree representation.
-
-#### Operators ####
-
-Operators allowed in expressions are:
-
-* \+ -- addition
-* \- -- substraction
-* \* -- multiplication
-* % -- modulo
-* / -- division
-* l -- left shift
-* r -- right shift
-* < -- less than
-* > -- greather than
-* ] -- greather or equal than
-* [ -- less or equal than
-* = -- equal than
-* ! -- different than
-* & -- bitwise and
-* | -- bitwise or
-* ^ -- bitwise xor
-* ~ -- bitwise complement
-* : -- asignation
-* _ -- unary negation
-* c -- function call
-* p -- parameter
-* . -- field
-* , -- comma operator
-* ? -- ternary operator
-* ' -- take address
-* a -- logical shortcut and
-* o -- logical shortcut or
-* @ -- content of pointer
-
-Assignation has some suboperators:
-
-* :/ -- divide and assign
-* :% -- modulo and assign
-* :+ -- addition and assign
-* :- -- substraction and assign
-* :l -- left shift and assign
-* :r -- right shift and assign
-* :& -- bitwise and and assign
-* :^ -- bitwise xor and assign
-* :| -- bitwise or and assign
-* :i -- post increment
-* :d -- post decrement
-
-Every operator in an expression has a type descriptor.
-
-#### Constants ####
-
-Constants are introduced with the character '#'. For instance, 10 is
-translated to #IA (all constants are emitted in hexadecimal),
-where I indicates that it is an integer constant.
-Strings are a special case because they are represented with
-the " character.
-The constant "hello" is emitted as "68656C6C6F. For example
-
-	int
-	main(void)
-	{
-		int i, j;
-
-		i = j+2*3;
-	}
-
-generates
-
-	F1
-	G1	F1	main
-	{
-	-
-	A2      I	i
-	A3      I	j
-		A2	A3	#I6	+I	:I
-	}
-
-Type casts are expressed with a tuple denoting the
-type conversion
-
-        int
-	main(void)
-	{
-		int i;
-		long j;
-
-		j = (long)i;
-	}
-
-generates
-
-	F1
-	G1      F1      main
-	{
-	-
-	A2      I       i
-	A3      W       j
-	        A2      A3      WI      :I
-	}
-
-### Statements ###
-#### Jumps #####
-
-Jumps have the following form:
-
-	j	L#	[expression]
-
-the optional expression field indicates some condition which
-must be satisfied to jump. Example:
-
-	int
-	main(void)
-	{
-		int i;
-
-		goto    label;
-	label:
-		i -= i;
-	}
-
-generates
-
-	F1
-	G1      F1      main
-	{
-	-
-	A2	I	i
-		j	L3
-	L3
-		A2	A2	:-I
-	}
-
-Another form of jump is the return statement, which uses the
-letter 'y' followed by a type identifier.
-Depending on the type, an optional expression follows.
-
-	int
-	main(void)
-	{
-		return 16;
-	}
-
-generates
-
-	F1
-	G1	F1	main
-	{
-	-
-		yI	#I10
-	}
-
-
-#### Loops ####
-
-There are two special characters that are used to indicate
-to the backend that the following statements are part of
-a loop body.
-
-* b -- beginning of loop
-* e -- end of loop
-
-#### Switch statement ####
-
-Switches are represented using a table, in which the labels
-where to jump for each case are indicated. Common cases are
-represented with 'v' and default with 'f'.
-The switch statement itself is represented with 's' followed
-by the label where the jump table is located, and the
-expression of the switch:
-
-	int
-	func(int n)
-	{
-		switch (n+1) {
-		case 1:
-		case 2:
-		case 3:
-		default:
-			++n;
-		}
-	}
-
-generates
-
-	F2	I
-	G1	F2	func
-	{
-	A1	I	n
-	-
-		s	L4	A1	#I1	+I
-	L5
-	L6
-	L7
-	L8
-		A1	#I1	:+I
-		j	L3
-	L4
-		t	#4
-		v	L7	#I3
-		v	L6	#I2
-		v	L5	#I1
-		f	L8
-	L3
-	}
-
-The beginning of the jump table is indicated by the the letter 't',
-followed by the number of cases (including default case) of the
-switch.
-
-## Resumen ##
-
-* C -- signed    8-Bit integer
-* I -- signed   16-Bit integer
-* W -- signed   32-Bit integer
-* O -- signed   64-Bit integer
-* M -- unsigned  8-Bit integer
-* N -- unsigned 16-Bit integer
-* Z -- unsigned 32-Bit integer
-* Q -- unsigned 64-Bit integer
-* 0 -- void
-* P -- pointer
-* F -- function
-* V -- vector
-* U -- union
-* S -- struct
-* B -- bool
-* J -- float
-* D -- double
-* H -- long double
-* A -- automatic
-* R -- register
-* G -- public (global variable declared in the module)
-* X -- extern (global variable declared in another module)
-* Y -- private (variable in file-scope)
-* T -- local (static variable in function-scope)
-* M -- member (struct/union member)
-* L -- label
-* { -- beginning of function body
-* } -- end of function body
-* \\ -- end of function parameters
-* \+ -- addition
-* \- -- substraction
-* \* -- multiplication
-* % -- modulo
-* / -- division
-* l -- left shift
-* r -- right shift
-* < -- less than
-* > -- greather than
-* ] -- greather or equal than
-* [ -- less or equal than
-* = -- equal than
-* ! -- different than
-* & -- bitwise and
-* | -- bitwise or
-* ^ -- bitwise xor
-* ~ -- bitwise complement
-* : -- asignation
-* _ -- unary negation
-* c -- function call
-* p -- parameter
-* . -- field
-* , -- comma operator
-* ? -- ternary operator
-* ' -- take address
-* a -- logical shortcut and
-* o -- logical shortcut or
-* @ -- content of pointer
-* :/ -- divide and assign
-* :% -- modulo and assign
-* :+ -- addition and assign
-* :- -- substraction and assign
-* :l -- left shift and assign
-* :r -- right shift and assign
-* :& -- bitwise and and assign
-* :^ -- bitwise xor and assign
-* :| -- bitwise or and assign
-* ;+ -- post increment
-* ;- -- post decrement
-* j -- jump
-* y -- return
-* b -- begin of loop
-* d -- end of loop
-* s -- switch statement
-* t -- switch table
-* v -- case entry in switch table
-* f -- default entry in switch table
--- a/src/cmd/scc/cc1/lex.c
+++ /dev/null
@@ -1,800 +1,0 @@
-#include <assert.h>
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <setjmp.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-#include "cc1.h"
-
-int yytoken;
-struct yystype yylval;
-char yytext[STRINGSIZ+3];
-unsigned short yylen;
-int lexmode = CCMODE;
-unsigned lineno;
-char filenam[FILENAME_MAX];
-
-int namespace = NS_IDEN;
-static int safe;
-Input *input;
-
-void
-ilex(void)
-{
-	static struct keyword keys[] = {
-		{"auto", SCLASS, AUTO},
-		{"break", BREAK, BREAK},
-		{"_Bool", TYPE, BOOL},
-		{"__builtin_va_list", TYPE, VA_LIST},
-		{"case", CASE, CASE},
-		{"char", TYPE, CHAR},
-		{"const", TQUALIFIER, CONST},
-		{"continue", CONTINUE, CONTINUE},
-		{"default", DEFAULT, DEFAULT},
-		{"do", DO, DO},
-		{"double", TYPE, DOUBLE},
-		{"else", ELSE, ELSE},
-		{"enum", TYPE, ENUM},
-		{"extern", SCLASS, EXTERN},
-		{"float", TYPE, FLOAT},
-		{"for", FOR, FOR},
-		{"goto", GOTO, GOTO},
-		{"if", IF, IF},
-		{"inline", TQUALIFIER, INLINE},
-		{"int", TYPE, INT},
-		{"long", TYPE, LONG},
-		{"register", SCLASS, REGISTER},
-		{"restrict", TQUALIFIER, RESTRICT},
-		{"return", RETURN, RETURN},
-		{"short", TYPE, SHORT},
-		{"signed", TYPE, SIGNED},
-		{"sizeof", SIZEOF, SIZEOF},
-		{"static", SCLASS, STATIC},
-		{"struct", TYPE, STRUCT},
-		{"switch", SWITCH, SWITCH},
-		{"typedef", SCLASS, TYPEDEF},
-		{"union", TYPE, UNION},
-		{"unsigned", TYPE, UNSIGNED},
-		{"void", TYPE, VOID},
-		{"volatile", TQUALIFIER, VOLATILE},
-		{"while", WHILE, WHILE},
-		{NULL, 0, 0},
-	};
-	keywords(keys, NS_KEYWORD);
-}
-
-void
-setloc(char *fname, unsigned line)
-{
-	size_t len;
-
-	if ((len = strlen(fname)) >= FILENAME_MAX)
-		die("cc1: %s: file name too long", fname);
-	memmove(filenam, fname, len);
-	filenam[len] = '\0';
-
-	free(input->filenam);
-	input->filenam = xstrdup(fname);
-	lineno = input->lineno = line;
-}
-
-void
-addinput(char *fname, Symbol *hide, char *buffer)
-{
-	FILE *fp;
-	char *extp;
-	unsigned flags;
-	int infileln;
-	Input *newip, *curip = input;
-
-	if (hide) {
-		/* this is a macro expansion */
-		fp = NULL;
-		if (hide->hide == UCHAR_MAX)
-			die("cc1: too many macro expansions");
-		++hide->hide;
-		flags = IMACRO;
-	} else  if (fname) {
-		/* a new file */
-		if ((fp = fopen(fname, "r")) == NULL)
-			die("cc1: %s: %s", fname, strerror(errno));
-		flags = IFILE;
-		if (curip && onlyheader) {
-			infileln = strlen(infile);
-			if (extp = strrchr(infile, '.'))
-				infileln -= strlen(extp);
-			printf("%.*s.o: %s %s\n",
-			       infileln, infile, infile, fname);
-		}
-	} else {
-		/* reading from stdin */
-		fp = stdin;
-		fname = "<stdin>";
-		flags = ISTDIN;
-	}
-
-	newip = xmalloc(sizeof(*newip));
-
-	if (!buffer) {
-		buffer = xmalloc(INPUTSIZ);
-		buffer[0] = '\0';
-	}
-
-	if (curip)
-		curip->lineno = lineno;
-
-	newip->p = newip->begin = newip->line = buffer;
-	newip->filenam = NULL;
-	newip->lineno = 0;
-	newip->next = curip;
-	newip->fp = fp;
-	newip->hide = hide;
-	newip->flags = flags;
-	input = newip;
-
-	setloc(fname, (curip) ? curip->lineno : newip->lineno);
-}
-
-void
-delinput(void)
-{
-	Input *ip = input;
-	Symbol *hide = ip->hide;
-
-	switch (ip->flags & ITYPE) {
-	case IFILE:
-		if (fclose(ip->fp))
-			die("cc1: %s: %s", ip->filenam, strerror(errno));
-		break;
-	case IMACRO:
-		assert(hide->hide == 1);
-		--hide->hide;
-		break;
-	}
-	input = ip->next;
-	free(ip->filenam);
-	free(ip->line);
-	if (input) {
-		lineno = input->lineno;
-		strcpy(filenam, input->filenam);
-	}
-}
-
-static void
-newline(void)
-{
-	if (++lineno == 0)
-		die("cc1: %s: file too long", filenam);
-}
-
-/*
- * Read the next character from the input file, counting number of lines
- * and joining lines escaped with \
- */
-static int
-readchar(void)
-{
-	FILE *fp = input->fp;
-	int c;
-
-repeat:
-	switch (c = getc(fp)) {
-	case '\\':
-		if ((c = getc(fp)) == '\n') {
-			newline();
-			goto repeat;
-		}
-		ungetc(c, fp);
-		c = '\\';
-		break;
-	case '\n':
-		newline();
-		break;
-	default:
-		if (!isprint(c) && !ispunct(c) && !isspace(c))
-			warn("invalid input character. The shame of UB is yours");
-		break;
-	}
-
-	return c;
-}
-
-/*
- * discard a C comment. This function is only called from readline
- * because it is impossible to have a comment in a macro, because
- * comments are always discarded before processing any cpp directive
- */
-static void
-comment(int type)
-{
-	int c;
-
-repeat:
-	while ((c = readchar()) != EOF && c != type)
-		;
-
-	if (c == EOF) {
-		errorp("unterminated comment");
-		return;
-	}
-
-	if (type == '*' && (c = readchar()) != '/')
-		goto repeat;
-}
-
-/*
- * readline is used to read a full logic line from a file.
- * It discards comments and check that the line fits in
- * the input buffer
- */
-static int
-readline(void)
-{
-	char *bp, *lim;
-	int c, peekc = 0;
-
-	if (feof(input->fp)) {
-		input->flags |= IEOF;
-		return 0;
-	}
-
-	*input->line = '\0';
-	lim = &input->line[INPUTSIZ-1];
-	for (bp = input->line; bp < lim-1; *bp++ = c) {
-		c = (peekc) ? peekc : readchar();
-		peekc = 0;
-		if (c == '\n' || c == EOF)
-			break;
-		if (c != '/')
-			continue;
-
-		/* check for /* or // */
-		peekc = readchar();
-		if (peekc != '*' && peekc != '/')
-			continue;
-		comment((peekc == '/') ? '\n' : '*');
-		peekc = 0;
-		c = ' ';
-	}
-
-	input->begin = input->p = input->line;
-	if (bp == lim-1) {
-		errorp("line too long");
-		--bp;
-	}
-	*bp++ = '\n';
-	*bp = '\0';
-
-	return 1;
-}
-
-/*
- * moreinput gets more bytes to be passed to the lexer.
- * It can take more bytes from macro expansions or
- * directly reading from files. When a cpp directive
- * is processed the line is discarded because it must not
- * be passed to the lexer
- */
-static int
-moreinput(void)
-{
-	int wasexpand = 0;
-
-repeat:
-	if (!input)
-		return 0;
-
-	if (*input->p == '\0') {
-		if ((input->flags&ITYPE) == IMACRO) {
-			wasexpand = 1;
-			input->flags |= IEOF;
-		}
-		if (input->flags & IEOF) {
-			delinput();
-			goto repeat;
-		}
-		if (!readline() || cpp()) {
-			*input->p = '\0';
-			goto repeat;
-		}
-	}
-
-	if (onlycpp && !wasexpand)
-		ppragmaln();
-	return 1;
-}
-
-static void
-tok2str(void)
-{
-	if ((yylen = input->p - input->begin) > INTIDENTSIZ)
-		error("token too big");
-	memcpy(yytext, input->begin, yylen);
-	yytext[yylen] = '\0';
-	input->begin = input->p;
-}
-
-static Symbol *
-readint(char *s, int base, int sign, Symbol *sym)
-{
-	Type *tp = sym->type;
-	struct limits *lim;
-	TUINT u, val, max;
-	int c;
-
-	lim = getlimits(tp);
-	max = lim->max.i;
-	if (*s == '0')
-		++s;
-	if (toupper(*s) == 'X')
-		++s;
-
-	for (u = 0; isxdigit(c = *s++); u = u*base + val) {
-		static char letters[] = "0123456789ABCDEF";
-		val = strchr(letters, toupper(c)) - letters;
-	repeat:
-		if (u <= max/base && u*base <= max - val)
-			continue;
-		if (tp->prop & TSIGNED) {
-			if (tp == inttype)
-				tp = (base==10) ? longtype : uinttype;
-			else if (tp == longtype)
-				tp = (base==10) ? llongtype : ulongtype;
-			else
-				goto overflow;
-		} else {
-			if (tp == uinttype)
-				tp = (sign==UNSIGNED) ? ulongtype : longtype;
-			else if (tp == ulongtype)
-				tp = (sign==UNSIGNED) ? ullongtype : llongtype;
-			else
-				goto overflow;
-		}
-		sym->type = tp;
-		lim = getlimits(tp);
-		max = lim->max.i;
-		goto repeat;
-	}
-
-	if (tp->prop & TSIGNED)
-		sym->u.i = u;
-	else
-		sym->u.u = u;
-
-	return sym;
-
-overflow:
-	errorp("overflow in integer constant");
-	return sym;
-}
-
-static int
-integer(char *s, int base)
-{
-	Type *tp;
-	Symbol *sym;
-	unsigned size, sign;
-
-	for (size = sign = 0; ; ++input->p) {
-		switch (toupper(*input->p)) {
-		case 'L':
-			if (size == LLONG)
-				goto wrong_type;
-			size = (size == LONG) ? LLONG : LONG;
-			continue;
-		case 'U':
-			if (sign == UNSIGNED)
-				goto wrong_type;
-			sign = UNSIGNED;
-			continue;
-		default:
-			goto convert;
-		wrong_type:
-			error("invalid suffix in integer constant");
-		}
-	}
-
-convert:
-	tp = ctype(INT, sign, size);
-	sym = newsym(NS_IDEN, NULL);
-	sym->type = tp;
-	sym->flags |= SCONSTANT;
-	yylval.sym = readint(s, base, sign, sym);
-	return CONSTANT;
-}
-
-static char *
-digits(int base)
-{
-	char *p;
-	int c;
-
-	for (p = input->p; c = *p; ++p) {
-		switch (base) {
-		case 8:
-			if (!strchr("01234567", c))
-				goto end;
-			break;
-		case 10:
-			if (!isdigit(c))
-				goto end;
-			break;
-		case 16:
-			if (!isxdigit(c))
-				goto end;
-			break;
-		}
-	}
-end:
-	input->p = p;
-	tok2str();
-	return yytext;
-}
-
-static int
-number(void)
-{
-	int base;
-
-	if (*input->p != '0') {
-		base = 10;
-	} else {
-		if (toupper(*++input->p) == 'X') {
-			++input->p;
-			base = 16;
-		} else {
-			base = 8;
-		}
-	}
-
-	return integer(digits(base), base);
-}
-
-static int
-escape(void)
-{
-	int c, base;
-
-	switch (*++input->p) {
-	case 'a':  return '\a';
-	case 'f':  return '\f';
-	case 'n':  return '\n';
-	case 'r':  return '\r';
-	case 't':  return '\t';
-	case 'v':  return '\v';
-	case '"':  return '"';
-	case '\'': return '\'';
-	case '\\': return '\\';
-	case '\?': return '\?';
-	case 'u':
-		/*
-		 * FIXME: universal constants are not correctly handled
-		 */
-		if (!isdigit(*++input->p))
-			warn("incorrect digit for numerical character constant");
-		base = 10;
-		break;
-	case 'x':
-		if (!isxdigit(*++input->p))
-			warn("\\x used with no following hex digits");
-		base = 16;
-		break;
-	case '0':
-		if (!strchr("01234567", *++input->p))
-			warn("\\0 used with no following octal digits");
-		base = 8;
-		break;
-	default:
-		warn("unknown escape sequence");
-		return ' ';
-	}
-	errno = 0;
-	c = strtoul(input->p, &input->p, base);
-	if (errno || c > 255)
-		warn("character constant out of range");
-	--input->p;
-	return c;
-}
-
-static int
-character(void)
-{
-	int c;
-	Symbol *sym;
-
-	if ((c = *++input->p) == '\\')
-		c = escape();
-	else
-		c = *input->p;
-	++input->p;
-	if (*input->p != '\'')
-		errorp("invalid character constant");
-	else
-		++input->p;
-
-	sym = newsym(NS_IDEN, NULL);
-	sym->u.i = c;
-	sym->type = inttype;
-	yylval.sym = sym;
-	tok2str();
-	return CONSTANT;
-}
-
-static int
-string(void)
-{
-	char *bp = yytext;
-	int c;
-
-	*bp++ = '"';
-	for (++input->p; (c = *input->p) != '"'; ++input->p) {
-		if (c == '\0') {
-			errorp("missing terminating '\"' character");
-			break;
-		}
-		if (c == '\\')
-			c = escape();
-		if (bp == &yytext[STRINGSIZ+1]) {
-			/* TODO: proper error handling here */
-			error("string too long");
-		}
-		*bp++ = c;
-	}
-
-	input->begin = ++input->p;
-	*bp = '\0';
-
-	yylen = bp - yytext + 1;
-	yylval.sym = newstring(yytext+1, yylen-1);
-	*bp++ = '"';
-	*bp = '\0';
-	return STRING;
-}
-
-static int
-iden(void)
-{
-	Symbol *sym;
-	char *p, *begin;
-
-	begin = input->p;
-	for (p = begin; isalnum(*p) || *p == '_'; ++p)
-		;
-	input->p = p;
-	tok2str();
-	if ((sym = lookup(NS_CPP, yytext, NOALLOC)) != NULL) {
-		if (!disexpand && !sym->hide && expand(begin, sym))
-			return next();
-	}
-	sym = lookup(namespace, yytext, ALLOC);
-	yylval.sym = sym;
-	if (sym->flags & SCONSTANT)
-		return CONSTANT;
-	if (sym->token != IDEN)
-		yylval.token = sym->u.token;
-	return sym->token;
-}
-
-static int
-follow(int expect, int ifyes, int ifno)
-{
-	if (*input->p++ == expect)
-		return ifyes;
-	--input->p;
-	return ifno;
-}
-
-static int
-minus(void)
-{
-	switch (*input->p++) {
-	case '-': return DEC;
-	case '>': return INDIR;
-	case '=': return SUB_EQ;
-	default: --input->p; return '-';
-	}
-}
-
-static int
-plus(void)
-{
-	switch (*input->p++) {
-	case '+': return INC;
-	case '=': return ADD_EQ;
-	default: --input->p; return '+';
-	}
-}
-
-static int
-relational(int op, int equal, int shift, int assig)
-{
-	int c;
-
-	if ((c = *input->p++) == '=')
-		return equal;
-	if (c == op)
-		return follow('=', assig, shift);
-	--input->p;
-	return op;
-}
-
-static int
-logic(int op, int equal, int logic)
-{
-	int c;
-
-	if ((c = *input->p++) == '=')
-		return equal;
-	if (c == op)
-		return logic;
-	--input->p;
-	return op;
-}
-
-static int
-dot(void)
-{
-	int c;
-
-	if ((c = *input->p) != '.')
-		return '.';
-	if ((c = *++input->p) != '.')
-		error("incorrect token '..'");
-	++input->p;
-	return ELLIPSIS;
-}
-
-static int
-operator(void)
-{
-	int t;
-
-	switch (t = *input->p++) {
-	case '<': t = relational('<', LE, SHL, SHL_EQ); break;
-	case '>': t = relational('>', GE, SHR, SHR_EQ); break;
-	case '&': t = logic('&', AND_EQ, AND); break;
-	case '|': t = logic('|', OR_EQ, OR); break;
-	case '=': t = follow('=', EQ, '='); break;
-	case '^': t = follow('=', XOR_EQ, '^'); break;
-	case '*': t = follow('=', MUL_EQ, '*'); break;
-	case '/': t = follow('=', DIV_EQ, '/'); break;
-	case '!': t = follow('=', NE, '!'); break;
-	case '#': t = follow('#', '$', '#'); break;
-	case '-': t = minus(); break;
-	case '+': t = plus(); break;
-	case '.': t = dot(); break;
-	}
-	tok2str();
-	return t;
-}
-
-/* TODO: Ensure that namespace is NS_IDEN after a recovery */
-
-/*
- * skip all the spaces until the next token. When we are in
- * CPPMODE \n is not considered a whitespace
- */
-static int
-skipspaces(void)
-{
-	int c;
-
-	for (;;) {
-		switch (c = *input->p) {
-		case '\n':
-			if (lexmode == CPPMODE)
-				goto return_byte;
-			++input->p;
-		case '\0':
-			if (!moreinput())
-				return EOF;
-			break;
-		case ' ':
-		case '\t':
-		case '\v':
-		case '\r':
-		case '\f':
-			++input->p;
-			break;
-		default:
-			goto return_byte;
-		}
-	}
-
-return_byte:
-	input->begin = input->p;
-	return c;
-}
-
-int
-next(void)
-{
-	int c;
-
-	if ((c = skipspaces()) == EOF)
-		yytoken = EOFTOK;
-	else if (isalpha(c) || c == '_')
-		yytoken = iden();
-	else if (isdigit(c))
-		yytoken = number();
-	else if (c == '"')
-		yytoken = string();
-	else if (c == '\'')
-		yytoken = character();
-	else
-		yytoken = operator();
-
-	if (yytoken == EOF) {
-		strcpy(yytext, "<EOF>");
-		if (cppctx)
-			errorp("#endif expected");
-	}
-
-	DBG("TOKEN %s", yytext);
-	return yytoken;
-}
-
-void
-expect(int tok)
-{
-	if (yytoken != tok) {
-		if (isgraph(tok))
-			errorp("expected '%c' before '%s'", tok, yytext);
-		else
-			errorp("unexpected '%s'", yytext);
-	} else {
-		next();
-	}
-}
-
-int
-ahead(void)
-{
-	skipspaces();
-	return *input->begin;
-}
-
-void
-setsafe(int type)
-{
-	safe = type;
-}
-
-void
-discard(void)
-{
-	extern jmp_buf recover;
-	int c;
-
-	input->begin = input->p;
-	for (c = yytoken; ; c = *input->begin++) {
-		switch (safe) {
-		case END_COMP:
-			if (c == '}')
-				goto jump;
-			goto semicolon;
-		case END_COND:
-			if (c == ')')
-				goto jump;
-			break;
-		case END_LDECL:
-			if (c == ',')
-				goto jump;
-		case END_DECL:
-		semicolon:
-			if (c == ';')
-				goto jump;
-			break;
-		}
-		if (c == '\0' && !moreinput())
-			exit(1);
-	}
-jump:
-	yytoken = c;
-	longjmp(recover, 1);
-}
--- a/src/cmd/scc/cc1/main.c
+++ /dev/null
@@ -1,101 +1,0 @@
-#include <setjmp.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include <scc/arg.h>
-#include <scc/scc.h>
-#include "cc1.h"
-
-char *argv0, *infile;
-
-int warnings;
-jmp_buf recover;
-
-static struct items uflags;
-int onlycpp, onlyheader;
-
-
-extern int failure;
-
-static void
-defmacro(char *macro)
-{
-	char *p = strchr(macro, '=');
-
-	if (p)
-		*p++ = '\0';
-	else
-		p = "1";
-
-	defdefine(macro, p, "command-line");
-}
-
-static void
-usage(void)
-{
-	fputs("usage: cc1 [-Ewd] [-D def[=val]]... [-U def]... "
-	      "[-I dir]... [-o output] [input]\n", stderr);
-	exit(1);
-}
-
-int
-main(int argc, char *argv[])
-{
-	int i;
-
-	ilex();
-	icpp();
-	icode();
-	ibuilts();
-
-	ARGBEGIN {
-	case 'D':
-		defmacro(EARGF(usage()));
-		break;
-	case 'M':
-		onlyheader = 1;
-		break;
-	case 'E':
-		onlycpp = 1;
-		break;
-	case 'I':
-		incdir(EARGF(usage()));
-		break;
-	case 'U':
-		newitem(&uflags, EARGF(usage()));
-		break;
-	case 'd':
-		DBGON();
-		break;
-	case 'w':
-		warnings = 1;
-		break;
-	default:
-		usage();
-	} ARGEND
-
-	if (argc > 1)
-		usage();
-
-	for (i = 0; i < uflags.n; ++i)
-		undefmacro(uflags.s[i]);
-
-	infile = (*argv) ? *argv : "<stdin>";
-	addinput(*argv, NULL, NULL);
-
-	/*
-	 * we cannot initialize arch until we have an
-	 * output stream, because we maybe want to emit new types
-	 */
-	iarch();
-	if (onlycpp || onlyheader) {
-		outcpp();
-	} else {
-		for (next(); yytoken != EOFTOK; decl())
-			;
-	}
-
-	return failure;
-}
--- a/src/cmd/scc/cc1/stmt.c
+++ /dev/null
@@ -1,385 +1,0 @@
-#include <stddef.h>
-#include <setjmp.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-#include "cc1.h"
-
-#define NEGATE   1
-#define NONEGATE 0
-
-Symbol *curfun;
-
-static void stmt(Symbol *lbreak, Symbol *lcont, Switch *lswitch);
-
-static void
-label(void)
-{
-	Symbol *sym;
-
-	switch (yytoken) {
-	case IDEN:
-	case TYPEIDEN:
-		sym = lookup(NS_LABEL, yytext, ALLOC);
-		if (sym->flags & SDEFINED)
-			error("label '%s' already defined", yytext);
-		if ((sym->flags & SDECLARED) == 0)
-			sym = install(NS_LABEL, sym);
-		sym->flags |= SDEFINED;
-		emit(OLABEL, sym);
-		next();
-		expect(':');
-		break;
-	default:
-		unexpected();
-	}
-}
-
-static void
-stmtexp(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
-{
-	Node *np;
-
-	if (accept(';'))
-		return;
-	if (yytoken == IDEN && ahead() == ':') {
-		label();
-		stmt(lbreak, lcont, lswitch);
-		return;
-	}
-	np = expr();
-	if ((np->flags & NEFFECT) == 0)
-		warn("expression without side effects");
-	emit(OEXPR, np);
-	expect(';');
-}
-
-static Node *
-condition(int neg)
-{
-	Node *np;
-
-	expect('(');
-	np = condexpr(neg);
-	expect(')');
-
-	return np;
-}
-
-static void
-While(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
-{
-	Symbol *begin;
-	Node *np;
-
-	begin = newlabel();
-	lcont = newlabel();
-	lbreak = newlabel();
-
-	expect(WHILE);
-	np = condition(NONEGATE);
-
-	emit(OJUMP, lcont);
-
-	emit(OBLOOP, NULL);
-	emit(OLABEL, begin);
-	stmt(lbreak, lcont, lswitch);
-	emit(OLABEL, lcont);
-	emit(OBRANCH, begin);
-	emit(OEXPR, np);
-	emit(OELOOP, NULL);
-
-	emit(OLABEL, lbreak);
-}
-
-static void
-For(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
-{
-	Symbol *begin, *cond;
-	Node *econd, *einc;
-
-	begin = newlabel();
-	lcont = newlabel();
-	cond = newlabel();
-	lbreak = newlabel();
-
-	pushctx();
-
-	expect(FOR);
-	expect('(');
-	switch (yytoken) {
-	case TYPE:
-	case TYPEIDEN:
-	case TQUALIFIER:
-	case SCLASS:
-		decl();
-		break;
-	default:
-		emit(OEXPR, expr());
-	case ';':
-		expect(';');
-		break;
-	}
-	econd = (yytoken != ';') ? condexpr(NONEGATE) : NULL;
-	expect(';');
-	einc = (yytoken != ')') ? expr() : NULL;
-	expect(')');
-
-	emit(OJUMP, cond);
-
-	emit(OBLOOP, NULL);
-	emit(OLABEL, begin);
-	stmt(lbreak, lcont, lswitch);
-	emit(OLABEL, lcont);
-	emit(OEXPR, einc);
-	emit(OLABEL, cond);
-	emit((econd) ? OBRANCH : OJUMP, begin);
-	emit(OEXPR, econd);
-	emit(OELOOP, NULL);
-
-	emit(OLABEL, lbreak);
-
-	popctx();
-}
-
-static void
-Dowhile(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
-{
-	Symbol *begin;
-	Node *np;
-
-	begin = newlabel();
-	lcont = newlabel();
-	lbreak = newlabel();
-
-	expect(DO);
-
-	emit(OBLOOP, NULL);
-	emit(OLABEL, begin);
-	stmt(lbreak, lcont, lswitch);
-	expect(WHILE);
-	np = condition(NONEGATE);
-	emit(OLABEL, lcont);
-	emit(OBRANCH, begin);
-	emit(OEXPR, np);
-	emit(OELOOP, NULL);
-
-	emit(OLABEL, lbreak);
-}
-
-static void
-Return(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
-{
-	Node *np;
-	Type *tp = curfun->type->type;
-
-	expect(RETURN);
-	np = (yytoken != ';') ? decay(expr()) : NULL;
-	expect(';');
-	if (!np) {
-		if (tp != voidtype)
-			warn("function returning non void returns no value");
-		tp = voidtype;
-	} else if (np->type != tp) {
-		if (tp == voidtype)
-			warn("function returning void returns a value");
-		else if ((np = convert(np, tp, 0)) == NULL)
-			errorp("incorrect type in return");
-	}
-	emit(ORET, NULL);
-	emit(OEXPR, np);
-}
-
-static void
-Break(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
-{
-	expect(BREAK);
-	if (!lbreak) {
-		errorp("break statement not within loop or switch");
-	} else {
-		emit(OJUMP, lbreak);
-		expect(';');
-	}
-}
-
-static void
-Continue(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
-{
-	expect(CONTINUE);
-	if (!lcont) {
-		errorp("continue statement not within loop");
-	} else {
-		emit(OJUMP, lcont);
-		expect(';');
-	}
-}
-
-static void
-Goto(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
-{
-	Symbol *sym;
-
-	namespace = NS_LABEL;
-	next();
-	namespace = NS_IDEN;
-
-	if (yytoken != IDEN)
-		unexpected();
-	sym = yylval.sym;
-	if ((sym->flags & SDECLARED) == 0)
-		sym = install(NS_LABEL, sym);
-	sym->flags |= SUSED;
-	emit(OJUMP, sym);
-	next();
-	expect(';');
-}
-
-static void
-Swtch(Symbol *obr, Symbol *lcont, Switch *osw)
-{
-	Switch sw = {0};
-	Node *cond;
-	Symbol *lbreak;
-
-	expect(SWITCH);
-
-	expect ('(');
-	if ((cond = convert(expr(), inttype, 0)) == NULL) {
-		errorp("incorrect type in switch statement");
-		cond = constnode(zero);
-	}
-	expect (')');
-
-	lbreak = newlabel();
-	emit(OBSWITCH, NULL);
-	emit(OEXPR, cond);
-	stmt(lbreak, lcont, &sw);
-	emit(OESWITCH, lbreak);
-	emit(OLABEL, lbreak);
-}
-
-static void
-Case(Symbol *lbreak, Symbol *lcont, Switch *sw)
-{
-	Node *np;
-	Symbol *label;
-
-	expect(CASE);
-	if ((np = constexpr()) == NULL)
-		errorp("case label does not reduce to an integer constant");
-	if (!sw) {
-		errorp("case label not within a switch statement");
-	} else if (sw->nr >= 0 && ++sw->nr == NR_SWITCH) {
-		errorp("too many case labels for a switch statement");
-		sw->nr = -1;
-	}
-	expect(':');
-
-	label = newlabel();
-	emit(OCASE, label);
-	emit(OEXPR, np);
-	emit(OLABEL, label);
-	stmt(lbreak, lcont, sw);
-}
-
-static void
-Default(Symbol *lbreak, Symbol *lcont, Switch *sw)
-{
-	Symbol *label = newlabel();
-
-	if (sw->hasdef)
-		errorp("multiple default labels in one switch");
-	sw->hasdef = 1;
-	expect(DEFAULT);
-	expect(':');
-	emit(ODEFAULT, label);
-	emit(OLABEL, label);
-	stmt(lbreak, lcont, sw);
-}
-
-static void
-If(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
-{
-	Symbol *end, *lelse;
-	Node *np;
-
-	lelse = newlabel();
-	expect(IF);
-	np = condition(NEGATE);
-	emit(OBRANCH, lelse);
-	emit(OEXPR, np);
-	stmt(lbreak, lcont, lswitch);
-	if (accept(ELSE)) {
-		end = newlabel();
-		emit(OJUMP, end);
-		emit(OLABEL, lelse);
-		stmt(lbreak, lcont, lswitch);
-		emit(OLABEL, end);
-	} else {
-		emit(OLABEL, lelse);
-	}
-}
-
-static void
-blockit(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
-{
-	switch (yytoken) {
-	case TYPEIDEN:
-		if (ahead() == ':')
-			goto parse_stmt;
-	case TYPE:
-	case TQUALIFIER:
-	case SCLASS:
-		decl();
-		return;
-	default:
-	parse_stmt:
-		stmt(lbreak, lcont, lswitch);
-	}
-}
-
-void
-compound(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
-{
-	static int nested;
-
-	pushctx();
-	expect('{');
-
-	if (nested == NR_BLOCK)
-		error("too many nesting levels of compound statements");
-
-	++nested;
-	for (;;) {
-		if (yytoken == '}')
-			break;
-		blockit(lbreak, lcont, lswitch);
-	}
-	--nested;
-
-	popctx();
-	expect('}');
-}
-
-static void
-stmt(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
-{
-	void (*fun)(Symbol *, Symbol *, Switch *);
-
-	switch (yytoken) {
-	case '{':      fun = compound; break;
-	case RETURN:   fun = Return;   break;
-	case WHILE:    fun = While;    break;
-	case FOR:      fun = For;      break;
-	case DO:       fun = Dowhile;  break;
-	case IF:       fun = If;       break;
-	case BREAK:    fun = Break;    break;
-	case CONTINUE: fun = Continue; break;
-	case GOTO:     fun = Goto;     break;
-	case SWITCH:   fun = Swtch;    break;
-	case CASE:     fun = Case;     break;
-	case DEFAULT:  fun = Default;  break;
-	default:       fun = stmtexp;  break;
-	}
-	(*fun)(lbreak, lcont, lswitch);
-}
--- a/src/cmd/scc/cc1/symbol.c
+++ /dev/null
@@ -1,351 +1,0 @@
-#include <assert.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-#include "cc1.h"
-
-#define NR_SYM_HASH 64
-#define NR_CPP_HASH 32
-#define NR_LBL_HASH 16
-
-unsigned curctx;
-static unsigned short counterid;
-
-static Symbol *head, *labels;
-static Symbol *htab[NR_SYM_HASH];
-static Symbol *htabcpp[NR_CPP_HASH];
-static Symbol *htablbl[NR_LBL_HASH];
-
-#ifndef NDEBUG
-void
-dumpstab(Symbol **tbl, char *msg)
-{
-	Symbol **bp, *sym;
-	unsigned size;
-
-	fprintf(stderr, "Symbol Table dump at ctx=%u\n%s\n", curctx, msg);
-	if (tbl == htab)
-		size = NR_SYM_HASH;
-	else if (tbl == htabcpp)
-		size = NR_CPP_HASH;
-	else if (tbl == htablbl)
-		size = NR_LBL_HASH;
-	else
-		abort();
-
-	for (bp = tbl; bp < &tbl[size]; ++bp) {
-		if (*bp == NULL)
-			continue;
-		fprintf(stderr, "%d", (int) (bp - htab));
-		for (sym = *bp; sym; sym = sym->hash)
-			fprintf(stderr, "->[%d,%d:'%s'=%p]",
-			        sym->ns, sym->ctx, sym->name, (void *) sym);
-		putc('\n', stderr);
-	}
-	fputs("head:", stderr);
-	for (sym = head; sym; sym = sym->next) {
-		fprintf(stderr, "->[%d,%d:'%s'=%p]",
-		        sym->ns, sym->ctx,
-		        (sym->name) ? sym->name : "", (void *) sym);
-	}
-	fputs("\nlabels:", stderr);
-	for (sym = labels; sym; sym = sym->next) {
-		fprintf(stderr, "->[%d,%d:'%s'=%p]",
-		        sym->ns, sym->ctx,
-		        (sym->name) ? sym->name : "", (void *) sym);
-	}
-	putc('\n', stderr);
-}
-#endif
-
-static Symbol **
-hash(char *s, int ns)
-{
-	unsigned h, size;
-	Symbol **tab;
-
-	h = genhash(s);
-
-	switch (ns) {
-	case NS_CPP:
-		tab = htabcpp;
-		size = NR_CPP_HASH-1;
-		break;
-	case NS_LABEL:
-		tab = htablbl;
-		size = NR_LBL_HASH-1;
-		break;
-	default:
-		tab = htab;
-		size = NR_SYM_HASH-1;
-		break;
-	}
-	return &tab[h & size];
-}
-
-static void
-unlinkhash(Symbol *sym)
-{
-	Symbol **h;
-
-	if ((sym->flags & SDECLARED) == 0)
-		return;
-	h = hash(sym->name, sym->ns);
-	assert(sym->ns == NS_CPP || *h == sym);
-	while (*h != sym)
-		h = &(*h)->hash;
-	*h = sym->hash;
-}
-
-void
-pushctx(void)
-{
-	DBG("SYM: pushed context %d", curctx+1);
-	if (++curctx == NR_BLOCK+1)
-		error("too many nested blocks");
-}
-
-void
-killsym(Symbol *sym)
-{
-	short f;
-	char *name;
-
-	if (!sym)
-		return;
-	f = sym->flags;
-	if (f & SSTRING)
-		free(sym->u.s);
-	if (sym->ns == NS_TAG)
-		sym->type->prop &= ~TDEFINED;
-	unlinkhash(sym);
-	if ((name = sym->name) != NULL) {
-		switch (sym->ns) {
-		case NS_LABEL:
-			if ((f & SDEFINED) == 0)
-				errorp("label '%s' is not defined", name);
-		case NS_IDEN:
-			if ((f & (SUSED|SGLOBAL|SDECLARED)) == SDECLARED)
-				warn("'%s' defined but not used", name);
-			break;
-		}
-	}
-	free(name);
-	free(sym);
-}
-
-void
-popctx(void)
-{
-	Symbol *next, *sym;
-	int ns, dangling = 0;
-
-	DBG("SYM: poped context %d", curctx);
-	/*
-	 * we have to be careful before popping the current
-	 * context, because since the parser is one token
-	 * ahead it may already have read an identifier at
-	 * this point, and yylval.sym is a pointer to
-	 * the symbol associated to such token. If that
-	 * symbol is from the context that we are popping
-	 * then we are going to generate a dangling pointer.
-	 * We can detect this situation and call again to
-	 * lookup.
-	 */
-	if ((yytoken == IDEN || yytoken == TYPEIDEN) &&
-	    yylval.sym->ctx == curctx) {
-		ns = yylval.sym->ns;
-		dangling = 1;
-	}
-
-	for (sym = head; sym && sym->ctx == curctx; sym = next) {
-		/*
-		 * Since we are unlinking them in the inverse order
-		 * we do know that sym is always the head of the
-		 * collision list
-		 */
-		next = sym->next;
-		killsym(sym);
-	}
-	head = sym;
-
-	if (--curctx == GLOBALCTX) {
-		for (sym = labels; sym; sym = next) {
-			next = sym->next;
-			killsym(sym);
-		}
-		labels = NULL;
-	}
-
-	if (dangling) {
-		yylval.sym = lookup(ns, yytext, ALLOC);
-		yytoken = yylval.sym->token;
-	}
-}
-
-unsigned
-newid(void)
-{
-	unsigned short id;
-
-	if (lexmode == CPPMODE)
-		return 0;
-	id = ++counterid;
-	if (id == 0) {
-		die("cc1: overflow in %s identifiers",
-		    (curctx) ? "internal" : "external");
-	}
-	return id;
-}
-
-Symbol *
-newsym(int ns, char *name)
-{
-	Symbol *sym;
-
-	sym = xmalloc(sizeof(*sym));
-	if (name)
-		name = xstrdup(name);
-	sym->name = name;
-	sym->id = 0;
-	sym->hide = 0;
-	sym->ns = ns;
-	sym->ctx = curctx;
-	sym->token = IDEN;
-	sym->flags = 0;
-	sym->u.s = NULL;
-	sym->type = NULL;
-	sym->hash = NULL;
-
-	if (ns == NS_LABEL) {
-		sym->next = labels;
-		labels = sym;
-	} else if (ns != NS_CPP) {
-		sym->next = head;
-		head = sym;
-	}
-	return sym;
-}
-
-static Symbol *
-linkhash(Symbol *sym)
-{
-	Symbol **h;
-
-	h = hash(sym->name, sym->ns);
-	sym->hash = *h;
-	*h = sym;
-
-	if (sym->ns != NS_CPP)
-		sym->id = newid();
-	sym->flags |= SDECLARED;
-	return sym;
-}
-
-Symbol *
-newstring(char *s, size_t len)
-{
-	Symbol *sym = newsym(NS_IDEN, NULL);
-
-	if (lexmode != CPPMODE)
-		sym->type = mktype(chartype, ARY, len, NULL);
-	sym->id = newid();
-	sym->flags |= SSTRING | SCONSTANT | SPRIVATE;
-	sym->u.s = xmalloc(len);
-	if (s)
-		memcpy(sym->u.s, s, len);
-
-	return sym;
-}
-
-Symbol *
-newlabel(void)
-{
-	Symbol *sym = newsym(NS_LABEL, NULL);
-	sym->id = newid();
-	return sym;
-}
-
-Symbol *
-lookup(int ns, char *name, int alloc)
-{
-	Symbol *sym;
-	int sns, c;
-	char *t;
-
-	c = *name;
-	for (sym = *hash(name, ns); sym; sym = sym->hash) {
-		t = sym->name;
-		if (*t != c || strcmp(t, name))
-			continue;
-		sns = sym->ns;
-		if (sns == ns)
-			return sym;
-		/*
-		 * When a lookup is done in a namespace associated
-		 * to a struct we also want symbols of NS_IDEN which
-		 * are typedef, because in other case we cannot declare
-		 * fields of such types.
-		 * TODO: Remove this trick
-		 */
-		if (sns == NS_KEYWORD ||
-		    (sym->flags & STYPEDEF) && ns >= NS_STRUCTS) {
-			return sym;
-		}
-	}
-	return (alloc == ALLOC) ? newsym(ns, name) : NULL;
-}
-
-Symbol *
-install(int ns, Symbol *sym)
-{
-	if (sym->flags & SDECLARED || sym->ctx != curctx) {
-		if (sym->ctx == curctx && ns == sym->ns)
-			return NULL;
-		sym = newsym(ns, sym->name);
-	}
-	return linkhash(sym);
-}
-
-void
-keywords(struct keyword *key, int ns)
-{
-	Symbol *sym;
-
-	for ( ; key->str; ++key) {
-		sym = linkhash(newsym(ns, key->str));
-		sym->token = key->token;
-		sym->u.token = key->value;
-	}
-	/*
-	 * Remove all the predefined symbols from * the symbol list. It
-	 * will make faster some operations. There is no problem of memory
-	 * leakeage because this memory is not ever freed
-	 */
-	counterid = 0;
-	head = NULL;
-}
-
-void
-builtins(struct builtin *built)
-{
-	Symbol *sym;
-	struct builtin *bp;
-
-	for (bp = built; bp->str; ++bp) {
-		sym = linkhash(newsym(NS_KEYWORD, bp->str));
-		sym->token = BUILTIN;
-		sym->u.fun = bp->fun;
-	}
-	/*
-	 * Remove all the predefined symbols from * the symbol list. It
-	 * will make faster some operations. There is no problem of memory
-	 * leakeage because this memory is not ever freed
-	 */
-	counterid = 0;
-	head = NULL;
-}
--- a/src/cmd/scc/cc1/target/amd64-sysv/arch.c
+++ /dev/null
@@ -1,218 +1,0 @@
-#include <scc/scc.h>
-#include "../../cc1.h"
-
-#define RANK_BOOL    0
-#define RANK_SCHAR   1
-#define RANK_UCHAR   1
-#define RANK_CHAR    1
-#define RANK_SHORT   2
-#define RANK_USHORT  2
-#define RANK_INT     3
-#define RANK_UINT    3
-#define RANK_LONG    4
-#define RANK_ULONG   4
-#define RANK_LLONG   5
-#define RANK_ULLONG  5
-#define RANK_FLOAT   6
-#define RANK_DOUBLE  7
-#define RANK_LDOUBLE 8
-
-/*
- * Initializaion of type pointers were done with
- * a C99 initilizator '... = &(Type) {...', but
- * c compiler in Plan9 gives error with this
- * syntax, so I have switched it to this ugly form
- * I hope I will change it again in the future
- */
-
-static Type types[] = {
-	{       /* 0 = voidtype */
-		.op = VOID,
-		.letter = L_VOID,
-	},
-	{       /* 1 = pvoidtype */
-		.op = PTR,
-		.letter = L_POINTER,
-		.prop = TDEFINED,
-		.type = &types[5],  /* chartype */
-		.size = 8,
-		.align = 8,
-	},
-	{      /* 2 = booltype */
-		.op = INT,
-		.letter = L_BOOL,
-		.prop = TDEFINED | TINTEGER | TARITH,
-		.size = 1,
-		.align = 1,
-		.n.rank = RANK_BOOL,
-	},
-	{       /* 3 = schartype */
-		.op = INT,
-		.letter = L_INT8,
-		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
-		.size = 1,
-		.align = 1,
-		.n.rank = RANK_SCHAR,
-	},
-	{      /* 4 = uchartype */
-		.op = INT,
-		.letter = L_UINT8,
-		.prop = TDEFINED | TINTEGER | TARITH,
-		.size = 1,
-		.align = 1,
-		.n.rank = RANK_UCHAR,
-	},
-	{      /* 5 = chartype */
-		.op = INT,
-		.letter = L_INT8,
-		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
-		.size = 1,
-		.align = 1,
-		.n.rank = RANK_CHAR,
-	},
-	{       /* 6 = ushortype */
-		.op = INT,
-		.letter = L_UINT16,
-		.prop = TDEFINED | TINTEGER | TARITH,
-		.size = 2,
-		.align = 2,
-		.n.rank = RANK_USHORT,
-	},
-	{       /* 7 = shortype */
-		.op = INT,
-		.letter = L_INT16,
-		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
-		.size = 2,
-		.align = 2,
-		.n.rank = RANK_SHORT,
-	},
-	{       /* 8 = uinttype */
-		.op = INT,
-		.letter = L_UINT32,
-		.prop = TDEFINED | TINTEGER | TARITH,
-		.size = 4,
-		.align = 4,
-		.n.rank = RANK_UINT,
-	},
-	{       /* 9 = inttype */
-		.op = INT,
-		.letter = L_INT32,
-		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
-		.size = 4,
-		.align = 4,
-		.n.rank = RANK_INT,
-	},
-	{      /* 10 = longtype */
-		.op = INT,
-		.letter = L_INT64,
-		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
-		.size = 8,
-		.align = 8,
-		.n.rank = RANK_LONG,
-	},
-	{       /* 11 = ulongtype */
-		.op = INT,
-		.letter = L_UINT64,
-		.prop = TDEFINED | TINTEGER | TARITH,
-		.size = 8,
-		.align = 8,
-		.n.rank = RANK_ULONG,
-	},
-	{	/* 12 = ullongtype */
-		.op = INT,
-		.letter = L_UINT64,
-		.prop = TDEFINED | TINTEGER | TARITH,
-		.size = 8,
-		.align = 8,
-		.n.rank = RANK_ULLONG,
-	},
-	{       /* 13 = llongtype */
-		.op = INT,
-		.letter = L_INT64,
-		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
-		.size = 8,
-		.align = 8,
-		.n.rank = RANK_LLONG,
-	},
-	{       /* 14 = floattype */
-		.op = FLOAT,
-		.letter = L_FLOAT,
-		.prop = TDEFINED | TARITH,
-		.size = 4,
-		.align = 4,
-		.n.rank = RANK_FLOAT,
-	},
-	{       /* 15 = doubletype */
-		.op = FLOAT,
-		.letter = L_DOUBLE,
-		.prop = TDEFINED | TARITH,
-		.size = 8,
-		.align = 8,
-		.n.rank = RANK_DOUBLE,
-	},
-	{       /* 16 = ldoubletype */
-		.op = FLOAT,
-		.letter = L_LDOUBLE,
-		.prop = TDEFINED | TARITH,
-		.size = 16,
-		.align = 16,
-		.n.rank = RANK_LDOUBLE,
-	},
-	{       /* 17 = sizettype */
-		.op = INT,
-		.letter = L_UINT64,
-		.prop = TDEFINED | TINTEGER | TARITH,
-		.size = 8,
-		.align = 8,
-		.n.rank = RANK_UINT,
-	},
-	{      /* 18 = ellipsis */
-		.op = ELLIPSIS,
-		.letter = L_ELLIPSIS,
-		.prop = TDEFINED,
-	},
-	{      /* 19 = pdifftype */
-		.op = INT,
-		.letter = L_INT64,
-		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
-		.size = 8,
-		.align = 8,
-		.n.rank = RANK_LONG,
-	},
-	{      /* 20 = va_type */
-		.op = STRUCT,
-		.letter = L_VA_ARG,
-		.prop = TDEFINED,
-		.size = 24,
-		.align = 8,
-	},
-};
-
-Type *voidtype = &types[0], *pvoidtype = &types[1],
-     *booltype = &types[2], *schartype = &types[3],
-     *uchartype = &types[4], *chartype = &types[5],
-     *ushortype = &types[6], *shortype = &types[7],
-     *uinttype = &types[8], *inttype = &types[9],
-     *longtype = &types[10], *ulongtype = &types[11],
-     *ullongtype = &types[12], *llongtype = &types[13],
-     *floattype = &types[14], *doubletype = &types[15],
-     *ldoubletype = &types[16],
-     *sizettype = &types[17], *pdifftype = &types[19],
-     *ellipsistype = &types[18], *va_type = &types[20],
-     *va_list_type;
-
-static Symbol dummy0 = {.u.i = 0, .type = &types[9]},
-              dummy1 = {.u.i = 1, .type = &types[9]};
-Symbol *zero = &dummy0, *one = &dummy1;
-
-void
-iarch(void)
-{
-	va_list_type = mktype(va_type, ARY, 1, NULL);
-}
-
-int
-valid_va_list(Type *tp)
-{
-	return tp->op == PTR && eqtype(tp->type, va_type, 1);
-}
--- a/src/cmd/scc/cc1/target/amd64-sysv/arch.mk
+++ /dev/null
@@ -1,4 +1,0 @@
-OBJ-amd64-sysv= $(OBJS)  target/amd64-sysv/arch.o
-
-$(LIBEXEC)/cc1-amd64-sysv: $(OBJ-amd64-sysv)
-	$(CC) $(SCC_LDFLAGS) $(OBJ-amd64-sysv) -lscc -o $@
--- a/src/cmd/scc/cc1/target/arm64-sysv/arch.c
+++ /dev/null
@@ -1,218 +1,0 @@
-#include <scc/scc.h>
-#include "../../cc1.h"
-
-#define RANK_BOOL    0
-#define RANK_SCHAR   1
-#define RANK_UCHAR   1
-#define RANK_CHAR    1
-#define RANK_SHORT   2
-#define RANK_USHORT  2
-#define RANK_INT     3
-#define RANK_UINT    3
-#define RANK_LONG    4
-#define RANK_ULONG   4
-#define RANK_LLONG   5
-#define RANK_ULLONG  5
-#define RANK_FLOAT   6
-#define RANK_DOUBLE  7
-#define RANK_LDOUBLE 8
-
-/*
- * Initializaion of type pointers were done with
- * a C99 initilizator '... = &(Type) {...', but
- * c compiler in Plan9 gives error with this
- * syntax, so I have switched it to this ugly form
- * I hope I will change it again in the future
- */
-
-static Type types[] = {
-	{       /* 0 = voidtype */
-		.op = VOID,
-		.letter = L_VOID,
-	},
-	{       /* 1 = pvoidtype */
-		.op = PTR,
-		.letter = L_POINTER,
-		.prop = TDEFINED,
-		.type = &types[5],  /* chartype */
-		.size = 8,
-		.align = 8,
-	},
-	{      /* 2 = booltype */
-		.op = INT,
-		.letter = L_BOOL,
-		.prop = TDEFINED | TINTEGER | TARITH,
-		.size = 1,
-		.align = 1,
-		.n.rank = RANK_BOOL,
-	},
-	{       /* 3 = schartype */
-		.op = INT,
-		.letter = L_INT8,
-		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
-		.size = 1,
-		.align = 1,
-		.n.rank = RANK_SCHAR,
-	},
-	{      /* 4 = uchartype */
-		.op = INT,
-		.letter = L_UINT8,
-		.prop = TDEFINED | TINTEGER | TARITH,
-		.size = 1,
-		.align = 1,
-		.n.rank = RANK_UCHAR,
-	},
-	{      /* 5 = chartype */
-		.op = INT,
-		.letter = L_INT8,
-		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
-		.size = 1,
-		.align = 1,
-		.n.rank = RANK_CHAR,
-	},
-	{       /* 6 = ushortype */
-		.op = INT,
-		.letter = L_UINT16,
-		.prop = TDEFINED | TINTEGER | TARITH,
-		.size = 2,
-		.align = 2,
-		.n.rank = RANK_USHORT,
-	},
-	{       /* 7 = shortype */
-		.op = INT,
-		.letter = L_INT16,
-		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
-		.size = 2,
-		.align = 2,
-		.n.rank = RANK_SHORT,
-	},
-	{       /* 8 = uinttype */
-		.op = INT,
-		.letter = L_UINT32,
-		.prop = TDEFINED | TINTEGER | TARITH,
-		.size = 4,
-		.align = 4,
-		.n.rank = RANK_UINT,
-	},
-	{       /* 9 = inttype */
-		.op = INT,
-		.letter = L_INT32,
-		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
-		.size = 4,
-		.align = 4,
-		.n.rank = RANK_INT,
-	},
-	{      /* 10 = longtype */
-		.op = INT,
-		.letter = L_INT64,
-		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
-		.size = 8,
-		.align = 8,
-		.n.rank = RANK_LONG,
-	},
-	{       /* 11 = ulongtype */
-		.op = INT,
-		.letter = L_UINT64,
-		.prop = TDEFINED | TINTEGER | TARITH,
-		.size = 8,
-		.align = 8,
-		.n.rank = RANK_ULONG,
-	},
-	{	/* 12 = ullongtype */
-		.op = INT,
-		.letter = L_UINT64,
-		.prop = TDEFINED | TINTEGER | TARITH,
-		.size = 8,
-		.align = 8,
-		.n.rank = RANK_ULLONG,
-	},
-	{       /* 13 = llongtype */
-		.op = INT,
-		.letter = L_INT64,
-		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
-		.size = 8,
-		.align = 8,
-		.n.rank = RANK_LLONG,
-	},
-	{       /* 14 = floattype */
-		.op = FLOAT,
-		.letter = L_FLOAT,
-		.prop = TDEFINED | TARITH,
-		.size = 4,
-		.align = 4,
-		.n.rank = RANK_FLOAT,
-	},
-	{       /* 15 = doubletype */
-		.op = FLOAT,
-		.letter = L_DOUBLE,
-		.prop = TDEFINED | TARITH,
-		.size = 8,
-		.align = 8,
-		.n.rank = RANK_DOUBLE,
-	},
-	{       /* 16 = ldoubletype */
-		.op = FLOAT,
-		.letter = L_LDOUBLE,
-		.prop = TDEFINED | TARITH,
-		.size = 16,
-		.align = 16,
-		.n.rank = RANK_LDOUBLE,
-	},
-	{       /* 17 = sizettype */
-		.op = INT,
-		.letter = L_UINT64,
-		.prop = TDEFINED | TINTEGER | TARITH,
-		.size = 8,
-		.align = 8,
-		.n.rank = RANK_UINT,
-	},
-	{      /* 18 = ellipsis */
-		.op = ELLIPSIS,
-		.letter = L_ELLIPSIS,
-		.prop = TDEFINED,
-	},
-	{      /* 19 = pdifftype */
-		.op = INT,
-		.letter = L_INT64,
-		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
-		.size = 8,
-		.align = 8,
-		.n.rank = RANK_LONG,
-	},
-	{      /* 20 = va_type */
-		.op = STRUCT,
-		.letter = L_VA_ARG,
-		.prop = TDEFINED,
-		.size = 24,
-		.align = 8,
-	},
-};
-
-Type *voidtype = &types[0], *pvoidtype = &types[1],
-     *booltype = &types[2], *schartype = &types[3],
-     *uchartype = &types[4], *chartype = &types[5],
-     *ushortype = &types[6], *shortype = &types[7],
-     *uinttype = &types[8], *inttype = &types[9],
-     *longtype = &types[10], *ulongtype = &types[11],
-     *ullongtype = &types[12], *llongtype = &types[13],
-     *floattype = &types[14], *doubletype = &types[15],
-     *ldoubletype = &types[16],
-     *sizettype = &types[17], *pdifftype = &types[19],
-     *ellipsistype = &types[18], *va_type = &types[20],
-     *va_list_type;
-
-static Symbol dummy0 = {.u.i = 0, .type = &types[9]},
-              dummy1 = {.u.i = 1, .type = &types[9]};
-Symbol *zero = &dummy0, *one = &dummy1;
-
-void
-iarch(void)
-{
-	va_list_type = mktype(va_type, ARY, 1, NULL);
-}
-
-int
-valid_va_list(Type *tp)
-{
-	return tp->op == PTR && eqtype(tp->type, va_type, 1);
-}
--- a/src/cmd/scc/cc1/target/arm64-sysv/arch.mk
+++ /dev/null
@@ -1,4 +1,0 @@
-OBJ-arm64-sysv= $(OBJS)  target/arm64-sysv/arch.o
-
-$(LIBEXEC)/cc1-arm64-sysv: $(OBJ-arm64-sysv)
-	$(CC) $(SCC_LDFLAGS) $(OBJ-arm64-sysv) -lscc -o $@
--- a/src/cmd/scc/cc1/target/i386-sysv/arch.c
+++ /dev/null
@@ -1,219 +1,0 @@
-#include <scc/scc.h>
-#include "../../cc1.h"
-
-#define RANK_BOOL    0
-#define RANK_SCHAR   1
-#define RANK_UCHAR   1
-#define RANK_CHAR    1
-#define RANK_SHORT   2
-#define RANK_USHORT  2
-#define RANK_INT     3
-#define RANK_UINT    3
-#define RANK_LONG    4
-#define RANK_ULONG   4
-#define RANK_LLONG   5
-#define RANK_ULLONG  5
-#define RANK_FLOAT   6
-#define RANK_DOUBLE  7
-#define RANK_LDOUBLE 8
-
-/*
- * Initializaion of type pointers were done with
- * a C99 initilizator '... = &(Type) {...', but
- * c compiler in Plan9 gives error with this
- * syntax, so I have switched it to this ugly form
- * I hope I will change it again in the future
- */
-
-static Type types[] = {
-	{       /* 0 = voidtype */
-		.op = VOID,
-		.letter = L_VOID,
-	},
-	{       /* 1 = pvoidtype */
-		.op = PTR,
-		.letter = L_POINTER,
-		.prop = TDEFINED,
-		.type = &types[5],  /* chartype */
-		.size = 4,
-		.align = 4,
-	},
-	{      /* 2 = booltype */
-		.op = INT,
-		.letter = L_BOOL,
-		.prop = TDEFINED | TINTEGER | TARITH,
-		.size = 1,
-		.align = 1,
-		.n.rank = RANK_BOOL,
-	},
-	{       /* 3 = schartype */
-		.op = INT,
-		.letter = L_INT8,
-		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
-		.size = 1,
-		.align = 1,
-		.n.rank = RANK_SCHAR,
-	},
-	{      /* 4 = uchartype */
-		.op = INT,
-		.letter = L_UINT8,
-		.prop = TDEFINED | TINTEGER | TARITH,
-		.size = 1,
-		.align = 1,
-		.n.rank = RANK_UCHAR,
-	},
-	{      /* 5 = chartype */
-		.op = INT,
-		.letter = L_INT8,
-		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
-		.size = 1,
-		.align = 1,
-		.n.rank = RANK_CHAR,
-	},
-	{       /* 6 = ushortype */
-		.op = INT,
-		.letter = L_UINT16,
-		.prop = TDEFINED | TINTEGER | TARITH,
-		.size = 2,
-		.align = 2,
-		.n.rank = RANK_USHORT,
-	},
-	{       /* 7 = shortype */
-		.op = INT,
-		.letter = L_INT16,
-		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
-		.size = 2,
-		.align = 2,
-		.n.rank = RANK_SHORT,
-	},
-	{       /* 8 = uinttype */
-		.op = INT,
-		.letter = L_UINT32,
-		.prop = TDEFINED | TINTEGER | TARITH,
-		.size = 4,
-		.align = 4,
-		.n.rank = RANK_UINT,
-	},
-	{       /* 9 = inttype */
-		.op = INT,
-		.letter = L_INT32,
-		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
-		.size = 4,
-		.align = 4,
-		.n.rank = RANK_INT,
-	},
-	{      /* 10 = longtype */
-		.op = INT,
-		.letter = L_INT32,
-		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
-		.size = 4,
-		.align = 4,
-		.n.rank = RANK_LONG,
-	},
-	{       /* 11 = ulongtype */
-		.op = INT,
-		.letter = L_UINT32,
-		.prop = TDEFINED | TINTEGER | TARITH,
-		.size = 4,
-		.align = 4,
-		.n.rank = RANK_ULONG,
-	},
-	{	/* 12 = ullongtype */
-		.op = INT,
-		.letter = L_UINT64,
-		.prop = TDEFINED | TINTEGER | TARITH,
-		.size = 8,
-		.align = 4,
-		.n.rank = RANK_ULLONG,
-	},
-	{       /* 13 = llongtype */
-		.op = INT,
-		.letter = L_INT64,
-		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
-		.size = 8,
-		.align = 4,
-		.n.rank = RANK_LLONG,
-	},
-	{       /* 14 = floattype */
-		.op = FLOAT,
-		.letter = L_FLOAT,
-		.prop = TDEFINED | TARITH,
-		.size = 4,
-		.align = 4,
-		.n.rank = RANK_FLOAT,
-	},
-	{       /* 15 = doubletype */
-		.op = FLOAT,
-		.letter = L_DOUBLE,
-		.prop = TDEFINED | TARITH,
-		.size = 8,
-		.align = 4,
-		.n.rank = RANK_DOUBLE,
-	},
-	{       /* 16 = ldoubletype */
-		.op = FLOAT,
-		.letter = L_LDOUBLE,
-		.prop = TDEFINED | TARITH,
-		.size = 12,
-		.align = 4,
-		.n.rank = RANK_LDOUBLE,
-	},
-	{       /* 17 = sizettype */
-		.op = INT,
-		.letter = L_UINT32,
-		.prop = TDEFINED | TINTEGER | TARITH,
-		.size = 4,
-		.align = 4,
-		.n.rank = RANK_UINT,
-	},
-	{      /* 18 = ellipsis */
-		.op = ELLIPSIS,
-		.letter = L_ELLIPSIS,
-		.prop = TDEFINED,
-	},
-	{       /* 19 = pdifftype */
-		.op = INT,
-		.letter = L_INT32,
-		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
-		.size = 4,
-		.align = 4,
-		.n.rank = RANK_INT,
-	},
-	{      /* 20 = va_list_type */
-		.op = PTR,
-		.letter = L_POINTER,
-		.prop = TDEFINED,
-		.size = 4,
-		.align = 4,
-	},
-};
-
-
-Type *voidtype = &types[0], *pvoidtype = &types[1],
-     *booltype = &types[2], *schartype = &types[3],
-     *uchartype = &types[4], *chartype = &types[5],
-     *ushortype = &types[6], *shortype = &types[7],
-     *uinttype = &types[8], *inttype = &types[9],
-     *longtype = &types[10], *ulongtype = &types[11],
-     *ullongtype = &types[12], *llongtype = &types[13],
-     *floattype = &types[14], *doubletype = &types[15],
-     *ldoubletype = &types[16],
-     *sizettype = &types[17], *pdifftype = &types[19],
-     *ellipsistype = &types[18], *va_list_type = &types[20];
-
-
-
-static Symbol dummy0 = {.u.i = 0, .type = &types[9]},
-              dummy1 = {.u.i = 1, .type = &types[9]};
-Symbol *zero = &dummy0, *one = &dummy1;
-
-void
-iarch(void)
-{
-}
-
-int
-valid_va_list(Type *tp)
-{
-	return eqtype(tp, va_list_type, 1);
-}
--- a/src/cmd/scc/cc1/target/i386-sysv/arch.mk
+++ /dev/null
@@ -1,4 +1,0 @@
-OBJ-i386-sysv= $(OBJS)  target/i386-sysv/arch.o
-
-$(LIBEXEC)/cc1-i386-sysv: $(OBJ-i386-sysv)
-	$(CC) $(SCC_LDFLAGS) $(OBJ-i386-sysv) -lscc -o $@
--- a/src/cmd/scc/cc1/target/z80-scc/arch.c
+++ /dev/null
@@ -1,217 +1,0 @@
-#include <scc/scc.h>
-#include "../../cc1.h"
-
-#define RANK_BOOL    0
-#define RANK_SCHAR   1
-#define RANK_UCHAR   1
-#define RANK_CHAR    1
-#define RANK_SHORT   2
-#define RANK_USHORT  2
-#define RANK_INT     3
-#define RANK_UINT    3
-#define RANK_LONG    4
-#define RANK_ULONG   4
-#define RANK_LLONG   5
-#define RANK_ULLONG  5
-#define RANK_FLOAT   6
-#define RANK_DOUBLE  7
-#define RANK_LDOUBLE 8
-
-/*
- * Initializaion of type pointers were done with
- * a C99 initilizator '... = &(Type) {...', but
- * c compiler in Plan9 gives error with this
- * syntax, so I have switched it to this ugly form
- * I hope I will change it again in the future
- */
-
-static Type types[] = {
-	{       /* 0 = voidtype */
-		.op = VOID,
-		.letter = L_VOID,
-	},
-	{       /* 1 = pvoidtype */
-		.op = PTR,
-		.letter = L_POINTER,
-		.prop = TDEFINED,
-		.type = &types[5], /* char type */
-		.size = 2,
-		.align = 2,
-	},
-	{      /* 2 = booltype */
-		.op = INT,
-		.letter = L_BOOL,
-		.prop = TDEFINED | TINTEGER | TARITH,
-		.size = 1,
-		.align = 1,
-		.n.rank = RANK_BOOL,
-	},
-	{       /* 3 = schartype */
-		.op = INT,
-		.letter = L_INT8,
-		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
-		.size = 1,
-		.align = 1,
-		.n.rank = RANK_SCHAR,
-	},
-	{      /* 4 = uchartype */
-		.op = INT,
-		.letter = L_UINT8,
-		.prop = TDEFINED | TINTEGER | TARITH,
-		.size = 1,
-		.align = 1,
-		.n.rank = RANK_UCHAR,
-	},
-	{      /* 5 = chartype */
-		.op = INT,
-		.letter = L_UINT8,
-		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
-		.size = 1,
-		.align = 1,
-		.n.rank = RANK_CHAR,
-	},
-	{       /* 6 = ushortype */
-		.op = INT,
-		.letter = L_UINT16,
-		.prop = TDEFINED | TINTEGER | TARITH,
-		.size = 2,
-		.align = 1,
-		.n.rank = RANK_USHORT,
-	},
-	{       /* 7 = shortype */
-		.op = INT,
-		.letter = L_INT16,
-		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
-		.size = 2,
-		.align = 1,
-		.n.rank = RANK_SHORT,
-	},
-	{       /* 8 = uinttype */
-		.op = INT,
-		.letter = L_UINT16,
-		.prop = TDEFINED | TINTEGER | TARITH,
-		.size = 2,
-		.align = 1,
-		.n.rank = RANK_UINT,
-	},
-	{       /* 9 = inttype */
-		.op = INT,
-		.letter = L_INT16,
-		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
-		.size = 2,
-		.align = 1,
-		.n.rank = RANK_INT,
-	},
-	{      /* 10 = longtype */
-		.op = INT,
-		.letter = L_INT32,
-		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
-		.size = 4,
-		.align = 1,
-		.n.rank = RANK_LONG,
-	},
-	{       /* 11 = ulongtype */
-		.op = INT,
-		.letter = L_UINT32,
-		.prop = TDEFINED | TINTEGER | TARITH,
-		.size = 4,
-		.align = 1,
-		.n.rank = RANK_ULONG,
-	},
-	{	/* 12 = ullongtype */
-		.op = INT,
-		.letter = L_UINT64,
-		.prop = TDEFINED | TINTEGER | TARITH,
-		.size = 8,
-		.align = 1,
-		.n.rank = RANK_ULLONG,
-	},
-	{       /* 13 = llongtype */
-		.op = INT,
-		.letter = L_INT64,
-		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
-		.size = 8,
-		.align = 1,
-		.n.rank = RANK_LLONG,
-	},
-	{       /* 14 = floattype */
-		.op = FLOAT,
-		.letter = L_FLOAT,
-		.prop = TDEFINED | TARITH,
-		.size = 4,
-		.align = 1,
-		.n.rank = RANK_FLOAT,
-	},
-	{       /* 15 = doubletype */
-		.op = FLOAT,
-		.letter = L_DOUBLE,
-		.prop = TDEFINED | TARITH,
-		.size = 8,
-		.align = 1,
-		.n.rank = RANK_DOUBLE,
-	},
-	{       /* 16 = ldoubletype */
-		.op = FLOAT,
-		.letter = L_LDOUBLE,
-		.prop = TDEFINED | TARITH,
-		.size = 16,
-		.align = 1,
-		.n.rank = RANK_LDOUBLE,
-	},
-	{       /* 17 = sizettype */
-		.op = INT,
-		.letter = L_UINT16,
-		.prop = TDEFINED | TINTEGER | TARITH,
-		.size = 2,
-		.align = 1,
-		.n.rank = RANK_UINT,
-	},
-	{      /* 18 = ellipsis */
-		.op = ELLIPSIS,
-		.letter = L_ELLIPSIS,
-		.prop = TDEFINED,
-	},
-	{       /* 7 = pdifftype */
-		.op = INT,
-		.letter = L_INT16,
-		.prop = TDEFINED | TINTEGER | TARITH | TSIGNED,
-		.size = 2,
-		.align = 1,
-		.n.rank = RANK_SHORT,
-	},
-	{       /* 20 = va_list_type */
-		.op = PTR,
-		.letter = L_POINTER,
-		.prop = TDEFINED,
-		.size = 2,
-		.align = 1,
-	}
-};
-
-Type *voidtype = &types[0], *pvoidtype = &types[1],
-     *booltype = &types[2], *schartype = &types[3],
-     *uchartype = &types[4], *chartype = &types[5],
-     *ushortype = &types[6], *shortype = &types[7],
-     *uinttype = &types[8], *inttype = &types[9],
-     *longtype = &types[10], *ulongtype = &types[11],
-     *ullongtype = &types[12], *llongtype = &types[13],
-     *floattype = &types[14], *doubletype = &types[15],
-     *ldoubletype = &types[16],
-     *sizettype = &types[17], *pdifftype = &types[19],
-     *ellipsistype = &types[18], *va_list_type = &types[20];
-
-
-static Symbol dummy0 = {.u.i = 0, .type = &types[9]},
-              dummy1 = {.u.i = 1, .type = &types[9]};
-Symbol *zero = &dummy0, *one = &dummy1;
-
-void
-iarch(void)
-{
-}
-
-int
-valid_va_list(Type *tp)
-{
-	return eqtype(tp, va_list_type, 1);
-}
--- a/src/cmd/scc/cc1/target/z80-scc/arch.mk
+++ /dev/null
@@ -1,4 +1,0 @@
-OBJ-z80-scc= $(OBJS) target/z80-scc/arch.o
-
-$(LIBEXEC)/cc1-z80-scc: $(OBJ-z80-scc)
-	$(CC) $(SCC_LDFLAGS) $(OBJ-z80-scc) -lscc -o $@
--- a/src/cmd/scc/cc1/types.c
+++ /dev/null
@@ -1,437 +1,0 @@
-#include <assert.h>
-#include <inttypes.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-#include "cc1.h"
-
-#define NR_TYPE_HASH 16
-#define HASH(t) (((t)->op ^ (uintptr_t) (t)->type>>3) & NR_TYPE_HASH-1)
-
-static Type *typetab[NR_TYPE_HASH], *localtypes;
-
-/* FIXME:
- * Compiler can generate warnings here if the ranges of TINT,
- * TUINT and TFLOAT are smaller than any of the constants in this
- * array. Ignore them if you know that the target types are correct
- */
-static struct limits limits[][4] = {
-	{
-		{	/* 0 = unsigned 1 byte */
-			.min.i = 0,
-			.max.i = 0xff
-		},
-		{	/* 1 = unsigned 2 bytes */
-			.min.i = 0,
-			.max.i = 0xffff
-		},
-		{	/* 2 = unsigned 4 bytes */
-			.min.i = 0,
-			.max.i = 0xffffffff
-		},
-		{	/* 3 = unsigned 8 bytes */
-			.min.i = 0,
-			.max.i = 0xffffffffffffffff
-		}
-	},
-	{
-		{	/* 0 = signed 1 byte */
-			.min.i = -0x7f-1,
-			.max.i = 0x7f
-		},
-		{	/* 1 = signed 2 byte */
-			.min.i = -0x7fff-1,
-			.max.i = 0x7fff
-		},
-		{	/* 2 = signed 4 byte */
-			.min.i = -0x7fffffff-1,
-			.max.i = 0x7fffffff
-		},
-		{	/* 3 = signed 8 byte */
-			.min.i = -0x7fffffffffffffff-1,
-			.max.i = 0x7fffffffffffffff,
-		}
-	},
-	{
-		{
-			/* 0 = float 4 bytes */
-			.min.f = -1,
-			.max.f = 2
-		},
-		{
-			/* 1 = float 8 bytes */
-			.min.f = -1,
-			.max.f = 2,
-		},
-		{
-			/* 2 = float 16 bytes */
-			.min.f = -1,
-			.max.f = 2,
-		}
-	}
-};
-
-struct limits *
-getlimits(Type *tp)
-{
-	int ntable, ntype;
-
-	switch (tp->op) {
-	case ENUM:
-	case INT:
-		ntable = ((tp->prop & TSIGNED) != 0);
-		switch (tp->size) {
-		case 1: ntype = 0; break;
-		case 2: ntype = 1; break;
-		case 4: ntype = 2; break;
-		case 8: ntype = 3; break;
-		}
-		break;
-	case FLOAT:
-		ntable = 2;
-		switch (tp->size) {
-		case 4:  ntype = 0; break;
-		case 8:  ntype = 1; break;
-		case 16: ntype = 2; break;
-		}
-		break;
-	default:
-		abort();
-	}
-
-	return &limits[ntable][ntype];
-}
-
-Type *
-ctype(int type, int sign, int size)
-{
-	switch (type) {
-	case CHAR:
-		if (size)
-			goto invalid_type;
-		switch (sign) {
-		case 0:
-			return chartype;
-		case SIGNED:
-			return schartype;
-		case UNSIGNED:
-			return uchartype;
-		}
-		break;
-	case VA_LIST:
-		if (size || sign)
-			goto invalid_type;
-		return va_list_type;
-	case VOID:
-		if (size || sign)
-			goto invalid_type;
-		return voidtype;
-	case BOOL:
-		if (size || sign)
-			goto invalid_type;
-		return booltype;
-	case 0:
-	case INT:
-		switch (size) {
-		case 0:
-			return (sign == UNSIGNED) ? uinttype   : inttype;
-		case SHORT:
-			return (sign == UNSIGNED) ? ushortype  : shortype;
-		case LONG:
-			return (sign == UNSIGNED) ? ulongtype  : longtype;
-		case LLONG:
-			return (sign == UNSIGNED) ? ullongtype : llongtype;
-		}
-		break;
-	case DOUBLE:
-		if (size == LLONG)
-			goto invalid_type;
-		if (size == LONG)
-			size = LLONG;
-		else
-			size = LONG;
-		goto floating;
-	case FLOAT:
-		if (size == LLONG)
-			goto invalid_type;
-	floating:
-		if (sign)
-			goto invalid_type;
-		switch (size) {
-		case 0:
-			return floattype;
-		case LONG:
-			return doubletype;
-		case LLONG:
-			return ldoubletype;
-		}
-		break;
-	}
-
-invalid_type:
-	error("invalid type specification");
-}
-
-void
-typesize(Type *tp)
-{
-	Symbol **sp;
-	Type *type;
-	unsigned long size, offset;
-	int align, a;
-	TINT n;
-
-	switch (tp->op) {
-	case ARY:
-		/* FIXME: Control overflow */
-		tp->size = tp->n.elem * tp->type->size;
-		tp->align = tp->type->align;
-		return;
-	case PTR:
-		tp->size = pvoidtype->size;
-		tp->align = pvoidtype->align;
-		return;
-	case STRUCT:
-	case UNION:
-		/* FIXME: Control overflow */
-		/*
-		 * The alignment of the struct/union is
-		 * he alignment of the largest included type.
-		 * The size of an union is the size of the largest
-		 * field, and the size of a struct is the sum
-		 * of the size of every field plus padding bits.
-		 */
-		offset = align = size = 0;
-		n = tp->n.elem;
-		for (sp = tp->p.fields; n--; ++sp) {
-			(*sp)->u.i = offset;
-			type = (*sp)->type;
-			a = type->align;
-			if (a > align)
-				align = a;
-			if (tp->op == STRUCT) {
-				if (--a != 0)
-					size = (size + a) & ~a;
-				size += type->size;
-				offset = size;
-			} else {
-				if (type->size > size)
-					size = type->size;
-			}
-		}
-
-		tp->align = align;
-		/*
-		 * We have to add the padding bits to
-		 * ensure next struct in an array is well
-		 * alignment.
-		 */
-		if (tp->op == STRUCT && align-- > 1)
-			size += size+align & ~align;
-		tp->size = size;
-		return;
-	case ENUM:
-		tp->size = inttype->size;
-		tp->align = inttype->align;
-		return;
-	case FTN:
-		return;
-	default:
-		abort();
-	}
-}
-
-Type *
-deftype(Type *tp)
-{
-	tp->prop |= TDEFINED;
-	typesize(tp);
-	emit(OTYP, tp);
-	return tp;
-}
-
-static Type *
-newtype(Type *base)
-{
-	Type *tp;
-	size_t siz;
-
-	tp = xmalloc(sizeof(*tp));
-	*tp = *base;
-	tp->id = newid();
-
-	if (tp->op == FTN) {
-		siz = tp->n.elem * sizeof(Type *);
-		tp->p.pars = memcpy(xmalloc(siz), tp->p.pars, siz);
-	}
-
-	if (curfun) {
-		/* it is a type defined in the body of a function */
-		tp->next = localtypes;
-		localtypes = tp;
-	}
-	if (tp->prop & TDEFINED)
-		deftype(tp);
-	return tp;
-}
-
-Type *
-mktype(Type *tp, int op, TINT nelem, Type *pars[])
-{
-	Type **tbl, type;
-	Type *bp;
-
-	if (op == PTR && tp == voidtype)
-		return pvoidtype;
-
-	memset(&type, 0, sizeof(type));
-	type.type = tp;
-	type.op = op;
-	type.p.pars = pars;
-	type.n.elem = nelem;
-
-	switch (op) {
-	case ARY:
-		if (tp == voidtype) {
-			errorp("declaration of array of voids type");
-			tp = inttype;
-		}
-		type.letter = L_ARRAY;
-		if (nelem != 0)
-			type.prop |= TDEFINED;
-		break;
-	case KRFTN:
-		type.prop |= TDEFINED | TK_R;
-		type.op = FTN;
-		type.letter = L_FUNCTION;
-		break;
-	case FTN:
-		if (nelem > 0 && pars[nelem-1] == ellipsistype)
-			type.prop |= TELLIPSIS;
-		type.letter = L_FUNCTION;
-		type.prop |= TDEFINED;
-		break;
-	case PTR:
-	        type.letter = L_POINTER;
-		type.prop |= TDEFINED;
-		break;
-	case ENUM:
-		type.letter = inttype->letter;
-		type.prop |= TINTEGER | TARITH;
-		type.n.rank = inttype->n.rank;
-		goto create_type;
-	case STRUCT:
-		type.letter = L_STRUCT;
-		type.prop |= TAGGREG;
-		goto create_type;
-	case UNION:
-		type.letter = L_UNION;
-		type.prop |= TAGGREG;
-	create_type:
-		return newtype(&type);
-	default:
-		abort();
-	}
-
-	tbl = &typetab[HASH(&type)];
-	for (bp = *tbl; bp; bp = bp->h_next) {
-		if (eqtype(bp, &type, 0))
-			return bp;
-	}
-
-	bp = newtype(&type);
-	bp->h_next = *tbl;
-	*tbl = bp;
-
-	return bp;
-}
-
-int
-eqtype(Type *tp1, Type *tp2, int equiv)
-{
-	TINT n;
-	Type **p1, **p2;
-	Symbol **s1, **s2;
-
-	if (tp1 == tp2)
-		return 1;
-	if (!tp1 || !tp2)
-		return 0;
-	if (tp1->op != tp2->op)
-		return 0;
-
-	switch (tp1->op) {
-	case UNION:
-	case STRUCT:
-		if (tp1->letter != tp2->letter)
-			return 0;
-		if (tp1->tag->name || tp2->tag->name)
-			return tp1->tag == tp2->tag;
-		if (tp1->n.elem != tp2->n.elem)
-			return 0;
-		s1 = tp1->p.fields, s2 = tp2->p.fields;
-		for (n = tp1->n.elem; n > 0; --n, ++s1, ++s2) {
-			if (strcmp((*s1)->name, (*s2)->name))
-				return 0;
-			if (!eqtype((*s1)->type, (*s2)->type, equiv))
-				return 0;
-		}
-		return 1;
-	case FTN:
-		if (tp1->n.elem != tp2->n.elem)
-			return 0;
-		p1 = tp1->p.pars, p2 = tp2->p.pars;
-		for (n = tp1->n.elem; n > 0; --n) {
-			if (!eqtype(*p1++, *p2++, equiv))
-				return 0;
-		}
-		goto check_base;
-	case ARY:
-		if (equiv && (tp1->n.elem == 0 || tp2->n.elem == 0))
-			goto check_base;
-		if (tp1->n.elem != tp2->n.elem)
-			return 0;
-	case PTR:
-	check_base:
-		return eqtype(tp1->type, tp2->type, equiv);
-	case VOID:
-	case ENUM:
-		return 0;
-	case INT:
-	case FLOAT:
-		return tp1->letter == tp2->letter;
-	default:
-		abort();
-	}
-}
-
-void
-flushtypes(void)
-{
-	Type *tp, *next, **h;
-
-	for (tp = localtypes; tp; tp = next) {
-		next = tp->next;
-		switch (tp->op) {
-		default:
-			/*
-			 * All the local types are linked after
-			 * global types, and since we are
-			 * unlinking them in the inverse order
-			 * we do know that tp is always the head
-			 * of the collision list
-			 */
-			h = &typetab[HASH(tp)];
-			assert(*h == tp);
-			*h = tp->h_next;
-		case STRUCT:
-		case UNION:
-		case ENUM:
-			free(tp);
-			break;
-		}
-	}
-	localtypes = NULL;
-}
--- a/src/cmd/scc/cc2/.gitignore
+++ /dev/null
@@ -1,1 +1,0 @@
-error.h
--- a/src/cmd/scc/cc2/Makefile
+++ /dev/null
@@ -1,40 +1,0 @@
-.POSIX:
-
-PROJECTDIR = ../../../..
-include $(PROJECTDIR)/scripts/rules.mk
-
-MORECFLAGS = -I$(INCDIR)/$(STD)
-
-OBJS = main.o \
-       parser.o \
-       peep.o \
-       symbol.o \
-       node.o \
-       code.o \
-       optm.o \
-
-TARGET  = $(LIBEXEC)/cc2-amd64-sysv \
-          $(LIBEXEC)/cc2-i386-sysv \
-          $(LIBEXEC)/cc2-qbe_amd64-sysv \
-          $(LIBEXEC)/cc2-z80-scc \
-
-all: $(TARGET)
-
-$(TARGET): error.h
-
-error.h: cc2.h
-	rm -f $@;\
-	trap 'r=$?;rm -f $$$$.h;exit $r' EXIT INT QUIT ;\
-	awk -f generror.awk cc2.h > $$$$.h && mv $$$$.h $@
-
-dep: inc-dep
-
-clean:
-	rm -f target/*/*.o error.h
-
-include target/amd64-sysv/target.mk
-include target/i386-sysv/target.mk
-include target/qbe_amd64-sysv/target.mk
-include target/qbe_arm64-sysv/target.mk
-include target/z80-scc/target.mk
-include deps.mk
--- a/src/cmd/scc/cc2/cc2.h
+++ /dev/null
@@ -1,256 +1,0 @@
-enum iflags {
-	BBENTRY =    1,        /* basic block entry */
-};
-
-enum tflags {
-	SIGNF   =     1 << 0,  /* Signed type */
-	INTF    =     1 << 1,  /* integer type */
-	FLOATF  =     1 << 2,  /* float type */
-	STRF    =     1 << 3,  /* string */
-	AGGRF   =     1 << 4,  /* aggregate */
-	FUNF    =     1 << 5,  /* function */
-	PARF    =     1 << 6,  /* parameter */
-	INITF   =     1 << 7,  /* initializer flag */
-	ELLIPS  =     1 << 8,  /* vararg function */
-};
-
-enum sclass {
-	SAUTO     = 'A',
-	SREG      = 'R',
-	SLABEL    = 'L',
-	SINDEX    = 'I',
-	STMP      = 'N',
-	SGLOB     = 'G',
-	SEXTRN    = 'X',
-	SPRIV     = 'Y',
-	SLOCAL    = 'T',
-	SMEMB     = 'M',
-	SCONST    = '#',
-	STRING    = '"',
-	SNONE     = 0 /* cc2 relies on SNONE being 0 in nextpc() */
-};
-
-enum types {
-	ELLIPSIS = 'E',
-	INT8     = 'C',
-	INT16    = 'I',
-	INT32    = 'W',
-	INT64    = 'Q',
-	UINT8    = 'K',
-	UINT16   = 'N',
-	UINT32   = 'Z',
-	UINT64   = 'O',
-	POINTER  = 'P',
-	FUNCTION = 'F',
-	VECTOR   = 'V',
-	UNION    = 'U',
-	STRUCT   = 'S',
-	BOOL     = 'B',
-	FLOAT    = 'J',
-	DOUBLE   = 'D',
-	LDOUBLE  = 'H',
-	VOID     = '0'
-};
-
-enum op {
-	/* kind of operand */
-	/* operands */
-	OMEM     = 'M',
-	OTMP     = 'N',
-	OAUTO    = 'A',
-	OREG     = 'R',
-	OCONST   = '#',
-	OSTRING  = '"',
-	OLOAD    = 'D',
-	OLABEL   = 'L',
-	OADD     = '+',
-	OSUB     = '-',
-	OMUL     = '*',
-	OMOD     = '%',
-	ODIV     = '/',
-	OSHL     = 'l',
-	OSHR     = 'r',
-	OLT      = '<',
-	OGT      = '>',
-	OLE      = '[',
-	OGE      = ']',
-	OEQ      = '=',
-	ONE      = '!',
-	OBAND    = '&',
-	OBOR     = '|',
-	OBXOR    = '^',
-	OCPL     = '~',
-	OASSIG   = ':',
-	OSNEG    = '_',
-	OCALL    = 'c',
-	OCALLE   = 'z',
-	OPAR     = 'p',
-	OFIELD   = '.',
-	OCOMMA   = ',',
-	OASK     = '?',
-	OCOLON   = ' ',
-	OADDR    = '\'',
-	OAND     = 'a',
-	OOR      = 'o',
-	ONEG     = 'n',
-	OPTR     = '@',
-	OCAST    = 'g',
-	OINC     = 'i',
-	ODEC     = 'd',
-	OBUILTIN = 'm',
-	/*statements */
-	ONOP     = 'q',
-	OJMP     = 'j',
-	OBRANCH  = 'y',
-	ORET     = 'h',
-	OBLOOP   = 'b',
-	OELOOP   = 'e',
-	OCASE    = 'v',
-	ODEFAULT = 'f',
-	OBSWITCH = 's',
-	OESWITCH = 't',
-	OBFUN    = 'x',
-	OEFUN    = 'k',
-};
-
-enum builtins {
-	BVA_START = 's',
-	BVA_END   = 'e',
-	BVA_ARG   = 'a',
-	BVA_COPY  = 'c',
-};
-
-enum nerrors {
-	EEOFFUN,       /* EOF while parsing function */
-	ENLABEL,       /* label without statement */
-	EIDOVER,       /* identifier overflow */
-	EOUTPAR,       /* out pf params */
-	ESYNTAX,       /* syntax error */
-	ESTACKA,       /* stack unaligned */
-	ESTACKO,       /* stack overflow */
-	ESTACKU,       /* stack underflow */
-	ELNLINE,       /* line too long */
-	ELNBLNE,       /* line without new line */
-	EFERROR,       /* error reading from file:%s */
-	EBADID,        /* incorrect symbol id */
-	EWTACKO,       /* switch stack overflow */
-	EWTACKU,       /* switch stack underflow */
-	ENOSWTC,       /* Out of switch statement */
-	EBBUILT,       /* Unknown builtin */
-	ENUMERR
-};
-
-typedef struct node Node;
-typedef struct type Type;
-typedef struct symbol Symbol;
-typedef struct addr Addr;
-typedef struct inst Inst;
-
-struct type {
-	unsigned long size;
-	unsigned long align;
-	short flags;
-};
-
-struct symbol {
-	Type type;
-	Type rtype;
-	unsigned short id;
-	unsigned short numid;
-	char *name;
-	char kind;
-	union {
-		unsigned long off;
-		Node *stmt;
-		Inst *inst;
-	} u;
-	Symbol *next;
-	Symbol *h_next;
-};
-
-struct node {
-	char op;
-	Type type;
-	char complex;
-	char address;
-	unsigned char flags;
-	union {
-		TUINT i;
-		TFLOAT f;
-		char reg;
-		char *s;
-		Symbol *sym;
-		char subop;
-	} u;
-	Symbol *label;
-	Node *left, *right;
-	Node *next, *prev;
-};
-
-struct addr {
-        char kind;
-        union {
-                char reg;
-                TUINT i;
-                Symbol *sym;
-        } u;
-};
-
-struct inst {
-	unsigned char op;
-	unsigned char flags;
-	Symbol *label;
-	Inst *next, *prev;
-	Addr from1, from2, to;
-};
-
-/* main.c */
-extern void error(unsigned nerror, ...);
-
-/* parse.c */
-extern void parse(void);
-
-/* optm.c */
-extern Node *optm_dep(Node *np), *optm_ind(Node *np);
-
-/* cgen.c */
-extern Node *sethi(Node *np);
-extern Node *cgen(Node *np);
-
-/* peep.c */
-extern void peephole(void);
-
-/* code.c */
-extern void data(Node *np);
-extern void writeout(void), endinit(void), newfun(void);
-extern void code(int op, Node *to, Node *from1, Node *from2);
-extern void defvar(Symbol *), defpar(Symbol *), defglobal(Symbol *);
-extern void setlabel(Symbol *sym), getbblocks(void);
-extern Node *label2node(Node *np, Symbol *sym);
-extern Node *constnode(Node *np, TUINT n, Type *tp);
-extern Symbol *newlabel(void);
-
-/* node.c */
-#define SETCUR  1
-#define KEEPCUR 0
-extern void apply(Node *(*fun)(Node *));
-extern void cleannodes(void);
-extern void delnode(Node *np);
-extern void deltree(Node *np);
-extern void prtree(Node *np), prforest(char *msg);
-extern Node *node(int op);
-extern Node *addstmt(Node *np, int flags);
-extern Node *delstmt(void);
-extern Node *nextstmt(void);
-
-/* symbol.c */
-#define TMPSYM  0
-extern Symbol *getsym(unsigned id);
-extern void popctx(void);
-extern void pushctx(void);
-extern void freesym(Symbol *sym);
-
-/* globals */
-extern Symbol *curfun;
-extern Symbol *locals;
-extern Inst *pc, *prog;
--- a/src/cmd/scc/cc2/code.c
+++ /dev/null
@@ -1,132 +1,0 @@
-#include <stdlib.h>
-#include <string.h>
-
-#include <scc/scc.h>
-#include "cc2.h"
-
-Inst *pc, *prog;
-
-static void
-nextpc(void)
-{
-        Inst *new;
-
-        new = xcalloc(1, sizeof(*new)); /* TODO: create an arena */
-
-        if (!pc) {
-                prog = new;
-        } else {
-                new->next = pc->next;
-                pc->next = new;
-        }
-
-	/* SNONE being 0, calloc initialized {from1,from2,to}.kind for us */
-        new->prev = pc;
-        pc = new;
-}
-
-static void
-addr(Node *np, Addr *addr)
-{
-	Symbol *sym;
-
-	switch (np->op) {
-	case OREG:
-		/* TODO:
-		 * At this moment this op is used also for register variables
-		 */
-		addr->kind = SREG;
-		addr->u.reg = np->u.reg;
-		break;
-	case OCONST:
-		addr->kind = SCONST;
-		/* TODO: Add support for more type of constants */
-		addr->u.i = np->u.i;
-		break;
-	case OTMP:
-	case OLABEL:
-	case OAUTO:
-	case OMEM:
-		sym = np->u.sym;
-		addr->kind = sym->kind;
-		addr->u.sym = sym;
-		break;
-	default:
-		abort();
-	}
-}
-
-Symbol *
-newlabel(void)
-{
-	Symbol *sym = getsym(TMPSYM);
-
-	sym->kind = SLABEL;
-	return sym;
-}
-
-Node *
-label2node(Node *np, Symbol *sym)
-{
-	if(!sym)
-		sym = newlabel();
-	if (!np)
-		np = node(OLABEL);
-	np->op = OLABEL;
-	np->u.sym = sym;
-
-	return np;
-}
-
-Node *
-constnode(Node *np, TUINT n, Type *tp)
-{
-	if (!np)
-		np = node(OCONST);
-	np->op = OCONST;
-	np->left = NULL;
-	np->right = NULL;
-	np->type = *tp;
-	np->u.i = n;
-	return np;
-}
-
-void
-setlabel(Symbol *sym)
-{
-	if (!sym)
-		return;
-	code(0, NULL, NULL, NULL);
-	pc->label = sym;
-	sym->u.inst = pc;
-}
-
-void
-code(int op, Node *to, Node *from1, Node *from2)
-{
-	nextpc();
-	if (from1)
-		addr(from1, &pc->from1);
-	if (from2)
-		addr(from2, &pc->from2);
-	if (to)
-		addr(to, &pc->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;
-        }
-}
--- a/src/cmd/scc/cc2/deps.mk
+++ /dev/null
@@ -1,61 +1,0 @@
-#deps
-./code.o: $(INCDIR)/scc/scc/scc.h
-./code.o: ./cc2.h
-./main.o: $(INCDIR)/scc/scc/arg.h
-./main.o: $(INCDIR)/scc/scc/scc.h
-./main.o: ./cc2.h
-./main.o: ./error.h
-./node.o: $(INCDIR)/scc/scc/scc.h
-./node.o: ./cc2.h
-./optm.o: $(INCDIR)/scc/scc/scc.h
-./optm.o: ./cc2.h
-./parser.o: $(INCDIR)/scc/scc/cstd.h
-./parser.o: $(INCDIR)/scc/scc/scc.h
-./parser.o: ./cc2.h
-./peep.o: $(INCDIR)/scc/scc/scc.h
-./peep.o: ./cc2.h
-./symbol.o: $(INCDIR)/scc/scc/scc.h
-./symbol.o: ./cc2.h
-./target/amd64-sysv/cgen.o: $(INCDIR)/scc/scc/scc.h
-./target/amd64-sysv/cgen.o: ./target/amd64-sysv/../../cc2.h
-./target/amd64-sysv/cgen.o: ./target/amd64-sysv/arch.h
-./target/amd64-sysv/code.o: $(INCDIR)/scc/scc/cstd.h
-./target/amd64-sysv/code.o: $(INCDIR)/scc/scc/scc.h
-./target/amd64-sysv/code.o: ./target/amd64-sysv/../../cc2.h
-./target/amd64-sysv/code.o: ./target/amd64-sysv/arch.h
-./target/amd64-sysv/optm.o: $(INCDIR)/scc/scc/scc.h
-./target/amd64-sysv/optm.o: ./target/amd64-sysv/../../cc2.h
-./target/amd64-sysv/types.o: $(INCDIR)/scc/scc/scc.h
-./target/amd64-sysv/types.o: ./target/amd64-sysv/../../cc2.h
-./target/i386-sysv/cgen.o: $(INCDIR)/scc/scc/scc.h
-./target/i386-sysv/cgen.o: ./target/i386-sysv/../../cc2.h
-./target/i386-sysv/cgen.o: ./target/i386-sysv/arch.h
-./target/i386-sysv/code.o: $(INCDIR)/scc/scc/cstd.h
-./target/i386-sysv/code.o: $(INCDIR)/scc/scc/scc.h
-./target/i386-sysv/code.o: ./target/i386-sysv/../../cc2.h
-./target/i386-sysv/code.o: ./target/i386-sysv/arch.h
-./target/i386-sysv/optm.o: $(INCDIR)/scc/scc/scc.h
-./target/i386-sysv/optm.o: ./target/i386-sysv/../../cc2.h
-./target/i386-sysv/types.o: $(INCDIR)/scc/scc/scc.h
-./target/i386-sysv/types.o: ./target/i386-sysv/../../cc2.h
-./target/qbe/cgen.o: $(INCDIR)/scc/scc/cstd.h
-./target/qbe/cgen.o: $(INCDIR)/scc/scc/scc.h
-./target/qbe/cgen.o: ./target/qbe/../../cc2.h
-./target/qbe/cgen.o: ./target/qbe/arch.h
-./target/qbe/code.o: $(INCDIR)/scc/scc/cstd.h
-./target/qbe/code.o: $(INCDIR)/scc/scc/scc.h
-./target/qbe/code.o: ./target/qbe/../../cc2.h
-./target/qbe/code.o: ./target/qbe/arch.h
-./target/qbe/optm.o: $(INCDIR)/scc/scc/scc.h
-./target/qbe/optm.o: ./target/qbe/../../cc2.h
-./target/z80-scc/cgen.o: $(INCDIR)/scc/scc/scc.h
-./target/z80-scc/cgen.o: ./target/z80-scc/../../cc2.h
-./target/z80-scc/cgen.o: ./target/z80-scc/arch.h
-./target/z80-scc/code.o: $(INCDIR)/scc/scc/cstd.h
-./target/z80-scc/code.o: $(INCDIR)/scc/scc/scc.h
-./target/z80-scc/code.o: ./target/z80-scc/../../cc2.h
-./target/z80-scc/code.o: ./target/z80-scc/arch.h
-./target/z80-scc/optm.o: $(INCDIR)/scc/scc/scc.h
-./target/z80-scc/optm.o: ./target/z80-scc/../../cc2.h
-./target/z80-scc/types.o: $(INCDIR)/scc/scc/scc.h
-./target/z80-scc/types.o: ./target/z80-scc/../../cc2.h
--- a/src/cmd/scc/cc2/generror.awk
+++ /dev/null
@@ -1,9 +1,0 @@
-/^enum nerrors \{/     {print "char *errlist[] = {"; inhome = 1}
-
-inhome && /E[A-Z]*, /  {sub(/,/, "", $1)
-                        printf("\t[%s] = \"", $1)
-                        for (i = 3; i <= NF-1; ++i)
-				printf("%s%s", $i, (i == NF-1) ? "\"" : " ")
-			print ","}
-
-inhome && /^}/          {print "};" ; inhome = 0}
--- a/src/cmd/scc/cc2/main.c
+++ /dev/null
@@ -1,68 +1,0 @@
-#include <errno.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <scc/arg.h>
-#include <scc/scc.h>
-#include "cc2.h"
-#include "error.h"
-
-char *argv0;
-
-void
-error(unsigned nerror, ...)
-{
-	va_list va;
-	va_start(va, nerror);
-	vfprintf(stderr, errlist[nerror], va);
-	va_end(va);
-	putc('\n', stderr);
-	exit(1);
-}
-
-static int
-moreinput(void)
-{
-	int c;
-
-repeat:
-	if (feof(stdin))
-		return 0;
-	if ((c = getchar()) == '\n' || c == EOF)
-		goto repeat;
-	ungetc(c, stdin);
-	return 1;
-}
-
-static void
-usage(void)
-{
-	fputs("usage: cc2 [irfile]\n", stderr);
-	exit(1);
-}
-
-int
-main(int argc, char *argv[])
-{
-	ARGBEGIN {
-	default:
-		usage();
-	} ARGEND
-
-	if (argv[0] && !freopen(argv[0], "r", stdin))
-		die("cc2: %s: %s", argv[0], strerror(errno));
-
-	while (moreinput()) {
-		parse();
-		apply(optm_ind);
-		apply(optm_dep);
-		apply(sethi);
-		apply(cgen);
-		getbblocks();  /* TODO: run apply over asm ins too */
-		peephole();
-		writeout();
-	}
-	return 0;
-}
--- a/src/cmd/scc/cc2/node.c
+++ /dev/null
@@ -1,141 +1,0 @@
-#include <stdlib.h>
-#include <string.h>
-
-#include <scc/scc.h>
-
-#include "cc2.h"
-
-#define NNODES   32
-
-Node *curstmt;
-Symbol *curfun;
-
-static Alloc *arena;
-
-
-Node *
-node(int op)
-{
-	struct arena *ap;
-	Node *np;
-
-	if (!arena)
-		arena = alloc(sizeof(Node), NNODES);
-	np = memset(new(arena), 0, sizeof(*np));
-	np->op = op;
-
-	return np;
-}
-
-#ifndef NDEBUG
-#include <stdio.h>
-
-static void
-prnode(Node *np)
-{
-	if (np->left)
-		prnode(np->left);
-	if (np->right)
-		prnode(np->right);
-	fprintf(stderr, "\t%c%lu", np->op, np->type.size);
-}
-
-void
-prtree(Node *np)
-{
-	prnode(np);
-	putc('\n', stderr);
-}
-
-void
-prforest(char *msg)
-{
-	Node *np;
-
-	if (!curfun)
-		return;
-
-	fprintf(stderr, "%s {\n", msg);
-	for (np = curfun->u.stmt; np; np = np->next)
-		prtree(np);
-	fputs("}\n", stderr);
-}
-#endif
-
-Node *
-addstmt(Node *np, int flag)
-{
-	if (curstmt)
-		np->next = curstmt->next;
-	np->prev = curstmt;
-
-	if (!curfun->u.stmt)
-		curfun->u.stmt = np;
-	else
-		curstmt->next = np;
-
-	if (flag == SETCUR)
-		curstmt = np;
-
-	return np;
-}
-
-Node *
-delstmt(void)
-{
-	Node *next, *prev;
-
-	next = curstmt->next;
-	prev = curstmt->prev;
-	if (next)
-		next->prev = prev;
-	if (prev)
-		prev->next = next;
-	else
-		curfun->u.stmt = next;
-	deltree(curstmt);
-
-	return curstmt = next;
-}
-
-Node *
-nextstmt(void)
-{
-	return curstmt = curstmt->next;
-}
-
-void
-delnode(Node *np)
-{
-	delete(arena, np);
-}
-
-void
-deltree(Node *np)
-{
-	if (!np)
-		return;
-	deltree(np->left);
-	deltree(np->right);
-	delnode(np);
-}
-
-void
-cleannodes(void)
-{
-	if (arena) {
-		dealloc(arena);
-		arena = NULL;
-	}
-	curstmt = NULL;
-}
-
-void
-apply(Node *(*fun)(Node *))
-{
-	if (!curfun)
-		return;
-	curstmt = curfun->u.stmt;
-	while (curstmt)
-		(*fun)(curstmt) ? nextstmt() : delstmt();
-}
--- a/src/cmd/scc/cc2/optm.c
+++ /dev/null
@@ -1,9 +1,0 @@
-#include <scc/scc.h>
-#include "cc2.h"
-
-Node *
-optm_ind(Node *np)
-{
-	return np;
-}
-
--- a/src/cmd/scc/cc2/parser.c
+++ /dev/null
@@ -1,721 +1,0 @@
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-
-#include "cc2.h"
-
-#define STACKSIZ     50
-
-extern Type int8type, int16type, int32type, int64type,
-            uint8type, uint16type, uint32type, uint64type,
-            float32type, float64type, float80type,
-            booltype,
-            ptrtype,
-            voidtype,
-            arg_type;
-
-Type funetype = {
-	.flags = FUNF | ELLIPS
-};
-
-Type funtype = {
-	.flags = FUNF
-};
-
-union tokenop {
-	void *arg;
-	unsigned op;
-};
-
-struct swtch {
-	int nr;
-	Node *first;
-	Node *last;
-};
-
-static struct swtch swtbl[NR_BLOCK], *swp = swtbl;
-static Symbol *lastfun;
-
-typedef void parsefun(char *, union tokenop);
-static parsefun type, symbol, getname, unary, binary, ternary, call,
-                constant, composed, binit, einit,
-                jump, oreturn, loop, assign,
-                ocase, bswitch, eswitch, builtin;
-
-typedef void evalfun(void);
-static evalfun vardecl, beginfun, endfun, endpars, stmt,
-               array, aggregate, flddecl, labeldcl;
-
-static struct decoc {
-	void (*eval)(void);
-	void (*parse)(char *token, union tokenop);
-	union tokenop u;
-} optbl[] = {      /*  eval     parse           args */
-	['A']   = {  vardecl,  symbol, .u.op  =  SAUTO<<8 | OAUTO},
-	['R']   = {  vardecl,  symbol, .u.op  =   SREG<<8 |  OREG},
-	['G']   = {  vardecl,  symbol, .u.op  =  SGLOB<<8 |  OMEM},
-	['X']   = {  vardecl,  symbol, .u.op  = SEXTRN<<8 |  OMEM},
-	['Y']   = {  vardecl,  symbol, .u.op  =  SPRIV<<8 |  OMEM},
-	['T']   = {  vardecl,  symbol, .u.op  = SLOCAL<<8 |  OMEM},
-	['M']   = {  flddecl,  symbol, .u.op  =  SMEMB<<8 |  OMEM},
-	['L']   = { labeldcl,  symbol, .u.op  = SLABEL<<8 | OLABEL},
-
-	['C']   = {     NULL,    type, .u.arg =    &int8type},
-	['I']   = {     NULL,    type, .u.arg =   &int16type},
-	['W']   = {     NULL,    type, .u.arg =   &int32type},
-	['Q']   = {     NULL,    type, .u.arg =   &int64type},
-	['K']   = {     NULL,    type, .u.arg =   &uint8type},
-	['N']   = {     NULL,    type, .u.arg =  &uint16type},
-	['Z']   = {     NULL,    type, .u.arg =  &uint32type},
-	['O']   = {     NULL,    type, .u.arg =  &uint64type},
-	['J']   = {     NULL,    type, .u.arg = &float32type},
-	['D']   = {     NULL,    type, .u.arg = &float64type},
-	['H']   = {     NULL,    type, .u.arg = &float80type},
-	['0']   = {     NULL,    type, .u.arg =    &voidtype},
-	['B']   = {     NULL,    type, .u.arg =    &booltype},
-	['P']   = {     NULL,    type, .u.arg =     &ptrtype},
-	['E']   = {     NULL,    type, .u.arg =    &funetype},
-	['1']	= {     NULL,    type, .u.arg =    &arg_type},
-
-	['F']   = {     NULL,    type, .u.arg =     &funtype},
-	['V']   = {    array,composed,                     0},
-	['U']   = {aggregate,composed,                     0},
-	['S']   = {aggregate,composed,                     0},
-
-	['"']   = {     NULL, getname,                     0},
-	['{']   = { beginfun,    NULL,                     0},
-	['}']   = {   endfun,    NULL,                     0},
-	['(']   = {     NULL,   binit,                     0},
-	[')']   = {     NULL,   einit,                     0},
-	['\\']  = {  endpars,    NULL,                     0},
-	['\t']  = {     stmt,    NULL,                     0},
-
-	['~']   = {     NULL,   unary, .u.op =          OCPL},
-	['_']   = {     NULL,   unary, .u.op =         OSNEG},
-	['\'']  = {     NULL,   unary, .u.op =         OADDR},
-	['@']   = {     NULL,   unary, .u.op =          OPTR},
-	['g']   = {     NULL,   unary, .u.op =         OCAST},
-	['p']   = {     NULL,   unary, .u.op =          OPAR},
-	['n']   = {     NULL,   unary, .u.op =          ONEG},
-
-	['a']   = {     NULL,  binary, .u.op =          OAND},
-	['o']   = {     NULL,  binary, .u.op =           OOR},
-	['.']   = {     NULL,  binary, .u.op =        OFIELD},
-	['+']   = {     NULL,  binary, .u.op =          OADD},
-	['-']   = {     NULL,  binary, .u.op =          OSUB},
-	['*']   = {     NULL,  binary, .u.op =          OMUL},
-	['%']   = {     NULL,  binary, .u.op =          OMOD},
-	['/']   = {     NULL,  binary, .u.op =          ODIV},
-	['l']   = {     NULL,  binary, .u.op =          OSHL},
-	['r']   = {     NULL,  binary, .u.op =          OSHR},
-	['<']   = {     NULL,  binary, .u.op =           OLT},
-	['>']   = {     NULL,  binary, .u.op =           OGT},
-	['[']   = {     NULL,  binary, .u.op =           OLE},
-	[']']   = {     NULL,  binary, .u.op =           OGE},
-	['=']   = {     NULL,  binary, .u.op =           OEQ},
-	['!']   = {     NULL,  binary, .u.op =           ONE},
-	['&']   = {     NULL,  binary, .u.op =         OBAND},
-	['|']   = {     NULL,  binary, .u.op =          OBOR},
-	['^']   = {     NULL,  binary, .u.op =         OBXOR},
-	[',']   = {     NULL,  binary, .u.op =        OCOMMA},
-	['m']   = {     NULL,  builtin,.u.op =      OBUILTIN},
-
-	[':']   = {     NULL,  assign, .u.op =        OASSIG},
-	['?']   = {     NULL, ternary, .u.op =          OASK},
-	['c']   = {     NULL,    call, .u.op =         OCALL},
-	['z']   = {     NULL,    call, .u.op =        OCALLE},
-
-	['#']   = {     NULL,constant, .u.op =        OCONST},
-
-	['j']   = {     NULL,    jump, .u.op =          OJMP},
-	['y']   = {     NULL,    jump, .u.op =       OBRANCH},
-	['h']   = {     NULL, oreturn, .u.op =          ORET},
-	['i']   = {     NULL,    NULL, .u.op =          OINC},
-	['d']   = {     NULL,    NULL, .u.op =          ODEC},
-
-	['b']   = {     NULL,    loop, .u.op =        OBLOOP},
-	['e']   = {     NULL,    loop, .u.op =        OELOOP},
-
-	['v']   = {     NULL,   ocase, .u.op =         OCASE},
-	['f']   = {     NULL,   ocase, .u.op =      ODEFAULT},
-	['t']   = {     NULL, eswitch, .u.op =      OESWITCH},
-	['s']   = {     NULL, bswitch, .u.op =      OBSWITCH},
-};
-
-static int sclass, inpars, ininit, endf, lineno;
-static void *stack[STACKSIZ], **sp = stack;
-
-static Node *
-push(void *elem)
-{
-	if (sp == &stack[STACKSIZ])
-		error(ESTACKO);
-	return *sp++ = elem;
-}
-
-static void *
-pop(void)
-{
-	if (sp == stack)
-		error(ESTACKU);
-	return *--sp;
-}
-
-static int
-empty(void)
-{
-	return sp == stack;
-}
-
-static void
-type(char *token, union tokenop u)
-{
-	push(u.arg);
-}
-
-static void
-composed(char *token, union tokenop u)
-{
-	Symbol *sym;
-
-	sym = getsym(atoi(token+1));
-	push(&sym->type);
-}
-
-static void
-getname(char *t, union tokenop u)
-{
-	push((*++t) ? xstrdup(t) : NULL);
-}
-
-static void
-symbol(char *token, union tokenop u)
-{
-	Node *np = node(u.op & 0xFF);
-	Symbol *sym = getsym(atoi(token+1));
-
-	sclass = u.op >> 8;
-	np->u.sym = sym;
-	np->type = sym->type;
-	push(np);
-}
-
-static Type *
-gettype(char *token)
-{
-	struct decoc *dp;
-
-	dp = &optbl[*token];
-	if (!dp->parse)
-		error(ESYNTAX);
-	(*dp->parse)(token, dp->u);
-	return pop();
-}
-
-static void
-constant(char *token, union tokenop u)
-{
-	static char letters[] = "0123456789ABCDEF";
-	Node *np;
-	TUINT v;
-	unsigned c;
-
-	++token;
-	if (*token == '"') {
-		++token;
-		np = node(OSTRING);
-		np->type.flags = STRF;
-		np->type.size = strlen(token);
-		np->type.align = int8type.align;
-		np->u.s = xstrdup(token);
-	} else {
-		np = node(OCONST);
-		np->type = *gettype(token++);
-		for (v = 0; c = *token++; v += c) {
-			v <<= 4;
-			c = strchr(letters, c) - letters;
-		}
-		np->u.i = v;
-	}
-	push(np);
-}
-
-static void
-assign(char *token, union tokenop u)
-{
-	int subop;
-	Node *np = node(u.op);
-
-	switch (subop = *++token) {
-	case '+':
-	case '-':
-	case '*':
-	case '%':
-	case '/':
-	case 'l':
-	case 'r':
-	case '&':
-	case '|':
-	case '^':
-	case 'i':
-	case 'd':
-		++token;
-		subop = optbl[subop].u.op;
-		break;
-	default:
-		subop = 0;
-		break;
-	}
-
-	np->u.subop = subop;
-	np->type = *gettype(token);
-	np->right = pop();
-	np->left = pop();
-	push(np);
-}
-
-static void
-ternary(char *token, union tokenop u)
-{
-	Node *ask = node(OASK), *colon = node(OCOLON);
-	Type *tp = gettype(token+1);
-
-	colon->right = pop();
-	colon->left = pop();
-
-	ask->type = *tp;
-	ask->left = pop();
-	ask->right = colon;
-	push(ask);
-}
-
-static void
-eval(char *tok)
-{
-	struct decoc *dp;
-
-	do {
-		dp = &optbl[*tok];
-		if (!dp->parse)
-			break;
-		(*dp->parse)(tok, dp->u);
-	} while (tok = strtok(NULL, "\t\n"));
-}
-
-static int
-nextline(void)
-{
-	static char line[LINESIZ];
-	size_t len;
-	int c;
-	void (*fun)(void);
-
-repeat:
-	++lineno;
-	if (!fgets(line, sizeof(line), stdin))
-		return 0;
-	if ((len = strlen(line)) == 0 || line[0] == '\n')
-		goto repeat;
-	if (line[len-1] != '\n')
-		error(len < sizeof(line)-1 ? ELNBLNE : ELNLINE);
-	line[len-1] = '\0';
-
-	c = *line;
-	eval(strtok(line, "\t\n"));
-	if ((fun = *optbl[c].eval) != NULL)
-		(*fun)();
-	if (sp != stack)
-		error(ESTACKA);
-	return 1;
-}
-
-static void
-oreturn(char *token, union tokenop u)
-{
-	Node *np = node(u.op);
-
-	if (token = strtok(NULL, "\t\n"))
-		eval(token);
-	if (!empty())
-		np->left = pop();
-	push(np);
-}
-
-/*
- * Move np (which is a OCASE/ODEFAULT/OESWITCH) to be contigous with
- * the last switch table. It is a bit ugly to touch directly curstmt
- * here, but moving this function to node.c is worse, because we are
- * putting knowledge of how the text is parsed into the node
- * represtation module.
- */
-static void
-waft(Node *np)
-{
-	Node *lastcase, *next;;
-	struct swtch *cur;
-	extern Node *curstmt;
-
-	if (swp == swtbl)
-		error(EWTACKU);
-
-	cur = swp - 1;
-	lastcase = cur->last;
-	next = lastcase->next;
-
-	np->next = next;
-	np->prev = lastcase;
-
-	if (next)
-		next->prev = np;
-	lastcase->next = np;
-
-	if (curstmt == cur->last)
-		curstmt = np;
-	cur->last = np;
-	cur->nr++;
-}
-
-static void
-bswitch(char *token, union tokenop u)
-{
-	struct swtch *cur;
-	Node *np = node(u.op);
-
-	if (swp == &swtbl[NR_BLOCK])
-		error(EWTACKO);
-	cur = swp++;
-	cur->nr = 0;
-
-	eval(strtok(NULL, "\t\n"));
-	np->left = pop();
-
-	push(cur->first = cur->last = np);
-}
-
-static void
-eswitch(char *token, union tokenop u)
-{
-	struct swtch *cur;
-
-	if (swp == swtbl)
-		error(EWTACKU);
-	jump(token, u);
-	waft(pop());
-	cur = --swp;
-	cur->first->u.i = cur->nr;
-}
-
-static void
-ocase(char *token, union tokenop u)
-{
-	jump(token, u);
-	waft(pop());
-}
-
-static void
-jump(char *token, union tokenop u)
-{
-	Node *aux, *np = node(u.op);
-
-	eval(strtok(NULL, "\t\n"));
-
-	if (u.op == OBRANCH || u.op == OCASE)
-		np->left = pop();
-	aux = pop();
-	np->u.sym = aux->u.sym;
-	delnode(aux);
-	push(np);
-}
-
-static void
-loop(char *token, union tokenop u)
-{
-	push(node(u.op));
-}
-
-static void
-unary(char *token, union tokenop u)
-{
-	Node *np = node(u.op);
-
-	np->type = *gettype(token+1);
-	np->left = pop();
-	np->right = NULL;
-	push(np);
-}
-
-static void
-call(char *token, union tokenop u)
-{
-	Node *np, *par, *fun = node(u.op);
-
-	for (par = NULL;; par = np) {
-		np = pop();
-		if (np->op != OPAR)
-			break;
-		np->right = par;
-	}
-
-	fun->type = *gettype(token+1);
-	fun->left = np;
-	fun->right = par;
-	push(fun);
-}
-
-static void
-builtin(char *token, union tokenop u)
-{
-	Node *np = node(u.op);
-	char *name;
-	unsigned subop, nchilds;
-
-	np->type = *gettype(token+1);
-	name = pop();
-
-	if (!strcmp("__builtin_va_arg", name)) {
-		nchilds = 1;
-		subop = BVA_ARG;
-	} else if (!strcmp("__builtin_va_start", name)) {
-		nchilds = 2;
-		subop = BVA_START;
-	} else if (!strcmp("__builtin_va_end", name)) {
-		nchilds = 1;
-		subop = BVA_END;
-	} else if (!strcmp("__builtin_va_copy", name)) {
-		nchilds = 2;
-		subop = BVA_COPY;
-	} else {
-		error(EBBUILT);;
-	}
-
-	np->u.subop = subop;
-	np->right = (nchilds == 2) ? pop() : NULL;
-	np->left = (nchilds != 0) ? pop() : NULL;
-
-	free(name);
-	push(np);
-}
-
-static void
-binary(char *token, union tokenop u)
-{
-	Node *np = node(u.op);
-
-	np->type = *gettype(token+1);
-	np->right = pop();
-	np->left = pop();
-	push(np);
-}
-
-static void
-binit(char *token, union tokenop u)
-{
-	ininit = 1;
-}
-
-static void
-einit(char *token, union tokenop u)
-{
-	ininit = 0;
-	endinit();
-}
-
-static void
-endpars(void)
-{
-	if (!curfun || !inpars)
-		error(ESYNTAX);
-	inpars = 0;
-}
-
-static void
-aggregate(void)
-{
-	Node *align, *size;
-	char *name;
-	Type *tp;
-	Symbol *sym;
-
-	align = pop();
-	size = pop();
-	name = pop();
-	tp = pop();
-
-	tp->size = size->u.i;
-	tp->align = align->u.i;
-	tp->flags = AGGRF;
-	/*
-	 * type is the first field of Symbol so we can obtain the
-	 * address of the symbol from the address of the type.
-	 * We have to do this because composed returns the pointer
-	 * to the type, but in this function we also need the
-	 * symbol to store the name.
-	 */
-	sym = (Symbol *) tp;
-	sym->name = name;
-
-	delnode(align);
-	delnode(size);
-}
-
-static void
-array(void)
-{
-	Type *tp, *base;
-	Node *size;
-
-	size = pop();
-	base = pop();
-	tp = pop();
-	tp->size = size->u.i * base->size; /* FIXME check for overflow */
-	tp->align = base->align;
-
-	delnode(size);
-}
-
-static void
-decl(Symbol *sym)
-{
-	Type *tp = &sym->type;
-
-	if (tp->flags & FUNF) {
-		lastfun = sym;
-	} else {
-		switch (sym->kind) {
-		case SEXTRN:
-		case SGLOB:
-		case SPRIV:
-		case SLOCAL:
-			defglobal(sym);
-			break;
-		case SAUTO:
-		case SREG:
-			if (!curfun)
-				error(ESYNTAX);
-			((inpars) ? defpar : defvar)(sym);
-			break;
-		default:
-			abort();
-		}
-	}
-}
-
-static void
-vardecl(void)
-{
-	Type *tp, *rp;
-	Node *np;
-	Symbol *sym;
-	char *name;
-
-	name = pop();
-	tp = pop();
-	if (tp->flags & FUNF)
-		rp = pop();
-	np = pop();
-
-	sym = np->u.sym;
-	/*
-	 * We have to free sym->name because in tentative declarations
-	 * we can have multiple declarations of the same symbol, and in
-	 * this case our parser will allocate twice the memory
-	 */
-	free(sym->name);
-	sym->name = name;
-	sym->type = *tp;
-	if (tp->flags & FUNF)
-		sym->rtype = *rp;
-	sym->kind = sclass;
-
-	if (ininit)
-		sym->type.flags |= INITF;
-	decl(sym);
-	delnode(np);
-}
-
-static void
-flddecl(void)
-{
-	Node *off, *np;
-	char *name;
-	Type *tp;
-	Symbol *sym;
-
-	off = pop();
-	name = pop();
-	tp = pop();
-	np = pop();
-
-	sym = np->u.sym;
-	sym->u.off = off->u.i;
-	sym->name = name;
-	sym->type = *tp;
-
-	delnode(np);
-	delnode(off);
-}
-
-static void
-labeldcl(void)
-{
-	Node *np;
-	Symbol *sym;
-
-	np = pop();
-	np->op = ONOP;
-	sym = np->u.sym;
-	sym->kind = SLABEL;
-	sym->u.stmt = np;
-	np->label = sym;
-	addstmt(np, SETCUR);
-}
-
-static void
-stmt(void)
-{
-	Node *np;
-
-	if (empty())
-		return;
-	np = pop();
-	if (ininit) {
-		data(np);
-		deltree(np);
-		return;
-	}
-	addstmt(np, SETCUR);
-}
-
-static void
-beginfun(void)
-{
-	curfun = lastfun;
-	inpars = 1;
-	pushctx();
-	addstmt(node(OBFUN), SETCUR);
-}
-
-static void
-endfun(void)
-{
-	endf = 1;
-	addstmt(node(OEFUN), SETCUR);
-}
-
-void
-parse(void)
-{
-	cleannodes();  /* remove code of previous function */
-	popctx();  /* remove context of previous function */
-	curfun = NULL;
-	endf = 0;
-
-	while (!endf && nextline())
-		;
-	if (ferror(stdin))
-		error(EFERROR, strerror(errno));
-}
--- a/src/cmd/scc/cc2/peep.c
+++ /dev/null
@@ -1,7 +1,0 @@
-#include <scc/scc.h>
-#include "cc2.h"
-
-void
-peephole(void)
-{
-}
--- a/src/cmd/scc/cc2/symbol.c
+++ /dev/null
@@ -1,91 +1,0 @@
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <scc/scc.h>
-
-#include "cc2.h"
-
-#define NR_SYMHASH  64
-
-Symbol *locals;
-
-static Symbol *symtab[NR_SYMHASH], *curlocal;
-static int infunction;
-
-
-void
-freesym(Symbol *sym)
-{
-	free(sym->name);
-	free(sym);
-}
-
-void
-pushctx(void)
-{
-	infunction = 1;
-}
-
-void
-popctx(void)
-{
-	Symbol *sym, *next;
-
-	infunction = 0;
-	for (sym = locals; sym; sym = next) {
-		next = sym->next;
-		/*
-		 * Symbols are inserted in the hash in the inverted
-		 * order they are found in locals and it is impossible
-		 * to have a global over a local, because a local is
-		 * any symbol defined in the body of a function,
-		 * even if it has extern linkage.
-		 * For this reason when we reach a symbol in the
-		 * locals list we know that it is the head of it
-		 * collision list and we can remove it assigning
-		 * it h_next to the hash table position
-		 */
-		if (sym->id != TMPSYM)
-			symtab[sym->id & NR_SYMHASH-1] = sym->h_next;
-		freesym(sym);
-	}
-	curlocal = locals = NULL;
-}
-
-Symbol *
-getsym(unsigned id)
-{
-	Symbol **htab, *sym;
-	static unsigned short num;
-
-	if (id >= USHRT_MAX)
-		error(EBADID);
-
-	if (id != TMPSYM) {
-		htab = &symtab[id & NR_SYMHASH-1];
-		for (sym = *htab; sym; sym = sym->h_next) {
-			if (sym->id == id)
-				return sym;
-		}
-	}
-
-	sym = xcalloc(1, sizeof(*sym));
-	sym->id = id;
-	if (infunction) {
-		if (!locals)
-			locals = sym;
-		if (curlocal)
-			curlocal->next = sym;
-		curlocal = sym;
-	}
-	if (id != TMPSYM) {
-		sym->h_next = *htab;
-		*htab = sym;
-	}
-	if ((sym->numid = ++num) == 0)
-		error(EIDOVER);
-
-	return sym;
-}
--- a/src/cmd/scc/cc2/target/amd64-sysv/cgen.c
+++ /dev/null
@@ -1,13 +1,0 @@
-#include "arch.h"
-#include <scc/scc.h>
-#include "../../cc2.h"
-
-Node *
-cgen(Node *np)
-{
-}
-
-Node *
-sethi(Node *np)
-{
-}
--- a/src/cmd/scc/cc2/target/amd64-sysv/code.c
+++ /dev/null
@@ -1,209 +1,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-
-#include "arch.h"
-#include "../../cc2.h"
-
-enum segment {
-	CODESEG,
-	DATASEG,
-	BSSSEG,
-	NOSEG
-};
-
-static int curseg = NOSEG;
-
-static void
-segment(int seg)
-{
-	static char *txt[] = {
-		[CODESEG] = "\t.text\n",
-		[DATASEG] = "\t.data\n",
-		[BSSSEG] = "\t.bss\n",
-	};
-
-	if (seg == curseg)
-		return;
-	fputs(txt[seg], stdout);
-	curseg = seg;
-}
-
-static char *
-symname(Symbol *sym)
-{
-	static char name[INTIDENTSIZ+1];
-
-	if (sym->name) {
-		switch (sym->kind) {
-		case SEXTRN:
-		case SGLOB:
-		case SPRIV:
-			return sym->name;
-		}
-	}
-
-	sprintf(name, ".L%d", sym->numid);
-
-	return name;
-}
-
-static void
-emitconst(Node *np)
-{
-	switch (np->type.size) {
-	case 1:
-		printf("%d", (int) np->u.i & 0xFF);
-		break;
-	case 2:
-		printf("%d", (int) np->u.i & 0xFFFF);
-		break;
-	case 4:
-		printf("%ld", (long) np->u.i & 0xFFFFFFFF);
-		break;
-	case 8:
-		printf("%lld", (long long) np->u.i & 0xFFFFFFFF);
-		break;
-	default:
-		abort();
-	}
-}
-
-static void
-emittree(Node *np)
-{
-	if (!np)
-		return;
-
-	switch (np->op) {
-	case OSTRING:
-		printf("\"%s\"", np->u.s);
-		free(np->u.s);
-		np->u.s = NULL;
-		break;
-	case OCONST:
-		emitconst(np);
-		break;
-	case OADDR:
-		emittree(np->left);
-		break;
-	case OMEM:
-		fputs(symname(np->u.sym), stdout);
-		break;
-	default:
-		emittree(np->left);
-		printf(" %c ", np->op);
-		emittree(np->right);
-		break;
-	}
-}
-static void
-size2asm(Type *tp)
-{
-	char *s;
-
-	if (tp->flags & STRF) {
-		s = "\t.ascii\t";
-	} else {
-		switch (tp->size) {
-		case 1:
-			s = "\t.byte\t";
-			break;
-		case 2:
-			s = "\t.short\t";
-			break;
-		case 4:
-			s = "\t.long\t";
-			break;
-		case 8:
-			s = "\t.quad\t";
-			break;
-		default:
-			s = "\t.space\t%lu,";
-			break;
-		}
-	}
-	printf(s, tp->size);
-}
-
-
-void
-data(Node *np)
-{
-	size2asm(&np->type);
-	emittree(np);
-	putchar('\n');
-}
-
-static void
-label(Symbol *sym)
-{
-	int seg;
-	char *name = symname(sym);
-	Type *tp = &sym->type;
-
-	if (sym->type.flags & FUNF)
-		seg = CODESEG;
-	else if (sym->type.flags & INITF)
-		seg = DATASEG;
-	else
-		seg = BSSSEG;
-	segment(seg);
-
-	switch (sym->kind) {
-	case SEXTRN:
-		printf("\t.extern\t%s\n", name);
-	case SLOCAL:
-		return;
-	case SGLOB:
-		printf("\t.global\t%s\n", name);
-		if (seg == BSSSEG)
-			printf("\t.comm\t%s,%lu\n", name, tp->size);
-		break;
-	}
-	if (sym->type.align != 1)
-		printf("\t.align\t%lu\n", sym->type.align );
-	printf("%s:\n", name);
-}
-
-void
-defglobal(Symbol *sym)
-{
-	label(sym);
-	if (sym->kind == SEXTRN || (sym->type.flags & INITF))
-		return;
-	size2asm(&sym->type);
-	puts("0");
-}
-
-void
-defvar(Symbol *sym)
-{
-}
-
-void
-defpar(Symbol *sym)
-{
-}
-
-void
-newfun(void)
-{
-}
-
-void
-writeout(void)
-{
-}
-
-void
-endinit(void)
-{
-}
-
-void
-getbblocks(void)
-{
-}
--- a/src/cmd/scc/cc2/target/amd64-sysv/optm.c
+++ /dev/null
@@ -1,9 +1,0 @@
-#include <scc/scc.h>
-
-#include "../../cc2.h"
-
-Node *
-optm_dep(Node *np)
-{
-	return np;
-}
--- a/src/cmd/scc/cc2/target/amd64-sysv/target.mk
+++ /dev/null
@@ -1,8 +1,0 @@
-OBJ-amd64-sysv = $(OBJS)  \
-        target/amd64-sysv/cgen.o \
-        target/amd64-sysv/optm.o \
-        target/amd64-sysv/code.o \
-        target/amd64-sysv/types.o
-
-$(LIBEXEC)/cc2-amd64-sysv: $(OBJ-amd64-sysv)
-	$(CC) $(SCC_LDFLAGS) $(OBJ-amd64-sysv) -lscc -o $@
--- a/src/cmd/scc/cc2/target/amd64-sysv/types.c
+++ /dev/null
@@ -1,92 +1,0 @@
-#include <scc/scc.h>
-
-#include "../../cc2.h"
-
-
-Type int8type = {
-	.flags  = SIGNF | INTF,
-	.size   = 1,
-	.align  = 1
-};
-
-Type int16type = {
-	.flags  = SIGNF | INTF,
-	.size   = 2,
-	.align  = 2
-};
-
-Type int32type = {
-	.flags  = SIGNF | INTF,
-	.size   = 4,
-	.align  = 4
-};
-
-Type int64type = {
-	.flags  = SIGNF | INTF,
-	.size   = 8,
-	.align  = 8
-};
-
-Type uint8type = {
-	.flags  = INTF,
-	.size   = 1,
-	.align  = 1
-};
-
-Type uint16type = {
-	.flags  = INTF,
-	.size   = 2,
-	.align  = 2
-};
-
-Type uint32type = {
-	.flags  = INTF,
-	.size   = 4,
-	.align  = 4
-};
-
-Type uint64type = {
-	.flags  = INTF,
-	.size   = 8,
-	.align  = 2
-};
-
-Type ptrtype = {
-	.flags  = INTF,
-	.size   = 8,
-	.align  = 8
-};
-
-Type booltype = {
-	.flags  = INTF,
-	.size   = 1,
-	.align  = 1
-};
-
-Type float32type = {
-	.flags  = FLOATF,
-	.size   = 4,
-	.align  = 4
-};
-
-Type float64type = {
-	.flags  = FLOATF,
-	.size   = 8,
-	.align  = 8
-};
-
-Type float80type = {
-	.flags  = FLOATF,
-	.size   = 16,
-	.align  = 16
-};
-
-Type voidtype = {
-	.size = 0,
-	.align = 0
-};
-
-Type arg_type = {
-	.size = 24,
-	.align = 8
-};
--- a/src/cmd/scc/cc2/target/i386-sysv/cgen.c
+++ /dev/null
@@ -1,14 +1,0 @@
-#include <scc/scc.h>
-
-#include "arch.h"
-#include "../../cc2.h"
-
-Node *
-cgen(Node *np)
-{
-}
-
-Node *
-sethi(Node *np)
-{
-}
--- a/src/cmd/scc/cc2/target/i386-sysv/code.c
+++ /dev/null
@@ -1,208 +1,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-
-#include "arch.h"
-#include "../../cc2.h"
-
-enum segment {
-	CODESEG,
-	DATASEG,
-	BSSSEG,
-	NOSEG
-};
-
-static int curseg = NOSEG;
-
-static void
-segment(int seg)
-{
-	static char *txt[] = {
-		[CODESEG] = "\t.text\n",
-		[DATASEG] = "\t.data\n",
-		[BSSSEG] = "\t.bss\n",
-	};
-
-	if (seg == curseg)
-		return;
-	fputs(txt[seg], stdout);
-	curseg = seg;
-}
-
-static char *
-symname(Symbol *sym)
-{
-	static char name[INTIDENTSIZ+1];
-
-	if (sym->name) {
-		switch (sym->kind) {
-		case SEXTRN:
-		case SGLOB:
-		case SPRIV:
-			return sym->name;
-		}
-	}
-
-	sprintf(name, ".L%d", sym->numid);
-
-	return name;
-}
-
-static void
-emitconst(Node *np)
-{
-	switch (np->type.size) {
-	case 1:
-		printf("%d", (int) np->u.i & 0xFF);
-		break;
-	case 2:
-		printf("%d", (int) np->u.i & 0xFFFF);
-		break;
-	case 4:
-		printf("%ld", (long) np->u.i & 0xFFFFFFFF);
-		break;
-	case 8:
-		printf("%lld", (long long) np->u.i & 0xFFFFFFFF);
-		break;
-	default:
-		abort();
-	}
-}
-
-static void
-emittree(Node *np)
-{
-	if (!np)
-		return;
-
-	switch (np->op) {
-	case OSTRING:
-		printf("\"%s\"", np->u.s);
-		free(np->u.s);
-		np->u.s = NULL;
-		break;
-	case OCONST:
-		emitconst(np);
-		break;
-	case OADDR:
-		emittree(np->left);
-		break;
-	case OMEM:
-		fputs(symname(np->u.sym), stdout);
-		break;
-	default:
-		emittree(np->left);
-		printf(" %c ", np->op);
-		emittree(np->right);
-		break;
-	}
-}
-static void
-size2asm(Type *tp)
-{
-	char *s;
-
-	if (tp->flags & STRF) {
-		s = "\t.ascii\t";
-	} else {
-		switch (tp->size) {
-		case 1:
-			s = "\t.byte\t";
-			break;
-		case 2:
-			s = "\t.short\t";
-			break;
-		case 4:
-			s = "\t.long\t";
-			break;
-		case 8:
-			s = "\t.quad\t";
-			break;
-		default:
-			s = "\t.space\t%lu,";
-			break;
-		}
-	}
-	printf(s, tp->size);
-}
-
-void
-data(Node *np)
-{
-	size2asm(&np->type);
-	emittree(np);
-	putchar('\n');
-}
-
-static void
-label(Symbol *sym)
-{
-	int seg;
-	char *name = symname(sym);
-	Type *tp = &sym->type;
-
-	if (sym->type.flags & FUNF)
-		seg = CODESEG;
-	else if (sym->type.flags & INITF)
-		seg = DATASEG;
-	else
-		seg = BSSSEG;
-	segment(seg);
-
-	switch (sym->kind) {
-	case SEXTRN:
-		printf("\t.extern\t%s\n", name);
-	case SLOCAL:
-		return;
-	case SGLOB:
-		printf("\t.global\t%s\n", name);
-		if (seg == BSSSEG)
-			printf("\t.comm\t%s,%lu\n", name, tp->size);
-		break;
-	}
-	if (sym->type.align != 1)
-		printf("\t.align\t%lu\n", sym->type.align );
-	printf("%s:\n", name);
-}
-
-void
-defglobal(Symbol *sym)
-{
-	label(sym);
-	if (sym->kind == SEXTRN || (sym->type.flags & INITF))
-		return;
-	size2asm(&sym->type);
-	puts("0");
-}
-
-void
-defpar(Symbol *sym)
-{
-}
-
-void
-defvar(Symbol *sym)
-{
-}
-
-void
-newfun(void)
-{
-}
-
-void
-writeout(void)
-{
-}
-
-void
-endinit(void)
-{
-}
-
-void
-getbblocks(void)
-{
-}
--- a/src/cmd/scc/cc2/target/i386-sysv/optm.c
+++ /dev/null
@@ -1,9 +1,0 @@
-#include <scc/scc.h>
-
-#include "../../cc2.h"
-
-Node *
-optm_dep(Node *np)
-{
-	return np;
-}
--- a/src/cmd/scc/cc2/target/i386-sysv/target.mk
+++ /dev/null
@@ -1,8 +1,0 @@
-OBJ-i386-sysv = $(OBJS)  \
-        target/i386-sysv/cgen.o \
-        target/i386-sysv/optm.o \
-        target/i386-sysv/code.o \
-        target/i386-sysv/types.o
-
-$(LIBEXEC)/cc2-i386-sysv: $(OBJ-i386-sysv)
-	$(CC) $(SCC_LDFLAGS) $(OBJ-i386-sysv) -lscc -o $@
--- a/src/cmd/scc/cc2/target/i386-sysv/types.c
+++ /dev/null
@@ -1,93 +1,0 @@
-#include <scc/scc.h>
-
-#include "../../cc2.h"
-
-
-Type int8type = {
-	.flags  = SIGNF | INTF,
-	.size   = 1,
-	.align  = 1
-};
-
-Type int16type = {
-	.flags  = SIGNF | INTF,
-	.size   = 2,
-	.align  = 2
-};
-
-Type int32type = {
-	.flags  = SIGNF | INTF,
-	.size   = 4,
-	.align  = 4
-};
-
-Type int64type = {
-	.flags  = SIGNF | INTF,
-	.size   = 8,
-	.align  = 4
-};
-
-Type uint8type = {
-	.flags  = INTF,
-	.size   = 1,
-	.align  = 1
-};
-
-Type uint16type = {
-	.flags  = INTF,
-	.size   = 2,
-	.align  = 2
-};
-
-Type uint32type = {
-	.flags  = INTF,
-	.size   = 4,
-	.align  = 2
-};
-
-Type uint64type = {
-	.flags  = INTF,
-	.size   = 8,
-	.align  = 4
-};
-
-Type ptrtype = {
-	.flags  = INTF,
-	.size   = 4,
-	.align  = 4
-};
-
-Type booltype = {
-	.flags  = INTF,
-	.size   = 1,
-	.align  = 1
-};
-
-Type float32type = {
-	.flags  = FLOATF,
-	.size   = 4,
-	.align  = 4
-};
-
-Type float64type = {
-	.flags  = FLOATF,
-	.size   = 8,
-	.align  = 4
-};
-
-Type float80type = {
-	.flags  = FLOATF,
-	.size   = 12,
-	.align  =  4
-};
-
-Type voidtype = {
-	.size = 0,
-	.align = 0
-};
-
-/* this type is not used in this architecture */
-Type arg_type = {
-        .size = 0,
-        .align = 0
-};
--- a/src/cmd/scc/cc2/target/qbe/arch.h
+++ /dev/null
@@ -1,135 +1,0 @@
-enum asmop {
-	ASNOP = 0,
-	ASSTB,
-	ASSTH,
-	ASSTW,
-	ASSTL,
-	ASSTM,
-	ASSTS,
-	ASSTD,
-
-	ASLDSB,
-	ASLDUB,
-	ASLDSH,
-	ASLDUH,
-	ASLDSW,
-	ASLDUW,
-	ASLDL,
-	ASLDS,
-	ASLDD,
-
-	ASADDW,
-	ASSUBW,
-	ASMULW,
-	ASMODW,
-	ASUMODW,
-	ASDIVW,
-	ASUDIVW,
-	ASSHLW,
-	ASSHRW,
-	ASUSHRW,
-	ASLTW,
-	ASULTW,
-	ASGTW,
-	ASUGTW,
-	ASLEW,
-	ASULEW,
-	ASGEW,
-	ASUGEW,
-	ASEQW,
-	ASNEW,
-	ASBANDW,
-	ASBORW,
-	ASBXORW,
-
-	ASADDL,
-	ASSUBL,
-	ASMULL,
-	ASMODL,
-	ASUMODL,
-	ASDIVL,
-	ASUDIVL,
-	ASSHLL,
-	ASSHRL,
-	ASUSHRL,
-	ASLTL,
-	ASULTL,
-	ASGTL,
-	ASUGTL,
-	ASLEL,
-	ASULEL,
-	ASGEL,
-	ASUGEL,
-	ASEQL,
-	ASNEL,
-	ASBANDL,
-	ASBORL,
-	ASBXORL,
-
-	ASADDS,
-	ASSUBS,
-	ASMULS,
-	ASDIVS,
-	ASLTS,
-	ASGTS,
-	ASLES,
-	ASGES,
-	ASEQS,
-	ASNES,
-
-	ASADDD,
-	ASSUBD,
-	ASMULD,
-	ASDIVD,
-	ASLTD,
-	ASGTD,
-	ASLED,
-	ASGED,
-	ASEQD,
-	ASNED,
-
-	ASEXTBW,
-	ASUEXTBW,
-	ASEXTBL,
-	ASUEXTBL,
-	ASEXTHW,
-	ASUEXTHW,
-	ASEXTHL,
-	ASUEXTHL,
-	ASEXTWL,
-	ASUEXTWL,
-
-	ASSTOL,
-	ASSTOW,
-	ASDTOL,
-	ASDTOW,
-
-	ASSWTOD,
-	ASSWTOS,
-	ASSLTOD,
-	ASSLTOS,
-
-	ASEXTS,
-	ASTRUNCD,
-
-	ASJMP,
-	ASBRANCH,
-	ASRET,
-	ASCALL,
-	ASCALLE,
-	ASCALLEX,
-	ASPAR,
-	ASPARE,
-	ASALLOC,
-	ASFORM,
-
-	ASCOPYB,
-	ASCOPYH,
-	ASCOPYW,
-	ASCOPYL,
-	ASCOPYS,
-	ASCOPYD,
-
-	ASVSTAR,
-	ASVARG,
-};
--- a/src/cmd/scc/cc2/target/qbe/cgen.c
+++ /dev/null
@@ -1,727 +1,0 @@
-#include <assert.h>
-#include <stdlib.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-
-#include "arch.h"
-#include "../../cc2.h"
-
-enum sflags {
-	ISTMP  = 1,
-	ISCONS = 2
-};
-
-static char opasmw[] = {
-	[OADD] = ASADDW,
-	[OSUB] = ASSUBW,
-	[OMUL] = ASMULW,
-	[OMOD] = ASMODW,
-	[ODIV] = ASDIVW,
-	[OSHL] = ASSHLW,
-	[OSHR] = ASSHRW,
-	[OLT] = ASLTW,
-	[OGT] = ASGTW,
-	[OLE] = ASLEW,
-	[OGE] = ASGEW,
-	[OEQ] = ASEQW,
-	[ONE] = ASNEW,
-	[OBAND] = ASBANDW,
-	[OBOR] = ASBORW,
-	[OBXOR] = ASBXORW,
-};
-
-static char opasml[] = {
-	[OADD] = ASADDL,
-	[OSUB] = ASSUBL,
-	[OMUL] = ASMULL,
-	[OMOD] = ASMODL,
-	[ODIV] = ASDIVL,
-	[OSHL] = ASSHLL,
-	[OSHR] = ASSHRL,
-	[OLT] = ASLTL,
-	[OGT] = ASGTL,
-	[OLE] = ASLEL,
-	[OGE] = ASGEL,
-	[OEQ] = ASEQL,
-	[ONE] = ASNEL,
-	[OBAND] = ASBANDL,
-	[OBOR] = ASBORL,
-	[OBXOR] = ASBXORL,
-};
-
-static char opasms[] = {
-	[OADD] = ASADDS,
-	[OSUB] = ASSUBS,
-	[OMUL] = ASMULS,
-	[ODIV] = ASDIVS,
-	[OLT] = ASLTS,
-	[OGT] = ASGTS,
-	[OLE] = ASLES,
-	[OGE] = ASGES,
-	[OEQ] = ASEQS,
-	[ONE] = ASNES,
-};
-static char opasmd[] = {
-	[OADD] = ASADDD,
-	[OSUB] = ASSUBD,
-	[OMUL] = ASMULD,
-	[ODIV] = ASDIVD,
-	[OLT] = ASLTD,
-	[OGT] = ASGTD,
-	[OLE] = ASLED,
-	[OGE] = ASGED,
-	[OEQ] = ASEQD,
-	[ONE] = ASNED,
-};
-
-extern Type int32type, uint32type, ptrtype;
-
-static Node *
-tmpnode(Node *np, Type *tp)
-{
-	char flags;
-	Symbol *sym;
-
-	if (!np)
-		np = node(OTMP);
-	sym = getsym(TMPSYM);
-	sym->type = np->type = *tp;
-	flags = tp->flags & ~(PARF|INITF);
-	sym->type.flags = np->type.flags = flags;
-	sym->kind = STMP;
-	np->left = np->right = NULL;
-	np->u.sym = sym;
-	np->op = OTMP;
-	np->flags |= ISTMP;
-	return np;
-}
-
-static Node *
-load(Type *tp, Node *np, Node *new)
-{
-	int op;
-	int flags = tp->flags;
-
-	if (flags & (AGGRF|FUNF)) {
-		*new = *np;
-		return new;
-	}
-	switch (tp->size) {
-	case 1:
-		op = ASLDSB;
-		break;
-	case 2:
-		op = ASLDSH;
-		break;
-	case 4:
-		op = (flags & FLOATF) ? ASLDS : ASLDSW;
-		break;
-	case 8:
-		op = (flags & FLOATF) ? ASLDD : ASLDL;
-		break;
-	default:
-		abort();
-	}
-	/*
-	 * unsigned version of operations are always +1 the
-	 * signed version
-	 */
-	if ((flags & (INTF|SIGNF)) == INTF && tp->size < 8)
-		++op;
-
-	code(op, tmpnode(new, tp), np, NULL);
-
-	return new;
-}
-
-static Node *rhs(Node *np, Node *new);
-
-static Node *
-cast(Type *td, Node *ns, Node *nd)
-{
-	Type *ts;
-	Node aux1, aux2;
-	int op, d_isint, s_isint;
-
-	ts = &ns->type;
-	d_isint = (td->flags & INTF) != 0;
-	s_isint = (ts->flags & INTF) != 0;
-
-	if (d_isint && s_isint) {
-		if (td->size <= ts->size) {
-			*nd = *ns;
-			return nd;
-		}
-		assert(td->size == 4 || td->size == 8);
-		switch (ts->size) {
-		case 1:
-			op = (td->size == 4) ? ASEXTBW : ASEXTBL;
-			break;
-		case 2:
-			op = (td->size == 4) ? ASEXTHW : ASEXTHL;
-			break;
-		case 4:
-			op = ASEXTWL;
-			break;
-		default:
-			abort();
-		}
-		/*
-		 * unsigned version of operations are always +1 the
-		 * signed version
-		 */
-		op += (ts->flags & SIGNF) == 0;
-	} else if (d_isint) {
-		/* conversion from float to int */
-		switch (ts->size) {
-		case 4:
-			op = (td->size == 8) ? ASSTOL : ASSTOW;
-			break;
-		case 8:
-			op = (td->size == 8) ? ASDTOL : ASDTOW;
-			break;
-		default:
-			abort();
-		}
-		/* TODO: Add signess */
-	} else if (s_isint) {
-		/* conversion from int to float */
-		switch (ts->size) {
-		case 1:
-		case 2:
-			ts = (ts->flags&SIGNF) ? &int32type : &uint32type;
-			ns = cast(ts, ns, tmpnode(&aux2, ts));
-		case 4:
-			op = (td->size == 8) ? ASSWTOD : ASSWTOS;
-			break;
-		case 8:
-			op = (td->size == 8) ? ASSLTOD : ASSLTOS;
-			break;
-		default:
-			abort();
-		}
-		/* TODO: Add signess */
-	} else {
-		/* conversion from float to float */
-		op = (td->size == 4) ? ASEXTS : ASTRUNCD;
-	}
-
-	code(op, tmpnode(nd, td), ns, NULL);
-	return nd;
-}
-
-static Node *
-call(Node *np, Node *fun, Node *ret)
-{
-	int n, op;
-	Type *tp;
-	Node aux, **q, *p, *pars[NR_FUNPARAM];
-
-	for (n = 0, p = np->right; p; p = p->right)
-		pars[n++] = rhs(p->left, node(OTMP));
-
-	tp = &np->type;
-	code(ASCALL, tmpnode(ret, tp), fun, NULL);
-
-	for (q = pars; q < &pars[n]; ++q) {
-		op = (q == &pars[n-1]) ? ASPARE : ASPAR;
-		tmpnode(&aux, &(*q)->type);
-		code(op, NULL, *q, &aux);
-	}
-	code((np->op == OCALL) ? ASCALLE : ASCALLEX, NULL, NULL, NULL);
-
-	return ret;
-}
-
-static Node *
-assign(Type *tp, Node *to, Node *from)
-{
-	int op;
-
-	switch (tp->size) {
-	case 1:
-		op = ASSTB;
-		break;
-	case 2:
-		op = ASSTH;
-		break;
-	case 4:
-		op = (tp->flags & FLOATF) ? ASSTS : ASSTW;
-		break;
-	case 8:
-		op = (tp->flags & FLOATF) ? ASSTD : ASSTL;
-		break;
-	default:
-		op = ASSTM;
-		break;
-	}
-	code(op, to, from, NULL);
-	return from;
-}
-
-static Node *
-copy(Type *tp, Node *to, Node *from)
-{
-	int op;
-
-	switch (tp->size) {
-	case 1:
-		op = ASCOPYB;
-		break;
-	case 2:
-		op = ASCOPYH;
-		break;
-	case 4:
-		op = (tp->flags & FLOATF) ? ASCOPYS : ASCOPYW;
-		break;
-	case 8:
-		op = (tp->flags & FLOATF) ? ASCOPYD : ASCOPYL;
-		break;
-	default:
-		/* TODO: Need to handle the general case */
-		abort();
-	}
-	code(op, to, from, NULL);
-	return from;
-}
-
-/* TODO: Do field() transformation in sethi */
-
-static Node *
-field(Node *np, Node *ret, int islhs)
-{
-	Node base, node, off, add, *addr;
-	TUINT offset = np->right->u.sym->u.off;
-
-	addr = rhs(np->left, &base);
-
-	if (offset != 0) {
-		node.op = OADD;
-		node.type = ptrtype;
-		node.left = addr;
-		node.right = constnode(&off, offset, &ptrtype);
-		addr = rhs(&node, &add);
-	}
-
-	if (islhs)
-		*ret = *addr;
-	else
-		load(&np->type, addr, ret);
-
-	return ret;
-}
-
-static Node *
-lhs(Node *np, Node *new)
-{
-	switch (np->op) {
-	case OMEM:
-	case OAUTO:
-		*new = *np;
-		return new;
-	case OPTR:
-		return rhs(np->left, new);
-	case OFIELD:
-		return field(np, new, 1);
-	default:
-		abort();
-	}
-}
-
-static void
-bool(Node *np, Symbol *true, Symbol *false)
-{
-	Node *l = np->left, *r = np->right;
-	Node ret, ifyes, ifno;
-	Symbol *label;
-
-	switch (np->op) {
-	case ONEG:
-		bool(l, false, true);
-		break;
-	case OAND:
-		label = newlabel();
-		bool(l, label, false);
-		setlabel(label);
-		bool(r, true, false);
-		break;
-	case OOR:
-		label = newlabel();
-		bool(l, true, label);
-		setlabel(label);
-		bool(r, true, false);
-		break;
-	default:
-		label2node(&ifyes, true);
-		label2node(&ifno, false);
-		code(ASBRANCH, rhs(np, &ret), &ifyes, &ifno);
-		break;
-	}
-}
-
-static Node *
-ternary(Node *np, Node *ret)
-{
-	Node ifyes, ifno, phi, *colon, aux1, aux2, aux3;
-
-	tmpnode(ret, &np->type);
-	label2node(&ifyes, NULL);
-	label2node(&ifno, NULL);
-	label2node(&phi, NULL);
-
-	colon = np->right;
-	code(ASBRANCH, rhs(np->left, &aux1), &ifyes, &ifno);
-
-	setlabel(ifyes.u.sym);
-	copy(&ret->type, ret, rhs(colon->left, &aux2));
-	code(ASJMP, NULL, &phi, NULL);
-
-	setlabel(ifno.u.sym);
-	copy(&ret->type, ret, rhs(colon->right, &aux3));
-	setlabel(phi.u.sym);
-
-	return ret;
-}
-
-static Node *
-function(void)
-{
-	Node aux;
-	Symbol *p;
-
-	/* allocate stack space for parameters */
-	for (p = locals; p && (p->type.flags & PARF) != 0; p = p->next)
-		code(ASALLOC, label2node(&aux, p), NULL, NULL);
-
-	/* allocate stack space for local variables) */
-	for ( ; p && p->id != TMPSYM; p = p->next) {
-		if (p->kind != SAUTO)
-			continue;
-		code(ASALLOC, label2node(&aux, p), NULL, NULL);
-	}
-	/* store formal parameters in parameters */
-	for (p = locals; p; p = p->next) {
-		if ((p->type.flags & PARF) == 0)
-			break;
-		code(ASFORM, label2node(&aux, p), NULL, NULL);
-	}
-	return NULL;
-}
-
-static void
-swtch_if(Node *idx)
-{
-	Node aux1, aux2, *np;
-	Symbol *deflabel = NULL;
-
-	for (;;) {
-		np = delstmt();
-		setlabel(np->label);
-
-		switch (np->op) {
-		case OESWITCH:
-			if (!deflabel)
-				deflabel = np->u.sym;
-			aux1.op = OJMP;
-			aux1.label = NULL;
-			aux1.u.sym = deflabel;
-			cgen(&aux1);
-			return;
-		case OCASE:
-			aux1 = *np;
-			aux1.op = OBRANCH;
-			aux1.label = NULL;
-			aux1.left = &aux2;
-
-			aux2.op = OEQ;
-			aux2.type = idx->type;
-			aux2.left = np->left;
-			aux2.right = idx;
-
-			cgen(&aux1);
-			break;
-		case ODEFAULT:
-			deflabel = np->u.sym;
-			break;
-		default:
-			abort();
-		}
-	}
-}
-
-static Node *
-rhs(Node *np, Node *ret)
-{
-	Node aux1, aux2, *phi, *l = np->left, *r = np->right;
-	Type *tp;
-	int off, op;
-	char *tbl;
-	Symbol *true, *false;
-
-	tp = &np->type;
-
-	switch (np->op) {
-	case OBFUN:
-		return function();
-	case ONOP:
-	case OBLOOP:
-	case OELOOP:
-	case OEFUN:
-		return NULL;
-	case OTMP:
-	case OCONST:
-		*ret = *np;
-		return np;
-	case OMEM:
-	case OAUTO:
-		return load(tp, np, ret);
-	case ONEG:
-	case OAND:
-	case OOR:
-		true = newlabel();
-		false = newlabel();
-		phi = label2node(&aux1, NULL);
-		tmpnode(ret, &int32type);
-
-		bool(np, true, false);
-
-		setlabel(true);
-		code(ASCOPYW, ret, constnode(&aux2, 1, &int32type), NULL);
-		code(ASJMP, NULL, phi, NULL);
-
-		setlabel(false);
-		code(ASCOPYW, ret, constnode(&aux2, 0, &int32type), NULL);
-
-		setlabel(phi->u.sym);
-		return ret;
-        case OMOD:
-        case OSHR:
-		assert(tp->flags & INTF);
-        case ODIV:
-        case OLT:
-        case OGT:
-        case OLE:
-        case OGE:
-                /*
-                 * unsigned version of operations are always +1 the
-                 * signed version
-                 */
-                off = (tp->flags & SIGNF) == 0;
-                goto binary;
-        case OSHL:
-        case OBAND:
-        case OBOR:
-        case OBXOR:
-		assert(tp->flags & INTF);
-        case OADD:
-        case OSUB:
-        case OMUL:
-        case OEQ:
-        case ONE:
-                off = 0;
-        binary:
-		if (l->complex >= r->complex) {
-			rhs(l, &aux1);
-			rhs(r, &aux2);
-		} else {
-			rhs(r, &aux2);
-			rhs(l, &aux1);
-		}
-                switch (tp->size) {
-                case 4:
-                        tbl = (tp->flags & FLOATF) ? opasms : opasmw;
-                        break;
-                case 8:
-                        tbl = (tp->flags & FLOATF) ? opasmd : opasml;
-                        break;
-                default:
-                        abort();
-                }
-                op = tbl[np->op] + off;
-		tmpnode(ret, tp);
-                code(op, ret, &aux1, &aux2);
-                return ret;
-	case OCALL:
-	case OCALLE:
-		if (l->op == OPTR)
-			l = rhs(l, &aux1);
-		return call(np, l, ret);
-	case OCAST:
-		return cast(tp, rhs(l, &aux1), ret);
-	case OASSIG:
-		/* TODO: Do this transformations in sethi */
-		switch (np->u.subop) {
-		case OINC:
-			op = OADD;
-			goto post_oper;
-		case ODEC:
-			op = OSUB;
-		post_oper:
-			aux1.op = op;
-			aux1.left = rhs(l, ret);
-			aux1.right = r;
-			aux1.type = np->type;
-			rhs(&aux1, &aux2);
-			lhs(l, &aux1);
-			assign(tp, &aux1, &aux2);
-			break;
-		default:
-			aux2.type = np->type;
-			aux2.op = np->u.subop;
-			aux2.right = np->right;
-			aux2.left = np->left;
-			r = rhs(&aux2, &aux1);
-			Node aux3;
-			if (l->op == OCAST) {
-				aux3.type = l->left->type;
-				aux3.op = OCAST;
-				aux3.left = r;
-				aux3.right = NULL;
-				r = &aux3;
-				l = l->left;
-			}
-		case 0:
-			/* TODO: see what is the most difficult */
-			lhs(l, &aux2);
-			rhs(r, ret);
-			return assign(tp, &aux2, ret);
-		}
-		return ret;
-	case OASK:
-		return ternary(np, ret);
-	case OCOMMA:
-		rhs(l, &aux1);
-		return rhs(r, ret);
-	case OPTR:
-		return load(tp, rhs(l, &aux1), ret);
-	case OADDR:
-		lhs(l, ret);
-		ret->type = *tp;
-		return ret;
-	case OFIELD:
-		return field(np, ret, 0);
-	case OBUILTIN:
-		switch (np->u.subop) {
-		case BVA_START:
-			l = rhs(l, &aux1);
-			code(ASVSTAR, NULL, l, NULL);
-			return NULL;
-		case BVA_END:
-			return NULL;
-		case BVA_ARG:
-			l = rhs(l, &aux1);
-			code(ASVARG, tmpnode(ret, tp), l, NULL);
-			return ret;
-		case BVA_COPY:
-			/* TODO */
-		default:
-			abort();
-		}
-	default:
-		abort();
-	}
-	abort();
-}
-
-Node *
-cgen(Node *np)
-{
-	Node aux, *p, *next;
-
-	setlabel(np->label);
-	switch (np->op) {
-	case OJMP:
-		label2node(&aux, np->u.sym);
-		code(ASJMP, NULL, &aux, NULL);
-		break;
-	case OBRANCH:
-		next = np->next;
-		if (!next->label)
-			next->label = newlabel();
-		bool(np->left, np->u.sym, next->label);
-		break;
-	case ORET:
-		p = (np->left) ? rhs(np->left, &aux) : NULL;
-		code(ASRET, NULL, p, NULL);
-		break;
-	case OBSWITCH:
-		p = rhs(np->left, &aux);
-		swtch_if(p);
-		break;
-	default:
-		rhs(np, &aux);
-		break;
-	}
-	return 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
- *     REG => 11           reg
- *     STATIC => 11        (value)
- *     CONST => 11         $value
- * These values of addressability are not used in the code generation.
- * They are only used to calculate the Sethi-Ullman numbers. Since
- * QBE is AMD64 targered we could do a better job there, and try to
- * detect some of the complex addressing modes of these processors.
- */
-Node *
-sethi(Node *np)
-{
-	Node *lp, *rp;
-
-	if (!np)
-		return np;
-
-	np->complex = 0;
-	np->address = 0;
-	lp = np->left;
-	rp = np->right;
-
-	switch (np->op) {
-	case OAUTO:
-	case OREG:
-	case OMEM:
-	case OCONST:
-		np->address = 11;
-		break;
-	case OCPL:
-		assert(np->type.flags & INTF);
-		np->op = OBXOR;
-		rp = constnode(NULL, ~(TUINT) 0, &np->type);
-		goto binary;
-	case OSNEG:
-		np->op = OSUB;
-		rp = lp;
-		lp = constnode(NULL, 0, &np->type);
-		if ((np->type.flags & INTF) == 0)
-			lp->u.f = 0.0;
-	default:
-	binary:
-		lp = sethi(lp);
-		rp = sethi(rp);
-		break;
-	}
-	np->left = lp;
-	np->right = rp;
-
-	if (np->address > 10)
-		return np;
-	if (lp)
-		np->complex = lp->complex;
-	if (rp) {
-		int 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;
-}
--- a/src/cmd/scc/cc2/target/qbe/code.c
+++ /dev/null
@@ -1,567 +1,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-
-#include "arch.h"
-#include "../../cc2.h"
-
-#define ADDR_LEN (INTIDENTSIZ+64)
-
-static void binary(void), unary(void), store(void), jmp(void), ret(void),
-            branch(void), call(void), ecall(void), param(void),
-            asalloc(void), form2local(void), ldir(void), vastart(void),
-            vaarg(void);
-
-static struct opdata {
-	void (*fun)(void);
-	char *txt;
-	char letter;
-} optbl [] = {
-	[ASLDSB]  =  {.fun = unary,  .txt = "loadsb", .letter = 'w'},
-	[ASLDUB]  =  {.fun = unary,  .txt = "loadub", .letter = 'w'},
-	[ASLDSH]  =  {.fun = unary,  .txt = "loadsh", .letter = 'w'},
-	[ASLDUH]  =  {.fun = unary,  .txt = "loaduh", .letter = 'w'},
-	[ASLDSW]  =  {.fun = unary,  .txt = "loadsw", .letter = 'w'},
-	[ASLDUW]  =  {.fun = unary,  .txt = "loaduw", .letter = 'w'},
-	[ASLDL]   =  {.fun = unary,  .txt = "loadl", .letter = 'l'},
-	[ASLDS]   =  {.fun = unary,  .txt = "loads", .letter = 's'},
-	[ASLDD]   =  {.fun = unary,  .txt = "loadd", .letter = 'd'},
-
-	[ASCOPYB] =  {.fun = unary,  .txt = "copy", .letter = 'b'},
-	[ASCOPYH] =  {.fun = unary,  .txt = "copy", .letter = 'h'},
-	[ASCOPYW] =  {.fun = unary,  .txt = "copy", .letter = 'w'},
-	[ASCOPYL] =  {.fun = unary,  .txt = "copy", .letter = 'l'},
-	[ASCOPYS] =  {.fun = unary,  .txt = "copy", .letter = 's'},
-	[ASCOPYD] =  {.fun = unary,  .txt = "copy", .letter = 'd'},
-
-	[ASSTB]   =  {.fun = store,  .txt = "store", .letter = 'b'},
-	[ASSTH]   =  {.fun = store,  .txt = "store", .letter = 'h'},
-	[ASSTW]   =  {.fun = store,  .txt = "store", .letter = 'w'},
-	[ASSTL]   =  {.fun = store,  .txt = "store", .letter = 'l'},
-	[ASSTM]   =  {.fun = ldir},
-	[ASSTS]   =  {.fun = store,  .txt = "store", .letter = 's'},
-	[ASSTD]   =  {.fun = store,  .txt = "store", .letter = 'd'},
-
-	[ASADDW]  =  {.fun = binary, .txt = "add", .letter = 'w'},
-	[ASSUBW]  =  {.fun = binary, .txt = "sub", .letter = 'w'},
-	[ASMULW]  =  {.fun = binary, .txt = "mul", .letter = 'w'},
-	[ASMODW]  =  {.fun = binary, .txt = "rem", .letter = 'w'},
-	[ASUMODW] =  {.fun = binary, .txt = "urem", .letter = 'w'},
-	[ASDIVW]  =  {.fun = binary, .txt = "div", .letter = 'w'},
-	[ASUDIVW] =  {.fun = binary, .txt = "udiv", .letter = 'w'},
-	[ASSHLW]  =  {.fun = binary, .txt = "shl", .letter = 'w'},
-	[ASSHRW]  =  {.fun = binary, .txt = "sar", .letter = 'w'},
-	[ASUSHRW] =  {.fun = binary, .txt = "shr", .letter = 'w'},
-	[ASLTW]   =  {.fun = binary, .txt = "csltw", .letter = 'w'},
-	[ASULTW]  =  {.fun = binary, .txt = "cultw", .letter = 'w'},
-	[ASGTW]   =  {.fun = binary, .txt = "csgtw", .letter = 'w'},
-	[ASUGTW]  =  {.fun = binary, .txt = "cugtw", .letter = 'w'},
-	[ASLEW]   =  {.fun = binary, .txt = "cslew", .letter = 'w'},
-	[ASULEW]  =  {.fun = binary, .txt = "culew", .letter = 'w'},
-	[ASGEW]   =  {.fun = binary, .txt = "csgew", .letter = 'w'},
-	[ASUGEW]  =  {.fun = binary, .txt = "cugew", .letter = 'w'},
-	[ASEQW]   =  {.fun = binary, .txt = "ceqw", .letter = 'w'},
-	[ASNEW]   =  {.fun = binary, .txt = "cnew", .letter = 'w'},
-	[ASBANDW] =  {.fun = binary, .txt = "and", .letter = 'w'},
-	[ASBORW]  =  {.fun = binary, .txt = "or", .letter = 'w'},
-	[ASBXORW] =  {.fun = binary, .txt = "xor", .letter = 'w'},
-
-	[ASADDL]  =  {.fun = binary, .txt = "add", .letter = 'l'},
-	[ASSUBL]  =  {.fun = binary, .txt = "sub", .letter = 'l'},
-	[ASMULL]  =  {.fun = binary, .txt = "mul", .letter = 'l'},
-	[ASMODL]  =  {.fun = binary, .txt = "rem", .letter = 'l'},
-	[ASUMODL] =  {.fun = binary, .txt = "urem", .letter = 'l'},
-	[ASDIVL]  =  {.fun = binary, .txt = "div", .letter = 'l'},
-	[ASUDIVL] =  {.fun = binary, .txt = "udiv", .letter = 'l'},
-	[ASSHLL]  =  {.fun = binary, .txt = "shl", .letter = 'l'},
-	[ASSHRL]  =  {.fun = binary, .txt = "sar", .letter = 'l'},
-	[ASUSHRL] =  {.fun = binary, .txt = "shr", .letter = 'l'},
-	[ASLTL]   =  {.fun = binary, .txt = "csltl", .letter = 'w'},
-	[ASULTL]  =  {.fun = binary, .txt = "cultl", .letter = 'w'},
-	[ASGTL]   =  {.fun = binary, .txt = "csgtl", .letter = 'w'},
-	[ASUGTL]  =  {.fun = binary, .txt = "cugtl", .letter = 'w'},
-	[ASLEL]   =  {.fun = binary, .txt = "cslel", .letter = 'w'},
-	[ASULEL]  =  {.fun = binary, .txt = "culel", .letter = 'w'},
-	[ASGEL]   =  {.fun = binary, .txt = "csgel", .letter = 'w'},
-	[ASUGEL]  =  {.fun = binary, .txt = "cugel", .letter = 'w'},
-	[ASEQL]   =  {.fun = binary, .txt = "ceql", .letter = 'w'},
-	[ASNEL]   =  {.fun = binary, .txt = "cnel", .letter = 'w'},
-	[ASBANDL] =  {.fun = binary, .txt = "and", .letter = 'l'},
-	[ASBORL]  =  {.fun = binary, .txt = "or", .letter = 'l'},
-	[ASBXORL] =  {.fun = binary, .txt = "xor", .letter = 'l'},
-
-	[ASADDS]  =  {.fun = binary, .txt = "add", .letter = 's'},
-	[ASSUBS]  =  {.fun = binary, .txt = "sub", .letter = 's'},
-	[ASMULS]  =  {.fun = binary, .txt = "mul", .letter = 's'},
-	[ASDIVS]  =  {.fun = binary, .txt = "div", .letter = 's'},
-	[ASLTS]   =  {.fun = binary, .txt = "clts", .letter = 'w'},
-	[ASGTS]   =  {.fun = binary, .txt = "cgts", .letter = 'w'},
-	[ASLES]   =  {.fun = binary, .txt = "cles", .letter = 'w'},
-	[ASGES]   =  {.fun = binary, .txt = "cges", .letter = 'w'},
-	[ASEQS]   =  {.fun = binary, .txt = "ceqs", .letter = 'w'},
-	[ASNES]   =  {.fun = binary, .txt = "cnes", .letter = 'w'},
-
-	[ASADDD]  =  {.fun = binary, .txt = "add", .letter = 'd'},
-	[ASSUBD]  =  {.fun = binary, .txt = "sub", .letter = 'd'},
-	[ASMULD]  =  {.fun = binary, .txt = "mul", .letter = 'd'},
-	[ASDIVD]  =  {.fun = binary, .txt = "div", .letter = 'd'},
-	[ASLTD]   =  {.fun = binary, .txt = "cltd", .letter = 'w'},
-	[ASGTD]   =  {.fun = binary, .txt = "cgtd", .letter = 'w'},
-	[ASLED]   =  {.fun = binary, .txt = "cled", .letter = 'w'},
-	[ASGED]   =  {.fun = binary, .txt = "cged", .letter = 'w'},
-	[ASEQD]   =  {.fun = binary, .txt = "ceqd", .letter = 'w'},
-	[ASNED]   =  {.fun = binary, .txt = "cned", .letter = 'w'},
-
-	[ASEXTBW] =  {.fun = unary, .txt = "extsb", .letter = 'w'},
-	[ASUEXTBW]=  {.fun = unary, .txt = "extub", .letter = 'w'},
-	[ASEXTBL] =  {.fun = unary, .txt = "extsb", .letter = 'l'},
-	[ASUEXTBL]=  {.fun = unary, .txt = "extub", .letter = 'l'},
-	[ASEXTHW] =  {.fun = unary, .txt = "extsh", .letter = 'w'},
-	[ASUEXTHW]=  {.fun = unary, .txt = "extuh", .letter = 'w'},
-	[ASEXTWL] =  {.fun = unary, .txt = "extsw", .letter = 'l'},
-	[ASUEXTWL]=  {.fun = unary, .txt = "extuw", .letter = 'l'},
-
-	[ASSTOL] = {.fun = unary, .txt = "stosi", .letter = 'l'},
-	[ASSTOW] = {.fun = unary, .txt = "stosi", .letter = 'w'},
-	[ASDTOL] = {.fun = unary, .txt = "dtosi", .letter = 'l'},
-	[ASDTOW] = {.fun = unary, .txt = "dtosi", .letter = 'w'},
-
-	[ASSWTOD] = {.fun = unary, .txt = "swtof", .letter = 'd'},
-	[ASSWTOS] = {.fun = unary, .txt = "swtof", .letter = 's'},
-	[ASSLTOD] = {.fun = unary, .txt = "sltof", .letter = 'd'},
-	[ASSLTOS] = {.fun = unary, .txt = "sltof", .letter = 's'},
-
-	[ASEXTS] = {.fun = unary, .txt = "exts", .letter = 'd'},
-	[ASTRUNCD] = {.fun = unary, .txt = "truncd", .letter = 's'},
-
-	[ASBRANCH] = {.fun = branch},
-	[ASJMP]  = {.fun = jmp},
-	[ASRET]  = {.fun = ret},
-	[ASCALL] = {.fun = call},
-	[ASCALLE] = {.fun = ecall, .txt = ")"},
-	[ASCALLEX] = {.fun = ecall, .txt = ", ...)"},
-	[ASPAR] = {.fun = param, .txt = "%s %s, "},
-	[ASPARE] = {.fun = param, .txt = "%s %s"},
-	[ASALLOC] = {.fun = asalloc},
-	[ASFORM] = {.fun = form2local},
-
-	[ASVSTAR] = {.fun = vastart},
-	[ASVARG] = {.fun = vaarg},
-};
-
-static char buff[ADDR_LEN];
-/*
- * : is for user-defined Aggregate Types
- * $ is for globals (represented by a pointer)
- * % is for function-scope temporaries
- * @ is for block labels
- */
-static char
-sigil(Symbol *sym)
-{
-	switch (sym->kind) {
-	case SEXTRN:
-	case SGLOB:
-	case SPRIV:
-	case SLOCAL:
-		return '$';
-	case SAUTO:
-	case STMP:
-		return '%';
-	case SLABEL:
-		return '@';
-	default:
-		abort();
-	}
-}
-
-static char *
-symname(Symbol *sym)
-{
-	char c = sigil(sym);
-
-	if (sym->name) {
-		switch (sym->kind) {
-		case SEXTRN:
-		case SGLOB:
-			sprintf(buff, "%c%s", c, sym->name);
-			return buff;
-		case SLOCAL:
-		case SPRIV:
-		case SAUTO:
-			sprintf(buff, "%c%s.%u", c, sym->name, sym->id);
-			return buff;
-		default:
-			abort();
-		}
-	}
-	sprintf(buff, "%c.%u", c, sym->numid);
-
-	return buff;
-}
-
-static void
-emitconst(Node *np)
-{
-	switch (np->type.size) {
-	case 1:
-		printf("%d", (int) np->u.i & 0xFF);
-		break;
-	case 2:
-		printf("%d", (int) np->u.i & 0xFFFF);
-		break;
-	case 4:
-		printf("%ld", (long) np->u.i & 0xFFFFFFFF);
-		break;
-        case 8:
-                printf("%lld", (long long) np->u.i);
-                break;
-	default:
-		abort();
-	}
-}
-
-static void
-emittree(Node *np)
-{
-	if (!np)
-		return;
-
-	switch (np->op) {
-	case OSTRING:
-		printf("\"%s\"", np->u.s);
-		free(np->u.s);
-		np->u.s = NULL;
-		break;
-	case OCONST:
-		emitconst(np);
-		break;
-	case OADDR:
-		emittree(np->left);
-		break;
-	case OMEM:
-		fputs(symname(np->u.sym), stdout);
-		break;
-	default:
-		emittree(np->left);
-		printf(" %c ", np->op);
-		emittree(np->right);
-		break;
-	}
-}
-
-static char *
-size2asm(Type *tp)
-{
-	if (tp->flags & STRF) {
-		return "b";
-	} else if (tp->flags & INTF) {
-		switch (tp->size) {
-		case 1:
-			return "b";
-		case 2:
-			return "h";
-		case 4:
-			return "w";
-		case 8:
-			return "l";
-		}
-	} else if (tp->flags & FLOATF) {
-		if (tp->size == 4)
-			return "s";
-		else if (tp->size == 8)
-			return "d";
-	}
-	abort();
-}
-
-void
-defglobal(Symbol *sym)
-{
-	if (sym->kind == SEXTRN)
-		return;
-	if (sym->kind == SGLOB)
-		fputs("export ", stdout);
-	printf("data %s = {\n", symname(sym));
-	if (sym->type.flags & INITF)
-		return;
-	printf("\tz\t%lu\n}\n", sym->type.size);
-}
-
-void
-defpar(Symbol *sym)
-{
-	sym->type.flags |= PARF;
-}
-
-void
-defvar(Symbol *sym)
-{
-	if (sym->kind == SREG)
-		sym->kind = SAUTO;
-}
-
-void
-data(Node *np)
-{
-	printf("\t%s\t", size2asm(&np->type));
-	emittree(np);
-	putchar(',');
-	putchar('\n');
-}
-
-static char *
-size2stack(Type *tp)
-{
-	if (tp->flags & INTF) {
-		switch (tp->size) {
-		case 1:
-		case 2:
-		case 4:
-			return "w";
-		case 8:
-			return "l";
-		}
-	} else if (tp->flags & FLOATF) {
-		if (tp->size == 4)
-			return "s";
-		else if (tp->size == 8)
-			return "d";
-	} else if (tp->size == 0) {
-		return "w";
-	}
-	abort();
-}
-
-void
-writeout(void)
-{
-	Symbol *p;
-	Type *tp;
-	char *sep, *name;
-	int haslabel = 0;
-
-	if (!curfun)
-		return;
-	if (curfun->kind == SGLOB)
-		fputs("export ", stdout);
-	printf("function %s %s(", size2stack(&curfun->rtype), symname(curfun));
-
-	/* declare formal parameters */
-	for (sep = "", p = locals; p; p = p->next, sep = ",") {
-		if ((p->type.flags & PARF) == 0)
-			break;
-		printf("%s%s %s.val", sep, size2stack(&p->type), symname(p));
-	}
-	printf("%s)\n{\n", (curfun->type.flags&ELLIPS) ? ", ..." : "");
-
-	/* emit assembler instructions */
-	for (pc = prog; pc; pc = pc->next) {
-		if (pc->label) {
-			haslabel = 1;
-			printf("%s\n", symname(pc->label));
-		}
-		if (!pc->op)
-			continue;
-		if (pc->flags&BBENTRY && !haslabel)
-			printf("%s\n", symname(newlabel()));
-		(*optbl[pc->op].fun)();
-		if (!pc->label)
-			haslabel = 0;
-	}
-
-	puts("}");
-}
-
-static char *
-addr2txt(Addr *a)
-{
-	switch (a->kind) {
-	case SCONST:
-		sprintf(buff, "%llu", (unsigned long long) a->u.i);
-		return buff;
-	case SAUTO:
-	case SLABEL:
-	case STMP:
-	case SGLOB:
-	case SEXTRN:
-	case SPRIV:
-	case SLOCAL:
-		return symname(a->u.sym);
-	default:
-		abort();
-	}
-}
-
-static void
-binary(void)
-{
-	struct opdata *p = &optbl[pc->op];
-	char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN];
-
-	strcpy(to, addr2txt(&pc->to));
-	strcpy(from1, addr2txt(&pc->from1));
-	strcpy(from2, addr2txt(&pc->from2));
-	printf("\t%s =%c\t%s\t%s,%s\n", to, p->letter, p->txt, from1, from2);
-}
-
-static void
-ldir(void)
-{
-	struct opdata *p = &optbl[pc->op];
-	char to[ADDR_LEN], from[ADDR_LEN];
-	/* TODO: what type do we use for the size? */
-
-	/* TODO: it is pending */
-}
-
-static void
-store(void)
-{
-	struct opdata *p = &optbl[pc->op];
-	char to[ADDR_LEN], from[ADDR_LEN];
-
-	strcpy(to, addr2txt(&pc->to));
-	strcpy(from, addr2txt(&pc->from1));
-	printf("\t\t%s%c\t%s,%s\n", p->txt, p->letter, from, to);
-}
-
-static void
-unary(void)
-{
-	struct opdata *p = &optbl[pc->op];
-	char to[ADDR_LEN], from[ADDR_LEN];
-
-	strcpy(to, addr2txt(&pc->to));
-	strcpy(from, addr2txt(&pc->from1));
-	printf("\t%s =%c\t%s\t%s\n", to, p->letter, p->txt, from);
-}
-
-static void
-call(void)
-{
-	struct opdata *p = &optbl[pc->op];
-	char to[ADDR_LEN], from[ADDR_LEN];
-	Symbol *sym = pc->to.u.sym;
-
-	strcpy(to, addr2txt(&pc->to));
-	strcpy(from, addr2txt(&pc->from1));
-	printf("\t%s =%s\tcall\t%s(",
-	       to, size2stack(&sym->type), from);
-}
-
-static void
-param(void)
-{
-	Symbol *sym = pc->from2.u.sym;
-
-	printf(optbl[pc->op].txt,
-	       size2stack(&sym->type), addr2txt(&pc->from1));
-}
-
-static void
-ecall(void)
-{
-	struct opdata *p = &optbl[pc->op];
-
-	puts(p->txt);
-}
-
-static void
-ret(void)
-{
-	if (pc->from1.kind == SNONE)
-		puts("\t\tret");
-	else
-		printf("\t\tret\t%s\n", addr2txt(&pc->from1));
-}
-
-static void
-jmp(void)
-{
-	printf("\t\tjmp\t%s\n", addr2txt(&pc->from1));
-}
-
-static void
-branch(void)
-{
-	char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN];
-
-	strcpy(to, addr2txt(&pc->to));
-	strcpy(from1, addr2txt(&pc->from1));
-	strcpy(from2, addr2txt(&pc->from2));
-	printf("\t\tjnz\t%s,%s,%s\n", to, from1, from2);
-}
-
-static void
-vastart(void)
-{
-	printf("\t\tvastart %s\n", addr2txt(&pc->from1));
-}
-
-static void
-vaarg(void)
-{
-	Symbol *sym = pc->to.u.sym;
-	Type *tp = &sym->type;
-	char to[ADDR_LEN], from[ADDR_LEN];
-
-	strcpy(to, addr2txt(&pc->to));
-	strcpy(from, addr2txt(&pc->from1));
-	printf("\t\t%s =%s vaarg %s\n", to, size2asm(tp), from);
-}
-
-static void
-asalloc(void)
-{
-	Symbol *sym = pc->to.u.sym;
-	Type *tp = &sym->type;
-	extern Type ptrtype;
-
-	printf("\t%s =%s\talloc%lu\t%lu\n",
-	       symname(sym), size2asm(&ptrtype), tp->align+3 & ~3, tp->size);
-}
-
-static void
-form2local(void)
-{
-	Symbol *sym = pc->to.u.sym;
-	Type *tp = &sym->type;
-	char *name = symname(sym);
-
-	printf("\t\tstore%s\t%s.val,%s\n", size2asm(tp), name, name);
-}
-
-void
-endinit(void)
-{
-	puts("}");
-}
-
-void
-getbblocks(void)
-{
-	Inst *i;
-
-	if (!prog)
-		return;
-
-	prog->flags |= BBENTRY;
-	for (pc = prog; pc; pc = pc->next) {
-		switch (pc->op) {
-		case ASBRANCH:
-			i = pc->from2.u.sym->u.inst;
-			i->flags |= BBENTRY;
-		case ASJMP:
-			i = pc->from1.u.sym->u.inst;
-			i->flags |= BBENTRY;
-		case ASRET:
-			if (pc->next)
-				pc->next->flags |= BBENTRY;
-			break;
-		}
-	}
-}
--- a/src/cmd/scc/cc2/target/qbe/optm.c
+++ /dev/null
@@ -1,56 +1,0 @@
-#include <stddef.h>
-
-#include <scc/scc.h>
-
-#include "../../cc2.h"
-
-Node *
-optm_dep(Node *np)
-{
-	int op = np->op;
-	Node *p, *dst, *next = np->next;
-	Symbol *sym, *osym;
-
-	switch (op) {
-	case OEFUN:
-		/*
-		 * In QBE we need at the end of a basic block
-		 * a jump, so we have to ensure that the last
-		 * statement of the function is a ret, a jmp
-		 * or a branch. In the same way, QBE does
-		 * not accept labels at the end of a function
-		 * (ONOP is used for labels) so we have to add
-		 * a ret there, and in the case of branches
-		 * we need a label for the next statement
-		 */
-		op = (np->prev) ? np->prev->op : 0;
-		if (!op || op == ONOP || op == OBRANCH || (op != ORET && op != OJMP))
-			addstmt(node(ORET), KEEPCUR);
-		break;
-	case OBRANCH:
-		if (!next->label) {
-			sym = getsym(TMPSYM);
-			sym->kind = SLABEL;
-			next->label = sym;
-		}
-	case OJMP:
-		for (;;) {
-			dst = np->u.sym->u.stmt;
-			if (dst->op != OJMP)
-				break;
-			np->u.sym = dst->u.sym;
-		}
-		for (p = np->next; p; p = p->next) {
-			if (p == dst)
-				return NULL;
-			if (p->op == ONOP ||
-			    p->op == OBLOOP ||
-			    p->op == OELOOP) {
-				continue;
-			}
-			break;
-		}
-		break;
-	}
-	return np;
-}
--- a/src/cmd/scc/cc2/target/qbe_amd64-sysv/target.mk
+++ /dev/null
@@ -1,8 +1,0 @@
-OBJ-qbe_amd64-sysv = $(OBJS)  \
-        target/qbe/cgen.o \
-        target/qbe/optm.o \
-        target/qbe/code.o \
-        target/amd64-sysv/types.o
-
-$(LIBEXEC)/cc2-qbe_amd64-sysv: $(OBJ-qbe_amd64-sysv)
-	$(CC) $(SCC_LDFLAGS) $(OBJ-qbe_amd64-sysv) -lscc -o $@
--- a/src/cmd/scc/cc2/target/qbe_arm64-sysv/target.mk
+++ /dev/null
@@ -1,5 +1,0 @@
-OBJ-qbe_arm64-sysv = $(OBJS)  \
-        target/qbe/cgen.o \
-        target/qbe/optm.o \
-        target/qbe/code.o \
-        target/arm64-sysv/types.o \
--- a/src/cmd/scc/cc2/target/z80-scc/arch.h
+++ /dev/null
@@ -1,5 +1,0 @@
-enum asmop {
-	ASJMP = 0,
-	ASRET,
-	ASBRANCH,
-};
--- a/src/cmd/scc/cc2/target/z80-scc/cgen.c
+++ /dev/null
@@ -1,159 +1,0 @@
-#include <stdlib.h>
-
-#include <scc/scc.h>
-
-#include "arch.h"
-#include "../../cc2.h"
-
-static void
-swtch(Node *idx)
-{
-}
-
-static Node *
-rhs(Node *np, Node *ret)
-{
-}
-
-static Node *
-field(Node *np, Node *ret, int islhs)
-{
-}
-
-static Node *
-lhs(Node *np, Node *new)
-{
-	switch (np->op) {
-	case OMEM:
-	case OAUTO:
-		*new = *np;
-		return new;
-	case OPTR:
-		return rhs(np->left, new);
-	case OFIELD:
-		return field(np, new, 1);
-	default:
-		abort();
-	}
-}
-
-static void
-bool(Node *np, Symbol *true, Symbol *false)
-{
-	Node *l = np->left, *r = np->right;
-	Node ret, ifyes, ifno;
-	Symbol *label;
-
-	switch (np->op) {
-	case ONEG:
-		bool(l, false, true);
-		break;
-	case OAND:
-		label = newlabel();
-		bool(l, label, false);
-		setlabel(label);
-		bool(r, true, false);
-		break;
-	case OOR:
-		label = newlabel();
-		bool(l, true, label);
-		setlabel(label);
-		bool(r, true, false);
-		break;
-	default:
-		label2node(&ifyes, true);
-		label2node(&ifno, false);
-		code(ASBRANCH, rhs(np, &ret), &ifyes, &ifno);
-		break;
-	}
-}
-
-Node *
-cgen(Node *np)
-{
-	Node aux, *p, *next;
-
-	setlabel(np->label);
-	switch (np->op) {
-	case OJMP:
-		label2node(&aux, np->u.sym);
-		code(ASJMP, NULL, &aux, NULL);
-		break;
-	case OBRANCH:
-		next = np->next;
-		if (!next->label)
-			next->label = newlabel();
-		bool(np->left, np->u.sym, next->label);
-		break;
-	case ORET:
-		p = np->left;
-		if (p)
-			p = rhs(np->left, &aux);
-		code(ASRET, NULL, p, NULL);
-		break;
-	case OBSWITCH:
-		swtch(rhs(np->left, &aux));
-		break;
-	default:
-		rhs(np, &aux);
-		break;
-	}
-	return 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
- *     REG => 13           reg
- *     STATIC => 12        (value)
- *     CONST => 20         $value
- */
-Node *
-sethi(Node *np)
-{
-	Node *lp, *rp;
-
-	if (!np)
-		return np;
-
-	np->complex = 0;
-	np->address = 0;
-	lp = np->left;
-	rp = np->right;
-	switch (np->op) {
-	case OAUTO:
-		np->address = 11;
-		break;
-	case OREG:
-		np->address = 13;
-		break;
-	case OMEM:
-		np->address = 12;
-		break;
-	case OCONST:
-		np->address = 20;
-		break;
-	default:
-		sethi(lp);
-		sethi(rp);
-		break;
-	}
-
-	if (np->address > 10)
-		return np;
-	if (lp)
-		np->complex = lp->complex;
-	if (rp) {
-		int 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;
-}
--- a/src/cmd/scc/cc2/target/z80-scc/code.c
+++ /dev/null
@@ -1,227 +1,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <scc/cstd.h>
-#include <scc/scc.h>
-
-#include "arch.h"
-#include "../../cc2.h"
-
-enum segment {
-	CODESEG,
-	DATASEG,
-	BSSSEG,
-	NOSEG
-};
-
-static int curseg = NOSEG;
-static unsigned long offpar, offvar;
-
-static void
-segment(int seg)
-{
-	static char *txt[] = {
-		[CODESEG] = "\tCSEG\n",
-		[DATASEG] = "\tDSEG\n",
-		[BSSSEG] = "\tASEG\n",
-	};
-
-	if (seg == curseg)
-		return;
-	fputs(txt[seg], stdout);
-	curseg = seg;
-}
-
-static char *
-symname(Symbol *sym)
-{
-	static char name[INTIDENTSIZ+1];
-
-	if (sym->name) {
-		switch (sym->kind) {
-		case SGLOB:
-		case SEXTRN:
-			snprintf(name, sizeof(name), "_%s", sym->name);
-			return name;
-		case SPRIV:
-			return sym->name;
-		}
-	}
-
-	sprintf(name, ".%d", sym->numid);
-
-	return name;
-}
-
-static void
-label(Symbol *sym)
-{
-	int seg;
-	char *name = symname(sym);
-
-	if (sym->type.flags & FUNF)
-		seg = CODESEG;
-	else if (sym->type.flags & INITF)
-		seg = DATASEG;
-	else
-		seg = BSSSEG;
-	segment(seg);
-
-	switch (sym->kind) {
-	case SEXTRN:
-		printf("\tEXTRN\t%s\n", name);
-		return;
-	case SGLOB:
-		printf("\tPUBLIC\t%s\n", name);
-		break;
-	}
-
-	printf("%s:\n", name);
-}
-
-static void
-emitconst(Node *np)
-{
-	switch (np->type.size) {
-	case 1:
-		printf("%d", (int) np->u.i & 0xFF);
-		break;
-	case 2:
-		printf("%d", (int) np->u.i & 0xFFFF);
-		break;
-	case 4:
-		printf("%ld", (long) np->u.i & 0xFFFFFFFF);
-		break;
-	default:
-		abort();
-	}
-}
-
-static void
-emittree(Node *np)
-{
-	if (!np)
-		return;
-
-	switch (np->op) {
-	case OSTRING:
-		printf("\"%s\"", np->u.s);
-		free(np->u.s);
-		np->u.s = NULL;
-		break;
-	case OCONST:
-		emitconst(np);
-		break;
-	case OADDR:
-		emittree(np->left);
-		break;
-	case OMEM:
-		fputs(symname(np->u.sym), stdout);
-		break;
-	default:
-		emittree(np->left);
-		printf(" %c ", np->op);
-		emittree(np->right);
-		break;
-	}
-}
-
-static void
-size2asm(Type *tp)
-{
-	char *s;
-
-	/*
-	 * In z80 we can ignore the alignment
-	 */
-	if (tp->flags & STRF) {
-		s = "\tDB\t";
-	} else {
-		switch (tp->size) {
-		case 1:
-			s = "\tDB\t";
-			break;
-		case 2:
-			s = "\tDW\t";
-			break;
-		case 4:
-			s = "\tDD\t";
-			break;
-		default:
-			s = "\tDS\t%lu,";
-			break;
-		}
-	}
-	printf(s, tp->size);
-}
-
-void
-newfun()
-{
-	offpar = offvar = 0;
-}
-
-void
-defpar(Symbol *sym)
-{
-	unsigned long align, size;
-
-	if (sym->kind != SREG && sym->kind != SAUTO)
-		return;
-	align = sym->type.align;
-	size = sym->type.size;
-
-	offpar -= align-1 & ~align;
-	sym->u.off = offpar;
-	offpar -= size;
-	sym->kind = SAUTO;
-}
-
-void
-defvar(Symbol *sym)
-{
-	unsigned long align, size;
-
-	if (sym->kind != SREG && sym->kind != SAUTO)
-		return;
-	align = sym->type.align;
-	size = sym->type.size;
-
-	offvar += align-1 & ~align;
-	sym->u.off = offvar;
-	offvar += size;
-	sym->kind = SAUTO;
-}
-
-void
-defglobal(Symbol *sym)
-{
-	label(sym);
-	if (sym->kind == SEXTRN || (sym->type.flags & INITF))
-		return;
-	size2asm(&sym->type);
-	puts("0");
-}
-
-void
-data(Node *np)
-{
-	size2asm(&np->type);
-	emittree(np);
-	putchar('\n');
-}
-
-void
-writeout(void)
-{
-}
-
-void
-endinit(void)
-{
-}
-
-void
-getbblocks(void)
-{
-}
--- a/src/cmd/scc/cc2/target/z80-scc/optm.c
+++ /dev/null
@@ -1,9 +1,0 @@
-#include <scc/scc.h>
-
-#include "../../cc2.h"
-
-Node *
-optm_dep(Node *np)
-{
-	return np;
-}
--- a/src/cmd/scc/cc2/target/z80-scc/target.mk
+++ /dev/null
@@ -1,8 +1,0 @@
-OBJ-z80-scc = $(OBJS)  \
-        target/z80-scc/cgen.o \
-        target/z80-scc/optm.o \
-        target/z80-scc/code.o \
-        target/z80-scc/types.o \
-
-$(LIBEXEC)/cc2-z80-scc: $(OBJ-z80-scc)
-	$(CC) $(SCC_LDFLAGS) $(OBJ-z80-scc) -lscc -o $@
--- a/src/cmd/scc/cc2/target/z80-scc/types.c
+++ /dev/null
@@ -1,93 +1,0 @@
-#include <scc/scc.h>
-
-#include "../../cc2.h"
-
-
-Type int8type = {
-	.flags  = SIGNF | INTF,
-	.size   = 1,
-	.align  = 1
-};
-
-Type int16type = {
-	.flags  = SIGNF | INTF,
-	.size   = 2,
-	.align  = 1
-};
-
-Type int32type = {
-	.flags  = SIGNF | INTF,
-	.size   = 4,
-	.align  = 1
-};
-
-Type int64type = {
-	.flags  = SIGNF | INTF,
-	.size   = 8,
-	.align  = 1
-};
-
-Type uint8type = {
-	.flags  = INTF,
-	.size   = 1,
-	.align  = 1
-};
-
-Type uint16type = {
-	.flags  = INTF,
-	.size   = 2,
-	.align  = 1
-};
-
-Type uint32type = {
-	.flags  = INTF,
-	.size   = 4,
-	.align  = 1
-};
-
-Type uint64type = {
-	.flags  = INTF,
-	.size   = 8,
-	.align  = 1
-};
-
-Type ptrtype = {
-	.flags  = INTF,
-	.size   = 2,
-	.align  = 1
-};
-
-Type booltype = {
-	.flags  = INTF,
-	.size   = 1,
-	.align  = 1
-};
-
-Type float32type = {
-	.flags  = FLOATF,
-	.size   = 4,
-	.align  = 1
-};
-
-Type float64type = {
-	.flags  = FLOATF,
-	.size   = 4,
-	.align  = 1
-};
-
-Type float80type = {
-	.flags  = FLOATF,
-	.size   = 4,
-	.align  = 1
-};
-
-Type voidtype = {
-	.size = 0,
-	.align = 0
-};
-
-/* this types is not going to be used in this arch */
-Type arg_type = {
-        .size = 0,
-        .align = 0
-};
--- a/src/cmd/scc/posix/.gitignore
+++ /dev/null
@@ -1,1 +1,0 @@
-config.h
--- a/src/cmd/scc/posix/Makefile
+++ /dev/null
@@ -1,38 +1,0 @@
-.POSIX:
-
-PROJECTDIR = ../../../..
-include $(PROJECTDIR)/scripts/rules.mk
-
-# SYSLST is a list of backend-arch-abi-sys. First
-# element of the list becomes the default target
-
-SYSLST  = amd64-sysv-linux-elf z80-scc-none-none \
-          i386-sysv-linux-elf amd64-sysv-openbsd-elf
-
-STDCFLAGS =
-
-TARGETS = $(BINDIR)/scc $(BINDIR)/scpp
-
-all: $(TARGETS)
-
-$(BINDIR)/scc: scc.o
-	$(CC) $(SCC_LDFLAGS) scc.o -lscc -o $@
-
-$(BINDIR)/scpp: cpp.sh
-	trap "rm -f $$$$.sh" 0 2 3;\
-	rm -f $@ ;\
-	sed "s%@PREFIX@%$(PREFIX)%" < cpp.sh > $$$$.sh && \
-	chmod +x $$$$.sh && \
-	mv $$$$.sh $@
-
-config.h:
-	PREFIX=$(PREFIX) mkconf $(SYSLST)
-
-dep: inc-dep
-
-clean:
-	rm -f scc scpp *.o
-	rm -f $(TARGETS)
-	rm -f config.h
-
-include deps.mk
--- a/src/cmd/scc/posix/cpp.sh
+++ /dev/null
@@ -1,4 +1,0 @@
-#!/bin/sh
-
-SCCPREFIX=${SCCPREFIX:-@PREFIX@}
-${SCCPREFIX}/bin/scc -E $@
--- a/src/cmd/scc/posix/deps.mk
+++ /dev/null
@@ -1,8 +1,0 @@
-#deps
-./scc.o: $(INCDIR)/scc/scc/arg.h
-./scc.o: $(INCDIR)/scc/scc/ldflags.h
-./scc.o: $(INCDIR)/scc/scc/scc.h
-./scc.o: $(INCDIR)/scc/scc/syscrts.h
-./scc.o: $(INCDIR)/scc/scc/sysincludes.h
-./scc.o: $(INCDIR)/scc/scc/syslibs.h
-./scc.o: ./config.h
--- a/src/cmd/scc/posix/mkconf
+++ /dev/null
@@ -1,16 +1,0 @@
-#!/bin/sh
-
-set -e
-
-rm -f config.h
-trap "rm -f $$.h" 0 2 3
-
-PREFIX=${PREFIX-$HOME}
-
-echo $@ |
-(IFS='- 	' read arch abi sys format r
-echo \#define PREFIX \"$PREFIX\"
-echo \#define ARCH \"$arch\"
-echo \#define SYS  \"$sys\"
-echo \#define ABI  \"$abi\"
-echo \#define FORMAT \"$format\") > $$.h && mv $$.h config.h
--- a/src/cmd/scc/posix/scc.c
+++ /dev/null
@@ -1,620 +1,0 @@
-#define _POSIX_SOURCE
-#define _XOPEN_SOURCE 500
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "config.h"
-#include <scc/arg.h>
-#include <scc/scc.h>
-#include <scc/syscrts.h>
-#include <scc/sysincludes.h>
-#include <scc/syslibs.h>
-#include <scc/ldflags.h>
-
-enum {
-	CC1,
-	TEEIR,
-	CC2,
-	TEEQBE,
-	QBE,
-	TEEAS,
-	AS,
-	LD,
-	STRIP,
-	LAST_TOOL,
-};
-
-static struct tool {
-	char   cmd[PATH_MAX];
-	char   bin[32];
-	char  *outfile;
-	struct items args;
-	unsigned nparams;
-	int    in, out, init;
-	pid_t  pid;
-} tools[] = {
-	[CC1]    = { .cmd = "cc1" },
-	[TEEIR]  = { .bin = "tee",   .cmd = "tee", },
-	[CC2]    = { .cmd = "cc2" },
-	[TEEQBE] = { .bin = "tee",   .cmd = "tee", },
-	[QBE]    = { .bin = "qbe",   .cmd = "qbe", },
-	[TEEAS]  = { .bin = "tee",   .cmd = "tee", },
-	[AS]     = { .bin = "as",    .cmd = "as", },
-	[LD]     = { .bin = "ld",    .cmd = "ld", },
-	[STRIP]  = { .bin = "strip", .cmd = "strip", },
-};
-
-char *argv0;
-static char *arch, *sys, *abi, *format;
-static char *prefix, *objfile, *outfile;
-static char *tmpdir;
-static size_t tmpdirln;
-static struct items objtmp, objout;
-static int Mflag, Eflag, Sflag, Wflag,
-           cflag, dflag, kflag, sflag, Qflag = 1; /* TODO: Remove Qflag */
-static int devnullfd = -1;
-
-extern int failure;
-
-static void
-terminate(void)
-{
-	unsigned i;
-
-	if (!kflag) {
-		for (i = 0; i < objtmp.n; ++i)
-			unlink(objtmp.s[i]);
-	}
-}
-
-static void
-addarg(int tool, char *arg)
-{
-	struct tool *t = &tools[tool];
-
-	if (t->args.n < 1)
-		t->args.n = 1;
-
-	newitem(&t->args, arg);
-}
-
-static void
-setargv0(int tool, char *arg)
-{
-	struct tool *t = &tools[tool];
-
-	if (t->args.n > 0)
-		t->args.s[0] = arg;
-	else
-		newitem(&t->args, arg);
-}
-
-static int
-qbe(int tool)
-{
-	if (tool != CC2 || !Qflag)
-		return 0;
-	if (!strcmp(arch, "amd64") && !strcmp(abi, "sysv"))
-		return 1;
-	return 0;
-}
-
-static int
-inittool(int tool)
-{
-	struct tool *t = &tools[tool];
-	char *crt, *fmt;
-	int n;
-
-	if (t->init)
-		return tool;
-
-	switch (tool) {
-	case CC1:
-		if (Wflag)
-			addarg(tool, "-w");
-		for (n = 0; sysincludes[n]; ++n) {
-			addarg(tool, "-I");
-			addarg(tool, sysincludes[n]);
-		}
-	case CC2:
-		fmt = (qbe(tool)) ? "%s-qbe_%s-%s" : "%s-%s-%s";
-		n = snprintf(t->bin, sizeof(t->bin), fmt, t->cmd, arch, abi);
-		if (n < 0 || n >= sizeof(t->bin))
-			die("scc: target tool name too long");
-
-		n = snprintf(t->cmd, sizeof(t->cmd),
-		             "%s/libexec/scc/%s", prefix, t->bin);
-		if (n < 0 || n >= sizeof(t->cmd))
-			die("scc: target tool path too long");
-		break;
-	case LD:
-		for (n = 0; ldflags[n]; ++n)
-			addarg(tool, ldflags[n]);
-		addarg(tool, "-o");
-		t->outfile = outfile ? outfile : xstrdup("a.out");
-		addarg(tool, t->outfile);
-		for (n = 0; syslibs[n]; ++n) {
-			addarg(tool, "-L");
-			addarg(tool, syslibs[n]);
-		}
-		if (syscrts[0]) {
-			for (n = 0; syscrts[n]; ++n)
-				addarg(tool, syscrts[n]);
-			break;
-		}
-		n = snprintf(NULL, 0,
-		             "%s/lib/scc/%s-%s-%s/crt.o",
-		             prefix, arch, abi, sys);
-		if (n < 0)
-			die("scc: wrong crt file name");
-		crt = xmalloc(++n);
-		sprintf(crt,
-		        "%s/lib/scc/%s-%s-%s/crt.o",
-		        prefix, arch, abi, sys);
-		addarg(tool, crt);
-		break;
-	case AS:
-		addarg(tool, "-o");
-		break;
-	default:
-		break;
-	}
-
-	setargv0(tool, t->bin);
-	t->nparams = t->args.n;
-	t->init = 1;
-
-	return tool;
-}
-
-static char *
-outfname(char *path, char *type)
-{
-	char *new, sep, *p;
-	size_t newsz, pathln;
-	int tmpfd, n;
-
-	if (path) {
-		sep = '.';
-		if (p = strrchr(path, '/'))
-			path = p + 1;
-		pathln = strlen(path);
-		if (p = strrchr(path, '.'))
-			pathln -= strlen(p);
-	} else {
-		sep = '/';
-		type = "scc-XXXXXX";
-		path = tmpdir;
-		pathln = tmpdirln;
-	}
-
-	newsz = pathln + 1 + strlen(type) + 1;
-	new = xmalloc(newsz);
-	n = snprintf(new, newsz, "%.*s%c%s", (int)pathln, path, sep, type);
-	if (n < 0 || n >= newsz)
-		die("scc: wrong output filename");
-	if (sep == '/') {
-		if ((tmpfd = mkstemp(new)) < 0)
-			die("scc: could not create output file '%s': %s",
-			    new, strerror(errno));
-		close(tmpfd);
-	}
-
-	return new;
-}
-
-static int
-settool(int tool, char *infile, int nexttool)
-{
-	struct tool *t = &tools[tool];
-	unsigned i;
-	int fds[2];
-	static int fdin = -1;
-
-	switch (tool) {
-	case TEEIR:
-		t->outfile = outfname(infile, "ir");
-		addarg(tool, t->outfile);
-		break;
-	case TEEQBE:
-		t->outfile = outfname(infile, "qbe");
-		addarg(tool, t->outfile);
-		break;
-	case TEEAS:
-		t->outfile = outfname(infile, "s");
-		addarg(tool, t->outfile);
-		break;
-	case AS:
-		if (cflag && outfile) {
-			objfile = outfile;
-		} else {
-			objfile = (cflag || kflag) ? infile : NULL;
-			objfile = outfname(objfile, "o");
-		}
-		t->outfile = xstrdup(objfile);
-		addarg(tool, t->outfile);
-		break;
-	case STRIP:
-		if (cflag || kflag) {
-			for (i = 0; i < objout.n; ++i)
-				addarg(tool, xstrdup(objout.s[i]));
-		}
-		if (!cflag && tools[LD].outfile)
-			addarg(tool, tools[LD].outfile);
-		break;
-	default:
-		break;
-	}
-
-	if (fdin > -1) {
-		t->in = fdin;
-		fdin = -1;
-	} else {
-		t->in = -1;
-		if (infile)
-			addarg(tool, xstrdup(infile));
-	}
-
-	if (nexttool < LAST_TOOL) {
-		if (pipe(fds))
-			die("scc: pipe: %s", strerror(errno));
-		t->out = fds[1];
-		fdin = fds[0];
-	} else {
-		t->out = -1;
-	}
-
-	addarg(tool, NULL);
-
-	return tool;
-}
-
-static void
-spawn(int tool)
-{
-	struct tool *t = &tools[tool];
-
-	switch (t->pid = fork()) {
-	case -1:
-		die("scc: %s: %s", t->bin, strerror(errno));
-	case 0:
-		if (t->out > -1)
-			dup2(t->out, 1);
-		if (t->in > -1)
-			dup2(t->in, 0);
-		if (!dflag && tool != CC1 && tool != LD)
-			dup2(devnullfd, 2);
-		execvp(t->cmd, t->args.s);
-		if (dflag) {
-			fprintf(stderr,
-			        "scc: execvp %s: %s\n",
-				t->cmd,
-			        strerror(errno));
-		}
-		abort();
-	default:
-		if (t->in > -1)
-			close(t->in);
-		if (t->out > -1)
-			close(t->out);
-		break;
-	}
-}
-
-static int
-toolfor(char *file)
-{
-	char *dot = strrchr(file, '.');
-
-	if (dot) {
-		if (!strcmp(dot, ".c"))
-			return CC1;
-		if (!strcmp(dot, ".ir"))
-			return CC2;
-		if (!strcmp(dot, ".qbe"))
-			return QBE;
-		if (!strcmp(dot, ".s"))
-			return AS;
-		if (!strcmp(dot, ".o"))
-			return LD;
-		if (!strcmp(dot, ".a"))
-			return LD;
-	} else if (!strcmp(file, "-")) {
-		return CC1;
-	}
-
-	die("scc: do not recognize filetype of %s", file);
-}
-
-static int
-valid(int tool, struct tool *t)
-{
-	int st;
-
-	if (waitpid(t->pid, &st, 0) == -1 || WIFSIGNALED(st))
-		goto internal;
-	if (WIFEXITED(st) && WEXITSTATUS(st) == 0)
-		return 1;
-	if (!failure && (tool == CC1 || tool == LD))
-		goto fail;
-
-internal:
-	fprintf(stderr, "scc:%s: internal error\n", t->bin);
-fail:
-	failure = 1;
-	return 0;
-}
-
-static int
-validatetools(void)
-{
-	struct tool *t;
-	unsigned i;
-	int tool, st, failed = LAST_TOOL;
-
-	for (tool = 0; tool < LAST_TOOL; ++tool) {
-		t = &tools[tool];
-		if (!t->pid)
-			continue;
-		if (!valid(tool, t))
-			failed = tool;
-		if (tool >= failed && t->outfile)
-			unlink(t->outfile);
-		for (i = t->nparams; i < t->args.n; ++i)
-			free(t->args.s[i]);
-		t->args.n = t->nparams;
-		t->pid = 0;
-	}
-	if (failed < LAST_TOOL) {
-		unlink(objfile);
-		free(objfile);
-		objfile = NULL;
-		return 0;
-	}
-
-	return 1;
-}
-
-static int
-buildfile(char *file, int tool)
-{
-	int nexttool;
-
-	for (; tool < LAST_TOOL; tool = nexttool) {
-		switch (tool) {
-		case CC1:
-			if (Eflag || Mflag)
-				nexttool = LAST_TOOL;
-			else
-				nexttool = kflag ? TEEIR : CC2;
-			break;
-		case TEEIR:
-			nexttool = CC2;
-			break;
-		case CC2:
-			if (Qflag)
-				nexttool = kflag ? TEEQBE : QBE;
-			else
-				nexttool = (Sflag || kflag) ? TEEAS : AS;
-			break;
-		case TEEQBE:
-			nexttool = QBE;
-			break;
-		case QBE:
-			nexttool = (Sflag || kflag) ? TEEAS : AS;
-			break;
-		case TEEAS:
-			nexttool = Sflag ? LAST_TOOL : AS;
-			break;
-		case AS:
-			nexttool = LAST_TOOL;
-			break;
-		default:
-			nexttool = LAST_TOOL;
-			continue;
-		}
-
-		spawn(settool(inittool(tool), file, nexttool));
-	}
-
-	return validatetools();
-}
-
-static void
-build(struct items *chain, int link)
-{
-	int i, tool;
-
-	if (link)
-		inittool(LD);
-
-	for (i = 0; i < chain->n; ++i) {
-		if (!strcmp(chain->s[i], "-l")) {
-			if (link) {
-				addarg(LD, xstrdup(chain->s[i++]));
-				addarg(LD, xstrdup(chain->s[i]));
-			} else {
-				++i;
-			}
-			continue;
-		}
-		tool = toolfor(chain->s[i]);
-		if (tool == LD) {
-			if (link)
-				addarg(LD, xstrdup(chain->s[i]));
-			continue;
-		}
-		if (buildfile(chain->s[i], tool)) {
-			if (link)
-				addarg(LD, xstrdup(objfile));
-			newitem((!link || kflag) ? &objout : &objtmp, objfile);
-		}
-	}
-}
-
-static void
-usage(void)
-{
-	fputs("usage: scc [-D def[=val]]... [-U def]... [-I dir]... "
-	       "[-L dir]... [-l dir]...\n"
-	       "           [-dgksw] [-m arch] [-M|-E|-S] [-o outfile] file...\n"
-	       "       scc [-D def[=val]]... [-U def]... [-I dir]... "
-	       "[-L dir]... [-l dir]...\n"
-	       "           [-dgksw] [-m arch] [-M|-E|-S] -c file...\n"
-	       "       scc [-D def[=val]]... [-U def]... [-I dir]... "
-	       "[-L dir]... [-l dir]...\n"
-	       "           [-dgksw] [-m arch] -c -o outfile file\n", stderr);
-	exit(1);
-}
-
-int
-main(int argc, char *argv[])
-{
-	struct items linkchain = { .n = 0, };
-	int link;
-
-	atexit(terminate);
-
-	if (!(arch = getenv("ARCH")))
-		arch = ARCH;
-	if (!(sys = getenv("SYS")))
-		sys = SYS;
-	if (!(abi = getenv("ABI")))
-		abi = ABI;
-	if (!(format = getenv("FORMAT")))
-		format = FORMAT;
-	if (!(prefix = getenv("SCCPREFIX")))
-		prefix = PREFIX;
-
-	ARGBEGIN {
-	case 'D':
-		addarg(CC1, "-D");
-		addarg(CC1, EARGF(usage()));
-		break;
-	case 'M':
-		Mflag = 1;
-		addarg(CC1, "-M");
-		break;
-	case 'E':
-		Eflag = 1;
-		addarg(CC1, "-E");
-		break;
-	case 'I':
-		addarg(CC1, "-I");
-		addarg(CC1, EARGF(usage()));
-		break;
-	case 'L':
-		addarg(LD, "-L");
-		addarg(LD, EARGF(usage()));
-		break;
-	case 'O':
-		EARGF(usage());
-		break;
-	case 'S':
-		Sflag = 1;
-		break;
-	case 'U':
-		addarg(CC1, "-U");
-		addarg(CC1, EARGF(usage()));
-		break;
-	case 'c':
-		cflag = 1;
-		break;
-	case 'd':
-		dflag = 1;
-		break;
-	case 'g':
-		addarg(AS, "-g");
-		addarg(LD, "-g");
-		break;
-	case 'k':
-		kflag = 1;
-		break;
-	case 'l':
-		newitem(&linkchain, "-l");
-		newitem(&linkchain, EARGF(usage()));
-		break;
-	case 'm':
-		arch = EARGF(usage());
-		break;
-	case 'o':
-		outfile = xstrdup(EARGF(usage()));
-		break;
-	case 's':
-		sflag = 1;
-		break;
-	case 't':
-		sys = EARGF(usage());
-		break;
-	case 'w':
-		Wflag = 0;
-		break;
-	case 'W':
-		Wflag = 1;
-		break;
-	case 'q':
-		Qflag = 0;
-		break;
-	case 'Q':
-		Qflag = 1;
-		break;
-	case '-':
-		fprintf(stderr,
-		        "scc: ignored parameter --%s\n", EARGF(usage()));
-		break;
-	default:
-		usage();
-	} ARGOPERAND {
-operand:
-		newitem(&linkchain, ARGOP());
-	} ARGEND
-
-	for (; *argv; --argc, ++argv)
-		goto operand;
-
-	if (Eflag && linkchain.n == 0)
-		newitem(&linkchain, "-");
-
-	if (Eflag && Mflag ||
-            (Eflag || Mflag) && (Sflag || kflag) ||
-	    linkchain.n == 0 ||
-	    linkchain.n > 1 && cflag && outfile)
-		usage();
-
-	if (!dflag) {
-		if ((devnullfd = open("/dev/null", O_WRONLY)) < 0)
-			fputs("scc: could not open /dev/null\n", stderr);
-	}
-
-	if (!(tmpdir = getenv("TMPDIR")) || !tmpdir[0])
-		tmpdir = ".";
-	tmpdirln = strlen(tmpdir);
-
-	build(&linkchain, (link = !(Mflag || Eflag || Sflag || cflag)));
-
-	if (!(link || cflag))
-		return failure;
-
-	if (link && !failure) {
-		addarg(LD, xstrdup("-lc"));
-		spawn(settool(LD, NULL, LAST_TOOL));
-		validatetools();
-	}
-
-	if (sflag) {
-		spawn(settool(inittool(STRIP), NULL, LAST_TOOL));
-		validatetools();
-	}
-
-	return failure;
-}