1 #include "l.h" 2 3 void 4 noops(void) 5 { 6 Prog *p, *p1, *q, *q1; 7 int o, 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 27 q = P; 28 for(p = firstp; p != P; p = p->link) { 29 30 /* find out how much arg space is used in this TEXT */ 31 if(p->to.type == D_OREG && p->to.reg == REGSP) 32 if(p->to.offset > curframe) 33 curframe = p->to.offset; 34 35 switch(p->as) { 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 p->mark |= LABEL|LEAF|SYNC; 47 if(p->link) 48 p->link->mark |= LABEL; 49 curtext = p; 50 break; 51 52 /* too hard, just leave alone */ 53 case AMOVW: 54 if(p->to.type == D_FCREG || 55 p->to.type == D_MREG) { 56 p->mark |= LABEL|SYNC; 57 break; 58 } 59 if(p->from.type == D_FCREG || 60 p->from.type == D_MREG) { 61 p->mark |= LABEL|SYNC; 62 addnop(p); 63 addnop(p); 64 nop.mfrom.count += 2; 65 nop.mfrom.outof += 2; 66 break; 67 } 68 break; 69 70 /* too hard, just leave alone */ 71 case ASYSCALL: 72 case AWORD: 73 case ATLBWR: 74 case ATLBWI: 75 case ATLBP: 76 case ATLBR: 77 p->mark |= LABEL|SYNC; 78 break; 79 80 case ANOR: 81 if(p->to.type == D_REG && p->to.reg == REGZERO) 82 p->mark |= LABEL|SYNC; 83 break; 84 85 case ARET: 86 /* special form of RET is BECOME */ 87 if(p->from.type == D_CONST) 88 if(p->from.offset > curbecome) 89 curbecome = p->from.offset; 90 91 if(p->link != P) 92 p->link->mark |= LABEL; 93 break; 94 95 case ANOP: 96 q1 = p->link; 97 q->link = q1; /* q is non-nop */ 98 q1->mark |= p->mark; 99 continue; 100 101 case ABGEZAL: 102 case ABLTZAL: 103 case AJAL: 104 if(curtext != P) 105 curtext->mark &= ~LEAF; 106 107 case AJMP: 108 case ABEQ: 109 case ABGEZ: 110 case ABGTZ: 111 case ABLEZ: 112 case ABLTZ: 113 case ABNE: 114 case ABFPT: 115 case ABFPF: 116 p->mark |= BRANCH; 117 q1 = p->cond; 118 if(q1 != P) { 119 while(q1->as == ANOP) { 120 q1 = q1->link; 121 p->cond = q1; 122 } 123 if(!(q1->mark & LEAF)) 124 q1->mark |= LABEL; 125 } else 126 p->mark |= LABEL; 127 q1 = p->link; 128 if(q1 != P) 129 q1->mark |= LABEL; 130 break; 131 } 132 q = p; 133 } 134 135 if(curtext && curtext->from.sym) { 136 curtext->from.sym->frame = curframe; 137 curtext->from.sym->become = curbecome; 138 if(curbecome > maxbecome) 139 maxbecome = curbecome; 140 } 141 142 if(debug['b']) 143 print("max become = %d\n", maxbecome); 144 xdefine("ALEFbecome", STEXT, maxbecome); 145 146 curtext = 0; 147 for(p = firstp; p != P; p = p->link) { 148 switch(p->as) { 149 case ATEXT: 150 curtext = p; 151 break; 152 case AJAL: 153 if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) { 154 o = maxbecome - curtext->from.sym->frame; 155 if(o <= 0) 156 break; 157 /* calling a become or calling a variable */ 158 if(p->to.sym == S || p->to.sym->become) { 159 curtext->to.offset += o; 160 if(debug['b']) { 161 curp = p; 162 print("%D calling %D increase %d\n", 163 &curtext->from, &p->to, o); 164 } 165 } 166 } 167 break; 168 } 169 } 170 171 for(p = firstp; p != P; p = p->link) { 172 o = p->as; 173 switch(o) { 174 case ATEXT: 175 curtext = p; 176 autosize = p->to.offset + 4; 177 if(autosize <= 4) 178 if(curtext->mark & LEAF) { 179 p->to.offset = -4; 180 autosize = 0; 181 } 182 183 q = p; 184 if(autosize) { 185 q = prg(); 186 q->as = AADD; 187 q->line = p->line; 188 q->from.type = D_CONST; 189 q->from.offset = -autosize; 190 q->to.type = D_REG; 191 q->to.reg = REGSP; 192 193 q->link = p->link; 194 p->link = q; 195 } else 196 if(!(curtext->mark & LEAF)) { 197 if(debug['v']) 198 Bprint(&bso, "save suppressed in: %s\n", 199 curtext->from.sym->name); 200 Bflush(&bso); 201 curtext->mark |= LEAF; 202 } 203 204 if(curtext->mark & LEAF) { 205 if(curtext->from.sym) 206 curtext->from.sym->type = SLEAF; 207 break; 208 } 209 210 q1 = prg(); 211 q1->as = AMOVW; 212 q1->line = p->line; 213 q1->from.type = D_REG; 214 q1->from.reg = REGLINK; 215 q1->to.type = D_OREG; 216 q1->from.offset = 0; 217 q1->to.reg = REGSP; 218 219 q1->link = q->link; 220 q->link = q1; 221 break; 222 223 case ARET: 224 nocache(p); 225 if(p->from.type == D_CONST) 226 goto become; 227 if(curtext->mark & LEAF) { 228 if(!autosize) { 229 p->as = AJMP; 230 p->from = zprg.from; 231 p->to.type = D_OREG; 232 p->to.offset = 0; 233 p->to.reg = REGLINK; 234 p->mark |= BRANCH; 235 break; 236 } 237 238 p->as = AADD; 239 p->from.type = D_CONST; 240 p->from.offset = autosize; 241 p->to.type = D_REG; 242 p->to.reg = REGSP; 243 244 q = prg(); 245 q->as = AJMP; 246 q->line = p->line; 247 q->to.type = D_OREG; 248 q->to.offset = 0; 249 q->to.reg = REGLINK; 250 q->mark |= BRANCH; 251 252 q->link = p->link; 253 p->link = q; 254 break; 255 } 256 p->as = AMOVW; 257 p->from.type = D_OREG; 258 p->from.offset = 0; 259 p->from.reg = REGSP; 260 p->to.type = D_REG; 261 p->to.reg = 2; 262 263 q = p; 264 if(autosize) { 265 q = prg(); 266 q->as = AADD; 267 q->line = p->line; 268 q->from.type = D_CONST; 269 q->from.offset = autosize; 270 q->to.type = D_REG; 271 q->to.reg = REGSP; 272 273 q->link = p->link; 274 p->link = q; 275 } 276 277 q1 = prg(); 278 q1->as = AJMP; 279 q1->line = p->line; 280 q1->to.type = D_OREG; 281 q1->to.offset = 0; 282 q1->to.reg = 2; 283 q1->mark |= BRANCH; 284 285 q1->link = q->link; 286 q->link = q1; 287 break; 288 289 become: 290 if(curtext->mark & LEAF) { 291 292 q = prg(); 293 q->line = p->line; 294 q->as = AJMP; 295 q->from = zprg.from; 296 q->to = p->to; 297 q->cond = p->cond; 298 q->link = p->link; 299 q->mark |= BRANCH; 300 p->link = q; 301 302 p->as = AADD; 303 p->from = zprg.from; 304 p->from.type = D_CONST; 305 p->from.offset = autosize; 306 p->to = zprg.to; 307 p->to.type = D_REG; 308 p->to.reg = REGSP; 309 310 break; 311 } 312 q = prg(); 313 q->line = p->line; 314 q->as = AJMP; 315 q->from = zprg.from; 316 q->to = p->to; 317 q->cond = p->cond; 318 q->link = p->link; 319 q->mark |= BRANCH; 320 p->link = q; 321 322 q = prg(); 323 q->line = p->line; 324 q->as = AADD; 325 q->from.type = D_CONST; 326 q->from.offset = autosize; 327 q->to.type = D_REG; 328 q->to.reg = REGSP; 329 q->link = p->link; 330 p->link = q; 331 332 p->as = AMOVW; 333 p->from = zprg.from; 334 p->from.type = D_OREG; 335 p->from.offset = 0; 336 p->from.reg = REGSP; 337 p->to = zprg.to; 338 p->to.type = D_REG; 339 p->to.reg = REGLINK; 340 341 break; 342 } 343 } 344 345 curtext = P; 346 q = P; /* p - 1 */ 347 q1 = firstp; /* top of block */ 348 o = 0; /* count of instructions */ 349 for(p = firstp; p != P; p = p1) { 350 p1 = p->link; 351 o++; 352 if(p->mark & NOSCHED){ 353 if(q1 != p){ 354 sched(q1, q); 355 } 356 for(; p != P; p = p->link){ 357 if(!(p->mark & NOSCHED)) 358 break; 359 q = p; 360 } 361 p1 = p; 362 q1 = p; 363 o = 0; 364 continue; 365 } 366 if(p->mark & (LABEL|SYNC)) { 367 if(q1 != p) 368 sched(q1, q); 369 q1 = p; 370 o = 1; 371 } 372 if(p->mark & (BRANCH|SYNC)) { 373 sched(q1, p); 374 q1 = p1; 375 o = 0; 376 } 377 if(o >= NSCHED) { 378 sched(q1, p); 379 q1 = p1; 380 o = 0; 381 } 382 q = p; 383 } 384 } 385 386 void 387 addnop(Prog *p) 388 { 389 Prog *q; 390 391 q = prg(); 392 q->as = ANOR; 393 q->line = p->line; 394 q->from.type = D_REG; 395 q->from.reg = REGZERO; 396 q->to.type = D_REG; 397 q->to.reg = REGZERO; 398 399 q->link = p->link; 400 p->link = q; 401 } 402 403 void 404 nocache(Prog *p) 405 { 406 p->optab = 0; 407 p->from.class = 0; 408 p->to.class = 0; 409 } 410