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
/* 80x86/reg_record.c */
32
 
33
/**********************************************************************
34
$Author: pwe $
35
$Date: 1998/03/15 16:00:22 $
36
$Revision: 1.3 $
37
 
38
$Log: reg_record.c,v $
39
 * Revision 1.3  1998/03/15  16:00:22  pwe
40
 * regtrack dwarf dagnostics added
41
 *
42
 * Revision 1.2  1998/02/02  11:18:25  pwe
43
 * 80x86 shape_overlap correction
44
 *
45
 * Revision 1.1.1.1  1998/01/17  15:55:52  release
46
 * First version to be checked into rolling release.
47
 *
48
 * Revision 1.4  1996/12/10  15:41:17  pwe
49
 * check condition at invalidate_dest
50
 *
51
 * Revision 1.3  1995/04/03  08:30:28  pwe
52
 * invalidate regs if overlap, eg if bitfield on byte boundaries
53
 *
54
 * Revision 1.2  1995/01/30  12:56:44  pwe
55
 * Ownership -> PWE, tidy banners
56
 *
57
 * Revision 1.1  1994/10/27  14:15:22  jmf
58
 * Initial revision
59
 *
60
 * Revision 1.1  1994/07/12  14:39:53  jmf
61
 * Initial revision
62
 *
63
**********************************************************************/
64
 
65
 
66
 
67
#include "config.h"
68
#include "common_types.h"
69
#include "operand.h"
70
#include "tags.h"
71
#include "exp.h"
72
#include "expmacs.h"
73
#include "instr386.h"
74
#include "shapemacs.h"
75
#include "codermacs.h"
76
#include "flags.h"
77
 
78
#ifdef NEWDWARF
79
#include "dw2_extra.h"
80
#endif
81
 
82
#include "reg_record.h"
83
 
84
 
85
/* This collection of routines maintains a record of what is known to
86
   to be in each register during code production
87
*/
88
 
89
/* VARIABLES */
90
/* All variables initialised */
91
 
92
reg_record crt_reg_record;
93
				/* init by cproc */
94
 
95
/* PROCEDURES */
96
 
97
/* clear out all the register records */
98
void clear_reg_record
99
    PROTO_N ( (s) )
100
    PROTO_T ( regcell * s )
101
{
102
  int   i;
103
  for (i = 0; i < no_fixed_regs; ++i) {
104
    s[i].regcell_key = 4;
105
#ifdef NEWDWARF
106
    if (dwarf2) {
107
      dw_close_regassn (i, 0);
108
      dw_close_regassn (i, 1);
109
    }
110
#endif
111
  }
112
  return;
113
}
114
 
115
/* clear out the registers not preserved
116
   over procedure calls */
117
void clear_low_reg_record
118
    PROTO_N ( (s) )
119
    PROTO_T ( regcell * s )
120
{
121
  int   i;
122
  for (i = 0; i < no_fixed_regs; ++i) {
123
    s[i].regcell_key = 4;
124
#ifdef NEWDWARF
125
    if (dwarf2) {
126
      dw_close_regassn (i, 0);
127
      dw_close_regassn (i, 1);
128
    }
129
#endif
130
  }
131
  return;
132
}
133
 
134
 
135
/* true if changing d invalidates r */
136
static  int inval
137
    PROTO_N ( (d, r) )
138
    PROTO_T ( exp d X exp r )
139
{
140
  if ((d == nilexp || name (d) == cont_tag) &&
141
      (name (r) == cont_tag || (name (r) == name_tag && isglob (son (r)))))
142
    return (1);
143
  if ((name (r) == name_tag && !isvar (son (r))) ||
144
	name (r) == cont_tag)
145
    return (eq_where (mw (d, 0), mw (r, 0)));
146
 
147
  if (name (r) == reff_tag)
148
    return (inval (d, son (r)));
149
 
150
  if (name (r) == addptr_tag) {
151
    if (name (bro (son (r))) == offset_mult_tag)
152
      return (inval (d, son (r)) || inval (d, son (bro (son (r)))));
153
    return (inval (d, son (r)) || inval (d, bro (son (r))));
154
  };
155
 
156
  if (name (r) == ident_tag)
157
    return (inval (d, son (r)) || inval (d, bro (son (r))));
158
 
159
  return (0);
160
}
161
 
