Subversion Repositories tendra.SVN

Rev

Rev 5 | Details | Compare with Previous | 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/instr.c,v 1.1.1.1 1998/01/17 15:55:49 release Exp $
65
--------------------------------------------------------------------------
66
$Log: instr.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.4  1997/11/13 08:27:12  ma
71
All avs test passed (except add_to_ptr).
72
 
73
Revision 1.3  1997/11/09 14:10:04  ma
74
Added comment.
75
 
76
Revision 1.2  1997/10/29 10:22:18  ma
77
Replaced use_alloca with has_alloca.
78
 
79
Revision 1.1.1.1  1997/10/13 12:42:54  ma
80
First version.
81
 
82
Revision 1.6  1997/10/13 08:49:32  ma
83
Made all pl_tests for general proc & exception handling pass.
84
 
85
Revision 1.5  1997/09/25 06:45:09  ma
86
All general_proc tests passed
87
 
88
Revision 1.4  1997/06/18 12:04:54  ma
89
Merged with Input Baseline changes.
90
 
91
Revision 1.3  1997/06/18 10:09:34  ma
92
Checking in before merging with Input Baseline changes.
93
 
94
Revision 1.2  1997/04/20 11:30:29  ma
95
Introduced gcproc.c & general_proc.[ch].
96
Added cases for apply_general_proc next to apply_proc in all files.
97
 
98
Revision 1.1.1.1  1997/03/14 07:50:13  ma
99
Imported from DRA
100
 
101
 * Revision 1.1.1.1  1996/09/20  10:57:00  john
102
 *
103
 * Revision 1.3  1996/07/30  16:31:02  john
104
 * Removed offset conversion
105
 *
106
 * Revision 1.2  1996/07/05  14:20:49  john
107
 * Changes for spec 3.1
108
 *
109
 * Revision 1.1.1.1  1996/03/26  15:45:12  john
110
 *
111
 * Revision 1.3  94/02/21  15:59:15  15:59:15  ra (Robert Andrews)
112
 * Make a couple of integer literals into longs.
113
 *
114
 * Revision 1.2  93/11/19  16:21:50  16:21:50  ra (Robert Andrews)
115
 * Added proc_tag case.
116
 *
117
 * Revision 1.1  93/02/22  17:15:50  17:15:50  ra (Robert Andrews)
118
 * Initial revision
119
 *
120
--------------------------------------------------------------------------
121
*/
122
 
123
 
124
#include "config.h"
125
#include "common_types.h"
126
#include "exp.h"
127
#include "expmacs.h"
128
#include "install_fns.h"
129
#include "externs.h"
130
#include "shapemacs.h"
131
#include "tags.h"
132
#include "instrs.h"
133
#include "mach.h"
134
#include "mach_ins.h"
135
#include "mach_op.h"
136
#include "codex.h"
137
#include "evaluate.h"
138
#include "utility.h"
139
#include "where.h"
140
#include "coder.h"
141
#include "instr.h"
142
#include "translate.h"
143
 
144
 
145
/*
146
    FIND THE EXTERNAL NAME OF AN OPERAND
147
 
148
    The expression e, representing an external, is looked up in the main_globals
149
    table, and its external name is returned.
150
*/
151
 
6 7u83 152
static char *
153
extname(exp e)
2 7u83 154
{
6 7u83 155
	dec *d = brog(e);
2 7u83 156
#if 0
6 7u83 157
	if (d->dec_u.dec_val.external_register) {
158
		error("External registers not yet implemented");
159
		return ("????");
160
	}
2 7u83 161
#endif
6 7u83 162
	return (d->dec_u.dec_val.dec_id);
2 7u83 163
}
164
 
165
 
166
/*
167
    MACROS
168
 
169
    These macros are used as convenient shorthands in operand.
170
*/
171
 
6 7u83 172
#define make_ind(X, Y)		make_indirect(reg(X), (Y) / 8)
173
#define make_ext(X, Y)		make_extern(extname(X), (Y) / 8)
174
#define make_ext_ind(X, Y)	make_extern_ind(extname(X), (Y) / 8)
2 7u83 175
 
176
 
177
/*
178
    TRANSLATE AN INDEX OPERAND
179
 
180
    The operand corresponding to w1 indexed by w2 times sf is translated into
181
    a mach_op.
182
*/
183
 
