|
|
1.1 root 1: /* Convert RTL to assembler code and output it, for GNU compiler.
2: Copyright (C) 1987, 1988, 1989, 1992 Free Software Foundation, Inc.
3:
4: This file is part of GNU CC.
5:
6: GNU CC is free software; you can redistribute it and/or modify
7: it under the terms of the GNU General Public License as published by
8: the Free Software Foundation; either version 2, or (at your option)
9: any later version.
10:
11: GNU CC is distributed in the hope that it will be useful,
12: but WITHOUT ANY WARRANTY; without even the implied warranty of
13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14: GNU General Public License for more details.
15:
16: You should have received a copy of the GNU General Public License
17: along with GNU CC; see the file COPYING. If not, write to
18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19:
20:
21: /* This is the final pass of the compiler.
22: It looks at the rtl code for a function and outputs assembler code.
23:
24: Call `final_start_function' to output the assembler code for function entry,
25: `final' to output assembler code for some RTL code,
26: `final_end_function' to output assembler code for function exit.
27: If a function is compiled in several pieces, each piece is
28: output separately with `final'.
29:
30: Some optimizations are also done at this level.
31: Move instructions that were made unnecessary by good register allocation
32: are detected and omitted from the output. (Though most of these
33: are removed by the last jump pass.)
34:
35: Instructions to set the condition codes are omitted when it can be
36: seen that the condition codes already had the desired values.
37:
38: In some cases it is sufficient if the inherited condition codes
39: have related values, but this may require the following insn
40: (the one that tests the condition codes) to be modified.
41:
42: The code for the function prologue and epilogue are generated
43: directly as assembler code by the macros FUNCTION_PROLOGUE and
44: FUNCTION_EPILOGUE. Those instructions never exist as rtl. */
45:
46: #include <stdio.h>
47: #include "config.h"
48: #include "gvarargs.h"
49: #include "rtl.h"
50: #include "regs.h"
51: #include "insn-config.h"
52: #include "insn-attr.h"
53: #include "insn-codes.h"
54: #include "recog.h"
55: #include "conditions.h"
56: #include "flags.h"
57: #include "real.h"
58: #include "output.h"
59: #include "hard-reg-set.h"
60:
61: #ifndef ASM_STABD_OP
62: #define ASM_STABD_OP ".stabd"
63: #endif
64:
65: /* Get N_SLINE and N_SOL from stab.h if we can expect the file to exist. */
66: #ifdef DBX_DEBUGGING_INFO
67: #ifdef USG
68: #include "gstab.h" /* If doing DBX on sysV, use our own stab.h. */
69: #else
70: #include <stab.h> /* On BSD, use the system's stab.h. */
71: #endif /* not USG */
72: #endif /* DBX_DEBUGGING_INFO */
73:
74: /* .stabd code for line number. */
75: #ifndef N_SLINE
76: #define N_SLINE 0x44
77: #endif
78:
79: /* .stabs code for included file name. */
80: #ifndef N_SOL
81: #define N_SOL 0x84
82: #endif
83:
84: #ifndef INT_TYPE_SIZE
85: #define INT_TYPE_SIZE BITS_PER_WORD
86: #endif
87:
88: /* If we aren't using cc0, CC_STATUS_INIT shouldn't exist. So define a
89: null default for it to save conditionalization later. */
90: #ifndef CC_STATUS_INIT
91: #define CC_STATUS_INIT
92: #endif
93:
94: /* How to start an assembler comment. */
95: #ifndef ASM_COMMENT_START
96: #define ASM_COMMENT_START ";#"
97: #endif
98:
99: rtx peephole ();
100: void output_asm_insn ();
101: rtx alter_subreg ();
102: static int alter_cond ();
103: void output_asm_label ();
104: static void output_operand ();
105: void output_address ();
106: void output_addr_const ();
107: static void output_source_line ();
108: rtx final_scan_insn ();
109: void profile_function ();
110:
111: #ifdef HAVE_ATTR_length
112: static int asm_insn_count ();
113: #endif
114:
115: /* Nonzero means this function is a leaf function, with no function calls.
116: This variable exists to be examined in FUNCTION_PROLOGUE
117: and FUNCTION_EPILOGUE. Always zero, unless set by some action. */
118: int leaf_function;
119:
120: int leaf_function_p ();
121:
122: #ifdef LEAF_REGISTERS
123: int only_leaf_regs_used ();
124: static void leaf_renumber_regs ();
125: void leaf_renumber_regs_insn ();
126: #endif
127:
128: /* Last insn processed by final_scan_insn. */
129: static rtx debug_insn = 0;
130:
131: /* Line number of last NOTE. */
132: static int last_linenum;
133:
134: /* Number of basic blocks seen so far;
135: used if profile_block_flag is set. */
136: static int count_basic_blocks;
137:
138: /* Nonzero while outputting an `asm' with operands.
139: This means that inconsistencies are the user's fault, so don't abort.
140: The precise value is the insn being output, to pass to error_for_asm. */
141: static rtx this_is_asm_operands;
142:
143: /* Number of operands of this insn, for an `asm' with operands. */
144: static int insn_noperands;
145:
146: /* Compare optimization flag. */
147:
148: static rtx last_ignored_compare = 0;
149:
150: /* Flag indicating this insn is the start of a new basic block. */
151:
152: static int new_block = 1;
153:
154: /* All the symbol-blocks (levels of scoping) in the compilation
155: are assigned sequence numbers in order of appearance of the
156: beginnings of the symbol-blocks. Both final and dbxout do this,
157: and assume that they will both give the same number to each block.
158: Final uses these sequence numbers to generate assembler label names
159: LBBnnn and LBEnnn for the beginning and end of the symbol-block.
160: Dbxout uses the sequence nunbers to generate references to the same labels
161: from the dbx debugging information.
162:
163: Sdb records this level at the beginning of each function,
164: in order to find the current level when recursing down declarations.
165: It outputs the block beginning and endings
166: at the point in the asm file where the blocks would begin and end. */
167:
168: int next_block_index;
169:
170: /* Assign a unique number to each insn that is output.
171: This can be used to generate unique local labels. */
172:
173: static int insn_counter = 0;
174:
175: #ifdef HAVE_cc0
176: /* This variable contains machine-dependent flags (defined in tm.h)
177: set and examined by output routines
178: that describe how to interpret the condition codes properly. */
179:
180: CC_STATUS cc_status;
181:
182: /* During output of an insn, this contains a copy of cc_status
183: from before the insn. */
184:
185: CC_STATUS cc_prev_status;
186: #endif
187:
188: /* Indexed by hardware reg number, is 1 if that register is ever
189: used in the current function.
190:
191: In life_analysis, or in stupid_life_analysis, this is set
192: up to record the hard regs used explicitly. Reload adds
193: in the hard regs used for holding pseudo regs. Final uses
194: it to generate the code in the function prologue and epilogue
195: to save and restore registers as needed. */
196:
197: char regs_ever_live[FIRST_PSEUDO_REGISTER];
198:
199: /* Nonzero means current function must be given a frame pointer.
200: Set in stmt.c if anything is allocated on the stack there.
201: Set in reload1.c if anything is allocated on the stack there. */
202:
203: int frame_pointer_needed;
204:
205: /* Assign unique numbers to labels generated for profiling. */
206:
207: int profile_label_no;
208:
209: /* Length so far allocated in PENDING_BLOCKS. */
210:
211: static int max_block_depth;
212:
213: /* Stack of sequence numbers of symbol-blocks of which we have seen the
214: beginning but not yet the end. Sequence numbers are assigned at
215: the beginning; this stack allows us to find the sequence number
216: of a block that is ending. */
217:
218: static int *pending_blocks;
219:
220: /* Number of elements currently in use in PENDING_BLOCKS. */
221:
222: static int block_depth;
223:
224: /* Nonzero if have enabled APP processing of our assembler output. */
225:
226: static int app_on;
227:
228: /* If we are outputting an insn sequence, this contains the sequence rtx.
229: Zero otherwise. */
230:
231: rtx final_sequence;
232:
233: /* Indexed by line number, nonzero if there is a note for that line. */
234:
235: static char *line_note_exists;
236:
237: /* Initialize data in final at the beginning of a compilation. */
238:
239: void
240: init_final (filename)
241: char *filename;
242: {
243: next_block_index = 2;
244: app_on = 0;
245: max_block_depth = 20;
246: pending_blocks = (int *) xmalloc (20 * sizeof *pending_blocks);
247: final_sequence = 0;
248: }
249:
250: /* Called at end of source file,
251: to output the block-profiling table for this entire compilation. */
252:
253: void
254: end_final (filename)
255: char *filename;
256: {
257: int i;
258:
259: if (profile_block_flag)
260: {
261: char name[12];
262:
263: data_section ();
264:
265: /* Output the main header, of 6 words:
266: 0: 1 if this file's initialized, else 0.
267: 1: address of file name.
268: 2: address of table of counts.
269: 4: number of counts in the table.
270: 5: always 0, for compatibility with Sun.
271: 6: extra word added by GNU: address of address table
272: which contains addresses of basic blocks,
273: in parallel with the table of counts. */
274: ASM_OUTPUT_ALIGN (asm_out_file,
275: exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
276:
277: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 0);
278: assemble_integer (const0_rtx, UNITS_PER_WORD, 1);
279: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 1);
280: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1);
281: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2);
282: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1);
283: assemble_integer (gen_rtx (CONST_INT, VOIDmode, count_basic_blocks),
284: UNITS_PER_WORD, 1);
285: assemble_integer (const0_rtx, UNITS_PER_WORD, 1);
286: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 3);
287: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1);
288:
289: /* Output the file name. */
290: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 1);
291: {
292: int len = strlen (filename);
293: char *data_file = (char *) alloca (len + 3);
294: strcpy (data_file, filename);
295: strip_off_ending (data_file, len);
296: strcat (data_file, ".d");
297: assemble_string (data_file, strlen (data_file) + 1);
298: }
299:
300: /* Realign data section. */
301: ASM_OUTPUT_ALIGN (asm_out_file,
302: exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
303:
304: /* Make space for the table of counts. */
305: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 2);
306: assemble_zeros (INT_TYPE_SIZE / BITS_PER_UNIT * count_basic_blocks);
307:
308: /* Output the table of addresses. */
309: readonly_data_section ();
310: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 3);
311: for (i = 0; i < count_basic_blocks; i++)
312: {
313: char name[12];
314: ASM_GENERATE_INTERNAL_LABEL (name, "LPB", i);
315: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name),
316: UNITS_PER_WORD, 1);
317: }
318:
319: /* End with the address of the table of addresses,
320: so we can find it easily, as the last word in the file's text. */
321: ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 3);
322: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1);
323: }
324: }
325:
326: /* Enable APP processing of subsequent output.
327: Used before the output from an `asm' statement. */
328:
329: void
330: app_enable ()
331: {
332: if (! app_on)
333: {
334: fprintf (asm_out_file, ASM_APP_ON);
335: app_on = 1;
336: }
337: }
338:
339: /* Enable APP processing of subsequent output.
340: Called from varasm.c before most kinds of output. */
341:
342: void
343: app_disable ()
344: {
345: if (app_on)
346: {
347: fprintf (asm_out_file, ASM_APP_OFF);
348: app_on = 0;
349: }
350: }
351:
352: /* Return the number of slots filled in the current
353: delayed branch sequence (we don't count the insn needing the
354: delay slot). Zero if not in a delayed branch sequence. */
355:
356: #ifdef DELAY_SLOTS
357: int
358: dbr_sequence_length ()
359: {
360: if (final_sequence != 0)
361: return XVECLEN (final_sequence, 0) - 1;
362: else
363: return 0;
364: }
365: #endif
366:
367: /* The next two pages contain routines used to compute the length of an insn
368: and to shorten branches. */
369:
370: /* Arrays for insn lengths, and addresses. The latter is referenced by
371: `insn_current_length'. */
372:
373: static short *insn_lengths;
374: int *insn_addresses;
375:
376: /* Address of insn being processed. Used by `insn_current_length'. */
377: int insn_current_address;
378:
379: /* Indicate the branch shortening hasn't yet been done. */
380:
381: void
382: init_insn_lengths ()
383: {
384: insn_lengths = 0;
385: }
386:
387: /* Obtain the current length of an insn. If branch shortening has been done,
388: get its actual length. Otherwise, get its maximum length. */
389:
390: int
391: get_attr_length (insn)
392: rtx insn;
393: {
394: #ifdef HAVE_ATTR_length
395: rtx body;
396: int i;
397: int length = 0;
398:
399: if (insn_lengths)
400: return insn_lengths[INSN_UID (insn)];
401: else
402: switch (GET_CODE (insn))
403: {
404: case NOTE:
405: case BARRIER:
406: case CODE_LABEL:
407: return 0;
408:
409: case CALL_INSN:
410: length = insn_default_length (insn);
411: break;
412:
413: case JUMP_INSN:
414: body = PATTERN (insn);
415: if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC)
416: {
417: /* This only takes room if jump tables go into the text section. */
418: #if !defined(READONLY_DATA_SECTION) || defined(JUMP_TABLES_IN_TEXT_SECTION)
419: length = (XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC)
420: * GET_MODE_SIZE (GET_MODE (body)));
421:
422: /* Be pessimistic and assume worst-case alignment. */
423: length += (GET_MODE_SIZE (GET_MODE (body)) - 1);
424: #else
425: return 0;
426: #endif
427: }
428: else
429: length = insn_default_length (insn);
430: break;
431:
432: case INSN:
433: body = PATTERN (insn);
434: if (GET_CODE (body) == USE || GET_CODE (body) == CLOBBER)
435: return 0;
436:
437: else if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0)
438: length = asm_insn_count (insn) * insn_default_length (insn);
439: else if (GET_CODE (body) == SEQUENCE)
440: for (i = 0; i < XVECLEN (body, 0); i++)
441: length += get_attr_length (XVECEXP (body, 0, i));
442: else
443: length = insn_default_length (insn);
444: }
445:
446: #ifdef ADJUST_INSN_LENGTH
447: ADJUST_INSN_LENGTH (insn, length);
448: #endif
449: return length;
450: #else /* not HAVE_ATTR_length */
451: return 0;
452: #endif /* not HAVE_ATTR_length */
453: }
454:
455: /* Make a pass over all insns and compute their actual lengths by shortening
456: any branches of variable length if possible. */
457:
458: /* Give a default value for the lowest address in a function. */
459:
460: #ifndef FIRST_INSN_ADDRESS
461: #define FIRST_INSN_ADDRESS 0
462: #endif
463:
464: void
465: shorten_branches (first)
466: rtx first;
467: {
468: #ifdef HAVE_ATTR_length
469: rtx insn;
470: int something_changed = 1;
471: int max_uid = 0;
472: char *varying_length;
473: rtx body;
474: int uid;
475:
476: /* Compute maximum UID and allocate arrays. */
477: for (insn = first; insn; insn = NEXT_INSN (insn))
478: if (INSN_UID (insn) > max_uid)
479: max_uid = INSN_UID (insn);
480:
481: max_uid++;
482: insn_lengths = (short *) oballoc (max_uid * sizeof (short));
483: insn_addresses = (int *) oballoc (max_uid * sizeof (int));
484: varying_length = (char *) oballoc (max_uid * sizeof (char));
485:
486: /* Compute initial lengths, addresses, and varying flags for each insn. */
487: for (insn_current_address = FIRST_INSN_ADDRESS, insn = first;
488: insn != 0;
489: insn_current_address += insn_lengths[uid], insn = NEXT_INSN (insn))
490: {
491: uid = INSN_UID (insn);
492: insn_addresses[uid] = insn_current_address;
493: insn_lengths[uid] = 0;
494: varying_length[uid] = 0;
495:
496: if (GET_CODE (insn) == NOTE || GET_CODE (insn) == BARRIER
497: || GET_CODE (insn) == CODE_LABEL)
498: continue;
499:
500: body = PATTERN (insn);
501: if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC)
502: {
503: /* This only takes room if read-only data goes into the text
504: section. */
505: #if !defined(READONLY_DATA_SECTION) || defined(JUMP_TABLES_IN_TEXT_SECTION)
506: int unitsize = GET_MODE_SIZE (GET_MODE (body));
507:
508: insn_lengths[uid] = (XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC)
509: * GET_MODE_SIZE (GET_MODE (body)));
510:
511: /* Account for possible alignment. */
512: insn_lengths[uid]
513: += unitsize - (insn_current_address & (unitsize - 1));
514: #else
515: ;
516: #endif
517: }
518: else if (asm_noperands (body) >= 0)
519: insn_lengths[uid] = asm_insn_count (body) * insn_default_length (insn);
520: else if (GET_CODE (body) == SEQUENCE)
521: {
522: int i;
523:
524: /* Inside a delay slot sequence, we do not do any branch shortening
525: (on the only machine known to have both variable-length branches
526: and delay slots, the ROMP, branch-with-execute is the same size
527: as the maximum branch anyway). So we only have to handle normal
528: insns (actually, reorg never puts ASM insns in a delay slot, but
529: we don't take advantage of that knowlege here). */
530: for (i = 0; i < XVECLEN (body, 0); i++)
531: {
532: rtx inner_insn = XVECEXP (body, 0, i);
533: int inner_uid = INSN_UID (inner_insn);
534: int inner_length;
535:
536: if (asm_noperands (PATTERN (XVECEXP (body, 0, i))) >= 0)
537: inner_length = (asm_insn_count (PATTERN (inner_insn))
538: * insn_default_length (inner_insn));
539: else
540: inner_length = insn_default_length (inner_insn);
541:
542: insn_lengths[inner_uid] = inner_length;
543: varying_length[inner_uid] = 0;
544: insn_lengths[uid] += inner_length;
545: }
546: }
547: else if (GET_CODE (body) != USE && GET_CODE (body) != CLOBBER)
548: {
549: insn_lengths[uid] = insn_default_length (insn);
550: varying_length[uid] = insn_variable_length_p (insn);
551: }
552:
553: /* If needed, do any adjustment. */
554: #ifdef ADJUST_INSN_LENGTH
555: ADJUST_INSN_LENGTH (insn, insn_lengths[uid]);
556: #endif
557: }
558:
559: /* Now loop over all the insns finding varying length insns. For each,
560: get the current insn length. If it has changed, reflect the change.
561: When nothing changes for a full pass, we are done. */
562:
563: while (something_changed)
564: {
565: something_changed = 0;
566: for (insn_current_address = FIRST_INSN_ADDRESS, insn = first;
567: insn != 0;
568: insn_current_address += insn_lengths[uid], insn = NEXT_INSN (insn))
569: {
570: int new_length;
571:
572: uid = INSN_UID (insn);
573: insn_addresses[uid] = insn_current_address;
574: if (! varying_length[uid])
575: continue;
576:
577: new_length = insn_current_length (insn);
578: if (new_length != insn_lengths[uid])
579: {
580: insn_lengths[uid] = new_length;
581: something_changed = 1;
582: }
583: }
584: }
585: #endif /* HAVE_ATTR_length */
586: }
587:
588: #ifdef HAVE_ATTR_length
589: /* Given the body of an INSN known to be generated by an ASM statement, return
590: the number of machine instructions likely to be generated for this insn.
591: This is used to compute its length. */
592:
593: static int
594: asm_insn_count (body)
595: rtx body;
596: {
597: char *template;
598: int count = 1;
599:
600: for (template = decode_asm_operands (body, 0, 0, 0, 0);
601: *template; template++)
602: if (*template == ';' || *template == '\n')
603: count++;
604:
605: return count;
606: }
607: #endif
608:
609: /* Output assembler code for the start of a function,
610: and initialize some of the variables in this file
611: for the new function. The label for the function and associated
612: assembler pseudo-ops have already been output in `assemble_start_function'.
613:
614: FIRST is the first insn of the rtl for the function being compiled.
615: FILE is the file to write assembler code to.
616: OPTIMIZE is nonzero if we should eliminate redundant
617: test and compare insns. */
618:
619: void
620: final_start_function (first, file, optimize)
621: rtx first;
622: FILE *file;
623: int optimize;
624: {
625: block_depth = 0;
626:
627: this_is_asm_operands = 0;
628:
629: #ifdef NON_SAVING_SETJMP
630: /* A function that calls setjmp should save and restore all the
631: call-saved registers on a system where longjmp clobbers them. */
632: if (NON_SAVING_SETJMP && current_function_calls_setjmp)
633: {
634: int i;
635:
636: for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
637: if (!call_used_regs[i] && !call_fixed_regs[i])
638: regs_ever_live[i] = 1;
639: }
640: #endif
641:
642: /* Initial line number is supposed to be output
643: before the function's prologue and label
644: so that the function's address will not appear to be
645: in the last statement of the preceding function. */
646: if (NOTE_LINE_NUMBER (first) != NOTE_INSN_DELETED)
647: {
648: if (write_symbols == SDB_DEBUG)
649: /* For sdb, let's not, but say we did.
650: We need to set last_linenum for sdbout_function_begin,
651: but we can't have an actual line number before the .bf symbol.
652: (sdb_begin_function_line is not set,
653: and other compilers don't do it.) */
654: last_linenum = NOTE_LINE_NUMBER (first);
655: else
656: output_source_line (file, first);
657: }
658:
659: #ifdef LEAF_REG_REMAP
660: if (leaf_function)
661: leaf_renumber_regs (first);
662: #endif
663:
664: /* The Sun386i and perhaps other machines don't work right
665: if the profiling code comes after the prologue. */
666: #ifdef PROFILE_BEFORE_PROLOGUE
667: if (profile_flag)
668: profile_function (file);
669: #endif /* PROFILE_BEFORE_PROLOGUE */
670:
671: #ifdef FUNCTION_PROLOGUE
672: /* First output the function prologue: code to set up the stack frame. */
673: FUNCTION_PROLOGUE (file, get_frame_size ());
674: #endif
675:
676: #ifdef SDB_DEBUGGING_INFO
677: if (write_symbols == SDB_DEBUG)
678: next_block_index = 1;
679: #endif
680:
681: #ifdef FUNCTION_BLOCK_PROFILER
682: if (profile_block_flag)
683: {
684: FUNCTION_BLOCK_PROFILER (file, profile_label_no);
685: }
686: #endif /* FUNCTION_BLOCK_PROFILER */
687:
688: #ifndef PROFILE_BEFORE_PROLOGUE
689: if (profile_flag)
690: profile_function (file);
691: #endif /* not PROFILE_BEFORE_PROLOGUE */
692:
693: profile_label_no++;
694: }
695:
696: void
697: profile_function (file)
698: FILE *file;
699: {
700: int align = MIN (BIGGEST_ALIGNMENT, INT_TYPE_SIZE);
701: int sval = current_function_returns_struct;
702: int cxt = current_function_needs_context;
703:
704: data_section ();
705: ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));
706: ASM_OUTPUT_INTERNAL_LABEL (file, "LP", profile_label_no);
707: assemble_integer (const0_rtx, UNITS_PER_WORD, 1);
708:
709: text_section ();
710:
711: #ifdef STRUCT_VALUE_INCOMING_REGNUM
712: if (sval)
713: ASM_OUTPUT_REG_PUSH (file, STRUCT_VALUE_INCOMING_REGNUM);
714: #else
715: #ifdef STRUCT_VALUE_REGNUM
716: if (sval)
717: ASM_OUTPUT_REG_PUSH (file, STRUCT_VALUE_REGNUM);
718: #endif
719: #endif
720:
721: #if 0
722: #ifdef STATIC_CHAIN_INCOMING_REGNUM
723: if (cxt)
724: ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_INCOMING_REGNUM);
725: #else
726: #ifdef STATIC_CHAIN_REGNUM
727: if (cxt)
728: ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_REGNUM);
729: #endif
730: #endif
731: #endif /* 0 */
732:
733: FUNCTION_PROFILER (file, profile_label_no);
734:
735: #if 0
736: #ifdef STATIC_CHAIN_INCOMING_REGNUM
737: if (cxt)
738: ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_INCOMING_REGNUM);
739: #else
740: #ifdef STATIC_CHAIN_REGNUM
741: if (cxt)
742: ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_REGNUM);
743: #endif
744: #endif
745: #endif /* 0 */
746:
747: #ifdef STRUCT_VALUE_INCOMING_REGNUM
748: if (sval)
749: ASM_OUTPUT_REG_POP (file, STRUCT_VALUE_INCOMING_REGNUM);
750: #else
751: #ifdef STRUCT_VALUE_REGNUM
752: if (sval)
753: ASM_OUTPUT_REG_POP (file, STRUCT_VALUE_REGNUM);
754: #endif
755: #endif
756: }
757:
758: /* Output assembler code for the end of a function.
759: For clarity, args are same as those of `final_start_function'
760: even though not all of them are needed. */
761:
762: void
763: final_end_function (first, file, optimize)
764: rtx first;
765: FILE *file;
766: int optimize;
767: {
768: if (app_on)
769: {
770: fprintf (file, ASM_APP_OFF);
771: app_on = 0;
772: }
773:
774: #ifdef SDB_DEBUGGING_INFO
775: if (write_symbols == SDB_DEBUG)
776: sdbout_end_function (last_linenum);
777: #endif
778:
779: #ifdef FUNCTION_EPILOGUE
780: /* Finally, output the function epilogue:
781: code to restore the stack frame and return to the caller. */
782: FUNCTION_EPILOGUE (file, get_frame_size ());
783: #endif
784:
785: #ifdef SDB_DEBUGGING_INFO
786: if (write_symbols == SDB_DEBUG)
787: sdbout_end_epilogue ();
788: #endif
789:
790: #ifdef DWARF_DEBUGGING_INFO
791: if (write_symbols == DWARF_DEBUG)
792: dwarfout_end_epilogue ();
793: #endif
794:
795: /* If FUNCTION_EPILOGUE is not defined, then the function body
796: itself contains return instructions wherever needed. */
797: }
798:
799: /* Output assembler code for some insns: all or part of a function.
800: For description of args, see `final_start_function', above.
801:
802: PRESCAN is 1 if we are not really outputting,
803: just scanning as if we were outputting.
804: Prescanning deletes and rearranges insns just like ordinary output.
805: PRESCAN is -2 if we are outputting after having prescanned.
806: In this case, don't try to delete or rearrange insns
807: because that has already been done.
808: Prescanning is done only on certain machines. */
809:
810: void
811: final (first, file, optimize, prescan)
812: rtx first;
813: FILE *file;
814: int optimize;
815: int prescan;
816: {
817: register rtx insn;
818: int max_line = 0;
819:
820: last_ignored_compare = 0;
821: new_block = 1;
822:
823: /* Make a map indicating which line numbers appear in this function. */
824: for (insn = first; insn; insn = NEXT_INSN (insn))
825: if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > max_line)
826: max_line = NOTE_LINE_NUMBER (insn);
827:
828: line_note_exists = (char *) oballoc (max_line + 1);
829: bzero (line_note_exists, max_line + 1);
830:
831: for (insn = first; insn; insn = NEXT_INSN (insn))
832: if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > 0)
833: line_note_exists[NOTE_LINE_NUMBER (insn)] = 1;
834:
835: init_recog ();
836:
837: CC_STATUS_INIT;
838:
839: /* Output the insns. */
840: for (insn = NEXT_INSN (first); insn;)
841: insn = final_scan_insn (insn, file, optimize, prescan, 0);
842:
843: /* Do basic-block profiling here
844: if the last insn was a conditional branch. */
845: if (profile_block_flag && new_block)
846: {
847: new_block = 0;
848: /* Enable the table of basic-block use counts
849: to point at the code it applies to. */
850: ASM_OUTPUT_INTERNAL_LABEL (file, "LPB", count_basic_blocks);
851: /* Before first insn of this basic block, increment the
852: count of times it was entered. */
853: #ifdef BLOCK_PROFILER
854: BLOCK_PROFILER (file, count_basic_blocks);
855: CC_STATUS_INIT;
856: #endif
857: count_basic_blocks++;
858: }
859: }
860:
861: /* The final scan for one insn, INSN.
862: Args are same as in `final', except that INSN
863: is the insn being scanned.
864: Value returned is the next insn to be scanned.
865:
866: NOPEEPHOLES is the flag to disallow peephole processing (currently
867: used for within delayed branch sequence output). */
868:
869: rtx
870: final_scan_insn (insn, file, optimize, prescan, nopeepholes)
871: rtx insn;
872: FILE *file;
873: int optimize;
874: int prescan;
875: int nopeepholes;
876: {
877: register int i;
878: insn_counter++;
879:
880: /* Ignore deleted insns. These can occur when we split insns (due to a
881: template of "#") while not optimizing. */
882: if (INSN_DELETED_P (insn))
883: return NEXT_INSN (insn);
884:
885: switch (GET_CODE (insn))
886: {
887: case NOTE:
888: if (prescan > 0)
889: break;
890:
891: /* Align the beginning of a loop, for higher speed
892: on certain machines. */
893:
894: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG && optimize > 0)
895: {
896: #ifdef ASM_OUTPUT_LOOP_ALIGN
897: rtx next = next_nonnote_insn (insn);
898: if (next && GET_CODE (next) == CODE_LABEL)
899: {
900: ASM_OUTPUT_LOOP_ALIGN (asm_out_file);
901: }
902: #endif
903: break;
904: }
905: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
906: break;
907:
908: if (write_symbols == NO_DEBUG)
909: break;
910: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG)
911: {
912: #ifdef SDB_DEBUGGING_INFO
913: if (write_symbols == SDB_DEBUG)
914: sdbout_begin_function (last_linenum);
915: #endif
916: break;
917: }
918: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED)
919: break; /* An insn that was "deleted" */
920: if (app_on)
921: {
922: fprintf (file, ASM_APP_OFF);
923: app_on = 0;
924: }
925: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG
926: && (debug_info_level == DINFO_LEVEL_NORMAL
927: || debug_info_level == DINFO_LEVEL_VERBOSE))
928: {
929: /* Beginning of a symbol-block. Assign it a sequence number
930: and push the number onto the stack PENDING_BLOCKS. */
931:
932: if (block_depth == max_block_depth)
933: {
934: /* PENDING_BLOCKS is full; make it longer. */
935: max_block_depth *= 2;
936: pending_blocks
937: = (int *) xrealloc (pending_blocks,
938: max_block_depth * sizeof (int));
939: }
940: pending_blocks[block_depth++] = next_block_index;
941:
942: /* Output debugging info about the symbol-block beginning. */
943:
944: #ifdef SDB_DEBUGGING_INFO
945: if (write_symbols == SDB_DEBUG)
946: sdbout_begin_block (file, last_linenum, next_block_index);
947: #endif
948: #ifdef DBX_DEBUGGING_INFO
949: if (write_symbols == DBX_DEBUG)
950: ASM_OUTPUT_INTERNAL_LABEL (file, "LBB", next_block_index);
951: #endif
952: #ifdef DWARF_DEBUGGING_INFO
953: if (write_symbols == DWARF_DEBUG && block_depth > 1)
954: dwarfout_begin_block (next_block_index);
955: #endif
956:
957: next_block_index++;
958: }
959: else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END
960: && (debug_info_level == DINFO_LEVEL_NORMAL
961: || debug_info_level == DINFO_LEVEL_VERBOSE))
962: {
963: /* End of a symbol-block. Pop its sequence number off
964: PENDING_BLOCKS and output debugging info based on that. */
965:
966: --block_depth;
967:
968: #ifdef DBX_DEBUGGING_INFO
969: if (write_symbols == DBX_DEBUG && block_depth >= 0)
970: ASM_OUTPUT_INTERNAL_LABEL (file, "LBE",
971: pending_blocks[block_depth]);
972: #endif
973: #ifdef SDB_DEBUGGING_INFO
974: if (write_symbols == SDB_DEBUG && block_depth >= 0)
975: sdbout_end_block (file, last_linenum);
976: #endif
977: #ifdef DWARF_DEBUGGING_INFO
978: if (write_symbols == DWARF_DEBUG && block_depth >= 1)
979: dwarfout_end_block (pending_blocks[block_depth]);
980: #endif
981: }
982: else if (NOTE_LINE_NUMBER (insn) > 0)
983: /* This note is a line-number. */
984: {
985: register rtx note;
986:
987: #if 0 /* This is what we used to do. */
988: output_source_line (file, insn);
989: #endif
990: int note_after = 0;
991:
992: /* If there is anything real after this note,
993: output it. If another line note follows, omit this one. */
994: for (note = NEXT_INSN (insn); note; note = NEXT_INSN (note))
995: {
996: if (GET_CODE (note) != NOTE && GET_CODE (note) != CODE_LABEL)
997: break;
998: else if (GET_CODE (note) == NOTE && NOTE_LINE_NUMBER (note) > 0)
999: {
1000: /* Another note follows; we can delete this note provided
1001: no intervening line numbers have notes elsewhere. */
1002: int num;
1003: for (num = NOTE_LINE_NUMBER (insn) + 1;
1004: num < NOTE_LINE_NUMBER (note);
1005: num++)
1006: if (line_note_exists[num])
1007: break;
1008:
1009: if (num == NOTE_LINE_NUMBER (note))
1010: note_after = 1;
1011: break;
1012: }
1013: }
1014:
1015: /* Output this line note
1016: if it is the first or the last line note in a row. */
1017: if (!note_after)
1018: output_source_line (file, insn);
1019: }
1020: break;
1021:
1022: case BARRIER:
1023: #ifdef ASM_OUTPUT_ALIGN_CODE
1024: ASM_OUTPUT_ALIGN_CODE (file);
1025: #endif
1026: break;
1027:
1028: case CODE_LABEL:
1029: CC_STATUS_INIT;
1030: if (prescan > 0)
1031: break;
1032: new_block = 1;
1033: #ifdef SDB_DEBUGGING_INFO
1034: if (write_symbols == SDB_DEBUG && LABEL_NAME (insn))
1035: sdbout_label (insn);
1036: #endif
1037: #ifdef DWARF_DEBUGGING_INFO
1038: if (write_symbols == DWARF_DEBUG && LABEL_NAME (insn))
1039: dwarfout_label (insn);
1040: #endif
1041: if (app_on)
1042: {
1043: fprintf (file, ASM_APP_OFF);
1044: app_on = 0;
1045: }
1046: if (NEXT_INSN (insn) != 0
1047: && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN)
1048: {
1049: rtx nextbody = PATTERN (NEXT_INSN (insn));
1050:
1051: /* If this label is followed by a jump-table,
1052: make sure we put the label in the read-only section. Also
1053: possibly write the label and jump table together. */
1054:
1055: if (GET_CODE (nextbody) == ADDR_VEC
1056: || GET_CODE (nextbody) == ADDR_DIFF_VEC)
1057: {
1058: #ifndef JUMP_TABLES_IN_TEXT_SECTION
1059: readonly_data_section ();
1060: #else
1061: text_section ();
1062: #endif
1063: #ifdef ASM_OUTPUT_CASE_LABEL
1064: ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn),
1065: NEXT_INSN (insn));
1066: #else
1067: ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn));
1068: #endif
1069: break;
1070: }
1071: }
1072:
1073: ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn));
1074: break;
1075:
1076: default:
1077: {
1078: register rtx body = PATTERN (insn);
1079: int insn_code_number;
1080: char *template;
1081: rtx note;
1082:
1083: /* An INSN, JUMP_INSN or CALL_INSN.
1084: First check for special kinds that recog doesn't recognize. */
1085:
1086: if (GET_CODE (body) == USE /* These are just declarations */
1087: || GET_CODE (body) == CLOBBER)
1088: break;
1089:
1090: #ifdef HAVE_cc0
1091: /* If there is a REG_CC_SETTER note on this insn, it means that
1092: the setting of the condition code was done in the delay slot
1093: of the insn that branched here. So recover the cc status
1094: from the insn that set it. */
1095:
1096: note = find_reg_note (insn, REG_CC_SETTER, 0);
1097: if (note)
1098: {
1099: NOTICE_UPDATE_CC (PATTERN (XEXP (note, 0)), XEXP (note, 0));
1100: cc_prev_status = cc_status;
1101: }
1102: #endif
1103:
1104: /* Detect insns that are really jump-tables
1105: and output them as such. */
1106:
1107: if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC)
1108: {
1109: register int vlen, idx;
1110:
1111: if (prescan > 0)
1112: break;
1113:
1114: if (app_on)
1115: {
1116: fprintf (file, ASM_APP_OFF);
1117: app_on = 0;
1118: }
1119:
1120: vlen = XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC);
1121: for (idx = 0; idx < vlen; idx++)
1122: {
1123: if (GET_CODE (body) == ADDR_VEC)
1124: ASM_OUTPUT_ADDR_VEC_ELT
1125: (file, CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 0, idx), 0)));
1126: else
1127: ASM_OUTPUT_ADDR_DIFF_ELT
1128: (file,
1129: CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 1, idx), 0)),
1130: CODE_LABEL_NUMBER (XEXP (XEXP (body, 0), 0)));
1131: }
1132: #ifdef ASM_OUTPUT_CASE_END
1133: ASM_OUTPUT_CASE_END (file,
1134: CODE_LABEL_NUMBER (PREV_INSN (insn)),
1135: insn);
1136: #endif
1137:
1138: text_section ();
1139:
1140: break;
1141: }
1142:
1143: /* Do basic-block profiling when we reach a new block.
1144: Done here to avoid jump tables. */
1145: if (profile_block_flag && new_block)
1146: {
1147: new_block = 0;
1148: /* Enable the table of basic-block use counts
1149: to point at the code it applies to. */
1150: ASM_OUTPUT_INTERNAL_LABEL (file, "LPB", count_basic_blocks);
1151: /* Before first insn of this basic block, increment the
1152: count of times it was entered. */
1153: #ifdef BLOCK_PROFILER
1154: BLOCK_PROFILER (file, count_basic_blocks);
1155: CC_STATUS_INIT;
1156: #endif
1157: count_basic_blocks++;
1158: }
1159:
1160: if (GET_CODE (body) == ASM_INPUT)
1161: {
1162: /* There's no telling what that did to the condition codes. */
1163: CC_STATUS_INIT;
1164: if (prescan > 0)
1165: break;
1166: if (! app_on)
1167: {
1168: fprintf (file, ASM_APP_ON);
1169: app_on = 1;
1170: }
1171: fprintf (asm_out_file, "\t%s\n", XSTR (body, 0));
1172: break;
1173: }
1174:
1175: /* Detect `asm' construct with operands. */
1176: if (asm_noperands (body) >= 0)
1177: {
1178: int noperands = asm_noperands (body);
1179: rtx *ops;
1180: char *string;
1181:
1182: /* There's no telling what that did to the condition codes. */
1183: CC_STATUS_INIT;
1184: if (prescan > 0)
1185: break;
1186:
1187: /* alloca won't do here, since only return from `final'
1188: would free it. */
1189: if (noperands > 0)
1190: ops = (rtx *) xmalloc (noperands * sizeof (rtx));
1191:
1192: if (! app_on)
1193: {
1194: fprintf (file, ASM_APP_ON);
1195: app_on = 1;
1196: }
1197:
1198: /* Get out the operand values. */
1199: string = decode_asm_operands (body, ops, 0, 0, 0);
1200: /* Inhibit aborts on what would otherwise be compiler bugs. */
1201: insn_noperands = noperands;
1202: this_is_asm_operands = insn;
1203: /* Output the insn using them. */
1204: output_asm_insn (string, ops);
1205: this_is_asm_operands = 0;
1206: if (noperands > 0)
1207: free (ops);
1208: break;
1209: }
1210:
1211: if (prescan <= 0 && app_on)
1212: {
1213: fprintf (file, ASM_APP_OFF);
1214: app_on = 0;
1215: }
1216:
1217: if (GET_CODE (body) == SEQUENCE)
1218: {
1219: /* A delayed-branch sequence */
1220: register int i;
1221: rtx next;
1222:
1223: if (prescan > 0)
1224: break;
1225: final_sequence = body;
1226:
1227: /* The first insn in this SEQUENCE might be a JUMP_INSN that will
1228: force the restoration of a comparison that was previously
1229: thought unnecessary. If that happens, cancel this sequence
1230: and cause that insn to be restored. */
1231:
1232: next = final_scan_insn (XVECEXP (body, 0, 0), file, 0, prescan, 1);
1233: if (next != XVECEXP (body, 0, 1))
1234: {
1235: final_sequence = 0;
1236: return next;
1237: }
1238:
1239: for (i = 1; i < XVECLEN (body, 0); i++)
1240: final_scan_insn (XVECEXP (body, 0, i), file, 0, prescan, 1);
1241: #ifdef DBR_OUTPUT_SEQEND
1242: DBR_OUTPUT_SEQEND (file);
1243: #endif
1244: final_sequence = 0;
1245:
1246: /* If the insn requiring the delay slot was a CALL_INSN, the
1247: insns in the delay slot are actually executed before the
1248: called function. Hence we don't preserve any CC-setting
1249: actions in these insns and the CC must be marked as being
1250: clobbered by the function. */
1251: if (GET_CODE (XVECEXP (body, 0, 0)) == CALL_INSN)
1252: CC_STATUS_INIT;
1253: break;
1254: }
1255:
1256: /* We have a real machine instruction as rtl. */
1257:
1258: body = PATTERN (insn);
1259:
1260: #ifdef HAVE_cc0
1261: /* Check for redundant test and compare instructions
1262: (when the condition codes are already set up as desired).
1263: This is done only when optimizing; if not optimizing,
1264: it should be possible for the user to alter a variable
1265: with the debugger in between statements
1266: and the next statement should reexamine the variable
1267: to compute the condition codes. */
1268:
1269: if (optimize
1270: && GET_CODE (body) == SET
1271: && GET_CODE (SET_DEST (body)) == CC0
1272: && insn != last_ignored_compare)
1273: {
1274: if (GET_CODE (SET_SRC (body)) == SUBREG)
1275: SET_SRC (body) = alter_subreg (SET_SRC (body));
1276: else if (GET_CODE (SET_SRC (body)) == COMPARE)
1277: {
1278: if (GET_CODE (XEXP (SET_SRC (body), 0)) == SUBREG)
1279: XEXP (SET_SRC (body), 0)
1280: = alter_subreg (XEXP (SET_SRC (body), 0));
1281: if (GET_CODE (XEXP (SET_SRC (body), 1)) == SUBREG)
1282: XEXP (SET_SRC (body), 1)
1283: = alter_subreg (XEXP (SET_SRC (body), 1));
1284: }
1285: if ((cc_status.value1 != 0
1286: && rtx_equal_p (SET_SRC (body), cc_status.value1))
1287: || (cc_status.value2 != 0
1288: && rtx_equal_p (SET_SRC (body), cc_status.value2)))
1289: {
1290: /* Don't delete insn if it has an addressing side-effect. */
1291: if (! FIND_REG_INC_NOTE (insn, 0)
1292: /* or if anything in it is volatile. */
1293: && ! volatile_refs_p (PATTERN (insn)))
1294: {
1295: /* We don't really delete the insn; just ignore it. */
1296: last_ignored_compare = insn;
1297: break;
1298: }
1299: }
1300: }
1301: #endif
1302:
1303: /* Following a conditional branch, we have a new basic block. */
1304: if ((GET_CODE (insn) == JUMP_INSN && GET_CODE (body) == SET
1305: && GET_CODE (SET_SRC (body)) != LABEL_REF)
1306: || (GET_CODE (insn) == JUMP_INSN && GET_CODE (body) == PARALLEL
1307: && GET_CODE (XVECEXP (body, 0, 0)) == SET
1308: && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) != LABEL_REF))
1309: new_block = 1;
1310:
1311: #ifndef STACK_REGS
1312: /* Don't bother outputting obvious no-ops, even without -O.
1313: This optimization is fast and doesn't interfere with debugging.
1314: Don't do this if the insn is in a delay slot, since this
1315: will cause an improper number of delay insns to be written. */
1316: if (final_sequence == 0
1317: && prescan >= 0
1318: && GET_CODE (insn) == INSN && GET_CODE (body) == SET
1319: && GET_CODE (SET_SRC (body)) == REG
1320: && GET_CODE (SET_DEST (body)) == REG
1321: && REGNO (SET_SRC (body)) == REGNO (SET_DEST (body)))
1322: break;
1323: #endif
1324:
1325: #ifdef HAVE_cc0
1326: /* If this is a conditional branch, maybe modify it
1327: if the cc's are in a nonstandard state
1328: so that it accomplishes the same thing that it would
1329: do straightforwardly if the cc's were set up normally. */
1330:
1331: if (cc_status.flags != 0
1332: && GET_CODE (insn) == JUMP_INSN
1333: && GET_CODE (body) == SET
1334: && SET_DEST (body) == pc_rtx
1335: && GET_CODE (SET_SRC (body)) == IF_THEN_ELSE
1336: /* This is done during prescan; it is not done again
1337: in final scan when prescan has been done. */
1338: && prescan >= 0)
1339: {
1340: /* This function may alter the contents of its argument
1341: and clear some of the cc_status.flags bits.
1342: It may also return 1 meaning condition now always true
1343: or -1 meaning condition now always false
1344: or 2 meaning condition nontrivial but altered. */
1345: register int result = alter_cond (XEXP (SET_SRC (body), 0));
1346: /* If condition now has fixed value, replace the IF_THEN_ELSE
1347: with its then-operand or its else-operand. */
1348: if (result == 1)
1349: SET_SRC (body) = XEXP (SET_SRC (body), 1);
1350: if (result == -1)
1351: SET_SRC (body) = XEXP (SET_SRC (body), 2);
1352:
1353: /* The jump is now either unconditional or a no-op.
1354: If it has become a no-op, don't try to output it.
1355: (It would not be recognized.) */
1356: if (SET_SRC (body) == pc_rtx)
1357: {
1358: PUT_CODE (insn, NOTE);
1359: NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
1360: NOTE_SOURCE_FILE (insn) = 0;
1361: break;
1362: }
1363: else if (GET_CODE (SET_SRC (body)) == RETURN)
1364: /* Replace (set (pc) (return)) with (return). */
1365: PATTERN (insn) = body = SET_SRC (body);
1366:
1367: /* Rerecognize the instruction if it has changed. */
1368: if (result != 0)
1369: INSN_CODE (insn) = -1;
1370: }
1371:
1372: /* Make same adjustments to instructions that examine the
1373: condition codes without jumping (if this machine has them). */
1374:
1375: if (cc_status.flags != 0
1376: && GET_CODE (body) == SET)
1377: {
1378: switch (GET_CODE (SET_SRC (body)))
1379: {
1380: case GTU:
1381: case GT:
1382: case LTU:
1383: case LT:
1384: case GEU:
1385: case GE:
1386: case LEU:
1387: case LE:
1388: case EQ:
1389: case NE:
1390: {
1391: register int result;
1392: if (XEXP (SET_SRC (body), 0) != cc0_rtx)
1393: break;
1394: result = alter_cond (SET_SRC (body));
1395: if (result == 1)
1396: validate_change (insn, &SET_SRC (body), const_true_rtx, 0);
1397: else if (result == -1)
1398: validate_change (insn, &SET_SRC (body), const0_rtx, 0);
1399: else if (result == 2)
1400: INSN_CODE (insn) = -1;
1401: }
1402: }
1403: }
1404: #endif
1405:
1406: /* Do machine-specific peephole optimizations if desired. */
1407:
1408: if (optimize && !flag_no_peephole && !nopeepholes)
1409: {
1410: rtx next = peephole (insn);
1411: /* When peepholing, if there were notes within the peephole,
1412: emit them before the peephole. */
1413: if (next != 0 && next != NEXT_INSN (insn))
1414: {
1415: rtx prev = PREV_INSN (insn);
1416: rtx note;
1417:
1418: for (note = NEXT_INSN (insn); note != next;
1419: note = NEXT_INSN (note))
1420: final_scan_insn (note, file, optimize, prescan, nopeepholes);
1421:
1422: /* In case this is prescan, put the notes
1423: in proper position for later rescan. */
1424: note = NEXT_INSN (insn);
1425: PREV_INSN (note) = prev;
1426: NEXT_INSN (prev) = note;
1427: NEXT_INSN (PREV_INSN (next)) = insn;
1428: PREV_INSN (insn) = PREV_INSN (next);
1429: NEXT_INSN (insn) = next;
1430: PREV_INSN (next) = insn;
1431: }
1432:
1433: /* PEEPHOLE might have changed this. */
1434: body = PATTERN (insn);
1435: }
1436:
1437: /* Try to recognize the instruction.
1438: If successful, verify that the operands satisfy the
1439: constraints for the instruction. Crash if they don't,
1440: since `reload' should have changed them so that they do. */
1441:
1442: insn_code_number = recog_memoized (insn);
1443: insn_extract (insn);
1444: for (i = 0; i < insn_n_operands[insn_code_number]; i++)
1445: {
1446: if (GET_CODE (recog_operand[i]) == SUBREG)
1447: recog_operand[i] = alter_subreg (recog_operand[i]);
1448: }
1449:
1450: #ifdef REGISTER_CONSTRAINTS
1451: if (! constrain_operands (insn_code_number, 1))
1452: fatal_insn_not_found (insn);
1453: #endif
1454:
1455: /* Some target machines need to prescan each insn before
1456: it is output. */
1457:
1458: #ifdef FINAL_PRESCAN_INSN
1459: FINAL_PRESCAN_INSN (insn, recog_operand,
1460: insn_n_operands[insn_code_number]);
1461: #endif
1462:
1463: #ifdef HAVE_cc0
1464: cc_prev_status = cc_status;
1465:
1466: /* Update `cc_status' for this instruction.
1467: The instruction's output routine may change it further.
1468: If the output routine for a jump insn needs to depend
1469: on the cc status, it should look at cc_prev_status. */
1470:
1471: NOTICE_UPDATE_CC (body, insn);
1472: #endif
1473:
1474: debug_insn = insn;
1475:
1476: /* If the proper template needs to be chosen by some C code,
1477: run that code and get the real template. */
1478:
1479: template = insn_template[insn_code_number];
1480: if (template == 0)
1481: {
1482: template = (*insn_outfun[insn_code_number]) (recog_operand, insn);
1483:
1484: /* If the C code returns 0, it means that it is a jump insn
1485: which follows a deleted test insn, and that test insn
1486: needs to be reinserted. */
1487: if (template == 0)
1488: {
1489: if (prev_nonnote_insn (insn) != last_ignored_compare)
1490: abort ();
1491: new_block = 0;
1492: return prev_nonnote_insn (insn);
1493: }
1494: }
1495:
1496: /* If the template is the string "#", it means that this insn must
1497: be split. */
1498: if (template[0] == '#' && template[1] == '\0')
1499: {
1500: rtx new = try_split (body, insn, 0);
1501:
1502: /* If we didn't split the insn, go away. */
1503: if (new == insn && PATTERN (new) == body)
1504: abort ();
1505:
1506: new_block = 0;
1507: return new;
1508: }
1509:
1510: if (prescan > 0)
1511: break;
1512:
1513: /* Output assembler code from the template. */
1514:
1515: output_asm_insn (template, recog_operand);
1516:
1517: #if 0
1518: /* It's not at all clear why we did this and doing so interferes
1519: with tests we'd like to do to use REG_WAS_0 notes, so let's try
1520: with this out. */
1521:
1522: /* Mark this insn as having been output. */
1523: INSN_DELETED_P (insn) = 1;
1524: #endif
1525:
1526: debug_insn = 0;
1527: }
1528: }
1529: return NEXT_INSN (insn);
1530: }
1531:
1532: /* Output debugging info to the assembler file FILE
1533: based on the NOTE-insn INSN, assumed to be a line number. */
1534:
1535: static void
1536: output_source_line (file, insn)
1537: FILE *file;
1538: rtx insn;
1539: {
1540: char ltext_label_name[100];
1541: register char *filename = NOTE_SOURCE_FILE (insn);
1542:
1543: last_linenum = NOTE_LINE_NUMBER (insn);
1544:
1545: if (write_symbols != NO_DEBUG)
1546: {
1547: #ifdef SDB_DEBUGGING_INFO
1548: if (write_symbols == SDB_DEBUG
1549: #if 0 /* People like having line numbers even in wrong file! */
1550: /* COFF can't handle multiple source files--lose, lose. */
1551: && !strcmp (filename, main_input_filename)
1552: #endif
1553: /* COFF relative line numbers must be positive. */
1554: && last_linenum > sdb_begin_function_line)
1555: {
1556: #ifdef ASM_OUTPUT_SOURCE_LINE
1557: ASM_OUTPUT_SOURCE_LINE (file, last_linenum);
1558: #else
1559: fprintf (file, "\t.ln\t%d\n",
1560: ((sdb_begin_function_line > -1)
1561: ? last_linenum - sdb_begin_function_line : 1));
1562: #endif
1563: }
1564: #endif
1565:
1566: #ifdef DBX_DEBUGGING_INFO
1567: if (write_symbols == DBX_DEBUG)
1568: {
1569: dbxout_source_file (file, filename);
1570:
1571: #ifdef ASM_OUTPUT_SOURCE_LINE
1572: ASM_OUTPUT_SOURCE_LINE (file, NOTE_LINE_NUMBER (insn));
1573: #else
1574: fprintf (file, "\t%s %d,0,%d\n", ASM_STABD_OP,
1575: N_SLINE, NOTE_LINE_NUMBER (insn));
1576: #endif
1577: }
1578: #endif /* DBX_DEBUGGING_INFO */
1579:
1580: #ifdef DWARF_DEBUGGING_INFO
1581: if (write_symbols == DWARF_DEBUG)
1582: dwarfout_line (filename, NOTE_LINE_NUMBER (insn));
1583: #endif
1584: }
1585: }
1586:
1587: /* If X is a SUBREG, replace it with a REG or a MEM,
1588: based on the thing it is a subreg of. */
1589:
1590: rtx
1591: alter_subreg (x)
1592: register rtx x;
1593: {
1594: register rtx y = SUBREG_REG (x);
1595: if (GET_CODE (y) == SUBREG)
1596: y = alter_subreg (y);
1597:
1598: if (GET_CODE (y) == REG)
1599: {
1600: /* If the containing reg really gets a hard reg, so do we. */
1601: PUT_CODE (x, REG);
1602: REGNO (x) = REGNO (y) + SUBREG_WORD (x);
1603: }
1604: else if (GET_CODE (y) == MEM)
1605: {
1606: register int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
1607: #if BYTES_BIG_ENDIAN
1608: offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x)))
1609: - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (y))));
1610: #endif
1611: PUT_CODE (x, MEM);
1612: MEM_VOLATILE_P (x) = MEM_VOLATILE_P (y);
1613: XEXP (x, 0) = plus_constant (XEXP (y, 0), offset);
1614: }
1615:
1616: return x;
1617: }
1618:
1619: /* Do alter_subreg on all the SUBREGs contained in X. */
1620:
1621: static rtx
1622: walk_alter_subreg (x)
1623: rtx x;
1624: {
1625: switch (GET_CODE (x))
1626: {
1627: case PLUS:
1628: case MULT:
1629: XEXP (x, 0) = walk_alter_subreg (XEXP (x, 0));
1630: XEXP (x, 1) = walk_alter_subreg (XEXP (x, 1));
1631: break;
1632:
1633: case MEM:
1634: XEXP (x, 0) = walk_alter_subreg (XEXP (x, 0));
1635: break;
1636:
1637: case SUBREG:
1638: return alter_subreg (x);
1639: }
1640:
1641: return x;
1642: }
1643:
1644: #ifdef HAVE_cc0
1645:
1646: /* Given BODY, the body of a jump instruction, alter the jump condition
1647: as required by the bits that are set in cc_status.flags.
1648: Not all of the bits there can be handled at this level in all cases.
1649:
1650: The value is normally 0.
1651: 1 means that the condition has become always true.
1652: -1 means that the condition has become always false.
1653: 2 means that COND has been altered. */
1654:
1655: static int
1656: alter_cond (cond)
1657: register rtx cond;
1658: {
1659: int value = 0;
1660:
1661: if (cc_status.flags & CC_REVERSED)
1662: {
1663: value = 2;
1664: PUT_CODE (cond, swap_condition (GET_CODE (cond)));
1665: }
1666:
1667: if (cc_status.flags & CC_INVERTED)
1668: {
1669: value = 2;
1670: PUT_CODE (cond, reverse_condition (GET_CODE (cond)));
1671: }
1672:
1673: if (cc_status.flags & CC_NOT_POSITIVE)
1674: switch (GET_CODE (cond))
1675: {
1676: case LE:
1677: case LEU:
1678: case GEU:
1679: /* Jump becomes unconditional. */
1680: return 1;
1681:
1682: case GT:
1683: case GTU:
1684: case LTU:
1685: /* Jump becomes no-op. */
1686: return -1;
1687:
1688: case GE:
1689: PUT_CODE (cond, EQ);
1690: value = 2;
1691: break;
1692:
1693: case LT:
1694: PUT_CODE (cond, NE);
1695: value = 2;
1696: break;
1697: }
1698:
1699: if (cc_status.flags & CC_NOT_NEGATIVE)
1700: switch (GET_CODE (cond))
1701: {
1702: case GE:
1703: case GEU:
1704: /* Jump becomes unconditional. */
1705: return 1;
1706:
1707: case LT:
1708: case LTU:
1709: /* Jump becomes no-op. */
1710: return -1;
1711:
1712: case LE:
1713: case LEU:
1714: PUT_CODE (cond, EQ);
1715: value = 2;
1716: break;
1717:
1718: case GT:
1719: case GTU:
1720: PUT_CODE (cond, NE);
1721: value = 2;
1722: break;
1723: }
1724:
1725: if (cc_status.flags & CC_NO_OVERFLOW)
1726: switch (GET_CODE (cond))
1727: {
1728: case GEU:
1729: /* Jump becomes unconditional. */
1730: return 1;
1731:
1732: case LEU:
1733: PUT_CODE (cond, EQ);
1734: value = 2;
1735: break;
1736:
1737: case GTU:
1738: PUT_CODE (cond, NE);
1739: value = 2;
1740: break;
1741:
1742: case LTU:
1743: /* Jump becomes no-op. */
1744: return -1;
1745: }
1746:
1747: if (cc_status.flags & (CC_Z_IN_NOT_N | CC_Z_IN_N))
1748: switch (GET_CODE (cond))
1749: {
1750: case LE:
1751: case LEU:
1752: case GE:
1753: case GEU:
1754: case LT:
1755: case LTU:
1756: case GT:
1757: case GTU:
1758: abort ();
1759:
1760: case NE:
1761: PUT_CODE (cond, cc_status.flags & CC_Z_IN_N ? GE : LT);
1762: value = 2;
1763: break;
1764:
1765: case EQ:
1766: PUT_CODE (cond, cc_status.flags & CC_Z_IN_N ? LT : GE);
1767: value = 2;
1768: break;
1769: }
1770:
1771: return value;
1772: }
1773: #endif
1774:
1775: /* Report inconsistency between the assembler template and the operands.
1776: In an `asm', it's the user's fault; otherwise, the compiler's fault. */
1777:
1778: void
1779: output_operand_lossage (str)
1780: char *str;
1781: {
1782: if (this_is_asm_operands)
1783: error_for_asm (this_is_asm_operands, "invalid `asm': %s", str);
1784: else
1785: abort ();
1786: }
1787:
1788: /* Output of assembler code from a template, and its subroutines. */
1789:
1790: /* Output text from TEMPLATE to the assembler output file,
1791: obeying %-directions to substitute operands taken from
1792: the vector OPERANDS.
1793:
1794: %N (for N a digit) means print operand N in usual manner.
1795: %lN means require operand N to be a CODE_LABEL or LABEL_REF
1796: and print the label name with no punctuation.
1797: %cN means require operand N to be a constant
1798: and print the constant expression with no punctuation.
1799: %aN means expect operand N to be a memory address
1800: (not a memory reference!) and print a reference
1801: to that address.
1802: %nN means expect operand N to be a constant
1803: and print a constant expression for minus the value
1804: of the operand, with no other punctuation. */
1805:
1806: void
1807: output_asm_insn (template, operands)
1808: char *template;
1809: rtx *operands;
1810: {
1811: register char *p;
1812: register int c;
1813:
1814: /* An insn may return a null string template
1815: in a case where no assembler code is needed. */
1816: if (*template == 0)
1817: return;
1818:
1819: p = template;
1820: putc ('\t', asm_out_file);
1821:
1822: #ifdef ASM_OUTPUT_OPCODE
1823: ASM_OUTPUT_OPCODE (asm_out_file, p);
1824: #endif
1825:
1826: while (c = *p++)
1827: {
1828: #ifdef ASM_OUTPUT_OPCODE
1829: if (c == '\n')
1830: {
1831: putc (c, asm_out_file);
1832: while ((c = *p) == '\t')
1833: {
1834: putc (c, asm_out_file);
1835: p++;
1836: }
1837: ASM_OUTPUT_OPCODE (asm_out_file, p);
1838: }
1839: else
1840: #endif
1841: if (c != '%')
1842: putc (c, asm_out_file);
1843: else
1844: {
1845: /* %% outputs a single %. */
1846: if (*p == '%')
1847: {
1848: p++;
1849: putc (c, asm_out_file);
1850: }
1851: /* %= outputs a number which is unique to each insn in the entire
1852: compilation. This is useful for making local labels that are
1853: referred to more than once in a given insn. */
1854: else if (*p == '=')
1855: fprintf (asm_out_file, "%d", insn_counter);
1856: /* % followed by a letter and some digits
1857: outputs an operand in a special way depending on the letter.
1858: Letters `acln' are implemented directly.
1859: Other letters are passed to `output_operand' so that
1860: the PRINT_OPERAND macro can define them. */
1861: else if ((*p >= 'a' && *p <= 'z')
1862: || (*p >= 'A' && *p <= 'Z'))
1863: {
1864: int letter = *p++;
1865: c = atoi (p);
1866:
1867: if (! (*p >= '0' && *p <= '9'))
1868: output_operand_lossage ("operand number missing after %-letter");
1869: else if (this_is_asm_operands && c >= (unsigned) insn_noperands)
1870: output_operand_lossage ("operand number out of range");
1871: else if (letter == 'l')
1872: output_asm_label (operands[c]);
1873: else if (letter == 'a')
1874: output_address (operands[c]);
1875: else if (letter == 'c')
1876: {
1877: if (CONSTANT_ADDRESS_P (operands[c]))
1878: output_addr_const (asm_out_file, operands[c]);
1879: else
1880: output_operand (operands[c], 'c');
1881: }
1882: else if (letter == 'n')
1883: {
1884: if (GET_CODE (operands[c]) == CONST_INT)
1885: fprintf (asm_out_file, "%d", - INTVAL (operands[c]));
1886: else
1887: {
1888: putc ('-', asm_out_file);
1889: output_addr_const (asm_out_file, operands[c]);
1890: }
1891: }
1892: else
1893: output_operand (operands[c], letter);
1894:
1895: while ((c = *p) >= '0' && c <= '9') p++;
1896: }
1897: /* % followed by a digit outputs an operand the default way. */
1898: else if (*p >= '0' && *p <= '9')
1899: {
1900: c = atoi (p);
1901: if (this_is_asm_operands && c >= (unsigned) insn_noperands)
1902: output_operand_lossage ("operand number out of range");
1903: else
1904: output_operand (operands[c], 0);
1905: while ((c = *p) >= '0' && c <= '9') p++;
1906: }
1907: /* % followed by punctuation: output something for that
1908: punctuation character alone, with no operand.
1909: The PRINT_OPERAND macro decides what is actually done. */
1910: #ifdef PRINT_OPERAND_PUNCT_VALID_P
1911: else if (PRINT_OPERAND_PUNCT_VALID_P (*p))
1912: output_operand (0, *p++);
1913: #endif
1914: else
1915: output_operand_lossage ("invalid %%-code");
1916: }
1917: }
1918:
1919: if (flag_print_asm_name)
1920: {
1921: /* Annotate the assembly with a comment describing the pattern and
1922: alternative used. */
1923: if (debug_insn)
1924: {
1925: register int num = INSN_CODE (debug_insn);
1926: fprintf (asm_out_file, " %s %d %s",
1927: ASM_COMMENT_START, INSN_UID (debug_insn), insn_name[num]);
1928: if (insn_n_alternatives[num] > 1)
1929: fprintf (asm_out_file, "/%d", which_alternative + 1);
1930:
1931: /* Clear this so only the first assembler insn
1932: of any rtl insn will get the special comment for -dp. */
1933: debug_insn = 0;
1934: }
1935: }
1936:
1937: putc ('\n', asm_out_file);
1938: }
1939:
1940: /* Output a LABEL_REF, or a bare CODE_LABEL, as an assembler symbol. */
1941:
1942: void
1943: output_asm_label (x)
1944: rtx x;
1945: {
1946: char buf[256];
1947:
1948: if (GET_CODE (x) == LABEL_REF)
1949: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
1950: else if (GET_CODE (x) == CODE_LABEL)
1951: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
1952: else
1953: output_operand_lossage ("`%l' operand isn't a label");
1954:
1955: assemble_name (asm_out_file, buf);
1956: }
1957:
1958: /* Print operand X using machine-dependent assembler syntax.
1959: The macro PRINT_OPERAND is defined just to control this function.
1960: CODE is a non-digit that preceded the operand-number in the % spec,
1961: such as 'z' if the spec was `%z3'. CODE is 0 if there was no char
1962: between the % and the digits.
1963: When CODE is a non-letter, X is 0.
1964:
1965: The meanings of the letters are machine-dependent and controlled
1966: by PRINT_OPERAND. */
1967:
1968: static void
1969: output_operand (x, code)
1970: rtx x;
1971: int code;
1972: {
1973: if (x && GET_CODE (x) == SUBREG)
1974: x = alter_subreg (x);
1975: PRINT_OPERAND (asm_out_file, x, code);
1976: }
1977:
1978: /* Print a memory reference operand for address X
1979: using machine-dependent assembler syntax.
1980: The macro PRINT_OPERAND_ADDRESS exists just to control this function. */
1981:
1982: void
1983: output_address (x)
1984: rtx x;
1985: {
1986: walk_alter_subreg (x);
1987: PRINT_OPERAND_ADDRESS (asm_out_file, x);
1988: }
1989:
1990: /* Print an integer constant expression in assembler syntax.
1991: Addition and subtraction are the only arithmetic
1992: that may appear in these expressions. */
1993:
1994: void
1995: output_addr_const (file, x)
1996: FILE *file;
1997: rtx x;
1998: {
1999: char buf[256];
2000:
2001: restart:
2002: switch (GET_CODE (x))
2003: {
2004: case PC:
2005: if (flag_pic)
2006: putc ('.', file);
2007: else
2008: abort ();
2009: break;
2010:
2011: case SYMBOL_REF:
2012: assemble_name (file, XSTR (x, 0));
2013: break;
2014:
2015: case LABEL_REF:
2016: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
2017: assemble_name (asm_out_file, buf);
2018: break;
2019:
2020: case CODE_LABEL:
2021: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
2022: assemble_name (asm_out_file, buf);
2023: break;
2024:
2025: case CONST_INT:
2026: fprintf (file, "%d", INTVAL (x));
2027: break;
2028:
2029: case CONST:
2030: /* This used to output parentheses around the expression,
2031: but that does not work on the 386 (either ATT or BSD assembler). */
2032: output_addr_const (file, XEXP (x, 0));
2033: break;
2034:
2035: case CONST_DOUBLE:
2036: if (GET_MODE (x) == VOIDmode)
2037: {
2038: /* We can use %d if the number is <32 bits and positive. */
2039: if (CONST_DOUBLE_HIGH (x) || CONST_DOUBLE_LOW (x) < 0)
2040: fprintf (file, "0x%x%08x",
2041: CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));
2042: else
2043: fprintf (file, "%d", CONST_DOUBLE_LOW (x));
2044: }
2045: else
2046: /* We can't handle floating point constants;
2047: PRINT_OPERAND must handle them. */
2048: output_operand_lossage ("floating constant misused");
2049: break;
2050:
2051: case PLUS:
2052: /* Some assemblers need integer constants to appear last (eg masm). */
2053: if (GET_CODE (XEXP (x, 0)) == CONST_INT)
2054: {
2055: output_addr_const (file, XEXP (x, 1));
2056: if (INTVAL (XEXP (x, 0)) >= 0)
2057: fprintf (file, "+");
2058: output_addr_const (file, XEXP (x, 0));
2059: }
2060: else
2061: {
2062: output_addr_const (file, XEXP (x, 0));
2063: if (INTVAL (XEXP (x, 1)) >= 0)
2064: fprintf (file, "+");
2065: output_addr_const (file, XEXP (x, 1));
2066: }
2067: break;
2068:
2069: case MINUS:
2070: output_addr_const (file, XEXP (x, 0));
2071: fprintf (file, "-");
2072: output_addr_const (file, XEXP (x, 1));
2073: break;
2074:
2075: default:
2076: output_operand_lossage ("invalid expression as operand");
2077: }
2078: }
2079:
2080: /* A poor man's fprintf, with the added features of %I, %R, %L, and %U.
2081: %R prints the value of REGISTER_PREFIX.
2082: %L prints the value of LOCAL_LABEL_PREFIX.
2083: %U prints the value of USER_LABEL_PREFIX.
2084: %I prints the value of IMMEDIATE_PREFIX.
2085: Also supported are %d, %x, %s, %e, %f, %g and %%. */
2086:
2087: void
2088: asm_fprintf (va_alist)
2089: va_dcl
2090: {
2091: va_list argptr;
2092: FILE *file;
2093: char buf[10];
2094: char *p, *q, c;
2095:
2096: va_start (argptr);
2097:
2098: file = va_arg (argptr, FILE *);
2099: p = va_arg (argptr, char *);
2100: buf[0] = '%';
2101:
2102: while (c = *p++)
2103: switch (c)
2104: {
2105: case '%':
2106: c = *p++;
2107: q = &buf[1];
2108: while ((c >= '0' && c <= '9') || c == '.')
2109: {
2110: *q++ = c;
2111: c = *p++;
2112: }
2113: switch (c)
2114: {
2115: case '%':
2116: fprintf (file, "%%");
2117: break;
2118:
2119: case 'd': case 'i': case 'u':
2120: case 'x': case 'p': case 'X':
2121: case 'o':
2122: *q++ = c;
2123: *q = 0;
2124: fprintf (file, buf, va_arg (argptr, int));
2125: break;
2126:
2127: case 'e':
2128: case 'f':
2129: case 'g':
2130: *q++ = c;
2131: *q = 0;
2132: fprintf (file, buf, va_arg (argptr, double));
2133: break;
2134:
2135: case 's':
2136: *q++ = c;
2137: *q = 0;
2138: fprintf (file, buf, va_arg (argptr, char *));
2139: break;
2140:
2141: case 'R':
2142: #ifdef REGISTER_PREFIX
2143: fprintf (file, "%s", REGISTER_PREFIX);
2144: #endif
2145: break;
2146:
2147: case 'I':
2148: #ifdef IMMEDIATE_PREFIX
2149: fprintf (file, "%s", IMMEDIATE_PREFIX);
2150: #endif
2151: break;
2152:
2153: case 'L':
2154: #ifdef LOCAL_LABEL_PREFIX
2155: fprintf (file, "%s", LOCAL_LABEL_PREFIX);
2156: #endif
2157: break;
2158:
2159: case 'U':
2160: #ifdef USER_LABEL_PREFIX
2161: fprintf (file, "%s", USER_LABEL_PREFIX);
2162: #endif
2163: break;
2164:
2165: default:
2166: abort ();
2167: }
2168: break;
2169:
2170: default:
2171: fputc (c, file);
2172: }
2173: }
2174:
2175: /* Split up a CONST_DOUBLE or integer constant rtx
2176: into two rtx's for single words,
2177: storing in *FIRST the word that comes first in memory in the target
2178: and in *SECOND the other. */
2179:
2180: void
2181: split_double (value, first, second)
2182: rtx value;
2183: rtx *first, *second;
2184: {
2185: if (GET_CODE (value) == CONST_INT)
2186: {
2187: /* The rule for using CONST_INT for a wider mode
2188: is that we regard the value as signed.
2189: So sign-extend it. */
2190: rtx high = (INTVAL (value) < 0 ? constm1_rtx : const0_rtx);
2191: #if WORDS_BIG_ENDIAN
2192: *first = high;
2193: *second = value;
2194: #else
2195: *first = value;
2196: *second = high;
2197: #endif
2198: }
2199: else if (GET_CODE (value) != CONST_DOUBLE)
2200: {
2201: #if WORDS_BIG_ENDIAN
2202: *first = const0_rtx;
2203: *second = value;
2204: #else
2205: *first = value;
2206: *second = const0_rtx;
2207: #endif
2208: }
2209: else if (GET_MODE (value) == VOIDmode
2210: /* This is the old way we did CONST_DOUBLE integers. */
2211: || GET_MODE_CLASS (GET_MODE (value)) == MODE_INT)
2212: {
2213: /* In an integer, the words are defined as most and least significant.
2214: So order them by the target's convention. */
2215: #if WORDS_BIG_ENDIAN
2216: *first = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (value));
2217: *second = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (value));
2218: #else
2219: *first = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (value));
2220: *second = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (value));
2221: #endif
2222: }
2223: else
2224: {
2225: if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
2226: || HOST_BITS_PER_INT != BITS_PER_WORD)
2227: && ! flag_pretend_float)
2228: abort ();
2229:
2230: #if defined (HOST_WORDS_BIG_ENDIAN) == WORDS_BIG_ENDIAN
2231: /* Host and target agree => no need to swap. */
2232: *first = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (value));
2233: *second = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (value));
2234: #else
2235: *second = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (value));
2236: *first = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (value));
2237: #endif
2238: }
2239: }
2240:
2241: /* Return nonzero if this function has no function calls. */
2242:
2243: int
2244: leaf_function_p ()
2245: {
2246: rtx insn;
2247:
2248: if (profile_flag || profile_block_flag)
2249: return 0;
2250:
2251: for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
2252: {
2253: if (GET_CODE (insn) == CALL_INSN)
2254: return 0;
2255: if (GET_CODE (insn) == INSN
2256: && GET_CODE (PATTERN (insn)) == SEQUENCE
2257: && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == CALL_INSN)
2258: return 0;
2259: }
2260: for (insn = current_function_epilogue_delay_list; insn; insn = XEXP (insn, 1))
2261: {
2262: if (GET_CODE (XEXP (insn, 0)) == CALL_INSN)
2263: return 0;
2264: if (GET_CODE (XEXP (insn, 0)) == INSN
2265: && GET_CODE (PATTERN (XEXP (insn, 0))) == SEQUENCE
2266: && GET_CODE (XVECEXP (PATTERN (XEXP (insn, 0)), 0, 0)) == CALL_INSN)
2267: return 0;
2268: }
2269:
2270: return 1;
2271: }
2272:
2273: /* On some machines, a function with no call insns
2274: can run faster if it doesn't create its own register window.
2275: When output, the leaf function should use only the "output"
2276: registers. Ordinarily, the function would be compiled to use
2277: the "input" registers to find its arguments; it is a candidate
2278: for leaf treatment if it uses only the "input" registers.
2279: Leaf function treatment means renumbering so the function
2280: uses the "output" registers instead. */
2281:
2282: #ifdef LEAF_REGISTERS
2283:
2284: static char permitted_reg_in_leaf_functions[] = LEAF_REGISTERS;
2285:
2286: /* Return 1 if this function uses only the registers that can be
2287: safely renumbered. */
2288:
2289: int
2290: only_leaf_regs_used ()
2291: {
2292: int i;
2293:
2294: for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2295: {
2296: if (regs_ever_live[i] > permitted_reg_in_leaf_functions[i])
2297: return 0;
2298: }
2299: return 1;
2300: }
2301:
2302: /* Scan all instructions and renumber all registers into those
2303: available in leaf functions. */
2304:
2305: static void
2306: leaf_renumber_regs (first)
2307: rtx first;
2308: {
2309: rtx insn;
2310:
2311: /* Renumber only the actual patterns.
2312: The reg-notes can contain frame pointer refs,
2313: and renumbering them could crash, and should not be needed. */
2314: for (insn = first; insn; insn = NEXT_INSN (insn))
2315: if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
2316: leaf_renumber_regs_insn (PATTERN (insn));
2317: for (insn = current_function_epilogue_delay_list; insn; insn = XEXP (insn, 1))
2318: if (GET_RTX_CLASS (GET_CODE (XEXP (insn, 0))) == 'i')
2319: leaf_renumber_regs_insn (PATTERN (XEXP (insn, 0)));
2320: }
2321:
2322: /* Scan IN_RTX and its subexpressions, and renumber all regs into those
2323: available in leaf functions. */
2324:
2325: void
2326: leaf_renumber_regs_insn (in_rtx)
2327: register rtx in_rtx;
2328: {
2329: register int i, j;
2330: register char *format_ptr;
2331:
2332: if (in_rtx == 0)
2333: return;
2334:
2335: /* Renumber all input-registers into output-registers.
2336: renumbered_regs would be 1 for an output-register;
2337: they */
2338:
2339: if (GET_CODE (in_rtx) == REG)
2340: {
2341: int newreg;
2342:
2343: /* Don't renumber the same reg twice. */
2344: if (in_rtx->used)
2345: return;
2346:
2347: newreg = REGNO (in_rtx);
2348: /* Don't try to renumber pseudo regs. It is possible for a psuedo reg
2349: to reach here as part of a REG_NOTE. */
2350: if (newreg >= FIRST_PSEUDO_REGISTER)
2351: {
2352: in_rtx->used = 1;
2353: return;
2354: }
2355: newreg = LEAF_REG_REMAP (newreg);
2356: if (newreg < 0)
2357: abort ();
2358: regs_ever_live[REGNO (in_rtx)] = 0;
2359: regs_ever_live[newreg] = 1;
2360: REGNO (in_rtx) = newreg;
2361: in_rtx->used = 1;
2362: }
2363:
2364: if (GET_RTX_CLASS (GET_CODE (in_rtx)) == 'i')
2365: {
2366: /* Inside a SEQUENCE, we find insns.
2367: Renumber just the patterns of these insns,
2368: just as we do for the top-level insns. */
2369: leaf_renumber_regs_insn (PATTERN (in_rtx));
2370: return;
2371: }
2372:
2373: format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx));
2374:
2375: for (i = 0; i < GET_RTX_LENGTH (GET_CODE (in_rtx)); i++)
2376: switch (*format_ptr++)
2377: {
2378: case 'e':
2379: leaf_renumber_regs_insn (XEXP (in_rtx, i));
2380: break;
2381:
2382: case 'E':
2383: if (NULL != XVEC (in_rtx, i))
2384: {
2385: for (j = 0; j < XVECLEN (in_rtx, i); j++)
2386: leaf_renumber_regs_insn (XVECEXP (in_rtx, i, j));
2387: }
2388: break;
2389:
2390: case 'S':
2391: case 's':
2392: case '0':
2393: case 'i':
2394: case 'n':
2395: case 'u':
2396: break;
2397:
2398: default:
2399: abort ();
2400: }
2401: }
2402: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.