Subversion Repositories tendra.SVN

Rev

Rev 2 | Go to most recent revision | Details | Compare with Previous | 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/mach_op.c,v 1.1.1.1 1998/01/17 15:55:49 release Exp $
35
--------------------------------------------------------------------------
36
$Log: mach_op.c,v $
37
 * Revision 1.1.1.1  1998/01/17  15:55:49  release
38
 * First version to be checked into rolling release.
39
 *
40
Revision 1.2  1997/10/29 10:22:21  ma
41
Replaced use_alloca with has_alloca.
42
 
43
Revision 1.1.1.1  1997/10/13 12:42:55  ma
44
First version.
45
 
46
Revision 1.3  1997/09/25 06:45:15  ma
47
All general_proc tests passed
48
 
49
Revision 1.2  1997/06/18 10:09:37  ma
50
Checking in before merging with Input Baseline changes.
51
 
52
Revision 1.1.1.1  1997/03/14 07:50:15  ma
53
Imported from DRA
54
 
55
 * Revision 1.2  1996/09/20  13:51:39  john
56
 * *** empty log message ***
57
 *
58
 * Revision 1.1.1.1  1996/09/20  10:56:55  john
59
 *
60
 * Revision 1.1.1.1  1996/03/26  15:45:14  john
61
 *
62
 * Revision 1.1  93/02/22  17:16:07  17:16:07  ra (Robert Andrews)
63
 * Initial revision
64
 *
65
--------------------------------------------------------------------------
66
*/
67
 
68
 
69
#include "config.h"
70
#include "common_types.h"
71
#include "instrs.h"
72
#include "mach.h"
73
#include "mach_ins.h"
74
#include "mach_op.h"
75
#include "codex.h"
76
#include "output.h"
77
#include "utility.h"
78
 
79
#ifndef tdf3
80
#define  par2_pl        4       /* procedure argument accessed by use of A5 */
81
#define  par3_pl        5       /* procedure argument accessed by use of SP */
82
#endif
83
 
84
 
85
/*
86
    LIST OF FREE OPERANDS
87
 
88
    A list of free mach_op's, linked by the plus field.
89
*/
90
 
91
static mach_op *mach_op_list = null ;
92
 
93
 
94
/*
95
    ALLOCATE A NEW OPERAND
96
 
97
    This routine returns a pointer to a mach_op.  This is taken from the
98
    list of free mach_op's.
99
*/
100
#ifndef tdf3
101
#ifdef EBUG
102
static int next_id = 0 ;
103
#endif
104
#endif
105
 
106
mach_op *new_mach_op
107
    PROTO_Z ()
108
{
109
    mach_op *p ;
110
    if ( mach_op_list == null ) {
111
	int i, n = 1000 ;
112
	p = alloc_nof ( mach_op, n ) ;
113
	for ( i = 0 ; i < n - 1 ; i++ ) {
114
	    ( p + i )->plus = p + ( i + 1 ) ;
115
	    ( p + i )->of = null ;
116
	}
117
	( p + ( n - 1 ) )->plus = null ;
118
	( p + ( n - 1 ) )->of = null ;
119
	mach_op_list = p ;
120
    }
121
    p = mach_op_list ;
122
    if ( p->of ) {
123
	mach_op *q = p->of ;
124
	mach_op_list = q ;
125
	while ( q->plus ) q = q->plus ;
126
	q->plus = p->plus ;
127
    } else {
128
	mach_op_list = p->plus ;
129
    }
130
    p->def.num = 0 ;
131
    p->plus = null ;
132
    p->of = null ;
133
#ifndef tdf3
134
#ifdef EBUG
135
    if (next_id == 70) {
136
       int dummy = next_id ;
137
    }
138
 
139
    p->id = next_id ++ ;
140
#endif
141
#endif
142
    return ( p ) ;
143
}
144
 
145
 
146
/*
147
    FREE AN OPERAND
148
 
149
    A mach_op is freed by adding it to the list of free mach_op's.
150
*/
151
 
152
void free_mach_op
153
    PROTO_N ( ( ptr ) )
154
    PROTO_T ( mach_op *ptr )
155
{
156
    mach_op *p = ptr ;
157
    if ( p == null ) return ;
158
    while ( p->plus ) p = p->plus ;
159
    p->plus = mach_op_list ;
160
    mach_op_list = ptr ;
161
    return ;
162
}
163
 
164
 
