Subversion Repositories tendra.SVN

Rev

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

Rev 2 Rev 7
Line -... Line 1...
-
 
1
/*
-
 
2
 * Copyright (c) 2002-2005 The TenDRA Project <http://www.tendra.org/>.
-
 
3
 * All rights reserved.
-
 
4
 *
-
 
5
 * Redistribution and use in source and binary forms, with or without
-
 
6
 * modification, are permitted provided that the following conditions are met:
-
 
7
 *
-
 
8
 * 1. Redistributions of source code must retain the above copyright notice,
-
 
9
 *    this list of conditions and the following disclaimer.
-
 
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
-
 
11
 *    this list of conditions and the following disclaimer in the documentation
-
 
12
 *    and/or other materials provided with the distribution.
-
 
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
-
 
14
 *    may be used to endorse or promote products derived from this software
-
 
15
 *    without specific, prior written permission.
-
 
16
 *
-
 
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
-
 
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-
 
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-
 
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
-
 
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-
 
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-
 
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-
 
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-
 
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-
 
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-
 
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
 
28
 *
-
 
29
 * $Id$
-
 
30
 */
1
/*
31
/*
2
    		 Crown Copyright (c) 1996
32
    		 Crown Copyright (c) 1996
3
 
33
 
4
    This TenDRA(r) Computer Program is subject to Copyright
34
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
35
    owned by the United Kingdom Secretary of State for Defence
Line 103... Line 133...
103
#include "installglob.h"
133
#include "installglob.h"
104
#include "special_exps.h"
134
#include "special_exps.h"
105
 
135
 
106
/* externals */
136
/* externals */
107
 
137
 
108
void scan2 PROTO_S ( ( bool sto, exp to, exp e ) ) ;
138
void scan2(bool sto, exp to, exp e);
109
extern bool just_ret ;
139
extern bool just_ret;
110
extern mach_ins *prologue_ins ;
140
extern mach_ins *prologue_ins;
111
 
141
 
112
static void code_postlude PROTO_S ((exp postlude, exp callers, ash stack, long post_offset)) ;
142
static void code_postlude(exp postlude, exp callers, ash stack, long post_offset);
113
static bool test_push_args PROTO_S ((exp args, ash* args_size )) ;
143
static bool test_push_args(exp args, ash* args_size);
114
static void push_args PROTO_S ((where w, ash stack, exp args )) ;
144
static void push_args(where w, ash stack, exp args);
115
static void place_arguments PROTO_S ((exp args, ash stack, long start )) ;
145
static void place_arguments(exp args, ash stack, long start);
116
 
146
 
117
/************************************************************************
147
/************************************************************************
118
    GCPROC
148
    GCPROC
119
 
149
 
120
    This routine encodes a procedure call.  The procedure is named pname
150
    This routine encodes a procedure call.  The procedure is named pname
121
    with oname as an alternative (used with diagnostics).  The actual
151
    with oname as an alternative (used with diagnostics).  The actual
122
    body of the procedure is p.
152
    body of the procedure is p.
123
 ************************************************************************/
153
 ************************************************************************/
124
 
154
 
125
/* coder.c & codex.c */
155
/* coder.c & codex.c */
126
extern ast add_shape_to_stack PROTO_S ((ash stack, shape s ));
156
extern ast add_shape_to_stack(ash stack, shape s);
127
extern void prologue PROTO_S ((void));
157
extern void prologue(void);
128
extern void out_profile PROTO_S (( bool save_a1 ));
158
extern void out_profile(bool save_a1);
129
extern int do_peephole ;
159
extern int do_peephole;
130
extern int do_pic ;
160
extern int do_pic;
131
 
161
 
132
void gcproc
162
void gcproc
133
    PROTO_N ( ( p, pname, cname, is_ext, reg_res, di) )
-
 
134
    PROTO_T ( exp p X char *pname X long cname X int is_ext X int reg_res X diag_global *di )
163
(exp p, char *pname, long cname, int is_ext, int reg_res, diag_global *di)
135
{
164
{
136
  exp t ;
165
  exp t;
137
  ash stack ;
166
  ash stack;
138
  ash param_pos ;
167
  ash param_pos;
139
 
168
 
140
  mach_op *op1, *op2 ;
169
  mach_op *op1, *op2;
141
  static long crt_proc_no = 0 ;
170
  static long crt_proc_no = 0;
142
 
171
 
143
  bool has_callers = 0;
172
  bool has_callers = 0;
144
  bool has_checkstack = 0;
173
  bool has_checkstack = 0;
145
  bool uses_callers_pointer = 0;
174
  bool uses_callers_pointer = 0;
146
  cur_proc_callees_size = 0;
175
  cur_proc_callees_size = 0;
147
 
176
 
148
  /* find out if the call has tail_call or same_callees constructs */
177
  /* find out if the call has tail_call or same_callees constructs */
149
  cur_proc_has_tail_call = 0;
178
  cur_proc_has_tail_call = 0;
150
  cur_proc_use_same_callees = 0;
179
  cur_proc_use_same_callees = 0;
151
  scan2(1, p, p);
180
  scan2(1, p, p);
152
  comp_weights ( p ) ;
181
  comp_weights(p);
153
 
182
 
154
  /* Set up flags, register masks, stack etc. */
183
  /* Set up flags, register masks, stack etc. */
155
  has_alloca = proc_has_alloca(p);
184
  has_alloca = proc_has_alloca(p);
156
  must_use_bp = has_alloca || proc_has_lv(p) || proc_uses_crt_env (p) ;
185
  must_use_bp = has_alloca || proc_has_lv(p) || proc_uses_crt_env(p);
157
  bigregs = 0 ;
186
  bigregs = 0;
158
  crt_ret_lab = next_lab () ;
187
  crt_ret_lab = next_lab();
159
  extra_stack = 0 ;
188
  extra_stack = 0;
160
  have_cond = 0 ;
189
  have_cond = 0;
161
  max_stack = 0 ;
190
  max_stack = 0;
162
  no_calls = 0 ;
191
  no_calls = 0;
163
  regsinproc = 0 ;
192
  regsinproc = 0;
164
  regsinuse = 0 ;
193
  regsinuse = 0;
165
  reuseables = 0 ;
194
  reuseables = 0;
166
  regsindec = 0 ;
195
  regsindec = 0;
167
  stack = 0 ;
196
  stack = 0;
168
  special_no = crt_proc_no++ ;
197
  special_no = crt_proc_no++;
169
  stack_dec = 0 ;
198
  stack_dec = 0;
170
  stack_size = 0 ;
199
  stack_size = 0;
171
  used_ldisp = 0 ;
200
  used_ldisp = 0;
172
  used_stack = do_profile || diagnose || must_use_bp ;
201
  used_stack = do_profile || diagnose || must_use_bp;
173
 
202
 
174
  /* Mark procedure body */
203
  /* Mark procedure body */
175
  ptno ( p ) = par_pl ;
204
  ptno(p) = par_pl;
176
  no ( p ) = 0 ;
205
  no(p) = 0;
177
 
206
 
178
  /* Mark procedure parameters */
207
  /* Mark procedure parameters */
179
  param_pos = 0 ;
208
  param_pos = 0;
180
 
209
 
181
  /* the callees are encoded first. Scan to first callee if any */
210
  /* the callees are encoded first. Scan to first callee if any */
182
 
211
 
183
  t = son ( p ) ;
212
  t = son(p);
184
  while ( name ( t ) == ident_tag && isparam ( t ) &&
213
  while (name(t) == ident_tag && isparam(t) &&
185
          name ( son ( t ) ) != formal_callee_tag ) {
214
          name(son(t))!= formal_callee_tag) {
186
    t = bro(son(t)) ;
215
    t = bro(son(t));
187
    has_callers = 1 ;
216
    has_callers = 1;
188
  }
217
  }
189
 
218
 
190
  cur_proc_has_vcallees = proc_has_vcallees(p) ;
219
  cur_proc_has_vcallees = proc_has_vcallees(p);
191
  uses_callers_pointer = cur_proc_has_vcallees && has_callers ;
220
  uses_callers_pointer = cur_proc_has_vcallees && has_callers;
192
 
221
 
193
  if (uses_callers_pointer) {
222
  if (uses_callers_pointer) {
194
    /* ok callers are accessed by use of a5 */
223
    /* ok callers are accessed by use of a5 */
195
    regsinproc |= regmsk ( REG_A5 ) ;
224
    regsinproc |= regmsk(REG_A5);
196
    regsinuse  |= regmsk ( REG_A5 ) ;
225
    regsinuse  |= regmsk(REG_A5);
197
  }
226
  }
198
 
227
 
199
 
228
 
200
  /* do we have any callees? */
229
  /* do we have any callees? */
201
  if (name(t) == ident_tag && name(son(t)) == formal_callee_tag) {
230
  if (name(t) == ident_tag && name(son(t)) == formal_callee_tag) {
202
    while(name(t) == ident_tag && name(son(t)) == formal_callee_tag) {
231
    while (name(t) == ident_tag && name(son(t)) == formal_callee_tag) {
203
      ast a ;
232
      ast a;
204
      a = add_shape_to_stack ( param_pos, sh ( son ( t ) ) ) ;
233
      a = add_shape_to_stack(param_pos, sh(son(t)));
205
      no ( t ) = a.astoff + a.astadj + (cur_proc_has_vcallees ? 4*8 : 0);
234
      no(t) = a.astoff + a.astadj + (cur_proc_has_vcallees ? 4*8 : 0);
206
      param_pos = a.astash ;
235
      param_pos = a.astash;
207
      ptno ( t ) = par_pl ;
236
      ptno(t) = par_pl;
208
 
237
 
209
      make_visible( t ) ;
238
      make_visible(t);
210
 
239
 
211
      t = bro ( son ( t ) ) ;
240
      t = bro(son(t));
212
    }
241
    }
213
    cur_proc_callees_size = param_pos ;
242
    cur_proc_callees_size = param_pos;
214
  }
243
  }
215
 
244
 
216
 
245
 
217
  /* encode the caller parameters */
246
  /* encode the caller parameters */
218
  {
247
  {
219
    exp caller = son ( p ) ;
248
    exp caller = son(p);
220
    int location_id = par_pl ;
249
    int location_id = par_pl;
221
    if ( uses_callers_pointer ) {
250
    if (uses_callers_pointer) {
222
      location_id = par2_pl ;
251
      location_id = par2_pl;
223
      param_pos = 0 ;
252
      param_pos = 0;
224
    }
253
    }
225
    while (name(caller) == ident_tag && isparam (caller) &&
254
    while (name(caller) == ident_tag && isparam(caller) &&
226
           name(son(caller)) != formal_callee_tag ) {
255
           name(son(caller))!= formal_callee_tag) {
227
 
256
 
228
      ast a;
257
      ast a;
229
      a = add_shape_to_stack ( param_pos, sh ( son ( caller ) ) ) ;
258
      a = add_shape_to_stack(param_pos, sh(son(caller)));
230
      ptno ( caller ) = location_id ;
259
      ptno(caller) = location_id;
231
      no ( caller ) = a.astoff + a.astadj ;
260
      no(caller) = a.astoff + a.astadj;
232
      param_pos = a.astash ;
261
      param_pos = a.astash;
233
 
262
 
234
      make_visible( caller ) ;
263
      make_visible(caller);
235
 
264
 
236
      caller = bro ( son ( caller ) ) ;
265
      caller = bro(son(caller));
237
    }
266
    }
238
  }
267
  }
239
 
268
 
240
  /* calculate callers size */
269
  /* calculate callers size */
241
  cur_proc_callers_size = param_pos ;
270
  cur_proc_callers_size = param_pos;
242
  if ( ! uses_callers_pointer )
271
  if (! uses_callers_pointer)
243
  cur_proc_callers_size -= cur_proc_callees_size ;
272
  cur_proc_callers_size -= cur_proc_callees_size;
244
 
273
 
245
  /* Output procedure name(s) */
274
  /* Output procedure name(s) */
246
  area ( ptext ) ;
275
  area(ptext);
247
  make_instr ( m_as_align4, null, null, 0 ) ;
276
  make_instr(m_as_align4, null, null, 0);
248
  if ( is_ext && pname ) {
277
  if (is_ext && pname) {
249
     if ( strcmp ( pname, "_cmppt" ) == 0 ) {
278
     if (strcmp(pname, "_cmppt") == 0) {
250
        /* Hack to get alignments right */
279
        /* Hack to get alignments right */
251
      make_instr ( m_nop, null, null, 0 ) ;
280
      make_instr(m_nop, null, null, 0);
252
      make_instr ( m_nop, null, null, 0 ) ;
281
      make_instr(m_nop, null, null, 0);
253
    }
282
    }
254
    op1 = make_extern_data ( pname, 0 ) ;
283
    op1 = make_extern_data(pname, 0);
255
    make_instr ( m_as_global, op1, null, 0 ) ;
284
    make_instr(m_as_global, op1, null, 0);
256
  }
285
  }
257
  if ( cname == -1 ) {
286
  if (cname == -1) {
258
    make_external_label ( pname ) ;
287
    make_external_label(pname);
259
  } else {
288
  } else {
260
     make_label ( cname ) ;
289
     make_label(cname);
261
  }
290
  }
262
 
291
 
263
  if (! strcmp (pname, "_main")) {
292
  if (! strcmp(pname, "_main")) {
264
     make_comment("Do Dynamic Initialization");
293
     make_comment("Do Dynamic Initialization");
265
     op1 = make_extern_ind("___TDF_main",0);
294
     op1 = make_extern_ind("___TDF_main",0);
266
     make_instr(m_call,op1,null,0);
295
     make_instr(m_call,op1,null,0);
267
  }
296
  }
268
 
297
 
269
  /* Output profiling information if required */
298
  /* Output profiling information if required */
270
  if ( do_profile ) {
299
  if (do_profile) {
271
    out_profile ( !reg_res ) ;
300
    out_profile(!reg_res);
272
    used_stack = 1 ;
301
    used_stack = 1;
273
  }
302
  }
274
 
303
 
275
  if ( proc_has_checkstack(p) ) {
304
  if (proc_has_checkstack(p)) {
276
     /* check that there is room for env_size(<this proc>) */
305
     /* check that there is room for env_size(<this proc>) */
277
     /* since callers, callees & return address are pushed */
306
     /* since callers, callees & return address are pushed */
278
     /* we only check for the rest */
307
     /* we only check for the rest */
279
     long already_allocated = cur_proc_callers_size + cur_proc_callees_size + 32 ;
308
     long already_allocated = cur_proc_callers_size + cur_proc_callees_size + 32;
280
     where w;
309
     where w;
281
     w = mw (get_env_size(cur_proc_dec), - already_allocated);
310
     w = mw(get_env_size(cur_proc_dec), - already_allocated);
282
     checkalloc_stack (w, 0);
311
     checkalloc_stack(w, 0);
283
     has_checkstack = 1 ;
312
     has_checkstack = 1;
284
  }
313
  }
285
 
314
 
286
 
315
 
287
  /* Set up procedure prologue */
316
  /* Set up procedure prologue */
288
  prologue () ;
317
  prologue();
289
 
318
 
290
  /* Diagnostics for start of procedure */
319
  /* Diagnostics for start of procedure */
291
#if have_diagnostics
320
#if have_diagnostics
292
  if ( di ) xdb_diag_proc_begin ( di, p, pname, cname, is_ext ) ;
321
  if (di)xdb_diag_proc_begin(di, p, pname, cname, is_ext);
293
#endif
322
#endif
294
 
323
 
295
  /* Allow for procedures which return compound results */
324
  /* Allow for procedures which return compound results */
296
  if ( !reg_res ) {
325
  if (!reg_res) {
297
    /* Save A1 on the stack */
326
    /* Save A1 on the stack */
298
    ast newstack ;
327
    ast newstack;
299
    newstack = add_shape_to_stack ( stack, slongsh ) ;
328
    newstack = add_shape_to_stack(stack, slongsh);
300
    stack = newstack.astash ;
329
    stack = newstack.astash;
301
    max_stack = 32 ;
330
    max_stack = 32;
302
    used_stack = 1 ;
331
    used_stack = 1;
303
    op1 = make_register ( REG_A1 ) ;
332
    op1 = make_register(REG_A1);
304
    op2 = make_indirect ( REG_AP, -4 ) ;
333
    op2 = make_indirect(REG_AP, -4);
305
    make_instr ( m_movl, op1, op2, 0 ) ;
334
    make_instr(m_movl, op1, op2, 0);
306
  }
335
  }
307
  need_preserve_stack = 0;
336
  need_preserve_stack = 0;
308
 
337
 
309
  if (proc_uses_crt_env(p) && proc_has_lv(p) && has_alloca) {
338
  if (proc_uses_crt_env(p) && proc_has_lv(p) && has_alloca) {
310
     need_preserve_stack = 1 ;
339
     need_preserve_stack = 1;
311
     stack += 32 ;
340
     stack += 32;
312
     max_stack += 32 ;
341
     max_stack += 32;
313
     save_stack () ;
342
     save_stack();
314
  };
343
  };
315
 
344
 
316
 
345
 
317
  /* Encode the procedure body */
346
  /* Encode the procedure body */
318
#if have_diagnostics
347
#if have_diagnostics
319
  if ( diagnose ) {
348
  if (diagnose) {
320
    dnt_begin () ;
349
    dnt_begin();
321
    coder ( zero, stack, t ) ;
350
    coder(zero, stack, t);
322
    dnt_end () ;
351
    dnt_end();
323
  } else
352
  } else
324
#endif
353
#endif
325
    coder ( zero, stack, t ) ;
354
    coder(zero, stack, t);
326
 
355
 
327
  /* Output the procedure epilogue */
356
  /* Output the procedure epilogue */
328
  general_epilogue (uses_callers_pointer, has_checkstack) ;
357
  general_epilogue(uses_callers_pointer, has_checkstack);
329
 
358
 
330
  /* Apply peephole optimizations and return */
359
  /* Apply peephole optimizations and return */
331
  if ( do_peephole ) peephole () ;
360
  if (do_peephole)peephole();
332
 
361
 
333
  /* Diagnostics for end of procedure */
362
  /* Diagnostics for end of procedure */
334
#if have_diagnostics
363
#if have_diagnostics
335
  if ( di ) xdb_diag_proc_end ( di ) ;
364
  if (di)xdb_diag_proc_end(di);
336
#endif
365
#endif
337
 
366
 
338
  return  ;
367
  return ;
339
}
368
}
340
 
