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) 1997
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/coder.c,v 1.1.1.1 1998/01/17 15:55:49 release Exp $
35
--------------------------------------------------------------------------
36
$Log: coder.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:10  ma
41
All avs test passed (except add_to_ptr).
42
 
43
Revision 1.3  1997/11/09 14:06:09  ma
44
Fixed AVS problems.
45
 
46
Revision 1.2  1997/10/29 10:22:06  ma
47
Replaced use_alloca with has_alloca.
48
 
49
Revision 1.1.1.1  1997/10/13 12:42:48  ma
50
First version.
51
 
52
Revision 1.8  1997/10/13 08:49:01  ma
53
Made all pl_tests for general proc & exception handling pass.
54
 
55
Revision 1.7  1997/09/25 06:44:52  ma
56
All general_proc tests passed
57
 
58
Revision 1.6  1997/06/24 10:55:57  ma
59
Added changes for "Plumhall Patch"
60
 
61
Revision 1.5  1997/06/18 12:04:49  ma
62
Merged with Input Baseline changes.
63
 
64
Revision 1.4  1997/06/18 10:09:23  ma
65
Checking in before merging with Input Baseline changes.
66
 
67
Revision 1.3  1997/04/20 11:30:19  ma
68
Introduced gcproc.c & general_proc.[ch].
69
Added cases for apply_general_proc next to apply_proc in all files.
70
 
71
Revision 1.2  1997/03/20 12:46:22  ma
72
Now tag ids are kept in unsigned chars (MAX tag id > 127).
73
 
74
Revision 1.1.1.1  1997/03/14 07:50:10  ma
75
Imported from DRA
76
 
77
 * Revision 1.1.1.1  1996/09/20  10:56:52  john
78
 *
79
 * Revision 1.4  1996/07/31  16:25:46  john
80
 * Changed alloca
81
 *
82
 * Revision 1.3  1996/07/30  16:30:43  john
83
 * Removed offset conversion
84
 *
85
 * Revision 1.2  1996/07/05  14:16:42  john
86
 * Changes for spec 3.1
87
 *
88
 * Revision 1.1.1.1  1996/03/26  15:45:09  john
89
 *
90
 * Revision 1.5  94/06/29  14:18:27  14:18:27  ra (Robert Andrews)
91
 * always_round_fl has changed its name.  Need to be slightly more careful
92
 * in a couple of places.
93
 *
94
 * Revision 1.4  94/02/21  15:56:25  15:56:25  ra (Robert Andrews)
95
 * A couple of flags which used to be bool are now int.
96
 *
97
 * Revision 1.3  93/11/19  16:15:49  16:15:49  ra (Robert Andrews)
98
 * Minor corrections to nof_tag and ncopies_tag cases.
99
 *
100
 * Revision 1.2  93/03/08  15:28:34  15:28:34  ra (Robert Andrews)
101
 * Procedures which take compound arguments and return a compound
102
 * result which is ignored were having their arguments put on the
103
 * stack in the wrong place.
104
 *
105
 * Revision 1.1  93/02/22  17:15:20  17:15:20  ra (Robert Andrews)
106
 * Initial revision
107
 *
108
--------------------------------------------------------------------------
109
*/
110
 
111
 
112
#include "config.h"
113
#include <limits.h>
114
#include "common_types.h"
115
#include "check.h"
116
#include "exp.h"
117
#include "expmacs.h"
118
#include "flags.h"
119
#include "shapemacs.h"
120
#include "externs.h"
121
#include "install_fns.h"
122
#include "spec.h"
123
#include "mach.h"
124
#include "where.h"
125
#include "tags.h"
126
#include "codec.h"
127
#include "coder.h"
128
#include "operations.h"
129
#include "mach.h"
130
#include "mach_ins.h"
131
#include "mach_op.h"
132
#include "instr.h"
133
#include "installglob.h"
134
#include "codex.h"
135
#include "instrs.h"
136
#include "peephole.h"
137
#include "szs_als.h"
138
#include "tests.h"
139
#include "utility.h"
140
#include "weights.h"
141
#include "translate.h"
142
#include "ops_shared.h"
143
#include "general_proc.h"
144
#include "68k_globals.h"
145
 
146
#if have_diagnostics
147
#include "xdb_basics.h"
148
#endif
149
 
150
extern int do_peephole ;
151
extern int normal_version ;
152
static int extra_weight = 0 ;
153
 
154
 
155
/*
156
    ADD A SHAPE TO A THE STACK
157
 
158
    Given an ash p, representing the stack, and a shape s, this procedure
159
    returns the ast correponding to the new stack formed by adding s to the
160
    old stack.
161
*/
162
 
163
ast add_shape_to_stack
164
    PROTO_N ( ( p, s ) )
165
    PROTO_T ( ash p X shape s )
166
{
167
    ast res ;
168
    char n = name ( s ) ;
169
    long sz = shape_size ( s ) ;
170
    long adj = 0 ;
171
    if ( n == scharhd || n == ucharhd || n == swordhd || n == uwordhd ) {
172
	adj = SLONG_SZ - sz ;
173
	sz = SLONG_SZ ;
174
    }
175
    if ( n == bitfhd ) sz = SLONG_SZ ;
176
    res.astoff = round ( p, param_align ) ;
177
    res.astadj = adj ;
178
    res.astash = round ( res.astoff + sz, param_align ) ;
179
    return ( res ) ;
180
}
181
 
182
 
183
/*
184
    REGISTER ALLOCATION ROUTINES
185
 
186
    This routine tries to choose registers for a value of shape sha.  br
187
    gives the breakpoint - the minimum number of registers which need to
188
    be free for it to be worth putting this value in a register.  The big
189
    flag is true to indicate that a register which is preserved across
190
    procedure calls is required.  If a register can be allocated, then
191
    its bitpattern is returned.  Otherwise 0 is returned.
192
*/
193
 
194
static bitpattern alloc_reg
195
    PROTO_N ( ( sha, br, big ) )
196
    PROTO_T ( shape sha X int br X bool big )
197
{
198
    int go = 1 ;
199
    bitpattern mask ;
200
    bitpattern rs = regsinuse ;
201
    int i, start, end, rev = 0 ;
202
 
203
    int rg ;
204
    int r = shtype ( sha ) ;
205
 
206
    if ( r == Dreg ) {
207
	rg = bits_in ( ~rs & 0x00fc ) ;
208
	mask = regmsk ( REG_D2 ) ;
209
	start =  REG_D2 ;
210
	end = REG_D7 ;
211
    } else if ( r == Areg ) {
212
	rg = bits_in ( ~rs & 0x3c00 ) ;
213
	mask = regmsk ( REG_A2 ) ;
214
	start = REG_A2 ;
215
	end = REG_A5 ;
216
	if ( br > extra_weight ) br -= extra_weight ;
217
    } else if ( r == Freg ) {
218
	if ( round_after_flop ) return ( 0 ) ;
219
	rg = bits_in ( ~rs & 0xfc0000 ) ;
220
	mask = regmsk ( REG_FP7 ) ;
221
	start = REG_FP7 ;
222
	end = REG_FP2 ;
223
	rev = 1 ;
224
    } else {
225
	error ( "Illegal register type" ) ;
226
	return ( 0 ) ;
227
    }
228
 
229
    if ( rg < br || rg == 0 ) return ( 0 ) ;
230
 
231
    i = start ;
232
    while ( go ) {
233
	if ( !( rs & mask ) ) {
234
	    if ( big ) {
235
		bigregs |= mask ;
236
		if ( r == Freg ) normal_version = 0 ;
237
	    }
238
	    regsinproc |= mask ;
239
	    return ( mask ) ;
240
	}
241
	if ( i == end ) {
242
	    go = 0 ;
243
	} else {
244
	    if ( rev ) {
245
		i-- ;
246
		mask >>= 1 ;
247
	    } else {
248
		i++ ;
249
		mask <<= 1 ;
250
	    }
251
	}
252
    }
253
    return ( 0 ) ;
254
}
255
 
256
 
257
/*
258
    IS A GIVEN EXPRESSION A USE OF A REUSABLE REGISTER?
259
 
260
    This routine returns 0 if the expression e is not a use of a reuseable
261
    register, and the bitmask of the register otherwise.
262
*/
263
 
264
static long reuse_check
265
    PROTO_N ( ( e ) )
266
    PROTO_T ( exp e )
267
{
268
    exp id ;
269
    if ( name ( e ) != name_tag ) return ( 0 ) ;
270
    id = son ( e ) ;
271
    if ( isglob ( id ) || pt ( id ) != reg_pl ) return ( 0 ) ;
272
    return ( reuseables & no ( id ) ) ;
273
}
274
 
275
 
276
/*
277
    CAN WE REUSE A REGISTER?
278
 
279
    This routine checks whether or not we can use a reuseable register to
280
    store def.  It returns the bitmask of a suitable register if so and 0
281
    otherwise.
282
*/
283
 
284
static long reuse
285
    PROTO_N ( ( def ) )
286
    PROTO_T ( exp def )