165
/*
166
    SPECIAL LABELS INFORMATION
167
 
168
    A special label consists of the label prefix, "L", followed by the
169
    special label identifier, followed by the value of special_no for
170
    the current procedure.  A particular special label is that with
171
    identifier special_str.
172
*/
173
 
174
long special_no = 0 ;
175
char *special_str = "S" ;
176
 
177
 
178
/*
179
    TEMPORARY REGISTER STATUS
180
 
181
    This records the number of temporary registers which have been allocated
182
    at any given moment, any temporary register preferences and the last
183
    temporary register used.
184
*/
185
 
186
int tmp_reg_status = 0 ;
187
int tmp_reg_prefer = 0 ;
188
static int last_reg = 0 ;
189
 
190
 
191
/*
192
    FIND THE NUMBER OF THE NEXT TEMPORARY REGISTER
193
 
194
    This is a look-ahead routine to find what the next temporary register
195
    allocated will be.  Let X denote the prefered temporary register
196
    (if specified) and Y denote any A-register used in the procedure
197
    but not currently active.
198
 
199
    If X is specified, it will always be the first temporary register
200
    returned.  The second will be Y, if that exists, or A1, unless
201
    this equals X, if which case A0 is used.
202
 
203
    If X is not specified, the first temporary register will be Y,
204
    if that exists, or A1.  The second will be A1 if Y exists, or
205
    A0 otherwise.
206
 
207
    Under very rare conditions a third temporary register is required.
208
    In these cases D0 always suffices.
209
*/
210
 
211
int next_tmp_reg
212
    PROTO_Z ()
213
{
214
    int r ;
215
    int t = tmp_reg_status ;
216
    if ( t > 1 ) {
217
	debug_warning ( "Temporary D-register used" ) ;
218
	r = REG_D0 ;
219
    } else if ( tmp_reg_prefer ) {
220
	if ( t == 0 ) {
221
	    r = tmp_reg_prefer ;
222
	    last_reg = r ;
223
	} else {
224
	    bitpattern na = ( regsinuse | reuseables | regsindec ) ;
225
	    bitpattern a = regsinproc & ~na & 0x3c00 ;
226
	    r = ( a ? reg ( a ) : REG_A1 ) ;
227
	    if ( r == last_reg ) r = REG_A0 ;
228
	}
229
    } else {
230
	bitpattern na = ( regsinuse | reuseables | regsindec ) ;
231
	bitpattern a = regsinproc & ~na & 0x3c00 ;
232
	if ( t == 0 ) {
233
	    r = ( a ? reg ( a ) : REG_A1 ) ;
234
	    last_reg = r ;
235
	} else {
236
	    r = ( a ? REG_A1 : REG_A0 ) ;
237
	    if ( r == last_reg ) r = ( r == REG_A0 ? REG_A1 : REG_A0 ) ;
238
	}
239
    }
240
    return ( r ) ;
241
}
242
 
243
 
244
/*
245
    AVOID A GIVEN TEMPORARY REGISTER
246
 
247
    This marks the given register number as to be avoided by pretending
248
    that it was the previous temporary register.
249
*/
250
 
251
void avoid_tmp_reg
252
    PROTO_N ( ( r ) )
253
    PROTO_T ( int r )
254
{
255
    last_reg = r ;
256
    tmp_reg_status++ ;
257
    return ;
258
}
259
 
260
 
261
/*
262
    MOVE AN OPERAND INTO A TEMPORARY REGISTER
263
 
264
    It is sometimes necessary to move an operand into a temporary address
265
    register.  A move instruction (given by instr) is output, and the
266
    number of the temporary register is returned.
267
*/
268
 
269
int tmp_reg
270
    PROTO_N ( ( instr, ptr ) )
271
    PROTO_T ( int instr X mach_op *ptr )
272
{
273
    int t = tmp_reg_status ;
274
    int r = next_tmp_reg () ;
275
    mach_op *p = new_mach_op () ;
276
    p->type = MACH_REG ;
277
    p->def.num = ( long ) r ;
278
    make_instr_aux ( instr, ptr, p, regmsk ( r ), 1 ) ;
279
    regsinproc |= regmsk ( r ) ;
280
    tmp_reg_status = t + 1 ;
281
    return ( r ) ;
282
}
283
 
284
 
285
/*
286
    TEST IF A REGISTER IS USED IN AN OPERAND
287
 
288
    This routine returns 1 if register r is used in the operand op.
289
*/
290
 
291
bool check_op
292
    PROTO_N ( ( op, r ) )
