Subversion Repositories tendra.SVN

Rev

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

Rev Author Line No. Line
2 7u83 1
/*
7 7u83 2
 * Copyright (c) 2002-2005 The TenDRA Project <http://www.tendra.org/>.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific, prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 * $Id$
30
 */
31
/*
2 7u83 32
    		 Crown Copyright (c) 1997
33
 
34
    This TenDRA(r) Computer Program is subject to Copyright
35
    owned by the United Kingdom Secretary of State for Defence
36
    acting through the Defence Evaluation and Research Agency
37
    (DERA).  It is made available to Recipients with a
38
    royalty-free licence for its use, reproduction, transfer
39
    to other parties and amendment for any purpose not excluding
40
    product development provided that any such use et cetera
41
    shall be deemed to be acceptance of the following conditions:-
42
 
43
	(1) Its Recipients shall ensure that this Notice is
44
	reproduced upon any copies or amended versions of it;
45
 
46
	(2) Any amended version of it shall be clearly marked to
47
	show both the nature of and the organisation responsible
48
	for the relevant amendment or amendments;
49
 
50
	(3) Its onward transfer from a recipient to another
51
	party shall be deemed to be that party's acceptance of
52
	these conditions;
53
 
54
	(4) DERA gives no warranty or assurance as to its
55
	quality or suitability for any purpose and DERA accepts
56
	no liability whatsoever in relation to any use to which
57
	it may be put.
58
*/
59
 
60
 
61
/*
62
$Log: proc.c,v $
63
 * Revision 1.1.1.1  1998/01/17  15:56:03  release
64
 * First version to be checked into rolling release.
65
 *
66
 * Revision 1.15  1996/12/09  12:52:46  wfs
67
 *    Prevented the superfluous "loading" to GR0.
68
 *
69
 * Revision 1.14  1996/11/14  15:22:24  wfs
70
 *    Fixed a bug in regexps.c which was common to most of the installers and
71
 * has only just come to light due to PWE's work on powertrans. (There was
72
 * previously only a patch.) Cosmetic changes to other files.
73
 *
74
 * Revision 1.13  1996/09/05  11:05:11  wfs
75
 * "dynamic_init" boolean variable removed - must always be considered true.
76
 *
77
 * Revision 1.12  1996/08/30  09:02:32  wfs
78
 * Various fixes of bugs arising from avs and pl_tdf tests.
79
 *
80
 * Revision 1.11  1996/03/28  10:53:19  wfs
81
 * Bug fixes to scan(), peephole optimisations in proc.c, and enum diagnostics.
82
 *
83
 * Revision 1.10  1996/03/08  11:52:27  wfs
84
 * Another typo in "proc.c".
85
 *
86
 * Revision 1.9  1996/03/08  11:31:14  wfs
87
 * typo in "proc.c" dynamic initialization code.
88
 *
89
 * Revision 1.8  1996/03/06  17:40:27  wfs
90
 * Corrected typo in last bug fix.
91
 *
92
 * Revision 1.7  1996/03/06  17:26:30  wfs
93
 * Fixed a bug in the profiling option.
94
 *
95
 * Revision 1.6  1996/01/30  15:36:31  wfs
96
 * Added the dynamic initialization files "dyn_begin.s" and "dyn_end.s" to
97
 * the hppatrans repository. The bl_install and bl_update scripts were
98
 * expanded to deal with these new "initcode" files.
99
 *
100
 * Revision 1.5  1996/01/19  14:13:20  wfs
101
 * Added "bool" type to an extern declaration in "frames.h".
102
 *
103
 * Revision 1.4  1996/01/11  14:46:33  wfs
104
 * Fixed bug in "ass_tag" case of scan(). Removed superfluous macro and comment.
105
 *
106
 * Revision 1.3  1995/12/19  16:52:51  wfs
107
 * Reinstated the "__main" call and a ".CODE" directive when producing gdb
108
 * diagnostic code.
109
 *
110
 * Revision 1.2  1995/12/18  13:12:18  wfs
111
 * Put hppatrans uder cvs control. Major Changes made since last release
112
 * include:
113
 * (i) PIC code generation.
114
 * (ii) Profiling.
115
 * (iii) Dynamic Initialization.
116
 * (iv) Debugging of Exception Handling and Diagnostics.
117
 *
118
 * Revision 5.5  1995/10/20  14:10:06  wfs
119
 * gcc compilation changes.
120
 *
121
 * Revision 5.4  1995/10/11  16:00:23  wfs
122
 * Moved all of the "apply_tag" stuff to "makecode.c".
123
 *
124
 * Revision 5.3  1995/10/09  10:41:02  wfs
125
 * Only one return from a procedure when producing diagnostics. White space
126
 * changes.
127
 *
128
 * Revision 5.2  1995/09/25  10:50:50  wfs
129
 * A "ghostscript" bug fix.
130
 *
131
 * Revision 5.1  1995/09/15  13:09:18  wfs
132
 * Finished the implementation of the exception token and stack limit
133
 * stuff + minor cosmetic changes.
134
 *
135
 * Revision 5.0  1995/08/25  13:42:58  wfs
136
 * Preperation for August 25 Glue release
137
 *
138
 * Revision 3.3  1995/08/25  10:21:17  wfs
139
 * A fairly major revision. A lot of the code which set up the frame
140
 * specific variables has been moved to "frames.c". 3.1 and 4.0 stuff
141
 * such as "return_to_label" and "untidy_return" have been incorporated.
142
 * Register synonyms changed. A lot of superfluous code was removed
143
 * after the register allocation stuff was changed.
144
 *
145
 * Revision 3.3  1995/08/25  10:21:17  wfs
146
 * A fairly major revision. A lot of the code which set up the frame
147
 * specific variables has been moved to "frames.c". 3.1 and 4.0 stuff
148
 * such as "return_to_label" and "untidy_return" have been incorporated.
149
 * Register synonyms changed. A lot of superfluous code was removed
150
 * after the register allocation stuff was changed.
151
 *
152
 * Revision 3.1  95/04/10  16:27:45  16:27:45  wfs (William Simmonds)
153
 * Apr95 tape version.
154
 *
155
 * Revision 3.0  95/03/30  11:18:36  11:18:36  wfs (William Simmonds)
156
 * Mar95 tape version with CRCR95_178 bug fix.
157
 *
158
 * Revision 2.0  95/03/15  15:28:27  15:28:27  wfs (William Simmonds)
159
 * spec 3.1 changes implemented, tests outstanding.
160
 *
161
 * Revision 1.3  95/02/22  11:28:47  11:28:47  wfs (William Simmonds)
162
 * Added Has_ll, changed the base register of mem_temp0 to R_FP.
163
 *
164
 * Revision 1.2  95/01/17  17:30:24  17:30:24  wfs (William Simmonds)
165
 * Changed name of an included header file.
166
 *
167
 * Revision 1.1  95/01/11  13:14:46  13:14:46  wfs (William Simmonds)
168
 * Initial revision
169
 *
170
*/
171
 
