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) 1997
32
    		 Crown Copyright (c) 1997
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 121... Line 151...
121
#endif
151
#endif
122
#ifndef tdf3
152
#ifndef tdf3
123
#include "general_proc.h"
153
#include "general_proc.h"
124
#include "68k_globals.h"
154
#include "68k_globals.h"
125
#endif
155
#endif
126
extern bool have_cond ;
156
extern bool have_cond;
127
extern int do_peephole ;
157
extern int do_peephole;
128
extern int do_pic ;
158
extern int do_pic;
129
extern ast add_shape_to_stack PROTO_S ( ( ash, shape ) ) ;
159
extern ast add_shape_to_stack(ash, shape);
130
 
160
 
131
 
161
 
132
/*
162
/*
133
    SELECT BYTE, WORD OR LONG INSTRUCTION
163
    SELECT BYTE, WORD OR LONG INSTRUCTION
134
 
164
 
135
    opb, opw and opl give the byte, word and long versions of an instruction.
165
    opb, opw and opl give the byte, word and long versions of an instruction.
136
    The appropriate instruction for size sz is returned.
166
    The appropriate instruction for size sz is returned.
137
*/
167
*/
138
 
168
 
139
int ins
169
int ins
140
    PROTO_N ( ( sz, opb, opw, opl ) )
-
 
141
    PROTO_T ( long sz X int opb X int opw X int opl )
170
(long sz, int opb, int opw, int opl)
142
{
171
{
143
    if ( sz <= 8 ) return ( opb ) ;
172
    if (sz <= 8) return(opb);
144
    if ( sz <= 16 ) return ( opw ) ;
173
    if (sz <= 16) return(opw);
145
    if ( sz <= 32 ) return ( opl ) ;
174
    if (sz <= 32) return(opl);
146
    error ( "Illegal instruction size" ) ;
175
    error("Illegal instruction size");
147
    return ( opl ) ;
176
    return(opl);
148
}
177
}
149
 
178
 
150
 
179
 
151
/*
180
/*
152
    SELECT SINGLE OR DOUBLE FLOATING-POINT INSTRUCTION
181
    SELECT SINGLE OR DOUBLE FLOATING-POINT INSTRUCTION
Line 154... Line 183...
154
    ops and opd give the single and double precision versions of an
183
    ops and opd give the single and double precision versions of an
155
    instruction.  The appropriate instruction for size sz is returned.
184
    instruction.  The appropriate instruction for size sz is returned.
156
*/
185
*/
157
 
186
 
158
int insf
187
int insf
159
    PROTO_N ( ( sz, ops, opd, opx ) )
-
 
160
    PROTO_T ( long sz X int ops X int opd X int opx )
188
(long sz, int ops, int opd, int opx)
161
{
189
{
162
    if ( sz == 32 ) return ( ops ) ;
190
    if (sz == 32) return(ops);
163
    if ( sz == 64 ) return ( opd ) ;
191
    if (sz == 64) return(opd);
164
    error ( "Illegal instruction size" ) ;
192
    error("Illegal instruction size");
165
    return ( opx ) ;
193
    return(opx);
166
}
194
}
167
 
195
 
168
 
196
 
169
/*
197
/*
170
    ADD A CONSTANT TO AN ADDRESS REGISTER
198
    ADD A CONSTANT TO AN ADDRESS REGISTER
Line 172... Line 200...
172
    This routine is used primarily for updating the stack.  It adds d
200
    This routine is used primarily for updating the stack.  It adds d
173
    to the A-register with number r.
201
    to the A-register with number r.
174
*/
202
*/
175
 
203
 
176
void add_to_reg
204
void add_to_reg
177
    PROTO_N ( ( r, d ) )
-
 
178
    PROTO_T ( int r X long d )
205
(int r, long d)
179
{
206
{
180
    if ( d ) {
207
    if (d) {
181
	int instr ;
208
	int instr;
182
	mach_op *op1 ;
209
	mach_op *op1;
183
	mach_op *op2 = make_register ( r ) ;
210
	mach_op *op2 = make_register(r);
184
	if ( d > 0 && d <= 8 ) {
211
	if (d > 0 && d <= 8) {
185
	    instr = m_addql ;
212
	    instr = m_addql;
186
	    op1 = make_value ( d ) ;
213
	    op1 = make_value(d);
187
	} else if ( d < 0 && d >= -8 ) {
214
	} else if (d < 0 && d >= -8) {
188
	    instr = m_subql ;
215
	    instr = m_subql;
189
	    op1 = make_value ( -d ) ;
216
	    op1 = make_value(-d);
190
	} else {
217
	} else {
191
	    instr = m_lea ;
218
	    instr = m_lea;
192
	    op1 = make_indirect ( r, d ) ;
219
	    op1 = make_indirect(r, d);
193
	}
220
	}
194
	make_instr ( instr, op1, op2, regmsk ( r ) ) ;
221
	make_instr(instr, op1, op2, regmsk(r));
195
	have_cond = 0 ;
222
	have_cond = 0;
196
    }
223
    }
197
    return ;
224
    return;
198
}
225
}
199
 
226
 
200
 
227
 
201
/*
228
/*
202
    CHECK RESERVED NAMES
229
    CHECK RESERVED NAMES
203
 
230
 
204
    This routine returns 1 if nm is a name reserved by the linker.
231
    This routine returns 1 if nm is a name reserved by the linker.
205
*/
232
*/
206
 
233
 
207
bool reserved
234
bool reserved
208
    PROTO_N ( ( nm ) )
-
 
209
    PROTO_T ( char *nm )
235
(char *nm)
210
{
236
{
211
    int i ;
237
    int i;
212
    static char *rn [] = {
238
    static char *rn[] = {
213
	"_edata", "_etext", "_end", "__edata", "__etext", "__end"
239
	"_edata", "_etext", "_end", "__edata", "__etext", "__end"
214
    } ;
240
    };
215
    for ( i = 0 ; i < array_size ( rn ) ; i++ ) {
241
    for (i = 0; i < array_size(rn); i++) {
216
	if ( eq ( nm, rn [i] ) ) return ( 1 ) ;
242
	if (eq(nm, rn[i])) return(1);
217
    }
243
    }
218
    return ( 0 ) ;
244
    return(0);
219
}
245
}
220
 
246
 
221
 
247
 
222
/*
248
/*
223
    LOOK FOR SPECIAL FUNCTIONS
249
    LOOK FOR SPECIAL FUNCTIONS
Line 227... Line 253...
227
    string (which is turned into a move instruction), and alloca
253
    string (which is turned into a move instruction), and alloca
228
    (which is inlined).
254
    (which is inlined).
229
*/
255
*/
230
 
256
 
231
speci special_fn
257
speci special_fn
232
    PROTO_N ( ( a1, a2, s ) )
-
 
233
    PROTO_T ( exp a1 X exp a2 X shape s )