293
    PROTO_T ( mach_op *op X int r )
294
{
295
    if ( op == null ) return ( 0 ) ;
296
    switch ( op->type ) {
297
 
298
	case MACH_CONT : return ( ( op->def.num ) & regmsk ( r ) ? 1 : 0 ) ;
299
 
300
	case MACH_REG :
301
	case MACH_DEC :
302
	case MACH_INC : return ( op->def.num == r ? 1 : 0 ) ;
303
 
304
	case MACH_BF : return ( check_op ( op->of, r ) ) ;
305
 
306
	case MACH_RPAIR : {
307
	    if ( op->def.num == r ) return ( 1 ) ;
308
	    return ( op->plus->def.num == r ? 1 : 0 ) ;
309
	}
310
    }
311
    return ( 0 ) ;
312
}
313
 
314
 
315
/*
316
    TEST IF TWO OPERANDS ARE EQUAL
317
 
318
    This returns 1 if the two operands have equal effect.  Note that,
319
    for example, consecutive uses of the same pre-decremented register,
320
    although having the same representation, are not equal in this
321
    context.
322
*/
323
 
324
bool equal_op
325
    PROTO_N ( ( op1, op2 ) )
326
    PROTO_T ( mach_op *op1 X mach_op *op2 )
327
{
328
    mach_op *p1 = op1, *p2 = op2 ;
329
    while ( p1 && p2 ) {
330
	if ( p1->type != p2->type ) return ( 0 ) ;
331
	if ( p1->type == MACH_DEC || p1->type == MACH_INC ) return ( 0 ) ;
332
	if ( p1->def.num != p2->def.num ) return ( 0 ) ;
333
	if ( p1->plus ) {
334
	    if ( p2->plus == null ) return ( 0 ) ;
335
	    if ( !equal_op ( p1->plus, p2->plus ) ) return ( 0 ) ;
336
	} else {
337
	    if ( p2->plus ) return ( 0 ) ;
338
	}
339
	p1 = p1->of ;
340
	p2 = p2->of ;
341
    }
342
    return ( p1 == p2 ? 1 : 0 ) ;
343
}
344
 
345
 
346
/*
347
    MAKE AN INTEGER CONSTANT OPERAND
348
 
349
    This and the subsequent routines are used to allocate machine operands.
350
    The constructions are simple applications of the descriptions given
351
    in mach.h.  They need very little other comment.
352
*/
353
 
354
mach_op *make_value
355
    PROTO_N ( ( n ) )
356
    PROTO_T ( long n )
357
{
358
    mach_op *p = new_mach_op () ;
359
    p->type = MACH_VAL ;
360
    p->def.num = n ;
361
    return ( p ) ;
362
}
363
 
364
 
365
/*
366
    MAKE AN INTEGER DATA OPERAND
367
*/
368
 
369
mach_op *make_int_data
370
    PROTO_N ( ( n ) )
371
    PROTO_T ( long n )
372
{
373
    mach_op *p = new_mach_op () ;
374
    p->type = MACH_VALQ ;
375
    p->def.num = n ;
376
    return ( p ) ;
377
}
378
 
379
 
380
/*
381
    MAKE A HEXADECIMAL INTEGER CONSTANT OPERAND
382
*/
383
 
384
mach_op *make_hex_value
385
    PROTO_N ( ( n ) )
386
    PROTO_T ( long n )
387
{
388
    mach_op *p = new_mach_op () ;
389
    p->type = MACH_HEX ;
390
    p->def.num = n ;
391
    return ( p ) ;
392
}
393
 
394
 
395
/*
396
    MAKE A HEXADECIMAL INTEGER CONSTANT DATA OPERAND
397
*/
398
 
399
mach_op *make_hex_data
400
    PROTO_N ( ( n ) )
401
    PROTO_T ( long n )
402
{
403
    mach_op *p = new_mach_op () ;
404
    p->type = MACH_HEXQ ;
405
    p->def.num = n ;
406
    return ( p ) ;
407
}
408
 
409
 
410
/*
411
    MAKE A FLOATING POINT DATA OPERAND
412
*/
413
 
414
mach_op *make_float_data
415
    PROTO_N ( ( f ) )
416
    PROTO_T ( flt *f )
417
{
418
    mach_op *p = new_mach_op () ;
419
    p->type = MACH_FLOATQ ;
420
    p->def.fp = f ;
421
    return ( p ) ;
422
}
423
 
424
 
425
/*
426
    MAKE A LABEL OPERAND
427
*/
428
 
