|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)hardexp.c 1.1 86/02/03 Copyr 1985 Sun Micro"; ! 3: #endif ! 4: ! 5: /* ! 6: * Copyright (c) 1985 by Sun Microsystems, Inc. ! 7: */ ! 8: ! 9: #include "as.h" ! 10: #include "c2.h" ! 11: ! 12: extern struct oper * newoperand(); ! 13: extern struct optree * newtree(); ! 14: ! 15: void ! 16: ocomplex( operation, subop1, subop2 ) ! 17: char operation; ! 18: struct oper * subop1, *subop2; ! 19: { ! 20: register struct optree *otp; ! 21: otp = newtree(); ! 22: otp->left_t = newoperand( subop1 ); ! 23: otp->right_t = subop2 ? newoperand( subop2 ) : NULL; ! 24: otp->op_t = operation; ! 25: subop1->sym_o = (struct sym_bkt *)otp; ! 26: subop1->flags_o |= O_COMPLEX; ! 27: } ! 28: ! 29: ! 30: static void ! 31: valcomplex( op ) ! 32: struct oper *op; ! 33: { ! 34: register struct optree *tp; ! 35: register struct oper *r, *l; ! 36: register int * vp; ! 37: struct sym_bkt *sp; ! 38: int operation; ! 39: vp = (op->type_o == T_INDEX) ? &op->disp_o : &op->value_o; ! 40: if (op->flags_o&O_COMPLEX){ ! 41: tp = (struct optree *)op->sym_o; ! 42: operation = tp->op_t; ! 43: l = tp->left_t ; ! 44: valcomplex( l ); ! 45: if ((r=tp->right_t) == NULL) ! 46: operation = -operation; /* so we can tell unary SUB from binary */ ! 47: else ! 48: valcomplex( r ); ! 49: if (l->sym_o || (r && r->sym_o)) { ! 50: if ( operation == SUB ! 51: && !(l->flags_o&O_COMPLEX) && !(r->flags_o&O_COMPLEX) ! 52: && l->sym_o->csect_s == r->sym_o->csect_s ! 53: && l->sym_o->csect_s != C_TEXT ! 54: && l->sym_o->attr_s&S_DEF && r->sym_o->attr_s&S_DEF ! 55: && l->sym_o->value_s >= 0 && r->sym_o->value_s >= 0 ){ ! 56: /* ! 57: * special case: it is ok to subtract two symbols in data ! 58: * space, as long as we know their values. ! 59: */ ! 60: *vp = l->sym_o->value_s - r->sym_o->value_s; ! 61: goto uncomplex; ! 62: } ! 63: return; ! 64: } ! 65: switch( operation ){ ! 66: case ADD: *vp = l->value_o + r->value_o; break; ! 67: case SUB: *vp = l->value_o - r->value_o; break; ! 68: case MUL: *vp = l->value_o * r->value_o; break; ! 69: case DIV: *vp = l->value_o / r->value_o; break; ! 70: case -SUB: *vp = - l->value_o; break; ! 71: case -NOT: *vp = ~ l->value_o; break; ! 72: } ! 73: uncomplex: ! 74: op->flags_o &= ~O_COMPLEX; ! 75: op->sym_o = NULL; ! 76: if (op->type_o == T_INDEX ! 77: && !(op->flags_o&(O_INDIRECT|O_BSUPRESS|O_PREINDEX|O_POSTINDEX)) ! 78: && op->disp_o >= -32768 && op->disp_o <= 32767) { ! 79: /* a T_DISPL disguised as a T_INDEX */ ! 80: op->type_o = T_DISPL; ! 81: op->value_o = op->disp_o; ! 82: op->disp_o = 0; ! 83: } ! 84: freeoperand(l); ! 85: freeoperand(r); ! 86: freetree(tp); ! 87: } else { ! 88: if ( op->sym_o == NULL ) return ; ! 89: sp = op->sym_o; ! 90: if ((sp->attr_s & S_DEF) == 0) return ; ! 91: if ( sp->csect_s == C_UNDEF ) { ! 92: *vp += sp->value_s; ! 93: op->sym_o = NULL; ! 94: } ! 95: } ! 96: return ; ! 97: } ! 98: ! 99: ! 100: void ! 101: rectify() ! 102: { ! 103: /* look at all operands. Try to fix up the complex ones */ ! 104: register NODE *np; ! 105: register struct oper *op; ! 106: register struct optree *tp; ! 107: register opno, nops; ! 108: struct sym_bkt * sp; ! 109: short m; ! 110: ! 111: for (np=first.forw; np!= &first; np = np->forw){ ! 112: if (np->op==OP_LABEL){ ! 113: np->nref = np->name->nuse_s; ! 114: continue; ! 115: } ! 116: nops = np->nref; ! 117: for (opno=0; opno<nops; opno++){ ! 118: op = np->ref[opno]; ! 119: if (op->flags_o&O_COMPLEX || op->sym_o) ! 120: valcomplex( op ); ! 121: } ! 122: switch( np->op){ ! 123: case OP_BRANCH: ! 124: case OP_DBRA: ! 125: if (op->type_o==T_NORMAL && ! 126: !(op->flags_o&O_COMPLEX) && op->value_o==0 ){ ! 127: /* make jump references point right at the label node */ ! 128: sp = op->sym_o; ! 129: if (sp->attr_s&S_DEF && sp->csect_s == C_TEXT){ ! 130: np->luse = sp->where_s; ! 131: np->lnext = np->luse->luse; ! 132: np->luse->luse = np; ! 133: switch( np->op){ ! 134: case OP_BRANCH: np->op = OP_JUMP; break; ! 135: case OP_DBRA: np->op = OP_DJMP; break; ! 136: } ! 137: freeoperand(op); ! 138: np->nref--; ! 139: continue; ! 140: } ! 141: } ! 142: break; ! 143: case OP_MOVEM: ! 144: /* try to fix up register use mask */ ! 145: np->ruse = addmask( np->ruse, movemmask( np->subop, RMASK, np->ref )); ! 146: np->rset = addmask( np->rset, movemmask( np->subop, WMASK, np->ref )); ! 147: break; ! 148: case OP_MOVE: ! 149: /* ! 150: * look for set pattern: ! 151: * movw pc@(6,d?:w),d0 ! 152: * jmp pc@(2,d0:w) ! 153: * Lnnn: ! 154: * .word Lyyy-Lnnn ! 155: * : : ! 156: * : : ! 157: * This is a C-style switch. ! 158: * When we find one of these, we want to treat it specially, ! 159: * so that flow-analysis will recognize it as a multi-way ! 160: * branch, and not as an unknown branch. So: ! 161: * Make the jmp instruction a OP_JUMP, JIND op/subop; ! 162: * Make the .word pseudoops OP_CSWITCH, and make them ! 163: * reference Lyyy like branches reference their labels. ! 164: */ ! 165: /* make sure we recognize the set pattern */ ! 166: if (np->subop!=SUBOP_W ! 167: || (op=np->ref[0])->type_o!= T_INDEX || op->reg_o != PCREG ! 168: || op->disp_o!=6 || op->value_o>=A0REG ! 169: || (op=np->ref[1])->type_o!= T_REG || op->value_o != D0REG) ! 170: break; ! 171: np = np->forw; ! 172: if (np->op!=OP_BRANCH || (op=np->ref[0])->type_o!=T_INDEX ! 173: || op->reg_o!=PCREG || op->disp_o!=2 || op->value_o!=D0REG ! 174: || op->flags_o!=(O_WINDEX|O_PREINDEX) ) ! 175: break; ! 176: /* following operand must be label */ ! 177: if (np->forw->op!=OP_LABEL) ! 178: break; ! 179: /* all looks good: fiddle the jmp instruction */ ! 180: np->op = OP_JUMP; ! 181: np->subop = JIND; ! 182: freeoperand( op ); ! 183: newreference( np->forw, np); ! 184: np->nref=0; ! 185: np = np->forw; ! 186: np->nref += np->name->nuse_s; ! 187: np= np->forw; ! 188: while (np->op==OP_WORD){ ! 189: int i; ! 190: register NODE *csw; ! 191: NODE *next; ! 192: np->op = OP_CSWITCH; ! 193: next = np->forw; ! 194: for (i=0; i<np->nref; i++){ ! 195: op = np->ref[i]; ! 196: if (!(op->flags_o&O_COMPLEX)) continue; /* trouble */ ! 197: /* CSWITCH can handle only one operand */ ! 198: if (i>0){ ! 199: /* this will never happen */ ! 200: csw = new(); ! 201: csw->back = next->back; ! 202: csw->back->forw = next->back = csw; ! 203: csw->forw=next; ! 204: csw->op = OP_CSWITCH; ! 205: csw->instr = np->instr; ! 206: csw->nref = 0; ! 207: } else { ! 208: csw = np; ! 209: } ! 210: tp = (struct optree *)op->sym_o; ! 211: freeoperand( tp->right_t ); ! 212: csw->luse = tp->left_t->sym_o->where_s; ! 213: csw->lnext = csw->luse->luse; ! 214: csw->luse->luse = csw; ! 215: freeoperand( tp->left_t ); ! 216: freetree( tp ); ! 217: } ! 218: np->nref = 0; ! 219: np = next; ! 220: } ! 221: np=np->back; /* so the for-loop increment will do the right thing */ ! 222: break; ! 223: } ! 224: } ! 225: if (first.forw != first.back){ ! 226: /* ! 227: * if this routine is non-empty, then we want to make sure that ! 228: * its entry-point has at least one reference. Most routines get ! 229: * this through the .globl pseudo-op, but class static routine ! 230: * will not. Thus we make sure here. ! 231: */ ! 232: for (np=first.forw; np != &first ; np=np->forw ) ! 233: if (np->op == OP_LABEL ){ ! 234: np->nref++; ! 235: break; ! 236: } ! 237: } ! 238: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.