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