429
mach_op *make_lab
430
    PROTO_N ( ( n, d ) )
431
    PROTO_T ( long n X long d )
432
{
433
    mach_op *p1 = new_mach_op () ;
434
    p1->type = MACH_LAB ;
435
    p1->def.num = n ;
436
    if ( d ) {
437
	mach_op *p2 = new_mach_op () ;
438
	p2->type = MACH_VAL ;
439
	p2->def.num = d ;
440
	p1->plus = p2 ;
441
    }
442
    return ( p1 ) ;
443
}
444
 
445
 
446
/*
447
    MAKE A LABEL DATA OPERAND
448
*/
449
 
450
mach_op *make_lab_data
451
    PROTO_N ( ( n, d ) )
452
    PROTO_T ( long n X long d )
453
{
454
    mach_op *p1 = new_mach_op () ;
455
    p1->type = MACH_LABQ ;
456
    p1->def.num = n ;
457
    if ( d ) {
458
	mach_op *p2 = new_mach_op () ;
459
	p2->type = MACH_VAL ;
460
	p2->def.num = d ;
461
	p1->plus = p2 ;
462
    }
463
    return ( p1 ) ;
464
}
465
 
466
 
467
/*
468
    MAKE AN OPERAND CORRESPONDING TO THE DIFFERENCE OF TWO LABELS
469
*/
470
 
471
mach_op *make_lab_diff
472
    PROTO_N ( ( a, b ) )
473
    PROTO_T ( long a X long b )
474
{
475
    mach_op *p1 = new_mach_op () ;
476
    mach_op *p2 = new_mach_op () ;
477
    mach_op *p3 = new_mach_op () ;
478
    p1->type = MACH_LABQ ;
479
    p1->def.num = a ;
480
    p1->plus = p2 ;
481
    p2->type = MACH_NEG ;
482
    p2->plus = p3 ;
483
    p3->type = MACH_LABQ ;
484
    p3->def.num = b ;
485
    return ( p1 ) ;
486
}
487
 
488
 
489
/*
490
    MAKE AN EXTERNAL OPERAND
491
*/
492
 
493
mach_op *make_extern
494
    PROTO_N ( ( nm, d ) )
495
    PROTO_T ( char *nm X long d )
496
{
497
    mach_op *p1 = new_mach_op () ;
498
    p1->type = MACH_EXT ;
499
    p1->def.str = nm ;
500
    if ( d ) {
501
	mach_op *p2 = new_mach_op () ;
502
	p2->type = MACH_VAL ;
503
	p2->def.num = d ;
504
	p1->plus = p2 ;
505
    }
506
    return ( p1 ) ;
507
}
508
 
509
 
510
/*
511
    MAKE AN EXTERNAL DATA OPERAND
512
*/
513
 
514
mach_op *make_extern_data
515
    PROTO_N ( ( nm, d ) )
516
    PROTO_T ( char *nm X long d )
517
{
518
    mach_op *p1 = new_mach_op () ;
519
    p1->type = MACH_EXTQ ;
520
    p1->def.str = nm ;
521
    if ( d ) {
522
	mach_op *p2 = new_mach_op () ;
523
	p2->type = MACH_VAL ;
524
	p2->def.num = d ;
525
	p1->plus = p2 ;
526
    }
527
    return ( p1 ) ;
528
}
529
 
530
 
531
/*
532
    MAKE A SPECIAL LABEL OPERAND
533
*/
534
 
535
mach_op *make_special
536
    PROTO_N ( ( nm ) )
537
    PROTO_T ( char *nm )
538
{
539
    mach_op *p = new_mach_op () ;
540
    p->type = MACH_SPEC ;
541
    p->def.str = nm ;
542
    return ( p ) ;
543
}
544
 
545
 
546
/*
547
    MAKE A SPECIAL LABEL DATA OPERAND
548
*/
549
 
550
mach_op *make_special_data
551
    PROTO_N ( ( nm ) )
552
    PROTO_T ( char *nm )
553
{
554
    mach_op *p = new_mach_op () ;
555
    p->type = MACH_SPECQ ;
556
    p->def.str = nm ;
557
    return ( p ) ;
558
}
559
 
560
 
561
/*
562
    MAKE A LABEL INDIRECT OPERAND
563
*/
564
 
565
mach_op *make_lab_ind
566
    PROTO_N ( ( n, d ) )
567
    PROTO_T ( long n X long d )
