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 static void setdiv(int); 9 10 static Prog * 11 movrr(Prog *q, int rs, int rd, Prog *p) 12 { 13 if(q == nil) 14 q = prg(); 15 q->as = AMOVW; 16 q->line = p->line; 17 q->from.type = D_REG; 18 q->from.reg = rs; 19 q->to.type = D_REG; 20 q->to.reg = rd; 21 q->link = p->link; 22 return q; 23 } 24 25 static Prog * 26 fnret(Prog *q, int rs, int foreign, Prog *p) 27 { 28 q = movrr(q, rs, REGPC, p); 29 if(foreign){ // BX rs 30 q->as = ABXRET; 31 q->from.type = D_NONE; 32 q->from.reg = NREG; 33 q->to.reg = rs; 34 } 35 return q; 36 } 37 38 static Prog * 39 aword(long w, Prog *p) 40 { 41 Prog *q; 42 43 q = prg(); 44 q->as = AWORD; 45 q->line = p->line; 46 q->from.type = D_NONE; 47 q->reg = NREG; 48 q->to.type = D_CONST; 49 q->to.offset = w; 50 q->link = p->link; 51 p->link = q; 52 return q; 53 } 54 55 static Prog * 56 adword(long w1, long w2, Prog *p) 57 { 58 Prog *q; 59 60 q = prg(); 61 q->as = ADWORD; 62 q->line = p->line; 63 q->from.type = D_CONST; 64 q->from.offset = w1; 65 q->reg = NREG; 66 q->to.type = D_CONST; 67 q->to.offset = w2; 68 q->link = p->link; 69 p->link = q; 70 return q; 71 } 72 73 void 74 noops(void) 75 { 76 Prog *p, *q, *q1, *q2; 77 int o, curframe, curbecome, maxbecome, foreign; 78 79 /* 80 * find leaf subroutines 81 * become sizes 82 * frame sizes 83 * strip NOPs 84 * expand RET 85 * expand BECOME pseudo 86 */ 87 88 if(debug['v']) 89 Bprint(&bso, "%5.2f noops\n", cputime()); 90 Bflush(&bso); 91 92 curframe = 0; 93 curbecome = 0; 94 maxbecome = 0; 95 curtext = 0; 96 97 q = P; 98 for(p = firstp; p != P; p = p->link) { 99 setarch(p); 100 101 /* find out how much arg space is used in this TEXT */ 102 if(p->to.type == D_OREG && p->to.reg == REGSP) 103 if(p->to.offset > curframe) 104 curframe = p->to.offset; 105 106 switch(p->as) { 107 case ATEXT: 108 if(curtext && curtext->from.sym) { 109 curtext->from.sym->frame = curframe; 110 curtext->from.sym->become = curbecome; 111 if(curbecome > maxbecome) 112 maxbecome = curbecome; 113 } 114 curframe = 0; 115 curbecome = 0; 116 117 p->mark |= LEAF; 118 curtext = p; 119 break; 120 121 case ARET: 122 /* special form of RET is BECOME */ 123 if(p->from.type == D_CONST) 124 if(p->from.offset > curbecome) 125 curbecome = p->from.offset; 126 break; 127 128 case ADIV: 129 case ADIVU: 130 case AMOD: 131 case AMODU: 132 q = p; 133 if(prog_div == P) 134 initdiv(); 135 if(curtext != P) 136 curtext->mark &= ~LEAF; 137 setdiv(p->as); 138 continue; 139 140 case ANOP: 141 q1 = p->link; 142 q->link = q1; /* q is non-nop */ 143 q1->mark |= p->mark; 144 continue; 145 146 case ABL: 147 case ABX: 148 if(curtext != P) 149 curtext->mark &= ~LEAF; 150 151 case ABCASE: 152 case AB: 153 154 case ABEQ: 155 case ABNE: 156 case ABCS: 157 case ABHS: 158 case ABCC: 159 case ABLO: 160 case ABMI: 161 case ABPL: 162 case ABVS: 163 case ABVC: 164 case ABHI: 165 case ABLS: 166 case ABGE: 167 case ABLT: 168 case ABGT: 169 case ABLE: 170 171 q1 = p->cond; 172 if(q1 != P) { 173 while(q1->as == ANOP) { 174 q1 = q1->link; 175 p->cond = q1; 176 } 177 } 178 break; 179 } 180 q = p; 181 } 182 183 if(curtext && curtext->from.sym) { 184 curtext->from.sym->frame = curframe; 185 curtext->from.sym->become = curbecome; 186 if(curbecome > maxbecome) 187 maxbecome = curbecome; 188 } 189 190 if(debug['b']) 191 print("max become = %d\n", maxbecome); 192 xdefine("ALEFbecome", STEXT, maxbecome); 193 194 curtext = 0; 195 for(p = firstp; p != P; p = p->link) { 196 setarch(p); 197 switch(p->as) { 198 case ATEXT: 199 curtext = p; 200 break; 201 case ABL: 202 // case ABX: 203 if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) { 204 o = maxbecome - curtext->from.sym->frame; 205 if(o <= 0) 206 break; 207 /* calling a become or calling a variable */ 208 if(p->to.sym == S || p->to.sym->become) { 209 curtext->to.offset += o; 210 if(debug['b']) { 211 curp = p; 212 print("%D calling %D increase %d\n", 213 &curtext->from, &p->to, o); 214 } 215 } 216 } 217 break; 218 } 219 } 220 221 for(p = firstp; p != P; p = p->link) { 222 setarch(p); 223 o = p->as; 224 switch(o) { 225 case ATEXT: 226 curtext = p; 227 autosize = p->to.offset + 4; 228 if(autosize <= 4) 229 if(curtext->mark & LEAF) { 230 p->to.offset = -4; 231 autosize = 0; 232 } 233 234 if(!autosize && !(curtext->mark & LEAF)) { 235 if(debug['v']) 236 Bprint(&bso, "save suppressed in: %s\n", 237 curtext->from.sym->name); 238 Bflush(&bso); 239 curtext->mark |= LEAF; 240 } 241 #ifdef CALLEEBX 242 if(p->from.sym->foreign){ 243 if(thumb) 244 // don't allow literal pool to seperate these 245 p = adword(0xe28f7001, 0xe12fff17, p); // arm add 1, pc, r7 and bx r7 246 // p = aword(0xe12fff17, aword(0xe28f7001, p)); // arm add 1, pc, r7 and bx r7 247 else 248 p = aword(0x4778, p); // thumb bx pc and 2 bytes padding 249 } 250 #endif 251 if(curtext->mark & LEAF) { 252 if(curtext->from.sym) 253 curtext->from.sym->type = SLEAF; 254 #ifdef optimise_time 255 if(autosize) { 256 q = prg(); 257 q->as = ASUB; 258 q->line = p->line; 259 q->from.type = D_CONST; 260 q->from.offset = autosize; 261 q->to.type = D_REG; 262 q->to.reg = REGSP; 263 264 q->link = p->link; 265 p->link = q; 266 } 267 break; 268 #else 269 if(!autosize) 270 break; 271 #endif 272 } 273 274 if(thumb){ 275 if(!(curtext->mark & LEAF)){ 276 q = movrr(nil, REGLINK, REGTMPT-1, p); 277 p->link = q; 278 q1 = prg(); 279 q1->as = AMOVW; 280 q1->line = p->line; 281 q1->from.type = D_REG; 282 q1->from.reg = REGTMPT-1; 283 q1->to.type = D_OREG; 284 q1->to.name = D_NONE; 285 q1->to.reg = REGSP; 286 q1->to.offset = 0; 287 q1->link = q->link; 288 q->link = q1; 289 } 290 if(autosize){ 291 q2 = prg(); 292 q2->as = ASUB; 293 q2->line = p->line; 294 q2->from.type = D_CONST; 295 q2->from.offset = autosize; 296 q2->to.type = D_REG; 297 q2->to.reg = REGSP; 298 q2->link = p->link; 299 p->link = q2; 300 } 301 break; 302 } 303 304 q1 = prg(); 305 q1->as = AMOVW; 306 q1->scond |= C_WBIT; 307 q1->line = p->line; 308 q1->from.type = D_REG; 309 q1->from.reg = REGLINK; 310 q1->to.type = D_OREG; 311 q1->to.offset = -autosize; 312 q1->to.reg = REGSP; 313 q1->link = p->link; 314 p->link = q1; 315 break; 316 317 case ARET: 318 nocache(p); 319 foreign = seenthumb && curtext->from.sym != S && (curtext->from.sym->foreign || curtext->from.sym->fnptr); 320 // print("%s %d %d\n", curtext->from.sym->name, curtext->from.sym->foreign, curtext->from.sym->fnptr); 321 if(p->from.type == D_CONST) 322 goto become; 323 if(curtext->mark & LEAF) { 324 if(!autosize) { 325 if(thumb){ 326 p = fnret(p, REGLINK, foreign, p); 327 break; 328 } 329 // if(foreign) print("ABXRET 1 %s\n", curtext->from.sym->name); 330 p->as = foreign ? ABXRET : AB; 331 p->from = zprg.from; 332 p->to.type = D_OREG; 333 p->to.offset = 0; 334 p->to.reg = REGLINK; 335 break; 336 } 337 338 #ifdef optimise_time 339 p->as = AADD; 340 p->from.type = D_CONST; 341 p->from.offset = autosize; 342 p->to.type = D_REG; 343 p->to.reg = REGSP; 344 if(thumb){ 345 p->link = fnret(nil, REGLINK, foreign, p); 346 break; 347 } 348 q = prg(); 349 // if(foreign) print("ABXRET 2 %s\n", curtext->from.sym->name); 350 q->as = foreign ? ABXRET : AB; 351 q->scond = p->scond; 352 q->line = p->line; 353 q->to.type = D_OREG; 354 q->to.offset = 0; 355 q->to.reg = REGLINK; 356 357 q->link = p->link; 358 p->link = q; 359 360 break; 361 #endif 362 } 363 if(thumb){ 364 if(curtext->mark & LEAF){ 365 if(autosize){ 366 p->as = AADD; 367 p->from.type = D_CONST; 368 p->from.offset = autosize; 369 p->to.type = D_REG; 370 p->to.reg = REGSP; 371 q = nil; 372 } 373 else 374 q = p; 375 q = fnret(q, REGLINK, foreign, p); 376 if(q != p) 377 p->link = q; 378 } 379 else{ 380 p->as = AMOVW; 381 p->from.type = D_OREG; 382 p->from.name = D_NONE; 383 p->from.reg = REGSP; 384 p->from.offset = 0; 385 p->to.type = D_REG; 386 p->to.reg = REGTMPT-1; 387 if(autosize){ 388 q = prg(); 389 q->as = AADD; 390 q->from.type = D_CONST; 391 q->from.offset = autosize; 392 q->to.type = D_REG; 393 q->to.reg = REGSP; 394 q->link = p->link; 395 p->link = q; 396 } 397 else 398 q = p; 399 q1 = fnret(nil, REGTMPT-1, foreign, p); 400 q1->link = q->link; 401 q->link = q1; 402 } 403 break; 404 } 405 if(foreign) { 406 // if(foreign) print("ABXRET 3 %s\n", curtext->from.sym->name); 407 #define R 1 408 p->as = AMOVW; 409 p->from.type = D_OREG; 410 p->from.name = D_NONE; 411 p->from.reg = REGSP; 412 p->from.offset = 0; 413 p->to.type = D_REG; 414 p->to.reg = R; 415 q = prg(); 416 q->as = AADD; 417 q->scond = p->scond; 418 q->line = p->line; 419 q->from.type = D_CONST; 420 q->from.offset = autosize; 421 q->to.type = D_REG; 422 q->to.reg = REGSP; 423 q->link = p->link; 424 p->link = q; 425 q1 = prg(); 426 q1->as = ABXRET; 427 q1->scond = p->scond; 428 q1->line = p->line; 429 q1->to.type = D_OREG; 430 q1->to.offset = 0; 431 q1->to.reg = R; 432 q1->link = q->link; 433 q->link = q1; 434 #undef R 435 } 436 else { 437 p->as = AMOVW; 438 p->scond |= C_PBIT; 439 p->from.type = D_OREG; 440 p->from.offset = autosize; 441 p->from.reg = REGSP; 442 p->to.type = D_REG; 443 p->to.reg = REGPC; 444 } 445 break; 446 447 become: 448 if(foreign){ 449 diag("foreign become - help"); 450 break; 451 } 452 if(thumb){ 453 diag("thumb become - help"); 454 break; 455 } 456 print("arm become\n"); 457 if(curtext->mark & LEAF) { 458 459 if(!autosize) { 460 p->as = AB; 461 p->from = zprg.from; 462 break; 463 } 464 465 #ifdef optimise_time 466 q = prg(); 467 q->scond = p->scond; 468 q->line = p->line; 469 q->as = AB; 470 q->from = zprg.from; 471 q->to = p->to; 472 q->cond = p->cond; 473 q->link = p->link; 474 p->link = q; 475 476 p->as = AADD; 477 p->from = zprg.from; 478 p->from.type = D_CONST; 479 p->from.offset = autosize; 480 p->to = zprg.to; 481 p->to.type = D_REG; 482 p->to.reg = REGSP; 483 484 break; 485 #endif 486 } 487 q = prg(); 488 q->scond = p->scond; 489 q->line = p->line; 490 q->as = AB; 491 q->from = zprg.from; 492 q->to = p->to; 493 q->cond = p->cond; 494 q->link = p->link; 495 p->link = q; 496 if(thumb){ 497 q1 = prg(); 498 q1->line = p->line; 499 q1->as = AADD; 500 q1->from.type = D_CONST; 501 q1->from.offset = autosize; 502 q1->to.type = D_REG; 503 q1->to.reg = REGSP; 504 p->as = AMOVW; 505 p->line = p->line; 506 p->from.type = D_OREG; 507 p->from.name = D_NONE; 508 p->from.reg = REGSP; 509 p->from.offset = 0; 510 p->to.type = D_REG; 511 p->to.reg = REGTMPT-1; 512 q1->link = q; 513 p->link = q1; 514 q2 = movrr(nil, REGTMPT-1, REGLINK, p); 515 q2->link = q; 516 q1->link = q2; 517 break; 518 } 519 p->as = AMOVW; 520 p->scond |= C_PBIT; 521 p->from = zprg.from; 522 p->from.type = D_OREG; 523 p->from.offset = autosize; 524 p->from.reg = REGSP; 525 p->to = zprg.to; 526 p->to.type = D_REG; 527 p->to.reg = REGLINK; 528 529 break; 530 531 case ADIV: 532 case ADIVU: 533 case AMOD: 534 case AMODU: 535 if(debug['M']) 536 break; 537 if(p->from.type != D_REG) 538 break; 539 if(p->to.type != D_REG) 540 break; 541 q1 = p; 542 543 /* MOV a,4(SP) */ 544 q = prg(); 545 q->link = p->link; 546 p->link = q; 547 p = q; 548 549 p->as = AMOVW; 550 p->line = q1->line; 551 p->from.type = D_REG; 552 p->from.reg = q1->from.reg; 553 p->to.type = D_OREG; 554 p->to.reg = REGSP; 555 p->to.offset = 4; 556 557 /* MOV b,REGTMP */ 558 q = prg(); 559 q->link = p->link; 560 p->link = q; 561 p = q; 562 563 p->as = AMOVW; 564 p->line = q1->line; 565 p->from.type = D_REG; 566 p->from.reg = q1->reg; 567 if(q1->reg == NREG) 568 p->from.reg = q1->to.reg; 569 p->to.type = D_REG; 570 p->to.reg = prog_div != UP && prog_div->from.sym->thumb ? REGTMPT : REGTMP; 571 p->to.offset = 0; 572 573 /* CALL appropriate */ 574 q = prg(); 575 q->link = p->link; 576 p->link = q; 577 p = q; 578 579 #ifdef CALLEEBX 580 p->as = ABL; 581 #else 582 if(prog_div != UP && prog_div->from.sym->thumb) 583 p->as = thumb ? ABL : ABX; 584 else 585 p->as = thumb ? ABX : ABL; 586 #endif 587 p->line = q1->line; 588 p->to.type = D_BRANCH; 589 p->cond = p; 590 switch(o) { 591 case ADIV: 592 p->cond = prog_div; 593 p->to.sym = sym_div; 594 break; 595 case ADIVU: 596 p->cond = prog_divu; 597 p->to.sym = sym_divu; 598 break; 599 case AMOD: 600 p->cond = prog_mod; 601 p->to.sym = sym_mod; 602 break; 603 case AMODU: 604 p->cond = prog_modu; 605 p->to.sym = sym_modu; 606 break; 607 } 608 609 /* MOV REGTMP, b */ 610 q = prg(); 611 q->link = p->link; 612 p->link = q; 613 p = q; 614 615 p->as = AMOVW; 616 p->line = q1->line; 617 p->from.type = D_REG; 618 p->from.reg = prog_div != UP && prog_div->from.sym->thumb ? REGTMPT : REGTMP; 619 p->from.offset = 0; 620 p->to.type = D_REG; 621 p->to.reg = q1->to.reg; 622 623 /* ADD $8,SP */ 624 q = prg(); 625 q->link = p->link; 626 p->link = q; 627 p = q; 628 629 p->as = AADD; 630 p->from.type = D_CONST; 631 p->from.reg = NREG; 632 p->from.offset = 8; 633 p->reg = NREG; 634 p->to.type = D_REG; 635 p->to.reg = REGSP; 636 637 /* SUB $8,SP */ 638 q1->as = ASUB; 639 q1->from.type = D_CONST; 640 q1->from.offset = 8; 641 q1->from.reg = NREG; 642 q1->reg = NREG; 643 q1->to.type = D_REG; 644 q1->to.reg = REGSP; 645 646 break; 647 case AMOVW: 648 if(thumb){ 649 Adr *a = &p->from; 650 651 if(a->type == D_CONST && ((a->name == D_NONE && a->reg == REGSP) || a->name == D_AUTO || a->name == D_PARAM) && (a->offset & 3)) 652 diag("SP offset not multiple of 4"); 653 } 654 break; 655 case AMOVB: 656 case AMOVBU: 657 case AMOVH: 658 case AMOVHU: 659 if(thumb){ 660 if(p->from.type == D_OREG && (p->from.name == D_AUTO || p->from.name == D_PARAM || (p->from.name == D_CONST && p->from.reg == REGSP))){ 661 q = prg(); 662 *q = *p; 663 if(p->from.name == D_AUTO) 664 q->from.offset += autosize; 665 else if(p->from.name == D_PARAM) 666 q->from.offset += autosize+4; 667 q->from.name = D_NONE; 668 q->from.reg = REGTMPT; 669 p = movrr(p, REGSP, REGTMPT, p); 670 q->link = p->link; 671 p->link = q; 672 } 673 if(p->to.type == D_OREG && (p->to.name == D_AUTO || p->to.name == D_PARAM || (p->to.name == D_CONST && p->to.reg == REGSP))){ 674 q = prg(); 675 *q = *p; 676 if(p->to.name == D_AUTO) 677 q->to.offset += autosize; 678 else if(p->to.name == D_PARAM) 679 q->to.offset += autosize+4; 680 q->to.name = D_NONE; 681 q->to.reg = REGTMPT; 682 p = movrr(p, REGSP, REGTMPT, p); 683 q->link = p->link; 684 p->link = q; 685 if(q->to.offset < 0 || q->to.offset > 255){ // complicated 686 p->to.reg = REGTMPT+1; // mov sp, r8 687 q1 = prg(); 688 q1->line = p->line; 689 q1->as = AMOVW; 690 q1->from.type = D_CONST; 691 q1->from.offset = q->to.offset; 692 q1->to.type = D_REG; 693 q1->to.reg = REGTMPT; // mov $o, r7 694 p->link = q1; 695 q1->link = q; 696 q1 = prg(); 697 q1->line = p->line; 698 q1->as = AADD; 699 q1->from.type = D_REG; 700 q1->from.reg = REGTMPT+1; 701 q1->to.type = D_REG; 702 q1->to.reg = REGTMPT; // add r8, r7 703 p->link->link = q1; 704 q1->link = q; 705 q->to.offset = 0; // mov* r, 0(r7) 706 /* phew */ 707 } 708 } 709 } 710 break; 711 case AMOVM: 712 if(thumb){ 713 if(p->from.type == D_OREG){ 714 if(p->from.offset == 0) 715 p->from.type = D_REG; 716 else 717 diag("non-zero AMOVM offset"); 718 } 719 else if(p->to.type == D_OREG){ 720 if(p->to.offset == 0) 721 p->to.type = D_REG; 722 else 723 diag("non-zero AMOVM offset"); 724 } 725 } 726 break; 727 case AB: 728 if(thumb && p->to.type == D_OREG){ 729 if(p->to.offset == 0){ 730 p->as = AMOVW; 731 p->from.type = D_REG; 732 p->from.reg = p->to.reg; 733 p->to.type = D_REG; 734 p->to.reg = REGPC; 735 } 736 else{ 737 p->as = AADD; 738 p->from.type = D_CONST; 739 p->from.offset = p->to.offset; 740 p->reg = p->to.reg; 741 p->to.type = D_REG; 742 p->to.reg = REGTMPT-1; 743 q = prg(); 744 q->as = AMOVW; 745 q->line = p->line; 746 q->from.type = D_REG; 747 q->from.reg = REGTMPT-1; 748 q->to.type = D_REG; 749 q->to.reg = REGPC; 750 q->link = p->link; 751 p->link = q; 752 } 753 } 754 if(seenthumb && !thumb && p->to.type == D_OREG && p->to.reg == REGLINK){ 755 // print("warn %s: b (R%d) assuming a return\n", curtext->from.sym->name, p->to.reg); 756 p->as = ABXRET; 757 } 758 break; 759 case ABL: 760 case ABX: 761 if(thumb && p->to.type == D_OREG){ 762 if(p->to.offset == 0){ 763 p->as = o; 764 p->from.type = D_NONE; 765 p->to.type = D_REG; 766 } 767 else{ 768 p->as = AADD; 769 p->from.type = D_CONST; 770 p->from.offset = p->to.offset; 771 p->reg = p->to.reg; 772 p->to.type = D_REG; 773 p->to.reg = REGTMPT-1; 774 q = prg(); 775 q->as = o; 776 q->line = p->line; 777 q->from.type = D_NONE; 778 q->to.type = D_REG; 779 q->to.reg = REGTMPT-1; 780 q->link = p->link; 781 p->link = q; 782 } 783 } 784 break; 785 } 786 } 787 } 788 789 static void 790 sigdiv(char *n) 791 { 792 Sym *s; 793 794 s = lookup(n, 0); 795 if(s->type == STEXT){ 796 if(s->sig == 0) 797 s->sig = SIGNINTERN; 798 } 799 else if(s->type == 0 || s->type == SXREF) 800 s->type = SUNDEF; 801 } 802 803 void 804 divsig(void) 805 { 806 sigdiv("_div"); 807 sigdiv("_divu"); 808 sigdiv("_mod"); 809 sigdiv("_modu"); 810 } 811 812 static void 813 sdiv(Sym *s) 814 { 815 if(s->type == 0 || s->type == SXREF){ 816 /* undefsym(s); */ 817 s->type = SXREF; 818 if(s->sig == 0) 819 s->sig = SIGNINTERN; 820 s->subtype = SIMPORT; 821 } 822 else if(s->type != STEXT) 823 diag("undefined: %s", s->name); 824 } 825 826 void 827 initdiv(void) 828 { 829 Sym *s2, *s3, *s4, *s5; 830 Prog *p; 831 832 if(prog_div != P) 833 return; 834 sym_div = s2 = lookup("_div", 0); 835 sym_divu = s3 = lookup("_divu", 0); 836 sym_mod = s4 = lookup("_mod", 0); 837 sym_modu = s5 = lookup("_modu", 0); 838 if(dlm) { 839 sdiv(s2); if(s2->type == SXREF) prog_div = UP; 840 sdiv(s3); if(s3->type == SXREF) prog_divu = UP; 841 sdiv(s4); if(s4->type == SXREF) prog_mod = UP; 842 sdiv(s5); if(s5->type == SXREF) prog_modu = UP; 843 } 844 for(p = firstp; p != P; p = p->link) 845 if(p->as == ATEXT) { 846 if(p->from.sym == s2) 847 prog_div = p; 848 if(p->from.sym == s3) 849 prog_divu = p; 850 if(p->from.sym == s4) 851 prog_mod = p; 852 if(p->from.sym == s5) 853 prog_modu = p; 854 } 855 if(prog_div == P) { 856 diag("undefined: %s", s2->name); 857 prog_div = curtext; 858 } 859 if(prog_divu == P) { 860 diag("undefined: %s", s3->name); 861 prog_divu = curtext; 862 } 863 if(prog_mod == P) { 864 diag("undefined: %s", s4->name); 865 prog_mod = curtext; 866 } 867 if(prog_modu == P) { 868 diag("undefined: %s", s5->name); 869 prog_modu = curtext; 870 } 871 } 872 873 static void 874 setdiv(int as) 875 { 876 Prog *p = nil; 877 878 switch(as){ 879 case ADIV: p = prog_div; break; 880 case ADIVU: p = prog_divu; break; 881 case AMOD: p = prog_mod; break; 882 case AMODU: p = prog_modu; break; 883 } 884 if(p != UP && thumb != p->from.sym->thumb) 885 p->from.sym->foreign = 1; 886 } 887 888 void 889 nocache(Prog *p) 890 { 891 p->optab = 0; 892 p->from.class = 0; 893 p->to.class = 0; 894 } 895