162
/* true if changing d invalidates r */
163
int invalidates
164
    PROTO_N ( (d, r) )
165
    PROTO_T ( exp d X exp r )
166
{
167
  if (name (r) == cont_tag || name (r) == ass_tag)
168
    return (inval (d, son (r)));
169
  return (0);
170
}
171
 
172
/* convert register mask to register number */
173
static int  get_regno
174
    PROTO_N ( (mask) )
175
    PROTO_T ( int mask )
176
{
177
  int   m = 1;
178
  int   res;
179
  for (res = 0; res < no_fixed_regs && (mask & m) == 0; res++)
180
    m = m + m;
181
  return (res);
182
}
183
 
184
/* if there is a register holding the same
185
   value as is in w, return this register
186
   (as a where), otherwise the where_exp
187
   field of the result will be nilexp */
188
where equiv_reg
189
    PROTO_N ( (w, sz) )
190
    PROTO_T ( where w X int sz )
191
{
192
  int   i;
193
  where res;
194
  res.where_exp = nilexp;
195
 
196
  if (w.where_off != 0)
197
    return (res);
198
  for (i = 0; i < no_fixed_regs; i++) {
199
    regcell * p = &crt_reg_record[i];
200
    if ((p -> regcell_key & 1) &&
201
	(sz == 0 || sz == p -> first_size) &&
202
	eq_where_exp (p -> first_dest, w.where_exp, 1, (sz==0))) {
203
#ifdef NEWDWARF
204
      if (dwarf2)
205
	dw_used_regassn (i, 0);
206
#endif
207
      return (reg_wheres[i]);
208
    }
209
    if ((p -> regcell_key & 2) &&
210
	(sz == 0 || sz == p -> second_size) &&
211
	eq_where_exp (p -> second_dest, w.where_exp, 1, (sz==0))) {
212
#ifdef NEWDWARF
213
      if (dwarf2)
214
	dw_used_regassn (i, 1);
215
#endif
216
      return (reg_wheres[i]);
217
    }
218
  };
219
  res.where_exp = nilexp;
220
  return (res);
221
}
222
 
223
static int is_aliased
224
    PROTO_N ( (dest) )
225
    PROTO_T ( exp dest )
226
{
227
  if (dest == nilexp)
228
    return 0;
229
  if (name (dest) != cont_tag &&
230
      name (dest) != ass_tag)
231
    return (0);
232
 
233
  if (name (son (dest)) == name_tag &&
234
      isvar (son (son (dest))) &&
235
      iscaonly (son (son (dest))))
236
    return (0);
237
  return (1);
238
}
239
 
240
static  int shape_overlap
241
    PROTO_N ( (e1, e2) )
242
    PROTO_T ( exp e1 X exp e2 )
243
{
244
  shape s1 = sh (e1);
245
  shape s2 = sh (e2);
246
  if (name (s1) <= doublehd && name (s1) > tophd && name (s2) == ptrhd)
247
    return (0);
248
  if (name (s2) <= doublehd && name (s2) > tophd && name (s1) == ptrhd)
249
    return (0);
250
  return (1);
251
}
252
 
253
 
254
/* make changes to the register record
255
   needed when dest receives an unknown
256
   value */
257
void invalidate_dest
258
    PROTO_N ( (dest) )
259
    PROTO_T ( where dest )