568
{
569
    mach_op *p1 = new_mach_op () ;
570
    mach_op *p2 = new_mach_op () ;
571
    p1->type = MACH_CONT ;
572
    p1->def.num = 0 ;
573
    p1->of = p2 ;
574
    p2->type = MACH_LAB ;
575
    p2->def.num = n ;
576
    if ( d ) {
577
	mach_op *p3 = new_mach_op () ;
578
	p3->type = MACH_VAL ;
579
	p3->def.num = d ;
580
	p2->plus = p3 ;
581
    }
582
    return ( p1 ) ;
583
}
584
 
585
 
586
/*
587
    MAKE AN EXTERNAL INDIRECT OPERAND
588
*/
589
 
590
mach_op *make_extern_ind
591
    PROTO_N ( ( nm, d ) )
592
    PROTO_T ( char *nm X long d )
593
{
594
    mach_op *p1 = new_mach_op () ;
595
    mach_op *p2 = new_mach_op () ;
596
    p1->type = MACH_CONT ;
597
    p1->def.num = 0 ;
598
    p1->of = p2 ;
599
    p2->type = MACH_EXT ;
600
    p2->def.str = nm ;
601
    if ( d ) {
602
	mach_op *p3 = new_mach_op () ;
603
	p3->type = MACH_VAL ;
604
	p3->def.num = d ;
605
	p2->plus = p3 ;
606
    }
607
    return ( p1 ) ;
608
}
609
 
610
 
611
/*
612
    MAKE A REGISTER DIRECT OPERAND
613
*/
614
 
615
mach_op *make_register
616
    PROTO_N ( ( r ) )
617
    PROTO_T ( int r )
618
{
619
    mach_op *p = new_mach_op () ;
620
    p->type = MACH_REG ;
621
    p->def.num = ( long ) r ;
622
    return ( p ) ;
623
}
624
 
625
/*
626
    MAKE PSEUDO OPERAND REPRESENTING LDISP
627
    (the space between sp and the parameters at procedure entry)
628
*/
629
 
630
mach_op *make_ldisp
631
    PROTO_N ( ( offset ) )
632
    PROTO_T ( long offset )
633
{
634
    mach_op *p1 = new_mach_op () ;
635
    p1->type = MACH_SPEC ;
636
    p1->def.str = special_str ;
637
    if (offset) {
638
       p1->plus = new_mach_op () ;
639
       p1->plus->type = MACH_VAL ;
640
       p1->plus->def.num = offset ;
641
    }
642
    return ( p1 ) ;
643
}
644
 
645
 
646
/*
647
    MAKE A REGISTER INDIRECT WITH DISPLACEMENT OPERAND
648
 
649
    This is the first example where a temporary register may be required.
650
    Under very rare circumstances, we may be trying to address relative
651
    to a D-register, if which case we need to use a temporary A-register
652
    instead.
653
*/
654
 
655
mach_op *make_indirect
656
    PROTO_N ( ( r, d ) )
657
    PROTO_T ( int r X long d )
658
{
659
    mach_op *p1 = new_mach_op () ;
660
    mach_op *p2 = new_mach_op () ;
661
    p1->type = MACH_CONT ;
662
    p1->def.num = regmsk ( r ) ;
663
    p2->type = MACH_REG ;
664
    p2->def.num = ( long ) r ;
665
    if ( is_dreg ( r ) ) {
666
	int t = tmp_reg ( m_movl, p2 ) ;
667
	p2 = new_mach_op () ;
668
	p2->type = MACH_REG ;
669
	p2->def.num = ( long ) t ;
670
	p1->def.num = regmsk ( t ) ;
671
    }
672
    p1->of = p2 ;
673
    if ( d ) {
674
	mach_op *p3 = new_mach_op () ;
675
	p3->type = MACH_VAL ;
676
	p3->def.num = d ;
677
	p2->plus = p3 ;
678
    }
679
    return ( p1 ) ;
680
}
681
 
682
 
683
/*
684
    MAKE A APPLICATION POINTER INDIRECT WITH DISPLACEMENT OPERAND
685
 
686
    Since we don't want to use an applications pointer unless absolutely
687
    necessary, this is often changed into a stack pointer indirect
688
    with displacement operand.
689
*/
690
 
691
mach_op *make_rel_ap
692
    PROTO_N ( ( d ) )
693
    PROTO_T ( long d )
