1 #include "l.h" 2 3 static Sym* sym_div; 4 static Sym* sym_divu; 5 static Sym* sym_mod; 6 static Sym* sym_modu; 7 8 void 9 noops(void) 10 { 11 Prog *p, *q, *q1; 12 int o, curframe, curbecome, maxbecome; 13 14 /* 15 * find leaf subroutines 16 * become sizes 17 * frame sizes 18 * strip NOPs 19 * expand RET 20 * expand BECOME pseudo 21 */ 22 23 if(debug['v']) 24 Bprint(&bso, "%5.2f noops\n", cputime()); 25 Bflush(&bso); 26 27 curframe = 0; 28 curbecome = 0; 29 maxbecome = 0; 30 curtext = 0; 31 32 q = P; 33 for(p = firstp; p != P; p = p->link) { 34 35 /* find out how much arg space is used in this TEXT */ 36 if(p->to.type == D_OREG && p->to.reg == REGSP) 37 if(p->to.offset > curframe) 38 curframe = p->to.offset; 39 40 switch(p->as) { 41 case ATEXT: 42 if(curtext && curtext->from.sym) { 43 curtext->from.sym->frame = curframe; 44 curtext->from.sym->become = curbecome; 45 if(curbecome > maxbecome) 46 maxbecome = curbecome; 47 } 48 curframe = 0; 49 curbecome = 0; 50 51 p->mark |= LEAF; 52 curtext = p; 53 break; 54 55 case ARET: 56 /* special form of RET is BECOME */ 57 if(p->from.type == D_CONST) 58 if(p->from.offset > curbecome) 59 curbecome = p->from.offset; 60 break; 61 62 case ADIV: 63 case ADIVU: 64 case AMOD: 65 case AMODU: 66 q = p; 67 if(prog_div == P) 68 initdiv(); 69 if(curtext != P) 70 curtext->mark &= ~LEAF; 71 continue; 72 73 case ANOP: 74 q1 = p->link; 75 q->link = q1; /* q is non-nop */ 76 q1->mark |= p->mark; 77 continue; 78 79 case ABL: 80 if(curtext != P) 81 curtext->mark &= ~LEAF; 82 83 case ABCASE: 84 case AB: 85 86 case ABEQ: 87 case ABNE: 88 case ABCS: 89 case ABHS: 90 case ABCC: 91 case ABLO: 92 case ABMI: 93 case ABPL: 94 case ABVS: 95 case ABVC: 96 case ABHI: 97 case ABLS: 98 case ABGE: 99 case ABLT: 100 case ABGT: 101 case ABLE: 102 103 q1 = p->cond; 104 if(q1 != P) { 105 while(q1->as == ANOP) { 106 q1 = q1->link; 107 p->cond = q1; 108 } 109 } 110 break; 111 } 112 q = p; 113 } 114 115 if(curtext && curtext->from.sym) { 116 curtext->from.sym->frame = curframe; 117 curtext->from.sym->become = curbecome; 118 if(curbecome > maxbecome) 119 maxbecome = curbecome; 120 } 121 122 if(debug['b']) 123 print("max become = %d\n", maxbecome); 124 xdefine("ALEFbecome", STEXT, maxbecome); 125 126 curtext = 0; 127 for(p = firstp; p != P; p = p->link) { 128 switch(p->as) { 129 case ATEXT: 130 curtext = p; 131 break; 132 case ABL: 133 if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) { 134 o = maxbecome - curtext->from.sym->frame; 135 if(o <= 0) 136 break; 137 /* calling a become or calling a variable */ 138 if(p->to.sym == S || p->to.sym->become) { 139 curtext->to.offset += o; 140 if(debug['b']) { 141 curp = p; 142 print("%D calling %D increase %d\n", 143 &curtext->from, &p->to, o); 144 } 145 } 146 } 147 break; 148 } 149 } 150 151 for(p = firstp; p != P; p = p->link) { 152 o = p->as; 153 switch(o) { 154 case ATEXT: 155 curtext = p; 156 autosize = p->to.offset + 4; 157 if(autosize <= 4) 158 if(curtext->mark & LEAF) { 159 p->to.offset = -4; 160 autosize = 0; 161 } 162 163 if(!autosize && !(curtext->mark & LEAF)) { 164 if(debug['v']) 165 Bprint(&bso, "save suppressed in: %s\n", 166 curtext->from.sym->name); 167 Bflush(&bso); 168 curtext->mark |= LEAF; 169 } 170 171 if(curtext->mark & LEAF) { 172 if(curtext->from.sym) 173 curtext->from.sym->type = SLEAF; 174 #ifdef optimise_time 175 if(autosize) { 176 q = prg(); 177 q->as = ASUB; 178 q->line = p->line; 179 q->from.type = D_CONST; 180 q->from.offset = autosize; 181 q->to.type = D_REG; 182 q->to.reg = REGSP; 183 184 q->link = p->link; 185 p->link = q; 186 } 187 break; 188 #else 189 if(!autosize) 190 break; 191 #endif 192 } 193 194 q1 = prg(); 195 q1->as = AMOVW; 196 q1->scond |= C_WBIT; 197 q1->line = p->line; 198 q1->from.type = D_REG; 199 q1->from.reg = REGLINK; 200 q1->to.type = D_OREG; 201 q1->to.offset = -autosize; 202 q1->to.reg = REGSP; 203 204 q1->link = p->link; 205 p->link = q1; 206 break; 207 208 case ARET: 209 nocache(p); 210 if(p->from.type == D_CONST) 211 goto become; 212 if(curtext->mark & LEAF) { 213 if(!autosize) { 214 p->as = AB; 215 p->from = zprg.from; 216 p->to.type = D_OREG; 217 p->to.offset = 0; 218 p->to.reg = REGLINK; 219 break; 220 } 221 222 #ifdef optimise_time 223 p->as = AADD; 224 p->from.type = D_CONST; 225 p->from.offset = autosize; 226 p->to.type = D_REG; 227 p->to.reg = REGSP; 228 229 q = prg(); 230 q->as = AB; 231 q->scond = p->scond; 232 q->line = p->line; 233 q->to.type = D_OREG; 234 q->to.offset = 0; 235 q->to.reg = REGLINK; 236 237 q->link = p->link; 238 p->link = q; 239 240 break; 241 #endif 242 } 243 p->as = AMOVW; 244 p->scond |= C_PBIT; 245 p->from.type = D_OREG; 246 p->from.offset = autosize; 247 p->from.reg = REGSP; 248 p->to.type = D_REG; 249 p->to.reg = REGPC; 250 break; 251 252 become: 253 if(curtext->mark & LEAF) { 254 255 if(!autosize) { 256 p->as = AB; 257 p->from = zprg.from; 258 break; 259 } 260 261 #ifdef optimise_time 262 q = prg(); 263 q->scond = p->scond; 264 q->line = p->line; 265 q->as = AB; 266 q->from = zprg.from; 267 q->to = p->to; 268 q->cond = p->cond; 269 q->link = p->link; 270 p->link = q; 271 272 p->as = AADD; 273 p->from = zprg.from; 274 p->from.type = D_CONST; 275 p->from.offset = autosize; 276 p->to = zprg.to; 277 p->to.type = D_REG; 278 p->to.reg = REGSP; 279 280 break; 281 #endif 282 } 283 q = prg(); 284 q->scond = p->scond; 285 q->line = p->line; 286 q->as = AB; 287 q->from = zprg.from; 288 q->to = p->to; 289 q->cond = p->cond; 290 q->link = p->link; 291 p->link = q; 292 293 p->as = AMOVW; 294 p->scond |= C_PBIT; 295 p->from = zprg.from; 296 p->from.type = D_OREG; 297 p->from.offset = autosize; 298 p->from.reg = REGSP; 299 p->to = zprg.to; 300 p->to.type = D_REG; 301 p->to.reg = REGLINK; 302 303 break; 304 305 /* 306 * 5c code generation for unsigned -> double made the 307 * unfortunate assumption that single and double floating 308 * point registers are aliased - true for emulated 7500 309 * but not for vfp. Now corrected, but this test is 310 * insurance against old 5c compiled code in libraries. 311 */ 312 case AMOVWD: 313 if((q = p->link) != P && q->as == ACMP) 314 if((q = q->link) != P && q->as == AMOVF) 315 if((q1 = q->link) != P && q1->as == AADDF) 316 if(q1->to.type == D_FREG && q1->to.reg == p->to.reg) { 317 q1->as = AADDD; 318 q1 = prg(); 319 q1->scond = q->scond; 320 q1->line = q->line; 321 q1->as = AMOVFD; 322 q1->from = q->to; 323 q1->to = q1->from; 324 q1->link = q->link; 325 q->link = q1; 326 } 327 break; 328 329 case ADIV: 330 case ADIVU: 331 case AMOD: 332 case AMODU: 333 if(debug['M']) 334 break; 335 if(p->from.type != D_REG) 336 break; 337 if(p->to.type != D_REG) 338 break; 339 q1 = p; 340 341 /* MOV a,4(SP) */ 342 q = prg(); 343 q->link = p->link; 344 p->link = q; 345 p = q; 346 347 p->as = AMOVW; 348 p->line = q1->line; 349 p->from.type = D_REG; 350 p->from.reg = q1->from.reg; 351 p->to.type = D_OREG; 352 p->to.reg = REGSP; 353 p->to.offset = 4; 354 355 /* MOV b,REGTMP */ 356 q = prg(); 357 q->link = p->link; 358 p->link = q; 359 p = q; 360 361 p->as = AMOVW; 362 p->line = q1->line; 363 p->from.type = D_REG; 364 p->from.reg = q1->reg; 365 if(q1->reg == NREG) 366 p->from.reg = q1->to.reg; 367 p->to.type = D_REG; 368 p->to.reg = REGTMP; 369 p->to.offset = 0; 370 371 /* CALL appropriate */ 372 q = prg(); 373 q->link = p->link; 374 p->link = q; 375 p = q; 376 377 p->as = ABL; 378 p->line = q1->line; 379 p->to.type = D_BRANCH; 380 p->cond = p; 381 switch(o) { 382 case ADIV: 383 p->cond = prog_div; 384 p->to.sym = sym_div; 385 break; 386 case ADIVU: 387 p->cond = prog_divu; 388 p->to.sym = sym_divu; 389 break; 390 case AMOD: 391 p->cond = prog_mod; 392 p->to.sym = sym_mod; 393 break; 394 case AMODU: 395 p->cond = prog_modu; 396 p->to.sym = sym_modu; 397 break; 398 } 399 400 /* MOV REGTMP, b */ 401 q = prg(); 402 q->link = p->link; 403 p->link = q; 404 p = q; 405 406 p->as = AMOVW; 407 p->line = q1->line; 408 p->from.type = D_REG; 409 p->from.reg = REGTMP; 410 p->from.offset = 0; 411 p->to.type = D_REG; 412 p->to.reg = q1->to.reg; 413 414 /* ADD $8,SP */ 415 q = prg(); 416 q->link = p->link; 417 p->link = q; 418 p = q; 419 420 p->as = AADD; 421 p->from.type = D_CONST; 422 p->from.reg = NREG; 423 p->from.offset = 8; 424 p->reg = NREG; 425 p->to.type = D_REG; 426 p->to.reg = REGSP; 427 428 /* SUB $8,SP */ 429 q1->as = ASUB; 430 q1->from.type = D_CONST; 431 q1->from.offset = 8; 432 q1->from.reg = NREG; 433 q1->reg = NREG; 434 q1->to.type = D_REG; 435 q1->to.reg = REGSP; 436 break; 437 } 438 } 439 } 440 441 static void 442 sigdiv(char *n) 443 { 444 Sym *s; 445 446 s = lookup(n, 0); 447 if(s->type == STEXT){ 448 if(s->sig == 0) 449 s->sig = SIGNINTERN; 450 } 451 else if(s->type == 0 || s->type == SXREF) 452 s->type = SUNDEF; 453 } 454 455 void 456 divsig(void) 457 { 458 sigdiv("_div"); 459 sigdiv("_divu"); 460 sigdiv("_mod"); 461 sigdiv("_modu"); 462 } 463 464 static void 465 sdiv(Sym *s) 466 { 467 if(s->type == 0 || s->type == SXREF){ 468 /* undefsym(s); */ 469 s->type = SXREF; 470 if(s->sig == 0) 471 s->sig = SIGNINTERN; 472 s->subtype = SIMPORT; 473 } 474 else if(s->type != STEXT) 475 diag("undefined: %s", s->name); 476 } 477 478 void 479 initdiv(void) 480 { 481 Sym *s2, *s3, *s4, *s5; 482 Prog *p; 483 484 if(prog_div != P) 485 return; 486 sym_div = s2 = lookup("_div", 0); 487 sym_divu = s3 = lookup("_divu", 0); 488 sym_mod = s4 = lookup("_mod", 0); 489 sym_modu = s5 = lookup("_modu", 0); 490 if(dlm) { 491 sdiv(s2); if(s2->type == SXREF) prog_div = UP; 492 sdiv(s3); if(s3->type == SXREF) prog_divu = UP; 493 sdiv(s4); if(s4->type == SXREF) prog_mod = UP; 494 sdiv(s5); if(s5->type == SXREF) prog_modu = UP; 495 } 496 for(p = firstp; p != P; p = p->link) 497 if(p->as == ATEXT) { 498 if(p->from.sym == s2) 499 prog_div = p; 500 if(p->from.sym == s3) 501 prog_divu = p; 502 if(p->from.sym == s4) 503 prog_mod = p; 504 if(p->from.sym == s5) 505 prog_modu = p; 506 } 507 if(prog_div == P) { 508 diag("undefined: %s", s2->name); 509 prog_div = curtext; 510 } 511 if(prog_divu == P) { 512 diag("undefined: %s", s3->name); 513 prog_divu = curtext; 514 } 515 if(prog_mod == P) { 516 diag("undefined: %s", s4->name); 517 prog_mod = curtext; 518 } 519 if(prog_modu == P) { 520 diag("undefined: %s", s5->name); 521 prog_modu = curtext; 522 } 523 } 524 525 void 526 nocache(Prog *p) 527 { 528 p->optab = 0; 529 p->from.class = 0; 530 p->to.class = 0; 531 } 532