258
(exp a1, exp a2, shape s)
234
{
259
{
235
    speci spec_fn ;
260
    speci spec_fn;
236
    dec *d = brog ( son ( a1 ) ) ;
261
    dec *d = brog(son(a1));
237
    char *id = d->dec_u.dec_val.dec_id ;
262
    char *id = d->dec_u.dec_val.dec_id;
238
    spec_fn.is_special = 0 ;
263
    spec_fn.is_special = 0;
239
 
264
 
240
    if ( id == null ) return ( spec_fn ) ;
265
    if (id == null) return(spec_fn);
241
 
266
 
242
    if ( eq ( id, "_setjmp" ) ) has_setjmp = 1 ;
267
    if (eq(id, "_setjmp"))has_setjmp = 1;
243
    if ( eq ( id, "_longjmp" ) ) has_setjmp = 1 ;
268
    if (eq(id, "_longjmp"))has_setjmp = 1;
244
 
269
 
245
    if ( !do_alloca ) return ( spec_fn ) ;
270
    if (!do_alloca) return(spec_fn);
246
 
271
 
247
    if ( ( /* eq ( id, "_alloca" ) || */ eq ( id, "___builtin_alloca" ) ) &&
272
    if ( ( /* eq ( id, "_alloca" ) || */ eq ( id, "___builtin_alloca" ) ) &&
248
	 a2 != nilexp && last ( a2 ) ) {
273
	 a2 != nilexp && last(a2)) {
249
	exp r = getexp ( s, nilexp, 0, a2, nilexp, 0, L0, alloca_tag ) ;
274
	exp r = getexp(s, nilexp, 0, a2, nilexp, 0, L0, alloca_tag);
250
	setfather ( r, son ( r ) ) ;
275
	setfather(r, son(r));
251
	has_alloca = 1 ;
276
	has_alloca = 1;
252
	spec_fn.is_special = 1 ;
277
	spec_fn.is_special = 1;
253
	spec_fn.special_exp = r ;
278
	spec_fn.special_exp = r;
254
	kill_exp ( a1, a1 ) ;
279
	kill_exp(a1, a1);
255
	return ( spec_fn ) ;
280
	return(spec_fn);
256
    }
281
    }
257
 
282
 
258
    return ( spec_fn ) ;
283
    return(spec_fn);
259
}
284
}
260
 
285
 
261
 
286
 
262
/*
287
/*
263
    STACK INFORMATION
288
    STACK INFORMATION
Line 281... Line 306...
281
    entire procedure has been coded, so a special label is used to
306
    entire procedure has been coded, so a special label is used to
282
    represent its value during the procedure coding.  used_ldisp is
307
    represent its value during the procedure coding.  used_ldisp is
283
    true to indicate that this special label has been used.
308
    true to indicate that this special label has been used.
284
*/
309
*/
285
 
310
 
286
bool used_stack = 0 ;
311
bool used_stack = 0;
287
long max_stack = 0 ;
312
long max_stack = 0;
288
long stack_dec = 0 ;
313
long stack_dec = 0;
289
long stack_size = 0 ;
314
long stack_size = 0;
290
long extra_stack = 0 ;
315
long extra_stack = 0;
291
bool used_ldisp = 0 ;
316
bool used_ldisp = 0;
292
long ldisp = 0 ;
317
long ldisp = 0;
293
 
318
 
294
 
319
 
295
/*
320
/*
296
    PENDING STACK DISPLACEMENT
321
    PENDING STACK DISPLACEMENT
297
 
322
 
298
    Consecutive changes to the stack pointer are combined whenever
323
    Consecutive changes to the stack pointer are combined whenever
299
    possible.  stack_change gives the current amount of change which
324
    possible.  stack_change gives the current amount of change which
300
    has not been output as an instruction.
325
    has not been output as an instruction.
301
*/
326
*/
302
 
327
 
303
long stack_change = 0 ;
328
long stack_change = 0;
304
int stack_direction = 0 ;
329
int stack_direction = 0;
305
 
330
 
306
 
331
 
307
/*
332
/*
308
    DECREASE THE STACK
333
    DECREASE THE STACK
309
 
334
 
310
    This routine decreases the stack pointer by d bits.
335
    This routine decreases the stack pointer by d bits.
311
*/
336
*/
312
 
337
 
313
void dec_stack
338
void dec_stack
314
    PROTO_N ( ( d ) )
-
 
315
    PROTO_T ( long d )
339
(long d)
316
{
340
{
317
    if ( d ) {
341
    if (d) {
318
	stack_change -= d ;
342
	stack_change -= d;
319
	stack_direction = ( d > 0 ? 1 : 0 ) ;
343
	stack_direction = (d > 0 ? 1 : 0);
320
	have_cond = 0 ;
344
	have_cond = 0;
321
#ifdef EBUG
345
#ifdef EBUG
322
        update_stack() ;
346
        update_stack();
323
#endif
347
#endif
324
    }
348
    }
325
    return ;
349
    return;
326
}
350
}
327
 
351
 
328
 
352
 
329
/*
353
/*
330
    OUTPUT STACK DISPLACEMENT
354
    OUTPUT STACK DISPLACEMENT
331
 
355
 
332
    This routine outputs any accummulated stack changes.
356
    This routine outputs any accummulated stack changes.
333
*/
357
*/
334
 
358
 
335
void update_stack
359
void update_stack
336
    PROTO_Z ()
360
(void)
337
{
361
{
338
    if ( stack_change ) {
362
    if (stack_change) {
339
	long d = stack_change / 8 ;
363
	long d = stack_change / 8;
340
	stack_size += stack_change ;
364
	stack_size += stack_change;
341
	stack_change = 0 ;
365
	stack_change = 0;
342
	add_to_reg ( REG_SP, d ) ;
366
	add_to_reg(REG_SP, d);
343
    }
367
    }
344
    return ;
368
    return;
345
}
369
}
346
 
370
 
347
 
371
 
348
/*
372
/*
349
    CHANGE DATA AREA
373
    CHANGE DATA AREA
Line 351... Line 375...
351
    This routine changes the current address area.  p can be one of
375
    This routine changes the current address area.  p can be one of
352
    the values ptext, pdata or pbss given in codex.h.
376
    the values ptext, pdata or pbss given in codex.h.
353
*/
377
*/
354
 
378
 
355
void area
379
void area
356
    PROTO_N ( ( p ) )
-
 
357
    PROTO_T ( int p )
380
(int p)
358
{
381
{
359
    static int current_area = -1 ;
382
    static int current_area = -1;
360
    static int previous_area = -1 ;
383
    static int previous_area = -1;
361
    if ( p == plast ) p = previous_area ;
384
    if (p == plast)p = previous_area;
362
    if ( p != current_area ) {
385
    if (p != current_area) {
363
	int i ;
386
	int i;
364
	switch ( p ) {
387
	switch (p) {
365
	    case ptext : i = m_as_text ; break ;
388
	    case ptext: i = m_as_text; break;
366
	    case pdata : i = m_as_data ; break ;
389
	    case pdata: i = m_as_data; break;
367
	    case pbss : i = m_as_bss ; break ;
390
	    case pbss: i = m_as_bss; break;
368
	    default : i = m_dont_know ; break ;
391
	    default : i = m_dont_know; break;
369
	}
392
	}
370
	make_instr ( i, null, null, 0 ) ;
393
	make_instr(i, null, null, 0);
371
	previous_area = current_area ;
394
	previous_area = current_area;
372
	current_area = p ;
395
	current_area = p;
373
    } else {
396
    } else {
374
	previous_area = current_area ;
397
	previous_area = current_area;
375
    }
398
    }
376
    return ;
399
    return;
377
}
400
}
378
 
401
 
379
 
402
 
380
/*
403
/*
381
    OUTPUT A LIBRARY CALL
404
    OUTPUT A LIBRARY CALL
382
 
405
 
383
    A call of the library routine with name nm is output.
406
    A call of the library routine with name nm is output.
384
*/
407
*/
385
 
408
 
386
void libcall
409
void libcall
387
    PROTO_N ( ( nm ) )
-
 
388
    PROTO_T ( char *nm )