694
{
695
    mach_op *p1 = new_mach_op () ;
696
    mach_op *p2 = new_mach_op () ;
697
    p1->type = MACH_CONT ;
698
    p1->def.num = 0 ;
699
    p2->type = MACH_REG ;
700
    p1->of = p2 ;
701
    if ( d > 0 ) {
702
	if ( !used_stack ) {
703
	    /* Use stack pointer instead of application pointer */
704
	    long s = stack_size + stack_change ;
705
	    mach_op *p3 = new_mach_op () ;
706
	    mach_op *p4 = new_mach_op () ;
707
	    p2->def.num = ( long ) REG_SP ;
708
	    p3->type = MACH_SPEC ;
709
	    p3->def.str = special_str ;
710
	    p2->plus = p3 ;
711
	    p4->type = MACH_VAL ;
712
	    p4->def.num = d - s / 8 ;
713
	    p3->plus = p4 ;
714
	    used_ldisp = 1 ;
715
	    return ( p1 ) ;
716
	}
717
	d += 4 ;
718
    }
719
    p2->def.num = ( long ) REG_AP ;
720
    if ( d ) {
721
	mach_op *p3 = new_mach_op () ;
722
	p3->type = MACH_VAL ;
723
	p3->def.num = d ;
724
	p2->plus = p3 ;
725
    }
726
    used_stack = 1 ;
727
    return ( p1 ) ;
728
}
729
 
730
#ifndef tdf3
731
/*
732
    MAKE A 2. APPLICATION POINTER INDIRECT WITH DISPLACEMENT OPERAND
733
 
734
    This application pointer A5 is used by general proc. to access
735
    the caller parameters, when there are a dynamic number of callees.
736
*/
737
 
738
mach_op *make_rel_ap2
739
    PROTO_N ( ( d ) )
740
    PROTO_T ( long d )
741
{
742
    mach_op *p1 = new_mach_op () ;
743
    mach_op *p2 = new_mach_op () ;
744
    mach_op *p3 = new_mach_op () ;
745
 
746
    p1->type = MACH_CONT ;
747
    p1->def.num = 0 ;
748
    p2->type = MACH_REG ;
749
    p1->of = p2 ;
750
    p2->def.num = ( long ) REG_A5 ;
751
 
752
    p3->type = MACH_VAL ;
753
    p3->def.num = d ;
754
    p2->plus = p3 ;
755
 
756
    used_stack = 1 ;
757
    return ( p1 ) ;
758
}
759
/*
760
   Used to access caller parrameters in the postlude.
761
 */
762
 
763
mach_op *make_rel_sp
764
    PROTO_N ( ( d ) )
765
    PROTO_T ( long d )
766
{
767
    mach_op *p1 = new_mach_op () ;
768
    mach_op *p2 = new_mach_op () ;
769
    mach_op *p3 = new_mach_op () ;
770
    long s = stack_size + stack_change ;
771
 
772
    p1->type = MACH_CONT ;
773
    p1->def.num = 0 ;
774
    p1->of = p2 ;
775
 
776
    p2->type = MACH_REG ;
777
    p2->def.num = ( long ) REG_SP ;
778
    p2->plus = p3 ;
779
 
780
    p3->type = MACH_VAL ;
781
    p3->def.num = d - s / 8 ;
782
 
783
    return ( p1 ) ;
784
}
785
 
786
#endif
787
 
788
/*
789
    MAKE A REGISTER INDIRECT WITH INDEX OPERAND
790
 
791
    Again we have to be careful, in case r1 is a D-register.
792
*/
793
 
794
mach_op *make_reg_index
795
    PROTO_N ( ( r1, r2, d, sf ) )
796
    PROTO_T ( int r1 X int r2 X long d X int sf )
797
{
798
    mach_op *p1 = new_mach_op () ;
799
    mach_op *p2 = new_mach_op () ;
800
    mach_op *p3 = new_mach_op () ;
801
    mach_op *p4 = new_mach_op () ;
802
    p1->type = MACH_CONT ;
803
    p2->type = MACH_REG ;
804
    p2->def.num = ( long ) r1 ;
805
    if ( is_dreg ( r1 ) ) {
806
	int t = tmp_reg ( m_movl, p2 ) ;
807
	p2 = new_mach_op () ;
808
	p2->type = MACH_REG ;
809
	p2->def.num = ( long ) t ;
810
	p1->def.num = ( regmsk ( t ) | regmsk ( r2 ) ) ;
811
    } else {
812
	p1->def.num = ( regmsk ( r1 ) | regmsk ( r2 ) ) ;
813
    }
814
    p1->of = p2 ;
815
    p2->plus = p3 ;
816
    p3->type = MACH_SCALE ;
817
    p3->def.num = ( long ) sf ;
818
    p3->of = p4 ;
819
    p4->type = MACH_REG ;
820
    p4->def.num = ( long ) r2 ;
821
    if ( d ) {
822
	mach_op *p5 = new_mach_op () ;
823
	p5->type = MACH_VAL ;
824
	p5->def.num = d ;
825
	p3->plus = p5 ;
826
    }
827
    return ( p1 ) ;
828
}
829
 
