13e12c5d1SDavid du Colombier #include "l.h" 23e12c5d1SDavid du Colombier 33e12c5d1SDavid du Colombier void 43e12c5d1SDavid du Colombier dodata(void) 53e12c5d1SDavid du Colombier { 63e12c5d1SDavid du Colombier int i; 73e12c5d1SDavid du Colombier Sym *s; 83e12c5d1SDavid du Colombier Prog *p; 93e12c5d1SDavid du Colombier long t, u; 103e12c5d1SDavid du Colombier 113e12c5d1SDavid du Colombier if(debug['v']) 123e12c5d1SDavid du Colombier Bprint(&bso, "%5.2f dodata\n", cputime()); 133e12c5d1SDavid du Colombier Bflush(&bso); 143e12c5d1SDavid du Colombier for(p = datap; p != P; p = p->link) { 153e12c5d1SDavid du Colombier s = p->from.sym; 16219b2ee8SDavid du Colombier if(p->as == ADYNT || p->as == AINIT) 17219b2ee8SDavid du Colombier s->value = dtype; 183e12c5d1SDavid du Colombier if(s->type == SBSS) 193e12c5d1SDavid du Colombier s->type = SDATA; 203e12c5d1SDavid du Colombier if(s->type != SDATA) 216b6b9ac8SDavid du Colombier diag("initialize non-data (%d): %s\n%P", 223e12c5d1SDavid du Colombier s->type, s->name, p); 233e12c5d1SDavid du Colombier t = p->from.offset + p->width; 243e12c5d1SDavid du Colombier if(t > s->value) 256b6b9ac8SDavid du Colombier diag("initialize bounds (%ld): %s\n%P", 263e12c5d1SDavid du Colombier s->value, s->name, p); 273e12c5d1SDavid du Colombier } 283e12c5d1SDavid du Colombier /* allocate small guys */ 293e12c5d1SDavid du Colombier datsize = 0; 303e12c5d1SDavid du Colombier for(i=0; i<NHASH; i++) 313e12c5d1SDavid du Colombier for(s = hash[i]; s != S; s = s->link) { 323e12c5d1SDavid du Colombier if(s->type != SDATA) 333e12c5d1SDavid du Colombier if(s->type != SBSS) 343e12c5d1SDavid du Colombier continue; 353e12c5d1SDavid du Colombier t = s->value; 363e12c5d1SDavid du Colombier if(t == 0) { 376b6b9ac8SDavid du Colombier diag("%s: no size", s->name); 383e12c5d1SDavid du Colombier t = 1; 393e12c5d1SDavid du Colombier } 403e12c5d1SDavid du Colombier t = rnd(t, 4);; 413e12c5d1SDavid du Colombier s->value = t; 423e12c5d1SDavid du Colombier if(t > MINSIZ) 433e12c5d1SDavid du Colombier continue; 443e12c5d1SDavid du Colombier s->value = datsize; 453e12c5d1SDavid du Colombier datsize += t; 463e12c5d1SDavid du Colombier s->type = SDATA1; 473e12c5d1SDavid du Colombier } 483e12c5d1SDavid du Colombier 493e12c5d1SDavid du Colombier /* allocate the rest of the data */ 503e12c5d1SDavid du Colombier for(i=0; i<NHASH; i++) 513e12c5d1SDavid du Colombier for(s = hash[i]; s != S; s = s->link) { 523e12c5d1SDavid du Colombier if(s->type != SDATA) { 533e12c5d1SDavid du Colombier if(s->type == SDATA1) 543e12c5d1SDavid du Colombier s->type = SDATA; 553e12c5d1SDavid du Colombier continue; 563e12c5d1SDavid du Colombier } 573e12c5d1SDavid du Colombier t = s->value; 583e12c5d1SDavid du Colombier s->value = datsize; 593e12c5d1SDavid du Colombier datsize += t; 603e12c5d1SDavid du Colombier } 613e12c5d1SDavid du Colombier 623e12c5d1SDavid du Colombier if(debug['j']) { 633e12c5d1SDavid du Colombier /* 643e12c5d1SDavid du Colombier * pad data with bss that fits up to next 653e12c5d1SDavid du Colombier * 8k boundary, then push data to 8k 663e12c5d1SDavid du Colombier */ 673e12c5d1SDavid du Colombier u = rnd(datsize, 8192); 683e12c5d1SDavid du Colombier u -= datsize; 693e12c5d1SDavid du Colombier for(i=0; i<NHASH; i++) 703e12c5d1SDavid du Colombier for(s = hash[i]; s != S; s = s->link) { 713e12c5d1SDavid du Colombier if(s->type != SBSS) 723e12c5d1SDavid du Colombier continue; 733e12c5d1SDavid du Colombier t = s->value; 743e12c5d1SDavid du Colombier if(t > u) 753e12c5d1SDavid du Colombier continue; 763e12c5d1SDavid du Colombier u -= t; 773e12c5d1SDavid du Colombier s->value = datsize; 783e12c5d1SDavid du Colombier s->type = SDATA; 793e12c5d1SDavid du Colombier datsize += t; 803e12c5d1SDavid du Colombier } 813e12c5d1SDavid du Colombier datsize += u; 823e12c5d1SDavid du Colombier } 833e12c5d1SDavid du Colombier 843e12c5d1SDavid du Colombier /* now the bss */ 853e12c5d1SDavid du Colombier bsssize = 0; 863e12c5d1SDavid du Colombier for(i=0; i<NHASH; i++) 873e12c5d1SDavid du Colombier for(s = hash[i]; s != S; s = s->link) { 883e12c5d1SDavid du Colombier if(s->type != SBSS) 893e12c5d1SDavid du Colombier continue; 903e12c5d1SDavid du Colombier t = s->value; 913e12c5d1SDavid du Colombier s->value = bsssize + datsize; 923e12c5d1SDavid du Colombier bsssize += t; 933e12c5d1SDavid du Colombier } 943e12c5d1SDavid du Colombier xdefine("edata", SBSS, datsize); 953e12c5d1SDavid du Colombier xdefine("end", SBSS, bsssize + datsize); 963e12c5d1SDavid du Colombier } 973e12c5d1SDavid du Colombier 983e12c5d1SDavid du Colombier Prog* 993e12c5d1SDavid du Colombier brchain(Prog *p) 1003e12c5d1SDavid du Colombier { 1013e12c5d1SDavid du Colombier int i; 1023e12c5d1SDavid du Colombier 1033e12c5d1SDavid du Colombier for(i=0; i<20; i++) { 1043e12c5d1SDavid du Colombier if(p == P || p->as != AJMP) 1053e12c5d1SDavid du Colombier return p; 1067dd7cddfSDavid du Colombier p = p->pcond; 1073e12c5d1SDavid du Colombier } 1083e12c5d1SDavid du Colombier return P; 1093e12c5d1SDavid du Colombier } 1103e12c5d1SDavid du Colombier 1113e12c5d1SDavid du Colombier void 1123e12c5d1SDavid du Colombier follow(void) 1133e12c5d1SDavid du Colombier { 1143e12c5d1SDavid du Colombier 1153e12c5d1SDavid du Colombier if(debug['v']) 1163e12c5d1SDavid du Colombier Bprint(&bso, "%5.2f follow\n", cputime()); 1173e12c5d1SDavid du Colombier Bflush(&bso); 1183e12c5d1SDavid du Colombier firstp = prg(); 1193e12c5d1SDavid du Colombier lastp = firstp; 1203e12c5d1SDavid du Colombier xfol(textp); 1213e12c5d1SDavid du Colombier lastp->link = P; 1223e12c5d1SDavid du Colombier firstp = firstp->link; 1233e12c5d1SDavid du Colombier } 1243e12c5d1SDavid du Colombier 1253e12c5d1SDavid du Colombier void 1263e12c5d1SDavid du Colombier xfol(Prog *p) 1273e12c5d1SDavid du Colombier { 1283e12c5d1SDavid du Colombier Prog *q; 1293e12c5d1SDavid du Colombier int i; 1303e12c5d1SDavid du Colombier enum as a; 1313e12c5d1SDavid du Colombier 1323e12c5d1SDavid du Colombier loop: 1333e12c5d1SDavid du Colombier if(p == P) 1343e12c5d1SDavid du Colombier return; 1353e12c5d1SDavid du Colombier if(p->as == ATEXT) 1363e12c5d1SDavid du Colombier curtext = p; 1373e12c5d1SDavid du Colombier if(p->as == AJMP) 1387dd7cddfSDavid du Colombier if((q = p->pcond) != P) { 1393e12c5d1SDavid du Colombier p->mark = 1; 1403e12c5d1SDavid du Colombier p = q; 1413e12c5d1SDavid du Colombier if(p->mark == 0) 1423e12c5d1SDavid du Colombier goto loop; 1433e12c5d1SDavid du Colombier } 1443e12c5d1SDavid du Colombier if(p->mark) { 1453e12c5d1SDavid du Colombier /* copy up to 4 instructions to avoid branch */ 1463e12c5d1SDavid du Colombier for(i=0,q=p; i<4; i++,q=q->link) { 1473e12c5d1SDavid du Colombier if(q == P) 1483e12c5d1SDavid du Colombier break; 1493e12c5d1SDavid du Colombier if(q == lastp) 1503e12c5d1SDavid du Colombier break; 1513e12c5d1SDavid du Colombier a = q->as; 1523e12c5d1SDavid du Colombier if(a == ANOP) { 1533e12c5d1SDavid du Colombier i--; 1543e12c5d1SDavid du Colombier continue; 1553e12c5d1SDavid du Colombier } 156219b2ee8SDavid du Colombier switch(a) { 157219b2ee8SDavid du Colombier case AJMP: 158219b2ee8SDavid du Colombier case ARET: 159219b2ee8SDavid du Colombier case AIRETL: 160219b2ee8SDavid du Colombier 161219b2ee8SDavid du Colombier case APUSHL: 162219b2ee8SDavid du Colombier case APUSHFL: 163219b2ee8SDavid du Colombier case APUSHW: 164219b2ee8SDavid du Colombier case APUSHFW: 165219b2ee8SDavid du Colombier case APOPL: 166219b2ee8SDavid du Colombier case APOPFL: 167219b2ee8SDavid du Colombier case APOPW: 168219b2ee8SDavid du Colombier case APOPFW: 169219b2ee8SDavid du Colombier goto brk; 170219b2ee8SDavid du Colombier } 1717dd7cddfSDavid du Colombier if(q->pcond == P || q->pcond->mark) 1723e12c5d1SDavid du Colombier continue; 1733e12c5d1SDavid du Colombier if(a == ACALL || a == ALOOP) 1743e12c5d1SDavid du Colombier continue; 1753e12c5d1SDavid du Colombier for(;;) { 1763e12c5d1SDavid du Colombier if(p->as == ANOP) { 1773e12c5d1SDavid du Colombier p = p->link; 1783e12c5d1SDavid du Colombier continue; 1793e12c5d1SDavid du Colombier } 1803e12c5d1SDavid du Colombier q = copyp(p); 1813e12c5d1SDavid du Colombier p = p->link; 1823e12c5d1SDavid du Colombier q->mark = 1; 1833e12c5d1SDavid du Colombier lastp->link = q; 1843e12c5d1SDavid du Colombier lastp = q; 1857dd7cddfSDavid du Colombier if(q->as != a || q->pcond == P || q->pcond->mark) 1863e12c5d1SDavid du Colombier continue; 187219b2ee8SDavid du Colombier 1883e12c5d1SDavid du Colombier q->as = relinv(q->as); 1897dd7cddfSDavid du Colombier p = q->pcond; 1907dd7cddfSDavid du Colombier q->pcond = q->link; 1913e12c5d1SDavid du Colombier q->link = p; 1923e12c5d1SDavid du Colombier xfol(q->link); 1933e12c5d1SDavid du Colombier p = q->link; 1943e12c5d1SDavid du Colombier if(p->mark) 1953e12c5d1SDavid du Colombier return; 1963e12c5d1SDavid du Colombier goto loop; 1973e12c5d1SDavid du Colombier } 1983e12c5d1SDavid du Colombier } /* */ 199219b2ee8SDavid du Colombier brk:; 2003e12c5d1SDavid du Colombier q = prg(); 2013e12c5d1SDavid du Colombier q->as = AJMP; 2023e12c5d1SDavid du Colombier q->line = p->line; 2033e12c5d1SDavid du Colombier q->to.type = D_BRANCH; 2043e12c5d1SDavid du Colombier q->to.offset = p->pc; 2057dd7cddfSDavid du Colombier q->pcond = p; 2063e12c5d1SDavid du Colombier p = q; 2073e12c5d1SDavid du Colombier } 2083e12c5d1SDavid du Colombier p->mark = 1; 2093e12c5d1SDavid du Colombier lastp->link = p; 2103e12c5d1SDavid du Colombier lastp = p; 2113e12c5d1SDavid du Colombier a = p->as; 2123e12c5d1SDavid du Colombier if(a == AJMP || a == ARET || a == AIRETL) 2133e12c5d1SDavid du Colombier return; 2147dd7cddfSDavid du Colombier if(p->pcond != P) 2153e12c5d1SDavid du Colombier if(a != ACALL) { 2163e12c5d1SDavid du Colombier q = brchain(p->link); 2173e12c5d1SDavid du Colombier if(q != P && q->mark) 2183e12c5d1SDavid du Colombier if(a != ALOOP) { 2193e12c5d1SDavid du Colombier p->as = relinv(a); 2207dd7cddfSDavid du Colombier p->link = p->pcond; 2217dd7cddfSDavid du Colombier p->pcond = q; 2223e12c5d1SDavid du Colombier } 2233e12c5d1SDavid du Colombier xfol(p->link); 2247dd7cddfSDavid du Colombier q = brchain(p->pcond); 2253e12c5d1SDavid du Colombier if(q->mark) { 2267dd7cddfSDavid du Colombier p->pcond = q; 2273e12c5d1SDavid du Colombier return; 2283e12c5d1SDavid du Colombier } 2293e12c5d1SDavid du Colombier p = q; 2303e12c5d1SDavid du Colombier goto loop; 2313e12c5d1SDavid du Colombier } 2323e12c5d1SDavid du Colombier p = p->link; 2333e12c5d1SDavid du Colombier goto loop; 2343e12c5d1SDavid du Colombier } 2353e12c5d1SDavid du Colombier 2363e12c5d1SDavid du Colombier int 2373e12c5d1SDavid du Colombier relinv(int a) 2383e12c5d1SDavid du Colombier { 2393e12c5d1SDavid du Colombier 2403e12c5d1SDavid du Colombier switch(a) { 2413e12c5d1SDavid du Colombier case AJEQ: return AJNE; 2423e12c5d1SDavid du Colombier case AJNE: return AJEQ; 2433e12c5d1SDavid du Colombier case AJLE: return AJGT; 2443e12c5d1SDavid du Colombier case AJLS: return AJHI; 2453e12c5d1SDavid du Colombier case AJLT: return AJGE; 2463e12c5d1SDavid du Colombier case AJMI: return AJPL; 2473e12c5d1SDavid du Colombier case AJGE: return AJLT; 2483e12c5d1SDavid du Colombier case AJPL: return AJMI; 2493e12c5d1SDavid du Colombier case AJGT: return AJLE; 2503e12c5d1SDavid du Colombier case AJHI: return AJLS; 2513e12c5d1SDavid du Colombier case AJCS: return AJCC; 2523e12c5d1SDavid du Colombier case AJCC: return AJCS; 2533e12c5d1SDavid du Colombier case AJPS: return AJPC; 2543e12c5d1SDavid du Colombier case AJPC: return AJPS; 2553e12c5d1SDavid du Colombier case AJOS: return AJOC; 2563e12c5d1SDavid du Colombier case AJOC: return AJOS; 2573e12c5d1SDavid du Colombier } 2586b6b9ac8SDavid du Colombier diag("unknown relation: %s in %s", anames[a], TNAME); 2593e12c5d1SDavid du Colombier return a; 2603e12c5d1SDavid du Colombier } 2613e12c5d1SDavid du Colombier 2623e12c5d1SDavid du Colombier void 2633e12c5d1SDavid du Colombier doinit(void) 2643e12c5d1SDavid du Colombier { 2653e12c5d1SDavid du Colombier Sym *s; 2663e12c5d1SDavid du Colombier Prog *p; 2673e12c5d1SDavid du Colombier int x; 2683e12c5d1SDavid du Colombier 2693e12c5d1SDavid du Colombier for(p = datap; p != P; p = p->link) { 2703e12c5d1SDavid du Colombier x = p->to.type; 2713e12c5d1SDavid du Colombier if(x != D_EXTERN && x != D_STATIC) 2723e12c5d1SDavid du Colombier continue; 2733e12c5d1SDavid du Colombier s = p->to.sym; 2743e12c5d1SDavid du Colombier if(s->type == 0 || s->type == SXREF) 2756b6b9ac8SDavid du Colombier diag("undefined %s initializer of %s", 2763e12c5d1SDavid du Colombier s->name, p->from.sym->name); 2773e12c5d1SDavid du Colombier p->to.offset += s->value; 2783e12c5d1SDavid du Colombier p->to.type = D_CONST; 2793e12c5d1SDavid du Colombier if(s->type == SDATA || s->type == SBSS) 2803e12c5d1SDavid du Colombier p->to.offset += INITDAT; 2813e12c5d1SDavid du Colombier } 2823e12c5d1SDavid du Colombier } 2833e12c5d1SDavid du Colombier 2843e12c5d1SDavid du Colombier void 2853e12c5d1SDavid du Colombier patch(void) 2863e12c5d1SDavid du Colombier { 2873e12c5d1SDavid du Colombier long c; 2883e12c5d1SDavid du Colombier Prog *p, *q; 2893e12c5d1SDavid du Colombier Sym *s; 2903e12c5d1SDavid du Colombier long vexit; 2913e12c5d1SDavid du Colombier 2923e12c5d1SDavid du Colombier if(debug['v']) 2933e12c5d1SDavid du Colombier Bprint(&bso, "%5.2f mkfwd\n", cputime()); 2943e12c5d1SDavid du Colombier Bflush(&bso); 2953e12c5d1SDavid du Colombier mkfwd(); 2963e12c5d1SDavid du Colombier if(debug['v']) 2973e12c5d1SDavid du Colombier Bprint(&bso, "%5.2f patch\n", cputime()); 2983e12c5d1SDavid du Colombier Bflush(&bso); 2993e12c5d1SDavid du Colombier s = lookup("exit", 0); 3003e12c5d1SDavid du Colombier vexit = s->value; 3013e12c5d1SDavid du Colombier for(p = firstp; p != P; p = p->link) { 3023e12c5d1SDavid du Colombier if(p->as == ATEXT) 3033e12c5d1SDavid du Colombier curtext = p; 304219b2ee8SDavid du Colombier if(p->as == ACALL || p->as == ARET) { 3053e12c5d1SDavid du Colombier s = p->to.sym; 3063e12c5d1SDavid du Colombier if(s) { 3079a747e4fSDavid du Colombier if(debug['c']) 3089a747e4fSDavid du Colombier Bprint(&bso, "%s calls %s\n", TNAME, s->name); 3099a747e4fSDavid du Colombier switch(s->type) { 310375daca8SDavid du Colombier default: 311375daca8SDavid du Colombier diag("undefined: %s in %s", s->name, TNAME); 312375daca8SDavid du Colombier s->type = STEXT; 313375daca8SDavid du Colombier s->value = vexit; 314375daca8SDavid du Colombier break; /* or fall through to set offset? */ 3159a747e4fSDavid du Colombier case STEXT: 3169a747e4fSDavid du Colombier p->to.offset = s->value; 3179a747e4fSDavid du Colombier break; 3189a747e4fSDavid du Colombier case SUNDEF: 3199a747e4fSDavid du Colombier p->pcond = UP; 3209a747e4fSDavid du Colombier p->to.offset = 0; 3219a747e4fSDavid du Colombier break; 3223e12c5d1SDavid du Colombier } 3233e12c5d1SDavid du Colombier p->to.type = D_BRANCH; 3243e12c5d1SDavid du Colombier } 3253e12c5d1SDavid du Colombier } 3269a747e4fSDavid du Colombier if(p->to.type != D_BRANCH || p->pcond == UP) 3273e12c5d1SDavid du Colombier continue; 3283e12c5d1SDavid du Colombier c = p->to.offset; 3293e12c5d1SDavid du Colombier for(q = firstp; q != P;) { 3303e12c5d1SDavid du Colombier if(q->forwd != P) 3313e12c5d1SDavid du Colombier if(c >= q->forwd->pc) { 3323e12c5d1SDavid du Colombier q = q->forwd; 3333e12c5d1SDavid du Colombier continue; 3343e12c5d1SDavid du Colombier } 3353e12c5d1SDavid du Colombier if(c == q->pc) 3363e12c5d1SDavid du Colombier break; 3373e12c5d1SDavid du Colombier q = q->link; 3383e12c5d1SDavid du Colombier } 3393e12c5d1SDavid du Colombier if(q == P) { 3406b6b9ac8SDavid du Colombier diag("branch out of range in %s\n%P", TNAME, p); 3413e12c5d1SDavid du Colombier p->to.type = D_NONE; 3423e12c5d1SDavid du Colombier } 3437dd7cddfSDavid du Colombier p->pcond = q; 3443e12c5d1SDavid du Colombier } 3453e12c5d1SDavid du Colombier 3463e12c5d1SDavid du Colombier for(p = firstp; p != P; p = p->link) { 3473e12c5d1SDavid du Colombier if(p->as == ATEXT) 3483e12c5d1SDavid du Colombier curtext = p; 3493e12c5d1SDavid du Colombier p->mark = 0; /* initialization for follow */ 3509a747e4fSDavid du Colombier if(p->pcond != P && p->pcond != UP) { 3517dd7cddfSDavid du Colombier p->pcond = brloop(p->pcond); 3527dd7cddfSDavid du Colombier if(p->pcond != P) 3533e12c5d1SDavid du Colombier if(p->to.type == D_BRANCH) 3547dd7cddfSDavid du Colombier p->to.offset = p->pcond->pc; 3553e12c5d1SDavid du Colombier } 3563e12c5d1SDavid du Colombier } 3573e12c5d1SDavid du Colombier } 3583e12c5d1SDavid du Colombier 3593e12c5d1SDavid du Colombier #define LOG 5 3603e12c5d1SDavid du Colombier void 3613e12c5d1SDavid du Colombier mkfwd(void) 3623e12c5d1SDavid du Colombier { 3633e12c5d1SDavid du Colombier Prog *p; 3643e12c5d1SDavid du Colombier int i; 3653e12c5d1SDavid du Colombier long dwn[LOG], cnt[LOG]; 3663e12c5d1SDavid du Colombier Prog *lst[LOG]; 3673e12c5d1SDavid du Colombier 3683e12c5d1SDavid du Colombier for(i=0; i<LOG; i++) { 3693e12c5d1SDavid du Colombier if(i == 0) 3703e12c5d1SDavid du Colombier cnt[i] = 1; else 3713e12c5d1SDavid du Colombier cnt[i] = LOG * cnt[i-1]; 3723e12c5d1SDavid du Colombier dwn[i] = 1; 3733e12c5d1SDavid du Colombier lst[i] = P; 3743e12c5d1SDavid du Colombier } 3753e12c5d1SDavid du Colombier i = 0; 3763e12c5d1SDavid du Colombier for(p = firstp; p != P; p = p->link) { 3773e12c5d1SDavid du Colombier if(p->as == ATEXT) 3783e12c5d1SDavid du Colombier curtext = p; 3793e12c5d1SDavid du Colombier i--; 3803e12c5d1SDavid du Colombier if(i < 0) 3813e12c5d1SDavid du Colombier i = LOG-1; 3823e12c5d1SDavid du Colombier p->forwd = P; 3833e12c5d1SDavid du Colombier dwn[i]--; 3843e12c5d1SDavid du Colombier if(dwn[i] <= 0) { 3853e12c5d1SDavid du Colombier dwn[i] = cnt[i]; 3863e12c5d1SDavid du Colombier if(lst[i] != P) 3873e12c5d1SDavid du Colombier lst[i]->forwd = p; 3883e12c5d1SDavid du Colombier lst[i] = p; 3893e12c5d1SDavid du Colombier } 3903e12c5d1SDavid du Colombier } 3913e12c5d1SDavid du Colombier } 3923e12c5d1SDavid du Colombier 3933e12c5d1SDavid du Colombier Prog* 3943e12c5d1SDavid du Colombier brloop(Prog *p) 3953e12c5d1SDavid du Colombier { 3963e12c5d1SDavid du Colombier int c; 3973e12c5d1SDavid du Colombier Prog *q; 3983e12c5d1SDavid du Colombier 3993e12c5d1SDavid du Colombier c = 0; 4007dd7cddfSDavid du Colombier for(q = p; q != P; q = q->pcond) { 4013e12c5d1SDavid du Colombier if(q->as != AJMP) 4023e12c5d1SDavid du Colombier break; 4033e12c5d1SDavid du Colombier c++; 4047dd7cddfSDavid du Colombier if(c >= 5000) 4053e12c5d1SDavid du Colombier return P; 4063e12c5d1SDavid du Colombier } 4073e12c5d1SDavid du Colombier return q; 4083e12c5d1SDavid du Colombier } 4093e12c5d1SDavid du Colombier 4103e12c5d1SDavid du Colombier void 4113e12c5d1SDavid du Colombier dostkoff(void) 4123e12c5d1SDavid du Colombier { 4133e12c5d1SDavid du Colombier Prog *p, *q; 414219b2ee8SDavid du Colombier long autoffset, deltasp; 415219b2ee8SDavid du Colombier int a, f, curframe, curbecome, maxbecome; 4163e12c5d1SDavid du Colombier 417219b2ee8SDavid du Colombier curframe = 0; 418219b2ee8SDavid du Colombier curbecome = 0; 419219b2ee8SDavid du Colombier maxbecome = 0; 420219b2ee8SDavid du Colombier curtext = 0; 421219b2ee8SDavid du Colombier for(p = firstp; p != P; p = p->link) { 422219b2ee8SDavid du Colombier 423219b2ee8SDavid du Colombier /* find out how much arg space is used in this TEXT */ 424219b2ee8SDavid du Colombier if(p->to.type == (D_INDIR+D_SP)) 425219b2ee8SDavid du Colombier if(p->to.offset > curframe) 426219b2ee8SDavid du Colombier curframe = p->to.offset; 427219b2ee8SDavid du Colombier 428219b2ee8SDavid du Colombier switch(p->as) { 429219b2ee8SDavid du Colombier case ATEXT: 430219b2ee8SDavid du Colombier if(curtext && curtext->from.sym) { 431219b2ee8SDavid du Colombier curtext->from.sym->frame = curframe; 432219b2ee8SDavid du Colombier curtext->from.sym->become = curbecome; 433219b2ee8SDavid du Colombier if(curbecome > maxbecome) 434219b2ee8SDavid du Colombier maxbecome = curbecome; 435219b2ee8SDavid du Colombier } 436219b2ee8SDavid du Colombier curframe = 0; 437219b2ee8SDavid du Colombier curbecome = 0; 438219b2ee8SDavid du Colombier 439219b2ee8SDavid du Colombier curtext = p; 440219b2ee8SDavid du Colombier break; 441219b2ee8SDavid du Colombier 442219b2ee8SDavid du Colombier case ARET: 443219b2ee8SDavid du Colombier /* special form of RET is BECOME */ 444219b2ee8SDavid du Colombier if(p->from.type == D_CONST) 445219b2ee8SDavid du Colombier if(p->from.offset > curbecome) 446219b2ee8SDavid du Colombier curbecome = p->from.offset; 447219b2ee8SDavid du Colombier break; 448219b2ee8SDavid du Colombier } 449219b2ee8SDavid du Colombier } 450219b2ee8SDavid du Colombier if(curtext && curtext->from.sym) { 451219b2ee8SDavid du Colombier curtext->from.sym->frame = curframe; 452219b2ee8SDavid du Colombier curtext->from.sym->become = curbecome; 453219b2ee8SDavid du Colombier if(curbecome > maxbecome) 454219b2ee8SDavid du Colombier maxbecome = curbecome; 455219b2ee8SDavid du Colombier } 456219b2ee8SDavid du Colombier 457219b2ee8SDavid du Colombier if(debug['b']) 458219b2ee8SDavid du Colombier print("max become = %d\n", maxbecome); 459219b2ee8SDavid du Colombier xdefine("ALEFbecome", STEXT, maxbecome); 460219b2ee8SDavid du Colombier 461219b2ee8SDavid du Colombier curtext = 0; 462219b2ee8SDavid du Colombier for(p = firstp; p != P; p = p->link) { 463219b2ee8SDavid du Colombier switch(p->as) { 464219b2ee8SDavid du Colombier case ATEXT: 465219b2ee8SDavid du Colombier curtext = p; 466219b2ee8SDavid du Colombier break; 467219b2ee8SDavid du Colombier case ACALL: 468219b2ee8SDavid du Colombier if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) { 469219b2ee8SDavid du Colombier f = maxbecome - curtext->from.sym->frame; 470219b2ee8SDavid du Colombier if(f <= 0) 471219b2ee8SDavid du Colombier break; 472219b2ee8SDavid du Colombier /* calling a become or calling a variable */ 473219b2ee8SDavid du Colombier if(p->to.sym == S || p->to.sym->become) { 474219b2ee8SDavid du Colombier curtext->to.offset += f; 475219b2ee8SDavid du Colombier if(debug['b']) { 476219b2ee8SDavid du Colombier curp = p; 477219b2ee8SDavid du Colombier print("%D calling %D increase %d\n", 478219b2ee8SDavid du Colombier &curtext->from, &p->to, f); 479219b2ee8SDavid du Colombier } 480219b2ee8SDavid du Colombier } 481219b2ee8SDavid du Colombier } 482219b2ee8SDavid du Colombier break; 483219b2ee8SDavid du Colombier } 484219b2ee8SDavid du Colombier } 485219b2ee8SDavid du Colombier 486219b2ee8SDavid du Colombier autoffset = 0; 487219b2ee8SDavid du Colombier deltasp = 0; 4883e12c5d1SDavid du Colombier for(p = firstp; p != P; p = p->link) { 4893e12c5d1SDavid du Colombier if(p->as == ATEXT) { 4903e12c5d1SDavid du Colombier curtext = p; 491219b2ee8SDavid du Colombier autoffset = p->to.offset; 492219b2ee8SDavid du Colombier if(autoffset < 0) 493219b2ee8SDavid du Colombier autoffset = 0; 494219b2ee8SDavid du Colombier if(autoffset) { 4953e12c5d1SDavid du Colombier p = appendp(p); 4963e12c5d1SDavid du Colombier p->as = AADJSP; 4973e12c5d1SDavid du Colombier p->from.type = D_CONST; 498219b2ee8SDavid du Colombier p->from.offset = autoffset; 4993e12c5d1SDavid du Colombier } 500219b2ee8SDavid du Colombier deltasp = autoffset; 5013e12c5d1SDavid du Colombier } 5023e12c5d1SDavid du Colombier a = p->from.type; 5033e12c5d1SDavid du Colombier if(a == D_AUTO) 504219b2ee8SDavid du Colombier p->from.offset += deltasp; 5053e12c5d1SDavid du Colombier if(a == D_PARAM) 506219b2ee8SDavid du Colombier p->from.offset += deltasp + 4; 5073e12c5d1SDavid du Colombier a = p->to.type; 5083e12c5d1SDavid du Colombier if(a == D_AUTO) 509219b2ee8SDavid du Colombier p->to.offset += deltasp; 5103e12c5d1SDavid du Colombier if(a == D_PARAM) 511219b2ee8SDavid du Colombier p->to.offset += deltasp + 4; 512219b2ee8SDavid du Colombier 513219b2ee8SDavid du Colombier switch(p->as) { 514219b2ee8SDavid du Colombier default: 5153e12c5d1SDavid du Colombier continue; 516219b2ee8SDavid du Colombier case APUSHL: 517219b2ee8SDavid du Colombier case APUSHFL: 518219b2ee8SDavid du Colombier deltasp += 4; 5193e12c5d1SDavid du Colombier continue; 520219b2ee8SDavid du Colombier case APUSHW: 521219b2ee8SDavid du Colombier case APUSHFW: 522219b2ee8SDavid du Colombier deltasp += 2; 523219b2ee8SDavid du Colombier continue; 524219b2ee8SDavid du Colombier case APOPL: 525219b2ee8SDavid du Colombier case APOPFL: 526219b2ee8SDavid du Colombier deltasp -= 4; 527219b2ee8SDavid du Colombier continue; 528219b2ee8SDavid du Colombier case APOPW: 529219b2ee8SDavid du Colombier case APOPFW: 530219b2ee8SDavid du Colombier deltasp -= 2; 531219b2ee8SDavid du Colombier continue; 532219b2ee8SDavid du Colombier case ARET: 533219b2ee8SDavid du Colombier break; 534219b2ee8SDavid du Colombier } 535219b2ee8SDavid du Colombier 536219b2ee8SDavid du Colombier if(autoffset != deltasp) 537219b2ee8SDavid du Colombier diag("unbalanced PUSH/POP"); 538219b2ee8SDavid du Colombier if(p->from.type == D_CONST) 539219b2ee8SDavid du Colombier goto become; 540219b2ee8SDavid du Colombier 541219b2ee8SDavid du Colombier if(autoffset) { 5423e12c5d1SDavid du Colombier q = p; 5433e12c5d1SDavid du Colombier p = appendp(p); 5443e12c5d1SDavid du Colombier p->as = ARET; 5453e12c5d1SDavid du Colombier 5463e12c5d1SDavid du Colombier q->as = AADJSP; 5473e12c5d1SDavid du Colombier q->from.type = D_CONST; 548219b2ee8SDavid du Colombier q->from.offset = -autoffset; 549219b2ee8SDavid du Colombier } 550219b2ee8SDavid du Colombier continue; 551219b2ee8SDavid du Colombier 552219b2ee8SDavid du Colombier become: 553219b2ee8SDavid du Colombier q = p; 554219b2ee8SDavid du Colombier p = appendp(p); 555219b2ee8SDavid du Colombier p->as = AJMP; 556219b2ee8SDavid du Colombier p->to = q->to; 5577dd7cddfSDavid du Colombier p->pcond = q->pcond; 558219b2ee8SDavid du Colombier 559219b2ee8SDavid du Colombier q->as = AADJSP; 560219b2ee8SDavid du Colombier q->from = zprg.from; 561219b2ee8SDavid du Colombier q->from.type = D_CONST; 562219b2ee8SDavid du Colombier q->from.offset = -autoffset; 563219b2ee8SDavid du Colombier q->to = zprg.to; 564219b2ee8SDavid du Colombier continue; 5653e12c5d1SDavid du Colombier } 5663e12c5d1SDavid du Colombier } 5673e12c5d1SDavid du Colombier 5683e12c5d1SDavid du Colombier long 5693e12c5d1SDavid du Colombier atolwhex(char *s) 5703e12c5d1SDavid du Colombier { 5713e12c5d1SDavid du Colombier long n; 5723e12c5d1SDavid du Colombier int f; 5733e12c5d1SDavid du Colombier 5743e12c5d1SDavid du Colombier n = 0; 5753e12c5d1SDavid du Colombier f = 0; 5763e12c5d1SDavid du Colombier while(*s == ' ' || *s == '\t') 5773e12c5d1SDavid du Colombier s++; 5783e12c5d1SDavid du Colombier if(*s == '-' || *s == '+') { 5793e12c5d1SDavid du Colombier if(*s++ == '-') 5803e12c5d1SDavid du Colombier f = 1; 5813e12c5d1SDavid du Colombier while(*s == ' ' || *s == '\t') 5823e12c5d1SDavid du Colombier s++; 5833e12c5d1SDavid du Colombier } 5843e12c5d1SDavid du Colombier if(s[0]=='0' && s[1]){ 5853e12c5d1SDavid du Colombier if(s[1]=='x' || s[1]=='X'){ 5863e12c5d1SDavid du Colombier s += 2; 5873e12c5d1SDavid du Colombier for(;;){ 5883e12c5d1SDavid du Colombier if(*s >= '0' && *s <= '9') 5893e12c5d1SDavid du Colombier n = n*16 + *s++ - '0'; 5903e12c5d1SDavid du Colombier else if(*s >= 'a' && *s <= 'f') 5913e12c5d1SDavid du Colombier n = n*16 + *s++ - 'a' + 10; 5923e12c5d1SDavid du Colombier else if(*s >= 'A' && *s <= 'F') 5933e12c5d1SDavid du Colombier n = n*16 + *s++ - 'A' + 10; 5943e12c5d1SDavid du Colombier else 5953e12c5d1SDavid du Colombier break; 5963e12c5d1SDavid du Colombier } 5973e12c5d1SDavid du Colombier } else 5983e12c5d1SDavid du Colombier while(*s >= '0' && *s <= '7') 5993e12c5d1SDavid du Colombier n = n*8 + *s++ - '0'; 6003e12c5d1SDavid du Colombier } else 6013e12c5d1SDavid du Colombier while(*s >= '0' && *s <= '9') 6023e12c5d1SDavid du Colombier n = n*10 + *s++ - '0'; 6033e12c5d1SDavid du Colombier if(f) 6043e12c5d1SDavid du Colombier n = -n; 6053e12c5d1SDavid du Colombier return n; 6063e12c5d1SDavid du Colombier } 6073e12c5d1SDavid du Colombier 6083e12c5d1SDavid du Colombier void 6093e12c5d1SDavid du Colombier undef(void) 6103e12c5d1SDavid du Colombier { 6113e12c5d1SDavid du Colombier int i; 6123e12c5d1SDavid du Colombier Sym *s; 6133e12c5d1SDavid du Colombier 6143e12c5d1SDavid du Colombier for(i=0; i<NHASH; i++) 6153e12c5d1SDavid du Colombier for(s = hash[i]; s != S; s = s->link) 6163e12c5d1SDavid du Colombier if(s->type == SXREF) 6176b6b9ac8SDavid du Colombier diag("%s: not defined", s->name); 6183e12c5d1SDavid du Colombier } 619375daca8SDavid du Colombier 620375daca8SDavid du Colombier void 621375daca8SDavid du Colombier import(void) 622375daca8SDavid du Colombier { 623375daca8SDavid du Colombier int i; 624375daca8SDavid du Colombier Sym *s; 625375daca8SDavid du Colombier 626375daca8SDavid du Colombier for(i = 0; i < NHASH; i++) 627375daca8SDavid du Colombier for(s = hash[i]; s != S; s = s->link) 628375daca8SDavid du Colombier if(s->sig != 0 && s->type == SXREF && (nimports == 0 || s->subtype == SIMPORT)){ 629375daca8SDavid du Colombier if(s->value != 0) 630375daca8SDavid du Colombier diag("value != 0 on SXREF"); 631375daca8SDavid du Colombier undefsym(s); 632*d7a1d466SDavid du Colombier if(debug['X']) 633375daca8SDavid du Colombier Bprint(&bso, "IMPORT: %s sig=%lux v=%ld\n", s->name, s->sig, s->value); 634375daca8SDavid du Colombier if(debug['S']) 635375daca8SDavid du Colombier s->sig = 0; 636375daca8SDavid du Colombier } 637375daca8SDavid du Colombier } 638375daca8SDavid du Colombier 639375daca8SDavid du Colombier void 640375daca8SDavid du Colombier ckoff(Sym *s, long v) 641375daca8SDavid du Colombier { 642375daca8SDavid du Colombier if(v < 0 || v >= 1<<Roffset) 643375daca8SDavid du Colombier diag("relocation offset %ld for %s out of range", v, s->name); 644375daca8SDavid du Colombier } 645375daca8SDavid du Colombier 646375daca8SDavid du Colombier static Prog* 647375daca8SDavid du Colombier newdata(Sym *s, int o, int w, int t) 648375daca8SDavid du Colombier { 649375daca8SDavid du Colombier Prog *p; 650375daca8SDavid du Colombier 651375daca8SDavid du Colombier p = prg(); 652375daca8SDavid du Colombier if(edatap == P) 653375daca8SDavid du Colombier datap = p; 654375daca8SDavid du Colombier else 655375daca8SDavid du Colombier edatap->link = p; 656375daca8SDavid du Colombier edatap = p; 657375daca8SDavid du Colombier p->as = ADATA; 658375daca8SDavid du Colombier p->width = w; 659375daca8SDavid du Colombier p->from.scale = w; 660375daca8SDavid du Colombier p->from.type = t; 661375daca8SDavid du Colombier p->from.sym = s; 662375daca8SDavid du Colombier p->from.offset = o; 663375daca8SDavid du Colombier p->to.type = D_CONST; 664375daca8SDavid du Colombier return p; 665375daca8SDavid du Colombier } 666375daca8SDavid du Colombier 667375daca8SDavid du Colombier void 668375daca8SDavid du Colombier export(void) 669375daca8SDavid du Colombier { 670375daca8SDavid du Colombier int i, j, n, off, nb, sv, ne; 671375daca8SDavid du Colombier Sym *s, *et, *str, **esyms; 672375daca8SDavid du Colombier Prog *p; 673375daca8SDavid du Colombier char buf[NSNAME], *t; 674375daca8SDavid du Colombier 675375daca8SDavid du Colombier n = 0; 676375daca8SDavid du Colombier for(i = 0; i < NHASH; i++) 677375daca8SDavid du Colombier for(s = hash[i]; s != S; s = s->link) 678375daca8SDavid du Colombier if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF && (nexports == 0 || s->subtype == SEXPORT)) 679375daca8SDavid du Colombier n++; 680375daca8SDavid du Colombier esyms = malloc(n*sizeof(Sym*)); 681375daca8SDavid du Colombier ne = n; 682375daca8SDavid du Colombier n = 0; 683375daca8SDavid du Colombier for(i = 0; i < NHASH; i++) 684375daca8SDavid du Colombier for(s = hash[i]; s != S; s = s->link) 685375daca8SDavid du Colombier if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF && (nexports == 0 || s->subtype == SEXPORT)) 686375daca8SDavid du Colombier esyms[n++] = s; 687375daca8SDavid du Colombier for(i = 0; i < ne-1; i++) 688375daca8SDavid du Colombier for(j = i+1; j < ne; j++) 689375daca8SDavid du Colombier if(strcmp(esyms[i]->name, esyms[j]->name) > 0){ 690375daca8SDavid du Colombier s = esyms[i]; 691375daca8SDavid du Colombier esyms[i] = esyms[j]; 692375daca8SDavid du Colombier esyms[j] = s; 693375daca8SDavid du Colombier } 694375daca8SDavid du Colombier 695375daca8SDavid du Colombier nb = 0; 696375daca8SDavid du Colombier off = 0; 697375daca8SDavid du Colombier et = lookup(EXPTAB, 0); 698375daca8SDavid du Colombier if(et->type != 0 && et->type != SXREF) 699375daca8SDavid du Colombier diag("%s already defined", EXPTAB); 700375daca8SDavid du Colombier et->type = SDATA; 701375daca8SDavid du Colombier str = lookup(".string", 0); 702375daca8SDavid du Colombier if(str->type == 0) 703375daca8SDavid du Colombier str->type = SDATA; 704375daca8SDavid du Colombier sv = str->value; 705375daca8SDavid du Colombier for(i = 0; i < ne; i++){ 706375daca8SDavid du Colombier s = esyms[i]; 707375daca8SDavid du Colombier if(debug['S']) 708375daca8SDavid du Colombier s->sig = 0; 709375daca8SDavid du Colombier /* Bprint(&bso, "EXPORT: %s sig=%lux t=%d\n", s->name, s->sig, s->type); */ 710375daca8SDavid du Colombier 711375daca8SDavid du Colombier /* signature */ 712375daca8SDavid du Colombier p = newdata(et, off, sizeof(long), D_EXTERN); 713375daca8SDavid du Colombier off += sizeof(long); 714375daca8SDavid du Colombier p->to.offset = s->sig; 715375daca8SDavid du Colombier 716375daca8SDavid du Colombier /* address */ 717375daca8SDavid du Colombier p = newdata(et, off, sizeof(long), D_EXTERN); 718375daca8SDavid du Colombier off += sizeof(long); 719375daca8SDavid du Colombier p->to.type = D_ADDR; 720375daca8SDavid du Colombier p->to.index = D_EXTERN; 721375daca8SDavid du Colombier p->to.sym = s; 722375daca8SDavid du Colombier 723375daca8SDavid du Colombier /* string */ 724375daca8SDavid du Colombier t = s->name; 725375daca8SDavid du Colombier n = strlen(t)+1; 726375daca8SDavid du Colombier for(;;){ 727375daca8SDavid du Colombier buf[nb++] = *t; 728375daca8SDavid du Colombier sv++; 729375daca8SDavid du Colombier if(nb >= NSNAME){ 730375daca8SDavid du Colombier p = newdata(str, sv-NSNAME, NSNAME, D_STATIC); 731375daca8SDavid du Colombier p->to.type = D_SCONST; 732375daca8SDavid du Colombier memmove(p->to.scon, buf, NSNAME); 733375daca8SDavid du Colombier nb = 0; 734375daca8SDavid du Colombier } 735375daca8SDavid du Colombier if(*t++ == 0) 736375daca8SDavid du Colombier break; 737375daca8SDavid du Colombier } 738375daca8SDavid du Colombier 739375daca8SDavid du Colombier /* name */ 740375daca8SDavid du Colombier p = newdata(et, off, sizeof(long), D_EXTERN); 741375daca8SDavid du Colombier off += sizeof(long); 742375daca8SDavid du Colombier p->to.type = D_ADDR; 743375daca8SDavid du Colombier p->to.index = D_STATIC; 744375daca8SDavid du Colombier p->to.sym = str; 745375daca8SDavid du Colombier p->to.offset = sv-n; 746375daca8SDavid du Colombier } 747375daca8SDavid du Colombier 748375daca8SDavid du Colombier if(nb > 0){ 749375daca8SDavid du Colombier p = newdata(str, sv-nb, nb, D_STATIC); 750375daca8SDavid du Colombier p->to.type = D_SCONST; 751375daca8SDavid du Colombier memmove(p->to.scon, buf, nb); 752375daca8SDavid du Colombier } 753375daca8SDavid du Colombier 754375daca8SDavid du Colombier for(i = 0; i < 3; i++){ 755375daca8SDavid du Colombier newdata(et, off, sizeof(long), D_EXTERN); 756375daca8SDavid du Colombier off += sizeof(long); 757375daca8SDavid du Colombier } 758375daca8SDavid du Colombier et->value = off; 759375daca8SDavid du Colombier if(sv == 0) 760375daca8SDavid du Colombier sv = 1; 761375daca8SDavid du Colombier str->value = sv; 762375daca8SDavid du Colombier exports = ne; 763375daca8SDavid du Colombier free(esyms); 764375daca8SDavid du Colombier } 765