xref: /inferno-os/limbo/optim.c (revision 1ca4518d984a3e2dee44a160397cb720c61d2449)
137da2899SCharles.Forsyth #include "limbo.h"
237da2899SCharles.Forsyth 
337da2899SCharles.Forsyth #define	bzero	bbzero	/* bsd name space pollution */
437da2899SCharles.Forsyth /*
537da2899SCharles.Forsyth 	(r, s) := f();	=> r, s have def on same pc
637da2899SCharles.Forsyth 	s = g();	=> this def kills previous r def (and s def)
737da2899SCharles.Forsyth 	solution: r has def pc, s has def pc+1 and next instruction has pc pc+2
837da2899SCharles.Forsyth */
937da2899SCharles.Forsyth 
1037da2899SCharles.Forsyth #define BLEN	(8*sizeof(ulong))
1137da2899SCharles.Forsyth #define BSHIFT	5	/* assumes ulong 4 */
1237da2899SCharles.Forsyth #define BMASK	(BLEN-1)
1337da2899SCharles.Forsyth 
1437da2899SCharles.Forsyth #define	SIGN(n)		(1<<(n-1))
1537da2899SCharles.Forsyth #define	MSK(n)		(SIGN(n)|(SIGN(n)-1))
1637da2899SCharles.Forsyth #define	MASK(a, b)	(MSK((b)-(a)+1)<<(a))
1737da2899SCharles.Forsyth 
1837da2899SCharles.Forsyth #define isnilsrc(s)	((s)->start.line == 0 && (s)->stop.line == 0 && (s)->start.pos == 0 && (s)->stop.pos == 0)
1937da2899SCharles.Forsyth 
2037da2899SCharles.Forsyth #define limbovar(d)	((d)->sym->name[0] != '.')
2137da2899SCharles.Forsyth #define structure(t)	((t)->kind == Tadt || (t)->kind == Ttuple)
2237da2899SCharles.Forsyth 
2337da2899SCharles.Forsyth enum
2437da2899SCharles.Forsyth {
2537da2899SCharles.Forsyth 	Bclr,
2637da2899SCharles.Forsyth 	Band,
2737da2899SCharles.Forsyth 	Bandinv,
2837da2899SCharles.Forsyth 	Bstore,
2937da2899SCharles.Forsyth 	Bandrev,
3037da2899SCharles.Forsyth 	Bnoop,
3137da2899SCharles.Forsyth 	Bxor,
3237da2899SCharles.Forsyth 	Bor,
3337da2899SCharles.Forsyth 	Bnor,
3437da2899SCharles.Forsyth 	Bequiv,
3537da2899SCharles.Forsyth 	Binv,
3637da2899SCharles.Forsyth 	Bimpby,
3737da2899SCharles.Forsyth 	Brev,
3837da2899SCharles.Forsyth 	Bimp,
3937da2899SCharles.Forsyth 	Bnand,
4037da2899SCharles.Forsyth 	Bset,
4137da2899SCharles.Forsyth };
4237da2899SCharles.Forsyth 
4337da2899SCharles.Forsyth enum
4437da2899SCharles.Forsyth {
4537da2899SCharles.Forsyth 	Suse = 1,
4637da2899SCharles.Forsyth 	Muse = 2,
4737da2899SCharles.Forsyth 	Duse = 4,
4837da2899SCharles.Forsyth 	Sdef = 8,
4937da2899SCharles.Forsyth 	Mdef = 16,
5037da2899SCharles.Forsyth 	Ddef = 32,
5137da2899SCharles.Forsyth 	Tuse1 = 64,	/* fixed point temporary */
5237da2899SCharles.Forsyth 	Tuse2 = 128,	/* fixed point temporary */
5337da2899SCharles.Forsyth 	Mduse = 256,	/* D used if M nil */
5437da2899SCharles.Forsyth 
5537da2899SCharles.Forsyth 	None = 0,
5637da2899SCharles.Forsyth 	Unop = Suse|Ddef,
5737da2899SCharles.Forsyth 	Cunop = Muse|Ddef,
5837da2899SCharles.Forsyth 	Threop = Suse|Muse|Ddef,
5937da2899SCharles.Forsyth 	Binop = Suse|Muse|Ddef|Mduse,
6037da2899SCharles.Forsyth 	Mbinop = Suse|Mdef|Duse,	/* strange */
6137da2899SCharles.Forsyth 	Abinop=Suse|Duse|Ddef,
6237da2899SCharles.Forsyth 	Mabinop = Suse|Muse|Duse|Ddef,
6337da2899SCharles.Forsyth 	Use1 = Suse,
6437da2899SCharles.Forsyth 	Use2 = Suse|Duse,
6537da2899SCharles.Forsyth 	Use3 = Suse|Muse|Duse,
6637da2899SCharles.Forsyth };
6737da2899SCharles.Forsyth 
6837da2899SCharles.Forsyth enum
6937da2899SCharles.Forsyth {
7037da2899SCharles.Forsyth 	Sshift = 10,
7137da2899SCharles.Forsyth 	Mshift = 5,
7237da2899SCharles.Forsyth 	Dshift = 0,
7337da2899SCharles.Forsyth };
7437da2899SCharles.Forsyth 
7537da2899SCharles.Forsyth #define S(x)	((x)<<Sshift)
7637da2899SCharles.Forsyth #define M(x)	((x)<<Mshift)
7737da2899SCharles.Forsyth #define D(x)	((x)<<Dshift)
7837da2899SCharles.Forsyth 
7937da2899SCharles.Forsyth #define SS(x)	(((x)>>Sshift)&0x1f)
8037da2899SCharles.Forsyth #define SM(x)	(((x)>>Mshift)&0x1f)
8137da2899SCharles.Forsyth #define SD(x)	(((x)>>Dshift)&0x1f)
8237da2899SCharles.Forsyth 
8337da2899SCharles.Forsyth enum
8437da2899SCharles.Forsyth {
8537da2899SCharles.Forsyth 	I = 0,		/* ignore */
8637da2899SCharles.Forsyth 	B = 1,	/* byte */
8737da2899SCharles.Forsyth 	W = 4,	/* int */
8837da2899SCharles.Forsyth 	P = 4,	/* pointer */
8937da2899SCharles.Forsyth 	A = 4,	/* array */
9037da2899SCharles.Forsyth 	C = 4,	/* string */
9137da2899SCharles.Forsyth 	X = 4,	/* fixed */
9237da2899SCharles.Forsyth 	R = 4,	/* float */
9337da2899SCharles.Forsyth 	L = 8,	/* big */
9437da2899SCharles.Forsyth 	F = 8,	/* real */
9537da2899SCharles.Forsyth 	Sh = 2,	/* short */
9637da2899SCharles.Forsyth 	Pc = 4,	/* pc */
9737da2899SCharles.Forsyth 	Mp = 16,	/* memory */
9837da2899SCharles.Forsyth 
9937da2899SCharles.Forsyth 	Bop2 = S(B)|D(B),
10037da2899SCharles.Forsyth 	Bop = S(B)|M(B)|D(B),
10137da2899SCharles.Forsyth 	Bopb = S(B)|M(B)|D(Pc),
10237da2899SCharles.Forsyth 	Wop2 = S(W)|D(W),
10337da2899SCharles.Forsyth 	Wop = S(W)|M(W)|D(W),
10437da2899SCharles.Forsyth 	Wopb = S(W)|M(W)|D(Pc),
10537da2899SCharles.Forsyth 	Lop2 = S(L)|D(L),
10637da2899SCharles.Forsyth 	Lop = S(L)|M(L)|D(L),
10737da2899SCharles.Forsyth 	Lopb = S(L)|M(L)|D(Pc),
10837da2899SCharles.Forsyth 	Cop2 = Wop2,
10937da2899SCharles.Forsyth 	Cop = Wop,
11037da2899SCharles.Forsyth 	Copb = Wopb,
11137da2899SCharles.Forsyth 	Fop2 = Lop2,
11237da2899SCharles.Forsyth 	Fop = Lop,
11337da2899SCharles.Forsyth 	Fopb = Lopb,
11437da2899SCharles.Forsyth 	Xop = Wop,
11537da2899SCharles.Forsyth };
11637da2899SCharles.Forsyth 
11737da2899SCharles.Forsyth typedef struct Array Array;
11837da2899SCharles.Forsyth typedef struct Bits Bits;
11937da2899SCharles.Forsyth typedef struct Blist Blist;
12037da2899SCharles.Forsyth typedef struct Block Block;
12137da2899SCharles.Forsyth typedef struct Idlist Idlist;
12237da2899SCharles.Forsyth typedef struct Optab Optab;
12337da2899SCharles.Forsyth 
12437da2899SCharles.Forsyth struct Array
12537da2899SCharles.Forsyth {
12637da2899SCharles.Forsyth 	int	n;
12737da2899SCharles.Forsyth 	int	m;
12837da2899SCharles.Forsyth 	Block	**a;
12937da2899SCharles.Forsyth };
13037da2899SCharles.Forsyth 
13137da2899SCharles.Forsyth struct Bits
13237da2899SCharles.Forsyth {
13337da2899SCharles.Forsyth 	int	n;
13437da2899SCharles.Forsyth 	ulong	*b;
13537da2899SCharles.Forsyth };
13637da2899SCharles.Forsyth 
13737da2899SCharles.Forsyth struct Blist
13837da2899SCharles.Forsyth {
13937da2899SCharles.Forsyth 	Block	*block;
14037da2899SCharles.Forsyth 	Blist	*next;
14137da2899SCharles.Forsyth };
14237da2899SCharles.Forsyth 
14337da2899SCharles.Forsyth struct Block
14437da2899SCharles.Forsyth {
14537da2899SCharles.Forsyth 	int	dfn;
14637da2899SCharles.Forsyth 	int	flags;
14737da2899SCharles.Forsyth 	Inst	*first;
14837da2899SCharles.Forsyth 	Inst	*last;
14937da2899SCharles.Forsyth 	Block	*prev;
15037da2899SCharles.Forsyth 	Block	*next;
15137da2899SCharles.Forsyth 	Blist	*pred;
15237da2899SCharles.Forsyth 	Blist *succ;
15337da2899SCharles.Forsyth 	Bits	kill;
15437da2899SCharles.Forsyth 	Bits	gen;
15537da2899SCharles.Forsyth 	Bits	in;
15637da2899SCharles.Forsyth 	Bits	out;
15737da2899SCharles.Forsyth };
15837da2899SCharles.Forsyth 
15937da2899SCharles.Forsyth struct Idlist
16037da2899SCharles.Forsyth {
16137da2899SCharles.Forsyth 	int id;
16237da2899SCharles.Forsyth 	Idlist *next;
16337da2899SCharles.Forsyth };
16437da2899SCharles.Forsyth 
16537da2899SCharles.Forsyth struct Optab
16637da2899SCharles.Forsyth {
16737da2899SCharles.Forsyth 	short flags;
16837da2899SCharles.Forsyth 	short size;
16937da2899SCharles.Forsyth };
17037da2899SCharles.Forsyth 
17137da2899SCharles.Forsyth Block	zblock;
17237da2899SCharles.Forsyth Decl	*regdecls;
17337da2899SCharles.Forsyth Idlist *frelist;
17437da2899SCharles.Forsyth Idlist *deflist;
17537da2899SCharles.Forsyth Idlist *uselist;
17637da2899SCharles.Forsyth 
17737da2899SCharles.Forsyth static void
addlist(Idlist ** hd,int id)17837da2899SCharles.Forsyth addlist(Idlist **hd, int id)
17937da2899SCharles.Forsyth {
18037da2899SCharles.Forsyth 	Idlist *il;
18137da2899SCharles.Forsyth 
18237da2899SCharles.Forsyth 	if(frelist == nil)
18337da2899SCharles.Forsyth 		il = (Idlist*)malloc(sizeof(Idlist));
18437da2899SCharles.Forsyth 	else{
18537da2899SCharles.Forsyth 		il = frelist;
18637da2899SCharles.Forsyth 		frelist = frelist->next;
18737da2899SCharles.Forsyth 	}
18837da2899SCharles.Forsyth 	il->id = id;
18937da2899SCharles.Forsyth 	il->next = *hd;
19037da2899SCharles.Forsyth 	*hd = il;
19137da2899SCharles.Forsyth }
19237da2899SCharles.Forsyth 
19337da2899SCharles.Forsyth static void
freelist(Idlist ** hd)19437da2899SCharles.Forsyth freelist(Idlist **hd)
19537da2899SCharles.Forsyth {
19637da2899SCharles.Forsyth 	Idlist *il;
19737da2899SCharles.Forsyth 
19837da2899SCharles.Forsyth 	for(il = *hd; il != nil && il->next != nil; il = il->next)
19937da2899SCharles.Forsyth 		;
20037da2899SCharles.Forsyth 	if(il != nil){
20137da2899SCharles.Forsyth 		il->next = frelist;
20237da2899SCharles.Forsyth 		frelist = *hd;
20337da2899SCharles.Forsyth 		*hd = nil;
20437da2899SCharles.Forsyth 	}
20537da2899SCharles.Forsyth }
20637da2899SCharles.Forsyth 
20737da2899SCharles.Forsyth Optab opflags[] = {
20837da2899SCharles.Forsyth 	/* INOP */	None,	0,
20937da2899SCharles.Forsyth 	/* IALT */	Unop,	S(Mp)|D(W),
21037da2899SCharles.Forsyth 	/* INBALT */	Unop,	S(Mp)|D(W),
21137da2899SCharles.Forsyth 	/* IGOTO */	Use2,	S(W)|D(I),
21237da2899SCharles.Forsyth 	/* ICALL */	Use2,	S(P)|D(Pc),
21337da2899SCharles.Forsyth 	/* IFRAME */	Unop,	S(W)|D(P),
21437da2899SCharles.Forsyth 	/* ISPAWN */	Use2,	S(P)|D(Pc),
21537da2899SCharles.Forsyth 	/* IRUNT */	None,	0,
21637da2899SCharles.Forsyth 	/* ILOAD */	Threop,	S(C)|M(P)|D(P),
21737da2899SCharles.Forsyth 	/* IMCALL */	Use3,	S(P)|M(W)|D(P),
21837da2899SCharles.Forsyth 	/* IMSPAWN */	Use3,	S(P)|M(W)|D(P),
21937da2899SCharles.Forsyth 	/* IMFRAME */	Threop,	S(P)|M(W)|D(P),
22037da2899SCharles.Forsyth 	/* IRET */	None,	0,
22137da2899SCharles.Forsyth 	/* IJMP */	Duse,	D(Pc),
22237da2899SCharles.Forsyth 	/* ICASE */	Use2,	S(W)|D(I),
22337da2899SCharles.Forsyth 	/* IEXIT */	None,	0,
22437da2899SCharles.Forsyth 	/* INEW */	Unop,	S(W)|D(P),
22537da2899SCharles.Forsyth 	/* INEWA */	Threop,	S(W)|M(W)|D(P),
22637da2899SCharles.Forsyth 	/* INEWCB */	Cunop,	M(W)|D(P),
22737da2899SCharles.Forsyth 	/* INEWCW */	Cunop,	M(W)|D(P),
22837da2899SCharles.Forsyth 	/* INEWCF */	Cunop,	M(W)|D(P),
22937da2899SCharles.Forsyth 	/* INEWCP */	Cunop,	M(W)|D(P),
23037da2899SCharles.Forsyth 	/* INEWCM */	Threop,	S(W)|M(W)|D(P),
23137da2899SCharles.Forsyth 	/* INEWCMP */	Threop,	S(W)|M(W)|D(P),
23237da2899SCharles.Forsyth 	/* ISEND */	Use2,	S(Mp)|D(P),
23337da2899SCharles.Forsyth 	/* IRECV */	Unop,	S(P)|D(Mp),
23437da2899SCharles.Forsyth 	/* ICONSB */	Abinop,	S(B)|D(P),
23537da2899SCharles.Forsyth 	/* ICONSW */	Abinop,	S(W)|D(P),
23637da2899SCharles.Forsyth 	/* ICONSP */	Abinop,	S(P)|D(P),
23737da2899SCharles.Forsyth 	/* ICONSF */	Abinop,	S(F)|D(P),
23837da2899SCharles.Forsyth 	/* ICONSM */	Mabinop,	S(Mp)|M(W)|D(P),
23937da2899SCharles.Forsyth 	/* ICONSMP */	Mabinop,	S(Mp)|M(W)|D(P),
24037da2899SCharles.Forsyth 	/* IHEADB */	Unop,	S(P)|D(B),
24137da2899SCharles.Forsyth 	/* IHEADW */	Unop,	S(P)|D(W),
24237da2899SCharles.Forsyth 	/* IHEADP */	Unop,	S(P)|D(P),
24337da2899SCharles.Forsyth 	/* IHEADF */	Unop,	S(P)|D(F),
24437da2899SCharles.Forsyth 	/* IHEADM */	Threop,	S(P)|M(W)|D(Mp),
24537da2899SCharles.Forsyth 	/* IHEADMP */	Threop,	S(P)|M(W)|D(Mp),
24637da2899SCharles.Forsyth 	/* ITAIL */	Unop,	S(P)|D(P),
24737da2899SCharles.Forsyth 	/* ILEA */	Ddef,	S(Mp)|D(P),	/* S done specially cos of ALT */
24837da2899SCharles.Forsyth 	/* IINDX */	Mbinop,	S(P)|M(P)|D(W),
24937da2899SCharles.Forsyth 	/* IMOVP */	Unop,	S(P)|D(P),
25037da2899SCharles.Forsyth 	/* IMOVM */	Threop,	S(Mp)|M(W)|D(Mp),
25137da2899SCharles.Forsyth 	/* IMOVMP */	Threop,	S(Mp)|M(W)|D(Mp),
25237da2899SCharles.Forsyth 	/* IMOVB */	Unop,	Bop2,
25337da2899SCharles.Forsyth 	/* IMOVW */	Unop,	Wop2,
25437da2899SCharles.Forsyth 	/* IMOVF */	Unop,	Fop2,
25537da2899SCharles.Forsyth 	/* ICVTBW */	Unop,	S(B)|D(W),
25637da2899SCharles.Forsyth 	/* ICVTWB */	Unop,	S(W)|D(B),
25737da2899SCharles.Forsyth 	/* ICVTFW */	Unop,	S(F)|D(W),
25837da2899SCharles.Forsyth 	/* ICVTWF */	Unop,	S(W)|D(F),
25937da2899SCharles.Forsyth 	/* ICVTCA */	Unop,	S(C)|D(A),
26037da2899SCharles.Forsyth 	/* ICVTAC */	Unop,	S(A)|D(C),
26137da2899SCharles.Forsyth 	/* ICVTWC */	Unop,	S(W)|D(C),
26237da2899SCharles.Forsyth 	/* ICVTCW */	Unop,	S(C)|D(W),
26337da2899SCharles.Forsyth 	/* ICVTFC */	Unop,	S(F)|D(C),
26437da2899SCharles.Forsyth 	/* ICVTCF */	Unop,	S(C)|D(F),
26537da2899SCharles.Forsyth 	/* IADDB */	Binop,	Bop,
26637da2899SCharles.Forsyth 	/* IADDW */	Binop,	Wop,
26737da2899SCharles.Forsyth 	/* IADDF */	Binop,	Fop,
26837da2899SCharles.Forsyth 	/* ISUBB */	Binop,	Bop,
26937da2899SCharles.Forsyth 	/* ISUBW */	Binop,	Wop,
27037da2899SCharles.Forsyth 	/* ISUBF */	Binop,	Fop,
27137da2899SCharles.Forsyth 	/* IMULB */	Binop,	Bop,
27237da2899SCharles.Forsyth 	/* IMULW */	Binop,	Wop,
27337da2899SCharles.Forsyth 	/* IMULF */	Binop,	Fop,
27437da2899SCharles.Forsyth 	/* IDIVB */	Binop,	Bop,
27537da2899SCharles.Forsyth 	/* IDIVW */	Binop,	Wop,
27637da2899SCharles.Forsyth 	/* IDIVF */	Binop,	Fop,
27737da2899SCharles.Forsyth 	/* IMODW */	Binop,	Wop,
27837da2899SCharles.Forsyth 	/* IMODB */	Binop,	Bop,
27937da2899SCharles.Forsyth 	/* IANDB */	Binop,	Bop,
28037da2899SCharles.Forsyth 	/* IANDW */	Binop,	Wop,
28137da2899SCharles.Forsyth 	/* IORB */	Binop,	Bop,
28237da2899SCharles.Forsyth 	/* IORW */	Binop,	Wop,
28337da2899SCharles.Forsyth 	/* IXORB */	Binop,	Bop,
28437da2899SCharles.Forsyth 	/* IXORW */	Binop,	Wop,
28537da2899SCharles.Forsyth 	/* ISHLB */	Binop,	S(W)|M(B)|D(B),
28637da2899SCharles.Forsyth 	/* ISHLW */	Binop,	Wop,
28737da2899SCharles.Forsyth 	/* ISHRB */	Binop,	S(W)|M(B)|D(B),
28837da2899SCharles.Forsyth 	/* ISHRW */	Binop,	Wop,
28937da2899SCharles.Forsyth 	/* IINSC */	Mabinop,	S(W)|M(W)|D(C),
29037da2899SCharles.Forsyth 	/* IINDC */	Threop,	S(C)|M(W)|D(W),
29137da2899SCharles.Forsyth 	/* IADDC */	Binop,	Cop,
29237da2899SCharles.Forsyth 	/* ILENC */	Unop,	S(C)|D(W),
29337da2899SCharles.Forsyth 	/* ILENA */	Unop,	S(A)|D(W),
29437da2899SCharles.Forsyth 	/* ILENL */	Unop,	S(P)|D(W),
29537da2899SCharles.Forsyth 	/* IBEQB */	Use3,	Bopb,
29637da2899SCharles.Forsyth 	/* IBNEB */	Use3,	Bopb,
29737da2899SCharles.Forsyth 	/* IBLTB */	Use3,	Bopb,
29837da2899SCharles.Forsyth 	/* IBLEB */	Use3,	Bopb,
29937da2899SCharles.Forsyth 	/* IBGTB */	Use3,	Bopb,
30037da2899SCharles.Forsyth 	/* IBGEB */	Use3,	Bopb,
30137da2899SCharles.Forsyth 	/* IBEQW */	Use3,	Wopb,
30237da2899SCharles.Forsyth 	/* IBNEW */	Use3,	Wopb,
30337da2899SCharles.Forsyth 	/* IBLTW */	Use3,	Wopb,
30437da2899SCharles.Forsyth 	/* IBLEW */	Use3,	Wopb,
30537da2899SCharles.Forsyth 	/* IBGTW */	Use3,	Wopb,
30637da2899SCharles.Forsyth 	/* IBGEW */	Use3,	Wopb,
30737da2899SCharles.Forsyth 	/* IBEQF */	Use3,	Fopb,
30837da2899SCharles.Forsyth 	/* IBNEF */	Use3,	Fopb,
30937da2899SCharles.Forsyth 	/* IBLTF */	Use3,	Fopb,
31037da2899SCharles.Forsyth 	/* IBLEF */	Use3,	Fopb,
31137da2899SCharles.Forsyth 	/* IBGTF */	Use3,	Fopb,
31237da2899SCharles.Forsyth 	/* IBGEF */	Use3,	Fopb,
31337da2899SCharles.Forsyth 	/* IBEQC */	Use3,	Copb,
31437da2899SCharles.Forsyth 	/* IBNEC */	Use3,	Copb,
31537da2899SCharles.Forsyth 	/* IBLTC */	Use3,	Copb,
31637da2899SCharles.Forsyth 	/* IBLEC */	Use3,	Copb,
31737da2899SCharles.Forsyth 	/* IBGTC */	Use3,	Copb,
31837da2899SCharles.Forsyth 	/* IBGEC */	Use3,	Copb,
31937da2899SCharles.Forsyth 	/* ISLICEA */	Mabinop,	S(W)|M(W)|D(P),
32037da2899SCharles.Forsyth 	/* ISLICELA */	Use3,	S(P)|M(W)|D(P),
32137da2899SCharles.Forsyth 	/* ISLICEC */	Mabinop,	S(W)|M(W)|D(C),
32237da2899SCharles.Forsyth 	/* IINDW */	Mbinop,	S(P)|M(P)|D(W),
32337da2899SCharles.Forsyth 	/* IINDF */	Mbinop,	S(P)|M(P)|D(W),
32437da2899SCharles.Forsyth 	/* IINDB */	Mbinop,	S(P)|M(P)|D(W),
32537da2899SCharles.Forsyth 	/* INEGF */	Unop,	Fop2,
32637da2899SCharles.Forsyth 	/* IMOVL */	Unop,	Lop2,
32737da2899SCharles.Forsyth 	/* IADDL */	Binop,	Lop,
32837da2899SCharles.Forsyth 	/* ISUBL */	Binop,	Lop,
32937da2899SCharles.Forsyth 	/* IDIVL */	Binop,	Lop,
33037da2899SCharles.Forsyth 	/* IMODL */	Binop,	Lop,
33137da2899SCharles.Forsyth 	/* IMULL */	Binop,	Lop,
33237da2899SCharles.Forsyth 	/* IANDL */	Binop,	Lop,
33337da2899SCharles.Forsyth 	/* IORL */	Binop,	Lop,
33437da2899SCharles.Forsyth 	/* IXORL */	Binop,	Lop,
33537da2899SCharles.Forsyth 	/* ISHLL */	Binop,	S(W)|M(L)|D(L),
33637da2899SCharles.Forsyth 	/* ISHRL */	Binop,	S(W)|M(L)|D(L),
33737da2899SCharles.Forsyth 	/* IBNEL */	Use3,	Lopb,
33837da2899SCharles.Forsyth 	/* IBLTL */	Use3,	Lopb,
33937da2899SCharles.Forsyth 	/* IBLEL */	Use3,	Lopb,
34037da2899SCharles.Forsyth 	/* IBGTL */	Use3,	Lopb,
34137da2899SCharles.Forsyth 	/* IBGEL */	Use3,	Lopb,
34237da2899SCharles.Forsyth 	/* IBEQL */	Use3,	Lopb,
34337da2899SCharles.Forsyth 	/* ICVTLF */	Unop,	S(L)|D(F),
34437da2899SCharles.Forsyth 	/* ICVTFL */	Unop,	S(F)|D(L),
34537da2899SCharles.Forsyth 	/* ICVTLW */	Unop,	S(L)|D(W),
34637da2899SCharles.Forsyth 	/* ICVTWL */	Unop,	S(W)|D(L),
34737da2899SCharles.Forsyth 	/* ICVTLC */	Unop,	S(L)|D(C),
34837da2899SCharles.Forsyth 	/* ICVTCL */	Unop,	S(C)|D(L),
34937da2899SCharles.Forsyth 	/* IHEADL */	Unop,	S(P)|D(L),
35037da2899SCharles.Forsyth 	/* ICONSL */	Abinop,	S(L)|D(P),
35137da2899SCharles.Forsyth 	/* INEWCL */	Cunop,	M(W)|D(P),
35237da2899SCharles.Forsyth 	/* ICASEC */	Use2,	S(C)|D(I),
35337da2899SCharles.Forsyth 	/* IINDL */	Mbinop,	S(P)|M(P)|D(W),
35437da2899SCharles.Forsyth 	/* IMOVPC */	Unop,	S(W)|D(P),
35537da2899SCharles.Forsyth 	/* ITCMP */	Use2,	S(P)|D(P),
35637da2899SCharles.Forsyth 	/* IMNEWZ */	Threop,	S(P)|M(W)|D(P),
35737da2899SCharles.Forsyth 	/* ICVTRF */	Unop,	S(R)|D(F),
35837da2899SCharles.Forsyth 	/* ICVTFR */	Unop,	S(F)|D(R),
35937da2899SCharles.Forsyth 	/* ICVTWS */	Unop,	S(W)|D(Sh),
36037da2899SCharles.Forsyth 	/* ICVTSW */	Unop,	S(Sh)|D(W),
36137da2899SCharles.Forsyth 	/* ILSRW */	Binop,	Wop,
36237da2899SCharles.Forsyth 	/* ILSRL */	Binop,	S(W)|M(L)|D(L),
36337da2899SCharles.Forsyth 	/* IECLR */	None,	0,
36437da2899SCharles.Forsyth 	/* INEWZ */	Unop,	S(W)|D(P),
36537da2899SCharles.Forsyth 	/* INEWAZ */	Threop,	S(W)|M(W)|D(P),
36637da2899SCharles.Forsyth 	/* IRAISE */	Use1,	S(P),
36737da2899SCharles.Forsyth 	/* ICASEL */	Use2,	S(L)|D(I),
36837da2899SCharles.Forsyth 	/* IMULX */	Binop|Tuse2,	Xop,
36937da2899SCharles.Forsyth 	/* IDIVX */	Binop|Tuse2,	Xop,
37037da2899SCharles.Forsyth 	/* ICVTXX */	Threop,	Xop,
37137da2899SCharles.Forsyth 	/* IMULX0 */	Binop|Tuse1|Tuse2,	Xop,
37237da2899SCharles.Forsyth 	/* IDIVX0 */	Binop|Tuse1|Tuse2,	Xop,
37337da2899SCharles.Forsyth 	/* ICVTXX0 */	Threop|Tuse1,	Xop,
37437da2899SCharles.Forsyth 	/* IMULX1 */	Binop|Tuse1|Tuse2,	Xop,
37537da2899SCharles.Forsyth 	/* IDIVX1 */	Binop|Tuse1|Tuse2,	Xop,
37637da2899SCharles.Forsyth 	/* ICVTXX1 */	Threop|Tuse1,	Xop,
37737da2899SCharles.Forsyth 	/* ICVTFX */	Threop,	S(F)|M(F)|D(X),
37837da2899SCharles.Forsyth 	/* ICVTXF */	Threop,	S(X)|M(F)|D(F),
37937da2899SCharles.Forsyth 	/* IEXPW */	Binop,	S(W)|M(W)|D(W),
38037da2899SCharles.Forsyth 	/* IEXPL */	Binop,	S(W)|M(L)|D(L),
38137da2899SCharles.Forsyth 	/* IEXPF */	Binop,	S(W)|M(F)|D(F),
38237da2899SCharles.Forsyth 	/* ISELF */	Ddef,	D(P),
38337da2899SCharles.Forsyth 	/* IEXC */		None,		0,
38437da2899SCharles.Forsyth 	/* IEXC0 */	None,		0,
38537da2899SCharles.Forsyth 	/* INOOP */	None,		0,
38637da2899SCharles.Forsyth };
38737da2899SCharles.Forsyth 
38837da2899SCharles.Forsyth /*
38937da2899SCharles.Forsyth static int
39037da2899SCharles.Forsyth pop(int i)
39137da2899SCharles.Forsyth {
39237da2899SCharles.Forsyth 	i = (i & 0x55555555) + ((i>>1) & 0x55555555);
39337da2899SCharles.Forsyth 	i = (i & 0x33333333) + ((i>>2) & 0x33333333);
39437da2899SCharles.Forsyth 	i = (i & 0x0F0F0F0F) + ((i>>4) & 0x0F0F0F0F);
39537da2899SCharles.Forsyth 	i = (i & 0x00FF00FF) + ((i>>8) & 0x00FF00FF);
39637da2899SCharles.Forsyth 	i = (i & 0x0000FFFF) + ((i>>16) & 0x0000FFFF);
39737da2899SCharles.Forsyth 	return i;
39837da2899SCharles.Forsyth }
39937da2899SCharles.Forsyth */
40037da2899SCharles.Forsyth 
40137da2899SCharles.Forsyth static int
bitc(uint x)40237da2899SCharles.Forsyth bitc(uint x)
40337da2899SCharles.Forsyth {
40437da2899SCharles.Forsyth 	uint n;
40537da2899SCharles.Forsyth 
40637da2899SCharles.Forsyth 	n = (x>>1)&0x77777777;
40737da2899SCharles.Forsyth 	x -= n;
40837da2899SCharles.Forsyth 	n = (n>>1)&0x77777777;
40937da2899SCharles.Forsyth 	x -= n;
41037da2899SCharles.Forsyth 	n = (n>>1)&0x77777777;
41137da2899SCharles.Forsyth 	x -= n;
41237da2899SCharles.Forsyth 	x = (x+(x>>4))&0x0f0f0f0f;
41337da2899SCharles.Forsyth 	x *= 0x01010101;
41437da2899SCharles.Forsyth 	return x>>24;
41537da2899SCharles.Forsyth }
41637da2899SCharles.Forsyth 
41737da2899SCharles.Forsyth /*
41837da2899SCharles.Forsyth static int
41937da2899SCharles.Forsyth top(uint x)
42037da2899SCharles.Forsyth {
42137da2899SCharles.Forsyth 	int i;
42237da2899SCharles.Forsyth 
42337da2899SCharles.Forsyth 	for(i = -1; x; i++)
42437da2899SCharles.Forsyth 		x >>= 1;
42537da2899SCharles.Forsyth 	return i;
42637da2899SCharles.Forsyth }
42737da2899SCharles.Forsyth */
42837da2899SCharles.Forsyth 
42937da2899SCharles.Forsyth static int
topb(uint x)43037da2899SCharles.Forsyth topb(uint x)
43137da2899SCharles.Forsyth {
43237da2899SCharles.Forsyth 	int i;
43337da2899SCharles.Forsyth 
43437da2899SCharles.Forsyth 	if(x == 0)
43537da2899SCharles.Forsyth 		return -1;
43637da2899SCharles.Forsyth 	i = 0;
43737da2899SCharles.Forsyth 	if(x&0xffff0000){
43837da2899SCharles.Forsyth 		i |= 16;
43937da2899SCharles.Forsyth 		x >>= 16;
44037da2899SCharles.Forsyth 	}
44137da2899SCharles.Forsyth 	if(x&0xff00){
44237da2899SCharles.Forsyth 		i |= 8;
44337da2899SCharles.Forsyth 		x >>= 8;
44437da2899SCharles.Forsyth 	}
44537da2899SCharles.Forsyth 	if(x&0xf0){
44637da2899SCharles.Forsyth 		i |= 4;
44737da2899SCharles.Forsyth 		x >>= 4;
44837da2899SCharles.Forsyth 	}
44937da2899SCharles.Forsyth 	if(x&0xc){
45037da2899SCharles.Forsyth 		i |= 2;
45137da2899SCharles.Forsyth 		x >>= 2;
45237da2899SCharles.Forsyth 	}
45337da2899SCharles.Forsyth 	if(x&0x2)
45437da2899SCharles.Forsyth 		i |= 1;
45537da2899SCharles.Forsyth 	return i;
45637da2899SCharles.Forsyth }
45737da2899SCharles.Forsyth 
45837da2899SCharles.Forsyth /*
45937da2899SCharles.Forsyth static int
46037da2899SCharles.Forsyth lowb(uint x)
46137da2899SCharles.Forsyth {
46237da2899SCharles.Forsyth 	int i;
46337da2899SCharles.Forsyth 
46437da2899SCharles.Forsyth 	if(x == 0)
46537da2899SCharles.Forsyth 		return -1;
46637da2899SCharles.Forsyth 	for(i = BLEN; x; i--)
46737da2899SCharles.Forsyth 		x <<= 1;
46837da2899SCharles.Forsyth 	return i;
46937da2899SCharles.Forsyth }
47037da2899SCharles.Forsyth */
47137da2899SCharles.Forsyth 
47237da2899SCharles.Forsyth static int
lowb(uint x)47337da2899SCharles.Forsyth lowb(uint x)
47437da2899SCharles.Forsyth {
47537da2899SCharles.Forsyth 	int i;
47637da2899SCharles.Forsyth 
47737da2899SCharles.Forsyth 	if(x == 0)
47837da2899SCharles.Forsyth 		return -1;
47937da2899SCharles.Forsyth 	i = 0;
48037da2899SCharles.Forsyth 	if((x&0xffff) == 0){
48137da2899SCharles.Forsyth 		i |= 16;
48237da2899SCharles.Forsyth 		x >>= 16;
48337da2899SCharles.Forsyth 	}
48437da2899SCharles.Forsyth 	if((x&0xff) == 0){
48537da2899SCharles.Forsyth 		i |= 8;
48637da2899SCharles.Forsyth 		x >>= 8;
48737da2899SCharles.Forsyth 	}
48837da2899SCharles.Forsyth 	if((x&0xf) == 0){
48937da2899SCharles.Forsyth 		i |= 4;
49037da2899SCharles.Forsyth 		x >>= 4;
49137da2899SCharles.Forsyth 	}
49237da2899SCharles.Forsyth 	if((x&0x3) == 0){
49337da2899SCharles.Forsyth 		i |= 2;
49437da2899SCharles.Forsyth 		x >>= 2;
49537da2899SCharles.Forsyth 	}
49637da2899SCharles.Forsyth 	return i+1-(x&1);
49737da2899SCharles.Forsyth }
49837da2899SCharles.Forsyth 
49937da2899SCharles.Forsyth static void
pbit(int x,int n)50037da2899SCharles.Forsyth pbit(int x, int n)
50137da2899SCharles.Forsyth {
50237da2899SCharles.Forsyth 	int i, m;
50337da2899SCharles.Forsyth 
50437da2899SCharles.Forsyth 	m = 1;
50537da2899SCharles.Forsyth 	for(i = 0; i < BLEN; i++){
50637da2899SCharles.Forsyth 		if(x&m)
50737da2899SCharles.Forsyth 			print("%d ", i+n);
50837da2899SCharles.Forsyth 		m <<= 1;
50937da2899SCharles.Forsyth 	}
51037da2899SCharles.Forsyth }
51137da2899SCharles.Forsyth 
51237da2899SCharles.Forsyth static ulong
bop(int o,ulong s,ulong d)51337da2899SCharles.Forsyth bop(int o, ulong s, ulong d)
51437da2899SCharles.Forsyth {
51537da2899SCharles.Forsyth 	switch(o){
51637da2899SCharles.Forsyth 	case Bclr:	return 0;
51737da2899SCharles.Forsyth 	case Band:	return s & d;
51837da2899SCharles.Forsyth 	case Bandinv:	return s & ~d;
51937da2899SCharles.Forsyth 	case Bstore:	return s;
52037da2899SCharles.Forsyth 	case Bandrev:	return ~s & d;
52137da2899SCharles.Forsyth 	case Bnoop:	return d;
52237da2899SCharles.Forsyth 	case Bxor:	return s ^ d;
52337da2899SCharles.Forsyth 	case Bor:	return s | d;
52437da2899SCharles.Forsyth 	case Bnor:	return ~(s | d);
52537da2899SCharles.Forsyth 	case Bequiv:	return ~(s ^ d);
52637da2899SCharles.Forsyth 	case Binv:	return ~d;
52737da2899SCharles.Forsyth 	case Bimpby:	return s | ~d;
52837da2899SCharles.Forsyth 	case Brev:	return ~s;
52937da2899SCharles.Forsyth 	case Bimp:	return ~s | d;
53037da2899SCharles.Forsyth 	case Bnand:	return ~(s & d);
53137da2899SCharles.Forsyth 	case Bset:	return 0xffffffff;
53237da2899SCharles.Forsyth 	}
53337da2899SCharles.Forsyth 	return 0;
53437da2899SCharles.Forsyth }
53537da2899SCharles.Forsyth 
53637da2899SCharles.Forsyth static Bits
bnew(int n,int bits)53737da2899SCharles.Forsyth bnew(int n, int bits)
53837da2899SCharles.Forsyth {
53937da2899SCharles.Forsyth 	Bits b;
54037da2899SCharles.Forsyth 
54137da2899SCharles.Forsyth 	if(bits)
54237da2899SCharles.Forsyth 		b.n = (n+BLEN-1)>>BSHIFT;
54337da2899SCharles.Forsyth 	else
54437da2899SCharles.Forsyth 		b.n = n;
54537da2899SCharles.Forsyth 	b.b = allocmem(b.n*sizeof(ulong));
54637da2899SCharles.Forsyth 	memset(b.b, 0, b.n*sizeof(ulong));
54737da2899SCharles.Forsyth 	return b;
54837da2899SCharles.Forsyth }
54937da2899SCharles.Forsyth 
55037da2899SCharles.Forsyth static void
bfree(Bits b)55137da2899SCharles.Forsyth bfree(Bits b)
55237da2899SCharles.Forsyth {
55337da2899SCharles.Forsyth 	free(b.b);
55437da2899SCharles.Forsyth }
55537da2899SCharles.Forsyth 
55637da2899SCharles.Forsyth static void
bset(Bits b,int n)55737da2899SCharles.Forsyth bset(Bits b, int n)
55837da2899SCharles.Forsyth {
55937da2899SCharles.Forsyth 	b.b[n>>BSHIFT] |= 1<<(n&BMASK);
56037da2899SCharles.Forsyth }
56137da2899SCharles.Forsyth 
56237da2899SCharles.Forsyth static void
bclr(Bits b,int n)56337da2899SCharles.Forsyth bclr(Bits b, int n)
56437da2899SCharles.Forsyth {
56537da2899SCharles.Forsyth 	b.b[n>>BSHIFT] &= ~(1<<(n&BMASK));
56637da2899SCharles.Forsyth }
56737da2899SCharles.Forsyth 
56837da2899SCharles.Forsyth static int
bmem(Bits b,int n)56937da2899SCharles.Forsyth bmem(Bits b, int n)
57037da2899SCharles.Forsyth {
57137da2899SCharles.Forsyth 	return b.b[n>>BSHIFT] & (1<<(n&BMASK));
57237da2899SCharles.Forsyth }
57337da2899SCharles.Forsyth 
57437da2899SCharles.Forsyth static void
bsets(Bits b,int m,int n)57537da2899SCharles.Forsyth bsets(Bits b, int m, int n)
57637da2899SCharles.Forsyth {
57737da2899SCharles.Forsyth 	int i, c1, c2;
57837da2899SCharles.Forsyth 
57937da2899SCharles.Forsyth 	c1 = m>>BSHIFT;
58037da2899SCharles.Forsyth 	c2 = n>>BSHIFT;
58137da2899SCharles.Forsyth 	m &= BMASK;
58237da2899SCharles.Forsyth 	n &= BMASK;
58337da2899SCharles.Forsyth 	if(c1 == c2){
58437da2899SCharles.Forsyth 		b.b[c1] |= MASK(m, n);
58537da2899SCharles.Forsyth 		return;
58637da2899SCharles.Forsyth 	}
58737da2899SCharles.Forsyth 	for(i = c1+1; i < c2; i++)
58837da2899SCharles.Forsyth 		b.b[i] = 0xffffffff;
58937da2899SCharles.Forsyth 	b.b[c1] |= MASK(m, BLEN-1);
59037da2899SCharles.Forsyth 	b.b[c2] |= MASK(0, n);
59137da2899SCharles.Forsyth }
59237da2899SCharles.Forsyth 
59337da2899SCharles.Forsyth static void
bclrs(Bits b,int m,int n)59437da2899SCharles.Forsyth bclrs(Bits b, int m, int n)
59537da2899SCharles.Forsyth {
59637da2899SCharles.Forsyth 	int i, c1, c2;
59737da2899SCharles.Forsyth 
59837da2899SCharles.Forsyth 	if(n < 0)
59937da2899SCharles.Forsyth 		n = (b.n<<BSHIFT)-1;
60037da2899SCharles.Forsyth 	c1 = m>>BSHIFT;
60137da2899SCharles.Forsyth 	c2 = n>>BSHIFT;
60237da2899SCharles.Forsyth 	m &= BMASK;
60337da2899SCharles.Forsyth 	n &= BMASK;
60437da2899SCharles.Forsyth 	if(c1 == c2){
60537da2899SCharles.Forsyth 		b.b[c1] &= ~MASK(m, n);
60637da2899SCharles.Forsyth 		return;
60737da2899SCharles.Forsyth 	}
60837da2899SCharles.Forsyth 	for(i = c1+1; i < c2; i++)
60937da2899SCharles.Forsyth 		b.b[i] = 0;
61037da2899SCharles.Forsyth 	b.b[c1] &= ~MASK(m, BLEN-1);
61137da2899SCharles.Forsyth 	b.b[c2] &= ~MASK(0, n);
61237da2899SCharles.Forsyth }
61337da2899SCharles.Forsyth 
61437da2899SCharles.Forsyth /* b = a op b */
61537da2899SCharles.Forsyth static Bits
boper(int o,Bits a,Bits b)61637da2899SCharles.Forsyth boper(int o, Bits a, Bits b)
61737da2899SCharles.Forsyth {
61837da2899SCharles.Forsyth 	int i, n;
61937da2899SCharles.Forsyth 
62037da2899SCharles.Forsyth 	n = a.n;
62137da2899SCharles.Forsyth 	if(b.n != n)
62237da2899SCharles.Forsyth 		fatal("boper %d %d %d", o, a.n, b.n);
62337da2899SCharles.Forsyth 	for(i = 0; i < n; i++)
62437da2899SCharles.Forsyth 		b.b[i] = bop(o, a.b[i], b.b[i]);
62537da2899SCharles.Forsyth 	return b;
62637da2899SCharles.Forsyth }
62737da2899SCharles.Forsyth 
62837da2899SCharles.Forsyth static int
beq(Bits a,Bits b)62937da2899SCharles.Forsyth beq(Bits a, Bits b)
63037da2899SCharles.Forsyth {
63137da2899SCharles.Forsyth 	int i, n;
63237da2899SCharles.Forsyth 
63337da2899SCharles.Forsyth 	n = a.n;
63437da2899SCharles.Forsyth 	for(i = 0; i < n; i++)
63537da2899SCharles.Forsyth 		if(a.b[i] != b.b[i])
63637da2899SCharles.Forsyth 			return 0;
63737da2899SCharles.Forsyth 	return 1;
63837da2899SCharles.Forsyth }
63937da2899SCharles.Forsyth 
64037da2899SCharles.Forsyth static int
bzero(Bits b)64137da2899SCharles.Forsyth bzero(Bits b)
64237da2899SCharles.Forsyth {
64337da2899SCharles.Forsyth 	int i, n;
64437da2899SCharles.Forsyth 
64537da2899SCharles.Forsyth 	n = b.n;
64637da2899SCharles.Forsyth 	for(i = 0; i < n; i++)
64737da2899SCharles.Forsyth 		if(b.b[i] != 0)
64837da2899SCharles.Forsyth 			return 0;
64937da2899SCharles.Forsyth 	return 1;
65037da2899SCharles.Forsyth }
65137da2899SCharles.Forsyth 
65237da2899SCharles.Forsyth static int
bitcnt(Bits b)65337da2899SCharles.Forsyth bitcnt(Bits b)
65437da2899SCharles.Forsyth {
65537da2899SCharles.Forsyth 	int i, m, n;
65637da2899SCharles.Forsyth 
65737da2899SCharles.Forsyth 	m = b.n;
65837da2899SCharles.Forsyth 	n = 0;
65937da2899SCharles.Forsyth 	for(i = 0; i < m; i++)
66037da2899SCharles.Forsyth 		n += bitc(b.b[i]);
66137da2899SCharles.Forsyth 	return n;
66237da2899SCharles.Forsyth }
66337da2899SCharles.Forsyth 
66437da2899SCharles.Forsyth static int
topbit(Bits b)66537da2899SCharles.Forsyth topbit(Bits b)
66637da2899SCharles.Forsyth {
66737da2899SCharles.Forsyth 	int i, n;
66837da2899SCharles.Forsyth 
66937da2899SCharles.Forsyth 	n = b.n;
67037da2899SCharles.Forsyth 	for(i = n-1; i >= 0; i--)
67137da2899SCharles.Forsyth 		if(b.b[i] != 0)
67237da2899SCharles.Forsyth 			return (i<<BSHIFT)+topb(b.b[i]);
67337da2899SCharles.Forsyth 	return -1;
67437da2899SCharles.Forsyth }
67537da2899SCharles.Forsyth 
67637da2899SCharles.Forsyth static int
lowbit(Bits b)67737da2899SCharles.Forsyth lowbit(Bits b)
67837da2899SCharles.Forsyth {
67937da2899SCharles.Forsyth 	int i, n;
68037da2899SCharles.Forsyth 
68137da2899SCharles.Forsyth 	n = b.n;
68237da2899SCharles.Forsyth 	for(i = 0; i < n; i++)
68337da2899SCharles.Forsyth 		if(b.b[i] != 0)
68437da2899SCharles.Forsyth 			return (i<<BSHIFT)+lowb(b.b[i]);
68537da2899SCharles.Forsyth 	return -1;
68637da2899SCharles.Forsyth }
68737da2899SCharles.Forsyth 
68837da2899SCharles.Forsyth static void
pbits(Bits b)68937da2899SCharles.Forsyth pbits(Bits b)
69037da2899SCharles.Forsyth {
69137da2899SCharles.Forsyth 	int i, n;
69237da2899SCharles.Forsyth 
69337da2899SCharles.Forsyth 	n = b.n;
69437da2899SCharles.Forsyth 	for(i = 0; i < n; i++)
69537da2899SCharles.Forsyth 		pbit(b.b[i], i<<BSHIFT);
69637da2899SCharles.Forsyth }
69737da2899SCharles.Forsyth 
69837da2899SCharles.Forsyth static char*
decname(Decl * d)69937da2899SCharles.Forsyth decname(Decl *d)
70037da2899SCharles.Forsyth {
70137da2899SCharles.Forsyth 	if(d->sym == nil)
7026e425a9dSCharles.Forsyth 		return "<nil>";
70337da2899SCharles.Forsyth 	return d->sym->name;
70437da2899SCharles.Forsyth }
70537da2899SCharles.Forsyth 
70637da2899SCharles.Forsyth static void
warning(Inst * i,char * s,Decl * d,Decl * sd)70737da2899SCharles.Forsyth warning(Inst *i, char *s, Decl *d, Decl *sd)
70837da2899SCharles.Forsyth {
70937da2899SCharles.Forsyth 	int n;
71037da2899SCharles.Forsyth 	char *f;
71137da2899SCharles.Forsyth 	Decl *ds;
71237da2899SCharles.Forsyth 
71337da2899SCharles.Forsyth 	n = 0;
71437da2899SCharles.Forsyth 	for(ds = sd; ds != nil; ds = ds->next)
71537da2899SCharles.Forsyth 		if(ds->link == d)
71637da2899SCharles.Forsyth 			n += strlen(ds->sym->name)+1;
71737da2899SCharles.Forsyth 	if(n == 0){
71837da2899SCharles.Forsyth 		warn(i->src.start, "%s: %s", d->sym->name, s);
71937da2899SCharles.Forsyth 		return;
72037da2899SCharles.Forsyth 	}
72137da2899SCharles.Forsyth 	n += strlen(d->sym->name);
72237da2899SCharles.Forsyth 	f = malloc(n+1);
72337da2899SCharles.Forsyth 	strcpy(f, d->sym->name);
72437da2899SCharles.Forsyth 	for(ds = sd; ds != nil; ds = ds->next){
72537da2899SCharles.Forsyth 		if(ds->link == d){
72637da2899SCharles.Forsyth 			strcat(f, "/");
72737da2899SCharles.Forsyth 			strcat(f, ds->sym->name);
72837da2899SCharles.Forsyth 		}
72937da2899SCharles.Forsyth 	}
73037da2899SCharles.Forsyth 	warn(i->src.start, "%s: %s", f, s);
73137da2899SCharles.Forsyth 	free(f);
73237da2899SCharles.Forsyth }
73337da2899SCharles.Forsyth 
73437da2899SCharles.Forsyth static int
inspc(Inst * in)73537da2899SCharles.Forsyth inspc(Inst *in)
73637da2899SCharles.Forsyth {
73737da2899SCharles.Forsyth 	int n;
73837da2899SCharles.Forsyth 	Inst *i;
73937da2899SCharles.Forsyth 
74037da2899SCharles.Forsyth 	n = 0;
74137da2899SCharles.Forsyth 	for(i = in; i != nil; i = i->next)
74237da2899SCharles.Forsyth 		i->pc = n++;
74337da2899SCharles.Forsyth 	return n;
74437da2899SCharles.Forsyth }
74537da2899SCharles.Forsyth 
74637da2899SCharles.Forsyth static Inst*
pc2i(Block * b,int pc)74737da2899SCharles.Forsyth pc2i(Block *b, int pc)
74837da2899SCharles.Forsyth {
74937da2899SCharles.Forsyth 	Inst *i;
75037da2899SCharles.Forsyth 
75137da2899SCharles.Forsyth 	for( ; b != nil; b = b->next){
75237da2899SCharles.Forsyth 		if(pc > b->last->pc)
75337da2899SCharles.Forsyth 			continue;
75437da2899SCharles.Forsyth 		for(i = b->first; ; i = i->next){
75537da2899SCharles.Forsyth 			if(i->pc == pc)
75637da2899SCharles.Forsyth 				return i;
75737da2899SCharles.Forsyth 			if(i == b->last)
75837da2899SCharles.Forsyth 				fatal("pc2i a");
75937da2899SCharles.Forsyth 		}
76037da2899SCharles.Forsyth 	}
76137da2899SCharles.Forsyth 	fatal("pc2i b");
76237da2899SCharles.Forsyth 	return nil;
76337da2899SCharles.Forsyth }
76437da2899SCharles.Forsyth 
76537da2899SCharles.Forsyth static void
padr(int am,Addr * a,Inst * br)76637da2899SCharles.Forsyth padr(int am, Addr *a, Inst *br)
76737da2899SCharles.Forsyth {
76837da2899SCharles.Forsyth 	long reg;
76937da2899SCharles.Forsyth 
77037da2899SCharles.Forsyth 	if(br != nil){
77137da2899SCharles.Forsyth 		print("$%ld", br->pc);
77237da2899SCharles.Forsyth 		return;
77337da2899SCharles.Forsyth 	}
77437da2899SCharles.Forsyth 	reg = a->reg;
77537da2899SCharles.Forsyth 	if(a->decl != nil && am != Adesc)
77637da2899SCharles.Forsyth 		reg += a->decl->offset;
77737da2899SCharles.Forsyth 	switch(am){
77837da2899SCharles.Forsyth 	case Anone:
77937da2899SCharles.Forsyth 		print("-");
78037da2899SCharles.Forsyth 		break;
78137da2899SCharles.Forsyth 	case Aimm:
78237da2899SCharles.Forsyth 	case Apc:
78337da2899SCharles.Forsyth 	case Adesc:
78437da2899SCharles.Forsyth 		print("$%ld", a->offset);
78537da2899SCharles.Forsyth 		break;
78637da2899SCharles.Forsyth 	case Aoff:
78737da2899SCharles.Forsyth 		print("$%ld", a->decl->iface->offset);
78837da2899SCharles.Forsyth 		break;
78937da2899SCharles.Forsyth 	case Anoff:
79037da2899SCharles.Forsyth 		print("-$%ld", a->decl->iface->offset);
79137da2899SCharles.Forsyth 		break;
79237da2899SCharles.Forsyth 	case Afp:
79337da2899SCharles.Forsyth 		print("%ld(fp)", reg);
79437da2899SCharles.Forsyth 		break;
79537da2899SCharles.Forsyth 	case Afpind:
79637da2899SCharles.Forsyth 		print("%ld(%ld(fp))", a->offset, reg);
79737da2899SCharles.Forsyth 		break;
79837da2899SCharles.Forsyth 	case Amp:
79937da2899SCharles.Forsyth 		print("%ld(mp)", reg);
80037da2899SCharles.Forsyth 		break;
80137da2899SCharles.Forsyth 	case Ampind:
80237da2899SCharles.Forsyth 		print("%ld(%ld(mp))", a->offset, reg);
80337da2899SCharles.Forsyth 		break;
80437da2899SCharles.Forsyth 	case Aldt:
80537da2899SCharles.Forsyth 		print("$%ld", reg);
80637da2899SCharles.Forsyth 		break;
80737da2899SCharles.Forsyth 	case Aerr:
80837da2899SCharles.Forsyth 	default:
80937da2899SCharles.Forsyth 		print("%ld(%ld(?%d?))", a->offset, reg, am);
81037da2899SCharles.Forsyth 		break;
81137da2899SCharles.Forsyth 	}
81237da2899SCharles.Forsyth }
81337da2899SCharles.Forsyth 
81437da2899SCharles.Forsyth static void
pins(Inst * i)81537da2899SCharles.Forsyth pins(Inst *i)
81637da2899SCharles.Forsyth {
81737da2899SCharles.Forsyth 	/* print("%L		%ld	", i->src.start, i->pc); */
81837da2899SCharles.Forsyth 	print("		%ld	", i->pc);
819*1ca4518dSCharles.Forsyth 	if(i->op < MAXDIS)
82037da2899SCharles.Forsyth 		print("%s", instname[i->op]);
82137da2899SCharles.Forsyth 	else
82237da2899SCharles.Forsyth 		print("noop");
82337da2899SCharles.Forsyth 	print("	");
82437da2899SCharles.Forsyth 	padr(i->sm, &i->s, nil);
82537da2899SCharles.Forsyth 	print(", ");
82637da2899SCharles.Forsyth 	padr(i->mm, &i->m, nil);
82737da2899SCharles.Forsyth 	print(", ");
82837da2899SCharles.Forsyth 	padr(i->dm, &i->d, i->branch);
82937da2899SCharles.Forsyth 	print("\n");
83037da2899SCharles.Forsyth }
83137da2899SCharles.Forsyth 
83237da2899SCharles.Forsyth static void
blfree(Blist * bl)83337da2899SCharles.Forsyth blfree(Blist *bl)
83437da2899SCharles.Forsyth {
83537da2899SCharles.Forsyth 	Blist *nbl;
83637da2899SCharles.Forsyth 
83737da2899SCharles.Forsyth 	for( ; bl != nil; bl = nbl){
83837da2899SCharles.Forsyth 		nbl = bl->next;
83937da2899SCharles.Forsyth 		free(bl);
84037da2899SCharles.Forsyth 	}
84137da2899SCharles.Forsyth }
84237da2899SCharles.Forsyth 
84337da2899SCharles.Forsyth static void
freebits(Bits * bs,int nv)84437da2899SCharles.Forsyth freebits(Bits *bs, int nv)
84537da2899SCharles.Forsyth {
84637da2899SCharles.Forsyth 	int i;
84737da2899SCharles.Forsyth 
84837da2899SCharles.Forsyth 	for(i = 0; i < nv; i++)
84937da2899SCharles.Forsyth 		bfree(bs[i]);
85037da2899SCharles.Forsyth 	free(bs);
85137da2899SCharles.Forsyth }
85237da2899SCharles.Forsyth 
85337da2899SCharles.Forsyth static void
freeblks(Block * b)85437da2899SCharles.Forsyth freeblks(Block *b)
85537da2899SCharles.Forsyth {
85637da2899SCharles.Forsyth 	Block *nb;
85737da2899SCharles.Forsyth 
85837da2899SCharles.Forsyth 	for( ; b != nil; b = nb){
85937da2899SCharles.Forsyth 		blfree(b->pred);
86037da2899SCharles.Forsyth 		blfree(b->succ);
86137da2899SCharles.Forsyth 		bfree(b->kill);
86237da2899SCharles.Forsyth 		bfree(b->gen);
86337da2899SCharles.Forsyth 		bfree(b->in);
86437da2899SCharles.Forsyth 		bfree(b->out);
86537da2899SCharles.Forsyth 		nb = b->next;
86637da2899SCharles.Forsyth 		free(b);
86737da2899SCharles.Forsyth 	}
86837da2899SCharles.Forsyth }
86937da2899SCharles.Forsyth 
87037da2899SCharles.Forsyth static int
len(Decl * d)87137da2899SCharles.Forsyth len(Decl *d)
87237da2899SCharles.Forsyth {
87337da2899SCharles.Forsyth 	int n;
87437da2899SCharles.Forsyth 
87537da2899SCharles.Forsyth 	n = 0;
87637da2899SCharles.Forsyth 	for( ; d != nil; d = d->next)
87737da2899SCharles.Forsyth 		n++;
87837da2899SCharles.Forsyth 	return n;
87937da2899SCharles.Forsyth }
88037da2899SCharles.Forsyth 
88137da2899SCharles.Forsyth static Bits*
allocbits(int nv,int npc)88237da2899SCharles.Forsyth allocbits(int nv, int npc)
88337da2899SCharles.Forsyth {
88437da2899SCharles.Forsyth 	int i;
88537da2899SCharles.Forsyth 	Bits *defs;
88637da2899SCharles.Forsyth 
88737da2899SCharles.Forsyth 	defs = (Bits*)allocmem(nv*sizeof(Bits));
88837da2899SCharles.Forsyth 	for(i = 0; i < nv; i++)
88937da2899SCharles.Forsyth 		defs[i] = bnew(npc, 1);
89037da2899SCharles.Forsyth 	return defs;
89137da2899SCharles.Forsyth }
89237da2899SCharles.Forsyth 
89337da2899SCharles.Forsyth static int
bitcount(Bits * bs,int nv)89437da2899SCharles.Forsyth bitcount(Bits *bs, int nv)
89537da2899SCharles.Forsyth {
89637da2899SCharles.Forsyth 	int i, n;
89737da2899SCharles.Forsyth 
89837da2899SCharles.Forsyth 	n = 0;
89937da2899SCharles.Forsyth 	for(i = 0; i < nv; i++)
90037da2899SCharles.Forsyth 		n += bitcnt(bs[i]);
90137da2899SCharles.Forsyth 	return n;
90237da2899SCharles.Forsyth }
90337da2899SCharles.Forsyth 
90437da2899SCharles.Forsyth static Block*
mkblock(Inst * i)90537da2899SCharles.Forsyth mkblock(Inst *i)
90637da2899SCharles.Forsyth {
90737da2899SCharles.Forsyth 	Block *b;
90837da2899SCharles.Forsyth 
90937da2899SCharles.Forsyth 	b = allocmem(sizeof(Block));
91037da2899SCharles.Forsyth 	*b = zblock;
91137da2899SCharles.Forsyth 	b->first = b->last = i;
91237da2899SCharles.Forsyth 	return b;
91337da2899SCharles.Forsyth }
91437da2899SCharles.Forsyth 
91537da2899SCharles.Forsyth static Blist*
mkblist(Block * b,Blist * nbl)91637da2899SCharles.Forsyth mkblist(Block *b, Blist *nbl)
91737da2899SCharles.Forsyth {
91837da2899SCharles.Forsyth 	Blist *bl;
91937da2899SCharles.Forsyth 
92037da2899SCharles.Forsyth 	bl = allocmem(sizeof(Blist));
92137da2899SCharles.Forsyth 	bl->block = b;
92237da2899SCharles.Forsyth 	bl->next = nbl;
92337da2899SCharles.Forsyth 	return bl;
92437da2899SCharles.Forsyth }
92537da2899SCharles.Forsyth 
92637da2899SCharles.Forsyth static void
leader(Inst * i,Array * ab)92737da2899SCharles.Forsyth leader(Inst *i, Array *ab)
92837da2899SCharles.Forsyth {
92937da2899SCharles.Forsyth 	int m, n;
93037da2899SCharles.Forsyth 	Block *b, **a;
93137da2899SCharles.Forsyth 
93237da2899SCharles.Forsyth 	if(i != nil && i->pc == 0){
93337da2899SCharles.Forsyth 		if((n = ab->n) == (m = ab->m)){
93437da2899SCharles.Forsyth 			a = ab->a;
93537da2899SCharles.Forsyth 			ab->a = allocmem(2*m*sizeof(Block*));
93637da2899SCharles.Forsyth 			memcpy(ab->a, a, m*sizeof(Block*));
93737da2899SCharles.Forsyth 			ab->m = 2*m;
93837da2899SCharles.Forsyth 			free(a);
93937da2899SCharles.Forsyth 		}
94037da2899SCharles.Forsyth 		b = mkblock(i);
94137da2899SCharles.Forsyth 		b->dfn = n;
94237da2899SCharles.Forsyth 		ab->a[n] = b;
94337da2899SCharles.Forsyth 		i->pc = ab->n = n+1;
94437da2899SCharles.Forsyth 	}
94537da2899SCharles.Forsyth }
94637da2899SCharles.Forsyth 
94737da2899SCharles.Forsyth static Block*
findb(Inst * i,Array * ab)94837da2899SCharles.Forsyth findb(Inst *i, Array *ab)
94937da2899SCharles.Forsyth {
95037da2899SCharles.Forsyth 	if(i == nil)
95137da2899SCharles.Forsyth 		return nil;
95237da2899SCharles.Forsyth 	if(i->pc <= 0)
95337da2899SCharles.Forsyth 		fatal("pc <= 0 in findb");
95437da2899SCharles.Forsyth 	return ab->a[i->pc-1];
95537da2899SCharles.Forsyth }
95637da2899SCharles.Forsyth 
95737da2899SCharles.Forsyth static int
memb(Block * b,Blist * bl)95837da2899SCharles.Forsyth memb(Block *b, Blist *bl)
95937da2899SCharles.Forsyth {
96037da2899SCharles.Forsyth 	for( ; bl != nil; bl = bl->next)
96137da2899SCharles.Forsyth 		if(bl->block == b)
96237da2899SCharles.Forsyth 			return 1;
96337da2899SCharles.Forsyth 	return 0;
96437da2899SCharles.Forsyth }
96537da2899SCharles.Forsyth 
96637da2899SCharles.Forsyth static int
canfallthrough(Inst * i)96737da2899SCharles.Forsyth canfallthrough(Inst *i)
96837da2899SCharles.Forsyth {
96937da2899SCharles.Forsyth 	if(i == nil)
97037da2899SCharles.Forsyth 		return 0;
97137da2899SCharles.Forsyth 	switch(i->op){
97237da2899SCharles.Forsyth 	case IGOTO:
97337da2899SCharles.Forsyth 	case ICASE:
97437da2899SCharles.Forsyth 	case ICASEL:
97537da2899SCharles.Forsyth 	case ICASEC:
97637da2899SCharles.Forsyth 	case IRET:
97737da2899SCharles.Forsyth 	case IEXIT:
97837da2899SCharles.Forsyth 	case IRAISE:
97937da2899SCharles.Forsyth 	case IJMP:
98037da2899SCharles.Forsyth 		return 0;
98137da2899SCharles.Forsyth 	case INOOP:
98237da2899SCharles.Forsyth 		return i->branch != nil;
98337da2899SCharles.Forsyth 	}
98437da2899SCharles.Forsyth 	return 1;
98537da2899SCharles.Forsyth }
98637da2899SCharles.Forsyth 
98737da2899SCharles.Forsyth static void
predsucc(Block * b1,Block * b2)98837da2899SCharles.Forsyth predsucc(Block *b1, Block *b2)
98937da2899SCharles.Forsyth {
99037da2899SCharles.Forsyth 	if(b1 == nil || b2 == nil)
99137da2899SCharles.Forsyth 		return;
99237da2899SCharles.Forsyth 	if(!memb(b1, b2->pred))
99337da2899SCharles.Forsyth 		b2->pred = mkblist(b1, b2->pred);
99437da2899SCharles.Forsyth 	if(!memb(b2, b1->succ))
99537da2899SCharles.Forsyth 		b1->succ = mkblist(b2, b1->succ);
99637da2899SCharles.Forsyth }
99737da2899SCharles.Forsyth 
99837da2899SCharles.Forsyth static Block*
mkblocks(Inst * in,int * nb)99937da2899SCharles.Forsyth mkblocks(Inst *in, int *nb)
100037da2899SCharles.Forsyth {
100137da2899SCharles.Forsyth 	Inst *i;
100237da2899SCharles.Forsyth 	Block *b, *firstb, *lastb;
100337da2899SCharles.Forsyth 	Label *lab;
100437da2899SCharles.Forsyth 	Array *ab;
100537da2899SCharles.Forsyth 	int j, n;
100637da2899SCharles.Forsyth 
100737da2899SCharles.Forsyth 	ab = allocmem(sizeof(Array));
100837da2899SCharles.Forsyth 	ab->n = 0;
100937da2899SCharles.Forsyth 	ab->m = 16;
101037da2899SCharles.Forsyth 	ab->a = allocmem(ab->m*sizeof(Block*));
101137da2899SCharles.Forsyth 	leader(in, ab);
101237da2899SCharles.Forsyth 	for(i = in; i != nil; i = i->next){
101337da2899SCharles.Forsyth 		switch(i->op){
101437da2899SCharles.Forsyth 		case IGOTO:
101537da2899SCharles.Forsyth 		case ICASE:
101637da2899SCharles.Forsyth 		case ICASEL:
101737da2899SCharles.Forsyth 		case ICASEC:
101837da2899SCharles.Forsyth 		case INOOP:
101937da2899SCharles.Forsyth 			if(i->op == INOOP && i->branch != nil){
102037da2899SCharles.Forsyth 				leader(i->branch, ab);
102137da2899SCharles.Forsyth 				leader(i->next, ab);
102237da2899SCharles.Forsyth 				break;
102337da2899SCharles.Forsyth 			}
102437da2899SCharles.Forsyth 			leader(i->d.decl->ty->cse->iwild, ab);
102537da2899SCharles.Forsyth 			lab = i->d.decl->ty->cse->labs;
102637da2899SCharles.Forsyth 			n = i->d.decl->ty->cse->nlab;
102737da2899SCharles.Forsyth 			for(j = 0; j < n; j++)
102837da2899SCharles.Forsyth 				leader(lab[j].inst, ab);
102937da2899SCharles.Forsyth 			leader(i->next, ab);
103037da2899SCharles.Forsyth 			break;
103137da2899SCharles.Forsyth 		case IRET:
103237da2899SCharles.Forsyth 		case IEXIT:
103337da2899SCharles.Forsyth 		case IRAISE:
103437da2899SCharles.Forsyth 			leader(i->next, ab);
103537da2899SCharles.Forsyth 			break;
103637da2899SCharles.Forsyth 		case IJMP:
103737da2899SCharles.Forsyth 			leader(i->branch, ab);
103837da2899SCharles.Forsyth 			leader(i->next, ab);
103937da2899SCharles.Forsyth 			break;
104037da2899SCharles.Forsyth 		default:
104137da2899SCharles.Forsyth 			if(i->branch != nil){
104237da2899SCharles.Forsyth 				leader(i->branch, ab);
104337da2899SCharles.Forsyth 				leader(i->next, ab);
104437da2899SCharles.Forsyth 			}
104537da2899SCharles.Forsyth 			break;
104637da2899SCharles.Forsyth 		}
104737da2899SCharles.Forsyth 	}
104837da2899SCharles.Forsyth 	firstb = lastb = mkblock(nil);
104937da2899SCharles.Forsyth 	for(i = in; i != nil; i = i->next){
105037da2899SCharles.Forsyth 		if(i->pc != 0){
105137da2899SCharles.Forsyth 			b = findb(i, ab);
105237da2899SCharles.Forsyth 			b->prev = lastb;
105337da2899SCharles.Forsyth 			lastb->next = b;
105437da2899SCharles.Forsyth 			if(canfallthrough(lastb->last))
105537da2899SCharles.Forsyth 				predsucc(lastb, b);
105637da2899SCharles.Forsyth 			lastb = b;
105737da2899SCharles.Forsyth 		}
105837da2899SCharles.Forsyth 		else
105937da2899SCharles.Forsyth 			lastb->last = i;
106037da2899SCharles.Forsyth 		switch(i->op){
106137da2899SCharles.Forsyth 		case IGOTO:
106237da2899SCharles.Forsyth 		case ICASE:
106337da2899SCharles.Forsyth 		case ICASEL:
106437da2899SCharles.Forsyth 		case ICASEC:
106537da2899SCharles.Forsyth 		case INOOP:
106637da2899SCharles.Forsyth 			if(i->op == INOOP && i->branch != nil){
106737da2899SCharles.Forsyth 				b = findb(i->next, ab);
106837da2899SCharles.Forsyth 				predsucc(lastb, b);
106937da2899SCharles.Forsyth 				b = findb(i->branch, ab);
107037da2899SCharles.Forsyth 				predsucc(lastb, b);
107137da2899SCharles.Forsyth 				break;
107237da2899SCharles.Forsyth 			}
107337da2899SCharles.Forsyth 			b = findb(i->d.decl->ty->cse->iwild, ab);
107437da2899SCharles.Forsyth 			predsucc(lastb, b);
107537da2899SCharles.Forsyth 			lab = i->d.decl->ty->cse->labs;
107637da2899SCharles.Forsyth 			n = i->d.decl->ty->cse->nlab;
107737da2899SCharles.Forsyth 			for(j = 0; j < n; j++){
107837da2899SCharles.Forsyth 				b = findb(lab[j].inst, ab);
107937da2899SCharles.Forsyth 				predsucc(lastb, b);
108037da2899SCharles.Forsyth 			}
108137da2899SCharles.Forsyth 			break;
108237da2899SCharles.Forsyth 		case IRET:
108337da2899SCharles.Forsyth 		case IEXIT:
108437da2899SCharles.Forsyth 		case IRAISE:
108537da2899SCharles.Forsyth 			break;
108637da2899SCharles.Forsyth 		case IJMP:
108737da2899SCharles.Forsyth 			b = findb(i->branch, ab);
108837da2899SCharles.Forsyth 			predsucc(lastb, b);
108937da2899SCharles.Forsyth 			break;
109037da2899SCharles.Forsyth 		default:
109137da2899SCharles.Forsyth 			if(i->branch != nil){
109237da2899SCharles.Forsyth 				b = findb(i->next, ab);
109337da2899SCharles.Forsyth 				predsucc(lastb, b);
109437da2899SCharles.Forsyth 				b = findb(i->branch, ab);
109537da2899SCharles.Forsyth 				predsucc(lastb, b);
109637da2899SCharles.Forsyth 			}
109737da2899SCharles.Forsyth 			break;
109837da2899SCharles.Forsyth 		}
109937da2899SCharles.Forsyth 	}
110037da2899SCharles.Forsyth 	*nb = ab->n;
110137da2899SCharles.Forsyth 	free(ab->a);
110237da2899SCharles.Forsyth 	free(ab);
110337da2899SCharles.Forsyth 	b = firstb->next;
110437da2899SCharles.Forsyth 	b->prev = nil;
110537da2899SCharles.Forsyth 	return b;
110637da2899SCharles.Forsyth }
110737da2899SCharles.Forsyth 
110837da2899SCharles.Forsyth static int
back(Block * b1,Block * b2)110937da2899SCharles.Forsyth back(Block *b1, Block *b2)
111037da2899SCharles.Forsyth {
111137da2899SCharles.Forsyth 	return b1->dfn >= b2->dfn;
111237da2899SCharles.Forsyth }
111337da2899SCharles.Forsyth 
111437da2899SCharles.Forsyth static void
pblocks(Block * b,int nb)111537da2899SCharles.Forsyth pblocks(Block *b, int nb)
111637da2899SCharles.Forsyth {
111737da2899SCharles.Forsyth 	Inst *i;
111837da2899SCharles.Forsyth 	Blist *bl;
111937da2899SCharles.Forsyth 
112037da2899SCharles.Forsyth 	print("--------------------%d blocks--------------------\n", nb);
112137da2899SCharles.Forsyth 	print("------------------------------------------------\n");
112237da2899SCharles.Forsyth 	for( ; b != nil; b = b->next){
112337da2899SCharles.Forsyth 		print("dfn=%d\n", b->dfn);
112437da2899SCharles.Forsyth 		print("    pred	");
112537da2899SCharles.Forsyth 		for(bl = b->pred; bl != nil; bl = bl->next)
112637da2899SCharles.Forsyth 			print("%d%s ", bl->block->dfn, back(bl->block, b) ? "*" : "");
112737da2899SCharles.Forsyth 		print("\n");
112837da2899SCharles.Forsyth 		print("    succ	");
112937da2899SCharles.Forsyth 		for(bl = b->succ; bl != nil; bl = bl->next)
113037da2899SCharles.Forsyth 			print("%d%s ", bl->block->dfn, back(b, bl->block) ? "*" : "");
113137da2899SCharles.Forsyth 		print("\n");
113237da2899SCharles.Forsyth 		for(i = b->first; i != nil; i = i->next){
113337da2899SCharles.Forsyth 			// print("	%I\n", i);
113437da2899SCharles.Forsyth 			pins(i);
113537da2899SCharles.Forsyth 			if(i == b->last)
113637da2899SCharles.Forsyth 				break;
113737da2899SCharles.Forsyth 		}
113837da2899SCharles.Forsyth 	}
113937da2899SCharles.Forsyth 	print("------------------------------------------------\n");
114037da2899SCharles.Forsyth }
114137da2899SCharles.Forsyth 
114237da2899SCharles.Forsyth static void
ckblocks(Inst * in,Block * b,int nb)114337da2899SCharles.Forsyth ckblocks(Inst *in, Block *b, int nb)
114437da2899SCharles.Forsyth {
114537da2899SCharles.Forsyth 	int n;
114637da2899SCharles.Forsyth 	Block *lastb;
114737da2899SCharles.Forsyth 
114837da2899SCharles.Forsyth 	if(b->first != in)
114937da2899SCharles.Forsyth 		fatal("A - %d", b->dfn);
115037da2899SCharles.Forsyth 	n = 0;
115137da2899SCharles.Forsyth 	lastb = nil;
115237da2899SCharles.Forsyth 	for( ; b != nil; b = b->next){
115337da2899SCharles.Forsyth 		n++;
115437da2899SCharles.Forsyth 		if(b->prev != lastb)
115537da2899SCharles.Forsyth 			fatal("a - %d\n", b->dfn);
115637da2899SCharles.Forsyth 		if(b->prev != nil && b->prev->next != b)
115737da2899SCharles.Forsyth 			fatal("b - %d\n", b->dfn);
115837da2899SCharles.Forsyth 		if(b->next != nil && b->next->prev != b)
115937da2899SCharles.Forsyth 			fatal("c - %d\n", b->dfn);
116037da2899SCharles.Forsyth 
116137da2899SCharles.Forsyth 		if(b->prev != nil && b->prev->last->next != b->first)
116237da2899SCharles.Forsyth 			fatal("B - %d\n", b->dfn);
116337da2899SCharles.Forsyth 		if(b->next != nil && b->last->next != b->next->first)
116437da2899SCharles.Forsyth 			fatal("C - %d\n", b->dfn);
116537da2899SCharles.Forsyth 		if(b->next == nil && b->last->next != nil)
116637da2899SCharles.Forsyth 			fatal("D - %d\n", b->dfn);
116737da2899SCharles.Forsyth 
116837da2899SCharles.Forsyth 		if(b->last->branch != nil && b->succ->block->first != b->last->branch)
116937da2899SCharles.Forsyth 			fatal("0 - %d\n", b->dfn);
117037da2899SCharles.Forsyth 
117137da2899SCharles.Forsyth 		lastb = b;
117237da2899SCharles.Forsyth 	}
117337da2899SCharles.Forsyth 	if(n != nb)
117437da2899SCharles.Forsyth 		fatal("N - %d %d\n", n, nb);
117537da2899SCharles.Forsyth }
117637da2899SCharles.Forsyth 
117737da2899SCharles.Forsyth static void
dfs0(Block * b,int * n)117837da2899SCharles.Forsyth dfs0(Block *b, int *n)
117937da2899SCharles.Forsyth {
118037da2899SCharles.Forsyth 	Block *s;
118137da2899SCharles.Forsyth 	Blist *bl;
118237da2899SCharles.Forsyth 
118337da2899SCharles.Forsyth 	b->flags = 1;
118437da2899SCharles.Forsyth 	for(bl = b->succ; bl != nil; bl = bl->next){
118537da2899SCharles.Forsyth 		s = bl->block;
118637da2899SCharles.Forsyth 		if(s->flags == 0)
118737da2899SCharles.Forsyth 			dfs0(s, n);
118837da2899SCharles.Forsyth 	}
118937da2899SCharles.Forsyth 	b->dfn = --(*n);
119037da2899SCharles.Forsyth }
119137da2899SCharles.Forsyth 
119237da2899SCharles.Forsyth static int
dfs(Block * b,int nb)119337da2899SCharles.Forsyth dfs(Block *b, int nb)
119437da2899SCharles.Forsyth {
119537da2899SCharles.Forsyth 	int n, u;
119637da2899SCharles.Forsyth 	Block *b0;
119737da2899SCharles.Forsyth 
119837da2899SCharles.Forsyth 	b0 = b;
119937da2899SCharles.Forsyth 	n = nb;
120037da2899SCharles.Forsyth 	dfs0(b0, &n);
120137da2899SCharles.Forsyth 	u = 0;
120237da2899SCharles.Forsyth 	for(b = b0; b != nil; b = b->next){
120337da2899SCharles.Forsyth 		if(b->flags == 0){	/* unreachable: see foldbranch */
120437da2899SCharles.Forsyth 			fatal("found unreachable code");
120537da2899SCharles.Forsyth 			u++;
120637da2899SCharles.Forsyth 			b->prev->next = b->next;
120737da2899SCharles.Forsyth 			if(b->next){
120837da2899SCharles.Forsyth 				b->next->prev = b->prev;
120937da2899SCharles.Forsyth 				b->prev->last->next = b->next->first;
121037da2899SCharles.Forsyth 			}
121137da2899SCharles.Forsyth 			else
121237da2899SCharles.Forsyth 				b->prev->last->next = nil;
121337da2899SCharles.Forsyth 		}
121437da2899SCharles.Forsyth 		b->flags = 0;
121537da2899SCharles.Forsyth 	}
121637da2899SCharles.Forsyth 	if(u){
121737da2899SCharles.Forsyth 		for(b = b0; b != nil; b = b->next)
121837da2899SCharles.Forsyth 			b->dfn -= u;
121937da2899SCharles.Forsyth 	}
122037da2899SCharles.Forsyth 	return nb-u;
122137da2899SCharles.Forsyth }
122237da2899SCharles.Forsyth 
122337da2899SCharles.Forsyth static void
loop0(Block * b)122437da2899SCharles.Forsyth loop0(Block *b)
122537da2899SCharles.Forsyth {
122637da2899SCharles.Forsyth 	Block *p;
122737da2899SCharles.Forsyth 	Blist *bl;
122837da2899SCharles.Forsyth 
122937da2899SCharles.Forsyth 	b->flags = 1;
123037da2899SCharles.Forsyth 	for(bl = b->pred; bl != nil; bl = bl->next){
123137da2899SCharles.Forsyth 		p = bl->block;
123237da2899SCharles.Forsyth 		if(p->flags == 0)
123337da2899SCharles.Forsyth 			loop0(p);
123437da2899SCharles.Forsyth 	}
123537da2899SCharles.Forsyth }
123637da2899SCharles.Forsyth 
123737da2899SCharles.Forsyth /* b1->b2 a back edge */
123837da2899SCharles.Forsyth static void
loop(Block * b,Block * b1,Block * b2)123937da2899SCharles.Forsyth loop(Block *b, Block *b1, Block *b2)
124037da2899SCharles.Forsyth {
124137da2899SCharles.Forsyth 	if(0 && debug['o'])
124237da2899SCharles.Forsyth 		print("back edge %d->%d\n", b1->dfn, b2->dfn);
124337da2899SCharles.Forsyth 	b2->flags = 1;
124437da2899SCharles.Forsyth 	if(b1->flags == 0)
124537da2899SCharles.Forsyth 		loop0(b1);
124637da2899SCharles.Forsyth 	if(0 && debug['o'])
124737da2899SCharles.Forsyth 		print("	loop	");
124837da2899SCharles.Forsyth 	for( ; b != nil; b = b->next){
124937da2899SCharles.Forsyth 		if(b->flags && 0 && debug['o'])
125037da2899SCharles.Forsyth 			print("%d ", b->dfn);
125137da2899SCharles.Forsyth 		b->flags = 0;
125237da2899SCharles.Forsyth 	}
125337da2899SCharles.Forsyth 	if(0 && debug['o'])
125437da2899SCharles.Forsyth 		print("\n");
125537da2899SCharles.Forsyth }
125637da2899SCharles.Forsyth 
125737da2899SCharles.Forsyth static void
loops(Block * b)125837da2899SCharles.Forsyth loops(Block *b)
125937da2899SCharles.Forsyth {
126037da2899SCharles.Forsyth 	Block *b0;
126137da2899SCharles.Forsyth 	Blist *bl;
126237da2899SCharles.Forsyth 
126337da2899SCharles.Forsyth 	b0 = b;
126437da2899SCharles.Forsyth 	for( ; b != nil; b = b->next){
126537da2899SCharles.Forsyth 		for(bl = b->succ; bl != nil; bl = bl->next){
126637da2899SCharles.Forsyth 			if(back(b, bl->block))
126737da2899SCharles.Forsyth 				loop(b0, b, bl->block);
126837da2899SCharles.Forsyth 		}
126937da2899SCharles.Forsyth 	}
127037da2899SCharles.Forsyth }
127137da2899SCharles.Forsyth 
127237da2899SCharles.Forsyth static int
imm(int m,Addr * a)127337da2899SCharles.Forsyth imm(int m, Addr *a)
127437da2899SCharles.Forsyth {
127537da2899SCharles.Forsyth 	if(m == Aimm)
127637da2899SCharles.Forsyth 		return a->offset;
127737da2899SCharles.Forsyth 	fatal("bad immediate value");
127837da2899SCharles.Forsyth 	return -1;
127937da2899SCharles.Forsyth }
128037da2899SCharles.Forsyth 
128137da2899SCharles.Forsyth static int
desc(int m,Addr * a)128237da2899SCharles.Forsyth desc(int m, Addr *a)
128337da2899SCharles.Forsyth {
128437da2899SCharles.Forsyth 	if(m == Adesc)
128537da2899SCharles.Forsyth 		return a->decl->desc->size;
128637da2899SCharles.Forsyth 	fatal("bad descriptor value");
128737da2899SCharles.Forsyth 	return -1;
128837da2899SCharles.Forsyth }
128937da2899SCharles.Forsyth 
129037da2899SCharles.Forsyth static int
fpoff(int m,Addr * a)129137da2899SCharles.Forsyth fpoff(int m, Addr *a)
129237da2899SCharles.Forsyth {
129337da2899SCharles.Forsyth 	int off;
129437da2899SCharles.Forsyth 	Decl *d;
129537da2899SCharles.Forsyth 
129637da2899SCharles.Forsyth 	if(m == Afp || m == Afpind){
129737da2899SCharles.Forsyth 		off = a->reg;
129837da2899SCharles.Forsyth 		if((d = a->decl) != nil)
129937da2899SCharles.Forsyth 			off += d->offset;
130037da2899SCharles.Forsyth 		return off;
130137da2899SCharles.Forsyth 	}
130237da2899SCharles.Forsyth 	return -1;
130337da2899SCharles.Forsyth }
130437da2899SCharles.Forsyth 
130537da2899SCharles.Forsyth static int
size(Inst * i)130637da2899SCharles.Forsyth size(Inst *i)
130737da2899SCharles.Forsyth {
130837da2899SCharles.Forsyth 	switch(i->op){
130937da2899SCharles.Forsyth 	case ISEND:
131037da2899SCharles.Forsyth 	case IRECV:
131137da2899SCharles.Forsyth 	case IALT:
131237da2899SCharles.Forsyth 	case INBALT:
131337da2899SCharles.Forsyth 	case ILEA:
131437da2899SCharles.Forsyth 		return i->m.offset;
131537da2899SCharles.Forsyth 	case IMOVM:
131637da2899SCharles.Forsyth 	case IHEADM:
131737da2899SCharles.Forsyth 	case ICONSM:
131837da2899SCharles.Forsyth 		return imm(i->mm, &i->m);
131937da2899SCharles.Forsyth 	case IMOVMP:
132037da2899SCharles.Forsyth 	case IHEADMP:
132137da2899SCharles.Forsyth 	case ICONSMP:
132237da2899SCharles.Forsyth 		return desc(i->mm, &i->m);
132337da2899SCharles.Forsyth 		break;
132437da2899SCharles.Forsyth 	}
132537da2899SCharles.Forsyth 	fatal("bad op in size");
132637da2899SCharles.Forsyth 	return -1;
132737da2899SCharles.Forsyth }
132837da2899SCharles.Forsyth 
132937da2899SCharles.Forsyth static Decl*
mkdec(int o)133037da2899SCharles.Forsyth mkdec(int o)
133137da2899SCharles.Forsyth {
133237da2899SCharles.Forsyth 	Decl *d;
133337da2899SCharles.Forsyth 
133437da2899SCharles.Forsyth 	d = mkdecl(&nosrc, Dlocal, tint);
133537da2899SCharles.Forsyth 	d->offset = o;
133637da2899SCharles.Forsyth 	return d;
133737da2899SCharles.Forsyth }
133837da2899SCharles.Forsyth 
133937da2899SCharles.Forsyth static void
mkdecls(void)134037da2899SCharles.Forsyth mkdecls(void)
134137da2899SCharles.Forsyth {
134237da2899SCharles.Forsyth 	regdecls = mkdec(REGRET*IBY2WD);
134337da2899SCharles.Forsyth 	regdecls->next = mkdec(STemp);
134437da2899SCharles.Forsyth 	regdecls->next->next = mkdec(DTemp);
134537da2899SCharles.Forsyth }
134637da2899SCharles.Forsyth 
134737da2899SCharles.Forsyth static Decl*
sharedecls(Decl * d)134837da2899SCharles.Forsyth sharedecls(Decl *d)
134937da2899SCharles.Forsyth {
135037da2899SCharles.Forsyth 	Decl *ld;
135137da2899SCharles.Forsyth 
135237da2899SCharles.Forsyth 	ld = d;
135337da2899SCharles.Forsyth 	for(d = d->next ; d != nil; d = d->next){
135437da2899SCharles.Forsyth 		if(d->offset <= ld->offset)
135537da2899SCharles.Forsyth 			break;
135637da2899SCharles.Forsyth 		ld = d;
135737da2899SCharles.Forsyth 	}
135837da2899SCharles.Forsyth 	return d;
135937da2899SCharles.Forsyth }
136037da2899SCharles.Forsyth 
136137da2899SCharles.Forsyth static int
finddec(int o,int s,Decl * vars,int * nv,Inst * i)136237da2899SCharles.Forsyth finddec(int o, int s, Decl *vars, int *nv, Inst *i)
136337da2899SCharles.Forsyth {
136437da2899SCharles.Forsyth 	int m, n;
136537da2899SCharles.Forsyth 	Decl *d;
136637da2899SCharles.Forsyth 
136737da2899SCharles.Forsyth 	n = 0;
136837da2899SCharles.Forsyth 	for(d = vars; d != nil; d = d->next){
136937da2899SCharles.Forsyth 		if(o >= d->offset && o < d->offset+d->ty->size){
137037da2899SCharles.Forsyth 			m = 1;
137137da2899SCharles.Forsyth 			while(o+s > d->offset+d->ty->size){
137237da2899SCharles.Forsyth 				m++;
137337da2899SCharles.Forsyth 				d = d->next;
137437da2899SCharles.Forsyth 			}
137537da2899SCharles.Forsyth 			*nv = m;
137637da2899SCharles.Forsyth 			return n;
137737da2899SCharles.Forsyth 		}
137837da2899SCharles.Forsyth 		n++;
137937da2899SCharles.Forsyth 	}
138037da2899SCharles.Forsyth 	// print("%d %d missing\n", o, s);
138137da2899SCharles.Forsyth 	pins(i);
138237da2899SCharles.Forsyth 	fatal("missing decl");
138337da2899SCharles.Forsyth 	return -1;
138437da2899SCharles.Forsyth }
138537da2899SCharles.Forsyth 
138637da2899SCharles.Forsyth static void
setud(Bits * b,int id,int n,int pc)138737da2899SCharles.Forsyth setud(Bits *b, int id, int n, int pc)
138837da2899SCharles.Forsyth {
138937da2899SCharles.Forsyth 	if(id < 0)
139037da2899SCharles.Forsyth 		return;
139137da2899SCharles.Forsyth 	while(--n >= 0)
139237da2899SCharles.Forsyth 		bset(b[id++], pc);
139337da2899SCharles.Forsyth }
139437da2899SCharles.Forsyth 
139537da2899SCharles.Forsyth static void
ud(Inst * i,Decl * vars,Bits * uses,Bits * defs)139637da2899SCharles.Forsyth ud(Inst *i, Decl *vars, Bits *uses, Bits *defs)
139737da2899SCharles.Forsyth {
139837da2899SCharles.Forsyth 	ushort f;
139937da2899SCharles.Forsyth 	int id, j, nv, pc, sz, s, m, d, ss, sm, sd;
140037da2899SCharles.Forsyth 	Optab *t;
140137da2899SCharles.Forsyth 	Idlist *l;
140237da2899SCharles.Forsyth 
140337da2899SCharles.Forsyth 	pc = i->pc;
140437da2899SCharles.Forsyth 	ss = 0;
140537da2899SCharles.Forsyth 	t = &opflags[i->op];
140637da2899SCharles.Forsyth 	f = t->flags;
140737da2899SCharles.Forsyth 	sz = t->size;
140837da2899SCharles.Forsyth 	s = fpoff(i->sm, &i->s);
140937da2899SCharles.Forsyth 	m = fpoff(i->mm, &i->m);
141037da2899SCharles.Forsyth 	d = fpoff(i->dm, &i->d);
141137da2899SCharles.Forsyth 	if(f&Mduse && i->mm == Anone)
141237da2899SCharles.Forsyth 		f |= Duse;
141337da2899SCharles.Forsyth 	if(s >= 0){
141437da2899SCharles.Forsyth 		if(i->sm == Afp){
141537da2899SCharles.Forsyth 			ss = SS(sz);
141637da2899SCharles.Forsyth 			if(ss == Mp)
141737da2899SCharles.Forsyth 				ss = size(i);
141837da2899SCharles.Forsyth 		}
141937da2899SCharles.Forsyth 		else
142037da2899SCharles.Forsyth 			ss = IBY2WD;
142137da2899SCharles.Forsyth 		id = finddec(s, ss, vars, &nv, i);
142237da2899SCharles.Forsyth 		if(f&Suse)
142337da2899SCharles.Forsyth 			setud(uses, id, nv, pc);
142437da2899SCharles.Forsyth 		if(f&Sdef){
142537da2899SCharles.Forsyth 			if(i->sm == Afp)
142637da2899SCharles.Forsyth 				setud(defs, id, nv, pc);
142737da2899SCharles.Forsyth 			else
142837da2899SCharles.Forsyth 				setud(uses, id, nv, pc);
142937da2899SCharles.Forsyth 		}
143037da2899SCharles.Forsyth 	}
143137da2899SCharles.Forsyth 	if(m >= 0){
143237da2899SCharles.Forsyth 		if(i->mm == Afp){
143337da2899SCharles.Forsyth 			sm = SM(sz);
143437da2899SCharles.Forsyth 			if(sm == Mp)
143537da2899SCharles.Forsyth 				sm = size(i);
143637da2899SCharles.Forsyth 		}
143737da2899SCharles.Forsyth 		else
143837da2899SCharles.Forsyth 			sm = IBY2WD;
143937da2899SCharles.Forsyth 		id = finddec(m, sm, vars, &nv, i);
144037da2899SCharles.Forsyth 		if(f&Muse)
144137da2899SCharles.Forsyth 			setud(uses, id, nv, pc);
144237da2899SCharles.Forsyth 		if(f&Mdef){
144337da2899SCharles.Forsyth 			if(i->mm == Afp)
144437da2899SCharles.Forsyth 				setud(defs, id, nv, pc);
144537da2899SCharles.Forsyth 			else
144637da2899SCharles.Forsyth 				setud(uses, id, nv, pc);
144737da2899SCharles.Forsyth 		}
144837da2899SCharles.Forsyth 	}
144937da2899SCharles.Forsyth 	if(d >= 0){
145037da2899SCharles.Forsyth 		if(i->dm == Afp){
145137da2899SCharles.Forsyth 			sd = SD(sz);
145237da2899SCharles.Forsyth 			if(sd == Mp)
145337da2899SCharles.Forsyth 				sd = size(i);
145437da2899SCharles.Forsyth 		}
145537da2899SCharles.Forsyth 		else
145637da2899SCharles.Forsyth 			sd = IBY2WD;
145737da2899SCharles.Forsyth 		id = finddec(d, sd, vars, &nv, i);
145837da2899SCharles.Forsyth 		if(f&Duse)
145937da2899SCharles.Forsyth 			setud(uses, id, nv, pc);
146037da2899SCharles.Forsyth 		if(f&Ddef){
146137da2899SCharles.Forsyth 			if(i->dm == Afp)
146237da2899SCharles.Forsyth 				setud(defs, id, nv, pc);
146337da2899SCharles.Forsyth 			else
146437da2899SCharles.Forsyth 				setud(uses, id, nv, pc);
146537da2899SCharles.Forsyth 		}
146637da2899SCharles.Forsyth 	}
146737da2899SCharles.Forsyth 	if(f&Tuse1){
146837da2899SCharles.Forsyth 		id = finddec(STemp, IBY2WD, vars, &nv, i);
146937da2899SCharles.Forsyth 		setud(uses, id, nv, pc);
147037da2899SCharles.Forsyth 	}
147137da2899SCharles.Forsyth 	if(f&Tuse2){
147237da2899SCharles.Forsyth 		id = finddec(DTemp, IBY2WD, vars, &nv, i);
147337da2899SCharles.Forsyth 		setud(uses, id, nv, pc);
147437da2899SCharles.Forsyth 	}
147537da2899SCharles.Forsyth 	if(i->op == ILEA){
147637da2899SCharles.Forsyth 		if(s >= 0){
147737da2899SCharles.Forsyth 			id = finddec(s, ss, vars, &nv, i);
147837da2899SCharles.Forsyth 			if(i->sm == Afp && i->m.reg == 0)
147937da2899SCharles.Forsyth 				setud(defs, id, nv, pc);
148037da2899SCharles.Forsyth 			else
148137da2899SCharles.Forsyth 				setud(uses, id, nv, pc);
148237da2899SCharles.Forsyth 		}
148337da2899SCharles.Forsyth 	}
148437da2899SCharles.Forsyth 	if(0)
148537da2899SCharles.Forsyth 	switch(i->op){
148637da2899SCharles.Forsyth 	case ILEA:
148737da2899SCharles.Forsyth 		if(s >= 0){
148837da2899SCharles.Forsyth 			id = finddec(s, ss, vars, &nv, i);
148937da2899SCharles.Forsyth 			if(id < 0)
149037da2899SCharles.Forsyth 				break;
149137da2899SCharles.Forsyth 			for(j = 0; j < nv; j++){
149237da2899SCharles.Forsyth 				if(i->sm == Afp && i->m.reg == 0)
149337da2899SCharles.Forsyth 					addlist(&deflist, id++);
149437da2899SCharles.Forsyth 				else
149537da2899SCharles.Forsyth 					addlist(&uselist, id++);
149637da2899SCharles.Forsyth 			}
149737da2899SCharles.Forsyth 		}
149837da2899SCharles.Forsyth 		break;
149937da2899SCharles.Forsyth 	case IALT:
150037da2899SCharles.Forsyth 	case INBALT:
150137da2899SCharles.Forsyth 	case ICALL:
150237da2899SCharles.Forsyth 	case IMCALL:
150337da2899SCharles.Forsyth 		for(l = deflist; l != nil; l = l->next){
150437da2899SCharles.Forsyth 			id = l->id;
150537da2899SCharles.Forsyth 			bset(defs[id], pc);
150637da2899SCharles.Forsyth 		}
150737da2899SCharles.Forsyth 		for(l = uselist; l != nil; l = l->next){
150837da2899SCharles.Forsyth 			id = l->id;
150937da2899SCharles.Forsyth 			bset(uses[id], pc);
151037da2899SCharles.Forsyth 		}
151137da2899SCharles.Forsyth 		freelist(&deflist);
151237da2899SCharles.Forsyth 		freelist(&uselist);
151337da2899SCharles.Forsyth 		break;
151437da2899SCharles.Forsyth 	}
151537da2899SCharles.Forsyth }
151637da2899SCharles.Forsyth 
151737da2899SCharles.Forsyth static void
usedef(Inst * in,Decl * vars,Bits * uses,Bits * defs)151837da2899SCharles.Forsyth usedef(Inst *in, Decl *vars, Bits *uses, Bits *defs)
151937da2899SCharles.Forsyth {
152037da2899SCharles.Forsyth 	Inst *i;
152137da2899SCharles.Forsyth 
152237da2899SCharles.Forsyth 	for(i = in; i != nil; i = i->next)
152337da2899SCharles.Forsyth 		ud(i, vars, uses, defs);
152437da2899SCharles.Forsyth }
152537da2899SCharles.Forsyth 
152637da2899SCharles.Forsyth static void
pusedef(Bits * ud,int nv,Decl * d,char * s)152737da2899SCharles.Forsyth pusedef(Bits *ud, int nv, Decl *d, char *s)
152837da2899SCharles.Forsyth {
152937da2899SCharles.Forsyth 	int i;
153037da2899SCharles.Forsyth 
153137da2899SCharles.Forsyth 	print("%s\n", s);
153237da2899SCharles.Forsyth 	for(i = 0; i < nv; i++){
153337da2899SCharles.Forsyth 		if(!bzero(ud[i])){
153437da2899SCharles.Forsyth 			print("\t%s(%ld):	", decname(d), d->offset);
153537da2899SCharles.Forsyth 			pbits(ud[i]);
153637da2899SCharles.Forsyth 			print("\n");
153737da2899SCharles.Forsyth 		}
153837da2899SCharles.Forsyth 		d = d->next;
153937da2899SCharles.Forsyth 	}
154037da2899SCharles.Forsyth }
154137da2899SCharles.Forsyth 
154237da2899SCharles.Forsyth static void
dummydefs(Bits * defs,int nv,int npc)154337da2899SCharles.Forsyth dummydefs(Bits *defs, int nv, int npc)
154437da2899SCharles.Forsyth {
154537da2899SCharles.Forsyth 	int i;
154637da2899SCharles.Forsyth 
154737da2899SCharles.Forsyth 	for(i = 0; i < nv; i++)
154837da2899SCharles.Forsyth 		bset(defs[i], npc++);
154937da2899SCharles.Forsyth }
155037da2899SCharles.Forsyth 
155137da2899SCharles.Forsyth static void
dogenkill(Block * b,Bits * defs,int nv)155237da2899SCharles.Forsyth dogenkill(Block *b, Bits *defs, int nv)
155337da2899SCharles.Forsyth {
155437da2899SCharles.Forsyth 	int i, n, t;
155537da2899SCharles.Forsyth 	Bits v;
155637da2899SCharles.Forsyth 
155737da2899SCharles.Forsyth 	n = defs[0].n;
155837da2899SCharles.Forsyth 	v = bnew(n, 0);
155937da2899SCharles.Forsyth 	for( ; b != nil; b = b->next){
156037da2899SCharles.Forsyth 		b->gen = bnew(n, 0);
156137da2899SCharles.Forsyth 		b->kill = bnew(n, 0);
156237da2899SCharles.Forsyth 		b->in = bnew(n, 0);
156337da2899SCharles.Forsyth 		b->out = bnew(n, 0);
156437da2899SCharles.Forsyth 		for(i = 0; i < nv; i++){
156537da2899SCharles.Forsyth 			boper(Bclr, v, v);
156637da2899SCharles.Forsyth 			bsets(v, b->first->pc, b->last->pc);
156737da2899SCharles.Forsyth 			boper(Band, defs[i], v);
156837da2899SCharles.Forsyth 			t = topbit(v);
156937da2899SCharles.Forsyth 			if(t >= 0)
157037da2899SCharles.Forsyth 				bset(b->gen, t);
157137da2899SCharles.Forsyth 			else
157237da2899SCharles.Forsyth 				continue;
157337da2899SCharles.Forsyth 			boper(Bclr, v, v);
157437da2899SCharles.Forsyth 			bsets(v, b->first->pc, b->last->pc);
157537da2899SCharles.Forsyth 			boper(Binv, v, v);
157637da2899SCharles.Forsyth 			boper(Band, defs[i], v);
157737da2899SCharles.Forsyth 			boper(Bor, v, b->kill);
157837da2899SCharles.Forsyth 		}
157937da2899SCharles.Forsyth 	}
158037da2899SCharles.Forsyth 	bfree(v);
158137da2899SCharles.Forsyth }
158237da2899SCharles.Forsyth 
158337da2899SCharles.Forsyth static void
udflow(Block * b,int nv,int npc)158437da2899SCharles.Forsyth udflow(Block *b, int nv, int npc)
158537da2899SCharles.Forsyth {
158637da2899SCharles.Forsyth 	int iter;
158737da2899SCharles.Forsyth 	Block *b0, *p;
158837da2899SCharles.Forsyth 	Blist *bl;
158937da2899SCharles.Forsyth 	Bits newin;
159037da2899SCharles.Forsyth 
159137da2899SCharles.Forsyth 	b0 = b;
159237da2899SCharles.Forsyth 	for(b = b0; b != nil; b = b->next)
159337da2899SCharles.Forsyth 		boper(Bstore, b->gen, b->out);
159437da2899SCharles.Forsyth 	newin = bnew(b0->in.n, 0);
159537da2899SCharles.Forsyth 	iter = 1;
159637da2899SCharles.Forsyth 	while(iter){
159737da2899SCharles.Forsyth 		iter = 0;
159837da2899SCharles.Forsyth 		for(b = b0; b != nil; b = b->next){
159937da2899SCharles.Forsyth 			boper(Bclr, newin, newin);
160037da2899SCharles.Forsyth 			for(bl = b->pred; bl != nil; bl = bl->next){
160137da2899SCharles.Forsyth 				p = bl->block;
160237da2899SCharles.Forsyth 				boper(Bor, p->out, newin);
160337da2899SCharles.Forsyth 			}
160437da2899SCharles.Forsyth 			if(b == b0)
160537da2899SCharles.Forsyth 				bsets(newin, npc, npc+nv-1);
160637da2899SCharles.Forsyth 			if(!beq(b->in, newin))
160737da2899SCharles.Forsyth 				iter = 1;
160837da2899SCharles.Forsyth 			boper(Bstore, newin, b->in);
160937da2899SCharles.Forsyth 			boper(Bstore, b->in, b->out);
161037da2899SCharles.Forsyth 			boper(Bandrev, b->kill, b->out);
161137da2899SCharles.Forsyth 			boper(Bor, b->gen, b->out);
161237da2899SCharles.Forsyth 		}
161337da2899SCharles.Forsyth 	}
161437da2899SCharles.Forsyth 	bfree(newin);
161537da2899SCharles.Forsyth }
161637da2899SCharles.Forsyth 
161737da2899SCharles.Forsyth static void
pflows(Block * b)161837da2899SCharles.Forsyth pflows(Block *b)
161937da2899SCharles.Forsyth {
162037da2899SCharles.Forsyth 	for( ; b != nil; b = b->next){
162137da2899SCharles.Forsyth 		print("block %d\n", b->dfn);
162237da2899SCharles.Forsyth 		print("	gen:	"); pbits(b->gen); print("\n");
162337da2899SCharles.Forsyth 		print("	kill:	"); pbits(b->kill); print("\n");
162437da2899SCharles.Forsyth 		print("	in:	"); pbits(b->in); print("\n");
162537da2899SCharles.Forsyth 		print("	out:	"); pbits(b->out); print("\n");
162637da2899SCharles.Forsyth 	}
162737da2899SCharles.Forsyth }
162837da2899SCharles.Forsyth 
162937da2899SCharles.Forsyth static int
set(Decl * d)163037da2899SCharles.Forsyth set(Decl *d)
163137da2899SCharles.Forsyth {
163237da2899SCharles.Forsyth 	if(d->store == Darg)
163337da2899SCharles.Forsyth 		return 1;
163437da2899SCharles.Forsyth 	if(d->sym == nil)	/* || d->sym->name[0] == '.') */
163537da2899SCharles.Forsyth 		return 1;
163637da2899SCharles.Forsyth 	if(tattr[d->ty->kind].isptr || d->ty->kind == Texception)
163737da2899SCharles.Forsyth 		return 1;
163837da2899SCharles.Forsyth 	return 0;
163937da2899SCharles.Forsyth }
164037da2899SCharles.Forsyth 
164137da2899SCharles.Forsyth static int
used(Decl * d)164237da2899SCharles.Forsyth used(Decl *d)
164337da2899SCharles.Forsyth {
164437da2899SCharles.Forsyth 	if(d->sym == nil )	/* || d->sym->name[0] == '.') */
164537da2899SCharles.Forsyth 		return 1;
164637da2899SCharles.Forsyth 	return 0;
164737da2899SCharles.Forsyth }
164837da2899SCharles.Forsyth 
164937da2899SCharles.Forsyth static void
udchain(Block * b,Decl * ds,int nv,int npc,Bits * defs,Bits * uses,Decl * sd)165037da2899SCharles.Forsyth udchain(Block *b, Decl *ds, int nv, int npc, Bits *defs, Bits *uses, Decl *sd)
165137da2899SCharles.Forsyth {
165237da2899SCharles.Forsyth 	int i, n, p, q;
165337da2899SCharles.Forsyth 	Bits d, u, dd, ud;
165437da2899SCharles.Forsyth 	Block *b0;
165537da2899SCharles.Forsyth 	Inst *in;
165637da2899SCharles.Forsyth 
165737da2899SCharles.Forsyth 	b0 = b;
165837da2899SCharles.Forsyth 	n = defs[0].n;
165937da2899SCharles.Forsyth 	u = bnew(n, 0);
166037da2899SCharles.Forsyth 	d = bnew(n, 0);
166137da2899SCharles.Forsyth 	dd = bnew(n, 0);
166237da2899SCharles.Forsyth 	ud = bnew(n, 0);
166337da2899SCharles.Forsyth 	for(i = 0; i < nv; i++){
166437da2899SCharles.Forsyth 		boper(Bstore, defs[i], ud);
166537da2899SCharles.Forsyth 		bclr(ud, npc+i);
166637da2899SCharles.Forsyth 		for(b = b0 ; b != nil; b = b->next){
166737da2899SCharles.Forsyth 			boper(Bclr, u, u);
166837da2899SCharles.Forsyth 			bsets(u, b->first->pc, b->last->pc);
166937da2899SCharles.Forsyth 			boper(Band, uses[i], u);
167037da2899SCharles.Forsyth 			boper(Bclr, d, d);
167137da2899SCharles.Forsyth 			bsets(d, b->first->pc, b->last->pc);
167237da2899SCharles.Forsyth 			boper(Band, defs[i], d);
167337da2899SCharles.Forsyth 			for(;;){
167437da2899SCharles.Forsyth 				p = topbit(u);
167537da2899SCharles.Forsyth 				if(p < 0)
167637da2899SCharles.Forsyth 					break;
167737da2899SCharles.Forsyth 				bclr(u, p);
167837da2899SCharles.Forsyth 				bclrs(d, p, -1);
167937da2899SCharles.Forsyth 				q = topbit(d);
168037da2899SCharles.Forsyth 				if(q >= 0){
168137da2899SCharles.Forsyth 					bclr(ud, q);
168237da2899SCharles.Forsyth 					if(debug['o'])
168337da2899SCharles.Forsyth 						print("udc b=%d v=%d(%s/%ld) u=%d d=%d\n", b->dfn, i, decname(ds), ds->offset, p, q);
168437da2899SCharles.Forsyth 				}
168537da2899SCharles.Forsyth 				else{
168637da2899SCharles.Forsyth 					boper(Bstore, defs[i], dd);
168737da2899SCharles.Forsyth 					boper(Band, b->in, dd);
168837da2899SCharles.Forsyth 					boper(Bandrev, dd, ud);
168937da2899SCharles.Forsyth 					if(!bzero(dd)){
169037da2899SCharles.Forsyth 						if(debug['o']){
169137da2899SCharles.Forsyth 							print("udc b=%d v=%d(%s/%ld) u=%d d=", b->dfn, i, decname(ds), ds->offset, p);
169237da2899SCharles.Forsyth 							pbits(dd);
169337da2899SCharles.Forsyth 							print("\n");
169437da2899SCharles.Forsyth 						}
169537da2899SCharles.Forsyth 						if(bmem(dd, npc+i) && !set(ds))
169637da2899SCharles.Forsyth 							warning(pc2i(b0, p), "used and not set", ds, sd);
169737da2899SCharles.Forsyth 					}
169837da2899SCharles.Forsyth 					else
169937da2899SCharles.Forsyth 						fatal("no defs in udchain");
170037da2899SCharles.Forsyth 				}
170137da2899SCharles.Forsyth 			}
170237da2899SCharles.Forsyth 		}
170337da2899SCharles.Forsyth 		for(;;){
170437da2899SCharles.Forsyth 			p = topbit(ud);
170537da2899SCharles.Forsyth 			if(p < 0)
170637da2899SCharles.Forsyth 				break;
170737da2899SCharles.Forsyth 			bclr(ud, p);
170837da2899SCharles.Forsyth 			if(!used(ds)){
170937da2899SCharles.Forsyth 				in = pc2i(b0, p);
171037da2899SCharles.Forsyth 				if(isnilsrc(&in->src))	/* nilling code */
171137da2899SCharles.Forsyth 					in->op = INOOP;	/* elim p from bitmaps ? */
171237da2899SCharles.Forsyth 				else if(limbovar(ds) && !structure(ds->ty))
171337da2899SCharles.Forsyth 					warning(in, "set and not used", ds, sd);
171437da2899SCharles.Forsyth 			}
171537da2899SCharles.Forsyth 		}
171637da2899SCharles.Forsyth 		ds = ds->next;
171737da2899SCharles.Forsyth 	}
171837da2899SCharles.Forsyth 	bfree(u);
171937da2899SCharles.Forsyth 	bfree(d);
172037da2899SCharles.Forsyth 	bfree(dd);
172137da2899SCharles.Forsyth 	bfree(ud);
172237da2899SCharles.Forsyth }
172337da2899SCharles.Forsyth 
172437da2899SCharles.Forsyth static void
ckflags(void)172537da2899SCharles.Forsyth ckflags(void)
172637da2899SCharles.Forsyth {
172737da2899SCharles.Forsyth 	int i, j, k, n;
172837da2899SCharles.Forsyth 	Optab *o;
172937da2899SCharles.Forsyth 
173037da2899SCharles.Forsyth 	n = nelem(opflags);
173137da2899SCharles.Forsyth 	o = opflags;
173237da2899SCharles.Forsyth 	for(i = 0; i < n; i++){
173337da2899SCharles.Forsyth 		j = (o->flags&(Suse|Sdef)) != 0;
173437da2899SCharles.Forsyth 		k = SS(o->size) != 0;
173537da2899SCharles.Forsyth 		if(j != k){
173637da2899SCharles.Forsyth 			if(!(j == 0 && k == 1 && i == ILEA))
173737da2899SCharles.Forsyth 				fatal("S %ld %s\n", o-opflags, instname[i]);
173837da2899SCharles.Forsyth 		}
173937da2899SCharles.Forsyth 		j = (o->flags&(Muse|Mdef)) != 0;
174037da2899SCharles.Forsyth 		k = SM(o->size) != 0;
174137da2899SCharles.Forsyth 		if(j != k)
174237da2899SCharles.Forsyth 			fatal("M %ld %s\n", o-opflags, instname[i]);
174337da2899SCharles.Forsyth 		j = (o->flags&(Duse|Ddef)) != 0;
174437da2899SCharles.Forsyth 		k = SD(o->size) != 0;
174537da2899SCharles.Forsyth 		if(j != k){
174637da2899SCharles.Forsyth 			if(!(j == 1 && k == 0 && (i == IGOTO || i == ICASE || i == ICASEC || i == ICASEL)))
174737da2899SCharles.Forsyth 				fatal("D %ld %s\n", o-opflags, instname[i]);
174837da2899SCharles.Forsyth 		}
174937da2899SCharles.Forsyth 		o++;
175037da2899SCharles.Forsyth 	}
175137da2899SCharles.Forsyth }
175237da2899SCharles.Forsyth 
175337da2899SCharles.Forsyth void
optim(Inst * in,Decl * d)175437da2899SCharles.Forsyth optim(Inst *in, Decl *d)
175537da2899SCharles.Forsyth {
175637da2899SCharles.Forsyth 	int nb, npc, nv, nd, nu;
175737da2899SCharles.Forsyth 	Block *b;
175837da2899SCharles.Forsyth 	Bits *uses, *defs;
175937da2899SCharles.Forsyth 	Decl *sd;
176037da2899SCharles.Forsyth 
176137da2899SCharles.Forsyth 	ckflags();
176237da2899SCharles.Forsyth 	if(debug['o'])
176337da2899SCharles.Forsyth 		print("************************************************\nfunction %s\n************************************************\n", d->sym->name);
176437da2899SCharles.Forsyth 	if(in == nil || errors > 0)
176537da2899SCharles.Forsyth 		return;
176637da2899SCharles.Forsyth 	d = d->ty->ids;
176737da2899SCharles.Forsyth 	if(regdecls == nil)
176837da2899SCharles.Forsyth 		mkdecls();
176937da2899SCharles.Forsyth 	regdecls->next->next->next = d;
177037da2899SCharles.Forsyth 	d = regdecls;
177137da2899SCharles.Forsyth 	sd = sharedecls(d);
177237da2899SCharles.Forsyth 	if(debug['o'])
177337da2899SCharles.Forsyth 		printdecls(d);
177437da2899SCharles.Forsyth 	b = mkblocks(in, &nb);
177537da2899SCharles.Forsyth 	ckblocks(in, b, nb);
177637da2899SCharles.Forsyth 	npc = inspc(in);
177737da2899SCharles.Forsyth 	nb = dfs(b, nb);
177837da2899SCharles.Forsyth 	if(debug['o'])
177937da2899SCharles.Forsyth 		pblocks(b, nb);
178037da2899SCharles.Forsyth 	loops(b);
178137da2899SCharles.Forsyth 	nv = len(d);
178237da2899SCharles.Forsyth 	uses = allocbits(nv, npc+nv);
178337da2899SCharles.Forsyth 	defs = allocbits(nv, npc+nv);
178437da2899SCharles.Forsyth 	dummydefs(defs, nv, npc);
178537da2899SCharles.Forsyth 	usedef(in, d, uses, defs);
178637da2899SCharles.Forsyth 	if(debug['o']){
178737da2899SCharles.Forsyth 		pusedef(uses, nv, d, "uses");
178837da2899SCharles.Forsyth 		pusedef(defs, nv, d, "defs");
178937da2899SCharles.Forsyth 	}
179037da2899SCharles.Forsyth 	nu = bitcount(uses, nv);
179137da2899SCharles.Forsyth 	nd = bitcount(defs, nv);
179237da2899SCharles.Forsyth 	dogenkill(b, defs, nv);
179337da2899SCharles.Forsyth 	udflow(b, nv, npc);
179437da2899SCharles.Forsyth 	if(debug['o'])
179537da2899SCharles.Forsyth 		pflows(b);
179637da2899SCharles.Forsyth 	udchain(b, d, nv, npc, defs, uses, sd);
179737da2899SCharles.Forsyth 	freeblks(b);
179837da2899SCharles.Forsyth 	freebits(uses, nv);
179937da2899SCharles.Forsyth 	freebits(defs, nv);
180037da2899SCharles.Forsyth 	if(debug['o'])
180137da2899SCharles.Forsyth 		print("nb=%d npc=%d nv=%d nd=%d nu=%d\n", nb, npc, nv, nd, nu);
180237da2899SCharles.Forsyth }
180337da2899SCharles.Forsyth 
1804