]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/2c/swt.c
awk: make empty FS unicodely-correct.
[plan9front.git] / sys / src / cmd / 2c / swt.c
1 #include "gc.h"
2
3 int
4 swcmp(const void *a1, const void *a2)
5 {
6         C1 *p1, *p2;
7
8         p1 = (C1*)a1;
9         p2 = (C1*)a2;
10         if(p1->val < p2->val)
11                 return -1;
12         return p1->val > p2->val;
13 }
14
15 void
16 doswit(int g, Node *n)
17 {
18         Case *c;
19         C1 *q, *iq;
20         long def, nc, i;
21
22         def = 0;
23         nc = 0;
24         for(c = cases; c->link != C; c = c->link) {
25                 if(c->def) {
26                         if(def)
27                                 diag(n, "more than one default in switch");
28                         def = c->label;
29                         continue;
30                 }
31                 nc++;
32         }
33
34         iq = alloc(nc*sizeof(C1));
35         q = iq;
36         for(c = cases; c->link != C; c = c->link) {
37                 if(c->def)
38                         continue;
39                 q->label = c->label;
40                 q->val = c->val;
41                 q++;
42         }
43         qsort(iq, nc, sizeof(C1), swcmp);
44         if(def == 0)
45                 def = breakpc;
46         for(i=0; i<nc-1; i++)
47                 if(iq[i].val == iq[i+1].val)
48                         diag(n, "duplicate cases in switch %lld", iq[i].val);
49         swit1(iq, nc, def, g, n);
50 }
51
52 #define N1      4       /* ncase: always linear */
53 #define N2      5       /* min ncase: direct */
54 #define N3      4       /* range/ncase: direct */
55                         /* else binary */
56 void
57 swit1(C1 *q, int nc, long def, int g, Node *n)
58 {
59         C1 *r, *s;
60         int i, l, m, y;
61         long v, range;
62         Prog *sp1, *sp2;
63
64         /* note that g and g+1 are not allocated */
65         if(nc <= N1)
66                 goto linear;
67         y = 23*nc/100 + 5;      /* number of cases needed to make */
68         if(y < N2)              /* direct switch worthwile */
69                 y = N2;                         /* try to do better than n**2 here */
70         for(m=nc; m>=y; m--) {                  /* m is number of cases */
71                 s = q+nc;
72                 r = s-m;
73                 for(l=nc-m; l>=0; l--) {        /* l is base of contig cases */
74                         s--;
75                         range = s->val - r->val;
76                         if(range > 0 && range <= N3*m)
77                                 goto direct;
78                         r--;
79                 }
80         }
81
82         /*
83          * divide and conquer
84          */
85         i = nc / 2;
86         r = q+i;
87         v = r->val;
88         /* compare median */
89         if(v >= -128 && v < 128) {
90                 gopcode(OAS, n->type, D_CONST, nodconst(v), g+1, n);
91                 gopcode(OEQ, n->type, g, n, g+1, n);
92         } else
93                 gopcode(OEQ, n->type, g, n, D_CONST, nodconst(v));
94         gbranch(OLT);
95         sp1 = p;
96         gbranch(OGT);
97         sp2 = p;
98         gbranch(OGOTO);
99         patch(p, r->label);
100
101         patch(sp1, pc);
102         swit1(q, i, def, g, n);
103
104         patch(sp2, pc);
105         swit1(r+1, nc-i-1, def, g, n);
106         return;
107
108 direct:
109         /* compare low bound */
110         v = r->val;
111         if(v >= -128 && v < 128) {
112                 gopcode(OAS, n->type, D_CONST, nodconst(v), g+1, n);
113                 gopcode(OEQ, n->type, g, n, g+1, n);
114         } else
115                 gopcode(OEQ, n->type, g, n, D_CONST, nodconst(v));
116         gbranch(OLT);
117         sp1 = p;
118
119         /* compare high bound */
120         v = s->val;
121         if(v >= -128 && v < 128) {
122                 gopcode(OAS, n->type, D_CONST, nodconst(v), g+1, n);
123                 gopcode(OEQ, n->type, g, n, g+1, n);
124         } else
125                 gopcode(OEQ, n->type, g, n, D_CONST, nodconst(v));
126         gbranch(OGT);
127         sp2 = p;
128
129         /* switch */
130         v = r->val;
131         gpseudo(AMOVW, symstatic, D_R0, 0L);
132         p->from.offset = nstatic - v*2;
133         p->from.index = g|I_INDEX1;
134         p->from.scale = 5;
135         nextpc();
136         p->as = ACASEW;
137
138         /* table */
139         for(i=0; i<=range; i++) {
140                 gbranch(OCASE);
141                 if(v == r->val) {
142                         patch(p, r->label);
143                         r++;
144                 } else
145                         patch(p, def);
146                 p->from.type = D_STATIC;
147                 p->from.sym = symstatic;
148                 p->from.offset = nstatic;
149                 nstatic += types[TSHORT]->width;
150                 v++;
151         }
152         gbranch(OGOTO);
153         patch(p, def);
154         if(r != s+1)
155                 print("smelly direct switch\n");
156
157         if(l > 0) {
158                 patch(sp1, pc);
159                 swit1(q, l, def, g, n);
160         } else
161                 patch(sp1, def);
162
163         m += l;
164         if(m < nc) {
165                 patch(sp2, pc);
166                 swit1(q+m, nc-m, def, g, n);
167         } else
168                 patch(sp2, def);
169         return;
170
171
172 linear:
173         for(i=0; i<nc; i++) {
174                 v = q->val;
175                 if(v >= -128 && v < 128) {
176                         gopcode(OAS, n->type, D_CONST, nodconst(v), g+1, n);
177                         gopcode(OEQ, n->type, g+1, n, g, n);
178                 } else
179                         gopcode(OEQ, n->type, g, n, D_CONST, nodconst(v));
180                 gbranch(OEQ);
181                 patch(p, q->label);
182                 q++;
183         }
184         gbranch(OGOTO);
185         patch(p, def);
186 }
187
188 void
189 casf(void)
190 {
191         Case *c;
192
193         c = alloc(sizeof(*c));
194         c->link = cases;
195         cases = c;
196 }
197
198
199 int
200 bitload(Node *b, int n1, int n2, int n3, Node *nn)
201 {
202         int sh, g, gs;
203         long v;
204         Node *l;
205         Type *t;
206
207         /*
208          * n1 gets adjusted/masked value
209          * n2 gets address of cell
210          * n3 gets contents of cell
211          */
212         gs = 0;
213         t = tfield;
214
215         l = b->left;
216         g = regalloc(t, n3);
217         if(n2 != D_NONE) {
218                 lcgen(l, n2, Z);
219                 n2 |= I_INDIR;
220                 gmove(t, t, n2, l, g, l);
221                 gmove(t, t, g, l, n1, l);
222         } else
223                 cgen(l, g, nn);
224         if(b->type->shift == 0 && typeu[b->type->etype]) {
225                 v = ~0 + (1L << b->type->nbits);
226                 gopcode(OAND, t, D_CONST, nodconst(v), g, l);
227         } else {
228                 sh = 32 - b->type->shift - b->type->nbits;
229                 if(sh > 0)
230                         if(sh >= 8) {
231                                 gs = regalloc(t, D_NONE);
232                                 gmove(t, t, D_CONST, nodconst(sh), gs, l);
233                                 gopcode(OASHL, t, gs, l, g, l);
234                                 if(b->type->shift)
235                                         regfree(gs);
236                         } else
237                                 gopcode(OASHL, t, D_CONST, nodconst(sh), g, l);
238                 sh += b->type->shift;
239                 if(sh > 0) {
240                         if(sh >= 8) {
241                                 if(b->type->shift) {
242                                         gs = regalloc(t, D_NONE);
243                                         gmove(t, t, D_CONST, nodconst(sh), gs, l);
244                                 }
245                                 if(typeu[b->type->etype])
246                                         gopcode(OLSHR, t, gs, l, g, l);
247                                 else
248                                         gopcode(OASHR, t, gs, l, g, l);
249                                 regfree(gs);
250                         } else {
251                                 if(typeu[b->type->etype])
252                                         gopcode(OLSHR, t, D_CONST, nodconst(sh), g, l);
253                                 else
254                                         gopcode(OASHR, t, D_CONST, nodconst(sh), g, l);
255                         }
256                 }
257         }
258         return g;
259 }
260
261 void
262 bitstore(Node *b, int n1, int n2, int n3, int result, Node *nn)
263 {
264         long v;
265         Node *l;
266         Type *t;
267         int sh, g, gs;
268
269         /*
270          * n1 has adjusted/masked value
271          * n2 has address of cell
272          * n3 has contents of cell
273          */
274         t = tfield;
275
276         l = b->left;
277         g = regalloc(t, D_NONE);
278         v = ~0 + (1L << b->type->nbits);
279         gopcode(OAND, t, D_CONST, nodconst(v), n1, l);
280         gmove(t, t, n1, l, g, l);
281         if(result != D_NONE)
282                 gmove(t, nn->type, n1, l, result, nn);
283         sh = b->type->shift;
284         if(sh > 0) {
285                 if(sh >= 8) {
286                         gs = regalloc(t, D_NONE);
287                         gmove(t, t, D_CONST, nodconst(sh), gs, l);
288                         gopcode(OASHL, t, gs, l, g, l);
289                         regfree(gs);
290                 } else
291                         gopcode(OASHL, t, D_CONST, nodconst(sh), g, l);
292         }
293         v <<= sh;
294         gopcode(OAND, t, D_CONST, nodconst(~v), n3, l);
295         gopcode(OOR, t, n3, l, g, l);
296         gmove(t, t, g, l, n2|I_INDIR, l);
297
298         regfree(g);
299         regfree(n1);
300         regfree(n2);
301         regfree(n3);
302 }
303
304 long
305 outstring(char *s, long n)
306 {
307         long r;
308
309         if(suppress)
310                 return nstring;
311         r = nstring;
312         while(n) {
313                 string[mnstring] = *s++;
314                 mnstring++;
315                 nstring++;
316                 if(mnstring >= NSNAME) {
317                         gpseudo(ADATA, symstring, D_SCONST, 0L);
318                         memmove(p->to.sval, string, NSNAME);
319                         p->from.offset = nstring - NSNAME;
320                         p->from.displace = NSNAME;
321                         mnstring = 0;
322                 }
323                 n--;
324         }
325         return r;
326 }
327
328 long
329 outlstring(Rune *s, long n)
330 {
331         char buf[sizeof(Rune)];
332         int c, i;
333         long r;
334
335         while(nstring % sizeof buf)
336                 outstring("", 1);
337         r = nstring;
338         while(n > 0) {
339                 c = *s++;
340                 if(align(0, types[TCHAR], Aarg1)) {
341                         for(i = sizeof buf; i > 0; c >>= 8)
342                                 buf[--i] = c;
343                 } else {
344                         for(i = 0; i < sizeof buf; c >>= 8)
345                                 buf[i++] = c;
346                 }
347                 outstring(buf, sizeof buf);
348                 n -= sizeof buf;
349         }
350         return r;
351 }
352
353 int
354 doinc(Node *n, int f)
355 {
356         Node *l;
357         int a;
358
359 loop:
360         if(n == Z)
361                 return 0;
362         l = n->left;
363         switch(n->op) {
364
365         case OPOSTINC:
366         case OPOSTDEC:
367                 if(f & POST) {
368                         a = n->addable;
369                         if(a >= INDEXED) {
370                                 if(f & TEST)
371                                         return 1;
372                                 n->addable = 0;
373                                 cgen(n, D_NONE, n);
374                                 n->addable = a;
375                         }
376                 }
377                 break;
378
379         case OAS:
380         case OASLMUL:
381         case OASLDIV:
382         case OASLMOD:
383         case OASMUL:
384         case OASDIV:
385         case OASMOD:
386         case OASXOR:
387         case OASOR:
388         case OASADD:
389         case OASSUB:
390         case OASLSHR:
391         case OASASHR:
392         case OASASHL:
393         case OASAND:
394
395         case OPREINC:
396         case OPREDEC:
397                 if(f & PRE) {
398                         a = n->addable;
399                         if(a >= INDEXED) {
400                                 if(f & TEST)
401                                         return 1;
402                                 n->addable = 0;
403                                 doinc(n, PRE);
404                                 cgen(n, D_NONE, n);
405                                 n->addable = a;
406                                 return 0;
407                         }
408                 }
409                 break;
410
411         case OFUNC:
412                 if(f & PRE)
413                         break;
414                 return 0;
415
416         case ONAME:
417         case OREGISTER:
418         case OSTRING:
419         case OCONST:
420
421         case OANDAND:
422         case OOROR:
423                 return 0;
424
425         case OCOND:
426                 return 0;
427
428         case OCOMMA:
429                 n = n->right;
430                 if(f & PRE)
431                         n = l;
432                 goto loop;
433         }
434         if(l != Z)
435                 if(doinc(l, f))
436                         return 1;
437         n = n->right;
438         goto loop;
439 }
440
441 void
442 setsp(void)
443 {
444
445         nextpc();
446         p->as = AADJSP;
447         p->from.type = D_CONST;
448         p->from.offset = 0;
449 }
450
451 void
452 adjsp(long o)
453 {
454
455         if(o != 0) {
456                 nextpc();
457                 p->as = AADJSP;
458                 p->from.type = D_CONST;
459                 p->from.offset = o;
460                 argoff += o;
461         }
462 }
463
464 int
465 simplv(Node *n)
466 {
467
468         if(n->addable <= INDEXED)
469                 return 0;
470         while(n->op == OIND)
471                 n = n->left;
472         if(n->op == ONAME)
473                 return 1;
474         return 0;
475 }
476
477 int
478 eval(Node *n, int g)
479 {
480
481         if(n->addable >= INDEXED)
482                 return D_TREE;
483         g = regalloc(n->type, g);
484         cgen(n, g, n);
485         return g;
486 }
487
488 void    outhist(Biobuf*);
489 void    zname(Biobuf*, Sym*, int);
490 void    zaddr(Biobuf*, Adr*, int);
491 void    zwrite(Biobuf*, Prog*, int, int);
492
493 void
494 outcode(void)
495 {
496         struct { Sym *sym; short type; } h[NSYM];
497         Prog *p;
498         Sym *s;
499         int f, sf, st, t, sym;
500         Biobuf b;
501
502         if(debug['S']) {
503                 for(p = firstp; p != P; p = p->link)
504                         if(p->as != ADATA && p->as != AGLOBL)
505                                 pc--;
506                 for(p = firstp; p != P; p = p->link) {
507                         print("%P\n", p);
508                         if(p->as != ADATA && p->as != AGLOBL)
509                                 pc++;
510                 }
511         }
512         f = open(outfile, OWRITE);
513         if(f < 0) {
514                 diag(Z, "cant open %s", outfile);
515                 errorexit();
516         }
517         Binit(&b, f, OWRITE);
518         Bseek(&b, 0L, 2);
519         outhist(&b);
520         for(sym=0; sym<NSYM; sym++) {
521                 h[sym].sym = S;
522                 h[sym].type = 0;
523         }
524         sym = 1;
525         for(p = firstp; p != P; p = p->link) {
526         jackpot:
527                 sf = 0;
528                 s = p->from.sym;
529                 while(s != S) {
530                         sf = s->sym;
531                         if(sf < 0 || sf >= NSYM)
532                                 sf = 0;
533                         t = p->from.type & D_MASK;
534                         if(h[sf].type == t)
535                         if(h[sf].sym == s)
536                                 break;
537                         s->sym = sym;
538                         zname(&b, s, t);
539                         h[sym].sym = s;
540                         h[sym].type = t;
541                         sf = sym;
542                         sym++;
543                         if(sym >= NSYM)
544                                 sym = 1;
545                         break;
546                 }
547                 st = 0;
548                 s = p->to.sym;
549                 while(s != S) {
550                         st = s->sym;
551                         if(st < 0 || st >= NSYM)
552                                 st = 0;
553                         t = p->to.type & D_MASK;
554                         if(h[st].type == t)
555                         if(h[st].sym == s)
556                                 break;
557                         s->sym = sym;
558                         zname(&b, s, t);
559                         h[sym].sym = s;
560                         h[sym].type = t;
561                         st = sym;
562                         sym++;
563                         if(sym >= NSYM)
564                                 sym = 1;
565                         if(st == sf)
566                                 goto jackpot;
567                         break;
568                 }
569                 zwrite(&b, p, sf, st);
570         }
571         Bflush(&b);
572         close(f);
573         firstp = P;
574         lastp = P;
575 }
576
577 void
578 zwrite(Biobuf *b, Prog *p, int sf, int st)
579 {
580         long l;
581
582         l = p->as;
583         Bputc(b, l);
584         Bputc(b, l>>8);
585         l = p->lineno;
586         Bputc(b, l);
587         Bputc(b, l>>8);
588         Bputc(b, l>>16);
589         Bputc(b, l>>24);
590         zaddr(b, &p->from, sf);
591         zaddr(b, &p->to, st);
592 }
593
594 void
595 zname(Biobuf *b, Sym *s, int t)
596 {
597         char *n;
598         ulong sig;
599
600         if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){
601                 sig = sign(s);
602                 Bputc(b, ASIGNAME);
603                 Bputc(b, ASIGNAME>>8);
604                 Bputc(b, sig);
605                 Bputc(b, sig>>8);
606                 Bputc(b, sig>>16);
607                 Bputc(b, sig>>24);
608                 s->sig = SIGDONE;
609         }
610         else{
611                 Bputc(b, ANAME);        /* as */
612                 Bputc(b, ANAME>>8);     /* as */
613         }
614         Bputc(b, t);            /* type */
615         Bputc(b, s->sym);               /* sym */
616         n = s->name;
617         while(*n) {
618                 Bputc(b, *n);
619                 n++;
620         }
621         Bputc(b, 0);
622 }
623
624 void
625 zaddr(Biobuf *b, Adr *a, int s)
626 {
627         long l;
628         int i, t;
629         char *n;
630         Ieee e;
631
632         t = 0;
633         if(a->field)
634                 t |= T_FIELD;
635         if(a->index != D_NONE)
636                 t |= T_INDEX;
637         if(s)
638                 t |= T_SYM;
639
640         switch(a->type) {
641         default:
642                 if(a->offset)
643                         t |= T_OFFSET;
644                 if(a->displace)
645                         t |= T_INDEX;
646                 if(a->type & ~0xff)
647                         t |= T_TYPE;
648                 break;
649         case D_FCONST:
650                 t |= T_FCONST;
651                 break;
652         case D_SCONST:
653                 t |= T_SCONST;
654                 break;
655         }
656         Bputc(b, t);
657
658         if(t & T_FIELD) {       /* implies field */
659                 i = a->field;
660                 Bputc(b, i);
661                 Bputc(b, i>>8);
662         }
663         if(t & T_INDEX) {       /* implies index, scale, displace */
664                 i = a->index;
665                 Bputc(b, i);
666                 Bputc(b, i>>8);
667                 Bputc(b, a->scale);
668                 l = a->displace;
669                 Bputc(b, l);
670                 Bputc(b, l>>8);
671                 Bputc(b, l>>16);
672                 Bputc(b, l>>24);
673         }
674         if(t & T_OFFSET) {      /* implies offset */
675                 l = a->offset;
676                 Bputc(b, l);
677                 Bputc(b, l>>8);
678                 Bputc(b, l>>16);
679                 Bputc(b, l>>24);
680         }
681         if(t & T_SYM)           /* implies sym */
682                 Bputc(b, s);
683         if(t & T_FCONST) {
684                 ieeedtod(&e, a->dval);
685                 l = e.l;
686                 Bputc(b, l);
687                 Bputc(b, l>>8);
688                 Bputc(b, l>>16);
689                 Bputc(b, l>>24);
690                 l = e.h;
691                 Bputc(b, l);
692                 Bputc(b, l>>8);
693                 Bputc(b, l>>16);
694                 Bputc(b, l>>24);
695                 return;
696         }
697         if(t & T_SCONST) {
698                 n = a->sval;
699                 for(i=0; i<NSNAME; i++) {
700                         Bputc(b, *n);
701                         n++;
702                 }
703                 return;
704         }
705         i = a->type;
706         Bputc(b, i);
707         if(t & T_TYPE)
708                 Bputc(b, i>>8);
709 }
710
711
712
713 void
714 outhist(Biobuf *b)
715 {
716         Hist *h;
717         char *p, *q, *op, c;
718         Prog pg;
719         int n;
720
721         pg = zprog;
722         pg.as = AHISTORY;
723         c = pathchar();
724         for(h = hist; h != H; h = h->link) {
725                 p = h->name;
726                 op = 0;
727                 /* on windows skip drive specifier in pathname */
728                 if(systemtype(Windows) && p && p[1] == ':'){
729                         p += 2;
730                         c = *p;
731                 }
732                 if(p && p[0] != c && h->offset == 0 && pathname){
733                         /* on windows skip drive specifier in pathname */
734                         if(systemtype(Windows) && pathname[1] == ':') {
735                                 op = p;
736                                 p = pathname+2;
737                                 c = *p;
738                         } else if(pathname[0] == c){
739                                 op = p;
740                                 p = pathname;
741                         }
742                 }
743                 while(p) {
744                         q = utfrune(p, c);
745                         if(q) {
746                                 n = q-p;
747                                 if(n == 0){
748                                         n = 1;  /* leading "/" */
749                                         *p = '/';       /* don't emit "\" on windows */
750                                 }
751                                 q++;
752                         } else {
753                                 n = strlen(p);
754                                 q = 0;
755                         }
756                         if(n) {
757                                 Bputc(b, ANAME);
758                                 Bputc(b, ANAME>>8);
759                                 Bputc(b, D_FILE);
760                                 Bputc(b, 1);
761                                 Bputc(b, '<');
762                                 Bwrite(b, p, n);
763                                 Bputc(b, 0);
764                         }
765                         p = q;
766                         if(p == 0 && op) {
767                                 p = op;
768                                 op = 0;
769                         }
770                 }
771                 pg.lineno = h->line;
772                 pg.to.type = zprog.to.type;
773                 pg.to.offset = h->offset;
774                 if(h->offset)
775                         pg.to.type = D_CONST;
776
777                 zwrite(b, &pg, 0, 0);
778         }
779 }
780
781 void
782 ieeedtod(Ieee *ieee, double native)
783 {
784         double fr, ho, f;
785         int exp;
786
787         if(native < 0) {
788                 ieeedtod(ieee, -native);
789                 ieee->h |= 0x80000000L;
790                 return;
791         }
792         if(native == 0) {
793                 ieee->l = 0;
794                 ieee->h = 0;
795                 return;
796         }
797         fr = frexp(native, &exp);
798         f = 2097152L;           /* shouldnt use fp constants here */
799         fr = modf(fr*f, &ho);
800         ieee->h = ho;
801         ieee->h &= 0xfffffL;
802         ieee->h |= (exp+1022L) << 20;
803         f = 65536L;
804         fr = modf(fr*f, &ho);
805         ieee->l = ho;
806         ieee->l <<= 16;
807         ieee->l |= (long)(fr*f);
808 }
809
810 int
811 nodalloc(Type *t, int g, Node *n)
812 {
813
814         n->type = t;
815         n->op = OREGISTER;
816         n->addable = 12;
817         n->complex = 0;
818         g = regaddr(g);
819         n->reg = g | I_INDIR;
820         n->xoffset = 0;
821         return g;
822 }
823
824 int
825 mulcon(Node *n, Node *c, int result, Node *nn)
826 {
827         long v;
828
829         if(typefd[n->type->etype])
830                 return 0;
831         v = c->vconst;
832         if(mulcon1(n, v, result, nn))
833                 return 1;
834         return 0;
835 }
836
837 int
838 shlcon(Node *n, Node *c, int result, Node *nn)
839 {
840         long v;
841
842         v = 1L << c->vconst;
843         return mulcon1(n, v, result, nn);
844 }
845
846 int
847 mulcon1(Node *n, long v, int result, Node *nn)
848 {
849         int g, g1, a1, a2, neg;
850         int o;
851         char code[10], *p;
852
853         if(result == D_NONE)
854                 return 0;
855         neg = 0;
856         if(v < 0) {
857                 v = -v;
858                 neg++;
859         }
860         a1 = 0;
861         a2 = multabsize;
862         for(;;) {
863                 if(a1 >= a2)
864                         return 0;
865                 g1 = (a2 + a1)/2;
866                 if(v < multab[g1].val) {
867                         a2 = g1;
868                         continue;
869                 }
870                 if(v > multab[g1].val) {
871                         a1 = g1+1;
872                         continue;
873                 }
874                 break;
875         }
876         strcpy(code, "0");
877         strncat(code, multab[g1].code, sizeof(multab[0].code));
878         p = code;
879         if(p[1] == 'i')
880                 p += 2;
881         g = regalloc(n->type, result);
882         cgen(n, g, n);
883         if(neg)
884                 gopcode(ONEG, n->type, D_NONE, n, g, n);
885         g1 = regalloc(n->type, D_NONE);
886 loop:
887         switch(*p) {
888         case 0:
889                 regfree(g1);
890                 gmove(n->type, nn->type, g, n, result, nn);
891                 regfree(g);
892                 return 1;
893         case '0':
894                 o = OAS;
895                 *p -= '0';
896                 goto com;
897         case '1':
898         case '2':
899                 o = OSUB;
900                 *p -= '1';
901                 goto com;
902         case '3':
903         case '4':
904         case '5':
905         case '6':
906                 o = OADD;
907                 *p -= '3';
908         com:
909                 a1 = g;
910                 if(*p == 1 || *p == 3)
911                         a1 = g1;
912                 a2 = g;
913                 if(*p == 0 || *p == 3)
914                         a2 = g1;
915                 gopcode(o, n->type, a1, n, a2, n);
916                 p++;
917                 break;
918         default:
919                 a1 = *p++ - 'a' + 1;
920                 a2 = g;
921                 if(a1 > 8) {
922                         a2 = g1;
923                         a1 -= 8;
924                 }
925                 gopcode(OASHL, n->type, D_CONST, nodconst(a1), a2, n);
926                 break;
927         }
928         goto loop;
929 }
930
931 void
932 nullwarn(Node *l, Node *r)
933 {
934         warn(Z, "result of operation not used");
935         if(l != Z)
936                 cgen(l, D_NONE, Z);
937         if(r != Z)
938                 cgen(r, D_NONE, Z);
939 }
940
941 void
942 sextern(Sym *s, Node *a, long o, long w)
943 {
944         long e, lw;
945
946         for(e=0; e<w; e+=NSNAME) {
947                 lw = NSNAME;
948                 if(w-e < lw)
949                         lw = w-e;
950                 gpseudo(ADATA, s, D_SCONST, 0L);
951                 p->from.offset += o+e;
952                 p->from.displace = lw;
953                 memmove(p->to.sval, a->cstring+e, lw);
954         }
955 }
956
957 void
958 gextern(Sym *s, Node *a, long o, long w)
959 {
960         if(a->op == OCONST && typev[a->type->etype]) {
961                 gpseudo(ADATA, s, D_CONST, (long)(a->vconst>>32));
962                 p->from.offset += o;
963                 p->from.displace = 4;
964                 gpseudo(ADATA, s, D_CONST, (long)(a->vconst));
965                 p->from.offset += o + 4;
966                 p->from.displace = 4;
967                 return;
968         }
969         gpseudotree(ADATA, s, a);
970         p->from.offset += o;
971         p->from.displace = w;
972 }
973
974 long
975 align(long i, Type *t, int op)
976 {
977         long o;
978         Type *v;
979         int w;
980
981         o = i;
982         w = 1;
983         switch(op) {
984         default:
985                 diag(Z, "unknown align opcode %d", op);
986                 break;
987
988         case Asu2:      /* padding at end of a struct */
989                 w = SZ_LONG;
990                 if(packflg)
991                         w = packflg;
992                 break;
993
994         case Ael1:      /* initial allign of struct element */
995                 for(v=t; v->etype==TARRAY; v=v->link)
996                         ;
997                 w = ewidth[v->etype];
998                 if(w <= 0 || w >= SZ_SHORT)
999                         w = SZ_SHORT;
1000                 if(packflg)
1001                         w = packflg;
1002                 break;
1003
1004         case Ael2:      /* width of a struct element */
1005                 o += t->width;
1006                 break;
1007
1008         case Aarg0:     /* initial passbyptr argument in arg list */
1009                 if(typesuv[t->etype]) {
1010                         o = align(o, types[TIND], Aarg1);
1011                         o = align(o, types[TIND], Aarg2);
1012                 }
1013                 break;
1014
1015         case Aarg1:     /* initial allign of parameter */
1016                 w = ewidth[t->etype];
1017                 if(w <= 0 || w >= SZ_LONG) {
1018                         w = SZ_LONG;
1019                         break;
1020                 }
1021                 o += SZ_LONG - w;       /* big endian adjustment */
1022                 w = 1;
1023                 break;
1024
1025         case Aarg2:     /* width of a parameter */
1026                 o += t->width;
1027                 w = SZ_LONG;
1028                 break;
1029
1030         case Aaut3:     /* total allign of automatic */
1031                 o = align(o, t, Ael1);
1032                 o = align(o, t, Ael2);
1033                 break;
1034         }
1035         o = round(o, w);
1036         if(debug['A'])
1037                 print("align %s %ld %T = %ld\n", bnames[op], i, t, o);
1038         return o;
1039 }
1040
1041 long
1042 maxround(long max, long v)
1043 {
1044         v += SZ_LONG-1;
1045         if(v > max)
1046                 max = round(v, SZ_LONG);
1047         return max;
1048 }