410
(char *nm)
389
{
411
{
390
    int lab;
412
    int lab;
391
    mach_op *p = make_extern_data ( nm, 0 ) ;
413
    mach_op *p = make_extern_data(nm, 0);
392
#if 0 /*float_to_unsigned*/
414
#if 0 /*float_to_unsigned*/
393
    if((have_overflow() || have_continue())&& !strcmp(nm,float_to_unsigned)) {
415
    if ((have_overflow() || have_continue()) && !strcmp(nm,float_to_unsigned)) {
394
      /* we need to ensure that the value in %fp0 is not outside the valid
416
      /* we need to ensure that the value in %fp0 is not outside the valid
395
	 range for an unsigned int, otherwise there will be a floating
417
	 range for an unsigned int, otherwise there will be a floating
396
	 point exception in the library routine. */
418
	 point exception in the library routine. */
397
      bool sw;
419
      bool sw;
398
      exp e = getexp(ulongsh,nilexp,0,nilexp,nilexp,0,1333788672,val_tag);
420
      exp e = getexp(ulongsh,nilexp,0,nilexp,nilexp,0,1333788672,val_tag);
399
      exp loc = sim_exp(shrealsh,FP1);
421
      exp loc = sim_exp(shrealsh,FP1);
400
      lab = (have_continue())?next_lab() : overflow_jump;
422
      lab = (have_continue())?next_lab(): overflow_jump;
401
      ins2(m_fmoves,shape_size(shrealsh),shape_size(shrealsh),zw(e),zw(loc));
423
      ins2(m_fmoves,shape_size(shrealsh),shape_size(shrealsh),zw(e),zw(loc));
402
      /*move(ulongsh,zw(e),zw(loc));  */
424
      /*move(ulongsh,zw(e),zw(loc));  */
403
      sw = cmp(shrealsh,FP0,FP1,tst_gr);
425
      sw = cmp(shrealsh,FP0,FP1,tst_gr);
404
 
426
 
405
      make_jump(branch_ins(tst_gr,sw,0,1),lab);
427
      make_jump(branch_ins(tst_gr,sw,0,1),lab);
406
      kill_exp(e,e);
428
      kill_exp(e,e);
407
    }
429
    }
408
#endif
430
#endif
409
 
431
 
410
    make_instr ( m_call, p, null, ~save_msk ) ;
432
    make_instr(m_call, p, null, ~save_msk);
411
    no_calls++ ;
433
    no_calls++;
412
#if 0
434
#if 0
413
    if(have_continue() && !strcmp(nm,float_to_unsigned)) {
435
    if (have_continue() && !strcmp(nm,float_to_unsigned)) {
414
      make_label(lab);
436
      make_label(lab);
415
    }
437
    }
416
#endif
438
#endif
417
    have_cond = 0 ;
439
    have_cond = 0;
418
    return ;
440
    return;
419
}
441
}
420
 
442
 
421
 
443
 
422
/*
444
/*
423
    REGISTER MASKS
445
    REGISTER MASKS
Line 428... Line 450...
428
    the record of all the current active reuseable registers.  bigregs
450
    the record of all the current active reuseable registers.  bigregs
429
    records all registers in the current procedure which span procedure
451
    records all registers in the current procedure which span procedure
430
    calls.
452
    calls.
431
*/
453
*/
432
 
454
 
433
bitpattern regsinuse ;
455
bitpattern regsinuse;
434
bitpattern regsinproc ;
456
bitpattern regsinproc;
435
bitpattern reuseables ;
457
bitpattern reuseables;
436
bitpattern regsindec ;
458
bitpattern regsindec;
437
bitpattern bigregs ;
459
bitpattern bigregs;
438
 
460
 
439
 
461
 
440
/*
462
/*
441
    OTHER VARIABLES
463
    OTHER VARIABLES
442
 
464
 
Line 444... Line 466...
444
    the current procedure.  just_ret is set to be true if the return
466
    the current procedure.  just_ret is set to be true if the return
445
    sequence just consists of a single rts instruction.  no_calls
467
    sequence just consists of a single rts instruction.  no_calls
446
    records the number of procedure calls in the current procedure.
468
    records the number of procedure calls in the current procedure.
447
*/
469
*/
448
 
470
 
449
long crt_ret_lab = 0 ;
471
long crt_ret_lab = 0;
450
bool just_ret = 0 ;
472
bool just_ret = 0;
451
int no_calls = 0 ;
473
int no_calls = 0;
452
 
474
 
453
 
475
 
454
/*
476
/*
455
    PROLOGUE POSITIONS
477
    PROLOGUE POSITIONS
456
 
478
 
457
    This records the position of the prologue of the current procedure.
479
    This records the position of the prologue of the current procedure.
458
*/
480
*/
459
 
481
 
460
mach_ins *prologue_ins ;
482
mach_ins *prologue_ins;
461
 
483
 
462
 
484
 
463
/*
485
/*
464
    GENERAL PURPOSE PROCEDURE PROLOGUE
486
    GENERAL PURPOSE PROCEDURE PROLOGUE
465
 
487
 
Line 468... Line 490...
468
    a number of special labels are used to represent values which will
490
    a number of special labels are used to represent values which will
469
    not be known until the end of the procedure.
491
    not be known until the end of the procedure.
470
*/
492
*/
471
 
493
 
472
void prologue
494
void prologue
473
    PROTO_Z ()
495
(void)
474
{
496
{
475
    mach_op *op1, *op2 ;
497
    mach_op *op1, *op2;
476
    have_cond = 0 ;
498
    have_cond = 0;
477
    just_ret = 1 ;
499
    just_ret = 1;
478
    if ( !output_immediately ) {
500
    if (!output_immediately) {
479
	/* Just record position in this case */
501
	/* Just record position in this case */
480
	prologue_ins = current_ins ;
502
	prologue_ins = current_ins;
481
	return ;
503
	return;
482
    }
504
    }
483
    /* Output generalized link and push instructions */
505
    /* Output generalized link and push instructions */
484
    op1 = make_register ( REG_AP ) ;
506
    op1 = make_register(REG_AP);
485
    op2 = make_special ( "PA" ) ;
507
    op2 = make_special("PA");
486
    make_instr ( m_linkl, op1, op2, 0 ) ;
508
    make_instr(m_linkl, op1, op2, 0);
487
    op1 = make_special ( "PB" ) ;
509
    op1 = make_special("PB");
488
    op2 = make_indirect ( REG_SP, 0 ) ;
510
    op2 = make_indirect(REG_SP, 0);
489
    make_instr ( m_moveml, op1, op2, 0 ) ;
511
    make_instr(m_moveml, op1, op2, 0);
490
    op1 = make_special ( "PC" ) ;
512
    op1 = make_special("PC");
491
    op2 = make_indirect ( REG_AP, 0 ) ;
513
    op2 = make_indirect(REG_AP, 0);
492
    op2->of->plus = make_special ( "PD" ) ;
514
    op2->of->plus = make_special("PD");
493
    make_instr ( m_fmovemx, op1, op2, 0 ) ;
515
    make_instr(m_fmovemx, op1, op2, 0);
494
    return ;
516
    return;
495
}
517
}
496
 
518
 
497
 
519
 
498
/*
520
/*
499
    GENERAL PURPOSE PROCEDURE EPILOGUE
521
    GENERAL PURPOSE PROCEDURE EPILOGUE
Line 505... Line 527...
505
    prologue are output.  There is some testing to see if D1, A0, A1
527
    prologue are output.  There is some testing to see if D1, A0, A1
506
    and FP1 can be put to better use.
528
    and FP1 can be put to better use.
507
*/
529
*/
508
 