6 7u83 184
static mach_op *
185
index_opnd(where w1, where w2, int sf)
2 7u83 186
{
6 7u83 187
	mach_op *op1, *op2;
188
	if (name(w2.wh_exp) != name_tag) {
189
		error("Illegal index operand");
190
		return (null);
191
	}
192
	op1 = operand(L32, w1);
193
	op2 = operand(L32, w2);
194
	return (make_index_op(op1, op2, sf));
2 7u83 195
}
196
 
197
 
198
/*
199
    ERROR MESSAGE
200
 
201
    In debugging mode a little extra information is always useful.
202
*/
203
 
204
#ifdef EBUG
6 7u83 205
static char *illegal_operand = "Illegal operand, case %d";
2 7u83 206
#else
6 7u83 207
static char *illegal_operand = "Illegal operand";
2 7u83 208
#endif
209
 
210
 
211
/*
212
    TRANSLATE A TDF OPERAND INTO A MACHINE OPERAND
213
 
214
    The value wh of size sz is converted into a mach_op.
215
*/
216
 
6 7u83 217
mach_op *
218
operand(long sz, where wh)
2 7u83 219
{
6 7u83 220
	long d;
221
	mach_op *op;
222
	exp w = wh.wh_exp;
223
	long off = wh.wh_off;
2 7u83 224
 
6 7u83 225
	switch (name(w)) {
226
	case val_tag: {
227
		long k = no(w) + off;
228
		if (is_offset(w)) {
229
			k /= 8;
2 7u83 230
		}
6 7u83 231
		if (sz == 8) {
232
			k &= 0xff;
2 7u83 233
		}
6 7u83 234
		if (sz == 16) {
235
			k &= 0xffff;
2 7u83 236
		}
6 7u83 237
		return (make_value(k));
238
	}
239
	case ident_tag:
240
	case labst_tag:
241
		switch (ptno(w)) {
242
		case var_pl:
243
			d = no(w) - off;
244
			return (make_rel_ap(- (d / 8)));
245
#ifndef tdf3
246
		case par2_pl:
247
			d = no(w) + off;
248
			return (make_rel_ap2(d / 8));
249
		case par3_pl:
250
			d = no(w) + off;
251
			return (make_rel_sp(d / 8));
2 7u83 252
#endif
6 7u83 253
		case par_pl:
254
			d = no(w) + off + 32;
255
			return (make_rel_ap(d / 8));
256
		case reg_pl:
257
			return (make_register(reg(no(w))));
258
		default:
259
			error(illegal_operand, 0);
260
			return (null);
2 7u83 261
		}
6 7u83 262
	case name_tag: {
263
		exp id = son(w);
264
		long d1 = no(w) + off;
265
		long d2 = no(id);
2 7u83 266
 
6 7u83 267
		if (isglob(id)) {
268
			if (name(sh(w)) == prokhd) {
2 7u83 269
#if 1
6 7u83 270
				if ((son(id) == nilexp ||
271
				     name(son(id)) == proc_tag ||
272
				     name(son(id)) == general_proc_tag))
2 7u83 273
#endif
6 7u83 274
					return (make_ext(id, d1));
2 7u83 275
 
6 7u83 276
			}
277
			return (make_ext_ind(id, d1));
2 7u83 278
		}
279
 
6 7u83 280
		switch (ptno(id)) {
2 7u83 281
#ifndef tdf3
6 7u83 282
		case par2_pl:
283
			return (make_rel_ap2((d1 + d2 ) / 8));
284
		case par3_pl:
285
			return (make_rel_sp((d1 + d2 ) / 8));
2 7u83 286
#endif
6 7u83 287
		case par_pl:
288
			return (make_rel_ap((d1 + d2 + 32) / 8));
289
		case var_pl:
290
			return (make_rel_ap((d1 - d2) / 8));
291
		case reg_pl:
292
			return (make_register(reg(d2)));
293
		default:
294
			error(illegal_operand, 1);
295
			return (null);
2 7u83 296
		}
297
	}
6 7u83 298
	case cont_tag:
299
	case ass_tag: {
300
		exp r = son(w);
301
		switch (name(r)) {
302
		case name_tag: {
303
			exp id = son(r);
304
			if (!isvar(id)) {
305
				if (isglob(id)) {
306
					int ra;
307
					if (name(sh(w)) == prokhd) {
308
						if (off) {
309
							error(illegal_operand,
310
							      2);
311
						}
312
						return (make_ext_ind(id, no(r)));
313
					}
314
					op = make_ext_ind(id, off);
315
					ra = tmp_reg(m_movl, op);
316
					return (make_indirect(ra, no(r) / 8));
317
				}
318
				switch (ptno(id)) {
319
				case par_pl:
320
					d = no(id) + no(r) + 32;
321
					op = make_ind_rel_ap(d / 8, off / 8);
322
					return (op);
2 7u83 323
#ifndef tdf3
6 7u83 324
				case par2_pl:
325
					d = no(id) + no(r);
326
					op = make_ind_rel_ap2(d / 8, off / 8);
327
					return (op);
328
				case par3_pl:
329
					d = no(id) + no(r);
330
					op = make_ind_rel_ap3(d / 8, off / 8);
331
					return (op);
2 7u83 332
#endif
6 7u83 333
				case var_pl:
334
					d = - (no(id)) + no(r);
335
					op = make_ind_rel_ap(d / 8, off / 8);
336
					return (op);
337
				case reg_pl:
338
					return (make_ind(no(id), off));
339
				default:
340
					error(illegal_operand, 4);
341
					return (null);
342
				}
343
			} else {
344
				where new_w;
345
				new_w.wh_exp = r;
346
				new_w.wh_off = off;
347
				return (operand(sz, new_w));
2 7u83 348
			}
349
		}
6 7u83 350
		case cont_tag: {
351
			exp rr = son(r);
352
			int roff = 0;
353
			if (name(rr) == reff_tag) {
354
				rr = son(rr);
355
				roff = no(rr);
356
			}
357
			switch (name(rr)) {
358
			case name_tag: {
359
				exp id = son(rr);
2 7u83 360
#if 0
6 7u83 361
				if (!isvar(id)) {
362
					error(illegal_operand, 5);
363
					return (null);
364
				}
2 7u83 365
#endif
6 7u83 366
				if (isglob(id)) {
367
					int ra;
368
					op = make_ext_ind(id, no(rr));
369
					ra = tmp_reg(m_movl, op);
370
					return (make_indirect(ra, off / 8));
2 7u83 371
				}
6 7u83 372
				switch (ptno(id)) {
373
				case par_pl:
374
					d = no(id) + no(rr) + 32 + roff;
375
					op = make_ind_rel_ap(d / 8, off / 8);
376
					return (op);
2 7u83 377
#ifndef tdf3
6 7u83 378
				case par2_pl:
379
					d = no(id) + no(rr);
380
					op = make_ind_rel_ap2(d / 8, off / 8);
381
					return (op);
382
				case par3_pl:
383
					d = no(id) + no(rr);
384
					op = make_ind_rel_ap3(d / 8, off / 8);
385
					return (op);
2 7u83 386
#endif
6 7u83 387
				case var_pl:
388
					d = - (no(id)) + no(rr) + roff;
389
					op = make_ind_rel_ap(d / 8, off / 8);
390
					return (op);
391
				case reg_pl:
392
					return (make_ind(no(id), off));
393
				default:
394
					error(illegal_operand, 6);
395
					return (null);
2 7u83 396
				}
397
			}
6 7u83 398
			default:
399
				error(illegal_operand, 7);
400
				return (null);
2 7u83 401
			}
402
		}
6 7u83 403
		case reff_tag: {
404
			exp rr = son(r);
405
			switch (name(rr)) {
406
			case name_tag: {
407
				exp id = son(rr);
408
				if (isglob(id)) {
409
					int ra;
410
					op = make_ext_ind(id, 0);
411
					ra = tmp_reg(m_movl, op);
412
					return (make_indirect(ra, no(r) / 8));
2 7u83 413
				}
6 7u83 414
				switch (ptno(id)) {
415
				case reg_pl:
416
					d = no(r) + off;
417
					return (make_ind(no(id), d));
418
				case par2_pl:
419
				case par3_pl:
420
				case par_pl: {
421
					int ra;
422
					where new_w;
423
					new_w.wh_exp = id;
424
					new_w.wh_off = 0;
425
					op = operand(L32, new_w);
426
					ra = tmp_reg(m_movl, op);
427
					d = no(r) + off;
428
					return (make_indirect(ra, d / 8));
2 7u83 429
				}
6 7u83 430
				case var_pl: {
431
					int ra;
432
					where new_w;
433
					new_w.wh_exp = id;
434
					new_w.wh_off = 0;
435
					op = operand(L32, new_w);
436
					ra = tmp_reg(m_movl, op);
437
					d = no(r) + off;
438
					return (make_indirect(ra, d / 8));
2 7u83 439
				}
6 7u83 440
				default:
441
					error(illegal_operand, 8);
442
					return (null);
2 7u83 443
				}
444
			}
6 7u83 445
			case cont_tag: {
446
				exp rrr = son(rr);
447
				exp id = son(rrr);
448
				if (ptno(id) == reg_pl) {
449
					d = no(r) + off;
450
					return (make_ind(no(id), d));
451
				}
452
				if (ptno(id) == var_pl) {
453
					int ra;
454
					where new_w;
455
					new_w.wh_exp = id;
456
					new_w.wh_off = 0;
457
					op = operand(L32, new_w);
458
					ra = tmp_reg(m_movl, op);
459
					d = no(r) + off;
460
					return (make_indirect(ra, d / 8));
461
				}
462
				error(illegal_operand, 9);
463
				return (null);
2 7u83 464
			}
6 7u83 465
			case addptr_tag: {
466
				where new_w;
467
				new_w.wh_exp = rr;
468
				new_w.wh_off = no(r) + off;
469
				return (operand(sz, new_w));
2 7u83 470
			}
6 7u83 471
			default:
472
				error(illegal_operand, 10);
473
				return (null);
2 7u83 474
			}
475
		}
6 7u83 476
		case addptr_tag: {
477
			where wb, wc;
478
			exp rr = son(r);
479
			exp eb = bro(rr);
480
			exp ec = simple_exp(cont_tag);
481
			son(ec) = rr;
482
			wb.wh_exp = eb;
483
			wb.wh_off = 0;
484
			wc.wh_exp = ec;
485
			wc.wh_off = off;
2 7u83 486
 
6 7u83 487
			switch (name(eb)) {
488
			case name_tag:
489
			case cont_tag:
490
				return (index_opnd(wc, wb, 1));
491
			case offset_mult_tag: {
492
				long k = no(bro(son(eb))) / 8;
493
				if (sz == 8 * k) {
494
					wb.wh_exp = son(eb);
495
					wb.wh_off = 0;
496
					return (index_opnd(wc, wb,(int)k));
497
				}
498
				error(illegal_operand, 11);
499
				return (null);
2 7u83 500
			}
6 7u83 501
			default:
502
				error(illegal_operand, 12);
503
				return (null);
2 7u83 504
			}
505
		}
6 7u83 506
		default:
507
			error(illegal_operand, 14);
508
			return (null);
2 7u83 509
		}
510
	}
6 7u83 511
	case dummy_tag: {
512
		exp r = son(w);
2 7u83 513
 
6 7u83 514
		switch (name(r)) {
515
		case ident_tag:
516
			/* This is used by m_lea */
517
			switch (ptno(r)) {
518
			case reg_pl:
519
				return (make_ind(no(r), no(w)));
520
			case var_pl: {
521
				int ra;
522
				where new_w;
523
				new_w.wh_exp = r;
524
				new_w.wh_off = 0;
525
				op = operand(L32, new_w);
526
				ra = tmp_reg(m_movl, op);
527
				d = no(w);
528
				return (make_indirect(ra, d / 8));
2 7u83 529
			}
6 7u83 530
			default:
531
				error(illegal_operand, 15);
532
				return (null);
2 7u83 533
			}
6 7u83 534
		case name_tag: {
535
			exp id = son(r);
536
			if (isglob(id)) {
537
				return (make_ext_ind(id, no(w)));
2 7u83 538
			}
6 7u83 539
			switch (ptno(id)) {
540
			case reg_pl:
541
				return (make_ind(no(id), no(w)));
542
			case var_pl: {
543
				int ra;
544
				where new_w;
545
				new_w.wh_exp = id;
546
				new_w.wh_off = 0;
547
				op = operand(L32, new_w);
548
				ra = tmp_reg(m_movl, op);
549
				d = no(w);
550
				return (make_indirect(ra, d / 8));
2 7u83 551
			}
6 7u83 552
			default:
553
				error(illegal_operand, 16);
554
				return (null);
2 7u83 555
			}
556
		}
6 7u83 557
		case cont_tag:
558
		case ass_tag: {
559
			exp rr = son(r);
560
			exp id = son(rr);
561
			if (isglob(id)) {
562
				return (make_ext_ind(id, no(w)));
2 7u83 563
			}
6 7u83 564
			switch (ptno(id)) {
565
			case reg_pl:
566
				return (make_ind(no(id), no(w)));
567
			case var_pl: {
568
				int ra;
569
				where new_w;
570
				new_w.wh_exp = id;
571
				new_w.wh_off = 0;
572
				op = operand(L32, new_w);
573
				ra = tmp_reg(m_movl, op);
574
				d = no(w);
575
				return (make_indirect(ra, d / 8));
2 7u83 576
			}
6 7u83 577
			default:
578
				error(illegal_operand, 17);
579
				return (null);
2 7u83 580
			}
581
		}
6 7u83 582
		case addptr_tag: {
583
			where new_w;
584
			new_w.wh_exp = r;
585
			new_w.wh_off = no(w) + off;
586
			return (operand(sz, new_w));
2 7u83 587
		}
6 7u83 588
		default:
589
			error(illegal_operand, 18);
590
			return (null);
2 7u83 591
		}
592
	}
6 7u83 593
	case reff_tag: {
594
		exp r = son(w);
2 7u83 595
 
6 7u83 596
		switch (name(r)) {
597
		case name_tag: {
598
			exp id = son(r);
599
			if (isglob(id)) {
600
				return (make_ext(id, no(w)));
601
			}
602
			switch (ptno(id)) {
603
			case reg_pl:
604
				if (no(w)) {
605
					int ra = reg(no(id));
606
					if (is_dreg(ra)) {
607
						op = make_register(ra);
608
						ra = tmp_reg(m_movl, op);
609
						add_to_reg(ra, no(w) / 8);
610
					} else {
611
						op = make_indirect(ra,
612
								   no(w) / 8);
613
						ra = tmp_reg(m_lea, op);
614
					}
615
					return (make_register(ra));
2 7u83 616
				}
6 7u83 617
				d = no(id);
618
				return (make_register(reg(d)));
619
			default:
620
				error(illegal_operand, 19);
621
				return (null);
2 7u83 622
			}
623
		}
6 7u83 624
		case cont_tag:
625
		case ass_tag: {
626
			exp rr = son(r);
627
			exp id = son(rr);
628
			if (isglob(id)) {
629
				if (no(w)) {
630
					int ra;
631
					op = make_ext_ind(id, 0);
632
					ra = tmp_reg(m_movl, op);
633
					add_to_reg(ra, no(w) / 8);
634
					return (make_register(ra));
635
				}
636
				return (make_ext_ind(id, 0));
2 7u83 637
			}
6 7u83 638
			switch (ptno(id)) {
639
			case reg_pl:
640
				debug_warning("reff - untested case");
641
				return (make_ind(no(id), no(w)));
642
			case var_pl: {
643
				int ra;
644
				where new_w;
645
				new_w.wh_exp = id;
646
				new_w.wh_off = 0;
647
				op = operand(L32, new_w);
648
				ra = tmp_reg(m_movl, op);
649
				if (no(w)) {
650
					add_to_reg(ra, no(w) / 8);
651
				}
652
				return (make_register(ra));
2 7u83 653
			}
6 7u83 654
			default:
655
				error(illegal_operand, 20);
656
				return (null);
2 7u83 657
			}
658
		}
6 7u83 659
		case addptr_tag: {
660
			where new_w;
661
			debug_warning("reff - untested case");
662
			new_w.wh_exp = r;
663
			new_w.wh_off = 0;
664
			return (operand(sz, new_w));
2 7u83 665
		}
6 7u83 666
		default:
667
			error(illegal_operand, 21);
668
			return (null);
2 7u83 669
		}
670
	}
6 7u83 671
	case addptr_tag: {
672
		where wb, wc;
673
		exp r = son(w);
674
		exp eb = bro(r);
675
		exp ec = simple_exp(cont_tag);
676
		son(ec) = r;
677
		wb.wh_exp = eb;
678
		wb.wh_off = 0;
679
		wc.wh_exp = ec;
680
		wc.wh_off = off;
2 7u83 681
 
6 7u83 682
		switch (name(eb)) {
683
		case name_tag:
684
		case cont_tag:
685
			return (index_opnd(wc, wb, 1));
686
		case offset_mult_tag: {
687
			long k = no(bro(son(eb))) / 8;
688
			wb.wh_exp = son(eb);
689
			wb.wh_off = 0;
690
			return (index_opnd(wc, wb,(int)k));
2 7u83 691
		}
6 7u83 692
		default:
693
			error(illegal_operand, 22);
694
			return (null);
2 7u83 695
		}
696
	}
6 7u83 697
	case general_proc_tag:
698
	case proc_tag: {
699
		long lb = next_lab();
700
		make_constant(lb, w);
701
		return (make_lab(lb, 0));
2 7u83 702
	}
6 7u83 703
	case real_tag:
704
	case string_tag: {
705
		long lb;
706
		if (off == 0) {
707
			lb = next_lab();
708
			make_constant(lb, w);
709
			return (make_lab_ind(lb, 0));
710
		}
711
		debug_warning("Offset from label");
712
		return (make_lab_ind(no(const_list) + 1, off / 8));
2 7u83 713
	}
6 7u83 714
	case res_tag:
715
		return (make_lab_ind(no(w), 0));
716
	case null_tag:
717
		return (make_value(0));
2 7u83 718
#ifndef tdf3
6 7u83 719
	case apply_general_tag:
720
	case tail_call_tag:
2 7u83 721
#endif
6 7u83 722
	case apply_tag:
723
		return (make_dec_sp());
724
	case field_tag: {
725
		where new_w;
726
		new_w.wh_exp = son(w);
727
		new_w.wh_off = no(w) + off;
728
		return (operand(sz, new_w));
2 7u83 729
	}
6 7u83 730
	case current_env_tag:
731
		return (make_register(REG_AP));
732
#ifndef tdf3
733
	case env_size_tag: {
734
		dec *dp = brog(son(son(w)));
735
		return (make_lab((long)dp, 0));
2 7u83 736
	}
6 7u83 737
	case env_offset_tag: {
738
		exp ident_exp = son(w);
739
		return (make_lab((long)ident_exp, 0));
2 7u83 740
	}
741
#else
6 7u83 742
	case env_offset_tag: {
743
		exp id = son(w);
744
		switch (ptno(id)) {
745
		case var_pl:
746
			d = no(id) - off;
747
			return (make_value(- (d / 8)));
748
		case par2_pl:
749
			d = no(id) + off;
750
			return (make_value(d / 8));
751
		case par3_pl:
752
		case par_pl:
753
			d = no(id) + off + 32;
754
			if (used_stack) {
755
				d += 32;
756
			}
757
			return (make_value(d / 8));
2 7u83 758
		}
6 7u83 759
		error(illegal_operand, 23);
760
		return (null);
2 7u83 761
	}
762
#endif
6 7u83 763
	case make_lv_tag:
764
		return (make_lab(ptno(pt(son(pt(w)))), 0));
765
	case local_free_all_tag:
766
		return (make_special_data("PA"));
767
	case internal_tag:
768
		return (make_lab_ind(no(w), off / 8));
769
	default:
770
		error(illegal_operand, 24);
771
		return (null);
2 7u83 772
	}
773
}
774
 
