xref: /plan9/sys/src/cmd/8c/gc.h (revision 178702b161d3fe3e021aa6cb2f305be898e56ca0)
13e12c5d1SDavid du Colombier #include	"../cc/cc.h"
23e12c5d1SDavid du Colombier #include	"../8c/8.out.h"
33e12c5d1SDavid du Colombier 
47dd7cddfSDavid du Colombier /*
57dd7cddfSDavid du Colombier  * 8c/386
67dd7cddfSDavid du Colombier  * Intel 386
77dd7cddfSDavid du Colombier  */
83e12c5d1SDavid du Colombier #define	SZ_CHAR		1
93e12c5d1SDavid du Colombier #define	SZ_SHORT	2
107dd7cddfSDavid du Colombier #define	SZ_INT		4
113e12c5d1SDavid du Colombier #define	SZ_LONG		4
123e12c5d1SDavid du Colombier #define	SZ_IND		4
133e12c5d1SDavid du Colombier #define	SZ_FLOAT	4
147dd7cddfSDavid du Colombier #define	SZ_VLONG	8
153e12c5d1SDavid du Colombier #define	SZ_DOUBLE	8
163e12c5d1SDavid du Colombier #define	FNX		100
173e12c5d1SDavid du Colombier 
183e12c5d1SDavid du Colombier typedef	struct	Adr	Adr;
193e12c5d1SDavid du Colombier typedef	struct	Prog	Prog;
203e12c5d1SDavid du Colombier typedef	struct	Case	Case;
213e12c5d1SDavid du Colombier typedef	struct	C1	C1;
223e12c5d1SDavid du Colombier typedef	struct	Var	Var;
233e12c5d1SDavid du Colombier typedef	struct	Reg	Reg;
243e12c5d1SDavid du Colombier typedef	struct	Rgn	Rgn;
25da51d93aSDavid du Colombier typedef	struct	Renv	Renv;
263e12c5d1SDavid du Colombier 
277dd7cddfSDavid du Colombier EXTERN	struct
283e12c5d1SDavid du Colombier {
293e12c5d1SDavid du Colombier 	Node*	regtree;
303e12c5d1SDavid du Colombier 	Node*	basetree;
313e12c5d1SDavid du Colombier 	short	scale;
323e12c5d1SDavid du Colombier 	short	reg;
3380ee5cbfSDavid du Colombier 	short	ptr;
343e12c5d1SDavid du Colombier } idx;
353e12c5d1SDavid du Colombier 
363e12c5d1SDavid du Colombier struct	Adr
373e12c5d1SDavid du Colombier {
383e12c5d1SDavid du Colombier 	long	offset;
393e12c5d1SDavid du Colombier 	double	dval;
403e12c5d1SDavid du Colombier 	char	sval[NSNAME];
417dd7cddfSDavid du Colombier 
423e12c5d1SDavid du Colombier 	Sym*	sym;
433e12c5d1SDavid du Colombier 	uchar	type;
443e12c5d1SDavid du Colombier 	uchar	index;
453e12c5d1SDavid du Colombier 	uchar	etype;
463e12c5d1SDavid du Colombier 	uchar	scale;	/* doubles as width in DATA op */
473e12c5d1SDavid du Colombier };
483e12c5d1SDavid du Colombier #define	A	((Adr*)0)
493e12c5d1SDavid du Colombier 
503e12c5d1SDavid du Colombier #define	INDEXED	9
513e12c5d1SDavid du Colombier struct	Prog
523e12c5d1SDavid du Colombier {
533e12c5d1SDavid du Colombier 	Adr	from;
543e12c5d1SDavid du Colombier 	Adr	to;
553e12c5d1SDavid du Colombier 	Prog*	link;
563e12c5d1SDavid du Colombier 	long	lineno;
573e12c5d1SDavid du Colombier 	short	as;
583e12c5d1SDavid du Colombier };
593e12c5d1SDavid du Colombier #define	P	((Prog*)0)
603e12c5d1SDavid du Colombier 
613e12c5d1SDavid du Colombier struct	Case
623e12c5d1SDavid du Colombier {
633e12c5d1SDavid du Colombier 	Case*	link;
64*3a276d32SDavid du Colombier 	vlong	val;
653e12c5d1SDavid du Colombier 	long	label;
663e12c5d1SDavid du Colombier 	char	def;
674ac975e2SDavid du Colombier 	char isv;
683e12c5d1SDavid du Colombier };
693e12c5d1SDavid du Colombier #define	C	((Case*)0)
703e12c5d1SDavid du Colombier 
713e12c5d1SDavid du Colombier struct	C1
723e12c5d1SDavid du Colombier {
73*3a276d32SDavid du Colombier 	vlong	val;
743e12c5d1SDavid du Colombier 	long	label;
753e12c5d1SDavid du Colombier };
763e12c5d1SDavid du Colombier 
773e12c5d1SDavid du Colombier struct	Var
783e12c5d1SDavid du Colombier {
793e12c5d1SDavid du Colombier 	long	offset;
803e12c5d1SDavid du Colombier 	Sym*	sym;
813e12c5d1SDavid du Colombier 	char	name;
823e12c5d1SDavid du Colombier 	char	etype;
833e12c5d1SDavid du Colombier };
843e12c5d1SDavid du Colombier 
853e12c5d1SDavid du Colombier struct	Reg
863e12c5d1SDavid du Colombier {
873e12c5d1SDavid du Colombier 	long	pc;
887dd7cddfSDavid du Colombier 	long	rpo;		/* reverse post ordering */
893e12c5d1SDavid du Colombier 
903e12c5d1SDavid du Colombier 	Bits	set;
913e12c5d1SDavid du Colombier 	Bits	use1;
923e12c5d1SDavid du Colombier 	Bits	use2;
933e12c5d1SDavid du Colombier 
943e12c5d1SDavid du Colombier 	Bits	refbehind;
953e12c5d1SDavid du Colombier 	Bits	refahead;
963e12c5d1SDavid du Colombier 	Bits	calbehind;
973e12c5d1SDavid du Colombier 	Bits	calahead;
983e12c5d1SDavid du Colombier 	Bits	regdiff;
993e12c5d1SDavid du Colombier 	Bits	act;
1003e12c5d1SDavid du Colombier 
1013e12c5d1SDavid du Colombier 	long	regu;
1023e12c5d1SDavid du Colombier 	long	loop;		/* could be shorter */
1033e12c5d1SDavid du Colombier 
1043e12c5d1SDavid du Colombier 	Reg*	log5;
1057dd7cddfSDavid du Colombier 	long	active;
1067dd7cddfSDavid du Colombier 
1073e12c5d1SDavid du Colombier 	Reg*	p1;
1083e12c5d1SDavid du Colombier 	Reg*	p2;
1093e12c5d1SDavid du Colombier 	Reg*	p2link;
1103e12c5d1SDavid du Colombier 	Reg*	s1;
1113e12c5d1SDavid du Colombier 	Reg*	s2;
1123e12c5d1SDavid du Colombier 	Reg*	link;
1133e12c5d1SDavid du Colombier 	Prog*	prog;
1143e12c5d1SDavid du Colombier };
1153e12c5d1SDavid du Colombier #define	R	((Reg*)0)
1163e12c5d1SDavid du Colombier 
117da51d93aSDavid du Colombier struct	Renv
118da51d93aSDavid du Colombier {
119da51d93aSDavid du Colombier 	int	safe;
120da51d93aSDavid du Colombier 	Node	base;
121da51d93aSDavid du Colombier 	Node*	saved;
122da51d93aSDavid du Colombier 	Node*	scope;
123da51d93aSDavid du Colombier };
124da51d93aSDavid du Colombier 
12580ee5cbfSDavid du Colombier #define	NRGN	600
1263e12c5d1SDavid du Colombier struct	Rgn
1273e12c5d1SDavid du Colombier {
1283e12c5d1SDavid du Colombier 	Reg*	enter;
1293e12c5d1SDavid du Colombier 	short	cost;
1303e12c5d1SDavid du Colombier 	short	varno;
1313e12c5d1SDavid du Colombier 	short	regno;
1323e12c5d1SDavid du Colombier };
1333e12c5d1SDavid du Colombier 
1347dd7cddfSDavid du Colombier EXTERN	long	breakpc;
1354ac975e2SDavid du Colombier EXTERN	long	nbreak;
1367dd7cddfSDavid du Colombier EXTERN	Case*	cases;
1377dd7cddfSDavid du Colombier EXTERN	Node	constnode;
1387dd7cddfSDavid du Colombier EXTERN	Node	fconstnode;
1397dd7cddfSDavid du Colombier EXTERN	long	continpc;
1407dd7cddfSDavid du Colombier EXTERN	long	curarg;
1417dd7cddfSDavid du Colombier EXTERN	long	cursafe;
1427dd7cddfSDavid du Colombier EXTERN	Prog*	firstp;
1437dd7cddfSDavid du Colombier EXTERN	Prog*	lastp;
1447dd7cddfSDavid du Colombier EXTERN	long	maxargsafe;
1457dd7cddfSDavid du Colombier EXTERN	int	mnstring;
1467dd7cddfSDavid du Colombier EXTERN	Node*	nodrat;
1477dd7cddfSDavid du Colombier EXTERN	Node*	nodret;
1487dd7cddfSDavid du Colombier EXTERN	Node*	nodsafe;
1497dd7cddfSDavid du Colombier EXTERN	long	nrathole;
1507dd7cddfSDavid du Colombier EXTERN	long	nstring;
1517dd7cddfSDavid du Colombier EXTERN	Prog*	p;
1527dd7cddfSDavid du Colombier EXTERN	long	pc;
1537dd7cddfSDavid du Colombier EXTERN	Node	regnode;
1547dd7cddfSDavid du Colombier EXTERN	Node	fregnode0;
1557dd7cddfSDavid du Colombier EXTERN	Node	fregnode1;
1567dd7cddfSDavid du Colombier EXTERN	char	string[NSNAME];
1577dd7cddfSDavid du Colombier EXTERN	Sym*	symrathole;
1587dd7cddfSDavid du Colombier EXTERN	Node	znode;
1597dd7cddfSDavid du Colombier EXTERN	Prog	zprog;
1607dd7cddfSDavid du Colombier EXTERN	int	reg[D_NONE];
1617dd7cddfSDavid du Colombier EXTERN	long	exregoffset;
1627dd7cddfSDavid du Colombier EXTERN	long	exfregoffset;
1633e12c5d1SDavid du Colombier 
1643e12c5d1SDavid du Colombier #define	BLOAD(r)	band(bnot(r->refbehind), r->refahead)
1653e12c5d1SDavid du Colombier #define	BSTORE(r)	band(bnot(r->calbehind), r->calahead)
1663e12c5d1SDavid du Colombier #define	LOAD(r)		(~r->refbehind.b[z] & r->refahead.b[z])
1673e12c5d1SDavid du Colombier #define	STORE(r)	(~r->calbehind.b[z] & r->calahead.b[z])
1683e12c5d1SDavid du Colombier 
1693e12c5d1SDavid du Colombier #define	bset(a,n)	((a).b[(n)/32]&(1L<<(n)%32))
1703e12c5d1SDavid du Colombier 
1713e12c5d1SDavid du Colombier #define	CLOAD	5
1723e12c5d1SDavid du Colombier #define	CREF	5
1733e12c5d1SDavid du Colombier #define	CINF	1000
1743e12c5d1SDavid du Colombier #define	LOOP	3
1753e12c5d1SDavid du Colombier 
1767dd7cddfSDavid du Colombier EXTERN	Rgn	region[NRGN];
1777dd7cddfSDavid du Colombier EXTERN	Rgn*	rgp;
1787dd7cddfSDavid du Colombier EXTERN	int	nregion;
1797dd7cddfSDavid du Colombier EXTERN	int	nvar;
1803e12c5d1SDavid du Colombier 
1817dd7cddfSDavid du Colombier EXTERN	Bits	externs;
1827dd7cddfSDavid du Colombier EXTERN	Bits	params;
1837dd7cddfSDavid du Colombier EXTERN	Bits	consts;
1847dd7cddfSDavid du Colombier EXTERN	Bits	addrs;
1853e12c5d1SDavid du Colombier 
1867dd7cddfSDavid du Colombier EXTERN	long	regbits;
1877dd7cddfSDavid du Colombier EXTERN	long	exregbits;
1883e12c5d1SDavid du Colombier 
1897dd7cddfSDavid du Colombier EXTERN	int	change;
1909a747e4fSDavid du Colombier EXTERN	int	suppress;
1913e12c5d1SDavid du Colombier 
1927dd7cddfSDavid du Colombier EXTERN	Reg*	firstr;
1937dd7cddfSDavid du Colombier EXTERN	Reg*	lastr;
1947dd7cddfSDavid du Colombier EXTERN	Reg	zreg;
1957dd7cddfSDavid du Colombier EXTERN	Reg*	freer;
1967dd7cddfSDavid du Colombier EXTERN	Var	var[NVAR];
19759cc4ca5SDavid du Colombier EXTERN	long*	idom;
19859cc4ca5SDavid du Colombier EXTERN	Reg**	rpo2r;
19959cc4ca5SDavid du Colombier EXTERN	long	maxnr;
2003e12c5d1SDavid du Colombier 
2013e12c5d1SDavid du Colombier extern	char*	anames[];
2023e12c5d1SDavid du Colombier 
2033e12c5d1SDavid du Colombier /*
2043e12c5d1SDavid du Colombier  * sgen.c
2053e12c5d1SDavid du Colombier  */
2063e12c5d1SDavid du Colombier void	codgen(Node*, Node*);
2073e12c5d1SDavid du Colombier void	gen(Node*);
2083e12c5d1SDavid du Colombier void	noretval(int);
2097dd7cddfSDavid du Colombier void	usedset(Node*, int);
2103e12c5d1SDavid du Colombier void	xcom(Node*);
2113e12c5d1SDavid du Colombier void	indx(Node*);
2129a747e4fSDavid du Colombier int	bcomplex(Node*, Node*);
2133e12c5d1SDavid du Colombier 
2143e12c5d1SDavid du Colombier /*
2153e12c5d1SDavid du Colombier  * cgen.c
2163e12c5d1SDavid du Colombier  */
217da51d93aSDavid du Colombier void	zeroregm(Node*);
2183e12c5d1SDavid du Colombier void	cgen(Node*, Node*);
2193e12c5d1SDavid du Colombier void	reglcgen(Node*, Node*, Node*);
2203e12c5d1SDavid du Colombier void	lcgen(Node*, Node*);
2213e12c5d1SDavid du Colombier void	bcgen(Node*, int);
2223e12c5d1SDavid du Colombier void	boolgen(Node*, int, Node*);
2233e12c5d1SDavid du Colombier void	sugen(Node*, Node*, long);
2243e12c5d1SDavid du Colombier int	needreg(Node*, int);
2253e12c5d1SDavid du Colombier 
2263e12c5d1SDavid du Colombier /*
227da51d93aSDavid du Colombier  * cgen64.c
228da51d93aSDavid du Colombier  */
229375daca8SDavid du Colombier int	vaddr(Node*, int);
230da51d93aSDavid du Colombier void	loadpair(Node*, Node*);
231da51d93aSDavid du Colombier int	cgen64(Node*, Node*);
232da51d93aSDavid du Colombier void	testv(Node*, int);
233da51d93aSDavid du Colombier 
234da51d93aSDavid du Colombier /*
2353e12c5d1SDavid du Colombier  * txt.c
2363e12c5d1SDavid du Colombier  */
2373e12c5d1SDavid du Colombier void	ginit(void);
2383e12c5d1SDavid du Colombier void	gclean(void);
2393e12c5d1SDavid du Colombier void	nextpc(void);
2403e12c5d1SDavid du Colombier void	gargs(Node*, Node*, Node*);
2413e12c5d1SDavid du Colombier void	garg1(Node*, Node*, Node*, int, Node**);
2423e12c5d1SDavid du Colombier Node*	nodconst(long);
243d40255d8SDavid du Colombier int	nareg(int);
244bd389b36SDavid du Colombier Node*	nodfconst(double);
2453e12c5d1SDavid du Colombier int	nodreg(Node*, Node*, int);
2463e12c5d1SDavid du Colombier int	isreg(Node*, int);
2473e12c5d1SDavid du Colombier void	regret(Node*, Node*);
2483e12c5d1SDavid du Colombier void	regalloc(Node*, Node*, Node*);
2493e12c5d1SDavid du Colombier void	regfree(Node*);
2503e12c5d1SDavid du Colombier void	regialloc(Node*, Node*, Node*);
2513e12c5d1SDavid du Colombier void	regsalloc(Node*, Node*);
2523e12c5d1SDavid du Colombier void	regaalloc1(Node*, Node*);
2533e12c5d1SDavid du Colombier void	regaalloc(Node*, Node*);
2543e12c5d1SDavid du Colombier void	regind(Node*, Node*);
2553e12c5d1SDavid du Colombier void	gprep(Node*, Node*);
2563e12c5d1SDavid du Colombier void	naddr(Node*, Adr*);
2573e12c5d1SDavid du Colombier void	gmove(Node*, Node*);
2583e12c5d1SDavid du Colombier void	gins(int a, Node*, Node*);
2593e12c5d1SDavid du Colombier void	fgopcode(int, Node*, Node*, int, int);
2603e12c5d1SDavid du Colombier void	gopcode(int, Type*, Node*, Node*);
2613e12c5d1SDavid du Colombier int	samaddr(Node*, Node*);
2623e12c5d1SDavid du Colombier void	gbranch(int);
2633e12c5d1SDavid du Colombier void	patch(Prog*, long);
2643e12c5d1SDavid du Colombier int	sconst(Node*);
2653e12c5d1SDavid du Colombier void	gpseudo(int, Sym*, Node*);
2663e12c5d1SDavid du Colombier 
2673e12c5d1SDavid du Colombier /*
2683e12c5d1SDavid du Colombier  * swt.c
2693e12c5d1SDavid du Colombier  */
2707dd7cddfSDavid du Colombier int	swcmp(const void*, const void*);
2713e12c5d1SDavid du Colombier void	doswit(Node*);
2723e12c5d1SDavid du Colombier void	swit1(C1*, int, long, Node*);
273ff4cd143SDavid du Colombier void	casf(void);
2743e12c5d1SDavid du Colombier void	bitload(Node*, Node*, Node*, Node*, Node*);
2753e12c5d1SDavid du Colombier void	bitstore(Node*, Node*, Node*, Node*, Node*);
2763e12c5d1SDavid du Colombier long	outstring(char*, long);
2773e12c5d1SDavid du Colombier void	nullwarn(Node*, Node*);
2783e12c5d1SDavid du Colombier void	gextern(Sym*, Node*, long, long);
2793e12c5d1SDavid du Colombier void	outcode(void);
2803e12c5d1SDavid du Colombier void	ieeedtod(Ieee*, double);
2813e12c5d1SDavid du Colombier 
2823e12c5d1SDavid du Colombier /*
2833e12c5d1SDavid du Colombier  * list
2843e12c5d1SDavid du Colombier  */
2853e12c5d1SDavid du Colombier void	listinit(void);
2869a747e4fSDavid du Colombier int	Pconv(Fmt*);
2879a747e4fSDavid du Colombier int	Aconv(Fmt*);
2889a747e4fSDavid du Colombier int	Dconv(Fmt*);
2899a747e4fSDavid du Colombier int	Sconv(Fmt*);
2909a747e4fSDavid du Colombier int	Rconv(Fmt*);
2919a747e4fSDavid du Colombier int	Xconv(Fmt*);
2929a747e4fSDavid du Colombier int	Bconv(Fmt*);
2933e12c5d1SDavid du Colombier 
2943e12c5d1SDavid du Colombier /*
2953e12c5d1SDavid du Colombier  * reg.c
2963e12c5d1SDavid du Colombier  */
2973e12c5d1SDavid du Colombier Reg*	rega(void);
2987dd7cddfSDavid du Colombier int	rcmp(const void*, const void*);
2993e12c5d1SDavid du Colombier void	regopt(Prog*);
3003e12c5d1SDavid du Colombier void	addmove(Reg*, int, int, int);
301d40255d8SDavid du Colombier Bits	mkvar(Reg*, Adr*, int);
3023e12c5d1SDavid du Colombier void	prop(Reg*, Bits, Bits);
3037dd7cddfSDavid du Colombier void	loopit(Reg*, long);
3043e12c5d1SDavid du Colombier void	synch(Reg*, Bits);
3053e12c5d1SDavid du Colombier ulong	allreg(ulong, Rgn*);
3063e12c5d1SDavid du Colombier void	paint1(Reg*, int);
3073e12c5d1SDavid du Colombier ulong	paint2(Reg*, int);
3083e12c5d1SDavid du Colombier void	paint3(Reg*, int, long, int);
3093e12c5d1SDavid du Colombier void	addreg(Adr*, int);
3103e12c5d1SDavid du Colombier 
3113e12c5d1SDavid du Colombier /*
3123e12c5d1SDavid du Colombier  * peep.c
3133e12c5d1SDavid du Colombier  */
3143e12c5d1SDavid du Colombier void	peep(void);
3153e12c5d1SDavid du Colombier void	excise(Reg*);
3163e12c5d1SDavid du Colombier Reg*	uniqp(Reg*);
3173e12c5d1SDavid du Colombier Reg*	uniqs(Reg*);
3183e12c5d1SDavid du Colombier int	regtyp(Adr*);
3193e12c5d1SDavid du Colombier int	anyvar(Adr*);
3203e12c5d1SDavid du Colombier int	subprop(Reg*);
3213e12c5d1SDavid du Colombier int	copyprop(Reg*);
3223e12c5d1SDavid du Colombier int	copy1(Adr*, Adr*, Reg*, int);
3233e12c5d1SDavid du Colombier int	copyu(Prog*, Adr*, Adr*);
3243e12c5d1SDavid du Colombier 
3253e12c5d1SDavid du Colombier int	copyas(Adr*, Adr*);
3263e12c5d1SDavid du Colombier int	copyau(Adr*, Adr*);
3273e12c5d1SDavid du Colombier int	copysub(Adr*, Adr*, Adr*, int);
3283e12c5d1SDavid du Colombier int	copysub1(Prog*, Adr*, Adr*, int);
3293e12c5d1SDavid du Colombier 
3303e12c5d1SDavid du Colombier long	RtoB(int);
3313e12c5d1SDavid du Colombier long	FtoB(int);
3323e12c5d1SDavid du Colombier int	BtoR(long);
3333e12c5d1SDavid du Colombier int	BtoF(long);
3343e12c5d1SDavid du Colombier 
3353e12c5d1SDavid du Colombier #define	D_HI	D_NONE
3363e12c5d1SDavid du Colombier #define	D_LO	D_NONE
337219b2ee8SDavid du Colombier 
338219b2ee8SDavid du Colombier /*
339219b2ee8SDavid du Colombier  * com64
340219b2ee8SDavid du Colombier  */
341da51d93aSDavid du Colombier int	cond(int);
342219b2ee8SDavid du Colombier int	com64(Node*);
343219b2ee8SDavid du Colombier void	com64init(void);
344219b2ee8SDavid du Colombier void	bool64(Node*);
345375daca8SDavid du Colombier long	lo64v(Node*);
346375daca8SDavid du Colombier long	hi64v(Node*);
347375daca8SDavid du Colombier Node*	lo64(Node*);
348375daca8SDavid du Colombier Node*	hi64(Node*);
349375daca8SDavid du Colombier 
350375daca8SDavid du Colombier /*
351375daca8SDavid du Colombier  * div/mul
352375daca8SDavid du Colombier  */
353375daca8SDavid du Colombier void	sdivgen(Node*, Node*, Node*, Node*);
354375daca8SDavid du Colombier void	udivgen(Node*, Node*, Node*, Node*);
355375daca8SDavid du Colombier void	sdiv2(long, int, Node*, Node*);
356375daca8SDavid du Colombier void	smod2(long, int, Node*, Node*);
357375daca8SDavid du Colombier void	mulgen(Type*, Node*, Node*);
358375daca8SDavid du Colombier void	genmuladd(Node*, Node*, int, Node*);
359375daca8SDavid du Colombier void	shiftit(Type*, Node*, Node*);
3607dd7cddfSDavid du Colombier 
3617dd7cddfSDavid du Colombier #pragma	varargck	type	"A"	int
3627dd7cddfSDavid du Colombier #pragma	varargck	type	"B"	Bits
3637dd7cddfSDavid du Colombier #pragma	varargck	type	"D"	Adr*
3647dd7cddfSDavid du Colombier #pragma	varargck	type	"P"	Prog*
3657dd7cddfSDavid du Colombier #pragma	varargck	type	"R"	int
3667dd7cddfSDavid du Colombier #pragma	varargck	type	"S"	char*
367da51d93aSDavid du Colombier 
368375daca8SDavid du Colombier /* wrecklessly steal a field */
369da51d93aSDavid du Colombier 
370da51d93aSDavid du Colombier #define	rplink	label
371