Add tests, fixes for tests, reinstate and type-convert stuff marked "bitrot"
[ccom.git] / c10.c
1 /*
2  *              C compiler, part 2
3  * 
4  * (long)btodb(l) produced 'no code table error for op: >>(17) type: 6'
5  * allow both long and ulong at line ~341.  1996/6/19
6 */
7
8 #if     !defined(lint) && defined(DOSCCS)
9 static  char    sccsid[] = "@(#)c10.c   2.1 (2.11BSD GTE) 10/4/94";
10 #endif
11
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include "c1.h"
15
16 #ifdef  DEBUG
17 #define dbprint(op)     fprintf(temp_fp[temp_fi], "     / %s", opntab[op])
18 #else
19 #define dbprint(op)     /* */
20 #endif
21
22 char    maprel[] = {    EQUAL, NEQUAL, GREATEQ, GREAT, LESSEQ,
23                         LESS, GREATQP, GREATP, LESSEQP, LESSP
24 };
25
26 char    notrel[] = {    NEQUAL, EQUAL, GREAT, GREATEQ, LESS,
27                         LESSEQ, GREATP, GREATQP, LESSP, LESSEQP
28 };
29
30 struct cnode czero = { { CON, INT, (int *)NULL, (union str *)NULL }, 0};
31 struct cnode cone  = { { CON, INT, (int *)NULL, (union str *)NULL }, 1};
32
33 struct locnnode sfuncr = { { { NAME, STRUCT, (int *)NULL, (union str *)NULL }, (struct nmlist *)NULL, STATIC/*nn_class*/, 0/*nn_regno*/, 0/*nn_offset*/ }, 0/*locnn_nloc*/ }; 
34 struct  table   *cregtab;
35
36 int     nreg    = 3;
37 int     isn1    = 10000;
38
39 #if 0
40 int main(argc, argv) int argc; char *argv[]; {
41         char    buf1[BUFSIZ],
42                 buf2[BUFSIZ];
43
44         if (argc<4) {
45                 error1("Arg count");
46                 exit(1);
47         }
48         if (freopen(argv[1], "r", stdin)==NULL) {
49                 error1("Missing temp file");
50                 exit(1);
51         }
52         setbuf(stdin,buf1);     /* sbrk problems */
53         if ((freopen(argv[3], "w", stdout)) == NULL) {
54                 error1("Can't create %s", argv[3]);
55                 exit(1);
56         }
57         setbuf(stdout,buf2);    /* sbrk problems */
58         funcbase = curbase = coremax = sbrk(0);
59         getree();
60         /*
61          * If any floating-point instructions
62          * were used, generate a reference that
63          * pulls in the floating-point part of printf.
64          */
65         if (nfloat)
66                 fprintf(temp_fp[temp_fi], ".globl       fltused\n");
67         /*
68          * tack on the string file.
69          */
70         fprintf(temp_fp[temp_fi], ".globl\n.data\n");
71         if (*argv[2] != '-') {
72                 if (freopen(argv[2], "r", stdin)==NULL) {
73                         error1("Missing temp file");
74                         exit(1);
75                 }
76                 setbuf(stdin,buf1);     /* sbrk problems */
77                 getree();
78         }
79         if (totspace >= (_UNSIGNED_INT)56000)
80                 werror1("possibly too much data");
81         exit(nerror!=0);
82 }
83 #endif
84
85 /*
86  * Given a tree, a code table, and a
87  * count of available registers, find the code table
88  * for the appropriate operator such that the operands
89  * are of the right type and the number of registers
90  * required is not too large.
91  * Return a ptr to the table entry or 0 if none found.
92  */
93 struct optab *match(tree, table, nrleft, nocvt) struct node *tree; struct table *table; int nrleft; int nocvt; {
94 #define NOCVL   1
95 #define NOCVR   2
96         int op, d1, d2, dope;
97         struct node *p2;
98         register struct node *p1;
99         register struct optab *opt;
100
101         if (tree==NULL)
102                 return(NULL);
103         if (table==lsptab)
104                 table = sptab;
105         if ((op = tree->n_op)==0)
106                 return(0);
107         dope = opdope1[op];
108         if ((dope&LEAF) == 0)
109                 p1 = ((struct tnode *)tree)->tn_tr1;
110         else
111                 p1 = tree;
112         d1 = dcalc(p1, nrleft);
113         if ((dope&BINARY)!=0) {
114 #define ttree ((struct tnode *)tree)
115                 p2 = ttree->tn_tr2;
116                 /*
117                  * If a subttree starts off with a conversion operator,
118                  * try for a match with the conversion eliminated.
119                  * E.g. int = double can be done without generating
120                  * the converted int in a register by
121                  * movf double,fr0; movfi fr0,int .
122                  */
123                 if (opdope1[p2->n_op]&CNVRT && (nocvt&NOCVR)==0
124                          && (opdope1[((struct tnode *)p2)->tn_tr1->n_op]&CNVRT)==0) {
125                         ttree->tn_tr2 = ((struct tnode *)p2)->tn_tr1;
126                         if (opt = match((struct node *)ttree, table, nrleft, NOCVL))
127                                 return(opt);
128                         ttree->tn_tr2 = p2;
129                 } else if (opdope1[p1->n_op]&CNVRT && (nocvt&NOCVL)==0
130                  && (opdope1[((struct tnode *)p1)->tn_tr1->n_op]&CNVRT)==0) {
131                         ttree->tn_tr1 = ((struct tnode *)p1)->tn_tr1;
132                         if (opt = match((struct node *)ttree, table, nrleft, NOCVR))
133                                 return(opt);
134                         ttree->tn_tr1 = p1;
135                 }
136                 d2 = dcalc(p2, nrleft);
137 #undef ttree
138         }
139         for (; table->tabop!=op; table++)
140                 if (table->tabop==0)
141                         return(0);
142         for (opt = table->tabp; opt->tabdeg1!=0; opt++) {
143                 if (d1 > (opt->tabdeg1&077)
144                  || (opt->tabdeg1 >= 0100 && (p1->n_op != STAR)))
145                         continue;
146                 if (notcompat(p1, opt->tabtyp1, opt->tabdeg1, op))
147                         continue;
148                 if ((opdope1[op]&BINARY)!=0 && p2!=0) {
149                         if (d2 > (opt->tabdeg2&077)
150                          || (opt->tabdeg2 >= 0100) && (p2->n_op != STAR) )
151                                 continue;
152                         if (notcompat(p2,opt->tabtyp2, opt->tabdeg2, 0))
153                                 continue;
154                         if ((opt->tabdeg2&077)==20 && xdcalc(p2,nrleft)>20)
155                                 continue;
156                 }
157                 return(opt);
158         }
159         return(0);
160 }
161
162 /*
163  * Given a tree, a code table, and a register,
164  * produce code to evaluate the tree with the appropriate table.
165  * Registers reg and upcan be used.
166  * If there is a value, it is desired that it appear in reg.
167  * The routine returns the register in which the value actually appears.
168  * This routine must work or there is an error.
169  * If the table called for is cctab, sptab, or efftab,
170  * and tree can't be done using the called-for table,
171  * another try is made.
172  * If the tree can't be compiled using cctab, regtab is
173  * used and a "tst" instruction is produced.
174  * If the tree can't be compiled using sptab,
175  * regtab is used and the register is pushed on the stack.
176  * If the tree can't be compiled using efftab,
177  * just use regtab.
178  * Regtab must succeed or an "op not found" error results.
179  *
180  * A number of special cases are recognized, and
181  * there is an interaction with the optimizer routines.
182  */
183 int rcexpr1(atree, atable, reg) struct node *atree; struct table *atable; int reg; {
184         register int r;
185         int modf, nargs, recurf;
186         register struct node *tree;
187         register struct table *table;
188
189  /*fprintf(stderr, "rcexpr1(0x%08x, 0x%08x, 0x%08x)\n", atree, atable, reg);*/
190         table = atable;
191         recurf = 0;
192         if (reg<0) {
193                 recurf++;
194                 reg = ~reg;
195                 if (reg>=020) {
196                         reg -= 020;
197                         recurf++;
198                 }
199         }
200 again:
201         if((tree=atree)==0)
202                 return(0);
203         if (tree->n_type==VOID) {
204                 if (table!=efftab)
205                         error1("Illegal use of void");
206                 tree->n_type = INT;
207         }
208         if (opdope1[tree->n_op]&RELAT && ((struct tnode *)tree)->tn_tr2->n_op==CON
209             && ((struct cnode *)((struct tnode *)tree)->tn_tr2)->cn_value==0
210             && table==cctab)
211                 tree = atree = ((struct tnode *)tree)->tn_tr1;
212         /*
213          * fieldselect(...) : in efftab mode,
214          * ignore the select, otherwise
215          * do the shift and mask.
216          */
217         if (tree->n_op == FSELT) {
218                 if (table==efftab)
219                         atree = tree = ((struct tnode *)tree)->tn_tr1;
220                 else {
221                         tree->n_op = FSEL;
222                         atree = tree = optim(tree);
223                 }
224         }
225         switch (tree->n_op)  {
226
227         /*
228          * Structure assignments
229          */
230  /*     case STRASG:*/
231  case ASSIGN:
232 #define ttree ((struct tnode *)tree)
233   if (ttree->tn_type != STRUCT)
234    break;
235                 strasg(ttree);
236                 return(0);
237 #undef ttree
238
239         /*
240          * An initializing expression
241          */
242         case INIT:
243                 tree = optim(tree);
244 #define ttree ((struct tnode *)tree)
245                 doinit(ttree->tn_type, ttree->tn_tr1);
246                 return(0);
247 #undef ttree
248
249         /*
250          * Put the value of an expression in r0,
251          * for a switch or a return
252          */
253         case RFORCE:
254 #define ttree ((struct tnode *)tree)
255  if (ttree->tn_type == STRUCT) {
256   strasg(ttree);
257   return(0);
258  }
259 #undef ttree
260                 tree = ((struct tnode *)tree)->tn_tr1;
261                 if((r=rcexpr1(tree, regtab, reg)) != 0)
262                         movreg(r, 0, tree);
263                 return(0);
264
265         /*
266          * sequential execution
267          */
268         case SEQNC:
269 #define ttree ((struct tnode *)tree)
270                 r = nstack;
271                 rcexpr1(ttree->tn_tr1, efftab, reg);
272                 nstack = r;
273 #undef ttree
274                 atree = tree = ((struct tnode *)tree)->tn_tr2;
275                 goto again;
276
277         /*
278          * In the generated &~ operator,
279          * fiddle things so a PDP-11 "bit"
280          * instruction will be produced when cctab is used.
281          */
282         case ANDN:
283 #define ttree ((struct tnode *)tree)
284                 if (table==cctab) {
285                         ttree->tn_op = TAND;
286                         ttree->tn_tr2 = optim((struct node *)tnode(COMPL, ttree->tn_type, ttree->tn_tr2, (struct node *)NULL));
287                 }
288                 break;
289 #undef ttree
290
291         /*
292          * Handle a subroutine call. It has to be done
293          * here because if cexpr got called twice, the
294          * arguments might be compiled twice.
295          * There is also some fiddling so the
296          * first argument, in favorable circumstances,
297          * goes to (sp) instead of -(sp), reducing
298          * the amount of stack-popping.
299          */
300         case CALL:
301                 r = 0;
302                 nargs = 0;
303                 modf = 0;
304 #ifdef notdef
305                 /*
306                  * The following code would catch instances of foo(...) where
307                  * "foo" was anything other than a simple name.  In particular
308                  * f(...), (fp(...))(...) and (ffp(...))(...) where "f" is a
309                  * pointer to a function, "fp" is a function returning a
310                  * pointer to a function and "ffp" is a pointer to a function
311                  * returning a pointer to a function.  The catch would among
312                  * other things cause the (sp)/-(sp) stack optimization to
313                  * stop working.  The compiler has been tested in all these
314                  * different cases with the catch commented out and all the
315                  * code generated was correct.  So what was it here for?
316                  * If a strange error crops up, uncommenting the catch might
317                  * be tried ...
318                  */
319                 if (tree->tn_tr1->tn_op!=NAME || tree->tn_tr1->nn_class!=EXTERN) {
320                         nargs++;
321                         nstack++;
322                 }
323 #endif
324                 tree = ((struct tnode *)tree)->tn_tr2;
325                 if(tree->n_op) {
326                         while (tree->n_op==COMMA) {
327                                 r += comarg(((struct tnode *)tree)->tn_tr2, &modf);
328                                 tree = ((struct tnode *)tree)->tn_tr1;
329                                 nargs++;
330                         }
331                         r += comarg(tree, &modf);
332                         nargs++;
333                 }
334                 tree = atree;
335 #define ttree ((struct tnode *)tree)
336                 ttree->tn_op = CALL2;
337                 if (modf && ttree->tn_tr1->n_op==NAME
338                    && ((struct nnode *)ttree->tn_tr1)->nn_class==EXTERN)
339                         ttree->tn_op = CALL1;
340                 if (cexpr((struct node *)ttree, regtab, reg)<0)
341                         error1("compiler botch: call");
342                 popstk(r);
343                 nstack -= nargs;
344                 if (table==efftab || table==regtab)
345                         return(0);
346                 r = 0;
347                 goto fixup;
348 #undef ttree
349
350         /*
351          * Longs need special treatment.
352          */
353         case ASULSH:    /* 18 */
354         case ULSH:      /* 17 */
355 #define ttree ((struct tnode *)tree)
356                 if (ttree->tn_type != LONG && ttree->tn_type != UNLONG)
357                         break;
358                 if (ttree->tn_tr2->n_op==ITOL)
359                         ttree->tn_tr2 = ((struct tnode *)ttree->tn_tr2)->tn_tr1;
360                 else
361                         ttree->tn_tr2 = optim((struct node *)tnode(LTOI,INT,ttree->tn_tr2,(struct node *)NULL));
362                 if (ttree->tn_op==ASULSH)
363                         {
364                         ttree->tn_op = UASLSHL;
365                         ttree->tn_tr1 = (struct node *)tnode(AMPER, LONG+PTR, ttree->tn_tr1, (struct node *)NULL);
366                         }
367                 else
368                         ttree->tn_op = ULLSHIFT;
369                 break;
370 #undef ttree
371
372         case ASLSH:
373         case LSHIFT:
374 #define ttree ((struct tnode *)tree)
375                 if (ttree->tn_type==LONG || ttree->tn_type==UNLONG) {
376                         if (ttree->tn_tr2->n_op==ITOL)
377                                 ttree->tn_tr2 = ((struct tnode *)ttree->tn_tr2)->tn_tr1;
378                         else
379                                 ttree->tn_tr2 = optim((struct node *)tnode(LTOI,INT,ttree->tn_tr2,(struct node *)NULL));
380                         if (ttree->tn_op==ASLSH)
381                                 ttree->tn_op = ASLSHL;
382                         else
383                                 ttree->tn_op = LLSHIFT;
384                 }
385                 break;
386 #undef ttree
387
388         /*
389          * Try to change * to shift.
390          */
391         case TIMES:
392         case ASTIMES:
393                 tree = (struct node *)pow2((struct tnode *)tree);
394         }
395         /*
396          * Try to find postfix ++ and -- operators that can be
397          * pulled out and done after the rest of the expression
398          */
399  /* delay() has to be able to assume input pointer is a tnode */
400  if (tree != atree) abort();
401         if (table!=cctab && table!=cregtab && recurf<2
402          && (opdope1[tree->n_op]&LEAF)==0) {
403                 if (r=delay(&atree, table, reg)) {
404                         tree = atree;
405                         table = efftab;
406                         reg = r-1;
407                 }
408         }
409         /*
410          * Basically, try to reorder the computation
411          * so  reg = x+y  is done as  reg = x; reg += y
412          */
413         if (recurf==0 && reorder(&atree, table, reg)) {
414                 if (table==cctab && atree->n_op==NAME)
415                         return(reg);
416         }
417         tree = atree;
418         if (table==efftab && tree->n_op==NAME)
419                 return(reg);
420         if ((r=cexpr(tree, table, reg))>=0) {
421                 if (table==cregtab && (tree->n_op==INCAFT
422                     || tree->n_op==DECAFT || tree->n_op==TIMES))
423                         goto fixup;
424                 return(r);
425         }
426         if (table!=regtab && (table!=cctab||(opdope1[tree->n_op]&RELAT)==0)) {
427                 if((r=cexpr(tree, regtab, reg))>=0) {
428         fixup:
429                         modf = isfloat(tree);
430                         dbprint(tree->n_op);
431                         if (table==sptab || table==lsptab) {
432                                 if (tree->n_type==LONG || tree->n_type==UNLONG){
433                                         fprintf(temp_fp[temp_fi], "mov\tr%d,-(sp)\n",r+1);
434                                         nstack++;
435                                 }
436                                 fprintf(temp_fp[temp_fi], "mov%s        r%d,%s(sp)\n", modf=='f'?"f":"", r,
437                                         table==sptab? "-":"");
438                                 nstack++;
439                         }
440                         if (table==cctab || table==cregtab)
441                                 fprintf(temp_fp[temp_fi], "tst%s        r%d\n", modf=='f'?"f":"", r);
442                         return(r);
443                 }
444         }
445         /*
446          * Special grace for unsigned chars as right operands
447          */
448         if (opdope1[tree->n_op]&BINARY && ((struct tnode *)tree)->tn_tr2->n_type==UNCHAR) {
449 #define ttree ((struct tnode *)tree)
450                 ttree->tn_tr2 = (struct node *)tnode(LOAD, UNSIGN, ttree->tn_tr2, (struct node *)NULL);
451                 return(rcexpr1((struct node *)ttree, table, reg));
452 #undef ttree
453         }
454         /*
455          * There's a last chance for this operator
456          */
457         if (tree->n_op==LTOI) {
458 #define ttree ((struct tnode *)tree)
459                 r = rcexpr1(ttree->tn_tr1, regtab, reg);
460                 if (r >= 0) {
461                         r++;
462                         goto fixup;
463                 }
464 #undef ttree
465         }
466
467         r = tree->n_op;
468         if (tree->n_type == STRUCT)
469                 error1("Illegal operation on structure");
470         else if (r > 0 && r < UASLSHL && opntab[r])
471                 error1("No code table for op: %s(%d) type: %d", opntab[r], r,
472                         tree->n_type);
473         else
474                 error1("No code table for op %d", r);
475         return(reg);
476 }
477
478 /*
479  * Try to compile the tree with the code table using
480  * registers areg and up.  If successful,
481  * return the register where the value actually ended up.
482  * If unsuccessful, return -1.
483  *
484  * Most of the work is the macro-expansion of the
485  * code table.
486  */
487 int cexpr(tree, table, areg) register struct node *tree; struct table *table; int areg; {
488         int c, r;
489         register struct node *p, *p1;
490         struct table *ctable;
491         struct node *p2;
492         char *string;
493         int reg, reg1, rreg, flag, opd;
494         struct optab *opt;
495
496         reg = areg;
497         c = tree->n_op;
498         opd = opdope1[c];
499         /*
500          * When the value of a relational or a logical expression is
501          * desired, more work must be done.
502          */
503         if ((opd&RELAT||c==LOGAND||c==LOGOR||c==EXCLA) && table!=cctab) {
504                 cbranch1(tree, c=isn1++, 1, reg);
505                 rcexpr1((struct node *)&czero, table, reg);
506                 branch1(isn1, 0, 0);
507                 label1(c);
508                 rcexpr1((struct node *)&cone, table, reg);
509                 label1(isn1++);
510                 return(reg);
511         }
512         if(c==QUEST) {
513 #define ttree ((struct tnode *)tree)
514                 if (table==cctab)
515                         return(-1);
516                 cbranch1(ttree->tn_tr1, c=isn1++, 0, reg);
517                 flag = nstack;
518                 rreg = rcexpr1(((struct tnode *)ttree->tn_tr2)->tn_tr1, table, reg);
519                 nstack = flag;
520                 branch1(r=isn1++, 0, 0);
521                 label1(c);
522                 reg = rcexpr1(((struct tnode *)ttree->tn_tr2)->tn_tr2, table, rreg);
523                 if (rreg!=reg)
524                         movreg(reg, rreg, ttree->tn_tr2);
525                 label1(r);
526                 return(rreg);
527 #undef ttree
528         }
529         reg = oddreg(tree, reg);
530         reg1 = reg+1;
531         /*
532          * long values take 2 registers.
533          */
534         if ((tree->n_type==LONG||tree->n_type==UNLONG||opd&RELAT&&(((struct tnode *)tree)->tn_tr1->n_type==LONG||((struct tnode *)tree)->tn_tr1->n_type==UNLONG))
535            && tree->n_op!=ITOL)
536                 reg1++;
537         /*
538          * Leaves of the expression tree
539          */
540         if ((r = chkleaf(tree, table, reg)) >= 0)
541                 return(r);
542  /* if chkleaf returns -1 then tree is a struct tnode */
543 #define ttree ((struct tnode *)tree)
544         /*
545          * x + (-1) is better done as x-1.
546          */
547         if (ttree->tn_op==PLUS||ttree->tn_op==ASPLUS) {
548                 if ((p1=ttree->tn_tr2)->n_op==CON && ((struct cnode *)p1)->cn_value==-1) {
549 #define cp1 ((struct cnode *)p1)
550                         cp1->cn_value = -cp1->cn_value;
551                         ttree->tn_op += (MINUS-PLUS);
552 #undef cp1
553                 }
554         }
555         /*
556          * Because of a peculiarity of the PDP11 table
557          * char = *intreg++ and *--intreg cannot go through.
558          */
559         if (ttree->tn_tr2 && (ttree->tn_tr2->n_op==AUTOI||ttree->tn_tr2->n_op==AUTOD)
560          && (ttree->tn_tr1->n_type==CHAR || ttree->tn_tr1->n_type==UNCHAR)
561          && ttree->tn_tr2->n_type!=CHAR && ttree->tn_tr2->n_type!=UNCHAR)
562                 ttree->tn_tr2 = (struct node *)tnode(LOAD, ttree->tn_tr2->n_type, ttree->tn_tr2, (struct node *)NULL);
563         /*
564          * Another peculiarity of the PDP11 table manifested itself when
565          * amplifying the move3: table.  The same case which optimizes
566          * u_char to char moves is used to move a u_char to a register. This
567          * is wrong, leading to sign extension.  Rather than lose the ability
568          * to generate better code when moving a u_char to a char, a check 
569          * is made here to prevent sign extension.
570          *
571          * If the opcode is assign, the destination is a register and the
572          * source is u_char then do a conversion.
573          *
574          * u_char handling in the compiler is a bit awkward, it would be nice
575          * if %aub in the tables had a more unique meaning.
576         */
577         if (ttree->tn_tr2 && ttree->tn_tr1->n_op == NAME
578          && ((struct nnode *)ttree->tn_tr1)->nn_class == REG && ttree->tn_op == ASSIGN
579          && ttree->tn_tr2->n_type == UNCHAR)
580                 ttree->tn_tr2 = (struct node *)tnode(LOAD, UNSIGN, ttree->tn_tr2, (struct node *)NULL);
581         if (table==cregtab)
582                 table = regtab;
583         /*
584          * The following peculiar code depends on the fact that
585          * if you just want the codition codes set, efftab
586          * will generate the right code unless the operator is
587          * a shift or
588          * postfix ++ or --. Unravelled, if the table is
589          * cctab and the operator is not special, try first
590          * for efftab;  if the table isn't, if the operator is,
591          * or the first match fails, try to match
592          * with the table actually asked for.
593          */
594         /*
595          * Account for longs and oddregs; below is really
596          * r = nreg - reg - (reg-areg) - (reg1-reg-1);
597          */
598         r = nreg - reg + areg - reg1 + 1;
599         if (table!=cctab || c==INCAFT || c==DECAFT || ttree->tn_type==LONG || ttree->tn_type==UNLONG
600 /*       || c==ASRSH || c==ASLSH || c==ASULSH || ttree->tn_tr1->tn_type==UNCHAR */
601          || c==ASRSH || c==ASLSH || c==ASULSH
602          || (opt = match((struct node *)ttree, efftab, r, 0)) == 0)
603                 if ((opt=match((struct node *)ttree, table, r, 0))==0)
604                         return(-1);
605         string = opt->tabstring;
606         p1 = ttree->tn_tr1;
607         if (p1->n_op==FCON && ((struct fnode *)p1)->fn_value>0) {
608 #define fp1 ((struct fnode *)p1)
609 #ifdef pdfp11
610 /* nonportable */
611                 fprintf(temp_fp[temp_fi], ".data\nL%d:%o;%o;%o;%o\n.text\n", fp1->fn_value,
612                         ((_UNSIGNED_INT *)&(fp1->fn_fvalue))[0],
613                         ((_UNSIGNED_INT *)&(fp1->fn_fvalue))[1],
614                         ((_UNSIGNED_INT *)&(fp1->fn_fvalue))[2],
615                         ((_UNSIGNED_INT *)&(fp1->fn_fvalue))[3] );
616 #else
617                 fprintf(temp_fp[temp_fi], ".data\nL%d:%o;%o;%o;%o\n.text\n", fp1->fn_value,
618                         (int)(fp1->fn_fvalue.h >> 16) & 0xffff,
619                         (int)fp1->fn_fvalue.h & 0xffff,
620                         (int)(fp1->fn_fvalue.l >> 16) & 0xffff,
621                         (int)fp1->fn_fvalue.l & 0xffff );
622 #endif
623                 fp1->fn_value = -fp1->fn_value; /* says flushed out */
624 #undef fp1
625         }
626         p2 = 0;
627         if (opdope1[ttree->tn_op]&BINARY) {
628                 p2 = ttree->tn_tr2;
629                 if (p2->n_op==FCON && ((struct fnode *)p2)->fn_value>0) {
630 #define fp2 ((struct fnode *)p2)
631 #ifdef pdp11
632 /* nonportable */
633                         fprintf(temp_fp[temp_fi], ".data\nL%d:%o;%o;%o;%o\n.text\n", fp2->fn_value,
634                                 ((_UNSIGNED_INT *)&(fp2->fn_fvalue))[0],
635                                 ((_UNSIGNED_INT *)&(fp2->fn_fvalue))[1],
636                                 ((_UNSIGNED_INT *)&(fp2->fn_fvalue))[2],
637                                 ((_UNSIGNED_INT *)&(fp2->fn_fvalue))[3] );
638 #else
639                         fprintf(temp_fp[temp_fi], ".data\nL%d:%o;%o;%o;%o\n.text\n", fp2->fn_value,
640                                 (int)(fp2->fn_fvalue.h >> 16) & 0xffff,
641                                 (int)fp2->fn_fvalue.h & 0xffff,
642                                 (int)(fp2->fn_fvalue.l >> 16) & 0xffff,
643                                 (int)fp2->fn_fvalue.l & 0xffff );
644 #endif
645                         fp2->fn_value = -fp2->fn_value; /* says flushed out */
646 #undef fp2
647                 }
648         }
649 loop:
650         /*
651          * The 0200 bit asks for a tab.
652          */
653         if ((c = *string++) & 0200) {
654                 c &= 0177;
655                 fputc('\t', temp_fp[temp_fi]) /*putchar('\t')*/;
656         }
657         switch (c) {
658
659         case '\n':
660                 dbprint(ttree->tn_op);
661                 break;
662
663         case '\0':
664                 if (!isfloat((struct node *)ttree))
665                         if (ttree->tn_op==DIVIDE||ttree->tn_op==ASDIV)
666                                 reg--;
667                 if (table==regtab && (opdope1[ttree->tn_op]&ASSGOP)) {
668                         if (ttree->tn_tr1->n_type==CHAR)
669                                 fprintf(temp_fp[temp_fi], "movb r%d,r%d\n", reg, reg);
670                 }
671                 return(reg);
672
673         /* A1 */
674         case 'A':
675                 p = p1;
676                 goto adr;
677
678         /* A2 */
679         case 'B':
680                 p = p2;
681                 goto adr;
682
683         adr:
684                 c = 0;
685                 while (*string=='\'') {
686                         c++;
687                         string++;
688                 }
689                 if (*string=='+') {
690                         c = 100;
691                         string++;
692                 }
693                 pname(p, c);
694                 goto loop;
695
696         /* I */
697         case 'M':
698                 if ((c = *string)=='\'')
699                         string++;
700                 else
701                         c = 0;
702                 prins(ttree->tn_op, c, instab, 0);
703                 goto loop;
704
705         /* B1 */
706         case 'C':
707                 if ((opd&LEAF) != 0)
708                         p = (struct node *)ttree;
709                 else
710                         p = p1;
711                 goto pbyte;
712
713         /* BF */
714         case 'P':
715                 p = (struct node *)ttree;
716                 goto pb1;
717
718         /* B2 */
719         case 'D':
720                 p = p2;
721         pbyte:
722                 if (p->n_type==CHAR || p->n_type==UNCHAR)
723                         fputc('b', temp_fp[temp_fi]);
724         pb1:
725                 if (isfloat(p))
726                         fputc('f', temp_fp[temp_fi]);
727                 goto loop;
728
729         /* BE */
730         case 'L':
731                 if (p1->n_type==CHAR || p2->n_type==CHAR
732                  || p1->n_type==UNCHAR || p2->n_type==UNCHAR)
733                         fputc('b', temp_fp[temp_fi]);
734                 p = (struct node *)ttree;
735                 goto pb1;
736
737         /* F */
738         case 'G':
739                 p = p1;
740                 flag = 01;
741                 goto subtre;
742
743         /* S */
744         case 'K':
745                 p = p2;
746                 flag = 02;
747                 goto subtre;
748
749         /* H */
750         case 'H':
751                 p = (struct node *)ttree;
752                 flag = 04;
753
754         subtre:
755                 ctable = regtab;
756                 if (flag&04)
757                         ctable = cregtab;
758                 c = *string++ - 'A';
759                 if (*string=='!') {
760                         string++;
761                         c |= 020;       /* force right register */
762                 }
763                 if (*string=='?') {
764                         string++;
765                         c |= 040;       /* force condition codes */
766                 }
767                 if ((c&02)!=0)
768                         ctable = sptab;
769                 if ((c&04)!=0)
770                         ctable = cctab;
771                 if ((flag&01) && ctable==regtab && (c&01)==0
772                   && ((c&040)||ttree->tn_op==DIVIDE||ttree->tn_op==MOD
773                    || ttree->tn_op==ASDIV||ttree->tn_op==ASMOD||ttree->tn_op==ITOL))
774                         ctable = cregtab;
775                 if ((c&01)!=0) {
776  /* previous code was accessing tn_tr1 without a type check */
777  if (opdope1[p->n_op] & LEAF) abort();
778                         p = ((struct tnode *)p)->tn_tr1;
779                         if(collcon(p) && ctable!=sptab) {
780                                 if (p->n_op==STAR)
781                                         p = ((struct tnode *)p)->tn_tr1;
782                                 p = ((struct tnode *)p)->tn_tr1;
783                         }
784                 }
785                 if (table==lsptab && ctable==sptab)
786                         ctable = lsptab;
787                 if (c&010)
788                         r = reg1;
789                 else
790                         if (opdope1[p->n_op]&LEAF || ((struct tnode *)p)->tn_degree < 2)
791                                 r = reg;
792                         else
793                                 r = areg;
794                 rreg = rcexpr1(p, ctable, r);
795                 if (ctable!=regtab && ctable!=cregtab)
796                         goto loop;
797                 if (c&010) {
798                         if (c&020 && rreg!=reg1)
799                                 movreg(rreg, reg1, p);
800                         else
801                                 reg1 = rreg;
802                 } else if (rreg!=reg)
803                         if ((c&020)==0 && oddreg((struct node *)ttree, 0)==0 && ttree->tn_type!=LONG
804                         && ttree->tn_type!=UNLONG
805                         && (flag&04
806                           || flag&01&&xdcalc(p2,nreg-rreg-1)<=(opt->tabdeg2&077)
807                           || flag&02&&xdcalc(p1,nreg-rreg-1)<=(opt->tabdeg1&077))) {
808                                 reg = rreg;
809                                 reg1 = rreg+1;
810                         } else
811                                 movreg(rreg, reg, p);
812                 goto loop;
813
814         /* R */
815         case 'I':
816                 r = reg;
817                 if (*string=='-') {
818                         string++;
819                         r--;
820                 }
821                 goto preg;
822
823         /* R1 */
824         case 'J':
825                 r = reg1;
826         preg:
827                 if (*string=='+') {
828                         string++;
829                         r++;
830                 }
831                 if (r>nreg || r>=4 && ttree->tn_type==DOUBLE) {
832                         if (regpanic)
833                                 error1("Register overflow: simplify expression");
834                         else
835  {
836   fprintf(stderr, "warning: register overflow\n");
837                                 longjmp(jmpbuf, 1);
838  }
839                 }
840                 fprintf(temp_fp[temp_fi], "r%d", r);
841                 goto loop;
842
843         case '-':               /* check -(sp) */
844                 if (*string=='(') {
845                         nstack++;
846                         if (table!=lsptab)
847                                 fputc('-', temp_fp[temp_fi]);
848                         goto loop;
849                 }
850                 break;
851
852         case ')':               /* check (sp)+ */
853                 fputc(')', temp_fp[temp_fi]);
854                 if (*string=='+')
855                         nstack--;
856                 goto loop;
857
858         /* #1 */
859         case '#':
860  /* previous code was accessing tn_tr1 without a type check */
861  if (opdope1[p1->n_op] & LEAF) abort();
862                 p = ((struct tnode *)p1)->tn_tr1;
863                 goto nmbr;
864
865         /* #2 */
866         case '"':
867  /* previous code was accessing tn_tr1 without a type check */
868  if (opdope1[p2->n_op] & LEAF) abort();
869                 p = ((struct tnode *)p2)->tn_tr1;
870
871         nmbr:
872                 if(collcon(p)) {
873                         if (p->n_op==STAR) {
874                                 fprintf(temp_fp[temp_fi], "*");
875                                 p = ((struct tnode *)p)->tn_tr1;
876                         }
877                         if ((p = ((struct tnode *)p)->tn_tr2)->n_op == CON) {
878 #define cp ((struct cnode *)p)
879                                 if (cp->cn_value)
880                                         psoct(cp->cn_value);
881 #undef cp
882                         } else if (p->n_op==AMPER)
883                                 pname(((struct tnode *)p)->tn_tr1, 0);
884                 }
885                 goto loop;
886
887         /*
888          * Certain adjustments for / %
889          */
890         case 'T':
891                 c = reg-1;
892                 if (uns(p1) || uns(p2)) {
893                         fprintf(temp_fp[temp_fi], "clr  r%d\n", c);
894                         goto loop;
895                 }
896                 if (dcalc(p1, 5)>12 && !match(p1, cctab, 10, 0))
897                         fprintf(temp_fp[temp_fi], "tst  r%d\n", reg);
898                 fprintf(temp_fp[temp_fi], "sxt  r%d\n", c);
899                 goto loop;
900
901         case 'V':       /* adc sbc, clr, or sxt as required for longs */
902                 switch(ttree->tn_op) {
903                 case PLUS:
904                 case ASPLUS:
905                 case INCBEF:
906                 case INCAFT:
907                         fprintf(temp_fp[temp_fi], "adc");
908                         break;
909
910                 case MINUS:
911                 case ASMINUS:
912                 case NEG:
913                 case DECBEF:
914                 case DECAFT:
915                         fprintf(temp_fp[temp_fi], "sbc");
916                         break;
917
918                 case ASSIGN:
919                         p = ttree->tn_tr2;
920                         goto lcasev;
921
922                 case ASDIV:
923                 case ASMOD:
924                 case ASULSH:
925                         p = ttree->tn_tr1;
926                 lcasev:
927                         if (p->n_type!=LONG && p->n_type!=UNLONG) {
928                                 if (uns(p) || uns(ttree->tn_tr2))
929                                         fprintf(temp_fp[temp_fi], "clr");
930                                 else
931                                         fprintf(temp_fp[temp_fi], "sxt");
932                                 goto loop;
933                         }
934                 default:
935  /* no conversion needed, skip to end of line */
936                         while ((c = *string++)!='\n' && c!='\0');
937                         break;
938                 }
939                 goto loop;
940
941         /*
942          * Mask used in field assignments
943          */
944         case 'Z':
945  /* previous code was accessing fa_mask without a type check */
946  if (ttree->tn_op != FSELA) abort();
947                 fprintf(temp_fp[temp_fi], "$%o", UNS(((struct fasgn *)ttree)->fa_mask));
948                 goto loop;
949
950         /*
951          * Relational on long values.
952          * Might bug out early. E.g.,
953          * (long<0) can be determined with only 1 test.
954          */
955         case 'X':
956                 if (xlongrel(*string++ - '0'))
957                         return(reg);
958                 goto loop;
959         }
960         fputc(c, temp_fp[temp_fi]);
961         goto loop;
962 #undef ttree
963 }
964
965 /*
966  * This routine just calls sreorder (below)
967  * on the subtrees and then on the tree itself.
968  * It returns non-zero if anything changed.
969  */
970 int reorder(treep, table, reg) struct node **treep; struct table *table; int reg; {
971         register int r, o;
972         register struct node *p;
973
974         p = *treep;
975         o = p->n_op;
976         if (opdope1[o]&LEAF||o==LOGOR||o==LOGAND||o==SEQNC||o==QUEST||o==COLON)
977                 return(0);
978 #define tp ((struct tnode *)p)
979         while(sreorder(&tp->tn_tr1, regtab, reg, 1))
980                 ;
981         if (opdope1[o]&BINARY) 
982                 while(sreorder(&tp->tn_tr2, regtab, reg, 1))
983                         ;
984         r = 0;
985         if (table!=cctab)
986         while (sreorder(treep, table, reg, 0))
987                 r++;
988         *treep = optim(*treep);
989         return(r);
990 #undef tp
991 }
992
993 /*
994  * Basically this routine carries out two kinds of optimization.
995  * First, it observes that "x + (reg = y)" where actually
996  * the = is any assignment op is better done as "reg=y; x+reg".
997  * In this case rcexpr is called to do the first part and the
998  * tree is modified so the name of the register
999  * replaces the assignment.
1000  * Moreover, expressions like "reg = x+y" are best done as
1001  * "reg = x; reg += y" (so long as "reg" and "y" are not the same!).
1002  */
1003 int sreorder(treep, table, reg, recurf) struct node **treep; struct table *table; int reg; int recurf; {
1004         register struct node *p, *p1;
1005
1006         p = *treep;
1007         if (opdope1[p->n_op]&LEAF)
1008                 return(0);
1009 #define tp ((struct tnode *)p)
1010         if (tp->tn_op==PLUS && recurf)
1011                 if (reorder(&tp->tn_tr2, table, reg))
1012  /* in this case optim() is guaranteed to return a struct tnode */
1013  {
1014                         *treep = p = optim((struct node *)tp);
1015   if (opdope1[p->n_op] & LEAF) abort();
1016  }
1017         if ((p1 = tp->tn_tr1)==(struct node *)NULL)
1018                 return(0);
1019         if (tp->tn_op==STAR || tp->tn_op==PLUS) {
1020                 if (recurf && reorder(&tp->tn_tr1, table, reg)) {
1021  /* in this case optim() might not return a struct tnode */
1022                         *treep = p = optim((struct node *)tp);
1023                         if (opdope1[p->n_op]&LEAF)
1024                                 return(0);
1025  /* but it's a struct tnode, so continue accessing via tp */
1026                 }
1027                 p1 = tp->tn_tr1;
1028         }
1029         if (p1->n_op==NAME) switch(tp->tn_op) {
1030         case ASLSH:
1031         case ASRSH:
1032         case ASSIGN:
1033                 if (((struct nnode *)p1)->nn_class != REG || ((struct nnode *)p1)->nn_type==CHAR
1034                   || isfloat(tp->tn_tr2))
1035                         return(0);
1036                 if (tp->tn_op==ASSIGN) switch (tp->tn_tr2->n_op) {
1037                 case RSHIFT:
1038                         if (tp->tn_type==UNSIGN)
1039                                 return(0);
1040                         goto caseGEN;
1041                 case TIMES:
1042                         if (!ispow2((struct tnode *)tp->tn_tr2))
1043                                 break;
1044                         tp->tn_tr2 = (struct node *)pow2((struct tnode *)tp->tn_tr2);
1045                 case PLUS:
1046                 case MINUS:
1047                 case AND:
1048                 case ANDN:
1049                 case OR:
1050                 case EXOR:
1051                 case LSHIFT:
1052                 caseGEN:
1053                         p1 = ((struct tnode *)tp->tn_tr2)->tn_tr2;
1054  /* here tp->tn_tr1 (former p1) is a locnnode of class REG, checked above */
1055  /* XXX formerly nn_class was not checked in the below, so random values of */
1056  /* nloc/name could (rarely) have caused the optimization not to be applied */
1057                         if (xdcalc(p1, 16) > 12
1058                          || p1->n_op==NAME
1059                          &&(((struct nnode *)p1)->nn_class == REG && ((struct locnnode *)p1)->locnn_nloc==((struct locnnode *)tp->tn_tr1)->locnn_nloc
1060                           || (((struct nnode *)p1)->nn_class == OFFS || ((struct nnode *)p1)->nn_class == SOFFS || ((struct nnode *)p1)->nn_class == XOFFS) && ((struct nnode *)p1)->nn_regno==((struct locnnode *)tp->tn_tr1)->locnn_nloc))
1061                                 return(0);
1062                         p1 = tp->tn_tr2;
1063 #define tp1 ((struct tnode *)p1)
1064                         tp->tn_tr2 = tp1->tn_tr1;
1065                         if (tp1->tn_tr1->n_op!=NAME
1066                          || ((struct nnode *)tp1->tn_tr1)->nn_class!=REG
1067                          || ((struct locnnode *)tp1->tn_tr1)->locnn_nloc!=((struct locnnode *)tp->tn_tr1)->locnn_nloc)
1068                                 rcexpr1((struct node *)tp, efftab, reg);
1069                         tp->tn_tr2 = tp1->tn_tr2;
1070                         tp->tn_op = tp1->tn_op + ASPLUS - PLUS;
1071                         *treep = (struct node *)tp;
1072                         return(1);
1073 #undef tp1
1074                 }
1075                 goto OK;
1076
1077         case ASTIMES:
1078                 if (!ispow2(tp))
1079                         return(0);
1080         case ASPLUS:
1081         case ASMINUS:
1082         case ASAND:
1083         case ASANDN:
1084         case ASOR:
1085         case ASXOR:
1086         case INCBEF:
1087         case DECBEF:
1088         OK:
1089                 if (table==cctab||table==cregtab)
1090                         reg += 020;
1091                 rcexpr1(optim((struct node *)tp), efftab, ~reg);
1092                 *treep = p1;
1093                 return(1);
1094         }
1095         return(0);
1096 #undef tp
1097 }
1098
1099 /*
1100  * Delay handles postfix ++ and -- 
1101  * It observes that "x + y++" is better
1102  * treated as "x + y; y++".
1103  * If the operator is ++ or -- itself,
1104  * it calls rcexpr to load the operand, letting
1105  * the calling instance of rcexpr to do the
1106  * ++ using efftab.
1107  * Otherwise it uses sdelay to search for inc/dec
1108  * among the operands.
1109  */
1110 int delay(treep, table, reg) struct node **treep; struct table *table; int reg; {
1111         register struct tnode *p;
1112         register struct node *p1;
1113         register int r;
1114
1115         p = (struct tnode *)*treep;
1116         if ((p->tn_op==INCAFT||p->tn_op==DECAFT)
1117          && p->tn_tr1->n_op==NAME) {
1118                 r = ((struct nnode *)p->tn_tr1)->nn_class;
1119                 if (r == EXTERN || r == OFFS || r == STATIC &&
1120                                 p->tn_tr1->n_type == UNCHAR)
1121                         return(1+rcexpr1(p->tn_tr1, table, reg));
1122                 else
1123                         return(1+rcexpr1(paint(p->tn_tr1, p->tn_type), table,reg));
1124         }
1125         p1 = 0;
1126 /*
1127  * typo fix, original code.
1128  *      if (opdope1[p->tn_op]&BINARY) {
1129  *              if (p->tn_op==LOGAND || p->tn_op==LOGOR
1130  *               || p->tn_op==QUEST || p->tn_op==COLON || p->tn_op==SEQNC)
1131  *                      return(0);
1132  *              }
1133  *              p1 = sdelay(&p->tn_tr2);
1134  *      if (p1==0)
1135  *              p1 = sdelay(&p->tn_tr1);
1136  */
1137         if (opdope1[p->tn_op]&BINARY) {
1138                 if (p->tn_op==LOGAND || p->tn_op==LOGOR
1139                  || p->tn_op==QUEST || p->tn_op==COLON || p->tn_op==SEQNC)
1140                         return(0);
1141                 p1 = sdelay(&p->tn_tr2);
1142         }
1143         if (p1==0)
1144                 p1 = sdelay(&p->tn_tr1);
1145         if (p1) {
1146                 r = rcexpr1(optim((struct node *)p), table, reg);
1147                 *treep = p1;
1148                 return(r+1);
1149         }
1150         return(0);
1151 }
1152
1153 struct node *sdelay(ap) struct node **ap; {
1154         register struct node *p, *p1;
1155
1156         if ((p = *ap)==(struct node *)NULL)
1157                 return((struct node *)NULL);
1158         if ((p->n_op==INCAFT||p->n_op==DECAFT) && ((struct tnode *)p)->tn_tr1->n_op==NAME) {
1159 #define tp ((struct tnode *)p)
1160                 *ap = paint((struct node *)ncopy((struct nnode *)tp->tn_tr1), tp->tn_type);
1161                 return((struct node *)tp);
1162 #undef tp
1163         }
1164         if (p->n_op==STAR || p->n_op==PLUS)
1165                 if (p1=sdelay(&((struct tnode *)p)->tn_tr1))
1166                         return(p1);
1167         if (p->n_op==PLUS)
1168                 return(sdelay(&((struct tnode *)p)->tn_tr2));
1169         return(0);
1170 }
1171
1172 /*
1173  * Propagate possible implicit type-changing operation
1174  */
1175 struct node *paint(tp, type) register struct node *tp; register int type; {
1176
1177         if (tp->n_type==type)
1178                 return(tp);
1179         if (tp->n_type==CHAR && type==INT)
1180                 return(tp);
1181         if (tp->n_type==CHAR || tp->n_type==UNCHAR)
1182                 return(optim((struct node *)tnode(LOAD, type, tp, (struct node *)NULL)));
1183         tp->n_type = type;
1184         if (tp->n_op==AMPER && type&XTYPE)
1185 #define ttp ((struct tnode *)tp)
1186                 ttp->tn_tr1 = paint(ttp->tn_tr1, decref1(type));
1187 #undef ttp
1188         else if (tp->n_op==STAR)
1189 #define ttp ((struct tnode *)tp)
1190                 ttp->tn_tr1 = paint(ttp->tn_tr1, incref1(type));
1191 #undef ttp
1192         else if (tp->n_op==ASSIGN) {
1193 #define ttp ((struct tnode *)tp)
1194  /* previous code was not saving back return value from paint() ??? */
1195  struct node *temp =
1196                 paint(ttp->tn_tr1, type);
1197  if (temp != ttp->tn_tr1) fprintf(stderr, "warning: possible paint() issue\n");
1198  temp =
1199                 paint(ttp->tn_tr2, type);
1200  if (temp != ttp->tn_tr2) fprintf(stderr, "warning: possible paint() issue\n");
1201 #undef ttp
1202         }
1203         return(tp);
1204 }
1205
1206 /*
1207  * Copy a tree node for a register variable.
1208  * Used by sdelay because if *reg-- is turned
1209  * into *reg; reg-- the *reg will in turn
1210  * be changed to some offset class, accidentally
1211  * modifying the reg--.
1212  */
1213 struct nnode *ncopy(p) register struct nnode *p; {
1214         struct nnode *q;
1215
1216         if (p->nn_class==EXTERN || p->nn_class==XOFFS) {
1217 #define extp ((struct extnnode *)p)
1218 #define extq (*(struct extnnode **)&q)
1219                 extq = (struct extnnode *)getblk(sizeof(struct extnnode));
1220                 extq->extnn_name = extp->extnn_name;
1221 #undef extp
1222 #undef extq
1223         }
1224         else {
1225 #define locp ((struct locnnode *)p)
1226 #define locq (*(struct locnnode **)&q)
1227                 locq = (struct locnnode *)getblk(sizeof(struct locnnode));
1228                 locq->locnn_nloc = locp->locnn_nloc;
1229 #undef locp
1230 #undef locq
1231         }
1232         q->nn_op = p->nn_op;
1233         q->nn_type = p->nn_type;
1234         q->nn_class = p->nn_class;
1235         q->nn_regno = p->nn_regno;
1236         q->nn_offset = p->nn_offset;
1237         return(q);
1238 }
1239
1240 /*
1241  * If the tree can be immediately loaded into a register,
1242  * produce code to do so and return success.
1243  */
1244 int chkleaf(tree, table, reg) register struct node *tree; struct table *table; int reg; {
1245         struct tnode lbuf;
1246
1247         if (tree->n_op!=STAR && dcalc(tree, nreg-reg) > 12)
1248                 return(-1);
1249  /* if dcalc() returns 0 then either tree == NULL or tree is a struct tnode */
1250 #define ttree ((struct tnode *)tree)
1251         lbuf.tn_op = LOAD;
1252         lbuf.tn_type = ttree->tn_type;
1253         lbuf.tn_degree = ttree->tn_degree;
1254         lbuf.tn_tr1 = tree;
1255  /* can't have garbage in lbuf.tr2, cexpr() will deref it if non-NULL */
1256  lbuf.tn_tr2 = (struct node *)NULL;
1257         return(rcexpr1((struct node *)&lbuf, table, reg));
1258 }
1259
1260 /*
1261  * Compile a function argument.
1262  * If the stack is currently empty, put it in (sp)
1263  * rather than -(sp); this will save a pop.
1264  * Return the number of bytes pushed,
1265  * for future popping.
1266  */
1267 int comarg(tree, flagp) register struct node *tree; int *flagp; {
1268         register int retval;
1269         int i;
1270         int size;
1271
1272         if (/*tree->n_op==STRASG*/tree->n_type==STRUCT) {
1273  /*             size = tree->fa_mask;
1274                 tree = tree->tn_tr1;*/
1275  size = tree->n_strp->S.ssize;
1276                 tree = strfunc(tree);
1277                 if (size <= sizeof(_INT)) {
1278                         paint(tree, INT);
1279                         goto normal;
1280                 }
1281                 if (size <= sizeof(_LONG)) {
1282                         paint(tree, LONG);
1283                         goto normal;
1284                 }
1285                 if (tree->n_op!=NAME && tree->n_op!=STAR) {
1286                         error1("Unimplemented structure assignment");
1287                         return(0);
1288                 }
1289                 tree = (struct node *)tnode(AMPER, STRUCT+PTR, tree, (struct node *)NULL);
1290                 tree = (struct node *)tnode(PLUS, STRUCT+PTR, tree, (struct node *)tconst(size, INT));
1291                 tree = optim(tree);
1292                 retval = rcexpr1(tree, regtab, 0);
1293                 size >>= 1;
1294                 if (size <= 5) {
1295                         for (i=0; i<size; i++)
1296                                 fprintf(temp_fp[temp_fi], "mov  -(r%d),-(sp)\n", retval);
1297                 } else {
1298                         if (retval!=0)
1299                                 fprintf(temp_fp[temp_fi], "mov  r%d,r0\n", retval);
1300                         fprintf(temp_fp[temp_fi], "mov  $%o,r1\n", UNS(size));
1301                         fprintf(temp_fp[temp_fi], "L%d:mov      -(r0),-(sp)\ndec\tr1\njne\tL%d\n", isn1, isn1);
1302                         isn1++;
1303                 }
1304                 nstack++;
1305                 return(size*2);
1306         }
1307 normal:
1308         if (nstack || isfloat(tree) || tree->n_type==LONG || tree->n_type==UNLONG) {
1309                 rcexpr1(tree, sptab, 0);
1310                 retval = arlength(tree->n_type);
1311         } else {
1312                 (*flagp)++;
1313                 rcexpr1(tree, lsptab, 0);
1314                 retval = 0;
1315         }
1316         return(retval);
1317 }
1318
1319 struct node *strfunc(tp) register struct node *tp; {
1320         if (tp->n_op != CALL)
1321                 return(tp);
1322         paint(tp, STRUCT+PTR);
1323         return((struct node *)tnode(STAR, STRUCT, tp, (struct node *)NULL));
1324 }
1325
1326 /*
1327  * Compile an initializing expression
1328  */
1329 void doinit(type, tree) register int type; register struct node *tree; {
1330         _FLOAT sfval;
1331         _DOUBLE fval;
1332         _LONG lval;
1333
1334         if (type==CHAR || type==UNCHAR) {
1335                 fprintf(temp_fp[temp_fi], ".byte ");
1336                 if (tree->n_type&XTYPE)
1337                         goto illinit;
1338                 type = INT;
1339         }
1340         if (type&XTYPE)
1341                 type = INT;
1342         switch (type) {
1343         case INT:
1344         case UNSIGN:
1345                 if (tree->n_op==FTOI) {
1346                         if (((struct tnode *)tree)->tn_tr1->n_op!=FCON && ((struct tnode *)tree)->tn_tr1->n_op!=SFCON)
1347                                 goto illinit;
1348                         tree = ((struct tnode *)tree)->tn_tr1;
1349                         fval = ((struct fnode *)tree)->fn_fvalue;
1350                         ((struct cnode *)tree)->cn_op = CON;
1351 #ifdef pdp11
1352                         ((struct cnode *)tree)->cn_value = fval;
1353 #else
1354                         ((struct cnode *)tree)->cn_value = fp_double_to_int(fval);
1355 #endif
1356                 } else if (tree->n_op==LTOI) {
1357                         if (((struct tnode *)tree)->tn_tr1->n_op!=LCON)
1358                                 goto illinit;
1359                         tree = ((struct tnode *)tree)->tn_tr1;
1360                         lval = ((struct lnode *)tree)->ln_lvalue;
1361                         ((struct cnode *)tree)->cn_op = CON;
1362                         ((struct cnode *)tree)->cn_value = lval;
1363                 }
1364                 if (tree->n_op == CON)
1365                         fprintf(temp_fp[temp_fi], "%o\n", UNS(((struct cnode *)tree)->cn_value));
1366                 else if (tree->n_op==AMPER) {
1367                         pname(((struct tnode *)tree)->tn_tr1, 0);
1368                         fputc('\n', temp_fp[temp_fi]) /*putchar('\n')*/;
1369                 } else
1370                         goto illinit;
1371                 return;
1372
1373         case DOUBLE:
1374         case FLOAT:
1375                 if (tree->n_op==ITOF) {
1376 #define ttree ((struct tnode *)tree)
1377                         if (ttree->tn_tr1->n_op==CON) {
1378 /* note: this should be changed to respect the signedness of the int */
1379 #ifdef pdp11
1380                                 fval = ((struct cnode *)ttree->tn_tr1)->cn_value;
1381 #else
1382                                 fval = fp_int_to_double(((struct cnode *)ttree->tn_tr1)->cn_value);
1383 #endif
1384                         } else
1385                                 goto illinit;
1386 #undef ttree
1387                 } else if (tree->n_op==FCON || tree->n_op==SFCON) {
1388                         fval = ((struct fnode *)tree)->fn_fvalue;
1389                 } else if (tree->n_op==LTOF) {
1390 #define ttree ((struct tnode *)tree)
1391                         if (ttree->tn_tr1->n_op!=LCON)
1392                                 goto illinit;
1393 /* note: this should be changed to respect the signedness of the long */
1394 #ifdef pdp11
1395                         fval = ((struct lnode *)ttree->tn_tr1)->ln_lvalue;
1396 #else
1397                         fval = fp_long_to_double(((struct lnode *)ttree->tn_tr1)->ln_lvalue);
1398 #endif
1399 #undef ttree
1400                 } else
1401                         goto illinit;
1402                 if (type==FLOAT) {
1403 #ifdef pdp11
1404                         sfval = fval;
1405 /*nonportable*/
1406                         fprintf(temp_fp[temp_fi], "%o; %o\n",
1407                                 ((_UNSIGNED_INT *)&sfval)[0],
1408                                 ((_UNSIGNED_INT *)&sfval)[1]);
1409 #else
1410                         sfval = fp_double_to_float(fval);
1411                         fprintf(temp_fp[temp_fi], "%o; %o\n",
1412                                 (int)(sfval.h >> 16) & 0xffff,
1413                                 (int)sfval.h & 0xffff);
1414 #endif
1415                 } else {
1416 #ifdef pdp11
1417 /* nonportable */
1418                         fprintf(temp_fp[temp_fi], "%o; %o; %o; %o\n",
1419                                 ((_UNSIGNED_INT *)&fval)[0],
1420                                 ((_UNSIGNED_INT *)&fval)[1],
1421                                 ((_UNSIGNED_INT *)&fval)[2],
1422                                 ((_UNSIGNED_INT *)&fval)[3]);
1423 #else
1424                         fprintf(temp_fp[temp_fi], "%o; %o; %o; %o\n",
1425                                 (int)(fval.h >> 16) & 0xffff,
1426                                 (int)fval.h & 0xffff,
1427                                 (int)(fval.l >> 16) & 0xffff,
1428                                 (int)fval.l & 0xffff);
1429 #endif
1430                 }
1431                 return;
1432
1433         case UNLONG:
1434         case LONG:
1435                 if (tree->n_op==FTOL) {
1436                         tree = ((struct tnode *)tree)->tn_tr1;
1437                         if (tree->n_op==SFCON)
1438                                 tree->n_op = FCON;
1439                         if (tree->n_op!= FCON)
1440                                 goto illinit;
1441 #ifdef pdp11
1442                         lval = ((struct fnode *)tree)->fn_fvalue;
1443 #else
1444                         lval = fp_double_to_long(((struct fnode *)tree)->fn_fvalue);
1445 #endif
1446                 } else if (tree->n_op==ITOL) {
1447 #define ttree ((struct tnode *)tree)
1448                         if (ttree->tn_tr1->n_op != CON)
1449                                 goto illinit;
1450                         if (uns(ttree->tn_tr1))
1451                                 lval = (_UNSIGNED_INT)((struct cnode *)ttree->tn_tr1)->cn_value;
1452                         else
1453                                 lval = ((struct cnode *)ttree->tn_tr1)->cn_value;
1454 #undef ttree
1455                 } else if (tree->n_op==LCON) {
1456                         lval = ((struct lnode *)tree)->ln_lvalue;
1457                 } else
1458                         goto illinit;
1459 /* nonportable */
1460                 fprintf(temp_fp[temp_fi], "%o; %o\n", UNS((lval>>16)), UNS(lval));
1461                 return;
1462         }
1463 illinit:
1464         error1("Illegal initialization");
1465 }
1466
1467 void movreg(r0, r1, tree) int r0; int r1; struct node *tree; {
1468         register char *s;
1469         char c;
1470
1471         if (r0==r1)
1472                 return;
1473         if (tree->n_type==LONG || tree->n_type == UNLONG) {
1474                 if (r0>=nreg || r1>=nreg) {
1475                         error1("register overflow: compiler error");
1476                 }
1477                 s = "mov        r%d,r%d\nmov    r%d,r%d\n";
1478                 if (r0 < r1)
1479                         fprintf(temp_fp[temp_fi], s, r0+1,r1+1,r0,r1);
1480                 else
1481                         fprintf(temp_fp[temp_fi], s, r0,r1,r0+1,r1+1);
1482                 return;
1483         }
1484         c = isfloat(tree);
1485         fprintf(temp_fp[temp_fi], "mov%.1s      r%d,r%d\n", &c, r0, r1);
1486 }