]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/8l/span.c
ndb/dns: remove single-ip-address assuptions
[plan9front.git] / sys / src / cmd / 8l / span.c
1 #include        "l.h"
2
3 void
4 span(void)
5 {
6         Prog *p, *q;
7         long v, c, idat;
8         int m, n, again;
9
10         xdefine("etext", STEXT, 0L);
11         idat = INITDAT;
12         for(p = firstp; p != P; p = p->link) {
13                 if(p->as == ATEXT)
14                         curtext = p;
15                 n = 0;
16                 if(p->to.type == D_BRANCH)
17                         if(p->pcond == P)
18                                 p->pcond = p;
19                 if((q = p->pcond) != P)
20                         if(q->back != 2)
21                                 n = 1;
22                 p->back = n;
23                 if(p->as == AADJSP) {
24                         p->to.type = D_SP;
25                         v = -p->from.offset;
26                         p->from.offset = v;
27                         p->as = AADDL;
28                         if(v < 0) {
29                                 p->as = ASUBL;
30                                 v = -v;
31                                 p->from.offset = v;
32                         }
33                         if(v == 0)
34                                 p->as = ANOP;
35                 }
36         }
37         n = 0;
38
39 start:
40         if(debug['v'])
41                 Bprint(&bso, "%5.2f span\n", cputime());
42         Bflush(&bso);
43         c = INITTEXT;
44         for(p = firstp; p != P; p = p->link) {
45                 if(p->as == ATEXT)
46                         curtext = p;
47                 if(p->to.type == D_BRANCH)
48                         if(p->back)
49                                 p->pc = c;
50                 asmins(p);
51                 p->pc = c;
52                 m = andptr-and;
53                 p->mark = m;
54                 c += m;
55         }
56
57 loop:
58         n++;
59         if(debug['v'])
60                 Bprint(&bso, "%5.2f span %d\n", cputime(), n);
61         Bflush(&bso);
62         if(n > 50) {
63                 print("span must be looping\n");
64                 errorexit();
65         }
66         again = 0;
67         c = INITTEXT;
68         for(p = firstp; p != P; p = p->link) {
69                 if(p->as == ATEXT)
70                         curtext = p;
71                 if(p->to.type == D_BRANCH) {
72                         if(p->back)
73                                 p->pc = c;
74                         asmins(p);
75                         m = andptr-and;
76                         if(m != p->mark) {
77                                 p->mark = m;
78                                 again++;
79                         }
80                 }
81                 p->pc = c;
82                 c += p->mark;
83         }
84         if(again) {
85                 textsize = c;
86                 goto loop;
87         }
88         if(INITRND) {
89                 INITDAT = rnd(c, INITRND);
90                 if(INITDAT != idat) {
91                         idat = INITDAT;
92                         goto start;
93                 }
94         }
95         xdefine("etext", STEXT, c);
96         if(debug['v'])
97                 Bprint(&bso, "etext = %lux\n", c);
98         Bflush(&bso);
99         for(p = textp; p != P; p = p->pcond)
100                 p->from.sym->value = p->pc;
101         textsize = c - INITTEXT;
102 }
103
104 void
105 xdefine(char *p, int t, long v)
106 {
107         Sym *s;
108
109         s = lookup(p, 0);
110         if(s->type == 0 || s->type == SXREF) {
111                 s->type = t;
112                 s->value = v;
113         }
114         if(s->type == STEXT && s->value == 0)
115                 s->value = v;
116 }
117
118 void
119 putsymb(char *s, int t, long v, int ver)
120 {
121         int i, f;
122
123         if(t == 'f')
124                 s++;
125         lput(v);
126         if(ver)
127                 t += 'a' - 'A';
128         cput(t+0x80);                   /* 0x80 is variable length */
129
130         if(t == 'Z' || t == 'z') {
131                 cput(s[0]);
132                 for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
133                         cput(s[i]);
134                         cput(s[i+1]);
135                 }
136                 cput(0);
137                 cput(0);
138                 i++;
139         }
140         else {
141                 for(i=0; s[i]; i++)
142                         cput(s[i]);
143                 cput(0);
144         }
145         symsize += 4 + 1 + i + 1;
146
147         if(debug['n']) {
148                 if(t == 'z' || t == 'Z') {
149                         Bprint(&bso, "%c %.8lux ", t, v);
150                         for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
151                                 f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
152                                 Bprint(&bso, "/%x", f);
153                         }
154                         Bprint(&bso, "\n");
155                         return;
156                 }
157                 if(ver)
158                         Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver);
159                 else
160                         Bprint(&bso, "%c %.8lux %s\n", t, v, s);
161         }
162 }
163
164 void
165 asmsym(void)
166 {
167         Prog *p;
168         Auto *a;
169         Sym *s;
170         int h;
171
172         s = lookup("etext", 0);
173         if(s->type == STEXT)
174                 putsymb(s->name, 'T', s->value, s->version);
175
176         for(h=0; h<NHASH; h++)
177                 for(s=hash[h]; s!=S; s=s->link)
178                         switch(s->type) {
179                         case SCONST:
180                                 putsymb(s->name, 'D', s->value, s->version);
181                                 continue;
182
183                         case SDATA:
184                                 putsymb(s->name, 'D', s->value+INITDAT, s->version);
185                                 continue;
186
187                         case SBSS:
188                                 putsymb(s->name, 'B', s->value+INITDAT, s->version);
189                                 continue;
190
191                         case SFILE:
192                                 putsymb(s->name, 'f', s->value, s->version);
193                                 continue;
194                         }
195
196         for(p=textp; p!=P; p=p->pcond) {
197                 s = p->from.sym;
198                 if(s->type != STEXT)
199                         continue;
200
201                 /* filenames first */
202                 for(a=p->to.autom; a; a=a->link)
203                         if(a->type == D_FILE)
204                                 putsymb(a->asym->name, 'z', a->aoffset, 0);
205                         else
206                         if(a->type == D_FILE1)
207                                 putsymb(a->asym->name, 'Z', a->aoffset, 0);
208
209                 putsymb(s->name, 'T', s->value, s->version);
210
211                 /* frame, auto and param after */
212                 putsymb(".frame", 'm', p->to.offset+4, 0);
213
214                 for(a=p->to.autom; a; a=a->link)
215                         if(a->type == D_AUTO)
216                                 putsymb(a->asym->name, 'a', -a->aoffset, 0);
217                         else
218                         if(a->type == D_PARAM)
219                                 putsymb(a->asym->name, 'p', a->aoffset, 0);
220         }
221         if(debug['v'] || debug['n'])
222                 Bprint(&bso, "symsize = %lud\n", symsize);
223         Bflush(&bso);
224 }
225
226 void
227 asmlc(void)
228 {
229         long oldpc, oldlc;
230         Prog *p;
231         long v, s;
232
233         oldpc = INITTEXT;
234         oldlc = 0;
235         for(p = firstp; p != P; p = p->link) {
236                 if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
237                         if(p->as == ATEXT)
238                                 curtext = p;
239                         if(debug['L'])
240                                 Bprint(&bso, "%6lux %P\n",
241                                         p->pc, p);
242                         continue;
243                 }
244                 if(debug['L'])
245                         Bprint(&bso, "\t\t%6ld", lcsize);
246                 v = (p->pc - oldpc) / MINLC;
247                 while(v) {
248                         s = 127;
249                         if(v < 127)
250                                 s = v;
251                         cput(s+128);    /* 129-255 +pc */
252                         if(debug['L'])
253                                 Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
254                         v -= s;
255                         lcsize++;
256                 }
257                 s = p->line - oldlc;
258                 oldlc = p->line;
259                 oldpc = p->pc + MINLC;
260                 if(s > 64 || s < -64) {
261                         cput(0);        /* 0 vv +lc */
262                         cput(s>>24);
263                         cput(s>>16);
264                         cput(s>>8);
265                         cput(s);
266                         if(debug['L']) {
267                                 if(s > 0)
268                                         Bprint(&bso, " lc+%ld(%d,%ld)\n",
269                                                 s, 0, s);
270                                 else
271                                         Bprint(&bso, " lc%ld(%d,%ld)\n",
272                                                 s, 0, s);
273                                 Bprint(&bso, "%6lux %P\n",
274                                         p->pc, p);
275                         }
276                         lcsize += 5;
277                         continue;
278                 }
279                 if(s > 0) {
280                         cput(0+s);      /* 1-64 +lc */
281                         if(debug['L']) {
282                                 Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
283                                 Bprint(&bso, "%6lux %P\n",
284                                         p->pc, p);
285                         }
286                 } else {
287                         cput(64-s);     /* 65-128 -lc */
288                         if(debug['L']) {
289                                 Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
290                                 Bprint(&bso, "%6lux %P\n",
291                                         p->pc, p);
292                         }
293                 }
294                 lcsize++;
295         }
296         while(lcsize & 1) {
297                 s = 129;
298                 cput(s);
299                 lcsize++;
300         }
301         if(debug['v'] || debug['L'])
302                 Bprint(&bso, "lcsize = %ld\n", lcsize);
303         Bflush(&bso);
304 }
305
306 int
307 prefixof(Adr *a)
308 {
309         switch(a->type) {
310         case D_INDIR+D_CS:
311                 return 0x2e;
312         case D_INDIR+D_DS:
313                 return 0x3e;
314         case D_INDIR+D_ES:
315                 return 0x26;
316         case D_INDIR+D_FS:
317                 return 0x64;
318         case D_INDIR+D_GS:
319                 return 0x65;
320         }
321         return 0;
322 }
323
324 int
325 oclass(Adr *a)
326 {
327         long v;
328
329         if((a->type >= D_INDIR && a->type < D_M0) || a->index != D_NONE) {
330                 if(a->index != D_NONE && a->scale == 0) {
331                         if(a->type == D_ADDR) {
332                                 switch(a->index) {
333                                 case D_EXTERN:
334                                 case D_STATIC:
335                                         return Yi32;
336                                 case D_AUTO:
337                                 case D_PARAM:
338                                         return Yiauto;
339                                 }
340                                 return Yxxx;
341                         }
342                         return Ycol;
343                 }
344                 return Ym;
345         }
346         switch(a->type)
347         {
348         case D_AL:
349                 return Yal;
350
351         case D_AX:
352                 return Yax;
353
354         case D_CL:
355                 return Ycl;
356
357         case D_DL:
358         case D_BL:
359         case D_AH:
360         case D_CH:
361         case D_DH:
362         case D_BH:
363                 return Yrb;
364
365         case D_CX:
366                 return Ycx;
367
368         case D_DX:
369         case D_BX:
370                 return Yrx;
371
372         case D_SP:
373         case D_BP:
374         case D_SI:
375         case D_DI:
376                 return Yrl;
377
378         case D_F0+0:
379                 return  Yf0;
380
381         case D_F0+1:
382         case D_F0+2:
383         case D_F0+3:
384         case D_F0+4:
385         case D_F0+5:
386         case D_F0+6:
387         case D_F0+7:
388                 return  Yrf;
389
390         case D_M0+0:
391         case D_M0+1:
392         case D_M0+2:
393         case D_M0+3:
394         case D_M0+4:
395         case D_M0+5:
396         case D_M0+6:
397         case D_M0+7:
398                 return  Ymr;
399
400         case D_X0+0:
401         case D_X0+1:
402         case D_X0+2:
403         case D_X0+3:
404         case D_X0+4:
405         case D_X0+5:
406         case D_X0+6:
407         case D_X0+7:
408                 return  Yxr;
409
410         case D_NONE:
411                 return Ynone;
412
413         case D_CS:      return  Ycs;
414         case D_SS:      return  Yss;
415         case D_DS:      return  Yds;
416         case D_ES:      return  Yes;
417         case D_FS:      return  Yfs;
418         case D_GS:      return  Ygs;
419
420         case D_GDTR:    return  Ygdtr;
421         case D_IDTR:    return  Yidtr;
422         case D_LDTR:    return  Yldtr;
423         case D_MSW:     return  Ymsw;
424         case D_TASK:    return  Ytask;
425
426         case D_CR+0:    return  Ycr0;
427         case D_CR+1:    return  Ycr1;
428         case D_CR+2:    return  Ycr2;
429         case D_CR+3:    return  Ycr3;
430         case D_CR+4:    return  Ycr4;
431         case D_CR+5:    return  Ycr5;
432         case D_CR+6:    return  Ycr6;
433         case D_CR+7:    return  Ycr7;
434
435         case D_DR+0:    return  Ydr0;
436         case D_DR+1:    return  Ydr1;
437         case D_DR+2:    return  Ydr2;
438         case D_DR+3:    return  Ydr3;
439         case D_DR+4:    return  Ydr4;
440         case D_DR+5:    return  Ydr5;
441         case D_DR+6:    return  Ydr6;
442         case D_DR+7:    return  Ydr7;
443
444         case D_TR+0:    return  Ytr0;
445         case D_TR+1:    return  Ytr1;
446         case D_TR+2:    return  Ytr2;
447         case D_TR+3:    return  Ytr3;
448         case D_TR+4:    return  Ytr4;
449         case D_TR+5:    return  Ytr5;
450         case D_TR+6:    return  Ytr6;
451         case D_TR+7:    return  Ytr7;
452
453         case D_EXTERN:
454         case D_STATIC:
455         case D_AUTO:
456         case D_PARAM:
457                 return Ym;
458
459         case D_CONST:
460         case D_ADDR:
461                 if(a->sym == S) {
462                         v = a->offset;
463                         if(v == 0)
464                                 return Yi0;
465                         if(v == 1)
466                                 return Yi1;
467                         if(v >= -128 && v <= 127)
468                                 return Yi8;
469                 }
470                 return Yi32;
471
472         case D_BRANCH:
473                 return Ybr;
474         }
475         return Yxxx;
476 }
477
478 void
479 asmidx(Adr *a, int base)
480 {
481         int i;
482
483         switch(a->index) {
484         default:
485                 goto bad;
486
487         case D_NONE:
488                 i = 4 << 3;
489                 goto bas;
490
491         case D_AX:
492         case D_CX:
493         case D_DX:
494         case D_BX:
495         case D_BP:
496         case D_SI:
497         case D_DI:
498                 i = reg[a->index] << 3;
499                 break;
500         }
501         switch(a->scale) {
502         default:
503                 goto bad;
504         case 1:
505                 break;
506         case 2:
507                 i |= (1<<6);
508                 break;
509         case 4:
510                 i |= (2<<6);
511                 break;
512         case 8:
513                 i |= (3<<6);
514                 break;
515         }
516 bas:
517         switch(base) {
518         default:
519                 goto bad;
520         case D_NONE:    /* must be mod=00 */
521                 i |= 5;
522                 break;
523         case D_AX:
524         case D_CX:
525         case D_DX:
526         case D_BX:
527         case D_SP:
528         case D_BP:
529         case D_SI:
530         case D_DI:
531                 i |= reg[base];
532                 break;
533         }
534         *andptr++ = i;
535         return;
536 bad:
537         diag("asmidx: bad address %D", a);
538         *andptr++ = 0;
539         return;
540 }
541
542 static void
543 put4(long v)
544 {
545         if(dlm && curp != P && reloca != nil){
546                 dynreloc(reloca->sym, curp->pc + andptr - &and[0], 1);
547                 reloca = nil;
548         }
549         andptr[0] = v;
550         andptr[1] = v>>8;
551         andptr[2] = v>>16;
552         andptr[3] = v>>24;
553         andptr += 4;
554 }
555
556 long
557 vaddr(Adr *a)
558 {
559         int t;
560         long v;
561         Sym *s;
562
563         t = a->type;
564         v = a->offset;
565         if(t == D_ADDR)
566                 t = a->index;
567         switch(t) {
568         case D_STATIC:
569         case D_EXTERN:
570                 s = a->sym;
571                 if(s != nil) {
572                         if(dlm && curp != P)
573                                 reloca = a;
574                         switch(s->type) {
575                         case SUNDEF:
576                                 ckoff(s, v);
577                         case STEXT:
578                         case SCONST:
579                                 v += s->value;
580                                 break;
581                         default:
582                                 v += INITDAT + s->value;
583                         }
584                 }
585         }
586         return v;
587 }
588
589 void
590 asmand(Adr *a, int r)
591 {
592         long v;
593         int t;
594         Adr aa;
595
596         v = a->offset;
597         t = a->type;
598         if(a->index != D_NONE) {
599                 if(t >= D_INDIR && t < D_M0) {
600                         t -= D_INDIR;
601                         if(t == D_NONE) {
602                                 *andptr++ = (0 << 6) | (4 << 0) | (r << 3);
603                                 asmidx(a, t);
604                                 put4(v);
605                                 return;
606                         }
607                         if(v == 0 && t != D_BP) {
608                                 *andptr++ = (0 << 6) | (4 << 0) | (r << 3);
609                                 asmidx(a, t);
610                                 return;
611                         }
612                         if(v >= -128 && v < 128) {
613                                 *andptr++ = (1 << 6) | (4 << 0) | (r << 3);
614                                 asmidx(a, t);
615                                 *andptr++ = v;
616                                 return;
617                         }
618                         *andptr++ = (2 << 6) | (4 << 0) | (r << 3);
619                         asmidx(a, t);
620                         put4(v);
621                         return;
622                 }
623                 switch(t) {
624                 default:
625                         goto bad;
626                 case D_STATIC:
627                 case D_EXTERN:
628                         aa.type = D_NONE+D_INDIR;
629                         break;
630                 case D_AUTO:
631                 case D_PARAM:
632                         aa.type = D_SP+D_INDIR;
633                         break;
634                 }
635                 aa.offset = vaddr(a);
636                 aa.index = a->index;
637                 aa.scale = a->scale;
638                 asmand(&aa, r);
639                 return;
640         }
641         if(t >= D_AL && t <= D_F0+7) {
642                 if(v)
643                         goto bad;
644                 *andptr++ = (3 << 6) | (reg[t] << 0) | (r << 3);
645                 return;
646         }
647         if(t >= D_M0 && t <= D_X0+7) {
648                 if(v)
649                         goto bad;
650                 *andptr++ = (3 << 6) | (reg[t] << 0) | (r << 3);
651                 return;
652         }
653         if(t >= D_INDIR && t < D_M0) {
654                 t -= D_INDIR;
655                 if(t == D_NONE || D_CS <= t && t <= D_GS) {
656                         *andptr++ = (0 << 6) | (5 << 0) | (r << 3);
657                         put4(v);
658                         return;
659                 }
660                 if(t == D_SP) {
661                         if(v == 0) {
662                                 *andptr++ = (0 << 6) | (4 << 0) | (r << 3);
663                                 asmidx(a, D_SP);
664                                 return;
665                         }
666                         if(v >= -128 && v < 128) {
667                                 *andptr++ = (1 << 6) | (4 << 0) | (r << 3);
668                                 asmidx(a, D_SP);
669                                 *andptr++ = v;
670                                 return;
671                         }
672                         *andptr++ = (2 << 6) | (4 << 0) | (r << 3);
673                         asmidx(a, D_SP);
674                         put4(v);
675                         return;
676                 }
677                 if(t >= D_AX && t <= D_DI) {
678                         if(v == 0 && t != D_BP) {
679                                 *andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3);
680                                 return;
681                         }
682                         if(v >= -128 && v < 128) {
683                                 andptr[0] = (1 << 6) | (reg[t] << 0) | (r << 3);
684                                 andptr[1] = v;
685                                 andptr += 2;
686                                 return;
687                         }
688                         *andptr++ = (2 << 6) | (reg[t] << 0) | (r << 3);
689                         put4(v);
690                         return;
691                 }
692                 goto bad;
693         }
694         switch(a->type) {
695         default:
696                 goto bad;
697         case D_STATIC:
698         case D_EXTERN:
699                 aa.type = D_NONE+D_INDIR;
700                 break;
701         case D_AUTO:
702         case D_PARAM:
703                 aa.type = D_SP+D_INDIR;
704                 break;
705         }
706         aa.index = D_NONE;
707         aa.scale = 1;
708         aa.offset = vaddr(a);
709         asmand(&aa, r);
710         return;
711 bad:
712         diag("asmand: bad address %D", a);
713         return;
714 }
715
716 #define E       0xff
717 uchar   ymovtab[] =
718 {
719 /* push */
720         APUSHL, Ycs,    Ynone,  0,      0x0e,E,0,0,
721         APUSHL, Yss,    Ynone,  0,      0x16,E,0,0,
722         APUSHL, Yds,    Ynone,  0,      0x1e,E,0,0,
723         APUSHL, Yes,    Ynone,  0,      0x06,E,0,0,
724         APUSHL, Yfs,    Ynone,  0,      0x0f,0xa0,E,0,
725         APUSHL, Ygs,    Ynone,  0,      0x0f,0xa8,E,0,
726
727         APUSHW, Ycs,    Ynone,  0,      Pe,0x0e,E,0,
728         APUSHW, Yss,    Ynone,  0,      Pe,0x16,E,0,
729         APUSHW, Yds,    Ynone,  0,      Pe,0x1e,E,0,
730         APUSHW, Yes,    Ynone,  0,      Pe,0x06,E,0,
731         APUSHW, Yfs,    Ynone,  0,      Pe,0x0f,0xa0,E,
732         APUSHW, Ygs,    Ynone,  0,      Pe,0x0f,0xa8,E,
733
734 /* pop */
735         APOPL,  Ynone,  Yds,    0,      0x1f,E,0,0,
736         APOPL,  Ynone,  Yes,    0,      0x07,E,0,0,
737         APOPL,  Ynone,  Yss,    0,      0x17,E,0,0,
738         APOPL,  Ynone,  Yfs,    0,      0x0f,0xa1,E,0,
739         APOPL,  Ynone,  Ygs,    0,      0x0f,0xa9,E,0,
740
741         APOPW,  Ynone,  Yds,    0,      Pe,0x1f,E,0,
742         APOPW,  Ynone,  Yes,    0,      Pe,0x07,E,0,
743         APOPW,  Ynone,  Yss,    0,      Pe,0x17,E,0,
744         APOPW,  Ynone,  Yfs,    0,      Pe,0x0f,0xa1,E,
745         APOPW,  Ynone,  Ygs,    0,      Pe,0x0f,0xa9,E,
746
747 /* mov seg */
748         AMOVW,  Yes,    Yml,    1,      0x8c,0,0,0,
749         AMOVW,  Ycs,    Yml,    1,      0x8c,1,0,0,
750         AMOVW,  Yss,    Yml,    1,      0x8c,2,0,0,
751         AMOVW,  Yds,    Yml,    1,      0x8c,3,0,0,
752         AMOVW,  Yfs,    Yml,    1,      0x8c,4,0,0,
753         AMOVW,  Ygs,    Yml,    1,      0x8c,5,0,0,
754
755         AMOVW,  Yml,    Yes,    2,      0x8e,0,0,0,
756         AMOVW,  Yml,    Ycs,    2,      0x8e,1,0,0,
757         AMOVW,  Yml,    Yss,    2,      0x8e,2,0,0,
758         AMOVW,  Yml,    Yds,    2,      0x8e,3,0,0,
759         AMOVW,  Yml,    Yfs,    2,      0x8e,4,0,0,
760         AMOVW,  Yml,    Ygs,    2,      0x8e,5,0,0,
761
762 /* mov cr */
763         AMOVL,  Ycr0,   Yml,    3,      0x0f,0x20,0,0,
764         AMOVL,  Ycr2,   Yml,    3,      0x0f,0x20,2,0,
765         AMOVL,  Ycr3,   Yml,    3,      0x0f,0x20,3,0,
766         AMOVL,  Ycr4,   Yml,    3,      0x0f,0x20,4,0,
767
768         AMOVL,  Yml,    Ycr0,   4,      0x0f,0x22,0,0,
769         AMOVL,  Yml,    Ycr2,   4,      0x0f,0x22,2,0,
770         AMOVL,  Yml,    Ycr3,   4,      0x0f,0x22,3,0,
771         AMOVL,  Yml,    Ycr4,   4,      0x0f,0x22,4,0,
772
773 /* mov dr */
774         AMOVL,  Ydr0,   Yml,    3,      0x0f,0x21,0,0,
775         AMOVL,  Ydr1,   Yml,    3,      0x0f,0x21,1,0,
776         AMOVL,  Ydr2,   Yml,    3,      0x0f,0x21,2,0,
777         AMOVL,  Ydr3,   Yml,    3,      0x0f,0x21,3,0,
778         AMOVL,  Ydr6,   Yml,    3,      0x0f,0x21,6,0,
779         AMOVL,  Ydr7,   Yml,    3,      0x0f,0x21,7,0,
780
781         AMOVL,  Yml,    Ydr0,   4,      0x0f,0x23,0,0,
782         AMOVL,  Yml,    Ydr1,   4,      0x0f,0x23,1,0,
783         AMOVL,  Yml,    Ydr2,   4,      0x0f,0x23,2,0,
784         AMOVL,  Yml,    Ydr3,   4,      0x0f,0x23,3,0,
785         AMOVL,  Yml,    Ydr6,   4,      0x0f,0x23,6,0,
786         AMOVL,  Yml,    Ydr7,   4,      0x0f,0x23,7,0,
787
788 /* mov tr */
789         AMOVL,  Ytr6,   Yml,    3,      0x0f,0x24,6,0,
790         AMOVL,  Ytr7,   Yml,    3,      0x0f,0x24,7,0,
791
792         AMOVL,  Yml,    Ytr6,   4,      0x0f,0x26,6,E,
793         AMOVL,  Yml,    Ytr7,   4,      0x0f,0x26,7,E,
794
795 /* lgdt, sgdt, lidt, sidt */
796         AMOVL,  Ym,     Ygdtr,  4,      0x0f,0x01,2,0,
797         AMOVL,  Ygdtr,  Ym,     3,      0x0f,0x01,0,0,
798         AMOVL,  Ym,     Yidtr,  4,      0x0f,0x01,3,0,
799         AMOVL,  Yidtr,  Ym,     3,      0x0f,0x01,1,0,
800
801 /* lldt, sldt */
802         AMOVW,  Yml,    Yldtr,  4,      0x0f,0x00,2,0,
803         AMOVW,  Yldtr,  Yml,    3,      0x0f,0x00,0,0,
804
805 /* lmsw, smsw */
806         AMOVW,  Yml,    Ymsw,   4,      0x0f,0x01,6,0,
807         AMOVW,  Ymsw,   Yml,    3,      0x0f,0x01,4,0,
808
809 /* ltr, str */
810         AMOVW,  Yml,    Ytask,  4,      0x0f,0x00,3,0,
811         AMOVW,  Ytask,  Yml,    3,      0x0f,0x00,1,0,
812
813 /* load full pointer */
814         AMOVL,  Yml,    Ycol,   5,      0,0,0,0,
815         AMOVW,  Yml,    Ycol,   5,      Pe,0,0,0,
816
817 /* double shift */
818         ASHLL,  Ycol,   Yml,    6,      0xa4,0xa5,0,0,
819         ASHRL,  Ycol,   Yml,    6,      0xac,0xad,0,0,
820
821 /* extra imul */
822         AIMULW, Yml,    Yrl,    7,      Pq,0xaf,0,0,
823         AIMULL, Yml,    Yrl,    7,      Pm,0xaf,0,0,
824         0
825 };
826
827 int
828 isax(Adr *a)
829 {
830
831         switch(a->type) {
832         case D_AX:
833         case D_AL:
834         case D_AH:
835         case D_INDIR+D_AX:
836                 return 1;
837         }
838         if(a->index == D_AX)
839                 return 1;
840         return 0;
841 }
842
843 void
844 subreg(Prog *p, int from, int to)
845 {
846
847         if(debug['Q'])
848                 print("\n%P     s/%R/%R/\n", p, from, to);
849
850         if(p->from.type == from)
851                 p->from.type = to;
852         if(p->to.type == from)
853                 p->to.type = to;
854
855         if(p->from.index == from)
856                 p->from.index = to;
857         if(p->to.index == from)
858                 p->to.index = to;
859
860         from += D_INDIR;
861         if(p->from.type == from)
862                 p->from.type = to+D_INDIR;
863         if(p->to.type == from)
864                 p->to.type = to+D_INDIR;
865
866         if(debug['Q'])
867                 print("%P\n", p);
868 }
869
870 static int
871 mediaop(Optab *o, int op, int osize, int z)
872 {
873         switch(op){
874         case Pm:
875         case Pe:
876         case Pf2:
877         case Pf3:
878                 if(osize != 1){
879                         if(op != Pm)
880                                 *andptr++ = op;
881                         *andptr++ = Pm;
882                         op = o->op[++z];
883                         break;
884                 }
885         default:
886                 if(andptr == and || andptr[-1] != Pm)
887                         *andptr++ = Pm;
888                 break;
889         }
890         *andptr++ = op;
891         return z;
892 }
893
894 void
895 doasm(Prog *p)
896 {
897         Optab *o;
898         Prog *q, pp;
899         uchar *t;
900         int z, op, ft, tt;
901         long v, pre;
902
903         pre = prefixof(&p->from);
904         if(pre)
905                 *andptr++ = pre;
906         pre = prefixof(&p->to);
907         if(pre)
908                 *andptr++ = pre;
909
910         o = opindex[p->as];
911         ft = oclass(&p->from) * Ymax;
912         tt = oclass(&p->to) * Ymax;
913         t = o->ytab;
914         if(t == 0) {
915                 diag("asmins: noproto %P", p);
916                 return;
917         }
918         for(z=0; *t; z+=t[3],t+=4)
919                 if(ycover[ft+t[0]])
920                 if(ycover[tt+t[1]])
921                         goto found;
922         goto domov;
923
924 found:
925         switch(o->prefix) {
926         case Pq:        /* 16 bit escape and opcode escape */
927                 *andptr++ = Pe;
928                 *andptr++ = Pm;
929                 break;
930
931         case Pf2:       /* xmm opcode escape */
932         case Pf3:
933                 *andptr++ = o->prefix;
934                 *andptr++ = Pm;
935                 break;
936
937         case Pm:        /* opcode escape */
938                 *andptr++ = Pm;
939                 break;
940
941         case Pe:        /* 16 bit escape */
942                 *andptr++ = Pe;
943                 break;
944
945         case Pb:        /* botch */
946                 break;
947         }
948         v = vaddr(&p->from);
949         op = o->op[z];
950         switch(t[2]) {
951         default:
952                 diag("asmins: unknown z %d %P", t[2], p);
953                 return;
954
955         case Zpseudo:
956                 break;
957
958         case Zlit:
959                 for(; op = o->op[z]; z++)
960                         *andptr++ = op;
961                 break;
962
963         case Zm_r:
964                 *andptr++ = op;
965                 asmand(&p->from, reg[p->to.type]);
966                 break;
967
968         case Zm_r_xm:
969                 mediaop(o, op, t[3], z);
970                 asmand(&p->from, reg[p->to.type]);
971                 break;
972
973         case Zm_r_i_xm:
974                 mediaop(o, op, t[3], z);
975                 asmand(&p->from, reg[p->to.type]);
976                 *andptr++ = p->to.offset;
977                 break;
978
979         case Zm_r_3d:
980                 *andptr++ = 0x0f;
981                 *andptr++ = 0x0f;
982                 asmand(&p->from, reg[p->to.type]);
983                 *andptr++ = op;
984                 break;
985
986         case Zibm_r:
987                 *andptr++ = op;
988                 asmand(&p->from, reg[p->to.type]);
989                 *andptr++ = p->to.offset;
990                 break;
991
992         case Zaut_r:
993                 *andptr++ = 0x8d;       /* leal */
994                 if(p->from.type != D_ADDR)
995                         diag("asmins: Zaut sb type ADDR");
996                 p->from.type = p->from.index;
997                 p->from.index = D_NONE;
998                 asmand(&p->from, reg[p->to.type]);
999                 p->from.index = p->from.type;
1000                 p->from.type = D_ADDR;
1001                 break;
1002
1003         case Zm_o:
1004                 *andptr++ = op;
1005                 asmand(&p->from, o->op[z+1]);
1006                 break;
1007
1008         case Zr_m:
1009                 *andptr++ = op;
1010                 asmand(&p->to, reg[p->from.type]);
1011                 break;
1012
1013         case Zr_m_xm:
1014                 mediaop(o, op, t[3], z);
1015                 asmand(&p->to, reg[p->from.type]);
1016                 break;
1017
1018         case Zr_m_i_xm:
1019                 mediaop(o, op, t[3], z);
1020                 asmand(&p->to, reg[p->from.type]);
1021                 *andptr++ = p->from.offset;
1022                 break;
1023
1024         case Zo_m:
1025                 *andptr++ = op;
1026                 asmand(&p->to, o->op[z+1]);
1027                 break;
1028
1029         case Zm_ibo:
1030                 v = vaddr(&p->to);
1031                 *andptr++ = op;
1032                 asmand(&p->from, o->op[z+1]);
1033                 *andptr++ = v;
1034                 break;
1035
1036         case Zibo_m:
1037                 *andptr++ = op;
1038                 asmand(&p->to, o->op[z+1]);
1039                 *andptr++ = v;
1040                 break;
1041
1042         case Zibo_m_xm:
1043                 z = mediaop(o, op, t[3], z);
1044                 asmand(&p->to, o->op[z+1]);
1045                 *andptr++ = v;
1046                 break;
1047
1048         case Z_ib:
1049                 v = vaddr(&p->to);
1050         case Zib_:
1051                 *andptr++ = op;
1052                 *andptr++ = v;
1053                 break;
1054
1055         case Zib_rp:
1056                 *andptr++ = op + reg[p->to.type];
1057                 *andptr++ = v;
1058                 break;
1059
1060         case Zil_rp:
1061                 *andptr++ = op + reg[p->to.type];
1062                 if(o->prefix == Pe) {
1063                         *andptr++ = v;
1064                         *andptr++ = v>>8;
1065                 }
1066                 else
1067                         put4(v);
1068                 break;
1069
1070         case Zib_rr:
1071                 *andptr++ = op;
1072                 asmand(&p->to, reg[p->to.type]);
1073                 *andptr++ = v;
1074                 break;
1075
1076         case Z_il:
1077                 v = vaddr(&p->to);
1078         case Zil_:
1079                 *andptr++ = op;
1080                 if(o->prefix == Pe) {
1081                         *andptr++ = v;
1082                         *andptr++ = v>>8;
1083                 }
1084                 else
1085                         put4(v);
1086                 break;
1087
1088         case Zm_ilo:
1089                 v = vaddr(&p->to);
1090                 *andptr++ = op;
1091                 asmand(&p->from, o->op[z+1]);
1092                 if(o->prefix == Pe) {
1093                         *andptr++ = v;
1094                         *andptr++ = v>>8;
1095                 }
1096                 else
1097                         put4(v);
1098                 break;
1099
1100         case Zilo_m:
1101                 *andptr++ = op;
1102                 asmand(&p->to, o->op[z+1]);
1103                 if(o->prefix == Pe) {
1104                         *andptr++ = v;
1105                         *andptr++ = v>>8;
1106                 }
1107                 else
1108                         put4(v);
1109                 break;
1110
1111         case Zil_rr:
1112                 *andptr++ = op;
1113                 asmand(&p->to, reg[p->to.type]);
1114                 if(o->prefix == Pe) {
1115                         *andptr++ = v;
1116                         *andptr++ = v>>8;
1117                 }
1118                 else
1119                         put4(v);
1120                 break;
1121
1122         case Z_rp:
1123                 *andptr++ = op + reg[p->to.type];
1124                 break;
1125
1126         case Zrp_:
1127                 *andptr++ = op + reg[p->from.type];
1128                 break;
1129
1130         case Zclr:
1131                 *andptr++ = op;
1132                 asmand(&p->to, reg[p->to.type]);
1133                 break;
1134
1135         case Zbr:
1136                 q = p->pcond;
1137                 if(q) {
1138                         v = q->pc - p->pc - 2;
1139                         if(v >= -128 && v <= 127) {
1140                                 *andptr++ = op;
1141                                 *andptr++ = v;
1142                         } else {
1143                                 v -= 6-2;
1144                                 *andptr++ = 0x0f;
1145                                 *andptr++ = o->op[z+1];
1146                                 *andptr++ = v;
1147                                 *andptr++ = v>>8;
1148                                 *andptr++ = v>>16;
1149                                 *andptr++ = v>>24;
1150                         }
1151                 }
1152                 break;
1153
1154         case Zcall:
1155                 q = p->pcond;
1156                 if(q) {
1157                         v = q->pc - p->pc - 5;
1158                         if(dlm && curp != P && p->to.sym->type == SUNDEF){
1159                                 /* v = 0 - p->pc - 5; */
1160                                 v = 0;
1161                                 ckoff(p->to.sym, v);
1162                                 v += p->to.sym->value;
1163                                 dynreloc(p->to.sym, p->pc+1, 0);
1164                         }
1165                         *andptr++ = op;
1166                         *andptr++ = v;
1167                         *andptr++ = v>>8;
1168                         *andptr++ = v>>16;
1169                         *andptr++ = v>>24;
1170                 }
1171                 break;
1172
1173         case Zjmp:
1174                 q = p->pcond;
1175                 if(q) {
1176                         v = q->pc - p->pc - 2;
1177                         if(v >= -128 && v <= 127) {
1178                                 *andptr++ = op;
1179                                 *andptr++ = v;
1180                         } else {
1181                                 v -= 5-2;
1182                                 *andptr++ = o->op[z+1];
1183                                 *andptr++ = v;
1184                                 *andptr++ = v>>8;
1185                                 *andptr++ = v>>16;
1186                                 *andptr++ = v>>24;
1187                         }
1188                 }
1189                 break;
1190
1191         case Zloop:
1192                 q = p->pcond;
1193                 if(q) {
1194                         v = q->pc - p->pc - 2;
1195                         if(v < -128 || v > 127)
1196                                 diag("loop too far: %P", p);
1197                         *andptr++ = op;
1198                         *andptr++ = v;
1199                 }
1200                 break;
1201
1202         case Zbyte:
1203                 *andptr++ = v;
1204                 if(op > 1) {
1205                         *andptr++ = v>>8;
1206                         if(op > 2) {
1207                                 *andptr++ = v>>16;
1208                                 *andptr++ = v>>24;
1209                         }
1210                 }
1211                 break;
1212
1213         case Zmov:
1214                 goto domov;
1215         }
1216         return;
1217
1218 domov:
1219         for(t=ymovtab; *t; t+=8)
1220                 if(p->as == t[0])
1221                 if(ycover[ft+t[1]])
1222                 if(ycover[tt+t[2]])
1223                         goto mfound;
1224 bad:
1225         /*
1226          * here, the assembly has failed.
1227          * if its a byte instruction that has
1228          * unaddressable registers, try to
1229          * exchange registers and reissue the
1230          * instruction with the operands renamed.
1231          */
1232         pp = *p;
1233         z = p->from.type;
1234         if(z >= D_BP && z <= D_DI) {
1235                 if(isax(&p->to)) {
1236                         *andptr++ = 0x87;                       /* xchg lhs,bx */
1237                         asmand(&p->from, reg[D_BX]);
1238                         subreg(&pp, z, D_BX);
1239                         doasm(&pp);
1240                         *andptr++ = 0x87;                       /* xchg lhs,bx */
1241                         asmand(&p->from, reg[D_BX]);
1242                 } else {
1243                         *andptr++ = 0x90 + reg[z];              /* xchg lsh,ax */
1244                         subreg(&pp, z, D_AX);
1245                         doasm(&pp);
1246                         *andptr++ = 0x90 + reg[z];              /* xchg lsh,ax */
1247                 }
1248                 return;
1249         }
1250         z = p->to.type;
1251         if(z >= D_BP && z <= D_DI) {
1252                 if(isax(&p->from)) {
1253                         *andptr++ = 0x87;                       /* xchg rhs,bx */
1254                         asmand(&p->to, reg[D_BX]);
1255                         subreg(&pp, z, D_BX);
1256                         doasm(&pp);
1257                         *andptr++ = 0x87;                       /* xchg rhs,bx */
1258                         asmand(&p->to, reg[D_BX]);
1259                 } else {
1260                         *andptr++ = 0x90 + reg[z];              /* xchg rsh,ax */
1261                         subreg(&pp, z, D_AX);
1262                         doasm(&pp);
1263                         *andptr++ = 0x90 + reg[z];              /* xchg rsh,ax */
1264                 }
1265                 return;
1266         }
1267         diag("doasm: notfound t2=%ux from=%ux to=%ux %P", t[2], p->from.type, p->to.type, p);
1268         return;
1269
1270 mfound:
1271         switch(t[3]) {
1272         default:
1273                 diag("asmins: unknown mov %d %P", t[3], p);
1274                 break;
1275
1276         case 0: /* lit */
1277                 for(z=4; t[z]!=E; z++)
1278                         *andptr++ = t[z];
1279                 break;
1280
1281         case 1: /* r,m */
1282                 *andptr++ = t[4];
1283                 asmand(&p->to, t[5]);
1284                 break;
1285
1286         case 2: /* m,r */
1287                 *andptr++ = t[4];
1288                 asmand(&p->from, t[5]);
1289                 break;
1290
1291         case 3: /* r,m - 2op */
1292                 *andptr++ = t[4];
1293                 *andptr++ = t[5];
1294                 asmand(&p->to, t[6]);
1295                 break;
1296
1297         case 4: /* m,r - 2op */
1298                 *andptr++ = t[4];
1299                 *andptr++ = t[5];
1300                 asmand(&p->from, t[6]);
1301                 break;
1302
1303         case 5: /* load full pointer, trash heap */
1304                 if(t[4])
1305                         *andptr++ = t[4];
1306                 switch(p->to.index) {
1307                 default:
1308                         goto bad;
1309                 case D_DS:
1310                         *andptr++ = 0xc5;
1311                         break;
1312                 case D_SS:
1313                         *andptr++ = 0x0f;
1314                         *andptr++ = 0xb2;
1315                         break;
1316                 case D_ES:
1317                         *andptr++ = 0xc4;
1318                         break;
1319                 case D_FS:
1320                         *andptr++ = 0x0f;
1321                         *andptr++ = 0xb4;
1322                         break;
1323                 case D_GS:
1324                         *andptr++ = 0x0f;
1325                         *andptr++ = 0xb5;
1326                         break;
1327                 }
1328                 asmand(&p->from, reg[p->to.type]);
1329                 break;
1330
1331         case 6: /* double shift */
1332                 z = p->from.type;
1333                 switch(z) {
1334                 default:
1335                         goto bad;
1336                 case D_CONST:
1337                         *andptr++ = 0x0f;
1338                         *andptr++ = t[4];
1339                         asmand(&p->to, reg[p->from.index]);
1340                         *andptr++ = p->from.offset;
1341                         break;
1342                 case D_CL:
1343                 case D_CX:
1344                         *andptr++ = 0x0f;
1345                         *andptr++ = t[5];
1346                         asmand(&p->to, reg[p->from.index]);
1347                         break;
1348                 }
1349                 break;
1350
1351         case 7: /* imul rm,r */
1352                 *andptr++ = t[4];
1353                 *andptr++ = t[5];
1354                 asmand(&p->from, reg[p->to.type]);
1355                 break;
1356         }
1357 }
1358
1359 void
1360 asmins(Prog *p)
1361 {
1362
1363         andptr = and;
1364         doasm(p);
1365 }
1366
1367 enum{
1368         ABSD = 0,
1369         ABSU = 1,
1370         RELD = 2,
1371         RELU = 3,
1372 };
1373
1374 int modemap[4] = { 0, 1, -1, 2, };
1375
1376 typedef struct Reloc Reloc;
1377
1378 struct Reloc
1379 {
1380         int n;
1381         int t;
1382         uchar *m;
1383         ulong *a;
1384 };
1385
1386 Reloc rels;
1387
1388 static void
1389 grow(Reloc *r)
1390 {
1391         int t;
1392         uchar *m, *nm;
1393         ulong *a, *na;
1394
1395         t = r->t;
1396         r->t += 64;
1397         m = r->m;
1398         a = r->a;
1399         r->m = nm = malloc(r->t*sizeof(uchar));
1400         r->a = na = malloc(r->t*sizeof(ulong));
1401         memmove(nm, m, t*sizeof(uchar));
1402         memmove(na, a, t*sizeof(ulong));
1403         free(m);
1404         free(a);
1405 }
1406
1407 void
1408 dynreloc(Sym *s, ulong v, int abs)
1409 {
1410         int i, k, n;
1411         uchar *m;
1412         ulong *a;
1413         Reloc *r;
1414
1415         if(s->type == SUNDEF)
1416                 k = abs ? ABSU : RELU;
1417         else
1418                 k = abs ? ABSD : RELD;
1419         /* Bprint(&bso, "R %s a=%ld(%lx) %d\n", s->name, v, v, k); */
1420         k = modemap[k];
1421         r = &rels;
1422         n = r->n;
1423         if(n >= r->t)
1424                 grow(r);
1425         m = r->m;
1426         a = r->a;
1427         for(i = n; i > 0; i--){
1428                 if(v < a[i-1]){ /* happens occasionally for data */
1429                         m[i] = m[i-1];
1430                         a[i] = a[i-1];
1431                 }
1432                 else
1433                         break;
1434         }
1435         m[i] = k;
1436         a[i] = v;
1437         r->n++;
1438 }
1439
1440 static int
1441 sput(char *s)
1442 {
1443         char *p;
1444
1445         p = s;
1446         while(*s)
1447                 cput(*s++);
1448         cput(0);
1449         return s-p+1;
1450 }
1451
1452 void
1453 asmdyn()
1454 {
1455         int i, n, t, c;
1456         Sym *s;
1457         ulong la, ra, *a;
1458         vlong off;
1459         uchar *m;
1460         Reloc *r;
1461
1462         cflush();
1463         off = seek(cout, 0, 1);
1464         lput(0);
1465         t = 0;
1466         lput(imports);
1467         t += 4;
1468         for(i = 0; i < NHASH; i++)
1469                 for(s = hash[i]; s != S; s = s->link)
1470                         if(s->type == SUNDEF){
1471                                 lput(s->sig);
1472                                 t += 4;
1473                                 t += sput(s->name);
1474                         }
1475
1476         la = 0;
1477         r = &rels;
1478         n = r->n;
1479         m = r->m;
1480         a = r->a;
1481         lput(n);
1482         t += 4;
1483         for(i = 0; i < n; i++){
1484                 ra = *a-la;
1485                 if(*a < la)
1486                         diag("bad relocation order");
1487                 if(ra < 256)
1488                         c = 0;
1489                 else if(ra < 65536)
1490                         c = 1;
1491                 else
1492                         c = 2;
1493                 cput((c<<6)|*m++);
1494                 t++;
1495                 if(c == 0){
1496                         cput(ra);
1497                         t++;
1498                 }
1499                 else if(c == 1){
1500                         wput(ra);
1501                         t += 2;
1502                 }
1503                 else{
1504                         lput(ra);
1505                         t += 4;
1506                 }
1507                 la = *a++;
1508         }
1509
1510         cflush();
1511         seek(cout, off, 0);
1512         lput(t);
1513
1514         if(debug['v']){
1515                 Bprint(&bso, "import table entries = %d\n", imports);
1516                 Bprint(&bso, "export table entries = %d\n", exports);
1517         }
1518 }