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
    Copyright (c) 1993 Open Software Foundation, Inc.
3
 
4
 
5
    All Rights Reserved
6
 
7
 
8
    Permission to use, copy, modify, and distribute this software
9
    and its documentation for any purpose and without fee is hereby
10
    granted, provided that the above copyright notice appears in all
11
    copies and that both the copyright notice and this permission
12
    notice appear in supporting documentation.
13
 
14
 
15
    OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING
16
    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
17
    PARTICULAR PURPOSE.
18
 
19
 
20
    IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
21
    CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
22
    LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
23
    NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
24
    WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25
*/
26
 
27
/*
28
    		 Crown Copyright (c) 1997
29
 
30
    This TenDRA(r) Computer Program is subject to Copyright
31
    owned by the United Kingdom Secretary of State for Defence
32
    acting through the Defence Evaluation and Research Agency
33
    (DERA).  It is made available to Recipients with a
34
    royalty-free licence for its use, reproduction, transfer
35
    to other parties and amendment for any purpose not excluding
36
    product development provided that any such use et cetera
37
    shall be deemed to be acceptance of the following conditions:-
38
 
39
        (1) Its Recipients shall ensure that this Notice is
40
        reproduced upon any copies or amended versions of it;
41
 
42
        (2) Any amended version of it shall be clearly marked to
43
        show both the nature of and the organisation responsible
44
        for the relevant amendment or amendments;
45
 
46
        (3) Its onward transfer from a recipient to another
47
        party shall be deemed to be that party's acceptance of
48
        these conditions;
49
 
50
        (4) DERA gives no warranty or assurance as to its
51
        quality or suitability for any purpose and DERA accepts
52
        no liability whatsoever in relation to any use to which
53
        it may be put.
54
*/
55
 
56
 
57
 
58
/**********************************************************************
59
$Author: release $
60
$Date: 1998/02/04 15:48:53 $
61
$Revision: 1.2 $
62
$Log: locate.c,v $
63
 * Revision 1.2  1998/02/04  15:48:53  release
64
 * Added OSF copyright message.
65
 *
66
 * Revision 1.1.1.1  1998/01/17  15:55:57  release
67
 * First version to be checked into rolling release.
68
 *
69
 * Revision 1.2  1996/10/04  16:01:52  pwe
70
 * add banners and mod for PWE ownership
71
 *
72
**********************************************************************/
73
 
74
 
75
/* locate.c
76
     discovers "where" an "exp" is;
77
     The where coding of an address tells one whether the result of
78
      evaluating an exp is in a register or directly or literally in store,
79
*/
80
#include "config.h"
81
#include "memtdf.h"
82
#include "codegen.h"
83
#include "geninst.h"
84
 
85
#include "proc.h"
86
#include "myassert.h"
87
#include "comment.h"
88
#include "stack.h"
89
#include "locate.h"
90
#include "frames.h"
91
/******************************************************************************
92
For non globals, boff encodes things in the following way.
93
The number of bytes gives a displacement from different positions on 
94
the stack depending on whether it is relative to R_SP R_FP or R_TP
95
 
96
The stack below gives the worst case of the stack i.e a general_proc with 
97
alloca
98
  |           |
99
  |           | #
100
  |           | |  x relative to R_TP i.e caller parameters
101
  |-----------| |                     in input caller parameter area
102
  | STACK     | |
103
  | LINK      | | STACK_ARG_AREA
104
  | AREA      | |
105
  |-----------|<--------R_TP
106
  | Input     |
107
  | Callees   |
108
  |           |
109
  |           |
110
  |           |
111
  |           |
112
  |-----------|<--------R_FP
113
  |           | |
114
  |           | |
115
  |           | |                          #
116
  |           | |                          | displacement x relative to R_FP
117
  |           | |                          | coded like this in regalloc
118
  |           | | p_frame_size          #
119
  |           | |                          |
120
  |           | |                          | p_locals_offset
121
  |           | |                          |
122
  |           | |                          |
123
  |           | # <--initial R_SP was here
124
  |-----------|
125
  |           | #
126
  |           | | x relative to R_SP i.e output caller parameter construction
127
  |-----------| |
128
  | STACK     | |
129
  | LINK      | | STACK_ARG_AREA
130
  | AREA      | |
131
  |-----------|<--------R_SP
132
******************************************************************************/
133
 
