10 xdefine("etext", STEXT, 0L);
12 for(p = firstp; p != P; p = p->link) {
16 if(p->to.type == D_BRANCH)
19 if((q = p->pcond) != P)
41 Bprint(&bso, "%5.2f span\n", cputime());
44 for(p = firstp; p != P; p = p->link) {
47 if(p->to.type == D_BRANCH)
60 Bprint(&bso, "%5.2f span %d\n", cputime(), n);
63 print("span must be looping\n");
68 for(p = firstp; p != P; p = p->link) {
71 if(p->to.type == D_BRANCH) {
89 INITDAT = rnd(c, INITRND);
95 xdefine("etext", STEXT, c);
97 Bprint(&bso, "etext = %lux\n", c);
99 for(p = textp; p != P; p = p->pcond)
100 p->from.sym->value = p->pc;
101 textsize = c - INITTEXT;
105 xdefine(char *p, int t, long v)
110 if(s->type == 0 || s->type == SXREF) {
114 if(s->type == STEXT && s->value == 0)
119 putsymb(char *s, int t, long v, int ver)
128 cput(t+0x80); /* 0x80 is variable length */
130 if(t == 'Z' || t == 'z') {
132 for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
145 symsize += 4 + 1 + i + 1;
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);
158 Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver);
160 Bprint(&bso, "%c %.8lux %s\n", t, v, s);
172 s = lookup("etext", 0);
174 putsymb(s->name, 'T', s->value, s->version);
176 for(h=0; h<NHASH; h++)
177 for(s=hash[h]; s!=S; s=s->link)
180 putsymb(s->name, 'D', s->value, s->version);
184 putsymb(s->name, 'D', s->value+INITDAT, s->version);
188 putsymb(s->name, 'B', s->value+INITDAT, s->version);
192 putsymb(s->name, 'f', s->value, s->version);
196 for(p=textp; p!=P; p=p->pcond) {
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);
206 if(a->type == D_FILE1)
207 putsymb(a->asym->name, 'Z', a->aoffset, 0);
209 putsymb(s->name, 'T', s->value, s->version);
211 /* frame, auto and param after */
212 putsymb(".frame", 'm', p->to.offset+4, 0);
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);
218 if(a->type == D_PARAM)
219 putsymb(a->asym->name, 'p', a->aoffset, 0);
221 if(debug['v'] || debug['n'])
222 Bprint(&bso, "symsize = %lud\n", symsize);
235 for(p = firstp; p != P; p = p->link) {
236 if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
240 Bprint(&bso, "%6lux %P\n",
245 Bprint(&bso, "\t\t%6ld", lcsize);
246 v = (p->pc - oldpc) / MINLC;
251 cput(s+128); /* 129-255 +pc */
253 Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
259 oldpc = p->pc + MINLC;
260 if(s > 64 || s < -64) {
261 cput(0); /* 0 vv +lc */
268 Bprint(&bso, " lc+%ld(%d,%ld)\n",
271 Bprint(&bso, " lc%ld(%d,%ld)\n",
273 Bprint(&bso, "%6lux %P\n",
280 cput(0+s); /* 1-64 +lc */
282 Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
283 Bprint(&bso, "%6lux %P\n",
287 cput(64-s); /* 65-128 -lc */
289 Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
290 Bprint(&bso, "%6lux %P\n",
301 if(debug['v'] || debug['L'])
302 Bprint(&bso, "lcsize = %ld\n", lcsize);
311 if(a->type >= D_INDIR || a->index != D_NONE) {
312 if(a->index != D_NONE && a->scale == 0) {
313 if(a->type == D_ADDR) {
373 case D_CS: return Ycs;
374 case D_SS: return Yss;
375 case D_DS: return Yds;
376 case D_ES: return Yes;
377 case D_FS: return Yfs;
378 case D_GS: return Ygs;
380 case D_GDTR: return Ygdtr;
381 case D_IDTR: return Yidtr;
382 case D_LDTR: return Yldtr;
383 case D_MSW: return Ymsw;
384 case D_TASK: return Ytask;
386 case D_CR+0: return Ycr0;
387 case D_CR+1: return Ycr1;
388 case D_CR+2: return Ycr2;
389 case D_CR+3: return Ycr3;
390 case D_CR+4: return Ycr4;
391 case D_CR+5: return Ycr5;
392 case D_CR+6: return Ycr6;
393 case D_CR+7: return Ycr7;
395 case D_DR+0: return Ydr0;
396 case D_DR+1: return Ydr1;
397 case D_DR+2: return Ydr2;
398 case D_DR+3: return Ydr3;
399 case D_DR+4: return Ydr4;
400 case D_DR+5: return Ydr5;
401 case D_DR+6: return Ydr6;
402 case D_DR+7: return Ydr7;
404 case D_TR+0: return Ytr0;
405 case D_TR+1: return Ytr1;
406 case D_TR+2: return Ytr2;
407 case D_TR+3: return Ytr3;
408 case D_TR+4: return Ytr4;
409 case D_TR+5: return Ytr5;
410 case D_TR+6: return Ytr6;
411 case D_TR+7: return Ytr7;
427 if(v >= -128 && v <= 127)
439 asmidx(Adr *a, int base)
458 i = reg[a->index] << 3;
480 case D_NONE: /* must be mod=00 */
497 diag("asmidx: bad address %D", a);
505 if(dlm && curp != P && reloca != nil){
506 dynreloc(reloca->sym, curp->pc + andptr - &and[0], 1);
542 v += INITDAT + s->value;
550 asmand(Adr *a, int r)
558 if(a->index != D_NONE) {
562 *andptr++ = (0 << 6) | (4 << 0) | (r << 3);
567 if(v == 0 && t != D_BP) {
568 *andptr++ = (0 << 6) | (4 << 0) | (r << 3);
572 if(v >= -128 && v < 128) {
573 *andptr++ = (1 << 6) | (4 << 0) | (r << 3);
578 *andptr++ = (2 << 6) | (4 << 0) | (r << 3);
588 aa.type = D_NONE+D_INDIR;
592 aa.type = D_SP+D_INDIR;
595 aa.offset = vaddr(a);
601 if(t >= D_AL && t <= D_F0+7) {
604 *andptr++ = (3 << 6) | (reg[t] << 0) | (r << 3);
610 *andptr++ = (0 << 6) | (5 << 0) | (r << 3);
616 *andptr++ = (0 << 6) | (4 << 0) | (r << 3);
620 if(v >= -128 && v < 128) {
621 *andptr++ = (1 << 6) | (4 << 0) | (r << 3);
626 *andptr++ = (2 << 6) | (4 << 0) | (r << 3);
631 if(t >= D_AX && t <= D_DI) {
632 if(v == 0 && t != D_BP) {
633 *andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3);
636 if(v >= -128 && v < 128) {
637 andptr[0] = (1 << 6) | (reg[t] << 0) | (r << 3);
642 *andptr++ = (2 << 6) | (reg[t] << 0) | (r << 3);
653 aa.type = D_NONE+D_INDIR;
657 aa.type = D_SP+D_INDIR;
662 aa.offset = vaddr(a);
666 diag("asmand: bad address %D", a);
674 APUSHL, Ycs, Ynone, 0, 0x0e,E,0,0,
675 APUSHL, Yss, Ynone, 0, 0x16,E,0,0,
676 APUSHL, Yds, Ynone, 0, 0x1e,E,0,0,
677 APUSHL, Yes, Ynone, 0, 0x06,E,0,0,
678 APUSHL, Yfs, Ynone, 0, 0x0f,0xa0,E,0,
679 APUSHL, Ygs, Ynone, 0, 0x0f,0xa8,E,0,
681 APUSHW, Ycs, Ynone, 0, Pe,0x0e,E,0,
682 APUSHW, Yss, Ynone, 0, Pe,0x16,E,0,
683 APUSHW, Yds, Ynone, 0, Pe,0x1e,E,0,
684 APUSHW, Yes, Ynone, 0, Pe,0x06,E,0,
685 APUSHW, Yfs, Ynone, 0, Pe,0x0f,0xa0,E,
686 APUSHW, Ygs, Ynone, 0, Pe,0x0f,0xa8,E,
689 APOPL, Ynone, Yds, 0, 0x1f,E,0,0,
690 APOPL, Ynone, Yes, 0, 0x07,E,0,0,
691 APOPL, Ynone, Yss, 0, 0x17,E,0,0,
692 APOPL, Ynone, Yfs, 0, 0x0f,0xa1,E,0,
693 APOPL, Ynone, Ygs, 0, 0x0f,0xa9,E,0,
695 APOPW, Ynone, Yds, 0, Pe,0x1f,E,0,
696 APOPW, Ynone, Yes, 0, Pe,0x07,E,0,
697 APOPW, Ynone, Yss, 0, Pe,0x17,E,0,
698 APOPW, Ynone, Yfs, 0, Pe,0x0f,0xa1,E,
699 APOPW, Ynone, Ygs, 0, Pe,0x0f,0xa9,E,
702 AMOVW, Yes, Yml, 1, 0x8c,0,0,0,
703 AMOVW, Ycs, Yml, 1, 0x8c,1,0,0,
704 AMOVW, Yss, Yml, 1, 0x8c,2,0,0,
705 AMOVW, Yds, Yml, 1, 0x8c,3,0,0,
706 AMOVW, Yfs, Yml, 1, 0x8c,4,0,0,
707 AMOVW, Ygs, Yml, 1, 0x8c,5,0,0,
709 AMOVW, Yml, Yes, 2, 0x8e,0,0,0,
710 AMOVW, Yml, Ycs, 2, 0x8e,1,0,0,
711 AMOVW, Yml, Yss, 2, 0x8e,2,0,0,
712 AMOVW, Yml, Yds, 2, 0x8e,3,0,0,
713 AMOVW, Yml, Yfs, 2, 0x8e,4,0,0,
714 AMOVW, Yml, Ygs, 2, 0x8e,5,0,0,
717 AMOVL, Ycr0, Yml, 3, 0x0f,0x20,0,0,
718 AMOVL, Ycr2, Yml, 3, 0x0f,0x20,2,0,
719 AMOVL, Ycr3, Yml, 3, 0x0f,0x20,3,0,
720 AMOVL, Ycr4, Yml, 3, 0x0f,0x20,4,0,
722 AMOVL, Yml, Ycr0, 4, 0x0f,0x22,0,0,
723 AMOVL, Yml, Ycr2, 4, 0x0f,0x22,2,0,
724 AMOVL, Yml, Ycr3, 4, 0x0f,0x22,3,0,
725 AMOVL, Yml, Ycr4, 4, 0x0f,0x22,4,0,
728 AMOVL, Ydr0, Yml, 3, 0x0f,0x21,0,0,
729 AMOVL, Ydr6, Yml, 3, 0x0f,0x21,6,0,
730 AMOVL, Ydr7, Yml, 3, 0x0f,0x21,7,0,
732 AMOVL, Yml, Ydr0, 4, 0x0f,0x23,0,0,
733 AMOVL, Yml, Ydr6, 4, 0x0f,0x23,6,0,
734 AMOVL, Yml, Ydr7, 4, 0x0f,0x23,7,0,
737 AMOVL, Ytr6, Yml, 3, 0x0f,0x24,6,0,
738 AMOVL, Ytr7, Yml, 3, 0x0f,0x24,7,0,
740 AMOVL, Yml, Ytr6, 4, 0x0f,0x26,6,E,
741 AMOVL, Yml, Ytr7, 4, 0x0f,0x26,7,E,
743 /* lgdt, sgdt, lidt, sidt */
744 AMOVL, Ym, Ygdtr, 4, 0x0f,0x01,2,0,
745 AMOVL, Ygdtr, Ym, 3, 0x0f,0x01,0,0,
746 AMOVL, Ym, Yidtr, 4, 0x0f,0x01,3,0,
747 AMOVL, Yidtr, Ym, 3, 0x0f,0x01,1,0,
750 AMOVW, Yml, Yldtr, 4, 0x0f,0x00,2,0,
751 AMOVW, Yldtr, Yml, 3, 0x0f,0x00,0,0,
754 AMOVW, Yml, Ymsw, 4, 0x0f,0x01,6,0,
755 AMOVW, Ymsw, Yml, 3, 0x0f,0x01,4,0,
758 AMOVW, Yml, Ytask, 4, 0x0f,0x00,3,0,
759 AMOVW, Ytask, Yml, 3, 0x0f,0x00,1,0,
761 /* load full pointer */
762 AMOVL, Yml, Ycol, 5, 0,0,0,0,
763 AMOVW, Yml, Ycol, 5, Pe,0,0,0,
766 ASHLL, Ycol, Yml, 6, 0xa4,0xa5,0,0,
767 ASHRL, Ycol, Yml, 6, 0xac,0xad,0,0,
770 AIMULL, Yml, Yrl, 7, Pm,0xaf,0,0,
791 subreg(Prog *p, int from, int to)
795 print("\n%P s/%R/%R/\n", p, from, to);
797 if(p->from.type == from)
799 if(p->to.type == from)
802 if(p->from.index == from)
804 if(p->to.index == from)
808 if(p->from.type == from)
809 p->from.type = to+D_INDIR;
810 if(p->to.type == from)
811 p->to.type = to+D_INDIR;
827 ft = oclass(&p->from) * Ymax;
828 tt = oclass(&p->to) * Ymax;
831 diag("asmins: noproto %P", p);
834 for(z=0; *t; z+=t[3],t+=4)
842 case Pq: /* 16 bit escape and opcode escape */
847 case Pm: /* opcode escape */
851 case Pe: /* 16 bit escape */
862 diag("asmins: unknown z %d %P", t[2], p);
869 for(; op = o->op[z]; z++)
875 asmand(&p->from, reg[p->to.type]);
879 *andptr++ = 0x8d; /* leal */
880 if(p->from.type != D_ADDR)
881 diag("asmins: Zaut sb type ADDR");
882 p->from.type = p->from.index;
883 p->from.index = D_NONE;
884 asmand(&p->from, reg[p->to.type]);
885 p->from.index = p->from.type;
886 p->from.type = D_ADDR;
891 asmand(&p->from, o->op[z+1]);
896 asmand(&p->to, reg[p->from.type]);
901 asmand(&p->to, o->op[z+1]);
907 asmand(&p->from, o->op[z+1]);
913 asmand(&p->to, o->op[z+1]);
925 *andptr++ = op + reg[p->to.type];
930 *andptr++ = op + reg[p->to.type];
931 if(o->prefix == Pe) {
941 asmand(&p->to, reg[p->to.type]);
949 if(o->prefix == Pe) {
960 asmand(&p->from, o->op[z+1]);
961 if(o->prefix == Pe) {
971 asmand(&p->to, o->op[z+1]);
972 if(o->prefix == Pe) {
982 asmand(&p->to, reg[p->to.type]);
983 if(o->prefix == Pe) {
992 *andptr++ = op + reg[p->to.type];
996 *andptr++ = op + reg[p->from.type];
1001 asmand(&p->to, reg[p->to.type]);
1007 v = q->pc - p->pc - 2;
1008 if(v >= -128 && v <= 127) {
1014 *andptr++ = o->op[z+1];
1026 v = q->pc - p->pc - 5;
1027 if(dlm && curp != P && p->to.sym->type == SUNDEF){
1028 /* v = 0 - p->pc - 5; */
1030 ckoff(p->to.sym, v);
1031 v += p->to.sym->value;
1032 dynreloc(p->to.sym, p->pc+1, 0);
1045 v = q->pc - p->pc - 2;
1046 if(v >= -128 && v <= 127) {
1051 *andptr++ = o->op[z+1];
1063 v = q->pc - p->pc - 2;
1064 if(v < -128 && v > 127)
1065 diag("loop too far: %P", p);
1088 for(t=ymovtab; *t; t+=8)
1095 * here, the assembly has failed.
1096 * if its a byte instruction that has
1097 * unaddressable registers, try to
1098 * exchange registers and reissue the
1099 * instruction with the operands renamed.
1103 if(z >= D_BP && z <= D_DI) {
1105 *andptr++ = 0x87; /* xchg lhs,bx */
1106 asmand(&p->from, reg[D_BX]);
1107 subreg(&pp, z, D_BX);
1109 *andptr++ = 0x87; /* xchg lhs,bx */
1110 asmand(&p->from, reg[D_BX]);
1112 *andptr++ = 0x90 + reg[z]; /* xchg lsh,ax */
1113 subreg(&pp, z, D_AX);
1115 *andptr++ = 0x90 + reg[z]; /* xchg lsh,ax */
1120 if(z >= D_BP && z <= D_DI) {
1121 if(isax(&p->from)) {
1122 *andptr++ = 0x87; /* xchg rhs,bx */
1123 asmand(&p->to, reg[D_BX]);
1124 subreg(&pp, z, D_BX);
1126 *andptr++ = 0x87; /* xchg rhs,bx */
1127 asmand(&p->to, reg[D_BX]);
1129 *andptr++ = 0x90 + reg[z]; /* xchg rsh,ax */
1130 subreg(&pp, z, D_AX);
1132 *andptr++ = 0x90 + reg[z]; /* xchg rsh,ax */
1136 diag("doasm: notfound t2=%ux from=%ux to=%ux %P", t[2], p->from.type, p->to.type, p);
1142 diag("asmins: unknown mov %d %P", t[3], p);
1146 for(z=4; t[z]!=E; z++)
1152 asmand(&p->to, t[5]);
1157 asmand(&p->from, t[5]);
1160 case 3: /* r,m - 2op */
1163 asmand(&p->to, t[6]);
1166 case 4: /* m,r - 2op */
1169 asmand(&p->from, t[6]);
1172 case 5: /* load full pointer, trash heap */
1175 switch(p->to.index) {
1197 asmand(&p->from, reg[p->to.type]);
1200 case 6: /* double shift */
1208 asmand(&p->to, reg[p->from.index]);
1209 *andptr++ = p->from.offset;
1215 asmand(&p->to, reg[p->from.index]);
1220 case 7: /* imul rm,r */
1223 asmand(&p->from, reg[p->to.type]);
1243 int modemap[4] = { 0, 1, -1, 2, };
1245 typedef struct Reloc Reloc;
1268 r->m = nm = malloc(r->t*sizeof(uchar));
1269 r->a = na = malloc(r->t*sizeof(ulong));
1270 memmove(nm, m, t*sizeof(uchar));
1271 memmove(na, a, t*sizeof(ulong));
1277 dynreloc(Sym *s, ulong v, int abs)
1284 if(s->type == SUNDEF)
1285 k = abs ? ABSU : RELU;
1287 k = abs ? ABSD : RELD;
1288 /* Bprint(&bso, "R %s a=%ld(%lx) %d\n", s->name, v, v, k); */
1296 for(i = n; i > 0; i--){
1297 if(v < a[i-1]){ /* happens occasionally for data */
1332 off = seek(cout, 0, 1);
1337 for(i = 0; i < NHASH; i++)
1338 for(s = hash[i]; s != S; s = s->link)
1339 if(s->type == SUNDEF){
1352 for(i = 0; i < n; i++){
1355 diag("bad relocation order");
1384 Bprint(&bso, "import table entries = %d\n", imports);
1385 Bprint(&bso, "export table entries = %d\n", exports);