287
{
288
    switch ( name ( def ) ) {
289
 
290
	case name_tag : {
291
	    return ( reuse_check ( def ) ) ;
292
	}
293
 
294
	case plus_tag :
295
	case and_tag :
296
	case or_tag :
297
	case xor_tag :
298
	case mult_tag : {
299
	    /* Allow at most two arguments - check both */
300
	    exp arg1 = son ( def ) ;
301
	    exp arg2 = bro ( arg1 ) ;
302
	    if ( last ( arg1 ) ) {
303
		return ( reuse_check ( arg1 ) ) ;
304
	    }
305
	    if ( last ( arg2 ) ) {
306
		return ( reuse_check ( arg1 ) || reuse_check ( arg2 ) ) ;
307
	    }
308
	    return ( 0 ) ;
309
	}
310
 
311
	case chvar_tag :
312
	case neg_tag :
313
	case not_tag : {
314
	    /* Check one argument */
315
	    return ( reuse_check ( son ( def ) ) ) ;
316
	}
317
 
318
	case minus_tag :
319
	case subptr_tag :
320
	case minptr_tag :
321
	case shl_tag :
322
	case shr_tag : {
323
	    /* Check two arguments */
324
	    exp arg1 = son ( def ) ;
325
	    exp arg2 = bro ( arg1 ) ;
326
	    return ( reuse_check ( arg1 ) || reuse_check ( arg2 ) ) ;
327
	}
328
    }
329
    return ( 0 ) ;
330
}
331
 
332
 
333
/*
334
    IS AN EXPRESSION GUARANTEED NOT TO USE D0?
335
 
336
    Or if it is, are we really careful?
337
*/
338
 
339
static bool nouse
340
    PROTO_N ( ( e ) )
341
    PROTO_T ( exp e )
342
{
343
    char n = name ( e ) ;
344
    if ( n == test_tag ) return ( 1 ) ;
345
    return ( 0 ) ;
346
}
347
 
348
 
349
/*
350
    WHERE IS A DECLARATION TO BE PUT?
351
 
352
    The routine alloc_variable chooses where to put a declaration. e is the
353
    declaration, def is the definition (for identity) or initialisation
354
    (for variable), stack is the ash for the current stack position.
355
    The place field of the result indicates where the declaration should
356
    be put (reg_pl, var_pl etc. - see coder.h).  num gives the offset
357
    (for objects put on the stack) or register mask (for objects put into
358
    registers).  new_stack gives the ash of the stack after this declaration.
359
    is_new is a flag indicating a new declaration or a reuse of an old
360
    declaration.
361
*/
362
 
363
static allocation alloc_variable
364
    PROTO_N ( ( e, def, stack ) )
365
    PROTO_T ( exp e X exp def X ash stack )
366
{
367
    ast locast ;
368
    allocation dc ;
369
    bitpattern ru ;
370
 
371
    unsigned char n = name ( def ) ;
372
    exp s = son ( def ) ;
373
    exp body = bro ( def ) ;
374
    int br = ( int ) no ( e ) ;
375
 
376
    bool force_reg = isusereg ( e ) ;
377
    bool big = ( props ( e ) & 0x80 ? 1 : 0 ) ;
378
    bool in_reg1 = 0, in_reg2 = 0, in_reg3 = 1 ;
379
 
380
    dc.new_stack = stack ;
381
    dc.is_new = 1 ;
382
 
383
    if ( name ( sh ( def ) ) == tophd && !isvis(e)) {
384
	dc.place = nowhere_pl ;
385
	dc.num = 0 ;
386
	return ( dc ) ;
387
    }
388
 
389
    if ( n == name_tag ) {
390
	in_reg1 = ( !isvar ( s ) && ( no ( def ) == 0 || !isglob ( s ) ) ) ;
391
    } else if ( n == cont_tag && name ( s ) == name_tag ) {
392
	exp t = son ( s ) ;
393
	in_reg2 = ( isvar ( t ) && ( no ( s ) == 0 || !isglob ( t ) ) &&
394
		    no_side ( body ) ) ;
395
    }
396
 
397
    if ( !isvar ( e ) && ( in_reg1 || in_reg2 ) ) {
398
 
399
	/* Re-identification or contents of variable not altered in body */
400
	if ( in_reg1 ) {
401
	    dc.place = ptno ( s ) ;
402
#ifndef tdf3
403
            switch ( ptno (s) ) {
404
            case var_pl:
405
		dc.num = no ( s ) - no ( def ) ;
406
                break;
407
 
408
            case par3_pl:
409
            case par2_pl:
410
		dc.num = no ( s ) - no ( def ) ;
411
                break;
412
 
413
            default:
414
		dc.num = no ( s ) + no ( def ) ;
415
            }
416
#else
417
	    if ( ptno ( s ) == var_pl ) {
418
		dc.num = no ( s ) - no ( def ) ;
419
	    } else {
420
		dc.num = no ( s ) + no ( def ) ;
421
	    }
422
#endif
423
 
424
	} else {
425
	    s = son ( s ) ;
426
	    dc.place = ptno ( s ) ;
427
	    if ( ptno ( s ) == var_pl ) {
428
		dc.num = no ( s ) - no ( son ( def ) ) ;
429
	    } else {
430
		dc.num = no ( s ) + no ( son ( def ) ) ;
431
	    }
432
	}
433
 
434
	/* We have a declaration */
435
	if ( dc.place == reg_pl ) {
436
	    /* If the old one was in registers, reuse it */
437
	    dc.is_new = 0 ;
438
	    return ( dc ) ;
439
	}
440
 
441
	if ( !force_reg ) {
442
	    if ( regable ( e ) ) {
443
		ru = alloc_reg ( sh ( def ), br, big ) ;
444
		if ( ru ) {
445
		    dc.place = reg_pl ;
446
		    dc.num = ru ;
447
		    return ( dc ) ;
448
		}
449
	    }
450
	    if ( isglob ( s ) ) {
451
		locast = add_shape_to_stack ( stack, sh ( def ) ) ;
452
		dc.new_stack = locast.astash ;
453
		dc.place = var_pl ;
454
		if ( locast.astadj ) {
455
		    dc.num = locast.astoff + locast.astadj ;
456
		} else {
457
		    dc.num = locast.astash ;
458
		}
459
		return ( dc ) ;
460
	    }
461
	    /* If there was not room, reuse the old dec */
462
	    dc.is_new = 0 ;
463
	    return ( dc ) ;
464
	}
465
 
466
	if ( regable ( e ) ) {
467
	    ru = alloc_reg ( sh ( def ), br, big ) ;
468
	    if ( ru ) {
469
		dc.place = reg_pl ;
470
		dc.num = ru ;
471
		return ( dc ) ;
472
	    }
473
	    if ( isglob ( s ) ) {
474
		locast = add_shape_to_stack ( stack, sh ( def ) ) ;
475
		dc.new_stack = locast.astash ;
476
		dc.place = var_pl ;
477
		if ( locast.astadj ) {
478
		    dc.num = locast.astoff + locast.astadj ;
479
		} else {
480
		    dc.num = locast.astash ;
481
		}
482
		return ( dc ) ;
483
	    }
484
	    dc.is_new = 0 ;
485
	    return ( dc ) ;
486
	}
487
	return ( dc ) ;
488
    }
489
 
490
    if ( n == apply_tag || n == apply_general_tag || n == tail_call_tag )
491
    in_reg3 = result_in_reg ( sh ( def ) ) ;
492
 
493
    /* Try to allocate in registers */
494
    if ( regable ( e ) && in_reg3 ) {
495
	if ( ( n == apply_tag || n == apply_general_tag || n == tail_call_tag )
496
            && shtype ( sh ( def ) ) != Freg && nouse ( bro ( def ) ) ) {
497
	    dc.place = reg_pl ;
498
	    dc.num = regmsk ( REG_D0 ) ;
499
	    return ( dc ) ;
500
	}
501
	if ( is_a ( n ) ) {
502
	    long rg = reuse ( def ) & 0x3cfc ;
503
	    if ( rg ) {
504
		reuseables &= ~rg ;
505
		dc.place = reg_pl ;
506
		dc.num = rg ;
507
		return ( dc ) ;
508
	    }
509
	}
510
	ru = alloc_reg ( sh ( def ), br, big ) ;
511
	if ( ru ) {
512
	    dc.place = reg_pl ;
513
	    dc.num = ru ;
514
	    return ( dc ) ;
515
	}
516
    }
517
 
518
    /* Otherwise allocate on the stack */
519
    locast = add_shape_to_stack ( stack, sh ( def ) ) ;
520
    dc.new_stack = locast.astash ;
521
    dc.place = var_pl ;
522
    if ( locast.astadj ) {
523
	dc.num = locast.astoff + locast.astadj ;
524
    } else {
525
	dc.num = locast.astash ;
526
    }
527
    return ( dc ) ;
528
}
529
 
530
 
531
/*
532
    CURRENT SCOPES
533
 
534
    These variables are used for the scope and destination of inlined
535
    procedures.
536
*/
537
 
538
static exp crt_rscope ;
539
static where rscope_dest ;
540
 
541
 
542
 
543
 
544
/*
545
    PUSH A SET OF PROCEDURE ARGUMENTS
546
 
547
    The arguments are given by a bro-list starting with t.  They are
548
    coded in reverse order.
549
*/
550
 
551
static void code_pars
552
    PROTO_N ( ( w, stack, t ) )
553
    PROTO_T ( where w X ash stack X exp t )
554
{
555
    long sz = shape_size ( sh ( t ) ) ;
556
    if ( last ( t ) ) {
557
	/* Code last argument */
558
	coder ( w, stack, t ) ;
559
	stack_dec -= round ( sz, param_align ) ;
560
    } else {
561
	/* Code the following arguments */
562
	code_pars ( w, stack, bro ( t ) ) ;
563
	/* And then this one */
564
	coder ( w, stack, t ) ;
565
	stack_dec -= round ( sz, param_align ) ;
566
    }
567
    return ;
568
}
569
 
570
 