172
 
173
#define HPPATRANS_CODE
174
#include "config.h"
175
#include "myassert.h"
176
#include "addrtypes.h"
177
#include "tags.h"
178
#include "expmacs.h"
179
#include "installtypes.h"
180
#include "exp.h"
181
#include "exptypes.h"
182
#include "frames.h"
183
#include "maxminmacs.h"
184
#include "shapemacs.h"
185
#include "basicread.h"
186
#include "proctypes.h"
187
#include "eval.h"
188
#include "move.h"
189
#include "comment.h"
190
#include "getregs.h"
191
#include "guard.h"
192
#include "locate.h"
193
#include "codehere.h"
194
#include "inst_fmt.h"
195
#include "hppains.h"
196
#include "bitsmacs.h"
197
#include "labels.h"
198
#include "regexps.h"
199
#include "regmacs.h"
200
#include "regable.h"
201
#include "flags.h"
202
#include "special.h"
203
#include "translat.h"
204
#include "makecode.h"
205
#include "out.h"
206
#include "proc.h"
207
#include "misc.h"
208
#include "hppadiags.h"
209
#include "loc_signal.h"
210
 
211
#define RES    1
212
#define TO_LAB 2
213
#define UNTIDY 3
214
 
215
#define	RN(r)  reg_name(r)  /* short hand */
216
#define NA    -1
217
 
218
 
219
extern outofline *odd_bits;
220
extern int repeat_level;
221
extern regpeep regexps[64];
222
extern char *proc_name;
223
extern int line;
224
extern char export[128];
225
extern int firstlab,labno;
226
int leaf;
7 7u83 227
extern baseoff find_tg(char* s);
228
extern exp find_named_tg(char *,shape);
229
extern shape f_pointer(alignment);
230
extern alignment f_alignment(shape);
2 7u83 231
extern shape f_proc;
7 7u83 232
extern void do_exception(int);
2 7u83 233
 
234
int res_label;
235
static int untidy_return_label,return_to_label_label;
236
static bool simpleans;
237
static ans procans;
238
int RSCOPE_LEVEL,RSCOPE_LABEL;
239
 
240
/*
241
*   Temporary space on stack which can be referenced by short instruction
242
*   sequences, the space is initialised by each procedure prelude.
243
 */