530
 
509
void epilogue
531
void epilogue
510
    PROTO_N ( ( restore_only ) )
-
 
511
    PROTO_T ( int restore_only )
532
(int restore_only)
512
{
533
{
513
    int r ;
534
    int r;
514
    bitpattern m ;
535
    bitpattern m;
515
    long st, st1 ;
536
    long st, st1;
516
    mach_op *op1, *op2 ;
537
    mach_op *op1, *op2;
517
 
538
 
518
    int push_all = 0, use_link = 0 ;
539
    int push_all = 0, use_link = 0;
519
    int tmp_d1 = -1, tmp_a0 = -1, tmp_a1 = -1 ;
540
    int tmp_d1 = -1, tmp_a0 = -1, tmp_a1 = -1;
520
 
541
 
521
    bitpattern rmsk = regs ( regsinproc & save_msk ) ;
542
    bitpattern rmsk = regs(regsinproc & save_msk);
522
    bitpattern smsk = rmsk ;
543
    bitpattern smsk = rmsk;
523
    bitpattern cmsk = 0 ;
544
    bitpattern cmsk = 0;
524
    bitpattern fmsk = 0 ;
545
    bitpattern fmsk = 0;
525
    bitpattern fsmsk = fregs ( regsinproc & save_msk ) ;
546
    bitpattern fsmsk = fregs(regsinproc & save_msk);
526
 
547
 
527
    reset_round_mode();  /* restore the default floating point rounding mode */
548
    reset_round_mode();  /* restore the default floating point rounding mode */
528
 
549
 
529
    for ( r = REG_FP7, m = 1 ; r >= REG_FP2 ; r--, m <<= 1 ) {
550
    for (r = REG_FP7, m = 1; r >= REG_FP2; r--, m <<= 1) {
530
	if ( regsinproc & regmsk ( r ) ) fmsk |= m ;
551
	if (regsinproc & regmsk(r))fmsk |= m;
531
    }
552
    }
532
 
553
 
533
    if ( no_calls ) {
554
    if (no_calls) {
534
	smsk &= ~bigregs ;
555
	smsk &= ~bigregs;
535
	fsmsk &= ~bigregs ;
556
	fsmsk &= ~bigregs;
536
    }
557
    }
537
    if(!restore_only) {
558
    if (!restore_only) {
538
      make_label ( crt_ret_lab ) ;
559
      make_label(crt_ret_lab);
539
    }
560
    }
540
 
561
 
541
#if have_diagnostics
562
#if have_diagnostics
542
    if ( diagnose ) xdb_diag_proc_return () ;
563
    if (diagnose)xdb_diag_proc_return();
543
#endif
564
#endif
544
 
565
 
545
    if ( !output_immediately ) {
566
    if (!output_immediately) {
546
	bool d1_free = 0 ;
567
	bool d1_free = 0;
547
 
568
 
548
	/* Use D1 if not already used */
569
	/* Use D1 if not already used */
549
	if ( !( regsinproc & regmsk ( REG_D1 ) ) ) {
570
	if (!(regsinproc & regmsk(REG_D1))) {
550
	    m = smsk & dreg_msk ;
571
	    m = smsk & dreg_msk;
551
	    if ( m ) {
572
	    if (m) {
552
		/* Replace a used D-register by D1 */
573
		/* Replace a used D-register by D1 */
553
		r = reg ( m ) ;
574
		r = reg(m);
554
		reg_names [r] = reg_names [ REG_D1 ] ;
575
		reg_names[r] = reg_names[REG_D1];
555
		rmsk &= ~regmsk ( r ) ;
576
		rmsk &= ~regmsk(r);
556
		smsk &= ~regmsk ( r ) ;
577
		smsk &= ~regmsk(r);
557
		cmsk |= regmsk ( r ) ;
578
		cmsk |= regmsk(r);
558
	    } else {
579
	    } else {
559
		d1_free = 1 ;
580
		d1_free = 1;
560
	    }
581
	    }
561
	}
582
	}
562
 
583
 
563
	/* Use A0 if not already used */
584
	/* Use A0 if not already used */
564
	if ( !( regsinproc & regmsk ( REG_A0 ) ) ) {
585
	if (!(regsinproc & regmsk(REG_A0))) {
565
	    m = smsk & areg_msk ;
586
	    m = smsk & areg_msk;
566
	    if ( m ) {
587
	    if (m) {
567
		/* Replace a used A-register by A0 */
588
		/* Replace a used A-register by A0 */
568
		r = reg ( m ) ;
589
		r = reg(m);
569
		reg_names [r] = reg_names [ REG_A0 ] ;
590
		reg_names[r] = reg_names[REG_A0];
570
		rmsk &= ~regmsk ( r ) ;
591
		rmsk &= ~regmsk(r);
571
		smsk &= ~regmsk ( r ) ;
592
		smsk &= ~regmsk(r);
572
		cmsk |= regmsk ( r ) ;
593
		cmsk |= regmsk(r);
573
	    } else if ( no_calls == 0 ) {
594
	    } else if (no_calls == 0) {
574
		m = rmsk & dreg_msk ;
595
		m = rmsk & dreg_msk;
575
		if ( m ) {
596
		if (m) {
576
		    /* Move a used D-register into A0 */
597
		    /* Move a used D-register into A0 */
577
		    tmp_a0 = reg ( m ) ;
598
		    tmp_a0 = reg(m);
578
		    rmsk &= ~regmsk ( tmp_a0 ) ;
599
		    rmsk &= ~regmsk(tmp_a0);
579
		    smsk = rmsk ;
600
		    smsk = rmsk;
580
		    op1 = make_register ( REG_A0 ) ;
601
		    op1 = make_register(REG_A0);
581
		    op2 = make_register ( tmp_a0 ) ;
602
		    op2 = make_register(tmp_a0);
582
		    make_instr ( m_movl, op1, op2, regmsk ( tmp_a0 ) ) ;
603
		    make_instr(m_movl, op1, op2, regmsk(tmp_a0));
583
		    just_ret = 0 ;
604
		    just_ret = 0;
584
		}
605
		}
585
	    }
606
	    }
586
	}
607
	}
587
 
608
 
588
	/* Use A1 if not already used */
609
	/* Use A1 if not already used */
589
	if ( !( regsinproc & regmsk ( REG_A1 ) ) ) {
610
	if (!(regsinproc & regmsk(REG_A1))) {
590
	    m = smsk & areg_msk ;
611
	    m = smsk & areg_msk;
591
	    if ( m ) {
612
	    if (m) {
592
		/* Replace a used A-register by A1 */
613
		/* Replace a used A-register by A1 */
593
		r = reg ( m ) ;
614
		r = reg(m);
594
		reg_names [r] = reg_names [ REG_A1 ] ;
615
		reg_names[r] = reg_names[REG_A1];
595
		rmsk &= ~regmsk ( r ) ;
616
		rmsk &= ~regmsk(r);
596
		smsk &= ~regmsk ( r ) ;
617
		smsk &= ~regmsk(r);
597
		cmsk |= regmsk ( r ) ;
618
		cmsk |= regmsk(r);
598
	    } else if ( no_calls == 0 ) {
619
	    } else if (no_calls == 0) {
599
		m = rmsk & dreg_msk ;
620
		m = rmsk & dreg_msk;
600
		if ( m ) {
621
		if (m) {
601
		    /* Move a used D-register into A1 */
622
		    /* Move a used D-register into A1 */
602
		    tmp_a1 = reg ( m ) ;
623
		    tmp_a1 = reg(m);
603
		    rmsk &= ~regmsk ( tmp_a1 ) ;
624
		    rmsk &= ~regmsk(tmp_a1);
604
		    smsk = rmsk ;
625
		    smsk = rmsk;
605
		    op1 = make_register ( REG_A1 ) ;
626
		    op1 = make_register(REG_A1);
606
		    op2 = make_register ( tmp_a1 ) ;
627
		    op2 = make_register(tmp_a1);
607
		    make_instr ( m_movl, op1, op2, regmsk ( tmp_a1 ) ) ;
628
		    make_instr(m_movl, op1, op2, regmsk(tmp_a1));
608
		    just_ret = 0 ;
629
		    just_ret = 0;
609
		}
630
		}
610
	    }
631
	    }
611
	}
632
	}
612
 
633
 
613
	/* Use FP1 if not already used */
634
	/* Use FP1 if not already used */
614
	if ( !( regsinproc & regmsk ( REG_FP1 ) ) ) {
635
	if (!(regsinproc & regmsk(REG_FP1))) {
615
	    for ( r = REG_FP7, m = 1 ; r >= REG_FP2 ; r--, m <<= 1 ) {
636
	    for (r = REG_FP7, m = 1; r >= REG_FP2; r--, m <<= 1) {
616
		if ( fsmsk & regmsk ( r ) ) {
637
		if (fsmsk & regmsk(r)) {
617
		    reg_names [r] = reg_names [ REG_FP1 ] ;
638
		    reg_names[r] = reg_names[REG_FP1];
618
		    fmsk &= ~m ;
639
		    fmsk &= ~m;
619
		    fsmsk &= ~regmsk ( r ) ;
640
		    fsmsk &= ~regmsk(r);
620
		    cmsk |= regmsk ( r ) ;
641
		    cmsk |= regmsk(r);
621
		    r = REG_FP1 ;
642
		    r = REG_FP1;
622
		}
643
		}
623
	    }
644
	    }
624
	}
645
	}
625
 
646
 
626
	if ( d1_free && no_calls == 0 ) {
647
	if (d1_free && no_calls == 0) {
627
	    m = rmsk & areg_msk ;
648
	    m = rmsk & areg_msk;
628
	    if ( m ) {
649
	    if (m) {
629
		/* Move a used A-register into D1 */
650
		/* Move a used A-register into D1 */
630
		tmp_d1 = reg ( m ) ;
651
		tmp_d1 = reg(m);
631
		rmsk &= ~regmsk ( tmp_d1 ) ;
652
		rmsk &= ~regmsk(tmp_d1);
632
		op1 = make_register ( REG_D1 ) ;
653
		op1 = make_register(REG_D1);
633
		op2 = make_register ( tmp_d1 ) ;
654
		op2 = make_register(tmp_d1);
634
		make_instr ( m_movl, op1, op2, regmsk ( tmp_d1 ) ) ;
655
		make_instr(m_movl, op1, op2, regmsk(tmp_d1));
635
		just_ret = 0 ;
656
		just_ret = 0;
636
	    }
657
	    }
637
	}
658
	}
638
 
659
 
639
    }
660
    }
640
 
661
 
641
    /* Calculate stack displacements */
662
    /* Calculate stack displacements */
642
/* todo use symbol instead of number */
663
/* todo use symbol instead of number */
643
    st1 = round ( max_stack, 32 ) / 8 + 16 * bits_in ( fmsk ) ;
664
    st1 = round(max_stack, 32) / 8 + 16 * bits_in(fmsk);
644
    st = st1 + 4 * bits_in ( rmsk ) ;
665
    st = st1 + 4 * bits_in(rmsk);
645
    if ( st1 || used_stack || !push_all || output_immediately ) use_link = 1 ;
666
    if (st1 || used_stack || !push_all || output_immediately)use_link = 1;
646
 
667
 
647
    /* Remove floating-point registers from the stack */
668
    /* Remove floating-point registers from the stack */
648
    if ( fmsk ) {
669
    if (fmsk) {
649
	just_ret = 0 ;
670
	just_ret = 0;
650
	op1 = make_indirect ( REG_AP, -st1 ) ;
671
	op1 = make_indirect(REG_AP, -st1);
651
	op2 = make_hex_value ( fmsk ) ;
672
	op2 = make_hex_value(fmsk);
652
	make_instr ( m_fmovemx, op1, op2, 0 ) ;
673
	make_instr(m_fmovemx, op1, op2, 0);
653
    }
674
    }
654
 
675
 
655
    /* Remove registers from the stack */
676
    /* Remove registers from the stack */
656
    if ( rmsk ) {
677
    if (rmsk) {
657
	just_ret = 0 ;
678
	just_ret = 0;
658
	if ( push_all ) {
679
	if (push_all) {
659
	    for ( r = REG_AP - 1 ; r > REG_D1 ; r-- ) {
680
	    for (r = REG_AP - 1; r > REG_D1; r--) {
660
		if ( rmsk & regmsk ( r ) ) {
681
		if (rmsk & regmsk(r)) {
661
		    op1 = make_inc_sp () ;
682
		    op1 = make_inc_sp();
662
		    op2 = make_register ( r ) ;
683
		    op2 = make_register(r);
663
		    make_instr ( m_movl, op1, op2, regmsk ( r ) ) ;
684
		    make_instr(m_movl, op1, op2, regmsk(r));
664
		}
685
		}
665
	    }
686
	    }
666
	} else {
687
	} else {
667
	    if ( must_use_bp ) {
688
	    if (must_use_bp) {
668
		op1 = make_indirect ( REG_AP, -st ) ;
689
		op1 = make_indirect(REG_AP, -st);
669
	    } else {
690
	    } else {
670
		op1 = make_indirect ( REG_SP, 0 ) ;
691
		op1 = make_indirect(REG_SP, 0);
671
	    }
692
	    }
672
	    op2 = make_hex_value ( rmsk ) ;
693
	    op2 = make_hex_value(rmsk);
673
	    make_instr ( m_moveml, op1, op2, rmsk ) ;
694
	    make_instr(m_moveml, op1, op2, rmsk);
674
	    just_ret = 0 ;
695
	    just_ret = 0;
675
	}
696
	}
676
    }
697
    }
677
 
698
 
678
    /* Output unlink instruction */
699
    /* Output unlink instruction */
679
    if ( use_link ) {
700
    if (use_link) {
680
	just_ret = 0 ;
701
	just_ret = 0;
681
	op1 = make_register ( REG_AP ) ;
702
	op1 = make_register(REG_AP);
682
	make_instr ( m_unlk, op1, null, 0 ) ;
703
	make_instr(m_unlk, op1, null, 0);
683
    }
704
    }
684
    if(!restore_only) {
705
    if (!restore_only) {
685
      /* Output return instruction */
706
      /* Output return instruction */
686
      make_instr ( m_rts, null, null, 0 ) ;
707
      make_instr(m_rts, null, null, 0);
687
    }
708
    }
688
 
709
 
689
    if ( output_immediately ) {
710
    if (output_immediately) {
690
 
711
 
691
	/* Output stack displacement value */
712
	/* Output stack displacement value */
692
	if ( used_ldisp ) {
713
	if (used_ldisp) {
693
	    op1 = make_int_data ( use_link ? st + 4 : st ) ;
714
	    op1 = make_int_data(use_link ? st + 4 : st);
694
	    set_special ( "S", op1 ) ;
715
	    set_special("S", op1);
695
	}
716
	}
696
 
717
 
697
	/* Output values used in prologue */
718
	/* Output values used in prologue */
698
	just_ret = 0 ;
719
	just_ret = 0;
699
	op1 = make_int_data ( -st ) ;
720
	op1 = make_int_data(-st);
700
	set_special ( "PA", op1 ) ;
721
	set_special("PA", op1);
701
	op1 = make_hex_data ( rmsk ) ;
722
	op1 = make_hex_data(rmsk);
702
	set_special ( "PB", op1 ) ;
723
	set_special("PB", op1);
703
	op1 = make_hex_data ( fmsk ) ;
724
	op1 = make_hex_data(fmsk);
704
	set_special ( "PC", op1 ) ;
725
	set_special("PC", op1);
705
	op1 = make_int_data ( -st1 ) ;
726
	op1 = make_int_data(-st1);
706
	set_special ( "PD", op1 ) ;
727
	set_special("PD", op1);
707
 
728
 
708
    } else if(!restore_only){
729
    } else if (!restore_only) {
709
 
730
 
710
	/* Go back to the prologue position */
731
	/* Go back to the prologue position */
711
	mach_ins *p = current_ins ;
732
	mach_ins *p = current_ins;
712
	current_ins = prologue_ins ;
733
	current_ins = prologue_ins;
713
 
734
 
714
        cur_proc_env_size = ldisp = ( use_link ? st + 4 : st ) ;
735
        cur_proc_env_size = ldisp = (use_link ? st + 4 : st);
715
 
736
 
716
	/* Output link instruction */
737
	/* Output link instruction */
717
	if ( use_link ) {
738
	if (use_link) {
718
	    long c = ( push_all ? -st1 : -st ) ;
739
	    long c = (push_all ? -st1 : -st);
719
	    int i = ( c < -0x7fff ? m_linkl : m_linkw ) ;
740
	    int i = (c < -0x7fff ? m_linkl : m_linkw);
720
	    op1 = make_register ( REG_AP ) ;
741
	    op1 = make_register(REG_AP);
721
	    op2 = make_value ( c ) ;
742
	    op2 = make_value(c);
722
	    make_instr ( i, op1, op2, 0 ) ;
743
	    make_instr(i, op1, op2, 0);
723
	}
744
	}
724
 
745
 
725
	/* Save register in D1 if necessary */
746
	/* Save register in D1 if necessary */
726
	if ( tmp_d1 >= 0 ) {
747
	if (tmp_d1 >= 0) {
727
	    op1 = make_register ( tmp_d1 ) ;
748
	    op1 = make_register(tmp_d1);
728
	    op2 = make_register ( REG_D1 ) ;
749
	    op2 = make_register(REG_D1);
729
	    make_instr ( m_movl, op1, op2, regmsk ( REG_D1 ) ) ;
750
	    make_instr(m_movl, op1, op2, regmsk(REG_D1));
730
	}
751
	}
731
 
752
 
732
	/* Save register in A0 if necessary */
753
	/* Save register in A0 if necessary */
733
	if ( tmp_a0 >= 0 ) {
754
	if (tmp_a0 >= 0) {
734
	    op1 = make_register ( tmp_a0 ) ;
755
	    op1 = make_register(tmp_a0);
735
	    op2 = make_register ( REG_A0 ) ;
756
	    op2 = make_register(REG_A0);
736
	    make_instr ( m_movl, op1, op2, regmsk ( REG_A0 ) ) ;
757
	    make_instr(m_movl, op1, op2, regmsk(REG_A0));
737
	}
758
	}
738
 
759
 
739
	/* Save register in A1 if necessary */
760
	/* Save register in A1 if necessary */
740
	if ( tmp_a1 >= 0 ) {
761
	if (tmp_a1 >= 0) {
741
	    op1 = make_register ( tmp_a1 ) ;
762
	    op1 = make_register(tmp_a1);
742
	    op2 = make_register ( REG_A1 ) ;
763
	    op2 = make_register(REG_A1);
743
	    make_instr ( m_movl, op1, op2, regmsk ( REG_A1 ) ) ;
764
	    make_instr(m_movl, op1, op2, regmsk(REG_A1));
744
	}
765
	}
745
 
766
 
746
	/* Put registers onto the stack */
767
	/* Put registers onto the stack */
747
	if ( rmsk ) {
768
	if (rmsk) {
748
	    if ( push_all ) {
769
	    if (push_all) {
749
		for ( r = REG_D1 + 1 ; r < REG_AP ; r++ ) {
770
		for (r = REG_D1 + 1; r < REG_AP; r++) {
750
		    if ( rmsk & regmsk ( r ) ) {
771
		    if (rmsk & regmsk(r)) {
751
			op1 = make_register ( r ) ;
772
			op1 = make_register(r);
752
			op2 = make_dec_sp () ;
773
			op2 = make_dec_sp();
753
			make_instr ( m_movl, op1, op2, 0 ) ;
774
			make_instr(m_movl, op1, op2, 0);
754
		    }
775
		    }
755
		}
776
		}
756
	    } else {
777
	    } else {
757
		op1 = make_hex_value ( rmsk ) ;
778
		op1 = make_hex_value(rmsk);
758
		op2 = make_indirect ( REG_SP, 0 ) ;
779
		op2 = make_indirect(REG_SP, 0);
759
		make_instr ( m_moveml, op1, op2, 0 ) ;
780
		make_instr(m_moveml, op1, op2, 0);
760
	    }
781
	    }
761
	}
782
	}
762
 
783
 
763
	/* Put floating-point registers onto the stack */
784
	/* Put floating-point registers onto the stack */
764
	if ( fmsk ) {
785
	if (fmsk) {
765
	    op1 = make_hex_value ( fmsk ) ;
786
	    op1 = make_hex_value(fmsk);
766
	    op2 = make_indirect ( REG_AP, -st1 ) ;
787
	    op2 = make_indirect(REG_AP, -st1);
767
	    make_instr ( m_fmovemx, op1, op2, 0 ) ;
788
	    make_instr(m_fmovemx, op1, op2, 0);
768
	}
789
	}
769
 
790
 
770
	/* Return to previous position */
791
	/* Return to previous position */
771
	current_ins = p ;
792
	current_ins = p;
772
    }
793
    }
773
    callmsk = cmsk ;
794
    callmsk = cmsk;
774
    have_cond = 0 ;
795
    have_cond = 0;
775
    return ;
796
    return;
776
}
797
}
777
 