369
 
341
 
370
 
342
/************************************************************************
371
/************************************************************************
343
  restore_regs_subsribers is used by restore_regs.
372
  restore_regs_subsribers is used by restore_regs.
344
  It is a list of places to put insructions to restore registers.
373
  It is a list of places to put insructions to restore registers.
345
I If untidy is true, it means that sp shall not be restored.
374
I If untidy is true, it means that sp shall not be restored.
346
*/
375
*/
347
 
376
 
348
typedef struct rrs_tag {
377
typedef struct rrs_tag {
349
  mach_ins* ins ;
378
  mach_ins* ins;
350
  restore_type_t restore_type  ;
379
  restore_type_t restore_type ;
351
  struct rrs_tag* next ;
380
  struct rrs_tag* next;
352
} rrs;
381
} rrs;
353
 
382
 
354
rrs* restore_regs_subsribers = 0 ;
383
rrs* restore_regs_subsribers = 0;
355
 
384
 
356
 
385
 
357
/************************************************************************
386
/************************************************************************
358
 RESTORE_REGS
387
 RESTORE_REGS
359
 
388
 
360
 Subscribe on code to restore registers. See restore_regs_output below.
389
 Subscribe on code to restore registers. See restore_regs_output below.
361
 Restore_type is one of: ALL, NOT_SP, NOT_A6_OR_SP
390
 Restore_type is one of: ALL, NOT_SP, NOT_A6_OR_SP
362
 ************************************************************************/
391
 ************************************************************************/
363
 
392
 
364
void restore_regs
393
void restore_regs
365
    PROTO_N ( ( typ ) )
-
 
366
    PROTO_T ( restore_type_t typ )
394
(restore_type_t typ)
367
{
395
{
368
  rrs* p = (rrs*) xmalloc(sizeof(rrs)) ;
396
  rrs* p = (rrs*)xmalloc(sizeof(rrs));
369
  p->ins  = current_ins ;
397
  p->ins  = current_ins;
370
  p->next = restore_regs_subsribers ;
398
  p->next = restore_regs_subsribers;
371
  p->restore_type = typ ;
399
  p->restore_type = typ;
372
  restore_regs_subsribers = p ;
400
  restore_regs_subsribers = p;
373
}
401
}
374
/************************************************************************/
402
/************************************************************************/
375
/* used by restore_regs_output below */
403
/* used by restore_regs_output below */
376
 
404
 
377
rrs* pop_restore_regs_subsriber
405
rrs* pop_restore_regs_subsriber
378
    PROTO_Z ()
406
(void)
379
{
407
{
380
   rrs* p = restore_regs_subsribers ;
408
   rrs* p = restore_regs_subsribers;
381
 
409
 
382
   if (p != 0) {
410
   if (p != 0) {
383
      restore_regs_subsribers = p->next ;
411
      restore_regs_subsribers = p->next;
384
   }
412
   }
385
 
413
 
386
   return p ;
414
   return p;
387
}
415
}
388
 
416
 
389
/************************************************************************
417
/************************************************************************
390
  RESTORE_REGS_OUTPUT
418
  RESTORE_REGS_OUTPUT
391
 
419
 
Line 400... Line 428...
400
 
428
 
401
  side effect: current_ins is changed
429
  side effect: current_ins is changed
402
 ************************************************************************/
430
 ************************************************************************/
403
 
431
 
404
void restore_regs_output
432
void restore_regs_output
405
    PROTO_N ( ( rmsk, fmsk, st, st1, uses_link ) )
-
 
406
    PROTO_T ( bitpattern rmsk X bitpattern fmsk X long st X long st1 X bool uses_link )
433
(bitpattern rmsk, bitpattern fmsk, long st, long st1, bool uses_link)
407
{
434
{
408
   rrs* p ;
435
   rrs* p;
409
   while ( ( p = pop_restore_regs_subsriber () ) ) {
436
   while ((p = pop_restore_regs_subsriber())) {
410
      mach_op *op1, *op2 ;
437
      mach_op *op1, *op2;
411
      current_ins = p->ins ;
438
      current_ins = p->ins;
412
 
439
 
413
      make_comment("Restore Registers") ;
440
      make_comment("Restore Registers");
414
 
441
 
415
      /* Restore floating-point registers from the stack */
442
      /* Restore floating-point registers from the stack */
416
      if ( fmsk ) {
443
      if (fmsk) {
417
         just_ret = 0 ;
444
         just_ret = 0;
418
         op1 = make_indirect ( REG_AP, -st1 ) ;
445
         op1 = make_indirect(REG_AP, -st1);
419
         op2 = make_hex_value ( fmsk ) ;
446
         op2 = make_hex_value(fmsk);
420
         make_instr ( m_fmovemx, op1, op2, fmsk ) ;
447
         make_instr(m_fmovemx, op1, op2, fmsk);
421
      }
448
      }
422
 
449
 
423
      /* Restore registers from the stack */
450
      /* Restore registers from the stack */
424
      if ( rmsk ) {
451
      if (rmsk) {
425
         just_ret = 0 ;
452
         just_ret = 0;
426
         if ( must_use_bp ) {
453
         if (must_use_bp) {
427
            op1 = make_indirect ( REG_AP, -st ) ;
454
            op1 = make_indirect(REG_AP, -st);
428
         } else {
455
         } else {
429
            op1 = make_indirect ( REG_SP, 0 ) ;
456
            op1 = make_indirect(REG_SP, 0);
430
         }
457
         }
431
         op2 = make_hex_value ( rmsk ) ;
458
         op2 = make_hex_value(rmsk);
432
         make_instr ( m_moveml, op1, op2, rmsk ) ;
459
         make_instr(m_moveml, op1, op2, rmsk);
433
      }
460
      }
434
 
461
 
435
      if ( uses_link ) {
462
      if (uses_link) {
436
         just_ret = 0 ;
463
         just_ret = 0;
437
 
464
 
438
         switch ( p->restore_type ){
465
         switch (p->restore_type) {
439
         case ALL:
466
         case ALL:
440
            /* Output unlink instruction */
467
            /* Output unlink instruction */
441
            op1 = make_register ( REG_AP ) ;
468
            op1 = make_register(REG_AP);
442
            make_instr ( m_unlk, op1, null, regmsk ( REG_AP ) ) ;
469
            make_instr(m_unlk, op1, null, regmsk(REG_AP));
443
            break;
470
            break;
444
         case NOT_SP:
471
         case NOT_SP:
445
            make_comment("untidy return => Restore A6, but not SP");
472
            make_comment("untidy return => Restore A6, but not SP");
446
            op1 = make_indirect ( REG_AP, 0 ) ;
473
            op1 = make_indirect(REG_AP, 0);
447
            op2 = make_register ( REG_AP ) ;
474
            op2 = make_register(REG_AP);
448
            make_instr ( m_movl, op1, op2, regmsk ( REG_AP ) ) ;
475
            make_instr(m_movl, op1, op2, regmsk(REG_AP));
449
            break;
476
            break;
450
         case NOT_A6_OR_SP:
477
         case NOT_A6_OR_SP:
451
            make_comment("exit with long jump => Don't restore A6 or SP");
478
            make_comment("exit with long jump => Don't restore A6 or SP");
452
            break;
479
            break;
453
         default:
480
         default:
454
            error("wrong restore type");
481
            error("wrong restore type");
455
         }
482
         }
456
      }
483
      }
457
   }
484
   }
458
}
485
}
459
 
486
 
460
/************************************************************************
487
/************************************************************************
461
  CLEANUP_BT
488
  CLEANUP_BT
462
 
489
 
463
  Cleanup before a tail call is performed. Used by tail_call.
490
  Cleanup before a tail call is performed. Used by tail_call.
464
  Restore registers and frees callees stack room and return address.
491
  Restore registers and frees callees stack room and return address.
465
  ************************************************************************/
492
  ************************************************************************/
466
 
493
 
467
void cleanup_bt
494
void cleanup_bt
468
    PROTO_N ( ( save_ret, rg ) )
-
 
469
    PROTO_T ( bool save_ret X int rg )
495
(bool save_ret, int rg)
470
{
496
{
471
   mach_op *op1, *op2 ;
497
   mach_op *op1, *op2;
472
 
498
 
473
   make_comment ( "Cleanup before tail call ..." );
499
   make_comment("Cleanup before tail call ...");
474
 
500
 
475
   /* save callees size in scratch register if needed */
501
   /* save callees size in scratch register if needed */
476
   if (cur_proc_has_vcallees) {
502
   if (cur_proc_has_vcallees) {
477
      make_comment ( "save old callees size" );
503
      make_comment("save old callees size");
478
      op1 = make_indirect ( REG_AP, 8 ) ;
504
      op1 = make_indirect(REG_AP, 8);
479
      op2 = make_register ( REG_D0 ) ;
505
      op2 = make_register(REG_D0);
480
      make_instr ( m_movl, op1, op2, regmsk ( REG_D0 ) ) ;
506
      make_instr(m_movl, op1, op2, regmsk(REG_D0));
481
   }
507
   }
482
 
508
 
483
   /* subscribe on code to restore registers */
509
   /* subscribe on code to restore registers */
484
   restore_regs(ALL) ;
510
   restore_regs(ALL);
485
 
511
 
486
   if ( save_ret ) {
512
   if (save_ret) {
487
      make_comment ( "save return address in register" );
513
      make_comment("save return address in register");
488
      op1 = make_indirect ( REG_SP, 0 ) ;
514
      op1 = make_indirect(REG_SP, 0);
489
      op2 = make_register ( rg ) ;
515
      op2 = make_register(rg);
490
      make_instr ( m_movl, op1, op2, regmsk ( rg ) ) ;
516
      make_instr(m_movl, op1, op2, regmsk(rg));
491
   }
517
   }
492
 
518
 
493
   if ( cur_proc_has_vcallees ) {
519
   if (cur_proc_has_vcallees) {
494
      make_comment("cleanup variable callees and return address");
520
      make_comment("cleanup variable callees and return address");
495
      op1 = make_register ( REG_D0 ) ;
521
      op1 = make_register(REG_D0);
496
      op2 = make_register ( REG_SP );
522
      op2 = make_register(REG_SP);
497
      make_instr ( m_addl, op1, op2, regmsk ( REG_SP ) );
523
      make_instr(m_addl, op1, op2, regmsk(REG_SP));
498
 
524
 
499
      op1 = make_value ( 8 ) ;  /* size of callers pointer & ret.addr. */
525
      op1 = make_value ( 8 ) ;  /* size of callers pointer & ret.addr. */
500
      op2 = make_register ( REG_SP );
526
      op2 = make_register(REG_SP);
501
      make_instr ( m_addl, op1, op2, regmsk ( REG_SP ) );
527
      make_instr(m_addl, op1, op2, regmsk(REG_SP));
502
   }
528
   }
503
   else {
529
   else {
504
      make_comment("cleanup static callees and return address");
530
      make_comment("cleanup static callees and return address");
505
      op1 = make_value ( cur_proc_callees_size / 8 + 4 ) ;
531
      op1 = make_value(cur_proc_callees_size / 8 + 4);
506
      op2 = make_register ( REG_SP );
532
      op2 = make_register(REG_SP);
507
      make_instr ( m_addl, op1, op2, regmsk ( REG_SP ) );
533
      make_instr(m_addl, op1, op2, regmsk(REG_SP));
508
   }
534
   }
509
   make_comment ( "Cleanup before tail call done" );
535
   make_comment("Cleanup before tail call done");
510
}
536
}
511
 
537
 
512
/************************************************************************
538
/************************************************************************
513
  CLEANUP
539
  CLEANUP
514
 
540
 
515
  Restore registers and frees callees stack room, just before return from
541
  Restore registers and frees callees stack room, just before return from
516
  a procedure. Used by general_epilogue.
542
  a procedure. Used by general_epilogue.
517
  The return address is restored.
543
  The return address is restored.
518
  ************************************************************************/
544
  ************************************************************************/
519
 
545
 
520
void cleanup
546
void cleanup
521
    PROTO_Z ()
