Subversion Repositories tendra.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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