1 #include "l.h" 2 3 void 4 dodata(void) 5 { 6 int i, t; 7 Sym *s; 8 Prog *p; 9 long orig, v; 10 11 if(debug['v']) 12 Bprint(&bso, "%5.2f dodata\n", cputime()); 13 Bflush(&bso); 14 for(p = datap; p != P; p = p->link) { 15 s = p->from.sym; 16 if(p->as == ADYNT || p->as == AINIT) 17 s->value = dtype; 18 if(s->type == SBSS) 19 s->type = SDATA; 20 if(s->type != SDATA) 21 diag("initialize non-data (%d): %s\n%P\n", 22 s->type, s->name, p); 23 v = p->from.offset + p->reg; 24 if(v > s->value) 25 diag("initialize bounds (%ld): %s\n%P\n", 26 s->value, s->name, p); 27 } 28 29 if(debug['t']) { 30 /* 31 * pull out string constants 32 */ 33 for(p = datap; p != P; p = p->link) { 34 s = p->from.sym; 35 if(p->to.type == D_SCONST) 36 s->type = SSTRING; 37 } 38 } 39 40 /* 41 * pass 1 42 * assign 'small' variables to data segment 43 * (rational is that data segment is more easily 44 * addressed through offset on R12) 45 */ 46 orig = 0; 47 for(i=0; i<NHASH; i++) 48 for(s = hash[i]; s != S; s = s->link) { 49 t = s->type; 50 if(t != SDATA && t != SBSS) 51 continue; 52 v = s->value; 53 if(v == 0) { 54 diag("%s: no size\n", s->name); 55 v = 1; 56 } 57 while(v & 3) 58 v++; 59 s->value = v; 60 if(v > MINSIZ) 61 continue; 62 s->value = orig; 63 orig += v; 64 s->type = SDATA1; 65 } 66 67 /* 68 * pass 2 69 * assign large 'data' variables to data segment 70 */ 71 for(i=0; i<NHASH; i++) 72 for(s = hash[i]; s != S; s = s->link) { 73 t = s->type; 74 if(t != SDATA) { 75 if(t == SDATA1) 76 s->type = SDATA; 77 continue; 78 } 79 v = s->value; 80 s->value = orig; 81 orig += v; 82 } 83 84 while(orig & 7) 85 orig++; 86 datsize = orig; 87 88 /* 89 * pass 3 90 * everything else to bss segment 91 */ 92 for(i=0; i<NHASH; i++) 93 for(s = hash[i]; s != S; s = s->link) { 94 if(s->type != SBSS) 95 continue; 96 v = s->value; 97 s->value = orig; 98 orig += v; 99 } 100 while(orig & 7) 101 orig++; 102 bsssize = orig-datsize; 103 104 xdefine("setR12", SDATA, 0L+BIG); 105 xdefine("bdata", SDATA, 0L); 106 xdefine("edata", SDATA, datsize); 107 xdefine("end", SBSS, datsize+bsssize); 108 xdefine("etext", STEXT, 0L); 109 } 110 111 void 112 undef(void) 113 { 114 int i; 115 Sym *s; 116 117 for(i=0; i<NHASH; i++) 118 for(s = hash[i]; s != S; s = s->link) 119 if(s->type == SXREF) 120 diag("%s: not defined\n", s->name); 121 } 122 123 Prog* 124 brchain(Prog *p) 125 { 126 int i; 127 128 for(i=0; i<20; i++) { 129 if(p == P || p->as != AB) 130 return p; 131 p = p->cond; 132 } 133 return P; 134 } 135 136 int 137 relinv(int a) 138 { 139 switch(a) { 140 case ABEQ: return ABNE; 141 case ABNE: return ABEQ; 142 case ABCS: return ABCC; 143 case ABHS: return ABLO; 144 case ABCC: return ABCS; 145 case ABLO: return ABHS; 146 case ABMI: return ABPL; 147 case ABPL: return ABMI; 148 case ABVS: return ABVC; 149 case ABVC: return ABVS; 150 case ABHI: return ABLS; 151 case ABLS: return ABHI; 152 case ABGE: return ABLT; 153 case ABLT: return ABGE; 154 case ABGT: return ABLE; 155 case ABLE: return ABGT; 156 } 157 diag("unknown relation: %s\n", anames[a]); 158 return a; 159 } 160 161 void 162 follow(void) 163 { 164 if(debug['v']) 165 Bprint(&bso, "%5.2f follow\n", cputime()); 166 Bflush(&bso); 167 168 firstp = prg(); 169 lastp = firstp; 170 xfol(textp); 171 172 firstp = firstp->link; 173 lastp->link = P; 174 } 175 176 void 177 xfol(Prog *p) 178 { 179 Prog *q, *r; 180 int a, i; 181 182 loop: 183 if(p == P) 184 return; 185 a = p->as; 186 if(a == ATEXT) 187 curtext = p; 188 if(a == AB) { 189 q = p->cond; 190 if(q != P) { 191 p->mark |= FOLL; 192 p = q; 193 if(!(p->mark & FOLL)) 194 goto loop; 195 } 196 } 197 if(p->mark & FOLL) { 198 for(i=0,q=p; i<4; i++,q=q->link) { 199 if(q == lastp) 200 break; 201 a = q->as; 202 if(a == ANOP) { 203 i--; 204 continue; 205 } 206 if(a == AB || (a == ARET && q->scond == 14) || a == ARFE) 207 goto copy; 208 if(!q->cond || (q->cond->mark&FOLL)) 209 continue; 210 if(a != ABEQ && a != ABNE) 211 continue; 212 copy: 213 for(;;) { 214 r = prg(); 215 *r = *p; 216 if(!(r->mark&FOLL)) 217 print("cant happen 1\n"); 218 r->mark |= FOLL; 219 if(p != q) { 220 p = p->link; 221 lastp->link = r; 222 lastp = r; 223 continue; 224 } 225 lastp->link = r; 226 lastp = r; 227 if(a == AB || (a == ARET && q->scond == 14) || a == ARFE) 228 return; 229 r->as = ABNE; 230 if(a == ABNE) 231 r->as = ABEQ; 232 r->cond = p->link; 233 r->link = p->cond; 234 if(!(r->link->mark&FOLL)) 235 xfol(r->link); 236 if(!(r->cond->mark&FOLL)) 237 print("cant happen 2\n"); 238 return; 239 } 240 } 241 a = AB; 242 q = prg(); 243 q->as = a; 244 q->line = p->line; 245 q->to.type = D_BRANCH; 246 q->to.offset = p->pc; 247 q->cond = p; 248 p = q; 249 } 250 p->mark |= FOLL; 251 lastp->link = p; 252 lastp = p; 253 if(a == AB || (a == ARET && p->scond == 14) || a == ARFE){ 254 return; 255 } 256 if(p->cond != P) 257 if(a != ABL && p->link != P) { 258 q = brchain(p->link); 259 if(a != ATEXT && a != ABCASE) 260 if(q != P && (q->mark&FOLL)) { 261 p->as = relinv(a); 262 p->link = p->cond; 263 p->cond = q; 264 } 265 xfol(p->link); 266 q = brchain(p->cond); 267 if(q == P) 268 q = p->cond; 269 if(q->mark&FOLL) { 270 p->cond = q; 271 return; 272 } 273 p = q; 274 goto loop; 275 } 276 p = p->link; 277 goto loop; 278 } 279 280 void 281 patch(void) 282 { 283 long c, vexit; 284 Prog *p, *q; 285 Sym *s; 286 int a; 287 288 if(debug['v']) 289 Bprint(&bso, "%5.2f patch\n", cputime()); 290 Bflush(&bso); 291 mkfwd(); 292 s = lookup("exit", 0); 293 vexit = s->value; 294 for(p = firstp; p != P; p = p->link) { 295 a = p->as; 296 if(a == ATEXT) 297 curtext = p; 298 if((a == ABL || a == AB || a == ARET) && 299 p->to.type != D_BRANCH && p->to.sym != S) { 300 s = p->to.sym; 301 if(s->type != STEXT) { 302 diag("undefined: %s\n%P\n", s->name, p); 303 s->type = STEXT; 304 s->value = vexit; 305 } 306 p->to.offset = s->value; 307 p->to.type = D_BRANCH; 308 } 309 if(p->to.type != D_BRANCH) 310 continue; 311 c = p->to.offset; 312 if(reloc && p->as == ABL && c == -1) { 313 p->cond = UP; 314 continue; 315 } 316 for(q = firstp; q != P;) { 317 if(q->forwd != P) 318 if(c >= q->forwd->pc) { 319 q = q->forwd; 320 continue; 321 } 322 if(c == q->pc) 323 break; 324 q = q->link; 325 } 326 if(q == P) { 327 diag("branch out of range %ld\n%P\n", c, p); 328 p->to.type = D_NONE; 329 } 330 p->cond = q; 331 } 332 333 for(p = firstp; p != P; p = p->link) { 334 if(p->as == ATEXT) 335 curtext = p; 336 if(p->cond != P && p->cond != UP) { 337 p->cond = brloop(p->cond); 338 if(p->cond != P) 339 if(p->to.type == D_BRANCH) 340 p->to.offset = p->cond->pc; 341 } 342 } 343 } 344 345 #define LOG 5 346 void 347 mkfwd(void) 348 { 349 Prog *p; 350 long dwn[LOG], cnt[LOG], i; 351 Prog *lst[LOG]; 352 353 for(i=0; i<LOG; i++) { 354 if(i == 0) 355 cnt[i] = 1; else 356 cnt[i] = LOG * cnt[i-1]; 357 dwn[i] = 1; 358 lst[i] = P; 359 } 360 i = 0; 361 for(p = firstp; p != P; p = p->link) { 362 if(p->as == ATEXT) 363 curtext = p; 364 i--; 365 if(i < 0) 366 i = LOG-1; 367 p->forwd = P; 368 dwn[i]--; 369 if(dwn[i] <= 0) { 370 dwn[i] = cnt[i]; 371 if(lst[i] != P) 372 lst[i]->forwd = p; 373 lst[i] = p; 374 } 375 } 376 } 377 378 Prog* 379 brloop(Prog *p) 380 { 381 Prog *q; 382 int c; 383 384 for(c=0; p!=P;) { 385 if(p->as != AB) 386 return p; 387 q = p->cond; 388 if(q <= p) { 389 c++; 390 if(q == p || c > 5000) 391 break; 392 } 393 p = q; 394 } 395 return P; 396 } 397 398 long 399 atolwhex(char *s) 400 { 401 long n; 402 int f; 403 404 n = 0; 405 f = 0; 406 while(*s == ' ' || *s == '\t') 407 s++; 408 if(*s == '-' || *s == '+') { 409 if(*s++ == '-') 410 f = 1; 411 while(*s == ' ' || *s == '\t') 412 s++; 413 } 414 if(s[0]=='0' && s[1]){ 415 if(s[1]=='x' || s[1]=='X'){ 416 s += 2; 417 for(;;){ 418 if(*s >= '0' && *s <= '9') 419 n = n*16 + *s++ - '0'; 420 else if(*s >= 'a' && *s <= 'f') 421 n = n*16 + *s++ - 'a' + 10; 422 else if(*s >= 'A' && *s <= 'F') 423 n = n*16 + *s++ - 'A' + 10; 424 else 425 break; 426 } 427 } else 428 while(*s >= '0' && *s <= '7') 429 n = n*8 + *s++ - '0'; 430 } else 431 while(*s >= '0' && *s <= '9') 432 n = n*10 + *s++ - '0'; 433 if(f) 434 n = -n; 435 return n; 436 } 437 438 long 439 rnd(long v, long r) 440 { 441 long c; 442 443 if(r <= 0) 444 return v; 445 v += r - 1; 446 c = v % r; 447 if(c < 0) 448 c += r; 449 v -= c; 450 return v; 451 } 452