547
(void)
522
{
548
{
523
   mach_op *op1, *op2 ;
549
   mach_op *op1, *op2;
524
   bool callees_to_clean = cur_proc_has_vcallees || cur_proc_callees_size ;
550
   bool callees_to_clean = cur_proc_has_vcallees || cur_proc_callees_size;
525
 
551
 
526
   make_comment ( "Cleanup before return ..." );
552
   make_comment("Cleanup before return ...");
527
 
553
 
528
   /* save callees size in scratch register if needed */
554
   /* save callees size in scratch register if needed */
529
   if ( cur_proc_has_vcallees ) {
555
   if (cur_proc_has_vcallees) {
530
      make_comment ( "save callees size" );
556
      make_comment("save callees size");
531
      op1 = make_indirect ( REG_AP, 8 ) ;
557
      op1 = make_indirect(REG_AP, 8);
532
      op2 = make_register ( REG_A0 ) ;
558
      op2 = make_register(REG_A0);
533
      make_instr ( m_movl, op1, op2, regmsk ( REG_A0 ) ) ;
559
      make_instr(m_movl, op1, op2, regmsk(REG_A0));
534
   }
560
   }
535
 
561
 
536
   /* subscribe on code to restore registers */
562
   /* subscribe on code to restore registers */
537
   restore_regs(ALL) ;
563
   restore_regs(ALL);
538
 
564
 
539
   if ( callees_to_clean ) {
565
   if (callees_to_clean) {
540
      make_comment ( "save return address in register" );
566
      make_comment("save return address in register");
541
      op1 = make_indirect ( REG_SP, 0 ) ;
567
      op1 = make_indirect(REG_SP, 0);
542
      op2 = make_register ( REG_A1 ) ;
568
      op2 = make_register(REG_A1);
543
      make_instr ( m_movl, op1, op2, regmsk ( REG_A1 ) ) ;
569
      make_instr(m_movl, op1, op2, regmsk(REG_A1));
544
 
570
 
545
      if ( cur_proc_has_vcallees ) {
571
      if (cur_proc_has_vcallees) {
546
         make_comment("cleanup variable callees and return address");
572
         make_comment("cleanup variable callees and return address");
547
         op1 = make_register ( REG_A0 ) ;
573
         op1 = make_register(REG_A0);
548
         op2 = make_register ( REG_SP );
574
         op2 = make_register(REG_SP);
549
         make_instr ( m_addl, op1, op2, regmsk ( REG_SP ) );
575
         make_instr(m_addl, op1, op2, regmsk(REG_SP));
550
 
576
 
551
         op1 = make_value ( 4 ) ; /* size of callers pointer */
577
         op1 = make_value ( 4 ) ; /* size of callers pointer */
552
         op2 = make_register ( REG_SP );
578
         op2 = make_register(REG_SP);
553
         make_instr ( m_addl, op1, op2, regmsk ( REG_SP ) );
579
         make_instr(m_addl, op1, op2, regmsk(REG_SP));
554
      }
580
      }
555
      else {
581
      else {
556
         make_comment("cleanup static callees");
582
         make_comment("cleanup static callees");
557
         op1 = make_value ( cur_proc_callees_size / 8 ) ;
583
         op1 = make_value(cur_proc_callees_size / 8);
558
         op2 = make_register ( REG_SP );
584
         op2 = make_register(REG_SP);
559
         make_instr ( m_addl, op1, op2, regmsk ( REG_SP ) );
585
         make_instr(m_addl, op1, op2, regmsk(REG_SP));
560
      }
586
      }
561
 
587
 
562
      make_comment("put return address back on the stack");
588
      make_comment("put return address back on the stack");
563
      op1 = make_register ( REG_A1 ) ;
589
      op1 = make_register(REG_A1);
564
      op2 = make_indirect ( REG_SP, 0 ) ;
590
      op2 = make_indirect(REG_SP, 0);
565
      make_instr ( m_movl, op1, op2, 0 ) ;
591
      make_instr(m_movl, op1, op2, 0);
566
   }
592
   }
567
   make_comment ( "Cleanup before return done" );
593
   make_comment("Cleanup before return done");
568
}
594
}
569
 
595
 
570
/************************************************************************
596
/************************************************************************
571
  PUSH_RANGE
597
  PUSH_RANGE
572
 
598
 
573
  Push memory in the range [start, end] on the stack. (start > end).
599
  Push memory in the range [start, end] on the stack. (start > end).
574
  (modifies start, end, SP)
600
  (modifies start, end, SP)
575
  ************************************************************************/
601
  ************************************************************************/
576
 
602
 
577
void push_range
603
void push_range
578
    PROTO_N ( ( start, end ) )
-
 
579
    PROTO_T ( int start X int end )
604
(int start, int end)
580
{
605
{
581
   mach_op *op1, *op2 ;
606
   mach_op *op1, *op2;
582
   long lb ;
607
   long lb;
583
 
608
 
584
   make_comment("Push range");
609
   make_comment("Push range");
585
 
610
 
586
   lb = next_lab () ;
611
   lb = next_lab();
587
   make_label ( lb ) ;
612
   make_label(lb);
588
 
613
 
589
   op1 = make_predec ( start ) ;
614
   op1 = make_predec(start);
590
   op2 = make_dec_sp () ;
615
   op2 = make_dec_sp();
591
   make_instr ( m_movw, op1, op2, regmsk ( REG_SP ) ) ;
616
   make_instr(m_movw, op1, op2, regmsk(REG_SP));
592
 
617
 
593
   op1 = make_register ( start ) ;
618
   op1 = make_register(start);
594
   op2 = make_register ( end ) ;
619
   op2 = make_register(end);
595
   make_instr ( m_cmpl, op1, op2, 0 ) ;
620
   make_instr(m_cmpl, op1, op2, 0);
596
 
621
 
597
   make_jump ( m_bne, lb ) ;
622
   make_jump(m_bne, lb);
598
}
623
}
599
 
624
 
600
/************************************************************************
625
/************************************************************************
601
  MAKE_CALLEES_SIZE
626
  MAKE_CALLEES_SIZE
602
 
627
 
603
  Returns an operand specifying the size of the callees for
628
  Returns an operand specifying the size of the callees for
604
  the current procedure.
629
  the current procedure.
605
  ************************************************************************/
630
  ************************************************************************/
606
 
631
 
607
mach_op* make_callees_size
632
mach_op* make_callees_size
608
    PROTO_Z ()
633
(void)
609
{
634
{
610
   /* Is it a run time value ? */
635
   /* Is it a run time value ? */
611
   if ( cur_proc_has_vcallees )
636
   if (cur_proc_has_vcallees)
612
   return make_indirect ( REG_AP, 8 ) ;
637
   return make_indirect(REG_AP, 8);
613
 
638
 
614
   /* or compile time value ? */
639
   /* or compile time value ? */
615
   return make_value ( cur_proc_callees_size / 8 ) ;
640
   return make_value(cur_proc_callees_size / 8);
616
}
641
}
617
 
642
 
618
/************************************************************************
643
/************************************************************************
619
  PUSH_SAME_CALLEES
644
  PUSH_SAME_CALLEES
620
 
645
 
621
  Used by apply_general_proc to push the same callees
646
  Used by apply_general_proc to push the same callees
622
  (modifies A0,D0,D1,SP)
647
  (modifies A0,D0,D1,SP)
623
  ************************************************************************/
648
  ************************************************************************/
624
 
649
 
625
void push_same_callees
650
void push_same_callees
626
    PROTO_N ( ( var_callees ) )
-
 
627
    PROTO_T ( bool var_callees )
651
(bool var_callees)
628
{
652
{
629
   mach_op *op1, *op2 ;
653
   mach_op *op1, *op2;
630
 
654
 
631
   /* do we have any callees to push ? */
655
   /* do we have any callees to push ? */
632
   if ( cur_proc_has_vcallees || cur_proc_callees_size ) {
656
   if (cur_proc_has_vcallees || cur_proc_callees_size) {
633
      make_comment("Push same callees");
657
      make_comment("Push same callees");
634
      make_comment("end of callees");
658
      make_comment("end of callees");
635
      op1 = make_register ( REG_AP ) ;
659
      op1 = make_register(REG_AP);
636
      op2 = make_register ( REG_D1 ) ;
660
      op2 = make_register(REG_D1);
637
      make_instr ( m_movl, op1, op2, regmsk ( REG_D1 ) ) ;
661
      make_instr(m_movl, op1, op2, regmsk(REG_D1));
638
 
662
 
639
      /* add sizeof(ret-addr)+sizeof(preincrement) ?+sizeof(callees size)? */
663
      /* add sizeof(ret-addr)+sizeof(preincrement) ?+sizeof(callees size)? */
640
      op1 = make_value( ( cur_proc_has_vcallees )? 12 : 8 ) ;
664
      op1 = make_value((cur_proc_has_vcallees)? 12 : 8);
641
      op2 = make_register ( REG_D1 ) ;
665
      op2 = make_register(REG_D1);
642
      make_instr ( m_addl, op1, op2, regmsk ( REG_D1 ) ) ;
666
      make_instr(m_addl, op1, op2, regmsk(REG_D1));
643
 
667
 
644
      make_comment("start of callees");
668
      make_comment("start of callees");
645
      op1 = make_register ( REG_D1 ) ;
669
      op1 = make_register(REG_D1);
646
      op2 = make_register ( REG_A0 ) ;
670
      op2 = make_register(REG_A0);
647
      make_instr ( m_movl, op1, op2, regmsk ( REG_A0 ) ) ;
671
      make_instr(m_movl, op1, op2, regmsk(REG_A0));
648
 
672
 
649
      op1 = make_callees_size() ;
673
      op1 = make_callees_size();
650
      op2 = make_register ( REG_A0 ) ;
674
      op2 = make_register(REG_A0);
651
      make_instr ( m_addl, op1, op2, regmsk ( REG_A0 ) ) ;
675
      make_instr(m_addl, op1, op2, regmsk(REG_A0));
652
 
676
 
653
      push_range ( REG_A0, REG_D1 ) ;
677
      push_range(REG_A0, REG_D1);
654
   }
678
   }
655
 
679
 
656
   if (var_callees) {
680
   if (var_callees) {
657
      make_comment("push size of callees on the stack");
681
      make_comment("push size of callees on the stack");
658
      op1 = make_callees_size () ;
682
      op1 = make_callees_size();
659
      op2 = make_dec_sp();
683
      op2 = make_dec_sp();
660
      make_instr ( m_movl, op1, op2, regmsk ( REG_SP )) ;
684
      make_instr(m_movl, op1, op2, regmsk(REG_SP));
661
 
685
 
662
      stack_size -= 32 ;
686
      stack_size -= 32;
663
   }
687
   }
664
}
688
}
665
 
689
 
666
/************************************************************************
690
/************************************************************************
667
  PUSH_DYNAMIC_CALLEES
691
  PUSH_DYNAMIC_CALLEES
Line 670... Line 694...
670
  Callees size is available in D1 afterwards.
694
  Callees size is available in D1 afterwards.
671
  (modifies A0,D0,D1,SP)
695
  (modifies A0,D0,D1,SP)
672
  ************************************************************************/
696
  ************************************************************************/
673
 
697
 
674
void push_dynamic_callees
698
void push_dynamic_callees
675
    PROTO_N ( ( pcallees, stack ) )
-
 
676
    PROTO_T ( exp pcallees X ash stack )
699
(exp pcallees, ash stack)
677
{
700
{
678
   mach_op *op1, *op2 ;
701
   mach_op *op1, *op2;
679
   exp ptr = son ( pcallees ) ;
702
   exp ptr = son(pcallees);
680
   exp sze = bro ( ptr ) ;
703
   exp sze = bro(ptr);
681
   exp ident, ident_def ;
704
   exp ident, ident_def;
682
   bool const_compound_shape = 0 ;
705
   bool const_compound_shape = 0;
683
   long total_size = 0 ;
706
   long total_size = 0;
684
 
707
 
685
   make_comment("Push dynamic callees");
708
   make_comment("Push dynamic callees");
686
 
709
 
687
   coder ( A1, stack, ptr ) ;
710
   coder(A1, stack, ptr);
688
   coder ( D1, stack, sze ) ;
711
   coder(D1, stack, sze);
689
 
712
 
690
   /* are callees of compond shape ? */
713
   /* are callees of compond shape ? */
691
   if ( name ( ptr ) == name_tag) {
714
   if (name(ptr) == name_tag) {
692
      ident = son ( ptr ) ;
715
      ident = son(ptr);
693
      ident_def = son ( ident ) ;
716
      ident_def = son(ident);
694
      if ( name ( ident_def ) == compound_tag ) {
717
      if (name(ident_def) == compound_tag) {
695
         const_compound_shape = ! ( isvar ( ident ) ) ;
718
         const_compound_shape = !(isvar(ident));
696
      }
719
      }
697
   }
720
   }
698
 
721
 
699
   if ( const_compound_shape ) {
722
   if (const_compound_shape) {
700
      long value ;
723
      long value;
701
      exp pair = son ( ident_def ) ;
724
      exp pair = son(ident_def);
702
      if ( pair ) for (;;) {
725
      if (pair) for (;;) {
703
         pair = bro ( pair ) ;
726
         pair = bro(pair);
704
         value = no ( pair ) ;
727
         value = no(pair);
705
 
728
 
706
         op1 = make_value ( value ) ;
729
         op1 = make_value(value);
707
         op2 = make_dec_sp () ;
730
         op2 = make_dec_sp();
708
         make_instr ( m_movl, op1, op2, regmsk ( REG_SP ) ) ;
731
         make_instr(m_movl, op1, op2, regmsk(REG_SP));
709
         total_size += 4 ;
732
         total_size += 4;
710
 
733
 
711
         if ( last ( pair ) ) break ;
734
         if (last(pair))break;
712
         pair = bro ( pair ) ;
735
         pair = bro(pair);
713
      }
736
      }
714
   }
737
   }
715
   else {
738
   else {
716
      /* Let A0 point to end of callees */
739
      /* Let A0 point to end of callees */
717
      op1 = make_register ( REG_A1 ) ;
740
      op1 = make_register(REG_A1);
718
      op2 = make_register ( REG_A0 ) ;
741
      op2 = make_register(REG_A0);
719
      make_instr ( m_movl, op1, op2, regmsk ( REG_A0 ) ) ;
742
      make_instr(m_movl, op1, op2, regmsk(REG_A0));
720
 
743
 
721
      op1 = make_register ( REG_D1 ) ;
744
      op1 = make_register(REG_D1);
722
      op2 = make_register ( REG_A0 ) ;
745
      op2 = make_register(REG_A0);
723
      make_instr ( m_addl, op1, op2, regmsk ( REG_A0 ) ) ;
746
      make_instr(m_addl, op1, op2, regmsk(REG_A0));
724
 
747
 
725
      push_range ( REG_A0, REG_A1 ) ;
748
      push_range(REG_A0, REG_A1);
726
   }
749
   }
727
 
750
 
728
   if ( call_has_vcallees(pcallees) ) {
751
   if (call_has_vcallees(pcallees)) {
729
      make_comment("push size of dynamic callees on the stack");
752
      make_comment("push size of dynamic callees on the stack");
730
      if ( const_compound_shape ) {
753
      if (const_compound_shape) {
731
         op1 = make_value ( total_size ) ;
754
         op1 = make_value(total_size);
732
      }
755
      }
733
      else {
756
      else {
734
         op1 = make_register ( REG_D1 ) ;
757
         op1 = make_register(REG_D1);
735
      }
758
      }
736
      op2 = make_dec_sp();
759
      op2 = make_dec_sp();
737
      make_instr ( m_movl, op1, op2, regmsk ( REG_SP )) ;
760
      make_instr(m_movl, op1, op2, regmsk(REG_SP));
738
 
761
 
739
      stack_size -= 32 ;
762
      stack_size -= 32;
740
   }
763
   }
741
   else {
764
   else {
742
       debug_warning("call with dynamic callees requires var_callees PROCPROPS");
765
       debug_warning("call with dynamic callees requires var_callees PROCPROPS");
743
   }
766
   }
744
}
767
}
745
 
768
 
746
/************************************************************************
769
/************************************************************************
747
  PUSH_DYNAMIC_CALLEES_BT
770
  PUSH_DYNAMIC_CALLEES_BT
748
 
771
 
749
  Used by tail_call to push dynamic callees
772
  Used by tail_call to push dynamic callees
750
  (modifies A0,A1,D0,D1,SP)
773
  (modifies A0,A1,D0,D1,SP)
751
  ************************************************************************/
774
  ************************************************************************/
752
 
775
 
753
void push_dynamic_callees_bt
776
void push_dynamic_callees_bt
754
    PROTO_N ( ( pcallees, stack ) )
-
 
755
    PROTO_T ( exp pcallees X ash stack )