830
 
831
/*
832
    MAKE A APPLICATION POINTER INDEXED WITH DISPLACEMENT OPERAND
833
 
834
    It is always quicker to do this using a temporary register rather
835
    than using the complex addressing mode.  However we do use the
836
    latter course when temporary registers are short.
837
 
838
    Typ determines the type of the application pointer.
839
*/
840
 
841
mach_op *_make_ind_rel_ap
842
    PROTO_N ( ( d, e, typ ) )
843
    PROTO_T ( long d X long e X int typ )
844
{
845
    mach_op *p1, *p2 ;
846
 
847
    switch (typ) {
848
    case par2_pl :
849
      p2 = make_rel_ap2 ( d ) ;
850
      break ;
851
    case par3_pl :
852
      p2 = make_rel_sp ( d ) ;
853
      break ;
854
    default :
855
      p2 = make_rel_ap ( d ) ;
856
    }
857
 
858
    if ( tmp_reg_status < 2 ) {
859
	int t = tmp_reg ( m_movl, p2 ) ;
860
	return ( make_indirect ( t, e ) ) ;
861
    }
862
 
863
    debug_warning ( "Complex operand" ) ;
864
 
865
    p1 = new_mach_op () ;
866
    p1->type = MACH_CONT ;
867
    p1->def.num = 0 ;
868
    p1->of = p2 ;
869
    if ( e ) {
870
	mach_op *p3 = new_mach_op () ;
871
	p3->type = MACH_VAL ;
872
	p3->def.num = e ;
873
	p2->plus = p3 ;
874
    }
875
    return ( p1 ) ;
876
}
877
 
878
mach_op *make_ind_rel_ap
879
    PROTO_N ( ( d, e) )
880
    PROTO_T ( long d X long e )
881
{
882
   return _make_ind_rel_ap ( d, e, 0 ) ;
883
}
884
 
885
mach_op *make_ind_rel_ap2
886
    PROTO_N ( ( d, e) )
887
    PROTO_T ( long d X long e )
888
{
889
   return _make_ind_rel_ap ( d, e, par2_pl ) ;
890
}
891
mach_op *make_ind_rel_ap3
892
    PROTO_N ( ( d, e) )
893
    PROTO_T ( long d X long e )
894
{
895
   return _make_ind_rel_ap ( d, e, par3_pl ) ;
896
}
897
 
898
 
899
 
900
/*
901
    MAKE A PRE-DECREMENT STACK POINTER OPERAND
902
*/
903
 
904
mach_op *make_dec_sp
905
    PROTO_Z ()
906
{
907
    mach_op *p = new_mach_op () ;
908
    p->type = MACH_DEC ;
909
    p->def.num = ( long ) REG_SP ;
910
    return ( p ) ;
911
}
912
 
913
 
914
/*
915
    MAKE A POST-INCREMENT STACK POINTER OPERAND
916
*/
917
 
918
mach_op *make_inc_sp
919
    PROTO_Z ()
920
{
921
    mach_op *p = new_mach_op () ;
922
    p->type = MACH_INC ;
923
    p->def.num = ( long ) REG_SP ;
924
    return ( p ) ;
925
}
926
 
927
#ifndef tdf3
928
/*
929
    MAKE A PRE-DECREMENT REGISTER OPERAND
930
*/
931
 
932
mach_op *make_predec
933
    PROTO_N ( ( r ) )
934
    PROTO_T ( int r )
935
{
936
    mach_op *p = new_mach_op () ;
937
    p->type = MACH_DEC ;
938
    p->def.num = ( long ) r ;
939
    return ( p ) ;
940
}
941
#endif
942
 
943
/*
944
    MAKE A POSTINCREMENT REGISTER OPERAND
945
*/
946
 
947
mach_op *make_postinc
948
    PROTO_N ( ( r ) )
949
    PROTO_T ( int r )
