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);
329 if((a->type >= D_INDIR && a->type < D_M0) || a->index != D_NONE) {
330 if(a->index != D_NONE && a->scale == 0) {
331 if(a->type == D_ADDR) {
413 case D_CS: return Ycs;
414 case D_SS: return Yss;
415 case D_DS: return Yds;
416 case D_ES: return Yes;
417 case D_FS: return Yfs;
418 case D_GS: return Ygs;
420 case D_GDTR: return Ygdtr;
421 case D_IDTR: return Yidtr;
422 case D_LDTR: return Yldtr;
423 case D_MSW: return Ymsw;
424 case D_TASK: return Ytask;
426 case D_CR+0: return Ycr0;
427 case D_CR+1: return Ycr1;
428 case D_CR+2: return Ycr2;
429 case D_CR+3: return Ycr3;
430 case D_CR+4: return Ycr4;
431 case D_CR+5: return Ycr5;
432 case D_CR+6: return Ycr6;
433 case D_CR+7: return Ycr7;
435 case D_DR+0: return Ydr0;
436 case D_DR+1: return Ydr1;
437 case D_DR+2: return Ydr2;
438 case D_DR+3: return Ydr3;
439 case D_DR+4: return Ydr4;
440 case D_DR+5: return Ydr5;
441 case D_DR+6: return Ydr6;
442 case D_DR+7: return Ydr7;
444 case D_TR+0: return Ytr0;
445 case D_TR+1: return Ytr1;
446 case D_TR+2: return Ytr2;
447 case D_TR+3: return Ytr3;
448 case D_TR+4: return Ytr4;
449 case D_TR+5: return Ytr5;
450 case D_TR+6: return Ytr6;
451 case D_TR+7: return Ytr7;
467 if(v >= -128 && v <= 127)
479 asmidx(Adr *a, int base)
498 i = reg[a->index] << 3;
520 case D_NONE: /* must be mod=00 */
537 diag("asmidx: bad address %D", a);
545 if(dlm && curp != P && reloca != nil){
546 dynreloc(reloca->sym, curp->pc + andptr - &and[0], 1);
582 v += INITDAT + s->value;
590 asmand(Adr *a, int r)
598 if(a->index != D_NONE) {
599 if(t >= D_INDIR && t < D_M0) {
602 *andptr++ = (0 << 6) | (4 << 0) | (r << 3);
607 if(v == 0 && t != D_BP) {
608 *andptr++ = (0 << 6) | (4 << 0) | (r << 3);
612 if(v >= -128 && v < 128) {
613 *andptr++ = (1 << 6) | (4 << 0) | (r << 3);
618 *andptr++ = (2 << 6) | (4 << 0) | (r << 3);
628 aa.type = D_NONE+D_INDIR;
632 aa.type = D_SP+D_INDIR;
635 aa.offset = vaddr(a);
641 if(t >= D_AL && t <= D_F0+7) {
644 *andptr++ = (3 << 6) | (reg[t] << 0) | (r << 3);
647 if(t >= D_M0 && t <= D_X0+7) {
650 *andptr++ = (3 << 6) | (reg[t] << 0) | (r << 3);
653 if(t >= D_INDIR && t < D_M0) {
655 if(t == D_NONE || D_CS <= t && t <= D_GS) {
656 *andptr++ = (0 << 6) | (5 << 0) | (r << 3);
662 *andptr++ = (0 << 6) | (4 << 0) | (r << 3);
666 if(v >= -128 && v < 128) {
667 *andptr++ = (1 << 6) | (4 << 0) | (r << 3);
672 *andptr++ = (2 << 6) | (4 << 0) | (r << 3);
677 if(t >= D_AX && t <= D_DI) {
678 if(v == 0 && t != D_BP) {
679 *andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3);
682 if(v >= -128 && v < 128) {
683 andptr[0] = (1 << 6) | (reg[t] << 0) | (r << 3);
688 *andptr++ = (2 << 6) | (reg[t] << 0) | (r << 3);
699 aa.type = D_NONE+D_INDIR;
703 aa.type = D_SP+D_INDIR;
708 aa.offset = vaddr(a);
712 diag("asmand: bad address %D", a);
720 APUSHL, Ycs, Ynone, 0, 0x0e,E,0,0,
721 APUSHL, Yss, Ynone, 0, 0x16,E,0,0,
722 APUSHL, Yds, Ynone, 0, 0x1e,E,0,0,
723 APUSHL, Yes, Ynone, 0, 0x06,E,0,0,
724 APUSHL, Yfs, Ynone, 0, 0x0f,0xa0,E,0,
725 APUSHL, Ygs, Ynone, 0, 0x0f,0xa8,E,0,
727 APUSHW, Ycs, Ynone, 0, Pe,0x0e,E,0,
728 APUSHW, Yss, Ynone, 0, Pe,0x16,E,0,
729 APUSHW, Yds, Ynone, 0, Pe,0x1e,E,0,
730 APUSHW, Yes, Ynone, 0, Pe,0x06,E,0,
731 APUSHW, Yfs, Ynone, 0, Pe,0x0f,0xa0,E,
732 APUSHW, Ygs, Ynone, 0, Pe,0x0f,0xa8,E,
735 APOPL, Ynone, Yds, 0, 0x1f,E,0,0,
736 APOPL, Ynone, Yes, 0, 0x07,E,0,0,
737 APOPL, Ynone, Yss, 0, 0x17,E,0,0,
738 APOPL, Ynone, Yfs, 0, 0x0f,0xa1,E,0,
739 APOPL, Ynone, Ygs, 0, 0x0f,0xa9,E,0,
741 APOPW, Ynone, Yds, 0, Pe,0x1f,E,0,
742 APOPW, Ynone, Yes, 0, Pe,0x07,E,0,
743 APOPW, Ynone, Yss, 0, Pe,0x17,E,0,
744 APOPW, Ynone, Yfs, 0, Pe,0x0f,0xa1,E,
745 APOPW, Ynone, Ygs, 0, Pe,0x0f,0xa9,E,
748 AMOVW, Yes, Yml, 1, 0x8c,0,0,0,
749 AMOVW, Ycs, Yml, 1, 0x8c,1,0,0,
750 AMOVW, Yss, Yml, 1, 0x8c,2,0,0,
751 AMOVW, Yds, Yml, 1, 0x8c,3,0,0,
752 AMOVW, Yfs, Yml, 1, 0x8c,4,0,0,
753 AMOVW, Ygs, Yml, 1, 0x8c,5,0,0,
755 AMOVW, Yml, Yes, 2, 0x8e,0,0,0,
756 AMOVW, Yml, Ycs, 2, 0x8e,1,0,0,
757 AMOVW, Yml, Yss, 2, 0x8e,2,0,0,
758 AMOVW, Yml, Yds, 2, 0x8e,3,0,0,
759 AMOVW, Yml, Yfs, 2, 0x8e,4,0,0,
760 AMOVW, Yml, Ygs, 2, 0x8e,5,0,0,
763 AMOVL, Ycr0, Yml, 3, 0x0f,0x20,0,0,
764 AMOVL, Ycr2, Yml, 3, 0x0f,0x20,2,0,
765 AMOVL, Ycr3, Yml, 3, 0x0f,0x20,3,0,
766 AMOVL, Ycr4, Yml, 3, 0x0f,0x20,4,0,
768 AMOVL, Yml, Ycr0, 4, 0x0f,0x22,0,0,
769 AMOVL, Yml, Ycr2, 4, 0x0f,0x22,2,0,
770 AMOVL, Yml, Ycr3, 4, 0x0f,0x22,3,0,
771 AMOVL, Yml, Ycr4, 4, 0x0f,0x22,4,0,
774 AMOVL, Ydr0, Yml, 3, 0x0f,0x21,0,0,
775 AMOVL, Ydr1, Yml, 3, 0x0f,0x21,1,0,
776 AMOVL, Ydr2, Yml, 3, 0x0f,0x21,2,0,
777 AMOVL, Ydr3, Yml, 3, 0x0f,0x21,3,0,
778 AMOVL, Ydr6, Yml, 3, 0x0f,0x21,6,0,
779 AMOVL, Ydr7, Yml, 3, 0x0f,0x21,7,0,
781 AMOVL, Yml, Ydr0, 4, 0x0f,0x23,0,0,
782 AMOVL, Yml, Ydr1, 4, 0x0f,0x23,1,0,
783 AMOVL, Yml, Ydr2, 4, 0x0f,0x23,2,0,
784 AMOVL, Yml, Ydr3, 4, 0x0f,0x23,3,0,
785 AMOVL, Yml, Ydr6, 4, 0x0f,0x23,6,0,
786 AMOVL, Yml, Ydr7, 4, 0x0f,0x23,7,0,
789 AMOVL, Ytr6, Yml, 3, 0x0f,0x24,6,0,
790 AMOVL, Ytr7, Yml, 3, 0x0f,0x24,7,0,
792 AMOVL, Yml, Ytr6, 4, 0x0f,0x26,6,E,
793 AMOVL, Yml, Ytr7, 4, 0x0f,0x26,7,E,
795 /* lgdt, sgdt, lidt, sidt */
796 AMOVL, Ym, Ygdtr, 4, 0x0f,0x01,2,0,
797 AMOVL, Ygdtr, Ym, 3, 0x0f,0x01,0,0,
798 AMOVL, Ym, Yidtr, 4, 0x0f,0x01,3,0,
799 AMOVL, Yidtr, Ym, 3, 0x0f,0x01,1,0,
802 AMOVW, Yml, Yldtr, 4, 0x0f,0x00,2,0,
803 AMOVW, Yldtr, Yml, 3, 0x0f,0x00,0,0,
806 AMOVW, Yml, Ymsw, 4, 0x0f,0x01,6,0,
807 AMOVW, Ymsw, Yml, 3, 0x0f,0x01,4,0,
810 AMOVW, Yml, Ytask, 4, 0x0f,0x00,3,0,
811 AMOVW, Ytask, Yml, 3, 0x0f,0x00,1,0,
813 /* load full pointer */
814 AMOVL, Yml, Ycol, 5, 0,0,0,0,
815 AMOVW, Yml, Ycol, 5, Pe,0,0,0,
818 ASHLL, Ycol, Yml, 6, 0xa4,0xa5,0,0,
819 ASHRL, Ycol, Yml, 6, 0xac,0xad,0,0,
822 AIMULW, Yml, Yrl, 7, Pq,0xaf,0,0,
823 AIMULL, Yml, Yrl, 7, Pm,0xaf,0,0,
844 subreg(Prog *p, int from, int to)
848 print("\n%P s/%R/%R/\n", p, from, to);
850 if(p->from.type == from)
852 if(p->to.type == from)
855 if(p->from.index == from)
857 if(p->to.index == from)
861 if(p->from.type == from)
862 p->from.type = to+D_INDIR;
863 if(p->to.type == from)
864 p->to.type = to+D_INDIR;
871 mediaop(Optab *o, int op, int osize, int z)
886 if(andptr == and || andptr[-1] != Pm)
903 pre = prefixof(&p->from);
906 pre = prefixof(&p->to);
911 ft = oclass(&p->from) * Ymax;
912 tt = oclass(&p->to) * Ymax;
915 diag("asmins: noproto %P", p);
918 for(z=0; *t; z+=t[3],t+=4)
926 case Pq: /* 16 bit escape and opcode escape */
931 case Pf2: /* xmm opcode escape */
933 *andptr++ = o->prefix;
937 case Pm: /* opcode escape */
941 case Pe: /* 16 bit escape */
952 diag("asmins: unknown z %d %P", t[2], p);
959 for(; op = o->op[z]; z++)
965 asmand(&p->from, reg[p->to.type]);
969 mediaop(o, op, t[3], z);
970 asmand(&p->from, reg[p->to.type]);
974 mediaop(o, op, t[3], z);
975 asmand(&p->from, reg[p->to.type]);
976 *andptr++ = p->to.offset;
982 asmand(&p->from, reg[p->to.type]);
988 asmand(&p->from, reg[p->to.type]);
989 *andptr++ = p->to.offset;
993 *andptr++ = 0x8d; /* leal */
994 if(p->from.type != D_ADDR)
995 diag("asmins: Zaut sb type ADDR");
996 p->from.type = p->from.index;
997 p->from.index = D_NONE;
998 asmand(&p->from, reg[p->to.type]);
999 p->from.index = p->from.type;
1000 p->from.type = D_ADDR;
1005 asmand(&p->from, o->op[z+1]);
1010 asmand(&p->to, reg[p->from.type]);
1014 mediaop(o, op, t[3], z);
1015 asmand(&p->to, reg[p->from.type]);
1019 mediaop(o, op, t[3], z);
1020 asmand(&p->to, reg[p->from.type]);
1021 *andptr++ = p->from.offset;
1026 asmand(&p->to, o->op[z+1]);
1032 asmand(&p->from, o->op[z+1]);
1038 asmand(&p->to, o->op[z+1]);
1043 z = mediaop(o, op, t[3], z);
1044 asmand(&p->to, o->op[z+1]);
1056 *andptr++ = op + reg[p->to.type];
1061 *andptr++ = op + reg[p->to.type];
1062 if(o->prefix == Pe) {
1072 asmand(&p->to, reg[p->to.type]);
1080 if(o->prefix == Pe) {
1091 asmand(&p->from, o->op[z+1]);
1092 if(o->prefix == Pe) {
1102 asmand(&p->to, o->op[z+1]);
1103 if(o->prefix == Pe) {
1113 asmand(&p->to, reg[p->to.type]);
1114 if(o->prefix == Pe) {
1123 *andptr++ = op + reg[p->to.type];
1127 *andptr++ = op + reg[p->from.type];
1132 asmand(&p->to, reg[p->to.type]);
1138 v = q->pc - p->pc - 2;
1139 if(v >= -128 && v <= 127) {
1145 *andptr++ = o->op[z+1];
1157 v = q->pc - p->pc - 5;
1158 if(dlm && curp != P && p->to.sym->type == SUNDEF){
1159 /* v = 0 - p->pc - 5; */
1161 ckoff(p->to.sym, v);
1162 v += p->to.sym->value;
1163 dynreloc(p->to.sym, p->pc+1, 0);
1176 v = q->pc - p->pc - 2;
1177 if(v >= -128 && v <= 127) {
1182 *andptr++ = o->op[z+1];
1194 v = q->pc - p->pc - 2;
1195 if(v < -128 || v > 127)
1196 diag("loop too far: %P", p);
1219 for(t=ymovtab; *t; t+=8)
1226 * here, the assembly has failed.
1227 * if its a byte instruction that has
1228 * unaddressable registers, try to
1229 * exchange registers and reissue the
1230 * instruction with the operands renamed.
1234 if(z >= D_BP && z <= D_DI) {
1236 *andptr++ = 0x87; /* xchg lhs,bx */
1237 asmand(&p->from, reg[D_BX]);
1238 subreg(&pp, z, D_BX);
1240 *andptr++ = 0x87; /* xchg lhs,bx */
1241 asmand(&p->from, reg[D_BX]);
1243 *andptr++ = 0x90 + reg[z]; /* xchg lsh,ax */
1244 subreg(&pp, z, D_AX);
1246 *andptr++ = 0x90 + reg[z]; /* xchg lsh,ax */
1251 if(z >= D_BP && z <= D_DI) {
1252 if(isax(&p->from)) {
1253 *andptr++ = 0x87; /* xchg rhs,bx */
1254 asmand(&p->to, reg[D_BX]);
1255 subreg(&pp, z, D_BX);
1257 *andptr++ = 0x87; /* xchg rhs,bx */
1258 asmand(&p->to, reg[D_BX]);
1260 *andptr++ = 0x90 + reg[z]; /* xchg rsh,ax */
1261 subreg(&pp, z, D_AX);
1263 *andptr++ = 0x90 + reg[z]; /* xchg rsh,ax */
1267 diag("doasm: notfound t2=%ux from=%ux to=%ux %P", t[2], p->from.type, p->to.type, p);
1273 diag("asmins: unknown mov %d %P", t[3], p);
1277 for(z=4; t[z]!=E; z++)
1283 asmand(&p->to, t[5]);
1288 asmand(&p->from, t[5]);
1291 case 3: /* r,m - 2op */
1294 asmand(&p->to, t[6]);
1297 case 4: /* m,r - 2op */
1300 asmand(&p->from, t[6]);
1303 case 5: /* load full pointer, trash heap */
1306 switch(p->to.index) {
1328 asmand(&p->from, reg[p->to.type]);
1331 case 6: /* double shift */
1339 asmand(&p->to, reg[p->from.index]);
1340 *andptr++ = p->from.offset;
1346 asmand(&p->to, reg[p->from.index]);
1351 case 7: /* imul rm,r */
1354 asmand(&p->from, reg[p->to.type]);
1374 int modemap[4] = { 0, 1, -1, 2, };
1376 typedef struct Reloc Reloc;
1399 r->m = nm = malloc(r->t*sizeof(uchar));
1400 r->a = na = malloc(r->t*sizeof(ulong));
1401 memmove(nm, m, t*sizeof(uchar));
1402 memmove(na, a, t*sizeof(ulong));
1408 dynreloc(Sym *s, ulong v, int abs)
1415 if(s->type == SUNDEF)
1416 k = abs ? ABSU : RELU;
1418 k = abs ? ABSD : RELD;
1419 /* Bprint(&bso, "R %s a=%ld(%lx) %d\n", s->name, v, v, k); */
1427 for(i = n; i > 0; i--){
1428 if(v < a[i-1]){ /* happens occasionally for data */
1463 off = seek(cout, 0, 1);
1468 for(i = 0; i < NHASH; i++)
1469 for(s = hash[i]; s != S; s = s->link)
1470 if(s->type == SUNDEF){
1483 for(i = 0; i < n; i++){
1486 diag("bad relocation order");
1515 Bprint(&bso, "import table entries = %d\n", imports);
1516 Bprint(&bso, "export table entries = %d\n", exports);