int genfun(TOKEN code) { int reg; //Load args //printf("here\n"); if((code->operands)->link != NULL) { reg = genarith((code->operands)->link); if(((code->operands)->link)->tokentype == STRINGTOK) { asmlitarg(reg, EDI); } else if(((code->operands)->link)->tokentype == NUMBERTOK && ((code->operands)->link)->datatype == INTEGER) { asmrr(MOVL, reg, EDI); reg_map[reg] = 0; reg = EDI; } else if(((code->operands)->link)->tokentype == IDENTIFIERTOK) { asmrr(MOVL, reg, EDI); reg_map[reg] = 0; reg = EDI; } clearreg(); reg_map[reg] = 1; } savereg(); asmcall(code->operands->stringval); restorereg(); if(code->datatype == REAL) return FBASE; else if(code->datatype == INTEGER) return RAX; }
rmove() { register struct node *p; register char *cp; register int r; int r1, flt; for (p=first.forw; p!=0; p = p->forw) { if (debug) { for (r=0; r<2*NREG; r++) if (regs[r][0]) printf("%d: %s\n", r, regs[r]); printf("-\n"); } flt = 0; switch (p->op) { case MOVF: case MOVFO: case MOVOF: flt = NREG; case MOV: dualop(p); if ((r = findrand(regs[RT1], flt)) >= 0) { if (r == flt+isreg(regs[RT2]) && p->forw->op!=CBR) { p->forw->back = p->back; p->back->forw = p->forw; redunm++; continue; } } repladdr(p, 0, flt); r = isreg(regs[RT1]); r1 = isreg(regs[RT2]); dest(regs[RT2], flt); if (r >= 0) if (r1 >= 0) savereg(r1+flt, regs[r+flt]); else savereg(r+flt, regs[RT2]); else if (r1 >= 0) savereg(r1+flt, regs[RT1]); else setcon(regs[RT1], regs[RT2]); source(regs[RT1]); setcc(regs[RT2]); continue; case ADDF: case SUBF: case DIVF: case MULF: flt = NREG; case ADD: case SUB: case BIC: case BIS: case MUL: case DIV: case ASH: dualop(p); repladdr(p, 0, flt); source(regs[RT1]); dest(regs[RT2], flt); if (p->op==DIV && (r = isreg(regs[RT2])>=0)) regs[r+1][0] = 0; ccloc[0] = 0; continue; case CLRF: case NEGF: flt = NREG; case CLR: case COM: case INC: case DEC: case NEG: case ASR: case ASL: case SXT: singop(p); dest(regs[RT1], flt); if (p->op==CLR && flt==0) if ((r = isreg(regs[RT1])) >= 0) savereg(r, "$0"); else setcon("$0", regs[RT1]); setcc(regs[RT1]); continue; case TSTF: flt = NREG; case TST: singop(p); repladdr(p, 0, flt); source(regs[RT1]); if (equstr(regs[RT1], ccloc)) { p->back->forw = p->forw; p->forw->back = p->back; p = p->back; nrtst++; nchange++; } continue; case CMPF: flt = NREG; case CMP: case BIT: dualop(p); source(regs[RT1]); source(regs[RT2]); repladdr(p, 1, flt); ccloc[0] = 0; continue; case CBR: case CFCC: ccloc[0] = 0; continue; case JBR: redunbr(p); default: clearreg(); } } }
rmove() { register struct node *p; register int r; register r1, flt; for (p=first.forw; p!=0; p = p->forw) { flt = 0; switch (p->op) { case MOVF: case MOVFO: case MOVOF: flt = NREG; case MOV: if (p->subop==BYTE) goto dble; dualop(p); if ((r = findrand(regs[RT1], flt)) >= 0) { if (r == flt+isreg(regs[RT2]) && p->forw->op!=CBR && p->forw->op!=SXT && p->forw->op!=CFCC) { p->forw->back = p->back; p->back->forw = p->forw; redunm++; continue; } } if (equstr(regs[RT1], "$0")) { p->op = CLR; strcpy(regs[RT1], regs[RT2]); regs[RT2][0] = 0; p->code = copy(1, regs[RT1]); goto sngl; } repladdr(p, 0, flt); r = isreg(regs[RT1]); r1 = isreg(regs[RT2]); dest(regs[RT2], flt); if (r >= 0) if (r1 >= 0) savereg(r1+flt, regs[r+flt]); else savereg(r+flt, regs[RT2]); else if (r1 >= 0) savereg(r1+flt, regs[RT1]); else setcon(regs[RT1], regs[RT2]); source(regs[RT1]); setcc(regs[RT2]); continue; case ADDF: case SUBF: case DIVF: case MULF: flt = NREG; goto dble; case ADD: case SUB: case BIC: case BIS: case MUL: case DIV: case ASH: dble: dualop(p); if (p->op==BIC && (equstr(regs[RT1], "$-1") || equstr(regs[RT1], "$177777"))) { p->op = CLR; strcpy(regs[RT1], regs[RT2]); regs[RT2][0] = 0; p->code = copy(1, regs[RT1]); goto sngl; } if ((p->op==BIC || p->op==BIS) && equstr(regs[RT1], "$0")) { if (p->forw->op!=CBR) { p->back->forw = p->forw; p->forw->back = p->back; continue; } } repladdr(p, 0, flt); source(regs[RT1]); dest(regs[RT2], flt); if (p->op==DIV && (r = isreg(regs[RT2])>=0)) regs[r+1][0] = 0; ccloc[0] = 0; continue; case CLRF: case NEGF: flt = NREG; case CLR: case COM: case INC: case DEC: case NEG: case ASR: case ASL: case SXT: singop(p); sngl: dest(regs[RT1], flt); if (p->op==CLR && flt==0) if ((r = isreg(regs[RT1])) >= 0) savereg(r, "$0"); else setcon("$0", regs[RT1]); ccloc[0] = 0; continue; case TSTF: flt = NREG; case TST: singop(p); repladdr(p, 0, flt); source(regs[RT1]); if (equstr(regs[RT1], ccloc)) { p->back->forw = p->forw; p->forw->back = p->back; p = p->back; nrtst++; nchange++; } continue; case CMPF: flt = NREG; case CMP: case BIT: dualop(p); source(regs[RT1]); source(regs[RT2]); if(p->op==BIT) { if (equstr(regs[RT1], "$-1") || equstr(regs[RT1], "$177777")) { p->op = TST; strcpy(regs[RT1], regs[RT2]); regs[RT2][0] = 0; p->code = copy(1, regs[RT1]); nchange++; nsaddr++; } else if (equstr(regs[RT2], "$-1") || equstr(regs[RT2], "$177777")) { p->op = TST; regs[RT2][0] = 0; p->code = copy(1, regs[RT1]); nchange++; nsaddr++; } if (equstr(regs[RT1], "$0")) { p->op = TST; regs[RT2][0] = 0; p->code = copy(1, regs[RT1]); nchange++; nsaddr++; } else if (equstr(regs[RT2], "$0")) { p->op = TST; strcpy(regs[RT1], regs[RT2]); regs[RT2][0] = 0; p->code = copy(1, regs[RT1]); nchange++; nsaddr++; } } repladdr(p, 1, flt); ccloc[0] = 0; continue; case CBR: if (p->back->op==TST || p->back->op==CMP) { if (p->back->op==TST) { singop(p->back); savereg(RT2, "$0"); } else dualop(p->back); r = compare(p->subop, findcon(RT1), findcon(RT2)); if (r==0) { p->back->back->forw = p->forw; p->forw->back = p->back->back; decref(p->ref); p = p->back->back; nchange++; } else if (r>0) { p->op = JBR; p->subop = 0; p->back->back->forw = p; p->back = p->back->back; p = p->back; nchange++; } } case CFCC: ccloc[0] = 0; continue; case JBR: redunbr(p); default: clearreg(); } } }
/* Generate code for a Statement from an intermediate-code form */ void genc(TOKEN code) { TOKEN tok, lhs, rhs; int reg, reg2, offs; int thenlbl, elselbl; SYMBOL sym; if (DEBUGGEN) { printf("genc\n"); dbugprinttok(code); }; if ( code->tokentype != OPERATOR ) { printf("Bad code token"); dbugprinttok(code); }; clearreg(); switch ( code->whichval ) { case PROGNOP: tok = code->operands; while ( tok != NULL ) { genc(tok); tok = tok->link; }; break; case ASSIGNOP: lhs = code->operands; if(lhs->whichval == AREFOP) { rhs = lhs->link; reg = genarith(rhs); /* generate rhs into a register */ reg2 = genaref(lhs, reg); //asmst(MOVL, reg, offs, lhs->stringval); } else { sym = lhs->symentry; /* assumes lhs is a simple var */ offs = sym->offset - stkframesize; /* net offset of the var */ rhs = lhs->link; reg = genarith(rhs); /* generate rhs into a register */ switch (code->datatype) /* store value into lhs */ { case INTEGER: asmst(MOVL, reg, offs, lhs->stringval); break; case REAL: asmst(MOVSD, reg, offs, lhs->stringval); break; case STRINGTYPE: asmst(MOVL, reg, offs, lhs->stringval); break; case BOOLETYPE: asmst(MOVL, reg, offs, lhs->stringval); break; case POINTER: asmst(MOVQ, reg, offs, lhs->stringval); break; }; } break; case GOTOOP: asmjump(JMP, code->operands->intval); break; case LABELOP: asmlabel(code->operands->intval); break; case IFOP: thenlbl = nextlabel++; elselbl = nextlabel++; genarith(code->operands); //genarith on condition asmjump(broptbl[code->operands->whichval], thenlbl); //branch to then if(((code->operands)->link)->link != NULL) //gen else genc(((code->operands)->link)->link); asmjump(JMP, elselbl); asmlabel(thenlbl); genc((code->operands)->link); //genthen asmlabel(elselbl); break; case FUNCALLOP: genfun(code); break; }; }
/* Generate code for a Statement from an intermediate-code form */ void genc(TOKEN code) { TOKEN tok, lhs, rhs; int reg, reg2, offs, jmpval, loop1, loop2; SYMBOL sym, lsym, rsym; if (DEBUGGEN) { printf("genc\n"); dbugprinttok(code); }; if ( code->tokentype != OPERATOR ) { printf("Bad code token"); dbugprinttok(code); }; // This switch statement will determine how to handle the token based on its operator value switch ( code->whichval ) { case PROGNOP: tok = code->operands; while ( tok != NULL ) { genc(tok); tok = tok->link; }; break; case ASSIGNOP: /* Trivial version: handles I := e */ lhs = code->operands; rhs = lhs->link; reg = genarith(rhs); /* generate rhs into a register */ if(rhs != NULL) rsym = rhs->symentry; if(lhs->tokentype == OPERATOR & lhs->whichval == AREFOP) { if(lhs->operands->tokentype != OPERATOR & lhs->operands->whichval != POINTEROP) { if(lhs->operands->link->tokentype == NUMBERTOK) { lsym = lhs->operands->symentry; reg2 = getreg(WORD); asmimmed(MOVL, lhs->operands->link->intval, reg2); asmop(CLTQ); if(reg < 8 & reg2 < 8) { asmstrr(MOVL, reg, lsym->offset - stkframesize, reg2, lhs->operands->stringval); } else { asmstrr(MOVSD, reg, lsym->offset - stkframesize, reg2, lhs->operands->stringval); } break; } else { reg2 = genarith(lhs->operands->link); asmop(CLTQ); lsym = lhs->operands->symentry; if(reg < 8 & reg2 < 8) { asmstrr(MOVL, reg, lsym->offset - stkframesize, reg2, lhs->operands->stringval); } else { asmstrr(MOVSD, reg, lsym->offset - stkframesize, reg2, lhs->operands->stringval); } break; } } reg2 = genarith(lhs->operands); offs = lhs->operands->link->intval; if(rsym != NULL) { if(rsym->datatype->kind == POINTERSYM) asmstr(MOVQ, reg, offs, reg2, "^. "); else { if (reg < 8 & reg2 < 8) asmstr(MOVL, reg, offs, reg2, "^. "); else asmstr(MOVSD, reg, offs, reg2, "^. "); } } else { if (reg < 8 & reg2 < 8) asmstr(MOVL, reg, offs, reg2, "^. "); else asmstr(MOVSD, reg, offs, reg2, "^. "); } unused(reg); break; } else { lsym = lhs->symentry; /* assumes lhs is a simple var */ offs = lsym->offset - stkframesize; /* net offset of the var */ } if(lsym->datatype->kind == POINTERSYM) { asmst(MOVQ, reg, offs, lhs->stringval); } else { switch (code->datatype) /* store value into lhs */ { case INTEGER: asmst(MOVL, reg, offs, lhs->stringval); break; case REAL: asmst(MOVSD, reg, offs, lhs->stringval); break; } } unused(reg); break; case PLUSOP: lhs = code->operands; rhs = lhs->link; lsym = lhs->symentry; rsym = rhs->symentry; if(lsym != NULL & lhs->tokentype != NUMBERTOK) asmldr(MOVL, lsym->offset - stkframesize, RBP, EAX, lsym->namestring); else asmimmed(MOVL, lhs->intval, EAX); if(rsym != NULL & rhs->tokentype != NUMBERTOK) asmldr(MOVL, rsym->offset - stkframesize, RBP, ECX, rsym->namestring); else asmimmed(MOVL, rhs->intval, ECX); asmrr(ADDL, ECX, EAX); break; case LABELOP: lhs = code->operands; asmlabel(lhs->intval); break; case IFOP: tok = code->operands; lhs = tok->operands; rhs = lhs->link; lsym = lhs->symentry; rsym = rhs->symentry; loop1 = nextlabel++; loop2 = nextlabel++; if(rhs->symtype != NULL) { if (rhs->symtype->kind == POINTERSYM) { if(lsym != NULL & lhs->tokentype != NUMBERTOK) asmldr(MOVQ, lsym->offset - stkframesize, RBP, EAX, lsym->namestring); else asmimmed(MOVQ, lhs->intval, EAX); if(rsym != NULL & rhs->tokentype != NUMBERTOK) asmldr(MOVQ, rsym->offset - stkframesize, RBP, ECX, rsym->namestring); else asmimmed(MOVQ, rhs->intval, ECX); asmrr(CMPQ, ECX, EAX); } else { if(lsym != NULL & lhs->tokentype != NUMBERTOK) asmldr(MOVL, lsym->offset - stkframesize, RBP, EAX, lsym->namestring); else asmimmed(MOVL, lhs->intval, EAX); if(rsym != NULL & rhs->tokentype != NUMBERTOK) asmldr(MOVL, rsym->offset - stkframesize, RBP, ECX, rsym->namestring); else asmimmed(MOVL, rhs->intval, ECX); asmrr(CMPL, ECX, EAX); } } else { if(lsym != NULL & lhs->tokentype != NUMBERTOK) asmldr(MOVL, lsym->offset - stkframesize, RBP, EAX, lsym->namestring); else asmimmed(MOVL, lhs->intval, EAX); if(rsym != NULL & rhs->tokentype != NUMBERTOK) asmldr(MOVL, rsym->offset - stkframesize, RBP, ECX, rsym->namestring); else asmimmed(MOVL, rhs->intval, ECX); asmrr(CMPL, ECX, EAX); } switch(tok->whichval) { case EQOP: jmpval = JE; break; case NEOP: jmpval = JNE; break; case LTOP: jmpval = JL; break; case LEOP: jmpval = JLE; break; case GEOP: jmpval = JGE; break; case GTOP: jmpval = JG; break; } asmjump(jmpval, loop1); tok = tok->link; //else part if(tok->link != NULL) genc(tok->link); asmjump(JMP, loop2); //if part asmlabel(loop1); genc(tok); asmlabel(loop2); break; case GOTOOP: lhs = code->operands; asmjump(JMP, lhs->intval); break; case FUNCALLOP: tok = code->operands; rhs = tok->link; if(rhs != NULL) { switch(rhs->tokentype) { case STRINGTOK: asmlitarg(nextlabel++, EDI); makeblit(rhs->stringval, nextlabel-1); asmcall(tok->stringval); break; case IDENTIFIERTOK: rsym = rhs->symentry; reg = getreg(WORD); asmld(MOVL, rsym->offset - stkframesize, reg, rhs->stringval); asmrr(MOVL, reg, EDI); asmcall(tok->stringval); break; case OPERATOR: rsym = rhs->symentry; reg = getreg(FLOAT); asmld(MOVL, -1000, EAX, rhs->operands->operands->stringval); asmldr(MOVSD, rhs->operands->link->intval, EAX, XMM0, "^. "); asmcall(tok->stringval); break; } } break; }; clearreg(); }
int mtrropt(u64t wc_addr, u64t wc_len, u32t *memlimit) { u32t reg; int ii, sv4idx = 0; mtrrentry save4[16]; memset(&save4,0,sizeof(save4)); *memlimit = 0; if (is_included(wc_addr,wc_len)<0 && is_intersection(wc_addr, wc_len)<0 && is_regavail(®)) { mtrr[reg].start = wc_addr; mtrr[reg].len = wc_len; mtrr[reg].cache = MTRRF_WC; mtrr[reg].on = 1; return 0; } // video memory in not in 4th GB if (wc_addr<_3GbLL || wc_addr+wc_len>_4GbLL) return OPTERR_VIDMEM3GB; /* turn off previous write combine on the same memory, but leave this block to catch low UC border successfully */ ii = is_include(wc_addr, wc_len); if (ii>=0 && mtrr[ii].cache==MTRRF_WC) mtrr[ii].cache=MTRRF_UC; // only WB and UC allowed in first 4Gb for (ii=0; ii<regs; ii++) if (mtrr[ii].on && mtrr[ii].cache!=MTRRF_UC && mtrr[ii].cache!=MTRRF_WB && mtrr[ii].start<_4GbLL) return OPTERR_UNKCT; // is block intersected with someone? ii = is_intersection(wc_addr, wc_len); if (ii>=0) return OPTERR_INTERSECT; // remove/truncate all above 4Gb (but save it) for (ii=0; ii<regs; ii++) if (mtrr[ii].on) if (mtrr[ii].start<_4GbLL && mtrr[ii].start+mtrr[ii].len>_4GbLL) { u64t newlen = _4GbLL - mtrr[ii].start, remain = mtrr[ii].len - newlen; if (!is_power2(newlen)) return OPTERR_SPLIT4GB; mtrr[ii].len = newlen; // save block if (is_power2(remain)) { save4[sv4idx].start = _4GbLL; save4[sv4idx].len = remain; save4[sv4idx].cache = mtrr[ii].cache; sv4idx++; } else if (is_power2(remain/3)) { } } else if (mtrr[ii].start>=_4GbLL || mtrr[ii].start+mtrr[ii].len>_4GbLL) { save4[sv4idx].start = mtrr[ii].start; save4[sv4idx].len = mtrr[ii].len; save4[sv4idx].cache = mtrr[ii].cache; sv4idx++; clearreg(ii); } u64t wbend = 0, ucstart = FFFF64; // searching for upper WB border for (ii=0; ii<regs; ii++) if (mtrr[ii].on) if (mtrr[ii].cache==MTRRF_WB) if (mtrr[ii].start+mtrr[ii].len > wbend) wbend = mtrr[ii].start+mtrr[ii].len; // searching for lower UC border (but ignore small blocks) for (ii=0; ii<regs; ii++) if (mtrr[ii].on) if (mtrr[ii].cache==MTRRF_UC) { int pwr = bsf64(mtrr[ii].len); if (pwr>=27) { if (ucstart>mtrr[ii].start) ucstart = mtrr[ii].start; clearreg(ii); } } // pass #2 - removing small blocks above selected border for (ii=0; ii<regs; ii++) if (mtrr[ii].on) if (mtrr[ii].cache==MTRRF_UC && ucstart<=mtrr[ii].start) clearreg(ii); // if no UC entries - use the end of WB as border if (ucstart>wbend) ucstart = wbend; // this can occur on small video memory size (<128Mb) if (wc_addr<ucstart) return OPTERR_BELOWUC; // build new WB list if (ucstart<wbend) { if (ucstart<_1GbLL) return OPTERR_LOWUC; for (ii=0; ii<regs; ii++) if (mtrr[ii].on) if (mtrr[ii].cache==MTRRF_WB) clearreg(ii); int regsfree = regsavail() - sv4idx - 1; log_it(2, "regs free: %i \n", regsfree); // force 3 registers (some memory above 4Gb can be lost) if (regsfree<3) regsfree = 3; // split memory to list u64t nextpos = 0; ii = 0; for (u64t size=_2GbLL; size>=_64MbLL; size>>=1) { if (ucstart>=size) { if (!is_regavail(®)) return OPTERR_NOREG; mtrr[reg].start = nextpos; nextpos += (mtrr[reg].len = size); mtrr[reg].cache = MTRRF_WB; mtrr[reg].on = 1; ucstart -= size; // use only 3 mtrr regs if (++ii==regsfree) break; } } // save memlimit value *memlimit = nextpos>>20; /** and again removing small blocks above selected border... splitted blocks sum can be smaller than previously selected UC border and some blocks can be cleared here */ for (ii=0; ii<regs; ii++) if (mtrr[ii].on) if (mtrr[ii].cache==MTRRF_UC && nextpos<=mtrr[ii].start) clearreg(ii); } // final check if (is_included(wc_addr,wc_len)>=0 || is_intersection(wc_addr,wc_len)>=0 || is_include(wc_addr,wc_len)>=0) return OPTERR_OPTERR; // add entry if (is_regavail(®)) { mtrr[reg].start = wc_addr; mtrr[reg].len = wc_len; mtrr[reg].cache = MTRRF_WC; mtrr[reg].on = 1; } // restore some of above 4Gb memory blocks if (sv4idx && regsavail()>0) { for (ii=0; ii<sv4idx; ii++) { if (!is_regavail(®)) break; mtrr[reg].start = save4[ii].start; mtrr[reg].len = save4[ii].len; mtrr[reg].cache = save4[ii].cache; mtrr[reg].on = 1; } // check lost items for included UC entries while (ii<sv4idx) { if (mtrr[ii].cache==MTRRF_UC) { int idx = is_included(save4[ii].start,save4[ii].len); if (idx<0) idx = is_intersection(save4[ii].start,save4[ii].len); // check it multiple times (for intersection) if (idx>=0) { clearreg(idx); continue; } } ii++; } } return 0; }
rmove() { register struct node *p; register int r; register r1, flt; for (p=first.forw; p!=0; p = p->forw) { flt = 0; switch (p->op) { case MOVF: case MOVFO: case MOVOF: flt = NREG; case MOV: if (p->subop==BYTE) goto dble; dualop(p); if ((r = findrand(regs[RT1], flt)) >= 0) { if (r == flt+isreg(regs[RT2]) && p->forw->op!=CBR && p->forw->op!=SXT && p->forw->op!=CFCC) { p->forw->back = p->back; p->back->forw = p->forw; redunm++; nchange++; continue; } } if (equstr(regs[RT1], "$0")) { p->op = CLR; strcpy(regs[RT1], regs[RT2]); regs[RT2][0] = 0; p->code = copy(1, regs[RT1]); nchange++; goto sngl; } repladdr(p, 0, flt); r = isreg(regs[RT1]); r1 = isreg(regs[RT2]); dest(regs[RT2], flt); if (r >= 0) if (r1 >= 0) savereg(r1+flt, regs[r+flt]); else savereg(r+flt, regs[RT2]); else if (r1 >= 0) savereg(r1+flt, regs[RT1]); else setcon(regs[RT1], regs[RT2]); source(regs[RT1]); setcc(regs[RT2]); continue; case ADDF: case SUBF: case DIVF: case MULF: flt = NREG; goto dble; case ADD: case SUB: case BIC: case BIS: case MUL: case DIV: case ASH: dble: dualop(p); if (p->op==BIC && (equstr(regs[RT1], "$-1") || equstr(regs[RT1], "$177777"))) { p->op = CLR; strcpy(regs[RT1], regs[RT2]); regs[RT2][0] = 0; p->code = copy(1, regs[RT1]); nchange++; goto sngl; } if ((p->op==BIC || p->op==BIS) && equstr(regs[RT1], "$0")) { if (p->forw->op!=CBR) { p->back->forw = p->forw; p->forw->back = p->back; nchange++; continue; } } /* * the next block of code looks for the sequences (which extract the * high byte of a word or the low byte respectively): * ash $-10,r * bic $-400,r * or * mov natural,r * bic $-400,r * and transforms them into: * clrb r * swab r * or * clr r * bisb natural,r * These constructs occur often enough in the kernel (dealing with major/minor * device numbers, etc) it's worth a little extra work at compile time. */ if (p->op == BIC && (equstr(regs[RT1],"$-400") || equstr(regs[RT1],"$-177400"))) { if (p->back->op == ASH) { r = isreg(regs[RT2]); dualop(p->back); if ((equstr(regs[RT1], "$-10") || equstr(regs[RT1], "$177770")) && r == isreg(regs[RT2])) { strcpy(regs[RT1], regs[RT2]); regs[RT2][0] = 0; p->back->op = CLR; p->back->subop = BYTE; p->back->code = copy(1, regs[RT1]); p->op = SWAB; p->code = copy(1, regs[RT1]); nchange++; goto sngl; } } else if (p->back->op == MOV && p->forw->op != CBR) { char temp[50]; r = isreg(regs[RT2]); if (r < 0 && !xnatural(regs[RT2])) goto out; strcpy(temp, regs[RT2]); dualop(p->back); if (isreg(regs[RT2]) == r && natural(regs[RT1])) { if (r < 0 && (!xnatural(regs[RT2]) || !equstr(temp, regs[RT2]))) goto out; /* * XXX - the sequence "movb rN,rN; bic $-400,rN" can not be transformed * because the 'clr' would lose all information about 'rN'. The best that can * be done is to remove the 'movb' instruction and leave the 'bic'. */ if (isreg(regs[RT1]) == r && r >= 0) { p = p->back; p->forw->back = p->back; p->back->forw = p->forw; nchange++; continue; } dest(regs[RT1], flt); p->back->op = CLR; p->back->subop = 0; p->back->code = copy(1, regs[RT2]); p->op = BIS; p->subop = BYTE; strcat(regs[RT1], ","); p->code = copy(2, regs[RT1], regs[RT2]); nchange++; } } out: dualop(p); /* restore banged up parsed operands */ } repladdr(p, 0, flt); source(regs[RT1]); dest(regs[RT2], flt); if (p->op==DIV && (r = isreg(regs[RT2]))>=0) regs[r|1][0] = 0; switch (p->op) { case ADD: case SUB: case BIC: case BIS: case ASH: setcc(regs[RT2]); break; default: ccloc[0] = 0; } continue; case SXT: singop(p); if (p->forw->op == CLR && p->forw->subop != BYTE && xnatural(regs[RT1]) && !strcmp(p->code, p->forw->code)){ p->forw->back = p->back; p->back->forw = p->forw; nchange++; continue; } goto sngl; case CLRF: case NEGF: flt = NREG; case CLR: case COM: case INC: case DEC: case NEG: case ASR: case ASL: case SWAB: singop(p); sngl: dest(regs[RT1], flt); if (p->op==CLR && flt==0) { if ((r = isreg(regs[RT1])) >= 0) savereg(r, "$0"); else setcon("$0", regs[RT1]); ccloc[0] = 0; } else setcc(regs[RT1]); continue; case TSTF: flt = NREG; case TST: singop(p); repladdr(p, 0, flt); source(regs[RT1]); if (p->back->op == TST && !flt && not_sp(regs[RT1])) { char rt1[MAXCPS + 2]; strcpy(rt1, regs[RT1]); singop(p->back); if (!strcmp("(sp)+", regs[RT1])) { p->back->subop = p->subop; p->back->forw = p->forw; p->forw->back = p->back; p = p->back; p->op = MOV; p->code = copy(2, rt1, ",(sp)+"); nrtst++; nchange++; continue; } singop(p); } if (p->back->op == MOV && p->back->subop == BYTE) { dualop(p->back); setcc(regs[RT2]); singop(p); } if (equstr(regs[RT1], ccloc) && p->subop == p->back->subop) { p->back->forw = p->forw; p->forw->back = p->back; p = p->back; nrtst++; nchange++; } else setcc(regs[RT1]); /* XXX - double TST in a row */ continue; case CMPF: flt = NREG; case CMP: case BIT: dualop(p); source(regs[RT1]); source(regs[RT2]); if(p->op==BIT) { if (equstr(regs[RT1], "$-1") || equstr(regs[RT1], "$177777")) { p->op = TST; strcpy(regs[RT1], regs[RT2]); regs[RT2][0] = 0; p->code = copy(1, regs[RT1]); nchange++; nsaddr++; } else if (equstr(regs[RT2], "$-1") || equstr(regs[RT2], "$177777")) { p->op = TST; regs[RT2][0] = 0; p->code = copy(1, regs[RT1]); nchange++; nsaddr++; } if (equstr(regs[RT1], "$0")) { p->op = TST; regs[RT2][0] = 0; p->code = copy(1, regs[RT1]); nchange++; nsaddr++; } else if (equstr(regs[RT2], "$0")) { p->op = TST; strcpy(regs[RT1], regs[RT2]); regs[RT2][0] = 0; p->code = copy(1, regs[RT1]); nchange++; nsaddr++; } } repladdr(p, 1, flt); ccloc[0] = 0; continue; case CBR: r = -1; if (p->back->op==TST || p->back->op==CMP) { if (p->back->op==TST) { singop(p->back); savereg(RT2, "$0"); } else dualop(p->back); if (equstr(regs[RT1], regs[RT2]) && natural(regs[RT1]) && natural(regs[RT2])) r = compare(p->subop, "$1", "$1"); else r = compare(p->subop, findcon(RT1), findcon(RT2)); if (r==0) { if (p->forw->op==CBR || p->forw->op==SXT || p->forw->op==CFCC) { p->back->forw = p->forw; p->forw->back = p->back; } else { p->back->back->forw = p->forw; p->forw->back = p->back->back; } decref(p->ref); p = p->back->back; nchange++; } else if (r>0) { p->op = JBR; p->subop = 0; p->back->back->forw = p; p->back = p->back->back; p = p->back; nchange++; } /* * If the instruction prior to the conditional branch was a 'tst' then * save the condition code status. The C construct: * if (x) * if (x > 0) * generates "tst _x; jeq ...; tst _x; jmi ...;jeq ...". The code below removes * the second "tst _x", leaving "tst _x; jeq ...;jmi ...; jeq ...". */ if (p->back->op == TST) { singop(p->back); setcc(regs[RT1]); break; } } /* * If the previous instruction was also a conditional branch then * attempt to merge the two into a single branch. */ if (p->back->op == CBR) fixupbr(p); case CFCC: ccloc[0] = 0; continue; /* * Unrecognized (unparsed) instructions, assignments (~foo=r2), and * data arrive here. In order to prevent throwing away information * about register contents just because a local assignment is done * we check for the first character being a tilde. */ case 0: if (p->code[0] != '~') clearreg(); continue; case JBR: redunbr(p); default: clearreg(); } } }