134
/* decodes e to give a baseoff suitable for xxx_ins functions */
135
baseoff boff PROTO_N ((e)) PROTO_T (exp e)
136
{
137
  baseoff an;
138
 
139
  if (isglob(e))
140
  {
141
    dec *gl = brog(e);
142
    long sno = gl->dec_u.dec_val.sym_number;
143
 
144
    /* an.base is negated global sym number, positive used for base reg number */
145
    an.base = -(sno + 1);
146
    an.offset = 0;
147
  }
148
  else
149
  {
150
    return boff_location(no(e));
151
  }
152
  return an;
153
}
154
baseoff boff_location PROTO_N ((n)) PROTO_T (int n)
155
{ 
156
  baseoff an;
157
  int br = n & 0x3f;		/* base reg in bottom 6 bits */
158
  long off = (n>>6);		/* offset in bytes from br in rest */
159
 
160
  ASSERT((n<0)==(off<0));	/* any sign propagated */
161
  if(br<0)
162
    br = -br;
163
 
164
  /* There are three possiblilities for br */
165
  /* i.e R_TP R_FP R_SP */
166
  /* R_TP|
167
     -----
168
     if something is relative to R_TP it is a caller of the previous proc
169
     since R_TP is the top of the frame
170
     R_FP|
171
     -----
172
     This is all locals to the current procedure
173
     R_SP|
174
     -----
175
     This is used for constructing argument lists for calling parameters
176
 
177
     It is possible that all three are the same
178
     i.e they are all calculated from the stack pointer.
179
     However in a general_proc
180
     things get nasty and all three will point to different places
181
     */
182
  if (br == R_SP)
183
  {
184
    an.base = R_SP;
185
    an.offset = off;
186
    ASSERT(off >= 0);
187
  }
188
  else if(br == R_FP)
189
  {
190
    if(p_has_fp)
191
    {
192
      an.base = R_FP;
193
      an.offset = p_locals_offset + off - p_frame_size;
194
    }
195
    else
196
    {
197
      an.base = R_SP;
198
      an.offset = p_locals_offset + off;
199
    }
200
  }
201
  else if(br == R_TP)
202
  {
203
    if (p_has_tp)
204
    {
205
      an.base = R_TP;
206
      an.offset = off;
207
    }
208
    else if(p_has_fp)
209
    {
210
      an.base = R_FP;
211
      an.offset = off;
212
    }
213
    else 
214
    {
215
      an.base = R_SP;
216
      an.offset = off + p_frame_size;
217
    }
218
  }
219
  else
220
  {
221
    fail("Error:boff_location: Unknown base");
222
  }
223
  return an;
224
}
225
int ENCODE_FOR_BOFF PROTO_N ((off,type)) PROTO_T (int off X int type)
226
{
227
 
228
  /* type is either */
229
  /* INPUT_CALLER_PARAMETER, INPUT_CALLEE_PARAMETER, OUTPUT_CALLER_PARAMETER */
230
  /* offset shoulb be in bytes */
231
  int encode_offset;
232
  int encode_base;
233
 
234
  switch(type)
235
  {
236
   case INPUT_CALLER_PARAMETER:
237
    {
238
      encode_base = R_TP;
239
      encode_offset = off + STACK_ARG_AREA;
240
      break;
241
    }
242
   case INPUT_CALLEE_PARAMETER:
243
    {
244
      encode_base = R_FP;
245
      encode_offset = p_frame_size - p_locals_offset + EXTRA_CALLEE_BYTES + off;
246
      break;
247
    }
248
   case OUTPUT_CALLER_PARAMETER:
249
    {
250
      encode_base = R_SP;
251
      encode_offset = STACK_ARG_AREA + off;
252
      break;
253
    }
254
   default:
255
    fail("Unknown encodeing for ENCODE_FOR_BOFF");
256
  }
257
  return (encode_offset<<6) + encode_base;
258
}
259
 
