Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – tendra.SVN – Blame – /branches/algol60/src/installers/sparc/common/locate.c – Rev 2

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
 
31
 
32
 
33
/*
34
			    VERSION INFORMATION
35
			    ===================
36
 
37
--------------------------------------------------------------------------
38
$Header: /u/g/release/CVSROOT/Source/src/installers/sparc/common/locate.c,v 1.1.1.1 1998/01/17 15:55:54 release Exp $
39
--------------------------------------------------------------------------
40
$Log: locate.c,v $
41
 * Revision 1.1.1.1  1998/01/17  15:55:54  release
42
 * First version to be checked into rolling release.
43
 *
44
 * Revision 1.11  1997/08/23  13:53:55  pwe
45
 * initial ANDF-DE
46
 *
47
 * Revision 1.10  1997/02/18  11:47:54  pwe
48
 * NEWDIAGS for debugging optimised code
49
 *
50
 * Revision 1.9  1996/03/20  16:13:56  john
51
 * Reformatting
52
 *
53
 * Revision 1.8  1996/01/23  10:31:13  john
54
 * Fix to handle env_offset in locate
55
 *
56
 * Revision 1.7  1995/12/15  10:24:59  john
57
 * Changed env_offset calculation
58
 *
59
 * Revision 1.6  1995/11/24  11:41:22  john
60
 * Change to caller location
61
 *
62
 * Revision 1.5  1995/11/02  18:03:43  john
63
 * Stopped using local reg to access data
64
 *
65
 * Revision 1.4  1995/07/14  16:31:26  john
66
 * Minor change
67
 *
68
 * Revision 1.3  1995/06/14  15:34:08  john
69
 * Fixed error in calculating offset for local_reg based address.
70
 *
71
 * Revision 1.2  1995/05/26  12:59:16  john
72
 * Changes for new spec (3.1)
73
 *
74
 * Revision 1.1.1.1  1995/03/13  10:18:42  john
75
 * Entered into CVS
76
 *
77
 * Revision 1.5  1994/12/01  13:47:39  djch
78
 * Create boff_env_offset to get the stack offset of an ident. Needs to trace the
79
 * parent proc.
80
 *
81
 * Revision 1.4  1994/07/04  10:48:58  djch
82
 * Jun94 tape version
83
 *
84
 * Revision 1.3  1994/05/25  14:15:07  djch
85
 * Added CREATE_instore_bits to shut up tcc
86
 *
87
 * Revision 1.2  1994/05/13  12:34:45  djch
88
 * Incorporates improvements from expt version
89
 * Use of new macros in addrtypes.h
90
 *
91
 * Revision 1.1  1994/05/03  14:49:41  djch
92
 * Initial revision
93
 *
94
 * Revision 1.5  93/08/27  11:29:36  11:29:36  ra (Robert Andrews)
95
 * Added a couple of explicit integer casts.
96
 * 
97
 * Revision 1.4  93/08/13  14:38:14  14:38:14  ra (Robert Andrews)
98
 * Reformatted.
99
 * 
100
 * 
101
 * Revision 1.3  93/07/05  18:20:37  18:20:37  ra (Robert Andrews)
102
 * Reordered include files.
103
 * 
104
 * Revision 1.2  93/06/29  14:27:11  14:27:11  ra (Robert Andrews)
105
 * Changed failer to fail.
106
 * 
107
 * Revision 1.1  93/06/24  14:58:37  14:58:37  ra (Robert Andrews)
108
 * Initial revision
109
 * 
110
--------------------------------------------------------------------------
111
*/
112
 
113
#define SPARCTRANS_CODE
114
#include "config.h"
115
#include "common_types.h"
116
#include "myassert.h"
117
#include "addrtypes.h"
118
#include "expmacs.h"
119
#include "tags.h"
120
#include "inst_fmt.h"
121
#include "regmacs.h"
122
#include "sparcins.h"
123
#include "bitsmacs.h"
124
#include "exp.h"
125
#include "procrec.h"
126
#include "guard.h"
127
#include "eval.h"
128
#include "regexps.h"
129
#include "shapemacs.h"
130
#include "comment.h"
131
#include "getregs.h"
132
#include "move.h"
133
#include "regable.h"
134
#include "codehere.h"
135
#include "proc.h"
136
#include "locate.h"
137
#include "flags.h"
138
#include "translat.h"
139
 
