Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – tendra.SVN – Blame – /branches/tendra5-amd64/src/installers/680x0/common/peephole.c – Rev 6

Subversion Repositories tendra.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
6 7u83 2
 * Copyright (c) 2002-2006 The TenDRA Project <http://www.tendra.org/>.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific, prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 * $Id$
30
 */
31
/*
2 7u83 32
    		 Crown Copyright (c) 1996
33
 
34
    This TenDRA(r) Computer Program is subject to Copyright
35
    owned by the United Kingdom Secretary of State for Defence
36
    acting through the Defence Evaluation and Research Agency
37
    (DERA).  It is made available to Recipients with a
38
    royalty-free licence for its use, reproduction, transfer
39
    to other parties and amendment for any purpose not excluding
40
    product development provided that any such use et cetera
41
    shall be deemed to be acceptance of the following conditions:-
42
 
43
        (1) Its Recipients shall ensure that this Notice is
44
        reproduced upon any copies or amended versions of it;
45
 
46
        (2) Any amended version of it shall be clearly marked to
47
        show both the nature of and the organisation responsible
48
        for the relevant amendment or amendments;
49
 
50
        (3) Its onward transfer from a recipient to another
51
        party shall be deemed to be that party's acceptance of
52
        these conditions;
53
 
54
        (4) DERA gives no warranty or assurance as to its
55
        quality or suitability for any purpose and DERA accepts
56
        no liability whatsoever in relation to any use to which
57
        it may be put.
58
*/
59
/*
60
			    VERSION INFORMATION
61
			    ===================
62
 
63
--------------------------------------------------------------------------
64
$Header: /u/g/release/CVSROOT/Source/src/installers/680x0/common/peephole.c,v 1.1.1.1 1998/01/17 15:55:50 release Exp $
65
--------------------------------------------------------------------------
66
$Log: peephole.c,v $
67
 * Revision 1.1.1.1  1998/01/17  15:55:50  release
68
 * First version to be checked into rolling release.
69
 *
70
Revision 1.1.1.1  1997/10/13 12:42:58  ma
71
First version.
72
 
73
Revision 1.2  1997/06/18 12:04:58  ma
74
Merged with Input Baseline changes.
75
 
76
Revision 1.1.1.1  1997/03/14 07:50:17  ma
77
Imported from DRA
78
 
79
 * Revision 1.2  1996/09/20  13:51:43  john
80
 * *** empty log message ***
81
 *
82
 * Revision 1.1.1.1  1996/09/20  10:56:58  john
83
 *
84
 * Revision 1.1.1.1  1996/03/26  15:45:16  john
85
 *
86
 * Revision 1.1  93/02/22  17:16:34  17:16:34  ra (Robert Andrews)
87
 * Initial revision
88
 *
89
--------------------------------------------------------------------------
90
*/
91
 
92
 
93
#include "config.h"
94
#include "common_types.h"
95
#include "assembler.h"
96
#include "instrs.h"
97
#include "exp.h"
98
#include "mach.h"
99
#include "mach_ins.h"
100
#include "mach_op.h"
101
#include "peephole.h"
102
#include "utility.h"
6 7u83 103
extern bool have_cond;
104
extern bool just_ret;
105
extern long crt_ret_lab;
2 7u83 106
 
107
 
108
/*
109
    SET UP TABLE OF OPPOSITE JUMPS
110
 
111
    This table gives a correspondence between the conditional jump
112
    "if condition goto ..." and the opposite conditional jump
113
    "if not condition goto ...".
114
*/
115
 
116
#define OPPOSITE_JUMPS
117
#include "instr_aux.h"
118
 
119
 
120
/*
121
    FIND A LABEL
122
 
123
    This routine searches the list of all instructions for label n.
124
    It returns null if it cannot be found.
125
*/
126
 
6 7u83 127
static mach_ins *
128
find_label(long n)
2 7u83 129
{
6 7u83 130
	mach_ins *p;
131
	for (p = all_mach_ins; p; p = p->next) {
132
		if (p->ins_no == m_label_ins && p->op1->def.num == n) {
133
			return (p);
134
		}
135
	}
136
	return (null);
2 7u83 137
}
138
 
