Subversion Repositories tendra.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
7 7u83 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
 */
31
/*
2 7u83 32
    		 Crown Copyright (c) 1997
7 7u83 33
 
2 7u83 34
    This TenDRA(r) Computer Program is subject to Copyright
35
    owned by the United Kingdom Secretary of State for Defence
36
    acting through the Defence Evaluation and Research Agency
37
    (DERA).  It is made available to Recipients with a
38
    royalty-free licence for its use, reproduction, transfer
39
    to other parties and amendment for any purpose not excluding
40
    product development provided that any such use et cetera
41
    shall be deemed to be acceptance of the following conditions:-
7 7u83 42
 
2 7u83 43
        (1) Its Recipients shall ensure that this Notice is
44
        reproduced upon any copies or amended versions of it;
7 7u83 45
 
2 7u83 46
        (2) Any amended version of it shall be clearly marked to
47
        show both the nature of and the organisation responsible
48
        for the relevant amendment or amendments;
7 7u83 49
 
2 7u83 50
        (3) Its onward transfer from a recipient to another
51
        party shall be deemed to be that party's acceptance of
52
        these conditions;
7 7u83 53
 
2 7u83 54
        (4) DERA gives no warranty or assurance as to its
55
        quality or suitability for any purpose and DERA accepts
56
        no liability whatsoever in relation to any use to which
57
        it may be put.
58
*/
59
 
60
 
61
 
62
 
63
/*
64
			    VERSION INFORMATION
65
			    ===================
66
 
67
--------------------------------------------------------------------------
68
$Header: /u/g/release/CVSROOT/Source/src/installers/sparc/common/proc.c,v 1.2 1998/03/15 16:00:43 pwe Exp $
69
--------------------------------------------------------------------------
70
$Log: proc.c,v $
71
 * Revision 1.2  1998/03/15  16:00:43  pwe
72
 * regtrack dwarf dagnostics added
73
 *
74
 * Revision 1.1.1.1  1998/01/17  15:55:55  release
75
 * First version to be checked into rolling release.
76
 *
77
 * Revision 1.61  1998/01/09  14:59:42  pwe
78
 * prep restructure
79
 *
80
 * Revision 1.60  1997/11/06  09:29:13  pwe
81
 * ANDF-DE V1.8
82
 *
83
 * Revision 1.59  1997/10/28  10:19:05  pwe
84
 * extra diags
85
 *
86
 * Revision 1.58  1997/10/23  09:33:16  pwe
87
 * prep extra_diags
88
 *
89
 * Revision 1.57  1997/10/10  18:32:56  pwe
90
 * prep ANDF-DE revision
91
 *
92
 * Revision 1.56  1997/08/23  13:54:28  pwe
93
 * initial ANDF-DE
94
 *
95
 * Revision 1.55  1997/05/02  11:09:11  pwe
96
 * dwarf2 re return address offset
97
 *
98
 * Revision 1.54  1997/04/24  15:16:31  pwe
99
 * optim -O0 in tail_call
100
 *
101
 * Revision 1.53  1997/04/17  11:59:54  pwe
102
 * dwarf2 support
103
 *
104
 * Revision 1.52  1997/03/26  13:04:45  pwe
105
 * general proc compatibility
106
 *
107
 * Revision 1.51  1997/03/24  17:09:35  pwe
108
 * reorganise solaris/sunos split
109
 *
110
 * Revision 1.50  1997/02/18  11:48:17  pwe
111
 * NEWDIAGS for debugging optimised code
112
 *
113
 * Revision 1.49  1996/09/18  12:03:59  pwe
114
 * fixed PIC_code
115
 *
116
 * Revision 1.48  1996/09/10  14:36:48  pwe
117
 * fix diags - nested scope, param struct and leaf return
118
 *
119
 * Revision 1.47  1996/09/09  12:32:52  pwe
120
 * protect result during postlude
121
 *
122
 * Revision 1.46  1996/09/06  16:50:27  pwe
123
 * fix outpar doubles for postlude
124
 *
125
 * Revision 1.45  1996/09/04  12:41:37  pwe
126
 * untidy_call must not remove stacked callees
127
 *
128
 * Revision 1.44  1996/08/30  17:00:25  pwe
129
 * ensure space available for struct return
130
 *
131
 * Revision 1.43  1996/08/28  16:57:51  pwe
132
 * postlude with calls and no callers
133
 *
134
 * Revision 1.42  1996/08/28  11:47:54  pwe
135
 * correct postlude with calls
136
 *
137
 * Revision 1.41  1996/08/27  14:09:09  pwe
138
 * ensure all varargs are stored, and ptr is not64bit
139
 *
140
 * Revision 1.40  1996/08/22  16:47:10  pwe
141
 * correct accessing for double params
142
 *
143
 * Revision 1.39  1996/06/24  08:46:09  john
144
 * Removed aggregate initialisation
145
 *
146
 * Revision 1.38  1996/06/19  15:39:22  john
147
 * Fixed register allocation bug
148
 *
149
 * Revision 1.37  1996/05/24  10:46:08  john
150
 * Fixed discarded return for function returning struct/long double
151
 *
152
 * Revision 1.36  1996/03/20  15:39:49  john
153
 * Fix to  double & long double handling
154
 *
155
 * Revision 1.35  1996/03/18  09:02:03  john
156
 * Change to caller move
157
 *
158
 * Revision 1.34  1996/02/20  14:16:29  john
159
 * Fix for caller param lists containing structures.
160
 *
161
 * Revision 1.33  1996/01/17  10:29:59  john
162
 * Fix to stack space usage on tail call
163
 *
164
 * Revision 1.32  1996/01/10  17:23:00  john
165
 * Fix to check_stack
166
 *
167
 * Revision 1.31  1996/01/08  11:15:24  john
168
 * Fix to discarded function return when using out_pars
169
 *
170
 * Revision 1.30  1995/12/15  10:26:23  john
171
 * Changes stack error handling + fixes to postlude for general procs
172
 *
173
 * Revision 1.29  1995/11/27  09:22:54  john
174
 * Fixed register allocation
175
 *
176
 * Revision 1.28  1995/11/24  14:51:43  john
177
 * Fixed bug in register allocation
178
 *
179
 * Revision 1.27  1995/11/24  11:41:38  john
180
 * Fix for postludes
181
 *
182
 * Revision 1.26  1995/11/23  12:47:43  john
183
 * Fix for general procs
184
 *
185
 * Revision 1.25  1995/11/17  13:01:08  john
186
 * Fix to general proc call
187
 *
188
 * Revision 1.24  1995/11/16  17:23:43  john
189
 * Fix to same_callees
190
 *
191
 * Revision 1.23  1995/11/16  14:14:00  john
192
 * Fixed untidy return
193
 *
194
 * Revision 1.22  1995/11/16  14:03:28  john
195
 * Fixed register problems in general procs
196
 *
197
 * Revision 1.21  1995/11/07  09:42:09  john
198
 * Extensive changes to handling of callee parameters in general procs
199
 *
200
 * Revision 1.20  1995/11/01  16:13:59  john
201
 * Changed general proc definition
202
 *
203
 * Revision 1.19  1995/10/31  12:48:10  john
204
 * Change to dynamic callees
205
 *
206
 * Revision 1.18  1995/10/27  14:22:54  john
207
 * change to previous fix
208
 *
209
 * Revision 1.17  1995/10/27  10:51:41  john
210
 * Fix to general procs
211
 *
212
 * Revision 1.16  1995/10/25  17:13:18  john
213
 * Changed stack overflow test to unsigned
214
 *
215
 * Revision 1.15  1995/09/29  09:23:09  john
216
 * Fixed condition for setting Has_no_vcallers
217
 *
218
 * Revision 1.14  1995/09/27  13:35:27  john
219
 * Fix to tail_call
220
 *
221
 * Revision 1.13  1995/09/22  15:58:23  john
222
 * Fix to apply_general_proc
223
 *
224
 * Revision 1.12  1995/09/22  13:07:07  john
225
 * Fix to general procs
226
 *
227
 * Revision 1.11  1995/09/15  16:17:02  john
228
 * New exception handling
229
 *
230
 * Revision 1.10  1995/09/04  10:14:22  john
231
 * Fix to general procs
232
 *
233
 * Revision 1.9  1995/08/04  15:46:34  john
234
 * Fix to general procs
235
 *
236
 * Revision 1.8  1995/07/27  16:31:32  john
237
 * Fixed prototype
238
 *
239
 * Revision 1.7  1995/07/18  08:24:34  john
240
 * Fix to tail calls
241
 *
242
 * Revision 1.6  1995/07/14  16:33:23  john
243
 * Various changes for new spec
244
 *
245
 * Revision 1.5  1995/07/04  07:51:45  john
246
 * *** empty log message ***
247
 *
248
 * Revision 1.4  1995/06/30  08:29:35  john
249
 * Fixed bug in tail_call
250
 *
251
 * Revision 1.3  1995/06/14  15:35:44  john
252
 * Added support for trap error treatment and stack limits.  Also, some
253
 * reformatting
254
 *
255
 * Revision 1.2  1995/05/26  13:00:28  john
256
 * Changes for new spec (3.1)
257
 *
258
 * Revision 1.1.1.1  1995/03/13  10:18:51  john
259
 * Entered into CVS
260
 *
261
 * Revision 1.5  1995/01/17  15:32:24  john
262
 * Removed structure parameter check.
263
 *
264
 * Revision 1.4  1994/12/01  13:07:34  djch
265
 * with longjmp one can get procs of shape bottom. consider them as returning
266
 * void
267
 *
268
 * Revision 1.3  1994/07/07  16:11:33  djch
269
 * Jul94 tape
270
 *
271
 * Revision 1.2  1994/05/13  13:06:59  djch
272
 * Incorporates improvements from expt version
273
 * removed rscope related fns.
274
 * added RET_IN_CODE, not set -> return at end of leaf, not in middle...
275
 *
276
 * Revision 1.1  94/05/03  14:49:48  djch
277
 * Initial revision
7 7u83 278
 *
2 7u83 279
 * Revision 1.8  94/02/21  16:12:49  16:12:49  ra (Robert Andrews)
280
 * reg_result now returns int, not bool.
7 7u83 281
 *
2 7u83 282
 * Revision 1.7  93/09/27  14:53:49  14:53:49  ra (Robert Andrews)
283
 * In System V the __GLOBAL_OFFSET_TABLE_ starts with only one _.
7 7u83 284
 *
2 7u83 285
 * Revision 1.6  93/08/27  11:35:12  11:35:12  ra (Robert Andrews)
286
 * A number of lint-like changes.
7 7u83 287
 *
2 7u83 288
 * Revision 1.5  93/08/13  14:44:13  14:44:13  ra (Robert Andrews)
289
 * Reformatted.
7 7u83 290
 *
2 7u83 291
 * Revision 1.4  93/07/14  11:21:26  11:21:26  ra (Robert Andrews)
292
 * Misprint when reformatting : .reserved should be .reserve.
7 7u83 293
 *
2 7u83 294
 * Revision 1.3  93/07/05  18:23:46  18:23:46  ra (Robert Andrews)
295
 * Made distinction between the System V assembler and the System V ABI.
296
 * Added support for PIC (procedure prologue).
7 7u83 297
 *
2 7u83 298
 * Revision 1.2  93/06/29  14:30:40  14:30:40  ra (Robert Andrews)
299
 * Changed an error message.
7 7u83 300
 *
2 7u83 301
 * Revision 1.1  93/06/24  14:59:01  14:59:01  ra (Robert Andrews)
302
 * Initial revision
7 7u83 303
 *
2 7u83 304
--------------------------------------------------------------------------
305
*/
306
 
307
/*
308
  This file contains functions which handle the various aspects
309
  of procedure definition and invocation.
310
*/
311
 
312
 
313
#define SPARCTRANS_CODE
314
#include "config.h"
315
#include "common_types.h"
316
#include "myassert.h"
317
#include "addrtypes.h"
318
#include "tags.h"
319
#include "expmacs.h"
320
#include "installtypes.h"
321
#include "exp.h"
322
#include "exptypes.h"
323
#include "maxminmacs.h"
324
#include "shapemacs.h"
325
#include "basicread.h"
326
#include "proctypes.h"
327
#include "eval.h"
328
#include "move.h"
329
#include "comment.h"
330
#include "getregs.h"
331
#include "guard.h"
332
#include "locate.h"
333
#include "codehere.h"
334
#include "inst_fmt.h"
335
#include "sparcins.h"
336
#include "bitsmacs.h"
337
#include "labels.h"
338
#include "regexps.h"
339
#include "regmacs.h"
340
#include "regable.h"
341
#include "flags.h"
342
#include "special.h"
343
#include "translat.h"
344
#include "makecode.h"
345
#include "out.h"
346
#include "proc.h"
347
#include "szs_als.h"
348
#include "externs.h"
349
#include "sparctrans.h"
350
 
