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/where.c,v 1.1.1.1 1998/01/17 15:55:50 release Exp $
35
--------------------------------------------------------------------------
36
$Log: where.c,v $
37
 * Revision 1.1.1.1  1998/01/17  15:55:50  release
38
 * First version to be checked into rolling release.
39
 *
40
Revision 1.3  1997/11/09 14:07:59  ma
41
Removed issigned function.
42
 
43
Revision 1.2  1997/10/29 10:22:32  ma
44
Replaced use_alloca with has_alloca.
45
 
46
Revision 1.1.1.1  1997/10/13 12:43:01  ma
47
First version.
48
 
49
Revision 1.5  1997/10/13 08:50:19  ma
50
Made all pl_tests for general proc & exception handling pass.
51
 
52
Revision 1.4  1997/09/25 06:45:41  ma
53
All general_proc tests passed
54
 
55
Revision 1.3  1997/06/18 10:09:46  ma
56
Checking in before merging with Input Baseline changes.
57
 
58
Revision 1.2  1997/04/20 11:30:43  ma
59
Introduced gcproc.c & general_proc.[ch].
60
Added cases for apply_general_proc next to apply_proc in all files.
61
 
62
Revision 1.1.1.1  1997/03/14 07:50:21  ma
63
Imported from DRA
64
 
65
 * Revision 1.1.1.1  1996/09/20  10:57:00  john
66
 *
67
 * Revision 1.2  1996/07/05  14:30:14  john
68
 * Changes for spec 3.1
69
 *
70
 * Revision 1.1.1.1  1996/03/26  15:45:19  john
71
 *
72
 * Revision 1.3  94/02/21  16:06:54  16:06:54  ra (Robert Andrews)
73
 * Change the argument to find_reg_ind to an int.
74
 *
75
 * Revision 1.2  93/03/03  14:51:05  14:51:05  ra (Robert Andrews)
76
 * Use correct number of registers in initialization routine.
77
 *
78
 * Revision 1.1  93/02/22  17:17:05  17:17:05  ra (Robert Andrews)
79
 * Initial revision
80
 *
81
--------------------------------------------------------------------------
82
*/
83
 
84
 
85
#include "config.h"
86
#include "common_types.h"
87
#include "exp.h"
88
#include "expmacs.h"
89
#include "externs.h"
90
#include "install_fns.h"
91
#include "shapemacs.h"
92
#include "tags.h"
93
#include "fbase.h"
94
#include "flpt.h"
95
#include "mach.h"
96
#include "tests.h"
97
#include "where.h"
98
#include "coder.h"
99
#include "utility.h"
100
#include "translate.h"
101
#include "evaluate.h"
102
#define REGISTER_SIZES
103
#include "instr_aux.h"
104
#include "special_exps.h"
105
static int find_where PROTO_S ( ( exp ) ) ;
106
 
107
/*
108
    MACROS
109
 
110
    These are used as convenient shorthands.
111
*/
112
 
113
#define  new_exp( A, B, C, D )	getexp ( A, nilexp, 0, B, nilexp, L0, C, D )
114
#define  ptrsh		 	ptr_shape ( slongsh )
115
 
116
 
117
/*
118
    WHAT SORT OF REGISTER SHOULD WE PUT SOMETHING OF A GIVEN SHAPE IN?
119
 
120
    The shape sha is examined and the appropriate register type -
121
    Dreg, Areg or Freg is returned.
122
*/
123
 
124
int shtype
125
    PROTO_N ( ( sha ) )
126
    PROTO_T ( shape sha )
127
{
128
    char n = name ( sha ) ;
129
    if ( n >= scharhd && n <= ulonghd ) return ( Dreg ) ;
130
    if ( n >= shrealhd && n <= doublehd ) return ( Freg ) ;
131
    if ( n != bitfhd && n != nofhd && n != cpdhd ) return ( Areg ) ;
132
    return ( shape_size ( sha ) <= 32 ? Dreg : Areg ) ;
133
}
134
 