798
 
778
 
799
 
779
/*
800
/*
780
    PROFILING
801
    PROFILING
Line 798... Line 819...
798
			long	0
819
			long	0
799
 
820
 
800
    The flag used_my_mcount is set to be true if Lmcount is used.
821
    The flag used_my_mcount is set to be true if Lmcount is used.
801
*/
822
*/
802
 
823
 
803
static bool used_my_mcount = 0 ;
824
static bool used_my_mcount = 0;
804
 
825
 
805
 
826
 
806
/*
827
/*
807
    OUTPUT PROFILING DATA
828
    OUTPUT PROFILING DATA
808
 
829
 
809
    This routine outputs the profiling data for a procedure.  If save_a1
830
    This routine outputs the profiling data for a procedure.  If save_a1
810
    is true, the alternative profiling routine is used.
831
    is true, the alternative profiling routine is used.
811
*/
832
*/
812
 
833
 
813
void out_profile
834
void out_profile
814
    PROTO_N ( ( save_a1 ) )
-
 
815
    PROTO_T ( bool save_a1 )
835
(bool save_a1)
816
{
836
{
817
    exp z ;
837
    exp z;
818
    mach_op *op1, *op2 ;
838
    mach_op *op1, *op2;
819
    /* Make a new label */
839
    /* Make a new label */
820
    long lb = next_lab () ;
840
    long lb = next_lab();
821
 
841
 
822
    if ( profiling_uses_lea ) {
842
    if (profiling_uses_lea) {
823
	op1 = make_lab_data ( lb, 0 ) ;
843
	op1 = make_lab_data(lb, 0);
824
	op2 = make_register ( profiling_reg ) ;
844
	op2 = make_register(profiling_reg);
825
	make_instr ( m_lea, op1, op2, regmsk ( profiling_reg ) ) ;
845
	make_instr(m_lea, op1, op2, regmsk(profiling_reg));
826
    } else {
846
    } else {
827
	op1 = make_lab ( lb, 0 ) ;
847
	op1 = make_lab(lb, 0);
828
	op2 = make_register ( profiling_reg ) ;
848
	op2 = make_register(profiling_reg);
829
	make_instr ( m_movl, op1, op2, regmsk ( profiling_reg ) ) ;
849
	make_instr(m_movl, op1, op2, regmsk(profiling_reg));
830
    }
850
    }
831
 
851
 
832
    if ( save_a1 ) {
852
    if (save_a1) {
833
	/* Call dummy version of mcount - see below */
853
	/* Call dummy version of mcount - see below */
834
	libcall ( "Lmcount" ) ;
854
	libcall("Lmcount");
835
	/* Restore the value of A1 */
855
	/* Restore the value of A1 */
836
	op1 = make_extern_ind ( "Lmstore", 0 ) ;
856
	op1 = make_extern_ind("Lmstore", 0);
837
	op2 = make_register ( REG_A1 ) ;
857
	op2 = make_register(REG_A1);
838
	make_instr ( m_movl, op1, op2, regmsk ( REG_A1 ) ) ;
858
	make_instr(m_movl, op1, op2, regmsk(REG_A1));
839
	used_my_mcount = 1 ;
859
	used_my_mcount = 1;
840
    } else {
860
    } else {
841
	/* Call mcount */
861
	/* Call mcount */
842
	libcall ( profiling_routine ) ;
862
	libcall(profiling_routine);
843
    }
863
    }
844
 
864
 
845
    /* Set up the label to point to 0 */
865
    /* Set up the label to point to 0 */
846
    z = simple_exp ( val_tag ) ;
866
    z = simple_exp(val_tag);
847
    sh ( z ) = slongsh ;
867
    sh(z) = slongsh;
848
    make_constant ( lb, z ) ;
868
    make_constant(lb, z);
849
    return ;
869
    return;
850
}
870
}
851
 