775
 
776
/*
777
    FIND WHICH REGISTERS ARE CHANGED IN AN OPERAND
778
 
779
    This routine returns the bitmask of all the registers changed in the
780
    operand op.  c is true to indicate that the operand is being assigned
781
    to.  If c is false, the only way op can change a register is if it is
782
    a pre-decrement or post-increment.
783
*/
784
 
6 7u83 785
bitpattern
786
regs_changed(mach_op *op, int c)
2 7u83 787
{
6 7u83 788
	int t = op->type;
789
	if (t == MACH_DEC || t == MACH_INC) {
790
		return (regmsk(op->def.num));
791
	}
792
	if (!c) {
793
		return (0);
794
	}
795
	if (t == MACH_REG) {
796
		return (regmsk(op->def.num));
797
	}
798
	if (t == MACH_RPAIR) {
799
		return (regmsk(op->def.num) | regmsk(op->plus->def.num));
800
	}
801
	return (0);
2 7u83 802
}
803
 
804
 
805
/*
806
    OUTPUT AN INSTRUCTION WITH NO OPERANDS
807
 
808
    The instruction instr is created.
809
*/
810
 
6 7u83 811
void
812
ins0(int instr)
2 7u83 813
{
6 7u83 814
	make_instr(instr, null, null, 0);
815
	return;
2 7u83 816
}
817
 