135
 
136
/*
137
    REGISTERS USED IN OPERAND
138
 
139
    This is a bitmask of all the registers used in an operand.  It is
140
    built up by find_where.
141
*/
142
 
143
static bitpattern where_regmsk ;
144
 
145
 
146
/*
147
    FIND ADDRESSING TYPE OF A REGISTER INDIRECT WITH DISPLACEMENT
148
 
149
    The addressing type of a register indirect operand with register
150
    mask rgs is returned.  This is RegInd if rgs corresponds to an
151
    A-register, and Other otherwise.
152
*/
153
 
154
static int find_reg_ind
155
    PROTO_N ( ( r ) )
156
    PROTO_T ( int r )
157
{
158
    bitpattern rgs = ( bitpattern ) r ;
159
    where_regmsk |= rgs ;
160
    /* If rgs corresponds to an A register, we have an effective address */
161
    if ( rgs & areg_msk ) return ( RegInd ) ;
162
    return ( Other ) ;
163
}
164
 
165
 
166
/*
167
    FIND ADDRESSING TYPE OF AN INDEX OPERAND
168
 
169
    The addressing type of the operand given by e1 indexed by e2 times
170
    some constant is returned.
171
*/
172
 
173
static int find_ind
174
    PROTO_N ( ( e1, e2 ) )
175
    PROTO_T ( exp e1 X exp e2 )
176
{
177
    int f1 = find_where ( e1 ) ;
178
    int f2 = find_where ( e2 ) ;
179
    if ( f1 == Other ) return ( Other ) ;
180
    if ( f2 == Dreg || f2 == Areg ) return ( EffAddr ) ;
181
    return ( Other ) ;
182
}
183
 
184
 
185
/*
186
    FIND ADDRESSING TYPE OF AN OPERAND
187
 
188
    The addressing type of the operand e is returned.  Meanwhile the
189
    bitmask of all the registers used in e is built up in where_regmsk.
190
    This routine should be compared with operand.
191
*/
192
 
193
static int find_where
194
    PROTO_N ( ( e ) )
195
    PROTO_T ( exp e )
