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