139
 
140
/*
141
    CHECK A JUMP ALIAS FOR CYCLES
142
 
143
    A jump alias is a label followed immediately by an unconditional
144
    jump to another label.  It is possible to get cycles of mutually
145
    dependent jump aliases.  This routine checks whether the alias a=>b
146
    is part of a cycle, and if so returns null.  Otherwise it returns
147
    the position of label b.
148
*/
149
 
150
#define  alias_max	20
151
 
6 7u83 152
static mach_ins *
153
check_jump_alias(long a, long b)
2 7u83 154
{
6 7u83 155
	int i, n;
156
	mach_ins *p, *q;
157
	long alias[alias_max];
2 7u83 158
 
6 7u83 159
	if (a == b) {
160
		return (null);
161
	}
2 7u83 162
 
6 7u83 163
	alias[0] = a;
164
	alias[1] = b;
165
	p = find_label(b);
166
	if (p == null) {
167
		return (null);
168
	}
2 7u83 169
 
6 7u83 170
	for (n = 2, q = p; n < alias_max; n++) {
171
		while (q && q->ins_no == m_label_ins)q = q->next;
172
		if (q && q->ins_no == m_bra) {
173
			long c = q->op1->def.num;
174
			for (i = 0; i < n; i++) {
175
				if (c == alias[i]) {
176
					return (null);
177
				}
178
			}
179
			alias[n] = c;
180
			q = find_label(c);
181
		} else {
182
			return (p);
183
		}
2 7u83 184
	}
6 7u83 185
	return (null);
2 7u83 186
}
187
 
188
 
189
/*
190
    CALCULATE ALL JUMP LENGTHS
191
 
192
    This routine finds the length of all jumps and marks each as long,
193
    word or byte.  The length is based on the number of instructions
194
    jumped over.  It would be better if the assembler could do this.
195
*/
196
 
197
#define  byte_len_min	-16
198
#define  byte_len_max	16
199
#define  word_len_min	-2000
200
#define  word_len_max	2000
201
 
202
#ifndef asm_does_jump_lens
203
 
6 7u83 204
static void
205
find_jump_sizes(long lmin, long lmax)
2 7u83 206
{
6 7u83 207
	long *tb;
208
	mach_ins *p;
209
	long i, n = lmax - lmin + 1;
2 7u83 210
 
6 7u83 211
	/* Allocate a temporary label position table */
212
	if (n <= 0) {
213
		return;
214
	}
2 7u83 215
#ifndef NO_ALLOCA
6 7u83 216
	tb = (long *)alloca(n * sizeof(long));
2 7u83 217
#else
6 7u83 218
	tb = alloc_nof(long, n);
2 7u83 219
#endif
6 7u83 220
	for (i = 0; i < n; i++) {
221
		tb[i] = 0;
222
	}
2 7u83 223
 
6 7u83 224
	/* Fill in label positions */
225
	for (p = all_mach_ins, i = 1; p; p = p->next) {
226
		if (p->ins_no == m_label_ins) {
227
			n = p->op1->def.num - lmin;
228
			tb[n] = i;
229
		} else {
230
			i++;
231
		}
2 7u83 232
	}
233
 
6 7u83 234
	/* Work out jump lengths */
235
	for (p = all_mach_ins, i = 1; p; p = p->next) {
236
		int r = p->ins_no;
237
		if (is_jump(r)) {
238
			n = p->op1->def.num;
239
			if (just_ret && n == crt_ret_lab && r == m_bra) {
240
				p->ins_no = m_rts;
241
				free_mach_op(p->op1);
242
				p->op1 = null;
243
			} else {
244
				int m = long_jump;
245
				long d = tb[n - lmin];
246
				if (d) {
247
					d -= i;
248
					if (d >= byte_len_min &&
249
					    d <= byte_len_max && d) {
250
						m = byte_jump;
251
					} else if (d >= word_len_min &&
252
						   d <= word_len_max) {
253
						m = word_jump;
254
					}
255
				}
256
				p->ins_no = r + m;
257
			}
2 7u83 258
		}
6 7u83 259
		if (r != m_label_ins) {
260
			i++;
261
		}
2 7u83 262
	}
263
 
264
#ifdef NO_ALLOCA
6 7u83 265
	free(tb);
2 7u83 266
#endif
6 7u83 267
	return;
2 7u83 268
}
269
 
