]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/2c/swt.c
mothra: fix alt display resizing, filter control characters in panel entries, use...
[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 %ld", 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         r = nstring;
310         while(n) {
311                 string[mnstring] = *s++;
312                 mnstring++;
313                 nstring++;
314                 if(mnstring >= NSNAME) {
315                         gpseudo(ADATA, symstring, D_SCONST, 0L);
316                         memmove(p->to.sval, string, NSNAME);
317                         p->from.offset = nstring - NSNAME;
318                         p->from.displace = NSNAME;
319                         mnstring = 0;
320                 }
321                 n--;
322         }
323         return r;
324 }
325
326 long
327 outlstring(ushort *s, long n)
328 {
329         char buf[2];
330         int c;
331         long r;
332
333         while(nstring & 1)
334                 outstring("", 1);
335         r = nstring;
336         while(n > 0) {
337                 c = *s++;
338                 if(align(0, types[TCHAR], Aarg1)) {
339                         buf[0] = c>>8;
340                         buf[1] = c;
341                 } else {
342                         buf[0] = c;
343                         buf[1] = c>>8;
344                 }
345                 outstring(buf, 2);
346                 n -= sizeof(ushort);
347         }
348         return r;
349 }
350
351 int
352 doinc(Node *n, int f)
353 {
354         Node *l;
355         int a;
356
357 loop:
358         if(n == Z)
359                 return 0;
360         l = n->left;
361         switch(n->op) {
362
363         case OPOSTINC:
364         case OPOSTDEC:
365                 if(f & POST) {
366                         a = n->addable;
367                         if(a >= INDEXED) {
368                                 if(f & TEST)
369                                         return 1;
370                                 n->addable = 0;
371                                 cgen(n, D_NONE, n);
372                                 n->addable = a;
373                         }
374                 }
375                 break;
376
377         case OAS:
378         case OASLMUL:
379         case OASLDIV:
380         case OASLMOD:
381         case OASMUL:
382         case OASDIV:
383         case OASMOD:
384         case OASXOR:
385         case OASOR:
386         case OASADD:
387         case OASSUB:
388         case OASLSHR:
389         case OASASHR:
390         case OASASHL:
391         case OASAND:
392
393         case OPREINC:
394         case OPREDEC:
395                 if(f & PRE) {
396                         a = n->addable;
397                         if(a >= INDEXED) {
398                                 if(f & TEST)
399                                         return 1;
400                                 n->addable = 0;
401                                 doinc(n, PRE);
402                                 cgen(n, D_NONE, n);
403                                 n->addable = a;
404                                 return 0;
405                         }
406                 }
407                 break;
408
409         case OFUNC:
410                 if(f & PRE)
411                         break;
412                 return 0;
413
414         case ONAME:
415         case OREGISTER:
416         case OSTRING:
417         case OCONST:
418
419         case OANDAND:
420         case OOROR:
421                 return 0;
422
423         case OCOND:
424                 return 0;
425
426         case OCOMMA:
427                 n = n->right;
428                 if(f & PRE)
429                         n = l;
430                 goto loop;
431         }
432         if(l != Z)
433                 if(doinc(l, f))
434                         return 1;
435         n = n->right;
436         goto loop;
437 }
438
439 void
440 setsp(void)
441 {
442
443         nextpc();
444         p->as = AADJSP;
445         p->from.type = D_CONST;
446         p->from.offset = 0;
447 }
448
449 void
450 adjsp(long o)
451 {
452
453         if(o != 0) {
454                 nextpc();
455                 p->as = AADJSP;
456                 p->from.type = D_CONST;
457                 p->from.offset = o;
458                 argoff += o;
459         }
460 }
461
462 int
463 simplv(Node *n)
464 {
465
466         if(n->addable <= INDEXED)
467                 return 0;
468         while(n->op == OIND)
469                 n = n->left;
470         if(n->op == ONAME)
471                 return 1;
472         return 0;
473 }
474
475 int
476 eval(Node *n, int g)
477 {
478
479         if(n->addable >= INDEXED)
480                 return D_TREE;
481         g = regalloc(n->type, g);
482         cgen(n, g, n);
483         return g;
484 }
485
486 void    outhist(Biobuf*);
487 void    zname(Biobuf*, Sym*, int);
488 void    zaddr(Biobuf*, Adr*, int);
489 void    zwrite(Biobuf*, Prog*, int, int);
490
491 void
492 outcode(void)
493 {
494         struct { Sym *sym; short type; } h[NSYM];
495         Prog *p;
496         Sym *s;
497         int f, sf, st, t, sym;
498         Biobuf b;
499
500         if(debug['S']) {
501                 for(p = firstp; p != P; p = p->link)
502                         if(p->as != ADATA && p->as != AGLOBL)
503                                 pc--;
504                 for(p = firstp; p != P; p = p->link) {
505                         print("%P\n", p);
506                         if(p->as != ADATA && p->as != AGLOBL)
507                                 pc++;
508                 }
509         }
510         f = open(outfile, OWRITE);
511         if(f < 0) {
512                 diag(Z, "cant open %s", outfile);
513                 errorexit();
514         }
515         Binit(&b, f, OWRITE);
516         Bseek(&b, 0L, 2);
517         outhist(&b);
518         for(sym=0; sym<NSYM; sym++) {
519                 h[sym].sym = S;
520                 h[sym].type = 0;
521         }
522         sym = 1;
523         for(p = firstp; p != P; p = p->link) {
524         jackpot:
525                 sf = 0;
526                 s = p->from.sym;
527                 while(s != S) {
528                         sf = s->sym;
529                         if(sf < 0 || sf >= NSYM)
530                                 sf = 0;
531                         t = p->from.type & D_MASK;
532                         if(h[sf].type == t)
533                         if(h[sf].sym == s)
534                                 break;
535                         s->sym = sym;
536                         zname(&b, s, t);
537                         h[sym].sym = s;
538                         h[sym].type = t;
539                         sf = sym;
540                         sym++;
541                         if(sym >= NSYM)
542                                 sym = 1;
543                         break;
544                 }
545                 st = 0;
546                 s = p->to.sym;
547                 while(s != S) {
548                         st = s->sym;
549                         if(st < 0 || st >= NSYM)
550                                 st = 0;
551                         t = p->to.type & D_MASK;
552                         if(h[st].type == t)
553                         if(h[st].sym == s)
554                                 break;
555                         s->sym = sym;
556                         zname(&b, s, t);
557                         h[sym].sym = s;
558                         h[sym].type = t;
559                         st = sym;
560                         sym++;
561                         if(sym >= NSYM)
562                                 sym = 1;
563                         if(st == sf)
564                                 goto jackpot;
565                         break;
566                 }
567                 zwrite(&b, p, sf, st);
568         }
569         Bflush(&b);
570         close(f);
571         firstp = P;
572         lastp = P;
573 }
574
575 void
576 zwrite(Biobuf *b, Prog *p, int sf, int st)
577 {
578         long l;
579
580         l = p->as;
581         Bputc(b, l);
582         Bputc(b, l>>8);
583         l = p->lineno;
584         Bputc(b, l);
585         Bputc(b, l>>8);
586         Bputc(b, l>>16);
587         Bputc(b, l>>24);
588         zaddr(b, &p->from, sf);
589         zaddr(b, &p->to, st);
590 }
591
592 void
593 zname(Biobuf *b, Sym *s, int t)
594 {
595         char *n;
596         ulong sig;
597
598         if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){
599                 sig = sign(s);
600                 Bputc(b, ASIGNAME);
601                 Bputc(b, ASIGNAME>>8);
602                 Bputc(b, sig);
603                 Bputc(b, sig>>8);
604                 Bputc(b, sig>>16);
605                 Bputc(b, sig>>24);
606                 s->sig = SIGDONE;
607         }
608         else{
609                 Bputc(b, ANAME);        /* as */
610                 Bputc(b, ANAME>>8);     /* as */
611         }
612         Bputc(b, t);            /* type */
613         Bputc(b, s->sym);               /* sym */
614         n = s->name;
615         while(*n) {
616                 Bputc(b, *n);
617                 n++;
618         }
619         Bputc(b, 0);
620 }
621
622 void
623 zaddr(Biobuf *b, Adr *a, int s)
624 {
625         long l;
626         int i, t;
627         char *n;
628         Ieee e;
629
630         t = 0;
631         if(a->field)
632                 t |= T_FIELD;
633         if(a->index != D_NONE)
634                 t |= T_INDEX;
635         if(s)
636                 t |= T_SYM;
637
638         switch(a->type) {
639         default:
640                 if(a->offset)
641                         t |= T_OFFSET;
642                 if(a->displace)
643                         t |= T_INDEX;
644                 if(a->type & ~0xff)
645                         t |= T_TYPE;
646                 break;
647         case D_FCONST:
648                 t |= T_FCONST;
649                 break;
650         case D_SCONST:
651                 t |= T_SCONST;
652                 break;
653         }
654         Bputc(b, t);
655
656         if(t & T_FIELD) {       /* implies field */
657                 i = a->field;
658                 Bputc(b, i);
659                 Bputc(b, i>>8);
660         }
661         if(t & T_INDEX) {       /* implies index, scale, displace */
662                 i = a->index;
663                 Bputc(b, i);
664                 Bputc(b, i>>8);
665                 Bputc(b, a->scale);
666                 l = a->displace;
667                 Bputc(b, l);
668                 Bputc(b, l>>8);
669                 Bputc(b, l>>16);
670                 Bputc(b, l>>24);
671         }
672         if(t & T_OFFSET) {      /* implies offset */
673                 l = a->offset;
674                 Bputc(b, l);
675                 Bputc(b, l>>8);
676                 Bputc(b, l>>16);
677                 Bputc(b, l>>24);
678         }
679         if(t & T_SYM)           /* implies sym */
680                 Bputc(b, s);
681         if(t & T_FCONST) {
682                 ieeedtod(&e, a->dval);
683                 l = e.l;
684                 Bputc(b, l);
685                 Bputc(b, l>>8);
686                 Bputc(b, l>>16);
687                 Bputc(b, l>>24);
688                 l = e.h;
689                 Bputc(b, l);
690                 Bputc(b, l>>8);
691                 Bputc(b, l>>16);
692                 Bputc(b, l>>24);
693                 return;
694         }
695         if(t & T_SCONST) {
696                 n = a->sval;
697                 for(i=0; i<NSNAME; i++) {
698                         Bputc(b, *n);
699                         n++;
700                 }
701                 return;
702         }
703         i = a->type;
704         Bputc(b, i);
705         if(t & T_TYPE)
706                 Bputc(b, i>>8);
707 }
708
709
710
711 void
712 outhist(Biobuf *b)
713 {
714         Hist *h;
715         char *p, *q, *op, c;
716         Prog pg;
717         int n;
718
719         pg = zprog;
720         pg.as = AHISTORY;
721         c = pathchar();
722         for(h = hist; h != H; h = h->link) {
723                 p = h->name;
724                 op = 0;
725                 /* on windows skip drive specifier in pathname */
726                 if(systemtype(Windows) && p && p[1] == ':'){
727                         p += 2;
728                         c = *p;
729                 }
730                 if(p && p[0] != c && h->offset == 0 && pathname){
731                         /* on windows skip drive specifier in pathname */
732                         if(systemtype(Windows) && pathname[1] == ':') {
733                                 op = p;
734                                 p = pathname+2;
735                                 c = *p;
736                         } else if(pathname[0] == c){
737                                 op = p;
738                                 p = pathname;
739                         }
740                 }
741                 while(p) {
742                         q = utfrune(p, c);
743                         if(q) {
744                                 n = q-p;
745                                 if(n == 0){
746                                         n = 1;  /* leading "/" */
747                                         *p = '/';       /* don't emit "\" on windows */
748                                 }
749                                 q++;
750                         } else {
751                                 n = strlen(p);
752                                 q = 0;
753                         }
754                         if(n) {
755                                 Bputc(b, ANAME);
756                                 Bputc(b, ANAME>>8);
757                                 Bputc(b, D_FILE);
758                                 Bputc(b, 1);
759                                 Bputc(b, '<');
760                                 Bwrite(b, p, n);
761                                 Bputc(b, 0);
762                         }
763                         p = q;
764                         if(p == 0 && op) {
765                                 p = op;
766                                 op = 0;
767                         }
768                 }
769                 pg.lineno = h->line;
770                 pg.to.type = zprog.to.type;
771                 pg.to.offset = h->offset;
772                 if(h->offset)
773                         pg.to.type = D_CONST;
774
775                 zwrite(b, &pg, 0, 0);
776         }
777 }
778
779 void
780 ieeedtod(Ieee *ieee, double native)
781 {
782         double fr, ho, f;
783         int exp;
784
785         if(native < 0) {
786                 ieeedtod(ieee, -native);
787                 ieee->h |= 0x80000000L;
788                 return;
789         }
790         if(native == 0) {
791                 ieee->l = 0;
792                 ieee->h = 0;
793                 return;
794         }
795         fr = frexp(native, &exp);
796         f = 2097152L;           /* shouldnt use fp constants here */
797         fr = modf(fr*f, &ho);
798         ieee->h = ho;
799         ieee->h &= 0xfffffL;
800         ieee->h |= (exp+1022L) << 20;
801         f = 65536L;
802         fr = modf(fr*f, &ho);
803         ieee->l = ho;
804         ieee->l <<= 16;
805         ieee->l |= (long)(fr*f);
806 }
807
808 int
809 nodalloc(Type *t, int g, Node *n)
810 {
811
812         n->type = t;
813         n->op = OREGISTER;
814         n->addable = 12;
815         n->complex = 0;
816         g = regaddr(g);
817         n->reg = g | I_INDIR;
818         n->xoffset = 0;
819         return g;
820 }
821
822 int
823 mulcon(Node *n, Node *c, int result, Node *nn)
824 {
825         long v;
826
827         if(typefd[n->type->etype])
828                 return 0;
829         v = c->vconst;
830         if(mulcon1(n, v, result, nn))
831                 return 1;
832         return 0;
833 }
834
835 int
836 shlcon(Node *n, Node *c, int result, Node *nn)
837 {
838         long v;
839
840         v = 1L << c->vconst;
841         return mulcon1(n, v, result, nn);
842 }
843
844 int
845 mulcon1(Node *n, long v, int result, Node *nn)
846 {
847         int g, g1, a1, a2, neg;
848         int o;
849         char code[10], *p;
850
851         if(result == D_NONE)
852                 return 0;
853         neg = 0;
854         if(v < 0) {
855                 v = -v;
856                 neg++;
857         }
858         a1 = 0;
859         a2 = multabsize;
860         for(;;) {
861                 if(a1 >= a2)
862                         return 0;
863                 g1 = (a2 + a1)/2;
864                 if(v < multab[g1].val) {
865                         a2 = g1;
866                         continue;
867                 }
868                 if(v > multab[g1].val) {
869                         a1 = g1+1;
870                         continue;
871                 }
872                 break;
873         }
874         strcpy(code, "0");
875         strncat(code, multab[g1].code, sizeof(multab[0].code));
876         p = code;
877         if(p[1] == 'i')
878                 p += 2;
879         g = regalloc(n->type, result);
880         cgen(n, g, n);
881         if(neg)
882                 gopcode(ONEG, n->type, D_NONE, n, g, n);
883         g1 = regalloc(n->type, D_NONE);
884 loop:
885         switch(*p) {
886         case 0:
887                 regfree(g1);
888                 gmove(n->type, nn->type, g, n, result, nn);
889                 regfree(g);
890                 return 1;
891         case '0':
892                 o = OAS;
893                 *p -= '0';
894                 goto com;
895         case '1':
896         case '2':
897                 o = OSUB;
898                 *p -= '1';
899                 goto com;
900         case '3':
901         case '4':
902         case '5':
903         case '6':
904                 o = OADD;
905                 *p -= '3';
906         com:
907                 a1 = g;
908                 if(*p == 1 || *p == 3)
909                         a1 = g1;
910                 a2 = g;
911                 if(*p == 0 || *p == 3)
912                         a2 = g1;
913                 gopcode(o, n->type, a1, n, a2, n);
914                 p++;
915                 break;
916         default:
917                 a1 = *p++ - 'a' + 1;
918                 a2 = g;
919                 if(a1 > 8) {
920                         a2 = g1;
921                         a1 -= 8;
922                 }
923                 gopcode(OASHL, n->type, D_CONST, nodconst(a1), a2, n);
924                 break;
925         }
926         goto loop;
927 }
928
929 void
930 nullwarn(Node *l, Node *r)
931 {
932         warn(Z, "result of operation not used");
933         if(l != Z)
934                 cgen(l, D_NONE, Z);
935         if(r != Z)
936                 cgen(r, D_NONE, Z);
937 }
938
939 void
940 sextern(Sym *s, Node *a, long o, long w)
941 {
942         long e, lw;
943
944         for(e=0; e<w; e+=NSNAME) {
945                 lw = NSNAME;
946                 if(w-e < lw)
947                         lw = w-e;
948                 gpseudo(ADATA, s, D_SCONST, 0L);
949                 p->from.offset += o+e;
950                 p->from.displace = lw;
951                 memmove(p->to.sval, a->cstring+e, lw);
952         }
953 }
954
955 void
956 gextern(Sym *s, Node *a, long o, long w)
957 {
958         if(a->op == OCONST && typev[a->type->etype]) {
959                 gpseudo(ADATA, s, D_CONST, (long)(a->vconst>>32));
960                 p->from.offset += o;
961                 p->from.displace = 4;
962                 gpseudo(ADATA, s, D_CONST, (long)(a->vconst));
963                 p->from.offset += o + 4;
964                 p->from.displace = 4;
965                 return;
966         }
967         gpseudotree(ADATA, s, a);
968         p->from.offset += o;
969         p->from.displace = w;
970 }
971
972 long
973 align(long i, Type *t, int op)
974 {
975         long o;
976         Type *v;
977         int w;
978
979         o = i;
980         w = 1;
981         switch(op) {
982         default:
983                 diag(Z, "unknown align opcode %d", op);
984                 break;
985
986         case Asu2:      /* padding at end of a struct */
987                 w = SZ_LONG;
988                 if(packflg)
989                         w = packflg;
990                 break;
991
992         case Ael1:      /* initial allign of struct element */
993                 for(v=t; v->etype==TARRAY; v=v->link)
994                         ;
995                 w = ewidth[v->etype];
996                 if(w <= 0 || w >= SZ_SHORT)
997                         w = SZ_SHORT;
998                 if(packflg)
999                         w = packflg;
1000                 break;
1001
1002         case Ael2:      /* width of a struct element */
1003                 o += t->width;
1004                 break;
1005
1006         case Aarg0:     /* initial passbyptr argument in arg list */
1007                 if(typesuv[t->etype]) {
1008                         o = align(o, types[TIND], Aarg1);
1009                         o = align(o, types[TIND], Aarg2);
1010                 }
1011                 break;
1012
1013         case Aarg1:     /* initial allign of parameter */
1014                 w = ewidth[t->etype];
1015                 if(w <= 0 || w >= SZ_LONG) {
1016                         w = SZ_LONG;
1017                         break;
1018                 }
1019                 o += SZ_LONG - w;       /* big endian adjustment */
1020                 w = 1;
1021                 break;
1022
1023         case Aarg2:     /* width of a parameter */
1024                 o += t->width;
1025                 w = SZ_LONG;
1026                 break;
1027
1028         case Aaut3:     /* total allign of automatic */
1029                 o = align(o, t, Ael1);
1030                 o = align(o, t, Ael2);
1031                 break;
1032         }
1033         o = round(o, w);
1034         if(debug['A'])
1035                 print("align %s %ld %T = %ld\n", bnames[op], i, t, o);
1036         return o;
1037 }
1038
1039 long
1040 maxround(long max, long v)
1041 {
1042         v += SZ_LONG-1;
1043         if(v > max)
1044                 max = round(v, SZ_LONG);
1045         return max;
1046 }