244
baseoff mem_temp
7 7u83 245
(int byte_offset)
2 7u83 246
{
247
   baseoff b;
248
   b = MEM_TEMP_BOFF;
249
 
250
   /* Only 2 words of temporary memory allocated */
251
   assert(byte_offset >= 0 && byte_offset < 8);
252
 
253
   b.offset+=byte_offset;
254
   return b;
255
}
256
 
257
 
258
 
259
/* Save callee-saves ("s") registers on the stack. */
260
void save_sregs
7 7u83 261
(void)
2 7u83 262
{
263
   if (fixdump==0)
264
      return;
265
   else
266
   {
267
      int o=0,r;
7 7u83 268
      for (r=16;r<32;r++)
2 7u83 269
      {
7 7u83 270
	 if (fixdump& (1<<r))
2 7u83 271
	 {
272
	    st_ir_ins(i_stw,cmplt_,r,fs_,empty_ltrl,o,SP);
273
	    o+=4;
274
	 }
275
      }
276
   }
277
}
278
 
279
 
280
/* Restore the callee-saves ("s") registers saved on the stack. */
281
void restore_sregs
7 7u83 282
(void)
2 7u83 283
{
284
   if (fixdump==0)
285
      return;
286
   else
287
   {
288
      int o=0,r;
7 7u83 289
      for (r=16;r<32;r++)
2 7u83 290
      {
7 7u83 291
	 if (fixdump& (1<<r))
2 7u83 292
	 {
293
	    ld_ir_ins(i_ldw,cmplt_,fs_,empty_ltrl,o,SP,r);
294
	    o+=4;
295
	 }
296
      }
297
   }
298
}
299
 
300
 
301
/*
302
*   Some (more or less) common code for res_tag, return_to_label and
303
*   untidy_return.
304
 */
305
static void code_for_ret
7 7u83 306
(int which_ret)
2 7u83 307
{
308
   if (which_ret==UNTIDY)
309
      rr_ins(i_copy,SP,T2);
310
   if (Has_fp)
311
      rr_ins(i_copy,FP,SP);
312
   else
313
   {
314
      baseoff b;
7 7u83 315
      b.base= (Has_vsp ? EP : SP); b.offset=- (frame_sz>>3);
2 7u83 316
      ld_ins(i_lo,0,b,SP);
317
   }
318
   restore_sregs();
319
   if (which_ret!=TO_LAB)
320
      ld_ir_ins(i_ldw,cmplt_,fs_,empty_ltrl,-20,SP,RP);
321
   extj_reg_ins(i_bv,RP);
322
   if (which_ret==UNTIDY)
323
      rr_ins(i_copy,T2,SP);
324
   else
325
      z_ins(i_nop);
326
}
327
 
328
 
329
static void add_odd_bits
7 7u83 330
(outofline *r)
2 7u83 331
{
332
   space sp;
7 7u83 333
   if (r!= (outofline*)nilexp)
2 7u83 334
   {
335
      add_odd_bits(r->next);
7 7u83 336
      if (r->next== (outofline*)nilexp)
2 7u83 337
	 last_odd_bit=1;
338
   }
339
   else
340
      return;
341
   outlab("L$$",r->labno);
342
   sp=r->sp;
343
   clear_all();
7 7u83 344
   make_code(r->body,sp,r->dest, name(sh(r->body))!=bothd ? ptno(r->jr): res_label);
2 7u83 345
   if (name(sh(r->body))!=bothd)
346
      ub_ins(cmplt_,ptno(r->jr));
347
}
348
 
349
 
350
/*
351
 * The following functions generate code for various procedure related
352
 * constructs.  They put the result in dest using t-regs given by sp.
353
 * If non-zero, exitlab is the label of where the code is to continue.
354
 * These functions are called by make_code(), the code selection switch.
355
 */
356
 
357
 
358
/*
359
*    Procedure definition
360
 */
