]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/2c/txt.c
devproc: can't wait for ourselfs to stop (thanks Shamar)
[plan9front.git] / sys / src / cmd / 2c / txt.c
1 #include "gc.h"
2
3 void
4 tindex(Type *tf, Type *tt)
5 {
6         int i, j;
7
8         j = 0;
9         if(tt != T) {
10                 j = tt->etype;
11                 if(j >= NTYPE)
12                         j = 0;
13         }
14         i = 0;
15         if(tf != T) {
16                 i = tf->etype;
17                 if(i >= NTYPE)
18                         if(typesu[i])
19                                 i = j;
20                         else
21                                 i = 0;
22         }
23         txtp = &txt[i][j];
24 }
25
26 void
27 ginit(void)
28 {
29         int i, j, si, sj;
30
31         thestring = "68020";
32         thechar = '2';
33         exregoffset = 7;
34         exaregoffset = 5;
35         exfregoffset = 7;
36         listinit();
37         for(i=0; i<NREG; i++) {
38                 regused[i] = 0;
39                 fregused[i] = 0;
40                 aregused[i] = 0;
41         }
42         regaddr(D_A0+6);
43         regaddr(D_A0+7);
44         for(i=0; i<sizeof(regbase); i++)
45                 regbase[i] = D_NONE;
46         for(i=0; i<NREG; i++) {
47                 regbase[D_R0+i] = D_R0+i;
48                 regbase[D_A0+i] = D_A0+i;
49                 regbase[D_F0+i] = D_F0+i;
50         }
51         regbase[D_TOS] = D_TOS;
52
53         for(i=0; i<NTYPE; i++)
54         for(j=0; j<NTYPE; j++) {
55                 txtp = &txt[i][j];
56                 txtp->movas = AGOK;
57                 txtp->preclr = 0;
58                 txtp->postext = AGOK;
59                 if(!(typechlp[i] && typechlp[j]))
60                         continue;
61                 si = types[i]->width;
62                 sj = types[j]->width;
63                 if(sj < si)
64                         txtp->preclr = -1;
65                 if(sj > si) {
66                         if(typeu[i]) {
67                                 txtp->preclr = 1;
68                         } else {
69                                 if(sj == 2)
70                                         txtp->postext = AEXTBW;
71                                 if(sj == 4)
72                                         if(si == 1)
73                                                 txtp->postext = AEXTBL;
74                                         else
75                                                 txtp->postext = AEXTWL;
76                         }
77                         sj = si;
78                 }
79                 if(sj == 1)
80                         txtp->movas = AMOVB;
81                 if(sj == 2)
82                         txtp->movas = AMOVW;
83                 if(sj == 4)
84                         txtp->movas = AMOVL;
85         }
86
87         for(i=0; i<ALLOP; i++)
88                 for(j=0; j<NTYPE; j++)
89                         opxt[i][j] = AGOK;
90         oinit(OFUNC, ABSR, ATRAP, AGOK, AGOK, AGOK);
91
92         oinit(OAS, AMOVB, AMOVW, AMOVL, AFMOVEF, AFMOVED);
93         oinit(OFAS, AFMOVEB, AFMOVEW, AFMOVEL, AFMOVEF, AFMOVED);
94         oinit(OADDR, AGOK, APEA, ALEA, AGOK, AGOK);
95         oinit(OPREINC, AADDB, AADDW, AADDL, AFADDF, AFADDD);
96         oinit(OPOSTINC, AADDB, AADDW, AADDL, AFADDF, AFADDD);
97         oinit(OPREDEC, ASUBB, ASUBW, ASUBL, AFSUBF, AFSUBD);
98         oinit(OPOSTDEC, ASUBB, ASUBW, ASUBL, AFSUBF, AFSUBD);
99         oinit(OADD, AADDB, AADDW, AADDL, AFADDF, AFADDD);
100         oinit(OASADD, AADDB, AADDW, AADDL, AFADDF, AFADDD);
101         oinit(OSUB, ASUBB, ASUBW, ASUBL, AFSUBF, AFSUBD);
102         oinit(OASSUB, ASUBB, ASUBW, ASUBL, AFSUBF, AFSUBD);
103         oinit(OMUL, AGOK, AMULSW, AMULSL, AFMULF, AFMULD);
104         oinit(OLMUL, AGOK, AMULSW, AMULSL, AFMULF, AFMULD);
105         oinit(OASMUL, AGOK, AMULSW, AMULSL, AFMULF, AFMULD);
106         oinit(OASLMUL, AGOK, AMULSW, AMULSL, AFMULF, AFMULD);
107         oinit(ODIV, AGOK, ADIVSW, ADIVSL, AFDIVF, AFDIVD);
108         oinit(OLDIV, AGOK, ADIVUW, ADIVUL, AFDIVF, AFDIVD);
109         oinit(OASDIV, AGOK, ADIVSW, ADIVSL, AFDIVF, AFDIVD);
110         oinit(OASLDIV, AGOK, ADIVUW, ADIVUL, AFDIVF, AFDIVD);
111         oinit(OMOD, AGOK, ADIVSW, ADIVSL, AFMODF, AFMODD);
112         oinit(OASMOD, AGOK, ADIVSW, ADIVSL, AGOK, AGOK);
113         oinit(OLMOD, AGOK, ADIVUW, ADIVUL, AGOK, AGOK);
114         oinit(OASLMOD, AGOK, ADIVUW, ADIVUL, AGOK, AGOK);
115         oinit(OAND, AANDB, AANDW, AANDL, AGOK, AGOK);
116         oinit(OASAND, AANDB, AANDW, AANDL, AGOK, AGOK);
117         oinit(OOR, AORB, AORW, AORL, AGOK, AGOK);
118         oinit(OASOR, AORB, AORW, AORL, AGOK, AGOK);
119         oinit(OXOR, AEORB, AEORW, AEORL, AGOK, AGOK);
120         oinit(OASXOR, AEORB, AEORW, AEORL, AGOK, AGOK);
121         oinit(ONEG, ANEGB, ANEGW, ANEGL, AFNEGF, AFNEGD);
122         oinit(OCOM, ANOTB, ANOTW, ANOTL, AGOK, AGOK);
123         oinit(OTST, ATSTB, ATSTW, ATSTL, AFTSTF, AFTSTD);
124         oinit(OEQ, ACMPB, ACMPW, ACMPL, AFCMPF, AFCMPD);
125         oinit(ONE, ACMPB, ACMPW, ACMPL, AFCMPF, AFCMPD);
126         oinit(OGE, ACMPB, ACMPW, ACMPL, AFCMPF, AFCMPD);
127         oinit(OGT, ACMPB, ACMPW, ACMPL, AFCMPF, AFCMPD);
128         oinit(OLT, ACMPB, ACMPW, ACMPL, AFCMPF, AFCMPD);
129         oinit(OLE, ACMPB, ACMPW, ACMPL, AFCMPF, AFCMPD);
130         oinit(OLS, ACMPB, ACMPW, ACMPL, AFCMPF, AFCMPD);
131         oinit(OLO, ACMPB, ACMPW, ACMPL, AFCMPF, AFCMPD);
132         oinit(OHS, ACMPB, ACMPW, ACMPL, AFCMPF, AFCMPD);
133         oinit(OHI, ACMPB, ACMPW, ACMPL, AFCMPF, AFCMPD);
134         oinit(OASHR, AASRB, AASRW, AASRL, AGOK, AGOK);
135         oinit(OASASHR, AASRB, AASRW, AASRL, AGOK, AGOK);
136         oinit(OLSHR, ALSRB, ALSRW, ALSRL, AGOK, AGOK);
137         oinit(OASLSHR, ALSRB, ALSRW, ALSRL, AGOK, AGOK);
138         oinit(OASHL, AASLB, AASLW, AASLL, AGOK, AGOK);
139         oinit(OASASHL, AASLB, AASLW, AASLL, AGOK, AGOK);
140         oinit(OBIT, ABFEXTU, AGOK, AGOK, AGOK, AGOK);
141
142         nstring = 0;
143         mnstring = 0;
144         nrathole = 0;
145         nstatic = 0;
146         pc = 0;
147         breakpc = -1;
148         continpc = -1;
149         cases = C;
150         firstp = P;
151         lastp = P;
152         tfield = types[TLONG];
153
154         zprog.link = P;
155         zprog.as = AGOK;
156         zprog.from.type = D_NONE;
157         zprog.from.index = D_NONE;
158         zprog.to = zprog.from;
159
160         nodret = new(ONAME, Z, Z);
161         nodret->sym = slookup(".ret");
162         nodret->type = types[TIND];
163         nodret->etype = types[TIND]->etype;
164         nodret->class = CPARAM;
165         nodret = new(OIND, nodret, Z);
166         complex(nodret);
167
168         symrathole = slookup(".rathole");
169         symrathole->class = CGLOBL;
170         symrathole->type = typ(TARRAY, types[TCHAR]);
171         nodrat = new(ONAME, Z, Z);
172         nodrat->sym = symrathole;
173         nodrat->type = types[TIND];
174         nodrat->etype = TVOID;
175         nodrat->class = CGLOBL;
176         complex(nodrat);
177         nodrat->type = symrathole->type;
178
179         com64init();
180
181         symstatic = slookup(".static");
182         symstatic->class = CSTATIC;
183         symstatic->type = typ(TARRAY, types[TLONG]);
184 }
185
186 void
187 gclean(void)
188 {
189         int i;
190         Sym *s;
191
192         regfree(D_A0+6);
193         regfree(D_A0+7);
194         for(i=0; i<NREG; i++) {
195                 if(regused[i])
196                         diag(Z, "missing R%d", i);
197                 if(aregused[i])
198                         diag(Z, "missing A%d", i);
199                 if(fregused[i])
200                         diag(Z, "missing F%d", i);
201         }
202
203         while(mnstring)
204                 outstring("", 1L);
205         symstring->type->width = nstring;
206         symstatic->type->width = nstatic;
207         symrathole->type->width = nrathole;
208         for(i=0; i<NHASH; i++)
209         for(s = hash[i]; s != S; s = s->link) {
210                 if(s->type == T)
211                         continue;
212                 if(s->type->width == 0)
213                         continue;
214                 if(s->class != CGLOBL && s->class != CSTATIC)
215                         continue;
216                 if(s->type == types[TENUM])
217                         continue;
218                 gpseudo(AGLOBL, s, D_CONST, s->type->width);
219                 pc--;
220         }
221         nextpc();
222         p->as = AEND;
223         outcode();
224 }
225
226 void
227 oinit(int o, int ab, int aw, int al, int af, int ad)
228 {
229         int i;
230
231         i = o;
232         if(i >= ALLOP) {
233                 diag(Z, "op(%d) >= ALLOP(%d)", i, ALLOP);
234                 errorexit();
235         }
236         opxt[i][TCHAR] = ab;
237         opxt[i][TUCHAR] = ab;
238         opxt[i][TSHORT] = aw;
239         opxt[i][TUSHORT] = aw;
240         opxt[i][TINT] = al;
241         opxt[i][TUINT] = al;
242         opxt[i][TLONG] = al;
243         opxt[i][TULONG] = al;
244         opxt[i][TIND] = al;
245         opxt[i][TFLOAT] = af;
246         opxt[i][TDOUBLE] = ad;
247 }
248
249 Prog*
250 prg(void)
251 {
252         Prog *p;
253
254         p = alloc(sizeof(*p));
255         *p = zprog;
256         return p;
257 }
258
259 void
260 nextpc(void)
261 {
262
263         p = prg();
264         pc++;
265         p->lineno = nearln;
266         if(firstp == P) {
267                 firstp = p;
268                 lastp = p;
269                 return;
270         }
271         lastp->link = p;
272         lastp = p;
273 }
274
275 void
276 gargs(Node *n)
277 {
278         long s;
279
280 loop:
281         if(n == Z)
282                 return;
283         if(n->op == OLIST) {
284                 gargs(n->right);
285                 n = n->left;
286                 goto loop;
287         }
288         s = argoff;
289         cgen(n, D_TOS, n);
290         argoff = s + n->type->width;
291 }
292
293 void
294 naddr(Node *n, Adr *a, int x)
295 {
296         Node *l;
297         long v;
298
299         switch(n->op) {
300         default:
301         bad:
302                 diag(n, "bad in naddr: %O", n->op);
303                 break;
304
305         case OADDR:
306         case OIND:
307                 naddr(n->left, a, x);
308                 goto noadd;
309
310         case OREGISTER:
311                 a->sym = S;
312                 a->type = n->reg;
313                 a->offset = n->xoffset;
314                 a->displace = 0;
315                 break;
316
317         case ONAME:
318                 a->etype = n->etype;
319                 a->displace = 0;
320                 a->sym = n->sym;
321                 a->offset = n->xoffset;
322                 a->type = D_STATIC;
323                 if(n->class == CSTATIC)
324                         break;
325                 if(n->class == CEXTERN || n->class == CGLOBL) {
326                         a->type = D_EXTERN;
327                         break;
328                 }
329                 if(n->class == CAUTO) {
330                         a->type = D_AUTO;
331                         break;
332                 }
333                 if(n->class == CPARAM) {
334                         a->type = D_PARAM;
335                         break;
336                 }
337                 goto bad;
338
339         case OINDEX:
340                 naddr(n->left, a, x);
341                 switch(n->left->addable) {
342                 default:
343                         goto bad;
344                 case 1:
345                 case 12:
346                         a->index = x | I_INDEX1;
347                         a->type &= D_MASK;
348                         break;
349                 case 2:
350                 case 10:
351                 case 11:
352                         a->index = x | I_INDEX2;
353                         break;
354                 }
355                 a->scale = n->scale;
356                 break;
357
358         case OCONST:
359                 a->displace = 0;
360                 if(typefd[n->type->etype]) {
361                         a->type = D_FCONST;
362                         a->dval = n->fconst;
363                         break;
364                 }
365                 a->type = D_CONST;
366                 a->offset = n->vconst;
367                 break;
368
369         case OADD:
370                 l = n->left;
371                 if(l->addable == 20) {
372                         v = l->vconst;
373                         naddr(n->right, a, x);
374                         goto add;
375                 }
376                 l = n->right;
377                 if(l->addable == 20) {
378                         v = l->vconst;
379                         naddr(n->left, a, x);
380                         goto add;
381                 }
382                 goto bad;
383         noadd:
384                 v = 0;
385         add:
386                 switch(n->addable) {
387                 default:
388                         goto bad;
389                 case 2:
390                         a->displace += v;
391                         break;
392                 case 21:
393                         a->type &= D_MASK;
394                         a->type |= I_INDIR;
395                         break;
396                 case 1:
397                 case 12:
398                         a->offset += v;
399                         a->type &= D_MASK;
400                         a->type |= I_ADDR;
401                         break;
402                 case 13:
403                         a->index = D_NONE|I_INDEX3;
404                 case 10:
405                 case 11:
406                 case 20:
407                         a->type &= D_MASK;
408                         a->type |= I_DIR;
409                         break;
410                 }
411                 break;
412
413         case OPREINC:
414         case OPREDEC:
415         case OPOSTINC:
416         case OPOSTDEC:
417
418         case OAS:
419         case OASLMUL:
420         case OASLDIV:
421         case OASLMOD:
422         case OASMUL:
423         case OASDIV:
424         case OASMOD:
425         case OASXOR:
426         case OASOR:
427         case OASADD:
428         case OASSUB:
429         case OASLSHR:
430         case OASASHR:
431         case OASASHL:
432         case OASAND:
433                 naddr(n->left, a, x);
434                 break;
435         }
436 }
437
438 int
439 regalloc(Type *t, int g)
440 {
441
442         if(t == T)
443                 return D_NONE;
444         g &= D_MASK;
445         if(typefd[t->etype]) {
446                 if(g >= D_F0 && g < D_F0+NREG) {
447                         fregused[g-D_F0]++;
448                         return g;
449                 }
450                 for(g=0; g<NREG; g++)
451                         if(fregused[g] == 0) {
452                                 fregused[g]++;
453                                 return g + D_F0;
454                         }
455         } else {
456                 if(g >= D_R0 && g < D_R0+NREG) {
457                         regused[g-D_R0]++;
458                         return g;
459                 }
460                 for(g=0; g<NREG; g++)
461                         if(regused[g] == 0) {
462                                 regused[g]++;
463                                 return g + D_R0;
464                         }
465         }
466         diag(Z, "out of registers");
467         return D_TOS;
468 }
469
470 int
471 regaddr(int g)
472 {
473
474         if(g >= D_A0 && g < D_A0+NREG) {
475                 aregused[g-D_A0]++;
476                 return g;
477         }
478         for(g=0; g<NREG; g++)
479                 if(aregused[g] == 0) {
480                         aregused[g]++;
481                         return g + D_A0;
482                 }
483         diag(Z, "out of addr registers");
484         return D_TOS;
485 }
486
487 int
488 regpair(int g)
489 {
490
491         if(g >= D_R0+1 && g < D_R0+NREG)
492                 if(!regused[g-D_R0-1]) {
493                         regused[g-D_R0-1]++;
494                         regused[g-D_R0]++;
495                         return g-1;
496                 }
497         if(g >= D_R0 && g < D_R0+NREG-1)
498                 if(!regused[g-D_R0+1]) {
499                         regused[g-D_R0+1]++;
500                         regused[g-D_R0]++;
501                         return g;
502                 }
503         for(g = 0; g < NREG-1; g++)
504                 if(!regused[g])
505                 if(!regused[g+1]) {
506                         regused[g]++;
507                         regused[g+1]++;
508                         return g + D_R0;
509                 }
510         diag(Z, "out of register pairs");
511         return D_TOS;
512 }
513
514 int
515 regret(Type *t)
516 {
517
518         if(t == T)
519                 return D_NONE;
520         if(typefd[t->etype])
521                 return D_F0;
522         return D_R0;
523 }
524
525 void
526 regfree(int g)
527 {
528
529         g &= D_MASK;
530         if(g == D_TOS || g == D_TREE || g == D_NONE)
531                 return;
532         if(g >= D_R0 && g < D_R0+NREG) {
533                 regused[g-D_R0]--;
534                 return;
535         }
536         if(g >= D_A0 && g < D_A0+NREG) {
537                 aregused[g-D_A0]--;
538                 return;
539         }
540         if(g >= D_F0 && g < D_F0+NREG) {
541                 fregused[g-D_F0]--;
542                 return;
543         }
544         diag(Z, "bad in regfree: %d", g);
545 }
546
547 void
548 gmove(Type *tf, Type *tt, int gf, Node *f, int gt, Node *t)
549 {
550         int g, a, b;
551         Prog *p1;
552
553         tindex(tf, tt);
554         if(txtp->preclr) {
555                 if(gf >= D_R0 && gf < D_R0+NREG)
556                 if(txtp->preclr < 0) {
557                         gmove(tt, tt, gf, f, gt, t);
558                         return;
559                 }
560                 g = regalloc(types[TLONG], gt);
561                 if(g == gf) {
562                         g = regalloc(types[TLONG], D_NONE);
563                         regfree(gf);
564                 }
565                 if(txtp->preclr > 0)
566                         gopcode(OAS, types[TLONG], D_CONST, nodconst(0), g, Z);
567                 gopcode(OAS, tf, gf, f, g, Z);
568                 if(g != gt)
569                         gopcode(OAS, tt, g, Z, gt, t);
570                 regfree(g);
571                 return;
572         }
573         a = txtp->postext;
574         if(a != AGOK) {
575                 if(gf >= D_R0 && gf < D_R0+NREG)
576                         g = regalloc(types[TLONG], gf);
577                 else
578                         g = regalloc(types[TLONG], gt);
579                 if(g != gf)
580                         gopcode(OAS, tf, gf, f, g, Z);
581                 nextpc();
582                 p->as = a;
583                 p->to.type = g;
584                 if(debug['g'])
585                         print("%P\n", p);
586                 if(g != gt)
587                         gopcode(OAS, tt, g, Z, gt, t);
588                 regfree(g);
589                 return;
590         }
591         if((regbase[gf] != D_NONE && regbase[gf] == regbase[gt]) ||
592            (gf == D_TREE && gt == D_TREE && f == t))
593                 return;
594         if(typefd[tf->etype] || typefd[tt->etype]) {
595                 if(typeu[tf->etype] && typefd[tt->etype]) {     /* unsign->float */
596                         a = regalloc(types[TLONG], D_NONE);
597                         gmove(tf, types[TLONG], gf, f, a, t);
598                         if(tf->etype == TULONG) {
599                                 b = regalloc(types[TDOUBLE], D_NONE);
600                                 gmove(types[TLONG], tt, a, t, b, t);
601                                 gopcode(OTST, types[TLONG], D_NONE, Z, a, t);
602                                 gbranch(OGE);
603                                 p1 = p;
604                                 gopcode(OASADD, types[TDOUBLE],
605                                         D_CONST, nodconst(100), b, t);
606                                 p->from.dval = 4294967296.;
607                                 patch(p1, pc);
608                                 gmove(types[TDOUBLE], tt, b, t, gt, t);
609                                 regfree(b);
610                         } else
611                                 gmove(types[TLONG], tt, a, t, gt, t);
612                         regfree(a);
613                         return;
614                 }
615                 if(typefd[tf->etype] && !typefd[tt->etype]) {   /* float->fix */
616                         a = regalloc(types[TLONG], D_NONE);
617                         gopcode(OAS, types[TLONG], D_FPCR, t, a, t);
618                         gopcode(OAS, types[TLONG], D_CONST, nodconst(16), D_FPCR, t);
619                 }
620                 if(gf < D_F0 || gf >= D_F0+NREG) {
621                         g = regalloc(types[TDOUBLE], gt);
622                         gopcode(OFAS, tf, gf, f, g, t);
623                         if(g != gt)
624                                 gopcode(OFAS, tt, g, t, gt, t);
625                         regfree(g);
626                 } else
627                         gopcode(OFAS, tt, gf, f, gt, t);
628                 if(typefd[tf->etype] && !typefd[tt->etype]) {   /* float->fix */
629                         gopcode(OAS, types[TLONG], a, t, D_FPCR, t);
630                         regfree(a);
631                 }
632                 return;
633         }
634         gopcode(OAS, tt, gf, f, gt, t);
635 }
636
637 void
638 gopcode(int o, Type *ty, int gf, Node *f, int gt, Node *t)
639 {
640         int i, fidx, tidx;
641         long v;
642
643         if(o == OAS)
644                 if(gf == gt)
645                         if(gf != D_TREE || f == t)
646                                 return;
647
648         fidx = D_NONE;
649         if(gf == D_TREE) {
650                 if(f->op == OINDEX) {
651                         fidx = regalloc(types[TIND], fidx);
652                         cgen(f->right, fidx, f->right);
653                 }
654         }
655         tidx = D_NONE;
656         if(gt == D_TREE) {
657                 if(t->op == OINDEX) {
658                         v = argoff;
659                         tidx = regalloc(types[TIND], tidx);
660                         cgen(t->right, tidx, t->right);
661                         if(gf == D_TOS)
662                                 adjsp(v - argoff);
663                 }
664         }
665         i = 0;
666         if(ty != T) {
667                 i = ty->etype;
668                 if(i >= NTYPE)
669                         i = 0;
670         }
671         nextpc();
672         if(gf == D_TREE) {
673                 naddr(f, &p->from, fidx);
674         } else {
675                 p->from.type = gf;
676                 if(gf == D_CONST) {
677                         p->from.offset = (long)(uintptr)f;
678                         if(typefd[i]) {
679                                 p->from.type = D_FCONST;
680                                 p->from.dval = (long)(uintptr)f;
681                         }
682                 }
683         }
684         p->as = opxt[o][i];
685         if(gt == D_TREE) {
686                 naddr(t, &p->to, tidx);
687         } else {
688                 p->to.type = gt;
689                 if(gt == D_CONST)
690                         p->to.offset = (long)(uintptr)t;
691         }
692         if(o == OBIT) {
693                 p->from.field = f->type->nbits;
694                 p->to.field = f->type->shift;
695                 if(p->from.field == 0)
696                         diag(Z, "BIT zero width bit field");
697         }
698         if(p->as == AMOVL || p->as == AMOVW || p->as == AMOVB)
699                 asopt();
700         if(debug['g'])
701                 print("%P\n", p);
702         if(p->as == AGOK)
703                 diag(Z, "GOK in gopcode: %s", onames[o]);
704         if(fidx != D_NONE)
705                 regfree(fidx);
706         if(tidx != D_NONE)
707                 regfree(tidx);
708 }
709
710 void
711 asopt(void)
712 {
713         long v;
714         int g;
715         Prog *q;
716
717         /*
718          * mov $0, ...
719          * ==>
720          * clr , ...
721          */
722         v = 0;
723         if(p->from.type == D_CONST) {
724                 v = p->from.offset;
725                 if(v == 0) {
726                         p->from.type = D_NONE;
727                         if(p->as == AMOVL)
728                                 p->as = ACLRL;
729                         if(p->as == AMOVW)
730                                 p->as = ACLRW;
731                         if(p->as == AMOVB)
732                                 p->as = ACLRB;
733                         return;
734                 }
735         }
736         /*
737          * mov ..., TOS
738          * ==>
739          * pea (...)
740          */
741         if(p->as == AMOVL && p->to.type == D_TOS && p->from.index == D_NONE)
742         switch(p->from.type) {
743         case D_CONST:
744                 p->from.type |= I_INDIR;
745                 p->to = p->from;
746                 p->from = zprog.from;
747                 p->as = APEA;
748                 return;
749
750         case I_ADDR|D_EXTERN:
751         case I_ADDR|D_STATIC:
752                 p->from.type &= ~I_ADDR;
753                 p->to = p->from;
754                 p->from = zprog.from;
755                 p->as = APEA;
756                 return;
757         }
758         /*
759          * movL $Qx, ...
760          * ==>
761          * movL $Qx,R
762          * movL R, ...
763          */
764         if(p->as == AMOVL && p->from.type == D_CONST)
765         if(v >= -128 && v < 128)
766         if(p->to.type < D_R0 || p->to.type >= D_R0+NREG) {
767                 g = regalloc(types[TLONG], D_NONE);
768                 q = p;
769                 nextpc();
770                 p->as = AMOVL;
771                 p->from.type = g;
772                 p->to = q->to;
773                 q->to = p->from;
774                 regfree(g);
775                 if(debug['g'])
776                         print("%P\n", q);
777                 return;
778         }
779 }
780
781 void
782 gbranch(int o)
783 {
784         int a;
785
786         a = ABNE;
787         switch(o) {
788         case ORETURN: a = ARTS; break;
789         case OGOTO: a = ABRA; break;
790         case OEQ: a = ABEQ; break;
791         case ONE: a = ABNE; break;
792         case OLE: a = ABLE; break;
793         case OLS: a = ABLS; break;
794         case OLT: a = ABLT; break;
795         case OLO: a = ABCS; break;
796         case OGE: a = ABGE; break;
797         case OHS: a = ABCC; break;
798         case OGT: a = ABGT; break;
799         case OHI: a = ABHI; break;
800         case OBIT: a = ABCS; break;
801         case OCASE: a = ABCASE; break;
802         }
803         nextpc();
804         p->from.type = D_NONE;
805         p->to.type = D_NONE;
806         p->as = a;
807 }
808
809 void
810 fpbranch(void)
811 {
812         int a;
813
814         a = p->as;
815         switch(a) {
816         case ABEQ: a = AFBEQ; break;
817         case ABNE: a = AFBNE; break;
818         case ABLE: a = AFBLE; break;
819         case ABLT: a = AFBLT; break;
820         case ABGE: a = AFBGE; break;
821         case ABGT: a = AFBGT; break;
822         }
823         p->as = a;
824 }
825
826 void
827 patch(Prog *op, long pc)
828 {
829
830         op->to.offset = pc;
831         op->to.type = D_BRANCH;
832 }
833
834 void
835 gpseudo(int a, Sym *s, int g, long v)
836 {
837
838         nextpc();
839         if(a == ADATA)
840                 pc--;
841         p->as = a;
842         if(g == D_TREE)
843                 abort();        /* obsolete */
844         p->to.type = g;
845         p->to.offset = v;
846         p->from.sym = s;
847         p->from.type = D_EXTERN;
848         if(s->class == CSTATIC)
849                 p->from.type = D_STATIC;
850 }
851
852 void
853 gpseudotree(int a, Sym *s, Node *n)
854 {
855         nextpc();
856         if(a == ADATA)
857                 pc--;
858         p->as = a;
859         naddr(n, &p->to, D_NONE);
860         p->from.sym = s;
861         p->from.type = D_EXTERN;
862         if(s->class == CSTATIC)
863                 p->from.type = D_STATIC;
864 }
865
866 long
867 exreg(Type *t)
868 {
869         long o;
870
871         if(typechl[t->etype]) {
872                 if(exregoffset <= 5)
873                         return 0;
874                 o = exregoffset + D_R0;
875                 exregoffset--;
876                 return o;
877         }
878         if(t->etype == TIND) {
879                 if(exaregoffset <= 3)
880                         return 0;
881                 o = exaregoffset + D_A0;
882                 exaregoffset--;
883                 return o;
884         }
885         if(typefd[t->etype]) {
886                 if(exfregoffset <= 5)
887                         return 0;
888                 o = exfregoffset + D_F0;
889                 exfregoffset--;
890                 return o;
891         }
892         return 0;
893 }
894
895 schar   ewidth[NTYPE] =
896 {
897         -1,             /* [TXXX] */
898         SZ_CHAR,        /* [TCHAR] */
899         SZ_CHAR,        /* [TUCHAR] */
900         SZ_SHORT,       /* [TSHORT] */
901         SZ_SHORT,       /* [TUSHORT] */
902         SZ_INT,         /* [TINT] */
903         SZ_INT,         /* [TUINT] */
904         SZ_LONG,        /* [TLONG] */
905         SZ_LONG,        /* [TULONG] */
906         SZ_VLONG,       /* [TVLONG] */
907         SZ_VLONG,       /* [TUVLONG] */
908         SZ_FLOAT,       /* [TFLOAT] */
909         SZ_DOUBLE,      /* [TDOUBLE] */
910         SZ_IND,         /* [TIND] */
911         0,              /* [TFUNC] */
912         -1,             /* [TARRAY] */
913         0,              /* [TVOID] */
914         -1,             /* [TSTRUCT] */
915         -1,             /* [TUNION] */
916         SZ_INT,         /* [TENUM] */
917 };
918 long    ncast[NTYPE] =
919 {
920         0,                              /* [TXXX] */
921         BCHAR|BUCHAR,                   /* [TCHAR] */
922         BCHAR|BUCHAR,                   /* [TUCHAR] */
923         BSHORT|BUSHORT,                 /* [TSHORT] */
924         BSHORT|BUSHORT,                 /* [TUSHORT] */
925         BINT|BUINT|BLONG|BULONG|BIND,   /* [TINT] */
926         BINT|BUINT|BLONG|BULONG|BIND,   /* [TUINT] */
927         BINT|BUINT|BLONG|BULONG|BIND,   /* [TLONG] */
928         BINT|BUINT|BLONG|BULONG|BIND,   /* [TULONG] */
929         BVLONG|BUVLONG,                 /* [TVLONG] */
930         BVLONG|BUVLONG,                 /* [TUVLONG] */
931         BFLOAT,                         /* [TFLOAT] */
932         BDOUBLE,                        /* [TDOUBLE] */
933         BLONG|BULONG|BIND,              /* [TIND] */
934         0,                              /* [TFUNC] */
935         0,                              /* [TARRAY] */
936         0,                              /* [TVOID] */
937         BSTRUCT,                        /* [TSTRUCT] */
938         BUNION,                         /* [TUNION] */
939         0,                              /* [TENUM] */
940 };