777
(exp pcallees, ash stack)
756
{
778
{
757
   mach_op *op1, *op2 ;
779
   mach_op *op1, *op2;
758
 
780
 
759
   push_dynamic_callees ( pcallees, stack );
781
   push_dynamic_callees(pcallees, stack);
760
 
782
 
761
   make_comment("push return address");
783
   make_comment("push return address");
762
   op1 = make_indirect ( REG_AP, 4 ) ;
784
   op1 = make_indirect(REG_AP, 4);
763
   op2 = make_dec_sp();
785
   op2 = make_dec_sp();
764
   make_instr ( m_movl, op1, op2, regmsk ( REG_SP ) ) ;
786
   make_instr(m_movl, op1, op2, regmsk(REG_SP));
765
 
787
 
766
   make_comment("put end of callees, size & return address in A1");
788
   make_comment("put end of callees, size & return address in A1");
767
   op1 = make_register ( REG_SP ) ;
789
   op1 = make_register(REG_SP);
768
   op2 = make_register ( REG_A1 ) ;
790
   op2 = make_register(REG_A1);
769
   make_instr ( m_movl, op1, op2, regmsk ( REG_A1 ) ) ;
791
   make_instr(m_movl, op1, op2, regmsk(REG_A1));
770
 
792
 
771
   make_comment("put start of callees in A0");
793
   make_comment("put start of callees in A0");
772
   op1 = make_register ( REG_A1 ) ;
794
   op1 = make_register(REG_A1);
773
   op2 = make_register ( REG_A0 ) ;
795
   op2 = make_register(REG_A0);
774
   make_instr ( m_movl, op1, op2, regmsk ( REG_A0 ) ) ;
796
   make_instr(m_movl, op1, op2, regmsk(REG_A0));
775
 
797
 
776
   /* add size of callee from D1 */
798
   /* add size of callee from D1 */
777
   op1 = make_register ( REG_D1 ) ;
799
   op1 = make_register(REG_D1);
778
   op2 = make_register ( REG_A0 ) ;
800
   op2 = make_register(REG_A0);
779
   make_instr ( m_addl, op1, op2, regmsk ( REG_A0 ) ) ;
801
   make_instr(m_addl, op1, op2, regmsk(REG_A0));
780
 
802
 
781
   /* add size of return address and size of callees size if needed */
803
   /* add size of return address and size of callees size if needed */
782
   op1 = make_value ((call_has_vcallees(pcallees)) ? 8 : 4) ;
804
   op1 = make_value((call_has_vcallees(pcallees))? 8 : 4);
783
   op2 = make_register ( REG_A0 ) ;
805
   op2 = make_register(REG_A0);
784
   make_instr ( m_addl, op1, op2, regmsk ( REG_A0 ) ) ;
806
   make_instr(m_addl, op1, op2, regmsk(REG_A0));
785
 
807
 
786
   cleanup_bt (0, 0) ;
808
   cleanup_bt(0, 0);
787
 
809
 
788
   push_range ( REG_A0, REG_A1 ) ;
810
   push_range(REG_A0, REG_A1);
789
}
811
}
790
 
812
 
791
/************************************************************************
813
/************************************************************************
792
  A1_RESULT_POINTER
814
  A1_RESULT_POINTER
793
 
815
 
794
  For results which do not fit into registers a pointer to
816
  For results which do not fit into registers a pointer to
795
  where the result is to be put is passed in A1
817
  where the result is to be put is passed in A1
796
  ************************************************************************/
818
  ************************************************************************/
797
 
819
 
798
void A1_result_pointer
820
void A1_result_pointer
799
    PROTO_N ( ( comp_size, longs, start_stack, dest ) )
-
 
800
    PROTO_T ( long comp_size X long longs X long start_stack X where dest )
821
(long comp_size, long longs, long start_stack, where dest)
801
{
822
{
802
   if ( comp_size ) {
823
   if (comp_size) {
803
      /* Find the space allocated for unwanted results */
824
      /* Find the space allocated for unwanted results */
804
      where w ;
825
      where w;
805
      w = mnw ( longs / 8 ) ;
826
      w = mnw(longs / 8);
806
      make_comment("let A1 point to unwanted compund result") ;
827
      make_comment("let A1 point to unwanted compund result");
807
      add ( slongsh, SP, w, A1 ) ;
828
      add(slongsh, SP, w, A1);
808
   } else {
829
   } else {
809
      long doff ;
830
      long doff;
810
      /* Find the address of where the result is to be put */
831
      /* Find the address of where the result is to be put */
811
      tmp_reg_prefer = REG_A1 ;
832
      tmp_reg_prefer = REG_A1;
812
      if ( apply_tag_flag ) {
833
      if (apply_tag_flag) {
813
         /* For recursive use of apply_proc or apply_general
834
         /* For recursive use of apply_proc or apply_general
814
            we need to be very careful if the result is itself
835
            we need to be very careful if the result is itself
815
            to be a procedure argument to get the right stack offset. */
836
            to be a procedure argument to get the right stack offset. */
816
 
837
 
817
         /* push old value */
838
         /* push old value */
818
         long ex = extra_stack ;
839
         long ex = extra_stack;
819
         extra_stack += start_stack ;
840
         extra_stack += start_stack;
820
 
841
 
821
         if ( (dest.wh_exp == SP_p.wh_exp) && (dest.wh_is == SP_p.wh_is) ) {
842
         if ((dest.wh_exp == SP_p.wh_exp) && (dest.wh_is == SP_p.wh_is)) {
822
            /* Careful! */
843
            /* Careful! */
823
 
844
 
824
            /* push where offset */
845
            /* push where offset */
825
            doff = dest.wh_off ;
846
            doff = dest.wh_off;
826
 
847
 
827
            dest.wh_off = doff + extra_stack ;
848
            dest.wh_off = doff + extra_stack;
828
 
849
 
829
            make_comment("let A1 point to compund result used as procedure argument") ;
850
            make_comment("let A1 point to compund result used as procedure argument");
830
            mova ( dest, A1 ) ;
851
            mova(dest, A1);
831
 
852
 
832
            /* pop where offset */
853
            /* pop where offset */
833
            dest.wh_off = doff ;
854
            dest.wh_off = doff;
834
 
855
 
835
         } else {
856
         } else {
836
            /* Easy */
857
            /* Easy */
837
            make_comment("let A1 point to compund result from eval. of call par.") ;
858
            make_comment("let A1 point to compund result from eval. of call par.");
838
            mova ( dest, A1 ) ;
859
            mova(dest, A1);
839
         }
860
         }
840
 
861
 
841
         /* pop value after call */
862
         /* pop value after call */
842
         extra_stack = ex  ;
863
         extra_stack = ex ;
843
      }
864
      }
844
      else {
865
      else {
845
         /* Otherwise (easy) ... */
866
         /* Otherwise (easy) ... */
846
         make_comment("let A1 point to compund result") ;
867
         make_comment("let A1 point to compund result");
847
         mova ( dest, A1 ) ;
868
         mova(dest, A1);
848
      }
869
      }
849
   }
870
   }
850
   /* Make sure we don't reuse A1 accidently */
871
   /* Make sure we don't reuse A1 accidently */
851
   avoid_tmp_reg ( REG_A1 ) ;
872
   avoid_tmp_reg(REG_A1);
852
   regsinproc |= regmsk ( REG_A1 ) ;
873
   regsinproc |= regmsk(REG_A1);
853
}
874
}
854
 
875
 
855
/************************************************************************
876
/************************************************************************
856
  POSTLUDE_HAS_CODE
877
  POSTLUDE_HAS_CODE
857
 
878
 
858
  Returns true if postlude has code
879
  Returns true if postlude has code
859
  ************************************************************************/
880
  ************************************************************************/
860
 
881
 
861
static bool postlude_has_code
882
static bool postlude_has_code
862
    PROTO_N ( ( postlude ) )
-
 
863
    PROTO_T ( exp postlude )
883
(exp postlude)
864
{
884
{
865
   while ( name( postlude ) == ident_tag && name(son( postlude )) == caller_name_tag) {
885
   while (name(postlude) == ident_tag && name(son(postlude)) == caller_name_tag) {
866
      postlude = bro( son( postlude ) );
886
      postlude = bro(son(postlude));
867
   }
887
   }
868
   return ( name( postlude ) != top_tag ) ;
888
   return(name(postlude)!= top_tag);
869
}
889
}
870
 
890
 
871
 
891
 
872
/************************************************************************
892
/************************************************************************
873
  APPLY_GENERAL_PROC
893
  APPLY_GENERAL_PROC
874
 
894
 
875
  Code a General Procedure Call.
895
  Code a General Procedure Call.
876
  ************************************************************************/
896
  ************************************************************************/
877
 
897
 
878
void apply_general_proc
898
void apply_general_proc
879
    PROTO_N ( ( e, dest, stack ) )
-
 
880
    PROTO_T ( exp e X where dest X ash stack )