571
/*
572
    PRODUCE CODE FOR A SOLVE STATEMENT
573
 
574
    The solve statement with starter s, labelled statements l, destination
575
    dest and default jump jr is processed.
576
*/
577
 
578
static void solve
579
    PROTO_N ( ( s, l, dest, jr, stack ) )
580
    PROTO_T ( exp s X exp l X where dest X exp jr X ash stack )
581
{
582
    exp t ;
583
    long r1 ;
584
 
585
    while ( !last ( l ) ) {
586
	allocation dc ;
587
	long lb = next_lab () ;
588
	exp record = simple_exp ( 0 ) ;
589
	if ( props ( son ( bro ( l ) ) ) & 2 ) setlast ( record ) ;
590
	no ( record ) = stack ;
591
	sonno ( record ) = stack_dec ;
592
	ptno ( record ) = lb ;
593
	pt ( son ( bro ( l ) ) ) = record ;
594
	dc = alloc_variable ( bro ( l ), son ( bro ( l ) ), stack ) ;
595
	ptno ( bro ( l ) ) = dc.place ;
596
	no ( bro ( l ) ) = dc.num ;
597
	l = bro ( l ) ;
598
    }
599
 
600
    r1 = regsinuse ;
601
 
602
    if ( name ( s ) != goto_tag || pt ( s ) != bro ( s ) ) {
603
	/* Code the starting expression */
604
	have_cond = 0 ;
605
	coder ( dest, stack, s ) ;
606
    }
607
    t = s ;
608
 
609
    do {
610
	regsinuse = r1 ;
611
	if ( name ( sh ( t ) ) != bothd ) make_jump ( m_bra, ptno ( jr ) ) ;
612
	t = bro ( t ) ;
613
	if ( no ( son ( t ) ) > 0 ) {
614
	    make_label ( ptno ( pt ( son ( t ) ) ) ) ;
615
	    coder ( dest, stack, t ) ;
616
	}
617
    } while ( !last ( t ) ) ;
618
 
619
    regsinuse = r1 ;
620
    have_cond = 0 ;
621
    return ;
622
}
623
 
624
 
625
/*
626
    PRODUCE CODE FOR A CASE STATEMENT
627
 
628
    The controlling number of the case statement is in the D1 register, from
629
    which already has been deducted.  The list of options is given as a
630
    bro-list in arg.  The routine returns the total number which has been
631
    deducted from D1 at the end.
632
*/
633
static long caser
634
    PROTO_N ( ( arg, already ) )
635
    PROTO_T ( exp arg X long already )
636
{
637
    bool sw, go = 1, diff = 0 ;
638
    exp t, jr, jt, split_at ;
639
    shape sha = sh ( arg ) ;
640
    double low, high ;
641
    double lowest = LONG_MAX, highest = LONG_MIN ;
642
    long i, j, n, *jtab ;
643
    long worth = 0 ;
644
 
645
    for ( t = bro ( arg ) ; go && ( t != nilexp ) ; t = bro ( t ) ) {
646
       if (is_signed(sh(t))) low = no (t) ;
647
       else low = (unsigned) no(t) ;
648
       if (son(t)) {
649
          if (is_signed(sh(son(t)))) high = no(son(t)) ;
650
          else high =(unsigned) no(son(t)) ;
651
       }
652
       else high = low ;
653
 
654
	if ( low != high ) diff = 1 ;
655
	if ( low < lowest ) lowest = low ;
656
	if ( high > highest ) highest = high ;
657
	worth += ( low == high ? 1 : 2 ) ;
658
	if ( bro ( t ) != nilexp ) {
659
           double nextlow;
660
           if (is_signed(sh(bro(t)))) nextlow = no(bro(t));
661
           else nextlow = (unsigned) no(bro(t));
662
	    if ( ( nextlow / 2 ) > ( high / 2 ) + 20 ) {
663
		split_at = t ;
664
		go = 0 ;
665
	    }
666
	}
667
#ifndef tdf3
668
        if (high/2 > low/2 + 20) {
669
           worth = 0 ;
670
        }
671
#endif
672
    }
673
 
674
    if ( !go ) {
675
	/* Split into two */
676
	long a ;
677
	exp new = copyexp ( arg ) ;
678
	exp old_bro = bro ( split_at ) ;
679
	bro ( new ) = old_bro ;
680
	bro ( split_at ) = nilexp ;
681
	setlast ( split_at ) ;
682
	/* Code the first half */
683
	a = caser ( arg, already ) ;
684
 
685
	/* Code the second half */
686
	return ( caser ( new, a ) ) ;
687
    }
688
 
689
    if ( worth > 2 ) {
690
 
691
	/* Construct a jump table */
692
	mach_op *op1, *op2 ;
693
	long rlab = next_lab () ;
694
	long tlab = next_lab () ;
695
	long slab = next_lab () ;
696
	n = highest - lowest + 1 ;
697
	jtab = ( long * ) xcalloc ( n, sizeof ( long ) ) ;
698
 
699
	for ( i = 0 ; i < n ; i++ ) jtab [i] = rlab ;
700
 
701
	for ( t = bro ( arg ) ; t != nilexp ; t = bro ( t ) ) {
702
           if (is_signed(sh(t))) low = no (t) ;
703
           else low = (unsigned) no(t) ;
704
           if (son(t)) {
705
              if (is_signed(sh(son(t)))) high = no(son(t)) ;
706
              else high =(unsigned) no(son(t)) ;
707
           }
708
           else high = low ;
709
 
710
           j = ptno ( pt ( son ( pt ( t ) ) ) ) ;
711
           for ( i = low ; i <= high ; i++ ) jtab [ i - (long)lowest ] = j ;
712
	}
713
 
714
	/* Move offset into D1 */
715
	jt = simple_exp ( 0 ) ;
716
	ptno ( jt ) = rlab ;
717
	/* Subtract the lowest value (minus anything already deducted) */
718
	sub ( slongsh, mnw ( lowest - already ), D1, D1 ) ;
719
	sw = cmp ( slongsh, D1, mnw ( highest - lowest ), tst_gr ) ;
720
	branch ( tst_gr, jt, 0, sw, 0 ) ;
721
 
722
	/* Move displacement into D0 */
723
#if 0
724
	op1 = make_reg_index ( REG_ZA0, REG_D1, 0, 4 ) ;
725
	op1->of->plus->plus = make_lab ( slab, 0 ) ;
726
	regsinproc |= regmsk ( REG_A0 ) ;
727
	debug_warning ( "%%za0 used" ) ;
728
#else
729
	op1 = make_lab_ind ( slab, 0 ) ;
730
	i = tmp_reg ( m_lea, op1 ) ;
731
	op1 = make_reg_index ( i, REG_D1, 0, 4 ) ;
732
#endif
733
	op2 = make_register ( REG_D0 ) ;
734
	make_instr ( m_movl, op1, op2, regmsk ( REG_D0 ) ) ;
735
 
736
	/* Do the jump */
737
	op1 = make_reg_index ( REG_PC, REG_D0, 2, 1 ) ;
738
	make_instr ( m_jmp, op1, null, 0 ) ;
739
 
740
	/* Print out table */
741
	make_label ( tlab ) ;
742
#ifndef no_align_directives
743
	make_instr ( m_as_align4, null, null, 0 ) ;
744
#endif
745
	make_label ( slab ) ;
746
	for ( i = 0 ; i < n ; i++ ) {
747
	    op1 = make_lab_diff ( jtab [i], tlab ) ;
748
	    make_instr ( m_as_long, op1, null, 0 ) ;
749
	}
750
	make_label ( rlab ) ;
751
 
752
	/* Return the total number deducted from D1 */
753
	return ( lowest ) ;
754
    }
755
 
756
    /* If 'high' is not always equal to 'low', restore value of D1 */
757
    if ( diff ) {
758
	add ( slongsh, D1, mnw ( already ), D1 ) ;
759
	already = 0 ;
760
    }
761
 
762
    /* A series of jumps/comparisons */
763
    for ( t = bro ( arg ) ; t != nilexp ; t = bro ( t ) ) {
764
       if (is_signed(sh(t))) low = no (t) ;
765
       else low = (unsigned) no(t) ;
766
       if (son(t)) {
767
          if (is_signed(sh(son(t)))) high = no(son(t)) ;
768
          else high =(unsigned) no(son(t)) ;
769
       }
770
       else high = low ;
771
 
772
	jr = pt ( son ( pt ( t ) ) ) ;
773
	if ( low == high ) {
774
	    sw = cmp ( sha, D1, mnw ( low - already ), tst_eq ) ;
775
	    branch ( tst_eq, jr, 1, sw, 0 ) ;
776
	} else {
777
	    jt = simple_exp ( 0 ) ;
778
	    ptno ( jt ) = next_lab () ;
779
	    sw = cmp ( sha, D1, mnw ( low - already ), tst_ls ) ;
780
	    branch ( tst_ls, jt, is_signed ( sh ( t ) ), sw, 0 ) ;
781
	    sw = cmp ( sha, D1, mnw ( (unsigned)(high - already) ), tst_le ) ;
782
	    branch ( tst_le, jr, is_signed ( sh ( son ( t ) ) ), sw, 0 ) ;
783
	    make_label ( ptno ( jt ) ) ;
784
	}
785
    }
786
    /* Return what has been subtracted from D1 */
787
    have_cond = 0 ;
788
    return ( already ) ;
789
}
790
 
791
/*
792
    RESET STACK POINTER FROM APPLICATIONS POINTER
793
    sp = AP - (env_size - (sizeof(params) + sizeof(ret-addr) + sizeof(AP)))
794
*/
795
 
796
static void reset_stack_pointer
797
    PROTO_Z ()