950
{
951
    mach_op *p = new_mach_op () ;
952
    p->type = MACH_INC ;
953
    p->def.num = ( long ) r ;
954
    return ( p ) ;
955
}
956
 
957
 
958
/*
959
    MAKE A REGISTER PAIR
960
*/
961
 
962
mach_op *make_reg_pair
963
    PROTO_N ( ( r1, r2 ) )
964
    PROTO_T ( int r1 X int r2 )
965
{
966
    mach_op *p1 = new_mach_op () ;
967
    mach_op *p2 = new_mach_op () ;
968
    p1->type = MACH_RPAIR ;
969
    p1->def.num = ( long ) r1 ;
970
    p1->plus = p2 ;
971
    p2->type = MACH_REG ;
972
    p2->def.num = ( long ) r2 ;
973
    return ( p1 ) ;
974
}
975
 
976
 
977
/*
978
    MAKE AN INDEX OPERAND
979
 
980
    The machine operands op1 and op2 are turned into an index operand
981
    with scale factor sf.  Unless op1 is very simple or temporary
982
    registers are short, it is always quicker to move the contents of
983
    op1 into a temporary register.  A temporary register may also be
984
    required for op2, but hopefully not too often.
985
*/
986
 
987
mach_op *make_index_op
988
    PROTO_N ( ( op1, op2, sf ) )
989
    PROTO_T ( mach_op *op1 X mach_op *op2 X int sf )
990
{
991
    bitpattern u ;
992
    bool use_tmp = 1 ;
993
    mach_op *p1, *p2 = new_mach_op () ;
994
 
995
    if ( op1->type != MACH_CONT ) {
996
	error ( "Illegal indexing operand" ) ;
997
	return ( null ) ;
998
    }
999
 
1000
    p1 = op1->of ;
1001
    u = op1->def.num ;
1002
    if ( p1->type == MACH_REG ) {
1003
	use_tmp = is_dreg ( p1->def.num ) ;
1004
    } else if ( tmp_reg_status && op2->type != MACH_REG ) {
1005
	if ( p1->type == MACH_EXT && p1->plus == null ) {
1006
	    p1->type = MACH_EXTQ ;
1007
	    use_tmp = 0 ;
1008
	} else if ( p1->type == MACH_CONT ) {
1009
	    mach_op *q = p1->of ;
1010
	    if ( q->type == MACH_REG ) {
1011
		q = q->plus ;
1012
		if ( q == null || q->type != MACH_SCALE ) use_tmp = 0 ;
1013
	    }
1014
	}
1015
    }
1016
 
1017
    if ( use_tmp ) {
1018
	int t = tmp_reg ( m_movl, p1 ) ;
1019
	p1 = new_mach_op () ;
1020
	p1->type = MACH_REG ;
1021
	p1->def.num = ( long ) t ;
1022
	u = regmsk ( t ) ;
1023
    }
1024
    op1->of = p1 ;
1025
    p2->type = MACH_SCALE ;
1026
    p2->def.num = ( long ) sf ;
1027
    p2->plus = p1->plus ;
1028
    p1->plus = p2 ;
1029
    if ( op2->type == MACH_REG ) {
1030
	u |= regmsk ( op2->def.num ) ;
1031
    } else {
1032
	int t = tmp_reg ( m_movl, op2 ) ;
1033
	op2 = new_mach_op () ;
1034
	op2->type = MACH_REG ;
1035
	op2->def.num = ( long ) t ;
1036
	u |= regmsk ( t ) ;
1037
    }
1038
    p2->of = op2 ;
1039
    op1->def.num = u ;
1040
    return ( op1 ) ;
1041
}
1042
 
1043
 
1044
/*
1045
    MAKE A BITFIELD OPERAND
1046
 
1047
    The machine operand op is turned into the corresponding bitfield
1048
    operand.
1049
*/
1050
 
1051
mach_op *make_bitfield_op
1052
    PROTO_N ( ( op, bf_off, bf_bits ) )
1053
    PROTO_T ( mach_op *op X int bf_off X int bf_bits )
1054
{
1055
    mach_op *p1 = new_mach_op () ;
1056
    mach_op *p2 = new_mach_op () ;
1057
    p1->type = MACH_BF ;
1058
    p1->def.num = ( long ) bf_off ;
1059
    p1->plus = p2 ;
1060
    p1->of = op ;
1061
    p2->type = MACH_VAL ;
1062
    p2->def.num = ( long ) bf_bits ;
1063
    return ( p1 ) ;
1064
}