270
#endif
271
 
272
 
273
/*
274
    MASK OF REGISTERS CHANGED BY PROCEDURE CALLS
275
 
276
    Normally this is just ~save_msk, but if, for example D2 is renamed to
277
    D1 by epilogue then D2 has to be marked as changed by procedure calls.
278
*/
279
 
6 7u83 280
bitpattern callmsk = 0;
2 7u83 281
 
282
 
283
/*
284
    APPLY ALL PEEPHOLE OPTIMIZATIONS
285
 
286
    This routine scans through the list of all instructions applying
287
    various simple optimizations.
288
*/
289
 
6 7u83 290
void
291
peephole(void)
2 7u83 292
{
6 7u83 293
    long a1, a2;
294
    mach_ins *p, *q;
295
    mach_op *op1, *op2;
296
    int knock_on_effects;
2 7u83 297
 
6 7u83 298
    mach_op *hold[32];
299
    bitpattern unknown;
2 7u83 300
 
6 7u83 301
    int removed_p;
302
    mach_ins *p_up, *p_down;
2 7u83 303
 
6 7u83 304
    long lmin = 100000, lmax = -100000;
2 7u83 305
 
306
#define  remove_p()			\
6 7u83 307
    if (p_up == null) {			\
308
	all_mach_ins = p_down;		\
2 7u83 309
    } else {				\
6 7u83 310
	p_up->next = p_down;		\
2 7u83 311
    }					\
6 7u83 312
    removed_p = 1;
2 7u83 313
 
314
    do {
6 7u83 315
	knock_on_effects = 0;
316
	unknown = 0xffffffff;
317
	p_up = null;
318
	p = all_mach_ins;
319
	while (p != null) {
320
	    int n = p->ins_no;
321
	    bitpattern ch = p->changed;
2 7u83 322
 
6 7u83 323
	    removed_p = 0;
324
	    p_down = p->next;
2 7u83 325
 
6 7u83 326
	    if (n == m_lea) {
2 7u83 327
		/* Some lea's can be turned into moves */
6 7u83 328
		op1 = p->op1;
329
		if (op1->type == MACH_CONT) {
330
		    op2 = op1->of;
331
		    if (op2->type == MACH_REG && op2->plus == null) {
332
			if (op2->def.num == p->op2->def.num) {
2 7u83 333
			    /* The move may be nugatory */
6 7u83 334
			    remove_p();
335
			    reclaim_ins(p);
2 7u83 336
			} else {
337
			    /* Create the move */
6 7u83 338
			    p->ins_no = m_movl;
339
			    p->op1 = op2;
340
			    op1->of = null;
341
			    free_mach_op(op1);
2 7u83 342
			}
343
		    }
344
		}
345
	    }
346
 
6 7u83 347
	    if (n == m_pea) {
2 7u83 348
		/* Some pea's can be turned into pushes */
6 7u83 349
		op1 = p->op1;
350
		if (op1->type == MACH_CONT) {
351
		    op2 = op1->of;
352
		    if (op2->type == MACH_REG && op2->plus == null) {
2 7u83 353
			/* Create the push */
6 7u83 354
			p->ins_no = m_movl;
355
			p->op1 = op2;
356
			op1->type = MACH_DEC;
357
			op1->def.num = REG_SP;
358
			op1->of = null;
359
			p->op2 = op1;
2 7u83 360
		    }
361
		}
362
	    }
363
 
6 7u83 364
	    if (n == m_bra) {
2 7u83 365
		/* Remove unreachable code after unconditional jumps */
6 7u83 366
		q = p_down;
367
		while (q && q->ins_no != m_label_ins) {
368
		    mach_ins *q1 = q->next;
369
		    reclaim_ins(q);
370
		    knock_on_effects = 1;
371
		    q = q1;
2 7u83 372
		}
6 7u83 373
		p->next = q;
374
		p_down = q;
2 7u83 375
	    }
376
 
6 7u83 377
	    if (is_jump(n)) {
378
		a1 = p->op1->def.num;
2 7u83 379
 
380
		/* Remove jumps to immediately following labels */
6 7u83 381
		q = p_down;
382
		while (q && q->ins_no == m_label_ins) {
383
		    a2 = q->op1->def.num;
384
		    if (a1 == a2) {
385
			remove_p();
386
			reclaim_ins(p);
387
			knock_on_effects = 1;
2 7u83 388
		    }
6 7u83 389
		    q = q->next;
2 7u83 390
		}
391
 
6 7u83 392
		if (!knock_on_effects && n != m_bra && p_down) {
393
		    int m = p_down->ins_no;
2 7u83 394
 
6 7u83 395
		    if (m == oppo_jump(n)) {
2 7u83 396
			/* A jump following its opposite jump can be
397
			   made unconditional */
6 7u83 398
			p_down->ins_no = m_bra;
399
			m = m_bra;
2 7u83 400
		    }
401
 
6 7u83 402
		    if (m == m_bra) {
2 7u83 403
			/* Negate conditionals if appropriate :
404
 
6 7u83 405
				if (cond) goto L1
2 7u83 406
				goto L2
6 7u83 407
				L1: ....
2 7u83 408
 
409
			   becomes :
410
 
6 7u83 411
				if (!cond) goto L2
412
				L1: ....
2 7u83 413
			*/
6 7u83 414
			q = p_down->next;
415
			while (q && q->ins_no == m_label_ins) {
416
			    a2 = q->op1->def.num;
417
			    if (a1 == a2) {
418
				remove_p();
419
				reclaim_ins(p);
420
				p_down->ins_no = oppo_jump(n);
421
				knock_on_effects = 1;
2 7u83 422
			    }
6 7u83 423
			    q = q->next;
2 7u83 424
			}
425
 
6 7u83 426
		    } else if (m == n) {
2 7u83 427
			/* Consecutive identical jumps are unnecessary */
6 7u83 428
			q = p_down;
429
			p_down = q->next;
430
			q->next = null;
431
			reclaim_ins(q);
432
			p->next = p_down;
433
			knock_on_effects = 1;
2 7u83 434
 
6 7u83 435
		    } else if (just_ret && m != m_label_ins) {
2 7u83 436
			/* Negate certain simple returns :
437
 
6 7u83 438
				if (cond) goto L1
2 7u83 439
				return x
6 7u83 440
				L1: ....
2 7u83 441
 
442
			   becomes :
443
 
6 7u83 444
				if (!cond) goto L2
445
				L1: ....
2 7u83 446
				.....
6 7u83 447
				L2: return x
2 7u83 448
			*/
6 7u83 449
			q = p_down->next;
450
			if (q && q->ins_no == m_bra &&
451
			     q->op1->def.num == crt_ret_lab) {
452
			    bool go = 0;
453
			    q = q->next;
454
			    while (q && q->ins_no == m_label_ins) {
455
				a2 = q->op1->def.num;
456
				if (a2 == a1) {
457
					go = 1;
458
				}
459
				if (a2 == crt_ret_lab) {
460
					go = 0;
461
				}
462
				q = q->next;
2 7u83 463
			    }
6 7u83 464
			    if (go) {
465
				a2 = next_lab();
466
				if (a2 < lmin) {
467
					lmin = a2;
468
				}
469
				if (a2 > lmax) {
470
					lmax = a2;
471
				}
472
				p->ins_no = oppo_jump(n);
473
				p->op1->def.num = a2;
474
				q = p_down->next;
475
				p->next = q->next;
476
				q->next = null;
477
				reclaim_ins(q);
2 7u83 478
#ifndef no_align_directives
6 7u83 479
                                make_instr(m_as_align4, null, null, 0);
2 7u83 480
#endif
6 7u83 481
				make_label(a2);
482
				current_ins->next = p_down;
483
				p_down->next = null;
484
				current_ins = current_ins->next;
485
				make_instr(m_rts, null, null, 0);
486
				p_down = p->next;
2 7u83 487
			    }
488
			}
489
		    }
490
		}
491
	    }
492
 
6 7u83 493
	    if (n == m_label_ins) {
2 7u83 494
		/* Update maximum and minimum label numbers */
6 7u83 495
		a1 = p->op1->def.num;
496
		if (a1 < lmin) {
497
			lmin = a1;
498
		}
499
		if (a1 > lmax) {
500
			lmax = a1;
501
		}
2 7u83 502
 
503
		/* Look for jump aliases :
504
 
505
			L1 : goto L2
506
			....
507
			L2 : ....
508
 
509
		   becomes :
510
 
511
			goto L2
512
			....
513
			L2 :
514
			L1 : ....
515
 
516
		   provided L1=>L2 is not part of a cycle of jump aliases.
517
		*/
6 7u83 518
		q = p->next;
519
		while (q && q->ins_no == m_label_ins)q = q->next;
520
		if (q && q->ins_no == m_bra) {
521
		    a2 = q->op1->def.num;
522
		    q = check_jump_alias(a1, a2);
523
		    if (q != null) {
2 7u83 524
			/* Move the label */
6 7u83 525
			remove_p();
526
			p->next = q->next;
527
			q->next = p;
528
			knock_on_effects = 1;
2 7u83 529
		    }
530
		}
531
	    }
532
 
533
	    /* Look at consecutive moves */
6 7u83 534
	    if (n == m_movl && p_down && p_down->ins_no == m_movl) {
535
		a1 = p->op1->type;
536
		a2 = p->op2->type;
537
		if (a1 == MACH_REG && a2 != MACH_REG &&
538
		     !check_op(p->op2, p->op1->def.num) &&
539
		     equal_op(p->op2, p_down->op1)) {
2 7u83 540
		    /* b = a, c = b => b = a, c = a */
6 7u83 541
		    free_mach_op(p_down->op1);
542
		    p_down->op1 = make_register(p->op1->def.num);
2 7u83 543
		}
6 7u83 544
		if (a1 != MACH_REG && a2 == MACH_REG &&
545
		     !check_op(p->op1, p->op2->def.num) &&
546
		     equal_op(p->op1, p_down->op1)) {
2 7u83 547
		    /* b = a, c = a => b = a, c = b */
6 7u83 548
		    free_mach_op(p_down->op1);
549
		    p_down->op1 = make_register(p->op2->def.num);
2 7u83 550
		}
551
	    }
552
 
553
	    /* Moving constants into registers */
6 7u83 554
	    if ((n == m_movl || n == m_moveq) && p->op2->type == MACH_REG) {
555
		int t = p->op1->type;
556
		if (t == MACH_HEX) {
557
			t = MACH_VAL;
558
		}
559
		if ((t == MACH_VAL || t == MACH_EXT || t == MACH_LAB) &&
560
		     p->op1->plus == null) {
561
		    long z = p->op2->def.num;
562
		    if (!(unknown & regmsk(z)) &&
563
			 hold[z] ->type == t &&
564
			 hold[z] ->def.num == p->op1->def.num) {
2 7u83 565
			/* Move is strictly unnecessary */
6 7u83 566
			if (p_down && is_jump(p_down->ins_no)) {
2 7u83 567
			    /* Keep it in for test purposes */
568
			} else {
6 7u83 569
			    remove_p();
570
			    reclaim_ins(p);
2 7u83 571
			}
572
		    } else {
6 7u83 573
			hold[z] = p->op1;
574
			hold[z] ->type = t;
575
			unknown &= ~ch;
576
			ch = 0;
2 7u83 577
		    }
578
		}
579
	    }
580
 
581
	    /* Remove ignore instructions */
6 7u83 582
	    if (n == m_ignore_ins) {
583
		remove_p();
584
		reclaim_ins(p);
2 7u83 585
	    }
586
 
587
	    /* Deal with registers changed by procedure calls */
6 7u83 588
	    if (n == m_call) {
589
		    ch |= callmsk;
590
	    }
2 7u83 591
 
592
	    /* Update p_up, p and unknown */
6 7u83 593
	    if (!removed_p) {
594
		p_up = p;
595
		unknown |= ch;
2 7u83 596
	    }
6 7u83 597
	    p = p_down;
2 7u83 598
	}
6 7u83 599
    } while (knock_on_effects);
2 7u83 600
 
601
    /* Work out jump sizes */
602
#ifndef asm_does_jump_lens
6 7u83 603
    find_jump_sizes(lmin, lmax);
2 7u83 604
#endif
6 7u83 605
    return;
2 7u83 606
}
607
 