798
{
799
    mach_op *op1, *op2, *op3 ;
800
    make_comment("reset stack pointer ...");
801
    update_stack () ;
802
 
803
    op1 = make_indirect ( REG_AP, 0 ) ;
804
    op2 = op1->of->plus = new_mach_op() ;
805
    op2->type = MACH_NEG ;
806
    op2->plus = make_ldisp(4);
807
 
808
    op2 = make_register ( REG_SP ) ;
809
    make_instr ( m_lea, op1, op2, regmsk ( REG_SP ) ) ;
810
 
811
#if 0
812
    /* gas misinterpret lea a6@( <label> ) if <label> isn't declared ?? */
813
    op1 = make_indirect ( REG_AP, 0 ) ;
814
    op2 = new_mach_op() ;
815
    op1->of->plus = op2 ;
816
    /* The address of cur_proc_dec is used to form the env_size label */
817
    op3 = make_lab ((long)cur_proc_dec,8+(cur_proc_callers_size+cur_proc_callees_size)/8);
818
    op2->type = MACH_NEG ;
819
    op2->plus = op3 ;
820
    op2 = make_register ( REG_SP ) ;
821
    make_instr ( m_lea, op1, op2, regmsk ( REG_SP ) ) ;
822
#endif
823
    make_comment("reset stack pointer done");
824
}
825
 
826
/*
827
    CHECK UP ON JUMPS
828
 
829
    This routine checks for jumps to immediately following labels.
830
*/
831
 
832
static bool red_jump
833
    PROTO_N ( ( e, la ) )
834
    PROTO_T ( exp e X exp la )
835
{
836
    if ( !last ( la ) && pt ( e ) == bro ( la ) ) return ( 1 ) ;
837
    return ( 0 ) ;
838
}
839
 
840
 
841
/*
842
    ALLOW SPACE ON STACK
843
*/
844
 
845
static ash stack_room
846
    PROTO_N ( ( stack, dest, off ) )
847
    PROTO_T ( ash stack X where dest X long off )
848
{
849
    exp e = dest.wh_exp ;
850
    if ( name ( e ) == ident_tag ) {
851
	if ( ptno ( e ) != var_pl ) return ( stack ) ;
852
	if ( no ( e ) + off > stack ) stack = no ( e ) + off ;
853
    }
854
    return ( stack ) ;
855
}
856
 
857
 
858
/*
859
    MAIN CODING ROUTINE
860
 
861
    This routine is the main coding routine for such things as identity
862
    definitions and control structures.  Most of the actual expression
863
    evaluation is dealt with by codec.  The expression e is coded and
864
    the result put into dest.  The stack argument gives the current
865
    structure of the stack.
866
*/
867
 
868
void coder
869
    PROTO_N ( ( dest, stack, e ) )
870
    PROTO_T ( where dest X ash stack X exp e )