196
{
197
    bitpattern rm ;
198
    switch ( name ( e ) ) {
199
 
200
	case val_tag :
201
	case null_tag :
202
	    return ( Value ) ;
203
 
204
	case real_tag :
205
	case string_tag :
206
	case res_tag :
207
	    return ( External ) ;
208
 
209
	case regpair_tag :
210
	    return ( RegPair ) ;
211
 
212
	case apply_general_tag :
213
	case tail_call_tag :
214
	case apply_tag :
215
	    return ( EffAddr ) ;
216
 
217
	case field_tag :
218
	    return ( find_where ( son ( e ) ) ) ;
219
 
220
	case ident_tag :
221
	case labst_tag : {
222
	    switch ( ptno ( e ) ) {
223
#ifndef tdf3
224
                case par2_pl :
225
                case par3_pl :
226
#endif
227
 
228
		case par_pl : return ( Parameter ) ;
229
		case var_pl : return ( Variable ) ;
230
		case reg_pl : {
231
		    rm = ( bitpattern ) no ( e ) ;
232
		    where_regmsk |= rm ;
233
		    /* A register, but what type? */
234
		    if ( rm & dreg_msk ) return ( Dreg ) ;
235
		    if ( rm & areg_msk ) return ( Areg ) ;
236
		    return ( Freg ) ;
237
		}
238
	    }
239
	    break ;
240
	}
241
 
242
	case name_tag : {
243
	    exp id = son ( e ) ;
244
#if 0
245
	    if((name(sh(e)) == prokhd) &&
246
	       ((son(id) == nilexp) || (name(son(id)) == proc_tag) ||
247
		(name(son(id)) == general_proc_tag))){
248
	      exp proc_cont = getexp(sh(e),nilexp,0,e,nilexp,0,
249
				     0,cont_tag);
250
	      /*return find_where(proc_cont);*/
251
	      e = proc_cont;
252
	      /*return EffAddr;*/
253
	      id = son(e);
254
/*	      return find_where(e);*/
255
	    }
256
#endif
257
 
258
	    if ( isglob ( id ) ) return ( External ) ;
259
	    switch ( ptno ( id ) ) {
260
#ifndef tdf3
261
		case par2_pl :
262
		case par3_pl :
263
#endif
264
 
265
		case par_pl :
266
		case var_pl : return ( EffAddr ) ;
267
		case reg_pl : {
268
		    rm = ( bitpattern ) no ( id ) ;
269
		    where_regmsk |= rm ;
270
		    /* A register, but what type? */
271
		    if ( rm & dreg_msk ) return ( Dreg ) ;
272
		    if ( rm & areg_msk ) return ( Areg ) ;
273
		    return ( Freg ) ;
274
		}
275
	    }
276
	    break ;
277
	}
278
 
279
	case cont_tag :
280
	case ass_tag : {
281
	    exp r = son ( e ) ;
282
	    switch ( name ( r ) ) {
283
 
284
		case name_tag : {
285
		    exp id = son ( r ) ;
286
		    long pt_id = ptno ( id ) ;
287
		    if ( isvar ( id ) ) return ( find_where ( r ) ) ;
288
		    if ( isglob ( id ) ) {
289
			if ( name ( sh ( e ) ) == prokhd ) return ( External ) ;
290
			return ( Other ) ;
291
		    }
292
		    switch ( pt_id ) {
293
#ifndef tdf3
294
                        case par2_pl :
295
                        case par3_pl :
296
#endif
297
 
298
			case par_pl :
299
			case var_pl : return ( EffAddr ) ;
300
			case reg_pl : return ( find_reg_ind ( no ( id ) ) ) ;
301
		    }
302
		    break ;
303
		}
304
 
305
		case cont_tag : {
306
		    exp rr = son ( r ) ;
307
		    if ( name ( rr ) == name_tag ) {
308
			exp id = son ( rr ) ;
309
			if ( !isvar ( id ) ) break ;
310
			if ( isglob ( id ) ) return ( Other ) ;
311
			switch ( ptno ( id ) ) {
312
#ifndef tdf3
313
                            case par2_pl :
314
                            case par3_pl :
315
#endif
316
 
317
			    case par_pl :
318
			    case var_pl : return ( EffAddr ) ;
319
			    case reg_pl : {
320
				return ( find_reg_ind ( no ( id ) ) ) ;
321
			    }
322
			}
323
		    }
324
		    break ;
325
		}
326
 
327
		case reff_tag : {
328
		    exp rr = son ( r ) ;
329
		    switch ( name ( rr ) ) {
330
 
331
			case name_tag : {
332
			    exp id = son ( rr ) ;
333
			    if ( ptno ( id ) == reg_pl ) {
334
				return ( find_reg_ind ( no ( id ) ) ) ;
335
			    }
336
			    return ( Other ) ;
337
			}
338
 
339
			case cont_tag : {
340
			    exp id = son ( son ( rr ) ) ;
341
			    if ( ptno ( id ) == reg_pl ) {
342
				return ( find_reg_ind ( no ( id ) ) ) ;
343
			    }
344
			    return ( Other ) ;
345
			}
346
 
347
			case addptr_tag : return ( find_where ( rr ) ) ;
348
		    }
349
		    break ;
350
		}
351
 
352
		case addptr_tag : {
353
		    exp rr = son ( r ) ;
354
		    exp eb = bro ( rr ) ;
355
		    exp ec = simple_exp ( cont_tag ) ;
356
		    son ( ec ) = rr ;
357
		    switch ( name ( eb ) ) {
358
			case name_tag :
359
			case cont_tag : return ( find_ind ( eb, ec ) ) ;
360
			case offset_mult_tag : {
361
			    return ( find_ind ( son ( eb ), ec ) ) ;
362
			}
363
		    }
364
		    break ;
365
		}
366
	    }
367
	    break ;
368
	}
369
 
370
	case reff_tag :
371
	case dummy_tag : {
372
	    exp r = son ( e ) ;
373
	    switch ( name ( r ) ) {
374
 
375
		case ident_tag : {
376
		    if ( ptno ( r ) == reg_pl ) {
377
			return ( find_reg_ind ( no ( r ) ) ) ;
378
		    }
379
		    break ;
380
		}
381
 
382
		case name_tag : {
383
		    exp id = son ( r ) ;
384
		    if ( isglob ( id ) ) return ( External ) ;
385
		    if ( ptno ( r ) == reg_pl ) {
386
			return ( find_reg_ind ( no ( id ) ) ) ;
387
		    }
388
		    break ;
389
		}
390
 
391
		case cont_tag :
392
		case ass_tag : {
393
		    exp id = son ( son ( r ) ) ;
394
		    if ( isglob ( id ) ) return ( External ) ;
395
		    if ( ptno ( r ) == reg_pl ) {
396
			return ( find_reg_ind ( no ( id ) ) ) ;
397
		    }
398
		    break ;
399
		}
400
 
401
		case addptr_tag : return ( find_where ( r ) ) ;
402
	    }
403
	    break ;
404
	}
405
 
406
	case addptr_tag : {
407
	    exp r = son ( e ) ;
408
	    exp eb = bro ( r ) ;
409
	    exp ec = simple_exp ( cont_tag ) ;
410
	    son ( ec ) = r ;
411
	    switch ( name ( eb ) ) {
412
		case name_tag :
413
		case cont_tag : return ( find_ind ( eb, ec ) ) ;
414
		case offset_mult_tag : {
415
		    return ( find_ind ( son ( eb ), ec ) ) ;
416
		}
417
	    }
418
	    break ;
419
	}
420
 
421
	case diagnose_tag : {
422
	    exp r = son ( e ) ;
423
	    return ( find_where ( r ) ) ;
424
	}
425
    }
426
    /* Allow all other operands through */
427
    return ( Other ) ;
428
}
429
 