260
{
261
  exp d = dest.where_exp;
262
  int  regmask = (d == nilexp) ? 0 : (in_reg (d) & 0x7fffffff);
263
  int  regno;
264
  where weq;
265
  int   i;
266
 
267
	/* this repeats the condition state check at start of move,
268
	   in case contop has reset it */
269
 
270
  if ((cond1_set && (eq_where (dest, cond1) ||
271
	  invalidates (dest.where_exp, cond1.where_exp))) ||
272
      (cond2_set &&
273
	(eq_where (dest, cond2a) || eq_where (dest, cond2b) ||
274
	  invalidates (dest.where_exp, cond2a.where_exp) ||
275
	  invalidates (dest.where_exp, cond2b.where_exp)))) {
276
    cond1_set = 0;
277
    cond2_set = 0;
278
  };
279
 
280
  if (is_aliased (dest.where_exp)) {
281
    for (i = 0; i < no_fixed_regs; ++i) {
282
      regcell * pr = &crt_reg_record[i];
283
      switch (pr -> regcell_key) {
284
	case 1:
285
	  if (is_aliased (pr -> first_dest) &&
286
	      shape_overlap (dest.where_exp, pr -> first_dest)) {
287
	    pr -> regcell_key = 4;
288
#ifdef NEWDWARF
289
	    if (dwarf2)
290
	      dw_close_regassn (i, 0);
291
#endif
292
	  }
293
	  break;
294
	case 2:
295
	  if (is_aliased (pr -> second_dest) &&
296
	      shape_overlap (dest.where_exp, pr -> second_dest)) {
297
	    pr -> regcell_key = 4;
298
#ifdef NEWDWARF
299
	    if (dwarf2)
300
	      dw_close_regassn (i, 1);
301
#endif
302
	  }
303
	  break;
304
	case 3:
305
	  if (is_aliased (pr -> first_dest) &&
306
	      shape_overlap (dest.where_exp, pr -> first_dest)) {
307
	    pr -> regcell_key &= 2;
308
#ifdef NEWDWARF
309
	    if (dwarf2)
310
	      dw_close_regassn (i, 0);
311
#endif
312
	  }
313
	  if (is_aliased (pr -> second_dest) &&
314
	      shape_overlap (dest.where_exp, pr -> second_dest)) {
315
	    pr -> regcell_key &= 1;
316
#ifdef NEWDWARF
317
	    if (dwarf2)
318
	      dw_close_regassn (i, 1);
319
#endif
320
	  }
321
	  if (pr -> regcell_key == 0)
322
	    pr -> regcell_key = 4;
323
	default: ;
324
      };
325
    };
326
  };
327
 
328
  if (regmask) {
329
    regno = get_regno (regmask);
330
    if (regno < no_fixed_regs)
331
      crt_reg_record[regno].regcell_key = 4;
332
  };
333
 
334
  if (regmask || d == nilexp) {
335
    for (i = 0; i < no_fixed_regs; ++i) {
336
      regcell * pr = &crt_reg_record[i];
337
      switch (pr -> regcell_key) {
338
	case 1:
339
	  if (invalidates (d, pr -> first_dest)) {
340
	    pr -> regcell_key = 4;
341
#ifdef NEWDWARF
342
	    if (dwarf2)
343
	      dw_close_regassn (i, 0);
344
#endif
345
	  }
346
	  break;
347
	case 2:
348
	  if (invalidates (d, pr -> second_dest)) {
349
	    pr -> regcell_key = 4;
350
#ifdef NEWDWARF
351
	    if (dwarf2)
352
	      dw_close_regassn (i, 1);
353
#endif
354
	  }
355
	  break;
356
	case 3:
357
	  if (invalidates (d, pr -> first_dest)) {
358
	    pr -> regcell_key &= 2;
359
#ifdef NEWDWARF
360
	    if (dwarf2)
361
	      dw_close_regassn (i, 0);
362
#endif
363
	  }
364
	  if (invalidates (d, pr -> second_dest)) {
365
	    pr -> regcell_key &= 1;
366
#ifdef NEWDWARF
367
	    if (dwarf2)
368
	      dw_close_regassn (i, 1);
369
#endif
370
	  }
371
	  if (pr -> regcell_key == 0)
372
	    pr -> regcell_key = 4;
373
	default: ;
374
      };
375
    };
376
    return;
377
  };
378
#ifdef NEWDWARF
379
  dw_ignore_used_regassn = 1;
380
#endif
381
  while (1) {
382
    weq = equiv_reg (dest, 0);
383
    if (weq.where_exp == nilexp)
384
      break;
385
    regmask = (in_reg (weq.where_exp) & 0x7fffffff);
386
    regno = get_regno (regmask);
387
    if (regno < no_fixed_regs)
388
      crt_reg_record[regno].regcell_key = 4;
389
  };
390
#ifdef NEWDWARF
391
  dw_ignore_used_regassn = 0;
392
#endif
393
  return;
394
}
395
 
