1 #include "l.h" 2 3 void 4 noops(void) 5 { 6 Prog *p, *p1, *q, *q1; 7 int o, mov, aoffset, curframe, curbecome, maxbecome; 8 9 /* 10 * find leaf subroutines 11 * become sizes 12 * frame sizes 13 * strip NOPs 14 * expand RET 15 * expand BECOME pseudo 16 */ 17 18 if(debug['v']) 19 Bprint(&bso, "%5.2f noops\n", cputime()); 20 Bflush(&bso); 21 22 curframe = 0; 23 curbecome = 0; 24 maxbecome = 0; 25 curtext = 0; 26 q = P; 27 for(p = firstp; p != P; p = p->link) { 28 29 /* find out how much arg space is used in this TEXT */ 30 if(p->to.type == D_OREG && p->to.reg == REGSP) 31 if(p->to.offset > curframe) 32 curframe = p->to.offset; 33 34 switch(p->as) { 35 /* too hard, just leave alone */ 36 case ATEXT: 37 if(curtext && curtext->from.sym) { 38 curtext->from.sym->frame = curframe; 39 curtext->from.sym->become = curbecome; 40 if(curbecome > maxbecome) 41 maxbecome = curbecome; 42 } 43 curframe = 0; 44 curbecome = 0; 45 46 q = p; 47 p->mark |= LABEL|LEAF|SYNC; 48 if(p->link) 49 p->link->mark |= LABEL; 50 curtext = p; 51 break; 52 53 case ANOR: 54 q = p; 55 if(p->to.type == D_REG) 56 if(p->to.reg == REGZERO) 57 p->mark |= LABEL|SYNC; 58 break; 59 60 case ALWAR: 61 case ASTWCCC: 62 case AECIWX: 63 case AECOWX: 64 case AEIEIO: 65 case AICBI: 66 case AISYNC: 67 case ATLBIE: 68 case ADCBF: 69 case ADCBI: 70 case ADCBST: 71 case ADCBT: 72 case ADCBTST: 73 case ADCBZ: 74 case ASYNC: 75 case ATW: 76 case AWORD: 77 case ARFI: 78 case ARFCI: 79 q = p; 80 p->mark |= LABEL|SYNC; 81 continue; 82 83 case AMOVW: 84 q = p; 85 switch(p->from.type) { 86 case D_MSR: 87 case D_SREG: 88 case D_SPR: 89 case D_FPSCR: 90 case D_CREG: 91 case D_DCR: 92 p->mark |= LABEL|SYNC; 93 } 94 switch(p->to.type) { 95 case D_MSR: 96 case D_SREG: 97 case D_SPR: 98 case D_FPSCR: 99 case D_CREG: 100 case D_DCR: 101 p->mark |= LABEL|SYNC; 102 } 103 continue; 104 105 case AFABS: 106 case AFABSCC: 107 case AFADD: 108 case AFADDCC: 109 case AFCTIW: 110 case AFCTIWCC: 111 case AFCTIWZ: 112 case AFCTIWZCC: 113 case AFDIV: 114 case AFDIVCC: 115 case AFMADD: 116 case AFMADDCC: 117 case AFMOVD: 118 case AFMOVDU: 119 /* case AFMOVDS: */ 120 case AFMOVS: 121 case AFMOVSU: 122 /* case AFMOVSD: */ 123 case AFMSUB: 124 case AFMSUBCC: 125 case AFMUL: 126 case AFMULCC: 127 case AFNABS: 128 case AFNABSCC: 129 case AFNEG: 130 case AFNEGCC: 131 case AFNMADD: 132 case AFNMADDCC: 133 case AFNMSUB: 134 case AFNMSUBCC: 135 case AFRSP: 136 case AFRSPCC: 137 case AFSUB: 138 case AFSUBCC: 139 q = p; 140 p->mark |= FLOAT; 141 continue; 142 143 case ABL: 144 case ABCL: 145 if(curtext != P) 146 curtext->mark &= ~LEAF; 147 148 case ABC: 149 case ABEQ: 150 case ABGE: 151 case ABGT: 152 case ABLE: 153 case ABLT: 154 case ABNE: 155 case ABR: 156 case ABVC: 157 case ABVS: 158 159 p->mark |= BRANCH; 160 q = p; 161 q1 = p->cond; 162 if(q1 != P) { 163 while(q1->as == ANOP) { 164 q1 = q1->link; 165 p->cond = q1; 166 } 167 if(!(q1->mark & LEAF)) 168 q1->mark |= LABEL; 169 } else 170 p->mark |= LABEL; 171 q1 = p->link; 172 if(q1 != P) 173 q1->mark |= LABEL; 174 continue; 175 176 case AFCMPO: 177 case AFCMPU: 178 q = p; 179 p->mark |= FCMP|FLOAT; 180 continue; 181 182 case ARETURN: 183 /* special form of RETURN is BECOME */ 184 if(p->from.type == D_CONST) 185 if(p->from.offset > curbecome) 186 curbecome = p->from.offset; 187 188 q = p; 189 if(p->link != P) 190 p->link->mark |= LABEL; 191 continue; 192 193 case ANOP: 194 q1 = p->link; 195 q->link = q1; /* q is non-nop */ 196 q1->mark |= p->mark; 197 continue; 198 199 default: 200 q = p; 201 continue; 202 } 203 } 204 if(curtext && curtext->from.sym) { 205 curtext->from.sym->frame = curframe; 206 curtext->from.sym->become = curbecome; 207 if(curbecome > maxbecome) 208 maxbecome = curbecome; 209 } 210 211 if(debug['b']) 212 print("max become = %d\n", maxbecome); 213 xdefine("ALEFbecome", STEXT, maxbecome); 214 215 curtext = 0; 216 for(p = firstp; p != P; p = p->link) { 217 switch(p->as) { 218 case ATEXT: 219 curtext = p; 220 break; 221 222 case ABL: /* ABCL? */ 223 if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) { 224 o = maxbecome - curtext->from.sym->frame; 225 if(o <= 0) 226 break; 227 /* calling a become or calling a variable */ 228 if(p->to.sym == S || p->to.sym->become) { 229 curtext->to.offset += o; 230 if(debug['b']) { 231 curp = p; 232 print("%D calling %D increase %d\n", 233 &curtext->from, &p->to, o); 234 } 235 } 236 } 237 break; 238 } 239 } 240 241 curtext = P; 242 for(p = firstp; p != P; p = p->link) { 243 o = p->as; 244 switch(o) { 245 case ATEXT: 246 mov = AMOVW; 247 aoffset = 0; 248 curtext = p; 249 autosize = p->to.offset + 4; 250 if((p->mark & LEAF) && autosize <= 4) 251 autosize = 0; 252 else 253 if(autosize & 4) 254 autosize += 4; 255 p->to.offset = autosize - 4; 256 257 q = p; 258 if(autosize) { 259 /* use MOVWU to adjust R1 when saving R31, if autosize is small */ 260 if(!(curtext->mark & LEAF) && autosize >= -BIG && autosize <= BIG) { 261 mov = AMOVWU; 262 aoffset = -autosize; 263 } else { 264 q = prg(); 265 q->as = AADD; 266 q->line = p->line; 267 q->from.type = D_CONST; 268 q->from.offset = -autosize; 269 q->to.type = D_REG; 270 q->to.reg = REGSP; 271 272 q->link = p->link; 273 p->link = q; 274 } 275 } else 276 if(!(curtext->mark & LEAF)) { 277 if(debug['v']) 278 Bprint(&bso, "save suppressed in: %s\n", 279 curtext->from.sym->name); 280 curtext->mark |= LEAF; 281 } 282 283 if(curtext->mark & LEAF) { 284 if(curtext->from.sym) 285 curtext->from.sym->type = SLEAF; 286 break; 287 } 288 289 q1 = prg(); 290 q1->as = mov; 291 q1->line = p->line; 292 q1->from.type = D_REG; 293 q1->from.reg = REGTMP; 294 q1->to.type = D_OREG; 295 q1->to.offset = aoffset; 296 q1->to.reg = REGSP; 297 298 q1->link = q->link; 299 q->link = q1; 300 301 q1 = prg(); 302 q1->as = AMOVW; 303 q1->line = p->line; 304 q1->from.type = D_SPR; 305 q1->from.offset = D_LR; 306 q1->to.type = D_REG; 307 q1->to.reg = REGTMP; 308 309 q1->link = q->link; 310 q->link = q1; 311 break; 312 313 case ARETURN: 314 if(p->from.type == D_CONST) 315 goto become; 316 if(curtext->mark & LEAF) { 317 if(!autosize) { 318 p->as = ABR; 319 p->from = zprg.from; 320 p->to.type = D_SPR; 321 p->to.offset = D_LR; 322 p->mark |= BRANCH; 323 break; 324 } 325 326 p->as = AADD; 327 p->from.type = D_CONST; 328 p->from.offset = autosize; 329 p->to.type = D_REG; 330 p->to.reg = REGSP; 331 332 q = prg(); 333 q->as = ABR; 334 q->line = p->line; 335 q->to.type = D_SPR; 336 q->to.offset = D_LR; 337 q->mark |= BRANCH; 338 339 q->link = p->link; 340 p->link = q; 341 break; 342 } 343 344 p->as = AMOVW; 345 p->from.type = D_OREG; 346 p->from.offset = 0; 347 p->from.reg = REGSP; 348 p->to.type = D_REG; 349 p->to.reg = REGTMP; 350 351 q = prg(); 352 q->as = AMOVW; 353 q->line = p->line; 354 q->from.type = D_REG; 355 q->from.reg = REGTMP; 356 q->to.type = D_SPR; 357 q->to.offset = D_LR; 358 359 q->link = p->link; 360 p->link = q; 361 p = q; 362 363 if(autosize) { 364 q = prg(); 365 q->as = AADD; 366 q->line = p->line; 367 q->from.type = D_CONST; 368 q->from.offset = autosize; 369 q->to.type = D_REG; 370 q->to.reg = REGSP; 371 372 q->link = p->link; 373 p->link = q; 374 } 375 376 q1 = prg(); 377 q1->as = ABR; 378 q1->line = p->line; 379 q1->to.type = D_SPR; 380 q1->to.offset = D_LR; 381 q1->mark |= BRANCH; 382 383 q1->link = q->link; 384 q->link = q1; 385 break; 386 387 become: 388 if(curtext->mark & LEAF) { 389 390 q = prg(); 391 q->line = p->line; 392 q->as = ABR; 393 q->from = zprg.from; 394 q->to = p->to; 395 q->cond = p->cond; 396 q->link = p->link; 397 q->mark |= BRANCH; 398 p->link = q; 399 400 p->as = AADD; 401 p->from = zprg.from; 402 p->from.type = D_CONST; 403 p->from.offset = autosize; 404 p->to = zprg.to; 405 p->to.type = D_REG; 406 p->to.reg = REGSP; 407 408 break; 409 } 410 q = prg(); 411 q->line = p->line; 412 q->as = ABR; 413 q->from = zprg.from; 414 q->to = p->to; 415 q->cond = p->cond; 416 q->mark |= BRANCH; 417 q->link = p->link; 418 p->link = q; 419 420 q = prg(); 421 q->line = p->line; 422 q->as = AADD; 423 q->from.type = D_CONST; 424 q->from.offset = autosize; 425 q->to.type = D_REG; 426 q->to.reg = REGSP; 427 q->link = p->link; 428 p->link = q; 429 430 q = prg(); 431 q->line = p->line; 432 q->as = AMOVW; 433 q->line = p->line; 434 q->from.type = D_REG; 435 q->from.reg = REGTMP; 436 q->to.type = D_SPR; 437 q->to.offset = D_LR; 438 q->link = p->link; 439 p->link = q; 440 441 p->as = AMOVW; 442 p->from = zprg.from; 443 p->from.type = D_OREG; 444 p->from.offset = 0; 445 p->from.reg = REGSP; 446 p->to = zprg.to; 447 p->to.type = D_REG; 448 p->to.reg = REGTMP; 449 450 break; 451 } 452 } 453 454 if(debug['Q'] == 0) 455 return; 456 457 curtext = P; 458 q = P; /* p - 1 */ 459 q1 = firstp; /* top of block */ 460 o = 0; /* count of instructions */ 461 for(p = firstp; p != P; p = p1) { 462 p1 = p->link; 463 o++; 464 if(p->mark & NOSCHED){ 465 if(q1 != p){ 466 sched(q1, q); 467 } 468 for(; p != P; p = p->link){ 469 if(!(p->mark & NOSCHED)) 470 break; 471 q = p; 472 } 473 p1 = p; 474 q1 = p; 475 o = 0; 476 continue; 477 } 478 if(p->mark & (LABEL|SYNC)) { 479 if(q1 != p) 480 sched(q1, q); 481 q1 = p; 482 o = 1; 483 } 484 if(p->mark & (BRANCH|SYNC)) { 485 sched(q1, p); 486 q1 = p1; 487 o = 0; 488 } 489 if(o >= NSCHED) { 490 sched(q1, p); 491 q1 = p1; 492 o = 0; 493 } 494 q = p; 495 } 496 } 497 498 void 499 addnop(Prog *p) 500 { 501 Prog *q; 502 503 q = prg(); 504 q->as = AOR; 505 q->line = p->line; 506 q->from.type = D_REG; 507 q->from.reg = REGZERO; 508 q->to.type = D_REG; 509 q->to.reg = REGZERO; 510 511 q->link = p->link; 512 p->link = q; 513 } 514