899
(exp e, where dest, ash stack)
881
{
900
{
882
 
901
 
883
   /* Procedure applications */
902
   /* Procedure applications */
884
   exp t ;
903
   exp t;
885
   ash st ;
904
   ash st;
886
   where tmp_dest;
905
   where tmp_dest;
887
   mach_op *op1, *op2 ;
906
   mach_op *op1, *op2;
888
   long comp_size = 0 ;
907
   long comp_size = 0;
889
   long longs = 0, stkdec ;
908
   long longs = 0, stkdec;
890
   long start_stack = stack_dec ;
909
   long start_stack = stack_dec;
891
   long callers_size = 0, callees_size = 0 ; /* size of parameters on the stack */
910
   long callers_size = 0, callees_size = 0 ; /* size of parameters on the stack */
892
   long size_size = 0 ;                      /* size of callees size */
911
   long size_size = 0 ;                      /* size of callees size */
893
   long callees_size_total = 0 ;             /* size of callees and callees size */
912
   long callees_size_total = 0 ;             /* size of callees and callees size */
894
   long result_size = 0 ;                    /* size of result */
913
   long result_size = 0 ;                    /* size of result */
895
 
914
 
896
   bool push_result = 0, use_push = 1, reg_res ;
915
   bool push_result = 0, use_push = 1, reg_res;
897
   bool has_postlude = 0, has_checkstack = 0, is_untidy = 0 ;
916
   bool has_postlude = 0, has_checkstack = 0, is_untidy = 0;
898
 
917
 
899
   exp proc, caller_args, pcallees = 0, postlude = 0, callee_args = 0 ;
918
   exp proc, caller_args, pcallees = 0, postlude = 0, callee_args = 0;
900
 
919
 
901
   make_comment("Apply Proc");
920
   make_comment("Apply Proc");
902
 
921
 
903
   /* Find the procedure and the arguments */
922
   /* Find the procedure and the arguments */
904
 
923
 
905
   tmp_dest = dest ;
924
   tmp_dest = dest;
906
   proc = son ( e ) ;
925
   proc = son(e);
907
   caller_args = (!last(proc)) ? bro (proc) : nilexp;
926
   caller_args = (!last(proc))? bro(proc): nilexp;
908
 
927
 
909
   if ( name(e) == apply_general_tag) {
928
   if (name(e) == apply_general_tag) {
910
      pcallees     = bro ( caller_args ) ;
929
      pcallees     = bro(caller_args);
911
      postlude    = bro ( pcallees );
930
      postlude    = bro(pcallees);
912
      callee_args = son ( pcallees ) ;
931
      callee_args = son(pcallees);
913
      caller_args = son ( caller_args );
932
      caller_args = son(caller_args);
914
 
933
 
915
      is_untidy = call_is_untidy(e);
934
      is_untidy = call_is_untidy(e);
916
      has_checkstack = call_has_checkstack(e);
935
      has_checkstack = call_has_checkstack(e);
917
      has_postlude = postlude_has_code( postlude ) ;
936
      has_postlude = postlude_has_code(postlude);
918
   }
937
   }
-
 
938
 
-
 
939
   /* calculate length of callers and see if we can push them */
919
 
940
 
920
   /* calculate length of callers and see if we can push them */
-
 
921
 
-
 
922
   if (! test_push_args(caller_args, &callers_size) ) use_push = 0;
941
   if (! test_push_args(caller_args, &callers_size))use_push = 0;
923
 
942
 
924
   if ( pcallees ) {
943
   if (pcallees) {
925
      if ( name( pcallees ) == make_callee_list_tag ) {
944
      if (name(pcallees) == make_callee_list_tag) {
926
         /* calculate length of callees and see if we can push them */
945
         /* calculate length of callees and see if we can push them */
927
         if (! test_push_args(callee_args, &callees_size) ) use_push = 0;
946
         if (! test_push_args(callee_args, &callees_size))use_push = 0;
928
      }
-
 
929
      size_size = ( ( call_has_vcallees(pcallees) )?32:0 ) ;
-
 
930
      callees_size_total = callees_size + size_size ;
-
 
931
   }
-
 
932
 
-
 
933
   /* total parameter space */
-
 
934
   longs = callers_size + callees_size_total ;
-
 
935
 
-
 
936
   /* Does the result go into a register? */
-
 
937
   reg_res = result_in_reg ( sh ( e ) ) ;
-
 
938
   if ( !reg_res ) {
-
 
939
      if ( eq_where ( dest, zero ) ) {
-
 
940
         /* Calculate size of ignored compound result */
-
 
941
         comp_size = round ( shape_size ( sh ( e ) ), param_align ) ;
-
 
942
      }
947
      }
-
 
948
      size_size = ((call_has_vcallees(pcallees))?32:0);
-
 
949
      callees_size_total = callees_size + size_size;
943
   }
950
   }
944
 
951
 
-
 
952
   /* total parameter space */
-
 
953
   longs = callers_size + callees_size_total;
-
 
954
 
-
 
955
   /* Does the result go into a register? */
-
 
956
   reg_res = result_in_reg(sh(e));
-
 
957
   if (!reg_res) {
-
 
958
      if (eq_where(dest, zero)) {
-
 
959
         /* Calculate size of ignored compound result */
-
 
960
         comp_size = round(shape_size(sh(e)), param_align);
-
 
961
      }
-
 
962
   }
-
 
963
 
945
   /* Find total amount of stack decrease */
964
   /* Find total amount of stack decrease */
946
   stkdec = longs + comp_size ;
965
   stkdec = longs + comp_size;
947
 
966
 
948
   if ( has_checkstack ) {
967
   if (has_checkstack) {
949
      /* check if there is room for parameters and return address on the stack */
968
      /* check if there is room for parameters and return address on the stack */
950
      checkalloc_stack( mnw( stkdec / 8 + 4 ), 0);
969
      checkalloc_stack(mnw(stkdec / 8 + 4), 0);
951
   }
970
   }
952
 
971
 
953
   /* Put arguments onto stack */
972
   /* Put arguments onto stack */
954
   if ( use_push ) {
973
   if (use_push) {
955
      if ( comp_size ) {
974
      if (comp_size) {
956
         /* Make room for unwanted compound result */
975
         /* Make room for unwanted compound result */
957
         dec_stack ( comp_size ) ;
976
         dec_stack(comp_size);
958
         stack_dec -= comp_size ;
977
         stack_dec -= comp_size;
959
      }
978
      }
960
 
979
 
961
      if ( caller_args ) {
980
      if (caller_args) {
962
         make_comment("Push callers");
981
         make_comment("Push callers");
963
         push_args ( zw ( e ), stack, caller_args ) ;
982
         push_args(zw(e), stack, caller_args);
964
      }
983
      }
965
 
984
 
966
      if ( pcallees ) {
985
      if (pcallees) {
967
         if ( name(pcallees) == make_dynamic_callee_tag ) {
986
         if (name(pcallees) == make_dynamic_callee_tag) {
968
            push_dynamic_callees ( pcallees, stack ) ;
987
            push_dynamic_callees(pcallees, stack);
969
            stack_dec -= callees_size_total ;
988
            stack_dec -= callees_size_total;
970
         }
989
         }
971
         else if ( name(pcallees) == same_callees_tag ) {
990
         else if (name(pcallees) == same_callees_tag) {
972
            push_same_callees(call_has_vcallees(pcallees)) ;
991
            push_same_callees(call_has_vcallees(pcallees));
973
            stack_dec -= callees_size_total ;
992
            stack_dec -= callees_size_total;
974
         }
993
         }
975
         else {
994
         else {
976
            if ( callee_args ) {
995
            if (callee_args) {
977
               make_comment("Push static callees");
996
               make_comment("Push static callees");
978
               push_args ( zw ( e ), stack, callee_args ) ;
997
               push_args(zw(e), stack, callee_args);
979
            }
998
            }
980
            if ( call_has_vcallees(pcallees) ) {
999
            if (call_has_vcallees(pcallees)) {
981
               make_comment("push size of callees on the stack");
1000
               make_comment("push size of callees on the stack");
982
               stack_dec -= 32 ;
1001
               stack_dec -= 32;
983
               stack_size -= 32 ;
1002
               stack_size -= 32;
984
 
1003
 
985
               op1 = make_value ( callees_size / 8 ) ;
1004
               op1 = make_value(callees_size / 8);
986
               op2 = make_dec_sp();
1005
               op2 = make_dec_sp();
987
               make_instr ( m_movl, op1, op2, regmsk ( REG_SP )) ;
1006
               make_instr(m_movl, op1, op2, regmsk(REG_SP));
988
            }
1007
            }
989
         }
1008
         }
990
      }
1009
      }
991
   }
1010
   }
992
   else {
1011
   else {
993
      /* Can't just use push => Decrease stack instead */
1012
      /* Can't just use push => Decrease stack instead */
994
      dec_stack ( stkdec ) ;
1013
      dec_stack(stkdec);
995
      stack_dec -= stkdec ;
1014
      stack_dec -= stkdec;
996
 
1015
 
997
      if ( caller_args ) {
1016
      if (caller_args) {
998
         make_comment("Place callers on the stack");
1017
         make_comment("Place callers on the stack");
999
         place_arguments(caller_args, stack, callees_size_total);
1018
         place_arguments(caller_args, stack, callees_size_total);
1000
      }
1019
      }
1001
      if ( pcallees ) {
1020
      if (pcallees) {
1002
         if ( name(pcallees) == make_dynamic_callee_tag ) {
1021
         if (name(pcallees) == make_dynamic_callee_tag) {
1003
            push_dynamic_callees ( pcallees, stack ) ;
1022
            push_dynamic_callees(pcallees, stack);
1004
         }
1023
         }
1005
         else if ( name(pcallees) == same_callees_tag ) {
1024
         else if (name(pcallees) == same_callees_tag) {
1006
            push_same_callees(call_has_vcallees(pcallees)) ;
1025
            push_same_callees(call_has_vcallees(pcallees));
1007
         }
1026
         }
1008
         else {
1027
         else {
1009
            if ( callee_args ) {
1028
            if (callee_args) {
1010
               make_comment("Place static callees on the stack");
1029
               make_comment("Place static callees on the stack");
1011
               place_arguments(callee_args, stack, size_size);
1030
               place_arguments(callee_args, stack, size_size);
1012
            }
1031
            }
1013
            if ( call_has_vcallees(pcallees) ) {
1032
            if (call_has_vcallees(pcallees)) {
1014
               make_comment("push size of callees on the stack");
1033
               make_comment("push size of callees on the stack");
1015
               op1 = make_value ( callees_size / 8 ) ;
1034
               op1 = make_value(callees_size / 8);
1016
               op2 = make_indirect ( REG_SP, 0 ) ;
1035
               op2 = make_indirect(REG_SP, 0);
1017
               make_instr ( m_movl, op1, op2, regmsk ( REG_SP )) ;
1036
               make_instr(m_movl, op1, op2, regmsk(REG_SP));
1018
            }
1037
            }
1019
         }
1038
         }
1020
      }
1039
      }
1021
   }
1040
   }
1022
 
1041
 
1023
   start_stack -= stack_dec ;
1042
   start_stack -= stack_dec;
1024
 
1043
 
1025
   if ( !reg_res )
1044
   if (!reg_res)
1026
   A1_result_pointer(comp_size, longs, start_stack, dest) ;
1045
   A1_result_pointer(comp_size, longs, start_stack, dest);
1027
 
1046
 
1028
   /* Output the call instruction */
1047
   /* Output the call instruction */
1029
   callins ( 0, proc ) ;
1048
   callins(0, proc);
1030
 
1049
 
1031
   if ( is_untidy ) {
1050
   if (is_untidy) {
1032
      stack_dec = 0; /* We can't keep track of it any longer */
1051
      stack_dec = 0; /* We can't keep track of it any longer */
1033
      if (need_preserve_stack)
1052
      if (need_preserve_stack)
1034
      save_stack ();
1053
      save_stack();
1035
   }
1054
   }
1036
   else {
1055
   else {
1037
      /* callees has now been cleaned up by called proc. */
1056
      /* callees has now been cleaned up by called proc. */
1038
      stack_dec += callees_size_total ;
1057
      stack_dec += callees_size_total;
1039
      stack_size += callees_size_total ;
1058
      stack_size += callees_size_total;
1040
   }
1059
   }
1041
 
1060
 
1042
   /* can we cleanup callers now ? */
1061
   /* can we cleanup callers now ? */
1043
   if ( ! ( has_postlude || is_untidy ) ) {
1062
   if (!(has_postlude || is_untidy)) {
1044
      /* Clean up of callers and room for ignored compund result. */
1063
      /* Clean up of callers and room for ignored compund result. */
1045
      stack_dec += callers_size + comp_size ;
1064
      stack_dec += callers_size + comp_size;
1046
      dec_stack ( - callers_size - comp_size );
1065
      dec_stack(- callers_size - comp_size);
1047
   }
1066
   }
1048
 
1067
 
1049
   /* Move the result into place */
1068
   /* Move the result into place */
1050
   if ( comp_size ) {
1069
   if (comp_size) {
1051
      make_comment("(unwanted compound result)");
1070
      make_comment("(unwanted compound result)");
1052
   }
1071
   }
1053
   else
1072
   else
1054
   if ( eq_where ( dest, zero ) ) {
1073
   if (eq_where(dest, zero)) {
1055
      make_comment("(unwanted simple result)");
1074
      make_comment("(unwanted simple result)");
1056
   }
1075
   }
1057
   else {
1076
   else {
1058
      /* ok the result is needed */
1077
      /* ok the result is needed */
1059
      if ( has_postlude ) {
1078
      if (has_postlude) {
1060
         /* we need to preserve result on stack */
1079
         /* we need to preserve result on stack */
1061
         result_size = rounder (shape_size(sh(e)), param_align);
1080
         result_size = rounder(shape_size(sh(e)), param_align);
1062
         dec_stack ( result_size ) ;
1081
         dec_stack(result_size);
1063
         stack_dec -= result_size;
1082
         stack_dec -= result_size;
1064
         tmp_dest = SP_p ;
1083
         tmp_dest = SP_p;
1065
         push_result = 1 ;
1084
         push_result = 1;
1066
      }
1085
      }
1067
      if ( reg_res ) {
1086
      if (reg_res) {
1068
         if ( shape_size ( sh ( e ) ) <= 32 ) {
1087
         if (shape_size(sh(e)) <= 32) {
1069
            /* Small register results are in D0 */
1088
            /* Small register results are in D0 */
1070
            move ( sh ( e ), D0, tmp_dest ) ;
1089
            move(sh(e), D0, tmp_dest);
1071
         } else {
1090
         } else {
1072
            /* Larger register results are in D0 and D1 */
1091
            /* Larger register results are in D0 and D1 */
1073
#ifdef SYSV_ABI
1092
#ifdef SYSV_ABI
1074
            move ( sh ( e ), FP0, tmp_dest ) ;
1093
            move(sh(e), FP0, tmp_dest);
1075
#else
1094
#else
1076
            move ( sh ( e ), D0_D1, tmp_dest ) ;
1095
            move(sh(e), D0_D1, tmp_dest);
1077
            regsinproc |= regmsk ( REG_D1 ) ;
1096
            regsinproc |= regmsk(REG_D1);
1078
#endif
1097
#endif
1079
         }
1098
         }
1080
      } else {
1099
      } else {
1081
         make_comment("(compound result)");
1100
         make_comment("(compound result)");
1082
         if ( has_postlude ) {
1101
         if (has_postlude) {
1083
            make_comment("save compound result before postlude...") ;
1102
            make_comment("save compound result before postlude...");
1084
            move ( sh ( e ), dest, tmp_dest ) ;
1103
            move(sh(e), dest, tmp_dest);
1085
            make_comment("save compound result before postlude done") ;
1104
            make_comment("save compound result before postlude done");
1086
         }
1105
         }
1087
 
1106
 
1088
         /* Compound results should already have been copied to
1107
         /* Compound results should already have been copied to
1089
            the position pointed to by A1 by the called procedure
1108
            the position pointed to by A1 by the called procedure
1090
            and returned by it in D0, so no further action should
1109
            and returned by it in D0, so no further action should
1091
            be required by the calling procedure.  Unfortunately
1110
            be required by the calling procedure.  Unfortunately
1092
            cc doesn't always get this right for union results. */
1111
            cc doesn't always get this right for union results. */
1093
#ifdef OLD_SPEC
1112
#ifdef OLD_SPEC
1094
         if ( cc_conventions && name ( sh ( e ) ) == unhd ) {
1113
         if (cc_conventions && name(sh(e)) == unhd) {
1095
            regsinproc |= regmsk ( REG_A0 ) ;
1114
            regsinproc |= regmsk(REG_A0);
1096
            move ( slongsh, D0, A0 ) ;
1115
            move(slongsh, D0, A0);
1097
            move ( sh ( e ), A0_p, dest ) ;
1116
            move(sh(e), A0_p, dest);
1098
         }
1117
         }
1099
#endif
1118
#endif
1100
      }
1119
      }
1101
   }
1120
   }
1102
 
1121
 
1103
   if ( has_postlude ) {
1122
   if (has_postlude) {
1104
      code_postlude(postlude, caller_args, stack, result_size ) ;
1123
      code_postlude(postlude, caller_args, stack, result_size);
1105
 
1124
 
1106
      /* put return value back in register */
1125
      /* put return value back in register */
1107
      if ( push_result ) {
1126
      if (push_result) {
1108
         make_comment("restore result after postlude...") ;
1127
         make_comment("restore result after postlude...");
1109
         move(sh(e), SP_p, dest);
1128
         move(sh(e), SP_p, dest);
1110
         make_comment("restore result after postlude done") ;
1129
         make_comment("restore result after postlude done");
1111
         dec_stack ( -result_size ) ;
1130
         dec_stack(-result_size);
1112
         stack_dec += result_size;
1131
         stack_dec += result_size;
1113
      }
1132
      }
1114
 
1133
 
1115
      /* Delayed clean up of callers and room for ignored compund result.
1134
      /* Delayed clean up of callers and room for ignored compund result.
1116
         callees are cleaned by the called proc. */
1135
         callees are cleaned by the called proc. */
1117
      if ( ! is_untidy ) {
1136
      if (! is_untidy) {
1118
         stack_dec += callers_size + comp_size ;
1137
         stack_dec += callers_size + comp_size;
1119
         dec_stack ( - callers_size - comp_size );
1138
         dec_stack(- callers_size - comp_size);
1120
      }
1139
      }
1121
   }
1140
   }
1122
}
1141
}
1123
 
1142
 
1124
/************************************************************************
1143
/************************************************************************
Line 1131... Line 1150...
1131
  The args_size is also used if false is returned.
1150
  The args_size is also used if false is returned.
1132
 
1151
 
1133
  ************************************************************************/
1152
  ************************************************************************/
1134
 
1153
 
1135
static bool test_push_args
1154
static bool test_push_args
1136
    PROTO_N ( (args, args_size) )
-
 
1137
    PROTO_T ( exp args X ash* args_size )
1155
(exp args, ash* args_size)
1138
{
1156
{
1139
 
1157
 
1140
   /* See if we can push all the arguments */
1158
   /* See if we can push all the arguments */
1141
 
1159
 
1142
   bool use_push = 1 ;
1160
   bool use_push = 1;
1143
   exp arg = args, formal ;
1161
   exp arg = args, formal;
1144
   ash stack = 0 ;
1162
   ash stack = 0;
1145
   ast stack_add_res;
1163
   ast stack_add_res;
1146
 
1164
 
1147
   while ( arg != nilexp ) {
1165
   while (arg != nilexp) {
1148
      formal = ( name ( arg ) == caller_tag) ? son ( arg ) : arg ;
1166
      formal = (name(arg) == caller_tag)? son(arg): arg;
1149
 
1167
 
1150
      if ( cpd_param ( sh ( formal ) ) ) use_push = 0 ;
1168
      if (cpd_param(sh(formal)))use_push = 0;
1151
      if ((name(sh(formal)) == s64hd) || (name(sh(formal)) == u64hd)) use_push = 0;
1169
      if ((name(sh(formal)) == s64hd) || (name(sh(formal)) == u64hd))use_push = 0;
1152
      if (! push_arg ( formal ) ) use_push = 0 ;
1170
      if (! push_arg(formal))use_push = 0;
1153
 
1171
 
1154
      stack_add_res = add_shape_to_stack ( stack, sh ( formal ) ) ;
1172
      stack_add_res = add_shape_to_stack(stack, sh(formal));
1155
      stack = stack_add_res.astash ;
1173
      stack = stack_add_res.astash;
1156
 
1174
 
1157
      /* information used by code_postlude */
1175
      /* information used by code_postlude */
1158
      if ( name ( arg ) == caller_tag)
1176
      if (name(arg) == caller_tag)
1159
      no ( arg ) = stack_add_res.astoff + stack_add_res.astadj ;
1177
      no(arg) = stack_add_res.astoff + stack_add_res.astadj;
1160
 
1178
 
1161
      arg = ( last ( arg ) ? nilexp : bro ( arg ) ) ;
1179
      arg = (last(arg)? nilexp : bro(arg));
1162
   }
1180
   }
1163
 
1181
 
1164
   (* args_size) = stack ;
1182
  (* args_size) = stack;
1165
 
1183
 
1166
 
1184
 
1167
   return use_push ;
1185
   return use_push;
1168
}
1186
}
1169
 
1187
 
1170
 
1188
 
1171
/************************************************************************
1189
/************************************************************************
1172
  PLACE_ARGUMENTS
1190
  PLACE_ARGUMENTS
1173
 
1191
 
1174
  Encodes procedure arguments on the stack.
1192
  Encodes procedure arguments on the stack.
1175
  ************************************************************************/
1193
  ************************************************************************/
1176
 
1194
 
1177
static void place_arguments
1195
static void place_arguments
1178
    PROTO_N ( (args, stack, start) )
-
 
1179
    PROTO_T ( exp args X ash stack X long start )
1196
(exp args, ash stack, long start)
1180
{
1197
{
1181
   exp arg = args ;
1198
   exp arg = args;
1182
   ast stack_add_res ;
1199
   ast stack_add_res;
1183
   where stack_pointer ;
1200
   where stack_pointer;
1184
   long adj ;
1201
   long adj;
1185
   long st = start ;
1202
   long st = start;
1186
 
1203
 
1187
   /* Indicate recursive calls */
1204
   /* Indicate recursive calls */
1188
   apply_tag_flag ++ ;
1205
   apply_tag_flag ++;
1189
 
1206
 
1190
   /* Encode the arguments onto the stack */
1207
   /* Encode the arguments onto the stack */
1191
   while (arg != nilexp) {
1208
   while (arg != nilexp) {
1192
      exp formal = ( name ( arg ) == caller_tag) ? son ( arg ) : arg ;
1209
      exp formal = (name(arg) == caller_tag)? son(arg): arg;
1193
 
1210
 
1194
      char nc = name ( sh ( formal ) ) ;
1211
      char nc = name(sh(formal));
1195
      if ( nc == scharhd || nc == ucharhd ) adj = 24 ;
1212
      if (nc == scharhd || nc == ucharhd)adj = 24;
1196
      else
1213
      else
1197
      if ( nc == swordhd || nc == uwordhd ) adj = 16 ;
1214
      if (nc == swordhd || nc == uwordhd)adj = 16;
1198
      else adj = 0 ;
1215
      else adj = 0;
1199
 
-
 
1200
      stack_pointer = mw ( SP_p.wh_exp, st + adj ) ;
-
 
1201
      coder ( stack_pointer, stack, formal ) ;
-
 
1202
      stack_add_res = add_shape_to_stack ( st, sh ( formal ) ) ;
-
 
1203
      st = stack_add_res.astash ;
-
 
1204
 
1216
 
-
 
1217
      stack_pointer = mw(SP_p.wh_exp, st + adj);
-
 
1218
      coder(stack_pointer, stack, formal);
-
 
1219
      stack_add_res = add_shape_to_stack(st, sh(formal));
-
 
1220
      st = stack_add_res.astash;
-
 
1221
 
1205
      arg = ( last ( arg ) ? nilexp : bro ( arg ) ) ;
1222
      arg = (last(arg)? nilexp : bro(arg));
1206
   }
1223
   }
1207
 
1224
 
1208
   apply_tag_flag -- ;
1225
   apply_tag_flag --;
1209
}
1226
}
1210
 
1227
 
1211
/************************************************************************
1228
/************************************************************************
1212
  PUSH A SET OF PROCEDURE ARGUMENTS
1229
  PUSH A SET OF PROCEDURE ARGUMENTS
1213
 
1230
 
1214
  The arguments are given by a bro-list t.
1231
  The arguments are given by a bro-list t.
1215
  They are coded in reverse order.
1232
  They are coded in reverse order.
1216
  ************************************************************************/