430
 
431
/*
432
    CREATE A WHERE
433
 
434
    A where is created from an expression e and an offset d.  The routine
435
    find_where is used to calculate the wh_is and wh_regs fields.
436
*/
437
 
438
where mw
439
    PROTO_N ( ( e, d ) )
440
    PROTO_T ( exp e X long d )
441
{
442
  where w ;
443
#if 0
444
 
445
  if ((name(e)==name_tag && name(sh(e)) == prokhd) &&
446
      !(((son (son(e)) == nilexp || name (son (son(e))) == proc_tag ||
447
	  name(son(son(e))) == apply_tag ||
448
	  name(son(son(e))) == apply_general_tag)))) {
449
    exp proc_cont = getexp(sh(e),nilexp,0,e,nilexp,0,0,cont_tag);
450
    e = proc_cont;
451
  }
452
#endif
453
  w.wh_exp = e ;
454
  w.wh_off = d ;
455
  where_regmsk = 0 ;
456
  w.wh_is = find_where ( e ) ;
457
  w.wh_regs = where_regmsk ;
458
  return ( w ) ;
459
}
460
 
461
 
462
/*
463
    CREATE A WHERE REPRESENTING A NUMBER
464
 
465
    A where is created corresponding to the integer constant d.
466
*/
467
 
468
where mnw
469
    PROTO_N ( ( d ) )
470
    PROTO_T ( long d )
471
{
472
    where w ;
473
    w.wh_exp = zeroe ;
474
    w.wh_off = d ;
475
    w.wh_is = Value ;
476
    w.wh_regs = 0 ;
477
    return ( w ) ;
478
}
479
 
