Subversion Repositories tendra.SVN

Rev

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
$Log: special.c,v $
33
 * Revision 1.1.1.1  1998/01/17  15:56:03  release
34
 * First version to be checked into rolling release.
35
 *
36
 * Revision 1.4  1996/11/25  13:43:27  wfs
37
 *    Fixed the comm_op register tracking bug in "oprators.c" and removed a
38
 * few superfluous "#if 0"s.
39
 *
40
 * Revision 1.3  1996/04/18  11:09:17  wfs
41
 * Fixed a bug in "needscan.c" where "locptr_tag" was being wrapped around
42
 * the wrong exps.
43
 *
44
 * Revision 1.2  1995/12/18  13:12:34  wfs
45
 * Put hppatrans uder cvs control. Major Changes made since last release
46
 * include:
47
 * (i) PIC code generation.
48
 * (ii) Profiling.
49
 * (iii) Dynamic Initialization.
50
 * (iv) Debugging of Exception Handling and Diagnostics.
51
 *
52
 * Revision 5.1  1995/10/20  14:12:03  wfs
53
 * gcc compilation changes.
54
 *
55
 * Revision 5.0  1995/08/25  13:42:58  wfs
56
 * Preperation for August 25 Glue release
57
 *
58
 * Revision 3.4  1995/08/25  10:32:18  wfs
59
 * Register synonyms changed. Minor change to "extj_special_ins"
60
 * required for tail_call's
61
 *
62
 * Revision 3.4  1995/08/25  10:32:18  wfs
63
 * Register synonyms changed. Minor change to "extj_special_ins"
64
 * required for tail_call's
65
 *
66
 * Revision 3.1  95/04/10  16:28:11  16:28:11  wfs (William Simmonds)
67
 * Apr95 tape version.
68
 * 
69
 * Revision 3.0  95/03/30  11:18:59  11:18:59  wfs (William Simmonds)
70
 * Mar95 tape version with CRCR95_178 bug fix.
71
 * 
72
 * Revision 2.0  95/03/15  15:28:49  15:28:49  wfs (William Simmonds)
73
 * spec 3.1 changes implemented, tests outstanding.
74
 * 
75
 * Revision 1.2  95/01/17  17:30:49  17:30:49  wfs (William Simmonds)
76
 * Changed name of an included header file.
77
 * 
78
 * Revision 1.1  95/01/11  13:18:45  13:18:45  wfs (William Simmonds)
79
 * Initial revision
80
 * 
81
*/
82
 
83
 
84
#define HPPATRANS_CODE
85
#include "config.h"
86
#include "common_types.h"
87
#include "exptypes.h"
88
#include "expmacs.h"
89
#include "codetypes.h"
90
#include "const.h"
91
#include "installtypes.h"
92
#include "exp.h"
93
#include "translat.h"
94
#include "addrtypes.h"
95
#include "shapemacs.h"
96
#include "move.h"
97
#include "regmacs.h"
98
#include "getregs.h"
99
#include "guard.h"
100
#include "codehere.h"
101
#include "inst_fmt.h"
102
#include "hppains.h"
103
#include "labels.h"
104
#include "tags.h"
105
#include "proctypes.h"
106
#include "bitsmacs.h"
107
#include "comment.h"
108
#include "machine.h"
109
#include "proc.h"
110
#include "myassert.h"
111
#include "out.h"
112
#include "frames.h"
113
#include "regexps.h"
114
#include "flags.h"
115
#include "special.h"
116
 
117
speci special_fn 
118
    PROTO_N ( ( a1, a2, s ) )
119
    PROTO_T ( exp a1 X exp a2 X shape s )
120
{				/* look for special functions */
121
  speci spr;
122
 
123
  /* +++ implement special fns handling */
124
  spr.is_special = 0;
125
  spr.special_exp = nilexp;
126
 
127
  return spr;
128
}
129
 
130
/* these are the procs I could do something about */
131
static int specno 
132
    PROTO_N ( ( n ) )
133
    PROTO_T ( char * n )
134
{
135
 
136
  /*
137
   * specno: >0 special, handle inline in specialmake 0 not special <0
138
   * special, rewrite TDF in specialneeds, no call to specialmake
139
   */
140
 
141
  FULLCOMMENT1("specno(%s)", (long) n);
142
 
143
  if (strcmp(n, "___builtin_strcpy") == 0 || strcmp(n, "___TDF_builtin_strcpy") == 0)
144
    return -1;
145
 
146
  if (strcmp(n, "___builtin_asm") == 0 || strcmp(n, "___TDF_builtin_asm") == 0)
147
    return 4;
148
 
149
  if (strcmp(n, "___builtin_alloca") == 0 || strcmp(n, "___TDF_builtin_alloca") == 0)
150
    return 5;
151
 
152
#if 0
153
  /* +++ use special maybe */
154
  if (strcmp(n, "strlen") == 0)
155
    return 2;
156
  if (strcmp(n, "strcmp") == 0)
157
    return -3;
158
#endif
159
 
160
  return 0;
161
}
162
 