140
int call_base_reg = R_SP;
141
 
142
/*
143
  DECODE x INTO A BASE REGISTER PLUS OFFSET
144
*/
145
 
146
baseoff boff 
147
    PROTO_N ( ( e ) )
148
    PROTO_T ( exp e ){
149
  int n = no ( e ) ;
150
  int b = REG_PART(n);
151
  baseoff an ;
152
  if ( isglob ( e ) ) {
153
    /* bro is index in main_globals */
154
    dec *gl = brog ( e ) ;
155
    long sno = gl->dec_u.dec_val.sym_number ;
156
    an.base = ( int ) ( -( sno + 1 ) ) ;
157
    an.offset = 0 ;
158
  } 
159
  else if ( isparam ( e ) && name(son(e)) != formal_callee_tag) {
160
    /* parameter, positive offset from %fp */
161
    /* assert ( name ( son ( e ) ) == clear_tag ) ;*/
162
    an.base = R_FP ;
163
    an.offset = BITS2BYTES( no ( son ( e ) ) + proc_state.params_offset );
164
    assert ( an.offset >= BITS2BYTES(proc_state.params_offset) ) ;
165
  } 
166
  else if (isparam(e) && name(son(e)) == formal_callee_tag){
167
    an.base = R_SP;
168
    an.offset = BITS2BYTES(no(son(e)));
169
#if 1
170
    if(Has_vcallees){
171
      an.base = local_reg;
172
      an.base = callee_start_reg;
173
      an.offset = BITS2BYTES(no(son(e)));
174
    }
175
    else{
176
/*
177
      an.base = R_FP;
178
      an.offset = BITS2BYTES(no(son(e)) - proc_state.callee_size);
179
*/
180
      an.base = callee_start_reg;
181
      an.offset = BITS2BYTES(no(son(e)));
182
    }
183
#endif
184
  }
185
  else if(name(son(e)) == caller_name_tag){
186
    /* caller name tag is located at [%sp+paramsoffset] */
187
    an.base = R_SP;
188
     an.base = call_base_reg;
189
    an.offset = BYTE_OFFSET_PART(n) + BITS2BYTES(PARAMS_OFFSET) ;
190
 
191
  }	
192
  else if ( b == R_FP ) {
193
    /* locally declared things, negative offset from %fp */
194
    an.base = R_FP ;
195
    an.offset = -( BITS2BYTES(proc_state.locals_space)) +
196
      BYTE_OFFSET_PART(n) + BITS2BYTES(proc_state.locals_offset) /*-
197
      BITS2BYTES(proc_state.callee_size)*/;
198
    assert ( an.offset <= 0 ) ;
199
    assert ( an.offset >= -(BITS2BYTES(proc_state.locals_space /*+ 
200
				       proc_state.callee_size*/))) ;
201
  } 
202
  else if ( b == R_SP ) {
203
    /* on stack temps */
204
    an.base = R_SP ;
205
    an.offset = BYTE_OFFSET_PART(n) ;
206
  } 
207
#if 0
208
  else if (b == local_reg && Has_vcallees){
209
    an.base = b;
210
    an.offset = -( BITS2BYTES(proc_state.locals_space)) +
211
      BYTE_OFFSET_PART(n) + BITS2BYTES(proc_state.locals_offset);
212
  }	
213
#endif
214
  else if ( b <= 31 ) {
215
    /* other base register and offset */
216
    an.base = b ;
217
    an.offset = BYTE_OFFSET_PART(n) ;
218
  }	
219
 
220
#if 1
221
  /* obsolete */
222
  else if ( b == 32 ) {
223
    /* global names */
224
    an.base = - ADDR_PART(n) ;
225
    an.offset = 0 ;
226
  } 
227
  else if ( b == 33 ) {
228
    /* local data label : LDNNNN */
229
    an.base = ADDR_PART(n) ;
230
    an.offset = 0 ;
231
  }
232
#endif
233
  else {
234
    fail ( "not a baseoff in boff" ) ;
235
  }
236
  return ( an ) ;
237
}
238
 
