]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/1c/txt.c
Import sources from 2011-03-30 iso image - lib
[plan9front.git] / sys / src / cmd / 1c / 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 = "68000";
32         thechar = '1';
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                                 else
72                                 if(sj == 4)
73                                         if(si == 1)
74                                                 txtp->postext = AEXTBL;
75                                         else
76                                                 txtp->postext = AEXTWL;
77                         }
78                         sj = si;
79                 }
80                 if(sj == 1)
81                         txtp->movas = AMOVB;
82                 if(sj == 2)
83                         txtp->movas = AMOVW;
84                 if(sj == 4)
85                         txtp->movas = AMOVL;
86         }
87
88         for(i=0; i<ALLOP; i++)
89                 for(j=0; j<NTYPE; j++)
90                         opxt[i][j] = AGOK;
91         oinit(OFUNC, ABSR, ATRAP, AGOK, AGOK, AGOK);
92
93         oinit(OAS, AMOVB, AMOVW, AMOVL, AFMOVEF, AFMOVED);
94         oinit(OFAS, AFMOVEB, AFMOVEW, AFMOVEL, AFMOVEF, AFMOVED);
95         oinit(OADDR, AGOK, APEA, ALEA, AGOK, AGOK);
96         oinit(OPREINC, AADDB, AADDW, AADDL, AFADDF, AFADDD);
97         oinit(OPOSTINC, AADDB, AADDW, AADDL, AFADDF, AFADDD);
98         oinit(OPREDEC, ASUBB, ASUBW, ASUBL, AFSUBF, AFSUBD);
99         oinit(OPOSTDEC, ASUBB, ASUBW, ASUBL, AFSUBF, AFSUBD);
100         oinit(OADD, AADDB, AADDW, AADDL, AFADDF, AFADDD);
101         oinit(OASADD, AADDB, AADDW, AADDL, AFADDF, AFADDD);
102         oinit(OSUB, ASUBB, ASUBW, ASUBL, AFSUBF, AFSUBD);
103         oinit(OASSUB, ASUBB, ASUBW, ASUBL, AFSUBF, AFSUBD);
104         oinit(OMUL, AGOK, AMULSW, AMULSL, AFMULF, AFMULD);
105         oinit(OLMUL, AGOK, AMULSW, AMULSL, AFMULF, AFMULD);
106         oinit(OASMUL, AGOK, AMULSW, AMULSL, AFMULF, AFMULD);
107         oinit(OASLMUL, AGOK, AMULSW, AMULSL, AFMULF, AFMULD);
108         oinit(ODIV, AGOK, ADIVSW, ADIVSL, AFDIVF, AFDIVD);
109         oinit(OLDIV, AGOK, ADIVUW, ADIVUL, AFDIVF, AFDIVD);
110         oinit(OASDIV, AGOK, ADIVSW, ADIVSL, AFDIVF, AFDIVD);
111         oinit(OASLDIV, AGOK, ADIVUW, ADIVUL, AFDIVF, AFDIVD);
112         oinit(OMOD, AGOK, ADIVSW, ADIVSL, AFMODF, AFMODD);
113         oinit(OASMOD, AGOK, ADIVSW, ADIVSL, AGOK, AGOK);
114         oinit(OLMOD, AGOK, ADIVUW, ADIVUL, AGOK, AGOK);
115         oinit(OASLMOD, AGOK, ADIVUW, ADIVUL, AGOK, AGOK);
116         oinit(OAND, AANDB, AANDW, AANDL, AGOK, AGOK);
117         oinit(OASAND, AANDB, AANDW, AANDL, AGOK, AGOK);
118         oinit(OOR, AORB, AORW, AORL, AGOK, AGOK);
119         oinit(OASOR, AORB, AORW, AORL, AGOK, AGOK);
120         oinit(OXOR, AEORB, AEORW, AEORL, AGOK, AGOK);
121         oinit(OASXOR, AEORB, AEORW, AEORL, AGOK, AGOK);
122         oinit(ONEG, ANEGB, ANEGW, ANEGL, AFNEGF, AFNEGD);
123         oinit(OCOM, ANOTB, ANOTW, ANOTL, AGOK, AGOK);
124         oinit(OTST, ATSTB, ATSTW, ATSTL, AFTSTF, AFTSTD);
125         oinit(OEQ, ACMPB, ACMPW, ACMPL, AFCMPF, AFCMPD);
126         oinit(ONE, ACMPB, ACMPW, ACMPL, AFCMPF, AFCMPD);
127         oinit(OGE, ACMPB, ACMPW, ACMPL, AFCMPF, AFCMPD);
128         oinit(OGT, ACMPB, ACMPW, ACMPL, AFCMPF, AFCMPD);
129         oinit(OLT, ACMPB, ACMPW, ACMPL, AFCMPF, AFCMPD);
130         oinit(OLE, ACMPB, ACMPW, ACMPL, AFCMPF, AFCMPD);
131         oinit(OLS, ACMPB, ACMPW, ACMPL, AFCMPF, AFCMPD);
132         oinit(OLO, ACMPB, ACMPW, ACMPL, AFCMPF, AFCMPD);
133         oinit(OHS, ACMPB, ACMPW, ACMPL, AFCMPF, AFCMPD);
134         oinit(OHI, ACMPB, ACMPW, ACMPL, AFCMPF, AFCMPD);
135         oinit(OASHR, AASRB, AASRW, AASRL, AGOK, AGOK);
136         oinit(OASASHR, AASRB, AASRW, AASRL, AGOK, AGOK);
137         oinit(OLSHR, ALSRB, ALSRW, ALSRL, AGOK, AGOK);
138         oinit(OASLSHR, ALSRB, ALSRW, ALSRL, AGOK, AGOK);
139         oinit(OASHL, AASLB, AASLW, AASLL, AGOK, AGOK);
140         oinit(OASASHL, AASLB, AASLW, AASLL, AGOK, AGOK);
141         oinit(OBIT, ABFEXTU, AGOK, AGOK, AGOK, AGOK);
142
143         nstring = 0;
144         mnstring = 0;
145         nrathole = 0;
146         nstatic = 0;
147         pc = 0;
148         breakpc = -1;
149         continpc = -1;
150         cases = C;
151         firstp = P;
152         lastp = P;
153         tfield = types[TLONG];
154
155         zprog.link = P;
156         zprog.as = AGOK;
157         zprog.from.type = 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 OCONST:
340                 a->displace = 0;
341                 if(typefd[n->type->etype]) {
342                         a->type = D_FCONST;
343                         a->dval = n->fconst;
344                         break;
345                 }
346                 a->type = D_CONST;
347                 a->offset = n->vconst;
348                 break;
349
350         case OADD:
351                 l = n->left;
352                 if(l->addable == 20) {
353                         v = l->vconst;
354                         naddr(n->right, a, x);
355                         goto add;
356                 }
357                 l = n->right;
358                 if(l->addable == 20) {
359                         v = l->vconst;
360                         naddr(n->left, a, x);
361                         goto add;
362                 }
363                 goto bad;
364
365         noadd:
366                 v = 0;
367         add:
368                 switch(n->addable) {
369                 default:
370                         goto bad;
371                 case 2:
372                         a->displace += v;
373                         break;
374                 case 21:
375                         a->type &= D_MASK;
376                         a->type |= I_INDIR;
377                         break;
378                 case 1:
379                 case 12:
380                         a->offset += v;
381                         a->type &= D_MASK;
382                         a->type |= I_ADDR;
383                         break;
384                 case 10:
385                 case 11:
386                 case 20:
387                         a->type &= D_MASK;
388                         a->type |= I_DIR;
389                         break;
390                 }
391                 break;
392
393         case OPREINC:
394         case OPREDEC:
395         case OPOSTINC:
396         case OPOSTDEC:
397
398         case OAS:
399         case OASLMUL:
400         case OASLDIV:
401         case OASLMOD:
402         case OASMUL:
403         case OASDIV:
404         case OASMOD:
405         case OASXOR:
406         case OASOR:
407         case OASADD:
408         case OASSUB:
409         case OASLSHR:
410         case OASASHR:
411         case OASASHL:
412         case OASAND:
413                 naddr(n->left, a, x);
414                 break;
415         }
416 }
417
418 int
419 regalloc(Type *t, int g)
420 {
421
422         if(t == T)
423                 return D_NONE;
424         g &= D_MASK;
425         if(typefd[t->etype]) {
426                 if(g >= D_F0 && g < D_F0+NREG) {
427                         fregused[g-D_F0]++;
428                         return g;
429                 }
430                 for(g=0; g<NREG; g++)
431                         if(fregused[g] == 0) {
432                                 fregused[g]++;
433                                 return g + D_F0;
434                         }
435         } else {
436                 if(g >= D_R0 && g < D_R0+NREG) {
437                         regused[g-D_R0]++;
438                         return g;
439                 }
440                 for(g=0; g<NREG; g++)
441                         if(regused[g] == 0) {
442                                 regused[g]++;
443                                 return g + D_R0;
444                         }
445         }
446         diag(Z, "out of registers");
447         return D_TOS;
448 }
449
450 int
451 regaddr(int g)
452 {
453
454         if(g >= D_A0 && g < D_A0+NREG) {
455                 aregused[g-D_A0]++;
456                 return g;
457         }
458         for(g=0; g<NREG; g++)
459                 if(aregused[g] == 0) {
460                         aregused[g]++;
461                         return g + D_A0;
462                 }
463         diag(Z, "out of addr registers");
464         return D_TOS;
465 }
466
467 int
468 regpair(int g)
469 {
470
471         if(g >= D_R0+1 && g < D_R0+NREG)
472                 if(!regused[g-D_R0-1]) {
473                         regused[g-D_R0-1]++;
474                         regused[g-D_R0]++;
475                         return g-1;
476                 }
477         if(g >= D_R0 && g < D_R0+NREG-1)
478                 if(!regused[g-D_R0+1]) {
479                         regused[g-D_R0+1]++;
480                         regused[g-D_R0]++;
481                         return g;
482                 }
483         for(g = 0; g < NREG-1; g++)
484                 if(!regused[g])
485                 if(!regused[g+1]) {
486                         regused[g]++;
487                         regused[g+1]++;
488                         return g + D_R0;
489                 }
490         diag(Z, "out of register pairs");
491         return D_TOS;
492 }
493
494 int
495 regret(Type *t)
496 {
497
498         if(t == T)
499                 return D_NONE;
500         if(typefd[t->etype])
501                 return D_F0;
502         return D_R0;
503 }
504
505 void
506 regfree(int g)
507 {
508
509         g &= D_MASK;
510         if(g == D_TOS || g == D_TREE || g == D_NONE)
511                 return;
512         if(g >= D_R0 && g < D_R0+NREG) {
513                 regused[g-D_R0]--;
514                 return;
515         }
516         if(g >= D_A0 && g < D_A0+NREG) {
517                 aregused[g-D_A0]--;
518                 return;
519         }
520         if(g >= D_F0 && g < D_F0+NREG) {
521                 fregused[g-D_F0]--;
522                 return;
523         }
524         diag(Z, "bad in regfree: %d", g);
525 }
526
527 void
528 gmove(Type *tf, Type *tt, int gf, Node *f, int gt, Node *t)
529 {
530         int g, a, b;
531         Prog *p1;
532
533         tindex(tf, tt);
534         if(txtp->preclr) {
535                 if(gf >= D_R0 && gf < D_R0+NREG)
536                 if(txtp->preclr < 0) {
537                         gmove(tt, tt, gf, f, gt, t);
538                         return;
539                 }
540                 g = regalloc(types[TLONG], gt);
541                 if(g == gf) {
542                         g = regalloc(types[TLONG], D_NONE);
543                         regfree(gf);
544                 }
545                 if(txtp->preclr > 0)
546                         gopcode(OAS, types[TLONG], D_CONST, nodconst(0), g, Z);
547                 gopcode(OAS, tf, gf, f, g, Z);
548                 if(g != gt)
549                         gopcode(OAS, tt, g, Z, gt, t);
550                 regfree(g);
551                 return;
552         }
553         a = txtp->postext;
554         if(a != AGOK) {
555                 if(gf >= D_R0 && gf < D_R0+NREG)
556                         g = regalloc(types[TLONG], gf);
557                 else
558                         g = regalloc(types[TLONG], gt);
559                 if(g != gf)
560                         gopcode(OAS, tf, gf, f, g, Z);
561                 nextpc();
562                 p->as = a;
563                 p->to.type = g;
564                 if(debug['g'])
565                         print("%P\n", p);
566                 if(g != gt)
567                         gopcode(OAS, tt, g, Z, gt, t);
568                 regfree(g);
569                 return;
570         }
571         if((regbase[gf] != D_NONE && regbase[gf] == regbase[gt]) ||
572            (gf == D_TREE && gt == D_TREE && f == t))
573                 return;
574         if(typefd[tf->etype] || typefd[tt->etype]) {
575                 if(typeu[tf->etype] && typefd[tt->etype]) {     /* unsign->float */
576                         a = regalloc(types[TLONG], D_NONE);
577                         gmove(tf, types[TLONG], gf, f, a, t);
578                         if(tf->etype == TULONG) {
579                                 b = regalloc(types[TDOUBLE], D_NONE);
580                                 gmove(types[TLONG], tt, a, t, b, t);
581                                 gopcode(OTST, types[TLONG], D_NONE, Z, a, t);
582                                 gbranch(OGE);
583                                 p1 = p;
584                                 gopcode(OASADD, types[TDOUBLE],
585                                         D_CONST, nodconst(100), b, t);
586                                 p->from.dval = 4294967296.;
587                                 patch(p1, pc);
588                                 gmove(types[TDOUBLE], tt, b, t, gt, t);
589                                 regfree(b);
590                         } else
591                                 gmove(types[TLONG], tt, a, t, gt, t);
592                         regfree(a);
593                         return;
594                 }
595                 if(typefd[tf->etype] && !typefd[tt->etype]) {   /* float->fix */
596                         a = regalloc(types[TLONG], D_NONE);
597                         gopcode(OAS, types[TLONG], D_FPCR, t, a, t);
598                         gopcode(OAS, types[TLONG], D_CONST, nodconst(16), D_FPCR, t);
599                 }
600                 if(gf < D_F0 || gf >= D_F0+NREG) {
601                         g = regalloc(types[TDOUBLE], gt);
602                         gopcode(OFAS, tf, gf, f, g, t);
603                         if(g != gt)
604                                 gopcode(OFAS, tt, g, t, gt, t);
605                         regfree(g);
606                 } else
607                         gopcode(OFAS, tt, gf, f, gt, t);
608                 if(typefd[tf->etype] && !typefd[tt->etype]) {   /* float->fix */
609                         gopcode(OAS, types[TLONG], a, t, D_FPCR, t);
610                         regfree(a);
611                 }
612                 return;
613         }
614         gopcode(OAS, tt, gf, f, gt, t);
615 }
616
617 void
618 gopcode(int o, Type *ty, int gf, Node *f, int gt, Node *t)
619 {
620         int i, fidx, tidx;
621
622         if(o == OAS)
623                 if(gf == gt)
624                         if(gf != D_TREE || f == t)
625                                 return;
626
627         fidx = D_NONE;
628         tidx = D_NONE;
629         i = 0;
630         if(ty != T) {
631                 i = ty->etype;
632                 if(i >= NTYPE)
633                         i = 0;
634         }
635         nextpc();
636         if(gf == D_TREE) {
637                 naddr(f, &p->from, fidx);
638         } else {
639                 p->from.type = gf;
640                 if(gf == D_CONST) {
641                         p->from.offset = (long)(uintptr)f;
642                         if(typefd[i]) {
643                                 p->from.type = D_FCONST;
644                                 p->from.dval = (long)(uintptr)f;
645                         }
646                 }
647         }
648         p->as = opxt[o][i];
649         if(gt == D_TREE) {
650                 naddr(t, &p->to, tidx);
651         } else {
652                 p->to.type = gt;
653                 if(gt == D_CONST)
654                         p->to.offset = (long)(uintptr)t;
655         }
656         if(o == OBIT) {
657                 p->from.field = f->type->nbits;
658                 p->to.field = f->type->shift;
659                 if(p->from.field == 0)
660                         diag(Z, "BIT zero width bit field");
661         }
662         if(p->as == AMOVL || p->as == AMOVW || p->as == AMOVB)
663                 asopt();
664         if(debug['g'])
665                 print("%P\n", p);
666         if(p->as == AGOK)
667                 diag(Z, "GOK in gopcode: %s", onames[o]);
668         if(fidx != D_NONE)
669                 regfree(fidx);
670         if(tidx != D_NONE)
671                 regfree(tidx);
672 }
673
674 void
675 asopt(void)
676 {
677         long v;
678         int g;
679         Prog *q;
680
681         /*
682          * mov $0, ...
683          * ==>
684          * clr , ...
685          */
686         v = 0;
687         if(p->from.type == D_CONST) {
688                 v = p->from.offset;
689                 if(v == 0) {
690                         p->from.type = D_NONE;
691                         if(p->as == AMOVL)
692                                 p->as = ACLRL;
693                         if(p->as == AMOVW)
694                                 p->as = ACLRW;
695                         if(p->as == AMOVB)
696                                 p->as = ACLRB;
697                         return;
698                 }
699         }
700         /*
701          * mov ..., TOS
702          * ==>
703          * pea (...)
704          */
705         if(p->as == AMOVL && p->to.type == D_TOS)
706         switch(p->from.type) {
707         case D_CONST:
708                 p->from.type |= I_INDIR;
709                 p->to = p->from;
710                 p->from = zprog.from;
711                 p->as = APEA;
712                 return;
713
714         case I_ADDR|D_EXTERN:
715         case I_ADDR|D_STATIC:
716                 p->from.type &= ~I_ADDR;
717                 p->to = p->from;
718                 p->from = zprog.from;
719                 p->as = APEA;
720                 return;
721         }
722         /*
723          * movL $Qx, ...
724          * ==>
725          * movL $Qx,R
726          * movL R, ...
727          */
728         if(p->as == AMOVL && p->from.type == D_CONST)
729         if(v >= -128 && v < 128)
730         if(p->to.type < D_R0 || p->to.type >= D_R0+NREG) {
731                 g = regalloc(types[TLONG], D_NONE);
732                 q = p;
733                 nextpc();
734                 p->as = AMOVL;
735                 p->from.type = g;
736                 p->to = q->to;
737                 q->to = p->from;
738                 regfree(g);
739                 if(debug['g'])
740                         print("%P\n", q);
741                 return;
742         }
743 }
744
745 void
746 gbranch(int o)
747 {
748         int a;
749
750         a = ABNE;
751         switch(o) {
752         case ORETURN: a = ARTS; break;
753         case OGOTO: a = ABRA; break;
754         case OEQ: a = ABEQ; break;
755         case ONE: a = ABNE; break;
756         case OLE: a = ABLE; break;
757         case OLS: a = ABLS; break;
758         case OLT: a = ABLT; break;
759         case OLO: a = ABCS; break;
760         case OGE: a = ABGE; break;
761         case OHS: a = ABCC; break;
762         case OGT: a = ABGT; break;
763         case OHI: a = ABHI; break;
764         case OBIT: a = ABCS; break;
765         case OCASE: a = ABCASE; break;
766         }
767         nextpc();
768         p->from.type = D_NONE;
769         p->to.type = D_NONE;
770         p->as = a;
771 }
772
773 void
774 fpbranch(void)
775 {
776         int a;
777
778         a = p->as;
779         switch(a) {
780         case ABEQ: a = AFBEQ; break;
781         case ABNE: a = AFBNE; break;
782         case ABLE: a = AFBLE; break;
783         case ABLT: a = AFBLT; break;
784         case ABGE: a = AFBGE; break;
785         case ABGT: a = AFBGT; break;
786         }
787         p->as = a;
788 }
789
790 void
791 patch(Prog *op, long pc)
792 {
793
794         op->to.offset = pc;
795         op->to.type = D_BRANCH;
796 }
797
798 void
799 gpseudo(int a, Sym *s, int g, long v)
800 {
801
802         nextpc();
803         if(a == ADATA)
804                 pc--;
805         p->as = a;
806         p->to.type = g;
807         p->to.offset = v;
808         p->from.sym = s;
809         p->from.type = D_EXTERN;
810         if(s->class == CSTATIC)
811                 p->from.type = D_STATIC;
812 }
813
814 void
815 gpseudotree(int a, Sym *s, Node *n)
816 {
817
818         nextpc();
819         if(a == ADATA)
820                 pc--;
821         p->as = a;
822         naddr(n, &p->to, D_NONE);
823         p->from.sym = s;
824         p->from.type = D_EXTERN;
825         if(s->class == CSTATIC)
826                 p->from.type = D_STATIC;
827 }
828
829 long
830 exreg(Type *t)
831 {
832         long o;
833
834         if(typechl[t->etype]) {
835                 if(exregoffset <= 5)
836                         return 0;
837                 o = exregoffset + D_R0;
838                 exregoffset--;
839                 return o;
840         }
841         if(t->etype == TIND) {
842                 if(exaregoffset <= 3)
843                         return 0;
844                 o = exaregoffset + D_A0;
845                 exaregoffset--;
846                 return o;
847         }
848         if(typefd[t->etype]) {
849                 if(exfregoffset <= 5)
850                         return 0;
851                 o = exfregoffset + D_F0;
852                 exfregoffset--;
853                 return o;
854         }
855         return 0;
856 }
857
858 schar   ewidth[NTYPE] =
859 {
860         -1,             /* [TXXX] */
861         SZ_CHAR,        /* [TCHAR] */
862         SZ_CHAR,        /* [TUCHAR] */
863         SZ_SHORT,       /* [TSHORT] */
864         SZ_SHORT,       /* [TUSHORT] */
865         SZ_INT,         /* [TINT] */
866         SZ_INT,         /* [TUINT] */
867         SZ_LONG,        /* [TLONG] */
868         SZ_LONG,        /* [TULONG] */
869         SZ_VLONG,       /* [TVLONG] */
870         SZ_VLONG,       /* [TUVLONG] */
871         SZ_FLOAT,       /* [TFLOAT] */
872         SZ_DOUBLE,      /* [TDOUBLE] */
873         SZ_IND,         /* [TIND] */
874         0,              /* [TFUNC] */
875         -1,             /* [TARRAY] */
876         0,              /* [TVOID] */
877         -1,             /* [TSTRUCT] */
878         -1,             /* [TUNION] */
879         SZ_INT,         /* [TENUM] */
880 };
881 long    ncast[NTYPE] =
882 {
883         0,                              /* [TXXX] */
884         BCHAR|BUCHAR,                   /* [TCHAR] */
885         BCHAR|BUCHAR,                   /* [TUCHAR] */
886         BSHORT|BUSHORT,                 /* [TSHORT] */
887         BSHORT|BUSHORT,                 /* [TUSHORT] */
888         BINT|BUINT|BLONG|BULONG|BIND,   /* [TINT] */
889         BINT|BUINT|BLONG|BULONG|BIND,   /* [TUINT] */
890         BINT|BUINT|BLONG|BULONG|BIND,   /* [TLONG] */
891         BINT|BUINT|BLONG|BULONG|BIND,   /* [TULONG] */
892         BVLONG|BUVLONG,                 /* [TVLONG] */
893         BVLONG|BUVLONG,                 /* [TUVLONG] */
894         BFLOAT,                         /* [TFLOAT] */
895         BDOUBLE,                        /* [TDOUBLE] */
896         BLONG|BULONG|BIND,              /* [TIND] */
897         0,                              /* [TFUNC] */
898         0,                              /* [TARRAY] */
899         0,                              /* [TVOID] */
900         BSTRUCT,                        /* [TSTRUCT] */
901         BUNION,                         /* [TUNION] */
902         0,                              /* [TENUM] */
903 };