871
 
852
 
872
 
853
/*
873
/*
854
    OUTPUT ALTERNATIVE PROFILING ROUTINE
874
    OUTPUT ALTERNATIVE PROFILING ROUTINE
Line 856... Line 876...
856
    This routine outputs the alternative profiling routine Lmcount
876
    This routine outputs the alternative profiling routine Lmcount
857
    described above if it is required.
877
    described above if it is required.
858
*/
878
*/
859
 
879
 
860
void profile_hack
880
void profile_hack
861
    PROTO_Z ()
881
(void)
862
{
882
{
863
    mach_op *op1, *op2 ;
883
    mach_op *op1, *op2;
864
    if ( !used_my_mcount ) return ;
884
    if (!used_my_mcount) return;
865
    area ( ptext ) ;
885
    area(ptext);
866
    make_external_label ( "Lmcount" ) ;
886
    make_external_label("Lmcount");
867
    op1 = make_register ( REG_A1 ) ;
887
    op1 = make_register(REG_A1);
868
    op2 = make_extern_ind ( "Lmstore", 0 ) ;
888
    op2 = make_extern_ind("Lmstore", 0);
869
    make_instr ( m_movl, op1, op2, 0 ) ;
889
    make_instr(m_movl, op1, op2, 0);
870
    op1 = make_extern_data ( profiling_routine, 0 ) ;
890
    op1 = make_extern_data(profiling_routine, 0);
871
    make_instr ( m_jmp, op1, null, 0 ) ;
891
    make_instr(m_jmp, op1, null, 0);
872
    area ( pdata ) ;
892
    area(pdata);
873
    make_external_label ( "Lmstore" ) ;
893
    make_external_label("Lmstore");
874
    op1 = make_int_data ( 0 ) ;
894
    op1 = make_int_data(0);
875
    make_instr ( m_as_long, op1, null, 0 ) ;
895
    make_instr(m_as_long, op1, null, 0);
876
    return ;
896
    return;
877
}
897
}
878
 
