Subversion Repositories tendra.SVN

Rev

Rev 5 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 5 Rev 6
Line -... Line 1...
-
 
1
/*
-
 
2
 * Copyright (c) 2002-2005 The TenDRA Project <http://www.tendra.org/>.
-
 
3
 * All rights reserved.
-
 
4
 *
-
 
5
 * Redistribution and use in source and binary forms, with or without
-
 
6
 * modification, are permitted provided that the following conditions are met:
-
 
7
 *
-
 
8
 * 1. Redistributions of source code must retain the above copyright notice,
-
 
9
 *    this list of conditions and the following disclaimer.
-
 
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
-
 
11
 *    this list of conditions and the following disclaimer in the documentation
-
 
12
 *    and/or other materials provided with the distribution.
-
 
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
-
 
14
 *    may be used to endorse or promote products derived from this software
-
 
15
 *    without specific, prior written permission.
-
 
16
 *
-
 
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
-
 
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-
 
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-
 
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
-
 
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-
 
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-
 
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-
 
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-
 
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-
 
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-
 
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
 
28
 *
-
 
29
 * $Id$
-
 
30
 */
1
/*
31
/*
2
    Copyright (c) 1993 Open Software Foundation, Inc.
32
    Copyright (c) 1993 Open Software Foundation, Inc.
3
 
33
 
4
 
34
 
5
    All Rights Reserved
35
    All Rights Reserved
Line 24... Line 54...
24
    WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
54
    WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25
*/
55
*/
26
 
56
 
27
/*
57
/*
28
    		 Crown Copyright (c) 1997
58
    		 Crown Copyright (c) 1997
29
    
59
 
30
    This TenDRA(r) Computer Program is subject to Copyright
60
    This TenDRA(r) Computer Program is subject to Copyright
31
    owned by the United Kingdom Secretary of State for Defence
61
    owned by the United Kingdom Secretary of State for Defence
32
    acting through the Defence Evaluation and Research Agency
62
    acting through the Defence Evaluation and Research Agency
33
    (DERA).  It is made available to Recipients with a
63
    (DERA).  It is made available to Recipients with a
34
    royalty-free licence for its use, reproduction, transfer
64
    royalty-free licence for its use, reproduction, transfer
35
    to other parties and amendment for any purpose not excluding
65
    to other parties and amendment for any purpose not excluding
36
    product development provided that any such use et cetera
66
    product development provided that any such use et cetera
37
    shall be deemed to be acceptance of the following conditions:-
67
    shall be deemed to be acceptance of the following conditions:-
38
    
68
 
39
        (1) Its Recipients shall ensure that this Notice is
69
        (1) Its Recipients shall ensure that this Notice is
40
        reproduced upon any copies or amended versions of it;
70
        reproduced upon any copies or amended versions of it;
41
    
71
 
42
        (2) Any amended version of it shall be clearly marked to
72
        (2) Any amended version of it shall be clearly marked to
43
        show both the nature of and the organisation responsible
73
        show both the nature of and the organisation responsible
44
        for the relevant amendment or amendments;
74
        for the relevant amendment or amendments;
45
    
75
 
46
        (3) Its onward transfer from a recipient to another
76
        (3) Its onward transfer from a recipient to another
47
        party shall be deemed to be that party's acceptance of
77
        party shall be deemed to be that party's acceptance of
48
        these conditions;
78
        these conditions;
49
    
79
 
50
        (4) DERA gives no warranty or assurance as to its
80
        (4) DERA gives no warranty or assurance as to its
51
        quality or suitability for any purpose and DERA accepts
81
        quality or suitability for any purpose and DERA accepts
52
        no liability whatsoever in relation to any use to which
82
        no liability whatsoever in relation to any use to which
53
        it may be put.
83
        it may be put.
54
*/
84
*/
Line 91... Line 121...
91
#include "mem_copy.h"
121
#include "mem_copy.h"
92
#include "xalloc.h"
122
#include "xalloc.h"
93
#include "parameter.h"
123
#include "parameter.h"
94
#include "error.h"
124
#include "error.h"
95
#include "dynamic_init.h"
125
#include "dynamic_init.h"
96
space do_callers PROTO_S ((int,exp,space));
126
space do_callers(int,exp,space);
97
void do_function_call PROTO_S ((exp,space));
127
void do_function_call(exp,space);
98
void do_general_function_call PROTO_S ((exp,space));
128
void do_general_function_call(exp,space);
99
makeans move_result_to_dest PROTO_S ((exp,space,where,int));
129
makeans move_result_to_dest(exp,space,where,int);
100
void restore_callers PROTO_S ((int));
130
void restore_callers(int);
101
void restore_callees PROTO_S ((void));
131
void restore_callees(void);
102
static exp find_ote PROTO_S ((exp,int));
132
static exp find_ote(exp,int);
103
 
133
 
104
typedef struct postl_ {exp pl; struct postl_ * outer; } postl_chain;
134
typedef struct postl_ {exp pl; struct postl_ * outer; } postl_chain;
105
static postl_chain * old_pls;
135
static postl_chain * old_pls;
106
 
136
 
107
void update_plc PROTO_N ((ch, ma))
-
 
108
    PROTO_T (postl_chain * ch X int ma)
137
void update_plc(postl_chain * ch, int ma)
109
{	
138
{
110
	while (ch != (postl_chain*)0) {
139
	while (ch != (postl_chain*)0) {
111
	  exp pl= ch->pl;
140
	  exp pl= ch->pl;
112
	  while (name(pl)==ident_tag && name(son(pl))==caller_name_tag) {
141
	  while (name(pl) ==ident_tag && name(son(pl)) ==caller_name_tag) {
113
		no(pl)+= (ma<<6);
142
		no(pl) += (ma<<6);
114
		pl = bro(son(pl));
143
		pl = bro(son(pl));
115
	  }
144
	  }
116
	  ch = ch->outer;
145
	  ch = ch->outer;
117
	}
146
	}
118
}
147
}
119
/*
148
/*
120
 * Temp location in stack frame callee param save area that can be used
149
 * Temp location in stack frame callee param save area that can be used
121
 * in short instruction sequence, such as move between float and fixed regs.
150
 * in short instruction sequence, such as move between float and fixed regs.
122
 * Initialised at procedure prelude, for that procedure.
151
 * Initialised at procedure prelude, for that procedure.
123
 */
152
 */
