|
|
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.