1233
  ************************************************************************/
1217
 
1234
 
1218
static void push_args
1235
static void push_args
1219
    PROTO_N ( ( w, stack, args ) )
-
 
1220
    PROTO_T ( where w X ash stack X exp args )
1236
(where w, ash stack, exp args)
1221
{
1237
{
1222
   long sz = shape_size ( sh ( args ) ) ;
1238
   long sz = shape_size(sh(args));
1223
   exp formal ;
1239
   exp formal;
1224
 
1240
 
1225
   if ( last ( args ) ) {
1241
   if (last(args)) {
1226
      /* Code last argument */
1242
      /* Code last argument */
1227
      formal = ( name ( args ) == caller_tag) ? son ( args ) : args ;
1243
      formal = (name(args) == caller_tag)? son(args): args;
1228
      coder ( w, stack, formal ) ;
1244
      coder(w, stack, formal);
1229
      stack_dec -= rounder ( sz, param_align ) ;
1245
      stack_dec -= rounder(sz, param_align);
1230
   } else {
1246
   } else {
1231
      /* Code the following arguments */
1247
      /* Code the following arguments */
1232
      push_args ( w, stack, bro ( args ) ) ;
1248
      push_args(w, stack, bro(args));
1233
      /* And then this one */
1249
      /* And then this one */
1234
      formal = ( name ( args ) == caller_tag) ? son ( args ) : args ;
1250
      formal = (name(args) == caller_tag)? son(args): args;
1235
      coder ( w, stack, formal ) ;
1251
      coder(w, stack, formal);
1236
      stack_dec -= rounder ( sz, param_align  ) ;
1252
      stack_dec -= rounder(sz, param_align );
1237
   }
1253
   }
1238
   return ;
1254
   return;
1239
}
1255
}
1240
 
1256
 
1241
/************************************************************************
1257
/************************************************************************
1242
  TAIL_CALL
1258
  TAIL_CALL
1243
 
1259
 
1244
  Code a tail call.
1260
  Code a tail call.
1245
  ************************************************************************/
1261
  ************************************************************************/
1246
 
1262
 
1247
void tail_call
1263
void tail_call
1248
    PROTO_N ( ( e, dest, stack ) )
-
 
1249
    PROTO_T ( exp e X where dest X ash stack )
1264
(exp e, where dest, ash stack)
1250
{
1265
{
1251
   exp proc        = son ( e );
1266
   exp proc        = son(e);
1252
   exp pcallees     = bro( proc );
1267
   exp pcallees     = bro(proc);
1253
   exp callee_args = son ( pcallees );
1268
   exp callee_args = son(pcallees);
1254
   int longs;
1269
   int longs;
1255
   mach_op *op1, *op2 ;
1270
   mach_op *op1, *op2;
1256
   long new_callees_size ;
1271
   long new_callees_size;
1257
   bool use_push = 1 ;
1272
   bool use_push = 1;
1258
 
1273
 
1259
   make_comment("Tail Call");
1274
   make_comment("Tail Call");
1260
 
1275
 
1261
   update_stack() ;
1276
   update_stack();
1262
 
1277
 
1263
   if ( name(pcallees) == make_dynamic_callee_tag ) {
1278
   if (name(pcallees) == make_dynamic_callee_tag) {
1264
      /* A0 and A1 are used by cleanup. We are just about to make the tail
1279
      /* A0 and A1 are used by cleanup. We are just about to make the tail
1265
         call with shape bottom, so they are free */
1280
         call with shape bottom, so they are free */
1266
      push_dynamic_callees_bt ( pcallees, stack ) ;
1281
      push_dynamic_callees_bt(pcallees, stack);
1267
      jmpins(proc) ;
1282
      jmpins(proc);
1268
      return ;
1283
      return;
1269
   }
1284
   }
1270
 
1285
 
1271
   /* same callees ? */
1286
   /* same callees ? */
1272
 
1287
 
1273
   if ( name(pcallees) == same_callees_tag ) {
1288
   if (name(pcallees) == same_callees_tag) {
1274
      restore_regs(ALL) ;
1289
      restore_regs(ALL);
1275
 
1290
 
1276
      if ( ! cur_proc_has_vcallees  && call_has_vcallees(pcallees) ) {
1291
      if (! cur_proc_has_vcallees  && call_has_vcallees(pcallees)) {
1277
         make_comment("push size of same static callees and ret.addr. on the stack");
1292
         make_comment("push size of same static callees and ret.addr. on the stack");
1278
         op1 = make_indirect ( REG_SP, 0 ) ;
1293
         op1 = make_indirect(REG_SP, 0);
1279
         op2 = make_register ( REG_D0 );
1294
         op2 = make_register(REG_D0);
1280
         make_instr ( m_movl, op1, op2, regmsk ( REG_SP )) ;
1295
         make_instr(m_movl, op1, op2, regmsk(REG_SP));
1281
 
1296
 
1282
         op1 = make_callees_size () ;
1297
         op1 = make_callees_size();
1283
         op2 = make_indirect ( REG_SP, 0 ) ;
1298
         op2 = make_indirect(REG_SP, 0);
1284
         make_instr ( m_movl, op1, op2, regmsk ( REG_SP )) ;
1299
         make_instr(m_movl, op1, op2, regmsk(REG_SP));
1285
 
1300
 
1286
         op1 = make_register ( REG_D0 );
1301
         op1 = make_register(REG_D0);
1287
         op2 = make_dec_sp () ;
1302
         op2 = make_dec_sp();
1288
         make_instr ( m_movl, op1, op2, regmsk ( REG_SP )) ;
1303
         make_instr(m_movl, op1, op2, regmsk(REG_SP));
1289
      }
1304
      }
1290
      else if ( cur_proc_has_vcallees  && ! call_has_vcallees(pcallees) ) {
1305
      else if (cur_proc_has_vcallees  && ! call_has_vcallees(pcallees)) {
1291
         make_comment("remove size of same static callees from the stack");
1306
         make_comment("remove size of same static callees from the stack");
1292
         op1 = make_inc_sp () ;
1307
         op1 = make_inc_sp();
1293
         op2 = make_indirect ( REG_SP, 0 ) ;
1308
         op2 = make_indirect(REG_SP, 0);
1294
         make_instr ( m_movl, op1, op2, regmsk ( REG_SP )) ;
1309
         make_instr(m_movl, op1, op2, regmsk(REG_SP));
1295
      }
1310
      }
1296
      jmpins(proc) ;
1311
      jmpins(proc);
1297
      return ;
1312
      return;
1298
   }
1313
   }
1299
 
1314
 
1300
   /* nothing more than same calleers ? */
1315
   /* nothing more than same calleers ? */
1301
 
1316
 
1302
   if (! (callee_args || cur_proc_has_vcallees || call_has_vcallees(pcallees))) {
1317
   if (!(callee_args || cur_proc_has_vcallees || call_has_vcallees(pcallees))) {
1303
      restore_regs(ALL) ;
1318
      restore_regs(ALL);
1304
      jmpins(proc) ;
1319
      jmpins(proc);
1305
      return ;
1320
      return;
1306
   }
1321
   }
1307
 
1322
 
1308
   /* no callees ? */
1323
   /* no callees ? */
1309
 
1324
 
1310
   if ( ! callee_args ) {
1325
   if (! callee_args) {
1311
      make_comment("save return address");
1326
      make_comment("save return address");
1312
      op1 = make_indirect ( REG_AP, 4 ) ;
1327
      op1 = make_indirect(REG_AP, 4);
1313
      op2 = make_register ( REG_A1 ) ;
1328
      op2 = make_register(REG_A1);
1314
      make_instr ( m_movl, op1, op2, regmsk ( REG_D0 ) ) ;
1329
      make_instr(m_movl, op1, op2, regmsk(REG_D0));
1315
 
1330
 
1316
      cleanup_bt(0,0);
1331
      cleanup_bt(0,0);
1317
 
1332
 
1318
      if ( call_has_vcallees( pcallees ) ) {
1333
      if (call_has_vcallees(pcallees)) {
1319
         make_comment("push zero size of callees on the stack");
1334
         make_comment("push zero size of callees on the stack");
1320
         op1 = make_value ( 0 ) ;
1335
         op1 = make_value(0);
1321
         op2 = make_dec_sp();
1336
         op2 = make_dec_sp();
1322
         make_instr ( m_movl, op1, op2, regmsk ( REG_SP )) ;
1337
         make_instr(m_movl, op1, op2, regmsk(REG_SP));
1323
      }
1338
      }
1324
 
1339
 
1325
      make_comment("push return address back");
1340
      make_comment("push return address back");
1326
      op1 = make_register ( REG_A1 ) ;
1341
      op1 = make_register(REG_A1);
1327
      op2 = make_dec_sp();
1342
      op2 = make_dec_sp();
1328
      make_instr ( m_movl, op1, op2, regmsk ( REG_SP )) ;
1343
      make_instr(m_movl, op1, op2, regmsk(REG_SP));
1329
 
1344
 
1330
      jmpins(proc) ;
1345
      jmpins(proc);
1331
      return ;
1346
      return;
1332
   }
1347
   }
1333
 
1348
 
1334
   /* new callees ! */
1349
   /* new callees ! */
1335
 
1350
 
1336
   if (! test_push_args(callee_args, &new_callees_size) ) use_push = 0;
1351
   if (! test_push_args(callee_args, &new_callees_size))use_push = 0;
1337
 
1352
 
1338
   if ( use_push ) {
1353
   if (use_push) {
1339
      make_comment("Push callees");
1354
      make_comment("Push callees");
1340
      push_args ( zw ( e ), stack, callee_args ) ;
1355
      push_args(zw(e), stack, callee_args);
1341
   }
1356
   }
1342
   else {
1357
   else {
1343
      /* Decrease stack */
1358
      /* Decrease stack */
1344
      dec_stack ( new_callees_size ) ;
1359
      dec_stack(new_callees_size);
1345
      stack_dec -= new_callees_size ;
1360
      stack_dec -= new_callees_size;
1346
      place_arguments(callee_args, stack, 0) ;
1361
      place_arguments(callee_args, stack, 0);
1347
   }
1362
   }
1348
 
1363
 
1349
   if ( call_has_vcallees(pcallees) ) {
1364
   if (call_has_vcallees(pcallees)) {
1350
      make_comment("push size of new callees on the stack");
1365
      make_comment("push size of new callees on the stack");
1351
      op1 = make_value ( new_callees_size / 8 ) ;
1366
      op1 = make_value(new_callees_size / 8);
1352
      op2 = make_dec_sp();
1367
      op2 = make_dec_sp();
1353
      make_instr ( m_movl, op1, op2, regmsk ( REG_SP )) ;
1368
      make_instr(m_movl, op1, op2, regmsk(REG_SP));
1354
   }
1369
   }
1355
 
1370
 
1356
   make_comment("push return address");
1371
   make_comment("push return address");
1357
   op1 = make_indirect ( REG_AP, 4 ) ;
1372
   op1 = make_indirect(REG_AP, 4);
1358
   op2 = make_dec_sp();
1373
   op2 = make_dec_sp();
1359
   make_instr ( m_movl, op1, op2, regmsk ( REG_SP ) ) ;
1374
   make_instr(m_movl, op1, op2, regmsk(REG_SP));
1360
 
1375
 
1361
   /*
1376
   /*
1362
      Setup source, dest and end mark for push_range
1377
      Setup source, dest and end mark for push_range
1363
      We will use D1 & A0.
1378
      We will use D1 & A0.
1364
      */
1379
      */
1365
 
1380
 
1366
   make_comment("save end of new callees and return address");
1381
   make_comment("save end of new callees and return address");
1367
   op1 = make_register ( REG_SP ) ;
1382
   op1 = make_register(REG_SP);
1368
   op2 = make_register ( REG_D1 ) ;
1383
   op2 = make_register(REG_D1);
1369
   make_instr ( m_movl, op1, op2, regmsk ( REG_D1 ) ) ;
1384
   make_instr(m_movl, op1, op2, regmsk(REG_D1));
1370
 
1385
 
1371
   make_comment("save start of new callees and return address");
1386
   make_comment("save start of new callees and return address");
1372
   op1 = make_register ( REG_SP ) ;
1387
   op1 = make_register(REG_SP);
1373
   op2 = make_register ( REG_A0 ) ;
1388
   op2 = make_register(REG_A0);
1374
   make_instr ( m_movl, op1, op2, regmsk ( REG_A0 ) ) ;
1389
   make_instr(m_movl, op1, op2, regmsk(REG_A0));
1375
 
1390
 
1376
   /* add sizeof(new calless) sizeof(ret-addr) + ?+sizeof(callees size)? */
1391
   /* add sizeof(new calless) sizeof(ret-addr) + ?+sizeof(callees size)? */
1377
   op1 = make_value(new_callees_size/8+4+(call_has_vcallees(pcallees)?4:0));
1392
   op1 = make_value(new_callees_size/8+4+ (call_has_vcallees(pcallees)?4:0));
1378
   op2 = make_register ( REG_A0 ) ;
1393
   op2 = make_register(REG_A0);
1379
   make_instr ( m_addl, op1, op2, regmsk ( REG_A0 ) ) ;
1394
   make_instr(m_addl, op1, op2, regmsk(REG_A0));
1380
 
1395
 
1381
   cleanup_bt(0,0) ;
1396
   cleanup_bt(0,0);
1382
 
1397
 
1383
   make_comment("push the new callees");
1398
   make_comment("push the new callees");
1384
   push_range ( REG_A0, REG_D1 ) ;
1399
   push_range(REG_A0, REG_D1);
1385
 
1400
 
1386
   /* make the jump instruction */
1401
   /* make the jump instruction */
1387
   jmpins(proc) ;
1402
   jmpins(proc);
1388
}
1403
}
1389
 
1404
 
1390
 
1405
 
1391
/************************************************************************
1406
/************************************************************************
1392
  GENERAL PURPOSE PROCEDURE EPILOGUE
1407
  GENERAL PURPOSE PROCEDURE EPILOGUE
Line 1396... Line 1411...
1396
  There is some testing to see if D1, A0, A1 and FP1 can be put to
1411
  There is some testing to see if D1, A0, A1 and FP1 can be put to
1397
  better use.
1412
  better use.
1398
  ************************************************************************/
1413
  ************************************************************************/
1399
 
1414
 
1400
void general_epilogue
1415
void general_epilogue
1401
    PROTO_N ( ( uses_callers_pointer, has_checkstack ) )
-
 
1402
    PROTO_T ( bool uses_callers_pointer X bool has_checkstack )
