1 #include "l.h"
2
3 void
span(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
xdefine(char * p,int t,long v)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
putsymb(char * s,int t,long v,int ver)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
asmsym(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
asmlc(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['V'])
240 Bprint(&bso, "%6lux %P\n",
241 p->pc, p);
242 continue;
243 }
244 if(debug['V'])
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['V'])
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['V']) {
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['V']) {
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['V']) {
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['V'])
302 Bprint(&bso, "lcsize = %ld\n", lcsize);
303 Bflush(&bso);
304 }
305
306 int
prefixof(Adr * a)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
oclass(Adr * a)325 oclass(Adr *a)
326 {
327 long v;
328
329 if(a->type >= D_INDIR || 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_NONE:
391 return Ynone;
392
393 case D_CS: return Ycs;
394 case D_SS: return Yss;
395 case D_DS: return Yds;
396 case D_ES: return Yes;
397 case D_FS: return Yfs;
398 case D_GS: return Ygs;
399
400 case D_GDTR: return Ygdtr;
401 case D_IDTR: return Yidtr;
402 case D_LDTR: return Yldtr;
403 case D_MSW: return Ymsw;
404 case D_TASK: return Ytask;
405
406 case D_CR+0: return Ycr0;
407 case D_CR+1: return Ycr1;
408 case D_CR+2: return Ycr2;
409 case D_CR+3: return Ycr3;
410 case D_CR+4: return Ycr4;
411 case D_CR+5: return Ycr5;
412 case D_CR+6: return Ycr6;
413 case D_CR+7: return Ycr7;
414
415 case D_DR+0: return Ydr0;
416 case D_DR+1: return Ydr1;
417 case D_DR+2: return Ydr2;
418 case D_DR+3: return Ydr3;
419 case D_DR+4: return Ydr4;
420 case D_DR+5: return Ydr5;
421 case D_DR+6: return Ydr6;
422 case D_DR+7: return Ydr7;
423
424 case D_TR+0: return Ytr0;
425 case D_TR+1: return Ytr1;
426 case D_TR+2: return Ytr2;
427 case D_TR+3: return Ytr3;
428 case D_TR+4: return Ytr4;
429 case D_TR+5: return Ytr5;
430 case D_TR+6: return Ytr6;
431 case D_TR+7: return Ytr7;
432
433 case D_EXTERN:
434 case D_STATIC:
435 case D_AUTO:
436 case D_PARAM:
437 return Ym;
438
439 case D_CONST:
440 case D_ADDR:
441 if(a->sym == S) {
442 v = a->offset;
443 if(v == 0)
444 return Yi0;
445 if(v == 1)
446 return Yi1;
447 if(v >= -128 && v <= 127)
448 return Yi8;
449 }
450 return Yi32;
451
452 case D_BRANCH:
453 return Ybr;
454 }
455 return Yxxx;
456 }
457
458 void
asmidx(Adr * a,int base)459 asmidx(Adr *a, int base)
460 {
461 int i;
462
463 switch(a->index) {
464 default:
465 goto bad;
466
467 case D_NONE:
468 i = 4 << 3;
469 goto bas;
470
471 case D_AX:
472 case D_CX:
473 case D_DX:
474 case D_BX:
475 case D_BP:
476 case D_SI:
477 case D_DI:
478 i = reg[a->index] << 3;
479 break;
480 }
481 switch(a->scale) {
482 default:
483 goto bad;
484 case 1:
485 break;
486 case 2:
487 i |= (1<<6);
488 break;
489 case 4:
490 i |= (2<<6);
491 break;
492 case 8:
493 i |= (3<<6);
494 break;
495 }
496 bas:
497 switch(base) {
498 default:
499 goto bad;
500 case D_NONE: /* must be mod=00 */
501 i |= 5;
502 break;
503 case D_AX:
504 case D_CX:
505 case D_DX:
506 case D_BX:
507 case D_SP:
508 case D_BP:
509 case D_SI:
510 case D_DI:
511 i |= reg[base];
512 break;
513 }
514 *andptr++ = i;
515 return;
516 bad:
517 diag("asmidx: bad address %D", a);
518 *andptr++ = 0;
519 return;
520 }
521
522 static void
put4(long v)523 put4(long v)
524 {
525 if(dlm && curp != P && reloca != nil){
526 dynreloc(reloca->sym, curp->pc + andptr - &and[0], 1);
527 reloca = nil;
528 }
529 andptr[0] = v;
530 andptr[1] = v>>8;
531 andptr[2] = v>>16;
532 andptr[3] = v>>24;
533 andptr += 4;
534 }
535
536 long
vaddr(Adr * a)537 vaddr(Adr *a)
538 {
539 int t;
540 long v;
541 Sym *s;
542
543 t = a->type;
544 v = a->offset;
545 if(t == D_ADDR)
546 t = a->index;
547 switch(t) {
548 case D_STATIC:
549 case D_EXTERN:
550 s = a->sym;
551 if(s != nil) {
552 if(dlm && curp != P)
553 reloca = a;
554 switch(s->type) {
555 case SUNDEF:
556 ckoff(s, v);
557 case STEXT:
558 case SCONST:
559 v += s->value;
560 break;
561 default:
562 v += INITDAT + s->value;
563 }
564 }
565 }
566 return v;
567 }
568
569 void
asmand(Adr * a,int r)570 asmand(Adr *a, int r)
571 {
572 long v;
573 int t;
574 Adr aa;
575
576 v = a->offset;
577 t = a->type;
578 if(a->index != D_NONE) {
579 if(t >= D_INDIR) {
580 t -= D_INDIR;
581 if(t == D_NONE) {
582 *andptr++ = (0 << 6) | (4 << 0) | (r << 3);
583 asmidx(a, t);
584 put4(v);
585 return;
586 }
587 if(v == 0 && t != D_BP) {
588 *andptr++ = (0 << 6) | (4 << 0) | (r << 3);
589 asmidx(a, t);
590 return;
591 }
592 if(v >= -128 && v < 128) {
593 *andptr++ = (1 << 6) | (4 << 0) | (r << 3);
594 asmidx(a, t);
595 *andptr++ = v;
596 return;
597 }
598 *andptr++ = (2 << 6) | (4 << 0) | (r << 3);
599 asmidx(a, t);
600 put4(v);
601 return;
602 }
603 switch(t) {
604 default:
605 goto bad;
606 case D_STATIC:
607 case D_EXTERN:
608 aa.type = D_NONE+D_INDIR;
609 break;
610 case D_AUTO:
611 case D_PARAM:
612 aa.type = D_SP+D_INDIR;
613 break;
614 }
615 aa.offset = vaddr(a);
616 aa.index = a->index;
617 aa.scale = a->scale;
618 asmand(&aa, r);
619 return;
620 }
621 if(t >= D_AL && t <= D_F0+7) {
622 if(v)
623 goto bad;
624 *andptr++ = (3 << 6) | (reg[t] << 0) | (r << 3);
625 return;
626 }
627 if(t >= D_INDIR) {
628 t -= D_INDIR;
629 if(t == D_NONE || D_CS <= t && t <= D_GS) {
630 *andptr++ = (0 << 6) | (5 << 0) | (r << 3);
631 put4(v);
632 return;
633 }
634 if(t == D_SP) {
635 if(v == 0) {
636 *andptr++ = (0 << 6) | (4 << 0) | (r << 3);
637 asmidx(a, D_SP);
638 return;
639 }
640 if(v >= -128 && v < 128) {
641 *andptr++ = (1 << 6) | (4 << 0) | (r << 3);
642 asmidx(a, D_SP);
643 *andptr++ = v;
644 return;
645 }
646 *andptr++ = (2 << 6) | (4 << 0) | (r << 3);
647 asmidx(a, D_SP);
648 put4(v);
649 return;
650 }
651 if(t >= D_AX && t <= D_DI) {
652 if(v == 0 && t != D_BP) {
653 *andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3);
654 return;
655 }
656 if(v >= -128 && v < 128) {
657 andptr[0] = (1 << 6) | (reg[t] << 0) | (r << 3);
658 andptr[1] = v;
659 andptr += 2;
660 return;
661 }
662 *andptr++ = (2 << 6) | (reg[t] << 0) | (r << 3);
663 put4(v);
664 return;
665 }
666 goto bad;
667 }
668 switch(a->type) {
669 default:
670 goto bad;
671 case D_STATIC:
672 case D_EXTERN:
673 aa.type = D_NONE+D_INDIR;
674 break;
675 case D_AUTO:
676 case D_PARAM:
677 aa.type = D_SP+D_INDIR;
678 break;
679 }
680 aa.index = D_NONE;
681 aa.scale = 1;
682 aa.offset = vaddr(a);
683 asmand(&aa, r);
684 return;
685 bad:
686 diag("asmand: bad address %D", a);
687 return;
688 }
689
690 #define E 0xff
691 uchar ymovtab[] =
692 {
693 /* push */
694 APUSHL, Ycs, Ynone, 0, 0x0e,E,0,0,
695 APUSHL, Yss, Ynone, 0, 0x16,E,0,0,
696 APUSHL, Yds, Ynone, 0, 0x1e,E,0,0,
697 APUSHL, Yes, Ynone, 0, 0x06,E,0,0,
698 APUSHL, Yfs, Ynone, 0, 0x0f,0xa0,E,0,
699 APUSHL, Ygs, Ynone, 0, 0x0f,0xa8,E,0,
700
701 APUSHW, Ycs, Ynone, 0, Pe,0x0e,E,0,
702 APUSHW, Yss, Ynone, 0, Pe,0x16,E,0,
703 APUSHW, Yds, Ynone, 0, Pe,0x1e,E,0,
704 APUSHW, Yes, Ynone, 0, Pe,0x06,E,0,
705 APUSHW, Yfs, Ynone, 0, Pe,0x0f,0xa0,E,
706 APUSHW, Ygs, Ynone, 0, Pe,0x0f,0xa8,E,
707
708 /* pop */
709 APOPL, Ynone, Yds, 0, 0x1f,E,0,0,
710 APOPL, Ynone, Yes, 0, 0x07,E,0,0,
711 APOPL, Ynone, Yss, 0, 0x17,E,0,0,
712 APOPL, Ynone, Yfs, 0, 0x0f,0xa1,E,0,
713 APOPL, Ynone, Ygs, 0, 0x0f,0xa9,E,0,
714
715 APOPW, Ynone, Yds, 0, Pe,0x1f,E,0,
716 APOPW, Ynone, Yes, 0, Pe,0x07,E,0,
717 APOPW, Ynone, Yss, 0, Pe,0x17,E,0,
718 APOPW, Ynone, Yfs, 0, Pe,0x0f,0xa1,E,
719 APOPW, Ynone, Ygs, 0, Pe,0x0f,0xa9,E,
720
721 /* mov seg */
722 AMOVW, Yes, Yml, 1, 0x8c,0,0,0,
723 AMOVW, Ycs, Yml, 1, 0x8c,1,0,0,
724 AMOVW, Yss, Yml, 1, 0x8c,2,0,0,
725 AMOVW, Yds, Yml, 1, 0x8c,3,0,0,
726 AMOVW, Yfs, Yml, 1, 0x8c,4,0,0,
727 AMOVW, Ygs, Yml, 1, 0x8c,5,0,0,
728
729 AMOVW, Yml, Yes, 2, 0x8e,0,0,0,
730 AMOVW, Yml, Ycs, 2, 0x8e,1,0,0,
731 AMOVW, Yml, Yss, 2, 0x8e,2,0,0,
732 AMOVW, Yml, Yds, 2, 0x8e,3,0,0,
733 AMOVW, Yml, Yfs, 2, 0x8e,4,0,0,
734 AMOVW, Yml, Ygs, 2, 0x8e,5,0,0,
735
736 /* mov cr */
737 AMOVL, Ycr0, Yml, 3, 0x0f,0x20,0,0,
738 AMOVL, Ycr2, Yml, 3, 0x0f,0x20,2,0,
739 AMOVL, Ycr3, Yml, 3, 0x0f,0x20,3,0,
740 AMOVL, Ycr4, Yml, 3, 0x0f,0x20,4,0,
741
742 AMOVL, Yml, Ycr0, 4, 0x0f,0x22,0,0,
743 AMOVL, Yml, Ycr2, 4, 0x0f,0x22,2,0,
744 AMOVL, Yml, Ycr3, 4, 0x0f,0x22,3,0,
745 AMOVL, Yml, Ycr4, 4, 0x0f,0x22,4,0,
746
747 /* mov dr */
748 AMOVL, Ydr0, Yml, 3, 0x0f,0x21,0,0,
749 AMOVL, Ydr6, Yml, 3, 0x0f,0x21,6,0,
750 AMOVL, Ydr7, Yml, 3, 0x0f,0x21,7,0,
751
752 AMOVL, Yml, Ydr0, 4, 0x0f,0x23,0,0,
753 AMOVL, Yml, Ydr6, 4, 0x0f,0x23,6,0,
754 AMOVL, Yml, Ydr7, 4, 0x0f,0x23,7,0,
755
756 /* mov tr */
757 AMOVL, Ytr6, Yml, 3, 0x0f,0x24,6,0,
758 AMOVL, Ytr7, Yml, 3, 0x0f,0x24,7,0,
759
760 AMOVL, Yml, Ytr6, 4, 0x0f,0x26,6,E,
761 AMOVL, Yml, Ytr7, 4, 0x0f,0x26,7,E,
762
763 /* lgdt, sgdt, lidt, sidt */
764 AMOVL, Ym, Ygdtr, 4, 0x0f,0x01,2,0,
765 AMOVL, Ygdtr, Ym, 3, 0x0f,0x01,0,0,
766 AMOVL, Ym, Yidtr, 4, 0x0f,0x01,3,0,
767 AMOVL, Yidtr, Ym, 3, 0x0f,0x01,1,0,
768
769 /* lldt, sldt */
770 AMOVW, Yml, Yldtr, 4, 0x0f,0x00,2,0,
771 AMOVW, Yldtr, Yml, 3, 0x0f,0x00,0,0,
772
773 /* lmsw, smsw */
774 AMOVW, Yml, Ymsw, 4, 0x0f,0x01,6,0,
775 AMOVW, Ymsw, Yml, 3, 0x0f,0x01,4,0,
776
777 /* ltr, str */
778 AMOVW, Yml, Ytask, 4, 0x0f,0x00,3,0,
779 AMOVW, Ytask, Yml, 3, 0x0f,0x00,1,0,
780
781 /* load full pointer */
782 AMOVL, Yml, Ycol, 5, 0,0,0,0,
783 AMOVW, Yml, Ycol, 5, Pe,0,0,0,
784
785 /* double shift */
786 ASHLL, Ycol, Yml, 6, 0xa4,0xa5,0,0,
787 ASHRL, Ycol, Yml, 6, 0xac,0xad,0,0,
788
789 /* extra imul */
790 AIMULW, Yml, Yrl, 7, Pq,0xaf,0,0,
791 AIMULL, Yml, Yrl, 7, Pm,0xaf,0,0,
792 0
793 };
794
795 int
isax(Adr * a)796 isax(Adr *a)
797 {
798
799 switch(a->type) {
800 case D_AX:
801 case D_AL:
802 case D_AH:
803 case D_INDIR+D_AX:
804 return 1;
805 }
806 if(a->index == D_AX)
807 return 1;
808 return 0;
809 }
810
811 void
subreg(Prog * p,int from,int to)812 subreg(Prog *p, int from, int to)
813 {
814
815 if(debug['Q'])
816 print("\n%P s/%R/%R/\n", p, from, to);
817
818 if(p->from.type == from)
819 p->from.type = to;
820 if(p->to.type == from)
821 p->to.type = to;
822
823 if(p->from.index == from)
824 p->from.index = to;
825 if(p->to.index == from)
826 p->to.index = to;
827
828 from += D_INDIR;
829 if(p->from.type == from)
830 p->from.type = to+D_INDIR;
831 if(p->to.type == from)
832 p->to.type = to+D_INDIR;
833
834 if(debug['Q'])
835 print("%P\n", p);
836 }
837
838 void
doasm(Prog * p)839 doasm(Prog *p)
840 {
841 Optab *o;
842 Prog *q, pp;
843 uchar *t;
844 int z, op, ft, tt;
845 long v, pre;
846
847 pre = prefixof(&p->from);
848 if(pre)
849 *andptr++ = pre;
850 pre = prefixof(&p->to);
851 if(pre)
852 *andptr++ = pre;
853
854 o = &optab[p->as];
855 ft = oclass(&p->from) * Ymax;
856 tt = oclass(&p->to) * Ymax;
857 t = o->ytab;
858 if(t == 0) {
859 diag("asmins: noproto %P", p);
860 return;
861 }
862 for(z=0; *t; z+=t[3],t+=4)
863 if(ycover[ft+t[0]])
864 if(ycover[tt+t[1]])
865 goto found;
866 goto domov;
867
868 found:
869 switch(o->prefix) {
870 case Pq: /* 16 bit escape and opcode escape */
871 *andptr++ = Pe;
872 *andptr++ = Pm;
873 break;
874
875 case Pm: /* opcode escape */
876 *andptr++ = Pm;
877 break;
878
879 case Pe: /* 16 bit escape */
880 *andptr++ = Pe;
881 break;
882
883 case Pb: /* botch */
884 break;
885 }
886 v = vaddr(&p->from);
887 op = o->op[z];
888 switch(t[2]) {
889 default:
890 diag("asmins: unknown z %d %P", t[2], p);
891 return;
892
893 case Zpseudo:
894 break;
895
896 case Zlit:
897 for(; op = o->op[z]; z++)
898 *andptr++ = op;
899 break;
900
901 case Zm_r:
902 *andptr++ = op;
903 asmand(&p->from, reg[p->to.type]);
904 break;
905
906 case Zaut_r:
907 *andptr++ = 0x8d; /* leal */
908 if(p->from.type != D_ADDR)
909 diag("asmins: Zaut sb type ADDR");
910 p->from.type = p->from.index;
911 p->from.index = D_NONE;
912 asmand(&p->from, reg[p->to.type]);
913 p->from.index = p->from.type;
914 p->from.type = D_ADDR;
915 break;
916
917 case Zm_o:
918 *andptr++ = op;
919 asmand(&p->from, o->op[z+1]);
920 break;
921
922 case Zr_m:
923 *andptr++ = op;
924 asmand(&p->to, reg[p->from.type]);
925 break;
926
927 case Zo_m:
928 *andptr++ = op;
929 asmand(&p->to, o->op[z+1]);
930 break;
931
932 case Zm_ibo:
933 v = vaddr(&p->to);
934 *andptr++ = op;
935 asmand(&p->from, o->op[z+1]);
936 *andptr++ = v;
937 break;
938
939 case Zibo_m:
940 *andptr++ = op;
941 asmand(&p->to, o->op[z+1]);
942 *andptr++ = v;
943 break;
944
945 case Z_ib:
946 v = vaddr(&p->to);
947 case Zib_:
948 *andptr++ = op;
949 *andptr++ = v;
950 break;
951
952 case Zib_rp:
953 *andptr++ = op + reg[p->to.type];
954 *andptr++ = v;
955 break;
956
957 case Zil_rp:
958 *andptr++ = op + reg[p->to.type];
959 if(o->prefix == Pe) {
960 *andptr++ = v;
961 *andptr++ = v>>8;
962 }
963 else
964 put4(v);
965 break;
966
967 case Zib_rr:
968 *andptr++ = op;
969 asmand(&p->to, reg[p->to.type]);
970 *andptr++ = v;
971 break;
972
973 case Z_il:
974 v = vaddr(&p->to);
975 case Zil_:
976 *andptr++ = op;
977 if(o->prefix == Pe) {
978 *andptr++ = v;
979 *andptr++ = v>>8;
980 }
981 else
982 put4(v);
983 break;
984
985 case Zm_ilo:
986 v = vaddr(&p->to);
987 *andptr++ = op;
988 asmand(&p->from, o->op[z+1]);
989 if(o->prefix == Pe) {
990 *andptr++ = v;
991 *andptr++ = v>>8;
992 }
993 else
994 put4(v);
995 break;
996
997 case Zilo_m:
998 *andptr++ = op;
999 asmand(&p->to, o->op[z+1]);
1000 if(o->prefix == Pe) {
1001 *andptr++ = v;
1002 *andptr++ = v>>8;
1003 }
1004 else
1005 put4(v);
1006 break;
1007
1008 case Zil_rr:
1009 *andptr++ = op;
1010 asmand(&p->to, reg[p->to.type]);
1011 if(o->prefix == Pe) {
1012 *andptr++ = v;
1013 *andptr++ = v>>8;
1014 }
1015 else
1016 put4(v);
1017 break;
1018
1019 case Z_rp:
1020 *andptr++ = op + reg[p->to.type];
1021 break;
1022
1023 case Zrp_:
1024 *andptr++ = op + reg[p->from.type];
1025 break;
1026
1027 case Zclr:
1028 *andptr++ = op;
1029 asmand(&p->to, reg[p->to.type]);
1030 break;
1031
1032 case Zbr:
1033 q = p->pcond;
1034 if(q) {
1035 v = q->pc - p->pc - 2;
1036 if(v >= -128 && v <= 127) {
1037 *andptr++ = op;
1038 *andptr++ = v;
1039 } else {
1040 v -= 6-2;
1041 *andptr++ = 0x0f;
1042 *andptr++ = o->op[z+1];
1043 *andptr++ = v;
1044 *andptr++ = v>>8;
1045 *andptr++ = v>>16;
1046 *andptr++ = v>>24;
1047 }
1048 }
1049 break;
1050
1051 case Zcall:
1052 q = p->pcond;
1053 if(q) {
1054 v = q->pc - p->pc - 5;
1055 if(dlm && curp != P && p->to.sym->type == SUNDEF){
1056 /* v = 0 - p->pc - 5; */
1057 v = 0;
1058 ckoff(p->to.sym, v);
1059 v += p->to.sym->value;
1060 dynreloc(p->to.sym, p->pc+1, 0);
1061 }
1062 *andptr++ = op;
1063 *andptr++ = v;
1064 *andptr++ = v>>8;
1065 *andptr++ = v>>16;
1066 *andptr++ = v>>24;
1067 }
1068 break;
1069
1070 case Zjmp:
1071 q = p->pcond;
1072 if(q) {
1073 v = q->pc - p->pc - 2;
1074 if(v >= -128 && v <= 127) {
1075 *andptr++ = op;
1076 *andptr++ = v;
1077 } else {
1078 v -= 5-2;
1079 *andptr++ = o->op[z+1];
1080 *andptr++ = v;
1081 *andptr++ = v>>8;
1082 *andptr++ = v>>16;
1083 *andptr++ = v>>24;
1084 }
1085 }
1086 break;
1087
1088 case Zloop:
1089 q = p->pcond;
1090 if(q) {
1091 v = q->pc - p->pc - 2;
1092 if(v < -128 || v > 127)
1093 diag("loop too far: %P", p);
1094 *andptr++ = op;
1095 *andptr++ = v;
1096 }
1097 break;
1098
1099 case Zbyte:
1100 *andptr++ = v;
1101 if(op > 1) {
1102 *andptr++ = v>>8;
1103 if(op > 2) {
1104 *andptr++ = v>>16;
1105 *andptr++ = v>>24;
1106 }
1107 }
1108 break;
1109
1110 case Zmov:
1111 goto domov;
1112 }
1113 return;
1114
1115 domov:
1116 for(t=ymovtab; *t; t+=8)
1117 if(p->as == t[0])
1118 if(ycover[ft+t[1]])
1119 if(ycover[tt+t[2]])
1120 goto mfound;
1121 bad:
1122 /*
1123 * here, the assembly has failed.
1124 * if its a byte instruction that has
1125 * unaddressable registers, try to
1126 * exchange registers and reissue the
1127 * instruction with the operands renamed.
1128 */
1129 pp = *p;
1130 z = p->from.type;
1131 if(z >= D_BP && z <= D_DI) {
1132 if(isax(&p->to)) {
1133 *andptr++ = 0x87; /* xchg lhs,bx */
1134 asmand(&p->from, reg[D_BX]);
1135 subreg(&pp, z, D_BX);
1136 doasm(&pp);
1137 *andptr++ = 0x87; /* xchg lhs,bx */
1138 asmand(&p->from, reg[D_BX]);
1139 } else {
1140 *andptr++ = 0x90 + reg[z]; /* xchg lsh,ax */
1141 subreg(&pp, z, D_AX);
1142 doasm(&pp);
1143 *andptr++ = 0x90 + reg[z]; /* xchg lsh,ax */
1144 }
1145 return;
1146 }
1147 z = p->to.type;
1148 if(z >= D_BP && z <= D_DI) {
1149 if(isax(&p->from)) {
1150 *andptr++ = 0x87; /* xchg rhs,bx */
1151 asmand(&p->to, reg[D_BX]);
1152 subreg(&pp, z, D_BX);
1153 doasm(&pp);
1154 *andptr++ = 0x87; /* xchg rhs,bx */
1155 asmand(&p->to, reg[D_BX]);
1156 } else {
1157 *andptr++ = 0x90 + reg[z]; /* xchg rsh,ax */
1158 subreg(&pp, z, D_AX);
1159 doasm(&pp);
1160 *andptr++ = 0x90 + reg[z]; /* xchg rsh,ax */
1161 }
1162 return;
1163 }
1164 diag("doasm: notfound t2=%ux from=%ux to=%ux %P", t[2], p->from.type, p->to.type, p);
1165 return;
1166
1167 mfound:
1168 switch(t[3]) {
1169 default:
1170 diag("asmins: unknown mov %d %P", t[3], p);
1171 break;
1172
1173 case 0: /* lit */
1174 for(z=4; t[z]!=E; z++)
1175 *andptr++ = t[z];
1176 break;
1177
1178 case 1: /* r,m */
1179 *andptr++ = t[4];
1180 asmand(&p->to, t[5]);
1181 break;
1182
1183 case 2: /* m,r */
1184 *andptr++ = t[4];
1185 asmand(&p->from, t[5]);
1186 break;
1187
1188 case 3: /* r,m - 2op */
1189 *andptr++ = t[4];
1190 *andptr++ = t[5];
1191 asmand(&p->to, t[6]);
1192 break;
1193
1194 case 4: /* m,r - 2op */
1195 *andptr++ = t[4];
1196 *andptr++ = t[5];
1197 asmand(&p->from, t[6]);
1198 break;
1199
1200 case 5: /* load full pointer, trash heap */
1201 if(t[4])
1202 *andptr++ = t[4];
1203 switch(p->to.index) {
1204 default:
1205 goto bad;
1206 case D_DS:
1207 *andptr++ = 0xc5;
1208 break;
1209 case D_SS:
1210 *andptr++ = 0x0f;
1211 *andptr++ = 0xb2;
1212 break;
1213 case D_ES:
1214 *andptr++ = 0xc4;
1215 break;
1216 case D_FS:
1217 *andptr++ = 0x0f;
1218 *andptr++ = 0xb4;
1219 break;
1220 case D_GS:
1221 *andptr++ = 0x0f;
1222 *andptr++ = 0xb5;
1223 break;
1224 }
1225 asmand(&p->from, reg[p->to.type]);
1226 break;
1227
1228 case 6: /* double shift */
1229 z = p->from.type;
1230 switch(z) {
1231 default:
1232 goto bad;
1233 case D_CONST:
1234 *andptr++ = 0x0f;
1235 *andptr++ = t[4];
1236 asmand(&p->to, reg[p->from.index]);
1237 *andptr++ = p->from.offset;
1238 break;
1239 case D_CL:
1240 case D_CX:
1241 *andptr++ = 0x0f;
1242 *andptr++ = t[5];
1243 asmand(&p->to, reg[p->from.index]);
1244 break;
1245 }
1246 break;
1247
1248 case 7: /* imul rm,r */
1249 *andptr++ = t[4];
1250 *andptr++ = t[5];
1251 asmand(&p->from, reg[p->to.type]);
1252 break;
1253 }
1254 }
1255
1256 void
asmins(Prog * p)1257 asmins(Prog *p)
1258 {
1259
1260 andptr = and;
1261 doasm(p);
1262 }
1263
1264 enum{
1265 ABSD = 0,
1266 ABSU = 1,
1267 RELD = 2,
1268 RELU = 3,
1269 };
1270
1271 int modemap[4] = { 0, 1, -1, 2, };
1272
1273 typedef struct Reloc Reloc;
1274
1275 struct Reloc
1276 {
1277 int n;
1278 int t;
1279 uchar *m;
1280 ulong *a;
1281 };
1282
1283 Reloc rels;
1284
1285 static void
grow(Reloc * r)1286 grow(Reloc *r)
1287 {
1288 int t;
1289 uchar *m, *nm;
1290 ulong *a, *na;
1291
1292 t = r->t;
1293 r->t += 64;
1294 m = r->m;
1295 a = r->a;
1296 r->m = nm = malloc(r->t*sizeof(uchar));
1297 r->a = na = malloc(r->t*sizeof(ulong));
1298 memmove(nm, m, t*sizeof(uchar));
1299 memmove(na, a, t*sizeof(ulong));
1300 free(m);
1301 free(a);
1302 }
1303
1304 void
dynreloc(Sym * s,ulong v,int abs)1305 dynreloc(Sym *s, ulong v, int abs)
1306 {
1307 int i, k, n;
1308 uchar *m;
1309 ulong *a;
1310 Reloc *r;
1311
1312 if(s->type == SUNDEF)
1313 k = abs ? ABSU : RELU;
1314 else
1315 k = abs ? ABSD : RELD;
1316 /* Bprint(&bso, "R %s a=%ld(%lx) %d\n", s->name, v, v, k); */
1317 k = modemap[k];
1318 r = &rels;
1319 n = r->n;
1320 if(n >= r->t)
1321 grow(r);
1322 m = r->m;
1323 a = r->a;
1324 for(i = n; i > 0; i--){
1325 if(v < a[i-1]){ /* happens occasionally for data */
1326 m[i] = m[i-1];
1327 a[i] = a[i-1];
1328 }
1329 else
1330 break;
1331 }
1332 m[i] = k;
1333 a[i] = v;
1334 r->n++;
1335 }
1336
1337 static int
sput(char * s)1338 sput(char *s)
1339 {
1340 char *p;
1341
1342 p = s;
1343 while(*s)
1344 cput(*s++);
1345 cput(0);
1346 return s-p+1;
1347 }
1348
1349 void
asmdyn()1350 asmdyn()
1351 {
1352 int i, n, t, c;
1353 Sym *s;
1354 ulong la, ra, *a;
1355 vlong off;
1356 uchar *m;
1357 Reloc *r;
1358
1359 cflush();
1360 off = seek(cout, 0, 1);
1361 lput(0);
1362 t = 0;
1363 lput(imports);
1364 t += 4;
1365 for(i = 0; i < NHASH; i++)
1366 for(s = hash[i]; s != S; s = s->link)
1367 if(s->type == SUNDEF){
1368 lput(s->sig);
1369 t += 4;
1370 t += sput(s->name);
1371 }
1372
1373 la = 0;
1374 r = &rels;
1375 n = r->n;
1376 m = r->m;
1377 a = r->a;
1378 lput(n);
1379 t += 4;
1380 for(i = 0; i < n; i++){
1381 ra = *a-la;
1382 if(*a < la)
1383 diag("bad relocation order");
1384 if(ra < 256)
1385 c = 0;
1386 else if(ra < 65536)
1387 c = 1;
1388 else
1389 c = 2;
1390 cput((c<<6)|*m++);
1391 t++;
1392 if(c == 0){
1393 cput(ra);
1394 t++;
1395 }
1396 else if(c == 1){
1397 wput(ra);
1398 t += 2;
1399 }
1400 else{
1401 lput(ra);
1402 t += 4;
1403 }
1404 la = *a++;
1405 }
1406
1407 cflush();
1408 seek(cout, off, 0);
1409 lput(t);
1410
1411 if(debug['v']){
1412 Bprint(&bso, "import table entries = %d\n", imports);
1413 Bprint(&bso, "export table entries = %d\n", exports);
1414 }
1415 }
1416