898
 
879
#if 0
899
#if 0
880
/*
900
/*
881
    ENCODE A PROCEDURE
901
    ENCODE A PROCEDURE
Line 884... Line 904...
884
    with oname as an alternative (used with diagnostics).  The actual
904
    with oname as an alternative (used with diagnostics).  The actual
885
    body of the procedure is p.
905
    body of the procedure is p.
886
*/
906
*/
887
 
907
 
888
void cproc
908
void cproc
889
    PROTO_N ( ( p, pname, cname, is_ext, reg_res, di ) )
-
 
890
    PROTO_T ( exp p X char *pname X long cname X int is_ext X int reg_res X diag_global *di )
909
(exp p, char *pname, long cname, int is_ext, int reg_res, diag_global *di)
891
{
910
{
892
    exp t ;
911
    exp t;
893
    ash stack ;
912
    ash stack;
894
    ash param_pos ;
913
    ash param_pos;
895
    mach_op *op1, *op2 ;
914
    mach_op *op1, *op2;
896
    static long crt_proc_no = 0 ;
915
    static long crt_proc_no = 0;
897
 
916
 
898
#ifndef tdf3
917
#ifndef tdf3
899
    cur_proc_has_tail_call = 0;
918
    cur_proc_has_tail_call = 0;
900
    cur_proc_use_same_callees = 0;
919
    cur_proc_use_same_callees = 0;
901
    scan2(1, p, p);
920
    scan2(1, p, p);
902
    comp_weights ( p ) ;
921
    comp_weights(p);
903
#endif
922
#endif
904
 
923
 
905
    /* Set up flags, register masks, stack etc. */
924
    /* Set up flags, register masks, stack etc. */
906
    bigregs = 0 ;
925
    bigregs = 0;
907
    crt_ret_lab = next_lab () ;
926
    crt_ret_lab = next_lab();
908
    extra_stack = 0 ;
927
    extra_stack = 0;
909
    have_cond = 0 ;
928
    have_cond = 0;
910
    max_stack = 0 ;
929
    max_stack = 0;
911
    no_calls = 0 ;
930
    no_calls = 0;
912
    regsinproc = 0 ;
931
    regsinproc = 0;
913
    regsinuse = 0 ;
932
    regsinuse = 0;
914
    reuseables = 0 ;
933
    reuseables = 0;
915
    regsindec = 0 ;
934
    regsindec = 0;
916
    stack = 0 ;
935
    stack = 0;
917
    special_no = crt_proc_no++ ;
936
    special_no = crt_proc_no++;
918
    stack_dec = 0 ;
937
    stack_dec = 0;
919
    stack_size = 0 ;
938
    stack_size = 0;
920
    used_ldisp = 0 ;
939
    used_ldisp = 0;
921
    used_stack = diagnose || must_use_bp ;
940
    used_stack = diagnose || must_use_bp;
922
 
941
 
923
    /* Mark procedure body */
942
    /* Mark procedure body */
924
    ptno ( p ) = par_pl ;
943
    ptno(p) = par_pl;
925
    no ( p ) = 0 ;
944
    no(p) = 0;
926
 
945
 
927
    /* Mark procedure parameters */
946
    /* Mark procedure parameters */
928
    param_pos = 0 ;
947
    param_pos = 0;
929
    t = son ( p ) ;
948
    t = son(p);
930
    while ( name ( t ) == ident_tag && isparam ( t ) ) {
949
    while (name(t) == ident_tag && isparam(t)) {
931
	ast a ;
950
	ast a;
932
	a = add_shape_to_stack ( param_pos, sh ( son ( t ) ) ) ;
951
	a = add_shape_to_stack(param_pos, sh(son(t)));
933
	ptno ( t ) = par_pl ;
952
	ptno(t) = par_pl;
934
	no ( t ) = a.astoff + a.astadj ;
953
	no(t) = a.astoff + a.astadj;
935
	param_pos = a.astash ;
954
	param_pos = a.astash;
936
 
955
 
937
        make_visible( t ) ;
956
        make_visible(t);
938
 
957
 
939
	t = bro ( son ( t ) ) ;
958
	t = bro(son(t));
940
    }
959
    }
941
 
960
 
942
    /* Output procedure name(s) */
961
    /* Output procedure name(s) */
943
    area ( ptext ) ;
962
    area(ptext);
944
#ifndef no_align_directives
963
#ifndef no_align_directives
945
    make_instr ( m_as_align4, null, null, 0 ) ;
964
    make_instr(m_as_align4, null, null, 0);
946
#endif
965
#endif
947
    if ( is_ext && pname ) {
966
    if (is_ext && pname) {
948
	if ( strcmp ( pname, "_cmppt" ) == 0 ) {
967
	if (strcmp(pname, "_cmppt") == 0) {
949
	    /* Hack to get alignments right */
968
	    /* Hack to get alignments right */
950
	    make_instr ( m_nop, null, null, 0 ) ;
969
	    make_instr(m_nop, null, null, 0);
951
	    make_instr ( m_nop, null, null, 0 ) ;
970
	    make_instr(m_nop, null, null, 0);
952
	}
971
	}
953
	op1 = make_extern_data ( pname, 0 ) ;
972
	op1 = make_extern_data(pname, 0);
954
	make_instr ( m_as_global, op1, null, 0 ) ;
973
	make_instr(m_as_global, op1, null, 0);
955
    }
974
    }
956
    if ( cname == -1 ) {
975
    if (cname == -1) {
957
	make_external_label ( pname ) ;
976
	make_external_label(pname);
958
    } else {
977
    } else {
959
	make_label ( cname ) ;
978
	make_label(cname);
960
    }
979
    }
961
 
980
 
962
    /* Output profiling information if required */
981
    /* Output profiling information if required */
963
    if ( do_profile ) {
982
    if (do_profile) {
964
	out_profile ( !reg_res ) ;
983
	out_profile(!reg_res);
965
	used_stack = 1 ;
984
	used_stack = 1;
966
    }
985
    }
967
 
986
 
968
    /* Set up procedure prologue */
987
    /* Set up procedure prologue */
969
    prologue () ;
988
    prologue();
970
 
989
 
971
    /* Output PIC prologue if necessary */
990
    /* Output PIC prologue if necessary */
972
    if ( do_pic && proc_uses_external ( p ) ) {
991
    if (do_pic && proc_uses_external(p)) {
973
	regsinproc |= regmsk ( REG_A5 ) ;
992
	regsinproc |= regmsk(REG_A5);
974
	regsinuse |= regmsk ( REG_A5 ) ;
993
	regsinuse |= regmsk(REG_A5);
975
	bigregs |= regmsk ( REG_A5 ) ;
994
	bigregs |= regmsk(REG_A5);
976
	op1 = make_indirect ( REG_PC, 0 ) ;
995
	op1 = make_indirect(REG_PC, 0);
977
	op1->of->plus = make_extern_data ( "_GLOBAL_OFFSET_TABLE_@GOTPC", 0 ) ;
996
	op1->of->plus = make_extern_data("_GLOBAL_OFFSET_TABLE_@GOTPC", 0);
978
	op2 = make_register ( REG_A5 ) ;
997
	op2 = make_register(REG_A5);
979
	make_instr ( m_lea, op1, op2, regmsk ( REG_A5 ) ) ;
998
	make_instr(m_lea, op1, op2, regmsk(REG_A5));
980
    }
999
    }
981
 
1000
 
982
    /* Diagnostics for start of procedure */
1001
    /* Diagnostics for start of procedure */
983
#if have_diagnostics
1002
#if have_diagnostics
984
    if ( di ) xdb_diag_proc_begin ( di, p, pname, cname, is_ext ) ;
1003
    if (di)xdb_diag_proc_begin(di, p, pname, cname, is_ext);
985
#endif
1004
#endif
986
 
1005
 
987
    /* Allow for procedures which return compound results */
1006
    /* Allow for procedures which return compound results */
988
    if ( !reg_res ) {
1007
    if (!reg_res) {
989
	/* Save A1 on the stack */
1008
	/* Save A1 on the stack */
990
	ast newstack ;
1009
	ast newstack;
991
	newstack = add_shape_to_stack ( stack, slongsh ) ;
1010
	newstack = add_shape_to_stack(stack, slongsh);
992
	stack = newstack.astash ;
1011
	stack = newstack.astash;
993
	max_stack = 32 ;
1012
	max_stack = 32;
994
	used_stack = 1 ;
1013
	used_stack = 1;
995
	op1 = make_register ( REG_A1 ) ;
1014
	op1 = make_register(REG_A1);
996
	op2 = make_indirect ( REG_AP, -4 ) ;
1015
	op2 = make_indirect(REG_AP, -4);
997
	make_instr ( m_movl, op1, op2, 0 ) ;
1016
	make_instr(m_movl, op1, op2, 0);
998
    }
1017
    }
999
 
1018
 
1000
    /* Encode the procedure body */
1019
    /* Encode the procedure body */
1001
#if have_diagnostics
1020
#if have_diagnostics
1002
    if ( diagnose ) {
1021
    if (diagnose) {
1003
	dnt_begin () ;
1022
	dnt_begin();
1004
	coder ( zero, stack, t ) ;
1023
	coder(zero, stack, t);
1005
	dnt_end () ;
1024
	dnt_end();
1006
    } else
1025
    } else
1007
#endif
1026
#endif
1008
    coder ( zero, stack, t ) ;
1027
    coder(zero, stack, t);
1009
 
1028
 
1010
    /* Output the procedure epilogue */
1029
    /* Output the procedure epilogue */
1011
#ifndef tdf3
1030
#ifndef tdf3
1012
    general_epilogue ( 0, 0 );
1031
    general_epilogue(0, 0);
1013
#else
1032
#else
1014
    epilogue (0) ;
1033
    epilogue(0);
1015
#endif
1034
#endif
1016
    /* Apply peephole optimizations and return */
1035
    /* Apply peephole optimizations and return */
1017
    if ( do_peephole ) peephole () ;
1036
    if (do_peephole)peephole();
1018
 
1037
 
1019
    /* Diagnostics for end of procedure */
1038
    /* Diagnostics for end of procedure */
1020
#if have_diagnostics
1039
#if have_diagnostics
1021
    if ( di ) xdb_diag_proc_end ( di ) ;
1040
    if (di)xdb_diag_proc_end(di);
1022
#endif
1041
#endif
1023
    return ;
1042
    return;
1024
}
1043
}
1025
 
1044
 
1026
#endif
1045
#endif
1027
 
1046