480
 
481
/*
482
    CREATE A WHERE REPRESENTING A FLOATING POINT NUMBER
483
 
484
    A where is created corresponding to the floating point number with
485
    sign sg (+1, 0 or -1), digits v and exponent e.
486
*/
487
 
488
where mfw
489
    PROTO_N ( ( sg, v, e ) )
490
#if ( FBASE == 10 )
491
    PROTO_T ( int sg X char *v X int e )
492
#else
493
    PROTO_T ( int sg X long *v X int e )
494
#endif
495
{
496
    where w ;
497
    int i, lv ;
498
    long lab = next_lab () ;
499
    exp fe, ft = simple_exp ( internal_tag ) ;
500
    long fm = new_flpt () ;
501
    flt *f = &flptnos [ fm ] ;
502
    f->sign = sg ;
503
    f->exp = e ;
504
#if ( FBASE == 10 )
505
    lv = strlen ( v ) ;
506
    for ( i = 0 ; i < lv ; i++ ) f->mant [i] = v [i] - '0' ;
507
#else
508
    i = 0 ;
509
    while ( v [i] != -1 ) {
510
	f->mant [i] = v [i] ;
511
	i++ ;
512
    }
513
    lv = i ;
514
#endif
515
    for ( i = lv ; i < MANT_SIZE ; i++ ) f->mant [i] = 0 ;
516
    fe = new_exp ( realsh, nilexp, fm, real_tag ) ;
517
    make_constant ( lab, fe ) ;
518
    no ( ft ) = lab ;
519
    w.wh_exp = ft ;
520
    w.wh_off = 0 ;
521
    w.wh_is = Value ;
522
    w.wh_regs = 0 ;
523
    return ( w ) ;
524
}
525
 
526
 
527
/*
528
    CONSTRUCT A REGISTER PAIR
529
 
530
    A where is created corresponding to the register pair a:b.  Both
531
    a and b must represent registers.
532
*/
533
 
534
where regpair
535
    PROTO_N ( ( a, b ) )
536
    PROTO_T ( where a X where b )
537
{
538
    where w ;
539
    exp ea = a.wh_exp ;
540
    exp eb = b.wh_exp ;
541
    w.wh_exp = getexp ( realsh, eb, 0, ea, nilexp, 0, 0, regpair_tag ) ;
542
    w.wh_off = 0 ;
543
    w.wh_is = RegPair ;
544
    where_regmsk = 0 ;
545
    if ( find_where ( ea ) != Dreg || find_where ( eb ) != Dreg ) {
546
	error ( "Illegal register pair" ) ;
547
    }
548
    w.wh_regs = where_regmsk ;
549
    return ( w ) ;
550
}
551
 
552
 
553
/*
554
    CONSTANT WHERE'S
555
 
556
    These represent commonly used numerical constants and registers.
557
    zero is the integer 0.  RW[] is the array of all registers.  A6_4
558
    represents a position on the stack.  A0_p, A1_p, SP_p and A6_4_p
559
    represent pointers.  D0_D1 is a register pair.
560
*/
561
 
562
where zero ;
563
where fzero ;
564
where RW [ NO_OF_REGS ] ;
565
where A6_4, A0_p, A1_p, SP_p, A6_4_p, D0_D1 ;
566
where dummy_double_dest ;
567
where firstlocal;
568
 
569
 
570
/*
571
    CONSTANT EXP'S
572
 
573
    These expressions are the wh_exp fields of the where's above.
574
*/
575
 
576
exp zeroe ;
577
static exp fzeroe ;
578
static exp RE [ NO_OF_REGS ] ;
579
static exp E_long, E_float, E_ptr, E_A6_4 ;
580
static exp firstlocalid;
581
 
582
/*
583
    SET UP CONSTANTS WHERE'S
584
 
585
    The constant where's are initialized.
586
*/
587
 
588
void init_wheres
589
    PROTO_Z ()