351
#ifdef NEWDIAGS
352
#include "dg_globs.h"
353
#endif
354
 
355
#ifdef NEWDWARF
356
#include "dw2_config.h"
357
#include "dw2_info.h"
358
#include "dw2_basic.h"
359
#include "dw2_extra.h"
360
#endif
361
 
362
/*
363
  CODE GENERATION STATE FOR THE CURRENT PROCEDURE
364
*/
365
 
7 7u83 366
static void alloc_space(int,int);
367
static void alloc_reg_space(int,int);
2 7u83 368
 
369
extern int call_base_reg;
370
 
371
 
7 7u83 372
struct proc_state proc_state;
2 7u83 373
static exp current_proc;
374
 
375
bool Has_vcallees = 0;
376
bool Has_no_vcallers = 0;
377
bool in_general_proc = 0;
378
#ifdef GENCOMPAT
379
bool May_have_callees = 0;
380
#endif
381
 
382
 
383
static bool in_postlude = 0;
384
 
385
extern char * proc_name;
386
int local_reg = R_I5;
387
 
388
int callee_start_reg = R_I5;   /* will point to start of callee params */
389
 
390
int callee_end_reg = R_I4;     /* will point to end of callee params.  Only
391
				  used for variable or dynamic parameter
392
				  lists */
393
int callee_start_reg_out = R_O5;
394
int callee_end_reg_out = R_O4;
395
 
396
 
397
static int vc_call = 0;
398
 
399
int aritherr_lab = 0;
400
 
401
int stackerr_lab = 0;
402
int local_stackerr_lab = 0;
403
 
7 7u83 404
#define is64(X)((name(X) ==u64hd) || (name(X) ==s64hd))
2 7u83 405
 
406
 
7 7u83 407
void call_tdf_main
408
(void) {
2 7u83 409
  outs("\tcall\t___TDF_main\n");
410
  outs("\tnop\n");
411
  return;
412
}
413
 
414
 
415
 
7 7u83 416
 
2 7u83 417
/*
418
  FIND TEMPORARY MEMORY
7 7u83 419
  This is a temporary location in the stack frame callee parameter
420
  save area that can be used in short instruction sequences, such
421
  as moving between float and fixed registers.  It is initialised
2 7u83 422
  in the procedure prelude.
423
*/
424
 
7 7u83 425
baseoff mem_temp
426
(int byte_offset) {
427
  baseoff b;
428
  b = proc_state.mem_temp0;
2 7u83 429
  /* only 2 words of temp allocated */
7 7u83 430
  assert(byte_offset >= 0 && byte_offset < 8);
431
  b.offset += byte_offset;
432
  return(b);
2 7u83 433
}
434
 
435
 
436
 
437
/*
7 7u83 438
  Postlude chaining function
2 7u83 439
*/
440
static postlude_chain * old_postludes;
441
 
7 7u83 442
void update_plc
443
(postlude_chain* chain, int maxargs) {
2 7u83 444
 
7 7u83 445
  while (chain) {
2 7u83 446
    exp pl = chain->postlude;
7 7u83 447
    while (name(pl) == ident_tag) {
2 7u83 448
      if (name(son(pl)) == caller_name_tag)
449
	no(pl) += (maxargs<<1);
450
      pl = bro(son(pl));
451
    }
452
    chain = chain->outer;
453
  }
454
  return;
455
}
456
 
457
 
458
/*
459
  ENCODE A PROCEDURE DEFINITION
460
*/
461
 