163
 
164
/* what name to use with call instruction for specials */
165
char *special_call_name 
166
    PROTO_N ( ( i ) )
167
    PROTO_T ( int i )
168
{
169
  switch (i)
170
  {
171
    case -1:
172
    case 1:
173
    return ("_strcpy");
174
 
175
  case 5:
176
    return ("_alloca");
177
 
178
  default:
179
    fail("attempting external call to builtin");
180
    return "";
181
  }
182
  /* NOTREACHED */
183
}
184
 
185
 
186
 
187
static needs zeroneeds = {0, 0, 0, 0};	/* has no needs */
188
#if 0
189
static CONST needs onefixneeds = {1, 0, 0, 0};	/* one fix reg needs */
190
static CONST needs twofixneeds = {2, 0, 0, 0};	/* two fix reg needs */
191
#endif
192
 
193
 
194
/* these are the needs for their expansion */
195
needs specialneeds 
196
    PROTO_N ( ( i, application, pars ) )
197
    PROTO_T ( int i X exp application X exp pars )
198
{
199
  FULLCOMMENT1("specialneeds(%d,...)", i);
200
 
201
  switch (i)
202
  {
203
/* +++ implement special fuinction handling */
204
 
205
  case 4:
206
  {   return zeroneeds;		/* asm(string) */ }
207
 
208
  case 5:
209
    return zeroneeds;		/* alloca(n) */
210
 
211
  default:
212
    comment1("specialneeds: unimplemented builtin %d", i);
213
    fail("unimplemented builtin");
214
    return zeroneeds;
215
  }
216
  /* NOTREACHED */
217
}
218
 
219
 
220
/* could I treat this function load specially ? */
221
int specialfn 
222
    PROTO_N ( ( fn ) )
223
    PROTO_T ( exp fn )
224
{
225
  if (name(fn) == name_tag && name(son(fn)) == ident_tag &&
226
      isglob(son(fn)) && son(son(fn)) == nilexp)
227
  {
228
    char *extname = brog(son(fn))->dec_u.dec_val.dec_id;
229
 
230
    return specno(extname);
231
  }
232
  return 0;
233
}
234
 
235
/* Is a call to this function reason to prohibit optmisation of caller? */
236
int specialopt 
237
    PROTO_N ( ( fn ) )
238
    PROTO_T ( exp fn )
239
{
240
  if (name(fn) == name_tag && name(son(fn)) == ident_tag &&
241
      isglob(son(fn)) && son(son(fn)) == nilexp)
242
  {
243
    char *extname = brog(son(fn))->dec_u.dec_val.dec_id;
244
 
245
    if (extname == 0)
246
      return 0;
247
 
248
    extname += strlen(name_prefix); /* Normalise "_foo" -> "foo" */
249
 
250
    FULLCOMMENT1("specialopt: %s", (int)extname);
251
 
252
    if ((strcmp(extname, "vfork") == 0) ||
253
	(strcmp(extname, "setjmp") == 0) ||
254
	(strcmp(extname, "_setjmp") == 0) ||
255
	(strcmp(extname, "sigsetjmp") == 0)
256
	)
257
    {
258
      FULLCOMMENT("specialopt: return 1");
259
      return 1;
260
    }
261
  }
262
  return 0;
263
}
264
 
265
 
266
int specialmake 
267
    PROTO_N ( ( i, par, sp, dest, exitlab ) )
268
    PROTO_T ( int i X exp par X space sp X where dest X int exitlab )