590
{
591
    int i ;
592
 
593
    /* Set up the exps corresponding to 0 */
594
    zeroe = new_exp ( botsh, nilexp, 0, val_tag ) ;
595
    fzeroe = new_exp ( realsh, nilexp, fzero_no, real_tag ) ;
596
 
597
    /* Set up the corresponding wheres */
598
    zero = zw ( zeroe ) ;
599
    fzero = zw ( fzeroe ) ;
600
 
601
    /* Create some dummy exp's */
602
    E_long = new_exp ( slongsh, nilexp, 0, val_tag ) ;
603
    E_float = new_exp ( realsh, nilexp, 0, real_tag ) ;
604
    E_ptr = new_exp ( ptrsh, E_long, 0, cont_tag ) ;
605
    E_A6_4 = new_exp ( botsh, E_ptr, 0, ident_tag ) ;
606
    ptno ( E_A6_4 ) = var_pl ;
607
 
608
    /* Set up the exp's corresponding to the utility registers */
609
    for ( i = 0 ; i < NO_OF_REGS ; i++ ) {
610
	exp t = E_float ;
611
	if ( is_dreg ( i ) ) t = E_long ;
612
	if ( is_areg ( i ) ) t = E_ptr ;
613
	RE [i] = new_exp ( botsh, t, regmsk ( i ), ident_tag ) ;
614
	ptno ( RE [i] ) = reg_pl ;
615
	RW [i] = zw ( new_exp ( slongsh, RE [i], 0, name_tag ) ) ;
616
    }
617
 
618
    /* Set up some pointer where's */
619
    A0_p = zw ( new_exp ( ptrsh, A0.wh_exp, 0, cont_tag ) ) ;
620
    A1_p = zw ( new_exp ( ptrsh, A1.wh_exp, 0, cont_tag ) ) ;
621
    SP_p = zw ( new_exp ( ptrsh, SP.wh_exp, 0, cont_tag ) ) ;
622
    A6_4 = zw ( new_exp ( slongsh, E_A6_4, -32, name_tag ) ) ;
623
    A6_4_p = zw ( new_exp ( ptrsh, A6_4.wh_exp, 0, cont_tag ) ) ;
624
 
625
    /* Set up the register pair D0:D1 */
626
    D0_D1 = regpair ( D0, D1 ) ;
627
 
628
    dummy_double_dest = zw(get_dummy_double_dest()) ;
629
 
630
    firstlocalid = new_exp (f_bottom, E_long, 0, ident_tag);
631
    ptno(firstlocalid) = var_pl;
632
    firstlocal = zw (new_exp (slongsh, firstlocalid, -32, name_tag));
633
}
634
 
635
 
636
/*
637
    ARE TWO WHERE'S EQUAL?
638
 
639
    This is actually an auxiliary routine.  eq_where ( a, b ) is a macro
640
    defined to be eq_where_a ( a, b, 1 ).  It returns 1 if the where's
641
    a and b are equal, but 0 otherwise.
642
*/
643
 
644
bool eq_where_a
645
    PROTO_N ( ( wa, wb, first ) )
646
    PROTO_T ( where wa X where wb X int first )