1416
(bool uses_callers_pointer, bool has_checkstack)
1403
{
1417
{
1404
   int r, instruction_id ;
1418
   int r, instruction_id;
1405
   bitpattern m ;
1419
   bitpattern m;
1406
   long st, st1 ;
1420
   long st, st1;
1407
   mach_op *op1, *op2 ;
1421
   mach_op *op1, *op2;
1408
   mach_ins * save_ins_pointer ;
1422
   mach_ins * save_ins_pointer;
1409
 
1423
 
1410
   int tmp_d1 = -1, tmp_a0 = -1, tmp_a1 = -1 ;
1424
   int tmp_d1 = -1, tmp_a0 = -1, tmp_a1 = -1;
1411
 
1425
 
1412
   bitpattern rmsk = regs ( regsinproc & save_msk ) ;
1426
   bitpattern rmsk = regs(regsinproc & save_msk);
1413
   bitpattern smsk = rmsk ;
1427
   bitpattern smsk = rmsk;
1414
   bitpattern cmsk = 0 ;
1428
   bitpattern cmsk = 0;
1415
   bitpattern fmsk = 0 ;
1429
   bitpattern fmsk = 0;
1416
   bitpattern fsmsk = fregs ( regsinproc & save_msk ) ;
1430
   bitpattern fsmsk = fregs(regsinproc & save_msk);
1417
   bool d1_free ;
1431
   bool d1_free;
1418
   bool save_d1 = 0 ;
1432
   bool save_d1 = 0;
1419
   bool uses_link = 0 ;
1433
   bool uses_link = 0;
1420
 
1434
 
1421
   make_comment("Epilogue");
1435
   make_comment("Epilogue");
1422
 
1436
 
1423
   /* restore the default floating point rounding mode */
1437
   /* restore the default floating point rounding mode */
1424
   reset_round_mode();
1438
   reset_round_mode();
1425
 
1439
 
1426
   for ( r = REG_FP7, m = 1 ; r >= REG_FP2 ; r--, m <<= 1 ) {
1440
   for (r = REG_FP7, m = 1; r >= REG_FP2; r--, m <<= 1) {
1427
      if ( regsinproc & regmsk ( r ) ) fmsk |= m ;
1441
      if (regsinproc & regmsk(r))fmsk |= m;
1428
   }
1442
   }
1429
 
1443
 
1430
   /* any calls? */
1444
   /* any calls? */
1431
   if ( no_calls > 0 ) {
1445
   if (no_calls > 0) {
1432
      if (uses_callers_pointer) {
1446
      if (uses_callers_pointer) {
1433
         /* Variable number of calles => A5 used as pointer to first caller */
1447
         /* Variable number of calles => A5 used as pointer to first caller */
1434
         smsk &= ~regmsk ( REG_A5 ) ;
1448
         smsk &= ~regmsk(REG_A5);
1435
      }
1449
      }
1436
 
1450
 
1437
      smsk &= ~bigregs ;
1451
      smsk &= ~bigregs;
1438
      fsmsk &= ~bigregs ;
1452
      fsmsk &= ~bigregs;
1439
   }
1453
   }
1440
 
1454
 
1441
   make_label ( crt_ret_lab ) ;
1455
   make_label(crt_ret_lab);
1442
 
1456
 
1443
#if have_diagnostics
1457
#if have_diagnostics
1444
   if ( diagnose ) xdb_diag_proc_return () ;
1458
   if (diagnose)xdb_diag_proc_return();
1445
#endif
1459
#endif
1446
 
1460
 
1447
   d1_free = !( regsinproc & regmsk ( REG_D1 ) ) ;
1461
   d1_free = !(regsinproc & regmsk(REG_D1));
1448
 
1462
 
1449
   /* Use D1 if not already used */
1463
   /* Use D1 if not already used */
1450
   if ( d1_free ) {
1464
   if (d1_free) {
1451
      m = smsk & dreg_msk ;     /* m = set of D'regs */
1465
      m = smsk & dreg_msk ;     /* m = set of D'regs */
1452
      if ( m ) {
1466
      if (m) {
1453
         /* Replace a used D-register by D1 */
1467
         /* Replace a used D-register by D1 */
1454
         r = reg ( m ) ;        /* get the first free register number in the set */
1468
         r = reg ( m ) ;        /* get the first free register number in the set */
1455
         reg_names [r] = reg_names [ REG_D1 ] ;
1469
         reg_names[r] = reg_names[REG_D1];
1456
         rmsk &= ~regmsk ( r ) ;
1470
         rmsk &= ~regmsk(r);
1457
         smsk &= ~regmsk ( r ) ;
1471
         smsk &= ~regmsk(r);
1458
         cmsk |= regmsk ( r ) ;
1472
         cmsk |= regmsk(r);
1459
         d1_free = 0 ;
1473
         d1_free = 0;
1460
      }
1474
      }
1461
   }
1475
   }
1462
 
1476
 
1463
   /* Use A0 if not already used */
1477
   /* Use A0 if not already used */
1464
   if ( !( regsinproc & regmsk ( REG_A0 ) ) ) {
1478
   if (!(regsinproc & regmsk(REG_A0))) {
1465
      m = smsk & areg_msk ;
1479
      m = smsk & areg_msk;
1466
      if ( m ) {
1480
      if (m) {
1467
         /* Replace a used A-register by A0 */
1481
         /* Replace a used A-register by A0 */
1468
         r = reg ( m ) ;
1482
         r = reg(m);
1469
         reg_names [r] = reg_names [ REG_A0 ] ;
1483
         reg_names[r] = reg_names[REG_A0];
1470
         rmsk &= ~regmsk ( r ) ;
1484
         rmsk &= ~regmsk(r);
1471
         smsk &= ~regmsk ( r ) ;
1485
         smsk &= ~regmsk(r);
1472
         cmsk |= regmsk ( r ) ;
1486
         cmsk |= regmsk(r);
1473
      } else if ( no_calls == 0 ) {
1487
      } else if (no_calls == 0) {
1474
         m = rmsk & dreg_msk ;
1488
         m = rmsk & dreg_msk;
1475
         if ( m ) {
1489
         if (m) {
1476
            /* Move a used D-register into A0 */
1490
            /* Move a used D-register into A0 */
1477
            tmp_a0 = reg ( m ) ;
1491
            tmp_a0 = reg(m);
1478
            rmsk &= ~regmsk ( tmp_a0 ) ;
1492
            rmsk &= ~regmsk(tmp_a0);
1479
            smsk = rmsk ;
1493
            smsk = rmsk;
1480
            op1 = make_register ( REG_A0 ) ;
1494
            op1 = make_register(REG_A0);
1481
            op2 = make_register ( tmp_a0 ) ;
1495
            op2 = make_register(tmp_a0);
1482
            make_instr ( m_movl, op1, op2, regmsk ( tmp_a0 ) ) ;
1496
            make_instr(m_movl, op1, op2, regmsk(tmp_a0));
1483
            just_ret = 0 ;
1497
            just_ret = 0;
1484
         }
1498
         }
1485
      }
1499
      }
1486
   }
1500
   }
1487
 
1501
 
1488
   /* Use A1 if not already used */
1502
   /* Use A1 if not already used */
1489
   if ( !( regsinproc & regmsk ( REG_A1 ) ) ) {
1503
   if (!(regsinproc & regmsk(REG_A1))) {
1490
      m = smsk & areg_msk ;
1504
      m = smsk & areg_msk;
1491
      if ( m ) {
1505
      if (m) {
1492
         /* Replace a used A-register by A1 */
1506
         /* Replace a used A-register by A1 */
1493
         r = reg ( m ) ;
1507
         r = reg(m);
1494
         reg_names [r] = reg_names [ REG_A1 ] ;
1508
         reg_names[r] = reg_names[REG_A1];
1495
         rmsk &= ~regmsk ( r ) ;
1509
         rmsk &= ~regmsk(r);
1496
         smsk &= ~regmsk ( r ) ;
1510
         smsk &= ~regmsk(r);
1497
         cmsk |= regmsk ( r ) ;
1511
         cmsk |= regmsk(r);
1498
      } else if ( no_calls == 0 ) {
1512
      } else if (no_calls == 0) {
1499
         m = rmsk & dreg_msk ;
1513
         m = rmsk & dreg_msk;
1500
         if ( m ) {
1514
         if (m) {
1501
            /* Move a used D-register into A1 */
1515
            /* Move a used D-register into A1 */
1502
            tmp_a1 = reg ( m ) ;
1516
            tmp_a1 = reg(m);
1503
            rmsk &= ~regmsk ( tmp_a1 ) ;
1517
            rmsk &= ~regmsk(tmp_a1);
1504
            smsk = rmsk ;
1518
            smsk = rmsk;
1505
            op1 = make_register ( REG_A1 ) ;
1519
            op1 = make_register(REG_A1);
1506
            op2 = make_register ( tmp_a1 ) ;
1520
            op2 = make_register(tmp_a1);
1507
            make_instr ( m_movl, op1, op2, regmsk ( tmp_a1 ) ) ;
1521
            make_instr(m_movl, op1, op2, regmsk(tmp_a1));
1508
            just_ret = 0 ;
1522
            just_ret = 0;
1509
         }
1523
         }
1510
      }
1524
      }
1511
   }
1525
   }
1512
 
1526
 
1513
   /* Use FP1 if not already used */
1527
   /* Use FP1 if not already used */
1514
   if ( fsmsk && !( regsinproc & regmsk ( REG_FP1 ) ) ) {
1528
   if (fsmsk && !(regsinproc & regmsk(REG_FP1))) {
1515
      for ( r = REG_FP7, m = 1 ; r >= REG_FP2 ; r--, m <<= 1 ) {
1529
      for (r = REG_FP7, m = 1; r >= REG_FP2; r--, m <<= 1) {
1516
         if ( fsmsk & regmsk ( r ) ) {
1530
         if (fsmsk & regmsk(r)) {
1517
            reg_names [r] = reg_names [ REG_FP1 ] ;
1531
            reg_names[r] = reg_names[REG_FP1];
1518
            fmsk &= ~m ;
1532
            fmsk &= ~m;
1519
            fsmsk &= ~regmsk ( r ) ;
1533
            fsmsk &= ~regmsk(r);
1520
            cmsk |= regmsk ( r ) ;
1534
            cmsk |= regmsk(r);
1521
            r = REG_FP1 ;
1535
            r = REG_FP1;
1522
         }
1536
         }
1523
      }
1537
      }
1524
   }
1538
   }
1525
 
1539
 
1526
   if ( d1_free && no_calls == 0 ) {
1540
   if (d1_free && no_calls == 0) {
1527
      m = rmsk & areg_msk ;
1541
      m = rmsk & areg_msk;
1528
      if ( m ) {
1542
      if (m) {
1529
         /* Move a used A-register into D1 */
1543
         /* Move a used A-register into D1 */
1530
         tmp_d1 = reg ( m ) ;
1544
         tmp_d1 = reg(m);
1531
         rmsk &= ~regmsk ( tmp_d1 ) ;
1545
         rmsk &= ~regmsk(tmp_d1);
1532
         op1 = make_register ( REG_D1 ) ;
1546
         op1 = make_register(REG_D1);
1533
         op2 = make_register ( tmp_d1 ) ;
1547
         op2 = make_register(tmp_d1);
1534
         make_instr ( m_movl, op1, op2, regmsk ( tmp_d1 ) ) ;
1548
         make_instr(m_movl, op1, op2, regmsk(tmp_d1));
1535
         just_ret = 0 ;
1549
         just_ret = 0;
1536
      }
1550
      }
1537
   }
1551
   }
1538
 
1552
 
1539
   /* Calculate stack displacements */
1553
   /* Calculate stack displacements */
1540
   st1 = round ( max_stack, 32 ) / 8 + 16 * bits_in ( fmsk ) ;
1554
   st1 = round(max_stack, 32) / 8 + 16 * bits_in(fmsk);
1541
   st = st1 + 4 * bits_in ( rmsk ) ;
1555
   st = st1 + 4 * bits_in(rmsk);
1542
 
1556
 
1543
   if ( st1 || st || used_stack || must_use_bp || cur_proc_has_vcallees ) uses_link = 1 ;
1557
   if (st1 || st || used_stack || must_use_bp || cur_proc_has_vcallees)uses_link = 1;
1544
 
1558
 
1545
   cleanup() ;
1559
   cleanup();
1546
 
1560
 
1547
   /* Output return instruction */
1561
   /* Output return instruction */
1548
   make_instr ( m_rts, null, null, 0 ) ;
1562
   make_instr(m_rts, null, null, 0);
1549
 
1563
 
1550
   /* Output instructions to restore registers */
1564
   /* Output instructions to restore registers */
1551
   save_ins_pointer = current_ins ;
1565
   save_ins_pointer = current_ins;
1552
   restore_regs_output(rmsk, fmsk, st, st1, uses_link) ;
1566
   restore_regs_output(rmsk, fmsk, st, st1, uses_link);
1553
 
1567
 
1554
   /* Go back to the prologue position */
1568
   /* Go back to the prologue position */
1555
   current_ins = prologue_ins ;
1569
   current_ins = prologue_ins;
1556
 
1570
 
1557
   /* Calculate the offset between procedure args and sp */
1571
   /* Calculate the offset between procedure args and sp */
1558
   ldisp = (uses_link ? st + 4 : st ) ;
1572
   ldisp = (uses_link ? st + 4 : st);
1559
 
1573
 
1560
   /* Calculate env_size ( ldisp + sizeof(return address) + sizeof(params) )*/
1574
   /* Calculate env_size ( ldisp + sizeof(return address) + sizeof(params) )*/
1561
   cur_proc_env_size = ldisp + 4 + (cur_proc_callers_size + cur_proc_callees_size)/8 ;
1575
   cur_proc_env_size = ldisp + 4 + (cur_proc_callers_size + cur_proc_callees_size) /8;
1562
#if 0
1576
#if 0
1563
   if ( has_checkstack )
1577
   if (has_checkstack)
1564
   cur_proc_env_size += 1024 ; /* room for exception handler */
1578
   cur_proc_env_size += 1024 ; /* room for exception handler */
1565
#endif
1579
#endif
1566
 
1580
 
1567
   if ( uses_link ) {
1581
   if (uses_link) {
1568
      /* Output link instruction */
1582
      /* Output link instruction */
1569
      /* push AP; AP = SP; sp=sp-st */
1583
      /* push AP; AP = SP; sp=sp-st */
1570
      instruction_id = ( -st > 0x7fff ? m_linkl : m_linkw ) ;
1584
      instruction_id = (-st > 0x7fff ? m_linkl : m_linkw);
1571
      op1 = make_register ( REG_AP ) ;
1585
      op1 = make_register(REG_AP);
1572
      op2 = make_value ( -st ) ;
1586
      op2 = make_value(-st);
1573
      make_instr ( instruction_id, op1, op2, regmsk ( REG_AP ) | regmsk ( REG_SP ) ) ;
1587
      make_instr(instruction_id, op1, op2, regmsk(REG_AP) | regmsk(REG_SP));
1574
   }
1588
   }
1575
 
1589
 
1576
   /* Save register in D1 if necessary */
1590
   /* Save register in D1 if necessary */
1577
   if ( tmp_d1 >= 0 ) {
1591
   if (tmp_d1 >= 0) {
1578
      op1 = make_register ( tmp_d1 ) ;
1592
      op1 = make_register(tmp_d1);
1579
      op2 = make_register ( REG_D1 ) ;
1593
      op2 = make_register(REG_D1);
1580
      make_instr ( m_movl, op1, op2, regmsk ( REG_D1 ) ) ;
1594
      make_instr(m_movl, op1, op2, regmsk(REG_D1));
1581
   }
1595
   }
1582
 
1596
 
1583
   /* Save register in A0 if necessary */
1597
   /* Save register in A0 if necessary */
1584
   if ( tmp_a0 >= 0 ) {
1598
   if (tmp_a0 >= 0) {
1585
      op1 = make_register ( tmp_a0 ) ;
1599
      op1 = make_register(tmp_a0);
1586
      op2 = make_register ( REG_A0 ) ;
1600
      op2 = make_register(REG_A0);
1587
      make_instr ( m_movl, op1, op2, regmsk ( REG_A0 ) ) ;
1601
      make_instr(m_movl, op1, op2, regmsk(REG_A0));
1588
   }
1602
   }
1589
 
1603
 
1590
   /* Save register in A1 if necessary */
1604
   /* Save register in A1 if necessary */
1591
   if ( tmp_a1 >= 0 ) {
1605
   if (tmp_a1 >= 0) {
1592
      op1 = make_register ( tmp_a1 ) ;
1606
      op1 = make_register(tmp_a1);
1593
      op2 = make_register ( REG_A1 ) ;
1607
      op2 = make_register(REG_A1);
1594
      make_instr ( m_movl, op1, op2, regmsk ( REG_A1 ) ) ;
1608
      make_instr(m_movl, op1, op2, regmsk(REG_A1));
1595
   }
1609
   }
1596
 
1610
 
1597
   /* Put registers onto the stack */
1611
   /* Put registers onto the stack */
1598
   if ( rmsk ) {
1612
   if (rmsk) {
1599
      op1 = make_hex_value ( rmsk ) ;
1613
      op1 = make_hex_value(rmsk);
1600
      op2 = make_indirect ( REG_SP, 0 ) ;
1614
      op2 = make_indirect(REG_SP, 0);
1601
      make_instr ( m_moveml, op1, op2, 0 ) ;
1615
      make_instr(m_moveml, op1, op2, 0);
1602
   }
1616
   }
1603
 
1617
 
1604
   /* Put floating-point registers onto the stack */
1618
   /* Put floating-point registers onto the stack */
1605
   if ( fmsk ) {
1619
   if (fmsk) {
1606
      op1 = make_hex_value ( fmsk ) ;
1620
      op1 = make_hex_value(fmsk);
1607
      op2 = make_indirect ( REG_AP, -st1 ) ;
1621
      op2 = make_indirect(REG_AP, -st1);
1608
      make_instr ( m_fmovemx, op1, op2, 0 ) ;
1622
      make_instr(m_fmovemx, op1, op2, 0);
1609
   }
1623
   }
1610
 
1624
 
1611
   if (uses_callers_pointer){
1625
   if (uses_callers_pointer) {
1612
      make_comment("Variable callees => Get address of first caller");
1626
      make_comment("Variable callees => Get address of first caller");
1613
 
1627
 
1614
      regsinproc |= regmsk ( REG_A5 ) ;
1628
      regsinproc |= regmsk(REG_A5);
1615
 
1629
 
1616
      op1 = make_register ( REG_AP ) ;
1630
      op1 = make_register(REG_AP);
1617
      op2 = make_register ( REG_A5 ) ;
1631
      op2 = make_register(REG_A5);
1618
      make_instr ( m_movl, op1, op2, regmsk ( REG_A5 ) ) ;
1632
      make_instr(m_movl, op1, op2, regmsk(REG_A5));
1619
 
1633
 
1620
      /* A5 = AP + cur_proc_callees_size */
1634
      /* A5 = AP + cur_proc_callees_size */
1621
      /* AP points to the first parameter, callees size is before */
1635
      /* AP points to the first parameter, callees size is before */
1622
      op1 = make_callees_size () ;
1636
      op1 = make_callees_size();
1623
      op2 = make_register ( REG_A5 ) ;
1637
      op2 = make_register(REG_A5);
1624
      make_instr ( m_addl, op1, op2, regmsk ( REG_A5 ) ) ;
1638
      make_instr(m_addl, op1, op2, regmsk(REG_A5));
1625
 
1639
 
1626
      op1 = make_value ( 12 ) ;
1640
      op1 = make_value(12);
1627
      op2 = make_register ( REG_A5 ) ;
1641
      op2 = make_register(REG_A5);
1628
      make_instr ( m_addl, op1, op2, regmsk ( REG_A5 ) ) ;
1642
      make_instr(m_addl, op1, op2, regmsk(REG_A5));
1629
   }
1643
   }
1630
 
1644
 
1631
 
1645
 
1632
   /* Return to previous position */
1646
   /* Return to previous position */
1633
   current_ins = save_ins_pointer ;
1647
   current_ins = save_ins_pointer;
1634
 
1648
 
1635
   callmsk = cmsk ;
1649
   callmsk = cmsk;
1636
   have_cond = 0 ;
1650
   have_cond = 0;
1637
   return ;
1651
   return;
1638
}
1652
}
1639
 