269
{
270
  switch (i)
271
  {
272
  case 4:
273
    {
274
      /* asm(s) - simply output s */
275
      exp e;
276
      char *s;
277
 
278
      /* "par" is (eval_tag (pack_tag (string_tag no=string-table-index))) */
279
      e = son(son(par));
280
      if (name(e) != string_tag)
281
      {
282
	fail("asm argument not string");
283
	return 0;
284
      }
285
      s = nostr(e);
286
 
287
      /* asm is dangerous; as the least precaution, zap register tracking. */
288
      clear_all();
289
      fprintf(outf,"!  asm:\n" ) ;
290
      fprintf(outf,s) ;
291
      fputc('\n',outf);
292
      break;
293
    }
294
 
295
  case 5:
296
    {
297
 
298
       /* alloca(n) - grow stack frame by n bytes and then grab 
299
	  grab n bytes */
300
 
301
       int maxargbytes = max_args>>3;
302
       int dreg;
303
       ans aa;
304
 
305
       dreg = ((discrim(dest.answhere)==inreg) ? regalt(dest.answhere) : getreg(sp.fixed));
306
 
307
       if (name(par) == val_tag)
308
       {
309
	  /* n is a constant */
310
	  int n = no(par);
311
 
312
	  /* adjust n to be multiple of 64 so stack stays 64 byte aligned */
313
	  n = (n+63) & ~(63);
314
 
315
	  if (n != 0)
316
	  {
317
	     /* alloca(n) = %sp - maxargbytes */
318
	     if (SIMM14(-maxargbytes))
319
		ld_ir_ins(i_ldo,cmplt_,fs_,empty_ltrl,-maxargbytes,SP,dreg);
320
	     else
321
	     {
322
		ir_ins(i_addil,fs_L,empty_ltrl,-maxargbytes,SP);
323
		ld_ir_ins(i_ldo,cmplt_,fs_R,empty_ltrl,-maxargbytes,GR1,dreg);
324
	     }
325
	     /* grow stack frame, i.e. %sp -> %sp + n */             
326
	     if (SIMM14(n))
327
		ld_ir_ins(i_ldo,cmplt_,fs_,empty_ltrl,n,SP,SP);
328
	     else
329
	     {
330
		/* grow stack frame by more than 8192 bytes */
331
		ir_ins(i_addil,fs_L,empty_ltrl,n,SP);
332
		ld_ir_ins(i_ldo,cmplt_,fs_R,empty_ltrl,n,GR1,SP);
333
	     }
334
	  }
335
       }
336
       else
337
       {
338
	  int nreg = reg_operand(par, sp);
339
 
340
 	  /* adjust nreg so that stack stays 64 byte aligned */
341
	  ld_ir_ins(i_ldo,cmplt_,fs_,empty_ltrl,63,nreg,GR1);
342
	  riir_ins(i_dep,c_,0,31,6,GR1);
343
 
344
	  /* alloca(n) = %sp - maxargbytes */
345
	  if (SIMM14(-maxargbytes))
346
	     ld_ir_ins(i_ldo,cmplt_,fs_,empty_ltrl,-maxargbytes,SP,dreg);
347
	  else
348
	  {
349
	     ir_ins(i_addil,fs_L,empty_ltrl,-maxargbytes,SP);
350
	     ld_ir_ins(i_ldo,cmplt_,fs_R,empty_ltrl,-maxargbytes,GR1,dreg);
351
	  }
352
	  /* %sp -> %sp + nreg */
353
	  rrr_ins(i_add,c_,SP,GR1,SP);
354
       }
355
 
356
      setregalt(aa, dreg);
357
      move(aa, dest, guardreg(dreg, sp).fixed, 0);
358
      break;
359
    }
360
 
361
  default:
362
    comment1("specialmake: unimplemented builtin %d", i);
363
    fail("unimplemented builtin");
364
    return 0;
365
  }
366
 
367
  return exitlab;		/* for most cases */
368
}
369
 
370
 
371
/*
372
    TDF LIBRARY KEY
373
 
374
    A value of 0 means that the library is not present, 1 that it is, and
375
    2 that it should be generated.
376
*/
377
 
378
int library_key = 0 ;
379
 
380
 
381
/*
382
    SPECIAL ROUTINES
383
*/
384
 
385
#define sz_millicode_lib 7
386
 
387
static struct {
388
		  CONST char *proc_name ;
389
		  bool called ;
390
		  bool in_library ;
391
	      } millicode_lib [ sz_millicode_lib ] =
392
	      {
393
		  { milli_mulU, 0, 1 },	        /* $$mulU    */
394
		  { milli_mulI, 0, 1 },	        /* $$mulI    */
395
		  { milli_divU, 0, 1 },	        /* $$mulU    */
396
		  { milli_divI, 0, 1 },    	/* $$divI    */
397
		  { milli_remU, 0, 1 },	        /* $$remU    */
398
		  { milli_remI, 0, 1 },  	/* $$remI    */
399
		  { milli_dyncall, 0, 1 },	/* $$dyncall */
400
	      } ;
401
 
402
 
403
/*
404
    OUTPUT A MILLICODE LIBRARY CALL
405
*/
406
 
407
void call_millicode
408
    PROTO_N ( ( n, r, stub, restore_linkage_ptr_reg ) )
409
    PROTO_T ( int n X int r X char *stub X bool restore_linkage_ptr_reg )
410
{
411
    CONST char *nm = millicode_lib[n].proc_name ;
412
    millicode_lib[n].called = 1 ;
413
    extj_special_ins ( nm, r, stub, 0 ) ;
414
    if (PIC_code && restore_linkage_ptr_reg)
415
       rr_ins(i_copy,GR5,GR19);
416
    return ;
417
 
418
}
419
 
420
void import_millicode
421
    PROTO_Z ()
422
{
423
   int n;
424
   for(n=0; n<sz_millicode_lib; n++)
425
      if ( millicode_lib[n].called )
426
	 fprintf(outf,"\t.IMPORT\t%s,MILLICODE\n",millicode_lib[n].proc_name);
427
}