changelog shortlog tags branches files raw gz bz2 help

Mercurial > hg > plan9front / changeset: add arm64 c compiler and assembler (thanks charles forsyth)

changeset 7140: 1c857cff1d86
parent 7139: fefcbee0b135
child 7141: 4e09a9199097
author: cinap_lenrek@felloff.net
date: Mon, 08 Apr 2019 13:45:49 +0200
files: sys/src/cmd/7a/a.h sys/src/cmd/7a/a.y sys/src/cmd/7a/lex.c sys/src/cmd/7a/mkfile sys/src/cmd/7c/7.out.h sys/src/cmd/7c/cgen.c sys/src/cmd/7c/gc.h sys/src/cmd/7c/list.c sys/src/cmd/7c/machcap.c sys/src/cmd/7c/mkenam sys/src/cmd/7c/mkfile sys/src/cmd/7c/mul.c sys/src/cmd/7c/peep.c sys/src/cmd/7c/reg.c sys/src/cmd/7c/sgen.c sys/src/cmd/7c/swt.c sys/src/cmd/7c/txt.c
description: add arm64 c compiler and assembler (thanks charles forsyth)

this is the the initial sync of charles forsyths plan9 c
compiler suite from http://bitbucket.org/plan9-from-bell-labs/9-cc
at changeset version 54:65fb8bb56c59
     1.1new file mode 100644
     1.2--- /dev/null
     1.3+++ b/sys/src/cmd/7a/a.h
     1.4@@ -0,0 +1,185 @@
     1.5+/*
     1.6+ * arm64
     1.7+ */
     1.8+#include <u.h>
     1.9+#include <libc.h>
    1.10+#include <bio.h>
    1.11+#include "../7c/7.out.h"
    1.12+
    1.13+typedef vlong int64;
    1.14+
    1.15+#ifndef	EXTERN
    1.16+#define	EXTERN	extern
    1.17+#endif
    1.18+
    1.19+typedef	struct	Sym	Sym;
    1.20+typedef	struct	Gen	Gen;
    1.21+typedef	struct	Io	Io;
    1.22+typedef	struct	Hist	Hist;
    1.23+
    1.24+#define	MAXALIGN	7
    1.25+#define	FPCHIP		1
    1.26+#define	NSYMB		8192
    1.27+#define	BUFSIZ		8192
    1.28+#define	HISTSZ		20
    1.29+#define	NINCLUDE	10
    1.30+#define	NHUNK		10000
    1.31+#define	EOF		(-1)
    1.32+#define	IGN		(-2)
    1.33+#define	GETC()		((--fi.c < 0)? filbuf(): *fi.p++ & 0xff)
    1.34+#define	NHASH		503
    1.35+#define	STRINGSZ	200
    1.36+#define	NMACRO		10
    1.37+
    1.38+struct	Sym
    1.39+{
    1.40+	Sym*	link;
    1.41+	char*	macro;
    1.42+	long	value;
    1.43+	ushort	type;
    1.44+	char	*name;
    1.45+	char	sym;
    1.46+};
    1.47+#define	S	((Sym*)0)
    1.48+
    1.49+EXTERN	struct
    1.50+{
    1.51+	char*	p;
    1.52+	int	c;
    1.53+} fi;
    1.54+
    1.55+struct	Io
    1.56+{
    1.57+	Io*	link;
    1.58+	char	b[BUFSIZ];
    1.59+	char*	p;
    1.60+	short	c;
    1.61+	short	f;
    1.62+};
    1.63+#define	I	((Io*)0)
    1.64+
    1.65+EXTERN	struct
    1.66+{
    1.67+	Sym*	sym;
    1.68+	short	type;
    1.69+} h[NSYM];
    1.70+
    1.71+struct	Gen
    1.72+{
    1.73+	Sym*	sym;
    1.74+	int64	offset;
    1.75+	short	type;
    1.76+	short	reg;
    1.77+	short	xreg;
    1.78+	short	name;
    1.79+	short	ext;
    1.80+	double	dval;
    1.81+	char	sval[NSNAME];
    1.82+};
    1.83+
    1.84+struct	Hist
    1.85+{
    1.86+	Hist*	link;
    1.87+	char*	name;
    1.88+	long	line;
    1.89+	long	offset;
    1.90+};
    1.91+#define	H	((Hist*)0)
    1.92+
    1.93+enum
    1.94+{
    1.95+	CLAST,
    1.96+	CMACARG,
    1.97+	CMACRO,
    1.98+	CPREPROC,
    1.99+};
   1.100+
   1.101+EXTERN	char	debug[256];
   1.102+EXTERN	Sym*	hash[NHASH];
   1.103+EXTERN	char*	Dlist[30];
   1.104+EXTERN	int	nDlist;
   1.105+EXTERN	Hist*	ehist;
   1.106+EXTERN	int	newflag;
   1.107+EXTERN	Hist*	hist;
   1.108+EXTERN	char*	hunk;
   1.109+EXTERN	char*	include[NINCLUDE];
   1.110+EXTERN	Io*	iofree;
   1.111+EXTERN	Io*	ionext;
   1.112+EXTERN	Io*	iostack;
   1.113+EXTERN	long	lineno;
   1.114+EXTERN	int	nerrors;
   1.115+EXTERN	long	nhunk;
   1.116+EXTERN	int	ninclude;
   1.117+EXTERN	Gen	nullgen;
   1.118+EXTERN	char*	outfile;
   1.119+EXTERN	int	pass;
   1.120+EXTERN	char*	pathname;
   1.121+EXTERN	long	pc;
   1.122+EXTERN	int	peekc;
   1.123+EXTERN	int	sym;
   1.124+EXTERN	char	symb[NSYMB];
   1.125+EXTERN	int	thechar;
   1.126+EXTERN	char*	thestring;
   1.127+EXTERN	long	thunk;
   1.128+EXTERN	Biobuf	obuf;
   1.129+
   1.130+void*	alloc(long);
   1.131+void*	allocn(void*, long, long);
   1.132+void	errorexit(void);
   1.133+void	pushio(void);
   1.134+void	newio(void);
   1.135+void	newfile(char*, int);
   1.136+Sym*	slookup(char*);
   1.137+Sym*	lookup(void);
   1.138+void	syminit(Sym*);
   1.139+long	yylex(void);
   1.140+int	getc(void);
   1.141+int	getnsc(void);
   1.142+void	unget(int);
   1.143+int	escchar(int);
   1.144+void	cinit(void);
   1.145+void	pinit(char*);
   1.146+void	cclean(void);
   1.147+void	outcode(int, Gen*, int, Gen*);
   1.148+void	outcodec(int, int, Gen*, int, Gen*);
   1.149+void	outcode4(int, Gen*, int, Gen*, Gen*);
   1.150+void	zname(char*, int, int);
   1.151+void	zaddr(Gen*, int);
   1.152+void	ieeedtod(Ieee*, double);
   1.153+int	filbuf(void);
   1.154+Sym*	getsym(void);
   1.155+void	domacro(void);
   1.156+void	macund(void);
   1.157+void	macdef(void);
   1.158+void	macexpand(Sym*, char*);
   1.159+void	macinc(void);
   1.160+void	maclin(void);
   1.161+void	macprag(void);
   1.162+void	macif(int);
   1.163+void	macend(void);
   1.164+void	outhist(void);
   1.165+void	dodefine(char*);
   1.166+void	prfile(long);
   1.167+void	linehist(char*, int);
   1.168+void	gethunk(void);
   1.169+void	yyerror(char*, ...);
   1.170+int	yyparse(void);
   1.171+void	setinclude(char*);
   1.172+int	assemble(char*);
   1.173+
   1.174+/*
   1.175+ *	system-dependent stuff from ../cc/compat.c
   1.176+ */
   1.177+
   1.178+enum				/* keep in synch with ../cc/cc.h */
   1.179+{
   1.180+	Plan9	= 1<<0,
   1.181+	Unix	= 1<<1,
   1.182+	Windows	= 1<<2,
   1.183+};
   1.184+int	mywait(int*);
   1.185+int	mycreat(char*, int);
   1.186+int	systemtype(int);
   1.187+int	pathchar(void);
   1.188+int	myfork(void);
   1.189+void*	mysbrk(ulong);
     2.1new file mode 100644
     2.2--- /dev/null
     2.3+++ b/sys/src/cmd/7a/a.y
     2.4@@ -0,0 +1,878 @@
     2.5+%{
     2.6+#include "a.h"
     2.7+%}
     2.8+%union
     2.9+{
    2.10+	Sym	*sym;
    2.11+	vlong	lval;
    2.12+	double	dval;
    2.13+	char	sval[NSNAME];
    2.14+	Gen	gen;
    2.15+}
    2.16+%left	'|'
    2.17+%left	'^'
    2.18+%left	'&'
    2.19+%left	'<' '>'
    2.20+%left	'+' '-'
    2.21+%left	'*' '/' '%'
    2.22+%token	<lval>	LTYPE0 LTYPE1 LTYPE2 LTYPE3 LTYPE4 LTYPE5
    2.23+%token	<lval>	LTYPE6 LTYPE7 LTYPE8 LTYPE9 LTYPEA
    2.24+%token	<lval>	LTYPEB LTYPEC LTYPED LTYPEE LTYPEF
    2.25+%token	<lval>	LTYPEG LTYPEH LTYPEI LTYPEJ LTYPEK
    2.26+%token	<lval>	LTYPEL LTYPEM LTYPEN LTYPEO LTYPEP LTYPEQ
    2.27+%token	<lval>	LTYPER LTYPES LTYPET LTYPEU LTYPEV LTYPEW LTYPEX LTYPEY LTYPEZ
    2.28+%token	<lval>	LMOVK LDMB LSTXR
    2.29+%token	<lval>	LCONST LSP LSB LFP LPC
    2.30+%token	<lval>	LR LREG LF LFREG LV LVREG LC LCREG LFCR LFCSEL
    2.31+%token	<lval>	LCOND LS LAT LEXT LSPR LSPREG LVTYPE
    2.32+%token	<dval>	LFCONST
    2.33+%token	<sval>	LSCONST
    2.34+%token	<sym>	LNAME LLAB LVAR
    2.35+%type	<lval>	con expr pointer offset sreg spreg
    2.36+%type	<lval>	scon indexreg vset vreglist
    2.37+%type	<gen>	gen rel reg freg vreg shift fcon frcon extreg vlane vgen
    2.38+%type	<gen>	imm ximm name oreg nireg ioreg imsr spr cond sysarg
    2.39+%%
    2.40+prog:
    2.41+|	prog line
    2.42+
    2.43+line:
    2.44+	LLAB ':'
    2.45+	{
    2.46+		if($1->value != pc)
    2.47+			yyerror("redeclaration of %s", $1->name);
    2.48+		$1->value = pc;
    2.49+	}
    2.50+	line
    2.51+|	LNAME ':'
    2.52+	{
    2.53+		$1->type = LLAB;
    2.54+		$1->value = pc;
    2.55+	}
    2.56+	line
    2.57+|	LNAME '=' expr ';'
    2.58+	{
    2.59+		$1->type = LVAR;
    2.60+		$1->value = $3;
    2.61+	}
    2.62+|	LVAR '=' expr ';'
    2.63+	{
    2.64+		if($1->value != $3)
    2.65+			yyerror("redeclaration of %s", $1->name);
    2.66+		$1->value = $3;
    2.67+	}
    2.68+|	';'
    2.69+|	inst ';'
    2.70+|	error ';'
    2.71+
    2.72+inst:
    2.73+/*
    2.74+ * ERET
    2.75+ */
    2.76+	LTYPE0 comma
    2.77+	{
    2.78+		outcode($1, &nullgen, NREG, &nullgen);
    2.79+	}
    2.80+/*
    2.81+ * ADD
    2.82+ */
    2.83+|	LTYPE1 imsr ',' spreg ',' reg
    2.84+	{
    2.85+		outcode($1, &$2, $4, &$6);
    2.86+	}
    2.87+|	LTYPE1 imsr ',' spreg ','
    2.88+	{
    2.89+		outcode($1, &$2, $4, &nullgen);
    2.90+	}
    2.91+|	LTYPE1 imsr ',' reg
    2.92+	{
    2.93+		outcode($1, &$2, NREG, &$4);
    2.94+	}
    2.95+/*
    2.96+ * CLS
    2.97+ */
    2.98+|	LTYPE2 imsr ',' reg
    2.99+	{
   2.100+		outcode($1, &$2, NREG, &$4);
   2.101+	}
   2.102+/*
   2.103+ * MOV
   2.104+ */
   2.105+|	LTYPE3 gen ',' gen
   2.106+	{
   2.107+		outcode($1, &$2, NREG, &$4);
   2.108+	}
   2.109+/*
   2.110+ * MOVK
   2.111+ */
   2.112+|	LMOVK imm ',' reg
   2.113+	{
   2.114+		outcode($1, &$2, NREG, &$4);
   2.115+	}
   2.116+|	LMOVK imm '<' '<' con ',' reg
   2.117+	{
   2.118+		Gen g;
   2.119+		g = nullgen;
   2.120+		g.type = D_CONST;
   2.121+		g.offset = $5;
   2.122+		outcode4($1, &$2, NREG, &g, &$7);
   2.123+	}
   2.124+/*
   2.125+ * B/BL
   2.126+ */
   2.127+|	LTYPE4 comma rel
   2.128+	{
   2.129+		outcode($1, &nullgen, NREG, &$3);
   2.130+	}
   2.131+|	LTYPE4 comma nireg
   2.132+	{
   2.133+		outcode($1, &nullgen, NREG, &$3);
   2.134+	}
   2.135+/*
   2.136+ * BEQ
   2.137+ */
   2.138+|	LTYPE5 comma rel
   2.139+	{
   2.140+		outcode($1, &nullgen, NREG, &$3);
   2.141+	}
   2.142+/*
   2.143+ * SVC
   2.144+ */
   2.145+|	LTYPE6 comma gen
   2.146+	{
   2.147+		outcode($1, &nullgen, NREG, &$3);
   2.148+	}
   2.149+|	LTYPE6
   2.150+	{
   2.151+		outcode($1, &nullgen, NREG, &nullgen);
   2.152+	}
   2.153+/*
   2.154+ * CMP
   2.155+ */
   2.156+|	LTYPE7 imsr ',' spreg comma
   2.157+	{
   2.158+		outcode($1, &$2, $4, &nullgen);
   2.159+	}
   2.160+/*
   2.161+ * CBZ
   2.162+ */
   2.163+|	LTYPE8 reg ',' rel
   2.164+	{
   2.165+		outcode($1, &$2, NREG, &$4);
   2.166+	}
   2.167+/*
   2.168+ * CSET
   2.169+ */
   2.170+|	LTYPER cond ',' reg
   2.171+	{
   2.172+		outcode($1, &$2, NREG, &$4);
   2.173+	}
   2.174+/*
   2.175+ * CSEL/CINC/CNEG/CINV
   2.176+ */
   2.177+|	LTYPES cond ',' reg ',' reg ',' reg
   2.178+	{
   2.179+		outcode4($1, &$2, $6.reg, &$4, &$8);
   2.180+	}
   2.181+|	LTYPES cond ',' reg ',' reg
   2.182+	{
   2.183+		outcode($1, &$2, $4.reg, &$6);
   2.184+	}
   2.185+/*
   2.186+ * TBZ
   2.187+ */
   2.188+|	LTYPET imm ',' reg ',' rel
   2.189+	{
   2.190+		outcode($1, &$2, $4.reg, &$6);
   2.191+	}
   2.192+/*
   2.193+ * CCMN
   2.194+ */
   2.195+|	LTYPEU cond ',' imsr ',' reg ',' imm comma
   2.196+	{
   2.197+		outcode4($1, &$2, $6.reg, &$4, &$8);
   2.198+	}
   2.199+/*
   2.200+ * ADR
   2.201+ */
   2.202+|	LTYPEV rel ',' reg
   2.203+	{
   2.204+		outcode($1, &$2, NREG, &$4);
   2.205+	}
   2.206+|	LTYPEV '$' name ',' reg
   2.207+	{
   2.208+		outcode($1, &$3, NREG, &$5);
   2.209+	}
   2.210+/*
   2.211+ * BFM/BFI
   2.212+ */
   2.213+|	LTYPEY imm ',' imm ',' spreg ',' reg
   2.214+	{
   2.215+		outcode4($1, &$2, $6, &$4, &$8);
   2.216+	}
   2.217+/*
   2.218+ * EXTR
   2.219+ */
   2.220+|	LTYPEP imm ',' reg ',' spreg ',' reg
   2.221+	{
   2.222+		outcode4($1, &$2, $6, &$4, &$8);
   2.223+	}
   2.224+/*
   2.225+ * RET/RETURN
   2.226+ */
   2.227+|	LTYPEA comma
   2.228+	{
   2.229+		outcode($1, &nullgen, NREG, &nullgen);
   2.230+	}
   2.231+|	LTYPEA reg
   2.232+	{
   2.233+		outcode($1, &nullgen, NREG, &$2);
   2.234+	}
   2.235+/*
   2.236+ * NOP
   2.237+ */
   2.238+|	LTYPEQ comma
   2.239+	{
   2.240+		outcode($1, &nullgen, NREG, &nullgen);
   2.241+	}
   2.242+|	LTYPEQ reg comma
   2.243+	{
   2.244+		outcode($1, &$2, NREG, &nullgen);
   2.245+	}
   2.246+|	LTYPEQ freg comma
   2.247+	{
   2.248+		outcode($1, &$2, NREG, &nullgen);
   2.249+	}
   2.250+|	LTYPEQ ',' reg
   2.251+	{
   2.252+		outcode($1, &nullgen, NREG, &$3);
   2.253+	}
   2.254+|	LTYPEQ ',' freg
   2.255+	{
   2.256+		outcode($1, &nullgen, NREG, &$3);
   2.257+	}
   2.258+/*
   2.259+ * TEXT/GLOBL
   2.260+ */
   2.261+|	LTYPEB name ',' imm
   2.262+	{
   2.263+		outcode($1, &$2, NREG, &$4);
   2.264+	}
   2.265+|	LTYPEB name ',' con ',' imm
   2.266+	{
   2.267+		outcode($1, &$2, $4, &$6);
   2.268+	}
   2.269+/*
   2.270+ * DATA
   2.271+ */
   2.272+|	LTYPEC name '/' con ',' ximm
   2.273+	{
   2.274+		outcode($1, &$2, $4, &$6);
   2.275+	}
   2.276+/*
   2.277+ * CASE
   2.278+ */
   2.279+|	LTYPED reg ',' reg
   2.280+	{
   2.281+		outcode($1, &$2, NREG, &$4);
   2.282+	}
   2.283+/*
   2.284+ * word
   2.285+ */
   2.286+|	LTYPEH comma ximm
   2.287+	{
   2.288+		outcode($1, &nullgen, NREG, &$3);
   2.289+	}
   2.290+/*
   2.291+ * floating-point
   2.292+ */
   2.293+|	LTYPEI freg ',' freg
   2.294+	{
   2.295+		outcode($1, &$2, NREG, &$4);
   2.296+	}
   2.297+/*
   2.298+ * FADDD
   2.299+ */
   2.300+|	LTYPEK frcon ',' freg
   2.301+	{
   2.302+		outcode($1, &$2, NREG, &$4);
   2.303+	}
   2.304+|	LTYPEK frcon ',' freg ',' freg
   2.305+	{
   2.306+		outcode($1, &$2, $4.reg, &$6);
   2.307+	}
   2.308+/*
   2.309+ * FCMP
   2.310+ */
   2.311+|	LTYPEL frcon ',' freg comma
   2.312+	{
   2.313+		outcode($1, &$2, $4.reg, &nullgen);
   2.314+	}
   2.315+/*
   2.316+ * FCCMP
   2.317+ */
   2.318+|	LTYPEF cond ',' freg ',' freg ',' imm comma
   2.319+	{
   2.320+		outcode4($1, &$2, $6.reg, &$4, &$8);
   2.321+	}
   2.322+/*
   2.323+ * FMULA
   2.324+ */
   2.325+|	LTYPE9 freg ',' freg ', ' freg ',' freg comma
   2.326+	{
   2.327+		outcode4($1, &$2, $4.reg, &$6, &$8);
   2.328+	}
   2.329+/*
   2.330+ * FCSEL
   2.331+ */
   2.332+|	LFCSEL cond ',' freg ',' freg ',' freg
   2.333+	{
   2.334+		outcode4($1, &$2, $6.reg, &$4, &$8);
   2.335+	}
   2.336+/*
   2.337+ * SIMD
   2.338+ */
   2.339+|	LTYPEW vgen ',' vgen
   2.340+	{
   2.341+		outcode($1, &$2, NREG, &$4);
   2.342+	}
   2.343+|	LTYPEW vgen ',' vgen ',' vgen
   2.344+	{
   2.345+		outcode($1, &$2, $4.reg, &$6);
   2.346+	}
   2.347+/*
   2.348+ * MOVP/MOVNP
   2.349+ */
   2.350+|	LTYPEJ gen ',' sreg ',' gen
   2.351+	{
   2.352+		outcode($1, &$2, $4, &$6);
   2.353+	}
   2.354+/*
   2.355+ * MADD Rn,Rm,Ra,Rd
   2.356+ */
   2.357+|	LTYPEM reg ',' reg ',' sreg ',' reg
   2.358+	{
   2.359+		outcode4($1, &$2, $6, &$4, &$8);
   2.360+	}
   2.361+/*
   2.362+ * SYS/SYSL
   2.363+ */
   2.364+|	LTYPEN sysarg
   2.365+	{
   2.366+		outcode($1, &$2, NREG, &nullgen);
   2.367+	}
   2.368+|	LTYPEN reg ',' sysarg
   2.369+	{
   2.370+		outcode($1, &$4, $2.reg, &nullgen);
   2.371+	}
   2.372+|	LTYPEO sysarg ',' reg
   2.373+	{
   2.374+		outcode($1, &$2, NREG, &$4);
   2.375+	}
   2.376+/*
   2.377+ * DMB, HINT
   2.378+ */
   2.379+|	LDMB imm
   2.380+	{
   2.381+		outcode($1, &$2, NREG, &nullgen);
   2.382+	}
   2.383+/*
   2.384+ * STXR
   2.385+ */
   2.386+|	LSTXR reg ',' gen ',' sreg
   2.387+	{
   2.388+		outcode($1, &$2, $6, &$4);
   2.389+	}
   2.390+/*
   2.391+ * END
   2.392+ */
   2.393+|	LTYPEE comma
   2.394+	{
   2.395+		outcode($1, &nullgen, NREG, &nullgen);
   2.396+	}
   2.397+
   2.398+cond:
   2.399+	LCOND
   2.400+	{
   2.401+		$$ = nullgen;
   2.402+		$$.type = D_COND;
   2.403+		$$.reg = $1;
   2.404+	}
   2.405+
   2.406+comma:
   2.407+|	',' comma
   2.408+
   2.409+sysarg:
   2.410+	con ',' con ',' con ',' con
   2.411+	{
   2.412+		$$ = nullgen;
   2.413+		$$.type = D_CONST;
   2.414+		$$.offset = SYSARG4($1, $3, $5, $7);
   2.415+	}
   2.416+|	imm
   2.417+
   2.418+rel:
   2.419+	con '(' LPC ')'
   2.420+	{
   2.421+		$$ = nullgen;
   2.422+		$$.type = D_BRANCH;
   2.423+		$$.offset = $1 + pc;
   2.424+	}
   2.425+|	LNAME offset
   2.426+	{
   2.427+		$$ = nullgen;
   2.428+		if(pass == 2)
   2.429+			yyerror("undefined label: %s", $1->name);
   2.430+		$$.type = D_BRANCH;
   2.431+		$$.sym = $1;
   2.432+		$$.offset = $2;
   2.433+	}
   2.434+|	LLAB offset
   2.435+	{
   2.436+		$$ = nullgen;
   2.437+		$$.type = D_BRANCH;
   2.438+		$$.sym = $1;
   2.439+		$$.offset = $1->value + $2;
   2.440+	}
   2.441+
   2.442+ximm:	'$' con
   2.443+	{
   2.444+		$$ = nullgen;
   2.445+		$$.type = D_CONST;
   2.446+		$$.offset = $2;
   2.447+	}
   2.448+|	'$' oreg
   2.449+	{
   2.450+		$$ = $2;
   2.451+		$$.type = D_CONST;
   2.452+	}
   2.453+|	'$' '*' '$' oreg
   2.454+	{
   2.455+		$$ = $4;
   2.456+		$$.type = D_OCONST;
   2.457+	}
   2.458+|	'$' LSCONST
   2.459+	{
   2.460+		$$ = nullgen;
   2.461+		$$.type = D_SCONST;
   2.462+		memmove($$.sval, $2, sizeof($$.sval));
   2.463+	}
   2.464+|	fcon
   2.465+
   2.466+fcon:
   2.467+	'$' LFCONST
   2.468+	{
   2.469+		$$ = nullgen;
   2.470+		$$.type = D_FCONST;
   2.471+		$$.dval = $2;
   2.472+	}
   2.473+|	'$' '-' LFCONST
   2.474+	{
   2.475+		$$ = nullgen;
   2.476+		$$.type = D_FCONST;
   2.477+		$$.dval = -$3;
   2.478+	}
   2.479+
   2.480+gen:
   2.481+	reg
   2.482+|	ximm
   2.483+|	LFCR
   2.484+	{
   2.485+		$$ = nullgen;
   2.486+		$$.type = D_SPR;
   2.487+		$$.offset = $1;
   2.488+	}
   2.489+|	con
   2.490+	{
   2.491+		$$ = nullgen;
   2.492+		$$.type = D_OREG;
   2.493+		$$.offset = $1;
   2.494+	}
   2.495+|	oreg
   2.496+|	freg
   2.497+|	vreg
   2.498+|	spr
   2.499+
   2.500+nireg:
   2.501+	'(' sreg ')'
   2.502+	{
   2.503+		$$ = nullgen;
   2.504+		$$.type = D_OREG;
   2.505+		$$.reg = $2;
   2.506+		$$.offset = 0;
   2.507+	}
   2.508+|	name
   2.509+	{
   2.510+		$$ = $1;
   2.511+		if($1.name != D_EXTERN && $1.name != D_STATIC) {
   2.512+		}
   2.513+	}
   2.514+
   2.515+oreg:
   2.516+	name
   2.517+|	name '(' sreg ')'
   2.518+	{
   2.519+		$$ = $1;
   2.520+		$$.type = D_OREG;
   2.521+		$$.reg = $3;
   2.522+	}
   2.523+|	ioreg
   2.524+
   2.525+ioreg:
   2.526+	'(' sreg ')'
   2.527+	{
   2.528+		$$ = nullgen;
   2.529+		$$.type = D_OREG;
   2.530+		$$.reg = $2;
   2.531+		$$.offset = 0;
   2.532+	}
   2.533+|	con '(' sreg ')'
   2.534+	{
   2.535+		$$ = nullgen;
   2.536+		$$.type = D_OREG;
   2.537+		$$.reg = $3;
   2.538+		$$.offset = $1;
   2.539+	}
   2.540+|	con '(' sreg ')' '!'
   2.541+	{
   2.542+		$$ = nullgen;
   2.543+		$$.type = D_XPRE;
   2.544+		$$.reg = $3;
   2.545+		$$.offset = $1;
   2.546+	}
   2.547+|	'(' sreg ')' con '!'
   2.548+	{
   2.549+		$$.type = D_XPOST;
   2.550+		$$.offset = $2;
   2.551+	}
   2.552+|	'(' sreg ')' '(' indexreg ')'
   2.553+	{
   2.554+		$$ = nullgen;
   2.555+		$$.type = D_ROFF;
   2.556+		$$.reg = $2;
   2.557+		$$.xreg = $5 & 0x1f;
   2.558+		$$.offset = $5;
   2.559+	}
   2.560+|	'(' sreg ')' '[' indexreg ']'
   2.561+	{
   2.562+		$$ = nullgen;
   2.563+		$$.type = D_ROFF;
   2.564+		$$.reg = $2;
   2.565+		$$.xreg = $5 & 0x1f;
   2.566+		$$.offset = $5 | (1<<16);
   2.567+	}
   2.568+
   2.569+imsr:
   2.570+	imm
   2.571+|	shift
   2.572+|	extreg
   2.573+
   2.574+imm:	'$' con
   2.575+	{
   2.576+		$$ = nullgen;
   2.577+		$$.type = D_CONST;
   2.578+		$$.offset = $2;
   2.579+	}
   2.580+
   2.581+reg:
   2.582+	sreg
   2.583+	{
   2.584+		$$ = nullgen;
   2.585+		$$.type = D_REG;
   2.586+		$$.reg = $1;
   2.587+	}
   2.588+|	LSP
   2.589+	{
   2.590+		$$ = nullgen;
   2.591+		$$.type = D_SP;
   2.592+		$$.reg = REGSP;
   2.593+	}
   2.594+
   2.595+shift:
   2.596+	sreg '<' '<' scon
   2.597+	{
   2.598+		$$ = nullgen;
   2.599+		$$.type = D_SHIFT;
   2.600+		$$.offset = ($1 << 16) | ($4 << 10) | (0 << 22);
   2.601+	}
   2.602+|	sreg '>' '>' scon
   2.603+	{
   2.604+		$$ = nullgen;
   2.605+		$$.type = D_SHIFT;
   2.606+		$$.offset = (($1&0x1F) << 16) | ($4 << 10) | (1 << 22);
   2.607+	}
   2.608+|	sreg '-' '>' scon
   2.609+	{
   2.610+		$$ = nullgen;
   2.611+		$$.type = D_SHIFT;
   2.612+		$$.offset = ($1 << 16) | ($4 << 10) | (2 << 22);
   2.613+	}
   2.614+|	sreg LAT '>' scon
   2.615+	{
   2.616+		$$ = nullgen;
   2.617+		$$.type = D_SHIFT;
   2.618+		$$.offset = ($1 << 16) | ($4 << 10) | (3 << 22);
   2.619+	}
   2.620+
   2.621+extreg:
   2.622+	sreg
   2.623+	{
   2.624+		$$ = nullgen;
   2.625+		$$.type = D_REG;
   2.626+		$$.reg = $1;
   2.627+	}
   2.628+|	sreg LEXT
   2.629+	{
   2.630+		$$ = nullgen;
   2.631+		$$.type = D_EXTREG;
   2.632+		$$.reg = $1;
   2.633+		$$.offset = ($1 << 16) | ($2 << 13);
   2.634+	}
   2.635+|	sreg LEXT '<' '<' con
   2.636+	{
   2.637+		if($5 < 0 || $5 > 4)
   2.638+			yyerror("shift value out of range");
   2.639+		$$ = nullgen;
   2.640+		$$.type = D_EXTREG;
   2.641+		$$.reg = $1;
   2.642+		$$.offset = ($1 << 16) | ($2 << 13) | ($5 << 10);
   2.643+	}
   2.644+
   2.645+indexreg:
   2.646+	sreg
   2.647+	{
   2.648+		$$ = (3 << 8) | $1;
   2.649+	}
   2.650+|	sreg LEXT
   2.651+	{
   2.652+		$$ = ($2 << 8) | $1;
   2.653+	}
   2.654+
   2.655+scon:
   2.656+	con
   2.657+	{
   2.658+		if($$ < 0 || $$ >= 64)
   2.659+			yyerror("shift value out of range");
   2.660+		$$ = $1&0x3F;
   2.661+	}
   2.662+
   2.663+sreg:
   2.664+	LREG
   2.665+|	LR '(' expr ')'
   2.666+	{
   2.667+		if($3 < 0 || $3 >= NREG)
   2.668+			print("register value out of range\n");
   2.669+		$$ = $3;
   2.670+	}
   2.671+
   2.672+spreg:
   2.673+	sreg
   2.674+|	LSP
   2.675+	{
   2.676+		$$ = REGSP;
   2.677+	}
   2.678+
   2.679+spr:
   2.680+	LSPREG
   2.681+	{
   2.682+		$$ = nullgen;
   2.683+		$$.type = D_SPR;
   2.684+		$$.offset = $1;
   2.685+	}
   2.686+|	LSPR '(' con ')'
   2.687+	{
   2.688+		$$ = nullgen;
   2.689+		$$.type = $1;
   2.690+		$$.offset = $3;
   2.691+	}
   2.692+
   2.693+frcon:
   2.694+	freg
   2.695+|	fcon
   2.696+
   2.697+freg:
   2.698+	LFREG
   2.699+	{
   2.700+		$$ = nullgen;
   2.701+		$$.type = D_FREG;
   2.702+		$$.reg = $1;
   2.703+	}
   2.704+|	LF '(' con ')'
   2.705+	{
   2.706+		$$ = nullgen;
   2.707+		$$.type = D_FREG;
   2.708+		$$.reg = $3;
   2.709+	}
   2.710+
   2.711+vgen:
   2.712+	oreg
   2.713+|	vreg
   2.714+|	vlane
   2.715+|	vset
   2.716+	{
   2.717+		$$ = nullgen;
   2.718+		$$.type = D_VSET;
   2.719+		$$.offset = $1;
   2.720+	}
   2.721+
   2.722+vlane:
   2.723+	vreg '[' con ']'
   2.724+	{
   2.725+		$$.type = D_VLANE;
   2.726+		$$.offset = $3;
   2.727+	}
   2.728+|	vset '[' con ']'
   2.729+	{
   2.730+		$$.type = D_VLANE;
   2.731+		$$.offset = $3;
   2.732+	}
   2.733+
   2.734+vset:
   2.735+	'{' vreglist '}'
   2.736+	{
   2.737+		$$ = $2;
   2.738+	}
   2.739+
   2.740+vreglist:
   2.741+	vreg
   2.742+	{
   2.743+		$$ = 1 << $1.reg;
   2.744+	}
   2.745+|	vreg '-' vreg
   2.746+	{
   2.747+		int i;
   2.748+		$$=0;
   2.749+		for(i=$1.reg; i<=$3.reg; i++)
   2.750+			$$ |= 1<<i;
   2.751+		for(i=$3.reg; i<=$1.reg; i++)
   2.752+			$$ |= 1<<i;
   2.753+	}
   2.754+|	vreg comma vreglist
   2.755+	{
   2.756+		$$ = (1<<$1.reg) | $3;
   2.757+	}
   2.758+
   2.759+vreg:
   2.760+	LVREG
   2.761+	{
   2.762+		$$ = nullgen;
   2.763+		$$.type = D_VREG;
   2.764+		$$.reg = $1;
   2.765+		/* TO DO: slice */
   2.766+	}
   2.767+|	LV '(' con ')'
   2.768+	{
   2.769+		$$ = nullgen;
   2.770+		$$.type = D_VREG;
   2.771+		$$.reg = $3;
   2.772+	}
   2.773+
   2.774+name:
   2.775+	con '(' pointer ')'
   2.776+	{
   2.777+		$$ = nullgen;
   2.778+		$$.type = D_OREG;
   2.779+		$$.name = $3;
   2.780+		$$.sym = S;
   2.781+		$$.offset = $1;
   2.782+	}
   2.783+|	LNAME offset '(' pointer ')'
   2.784+	{
   2.785+		$$ = nullgen;
   2.786+		$$.type = D_OREG;
   2.787+		$$.name = $4;
   2.788+		$$.sym = $1;
   2.789+		$$.offset = $2;
   2.790+	}
   2.791+|	LNAME '<' '>' offset '(' LSB ')'
   2.792+	{
   2.793+		$$ = nullgen;
   2.794+		$$.type = D_OREG;
   2.795+		$$.name = D_STATIC;
   2.796+		$$.sym = $1;
   2.797+		$$.offset = $4;
   2.798+	}
   2.799+
   2.800+offset:
   2.801+	{
   2.802+		$$ = 0;
   2.803+	}
   2.804+|	'+' con
   2.805+	{
   2.806+		$$ = $2;
   2.807+	}
   2.808+|	'-' con
   2.809+	{
   2.810+		$$ = -$2;
   2.811+	}
   2.812+
   2.813+pointer:
   2.814+	LSB
   2.815+|	LSP
   2.816+|	LFP
   2.817+
   2.818+con:
   2.819+	LCONST
   2.820+|	LVAR
   2.821+	{
   2.822+		$$ = $1->value;
   2.823+	}
   2.824+|	'-' con
   2.825+	{
   2.826+		$$ = -$2;
   2.827+	}
   2.828+|	'+' con
   2.829+	{
   2.830+		$$ = $2;
   2.831+	}
   2.832+|	'~' con
   2.833+	{
   2.834+		$$ = ~$2;
   2.835+	}
   2.836+|	'(' expr ')'
   2.837+	{
   2.838+		$$ = $2;
   2.839+	}
   2.840+
   2.841+expr:
   2.842+	con
   2.843+|	expr '+' expr
   2.844+	{
   2.845+		$$ = $1 + $3;
   2.846+	}
   2.847+|	expr '-' expr
   2.848+	{
   2.849+		$$ = $1 - $3;
   2.850+	}
   2.851+|	expr '*' expr
   2.852+	{
   2.853+		$$ = $1 * $3;
   2.854+	}
   2.855+|	expr '/' expr
   2.856+	{
   2.857+		$$ = $1 / $3;
   2.858+	}
   2.859+|	expr '%' expr
   2.860+	{
   2.861+		$$ = $1 % $3;
   2.862+	}
   2.863+|	expr '<' '<' expr
   2.864+	{
   2.865+		$$ = $1 << $4;
   2.866+	}
   2.867+|	expr '>' '>' expr
   2.868+	{
   2.869+		$$ = $1 >> $4;
   2.870+	}
   2.871+|	expr '&' expr
   2.872+	{
   2.873+		$$ = $1 & $3;
   2.874+	}
   2.875+|	expr '^' expr
   2.876+	{
   2.877+		$$ = $1 ^ $3;
   2.878+	}
   2.879+|	expr '|' expr
   2.880+	{
   2.881+		$$ = $1 | $3;
   2.882+	}
     3.1new file mode 100644
     3.2--- /dev/null
     3.3+++ b/sys/src/cmd/7a/lex.c
     3.4@@ -0,0 +1,1041 @@
     3.5+#define	EXTERN
     3.6+#include "a.h"
     3.7+#include "y.tab.h"
     3.8+#include <ctype.h>
     3.9+
    3.10+void
    3.11+main(int argc, char *argv[])
    3.12+{
    3.13+	char *p;
    3.14+	int nout, nproc, status, i, c;
    3.15+
    3.16+	thechar = '7';
    3.17+	thestring = "arm64";
    3.18+	memset(debug, 0, sizeof(debug));
    3.19+	cinit();
    3.20+	outfile = 0;
    3.21+	include[ninclude++] = ".";
    3.22+	ARGBEGIN {
    3.23+	default:
    3.24+		c = ARGC();
    3.25+		if(c >= 0 || c < sizeof(debug))
    3.26+			debug[c] = 1;
    3.27+		break;
    3.28+
    3.29+	case 'o':
    3.30+		outfile = ARGF();
    3.31+		break;
    3.32+
    3.33+	case 'D':
    3.34+		p = ARGF();
    3.35+		if(p)
    3.36+			Dlist[nDlist++] = p;
    3.37+		break;
    3.38+
    3.39+	case 'I':
    3.40+		p = ARGF();
    3.41+		setinclude(p);
    3.42+		break;
    3.43+	} ARGEND
    3.44+	if(*argv == 0) {
    3.45+		print("usage: %ca [-options] file.s\n", thechar);
    3.46+		errorexit();
    3.47+	}
    3.48+	if(argc > 1 && systemtype(Windows)){
    3.49+		print("can't assemble multiple files on windows\n");
    3.50+		errorexit();
    3.51+	}
    3.52+	if(argc > 1 && !systemtype(Windows)) {
    3.53+		nproc = 1;
    3.54+		if(p = getenv("NPROC"))
    3.55+			nproc = atol(p);	/* */
    3.56+		c = 0;
    3.57+		nout = 0;
    3.58+		for(;;) {
    3.59+			while(nout < nproc && argc > 0) {
    3.60+				i = myfork();
    3.61+				if(i < 0) {
    3.62+					i = mywait(&status);
    3.63+					if(i < 0)
    3.64+						errorexit();
    3.65+					if(status)
    3.66+						c++;
    3.67+					nout--;
    3.68+					continue;
    3.69+				}
    3.70+				if(i == 0) {
    3.71+					print("%s:\n", *argv);
    3.72+					if(assemble(*argv))
    3.73+						errorexit();
    3.74+					exits(0);
    3.75+				}
    3.76+				nout++;
    3.77+				argc--;
    3.78+				argv++;
    3.79+			}
    3.80+			i = mywait(&status);
    3.81+			if(i < 0) {
    3.82+				if(c)
    3.83+					errorexit();
    3.84+				exits(0);
    3.85+			}
    3.86+			if(status)
    3.87+				c++;
    3.88+			nout--;
    3.89+		}
    3.90+	}
    3.91+	if(assemble(argv[0]))
    3.92+		errorexit();
    3.93+	exits(0);
    3.94+}
    3.95+
    3.96+int
    3.97+assemble(char *file)
    3.98+{
    3.99+	char ofile[100], incfile[20], *p;
   3.100+	int i, of;
   3.101+
   3.102+	strcpy(ofile, file);
   3.103+	p = utfrrune(ofile, pathchar());
   3.104+	if(p) {
   3.105+		include[0] = ofile;
   3.106+		*p++ = 0;
   3.107+	} else
   3.108+		p = ofile;
   3.109+	if(outfile == 0) {
   3.110+		outfile = p;
   3.111+		if(outfile){
   3.112+			p = utfrrune(outfile, '.');
   3.113+			if(p)
   3.114+				if(p[1] == 's' && p[2] == 0)
   3.115+					p[0] = 0;
   3.116+			p = utfrune(outfile, 0);
   3.117+			p[0] = '.';
   3.118+			p[1] = thechar;
   3.119+			p[2] = 0;
   3.120+		} else
   3.121+			outfile = "/dev/null";
   3.122+	}
   3.123+	p = getenv("INCLUDE");
   3.124+	if(p) {
   3.125+		setinclude(p);
   3.126+	} else {
   3.127+		if(systemtype(Plan9)) {
   3.128+			sprint(incfile,"/%s/include", thestring);
   3.129+			setinclude(strdup(incfile));
   3.130+		}
   3.131+	}
   3.132+
   3.133+	of = mycreat(outfile, 0664);
   3.134+	if(of < 0) {
   3.135+		yyerror("%ca: cannot create %s", thechar, outfile);
   3.136+		errorexit();
   3.137+	}
   3.138+	Binit(&obuf, of, OWRITE);
   3.139+
   3.140+	pass = 1;
   3.141+	pinit(file);
   3.142+	for(i=0; i<nDlist; i++)
   3.143+		dodefine(Dlist[i]);
   3.144+	yyparse();
   3.145+	if(nerrors) {
   3.146+		cclean();
   3.147+		return nerrors;
   3.148+	}
   3.149+
   3.150+	pass = 2;
   3.151+	outhist();
   3.152+	pinit(file);
   3.153+	for(i=0; i<nDlist; i++)
   3.154+		dodefine(Dlist[i]);
   3.155+	yyparse();
   3.156+	cclean();
   3.157+	return nerrors;
   3.158+}
   3.159+
   3.160+struct
   3.161+{
   3.162+	char	*name;
   3.163+	ushort	type;
   3.164+	ulong	value;
   3.165+} itab[] =
   3.166+{
   3.167+	"SP",		LSP,	D_AUTO,
   3.168+	"SB",		LSB,	D_EXTERN,
   3.169+	"FP",		LFP,	D_PARAM,
   3.170+	"PC",		LPC,	D_BRANCH,
   3.171+
   3.172+	"R",		LR,	0,
   3.173+	"R0",		LREG,	0,
   3.174+	"R1",		LREG,	1,
   3.175+	"R2",		LREG,	2,
   3.176+	"R3",		LREG,	3,
   3.177+	"R4",		LREG,	4,
   3.178+	"R5",		LREG,	5,
   3.179+	"R6",		LREG,	6,
   3.180+	"R7",		LREG,	7,
   3.181+	"R8",		LREG,	8,
   3.182+	"R9",		LREG,	9,
   3.183+	"R10",		LREG,	10,
   3.184+	"R11",		LREG,	11,
   3.185+	"R12",		LREG,	12,
   3.186+	"R13",		LREG,	13,
   3.187+	"R14",		LREG,	14,
   3.188+	"R15",		LREG,	15,
   3.189+	"R16",		LREG,	16,
   3.190+	"R17",		LREG,	17,
   3.191+	"R18",		LREG,	18,
   3.192+	"R19",		LREG,	19,
   3.193+	"R20",		LREG,	20,
   3.194+	"R21",		LREG,	21,
   3.195+	"R22",		LREG,	22,
   3.196+	"R23",		LREG,	23,
   3.197+	"R24",		LREG,	24,
   3.198+	"R25",		LREG,	25,
   3.199+	"R26",		LREG,	26,
   3.200+	"R27",		LREG,	27,
   3.201+	"R28",		LREG,	28,
   3.202+	"R29",		LREG,	29,
   3.203+	"R30",		LREG,	30,
   3.204+	"LR",			LREG,	30,
   3.205+	"ZR",			LREG,	31,
   3.206+
   3.207+	"RARG",		LREG,	REGARG,
   3.208+	"RARG0",	LREG,	REGARG,
   3.209+	"RSP",	LREG,	31,
   3.210+
   3.211+	"F",		LF,	0,
   3.212+
   3.213+	"F0",		LFREG,	0,
   3.214+	"F1",		LFREG,	1,
   3.215+	"F2",		LFREG,	2,
   3.216+	"F3",		LFREG,	3,
   3.217+	"F4",		LFREG,	4,
   3.218+	"F5",		LFREG,	5,
   3.219+	"F6",		LFREG,	6,
   3.220+	"F7",		LFREG,	7,
   3.221+	"F8",		LFREG,	8,
   3.222+	"F9",		LFREG,	9,
   3.223+	"F10",	LFREG,	10,
   3.224+	"F11",	LFREG,	11,
   3.225+	"F12",	LFREG,	12,
   3.226+	"F13",	LFREG,	13,
   3.227+	"F14",	LFREG,	14,
   3.228+	"F15",	LFREG,	15,
   3.229+	"F16",	LFREG,	16,
   3.230+	"F17",	LFREG,	17,
   3.231+	"F18",	LFREG,	18,
   3.232+	"F19",	LFREG,	19,
   3.233+	"F20",	LFREG,	20,
   3.234+	"F21",	LFREG,	21,
   3.235+	"F22",	LFREG,	22,
   3.236+	"F23",	LFREG,	23,
   3.237+	"F24",	LFREG,	24,
   3.238+	"F25",	LFREG,	25,
   3.239+	"F26",	LFREG,	26,
   3.240+	"F27",	LFREG,	27,
   3.241+	"F28",	LFREG,	28,
   3.242+	"F29",	LFREG,	29,
   3.243+	"F30",	LFREG,	30,
   3.244+	"F31",	LFREG,	31,
   3.245+
   3.246+	"V",		LV,	0,
   3.247+
   3.248+	"V0",		LVREG,	0,
   3.249+	"V1",		LVREG,	1,
   3.250+	"V2",		LVREG,	2,
   3.251+	"V3",		LVREG,	3,
   3.252+	"V4",		LVREG,	4,
   3.253+	"V5",		LVREG,	5,
   3.254+	"V6",		LVREG,	6,
   3.255+	"V7",		LVREG,	7,
   3.256+	"V8",		LVREG,	8,
   3.257+	"V9",		LVREG,	9,
   3.258+	"V10",	LVREG,	10,
   3.259+	"V11",	LVREG,	11,
   3.260+	"V12",	LVREG,	12,
   3.261+	"V13",	LVREG,	13,
   3.262+	"V14",	LVREG,	14,
   3.263+	"V15",	LVREG,	15,
   3.264+	"V16",	LVREG,	16,
   3.265+	"V17",	LVREG,	17,
   3.266+	"V18",	LVREG,	18,
   3.267+	"V19",	LVREG,	19,
   3.268+	"V20",	LVREG,	20,
   3.269+	"V21",	LVREG,	21,
   3.270+	"V22",	LVREG,	22,
   3.271+	"V23",	LVREG,	23,
   3.272+	"V24",	LVREG,	24,
   3.273+	"V25",	LVREG,	25,
   3.274+	"V26",	LVREG,	26,
   3.275+	"V27",	LVREG,	27,
   3.276+	"V28",	LVREG,	28,
   3.277+	"V29",	LVREG,	29,
   3.278+	"V30",	LVREG,	30,
   3.279+	"V31",	LVREG,	31,
   3.280+
   3.281+	"FPSR",		LFCR,	D_FPSR,
   3.282+	"FPCR",		LFCR,	D_FPCR,
   3.283+
   3.284+	"SPR",		LSPR,	D_SPR,
   3.285+	"NZCV",		LSPREG,	D_NZCV,
   3.286+	"ELR_EL1",	LSPREG,	D_ELR_EL1,
   3.287+	"ELR_EL2",	LSPREG,	D_ELR_EL2,
   3.288+//	"ELR_EL3",	LSPREG,	D_ELR_EL3,
   3.289+//	"LR_EL0",	LSPREG,	D_LR_EL0,
   3.290+	"DAIF",	LSPREG,	D_DAIF,
   3.291+	"CurrentEL",	LSPREG,	D_CurrentEL,
   3.292+	"SP_EL0",	LSPREG,	D_SP_EL0,
   3.293+//	"SP_EL1",	LSPREG,	D_SP_EL1,
   3.294+//	"SP_EL2",	LSPREG,	D_SP_EL2,
   3.295+	"SPSel",	LSPREG,	D_SPSel,
   3.296+//	"SPSR_abt",	LSPREG,	D_SPSR_abt,	
   3.297+	"SPSR_EL1",	LSPREG,	D_SPSR_EL1,
   3.298+	"SPSR_EL2",	LSPREG,	D_SPSR_EL2,
   3.299+//	"SPSR_EL3",	LSPREG,	D_SPSR_EL3,
   3.300+//	"SPSR_fiq",	LSPREG,	D_SPSR_fiq,
   3.301+//	"SPSR_ieq",	LSPREG,	D_SPSR_ieq,
   3.302+//	"SPSR_und",	LSPREG,	D_SPSR_und,
   3.303+	"DAIFSet",	LSPREG,	D_DAIFSet,
   3.304+	"DAIFClr",	LSPREG,	D_DAIFClr,
   3.305+
   3.306+	"EQ",		LCOND,	0,
   3.307+	"NE",		LCOND,	1,
   3.308+	"CS",		LCOND,	2,
   3.309+	"HS",		LCOND,	2,
   3.310+	"CC",	LCOND,	3,
   3.311+	"LO",		LCOND,	3,
   3.312+	"MI",		LCOND,	4,
   3.313+	"PL",		LCOND,	5,
   3.314+	"VS",		LCOND,	6,
   3.315+	"VC",	LCOND,	7,
   3.316+	"HI",		LCOND,	8,
   3.317+	"LS",		LCOND,	9,
   3.318+	"GE",		LCOND,	10,
   3.319+	"LT",		LCOND,	11,
   3.320+	"GT",		LCOND,	12,
   3.321+	"LE",		LCOND,	13,
   3.322+	"AL",		LCOND,	14,
   3.323+
   3.324+	".UXTB",	LEXT,	0,
   3.325+	".UXTH",	LEXT,	1,
   3.326+	".UXTW",	LEXT,	2,
   3.327+	".UXTX",	LEXT,	3,
   3.328+	".SXTB",	LEXT,	4,
   3.329+	".SXTH",	LEXT,	5,
   3.330+	".SXTW",	LEXT,	6,
   3.331+	".SXTX",	LEXT,	7,
   3.332+
   3.333+	".UB",	LEXT,	0,
   3.334+	".UH",	LEXT,	1,
   3.335+	".UW",	LEXT,	2,
   3.336+	".UX",	LEXT,	3,
   3.337+	".SB",	LEXT,	4,
   3.338+	".SH",	LEXT,	5,
   3.339+	".SW",	LEXT,	6,
   3.340+	".SX",	LEXT,	7,
   3.341+
   3.342+	"@",		LAT,	0,
   3.343+
   3.344+	"ADC",	LTYPE1,	AADC,
   3.345+	"ADCS",	LTYPE1,	AADCS,
   3.346+	"ADCSW",	LTYPE1,	AADCSW,
   3.347+	"ADCW",	LTYPE1,	AADCW,
   3.348+	"ADD",	LTYPE1,	AADD,
   3.349+	"ADDS",	LTYPE1,	AADDS,
   3.350+	"ADDSW",	LTYPE1,	AADDSW,
   3.351+	"ADDW",	LTYPE1,	AADDW,
   3.352+	"ADR",	LTYPEV,	AADR,
   3.353+	"ADRP",	LTYPEV,	AADRP,
   3.354+	"AND",	LTYPE1,	AAND,
   3.355+	"ANDS",	LTYPE1,	AANDS,
   3.356+	"ANDSW",	LTYPE1,	AANDSW,
   3.357+	"ANDW",	LTYPE1,	AANDW,
   3.358+	"ASR",	LTYPE1,	AASR,
   3.359+	"ASRW",	LTYPE1,	AASRW,
   3.360+	"AT",	LTYPEN,	AAT,
   3.361+	"BFI",	LTYPEY,	ABFI,
   3.362+	"BFIW",	LTYPEY,	ABFIW,
   3.363+	"BFM",	LTYPEY,	ABFM,
   3.364+	"BFMW",	LTYPEY,	ABFMW,
   3.365+	"BFXIL",	LTYPEY,	ABFXIL,
   3.366+	"BFXILW",	LTYPEY,	ABFXILW,
   3.367+	"BIC",	LTYPE1,	ABIC,
   3.368+	"BICS",	LTYPE1,	ABICS,
   3.369+	"BICSW",	LTYPE1,	ABICSW,
   3.370+	"BICW",	LTYPE1,	ABICW,
   3.371+	"BRK",	LTYPE6,	ABRK,
   3.372+	"CBNZ",	LTYPE8,	ACBNZ,
   3.373+	"CBNZW",	LTYPE8,	ACBNZW,
   3.374+	"CBZ",	LTYPE8,	ACBZ,
   3.375+	"CBZW",	LTYPE8,	ACBZW,
   3.376+	"CCMN",	LTYPEU,	ACCMN,
   3.377+	"CCMNW",	LTYPEU,	ACCMNW,
   3.378+	"CCMP",	LTYPEU,	ACCMP,
   3.379+	"CCMPW",	LTYPEU,	ACCMPW,
   3.380+	"CINC",	LTYPES,	ACINC,
   3.381+	"CINCW",	LTYPES,	ACINCW,
   3.382+	"CINV",	LTYPES,	ACINV,
   3.383+	"CINVW",	LTYPES,	ACINVW,
   3.384+	"CLREX",	LTYPE6,	ACLREX,
   3.385+	"CLS",	LTYPE2,	ACLS,
   3.386+	"CLSW",	LTYPE2,	ACLSW,
   3.387+	"CLZ",	LTYPE2,	ACLZ,
   3.388+	"CLZW",	LTYPE2,	ACLZW,
   3.389+	"CMN",	LTYPE7,	ACMN,
   3.390+	"CMNW",	LTYPE7,	ACMNW,
   3.391+	"CMP",	LTYPE7,	ACMP,
   3.392+	"CMPW",	LTYPE7,	ACMPW,
   3.393+	"CNEG",	LTYPES,	ACNEG,
   3.394+	"CNEGW",	LTYPES,	ACNEGW,
   3.395+	"CRC32B",	LTYPE1,	ACRC32B,
   3.396+	"CRC32CB",	LTYPE1,	ACRC32CB,
   3.397+	"CRC32CH",	LTYPE1,	ACRC32CH,
   3.398+	"CRC32CW",	LTYPE1,	ACRC32CW,
   3.399+	"CRC32CX",	LTYPE1,	ACRC32CX,
   3.400+	"CRC32H",	LTYPE1,	ACRC32H,
   3.401+	"CRC32W",	LTYPE1,	ACRC32W,
   3.402+	"CRC32X",	LTYPE1,	ACRC32X,
   3.403+	"CSEL",	LTYPES,	ACSEL,
   3.404+	"CSELW",	LTYPES,	ACSELW,
   3.405+	"CSET",	LTYPER,	ACSET,
   3.406+	"CSETM",	LTYPER,	ACSETM,
   3.407+	"CSETMW",	LTYPER,	ACSETMW,
   3.408+	"CSETW",	LTYPER,	ACSETW,
   3.409+	"CSINC",	LTYPES,	ACSINC,
   3.410+	"CSINCW",	LTYPES,	ACSINCW,
   3.411+	"CSINV",	LTYPES,	ACSINV,
   3.412+	"CSINVW",	LTYPES,	ACSINVW,
   3.413+	"CSNEG",	LTYPES,	ACSNEG,
   3.414+	"CSNEGW",	LTYPES,	ACSNEGW,
   3.415+	"DC",	LTYPEN,	ADC,
   3.416+	"DCPS1",	LTYPE6,	ADCPS1,
   3.417+	"DCPS2",	LTYPE6,	ADCPS2,
   3.418+	"DCPS3",	LTYPE6,	ADCPS3,
   3.419+	"DMB",	LDMB,	ADMB,
   3.420+	"DRPS",	LTYPE6,	ADRPS,
   3.421+	"DSB",	LDMB,	ADSB,
   3.422+	"EON",	LTYPE1,	AEON,
   3.423+	"EONW",	LTYPE1,	AEONW,
   3.424+	"EOR",	LTYPE1,	AEOR,
   3.425+	"EORW",	LTYPE1,	AEORW,
   3.426+	"ERET",	LTYPE0,	AERET,
   3.427+	"EXTR",	LTYPEP,	AEXTR,
   3.428+	"EXTRW",	LTYPEP,	AEXTRW,
   3.429+	"HINT",	LDMB,	AHINT,
   3.430+	"HLT",	LTYPE6,	AHLT,
   3.431+	"HVC",	LTYPE6,	AHVC,
   3.432+	"IC",	LTYPEN,	AIC,
   3.433+	"ISB",	LDMB,	AISB,
   3.434+	"LSL",	LTYPE1,	ALSL,
   3.435+	"LSLW",	LTYPE1,	ALSLW,
   3.436+	"LSR",	LTYPE1,	ALSR,
   3.437+	"LSRW",	LTYPE1,	ALSRW,
   3.438+	"MADD",	LTYPEM,	AMADD,
   3.439+	"MADDW",	LTYPEM,	AMADDW,
   3.440+	"MNEG",	LTYPE1,	AMNEG,
   3.441+	"MNEGW",	LTYPE1,	AMNEGW,
   3.442+	"MRS",	LTYPE3,	AMRS,
   3.443+	"MSR",	LTYPE3,	AMSR,
   3.444+	"MSUB",	LTYPEM,	AMSUB,
   3.445+	"MSUBW",	LTYPEM,	AMSUBW,
   3.446+	"MUL",	LTYPE1,	AMUL,
   3.447+	"MULW",	LTYPE1,	AMULW,
   3.448+	"MVN",	LTYPE1,	AMVN,
   3.449+	"MVNW",	LTYPE1,	AMVNW,
   3.450+	"NEG",	LTYPE1,	ANEG,
   3.451+	"NEGS",	LTYPE1,	ANEGS,
   3.452+	"NEGSW",	LTYPE1,	ANEGSW,
   3.453+	"NEGW",	LTYPE1,	ANEGW,
   3.454+	"NGC",	LTYPE2,	ANGC,
   3.455+	"NGCS",	LTYPE2,	ANGCS,
   3.456+	"NGCSW",	LTYPE2,	ANGCSW,
   3.457+	"NGCW",	LTYPE2,	ANGCW,
   3.458+	"ORN",	LTYPE1,	AORN,
   3.459+	"ORNW",	LTYPE1,	AORNW,
   3.460+	"ORR",	LTYPE1,	AORR,
   3.461+	"ORRW",	LTYPE1,	AORRW,
   3.462+	"PRFM",	LTYPE1,	APRFM,
   3.463+	"PRFUM",	LTYPE1,	APRFUM,
   3.464+	"RBIT",	LTYPE2,	ARBIT,
   3.465+	"RBITW",	LTYPE2,	ARBITW,
   3.466+	"REM",	LTYPE1, AREM,
   3.467+	"REMW",	LTYPE1,	AREMW,
   3.468+	"RET",	LTYPEA,	ARET,
   3.469+	"REV",	LTYPE2,	AREV,
   3.470+	"REV16",	LTYPE2,	AREV16,
   3.471+	"REV16W",	LTYPE2,	AREV16W,
   3.472+	"REV32",	LTYPE2,	AREV32,
   3.473+	"REVW",	LTYPE2,	AREVW,
   3.474+	"ROR",	LTYPE1,	AROR,
   3.475+	"RORW",	LTYPE1,	ARORW,
   3.476+	"SBC",	LTYPE1,	ASBC,
   3.477+	"SBCS",	LTYPE1,	ASBCS,
   3.478+	"SBCSW",	LTYPE1,	ASBCSW,
   3.479+	"SBCW",	LTYPE1,	ASBCW,
   3.480+	"SBFIZ",	LTYPEY,	ASBFIZ,
   3.481+	"SBFIZW",	LTYPEY,	ASBFIZW,
   3.482+	"SBFM",	LTYPEY,	ASBFM,
   3.483+	"SBFMW",	LTYPEY,	ASBFMW,
   3.484+	"SBFX",	LTYPEY,	ASBFX,
   3.485+	"SBFXW",	LTYPEY,	ASBFXW,
   3.486+	"SDIV",	LTYPE1,	ASDIV,
   3.487+	"SDIVW",	LTYPE1,	ASDIVW,
   3.488+	"SEV",	LTYPE0,	ASEV,
   3.489+	"SEVL",	LTYPE0,	ASEVL,
   3.490+	"SMADDL",	LTYPEM,	ASMADDL,
   3.491+	"SMC",	LTYPE6,	ASMC,
   3.492+	"SMNEGL",	LTYPE1,	ASMNEGL,
   3.493+	"SMSUBL",	LTYPEM,	ASMSUBL,
   3.494+	"SMULH",	LTYPE1,	ASMULH,
   3.495+	"SMULL",	LTYPE1,	ASMULL,
   3.496+	"STLR",	LSTXR,	ASTLR,
   3.497+	"STLRB",	LSTXR,	ASTLRB,
   3.498+	"STLRH",	LSTXR,	ASTLRH,
   3.499+	"STLRW",	LSTXR,	ASTLRW,
   3.500+	"STLXP",	LSTXR,	ASTLXP,
   3.501+	"STLXR",	LSTXR,	ASTLXR,
   3.502+	"STLXRB",	LSTXR,	ASTLXRB,
   3.503+	"STLXRH",	LSTXR,	ASTLXRH,
   3.504+	"STLXRW",	LSTXR,	ASTLXRW,
   3.505+	"STXR",	LSTXR,	ASTXR,
   3.506+	"STXRB",	LSTXR,	ASTXRB,
   3.507+	"STXRH",	LSTXR,	ASTXRH,
   3.508+	"STXP",	LSTXR,	ASTXP,
   3.509+	"STXPW",	LSTXR,	ASTXPW,
   3.510+	"STXRW",	LSTXR,	ASTXRW,
   3.511+	"SUB",	LTYPE1,	ASUB,
   3.512+	"SUBS",	LTYPE1,	ASUBS,
   3.513+	"SUBSW",	LTYPE1,	ASUBSW,
   3.514+	"SUBW",	LTYPE1,	ASUBW,
   3.515+	"SVC",	LTYPE6,	ASVC,
   3.516+	"SXTB",	LTYPE2,	ASXTB,
   3.517+	"SXTBW",	LTYPE2,	ASXTBW,
   3.518+	"SXTH",	LTYPE2,	ASXTH,
   3.519+	"SXTHW",	LTYPE2,	ASXTHW,
   3.520+	"SXTW",	LTYPE2,	ASXTW,
   3.521+	"SYS",	LTYPEN,	ASYS,
   3.522+	"SYSL",	LTYPEO,	ASYSL,
   3.523+	"TBNZ",	LTYPET,	ATBNZ,
   3.524+	"TBZ",	LTYPET,	ATBZ,
   3.525+	"TLBI",	LTYPEN,	ATLBI,
   3.526+	"TST",	LTYPE7,	ATST,
   3.527+	"TSTW",	LTYPE7,	ATSTW,
   3.528+	"UBFIZ",	LTYPEY,	AUBFIZ,
   3.529+	"UBFIZW",	LTYPEY,	AUBFIZW,
   3.530+	"UBFM",	LTYPEY,	AUBFM,
   3.531+	"UBFMW",	LTYPEY,	AUBFMW,
   3.532+	"UBFX",	LTYPEY,	AUBFX,
   3.533+	"UBFXW",	LTYPEY,	AUBFXW,
   3.534+	"UDIV",	LTYPE1,	AUDIV,
   3.535+	"UDIVW",	LTYPE1,	AUDIVW,
   3.536+	"UMADDL",	LTYPEM,	AUMADDL,
   3.537+	"UMNEGL",	LTYPE1,	AUMNEGL,
   3.538+	"UMSUBL",	LTYPEM,	AUMSUBL,
   3.539+	"UMULH",	LTYPE1,	AUMULH,
   3.540+	"UMULL",	LTYPE1,	AUMULL,
   3.541+	"UREM",		LTYPE1,	AUREM,
   3.542+	"UREMW",	LTYPE1,	AUREMW,
   3.543+	"UXTB",	LTYPE2,	AUXTB,
   3.544+	"UXTH",	LTYPE2,	AUXTH,
   3.545+	"UXTBW",	LTYPE2,	AUXTBW,
   3.546+	"UXTHW",	LTYPE2,	AUXTHW,
   3.547+	"UXTW",		LTYPE2,	AUXTW,
   3.548+	"WFE",	LTYPE0,	AWFE,
   3.549+	"WFI",	LTYPE0,	AWFI,
   3.550+	"YIELD",	LTYPE0,	AYIELD,
   3.551+
   3.552+	"LDXR",	LTYPE3,	ALDXR,
   3.553+	"LDXRB",	LTYPE3,	ALDXRB,
   3.554+	"LDXRH",	LTYPE3,	ALDXRH,
   3.555+	"LDXRW",	LTYPE3,	ALDXRW,
   3.556+
   3.557+	"LDAR",	LTYPE3,	ALDAR,
   3.558+	"LDARB",	LTYPE3,	ALDARB,
   3.559+	"LDARH",	LTYPE3,	ALDARH,
   3.560+	"LDARW",	LTYPE3,	ALDARW,
   3.561+
   3.562+	"LDXP",	LTYPE3,	ALDXP,
   3.563+	"LDXPW",	LTYPE3,	ALDXPW,
   3.564+	"LDAXP",	LTYPE3,	ALDAXP,
   3.565+	"LDAXPW",	LTYPE3,	ALDAXPW,
   3.566+
   3.567+	"LDAXR",	LTYPE3,	ALDAXR,
   3.568+	"LDAXRB",	LTYPE3,	ALDAXRB,
   3.569+	"LDAXRH",	LTYPE3,	ALDAXRH,
   3.570+	"LDAXRW",	LTYPE3,	ALDAXRW,
   3.571+
   3.572+	"MOVK",	LMOVK,	AMOVK,
   3.573+	"MOVKW",	LMOVK,	AMOVKW,
   3.574+	"MOVN",	LMOVK,	AMOVN,
   3.575+	"MOVNW",	LMOVK,	AMOVNW,
   3.576+	"MOVZ",	LMOVK,	AMOVZ,
   3.577+	"MOVZW",	LMOVK,	AMOVZW,
   3.578+
   3.579+	"MOVB",		LTYPE3, AMOVB,
   3.580+	"MOVBU",	LTYPE3, AMOVBU,
   3.581+	"MOVH",		LTYPE3, AMOVH,
   3.582+	"MOVHU",	LTYPE3, AMOVHU,
   3.583+	"MOVW",		LTYPE3, AMOVW,
   3.584+	"MOVWU",		LTYPE3, AMOVWU,
   3.585+	"MOV",		LTYPE3, AMOV,
   3.586+
   3.587+	"MOVP",	LTYPEJ,	AMOVP,
   3.588+	"MOVPD",	LTYPEJ,	AMOVPD,
   3.589+	"MOVPQ",	LTYPEJ,	AMOVPQ,
   3.590+	"MOVPS",	LTYPEJ,	AMOVPS,
   3.591+	"MOVPSW",	LTYPEJ,	AMOVPSW,
   3.592+	"MOVPW",	LTYPEJ,	AMOVPW,
   3.593+
   3.594+	"MOVNP",	LTYPEJ,	AMOVNP,
   3.595+	"MOVNPW",	LTYPEJ,	AMOVNPW,
   3.596+
   3.597+	"FMOVD",		LTYPE3, AFMOVD,
   3.598+	"FMOVS",		LTYPE3, AFMOVS,
   3.599+
   3.600+	"SCVTFD",	LTYPE3,	ASCVTFD,
   3.601+	"SCVTFS",	LTYPE3,	ASCVTFS,
   3.602+	"SCVTFWD",	LTYPE3,	ASCVTFWD,
   3.603+	"SCVTFWS",	LTYPE3,	ASCVTFWS,
   3.604+	"UCVTFD",	LTYPE3,	AUCVTFD,
   3.605+	"UCVTFS",	LTYPE3,	AUCVTFS,
   3.606+	"UCVTFWD",	LTYPE3,	AUCVTFWD,
   3.607+	"UCVTFWS",	LTYPE3,	AUCVTFWS,
   3.608+
   3.609+	"FCVTSD",	LTYPE3,	AFCVTSD,
   3.610+	"FCVTDS",	LTYPE3,	AFCVTDS,
   3.611+	"FCVTZSD",	LTYPE3,	AFCVTZSD,
   3.612+	"FCVTZSDW",	LTYPE3,	AFCVTZSDW,
   3.613+	"FCVTZSS",	LTYPE3,	AFCVTZSS,
   3.614+	"FCVTZSSW",	LTYPE3,	AFCVTZSSW,
   3.615+	"FCVTZUD",	LTYPE3,	AFCVTZUD,
   3.616+	"FCVTZUDW",	LTYPE3,	AFCVTZUDW,
   3.617+	"FCVTZUS",	LTYPE3,	AFCVTZUS,
   3.618+	"FCVTZUSW",	LTYPE3,	AFCVTZUSW,
   3.619+
   3.620+	"FCMPS",		LTYPEL, AFCMPS,
   3.621+	"FCMPD",		LTYPEL, AFCMPD,
   3.622+	"FCMPES",		LTYPEL, AFCMPES,
   3.623+	"FCMPED",	LTYPEL, AFCMPED,
   3.624+	"FCCMPS",	LTYPEF, AFCCMPS,
   3.625+	"FCCMPD",	LTYPEF, AFCCMPD,
   3.626+	"FCCMPES",	LTYPEF, AFCCMPES,
   3.627+	"FCCMPED",	LTYPEF, AFCCMPED,
   3.628+	"FADDS",		LTYPEK,	AFADDS,
   3.629+	"FADDD",		LTYPEK,	AFADDD,
   3.630+	"FSUBS",		LTYPEK,	AFSUBS,
   3.631+	"FSUBD",		LTYPEK,	AFSUBD,
   3.632+	"FMULS",		LTYPEK,	AFMULS,
   3.633+	"FMULD",		LTYPEK,	AFMULD,
   3.634+	"FDIVS",		LTYPEK,	AFDIVS,
   3.635+	"FDIVD",		LTYPEK,	AFDIVD,
   3.636+
   3.637+	"FCSELS",	LFCSEL,	AFCSELS,
   3.638+	"FCSELD",	LFCSEL,	AFCSELD,
   3.639+	"FMAXS",	LTYPEK,	AFMAXS,
   3.640+	"FMINS",	LTYPEK,	AFMINS,
   3.641+	"FMAXD",	LTYPEK,	AFMAXD,
   3.642+	"FMIND",	LTYPEK,	AFMIND,
   3.643+	"FMAXNMS",	LTYPEK,	AFMAXNMS,
   3.644+	"FMAXNMD",	LTYPEK,	AFMAXNMD,
   3.645+	"FMINNMS",	LTYPEK,	AFMINNMS,
   3.646+	"FMINNMD",	LTYPEK,	AFMINNMD,
   3.647+	"FNMULS",	LTYPEK,	AFNMULS,
   3.648+	"FNMULD",	LTYPEK,	AFNMULD,
   3.649+	"FRINTNS",	LTYPE3,	AFRINTNS,
   3.650+	"FRINTND",	LTYPE3,	AFRINTND,
   3.651+	"FRINTPS",	LTYPE3,	AFRINTPS,
   3.652+	"FRINTPD",	LTYPE3,	AFRINTPD,
   3.653+	"FRINTMS",	LTYPE3,	AFRINTMS,
   3.654+	"FRINTMD",	LTYPE3,	AFRINTMD,
   3.655+	"FRINTZS",	LTYPE3,	AFRINTZS,
   3.656+	"FRINTZD",	LTYPE3,	AFRINTZD,
   3.657+	"FRINTAS",	LTYPE3,	AFRINTAS,
   3.658+	"FRINTAD",	LTYPE3,	AFRINTAD,
   3.659+	"FRINTXS",	LTYPE3,	AFRINTXS,
   3.660+	"FRINTXD",	LTYPE3,	AFRINTXD,
   3.661+	"FRINTIS",	LTYPE3,	AFRINTIS,
   3.662+	"FRINTID",	LTYPE3,	AFRINTID,
   3.663+	"FMADDS",	LTYPEM,	AFMADDS,
   3.664+	"FMADDD",	LTYPEM,	AFMADDD,
   3.665+	"FMSUBS",	LTYPEM,	AFMSUBS,
   3.666+	"FMSUBD",	LTYPEM,	AFMSUBD,
   3.667+	"FNMADDS",	LTYPEM,	AFNMADDS,
   3.668+	"FNMADDD",	LTYPEM,	AFNMADDD,
   3.669+	"FNMSUBS",	LTYPEM,	AFNMSUBS,
   3.670+	"FNMSUBD",	LTYPEM,	AFNMSUBD,
   3.671+
   3.672+	"FABSS",	LTYPE3, 	AFABSS,
   3.673+	"FABSD",	LTYPE3,	AFABSD,
   3.674+	"FNEGS",	LTYPE3,	AFNEGS,
   3.675+	"FNEGD",	LTYPE3,	AFNEGD,
   3.676+	"FSQRTS",	LTYPE3,	AFSQRTS,
   3.677+	"FSQRTD",	LTYPE3,	AFSQRTD,
   3.678+	"FCVTDH",	LTYPE3,	AFCVTDH,
   3.679+	"FCVTHS",	LTYPE3,	AFCVTHS,
   3.680+	"FCVTHD",	LTYPE3,	AFCVTHD,
   3.681+	"FCVTSH",	LTYPE3,	AFCVTSH,
   3.682+
   3.683+	"AESD",	LTYPEW,	AAESD,
   3.684+	"AESE",	LTYPEW,	AAESE,
   3.685+	"AESIMC",	LTYPEW,	AAESIMC,
   3.686+	"AESMC",	LTYPEW,	AAESMC,
   3.687+	"SHA1C",	LTYPEW,	ASHA1C,
   3.688+	"SHA1H",	LTYPEW,	ASHA1H,
   3.689+	"SHA1M",	LTYPEW,	ASHA1M,
   3.690+	"SHA1P",	LTYPEW,	ASHA1P,
   3.691+	"SHA1SU0",	LTYPEW,	ASHA1SU0,
   3.692+	"SHA1SU1",	LTYPEW,	ASHA1SU1,
   3.693+	"SHA256H",	LTYPEW,	ASHA256H,
   3.694+	"SHA256H2",	LTYPEW,	ASHA256H2,
   3.695+	"SHA256SU0",	LTYPEW,	ASHA256SU0,
   3.696+	"SHA256SU1",	LTYPEW,	ASHA256SU1,
   3.697+
   3.698+	"B",		LTYPE4, AB,
   3.699+	"BL",		LTYPE4, ABL,
   3.700+
   3.701+	"BEQ",		LTYPE5,	ABEQ,
   3.702+	"BNE",		LTYPE5,	ABNE,
   3.703+	"BCS",		LTYPE5,	ABCS,
   3.704+	"BHS",		LTYPE5,	ABHS,
   3.705+	"BCC",		LTYPE5,	ABCC,
   3.706+	"BLO",		LTYPE5,	ABLO,
   3.707+	"BMI",		LTYPE5,	ABMI,
   3.708+	"BPL",		LTYPE5,	ABPL,
   3.709+	"BVS",		LTYPE5,	ABVS,
   3.710+	"BVC",		LTYPE5,	ABVC,
   3.711+	"BHI",		LTYPE5,	ABHI,
   3.712+	"BLS",		LTYPE5,	ABLS,
   3.713+	"BGE",		LTYPE5,	ABGE,
   3.714+	"BLT",		LTYPE5,	ABLT,
   3.715+	"BGT",		LTYPE5,	ABGT,
   3.716+	"BLE",		LTYPE5,	ABLE,
   3.717+	"BCASE",	LTYPE5,	ABCASE,
   3.718+
   3.719+	"TEXT",		LTYPEB, ATEXT,
   3.720+	"GLOBL",	LTYPEB, AGLOBL,
   3.721+	"DATA",		LTYPEC, ADATA,
   3.722+	"CASE",		LTYPED, ACASE,
   3.723+	"END",		LTYPEE, AEND,
   3.724+	"WORD",		LTYPEH, AWORD,
   3.725+	"DWORD",		LTYPEH, ADWORD,
   3.726+	"NOP",		LTYPEQ, ANOP,
   3.727+	"RETURN",	LTYPEA,	ARETURN,
   3.728+	0
   3.729+};
   3.730+
   3.731+void
   3.732+cinit(void)
   3.733+{
   3.734+	Sym *s;
   3.735+	int i;
   3.736+
   3.737+	nullgen.sym = S;
   3.738+	nullgen.offset = 0;
   3.739+	nullgen.type = D_NONE;
   3.740+	nullgen.name = D_NONE;
   3.741+	nullgen.reg = NREG;
   3.742+	nullgen.xreg = NREG;
   3.743+	if(FPCHIP)
   3.744+		nullgen.dval = 0;
   3.745+	for(i=0; i<sizeof(nullgen.sval); i++)
   3.746+		nullgen.sval[i] = 0;
   3.747+
   3.748+	nerrors = 0;
   3.749+	iostack = I;
   3.750+	iofree = I;
   3.751+	peekc = IGN;
   3.752+	nhunk = 0;
   3.753+	for(i=0; i<NHASH; i++)
   3.754+		hash[i] = S;
   3.755+	for(i=0; itab[i].name; i++) {
   3.756+		s = slookup(itab[i].name);
   3.757+		if(s->value != 0)
   3.758+			yyerror("internal: duplicate %s", s->name);
   3.759+		s->type = itab[i].type;
   3.760+		s->value = itab[i].value;
   3.761+	}
   3.762+
   3.763+	pathname = allocn(pathname, 0, 100);
   3.764+	if(getwd(pathname, 99) == 0) {
   3.765+		pathname = allocn(pathname, 100, 900);
   3.766+		if(getwd(pathname, 999) == 0)
   3.767+			strcpy(pathname, "/???");
   3.768+	}
   3.769+}
   3.770+
   3.771+void
   3.772+syminit(Sym *s)
   3.773+{
   3.774+
   3.775+	s->type = LNAME;
   3.776+	s->value = 0;
   3.777+}
   3.778+
   3.779+void
   3.780+cclean(void)
   3.781+{
   3.782+
   3.783+	outcode(AEND, &nullgen, NREG, &nullgen);
   3.784+	Bflush(&obuf);
   3.785+}
   3.786+
   3.787+void
   3.788+zname(char *n, int t, int s)
   3.789+{
   3.790+
   3.791+	Bputc(&obuf, ANAME);
   3.792+	Bputc(&obuf, ANAME>>8);
   3.793+	Bputc(&obuf, t);	/* type */
   3.794+	Bputc(&obuf, s);	/* sym */
   3.795+	while(*n) {
   3.796+		Bputc(&obuf, *n);
   3.797+		n++;
   3.798+	}
   3.799+	Bputc(&obuf, 0);
   3.800+}
   3.801+
   3.802+void
   3.803+zaddr(Gen *a, int s)
   3.804+{
   3.805+	long l;
   3.806+	int i;
   3.807+	char *n;
   3.808+	Ieee e;
   3.809+
   3.810+	if(a->type == D_CONST){
   3.811+		l = a->offset;
   3.812+		if((vlong)l != a->offset)
   3.813+			a->type = D_DCONST;
   3.814+	}
   3.815+	Bputc(&obuf, a->type);
   3.816+	Bputc(&obuf, a->reg);
   3.817+	Bputc(&obuf, s);
   3.818+	Bputc(&obuf, a->name);
   3.819+	switch(a->type) {
   3.820+	default:
   3.821+		print("unknown type %d\n", a->type);
   3.822+		exits("arg");
   3.823+
   3.824+	case D_NONE:
   3.825+	case D_REG:
   3.826+	case D_SP:
   3.827+	case D_FREG:
   3.828+	case D_VREG:
   3.829+	case D_COND:
   3.830+		break;
   3.831+
   3.832+	case D_DCONST:
   3.833+		l = a->offset;
   3.834+		Bputc(&obuf, l);
   3.835+		Bputc(&obuf, l>>8);
   3.836+		Bputc(&obuf, l>>16);
   3.837+		Bputc(&obuf, l>>24);
   3.838+		l = a->offset>>32;
   3.839+		Bputc(&obuf, l);
   3.840+		Bputc(&obuf, l>>8);
   3.841+		Bputc(&obuf, l>>16);
   3.842+		Bputc(&obuf, l>>24);
   3.843+		break;
   3.844+
   3.845+	case D_OREG:
   3.846+	case D_XPRE:
   3.847+	case D_XPOST:
   3.848+	case D_CONST:
   3.849+	case D_BRANCH:
   3.850+	case D_SHIFT:
   3.851+	case D_EXTREG:
   3.852+	case D_ROFF:
   3.853+	case D_SPR:
   3.854+		l = a->offset;
   3.855+		Bputc(&obuf, l);
   3.856+		Bputc(&obuf, l>>8);
   3.857+		Bputc(&obuf, l>>16);
   3.858+		Bputc(&obuf, l>>24);
   3.859+		break;
   3.860+
   3.861+	case D_SCONST:
   3.862+		n = a->sval;
   3.863+		for(i=0; i<NSNAME; i++) {
   3.864+			Bputc(&obuf, *n);
   3.865+			n++;
   3.866+		}
   3.867+		break;
   3.868+
   3.869+	case D_FCONST:
   3.870+		ieeedtod(&e, a->dval);
   3.871+		Bputc(&obuf, e.l);
   3.872+		Bputc(&obuf, e.l>>8);
   3.873+		Bputc(&obuf, e.l>>16);
   3.874+		Bputc(&obuf, e.l>>24);
   3.875+		Bputc(&obuf, e.h);
   3.876+		Bputc(&obuf, e.h>>8);
   3.877+		Bputc(&obuf, e.h>>16);
   3.878+		Bputc(&obuf, e.h>>24);
   3.879+		break;
   3.880+	}
   3.881+}
   3.882+
   3.883+static int
   3.884+outsim(Gen *g)
   3.885+{
   3.886+	Sym *s;
   3.887+	int sno, t;
   3.888+
   3.889+	s = g->sym;
   3.890+	if(s == S)
   3.891+		return 0;
   3.892+	sno = s->sym;
   3.893+	if(sno < 0 || sno >= NSYM)
   3.894+		sno = 0;
   3.895+	t = g->name;
   3.896+	if(h[sno].type == t && h[sno].sym == s)
   3.897+		return sno;
   3.898+	zname(s->name, t, sym);
   3.899+	s->sym = sym;
   3.900+	h[sym].sym = s;
   3.901+	h[sym].type = t;
   3.902+	sno = sym;
   3.903+	sym++;
   3.904+	if(sym >= NSYM)
   3.905+		sym = 1;
   3.906+	return sno;
   3.907+}
   3.908+
   3.909+void
   3.910+outcode(int a, Gen *g1, int reg, Gen *g2)
   3.911+{
   3.912+	int sf, st;
   3.913+
   3.914+	if(a != AGLOBL && a != ADATA)
   3.915+		pc++;
   3.916+	if(pass == 1)
   3.917+		return;
   3.918+	if(g1->xreg != NREG) {
   3.919+		if(reg != NREG || g2->xreg != NREG)
   3.920+			yyerror("bad addressing modes");
   3.921+		reg = g1->xreg;
   3.922+	} else if(g2->xreg != NREG) {
   3.923+		if(reg != NREG)
   3.924+			yyerror("bad addressing modes");
   3.925+		reg = g2->xreg;
   3.926+	}
   3.927+	do{
   3.928+		sf = outsim(g1);
   3.929+		st = outsim(g2);
   3.930+	} while(sf != 0 && st == sf);
   3.931+	Bputc(&obuf, a);
   3.932+	Bputc(&obuf, a>>8);
   3.933+	Bputc(&obuf, reg);
   3.934+	Bputc(&obuf, lineno);
   3.935+	Bputc(&obuf, lineno>>8);
   3.936+	Bputc(&obuf, lineno>>16);
   3.937+	Bputc(&obuf, lineno>>24);
   3.938+	zaddr(g1, sf);
   3.939+	zaddr(g2, st);
   3.940+}
   3.941+
   3.942+void
   3.943+outcode4(int a, Gen *g1, int reg, Gen *g2, Gen *g3)
   3.944+{
   3.945+	int s1, s2, s3, flag;
   3.946+
   3.947+	if(a != AGLOBL && a != ADATA)
   3.948+		pc++;
   3.949+	if(pass == 1)
   3.950+		return;
   3.951+	do{
   3.952+		s1 = outsim(g1);
   3.953+		s2 = outsim(g2);
   3.954+		s3 = outsim(g3);
   3.955+	} while(s1 && (s2 && s1 == s2 || s3 && s1 == s3) || s2 && (s3 && s2 == s3));
   3.956+	flag = 0;
   3.957+	if(g2->type != D_NONE)
   3.958+		flag = 0x40;	/* flags extra operand */
   3.959+	Bputc(&obuf, a);
   3.960+	Bputc(&obuf, a>>8);
   3.961+	Bputc(&obuf, reg | flag);
   3.962+	Bputc(&obuf, lineno);
   3.963+	Bputc(&obuf, lineno>>8);
   3.964+	Bputc(&obuf, lineno>>16);
   3.965+	Bputc(&obuf, lineno>>24);
   3.966+	zaddr(g1, s1);
   3.967+	if(flag)
   3.968+		zaddr(g2, s2);
   3.969+	zaddr(g3, s3);
   3.970+}
   3.971+
   3.972+void
   3.973+outhist(void)
   3.974+{
   3.975+	Gen g;
   3.976+	Hist *h;
   3.977+	char *p, *q, *op, c;
   3.978+	int n;
   3.979+
   3.980+	g = nullgen;
   3.981+	c = pathchar();
   3.982+	for(h = hist; h != H; h = h->link) {
   3.983+		p = h->name;
   3.984+		op = 0;
   3.985+		/* on windows skip drive specifier in pathname */
   3.986+		if(systemtype(Windows) && p && p[1] == ':'){
   3.987+			p += 2;
   3.988+			c = *p;
   3.989+		}
   3.990+		if(p && p[0] != c && h->offset == 0 && pathname){
   3.991+			/* on windows skip drive specifier in pathname */
   3.992+			if(systemtype(Windows) && pathname[1] == ':') {
   3.993+				op = p;
   3.994+				p = pathname+2;
   3.995+				c = *p;
   3.996+			} else if(pathname[0] == c){
   3.997+				op = p;
   3.998+				p = pathname;
   3.999+			}
  3.1000+		}
  3.1001+		while(p) {
  3.1002+			q = strchr(p, c);
  3.1003+			if(q) {
  3.1004+				n = q-p;
  3.1005+				if(n == 0){
  3.1006+					n = 1;	/* leading "/" */
  3.1007+					*p = '/';	/* don't emit "\" on windows */
  3.1008+				}
  3.1009+				q++;
  3.1010+			} else {
  3.1011+				n = strlen(p);
  3.1012+				q = 0;
  3.1013+			}
  3.1014+			if(n) {
  3.1015+				Bputc(&obuf, ANAME);
  3.1016+				Bputc(&obuf, ANAME>>8);
  3.1017+				Bputc(&obuf, D_FILE);	/* type */
  3.1018+				Bputc(&obuf, 1);	/* sym */
  3.1019+				Bputc(&obuf, '<');
  3.1020+				Bwrite(&obuf, p, n);
  3.1021+				Bputc(&obuf, 0);
  3.1022+			}
  3.1023+			p = q;
  3.1024+			if(p == 0 && op) {
  3.1025+				p = op;
  3.1026+				op = 0;
  3.1027+			}
  3.1028+		}
  3.1029+		g.offset = h->offset;
  3.1030+
  3.1031+		Bputc(&obuf, AHISTORY);
  3.1032+		Bputc(&obuf, AHISTORY>>8);
  3.1033+		Bputc(&obuf, 0);
  3.1034+		Bputc(&obuf, h->line);
  3.1035+		Bputc(&obuf, h->line>>8);
  3.1036+		Bputc(&obuf, h->line>>16);
  3.1037+		Bputc(&obuf, h->line>>24);
  3.1038+		zaddr(&nullgen, 0);
  3.1039+		zaddr(&g, 0);
  3.1040+	}
  3.1041+}
  3.1042+
  3.1043+#include "../cc/lexbody"
  3.1044+#include "../cc/macbody"
  3.1045+#include "../cc/compat"
     4.1new file mode 100644
     4.2--- /dev/null
     4.3+++ b/sys/src/cmd/7a/mkfile
     4.4@@ -0,0 +1,19 @@
     4.5+</$objtype/mkfile
     4.6+
     4.7+TARG=7a
     4.8+OFILES=\
     4.9+	y.tab.$O\
    4.10+	lex.$O\
    4.11+
    4.12+HFILES=\
    4.13+	../7c/7.out.h\
    4.14+	y.tab.h\
    4.15+	a.h\
    4.16+
    4.17+YFILES=a.y\
    4.18+
    4.19+BIN=/$objtype/bin
    4.20+< /sys/src/cmd/mkone
    4.21+YFLAGS=-D1 -d
    4.22+
    4.23+lex.$O:	../cc/macbody ../cc/lexbody
     5.1new file mode 100644
     5.2--- /dev/null
     5.3+++ b/sys/src/cmd/7c/7.out.h
     5.4@@ -0,0 +1,517 @@
     5.5+/*
     5.6+ * arm64
     5.7+ */
     5.8+
     5.9+#define	NSNAME		8
    5.10+#define	NSYM		50
    5.11+#define	NREG		32
    5.12+
    5.13+#define NOPROF		(1<<0)
    5.14+#define DUPOK		(1<<1)
    5.15+
    5.16+#define	REGRET		0
    5.17+#define	REGARG		0
    5.18+/* R1 to R7 are potential parameter/return registers */
    5.19+#define	REGIRL		8	/* indirect result location (TO DO) */
    5.20+/* compiler allocates R9 up as temps */
    5.21+/* compiler allocates register variables R10 up */
    5.22+#define	REGMIN		9
    5.23+#define	REGMAX		15
    5.24+#define	REGIP0		16
    5.25+#define	REGIP1		17
    5.26+#define	REGTMP		REGIP1
    5.27+/* compiler allocates external registers R27 down */
    5.28+#define	REGEXT		27
    5.29+#define	REGSB		28
    5.30+#define	REGFP		29
    5.31+#define	REGLINK		30
    5.32+#define	REGSP		31
    5.33+#define	REGZERO		31
    5.34+
    5.35+#define	NFREG		32
    5.36+#define	FREGRET		0
    5.37+#define	FREGMIN		7
    5.38+#define	FREGEXT		15
    5.39+
    5.40+/* compiler allocates register variables F0 up */
    5.41+/* compiler allocates external registers F15 down */
    5.42+
    5.43+enum	as
    5.44+{
    5.45+	AXXX,
    5.46+
    5.47+	AADC,
    5.48+	AADCS,
    5.49+	AADCSW,
    5.50+	AADCW,
    5.51+	AADD,
    5.52+	AADDS,
    5.53+	AADDSW,
    5.54+	AADDW,
    5.55+	AADR,
    5.56+	AADRP,
    5.57+	AAND,
    5.58+	AANDS,
    5.59+	AANDSW,
    5.60+	AANDW,
    5.61+	AASR,
    5.62+	AASRW,
    5.63+	AAT,
    5.64+	AB,
    5.65+	ABFI,
    5.66+	ABFIW,
    5.67+	ABFM,
    5.68+	ABFMW,
    5.69+	ABFXIL,
    5.70+	ABFXILW,
    5.71+	ABIC,
    5.72+	ABICS,
    5.73+	ABICSW,
    5.74+	ABICW,
    5.75+	ABL,
    5.76+	ABRK,
    5.77+	ACBNZ,
    5.78+	ACBNZW,
    5.79+	ACBZ,
    5.80+	ACBZW,
    5.81+	ACCMN,
    5.82+	ACCMNW,
    5.83+	ACCMP,
    5.84+	ACCMPW,
    5.85+	ACINC,
    5.86+	ACINCW,
    5.87+	ACINV,
    5.88+	ACINVW,
    5.89+	ACLREX,
    5.90+	ACLS,
    5.91+	ACLSW,
    5.92+	ACLZ,
    5.93+	ACLZW,
    5.94+	ACMN,
    5.95+	ACMNW,
    5.96+	ACMP,
    5.97+	ACMPW,
    5.98+	ACNEG,
    5.99+	ACNEGW,
   5.100+	ACRC32B,
   5.101+	ACRC32CB,
   5.102+	ACRC32CH,
   5.103+	ACRC32CW,
   5.104+	ACRC32CX,
   5.105+	ACRC32H,
   5.106+	ACRC32W,
   5.107+	ACRC32X,
   5.108+	ACSEL,
   5.109+	ACSELW,
   5.110+	ACSET,
   5.111+	ACSETM,
   5.112+	ACSETMW,
   5.113+	ACSETW,
   5.114+	ACSINC,
   5.115+	ACSINCW,
   5.116+	ACSINV,
   5.117+	ACSINVW,
   5.118+	ACSNEG,
   5.119+	ACSNEGW,
   5.120+	ADC,
   5.121+	ADCPS1,
   5.122+	ADCPS2,
   5.123+	ADCPS3,
   5.124+	ADMB,
   5.125+	ADRPS,
   5.126+	ADSB,
   5.127+	AEON,
   5.128+	AEONW,
   5.129+	AEOR,
   5.130+	AEORW,
   5.131+	AERET,
   5.132+	AEXTR,
   5.133+	AEXTRW,
   5.134+	AHINT,
   5.135+	AHLT,
   5.136+	AHVC,
   5.137+	AIC,
   5.138+	AISB,
   5.139+	ALDAR,
   5.140+	ALDARB,
   5.141+	ALDARH,
   5.142+	ALDARW,
   5.143+	ALDAXP,
   5.144+	ALDAXPW,
   5.145+	ALDAXR,
   5.146+	ALDAXRB,
   5.147+	ALDAXRH,
   5.148+	ALDAXRW,
   5.149+	ALDXR,
   5.150+	ALDXRB,
   5.151+	ALDXRH,
   5.152+	ALDXRW,
   5.153+	ALDXP,
   5.154+	ALDXPW,
   5.155+	ALSL,
   5.156+	ALSLW,
   5.157+	ALSR,
   5.158+	ALSRW,
   5.159+	AMADD,
   5.160+	AMADDW,
   5.161+	AMNEG,
   5.162+	AMNEGW,
   5.163+	AMOVK,
   5.164+	AMOVKW,
   5.165+	AMOVN,
   5.166+	AMOVNW,
   5.167+	AMOVZ,
   5.168+	AMOVZW,
   5.169+	AMRS,
   5.170+	AMSR,
   5.171+	AMSUB,
   5.172+	AMSUBW,
   5.173+	AMUL,
   5.174+	AMULW,
   5.175+	AMVN,
   5.176+	AMVNW,
   5.177+	ANEG,
   5.178+	ANEGS,
   5.179+	ANEGSW,
   5.180+	ANEGW,
   5.181+	ANGC,
   5.182+	ANGCS,
   5.183+	ANGCSW,
   5.184+	ANGCW,
   5.185+	ANOP,
   5.186+	AORN,
   5.187+	AORNW,
   5.188+	AORR,
   5.189+	AORRW,
   5.190+	APRFM,
   5.191+	APRFUM,
   5.192+	ARBIT,
   5.193+	ARBITW,
   5.194+	AREM,
   5.195+	AREMW,
   5.196+	ARET,
   5.197+	AREV,
   5.198+	AREV16,
   5.199+	AREV16W,
   5.200+	AREV32,
   5.201+	AREVW,
   5.202+	AROR,
   5.203+	ARORW,
   5.204+	ASBC,
   5.205+	ASBCS,
   5.206+	ASBCSW,
   5.207+	ASBCW,
   5.208+	ASBFIZ,
   5.209+	ASBFIZW,
   5.210+	ASBFM,
   5.211+	ASBFMW,
   5.212+	ASBFX,
   5.213+	ASBFXW,
   5.214+	ASDIV,
   5.215+	ASDIVW,
   5.216+	ASEV,
   5.217+	ASEVL,
   5.218+	ASMADDL,
   5.219+	ASMC,
   5.220+	ASMNEGL,
   5.221+	ASMSUBL,
   5.222+	ASMULH,
   5.223+	ASMULL,
   5.224+	ASTXR,
   5.225+	ASTXRB,
   5.226+	ASTXRH,
   5.227+	ASTXP,
   5.228+	ASTXPW,
   5.229+	ASTXRW,
   5.230+	ASTLP,
   5.231+	ASTLPW,
   5.232+	ASTLR,
   5.233+	ASTLRB,
   5.234+	ASTLRH,
   5.235+	ASTLRW,
   5.236+	ASTLXP,
   5.237+	ASTLXPW,
   5.238+	ASTLXR,
   5.239+	ASTLXRB,
   5.240+	ASTLXRH,
   5.241+	ASTLXRW,
   5.242+	ASUB,
   5.243+	ASUBS,
   5.244+	ASUBSW,
   5.245+	ASUBW,
   5.246+	ASVC,
   5.247+	ASXTB,
   5.248+	ASXTBW,
   5.249+	ASXTH,
   5.250+	ASXTHW,
   5.251+	ASXTW,
   5.252+	ASYS,
   5.253+	ASYSL,
   5.254+	ATBNZ,
   5.255+	ATBZ,
   5.256+	ATLBI,
   5.257+	ATST,
   5.258+	ATSTW,
   5.259+	AUBFIZ,
   5.260+	AUBFIZW,
   5.261+	AUBFM,
   5.262+	AUBFMW,
   5.263+	AUBFX,
   5.264+	AUBFXW,
   5.265+	AUDIV,
   5.266+	AUDIVW,
   5.267+	AUMADDL,
   5.268+	AUMNEGL,
   5.269+	AUMSUBL,
   5.270+	AUMULH,
   5.271+	AUMULL,
   5.272+	AUREM,
   5.273+	AUREMW,
   5.274+	AUXTB,
   5.275+	AUXTH,
   5.276+	AUXTW,
   5.277+	AUXTBW,
   5.278+	AUXTHW,
   5.279+	AWFE,
   5.280+	AWFI,
   5.281+	AYIELD,
   5.282+
   5.283+	AMOVB,
   5.284+	AMOVBU,
   5.285+	AMOVH,
   5.286+	AMOVHU,
   5.287+	AMOVW,
   5.288+	AMOVWU,
   5.289+	AMOV,
   5.290+	AMOVNP,
   5.291+	AMOVNPW,
   5.292+	AMOVP,
   5.293+	AMOVPD,
   5.294+	AMOVPQ,
   5.295+	AMOVPS,
   5.296+	AMOVPSW,
   5.297+	AMOVPW,
   5.298+
   5.299+/* 
   5.300+ * Do not reorder or fragment the conditional branch 
   5.301+ * opcodes, or the predication code will break 
   5.302+ */ 
   5.303+	ABEQ,
   5.304+	ABNE,
   5.305+	ABCS,
   5.306+	ABHS,
   5.307+	ABCC,
   5.308+	ABLO,
   5.309+	ABMI,
   5.310+	ABPL,
   5.311+	ABVS,
   5.312+	ABVC,
   5.313+	ABHI,
   5.314+	ABLS,
   5.315+	ABGE,
   5.316+	ABLT,
   5.317+	ABGT,
   5.318+	ABLE,
   5.319+
   5.320+	AFABSD,
   5.321+	AFABSS,
   5.322+	AFADDD,
   5.323+	AFADDS,
   5.324+	AFCCMPD,
   5.325+	AFCCMPED,
   5.326+	AFCCMPS,
   5.327+	AFCCMPES,
   5.328+	AFCMPD,
   5.329+	AFCMPED,
   5.330+	AFCMPES,
   5.331+	AFCMPS,
   5.332+	AFCVTSD,
   5.333+	AFCVTDS,
   5.334+	AFCVTZSD,
   5.335+	AFCVTZSDW,
   5.336+	AFCVTZSS,
   5.337+	AFCVTZSSW,
   5.338+	AFCVTZUD,
   5.339+	AFCVTZUDW,
   5.340+	AFCVTZUS,
   5.341+	AFCVTZUSW,
   5.342+	AFDIVD,
   5.343+	AFDIVS,
   5.344+	AFMOVD,
   5.345+	AFMOVS,
   5.346+	AFMULD,
   5.347+	AFMULS,
   5.348+	AFNEGD,
   5.349+	AFNEGS,
   5.350+	AFSQRTD,
   5.351+	AFSQRTS,
   5.352+	AFSUBD,
   5.353+	AFSUBS,
   5.354+	ASCVTFD,
   5.355+	ASCVTFS,
   5.356+	ASCVTFWD,
   5.357+	ASCVTFWS,
   5.358+	AUCVTFD,
   5.359+	AUCVTFS,
   5.360+	AUCVTFWD,
   5.361+	AUCVTFWS,
   5.362+
   5.363+	ATEXT,
   5.364+	ADATA,
   5.365+	AGLOBL,
   5.366+	AHISTORY,
   5.367+	ANAME,
   5.368+	AWORD,
   5.369+	ADYNT,
   5.370+	AINIT,
   5.371+	ABCASE,
   5.372+	ACASE,
   5.373+	ADWORD,
   5.374+	ASIGNAME,
   5.375+	AGOK,
   5.376+	ARETURN,
   5.377+	AEND,
   5.378+
   5.379+	AFCSELS,
   5.380+	AFCSELD,
   5.381+	AFMAXS,
   5.382+	AFMINS,
   5.383+	AFMAXD,
   5.384+	AFMIND,
   5.385+	AFMAXNMS,
   5.386+	AFMAXNMD,
   5.387+	AFNMULS,
   5.388+	AFNMULD,
   5.389+	AFRINTNS,
   5.390+	AFRINTND,
   5.391+	AFRINTPS,
   5.392+	AFRINTPD,
   5.393+	AFRINTMS,
   5.394+	AFRINTMD,
   5.395+	AFRINTZS,
   5.396+	AFRINTZD,
   5.397+	AFRINTAS,
   5.398+	AFRINTAD,
   5.399+	AFRINTXS,
   5.400+	AFRINTXD,
   5.401+	AFRINTIS,
   5.402+	AFRINTID,
   5.403+	AFMADDS,
   5.404+	AFMADDD,
   5.405+	AFMSUBS,
   5.406+	AFMSUBD,
   5.407+	AFNMADDS,
   5.408+	AFNMADDD,
   5.409+	AFNMSUBS,
   5.410+	AFNMSUBD,
   5.411+	AFMINNMS,
   5.412+	AFMINNMD,
   5.413+	AFCVTDH,
   5.414+	AFCVTHS,
   5.415+	AFCVTHD,
   5.416+	AFCVTSH,
   5.417+
   5.418+	AAESD,
   5.419+	AAESE,
   5.420+	AAESIMC,
   5.421+	AAESMC,
   5.422+	ASHA1C,
   5.423+	ASHA1H,
   5.424+	ASHA1M,
   5.425+	ASHA1P,
   5.426+	ASHA1SU0,
   5.427+	ASHA1SU1,
   5.428+	ASHA256H,
   5.429+	ASHA256H2,
   5.430+	ASHA256SU0,
   5.431+	ASHA256SU1,
   5.432+	
   5.433+	ALAST,
   5.434+};
   5.435+
   5.436+/* form offset parameter to SYS; special register number */
   5.437+#define	SYSARG5(op0,op1,Cn,Cm,op2)	((op0)<<19|(op1)<<16|(Cn)<<12|(Cm)<<8|(op2)<<5)
   5.438+#define	SYSARG4(op1,Cn,Cm,op2)	SYSARG5(0,op1,Cn,Cm,op2)
   5.439+
   5.440+/* type/name */
   5.441+enum
   5.442+{
   5.443+	D_GOK	= 0,
   5.444+	D_NONE,
   5.445+
   5.446+/* name */
   5.447+	D_EXTERN,
   5.448+	D_STATIC,
   5.449+	D_AUTO,
   5.450+	D_PARAM,
   5.451+
   5.452+/* type */
   5.453+	D_BRANCH,
   5.454+	D_OREG,		/* offset(reg) */
   5.455+	D_XPRE,		/* offset(reg)! - pre-indexed */
   5.456+	D_XPOST,		/* (reg)offset! - post-indexed */
   5.457+	D_CONST,	/* 32-bit constant */
   5.458+	D_DCONST,	/* 64-bit constant */
   5.459+	D_FCONST,	/* floating-point constant */
   5.460+	D_SCONST,	/* short string constant */
   5.461+	D_REG,		/* Rn = Wn or Xn depending on op */
   5.462+	D_SP,		/* distinguish REGSP from REGZERO */
   5.463+	D_FREG,		/* Fn = Sn or Dn depending on op */
   5.464+	D_VREG,		/* Vn = SIMD register */
   5.465+	D_SPR,		/* special processor register */
   5.466+	D_FILE,
   5.467+	D_OCONST,	/* absolute address constant (unused) */
   5.468+	D_FILE1,
   5.469+
   5.470+	D_SHIFT,		/* Rm{, ashift #imm} */
   5.471+	D_PAIR,		/* pair of gprs */
   5.472+	D_ADDR,		/* address constant (dynamic loading) */
   5.473+	D_ADRP,		/* pc-relative addressing, page */
   5.474+	D_ADRLO,	/* low-order 12 bits of external reference */
   5.475+	D_EXTREG,	/* Rm{, ext #imm} */
   5.476+	D_ROFF,		/* register offset Rn+ext(Rm)<<s */
   5.477+	D_COND,		/* condition EQ, NE, etc */
   5.478+	D_VLANE,		/* Vn lane */
   5.479+	D_VSET,		/* set of Vn */
   5.480+
   5.481+	/* offset iff type is D_SPR */
   5.482+	D_DAIF	= SYSARG5(3,3,4,2,1),
   5.483+	D_NZCV	= SYSARG5(3,3,4,2,0),
   5.484+	D_FPSR	= SYSARG5(3,3,4,4,1),
   5.485+	D_FPCR	= SYSARG5(3,3,4,4,0),
   5.486+	D_SPSR_EL1 = SYSARG5(3,0,4,0,0),
   5.487+	D_ELR_EL1 = SYSARG5(3,0,4,0,1),
   5.488+	D_SPSR_EL2 = SYSARG5(3,4,4,0,0),
   5.489+	D_ELR_EL2 = SYSARG5(3,4,4,0,1),
   5.490+//	D_SPSR_EL3 = SYSARG5(3,x,4,x,x),
   5.491+//	D_ELR_EL3 = SYSARG5(3,x,4,x,x),
   5.492+//	D_LR_EL0 = SYSARG5(3,x,4,x,x),
   5.493+	D_CurrentEL = SYSARG5(3,0,4,2,2),
   5.494+	D_SP_EL0 = SYSARG5(3,0,4,1,0),
   5.495+//	D_SP_EL1 = SYSARG5(3,x,4,x,x),
   5.496+//	D_SP_EL2 = SYSARG5(3,x,4,x,x),
   5.497+	D_SPSel	= SYSARG5(3,0,4,2,0),
   5.498+//	D_SPSR_abt  = SYSARG5(3,x,4,x,x),
   5.499+//	D_SPSR_fiq = SYSARG5(3,x,4,x,x),
   5.500+//	D_SPSR_ieq = SYSARG5(3,x,4,x,x),
   5.501+//	D_SPSR_und = SYSARG5(3,x,4,x,x),
   5.502+	D_DAIFSet = (1<<30)|0,
   5.503+	D_DAIFClr = (1<<30)|1
   5.504+};
   5.505+
   5.506+/*
   5.507+ * this is the ranlib header
   5.508+ */
   5.509+#define	SYMDEF	"__.SYMDEF"
   5.510+
   5.511+/*
   5.512+ * this is the simulated IEEE floating point
   5.513+ */
   5.514+typedef	struct	Ieee	Ieee;
   5.515+struct	Ieee
   5.516+{
   5.517+	long	l;	/* contains ls-man	0xffffffff */
   5.518+	long	h;	/* contains sign	0x80000000
   5.519+				    exp		0x7ff00000
   5.520+				    ms-man	0x000fffff */
   5.521+};
     6.1new file mode 100644
     6.2--- /dev/null
     6.3+++ b/sys/src/cmd/7c/cgen.c
     6.4@@ -0,0 +1,1256 @@
     6.5+#include "gc.h"
     6.6+
     6.7+void
     6.8+cgen(Node *n, Node *nn)
     6.9+{
    6.10+	cgenrel(n, nn, 0);
    6.11+}
    6.12+
    6.13+void
    6.14+cgenrel(Node *n, Node *nn, int inrel)
    6.15+{
    6.16+	Node *l, *r;
    6.17+	Prog *p1;
    6.18+	Node nod, nod1, nod2, nod3, nod4;
    6.19+	int o, t;
    6.20+	long v, curs;
    6.21+
    6.22+	if(debug['g']) {
    6.23+		prtree(nn, "cgen lhs");
    6.24+		prtree(n, "cgen");
    6.25+	}
    6.26+	if(n == Z || n->type == T)
    6.27+		return;
    6.28+	if(typesu[n->type->etype]) {
    6.29+		sugen(n, nn, n->type->width);
    6.30+		return;
    6.31+	}
    6.32+	l = n->left;
    6.33+	r = n->right;
    6.34+	o = n->op;
    6.35+	if(n->addable >= INDEXED) {
    6.36+		if(nn == Z) {
    6.37+			switch(o) {
    6.38+			default:
    6.39+				nullwarn(Z, Z);
    6.40+				break;
    6.41+			case OINDEX:
    6.42+				nullwarn(l, r);
    6.43+				break;
    6.44+			}
    6.45+			return;
    6.46+		}
    6.47+		gmove(n, nn);
    6.48+		return;
    6.49+	}
    6.50+	curs = cursafe;
    6.51+
    6.52+	if(n->complex >= FNX)
    6.53+	if(l->complex >= FNX)
    6.54+	if(r != Z && r->complex >= FNX)
    6.55+	switch(o) {
    6.56+	default:
    6.57+		if(cond(o) && typesu[l->type->etype])
    6.58+			break;
    6.59+
    6.60+		regret(&nod, r);
    6.61+		cgen(r, &nod);
    6.62+
    6.63+		regsalloc(&nod1, r);
    6.64+		gopcode(OAS, &nod, Z, &nod1);
    6.65+
    6.66+		regfree(&nod);
    6.67+		nod = *n;
    6.68+		nod.right = &nod1;
    6.69+		cgen(&nod, nn);
    6.70+		return;
    6.71+
    6.72+	case OFUNC:
    6.73+	case OCOMMA:
    6.74+	case OANDAND:
    6.75+	case OOROR:
    6.76+	case OCOND:
    6.77+	case ODOT:
    6.78+		break;
    6.79+	}
    6.80+
    6.81+	switch(o) {
    6.82+	default:
    6.83+		diag(n, "unknown op in cgen: %O", o);
    6.84+		break;
    6.85+
    6.86+	case ONEG:
    6.87+	case OCOM:
    6.88+		if(nn == Z) {
    6.89+			nullwarn(l, Z);
    6.90+			break;
    6.91+		}
    6.92+		regalloc(&nod, l, nn);
    6.93+		cgen(l, &nod);
    6.94+		gopcode(o, &nod, Z, &nod);
    6.95+		gmove(&nod, nn);
    6.96+		regfree(&nod);
    6.97+		break;
    6.98+
    6.99+	case OAS:
   6.100+		if(l->op == OBIT)
   6.101+			goto bitas;
   6.102+		if(l->addable >= INDEXED && l->complex < FNX) {
   6.103+			if(nn != Z || r->addable < INDEXED) {	/* || hardconst(r) */
   6.104+				if(r->complex >= FNX && nn == Z)
   6.105+					regret(&nod, r);
   6.106+				else
   6.107+					regalloc(&nod, r, nn);
   6.108+				cgen(r, &nod);
   6.109+				gmove(&nod, l);
   6.110+				if(nn != Z)
   6.111+					gmove(&nod, nn);
   6.112+				regfree(&nod);
   6.113+			} else
   6.114+				gmove(r, l);
   6.115+			break;
   6.116+		}
   6.117+		if(l->complex >= r->complex) {
   6.118+			/* TO DO: see 6c for OINDEX && immconst(r) */
   6.119+			reglcgen(&nod1, l, Z);
   6.120+			if(r->addable >= INDEXED) {	/* && !hardconst(r) */
   6.121+				gmove(r, &nod1);
   6.122+				if(nn != Z)
   6.123+					gmove(r, nn);
   6.124+				regfree(&nod1);
   6.125+				break;
   6.126+			}
   6.127+			regalloc(&nod, r, nn);
   6.128+			cgen(r, &nod);
   6.129+		} else {
   6.130+			regalloc(&nod, r, nn);
   6.131+			cgen(r, &nod);
   6.132+			reglcgen(&nod1, l, Z);
   6.133+		}
   6.134+		gmove(&nod, &nod1);
   6.135+		regfree(&nod);
   6.136+		regfree(&nod1);
   6.137+		break;
   6.138+
   6.139+	bitas:
   6.140+		n = l->left;
   6.141+		regalloc(&nod, r, nn);
   6.142+		if(l->complex >= r->complex) {
   6.143+			reglcgen(&nod1, n, Z);
   6.144+			cgen(r, &nod);
   6.145+		} else {
   6.146+			cgen(r, &nod);
   6.147+			reglcgen(&nod1, n, Z);
   6.148+		}
   6.149+		regalloc(&nod2, n, Z);
   6.150+		gopcode(OAS, &nod1, Z, &nod2);
   6.151+		bitstore(l, &nod, &nod1, &nod2, nn);
   6.152+		break;
   6.153+
   6.154+	case OBIT:
   6.155+		if(nn == Z) {
   6.156+			nullwarn(l, Z);
   6.157+			break;
   6.158+		}
   6.159+		bitload(n, &nod, Z, Z, nn);
   6.160+		gopcode(OAS, &nod, Z, nn);
   6.161+		regfree(&nod);
   6.162+		break;
   6.163+
   6.164+	case ODIV:
   6.165+	case OMOD:
   6.166+		if(nn != Z)
   6.167+		if((t = vlog(r)) >= 0) {
   6.168+			/* signed div/mod by constant power of 2 */
   6.169+			cgen(l, nn);
   6.170+			gopcode(OGE, nodconst(0), nn, Z);
   6.171+			p1 = p;
   6.172+			if(o == ODIV) {
   6.173+				gopcode(OADD, nodconst((1<<t)-1), Z, nn);
   6.174+				patch(p1, pc);
   6.175+				gopcode(OASHR, nodconst(t), Z, nn);
   6.176+			} else {
   6.177+				gopcode(ONEG, nn, Z, nn);
   6.178+				gopcode(OAND, nodconst((1<<t)-1), Z, nn);
   6.179+				gopcode(ONEG, nn, Z, nn);
   6.180+				gbranch(OGOTO);
   6.181+				patch(p1, pc);
   6.182+				p1 = p;
   6.183+				gopcode(OAND, nodconst((1<<t)-1), Z, nn);
   6.184+				patch(p1, pc);
   6.185+			}
   6.186+			break;
   6.187+		}
   6.188+		goto muldiv;
   6.189+
   6.190+	case OXOR:
   6.191+#ifdef NOTYET
   6.192+		if(nn != Z)
   6.193+		if(r->op == OCONST && r->vconst == -1){
   6.194+			cgen(l, nn);
   6.195+			gopcode(OCOM, nn, Z, nn);
   6.196+			break;
   6.197+		}
   6.198+#endif
   6.199+
   6.200+	case OSUB:
   6.201+	case OADD:
   6.202+	case OAND:
   6.203+	case OOR:
   6.204+	case OLSHR:
   6.205+	case OASHL:
   6.206+	case OASHR:
   6.207+		/*
   6.208+		 * immediate operands
   6.209+		 */
   6.210+		if(nn != Z)
   6.211+		if(r->op == OCONST)
   6.212+		if(!typefd[n->type->etype]) {
   6.213+			cgen(l, nn);
   6.214+			if(r->vconst == 0)
   6.215+			if(o != OAND)
   6.216+				break;
   6.217+			if(nn != Z)
   6.218+				gopcode(o, r, Z, nn);
   6.219+			break;
   6.220+		}
   6.221+
   6.222+	case OLMUL:
   6.223+	case OLDIV:
   6.224+	case OLMOD:
   6.225+	case OMUL:
   6.226+	muldiv:
   6.227+		if(nn == Z) {
   6.228+			nullwarn(l, r);
   6.229+			break;
   6.230+		}
   6.231+		if(o == OMUL || o == OLMUL) {
   6.232+			if(mulcon(n, nn))
   6.233+				break;
   6.234+		}
   6.235+		if(l->complex >= r->complex) {
   6.236+			regalloc(&nod, l, nn);
   6.237+			cgen(l, &nod);
   6.238+			regalloc(&nod1, l, Z);		/* note: l used for type, so shifts work! */
   6.239+			cgen(r, &nod1);
   6.240+			gopcode(o, &nod1, Z, &nod);
   6.241+		} else {
   6.242+			regalloc(&nod, l, nn);		/* note: l used for type, so shifts work! */
   6.243+			cgen(r, &nod);
   6.244+			regalloc(&nod1, l, Z);
   6.245+			cgen(l, &nod1);
   6.246+			gopcode(o, &nod, &nod1, &nod);
   6.247+		}
   6.248+		gopcode(OAS, &nod, Z, nn);
   6.249+		regfree(&nod);
   6.250+		regfree(&nod1);
   6.251+		break;
   6.252+
   6.253+	case OASLSHR:
   6.254+	case OASASHL:
   6.255+	case OASASHR:
   6.256+	case OASAND:
   6.257+	case OASADD:
   6.258+	case OASSUB:
   6.259+	case OASXOR:
   6.260+	case OASOR:
   6.261+		if(l->op == OBIT)
   6.262+			goto asbitop;
   6.263+		if(r->op == OCONST)
   6.264+		if(!typefd[r->type->etype])
   6.265+		if(!typefd[n->type->etype]) {
   6.266+			if(l->addable < INDEXED)
   6.267+				reglcgen(&nod2, l, Z);
   6.268+			else
   6.269+				nod2 = *l;
   6.270+			regalloc(&nod, l, nn);		/* note: l used for type, so shifts work! */
   6.271+			gopcode(OAS, &nod2, Z, &nod);
   6.272+			gopcode(o, r, Z, &nod);
   6.273+			gopcode(OAS, &nod, Z, &nod2);
   6.274+	
   6.275+			regfree(&nod);
   6.276+			if(l->addable < INDEXED)
   6.277+				regfree(&nod2);
   6.278+			break;
   6.279+		}
   6.280+
   6.281+	case OASLMUL:
   6.282+	case OASLDIV:
   6.283+	case OASLMOD:
   6.284+	case OASMUL:
   6.285+	case OASDIV:
   6.286+	case OASMOD:
   6.287+		if(l->op == OBIT)
   6.288+			goto asbitop;
   6.289+		if(l->complex >= r->complex) {
   6.290+			if(l->addable < INDEXED)
   6.291+				reglcgen(&nod2, l, Z);
   6.292+			else
   6.293+				nod2 = *l;
   6.294+			regalloc(&nod, n, nn);
   6.295+			cgen(r, &nod);
   6.296+		} else {
   6.297+			regalloc(&nod, n, nn);
   6.298+			cgen(r, &nod);
   6.299+			if(l->addable < INDEXED)
   6.300+				reglcgen(&nod2, l, Z);
   6.301+			else
   6.302+				nod2 = *l;
   6.303+		}
   6.304+		regalloc(&nod1, n, Z);
   6.305+		gopcode(OAS, &nod2, Z, &nod1);
   6.306+		if(nod1.type->etype != nod.type->etype){
   6.307+			regalloc(&nod3, &nod, Z);
   6.308+			gmove(&nod1, &nod3);
   6.309+			regfree(&nod1);
   6.310+			nod1 = nod3;
   6.311+		}
   6.312+		gopcode(o, &nod, &nod1, &nod);
   6.313+		gmove(&nod, &nod2);
   6.314+		if(nn != Z)
   6.315+			gmove(&nod, nn);
   6.316+		regfree(&nod);
   6.317+		regfree(&nod1);
   6.318+		if(l->addable < INDEXED)
   6.319+			regfree(&nod2);
   6.320+		break;
   6.321+
   6.322+	asbitop:
   6.323+		regalloc(&nod4, n, nn);
   6.324+		regalloc(&nod3, r, Z);
   6.325+		if(l->complex >= r->complex) {
   6.326+			bitload(l, &nod, &nod1, &nod2, &nod4);
   6.327+			cgen(r, &nod3);
   6.328+		} else {
   6.329+			cgen(r, &nod3);
   6.330+			bitload(l, &nod, &nod1, &nod2, &nod4);
   6.331+		}
   6.332+		gmove(&nod, &nod4);
   6.333+		gopcode(o, &nod3, Z, &nod4);
   6.334+		regfree(&nod3);
   6.335+		gmove(&nod4, &nod);
   6.336+		regfree(&nod4);
   6.337+		bitstore(l, &nod, &nod1, &nod2, nn);
   6.338+		break;
   6.339+
   6.340+	case OADDR:
   6.341+		if(nn == Z) {
   6.342+			nullwarn(l, Z);
   6.343+			break;
   6.344+		}
   6.345+		lcgen(l, nn);
   6.346+		break;
   6.347+
   6.348+	case OFUNC:
   6.349+		l = uncomma(l);
   6.350+		if(l->complex >= FNX) {
   6.351+			if(l->op != OIND)
   6.352+				diag(n, "bad function call");
   6.353+
   6.354+			regret(&nod, l->left);
   6.355+			cgen(l->left, &nod);
   6.356+			regsalloc(&nod1, l->left);
   6.357+			gopcode(OAS, &nod, Z, &nod1);
   6.358+			regfree(&nod);
   6.359+
   6.360+			nod = *n;
   6.361+			nod.left = &nod2;
   6.362+			nod2 = *l;
   6.363+			nod2.left = &nod1;
   6.364+			nod2.complex = 1;
   6.365+			cgen(&nod, nn);
   6.366+
   6.367+			return;
   6.368+		}
   6.369+		if(REGARG >= 0)
   6.370+			o = reg[REGARG];
   6.371+		gargs(r, &nod, &nod1);
   6.372+		if(l->addable < INDEXED) {
   6.373+			reglcgen(&nod, l, Z);
   6.374+			gopcode(OFUNC, Z, Z, &nod);
   6.375+			regfree(&nod);
   6.376+		} else
   6.377+			gopcode(OFUNC, Z, Z, l);
   6.378+		if(REGARG >= 0)
   6.379+			if(o != reg[REGARG])
   6.380+				reg[REGARG]--;
   6.381+		if(nn != Z) {
   6.382+			regret(&nod, n);
   6.383+			gopcode(OAS, &nod, Z, nn);
   6.384+			regfree(&nod);
   6.385+		}
   6.386+		break;
   6.387+
   6.388+	case OIND:
   6.389+		if(nn == Z) {
   6.390+			nullwarn(l, Z);
   6.391+			break;
   6.392+		}
   6.393+		regialloc(&nod, n, nn);
   6.394+		r = l;
   6.395+		while(r->op == OADD)
   6.396+			r = r->right;
   6.397+		if(sconst(r) && (v = r->vconst+nod.xoffset) >= -4096 && v < 4096) {
   6.398+			v = r->vconst;
   6.399+			r->vconst = 0;
   6.400+			cgen(l, &nod);
   6.401+			nod.xoffset += v;
   6.402+			r->vconst = v;
   6.403+		} else
   6.404+			cgen(l, &nod);
   6.405+		regind(&nod, n);
   6.406+		gopcode(OAS, &nod, Z, nn);
   6.407+		regfree(&nod);
   6.408+		break;
   6.409+
   6.410+	case OEQ:
   6.411+	case ONE:
   6.412+	case OLE:
   6.413+	case OLT:
   6.414+	case OGE:
   6.415+	case OGT:
   6.416+	case OLO:
   6.417+	case OLS:
   6.418+	case OHI:
   6.419+	case OHS:
   6.420+		if(nn == Z) {
   6.421+			nullwarn(l, r);
   6.422+			break;
   6.423+		}
   6.424+		boolgen(n, 1, nn);
   6.425+		break;
   6.426+
   6.427+	case OANDAND:
   6.428+	case OOROR:
   6.429+		boolgen(n, 1, nn);
   6.430+		if(nn == Z)
   6.431+			patch(p, pc);
   6.432+		break;
   6.433+
   6.434+	case ONOT:
   6.435+		if(nn == Z) {
   6.436+			nullwarn(l, Z);
   6.437+			break;
   6.438+		}
   6.439+		boolgen(n, 1, nn);
   6.440+		break;
   6.441+
   6.442+	case OCOMMA:
   6.443+		cgen(l, Z);
   6.444+		cgen(r, nn);
   6.445+		break;
   6.446+
   6.447+	case OCAST:
   6.448+		if(nn == Z) {
   6.449+			nullwarn(l, Z);
   6.450+			break;
   6.451+		}
   6.452+		/*
   6.453+		 * convert from types l->n->nn
   6.454+		 */
   6.455+		if(nocast(l->type, n->type) && nocast(n->type, nn->type)) {
   6.456+			/* both null, gen l->nn */
   6.457+			cgen(l, nn);
   6.458+			break;
   6.459+		}
   6.460+		if(ewidth[n->type->etype] < ewidth[l->type->etype]){
   6.461+			if(l->type->etype == TIND && typechlp[n->type->etype])
   6.462+				warn(n, "conversion of pointer to shorter integer");
   6.463+		}else if(0){
   6.464+			if(nocast(n->type, nn->type) || castup(n->type, nn->type)){
   6.465+				if(typefd[l->type->etype] != typefd[nn->type->etype])
   6.466+					regalloc(&nod, l, nn);
   6.467+				else
   6.468+					regalloc(&nod, nn, nn);
   6.469+				cgen(l, &nod);
   6.470+				gmove(&nod, nn);
   6.471+				regfree(&nod);
   6.472+				break;
   6.473+			}
   6.474+		}
   6.475+		regalloc(&nod, l, nn);
   6.476+		cgen(l, &nod);
   6.477+		regalloc(&nod1, n, &nod);
   6.478+		if(inrel)
   6.479+			gmover(&nod, &nod1);
   6.480+		else
   6.481+			gopcode(OAS, &nod, Z, &nod1);
   6.482+		gopcode(OAS, &nod1, Z, nn);
   6.483+		regfree(&nod1);
   6.484+		regfree(&nod);
   6.485+		break;
   6.486+
   6.487+	case ODOT:
   6.488+		sugen(l, nodrat, l->type->width);
   6.489+		if(nn != Z) {
   6.490+			warn(n, "non-interruptable temporary");
   6.491+			nod = *nodrat;
   6.492+			if(!r || r->op != OCONST) {
   6.493+				diag(n, "DOT and no offset");
   6.494+				break;
   6.495+			}
   6.496+			nod.xoffset += (long)r->vconst;
   6.497+			nod.type = n->type;
   6.498+			cgen(&nod, nn);
   6.499+		}
   6.500+		break;
   6.501+
   6.502+	case OCOND:
   6.503+		bcgen(l, 1);
   6.504+		p1 = p;
   6.505+		cgen(r->left, nn);
   6.506+		gbranch(OGOTO);
   6.507+		patch(p1, pc);
   6.508+		p1 = p;
   6.509+		cgen(r->right, nn);
   6.510+		patch(p1, pc);
   6.511+		break;
   6.512+
   6.513+	case OPOSTINC:
   6.514+	case OPOSTDEC:
   6.515+		v = 1;
   6.516+		if(l->type->etype == TIND)
   6.517+			v = l->type->link->width;
   6.518+		if(o == OPOSTDEC)
   6.519+			v = -v;
   6.520+		if(l->op == OBIT)
   6.521+			goto bitinc;
   6.522+		if(nn == Z)
   6.523+			goto pre;
   6.524+
   6.525+		if(l->addable < INDEXED)
   6.526+			reglcgen(&nod2, l, Z);
   6.527+		else
   6.528+			nod2 = *l;
   6.529+
   6.530+		regalloc(&nod, l, nn);
   6.531+		gopcode(OAS, &nod2, Z, &nod);
   6.532+		regalloc(&nod1, l, Z);
   6.533+		if(typefd[l->type->etype]) {
   6.534+			regalloc(&nod3, l, Z);
   6.535+			if(v < 0) {
   6.536+				gopcode(OAS, nodfconst(-v), Z, &nod3);
   6.537+				gopcode(OSUB, &nod3, &nod, &nod1);
   6.538+			} else {
   6.539+				gopcode(OAS, nodfconst(v), Z, &nod3);
   6.540+				gopcode(OADD, &nod3, &nod, &nod1);
   6.541+			}
   6.542+			regfree(&nod3);
   6.543+		} else
   6.544+			gopcode(OADD, nodconst(v), &nod, &nod1);
   6.545+		gopcode(OAS, &nod1, Z, &nod2);
   6.546+
   6.547+		regfree(&nod);
   6.548+		regfree(&nod1);
   6.549+		if(l->addable < INDEXED)
   6.550+			regfree(&nod2);
   6.551+		break;
   6.552+
   6.553+	case OPREINC:
   6.554+	case OPREDEC:
   6.555+		v = 1;
   6.556+		if(l->type->etype == TIND)
   6.557+			v = l->type->link->width;
   6.558+		if(o == OPREDEC)
   6.559+			v = -v;
   6.560+		if(l->op == OBIT)
   6.561+			goto bitinc;
   6.562+
   6.563+	pre:
   6.564+		if(l->addable < INDEXED)
   6.565+			reglcgen(&nod2, l, Z);
   6.566+		else
   6.567+			nod2 = *l;
   6.568+
   6.569+		regalloc(&nod, l, nn);
   6.570+		gopcode(OAS, &nod2, Z, &nod);
   6.571+		if(typefd[l->type->etype]) {
   6.572+			regalloc(&nod3, l, Z);
   6.573+			if(v < 0) {
   6.574+				gopcode(OAS, nodfconst(-v), Z, &nod3);
   6.575+				gopcode(OSUB, &nod3, Z, &nod);
   6.576+			} else {
   6.577+				gopcode(OAS, nodfconst(v), Z, &nod3);
   6.578+				gopcode(OADD, &nod3, Z, &nod);
   6.579+			}
   6.580+			regfree(&nod3);
   6.581+		} else
   6.582+			gopcode(OADD, nodconst(v), Z, &nod);
   6.583+		gopcode(OAS, &nod, Z, &nod2);
   6.584+		if(nn && l->op == ONAME)	/* in x=++i, emit USED(i) */
   6.585+			gins(ANOP, l, Z);
   6.586+
   6.587+		regfree(&nod);
   6.588+		if(l->addable < INDEXED)
   6.589+			regfree(&nod2);
   6.590+		break;
   6.591+
   6.592+	bitinc:
   6.593+		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
   6.594+			bitload(l, &nod, &nod1, &nod2, Z);
   6.595+			gopcode(OAS, &nod, Z, nn);
   6.596+			gopcode(OADD, nodconst(v), Z, &nod);
   6.597+			bitstore(l, &nod, &nod1, &nod2, Z);
   6.598+			break;
   6.599+		}
   6.600+		bitload(l, &nod, &nod1, &nod2, nn);
   6.601+		gopcode(OADD, nodconst(v), Z, &nod);
   6.602+		bitstore(l, &nod, &nod1, &nod2, nn);
   6.603+		break;
   6.604+	}
   6.605+	cursafe = curs;
   6.606+	return;
   6.607+}
   6.608+
   6.609+void
   6.610+reglcgen(Node *t, Node *n, Node *nn)
   6.611+{
   6.612+	Node *r;
   6.613+	long v;
   6.614+
   6.615+	regialloc(t, n, nn);
   6.616+	if(n->op == OIND) {
   6.617+		r = n->left;
   6.618+		while(r->op == OADD)
   6.619+			r = r->right;
   6.620+		if(sconst(r) && (v = r->vconst+t->xoffset) >= -4096 && v < 4096) {
   6.621+			v = r->vconst;
   6.622+			r->vconst = 0;
   6.623+			lcgen(n, t);
   6.624+			t->xoffset += v;
   6.625+			r->vconst = v;
   6.626+			regind(t, n);
   6.627+			return;
   6.628+		}
   6.629+	} else if(n->op == OINDREG) {
   6.630+		if((v = n->xoffset) >= -4096 && v < 4096) {
   6.631+			n->op = OREGISTER;
   6.632+			cgen(n, t);
   6.633+			t->xoffset += v;
   6.634+			n->op = OINDREG;
   6.635+			regind(t, n);
   6.636+			return;
   6.637+		}
   6.638+	}
   6.639+	lcgen(n, t);
   6.640+	regind(t, n);
   6.641+}
   6.642+
   6.643+void
   6.644+lcgen(Node *n, Node *nn)
   6.645+{
   6.646+	Prog *p1;
   6.647+	Node nod;
   6.648+
   6.649+	if(debug['g']) {
   6.650+		prtree(nn, "lcgen lhs");
   6.651+		prtree(n, "lcgen");
   6.652+	}
   6.653+	if(n == Z || n->type == T)
   6.654+		return;
   6.655+	if(nn == Z) {
   6.656+		nn = &nod;
   6.657+		regalloc(&nod, n, Z);
   6.658+	}
   6.659+	switch(n->op) {
   6.660+	default:
   6.661+		if(n->addable < INDEXED) {
   6.662+			diag(n, "unknown op in lcgen: %O", n->op);
   6.663+			break;
   6.664+		}
   6.665+		nod = *n;
   6.666+		nod.op = OADDR;
   6.667+		nod.left = n;
   6.668+		nod.right = Z;
   6.669+		nod.type = types[TIND];
   6.670+		gopcode(OAS, &nod, Z, nn);
   6.671+		break;
   6.672+
   6.673+	case OCOMMA:
   6.674+		cgen(n->left, n->left);
   6.675+		lcgen(n->right, nn);
   6.676+		break;
   6.677+
   6.678+	case OIND:
   6.679+		cgen(n->left, nn);
   6.680+		break;
   6.681+
   6.682+	case OCOND:
   6.683+		bcgen(n->left, 1);
   6.684+		p1 = p;
   6.685+		lcgen(n->right->left, nn);
   6.686+		gbranch(OGOTO);
   6.687+		patch(p1, pc);
   6.688+		p1 = p;
   6.689+		lcgen(n->right->right, nn);
   6.690+		patch(p1, pc);
   6.691+		break;
   6.692+	}
   6.693+}
   6.694+
   6.695+void
   6.696+bcgen(Node *n, int true)
   6.697+{
   6.698+
   6.699+	if(n->type == T)
   6.700+		gbranch(OGOTO);
   6.701+	else
   6.702+		boolgen(n, true, Z);
   6.703+}
   6.704+
   6.705+void
   6.706+boolgen(Node *n, int true, Node *nn)
   6.707+{
   6.708+	int o;
   6.709+	Prog *p1, *p2;
   6.710+	Node *l, *r, nod, nod1;
   6.711+	long curs;
   6.712+
   6.713+	if(debug['g']) {
   6.714+		prtree(nn, "boolgen lhs");
   6.715+		prtree(n, "boolgen");
   6.716+	}
   6.717+	curs = cursafe;
   6.718+	l = n->left;
   6.719+	r = n->right;
   6.720+	switch(n->op) {
   6.721+
   6.722+	default:
   6.723+		regalloc(&nod, n, nn);
   6.724+		cgen(n, &nod);
   6.725+		o = ONE;
   6.726+		if(true)
   6.727+			o = OEQ;
   6.728+		if(typefd[n->type->etype]) {
   6.729+			gopcode(true ? o | BTRUE : o, nodfconst(0), &nod, Z);
   6.730+		} else
   6.731+			gopcode(o, nodconst(0), &nod, Z);
   6.732+		regfree(&nod);
   6.733+		goto com;
   6.734+
   6.735+	case OCONST:
   6.736+		o = vconst(n);
   6.737+		if(!true)
   6.738+			o = !o;
   6.739+		gbranch(OGOTO);
   6.740+		if(o) {
   6.741+			p1 = p;
   6.742+			gbranch(OGOTO);
   6.743+			patch(p1, pc);
   6.744+		}
   6.745+		goto com;
   6.746+
   6.747+	case OCOMMA:
   6.748+		cgen(l, Z);
   6.749+		boolgen(r, true, nn);
   6.750+		break;
   6.751+
   6.752+	case ONOT:
   6.753+		boolgen(l, !true, nn);
   6.754+		break;
   6.755+
   6.756+	case OCOND:
   6.757+		bcgen(l, 1);
   6.758+		p1 = p;
   6.759+		bcgen(r->left, true);
   6.760+		p2 = p;
   6.761+		gbranch(OGOTO);
   6.762+		patch(p1, pc);
   6.763+		p1 = p;
   6.764+		bcgen(r->right, !true);
   6.765+		patch(p2, pc);
   6.766+		p2 = p;
   6.767+		gbranch(OGOTO);
   6.768+		patch(p1, pc);
   6.769+		patch(p2, pc);
   6.770+		goto com;
   6.771+
   6.772+	case OANDAND:
   6.773+		if(!true)
   6.774+			goto caseor;
   6.775+
   6.776+	caseand:
   6.777+		bcgen(l, true);
   6.778+		p1 = p;
   6.779+		bcgen(r, !true);
   6.780+		p2 = p;
   6.781+		patch(p1, pc);
   6.782+		gbranch(OGOTO);
   6.783+		patch(p2, pc);
   6.784+		goto com;
   6.785+
   6.786+	case OOROR:
   6.787+		if(!true)
   6.788+			goto caseand;
   6.789+
   6.790+	caseor:
   6.791+		bcgen(l, !true);
   6.792+		p1 = p;
   6.793+		bcgen(r, !true);
   6.794+		p2 = p;
   6.795+		gbranch(OGOTO);
   6.796+		patch(p1, pc);
   6.797+		patch(p2, pc);
   6.798+		goto com;
   6.799+
   6.800+	case OEQ:
   6.801+	case ONE:
   6.802+	case OLE:
   6.803+	case OLT:
   6.804+	case OGE:
   6.805+	case OGT:
   6.806+	case OHI:
   6.807+	case OHS:
   6.808+	case OLO:
   6.809+	case OLS:
   6.810+		o = n->op;
   6.811+		if(true)
   6.812+			o = comrel[relindex(o)];
   6.813+		if(l->complex >= FNX && r->complex >= FNX) {
   6.814+			regret(&nod, r);
   6.815+			cgenrel(r, &nod, 1);
   6.816+			regsalloc(&nod1, r);
   6.817+			gopcode(OAS, &nod, Z, &nod1);
   6.818+			regfree(&nod);
   6.819+			nod = *n;
   6.820+			nod.right = &nod1;
   6.821+			boolgen(&nod, true, nn);
   6.822+			break;
   6.823+		}
   6.824+		if(sconst(l)) {
   6.825+			regalloc(&nod, r, nn);
   6.826+			cgenrel(r, &nod, 1);
   6.827+			o = invrel[relindex(o)];
   6.828+			gopcode(true ? o | BTRUE : o, l, &nod, Z);
   6.829+			regfree(&nod);
   6.830+			goto com;
   6.831+		}
   6.832+		if(sconst(r)) {
   6.833+			regalloc(&nod, l, nn);
   6.834+			cgenrel(l, &nod, 1);
   6.835+			gopcode(true ? o | BTRUE : o, r, &nod, Z);
   6.836+			regfree(&nod);
   6.837+			goto com;
   6.838+		}
   6.839+		if(l->complex >= r->complex) {
   6.840+			regalloc(&nod1, l, nn);
   6.841+			cgenrel(l, &nod1, 1);
   6.842+			regalloc(&nod, r, Z);
   6.843+			cgenrel(r, &nod, 1);
   6.844+		} else {
   6.845+			regalloc(&nod, r, nn);
   6.846+			cgenrel(r, &nod, 1);
   6.847+			regalloc(&nod1, l, Z);
   6.848+			cgenrel(l, &nod1, 1);
   6.849+		}
   6.850+		gopcode(true ? o | BTRUE : o, &nod, &nod1, Z);
   6.851+		regfree(&nod);
   6.852+		regfree(&nod1);
   6.853+
   6.854+	com:
   6.855+		if(nn != Z) {
   6.856+			p1 = p;
   6.857+			gopcode(OAS, nodconst(1), Z, nn);
   6.858+			gbranch(OGOTO);
   6.859+			p2 = p;
   6.860+			patch(p1, pc);
   6.861+			gopcode(OAS, nodconst(0), Z, nn);
   6.862+			patch(p2, pc);
   6.863+		}
   6.864+		break;
   6.865+	}
   6.866+	cursafe = curs;
   6.867+}
   6.868+
   6.869+void
   6.870+sugen(Node *n, Node *nn, long w)
   6.871+{
   6.872+	Prog *p1;
   6.873+	Node nod0, nod1, nod2, nod3, nod4, *l, *r;
   6.874+	Type *t;
   6.875+	long pc1;
   6.876+	int i, m, c;
   6.877+
   6.878+	if(n == Z || n->type == T)
   6.879+		return;
   6.880+	if(debug['g']) {
   6.881+		prtree(nn, "sugen lhs");
   6.882+		prtree(n, "sugen");
   6.883+	}
   6.884+	if(nn == nodrat)
   6.885+		if(w > nrathole)
   6.886+			nrathole = w;
   6.887+	switch(n->op) {
   6.888+	case OIND:
   6.889+		if(nn == Z) {
   6.890+			nullwarn(n->left, Z);
   6.891+			break;
   6.892+		}
   6.893+
   6.894+	default:
   6.895+		goto copy;
   6.896+
   6.897+	case OCONST:
   6.898+		if(n->type && typev[n->type->etype]) {
   6.899+			if(nn == Z) {
   6.900+				nullwarn(n->left, Z);
   6.901+				break;
   6.902+			}
   6.903+
   6.904+			t = nn->type;
   6.905+			nn->type = types[TLONG];
   6.906+			reglcgen(&nod1, nn, Z);
   6.907+			nn->type = t;
   6.908+
   6.909+			if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
   6.910+				gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
   6.911+			else
   6.912+				gopcode(OAS, nod32const(n->vconst), Z, &nod1);
   6.913+			nod1.xoffset += SZ_LONG;
   6.914+			if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
   6.915+				gopcode(OAS, nod32const(n->vconst), Z, &nod1);
   6.916+			else
   6.917+				gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
   6.918+
   6.919+			regfree(&nod1);
   6.920+			break;
   6.921+		}
   6.922+		goto copy;
   6.923+
   6.924+	case ODOT:
   6.925+		l = n->left;
   6.926+		sugen(l, nodrat, l->type->width);
   6.927+		if(nn != Z) {
   6.928+			warn(n, "non-interruptable temporary");
   6.929+			nod1 = *nodrat;
   6.930+			r = n->right;
   6.931+			if(!r || r->op != OCONST) {
   6.932+				diag(n, "DOT and no offset");
   6.933+				break;
   6.934+			}
   6.935+			nod1.xoffset += (long)r->vconst;
   6.936+			nod1.type = n->type;
   6.937+			sugen(&nod1, nn, w);
   6.938+		}
   6.939+		break;
   6.940+
   6.941+	case OSTRUCT:
   6.942+		/*
   6.943+		 * rewrite so lhs has no side effects
   6.944+		 */
   6.945+		if(nn != Z && side(nn)) {
   6.946+			nod1 = *n;
   6.947+			nod1.type = typ(TIND, n->type);
   6.948+			regret(&nod2, &nod1);
   6.949+			lcgen(nn, &nod2);
   6.950+			regsalloc(&nod0, &nod1);
   6.951+			gopcode(OAS, &nod2, Z, &nod0);
   6.952+			regfree(&nod2);
   6.953+
   6.954+			nod1 = *n;
   6.955+			nod1.op = OIND;
   6.956+			nod1.left = &nod0;
   6.957+			nod1.right = Z;
   6.958+			nod1.complex = 1;
   6.959+
   6.960+			sugen(n, &nod1, w);
   6.961+			return;
   6.962+		}
   6.963+
   6.964+		r = n->left;
   6.965+		for(t = n->type->link; t != T; t = t->down) {
   6.966+			l = r;
   6.967+			if(r->op == OLIST) {
   6.968+				l = r->left;
   6.969+				r = r->right;
   6.970+			}
   6.971+			if(nn == Z) {
   6.972+				cgen(l, nn);
   6.973+				continue;
   6.974+			}
   6.975+			/*
   6.976+			 * hand craft *(&nn + o) = l
   6.977+			 */
   6.978+			nod0 = znode;
   6.979+			nod0.op = OAS;
   6.980+			nod0.type = t;
   6.981+			nod0.left = &nod1;
   6.982+			nod0.right = l;
   6.983+
   6.984+			nod1 = znode;
   6.985+			nod1.op = OIND;
   6.986+			nod1.type = t;
   6.987+			nod1.left = &nod2;
   6.988+
   6.989+			nod2 = znode;
   6.990+			nod2.op = OADD;
   6.991+			nod2.type = typ(TIND, t);
   6.992+			nod2.left = &nod3;
   6.993+			nod2.right = &nod4;
   6.994+
   6.995+			nod3 = znode;
   6.996+			nod3.op = OADDR;
   6.997+			nod3.type = nod2.type;
   6.998+			nod3.left = nn;
   6.999+
  6.1000+			nod4 = znode;
  6.1001+			nod4.op = OCONST;
  6.1002+			nod4.type = nod2.type;
  6.1003+			nod4.vconst = t->offset;
  6.1004+
  6.1005+			ccom(&nod0);
  6.1006+			acom(&nod0);
  6.1007+			xcom(&nod0);
  6.1008+			nod0.addable = 0;
  6.1009+
  6.1010+			cgen(&nod0, Z);
  6.1011+		}
  6.1012+		break;
  6.1013+
  6.1014+	case OAS:
  6.1015+		if(nn == Z) {
  6.1016+			if(n->addable < INDEXED)
  6.1017+				sugen(n->right, n->left, w);
  6.1018+			break;
  6.1019+		}
  6.1020+		sugen(n->right, nodrat, w);
  6.1021+		warn(n, "non-interruptable temporary");
  6.1022+		sugen(nodrat, n->left, w);
  6.1023+		sugen(nodrat, nn, w);
  6.1024+		break;
  6.1025+
  6.1026+	case OFUNC:
  6.1027+		if(nn == Z) {
  6.1028+			sugen(n, nodrat, w);
  6.1029+			break;
  6.1030+		}
  6.1031+		if(nn->op != OIND) {
  6.1032+			nn = new1(OADDR, nn, Z);
  6.1033+			nn->type = types[TIND];
  6.1034+			nn->addable = 0;
  6.1035+		} else
  6.1036+			nn = nn->left;
  6.1037+		n = new(OFUNC, n->left, new(OLIST, nn, n->right));
  6.1038+		n->type = types[TVOID];
  6.1039+		n->left->type = types[TVOID];
  6.1040+		cgen(n, Z);
  6.1041+		break;
  6.1042+
  6.1043+	case OCOND:
  6.1044+		bcgen(n->left, 1);
  6.1045+		p1 = p;
  6.1046+		sugen(n->right->left, nn, w);
  6.1047+		gbranch(OGOTO);
  6.1048+		patch(p1, pc);
  6.1049+		p1 = p;
  6.1050+		sugen(n->right->right, nn, w);
  6.1051+		patch(p1, pc);
  6.1052+		break;
  6.1053+
  6.1054+	case OCOMMA:
  6.1055+		cgen(n->left, Z);
  6.1056+		sugen(n->right, nn, w);
  6.1057+		break;
  6.1058+	}
  6.1059+	return;
  6.1060+
  6.1061+copy:
  6.1062+	if(nn == Z)
  6.1063+		return;
  6.1064+	if(n->complex >= FNX && nn->complex >= FNX) {
  6.1065+		t = nn->type;
  6.1066+		nn->type = types[TLONG];
  6.1067+		regialloc(&nod1, nn, Z);
  6.1068+		lcgen(nn, &nod1);
  6.1069+		regsalloc(&nod2, nn);
  6.1070+		nn->type = t;
  6.1071+
  6.1072+		gopcode(OAS, &nod1, Z, &nod2);
  6.1073+		regfree(&nod1);
  6.1074+
  6.1075+		nod2.type = typ(TIND, t);
  6.1076+
  6.1077+		nod1 = nod2;
  6.1078+		nod1.op = OIND;
  6.1079+		nod1.left = &nod2;
  6.1080+		nod1.right = Z;
  6.1081+		nod1.complex = 1;
  6.1082+		nod1.type = t;
  6.1083+
  6.1084+		sugen(n, &nod1, w);
  6.1085+		return;
  6.1086+	}
  6.1087+
  6.1088+	/* TO DO: use AMOV/VLONG when possible */
  6.1089+	if(n->complex > nn->complex) {
  6.1090+		t = n->type;
  6.1091+		n->type = types[TLONG];
  6.1092+		reglcgen(&nod1, n, Z);
  6.1093+		n->type = t;
  6.1094+
  6.1095+		t = nn->type;
  6.1096+		nn->type = types[TLONG];
  6.1097+		reglcgen(&nod2, nn, Z);
  6.1098+		nn->type = t;
  6.1099+	} else {
  6.1100+		t = nn->type;
  6.1101+		nn->type = types[TLONG];
  6.1102+		reglcgen(&nod2, nn, Z);
  6.1103+		nn->type = t;
  6.1104+
  6.1105+		t = n->type;
  6.1106+		n->type = types[TLONG];
  6.1107+		reglcgen(&nod1, n, Z);
  6.1108+		n->type = t;
  6.1109+	}
  6.1110+
  6.1111+	w /= SZ_LONG;
  6.1112+	if(w <= 5) {
  6.1113+		layout(&nod1, &nod2, w, 0, Z);
  6.1114+		goto out;
  6.1115+	}
  6.1116+
  6.1117+	/*
  6.1118+	 * minimize space for unrolling loop
  6.1119+	 * 3,4,5 times. (6 or more is never minimum)
  6.1120+	 * if small structure, try 2 also.
  6.1121+	 */
  6.1122+	c = 0; /* set */
  6.1123+	m = 100;
  6.1124+	i = 3;
  6.1125+	if(w <= 15)
  6.1126+		i = 2;
  6.1127+	for(; i<=5; i++)
  6.1128+		if(i + w%i <= m) {
  6.1129+			c = i;
  6.1130+			m = c + w%c;
  6.1131+		}
  6.1132+
  6.1133+	regalloc(&nod3, &regnode, Z);
  6.1134+	layout(&nod1, &nod2, w%c, w/c, &nod3);
  6.1135+	
  6.1136+	pc1 = pc;
  6.1137+	layout(&nod1, &nod2, c, 0, Z);
  6.1138+
  6.1139+	gopcode(OSUB, nodconst(1L), Z, &nod3);
  6.1140+	nod1.op = OREGISTER;
  6.1141+	t = nod1.type;
  6.1142+	nod1.type = types[TIND];
  6.1143+	gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod1);
  6.1144+	nod1.type = t;
  6.1145+	nod2.op = OREGISTER;
  6.1146+	t = nod2.type;
  6.1147+	nod2.type = types[TIND];
  6.1148+	gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod2);
  6.1149+	nod2.type = t;
  6.1150+	
  6.1151+	gopcode(OGT, nodconst(0), &nod3, Z);
  6.1152+	patch(p, pc1);
  6.1153+
  6.1154+	regfree(&nod3);
  6.1155+out:
  6.1156+	regfree(&nod1);
  6.1157+	regfree(&nod2);
  6.1158+}
  6.1159+
  6.1160+void
  6.1161+layout(Node *f, Node *t, int c, int cv, Node *cn)
  6.1162+{
  6.1163+	Node t1, t2;
  6.1164+
  6.1165+	while(c > 3) {
  6.1166+		layout(f, t, 2, 0, Z);
  6.1167+		c -= 2;
  6.1168+	}
  6.1169+
  6.1170+	regalloc(&t1, &regnode, Z);
  6.1171+	regalloc(&t2, &regnode, Z);
  6.1172+	if(c > 0) {
  6.1173+		gopcode(OAS, f, Z, &t1);
  6.1174+		f->xoffset += SZ_LONG;
  6.1175+	}
  6.1176+	if(cn != Z)
  6.1177+		gopcode(OAS, nodconst(cv), Z, cn);
  6.1178+	if(c > 1) {
  6.1179+		gopcode(OAS, f, Z, &t2);
  6.1180+		f->xoffset += SZ_LONG;
  6.1181+	}
  6.1182+	if(c > 0) {
  6.1183+		gopcode(OAS, &t1, Z, t);
  6.1184+		t->xoffset += SZ_LONG;
  6.1185+	}
  6.1186+	if(c > 2) {
  6.1187+		gopcode(OAS, f, Z, &t1);
  6.1188+		f->xoffset += SZ_LONG;
  6.1189+	}
  6.1190+	if(c > 1) {
  6.1191+		gopcode(OAS, &t2, Z, t);
  6.1192+		t->xoffset += SZ_LONG;
  6.1193+	}
  6.1194+	if(c > 2) {
  6.1195+		gopcode(OAS, &t1, Z, t);
  6.1196+		t->xoffset += SZ_LONG;
  6.1197+	}
  6.1198+	regfree(&t1);
  6.1199+	regfree(&t2);
  6.1200+}
  6.1201+
  6.1202+/*
  6.1203+ * if a constant and vlong, doesn't fit as 32-bit signed immediate
  6.1204+ */
  6.1205+int
  6.1206+hardconst(Node *n)
  6.1207+{
  6.1208+	return n->op == OCONST && !sconst(n);
  6.1209+}
  6.1210+
  6.1211+/*
  6.1212+ * casting up to t2 covers an intermediate cast to t1
  6.1213+ */
  6.1214+int
  6.1215+castup(Type *t1, Type *t2)
  6.1216+{
  6.1217+	int ft;
  6.1218+
  6.1219+	if(!nilcast(t1, t2))
  6.1220+		return 0;
  6.1221+	/* known to be small to large */
  6.1222+	ft = t1->etype;
  6.1223+	switch(t2->etype){
  6.1224+	case TINT:
  6.1225+	case TLONG:
  6.1226+		return ft == TLONG || ft == TINT || ft == TSHORT || ft == TCHAR;
  6.1227+	case TUINT:
  6.1228+	case TULONG:
  6.1229+		return ft == TULONG || ft == TUINT || ft == TUSHORT || ft == TUCHAR;
  6.1230+	case TVLONG:
  6.1231+		return ft == TLONG || ft == TINT || ft == TSHORT;
  6.1232+	case TUVLONG:
  6.1233+		return ft == TULONG || ft == TUINT || ft == TUSHORT;
  6.1234+	}
  6.1235+	return 0;
  6.1236+}
  6.1237+
  6.1238+int
  6.1239+cond(int op)
  6.1240+{
  6.1241+	switch(op) {
  6.1242+	case OANDAND:
  6.1243+	case OOROR:
  6.1244+	case ONOT:
  6.1245+		return 1;
  6.1246+
  6.1247+	case OEQ:
  6.1248+	case ONE:
  6.1249+	case OLE:
  6.1250+	case OLT:
  6.1251+	case OGE:
  6.1252+	case OGT:
  6.1253+	case OHI:
  6.1254+	case OHS:
  6.1255+	case OLO:
  6.1256+	case OLS:
  6.1257+		return 1;
  6.1258+	}
  6.1259+	return 0;
  6.1260+}
     7.1new file mode 100644
     7.2--- /dev/null
     7.3+++ b/sys/src/cmd/7c/gc.h
     7.4@@ -0,0 +1,358 @@
     7.5+#include	"../cc/cc.h"
     7.6+#include	"../7c/7.out.h"
     7.7+
     7.8+/*
     7.9+ * 7c/arm64
    7.10+ * Arm64
    7.11+ */
    7.12+#define	SZ_CHAR		1
    7.13+#define	SZ_SHORT	2
    7.14+#define	SZ_INT		4
    7.15+#define	SZ_LONG		4
    7.16+#define	SZ_IND		8
    7.17+#define	SZ_FLOAT	4
    7.18+#define	SZ_VLONG	8
    7.19+#define	SZ_DOUBLE	8
    7.20+#define	FNX		100
    7.21+#define	BTRUE		0x1000
    7.22+
    7.23+typedef	struct	Adr	Adr;
    7.24+typedef	struct	Prog	Prog;
    7.25+typedef	struct	Case	Case;
    7.26+typedef	struct	C1	C1;
    7.27+typedef	struct	Multab	Multab;
    7.28+typedef	struct	Hintab	Hintab;
    7.29+typedef	struct	Var	Var;
    7.30+typedef	struct	Reg	Reg;
    7.31+typedef	struct	Rgn	Rgn;
    7.32+
    7.33+
    7.34+struct	Adr
    7.35+{
    7.36+	vlong	offset;
    7.37+	double	dval;
    7.38+	char	sval[NSNAME];
    7.39+	Ieee	ieee;
    7.40+
    7.41+	Sym*	sym;
    7.42+	char	type;
    7.43+	char	reg;
    7.44+	char	name;
    7.45+	char	etype;
    7.46+};
    7.47+#define	A	((Adr*)0)
    7.48+
    7.49+#define	INDEXED	9
    7.50+struct	Prog
    7.51+{
    7.52+	Adr	from;
    7.53+	Adr	to;
    7.54+	Prog*	link;
    7.55+	long	lineno;
    7.56+	ushort	as;
    7.57+	char	reg;
    7.58+	uchar	scond;
    7.59+};
    7.60+#define	P	((Prog*)0)
    7.61+
    7.62+struct	Case
    7.63+{
    7.64+	Case*	link;
    7.65+	vlong	val;
    7.66+	long	label;
    7.67+	char	def;
    7.68+	char isv;
    7.69+};
    7.70+#define	C	((Case*)0)
    7.71+
    7.72+struct	C1
    7.73+{
    7.74+	vlong	val;
    7.75+	long	label;
    7.76+};
    7.77+
    7.78+struct	Multab
    7.79+{
    7.80+	long	val;
    7.81+	char	code[20];
    7.82+};
    7.83+
    7.84+struct	Hintab
    7.85+{
    7.86+	ushort	val;
    7.87+	char	hint[10];
    7.88+};
    7.89+
    7.90+struct	Var
    7.91+{
    7.92+	vlong	offset;
    7.93+	Sym*	sym;
    7.94+	char	name;
    7.95+	char	etype;
    7.96+};
    7.97+
    7.98+struct	Reg
    7.99+{
   7.100+	long	pc;
   7.101+	long	rpo;		/* reverse post ordering */
   7.102+
   7.103+	Bits	set;
   7.104+	Bits	use1;
   7.105+	Bits	use2;
   7.106+
   7.107+	Bits	refbehind;
   7.108+	Bits	refahead;
   7.109+	Bits	calbehind;
   7.110+	Bits	calahead;
   7.111+	Bits	regdiff;
   7.112+	Bits	act;
   7.113+
   7.114+	long	regu;
   7.115+	long	loop;		/* could be shorter */
   7.116+
   7.117+	
   7.118+	Reg*	log5;
   7.119+	long	active;
   7.120+
   7.121+	Reg*	p1;
   7.122+	Reg*	p2;
   7.123+	Reg*	p2link;
   7.124+	Reg*	s1;
   7.125+	Reg*	s2;
   7.126+	Reg*	link;
   7.127+	Prog*	prog;
   7.128+};
   7.129+#define	R	((Reg*)0)
   7.130+
   7.131+#define	NRGN	1000		/* was 600; raised for paranoia.c */
   7.132+struct	Rgn
   7.133+{
   7.134+	Reg*	enter;
   7.135+	short	cost;
   7.136+	short	varno;
   7.137+	short	regno;
   7.138+};
   7.139+
   7.140+EXTERN	long	breakpc;
   7.141+EXTERN	long	nbreak;
   7.142+EXTERN	Case*	cases;
   7.143+EXTERN	Node	constnode;
   7.144+EXTERN	Node	fconstnode;
   7.145+EXTERN	Node	vconstnode;
   7.146+EXTERN	long	continpc;
   7.147+EXTERN	long	curarg;
   7.148+EXTERN	long	cursafe;
   7.149+EXTERN	Prog*	firstp;
   7.150+EXTERN	Prog*	lastp;
   7.151+EXTERN	long	maxargsafe;
   7.152+EXTERN	int	mnstring;
   7.153+EXTERN	Multab	multab[20];
   7.154+EXTERN	int	hintabsize;
   7.155+EXTERN	Node*	nodrat;
   7.156+EXTERN	Node*	nodret;
   7.157+EXTERN	Node*	nodsafe;
   7.158+EXTERN	long	nrathole;
   7.159+EXTERN	long	nstring;
   7.160+EXTERN	Prog*	p;
   7.161+EXTERN	long	pc;
   7.162+EXTERN	Node	regnode;
   7.163+EXTERN	Node	qregnode;
   7.164+EXTERN	char	string[NSNAME];
   7.165+EXTERN	Sym*	symrathole;
   7.166+EXTERN	Node	znode;
   7.167+EXTERN	Prog	zprog;
   7.168+EXTERN	char	reg[NREG+NFREG];
   7.169+EXTERN	long	exregoffset;
   7.170+EXTERN	long	exfregoffset;
   7.171+EXTERN	int	suppress;
   7.172+EXTERN	uchar	typechlpv[NTYPE];
   7.173+
   7.174+#define	BLOAD(r)	band(bnot(r->refbehind), r->refahead)
   7.175+#define	BSTORE(r)	band(bnot(r->calbehind), r->calahead)
   7.176+#define	LOAD(r)		(~r->refbehind.b[z] & r->refahead.b[z])
   7.177+#define	STORE(r)	(~r->calbehind.b[z] & r->calahead.b[z])
   7.178+
   7.179+#define	bset(a,n)	((a).b[(n)/32]&(1L<<(n)%32))
   7.180+
   7.181+#define	CLOAD	4
   7.182+#define	CREF	5
   7.183+#define	CINF	1000
   7.184+#define	LOOP	3
   7.185+
   7.186+EXTERN	Rgn	region[NRGN];
   7.187+EXTERN	Rgn*	rgp;
   7.188+EXTERN	int	nregion;
   7.189+EXTERN	int	nvar;
   7.190+
   7.191+EXTERN	Bits	externs;
   7.192+EXTERN	Bits	params;
   7.193+EXTERN	Bits	consts;
   7.194+EXTERN	Bits	addrs;
   7.195+
   7.196+EXTERN	long	regbits;
   7.197+EXTERN	long	exregbits;
   7.198+
   7.199+EXTERN	int	change;
   7.200+
   7.201+EXTERN	Reg*	firstr;
   7.202+EXTERN	Reg*	lastr;
   7.203+EXTERN	Reg	zreg;
   7.204+EXTERN	Reg*	freer;
   7.205+EXTERN	Var	var[NVAR];
   7.206+EXTERN	long*	idom;
   7.207+EXTERN	Reg**	rpo2r;
   7.208+EXTERN	long	maxnr;
   7.209+
   7.210+extern	char*	anames[];
   7.211+extern	Hintab	hintab[];
   7.212+
   7.213+/*
   7.214+ * sgen.c
   7.215+ */
   7.216+void	codgen(Node*, Node*);
   7.217+void	gen(Node*);
   7.218+void	noretval(int);
   7.219+void	usedset(Node*, int);
   7.220+void	xcom(Node*);
   7.221+int	bcomplex(Node*, Node*);
   7.222+
   7.223+/*
   7.224+ * cgen.c
   7.225+ */
   7.226+int	castup(Type*, Type*);
   7.227+void	cgen(Node*, Node*);
   7.228+void	cgenrel(Node*, Node*, int);
   7.229+int	cond(int);
   7.230+int	hardconst(Node*);
   7.231+void	reglcgen(Node*, Node*, Node*);
   7.232+void	layout(Node*, Node*, int, int, Node*);
   7.233+void	lcgen(Node*, Node*);
   7.234+void	bcgen(Node*, int);
   7.235+void	boolgen(Node*, int, Node*);
   7.236+void	sugen(Node*, Node*, long);
   7.237+void	layout(Node*, Node*, int, int, Node*);
   7.238+
   7.239+/*
   7.240+ * txt.c
   7.241+ */
   7.242+void	ginit(void);
   7.243+void	gclean(void);
   7.244+void	nextpc(void);
   7.245+void	gargs(Node*, Node*, Node*);
   7.246+void	garg1(Node*, Node*, Node*, int, Node**);
   7.247+Node*	nodconst(long);
   7.248+Node*	nod32const(vlong);
   7.249+Node*	nodfconst(double);
   7.250+void	nodreg(Node*, Node*, int);
   7.251+void	regret(Node*, Node*);
   7.252+void	regalloc(Node*, Node*, Node*);
   7.253+void	regfree(Node*);
   7.254+void	regialloc(Node*, Node*, Node*);
   7.255+void	regsalloc(Node*, Node*);
   7.256+void	regaalloc1(Node*, Node*);
   7.257+void	regaalloc(Node*, Node*);
   7.258+void	regind(Node*, Node*);
   7.259+void	gprep(Node*, Node*);
   7.260+void	raddr(Node*, Prog*);
   7.261+void	naddr(Node*, Adr*);
   7.262+void	gmovm(Node*, Node*, int);
   7.263+void	gmove(Node*, Node*);
   7.264+void	gmover(Node*, Node*);
   7.265+void	gins(int a, Node*, Node*);
   7.266+void	gopcode(int, Node*, Node*, Node*);
   7.267+int	samaddr(Node*, Node*);
   7.268+void	gbranch(int);
   7.269+void	patch(Prog*, long);
   7.270+int	sconst(Node*);
   7.271+int	sval(long);
   7.272+void	gpseudo(int, Sym*, Node*);
   7.273+int	usableoffset(Node*, vlong, Node*);
   7.274+
   7.275+/*
   7.276+ * swt.c
   7.277+ */
   7.278+int	swcmp(void*, void*);
   7.279+void	doswit(Node*);
   7.280+void	swit1(C1*, int, long, Node*);
   7.281+void	swit2(C1*, int, long, Node*, Node*);
   7.282+void	casf(void);
   7.283+void	bitload(Node*, Node*, Node*, Node*, Node*);
   7.284+void	bitstore(Node*, Node*, Node*, Node*, Node*);
   7.285+long	outstring(char*, long);
   7.286+int	mulcon(Node*, Node*);
   7.287+Multab*	mulcon0(long);
   7.288+void	nullwarn(Node*, Node*);
   7.289+void	gextern(Sym*, Node*, long, long);
   7.290+void	outcode(void);
   7.291+void	ieeedtod(Ieee*, double);
   7.292+
   7.293+/*
   7.294+ * list
   7.295+ */
   7.296+void	listinit(void);
   7.297+int	Pconv(Fmt*);
   7.298+int	Aconv(Fmt*);
   7.299+int	Dconv(Fmt*);
   7.300+int	Sconv(Fmt*);
   7.301+int	Nconv(Fmt*);
   7.302+int	Bconv(Fmt*);
   7.303+int	Rconv(Fmt*);
   7.304+
   7.305+/*
   7.306+ * reg.c
   7.307+ */
   7.308+Reg*	rega(void);
   7.309+int	rcmp(void*, void*);
   7.310+void	regopt(Prog*);
   7.311+void	addmove(Reg*, int, int, int);
   7.312+Bits	mkvar(Adr*, int);
   7.313+void	prop(Reg*, Bits, Bits);
   7.314+void	loopit(Reg*, long);
   7.315+void	synch(Reg*, Bits);
   7.316+ulong	allreg(ulong, Rgn*);
   7.317+void	paint1(Reg*, int);
   7.318+ulong	paint2(Reg*, int);
   7.319+void	paint3(Reg*, int, long, int);
   7.320+void	addreg(Adr*, int);
   7.321+
   7.322+/*
   7.323+ * peep.c
   7.324+ */
   7.325+void	peep(void);
   7.326+void	excise(Reg*);
   7.327+Reg*	uniqp(Reg*);
   7.328+Reg*	uniqs(Reg*);
   7.329+int	regtyp(Adr*);
   7.330+int	regzer(Adr*);
   7.331+int	anyvar(Adr*);
   7.332+int	subprop(Reg*);
   7.333+int	copyprop(Reg*);
   7.334+int	shiftprop(Reg*);
   7.335+void	constprop(Adr*, Adr*, Reg*);
   7.336+int	copy1(Adr*, Adr*, Reg*, int);
   7.337+int	copyu(Prog*, Adr*, Adr*);
   7.338+
   7.339+int	copyas(Adr*, Adr*);
   7.340+int	copyau(Adr*, Adr*);
   7.341+int	copyau1(Prog*, Adr*);
   7.342+int	copysub(Adr*, Adr*, Adr*, int);
   7.343+int	copysub1(Prog*, Adr*, Adr*, int);
   7.344+
   7.345+long	RtoB(int);
   7.346+long	FtoB(int);
   7.347+int	BtoR(long);
   7.348+int	BtoF(long);
   7.349+
   7.350+void	predicate(void); 
   7.351+int	isbranch(Prog *); 
   7.352+int	predicable(Prog *p); 
   7.353+int	modifiescpsr(Prog *p); 
   7.354+
   7.355+#pragma	varargck	type	"A"	int
   7.356+#pragma	varargck	type	"A"	uint
   7.357+#pragma	varargck	type	"B"	Bits
   7.358+#pragma	varargck	type	"D"	Adr*
   7.359+#pragma	varargck	type	"N"	Adr*
   7.360+#pragma	varargck	type	"R"	Adr*
   7.361+#pragma	varargck	type	"P"	Prog*
   7.362+#pragma	varargck	type	"S"	char*
     8.1new file mode 100644
     8.2--- /dev/null
     8.3+++ b/sys/src/cmd/7c/list.c
     8.4@@ -0,0 +1,329 @@
     8.5+#define	EXTERN
     8.6+#include "gc.h"
     8.7+
     8.8+void
     8.9+listinit(void)
    8.10+{
    8.11+
    8.12+	fmtinstall('A', Aconv);
    8.13+	fmtinstall('P', Pconv);
    8.14+	fmtinstall('S', Sconv);
    8.15+	fmtinstall('N', Nconv);
    8.16+	fmtinstall('B', Bconv);
    8.17+	fmtinstall('D', Dconv);
    8.18+	fmtinstall('R', Rconv);
    8.19+}
    8.20+
    8.21+int
    8.22+Bconv(Fmt *fp)
    8.23+{
    8.24+	char str[STRINGSZ], ss[STRINGSZ], *s;
    8.25+	Bits bits;
    8.26+	int i;
    8.27+
    8.28+	str[0] = 0;
    8.29+	bits = va_arg(fp->args, Bits);
    8.30+	while(bany(&bits)) {
    8.31+		i = bnum(bits);
    8.32+		if(str[0])
    8.33+			strcat(str, " ");
    8.34+		if(var[i].sym == S) {
    8.35+			snprint(ss, sizeof(ss), "$%lld", var[i].offset);
    8.36+			s = ss;
    8.37+		} else
    8.38+			s = var[i].sym->name;
    8.39+		if(strlen(str) + strlen(s) + 1 >= STRINGSZ)
    8.40+			break;
    8.41+		strcat(str, s);
    8.42+		bits.b[i/32] &= ~(1L << (i%32));
    8.43+	}
    8.44+	return fmtstrcpy(fp, str);
    8.45+}
    8.46+
    8.47+static char *conds[] = {
    8.48+	".EQ", ".NE", ".CS", ".CC", 
    8.49+	".MI", ".PL", ".VS", ".VC", 
    8.50+	".HI", ".LS", ".GE", ".LT", 
    8.51+	".GT", ".LE", "", ".NV",
    8.52+};
    8.53+
    8.54+int
    8.55+Pconv(Fmt *fp)
    8.56+{
    8.57+	char str[STRINGSZ];
    8.58+	Prog *p;
    8.59+	int a;
    8.60+
    8.61+	p = va_arg(fp->args, Prog*);
    8.62+	a = p->as;
    8.63+	if(a == ADATA)
    8.64+		snprint(str, sizeof(str), "	%A	%D/%d,%D", a, &p->from, p->reg, &p->to);
    8.65+	else
    8.66+	if(p->as == ATEXT)
    8.67+		snprint(str, sizeof(str), "	%A	%D,%d,%D", a, &p->from, p->reg, &p->to);
    8.68+	else
    8.69+	if(p->reg == NREG)
    8.70+		snprint(str, sizeof(str), "	%A	%D,%D", a, &p->from, &p->to);
    8.71+	else
    8.72+	if(p->from.type != D_FREG)
    8.73+		snprint(str, sizeof(str), "	%A	%D,R%d,%D", a, &p->from, p->reg, &p->to);
    8.74+	else
    8.75+		snprint(str, sizeof(str), "	%A	%D,F%d,%D", a, &p->from, p->reg, &p->to);
    8.76+	return fmtstrcpy(fp, str);
    8.77+}
    8.78+
    8.79+int
    8.80+Aconv(Fmt *fp)
    8.81+{
    8.82+	char *s;
    8.83+	int a;
    8.84+
    8.85+	a = va_arg(fp->args, int);
    8.86+	s = "???";
    8.87+	if(a >= AXXX && a < ALAST)
    8.88+		s = anames[a];
    8.89+	return fmtstrcpy(fp, s);
    8.90+}
    8.91+
    8.92+int
    8.93+Dconv(Fmt *fp)
    8.94+{
    8.95+	char str[STRINGSZ];
    8.96+	Adr *a;
    8.97+	char *op;
    8.98+	int v;
    8.99+	static char *extop[] = {".UB", ".UH", ".UW", ".UX", ".SB", ".SH", ".SW", ".SX"};
   8.100+
   8.101+	a = va_arg(fp->args, Adr*);
   8.102+	switch(a->type) {
   8.103+
   8.104+	default:
   8.105+		snprint(str, sizeof(str), "GOK-type(%d)", a->type);
   8.106+		break;
   8.107+
   8.108+	case D_NONE:
   8.109+		str[0] = 0;
   8.110+		if(a->name != D_NONE || a->reg != NREG || a->sym != S)
   8.111+			snprint(str, sizeof(str), "%N(R%d)(NONE)", a, a->reg);
   8.112+		break;
   8.113+
   8.114+	case D_CONST:
   8.115+		if(a->reg != NREG)
   8.116+			snprint(str, sizeof(str), "$%N(R%d)", a, a->reg);
   8.117+		else
   8.118+			snprint(str, sizeof(str), "$%N", a);
   8.119+		break;
   8.120+
   8.121+	case D_SHIFT:
   8.122+		v = a->offset;
   8.123+		op = "<<>>->@>" + (((v>>5) & 3) << 1);
   8.124+		if(v & (1<<4))
   8.125+			snprint(str, sizeof(str), "R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15);
   8.126+		else
   8.127+			snprint(str, sizeof(str), "R%d%c%c%d", v&15, op[0], op[1], (v>>7)&31);
   8.128+		if(a->reg != NREG)
   8.129+			sprint(str+strlen(str), "(R%d)", a->reg);
   8.130+		break;
   8.131+
   8.132+	case D_OREG:
   8.133+		if(a->reg != NREG)
   8.134+			snprint(str, sizeof(str), "%N(R%d)", a, a->reg);
   8.135+		else
   8.136+			snprint(str, sizeof(str), "%N", a);
   8.137+		break;
   8.138+
   8.139+	case D_XPRE:
   8.140+		if(a->reg != NREG)
   8.141+			snprint(str, sizeof(str), "%N(R%d)!", a, a->reg);
   8.142+		else
   8.143+			snprint(str, sizeof(str), "%N!", a);
   8.144+		break;
   8.145+
   8.146+	case D_XPOST:
   8.147+		if(a->reg != NREG)
   8.148+			snprint(str, sizeof(str), "(R%d)%N!", a->reg, a);
   8.149+		else
   8.150+			snprint(str, sizeof(str), "%N!", a);
   8.151+		break;
   8.152+
   8.153+	case D_EXTREG:
   8.154+		v = a->offset;
   8.155+		if(v & (7<<10))
   8.156+			snprint(str, sizeof(str), "R%d%s<<%d", (v>>16)&31, extop[(v>>13)&7], (v>>10)&7);
   8.157+		else
   8.158+			snprint(str, sizeof(str), "R%d%s", (v>>16)&31, extop[(v>>13)&7]);
   8.159+		break;
   8.160+
   8.161+	case D_REG:
   8.162+		snprint(str, sizeof(str), "R%d", a->reg);
   8.163+		if(a->name != D_NONE || a->sym != S)
   8.164+			snprint(str, sizeof(str), "%N(R%d)(REG)", a, a->reg);
   8.165+		break;
   8.166+
   8.167+	case D_SP:
   8.168+		if(a->name != D_NONE || a->sym != S)
   8.169+			snprint(str, sizeof(str), "%N(R%d)(REG)", a, a->reg);
   8.170+		else
   8.171+			strcpy(str, "SP");
   8.172+		break;
   8.173+
   8.174+	case D_FREG:
   8.175+		snprint(str, sizeof(str), "F%d", a->reg);
   8.176+		if(a->name != D_NONE || a->sym != S)
   8.177+			snprint(str, sizeof(str), "%N(R%d)(REG)", a, a->reg);
   8.178+		break;
   8.179+
   8.180+
   8.181+	case D_SPR:
   8.182+		switch((ulong)a->offset){
   8.183+		case D_FPSR:
   8.184+			sprint(str, "FPSR");
   8.185+			break;
   8.186+		case D_FPCR:
   8.187+			sprint(str, "FPCR");
   8.188+			break;
   8.189+		case D_NZCV:
   8.190+			sprint(str, "NZCV");
   8.191+			break;
   8.192+		default:
   8.193+			sprint(str, "SPR(%#llux)", a->offset);
   8.194+			break;
   8.195+		}
   8.196+		if(a->name != D_NONE || a->sym != S)
   8.197+			snprint(str, sizeof(str), "%N(SPR(%lld))(REG)", a, a->offset);
   8.198+		break;
   8.199+
   8.200+	case D_BRANCH:
   8.201+		snprint(str, sizeof(str), "%lld(PC)", a->offset-pc);
   8.202+		break;
   8.203+
   8.204+	case D_FCONST:
   8.205+		snprint(str, sizeof(str), "$%.17e", a->dval);
   8.206+		break;
   8.207+
   8.208+	case D_SCONST:
   8.209+		snprint(str, sizeof(str), "$\"%S\"", a->sval);
   8.210+		break;
   8.211+	}
   8.212+	return fmtstrcpy(fp, str);
   8.213+}
   8.214+
   8.215+int
   8.216+Rconv(Fmt *fp)
   8.217+{
   8.218+	char str[STRINGSZ], *p, *e;
   8.219+	Adr *a;
   8.220+	int i, v;
   8.221+
   8.222+	a = va_arg(fp->args, Adr*);
   8.223+	snprint(str, sizeof(str), "GOK-reglist");
   8.224+	switch(a->type) {
   8.225+	case D_CONST:
   8.226+		if(a->reg != NREG)
   8.227+			break;
   8.228+		if(a->sym != S)
   8.229+			break;
   8.230+		v = a->offset;
   8.231+		p = str;
   8.232+		e = str+sizeof(str);
   8.233+		for(i=0; i<NREG; i++) {
   8.234+			if(v & (1<<i)) {
   8.235+				if(p == str)
   8.236+					p = seprint(p, e, "[R%d", i);
   8.237+				else
   8.238+					p = seprint(p, e, ",R%d", i);
   8.239+			}
   8.240+		}
   8.241+		seprint(p, e, "]");
   8.242+	}
   8.243+	return fmtstrcpy(fp, str);
   8.244+}
   8.245+
   8.246+int
   8.247+Sconv(Fmt *fp)
   8.248+{
   8.249+	int i, c;
   8.250+	char str[STRINGSZ], *p, *a;
   8.251+
   8.252+	a = va_arg(fp->args, char*);
   8.253+	p = str;
   8.254+	for(i=0; i<NSNAME; i++) {
   8.255+		c = a[i] & 0xff;
   8.256+		if(c >= 'a' && c <= 'z' ||
   8.257+		   c >= 'A' && c <= 'Z' ||
   8.258+		   c >= '0' && c <= '9' ||
   8.259+		   c == ' ' || c == '%') {
   8.260+			*p++ = c;
   8.261+			continue;
   8.262+		}
   8.263+		*p++ = '\\';
   8.264+		switch(c) {
   8.265+		case 0:
   8.266+			*p++ = 'z';
   8.267+			continue;
   8.268+		case '\\':
   8.269+		case '"':
   8.270+			*p++ = c;
   8.271+			continue;
   8.272+		case '\n':
   8.273+			*p++ = 'n';
   8.274+			continue;
   8.275+		case '\t':
   8.276+			*p++ = 't';
   8.277+			continue;
   8.278+		case '\r':
   8.279+			*p++ = 'r';
   8.280+			continue;
   8.281+		case '\f':
   8.282+			*p++ = 'f';
   8.283+			continue;
   8.284+		}
   8.285+		*p++ = (c>>6) + '0';
   8.286+		*p++ = ((c>>3) & 7) + '0';
   8.287+		*p++ = (c & 7) + '0';
   8.288+	}
   8.289+	*p = 0;
   8.290+	return fmtstrcpy(fp, str);
   8.291+}
   8.292+
   8.293+int
   8.294+Nconv(Fmt *fp)
   8.295+{
   8.296+	char str[STRINGSZ];
   8.297+	Adr *a;
   8.298+	Sym *s;
   8.299+
   8.300+	a = va_arg(fp->args, Adr*);
   8.301+	s = a->sym;
   8.302+	if(s == S) {
   8.303+		snprint(str, sizeof(str), "%lld", a->offset);
   8.304+		goto out;
   8.305+	}
   8.306+	switch(a->name) {
   8.307+	default:
   8.308+		snprint(str, sizeof(str), "GOK-name(%d)", a->name);
   8.309+		break;
   8.310+
   8.311+	case D_NONE:
   8.312+		snprint(str, sizeof(str), "%lld", a->offset);
   8.313+		break;
   8.314+
   8.315+	case D_EXTERN:
   8.316+		snprint(str, sizeof(str), "%s+%lld(SB)", s->name, a->offset);
   8.317+		break;
   8.318+
   8.319+	case D_STATIC:
   8.320+		snprint(str, sizeof(str), "%s<>+%lld(SB)", s->name, a->offset);
   8.321+		break;
   8.322+
   8.323+	case D_AUTO:
   8.324+		snprint(str, sizeof(str), "%s-%lld(SP)", s->name, -a->offset);
   8.325+		break;
   8.326+
   8.327+	case D_PARAM:
   8.328+		snprint(str, sizeof(str), "%s+%lld(FP)", s->name, a->offset);
   8.329+		break;
   8.330+	}
   8.331+out:
   8.332+	return fmtstrcpy(fp, str);
   8.333+}
     9.1new file mode 100644
     9.2--- /dev/null
     9.3+++ b/sys/src/cmd/7c/machcap.c
     9.4@@ -0,0 +1,81 @@
     9.5+#include "gc.h"
     9.6+
     9.7+int
     9.8+machcap(Node *n)
     9.9+{
    9.10+
    9.11+	if(n == Z)
    9.12+		return 1;	/* test */
    9.13+
    9.14+	switch(n->op) {
    9.15+	case OMUL:
    9.16+	case OLMUL:
    9.17+	case OASMUL:
    9.18+	case OASLMUL:
    9.19+		if(typechlv[n->type->etype])
    9.20+			return 1;
    9.21+		break;
    9.22+
    9.23+	case OADD:
    9.24+	case OAND:
    9.25+	case OOR:
    9.26+	case OSUB:
    9.27+	case OXOR:
    9.28+	case OASHL:
    9.29+	case OLSHR:
    9.30+	case OASHR:
    9.31+		if(typechlv[n->left->type->etype])
    9.32+			return 1;
    9.33+		break;
    9.34+
    9.35+	case OCAST:
    9.36+		return 1;
    9.37+
    9.38+	case OCOND:
    9.39+	case OCOMMA:
    9.40+	case OLIST:
    9.41+	case OANDAND:
    9.42+	case OOROR:
    9.43+	case ONOT:
    9.44+		return 1;
    9.45+
    9.46+	case OASADD:
    9.47+	case OASSUB:
    9.48+	case OASAND:
    9.49+	case OASOR:
    9.50+	case OASXOR:
    9.51+		return 1;
    9.52+
    9.53+	case OASASHL:
    9.54+	case OASASHR:
    9.55+	case OASLSHR:
    9.56+		return 1;
    9.57+
    9.58+	case OPOSTINC:
    9.59+	case OPOSTDEC:
    9.60+	case OPREINC:
    9.61+	case OPREDEC:
    9.62+		return 1;
    9.63+
    9.64+	case OEQ:
    9.65+	case ONE:
    9.66+	case OLE:
    9.67+	case OGT:
    9.68+	case OLT:
    9.69+	case OGE:
    9.70+	case OHI:
    9.71+	case OHS:
    9.72+	case OLO:
    9.73+	case OLS:
    9.74+		return 1;
    9.75+
    9.76+	case ONEG:
    9.77+		if(typechlv[n->left->type->etype])
    9.78+			return 1;
    9.79+		break;
    9.80+
    9.81+	case OCOM:
    9.82+		break;
    9.83+	}
    9.84+	return 0;
    9.85+}
    10.1new file mode 100644
    10.2--- /dev/null
    10.3+++ b/sys/src/cmd/7c/mkenam
    10.4@@ -0,0 +1,15 @@
    10.5+ed - ../7c/7.out.h <<'!'
    10.6+v/^	A/d
    10.7+,s/^	A/	"/
    10.8+g/ .*$/s///
    10.9+,s/,*$/",/
   10.10+1i
   10.11+char*	anames[] =
   10.12+{
   10.13+.
   10.14+$a
   10.15+};
   10.16+.
   10.17+w enam.c
   10.18+Q
   10.19+!
    11.1new file mode 100644
    11.2--- /dev/null
    11.3+++ b/sys/src/cmd/7c/mkfile
    11.4@@ -0,0 +1,41 @@
    11.5+</$objtype/mkfile
    11.6+
    11.7+TARG=7c
    11.8+OFILES=\
    11.9+	cgen.$O\
   11.10+	enam.$O\
   11.11+	list.$O\
   11.12+	machcap.$O\
   11.13+	mul.$O\
   11.14+	peep.$O\
   11.15+	pgen.$O\
   11.16+	pswt.$O\
   11.17+	reg.$O\
   11.18+	sgen.$O\
   11.19+	swt.$O\
   11.20+	txt.$O\
   11.21+
   11.22+HFILES=\
   11.23+	gc.h\
   11.24+	7.out.h\
   11.25+	../cc/cc.h\
   11.26+
   11.27+LIB=../cc/cc.a$O
   11.28+
   11.29+BIN=/$objtype/bin
   11.30+</sys/src/cmd/mkone
   11.31+
   11.32+$LIB:	../cc/cc.h
   11.33+	cd ../cc
   11.34+	mk install
   11.35+
   11.36+%.$O: ../cc/%.c
   11.37+	$CC $CFLAGS ../cc/$stem.c
   11.38+
   11.39+t:V:	$O.out
   11.40+	$O.out -S t
   11.41+	$LD -o t.out t.$O
   11.42+	t.out
   11.43+
   11.44+enam.c: 7.out.h
   11.45+	rc mkenam
    12.1new file mode 100644
    12.2--- /dev/null
    12.3+++ b/sys/src/cmd/7c/mul.c
    12.4@@ -0,0 +1,609 @@
    12.5+#include "gc.h"
    12.6+
    12.7+/*
    12.8+ * code sequences for multiply by constant.
    12.9+ * [a-l][0-3]
   12.10+ *	lsl	$(A-'a'),r0,r1
   12.11+ * [+][0-7]
   12.12+ *	add	r0,r1,r2
   12.13+ * [-][0-7]
   12.14+ *	sub	r0,r1,r2
   12.15+ */
   12.16+
   12.17+static  int	maxmulops = 3;	/* max # of ops to replace mul with */
   12.18+static	int	multabp;
   12.19+static	long	mulval;
   12.20+static	char*	mulcp;
   12.21+static	long	valmax;
   12.22+static	int	shmax;
   12.23+
   12.24+static int	docode(char *hp, char *cp, int r0, int r1);
   12.25+static int	gen1(int len);
   12.26+static int	gen2(int len, long r1);
   12.27+static int	gen3(int len, long r0, long r1, int flag);
   12.28+enum
   12.29+{
   12.30+	SR1	= 1<<0,		/* r1 has been shifted */
   12.31+	SR0	= 1<<1,		/* r0 has been shifted */
   12.32+	UR1	= 1<<2,		/* r1 has not been used */
   12.33+	UR0	= 1<<3,		/* r0 has not been used */
   12.34+};
   12.35+
   12.36+Multab*
   12.37+mulcon0(long v)
   12.38+{
   12.39+	int a1, a2, g;
   12.40+	Multab *m, *m1;
   12.41+	char hint[10];
   12.42+
   12.43+	if(v < 0)
   12.44+		v = -v;
   12.45+
   12.46+	/*
   12.47+	 * look in cache
   12.48+	 */
   12.49+	m = multab;
   12.50+	for(g=0; g<nelem(multab); g++) {
   12.51+		if(m->val == v) {
   12.52+			if(m->code[0] == 0)
   12.53+				return 0;
   12.54+			return m;
   12.55+		}
   12.56+		m++;
   12.57+	}
   12.58+
   12.59+	/*
   12.60+	 * select a spot in cache to overwrite
   12.61+	 */
   12.62+	multabp++;
   12.63+	if(multabp < 0 || multabp >= nelem(multab))
   12.64+		multabp = 0;
   12.65+	m = multab+multabp;
   12.66+	m->val = v;
   12.67+	mulval = v;
   12.68+
   12.69+	/*
   12.70+	 * look in execption hint table
   12.71+	 */
   12.72+	a1 = 0;
   12.73+	a2 = hintabsize;
   12.74+	for(;;) {
   12.75+		if(a1 >= a2)
   12.76+			goto no;
   12.77+		g = (a2 + a1)/2;
   12.78+		if(v < hintab[g].val) {
   12.79+			a2 = g;
   12.80+			continue;
   12.81+		}
   12.82+		if(v > hintab[g].val) {
   12.83+			a1 = g+1;
   12.84+			continue;
   12.85+		}
   12.86+		break;
   12.87+	}
   12.88+
   12.89+	if(docode(hintab[g].hint, m->code, 1, 0))
   12.90+		return m;
   12.91+	print("multiply table failure %ld\n", v);
   12.92+	m->code[0] = 0;
   12.93+	return 0;
   12.94+
   12.95+no:
   12.96+	/*
   12.97+	 * try to search
   12.98+	 */
   12.99+	hint[0] = 0;
  12.100+	for(g=1; g<=maxmulops; g++) {
  12.101+		if(g >= maxmulops && v >= 65535)
  12.102+			break;
  12.103+		mulcp = hint+g;
  12.104+		*mulcp = 0;
  12.105+		if(gen1(g)) {
  12.106+			if(docode(hint, m->code, 1, 0))
  12.107+				return m;
  12.108+			print("multiply table failure %ld\n", v);
  12.109+			break;
  12.110+		}
  12.111+	}
  12.112+
  12.113+	/*
  12.114+	 * try a recur followed by a shift
  12.115+	 */
  12.116+	g = 0;
  12.117+	while(!(v & 1)) {
  12.118+		g++;
  12.119+		v >>= 1;
  12.120+	}
  12.121+	if(g) {
  12.122+		m1 = mulcon0(v);
  12.123+		if(m1) {
  12.124+			strcpy(m->code, m1->code);
  12.125+			sprint(strchr(m->code, 0), "%c0", g+'a');
  12.126+			return m;
  12.127+		}
  12.128+	}
  12.129+	m->code[0] = 0;
  12.130+	return 0;
  12.131+}
  12.132+
  12.133+static int
  12.134+docode(char *hp, char *cp, int r0, int r1)
  12.135+{
  12.136+	int c, i;
  12.137+
  12.138+	c = *hp++;
  12.139+	*cp = c;
  12.140+	cp += 2;
  12.141+	switch(c) {
  12.142+	default:
  12.143+		c -= 'a';
  12.144+		if(c < 1 || c >= 30)
  12.145+			break;
  12.146+		for(i=0; i<4; i++) {
  12.147+			switch(i) {
  12.148+			case 0:
  12.149+				if(docode(hp, cp, r0<<c, r1))
  12.150+					goto out;
  12.151+				break;
  12.152+			case 1:
  12.153+				if(docode(hp, cp, r1<<c, r1))
  12.154+					goto out;
  12.155+				break;
  12.156+			case 2:
  12.157+				if(docode(hp, cp, r0, r0<<c))
  12.158+					goto out;
  12.159+				break;
  12.160+			case 3:
  12.161+				if(docode(hp, cp, r0, r1<<c))
  12.162+					goto out;
  12.163+				break;
  12.164+			}
  12.165+		}
  12.166+		break;
  12.167+
  12.168+	case '+':
  12.169+		for(i=0; i<8; i++) {
  12.170+			cp[-1] = i+'0';
  12.171+			switch(i) {
  12.172+			case 1:
  12.173+				if(docode(hp, cp, r0+r1, r1))
  12.174+					goto out;
  12.175+				break;
  12.176+			case 5:
  12.177+				if(docode(hp, cp, r0, r0+r1))
  12.178+					goto out;
  12.179+				break;
  12.180+			}
  12.181+		}
  12.182+		break;
  12.183+
  12.184+	case '-':
  12.185+		for(i=0; i<8; i++) {
  12.186+			cp[-1] = i+'0';
  12.187+			switch(i) {
  12.188+			case 1:
  12.189+				if(docode(hp, cp, r0-r1, r1))
  12.190+					goto out;
  12.191+				break;
  12.192+			case 2:
  12.193+				if(docode(hp, cp, r1-r0, r1))
  12.194+					goto out;
  12.195+				break;
  12.196+			case 5:
  12.197+				if(docode(hp, cp, r0, r0-r1))
  12.198+					goto out;
  12.199+				break;
  12.200+			case 6:
  12.201+				if(docode(hp, cp, r0, r1-r0))
  12.202+					goto out;
  12.203+				break;
  12.204+			}
  12.205+		}
  12.206+		break;
  12.207+
  12.208+	case 0:
  12.209+		if(r0 == mulval)
  12.210+			return 1;
  12.211+	}
  12.212+	return 0;
  12.213+
  12.214+out:
  12.215+	cp[-1] = i+'0';
  12.216+	return 1;
  12.217+}
  12.218+
  12.219+static int
  12.220+gen1(int len)
  12.221+{
  12.222+	int i;
  12.223+
  12.224+	for(shmax=1; shmax<30; shmax++) {
  12.225+		valmax = 1<<shmax;
  12.226+		if(valmax >= mulval)
  12.227+			break;
  12.228+	}
  12.229+	if(mulval == 1)
  12.230+		return 1;
  12.231+
  12.232+	len--;
  12.233+	for(i=1; i<=shmax; i++)
  12.234+		if(gen2(len, 1<<i)) {
  12.235+			*--mulcp = 'a'+i;
  12.236+			return 1;
  12.237+		}
  12.238+	return 0;
  12.239+}
  12.240+
  12.241+static int
  12.242+gen2(int len, long r1)
  12.243+{
  12.244+	int i;
  12.245+
  12.246+	if(len <= 0) {
  12.247+		if(r1 == mulval)
  12.248+			return 1;
  12.249+		return 0;
  12.250+	}
  12.251+
  12.252+	len--;
  12.253+	if(len == 0)
  12.254+		goto calcr0;
  12.255+
  12.256+	if(gen3(len, r1, r1+1, UR1)) {
  12.257+		i = '+';
  12.258+		goto out;
  12.259+	}
  12.260+	if(gen3(len, r1-1, r1, UR0)) {
  12.261+		i = '-';
  12.262+		goto out;
  12.263+	}
  12.264+	if(gen3(len, 1, r1+1, UR1)) {
  12.265+		i = '+';
  12.266+		goto out;
  12.267+	}
  12.268+	if(gen3(len, 1, r1-1, UR1)) {
  12.269+		i = '-';
  12.270+		goto out;
  12.271+	}
  12.272+
  12.273+	return 0;
  12.274+
  12.275+calcr0:
  12.276+	if(mulval == r1+1) {
  12.277+		i = '+';
  12.278+		goto out;
  12.279+	}
  12.280+	if(mulval == r1-1) {
  12.281+		i = '-';
  12.282+		goto out;
  12.283+	}
  12.284+	return 0;
  12.285+
  12.286+out:
  12.287+	*--mulcp = i;
  12.288+	return 1;
  12.289+}
  12.290+
  12.291+static int
  12.292+gen3(int len, long r0, long r1, int flag)
  12.293+{
  12.294+	int i, f1, f2;
  12.295+	long x;
  12.296+
  12.297+	if(r0 <= 0 ||
  12.298+	   r0 >= r1 ||
  12.299+	   r1 > valmax)
  12.300+		return 0;
  12.301+
  12.302+	len--;
  12.303+	if(len == 0)
  12.304+		goto calcr0;
  12.305+
  12.306+	if(!(flag & UR1)) {
  12.307+		f1 = UR1|SR1;
  12.308+		for(i=1; i<=shmax; i++) {
  12.309+			x = r0<<i;
  12.310+			if(x > valmax)
  12.311+				break;
  12.312+			if(gen3(len, r0, x, f1)) {
  12.313+				i += 'a';
  12.314+				goto out;
  12.315+			}
  12.316+		}
  12.317+	}
  12.318+
  12.319+	if(!(flag & UR0)) {
  12.320+		f1 = UR1|SR1;
  12.321+		for(i=1; i<=shmax; i++) {
  12.322+			x = r1<<i;
  12.323+			if(x > valmax)
  12.324+				break;
  12.325+			if(gen3(len, r1, x, f1)) {
  12.326+				i += 'a';
  12.327+				goto out;
  12.328+			}
  12.329+		}
  12.330+	}
  12.331+
  12.332+	if(!(flag & SR1)) {
  12.333+		f1 = UR1|SR1|(flag&UR0);
  12.334+		for(i=1; i<=shmax; i++) {
  12.335+			x = r1<<i;
  12.336+			if(x > valmax)
  12.337+				break;
  12.338+			if(gen3(len, r0, x, f1)) {
  12.339+				i += 'a';
  12.340+				goto out;
  12.341+			}
  12.342+		}
  12.343+	}
  12.344+
  12.345+	if(!(flag & SR0)) {
  12.346+		f1 = UR0|SR0|(flag&(SR1|UR1));
  12.347+
  12.348+		f2 = UR1|SR1;
  12.349+		if(flag & UR1)
  12.350+			f2 |= UR0;
  12.351+		if(flag & SR1)
  12.352+			f2 |= SR0;
  12.353+
  12.354+		for(i=1; i<=shmax; i++) {
  12.355+			x = r0<<i;
  12.356+			if(x > valmax)
  12.357+				break;
  12.358+			if(x > r1) {
  12.359+				if(gen3(len, r1, x, f2)) {
  12.360+					i += 'a';
  12.361+					goto out;
  12.362+				}
  12.363+			} else
  12.364+				if(gen3(len, x, r1, f1)) {
  12.365+					i += 'a';
  12.366+					goto out;
  12.367+				}
  12.368+		}
  12.369+	}
  12.370+
  12.371+	x = r1+r0;
  12.372+	if(gen3(len, r0, x, UR1)) {
  12.373+		i = '+';
  12.374+		goto out;
  12.375+	}
  12.376+
  12.377+	if(gen3(len, r1, x, UR1)) {
  12.378+		i = '+';
  12.379+		goto out;
  12.380+	}
  12.381+
  12.382+	x = r1-r0;
  12.383+	if(gen3(len, x, r1, UR0)) {
  12.384+		i = '-';
  12.385+		goto out;
  12.386+	}
  12.387+
  12.388+	if(x > r0) {
  12.389+		if(gen3(len, r0, x, UR1)) {
  12.390+			i = '-';
  12.391+			goto out;
  12.392+		}
  12.393+	} else
  12.394+		if(gen3(len, x, r0, UR0)) {
  12.395+			i = '-';
  12.396+			goto out;
  12.397+		}
  12.398+
  12.399+	return 0;
  12.400+
  12.401+calcr0:
  12.402+	f1 = flag & (UR0|UR1);
  12.403+	if(f1 == UR1) {
  12.404+		for(i=1; i<=shmax; i++) {
  12.405+			x = r1<<i;
  12.406+			if(x >= mulval) {
  12.407+				if(x == mulval) {
  12.408+					i += 'a';
  12.409+					goto out;
  12.410+				}
  12.411+				break;
  12.412+			}
  12.413+		}
  12.414+	}
  12.415+
  12.416+	if(mulval == r1+r0) {
  12.417+		i = '+';
  12.418+		goto out;
  12.419+	}
  12.420+	if(mulval == r1-r0) {
  12.421+		i = '-';
  12.422+		goto out;
  12.423+	}
  12.424+
  12.425+	return 0;
  12.426+
  12.427+out:
  12.428+	*--mulcp = i;
  12.429+	return 1;
  12.430+}
  12.431+
  12.432+/*
  12.433+ * hint table has numbers that
  12.434+ * the search algorithm fails on.
  12.435+ * <1000:
  12.436+ *	all numbers
  12.437+ * <5000:
  12.438+ * 	÷ by 5
  12.439+ * <10000:
  12.440+ * 	÷ by 50
  12.441+ * <65536:
  12.442+ * 	÷ by 250
  12.443+ */
  12.444+Hintab	hintab[] =
  12.445+{
  12.446+	683,	"b++d+e+",
  12.447+	687,	"b+e++e-",
  12.448+	691,	"b++d+e+",
  12.449+	731,	"b++d+e+",
  12.450+	811,	"b++d+i+",
  12.451+	821,	"b++e+e+",
  12.452+	843,	"b+d++e+",
  12.453+	851,	"b+f-+e-",
  12.454+	853,	"b++e+e+",
  12.455+	877,	"c++++g-",
  12.456+	933,	"b+c++g-",
  12.457+	981,	"c-+e-d+",
  12.458+	1375,	"b+c+b+h-",
  12.459+	1675,	"d+b++h+",
  12.460+	2425,	"c++f-e+",
  12.461+	2675,	"c+d++f-",
  12.462+	2750,	"b+d-b+h-",
  12.463+	2775,	"c-+g-e-",
  12.464+	3125,	"b++e+g+",
  12.465+	3275,	"b+c+g+e+",
  12.466+	3350,	"c++++i+",
  12.467+	3475,	"c-+e-f-",
  12.468+	3525,	"c-+d+g-",
  12.469+	3625,	"c-+e-j+",
  12.470+	3675,	"b+d+d+e+",
  12.471+	3725,	"b+d-+h+",
  12.472+	3925,	"b+d+f-d-",
  12.473+	4275,	"b+g++e+",
  12.474+	4325,	"b+h-+d+",
  12.475+	4425,	"b+b+g-j-",
  12.476+	4525,	"b+d-d+f+",
  12.477+	4675,	"c++d-g+",
  12.478+	4775,	"b+d+b+g-",
  12.479+	4825,	"c+c-+i-",
  12.480+	4850,	"c++++i-",
  12.481+	4925,	"b++e-g-",
  12.482+	4975,	"c+f++e-",
  12.483+	5500,	"b+g-c+d+",
  12.484+	6700,	"d+b++i+",
  12.485+	9700,	"d++++j-",
  12.486+	11000,	"b+f-c-h-",
  12.487+	11750,	"b+d+g+j-",
  12.488+	12500,	"b+c+e-k+",
  12.489+	13250,	"b+d+e-f+",
  12.490+	13750,	"b+h-c-d+",
  12.491+	14250,	"b+g-c+e-",
  12.492+	14500,	"c+f+j-d-",
  12.493+	14750,	"d-g--f+",
  12.494+	16750,	"b+e-d-n+",
  12.495+	17750,	"c+h-b+e+",
  12.496+	18250,	"d+b+h-d+",
  12.497+	18750,	"b+g-++f+",
  12.498+	19250,	"b+e+b+h+",
  12.499+	19750,	"b++h--f-",
  12.500+	20250,	"b+e-l-c+",
  12.501+	20750,	"c++bi+e-",
  12.502+	21250,	"b+i+l+c+",
  12.503+	22000,	"b+e+d-g-",
  12.504+	22250,	"b+d-h+k-",
  12.505+	22750,	"b+d-e-g+",
  12.506+	23250,	"b+c+h+e-",
  12.507+	23500,	"b+g-c-g-",
  12.508+	23750,	"b+g-b+h-",
  12.509+	24250,	"c++g+m-",
  12.510+	24750,	"b+e+e+j-",
  12.511+	25000,	"b++dh+g+",
  12.512+	25250,	"b+e+d-g-",
  12.513+	25750,	"b+e+b+j+",
  12.514+	26250,	"b+h+c+e+",
  12.515+	26500,	"b+h+c+g+",
  12.516+	26750,	"b+d+e+g-",
  12.517+	27250,	"b+e+e+f+",
  12.518+	27500,	"c-i-c-d+",
  12.519+	27750,	"b+bd++j+",
  12.520+	28250,	"d-d-++i-",
  12.521+	28500,	"c+c-h-e-",
  12.522+	29000,	"b+g-d-f+",
  12.523+	29500,	"c+h+++e-",
  12.524+	29750,	"b+g+f-c+",
  12.525+	30250,	"b+f-g-c+",
  12.526+	33500,	"c-f-d-n+",
  12.527+	33750,	"b+d-b+j-",
  12.528+	34250,	"c+e+++i+",
  12.529+	35250,	"e+b+d+k+",
  12.530+	35500,	"c+e+d-g-",
  12.531+	35750,	"c+i-++e+",
  12.532+	36250,	"b+bh-d+e+",
  12.533+	36500,	"c+c-h-e-",
  12.534+	36750,	"d+e--i+",
  12.535+	37250,	"b+g+g+b+",
  12.536+	37500,	"b+h-b+f+",
  12.537+	37750,	"c+be++j-",
  12.538+	38500,	"b+e+b+i+",
  12.539+	38750,	"d+i-b+d+",
  12.540+	39250,	"b+g-l-+d+",
  12.541+	39500,	"b+g-c+g-",
  12.542+	39750,	"b+bh-c+f-",
  12.543+	40250,	"b+bf+d+g-",
  12.544+	40500,	"b+g-c+g+",
  12.545+	40750,	"c+b+i-e+",
  12.546+	41250,	"d++bf+h+",
  12.547+	41500,	"b+j+c+d-",
  12.548+	41750,	"c+f+b+h-",
  12.549+	42500,	"c+h++g+",
  12.550+	42750,	"b+g+d-f-",
  12.551+	43250,	"b+l-e+d-",
  12.552+	43750,	"c+bd+h+f-",
  12.553+	44000,	"b+f+g-d-",
  12.554+	44250,	"b+d-g--f+",
  12.555+	44500,	"c+e+c+h+",
  12.556+	44750,	"b+e+d-h-",
  12.557+	45250,	"b++g+j-g+",
  12.558+	45500,	"c+d+e-g+",
  12.559+	45750,	"b+d-h-e-",
  12.560+	46250,	"c+bd++j+",
  12.561+	46500,	"b+d-c-j-",
  12.562+	46750,	"e-e-b+g-",
  12.563+	47000,	"b+c+d-j-",
  12.564+	47250,	"b+e+e-g-",
  12.565+	47500,	"b+g-c-h-",
  12.566+	47750,	"b+f-c+h-",
  12.567+	48250,	"d--h+n-",
  12.568+	48500,	"b+c-g+m-",
  12.569+	48750,	"b+e+e-g+",
  12.570+	49500,	"c-f+e+j-",
  12.571+	49750,	"c+c+g++f-",
  12.572+	50000,	"b+e+e+k+",
  12.573+	50250,	"b++i++g+",
  12.574+	50500,	"c+g+f-i+",
  12.575+	50750,	"b+e+d+k-",
  12.576+	51500,	"b+i+c-f+",
  12.577+	51750,	"b+bd+g-e-",
  12.578+	52250,	"b+d+g-j+",
  12.579+	52500,	"c+c+f+g+",
  12.580+	52750,	"b+c+e+i+",
  12.581+	53000,	"b+i+c+g+",
  12.582+	53500,	"c+g+g-n+",
  12.583+	53750,	"b+j+d-c+",
  12.584+	54250,	"b+d-g-j-",
  12.585+	54500,	"c-f+e+f+",
  12.586+	54750,	"b+f-+c+g+",
  12.587+	55000,	"b+g-d-g-",
  12.588+	55250,	"b+e+e+g+",
  12.589+	55500,	"b+cd++j+",
  12.590+	55750,	"b+bh-d-f-",
  12.591+	56250,	"c+d-b+j-",
  12.592+	56500,	"c+d+c+i+",
  12.593+	56750,	"b+e+d++h-",
  12.594+	57000,	"b+d+g-f+",
  12.595+	57250,	"b+f-m+d-",
  12.596+	57750,	"b+i+c+e-",
  12.597+	58000,	"b+e+d+h+",
  12.598+	58250,	"c+b+g+g+",
  12.599+	58750,	"d-e-j--e+",
  12.600+	59000,	"d-i-+e+",
  12.601+	59250,	"e--h-m+",
  12.602+	59500,	"c+c-h+f-",
  12.603+	59750,	"b+bh-e+i-",
  12.604+	60250,	"b+bh-e-e-",
  12.605+	60500,	"c+c-g-g-",
  12.606+	60750,	"b+e-l-e-",
  12.607+	61250,	"b+g-g-c+",
  12.608+	61750,	"b+g-c+g+",
  12.609+	62250,	"f--+c-i-",
  12.610+	62750,	"e+f--+g+",
  12.611+	64750,	"b+f+d+p-",
  12.612+};
  12.613+int	hintabsize	= nelem(hintab);
    13.1new file mode 100644
    13.2--- /dev/null
    13.3+++ b/sys/src/cmd/7c/peep.c
    13.4@@ -0,0 +1,1546 @@
    13.5+#include "gc.h"
    13.6+
    13.7+int xtramodes(Reg*, Adr*);
    13.8+
    13.9+void
   13.10+peep(void)
   13.11+{
   13.12+	Reg *r, *r1, *r2;
   13.13+	Prog *p, *p1;
   13.14+	int t;
   13.15+/*
   13.16+ * complete R structure
   13.17+ */
   13.18+	t = 0;
   13.19+	for(r=firstr; r!=R; r=r1) {
   13.20+		r1 = r->link;
   13.21+		if(r1 == R)
   13.22+			break;
   13.23+		p = r->prog->link;
   13.24+		while(p != r1->prog)
   13.25+		switch(p->as) {
   13.26+		default:
   13.27+			r2 = rega();
   13.28+			r->link = r2;
   13.29+			r2->link = r1;
   13.30+
   13.31+			r2->prog = p;
   13.32+			r2->p1 = r;
   13.33+			r->s1 = r2;
   13.34+			r2->s1 = r1;
   13.35+			r1->p1 = r2;
   13.36+
   13.37+			r = r2;
   13.38+			t++;
   13.39+
   13.40+		case ADATA:
   13.41+		case AGLOBL:
   13.42+		case ANAME:
   13.43+		case ASIGNAME:
   13.44+			p = p->link;
   13.45+		}
   13.46+	}
   13.47+
   13.48+loop1:
   13.49+	t = 0;
   13.50+	for(r=firstr; r!=R; r=r->link) {
   13.51+		p = r->prog;
   13.52+		if(p->as == ALSL || p->as == ALSR || p->as == AASR ||
   13.53+		   p->as == ALSLW || p->as == ALSRW || p->as == AASRW) {
   13.54+			/*
   13.55+			 * elide shift into D_SHIFT operand of subsequent instruction
   13.56+			 */
   13.57+			if(0 && shiftprop(r)) {
   13.58+				excise(r);
   13.59+				t++;
   13.60+			}
   13.61+		}
   13.62+		if(p->as == AMOV || p->as == AMOVW || p->as == AFMOVS || p->as == AFMOVD)
   13.63+		if(regtyp(&p->to)) {
   13.64+			if(p->from.type == D_CONST)
   13.65+				constprop(&p->from, &p->to, r->s1);
   13.66+			else if(regtyp(&p->from))
   13.67+			if(p->from.type == p->to.type) {
   13.68+				if(copyprop(r)) {
   13.69+					excise(r);
   13.70+					t++;
   13.71+				} else
   13.72+				if(subprop(r) && copyprop(r)) {
   13.73+					excise(r);
   13.74+					t++;
   13.75+				}
   13.76+			}
   13.77+			if(regzer(&p->from))
   13.78+			if(p->to.type == D_REG) {
   13.79+				p->from.type = D_REG;
   13.80+				p->from.reg = REGZERO;
   13.81+				if(copyprop(r)) {
   13.82+					excise(r);
   13.83+					t++;
   13.84+				} else
   13.85+				if(subprop(r) && copyprop(r)) {
   13.86+					excise(r);
   13.87+					t++;
   13.88+				}
   13.89+			}
   13.90+		}
   13.91+	}
   13.92+	if(t)
   13.93+		goto loop1;
   13.94+	/*
   13.95+	 * look for MOVB x,R; MOVB R,R
   13.96+	 */
   13.97+	for(r=firstr; r!=R; r=r->link) {
   13.98+		p = r->prog;
   13.99+		switch(p->as) {
  13.100+		default:
  13.101+			continue;
  13.102+		case AEOR:
  13.103+			/*
  13.104+			 * EOR -1,x,y => MVN x,y
  13.105+			 */
  13.106+			if(p->from.type == D_CONST && p->from.offset == -1) {
  13.107+				p->as = AMVN;
  13.108+				p->from.type = D_REG;
  13.109+				if(p->reg != NREG)
  13.110+					p->from.reg = p->reg;
  13.111+				else
  13.112+					p->from.reg = p->to.reg;
  13.113+				p->reg = NREG;
  13.114+			}
  13.115+			continue;
  13.116+		case AEORW:
  13.117+			/*
  13.118+			 * EOR -1,x,y => MVN x,y
  13.119+			 */
  13.120+			if(p->from.type == D_CONST && (p->from.offset&0xFFFFFFFF)==0xFFFFFFFF){
  13.121+				p->as = AMVNW;
  13.122+				p->from.type = D_REG;
  13.123+				if(p->reg != NREG)
  13.124+					p->from.reg = p->reg;
  13.125+				else
  13.126+					p->from.reg = p->to.reg;
  13.127+				p->reg = NREG;
  13.128+			}
  13.129+			continue;
  13.130+		case AMOVH:
  13.131+		case AMOVHU:
  13.132+		case AMOVB:
  13.133+		case AMOVBU:
  13.134+		case AMOVW:
  13.135+		case AMOVWU:
  13.136+			if(p->to.type != D_REG)
  13.137+				continue;
  13.138+			break;
  13.139+		}
  13.140+		r1 = r->link;
  13.141+		if(r1 == R)
  13.142+			continue;
  13.143+		p1 = r1->prog;
  13.144+		if(p1->as != p->as)
  13.145+			continue;
  13.146+		if(p1->from.type != D_REG || p1->from.reg != p->to.reg)
  13.147+			continue;
  13.148+		if(p1->to.type != D_REG || p1->to.reg != p->to.reg)
  13.149+			continue;
  13.150+		excise(r1);
  13.151+	}
  13.152+
  13.153+#ifdef NOTYET
  13.154+	for(r=firstr; r!=R; r=r->link) {
  13.155+		p = r->prog;
  13.156+		switch(p->as) {
  13.157+		case AMOVW:
  13.158+		case AMOVB:
  13.159+		case AMOVBU:
  13.160+			if(p->from.type == D_OREG && p->from.offset == 0)
  13.161+				xtramodes(r, &p->from);
  13.162+			else if(p->to.type == D_OREG && p->to.offset == 0)
  13.163+				xtramodes(r, &p->to);
  13.164+			else
  13.165+				continue;
  13.166+			break;
  13.167+		case ACMP:
  13.168+			/*
  13.169+			 * elide CMP $0,x if calculation of x can set condition codes
  13.170+			 */
  13.171+			if(p->from.type != D_CONST || p->from.offset != 0)
  13.172+				continue;
  13.173+			r2 = r->s1;
  13.174+			if(r2 == R)
  13.175+				continue;
  13.176+			t = r2->prog->as;
  13.177+			switch(t) {
  13.178+			default:
  13.179+				continue;
  13.180+			case ABEQ:
  13.181+			case ABNE:
  13.182+			case ABMI:
  13.183+			case ABPL:
  13.184+				break;
  13.185+			case ABGE:
  13.186+				t = ABPL;
  13.187+				break;
  13.188+			case ABLT:
  13.189+				t = ABMI;
  13.190+				break;
  13.191+			case ABHI:
  13.192+				t = ABNE;
  13.193+				break;
  13.194+			case ABLS:
  13.195+				t = ABEQ;
  13.196+				break;
  13.197+			}
  13.198+			r1 = r;
  13.199+			do
  13.200+				r1 = uniqp(r1);
  13.201+			while (r1 != R && r1->prog->as == ANOP);
  13.202+			if(r1 == R)
  13.203+				continue;
  13.204+			p1 = r1->prog;
  13.205+			if(p1->to.type != D_REG)
  13.206+				continue;
  13.207+			if(p1->to.reg != p->reg)
  13.208+			if(!(p1->as == AMOVW && p1->from.type == D_REG && p1->from.reg == p->reg))
  13.209+				continue;
  13.210+			switch(p1->as) {
  13.211+			default:
  13.212+				continue;
  13.213+			case AMOVW:
  13.214+				if(p1->from.type != D_REG)
  13.215+					continue;
  13.216+			case AAND:
  13.217+			case AEOR:
  13.218+			case AORR:
  13.219+			case ABIC:
  13.220+			case AMVN:
  13.221+			case ASUB:
  13.222+			case AADD:
  13.223+			case AADC:
  13.224+			case ASBC:
  13.225+				break;
  13.226+			}
  13.227+			p1->scond |= C_SBIT;
  13.228+			r2->prog->as = t;
  13.229+			excise(r);
  13.230+			continue;
  13.231+		}
  13.232+	}
  13.233+#endif
  13.234+
  13.235+#ifdef XXX
  13.236+	predicate();
  13.237+#endif
  13.238+}
  13.239+
  13.240+void
  13.241+excise(Reg *r)
  13.242+{
  13.243+	Prog *p;
  13.244+
  13.245+	p = r->prog;
  13.246+	p->as = ANOP;
  13.247+	p->scond = zprog.scond;
  13.248+	p->from = zprog.from;
  13.249+	p->to = zprog.to;
  13.250+	p->reg = zprog.reg; /**/
  13.251+}
  13.252+
  13.253+Reg*
  13.254+uniqp(Reg *r)
  13.255+{
  13.256+	Reg *r1;
  13.257+
  13.258+	r1 = r->p1;
  13.259+	if(r1 == R) {
  13.260+		r1 = r->p2;
  13.261+		if(r1 == R || r1->p2link != R)
  13.262+			return R;
  13.263+	} else
  13.264+		if(r->p2 != R)
  13.265+			return R;
  13.266+	return r1;
  13.267+}
  13.268+
  13.269+Reg*
  13.270+uniqs(Reg *r)
  13.271+{
  13.272+	Reg *r1;
  13.273+
  13.274+	r1 = r->s1;
  13.275+	if(r1 == R) {
  13.276+		r1 = r->s2;
  13.277+		if(r1 == R)
  13.278+			return R;
  13.279+	} else
  13.280+		if(r->s2 != R)
  13.281+			return R;
  13.282+	return r1;
  13.283+}
  13.284+
  13.285+/*
  13.286+ * convert references to $0 to references to ZR (REGZERO)
  13.287+ */
  13.288+int
  13.289+regzer(Adr *a)
  13.290+{
  13.291+return 0;
  13.292+	switch(a->type){
  13.293+	case D_CONST:
  13.294+		return a->sym == S && a->offset == 0;
  13.295+	case D_REG:
  13.296+		return a->reg == REGZERO;
  13.297+	}
  13.298+	return 0;
  13.299+}
  13.300+
  13.301+int
  13.302+regtyp(Adr *a)
  13.303+{
  13.304+
  13.305+	if(a->type == D_REG){
  13.306+		if(a->reg == REGZERO)
  13.307+			return 0;
  13.308+		return 1;
  13.309+	}
  13.310+	if(a->type == D_FREG)
  13.311+		return 1;
  13.312+	return 0;
  13.313+}
  13.314+
  13.315+/*
  13.316+ * the idea is to substitute
  13.317+ * one register for another
  13.318+ * from one MOV to another
  13.319+ *	MOV	a, R0
  13.320+ *	ADD	b, R0	/ no use of R1
  13.321+ *	MOV	R0, R1
  13.322+ * would be converted to
  13.323+ *	MOV	a, R1
  13.324+ *	ADD	b, R1
  13.325+ *	MOV	R1, R0
  13.326+ * hopefully, then the former or latter MOV
  13.327+ * will be eliminated by copy propagation.
  13.328+ */
  13.329+int
  13.330+subprop(Reg *r0)
  13.331+{
  13.332+	Prog *p;
  13.333+	Adr *v1, *v2;
  13.334+	Reg *r;
  13.335+	int t;
  13.336+
  13.337+	p = r0->prog;
  13.338+	v1 = &p->from;
  13.339+	if(!regtyp(v1))
  13.340+		return 0;
  13.341+	v2 = &p->to;
  13.342+	if(!regtyp(v2))
  13.343+		return 0;
  13.344+	for(r=uniqp(r0); r!=R; r=uniqp(r)) {
  13.345+		if(uniqs(r) == R)
  13.346+			break;
  13.347+		p = r->prog;
  13.348+		switch(p->as) {
  13.349+		case ABL:
  13.350+			return 0;
  13.351+
  13.352+		case ACMP:
  13.353+		case ACMN:
  13.354+		case AADC:
  13.355+		case AADCS:
  13.356+		case AADD:
  13.357+		case AADDS:
  13.358+		case ASUB:
  13.359+		case ASUBS:
  13.360+		case ALSL:
  13.361+		case ALSR:
  13.362+		case AASR:
  13.363+		case AORR:
  13.364+		case AAND:
  13.365+		case AANDS:
  13.366+		case AEOR:
  13.367+		case AMUL:
  13.368+		case ASDIV:
  13.369+		case AUDIV:
  13.370+		case AREM:
  13.371+		case AUREM:
  13.372+
  13.373+		case ACMPW:
  13.374+		case ACMNW:
  13.375+		case AADCW:
  13.376+		case AADCSW:
  13.377+		case AADDSW:
  13.378+		case AADDW:
  13.379+		case ASUBSW:
  13.380+		case ASUBW:
  13.381+		case ALSLW:
  13.382+		case ALSRW:
  13.383+		case AASRW:
  13.384+		case AORRW:
  13.385+		case AANDW:
  13.386+		case AANDSW:
  13.387+		case AEORW:
  13.388+		case AMULW:
  13.389+		case ASDIVW:
  13.390+		case AUDIVW:
  13.391+		case AREMW:
  13.392+		case AUREMW:
  13.393+
  13.394+		case AFCMPS:
  13.395+		case AFCMPD:
  13.396+		case AFADDD:
  13.397+		case AFADDS:
  13.398+		case AFSUBD:
  13.399+		case AFSUBS:
  13.400+		case AFMULD:
  13.401+		case AFMULS:
  13.402+		case AFDIVD:
  13.403+		case AFDIVS:
  13.404+			if(p->to.type == v1->type)
  13.405+			if(p->to.reg == v1->reg) {
  13.406+				if(p->reg == NREG)
  13.407+					p->reg = p->to.reg;
  13.408+				goto gotit;
  13.409+			}
  13.410+			break;
  13.411+
  13.412+		case ANEG:
  13.413+		case ANEGS:
  13.414+		case ANEGSW:
  13.415+		case ANEGW:
  13.416+		case ANGC:
  13.417+		case ANGCS:
  13.418+		case ANGCSW:
  13.419+		case ANGCW:
  13.420+		case AMVN:
  13.421+		case AMVNW:
  13.422+		case AFNEGD:
  13.423+		case AFNEGS:
  13.424+		case AFABSS:
  13.425+		case AFABSD:
  13.426+		case AFSQRTS:
  13.427+		case AFSQRTD:
  13.428+		case AFMOVS:
  13.429+		case AFMOVD:
  13.430+		case AMOVW:
  13.431+		case AMOV:
  13.432+			if(p->to.type == v1->type)
  13.433+			if(p->to.reg == v1->reg)
  13.434+				goto gotit;
  13.435+			break;
  13.436+
  13.437+		}
  13.438+		if(copyau(&p->from, v2) ||
  13.439+		   copyau1(p, v2) ||
  13.440+		   copyau(&p->to, v2))
  13.441+			break;
  13.442+		if(copysub(&p->from, v1, v2, 0) ||
  13.443+		   copysub1(p, v1, v2, 0) ||
  13.444+		   copysub(&p->to, v1, v2, 0))
  13.445+			break;
  13.446+	}
  13.447+	return 0;
  13.448+
  13.449+gotit:
  13.450+	copysub(&p->to, v1, v2, 1);
  13.451+	if(debug['P']) {
  13.452+		print("gotit: %D->%D\n%P", v1, v2, r->prog);
  13.453+		if(p->from.type == v2->type)
  13.454+			print(" excise");
  13.455+		print("\n");
  13.456+	}
  13.457+	for(r=uniqs(r); r!=r0; r=uniqs(r)) {
  13.458+		p = r->prog;
  13.459+		copysub(&p->from, v1, v2, 1);
  13.460+		copysub1(p, v1, v2, 1);
  13.461+		copysub(&p->to, v1, v2, 1);
  13.462+		if(debug['P'])
  13.463+			print("%P\n", r->prog);
  13.464+	}
  13.465+	t = v1->reg;
  13.466+	v1->reg = v2->reg;
  13.467+	v2->reg = t;
  13.468+	if(debug['P'])
  13.469+		print("%P last\n", r->prog);
  13.470+	return 1;
  13.471+}
  13.472+
  13.473+/*
  13.474+ * The idea is to remove redundant copies.
  13.475+ *	v1->v2	F=0
  13.476+ *	(use v2	s/v2/v1/)*
  13.477+ *	set v1	F=1
  13.478+ *	use v2	return fail
  13.479+ *	-----------------
  13.480+ *	v1->v2	F=0
  13.481+ *	(use v2	s/v2/v1/)*
  13.482+ *	set v1	F=1
  13.483+ *	set v2	return success
  13.484+ */
  13.485+int
  13.486+copyprop(Reg *r0)
  13.487+{
  13.488+	Prog *p;
  13.489+	Adr *v1, *v2;
  13.490+	Reg *r;
  13.491+
  13.492+	p = r0->prog;
  13.493+	v1 = &p->from;
  13.494+	v2 = &p->to;
  13.495+	if(copyas(v1, v2))
  13.496+		return 1;
  13.497+	for(r=firstr; r!=R; r=r->link)
  13.498+		r->active = 0;
  13.499+	return copy1(v1, v2, r0->s1, 0);
  13.500+}
  13.501+
  13.502+int
  13.503+copy1(Adr *v1, Adr *v2, Reg *r, int f)
  13.504+{
  13.505+	int t;
  13.506+	Prog *p;
  13.507+
  13.508+	if(r->active) {
  13.509+		if(debug['P'])
  13.510+			print("act set; return 1\n");
  13.511+		return 1;
  13.512+	}
  13.513+	r->active = 1;
  13.514+	if(debug['P'])
  13.515+		print("copy %D->%D f=%d\n", v1, v2, f);
  13.516+	for(; r != R; r = r->s1) {
  13.517+		p = r->prog;
  13.518+		if(debug['P'])
  13.519+			print("%P", p);
  13.520+		if(!f && uniqp(r) == R) {
  13.521+			f = 1;
  13.522+			if(debug['P'])
  13.523+				print("; merge; f=%d", f);
  13.524+		}
  13.525+		t = copyu(p, v2, A);
  13.526+		switch(t) {
  13.527+		case 2:	/* rar, cant split */
  13.528+			if(debug['P'])
  13.529+				print("; %Drar; return 0\n", v2);
  13.530+			return 0;
  13.531+
  13.532+		case 3:	/* set */
  13.533+			if(debug['P'])
  13.534+				print("; %Dset; return 1\n", v2);
  13.535+			return 1;
  13.536+
  13.537+		case 1:	/* used, substitute */
  13.538+		case 4:	/* use and set */
  13.539+			if(f) {
  13.540+				if(!debug['P'])
  13.541+					return 0;
  13.542+				if(t == 4)
  13.543+					print("; %Dused+set and f=%d; return 0\n", v2, f);
  13.544+				else
  13.545+					print("; %Dused and f=%d; return 0\n", v2, f);
  13.546+				return 0;
  13.547+			}
  13.548+			if(copyu(p, v2, v1)) {
  13.549+				if(debug['P'])
  13.550+					print("; sub fail; return 0\n");
  13.551+				return 0;
  13.552+			}
  13.553+			if(debug['P'])
  13.554+				print("; sub%D/%D", v2, v1);
  13.555+			if(t == 4) {
  13.556+				if(debug['P'])
  13.557+					print("; %Dused+set; return 1\n", v2);
  13.558+				return 1;
  13.559+			}
  13.560+			break;
  13.561+		}
  13.562+		if(!f) {
  13.563+			t = copyu(p, v1, A);
  13.564+			if(!f && (t == 2 || t == 3 || t == 4)) {
  13.565+				f = 1;
  13.566+				if(debug['P'])
  13.567+					print("; %Dset and !f; f=%d", v1, f);
  13.568+			}
  13.569+		}
  13.570+		if(debug['P'])
  13.571+			print("\n");
  13.572+		if(r->s2)
  13.573+			if(!copy1(v1, v2, r->s2, f))
  13.574+				return 0;
  13.575+	}
  13.576+	return 1;
  13.577+}
  13.578+
  13.579+/*
  13.580+ * The idea is to remove redundant constants.
  13.581+ *	$c1->v1
  13.582+ *	($c1->v2 s/$c1/v1)*
  13.583+ *	set v1  return
  13.584+ * The v1->v2 should be eliminated by copy propagation.
  13.585+ */
  13.586+void
  13.587+constprop(Adr *c1, Adr *v1, Reg *r)
  13.588+{
  13.589+	Prog *p;
  13.590+
  13.591+	if(debug['C'])
  13.592+		print("constprop %D->%D\n", c1, v1);
  13.593+	for(; r != R; r = r->s1) {
  13.594+		p = r->prog;
  13.595+		if(debug['C'])
  13.596+			print("%P", p);
  13.597+		if(uniqp(r) == R) {
  13.598+			if(debug['C'])
  13.599+				print("; merge; return\n");
  13.600+			return;
  13.601+		}
  13.602+		if(p->as == AMOVW && copyas(&p->from, c1)) {
  13.603+			if(debug['C'])
  13.604+				print("; sub%D/%D", &p->from, v1);
  13.605+			p->from = *v1;
  13.606+		} else if(copyu(p, v1, A) > 1) {
  13.607+			if(debug['C'])
  13.608+				print("; %Dset; return\n", v1);
  13.609+			return;
  13.610+		}
  13.611+		if(debug['C'])
  13.612+			print("\n");
  13.613+		if(r->s2)
  13.614+			constprop(c1, v1, r->s2);
  13.615+	}
  13.616+}
  13.617+
  13.618+/*
  13.619+ * ALSL x,y,w
  13.620+ * .. (not use w, not set x y w)
  13.621+ * AXXX w,a,b (a != w)
  13.622+ * .. (not use w)
  13.623+ * (set w)
  13.624+ * ----------- changed to
  13.625+ * ..
  13.626+ * AXXX (x<<y),a,b
  13.627+ * ..
  13.628+ */
  13.629+#define FAIL(msg) { if(debug['H']) print("\t%s; FAILURE\n", msg); return 0; }
  13.630+int
  13.631+shiftprop(Reg *r)
  13.632+{
  13.633+	Reg *r1;
  13.634+	Prog *p, *p1, *p2;
  13.635+	int n, o;
  13.636+	Adr a;
  13.637+
  13.638+	p = r->prog;
  13.639+	if(p->to.type != D_REG)
  13.640+		FAIL("BOTCH: result not reg");
  13.641+	n = p->to.reg;
  13.642+	a = zprog.from;
  13.643+	if(p->reg != NREG && p->reg != p->to.reg) {
  13.644+		a.type = D_REG;
  13.645+		a.reg = p->reg;
  13.646+	}
  13.647+	if(debug['H'])
  13.648+		print("shiftprop\n%P", p);
  13.649+	r1 = r;
  13.650+	for(;;) {
  13.651+		/* find first use of shift result; abort if shift operands or result are changed */
  13.652+		r1 = uniqs(r1);
  13.653+		if(r1 == R)
  13.654+			FAIL("branch");
  13.655+		if(uniqp(r1) == R)
  13.656+			FAIL("merge");
  13.657+		p1 = r1->prog;
  13.658+		if(debug['H'])
  13.659+			print("\n%P", p1);
  13.660+		switch(copyu(p1, &p->to, A)) {
  13.661+		case 0:	/* not used or set */
  13.662+			if((p->from.type == D_REG && copyu(p1, &p->from, A) > 1) ||
  13.663+			   (a.type == D_REG && copyu(p1, &a, A) > 1))
  13.664+				FAIL("args modified");
  13.665+			continue;
  13.666+		case 3:	/* set, not used */
  13.667+			FAIL("BOTCH: noref");
  13.668+		}
  13.669+		break;
  13.670+	}
  13.671+	/* check whether substitution can be done */
  13.672+	switch(p1->as) {
  13.673+	case ABIC:
  13.674+	case ACMP:
  13.675+	case ACMN:
  13.676+		if(p1->reg == n)
  13.677+			FAIL("can't swap");
  13.678+		if(p1->reg == NREG && p1->to.reg == n)
  13.679+			FAIL("shift result used twice");
  13.680+	case AMVN:
  13.681+		if(p1->from.type == D_SHIFT)
  13.682+			FAIL("shift result used in shift");
  13.683+		if(p1->from.type != D_REG || p1->from.reg != n)
  13.684+			FAIL("BOTCH: where is it used?");
  13.685+		break;
  13.686+	}
  13.687+	/* check whether shift result is used subsequently */
  13.688+	p2 = p1;
  13.689+	if(p1->to.reg != n)
  13.690+	for (;;) {
  13.691+		r1 = uniqs(r1);
  13.692+		if(r1 == R)
  13.693+			FAIL("inconclusive");
  13.694+		p1 = r1->prog;
  13.695+		if(debug['H'])
  13.696+			print("\n%P", p1);
  13.697+		switch(copyu(p1, &p->to, A)) {
  13.698+		case 0:	/* not used or set */
  13.699+			continue;
  13.700+		case 3: /* set, not used */
  13.701+			break;
  13.702+		default:/* used */
  13.703+			FAIL("reused");
  13.704+		}
  13.705+		break;
  13.706+	}
  13.707+	/* make the substitution */
  13.708+	p2->from.type = D_SHIFT;
  13.709+	p2->from.reg = NREG;
  13.710+	o = p->reg;
  13.711+	if(o == NREG)
  13.712+		o = p->to.reg;
  13.713+	switch(p->from.type){
  13.714+	case D_CONST:
  13.715+		o |= (p->from.offset&0x3f)<<7;
  13.716+		break;
  13.717+	case D_REG:
  13.718+		o |= (1<<4) | (p->from.reg<<8);
  13.719+		break;
  13.720+	}
  13.721+	switch(p->as){
  13.722+	case ALSL:
  13.723+		o |= 0<<5;
  13.724+		break;
  13.725+	case ALSR:
  13.726+		o |= 1<<5;
  13.727+		break;
  13.728+	case AASR:
  13.729+		o |= 2<<5;
  13.730+		break;
  13.731+	}
  13.732+	p2->from.offset = o;
  13.733+	if(debug['H'])
  13.734+		print("\t=>%P\tSUCCEED\n", p2);
  13.735+	return 1;
  13.736+}
  13.737+
  13.738+Reg*
  13.739+findpre(Reg *r, Adr *v)
  13.740+{
  13.741+	Reg *r1;
  13.742+
  13.743+	for(r1=uniqp(r); r1!=R; r=r1,r1=uniqp(r)) {
  13.744+		if(uniqs(r1) != r)
  13.745+			return R;
  13.746+		switch(copyu(r1->prog, v, A)) {
  13.747+		case 1: /* used */
  13.748+		case 2: /* read-alter-rewrite */
  13.749+			return R;
  13.750+		case 3: /* set */
  13.751+		case 4: /* set and used */
  13.752+			return r1;
  13.753+		}
  13.754+	}
  13.755+	return R;
  13.756+}
  13.757+
  13.758+Reg*
  13.759+findinc(Reg *r, Reg *r2, Adr *v)
  13.760+{
  13.761+	Reg *r1;
  13.762+	Prog *p;
  13.763+
  13.764+
  13.765+	for(r1=uniqs(r); r1!=R && r1!=r2; r=r1,r1=uniqs(r)) {
  13.766+		if(uniqp(r1) != r)
  13.767+			return R;
  13.768+		switch(copyu(r1->prog, v, A)) {
  13.769+		case 0: /* not touched */
  13.770+			continue;
  13.771+		case 4: /* set and used */
  13.772+			p = r1->prog;
  13.773+			if(p->as == AADD)
  13.774+			if(p->from.type == D_CONST)
  13.775+			if(p->from.offset > -256 && p->from.offset < 256)
  13.776+				return r1;
  13.777+		default:
  13.778+			return R;
  13.779+		}
  13.780+	}
  13.781+	return R;
  13.782+}
  13.783+
  13.784+int
  13.785+nochange(Reg *r, Reg *r2, Prog *p)
  13.786+{
  13.787+	Adr a[3];
  13.788+	int i, n;
  13.789+
  13.790+	if(r == r2)
  13.791+		return 1;
  13.792+	n = 0;
  13.793+	if(p->reg != NREG && p->reg != p->to.reg) {
  13.794+		a[n].type = D_REG;
  13.795+		a[n++].reg = p->reg;
  13.796+	}
  13.797+	switch(p->from.type) {
  13.798+	case D_SHIFT:
  13.799+		a[n].type = D_REG;
  13.800+		a[n++].reg = p->from.offset&0xf;
  13.801+	case D_REG:
  13.802+		a[n].type = D_REG;
  13.803+		a[n++].reg = p->from.reg;
  13.804+	}
  13.805+	if(n == 0)
  13.806+		return 1;
  13.807+	for(; r!=R && r!=r2; r=uniqs(r)) {
  13.808+		p = r->prog;
  13.809+		for(i=0; i<n; i++)
  13.810+			if(copyu(p, &a[i], A) > 1)
  13.811+				return 0;
  13.812+	}
  13.813+	return 1;
  13.814+}
  13.815+
  13.816+int
  13.817+findu1(Reg *r, Adr *v)
  13.818+{
  13.819+	for(; r != R; r = r->s1) {
  13.820+		if(r->active)
  13.821+			return 0;
  13.822+		r->active = 1;
  13.823+		switch(copyu(r->prog, v, A)) {
  13.824+		case 1: /* used */
  13.825+		case 2: /* read-alter-rewrite */
  13.826+		case 4: /* set and used */
  13.827+			return 1;
  13.828+		case 3: /* set */
  13.829+			return 0;
  13.830+		}
  13.831+		if(r->s2)
  13.832+			if (findu1(r->s2, v))
  13.833+				return 1;
  13.834+	}
  13.835+	return 0;
  13.836+}
  13.837+
  13.838+int
  13.839+finduse(Reg *r, Adr *v)
  13.840+{
  13.841+	Reg *r1;
  13.842+
  13.843+	for(r1=firstr; r1!=R; r1=r1->link)
  13.844+		r1->active = 0;
  13.845+	return findu1(r, v);
  13.846+}
  13.847+
  13.848+#ifdef NOTYET
  13.849+int
  13.850+xtramodes(Reg *r, Adr *a)
  13.851+{
  13.852+	Reg *r1, *r2, *r3;
  13.853+	Prog *p, *p1;
  13.854+	Adr v;
  13.855+
  13.856+	p = r->prog;
  13.857+	if(debug['h'] && p->as == AMOVB && p->from.type == D_OREG)	/* byte load */
  13.858+		return 0;
  13.859+	v = *a;
  13.860+	v.type = D_REG;
  13.861+	r1 = findpre(r, &v);
  13.862+	if(r1 != R) {
  13.863+		p1 = r1->prog;
  13.864+		if(p1->to.type == D_REG && p1->to.reg == v.reg)
  13.865+		switch(p1->as) {
  13.866+		case AADD:
  13.867+			if(p1->from.type == D_REG ||
  13.868+			   (p1->from.type == D_SHIFT && (p1->from.offset&(1<<4)) == 0 &&
  13.869+			    (p->as != AMOVB || (a == &p->from && (p1->from.offset&~0xf) == 0))) ||
  13.870+			   (p1->from.type == D_CONST && 
  13.871+			    p1->from.offset > -4096 && p1->from.offset < 4096))
  13.872+			if(nochange(uniqs(r1), r, p1)) {
  13.873+				if(a != &p->from || v.reg != p->to.reg)
  13.874+				if (finduse(r->s1, &v)) {
  13.875+					if(p1->reg == NREG || p1->reg == v.reg)
  13.876+						/* pre-indexing */
  13.877+						p->scond |= C_WBIT;
  13.878+					else return 0;	
  13.879+				}
  13.880+				switch (p1->from.type) {
  13.881+				case D_REG:
  13.882+					/* register offset */
  13.883+					a->type = D_SHIFT;
  13.884+					a->offset = p1->from.reg;
  13.885+					break;
  13.886+				case D_SHIFT:
  13.887+					/* scaled register offset */
  13.888+					a->type = D_SHIFT;
  13.889+				case D_CONST:
  13.890+					/* immediate offset */
  13.891+					a->offset = p1->from.offset;
  13.892+					break;
  13.893+				}
  13.894+				if(p1->reg != NREG)
  13.895+					a->reg = p1->reg;
  13.896+				excise(r1);
  13.897+				return 1;
  13.898+			}
  13.899+			break;
  13.900+		case AMOVW:
  13.901+			if(p1->from.type == D_REG)
  13.902+			if((r2 = findinc(r1, r, &p1->from)) != R) {
  13.903+			for(r3=uniqs(r2); r3->prog->as==ANOP; r3=uniqs(r3))
  13.904+				;
  13.905+			if(r3 == r) {
  13.906+				/* post-indexing */
  13.907+				p1 = r2->prog;
  13.908+				a->reg = p1->to.reg;
  13.909+				a->offset = p1->from.offset;
  13.910+				p->scond |= C_PBIT;
  13.911+				if(!finduse(r, &r1->prog->to))
  13.912+					excise(r1);
  13.913+				excise(r2);
  13.914+				return 1;
  13.915+			}
  13.916+			}
  13.917+			break;
  13.918+		}
  13.919+	}
  13.920+	if(a != &p->from || a->reg != p->to.reg)
  13.921+	if((r1 = findinc(r, R, &v)) != R) {
  13.922+		/* post-indexing */
  13.923+		p1 = r1->prog;
  13.924+		a->offset = p1->from.offset;
  13.925+		p->scond |= C_PBIT;
  13.926+		excise(r1);
  13.927+		return 1;
  13.928+	}
  13.929+	return 0;
  13.930+}
  13.931+#endif
  13.932+
  13.933+/*
  13.934+ * return
  13.935+ * 1 if v only used (and substitute),
  13.936+ * 2 if read-alter-rewrite
  13.937+ * 3 if set
  13.938+ * 4 if set and used
  13.939+ * 0 otherwise (not touched)
  13.940+ */
  13.941+int
  13.942+copyu(Prog *p, Adr *v, Adr *s)
  13.943+{
  13.944+
  13.945+	switch(p->as) {
  13.946+
  13.947+	default:
  13.948+		if(debug['P'])
  13.949+			print(" (unk)");
  13.950+		return 2;
  13.951+
  13.952+	case ANOP:	/* read, write */
  13.953+	case AFMOVS:
  13.954+	case AFMOVD:
  13.955+	case AMOVH:
  13.956+	case AMOVHU:
  13.957+	case AMOVB:
  13.958+	case AMOVBU:
  13.959+	case AMOVW:
  13.960+	case AMOVWU:
  13.961+	case AMOV:
  13.962+
  13.963+	case AMVN:
  13.964+	case AMVNW:
  13.965+	case ANEG:
  13.966+	case ANEGS:
  13.967+	case ANEGW:
  13.968+	case ANEGSW:
  13.969+	case ANGC:
  13.970+	case ANGCS:
  13.971+	case ANGCW:
  13.972+	case ANGCSW:
  13.973+	case AFCVTSD:
  13.974+	case AFCVTDS:
  13.975+	case AFCVTZSD:
  13.976+	case AFCVTZSDW:
  13.977+	case AFCVTZSS:
  13.978+	case AFCVTZSSW:
  13.979+	case AFCVTZUD:
  13.980+	case AFCVTZUDW:
  13.981+	case AFCVTZUS:
  13.982+	case AFCVTZUSW:
  13.983+	case ASCVTFD:
  13.984+	case ASCVTFS:
  13.985+	case ASCVTFWD:
  13.986+	case ASCVTFWS:
  13.987+	case AUCVTFD:
  13.988+	case AUCVTFS:
  13.989+	case AUCVTFWD:
  13.990+	case AUCVTFWS:
  13.991+	case AFNEGD:
  13.992+	case AFNEGS:
  13.993+	case AFABSD:
  13.994+	case AFABSS:
  13.995+	case AFSQRTD:
  13.996+	case AFSQRTS:
  13.997+	case ACASE:
  13.998+#ifdef YYY
  13.999+		if(p->scond&(C_WBIT|C_PBIT))
 13.1000+		if(v->type == D_REG) {
 13.1001+			if(p->from.type == D_OREG || p->from.type == D_SHIFT) {
 13.1002+				if(p->from.reg == v->reg)
 13.1003+					return 2;
 13.1004+			} else {
 13.1005+		  		if(p->to.reg == v->reg)
 13.1006+					return 2;
 13.1007+			}
 13.1008+		}
 13.1009+#endif
 13.1010+		if(s != A) {
 13.1011+			if(copysub(&p->from, v, s, 1))
 13.1012+				return 1;
 13.1013+			if(!copyas(&p->to, v))
 13.1014+				if(copysub(&p->to, v, s, 1))
 13.1015+					return 1;
 13.1016+			return 0;
 13.1017+		}
 13.1018+		if(copyas(&p->to, v)) {
 13.1019+			if(copyau(&p->from, v))
 13.1020+				return 4;
 13.1021+			return 3;
 13.1022+		}
 13.1023+		if(copyau(&p->from, v))
 13.1024+			return 1;
 13.1025+		if(copyau(&p->to, v))
 13.1026+			return 1;
 13.1027+		return 0;
 13.1028+
 13.1029+
 13.1030+	case AADD:	/* read, read, write */
 13.1031+	case AADDW:
 13.1032+	case AADDS:
 13.1033+	case AADDSW:
 13.1034+	case ASUB:
 13.1035+	case ASUBW:
 13.1036+	case ASUBS:
 13.1037+	case ASUBSW:
 13.1038+		if(0 && p->from.type == D_CONST){
 13.1039+			if(s != A && regzer(s))
 13.1040+				return 4;	/* add/sub $c,r,r -> r31 is sp not zr, don't touch */
 13.1041+		}
 13.1042+
 13.1043+	case ALSL:
 13.1044+	case ALSLW:
 13.1045+	case ALSR:
 13.1046+	case ALSRW:
 13.1047+	case AASR:
 13.1048+	case AASRW:
 13.1049+	case AORR:
 13.1050+	case AORRW:
 13.1051+	case AAND:
 13.1052+	case AANDW:
 13.1053+	case AEOR:
 13.1054+	case AEORW:
 13.1055+	case AMUL:
 13.1056+	case AMULW:
 13.1057+	case AUMULL:
 13.1058+	case AREM:
 13.1059+	case AREMW:
 13.1060+	case ASDIV:
 13.1061+	case ASDIVW:
 13.1062+	case AUDIV:
 13.1063+	case AUDIVW:
 13.1064+	case AUREM:
 13.1065+	case AUREMW:
 13.1066+	case AFADDS:
 13.1067+	case AFADDD:
 13.1068+	case AFSUBS:
 13.1069+	case AFSUBD:
 13.1070+	case AFMULS:
 13.1071+	case AFMULD:
 13.1072+	case AFDIVS:
 13.1073+	case AFDIVD:
 13.1074+		if(s != A) {
 13.1075+			if(copysub(&p->from, v, s, 1))
 13.1076+				return 1;
 13.1077+			if(copysub1(p, v, s, 1))
 13.1078+				return 1;
 13.1079+			if(!copyas(&p->to, v))
 13.1080+				if(copysub(&p->to, v, s, 1))
 13.1081+					return 1;
 13.1082+			return 0;
 13.1083+		}
 13.1084+		if(copyas(&p->to, v)) {
 13.1085+			if(p->reg == NREG)
 13.1086+				p->reg = p->to.reg;
 13.1087+			if(copyau(&p->from, v))
 13.1088+				return 4;
 13.1089+			if(copyau1(p, v))
 13.1090+				return 4;
 13.1091+			return 3;
 13.1092+		}
 13.1093+		if(copyau(&p->from, v))
 13.1094+			return 1;
 13.1095+		if(copyau1(p, v))
 13.1096+			return 1;
 13.1097+		if(copyau(&p->to, v))
 13.1098+			return 1;
 13.1099+		return 0;
 13.1100+
 13.1101+	case ABEQ:	/* read, read */
 13.1102+	case ABNE:
 13.1103+	case ABCS:
 13.1104+	case ABHS:
 13.1105+	case ABCC:
 13.1106+	case ABLO:
 13.1107+	case ABMI:
 13.1108+	case ABPL:
 13.1109+	case ABVS:
 13.1110+	case ABVC:
 13.1111+	case ABHI:
 13.1112+	case ABLS:
 13.1113+	case ABGE:
 13.1114+	case ABLT:
 13.1115+	case ABGT:
 13.1116+	case ABLE:
 13.1117+
 13.1118+	case AFCMPS:
 13.1119+	case AFCMPD:
 13.1120+	case ACMP:
 13.1121+	case ACMPW:
 13.1122+	case ACMN:
 13.1123+	case ACMNW:
 13.1124+		if(s != A) {
 13.1125+			if(copysub(&p->from, v, s, 1))
 13.1126+				return 1;
 13.1127+			return copysub1(p, v, s, 1);
 13.1128+		}
 13.1129+		if(copyau(&p->from, v))
 13.1130+			return 1;
 13.1131+		if(copyau1(p, v))
 13.1132+			return 1;
 13.1133+		return 0;
 13.1134+
 13.1135+	case AB:	/* funny */
 13.1136+		if(s != A) {
 13.1137+			if(copysub(&p->to, v, s, 1))
 13.1138+				return 1;
 13.1139+			return 0;
 13.1140+		}
 13.1141+		if(copyau(&p->to, v))
 13.1142+			return 1;
 13.1143+		return 0;
 13.1144+
 13.1145+	case ARET:
 13.1146+	case ARETURN:	/* funny */
 13.1147+		if(v->type == D_REG)
 13.1148+		if(v->reg == REGRET)
 13.1149+			return 2;
 13.1150+		if(v->type == D_FREG)
 13.1151+		if(v->reg == FREGRET)
 13.1152+			return 2;
 13.1153+
 13.1154+	case ABL:	/* funny */
 13.1155+		if(v->type == D_REG) {
 13.1156+			if(v->reg <= REGEXT && v->reg > exregoffset)
 13.1157+				return 2;
 13.1158+			if(v->reg == REGARG)
 13.1159+				return 2;
 13.1160+		}
 13.1161+		if(v->type == D_FREG)
 13.1162+			if(v->reg <= FREGEXT && v->reg > exfregoffset)
 13.1163+				return 2;
 13.1164+
 13.1165+		if(s != A) {
 13.1166+			if(copysub(&p->to, v, s, 1))
 13.1167+				return 1;
 13.1168+			return 0;
 13.1169+		}
 13.1170+		if(copyau(&p->to, v))
 13.1171+			return 4;
 13.1172+		return 3;
 13.1173+
 13.1174+	case ATEXT:	/* funny */
 13.1175+		if(v->type == D_REG)
 13.1176+			if(v->reg == REGARG)
 13.1177+				return 3;
 13.1178+		return 0;
 13.1179+	}
 13.1180+}
 13.1181+
 13.1182+int
 13.1183+a2type(Prog *p)
 13.1184+{
 13.1185+
 13.1186+	switch(p->as) {
 13.1187+
 13.1188+	case ACMP:
 13.1189+	case ACMPW:
 13.1190+	case ACMN:
 13.1191+	case ACMNW:
 13.1192+
 13.1193+	case AADD:
 13.1194+	case AADDW:
 13.1195+	case AADDS:
 13.1196+	case AADDSW:
 13.1197+	case ASUB:
 13.1198+	case ASUBS:
 13.1199+	case ASUBSW:
 13.1200+	case ASUBW:
 13.1201+	case ALSL:
 13.1202+	case ALSLW:
 13.1203+	case ALSR:
 13.1204+	case ALSRW:
 13.1205+	case AASR:
 13.1206+	case AASRW:
 13.1207+	case AORR:
 13.1208+	case AORRW:
 13.1209+	case AAND:
 13.1210+	case AANDW:
 13.1211+	case AANDS:
 13.1212+	case AANDSW:
 13.1213+	case AEOR:
 13.1214+	case AEORW:
 13.1215+	case AMUL:
 13.1216+	case AMULW:
 13.1217+	case AUMULL:
 13.1218+	case AREM:
 13.1219+	case AREMW:
 13.1220+	case ASDIV:
 13.1221+	case ASDIVW:
 13.1222+	case AUDIV:
 13.1223+	case AUDIVW:
 13.1224+	case AUREM:
 13.1225+	case AUREMW:
 13.1226+		return D_REG;
 13.1227+
 13.1228+	case AFCMPS:
 13.1229+	case AFCMPD:
 13.1230+
 13.1231+	case AFADDS:
 13.1232+	case AFADDD:
 13.1233+	case AFSUBS:
 13.1234+	case AFSUBD:
 13.1235+	case AFMULS:
 13.1236+	case AFMULD:
 13.1237+	case AFDIVS:
 13.1238+	case AFDIVD:
 13.1239+		return D_FREG;
 13.1240+	}
 13.1241+	return D_NONE;
 13.1242+}
 13.1243+
 13.1244+/*
 13.1245+ * direct reference,
 13.1246+ * could be set/use depending on
 13.1247+ * semantics
 13.1248+ */
 13.1249+int
 13.1250+copyas(Adr *a, Adr *v)
 13.1251+{
 13.1252+
 13.1253+	if(regtyp(v)) {
 13.1254+		if(a->type == v->type)
 13.1255+		if(a->reg == v->reg)
 13.1256+			return 1;
 13.1257+	} else if(v->type == D_CONST) {		/* for constprop */
 13.1258+		if(a->type == v->type)
 13.1259+		if(a->name == v->name)
 13.1260+		if(a->sym == v->sym)
 13.1261+		if(a->reg == v->reg)
 13.1262+		if(a->offset == v->offset)
 13.1263+			return 1;
 13.1264+	}
 13.1265+	return 0;
 13.1266+}
 13.1267+
 13.1268+/*
 13.1269+ * either direct or indirect
 13.1270+ */
 13.1271+int
 13.1272+copyau(Adr *a, Adr *v)
 13.1273+{
 13.1274+
 13.1275+	if(copyas(a, v))
 13.1276+		return 1;
 13.1277+	if(v->type == D_REG) {
 13.1278+		if(a->type == D_OREG) {
 13.1279+			if(v->reg == a->reg)
 13.1280+				return 1;
 13.1281+		} else if(a->type == D_SHIFT) {
 13.1282+			if(((a->offset>>16)&0x1F) == v->reg)
 13.1283+				return 1;
 13.1284+		} else if(a->type == D_EXTREG) {
 13.1285+			if(a->reg == v->reg || ((a->offset>>16)&0x1F) == v->reg)
 13.1286+				return 1;
 13.1287+		}
 13.1288+	}
 13.1289+	return 0;
 13.1290+}
 13.1291+
 13.1292+int
 13.1293+copyau1(Prog *p, Adr *v)
 13.1294+{
 13.1295+
 13.1296+	if(regtyp(v)) {
 13.1297+		if(a2type(p) == v->type)
 13.1298+		if(p->reg == v->reg) {
 13.1299+			if(a2type(p) != v->type)
 13.1300+				print("botch a2type %P\n", p);
 13.1301+			return 1;
 13.1302+		}
 13.1303+	}
 13.1304+	return 0;
 13.1305+}
 13.1306+
 13.1307+/*
 13.1308+ * substitute s for v in a
 13.1309+ * return failure to substitute
 13.1310+ */
 13.1311+int
 13.1312+copysub(Adr *a, Adr *v, Adr *s, int f)
 13.1313+{
 13.1314+
 13.1315+	if(f)
 13.1316+	if(copyau(a, v)) {
 13.1317+		if(a->type == D_SHIFT) {
 13.1318+			if(((a->offset>>16)&0x1F) == v->reg)
 13.1319+				a->offset = (a->offset&~(0x1F<<16))|(s->reg<<16);
 13.1320+		} else
 13.1321+			a->reg = s->reg;
 13.1322+	}
 13.1323+	return 0;
 13.1324+}
 13.1325+
 13.1326+int
 13.1327+copysub1(Prog *p1, Adr *v, Adr *s, int f)
 13.1328+{
 13.1329+
 13.1330+	if(f)
 13.1331+	if(copyau1(p1, v))
 13.1332+		p1->reg = s->reg;
 13.1333+	return 0;
 13.1334+}
 13.1335+
 13.1336+struct {
 13.1337+	int opcode;
 13.1338+	int notopcode;
 13.1339+	int scond; 
 13.1340+	int notscond; 
 13.1341+} predinfo[]  = { 
 13.1342+	{ ABEQ,	ABNE,	0x0,	0x1, }, 
 13.1343+	{ ABNE,	ABEQ,	0x1,	0x0, }, 
 13.1344+	{ ABCS,	ABCC,	0x2,	0x3, }, 
 13.1345+	{ ABHS,	ABLO,	0x2,	0x3, }, 
 13.1346+	{ ABCC,	ABCS,	0x3,	0x2, }, 
 13.1347+	{ ABLO,	ABHS,	0x3,	0x2, }, 
 13.1348+	{ ABMI,	ABPL,	0x4,	0x5, }, 
 13.1349+	{ ABPL,	ABMI,	0x5,	0x4, }, 
 13.1350+	{ ABVS,	ABVC,	0x6,	0x7, }, 
 13.1351+	{ ABVC,	ABVS,	0x7,	0x6, }, 
 13.1352+	{ ABHI,	ABLS,	0x8,	0x9, }, 
 13.1353+	{ ABLS,	ABHI,	0x9,	0x8, }, 
 13.1354+	{ ABGE,	ABLT,	0xA,	0xB, }, 
 13.1355+	{ ABLT,	ABGE,	0xB,	0xA, }, 
 13.1356+	{ ABGT,	ABLE,	0xC,	0xD, }, 
 13.1357+	{ ABLE,	ABGT,	0xD,	0xC, }, 
 13.1358+}; 
 13.1359+
 13.1360+typedef struct {
 13.1361+	Reg *start;
 13.1362+	Reg *last;
 13.1363+	Reg *end;
 13.1364+	int len;
 13.1365+} Joininfo;
 13.1366+
 13.1367+enum {
 13.1368+	Join,
 13.1369+	Split,
 13.1370+	End,
 13.1371+	Branch,
 13.1372+	Setcond,
 13.1373+	Toolong
 13.1374+};
 13.1375+	
 13.1376+enum {
 13.1377+	Falsecond,
 13.1378+	Truecond,
 13.1379+	Delbranch,
 13.1380+	Keepbranch
 13.1381+};
 13.1382+
 13.1383+int 
 13.1384+isbranch(Prog *p)
 13.1385+{
 13.1386+	return (ABEQ <= p->as) && (p->as <= ABLE); 
 13.1387+}
 13.1388+
 13.1389+int
 13.1390+predicable(Prog *p)
 13.1391+{
 13.1392+	if (isbranch(p)
 13.1393+		|| p->as == ANOP
 13.1394+		|| p->as == AXXX
 13.1395+		|| p->as == ADATA
 13.1396+		|| p->as == AGLOBL
 13.1397+		|| p->as == AGOK
 13.1398+		|| p->as == AHISTORY
 13.1399+		|| p->as == ANAME
 13.1400+		|| p->as == ASIGNAME
 13.1401+		|| p->as == ATEXT
 13.1402+		|| p->as == AWORD
 13.1403+		|| p->as == ADYNT
 13.1404+		|| p->as == AINIT
 13.1405+		|| p->as == ABCASE
 13.1406+		|| p->as == ACASE)
 13.1407+		return 0; 
 13.1408+	return 1; 
 13.1409+}
 13.1410+
 13.1411+/* 
 13.1412+ * Depends on an analysis of the encodings performed by 5l. 
 13.1413+ * These seem to be all of the opcodes that lead to the "S" bit
 13.1414+ * being set in the instruction encodings. 
 13.1415+ * 
 13.1416+ * C_SBIT may also have been set explicitly in p->scond.
 13.1417+ */ 
 13.1418+int
 13.1419+modifiescpsr(Prog *p)
 13.1420+{
 13.1421+//	return (p->scond&C_SBIT)
 13.1422+	return 1
 13.1423+		|| p->as == ATST 
 13.1424+		|| p->as == ACMN
 13.1425+		|| p->as == ACMP
 13.1426+		|| p->as == AUMULL
 13.1427+		|| p->as == AUDIV
 13.1428+		|| p->as == AMUL
 13.1429+		|| p->as == ASDIV
 13.1430+		|| p->as == AREM
 13.1431+		|| p->as == AUREM
 13.1432+		|| p->as == ABL;
 13.1433+} 
 13.1434+
 13.1435+/*
 13.1436+ * Find the maximal chain of instructions starting with r which could
 13.1437+ * be executed conditionally
 13.1438+ */
 13.1439+int
 13.1440+joinsplit(Reg *r, Joininfo *j)
 13.1441+{
 13.1442+	j->start = r;
 13.1443+	j->last = r;
 13.1444+	j->len = 0;
 13.1445+	do {
 13.1446+		if (r->p2 && (r->p1 || r->p2->p2link)) {
 13.1447+			j->end = r;
 13.1448+			return Join;
 13.1449+		}
 13.1450+		if (r->s1 && r->s2) {
 13.1451+			j->end = r;
 13.1452+			return Split;
 13.1453+		}
 13.1454+		j->last = r;
 13.1455+		if (r->prog->as != ANOP)
 13.1456+			j->len++;
 13.1457+		if (!r->s1 && !r->s2) {
 13.1458+			j->end = r->link;
 13.1459+			return End;
 13.1460+		}
 13.1461+		if (r->s2) {
 13.1462+			j->end = r->s2;
 13.1463+			return Branch;
 13.1464+		}
 13.1465+		if (modifiescpsr(r->prog)) {
 13.1466+			j->end = r->s1;
 13.1467+			return Setcond;
 13.1468+		}
 13.1469+		r = r->s1;
 13.1470+	} while (j->len < 4);
 13.1471+	j->end = r;
 13.1472+	return Toolong;
 13.1473+}
 13.1474+
 13.1475+Reg *
 13.1476+successor(Reg *r)
 13.1477+{
 13.1478+	if (r->s1)
 13.1479+		return r->s1; 
 13.1480+	else
 13.1481+		return r->s2; 
 13.1482+}
 13.1483+
 13.1484+#ifdef XXX
 13.1485+void
 13.1486+applypred(Reg *rstart, Joininfo *j, int cond, int branch)
 13.1487+{
 13.1488+	int pred; 
 13.1489+	Reg *r; 
 13.1490+
 13.1491+	if(j->len == 0)
 13.1492+		return;
 13.1493+	if (cond == Truecond)
 13.1494+		pred = predinfo[rstart->prog->as - ABEQ].scond;
 13.1495+	else
 13.1496+		pred = predinfo[rstart->prog->as - ABEQ].notscond; 
 13.1497+	
 13.1498+	for (r = j->start; ; r = successor(r)) {
 13.1499+		if (r->prog->as == AB) {
 13.1500+			if (r != j->last || branch == Delbranch)
 13.1501+				excise(r);
 13.1502+			else {
 13.1503+			  if (cond == Truecond)
 13.1504+				r->prog->as = predinfo[rstart->prog->as - ABEQ].opcode;
 13.1505+			  else
 13.1506+				r->prog->as = predinfo[rstart->prog->as - ABEQ].notopcode;
 13.1507+			}
 13.1508+		}
 13.1509+		else if (predicable(r->prog)) 
 13.1510+			r->prog->scond = (r->prog->scond&~C_SCOND)|pred;
 13.1511+		if (r->s1 != r->link) {
 13.1512+			r->s1 = r->link;
 13.1513+			r->link->p1 = r;
 13.1514+		}
 13.1515+		if (r == j->last)
 13.1516+			break;
 13.1517+	}
 13.1518+}
 13.1519+
 13.1520+
 13.1521+void
 13.1522+predicate(void)
 13.1523+{	
 13.1524+	Reg *r;
 13.1525+	int t1, t2;
 13.1526+	Joininfo j1, j2;
 13.1527+
 13.1528+	for(r=firstr; r!=R; r=r->link) {
 13.1529+		if (isbranch(r->prog)) {
 13.1530+			t1 = joinsplit(r->s1, &j1);
 13.1531+			t2 = joinsplit(r->s2, &j2);
 13.1532+			if(j1.last->link != j2.start)
 13.1533+				continue;
 13.1534+			if(j1.end == j2.end)
 13.1535+			if((t1 == Branch && (t2 == Join || t2 == Setcond)) ||
 13.1536+			   (t2 == Join && (t1 == Join || t1 == Setcond))) {
 13.1537+				applypred(r, &j1, Falsecond, Delbranch);
 13.1538+				applypred(r, &j2, Truecond, Delbranch);
 13.1539+				excise(r);
 13.1540+				continue;
 13.1541+			}
 13.1542+			if(t1 == End || t1 == Branch) {
 13.1543+				applypred(r, &j1, Falsecond, Keepbranch);
 13.1544+				excise(r);
 13.1545+				continue;
 13.1546+			}
 13.1547+		} 
 13.1548+	} 
 13.1549+}
 13.1550+#endif
    14.1new file mode 100644
    14.2--- /dev/null
    14.3+++ b/sys/src/cmd/7c/reg.c
    14.4@@ -0,0 +1,1160 @@
    14.5+#include "gc.h"
    14.6+
    14.7+void	addsplits(void);
    14.8+
    14.9+Reg*
   14.10+rega(void)
   14.11+{
   14.12+	Reg *r;
   14.13+
   14.14+	r = freer;
   14.15+	if(r == R) {
   14.16+		r = alloc(sizeof(*r));
   14.17+	} else
   14.18+		freer = r->link;
   14.19+
   14.20+	*r = zreg;
   14.21+	return r;
   14.22+}
   14.23+
   14.24+int
   14.25+rcmp(void *a1, void *a2)
   14.26+{
   14.27+	Rgn *p1, *p2;
   14.28+	int c1, c2;
   14.29+
   14.30+	p1 = (Rgn*)a1;
   14.31+	p2 = (Rgn*)a2;
   14.32+	c1 = p2->cost;
   14.33+	c2 = p1->cost;
   14.34+	if(c1 -= c2)
   14.35+		return c1;
   14.36+	return p2->varno - p1->varno;
   14.37+}
   14.38+
   14.39+void
   14.40+regopt(Prog *p)
   14.41+{
   14.42+	Reg *r, *r1, *r2;
   14.43+	Prog *p1;
   14.44+	int i, z;
   14.45+	long initpc, val, npc;
   14.46+	ulong vreg;
   14.47+	Bits bit;
   14.48+	struct
   14.49+	{
   14.50+		long	m;
   14.51+		long	c;
   14.52+		Reg*	p;
   14.53+	} log5[6], *lp;
   14.54+
   14.55+	firstr = R;
   14.56+	lastr = R;
   14.57+	nvar = 0;
   14.58+	regbits = 0;
   14.59+	for(z=0; z<BITS; z++) {
   14.60+		externs.b[z] = 0;
   14.61+		params.b[z] = 0;
   14.62+		consts.b[z] = 0;
   14.63+		addrs.b[z] = 0;
   14.64+	}
   14.65+
   14.66+	/*
   14.67+	 * pass 1
   14.68+	 * build aux data structure
   14.69+	 * allocate pcs
   14.70+	 * find use and set of variables
   14.71+	 */
   14.72+	val = 5L * 5L * 5L * 5L * 5L;
   14.73+	lp = log5;
   14.74+	for(i=0; i<5; i++) {
   14.75+		lp->m = val;
   14.76+		lp->c = 0;
   14.77+		lp->p = R;
   14.78+		val /= 5L;
   14.79+		lp++;
   14.80+	}
   14.81+	val = 0;
   14.82+	for(; p != P; p = p->link) {
   14.83+		switch(p->as) {
   14.84+		case ADATA:
   14.85+		case AGLOBL:
   14.86+		case ANAME:
   14.87+		case ASIGNAME:
   14.88+			continue;
   14.89+		}
   14.90+		r = rega();
   14.91+		if(firstr == R) {
   14.92+			firstr = r;
   14.93+			lastr = r;
   14.94+		} else {
   14.95+			lastr->link = r;
   14.96+			r->p1 = lastr;
   14.97+			lastr->s1 = r;
   14.98+			lastr = r;
   14.99+		}
  14.100+		r->prog = p;
  14.101+		r->pc = val;
  14.102+		val++;
  14.103+
  14.104+		lp = log5;
  14.105+		for(i=0; i<5; i++) {
  14.106+			lp->c--;
  14.107+			if(lp->c <= 0) {
  14.108+				lp->c = lp->m;
  14.109+				if(lp->p != R)
  14.110+					lp->p->log5 = r;
  14.111+				lp->p = r;
  14.112+				(lp+1)->c = 0;
  14.113+				break;
  14.114+			}
  14.115+			lp++;
  14.116+		}
  14.117+
  14.118+		r1 = r->p1;
  14.119+		if(r1 != R)
  14.120+		switch(r1->prog->as) {
  14.121+		case ARETURN:
  14.122+		case ARET:
  14.123+		case AB:
  14.124+		case AERET:
  14.125+			r->p1 = R;
  14.126+			r1->s1 = R;
  14.127+		}
  14.128+
  14.129+		/*
  14.130+		 * left side always read
  14.131+		 */
  14.132+		bit = mkvar(&p->from, p->as==AMOVW || p->as == AMOVWU || p->as == AMOV);
  14.133+		for(z=0; z<BITS; z++)
  14.134+			r->use1.b[z] |= bit.b[z];
  14.135+
  14.136+		/*
  14.137+		 * right side depends on opcode
  14.138+		 */
  14.139+		bit = mkvar(&p->to, 0);
  14.140+		if(bany(&bit))
  14.141+		switch(p->as) {
  14.142+		default:
  14.143+			diag(Z, "reg: unknown asop: %A", p->as);
  14.144+			break;
  14.145+
  14.146+		/*
  14.147+		 * right side write
  14.148+		 */
  14.149+		case ANOP:
  14.150+		case AMOV:
  14.151+		case AMOVB:
  14.152+		case AMOVBU:
  14.153+		case AMOVH:
  14.154+		case AMOVHU:
  14.155+		case AMOVW:
  14.156+		case AMOVWU:
  14.157+		case AFMOVS:
  14.158+		case AFCVTSD:
  14.159+		case AFMOVD:
  14.160+		case AFCVTDS:
  14.161+			for(z=0; z<BITS; z++)
  14.162+				r->set.b[z] |= bit.b[z];
  14.163+			break;
  14.164+
  14.165+		/*
  14.166+		 * funny
  14.167+		 */
  14.168+		case ABL:
  14.169+			for(z=0; z<BITS; z++)
  14.170+				addrs.b[z] |= bit.b[z];
  14.171+			break;
  14.172+		}
  14.173+
  14.174+	}
  14.175+	if(firstr == R)
  14.176+		return;
  14.177+	initpc = pc - val;
  14.178+	npc = val;
  14.179+
  14.180+	/*
  14.181+	 * pass 2
  14.182+	 * turn branch references to pointers
  14.183+	 * build back pointers
  14.184+	 */
  14.185+	for(r = firstr; r != R; r = r->link) {
  14.186+		p = r->prog;
  14.187+		if(p->to.type == D_BRANCH) {
  14.188+			val = p->to.offset - initpc;
  14.189+			r1 = firstr;
  14.190+			while(r1 != R) {
  14.191+				r2 = r1->log5;
  14.192+				if(r2 != R && val >= r2->pc) {
  14.193+					r1 = r2;
  14.194+					continue;
  14.195+				}
  14.196+				if(r1->pc == val)
  14.197+					break;
  14.198+				r1 = r1->link;
  14.199+			}
  14.200+			if(r1 == R) {
  14.201+				nearln = p->lineno;
  14.202+				diag(Z, "ref not found\n%P", p);
  14.203+				continue;
  14.204+			}
  14.205+			if(r1 == r) {
  14.206+				nearln = p->lineno;
  14.207+				diag(Z, "ref to self\n%P", p);
  14.208+				continue;
  14.209+			}
  14.210+			r->s2 = r1;
  14.211+			r->p2link = r1->p2;
  14.212+			r1->p2 = r;
  14.213+		}
  14.214+	}
  14.215+	if(debug['R']) {
  14.216+		p = firstr->prog;
  14.217+		print("\n%L %D\n", p->lineno, &p->from);
  14.218+	}
  14.219+
  14.220+	/*
  14.221+	 * pass 2.5
  14.222+	 * find looping structure
  14.223+	 */
  14.224+	for(r = firstr; r != R; r = r->link)
  14.225+		r->active = 0;
  14.226+	change = 0;
  14.227+	loopit(firstr, npc);
  14.228+
  14.229+	/*
  14.230+	 * pass 3
  14.231+	 * iterate propagating usage
  14.232+	 * 	back until flow graph is complete
  14.233+	 */
  14.234+loop1:
  14.235+	change = 0;
  14.236+	for(r = firstr; r != R; r = r->link)
  14.237+		r->active = 0;
  14.238+	for(r = firstr; r != R; r = r->link)
  14.239+		if(r->prog->as == ARET || r->prog->as == ARETURN)
  14.240+			prop(r, zbits, zbits);
  14.241+loop11:
  14.242+	/* pick up unreachable code */
  14.243+	i = 0;
  14.244+	for(r = firstr; r != R; r = r1) {
  14.245+		r1 = r->link;
  14.246+		if(r1 && r1->active && !r->active) {
  14.247+			prop(r, zbits, zbits);
  14.248+			i = 1;
  14.249+		}
  14.250+	}
  14.251+	if(i)
  14.252+		goto loop11;
  14.253+	if(change)
  14.254+		goto loop1;
  14.255+
  14.256+
  14.257+	/*
  14.258+	 * pass 4
  14.259+	 * iterate propagating register/variable synchrony
  14.260+	 * 	forward until graph is complete
  14.261+	 */
  14.262+loop2:
  14.263+	change = 0;
  14.264+	for(r = firstr; r != R; r = r->link)
  14.265+		r->active = 0;
  14.266+	synch(firstr, zbits);
  14.267+	if(change)
  14.268+		goto loop2;
  14.269+
  14.270+	addsplits();
  14.271+
  14.272+	if(debug['R'] && debug['v']) {
  14.273+		print("\nprop structure:\n");
  14.274+		for(r = firstr; r != R; r = r->link) {
  14.275+			print("%ld:%P", r->loop, r->prog);
  14.276+			for(z=0; z<BITS; z++)
  14.277+				bit.b[z] = r->set.b[z] |
  14.278+					r->refahead.b[z] | r->calahead.b[z] |
  14.279+					r->refbehind.b[z] | r->calbehind.b[z] |
  14.280+					r->use1.b[z] | r->use2.b[z];
  14.281+			if(bany(&bit)) {
  14.282+				print("\t");
  14.283+				if(bany(&r->use1))
  14.284+					print(" u1=%B", r->use1);
  14.285+				if(bany(&r->use2))
  14.286+					print(" u2=%B", r->use2);
  14.287+				if(bany(&r->set))
  14.288+					print(" st=%B", r->set);
  14.289+				if(bany(&r->refahead))
  14.290+					print(" ra=%B", r->refahead);
  14.291+				if(bany(&r->calahead))
  14.292+					print(" ca=%B", r->calahead);
  14.293+				if(bany(&r->refbehind))
  14.294+					print(" rb=%B", r->refbehind);
  14.295+				if(bany(&r->calbehind))
  14.296+					print(" cb=%B", r->calbehind);
  14.297+			}
  14.298+			print("\n");
  14.299+		}
  14.300+	}
  14.301+
  14.302+	/*
  14.303+	 * pass 5
  14.304+	 * isolate regions
  14.305+	 * calculate costs (paint1)
  14.306+	 */
  14.307+	r = firstr;
  14.308+	if(r) {
  14.309+		for(z=0; z<BITS; z++)
  14.310+			bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) &
  14.311+			  ~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]);
  14.312+		if(bany(&bit)) {
  14.313+			nearln = r->prog->lineno;
  14.314+			warn(Z, "used and not set: %B", bit);
  14.315+			if(debug['R'] && !debug['w'])
  14.316+				print("used and not set: %B\n", bit);
  14.317+		}
  14.318+	}
  14.319+
  14.320+	for(r = firstr; r != R; r = r->link)
  14.321+		r->act = zbits;
  14.322+	rgp = region;
  14.323+	nregion = 0;
  14.324+	for(r = firstr; r != R; r = r->link) {
  14.325+		for(z=0; z<BITS; z++)
  14.326+			bit.b[z] = r->set.b[z] &
  14.327+			  ~(r->refahead.b[z] | r->calahead.b[z] | addrs.b[z]);
  14.328+		if(bany(&bit)) {
  14.329+			nearln = r->prog->lineno;
  14.330+			warn(Z, "set and not used: %B", bit);
  14.331+			if(debug['R'])
  14.332+				print("set and not used: %B\n", bit);
  14.333+			excise(r);
  14.334+		}
  14.335+		for(z=0; z<BITS; z++)
  14.336+			bit.b[z] = LOAD(r) & ~(r->act.b[z] | addrs.b[z]);
  14.337+		while(bany(&bit)) {
  14.338+			i = bnum(bit);
  14.339+			rgp->enter = r;
  14.340+			rgp->varno = i;
  14.341+			change = 0;
  14.342+			if(debug['R'] && debug['v'])
  14.343+				print("\n");
  14.344+			paint1(r, i);
  14.345+			bit.b[i/32] &= ~(1L<<(i%32));
  14.346+			if(change <= 0) {
  14.347+				if(debug['R'])
  14.348+					print("%L $%d: %B\n",
  14.349+						r->prog->lineno, change, blsh(i));
  14.350+				continue;
  14.351+			}
  14.352+			rgp->cost = change;
  14.353+			nregion++;
  14.354+			if(nregion >= NRGN) {
  14.355+				warn(Z, "too many regions");
  14.356+				goto brk;
  14.357+			}
  14.358+			rgp++;
  14.359+		}
  14.360+	}
  14.361+brk:
  14.362+	qsort(region, nregion, sizeof(region[0]), rcmp);
  14.363+
  14.364+	/*
  14.365+	 * pass 6
  14.366+	 * determine used registers (paint2)
  14.367+	 * replace code (paint3)
  14.368+	 */
  14.369+	rgp = region;
  14.370+	for(i=0; i<nregion; i++) {
  14.371+		bit = blsh(rgp->varno);
  14.372+		vreg = paint2(rgp->enter, rgp->varno);
  14.373+		vreg = allreg(vreg, rgp);
  14.374+		if(debug['R']) {
  14.375+			if(rgp->regno >= NREG)
  14.376+				print("%L $%d F%d: %B\n",
  14.377+					rgp->enter->prog->lineno,
  14.378+					rgp->cost,
  14.379+					rgp->regno-NREG,
  14.380+					bit);
  14.381+			else
  14.382+				print("%L $%d R%d: %B\n",
  14.383+					rgp->enter->prog->lineno,
  14.384+					rgp->cost,
  14.385+					rgp->regno,
  14.386+					bit);
  14.387+		}
  14.388+		if(rgp->regno != 0)
  14.389+			paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
  14.390+		rgp++;
  14.391+	}
  14.392+	/*
  14.393+	 * pass 7
  14.394+	 * peep-hole on basic block
  14.395+	 */
  14.396+	if(!debug['R'] || debug['P'])
  14.397+		peep();
  14.398+
  14.399+	/*
  14.400+	 * pass 8
  14.401+	 * recalculate pc
  14.402+	 */
  14.403+	val = initpc;
  14.404+	for(r = firstr; r != R; r = r1) {
  14.405+		r->pc = val;
  14.406+		p = r->prog;
  14.407+		p1 = P;
  14.408+		r1 = r->link;
  14.409+		if(r1 != R)
  14.410+			p1 = r1->prog;
  14.411+		for(; p != p1; p = p->link) {
  14.412+			switch(p->as) {
  14.413+			default:
  14.414+				val++;
  14.415+				break;
  14.416+
  14.417+			case ANOP:
  14.418+			case ADATA:
  14.419+			case AGLOBL:
  14.420+			case ANAME:
  14.421+			case ASIGNAME:
  14.422+				break;
  14.423+			}
  14.424+		}
  14.425+	}
  14.426+	pc = val;
  14.427+
  14.428+	/*
  14.429+	 * fix up branches
  14.430+	 */
  14.431+	if(debug['R'])
  14.432+		if(bany(&addrs))
  14.433+			print("addrs: %B\n", addrs);
  14.434+
  14.435+	r1 = 0; /* set */
  14.436+	for(r = firstr; r != R; r = r->link) {
  14.437+		p = r->prog;
  14.438+		if(p->to.type == D_BRANCH)
  14.439+			p->to.offset = r->s2->pc;
  14.440+		r1 = r;
  14.441+	}
  14.442+
  14.443+	/*
  14.444+	 * last pass
  14.445+	 * eliminate nops
  14.446+	 * free aux structures
  14.447+	 */
  14.448+	for(p = firstr->prog; p != P; p = p->link){
  14.449+		while(p->link && p->link->as == ANOP)
  14.450+			p->link = p->link->link;
  14.451+	}
  14.452+	if(r1 != R) {
  14.453+		r1->link = freer;
  14.454+		freer = firstr;
  14.455+	}
  14.456+}
  14.457+
  14.458+void
  14.459+addsplits(void)
  14.460+{
  14.461+	Reg *r, *r1;
  14.462+	int z, i;
  14.463+	Bits bit;
  14.464+
  14.465+	for(r = firstr; r != R; r = r->link) {
  14.466+		if(r->loop > 1)
  14.467+			continue;
  14.468+		if(r->prog->as == ABL)
  14.469+			continue;
  14.470+		for(r1 = r->p2; r1 != R; r1 = r1->p2link) {
  14.471+			if(r1->loop <= 1)
  14.472+				continue;
  14.473+			for(z=0; z<BITS; z++)
  14.474+				bit.b[z] = r1->calbehind.b[z] &
  14.475+					(r->refahead.b[z] | r->use1.b[z] | r->use2.b[z]) &
  14.476+					~(r->calahead.b[z] & addrs.b[z]);
  14.477+			while(bany(&bit)) {
  14.478+				i = bnum(bit);
  14.479+				bit.b[i/32] &= ~(1L << (i%32));
  14.480+			}
  14.481+		}
  14.482+	}
  14.483+}
  14.484+
  14.485+/*
  14.486+ * add mov b,rn
  14.487+ * just after r
  14.488+ */
  14.489+void
  14.490+addmove(Reg *r, int bn, int rn, int f)
  14.491+{
  14.492+	Prog *p, *p1;
  14.493+	Adr *a;
  14.494+	Var *v;
  14.495+
  14.496+	p1 = alloc(sizeof(*p1));
  14.497+	*p1 = zprog;
  14.498+	p = r->prog;
  14.499+
  14.500+	p1->link = p->link;
  14.501+	p->link = p1;
  14.502+	p1->lineno = p->lineno;
  14.503+
  14.504+	v = var + bn;
  14.505+
  14.506+	a = &p1->to;
  14.507+	a->sym = v->sym;
  14.508+	a->name = v->name;
  14.509+	a->offset = v->offset;
  14.510+	a->etype = v->etype;
  14.511+	a->type = D_OREG;
  14.512+	if(a->etype == TARRAY || a->sym == S)
  14.513+		a->type = D_CONST;
  14.514+
  14.515+	p1->as = AMOVW;
  14.516+	if(v->etype == TCHAR || v->etype == TUCHAR)
  14.517+		p1->as = AMOVB;
  14.518+	if(v->etype == TSHORT || v->etype == TUSHORT)
  14.519+		p1->as = AMOVH;
  14.520+	if(v->etype == TVLONG || v->etype == TUVLONG || v->etype == TIND)
  14.521+		p1->as = AMOV;
  14.522+	if(v->etype == TFLOAT)
  14.523+		p1->as = AFMOVS;
  14.524+	if(v->etype == TDOUBLE)
  14.525+		p1->as = AFMOVD;
  14.526+
  14.527+	p1->from.type = D_REG;
  14.528+	p1->from.reg = rn;
  14.529+	if(rn >= NREG) {
  14.530+		p1->from.type = D_FREG;
  14.531+		p1->from.reg = rn-NREG;
  14.532+	}
  14.533+	if(!f) {
  14.534+		p1->from = *a;
  14.535+		*a = zprog.from;
  14.536+		a->type = D_REG;
  14.537+		a->reg = rn;
  14.538+		if(rn >= NREG) {
  14.539+			a->type = D_FREG;
  14.540+			a->reg = rn-NREG;
  14.541+		}
  14.542+		if(v->etype == TUCHAR)
  14.543+			p1->as = AMOVBU;
  14.544+		if(v->etype == TUSHORT)
  14.545+			p1->as = AMOVHU;
  14.546+		if(v->etype == TUINT || v->etype == TULONG)
  14.547+			p1->as = AMOVWU;
  14.548+	}
  14.549+	if(debug['R'])
  14.550+		print("%P\t.a%P\n", p, p1);
  14.551+}
  14.552+
  14.553+Bits
  14.554+mkvar(Adr *a, int docon)
  14.555+{
  14.556+	Var *v;
  14.557+	int i, t, n, et, z;
  14.558+	long o;
  14.559+	Bits bit;
  14.560+	Sym *s;
  14.561+
  14.562+	t = a->type;
  14.563+	if(t == D_REG && a->reg != NREG)
  14.564+		regbits |= RtoB(a->reg);
  14.565+	if(t == D_FREG && a->reg != NREG)
  14.566+		regbits |= FtoB(a->reg);
  14.567+	s = a->sym;
  14.568+	o = a->offset;
  14.569+	et = a->etype;
  14.570+	if(s == S) {
  14.571+		if(t != D_CONST || !docon || a->reg != NREG)
  14.572+			goto none;
  14.573+		et = TLONG;
  14.574+	}
  14.575+	if(t == D_CONST) {
  14.576+		if(s == S && sval(o))
  14.577+			goto none;
  14.578+	}
  14.579+
  14.580+	n = a->name;
  14.581+	v = var;
  14.582+	for(i=0; i<nvar; i++) {
  14.583+		if(s == v->sym)
  14.584+		if(n == v->name)
  14.585+		if(o == v->offset)
  14.586+			goto out;
  14.587+		v++;
  14.588+	}
  14.589+	if(s)
  14.590+		if(s->name[0] == '.')
  14.591+			goto none;
  14.592+	if(nvar >= NVAR) {
  14.593+		if(debug['w'] > 1 && s)
  14.594+			warn(Z, "variable not optimized: %s", s->name);
  14.595+		goto none;
  14.596+	}
  14.597+	i = nvar;
  14.598+	nvar++;
  14.599+	v = &var[i];
  14.600+	v->sym = s;
  14.601+	v->offset = o;
  14.602+	v->etype = et;
  14.603+	v->name = n;
  14.604+	if(debug['R'])
  14.605+		print("bit=%2d et=%2d %D\n", i, et, a);
  14.606+out:
  14.607+	bit = blsh(i);
  14.608+	if(n == D_EXTERN || n == D_STATIC)
  14.609+		for(z=0; z<BITS; z++)
  14.610+			externs.b[z] |= bit.b[z];
  14.611+	if(n == D_PARAM)
  14.612+		for(z=0; z<BITS; z++)
  14.613+			params.b[z] |= bit.b[z];
  14.614+	if(v->etype != et || !(typechlpfd[et] || typev[et]))	/* funny punning */
  14.615+		for(z=0; z<BITS; z++)
  14.616+			addrs.b[z] |= bit.b[z];
  14.617+	if(t == D_CONST) {
  14.618+		if(s == S) {
  14.619+			for(z=0; z<BITS; z++)
  14.620+				consts.b[z] |= bit.b[z];
  14.621+			return bit;
  14.622+		}
  14.623+		if(et != TARRAY)
  14.624+			for(z=0; z<BITS; z++)
  14.625+				addrs.b[z] |= bit.b[z];
  14.626+		for(z=0; z<BITS; z++)
  14.627+			params.b[z] |= bit.b[z];
  14.628+		return bit;
  14.629+	}
  14.630+	if(t == D_OREG)
  14.631+		return bit;
  14.632+
  14.633+none:
  14.634+	return zbits;
  14.635+}
  14.636+
  14.637+void
  14.638+prop(Reg *r, Bits ref, Bits cal)
  14.639+{
  14.640+	Reg *r1, *r2;
  14.641+	int z;
  14.642+
  14.643+	for(r1 = r; r1 != R; r1 = r1->p1) {
  14.644+		for(z=0; z<BITS; z++) {
  14.645+			ref.b[z] |= r1->refahead.b[z];
  14.646+			if(ref.b[z] != r1->refahead.b[z]) {
  14.647+				r1->refahead.b[z] = ref.b[z];
  14.648+				change++;
  14.649+			}
  14.650+			cal.b[z] |= r1->calahead.b[z];
  14.651+			if(cal.b[z] != r1->calahead.b[z]) {
  14.652+				r1->calahead.b[z] = cal.b[z];
  14.653+				change++;
  14.654+			}
  14.655+		}
  14.656+		switch(r1->prog->as) {
  14.657+		case ABL:
  14.658+			for(z=0; z<BITS; z++) {
  14.659+				cal.b[z] |= ref.b[z] | externs.b[z];
  14.660+				ref.b[z] = 0;
  14.661+			}
  14.662+			break;
  14.663+
  14.664+		case ATEXT:
  14.665+			for(z=0; z<BITS; z++) {
  14.666+				cal.b[z] = 0;
  14.667+				ref.b[z] = 0;
  14.668+			}
  14.669+			break;
  14.670+
  14.671+		case ARET:
  14.672+		case ARETURN:
  14.673+			for(z=0; z<BITS; z++) {
  14.674+				cal.b[z] = externs.b[z];
  14.675+				ref.b[z] = 0;
  14.676+			}
  14.677+		}
  14.678+		for(z=0; z<BITS; z++) {
  14.679+			ref.b[z] = (ref.b[z] & ~r1->set.b[z]) |
  14.680+				r1->use1.b[z] | r1->use2.b[z];
  14.681+			cal.b[z] &= ~(r1->set.b[z] | r1->use1.b[z] | r1->use2.b[z]);
  14.682+			r1->refbehind.b[z] = ref.b[z];
  14.683+			r1->calbehind.b[z] = cal.b[z];
  14.684+		}
  14.685+		if(r1->active)
  14.686+			break;
  14.687+		r1->active = 1;
  14.688+	}
  14.689+	for(; r != r1; r = r->p1)
  14.690+		for(r2 = r->p2; r2 != R; r2 = r2->p2link)
  14.691+			prop(r2, r->refbehind, r->calbehind);
  14.692+}
  14.693+
  14.694+/*
  14.695+ * find looping structure
  14.696+ *
  14.697+ * 1) find reverse postordering
  14.698+ * 2) find approximate dominators,
  14.699+ *	the actual dominators if the flow graph is reducible
  14.700+ *	otherwise, dominators plus some other non-dominators.
  14.701+ *	See Matthew S. Hecht and Jeffrey D. Ullman,
  14.702+ *	"Analysis of a Simple Algorithm for Global Data Flow Problems",
  14.703+ *	Conf.  Record of ACM Symp. on Principles of Prog. Langs, Boston, Massachusetts,
  14.704+ *	Oct. 1-3, 1973, pp.  207-217.
  14.705+ * 3) find all nodes with a predecessor dominated by the current node.
  14.706+ *	such a node is a loop head.
  14.707+ *	recursively, all preds with a greater rpo number are in the loop
  14.708+ */
  14.709+long
  14.710+postorder(Reg *r, Reg **rpo2r, long n)
  14.711+{
  14.712+	Reg *r1;
  14.713+
  14.714+	r->rpo = 1;
  14.715+	r1 = r->s1;
  14.716+	if(r1 && !r1->rpo)
  14.717+		n = postorder(r1, rpo2r, n);
  14.718+	r1 = r->s2;
  14.719+	if(r1 && !r1->rpo)
  14.720+		n = postorder(r1, rpo2r, n);
  14.721+	rpo2r[n] = r;
  14.722+	n++;
  14.723+	return n;
  14.724+}
  14.725+
  14.726+long
  14.727+rpolca(long *idom, long rpo1, long rpo2)
  14.728+{
  14.729+	long t;
  14.730+
  14.731+	if(rpo1 == -1)
  14.732+		return rpo2;
  14.733+	while(rpo1 != rpo2){
  14.734+		if(rpo1 > rpo2){
  14.735+			t = rpo2;
  14.736+			rpo2 = rpo1;
  14.737+			rpo1 = t;
  14.738+		}
  14.739+		while(rpo1 < rpo2){
  14.740+			t = idom[rpo2];
  14.741+			if(t >= rpo2)
  14.742+				fatal(Z, "bad idom");
  14.743+			rpo2 = t;
  14.744+		}
  14.745+	}
  14.746+	return rpo1;
  14.747+}
  14.748+
  14.749+int
  14.750+doms(long *idom, long r, long s)
  14.751+{
  14.752+	while(s > r)
  14.753+		s = idom[s];
  14.754+	return s == r;
  14.755+}
  14.756+
  14.757+int
  14.758+loophead(long *idom, Reg *r)
  14.759+{
  14.760+	long src;
  14.761+
  14.762+	src = r->rpo;
  14.763+	if(r->p1 != R && doms(idom, src, r->p1->rpo))
  14.764+		return 1;
  14.765+	for(r = r->p2; r != R; r = r->p2link)
  14.766+		if(doms(idom, src, r->rpo))
  14.767+			return 1;
  14.768+	return 0;
  14.769+}
  14.770+
  14.771+void
  14.772+loopmark(Reg **rpo2r, long head, Reg *r)
  14.773+{
  14.774+	if(r->rpo < head || r->active == head)
  14.775+		return;
  14.776+	r->active = head;
  14.777+	r->loop += LOOP;
  14.778+	if(r->p1 != R)
  14.779+		loopmark(rpo2r, head, r->p1);
  14.780+	for(r = r->p2; r != R; r = r->p2link)
  14.781+		loopmark(rpo2r, head, r);
  14.782+}
  14.783+
  14.784+void
  14.785+loopit(Reg *r, long nr)
  14.786+{
  14.787+	Reg *r1;
  14.788+	long i, d, me;
  14.789+
  14.790+	if(nr > maxnr) {
  14.791+		rpo2r = alloc(nr * sizeof(Reg*));
  14.792+		idom = alloc(nr * sizeof(long));
  14.793+		maxnr = nr;
  14.794+	}
  14.795+
  14.796+	d = postorder(r, rpo2r, 0);
  14.797+	if(d > nr)
  14.798+		fatal(Z, "too many reg nodes");
  14.799+	nr = d;
  14.800+	for(i = 0; i < nr / 2; i++){
  14.801+		r1 = rpo2r[i];
  14.802+		rpo2r[i] = rpo2r[nr - 1 - i];
  14.803+		rpo2r[nr - 1 - i] = r1;
  14.804+	}
  14.805+	for(i = 0; i < nr; i++)
  14.806+		rpo2r[i]->rpo = i;
  14.807+
  14.808+	idom[0] = 0;
  14.809+	for(i = 0; i < nr; i++){
  14.810+		r1 = rpo2r[i];
  14.811+		me = r1->rpo;
  14.812+		d = -1;
  14.813+		if(r1->p1 != R && r1->p1->rpo < me)
  14.814+			d = r1->p1->rpo;
  14.815+		for(r1 = r1->p2; r1 != nil; r1 = r1->p2link)
  14.816+			if(r1->rpo < me)
  14.817+				d = rpolca(idom, d, r1->rpo);
  14.818+		idom[i] = d;
  14.819+	}
  14.820+
  14.821+	for(i = 0; i < nr; i++){
  14.822+		r1 = rpo2r[i];
  14.823+		r1->loop++;
  14.824+		if(r1->p2 != R && loophead(idom, r1))
  14.825+			loopmark(rpo2r, i, r1);
  14.826+	}
  14.827+}
  14.828+
  14.829+void
  14.830+synch(Reg *r, Bits dif)
  14.831+{
  14.832+	Reg *r1;
  14.833+	int z;
  14.834+
  14.835+	for(r1 = r; r1 != R; r1 = r1->s1) {
  14.836+		for(z=0; z<BITS; z++) {
  14.837+			dif.b[z] = (dif.b[z] &
  14.838+				~(~r1->refbehind.b[z] & r1->refahead.b[z])) |
  14.839+					r1->set.b[z] | r1->regdiff.b[z];
  14.840+			if(dif.b[z] != r1->regdiff.b[z]) {
  14.841+				r1->regdiff.b[z] = dif.b[z];
  14.842+				change++;
  14.843+			}
  14.844+		}
  14.845+		if(r1->active)
  14.846+			break;
  14.847+		r1->active = 1;
  14.848+		for(z=0; z<BITS; z++)
  14.849+			dif.b[z] &= ~(~r1->calbehind.b[z] & r1->calahead.b[z]);
  14.850+		if(r1->s2 != R)
  14.851+			synch(r1->s2, dif);
  14.852+	}
  14.853+}
  14.854+
  14.855+ulong
  14.856+allreg(ulong b, Rgn *r)
  14.857+{
  14.858+	Var *v;
  14.859+	int i;
  14.860+
  14.861+	v = var + r->varno;
  14.862+	r->regno = 0;
  14.863+	switch(v->etype) {
  14.864+
  14.865+	default:
  14.866+		diag(Z, "unknown etype %d/%d", bitno(b), v->etype);
  14.867+		break;
  14.868+
  14.869+	case TCHAR:
  14.870+	case TUCHAR:
  14.871+	case TSHORT:
  14.872+	case TUSHORT:
  14.873+	case TINT:
  14.874+	case TUINT:
  14.875+	case TLONG:
  14.876+	case TULONG:
  14.877+	case TIND:
  14.878+	case TVLONG:
  14.879+	case TUVLONG:
  14.880+	case TARRAY:
  14.881+		i = BtoR(~b);
  14.882+		if(i && r->cost > 0) {
  14.883+			r->regno = i;
  14.884+			return RtoB(i);
  14.885+		}
  14.886+		break;
  14.887+
  14.888+	case TDOUBLE:
  14.889+	case TFLOAT:
  14.890+		i = BtoF(~b);
  14.891+		if(i && r->cost > 0) {
  14.892+			r->regno = i+NREG;
  14.893+			return FtoB(i);
  14.894+		}
  14.895+		break;
  14.896+	}
  14.897+	return 0;
  14.898+}
  14.899+
  14.900+void
  14.901+paint1(Reg *r, int bn)
  14.902+{
  14.903+	Reg *r1;
  14.904+	Prog *p;
  14.905+	int z;
  14.906+	ulong bb;
  14.907+
  14.908+	z = bn/32;
  14.909+	bb = 1L<<(bn%32);
  14.910+	if(r->act.b[z] & bb)
  14.911+		return;
  14.912+	for(;;) {
  14.913+		if(!(r->refbehind.b[z] & bb))
  14.914+			break;
  14.915+		r1 = r->p1;
  14.916+		if(r1 == R)
  14.917+			break;
  14.918+		if(!(r1->refahead.b[z] & bb))
  14.919+			break;
  14.920+		if(r1->act.b[z] & bb)
  14.921+			break;
  14.922+		r = r1;
  14.923+	}
  14.924+
  14.925+	if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb) {
  14.926+		change -= CLOAD * r->loop;
  14.927+		if(debug['R'] && debug['v'])
  14.928+			print("%ld%P\tld %B $%d\n", r->loop,
  14.929+				r->prog, blsh(bn), change);
  14.930+	}
  14.931+	for(;;) {
  14.932+		r->act.b[z] |= bb;
  14.933+		p = r->prog;
  14.934+
  14.935+		if(r->use1.b[z] & bb) {
  14.936+			change += CREF * r->loop;
  14.937+			if(p->to.type == D_FREG && (p->as == AMOVW || p->as == AMOV))
  14.938+				change = -CINF;		/* cant go Rreg to Freg */
  14.939+			if(debug['R'] && debug['v'])
  14.940+				print("%ld%P\tu1 %B $%d\n", r->loop,
  14.941+					p, blsh(bn), change);
  14.942+		}
  14.943+
  14.944+		if((r->use2.b[z]|r->set.b[z]) & bb) {
  14.945+			change += CREF * r->loop;
  14.946+			if(p->from.type == D_FREG && (p->as == AMOVW || p->as == AMOV))
  14.947+				change = -CINF;		/* cant go Rreg to Freg */
  14.948+			if(debug['R'] && debug['v'])
  14.949+				print("%ld%P\tu2 %B $%d\n", r->loop,
  14.950+					p, blsh(bn), change);
  14.951+		}
  14.952+
  14.953+		if(STORE(r) & r->regdiff.b[z] & bb) {
  14.954+			change -= CLOAD * r->loop;
  14.955+			if(debug['R'] && debug['v'])
  14.956+				print("%ld%P\tst %B $%d\n", r->loop,
  14.957+					p, blsh(bn), change);
  14.958+		}
  14.959+
  14.960+		if(r->refbehind.b[z] & bb)
  14.961+			for(r1 = r->p2; r1 != R; r1 = r1->p2link)
  14.962+				if(r1->refahead.b[z] & bb)
  14.963+					paint1(r1, bn);
  14.964+
  14.965+		if(!(r->refahead.b[z] & bb))
  14.966+			break;
  14.967+		r1 = r->s2;
  14.968+		if(r1 != R)
  14.969+			if(r1->refbehind.b[z] & bb)
  14.970+				paint1(r1, bn);
  14.971+		r = r->s1;
  14.972+		if(r == R)
  14.973+			break;
  14.974+		if(r->act.b[z] & bb)
  14.975+			break;
  14.976+		if(!(r->refbehind.b[z] & bb))
  14.977+			break;
  14.978+	}
  14.979+}
  14.980+
  14.981+ulong
  14.982+paint2(Reg *r, int bn)
  14.983+{
  14.984+	Reg *r1;
  14.985+	int z;
  14.986+	ulong bb, vreg;
  14.987+
  14.988+	z = bn/32;
  14.989+	bb = 1L << (bn%32);
  14.990+	vreg = regbits;
  14.991+	if(!(r->act.b[z] & bb))
  14.992+		return vreg;
  14.993+	for(;;) {
  14.994+		if(!(r->refbehind.b[z] & bb))
  14.995+			break;
  14.996+		r1 = r->p1;
  14.997+		if(r1 == R)
  14.998+			break;
  14.999+		if(!(r1->refahead.b[z] & bb))
 14.1000+			break;
 14.1001+		if(!(r1->act.b[z] & bb))
 14.1002+			break;
 14.1003+		r = r1;
 14.1004+	}
 14.1005+	for(;;) {
 14.1006+		r->act.b[z] &= ~bb;
 14.1007+
 14.1008+		vreg |= r->regu;
 14.1009+
 14.1010+		if(r->refbehind.b[z] & bb)
 14.1011+			for(r1 = r->p2; r1 != R; r1 = r1->p2link)
 14.1012+				if(r1->refahead.b[z] & bb)
 14.1013+					vreg |= paint2(r1, bn);
 14.1014+
 14.1015+		if(!(r->refahead.b[z] & bb))
 14.1016+			break;
 14.1017+		r1 = r->s2;
 14.1018+		if(r1 != R)
 14.1019+			if(r1->refbehind.b[z] & bb)
 14.1020+				vreg |= paint2(r1, bn);
 14.1021+		r = r->s1;
 14.1022+		if(r == R)
 14.1023+			break;
 14.1024+		if(!(r->act.b[z] & bb))
 14.1025+			break;
 14.1026+		if(!(r->refbehind.b[z] & bb))
 14.1027+			break;
 14.1028+	}
 14.1029+	return vreg;
 14.1030+}
 14.1031+
 14.1032+void
 14.1033+paint3(Reg *r, int bn, long rb, int rn)
 14.1034+{
 14.1035+	Reg *r1;
 14.1036+	Prog *p;
 14.1037+	int z;
 14.1038+	ulong bb;
 14.1039+
 14.1040+	z = bn/32;
 14.1041+	bb = 1L << (bn%32);
 14.1042+	if(r->act.b[z] & bb)
 14.1043+		return;
 14.1044+	for(;;) {
 14.1045+		if(!(r->refbehind.b[z] & bb))
 14.1046+			break;
 14.1047+		r1 = r->p1;
 14.1048+		if(r1 == R)
 14.1049+			break;
 14.1050+		if(!(r1->refahead.b[z] & bb))
 14.1051+			break;
 14.1052+		if(r1->act.b[z] & bb)
 14.1053+			break;
 14.1054+		r = r1;
 14.1055+	}
 14.1056+
 14.1057+	if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb)
 14.1058+		addmove(r, bn, rn, 0);
 14.1059+	for(;;) {
 14.1060+		r->act.b[z] |= bb;
 14.1061+		p = r->prog;
 14.1062+
 14.1063+		if(r->use1.b[z] & bb) {
 14.1064+			if(debug['R'])
 14.1065+				print("%P", p);
 14.1066+			addreg(&p->from, rn);
 14.1067+			if(debug['R'])
 14.1068+				print("\t.c%P\n", p);
 14.1069+		}
 14.1070+		if((r->use2.b[z]|r->set.b[z]) & bb) {
 14.1071+			if(debug['R'])
 14.1072+				print("%P", p);
 14.1073+			addreg(&p->to, rn);
 14.1074+			if(debug['R'])
 14.1075+				print("\t.c%P\n", p);
 14.1076+		}
 14.1077+
 14.1078+		if(STORE(r) & r->regdiff.b[z] & bb)
 14.1079+			addmove(r, bn, rn, 1);
 14.1080+		r->regu |= rb;
 14.1081+
 14.1082+		if(r->refbehind.b[z] & bb)
 14.1083+			for(r1 = r->p2; r1 != R; r1 = r1->p2link)
 14.1084+				if(r1->refahead.b[z] & bb)
 14.1085+					paint3(r1, bn, rb, rn);
 14.1086+
 14.1087+		if(!(r->refahead.b[z] & bb))
 14.1088+			break;
 14.1089+		r1 = r->s2;
 14.1090+		if(r1 != R)
 14.1091+			if(r1->refbehind.b[z] & bb)
 14.1092+				paint3(r1, bn, rb, rn);
 14.1093+		r = r->s1;
 14.1094+		if(r == R)
 14.1095+			break;
 14.1096+		if(r->act.b[z] & bb)
 14.1097+			break;
 14.1098+		if(!(r->refbehind.b[z] & bb))
 14.1099+			break;
 14.1100+	}
 14.1101+}
 14.1102+
 14.1103+void
 14.1104+addreg(Adr *a, int rn)
 14.1105+{
 14.1106+
 14.1107+	a->sym = 0;
 14.1108+	a->name = D_NONE;
 14.1109+	a->type = D_REG;
 14.1110+	a->reg = rn;
 14.1111+	if(rn >= NREG) {
 14.1112+		a->type = D_FREG;
 14.1113+		a->reg = rn-NREG;
 14.1114+	}
 14.1115+}
 14.1116+
 14.1117+/*
 14.1118+ *	bit	reg
 14.1119+ *	0	R9
 14.1120+ *	1	R10
 14.1121+ *	...	...
 14.1122+ *	6	R15
 14.1123+ */
 14.1124+long
 14.1125+RtoB(int r)
 14.1126+{
 14.1127+	if(r >= REGMIN && r <= REGMAX)
 14.1128+		return 1L << (r-REGMIN);
 14.1129+	return 0;
 14.1130+}
 14.1131+
 14.1132+int
 14.1133+BtoR(long b)
 14.1134+{
 14.1135+	b &= 0x07fL;
 14.1136+	if(b == 0)
 14.1137+		return 0;
 14.1138+	return bitno(b) + REGMIN;
 14.1139+}
 14.1140+
 14.1141+/*
 14.1142+ *	bit	reg
 14.1143+ *	22	F7
 14.1144+ *	23	F8
 14.1145+ *	...	...
 14.1146+ *	29	F14
 14.1147+ */
 14.1148+long
 14.1149+FtoB(int f)
 14.1150+{
 14.1151+	if(f < FREGMIN || f > FREGEXT)
 14.1152+		return 0;
 14.1153+	return 1L << (f - FREGMIN + 22);
 14.1154+}
 14.1155+
 14.1156+int
 14.1157+BtoF(long b)
 14.1158+{
 14.1159+
 14.1160+	b &= 0x3fc00000L;
 14.1161+	if(b == 0)
 14.1162+		return 0;
 14.1163+	return bitno(b) - 22 + FREGMIN;
 14.1164+}
    15.1new file mode 100644
    15.2--- /dev/null
    15.3+++ b/sys/src/cmd/7c/sgen.c
    15.4@@ -0,0 +1,247 @@
    15.5+#include "gc.h"
    15.6+
    15.7+void
    15.8+noretval(int n)
    15.9+{
   15.10+
   15.11+	if(n & 1) {
   15.12+		gins(ANOP, Z, Z);
   15.13+		p->to.type = D_REG;
   15.14+		p->to.reg = REGRET;
   15.15+	}
   15.16+	if(n & 2) {
   15.17+		gins(ANOP, Z, Z);
   15.18+		p->to.type = D_FREG;
   15.19+		p->to.reg = FREGRET;
   15.20+	}
   15.21+}
   15.22+
   15.23+/*
   15.24+ *	calculate addressability as follows
   15.25+ *		CONST ==> 20		$value
   15.26+ *		NAME ==> 10		name
   15.27+ *		REGISTER ==> 11		register
   15.28+ *		INDREG ==> 12		*[(reg)+offset]
   15.29+ *		&10 ==> 2		$name
   15.30+ *		ADD(2, 20) ==> 2	$name+offset
   15.31+ *		ADD(3, 20) ==> 3	$(reg)+offset
   15.32+ *		&12 ==> 3		$(reg)+offset
   15.33+ *		*11 ==> 11		??
   15.34+ *		*2 ==> 10		name
   15.35+ *		*3 ==> 12		*(reg)+offset
   15.36+ *	calculate complexity (number of registers)
   15.37+ */
   15.38+void
   15.39+xcom(Node *n)
   15.40+{
   15.41+	Node *l, *r;
   15.42+	int t;
   15.43+
   15.44+	if(n == Z)
   15.45+		return;
   15.46+	l = n->left;
   15.47+	r = n->right;
   15.48+	n->addable = 0;
   15.49+	n->complex = 0;
   15.50+	switch(n->op) {
   15.51+	case OCONST:
   15.52+		n->addable = 20;
   15.53+		return;
   15.54+
   15.55+	case OREGISTER:
   15.56+		n->addable = 11;
   15.57+		return;
   15.58+
   15.59+	case OINDREG:
   15.60+		n->addable = 12;
   15.61+		return;
   15.62+
   15.63+	case ONAME:
   15.64+		n->addable = 10;
   15.65+		return;
   15.66+
   15.67+	case OADDR:
   15.68+		xcom(l);
   15.69+		if(l->addable == 10)
   15.70+			n->addable = 2;
   15.71+		if(l->addable == 12)
   15.72+			n->addable = 3;
   15.73+		break;
   15.74+
   15.75+	case OIND:
   15.76+		xcom(l);
   15.77+		if(l->addable == 11)
   15.78+			n->addable = 12;
   15.79+		if(l->addable == 3)
   15.80+			n->addable = 12;
   15.81+		if(l->addable == 2)
   15.82+			n->addable = 10;
   15.83+		break;
   15.84+
   15.85+	case OADD:
   15.86+		xcom(l);
   15.87+		xcom(r);
   15.88+		if(l->addable == 20) {
   15.89+			if(r->addable == 2)
   15.90+				n->addable = 2;
   15.91+			if(r->addable == 3)
   15.92+				n->addable = 3;
   15.93+		}
   15.94+		if(r->addable == 20) {
   15.95+			if(l->addable == 2)
   15.96+				n->addable = 2;
   15.97+			if(l->addable == 3)
   15.98+				n->addable = 3;
   15.99+		}
  15.100+		break;
  15.101+
  15.102+	case OASMUL:
  15.103+	case OASLMUL:
  15.104+		xcom(l);
  15.105+		xcom(r);
  15.106+		t = vlog(r);
  15.107+		if(t >= 0) {
  15.108+			n->op = OASASHL;
  15.109+			r->vconst = t;
  15.110+			r->type = types[TINT];
  15.111+		}
  15.112+		break;
  15.113+
  15.114+	case OMUL:
  15.115+	case OLMUL:
  15.116+		xcom(l);
  15.117+		xcom(r);
  15.118+		t = vlog(r);
  15.119+		if(t >= 0) {
  15.120+			n->op = OASHL;
  15.121+			r->vconst = t;
  15.122+			r->type = types[TINT];
  15.123+		}
  15.124+		t = vlog(l);
  15.125+		if(t >= 0) {
  15.126+			n->op = OASHL;
  15.127+			n->left = r;
  15.128+			n->right = l;
  15.129+			r = l;
  15.130+			l = n->left;
  15.131+			r->vconst = t;
  15.132+			r->type = types[TINT];
  15.133+			simplifyshift(n);
  15.134+		}
  15.135+		break;
  15.136+
  15.137+	case OASLDIV:
  15.138+		xcom(l);
  15.139+		xcom(r);
  15.140+		t = vlog(r);
  15.141+		if(t >= 0) {
  15.142+			n->op = OASLSHR;
  15.143+			r->vconst = t;
  15.144+			r->type = types[TINT];
  15.145+		}
  15.146+		break;
  15.147+
  15.148+	case OLDIV:
  15.149+		xcom(l);
  15.150+		xcom(r);
  15.151+		t = vlog(r);
  15.152+		if(t >= 0) {
  15.153+			n->op = OLSHR;
  15.154+			r->vconst = t;
  15.155+			r->type = types[TINT];
  15.156+			simplifyshift(n);
  15.157+		}
  15.158+		break;
  15.159+
  15.160+	case OASLMOD:
  15.161+		xcom(l);
  15.162+		xcom(r);
  15.163+		t = vlog(r);
  15.164+		if(t >= 0) {
  15.165+			n->op = OASAND;
  15.166+			r->vconst--;
  15.167+		}
  15.168+		break;
  15.169+
  15.170+	case OLMOD:
  15.171+		xcom(l);
  15.172+		xcom(r);
  15.173+		t = vlog(r);
  15.174+		if(t >= 0) {
  15.175+			n->op = OAND;
  15.176+			r->vconst--;
  15.177+		}
  15.178+		break;
  15.179+
  15.180+	case OLSHR:
  15.181+	case OASHL:
  15.182+	case OASHR:
  15.183+		xcom(l);
  15.184+		xcom(r);
  15.185+		simplifyshift(n);
  15.186+		break;
  15.187+
  15.188+	default:
  15.189+		if(l != Z)
  15.190+			xcom(l);
  15.191+		if(r != Z)
  15.192+			xcom(r);
  15.193+		break;
  15.194+	}
  15.195+	if(n->addable >= 10)
  15.196+		return;
  15.197+
  15.198+	if(l != Z)
  15.199+		n->complex = l->complex;
  15.200+	if(r != Z) {
  15.201+		if(r->complex == n->complex)
  15.202+			n->complex = r->complex+1;
  15.203+		else
  15.204+		if(r->complex > n->complex)
  15.205+			n->complex = r->complex;
  15.206+	}
  15.207+	if(n->complex == 0)
  15.208+		n->complex++;
  15.209+
  15.210+//	if(com64(n))
  15.211+//		return;
  15.212+
  15.213+	switch(n->op) {
  15.214+	case OFUNC:
  15.215+		n->complex = FNX;
  15.216+		break;
  15.217+
  15.218+	case OEQ:
  15.219+	case ONE:
  15.220+	case OLE:
  15.221+	case OLT:
  15.222+	case OGE:
  15.223+	case OGT:
  15.224+	case OHI:
  15.225+	case OHS:
  15.226+	case OLO:
  15.227+	case OLS:
  15.228+		/*
  15.229+		 * immediate operators, make const on right
  15.230+		 */
  15.231+		if(l->op == OCONST) {
  15.232+			n->left = r;
  15.233+			n->right = l;
  15.234+			n->op = invrel[relindex(n->op)];
  15.235+		}
  15.236+		break;
  15.237+
  15.238+	case OADD:
  15.239+	case OXOR:
  15.240+	case OAND:
  15.241+	case OOR:
  15.242+		/*
  15.243+		 * immediate operators, make const on right
  15.244+		 */
  15.245+		if(l->op == OCONST) {
  15.246+			n->left = r;
  15.247+			n->right = l;
  15.248+		}
  15.249+		break;
  15.250+	}
  15.251+}
    16.1new file mode 100644
    16.2--- /dev/null
    16.3+++ b/sys/src/cmd/7c/swt.c
    16.4@@ -0,0 +1,654 @@
    16.5+#include "gc.h"
    16.6+
    16.7+void
    16.8+swit1(C1 *q, int nc, long def, Node *n)
    16.9+{
   16.10+	Node tn;
   16.11+	
   16.12+	regalloc(&tn, &regnode, Z);
   16.13+	swit2(q, nc, def, n, &tn);
   16.14+	regfree(&tn);
   16.15+}
   16.16+
   16.17+void
   16.18+swit2(C1 *q, int nc, long def, Node *n, Node *tn)
   16.19+{
   16.20+	C1 *r;
   16.21+	int i;
   16.22+	long v;
   16.23+	Prog *sp;
   16.24+
   16.25+	if(nc >= 3) {
   16.26+		i = (q+nc-1)->val - (q+0)->val;
   16.27+		if(i > 0 && i < nc*2)
   16.28+			goto direct;
   16.29+	}
   16.30+	if(nc < 5) {
   16.31+		for(i=0; i<nc; i++) {
   16.32+			if(debug['K'])
   16.33+				print("case = %.8llux\n", q->val);
   16.34+			gopcode(OEQ, nodconst(q->val), n, Z);
   16.35+			patch(p, q->label);
   16.36+			q++;
   16.37+		}
   16.38+		gbranch(OGOTO);
   16.39+		patch(p, def);
   16.40+		return;
   16.41+	}
   16.42+
   16.43+	i = nc / 2;
   16.44+	r = q+i;
   16.45+	if(debug['K'])
   16.46+		print("case > %.8llux\n", r->val);
   16.47+	gopcode(OGT, nodconst(r->val), n, Z);
   16.48+	sp = p;
   16.49+	gopcode(OEQ, nodconst(r->val), n, Z);	/* just gen the B.EQ */
   16.50+	patch(p, r->label);
   16.51+	swit2(q, i, def, n, tn);
   16.52+
   16.53+	if(debug['K'])
   16.54+		print("case < %.8llux\n", r->val);
   16.55+	patch(sp, pc);
   16.56+	swit2(r+1, nc-i-1, def, n, tn);
   16.57+	return;
   16.58+
   16.59+direct:
   16.60+	v = q->val;
   16.61+	if(v != 0)
   16.62+		gopcode(OSUB, nodconst(v), Z, n);
   16.63+	gopcode(OHI, nodconst((q+nc-1)->val - v), n, Z);
   16.64+	patch(p, def);
   16.65+	gopcode(OCASE, n, Z, tn);
   16.66+	for(i=0; i<nc; i++) {
   16.67+		if(debug['K'])
   16.68+			print("case = %.8llux\n", q->val);
   16.69+		while(q->val != v) {
   16.70+			nextpc();
   16.71+			p->as = ABCASE;
   16.72+			patch(p, def);
   16.73+			v++;
   16.74+		}
   16.75+		nextpc();
   16.76+		p->as = ABCASE;
   16.77+		patch(p, q->label);
   16.78+		q++;
   16.79+		v++;
   16.80+	}
   16.81+	gbranch(OGOTO);		/* so that regopt() won't be confused */
   16.82+	patch(p, def);
   16.83+}
   16.84+
   16.85+void
   16.86+bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
   16.87+{
   16.88+	int sh;
   16.89+	long v;
   16.90+	Node *l;
   16.91+
   16.92+	/*
   16.93+	 * n1 gets adjusted/masked value
   16.94+	 * n2 gets address of cell
   16.95+	 * n3 gets contents of cell
   16.96+	 */
   16.97+	l = b->left;
   16.98+	if(n2 != Z) {
   16.99+		regalloc(n1, l, nn);
  16.100+		reglcgen(n2, l, Z);
  16.101+		regalloc(n3, l, Z);
  16.102+		gopcode(OAS, n2, Z, n3);
  16.103+		gopcode(OAS, n3, Z, n1);
  16.104+	} else {
  16.105+		regalloc(n1, l, nn);
  16.106+		cgen(l, n1);
  16.107+	}
  16.108+	if(b->type->shift == 0 && typeu[b->type->etype]) {
  16.109+		v = ~0 + (1L << b->type->nbits);
  16.110+		gopcode(OAND, nodconst(v), Z, n1);
  16.111+	} else {
  16.112+		sh = 32 - b->type->shift - b->type->nbits;
  16.113+		if(sh > 0)
  16.114+			gopcode(OASHL, nodconst(sh), Z, n1);
  16.115+		sh += b->type->shift;
  16.116+		if(sh > 0)
  16.117+			if(typeu[b->type->etype])
  16.118+				gopcode(OLSHR, nodconst(sh), Z, n1);
  16.119+			else
  16.120+				gopcode(OASHR, nodconst(sh), Z, n1);
  16.121+	}
  16.122+}
  16.123+
  16.124+void
  16.125+bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
  16.126+{
  16.127+	long v;
  16.128+	Node nod, *l;
  16.129+	int sh;
  16.130+
  16.131+	/*
  16.132+	 * n1 has adjusted/masked value
  16.133+	 * n2 has address of cell
  16.134+	 * n3 has contents of cell
  16.135+	 */
  16.136+	l = b->left;
  16.137+	regalloc(&nod, l, Z);
  16.138+	v = ~0 + (1L << b->type->nbits);
  16.139+	gopcode(OAND, nodconst(v), Z, n1);
  16.140+	gopcode(OAS, n1, Z, &nod);
  16.141+	if(nn != Z)
  16.142+		gopcode(OAS, n1, Z, nn);
  16.143+	sh = b->type->shift;
  16.144+	if(sh > 0)
  16.145+		gopcode(OASHL, nodconst(sh), Z, &nod);
  16.146+	v <<= sh;
  16.147+	gopcode(OAND, nodconst(~v), Z, n3);
  16.148+	gopcode(OOR, n3, Z, &nod);
  16.149+	gopcode(OAS, &nod, Z, n2);
  16.150+
  16.151+	regfree(&nod);
  16.152+	regfree(n1);
  16.153+	regfree(n2);
  16.154+	regfree(n3);
  16.155+}
  16.156+
  16.157+long
  16.158+outstring(char *s, long n)
  16.159+{
  16.160+	long r;
  16.161+
  16.162+	if(suppress)
  16.163+		return nstring;
  16.164+	r = nstring;
  16.165+	while(n) {
  16.166+		string[mnstring] = *s++;
  16.167+		mnstring++;
  16.168+		nstring++;
  16.169+		if(mnstring >= NSNAME) {
  16.170+			gpseudo(ADATA, symstring, nodconst(0L));
  16.171+			p->from.offset += nstring - NSNAME;
  16.172+			p->reg = NSNAME;
  16.173+			p->to.type = D_SCONST;
  16.174+			memmove(p->to.sval, string, NSNAME);
  16.175+			mnstring = 0;
  16.176+		}
  16.177+		n--;
  16.178+	}
  16.179+	return r;
  16.180+}
  16.181+
  16.182+int
  16.183+mulcon(Node *n, Node *nn)
  16.184+{
  16.185+	Node *l, *r, nod1, nod2;
  16.186+	Multab *m;
  16.187+	long v, vs;
  16.188+	int o;
  16.189+	char code[sizeof(m->code)+2], *p;
  16.190+
  16.191+	if(typefd[n->type->etype])
  16.192+		return 0;
  16.193+	l = n->left;
  16.194+	r = n->right;
  16.195+	if(l->op == OCONST) {
  16.196+		l = r;
  16.197+		r = n->left;
  16.198+	}
  16.199+	if(r->op != OCONST)
  16.200+		return 0;
  16.201+	v = convvtox(r->vconst, n->type->etype);
  16.202+	if(v != r->vconst) {
  16.203+		if(debug['M'])
  16.204+			print("%L multiply conv: %lld\n", n->lineno, r->vconst);
  16.205+		return 0;
  16.206+	}
  16.207+	m = mulcon0(v);
  16.208+	if(!m) {
  16.209+		if(debug['M'])
  16.210+			print("%L multiply table: %lld\n", n->lineno, r->vconst);
  16.211+		return 0;
  16.212+	}
  16.213+	if(debug['M'] && debug['v'])
  16.214+		print("%L multiply: %ld\n", n->lineno, v);
  16.215+
  16.216+	memmove(code, m->code, sizeof(m->code));
  16.217+	code[sizeof(m->code)] = 0;
  16.218+
  16.219+	p = code;
  16.220+	if(p[1] == 'i')
  16.221+		p += 2;
  16.222+	regalloc(&nod1, n, nn);
  16.223+	cgen(l, &nod1);
  16.224+	vs = v;
  16.225+	regalloc(&nod2, n, Z);
  16.226+
  16.227+loop:
  16.228+	switch(*p) {
  16.229+	case 0:
  16.230+		regfree(&nod2);
  16.231+		if(vs < 0) {
  16.232+			gopcode(OAS, &nod1, Z, &nod1);
  16.233+			gopcode(ONEG, &nod1, Z, nn);
  16.234+		} else 
  16.235+			gopcode(OAS, &nod1, Z, nn);
  16.236+		regfree(&nod1);
  16.237+		return 1;
  16.238+	case '+':
  16.239+		o = OADD;
  16.240+		goto addsub;
  16.241+	case '-':
  16.242+		o = OSUB;
  16.243+	addsub:	/* number is r,n,l */
  16.244+		v = p[1] - '0';
  16.245+		r = &nod1;
  16.246+		if(v&4)
  16.247+			r = &nod2;
  16.248+		n = &nod1;
  16.249+		if(v&2)
  16.250+			n = &nod2;
  16.251+		l = &nod1;
  16.252+		if(v&1)
  16.253+			l = &nod2;
  16.254+		gopcode(o, l, n, r);
  16.255+		break;
  16.256+	default: /* op is shiftcount, number is r,l */
  16.257+		v = p[1] - '0';
  16.258+		r = &nod1;
  16.259+		if(v&2)
  16.260+			r = &nod2;
  16.261+		l = &nod1;
  16.262+		if(v&1)
  16.263+			l = &nod2;
  16.264+		v = *p - 'a';
  16.265+		if(v < 0 || v >= 32) {
  16.266+			diag(n, "mulcon unknown op: %c%c", p[0], p[1]);
  16.267+			break;
  16.268+		}
  16.269+		gopcode(OASHL, nodconst(v), l, r);
  16.270+		break;
  16.271+	}
  16.272+	p += 2;
  16.273+	goto loop;
  16.274+}
  16.275+
  16.276+void
  16.277+gextern(Sym *s, Node *a, long o, long w)
  16.278+{
  16.279+
  16.280+	if(a->op == OCONST && typev[a->type->etype]) {
  16.281+		if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
  16.282+			gpseudo(ADATA, s, nod32const(a->vconst>>32));
  16.283+		else
  16.284+			gpseudo(ADATA, s, nod32const(a->vconst));
  16.285+		p->from.offset += o;
  16.286+		p->reg = 4;
  16.287+		if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
  16.288+			gpseudo(ADATA, s, nod32const(a->vconst));
  16.289+		else
  16.290+			gpseudo(ADATA, s, nod32const(a->vconst>>32));
  16.291+		p->from.offset += o + 4;
  16.292+		p->reg = 4;
  16.293+		return;
  16.294+	}
  16.295+	gpseudo(ADATA, s, a);
  16.296+	p->from.offset += o;
  16.297+	p->reg = w;
  16.298+	if(p->to.type == D_OREG)
  16.299+		p->to.type = D_CONST;
  16.300+}
  16.301+
  16.302+void	zname(Biobuf*, Sym*, int);
  16.303+char*	zaddr(char*, Adr*, int);
  16.304+void	zwrite(Biobuf*, Prog*, int, int);
  16.305+void	outhist(Biobuf*);
  16.306+
  16.307+void
  16.308+zwrite(Biobuf *b, Prog *p, int sf, int st)
  16.309+{
  16.310+	char bf[100], *bp;
  16.311+	long l;
  16.312+
  16.313+	bf[0] = p->as;
  16.314+	bf[1] = p->as>>8;
  16.315+	bf[2] = p->reg;
  16.316+	l = p->lineno;
  16.317+	bf[3] = l;
  16.318+	bf[4] = l>>8;
  16.319+	bf[5] = l>>16;
  16.320+	bf[6] = l>>24;
  16.321+	bp = zaddr(bf+7, &p->from, sf);
  16.322+	bp = zaddr(bp, &p->to, st);
  16.323+	Bwrite(b, bf, bp-bf);
  16.324+}
  16.325+
  16.326+void
  16.327+outcode(void)
  16.328+{
  16.329+	struct { Sym *sym; short type; } h[NSYM];
  16.330+	Prog *p;
  16.331+	Sym *s;
  16.332+	int sf, st, t, sym;
  16.333+
  16.334+	if(debug['S']) {
  16.335+		for(p = firstp; p != P; p = p->link)
  16.336+			if(p->as != ADATA && p->as != AGLOBL)
  16.337+				pc--;
  16.338+		for(p = firstp; p != P; p = p->link) {
  16.339+			print("%P\n", p);
  16.340+			if(p->as != ADATA && p->as != AGLOBL)
  16.341+				pc++;
  16.342+		}
  16.343+	}
  16.344+	outhist(&outbuf);
  16.345+	for(sym=0; sym<NSYM; sym++) {
  16.346+		h[sym].sym = S;
  16.347+		h[sym].type = 0;
  16.348+	}
  16.349+	sym = 1;
  16.350+	for(p = firstp; p != P; p = p->link) {
  16.351+	jackpot:
  16.352+		sf = 0;
  16.353+		s = p->from.sym;
  16.354+		while(s != S) {
  16.355+			sf = s->sym;
  16.356+			if(sf < 0 || sf >= NSYM)
  16.357+				sf = 0;
  16.358+			t = p->from.name;
  16.359+			if(h[sf].type == t)
  16.360+			if(h[sf].sym == s)
  16.361+				break;
  16.362+			s->sym = sym;
  16.363+			zname(&outbuf, s, t);
  16.364+			h[sym].sym = s;
  16.365+			h[sym].type = t;
  16.366+			sf = sym;
  16.367+			sym++;
  16.368+			if(sym >= NSYM)
  16.369+				sym = 1;
  16.370+			break;
  16.371+		}
  16.372+		st = 0;
  16.373+		s = p->to.sym;
  16.374+		while(s != S) {
  16.375+			st = s->sym;
  16.376+			if(st < 0 || st >= NSYM)
  16.377+				st = 0;
  16.378+			t = p->to.name;
  16.379+			if(h[st].type == t)
  16.380+			if(h[st].sym == s)
  16.381+				break;
  16.382+			s->sym = sym;
  16.383+			zname(&outbuf, s, t);
  16.384+			h[sym].sym = s;
  16.385+			h[sym].type = t;
  16.386+			st = sym;
  16.387+			sym++;
  16.388+			if(sym >= NSYM)
  16.389+				sym = 1;
  16.390+			if(st == sf)
  16.391+				goto jackpot;
  16.392+			break;
  16.393+		}
  16.394+		zwrite(&outbuf, p, sf, st);
  16.395+	}
  16.396+	firstp = P;
  16.397+	lastp = P;
  16.398+}
  16.399+
  16.400+void
  16.401+outhist(Biobuf *b)
  16.402+{
  16.403+	Hist *h;
  16.404+	char *p, *q, *op, c;
  16.405+	Prog pg;
  16.406+	int n;
  16.407+
  16.408+	pg = zprog;
  16.409+	pg.as = AHISTORY;
  16.410+	c = pathchar();
  16.411+	for(h = hist; h != H; h = h->link) {
  16.412+		p = h->name;
  16.413+		op = 0;
  16.414+		/* on windows skip drive specifier in pathname */
  16.415+		if(systemtype(Windows) && p && p[1] == ':'){
  16.416+			p += 2;
  16.417+			c = *p;
  16.418+		}
  16.419+		if(p && p[0] != c && h->offset == 0 && pathname){
  16.420+			/* on windows skip drive specifier in pathname */
  16.421+			if(systemtype(Windows) && pathname[1] == ':') {
  16.422+				op = p;
  16.423+				p = pathname+2;
  16.424+				c = *p;
  16.425+			} else if(pathname[0] == c){
  16.426+				op = p;
  16.427+				p = pathname;
  16.428+			}
  16.429+		}
  16.430+		while(p) {
  16.431+			q = utfrune(p, c);
  16.432+			if(q) {
  16.433+				n = q-p;
  16.434+				if(n == 0){
  16.435+					n = 1;	/* leading "/" */
  16.436+					*p = '/';	/* don't emit "\" on windows */
  16.437+				}
  16.438+				q++;
  16.439+			} else {
  16.440+				n = strlen(p);
  16.441+				q = 0;
  16.442+			}
  16.443+			if(n) {
  16.444+				Bputc(b, ANAME);
  16.445+				Bputc(b, ANAME>>8);
  16.446+				Bputc(b, D_FILE);
  16.447+				Bputc(b, 1);
  16.448+				Bputc(b, '<');
  16.449+				Bwrite(b, p, n);
  16.450+				Bputc(b, 0);
  16.451+			}
  16.452+			p = q;
  16.453+			if(p == 0 && op) {
  16.454+				p = op;
  16.455+				op = 0;
  16.456+			}
  16.457+		}
  16.458+		pg.lineno = h->line;
  16.459+		pg.to.type = zprog.to.type;
  16.460+		pg.to.offset = h->offset;
  16.461+		if(h->offset)
  16.462+			pg.to.type = D_CONST;
  16.463+
  16.464+		zwrite(b, &pg, 0, 0);
  16.465+	}
  16.466+}
  16.467+
  16.468+void
  16.469+zname(Biobuf *b, Sym *s, int t)
  16.470+{
  16.471+	char *n, bf[8];
  16.472+	ulong sig;
  16.473+
  16.474+	n = s->name;
  16.475+	if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){
  16.476+		sig = sign(s);
  16.477+		bf[0] = ASIGNAME;
  16.478+		bf[1] = ASIGNAME>>8;
  16.479+		bf[2] = sig;
  16.480+		bf[3] = sig>>8;
  16.481+		bf[4] = sig>>16;
  16.482+		bf[5] = sig>>24;
  16.483+		bf[6] = t;
  16.484+		bf[7] = s->sym;
  16.485+		Bwrite(b, bf, 8);
  16.486+		s->sig = SIGDONE;
  16.487+	}
  16.488+	else{
  16.489+		bf[0] = ANAME;
  16.490+		bf[1] = ANAME>>8;
  16.491+		bf[2] = t;	/* type */
  16.492+		bf[3] = s->sym;	/* sym */
  16.493+		Bwrite(b, bf, 4);
  16.494+	}
  16.495+	Bwrite(b, n, strlen(n)+1);
  16.496+}
  16.497+
  16.498+char*
  16.499+zaddr(char *bp, Adr *a, int s)
  16.500+{
  16.501+	long l;
  16.502+	Ieee e;
  16.503+
  16.504+	if(a->type == D_CONST){
  16.505+		l = a->offset;
  16.506+		if((vlong)l != a->offset)
  16.507+			a->type = D_DCONST;
  16.508+	}
  16.509+	bp[0] = a->type;
  16.510+	bp[1] = a->reg;
  16.511+	bp[2] = s;
  16.512+	bp[3] = a->name;
  16.513+	bp += 4;
  16.514+	switch(a->type) {
  16.515+	default:
  16.516+		diag(Z, "unknown type %d in zaddr", a->type);
  16.517+
  16.518+	case D_NONE:
  16.519+	case D_REG:
  16.520+	case D_SP:
  16.521+	case D_FREG:
  16.522+	case D_VREG:
  16.523+		break;
  16.524+
  16.525+	case D_PAIR:
  16.526+		*bp++ = a->offset;
  16.527+		break;
  16.528+
  16.529+	case D_OREG:
  16.530+	case D_XPRE:
  16.531+	case D_XPOST:
  16.532+	case D_CONST:
  16.533+	case D_BRANCH:
  16.534+	case D_SHIFT:
  16.535+	case D_EXTREG:
  16.536+	case D_SPR:
  16.537+		l = a->offset;
  16.538+		bp[0] = l;
  16.539+		bp[1] = l>>8;
  16.540+		bp[2] = l>>16;
  16.541+		bp[3] = l>>24;
  16.542+		bp += 4;
  16.543+		break;
  16.544+
  16.545+	case D_DCONST:
  16.546+		l = a->offset;
  16.547+		bp[0] = l;
  16.548+		bp[1] = l>>8;
  16.549+		bp[2] = l>>16;
  16.550+		bp[3] = l>>24;
  16.551+		bp += 4;
  16.552+		l = a->offset>>32;
  16.553+		bp[0] = l;
  16.554+		bp[1] = l>>8;
  16.555+		bp[2] = l>>16;
  16.556+		bp[3] = l>>24;
  16.557+		bp += 4;
  16.558+		break;
  16.559+
  16.560+	case D_SCONST:
  16.561+		memmove(bp, a->sval, NSNAME);
  16.562+		bp += NSNAME;
  16.563+		break;
  16.564+
  16.565+	case D_FCONST:
  16.566+		ieeedtod(&e, a->dval);
  16.567+		l = e.l;
  16.568+		bp[0] = l;
  16.569+		bp[1] = l>>8;
  16.570+		bp[2] = l>>16;
  16.571+		bp[3] = l>>24;
  16.572+		bp += 4;
  16.573+		l = e.h;
  16.574+		bp[0] = l;
  16.575+		bp[1] = l>>8;
  16.576+		bp[2] = l>>16;
  16.577+		bp[3] = l>>24;
  16.578+		bp += 4;
  16.579+		break;
  16.580+	}
  16.581+	return bp;
  16.582+}
  16.583+
  16.584+long
  16.585+align(long i, Type *t, int op)
  16.586+{
  16.587+	long o;
  16.588+	Type *v;
  16.589+	int w;
  16.590+
  16.591+	o = i;
  16.592+	w = 1;
  16.593+	switch(op) {
  16.594+	default:
  16.595+		diag(Z, "unknown align opcode %d", op);
  16.596+		break;
  16.597+
  16.598+	case Asu2:	/* padding at end of a struct */
  16.599+		w = SZ_VLONG;
  16.600+		if(packflg)
  16.601+			w = packflg;
  16.602+		break;
  16.603+
  16.604+	case Ael1:	/* initial align of struct element */
  16.605+		for(v=t; v->etype==TARRAY; v=v->link)
  16.606+			;
  16.607+		w = ewidth[v->etype];
  16.608+		if(w <= 0 || w >= SZ_VLONG)
  16.609+			w = SZ_VLONG;
  16.610+		if(packflg)
  16.611+			w = packflg;
  16.612+		break;
  16.613+
  16.614+	case Ael2:	/* width of a struct element */
  16.615+		o += t->width;
  16.616+		break;
  16.617+
  16.618+	case Aarg0:	/* initial passbyptr argument in arg list */
  16.619+		if(typesu[t->etype]) {
  16.620+			o = align(o, types[TIND], Aarg1);
  16.621+			o = align(o, types[TIND], Aarg2);
  16.622+		}
  16.623+		break;
  16.624+
  16.625+	case Aarg1:	/* initial align of parameter */
  16.626+		w = ewidth[t->etype];
  16.627+		if(w <= 0 || w >= SZ_VLONG) {
  16.628+			w = SZ_VLONG;
  16.629+			break;
  16.630+		}
  16.631+		w = 1;		/* little endian no adjustment */
  16.632+		break;
  16.633+
  16.634+	case Aarg2:	/* width of a parameter */
  16.635+		o += t->width;
  16.636+		w = SZ_VLONG;
  16.637+		break;
  16.638+
  16.639+	case Aaut3:	/* total align of automatic */
  16.640+		o = align(o, t, Ael2);
  16.641+		o = align(o, t, Ael1);
  16.642+		w = SZ_LONG;	/* because of a pun in cc/dcl.c:contig() */
  16.643+		break;
  16.644+	}
  16.645+	o = round(o, w);
  16.646+	if(debug['A'])
  16.647+		print("align %s %ld %T = %ld\n", bnames[op], i, t, o);
  16.648+	return o;
  16.649+}
  16.650+
  16.651+long
  16.652+maxround(long max, long v)
  16.653+{
  16.654+	v = round(v, SZ_VLONG);
  16.655+	if(v > max)
  16.656+		return v;
  16.657+	return max;
  16.658+}
    17.1new file mode 100644
    17.2--- /dev/null
    17.3+++ b/sys/src/cmd/7c/txt.c
    17.4@@ -0,0 +1,1412 @@
    17.5+#include "gc.h"
    17.6+
    17.7+static	char	resvreg[nelem(reg)];
    17.8+
    17.9+#define	isv(et)	((et) == TVLONG || (et) == TUVLONG || (et) == TIND)
   17.10+
   17.11+void
   17.12+ginit(void)
   17.13+{
   17.14+	Type *t;
   17.15+
   17.16+	thechar = '7';
   17.17+	thestring = "arm64";
   17.18+	exregoffset = REGEXT;
   17.19+	exfregoffset = FREGEXT;
   17.20+	newvlongcode = 1;
   17.21+	listinit();
   17.22+	nstring = 0;
   17.23+	mnstring = 0;
   17.24+	nrathole = 0;
   17.25+	pc = 0;
   17.26+	breakpc = -1;
   17.27+	continpc = -1;
   17.28+	cases = C;
   17.29+	firstp = P;
   17.30+	lastp = P;
   17.31+	tfield = types[TLONG];
   17.32+
   17.33+	typeswitch = typechlv;
   17.34+	typeword = typechlvp;
   17.35+	typecmplx = typesu;
   17.36+	/* TO DO */
   17.37+	memmove(typechlpv, typechlp, sizeof(typechlpv));
   17.38+	typechlpv[TVLONG] = 1;
   17.39+	typechlpv[TUVLONG] = 1;
   17.40+
   17.41+	zprog.link = P;
   17.42+	zprog.as = AGOK;
   17.43+	zprog.reg = NREG;
   17.44+	zprog.from.type = D_NONE;
   17.45+	zprog.from.name = D_NONE;
   17.46+	zprog.from.reg = NREG;
   17.47+	zprog.to = zprog.from;
   17.48+
   17.49+	regnode.op = OREGISTER;
   17.50+	regnode.class = CEXREG;
   17.51+	regnode.reg = REGTMP;
   17.52+	regnode.complex = 0;
   17.53+	regnode.addable = 11;
   17.54+	regnode.type = types[TLONG];
   17.55+
   17.56+	qregnode = regnode;
   17.57+	qregnode.type = types[TVLONG];
   17.58+
   17.59+	constnode.op = OCONST;
   17.60+	constnode.class = CXXX;
   17.61+	constnode.complex = 0;
   17.62+	constnode.addable = 20;
   17.63+	constnode.type = types[TLONG];
   17.64+
   17.65+	vconstnode = constnode;
   17.66+	vconstnode.type = types[TVLONG];
   17.67+
   17.68+	fconstnode.op = OCONST;
   17.69+	fconstnode.class = CXXX;
   17.70+	fconstnode.complex = 0;
   17.71+	fconstnode.addable = 20;
   17.72+	fconstnode.type = types[TDOUBLE];
   17.73+
   17.74+	nodsafe = new(ONAME, Z, Z);
   17.75+	nodsafe->sym = slookup(".safe");
   17.76+	nodsafe->type = types[TINT];
   17.77+	nodsafe->etype = types[TINT]->etype;
   17.78+	nodsafe->class = CAUTO;
   17.79+	complex(nodsafe);
   17.80+
   17.81+	t = typ(TARRAY, types[TCHAR]);
   17.82+	symrathole = slookup(".rathole");
   17.83+	symrathole->class = CGLOBL;
   17.84+	symrathole->type = t;
   17.85+
   17.86+	nodrat = new(ONAME, Z, Z);
   17.87+	nodrat->sym = symrathole;
   17.88+	nodrat->type = types[TIND];
   17.89+	nodrat->etype = TVOID;
   17.90+	nodrat->class = CGLOBL;
   17.91+	complex(nodrat);
   17.92+	nodrat->type = t;
   17.93+
   17.94+	nodret = new(ONAME, Z, Z);
   17.95+	nodret->sym = slookup(".ret");
   17.96+	nodret->type = types[TIND];
   17.97+	nodret->etype = TIND;
   17.98+	nodret->class = CPARAM;
   17.99+	nodret = new(OIND, nodret, Z);
  17.100+	complex(nodret);
  17.101+
  17.102+	com64init();
  17.103+
  17.104+	memset(reg, 0, sizeof(reg));
  17.105+	/* don't allocate */
  17.106+	reg[REGTMP] = 1;
  17.107+	reg[REGSB] = 1;
  17.108+	reg[REGSP] = 1;
  17.109+	reg[REGZERO] = 1;
  17.110+	/* keep two external registers */
  17.111+	reg[REGEXT] = 1;
  17.112+	reg[REGEXT-1] = 1;
  17.113+	memmove(resvreg, reg, sizeof(reg));
  17.114+}
  17.115+
  17.116+void
  17.117+gclean(void)
  17.118+{
  17.119+	int i;
  17.120+	Sym *s;
  17.121+
  17.122+	for(i=0; i<NREG; i++)
  17.123+		if(reg[i] && !resvreg[i])
  17.124+			diag(Z, "reg %d left allocated", i);
  17.125+	for(i=NREG; i<NREG+NFREG; i++)
  17.126+		if(reg[i] && !resvreg[i])
  17.127+			diag(Z, "freg %d left allocated", i-NREG);
  17.128+	while(mnstring)
  17.129+		outstring("", 1L);
  17.130+	symstring->type->width = nstring;
  17.131+	symrathole->type->width = nrathole;
  17.132+	for(i=0; i<NHASH; i++)
  17.133+	for(s = hash[i]; s != S; s = s->link) {
  17.134+		if(s->type == T)
  17.135+			continue;
  17.136+		if(s->type->width == 0)
  17.137+			continue;
  17.138+		if(s->class != CGLOBL && s->class != CSTATIC)
  17.139+			continue;
  17.140+		if(s->type == types[TENUM])
  17.141+			continue;
  17.142+		gpseudo(AGLOBL, s, nodconst(s->type->width));
  17.143+	}
  17.144+	nextpc();
  17.145+	p->as = AEND;
  17.146+	outcode();
  17.147+}
  17.148+
  17.149+void
  17.150+nextpc(void)
  17.151+{
  17.152+
  17.153+	p = alloc(sizeof(*p));
  17.154+	*p = zprog;
  17.155+	p->lineno = nearln;
  17.156+	pc++;
  17.157+	if(firstp == P) {
  17.158+		firstp = p;
  17.159+		lastp = p;
  17.160+		return;
  17.161+	}
  17.162+	lastp->link = p;
  17.163+	lastp = p;
  17.164+}
  17.165+
  17.166+void
  17.167+gargs(Node *n, Node *tn1, Node *tn2)
  17.168+{
  17.169+	long regs;
  17.170+	Node fnxargs[20], *fnxp;
  17.171+
  17.172+	regs = cursafe;
  17.173+
  17.174+	fnxp = fnxargs;
  17.175+	garg1(n, tn1, tn2, 0, &fnxp);	/* compile fns to temps */
  17.176+
  17.177+	curarg = 0;
  17.178+	fnxp = fnxargs;
  17.179+	garg1(n, tn1, tn2, 1, &fnxp);	/* compile normal args and temps */
  17.180+
  17.181+	cursafe = regs;
  17.182+}
  17.183+
  17.184+void
  17.185+garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp)
  17.186+{
  17.187+	Node nod;
  17.188+
  17.189+	if(n == Z)
  17.190+		return;
  17.191+	if(n->op == OLIST) {
  17.192+		garg1(n->left, tn1, tn2, f, fnxp);
  17.193+		garg1(n->right, tn1, tn2, f, fnxp);
  17.194+		return;
  17.195+	}
  17.196+	if(f == 0) {
  17.197+		if(n->complex >= FNX) {
  17.198+			regsalloc(*fnxp, n);
  17.199+			nod = znode;
  17.200+			nod.op = OAS;
  17.201+			nod.left = *fnxp;
  17.202+			nod.right = n;
  17.203+			nod.type = n->type;
  17.204+			cgen(&nod, Z);
  17.205+			(*fnxp)++;
  17.206+		}
  17.207+		return;
  17.208+	}
  17.209+	if(typesu[n->type->etype]) {
  17.210+		regaalloc(tn2, n);
  17.211+		if(n->complex >= FNX) {
  17.212+			sugen(*fnxp, tn2, n->type->width);
  17.213+			(*fnxp)++;
  17.214+		} else
  17.215+			sugen(n, tn2, n->type->width);
  17.216+		return;
  17.217+	}
  17.218+	if(REGARG >= 0 && curarg == 0 && typechlpv[n->type->etype]) {
  17.219+		regaalloc1(tn1, n);
  17.220+		if(n->complex >= FNX) {
  17.221+			cgen(*fnxp, tn1);
  17.222+			(*fnxp)++;
  17.223+		} else
  17.224+			cgen(n, tn1);
  17.225+		return;
  17.226+	}
  17.227+	if(vconst(n) == 0) {
  17.228+		regaalloc(tn2, n);
  17.229+		gopcode(OAS, n, Z, tn2);
  17.230+		return;
  17.231+	}
  17.232+	regalloc(tn1, n, Z);
  17.233+	if(n->complex >= FNX) {
  17.234+		cgen(*fnxp, tn1);
  17.235+		(*fnxp)++;
  17.236+	} else
  17.237+		cgen(n, tn1);
  17.238+	regaalloc(tn2, n);
  17.239+	gopcode(OAS, tn1, Z, tn2);
  17.240+	regfree(tn1);
  17.241+}
  17.242+
  17.243+Node*
  17.244+nodgconst(vlong v, Type *t)
  17.245+{
  17.246+	if(!typev[t->etype])
  17.247+		return nodconst((long)v);
  17.248+	vconstnode.vconst = v;
  17.249+	return &vconstnode;
  17.250+}
  17.251+
  17.252+Node*
  17.253+nodconst(long v)
  17.254+{
  17.255+	constnode.vconst = v;
  17.256+	return &constnode;
  17.257+}
  17.258+
  17.259+Node*
  17.260+nod32const(vlong v)
  17.261+{
  17.262+	constnode.vconst = v & MASK(32);
  17.263+	return &constnode;
  17.264+}
  17.265+
  17.266+Node*
  17.267+nodfconst(double d)
  17.268+{
  17.269+	fconstnode.fconst = d;
  17.270+	return &fconstnode;
  17.271+}
  17.272+
  17.273+void
  17.274+nodreg(Node *n, Node *nn, int reg)
  17.275+{
  17.276+	*n = qregnode;
  17.277+	n->reg = reg;
  17.278+	n->type = nn->type;
  17.279+	n->lineno = nn->lineno;
  17.280+}
  17.281+
  17.282+void
  17.283+regret(Node *n, Node *nn)
  17.284+{
  17.285+	int r;
  17.286+
  17.287+	r = REGRET;
  17.288+	if(typefd[nn->type->etype])
  17.289+		r = FREGRET+NREG;
  17.290+	nodreg(n, nn, r);
  17.291+	reg[r]++;
  17.292+}
  17.293+
  17.294+void
  17.295+regalloc(Node *n, Node *tn, Node *o)
  17.296+{
  17.297+	int i, j;
  17.298+	static int lasti;
  17.299+
  17.300+	switch(tn->type->etype) {
  17.301+	case TCHAR:
  17.302+	case TUCHAR:
  17.303+	case TSHORT:
  17.304+	case TUSHORT:
  17.305+	case TINT:
  17.306+	case TUINT:
  17.307+	case TLONG:
  17.308+	case TULONG:
  17.309+	case TVLONG:
  17.310+	case TUVLONG:
  17.311+	case TIND:
  17.312+		if(o != Z && o->op == OREGISTER) {
  17.313+			i = o->reg;
  17.314+			if(i >= 0 && i < NREG)
  17.315+				goto out;
  17.316+		}
  17.317+		j = lasti + REGRET+1;
  17.318+		for(i=REGRET+1; i<NREG; i++) {
  17.319+			if(j >= NREG)
  17.320+				j = REGRET+1;
  17.321+			if(reg[j] == 0 && resvreg[j] == 0) {
  17.322+				i = j;
  17.323+				goto out;
  17.324+			}
  17.325+			j++;
  17.326+		}
  17.327+		diag(tn, "out of fixed registers");
  17.328+		goto err;
  17.329+
  17.330+	case TFLOAT:
  17.331+	case TDOUBLE:
  17.332+		if(o != Z && o->op == OREGISTER) {
  17.333+			i = o->reg;
  17.334+			if(i >= NREG && i < NREG+NFREG)
  17.335+				goto out;
  17.336+		}
  17.337+		j = lasti + NREG;
  17.338+		for(i=NREG; i<NREG+NFREG; i++) {
  17.339+			if(j >= NREG+NFREG)
  17.340+				j = NREG;
  17.341+			if(reg[j] == 0) {
  17.342+				i = j;
  17.343+				goto out;
  17.344+			}
  17.345+			j++;
  17.346+		}
  17.347+		diag(tn, "out of float registers");
  17.348+		goto err;
  17.349+	}
  17.350+	diag(tn, "unknown type in regalloc: %T", tn->type);
  17.351+err:
  17.352+	nodreg(n, tn, 0);
  17.353+	return;
  17.354+out:
  17.355+	reg[i]++;
  17.356+	lasti++;
  17.357+	if(lasti >= 5)
  17.358+		lasti = 0;
  17.359+	nodreg(n, tn, i);
  17.360+}
  17.361+
  17.362+void
  17.363+regialloc(Node *n, Node *tn, Node *o)
  17.364+{
  17.365+	Node nod;
  17.366+
  17.367+	nod = *tn;
  17.368+	nod.type = types[TIND];
  17.369+	regalloc(n, &nod, o);
  17.370+}
  17.371+
  17.372+void
  17.373+regfree(Node *n)
  17.374+{
  17.375+	int i;
  17.376+
  17.377+	i = 0;
  17.378+	if(n->op != OREGISTER && n->op != OINDREG)
  17.379+		goto err;
  17.380+	i = n->reg;
  17.381+	if(i < 0 || i >= sizeof(reg))
  17.382+		goto err;
  17.383+	if(reg[i] <= 0)
  17.384+		goto err;
  17.385+	reg[i]--;
  17.386+	return;
  17.387+err:
  17.388+	diag(n, "error in regfree: %d", i);
  17.389+}
  17.390+
  17.391+void
  17.392+regsalloc(Node *n, Node *nn)
  17.393+{
  17.394+	cursafe = align(cursafe, nn->type, Aaut3);
  17.395+	maxargsafe = maxround(maxargsafe, cursafe+curarg);
  17.396+	*n = *nodsafe;
  17.397+	n->xoffset = -(stkoff + cursafe);
  17.398+	n->type = nn->type;
  17.399+	n->etype = nn->type->etype;
  17.400+	n->lineno = nn->lineno;
  17.401+}
  17.402+
  17.403+void
  17.404+regaalloc1(Node *n, Node *nn)
  17.405+{
  17.406+	nodreg(n, nn, REGARG);
  17.407+	reg[REGARG]++;
  17.408+	curarg = align(curarg, nn->type, Aarg1);
  17.409+	curarg = align(curarg, nn->type, Aarg2);
  17.410+	maxargsafe = maxround(maxargsafe, cursafe+curarg);
  17.411+}
  17.412+
  17.413+void
  17.414+regaalloc(Node *n, Node *nn)
  17.415+{
  17.416+	curarg = align(curarg, nn->type, Aarg1);
  17.417+	*n = *nn;
  17.418+	n->op = OINDREG;
  17.419+	n->reg = REGSP;
  17.420+	n->xoffset = curarg + SZ_VLONG;
  17.421+	n->complex = 0;
  17.422+	n->addable = 20;
  17.423+	curarg = align(curarg, nn->type, Aarg2);
  17.424+	maxargsafe = maxround(maxargsafe, cursafe+curarg);
  17.425+}
  17.426+
  17.427+void
  17.428+regind(Node *n, Node *nn)
  17.429+{
  17.430+
  17.431+	if(n->op != OREGISTER) {
  17.432+		diag(n, "regind not OREGISTER");
  17.433+		return;
  17.434+	}
  17.435+	n->op = OINDREG;
  17.436+	n->type = nn->type;
  17.437+}
  17.438+
  17.439+void
  17.440+raddr(Node *n, Prog *p)
  17.441+{
  17.442+	Adr a;
  17.443+
  17.444+	naddr(n, &a);
  17.445+	if(a.type == D_CONST && a.offset == 0) {
  17.446+		a.type = D_REG;
  17.447+		a.reg = REGZERO;
  17.448+	}
  17.449+	if(a.type != D_REG && a.type != D_FREG) {
  17.450+		if(n)
  17.451+			diag(n, "bad in raddr: %O", n->op);
  17.452+		else
  17.453+			diag(n, "bad in raddr: <null>");
  17.454+		p->reg = NREG;
  17.455+	} else
  17.456+		p->reg = a.reg;
  17.457+}
  17.458+
  17.459+void
  17.460+naddr(Node *n, Adr *a)
  17.461+{
  17.462+	long v;
  17.463+
  17.464+	a->type = D_NONE;
  17.465+	if(n == Z)
  17.466+		return;
  17.467+	switch(n->op) {
  17.468+	default:
  17.469+	bad:
  17.470+		diag(n, "bad in naddr: %O", n->op);
  17.471+		break;
  17.472+
  17.473+	case OREGISTER:
  17.474+		a->type = D_REG;
  17.475+		a->sym = S;
  17.476+		a->reg = n->reg;
  17.477+		if(a->reg >= NREG) {
  17.478+			a->type = D_FREG;
  17.479+			a->reg -= NREG;
  17.480+		}
  17.481+		break;
  17.482+
  17.483+	case OIND:
  17.484+		naddr(n->left, a);
  17.485+		if(a->type == D_REG) {
  17.486+			a->type = D_OREG;
  17.487+			break;
  17.488+		}
  17.489+		if(a->type == D_CONST) {
  17.490+			a->type = D_OREG;
  17.491+			break;
  17.492+		}
  17.493+		goto bad;
  17.494+
  17.495+	case OINDREG:
  17.496+		a->type = D_OREG;
  17.497+		a->sym = S;
  17.498+		a->offset = n->xoffset;
  17.499+		a->reg = n->reg;
  17.500+		break;
  17.501+
  17.502+	case ONAME:
  17.503+		a->etype = n->etype;
  17.504+		a->type = D_OREG;
  17.505+		a->name = D_STATIC;
  17.506+		a->sym = n->sym;
  17.507+		a->offset = n->xoffset;
  17.508+		if(n->class == CSTATIC)
  17.509+			break;
  17.510+		if(n->class == CEXTERN || n->class == CGLOBL) {
  17.511+			a->name = D_EXTERN;
  17.512+			break;
  17.513+		}
  17.514+		if(n->class == CAUTO) {
  17.515+			a->name = D_AUTO;
  17.516+			break;
  17.517+		}
  17.518+		if(n->class == CPARAM) {
  17.519+			a->name = D_PARAM;
  17.520+			break;
  17.521+		}
  17.522+		goto bad;
  17.523+
  17.524+	case OCONST:
  17.525+		a->sym = S;
  17.526+		a->reg = NREG;
  17.527+		if(typefd[n->type->etype]) {
  17.528+			a->type = D_FCONST;
  17.529+			a->dval = n->fconst;
  17.530+		} else {
  17.531+			a->type = D_CONST;
  17.532+			a->offset = n->vconst;
  17.533+		}
  17.534+		break;
  17.535+
  17.536+	case OADDR:
  17.537+		naddr(n->left, a);
  17.538+		if(a->type == D_OREG) {
  17.539+			a->type = D_CONST;
  17.540+			break;
  17.541+		}
  17.542+print("bad addr %D\n", a);
  17.543+		goto bad;
  17.544+
  17.545+	case OADD:
  17.546+		if(n->left->op == OCONST) {
  17.547+			naddr(n->left, a);
  17.548+			v = a->offset;
  17.549+			naddr(n->right, a);
  17.550+		} else {
  17.551+			naddr(n->right, a);
  17.552+			v = a->offset;
  17.553+			naddr(n->left, a);
  17.554+		}
  17.555+		a->offset += v;
  17.556+		break;
  17.557+
  17.558+	}
  17.559+}
  17.560+
  17.561+void
  17.562+fop(int as, int f1, int f2, Node *t)
  17.563+{
  17.564+	Node nod1, nod2, nod3;
  17.565+
  17.566+	nodreg(&nod1, t, NREG+f1);
  17.567+	nodreg(&nod2, t, NREG+f2);
  17.568+	regalloc(&nod3, t, t);
  17.569+	gopcode(as, &nod1, &nod2, &nod3);
  17.570+	gmove(&nod3, t);
  17.571+	regfree(&nod3);
  17.572+}
  17.573+
  17.574+void
  17.575+gmove(Node *f, Node *t)
  17.576+{
  17.577+	int ft, tt, a;
  17.578+	Node nod;
  17.579+
  17.580+	ft = f->type->etype;
  17.581+	tt = t->type->etype;
  17.582+
  17.583+	if(ft == TDOUBLE && f->op == OCONST) {
  17.584+	}
  17.585+	if(ft == TFLOAT && f->op == OCONST) {
  17.586+	}
  17.587+
  17.588+	/*
  17.589+	 * a load --
  17.590+	 * put it into a register then
  17.591+	 * worry what to do with it.
  17.592+	 */
  17.593+	if(f->op == ONAME || f->op == OINDREG || f->op == OIND) {
  17.594+		switch(ft) {
  17.595+		default:
  17.596+			if(ewidth[ft] == 4){
  17.597+				if(typeu[ft])
  17.598+					a = AMOVWU;
  17.599+				else
  17.600+					a = AMOVW;
  17.601+			}else
  17.602+				a = AMOV;
  17.603+			break;
  17.604+		case TINT:
  17.605+			a = AMOVW;
  17.606+			break;
  17.607+		case TUINT:
  17.608+			a = AMOVWU;
  17.609+			break;
  17.610+		case TFLOAT:
  17.611+			a = AFMOVS;
  17.612+			break;
  17.613+		case TDOUBLE:
  17.614+			a = AFMOVD;
  17.615+			break;
  17.616+		case TCHAR:
  17.617+			a = AMOVB;
  17.618+			break;
  17.619+		case TUCHAR:
  17.620+			a = AMOVBU;
  17.621+			break;
  17.622+		case TSHORT:
  17.623+			a = AMOVH;
  17.624+			break;
  17.625+		case TUSHORT:
  17.626+			a = AMOVHU;
  17.627+			break;
  17.628+		}
  17.629+		regalloc(&nod, f, t);
  17.630+		gins(a, f, &nod);
  17.631+		gmove(&nod, t);
  17.632+		regfree(&nod);
  17.633+		return;
  17.634+	}
  17.635+
  17.636+	/*
  17.637+	 * a store --
  17.638+	 * put it into a register then
  17.639+	 * store it.
  17.640+	 */
  17.641+	if(t->op == ONAME || t->op == OINDREG || t->op == OIND) {
  17.642+		switch(tt) {
  17.643+		default:
  17.644+			if(ewidth[tt] == 4)
  17.645+				a = AMOVW;
  17.646+			else
  17.647+				a = AMOV;
  17.648+			break;
  17.649+		case TINT:
  17.650+			a = AMOVW;
  17.651+			break;
  17.652+		case TUINT:
  17.653+			a = AMOVWU;
  17.654+			break;
  17.655+		case TUCHAR:
  17.656+			a = AMOVBU;
  17.657+			break;
  17.658+		case TCHAR:
  17.659+			a = AMOVB;
  17.660+			break;
  17.661+		case TUSHORT:
  17.662+			a = AMOVHU;
  17.663+			break;
  17.664+		case TSHORT:
  17.665+			a = AMOVH;
  17.666+			break;
  17.667+		case TFLOAT:
  17.668+			a = AFMOVS;
  17.669+			break;
  17.670+		case TDOUBLE:
  17.671+			a = AFMOVD;
  17.672+			break;
  17.673+		}
  17.674+		if(!typefd[ft] && vconst(f) == 0) {
  17.675+			gins(a, f, t);
  17.676+			return;
  17.677+		}
  17.678+		if(ft == tt)
  17.679+			regalloc(&nod, t, f);
  17.680+		else
  17.681+			regalloc(&nod, t, Z);
  17.682+		gmove(f, &nod);
  17.683+		gins(a, &nod, t);
  17.684+		regfree(&nod);
  17.685+		return;
  17.686+	}
  17.687+
  17.688+	/*
  17.689+	 * type x type cross table
  17.690+	 */
  17.691+	a = AGOK;
  17.692+	switch(ft) {
  17.693+	case TDOUBLE:
  17.694+	case TFLOAT:
  17.695+		switch(tt) {
  17.696+		case TDOUBLE:
  17.697+			a = AFMOVD;
  17.698+			if(ft == TFLOAT)
  17.699+				a = AFCVTSD;
  17.700+			break;
  17.701+		case TFLOAT:
  17.702+			a = AFMOVS;
  17.703+			if(ft == TDOUBLE)
  17.704+				a = AFCVTDS;
  17.705+			break;
  17.706+		case TCHAR:
  17.707+		case TSHORT:
  17.708+		case TINT:
  17.709+		case TLONG:
  17.710+			a = AFCVTZSDW;
  17.711+			if(ft == TFLOAT)
  17.712+				a = AFCVTZSSW;
  17.713+			break;
  17.714+		case TUCHAR:
  17.715+		case TUSHORT:
  17.716+		case TUINT:
  17.717+		case TULONG:
  17.718+			a = AFCVTZUDW;
  17.719+			if(ft == TFLOAT)
  17.720+				a = AFCVTZUSW;
  17.721+			break;
  17.722+		case TVLONG:
  17.723+			a = AFCVTZSD;
  17.724+			if(ft == TFLOAT)