7 7u83 462
makeans make_proc_tag_code
463
(exp e, space sp, where dest, int exitlab) {
464
  procrec *pr = &procrecs[no(e)];
465
  needs *ndpr = &pr->needsproc;
466
  spacereq *sppr = &pr->spacereqproc;
467
  long pprops = (long)(ndpr->prps);
2 7u83 468
  bool leaf = ( bool ) ( ( pprops & anyproccall ) == 0 ) ;	/* LINT */
469
  long maxargs = ndpr->maxargs ;/* maxargs of proc body in bits */
470
  long st = sppr->stack ;		/* space for locals in bits */
7 7u83 471
  struct proc_state old_proc_state;
472
  makeans mka;
473
  exp par;
2 7u83 474
  old_postludes = (postlude_chain*)NULL;
475
  current_proc = e;
476
  Has_vcallees = (name(e) == general_proc_tag) && (proc_has_vcallees(e));
477
  Has_no_vcallers = (name(e) == proc_tag) || (!proc_has_vcallers(e));
478
  in_general_proc = (name(e) == general_proc_tag);
479
#ifdef GENCOMPAT
480
  May_have_callees = proc_may_have_callees(e);
481
#endif
482
  /* save & reinstate proc_state for nested procs */
7 7u83 483
  old_proc_state = proc_state;
484
  mka.lab = exitlab;
485
  mka.regmove = NOREG;
2 7u83 486
#ifdef GENCOMPAT
487
  if (May_have_callees) {
488
#else
7 7u83 489
  if (in_general_proc) {
2 7u83 490
#endif
491
    sp = guardreg(callee_start_reg,sp);
492
  }
7 7u83 493
 
494
  if (Has_vcallees) {
2 7u83 495
    sp = guardreg(callee_end_reg,sp);
7 7u83 496
    outs("\t.optim\t\"-O0\"\n"); /* as -O2 optimises out some moves
2 7u83 497
				    from %sp to other registers */
498
  }
7 7u83 499
 
2 7u83 500
  /* this is a procedure definition */
7 7u83 501
  assert(name(e) == proc_tag || name(e) == general_proc_tag);
502
 
2 7u83 503
  /* set global flag for res_tag */
7 7u83 504
  proc_state.leaf_proc = leaf;
2 7u83 505
 
506
  /* maxargs is the maxargs in bits of any proc called, not this proc */
507
 
508
  /* SPARC reserved stack area */
7 7u83 509
  if (leaf) {
2 7u83 510
    /* reg window dump area */
7 7u83 511
    assert(maxargs == 0);
512
    maxargs = (16)* 32;
513
  }
2 7u83 514
  else {
7 7u83 515
    assert(maxargs >= 0);
2 7u83 516
    /* at least reg param dump for calls */
7 7u83 517
    if (maxargs < (6)* 32)maxargs = (6)* 32;
2 7u83 518
    /* plus reg window dump area + hidden struct return param */
7 7u83 519
    maxargs += (16 + 1)* 32;
2 7u83 520
  }
7 7u83 521
 
2 7u83 522
  /* use space we are allowing for called procs */
7 7u83 523
  proc_state.mem_temp0.base = R_SP;
524
  proc_state.mem_temp0.offset = (16 + 1 + 1)* 4;
2 7u83 525
 
526
  /* double word aligned */
7 7u83 527
  assert((proc_state.mem_temp0.offset & 7) == 0);
528
 
2 7u83 529
  /* make sure mem_temp () is allowed for */
7 7u83 530
  if (proc_state.mem_temp0.base == R_SP &&
531
       maxargs < ((proc_state.mem_temp0.offset + 8) << 3)) {
2 7u83 532
    /* ie, a leaf proc */
7 7u83 533
    assert(leaf);
534
    maxargs = (proc_state.mem_temp0.offset + 8) << 3;
2 7u83 535
    }
7 7u83 536
 
2 7u83 537
  /* align to 64 bit boundaries */
7 7u83 538
  maxargs = (maxargs + 63) & ~63;
539
  st = (st + 63) & ~63;
2 7u83 540
  /* -----------------------WARNING--------------------------- */
7 7u83 541
  /* if you alter these then please check boff_env_offset, 'cos
2 7u83 542
     they're effectively reproduced there..... */
7 7u83 543
  proc_state.locals_space = st;
544
  proc_state.locals_offset = 0;
2 7u83 545
  /*proc_state.params_offset = ( 16 + 1 ) * 32 ;*/
546
  proc_state.params_offset = PARAMS_OFFSET;
547
  proc_state.callee_size = ndpr->callee_size;
7 7u83 548
  /* beyond register window save area and hidden param of
2 7u83 549
     caller's frame */
550
 
7 7u83 551
  proc_state.frame_size = maxargs + st;
552
  proc_state.maxargs = maxargs;
553
 
554
  st = proc_state.frame_size >> 3;
555
 
2 7u83 556
#ifdef NEWDWARF
557
  if (dwarf2) {
7 7u83 558
    START_BB();
2 7u83 559
    dw2_start_fde(current_proc);
560
  }
561
#endif
562
 
7 7u83 563
  if (name(e) == general_proc_tag) {
564
    if (proc_has_checkstack(e) && (st > 64)) {
2 7u83 565
      rir_ins(i_save,R_SP,-64,R_SP);
566
    }
567
    else {
568
      rir_ins(i_save,R_SP,-st,R_SP);
569
    }
570
#ifdef NEWDWARF
571
    if (dwarf2)
572
      dw2_fde_save();
573
#endif
574
#ifdef GENCOMPAT
575
    if (May_have_callees)
576
#endif
577
    {
578
      int entry_lab = new_label();
579
      uncond_ins(i_b,entry_lab);
580
      /*rir_ins(i_save,R_SP,0,R_SP);*/
581
 
7 7u83 582
      if (st>64) {
2 7u83 583
	rir_ins(i_sub,R_SP, st - 64,R_SP);
584
      }
585
      set_label(entry_lab);
586
    }
587
  }
588
  else{
7 7u83 589
    rir_ins(i_save, R_SP, -st, R_SP);
2 7u83 590
#ifdef NEWDWARF
591
    if (dwarf2)
592
      dw2_fde_save();
593
#endif
594
    /* more here about fp */
595
  }
7 7u83 596
 
2 7u83 597
  /* position independent code */
7 7u83 598
  if (PIC_code && proc_uses_external(e)) {
599
    char *g = "__GLOBAL_OFFSET_TABLE_";
600
    if (sysV_assembler)g++;
601
    outs("1:\n");
602
    outs("\tcall\t2f\n");
603
    outf("\tsethi\t%%hi(%s+ (.-1b)),%%l7\n", g);
604
    outs("2:\n");
605
    outf("\tor\t%%l7,%%lo(%s+ (.-1b)),%%l7\n", g);
606
    outs("\tadd\t%l7,%o7,%l7\n");
2 7u83 607
#ifdef NEWDWARF
608
    if (dwarf2)
609
      lost_count_ins();
610
#endif
611
  }
612
 
613
  local_stackerr_lab = 0;
614
  stackerr_lab = 0;
7 7u83 615
  if (name(e) == general_proc_tag) {
616
    if (proc_has_checkstack(e)) {
2 7u83 617
      baseoff b;
618
      int rtmp;
619
      int rt;
620
      if (st > 64) {
621
	rt = getreg(sp.fixed);
622
	rir_ins(i_sub,R_SP,(st - 64),rt);
623
      }
624
      else {
625
	rt = R_SP;
626
      }
627
      b = find_tag(TDF_STACKLIM);
628
      stackerr_lab = new_label();
629
      rtmp = getreg(guardreg(rt,sp).fixed);
630
      ld_ins(i_ld,b,rtmp);
631
      condrr_ins(i_bgtu,rtmp,R_SP,stackerr_lab);
7 7u83 632
      if (rt != R_SP) {
2 7u83 633
	rr_ins(i_mov,rt,R_SP);
634
      }
635
    }
636
 
637
    /* Here we make a local copy of the callees */
7 7u83 638
    if (Has_vcallees) {
2 7u83 639
      baseoff b;
640
      int copy_lab = new_label();
641
      int end_copy_lab = new_label();
642
      /* copy callees to new space (pointed to by reg rdest) */
643
      int rsize = getreg(sp.fixed);
644
      int rdest = getreg(guardreg(rsize,sp).fixed);
645
      int rt = getreg(guardreg(rdest,sp).fixed);
646
      rrr_ins(i_sub,callee_end_reg,callee_start_reg,rsize);
647
      condrr_ins(i_be,rsize,R_G0,end_copy_lab);
648
      alloc_reg_space(rsize,rdest);
649
      b.offset = 0;
650
      set_label(copy_lab);
651
      b.base = callee_start_reg;
652
      ld_ro_ins(i_ld,b,rt);
653
      b.base = rdest;
654
      st_ro_ins(i_st,rt,b);
655
      rir_ins(i_add,callee_start_reg,PTR_SZ>>3,callee_start_reg);
656
      rir_ins(i_add,rdest,PTR_SZ>>3,rdest);
657
      condrr_ins(i_bne,callee_start_reg,callee_end_reg,copy_lab);
658
      /* now set up the new callee pointers */
659
      rr_ins(i_mov,rdest,callee_end_reg);
660
      rrr_ins(i_sub,rdest,rsize,callee_start_reg);
661
      set_label(end_copy_lab);
662
    }
663
#ifdef GENCOMPAT
664
    else
665
    if (May_have_callees) {
666
#else
667
    else {
668
#endif
669
      baseoff b;
670
      int size = proc_state.callee_size/8;
671
      int rdest = getreg(sp.fixed);
672
      int el;
673
      int rt = getreg(guardreg(rdest,sp).fixed);
674
      alloc_space(size,rdest);
675
      b.offset = 0;
7 7u83 676
      for (el = proc_state.callee_size/8;el>0;el -= (PTR_SZ>>3)) {
2 7u83 677
	b.base = callee_start_reg;
678
	b.offset = el - (PTR_SZ>>3);
679
	ld_ro_ins(i_ld,b,rt);
680
	b.base = rdest;
681
	st_ro_ins(i_st,rt,b);
682
      }
7 7u83 683
      /* now deallocate old storage.  This is needs for outpars to be
2 7u83 684
	 accessed properly from postludes. */
685
#if 0
7 7u83 686
      rir_ins(i_add,callee_start_reg,((proc_state.callee_size>>3) +7) &~7,callee_start_reg);
2 7u83 687
      rir_ins(i_sub,callee_start_reg,96,R_FP);
688
#endif
689
      rr_ins(i_mov,rdest,callee_start_reg);
690
 
691
    }
692
  }
7 7u83 693
  if (do_profile) {
2 7u83 694
      /* implement -p option, call mcount */
7 7u83 695
    static int p_lab = 0;
696
    p_lab++;
697
    if (sysV_assembler) {
698
      outs("\t.reserve\tLP.");
699
      outn(p_lab);
700
      outs(",4,\".bss\",4\n");
701
      }
2 7u83 702
    else {
7 7u83 703
      outs("\t.reserve\tLP.");
704
      outn(p_lab);
705
      outs(",4,\"bss\",4\n");
2 7u83 706
    }
7 7u83 707
    insection(text_section);
708
    outs("\tset\tLP.");
709
    outn(p_lab);
710
    outs(",%o0\n");
2 7u83 711
#ifdef NEWDWARF
712
    if (dwarf2)
713
      lost_count_ins();
714
#endif
7 7u83 715
    extj_special_ins(i_call, "mcount", 1);
2 7u83 716
  }
717
 
718
    /* Move params if necessary */
7 7u83 719
  par = son(e);
720
  while (name(par) == ident_tag) {
721
    if (isparam(par)) {
2 7u83 722
      /* Got a parameter ident */
7 7u83 723
      int r = (int)props(son(par));
2 7u83 724
      /* ( r == 0 ) ? ( on stack ) : ( input reg no ) */
725
/*	assert ( name ( son ( par ) ) == clear_tag ) ;*/
726
 
7 7u83 727
      if (r != 0) {
2 7u83 728
	/* Parameter in register */
7 7u83 729
	assert(R_I0 <= r && r <= R_I5);
730
 
731
	if (no(par)!= 0) {
732
	  if (no(par) == R_NO_REG) {
2 7u83 733
	    /* struct/union parameter, on stack aleady,
734
	       nothing useful in reg */
7 7u83 735
	    assert(!fixregable(par) &&
736
		     !floatregable(par));
737
	  }
738
	  else if (no(par) == r) {
739
	    if (name(sh(son(par))) == ucharhd) {
740
	      rir_ins(i_and, r, 255, no(par));
741
	    }
742
	    else if (name(sh(son(par))) == uwordhd) {
743
	      rir_ins(i_and, r, 65535, no(par));
744
	    }
745
	  }
2 7u83 746
	  else {
7 7u83 747
	    if (name(sh(son(par))) == ucharhd) {
748
	      rir_ins(i_and, r, 255, no(par));
749
	    }
750
	    else if (name(sh(son(par))) == uwordhd) {
751
	      rir_ins(i_and, r, 65535, no(par));
752
	    }
2 7u83 753
	    else {
7 7u83 754
	      rr_ins(i_mov, r, no(par));
2 7u83 755
	    }
756
	  }
7 7u83 757
	}
2 7u83 758
	else {
759
	  /* Parameter in reg move to stack */
7 7u83 760
	  baseoff stackpos;
761
	  long size = shape_size(sh(son(par)));
762
	  int offs = (int)((no(son(par)) +
763
				 proc_state.params_offset) >> 3);
764
	  stackpos.base = R_FP;
765
	  stackpos.offset =offs;
2 7u83 766
 
7 7u83 767
	  switch (size) {
768
	    case 8: {
769
	      st_ro_ins(i_stb, r, stackpos);
770
	      break;
2 7u83 771
	    }
7 7u83 772
	    case 16: {
773
	      st_ro_ins(i_sth, r, stackpos);
774
	      break;
2 7u83 775
	    }
7 7u83 776
	    case 32: {
777
	      st_ro_ins(i_st, r, stackpos);
778
	      break;
2 7u83 779
	    }
7 7u83 780
	    case 64: {
2 7u83 781
	      /* A double can be passed first word in reg
782
		 (R_I5) and second word on stack. Must only
783
		 store out first word in this case  */
7 7u83 784
	      st_ro_ins(i_st, r, stackpos);
785
	      if (r != R_I5) {
2 7u83 786
		/* float point double passed in fixed
787
		   point reg pair */
7 7u83 788
		stackpos.offset += 4;
789
		st_ro_ins(i_st, r + 1, stackpos);
2 7u83 790
	      }
7 7u83 791
	      break;
2 7u83 792
	    }
793
	    default : {
7 7u83 794
	      fail("bad size in make_proc_tag_code");
795
	      break;
2 7u83 796
	    }
797
	  }
798
	}
7 7u83 799
      }
2 7u83 800
      else {
801
	/* Param on stack, no change */
802
      }
803
    }
7 7u83 804
    par = bro(son(par));
2 7u83 805
  }
806
 
7 7u83 807
  clear_all();
808
 
809
 
810
    if ((pprops & long_result_bit)!= 0) {
2 7u83 811
      /* structure or union result, address of space to [ %fp+64 ] */
7 7u83 812
      instore is;
2 7u83 813
      /* [%fp+64] as per call convention */
7 7u83 814
      is.adval = 0;
815
      is.b.base = R_FP;
816
      is.b.offset = (16 * 4);
817
      setinsalt(proc_state.procans, is);
818
    }
819
    else if ((pprops & realresult_bit)!= 0) {
2 7u83 820
      /* proc has real result */
7 7u83 821
      freg frg;
822
      frg.fr = 0;
823
      frg.dble = (bool)((pprops & longrealresult_bit)? 1 : 0);
824
      setfregalt(proc_state.procans, frg);
825
    }
826
    else if ((pprops & has_result_bit)!= 0) {
827
      setregalt(proc_state.procans, R_I0);
828
    }
2 7u83 829
    else {
830
      /* no result */
7 7u83 831
      setregalt(proc_state.procans, R_G0);
2 7u83 832
    }
833
 
7 7u83 834
    proc_state.rscope_level = 0;
835
    proc_state.result_label = 0;
2 7u83 836
 
837
    /* code for body of proc */
838
#if 1
7 7u83 839
    if (!sysV_abi && do_dynamic_init && !strcmp(proc_name,"_main")) {
2 7u83 840
      call_tdf_main();
841
    }
7 7u83 842
#endif
843
   (void)code_here(son(e), sp, nowhere);
844
    clear_all();
845
    if (stackerr_lab) {
2 7u83 846
      set_label(stackerr_lab);
7 7u83 847
      fprintf(as_file, "\t%s\n", i_restore);
848
      if (local_stackerr_lab) {
2 7u83 849
	set_label(local_stackerr_lab);
850
      }
7 7u83 851
 
2 7u83 852
      /*rir_ins(i_add,R_SP,proc_state.frame_size>>3,R_SP);*/
853
      do_exception(f_stack_overflow);
854
    }
7 7u83 855
    if (aritherr_lab != 0) {
2 7u83 856
      set_label(aritherr_lab);
857
      do_exception(f_overflow);
858
    }
7 7u83 859
 
2 7u83 860
#ifndef RET_IN_CODE
7 7u83 861
    if (proc_state.result_label !=0) {
862
      set_label(proc_state.result_label);
2 7u83 863
#ifdef NEWDWARF
864
      if (dwarf2)
7 7u83 865
        dw2_return_pos(0);
2 7u83 866
#endif
7 7u83 867
      ret_restore_ins();
2 7u83 868
    }
7 7u83 869
#endif
2 7u83 870
#ifdef NEWDWARF
871
    if (dwarf2)
7 7u83 872
      dw2_complete_fde();
873
#endif
874
    proc_state = old_proc_state;
875
    return(mka);
2 7u83 876
}
877
 
878
 
879
 
880
/*
881
  ENCODE A PROCEDURE RESULT
882
*/
883
 
7 7u83 884
makeans make_res_tag_code
885
(exp e, space sp, where dest, int exitlab) {
886
  where w;
887
  makeans mka;
888
  mka.lab = exitlab;
889
  mka.regmove = NOREG;
890
  assert(name(e) == res_tag || name(e) == untidy_return_tag);
891
  w.answhere = proc_state.procans;
892
  w.ashwhere = ashof(sh(son(e)));
893
 (void)code_here(son(e), sp, w);
2 7u83 894
  assert(proc_state.rscope_level == 0);
895
				/* procedure return */
7 7u83 896
  switch (discrim(w.answhere)) {
897
    case notinreg: {
898
      instore isw;
899
      isw = insalt(w.answhere);
2 7u83 900
      /* [%fp+64] as per call convention */
7 7u83 901
      if (isw.adval == 0 && isw.b.base == R_FP &&
902
	   isw.b.offset == (16 * 4)) {
2 7u83 903
	/* struct or union result */
904
#ifdef NEWDWARF
905
	if (dwarf2)
7 7u83 906
	  dw2_return_pos(0);
2 7u83 907
#endif
7 7u83 908
	stret_restore_ins();
909
	break;
910
      }
2 7u83 911
	   /* FALL THROUGH */
912
    }
7 7u83 913
    default :
2 7u83 914
    {
915
      /* not struct or union result */
7 7u83 916
      if (proc_state.leaf_proc && name(e) == res_tag && !sysV_assembler
2 7u83 917
#ifdef NEWDIAGS
918
		&& !diag_visible) {
919
#else
920
		&& !diagnose) {
921
#endif
922
	/* Use only one return per proc, as this is necessary
923
	   for the peep-hole assembler 'as -O' to recognise
924
	   leaf procs (not applicable in SunOS
925
	   5 assembler).  Empirical tests show that using last
926
	   return is very slightly faster for SPECint tests
927
		- but beware of confusing diagnostic info */
7 7u83 928
	if (proc_state.result_label == 0) {
2 7u83 929
	  /* first return in proc, generate return */
7 7u83 930
	  proc_state.result_label = new_label();
2 7u83 931
	  /* first return in a leaf proc is ret_restore,
932
	     others branch here */
933
#if RET_IN_CODE
7 7u83 934
	  set_label(proc_state.result_label);
2 7u83 935
	  {
936
	    baseoff b;
937
	    b.base = R_FP;
938
#if 0
7 7u83 939
	    if (Has_vcallees) {
2 7u83 940
	      baseoff b;
941
	      b.base = R_FP;
942
	      b.offset = -4 * PTR_SZ>>3;
943
	      ld_ro_ins(i_ld,b,local_reg);
944
	    }
945
#endif
946
	  }
947
#ifdef NEWDWARF
948
	  if (dwarf2)
7 7u83 949
	    dw2_return_pos(0);
2 7u83 950
#endif
7 7u83 951
	  if (name(e) == res_tag) {
952
	    ret_restore_ins();
2 7u83 953
	  }
954
	  else {
7 7u83 955
	    fprintf(as_file, "\t%s\n", i_ret);
2 7u83 956
#ifdef NEWDWARF
957
	    if (dwarf2)
958
	      count_ins(1);
959
#endif
960
	    rir_ins(i_restore,R_SP,-proc_state.maxargs>>3,R_SP);
961
	  }
7 7u83 962
 
2 7u83 963
#else
7 7u83 964
	  uncond_ins(i_b, proc_state.result_label);
2 7u83 965
#endif
7 7u83 966
	}
2 7u83 967
	else {
968
	  /* jump to the return for this proc */
7 7u83 969
	  uncond_ins(i_b, proc_state.result_label);
2 7u83 970
	}
7 7u83 971
      }
2 7u83 972
      else {
973
	baseoff b;
974
	b.base = R_FP;
975
#if 0
7 7u83 976
	if (Has_vcallees) {
2 7u83 977
	  baseoff b;
978
	  b.base = R_FP;
979
	  b.offset = -4 * PTR_SZ>>3;
980
	  ld_ro_ins(i_ld,b,local_reg);
981
	}
982
#endif
983
	/* return here, avoiding cost of branch to return */
984
#ifdef NEWDWARF
985
	if (dwarf2)
7 7u83 986
	  dw2_return_pos(0);
2 7u83 987
#endif
7 7u83 988
	if (name(e) == res_tag) {
989
	  ret_restore_ins();
2 7u83 990
	}
991
	else {
7 7u83 992
	  fprintf(as_file, "\t%s\n", i_ret);
2 7u83 993
#ifdef NEWDWARF
994
	  if (dwarf2)
995
	    count_ins(1);
996
#endif
997
	  rir_ins(i_restore,R_SP,-proc_state.maxargs>>3,R_SP);
998
	  /*fprintf ( as_file, "\t%s,\%sp,0,\%sp\n", i_restore ) ;*/
999
	}
1000
	/*      ret_restore_ins () ;*/
1001
      }
1002
    }
1003
  }
1004
  /* regs invalid after return (what about inlining?) */
7 7u83 1005
  clear_all();
1006
  return(mka);
2 7u83 1007
}
1008
 
1009
 
1010
/*
1011
  ENCODE A PROCEDURE CALL
1012
*/
7 7u83 1013
extern int reg_result(shape);
2 7u83 1014
 
7 7u83 1015
makeans make_apply_tag_code
1016
(exp e, space sp, where dest, int exitlab) {
1017
  exp fn = son(e);
1018
  exp par = bro(fn);
1019
  exp list = par;
1020
  int hda = (int)name(sh(e));
1021
  int special;
2 7u83 1022
  int param_reg = R_O0 ;	 /* next param reg to use */
1023
  int param_regs_used ;	 /* how many were used */
7 7u83 1024
  ash ansash;
1025
  space nsp;
1026
  int void_result = ((name(sh(e)) == tophd) ||
1027
		    (name(sh(e)) == bothd));
1028
 
1029
  int reg_res = reg_result(sh(e));
2 7u83 1030
  int guarded_dest_reg = R_NO_REG ;/* reg used to address tuple result */
7 7u83 1031
  makeans mka;
2 7u83 1032
 
7 7u83 1033
  exp dad = father(e);
1034
  bool tlrecurse = (bool)(proc_state.rscope_level == 0 &&
1035
			      name(dad) == res_tag && props(dad));
2 7u83 1036
 
7 7u83 1037
  nsp = sp;
2 7u83 1038
 
7 7u83 1039
  mka.lab = exitlab;
1040
  mka.regmove = NOREG;
1041
  assert(name(e) == apply_tag);
2 7u83 1042
 
1043
  /* first see if it is a special to be handled inline */
7 7u83 1044
  if ((special = specialfn(fn)) > 0) {
2 7u83 1045
    /* eg function is strlen */
7 7u83 1046
    mka.lab = specialmake(special, list, sp, dest, exitlab);
1047
    return(mka);
2 7u83 1048
  }
1049
 
7 7u83 1050
  ansash = ashof(sh(e));
2 7u83 1051
 
7 7u83 1052
  if (!reg_res && !void_result) {
1053
    /* structure or union result, address of space to [%sp+64]
2 7u83 1054
     must do this before evaluating args as dest may use param reg */
7 7u83 1055
    instore is;
1056
    baseoff stack_struct_ret_addr;
2 7u83 1057
 
1058
    /* [%sp+64] as per call convention */
7 7u83 1059
    stack_struct_ret_addr.base = R_SP;
1060
    stack_struct_ret_addr.offset = (16 * 4);
2 7u83 1061
 
7 7u83 1062
    assert(discrim(dest.answhere) == notinreg);
2 7u83 1063
    if(discrim(dest.answhere) != notinreg){	/* should be redundant */
1064
      is.b = mem_temp(0);
1065
      is.adval = 1;
1066
    }
1067
    else{
7 7u83 1068
      is = insalt(dest.answhere);
2 7u83 1069
    }
7 7u83 1070
    if (is.adval) {
2 7u83 1071
      /* generate address of dest */
7 7u83 1072
      if (IS_FIXREG(is.b.base)) {
1073
	if (is.b.offset == 0) {
1074
	  st_ro_ins(i_st, is.b.base, stack_struct_ret_addr);
1075
	}
2 7u83 1076
	else {
7 7u83 1077
	  rir_ins(i_add, is.b.base, is.b.offset, R_TMP);
1078
	  st_ro_ins(i_st, R_TMP, stack_struct_ret_addr);
2 7u83 1079
	}
1080
	guarded_dest_reg = is.b.base ;	/* can be guarded */
7 7u83 1081
      }
2 7u83 1082
      else {
7 7u83 1083
	set_ins(is.b, R_TMP);
1084
	st_ro_ins(i_st, R_TMP, stack_struct_ret_addr);
2 7u83 1085
      }
7 7u83 1086
    }
2 7u83 1087
    else {
1088
      /* load dest */
7 7u83 1089
      ld_ins(i_ld, is.b, R_TMP);
1090
      st_ro_ins(i_st, R_TMP, stack_struct_ret_addr);
2 7u83 1091
    }
1092
  }
1093
 
1094
 
1095
  /* evaluate params to param reg or stack */
7 7u83 1096
  if (!last(fn)) {
1097
    int param_offset = (16 + 1)* 32;
2 7u83 1098
    /* beyond reg window save area and hidden param of caller's frame */
1099
 
1100
    /* evaluate parameters in turn */
7 7u83 1101
    for (; ;) {
1102
      ash ap;
1103
      where w;
1104
      shape a = sh(list);
1105
      int hd = (int)name(a);
1106
      ap = ashof(a);
1107
      w.ashwhere = ap;
2 7u83 1108
 
1109
      if ( 0 /*struct_par*/ ) {
1110
	/* non-ABI construct being used - give stronger warning */
7 7u83 1111
	if (sysV_abi)fail("Structure parameter passed by value");
2 7u83 1112
      }
1113
 
7 7u83 1114
      if (is_floating(hd) && param_reg <= R_O5) {
2 7u83 1115
	/* Float point. Copy to stack as if stack parameter,
1116
	   then recover words as needed into fixed point regs */
7 7u83 1117
	instore is;
2 7u83 1118
	/* Locations we offer may not be aligned for doubles.  We
1119
	   assume 'move' can cope with this */
7 7u83 1120
	is.b.base = R_SP;
1121
	is.b.offset = param_offset >> 3;
1122
	is.adval = 1;
2 7u83 1123
 
7 7u83 1124
	setinsalt(w.answhere, is);
1125
	(void)code_here(list, nsp, w);
1126
	ld_ro_ins(i_ld, is.b, param_reg);
1127
	nsp = guardreg(param_reg, nsp);
1128
	param_reg++;
1129
	param_offset += 32;
2 7u83 1130
 
7 7u83 1131
	if (hd != shrealhd) {
2 7u83 1132
	  /* double */
7 7u83 1133
	  if (param_reg <= R_O5) {
2 7u83 1134
	    /* double whose second word can go in reg */
7 7u83 1135
	    is.b.offset += 4;
1136
	    ld_ro_ins(i_ld, is.b, param_reg);
1137
	    nsp = guardreg(param_reg, nsp);
1138
	    param_reg++;
2 7u83 1139
	  }
7 7u83 1140
	  param_offset += 32;
2 7u83 1141
	}
7 7u83 1142
      }
1143
      else if (valregable(sh(list)) && param_reg <= R_O5) {
2 7u83 1144
	/* fixed point parameter in a single reg */
7 7u83 1145
	nsp = guardreg(param_reg, nsp);
1146
	reg_operand_here(list, nsp, param_reg);
1147
	param_reg++;
1148
	param_offset += 32;
1149
      }
2 7u83 1150
      else {
1151
	/* stack parameter */
7 7u83 1152
	instore is;
2 7u83 1153
	/* Locations we offer may not be aligned for doubles.
1154
	   We assume 'move' can cope with this  */
7 7u83 1155
	is.b.base = R_SP;
1156
	is.b.offset = param_offset >> 3;
1157
	is.adval = 1;
1158
	if (valregable(sh(list)) &&
1159
	    (ap.ashsize == 8 || ap.ashsize == 16)) {
2 7u83 1160
	  /* Byte or 16bit scalar parameter - convert to integer.
1161
	     We must pass a full word to conform with SPARC ABI,
1162
	     so have to expand source to full word.  We do this
1163
	     by loading into a reg */
7 7u83 1164
	  int r = reg_operand(list, nsp);
1165
	  ans op;
1166
	  setregalt(op, r);
2 7u83 1167
	  /* round down to word boundary */
7 7u83 1168
	  is.b.offset &= ~0x3;
1169
	  ap.ashsize = ap.ashalign = 32;
1170
	  w.ashwhere = ap;
1171
	  setinsalt(w.answhere, is);
1172
	 (void)move(op, w, guardreg(r, nsp).fixed, 1);
1173
	}
2 7u83 1174
	else {
7 7u83 1175
	  setinsalt(w.answhere, is);
1176
	 (void)code_here(list, nsp, w);
2 7u83 1177
	}
7 7u83 1178
	param_offset = (int)(param_offset + ap.ashsize);
2 7u83 1179
      }
1180
 
7 7u83 1181
      if (last(list))break;
1182
      list = bro(list);
2 7u83 1183
    }
1184
  }
1185
 
7 7u83 1186
  assert(param_reg >= R_O0 && param_reg <= R_O5 + 1);
1187
  param_regs_used = param_reg - R_O0;
2 7u83 1188
 
7 7u83 1189
  if (special != 0) {
1190
    extj_special_ins(i_call, special_call_name(special),
1191
		       param_regs_used);
1192
  }
1193
  else if (name(fn) == name_tag &&
1194
	      name(son(fn)) == ident_tag &&
1195
	     (son(son(fn)) == nilexp ||
1196
		(name(son(son(fn))) == proc_tag ||
1197
		 name(son(son(fn))) == general_proc_tag))) {
1198
    baseoff b;
1199
    b = boff(son(fn));
1200
    if (!tlrecurse) {
2 7u83 1201
#ifdef NEWDWARF
1202
      if (current_dg_info) {
7 7u83 1203
	current_dg_info->data.i_call.brk = set_dw_text_label();
2 7u83 1204
	current_dg_info->data.i_call.p.k = WH_CODELAB;
1205
	current_dg_info->data.i_call.p.u.l = b.base;
1206
	current_dg_info->data.i_call.p.o = b.offset;
1207
      }
1208
#endif
7 7u83 1209
      extj_ins(i_call, b, param_regs_used);
1210
    }
2 7u83 1211
    else {
7 7u83 1212
      assert(!tlrecurse);
2 7u83 1213
    }
7 7u83 1214
  }
2 7u83 1215
  else {
7 7u83 1216
    int r = reg_operand(fn, nsp);
2 7u83 1217
#ifdef NEWDWARF
1218
    if (current_dg_info) {
7 7u83 1219
      current_dg_info->data.i_call.brk = set_dw_text_label();
2 7u83 1220
      current_dg_info->data.i_call.p.k = WH_REG;
1221
      current_dg_info->data.i_call.p.u.l = r;
1222
    }
1223
#endif
7 7u83 1224
    extj_reg_ins(i_call, r, param_regs_used);
2 7u83 1225
  }
1226
 
7 7u83 1227
  if (!reg_res && !void_result) {
2 7u83 1228
    /* Generate unimp instruction, as per structure result call
1229
       convention.  Argument is low-order 12 bits of structure size,
1230
       see section D.4 of * SPARC architecture manual */
7 7u83 1231
    unimp_ins((long)((ansash.ashsize / 8) & 0xfff));
2 7u83 1232
  }
1233
 
1234
#ifdef NEWDWARF
1235
  if (dwarf2)
7 7u83 1236
    START_BB();
2 7u83 1237
#endif
1238
 
1239
  /* grab clobbered %g and %o regs, as safety test for bad code */
1240
  {
7 7u83 1241
    int r;
1242
    space gsp;
1243
    gsp = sp;
2 7u83 1244
 
1245
    /* %g1..%g_reg_max, %o0..%o7 */
7 7u83 1246
    for (r = R_G1; r < R_O7 + 1;
1247
		     r = ((r == R_G0 + g_reg_max)? R_O0 : r + 1)) {
2 7u83 1248
      /* skip R_O0 as often used in result-reg optimisation */
7 7u83 1249
      if (!(r == R_TMP || r == R_O0 || r == R_SP ||
1250
	      r == guarded_dest_reg)) {
2 7u83 1251
	/* not special regs */
7 7u83 1252
	gsp = needreg(r, gsp);
2 7u83 1253
      }
1254
    }
1255
  }
1256
  clear_all () ;	/* ??? not %i0..%l7 that may be t-regs */
1257
 
7 7u83 1258
  if (reg_res) {
1259
    ans aa;
1260
    if (is_floating(hda)) {
1261
      freg frg;
1262
      frg.fr = 0;
1263
      frg.dble = (bool)(hda != shrealhd);
1264
      setfregalt(aa, frg);
2 7u83 1265
      /* move floating point result of application to destination */
7 7u83 1266
     (void)move(aa, dest, sp.fixed, 1);
1267
    }
2 7u83 1268
    else {
7 7u83 1269
      setregalt(aa, R_O0);
1270
      if (discrim(dest.answhere) == inreg) {
1271
	int r = regalt(dest.answhere);
1272
	if (r == R_G0) {
2 7u83 1273
	  /* void result */
1274
	}
7 7u83 1275
	else if (r != R_O0) {
2 7u83 1276
	  /* move result from %o0 */
7 7u83 1277
	 (void)move(aa, dest, sp.fixed, 1);
1278
	}
2 7u83 1279
	else {
1280
	  /* no move required */
1281
	}
7 7u83 1282
	mka.regmove = R_O0;
1283
      }
2 7u83 1284
      else {
7 7u83 1285
	(void)move(aa, dest, sp.fixed, 1);
2 7u83 1286
      }
1287
    }
7 7u83 1288
  }
2 7u83 1289
  else {
1290
    /* not register result */
1291
  }
7 7u83 1292
  return(mka);
2 7u83 1293
}
1294
 
1295
 
7 7u83 1296
static space do_callers
1297
(exp list, space sp, int* param_reg, bool trad_call) {
1298
  int param_offset = (16+1)*32; /* beyond reg window save area &
2 7u83 1299
				 hidden param of callers frame */
1300
  int last_reg;
1301
#ifdef GENCOMPAT
1302
  if (!trad_call) {
1303
#else
7 7u83 1304
  if (in_general_proc) {
2 7u83 1305
#endif
7 7u83 1306
    if (vc_call) {
2 7u83 1307
      last_reg = R_O3;
1308
    }
1309
    else {
1310
      last_reg = R_O4;
1311
    }
1312
  }
1313
  else {
1314
    last_reg = R_O5;
1315
  }
7 7u83 1316
 
1317
  for (;;) {
2 7u83 1318
    ash ap;
1319
    where w;
1320
    shape a = sh(list);
1321
    int hd = (int)name(a);
7 7u83 1322
    exp par = (name(list) == caller_tag)?son(list): list;
2 7u83 1323
    ap = ashof(a);
1324
    w.ashwhere = ap;
7 7u83 1325
    if (is_floating(hd) && *param_reg <= last_reg) {
2 7u83 1326
      /* floating pt.  Copy to stack as if stack param then recover
1327
	 into fixed point reg */
1328
      instore is;
1329
      is.b.base = R_SP;
1330
      is.b.offset = param_offset>>3;
1331
      is.adval = 1;
1332
      setinsalt(w.answhere,is);
7 7u83 1333
     (void)code_here(par, sp, w);
1334
      if (hd == doublehd) {
2 7u83 1335
	rir_ins(i_add,is.b.base,is.b.offset,*param_reg);
1336
      }
1337
      else {
7 7u83 1338
	ld_ro_ins(i_ld, is.b, *param_reg);
2 7u83 1339
      }
7 7u83 1340
      sp = guardreg(*param_reg, sp);
1341
     (*param_reg) ++;
1342
      param_offset += 32;
1343
      if (hd == realhd) {
2 7u83 1344
	/* double */
7 7u83 1345
	if (*param_reg <= last_reg) {
2 7u83 1346
	  /* double whose second word can go in reg */
7 7u83 1347
	  is.b.offset += 4;
1348
	  ld_ro_ins(i_ld, is.b, *param_reg);
1349
	  sp = guardreg(* param_reg, sp);
1350
	 (*param_reg) ++;
2 7u83 1351
	}
7 7u83 1352
	param_offset += 32;
2 7u83 1353
      }
7 7u83 1354
    }
1355
    else if (valregable(sh(list)) && *param_reg <= last_reg) {
2 7u83 1356
      /* fixed point parameter in a single reg */
7 7u83 1357
      sp = guardreg(*param_reg, sp);
1358
      reg_operand_here(list, sp, *param_reg);
1359
     (*param_reg) ++;
1360
      param_offset += 32;
1361
    }
2 7u83 1362
    else {
1363
      /* stack parameter */
7 7u83 1364
      instore is;
2 7u83 1365
      /* Locations we offer may not be aligned for doubles.
1366
	 We assume 'move' can cope with this  */
7 7u83 1367
      is.b.base = R_SP;
1368
      is.b.offset = param_offset >> 3;
1369
      is.adval = 1;
1370
      if (valregable(sh(list)) &&
1371
	  (ap.ashsize == 8 || ap.ashsize == 16)) {
2 7u83 1372
	/* Byte or 16bit scalar parameter - convert to integer.
1373
	   We must pass a full word to conform with SPARC ABI,
1374
	   so have to expand source to full word.  We do this
1375
	   by loading into a reg */
7 7u83 1376
	int r = reg_operand(list, sp);
1377
	ans op;
1378
	setregalt(op, r);
2 7u83 1379
	/* round down to word boundary */
7 7u83 1380
	is.b.offset &= ~0x3;
1381
	ap.ashsize = ap.ashalign = 32;
1382
	w.ashwhere = ap;
1383
	setinsalt(w.answhere, is);
1384
	(void)move(op, w, guardreg(r, sp).fixed, 1);
1385
      }
2 7u83 1386
      else{
7 7u83 1387
	setinsalt(w.answhere, is);
1388
	(void)code_here(par, sp, w);
2 7u83 1389
      }
7 7u83 1390
      if (*param_reg <= last_reg) {
2 7u83 1391
	/* Copy back into the correct param regs */
1392
	int start_offset = is.b.offset;
1393
	int block_size = w.ashwhere.ashsize;
1394
	baseoff curr_pos;
1395
	curr_pos.base = R_SP;
1396
	curr_pos.offset = start_offset;
7 7u83 1397
	if (is64(sh(list)) || (name(sh(list)) == cpdhd) ||
1398
	  (name(sh(list)) == nofhd)) {
2 7u83 1399
	  rir_ins(i_add,curr_pos.base,curr_pos.offset,*param_reg);
7 7u83 1400
	 (*param_reg) ++;
2 7u83 1401
	  block_size -=32;
1402
        }
1403
	else {
1404
	  while (*param_reg <= last_reg && block_size>0) {
1405
	    ld_ro_ins(i_ld,curr_pos,*param_reg);
7 7u83 1406
	    ++ (*param_reg);
2 7u83 1407
	    curr_pos.offset += 4;
1408
	    block_size -= 32;
1409
	  }
1410
	}
1411
      }
7 7u83 1412
      param_offset = (int)(param_offset + ap.ashsize);
2 7u83 1413
    }
7 7u83 1414
    if (last(list)) return sp;
1415
    list = bro(list);
2 7u83 1416
  }
1417
 
1418
  return sp;
1419
}
1420
 
1421
/*
1422
  Give the first parameter par_base, find parameter 'num'
1423
*/
7 7u83 1424
exp get_param
1425
(exp par_base, int num) {
2 7u83 1426
  exp res_exp = par_base;
1427
  int current_par;
7 7u83 1428
  if (num == 1) return par_base;
1429
  for (current_par = 2;current_par<=num;++current_par) {
2 7u83 1430
    res_exp = bro(res_exp);
1431
  }
1432
  return res_exp;
1433
}
1434
 
1435
 
7 7u83 1436
 
1437
 
2 7u83 1438
/*
1439
  Move the caller parameters up the stack from their current position
7 7u83 1440
  by %size_reg bytes.  The function assumes that there will always be at
2 7u83 1441
  least one parameter.
1442
*/
7 7u83 1443
static void move_parameters
1444
(exp callers, int size_reg, space sp) {
2 7u83 1445
  int param_offset;   /* offset of first parameter */
1446
  int newbase;
1447
  baseoff b;
1448
  int last_caller = 0;
1449
  int has_callers = 0;
1450
  exp current_caller = son(callers);
1451
  int rtmp = getreg(sp.fixed);
1452
  int rtop = getreg(guardreg(rtmp,sp).fixed);
1453
  int i;
7 7u83 1454
 
2 7u83 1455
  param_offset = 64;
7 7u83 1456
  for (i=0;i<no(callers);++i) {
2 7u83 1457
    if (shape_size(sh(current_caller)) > 32)
1458
      param_offset += 8;
1459
    else
1460
      param_offset += 4;
1461
    current_caller = bro(current_caller);
1462
  }
1463
  current_caller = son(callers);
1464
 
7 7u83 1465
 
2 7u83 1466
  /* top is sp + param_offset + callers * num */
7 7u83 1467
  while (!last_caller) {
2 7u83 1468
    last_caller = last(current_caller);
7 7u83 1469
    if (name(current_caller) == caller_tag) {
2 7u83 1470
      has_callers = 1;
1471
    }
1472
    current_caller = bro(current_caller);
1473
  }
1474
  current_caller = son(callers);
1475
  last_caller = 0;
1476
 
7 7u83 1477
  if (!has_callers) return;
2 7u83 1478
  rir_ins(i_add,R_SP,param_offset /*+ (no(callers))*/,rtop);
7 7u83 1479
 
1480
 
2 7u83 1481
  b.offset = param_offset;
1482
  b.offset = 0;
1483
  if (size_reg == R_NO_REG)
1484
    newbase = rtop;
1485
  else {
1486
    newbase = getreg(guardreg(rtop,sp).fixed);
1487
    rrr_ins(i_add,rtop,size_reg,newbase);
1488
  }
1489
  assert(current_caller != (exp)NULL);
1490
 
7 7u83 1491
  for (i=no(callers);i>0;--i) {
2 7u83 1492
    exp par = get_param(son(callers),i);
7 7u83 1493
    if (name(par) == caller_tag) {
2 7u83 1494
      /* move it up the stack */
1495
      b.base = rtop;
1496
      ld_ro_ins(i_ld,b,rtmp);
1497
      b.base = newbase;
1498
      st_ro_ins(i_st,rtmp,b);
7 7u83 1499
      if (shape_size(sh(par)) > 32) {
2 7u83 1500
	b.base = rtop;
1501
	b.offset = -4;
1502
	ld_ro_ins(i_ld,b,rtmp);
1503
	b.base = newbase;
1504
	st_ro_ins(i_st,rtmp,b);
1505
      }
1506
      b.offset -= 4;
1507
    }
1508
    else
1509
      b.offset -= (shape_size(sh(par)) > 32 ? 8 : 4);
1510
  }
1511
  return;
1512
}
1513
 
1514
 
7 7u83 1515
 
1516
makeans make_apply_general_tag_code
1517
(exp e, space sp, where dest, int exitlab) {
2 7u83 1518
  exp fn = son(e);
1519
  exp callers = bro(fn);
1520
  exp cllees = bro(callers);
1521
  exp postlude = bro(cllees);
1522
  int hda = (int)name(sh(e));
1523
  int param_reg = R_O0;
1524
  int param_regs_used;
1525
  ash ansash;
1526
  space nsp;
7 7u83 1527
  int void_result = ((name(sh(e)) == tophd) ||
1528
		    (name(sh(e)) == bothd));
1529
 
1530
  int reg_res = reg_result(sh(e));
2 7u83 1531
  int guarded_dest_reg = R_NO_REG; /* reg used to address tuple result */
7 7u83 1532
  makeans mka;
1533
  exp dad = father(e);
1534
  bool tlrecurse = (bool)(proc_state.rscope_level == 0 &&
1535
			      name(dad) == res_tag && props(dad));
2 7u83 1536
  bool trad_call = 0;
1537
  ansash = ashof(sh(e));
1538
  nsp = sp;
7 7u83 1539
  mka.lab = exitlab;
1540
  mka.regmove = NOREG;
1541
  if ((call_has_vcallees(cllees)!= 0)) {
1542
    outs("\t.optim\t\"-O0\"\n");
2 7u83 1543
  }
1544
 
1545
  param_regs_used = param_reg - R_O0;
1546
 
1547
#ifdef GENCOMPAT
7 7u83 1548
  if ((call_has_vcallees(cllees) == 0)) {
2 7u83 1549
    if (name(cllees) == make_callee_list_tag) {
1550
      if (no(cllees) == 0)
1551
	trad_call = 1;
1552
    }
1553
    else if (name(cllees) == make_dynamic_callee_tag) {
1554
      if (name(bro(son(cllees))) == val_tag && no(bro(son(cllees))) == 0)
1555
	trad_call = 1;
1556
    }
1557
    else {	/* same callees */
1558
      if (!May_have_callees)
1559
	trad_call = 1;
1560
    }
1561
  }
1562
#endif
1563
  if (!trad_call)
7 7u83 1564
   (void)make_code(cllees,nsp,nowhere,0);
2 7u83 1565
 
7 7u83 1566
  if (!reg_res && !void_result) {
2 7u83 1567
    /* structure result */
7 7u83 1568
        instore is;
1569
    baseoff stack_struct_ret_addr;
2 7u83 1570
 
1571
    /* [%sp+64] as per call convention */
7 7u83 1572
    stack_struct_ret_addr.base = R_SP;
1573
    stack_struct_ret_addr.offset = (16 * 4);
2 7u83 1574
 
7 7u83 1575
    assert(discrim(dest.answhere) == notinreg);
2 7u83 1576
    if(discrim(dest.answhere) != notinreg){	/* should be redundant */
1577
      discrim(dest.answhere) = notinreg;
1578
      is.b.base = R_SP;
1579
      is.b.offset = (4*16);
1580
      /* is.b = mem_temp(0);   not compatible with out_pars */
1581
      is.adval = 1;
1582
      dest.answhere.val.instoreans = is;
1583
    }
1584
    else{
7 7u83 1585
      is = insalt(dest.answhere);
2 7u83 1586
    }
7 7u83 1587
    if (is.adval) {
2 7u83 1588
      /* generate address of dest */
7 7u83 1589
      if (IS_FIXREG(is.b.base)) {
1590
	if (is.b.offset == 0) {
1591
	  st_ro_ins(i_st, is.b.base, stack_struct_ret_addr);
1592
	}
2 7u83 1593
	else {
7 7u83 1594
	  rir_ins(i_add, is.b.base, is.b.offset, R_TMP);
1595
	  st_ro_ins(i_st, R_TMP, stack_struct_ret_addr);
2 7u83 1596
	}
1597
	guarded_dest_reg = is.b.base ;	/* can be guarded */
7 7u83 1598
      }
2 7u83 1599
      else {
7 7u83 1600
	set_ins(is.b, R_TMP);
1601
	st_ro_ins(i_st, R_TMP, stack_struct_ret_addr);
2 7u83 1602
      }
7 7u83 1603
    }
2 7u83 1604
    else {
1605
      /* load dest */
7 7u83 1606
      ld_ins(i_ld, is.b, R_TMP);
1607
      st_ro_ins(i_st, R_TMP, stack_struct_ret_addr);
2 7u83 1608
    }
1609
  }
1610
 
1611
 
1612
#ifdef GENCOMPAT
1613
  if (!trad_call)
1614
#endif
1615
  {
7 7u83 1616
    /*rr_ins(i_mov,callee_start_reg,R_O5);*/
2 7u83 1617
    nsp = guardreg(R_O5,nsp);
7 7u83 1618
    if (call_has_vcallees(cllees)) {
2 7u83 1619
      /*rr_ins(i_mov,callee_end_reg,R_O4);*/
1620
      nsp = guardreg(R_O4,nsp);
1621
    }
1622
  }
1623
 
7 7u83 1624
  if (no(callers)!= 0) {
2 7u83 1625
    int tmp = in_general_proc;
1626
    in_general_proc = 1;
1627
    vc_call = (call_has_vcallees(cllees)!=0);
1628
    nsp = do_callers(son(callers),nsp,&param_reg, trad_call);
1629
    vc_call = 0;
1630
    in_general_proc = tmp;
1631
  }
1632
  call_base_reg = R_SP;
7 7u83 1633
 
1634
  if (name(fn) == name_tag && name(son(fn)) == ident_tag &&
1635
      (son(son(fn)) == nilexp ||
1636
	(name(son(son(fn))) == proc_tag ||
1637
	  name(son(son(fn))) == general_proc_tag))) {
2 7u83 1638
    baseoff b;
1639
    b = boff(son(fn));
7 7u83 1640
    if (!tlrecurse) {
2 7u83 1641
      /* don't tell the assembler how many parameters are being used, as
1642
	 it optimises away changes to "unused" parameter registers which,
1643
	 in general procs, are needed to pass callees.
1644
	 */
1645
#ifdef NEWDWARF
1646
      if (current_dg_info) {
7 7u83 1647
	current_dg_info->data.i_call.brk = set_dw_text_label();
2 7u83 1648
	current_dg_info->data.i_call.p.k = WH_CODELAB;
1649
	current_dg_info->data.i_call.p.u.l = b.base;
1650
	current_dg_info->data.i_call.p.o = b.offset;
1651
      }
1652
#endif
1653
      extj_ins(i_call,b,-1 /*param_regs_used*/);
1654
    }
1655
    else{
1656
      assert(!tlrecurse);
1657
    }
1658
  }
1659
  else{
1660
    int r = reg_operand(fn,nsp);
1661
#ifdef NEWDWARF
1662
    if (current_dg_info) {
7 7u83 1663
      current_dg_info->data.i_call.brk = set_dw_text_label();
2 7u83 1664
      current_dg_info->data.i_call.p.k = WH_REG;
1665
      current_dg_info->data.i_call.p.u.l = r;
1666
    }
1667
#endif
1668
    extj_reg_ins(i_call,r,-1 /*param_regs_used*/);
1669
  }
7 7u83 1670
  if (!reg_res && !void_result) {
2 7u83 1671
    /* Generate unimp instruction, as per structure result call
1672
	   convention.  Argument is low-order 12 bits of structure size,
1673
	   see section D.4 of * SPARC architecture manual */
7 7u83 1674
    unimp_ins((long)((ansash.ashsize / 8) & 0xfff));
2 7u83 1675
  }
1676
 
1677
#ifdef NEWDWARF
1678
  if (dwarf2)
7 7u83 1679
    START_BB();
2 7u83 1680
#endif
1681
 
1682
  /* free the space used to generate the callee parameters and, if in
7 7u83 1683
     a postlude, move the caller outpars up the stack to a correct parameter
2 7u83 1684
     offset from the new stack pointer */
1685
 
1686
  clear_all();
1687
  {
1688
    int size_reg;
1689
    space nsp;
1690
    nsp = guardreg(R_O0,sp);
1691
#ifdef GENCOMPAT
1692
    if (trad_call)
1693
      size_reg = R_NO_REG;
1694
    else
1695
#endif
1696
    {
7 7u83 1697
      if (name(cllees) == make_callee_list_tag) {
2 7u83 1698
	size_reg = getreg(nsp.fixed);
7 7u83 1699
	ir_ins(i_mov,((no(cllees) >>3) +23) &~7,size_reg);
2 7u83 1700
      }
7 7u83 1701
      else if (name(cllees) == make_dynamic_callee_tag) {
2 7u83 1702
	size_reg = reg_operand(bro(son(cllees)),nsp);
7 7u83 1703
	rir_ins(i_add,size_reg,4*(PTR_SZ>>3) +7,size_reg);
2 7u83 1704
	rir_ins(i_and,size_reg,~7,size_reg);
1705
      }
1706
      else {	/* same callees */
1707
	size_reg = getreg(nsp.fixed);
7 7u83 1708
	if (Has_vcallees) {
2 7u83 1709
	  rrr_ins(i_sub,callee_end_reg,callee_start_reg,size_reg);
1710
	}
1711
	else {
1712
	  ir_ins(i_mov,proc_state.callee_size/8,size_reg);
1713
	}
1714
      }
1715
      nsp = guardreg(size_reg,nsp);
1716
    }
1717
    if(no(callers)/* && (in_postlude || postlude_has_call(e))*/) {
7 7u83 1718
      move_parameters(callers,size_reg,nsp); /* move all outpars into
2 7u83 1719
						    correct positions */
1720
    }
7 7u83 1721
    if (!call_is_untidy(cllees) && size_reg != R_NO_REG) {
1722
      if (!sysV_assembler) {
2 7u83 1723
	/* with -O2 SunOS removes [add %sp,X,%sp] statements. */
7 7u83 1724
	outs("\t.optim\t\"-O0\"\n");
2 7u83 1725
      }
1726
      rrr_ins(i_add,R_SP,size_reg,R_SP);
1727
    }
1728
  }
1729
 
7 7u83 1730
 
1731
 
2 7u83 1732
  /* grab clobbered %g and %o regs, as safety test for bad code */
1733
  {
7 7u83 1734
    int r;
1735
    space gsp;
1736
    gsp = sp;
2 7u83 1737
 
1738
    /* %g1..%g_reg_max, %o0..%o7 */
7 7u83 1739
    for (r = R_G1; r < R_O7 + 1;
1740
		     r = ((r == R_G0 + g_reg_max)? R_O0 : r + 1)) {
2 7u83 1741
      /* skip R_O0 as often used in result-reg optimisation */
7 7u83 1742
      if (!(r == R_TMP || r == R_O0 || r == R_SP ||
1743
	      r == guarded_dest_reg)) {
2 7u83 1744
	/* not special regs */
7 7u83 1745
	gsp = needreg(r, gsp);
2 7u83 1746
      }
1747
    }
1748
  }
1749
  clear_all () ;	/* ??? not %i0..%l7 that may be t-regs */
1750
 
7 7u83 1751
  if (reg_res) {
1752
    ans aa;
1753
    if (is_floating(hda)) {
1754
      freg frg;
1755
      frg.fr = 0;
1756
      frg.dble = (bool)(hda != shrealhd);
1757
      setfregalt(aa, frg);
2 7u83 1758
      /* move floating point result of application to destination */
7 7u83 1759
     (void)move(aa, dest, sp.fixed, 1);
2 7u83 1760
    } else {
7 7u83 1761
      setregalt(aa, R_O0);
1762
      if (discrim(dest.answhere) == inreg) {
1763
	int r = regalt(dest.answhere);
1764
	if (r == R_G0) {
2 7u83 1765
	  /* void result */
7 7u83 1766
	}
1767
	else if (r != R_O0) {
2 7u83 1768
	  /* move result from %o0 */
7 7u83 1769
	 (void)move(aa, dest, sp.fixed, 1);
1770
	}
2 7u83 1771
	else {
1772
	  /* no move required */
7 7u83 1773
	  assert(name(postlude) == top_tag);
2 7u83 1774
	}
7 7u83 1775
	mka.regmove = R_O0;
1776
      }
2 7u83 1777
      else {
7 7u83 1778
	(void)move(aa, dest, sp.fixed, 1);
2 7u83 1779
      }
1780
    }
7 7u83 1781
  }
2 7u83 1782
  else {
1783
    /* not register result */
1784
  }
1785
#if 0
7 7u83 1786
  if (Has_vcallees) {
2 7u83 1787
    baseoff b;
1788
    b.base = R_FP;
7 7u83 1789
    b.offset = -3 *(PTR_SZ>>3);
2 7u83 1790
    ld_ro_ins(i_ld,b,local_reg);
1791
  }
1792
#endif
7 7u83 1793
 
1794
  if (call_is_untidy(cllees)) {
2 7u83 1795
    /*    rir_ins(i_sub,R_SP,proc_state.maxargs>>3,R_SP);*/
1796
    /*assert(name(bro(cllees)) == top_tag);*/
1797
  }
7 7u83 1798
  else if (postlude_has_call(e)) {
2 7u83 1799
    exp x = son(callers);
1800
    postlude_chain p;
7 7u83 1801
 
2 7u83 1802
    if (x != nilexp) {
7 7u83 1803
      for (;;) {
1804
	if (name(x) == caller_tag) {
2 7u83 1805
	  no(x) += proc_state.maxargs;
1806
#if 0
7 7u83 1807
	  if (name(sh(x)) == realhd) {
2 7u83 1808
	    no(x) -=32;
1809
	  }
1810
#endif
1811
	}
7 7u83 1812
	if (last(x))break;
2 7u83 1813
	x = bro(x);
1814
      }
1815
    }
1816
    mka.regmove = NOREG;
1817
    update_plc(old_postludes,proc_state.maxargs);
1818
    p.postlude = postlude;
1819
    p.outer = old_postludes;
1820
    old_postludes = &p;
1821
    rir_ins(i_sub,R_SP,proc_state.maxargs>>3,R_SP);
1822
 
1823
    in_postlude = 1;
7 7u83 1824
   (void)make_code(postlude,sp,nowhere,0);
2 7u83 1825
    in_postlude = 0;
1826
    rir_ins(i_add,R_SP,proc_state.maxargs>>3,R_SP);
1827
    old_postludes = p.outer;
1828
    update_plc(old_postludes,-proc_state.maxargs);
1829
  }
1830
  else {
7 7u83 1831
   (void)make_code(postlude,sp,nowhere,0);
2 7u83 1832
  }
1833
 
1834
  return mka;
1835
}
1836
 
1837
 
1838
/*
1839
  Allocate an amount of space on the stack corresponding to the value
1840
  held in register size_reg, and store a pointer to the resulting area
1841
  in register ptr_reg.
1842
*/
7 7u83 1843
static void alloc_reg_space
1844
(int size_reg, int ptr_reg) {
1845
 
2 7u83 1846
  int maxargbytes = (int)proc_state.maxargs/8;
7 7u83 1847
  rir_ins(i_add,size_reg,7,R_TMP);
2 7u83 1848
  rir_ins(i_and,R_TMP,~7,R_TMP);      /* make the size a multiple of 8 */
1849
  rrr_ins(i_sub,R_SP,R_TMP,R_SP);
1850
  rir_ins(i_add,R_SP,maxargbytes,ptr_reg);
1851
  return;
1852
}
1853
 
7 7u83 1854
 
1855
/*
2 7u83 1856
   As alloc_reg_space, but with a constant size.
1857
*/
7 7u83 1858
static void alloc_space
1859
(int size, int ptr_reg) {
2 7u83 1860
  int maxargbytes = (int)proc_state.maxargs/8;
7 7u83 1861
  size = (size+7) &~7;
2 7u83 1862
  rir_ins(i_sub,R_SP,size,R_SP);
1863
  rir_ins(i_add,R_SP,maxargbytes,ptr_reg);
1864
  return;
1865
}
1866
 
1867
 
7 7u83 1868
makeans make_make_callee_list_tag
1869
(exp e, space sp, where dest, int exitlab) {
1870
  int size = ((no(e) >>3) + 23) &~7;
2 7u83 1871
  makeans mka;
1872
  bool vc = call_has_vcallees(e);
1873
  exp list = son(e);
1874
  where w;
1875
  instore is;
1876
  baseoff b;
1877
  int disp = 0;
1878
  ash ap;
1879
  space nsp;
1880
  int rdest;
7 7u83 1881
 
2 7u83 1882
  nsp = guardreg(R_O5,sp);
1883
  nsp = guardreg(R_O4,nsp);
1884
  mka.regmove = R_G0;
1885
  mka.lab = 0;
1886
  /* perform an alloca */
1887
  call_base_reg = getreg((nsp.fixed|PARAM_TREGS));
1888
  nsp = guardreg(call_base_reg,nsp);
1889
  rr_ins(i_mov,R_SP,call_base_reg);
1890
  rdest  = getreg(nsp.fixed);
1891
  nsp = guardreg(rdest,nsp);
1892
  alloc_space(size,rdest); /* */
7 7u83 1893
 
2 7u83 1894
  b.base = rdest;
1895
  b.offset = size - (PTR_SZ>>3);
1896
  st_ro_ins(i_st,R_FP,b);
7 7u83 1897
  if (no(e)) {
2 7u83 1898
    int lastpar = 0;
7 7u83 1899
    for (;!lastpar;list = bro(list)) {
2 7u83 1900
      ap = ashof(sh(list));
1901
      disp = rounder(disp,ap.ashalign);
1902
      is.b.offset = disp>>3;
1903
      is.b.base = rdest;
1904
      is.adval = 1;
1905
      w.ashwhere = ap;
1906
      setinsalt(w.answhere,is);
1907
      code_here(list,guard(w,nsp),w);
1908
      disp = rounder(disp+ap.ashsize,PTR_SZ);
1909
      lastpar = last(list);
1910
    }
1911
  }
7 7u83 1912
  rr_ins(i_mov,rdest,callee_start_reg_out);/* Not before, as the construction
1913
					      of the callees may require that
1914
					      we access some of the old
2 7u83 1915
					      callees */
7 7u83 1916
  if (vc) {
2 7u83 1917
    rir_ins(i_add,callee_start_reg_out,size,callee_end_reg_out);
1918
    /*rir_ins(i_add,R_FP,size,R_FP);*/
1919
  }
1920
  return mka;
1921
}
1922
 
1923
 
7 7u83 1924
 
2 7u83 1925
/*
1926
  Construct a copy of the current callees for use in a new procedure
7 7u83 1927
  call.  This writes the callee pointer(s) to the output registers o4 and
2 7u83 1928
  o5, so a tail call will have to copy back to i4,i5.
1929
*/
7 7u83 1930
makeans make_same_callees_tag
1931
(exp e, space sp, where dest, int exitlab) {
2 7u83 1932
  baseoff b;
1933
  bool vc = call_has_vcallees(e);
1934
  makeans mka;
1935
  space nsp;
1936
  mka.regmove = R_G0;
7 7u83 1937
  if (Has_vcallees) {
2 7u83 1938
    /* copy from [callee_start_reg ... callee_end_reg] into newly allocated
1939
       area, then set callee_start reg to start of area and, if the call
1940
       also has vcallees, set callee_end_reg to the end of the area.
1941
       */
7 7u83 1942
    int rsize; /* register to contain the size of the
2 7u83 1943
				     callee parameters area */
7 7u83 1944
    int rsrc,rdest;               /* registers containing pointers to where
2 7u83 1945
				     to copy from and to */
1946
    int rtmp;                     /* temporary register used in copying */
7 7u83 1947
 
2 7u83 1948
    int end_copy_lab = new_label();   /* marks end of copy loop */
1949
    int start_copy_lab = new_label(); /* marks start of copy loop */
1950
    nsp = guardreg(R_O4,sp);
1951
    nsp = guardreg(R_O5,nsp);
1952
    call_base_reg = getreg((nsp.fixed|PARAM_TREGS));
1953
    nsp = guardreg(call_base_reg,sp);
1954
    rsize = getreg(nsp.fixed);
1955
    nsp = guardreg(rsize,sp);
1956
    rsrc = getreg(nsp.fixed);
1957
    nsp = guardreg(rsrc,nsp);
1958
    rdest = getreg(nsp.fixed);
1959
    nsp = guardreg(rdest,nsp);
1960
    rrr_ins(i_sub,callee_end_reg,callee_start_reg,rsize);
1961
    rr_ins(i_mov,R_SP,call_base_reg);
1962
    alloc_reg_space(rsize,rdest); /* */
1963
    rrr_ins(i_add,rdest,rsize,rdest);
7 7u83 1964
 
2 7u83 1965
    /* now do top-down copy of parameters */
1966
    rir_ins(i_sub,callee_end_reg, 4*(PTR_SZ>>3), rsrc);
1967
    rir_ins(i_sub,rdest, 4*(PTR_SZ>>3), rdest);
1968
    /*condrr_ins(i_be,rdest,rsrc,end_copy_lab);*/
1969
    set_label(start_copy_lab);
1970
    b.base = rsrc;
7 7u83 1971
    b.offset = - (PTR_SZ>>3);
2 7u83 1972
    rtmp = getreg(nsp.fixed);
1973
    ld_ro_ins(i_ld,b,rtmp);
1974
    b.base = rdest;
1975
    st_ro_ins(i_st,rtmp,b);
1976
    rir_ins(i_sub,rsrc,PTR_SZ>>3,rsrc);
1977
    rir_ins(i_sub,rdest,PTR_SZ>>3,rdest);
1978
    condrr_ins(i_bne,rsrc,callee_start_reg,start_copy_lab);
1979
    set_label(end_copy_lab);
1980
    /* callee_start_reg will now be rdest */
1981
    rr_ins(i_mov,rdest,callee_start_reg_out);
7 7u83 1982
 
1983
    if (vc) {
2 7u83 1984
      rrr_ins(i_add,callee_start_reg_out,rsize,callee_end_reg_out);
1985
    }
1986
  }
1987
  else {
1988
    int size_of_callees = proc_state.callee_size/8;
1989
    int rdest;
1990
    int el;
1991
    int rsrc;
1992
    space nsp;
7 7u83 1993
    int tmpreg;
2 7u83 1994
    nsp = guardreg(R_O4,sp);
1995
    nsp = guardreg(R_O5,nsp);
1996
    call_base_reg = getreg((nsp.fixed|PARAM_TREGS));
1997
    nsp = guardreg(call_base_reg,sp);
1998
    rdest = getreg(nsp.fixed);
1999
    nsp = guardreg(rdest,sp);
2000
    tmpreg = getreg(nsp.fixed);
2001
    nsp = guardreg(tmpreg,nsp);
2002
    rr_ins(i_mov,R_SP,call_base_reg);
2003
    alloc_space(size_of_callees,rdest); /* */
2004
    b.base = rdest;
2005
    b.offset = size_of_callees - (PTR_SZ>>3);
2006
    st_ro_ins(i_st,R_FP,b);
2007
    rsrc = getreg(nsp.fixed);
2008
    rir_ins(i_add,callee_start_reg,size_of_callees,rsrc);
2009
    /*rir_ins(i_add,rdest,size_of_callees,rdest);*/
7 7u83 2010
    for (el= (size_of_callees-4*(PTR_SZ>>3));el>0;el-= (PTR_SZ>>3)) {
2 7u83 2011
      b.base = rsrc;
2012
      b.offset = el - size_of_callees - (PTR_SZ>>3);
2013
      ld_ro_ins(i_ld,b,tmpreg);
2014
      b.base = rdest;
2015
      b.offset = el - (PTR_SZ>>3);
2016
      st_ro_ins(i_st,tmpreg,b);
2017
    }
2018
    /* callee_start_reg will no be rdest */
7 7u83 2019
    if (vc) {
2 7u83 2020
      rir_ins(i_add,rdest,size_of_callees,callee_end_reg_out);
2021
      /*rr_ins(i_mov,rdest,callee_end_reg_out);*/
2022
    }
2023
    rr_ins(i_mov,rdest,callee_start_reg_out);
2024
    /*rir_ins(i_sub,rdest,size_of_callees,callee_start_reg_out);*/
2025
  }
2026
  return mka;
2027
}
2028
 
2029
 
7 7u83 2030
/*
2 7u83 2031
   Produce code to dynamically construct a new set of callee params.  The
7 7u83 2032
   parameters are placed in a specially allocated piece of the current stack,
2 7u83 2033
   and pointed to by callee_start_reg and callee_end_reg.
2034
*/
7 7u83 2035
makeans make_make_dynamic_callee_tag
2036
(exp e, space sp, where dest, int exitlab) {
2 7u83 2037
  /* bool vc = call_has_vcallees(e); */
2038
  int rptr,rsize,rdest,r_true_size;
2039
  int copy_start_lab = new_label();
2040
  int copy_end_lab = new_label();
2041
  space nsp;
2042
  baseoff b;
2043
  makeans mka;
2044
  mka.regmove = R_G0;
2045
  mka.lab = exitlab;
2046
  nsp = guardreg(R_O5,sp);
2047
  nsp = guardreg(R_O4,nsp);
2048
  call_base_reg = getreg((nsp.fixed|PARAM_TREGS));
2049
  nsp = guardreg(call_base_reg,nsp);
2050
  rptr = getreg(nsp.fixed);
2051
  nsp = guardreg(rptr,nsp);
2052
  load_reg(son(e),rptr,nsp);    /* rptr now contains a pointer to the start of
2053
			       the callees */
2054
  rsize = getreg(nsp.fixed);
2055
  nsp = guardreg(rsize,nsp);
7 7u83 2056
  load_reg(bro(son(e)),rsize,nsp); /* rsize now contains the size of the
2 7u83 2057
				      callees */
2058
  rdest = getreg(nsp.fixed);
2059
  nsp = guardreg(rdest,nsp);
2060
  r_true_size = getreg(nsp.fixed);
2061
  nsp = guardreg(r_true_size,nsp);
2062
  /*rdest = callee_start_reg_out;*/ /*getreg(nsp.fixed);*/
7 7u83 2063
  rir_ins(i_add,rsize,4*(PTR_SZ>>3) +7,r_true_size);
2 7u83 2064
  rir_ins(i_and,r_true_size,~7,r_true_size);
2065
  rr_ins(i_mov,R_SP,call_base_reg);
7 7u83 2066
 
2 7u83 2067
  alloc_reg_space(r_true_size,rdest); /* */
2068
  rrr_ins(i_add,rdest,r_true_size /*rsize*/,R_TMP);
2069
  /*rrr_ins(i_sub,rdest,r_true_size,rdest);*/
2070
  b.base = R_TMP;
7 7u83 2071
  b.offset = - (PTR_SZ>>3);
2 7u83 2072
  st_ro_ins(i_st,R_FP,b);
2073
  rr_ins(i_mov,rdest,callee_start_reg_out);
2074
  /*if(vc)*/ rr_ins(i_mov,R_TMP,callee_end_reg_out);
7 7u83 2075
 
2 7u83 2076
  /* Now copy from rptr to rdest */
2077
  condrr_ins(i_ble,rsize,R_G0,copy_end_lab);  /* make shure size > 0 */
2078
  b.offset = 0;
2079
  set_label(copy_start_lab);
2080
  b.base = rptr;
2081
  ld_ro_ins(i_ld,b,R_TMP);
2082
  b.base = rdest;
2083
  st_ro_ins(i_st,R_TMP,b);
2084
  rir_ins(i_add,rptr,PTR_SZ>>3,rptr);
2085
  rir_ins(i_add,rdest,PTR_SZ>>3,rdest);
2086
  rir_ins(i_sub,rsize,PTR_SZ>>3,rsize);
2087
  condrr_ins(i_bgt,rsize,R_G0,copy_start_lab);
2088
  set_label(copy_end_lab);
2089
  return mka;
2090
}
2091
 
7 7u83 2092
 
2093
 
2094
 
2 7u83 2095
/*
7 7u83 2096
  This generates code for a tail_call tag.  The target of the call MUST be
2 7u83 2097
  a general proc.
2098
*/
7 7u83 2099
makeans make_tail_call_tag
2100
(exp e, space sp, where dest, int exitlab) {
2 7u83 2101
  exp fn = son(e);
2102
  exp cllees = bro(fn);
2103
  exp bdy = son(current_proc);
2104
  space nsp;
2105
  bool vc = call_has_vcallees(cllees);
2106
  int callee_size = proc_state.callee_size;
2107
  makeans mka;
2108
  baseoff bproc;
2109
  bool glob = ((name(fn) == name_tag) && (name(son(fn)) == ident_tag) &&
7 7u83 2110
	      ((son(son(fn)) == nilexp) || (name(son(son(fn))) == proc_tag)
2 7u83 2111
		|| (name(son(son(fn))) == general_proc_tag)));
2112
  bool trad_proc = 0;
2113
#ifdef GENCOMPAT
2114
  if (!vc) {
2115
    if (name(cllees) == make_callee_list_tag) {
2116
      if (no(cllees) == 0)
2117
	trad_proc = 1;
2118
    }
2119
    else if (name(cllees) == make_dynamic_callee_tag) {
2120
      if (name(bro(son(cllees))) == val_tag && no(bro(son(cllees))) == 0)
2121
	trad_proc = 1;
2122
    }
2123
    else {	/* same callees */
2124
      if (!May_have_callees)
2125
	trad_proc = 1;
2126
    }
2127
  }
2128
#endif
2129
 
2130
  mka.lab = exitlab;
2131
  mka.regmove = R_G0;
2132
  nsp = sp;
2133
  nsp.fixed |= PARAM_TREGS;
7 7u83 2134
  if (name(cllees)!= same_callees_tag) {
2 7u83 2135
    code_here(cllees,sp,nowhere);
2136
  }
2137
#ifndef NEWDIAGS
7 7u83 2138
  for (;name(bdy) == diagnose_tag;bdy=son(bdy));
2 7u83 2139
#endif
2140
 
7 7u83 2141
  while (name(bdy) == ident_tag && isparam(bdy)) {
2 7u83 2142
    exp sbdy = son(bdy);
2143
    baseoff b;
2144
    b.base = R_FP;
7 7u83 2145
    b.offset = (no(sbdy) >>3) + (proc_state.params_offset>>3);
2 7u83 2146
 
2147
    if (name(sbdy) == formal_callee_tag) {
7 7u83 2148
      if ((props(bdy) & inanyreg)!=0) {
2 7u83 2149
	b.offset -= (proc_state.callee_size>>3);
7 7u83 2150
	if (isvar(bdy)) {
2151
	  if (is_floating(name(sh(bdy)))) {
2 7u83 2152
	    stf_ins(i_st,no(bdy)<<1,b); 	/* add case for long double */
2153
	  }
2154
	  else {
2155
	    st_ro_ins(i_st,no(bdy),b);
2156
	  }
2157
	}
2158
      }
2159
    }
7 7u83 2160
    else if (props(sbdy) == 0 && ((props(bdy) & inanyreg)!=0)) {
2 7u83 2161
      /* move from reg to store */
7 7u83 2162
      if (isvar(bdy)) {
2163
	if (is_floating(name(sh(sbdy)))) {
2164
	  stf_ins(i_stf,no(bdy) <<1,b);
2 7u83 2165
	}
2166
	else{
7 7u83 2167
	  assert(IS_IN_REG(props(sbdy)));
2 7u83 2168
/*	  props(sbdy) = (props(sbdy)-R_I0)+R_O0;*/
2169
	  st_ro_ins(i_st,no(bdy),b);
2170
	}
2171
      }
2172
    }
7 7u83 2173
    else if (props(sbdy)!=0 && ((props(bdy) &inanyreg) == 0)) {
2 7u83 2174
      /* move from store to reg */
2175
      int par_reg = props(sbdy);
2176
      int last_reg = (shape_size(sh(sbdy)) > 32 ? par_reg+1 : par_reg);
7 7u83 2177
      int past_reg = ((trad_proc)? R_I5+1 :(vc)?R_I4:R_I5);
2 7u83 2178
					  /* registers i4 & i5 are reserved
2179
					       in general procs for handling
2180
					       of callee parameters */
7 7u83 2181
      assert(IS_IN_REG(par_reg));
2 7u83 2182
/*    props(sbdy) = (props(sbdy)-R_I0)+R_O0;*/
2183
      if ((last_param(bdy) && isvis(bdy) && !Has_no_vcallers)
2184
		|| last_reg >= past_reg)
2185
	last_reg = past_reg - 1;
7 7u83 2186
      while (par_reg <= last_reg) {
2 7u83 2187
	ld_ro_ins(i_ld,b,par_reg);
2188
	++par_reg;
2189
	b.offset += 4;
2190
      }
2191
    }
7 7u83 2192
    else if (props(sbdy)!= 0 && (props(sbdy)!= no(bdy))) {
2193
      if (is_floating(name(sh(sbdy)))) {
2 7u83 2194
	freg fr;
2195
	fr.fr = no(bdy);
2196
	fr.dble = (name(sh(sbdy)) == realhd);
7 7u83 2197
	stf_ins(i_st, fr.fr<<1, mem_temp(0));
2198
	ld_ro_ins(i_ld, mem_temp(0), props(sbdy));
2199
	if (fr.dble) {
2200
	  stf_ins(i_st,(fr.fr << 1) + 1,
2201
		    mem_temp(4));
2202
	  ld_ro_ins(i_ld, mem_temp(4), props(sbdy) + 1);
2 7u83 2203
	}
2204
      }
2205
      else{
7 7u83 2206
	assert(IS_IN_REG(props(sbdy)));
2 7u83 2207
/*	props(sbdy) = (props(sbdy)-R_I0)+R_O0;*/
2208
	rr_ins(i_mov,no(bdy),props(sbdy));
2209
      }
2210
    }
2211
    bdy = bro(sbdy);
2212
  }
2213
 
2214
  bproc = boff(son(fn));
2215
  assert(bproc.offset == 0);
2216
#ifdef GENCOMPAT
2217
  if (trad_proc) {
2218
    int r = getreg(nsp.fixed);
2219
    if (glob) {
2220
      set_ins(bproc,r);
2221
    }
2222
    else{
2223
      load_reg(fn,r,nsp);
2224
    }
7 7u83 2225
    if (!sysV_assembler) {
2 7u83 2226
	/* with -O2 SunOS corrupts unusual jmp/restore combination. */
7 7u83 2227
      outs("\t.optim\t\"-O0\"\n");
2 7u83 2228
    }
2229
#ifdef NEWDWARF
2230
    if (current_dg_info) {
7 7u83 2231
	current_dg_info->data.i_lj.brk = set_dw_text_label();
2 7u83 2232
	current_dg_info->data.i_lj.j.k = WH_REG;
2233
	current_dg_info->data.i_lj.j.u.l = r;
2234
    }
2235
#endif
2236
    extj_reg_ins_no_delay(i_jmp,r,-1);
2237
    fprintf ( as_file, "\t%s\n", i_restore ) ;	/* delay slot */
2238
#ifdef NEWDWARF
2239
    if (dwarf2)
2240
      count_ins(1);
2241
#endif
2242
  }
2243
  else
2244
#endif
2245
  {
2246
    bproc.offset = 12;
7 7u83 2247
    if (name(cllees)!= same_callees_tag) {
2 7u83 2248
      rr_ins(i_mov,callee_start_reg_out,callee_start_reg);
7 7u83 2249
      if (vc)rr_ins(i_mov,callee_end_reg_out,callee_end_reg);
2 7u83 2250
    }
7 7u83 2251
    if (name(cllees) == same_callees_tag && (vc && !Has_vcallees)) {
2 7u83 2252
      rir_ins(i_add,callee_start_reg,callee_size>>3,callee_end_reg);
2253
    }
7 7u83 2254
 
2 7u83 2255
    {
2256
      int r = getreg(nsp.fixed);
7 7u83 2257
      if (glob) {
2 7u83 2258
	set_ins(bproc,r);
2259
#ifdef NEWDWARF
2260
	if (current_dg_info) {
7 7u83 2261
	  current_dg_info->data.i_lj.brk = set_dw_text_label();
2 7u83 2262
	  current_dg_info->data.i_lj.j.k = WH_REG;
2263
	  current_dg_info->data.i_lj.j.u.l = r;
2264
	}
2265
#endif
2266
	extj_reg_ins(i_jmp,r,-1);
2267
      }
2268
      else{
2269
	load_reg(fn,r,nsp);
2270
	rir_ins(i_add,r,12,r);
2271
#ifdef NEWDWARF
2272
	if (current_dg_info) {
7 7u83 2273
	  current_dg_info->data.i_lj.brk = set_dw_text_label();
2 7u83 2274
	  current_dg_info->data.i_lj.j.k = WH_REG;
2275
	  current_dg_info->data.i_lj.j.u.l = r;
2276
	}
2277
#endif
2278
	extj_reg_ins(i_jmp,r,-1);
2279
      }
2280
    }
2281
  }
2282
  clear_all();
2283
  return mka;
7 7u83 2284
}
2 7u83 2285
 
2286
 
2287
 
2288