1*b370703fSCharles.Forsyth #include "gc.h"
2*b370703fSCharles.Forsyth
3*b370703fSCharles.Forsyth static int
needc(Prog * p)4*b370703fSCharles.Forsyth needc(Prog *p)
5*b370703fSCharles.Forsyth {
6*b370703fSCharles.Forsyth while(p != P) {
7*b370703fSCharles.Forsyth switch(p->as) {
8*b370703fSCharles.Forsyth case AADCL:
9*b370703fSCharles.Forsyth case AADCQ:
10*b370703fSCharles.Forsyth case ASBBL:
11*b370703fSCharles.Forsyth case ASBBQ:
12*b370703fSCharles.Forsyth case ARCRL:
13*b370703fSCharles.Forsyth case ARCRQ:
14*b370703fSCharles.Forsyth return 1;
15*b370703fSCharles.Forsyth case AADDL:
16*b370703fSCharles.Forsyth case AADDQ:
17*b370703fSCharles.Forsyth case ASUBL:
18*b370703fSCharles.Forsyth case ASUBQ:
19*b370703fSCharles.Forsyth case AJMP:
20*b370703fSCharles.Forsyth case ARET:
21*b370703fSCharles.Forsyth case ACALL:
22*b370703fSCharles.Forsyth return 0;
23*b370703fSCharles.Forsyth default:
24*b370703fSCharles.Forsyth if(p->to.type == D_BRANCH)
25*b370703fSCharles.Forsyth return 0;
26*b370703fSCharles.Forsyth }
27*b370703fSCharles.Forsyth p = p->link;
28*b370703fSCharles.Forsyth }
29*b370703fSCharles.Forsyth return 0;
30*b370703fSCharles.Forsyth }
31*b370703fSCharles.Forsyth
32*b370703fSCharles.Forsyth static Reg*
rnops(Reg * r)33*b370703fSCharles.Forsyth rnops(Reg *r)
34*b370703fSCharles.Forsyth {
35*b370703fSCharles.Forsyth Prog *p;
36*b370703fSCharles.Forsyth Reg *r1;
37*b370703fSCharles.Forsyth
38*b370703fSCharles.Forsyth if(r != R)
39*b370703fSCharles.Forsyth for(;;){
40*b370703fSCharles.Forsyth p = r->prog;
41*b370703fSCharles.Forsyth if(p->as != ANOP || p->from.type != D_NONE || p->to.type != D_NONE)
42*b370703fSCharles.Forsyth break;
43*b370703fSCharles.Forsyth r1 = uniqs(r);
44*b370703fSCharles.Forsyth if(r1 == R)
45*b370703fSCharles.Forsyth break;
46*b370703fSCharles.Forsyth r = r1;
47*b370703fSCharles.Forsyth }
48*b370703fSCharles.Forsyth return r;
49*b370703fSCharles.Forsyth }
50*b370703fSCharles.Forsyth
51*b370703fSCharles.Forsyth void
peep(void)52*b370703fSCharles.Forsyth peep(void)
53*b370703fSCharles.Forsyth {
54*b370703fSCharles.Forsyth Reg *r, *r1, *r2;
55*b370703fSCharles.Forsyth Prog *p, *p1;
56*b370703fSCharles.Forsyth int t;
57*b370703fSCharles.Forsyth
58*b370703fSCharles.Forsyth /*
59*b370703fSCharles.Forsyth * complete R structure
60*b370703fSCharles.Forsyth */
61*b370703fSCharles.Forsyth t = 0;
62*b370703fSCharles.Forsyth for(r=firstr; r!=R; r=r1) {
63*b370703fSCharles.Forsyth r1 = r->link;
64*b370703fSCharles.Forsyth if(r1 == R)
65*b370703fSCharles.Forsyth break;
66*b370703fSCharles.Forsyth p = r->prog->link;
67*b370703fSCharles.Forsyth while(p != r1->prog)
68*b370703fSCharles.Forsyth switch(p->as) {
69*b370703fSCharles.Forsyth default:
70*b370703fSCharles.Forsyth r2 = rega();
71*b370703fSCharles.Forsyth r->link = r2;
72*b370703fSCharles.Forsyth r2->link = r1;
73*b370703fSCharles.Forsyth
74*b370703fSCharles.Forsyth r2->prog = p;
75*b370703fSCharles.Forsyth r2->p1 = r;
76*b370703fSCharles.Forsyth r->s1 = r2;
77*b370703fSCharles.Forsyth r2->s1 = r1;
78*b370703fSCharles.Forsyth r1->p1 = r2;
79*b370703fSCharles.Forsyth
80*b370703fSCharles.Forsyth r = r2;
81*b370703fSCharles.Forsyth t++;
82*b370703fSCharles.Forsyth
83*b370703fSCharles.Forsyth case ADATA:
84*b370703fSCharles.Forsyth case AGLOBL:
85*b370703fSCharles.Forsyth case ANAME:
86*b370703fSCharles.Forsyth case ASIGNAME:
87*b370703fSCharles.Forsyth p = p->link;
88*b370703fSCharles.Forsyth }
89*b370703fSCharles.Forsyth }
90*b370703fSCharles.Forsyth
91*b370703fSCharles.Forsyth pc = 0; /* speculating it won't kill */
92*b370703fSCharles.Forsyth
93*b370703fSCharles.Forsyth loop1:
94*b370703fSCharles.Forsyth
95*b370703fSCharles.Forsyth t = 0;
96*b370703fSCharles.Forsyth for(r=firstr; r!=R; r=r->link) {
97*b370703fSCharles.Forsyth p = r->prog;
98*b370703fSCharles.Forsyth switch(p->as) {
99*b370703fSCharles.Forsyth case AMOVL:
100*b370703fSCharles.Forsyth case AMOVQ:
101*b370703fSCharles.Forsyth case AMOVSS:
102*b370703fSCharles.Forsyth case AMOVSD:
103*b370703fSCharles.Forsyth if(regtyp(&p->to))
104*b370703fSCharles.Forsyth if(regtyp(&p->from)) {
105*b370703fSCharles.Forsyth if(copyprop(r)) {
106*b370703fSCharles.Forsyth excise(r);
107*b370703fSCharles.Forsyth t++;
108*b370703fSCharles.Forsyth } else
109*b370703fSCharles.Forsyth if(subprop(r) && copyprop(r)) {
110*b370703fSCharles.Forsyth excise(r);
111*b370703fSCharles.Forsyth t++;
112*b370703fSCharles.Forsyth }
113*b370703fSCharles.Forsyth }
114*b370703fSCharles.Forsyth break;
115*b370703fSCharles.Forsyth
116*b370703fSCharles.Forsyth case AMOVBLZX:
117*b370703fSCharles.Forsyth case AMOVWLZX:
118*b370703fSCharles.Forsyth case AMOVBLSX:
119*b370703fSCharles.Forsyth case AMOVWLSX:
120*b370703fSCharles.Forsyth if(regtyp(&p->to)) {
121*b370703fSCharles.Forsyth r1 = rnops(uniqs(r));
122*b370703fSCharles.Forsyth if(r1 != R) {
123*b370703fSCharles.Forsyth p1 = r1->prog;
124*b370703fSCharles.Forsyth if(p->as == p1->as && p->to.type == p1->from.type){
125*b370703fSCharles.Forsyth p1->as = AMOVL;
126*b370703fSCharles.Forsyth t++;
127*b370703fSCharles.Forsyth }
128*b370703fSCharles.Forsyth }
129*b370703fSCharles.Forsyth }
130*b370703fSCharles.Forsyth break;
131*b370703fSCharles.Forsyth
132*b370703fSCharles.Forsyth case AMOVBQSX:
133*b370703fSCharles.Forsyth case AMOVBQZX:
134*b370703fSCharles.Forsyth case AMOVWQSX:
135*b370703fSCharles.Forsyth case AMOVWQZX:
136*b370703fSCharles.Forsyth case AMOVLQSX:
137*b370703fSCharles.Forsyth case AMOVLQZX:
138*b370703fSCharles.Forsyth if(regtyp(&p->to)) {
139*b370703fSCharles.Forsyth r1 = rnops(uniqs(r));
140*b370703fSCharles.Forsyth if(r1 != R) {
141*b370703fSCharles.Forsyth p1 = r1->prog;
142*b370703fSCharles.Forsyth if(p->as == p1->as && p->to.type == p1->from.type){
143*b370703fSCharles.Forsyth p1->as = AMOVQ;
144*b370703fSCharles.Forsyth t++;
145*b370703fSCharles.Forsyth }
146*b370703fSCharles.Forsyth }
147*b370703fSCharles.Forsyth }
148*b370703fSCharles.Forsyth break;
149*b370703fSCharles.Forsyth
150*b370703fSCharles.Forsyth case AADDL:
151*b370703fSCharles.Forsyth case AADDQ:
152*b370703fSCharles.Forsyth case AADDW:
153*b370703fSCharles.Forsyth if(p->from.type != D_CONST || needc(p->link))
154*b370703fSCharles.Forsyth break;
155*b370703fSCharles.Forsyth if(p->from.offset == -1){
156*b370703fSCharles.Forsyth if(p->as == AADDQ)
157*b370703fSCharles.Forsyth p->as = ADECQ;
158*b370703fSCharles.Forsyth else if(p->as == AADDL)
159*b370703fSCharles.Forsyth p->as = ADECL;
160*b370703fSCharles.Forsyth else
161*b370703fSCharles.Forsyth p->as = ADECW;
162*b370703fSCharles.Forsyth p->from = zprog.from;
163*b370703fSCharles.Forsyth }
164*b370703fSCharles.Forsyth else if(p->from.offset == 1){
165*b370703fSCharles.Forsyth if(p->as == AADDQ)
166*b370703fSCharles.Forsyth p->as = AINCQ;
167*b370703fSCharles.Forsyth else if(p->as == AADDL)
168*b370703fSCharles.Forsyth p->as = AINCL;
169*b370703fSCharles.Forsyth else
170*b370703fSCharles.Forsyth p->as = AINCW;
171*b370703fSCharles.Forsyth p->from = zprog.from;
172*b370703fSCharles.Forsyth }
173*b370703fSCharles.Forsyth break;
174*b370703fSCharles.Forsyth
175*b370703fSCharles.Forsyth case ASUBL:
176*b370703fSCharles.Forsyth case ASUBQ:
177*b370703fSCharles.Forsyth case ASUBW:
178*b370703fSCharles.Forsyth if(p->from.type != D_CONST || needc(p->link))
179*b370703fSCharles.Forsyth break;
180*b370703fSCharles.Forsyth if(p->from.offset == -1) {
181*b370703fSCharles.Forsyth if(p->as == ASUBQ)
182*b370703fSCharles.Forsyth p->as = AINCQ;
183*b370703fSCharles.Forsyth else if(p->as == ASUBL)
184*b370703fSCharles.Forsyth p->as = AINCL;
185*b370703fSCharles.Forsyth else
186*b370703fSCharles.Forsyth p->as = AINCW;
187*b370703fSCharles.Forsyth p->from = zprog.from;
188*b370703fSCharles.Forsyth }
189*b370703fSCharles.Forsyth else if(p->from.offset == 1){
190*b370703fSCharles.Forsyth if(p->as == ASUBQ)
191*b370703fSCharles.Forsyth p->as = ADECQ;
192*b370703fSCharles.Forsyth else if(p->as == ASUBL)
193*b370703fSCharles.Forsyth p->as = ADECL;
194*b370703fSCharles.Forsyth else
195*b370703fSCharles.Forsyth p->as = ADECW;
196*b370703fSCharles.Forsyth p->from = zprog.from;
197*b370703fSCharles.Forsyth }
198*b370703fSCharles.Forsyth break;
199*b370703fSCharles.Forsyth }
200*b370703fSCharles.Forsyth }
201*b370703fSCharles.Forsyth if(t)
202*b370703fSCharles.Forsyth goto loop1;
203*b370703fSCharles.Forsyth }
204*b370703fSCharles.Forsyth
205*b370703fSCharles.Forsyth void
excise(Reg * r)206*b370703fSCharles.Forsyth excise(Reg *r)
207*b370703fSCharles.Forsyth {
208*b370703fSCharles.Forsyth Prog *p;
209*b370703fSCharles.Forsyth
210*b370703fSCharles.Forsyth p = r->prog;
211*b370703fSCharles.Forsyth p->as = ANOP;
212*b370703fSCharles.Forsyth p->from = zprog.from;
213*b370703fSCharles.Forsyth p->to = zprog.to;
214*b370703fSCharles.Forsyth }
215*b370703fSCharles.Forsyth
216*b370703fSCharles.Forsyth Reg*
uniqp(Reg * r)217*b370703fSCharles.Forsyth uniqp(Reg *r)
218*b370703fSCharles.Forsyth {
219*b370703fSCharles.Forsyth Reg *r1;
220*b370703fSCharles.Forsyth
221*b370703fSCharles.Forsyth r1 = r->p1;
222*b370703fSCharles.Forsyth if(r1 == R) {
223*b370703fSCharles.Forsyth r1 = r->p2;
224*b370703fSCharles.Forsyth if(r1 == R || r1->p2link != R)
225*b370703fSCharles.Forsyth return R;
226*b370703fSCharles.Forsyth } else
227*b370703fSCharles.Forsyth if(r->p2 != R)
228*b370703fSCharles.Forsyth return R;
229*b370703fSCharles.Forsyth return r1;
230*b370703fSCharles.Forsyth }
231*b370703fSCharles.Forsyth
232*b370703fSCharles.Forsyth Reg*
uniqs(Reg * r)233*b370703fSCharles.Forsyth uniqs(Reg *r)
234*b370703fSCharles.Forsyth {
235*b370703fSCharles.Forsyth Reg *r1;
236*b370703fSCharles.Forsyth
237*b370703fSCharles.Forsyth r1 = r->s1;
238*b370703fSCharles.Forsyth if(r1 == R) {
239*b370703fSCharles.Forsyth r1 = r->s2;
240*b370703fSCharles.Forsyth if(r1 == R)
241*b370703fSCharles.Forsyth return R;
242*b370703fSCharles.Forsyth } else
243*b370703fSCharles.Forsyth if(r->s2 != R)
244*b370703fSCharles.Forsyth return R;
245*b370703fSCharles.Forsyth return r1;
246*b370703fSCharles.Forsyth }
247*b370703fSCharles.Forsyth
248*b370703fSCharles.Forsyth int
regtyp(Adr * a)249*b370703fSCharles.Forsyth regtyp(Adr *a)
250*b370703fSCharles.Forsyth {
251*b370703fSCharles.Forsyth int t;
252*b370703fSCharles.Forsyth
253*b370703fSCharles.Forsyth t = a->type;
254*b370703fSCharles.Forsyth if(t >= D_AX && t <= D_R15)
255*b370703fSCharles.Forsyth return 1;
256*b370703fSCharles.Forsyth if(t >= D_X0 && t <= D_X0+15)
257*b370703fSCharles.Forsyth return 1;
258*b370703fSCharles.Forsyth return 0;
259*b370703fSCharles.Forsyth }
260*b370703fSCharles.Forsyth
261*b370703fSCharles.Forsyth /*
262*b370703fSCharles.Forsyth * the idea is to substitute
263*b370703fSCharles.Forsyth * one register for another
264*b370703fSCharles.Forsyth * from one MOV to another
265*b370703fSCharles.Forsyth * MOV a, R0
266*b370703fSCharles.Forsyth * ADD b, R0 / no use of R1
267*b370703fSCharles.Forsyth * MOV R0, R1
268*b370703fSCharles.Forsyth * would be converted to
269*b370703fSCharles.Forsyth * MOV a, R1
270*b370703fSCharles.Forsyth * ADD b, R1
271*b370703fSCharles.Forsyth * MOV R1, R0
272*b370703fSCharles.Forsyth * hopefully, then the former or latter MOV
273*b370703fSCharles.Forsyth * will be eliminated by copy propagation.
274*b370703fSCharles.Forsyth */
275*b370703fSCharles.Forsyth int
subprop(Reg * r0)276*b370703fSCharles.Forsyth subprop(Reg *r0)
277*b370703fSCharles.Forsyth {
278*b370703fSCharles.Forsyth Prog *p;
279*b370703fSCharles.Forsyth Adr *v1, *v2;
280*b370703fSCharles.Forsyth Reg *r;
281*b370703fSCharles.Forsyth int t;
282*b370703fSCharles.Forsyth
283*b370703fSCharles.Forsyth p = r0->prog;
284*b370703fSCharles.Forsyth v1 = &p->from;
285*b370703fSCharles.Forsyth if(!regtyp(v1))
286*b370703fSCharles.Forsyth return 0;
287*b370703fSCharles.Forsyth v2 = &p->to;
288*b370703fSCharles.Forsyth if(!regtyp(v2))
289*b370703fSCharles.Forsyth return 0;
290*b370703fSCharles.Forsyth for(r=uniqp(r0); r!=R; r=uniqp(r)) {
291*b370703fSCharles.Forsyth if(uniqs(r) == R)
292*b370703fSCharles.Forsyth break;
293*b370703fSCharles.Forsyth p = r->prog;
294*b370703fSCharles.Forsyth switch(p->as) {
295*b370703fSCharles.Forsyth case ACALL:
296*b370703fSCharles.Forsyth return 0;
297*b370703fSCharles.Forsyth
298*b370703fSCharles.Forsyth case AIMULL:
299*b370703fSCharles.Forsyth case AIMULQ:
300*b370703fSCharles.Forsyth case AIMULW:
301*b370703fSCharles.Forsyth if(p->to.type != D_NONE)
302*b370703fSCharles.Forsyth break;
303*b370703fSCharles.Forsyth
304*b370703fSCharles.Forsyth case ADIVB:
305*b370703fSCharles.Forsyth case ADIVL:
306*b370703fSCharles.Forsyth case ADIVQ:
307*b370703fSCharles.Forsyth case ADIVW:
308*b370703fSCharles.Forsyth case AIDIVB:
309*b370703fSCharles.Forsyth case AIDIVL:
310*b370703fSCharles.Forsyth case AIDIVQ:
311*b370703fSCharles.Forsyth case AIDIVW:
312*b370703fSCharles.Forsyth case AIMULB:
313*b370703fSCharles.Forsyth case AMULB:
314*b370703fSCharles.Forsyth case AMULL:
315*b370703fSCharles.Forsyth case AMULQ:
316*b370703fSCharles.Forsyth case AMULW:
317*b370703fSCharles.Forsyth
318*b370703fSCharles.Forsyth case AROLB:
319*b370703fSCharles.Forsyth case AROLL:
320*b370703fSCharles.Forsyth case AROLQ:
321*b370703fSCharles.Forsyth case AROLW:
322*b370703fSCharles.Forsyth case ARORB:
323*b370703fSCharles.Forsyth case ARORL:
324*b370703fSCharles.Forsyth case ARORQ:
325*b370703fSCharles.Forsyth case ARORW:
326*b370703fSCharles.Forsyth case ASALB:
327*b370703fSCharles.Forsyth case ASALL:
328*b370703fSCharles.Forsyth case ASALQ:
329*b370703fSCharles.Forsyth case ASALW:
330*b370703fSCharles.Forsyth case ASARB:
331*b370703fSCharles.Forsyth case ASARL:
332*b370703fSCharles.Forsyth case ASARQ:
333*b370703fSCharles.Forsyth case ASARW:
334*b370703fSCharles.Forsyth case ASHLB:
335*b370703fSCharles.Forsyth case ASHLL:
336*b370703fSCharles.Forsyth case ASHLQ:
337*b370703fSCharles.Forsyth case ASHLW:
338*b370703fSCharles.Forsyth case ASHRB:
339*b370703fSCharles.Forsyth case ASHRL:
340*b370703fSCharles.Forsyth case ASHRQ:
341*b370703fSCharles.Forsyth case ASHRW:
342*b370703fSCharles.Forsyth
343*b370703fSCharles.Forsyth case AREP:
344*b370703fSCharles.Forsyth case AREPN:
345*b370703fSCharles.Forsyth
346*b370703fSCharles.Forsyth case ACWD:
347*b370703fSCharles.Forsyth case ACDQ:
348*b370703fSCharles.Forsyth case ACQO:
349*b370703fSCharles.Forsyth
350*b370703fSCharles.Forsyth case AMOVSL:
351*b370703fSCharles.Forsyth case AMOVSQ:
352*b370703fSCharles.Forsyth return 0;
353*b370703fSCharles.Forsyth
354*b370703fSCharles.Forsyth case AMOVL:
355*b370703fSCharles.Forsyth case AMOVQ:
356*b370703fSCharles.Forsyth if(p->to.type == v1->type)
357*b370703fSCharles.Forsyth goto gotit;
358*b370703fSCharles.Forsyth break;
359*b370703fSCharles.Forsyth }
360*b370703fSCharles.Forsyth if(copyau(&p->from, v2) ||
361*b370703fSCharles.Forsyth copyau(&p->to, v2))
362*b370703fSCharles.Forsyth break;
363*b370703fSCharles.Forsyth if(copysub(&p->from, v1, v2, 0) ||
364*b370703fSCharles.Forsyth copysub(&p->to, v1, v2, 0))
365*b370703fSCharles.Forsyth break;
366*b370703fSCharles.Forsyth }
367*b370703fSCharles.Forsyth return 0;
368*b370703fSCharles.Forsyth
369*b370703fSCharles.Forsyth gotit:
370*b370703fSCharles.Forsyth copysub(&p->to, v1, v2, 1);
371*b370703fSCharles.Forsyth if(debug['P']) {
372*b370703fSCharles.Forsyth print("gotit: %D->%D\n%P", v1, v2, r->prog);
373*b370703fSCharles.Forsyth if(p->from.type == v2->type)
374*b370703fSCharles.Forsyth print(" excise");
375*b370703fSCharles.Forsyth print("\n");
376*b370703fSCharles.Forsyth }
377*b370703fSCharles.Forsyth for(r=uniqs(r); r!=r0; r=uniqs(r)) {
378*b370703fSCharles.Forsyth p = r->prog;
379*b370703fSCharles.Forsyth copysub(&p->from, v1, v2, 1);
380*b370703fSCharles.Forsyth copysub(&p->to, v1, v2, 1);
381*b370703fSCharles.Forsyth if(debug['P'])
382*b370703fSCharles.Forsyth print("%P\n", r->prog);
383*b370703fSCharles.Forsyth }
384*b370703fSCharles.Forsyth t = v1->type;
385*b370703fSCharles.Forsyth v1->type = v2->type;
386*b370703fSCharles.Forsyth v2->type = t;
387*b370703fSCharles.Forsyth if(debug['P'])
388*b370703fSCharles.Forsyth print("%P last\n", r->prog);
389*b370703fSCharles.Forsyth return 1;
390*b370703fSCharles.Forsyth }
391*b370703fSCharles.Forsyth
392*b370703fSCharles.Forsyth /*
393*b370703fSCharles.Forsyth * The idea is to remove redundant copies.
394*b370703fSCharles.Forsyth * v1->v2 F=0
395*b370703fSCharles.Forsyth * (use v2 s/v2/v1/)*
396*b370703fSCharles.Forsyth * set v1 F=1
397*b370703fSCharles.Forsyth * use v2 return fail
398*b370703fSCharles.Forsyth * -----------------
399*b370703fSCharles.Forsyth * v1->v2 F=0
400*b370703fSCharles.Forsyth * (use v2 s/v2/v1/)*
401*b370703fSCharles.Forsyth * set v1 F=1
402*b370703fSCharles.Forsyth * set v2 return success
403*b370703fSCharles.Forsyth */
404*b370703fSCharles.Forsyth int
copyprop(Reg * r0)405*b370703fSCharles.Forsyth copyprop(Reg *r0)
406*b370703fSCharles.Forsyth {
407*b370703fSCharles.Forsyth Prog *p;
408*b370703fSCharles.Forsyth Adr *v1, *v2;
409*b370703fSCharles.Forsyth Reg *r;
410*b370703fSCharles.Forsyth
411*b370703fSCharles.Forsyth p = r0->prog;
412*b370703fSCharles.Forsyth v1 = &p->from;
413*b370703fSCharles.Forsyth v2 = &p->to;
414*b370703fSCharles.Forsyth if(copyas(v1, v2))
415*b370703fSCharles.Forsyth return 1;
416*b370703fSCharles.Forsyth for(r=firstr; r!=R; r=r->link)
417*b370703fSCharles.Forsyth r->active = 0;
418*b370703fSCharles.Forsyth return copy1(v1, v2, r0->s1, 0);
419*b370703fSCharles.Forsyth }
420*b370703fSCharles.Forsyth
421*b370703fSCharles.Forsyth int
copy1(Adr * v1,Adr * v2,Reg * r,int f)422*b370703fSCharles.Forsyth copy1(Adr *v1, Adr *v2, Reg *r, int f)
423*b370703fSCharles.Forsyth {
424*b370703fSCharles.Forsyth int t;
425*b370703fSCharles.Forsyth Prog *p;
426*b370703fSCharles.Forsyth
427*b370703fSCharles.Forsyth if(r->active) {
428*b370703fSCharles.Forsyth if(debug['P'])
429*b370703fSCharles.Forsyth print("act set; return 1\n");
430*b370703fSCharles.Forsyth return 1;
431*b370703fSCharles.Forsyth }
432*b370703fSCharles.Forsyth r->active = 1;
433*b370703fSCharles.Forsyth if(debug['P'])
434*b370703fSCharles.Forsyth print("copy %D->%D f=%d\n", v1, v2, f);
435*b370703fSCharles.Forsyth for(; r != R; r = r->s1) {
436*b370703fSCharles.Forsyth p = r->prog;
437*b370703fSCharles.Forsyth if(debug['P'])
438*b370703fSCharles.Forsyth print("%P", p);
439*b370703fSCharles.Forsyth if(!f && uniqp(r) == R) {
440*b370703fSCharles.Forsyth f = 1;
441*b370703fSCharles.Forsyth if(debug['P'])
442*b370703fSCharles.Forsyth print("; merge; f=%d", f);
443*b370703fSCharles.Forsyth }
444*b370703fSCharles.Forsyth t = copyu(p, v2, A);
445*b370703fSCharles.Forsyth switch(t) {
446*b370703fSCharles.Forsyth case 2: /* rar, cant split */
447*b370703fSCharles.Forsyth if(debug['P'])
448*b370703fSCharles.Forsyth print("; %D rar; return 0\n", v2);
449*b370703fSCharles.Forsyth return 0;
450*b370703fSCharles.Forsyth
451*b370703fSCharles.Forsyth case 3: /* set */
452*b370703fSCharles.Forsyth if(debug['P'])
453*b370703fSCharles.Forsyth print("; %D set; return 1\n", v2);
454*b370703fSCharles.Forsyth return 1;
455*b370703fSCharles.Forsyth
456*b370703fSCharles.Forsyth case 1: /* used, substitute */
457*b370703fSCharles.Forsyth case 4: /* use and set */
458*b370703fSCharles.Forsyth if(f) {
459*b370703fSCharles.Forsyth if(!debug['P'])
460*b370703fSCharles.Forsyth return 0;
461*b370703fSCharles.Forsyth if(t == 4)
462*b370703fSCharles.Forsyth print("; %D used+set and f=%d; return 0\n", v2, f);
463*b370703fSCharles.Forsyth else
464*b370703fSCharles.Forsyth print("; %D used and f=%d; return 0\n", v2, f);
465*b370703fSCharles.Forsyth return 0;
466*b370703fSCharles.Forsyth }
467*b370703fSCharles.Forsyth if(copyu(p, v2, v1)) {
468*b370703fSCharles.Forsyth if(debug['P'])
469*b370703fSCharles.Forsyth print("; sub fail; return 0\n");
470*b370703fSCharles.Forsyth return 0;
471*b370703fSCharles.Forsyth }
472*b370703fSCharles.Forsyth if(debug['P'])
473*b370703fSCharles.Forsyth print("; sub %D/%D", v2, v1);
474*b370703fSCharles.Forsyth if(t == 4) {
475*b370703fSCharles.Forsyth if(debug['P'])
476*b370703fSCharles.Forsyth print("; %D used+set; return 1\n", v2);
477*b370703fSCharles.Forsyth return 1;
478*b370703fSCharles.Forsyth }
479*b370703fSCharles.Forsyth break;
480*b370703fSCharles.Forsyth }
481*b370703fSCharles.Forsyth if(!f) {
482*b370703fSCharles.Forsyth t = copyu(p, v1, A);
483*b370703fSCharles.Forsyth if(!f && (t == 2 || t == 3 || t == 4)) {
484*b370703fSCharles.Forsyth f = 1;
485*b370703fSCharles.Forsyth if(debug['P'])
486*b370703fSCharles.Forsyth print("; %D set and !f; f=%d", v1, f);
487*b370703fSCharles.Forsyth }
488*b370703fSCharles.Forsyth }
489*b370703fSCharles.Forsyth if(debug['P'])
490*b370703fSCharles.Forsyth print("\n");
491*b370703fSCharles.Forsyth if(r->s2)
492*b370703fSCharles.Forsyth if(!copy1(v1, v2, r->s2, f))
493*b370703fSCharles.Forsyth return 0;
494*b370703fSCharles.Forsyth }
495*b370703fSCharles.Forsyth return 1;
496*b370703fSCharles.Forsyth }
497*b370703fSCharles.Forsyth
498*b370703fSCharles.Forsyth /*
499*b370703fSCharles.Forsyth * return
500*b370703fSCharles.Forsyth * 1 if v only used (and substitute),
501*b370703fSCharles.Forsyth * 2 if read-alter-rewrite
502*b370703fSCharles.Forsyth * 3 if set
503*b370703fSCharles.Forsyth * 4 if set and used
504*b370703fSCharles.Forsyth * 0 otherwise (not touched)
505*b370703fSCharles.Forsyth */
506*b370703fSCharles.Forsyth int
copyu(Prog * p,Adr * v,Adr * s)507*b370703fSCharles.Forsyth copyu(Prog *p, Adr *v, Adr *s)
508*b370703fSCharles.Forsyth {
509*b370703fSCharles.Forsyth
510*b370703fSCharles.Forsyth switch(p->as) {
511*b370703fSCharles.Forsyth
512*b370703fSCharles.Forsyth default:
513*b370703fSCharles.Forsyth if(debug['P'])
514*b370703fSCharles.Forsyth print("unknown op %A\n", p->as);
515*b370703fSCharles.Forsyth /* SBBL; ADCL; FLD1; SAHF */
516*b370703fSCharles.Forsyth return 2;
517*b370703fSCharles.Forsyth
518*b370703fSCharles.Forsyth
519*b370703fSCharles.Forsyth case ANEGB:
520*b370703fSCharles.Forsyth case ANEGW:
521*b370703fSCharles.Forsyth case ANEGL:
522*b370703fSCharles.Forsyth case ANEGQ:
523*b370703fSCharles.Forsyth case ANOTB:
524*b370703fSCharles.Forsyth case ANOTW:
525*b370703fSCharles.Forsyth case ANOTL:
526*b370703fSCharles.Forsyth case ANOTQ:
527*b370703fSCharles.Forsyth if(copyas(&p->to, v))
528*b370703fSCharles.Forsyth return 2;
529*b370703fSCharles.Forsyth break;
530*b370703fSCharles.Forsyth
531*b370703fSCharles.Forsyth case ALEAL: /* lhs addr, rhs store */
532*b370703fSCharles.Forsyth case ALEAQ:
533*b370703fSCharles.Forsyth if(copyas(&p->from, v))
534*b370703fSCharles.Forsyth return 2;
535*b370703fSCharles.Forsyth
536*b370703fSCharles.Forsyth
537*b370703fSCharles.Forsyth case ANOP: /* rhs store */
538*b370703fSCharles.Forsyth case AMOVL:
539*b370703fSCharles.Forsyth case AMOVQ:
540*b370703fSCharles.Forsyth case AMOVBLSX:
541*b370703fSCharles.Forsyth case AMOVBLZX:
542*b370703fSCharles.Forsyth case AMOVBQSX:
543*b370703fSCharles.Forsyth case AMOVBQZX:
544*b370703fSCharles.Forsyth case AMOVLQSX:
545*b370703fSCharles.Forsyth case AMOVLQZX:
546*b370703fSCharles.Forsyth case AMOVWLSX:
547*b370703fSCharles.Forsyth case AMOVWLZX:
548*b370703fSCharles.Forsyth case AMOVWQSX:
549*b370703fSCharles.Forsyth case AMOVWQZX:
550*b370703fSCharles.Forsyth
551*b370703fSCharles.Forsyth case AMOVSS:
552*b370703fSCharles.Forsyth case AMOVSD:
553*b370703fSCharles.Forsyth case ACVTSD2SL:
554*b370703fSCharles.Forsyth case ACVTSD2SQ:
555*b370703fSCharles.Forsyth case ACVTSD2SS:
556*b370703fSCharles.Forsyth case ACVTSL2SD:
557*b370703fSCharles.Forsyth case ACVTSL2SS:
558*b370703fSCharles.Forsyth case ACVTSQ2SD:
559*b370703fSCharles.Forsyth case ACVTSQ2SS:
560*b370703fSCharles.Forsyth case ACVTSS2SD:
561*b370703fSCharles.Forsyth case ACVTSS2SL:
562*b370703fSCharles.Forsyth case ACVTSS2SQ:
563*b370703fSCharles.Forsyth case ACVTTSD2SL:
564*b370703fSCharles.Forsyth case ACVTTSD2SQ:
565*b370703fSCharles.Forsyth case ACVTTSS2SL:
566*b370703fSCharles.Forsyth case ACVTTSS2SQ:
567*b370703fSCharles.Forsyth if(copyas(&p->to, v)) {
568*b370703fSCharles.Forsyth if(s != A)
569*b370703fSCharles.Forsyth return copysub(&p->from, v, s, 1);
570*b370703fSCharles.Forsyth if(copyau(&p->from, v))
571*b370703fSCharles.Forsyth return 4;
572*b370703fSCharles.Forsyth return 3;
573*b370703fSCharles.Forsyth }
574*b370703fSCharles.Forsyth goto caseread;
575*b370703fSCharles.Forsyth
576*b370703fSCharles.Forsyth case AROLB:
577*b370703fSCharles.Forsyth case AROLL:
578*b370703fSCharles.Forsyth case AROLQ:
579*b370703fSCharles.Forsyth case AROLW:
580*b370703fSCharles.Forsyth case ARORB:
581*b370703fSCharles.Forsyth case ARORL:
582*b370703fSCharles.Forsyth case ARORQ:
583*b370703fSCharles.Forsyth case ARORW:
584*b370703fSCharles.Forsyth case ASALB:
585*b370703fSCharles.Forsyth case ASALL:
586*b370703fSCharles.Forsyth case ASALQ:
587*b370703fSCharles.Forsyth case ASALW:
588*b370703fSCharles.Forsyth case ASARB:
589*b370703fSCharles.Forsyth case ASARL:
590*b370703fSCharles.Forsyth case ASARQ:
591*b370703fSCharles.Forsyth case ASARW:
592*b370703fSCharles.Forsyth case ASHLB:
593*b370703fSCharles.Forsyth case ASHLL:
594*b370703fSCharles.Forsyth case ASHLQ:
595*b370703fSCharles.Forsyth case ASHLW:
596*b370703fSCharles.Forsyth case ASHRB:
597*b370703fSCharles.Forsyth case ASHRL:
598*b370703fSCharles.Forsyth case ASHRQ:
599*b370703fSCharles.Forsyth case ASHRW:
600*b370703fSCharles.Forsyth if(copyas(&p->to, v))
601*b370703fSCharles.Forsyth return 2;
602*b370703fSCharles.Forsyth if(copyas(&p->from, v))
603*b370703fSCharles.Forsyth if(p->from.type == D_CX)
604*b370703fSCharles.Forsyth return 2;
605*b370703fSCharles.Forsyth goto caseread;
606*b370703fSCharles.Forsyth
607*b370703fSCharles.Forsyth case AADDB: /* rhs rar */
608*b370703fSCharles.Forsyth case AADDL:
609*b370703fSCharles.Forsyth case AADDQ:
610*b370703fSCharles.Forsyth case AADDW:
611*b370703fSCharles.Forsyth case AANDB:
612*b370703fSCharles.Forsyth case AANDL:
613*b370703fSCharles.Forsyth case AANDQ:
614*b370703fSCharles.Forsyth case AANDW:
615*b370703fSCharles.Forsyth case ADECL:
616*b370703fSCharles.Forsyth case ADECQ:
617*b370703fSCharles.Forsyth case ADECW:
618*b370703fSCharles.Forsyth case AINCL:
619*b370703fSCharles.Forsyth case AINCQ:
620*b370703fSCharles.Forsyth case AINCW:
621*b370703fSCharles.Forsyth case ASUBB:
622*b370703fSCharles.Forsyth case ASUBL:
623*b370703fSCharles.Forsyth case ASUBQ:
624*b370703fSCharles.Forsyth case ASUBW:
625*b370703fSCharles.Forsyth case AORB:
626*b370703fSCharles.Forsyth case AORL:
627*b370703fSCharles.Forsyth case AORQ:
628*b370703fSCharles.Forsyth case AORW:
629*b370703fSCharles.Forsyth case AXORB:
630*b370703fSCharles.Forsyth case AXORL:
631*b370703fSCharles.Forsyth case AXORQ:
632*b370703fSCharles.Forsyth case AXORW:
633*b370703fSCharles.Forsyth case AMOVB:
634*b370703fSCharles.Forsyth case AMOVW:
635*b370703fSCharles.Forsyth
636*b370703fSCharles.Forsyth case AADDSD:
637*b370703fSCharles.Forsyth case AADDSS:
638*b370703fSCharles.Forsyth case ACMPSD:
639*b370703fSCharles.Forsyth case ACMPSS:
640*b370703fSCharles.Forsyth case ADIVSD:
641*b370703fSCharles.Forsyth case ADIVSS:
642*b370703fSCharles.Forsyth case AMAXSD:
643*b370703fSCharles.Forsyth case AMAXSS:
644*b370703fSCharles.Forsyth case AMINSD:
645*b370703fSCharles.Forsyth case AMINSS:
646*b370703fSCharles.Forsyth case AMULSD:
647*b370703fSCharles.Forsyth case AMULSS:
648*b370703fSCharles.Forsyth case ARCPSS:
649*b370703fSCharles.Forsyth case ARSQRTSS:
650*b370703fSCharles.Forsyth case ASQRTSD:
651*b370703fSCharles.Forsyth case ASQRTSS:
652*b370703fSCharles.Forsyth case ASUBSD:
653*b370703fSCharles.Forsyth case ASUBSS:
654*b370703fSCharles.Forsyth case AXORPD:
655*b370703fSCharles.Forsyth if(copyas(&p->to, v))
656*b370703fSCharles.Forsyth return 2;
657*b370703fSCharles.Forsyth goto caseread;
658*b370703fSCharles.Forsyth
659*b370703fSCharles.Forsyth case ACMPL: /* read only */
660*b370703fSCharles.Forsyth case ACMPW:
661*b370703fSCharles.Forsyth case ACMPB:
662*b370703fSCharles.Forsyth case ACMPQ:
663*b370703fSCharles.Forsyth
664*b370703fSCharles.Forsyth case ACOMISD:
665*b370703fSCharles.Forsyth case ACOMISS:
666*b370703fSCharles.Forsyth case AUCOMISD:
667*b370703fSCharles.Forsyth case AUCOMISS:
668*b370703fSCharles.Forsyth caseread:
669*b370703fSCharles.Forsyth if(s != A) {
670*b370703fSCharles.Forsyth if(copysub(&p->from, v, s, 1))
671*b370703fSCharles.Forsyth return 1;
672*b370703fSCharles.Forsyth return copysub(&p->to, v, s, 1);
673*b370703fSCharles.Forsyth }
674*b370703fSCharles.Forsyth if(copyau(&p->from, v))
675*b370703fSCharles.Forsyth return 1;
676*b370703fSCharles.Forsyth if(copyau(&p->to, v))
677*b370703fSCharles.Forsyth return 1;
678*b370703fSCharles.Forsyth break;
679*b370703fSCharles.Forsyth
680*b370703fSCharles.Forsyth case AJGE: /* no reference */
681*b370703fSCharles.Forsyth case AJNE:
682*b370703fSCharles.Forsyth case AJLE:
683*b370703fSCharles.Forsyth case AJEQ:
684*b370703fSCharles.Forsyth case AJHI:
685*b370703fSCharles.Forsyth case AJLS:
686*b370703fSCharles.Forsyth case AJMI:
687*b370703fSCharles.Forsyth case AJPL:
688*b370703fSCharles.Forsyth case AJGT:
689*b370703fSCharles.Forsyth case AJLT:
690*b370703fSCharles.Forsyth case AJCC:
691*b370703fSCharles.Forsyth case AJCS:
692*b370703fSCharles.Forsyth
693*b370703fSCharles.Forsyth case AADJSP:
694*b370703fSCharles.Forsyth case AWAIT:
695*b370703fSCharles.Forsyth case ACLD:
696*b370703fSCharles.Forsyth break;
697*b370703fSCharles.Forsyth
698*b370703fSCharles.Forsyth case AIMULL:
699*b370703fSCharles.Forsyth case AIMULQ:
700*b370703fSCharles.Forsyth case AIMULW:
701*b370703fSCharles.Forsyth if(p->to.type != D_NONE) {
702*b370703fSCharles.Forsyth if(copyas(&p->to, v))
703*b370703fSCharles.Forsyth return 2;
704*b370703fSCharles.Forsyth goto caseread;
705*b370703fSCharles.Forsyth }
706*b370703fSCharles.Forsyth
707*b370703fSCharles.Forsyth case ADIVB:
708*b370703fSCharles.Forsyth case ADIVL:
709*b370703fSCharles.Forsyth case ADIVQ:
710*b370703fSCharles.Forsyth case ADIVW:
711*b370703fSCharles.Forsyth case AIDIVB:
712*b370703fSCharles.Forsyth case AIDIVL:
713*b370703fSCharles.Forsyth case AIDIVQ:
714*b370703fSCharles.Forsyth case AIDIVW:
715*b370703fSCharles.Forsyth case AIMULB:
716*b370703fSCharles.Forsyth case AMULB:
717*b370703fSCharles.Forsyth case AMULL:
718*b370703fSCharles.Forsyth case AMULQ:
719*b370703fSCharles.Forsyth case AMULW:
720*b370703fSCharles.Forsyth
721*b370703fSCharles.Forsyth case ACWD:
722*b370703fSCharles.Forsyth case ACDQ:
723*b370703fSCharles.Forsyth case ACQO:
724*b370703fSCharles.Forsyth if(v->type == D_AX || v->type == D_DX)
725*b370703fSCharles.Forsyth return 2;
726*b370703fSCharles.Forsyth goto caseread;
727*b370703fSCharles.Forsyth
728*b370703fSCharles.Forsyth case AMOVSL:
729*b370703fSCharles.Forsyth case AMOVSQ:
730*b370703fSCharles.Forsyth case AREP:
731*b370703fSCharles.Forsyth case AREPN:
732*b370703fSCharles.Forsyth if(v->type == D_CX || v->type == D_DI || v->type == D_SI)
733*b370703fSCharles.Forsyth return 2;
734*b370703fSCharles.Forsyth goto caseread;
735*b370703fSCharles.Forsyth
736*b370703fSCharles.Forsyth case AJMP: /* funny */
737*b370703fSCharles.Forsyth if(s != A) {
738*b370703fSCharles.Forsyth if(copysub(&p->to, v, s, 1))
739*b370703fSCharles.Forsyth return 1;
740*b370703fSCharles.Forsyth return 0;
741*b370703fSCharles.Forsyth }
742*b370703fSCharles.Forsyth if(copyau(&p->to, v))
743*b370703fSCharles.Forsyth return 1;
744*b370703fSCharles.Forsyth return 0;
745*b370703fSCharles.Forsyth
746*b370703fSCharles.Forsyth case ARET: /* funny */
747*b370703fSCharles.Forsyth if(v->type == REGRET || v->type == FREGRET)
748*b370703fSCharles.Forsyth return 2;
749*b370703fSCharles.Forsyth if(s != A)
750*b370703fSCharles.Forsyth return 1;
751*b370703fSCharles.Forsyth return 3;
752*b370703fSCharles.Forsyth
753*b370703fSCharles.Forsyth case ACALL: /* funny */
754*b370703fSCharles.Forsyth if(REGEXT && v->type <= REGEXT && v->type > exregoffset)
755*b370703fSCharles.Forsyth return 2;
756*b370703fSCharles.Forsyth if(REGARG && v->type == REGARG)
757*b370703fSCharles.Forsyth return 2;
758*b370703fSCharles.Forsyth
759*b370703fSCharles.Forsyth if(s != A) {
760*b370703fSCharles.Forsyth if(copysub(&p->to, v, s, 1))
761*b370703fSCharles.Forsyth return 1;
762*b370703fSCharles.Forsyth return 0;
763*b370703fSCharles.Forsyth }
764*b370703fSCharles.Forsyth if(copyau(&p->to, v))
765*b370703fSCharles.Forsyth return 4;
766*b370703fSCharles.Forsyth return 3;
767*b370703fSCharles.Forsyth
768*b370703fSCharles.Forsyth case ATEXT: /* funny */
769*b370703fSCharles.Forsyth if(REGARG && v->type == REGARG)
770*b370703fSCharles.Forsyth return 3;
771*b370703fSCharles.Forsyth return 0;
772*b370703fSCharles.Forsyth }
773*b370703fSCharles.Forsyth return 0;
774*b370703fSCharles.Forsyth }
775*b370703fSCharles.Forsyth
776*b370703fSCharles.Forsyth /*
777*b370703fSCharles.Forsyth * direct reference,
778*b370703fSCharles.Forsyth * could be set/use depending on
779*b370703fSCharles.Forsyth * semantics
780*b370703fSCharles.Forsyth */
781*b370703fSCharles.Forsyth int
copyas(Adr * a,Adr * v)782*b370703fSCharles.Forsyth copyas(Adr *a, Adr *v)
783*b370703fSCharles.Forsyth {
784*b370703fSCharles.Forsyth if(a->type != v->type)
785*b370703fSCharles.Forsyth return 0;
786*b370703fSCharles.Forsyth if(regtyp(v))
787*b370703fSCharles.Forsyth return 1;
788*b370703fSCharles.Forsyth if(v->type == D_AUTO || v->type == D_PARAM)
789*b370703fSCharles.Forsyth if(v->offset == a->offset)
790*b370703fSCharles.Forsyth return 1;
791*b370703fSCharles.Forsyth return 0;
792*b370703fSCharles.Forsyth }
793*b370703fSCharles.Forsyth
794*b370703fSCharles.Forsyth /*
795*b370703fSCharles.Forsyth * either direct or indirect
796*b370703fSCharles.Forsyth */
797*b370703fSCharles.Forsyth int
copyau(Adr * a,Adr * v)798*b370703fSCharles.Forsyth copyau(Adr *a, Adr *v)
799*b370703fSCharles.Forsyth {
800*b370703fSCharles.Forsyth
801*b370703fSCharles.Forsyth if(copyas(a, v))
802*b370703fSCharles.Forsyth return 1;
803*b370703fSCharles.Forsyth if(regtyp(v)) {
804*b370703fSCharles.Forsyth if(a->type-D_INDIR == v->type)
805*b370703fSCharles.Forsyth return 1;
806*b370703fSCharles.Forsyth if(a->index == v->type)
807*b370703fSCharles.Forsyth return 1;
808*b370703fSCharles.Forsyth }
809*b370703fSCharles.Forsyth return 0;
810*b370703fSCharles.Forsyth }
811*b370703fSCharles.Forsyth
812*b370703fSCharles.Forsyth /*
813*b370703fSCharles.Forsyth * substitute s for v in a
814*b370703fSCharles.Forsyth * return failure to substitute
815*b370703fSCharles.Forsyth */
816*b370703fSCharles.Forsyth int
copysub(Adr * a,Adr * v,Adr * s,int f)817*b370703fSCharles.Forsyth copysub(Adr *a, Adr *v, Adr *s, int f)
818*b370703fSCharles.Forsyth {
819*b370703fSCharles.Forsyth int t;
820*b370703fSCharles.Forsyth
821*b370703fSCharles.Forsyth if(copyas(a, v)) {
822*b370703fSCharles.Forsyth t = s->type;
823*b370703fSCharles.Forsyth if(t >= D_AX && t <= D_R15 || t >= D_X0 && t <= D_X0+15) {
824*b370703fSCharles.Forsyth if(f)
825*b370703fSCharles.Forsyth a->type = t;
826*b370703fSCharles.Forsyth }
827*b370703fSCharles.Forsyth return 0;
828*b370703fSCharles.Forsyth }
829*b370703fSCharles.Forsyth if(regtyp(v)) {
830*b370703fSCharles.Forsyth t = v->type;
831*b370703fSCharles.Forsyth if(a->type == t+D_INDIR) {
832*b370703fSCharles.Forsyth if((s->type == D_BP || s->type == D_R13) && a->index != D_NONE)
833*b370703fSCharles.Forsyth return 1; /* can't use BP-base with index */
834*b370703fSCharles.Forsyth if(f)
835*b370703fSCharles.Forsyth a->type = s->type+D_INDIR;
836*b370703fSCharles.Forsyth // return 0;
837*b370703fSCharles.Forsyth }
838*b370703fSCharles.Forsyth if(a->index == t) {
839*b370703fSCharles.Forsyth if(f)
840*b370703fSCharles.Forsyth a->index = s->type;
841*b370703fSCharles.Forsyth return 0;
842*b370703fSCharles.Forsyth }
843*b370703fSCharles.Forsyth return 0;
844*b370703fSCharles.Forsyth }
845*b370703fSCharles.Forsyth return 0;
846*b370703fSCharles.Forsyth }
847