239
int boff_env_offset 
240
    PROTO_N ( ( e ) )
241
    PROTO_T ( exp e ){
242
  /* used ONLY for envoffsets as init values for globals. 
243
   cf make_proc_tag_code */
244
  int n = no ( e ) ;
245
  /*int b = REG_PART(n);*/
246
  int offset = 0x7fffffff;/* if not set should be outside stack seg */
247
  /*int this_callee_size = 0;*/
248
  exp x = e;
249
  assert (! isglob ( e ));
250
  /*assert (b == R_FP);*/
251
 
252
#define VAL_params_offset ( ( 16 + 1 ) * 32 )
253
#define VAL_locals_offset (0)
254
  while (name(x) != proc_tag && name(x)!=general_proc_tag){
255
    x = father(x);
256
    assert (x != nilexp);
257
  }
258
  if ( isparam ( e ) ) {
259
    /* parameter, positive offset from %fp */
260
    /*    assert ( name ( son ( e ) ) == clear_tag ) ;*/
261
    if(name(son(e)) == formal_callee_tag) {
262
      offset =  no(son(e))>>3;
263
    }
264
    else {
265
      offset = BITS2BYTES( no ( son ( e ) ) + VAL_params_offset );
266
      assert ( offset >= BITS2BYTES(VAL_params_offset) ) ;
267
    }
268
  } 
269
  else {
270
  /* locally declared things, negative offset from %fp */
271
  /* Now we need the stack size from the procrec, so find the proc */
272
    long locals_space;
273
 
274
    locals_space = procrecs[no(x)].spacereqproc.stack;
275
    locals_space = (locals_space +63) &~63; /* 8 byte aligned */
276
    offset = -( BITS2BYTES(locals_space)) +
277
      BYTE_OFFSET_PART(n) + BITS2BYTES(VAL_locals_offset) ;
278
    assert ( offset < 0 ) ;
279
    assert ( offset >= -(BITS2BYTES(locals_space))) ;
280
  }
281
  return ( offset ) ;
282
}	
283
 
284
 
285
/*
286
  AUXILLIARY LOCATION ROUTINE
287
 
288
  Finds the address of the expression e using shape s.  sp gives the
289
  available t-registers for any inner evaluation.  dreg is 
290
  historical.
291
*/
292
 
293
where locate1 
294
    PROTO_N ( ( e, sp, s, dreg ) )