260
 
261
 
262
/* mutual recursion between locate1() and locate() */
263
where locate PROTO_S ((exp, space, shape, int));
264
 
265
 
266
 /*
267
  * finds the address of e using shape s; sp gives available t-regs for any
268
  * inner evaluation. dreg is historical.
269
  */
270
static where locate1 PROTO_N ((e,sp,s,dreg)) PROTO_T (exp e X space sp X shape s X int dreg)
271
{
272
  ash a;
273
  ans aa;
274
  where wans;
275
 
276
  FULLCOMMENT3("locate1: name(e)=%d, name(s)=%d, dreg=%d", name(e), name(s), dreg);
277
 
278
  a = ashof(s);
279
 
280
  switch (name(e))
281
  {
282
    /***********************************************/
283
   case name_tag:
284
    { 
285
      /* NAME_TAG */
286
      exp dc = son(e);
287
      bool var = isvar(dc);
288
 
289
      FULLCOMMENT2("locate1 name_tag: name(dc)=%d, var=%d", name(dc), var);
290
 
291
      if (props(dc) & defer_bit)
292
      {
293
	/*
294
	 * ... it has been identified with a simple expression which is
295
	 * better evaluated every time
296
	 */
297
	where w;
298
 
299
	w = locate(son(dc), sp, sh(son(dc)), dreg);
300
 
301
	if (no(e) == 0)
302
	{
303
	  aa = w.answhere;
304
	}
305
	else
306
	{
307
	  instore is;
308
 
309
	  switch (w.answhere.discrim)
310
	  {
311
	   case notinreg:
312
	    {
313
	      is = insalt(w.answhere);
314
	      is.b.offset += (no(e) / 8);
315
	      break;
316
	    }
317
	   default:
318
	    fail("name not deferable");
319
	  }
320
 
321
	  setinsalt(aa, is);
322
	}
323
      }
324
      else if (props(dc) & inreg_bits)
325
      {
326
	/* ... it has been allocated in a fixed point reg */
327
	if (var)
328
	{
329
	  setregalt(aa, no(dc));
330
	}
331
	else
332
	{
333
	  instore b;
334
 
335
	  b.b.base = no(dc);
336
	  b.b.offset = 0;
337
	  b.adval = 1;
338
	  setinsalt(aa, b);
339
	}
340
      }
341
      else if (props(dc) & infreg_bits)
342
      {
343
	/* ... it has been allocated in a floating point reg */
344
	freg fr;
345
 
346
	fr.fr = no(dc);
347
	fr.dble = (a.ashsize == 64) ? 1 : 0;
348
	setfregalt(aa, fr);
349
      }
350
      else
351
      {
352
	/* ... it is in memory */
353
	instore is;
354
 
355
	if (var|| (name(sh(e)) == prokhd &&
356
		      (son(dc) == nilexp || IS_A_PROC(son(dc)))))
357
	{
358
	  is.adval = 1;
359
	  /* If it is a var tag you can get address of it */
360
	}
361
	else
362
	{
363
	  is.adval = 0;
364
	}
365
	is.b = boff(dc);
366
 
367
	is.b.offset += (no(e) / 8);
368
 
369
#if 1
370
	if (var && name(sh(e)) != prokhd && !IS_FIXREG(is.b.base) && is.b.offset == 0)
371
	{
372
	  /*
373
	   * A global which has to be accessed via TOC.
374
	   * We load it explicitly into reg here so we can
375
	   * use the reg contents tracking mechanism for
376
	   * addresses found in the TOC.
377
	   * If we did not do this, we would still generate correct code,
378
	   * but needlessly reload from TOC.
379
	   * +++ offset != 0 -> keepglob for 0 offset & keepreg for offset
380
	   */
381
	  if (dreg == 0)
382
	    dreg = getreg(sp.fixed);
383
 
384
	  set_ins(is.b, dreg);
385
	  keepreg(e, dreg);
386
	  FULLCOMMENT3("locate1 name_tag: keepreg glob adval=%d bo={%d,%d}", is.adval, is.b.base, is.b.offset);
387
	  is.b.base = dreg;
388
	  is.b.offset = 0;
389
	}
390
#endif
391
	setinsalt(aa, is);
392
 
393
      }
394
 
395
      wans.answhere = aa;
396
      wans.ashwhere = a;
397
      return wans;
398
    }
399
    /***********************************************/
400
  case addptr_tag:
401
    {
402
      exp sum = son(e);
403
      where wsum;
404
      int addend;
405
      space nsp;
406
      int reg;
407
      int ind = R_NO_REG;
408
      instore is;
409
      ans asum;
410
 
411
      wsum = locate(sum, sp, sh(sum), 0);
412
      asum = wsum.answhere;
413
 
414
      /*
415
       * answer is going to be wsum displaced by integer result of evaluating
416
       * bro(sum)
417
       */
418
 
419
      switch (asum.discrim)
420
      {
421
      case notinreg:
422
	{
423
	  is = insalt(asum);
424
	  if (is.adval)
425
	  {
426
	    /* wsum is a literal address in store ... */
427
	    baseoff b;
428
 
429
	    b = is.b;
430
	    if (!IS_FIXREG(b.base))
431
	    {
432
	      /* ... it is not a base-offset, so make it one */
433
	      reg = getreg(sp.fixed);
434
	      set_ins(b, reg);
435
	      keepreg(sum, reg);
436
	      b.base = reg;
437
	      b.offset = 0;
438
	    }
439
	    nsp = guardreg(b.base, sp);
440
 
441
	    addend = reg_operand(bro(sum), nsp);
442
 
443
	    /* evaluate the displacement ... */
444
	    if (dreg == 0)
445
	      dreg = getreg(nsp.fixed);
446
	    rrr_ins(i_a, b.base, addend, dreg);
447
 
448
	    /* ... add it to the base register into new reg */
449
	    b.base = dreg;
450
	    is.b = b;
451
	    setinsalt(aa, is);
452
	    wans.answhere = aa;
453
	    wans.ashwhere = a;
454
 
455
	    /* ...and use it as base a literal base-offset result */
456
	    keepexp(e, aa);
457
	    return wans;
458
	  }
459
	  else
460
	  {
461
	    /* wsum represents an actual pointer in store... */
462
	    /* ... so load it into a good register */
463
	    ind = getreg(sp.fixed);
464
	    ld_ins(i_l, is.b, ind);
465
	  }
466
	  break;
467
	}			/* end notinreg */
468
 
469
      case inreg:
470
	{
471
	  /* wsum is already in reg */
472
	  ind = regalt(asum);
473
	  break;
474
	}
475
 
476
      default:
477
	{
478
	  fail("locate ? reg");
479
	}
480
      }				/* end case */
481
 
482
      /* register ind contains the evaluation of 1st operand of addptr */
483
      nsp = guardreg(ind, sp);
484
 
485
      if (name(bro(sum)) == env_offset_tag || name(bro(sum))==general_env_offset_tag)
486
      {
487
	is.b.base = ind;
488
	is.b.offset = frame_offset(son(bro(sum)));
489
      }
490
      else
491
      {
492
	addend = reg_operand(bro(sum), nsp);
493
 
494
	/* evaluate displacement, add it to ind in new reg */
495
	if (dreg == 0)
496
	  dreg = getreg(nsp.fixed);
497
	rrr_ins(i_a, ind, addend, dreg);
498
 
499
	is.b.base = dreg;
500
	is.b.offset = 0;
501
      }
502
 
503
      is.adval = 1;
504
      setinsalt(aa, is);
505
 
506
      wans.answhere = aa;
507
      wans.ashwhere = a;
508
      /* ... and deliver literal base_offset */
509
      keepexp(e, aa);
510
      return wans;
511
    }				/* end add_ptr */
512
 
513
  case subptr_tag:		/* this is nugatory - previous transforms make
514
				 * it into addptr or reff */
515
    {
516
      exp sum = son(e);
517
      int ind = reg_operand(sum, sp);
518
      instore isa;
519
 
520
      isa.adval = 1;
521
      sum = bro(sum);
522
      if (name(sum) == val_tag)
523
      {
524
	instore isa;
525
 
526
	isa.b.base = ind;
527
	isa.b.offset = -no(e);
528
	setinsalt(aa, isa);
529
      }
530
      else
531
      {
532
	if (dreg == 0)
533
	  dreg = getreg(sp.fixed);
534
	rrr_ins(i_s, ind, reg_operand(sum, guardreg(ind, sp)), dreg);
535
	isa.b.base = dreg;
536
	isa.b.offset = 0;
537
      }
538
      setinsalt(aa, isa);
539
      wans.answhere = aa;
540
      wans.ashwhere = a;
541
      keepexp(e, aa);
542
      return wans;
543
    }				/* end subptr */
544
 
545
  case reff_tag:
546
    {
547
      instore isa;
548
      bool bitfield;
549
 
550
      /* answer is going to be wans displaced by no(e) */
551
 
552
      wans = locate(son(e), sp, sh(son(e)), 0);
553
 
554
      bitfield = ((name(sh(e)) == ptrhd) && (al1(sh(e)) == 1));
555
 
556
      switch (wans.answhere.discrim)
557
      {
558
      case notinreg:
559
	{
560
	  isa = insalt(wans.answhere);
561
	  if (!isa.adval)
562
	  {
563
 
564
	    /*
565
	     * wans is an actual pointer  in store, so make it into a literal
566
	     * address....
567
	     */
568
	    int reg = getreg(sp.fixed);
569
 
570
	    ld_ins(i_l, isa.b, reg);
571
	    isa.b.offset = 0;
572
	    isa.b.base = reg;
573
	    isa.adval = 1;
574
	  }
575
 
576
	  /*
577
	   * ... and add appropriate displacement to give result
578
	   */
579
 
580
	  isa.b.offset += no(e) / 8;
581
	  setinsalt(wans.answhere, isa);
582
	  keepexp(e, wans.answhere);
583
	  break;
584
	}
585
      case inreg:
586
	{
587
	  /* wans is a pointer in a register */
588
	  isa.b.base = regalt(wans.answhere);
589
	  isa.adval = 1;
590
 
591
	  isa.b.offset = no(e) / 8;
592
	  setinsalt(wans.answhere, isa);
593
	  break;
594
	}
595
      default:
596
	{
597
	  fail("locate ? reg ");
598
	}
599
      }
600
      wans.ashwhere = a;
601
      return wans;
602
    }				/* end reff */
603
 
604
   case cont_tag:
605
   case contvol_tag:
606
    {
607
      exp p = son(e);
608
      ans ason;
609
      instore isa;
610
      int reg;
611
      where fc;
612
 
613
      fc = locate(p, sp, sh(e) , 0);
614
      ason = fc.answhere;
615
 
616
 
617
      /*
618
       * answer is going to be the contents of address represented by fc
619
       */
620
 
621
      switch (ason.discrim)
622
      {
623
       case notinreg:
624
	{
625
	  isa = insalt(ason);
626
	  FULLCOMMENT3("locate1 cont_tag: adval=%d bo={%d,%d}", isa.adval, isa.b.base, isa.b.offset);
627
	  if (isa.adval)
628
	  {
629
	    /* literal store address, so make it into a direct one */
630
	    isa.adval = 0;
631
	    setinsalt(aa, isa);
632
	  }
633
	  else
634
	  {
635
	    /*
636
	     * actual pointer in store
637
	     * so load it into reg and deliver direct base-offset (reg,0)
638
	     */
639
	    reg = getreg(sp.fixed);
640
	    ld_ins(i_l, isa.b, reg);
641
	    isa.b.base = reg;
642
	    isa.b.offset = 0;
643
	    setinsalt(aa, isa);
644
	    if (name(e) != contvol_tag && fc.ashwhere.ashalign != 1)
645
	      keepexp(e, aa);
646
	  }
647
	  goto breakson;
648
 
649
	}			/* end notinrg */
650
 
651
      case inreg:
652
 
653
	/*
654
	 * this one is fraught
655
	 * - it depends on only being used in lh-value positions from vars
656
	 * - take care
657
	 */
658
	{
659
	  isa.b.base = regalt(ason);
660
	  isa.b.offset = 0;
661
	  isa.adval = 1;
662
	  setinsalt(aa, isa);
663
	  /* fc is in register, so deliver literal(!? ) base-offset */
664
	  goto breakson;
665
	}
666
 
667
      case infreg:		/* ditto caveat above */
668
	{
669
	  aa = ason;
670
	  goto breakson;
671
	}
672
      default:
673
	{
674
	  fail("locate ? reg");
675
	}
676
      }
677
  breakson:
678
      wans.answhere = aa;
679
      wans.ashwhere = a;
680
      return wans;
681
 
682
    }				/* end cont */
683
 
684
  case top_tag:		/* does this ever happen ? */
685
    {
686
      setregalt(aa, 0);
687
      wans.answhere = aa;
688
      wans.ashwhere = a;
689
      return wans;
690
    }				/* end top */
691
 
692
  case field_tag:
693
    {
694
      instore isa;
695
 
696
      wans = locate(son(e), sp, sh(son(e)), 0);
697
 
698
      /*
699
       * answer is wans displace literally by no(e);
700
       * it should always be a literal store address
701
       */
702
 
703
      switch (wans.answhere.discrim)
704
      {
705
      case notinreg:
706
	{
707
	  isa = insalt(wans.answhere);
708
	  isa.b.offset += no(e) / 8;
709
	  setinsalt(wans.answhere, isa);
710
	  FULLCOMMENT1("locate field_tag: adjusting byte offset to %d", isa.b.offset);
711
	  break;
712
	}
713
       default:
714
	fail("field should be transformed");
715
      }
716
      wans.ashwhere = a;
717
      return wans;
718
    }				/* end field */
719
 
720
  default:
721
    {
722
      /*
723
       * general catch all; 
724
       * evaluate e into register and deliver it as a literal
725
       * store address
726
       */
727
      int r = reg_operand(e, sp);
728
      instore is;
729
 
730
      if (r == R_RESULT)
731
      {
732
	/* guard possible result from proc - can do better +++ */
733
	FULLCOMMENT("guarding possible result");
734
	r = getreg(sp.fixed);
735
	if (r != R_RESULT)
736
	{
737
	  mov_rr_ins(R_RESULT, r);comment("move R_RESULT to reg");
738
	}
739
      }
740
      is.b.base = r;
741
      is.b.offset = 0;
742
      is.adval = 1;
743
      setinsalt(aa, is);
744
      wans.answhere = aa;
745
      wans.ashwhere = a;
746
      return wans;
747
    }
748
  }
749
}
750
 