361
makeans make_proc_tag_code
7 7u83 362
(exp e, space sp, where dest, int exitlab)
2 7u83 363
{
364
   static int p_lab = 0;
365
   procrec *pr=&procrecs[no(e)];
366
   needs *ndpr=&pr->needsproc;
7 7u83 367
   long pprops= (long)(ndpr->propsneeds);
2 7u83 368
   makeans mka;
369
   bool is_main=STRCMP(proc_name,"main");
370
   bool save_sp;
371
 
372
   set_up_frame(e);
373
 
374
   /*
375
   *   Grab the frame size, offsets, etc. of this procedure's frame
376
    */
377
   leaf = pr->leaf;
378
   locals_space = pr->locals_space;
379
   max_args = pr->max_args;
380
   frame_sz = pr->frame_sz;
381
   callees_offset = pr->callees_offset;
382
   params_offset = pr->params_offset;
383
   locals_offset = pr->locals_offset;
384
   callee_sz = pr->callee_sz;
385
   simpleans = (pprops & long_result_bit) == 0;
386
 
7 7u83 387
   save_sp = (((Has_fp && (No_S || (Uses_crt_env && Has_vcallees)))) ||
388
	      (Uses_crt_env && (!leaf || proc_has_checkstack(e)
2 7u83 389
				       || Has_checkalloc)));
390
 
391
   if (OPTIM)
392
   {
393
      lines=BLOCK;
7 7u83 394
      pCode = (pIn*)malloc(BLOCK*sizeof(pIn));
2 7u83 395
      nLabels=4096;
7 7u83 396
      labIntro = (int*)malloc(nLabels*sizeof(int));
397
      for (line=0;line<4096;line++)
398
	 labIntro[line] =-1;
2 7u83 399
      line=0;
400
   }
401
   odd_bits = (outofline*)0;
402
   repeat_level=0;
403
 
404
   mka.lab = exitlab;
405
   mka.regmove = NOREG;
406
 
407
   assert(name(e) == proc_tag);	/* procedure definition */
408
 
7 7u83 409
   export[0] =0;
2 7u83 410
   outnl();
411
   if (is_main)
412
   {
413
      if (gcc_assembler)
414
      {
415
	 outs("\t.IMPORT\t__CTOR_LIST__,DATA\n");
416
	 outs("\t.IMPORT\t__main,CODE\n");
417
      }
418
      else
419
	 outs("\t.IMPORT\t__TDF_CTOR_LIST__,DATA\n");
420
   }
421
   if (do_profile)
422
   {
423
      outs("\t.BSS\n");
424
      outs("\t.ALIGN\t4\n");
425
      outs("G$");
426
      outn(p_lab);
427
      outs("\t.BLOCKZ\t4\n");
428
   }
429
   outs("\t.CODE\n");
430
   outs(proc_name);
431
   outnl();
432
   outs("\t.PROC\n");
433
   /*
434
   *   Output `CALLINFO' directive (c.f. pp 3-10 - 3-13 of assembly language
435
   *   reference manual)
436
    */
437
   outs("\t.CALLINFO FRAME=");
438
		  /* FRAME=frame size - frame marker bytes (if allocated) */
439
   if (gcc_assembler)
440
   {
441
      outn(frame_sz>>3);
442
   }
443
   else
444
   {
445
      outn((frame_sz>>3) - (leaf ? 0 : 8<<2));
446
   }
447
   if (save_sp)
448
      outs(",SAVE_SP");
449
   outs(",SAVE_RP,ENTRY_GR=3");
450
   if (leaf)
451
   {
452
      outc('\n');
453
   }
454
   else
455
   {
456
      outs(",CALLS\n");
457
   }
458
   outs("\t.ENTRY\n");
459
 
460
   /* store return pointer */
461
   st_ir_ins(i_stw,cmplt_,RP,fs_,empty_ltrl,-20,SP);
462
 
463
   if (fixdump != 0)
464
   {
465
      save_sregs();  /* Save the s-regs on stack. */
466
   }
467
 
468
   if (do_profile)
469
   {
470
      char g[128];
471
      baseoff b;
472
      b.base=SP;
473
      b.offset=-36;
474
      st_ins(i_sw,ARG0,b);
475
      b.offset-=4;
476
      st_ins(i_sw,ARG1,b);
477
      b.offset-=4;
478
      st_ins(i_sw,ARG2,b);
479
      b.offset-=4;
480
      st_ins(i_sw,ARG3,b);
481
      b.base=0; b.offset=0;
482
      sprintf(g,"G$%d",p_lab);
483
      set_ins(g,b,ARG2);
484
      rr_ins(i_blr,GR0,ARG1);
485
      rr_ins(i_copy,RP,ARG0);
486
      call_ins(cmplt_,"_mcount",RP,"ARGW0=GR,ARGW1=GR,ARGW2=GR");
487
      p_lab++;
488
      b.base=SP;
489
      b.offset=-36;
490
      ld_ins(i_lw,0,b,ARG0);
491
      b.offset-=4;
492
      ld_ins(i_lw,0,b,ARG1);
493
      b.offset-=4;
494
      ld_ins(i_lw,0,b,ARG2);
495
      b.offset-=4;
496
      ld_ins(i_lw,0,b,ARG3);
497
   }
498
 
499
   {
500
      /*
501
      *   Increment the Stack Pointer
502
       */
503
      int R = SP;
504
      if (proc_has_checkstack(e))
505
      {
506
	 R = T1;
507
      }
508
      else if (Has_fp)
509
      {
510
	 rr_ins(i_copy,SP,FP);
511
      }
512
      else
513
      if (save_sp)
514
      {
515
	 rr_ins(i_copy,SP,T1);
516
      }
517
      if (Has_vcallees)
518
      {
519
	 /* Add on callee_sz passed on stack by caller... */
520
	 ld_ir_ins(i_ldw,cmplt_,fs_,empty_ltrl,(16<<2),SP,GR1);
521
	 rrr_ins(i_add,c_,SP,GR1,R);
522
	 /* ...and ensure the stack pointer stays 16 word (64 byte) aligned */
7 7u83 523
	 if (SIMM14((frame_sz>>3) +63))
2 7u83 524
	 {
7 7u83 525
	    ld_ir_ins(i_ldo,cmplt_,fs_,empty_ltrl,(frame_sz>>3) +63,R,R);
2 7u83 526
	 }
527
	 else
528
	 {
7 7u83 529
	    ir_ins(i_addil,fs_L,empty_ltrl,(frame_sz>>3) +63,R);
530
	    ld_ir_ins(i_ldo,cmplt_,fs_R,empty_ltrl,(frame_sz>>3) +63,GR1,R);
2 7u83 531
	 }
532
	 riir_ins(i_dep,c_,0,31,6,R);
533
      }
534
      else
535
      {
536
	 if (SIMM14(frame_sz>>3))
537
	 {
538
	    ld_ir_ins(i_ldo,cmplt_,fs_,empty_ltrl,frame_sz>>3,SP,R);
539
	 }
540
	 else
541
	 {
542
	    ir_ins(i_addil,fs_L,empty_ltrl,frame_sz>>3,SP);
543
	    ld_ir_ins(i_ldo,cmplt_,fs_R,empty_ltrl,frame_sz>>3,GR1,R);
544
	 }
545
      }
546
   }
547
 
548
   if (save_sp && !Has_fp)
549
   {
550
      if (proc_has_checkstack(e))
551
	 st_ir_ins(i_stw,cmplt_,SP,fs_,empty_ltrl,FP_BOFF.offset,T1);
552
      else
553
	 st_ir_ins(i_stw,cmplt_,T1,fs_,empty_ltrl,FP_BOFF.offset,SP);
554
   }
555
 
556
   if (proc_has_checkstack(e))
557
   {
558
      baseoff b;
559
      exp stl = find_named_tg("__TDFstacklim",
560
			      f_pointer(f_alignment(f_proc)));
561
      setvar(stl);
562
      b = boff(stl);
563
      stackerr_lab = new_label();
564
      ld_ins(i_lw,1,b,GR1);
565
      cj_ins(c_g,T1,GR1,stackerr_lab);
566
      if (Has_fp)
567
	 rr_ins(i_copy,SP,FP);
568
      rr_ins(i_copy,T1,SP);
569
   }
570
 
571
   if (PIC_code)
572
   {
573
      st_ir_ins(i_stw,cmplt_,GR19,fs_,empty_ltrl,-32,SP);
574
      if (!leaf && !is_main)
575
      {
576
	 rr_ins(i_copy,GR19,GR5);
577
      }
578
   }
579
 
580
   if (is_main)
581
   {
582
      int n = new_label();
583
      int end = new_label();
584
      baseoff b;
7 7u83 585
      b.base = 0; b.offset = (gcc_assembler ? 0 : 4);
2 7u83 586
      set_ins((gcc_assembler ? "__CTOR_LIST__" : "__TDF_CTOR_LIST__"),b,GR4);
587
      b.base = GR4;
588
      b.offset = 4;
589
      if (gcc_assembler)
590
      {
591
	 ld_ins(i_lwm,1,b,GR5);
592
	 cj_ins(c_eq,GR0,GR5,end);
593
	 rrr_ins(i_sh2add,c_,GR5,GR4,GR5);
594
	 outlab("L$$",n);
595
	 ld_ins(i_lwm,1,b,GR22);
7 7u83 596
	 call_millicode(MILLI_DYNCALL, RP, "",0);
2 7u83 597
	 cj_ins(c_l,GR4,GR5,n);
598
	 outlab("L$$",end);
599
	 if (is_PIC_and_calls)
600
	    ld_ir_ins(i_ldw,cmplt_,fs_,empty_ltrl,-32,SP,GR5);
601
	 call_ins(cmplt_,"__main",RP,"");
602
      }
603
      else
604
      {
605
	 ld_ins(i_lwm,1,b,GR22);
606
	 cj_ins(c_eq,GR0,GR22,end);
607
	 outlab("L$$",n);
7 7u83 608
	 call_millicode(MILLI_DYNCALL, RP, "",0);
2 7u83 609
	 ld_ins(i_lwm,1,b,GR22);
610
	 cj_ins(c_neq,GR0,GR22,n);
611
	 outlab("L$$",end);
612
      }
613
   }
614
 
615
   if (Has_vsp)
616
      rr_ins(i_copy,SP,EP);
617
   if (Has_tos)
618
      st_ins(i_sw,SP,SP_BOFF);
7 7u83 619
   if ((Has_fp && (No_S || (Uses_crt_env && Has_vcallees))))
2 7u83 620
      st_ins(i_sw,FP,FP_BOFF);
621
 
622
   if (!simpleans)
623
   {
624
      /* structure or union result */
625
      instore is;
626
      /* where to find address of result */
627
      is.adval = 0;
628
      is.b = LONG_RESULT_BOFF;
629
      setinsalt(procans,is);
630
      st_ins(i_sw,RET0,is.b);
631
   }
7 7u83 632
   else if ((pprops & realresult_bit)!= 0)
2 7u83 633
   {
634
      /* real result */
635
      freg frg;
636
      frg.fr = R_FR4;
7 7u83 637
      frg.dble = (pprops & longrealresult_bit)? 1 : 0;
2 7u83 638
      setfregalt(procans,frg);
639
   }
7 7u83 640
   else if ((pprops & has_result_bit)!= 0)
2 7u83 641
   {
642
      /* fixed register result */
643
      setregalt(procans,RET0);
644
   }
645
   else
646
   {
647
      /* no result */
648
      setregalt(procans,GR0);
649
   }
650
 
651
  clear_all();
652
  RSCOPE_LEVEL = 0;
653
  res_label = 0;
654
  untidy_return_label = 0;
655
  return_to_label_label = 0;
656
  last_odd_bit = 0;
657
  doing_odd_bits = 0;
658
 
659
  code_here(son(e),sp,nowhere);	/* Code body of procedure. */
660
 
661
  if (stackerr_lab!=0)
662
  {
663
     outlab("L$$",stackerr_lab);
664
     do_exception(SIGUSR1);
665
  }
666
  if (aritherr_lab!=0)
667
  {
668
     outlab("L$$",aritherr_lab);
669
     do_exception(SIGFPE);
670
  }
671
 
672
  doing_odd_bits = 1;
673
  while (odd_bits != (outofline*)0)
674
  {
675
     outofline *ol = odd_bits;
676
     odd_bits = (outofline*)0;
677
     last_odd_bit=0;
678
     add_odd_bits(ol);
679
  }
680
 
681
  if (xdb)
682
  {
683
     outlab("L$$",res_label);
684
     code_for_ret(RES);
685
  }
686
 
687
 
688
  if (OPTIM)
689
  {
690
     /*
691
     *   Jump and "peephole" optimisations
692
      */
693
     int i,j;
694
     char *hit;
695
     FILE_POSN Pos;
696
     GET_FILE_POSN(outf,Pos);
7 7u83 697
     hit = (char*)malloc((nLabels+8)*sizeof(char));
698
     for (i=0;i<line;i++)
2 7u83 699
     {
700
	char s[65];
701
	int lab,to=0,jump;
7 7u83 702
	lab=pCode[i] ->lab;
2 7u83 703
	if (lab==res_label && lab>0)
704
	   to=labIntro[lab-firstlab];
705
	else
7 7u83 706
	if (lab>NA && lab != res_label && pCode[i] ->ins != i_lab)
2 7u83 707
	{
708
	   for (j=0;j<nLabels+8;j++)
7 7u83 709
	       hit[j] =0;
2 7u83 710
	   to=labIntro[lab-firstlab];
7 7u83 711
	   while (to+1<line && lab!=res_label && pCode[to+1] ->lab>NA
712
			   && pCode[to+1] ->ins==i_ub && hit[lab-firstlab] ==0)
2 7u83 713
	   {
7 7u83 714
	      hit[lab-firstlab] =1;
715
	      lab=pCode[to+1] ->lab;
2 7u83 716
	      to=labIntro[lab-firstlab];
717
	   }
718
	}
7 7u83 719
	if (pCode[i] ->ins==i_bb)
2 7u83 720
	{
7 7u83 721
	   jump = i-to;
2 7u83 722
	   if (SIMM11(jump*4))
723
	   {
724
	      ins_p cc;
725
	      int a,b;
7 7u83 726
	      cc=pCode[i] ->cc;
727
	      SET_FILE_POSN(outf,(pCode[i] ->fpos));
728
	      a=pCode[i] ->op[0];
729
	      b=pCode[i] ->op[1];
2 7u83 730
	      IGNORE sprintf(s,"\tbb%s,N\t%s,%d,L$$%d\n\tnop",cc,RN(a),b,lab);
7 7u83 731
	      j= (int)strlen(s);
732
	      for (;j<63;j++)
733
		 s[j] =' ';
734
	      s[63] =0;
2 7u83 735
	      fprintf(outf,"%s\n",s);
736
	   }
737
	   else
738
	   {
739
	      ins_p cc;
740
	      int a,b;
7 7u83 741
	      if (pCode[i] ->cc==bit_is_0)
2 7u83 742
		 cc=c_OD;
743
	      else
744
		 cc=c_EV;
7 7u83 745
	      SET_FILE_POSN(outf,(pCode[i] ->fpos));
746
	      a=pCode[i] ->op[0];
747
	      b=pCode[i] ->op[1];
2 7u83 748
	      IGNORE sprintf(s,"\textru%s\t%s,%d,1,0\n\tb\tL$$%d\n\tnop",cc,RN(a),b,lab);
7 7u83 749
	      j= (int)strlen(s);
750
	      for (;j<63;j++)
751
		 s[j] =' ';
752
	      s[63] =0;
2 7u83 753
	      fprintf(outf,"%s\n",s);
754
	   }
755
	}
756
	else
7 7u83 757
	if (pCode[i] ->ins==i_ub)
2 7u83 758
	{
7 7u83 759
	   jump = i-to;
760
	   SET_FILE_POSN(outf,(pCode[i] ->fpos));
2 7u83 761
#if 0
762
	   if (SIMM19(jump*4))
763
	   {
764
#endif
765
	      IGNORE sprintf(s,"\tb\tL$$%d\n\tnop",lab);
7 7u83 766
	      j= (int)strlen(s);
767
	      for (;j<63;j++)
768
		 s[j] =' ';
769
	      s[63] ='\n';
770
	      s[64] =0;
2 7u83 771
	      fprintf(outf,"%s",s);
772
#if 0
773
	   }
774
	   else
775
	   {
776
	   }
777
#endif
778
	}
779
	else
7 7u83 780
	if (pCode[i] ->ins==i_cj || pCode[i] ->ins==i_cij)
2 7u83 781
	{
7 7u83 782
	   jump = i-to;
2 7u83 783
	   if (SIMM11(jump*4))
784
	   {
785
	      ins_p cc;
786
	      int a,b;
7 7u83 787
	      cc=pCode[i] ->cc;
788
	      SET_FILE_POSN(outf,(pCode[i] ->fpos));
789
	      a=pCode[i] ->op[0];
790
	      b=pCode[i] ->op[1];
2 7u83 791
	      if (jump<0 && line>i)
792
	      {
7 7u83 793
	      if (pCode[i] ->ins==i_cj)
2 7u83 794
		 IGNORE sprintf(s,"\tcomb%s,N\t%s,%s,L$$%d\n",cc,RN(a),RN(b),lab);
795
	      else
796
		 IGNORE sprintf(s,"\tcomib%s,N\t%d,%s,L$$%d\n",cc,a,RN(b),lab);
797
	      }
798
	      else
799
	      {
7 7u83 800
	      if (pCode[i] ->ins==i_cj)
2 7u83 801
		 IGNORE sprintf(s,"\tcomb%s,N\t%s,%s,L$$%d\n\tnop",cc,RN(a),RN(b),lab);
802
	      else
803
		 IGNORE sprintf(s,"\tcomib%s,N\t%d,%s,L$$%d\n\tnop",cc,a,RN(b),lab);
804
	      }
7 7u83 805
	      j= (int)strlen(s);
806
	      for (;j<63;j++)
807
		 s[j] =' ';
808
	      s[63] =0;
2 7u83 809
	      fprintf(outf,"%s\n",s);
810
	   }
811
	   else
812
#if 0
813
	   if (SIMM19(jump*4))
814
#endif
815
	   {
816
	      ins_p cc;
817
	      int a,b;
7 7u83 818
	      cc=opp(pCode[i] ->cc);
819
	      SET_FILE_POSN(outf,(pCode[i] ->fpos));
820
	      a=pCode[i] ->op[0];
821
	      b=pCode[i] ->op[1];
822
	      if (pCode[i] ->ins==i_cj)
2 7u83 823
		 IGNORE sprintf(s,"\tcomclr%s\t%s,%s,0\n\tb\tL$$%d\n\tnop",cc,RN(a),RN(b),lab);
824
	      else
825
		 IGNORE sprintf(s,"\tcomiclr%s\t%d,%s,0\n\tb\tL$$%d\n\tnop",cc,a,RN(b),lab);
7 7u83 826
	      j= (int)strlen(s);
827
	      for (;j<63;j++)
828
		 s[j] =' ';
829
	      s[63] =0;
2 7u83 830
	      fprintf(outf,"%s\n",s);
831
	   }
832
#if 0
833
	   else
834
	   {
835
	      ins_p cc;
836
	      int a,b;
7 7u83 837
	      cc=pCode[i] ->cc;
838
	      SET_FILE_POSN(outf,(pCode[i] ->fpos));
839
	      a=pCode[i] ->op[0];
840
	      b=pCode[i] ->op[1];
841
	      if (pCode[i] ->ins==i_cj)
2 7u83 842
		 IGNORE sprintf(s,"\tcomb%s,N\t%s,%s,.+16\n\tnop\n\tLB\tL$$%d\n",cc,RN(a),RN(b),lab);
843
	      else
844
		 IGNORE sprintf(s,"\tcomib%s,N\t%d,%s,.+16\n\tnop\n\tLB\tL$$%d\n",cc,a,RN(b),lab);
7 7u83 845
	      j= (int)strlen(s);
846
	      for (;j<63;j++)
847
		 s[j] =' ';
848
	      s[63] =0;
2 7u83 849
	      fprintf(outf,"%s\n",s);
850
	   }
851
#endif
852
	}
853
     }
854
     SET_FILE_POSN(outf,Pos);
855
     free(hit);
856
  }
857
 
858
 
859
 
860
{
861
   int i;
7 7u83 862
   for (i=0;i<line;i++)
2 7u83 863
   {
864
      pIn j=pCode[line];
865
      free(j);
866
   }
867
   free(pCode);
868
   free(labIntro);
869
}
870
 
871
 
872
   outs("\t.EXIT\n");
873
   clear_all();  /* for next proc */
874
   return mka;
875
}
876
 
