|
|
1.1 ! root 1: /* ! 2: * Peephole optimizer. Look through the ! 3: * code graph, tracking the state of the machine ! 4: * and deleting and/or simplifing instructions that ! 5: * have no change on the machine state. This code ! 6: * is machine independent in spirit, but is in fact ! 7: * only for the Intel 8086. ! 8: */ ! 9: #ifdef vax ! 10: #include "INC$LIB:cc2.h" ! 11: #else ! 12: #include "cc2.h" ! 13: #endif ! 14: ! 15: /* ! 16: * Machine registers. These codes are the ! 17: * same as the ones used by the processor in the ! 18: * REGM field of an instruction. This makes it easier ! 19: * to get the register code from an AFIELD. Unless ! 20: * Intel changes the chip, do not change the values ! 21: * here. ! 22: */ ! 23: #define MAX 0 ! 24: #define MCX 1 ! 25: #define MDX 2 ! 26: #define MBX 3 ! 27: #define MSP 4 ! 28: #define MBP 5 ! 29: #define MSI 6 ! 30: #define MDI 7 ! 31: ! 32: #define MES 0 ! 33: #define MCS 1 ! 34: #define MSS 2 ! 35: #define MDS 3 ! 36: ! 37: #define NMREG 8 ! 38: #define NSREG 4 ! 39: ! 40: /* ! 41: * Register state tables. Just an AFIELD ! 42: * structure for each kind of register (machine or ! 43: * segment). An "a_mode" of "A_NONE" means the ! 44: * register is empty or contains unknown information. ! 45: * Indexed by machine register code. ! 46: */ ! 47: AFIELD mregstate[NMREG]; ! 48: AFIELD sregstate[NSREG]; ! 49: ! 50: AFIELD *afresolve(); ! 51: ! 52: AFIELD afdsfakeing = { A_SR|MDS, NULL, 0 }; ! 53: AFIELD afesfakeing = { A_SR|MES, NULL, 0 }; ! 54: ! 55: /* ! 56: * Mainline of the peephole pass. ! 57: * Mark all of the world as unknown. Sweep the ! 58: * code graph, watching out for labels and machine ! 59: * code. Any label makes the entire machine state an ! 60: * unknown (with some flow analysis, this would not really ! 61: * be necessary). ! 62: */ ! 63: peephole() ! 64: { ! 65: register INS *ip; ! 66: register int rel; ! 67: ! 68: emptyall(); ! 69: for (ip=ins.i_fp; ip!=&ins; ip=ip->i_fp) { ! 70: if (ip->i_type == LLABEL) ! 71: emptyall(); ! 72: else if (ip->i_type == JUMP) { ! 73: rel = ip->i_rel; ! 74: if (rel==ZLOOP || rel==ZLOOPE || rel==ZLOOPNE) ! 75: emptymreg(&mregstate[MCX]); ! 76: } else if (ip->i_type == CODE) { ! 77: if (noeffect(ip)) { ! 78: ip = deleteins(ip, ip->i_fp); ! 79: ++nuseless; ! 80: ++changes; ! 81: } else { ! 82: simplify(ip); ! 83: track(ip); ! 84: } ! 85: } ! 86: } ! 87: } ! 88: ! 89: /* ! 90: * Mark all of the registers in the ! 91: * processor state as empty. Used whenever the ! 92: * state of the machine is, or will become, ! 93: * completely undefined. ! 94: */ ! 95: emptyall() ! 96: { ! 97: register AFIELD *sp; ! 98: ! 99: sp = &mregstate[0]; ! 100: while (sp < &mregstate[NMREG]) { ! 101: emptymreg(sp); ! 102: ++sp; ! 103: } ! 104: sp = &sregstate[0]; ! 105: while (sp < &sregstate[NSREG]) { ! 106: emptysreg(sp); ! 107: ++sp; ! 108: } ! 109: } ! 110: ! 111: /* ! 112: * Flag machine register "r" as empty ! 113: * (contains unknown data) in the processor state. ! 114: * If "r" is an indexing base (BX, SI, DI) then any ! 115: * processor state entries based off these registers ! 116: * must also be set empty. Note that there is a ! 117: * register number change between bx and [bx], so a ! 118: * bit of funnyness is required. ! 119: */ ! 120: emptymreg(rsp) ! 121: register AFIELD *rsp; ! 122: { ! 123: register AFIELD *sp; ! 124: register short xmode; ! 125: ! 126: rsp->a_mode = A_NONE; ! 127: if (rsp == &mregstate[MBX] ! 128: || rsp == &mregstate[MSI] ! 129: || rsp == &mregstate[MDI]) { ! 130: if (rsp == &mregstate[MBX]) ! 131: xmode = A_XBX; ! 132: else if (rsp == &mregstate[MSI]) ! 133: xmode = A_XSI; ! 134: else ! 135: xmode = A_XDI; ! 136: sp = &mregstate[0]; ! 137: while (sp < &mregstate[NMREG]) { ! 138: if ((sp->a_mode&(A_AMOD|A_REGM)) == xmode) ! 139: sp->a_mode = A_NONE; ! 140: ++sp; ! 141: } ! 142: sp = &sregstate[0]; ! 143: while (sp < &sregstate[NSREG]) { ! 144: if ((sp->a_mode&(A_AMOD|A_REGM)) == xmode) ! 145: sp->a_mode = A_NONE; ! 146: ++sp; ! 147: } ! 148: } ! 149: } ! 150: ! 151: /* ! 152: * Flag segment register "r" as empty ! 153: * (contains unknown data) in the processor state. ! 154: * If "r" is the ES register then all entries in the ! 155: * processor state being accessed through ES must also ! 156: * flagged as empty. ! 157: */ ! 158: emptysreg(rsp) ! 159: register AFIELD *rsp; ! 160: { ! 161: register AFIELD *sp; ! 162: ! 163: rsp->a_mode = A_NONE; ! 164: if (rsp == &sregstate[MES]) { ! 165: sp = &mregstate[0]; ! 166: while (sp < &mregstate[NMREG]) { ! 167: if ((sp->a_mode&A_AMOD) != A_NONE ! 168: && (sp->a_mode&A_PREFX) == A_ES) ! 169: sp->a_mode = A_NONE; ! 170: ++sp; ! 171: } ! 172: sp = &sregstate[0]; ! 173: while (sp < &sregstate[NSREG]) { ! 174: if ((sp->a_mode&A_AMOD) != A_NONE ! 175: && (sp->a_mode&A_PREFX) == A_ES) ! 176: sp->a_mode = A_NONE; ! 177: ++sp; ! 178: } ! 179: } ! 180: if (rsp == &sregstate[MDS]) { ! 181: sp = &mregstate[0]; ! 182: while (sp < &mregstate[NMREG]) { ! 183: if ((sp->a_mode&A_AMOD) != A_NONE) { ! 184: if ((sp->a_mode&A_PREFX) == A_DS) ! 185: sp->a_mode = A_NONE; ! 186: else if ((sp->a_mode&A_PREFX) == A_NONE ! 187: && (sp->a_mode&(A_AMOD|A_REGM)) != A_XBP) ! 188: sp->a_mode = A_NONE; ! 189: } ! 190: ++sp; ! 191: } ! 192: sp = &sregstate[0]; ! 193: while (sp < &sregstate[NSREG]) { ! 194: if ((sp->a_mode&A_AMOD) != A_NONE) { ! 195: if ((sp->a_mode&A_PREFX) == A_DS) ! 196: sp->a_mode = A_NONE; ! 197: else if ((sp->a_mode&A_PREFX) == A_NONE ! 198: && (sp->a_mode&(A_AMOD|A_REGM)) != A_XBP) ! 199: sp->a_mode = A_NONE; ! 200: } ! 201: ++sp; ! 202: } ! 203: } ! 204: } ! 205: ! 206: /* ! 207: * This routine, given a pointer to ! 208: * a CODE node, returns 1 if the instruction has ! 209: * no effect on the machine state. This is determined by ! 210: * looking at the operands of the instruction and the value ! 211: * that is currently in the registers. Some care must be ! 212: * taken to make sure that an instruction that is being used ! 213: * to set the flags is not considered to have no effect. ! 214: */ ! 215: noeffect(ip) ! 216: register INS *ip; ! 217: { ! 218: register AFIELD *sp; ! 219: register short mode; ! 220: ! 221: if (ip->i_op == ZSUB) { ! 222: if ((ip->i_af[0].a_mode&A_AMOD) == A_WR ! 223: && ip->i_af[0].a_mode == ip->i_af[1].a_mode) { ! 224: sp = &mregstate[ip->i_af[0].a_mode&A_REGM]; ! 225: if ((sp->a_mode&A_AMOD) == A_IMM ! 226: && sp->a_sp == NULL ! 227: && sp->a_value == 0) { ! 228: /* Need flags? */ ! 229: if ((ip = ip->i_fp) == &ins) ! 230: return (0); ! 231: if (ip->i_type==JUMP && ip->i_rel!=ZJMP) ! 232: return (0); ! 233: return (1); ! 234: } ! 235: } ! 236: return (0); ! 237: } ! 238: if (ip->i_op == ZLEA) { ! 239: if (afcompare(A_EA, &ip->i_af[0], &ip->i_af[1], 0)) ! 240: return (1); ! 241: return (0); ! 242: } ! 243: if (ip->i_op==ZLDS || ip->i_op==ZLES) { ! 244: sp = (ip->i_op==ZLDS) ? &sregstate[MDS] : &sregstate[MES]; ! 245: if (afcompare(0, sp, &ip->i_af[1], 2) ! 246: && afcompare(0, &ip->i_af[0], &ip->i_af[1], 0)) ! 247: return (1); ! 248: return (0); ! 249: } ! 250: if (ip->i_op == ZMOV) { ! 251: mode = ip->i_af[0].a_mode&A_AMOD; ! 252: if ((mode==A_WR || mode==A_SR) ! 253: && afcompare(0, &ip->i_af[0], &ip->i_af[1], 0)) ! 254: return (1); ! 255: return (0); ! 256: } ! 257: return (0); ! 258: } ! 259: ! 260: /* ! 261: * This routine looks at a CODE node ! 262: * and tries to make it into a simpler node that ! 263: * performs the same transformation of the machine ! 264: * state. The current idioms understood are: ! 265: * 1) Look for "half loaded" "lds" and "les" instructions ! 266: * that can be changed into the approproate "mov". ! 267: * 2) Try to replace memory operands of dual op instructions ! 268: * and push instructions with old register data. ! 269: */ ! 270: simplify(ip) ! 271: register INS *ip; ! 272: { ! 273: register AFIELD *sp; ! 274: ! 275: switch (ip->i_op) { ! 276: ! 277: case ZLDS: ! 278: case ZLES: ! 279: sp = (ip->i_op==ZLDS) ? &sregstate[MDS] : &sregstate[MES]; ! 280: if (afcompare(0, sp, &ip->i_af[1], 2)) { ! 281: if (!afcompare(0, &ip->i_af[0], &ip->i_af[1], 0)) { ! 282: ip->i_op = ZMOV; ! 283: ++nsimplify; ! 284: ++changes; ! 285: } ! 286: } else if (afcompare(0, &ip->i_af[0], &ip->i_af[1], 0)) { ! 287: if (ip->i_op == ZLDS) ! 288: ip->i_af[0].a_mode = A_SR|MDS; else ! 289: ip->i_af[0].a_mode = A_SR|MES; ! 290: ip->i_af[1].a_value += 2; ! 291: ip->i_op = ZMOV; ! 292: ++nsimplify; ! 293: ++changes; ! 294: } ! 295: break; ! 296: ! 297: case ZADC: ! 298: case ZADD: ! 299: case ZAND: ! 300: case ZOR: ! 301: case ZSBB: ! 302: case ZSUB: ! 303: case ZXOR: ! 304: simpoper(&ip->i_af[1]); ! 305: break; ! 306: ! 307: case ZPUSH: ! 308: simpoper(&ip->i_af[0]); ! 309: break; ! 310: } ! 311: } ! 312: ! 313: /* ! 314: * The "afp" points at an AFIELD. If it is ! 315: * a memory AFIELD look through the processor state ! 316: * to see if a register contains the same value. If such ! 317: * a register is found adjust the AFIELD to refer to the ! 318: * machine register. ! 319: */ ! 320: simpoper(afp) ! 321: register AFIELD *afp; ! 322: { ! 323: register AFIELD *sp; ! 324: register int mode; ! 325: ! 326: mode = afp->a_mode&A_AMOD; ! 327: if (mode==A_IMM || mode==A_DIR || mode==A_X) { ! 328: sp = &mregstate[0]; ! 329: while (sp < &mregstate[NMREG]) { ! 330: if (afcompare(0, sp, afp, 0)) { ! 331: afp->a_mode = A_WR | (sp-&mregstate[0]); ! 332: afp->a_sp = NULL; ! 333: afp->a_value = 0; ! 334: ++nsimplify; ! 335: ++changes; ! 336: break; ! 337: } ! 338: ++sp; ! 339: } ! 340: } ! 341: } ! 342: ! 343: /* ! 344: * Look at the CODE node pointed to ! 345: * by "ip", and make the required changes to the processor ! 346: * state. Some special compiler idioms have special checks. ! 347: * Any instruction for which there is no special knowledge ! 348: * is assumed to have no effect on the machine state. ! 349: */ ! 350: track(ip) ! 351: register INS *ip; ! 352: { ! 353: register AFIELD *sp; ! 354: register short destmode; ! 355: register short destreg; ! 356: register short isbyte; ! 357: ! 358: if (ip->i_op == ZOR ! 359: && (ip->i_af[0].a_mode&A_AMOD) == A_WR ! 360: && ip->i_af[0].a_mode == ip->i_af[1].a_mode) ! 361: return; ! 362: if (ip->i_op == ZSUB ! 363: && (ip->i_af[0].a_mode&A_AMOD) == A_WR ! 364: && ip->i_af[0].a_mode == ip->i_af[1].a_mode) { ! 365: sp = &mregstate[ip->i_af[0].a_mode&A_REGM]; ! 366: sp->a_mode = A_IMM; ! 367: sp->a_sp = NULL; ! 368: sp->a_value = 0; ! 369: return; ! 370: } ! 371: isbyte = 0; ! 372: switch (ip->i_op) { ! 373: ! 374: case ZAAA: ! 375: case ZAAD: ! 376: case ZAAM: ! 377: case ZAAS: ! 378: case ZCBW: ! 379: case ZDAA: ! 380: case ZDAS: ! 381: case ZDIVB: ! 382: case ZIDIVB: ! 383: case ZIMULB: ! 384: case ZIN: ! 385: case ZINB: ! 386: case ZLAHF: ! 387: case ZMULB: ! 388: emptymreg(&mregstate[MAX]); ! 389: break; ! 390: ! 391: case ZCWD: ! 392: emptymreg(&mregstate[MDX]); ! 393: break; ! 394: ! 395: case ZDIV: ! 396: case ZIDIV: ! 397: case ZIMUL: ! 398: case ZMUL: ! 399: emptymreg(&mregstate[MAX]); ! 400: emptymreg(&mregstate[MDX]); ! 401: break; ! 402: ! 403: case ZREPE: ! 404: case ZREPNE: ! 405: emptymreg(&mregstate[MCX]); ! 406: break; ! 407: ! 408: case ZCALL: ! 409: case ZICALL: ! 410: case ZIXCALL: ! 411: case ZXCALL: ! 412: case ZCMPS: ! 413: case ZCMPSB: ! 414: case ZINT: ! 415: case ZINTO: ! 416: case ZLODS: ! 417: case ZLODSB: ! 418: case ZMOVS: ! 419: case ZMOVSB: ! 420: case ZSCAS: ! 421: case ZSCASB: ! 422: case ZSTOS: ! 423: case ZSTOSB: ! 424: case ZXCHG: ! 425: case ZXCHGB: ! 426: case ZXLAT: ! 427: emptyall(); ! 428: break; ! 429: ! 430: case ZADCB: ! 431: case ZADDB: ! 432: case ZANDB: ! 433: case ZDECB: ! 434: case ZINCB: ! 435: case ZNEGB: ! 436: case ZNOTB: ! 437: case ZORB: ! 438: case ZRCLB: ! 439: case ZRCRB: ! 440: case ZROLB: ! 441: case ZRORB: ! 442: case ZSALB: ! 443: case ZSARB: ! 444: case ZSBBB: ! 445: case ZSHLB: ! 446: case ZSHRB: ! 447: case ZSUBB: ! 448: case ZXORB: ! 449: isbyte = 1; ! 450: case ZADC: ! 451: case ZADD: ! 452: case ZAND: ! 453: case ZINC: ! 454: case ZDEC: ! 455: case ZNEG: ! 456: case ZNOT: ! 457: case ZOR: ! 458: case ZPOP: ! 459: case ZRCL: ! 460: case ZRCR: ! 461: case ZROL: ! 462: case ZROR: ! 463: case ZSAL: ! 464: case ZSAR: ! 465: case ZSBB: ! 466: case ZSHL: ! 467: case ZSHR: ! 468: case ZSUB: ! 469: case ZXOR: ! 470: case ZIMULI: ! 471: destmode = ip->i_af[0].a_mode&A_AMOD; ! 472: destreg = ip->i_af[0].a_mode&A_REGM; ! 473: if (destmode==A_WR || destmode==A_BR) { ! 474: if (isbyte != 0) ! 475: destreg &= 0x03; ! 476: emptymreg(&mregstate[destreg]); ! 477: } else if (destmode == A_SR) ! 478: emptysreg(&sregstate[destreg]); ! 479: else if (isbyte==0 && (destmode==A_DIR || destmode==A_X)) ! 480: emptyaf(&ip->i_af[0]); ! 481: else ! 482: emptyall(); ! 483: break; ! 484: ! 485: case ZLEA: ! 486: afupdate(A_EA, &ip->i_af[0], &ip->i_af[1], 0); ! 487: break; ! 488: ! 489: case ZLDS: ! 490: afupdate(0, &ip->i_af[0], &ip->i_af[1], 0); ! 491: afupdate(0, &afdsfakeing, &ip->i_af[1], 2); ! 492: break; ! 493: ! 494: case ZLES: ! 495: afupdate(0, &ip->i_af[0], &ip->i_af[1], 0); ! 496: afupdate(0, &afesfakeing, &ip->i_af[1], 2); ! 497: break; ! 498: ! 499: case ZMOV: ! 500: destmode = ip->i_af[0].a_mode&A_AMOD; ! 501: destreg = ip->i_af[0].a_mode&A_REGM; ! 502: if (destmode==A_WR || destmode==A_SR) ! 503: afupdate(0, &ip->i_af[0], &ip->i_af[1], 0); ! 504: else if (destmode==A_DIR || destmode==A_X) { ! 505: emptyaf(&ip->i_af[0]); ! 506: destmode = ip->i_af[1].a_mode&A_AMOD; ! 507: if (destmode==A_WR || destmode==A_SR) ! 508: afupdate(0, &ip->i_af[1], &ip->i_af[0], 0); ! 509: } else ! 510: emptyall(); ! 511: break; ! 512: ! 513: case ZMOVB: ! 514: destmode = ip->i_af[0].a_mode&A_AMOD; ! 515: destreg = ip->i_af[0].a_mode&A_REGM; ! 516: if (destmode == A_BR) ! 517: emptymreg(&mregstate[destreg&0x03]); ! 518: else if (destmode==A_DIR || destmode==A_X) ! 519: emptyaf(&ip->i_af[0]); ! 520: else ! 521: emptyall(); ! 522: } ! 523: } ! 524: ! 525: /* ! 526: * This routine compares address fields. ! 527: * The "afp1" and "afp2" parameters are the fields ! 528: * themselves. They must be "resolved" to the machine ! 529: * state if registers. The "afp1" argument always is ! 530: * the register side, and is required to have the flags ! 531: * that are set in "flags" in the address. The "afp2" ! 532: * is the lvalue side; it gets its address adjusted by ! 533: * "bump" bytes before the compare is done. ! 534: */ ! 535: afcompare(flag, afp1, afp2, bump) ! 536: register AFIELD *afp1; ! 537: register AFIELD *afp2; ! 538: { ! 539: register short mode; ! 540: ! 541: if ((afp1=afresolve(afp1, 0x00, 0)) == NULL) ! 542: return (0); ! 543: if ((afp2=afresolve(afp2, bump, 0)) == NULL) ! 544: return (0); ! 545: if (afp1->a_mode==A_NONE || afp2->a_mode==A_NONE) ! 546: return (0); ! 547: if (afp1->a_mode != afp2->a_mode) ! 548: return (0); ! 549: mode = afp1->a_mode&A_AMOD; ! 550: if (mode==A_IMM || mode==A_DIR || mode==A_X) { ! 551: if (afp1->a_sp != afp2->a_sp) ! 552: return (0); ! 553: if (afp1->a_value != afp2->a_value+bump) ! 554: return (0); ! 555: if ((afp1->a_mode&A_EA) != flag) ! 556: return (0); ! 557: } ! 558: return (1); ! 559: } ! 560: ! 561: /* ! 562: * Update address fields in the processor ! 563: * state tables. The arguments have the same functions ! 564: * as their namesakes in "afcompare" (above). ! 565: */ ! 566: afupdate(flag, afp1, afp2, bump) ! 567: register AFIELD *afp1; ! 568: register AFIELD *afp2; ! 569: { ! 570: if ((afp1=afresolve(afp1, 0x00, 1)) == NULL) ! 571: cbotch("afupdate"); ! 572: if ((afp2=afresolve(afp2, bump, 0)) == NULL) ! 573: afp1->a_mode = A_NONE; ! 574: else if (afdependency(afp1, afp2)) ! 575: afp1->a_mode = A_NONE; ! 576: else { ! 577: afp1->a_mode = afp2->a_mode; ! 578: afp1->a_sp = afp2->a_sp; ! 579: afp1->a_value = afp2->a_value+bump; ! 580: if (afp1->a_mode != A_NONE) ! 581: afp1->a_mode |= flag; ! 582: } ! 583: } ! 584: ! 585: /* ! 586: * Resolve an address descriptor to the entry ! 587: * in the processor state. If the entry will not map ! 588: * for some reason, return NULL. The "bump" argument is ! 589: * passed so that "afresolve" can fail on bumped registers. ! 590: * If "flag" is set the register descriptor is flushed. ! 591: */ ! 592: AFIELD * ! 593: afresolve(afp, bump, flag) ! 594: register AFIELD *afp; ! 595: { ! 596: register short mode; ! 597: ! 598: if ((mode=afp->a_mode&A_AMOD) == A_BR) ! 599: return (NULL); ! 600: if (mode == A_WR) { ! 601: if (bump != 0) ! 602: return (NULL); ! 603: afp = &mregstate[afp->a_mode&A_REGM]; ! 604: if (flag != 0) ! 605: emptymreg(afp); ! 606: return (afp); ! 607: } ! 608: if (mode == A_SR) { ! 609: if (bump != 0) ! 610: return (NULL); ! 611: afp = &sregstate[afp->a_mode&A_REGM]; ! 612: if (flag != 0) ! 613: emptysreg(afp); ! 614: return (afp); ! 615: } ! 616: return (afp); ! 617: } ! 618: ! 619: /* ! 620: * Given two AFIELD nodes, ! 621: * return true if the second depends ! 622: * on the value of the first. This checks ! 623: * for instructions like "mov bx,3[bx]", ! 624: * where you must not set the contents of ! 625: * "bx" to be "3[bx]". ! 626: */ ! 627: afdependency(afp1, afp2) ! 628: register AFIELD *afp1; ! 629: register AFIELD *afp2; ! 630: { ! 631: if (afp1 == &mregstate[MBX]) { ! 632: if ((afp2->a_mode&(A_AMOD|A_REGM)) == A_XBX) ! 633: return (1); ! 634: return (0); ! 635: } ! 636: if (afp1 == &mregstate[MSI]) { ! 637: if ((afp2->a_mode&(A_AMOD|A_REGM)) == A_XSI) ! 638: return (1); ! 639: return (0); ! 640: } ! 641: if (afp1 == &mregstate[MDI]) { ! 642: if ((afp2->a_mode&(A_AMOD|A_REGM)) == A_XDI) ! 643: return (1); ! 644: return (0); ! 645: } ! 646: if (afp1 == &sregstate[MES]) { ! 647: if ((afp2->a_mode&A_PREFX) == A_ES) ! 648: return (1); ! 649: return (0); ! 650: } ! 651: if (afp1 == &sregstate[MDS]) { ! 652: if ((afp2->a_mode&A_PREFX) == A_DS) ! 653: return (1); ! 654: if ((afp2->a_mode&A_PREFX) == A_NONE ! 655: && (afp2->a_mode&(A_AMOD|A_REGM)) != A_XBP) ! 656: return (1); ! 657: return (0); ! 658: } ! 659: return (0); ! 660: } ! 661: ! 662: /* ! 663: * Purge any processor state entries that ! 664: * think they are holding the value of "afp". This ! 665: * is used to purge the state of the world when a register ! 666: * is stored into memory. ! 667: */ ! 668: emptyaf(afp) ! 669: register AFIELD *afp; ! 670: { ! 671: register AFIELD *sp; ! 672: ! 673: sp = &mregstate[0]; ! 674: while (sp < &mregstate[NMREG]) { ! 675: if (afcompare(0, sp, afp, 0)) ! 676: emptymreg(sp); ! 677: ++sp; ! 678: } ! 679: sp = &sregstate[0]; ! 680: while (sp < &sregstate[NSREG]) { ! 681: if (afcompare(0, sp, afp, 0)) ! 682: emptysreg(sp); ! 683: ++sp; ! 684: } ! 685: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.