647
{
648
    where sa, sb ;
649
    exp a = wa.wh_exp ;
650
    exp b = wb.wh_exp ;
651
    char na = name ( a ) ;
652
    char nb = name ( b ) ;
653
 
654
    if ( wa.wh_off != wb.wh_off ) return ( 0 ) ;
655
    if ( a == b ) return ( 1 ) ;
656
 
657
    if ( na == nb ) {
658
 
659
	switch ( na ) {
660
 
661
	    case val_tag : {
662
		return ( no ( a ) == no ( b ) ? 1 : 0 ) ;
663
	    }
664
 
665
	    case ident_tag : {
666
		if ( no ( a ) != no ( b ) ) return ( 0 ) ;
667
		return ( ptno ( a ) == ptno ( b ) ? 1 : 0 ) ;
668
	    }
669
 
670
	    case name_tag :
671
	    case field_tag :
672
	    case reff_tag : {
673
		if ( no ( a ) != no ( b ) ) return ( 0 ) ;
674
		sa.wh_exp = son ( a ) ;
675
		sa.wh_off = 0 ;
676
		sb.wh_exp = son ( b ) ;
677
		sb.wh_off = 0 ;
678
		return ( eq_where_a ( sa, sb, 0 ) ) ;
679
	    }
680
 
681
	    case cont_tag : {
682
		sa.wh_exp = son ( a ) ;
683
		sa.wh_off = 0 ;
684
		sb.wh_exp = son ( b ) ;
685
		sb.wh_off = 0 ;
686
		return ( eq_where_a ( sa, sb, 0 ) ) ;
687
	    }
688
 
689
	    case real_tag : {
690
		int i ;
691
		bool z = 1 ;
692
		flt fa, fb ;
693
		fa = flptnos [ no ( a ) ] ;
694
		fb = flptnos [ no ( b ) ] ;
695
 
696
		for ( i = 0 ; i < MANT_SIZE ; i++ ) {
697
		    if ( fa.mant [i] != fb.mant [i] ) return ( 0 ) ;
698
		    if ( fa.mant [i] ) z = 0 ;
699
		}
700
 
701
		if ( z ) return ( 1 ) ;
702
		if ( fa.exp != fb.exp ) return ( 0 ) ;
703
		if ( fa.sign != fb.sign ) return ( 0 ) ;
704
		return ( 1 ) ;
705
	    }
706
	}
707
	return ( 0 ) ;
708
    }
709
 
710
    if ( first && na == name_tag && nb == ident_tag ) {
711
	if ( no ( a ) ) return ( 0 ) ;
712
	sa.wh_exp = son ( a ) ;
713
	sa.wh_off = 0 ;
714
	return ( eq_where_a ( sa, wb, 0 ) ) ;
715
    }
716
 
717
    if ( first && nb == name_tag && na == ident_tag ) {
718
	if ( no ( b ) ) return ( 0 ) ;
719
	sb.wh_exp = son ( b ) ;
720
	sb.wh_off = 0 ;
721
	return ( eq_where_a ( wa, sb, 0 ) ) ;
722
    }
723
 
724
    if ( ( na == cont_tag || na == ass_tag ) &&
725
	 name ( son ( a ) ) == name_tag &&
726
	 isvar ( son ( son ( a ) ) ) &&
727
	 ( nb == ident_tag || nb == name_tag ) ) {
728
	if ( no ( son ( a ) ) ) return ( 0 ) ;
729
	sa.wh_exp = son ( son ( a ) ) ;
730
	sa.wh_off = 0 ;
731
	return ( eq_where_a ( sa, wb, 0 ) ) ;
732
    }
733
 
734
    if ( ( nb == cont_tag || nb == ass_tag ) &&
735
	 name ( son ( b ) ) == name_tag &&
736
	 isvar ( son ( son ( b ) ) ) &&
737
	 ( na == ident_tag || na == name_tag ) ) {
738
	if ( no ( son ( b ) ) ) return ( 0 ) ;
739
	sb.wh_exp = son ( son ( b ) ) ;
740
	sb.wh_off = 0 ;
741
	return ( eq_where_a ( wa, sb, 0 ) ) ;
742
    }
743
 
744
 
745
    if ( ( na == ass_tag && nb == cont_tag ) ||
746
	 ( nb == ass_tag && na == cont_tag ) ) {
747
	sa.wh_exp = son ( a ) ;
748
	sa.wh_off = 0 ;
749
	sb.wh_exp = son ( b ) ;
750
	sb.wh_off = 0 ;
751
	return ( eq_where_a ( sa, sb, 0 ) ) ;
752
    }
753
 
754
    return ( 0 ) ;
755
}