818
 
819
/*
820
    OUTPUT AN INSTRUCTION WITH ONE OPERAND
821
 
822
    The instruction instr with a single operand, a, of size asz is created.
823
    a_changed is true to indicate that a is assigned to.
824
*/
825
 
6 7u83 826
void
827
ins1(int instr, long asz, where a, int a_changed)
2 7u83 828
{
6 7u83 829
	mach_op *op = operand(asz, a);
830
	bitpattern ch = regs_changed(op, a_changed);
831
	make_instr(instr, op, null, ch);
832
	return;
2 7u83 833
}
834
 
835
 
836
/*
837
    OUTPUT AN INSTRUCTION WITH TWO OPERANDS
838
 
839
    The instruction instr with a two operands, a of size asz and b of size bsz,
840
    is created.  b_changed is true to indicate that b is assigned to.
841
*/
842
 
6 7u83 843
void
844
ins2(int instr, long asz, long bsz, where a, where b, int b_changed)
2 7u83 845
{
6 7u83 846
	bitpattern ch;
847
	mach_op *opa = operand(asz, a);
848
	mach_op *opb = operand(bsz, b);
849
	ch = (regs_changed(opa, 0) | regs_changed(opb, b_changed));
850
	make_instr(instr, opa, opb, ch);
851
	return;
2 7u83 852
}
853
 
