17dd7cddfSDavid du Colombier #include "l.h"
27dd7cddfSDavid du Colombier
37dd7cddfSDavid du Colombier void
dodata(void)47dd7cddfSDavid du Colombier dodata(void)
57dd7cddfSDavid du Colombier {
67dd7cddfSDavid du Colombier int i, t;
77dd7cddfSDavid du Colombier Sym *s;
87dd7cddfSDavid du Colombier Prog *p, *p1;
97dd7cddfSDavid du Colombier long orig, orig1, v;
107dd7cddfSDavid du Colombier
117dd7cddfSDavid du Colombier if(debug['v'])
127dd7cddfSDavid du Colombier Bprint(&bso, "%5.2f dodata\n", cputime());
137dd7cddfSDavid du Colombier Bflush(&bso);
147dd7cddfSDavid du Colombier for(p = datap; p != P; p = p->link) {
157dd7cddfSDavid du Colombier s = p->from.sym;
167dd7cddfSDavid du Colombier if(p->as == ADYNT || p->as == AINIT)
177dd7cddfSDavid du Colombier s->value = dtype;
187dd7cddfSDavid du Colombier if(s->type == SBSS)
197dd7cddfSDavid du Colombier s->type = SDATA;
207dd7cddfSDavid du Colombier if(s->type != SDATA)
216b6b9ac8SDavid du Colombier diag("initialize non-data (%d): %s\n%P",
227dd7cddfSDavid du Colombier s->type, s->name, p);
237dd7cddfSDavid du Colombier v = p->from.offset + p->reg;
247dd7cddfSDavid du Colombier if(v > s->value)
256b6b9ac8SDavid du Colombier diag("initialize bounds (%ld): %s\n%P",
267dd7cddfSDavid du Colombier s->value, s->name, p);
277dd7cddfSDavid du Colombier }
287dd7cddfSDavid du Colombier
297dd7cddfSDavid du Colombier /*
307dd7cddfSDavid du Colombier * pass 1
317dd7cddfSDavid du Colombier * assign 'small' variables to data segment
327dd7cddfSDavid du Colombier * (rational is that data segment is more easily
337dd7cddfSDavid du Colombier * addressed through offset on REGSB)
347dd7cddfSDavid du Colombier */
357dd7cddfSDavid du Colombier orig = 0;
367dd7cddfSDavid du Colombier for(i=0; i<NHASH; i++)
377dd7cddfSDavid du Colombier for(s = hash[i]; s != S; s = s->link) {
387dd7cddfSDavid du Colombier t = s->type;
397dd7cddfSDavid du Colombier if(t != SDATA && t != SBSS)
407dd7cddfSDavid du Colombier continue;
417dd7cddfSDavid du Colombier v = s->value;
427dd7cddfSDavid du Colombier if(v == 0) {
436b6b9ac8SDavid du Colombier diag("%s: no size", s->name);
447dd7cddfSDavid du Colombier v = 1;
457dd7cddfSDavid du Colombier }
467dd7cddfSDavid du Colombier while(v & 3)
477dd7cddfSDavid du Colombier v++;
487dd7cddfSDavid du Colombier s->value = v;
497dd7cddfSDavid du Colombier if(v > MINSIZ)
507dd7cddfSDavid du Colombier continue;
517dd7cddfSDavid du Colombier if(v >= 8)
527dd7cddfSDavid du Colombier while(orig & 7)
537dd7cddfSDavid du Colombier orig++;
547dd7cddfSDavid du Colombier s->value = orig;
557dd7cddfSDavid du Colombier orig += v;
567dd7cddfSDavid du Colombier s->type = SDATA1;
577dd7cddfSDavid du Colombier }
587dd7cddfSDavid du Colombier orig1 = orig;
597dd7cddfSDavid du Colombier
607dd7cddfSDavid du Colombier /*
617dd7cddfSDavid du Colombier * pass 2
627dd7cddfSDavid du Colombier * assign 'data' variables to data segment
637dd7cddfSDavid du Colombier */
647dd7cddfSDavid du Colombier for(i=0; i<NHASH; i++)
657dd7cddfSDavid du Colombier for(s = hash[i]; s != S; s = s->link) {
667dd7cddfSDavid du Colombier t = s->type;
677dd7cddfSDavid du Colombier if(t != SDATA) {
687dd7cddfSDavid du Colombier if(t == SDATA1)
697dd7cddfSDavid du Colombier s->type = SDATA;
707dd7cddfSDavid du Colombier continue;
717dd7cddfSDavid du Colombier }
727dd7cddfSDavid du Colombier v = s->value;
737dd7cddfSDavid du Colombier if(v >= 8)
747dd7cddfSDavid du Colombier while(orig & 7)
757dd7cddfSDavid du Colombier orig++;
767dd7cddfSDavid du Colombier s->value = orig;
777dd7cddfSDavid du Colombier orig += v;
787dd7cddfSDavid du Colombier s->type = SDATA1;
797dd7cddfSDavid du Colombier }
807dd7cddfSDavid du Colombier
817dd7cddfSDavid du Colombier while(orig & 7)
827dd7cddfSDavid du Colombier orig++;
837dd7cddfSDavid du Colombier datsize = orig;
847dd7cddfSDavid du Colombier
857dd7cddfSDavid du Colombier /*
867dd7cddfSDavid du Colombier * pass 3
877dd7cddfSDavid du Colombier * everything else to bss segment
887dd7cddfSDavid du Colombier */
897dd7cddfSDavid du Colombier for(i=0; i<NHASH; i++)
907dd7cddfSDavid du Colombier for(s = hash[i]; s != S; s = s->link) {
917dd7cddfSDavid du Colombier if(s->type != SBSS)
927dd7cddfSDavid du Colombier continue;
937dd7cddfSDavid du Colombier v = s->value;
947dd7cddfSDavid du Colombier if(v >= 8)
957dd7cddfSDavid du Colombier while(orig & 7)
967dd7cddfSDavid du Colombier orig++;
977dd7cddfSDavid du Colombier s->value = orig;
987dd7cddfSDavid du Colombier orig += v;
997dd7cddfSDavid du Colombier }
1007dd7cddfSDavid du Colombier while(orig & 7)
1017dd7cddfSDavid du Colombier orig++;
1027dd7cddfSDavid du Colombier bsssize = orig-datsize;
1037dd7cddfSDavid du Colombier
1047dd7cddfSDavid du Colombier /*
1057dd7cddfSDavid du Colombier * pass 4
1067dd7cddfSDavid du Colombier * add literals to all large values.
1077dd7cddfSDavid du Colombier * at this time:
1087dd7cddfSDavid du Colombier * small data is allocated DATA
1097dd7cddfSDavid du Colombier * large data is allocated DATA1
1107dd7cddfSDavid du Colombier * large bss is allocated BSS
1117dd7cddfSDavid du Colombier * the new literals are loaded between
1127dd7cddfSDavid du Colombier * small data and large data.
1137dd7cddfSDavid du Colombier */
1147dd7cddfSDavid du Colombier orig = 0;
1157dd7cddfSDavid du Colombier for(p = firstp; p != P; p = p->link) {
1167dd7cddfSDavid du Colombier if(p->as != AMOVW)
1177dd7cddfSDavid du Colombier continue;
1187dd7cddfSDavid du Colombier if(p->from.type != D_CONST)
1197dd7cddfSDavid du Colombier continue;
1207dd7cddfSDavid du Colombier if(s = p->from.sym) {
1217dd7cddfSDavid du Colombier t = s->type;
1227dd7cddfSDavid du Colombier if(t != SDATA && t != SDATA1 && t != SBSS)
1237dd7cddfSDavid du Colombier continue;
1247dd7cddfSDavid du Colombier t = p->from.name;
1257dd7cddfSDavid du Colombier if(t != D_EXTERN && t != D_STATIC)
1267dd7cddfSDavid du Colombier continue;
1277dd7cddfSDavid du Colombier v = s->value + p->from.offset;
1287dd7cddfSDavid du Colombier if(v >= 0 && v <= 0xffff)
1297dd7cddfSDavid du Colombier continue;
1307dd7cddfSDavid du Colombier if(!strcmp(s->name, "setSB"))
1317dd7cddfSDavid du Colombier continue;
1327dd7cddfSDavid du Colombier /* size should be 19 max */
1337dd7cddfSDavid du Colombier if(strlen(s->name) >= 10) /* has loader address */
134*73e742d7SDavid du Colombier sprint(literal, "$%p.%lux", s, p->from.offset);
1357dd7cddfSDavid du Colombier else
1367dd7cddfSDavid du Colombier sprint(literal, "$%s.%d.%lux", s->name, s->version, p->from.offset);
1377dd7cddfSDavid du Colombier } else {
1387dd7cddfSDavid du Colombier if(p->from.name != D_NONE)
1397dd7cddfSDavid du Colombier continue;
1407dd7cddfSDavid du Colombier if(p->from.reg != NREG)
1417dd7cddfSDavid du Colombier continue;
1427dd7cddfSDavid du Colombier v = p->from.offset;
1437dd7cddfSDavid du Colombier if(v >= -0x7fff-1 && v <= 0x7fff)
1447dd7cddfSDavid du Colombier continue;
1457dd7cddfSDavid du Colombier if(!(v & 0xffff))
1467dd7cddfSDavid du Colombier continue;
1477dd7cddfSDavid du Colombier if(v)
1487dd7cddfSDavid du Colombier continue; /* quicker to build it than load it */
1497dd7cddfSDavid du Colombier /* size should be 9 max */
1507dd7cddfSDavid du Colombier sprint(literal, "$%lux", v);
1517dd7cddfSDavid du Colombier }
1527dd7cddfSDavid du Colombier s = lookup(literal, 0);
1537dd7cddfSDavid du Colombier if(s->type == 0) {
1547dd7cddfSDavid du Colombier s->type = SDATA;
1557dd7cddfSDavid du Colombier s->value = orig1+orig;
1567dd7cddfSDavid du Colombier orig += 4;
1577dd7cddfSDavid du Colombier p1 = prg();
1587dd7cddfSDavid du Colombier p1->as = ADATA;
1597dd7cddfSDavid du Colombier p1->line = p->line;
1607dd7cddfSDavid du Colombier p1->from.type = D_OREG;
1617dd7cddfSDavid du Colombier p1->from.sym = s;
1627dd7cddfSDavid du Colombier p1->from.name = D_EXTERN;
1637dd7cddfSDavid du Colombier p1->reg = 4;
1647dd7cddfSDavid du Colombier p1->to = p->from;
1657dd7cddfSDavid du Colombier p1->link = datap;
1667dd7cddfSDavid du Colombier datap = p1;
1677dd7cddfSDavid du Colombier }
1687dd7cddfSDavid du Colombier if(s->type != SDATA)
1697dd7cddfSDavid du Colombier diag("literal not data: %s", s->name);
1707dd7cddfSDavid du Colombier p->from.type = D_OREG;
1717dd7cddfSDavid du Colombier p->from.sym = s;
1727dd7cddfSDavid du Colombier p->from.name = D_EXTERN;
1737dd7cddfSDavid du Colombier p->from.offset = 0;
1747dd7cddfSDavid du Colombier continue;
1757dd7cddfSDavid du Colombier }
1767dd7cddfSDavid du Colombier while(orig & 7)
1777dd7cddfSDavid du Colombier orig++;
1787dd7cddfSDavid du Colombier /*
1797dd7cddfSDavid du Colombier * pass 5
1807dd7cddfSDavid du Colombier * re-adjust offsets
1817dd7cddfSDavid du Colombier */
1827dd7cddfSDavid du Colombier for(i=0; i<NHASH; i++)
1837dd7cddfSDavid du Colombier for(s = hash[i]; s != S; s = s->link) {
1847dd7cddfSDavid du Colombier t = s->type;
1857dd7cddfSDavid du Colombier if(t == SBSS) {
1867dd7cddfSDavid du Colombier s->value += orig;
1877dd7cddfSDavid du Colombier continue;
1887dd7cddfSDavid du Colombier }
1897dd7cddfSDavid du Colombier if(t == SDATA1) {
1907dd7cddfSDavid du Colombier s->type = SDATA;
1917dd7cddfSDavid du Colombier s->value += orig;
1927dd7cddfSDavid du Colombier continue;
1937dd7cddfSDavid du Colombier }
1947dd7cddfSDavid du Colombier }
1957dd7cddfSDavid du Colombier datsize += orig;
1967dd7cddfSDavid du Colombier xdefine("setSB", SDATA, 0L+BIG);
1977dd7cddfSDavid du Colombier xdefine("bdata", SDATA, 0L);
1987dd7cddfSDavid du Colombier xdefine("edata", SDATA, datsize);
1997dd7cddfSDavid du Colombier xdefine("end", SBSS, datsize+bsssize);
2007dd7cddfSDavid du Colombier xdefine("etext", STEXT, 0L);
2017dd7cddfSDavid du Colombier }
2027dd7cddfSDavid du Colombier
2037dd7cddfSDavid du Colombier void
undef(void)2047dd7cddfSDavid du Colombier undef(void)
2057dd7cddfSDavid du Colombier {
2067dd7cddfSDavid du Colombier int i;
2077dd7cddfSDavid du Colombier Sym *s;
2087dd7cddfSDavid du Colombier
2097dd7cddfSDavid du Colombier for(i=0; i<NHASH; i++)
2107dd7cddfSDavid du Colombier for(s = hash[i]; s != S; s = s->link)
2117dd7cddfSDavid du Colombier if(s->type == SXREF)
2126b6b9ac8SDavid du Colombier diag("%s: not defined", s->name);
2137dd7cddfSDavid du Colombier }
2147dd7cddfSDavid du Colombier
2157dd7cddfSDavid du Colombier int
relinv(int a)2167dd7cddfSDavid du Colombier relinv(int a)
2177dd7cddfSDavid du Colombier {
2187dd7cddfSDavid du Colombier
2197dd7cddfSDavid du Colombier switch(a) {
2207dd7cddfSDavid du Colombier case ABEQ: return ABNE;
2217dd7cddfSDavid du Colombier case ABNE: return ABEQ;
2227dd7cddfSDavid du Colombier
2237dd7cddfSDavid du Colombier case ABGE: return ABLT;
2247dd7cddfSDavid du Colombier case ABLT: return ABGE;
2257dd7cddfSDavid du Colombier
2267dd7cddfSDavid du Colombier case ABGT: return ABLE;
2277dd7cddfSDavid du Colombier case ABLE: return ABGT;
2287dd7cddfSDavid du Colombier
2297dd7cddfSDavid du Colombier case ABVC: return ABVS;
2307dd7cddfSDavid du Colombier case ABVS: return ABVC;
2317dd7cddfSDavid du Colombier }
2327dd7cddfSDavid du Colombier return 0;
2337dd7cddfSDavid du Colombier }
2347dd7cddfSDavid du Colombier
2357dd7cddfSDavid du Colombier void
follow(void)2367dd7cddfSDavid du Colombier follow(void)
2377dd7cddfSDavid du Colombier {
2387dd7cddfSDavid du Colombier
2397dd7cddfSDavid du Colombier if(debug['v'])
2407dd7cddfSDavid du Colombier Bprint(&bso, "%5.2f follow\n", cputime());
2417dd7cddfSDavid du Colombier Bflush(&bso);
2427dd7cddfSDavid du Colombier
2437dd7cddfSDavid du Colombier firstp = prg();
2447dd7cddfSDavid du Colombier lastp = firstp;
2457dd7cddfSDavid du Colombier
2467dd7cddfSDavid du Colombier xfol(textp);
2477dd7cddfSDavid du Colombier
2487dd7cddfSDavid du Colombier firstp = firstp->link;
2497dd7cddfSDavid du Colombier lastp->link = P;
2507dd7cddfSDavid du Colombier }
2517dd7cddfSDavid du Colombier
2527dd7cddfSDavid du Colombier void
xfol(Prog * p)2537dd7cddfSDavid du Colombier xfol(Prog *p)
2547dd7cddfSDavid du Colombier {
2557dd7cddfSDavid du Colombier Prog *q, *r;
2567dd7cddfSDavid du Colombier int a, b, i;
2577dd7cddfSDavid du Colombier
2587dd7cddfSDavid du Colombier loop:
2597dd7cddfSDavid du Colombier if(p == P)
2607dd7cddfSDavid du Colombier return;
2617dd7cddfSDavid du Colombier a = p->as;
2627dd7cddfSDavid du Colombier if(a == ATEXT)
2637dd7cddfSDavid du Colombier curtext = p;
2647dd7cddfSDavid du Colombier if(a == ABR) {
2657dd7cddfSDavid du Colombier q = p->cond;
2667dd7cddfSDavid du Colombier if((p->mark&NOSCHED) || q && (q->mark&NOSCHED)){
2677dd7cddfSDavid du Colombier p->mark |= FOLL;
2687dd7cddfSDavid du Colombier lastp->link = p;
2697dd7cddfSDavid du Colombier lastp = p;
2707dd7cddfSDavid du Colombier p = p->link;
2717dd7cddfSDavid du Colombier xfol(p);
2727dd7cddfSDavid du Colombier p = q;
2737dd7cddfSDavid du Colombier if(p && !(p->mark & FOLL))
2747dd7cddfSDavid du Colombier goto loop;
2757dd7cddfSDavid du Colombier return;
2767dd7cddfSDavid du Colombier }
2777dd7cddfSDavid du Colombier if(q != P) {
2787dd7cddfSDavid du Colombier p->mark |= FOLL;
2797dd7cddfSDavid du Colombier p = q;
2807dd7cddfSDavid du Colombier if(!(p->mark & FOLL))
2817dd7cddfSDavid du Colombier goto loop;
2827dd7cddfSDavid du Colombier }
2837dd7cddfSDavid du Colombier }
2847dd7cddfSDavid du Colombier if(p->mark & FOLL) {
2857dd7cddfSDavid du Colombier for(i=0,q=p; i<4; i++,q=q->link) {
2867dd7cddfSDavid du Colombier if(q == lastp || (q->mark&NOSCHED))
2877dd7cddfSDavid du Colombier break;
2887dd7cddfSDavid du Colombier b = 0; /* set */
2897dd7cddfSDavid du Colombier a = q->as;
2907dd7cddfSDavid du Colombier if(a == ANOP) {
2917dd7cddfSDavid du Colombier i--;
2927dd7cddfSDavid du Colombier continue;
2937dd7cddfSDavid du Colombier }
294375daca8SDavid du Colombier if(a == ABR || a == ARETURN || a == ARFI || a == ARFCI)
2957dd7cddfSDavid du Colombier goto copy;
2967dd7cddfSDavid du Colombier if(!q->cond || (q->cond->mark&FOLL))
2977dd7cddfSDavid du Colombier continue;
2987dd7cddfSDavid du Colombier b = relinv(a);
2997dd7cddfSDavid du Colombier if(!b)
3007dd7cddfSDavid du Colombier continue;
3017dd7cddfSDavid du Colombier copy:
3027dd7cddfSDavid du Colombier for(;;) {
3037dd7cddfSDavid du Colombier r = prg();
3047dd7cddfSDavid du Colombier *r = *p;
3057dd7cddfSDavid du Colombier if(!(r->mark&FOLL))
3067dd7cddfSDavid du Colombier print("cant happen 1\n");
3077dd7cddfSDavid du Colombier r->mark |= FOLL;
3087dd7cddfSDavid du Colombier if(p != q) {
3097dd7cddfSDavid du Colombier p = p->link;
3107dd7cddfSDavid du Colombier lastp->link = r;
3117dd7cddfSDavid du Colombier lastp = r;
3127dd7cddfSDavid du Colombier continue;
3137dd7cddfSDavid du Colombier }
3147dd7cddfSDavid du Colombier lastp->link = r;
3157dd7cddfSDavid du Colombier lastp = r;
316375daca8SDavid du Colombier if(a == ABR || a == ARETURN || a == ARFI || a == ARFCI)
3177dd7cddfSDavid du Colombier return;
3187dd7cddfSDavid du Colombier r->as = b;
3197dd7cddfSDavid du Colombier r->cond = p->link;
3207dd7cddfSDavid du Colombier r->link = p->cond;
3217dd7cddfSDavid du Colombier if(!(r->link->mark&FOLL))
3227dd7cddfSDavid du Colombier xfol(r->link);
3237dd7cddfSDavid du Colombier if(!(r->cond->mark&FOLL))
3247dd7cddfSDavid du Colombier print("cant happen 2\n");
3257dd7cddfSDavid du Colombier return;
3267dd7cddfSDavid du Colombier }
3277dd7cddfSDavid du Colombier }
3287dd7cddfSDavid du Colombier
3297dd7cddfSDavid du Colombier a = ABR;
3307dd7cddfSDavid du Colombier q = prg();
3317dd7cddfSDavid du Colombier q->as = a;
3327dd7cddfSDavid du Colombier q->line = p->line;
3337dd7cddfSDavid du Colombier q->to.type = D_BRANCH;
3347dd7cddfSDavid du Colombier q->to.offset = p->pc;
3357dd7cddfSDavid du Colombier q->cond = p;
3367dd7cddfSDavid du Colombier p = q;
3377dd7cddfSDavid du Colombier }
3387dd7cddfSDavid du Colombier p->mark |= FOLL;
3397dd7cddfSDavid du Colombier lastp->link = p;
3407dd7cddfSDavid du Colombier lastp = p;
341375daca8SDavid du Colombier if(a == ABR || a == ARETURN || a == ARFI || a == ARFCI){
3427dd7cddfSDavid du Colombier if(p->mark & NOSCHED){
3437dd7cddfSDavid du Colombier p = p->link;
3447dd7cddfSDavid du Colombier goto loop;
3457dd7cddfSDavid du Colombier }
3467dd7cddfSDavid du Colombier return;
3477dd7cddfSDavid du Colombier }
3487dd7cddfSDavid du Colombier if(p->cond != P)
3497dd7cddfSDavid du Colombier if(a != ABL && p->link != P) {
3507dd7cddfSDavid du Colombier xfol(p->link);
3517dd7cddfSDavid du Colombier p = p->cond;
3527dd7cddfSDavid du Colombier if(p == P || (p->mark&FOLL))
3537dd7cddfSDavid du Colombier return;
3547dd7cddfSDavid du Colombier goto loop;
3557dd7cddfSDavid du Colombier }
3567dd7cddfSDavid du Colombier p = p->link;
3577dd7cddfSDavid du Colombier goto loop;
3587dd7cddfSDavid du Colombier }
3597dd7cddfSDavid du Colombier
3607dd7cddfSDavid du Colombier void
patch(void)3617dd7cddfSDavid du Colombier patch(void)
3627dd7cddfSDavid du Colombier {
3637dd7cddfSDavid du Colombier long c, vexit;
3647dd7cddfSDavid du Colombier Prog *p, *q;
3657dd7cddfSDavid du Colombier Sym *s;
3667dd7cddfSDavid du Colombier int a;
3677dd7cddfSDavid du Colombier
3687dd7cddfSDavid du Colombier if(debug['v'])
3697dd7cddfSDavid du Colombier Bprint(&bso, "%5.2f patch\n", cputime());
3707dd7cddfSDavid du Colombier Bflush(&bso);
3717dd7cddfSDavid du Colombier mkfwd();
3727dd7cddfSDavid du Colombier s = lookup("exit", 0);
3737dd7cddfSDavid du Colombier vexit = s->value;
3747dd7cddfSDavid du Colombier for(p = firstp; p != P; p = p->link) {
3757dd7cddfSDavid du Colombier a = p->as;
3767dd7cddfSDavid du Colombier if(a == ATEXT)
3777dd7cddfSDavid du Colombier curtext = p;
3787dd7cddfSDavid du Colombier if((a == ABL || a == ARETURN) && p->to.sym != S) {
3797dd7cddfSDavid du Colombier s = p->to.sym;
380375daca8SDavid du Colombier if(s->type != STEXT && s->type != SUNDEF) {
3816b6b9ac8SDavid du Colombier diag("undefined: %s\n%P", s->name, p);
3827dd7cddfSDavid du Colombier s->type = STEXT;
3837dd7cddfSDavid du Colombier s->value = vexit;
3847dd7cddfSDavid du Colombier }
385375daca8SDavid du Colombier if(s->type == SUNDEF){
386375daca8SDavid du Colombier p->to.offset = 0;
387375daca8SDavid du Colombier p->cond = UP;
388375daca8SDavid du Colombier }
389375daca8SDavid du Colombier else
3907dd7cddfSDavid du Colombier p->to.offset = s->value;
3917dd7cddfSDavid du Colombier p->to.type = D_BRANCH;
3927dd7cddfSDavid du Colombier }
393375daca8SDavid du Colombier if(p->to.type != D_BRANCH || p->cond == UP)
3947dd7cddfSDavid du Colombier continue;
3957dd7cddfSDavid du Colombier c = p->to.offset;
3967dd7cddfSDavid du Colombier for(q = firstp; q != P;) {
3977dd7cddfSDavid du Colombier if(q->forwd != P)
3987dd7cddfSDavid du Colombier if(c >= q->forwd->pc) {
3997dd7cddfSDavid du Colombier q = q->forwd;
4007dd7cddfSDavid du Colombier continue;
4017dd7cddfSDavid du Colombier }
4027dd7cddfSDavid du Colombier if(c == q->pc)
4037dd7cddfSDavid du Colombier break;
4047dd7cddfSDavid du Colombier q = q->link;
4057dd7cddfSDavid du Colombier }
4067dd7cddfSDavid du Colombier if(q == P) {
4076b6b9ac8SDavid du Colombier diag("branch out of range %ld\n%P", c, p);
4087dd7cddfSDavid du Colombier p->to.type = D_NONE;
4097dd7cddfSDavid du Colombier }
4107dd7cddfSDavid du Colombier p->cond = q;
4117dd7cddfSDavid du Colombier }
4127dd7cddfSDavid du Colombier
4137dd7cddfSDavid du Colombier for(p = firstp; p != P; p = p->link) {
4147dd7cddfSDavid du Colombier if(p->as == ATEXT)
4157dd7cddfSDavid du Colombier curtext = p;
416375daca8SDavid du Colombier p->mark = 0; /* initialization for follow */
417375daca8SDavid du Colombier if(p->cond != P && p->cond != UP) {
4187dd7cddfSDavid du Colombier p->cond = brloop(p->cond);
4197dd7cddfSDavid du Colombier if(p->cond != P)
4207dd7cddfSDavid du Colombier if(p->to.type == D_BRANCH)
4217dd7cddfSDavid du Colombier p->to.offset = p->cond->pc;
4227dd7cddfSDavid du Colombier }
4237dd7cddfSDavid du Colombier }
4247dd7cddfSDavid du Colombier }
4257dd7cddfSDavid du Colombier
4267dd7cddfSDavid du Colombier #define LOG 5
4277dd7cddfSDavid du Colombier void
mkfwd(void)4287dd7cddfSDavid du Colombier mkfwd(void)
4297dd7cddfSDavid du Colombier {
4307dd7cddfSDavid du Colombier Prog *p;
4317dd7cddfSDavid du Colombier long dwn[LOG], cnt[LOG], i;
4327dd7cddfSDavid du Colombier Prog *lst[LOG];
4337dd7cddfSDavid du Colombier
4347dd7cddfSDavid du Colombier for(i=0; i<LOG; i++) {
4357dd7cddfSDavid du Colombier if(i == 0)
4367dd7cddfSDavid du Colombier cnt[i] = 1; else
4377dd7cddfSDavid du Colombier cnt[i] = LOG * cnt[i-1];
4387dd7cddfSDavid du Colombier dwn[i] = 1;
4397dd7cddfSDavid du Colombier lst[i] = P;
4407dd7cddfSDavid du Colombier }
4417dd7cddfSDavid du Colombier i = 0;
4427dd7cddfSDavid du Colombier for(p = firstp; p != P; p = p->link) {
4437dd7cddfSDavid du Colombier if(p->as == ATEXT)
4447dd7cddfSDavid du Colombier curtext = p;
4457dd7cddfSDavid du Colombier i--;
4467dd7cddfSDavid du Colombier if(i < 0)
4477dd7cddfSDavid du Colombier i = LOG-1;
4487dd7cddfSDavid du Colombier p->forwd = P;
4497dd7cddfSDavid du Colombier dwn[i]--;
4507dd7cddfSDavid du Colombier if(dwn[i] <= 0) {
4517dd7cddfSDavid du Colombier dwn[i] = cnt[i];
4527dd7cddfSDavid du Colombier if(lst[i] != P)
4537dd7cddfSDavid du Colombier lst[i]->forwd = p;
4547dd7cddfSDavid du Colombier lst[i] = p;
4557dd7cddfSDavid du Colombier }
4567dd7cddfSDavid du Colombier }
4577dd7cddfSDavid du Colombier }
4587dd7cddfSDavid du Colombier
4597dd7cddfSDavid du Colombier Prog*
brloop(Prog * p)4607dd7cddfSDavid du Colombier brloop(Prog *p)
4617dd7cddfSDavid du Colombier {
4627dd7cddfSDavid du Colombier Prog *q;
4637dd7cddfSDavid du Colombier int c;
4647dd7cddfSDavid du Colombier
4657dd7cddfSDavid du Colombier for(c=0; p!=P;) {
4667dd7cddfSDavid du Colombier if(p->as != ABR || (p->mark&NOSCHED))
4677dd7cddfSDavid du Colombier return p;
4687dd7cddfSDavid du Colombier q = p->cond;
4697dd7cddfSDavid du Colombier if(q <= p) {
4707dd7cddfSDavid du Colombier c++;
4717dd7cddfSDavid du Colombier if(q == p || c > 5000)
4727dd7cddfSDavid du Colombier break;
4737dd7cddfSDavid du Colombier }
4747dd7cddfSDavid du Colombier p = q;
4757dd7cddfSDavid du Colombier }
4767dd7cddfSDavid du Colombier return P;
4777dd7cddfSDavid du Colombier }
4787dd7cddfSDavid du Colombier
4797dd7cddfSDavid du Colombier long
atolwhex(char * s)4807dd7cddfSDavid du Colombier atolwhex(char *s)
4817dd7cddfSDavid du Colombier {
4827dd7cddfSDavid du Colombier long n;
4837dd7cddfSDavid du Colombier int f;
4847dd7cddfSDavid du Colombier
4857dd7cddfSDavid du Colombier n = 0;
4867dd7cddfSDavid du Colombier f = 0;
4877dd7cddfSDavid du Colombier while(*s == ' ' || *s == '\t')
4887dd7cddfSDavid du Colombier s++;
4897dd7cddfSDavid du Colombier if(*s == '-' || *s == '+') {
4907dd7cddfSDavid du Colombier if(*s++ == '-')
4917dd7cddfSDavid du Colombier f = 1;
4927dd7cddfSDavid du Colombier while(*s == ' ' || *s == '\t')
4937dd7cddfSDavid du Colombier s++;
4947dd7cddfSDavid du Colombier }
4957dd7cddfSDavid du Colombier if(s[0]=='0' && s[1]){
4967dd7cddfSDavid du Colombier if(s[1]=='x' || s[1]=='X'){
4977dd7cddfSDavid du Colombier s += 2;
4987dd7cddfSDavid du Colombier for(;;){
4997dd7cddfSDavid du Colombier if(*s >= '0' && *s <= '9')
5007dd7cddfSDavid du Colombier n = n*16 + *s++ - '0';
5017dd7cddfSDavid du Colombier else if(*s >= 'a' && *s <= 'f')
5027dd7cddfSDavid du Colombier n = n*16 + *s++ - 'a' + 10;
5037dd7cddfSDavid du Colombier else if(*s >= 'A' && *s <= 'F')
5047dd7cddfSDavid du Colombier n = n*16 + *s++ - 'A' + 10;
5057dd7cddfSDavid du Colombier else
5067dd7cddfSDavid du Colombier break;
5077dd7cddfSDavid du Colombier }
5087dd7cddfSDavid du Colombier } else
5097dd7cddfSDavid du Colombier while(*s >= '0' && *s <= '7')
5107dd7cddfSDavid du Colombier n = n*8 + *s++ - '0';
5117dd7cddfSDavid du Colombier } else
5127dd7cddfSDavid du Colombier while(*s >= '0' && *s <= '9')
5137dd7cddfSDavid du Colombier n = n*10 + *s++ - '0';
5147dd7cddfSDavid du Colombier if(f)
5157dd7cddfSDavid du Colombier n = -n;
5167dd7cddfSDavid du Colombier return n;
5177dd7cddfSDavid du Colombier }
5187dd7cddfSDavid du Colombier
5197dd7cddfSDavid du Colombier long
rnd(long v,long r)5207dd7cddfSDavid du Colombier rnd(long v, long r)
5217dd7cddfSDavid du Colombier {
5227dd7cddfSDavid du Colombier long c;
5237dd7cddfSDavid du Colombier
5247dd7cddfSDavid du Colombier if(r <= 0)
5257dd7cddfSDavid du Colombier return v;
5267dd7cddfSDavid du Colombier v += r - 1;
5277dd7cddfSDavid du Colombier c = v % r;
5287dd7cddfSDavid du Colombier if(c < 0)
5297dd7cddfSDavid du Colombier c += r;
5307dd7cddfSDavid du Colombier v -= c;
5317dd7cddfSDavid du Colombier return v;
5327dd7cddfSDavid du Colombier }
533375daca8SDavid du Colombier
534375daca8SDavid du Colombier void
import(void)535375daca8SDavid du Colombier import(void)
536375daca8SDavid du Colombier {
537375daca8SDavid du Colombier int i;
538375daca8SDavid du Colombier Sym *s;
539375daca8SDavid du Colombier
540375daca8SDavid du Colombier for(i = 0; i < NHASH; i++)
541375daca8SDavid du Colombier for(s = hash[i]; s != S; s = s->link)
542375daca8SDavid du Colombier if(s->sig != 0 && s->type == SXREF && (nimports == 0 || s->subtype == SIMPORT)){
543375daca8SDavid du Colombier undefsym(s);
544375daca8SDavid du Colombier Bprint(&bso, "IMPORT: %s sig=%lux v=%ld\n", s->name, s->sig, s->value);
545375daca8SDavid du Colombier }
546375daca8SDavid du Colombier }
547375daca8SDavid du Colombier
548375daca8SDavid du Colombier void
ckoff(Sym * s,long v)549375daca8SDavid du Colombier ckoff(Sym *s, long v)
550375daca8SDavid du Colombier {
551375daca8SDavid du Colombier if(v < 0 || v >= 1<<Roffset)
552375daca8SDavid du Colombier diag("relocation offset %ld for %s out of range", v, s->name);
553375daca8SDavid du Colombier }
554375daca8SDavid du Colombier
555375daca8SDavid du Colombier static Prog*
newdata(Sym * s,int o,int w,int t)556375daca8SDavid du Colombier newdata(Sym *s, int o, int w, int t)
557375daca8SDavid du Colombier {
558375daca8SDavid du Colombier Prog *p;
559375daca8SDavid du Colombier
560375daca8SDavid du Colombier p = prg();
561375daca8SDavid du Colombier p->link = datap;
562375daca8SDavid du Colombier datap = p;
563375daca8SDavid du Colombier p->as = ADATA;
564375daca8SDavid du Colombier p->reg = w;
565375daca8SDavid du Colombier p->from.type = D_OREG;
566375daca8SDavid du Colombier p->from.name = t;
567375daca8SDavid du Colombier p->from.sym = s;
568375daca8SDavid du Colombier p->from.offset = o;
569375daca8SDavid du Colombier p->to.type = D_CONST;
570375daca8SDavid du Colombier p->to.name = D_NONE;
571375daca8SDavid du Colombier return p;
572375daca8SDavid du Colombier }
573375daca8SDavid du Colombier
574375daca8SDavid du Colombier void
export(void)575375daca8SDavid du Colombier export(void)
576375daca8SDavid du Colombier {
577375daca8SDavid du Colombier int i, j, n, off, nb, sv, ne;
578375daca8SDavid du Colombier Sym *s, *et, *str, **esyms;
579375daca8SDavid du Colombier Prog *p;
580375daca8SDavid du Colombier char buf[NSNAME], *t;
581375daca8SDavid du Colombier
582375daca8SDavid du Colombier n = 0;
583375daca8SDavid du Colombier for(i = 0; i < NHASH; i++)
584375daca8SDavid du Colombier for(s = hash[i]; s != S; s = s->link)
585375daca8SDavid du Colombier if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF && (nexports == 0 || s->subtype == SEXPORT))
586375daca8SDavid du Colombier n++;
587375daca8SDavid du Colombier esyms = malloc(n*sizeof(Sym*));
588375daca8SDavid du Colombier ne = n;
589375daca8SDavid du Colombier n = 0;
590375daca8SDavid du Colombier for(i = 0; i < NHASH; i++)
591375daca8SDavid du Colombier for(s = hash[i]; s != S; s = s->link)
592375daca8SDavid du Colombier if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF && (nexports == 0 || s->subtype == SEXPORT))
593375daca8SDavid du Colombier esyms[n++] = s;
594375daca8SDavid du Colombier for(i = 0; i < ne-1; i++)
595375daca8SDavid du Colombier for(j = i+1; j < ne; j++)
596375daca8SDavid du Colombier if(strcmp(esyms[i]->name, esyms[j]->name) > 0){
597375daca8SDavid du Colombier s = esyms[i];
598375daca8SDavid du Colombier esyms[i] = esyms[j];
599375daca8SDavid du Colombier esyms[j] = s;
600375daca8SDavid du Colombier }
601375daca8SDavid du Colombier
602375daca8SDavid du Colombier nb = 0;
603375daca8SDavid du Colombier off = 0;
604375daca8SDavid du Colombier et = lookup(EXPTAB, 0);
605375daca8SDavid du Colombier if(et->type != 0 && et->type != SXREF)
606375daca8SDavid du Colombier diag("%s already defined", EXPTAB);
607375daca8SDavid du Colombier et->type = SDATA;
608375daca8SDavid du Colombier str = lookup(".string", 0);
609375daca8SDavid du Colombier if(str->type == 0)
610375daca8SDavid du Colombier str->type = SDATA;
611375daca8SDavid du Colombier sv = str->value;
612375daca8SDavid du Colombier for(i = 0; i < ne; i++){
613375daca8SDavid du Colombier s = esyms[i];
614375daca8SDavid du Colombier Bprint(&bso, "EXPORT: %s sig=%lux t=%d\n", s->name, s->sig, s->type);
615375daca8SDavid du Colombier
616375daca8SDavid du Colombier /* signature */
617375daca8SDavid du Colombier p = newdata(et, off, sizeof(long), D_EXTERN);
618375daca8SDavid du Colombier off += sizeof(long);
619375daca8SDavid du Colombier p->to.offset = s->sig;
620375daca8SDavid du Colombier
621375daca8SDavid du Colombier /* address */
622375daca8SDavid du Colombier p = newdata(et, off, sizeof(long), D_EXTERN);
623375daca8SDavid du Colombier off += sizeof(long);
624375daca8SDavid du Colombier p->to.name = D_EXTERN;
625375daca8SDavid du Colombier p->to.sym = s;
626375daca8SDavid du Colombier
627375daca8SDavid du Colombier /* string */
628375daca8SDavid du Colombier t = s->name;
629375daca8SDavid du Colombier n = strlen(t)+1;
630375daca8SDavid du Colombier for(;;){
631375daca8SDavid du Colombier buf[nb++] = *t;
632375daca8SDavid du Colombier sv++;
633375daca8SDavid du Colombier if(nb >= NSNAME){
634375daca8SDavid du Colombier p = newdata(str, sv-NSNAME, NSNAME, D_STATIC);
635375daca8SDavid du Colombier p->to.type = D_SCONST;
636375daca8SDavid du Colombier memmove(p->to.sval, buf, NSNAME);
637375daca8SDavid du Colombier nb = 0;
638375daca8SDavid du Colombier }
639375daca8SDavid du Colombier if(*t++ == 0)
640375daca8SDavid du Colombier break;
641375daca8SDavid du Colombier }
642375daca8SDavid du Colombier
643375daca8SDavid du Colombier /* name */
644375daca8SDavid du Colombier p = newdata(et, off, sizeof(long), D_EXTERN);
645375daca8SDavid du Colombier off += sizeof(long);
646375daca8SDavid du Colombier p->to.name = D_STATIC;
647375daca8SDavid du Colombier p->to.sym = str;
648375daca8SDavid du Colombier p->to.offset = sv-n;
649375daca8SDavid du Colombier }
650375daca8SDavid du Colombier
651375daca8SDavid du Colombier if(nb > 0){
652375daca8SDavid du Colombier p = newdata(str, sv-nb, nb, D_STATIC);
653375daca8SDavid du Colombier p->to.type = D_SCONST;
654375daca8SDavid du Colombier memmove(p->to.sval, buf, nb);
655375daca8SDavid du Colombier }
656375daca8SDavid du Colombier
657375daca8SDavid du Colombier for(i = 0; i < 3; i++){
658375daca8SDavid du Colombier newdata(et, off, sizeof(long), D_EXTERN);
659375daca8SDavid du Colombier off += sizeof(long);
660375daca8SDavid du Colombier }
661375daca8SDavid du Colombier et->value = off;
662375daca8SDavid du Colombier if(sv == 0)
663375daca8SDavid du Colombier sv = 1;
664375daca8SDavid du Colombier str->value = sv;
665375daca8SDavid du Colombier exports = ne;
666375daca8SDavid du Colombier free(esyms);
667375daca8SDavid du Colombier }
668