295
    PROTO_T ( exp e X space sp X shape s X int dreg ){
296
  ash a ;
297
  ans aa ;
298
  where wans ;
299
  a = ashof ( s ) ;
300
 
301
  switch ( name ( e ) ) {
302
    case name_tag : {
303
      /* this a locally declared name ... */
304
      exp dc = son ( e ) ;
305
      bool var = ( bool ) isvar ( dc ) ;
306
      if ( props ( dc ) & defer_bit ) {
307
	/* ... it has been identified with a simple expression
308
	   which is better evaluated every time */
309
	where w ;
310
	w = locate ( son ( dc ), sp, sh ( son ( dc ) ), dreg ) ;
311
	if ( no ( e ) == 0 ) {
312
	  aa = w.answhere ;
313
	} 
314
        else {
315
	  instore is ;
316
	  switch ( discrim ( w.answhere ) ) {
317
	    case notinreg : {
318
	      is = insalt ( w.answhere ) ;
319
	      is.b.offset += ( no ( e ) / 8 ) ;
320
	      break ;
321
	    }
322
	    default : {
323
	      fail ( "name not deferable" ) ;
324
	    }
325
	  }
326
	  setinsalt ( aa, is ) ;
327
	}
328
      } 
329
      else if ( props ( dc ) & inreg_bits ) {
330
	/* ... it has been allocated in a fixed point register */
331
	if ( var ) {
332
	  setregalt ( aa, no ( dc ) ) ;
333
	} 
334
        else {
335
	  instore b ;
336
	  b.b.base = no ( dc ) ;
337
	  b.b.offset = 0 ;
338
	  b.adval = 1 ;
339
	  setinsalt ( aa, b ) ;
340
	}
341
      } 
342
      else if ( props ( dc ) & infreg_bits ) {
343
	/* ... it has been allocated in a floating point register */
344
	freg fr ;
345
	fr.fr = no ( dc ) ;
346
	fr.dble = ( bool ) ( ( a.ashsize == 64 ) ? 1 : 0 ) ;
347
	setfregalt ( aa, fr ) ;
348
      } 
349
      else {
350
	/* ... it is in memory */
351
	instore is ;
352
	if ( var || ( name ( sh ( e ) ) == prokhd &&
353
		      ( son ( dc ) == nilexp ||
354
			name ( son ( dc ) ) == proc_tag ||
355
			name(son(dc)) == general_proc_tag) ) ) {
356
	  is.adval = 1 ;
357
	} 
358
        else {
359
	  is.adval = 0 ;
360
	}
361
	is.b = boff ( dc ) ;
362
	is.b.offset += BITS2BYTES(no(e));
363
	setinsalt(aa,is);
364
      }
365
      wans.answhere = aa ;
366
      wans.ashwhere = a ;
367
      return ( wans ) ;
368
    }
369
    case addptr_tag : {
370
      exp sum = son ( e ) ;
371
      where wsum ;
372
      int addend ;
373
      space nsp ;
374
      int reg ;
375
      int ind = R_NO_REG ;
376
      instore is ;
377
      ans asum ;
378
 
379
      wsum = locate ( sum, sp, sh ( sum ), 0 ) ;
380
      asum = wsum.answhere ;
381
 
382
      /* answer is going to be wsum displaced by integer result of
383
       evaluating bro ( sum ) */
384
      switch ( discrim ( asum ) ) {
385
	case notinreg : {
386
	  is = insalt ( asum ) ;
387
	  if ( is.adval ) {
388
	    /* wsum is a literal address in store ... */
389
	    baseoff b ;
390
	    b = is.b ;
391
	    if ( !IS_FIXREG ( b.base ) ) {
392
	      /* ... it is not a base-offset, so make it one */
393
	      reg = getreg ( sp.fixed ) ;
394
	      set_ins ( b, reg ) ;
395
	      keepreg ( sum, reg ) ;
396
	      b.base = reg ;
397
	      b.offset = 0 ;
398
	    }
399
	    nsp = guardreg ( b.base, sp ) ;
400
	    addend = reg_operand ( bro ( sum ), nsp ) ;
401
 
402
	    /* evaluate the displacement ... */
403
	    if ( dreg == 0 ) dreg = getreg ( nsp.fixed ) ;
404
	    rrr_ins ( i_add, b.base, addend, dreg ) ;
405
	    clear_reg ( dreg ) ;
406
 
407
	    /* ... add it to the base register into new reg */
408
	    b.base = dreg ;
409
	    is.b = b ;
410
	    setinsalt ( aa, is ) ;
411
	    wans.answhere = aa ;
412
	    wans.ashwhere = a ;
413
 
414
	    /* ...and use it as base a literal base-offset result */
415
	    keepexp ( e, aa ) ;
416
	    return ( wans ) ;
417
	  } 
418
          else {
419
	    /* wsum represents an actual pointer in store ... */
420
	    /* ... so load it into a good register */
421
	    ind = getreg ( sp.fixed ) ;
422
	    ld_ins ( i_ld, is.b, ind ) ;
423
	  }
424
	  break ;
425
	}
426
	case inreg : {
427
	  /* wsum is already in reg */
428
	  ind = regalt ( asum ) ;
429
	  break ;
430
	}
431
	default : {
432
	  fail ( "locate ? reg" ) ;
433
	}
434
      }
435
    /*register ind contains the evaluation of 1st operand of addptr*/
436
      if ( name ( bro ( sum ) ) == env_offset_tag || 
437
	   name (bro(sum)) == general_env_offset_tag) {
438
	is.b.base = ind;
439
	is.b.offset = boff_env_offset(son(bro(sum)));
440
      }
441
      nsp = guardreg ( ind, sp ) ;
442
      addend = reg_operand ( bro ( sum ), nsp ) ;
443
      /* evaluate displacement, add it to ind in new reg */
444
      if ( dreg == 0 ) dreg = getreg ( nsp.fixed ) ;
445
      rrr_ins ( i_add, ind, addend, dreg ) ;
446
      clear_reg ( dreg ) ;
447
      is.b.base = dreg ;
448
      is.b.offset = 0 ;
449
      is.adval = 1 ;
450
      setinsalt ( aa, is ) ;
451
      wans.answhere = aa ;
452
      wans.ashwhere = a ;
453
      /* ... and deliver literal base_offset */
454
      keepexp ( e, aa ) ;
455
      return ( wans ) ;
456
    }
457
    case subptr_tag : {
458
      /* shouldn't occur */
459
      exp sum = son ( e ) ;
460
      int ind = reg_operand ( sum, sp ) ;
461
      instore isa ;
462
      isa.adval = 1 ;
463
      sum = bro ( sum ) ;
464
      if ( name ( sum ) == val_tag ) {
465
	isa.b.base = ind ;
466
	isa.b.offset = -no ( e ) ;
467
	setinsalt ( aa, isa ) ;
468
      } 
469
      else {
470
	if ( dreg == 0 ) dreg = getreg ( sp.fixed ) ;
471
	rrr_ins ( i_sub, ind,
472
		  reg_operand ( sum, guardreg ( ind, sp ) ), dreg ) ;
473
	isa.b.base = dreg ;
474
	isa.b.offset = 0 ;
475
      }
476
      setinsalt ( aa, isa ) ;
477
      wans.answhere = aa ;
478
      wans.ashwhere = a ;
479
      keepexp ( e, aa ) ;
480
      return ( wans ) ;
481
    }
482
    case reff_tag : {
483
      /* answer is going to be wans displaced by no ( e ) */
484
      wans = locate ( son ( e ), sp, sh ( son ( e ) ), 0 ) ;
485
      switch ( discrim ( wans.answhere ) ) {
486
	case notinreg : {
487
	  instore isa;
488
	  isa = insalt ( wans.answhere ) ;
489
	  if ( !isa.adval ) {
490
	    /* wans is an actual pointer in store, so make it
491
	       into a literal address ...  */
492
	    int reg = getreg ( sp.fixed ) ;
493
	    ld_ins ( i_ld, isa.b, reg ) ;
494
	    isa.b.offset = 0 ;
495
	    isa.b.base = reg ;
496
	    isa.adval = 1 ;
497
	  }
498
	  /* ... and add appropriate displacement to give result */
499
	  isa.b.offset += BITS2BYTES(no ( e )) ;
500
	  setinsalt ( wans.answhere, isa ) ;
501
	  keepexp ( e, wans.answhere ) ;
502
	  break ;
503
	}
504
	case inreg : {
505
	  /* wans is a pointer in a register */
506
	  instore isa;
507
 
508
	  isa.b.base = regalt ( wans.answhere ) ;
509
	  isa.adval = 1 ;
510
	  isa.b.offset = BITS2BYTES(no ( e )) ;
511
	  setinsalt ( wans.answhere, isa ) ;
512
	  break ;
513
	}
514
	default : {
515
	  fail ( "locate ? reg " ) ;
516
	}
517
      }
518
      wans.ashwhere = a ;
519
      return ( wans ) ;
520
    }
521
    case cont_tag :
522
    case contvol_tag : {
523
      exp se = son ( e ) ;
524
      ans ason ;
525
      instore isa ;
526
      int reg ;
527
      where fc ;
528
      /* answer is contents of address represented by fc */
529
      fc = locate ( se, sp, sh ( e ), 0 ) ;
530
      ason = fc.answhere ;
531
      switch ( discrim ( ason ) ) {
532
	case notinreg : {
533
	  isa = insalt ( ason ) ;
534
	  if ( isa.adval ) {
535
	    /* literal store address, make it a direct one */
536
	    isa.adval = 0 ;
537
	    setinsalt ( aa, isa ) ;
538
	  } 
539
          else {
540
	    /* actual pointer in store so load it into reg and
541
	       deliver direct base-offset ( reg, 0 ) */
542
	    reg = getreg ( sp.fixed ) ;
543
	    ld_ins ( i_ld, isa.b, reg ) ;
544
	    isa.b.base = reg ;
545
	    isa.b.offset = 0 ;
546
	    setinsalt ( aa, isa ) ;
547
	    if ( name ( e ) != contvol_tag &&
548
		 fc.ashwhere.ashalign != 1 ) {
549
	      keepexp ( e, aa ) ;
550
	    }
551
	  }
552
	  goto breakson ;
553
	}
554
	case inreg : {
555
	  /* this one is fraught - it depends on only being used
556
	     in lh-value positions from vars - take care */
557
	  isa.b.base = regalt ( ason ) ;
558
	  isa.b.offset = 0 ;
559
	  isa.adval = 1 ;
560
	  setinsalt ( aa, isa ) ;
561
	  /* fc is in register, so deliver literal base-offset */
562
	  goto breakson ;
563
	}
564
	case infreg : {
565
	  /* ditto caveat above */
566
	  aa = ason ;
567
	  goto breakson ;
568
	}
569
	default : {
570
	  fail ( "locate ? reg" ) ;
571
	}
572
      }
573
      breakson :
574
	wans.answhere = aa ;
575
      wans.ashwhere = a ;
576
      return ( wans ) ;
577
    }
578
    case top_tag : {
579
      /* does this ever happen? */
580
      setregalt ( aa, 0 ) ;
581
      wans.answhere = aa ;
582
      wans.ashwhere = a ;
583
      return ( wans ) ;
584
    }
585
    case field_tag : {
586
      /* answer is wans displace literally by no ( e ) ; it should
587
	 always be a literal store address */
588
      wans = locate ( son ( e ), sp, sh ( son ( e ) ), 0 ) ;
589
      switch ( discrim ( wans.answhere ) ) {
590
	case notinreg : {
591
	  instore isa;
592
	  isa = insalt ( wans.answhere ) ;
593
	  isa.b.offset += BITS2BYTES(no ( e )) ;
594
	  setinsalt(wans.answhere,isa);
595
	  break ;
596
	}
597
	default : {
598
	  fail ( "field should be transformed" ) ;
599
	}
600
      }
601
      wans.ashwhere = a ;
602
      return ( wans ) ;
603
    }
604
    default : {
605
      /* general catch all ; evaluate e into register and deliver
606
	 it as a literal store address */
607
      int r = reg_operand ( e, sp ) ;
608
      instore is ;
609
      /* Is this needed on SPARC??? */
610
      if ( r == R_O0 ) {
611
	/* guard possible result from proc - can do better */
612
	r = getreg ( sp.fixed ) ;
613
	if ( r != R_O0 ) rr_ins ( i_mov, R_O0, r ) ;
614
      }
615
      is.b.base = r ;
616
      is.b.offset = 0 ;
617
      is.adval = 1 ;
618
      setinsalt ( aa, is ) ;
619
      wans.answhere = aa ;
620
      wans.ashwhere = a ;
621
      return ( wans ) ;
622
    }
623
  }
624
}
625
 
626
 
627
/*
628
  MAIN LOCATION ROUTINE
629
 
630
  This is similar to locate1, but firstly checks if e is kept in a
631
  register.
632
*/
633
 
634
where locate 
635
    PROTO_N ( ( e, sp, s, dreg ) )
636
    PROTO_T ( exp e X space sp X shape s X int dreg ){
637
  ans ak ;
638
  where w ;
639
  ak = iskept ( e ) ;
640
  if ( discrim ( ak ) == inreg && regalt ( ak ) == 0 ) {
641
    w = locate1 ( e, sp, s, dreg ) ;
642
  } 
643
  else {
644
    w.answhere = ak ;
645
    w.ashwhere = ashof ( s ) ;
646
  }
647
  return ( w ) ;
648
}
649
 
650
 
651
 
652