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