854
 
855
/*
856
    OUTPUT AN INSTRUCTION WITH TWO OPERANDS, ONE A CONSTANT
857
 
858
    The instruction instr with a two operands, a constant c and a of size asz,
859
    is created.  a_changed is true to indicate that a is assigned to.
860
*/
861
 
6 7u83 862
void
863
ins2n(int instr, long c, long asz, where a, int a_changed)
2 7u83 864
{
6 7u83 865
	mach_op *opc = make_value(c);
866
	mach_op *opa = operand(asz, a);
867
	bitpattern ch = regs_changed(opa, a_changed);
868
	make_instr(instr, opc, opa, ch);
869
	return;
2 7u83 870
}
871
 
872
 
873
/*
874
    OUTPUT AN INSTRUCTION WITH TWO OPERANDS, ONE A HEX CONSTANT
875
 
876
    The instruction instr with a two operands, a constant c and a of size asz,
877
    is created.  a_changed is true to indicate that a is assigned to.  This
878
    routine only differs from ins2n in that the constant will be output in
879
    hex rather than decimal.
880
*/
881
 
6 7u83 882
void
883
ins2h(int instr, long c, long asz, where a, int a_changed)
2 7u83 884
{
6 7u83 885
	mach_op *opc = make_hex_value(c);
886
	mach_op *opa = operand(asz, a);
887
	bitpattern ch = regs_changed(opa, a_changed);
888
	make_instr(instr, opc, opa, ch);
889
	return;
2 7u83 890
}
891
 
6 7u83 892
void
893
save_stack(void)
2 7u83 894
{
6 7u83 895
	if (extra_stack || stack_dec) {
896
		error("unclean stack");
897
	}
898
	make_comment("Save stack pointer");
899
	ins2(m_movl, 32, 32, SP, firstlocal, 1);
2 7u83 900
}
901
 
6 7u83 902
void
903
restore_stack(void)
2 7u83 904
{
6 7u83 905
	if (extra_stack || stack_dec) {
906
		error("unclean stack");
907
	}
908
	make_comment("Restore stack pointer");
909
	ins2(m_movl, 32, 32, firstlocal, SP, 1);
2 7u83 910
}
911