124
baseoff mem_temp PROTO_N ((byte_offset)) PROTO_T (int byte_offset)
153
baseoff mem_temp(int byte_offset)
125
{
154
{
126
  baseoff b;
155
  baseoff b;
127
 
156
 
128
  b.base = R_SP;
157
  b.base = R_SP;
129
  b.offset = -8;
158
  b.offset = -8;
130
  
159
 
131
  /*
160
  /*
132
   * Only 2 words of temp allocated
161
   * Only 2 words of temp allocated
133
   */
162
   */
134
  ASSERT(byte_offset >= 0 && byte_offset < 8);
163
  ASSERT(byte_offset >= 0 && byte_offset < 8);
135
  b.offset += byte_offset;
164
  b.offset += byte_offset;
Line 139... Line 168...
139
 
168
 
140
 
169
 
141
/*
170
/*
142
 * Implement -p option, by calling mcount with static location address as param.
171
 * Implement -p option, by calling mcount with static location address as param.
143
 */
172
 */
144
static void call_mcount PROTO_Z ()
173
static void call_mcount(void)
145
{
174
{
146
  static int p_lab = 0;
175
  static int p_lab = 0;
147
 
176
 
148
  p_lab++;
177
  p_lab++;
149
 
178
 
Line 167... Line 196...
167
  clear_all();
196
  clear_all();
168
}
197
}
169
 
198
 
170
 
199
 
171
/* is param ident e the last param, or for a proc no params? */
200
/* is param ident e the last param, or for a proc no params? */
172
bool last_caller_param PROTO_N ((e)) PROTO_T (exp e)
201
bool last_caller_param(exp e)
173
{
202
{
174
  exp next;
203
  exp next;
175
 
204
 
176
  ASSERT(IS_A_PROC(e) || (name(e) == ident_tag && isparam(e)));
205
  ASSERT(IS_A_PROC(e) || (name(e) == ident_tag && isparam(e)));
177
  /* Look at the body of the ident for another param */
206
  /* Look at the body of the ident for another param */
178
  if (IS_A_PROC(e))
207
  if (IS_A_PROC(e))
179
  {
208
  {
180
    next = son(e);
209
    next = son(e);
181
  }
210
  }
182
  else
211
  else
183
  {
212
  {
184
    next = bro(son(e));
213
    next = bro(son(e));
185
  }
214
  }
186
 
215
 
187
  /* Skip diagnose_tag which may be before next param */
216
  /* Skip diagnose_tag which may be before next param */
188
  while(name(next) == diagnose_tag)
217
  while (name(next) == diagnose_tag)
189
  {
218
  {
190
    next = son(next);
219
    next = son(next);
191
  }
220
  }
192
  
221
 
193
  if (name(next) == ident_tag 
222
  if (name(next) == ident_tag
194
      && isparam(next) 
223
      && isparam(next)
195
      && name(son(next))!=formal_callee_tag)
224
      && name(son(next))!=formal_callee_tag)
196
  {
225
  {
197
    return 0;			/* another caller param */
226
    return 0;			/* another caller param */
198
  }
227
  }
199
  else
228
  else
Line 210... Line 239...
210
 * These functions are called by make_code(), the code selection switch.
239
 * These functions are called by make_code(), the code selection switch.
211
 */
240
 */
212
 
241
 
213
 
242
 
214
/* procedure definition */
243
/* procedure definition */
215
void make_proc_tag_code PROTO_N ((e,sp)) PROTO_T (exp e X space sp)
244
void make_proc_tag_code(exp e, space sp)
216
{
245
{
217
  procrec *pr = &procrecs[no(e)];
246
  procrec *pr = &procrecs[no(e)];
218
  long pprops = pr->needsproc.propsneeds;
247
  long pprops = pr->needsproc.propsneeds;
219
 
248
 
220
  clear_all();
249
  clear_all();
221
  
250
 
222
  suspected_varargs = 0;
251
  suspected_varargs = 0;
223
  
252
 
224
  old_pls = (postl_chain *)0;
253
  old_pls = (postl_chain *)0;
225
  
254
 
226
  p_current = e;
255
  p_current = e;
227
  
256
 
228
  initialise_procedure(pr);
257
  initialise_procedure(pr);
229
 
258
 
230
  generate_procedure_prologue();
259
  generate_procedure_prologue();
231
  
260
 
232
  output_parameters(e);
261
  output_parameters(e);
233
#ifdef DO_DYNAMIC_INITIALISATION
262
#ifdef DO_DYNAMIC_INITIALISATION
234
  if (proc_is_main(e))
263
  if (proc_is_main(e))
235
  {
264
  {
236
    call__main();
265
    call__main();
237
  }
266
  }
238
#endif
267
#endif
239
  /*
268
  /*
240
   * Profiling info
269
   * Profiling info
241
   */
270
   */
242
  if (do_profile && !p_leaf)
271
  if (do_profile && !p_leaf)
243
  {/* In the event of the procedure having no parameters, mcount would not
272
  {/* In the event of the procedure having no parameters, mcount would not
244
      have been called,so we call it here */
273
      have been called,so we call it here */
245
    call_mcount();
274
    call_mcount();
246
  }
275
  }
247
  
276
 
248
  /*
277
  /*
249
   * Setup p_result
278
   * Setup p_result
250
   */
279
   */
251
  if ((pprops & realresult_bit) != 0)	/* proc has real result */
280
  if ((pprops & realresult_bit) != 0)	/* proc has real result */
252
  {
281
  {
253
    freg frg;
282
    freg frg;
254
    
283
 
255
    frg.fr = FR_RESULT;
284
    frg.fr = FR_RESULT;
256
    frg.dble = (pprops & longrealresult_bit) ? 1 : 0;
285
    frg.dble = (pprops & longrealresult_bit)? 1 : 0;
257
    setfregalt(p_result, frg);
286
    setfregalt(p_result, frg);
258
  }
287
  }
259
  else if ((pprops & has_result_bit) != 0)
288
  else if ((pprops & has_result_bit)!= 0)
260
  {
289
  {
261
    setregalt(p_result, R_RESULT);
290
    setregalt(p_result, R_RESULT);
262
  }
291
  }
263
  else
292
  else
264
  {
293
  {
265
    setregalt(p_result, R_0);		/* no result */
294
    setregalt(p_result, R_0);		/* no result */
266
  }
295
  }
267
  p_return_label = 0;
296
  p_return_label = 0;
268
 
297
 
269
  init_proc_errors(e);
298
  init_proc_errors(e);
270
  
299
 
271
  make_code(son(e), sp, nowhere, 0);
300
  make_code(son(e), sp, nowhere, 0);
272
 
301
 
273
  output_error_labels();
302
  output_error_labels();
274
  
303
 
275
  /* epilogue created at make_res_tag_code */
304
  /* epilogue created at make_res_tag_code */
276
  return;
305
  return;
277
}
306
}
278
 
307
 
279
 
308
 
280
/* ident/param definition within proc */
309
/* ident/param definition within proc */
281
makeans make_ident_tag_code PROTO_N ((e,sp,dest,exitlab)) PROTO_T (exp e X space sp X where dest X int exitlab)
310
makeans make_ident_tag_code(exp e, space sp, where dest, int exitlab)
282
{
311
{
283
  exp init_exp = son(e);			/* initialisation exp */
312
  exp init_exp = son(e);			/* initialisation exp */
284
  int ident_size = shape_size(sh(init_exp));
313
  int ident_size = shape_size(sh(init_exp));
285
  int ident_align = shape_align(sh(init_exp));
314
  int ident_align = shape_align(sh(init_exp));
286
  int ident_no = no(e);
315
  int ident_no = no(e);
287
  where placew;
316
  where placew;
288
  int r = R_NO_REG;
317
  int r = R_NO_REG;
289
  bool remember = 0;
318
  bool remember = 0;
290
  makeans mka;
319
  makeans mka;
291
  
320
 
292
  if (props(e) & defer_bit)
321
  if (props(e) & defer_bit)
293
  {
322
  {
294
    return make_code(bro(init_exp), sp, dest, exitlab);
323
    return make_code(bro(init_exp), sp, dest, exitlab);
295
  }
324
  }
296
 
325
 
297
  /**************Is it an identification of a caller in a postlude?***********/
326
  /**************Is it an identification of a caller in a postlude?***********/
298
  if ( name(init_exp)==caller_name_tag )
327
  if (name(init_exp) ==caller_name_tag)
299
  {
328
  {
300
    exp ote = find_ote(e,no(init_exp));
329
    exp ote = find_ote(e,no(init_exp));
301
    long caller_disp = no(ote)>>3;
330
    long caller_disp = no(ote) >>3;
302
    
331
 
303
    no(e) = ENCODE_FOR_BOFF(caller_disp , OUTPUT_CALLER_PARAMETER );
332
    no(e) = ENCODE_FOR_BOFF(caller_disp , OUTPUT_CALLER_PARAMETER);
304
    set_coded_caller(ote); /* Used in apply_general*/
333
    set_coded_caller(ote); /* Used in apply_general*/
305
 
334
 
306
    ASSERT((props(e) & inanyreg )==0);
335
    ASSERT((props(e) & inanyreg) ==0);
307
    /* Should not have been allocated a register by regalloc or scan */
336
    /* Should not have been allocated a register by regalloc or scan */
308
    placew = nowhere;
337
    placew = nowhere;
309
  }
338
  }
310
  /**************Is it in a fixed point register?***************/
339
  /**************Is it in a fixed point register?***************/
311
  else if (props(e)&inreg_bits)
340
  else if (props(e) &inreg_bits)
312
  {
341
  {
313
    if (ident_no==R_NO_REG)	/* Need to allocate a t-reg */
342
    if (ident_no==R_NO_REG)	/* Need to allocate a t-reg */
314
    {
343
    {
315
      int s = sp.fixed;
344
      int s = sp.fixed;
316
 
345
 
Line 332... Line 361...
332
  {
361
  {
333
    freg frg;
362
    freg frg;
334
    if (ident_no==FR_NO_REG)	/* Need to allocate a t-reg */
363
    if (ident_no==FR_NO_REG)	/* Need to allocate a t-reg */
335
    {
364
    {
336
      int s = sp.flt;
365
      int s = sp.flt;
337
      
366
 
338
      if (props(e) & notparreg)
367
      if (props(e) & notparreg)
339
      {
368
      {
340
	s |= PARAM_FLT_TREGS;
369
	s |= PARAM_FLT_TREGS;
341
      }
370
      }
342
      if (props(e) & notresreg)
371
      if (props(e) & notresreg)
Line 352... Line 381...
352
  }
381
  }
353
  /**************Is it a parameter on the stack?***************/
382
  /**************Is it a parameter on the stack?***************/
354
  else if (isparam(e))
383
  else if (isparam(e))
355
  {
384
  {
356
    instore is;
385
    instore is;
357
    
386
 
358
    if(name(init_exp) != formal_callee_tag)
387
    if (name(init_exp)!= formal_callee_tag)
359
    {
388
    {
360
      /* Caller parameter living on stack */
389
      /* Caller parameter living on stack */
361
      long caller_offset = no(init_exp)>>3;
390
      long caller_offset = no(init_exp) >>3;
362
      no(e) = ENCODE_FOR_BOFF( caller_offset , INPUT_CALLER_PARAMETER ); 
391
      no(e) = ENCODE_FOR_BOFF(caller_offset , INPUT_CALLER_PARAMETER);
363
      if (isvarargparam(e))
392
      if (isvarargparam(e))
364
      {
393
      {
365
	if (ident_size == 0)
394
	if (ident_size == 0)
366
	{
395
	{
367
	  /* void from <varargs.h> */
396
	  /* void from <varargs.h> */
368
	  ident_size = 32;
397
	  ident_size = 32;
369
	  ident_align = 32;
398
	  ident_align = 32;
370
	}
399
	}
371
      }
400
      }
372
    }
401
    }
373
    else 
402
    else
374
    {
403
    {
375
      /* Callee parameter living on stack */
404
      /* Callee parameter living on stack */
376
      long callee_offset = no(init_exp)>>3;
405
      long callee_offset = no(init_exp) >>3;
377
      no(e) = ENCODE_FOR_BOFF( callee_offset , INPUT_CALLEE_PARAMETER );
406
      no(e) = ENCODE_FOR_BOFF(callee_offset , INPUT_CALLEE_PARAMETER);
378
    }
407
    }
379
    is.b = boff(e);
408
    is.b = boff(e);
380
    is.adval = 1;
409
    is.adval = 1;
381
    setinsalt(placew.answhere, is);
410
    setinsalt(placew.answhere, is);
382
  }
411
  }
383
  /**************Allocate on the stack?***************/
412
  /**************Allocate on the stack?***************/
384
  else
413
  else
385
  {
414
  {
386
    /* It is a local living on the stack */
415
    /* It is a local living on the stack */
387
    instore is;
416
    instore is;
388
    
417
 
389
    is.b = boff(e);
418
    is.b = boff(e);
390
    is.adval = 1;
419
    is.adval = 1;
391
    setinsalt(placew.answhere, is);
420
    setinsalt(placew.answhere, is);
392
    remember = 1;
421
    remember = 1;
393
  }
422
  }
394
  
423
 
395
  placew.ashwhere.ashsize  = ident_size;
424
  placew.ashwhere.ashsize  = ident_size;
396
  placew.ashwhere.ashalign = ident_align;
425
  placew.ashwhere.ashalign = ident_align;
397
 
426
 
398
  if( isparam(e))
427
  if (isparam(e))
399
  {
428
  {
400
    if(name(init_exp)==formal_callee_tag && (props(e) & inanyreg) )
429
    if (name(init_exp) ==formal_callee_tag && (props(e) & inanyreg))
401
    {
430
    {
402
      instore is;
431
      instore is;
403
      ans aa;
432
      ans aa;
404
      ASSERT(p_has_fp);
433
      ASSERT(p_has_fp);
405
      is.b.base = R_FP;
434
      is.b.base = R_FP;
406
      is.b.offset = EXTRA_CALLEE_BYTES + (no(init_exp)>>3);
435
      is.b.offset = EXTRA_CALLEE_BYTES + (no(init_exp) >>3);
407
      is.adval = 0;
436
      is.adval = 0;
408
      setinsalt(aa,is);
437
      setinsalt(aa,is);
409
      move(aa,placew,sp.fixed,is_signed(sh(init_exp)));
438
      move(aa,placew,sp.fixed,is_signed(sh(init_exp)));
410
    }
439
    }
411
  }
440
  }
412
  else
441
  else
413
  {
442
  {
414
    r = code_here(init_exp, sp, placew);
443
    r = code_here(init_exp, sp, placew);
415
  }
444
  }
416
  
445
 
417
  COMMENT1("make_ident_tag_code end_init: no(e)=%d", no(e));
446
  COMMENT1("make_ident_tag_code end_init: no(e) =%d", no(e));
418
  
447
 
419
  if (remember && r != R_NO_REG && pt(e) != nilexp 
448
  if (remember && r != R_NO_REG && pt(e)!= nilexp
420
      && keep_eq_size(sh(init_exp), sh(pt(e))))
449
      && keep_eq_size(sh(init_exp), sh(pt(e))))
421
  {
450
  {
422
    /* It was temporarily in a register, track it to optimise future access */
451
    /* It was temporarily in a register, track it to optimise future access */
423
    if (isvar(e))
452
    if (isvar(e))
424
    {
453
    {
425
      keepcont(pt(e), r);
454
      keepcont(pt(e), r);
426
    }
455
    }
427
    else
456
    else
428
    {
457
    {
429
      keepreg(pt(e), r);
458
      keepreg(pt(e), r);
430
    }
459
    }
431
  }
460
  }
432
 
461
 
433
  /* and evaluate the body of the declaration */
462
  /* and evaluate the body of the declaration */
434
  mka = make_code(bro(init_exp), guard(placew, sp), dest, exitlab);
463
  mka = make_code(bro(init_exp), guard(placew, sp), dest, exitlab);
435
 
464
 
436
  COMMENT1("make_ident_tag_code end_range: no(e)=%d", no(e));
465
  COMMENT1("make_ident_tag_code end_range: no(e) =%d", no(e));
437
 
466
 
438
  return mka;
467
  return mka;
439
}
468
}
440
 
469
 
441
 
470
 
442
/* 
471
/*
443
 * Delivers the procedure result
472
 * Delivers the procedure result
444
 * with either a normal or an untidy return
473
 * with either a normal or an untidy return
445
 */
474
 */
446
void make_res_tag_code PROTO_N ((e,sp)) PROTO_T (exp e X space sp)
475
void make_res_tag_code(exp e, space sp)
447
{
476
{
448
  where w;
477
  where w;
449
  bool untidy = (name(e)==untidy_return_tag) ? 1 : 0 ;
478
  bool untidy = (name(e) ==untidy_return_tag)? 1 : 0;
450
  
479
 
451
  w.answhere = p_result;
480
  w.answhere = p_result;
452
  w.ashwhere = ashof(sh(son(e)));
481
  w.ashwhere = ashof(sh(son(e)));
453
  
482
 
454
  code_here(son(e), sp, w);	/* Evaluation of result value */
483
  code_here(son(e), sp, w);	/* Evaluation of result value */
455
  
484
 
456
  
485
 
457
  if ( p_leaf
486
  if (p_leaf
458
      && p_sreg_first_save == R_NO_REG
487
      && p_sreg_first_save == R_NO_REG
459
      && p_sfreg_first_save == FR_NO_REG)
488
      && p_sfreg_first_save == FR_NO_REG)
460
  {
489
  {
461
    /* Short return sequence so generate everytime */
490
    /* Short return sequence so generate everytime */
462
    if(untidy)
491
    if (untidy)
463
    {
492
    {
464
      generate_untidy_procedure_epilogue();
493
      generate_untidy_procedure_epilogue();
465
    }
494
    }
466
    else
495
    else
467
    {
496
    {
Line 469... Line 498...
469
    }
498
    }
470
  }
499
  }
471
  else
500
  else
472
  {
501
  {
473
    /* jump to the end of proc for long return sequence */
502
    /* jump to the end of proc for long return sequence */
474
    if(p_return_label == 0)
503
    if (p_return_label == 0)
475
    {
504
    {
476
      /* For diagnostics always produce return code */
505
      /* For diagnostics always produce return code */
477
      if (p_no_of_returns>1 && !diagnose)
506
      if (p_no_of_returns>1 && !diagnose)
478
      {
507
      {
479
	p_return_label = new_label();
508
	p_return_label = new_label();
480
	set_label(p_return_label);
509
	set_label(p_return_label);
481
      }
510
      }
482
      if(untidy)
511
      if (untidy)
483
      {
512
      {
484
	generate_untidy_procedure_epilogue();
513
	generate_untidy_procedure_epilogue();
485
      }
514
      }
486
      else
515
      else
487
      {
516
      {
Line 492... Line 521...
492
    {
521
    {
493
      /* jump to the return sequence at first return */
522
      /* jump to the return sequence at first return */
494
      uncond_ins(i_b, p_return_label);
523
      uncond_ins(i_b, p_return_label);
495
    }
524
    }
496
  }
525
  }
497
    
526
 
498
  clear_all();			
527
  clear_all();
499
  return;
528
  return;
500
}
529
}
501
 
530
 
502
 
531
 
503
/* procedure call */
532
/* procedure call */
504
makeans make_apply_tag_code PROTO_N ((e,sp,dest,exitlab)) PROTO_T (exp e X space sp X where dest X int exitlab)
533
makeans make_apply_tag_code(exp e, space sp, where dest, int exitlab)
505
{
534
{
506
  exp fn = son(e);		/* Function */
535
  exp fn = son(e);		/* Function */
507
  exp par = bro(fn);		/* Parameters list */
536
  exp par = bro(fn);		/* Parameters list */
508
  space nsp;
537
  space nsp;
509
  nsp=sp;
538
  nsp=sp;
510
  
539
 
511
  /* Structure results are assumed to be transformed */
540
  /* Structure results are assumed to be transformed */
512
  ASSERT(redo_structfns);
541
  ASSERT(redo_structfns);
513
  ASSERT(reg_result(sh(e)));
542
  ASSERT(reg_result(sh(e)));
514
  
543
 
515
  /* Callers evaluated to usual place relative to sp */
544
  /* Callers evaluated to usual place relative to sp */
516
  if(!last(fn)){nsp = do_callers(PROC_PARAM_REGS,par,nsp);}
545
  if (!last(fn)) {nsp = do_callers(PROC_PARAM_REGS,par,nsp);}
517
  
546
 
518
  /* Function call */
547
  /* Function call */
519
  (void) do_function_call(fn,nsp);
548
 (void) do_function_call(fn,nsp);
520
  
549
 
521
  /* Clear all treg associations */
550
  /* Clear all treg associations */
522
  clear_all();
551
  clear_all();
523
  
552
 
524
  /* Move the result to correct destination */
553
  /* Move the result to correct destination */
525
  return move_result_to_dest(e,sp,dest,exitlab);
554
  return move_result_to_dest(e,sp,dest,exitlab);
526
}
555
}
527
 
556
 
528
makeans make_apply_general_tag_code PROTO_N ((e,sp,dest,exitlab)) PROTO_T (exp e X space sp X where dest X int exitlab )
557
makeans make_apply_general_tag_code(exp e, space sp, where dest, int exitlab)
529
{
558
{
530
  exp fn = son(e);
559
  exp fn = son(e);
531
  exp cers = bro(fn);
560
  exp cers = bro(fn);
532
  exp cees = bro(cers);
561
  exp cees = bro(cers);
533
  exp pl = bro(cees);
562
  exp pl = bro(cees);
Line 535... Line 564...
535
  makeans mka;
564
  makeans mka;
536
  nsp = sp;
565
  nsp = sp;
537
 
566
 
538
  /* Callers evaluated to usual place relative to sp */
567
  /* Callers evaluated to usual place relative to sp */
539
  /* Any params with caller_tag are marked with offset */
568
  /* Any params with caller_tag are marked with offset */
540
  if(no(cers) !=0)  { nsp = do_callers(GENERAL_PROC_PARAM_REGS,son(cers),sp);}
569
  if (no(cers)!=0) { nsp = do_callers(GENERAL_PROC_PARAM_REGS,son(cers),sp);}
541
 
570
 
542
  /* Callees */
571
  /* Callees */
543
  (void)make_code(cees,nsp,nowhere,0);
572
 (void)make_code(cees,nsp,nowhere,0);
544
 
573
 
545
  /* Function */
574
  /* Function */
546
  (void)do_general_function_call(fn,nsp);
575
 (void) do_general_function_call(fn,nsp);
547
 
576
 
548
  
577
 
549
  /* This code works on the assumption that the stack pointer is returned to 
578
  /* This code works on the assumption that the stack pointer is returned to
550
     where it was initially 
579
     where it was initially
551
     i.e no untidy returns from the general_proc */
580
     i.e no untidy returns from the general_proc */
552
  /* The postlude also works on the assumption that no calls to alloca are 
581
  /* The postlude also works on the assumption that no calls to alloca are
553
     done within it */
582
     done within it */
554
 
583
 
555
  /* clear all register associations */
584
  /* clear all register associations */
556
  clear_all();
585
  clear_all();
557
  
586
 
558
  /* move the result to the destination */
587
  /* move the result to the destination */
559
  mka = move_result_to_dest(e,sp,dest,exitlab);
588
  mka = move_result_to_dest(e,sp,dest,exitlab);
560
 
589
 
561
  /* Possibility here that the function is untidy
590
  /* Possibility here that the function is untidy
562
   * In this case we must ensure that there is room to construct 
591
   * In this case we must ensure that there is room to construct
563
   * subsequent parameter lists within this procedure
592
   * subsequent parameter lists within this procedure
564
   * The only way to guarantee this is to pull down the stack pointer by
593
   * The only way to guarantee this is to pull down the stack pointer by
565
   * an extra p_args_and_link_size
594
   * an extra p_args_and_link_size
566
   */
595
   */
567
  if (call_is_untidy(cees))
596
  if (call_is_untidy(cees))
568
  {
597
  {
569
    rir_ins(i_a,R_SP,-p_args_and_link_size,R_SP);
598
    rir_ins(i_a,R_SP,-p_args_and_link_size,R_SP);
570
    if (p_has_saved_sp)
599
    if (p_has_saved_sp)
571
    {
600
    {
572
      save_sp_on_stack();
601
      save_sp_on_stack();
573
    }
602
    }
574
  }
603
  }
575
    
604
 
576
  if (postlude_has_call(e))
605
  if (postlude_has_call(e))
577
  {
606
  {
578
    exp x = son(cers);
607
    exp x = son(cers);
579
    postl_chain p;
608
    postl_chain p;
580
    for(;x != nilexp;)
609
    for (;x != nilexp;)
581
    {
610
    {
582
      if(name(x)==caller_tag)
611
      if (name(x) ==caller_tag)
583
      {
612
      {
584
	no(x) += p_args_and_link_size<<3;
613
	no(x) += p_args_and_link_size<<3;
585
      }
614
      }
586
      if(last(x))
615
      if (last(x))
587
      {
616
      {
588
	break;
617
	break;
589
      }
618
      }
590
      x=bro(x);
619
      x=bro(x);
591
    }
620
    }
592
    update_plc(old_pls, p_args_and_link_size);
621
    update_plc(old_pls, p_args_and_link_size);
593
    p.pl = pl;
622
    p.pl = pl;
594
    p.outer = old_pls;
623
    p.outer = old_pls;
595
    old_pls = &p;
624
    old_pls = &p;
596
 
625
 
597
    rir_ins(i_a,R_SP,-p_args_and_link_size,R_SP);    
626
    rir_ins(i_a,R_SP,-p_args_and_link_size,R_SP);
598
    (void)make_code(pl,sp,nowhere,0);
627
   (void)make_code(pl,sp,nowhere,0);
599
    rir_ins(i_a,R_SP,p_args_and_link_size,R_SP);
628
    rir_ins(i_a,R_SP,p_args_and_link_size,R_SP);
600
 
629
 
601
    old_pls = p.outer;
630
    old_pls = p.outer;
602
    update_plc(old_pls, -p_args_and_link_size);
631
    update_plc(old_pls, -p_args_and_link_size);
603
    mka.regmove = R_NO_REG; /* The result reg is corrupted */
632
    mka.regmove = R_NO_REG; /* The result reg is corrupted */
604
  }
633
  }
605
  else
634
  else
606
  {
635
  {
607
    (void)make_code(pl,sp,nowhere,0);
636
   (void)make_code(pl,sp,nowhere,0);
608
  }
637
  }
609
  return mka;
638
  return mka;
610
}
639
}
611
void make_return_to_label_tag_code PROTO_N ((e,sp)) PROTO_T (exp e X space sp)
640
void make_return_to_label_tag_code(exp e, space sp)
612
{
641
{
613
  int r = reg_operand(son(e),sp);
642
  int r = reg_operand(son(e),sp);
614
 
643
 
615
  mt_ins(i_mtlr,r);  
644
  mt_ins(i_mtlr,r);
616
  /* See generate_procedure_epilogue in stack.c for similarity */
645
  /* See generate_procedure_epilogue in stack.c for similarity */
617
  if (p_frame_size != 0)
646
  if (p_frame_size != 0)
618
  {
647
  {
619
    if (p_has_fp)
648
    if (p_has_fp)
620
    {
649
    {
621
      /* Use the frame pointer to collapse the frame */
650
      /* Use the frame pointer to collapse the frame */
622
      mov_rr_ins(R_FP,R_SP);comment("collapse frame using FP");
651
      mov_rr_ins(R_FP,R_SP);comment("collapse frame using FP");
623
    }
652
    }
624
    else if ( p_has_back_chain )
653
    else if (p_has_back_chain)
625
    {
654
    {
626
      /* Use the back chain to collapse the stack frame */
655
      /* Use the back chain to collapse the stack frame */
627
      baseoff back_chain;
656
      baseoff back_chain;
628
      back_chain.base = R_SP;
657
      back_chain.base = R_SP;
629
      back_chain.offset = 0;
658
      back_chain.offset = 0;
Line 647... Line 676...
647
  {
676
  {
648
    restore_sregs(R_SP,0);
677
    restore_sregs(R_SP,0);
649
  }
678
  }
650
  /* At this point the stack pointer is in its return position */
679
  /* At this point the stack pointer is in its return position */
651
  /* Now we move r to the link register */
680
  /* Now we move r to the link register */
652
 
681
 
653
  z_ins(i_br);
682
  z_ins(i_br);
654
  return;
683
  return;
655
}
684
}
656
 
685
 
657
void make_tail_call_tag_code PROTO_N ((e,sp)) PROTO_T (exp e X space sp)
686
void make_tail_call_tag_code(exp e, space sp)
658
{
687
{
659
  exp fn =son(e);
688
  exp fn =son(e);
660
  exp cees = bro(fn);
689
  exp cees = bro(fn);
661
  baseoff callee_pointer;
690
  baseoff callee_pointer;
662
  bool direct_call = (name(fn) == name_tag 
691
  bool direct_call = (name(fn) == name_tag
663
		      && name(son(fn)) == ident_tag
692
		      && name(son(fn)) == ident_tag
664
		      && (son(son(fn)) == nilexp || IS_A_PROC(son(son(fn)))));
693
		      && (son(son(fn)) == nilexp || IS_A_PROC(son(son(fn)))));
665
  static int identification = 0;
694
  static int identification = 0;
666
  identification++;
695
  identification++;
667
  fprintf(as_file,"# Begin tail call no %d\n",identification);
696
  fprintf(as_file,"# Begin tail call no %d\n",identification);
668
  
697
 
669
  
698
 
670
  callee_pointer.base = R_SP;
699
  callee_pointer.base = R_SP;
671
  callee_pointer.offset = 0;
700
  callee_pointer.offset = 0;
672
  ASSERT(p_has_fp);
701
  ASSERT(p_has_fp);
673
  
702
 
674
 
703
 
675
  if(name(cees)==make_callee_list_tag || name(cees)==make_dynamic_callee_tag)
704
  if (name(cees) ==make_callee_list_tag || name(cees) ==make_dynamic_callee_tag)
676
  {
705
  {
677
    /* +++ This is a bit of a long winded way to do the tail call for
706
    /* +++ This is a bit of a long winded way to do the tail call for
678
       make_dynamic_callee_tag since the callees are copied twice. */
707
       make_dynamic_callee_tag since the callees are copied twice. */
679
    code_here(cees,sp,nowhere);
708
    code_here(cees,sp,nowhere);
680
    if (direct_call==0)
709
    if (direct_call==0)
681
    {
710
    {
682
      /* dynamic call */
711
      /* dynamic call */
683
      int desc_base = reg_operand(fn,sp);
712
      int desc_base = reg_operand(fn,sp);
684
      baseoff b;
713
      baseoff b;
685
      
714
 
686
      b.base = desc_base;
715
      b.base = desc_base;
687
      b.offset = 0;
716
      b.offset = 0;
688
      ld_ro_ins(i_l,b,R_TMP0);comment(NIL);
717
      ld_ro_ins(i_l,b,R_TMP0);comment(NIL);
689
      b.base = R_SP;
718
      b.base = R_SP;
690
      b.offset = 4;
719
      b.offset = 4;
Line 704... Line 733...
704
    }
733
    }
705
    mov_rr_ins(R_FP,R_TEMP_FP);comment("copy FP to TEMP_FP");
734
    mov_rr_ins(R_FP,R_TEMP_FP);comment("copy FP to TEMP_FP");
706
    restore_sregs(R_TEMP_FP,0);
735
    restore_sregs(R_TEMP_FP,0);
707
 
736
 
708
    /* At this point R_TP is R_TEMP_TP and R_FP is R_TEMP_FP */
737
    /* At this point R_TP is R_TEMP_TP and R_FP is R_TEMP_FP */
709
    
738
 
710
    /* Pull down R_TEMP_TP by the size of the callees */
739
    /* Pull down R_TEMP_TP by the size of the callees */
711
    if(name(cees)==make_callee_list_tag)
740
    if (name(cees) ==make_callee_list_tag)
712
    {
741
    {
713
      int size_of_callee_list=ALIGNNEXT((no(cees)>>3)+EXTRA_CALLEE_BYTES , 8);
742
      int size_of_callee_list=ALIGNNEXT((no(cees) >>3) +EXTRA_CALLEE_BYTES , 8);
714
      st_ro_ins(i_st,R_TEMP_TP,callee_pointer);comment(NIL);
743
      st_ro_ins(i_st,R_TEMP_TP,callee_pointer);comment(NIL);
715
      
744
 
716
      mov_rr_ins(R_SP,R_TEMP_FP);comment(NIL);
745
      mov_rr_ins(R_SP,R_TEMP_FP);comment(NIL);
717
      rir_ins(i_a,R_TEMP_TP,-(long)(size_of_callee_list),R_TEMP_TP);
746
      rir_ins(i_a,R_TEMP_TP,- (long)(size_of_callee_list),R_TEMP_TP);
718
      reverse_static_memory_copy(R_TEMP_FP,R_TEMP_TP,size_of_callee_list);
747
      reverse_static_memory_copy(R_TEMP_FP,R_TEMP_TP,size_of_callee_list);
719
      mov_rr_ins(R_TEMP_TP,R_SP);comment(NIL);
748
      mov_rr_ins(R_TEMP_TP,R_SP);comment(NIL);
720
    }
749
    }
721
    else
750
    else
722
    {
751
    {
Line 732... Line 761...
732
    }
761
    }
733
    /* The memory copy does not corrupt R_TEMP_TP or R_TEMP_FP */
762
    /* The memory copy does not corrupt R_TEMP_TP or R_TEMP_FP */
734
    /* Finally put the stack pointer at the bottom of the callees */
763
    /* Finally put the stack pointer at the bottom of the callees */
735
 
764
 
736
  }
765
  }
737
  else if(name(cees)==same_callees_tag)
766
  else if (name(cees) ==same_callees_tag)
738
  {
767
  {
739
    if (name(p_current)==general_proc_tag)
768
    if (name(p_current) ==general_proc_tag)
740
    {
769
    {
741
      if (direct_call ==0)
770
      if (direct_call ==0)
742
      {
771
      {
743
	/* dynamic call */
772
	/* dynamic call */
744
	int desc_base = reg_operand(fn,sp);
773
	int desc_base = reg_operand(fn,sp);
745
	baseoff b;
774
	baseoff b;
746
	
775
 
747
	b.base = desc_base;
776
	b.base = desc_base;
748
	b.offset = 0;
777
	b.offset = 0;
749
	ld_ro_ins(i_l,b,R_TMP0);comment(NIL);
778
	ld_ro_ins(i_l,b,R_TMP0);comment(NIL);
750
	b.base = R_FP;
779
	b.base = R_FP;
751
	b.offset = 4;
780
	b.offset = 4;
Line 757... Line 786...
757
      mov_rr_ins(R_FP,R_TEMP_FP);comment("copy FP to TEMP_FP");
786
      mov_rr_ins(R_FP,R_TEMP_FP);comment("copy FP to TEMP_FP");
758
      restore_sregs(R_TEMP_FP,0);
787
      restore_sregs(R_TEMP_FP,0);
759
      mov_rr_ins(R_TEMP_FP,R_SP);comment("collapse frame using TEMP_FP");
788
      mov_rr_ins(R_TEMP_FP,R_SP);comment("collapse frame using TEMP_FP");
760
    }
789
    }
761
    else
790
    else
762
    {
791
    {
763
      /* This should only occur in the initialisation required for dynamic
792
      /* This should only occur in the initialisation required for dynamic
764
	 initialisation of globals as required for c++ */
793
	 initialisation of globals as required for c++ */
765
      ASSERT(p_has_fp);
794
      ASSERT(p_has_fp);
766
      restore_link_register();
795
      restore_link_register();
767
      restore_callers(PROC_PARAM_REGS);
796
      restore_callers(PROC_PARAM_REGS);
768
      mov_rr_ins(R_FP,R_TEMP_FP);comment("copy FP to TEMP_FP");
797
      mov_rr_ins(R_FP,R_TEMP_FP);comment("copy FP to TEMP_FP");
769
      restore_sregs(R_TEMP_FP,0);
798
      restore_sregs(R_TEMP_FP,0);
770
      mov_rr_ins(R_TEMP_FP,R_SP);comment("collapse frame using TEMP_FP");
799
      mov_rr_ins(R_TEMP_FP,R_SP);comment("collapse frame using TEMP_FP");
771
    }
800
    }
772
  }
801
  }
773
  
802
 
774
  /* Function */
803
  /* Function */
775
  if (direct_call)
804
  if (direct_call)
776
  {
805
  {
777
    baseoff b;
806
    baseoff b;
778
    b = boff(son(fn));
807
    b = boff(son(fn));
Line 789... Line 818...
789
    ld_ro_ins(i_l,b,R_TMP0);comment(NIL);
818
    ld_ro_ins(i_l,b,R_TMP0);comment(NIL);
790
    mt_ins(i_mtctr,R_TMP0);
819
    mt_ins(i_mtctr,R_TMP0);
791
    z_ins(i_bctr);
820
    z_ins(i_bctr);
792
  }
821
  }
793
  fprintf(as_file,"# End tail call no %d\n",identification);
822
  fprintf(as_file,"# End tail call no %d\n",identification);
794
  return;
823
  return;
795
}
824
}
796
 
825
 
797
void make_same_callees_tag_code PROTO_N ((e,sp)) PROTO_T (exp e X space sp)
826
void make_same_callees_tag_code(exp e, space sp)
798
{
827
{
799
  int roldsp;
828
  int roldsp;
800
  int rfrom;
829
  int rfrom;
801
  int rto;
830
  int rto;
802
  space nsp;
831
  space nsp;
803
  baseoff callee_pointer;
832
  baseoff callee_pointer;
804
  nsp = sp;
833
  nsp = sp;
805
  callee_pointer.base = R_SP;
834
  callee_pointer.base = R_SP;
806
  callee_pointer.offset = 0;
835
  callee_pointer.offset = 0;
807
 
836
 
808
  ASSERT(name(p_current)==general_proc_tag);
837
  ASSERT(name(p_current) ==general_proc_tag);
809
  
838
 
810
  rfrom = getreg(nsp.fixed);nsp = guardreg(rfrom,nsp);
839
  rfrom = getreg(nsp.fixed);nsp = guardreg(rfrom,nsp);
811
  rto = getreg(nsp.fixed);nsp = guardreg(rto,nsp);
840
  rto = getreg(nsp.fixed);nsp = guardreg(rto,nsp);
812
  roldsp = getreg(nsp.fixed);nsp = guardreg(roldsp,nsp);
841
  roldsp = getreg(nsp.fixed);nsp = guardreg(roldsp,nsp);
813
 
842
 
814
  restore_callees();
843
  restore_callees();
815
  mov_rr_ins(R_FP,rfrom);comment(NIL);
844
  mov_rr_ins(R_FP,rfrom);comment(NIL);
816
  mov_rr_ins(R_SP,roldsp);comment(NIL);
845
  mov_rr_ins(R_SP,roldsp);comment(NIL);
817
  
846
 
818
  if (p_has_vcallees)
847
  if (p_has_vcallees)
819
  {  /* We use the difference between R_TP and R_FP to
848
  {  /* We use the difference between R_TP and R_FP to
820
     calculate the size of the vcallees and then pulls the
849
     calculate the size of the vcallees and then pulls the
821
     stack pointer down by this amount and copies the callees
850
     stack pointer down by this amount and copies the callees
822
     onto the bottom of the stack.
851
     onto the bottom of the stack.
823
     Finally it sets up the callee pointer which points to
852
     Finally it sets up the callee pointer which points to
824
     the top of the newly constructed callee list */
853
     the top of the newly constructed callee list */
825
    int rsize;
854
    int rsize;
826
    rsize = getreg(nsp.fixed);nsp = guardreg(rsize,nsp);
855
    rsize = getreg(nsp.fixed);nsp = guardreg(rsize,nsp);
827
    
856
 
828
 
857
 
829
    rrr_ins(i_s,R_TP,R_FP,rsize);
858
    rrr_ins(i_s,R_TP,R_FP,rsize);
830
    rrr_ins(i_s,R_SP,rsize,R_SP);
859
    rrr_ins(i_s,R_SP,rsize,R_SP);
831
    mov_rr_ins(R_SP,rto);comment(NIL);
860
    mov_rr_ins(R_SP,rto);comment(NIL);
832
    
861
 
833
    dynamic_word_memory_copy(rfrom,rto,rsize); /* copy the callees */
862
    dynamic_word_memory_copy(rfrom,rto,rsize); /* copy the callees */
834
  }
863
  }
835
  else
864
  else
836
  {
865
  {
837
    /* We can do slightly better since we know the size of the callees */
866
    /* We can do slightly better since we know the size of the callees */
838
    long csize = ALIGNNEXT(p_callee_size + EXTRA_CALLEE_BYTES,8);
867
    long csize = ALIGNNEXT(p_callee_size + EXTRA_CALLEE_BYTES,8);
839
    
868
 
840
    rir_ins(i_a,R_SP,-csize,R_SP);
869
    rir_ins(i_a,R_SP,-csize,R_SP);
841
    mov_rr_ins(R_SP,rto);comment(NIL);
870
    mov_rr_ins(R_SP,rto);comment(NIL);
842
    static_memory_copy(rfrom,rto,csize);
871
    static_memory_copy(rfrom,rto,csize);
843
  }
872
  }
844
  st_ro_ins(i_st,roldsp,callee_pointer);comment(NIL);
873
  st_ro_ins(i_st,roldsp,callee_pointer);comment(NIL);
845
  return;
874
  return;
846
}
875
}
847
 
876
 
848
 
877
 
849
    
-
 
850
 
878
 
-
 
879
 
851
void make_callee_list_tag_code PROTO_N ((e,sp)) PROTO_T (exp e X space sp )
880
void make_callee_list_tag_code(exp e, space sp)
852
{
881
{
853
  long x; 
882
  long x;
854
  exp list = son(e);
883
  exp list = son(e);
855
  long disp;
884
  long disp;
856
  where w;
885
  where w;
857
  instore is;
886
  instore is;
858
  baseoff new_stackpos;
887
  baseoff new_stackpos;
859
  
888
 
860
  /* This is an explicit creation of the callee list on the bottom 
889
  /* This is an explicit creation of the callee list on the bottom
861
     of the stack. no(e) contains the total size in bits required
890
     of the stack. no(e) contains the total size in bits required
862
     to create the callee list.  The EXTRA_CALLEE_BYTES are the 
891
     to create the callee list.  The EXTRA_CALLEE_BYTES are the
863
     bytes needed to store the extra info on the bottom of the callee
892
     bytes needed to store the extra info on the bottom of the callee
864
     list. At present only 4 bytes are required to hold a pointer which
893
     list. At present only 4 bytes are required to hold a pointer which
865
     points to the top of the list.*/
894
     points to the top of the list.*/
866
  
895
 
867
  x = ALIGNNEXT( (no(e)>>3) + EXTRA_CALLEE_BYTES  , 8 );
896
  x = ALIGNNEXT((no(e) >>3) + EXTRA_CALLEE_BYTES  , 8);
868
  new_stackpos.base = R_SP;
897
  new_stackpos.base = R_SP;
869
  new_stackpos.offset = -x;
898
  new_stackpos.offset = -x;
870
  st_ro_ins(i_stu , R_SP , new_stackpos);comment(NIL);
899
  st_ro_ins(i_stu , R_SP , new_stackpos);comment(NIL);
871
  
900
 
872
  disp = EXTRA_CALLEE_BYTES * 8;/* start coding them here */
901
  disp = EXTRA_CALLEE_BYTES * 8;/* start coding them here */
873
  update_plc(old_pls,x);
902
  update_plc(old_pls,x);
874
  if(no(e)!=0)
903
  if (no(e)!=0)
875
  {
904
  {
876
    for(;;)
905
    for (;;)
877
    {
906
    {
878
      ash ap;
907
      ash ap;
879
      
908
 
880
      ap = ashof(sh(list));
909
      ap = ashof(sh(list));
881
      disp = ALIGNNEXT(disp, ap.ashalign);
910
      disp = ALIGNNEXT(disp, ap.ashalign);
882
      is.b.offset = disp>>3;
911
      is.b.offset = disp>>3;
883
      is.b.base = R_SP;
912
      is.b.base = R_SP;
884
      is.adval = 1;
913
      is.adval = 1;
885
      w.ashwhere = ap;
914
      w.ashwhere = ap;
886
      setinsalt(w.answhere,is);
915
      setinsalt(w.answhere,is);
887
      code_here(list,sp,w);
916
      code_here(list,sp,w);
888
      disp = ALIGNNEXT(disp + ap.ashsize,32);
917
      disp = ALIGNNEXT(disp + ap.ashsize,32);
889
      if(last(list))
918
      if (last(list))
890
	break;
919
	break;
891
      list = bro(list);
920
      list = bro(list);
892
    }
921
    }
893
  }
922
  }
894
  update_plc(old_pls,-x);
923
  update_plc(old_pls,-x);
895
  return ;
924
  return;
896
}
925
}
897
 
926
 
898
void make_dynamic_callee_tag_code PROTO_N ((e,sp)) PROTO_T (exp e X space sp )
927
void make_dynamic_callee_tag_code(exp e, space sp)
899
{
928
{
900
  int rfrom;
929
  int rfrom;
901
  int rto;
930
  int rto;
902
  int rsize;
931
  int rsize;
903
  int rsize_adjusted;
932
  int rsize_adjusted;
904
  baseoff callee_pointer;
933
  baseoff callee_pointer;
905
  space nsp;
934
  space nsp;
906
 
935
 
907
  callee_pointer.base = R_SP;
936
  callee_pointer.base = R_SP;
908
  callee_pointer.offset = 0;
937
  callee_pointer.offset = 0;
909
  
938
 
910
  rfrom = reg_operand(son(e),sp);nsp = guardreg(rfrom,sp);
939
  rfrom = reg_operand(son(e),sp);nsp = guardreg(rfrom,sp);
911
  rsize = reg_operand(bro(son(e)),nsp);nsp = guardreg(rsize,nsp);
940
  rsize = reg_operand(bro(son(e)),nsp);nsp = guardreg(rsize,nsp);
912
  if (al2(sh(bro(son(e)))) < 32)
941
  if (al2(sh(bro(son(e)))) < 32)
913
  {	/* shouldn't happen for correct ANDF? */
942
  {	/* shouldn't happen for correct ANDF? */
914
    rir_ins(i_a, rsize, 3, rsize);
943
    rir_ins(i_a, rsize, 3, rsize);
915
    rir_ins(i_and, rsize, ~3, rsize);
944
    rir_ins(i_and, rsize, ~3, rsize);
916
  }
945
  }
917
  
946
 
918
  rto = getreg(nsp.fixed);nsp = guardreg(rto,nsp);
947
  rto = getreg(nsp.fixed);nsp = guardreg(rto,nsp);
919
  rsize_adjusted = getreg(nsp.fixed);nsp = guardreg(rsize_adjusted,nsp);
948
  rsize_adjusted = getreg(nsp.fixed);nsp = guardreg(rsize_adjusted,nsp);
920
  
949
 
921
    
950
 
922
  rir_ins(i_a,rsize , EXTRA_CALLEE_BYTES + 7 , rsize_adjusted);
951
  rir_ins(i_a,rsize , EXTRA_CALLEE_BYTES + 7 , rsize_adjusted);
923
  rir_ins(i_and ,rsize_adjusted ,~7 , rsize_adjusted );
952
  rir_ins(i_and ,rsize_adjusted ,~7 , rsize_adjusted);
924
  /* Pull down the stack frame by rsize_adjusted bytes */
953
  /* Pull down the stack frame by rsize_adjusted bytes */
925
  rrr_ins(i_s, R_SP, rsize_adjusted , R_SP);
954
  rrr_ins(i_s, R_SP, rsize_adjusted , R_SP);
926
  
955
 
927
  rir_ins(i_a, R_SP , EXTRA_CALLEE_BYTES , rto); /* copy to here */
956
  rir_ins(i_a, R_SP , EXTRA_CALLEE_BYTES , rto); /* copy to here */
928
  /* copy rsize bytes from rfrom to rto */
957
  /* copy rsize bytes from rfrom to rto */
929
  /* +++ Can we do this word at a time */
958
  /* +++ Can we do this word at a time */
930
 
959
 
931
  reverse_dynamic_word_memory_copy(rfrom,rto,rsize);
960
  reverse_dynamic_word_memory_copy(rfrom,rto,rsize);
Line 933... Line 962...
933
  rrr_ins(i_a,rsize_adjusted,R_SP,R_TMP0);
962
  rrr_ins(i_a,rsize_adjusted,R_SP,R_TMP0);
934
  st_ro_ins(i_st,R_TMP0,callee_pointer);comment(NIL);
963
  st_ro_ins(i_st,R_TMP0,callee_pointer);comment(NIL);
935
  return;
964
  return;
936
}
965
}
937
 
966
 
938
space do_callers PROTO_N ((n,list,sp)) PROTO_T (int n X exp list X space sp )
967
space do_callers(int n, exp list, space sp)
939
{
968
{
940
  /* Evaluates parameters into fixed registers or float registers or stack 
969
  /* Evaluates parameters into fixed registers or float registers or stack
941
   according to the calling convention */
970
   according to the calling convention */
942
  int disp = 0;
971
  int disp = 0;
943
  int param_reg = R_FIRST_PARAM;
972
  int param_reg = R_FIRST_PARAM;
944
  int last_param_reg = R_FIRST_PARAM;
973
  int last_param_reg = R_FIRST_PARAM;
945
  int fr_param_reg = FR_FIRST_PARAM;
974
  int fr_param_reg = FR_FIRST_PARAM;
946
  space nsp;
975
  space nsp;
947
  int final_param = n + R_FIRST_PARAM - 1;
976
  int final_param = n + R_FIRST_PARAM - 1;
948
  nsp =sp;
977
  nsp =sp;
949
  
978
 
950
  for (;;)
979
  for (;;)
951
  {
980
  {
952
    exp par = name(list)==caller_tag ?son(list):list;
981
    exp par = name(list) ==caller_tag ?son(list):list;
953
    shape par_shape = sh(par);
982
    shape par_shape = sh(par);
954
    ash ap;
983
    ash ap;
955
    where w;
984
    where w;
956
    ap = ashof(sh(par));
985
    ap = ashof(sh(par));
957
    w.ashwhere = ap;
986
    w.ashwhere = ap;
958
    
987
 
959
    if (is_floating(name(par_shape)) && param_reg <= final_param)
988
    if (is_floating(name(par_shape)) && param_reg <= final_param)
960
    {
989
    {
961
      bool dble = is_double_precision(par_shape);
990
      bool dble = is_double_precision(par_shape);
962
      instore is;
991
      instore is;
963
      freg frg;
992
      freg frg;
964
      
993
 
965
      is.b = boff_location(ENCODE_FOR_BOFF((disp>>3),OUTPUT_CALLER_PARAMETER));
994
      is.b = boff_location(ENCODE_FOR_BOFF((disp>>3),OUTPUT_CALLER_PARAMETER));
966
      is.adval = 1;
995
      is.adval = 1;
967
      
996
 
968
      frg.fr=(fr_param_reg<=FR_LAST_PARAM?fr_param_reg:getfreg(nsp.flt));
997
      frg.fr= (fr_param_reg<=FR_LAST_PARAM?fr_param_reg:getfreg(nsp.flt));
969
      frg.dble = dble;
998
      frg.dble = dble;
970
      setfregalt(w.answhere, frg);
999
      setfregalt(w.answhere, frg);
971
 
1000
 
972
      /* The floating parameter is evaluated into a floating parameter t-reg
1001
      /* The floating parameter is evaluated into a floating parameter t-reg
973
	 (If we have not filled them all up ) else a spare t-reg */
1002
	 (If we have not filled them all up ) else a spare t-reg */
974
      code_here(par, nsp, w);
1003
      code_here(par, nsp, w);
975
      
1004
 
976
      if (frg.fr == fr_param_reg)
1005
      if (frg.fr == fr_param_reg)
977
      {
1006
      {
978
	/* The floatind paramter is in a floating parameter t-reg so
1007
	/* The floatind paramter is in a floating parameter t-reg so
979
	   we must guard it */
1008
	   we must guard it */
980
	nsp = guardfreg(frg.fr, nsp);
1009
	nsp = guardfreg(frg.fr, nsp);
Line 986... Line 1015...
986
      ld_ro_ins(i_l, is.b, param_reg);comment("load float-param from stack into param reg");
1015
      ld_ro_ins(i_l, is.b, param_reg);comment("load float-param from stack into param reg");
987
      nsp = guardreg(param_reg, nsp);
1016
      nsp = guardreg(param_reg, nsp);
988
 
1017
 
989
      param_reg++;
1018
      param_reg++;
990
      last_param_reg = param_reg;
1019
      last_param_reg = param_reg;
991
      
1020
 
992
      if (dble && param_reg <= final_param)
1021
      if (dble && param_reg <= final_param)
993
      {
1022
      {
994
	/* Double whose second half can be loaded into fixed param t-reg */
1023
	/* Double whose second half can be loaded into fixed param t-reg */
995
	is.b.offset += 4;
1024
	is.b.offset += 4;
996
	ld_ro_ins(i_l, is.b, param_reg);comment("it was a double so we load other half"); 
1025
	ld_ro_ins(i_l, is.b, param_reg);comment("it was a double so we load other half");
997
	nsp = guardreg(param_reg, nsp);
1026
	nsp = guardreg(param_reg, nsp);
998
	param_reg++;
1027
	param_reg++;
999
	last_param_reg = param_reg;
1028
	last_param_reg = param_reg;
1000
      }
1029
      }
1001
      fr_param_reg++;
1030
      fr_param_reg++;
Line 1016... Line 1045...
1016
    {
1045
    {
1017
      /* stack parameter */
1046
      /* stack parameter */
1018
      int param_size = ap.ashsize;
1047
      int param_size = ap.ashsize;
1019
      instore is;
1048
      instore is;
1020
      is.adval = 1;
1049
      is.adval = 1;
1021
      
1050
 
1022
      is.b= boff_location(ENCODE_FOR_BOFF((disp >> 3),OUTPUT_CALLER_PARAMETER));
1051
      is.b= boff_location(ENCODE_FOR_BOFF((disp >> 3),OUTPUT_CALLER_PARAMETER));
1023
      if (param_size == 0)
1052
      if (param_size == 0)
1024
      {
1053
      {
1025
	/* from fake <varargs.h> param, nothing to do */
1054
	/* from fake <varargs.h> param, nothing to do */
1026
	/* Could be something of shape top which needs evaluating */
1055
	/* Could be something of shape top which needs evaluating */
1027
	/* Fix for avs suite FlowControl/apply_proc*/
1056
	/* Fix for avs suite FlowControl/apply_proc*/
1028
	code_here(par,sp,nowhere);
1057
	code_here(par,sp,nowhere);
1029
      }
1058
      }
1030
      else if (is_floating(name(par_shape)))
1059
      else if (is_floating(name(par_shape)))
1031
      {
1060
      {
1032
	freg frg;
1061
	freg frg;
1033
	/* store floating parameter on the stack */
1062
	/* store floating parameter on the stack */
1034
	frg.fr=(fr_param_reg<=FR_LAST_PARAM ? fr_param_reg : getfreg(nsp.flt));
1063
	frg.fr= (fr_param_reg<=FR_LAST_PARAM ? fr_param_reg : getfreg(nsp.flt));
1035
	
1064
 
1036
	frg.dble = name(par_shape) != shrealhd;
1065
	frg.dble = name(par_shape)!= shrealhd;
1037
	setfregalt(w.answhere, frg);
1066
	setfregalt(w.answhere, frg);
1038
	code_here(par, nsp, w);
1067
	code_here(par, nsp, w);
1039
	
1068
 
1040
	if (frg.fr == fr_param_reg)
1069
	if (frg.fr == fr_param_reg)
1041
	{
1070
	{
1042
	  nsp = guardfreg(frg.fr, nsp);
1071
	  nsp = guardfreg(frg.fr, nsp);
1043
	}
1072
	}
1044
	
1073
 
1045
	stf_ro_ins((frg.dble ? i_stfd : i_stfs), frg.fr, is.b);
1074
	stf_ro_ins((frg.dble ? i_stfd : i_stfs), frg.fr, is.b);
1046
	
1075
 
1047
	fr_param_reg++;
1076
	fr_param_reg++;
1048
      }
1077
      }
1049
      else if (param_reg <= final_param)
1078
      else if (param_reg <= final_param)
1050
      {
1079
      {
1051
	/* By elimination it must be an aggregrate whose 
1080
	/* By elimination it must be an aggregrate whose
1052
	   whole or part is to be passed in regs */
1081
	   whole or part is to be passed in regs */
1053
	int last_ld_reg;
1082
	int last_ld_reg;
1054
	int r;
1083
	int r;
1055
	bool allinreg;
1084
	bool allinreg;
1056
	int dolastoffset;
1085
	int dolastoffset;
1057
 
1086
 
1058
	last_ld_reg = param_reg + (ALIGNNEXT(param_size, 32)/32) - 1;
1087
	last_ld_reg = param_reg + (ALIGNNEXT(param_size, 32) /32) - 1;
1059
	if (last_ld_reg > final_param)
1088
	if (last_ld_reg > final_param)
1060
	{
1089
	{
1061
	  last_ld_reg = final_param;
1090
	  last_ld_reg = final_param;
1062
	  allinreg = 0;
1091
	  allinreg = 0;
1063
	}
1092
	}
1064
	else
1093
	else
1065
	{
1094
	{
1066
	  allinreg = 1;
1095
	  allinreg = 1;
1067
	}
1096
	}
1068
	
1097
 
1069
	if (allinreg && name(par) == cont_tag)
1098
	if (allinreg && name(par) == cont_tag)
1070
	{
1099
	{
1071
	  /* a small simple ident, which we can load easily */
1100
	  /* a small simple ident, which we can load easily */
1072
	  where w;
1101
	  where w;
1073
	  w = locate(par, nsp, sh(par), 0);
1102
	  w = locate(par, nsp, sh(par), 0);
1074
	  
1103
 
1075
	  ASSERT(w.answhere.discrim==notinreg);
1104
	  ASSERT(w.answhere.discrim==notinreg);
1076
	  
1105
 
1077
	  is = insalt(w.answhere);
1106
	  is = insalt(w.answhere);
1078
	  
1107
 
1079
	  COMMENT3("apply: simple aggregate parameter: adval=%d reg=%d off=%d",
1108
	  COMMENT3("apply: simple aggregate parameter: adval=%d reg=%d off=%d",
1080
		   is.adval, is.b.base, is.b.offset);
1109
		   is.adval, is.b.base, is.b.offset);
1081
	  ASSERT(!is.adval);
1110
	  ASSERT(!is.adval);
1082
	  /* it is already lying about */
1111
	  /* it is already lying about */
1083
	  if (!IS_FIXREG(is.b.base))
1112
	  if (!IS_FIXREG(is.b.base))
1084
	  {
1113
	  {
1085
	    /* make addressable */
1114
	    /* make addressable */
1086
	    set_ins(is.b, last_ld_reg);
1115
	    set_ins(is.b, last_ld_reg);
1087
	    is.b.base = last_ld_reg;
1116
	    is.b.base = last_ld_reg;
1088
	    is.b.offset = 0;
1117
	    is.b.offset = 0;
1089
	  }
1118
	  }
1090
	  
1119
 
1091
	}
1120
	}
1092
	else
1121
	else
1093
	{
1122
	{
1094
	  /* evaluate aggregate to stack location for param, then move to regs */
1123
	  /* evaluate aggregate to stack location for param, then move to regs */
1095
	  /* +++ do better for aggregate passed partially in regs */
1124
	  /* +++ do better for aggregate passed partially in regs */
1096
	  setinsalt(w.answhere, is);
1125
	  setinsalt(w.answhere, is);
1097
	  /* Get that horrible thing written directly into the stack */
1126
	  /* Get that horrible thing written directly into the stack */
1098
	  code_here(par, nsp, w);
1127
	  code_here(par, nsp, w);
1099
	}
1128
	}
1100
	
1129
 
1101
	/* now load as many regs as required */
1130
	/* now load as many regs as required */
1102
	
1131
 
1103
	dolastoffset = -1;
1132
	dolastoffset = -1;
1104
	
1133
 
1105
	for (r = param_reg; r <= last_ld_reg; r++)
1134
	for (r = param_reg; r <= last_ld_reg; r++)
1106
	{
1135
	{
1107
	  if (r == is.b.base)
1136
	  if (r == is.b.base)
1108
	  {
1137
	  {
1109
	    /* clash with base reg, do it later */
1138
	    /* clash with base reg, do it later */
Line 1111... Line 1140...
1111
	  }
1140
	  }
1112
	  else
1141
	  else
1113
	  {
1142
	  {
1114
	    ld_ro_ins(i_l, is.b, r);comment("copy struct param from stack into param regs");
1143
	    ld_ro_ins(i_l, is.b, r);comment("copy struct param from stack into param regs");
1115
	  }
1144
	  }
1116
	  
1145
 
1117
	  nsp = guardreg(r, nsp);
1146
	  nsp = guardreg(r, nsp);
1118
	  is.b.offset += 4;
1147
	  is.b.offset += 4;
1119
	}
1148
	}
1120
	
1149
 
1121
	if (dolastoffset != -1)
1150
	if (dolastoffset != -1)
1122
	{
1151
	{
1123
	  /* do ld that clashed with base reg */
1152
	  /* do ld that clashed with base reg */
1124
	  is.b.offset = dolastoffset;
1153
	  is.b.offset = dolastoffset;
1125
	  ld_ro_ins(i_l, is.b, is.b.base);comment("copy the last part of the structure due to clash of regs");
1154
	  ld_ro_ins(i_l, is.b, is.b.base);comment("copy the last part of the structure due to clash of regs");
Line 1128... Line 1157...
1128
      else
1157
      else
1129
      {
1158
      {
1130
	setinsalt(w.answhere, is);
1159
	setinsalt(w.answhere, is);
1131
	code_here(par, nsp, w);
1160
	code_here(par, nsp, w);
1132
      }
1161
      }
1133
      
1162
 
1134
      /* move param_reg on by size */
1163
      /* move param_reg on by size */
1135
      param_reg += (param_size + 31) / 32;
1164
      param_reg += (param_size + 31) / 32;
1136
    }
1165
    }
1137
    
1166
 
1138
    if(name(list)==caller_tag)
1167
    if (name(list) ==caller_tag)
1139
    {
1168
    {
1140
      no(list)=disp;
1169
      no(list) =disp;
1141
    }
1170
    }
1142
    
1171
 
1143
    if (last(list))
1172
    if (last(list))
1144
      break;
1173
      break;
1145
    list = bro(list);
1174
    list = bro(list);
1146
    
1175
 
1147
    disp = ALIGNNEXT(disp + ap.ashsize, 32);
1176
    disp = ALIGNNEXT(disp + ap.ashsize, 32);
1148
  }				/* end for */
1177
  }				/* end for */
1149
 
1178
 
1150
  ASSERT(last_param_reg >= R_FIRST_PARAM && last_param_reg <= final_param + 1);
1179
  ASSERT(last_param_reg >= R_FIRST_PARAM && last_param_reg <= final_param + 1);
1151
  return nsp;
1180
  return nsp;
1152
  
1181
 
1153
}
1182
}
1154
void do_function_call PROTO_N ((fn,sp)) PROTO_T (exp fn X space sp)
1183
void do_function_call(exp fn, space sp)
1155
{
1184
{
1156
  if ( name(fn) == name_tag 
1185
  if (name(fn) == name_tag
1157
      && name(son(fn)) == ident_tag
1186
      && name(son(fn)) == ident_tag
1158
      && (son(son(fn)) == nilexp || IS_A_PROC(son(son(fn)))) 
1187
      && (son(son(fn)) == nilexp || IS_A_PROC(son(son(fn))))
1159
      )
1188
     )
1160
  {
1189
  {
1161
    /* direct call */
1190
    /* direct call */
1162
    baseoff b;
1191
    baseoff b;
1163
    b = boff(son(fn));
1192
    b = boff(son(fn));
1164
    extj_ins(i_bl, b);
1193
    extj_ins(i_bl, b);
1165
  }
1194
  }
1166
  else
1195
  else
1167
  {
1196
  {
1168
    /* proc ptr call */
1197
    /* proc ptr call */
1169
    int desc_base = reg_operand(fn, sp);
1198
    int desc_base = reg_operand(fn, sp);
1170
    baseoff b;
1199
    baseoff b;
1171
    
1200
 
1172
    COMMENT("proc ptr call");
1201
    COMMENT("proc ptr call");
1173
    
1202
 
1174
    b.base = desc_base;
1203
    b.base = desc_base;
1175
    b.offset = 0;
1204
    b.offset = 0;
1176
    ld_ro_ins(i_l, b, R_TMP0);comment("load function address to R_TMP0");
1205
    ld_ro_ins(i_l, b, R_TMP0);comment("load function address to R_TMP0");
1177
    mt_ins(i_mtlr, R_TMP0);
1206
    mt_ins(i_mtlr, R_TMP0);
1178
    /* +++ use scan() so we can do this in proc prelude */
1207
    /* +++ use scan() so we can do this in proc prelude */
1179
    b.base = R_SP;
1208
    b.base = R_SP;
1180
    b.offset = STACK_SAVED_TOC;
1209
    b.offset = STACK_SAVED_TOC;
1181
    st_ro_ins(i_st, R_TOC, b);comment("save toc pointer for this function");
1210
    st_ro_ins(i_st, R_TOC, b);comment("save toc pointer for this function");
1182
    b.base = desc_base;
1211
    b.base = desc_base;
1183
    b.offset = 4;
1212
    b.offset = 4;
1184
    ld_ro_ins(i_l, b, R_TOC);comment("load up toc pointer for function");
1213
    ld_ro_ins(i_l, b, R_TOC);comment("load up toc pointer for function");
1185
    /* +++ load env ptr from descriptor */
1214
    /* +++ load env ptr from descriptor */
1186
    z_ins(i_brl);
1215
    z_ins(i_brl);
1187
    b.base = R_SP;
1216
    b.base = R_SP;
1188
    b.offset = STACK_SAVED_TOC;
1217
    b.offset = STACK_SAVED_TOC;
1189
    ld_ro_ins(i_l, b, R_TOC);comment("restore toc pointer");
1218
    ld_ro_ins(i_l, b, R_TOC);comment("restore toc pointer");
1190
  }
1219
  }
1191
}
1220
}
1192
void do_general_function_call PROTO_N ((fn,sp)) PROTO_T (exp fn X space sp)
1221
void do_general_function_call(exp fn, space sp)
1193
{
1222
{
1194
  if ( name(fn) == name_tag 
1223
  if (name(fn) == name_tag
1195
      && name(son(fn)) == ident_tag
1224
      && name(son(fn)) == ident_tag
1196
      && (son(son(fn)) == nilexp || IS_A_PROC(son(son(fn)))) 
1225
      && (son(son(fn)) == nilexp || IS_A_PROC(son(son(fn))))
1197
      )
1226
     )
1198
  {
1227
  {
1199
    /* direct call */
1228
    /* direct call */
1200
    baseoff b;
1229
    baseoff b;
1201
    b = boff(son(fn));
1230
    b = boff(son(fn));
1202
    extj_ins(i_bl, b);
1231
    extj_ins(i_bl, b);
1203
  }
1232
  }
1204
  else
1233
  else
1205
  {
1234
  {
1206
    /* proc ptr call */
1235
    /* proc ptr call */
1207
    int desc_base = reg_operand(fn, sp);
1236
    int desc_base = reg_operand(fn, sp);
1208
    baseoff b;
1237
    baseoff b;
1209
    baseoff saved_toc;
1238
    baseoff saved_toc;
1210
    int r;
1239
    int r;
1211
    
1240
 
1212
    COMMENT("proc ptr call");
1241
    COMMENT("proc ptr call");
1213
    r = getreg(guardreg(desc_base,sp).fixed);
1242
    r = getreg(guardreg(desc_base,sp).fixed);
1214
    
1243
 
1215
    b.base = desc_base;
1244
    b.base = desc_base;
1216
    b.offset = 0;
1245
    b.offset = 0;
1217
    ld_ro_ins(i_l, b, R_TMP0);comment("load function address to R_TMP0");
1246
    ld_ro_ins(i_l, b, R_TMP0);comment("load function address to R_TMP0");
1218
    mt_ins(i_mtlr, R_TMP0);
1247
    mt_ins(i_mtlr, R_TMP0);
1219
    saved_toc.base = R_SP;
1248
    saved_toc.base = R_SP;
Line 1231... Line 1260...
1231
    b.base = R_SP;
1260
    b.base = R_SP;
1232
    b.offset = STACK_SAVED_TOC;
1261
    b.offset = STACK_SAVED_TOC;
1233
    ld_ro_ins(i_l, b, R_TOC);comment("restore toc pointer");
1262
    ld_ro_ins(i_l, b, R_TOC);comment("restore toc pointer");
1234
  }
1263
  }
1235
}
1264
}
1236
makeans move_result_to_dest PROTO_N ((e,sp,dest,exitlab)) PROTO_T (exp e X space sp X where dest X int exitlab )
1265
makeans move_result_to_dest(exp e, space sp, where dest, int exitlab)
1237
{
1266
{
1238
  makeans mka;
1267
  makeans mka;
1239
  int hda = name(sh(e));	/* Shape of result */
1268
  int hda = name(sh(e));	/* Shape of result */
1240
  ans aa;
1269
  ans aa;
1241
  mka.regmove=R_NO_REG;
1270
  mka.regmove=R_NO_REG;
1242
  mka.lab = exitlab;
1271
  mka.lab = exitlab;
1243
  
1272
 
1244
  /* move result of application to destination */
1273
  /* move result of application to destination */
1245
  if (is_floating(hda))
1274
  if (is_floating(hda))
1246
  {
1275
  {
1247
    freg frg;
1276
    freg frg;
1248
    
1277
 
1249
    frg.fr = FR_RESULT;
1278
    frg.fr = FR_RESULT;
1250
    frg.dble = (hda != shrealhd);
1279
    frg.dble = (hda != shrealhd);
1251
    setfregalt(aa, frg);
1280
    setfregalt(aa, frg);
1252
    COMMENT1("apply: is_floating result, dble=%d", frg.dble);
1281
    COMMENT1("apply: is_floating result, dble=%d", frg.dble);
1253
    move(aa, dest, sp.fixed, 1);
1282
    move(aa, dest, sp.fixed, 1);
Line 1271... Line 1300...
1271
      }
1300
      }
1272
      else
1301
      else
1273
      {
1302
      {
1274
	COMMENT("apply: dest R_RESULT, no move");
1303
	COMMENT("apply: dest R_RESULT, no move");
1275
      }
1304
      }
1276
    }  
1305
    }
1277
    else if (dest.answhere.discrim == insomereg)
1306
    else if (dest.answhere.discrim == insomereg)
1278
    {
1307
    {
1279
      int *dr = someregalt(dest.answhere);
1308
      int *dr = someregalt(dest.answhere);
1280
      COMMENT("apply: dest insomereg set to R_RESULT");
1309
      COMMENT("apply: dest insomereg set to R_RESULT");
1281
      if(*dr != -1 ) 
1310
      if (*dr != -1)
1282
      {
1311
      {
1283
	fail("somereg been set up");
1312
	fail("somereg been set up");
1284
      }
1313
      }
1285
      *dr = R_RESULT;
1314
      *dr = R_RESULT;
1286
    }
1315
    }
Line 1289... Line 1318...
1289
      COMMENT("apply: dest not inreg or insomereg");
1318
      COMMENT("apply: dest not inreg or insomereg");
1290
      move(aa, dest, sp.fixed, 1);
1319
      move(aa, dest, sp.fixed, 1);
1291
    }
1320
    }
1292
  }
1321
  }
1293
  return mka;
1322
  return mka;
1294
}  
1323
}
1295
void restore_callers PROTO_N ((n)) PROTO_T (int n)
1324
void restore_callers(int n)
1296
{
1325
{
1297
  /* finds all the callers and puts them into there correct register */
1326
  /* finds all the callers and puts them into there correct register */
1298
  exp bdy = son(p_current);
1327
  exp bdy = son(p_current);
1299
  int final_param = n + R_FIRST_PARAM - 1;
1328
  int final_param = n + R_FIRST_PARAM - 1;
1300
  
1329
 
1301
  COMMENT("restore callers");
1330
  COMMENT("restore callers");
1302
  while(name(bdy)==diagnose_tag)
1331
  while (name(bdy) ==diagnose_tag)
1303
  {
1332
  {
1304
    bdy = son(bdy);
1333
    bdy = son(bdy);
1305
  }
1334
  }
1306
  while (name(bdy)==ident_tag && isparam(bdy)
1335
  while (name(bdy) ==ident_tag && isparam(bdy)
1307
	 && name(son(bdy)) !=formal_callee_tag )
1336
	 && name(son(bdy))!=formal_callee_tag)
1308
  {
1337
  {
1309
    exp sbdy = son(bdy);
1338
    exp sbdy = son(bdy);
1310
    baseoff parampos;
1339
    baseoff parampos;
1311
    bool ident_in_register = (props(bdy) & inanyreg) !=0;
1340
    bool ident_in_register = (props(bdy) & inanyreg)!=0;
1312
    bool is_aggregate = IS_AGGREGATE(sh(sbdy));
1341
    bool is_aggregate = IS_AGGREGATE(sh(sbdy));
1313
    int param_reg = props(sbdy);
1342
    int param_reg = props(sbdy);
1314
    int ident_size = shape_size(sh(sbdy));
1343
    int ident_size = shape_size(sh(sbdy));
1315
    
1344
 
1316
    if (p_has_tp)
1345
    if (p_has_tp)
1317
    {
1346
    {
1318
      parampos.base = R_TP;
1347
      parampos.base = R_TP;
1319
    }
1348
    }
1320
    else
1349
    else
1321
    {
1350
    {
1322
      /* Non general proc */
1351
      /* Non general proc */
1323
      parampos.base = R_FP;
1352
      parampos.base = R_FP;
1324
    }
1353
    }
1325
    
1354
 
1326
    parampos.offset = (no(sbdy)>>3) + STACK_ARG_AREA;
1355
    parampos.offset = (no(sbdy) >>3) + STACK_ARG_AREA;
1327
    
1356
 
1328
    
1357
 
1329
    if( param_reg==0 && ident_in_register)
1358
    if (param_reg==0 && ident_in_register)
1330
    {
1359
    {
1331
      /* Parameter which was passed by stack and allocated into
1360
      /* Parameter which was passed by stack and allocated into
1332
	 a register */
1361
	 a register */
1333
      ASSERT(!is_aggregate);/* +++ allow 32 bit aggregates */
1362
      ASSERT(!is_aggregate);/* +++ allow 32 bit aggregates */
1334
      if(isvar(bdy))
1363
      if (isvar(bdy))
1335
      {
1364
      {
1336
	/* somebody has assigned to it so it must be reloaded */
1365
	/* somebody has assigned to it so it must be reloaded */
1337
	if(is_floating(name(sh(sbdy))))
1366
	if (is_floating(name(sh(sbdy))))
1338
	{
1367
	{
1339
	  bool dble = is_double_precision(sh(sbdy));
1368
	  bool dble = is_double_precision(sh(sbdy));
1340
	  stf_ro_ins(dble ? i_stfd :i_stfs,no(bdy),parampos);
1369
	  stf_ro_ins(dble ? i_stfd :i_stfs,no(bdy),parampos);
1341
	}
1370
	}
1342
	else
1371
	else
1343
	{
1372
	{
1344
	  st_ro_ins(i_st,no(bdy),parampos);comment(NIL);
1373
	  st_ro_ins(i_st,no(bdy),parampos);comment(NIL);
1345
	}
1374
	}
1346
      }
1375
      }
1347
    }
1376
    }
1348
    else if( param_reg != 0 && ! ident_in_register)
1377
    else if (param_reg != 0 && ! ident_in_register)
1349
    {
1378
    {
1350
      /* should be in reg is in store */
1379
      /* should be in reg is in store */
1351
      if(is_aggregate)
1380
      if (is_aggregate)
1352
      {
1381
      {
1353
	/* this is an aggregate which was passed partially or
1382
	/* this is an aggregate which was passed partially or
1354
	   totally in register
1383
	   totally in register
1355
	   */
1384
	   */
1356
	int last_st_reg = param_reg + (ALIGNNEXT(ident_size,32)) -1;
1385
	int last_st_reg = param_reg + (ALIGNNEXT(ident_size,32)) -1;
1357
	int r;
1386
	int r;
1358
	baseoff bo;
1387
	baseoff bo;
1359
	bo = boff(bdy);
1388
	bo = boff(bdy);
1360
	
1389
 
1361
	if (last_st_reg > final_param)
1390
	if (last_st_reg > final_param)
1362
	  last_st_reg = final_param;
1391
	  last_st_reg = final_param;
1363
	
1392
 
1364
	for (r = param_reg;r<=last_st_reg;r++)
1393
	for (r = param_reg;r<=last_st_reg;r++)
1365
	{
1394
	{
1366
	  ld_ro_ins(i_l,bo,r);comment("restore struct into caller param regs");
1395
	  ld_ro_ins(i_l,bo,r);comment("restore struct into caller param regs");
1367
	  bo.offset +=4;
1396
	  bo.offset +=4;
1368
	}
1397
	}
Line 1378... Line 1407...
1378
      }
1407
      }
1379
    }
1408
    }
1380
    else if (props(sbdy)!=0 && props(sbdy)!=no(bdy))
1409
    else if (props(sbdy)!=0 && props(sbdy)!=no(bdy))
1381
    {
1410
    {
1382
      /* in wrong register */
1411
      /* in wrong register */
1383
      if(is_floating(name(sh(sbdy))))
1412
      if (is_floating(name(sh(sbdy))))
1384
      {
1413
      {
1385
	rrf_ins(i_fmr,no(bdy),param_reg);
1414
	rrf_ins(i_fmr,no(bdy),param_reg);
1386
      }
1415
      }
1387
      else
1416
      else
1388
      {
1417
      {
1389
	mov_rr_ins(no(bdy),param_reg);comment("restore param reg from reg");
1418
	mov_rr_ins(no(bdy),param_reg);comment("restore param reg from reg");
1390
      }
1419
      }
1391
    }
1420
    }
1392
    bdy = bro(sbdy);
1421
    bdy = bro(sbdy);
1393
  }
1422
  }
1394
  if(suspected_varargs)
1423
  if (suspected_varargs)
1395
  {
1424
  {
1396
    baseoff v ;
1425
    baseoff v;
1397
    int r;
1426
    int r;
1398
    if (p_has_tp)
1427
    if (p_has_tp)
1399
    {
1428
    {
1400
      v.base = R_TP;
1429
      v.base = R_TP;
1401
    }
1430
    }
1402
    else
1431
    else
1403
    {
1432
    {
1404
      v.base = R_FP;
1433
      v.base = R_FP;
1405
    }
1434
    }
1406
    v.offset = saved_varargs_offset;
1435
    v.offset = saved_varargs_offset;
1407
    for(r = saved_varargs_register ; r<= final_param ;r++)
1436
    for (r = saved_varargs_register; r<= final_param ;r++)
1408
    {
1437
    {
1409
      ld_ro_ins(i_l,v,r);comment("restore all params since varargs");
1438
      ld_ro_ins(i_l,v,r);comment("restore all params since varargs");
1410
      v.offset += 4;
1439
      v.offset += 4;
1411
    }
1440
    }
1412
  }
1441
  }
1413
  return;
1442
  return;
1414
}
1443
}
1415
void restore_callees PROTO_Z ()
1444
void restore_callees(void)
1416
{
1445
{
1417
  /* It is possible that callees are allocated s-regs in which case they must
1446
  /* It is possible that callees are allocated s-regs in which case they must
1418
     be moved back on to their proper place on the stack */
1447
     be moved back on to their proper place on the stack */
1419
  exp bdy = son(p_current);
1448
  exp bdy = son(p_current);
1420
  COMMENT("restore callees");
1449
  COMMENT("restore callees");
1421
  
1450
 
1422
  while(name(bdy)==diagnose_tag)
1451
  while (name(bdy) ==diagnose_tag)
1423
  {
1452
  {
1424
    bdy = son(bdy);
1453
    bdy = son(bdy);
1425
  }  
1454
  }
1426
  while (name(bdy)==ident_tag && isparam(bdy)
1455
  while (name(bdy) ==ident_tag && isparam(bdy)
1427
	 && name(son(bdy)) !=formal_callee_tag )  
1456
	 && name(son(bdy))!=formal_callee_tag)
1428
  {
1457
  {
1429
    bdy = bro(son(bdy));
1458
    bdy = bro(son(bdy));
1430
  }
1459
  }
1431
  while (name(bdy)==ident_tag && isparam(bdy) )  
1460
  while (name(bdy) ==ident_tag && isparam(bdy))
1432
  {
1461
  {
1433
    exp sbdy = son(bdy);
1462
    exp sbdy = son(bdy);
1434
    baseoff stackpos;
1463
    baseoff stackpos;
1435
    stackpos.base = R_FP;
1464
    stackpos.base = R_FP;
1436
    stackpos.offset = EXTRA_CALLEE_BYTES + (no(sbdy)>>3);
1465
    stackpos.offset = EXTRA_CALLEE_BYTES + (no(sbdy) >>3);
1437
    if (props(bdy) & infreg_bits)
1466
    if (props(bdy) & infreg_bits)
1438
    {
1467
    {
1439
      bool dble = is_double_precision(sh(sbdy));
1468
      bool dble = is_double_precision(sh(sbdy));
1440
      ASSERT(IS_FLT_SREG(no(bdy)));
1469
      ASSERT(IS_FLT_SREG(no(bdy)));
1441
      stf_ro_ins(dble?i_stfd:i_stfs,no(bdy),stackpos);
1470
      stf_ro_ins(dble?i_stfd:i_stfs,no(bdy),stackpos);
Line 1447... Line 1476...
1447
    }
1476
    }
1448
    bdy = bro(sbdy);
1477
    bdy = bro(sbdy);
1449
  }
1478
  }
1450
  return;
1479
  return;
1451
}
1480
}
1452
static exp find_ote PROTO_N ((e,n)) PROTO_T (exp e X int n)
1481
static exp find_ote(exp e, int n)
1453
{
1482
{
1454
  exp d = father(e);
1483
  exp d = father(e);
1455
  while (name(d)!=apply_general_tag) d = father(d);
1484
  while (name(d)!=apply_general_tag)d = father(d);
1456
  d = son(bro(son(d))); /* list otagexps */
1485
  d = son(bro(son(d))); /* list otagexps */
1457
  while(n !=0) { d = bro(d); n--;}
1486
  while (n !=0) { d = bro(d); n--;}
1458
  ASSERT(name(d)==caller_tag);
1487
  ASSERT(name(d) ==caller_tag);
1459
  return d;
1488
  return d;
1460
}		
1489
}