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

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

Subversion Repositories tendra.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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