608
 
609
/*
610
    TABLE OF INSTRUCTION SIZES
611
 
612
    This table gives the correspondence between instruction numbers
613
    and instruction sizes.
614
*/
615
 
6 7u83 616
static bool instr_sz[] = {
2 7u83 617
#define INSTR_SIZES
618
#include "instr_aux.h"
6 7u83 619
};
2 7u83 620
 
621
 
622
/*
623
    CHECK FOR POST-INCREMENT AND PRE-DECREMENT
624
 
625
    This routine checks for (some) possible uses of post-increment and
626
    pre-decrement instructions.  It returns 1 if a change has been
627
    made.
628
*/
629
 
6 7u83 630
bool
631
post_inc_check(mach_ins *q, bitpattern r)
2 7u83 632
{
6 7u83 633
	long r1, r2, sz;
634
	int move_ins;
635
	bool incr = 1, use_op1 = 1, use_op2 = 1;
2 7u83 636
 
6 7u83 637
	mach_op *op;
638
	mach_ins *p = q->next;
2 7u83 639
 
6 7u83 640
	if (p == null) {
641
		return (0);
642
	}
2 7u83 643
 
6 7u83 644
	/* The first instruction may be m_subql */
645
	if (p->ins_no == m_subql) {
646
		sz = p->op1->def.num;
647
		r1 = p->op2->def.num;
648
		p = p->next;
649
		if (p == null) {
650
			return (0);
651
		}
652
		incr = 0;
653
	}
2 7u83 654
 
6 7u83 655
	/* The next instruction must be a move of two registers */
656
	if (p->ins_no != m_movl) {
657
		return (0);
658
	}
659
	if (p->op1->type != MACH_REG) {
660
		return (0);
661
	}
662
	if (p->op2->type != MACH_REG) {
663
		return (0);
664
	}
665
	if (incr) {
666
		r1 = p->op1->def.num;
667
	} else {
668
		/* The first register must be the one in the m_subql */
669
		if (p->op1->def.num != r1) {
670
			return (0);
671
		}
672
	}
2 7u83 673
 
6 7u83 674
	/* The second register must be that given by r */
675
	r2 = p->op2->def.num;
676
	if (regmsk(r2) != r) {
677
		return (0);
678
	}
2 7u83 679
 
6 7u83 680
	if (incr) {
681
		/* The next instruction must be "lea sz(r2), r1" */
682
		p = p->next;
683
		if (p == null) {
684
			return (0);
685
		}
686
		if (p->ins_no != m_lea) {
687
			return (0);
688
		}
689
		if (p->op1->type != MACH_CONT) {
690
			return (0);
691
		}
692
		if (p->op1->of->type != MACH_REG) {
693
			return (0);
694
		}
695
		if (p->op1->of->def.num != r2) {
696
			return (0);
697
		}
698
		if (p->op1->of->plus->type != MACH_VAL) {
699
			return (0);
700
		}
701
		sz = p->op1->of->plus->def.num;
702
		if (p->op2->type != MACH_REG) {
703
			return (0);
704
		}
705
		if (p->op2->def.num != r1) {
706
			return (0);
707
		}
708
	}
2 7u83 709
 
6 7u83 710
	/* Check the value of sz */
711
	if (sz == 1) {
712
		move_ins = m_movb;
713
	} else if (sz == 2) {
714
		move_ins = m_movw;
715
	} else if (sz == 4) {
716
		move_ins = m_movl;
717
	} else {
718
		return (0);
719
	}
2 7u83 720
 
6 7u83 721
	p = p->next;
722
	if (p == null) {
723
		return (0);
724
	}
725
	if (p->next) {
726
		/* The next instruction may be "move (r2), reg" */
727
		if (p->next->next) {
728
			return (0);
729
		}
730
		if (p->next->ins_no != move_ins) {
731
			return (0);
732
		}
733
		op = p->next->op1;
734
		if (op->type != MACH_CONT) {
735
			return (0);
736
		}
737
		if (op->of->type != MACH_REG) {
738
			return (0);
739
		}
740
		if (op->of->def.num != r2) {
741
			return (0);
742
		}
743
		if (op->of->plus != null) {
744
			return (0);
745
		}
746
	}
2 7u83 747
 
6 7u83 748
	/* Check the size of the current operation */
749
	if (!is_simple(p->ins_no) || instr_sz[p->ins_no] != sz) {
750
		return (0);
751
	}
2 7u83 752
 
6 7u83 753
	/* Check if the first operand is (r2) */
754
	if (p->op1) {
755
		op = p->op1;
756
		if (op->type != MACH_CONT) {
757
			use_op1 = 0;
758
		} else {
759
			if (op->of->type != MACH_REG) {
760
				use_op1 = 0;
761
			}
762
			if (op->of->def.num != r2) {
763
				use_op1 = 0;
764
			}
765
			if (op->of->plus != null) {
766
				use_op1 = 0;
767
			}
768
		}
2 7u83 769
	} else {
6 7u83 770
		use_op1 = 0;
2 7u83 771
	}
772
 
6 7u83 773
	/* Check if the second operand is (r2) */
774
	if (p->op2) {
775
		op = p->op2;
776
		if (op->type != MACH_CONT) {
777
			use_op2 = 0;
778
		} else {
779
			if (op->of->type != MACH_REG) {
780
				use_op2 = 0;
781
			}
782
			if (op->of->def.num != r2) {
783
				use_op2 = 0;
784
			}
785
			if (op->of->plus != null) {
786
				use_op2 = 0;
787
			}
788
		}
2 7u83 789
	} else {
6 7u83 790
		use_op2 = 0;
2 7u83 791
	}
792
 
6 7u83 793
	/* Check that the operands are alright */
794
	if (use_op1 + use_op2 != 1) {
795
		return (0);
796
	}
797
	if (use_op1 && check_op(p->op2, r2)) {
798
		return (0);
799
	}
800
	if (use_op2 && check_op(p->op1, r2)) {
801
		return (0);
802
	}
2 7u83 803
 
6 7u83 804
	/* Make the change */
805
	reclaim_ins(q->next->next);
806
	reclaim_ins(q->next);
807
	if (use_op1) {
808
		free_mach_op(p->op1);
809
		p->op1 = (incr ? make_inc_sp(): make_dec_sp());
810
		p->op1->def.num = r1;
811
	} else {
812
		free_mach_op(p->op2);
813
		p->op2 = (incr ? make_inc_sp(): make_dec_sp());
814
		p->op2->def.num = r1;
815
	}
816
	p->changed |= regmsk(r1);
817
	q->next = p;
818
	if (p->next) {
819
		p->next->op1->of->def.num = r1;
820
		if (incr)p->next->op1->of->plus = make_value(-sz);
821
	} else {
822
		if (use_op2)have_cond = 0;
823
	}
824
	return (1);
2 7u83 825
}