871
{
872
    bool sw ;
873
 
874
    if ( e == nilexp ) {
875
	error ( "Internal coding error" ) ;
876
	return ;
877
    }
878
 
879
    switch ( name ( e ) ) {
880
 
881
	case ident_tag : {
882
 
883
	    long sz ;
884
	    int dw = 0 ;
885
	    allocation dc ;
886
	    bool used_once, used_twice ;
887
	    bitpattern rg = regsinproc ;
888
	    mach_ins *p = current_ins ;
889
 
890
	    /* Find the identity definition and body */
891
	    exp def = son ( e ) ;
892
	    exp body = bro ( def ) ;
893
 
894
	    /* Check up on uses */
895
	    exp x = pt ( e ) ;
896
	    used_once = ( x == nilexp || pt ( x ) == nilexp ) ;
897
	    used_twice = ( used_once || pt ( pt ( x ) ) == nilexp ) ;
898
 
899
	    /* Allocate space for definition */
900
	    if ( ismarked ( e ) && isparam ( e ) &&  no ( e ) > 2 ) {
901
		/* Rarely used procedure arguments ... */
902
		dc.is_new = 0 ;
903
		dc.place = par_pl ;
904
		dc.num = no ( def ) ;
905
		dc.new_stack = stack ;
906
		extra_weight++ ;
907
		dw = 1 ;
908
	    } else {
909
		/* And the rest ... */
910
		dc = alloc_variable ( e, def, stack ) ;
911
	    }
912
 
913
	    /* Mark the declaration */
914
	    ptno ( e ) = dc.place ;
915
	    no ( e ) = dc.num ;
916
#ifndef tdf3
917
            make_visible( e ) ;
918
#endif
919
	    if ( dc.place == var_pl ) used_stack = 1 ;
920
	    sz = dc.new_stack ;
921
 
922
	    /* Does the definition need evaluating? */
923
	    if ( dc.is_new ) {
924
		if ( ptno ( e ) == nowhere_pl ) {
925
		    /* Calculate and discard value if not required */
926
		    coder ( zero, stack, def ) ;
927
		} else {
928
		    /* Encode the definition */
929
		    if ( ptno ( e ) == reg_pl ) regsindec |= dc.num ;
930
		    coder ( zw ( e ), stack, def ) ;
931
		}
932
 
933
		/* Modify regsinuse if a register is being used */
934
		if ( ptno ( e ) == reg_pl ) {
935
		    regsindec &= ~dc.num ;
936
		    if ( used_once ) {
937
			regsinuse |= dc.num ;
938
			reuseables |= dc.num ;
939
		    } else {
940
			regsinuse |= dc.num ;
941
			reuseables &= ~dc.num ;
942
		    }
943
		}
944
 
945
		/* Modify max_stack is the stack is being used */
946
		if ( ptno ( e ) == var_pl && sz > max_stack ) max_stack = sz ;
947
	    }
948
 
949
	    /* Encode the body */
950
	    coder ( dest, dc.new_stack, body ) ;
951
	    extra_weight -= dw ;
952
 
953
	    /* Look for peephole optimizations */
954
	    if ( dc.is_new && pt ( e ) == reg_pl ) {
955
		regsinuse &= ~dc.num ;
956
		if ( !output_immediately && p && do_peephole ) {
957
		    if ( used_twice && post_inc_check ( p, no ( e ) ) ) {
958
			regsinproc = rg ;
959
			return ;
960
		    }
961
		}
962
	    }
963
	    return ;
964
	}
965
#ifndef tdf3
966
#else
967
	case clear_tag : {
968
	    /* Clear means do nothing */
969
	    return ;
970
	}
971
#endif
972
	case seq_tag : {
973
	    /* Sequences */
974
	    bool no_bottom = 1 ;
975
	    exp t = son ( son ( e ) ) ;
976
	    /* Code each sub-expression */
977
	    while ( coder ( zero, stack, t ),
978
		    no_bottom = ( name ( sh ( t ) ) != bothd ),
979
		    !last ( t ) ) t = bro ( t ) ;
980
	    /* Code the result expression if necessary */
981
	    if ( no_bottom ) coder ( dest, stack, bro ( son ( e ) ) ) ;
982
	    return ;
983
	}
984
 
985
	case cond_tag : {
986
	    /* Conditionals */
987
	    long lb, r1 ;
988
	    allocation dc ;
989
	    exp jr, record ;
990
	    bool is_condgoto = 0 ;
991
 
992
	    /* Find the first and alternative expressions */
993
	    exp first = son ( e ) ;
994
	    exp alt = bro ( first ) ;
995
 
996
	    /* Check for "if cond goto ..." */
997
	    if ( name ( bro ( son ( alt ) ) ) == goto_tag ) is_condgoto = 1 ;
998
 
999
	    /* Find or create the label */
1000
	    if ( is_condgoto ) {
1001
		record = pt ( son ( pt ( bro ( son ( alt ) ) ) ) ) ;
1002
	    } else {
1003
		lb = next_lab () ;
1004
		record = simple_exp ( 0 ) ;
1005
		no ( record ) = stack ;
1006
		sonno ( record ) = stack_dec ;
1007
		ptno ( record ) = lb ;
1008
	    }
1009
	    no(son(alt)) = ptno(record);
1010
	    pt ( son ( alt ) ) = record ;
1011
 
1012
	    /* Allocate space for the alternative expression */
1013
	    dc = alloc_variable ( alt, son ( alt ), stack ) ;
1014
	    ptno ( alt ) = dc.place ;
1015
	    no ( alt ) = dc.num ;
1016
 
1017
	    /* If first is just a jump to alt, just encode alt */
1018
	    if ( name ( first ) == goto_tag && pt ( first ) == alt &&
1019
		 son ( first ) != nilexp &&
1020
		 name ( sh ( son ( first ) ) ) == tophd ) {
1021
		coder ( dest, stack, bro ( son ( alt ) ) ) ;
1022
		return ;
1023
	    }
1024
 
1025
	    /* Code the first expression */
1026
	    reuseables = 0 ;
1027
	    r1 = regsinuse ;
1028
	    coder ( dest, stack, first ) ;
1029
 
1030
	    /* Restore regsinuse */
1031
	    regsinuse = r1 ;
1032
 
1033
	    /* If alt is trivial, no further action is required */
1034
	    if ( name ( bro ( son ( alt ) ) ) == top_tag ) {
1035
		bitpattern ch = last_jump_regs ;
1036
		make_label ( ptno ( record ) ) ;
1037
		if ( !is_condgoto && !output_immediately && last_jump == lb ) {
1038
		    current_ins->changed = ch ;
1039
		}
1040
		return ;
1041
	    }
1042
 
1043
	    /* No further action is required for conditional gotos */
1044
	    if ( is_condgoto ) return ;
1045
 
1046
	    /* If first doesn't end with a jump, add one */
1047
	    if ( name ( sh ( first ) ) != bothd ) {
1048
		long lb2 = next_lab () ;
1049
		jr = simple_exp ( 0 ) ;
1050
		ptno ( jr ) = lb2 ;
1051
		make_jump ( m_bra, lb2 ) ;
1052
	    }
1053
 
1054
	    /* Encode the alternative expression */
1055
	    reuseables = 0 ;
1056
	    make_label ( ptno ( record ) ) ;
1057
	    coder ( dest, stack, alt ) ;
1058
	    regsinuse = r1 ;
1059
	    reuseables = 0 ;
1060
 
1061
	    /* Output the label for the jump added to first if necessary */
1062
	    if ( name ( sh ( first ) ) != bothd ) {
1063
		make_label ( ptno ( jr ) ) ;
1064
		retcell ( jr ) ;
1065
	    }
1066
	    have_cond = 0 ;
1067
	    retcell ( record ) ;
1068
	    return ;
1069
	}
1070
 
1071
	case labst_tag : {
1072
	    /* Labelled statements */
1073
	    allocation dc ;
1074
	    have_cond = 0 ;
1075
 
1076
            /* Is there long jump access to this label ? */
1077
            if ( is_loaded_lv(e) ) {
1078
               if ( need_preserve_stack )
1079
                  restore_stack ();
1080
               else if (!has_alloca)
1081
                  reset_stack_pointer() ;
1082
            };
1083
 
1084
	    /* Allocate space */
1085
	    dc = alloc_variable ( e, son ( e ), stack ) ;
1086
	    if ( dc.place == reg_pl ) {
1087
		regsinuse |= dc.num ;
1088
		reuseables &= ~dc.num ;
1089
	    }
1090
 
1091
	    /* Encode the body */
1092
	    coder ( dest, stack, bro ( son ( e ) ) ) ;
1093
 
1094
	    /* Update max_stack and regsinuse */
1095
	    if ( dc.place == var_pl ) {
1096
		if ( dc.new_stack > max_stack ) max_stack = dc.new_stack ;
1097
	    }
1098
	    if ( dc.place == reg_pl ) regsinuse &= ( ~dc.num ) ;
1099
	    return ;
1100
	}
1101
 
1102
	case rep_tag : {
1103
	    /* Loops */
1104
	    long lb ;
1105
	    exp record ;
1106
	    allocation dc ;
1107
 
1108
	    /* Find the starter and the body of the loop */
1109
	    exp start = son ( e ) ;
1110
	    exp body = bro ( start ) ;
1111
 
1112
	    /* Allocate space */
1113
	    dc = alloc_variable ( body, son ( body ), stack ) ;
1114
	    ptno ( body ) = dc.place ;
1115
	    no ( body ) = dc.num ;
1116
 
1117
	    /* Code the starter of the loop */
1118
	    coder ( zw ( body ), stack, start ) ;
1119
 
1120
	    /* Create the repeat label */
1121
	    lb = next_lab () ;
1122
	    make_label ( lb ) ;
1123
	    record = simple_exp ( 0 ) ;
1124
	    setlast ( record ) ;
1125
	    no ( record ) = stack ;
1126
	    sonno ( record ) = stack_dec ;
1127
	    ptno ( record ) = lb ;
1128
	    pt ( son ( body ) ) = record ;
1129
	    reuseables = 0 ;
1130
 
1131
	    /* Encode the body of the loop */
1132
	    coder ( dest, stack, body ) ;
1133
	    retcell ( record ) ;
1134
	    return ;
1135
	}
1136
 
1137
	case goto_tag : {
1138
	  /* Jumps */
1139
	  exp lab ;
1140
 
1141
	  /* Try to avoid unnecessary jumps */
1142
	  if ( last ( e ) && name ( bro ( e ) ) == seq_tag &&
1143
	       name ( bro ( bro ( e ) ) ) == labst_tag &&
1144
	       red_jump ( e, bro ( e ) ) ) return ;
1145
 
1146
	  /* Output the jump */
1147
	  lab = pt ( e ) ;
1148
	  make_jump ( m_bra, ptno ( pt ( son ( lab ) ) ) ) ;
1149
	  reuseables = 0 ;
1150
	  return ;
1151
	}
1152
 
1153
	case goto_lv_tag : {
1154
	  exp dest_exp = son(e); /* destination label */
1155
	  exp cont_exp = getexp(sh(dest_exp),nilexp,1,dest_exp,nilexp,0,0,
1156
				cont_tag);
1157
	  where wh;
1158
	  mach_op *op;
1159
	  wh = zw(cont_exp);
1160
	  wh.wh_is = RegInd;
1161
	  op = operand(32,wh);
1162
	  /*epilogue(1);*/
1163
	  make_instr(m_jmp,op,null,~save_msk);
1164
	  /*ins1(m_jmp,32,D0,0);*/
1165
	  return ;
1166
	}
1167
#ifndef tdf3
1168
        case return_to_label_tag: {
1169
           exp dest_lab = son(e);
1170
 
1171
           make_comment("return_to_label ...");
1172
 
1173
           move(slongsh, zw(dest_lab), A0);
1174
           restore_regs(ALL);
1175
           make_instr(m_jmp,operand(32,A0_p),null,~save_msk);
1176
 
1177
           make_comment("return_to_label done");
1178
           return;
1179
        };
1180
#endif
1181
	case long_jump_tag : {
1182
	  exp new_env = son(e);
1183
	  exp dest_lab = bro(new_env);
1184
          make_comment("long_jump");
1185
 
1186
	  move(sh(dest_lab),zw(dest_lab),A0);
1187
	  move(sh(new_env),zw(new_env),A1);
1188
 
1189
          /* restore all registers but A6 or SP */
1190
          restore_regs(NOT_A6_OR_SP);
1191
 
1192
	  move(sh(new_env),A1,AP);
1193
	  make_instr(m_jmp,operand(32,A0_p),null,~save_msk);
1194
	  return ;
1195
	}
1196
	case test_tag : {
1197
	    /* Tests */
1198
	    exp qwe ;
1199
	    where qw ;
1200
	    bool sg = 1, sf = 0 ;
1201
            int shn ;
1202
 
1203
	    /* Find the test number */
1204
	    long test_n = ( long ) props ( e ) ;
1205
 
1206
	    /* Find the expressions being compared */
1207
	    exp arg1 = son ( e ) ;
1208
	    exp arg2 = bro ( arg1 ) ;
1209
 
1210
	    /* Find the label to be jumped to */
1211
	    exp lab_exp = pt ( e ) ;
1212
	    exp jr = pt ( son ( lab_exp ) ) ;
1213
 
1214
	    /* If arg1 is not an operand, code it into D1 */
1215
	    if ( !is_o ( name ( arg1 ) ) ) {
1216
		qwe = sim_exp ( sh ( arg1 ), D1 ) ;
1217
		qw = zw ( qwe ) ;
1218
		regsinproc |= regmsk ( REG_D1 ) ;
1219
		coder ( qw, stack, arg1 ) ;
1220
		arg1 = qwe ;
1221
	    }
1222
 
1223
	    /* If arg2 is not an operand, code it into D1 */
1224
	    if ( !is_o ( name ( arg2 ) ) ) {
1225
		qwe = sim_exp ( sh ( arg2 ), D1 ) ;
1226
		qw = zw ( qwe ) ;
1227
		regsinproc |= regmsk ( REG_D1 ) ;
1228
		coder ( qw, stack, arg2 ) ;
1229
		arg2 = qwe ;
1230
	    }
1231
 
1232
	    /* Look for unsigned or floating tests */
1233
            shn = name ( sh ( arg1 ) ) ;
1234
 
1235
	    switch ( shn ) {
1236
	        case ucharhd :
1237
	        case uwordhd :
1238
	        case ulonghd :
1239
                case u64hd   :  sg = 0 ; break ;
1240
		case shrealhd :
1241
		case realhd :
1242
		case doublehd : sg = 0 ; sf = 1 ; break ;
1243
	    }
1244
 
1245
	    /* Certain comparisons with 1 or -1 can be changed */
1246
	    if ( name ( arg1 ) == val_tag ) {
1247
		long d = no ( arg1 ) ;
1248
		if ( is_offset ( arg1 ) ) d /= 8 ;
1249
		if ( d == 1 ) {
1250
		    if ( test_n == tst_le ) {
1251
			/* 1 <= x becomes 0 < x */
1252
			test_n = tst_ls ;
1253
			no ( arg1 ) = 0 ;
1254
		    } else if ( test_n == tst_gr ) {
1255
			/* 1 > x becomes 0 >= x */
1256
			test_n = tst_ge ;
1257
			no ( arg1 ) = 0 ;
1258
		    }
1259
		} else if ( d == -1 && sg ) {
1260
		    if ( test_n == tst_ls ) {
1261
			/* -1 < x becomes 0 <= x */
1262
			test_n = tst_le ;
1263
			no ( arg1 ) = 0 ;
1264
		    } else if ( test_n == tst_ge ) {
1265
			/* -1 >= x becomes 0 > x */
1266
			test_n = tst_gr ;
1267
			no ( arg1 ) = 0 ;
1268
		    }
1269
		}
1270
	    }
1271
 
1272
	    /* Certain other comparisons with 1 or -1 can be changed */
1273
	    if ( name ( arg2 ) == val_tag ) {
1274
		long d = no ( arg2 ) ;
1275
		if ( is_offset ( arg2 ) ) d /= 8 ;
1276
		if ( d == 1 ) {
1277
		    if ( test_n == tst_ge ) {
1278
			/* x >= 1 becomes x > 0 */
1279
			test_n = tst_gr ;
1280
			no ( arg2 ) = 0 ;
1281
		    } else if ( test_n == tst_ls ) {
1282
			/* x < 1 becomes x <= 0 */
1283
			test_n = tst_le ;
1284
			no ( arg2 ) = 0 ;
1285
		    }
1286
		} else if ( d == -1 && sg ) {
1287
		    if ( test_n == tst_gr ) {
1288
			/* x > -1 becomes x >= 0 */
1289
			test_n = tst_ge ;
1290
			no ( arg2 ) = 0 ;
1291
		    } else if ( test_n == tst_le ) {
1292
			/* x <= 1 becomes x < 0 */
1293
			test_n = tst_ls ;
1294
			no ( arg2 ) = 0 ;
1295
		    }
1296
		}
1297
	    }
1298
            if ( shn == u64hd || shn == s64hd ) {
1299
	      where w1, w2 ;
1300
              w1 = zw ( arg1 ) ;
1301
	      w2 = zw ( arg2 ) ;
1302
 
1303
              /* compare low word (unsigned) */
1304
              sw = cmp ( ulongsh, w1, w2, test_n ) ;
1305
              branch ( test_n, jr, sg, sw, sf ) ;
1306
 
1307
              /* compare high word */
1308
              w1.wh_off += 32 ;
1309
              w2.wh_off += 32 ;
1310
              if ( sg )
1311
                sw = cmp ( slongsh, w1, w2, test_n ) ;
1312
              else
1313
                sw = cmp ( ulongsh, w1, w2, test_n ) ;
1314
              branch ( test_n, jr, sg, sw, sf ) ;
1315
 
1316
              return ;
1317
            }
1318
 
1319
	    /* Code the comparison */
1320
	    sw = cmp ( sh ( arg1 ), zw ( arg1 ), zw ( arg2 ), test_n ) ;
1321
 
1322
	    /* Output the condition jump */
1323
	    branch ( test_n, jr, sg, sw, sf ) ;
1324
	    return ;
1325
	}
1326
 
1327
	case testbit_tag : {
1328
	    /* Bit tests */
1329
	    exp qwe ;
1330
	    where qw ;
1331
 
1332
	    /* Find the arguments */
1333
	    exp arg1 = son ( e ) ;
1334
	    exp arg2 = bro ( arg1 ) ;
1335
 
1336
	    /* Find the label to be jumped to */
1337
	    exp lab_exp = pt ( e ) ;
1338
	    exp jr = pt ( son ( lab_exp ) ) ;
1339
 
1340
	    /* If arg1 is not an operand, code it into D1 */
1341
	    if ( !is_o ( name ( arg1 ) ) ) {
1342
		qwe = sim_exp ( sh ( arg1 ), D1 ) ;
1343
		qw = zw ( qwe ) ;
1344
		regsinproc |= regmsk ( REG_D1 ) ;
1345
		coder ( qw, stack, arg1 ) ;
1346
		arg1 = qwe ;
1347
	    }
1348
 
1349
	    /* If arg2 is not an operand, code it into D1 */
1350
	    if ( !is_o ( name( arg2 ) ) ) {
1351
		qwe = sim_exp ( sh ( arg2 ), D1 ) ;
1352
		qw = zw ( qwe ) ;
1353
		regsinproc |= regmsk ( REG_D1 ) ;
1354
		coder ( qw, stack, arg2 ) ;
1355
		arg2 = qwe ;
1356
	    }
1357
 
1358
	    /* Code the test */
1359
	    bit_test ( sh ( arg1 ), zw ( arg1 ), zw ( arg2 ) ) ;
1360
 
1361
	    /* Output the conditional jump */
1362
	    branch ( ( long ) props ( e ), jr, 1, 0, 0 ) ;
1363
	    return ;
1364
	}
1365
 
1366
	case ass_tag :
1367
	case assvol_tag : {
1368
	    /* Variable assignments */
1369
	    exp assdest = son ( e ) ;
1370
	    exp assval = bro ( assdest ) ;
1371
            make_comment("assign ...") ;
1372
	    if ( name ( sh ( assval ) ) == bitfhd ) {
1373
 
1374
		int_to_bitf ( assval, e, stack ) ;
1375
		return ;
1376
	    }
1377
	    codec (zw ( e ), stack, assval ) ;
1378
            make_comment("assign done") ;
1379
	    return ;
1380
	}
1381
 
1382
	case nof_tag : {
1383
	    shape sha ;
1384
	    long crt, off ;
1385
	    exp v = son ( e ) ;
1386
 
1387
	    if ( v == nilexp ) return ;
1388
	    if ( name ( dest.wh_exp ) == val_tag ) return ;
1389
 
1390
	    sha = sh ( v ) ;
1391
	    crt = dest.wh_off ;
1392
	    off = rounder ( shape_size ( sha ), shape_align ( sha ) ) ;
1393
 
1394
	    while ( 1 ) {
1395
		where wh ;
1396
		ash stack2 ;
1397
		wh = mw ( dest.wh_exp, crt ) ;
1398
		stack2 = stack_room ( stack, dest, off + crt ) ;
1399
		coder ( wh, stack2, v ) ;
1400
		if ( last ( v ) ) return ;
1401
		crt += off ;
1402
		v = bro ( v ) ;
1403
	    }
1404
	    /* Not reached */
1405
	}
1406
 
1407
	case ncopies_tag : {
1408
	    where wh ;
1409
	    long n = no ( e ) ;
1410
	    shape sha = sh ( son ( e ) ) ;
1411
	    long sz = rounder ( shape_size ( sha ), shape_align ( sha ) ) ;
1412
	    if ( n == 0 ) return ;
1413
	    if ( name ( dest.wh_exp ) == val_tag ) return ;
1414
	    if ( n == 1 ) {
1415
		coder ( dest, stack, son ( e ) ) ;
1416
		return ;
1417
	    }
1418
	    if ( sz == 8 || sz == 16 || sz == 32 ) {
1419
		coder ( D1, stack, son ( e ) ) ;
1420
		regsinproc |= regmsk ( REG_D1 ) ;
1421
		if ( n <= 10 ) {
1422
		    long i ;
1423
		    for ( i = 0 ; i < n ; i++ ) {
1424
			wh = mw ( dest.wh_exp, dest.wh_off + i * sz ) ;
1425
			move ( sha, D1, wh ) ;
1426
		    }
1427
		    return ;
1428
		} else {
1429
		    mach_op *op1, *op2 ;
1430
		    long lab = next_lab () ;
1431
		    int instr = ins ( sz, ml_mov ) ;
1432
		    mova ( dest, A0 ) ;
1433
		    regsinproc |= regmsk ( REG_A0 ) ;
1434
		    move ( slongsh, mnw ( n - 1 ), D0 ) ;
1435
		    make_label ( lab ) ;
1436
		    op1 = make_register ( REG_D1 ) ;
1437
		    op2 = make_postinc ( REG_A0 ) ;
1438
		    make_instr ( instr, op1, op2, regmsk ( REG_A0 ) ) ;
1439
		    op1 = make_register ( REG_D0 ) ;
1440
		    op2 = make_lab_data ( lab, 0 ) ;
1441
		    make_instr ( m_dbf, op1, op2, regmsk ( REG_D0 ) ) ;
1442
		    return ;
1443
		}
1444
	    }
1445
	    coder ( dest, stack, son ( e ) ) ;
1446
	    wh = mw ( dest.wh_exp, dest.wh_off + sz ) ;
1447
	    move_bytes ( sz * ( n - 1 ), dest, wh, 0 ) ;
1448
	    return ;
1449
	}
1450
 
1451
	case concatnof_tag : {
1452
	    ash stack2 ;
1453
	    exp a1 = son ( e ) ;
1454
	    exp a2 = bro ( a1 ) ;
1455
	    long off = dest.wh_off + shape_size ( sh ( a1 ) ) ;
1456
	    coder ( dest, stack, a1 ) ;
1457
	    stack2 = stack_room ( stack, dest, off ) ;
1458
	    coder ( mw ( dest.wh_exp, off ), stack2, a2 ) ;
1459
	    return ;
1460
	}
1461
 
1462
#ifndef tdf3
1463
          case apply_tag :
1464
          case apply_general_tag : {
1465
             apply_general_proc(e, dest, stack);
1466
             return;
1467
          }
1468
 
1469
          case tail_call_tag : {
1470
             int old_stack_dec = stack_dec;
1471
             tail_call(e, dest, stack);
1472
             stack_dec = old_stack_dec;
1473
             return;
1474
          }
1475
 
1476
          case caller_tag : {
1477
             coder ( dest, stack, son ( e ) ) ;
1478
             return;
1479
          }
1480
          case trap_tag: {
1481
             trap_ins( no( e ) ) ;
1482
             return;
1483
          }
1484
#endif
1485
#if 0
1486
	case apply_tag : {
1487
	    /* Procedure applications */
1488
#ifndef tdf3
1489
#else
1490
          static int apply_tag_flag = 0 ;
1491
#endif
1492
	    exp t ;
1493
	    ash st ;
1494
	    long comp_room = 0 ;
1495
	    long longs = 0, stkdec ;
1496
	    long start_stack = stack_dec ;
1497
	    bool use_push = 1, reg_res ;
1498
 
1499
	    /* Find the procedure and the arguments */
1500
	    exp proc = son ( e ) ;
1501
	    exp arg = ( last ( proc ) ? nilexp : bro ( proc ) ) ;
1502
 
1503
 
1504
#if 0
1505
            /* not a normal procedure call, but a way to specify a debuger break point */
1506
          if ((brog(son(proc))->dec_u.dec_val.processed) &&
1507
              (brog(son(proc))->dec_u.dec_val.extnamed)  &&
1508
              (!strcmp( brog(son(proc))->dec_u.dec_val.dec_id, "_TESTPOINT"))) {
1509
               TESTPOINT();
1510
               return;
1511
            }
1512
#endif
1513
 
1514
   make_comment("Call Normal Proc");
1515
	    /* See if we can push all the arguments */
1516
	    st = 0 ;
1517
	    if ( arg != nilexp ) {
1518
		t = arg ;
1519
		while ( t != nilexp ) {
1520
		    ast a ;
1521
                    if ( cpd_param ( sh ( t ) ) ) use_push = 0 ;
1522
                    if ((name(sh(t)) == s64hd) || (name(sh(t)) == u64hd)){
1523
                      use_push = 0;
1524
                    }
1525
                    if ( !push_arg ( t ) ) use_push = 0 ;
1526
		    a = add_shape_to_stack ( st, sh ( t ) ) ;
1527
		    st = a.astash ;
1528
 
1529
		    t = ( last ( t ) ? nilexp : bro ( t ) ) ;
1530
		}
1531
	    }
1532
	    longs = st ;
1533
 
1534
	    /* Does the result go into a register? */
1535
	    reg_res = result_in_reg ( sh ( e ) ) ;
1536
	    if ( !reg_res ) {
1537
		if ( eq_where ( dest, zero ) ) {
1538
		    /* Calculate room for ignored compound result */
1539
/* todo: use symbol instead of 32 */
1540
		    comp_room = round ( shape_size ( sh ( e ) ), 32 ) ;
1541
		}
1542
	    }
1543
 
1544
	    /* Find total amount of stack decrease */
1545
	    stkdec = longs + comp_room ;
1546
 
1547
	    /* Put arguments onto stack */
1548
	    if ( use_push ) {
1549
              make_comment("Push callers");
1550
		if ( comp_room ) {
1551
		    /* Make room for unwanted compound result */
1552
		    dec_stack ( comp_room ) ;
1553
		    stack_dec -= comp_room ;
1554
		}
1555
		/* Push the arguments */
1556
		if ( arg != nilexp ) code_pars ( zw ( e ), stack, arg ) ;
1557
	    } else {
1558
              make_comment("Place callers");
1559
		/* Decrease stack */
1560
		if ( stkdec ) dec_stack ( stkdec ) ;
1561
		stack_dec -= stkdec ;
1562
		/* Indicate recursive calls */
1563
		apply_tag_flag++ ;
1564
		/* Encode the arguments onto the stack */
1565
		st = 0 ;
1566
		t = arg ;
1567
		while ( t != nilexp ) {
1568
		    ast a ;
1569
		    where stp ;
1570
		    long adj = 0 ;
1571
		    char nc = name ( sh ( t ) ) ;
1572
		    if ( nc == scharhd || nc == ucharhd ) adj = 24 ;
1573
		    if ( nc == swordhd || nc == uwordhd ) adj = 16 ;
1574
		    stp = mw ( SP_p.wh_exp, st + adj ) ;
1575
		    coder ( stp, stack, t ) ;
1576
		    a = add_shape_to_stack ( st, sh ( t ) ) ;
1577
		    st = a.astash ;
1578
		    t = ( last ( t ) ? nilexp : bro ( t ) ) ;
1579
		}
1580
		apply_tag_flag-- ;
1581
	    }
1582
	    start_stack -= stack_dec ;
1583
 
1584
	    /* For results which do not fit into registers a pointer to
1585
	       where the result is to be put is passed in in A1 */
1586
	    if ( !reg_res ) {
1587
		if ( comp_room ) {
1588
		    /* Find the space allocated for unwanted results */
1589
		    where w ;
1590
		    w = mnw ( longs / 8 ) ;
1591
		    add ( slongsh, SP, w, A1 ) ;
1592
		} else {
1593
		    /* Find the address of where the result is to be put */
1594
		    tmp_reg_prefer = REG_A1 ;
1595
		    if ( apply_tag_flag ) {
1596
			/* For recursive calls we need to be very careful
1597
			   if the result is itself to be a procedure argument
1598
			   to get the right stack offset. */
1599
			long ex = extra_stack ;
1600
			long doff = dest.wh_off ;
1601
			extra_stack += start_stack ;
1602
			dest.wh_off = 0 ;
1603
			if ( eq_where ( dest, SP_p ) ) {
1604
			    /* Careful! */
1605
			    dest.wh_off = doff + extra_stack ;
1606
			    mova ( dest, A1 ) ;
1607
			    dest.wh_off = doff ;
1608
			} else {
1609
			    /* Easy */
1610
			    dest.wh_off = doff ;
1611
			    mova ( dest, A1 ) ;
1612
			}
1613
			extra_stack = ex ;
1614
		    } else {
1615
			/* Otherwise (easy) ... */
1616
			mova ( dest, A1 ) ;
1617
		    }
1618
		}
1619
		/* Make sure we don't reuse A1 accidently */
1620
		avoid_tmp_reg ( REG_A1 ) ;
1621
		regsinproc |= regmsk ( REG_A1 ) ;
1622
	    }
1623
 
1624
	    /* Output the call instruction */
1625
	    callins ( longs, son ( e ) ) ;
1626
	    stack_dec += stkdec ;
1627
	    have_cond = 0 ;
1628
 
1629
	    /* Throw away unwanted compound result */
1630
	    if ( comp_room ) {
1631
		dec_stack ( -comp_room ) ;
1632
		return ;
1633
	    }
1634
 
1635
	    /* Throw away unwanted simple result */
1636
	    if ( eq_where ( dest, zero ) ) return ;
1637
 
1638
	    /* Now move the result into place */
1639
	    if ( reg_res ) {
1640
		if ( shape_size ( sh ( e ) ) <= 32 ) {
1641
		    /* Small register results are in D0 */
1642
		    move ( sh ( e ), D0, dest ) ;
1643
		    return ;
1644
		} else {
1645
		    /* Larger register results are in D0 and D1 */
1646
#ifdef SYSV_ABI
1647
		    move ( sh ( e ), FP0, dest ) ;
1648
#else
1649
		    move ( sh ( e ), D0_D1, dest ) ;
1650
		    regsinproc |= regmsk ( REG_D1 ) ;
1651
#endif
1652
		    return ;
1653
		}
1654
	    } else {
1655
		/* Compound results should already have been copied to
1656
		   the position pointed to by A1 by the called procedure
1657
		   and returned by it in D0, so no further action should
1658
		   be required by the calling procedure.  Unfortunately
1659
		   cc doesn't always get this right for union results. */
1660
#ifdef OLD_SPEC
1661
		if ( cc_conventions && name ( sh ( e ) ) == unhd ) {
1662
		    regsinproc |= regmsk ( REG_A0 ) ;
1663
		    move ( slongsh, D0, A0 ) ;
1664
		    move ( sh ( e ), A0_p, dest ) ;
1665
		}
1666
#endif
1667
		return ;
1668
	    }
1669
	}
1670
#endif
1671
	case alloca_tag : {
1672
	    /* Local memory allocation */
1673
	    exp s = son ( e ) ;
1674
            where size_w ;
1675
            bool allocation_done = 0 ;
1676
	    used_stack = 1 ;
1677
 
1678
            make_comment("Allocate ...") ;
1679
 
1680
            /* Create a where representing the value to be allocated */
1681
 
1682
	    if ( name ( s ) == val_tag ) {
1683
              long off = no ( s ) ;
1684
              if ( ! is_offset ( s ) ) off *= 8 ;
1685
              off = rounder(off, stack_align) ;
1686
 
1687
              if ( checkalloc(e)) {
1688
                 size_w = mw(zeroe, off / 8);
1689
              }
1690
              else {
1691
                 /* simple allocation of constant */
1692
                 dec_stack ( off ) ;
1693
                 allocation_done = 1 ;
1694
              }
1695
	    }
1696
            else {
1697
               size_w = zw(s) ;
1698
            }
1699
 
1700
            /* Allocate (checked or not) */
1701
 
1702
            if ( ! allocation_done )
1703
            if (checkalloc(e)) checkalloc_stack (size_w, 1) ;
1704
            else sub ( slongsh, size_w, SP, SP ) ;
1705
 
1706
	    /* The result of the construct is SP */
1707
 
1708
	    if ( !eq_where ( dest, zero ) ) move ( sh ( e ), SP, dest ) ;
1709
 
1710
	    have_cond = 0 ;
1711
 
1712
            if (need_preserve_stack) save_stack ();
1713
 
1714
            make_comment("Allocate done") ;
1715
	    return ;
1716
	}
1717
 
1718
	case last_local_tag : {
1719
           make_comment("last_local ...");
1720
           move ( sh ( e ), SP, dest ) ;
1721
           make_comment("last_local done");
1722
           return ;
1723
	}
1724
 
1725
	case local_free_tag : {
1726
	  exp base = son(e);
1727
	  exp offset = bro(base);
1728
	  exp s_a0 = sim_exp(sh(base),A0);
1729
	  where w_a0;
1730
	  w_a0 = zw(s_a0);
1731
 
1732
          make_comment("local_free ...");
1733
 
1734
	  coder(w_a0,stack,base);
1735
 
1736
	  if(name(offset) == val_tag) {
1737
            long off = no ( offset ) ;
1738
            where size_w ;
1739
 
1740
            if ( ! is_offset ( offset ) ) off *= 8 ;
1741
            off = rounder(off, stack_align) / 8 ;
1742
            size_w = mw(zeroe, off);
1743
	    add(sh(offset),A0,zw(offset),SP);
1744
	  }
1745
	  else {
1746
	    exp s_d0 = sim_exp(sh(offset),D0);
1747
	    where w_d0;
1748
	    w_d0 = zw(s_d0);
1749
	    coder(w_d0,stack,offset);
1750
	    add(sh(offset),mnw(7),D0,D0);
1751
	    and(sh(offset),D0,mnw(~7),D0);
1752
	    add(sh(offset),A0,D0,SP);
1753
	  }
1754
 
1755
          if (need_preserve_stack)
1756
	  save_stack ();
1757
 
1758
          make_comment("local_free done");
1759
 
1760
	  return ;
1761
	}
1762
 
1763
	case local_free_all_tag : {
1764
           mach_op *op1, *op2 ;
1765
           must_use_bp = 1 ;
1766
           make_comment("local_free_all ...");
1767
           reset_stack_pointer();
1768
           if (need_preserve_stack)
1769
           save_stack ();
1770
           make_comment("local_free_all done");
1771
           return ;
1772
	}
1773
 
1774
#ifndef tdf3
1775
        case untidy_return_tag :
1776
#endif
1777
	case res_tag : {
1778
	    /* Procedure results */
1779
	    have_cond = 0 ;
1780
 
1781
	    /* Has the procedure been inlined? */
1782
	    if ( crt_rscope == 0 ) {
1783
 
1784
		/* Non-inlined procedures */
1785
		shape rsha = sh ( son ( e ) ) ;
1786
 
1787
		/* Does the result go into a register? */
1788
		if ( result_in_reg ( rsha ) ) {
1789
		    if ( shape_size ( rsha ) <= 32 ) {
1790
			/* Small register results go into D0 */
1791
			coder ( D0, stack, son ( e ) ) ;
1792
		    } else {
1793
#ifdef SYSV_ABI
1794
			coder ( FP0, stack, son ( e ) ) ;
1795
#else
1796
			/* Larger register results go into D0 and D1 */
1797
			coder ( D0_D1, stack, son ( e ) ) ;
1798
			regsinproc |= regmsk ( REG_D1 ) ;
1799
#endif
1800
		    }
1801
		    /* Jump to the return label */
1802
		    if ( name ( rsha ) != bothd ) {
1803
#ifndef tdf3
1804
                       if ( name ( e ) == untidy_return_tag ) {
1805
                          untidy_return() ;
1806
                       }
1807
                       else
1808
#endif
1809
			make_jump ( m_bra, crt_ret_lab ) ;
1810
		    }
1811
		    return ;
1812
		}
1813
 
1814
		/* Otherwise the result has to be encoded into the
1815
		   position pointed to by A1 at the start of the procedure.
1816
		   This value was stored in A6_4.  The value of this
1817
		   pointer is returned in D0. */
1818
		if (   name ( son ( e ) ) == apply_tag
1819
                    || name ( son ( e ) ) == apply_general_tag ) {
1820
		    coder ( A6_4_p, stack, son ( e ) ) ;
1821
		} else {
1822
		    codec ( A6_4_p, stack, son ( e ) ) ;
1823
		}
1824
#ifdef SYSV_ABI
1825
		move ( slongsh, A6_4, A1 ) ;
1826
#else
1827
		move ( slongsh, A6_4, D0 ) ;
1828
#endif
1829
		regsinproc |= regmsk ( REG_A1 ) ;
1830
#ifndef tdf3
1831
                if ( name ( e ) == untidy_return_tag ) {
1832
                   untidy_return() ;
1833
                }
1834
                else
1835
#endif
1836
		make_jump ( m_bra, crt_ret_lab ) ;
1837
		return ;
1838
 
1839
	    } else {
1840
		/* For inlined procedures, the result goes into rscope_dest
1841
		   and a jump is made to crt_rscope */
1842
		coder ( rscope_dest, stack, son ( e ) ) ;
1843
#ifndef tdf3
1844
                if ( name ( e ) == untidy_return_tag ) {
1845
                   untidy_return() ;
1846
                }
1847
                else
1848
#endif
1849
		make_jump ( m_bra, ptno ( crt_rscope ) ) ;
1850
		return ;
1851
	    }
1852
	}
1853
 
1854
#ifdef rscope_tag
1855
	case rscope_tag : {
1856
	    /* Procedure scopes */
1857
	    exp record ;
1858
	    where old_rscope_dest ;
1859
	    exp old_rscope = crt_rscope ;
1860
	    old_rscope_dest = rscope_dest ;
1861
 
1862
	    /* Check for inlined procedures */
1863
	    if ( last ( e ) && ( name ( bro ( e ) ) == proc_tag
1864
                                || name ( bro ( e ) ) == general_proc_tag ) ) {
1865
		/* Non-inlined procedures are simple */
1866
		crt_rscope = 0 ;
1867
		coder ( zero, stack, son ( e ) ) ;
1868
	    } else {
1869
		/* This is an inlined procedure */
1870
		long lb = next_lab () ;
1871
		record = simple_exp ( 0 ) ;
1872
		ptno ( record ) = lb ;
1873
		crt_rscope = record ;
1874
		rscope_dest = dest ;
1875
		coder ( zero, stack, son ( e ) ) ;
1876
		make_label ( lb ) ;
1877
		retcell ( record ) ;
1878
	    }
1879
 
1880
	    /* Restore the previous scopes */
1881
	    rscope_dest = old_rscope_dest ;
1882
	    crt_rscope = old_rscope ;
1883
	    return ;
1884
	}
1885
#endif
1886
 
1887
	case solve_tag : {
1888
	    /* Solve statements */
1889
	    long lb = next_lab () ;
1890
	    exp jr = simple_exp ( 0 ) ;
1891
	    ptno ( jr ) = lb ;
1892
	    solve ( son ( e ), son ( e ), dest, jr, stack ) ;
1893
	    make_label ( lb ) ;
1894
	    retcell ( jr ) ;
1895
	    return ;
1896
	}
1897
 
1898
	case case_tag : {
1899
	    /* Case statements */
1900
	    exp d1 ;
1901
	    where w1 ;
1902
	    bool old_D1_sp = D1_is_special ;
1903
	    exp arg1 = son ( e ) ;
1904
	    exp t = arg1 ;
1905
 
1906
	    /* Mark the end of the cases */
1907
	    while ( !last ( t ) ) t = bro ( t ) ;
1908
	    bro ( t ) = nilexp ;
1909
 
1910
	    d1 = sim_exp ( sh ( arg1 ), D1 ) ;
1911
	    w1 = zw ( d1 ) ;
1912
	    D1_is_special = 1 ;
1913
	    regsinproc |= regmsk ( REG_D1 ) ;
1914
	    coder ( w1, stack, arg1 ) ;
1915
 
1916
	    change_var_sh ( slongsh, sh ( arg1 ), w1, D1 ) ;
1917
	    D1_is_special = old_D1_sp ;
1918
 
1919
	    /* Output the case statement */
1920
	    ( void ) caser ( arg1, L0 ) ;
1921
 
1922
	    retcell ( d1 ) ;
1923
	    return ;
1924
	}
1925
 
1926
	case movecont_tag : {
1927
	  /* This is done by a library call to memmove */
1928
	  exp from_exp = son(e);
1929
	  exp to_exp = bro(from_exp);
1930
	  exp num_bytes = bro(to_exp);
1931
#if defined(SUN)
1932
          mach_op *op = make_extern_ind("_bcopy",0);
1933
#else
1934
          mach_op *op = make_extern_ind("_memmove",0);
1935
#endif
1936
          make_comment("move_some ...");
1937
	  push(slongsh,L32,D0);
1938
	  push(slongsh,L32,D1);
1939
	  push(slongsh,L32,zw(num_bytes));
1940
#if defined(SUN)
1941
	  push(slongsh,L32,zw(to_exp));
1942
	  push(slongsh,L32,zw(from_exp));
1943
#else
1944
	  push(slongsh,L32,zw(from_exp));
1945
	  push(slongsh,L32,zw(to_exp));
1946
#endif
1947
	  make_instr(m_call,op,null,0);
1948
	  dec_stack(-96);
1949
	  pop(slongsh,L32,D1);
1950
	  pop(slongsh,L32,D0);
1951
          make_comment("move_some done");
1952
	  return ;
1953
	}
1954
 
1955
	case diagnose_tag : {
1956
#if have_diagnostics
1957
	    diag_start ( dno ( e ), e ) ;
1958
	    coder ( dest, stack, son ( e ) ) ;
1959
	    diag_end ( dno ( e ), e ) ;
1960
#else
1961
	    coder ( dest, stack, son ( e ) ) ;
1962
#endif
1963
	    return ;
1964
	}
1965
	case prof_tag :{
1966
	  return;
1967
	}
1968
 
1969
	default :  {
1970
	    if ( !is_a ( name ( e ) ) ) {
1971
		error ( "Bad operation" ) ;
1972
		return ;
1973
	    }
1974
	    if ( name ( dest.wh_exp ) != val_tag){
1975
               /* All other cases are passed to codec */
1976
               codec ( dest, stack, e ) ;
1977
               return ;
1978
	    }
1979
	    else if (!optop(e)){
1980
               /* An operation with an error jump must always be performed,
1981
                  even if the result is discarded.  */
1982
               codec (zero,stack,e);
1983
               return ;
1984
	    }
1985
	}
1986
    }
1987
}