1653
 
1640
/************************************************************************
1654
/************************************************************************
1641
  CODE_POSTLUDE
1655
  CODE_POSTLUDE
1642
  The postlude parameters positions on the stack are setup, and coder
1656
  The postlude parameters positions on the stack are setup, and coder
1643
  is called with the postlude body.
1657
  is called with the postlude body.
1644
 
1658
 
1645
  ************************************************************************/
1659
  ************************************************************************/
1646
static void code_postlude
1660
static void code_postlude
1647
    PROTO_N ( ( postlude, callers, stack, post_offset ) )
-
 
1648
    PROTO_T ( exp postlude X exp callers X ash stack X long post_offset )
1661
(exp postlude, exp callers, ash stack, long post_offset)
1649
{
1662
{
1650
   make_comment("Postlude ...");
1663
   make_comment("Postlude ...");
1651
 
1664
 
1652
   /* mark parameters by use of the values calculated by gcproc */
1665
   /* mark parameters by use of the values calculated by gcproc */
1653
   while ( name( postlude ) == ident_tag && name(son( postlude )) == caller_name_tag) {
1666
   while (name(postlude) == ident_tag && name(son(postlude)) == caller_name_tag) {
1654
      int n = no(son( postlude ));
1667
      int n = no(son(postlude));
1655
      exp a = callers;
1668
      exp a = callers;
1656
      while (n != 0) {
1669
      while (n != 0) {
1657
         a = bro(a);
1670
         a = bro(a);
1658
         n--;
1671
         n--;
1659
      }
1672
      }
1660
      if (name(a) != caller_tag)
1673
      if (name(a)!= caller_tag)
1661
      error("Bad postlude") ;
1674
      error("Bad postlude");
1662
 
1675
 
1663
      ptno( postlude ) = par3_pl;
1676
      ptno(postlude) = par3_pl;
1664
      no( postlude ) = no(a) + stack_dec + post_offset ;
1677
      no(postlude) = no(a) + stack_dec + post_offset;
1665
 
1678
 
1666
      postlude = bro( son( postlude ) );
1679
      postlude = bro(son(postlude));
1667
   }
1680
   }
1668
 
1681
 
1669
   /* code the postlude */
1682
   /* code the postlude */
1670
   coder ( zero, stack, postlude ) ;
1683
   coder(zero, stack, postlude);
1671
 
1684
 
1672
   make_comment("Postlude done");
1685
   make_comment("Postlude done");
1673
}
1686
}
1674
 
1687
 
1675
/************************************************************************
1688
/************************************************************************
1676
  Makes code for untidy return
1689
  Makes code for untidy return
1677
  ************************************************************************/
1690
  ************************************************************************/
1678
 
1691
 
1679
void untidy_return
1692
void untidy_return
1680
    PROTO_Z ()
1693
(void)
1681
{
1694
{
1682
   mach_op *op1, *op2 ;
1695
   mach_op *op1, *op2;
1683
 
1696
 
1684
   make_comment("untidy return") ;
1697
   make_comment("untidy return");
1685
 
1698
 
1686
   make_comment("push return address");
1699
   make_comment("push return address");
1687
   op1 = make_indirect ( REG_AP, 4 ) ;
1700
   op1 = make_indirect(REG_AP, 4);
1688
   op2 = make_dec_sp();
1701
   op2 = make_dec_sp();
1689
   make_instr ( m_movl, op1, op2, regmsk ( REG_SP ) ) ;
1702
   make_instr(m_movl, op1, op2, regmsk(REG_SP));
1690
 
1703
 
1691
   restore_regs(NOT_SP) ;
1704
   restore_regs(NOT_SP);
1692
   /* Output return instruction */
1705
   /* Output return instruction */
1693
   make_instr ( m_rts, null, null, 0 ) ;
1706
   make_instr(m_rts, null, null, 0);
1694
}
1707
}
1695
 
1708
 
1696
/************************************************************************
1709
/************************************************************************
1697
  Make a label with named after the address of e and the value of the
1710
  Make a label with named after the address of e and the value of the
1698
  env offset from e (an ident_tag) to the application pointer.
1711
  env offset from e (an ident_tag) to the application pointer.
1699
  ************************************************************************/
1712
  ************************************************************************/
1700
 
1713
 
1701
void make_visible
1714
void make_visible
1702
    PROTO_N ( ( e ) )
-
 
1703
    PROTO_T ( exp e )
1715
(exp e)
1704
{
1716
{
1705
   mach_op *op1, *op2 ;
1717
   mach_op *op1, *op2;
1706
   long offval ;
1718
   long offval;
1707
 
1719
 
1708
   /* Does it need to be visible? */
1720
   /* Does it need to be visible? */
1709
 
1721
 
1710
   if (! ((isvis(e)) || (isenvoff(e))) ) return ;
1722
   if (!((isvis(e)) || (isenvoff(e)))) return;
1711
 
1723
 
1712
   setismarked(e) ;
1724
   setismarked(e);
1713
 
1725
 
1714
   switch ( ptno( e ) ) {
1726
   switch (ptno(e)) {
1715
   case var_pl:
1727
   case var_pl:
1716
      offval = -no(e)/8;
1728
      offval = -no(e) /8;
1717
      break;
1729
      break;
1718
   case par2_pl:
1730
   case par2_pl:
1719
      offval = no(e)/8;
1731
      offval = no(e) /8;
1720
      break;
1732
      break;
1721
   case par3_pl:
1733
   case par3_pl:
1722
   case par_pl:
1734
   case par_pl:
1723
   default:
1735
   default:
1724
      offval = no(e)/8 + 4;
1736
      offval = no(e) /8 + 4;
1725
      if(used_stack) offval += 4;
1737
      if (used_stack)offval += 4;
1726
   }
1738
   }
1727
   op1 = make_lab_data ((long)e, 0) ;
1739
   op1 = make_lab_data((long)e, 0);
1728
   op2 = make_int_data (offval) ;
1740
   op2 = make_int_data(offval);
1729
   make_instr_aux ( m_as_assign, op1, op2, 0, 0 ) ;
1741
   make_instr_aux(m_as_assign, op1, op2, 0, 0);
1730
}
1742
}
1731
 
1743
 
1732
 
1744
 
1733
/************************************************************************
1745
/************************************************************************
1734
  If a caller parameter is accessed from a framepointer with variable
1746
  If a caller parameter is accessed from a framepointer with variable
1735
  callees we need to transform the pointer in the addptr expression to
1747
  callees we need to transform the pointer in the addptr expression to
1736
  callers pointer.
1748
  callers pointer.
1737
  ************************************************************************/
1749
  ************************************************************************/
1738
 
1750
 
1739
void fix_addptr
1751
void fix_addptr
1740
    PROTO_N ( ( addptr ) )
-
 
1741
    PROTO_T ( exp addptr )
1752
(exp addptr)
1742
{
1753
{
1743
   exp pointer  = son ( addptr ) ;
1754
   exp pointer  = son(addptr);
1744
   exp offset   = bro ( pointer ) ;
1755
   exp offset   = bro(pointer);
1745
   exp E1,E2,E3,E4,E5;
1756
   exp E1,E2,E3,E4,E5;
1746
   shape pc_sh;
1757
   shape pc_sh;
1747
 
1758
 
1748
   /* access of a caller param. relative to an environment with variable? */
1759
   /* access of a caller param. relative to an environment with variable? */
1749
 
1760
 
1750
   if (! ((frame_al_of_ptr(sh(pointer)) & al_includes_vcallees) &&
1761
   if (!((frame_al_of_ptr(sh(pointer)) & al_includes_vcallees) &&
1751
          (frame_al1_of_offset(sh(offset)) & al_includes_caller_args)) ) return;
1762
         (frame_al1_of_offset(sh(offset)) & al_includes_caller_args))) return;
1752
 
1763
 
1753
 
1764
 
1754
   /*
1765
   /*
1755
      exchange application pointer with callers pointer:
1766
      exchange application pointer with callers pointer:
1756
 
1767
 
Line 1779... Line 1790...
1779
 
1790
 
1780
      */
1791
      */
1781
 
1792
 
1782
   pc_sh = f_pointer(f_callers_alignment(0));
1793
   pc_sh = f_pointer(f_callers_alignment(0));
1783
 
1794
 
1784
   E1 = copyexp(pointer) ;
1795
   E1 = copyexp(pointer);
1785
   E2 = getexp (pc_sh, 0, 0, E1, 0, 0, 8*8, reff_tag);
1796
   E2 = getexp(pc_sh, 0, 0, E1, 0, 0, 8*8, reff_tag);
1786
   E3 = getexp (pc_sh, 0, 0, E2, 0, 0, 0, cont_tag);
1797
   E3 = getexp(pc_sh, 0, 0, E2, 0, 0, 0, cont_tag);
1787
   E4 = getexp (pc_sh, 0, 0, pointer, 0, 0, 0, addptr_tag);
1798
   E4 = getexp(pc_sh, 0, 0, pointer, 0, 0, 0, addptr_tag);
1788
   E5 = getexp (pc_sh, 0, 0, E4, 0, 0, 12*8, reff_tag);
1799
   E5 = getexp(pc_sh, 0, 0, E4, 0, 0, 12*8, reff_tag);
1789
   son(addptr) = E5;
1800
   son(addptr) = E5;
1790
 
1801
 
1791
   /* Terminate each bro list */
1802
   /* Terminate each bro list */
1792
   setfather (E2, E1);
1803
   setfather(E2, E1);
1793
   setfather (E3, E2);
1804
   setfather(E3, E2);
1794
   setfather (E4, E3);
1805
   setfather(E4, E3);
1795
   setfather (E5, E4);
1806
   setfather(E5, E4);
1796
 
1807
 
1797
   bro (pointer) = E3;
1808
   bro(pointer) = E3;
1798
   bro (E5) = offset;
1809
   bro(E5) = offset;
1799
}
1810
}
1800
 
1811
 
1801
/************************************************************************
1812
/************************************************************************
1802
  Transforms an entire exp recursively.
1813
  Transforms an entire exp recursively.
1803
  ************************************************************************/
1814
  ************************************************************************/
1804
static void transform
1815
static void transform
1805
    PROTO_N ( ( e ) )
-
 
1806
    PROTO_T ( exp e )
1816
(exp e)
1807
{
1817
{
1808
   exp s = son(e) ;
1818
   exp s = son(e);
1809
 
1819
 
1810
   /* Transform the childs (if any) */
1820
   /* Transform the childs (if any) */
1811
   if ( s && (name(e) != name_tag) && (name(e) != env_offset_tag) && (name(e) != case_tag) )
1821
   if (s && (name(e)!= name_tag) && (name(e)!= env_offset_tag) && (name(e)!= case_tag))
1812
   for (; s && s!=e; s=bro(s)) {
1822
   for (; s && s!=e; s=bro(s)) {
1813
      transform(s);
1823
      transform(s);
1814
   }
1824
   }
1815
 
1825
 
1816
   /* Transform this one */
1826
   /* Transform this one */
1817
   switch ( name( e ) ) {
1827
   switch (name(e)) {
1818
   case addptr_tag:
1828
   case addptr_tag:
1819
      fix_addptr(e);
1829
      fix_addptr(e);
1820
      break;
1830
      break;
1821
   default:
1831
   default:
1822
      /* nothing to do */
1832
      /* nothing to do */
Line 1827... Line 1837...
1827
/************************************************************************
1837
/************************************************************************
1828
  Scan through the declarations and apply transform
1838
  Scan through the declarations and apply transform
1829
  called from trans.
1839
  called from trans.
1830
  ************************************************************************/
1840
  ************************************************************************/
1831
void make_transformations
1841
void make_transformations
1832
    PROTO_Z ()
1842
(void)
1833
{
1843
{
1834
   dec *d = top_def ;
1844
   dec *d = top_def;
1835
 
1845
 
1836
   while ( d ) {
1846
   while (d) {
1837
      exp e = son ( d->dec_u.dec_val.dec_exp ) ;
1847
      exp e = son(d->dec_u.dec_val.dec_exp);
1838
      if ( e ) transform ( e ) ;
1848
      if (e)transform(e);
1839
      d = d->def_next ;
1849
      d = d->def_next;
1840
   }
1850
   }
1841
}
1851
}
1842
/************************************************************************
1852
/************************************************************************
1843
  Make a label with:
1853
  Make a label with:
1844
  value: env_size ( proc )
1854
  value: env_size ( proc )
1845
  name:  L<value of procedure declaration pointer)
1855
  name:  L<value of procedure declaration pointer)
1846
  ************************************************************************/
1856
  ************************************************************************/
1847
 
1857
 
1848
void output_env_size
1858
void output_env_size
1849
    PROTO_N ( ( proc, envsize ) )
-
 
1850
    PROTO_T ( dec* proc X long envsize )
1859
(dec* proc, long envsize)
1851
{
1860
{
1852
   mach_op *op1, *op2 ;
1861
   mach_op *op1, *op2;
1853
   long offval ;
1862
   long offval;
1854
 
1863
 
1855
   make_comment("env_size comes here:");
1864
   make_comment("env_size comes here:");
1856
   op1 = make_lab_data ((long)proc, 0) ;
1865
   op1 = make_lab_data((long)proc, 0);
1857
   op2 = make_int_data (envsize) ;
1866
   op2 = make_int_data(envsize);
1858
   make_instr_aux ( m_as_assign, op1, op2, 0, 0 ) ;
1867
   make_instr_aux(m_as_assign, op1, op2, 0, 0);
1859
}
1868
}
1860
 
1869