751
 
752
 /*
753
  * locate differs from locate1 only in that it looks to see if e has already
754
  * been evaluated and remembered by register contents tracking scheme
755
  */
756
where locate PROTO_N ((e,sp,s,dreg)) PROTO_T (exp e X space sp X shape s X int dreg)
757
{
758
  ans ak;
759
  where w;
760
 
761
  /* Check to see if e has already been evaluated and remembered */
762
  if (!IS_R_NO_REG(dreg))
763
  {
764
    /* first try for exact reg */
765
    ak = iskept_inreg(e, dreg);
766
    if (ak.discrim == inreg && (regalt(ak) == 0))
767
      ak = iskept(e);			/* no luck, try anywhere */
768
  }
769
  else
770
  {
771
    ak = iskept(e);
772
  }
773
 
774
  if (ak.discrim == inreg && (regalt(ak) == 0))	/* See if we found a register */
775
  {
776
    w = locate1(e, sp, s, dreg);/* No register found so we must use locate1 */
777
  }
778
  else
779
  {
780
    FULLCOMMENT2("locate: iskept() found value inreg=%d [reg=%d]", ak.discrim == inreg, regalt(ak));
781
    w.answhere = ak;
782
    w.ashwhere = ashof(s);
783
  }
784
  return w;
785
}