396
/* from is being moved to to. Make changes
397
   to the register records accordingly */
398
void move_reg
399
    PROTO_N ( (from, to, sha) )
400
    PROTO_T ( where from X where to X shape sha )
401
{
402
  int  regmask_to = in_reg (to.where_exp);
403
  int  regmask_from = in_reg (from.where_exp);
404
  int sz = shape_size(sha);
405
  if (name(sha) == shrealhd)
406
    return;
407
  if (regmask_from != 0 && regmask_to != 0)
408
    return;
409
  if ((regmask_from & (int)0x80000000) || (regmask_to & (int)0x80000000))
410
    return;
411
  if (from.where_off != 0 || to.where_off != 0)
412
    return;
413
  if (regmask_to && invalidates (to.where_exp, from.where_exp))
414
    return;
415
  if (regmask_to && regmask_to < 64) {
416
    int   regno_to = get_regno (regmask_to);
417
    regcell * p = &crt_reg_record[regno_to];
418
    switch (p -> regcell_key) {
419
      case 1:
420
	{
421
	  p -> regcell_key = 3;
422
	  p -> second_dest = from.where_exp;
423
	  p -> second_size = sz;
424
#ifdef NEWDWARF
425
	  if (dwarf2)
426
	    dw_init_regassn (regno_to, 1);
427
#endif
428
	  break;
429
	};
430
      case 2:
431
	{
432
	  p -> regcell_key = 3;
433
	  p -> first_dest = from.where_exp;
434
	  p -> first_size = sz;
435
#ifdef NEWDWARF
436
	  if (dwarf2)
437
	    dw_init_regassn (regno_to, 0);
438
#endif
439
	  break;
440
	};
441
      case 3:
442
	break;
443
      default:
444
	{
445
	  p -> regcell_key = 1;
446
	  p -> first_dest = from.where_exp;
447
	  p -> first_size = sz;
448
#ifdef NEWDWARF
449
	  if (dwarf2)
450
	    dw_init_regassn (regno_to, 0);
451
#endif
452
	  break;
453
	};
454
    };
455
  };
456
  if (regmask_from && regmask_from < 64) {
457
    int   regno_from = get_regno (regmask_from);
458
    regcell * p = &crt_reg_record[regno_from];
459
    switch (p -> regcell_key) {
460
      case 1:
461
	{
462
	  p -> regcell_key = 3;
463
	  p -> second_dest = to.where_exp;
464
	  p -> second_size = sz;
465
#ifdef NEWDWARF
466
	  if (dwarf2)
467
	    dw_init_regassn (regno_from, 1);
468
#endif
469
	  break;
470
	};
471
      case 2:
472
	{
473
	  p -> regcell_key = 3;
474
	  p -> first_dest = to.where_exp;
475
	  p -> first_size = sz;
476
#ifdef NEWDWARF
477
	  if (dwarf2)
478
	    dw_init_regassn (regno_from, 0);
479
#endif
480
	  break;
481
	};
482
      case 3:
483
	break;
484
      default:
485
	{
486
	  p -> regcell_key = 1;
487
	  p -> first_dest = to.where_exp;
488
	  p -> first_size = sz;
489
#ifdef NEWDWARF
490
	  if (dwarf2)
491
	    dw_init_regassn (regno_from, 0);
492
#endif
493
	  break;
494
	};
495
    };
496
  };
497
}