877
 
878
/*
879
*   res_tag, return_to_label or untidy_return
880
 */
881
 
882
makeans make_res_tag_code
7 7u83 883
(exp e, space sp, where dest, int exitlab)
2 7u83 884
{
885
   makeans mka;
886
   int nm,*ret_label;
887
   mka.lab = exitlab;
888
   mka.regmove = NOREG;
7 7u83 889
   if (name(e) ==res_tag)
2 7u83 890
   {
891
      nm=RES;
892
      ret_label=&res_label;
893
   }
894
   else
7 7u83 895
   if (name(e) ==return_to_label_tag)
2 7u83 896
   {
897
      nm=TO_LAB;
898
      ret_label=&return_to_label_label;
899
   }
900
   else
901
   {
902
      nm=UNTIDY;
903
      ret_label=&untidy_return_label;
904
   }
905
   if (nm!=TO_LAB)  /* don't evaluate result if returning to label */
906
   {
907
      where w;
908
      bool cmpd;
909
      w.answhere = procans;
910
      w.ashwhere = ashof(sh(son(e)));
911
      cmpd = (w.ashwhere.ashsize<65 && !simpleans);
912
      if (cmpd)
913
      {
914
	 /*
915
	 *   The HP_PA RISC convention states that compound results of 64
916
	*    bits are to be returned in the registers RET0 and RET1. We put
917
	*    the result into the stack space LONG_RESULT_BOFF and then load
918
	 *   into the registers.
919
	  */
920
	w.answhere.val.instoreans.adval=1;
921
      }
922
      code_here(son(e),sp,w); /*  Get the result  */
923
      if (cmpd)
924
      {
925
	 instore is;
926
	 baseoff b;
927
	 is=procans.val.instoreans;
928
	 b = is.b;
929
	 ld_ins(i_lw,SIGNED,b,RET0);
930
	 b.offset+=4;
931
	 ld_ins(i_lw,SIGNED,b,RET1);
932
      }
933
   }
934
   if (RSCOPE_LEVEL==0)
935
   {
936
      if (nm==TO_LAB)
937
	 reg_operand_here(son(e),sp,RP);
938
      if (*ret_label==0)
939
      {
940
	 /*
941
	 *    Must be the first res_tag, the first return_to_label, or the
942
	 *    first untidy_return encountered in this procedure - label
943
	  *   and output relevant code sequence
944
	   */
945
	 *ret_label = new_label();
946
	 if (xdb)
947
	 {
948
	    ub_ins(cmplt_,*ret_label);
949
	 }
950
	 else
951
	 {
952
	    outlab("L$$",*ret_label);
953
	    code_for_ret(nm);
954
	 }
955
      }
956
      else
957
      if (xdb || fixdump)
958
	 ub_ins(cmplt_,*ret_label);
959
      else
960
	 code_for_ret(nm);  /*
961
			    *   A very short return sequence - output code
962
			    *   each time thus avoiding a jump to *ret_label
963
			     */
964
   }
965
   else
966
   {
967
      /* inlined result */
968
      if (RSCOPE_LABEL == 0)
969
	 RSCOPE_LABEL = new_label();
970
      if (RSCOPE_LABEL != exitlab)
971
	 ub_ins(cmplt_,RSCOPE_LABEL);
972
   }
973
 
974
   clear_all();	  /* regs invalid after return. (Not needed for inlining?) */
975
 
976
   return mka;
977
}
978
 
979
 
980