xref: /csrg-svn/usr.bin/f77/pass1.vax/putpcc.c (revision 33257)
122866Smckusick /*
222866Smckusick  * Copyright (c) 1980 Regents of the University of California.
322866Smckusick  * All rights reserved.  The Berkeley software License Agreement
422866Smckusick  * specifies the terms and conditions for redistribution.
522866Smckusick  */
622866Smckusick 
722866Smckusick #ifndef lint
8*33257Sbostic static char sccsid[] = "@(#)putpcc.c	5.3 (Berkeley) 01/03/88";
922866Smckusick #endif not lint
1022866Smckusick 
1122866Smckusick /*
1222866Smckusick  * putpcc.c
1322866Smckusick  *
1422866Smckusick  * Intermediate code generation for S. C. Johnson C compilers
1522866Smckusick  * New version using binary polish postfix intermediate
1622866Smckusick  *
1722866Smckusick  * University of Utah CS Dept modification history:
1822866Smckusick  *
1926513Sdonn  * $Header: putpcc.c,v 5.2 86/03/04 17:49:38 donn Exp $
2022866Smckusick  * $Log:	putpcc.c,v $
2126513Sdonn  * Revision 5.2  86/03/04  17:49:38  donn
2226513Sdonn  * Change putct1() to emit the memoffset before the vleng -- the memoffset
2326513Sdonn  * may define a temporary which is used by the vleng to avoid repeated
2426513Sdonn  * evaluation of an expression with side effects.
2526513Sdonn  *
2626513Sdonn  * Revision 5.1  85/08/10  03:49:26  donn
2726513Sdonn  * 4.3 alpha
2826513Sdonn  *
2922866Smckusick  * Revision 3.2  85/03/25  09:35:57  root
3022866Smckusick  * fseek return -1 on error.
3122866Smckusick  *
3222866Smckusick  * Revision 3.1  85/02/27  19:06:55  donn
3322866Smckusick  * Changed to use pcc.h instead of pccdefs.h.
3422866Smckusick  *
3522866Smckusick  * Revision 2.12  85/02/22  01:05:54  donn
3622866Smckusick  * putaddr() didn't know about intrinsic functions...
3722866Smckusick  *
3822866Smckusick  * Revision 2.11  84/11/28  21:28:49  donn
3922866Smckusick  * Hacked putop() to handle any character expression being converted to int,
4022866Smckusick  * not just function calls.  Previously it bombed on concatenations.
4122866Smckusick  *
4222866Smckusick  * Revision 2.10  84/11/01  22:07:07  donn
4322866Smckusick  * Yet another try at getting putop() to work right.  It appears that the
4422866Smckusick  * second pass can't abide certain explicit conversions (e.g. short to long)
4522866Smckusick  * so the conversion code in putop() tries to remove them.  I think this
4622866Smckusick  * version (finally) works.
4722866Smckusick  *
4822866Smckusick  * Revision 2.9  84/10/29  02:30:57  donn
4922866Smckusick  * Earlier fix to putop() for conversions was insufficient -- we NEVER want to
5022866Smckusick  * see the type of the left operand of the thing left over from stripping off
5122866Smckusick  * conversions...
5222866Smckusick  *
5322866Smckusick  * Revision 2.8  84/09/18  03:09:21  donn
5422866Smckusick  * Fixed bug in putop() where the left operand of an addrblock was being
5522866Smckusick  * extracted...  This caused an extremely obscure conversion error when
5622866Smckusick  * an array of longs was subscripted by a short.
5722866Smckusick  *
5822866Smckusick  * Revision 2.7  84/08/19  20:10:19  donn
5922866Smckusick  * Removed stuff in putbranch that treats STGARG parameters specially -- the
6022866Smckusick  * bug in the code generation pass that motivated it has been fixed.
6122866Smckusick  *
6222866Smckusick  * Revision 2.6  84/08/07  21:32:23  donn
6322866Smckusick  * Bumped the size of the buffer for the intermediate code file from 0.5K
6422866Smckusick  * to 4K on a VAX.
6522866Smckusick  *
6622866Smckusick  * Revision 2.5  84/08/04  20:26:43  donn
6722866Smckusick  * Fixed a goof in the new putbranch() -- it now calls mkaltemp instead of
6822866Smckusick  * mktemp().  Correction due to Jerry Berkman.
6922866Smckusick  *
7022866Smckusick  * Revision 2.4  84/07/24  19:07:15  donn
7122866Smckusick  * Fixed bug reported by Craig Leres in which putmnmx() mistakenly assumed
7222866Smckusick  * that mkaltemp() returns tempblocks, and tried to free them with frtemp().
7322866Smckusick  *
7422866Smckusick  * Revision 2.3  84/07/19  17:22:09  donn
7522866Smckusick  * Changed putch1() so that OPPAREN expressions of type CHARACTER are legal.
7622866Smckusick  *
7722866Smckusick  * Revision 2.2  84/07/19  12:30:38  donn
7822866Smckusick  * Fixed a type clash in Bob Corbett's new putbranch().
7922866Smckusick  *
8022866Smckusick  * Revision 2.1  84/07/19  12:04:27  donn
8122866Smckusick  * Changed comment headers for UofU.
8222866Smckusick  *
8322866Smckusick  * Revision 1.8  84/07/19  11:38:23  donn
8422866Smckusick  * Replaced putbranch() routine so that you can ASSIGN into argument variables.
8522866Smckusick  * The code is from Bob Corbett, donated by Jerry Berkman.
8622866Smckusick  *
8722866Smckusick  * Revision 1.7  84/05/31  00:48:32  donn
8822866Smckusick  * Fixed an extremely obscure bug dealing with the comparison of CHARACTER*1
8922866Smckusick  * expressions -- a foulup in the order of COMOP and the comparison caused
9022866Smckusick  * one operand of the comparison to be garbage.
9122866Smckusick  *
9222866Smckusick  * Revision 1.6  84/04/16  09:54:19  donn
9322866Smckusick  * Backed out earlier fix for bug where items in the argtemplist were
9422866Smckusick  * (incorrectly) being given away; this is now fixed in mkargtemp().
9522866Smckusick  *
9622866Smckusick  * Revision 1.5  84/03/23  22:49:48  donn
9722866Smckusick  * Took out the initialization of the subroutine argument temporary list in
9822866Smckusick  * putcall() -- it needs to be done once per statement instead of once per call.
9922866Smckusick  *
10022866Smckusick  * Revision 1.4  84/03/01  06:48:05  donn
10122866Smckusick  * Fixed bug in Bob Corbett's code for argument temporaries that caused an
10222866Smckusick  * addrblock to get thrown out inadvertently when it was needed for recycling
10322866Smckusick  * purposes later on.
10422866Smckusick  *
10522866Smckusick  * Revision 1.3  84/02/26  06:32:38  donn
10622866Smckusick  * Added Berkeley changes to move data definitions around and reduce offsets.
10722866Smckusick  *
10822866Smckusick  * Revision 1.2  84/02/26  06:27:45  donn
10922866Smckusick  * Added code to catch TTEMP values passed to putx().
11022866Smckusick  *
11122866Smckusick  */
11222866Smckusick 
11322866Smckusick #if FAMILY != PCC
11422866Smckusick 	WRONG put FILE !!!!
11522866Smckusick #endif
11622866Smckusick 
11722866Smckusick #include "defs.h"
11822866Smckusick #include <pcc.h>
11922866Smckusick 
12022866Smckusick Addrp putcall(), putcxeq(), putcx1(), realpart();
12122866Smckusick expptr imagpart();
12222866Smckusick ftnint lencat();
12322866Smckusick 
12422866Smckusick #define FOUR 4
12522866Smckusick extern int ops2[];
12622866Smckusick extern int types2[];
12722866Smckusick 
12822866Smckusick #if HERE==VAX
12922866Smckusick #define PCC_BUFFMAX 1024
13022866Smckusick #else
13122866Smckusick #define PCC_BUFFMAX 128
13222866Smckusick #endif
13322866Smckusick static long int p2buff[PCC_BUFFMAX];
13422866Smckusick static long int *p2bufp		= &p2buff[0];
13522866Smckusick static long int *p2bufend	= &p2buff[PCC_BUFFMAX];
13622866Smckusick 
13722866Smckusick 
13822866Smckusick puthead(s, class)
13922866Smckusick char *s;
14022866Smckusick int class;
14122866Smckusick {
14222866Smckusick char buff[100];
14322866Smckusick #if TARGET == VAX
14422866Smckusick 	if(s)
14522866Smckusick 		p2ps("\t.globl\t_%s", s);
14622866Smckusick #endif
14722866Smckusick /* put out fake copy of left bracket line, to be redone later */
14822866Smckusick if( ! headerdone )
14922866Smckusick 	{
15022866Smckusick #if FAMILY == PCC
15122866Smckusick 	p2flush();
15222866Smckusick #endif
15322866Smckusick 	headoffset = ftell(textfile);
15422866Smckusick 	prhead(textfile);
15522866Smckusick 	headerdone = YES;
15622866Smckusick 	p2triple(PCCF_FEXPR, (strlen(infname)+FOUR-1)/FOUR, 0);
15722866Smckusick 	p2str(infname);
15822866Smckusick #if TARGET == PDP11
15922866Smckusick 	/* fake jump to start the optimizer */
16022866Smckusick 	if(class != CLBLOCK)
16122866Smckusick 		putgoto( fudgelabel = newlabel() );
16222866Smckusick #endif
16322866Smckusick 
16422866Smckusick #if TARGET == VAX
16522866Smckusick 	/* jump from top to bottom */
16622866Smckusick 	if(s!=CNULL && class!=CLBLOCK)
16722866Smckusick 		{
16822866Smckusick 		int proflab = newlabel();
16922866Smckusick 		p2ps("_%s:", s);
17022866Smckusick 		p2pi("\t.word\tLWM%d", procno);
17122866Smckusick 		prsave(proflab);
17222866Smckusick 		p2pi("\tjbr\tL%d", fudgelabel = newlabel());
17322866Smckusick 		}
17422866Smckusick #endif
17522866Smckusick 	}
17622866Smckusick }
17722866Smckusick 
17822866Smckusick 
17922866Smckusick 
18022866Smckusick 
18122866Smckusick 
18222866Smckusick /* It is necessary to precede each procedure with a "left bracket"
18322866Smckusick  * line that tells pass 2 how many register variables and how
18422866Smckusick  * much automatic space is required for the function.  This compiler
18522866Smckusick  * does not know how much automatic space is needed until the
18622866Smckusick  * entire procedure has been processed.  Therefore, "puthead"
18722866Smckusick  * is called at the begining to record the current location in textfile,
18822866Smckusick  * then to put out a placeholder left bracket line.  This procedure
18922866Smckusick  * repositions the file and rewrites that line, then puts the
19022866Smckusick  * file pointer back to the end of the file.
19122866Smckusick  */
19222866Smckusick 
19322866Smckusick putbracket()
19422866Smckusick {
19522866Smckusick long int hereoffset;
19622866Smckusick 
19722866Smckusick #if FAMILY == PCC
19822866Smckusick 	p2flush();
19922866Smckusick #endif
20022866Smckusick hereoffset = ftell(textfile);
20122866Smckusick if(fseek(textfile, headoffset, 0) == -1)
20222866Smckusick 	fatal("fseek failed");
20322866Smckusick prhead(textfile);
20422866Smckusick if(fseek(textfile, hereoffset, 0) == -1)
20522866Smckusick 	fatal("fseek failed 2");
20622866Smckusick }
20722866Smckusick 
20822866Smckusick 
20922866Smckusick 
21022866Smckusick 
21122866Smckusick putrbrack(k)
21222866Smckusick int k;
21322866Smckusick {
21422866Smckusick p2op(PCCF_FRBRAC, k);
21522866Smckusick }
21622866Smckusick 
21722866Smckusick 
21822866Smckusick 
21922866Smckusick putnreg()
22022866Smckusick {
22122866Smckusick }
22222866Smckusick 
22322866Smckusick 
22422866Smckusick 
22522866Smckusick 
22622866Smckusick 
22722866Smckusick 
22822866Smckusick puteof()
22922866Smckusick {
23022866Smckusick p2op(PCCF_FEOF, 0);
23122866Smckusick p2flush();
23222866Smckusick }
23322866Smckusick 
23422866Smckusick 
23522866Smckusick 
23622866Smckusick putstmt()
23722866Smckusick {
23822866Smckusick p2triple(PCCF_FEXPR, 0, lineno);
23922866Smckusick }
24022866Smckusick 
24122866Smckusick 
24222866Smckusick 
24322866Smckusick 
24422866Smckusick /* put out code for if( ! p) goto l  */
24522866Smckusick putif(p,l)
24622866Smckusick register expptr p;
24722866Smckusick int l;
24822866Smckusick {
24922866Smckusick register int k;
25022866Smckusick 
25122866Smckusick if( ( k = (p = fixtype(p))->headblock.vtype) != TYLOGICAL)
25222866Smckusick 	{
25322866Smckusick 	if(k != TYERROR)
25422866Smckusick 		err("non-logical expression in IF statement");
25522866Smckusick 	frexpr(p);
25622866Smckusick 	}
25722866Smckusick else
25822866Smckusick 	{
25922866Smckusick 	putex1(p);
26022866Smckusick 	p2icon( (long int) l , PCCT_INT);
26122866Smckusick 	p2op(PCC_CBRANCH, 0);
26222866Smckusick 	putstmt();
26322866Smckusick 	}
26422866Smckusick }
26522866Smckusick 
26622866Smckusick 
26722866Smckusick 
26822866Smckusick 
26922866Smckusick 
27022866Smckusick /* put out code for  goto l   */
27122866Smckusick putgoto(label)
27222866Smckusick int label;
27322866Smckusick {
27422866Smckusick p2triple(PCC_GOTO, 1, label);
27522866Smckusick putstmt();
27622866Smckusick }
27722866Smckusick 
27822866Smckusick 
27922866Smckusick /* branch to address constant or integer variable */
28022866Smckusick putbranch(p)
28122866Smckusick register Addrp p;
28222866Smckusick {
28322866Smckusick   putex1((expptr) p);
28422866Smckusick   p2op(PCC_GOTO, PCCT_INT);
28522866Smckusick   putstmt();
28622866Smckusick }
28722866Smckusick 
28822866Smckusick 
28922866Smckusick 
29022866Smckusick /* put out label  l:     */
29122866Smckusick putlabel(label)
29222866Smckusick int label;
29322866Smckusick {
29422866Smckusick p2op(PCCF_FLABEL, label);
29522866Smckusick }
29622866Smckusick 
29722866Smckusick 
29822866Smckusick 
29922866Smckusick 
30022866Smckusick putexpr(p)
30122866Smckusick expptr p;
30222866Smckusick {
30322866Smckusick putex1(p);
30422866Smckusick putstmt();
30522866Smckusick }
30622866Smckusick 
30722866Smckusick 
30822866Smckusick 
30922866Smckusick 
31022866Smckusick putcmgo(index, nlab, labs)
31122866Smckusick expptr index;
31222866Smckusick int nlab;
31322866Smckusick struct Labelblock *labs[];
31422866Smckusick {
31522866Smckusick int i, labarray, skiplabel;
31622866Smckusick 
31722866Smckusick if(! ISINT(index->headblock.vtype) )
31822866Smckusick 	{
31922866Smckusick 	execerr("computed goto index must be integer", CNULL);
32022866Smckusick 	return;
32122866Smckusick 	}
32222866Smckusick 
32322866Smckusick #if TARGET == VAX
32422866Smckusick 	/* use special case instruction */
32522866Smckusick 	vaxgoto(index, nlab, labs);
32622866Smckusick #else
32722866Smckusick 	labarray = newlabel();
32822866Smckusick 	preven(ALIADDR);
32922866Smckusick 	prlabel(asmfile, labarray);
33022866Smckusick 	prcona(asmfile, (ftnint) (skiplabel = newlabel()) );
33122866Smckusick 	for(i = 0 ; i < nlab ; ++i)
33222866Smckusick 		if( labs[i] )
33322866Smckusick 			prcona(asmfile, (ftnint)(labs[i]->labelno) );
33422866Smckusick 	prcmgoto(index, nlab, skiplabel, labarray);
33522866Smckusick 	putlabel(skiplabel);
33622866Smckusick #endif
33722866Smckusick }
33822866Smckusick 
33922866Smckusick putx(p)
34022866Smckusick expptr p;
34122866Smckusick {
34222866Smckusick char *memname();
34322866Smckusick int opc;
34422866Smckusick int ncomma;
34522866Smckusick int type, k;
34622866Smckusick 
34722866Smckusick if (!p)
34822866Smckusick 	return;
34922866Smckusick 
35022866Smckusick switch(p->tag)
35122866Smckusick 	{
35222866Smckusick 	case TERROR:
35322866Smckusick 		free( (charptr) p );
35422866Smckusick 		break;
35522866Smckusick 
35622866Smckusick 	case TCONST:
35722866Smckusick 		switch(type = p->constblock.vtype)
35822866Smckusick 			{
35922866Smckusick 			case TYLOGICAL:
36022866Smckusick 				type = tyint;
36122866Smckusick 			case TYLONG:
36222866Smckusick 			case TYSHORT:
363*33257Sbostic 				p2icon(p->constblock.constant.ci, types2[type]);
36422866Smckusick 				free( (charptr) p );
36522866Smckusick 				break;
36622866Smckusick 
36722866Smckusick 			case TYADDR:
36822866Smckusick 				p2triple(PCC_ICON, 1, PCCT_INT|PCCTM_PTR);
36922866Smckusick 				p2word(0L);
37022866Smckusick 				p2name(memname(STGCONST,
371*33257Sbostic 					(int) p->constblock.constant.ci) );
37222866Smckusick 				free( (charptr) p );
37322866Smckusick 				break;
37422866Smckusick 
37522866Smckusick 			default:
37622866Smckusick 				putx( putconst(p) );
37722866Smckusick 				break;
37822866Smckusick 			}
37922866Smckusick 		break;
38022866Smckusick 
38122866Smckusick 	case TEXPR:
38222866Smckusick 		switch(opc = p->exprblock.opcode)
38322866Smckusick 			{
38422866Smckusick 			case OPCALL:
38522866Smckusick 			case OPCCALL:
38622866Smckusick 				if( ISCOMPLEX(p->exprblock.vtype) )
38722866Smckusick 					putcxop(p);
38822866Smckusick 				else	putcall(p);
38922866Smckusick 				break;
39022866Smckusick 
39122866Smckusick 			case OPMIN:
39222866Smckusick 			case OPMAX:
39322866Smckusick 				putmnmx(p);
39422866Smckusick 				break;
39522866Smckusick 
39622866Smckusick 
39722866Smckusick 			case OPASSIGN:
39822866Smckusick 				if(ISCOMPLEX(p->exprblock.leftp->headblock.vtype)
39922866Smckusick 				|| ISCOMPLEX(p->exprblock.rightp->headblock.vtype) )
40022866Smckusick 					frexpr( putcxeq(p) );
40122866Smckusick 				else if( ISCHAR(p) )
40222866Smckusick 					putcheq(p);
40322866Smckusick 				else
40422866Smckusick 					goto putopp;
40522866Smckusick 				break;
40622866Smckusick 
40722866Smckusick 			case OPEQ:
40822866Smckusick 			case OPNE:
40922866Smckusick 				if( ISCOMPLEX(p->exprblock.leftp->headblock.vtype) ||
41022866Smckusick 				    ISCOMPLEX(p->exprblock.rightp->headblock.vtype) )
41122866Smckusick 					{
41222866Smckusick 					putcxcmp(p);
41322866Smckusick 					break;
41422866Smckusick 					}
41522866Smckusick 			case OPLT:
41622866Smckusick 			case OPLE:
41722866Smckusick 			case OPGT:
41822866Smckusick 			case OPGE:
41922866Smckusick 				if(ISCHAR(p->exprblock.leftp))
42022866Smckusick 					{
42122866Smckusick 					putchcmp(p);
42222866Smckusick 					break;
42322866Smckusick 					}
42422866Smckusick 				goto putopp;
42522866Smckusick 
42622866Smckusick 			case OPPOWER:
42722866Smckusick 				putpower(p);
42822866Smckusick 				break;
42922866Smckusick 
43022866Smckusick 			case OPSTAR:
43122866Smckusick #if FAMILY == PCC
43222866Smckusick 				/*   m * (2**k) -> m<<k   */
43322866Smckusick 				if(INT(p->exprblock.leftp->headblock.vtype) &&
43422866Smckusick 				   ISICON(p->exprblock.rightp) &&
435*33257Sbostic 				   ( (k = log2(p->exprblock.rightp->constblock.constant.ci))>0) )
43622866Smckusick 					{
43722866Smckusick 					p->exprblock.opcode = OPLSHIFT;
43822866Smckusick 					frexpr(p->exprblock.rightp);
43922866Smckusick 					p->exprblock.rightp = ICON(k);
44022866Smckusick 					goto putopp;
44122866Smckusick 					}
44222866Smckusick #endif
44322866Smckusick 
44422866Smckusick 			case OPMOD:
44522866Smckusick 				goto putopp;
44622866Smckusick 			case OPPLUS:
44722866Smckusick 			case OPMINUS:
44822866Smckusick 			case OPSLASH:
44922866Smckusick 			case OPNEG:
45022866Smckusick 				if( ISCOMPLEX(p->exprblock.vtype) )
45122866Smckusick 					putcxop(p);
45222866Smckusick 				else	goto putopp;
45322866Smckusick 				break;
45422866Smckusick 
45522866Smckusick 			case OPCONV:
45622866Smckusick 				if( ISCOMPLEX(p->exprblock.vtype) )
45722866Smckusick 					putcxop(p);
45822866Smckusick 				else if( ISCOMPLEX(p->exprblock.leftp->headblock.vtype) )
45922866Smckusick 					{
46022866Smckusick 					ncomma = 0;
46122866Smckusick 					putx( mkconv(p->exprblock.vtype,
46222866Smckusick 						realpart(putcx1(p->exprblock.leftp,
46322866Smckusick 							&ncomma))));
46422866Smckusick 					putcomma(ncomma, p->exprblock.vtype, NO);
46522866Smckusick 					free( (charptr) p );
46622866Smckusick 					}
46722866Smckusick 				else	goto putopp;
46822866Smckusick 				break;
46922866Smckusick 
47022866Smckusick 			case OPNOT:
47122866Smckusick 			case OPOR:
47222866Smckusick 			case OPAND:
47322866Smckusick 			case OPEQV:
47422866Smckusick 			case OPNEQV:
47522866Smckusick 			case OPADDR:
47622866Smckusick 			case OPPLUSEQ:
47722866Smckusick 			case OPSTAREQ:
47822866Smckusick 			case OPCOMMA:
47922866Smckusick 			case OPQUEST:
48022866Smckusick 			case OPCOLON:
48122866Smckusick 			case OPBITOR:
48222866Smckusick 			case OPBITAND:
48322866Smckusick 			case OPBITXOR:
48422866Smckusick 			case OPBITNOT:
48522866Smckusick 			case OPLSHIFT:
48622866Smckusick 			case OPRSHIFT:
48722866Smckusick 		putopp:
48822866Smckusick 				putop(p);
48922866Smckusick 				break;
49022866Smckusick 
49122866Smckusick 			case OPPAREN:
49222866Smckusick 				putx (p->exprblock.leftp);
49322866Smckusick 				break;
49422866Smckusick 			default:
49522866Smckusick 				badop("putx", opc);
49622866Smckusick 			}
49722866Smckusick 		break;
49822866Smckusick 
49922866Smckusick 	case TADDR:
50022866Smckusick 		putaddr(p, YES);
50122866Smckusick 		break;
50222866Smckusick 
50322866Smckusick 	case TTEMP:
50422866Smckusick 		/*
50522866Smckusick 		 * This type is sometimes passed to putx when errors occur
50622866Smckusick 		 *	upstream, I don't know why.
50722866Smckusick 		 */
50822866Smckusick 		frexpr(p);
50922866Smckusick 		break;
51022866Smckusick 
51122866Smckusick 	default:
51222866Smckusick 		badtag("putx", p->tag);
51322866Smckusick 	}
51422866Smckusick }
51522866Smckusick 
51622866Smckusick 
51722866Smckusick 
51822866Smckusick LOCAL putop(p)
51922866Smckusick expptr p;
52022866Smckusick {
52122866Smckusick int k;
52222866Smckusick expptr lp, tp;
52322866Smckusick int pt, lt, tt;
52422866Smckusick int comma;
52522866Smckusick Addrp putch1();
52622866Smckusick 
52722866Smckusick switch(p->exprblock.opcode)	/* check for special cases and rewrite */
52822866Smckusick 	{
52922866Smckusick 	case OPCONV:
53022866Smckusick 		tt = pt = p->exprblock.vtype;
53122866Smckusick 		lp = p->exprblock.leftp;
53222866Smckusick 		lt = lp->headblock.vtype;
53322866Smckusick 		if (pt == TYREAL && lt == TYDREAL)
53422866Smckusick 			{
53522866Smckusick 			putx(lp);
53622866Smckusick 			p2op(PCC_SCONV, PCCT_FLOAT);
53722866Smckusick 			return;
53822866Smckusick 			}
53922866Smckusick 		while(p->tag==TEXPR && p->exprblock.opcode==OPCONV &&
54022866Smckusick 		      ( (ISREAL(pt)&&ISREAL(lt)) ||
54122866Smckusick 			(INT(pt)&&(ONEOF(lt,MSKINT|MSKADDR|MSKCHAR|M(TYSUBR)))) ))
54222866Smckusick 			{
54322866Smckusick #if SZINT < SZLONG
54422866Smckusick 			if(lp->tag != TEXPR)
54522866Smckusick 				{
54622866Smckusick 				if(pt==TYINT && lt==TYLONG)
54722866Smckusick 					break;
54822866Smckusick 				if(lt==TYINT && pt==TYLONG)
54922866Smckusick 					break;
55022866Smckusick 				}
55122866Smckusick #endif
55222866Smckusick 
55322866Smckusick #if TARGET == VAX
55422866Smckusick 			if(pt==TYDREAL && lt==TYREAL)
55522866Smckusick 				{
55622866Smckusick 				if(lp->tag==TEXPR &&
55722866Smckusick 				   lp->exprblock.opcode==OPCONV &&
55822866Smckusick 				   lp->exprblock.leftp->headblock.vtype==TYDREAL)
55922866Smckusick 					{
56022866Smckusick 					putx(lp->exprblock.leftp);
56122866Smckusick 					p2op(PCC_SCONV, PCCT_FLOAT);
56222866Smckusick 					p2op(PCC_SCONV, PCCT_DOUBLE);
56322866Smckusick 					free( (charptr) p );
56422866Smckusick 					return;
56522866Smckusick 					}
56622866Smckusick 				else break;
56722866Smckusick 				}
56822866Smckusick #endif
56922866Smckusick 			if(lt==TYCHAR && lp->tag==TEXPR)
57022866Smckusick 				{
57122866Smckusick 				int ncomma = 0;
57222866Smckusick 				p->exprblock.leftp = (expptr) putch1(lp, &ncomma);
57322866Smckusick 				putop(p);
57422866Smckusick 				putcomma(ncomma, pt, NO);
57522866Smckusick 				free( (charptr) p );
57622866Smckusick 				return;
57722866Smckusick 				}
57822866Smckusick 			free( (charptr) p );
57922866Smckusick 			p = lp;
58022866Smckusick 			pt = lt;
58122866Smckusick 			if (p->tag == TEXPR)
58222866Smckusick 				{
58322866Smckusick 				lp = p->exprblock.leftp;
58422866Smckusick 				lt = lp->headblock.vtype;
58522866Smckusick 				}
58622866Smckusick 			}
58722866Smckusick 		if(p->tag==TEXPR && p->exprblock.opcode==OPCONV)
58822866Smckusick 			break;
58922866Smckusick 		putx(p);
59022866Smckusick 		if (types2[tt] != types2[pt] &&
59122866Smckusick 		    ! ( (ISREAL(tt)&&ISREAL(pt)) ||
59222866Smckusick 			(INT(tt)&&(ONEOF(pt,MSKINT|MSKADDR|MSKCHAR|M(TYSUBR)))) ))
59322866Smckusick 			p2op(PCC_SCONV,types2[tt]);
59422866Smckusick 		return;
59522866Smckusick 
59622866Smckusick 	case OPADDR:
59722866Smckusick 		comma = NO;
59822866Smckusick 		lp = p->exprblock.leftp;
59922866Smckusick 		if(lp->tag != TADDR)
60022866Smckusick 			{
60122866Smckusick 			tp = (expptr) mkaltemp
60222866Smckusick 				(lp->headblock.vtype,lp->headblock.vleng);
60322866Smckusick 			putx( mkexpr(OPASSIGN, cpexpr(tp), lp) );
60422866Smckusick 			lp = tp;
60522866Smckusick 			comma = YES;
60622866Smckusick 			}
60722866Smckusick 		putaddr(lp, NO);
60822866Smckusick 		if(comma)
60922866Smckusick 			putcomma(1, TYINT, NO);
61022866Smckusick 		free( (charptr) p );
61122866Smckusick 		return;
61222866Smckusick #if TARGET == VAX
61322866Smckusick /* take advantage of a glitch in the code generator that does not check
61422866Smckusick    the type clash in an assignment or comparison of an integer zero and
61522866Smckusick    a floating left operand, and generates optimal code for the correct
61622866Smckusick    type.  (The PCC has no floating-constant node to encode this correctly.)
61722866Smckusick */
61822866Smckusick 	case OPASSIGN:
61922866Smckusick 	case OPLT:
62022866Smckusick 	case OPLE:
62122866Smckusick 	case OPGT:
62222866Smckusick 	case OPGE:
62322866Smckusick 	case OPEQ:
62422866Smckusick 	case OPNE:
62522866Smckusick 		if(ISREAL(p->exprblock.leftp->headblock.vtype) &&
62622866Smckusick 		   ISREAL(p->exprblock.rightp->headblock.vtype) &&
62722866Smckusick 		   ISCONST(p->exprblock.rightp) &&
628*33257Sbostic 		   p->exprblock.rightp->constblock.constant.cd[0]==0)
62922866Smckusick 			{
63022866Smckusick 			p->exprblock.rightp->constblock.vtype = TYINT;
631*33257Sbostic 			p->exprblock.rightp->constblock.constant.ci = 0;
63222866Smckusick 			}
63322866Smckusick #endif
63422866Smckusick 	}
63522866Smckusick 
63622866Smckusick if( (k = ops2[p->exprblock.opcode]) <= 0)
63722866Smckusick 	badop("putop", p->exprblock.opcode);
63822866Smckusick putx(p->exprblock.leftp);
63922866Smckusick if(p->exprblock.rightp)
64022866Smckusick 	putx(p->exprblock.rightp);
64122866Smckusick p2op(k, types2[p->exprblock.vtype]);
64222866Smckusick 
64322866Smckusick if(p->exprblock.vleng)
64422866Smckusick 	frexpr(p->exprblock.vleng);
64522866Smckusick free( (charptr) p );
64622866Smckusick }
64722866Smckusick 
64822866Smckusick putforce(t, p)
64922866Smckusick int t;
65022866Smckusick expptr p;
65122866Smckusick {
65222866Smckusick p = mkconv(t, fixtype(p));
65322866Smckusick putx(p);
65422866Smckusick p2op(PCC_FORCE,
65522866Smckusick 	(t==TYSHORT ? PCCT_SHORT : (t==TYLONG ? PCCT_LONG : PCCT_DOUBLE)) );
65622866Smckusick putstmt();
65722866Smckusick }
65822866Smckusick 
65922866Smckusick 
66022866Smckusick 
66122866Smckusick LOCAL putpower(p)
66222866Smckusick expptr p;
66322866Smckusick {
66422866Smckusick expptr base;
66522866Smckusick Addrp t1, t2;
66622866Smckusick ftnint k;
66722866Smckusick int type;
66822866Smckusick int ncomma;
66922866Smckusick 
67022866Smckusick if(!ISICON(p->exprblock.rightp) ||
671*33257Sbostic     (k = p->exprblock.rightp->constblock.constant.ci)<2)
67222866Smckusick 	fatal("putpower: bad call");
67322866Smckusick base = p->exprblock.leftp;
67422866Smckusick type = base->headblock.vtype;
67522866Smckusick 
67622866Smckusick if ((k == 2) && base->tag == TADDR && ISCONST(base->addrblock.memoffset))
67722866Smckusick {
67822866Smckusick 	putx( mkexpr(OPSTAR,cpexpr(base),cpexpr(base)));
67922866Smckusick 
68022866Smckusick 	return;
68122866Smckusick }
68222866Smckusick t1 = mkaltemp(type, PNULL);
68322866Smckusick t2 = NULL;
68422866Smckusick ncomma = 1;
68522866Smckusick putassign(cpexpr(t1), cpexpr(base) );
68622866Smckusick 
68722866Smckusick for( ; (k&1)==0 && k>2 ; k>>=1 )
68822866Smckusick 	{
68922866Smckusick 	++ncomma;
69022866Smckusick 	putsteq(t1, t1);
69122866Smckusick 	}
69222866Smckusick 
69322866Smckusick if(k == 2)
69422866Smckusick 	putx( mkexpr(OPSTAR, cpexpr(t1), cpexpr(t1)) );
69522866Smckusick else
69622866Smckusick 	{
69722866Smckusick 	t2 = mkaltemp(type, PNULL);
69822866Smckusick 	++ncomma;
69922866Smckusick 	putassign(cpexpr(t2), cpexpr(t1));
70022866Smckusick 
70122866Smckusick 	for(k>>=1 ; k>1 ; k>>=1)
70222866Smckusick 		{
70322866Smckusick 		++ncomma;
70422866Smckusick 		putsteq(t1, t1);
70522866Smckusick 		if(k & 1)
70622866Smckusick 			{
70722866Smckusick 			++ncomma;
70822866Smckusick 			putsteq(t2, t1);
70922866Smckusick 			}
71022866Smckusick 		}
71122866Smckusick 	putx( mkexpr(OPSTAR, cpexpr(t2),
71222866Smckusick 		mkexpr(OPSTAR, cpexpr(t1), cpexpr(t1)) ));
71322866Smckusick 	}
71422866Smckusick putcomma(ncomma, type, NO);
71522866Smckusick frexpr(t1);
71622866Smckusick if(t2)
71722866Smckusick 	frexpr(t2);
71822866Smckusick frexpr(p);
71922866Smckusick }
72022866Smckusick 
72122866Smckusick 
72222866Smckusick 
72322866Smckusick 
72422866Smckusick LOCAL Addrp intdouble(p, ncommap)
72522866Smckusick Addrp p;
72622866Smckusick int *ncommap;
72722866Smckusick {
72822866Smckusick register Addrp t;
72922866Smckusick 
73022866Smckusick t = mkaltemp(TYDREAL, PNULL);
73122866Smckusick ++*ncommap;
73222866Smckusick putassign(cpexpr(t), p);
73322866Smckusick return(t);
73422866Smckusick }
73522866Smckusick 
73622866Smckusick 
73722866Smckusick 
73822866Smckusick 
73922866Smckusick 
74022866Smckusick LOCAL Addrp putcxeq(p)
74122866Smckusick register expptr p;
74222866Smckusick {
74322866Smckusick register Addrp lp, rp;
74422866Smckusick int ncomma;
74522866Smckusick 
74622866Smckusick if(p->tag != TEXPR)
74722866Smckusick 	badtag("putcxeq", p->tag);
74822866Smckusick 
74922866Smckusick ncomma = 0;
75022866Smckusick lp = putcx1(p->exprblock.leftp, &ncomma);
75122866Smckusick rp = putcx1(p->exprblock.rightp, &ncomma);
75222866Smckusick putassign(realpart(lp), realpart(rp));
75322866Smckusick if( ISCOMPLEX(p->exprblock.vtype) )
75422866Smckusick 	{
75522866Smckusick 	++ncomma;
75622866Smckusick 	putassign(imagpart(lp), imagpart(rp));
75722866Smckusick 	}
75822866Smckusick putcomma(ncomma, TYREAL, NO);
75922866Smckusick frexpr(rp);
76022866Smckusick free( (charptr) p );
76122866Smckusick return(lp);
76222866Smckusick }
76322866Smckusick 
76422866Smckusick 
76522866Smckusick 
76622866Smckusick LOCAL putcxop(p)
76722866Smckusick expptr p;
76822866Smckusick {
76922866Smckusick Addrp putcx1();
77022866Smckusick int ncomma;
77122866Smckusick 
77222866Smckusick ncomma = 0;
77322866Smckusick putaddr( putcx1(p, &ncomma), NO);
77422866Smckusick putcomma(ncomma, TYINT, NO);
77522866Smckusick }
77622866Smckusick 
77722866Smckusick 
77822866Smckusick 
77922866Smckusick LOCAL Addrp putcx1(p, ncommap)
78022866Smckusick register expptr p;
78122866Smckusick int *ncommap;
78222866Smckusick {
78322866Smckusick expptr q;
78422866Smckusick Addrp lp, rp;
78522866Smckusick register Addrp resp;
78622866Smckusick int opcode;
78722866Smckusick int ltype, rtype;
78822866Smckusick expptr mkrealcon();
78922866Smckusick 
79022866Smckusick if(p == NULL)
79122866Smckusick 	return(NULL);
79222866Smckusick 
79322866Smckusick switch(p->tag)
79422866Smckusick 	{
79522866Smckusick 	case TCONST:
79622866Smckusick 		if( ISCOMPLEX(p->constblock.vtype) )
79722866Smckusick 			p = (expptr) putconst(p);
79822866Smckusick 		return( (Addrp) p );
79922866Smckusick 
80022866Smckusick 	case TADDR:
80122866Smckusick 		if( ! addressable(p) )
80222866Smckusick 			{
80322866Smckusick 			++*ncommap;
80422866Smckusick 			resp = mkaltemp(tyint, PNULL);
80522866Smckusick 			putassign( cpexpr(resp), p->addrblock.memoffset );
80622866Smckusick 			p->addrblock.memoffset = (expptr)resp;
80722866Smckusick 			}
80822866Smckusick 		return( (Addrp) p );
80922866Smckusick 
81022866Smckusick 	case TEXPR:
81122866Smckusick 		if( ISCOMPLEX(p->exprblock.vtype) )
81222866Smckusick 			break;
81322866Smckusick 		++*ncommap;
81422866Smckusick 		resp = mkaltemp(TYDREAL, NO);
81522866Smckusick 		putassign( cpexpr(resp), p);
81622866Smckusick 		return(resp);
81722866Smckusick 
81822866Smckusick 	default:
81922866Smckusick 		badtag("putcx1", p->tag);
82022866Smckusick 	}
82122866Smckusick 
82222866Smckusick opcode = p->exprblock.opcode;
82322866Smckusick if(opcode==OPCALL || opcode==OPCCALL)
82422866Smckusick 	{
82522866Smckusick 	++*ncommap;
82622866Smckusick 	return( putcall(p) );
82722866Smckusick 	}
82822866Smckusick else if(opcode == OPASSIGN)
82922866Smckusick 	{
83022866Smckusick 	++*ncommap;
83122866Smckusick 	return( putcxeq(p) );
83222866Smckusick 	}
83322866Smckusick resp = mkaltemp(p->exprblock.vtype, PNULL);
83422866Smckusick if(lp = putcx1(p->exprblock.leftp, ncommap) )
83522866Smckusick 	ltype = lp->vtype;
83622866Smckusick if(rp = putcx1(p->exprblock.rightp, ncommap) )
83722866Smckusick 	rtype = rp->vtype;
83822866Smckusick 
83922866Smckusick switch(opcode)
84022866Smckusick 	{
84122866Smckusick 	case OPPAREN:
84222866Smckusick 		frexpr (resp);
84322866Smckusick 		resp = lp;
84422866Smckusick 		lp = NULL;
84522866Smckusick 		break;
84622866Smckusick 
84722866Smckusick 	case OPCOMMA:
84822866Smckusick 		frexpr(resp);
84922866Smckusick 		resp = rp;
85022866Smckusick 		rp = NULL;
85122866Smckusick 		break;
85222866Smckusick 
85322866Smckusick 	case OPNEG:
85422866Smckusick 		putassign( realpart(resp), mkexpr(OPNEG, realpart(lp), ENULL) );
85522866Smckusick 		putassign( imagpart(resp), mkexpr(OPNEG, imagpart(lp), ENULL) );
85622866Smckusick 		*ncommap += 2;
85722866Smckusick 		break;
85822866Smckusick 
85922866Smckusick 	case OPPLUS:
86022866Smckusick 	case OPMINUS:
86122866Smckusick 		putassign( realpart(resp),
86222866Smckusick 			mkexpr(opcode, realpart(lp), realpart(rp) ));
86322866Smckusick 		if(rtype < TYCOMPLEX)
86422866Smckusick 			putassign( imagpart(resp), imagpart(lp) );
86522866Smckusick 		else if(ltype < TYCOMPLEX)
86622866Smckusick 			{
86722866Smckusick 			if(opcode == OPPLUS)
86822866Smckusick 				putassign( imagpart(resp), imagpart(rp) );
86922866Smckusick 			else	putassign( imagpart(resp),
87022866Smckusick 					mkexpr(OPNEG, imagpart(rp), ENULL) );
87122866Smckusick 			}
87222866Smckusick 		else
87322866Smckusick 			putassign( imagpart(resp),
87422866Smckusick 				mkexpr(opcode, imagpart(lp), imagpart(rp) ));
87522866Smckusick 
87622866Smckusick 		*ncommap += 2;
87722866Smckusick 		break;
87822866Smckusick 
87922866Smckusick 	case OPSTAR:
88022866Smckusick 		if(ltype < TYCOMPLEX)
88122866Smckusick 			{
88222866Smckusick 			if( ISINT(ltype) )
88322866Smckusick 				lp = intdouble(lp, ncommap);
88422866Smckusick 			putassign( realpart(resp),
88522866Smckusick 				mkexpr(OPSTAR, cpexpr(lp), realpart(rp) ));
88622866Smckusick 			putassign( imagpart(resp),
88722866Smckusick 				mkexpr(OPSTAR, cpexpr(lp), imagpart(rp) ));
88822866Smckusick 			}
88922866Smckusick 		else if(rtype < TYCOMPLEX)
89022866Smckusick 			{
89122866Smckusick 			if( ISINT(rtype) )
89222866Smckusick 				rp = intdouble(rp, ncommap);
89322866Smckusick 			putassign( realpart(resp),
89422866Smckusick 				mkexpr(OPSTAR, cpexpr(rp), realpart(lp) ));
89522866Smckusick 			putassign( imagpart(resp),
89622866Smckusick 				mkexpr(OPSTAR, cpexpr(rp), imagpart(lp) ));
89722866Smckusick 			}
89822866Smckusick 		else	{
89922866Smckusick 			putassign( realpart(resp), mkexpr(OPMINUS,
90022866Smckusick 				mkexpr(OPSTAR, realpart(lp), realpart(rp)),
90122866Smckusick 				mkexpr(OPSTAR, imagpart(lp), imagpart(rp)) ));
90222866Smckusick 			putassign( imagpart(resp), mkexpr(OPPLUS,
90322866Smckusick 				mkexpr(OPSTAR, realpart(lp), imagpart(rp)),
90422866Smckusick 				mkexpr(OPSTAR, imagpart(lp), realpart(rp)) ));
90522866Smckusick 			}
90622866Smckusick 		*ncommap += 2;
90722866Smckusick 		break;
90822866Smckusick 
90922866Smckusick 	case OPSLASH:
91022866Smckusick 		/* fixexpr has already replaced all divisions
91122866Smckusick 		 * by a complex by a function call
91222866Smckusick 		 */
91322866Smckusick 		if( ISINT(rtype) )
91422866Smckusick 			rp = intdouble(rp, ncommap);
91522866Smckusick 		putassign( realpart(resp),
91622866Smckusick 			mkexpr(OPSLASH, realpart(lp), cpexpr(rp)) );
91722866Smckusick 		putassign( imagpart(resp),
91822866Smckusick 			mkexpr(OPSLASH, imagpart(lp), cpexpr(rp)) );
91922866Smckusick 		*ncommap += 2;
92022866Smckusick 		break;
92122866Smckusick 
92222866Smckusick 	case OPCONV:
92322866Smckusick 		putassign( realpart(resp), realpart(lp) );
92422866Smckusick 		if( ISCOMPLEX(lp->vtype) )
92522866Smckusick 			q = imagpart(lp);
92622866Smckusick 		else if(rp != NULL)
92722866Smckusick 			q = (expptr) realpart(rp);
92822866Smckusick 		else
92922866Smckusick 			q = mkrealcon(TYDREAL, 0.0);
93022866Smckusick 		putassign( imagpart(resp), q);
93122866Smckusick 		*ncommap += 2;
93222866Smckusick 		break;
93322866Smckusick 
93422866Smckusick 	default:
93522866Smckusick 		badop("putcx1", opcode);
93622866Smckusick 	}
93722866Smckusick 
93822866Smckusick frexpr(lp);
93922866Smckusick frexpr(rp);
94022866Smckusick free( (charptr) p );
94122866Smckusick return(resp);
94222866Smckusick }
94322866Smckusick 
94422866Smckusick 
94522866Smckusick 
94622866Smckusick 
94722866Smckusick LOCAL putcxcmp(p)
94822866Smckusick register expptr p;
94922866Smckusick {
95022866Smckusick int opcode;
95122866Smckusick int ncomma;
95222866Smckusick register Addrp lp, rp;
95322866Smckusick expptr q;
95422866Smckusick 
95522866Smckusick if(p->tag != TEXPR)
95622866Smckusick 	badtag("putcxcmp", p->tag);
95722866Smckusick 
95822866Smckusick ncomma = 0;
95922866Smckusick opcode = p->exprblock.opcode;
96022866Smckusick lp = putcx1(p->exprblock.leftp, &ncomma);
96122866Smckusick rp = putcx1(p->exprblock.rightp, &ncomma);
96222866Smckusick 
96322866Smckusick q = mkexpr( opcode==OPEQ ? OPAND : OPOR ,
96422866Smckusick 	mkexpr(opcode, realpart(lp), realpart(rp)),
96522866Smckusick 	mkexpr(opcode, imagpart(lp), imagpart(rp)) );
96622866Smckusick putx( fixexpr(q) );
96722866Smckusick putcomma(ncomma, TYINT, NO);
96822866Smckusick 
96922866Smckusick free( (charptr) lp);
97022866Smckusick free( (charptr) rp);
97122866Smckusick free( (charptr) p );
97222866Smckusick }
97322866Smckusick 
97422866Smckusick LOCAL Addrp putch1(p, ncommap)
97522866Smckusick register expptr p;
97622866Smckusick int * ncommap;
97722866Smckusick {
97822866Smckusick register Addrp t;
97922866Smckusick 
98022866Smckusick switch(p->tag)
98122866Smckusick 	{
98222866Smckusick 	case TCONST:
98322866Smckusick 		return( putconst(p) );
98422866Smckusick 
98522866Smckusick 	case TADDR:
98622866Smckusick 		return( (Addrp) p );
98722866Smckusick 
98822866Smckusick 	case TEXPR:
98922866Smckusick 		++*ncommap;
99022866Smckusick 
99122866Smckusick 		switch(p->exprblock.opcode)
99222866Smckusick 			{
99322866Smckusick 			expptr q;
99422866Smckusick 
99522866Smckusick 			case OPCALL:
99622866Smckusick 			case OPCCALL:
99722866Smckusick 				t = putcall(p);
99822866Smckusick 				break;
99922866Smckusick 
100022866Smckusick 			case OPPAREN:
100122866Smckusick 				--*ncommap;
100222866Smckusick 				t = putch1(p->exprblock.leftp, ncommap);
100322866Smckusick 				break;
100422866Smckusick 
100522866Smckusick 			case OPCONCAT:
100622866Smckusick 				t = mkaltemp(TYCHAR, ICON(lencat(p)) );
100722866Smckusick 				q = (expptr) cpexpr(p->headblock.vleng);
100822866Smckusick 				putcat( cpexpr(t), p );
100922866Smckusick 				/* put the correct length on the block */
101022866Smckusick 				frexpr(t->vleng);
101122866Smckusick 				t->vleng = q;
101222866Smckusick 
101322866Smckusick 				break;
101422866Smckusick 
101522866Smckusick 			case OPCONV:
101622866Smckusick 				if(!ISICON(p->exprblock.vleng)
1017*33257Sbostic 				   || p->exprblock.vleng->constblock.constant.ci!=1
101822866Smckusick 				   || ! INT(p->exprblock.leftp->headblock.vtype) )
101922866Smckusick 					fatal("putch1: bad character conversion");
102022866Smckusick 				t = mkaltemp(TYCHAR, ICON(1) );
102122866Smckusick 				putop( mkexpr(OPASSIGN, cpexpr(t), p) );
102222866Smckusick 				break;
102322866Smckusick 			default:
102422866Smckusick 				badop("putch1", p->exprblock.opcode);
102522866Smckusick 			}
102622866Smckusick 		return(t);
102722866Smckusick 
102822866Smckusick 	default:
102922866Smckusick 		badtag("putch1", p->tag);
103022866Smckusick 	}
103122866Smckusick /* NOTREACHED */
103222866Smckusick }
103322866Smckusick 
103422866Smckusick 
103522866Smckusick 
103622866Smckusick 
103722866Smckusick LOCAL putchop(p)
103822866Smckusick expptr p;
103922866Smckusick {
104022866Smckusick int ncomma;
104122866Smckusick 
104222866Smckusick ncomma = 0;
104322866Smckusick putaddr( putch1(p, &ncomma) , NO );
104422866Smckusick putcomma(ncomma, TYCHAR, YES);
104522866Smckusick }
104622866Smckusick 
104722866Smckusick 
104822866Smckusick 
104922866Smckusick 
105022866Smckusick LOCAL putcheq(p)
105122866Smckusick register expptr p;
105222866Smckusick {
105322866Smckusick int ncomma;
105422866Smckusick expptr lp, rp;
105522866Smckusick 
105622866Smckusick if(p->tag != TEXPR)
105722866Smckusick 	badtag("putcheq", p->tag);
105822866Smckusick 
105922866Smckusick ncomma = 0;
106022866Smckusick lp = p->exprblock.leftp;
106122866Smckusick rp = p->exprblock.rightp;
106222866Smckusick if( rp->tag==TEXPR && rp->exprblock.opcode==OPCONCAT )
106322866Smckusick 	putcat(lp, rp);
106422866Smckusick else if( ISONE(lp->headblock.vleng) && ISONE(rp->headblock.vleng) )
106522866Smckusick 	{
106622866Smckusick 	putaddr( putch1(lp, &ncomma) , YES );
106722866Smckusick 	putaddr( putch1(rp, &ncomma) , YES );
106822866Smckusick 	putcomma(ncomma, TYINT, NO);
106922866Smckusick 	p2op(PCC_ASSIGN, PCCT_CHAR);
107022866Smckusick 	}
107122866Smckusick else
107222866Smckusick 	{
107322866Smckusick 	putx( call2(TYINT, "s_copy", lp, rp) );
107422866Smckusick 	putcomma(ncomma, TYINT, NO);
107522866Smckusick 	}
107622866Smckusick 
107722866Smckusick frexpr(p->exprblock.vleng);
107822866Smckusick free( (charptr) p );
107922866Smckusick }
108022866Smckusick 
108122866Smckusick 
108222866Smckusick 
108322866Smckusick 
108422866Smckusick LOCAL putchcmp(p)
108522866Smckusick register expptr p;
108622866Smckusick {
108722866Smckusick int ncomma;
108822866Smckusick expptr lp, rp;
108922866Smckusick 
109022866Smckusick if(p->tag != TEXPR)
109122866Smckusick 	badtag("putchcmp", p->tag);
109222866Smckusick 
109322866Smckusick ncomma = 0;
109422866Smckusick lp = p->exprblock.leftp;
109522866Smckusick rp = p->exprblock.rightp;
109622866Smckusick 
109722866Smckusick if(ISONE(lp->headblock.vleng) && ISONE(rp->headblock.vleng) )
109822866Smckusick 	{
109922866Smckusick 	putaddr( putch1(lp, &ncomma) , YES );
110022866Smckusick 	putcomma(ncomma, TYINT, NO);
110122866Smckusick 	ncomma = 0;
110222866Smckusick 	putaddr( putch1(rp, &ncomma) , YES );
110322866Smckusick 	putcomma(ncomma, TYINT, NO);
110422866Smckusick 	p2op(ops2[p->exprblock.opcode], PCCT_CHAR);
110522866Smckusick 	free( (charptr) p );
110622866Smckusick 	}
110722866Smckusick else
110822866Smckusick 	{
110922866Smckusick 	p->exprblock.leftp = call2(TYINT,"s_cmp", lp, rp);
111022866Smckusick 	p->exprblock.rightp = ICON(0);
111122866Smckusick 	putop(p);
111222866Smckusick 	}
111322866Smckusick }
111422866Smckusick 
111522866Smckusick 
111622866Smckusick 
111722866Smckusick 
111822866Smckusick 
111922866Smckusick LOCAL putcat(lhs, rhs)
112022866Smckusick register Addrp lhs;
112122866Smckusick register expptr rhs;
112222866Smckusick {
112322866Smckusick int n, ncomma;
112422866Smckusick Addrp lp, cp;
112522866Smckusick 
112622866Smckusick ncomma = 0;
112722866Smckusick n = ncat(rhs);
112822866Smckusick lp = mkaltmpn(n, TYLENG, PNULL);
112922866Smckusick cp = mkaltmpn(n, TYADDR, PNULL);
113022866Smckusick 
113122866Smckusick n = 0;
113222866Smckusick putct1(rhs, lp, cp, &n, &ncomma);
113322866Smckusick 
113422866Smckusick putx( call4(TYSUBR, "s_cat", lhs, cp, lp, mkconv(TYLONG, ICON(n)) ) );
113522866Smckusick putcomma(ncomma, TYINT, NO);
113622866Smckusick }
113722866Smckusick 
113822866Smckusick 
113922866Smckusick 
114022866Smckusick 
114122866Smckusick 
114222866Smckusick LOCAL putct1(q, lp, cp, ip, ncommap)
114322866Smckusick register expptr q;
114422866Smckusick register Addrp lp, cp;
114522866Smckusick int *ip, *ncommap;
114622866Smckusick {
114722866Smckusick int i;
114822866Smckusick Addrp lp1, cp1;
114922866Smckusick 
115022866Smckusick if(q->tag==TEXPR && q->exprblock.opcode==OPCONCAT)
115122866Smckusick 	{
115222866Smckusick 	putct1(q->exprblock.leftp, lp, cp, ip, ncommap);
115322866Smckusick 	putct1(q->exprblock.rightp, lp, cp , ip, ncommap);
115422866Smckusick 	frexpr(q->exprblock.vleng);
115522866Smckusick 	free( (charptr) q );
115622866Smckusick 	}
115722866Smckusick else
115822866Smckusick 	{
115922866Smckusick 	i = (*ip)++;
116026513Sdonn 	cp1 = (Addrp) cpexpr(cp);
116126513Sdonn 	cp1->memoffset = mkexpr(OPPLUS, cp1->memoffset, ICON(i*SZADDR));
116222866Smckusick 	lp1 = (Addrp) cpexpr(lp);
116322866Smckusick 	lp1->memoffset = mkexpr(OPPLUS,lp1->memoffset, ICON(i*SZLENG));
116426513Sdonn 	putassign( cp1, addrof(putch1(cpexpr(q),ncommap)) );
116526513Sdonn 	putassign( lp1, q->headblock.vleng );
116626513Sdonn 	free( (charptr) q );
116722866Smckusick 	*ncommap += 2;
116822866Smckusick 	}
116922866Smckusick }
117022866Smckusick 
117122866Smckusick LOCAL putaddr(p, indir)
117222866Smckusick register Addrp p;
117322866Smckusick int indir;
117422866Smckusick {
117522866Smckusick int type, type2, funct;
117622866Smckusick ftnint offset, simoffset();
117722866Smckusick expptr offp, shorten();
117822866Smckusick 
117922866Smckusick if( p->tag==TERROR || (p->memoffset!=NULL && ISERROR(p->memoffset)) )
118022866Smckusick 	{
118122866Smckusick 	frexpr(p);
118222866Smckusick 	return;
118322866Smckusick 	}
118422866Smckusick if (p->tag != TADDR) badtag ("putaddr",p->tag);
118522866Smckusick 
118622866Smckusick type = p->vtype;
118722866Smckusick type2 = types2[type];
118822866Smckusick funct = (p->vclass==CLPROC ? PCCTM_FTN<<2 : 0);
118922866Smckusick 
119022866Smckusick offp = (p->memoffset ? (expptr) cpexpr(p->memoffset) : (expptr)NULL );
119122866Smckusick 
119222866Smckusick 
119322866Smckusick #if (FUDGEOFFSET != 1)
119422866Smckusick if(offp)
119522866Smckusick 	offp = mkexpr(OPSTAR, ICON(FUDGEOFFSET), offp);
119622866Smckusick #endif
119722866Smckusick 
119822866Smckusick offset = simoffset( &offp );
119922866Smckusick #if SZINT < SZLONG
120022866Smckusick 	if(offp)
120122866Smckusick 		if(shortsubs)
120222866Smckusick 			offp = shorten(offp);
120322866Smckusick 		else
120422866Smckusick 			offp = mkconv(TYINT, offp);
120522866Smckusick #else
120622866Smckusick 	if(offp)
120722866Smckusick 		offp = mkconv(TYINT, offp);
120822866Smckusick #endif
120922866Smckusick 
121022866Smckusick if (p->vclass == CLVAR
121122866Smckusick     && (p->vstg == STGBSS || p->vstg == STGEQUIV)
121222866Smckusick     && SMALLVAR(p->varsize)
121322866Smckusick     && offset >= -32768 && offset <= 32767)
121422866Smckusick   {
121522866Smckusick     anylocals = YES;
121622866Smckusick     if (indir && !offp)
121722866Smckusick       p2ldisp(offset, memname(p->vstg, p->memno), type2);
121822866Smckusick     else
121922866Smckusick       {
122022866Smckusick 	p2reg(11, type2 | PCCTM_PTR);
122122866Smckusick 	p2triple(PCC_ICON, 1, PCCT_INT);
122222866Smckusick 	p2word(offset);
122322866Smckusick 	p2ndisp(memname(p->vstg, p->memno));
122422866Smckusick 	p2op(PCC_PLUS, type2 | PCCTM_PTR);
122522866Smckusick 	if (offp)
122622866Smckusick 	  {
122722866Smckusick 	    putx(offp);
122822866Smckusick 	    p2op(PCC_PLUS, type2 | PCCTM_PTR);
122922866Smckusick 	  }
123022866Smckusick 	if (indir)
123122866Smckusick 	  p2op(PCC_DEREF, type2);
123222866Smckusick       }
123322866Smckusick     frexpr((tagptr) p);
123422866Smckusick     return;
123522866Smckusick   }
123622866Smckusick 
123722866Smckusick switch(p->vstg)
123822866Smckusick 	{
123922866Smckusick 	case STGAUTO:
124022866Smckusick 		if(indir && !offp)
124122866Smckusick 			{
124222866Smckusick 			p2oreg(offset, AUTOREG, type2);
124322866Smckusick 			break;
124422866Smckusick 			}
124522866Smckusick 
124622866Smckusick 		if(!indir && !offp && !offset)
124722866Smckusick 			{
124822866Smckusick 			p2reg(AUTOREG, type2 | PCCTM_PTR);
124922866Smckusick 			break;
125022866Smckusick 			}
125122866Smckusick 
125222866Smckusick 		p2reg(AUTOREG, type2 | PCCTM_PTR);
125322866Smckusick 		if(offp)
125422866Smckusick 			{
125522866Smckusick 			putx(offp);
125622866Smckusick 			if(offset)
125722866Smckusick 				p2icon(offset, PCCT_INT);
125822866Smckusick 			}
125922866Smckusick 		else
126022866Smckusick 			p2icon(offset, PCCT_INT);
126122866Smckusick 		if(offp && offset)
126222866Smckusick 			p2op(PCC_PLUS, type2 | PCCTM_PTR);
126322866Smckusick 		p2op(PCC_PLUS, type2 | PCCTM_PTR);
126422866Smckusick 		if(indir)
126522866Smckusick 			p2op(PCC_DEREF, type2);
126622866Smckusick 		break;
126722866Smckusick 
126822866Smckusick 	case STGARG:
126922866Smckusick 		p2oreg(
127022866Smckusick #ifdef ARGOFFSET
127122866Smckusick 			ARGOFFSET +
127222866Smckusick #endif
127322866Smckusick 			(ftnint) (FUDGEOFFSET*p->memno),
127422866Smckusick 			ARGREG,   type2 | PCCTM_PTR | funct );
127522866Smckusick 
127622866Smckusick 	based:
127722866Smckusick 		if(offset)
127822866Smckusick 			{
127922866Smckusick 			p2icon(offset, PCCT_INT);
128022866Smckusick 			p2op(PCC_PLUS, type2 | PCCTM_PTR);
128122866Smckusick 			}
128222866Smckusick 		if(offp)
128322866Smckusick 			{
128422866Smckusick 			putx(offp);
128522866Smckusick 			p2op(PCC_PLUS, type2 | PCCTM_PTR);
128622866Smckusick 			}
128722866Smckusick 		if(indir)
128822866Smckusick 			p2op(PCC_DEREF, type2);
128922866Smckusick 		break;
129022866Smckusick 
129122866Smckusick 	case STGLENG:
129222866Smckusick 		if(indir)
129322866Smckusick 			{
129422866Smckusick 			p2oreg(
129522866Smckusick #ifdef ARGOFFSET
129622866Smckusick 				ARGOFFSET +
129722866Smckusick #endif
129822866Smckusick 				(ftnint) (FUDGEOFFSET*p->memno),
129922866Smckusick 				ARGREG,   type2 );
130022866Smckusick 			}
130122866Smckusick 		else	{
130222866Smckusick 			p2reg(ARGREG, type2 | PCCTM_PTR );
130322866Smckusick 			p2icon(
130422866Smckusick #ifdef ARGOFFSET
130522866Smckusick 				ARGOFFSET +
130622866Smckusick #endif
130722866Smckusick 				(ftnint) (FUDGEOFFSET*p->memno), PCCT_INT);
130822866Smckusick 			p2op(PCC_PLUS, type2 | PCCTM_PTR );
130922866Smckusick 			}
131022866Smckusick 		break;
131122866Smckusick 
131222866Smckusick 
131322866Smckusick 	case STGBSS:
131422866Smckusick 	case STGINIT:
131522866Smckusick 	case STGEXT:
131622866Smckusick 	case STGINTR:
131722866Smckusick 	case STGCOMMON:
131822866Smckusick 	case STGEQUIV:
131922866Smckusick 	case STGCONST:
132022866Smckusick 		if(offp)
132122866Smckusick 			{
132222866Smckusick 			putx(offp);
132322866Smckusick 			putmem(p, PCC_ICON, offset);
132422866Smckusick 			p2op(PCC_PLUS, type2 | PCCTM_PTR);
132522866Smckusick 			if(indir)
132622866Smckusick 				p2op(PCC_DEREF, type2);
132722866Smckusick 			}
132822866Smckusick 		else
132922866Smckusick 			putmem(p, (indir ? PCC_NAME : PCC_ICON), offset);
133022866Smckusick 
133122866Smckusick 		break;
133222866Smckusick 
133322866Smckusick 	case STGREG:
133422866Smckusick 		if(indir)
133522866Smckusick 			p2reg(p->memno, type2);
133622866Smckusick 		else
133722866Smckusick 			fatal("attempt to take address of a register");
133822866Smckusick 		break;
133922866Smckusick 
134022866Smckusick 	case STGPREG:
134122866Smckusick 		if(indir && !offp)
134222866Smckusick 			p2oreg(offset, p->memno, type2);
134322866Smckusick 		else
134422866Smckusick 			{
134522866Smckusick 			p2reg(p->memno, type2 | PCCTM_PTR);
134622866Smckusick 			goto based;
134722866Smckusick 			}
134822866Smckusick 		break;
134922866Smckusick 
135022866Smckusick 	default:
135122866Smckusick 		badstg("putaddr", p->vstg);
135222866Smckusick 	}
135322866Smckusick frexpr(p);
135422866Smckusick }
135522866Smckusick 
135622866Smckusick 
135722866Smckusick 
135822866Smckusick 
135922866Smckusick LOCAL putmem(p, class, offset)
136022866Smckusick expptr p;
136122866Smckusick int class;
136222866Smckusick ftnint offset;
136322866Smckusick {
136422866Smckusick int type2;
136522866Smckusick int funct;
136622866Smckusick char *name,  *memname();
136722866Smckusick 
136822866Smckusick funct = (p->headblock.vclass==CLPROC ? PCCTM_FTN<<2 : 0);
136922866Smckusick type2 = types2[p->headblock.vtype];
137022866Smckusick if(p->headblock.vclass == CLPROC)
137122866Smckusick 	type2 |= (PCCTM_FTN<<2);
137222866Smckusick name = memname(p->addrblock.vstg, p->addrblock.memno);
137322866Smckusick if(class == PCC_ICON)
137422866Smckusick 	{
137522866Smckusick 	p2triple(PCC_ICON, name[0]!='\0', type2|PCCTM_PTR);
137622866Smckusick 	p2word(offset);
137722866Smckusick 	if(name[0])
137822866Smckusick 		p2name(name);
137922866Smckusick 	}
138022866Smckusick else
138122866Smckusick 	{
138222866Smckusick 	p2triple(PCC_NAME, offset!=0, type2);
138322866Smckusick 	if(offset != 0)
138422866Smckusick 		p2word(offset);
138522866Smckusick 	p2name(name);
138622866Smckusick 	}
138722866Smckusick }
138822866Smckusick 
138922866Smckusick 
139022866Smckusick 
139122866Smckusick LOCAL Addrp putcall(p)
139222866Smckusick register Exprp p;
139322866Smckusick {
139422866Smckusick chainp arglist, charsp, cp;
139522866Smckusick int n, first;
139622866Smckusick Addrp t;
139722866Smckusick register expptr q;
139822866Smckusick Addrp fval, mkargtemp();
139922866Smckusick int type, type2, ctype, qtype, indir;
140022866Smckusick 
140122866Smckusick type2 = types2[type = p->vtype];
140222866Smckusick charsp = NULL;
140322866Smckusick indir =  (p->opcode == OPCCALL);
140422866Smckusick n = 0;
140522866Smckusick first = YES;
140622866Smckusick 
140722866Smckusick if(p->rightp)
140822866Smckusick 	{
140922866Smckusick 	arglist = p->rightp->listblock.listp;
141022866Smckusick 	free( (charptr) (p->rightp) );
141122866Smckusick 	}
141222866Smckusick else
141322866Smckusick 	arglist = NULL;
141422866Smckusick 
141522866Smckusick for(cp = arglist ; cp ; cp = cp->nextp)
141622866Smckusick 	{
141722866Smckusick 	q = (expptr) cp->datap;
141822866Smckusick 	if(indir)
141922866Smckusick 		++n;
142022866Smckusick 	else	{
142122866Smckusick 		q = (expptr) (cp->datap);
142222866Smckusick 		if( ISCONST(q) )
142322866Smckusick 			{
142422866Smckusick 			q = (expptr) putconst(q);
142522866Smckusick 			cp->datap = (tagptr) q;
142622866Smckusick 			}
142722866Smckusick 		if( ISCHAR(q) && q->headblock.vclass!=CLPROC )
142822866Smckusick 			{
142922866Smckusick 			charsp = hookup(charsp,
143022866Smckusick 					mkchain(cpexpr(q->headblock.vleng),
143122866Smckusick 						CHNULL));
143222866Smckusick 			n += 2;
143322866Smckusick 			}
143422866Smckusick 		else
143522866Smckusick 			n += 1;
143622866Smckusick 		}
143722866Smckusick 	}
143822866Smckusick 
143922866Smckusick if(type == TYCHAR)
144022866Smckusick 	{
144122866Smckusick 	if( ISICON(p->vleng) )
144222866Smckusick 		{
144322866Smckusick 		fval = mkargtemp(TYCHAR, p->vleng);
144422866Smckusick 		n += 2;
144522866Smckusick 		}
144622866Smckusick 	else	{
144722866Smckusick 		err("adjustable character function");
144822866Smckusick 		return;
144922866Smckusick 		}
145022866Smckusick 	}
145122866Smckusick else if( ISCOMPLEX(type) )
145222866Smckusick 	{
145322866Smckusick 	fval = mkargtemp(type, PNULL);
145422866Smckusick 	n += 1;
145522866Smckusick 	}
145622866Smckusick else
145722866Smckusick 	fval = NULL;
145822866Smckusick 
145922866Smckusick ctype = (fval ? PCCT_INT : type2);
146022866Smckusick putaddr(p->leftp, NO);
146122866Smckusick 
146222866Smckusick if(fval)
146322866Smckusick 	{
146422866Smckusick 	first = NO;
146522866Smckusick 	putaddr( cpexpr(fval), NO);
146622866Smckusick 	if(type==TYCHAR)
146722866Smckusick 		{
146822866Smckusick 		putx( mkconv(TYLENG,p->vleng) );
146922866Smckusick 		p2op(PCC_CM, type2);
147022866Smckusick 		}
147122866Smckusick 	}
147222866Smckusick 
147322866Smckusick for(cp = arglist ; cp ; cp = cp->nextp)
147422866Smckusick 	{
147522866Smckusick 	q = (expptr) (cp->datap);
147622866Smckusick 	if(q->tag==TADDR && (indir || q->addrblock.vstg!=STGREG) )
147722866Smckusick 		putaddr(q, indir && q->addrblock.vtype!=TYCHAR);
147822866Smckusick 	else if( ISCOMPLEX(q->headblock.vtype) )
147922866Smckusick 		putcxop(q);
148022866Smckusick 	else if (ISCHAR(q) )
148122866Smckusick 		putchop(q);
148222866Smckusick 	else if( ! ISERROR(q) )
148322866Smckusick 		{
148422866Smckusick 		if(indir)
148522866Smckusick 			putx(q);
148622866Smckusick 		else	{
148722866Smckusick 			t = mkargtemp(qtype = q->headblock.vtype,
148822866Smckusick 				q->headblock.vleng);
148922866Smckusick 			putassign( cpexpr(t), q );
149022866Smckusick 			putaddr(t, NO);
149122866Smckusick 			putcomma(1, qtype, YES);
149222866Smckusick 			}
149322866Smckusick 		}
149422866Smckusick 	if(first)
149522866Smckusick 		first = NO;
149622866Smckusick 	else
149722866Smckusick 		p2op(PCC_CM, type2);
149822866Smckusick 	}
149922866Smckusick 
150022866Smckusick if(arglist)
150122866Smckusick 	frchain(&arglist);
150222866Smckusick for(cp = charsp ; cp ; cp = cp->nextp)
150322866Smckusick 	{
150422866Smckusick 	putx( mkconv(TYLENG,cp->datap) );
150522866Smckusick 	p2op(PCC_CM, type2);
150622866Smckusick 	}
150722866Smckusick frchain(&charsp);
150822866Smckusick p2op(n>0 ? PCC_CALL : PCC_UCALL , ctype);
150922866Smckusick free( (charptr) p );
151022866Smckusick return(fval);
151122866Smckusick }
151222866Smckusick 
151322866Smckusick 
151422866Smckusick 
151522866Smckusick LOCAL putmnmx(p)
151622866Smckusick register expptr p;
151722866Smckusick {
151822866Smckusick int op, type;
151922866Smckusick int ncomma;
152022866Smckusick expptr qp;
152122866Smckusick chainp p0, p1;
152222866Smckusick Addrp sp, tp;
152322866Smckusick 
152422866Smckusick if(p->tag != TEXPR)
152522866Smckusick 	badtag("putmnmx", p->tag);
152622866Smckusick 
152722866Smckusick type = p->exprblock.vtype;
152822866Smckusick op = (p->exprblock.opcode==OPMIN ? OPLT : OPGT );
152922866Smckusick p0 = p->exprblock.leftp->listblock.listp;
153022866Smckusick free( (charptr) (p->exprblock.leftp) );
153122866Smckusick free( (charptr) p );
153222866Smckusick 
153322866Smckusick sp = mkaltemp(type, PNULL);
153422866Smckusick tp = mkaltemp(type, PNULL);
153522866Smckusick qp = mkexpr(OPCOLON, cpexpr(tp), cpexpr(sp));
153622866Smckusick qp = mkexpr(OPQUEST, mkexpr(op, cpexpr(tp),cpexpr(sp)), qp);
153722866Smckusick qp = fixexpr(qp);
153822866Smckusick 
153922866Smckusick ncomma = 1;
154022866Smckusick putassign( cpexpr(sp), p0->datap );
154122866Smckusick 
154222866Smckusick for(p1 = p0->nextp ; p1 ; p1 = p1->nextp)
154322866Smckusick 	{
154422866Smckusick 	++ncomma;
154522866Smckusick 	putassign( cpexpr(tp), p1->datap );
154622866Smckusick 	if(p1->nextp)
154722866Smckusick 		{
154822866Smckusick 		++ncomma;
154922866Smckusick 		putassign( cpexpr(sp), cpexpr(qp) );
155022866Smckusick 		}
155122866Smckusick 	else
155222866Smckusick 		putx(qp);
155322866Smckusick 	}
155422866Smckusick 
155522866Smckusick putcomma(ncomma, type, NO);
155622866Smckusick frexpr(sp);
155722866Smckusick frexpr(tp);
155822866Smckusick frchain( &p0 );
155922866Smckusick }
156022866Smckusick 
156122866Smckusick 
156222866Smckusick 
156322866Smckusick 
156422866Smckusick LOCAL putcomma(n, type, indir)
156522866Smckusick int n, type, indir;
156622866Smckusick {
156722866Smckusick type = types2[type];
156822866Smckusick if(indir)
156922866Smckusick 	type |= PCCTM_PTR;
157022866Smckusick while(--n >= 0)
157122866Smckusick 	p2op(PCC_COMOP, type);
157222866Smckusick }
157322866Smckusick 
157422866Smckusick 
157522866Smckusick 
157622866Smckusick 
157722866Smckusick ftnint simoffset(p0)
157822866Smckusick expptr *p0;
157922866Smckusick {
158022866Smckusick ftnint offset, prod;
158122866Smckusick register expptr p, lp, rp;
158222866Smckusick 
158322866Smckusick offset = 0;
158422866Smckusick p = *p0;
158522866Smckusick if(p == NULL)
158622866Smckusick 	return(0);
158722866Smckusick 
158822866Smckusick if( ! ISINT(p->headblock.vtype) )
158922866Smckusick 	return(0);
159022866Smckusick 
159122866Smckusick if(p->tag==TEXPR && p->exprblock.opcode==OPSTAR)
159222866Smckusick 	{
159322866Smckusick 	lp = p->exprblock.leftp;
159422866Smckusick 	rp = p->exprblock.rightp;
159522866Smckusick 	if(ISICON(rp) && lp->tag==TEXPR &&
159622866Smckusick 	   lp->exprblock.opcode==OPPLUS && ISICON(lp->exprblock.rightp))
159722866Smckusick 		{
159822866Smckusick 		p->exprblock.opcode = OPPLUS;
159922866Smckusick 		lp->exprblock.opcode = OPSTAR;
1600*33257Sbostic 		prod = rp->constblock.constant.ci *
1601*33257Sbostic 			lp->exprblock.rightp->constblock.constant.ci;
1602*33257Sbostic 		lp->exprblock.rightp->constblock.constant.ci = rp->constblock.constant.ci;
1603*33257Sbostic 		rp->constblock.constant.ci = prod;
160422866Smckusick 		}
160522866Smckusick 	}
160622866Smckusick 
160722866Smckusick if(p->tag==TEXPR && p->exprblock.opcode==OPPLUS &&
160822866Smckusick     ISICON(p->exprblock.rightp))
160922866Smckusick 	{
161022866Smckusick 	rp = p->exprblock.rightp;
161122866Smckusick 	lp = p->exprblock.leftp;
1612*33257Sbostic 	offset += rp->constblock.constant.ci;
161322866Smckusick 	frexpr(rp);
161422866Smckusick 	free( (charptr) p );
161522866Smckusick 	*p0 = lp;
161622866Smckusick 	}
161722866Smckusick 
161822866Smckusick if( ISCONST(p) )
161922866Smckusick 	{
1620*33257Sbostic 	offset += p->constblock.constant.ci;
162122866Smckusick 	frexpr(p);
162222866Smckusick 	*p0 = NULL;
162322866Smckusick 	}
162422866Smckusick 
162522866Smckusick return(offset);
162622866Smckusick }
162722866Smckusick 
162822866Smckusick 
162922866Smckusick 
163022866Smckusick 
163122866Smckusick 
163222866Smckusick p2op(op, type)
163322866Smckusick int op, type;
163422866Smckusick {
163522866Smckusick p2triple(op, 0, type);
163622866Smckusick }
163722866Smckusick 
163822866Smckusick p2icon(offset, type)
163922866Smckusick ftnint offset;
164022866Smckusick int type;
164122866Smckusick {
164222866Smckusick p2triple(PCC_ICON, 0, type);
164322866Smckusick p2word(offset);
164422866Smckusick }
164522866Smckusick 
164622866Smckusick 
164722866Smckusick 
164822866Smckusick 
164922866Smckusick p2oreg(offset, reg, type)
165022866Smckusick ftnint offset;
165122866Smckusick int reg, type;
165222866Smckusick {
165322866Smckusick p2triple(PCC_OREG, reg, type);
165422866Smckusick p2word(offset);
165522866Smckusick p2name("");
165622866Smckusick }
165722866Smckusick 
165822866Smckusick 
165922866Smckusick 
166022866Smckusick 
166122866Smckusick p2reg(reg, type)
166222866Smckusick int reg, type;
166322866Smckusick {
166422866Smckusick p2triple(PCC_REG, reg, type);
166522866Smckusick }
166622866Smckusick 
166722866Smckusick 
166822866Smckusick 
166922866Smckusick p2pi(s, i)
167022866Smckusick char *s;
167122866Smckusick int i;
167222866Smckusick {
167322866Smckusick char buff[100];
167422866Smckusick sprintf(buff, s, i);
167522866Smckusick p2pass(buff);
167622866Smckusick }
167722866Smckusick 
167822866Smckusick 
167922866Smckusick 
168022866Smckusick p2pij(s, i, j)
168122866Smckusick char *s;
168222866Smckusick int i, j;
168322866Smckusick {
168422866Smckusick char buff[100];
168522866Smckusick sprintf(buff, s, i, j);
168622866Smckusick p2pass(buff);
168722866Smckusick }
168822866Smckusick 
168922866Smckusick 
169022866Smckusick 
169122866Smckusick 
169222866Smckusick p2ps(s, t)
169322866Smckusick char *s, *t;
169422866Smckusick {
169522866Smckusick char buff[100];
169622866Smckusick sprintf(buff, s, t);
169722866Smckusick p2pass(buff);
169822866Smckusick }
169922866Smckusick 
170022866Smckusick 
170122866Smckusick 
170222866Smckusick 
170322866Smckusick p2pass(s)
170422866Smckusick char *s;
170522866Smckusick {
170622866Smckusick p2triple(PCCF_FTEXT, (strlen(s) + FOUR-1)/FOUR, 0);
170722866Smckusick p2str(s);
170822866Smckusick }
170922866Smckusick 
171022866Smckusick 
171122866Smckusick 
171222866Smckusick 
171322866Smckusick p2str(s)
171422866Smckusick register char *s;
171522866Smckusick {
171622866Smckusick union { long int word; char str[FOUR]; } u;
171722866Smckusick register int i;
171822866Smckusick 
171922866Smckusick i = 0;
172022866Smckusick u.word = 0;
172122866Smckusick while(*s)
172222866Smckusick 	{
172322866Smckusick 	u.str[i++] = *s++;
172422866Smckusick 	if(i == FOUR)
172522866Smckusick 		{
172622866Smckusick 		p2word(u.word);
172722866Smckusick 		u.word = 0;
172822866Smckusick 		i = 0;
172922866Smckusick 		}
173022866Smckusick 	}
173122866Smckusick if(i > 0)
173222866Smckusick 	p2word(u.word);
173322866Smckusick }
173422866Smckusick 
173522866Smckusick 
173622866Smckusick 
173722866Smckusick 
173822866Smckusick p2triple(op, var, type)
173922866Smckusick int op, var, type;
174022866Smckusick {
174122866Smckusick register long word;
174222866Smckusick word = PCCM_TRIPLE(op, var, type);
174322866Smckusick p2word(word);
174422866Smckusick }
174522866Smckusick 
174622866Smckusick 
174722866Smckusick 
174822866Smckusick 
174922866Smckusick 
175022866Smckusick p2name(s)
175122866Smckusick register char *s;
175222866Smckusick {
175322866Smckusick register int i;
175422866Smckusick 
175522866Smckusick #ifdef UCBPASS2
175622866Smckusick 	/* arbitrary length names, terminated by a null,
175722866Smckusick 	   padded to a full word */
175822866Smckusick 
175922866Smckusick #	define WL   sizeof(long int)
176022866Smckusick 	union { long int word; char str[WL]; } w;
176122866Smckusick 
176222866Smckusick 	w.word = 0;
176322866Smckusick 	i = 0;
176422866Smckusick 	while(w.str[i++] = *s++)
176522866Smckusick 		if(i == WL)
176622866Smckusick 			{
176722866Smckusick 			p2word(w.word);
176822866Smckusick 			w.word = 0;
176922866Smckusick 			i = 0;
177022866Smckusick 			}
177122866Smckusick 	if(i > 0)
177222866Smckusick 		p2word(w.word);
177322866Smckusick #else
177422866Smckusick 	/* standard intermediate, names are 8 characters long */
177522866Smckusick 
177622866Smckusick 	union  { long int word[2];  char str[8]; } u;
177722866Smckusick 
177822866Smckusick 	u.word[0] = u.word[1] = 0;
177922866Smckusick 	for(i = 0 ; i<8 && *s ; ++i)
178022866Smckusick 		u.str[i] = *s++;
178122866Smckusick 	p2word(u.word[0]);
178222866Smckusick 	p2word(u.word[1]);
178322866Smckusick 
178422866Smckusick #endif
178522866Smckusick 
178622866Smckusick }
178722866Smckusick 
178822866Smckusick 
178922866Smckusick 
179022866Smckusick 
179122866Smckusick p2word(w)
179222866Smckusick long int w;
179322866Smckusick {
179422866Smckusick *p2bufp++ = w;
179522866Smckusick if(p2bufp >= p2bufend)
179622866Smckusick 	p2flush();
179722866Smckusick }
179822866Smckusick 
179922866Smckusick 
180022866Smckusick 
180122866Smckusick p2flush()
180222866Smckusick {
180322866Smckusick if(p2bufp > p2buff)
180422866Smckusick 	write(fileno(textfile), p2buff, (p2bufp-p2buff)*sizeof(long int));
180522866Smckusick p2bufp = p2buff;
180622866Smckusick }
180722866Smckusick 
180822866Smckusick 
180922866Smckusick 
181022866Smckusick LOCAL
181122866Smckusick p2ldisp(offset, vname, type)
181222866Smckusick ftnint offset;
181322866Smckusick char *vname;
181422866Smckusick int type;
181522866Smckusick {
181622866Smckusick   char buff[100];
181722866Smckusick 
181822866Smckusick   sprintf(buff, "%s-v.%d", vname, bsslabel);
181922866Smckusick   p2triple(PCC_OREG, 11, type);
182022866Smckusick   p2word(offset);
182122866Smckusick   p2name(buff);
182222866Smckusick }
182322866Smckusick 
182422866Smckusick 
182522866Smckusick 
182622866Smckusick p2ndisp(vname)
182722866Smckusick char *vname;
182822866Smckusick {
182922866Smckusick   char buff[100];
183022866Smckusick 
183122866Smckusick   sprintf(buff, "%s-v.%d", vname, bsslabel);
183222866Smckusick   p2name(buff);
183322866Smckusick }
1834