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 5

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