]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/7l/span.c
grep: error if sbrk fails
[plan9front.git] / sys / src / cmd / 7l / span.c
1 #include        "l.h"
2
3 #define BIT(n)  ((uvlong)1<<(n))
4
5 static struct {
6         ulong   start;
7         ulong   size;
8 } pool;
9
10 static void     checkpool(Prog*, int);
11 static void     flushpool(Prog*, int);
12 static int      ispcdisp(long);
13
14 static Optab *badop;
15 static Oprang   oprange[ALAST];
16
17 void
18 span(void)
19 {
20         Prog *p;
21         Sym *setext, *s;
22         Optab *o;
23         int m, bflag, i;
24         long c, otxt, v;
25
26         if(debug['v'])
27                 Bprint(&bso, "%5.2f span\n", cputime());
28         Bflush(&bso);
29
30         bflag = 0;
31         c = INITTEXT;
32         otxt = c;
33         for(p = firstp; p != P; p = p->link) {
34                 if(p->as == ADWORD && (c&7) != 0)
35                         c += 4;
36                 p->pc = c;
37                 o = oplook(p);
38                 m = o->size;
39                 if(m == 0) {
40                         if(p->as == ATEXT) {
41                                 curtext = p;
42                                 autosize = p->to.offset + PCSZ;
43                                 if(p->from.sym != S)
44                                         p->from.sym->value = c;
45                                 /* need passes to resolve branches */
46                                 if(c-otxt >= 1L<<20)
47                                         bflag = 1;
48                                 otxt = c;
49                                 continue;
50                         }
51                         diag("zero-width instruction\n%P", p);
52                         continue;
53                 }
54                 switch(o->flag & (LFROM|LTO)) {
55                 case LFROM:
56                         addpool(p, &p->from);
57                         break;
58                 case LTO:
59                         addpool(p, &p->to);
60                         break;
61                 }
62                 if(p->as == AB || p->as == ARET || p->as == AERET || p->as == ARETURN)  /* TO DO: other unconditional operations */
63                         checkpool(p, 0);
64                 c += m;
65                 if(blitrl)
66                         checkpool(p, 1);
67         }
68
69         /*
70          * if any procedure is large enough to
71          * generate a large SBRA branch, then
72          * generate extra passes putting branches
73          * around jmps to fix. this is rare.
74          */
75         while(bflag) {
76                 if(debug['v'])
77                         Bprint(&bso, "%5.2f span1\n", cputime());
78                 bflag = 0;
79                 c = INITTEXT;
80                 for(p = firstp; p != P; p = p->link) {
81                         if(p->as == ADWORD && (c&7) != 0)
82                                 c += 4;
83                         p->pc = c;
84                         o = oplook(p);
85 /* very large branches
86                         if(o->type == 6 && p->cond) {
87                                 otxt = p->cond->pc - c;
88                                 if(otxt < 0)
89                                         otxt = -otxt;
90                                 if(otxt >= (1L<<17) - 10) {
91                                         q = prg();
92                                         q->link = p->link;
93                                         p->link = q;
94                                         q->as = AB;
95                                         q->to.type = D_BRANCH;
96                                         q->cond = p->cond;
97                                         p->cond = q;
98                                         q = prg();
99                                         q->link = p->link;
100                                         p->link = q;
101                                         q->as = AB;
102                                         q->to.type = D_BRANCH;
103                                         q->cond = q->link->link;
104                                         bflag = 1;
105                                 }
106                         }
107  */
108                         m = o->size;
109                         if(m == 0) {
110                                 if(p->as == ATEXT) {
111                                         curtext = p;
112                                         autosize = p->to.offset + PCSZ;
113                                         if(p->from.sym != S)
114                                                 p->from.sym->value = c;
115                                         continue;
116                                 }
117                                 diag("zero-width instruction\n%P", p);
118                                 continue;
119                         }
120                         c += m;
121                 }
122         }
123
124         if(debug['t']) {
125                 /* 
126                  * add strings to text segment
127                  */
128                 c = rnd(c, 8);
129                 for(i=0; i<NHASH; i++)
130                 for(s = hash[i]; s != S; s = s->link) {
131                         if(s->type != SSTRING)
132                                 continue;
133                         v = s->value;
134                         while(v & 3)
135                                 v++;
136                         s->value = c;
137                         c += v;
138                 }
139         }
140
141         c = rnd(c, 8);
142
143         setext = lookup("etext", 0);
144         if(setext != S) {
145                 setext->value = c;
146                 textsize = c - INITTEXT;
147         }
148         if(INITRND)
149                 INITDAT = rnd(c, INITRND);
150         if(debug['v'])
151                 Bprint(&bso, "tsize = %#llux\n", textsize);
152         Bflush(&bso);
153 }
154
155 /*
156  * when the first reference to the literal pool threatens
157  * to go out of range of a 1Mb PC-relative offset
158  * drop the pool now, and branch round it.
159  */
160 static void
161 checkpool(Prog *p, int skip)
162 {
163         if(pool.size >= 0xffff0 || !ispcdisp(p->pc+4+pool.size - pool.start+8))
164                 flushpool(p, skip);
165         else if(p->link == P)
166                 flushpool(p, 2);
167 }
168
169 static void
170 flushpool(Prog *p, int skip)
171 {
172         Prog *q;
173
174         if(blitrl) {
175                 if(skip){
176                         if(debug['v'] && skip == 1)
177                                 print("note: flush literal pool at %#llux: len=%lud ref=%lux\n", p->pc+4, pool.size, pool.start);
178                         q = prg();
179                         q->as = AB;
180                         q->to.type = D_BRANCH;
181                         q->cond = p->link;
182                         q->link = blitrl;
183                         blitrl = q;
184                 }
185                 else if(p->pc+pool.size-pool.start < 1024*1024)
186                         return;
187                 elitrl->link = p->link;
188                 p->link = blitrl;
189                 blitrl = 0;     /* BUG: should refer back to values until out-of-range */
190                 elitrl = 0;
191                 pool.size = 0;
192                 pool.start = 0;
193         }
194 }
195
196 /*
197  * TO DO: hash
198  */
199 void
200 addpool(Prog *p, Adr *a)
201 {
202         Prog *q, t;
203         int sz;
204
205
206         t = zprg;
207         t.as = AWORD;
208         sz = 4;
209         switch(aclass(a)) {
210         default:
211                 if(p->as == AMOV && (a->name == D_EXTERN || a->name == D_STATIC)
212                 || (a->offset >> 32) != 0 && (a->offset >> 31) != -1){
213                         t.as = ADWORD;
214                         sz = 8;
215                 }
216                 t.to = *a;
217                 break;
218         case C_PSAUTO:
219         case C_PPAUTO:
220         case C_UAUTO4K:
221         case C_UAUTO8K:
222         case C_UAUTO16K:
223         case C_UAUTO32K:
224         case C_UAUTO64K:
225         case C_NSAUTO:
226         case C_NPAUTO:
227         case C_LAUTO:
228         case C_PPOREG:
229         case C_PSOREG:
230         case C_UOREG4K:
231         case C_UOREG8K:
232         case C_UOREG16K:
233         case C_UOREG32K:
234         case C_UOREG64K:
235         case C_NSOREG:
236         case C_NPOREG:
237         case C_LOREG:
238         case C_LACON:
239                 if((instoffset >> 32) != 0 && (instoffset >> 31) != -1)
240                         diag("offset too large\n%P", p);
241                 t.to.type = D_CONST;
242                 t.to.offset = instoffset;
243                 break;
244         }
245
246         for(q = blitrl; q != P; q = q->link)    /* could hash on t.t0.offset */
247                 if(memcmp(&q->to, &t.to, sizeof(t.to)) == 0) {
248                         p->cond = q;
249                         return;
250                 }
251
252         q = prg();
253         *q = t;
254         q->pc = pool.size;
255
256         if(blitrl == P) {
257                 blitrl = q;
258                 pool.start = p->pc;
259         } else
260                 elitrl->link = q;
261         elitrl = q;
262         pool.size = rnd(pool.size, sz);
263         pool.size += sz;
264
265         p->cond = q;
266 }
267
268 int
269 relinv(int a)
270 {
271         switch(a) {
272         case ABEQ:      return ABNE;
273         case ABNE:      return ABEQ;
274         case ABCS:      return ABCC;
275         case ABHS:      return ABLO;
276         case ABCC:      return ABCS;
277         case ABLO:      return ABHS;
278         case ABMI:      return ABPL;
279         case ABPL:      return ABMI;
280         case ABVS:      return ABVC;
281         case ABVC:      return ABVS;
282         case ABHI:      return ABLS;
283         case ABLS:      return ABHI;
284         case ABGE:      return ABLT;
285         case ABLT:      return ABGE;
286         case ABGT:      return ABLE;
287         case ABLE:      return ABGT;
288         }
289         diag("unknown relation: %A", a);
290         return a;
291 }
292
293 void
294 xdefine(char *p, int t, long v)
295 {
296         Sym *s;
297
298         s = lookup(p, 0);
299         if(s->type == 0 || s->type == SXREF) {
300                 s->type = t;
301                 s->value = v;
302         }
303 }
304
305 long
306 regoff(Adr *a)
307 {
308
309         instoffset = 0;
310         aclass(a);
311         return instoffset;
312 }
313
314 static int
315 ispcdisp(long v)
316 {
317         /* pc-relative addressing will reach? */
318         return v >= -0xfffff && v <= 0xfffff && (v&3) == 0;
319 }
320
321 static int
322 isaddcon(vlong v)
323 {
324         /* uimm12 or uimm24? */
325         if(v < 0)
326                 return 0;
327         if((v & 0xFFF) == 0)
328                 v >>= 12;
329         return v <= 0xFFF;
330 }
331
332 static int
333 isbitcon64(uvlong v)
334 {
335         return findmask(v) != nil;
336 }
337
338 static int
339 isbitcon32(uvlong v)
340 {
341         return (v >> 32) == 0 && findmask(v | v<<32) != nil;
342 }
343
344 static int
345 isbitcon(uvlong v)
346 {
347         Mask *m;
348
349         if((v >> 32) != 0)
350                 return 0;
351         m = findmask(v);
352         if(m == nil)
353                 return 0;
354         if(m->s >= 32)
355                 return 0;
356         return 1;
357 }
358
359 static int
360 maxstr1(uvlong x)
361 {
362         int i;
363
364         for(i = 0; x != 0; i++)
365                 x &= x<<1;
366         return i;
367 }
368
369 static uvlong
370 findrotl(uvlong x, int *l)
371 {
372         int i;
373
374         for(i = 0; (x&1) == 0 || (x&BIT(63)) != 0; i++)
375                 x = (x<<1) | ((x&BIT(63))!=0);
376         *l = i;
377         return x;
378 }
379
380 static int
381 findmask64(Mask *m, uvlong v)
382 {
383         uvlong x, f, fm;
384         int i, lr, l0, l1, e;
385
386         if(v == 0 || v == ~(uvlong)0)
387                 return 0;
388         x = findrotl(v, &lr);
389         l1 = maxstr1(x);
390         l0 = maxstr1(~x);
391         e = l0+l1;
392         if(e == 0 || l1 == 64 || l0 == 64 || 64%e != 0)
393                 return 0;
394         if(e != 64){
395                 f = BIT(l1)-1;
396                 fm = BIT(e)-1;
397                 if(e > 32 && x != f)
398                         return 0;
399                 for(i = 0; i < 64; i += e)
400                         if(((x>>i) & fm) != f)
401                                 return 0;
402         }
403         print("%#llux   %#llux 1:%d 0:%d r:%d\n", v, x, l1, l0, lr%e);
404         m->v = v;
405         m->s = l1;
406         m->e = e;
407         m->r = lr%e;
408         return 1;
409 }
410
411 /*
412  * internal class codes for different constant classes:
413  * they partition the constant/offset range into disjoint ranges that
414  * are somehow treated specially by one or more load/store instructions.
415  */
416 static int      autoclass[] = {C_PSAUTO, C_NSAUTO, C_NPAUTO, C_PSAUTO, C_PPAUTO, C_UAUTO4K, C_UAUTO8K, C_UAUTO16K, C_UAUTO32K, C_UAUTO64K, C_LAUTO};
417 static int      oregclass[] = {C_ZOREG, C_NSOREG, C_NPOREG, C_PSOREG, C_PPOREG, C_UOREG4K, C_UOREG8K, C_UOREG16K, C_UOREG32K, C_UOREG64K, C_LOREG};
418 static int      sextclass[] = {C_SEXT1, C_LEXT, C_LEXT, C_SEXT1, C_SEXT1, C_SEXT1, C_SEXT2, C_SEXT4, C_SEXT8, C_SEXT16, C_LEXT};
419
420 /*
421  * return appropriate index into tables above
422  */
423 static int
424 constclass(vlong l)
425 {
426         if(l == 0)
427                 return 0;
428         if(l < 0){
429                 if(l >= -256)
430                         return 1;
431                 if(l >= -512 && (l&7) == 0)
432                         return 2;
433                 return 10;
434         }
435         if(l <= 255)
436                 return 3;
437         if(l <= 504 && (l&7) == 0)
438                 return 4;
439         if(l <= 4095)
440                 return 5;
441         if(l <= 8190 && (l&1) == 0)
442                 return 6;
443         if(l <= 16380 && (l&3) == 0)
444                 return 7;
445         if(l <= 32760 && (l&7) == 0)
446                 return 8;
447         if(l <= 65520 && (l&0xF) == 0)
448                 return 9;
449         return 10;
450 }
451
452 /*
453  * given an offset v and a class c (see above)
454  * return the offset value to use in the instruction,
455  * scaled if necessary
456  */
457 vlong
458 offsetshift(vlong v, int c)
459 {
460         vlong vs;
461         int s;
462         static int shifts[] = {0, 1, 2, 3, 4};
463
464         s = 0;
465         if(c >= C_SEXT1 && c <= C_SEXT16)
466                 s = shifts[c-C_SEXT1];
467         else if(c >= C_UAUTO4K && c <= C_UAUTO64K)
468                 s = shifts[c-C_UAUTO4K];
469         else if(c >= C_UOREG4K && c <= C_UOREG64K)
470                 s = shifts[c-C_UOREG4K];
471         vs = v>>s;
472         if(vs<<s != v)
473                 diag("odd offset: %lld\n%P", v, curp);
474         return vs;
475 }
476
477 /*
478  * if v contains a single 16-bit value aligned
479  * on a 16-bit field, and thus suitable for movk/movn,
480  * return the field index 0 to 3; otherwise return -1
481  */
482 int
483 movcon(vlong v)
484 {
485         int s;
486
487         for(s = 0; s < 64; s += 16)
488                 if((v & ~((uvlong)0xFFFF<<s)) == 0)
489                         return s/16;
490         return -1;
491 }
492
493 int
494 aclass(Adr *a)
495 {
496         vlong v;
497         Sym *s;
498         int t;
499
500         instoffset = 0;
501         switch(a->type) {
502         case D_NONE:
503                 return C_NONE;
504
505         case D_REG:
506                 return C_REG;
507
508         case D_VREG:
509                 return C_VREG;
510
511         case D_SP:
512                 return C_RSP;
513
514         case D_COND:
515                 return C_COND;
516
517         case D_SHIFT:
518                 return C_SHIFT;
519
520         case D_EXTREG:
521                 return C_EXTREG;
522
523         case D_ROFF:
524                 return C_ROFF;
525
526         case D_XPOST:
527                 return C_XPOST;
528
529         case D_XPRE:
530                 return C_XPRE;
531
532         case D_FREG:
533                 return C_FREG;
534
535         case D_OREG:
536                 switch(a->name) {
537                 case D_EXTERN:
538                 case D_STATIC:
539                         if(a->sym == 0 || a->sym->name == 0) {
540                                 print("null sym external\n");
541                                 print("%D\n", a);
542                                 return C_GOK;
543                         }
544                         s = a->sym;
545                         t = s->type;
546                         if(t == 0 || t == SXREF) {
547                                 diag("undefined external: %s in %s",
548                                         s->name, TNAME);
549                                 s->type = SDATA;
550                         }
551                         if(dlm) {
552                                 switch(t) {
553                                 default:
554                                         instoffset = s->value + a->offset + INITDAT;
555                                         break;
556                                 case SUNDEF:
557                                 case STEXT:
558                                 case SCONST:
559                                 case SLEAF:
560                                 case SSTRING:
561                                         instoffset = s->value + a->offset;
562                                         break;
563                                 }
564                                 return C_ADDR;
565                         }
566                         instoffset = s->value + a->offset;
567                         if(instoffset >= 0)
568                                 return sextclass[constclass(instoffset)];
569                         return C_LEXT;
570
571                 case D_AUTO:
572                         instoffset = autosize + a->offset;
573                         return autoclass[constclass(instoffset)];
574
575                 case D_PARAM:
576                         instoffset = autosize + a->offset + PCSZ;
577                         return autoclass[constclass(instoffset)];
578
579                 case D_NONE:
580                         instoffset = a->offset;
581                         return oregclass[constclass(instoffset)];
582                 }
583                 return C_GOK;
584
585         case D_SPR:
586                 return C_SPR;
587
588         case D_OCONST:
589                 switch(a->name) {
590                 case D_EXTERN:
591                 case D_STATIC:
592                         s = a->sym;
593                         t = s->type;
594                         if(t == 0 || t == SXREF) {
595                                 diag("undefined external: %s in %s",
596                                         s->name, TNAME);
597                                 s->type = SDATA;
598                         }
599                         instoffset = s->value + a->offset + INITDAT;
600                         if(s->type == STEXT || s->type == SLEAF || s->type == SUNDEF)
601                                 instoffset = s->value + a->offset;
602                         return C_LCON;
603                 }
604                 return C_GOK;
605
606         case D_FCONST:
607                 return C_FCON;
608
609         case D_CONST:
610                 switch(a->name) {
611
612                 case D_NONE:
613                         instoffset = a->offset;
614                         if(a->reg != NREG && a->reg != REGZERO)
615                                 goto aconsize;
616
617                         v = instoffset;
618                         if(v == 0)
619                                 return C_ZCON;
620                         if(isaddcon(v)){
621                                 if(isbitcon(v))
622                                         return C_ABCON;
623                                 if(v <= 0xFFF)
624                                         return C_ADDCON0;
625                                 return C_ADDCON;
626                         }
627                         t = movcon(v);
628                         if(t >= 0){
629                                 if(isbitcon(v))
630                                         return C_MBCON;
631                                 return C_MOVCON;
632                         }
633                         t = movcon(~v);
634                         if(t >= 0){
635                                 if(isbitcon(v))
636                                         return C_MBCON;
637                                 return C_MOVCON;
638                         }
639                         if(isbitcon(v))
640                                 return C_BITCON;
641                         if(isbitcon64(v))
642                                 return C_BITCON64;
643                         if(isbitcon32(v))
644                                 return C_BITCON32;
645                         return C_LCON;
646
647                 case D_EXTERN:
648                 case D_STATIC:
649                         s = a->sym;
650                         if(s == S)
651                                 break;
652                         t = s->type;
653                         switch(t) {
654                         case 0:
655                         case SXREF:
656                                 diag("undefined external: %s in %s",
657                                         s->name, TNAME);
658                                 s->type = SDATA;
659                                 break;
660                         case SUNDEF:
661                         case STEXT:
662                         case SSTRING:
663                         case SCONST:
664                         case SLEAF:
665                                 instoffset = s->value + a->offset;
666                                 return C_LCON;
667                         }
668                         if(!dlm) {
669                                 instoffset = s->value + a->offset;
670                                 if(instoffset != 0 && isaddcon(instoffset))
671                                         return C_AECON;
672                         }
673                         instoffset = s->value + a->offset + INITDAT;
674                         return C_LCON;
675
676                 case D_AUTO:
677                         instoffset = autosize + a->offset;
678                         goto aconsize;
679
680                 case D_PARAM:
681                         instoffset = autosize + a->offset + PCSZ;
682                 aconsize:
683                         if(isaddcon(instoffset))
684                                 return C_AACON;
685                         return C_LACON;
686                 }
687                 return C_GOK;
688
689         case D_BRANCH:
690                 return C_SBRA;
691         }
692         return C_GOK;
693 }
694
695 Optab*
696 oplook(Prog *p)
697 {
698         int a1, a2, a3, r;
699         char *c1, *c2, *c3;
700         Optab *o, *e;
701
702         a1 = p->optab;
703         if(a1)
704                 return optab+(a1-1);
705         a1 = p->from.class;
706         if(a1 == 0) {
707                 a1 = aclass(&p->from) + 1;
708                 p->from.class = a1;
709         }
710         a1--;
711         a3 = p->to.class;
712         if(a3 == 0) {
713                 a3 = aclass(&p->to) + 1;
714                 p->to.class = a3;
715         }
716         a3--;
717         a2 = C_NONE;
718         if(p->reg != NREG)
719                 a2 = C_REG;
720         r = p->as;
721         o = oprange[r].start;
722         if(o == 0) {
723                 a1 = opcross[repop[r]][a1][a2][a3];
724                 if(a1) {
725                         p->optab = a1+1;
726                         return optab+a1;
727                 }
728                 o = oprange[r].stop; /* just generate an error */
729         }
730         if(0) {
731                 print("oplook %A %d %d %d\n",
732                         (int)p->as, a1, a2, a3);
733                 print("         %d %d\n", p->from.type, p->to.type);
734         }
735         e = oprange[r].stop;
736         c1 = xcmp[a1];
737         c2 = xcmp[a2];
738         c3 = xcmp[a3];
739         for(; o<e; o++)
740                 if(o->a2 == a2 || c2[o->a2])
741                 if(c1[o->a1])
742                 if(c3[o->a3]) {
743                         if(0)
744                                 print("%P\t-> %d (%d %d %d)\n", p, o->type,
745                                         o->a1, o->a2, o->a3);
746                         p->optab = (o-optab)+1;
747                         return o;
748                 }
749         diag("illegal combination %A %R %R %R",
750                 p->as, a1, a2, a3);
751         prasm(p);
752         o = badop;
753         if(o == 0)
754                 errorexit();
755         return o;
756 }
757
758 int
759 cmp(int a, int b)
760 {
761
762         if(a == b)
763                 return 1;
764         switch(a) {
765         case C_RSP:
766                 if(b == C_REG)
767                         return 1;
768                 break;
769
770         case C_REG:
771                 if(b == C_ZCON)
772                         return 1;
773                 break;
774
775         case C_ADDCON0:
776                 if(b == C_ZCON)
777                         return 1;
778                 break;
779
780         case C_ADDCON:
781                 if(b == C_ZCON || b == C_ADDCON0 || b == C_ABCON)
782                         return 1;
783                 break;
784
785         case C_BITCON32:
786         case C_BITCON64:
787                 if(b == C_BITCON)
788                         return 1;
789                 /* wet floor */
790         case C_BITCON:
791                 if(b == C_ABCON || b == C_MBCON)
792                         return 1;
793                 break;
794
795         case C_MOVCON:
796                 if(b == C_MBCON || b == C_ZCON || b == C_ADDCON0)
797                         return 1;
798                 break;
799
800         case C_LCON:
801                 if(b == C_ZCON || b == C_BITCON || b == C_BITCON32 || b == C_BITCON64 || b == C_ADDCON || b == C_ADDCON0 || b == C_ABCON || b == C_MBCON || b == C_MOVCON)
802                         return 1;
803                 break;
804
805         case C_VCON:
806                 return cmp(C_LCON, b);
807
808         case C_LACON:
809                 if(b == C_AACON)
810                         return 1;
811                 break;
812
813         case C_SEXT2:
814                 if(b == C_SEXT1)
815                         return 1;
816                 break;
817
818         case C_SEXT4:
819                 if(b == C_SEXT1 || b == C_SEXT2)
820                         return 1;
821                 break;
822
823         case C_SEXT8:
824                 if(b >= C_SEXT1 && b <= C_SEXT4)
825                         return 1;
826                 break;
827
828         case C_SEXT16:
829                 if(b >= C_SEXT1 && b <= C_SEXT8)
830                         return 1;
831                 break;
832
833         case C_LEXT:
834                 if(b >= C_SEXT1 && b <= C_SEXT16)
835                         return 1;
836                 break;
837
838         case C_PPAUTO:
839                 if(b == C_PSAUTO)
840                         return 1;
841                 break;
842
843         case C_UAUTO4K:
844                 if(b == C_PSAUTO || b == C_PPAUTO)
845                         return 1;
846                 break;
847
848         case C_UAUTO8K:
849                 return cmp(C_UAUTO4K, b);
850
851         case C_UAUTO16K:
852                 return cmp(C_UAUTO8K, b);
853
854         case C_UAUTO32K:
855                 return cmp(C_UAUTO16K, b);
856
857         case C_UAUTO64K:
858                 return cmp(C_UAUTO32K, b);
859
860         case C_NPAUTO:
861                 return cmp(C_NSAUTO, b);
862
863         case C_LAUTO:
864                 return cmp(C_NPAUTO, b) || cmp(C_UAUTO64K, b);
865
866         case C_PSOREG:
867                 if(b == C_ZOREG)
868                         return 1;
869                 break;
870
871         case C_PPOREG:
872                 if(b == C_ZOREG || b == C_PSOREG)
873                         return 1;
874                 break;
875
876         case C_UOREG4K:
877                 if(b == C_ZOREG || b == C_PSAUTO || b == C_PSOREG || b == C_PPAUTO || b == C_PPOREG)
878                         return 1;
879                 break;
880
881         case C_UOREG8K:
882                 return cmp(C_UOREG4K, b);
883
884         case C_UOREG16K:
885                 return cmp(C_UOREG8K, b);
886
887         case C_UOREG32K:
888                 return cmp(C_UOREG16K, b);
889
890         case C_UOREG64K:
891                 return cmp(C_UOREG32K, b);
892
893         case C_NPOREG:
894                 return cmp(C_NSOREG, b);
895
896         case C_LOREG:
897                 return cmp(C_NPOREG, b) || cmp(C_UOREG64K, b);
898
899         case C_LBRA:
900                 if(b == C_SBRA)
901                         return 1;
902                 break;
903         }
904         return 0;
905 }
906
907 static int
908 ocmp(const void *a1, const void *a2)
909 {
910         Optab *p1, *p2;
911         int n;
912
913         p1 = (Optab*)a1;
914         p2 = (Optab*)a2;
915         n = p1->as - p2->as;
916         if(n)
917                 return n;
918         n = p1->a1 - p2->a1;
919         if(n)
920                 return n;
921         n = p1->a2 - p2->a2;
922         if(n)
923                 return n;
924         n = p1->a3 - p2->a3;
925         if(n)
926                 return n;
927         return 0;
928 }
929
930 void
931 buildop(void)
932 {
933         int i, n, r;
934         Oprang t;
935
936         for(i=0; i<C_GOK; i++)
937                 for(n=0; n<C_GOK; n++)
938                         xcmp[i][n] = cmp(n, i);
939         for(n=0; optab[n].as != AXXX; n++)
940                 ;
941         badop = optab+n;
942         qsort(optab, n, sizeof(optab[0]), ocmp);
943         for(i=0; i<n; i++) {
944                 r = optab[i].as;
945                 oprange[r].start = optab+i;
946                 while(optab[i].as == r)
947                         i++;
948                 oprange[r].stop = optab+i;
949                 i--;
950
951                 t = oprange[r];
952                 switch(r){
953                 default:
954                         diag("unknown op in build: %A", r);
955                         errorexit();
956                 case AXXX:
957                         break;
958                 case AADD:
959                         oprange[AADDS] = t;
960                         oprange[ASUB] = t;
961                         oprange[ASUBS] = t;
962                         oprange[AADDW] = t;
963                         oprange[AADDSW] = t;
964                         oprange[ASUBW] = t;
965                         oprange[ASUBSW] = t;
966                         break;
967                 case AAND:      /* logical immediate, logical shifted register */
968                         oprange[AANDS] = t;
969                         oprange[AEOR] = t;
970                         oprange[AORR] = t;
971                         break;
972                 case AANDW:
973                         oprange[AANDSW] = t;
974                         oprange[AANDW] = t;
975                         oprange[AEORW] = t;
976                         oprange[AORRW] = t;
977                         break;
978                 case ABIC:      /* only logical shifted register */
979                         oprange[ABICS] = t;
980                         oprange[AEON] = t;
981                         oprange[AORN] = t;
982                         break;
983                 case ABICW:
984                         oprange[ABICSW] = t;
985                         oprange[ABICW] = t;
986                         oprange[AEONW] = t;
987                         oprange[AORNW] = t;
988                         break;
989                 case ANEG:
990                         oprange[ANEGS] = t;
991                         oprange[ANEGSW] = t;
992                         oprange[ANEGW] = t;
993                         break;
994                 case AADC:      /* rn=Rd */
995                         oprange[AADCW] = t;
996                         oprange[AADCS] = t;
997                         oprange[AADCSW] = t;
998                         oprange[ASBC] = t;
999                         oprange[ASBCW] = t;
1000                         oprange[ASBCS] = t;
1001                         oprange[ASBCSW] = t;
1002                         break;
1003                 case ANGC:      /* rn=REGZERO */
1004                         oprange[ANGCW] = t;
1005                         oprange[ANGCS] = t;
1006                         oprange[ANGCSW] = t;
1007                         break;
1008                 case ACMP:
1009                         oprange[ACMPW] = t;
1010                         oprange[ACMN] = t;
1011                         oprange[ACMNW] = t;
1012                         break;
1013                 case ATST:
1014                         oprange[ATSTW] = t;
1015                         break;
1016                 case AMVN:
1017                         /* register/register, and shifted */
1018                         oprange[AMVNW] = t;
1019                         break;
1020                 case AMOVK:
1021                         oprange[AMOVKW] = t;
1022                         oprange[AMOVN] = t;
1023                         oprange[AMOVNW] = t;
1024                         oprange[AMOVZ] = t;
1025                         oprange[AMOVZW] = t;
1026                         break;
1027                 case ABEQ:
1028                         oprange[ABNE] = t;
1029                         oprange[ABCS] = t;
1030                         oprange[ABHS] = t;
1031                         oprange[ABCC] = t;
1032                         oprange[ABLO] = t;
1033                         oprange[ABMI] = t;
1034                         oprange[ABPL] = t;
1035                         oprange[ABVS] = t;
1036                         oprange[ABVC] = t;
1037                         oprange[ABHI] = t;
1038                         oprange[ABLS] = t;
1039                         oprange[ABGE] = t;
1040                         oprange[ABLT] = t;
1041                         oprange[ABGT] = t;
1042                         oprange[ABLE] = t;
1043                         break;
1044                 case ALSL:
1045                         oprange[ALSLW] = t;
1046                         oprange[ALSR] = t;
1047                         oprange[ALSRW] = t;
1048                         oprange[AASR] = t;
1049                         oprange[AASRW] = t;
1050                         oprange[AROR] = t;
1051                         oprange[ARORW] = t;
1052                         break;
1053                 case ACLS:
1054                         oprange[ACLSW] = t;
1055                         oprange[ACLZ] = t;
1056                         oprange[ACLZW] = t;
1057                         oprange[ARBIT] = t;
1058                         oprange[ARBITW] = t;
1059                         oprange[AREV] = t;
1060                         oprange[AREVW] = t;
1061                         oprange[AREV16] = t;
1062                         oprange[AREV16W] = t;
1063                         oprange[AREV32] = t;
1064                         break;
1065                 case ASDIV:
1066                         oprange[ASDIVW] = t;
1067                         oprange[AUDIV] = t;
1068                         oprange[AUDIVW] = t;
1069                         oprange[ACRC32B] = t;
1070                         oprange[ACRC32CB] = t;
1071                         oprange[ACRC32CH] = t;
1072                         oprange[ACRC32CW] = t;
1073                         oprange[ACRC32CX] = t;
1074                         oprange[ACRC32H] = t;
1075                         oprange[ACRC32W] = t;
1076                         oprange[ACRC32X] = t;
1077                         break;
1078                 case AMADD:
1079                         oprange[AMADDW] = t;
1080                         oprange[AMSUB] = t;
1081                         oprange[AMSUBW] = t;
1082                         oprange[ASMADDL] = t;
1083                         oprange[ASMSUBL] = t;
1084                         oprange[AUMADDL] = t;
1085                         oprange[AUMSUBL] = t;
1086                         break;
1087                 case AREM:
1088                         oprange[AREMW] = t;
1089                         oprange[AUREM] = t;
1090                         oprange[AUREMW] = t;
1091                         break;
1092                 case AMUL:
1093                         oprange[AMULW] = t;
1094                         oprange[AMNEG] = t;
1095                         oprange[AMNEGW] = t;
1096                         oprange[ASMNEGL] = t;
1097                         oprange[ASMULL] = t;
1098                         oprange[ASMULH] = t;
1099                         oprange[AUMNEGL] = t;
1100                         oprange[AUMULH] = t;
1101                         oprange[AUMULL] = t;
1102                         break;
1103                 case AMOVH:
1104                         oprange[AMOVHU] = t;
1105                         break;
1106                 case AMOVW:
1107                         oprange[AMOVWU] = t;
1108                         break;
1109                 case ABFM:
1110                         oprange[ABFMW] = t;
1111                         oprange[ASBFM] = t;
1112                         oprange[ASBFMW] = t;
1113                         oprange[AUBFM] = t;
1114                         oprange[AUBFMW] = t;
1115                         break;
1116                 case ABFI:
1117                         oprange[ABFIW] = t;
1118                         oprange[ABFXIL] = t;
1119                         oprange[ABFXILW] = t;
1120                         oprange[ASBFIZ] = t;
1121                         oprange[ASBFIZW] = t;
1122                         oprange[ASBFX] = t;
1123                         oprange[ASBFXW] = t;
1124                         oprange[AUBFIZ] = t;
1125                         oprange[AUBFIZW] = t;
1126                         oprange[AUBFX] = t;
1127                         oprange[AUBFXW] = t;
1128                         break;
1129                 case AEXTR:
1130                         oprange[AEXTRW] = t;
1131                         break;
1132                 case ASXTB:
1133                         oprange[ASXTBW] = t;
1134                         oprange[ASXTH] = t;
1135                         oprange[ASXTHW] = t;
1136                         oprange[ASXTW] = t;
1137                         oprange[AUXTB] = t;
1138                         oprange[AUXTH] = t;
1139                         oprange[AUXTW] = t;
1140                         oprange[AUXTBW] = t;
1141                         oprange[AUXTHW] = t;
1142                         break;
1143                 case ACCMN:
1144                         oprange[ACCMNW] = t;
1145                         oprange[ACCMP] = t;
1146                         oprange[ACCMPW] = t;
1147                         break;
1148                 case ACSEL:
1149                         oprange[ACSELW] = t;
1150                         oprange[ACSINC] = t;
1151                         oprange[ACSINCW] = t;
1152                         oprange[ACSINV] = t;
1153                         oprange[ACSINVW] = t;
1154                         oprange[ACSNEG] = t;
1155                         oprange[ACSNEGW] = t;
1156                         // aliases Rm=Rn, !cond
1157                         oprange[ACINC] = t;
1158                         oprange[ACINCW] = t;
1159                         oprange[ACINV] = t;
1160                         oprange[ACINVW] = t;
1161                         oprange[ACNEG] = t;
1162                         oprange[ACNEGW] = t;
1163                         break;
1164                 case ACSET:
1165                         // aliases, Rm=Rn=REGZERO, !cond
1166                         oprange[ACSETW] = t;
1167                         oprange[ACSETM] = t;
1168                         oprange[ACSETMW] = t;
1169                         break;
1170                 case AMOV:
1171                 case AMOVB:
1172                 case AMOVBU:
1173                 case AB:
1174                 case ABL:
1175                 case AWORD:
1176                 case ADWORD:
1177                 case ARET:
1178                 case ATEXT:
1179                 case ACASE:
1180                 case ABCASE:
1181                         break;
1182                 case AERET:
1183                         oprange[ANOP] = t;
1184                         oprange[AWFE] = t;
1185                         oprange[AWFI] = t;
1186                         oprange[AYIELD] = t;
1187                         oprange[ASEV] = t;
1188                         oprange[ASEVL] = t;
1189                         oprange[ADRPS] = t;
1190                         break;
1191                 case ACBZ:
1192                         oprange[ACBZW] = t;
1193                         oprange[ACBNZ] = t;
1194                         oprange[ACBNZW] = t;
1195                         break;
1196                 case ATBZ:
1197                         oprange[ATBNZ] = t;
1198                         break;
1199                 case AADR:
1200                 case AADRP:
1201                         break;
1202                 case ACLREX:
1203                         break;
1204                 case ASVC:
1205                         oprange[AHLT] = t;
1206                         oprange[AHVC] = t;
1207                         oprange[ASMC] = t;
1208                         oprange[ABRK] = t;
1209                         oprange[ADCPS1] = t;
1210                         oprange[ADCPS2] = t;
1211                         oprange[ADCPS3] = t;
1212                         break;
1213                 case AFADDS:
1214                         oprange[AFADDD] = t;
1215                         oprange[AFSUBS] = t;
1216                         oprange[AFSUBD] = t;
1217                         oprange[AFMULS] = t;
1218                         oprange[AFMULD] = t;
1219                         oprange[AFNMULS] = t;
1220                         oprange[AFNMULD] = t;
1221                         oprange[AFDIVS] = t;
1222                         oprange[AFMAXD] = t;
1223                         oprange[AFMAXS] = t;
1224                         oprange[AFMIND] = t;
1225                         oprange[AFMINS] = t;
1226                         oprange[AFMAXNMD] = t;
1227                         oprange[AFMAXNMS] = t;
1228                         oprange[AFMINNMD] = t;
1229                         oprange[AFMINNMS] = t;
1230                         oprange[AFDIVD] = t;
1231                         break;
1232                 case AFCVTSD:
1233                         oprange[AFCVTDS] = t;
1234                         oprange[AFABSD] = t;
1235                         oprange[AFABSS] = t;
1236                         oprange[AFNEGD] = t;
1237                         oprange[AFNEGS] = t;
1238                         oprange[AFSQRTD] = t;
1239                         oprange[AFSQRTS] = t;
1240                         oprange[AFRINTNS] = t;
1241                         oprange[AFRINTND] = t;
1242                         oprange[AFRINTPS] = t;
1243                         oprange[AFRINTPD] = t;
1244                         oprange[AFRINTMS] = t;
1245                         oprange[AFRINTMD] = t;
1246                         oprange[AFRINTZS] = t;
1247                         oprange[AFRINTZD] = t;
1248                         oprange[AFRINTAS] = t;
1249                         oprange[AFRINTAD] = t;
1250                         oprange[AFRINTXS] = t;
1251                         oprange[AFRINTXD] = t;
1252                         oprange[AFRINTIS] = t;
1253                         oprange[AFRINTID] = t;
1254                         oprange[AFCVTDH] = t;
1255                         oprange[AFCVTHS] = t;
1256                         oprange[AFCVTHD] = t;
1257                         oprange[AFCVTSH] = t;
1258                         break;
1259                 case AFCMPS:
1260                         oprange[AFCMPD] = t;
1261                         oprange[AFCMPES] = t;
1262                         oprange[AFCMPED] = t;
1263                         break;
1264                 case AFCCMPS:
1265                         oprange[AFCCMPD] = t;
1266                         oprange[AFCCMPES] = t;
1267                         oprange[AFCCMPED] = t;
1268                         break;
1269                 case AFCSELD:
1270                         oprange[AFCSELS] = t;
1271                         break;
1272
1273                 case AFMOVS:
1274                 case AFMOVD:
1275                         break;
1276
1277                 case AFCVTZSD:
1278                         oprange[AFCVTZSDW] = t;
1279                         oprange[AFCVTZSS] = t;
1280                         oprange[AFCVTZSSW] = t;
1281                         oprange[AFCVTZUD] = t;
1282                         oprange[AFCVTZUDW] = t;
1283                         oprange[AFCVTZUS] = t;
1284                         oprange[AFCVTZUSW] = t;
1285                         break;
1286                 case ASCVTFD:
1287                         oprange[ASCVTFS] = t;
1288                         oprange[ASCVTFWD] = t;
1289                         oprange[ASCVTFWS] = t;
1290                         oprange[AUCVTFD] = t;
1291                         oprange[AUCVTFS] = t;
1292                         oprange[AUCVTFWD] = t;
1293                         oprange[AUCVTFWS] = t;
1294                         break;
1295
1296                 case ASYS:
1297                         oprange[AAT] = t;
1298                         oprange[ADC] = t;
1299                         oprange[AIC] = t;
1300                         oprange[ATLBI] = t;
1301                         break;
1302
1303                 case ASYSL:
1304                 case AHINT:
1305                         break;
1306
1307                 case ADMB:
1308                         oprange[ADSB] = t;
1309                         oprange[AISB] = t;
1310                         break;
1311
1312                 case AMRS:
1313                 case AMSR:
1314                         break;
1315
1316                 case ALDXR:
1317                         oprange[ALDXRB] = t;
1318                         oprange[ALDXRH] = t;
1319                         oprange[ALDXRW] = t;
1320                         break;
1321                 case ALDXP:
1322                         oprange[ALDXPW] = t;
1323                         break;
1324                 case ASTXR:
1325                         oprange[ASTXRB] = t;
1326                         oprange[ASTXRH] = t;
1327                         oprange[ASTXRW] = t;
1328                         break;
1329                 case ASTXP:
1330                         oprange[ASTXPW] = t;
1331                         break;
1332
1333                 case AAESD:
1334                         oprange[AAESE] = t;
1335                         oprange[AAESMC] = t;
1336                         oprange[AAESIMC] = t;
1337                         oprange[ASHA1H] = t;
1338                         oprange[ASHA1SU1] = t;
1339                         oprange[ASHA256SU0] = t;
1340                         break;
1341
1342                 case ASHA1C:
1343                         oprange[ASHA1P] = t;
1344                         oprange[ASHA1M] = t;
1345                         oprange[ASHA1SU0] = t;
1346                         oprange[ASHA256H] = t;
1347                         oprange[ASHA256H2] = t;
1348                         oprange[ASHA256SU1] = t;
1349                         break;
1350
1351                 case AMOVP:
1352                         oprange[AMOVPW] = t;
1353                         oprange[AMOVPSW] = t;
1354                         break;
1355                 }
1356         }
1357 }