final.c revision 169699
118334Speter/* Convert RTL to assembler code and output it, for GNU compiler.
290087Sobrien   Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
3169699Skan   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
4169699Skan   Free Software Foundation, Inc.
518334Speter
690087SobrienThis file is part of GCC.
718334Speter
890087SobrienGCC is free software; you can redistribute it and/or modify it under
990087Sobrienthe terms of the GNU General Public License as published by the Free
1090087SobrienSoftware Foundation; either version 2, or (at your option) any later
1190087Sobrienversion.
1218334Speter
1390087SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1490087SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or
1590087SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1690087Sobrienfor more details.
1718334Speter
1818334SpeterYou should have received a copy of the GNU General Public License
1990087Sobrienalong with GCC; see the file COPYING.  If not, write to the Free
20169699SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
21169699Skan02110-1301, USA.  */
2218334Speter
2318334Speter/* This is the final pass of the compiler.
2418334Speter   It looks at the rtl code for a function and outputs assembler code.
2518334Speter
2618334Speter   Call `final_start_function' to output the assembler code for function entry,
2718334Speter   `final' to output assembler code for some RTL code,
2818334Speter   `final_end_function' to output assembler code for function exit.
2918334Speter   If a function is compiled in several pieces, each piece is
3018334Speter   output separately with `final'.
3118334Speter
3218334Speter   Some optimizations are also done at this level.
3318334Speter   Move instructions that were made unnecessary by good register allocation
3418334Speter   are detected and omitted from the output.  (Though most of these
3518334Speter   are removed by the last jump pass.)
3618334Speter
3718334Speter   Instructions to set the condition codes are omitted when it can be
3818334Speter   seen that the condition codes already had the desired values.
3918334Speter
4018334Speter   In some cases it is sufficient if the inherited condition codes
4118334Speter   have related values, but this may require the following insn
4218334Speter   (the one that tests the condition codes) to be modified.
4318334Speter
4418334Speter   The code for the function prologue and epilogue are generated
4590087Sobrien   directly in assembler by the target functions function_prologue and
4690087Sobrien   function_epilogue.  Those instructions never exist as rtl.  */
4718334Speter
4818334Speter#include "config.h"
4950503Sobrien#include "system.h"
50132727Skan#include "coretypes.h"
51132727Skan#include "tm.h"
5218334Speter
5318334Speter#include "tree.h"
5418334Speter#include "rtl.h"
5590087Sobrien#include "tm_p.h"
5618334Speter#include "regs.h"
5718334Speter#include "insn-config.h"
5818334Speter#include "insn-attr.h"
5918334Speter#include "recog.h"
6018334Speter#include "conditions.h"
6118334Speter#include "flags.h"
6218334Speter#include "real.h"
6318334Speter#include "hard-reg-set.h"
6418334Speter#include "output.h"
6550503Sobrien#include "except.h"
6690087Sobrien#include "function.h"
6750503Sobrien#include "toplev.h"
6850503Sobrien#include "reload.h"
6952515Sobrien#include "intl.h"
7090087Sobrien#include "basic-block.h"
7190087Sobrien#include "target.h"
7290087Sobrien#include "debug.h"
7390087Sobrien#include "expr.h"
74117404Skan#include "cfglayout.h"
75169699Skan#include "tree-pass.h"
76169699Skan#include "timevar.h"
77169699Skan#include "cgraph.h"
78169699Skan#include "coverage.h"
7918334Speter
8018334Speter#ifdef XCOFF_DEBUGGING_INFO
8190087Sobrien#include "xcoffout.h"		/* Needed for external data
8290087Sobrien				   declarations for e.g. AIX 4.x.  */
8318334Speter#endif
8418334Speter
8550503Sobrien#if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
8650503Sobrien#include "dwarf2out.h"
8750503Sobrien#endif
8850503Sobrien
89132727Skan#ifdef DBX_DEBUGGING_INFO
90132727Skan#include "dbxout.h"
91132727Skan#endif
92132727Skan
93169699Skan#ifdef SDB_DEBUGGING_INFO
94169699Skan#include "sdbout.h"
95169699Skan#endif
96169699Skan
9718334Speter/* If we aren't using cc0, CC_STATUS_INIT shouldn't exist.  So define a
9818334Speter   null default for it to save conditionalization later.  */
9918334Speter#ifndef CC_STATUS_INIT
10018334Speter#define CC_STATUS_INIT
10118334Speter#endif
10218334Speter
10318334Speter/* How to start an assembler comment.  */
10418334Speter#ifndef ASM_COMMENT_START
10518334Speter#define ASM_COMMENT_START ";#"
10618334Speter#endif
10718334Speter
10818334Speter/* Is the given character a logical line separator for the assembler?  */
10918334Speter#ifndef IS_ASM_LOGICAL_LINE_SEPARATOR
11018334Speter#define IS_ASM_LOGICAL_LINE_SEPARATOR(C) ((C) == ';')
11118334Speter#endif
11218334Speter
11350503Sobrien#ifndef JUMP_TABLES_IN_TEXT_SECTION
11450503Sobrien#define JUMP_TABLES_IN_TEXT_SECTION 0
11550503Sobrien#endif
11650503Sobrien
117132727Skan/* Bitflags used by final_scan_insn.  */
118132727Skan#define SEEN_BB		1
119132727Skan#define SEEN_NOTE	2
120132727Skan#define SEEN_EMITTED	4
121132727Skan
12218334Speter/* Last insn processed by final_scan_insn.  */
12390087Sobrienstatic rtx debug_insn;
12490087Sobrienrtx current_output_insn;
12518334Speter
12618334Speter/* Line number of last NOTE.  */
12718334Speterstatic int last_linenum;
12818334Speter
12918334Speter/* Highest line number in current block.  */
13018334Speterstatic int high_block_linenum;
13118334Speter
13218334Speter/* Likewise for function.  */
13318334Speterstatic int high_function_linenum;
13418334Speter
13518334Speter/* Filename of last NOTE.  */
13690087Sobrienstatic const char *last_filename;
13718334Speter
138169699Skan/* Whether to force emission of a line note before the next insn.  */
139169699Skanstatic bool force_source_line = false;
14050503Sobrien
141169699Skanextern const int length_unit_log; /* This is defined in insn-attrtab.c.  */
142169699Skan
14318334Speter/* Nonzero while outputting an `asm' with operands.
144169699Skan   This means that inconsistencies are the user's fault, so don't die.
14518334Speter   The precise value is the insn being output, to pass to error_for_asm.  */
146117404Skanrtx this_is_asm_operands;
14718334Speter
14818334Speter/* Number of operands of this insn, for an `asm' with operands.  */
14950503Sobrienstatic unsigned int insn_noperands;
15018334Speter
15118334Speter/* Compare optimization flag.  */
15218334Speter
15318334Speterstatic rtx last_ignored_compare = 0;
15418334Speter
15518334Speter/* Assign a unique number to each insn that is output.
15618334Speter   This can be used to generate unique local labels.  */
15718334Speter
15818334Speterstatic int insn_counter = 0;
15918334Speter
16018334Speter#ifdef HAVE_cc0
16118334Speter/* This variable contains machine-dependent flags (defined in tm.h)
16218334Speter   set and examined by output routines
16318334Speter   that describe how to interpret the condition codes properly.  */
16418334Speter
16518334SpeterCC_STATUS cc_status;
16618334Speter
16718334Speter/* During output of an insn, this contains a copy of cc_status
16818334Speter   from before the insn.  */
16918334Speter
17018334SpeterCC_STATUS cc_prev_status;
17118334Speter#endif
17218334Speter
17318334Speter/* Indexed by hardware reg number, is 1 if that register is ever
17418334Speter   used in the current function.
17518334Speter
17618334Speter   In life_analysis, or in stupid_life_analysis, this is set
17718334Speter   up to record the hard regs used explicitly.  Reload adds
17818334Speter   in the hard regs used for holding pseudo regs.  Final uses
17918334Speter   it to generate the code in the function prologue and epilogue
18018334Speter   to save and restore registers as needed.  */
18118334Speter
18218334Speterchar regs_ever_live[FIRST_PSEUDO_REGISTER];
18318334Speter
184132727Skan/* Like regs_ever_live, but 1 if a reg is set or clobbered from an asm.
185132727Skan   Unlike regs_ever_live, elements of this array corresponding to
186132727Skan   eliminable regs like the frame pointer are set if an asm sets them.  */
187132727Skan
188132727Skanchar regs_asm_clobbered[FIRST_PSEUDO_REGISTER];
189132727Skan
19018334Speter/* Nonzero means current function must be given a frame pointer.
191132727Skan   Initialized in function.c to 0.  Set only in reload1.c as per
192132727Skan   the needs of the function.  */
19318334Speter
19418334Speterint frame_pointer_needed;
19518334Speter
19690087Sobrien/* Number of unmatched NOTE_INSN_BLOCK_BEG notes we have seen.  */
19718334Speter
19818334Speterstatic int block_depth;
19918334Speter
20018334Speter/* Nonzero if have enabled APP processing of our assembler output.  */
20118334Speter
20218334Speterstatic int app_on;
20318334Speter
20418334Speter/* If we are outputting an insn sequence, this contains the sequence rtx.
20518334Speter   Zero otherwise.  */
20618334Speter
20718334Speterrtx final_sequence;
20818334Speter
20918334Speter#ifdef ASSEMBLER_DIALECT
21018334Speter
21118334Speter/* Number of the assembler dialect to use, starting at 0.  */
21218334Speterstatic int dialect_number;
21318334Speter#endif
21418334Speter
21590087Sobrien#ifdef HAVE_conditional_execution
21690087Sobrien/* Nonnull if the insn currently being emitted was a COND_EXEC pattern.  */
21790087Sobrienrtx current_insn_predicate;
21890087Sobrien#endif
21918334Speter
22050503Sobrien#ifdef HAVE_ATTR_length
221132727Skanstatic int asm_insn_count (rtx);
22250503Sobrien#endif
223132727Skanstatic void profile_function (FILE *);
224132727Skanstatic void profile_after_prologue (FILE *);
225132727Skanstatic bool notice_source_line (rtx);
226132727Skanstatic rtx walk_alter_subreg (rtx *);
227132727Skanstatic void output_asm_name (void);
228132727Skanstatic void output_alternate_entry_point (FILE *, rtx);
229132727Skanstatic tree get_mem_expr_from_op (rtx, int *);
230132727Skanstatic void output_asm_operand_names (rtx *, int *, int);
231132727Skanstatic void output_operand (rtx, int);
23250503Sobrien#ifdef LEAF_REGISTERS
233132727Skanstatic void leaf_renumber_regs (rtx);
23450503Sobrien#endif
23550503Sobrien#ifdef HAVE_cc0
236132727Skanstatic int alter_cond (rtx);
23750503Sobrien#endif
23890087Sobrien#ifndef ADDR_VEC_ALIGN
239132727Skanstatic int final_addr_vec_align (rtx);
24090087Sobrien#endif
24190087Sobrien#ifdef HAVE_ATTR_length
242132727Skanstatic int align_fuzz (rtx, rtx, int, unsigned);
24390087Sobrien#endif
24418334Speter
24518334Speter/* Initialize data in final at the beginning of a compilation.  */
24618334Speter
24718334Spetervoid
248132727Skaninit_final (const char *filename ATTRIBUTE_UNUSED)
24918334Speter{
25018334Speter  app_on = 0;
25118334Speter  final_sequence = 0;
25218334Speter
25318334Speter#ifdef ASSEMBLER_DIALECT
25418334Speter  dialect_number = ASSEMBLER_DIALECT;
25518334Speter#endif
25618334Speter}
25718334Speter
25890087Sobrien/* Default target function prologue and epilogue assembler output.
25918334Speter
26090087Sobrien   If not overridden for epilogue code, then the function body itself
26190087Sobrien   contains return instructions wherever needed.  */
26290087Sobrienvoid
263132727Skandefault_function_pro_epilogue (FILE *file ATTRIBUTE_UNUSED,
264132727Skan			       HOST_WIDE_INT size ATTRIBUTE_UNUSED)
26590087Sobrien{
26690087Sobrien}
26718334Speter
26890087Sobrien/* Default target hook that outputs nothing to a stream.  */
26990087Sobrienvoid
270132727Skanno_asm_to_stream (FILE *file ATTRIBUTE_UNUSED)
27190087Sobrien{
27218334Speter}
27318334Speter
27418334Speter/* Enable APP processing of subsequent output.
27518334Speter   Used before the output from an `asm' statement.  */
27618334Speter
27718334Spetervoid
278132727Skanapp_enable (void)
27918334Speter{
28018334Speter  if (! app_on)
28118334Speter    {
28250503Sobrien      fputs (ASM_APP_ON, asm_out_file);
28318334Speter      app_on = 1;
28418334Speter    }
28518334Speter}
28618334Speter
28718334Speter/* Disable APP processing of subsequent output.
28818334Speter   Called from varasm.c before most kinds of output.  */
28918334Speter
29018334Spetervoid
291132727Skanapp_disable (void)
29218334Speter{
29318334Speter  if (app_on)
29418334Speter    {
29550503Sobrien      fputs (ASM_APP_OFF, asm_out_file);
29618334Speter      app_on = 0;
29718334Speter    }
29818334Speter}
29918334Speter
30090087Sobrien/* Return the number of slots filled in the current
30118334Speter   delayed branch sequence (we don't count the insn needing the
30218334Speter   delay slot).   Zero if not in a delayed branch sequence.  */
30318334Speter
30418334Speter#ifdef DELAY_SLOTS
30518334Speterint
306132727Skandbr_sequence_length (void)
30718334Speter{
30818334Speter  if (final_sequence != 0)
30918334Speter    return XVECLEN (final_sequence, 0) - 1;
31018334Speter  else
31118334Speter    return 0;
31218334Speter}
31318334Speter#endif
31418334Speter
31518334Speter/* The next two pages contain routines used to compute the length of an insn
31618334Speter   and to shorten branches.  */
31718334Speter
31818334Speter/* Arrays for insn lengths, and addresses.  The latter is referenced by
31918334Speter   `insn_current_length'.  */
32018334Speter
32190087Sobrienstatic int *insn_lengths;
32218334Speter
32390087Sobrienvarray_type insn_addresses_;
32490087Sobrien
32552515Sobrien/* Max uid for which the above arrays are valid.  */
32652515Sobrienstatic int insn_lengths_max_uid;
32752515Sobrien
32818334Speter/* Address of insn being processed.  Used by `insn_current_length'.  */
32918334Speterint insn_current_address;
33018334Speter
33150503Sobrien/* Address of insn being processed in previous iteration.  */
33250503Sobrienint insn_last_address;
33350503Sobrien
33490087Sobrien/* known invariant alignment of insn being processed.  */
33550503Sobrienint insn_current_align;
33650503Sobrien
33750503Sobrien/* After shorten_branches, for any insn, uid_align[INSN_UID (insn)]
33850503Sobrien   gives the next following alignment insn that increases the known
33950503Sobrien   alignment, or NULL_RTX if there is no such insn.
34050503Sobrien   For any alignment obtained this way, we can again index uid_align with
34150503Sobrien   its uid to obtain the next following align that in turn increases the
34250503Sobrien   alignment, till we reach NULL_RTX; the sequence obtained this way
34350503Sobrien   for each insn we'll call the alignment chain of this insn in the following
34450503Sobrien   comments.  */
34550503Sobrien
34690087Sobrienstruct label_alignment
34790087Sobrien{
34850503Sobrien  short alignment;
34950503Sobrien  short max_skip;
35050503Sobrien};
35150503Sobrien
35250503Sobrienstatic rtx *uid_align;
35350503Sobrienstatic int *uid_shuid;
35450503Sobrienstatic struct label_alignment *label_align;
35550503Sobrien
35618334Speter/* Indicate that branch shortening hasn't yet been done.  */
35718334Speter
35818334Spetervoid
359132727Skaninit_insn_lengths (void)
36018334Speter{
36150503Sobrien  if (uid_shuid)
36250503Sobrien    {
36350503Sobrien      free (uid_shuid);
36450503Sobrien      uid_shuid = 0;
36550503Sobrien    }
36650503Sobrien  if (insn_lengths)
36750503Sobrien    {
36850503Sobrien      free (insn_lengths);
36950503Sobrien      insn_lengths = 0;
37052515Sobrien      insn_lengths_max_uid = 0;
37150503Sobrien    }
37290087Sobrien#ifdef HAVE_ATTR_length
37390087Sobrien  INSN_ADDRESSES_FREE ();
37490087Sobrien#endif
37550503Sobrien  if (uid_align)
37650503Sobrien    {
37750503Sobrien      free (uid_align);
37850503Sobrien      uid_align = 0;
37950503Sobrien    }
38018334Speter}
38118334Speter
38218334Speter/* Obtain the current length of an insn.  If branch shortening has been done,
383169699Skan   get its actual length.  Otherwise, use FALLBACK_FN to calculate the
384169699Skan   length.  */
385169699Skanstatic inline int
386169699Skanget_attr_length_1 (rtx insn ATTRIBUTE_UNUSED,
387169699Skan		   int (*fallback_fn) (rtx) ATTRIBUTE_UNUSED)
38818334Speter{
38918334Speter#ifdef HAVE_ATTR_length
39018334Speter  rtx body;
39118334Speter  int i;
39218334Speter  int length = 0;
39318334Speter
39452515Sobrien  if (insn_lengths_max_uid > INSN_UID (insn))
39518334Speter    return insn_lengths[INSN_UID (insn)];
39618334Speter  else
39718334Speter    switch (GET_CODE (insn))
39818334Speter      {
39918334Speter      case NOTE:
40018334Speter      case BARRIER:
40118334Speter      case CODE_LABEL:
40218334Speter	return 0;
40318334Speter
40418334Speter      case CALL_INSN:
405169699Skan	length = fallback_fn (insn);
40618334Speter	break;
40718334Speter
40818334Speter      case JUMP_INSN:
40918334Speter	body = PATTERN (insn);
410117404Skan	if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC)
41118334Speter	  {
41250503Sobrien	    /* Alignment is machine-dependent and should be handled by
41350503Sobrien	       ADDR_VEC_ALIGN.  */
41418334Speter	  }
41518334Speter	else
416169699Skan	  length = fallback_fn (insn);
41718334Speter	break;
41818334Speter
41918334Speter      case INSN:
42018334Speter	body = PATTERN (insn);
42118334Speter	if (GET_CODE (body) == USE || GET_CODE (body) == CLOBBER)
42218334Speter	  return 0;
42318334Speter
42418334Speter	else if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0)
425169699Skan	  length = asm_insn_count (body) * fallback_fn (insn);
42618334Speter	else if (GET_CODE (body) == SEQUENCE)
42718334Speter	  for (i = 0; i < XVECLEN (body, 0); i++)
42818334Speter	    length += get_attr_length (XVECEXP (body, 0, i));
42918334Speter	else
430169699Skan	  length = fallback_fn (insn);
43150503Sobrien	break;
43250503Sobrien
43350503Sobrien      default:
43450503Sobrien	break;
43518334Speter      }
43618334Speter
43718334Speter#ifdef ADJUST_INSN_LENGTH
43818334Speter  ADJUST_INSN_LENGTH (insn, length);
43918334Speter#endif
44018334Speter  return length;
44118334Speter#else /* not HAVE_ATTR_length */
44218334Speter  return 0;
443169699Skan#define insn_default_length 0
444169699Skan#define insn_min_length 0
44518334Speter#endif /* not HAVE_ATTR_length */
44618334Speter}
447169699Skan
448169699Skan/* Obtain the current length of an insn.  If branch shortening has been done,
449169699Skan   get its actual length.  Otherwise, get its maximum length.  */
450169699Skanint
451169699Skanget_attr_length (rtx insn)
452169699Skan{
453169699Skan  return get_attr_length_1 (insn, insn_default_length);
454169699Skan}
455169699Skan
456169699Skan/* Obtain the current length of an insn.  If branch shortening has been done,
457169699Skan   get its actual length.  Otherwise, get its minimum length.  */
458169699Skanint
459169699Skanget_attr_min_length (rtx insn)
460169699Skan{
461169699Skan  return get_attr_length_1 (insn, insn_min_length);
462169699Skan}
46318334Speter
46450503Sobrien/* Code to handle alignment inside shorten_branches.  */
46550503Sobrien
46650503Sobrien/* Here is an explanation how the algorithm in align_fuzz can give
46750503Sobrien   proper results:
46850503Sobrien
46950503Sobrien   Call a sequence of instructions beginning with alignment point X
47050503Sobrien   and continuing until the next alignment point `block X'.  When `X'
47190087Sobrien   is used in an expression, it means the alignment value of the
47250503Sobrien   alignment point.
47390087Sobrien
47450503Sobrien   Call the distance between the start of the first insn of block X, and
47550503Sobrien   the end of the last insn of block X `IX', for the `inner size of X'.
47650503Sobrien   This is clearly the sum of the instruction lengths.
47790087Sobrien
47850503Sobrien   Likewise with the next alignment-delimited block following X, which we
47950503Sobrien   shall call block Y.
48090087Sobrien
48150503Sobrien   Call the distance between the start of the first insn of block X, and
48250503Sobrien   the start of the first insn of block Y `OX', for the `outer size of X'.
48390087Sobrien
48450503Sobrien   The estimated padding is then OX - IX.
48590087Sobrien
48650503Sobrien   OX can be safely estimated as
48790087Sobrien
48850503Sobrien           if (X >= Y)
48950503Sobrien                   OX = round_up(IX, Y)
49050503Sobrien           else
49150503Sobrien                   OX = round_up(IX, X) + Y - X
49290087Sobrien
49350503Sobrien   Clearly est(IX) >= real(IX), because that only depends on the
49450503Sobrien   instruction lengths, and those being overestimated is a given.
49590087Sobrien
49650503Sobrien   Clearly round_up(foo, Z) >= round_up(bar, Z) if foo >= bar, so
49750503Sobrien   we needn't worry about that when thinking about OX.
49890087Sobrien
49950503Sobrien   When X >= Y, the alignment provided by Y adds no uncertainty factor
50050503Sobrien   for branch ranges starting before X, so we can just round what we have.
50150503Sobrien   But when X < Y, we don't know anything about the, so to speak,
50250503Sobrien   `middle bits', so we have to assume the worst when aligning up from an
50350503Sobrien   address mod X to one mod Y, which is Y - X.  */
50450503Sobrien
50550503Sobrien#ifndef LABEL_ALIGN
50690087Sobrien#define LABEL_ALIGN(LABEL) align_labels_log
50750503Sobrien#endif
50850503Sobrien
50950503Sobrien#ifndef LABEL_ALIGN_MAX_SKIP
51090087Sobrien#define LABEL_ALIGN_MAX_SKIP align_labels_max_skip
51150503Sobrien#endif
51250503Sobrien
51350503Sobrien#ifndef LOOP_ALIGN
51490087Sobrien#define LOOP_ALIGN(LABEL) align_loops_log
51550503Sobrien#endif
51650503Sobrien
51750503Sobrien#ifndef LOOP_ALIGN_MAX_SKIP
51890087Sobrien#define LOOP_ALIGN_MAX_SKIP align_loops_max_skip
51950503Sobrien#endif
52050503Sobrien
52150503Sobrien#ifndef LABEL_ALIGN_AFTER_BARRIER
52250503Sobrien#define LABEL_ALIGN_AFTER_BARRIER(LABEL) 0
52350503Sobrien#endif
52450503Sobrien
52550503Sobrien#ifndef LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP
52650503Sobrien#define LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP 0
52750503Sobrien#endif
52850503Sobrien
52990087Sobrien#ifndef JUMP_ALIGN
53090087Sobrien#define JUMP_ALIGN(LABEL) align_jumps_log
53190087Sobrien#endif
53290087Sobrien
53390087Sobrien#ifndef JUMP_ALIGN_MAX_SKIP
53490087Sobrien#define JUMP_ALIGN_MAX_SKIP align_jumps_max_skip
53590087Sobrien#endif
53690087Sobrien
53750503Sobrien#ifndef ADDR_VEC_ALIGN
53890087Sobrienstatic int
539132727Skanfinal_addr_vec_align (rtx addr_vec)
54050503Sobrien{
54190087Sobrien  int align = GET_MODE_SIZE (GET_MODE (PATTERN (addr_vec)));
54250503Sobrien
54350503Sobrien  if (align > BIGGEST_ALIGNMENT / BITS_PER_UNIT)
54450503Sobrien    align = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
54590087Sobrien  return exact_log2 (align);
54650503Sobrien
54750503Sobrien}
54890087Sobrien
54950503Sobrien#define ADDR_VEC_ALIGN(ADDR_VEC) final_addr_vec_align (ADDR_VEC)
55050503Sobrien#endif
55150503Sobrien
55250503Sobrien#ifndef INSN_LENGTH_ALIGNMENT
55350503Sobrien#define INSN_LENGTH_ALIGNMENT(INSN) length_unit_log
55450503Sobrien#endif
55550503Sobrien
55650503Sobrien#define INSN_SHUID(INSN) (uid_shuid[INSN_UID (INSN)])
55750503Sobrien
55850503Sobrienstatic int min_labelno, max_labelno;
55950503Sobrien
56050503Sobrien#define LABEL_TO_ALIGNMENT(LABEL) \
56150503Sobrien  (label_align[CODE_LABEL_NUMBER (LABEL) - min_labelno].alignment)
56250503Sobrien
56350503Sobrien#define LABEL_TO_MAX_SKIP(LABEL) \
56450503Sobrien  (label_align[CODE_LABEL_NUMBER (LABEL) - min_labelno].max_skip)
56550503Sobrien
56650503Sobrien/* For the benefit of port specific code do this also as a function.  */
56790087Sobrien
56850503Sobrienint
569132727Skanlabel_to_alignment (rtx label)
57050503Sobrien{
57150503Sobrien  return LABEL_TO_ALIGNMENT (label);
57250503Sobrien}
57350503Sobrien
57450503Sobrien#ifdef HAVE_ATTR_length
57550503Sobrien/* The differences in addresses
57650503Sobrien   between a branch and its target might grow or shrink depending on
57750503Sobrien   the alignment the start insn of the range (the branch for a forward
57850503Sobrien   branch or the label for a backward branch) starts out on; if these
57950503Sobrien   differences are used naively, they can even oscillate infinitely.
58050503Sobrien   We therefore want to compute a 'worst case' address difference that
58150503Sobrien   is independent of the alignment the start insn of the range end
58250503Sobrien   up on, and that is at least as large as the actual difference.
58350503Sobrien   The function align_fuzz calculates the amount we have to add to the
58450503Sobrien   naively computed difference, by traversing the part of the alignment
58550503Sobrien   chain of the start insn of the range that is in front of the end insn
58650503Sobrien   of the range, and considering for each alignment the maximum amount
58750503Sobrien   that it might contribute to a size increase.
58850503Sobrien
58950503Sobrien   For casesi tables, we also want to know worst case minimum amounts of
59050503Sobrien   address difference, in case a machine description wants to introduce
59150503Sobrien   some common offset that is added to all offsets in a table.
59290087Sobrien   For this purpose, align_fuzz with a growth argument of 0 computes the
59350503Sobrien   appropriate adjustment.  */
59450503Sobrien
59550503Sobrien/* Compute the maximum delta by which the difference of the addresses of
59650503Sobrien   START and END might grow / shrink due to a different address for start
59750503Sobrien   which changes the size of alignment insns between START and END.
59850503Sobrien   KNOWN_ALIGN_LOG is the alignment known for START.
59950503Sobrien   GROWTH should be ~0 if the objective is to compute potential code size
60050503Sobrien   increase, and 0 if the objective is to compute potential shrink.
60150503Sobrien   The return value is undefined for any other value of GROWTH.  */
60290087Sobrien
60390087Sobrienstatic int
604132727Skanalign_fuzz (rtx start, rtx end, int known_align_log, unsigned int growth)
60550503Sobrien{
60650503Sobrien  int uid = INSN_UID (start);
60750503Sobrien  rtx align_label;
60850503Sobrien  int known_align = 1 << known_align_log;
60950503Sobrien  int end_shuid = INSN_SHUID (end);
61050503Sobrien  int fuzz = 0;
61150503Sobrien
61250503Sobrien  for (align_label = uid_align[uid]; align_label; align_label = uid_align[uid])
61350503Sobrien    {
61450503Sobrien      int align_addr, new_align;
61550503Sobrien
61650503Sobrien      uid = INSN_UID (align_label);
61790087Sobrien      align_addr = INSN_ADDRESSES (uid) - insn_lengths[uid];
61850503Sobrien      if (uid_shuid[uid] > end_shuid)
61950503Sobrien	break;
62050503Sobrien      known_align_log = LABEL_TO_ALIGNMENT (align_label);
62150503Sobrien      new_align = 1 << known_align_log;
62250503Sobrien      if (new_align < known_align)
62350503Sobrien	continue;
62450503Sobrien      fuzz += (-align_addr ^ growth) & (new_align - known_align);
62550503Sobrien      known_align = new_align;
62650503Sobrien    }
62750503Sobrien  return fuzz;
62850503Sobrien}
62950503Sobrien
63050503Sobrien/* Compute a worst-case reference address of a branch so that it
63150503Sobrien   can be safely used in the presence of aligned labels.  Since the
63250503Sobrien   size of the branch itself is unknown, the size of the branch is
63350503Sobrien   not included in the range.  I.e. for a forward branch, the reference
63450503Sobrien   address is the end address of the branch as known from the previous
63550503Sobrien   branch shortening pass, minus a value to account for possible size
63650503Sobrien   increase due to alignment.  For a backward branch, it is the start
63750503Sobrien   address of the branch as known from the current pass, plus a value
63850503Sobrien   to account for possible size increase due to alignment.
63950503Sobrien   NB.: Therefore, the maximum offset allowed for backward branches needs
64050503Sobrien   to exclude the branch size.  */
64190087Sobrien
64250503Sobrienint
643132727Skaninsn_current_reference_address (rtx branch)
64450503Sobrien{
64590087Sobrien  rtx dest, seq;
64690087Sobrien  int seq_uid;
64790087Sobrien
64890087Sobrien  if (! INSN_ADDRESSES_SET_P ())
64990087Sobrien    return 0;
65090087Sobrien
65190087Sobrien  seq = NEXT_INSN (PREV_INSN (branch));
65290087Sobrien  seq_uid = INSN_UID (seq);
653169699Skan  if (!JUMP_P (branch))
65450503Sobrien    /* This can happen for example on the PA; the objective is to know the
65550503Sobrien       offset to address something in front of the start of the function.
65650503Sobrien       Thus, we can treat it like a backward branch.
65750503Sobrien       We assume here that FUNCTION_BOUNDARY / BITS_PER_UNIT is larger than
65850503Sobrien       any alignment we'd encounter, so we skip the call to align_fuzz.  */
65950503Sobrien    return insn_current_address;
66050503Sobrien  dest = JUMP_LABEL (branch);
66190087Sobrien
66290087Sobrien  /* BRANCH has no proper alignment chain set, so use SEQ.
66390087Sobrien     BRANCH also has no INSN_SHUID.  */
66490087Sobrien  if (INSN_SHUID (seq) < INSN_SHUID (dest))
66550503Sobrien    {
66690087Sobrien      /* Forward branch.  */
66750503Sobrien      return (insn_last_address + insn_lengths[seq_uid]
66850503Sobrien	      - align_fuzz (seq, dest, length_unit_log, ~0));
66950503Sobrien    }
67050503Sobrien  else
67150503Sobrien    {
67290087Sobrien      /* Backward branch.  */
67350503Sobrien      return (insn_current_address
67450503Sobrien	      + align_fuzz (dest, seq, length_unit_log, ~0));
67550503Sobrien    }
67650503Sobrien}
67750503Sobrien#endif /* HAVE_ATTR_length */
67850503Sobrien
679169699Skan/* Compute branch alignments based on frequency information in the
680169699Skan   CFG.  */
681169699Skan
682169699Skanstatic unsigned int
683132727Skancompute_alignments (void)
68490087Sobrien{
68590087Sobrien  int log, max_skip, max_log;
686117404Skan  basic_block bb;
68790087Sobrien
68890087Sobrien  if (label_align)
68990087Sobrien    {
69090087Sobrien      free (label_align);
69190087Sobrien      label_align = 0;
69290087Sobrien    }
69390087Sobrien
69490087Sobrien  max_labelno = max_label_num ();
69590087Sobrien  min_labelno = get_first_label_num ();
696169699Skan  label_align = XCNEWVEC (struct label_alignment, max_labelno - min_labelno + 1);
69790087Sobrien
69890087Sobrien  /* If not optimizing or optimizing for size, don't assign any alignments.  */
69990087Sobrien  if (! optimize || optimize_size)
700169699Skan    return 0;
70190087Sobrien
702117404Skan  FOR_EACH_BB (bb)
70390087Sobrien    {
704132727Skan      rtx label = BB_HEAD (bb);
70590087Sobrien      int fallthru_frequency = 0, branch_frequency = 0, has_fallthru = 0;
70690087Sobrien      edge e;
707169699Skan      edge_iterator ei;
70890087Sobrien
709169699Skan      if (!LABEL_P (label)
710132727Skan	  || probably_never_executed_bb_p (bb))
71190087Sobrien	continue;
71290087Sobrien      max_log = LABEL_ALIGN (label);
71390087Sobrien      max_skip = LABEL_ALIGN_MAX_SKIP;
71490087Sobrien
715169699Skan      FOR_EACH_EDGE (e, ei, bb->preds)
71690087Sobrien	{
71790087Sobrien	  if (e->flags & EDGE_FALLTHRU)
71890087Sobrien	    has_fallthru = 1, fallthru_frequency += EDGE_FREQUENCY (e);
71990087Sobrien	  else
72090087Sobrien	    branch_frequency += EDGE_FREQUENCY (e);
72190087Sobrien	}
72290087Sobrien
72390087Sobrien      /* There are two purposes to align block with no fallthru incoming edge:
72490087Sobrien	 1) to avoid fetch stalls when branch destination is near cache boundary
72590087Sobrien	 2) to improve cache efficiency in case the previous block is not executed
72690087Sobrien	    (so it does not need to be in the cache).
72790087Sobrien
72890087Sobrien	 We to catch first case, we align frequently executed blocks.
72990087Sobrien	 To catch the second, we align blocks that are executed more frequently
73090087Sobrien	 than the predecessor and the predecessor is likely to not be executed
73190087Sobrien	 when function is called.  */
73290087Sobrien
73390087Sobrien      if (!has_fallthru
73490087Sobrien	  && (branch_frequency > BB_FREQ_MAX / 10
735117404Skan	      || (bb->frequency > bb->prev_bb->frequency * 10
736117404Skan		  && (bb->prev_bb->frequency
73790087Sobrien		      <= ENTRY_BLOCK_PTR->frequency / 2))))
73890087Sobrien	{
73990087Sobrien	  log = JUMP_ALIGN (label);
74090087Sobrien	  if (max_log < log)
74190087Sobrien	    {
74290087Sobrien	      max_log = log;
74390087Sobrien	      max_skip = JUMP_ALIGN_MAX_SKIP;
74490087Sobrien	    }
74590087Sobrien	}
74690087Sobrien      /* In case block is frequent and reached mostly by non-fallthru edge,
747117404Skan	 align it.  It is most likely a first block of loop.  */
74890087Sobrien      if (has_fallthru
749132727Skan	  && maybe_hot_bb_p (bb)
75090087Sobrien	  && branch_frequency + fallthru_frequency > BB_FREQ_MAX / 10
751117404Skan	  && branch_frequency > fallthru_frequency * 2)
75290087Sobrien	{
75390087Sobrien	  log = LOOP_ALIGN (label);
75490087Sobrien	  if (max_log < log)
75590087Sobrien	    {
75690087Sobrien	      max_log = log;
75790087Sobrien	      max_skip = LOOP_ALIGN_MAX_SKIP;
75890087Sobrien	    }
75990087Sobrien	}
76090087Sobrien      LABEL_TO_ALIGNMENT (label) = max_log;
76190087Sobrien      LABEL_TO_MAX_SKIP (label) = max_skip;
76290087Sobrien    }
763169699Skan  return 0;
76490087Sobrien}
765169699Skan
766169699Skanstruct tree_opt_pass pass_compute_alignments =
767169699Skan{
768169699Skan  NULL,                                 /* name */
769169699Skan  NULL,                                 /* gate */
770169699Skan  compute_alignments,                   /* execute */
771169699Skan  NULL,                                 /* sub */
772169699Skan  NULL,                                 /* next */
773169699Skan  0,                                    /* static_pass_number */
774169699Skan  0,                                    /* tv_id */
775169699Skan  0,                                    /* properties_required */
776169699Skan  0,                                    /* properties_provided */
777169699Skan  0,                                    /* properties_destroyed */
778169699Skan  0,                                    /* todo_flags_start */
779169699Skan  0,                                    /* todo_flags_finish */
780169699Skan  0                                     /* letter */
781169699Skan};
782169699Skan
78390087Sobrien
78418334Speter/* Make a pass over all insns and compute their actual lengths by shortening
78518334Speter   any branches of variable length if possible.  */
78618334Speter
78750503Sobrien/* shorten_branches might be called multiple times:  for example, the SH
78850503Sobrien   port splits out-of-range conditional branches in MACHINE_DEPENDENT_REORG.
78950503Sobrien   In order to do this, it needs proper length information, which it obtains
79050503Sobrien   by calling shorten_branches.  This cannot be collapsed with
79190087Sobrien   shorten_branches itself into a single pass unless we also want to integrate
79250503Sobrien   reorg.c, since the branch splitting exposes new instructions with delay
79350503Sobrien   slots.  */
79450503Sobrien
79518334Spetervoid
796132727Skanshorten_branches (rtx first ATTRIBUTE_UNUSED)
79718334Speter{
79850503Sobrien  rtx insn;
79950503Sobrien  int max_uid;
80050503Sobrien  int i;
80150503Sobrien  int max_log;
80250503Sobrien  int max_skip;
80318334Speter#ifdef HAVE_ATTR_length
80450503Sobrien#define MAX_CODE_ALIGN 16
80550503Sobrien  rtx seq;
80618334Speter  int something_changed = 1;
80718334Speter  char *varying_length;
80818334Speter  rtx body;
80918334Speter  int uid;
81050503Sobrien  rtx align_tab[MAX_CODE_ALIGN];
81118334Speter
81250503Sobrien#endif
81318334Speter
81450503Sobrien  /* Compute maximum UID and allocate label_align / uid_shuid.  */
81550503Sobrien  max_uid = get_max_uid ();
81650503Sobrien
817169699Skan  /* Free uid_shuid before reallocating it.  */
818169699Skan  free (uid_shuid);
81950503Sobrien
820169699Skan  uid_shuid = XNEWVEC (int, max_uid);
821169699Skan
82290087Sobrien  if (max_labelno != max_label_num ())
82390087Sobrien    {
82490087Sobrien      int old = max_labelno;
82590087Sobrien      int n_labels;
82690087Sobrien      int n_old_labels;
82790087Sobrien
82890087Sobrien      max_labelno = max_label_num ();
82990087Sobrien
83090087Sobrien      n_labels = max_labelno - min_labelno + 1;
83190087Sobrien      n_old_labels = old - min_labelno + 1;
83290087Sobrien
833132727Skan      label_align = xrealloc (label_align,
834132727Skan			      n_labels * sizeof (struct label_alignment));
83590087Sobrien
836169699Skan      /* Range of labels grows monotonically in the function.  Failing here
83790087Sobrien         means that the initialization of array got lost.  */
838169699Skan      gcc_assert (n_old_labels <= n_labels);
83990087Sobrien
84090087Sobrien      memset (label_align + n_old_labels, 0,
84190087Sobrien	      (n_labels - n_old_labels) * sizeof (struct label_alignment));
84290087Sobrien    }
84390087Sobrien
84450503Sobrien  /* Initialize label_align and set up uid_shuid to be strictly
84550503Sobrien     monotonically rising with insn order.  */
84650503Sobrien  /* We use max_log here to keep track of the maximum alignment we want to
84750503Sobrien     impose on the next CODE_LABEL (or the current one if we are processing
84850503Sobrien     the CODE_LABEL itself).  */
84990087Sobrien
85050503Sobrien  max_log = 0;
85150503Sobrien  max_skip = 0;
85250503Sobrien
85350503Sobrien  for (insn = get_insns (), i = 1; insn; insn = NEXT_INSN (insn))
85450503Sobrien    {
85550503Sobrien      int log;
85650503Sobrien
85750503Sobrien      INSN_SHUID (insn) = i++;
85890087Sobrien      if (INSN_P (insn))
859169699Skan	continue;
860169699Skan
861169699Skan      if (LABEL_P (insn))
86250503Sobrien	{
86350503Sobrien	  rtx next;
86450503Sobrien
86590087Sobrien	  /* Merge in alignments computed by compute_alignments.  */
86690087Sobrien	  log = LABEL_TO_ALIGNMENT (insn);
86790087Sobrien	  if (max_log < log)
86890087Sobrien	    {
86990087Sobrien	      max_log = log;
87090087Sobrien	      max_skip = LABEL_TO_MAX_SKIP (insn);
87190087Sobrien	    }
87290087Sobrien
87350503Sobrien	  log = LABEL_ALIGN (insn);
87450503Sobrien	  if (max_log < log)
87550503Sobrien	    {
87650503Sobrien	      max_log = log;
87750503Sobrien	      max_skip = LABEL_ALIGN_MAX_SKIP;
87850503Sobrien	    }
879169699Skan	  next = next_nonnote_insn (insn);
88050503Sobrien	  /* ADDR_VECs only take room if read-only data goes into the text
88150503Sobrien	     section.  */
882169699Skan	  if (JUMP_TABLES_IN_TEXT_SECTION
883169699Skan	      || readonly_data_section == text_section)
884169699Skan	    if (next && JUMP_P (next))
88550503Sobrien	      {
88650503Sobrien		rtx nextbody = PATTERN (next);
88750503Sobrien		if (GET_CODE (nextbody) == ADDR_VEC
88850503Sobrien		    || GET_CODE (nextbody) == ADDR_DIFF_VEC)
88950503Sobrien		  {
89050503Sobrien		    log = ADDR_VEC_ALIGN (next);
89150503Sobrien		    if (max_log < log)
89250503Sobrien		      {
89350503Sobrien			max_log = log;
89450503Sobrien			max_skip = LABEL_ALIGN_MAX_SKIP;
89550503Sobrien		      }
89650503Sobrien		  }
89750503Sobrien	      }
89850503Sobrien	  LABEL_TO_ALIGNMENT (insn) = max_log;
89950503Sobrien	  LABEL_TO_MAX_SKIP (insn) = max_skip;
90050503Sobrien	  max_log = 0;
90150503Sobrien	  max_skip = 0;
90250503Sobrien	}
903169699Skan      else if (BARRIER_P (insn))
90450503Sobrien	{
90550503Sobrien	  rtx label;
90650503Sobrien
90790087Sobrien	  for (label = insn; label && ! INSN_P (label);
90850503Sobrien	       label = NEXT_INSN (label))
909169699Skan	    if (LABEL_P (label))
91050503Sobrien	      {
91150503Sobrien		log = LABEL_ALIGN_AFTER_BARRIER (insn);
91250503Sobrien		if (max_log < log)
91350503Sobrien		  {
91450503Sobrien		    max_log = log;
91550503Sobrien		    max_skip = LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP;
91650503Sobrien		  }
91750503Sobrien		break;
91850503Sobrien	      }
91950503Sobrien	}
92050503Sobrien    }
92150503Sobrien#ifdef HAVE_ATTR_length
92250503Sobrien
92350503Sobrien  /* Allocate the rest of the arrays.  */
924169699Skan  insn_lengths = XNEWVEC (int, max_uid);
92552515Sobrien  insn_lengths_max_uid = max_uid;
92650503Sobrien  /* Syntax errors can lead to labels being outside of the main insn stream.
92750503Sobrien     Initialize insn_addresses, so that we get reproducible results.  */
92890087Sobrien  INSN_ADDRESSES_ALLOC (max_uid);
92950503Sobrien
930169699Skan  varying_length = XCNEWVEC (char, max_uid);
93150503Sobrien
93250503Sobrien  /* Initialize uid_align.  We scan instructions
93350503Sobrien     from end to start, and keep in align_tab[n] the last seen insn
93450503Sobrien     that does an alignment of at least n+1, i.e. the successor
93550503Sobrien     in the alignment chain for an insn that does / has a known
93650503Sobrien     alignment of n.  */
937169699Skan  uid_align = XCNEWVEC (rtx, max_uid);
93850503Sobrien
93990087Sobrien  for (i = MAX_CODE_ALIGN; --i >= 0;)
94050503Sobrien    align_tab[i] = NULL_RTX;
94150503Sobrien  seq = get_last_insn ();
94250503Sobrien  for (; seq; seq = PREV_INSN (seq))
94350503Sobrien    {
94450503Sobrien      int uid = INSN_UID (seq);
94550503Sobrien      int log;
946169699Skan      log = (LABEL_P (seq) ? LABEL_TO_ALIGNMENT (seq) : 0);
94750503Sobrien      uid_align[uid] = align_tab[0];
94850503Sobrien      if (log)
94950503Sobrien	{
95050503Sobrien	  /* Found an alignment label.  */
95150503Sobrien	  uid_align[uid] = align_tab[log];
95250503Sobrien	  for (i = log - 1; i >= 0; i--)
95350503Sobrien	    align_tab[i] = seq;
95450503Sobrien	}
95550503Sobrien    }
95650503Sobrien#ifdef CASE_VECTOR_SHORTEN_MODE
95750503Sobrien  if (optimize)
95850503Sobrien    {
95950503Sobrien      /* Look for ADDR_DIFF_VECs, and initialize their minimum and maximum
96050503Sobrien         label fields.  */
96150503Sobrien
96250503Sobrien      int min_shuid = INSN_SHUID (get_insns ()) - 1;
96350503Sobrien      int max_shuid = INSN_SHUID (get_last_insn ()) + 1;
96450503Sobrien      int rel;
96550503Sobrien
96650503Sobrien      for (insn = first; insn != 0; insn = NEXT_INSN (insn))
96750503Sobrien	{
96850503Sobrien	  rtx min_lab = NULL_RTX, max_lab = NULL_RTX, pat;
96950503Sobrien	  int len, i, min, max, insn_shuid;
97050503Sobrien	  int min_align;
97150503Sobrien	  addr_diff_vec_flags flags;
97250503Sobrien
973169699Skan	  if (!JUMP_P (insn)
97450503Sobrien	      || GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC)
97550503Sobrien	    continue;
97650503Sobrien	  pat = PATTERN (insn);
97750503Sobrien	  len = XVECLEN (pat, 1);
978169699Skan	  gcc_assert (len > 0);
97950503Sobrien	  min_align = MAX_CODE_ALIGN;
98050503Sobrien	  for (min = max_shuid, max = min_shuid, i = len - 1; i >= 0; i--)
98150503Sobrien	    {
98250503Sobrien	      rtx lab = XEXP (XVECEXP (pat, 1, i), 0);
98350503Sobrien	      int shuid = INSN_SHUID (lab);
98450503Sobrien	      if (shuid < min)
98550503Sobrien		{
98650503Sobrien		  min = shuid;
98750503Sobrien		  min_lab = lab;
98850503Sobrien		}
98950503Sobrien	      if (shuid > max)
99050503Sobrien		{
99150503Sobrien		  max = shuid;
99250503Sobrien		  max_lab = lab;
99350503Sobrien		}
99450503Sobrien	      if (min_align > LABEL_TO_ALIGNMENT (lab))
99550503Sobrien		min_align = LABEL_TO_ALIGNMENT (lab);
99650503Sobrien	    }
997169699Skan	  XEXP (pat, 2) = gen_rtx_LABEL_REF (Pmode, min_lab);
998169699Skan	  XEXP (pat, 3) = gen_rtx_LABEL_REF (Pmode, max_lab);
99950503Sobrien	  insn_shuid = INSN_SHUID (insn);
100050503Sobrien	  rel = INSN_SHUID (XEXP (XEXP (pat, 0), 0));
1001169699Skan	  memset (&flags, 0, sizeof (flags));
100250503Sobrien	  flags.min_align = min_align;
100350503Sobrien	  flags.base_after_vec = rel > insn_shuid;
100450503Sobrien	  flags.min_after_vec  = min > insn_shuid;
100550503Sobrien	  flags.max_after_vec  = max > insn_shuid;
100650503Sobrien	  flags.min_after_base = min > rel;
100750503Sobrien	  flags.max_after_base = max > rel;
100850503Sobrien	  ADDR_DIFF_VEC_FLAGS (pat) = flags;
100950503Sobrien	}
101050503Sobrien    }
101150503Sobrien#endif /* CASE_VECTOR_SHORTEN_MODE */
101250503Sobrien
101318334Speter  /* Compute initial lengths, addresses, and varying flags for each insn.  */
1014132727Skan  for (insn_current_address = 0, insn = first;
101518334Speter       insn != 0;
101618334Speter       insn_current_address += insn_lengths[uid], insn = NEXT_INSN (insn))
101718334Speter    {
101818334Speter      uid = INSN_UID (insn);
101950503Sobrien
102050503Sobrien      insn_lengths[uid] = 0;
102150503Sobrien
1022169699Skan      if (LABEL_P (insn))
102350503Sobrien	{
102450503Sobrien	  int log = LABEL_TO_ALIGNMENT (insn);
102550503Sobrien	  if (log)
102650503Sobrien	    {
102750503Sobrien	      int align = 1 << log;
102850503Sobrien	      int new_address = (insn_current_address + align - 1) & -align;
102950503Sobrien	      insn_lengths[uid] = new_address - insn_current_address;
103050503Sobrien	    }
103150503Sobrien	}
103250503Sobrien
1033117404Skan      INSN_ADDRESSES (uid) = insn_current_address + insn_lengths[uid];
103490087Sobrien
1035169699Skan      if (NOTE_P (insn) || BARRIER_P (insn)
1036169699Skan	  || LABEL_P (insn))
103718334Speter	continue;
103850503Sobrien      if (INSN_DELETED_P (insn))
103950503Sobrien	continue;
104018334Speter
104118334Speter      body = PATTERN (insn);
104218334Speter      if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC)
104318334Speter	{
104418334Speter	  /* This only takes room if read-only data goes into the text
104518334Speter	     section.  */
1046169699Skan	  if (JUMP_TABLES_IN_TEXT_SECTION
1047169699Skan	      || readonly_data_section == text_section)
104850503Sobrien	    insn_lengths[uid] = (XVECLEN (body,
104950503Sobrien					  GET_CODE (body) == ADDR_DIFF_VEC)
105050503Sobrien				 * GET_MODE_SIZE (GET_MODE (body)));
105150503Sobrien	  /* Alignment is handled by ADDR_VEC_ALIGN.  */
105218334Speter	}
105390087Sobrien      else if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0)
105418334Speter	insn_lengths[uid] = asm_insn_count (body) * insn_default_length (insn);
105518334Speter      else if (GET_CODE (body) == SEQUENCE)
105618334Speter	{
105718334Speter	  int i;
105818334Speter	  int const_delay_slots;
105918334Speter#ifdef DELAY_SLOTS
106018334Speter	  const_delay_slots = const_num_delay_slots (XVECEXP (body, 0, 0));
106118334Speter#else
106218334Speter	  const_delay_slots = 0;
106318334Speter#endif
106418334Speter	  /* Inside a delay slot sequence, we do not do any branch shortening
106518334Speter	     if the shortening could change the number of delay slots
106650503Sobrien	     of the branch.  */
106718334Speter	  for (i = 0; i < XVECLEN (body, 0); i++)
106818334Speter	    {
106918334Speter	      rtx inner_insn = XVECEXP (body, 0, i);
107018334Speter	      int inner_uid = INSN_UID (inner_insn);
107118334Speter	      int inner_length;
107218334Speter
107390087Sobrien	      if (GET_CODE (body) == ASM_INPUT
107490087Sobrien		  || asm_noperands (PATTERN (XVECEXP (body, 0, i))) >= 0)
107518334Speter		inner_length = (asm_insn_count (PATTERN (inner_insn))
107618334Speter				* insn_default_length (inner_insn));
107718334Speter	      else
107818334Speter		inner_length = insn_default_length (inner_insn);
107990087Sobrien
108018334Speter	      insn_lengths[inner_uid] = inner_length;
108118334Speter	      if (const_delay_slots)
108218334Speter		{
108318334Speter		  if ((varying_length[inner_uid]
108418334Speter		       = insn_variable_length_p (inner_insn)) != 0)
108518334Speter		    varying_length[uid] = 1;
108690087Sobrien		  INSN_ADDRESSES (inner_uid) = (insn_current_address
108790087Sobrien						+ insn_lengths[uid]);
108818334Speter		}
108918334Speter	      else
109018334Speter		varying_length[inner_uid] = 0;
109118334Speter	      insn_lengths[uid] += inner_length;
109218334Speter	    }
109318334Speter	}
109418334Speter      else if (GET_CODE (body) != USE && GET_CODE (body) != CLOBBER)
109518334Speter	{
109618334Speter	  insn_lengths[uid] = insn_default_length (insn);
109718334Speter	  varying_length[uid] = insn_variable_length_p (insn);
109818334Speter	}
109918334Speter
110018334Speter      /* If needed, do any adjustment.  */
110118334Speter#ifdef ADJUST_INSN_LENGTH
110218334Speter      ADJUST_INSN_LENGTH (insn, insn_lengths[uid]);
110352515Sobrien      if (insn_lengths[uid] < 0)
110490087Sobrien	fatal_insn ("negative insn length", insn);
110518334Speter#endif
110618334Speter    }
110718334Speter
110818334Speter  /* Now loop over all the insns finding varying length insns.  For each,
110918334Speter     get the current insn length.  If it has changed, reflect the change.
111018334Speter     When nothing changes for a full pass, we are done.  */
111118334Speter
111218334Speter  while (something_changed)
111318334Speter    {
111418334Speter      something_changed = 0;
111550503Sobrien      insn_current_align = MAX_CODE_ALIGN - 1;
1116132727Skan      for (insn_current_address = 0, insn = first;
111718334Speter	   insn != 0;
111818334Speter	   insn = NEXT_INSN (insn))
111918334Speter	{
112018334Speter	  int new_length;
112150503Sobrien#ifdef ADJUST_INSN_LENGTH
112218334Speter	  int tmp_length;
112350503Sobrien#endif
112450503Sobrien	  int length_align;
112518334Speter
112618334Speter	  uid = INSN_UID (insn);
112750503Sobrien
1128169699Skan	  if (LABEL_P (insn))
112950503Sobrien	    {
113050503Sobrien	      int log = LABEL_TO_ALIGNMENT (insn);
113150503Sobrien	      if (log > insn_current_align)
113250503Sobrien		{
113350503Sobrien		  int align = 1 << log;
113450503Sobrien		  int new_address= (insn_current_address + align - 1) & -align;
113550503Sobrien		  insn_lengths[uid] = new_address - insn_current_address;
113650503Sobrien		  insn_current_align = log;
113750503Sobrien		  insn_current_address = new_address;
113850503Sobrien		}
113950503Sobrien	      else
114050503Sobrien		insn_lengths[uid] = 0;
114190087Sobrien	      INSN_ADDRESSES (uid) = insn_current_address;
114250503Sobrien	      continue;
114350503Sobrien	    }
114450503Sobrien
114550503Sobrien	  length_align = INSN_LENGTH_ALIGNMENT (insn);
114650503Sobrien	  if (length_align < insn_current_align)
114750503Sobrien	    insn_current_align = length_align;
114850503Sobrien
114990087Sobrien	  insn_last_address = INSN_ADDRESSES (uid);
115090087Sobrien	  INSN_ADDRESSES (uid) = insn_current_address;
115150503Sobrien
115250503Sobrien#ifdef CASE_VECTOR_SHORTEN_MODE
1153169699Skan	  if (optimize && JUMP_P (insn)
115450503Sobrien	      && GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
115518334Speter	    {
115650503Sobrien	      rtx body = PATTERN (insn);
115750503Sobrien	      int old_length = insn_lengths[uid];
115850503Sobrien	      rtx rel_lab = XEXP (XEXP (body, 0), 0);
115950503Sobrien	      rtx min_lab = XEXP (XEXP (body, 2), 0);
116050503Sobrien	      rtx max_lab = XEXP (XEXP (body, 3), 0);
116190087Sobrien	      int rel_addr = INSN_ADDRESSES (INSN_UID (rel_lab));
116290087Sobrien	      int min_addr = INSN_ADDRESSES (INSN_UID (min_lab));
116390087Sobrien	      int max_addr = INSN_ADDRESSES (INSN_UID (max_lab));
116450503Sobrien	      rtx prev;
116550503Sobrien	      int rel_align = 0;
116690087Sobrien	      addr_diff_vec_flags flags;
116750503Sobrien
116890087Sobrien	      /* Avoid automatic aggregate initialization.  */
116990087Sobrien	      flags = ADDR_DIFF_VEC_FLAGS (body);
117090087Sobrien
117150503Sobrien	      /* Try to find a known alignment for rel_lab.  */
117250503Sobrien	      for (prev = rel_lab;
117350503Sobrien		   prev
117450503Sobrien		   && ! insn_lengths[INSN_UID (prev)]
117550503Sobrien		   && ! (varying_length[INSN_UID (prev)] & 1);
117650503Sobrien		   prev = PREV_INSN (prev))
117750503Sobrien		if (varying_length[INSN_UID (prev)] & 2)
117850503Sobrien		  {
117950503Sobrien		    rel_align = LABEL_TO_ALIGNMENT (prev);
118050503Sobrien		    break;
118150503Sobrien		  }
118250503Sobrien
118350503Sobrien	      /* See the comment on addr_diff_vec_flags in rtl.h for the
118450503Sobrien		 meaning of the flags values.  base: REL_LAB   vec: INSN  */
118550503Sobrien	      /* Anything after INSN has still addresses from the last
118650503Sobrien		 pass; adjust these so that they reflect our current
118750503Sobrien		 estimate for this pass.  */
118850503Sobrien	      if (flags.base_after_vec)
118950503Sobrien		rel_addr += insn_current_address - insn_last_address;
119050503Sobrien	      if (flags.min_after_vec)
119150503Sobrien		min_addr += insn_current_address - insn_last_address;
119250503Sobrien	      if (flags.max_after_vec)
119350503Sobrien		max_addr += insn_current_address - insn_last_address;
119450503Sobrien	      /* We want to know the worst case, i.e. lowest possible value
119550503Sobrien		 for the offset of MIN_LAB.  If MIN_LAB is after REL_LAB,
119650503Sobrien		 its offset is positive, and we have to be wary of code shrink;
119750503Sobrien		 otherwise, it is negative, and we have to be vary of code
119850503Sobrien		 size increase.  */
119950503Sobrien	      if (flags.min_after_base)
120050503Sobrien		{
120150503Sobrien		  /* If INSN is between REL_LAB and MIN_LAB, the size
120250503Sobrien		     changes we are about to make can change the alignment
120350503Sobrien		     within the observed offset, therefore we have to break
120450503Sobrien		     it up into two parts that are independent.  */
120550503Sobrien		  if (! flags.base_after_vec && flags.min_after_vec)
120650503Sobrien		    {
120750503Sobrien		      min_addr -= align_fuzz (rel_lab, insn, rel_align, 0);
120850503Sobrien		      min_addr -= align_fuzz (insn, min_lab, 0, 0);
120950503Sobrien		    }
121050503Sobrien		  else
121150503Sobrien		    min_addr -= align_fuzz (rel_lab, min_lab, rel_align, 0);
121250503Sobrien		}
121350503Sobrien	      else
121450503Sobrien		{
121550503Sobrien		  if (flags.base_after_vec && ! flags.min_after_vec)
121650503Sobrien		    {
121750503Sobrien		      min_addr -= align_fuzz (min_lab, insn, 0, ~0);
121850503Sobrien		      min_addr -= align_fuzz (insn, rel_lab, 0, ~0);
121950503Sobrien		    }
122050503Sobrien		  else
122150503Sobrien		    min_addr -= align_fuzz (min_lab, rel_lab, 0, ~0);
122250503Sobrien		}
122350503Sobrien	      /* Likewise, determine the highest lowest possible value
122450503Sobrien		 for the offset of MAX_LAB.  */
122550503Sobrien	      if (flags.max_after_base)
122650503Sobrien		{
122750503Sobrien		  if (! flags.base_after_vec && flags.max_after_vec)
122850503Sobrien		    {
122950503Sobrien		      max_addr += align_fuzz (rel_lab, insn, rel_align, ~0);
123050503Sobrien		      max_addr += align_fuzz (insn, max_lab, 0, ~0);
123150503Sobrien		    }
123250503Sobrien		  else
123350503Sobrien		    max_addr += align_fuzz (rel_lab, max_lab, rel_align, ~0);
123450503Sobrien		}
123550503Sobrien	      else
123650503Sobrien		{
123750503Sobrien		  if (flags.base_after_vec && ! flags.max_after_vec)
123850503Sobrien		    {
123950503Sobrien		      max_addr += align_fuzz (max_lab, insn, 0, 0);
124050503Sobrien		      max_addr += align_fuzz (insn, rel_lab, 0, 0);
124150503Sobrien		    }
124250503Sobrien		  else
124350503Sobrien		    max_addr += align_fuzz (max_lab, rel_lab, 0, 0);
124450503Sobrien		}
124550503Sobrien	      PUT_MODE (body, CASE_VECTOR_SHORTEN_MODE (min_addr - rel_addr,
124650503Sobrien							max_addr - rel_addr,
124750503Sobrien							body));
1248169699Skan	      if (JUMP_TABLES_IN_TEXT_SECTION
1249169699Skan		  || readonly_data_section == text_section)
125050503Sobrien		{
125150503Sobrien		  insn_lengths[uid]
125250503Sobrien		    = (XVECLEN (body, 1) * GET_MODE_SIZE (GET_MODE (body)));
125350503Sobrien		  insn_current_address += insn_lengths[uid];
125450503Sobrien		  if (insn_lengths[uid] != old_length)
125550503Sobrien		    something_changed = 1;
125650503Sobrien		}
125750503Sobrien
125850503Sobrien	      continue;
125950503Sobrien	    }
126050503Sobrien#endif /* CASE_VECTOR_SHORTEN_MODE */
126150503Sobrien
126250503Sobrien	  if (! (varying_length[uid]))
126350503Sobrien	    {
1264169699Skan	      if (NONJUMP_INSN_P (insn)
126590087Sobrien		  && GET_CODE (PATTERN (insn)) == SEQUENCE)
126690087Sobrien		{
126790087Sobrien		  int i;
126890087Sobrien
126990087Sobrien		  body = PATTERN (insn);
127090087Sobrien		  for (i = 0; i < XVECLEN (body, 0); i++)
127190087Sobrien		    {
127290087Sobrien		      rtx inner_insn = XVECEXP (body, 0, i);
127390087Sobrien		      int inner_uid = INSN_UID (inner_insn);
127490087Sobrien
127590087Sobrien		      INSN_ADDRESSES (inner_uid) = insn_current_address;
127690087Sobrien
127790087Sobrien		      insn_current_address += insn_lengths[inner_uid];
127890087Sobrien		    }
1279117404Skan		}
128090087Sobrien	      else
128190087Sobrien		insn_current_address += insn_lengths[uid];
128290087Sobrien
128318334Speter	      continue;
128418334Speter	    }
128590087Sobrien
1286169699Skan	  if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE)
128718334Speter	    {
128818334Speter	      int i;
128990087Sobrien
129018334Speter	      body = PATTERN (insn);
129118334Speter	      new_length = 0;
129218334Speter	      for (i = 0; i < XVECLEN (body, 0); i++)
129318334Speter		{
129418334Speter		  rtx inner_insn = XVECEXP (body, 0, i);
129518334Speter		  int inner_uid = INSN_UID (inner_insn);
129618334Speter		  int inner_length;
129718334Speter
129890087Sobrien		  INSN_ADDRESSES (inner_uid) = insn_current_address;
129918334Speter
130018334Speter		  /* insn_current_length returns 0 for insns with a
130118334Speter		     non-varying length.  */
130218334Speter		  if (! varying_length[inner_uid])
130318334Speter		    inner_length = insn_lengths[inner_uid];
130418334Speter		  else
130518334Speter		    inner_length = insn_current_length (inner_insn);
130618334Speter
130718334Speter		  if (inner_length != insn_lengths[inner_uid])
130818334Speter		    {
130918334Speter		      insn_lengths[inner_uid] = inner_length;
131018334Speter		      something_changed = 1;
131118334Speter		    }
131218334Speter		  insn_current_address += insn_lengths[inner_uid];
131318334Speter		  new_length += inner_length;
131418334Speter		}
131518334Speter	    }
131618334Speter	  else
131718334Speter	    {
131818334Speter	      new_length = insn_current_length (insn);
131918334Speter	      insn_current_address += new_length;
132018334Speter	    }
132118334Speter
132218334Speter#ifdef ADJUST_INSN_LENGTH
132318334Speter	  /* If needed, do any adjustment.  */
132418334Speter	  tmp_length = new_length;
132518334Speter	  ADJUST_INSN_LENGTH (insn, new_length);
132618334Speter	  insn_current_address += (new_length - tmp_length);
132718334Speter#endif
132818334Speter
132918334Speter	  if (new_length != insn_lengths[uid])
133018334Speter	    {
133118334Speter	      insn_lengths[uid] = new_length;
133218334Speter	      something_changed = 1;
133318334Speter	    }
133418334Speter	}
133518334Speter      /* For a non-optimizing compile, do only a single pass.  */
133618334Speter      if (!optimize)
133718334Speter	break;
133818334Speter    }
133950503Sobrien
134050503Sobrien  free (varying_length);
134150503Sobrien
134218334Speter#endif /* HAVE_ATTR_length */
134318334Speter}
134418334Speter
134518334Speter#ifdef HAVE_ATTR_length
134618334Speter/* Given the body of an INSN known to be generated by an ASM statement, return
134718334Speter   the number of machine instructions likely to be generated for this insn.
134818334Speter   This is used to compute its length.  */
134918334Speter
135018334Speterstatic int
1351132727Skanasm_insn_count (rtx body)
135218334Speter{
135390087Sobrien  const char *template;
135418334Speter  int count = 1;
135518334Speter
135618334Speter  if (GET_CODE (body) == ASM_INPUT)
135718334Speter    template = XSTR (body, 0);
135818334Speter  else
135990087Sobrien    template = decode_asm_operands (body, NULL, NULL, NULL, NULL);
136018334Speter
136190087Sobrien  for (; *template; template++)
136290087Sobrien    if (IS_ASM_LOGICAL_LINE_SEPARATOR (*template) || *template == '\n')
136318334Speter      count++;
136418334Speter
136518334Speter  return count;
136618334Speter}
136718334Speter#endif
136818334Speter
136918334Speter/* Output assembler code for the start of a function,
137018334Speter   and initialize some of the variables in this file
137118334Speter   for the new function.  The label for the function and associated
137218334Speter   assembler pseudo-ops have already been output in `assemble_start_function'.
137318334Speter
137418334Speter   FIRST is the first insn of the rtl for the function being compiled.
137518334Speter   FILE is the file to write assembler code to.
137618334Speter   OPTIMIZE is nonzero if we should eliminate redundant
137718334Speter     test and compare insns.  */
137818334Speter
137918334Spetervoid
1380132727Skanfinal_start_function (rtx first ATTRIBUTE_UNUSED, FILE *file,
1381132727Skan		      int optimize ATTRIBUTE_UNUSED)
138218334Speter{
138318334Speter  block_depth = 0;
138418334Speter
138518334Speter  this_is_asm_operands = 0;
138618334Speter
1387132727Skan  last_filename = locator_file (prologue_locator);
1388132727Skan  last_linenum = locator_line (prologue_locator);
138918334Speter
139090087Sobrien  high_block_linenum = high_function_linenum = last_linenum;
139118334Speter
139290087Sobrien  (*debug_hooks->begin_prologue) (last_linenum, last_filename);
139350503Sobrien
1394169699Skan#if defined (DWARF2_UNWIND_INFO) || defined (TARGET_UNWIND_INFO)
139590087Sobrien  if (write_symbols != DWARF2_DEBUG && write_symbols != VMS_AND_DWARF2_DEBUG)
139690087Sobrien    dwarf2out_begin_prologue (0, NULL);
139718334Speter#endif
139818334Speter
139918334Speter#ifdef LEAF_REG_REMAP
140052515Sobrien  if (current_function_uses_only_leaf_regs)
140118334Speter    leaf_renumber_regs (first);
140218334Speter#endif
140318334Speter
140418334Speter  /* The Sun386i and perhaps other machines don't work right
140518334Speter     if the profiling code comes after the prologue.  */
140618334Speter#ifdef PROFILE_BEFORE_PROLOGUE
140790087Sobrien  if (current_function_profile)
140818334Speter    profile_function (file);
140918334Speter#endif /* PROFILE_BEFORE_PROLOGUE */
141018334Speter
141150503Sobrien#if defined (DWARF2_UNWIND_INFO) && defined (HAVE_prologue)
141250503Sobrien  if (dwarf2out_do_frame ())
1413169699Skan    dwarf2out_frame_debug (NULL_RTX, false);
141450503Sobrien#endif
141550503Sobrien
141690087Sobrien  /* If debugging, assign block numbers to all of the blocks in this
141790087Sobrien     function.  */
141890087Sobrien  if (write_symbols)
141990087Sobrien    {
1420132727Skan      reemit_insn_block_notes ();
142190087Sobrien      number_blocks (current_function_decl);
142290087Sobrien      /* We never actually put out begin/end notes for the top-level
142390087Sobrien	 block in the function.  But, conceptually, that block is
142490087Sobrien	 always needed.  */
142590087Sobrien      TREE_ASM_WRITTEN (DECL_INITIAL (current_function_decl)) = 1;
142690087Sobrien    }
142790087Sobrien
142818334Speter  /* First output the function prologue: code to set up the stack frame.  */
1429169699Skan  targetm.asm_out.function_prologue (file, get_frame_size ());
143018334Speter
143118334Speter  /* If the machine represents the prologue as RTL, the profiling code must
143218334Speter     be emitted when NOTE_INSN_PROLOGUE_END is scanned.  */
143318334Speter#ifdef HAVE_prologue
143418334Speter  if (! HAVE_prologue)
143518334Speter#endif
143618334Speter    profile_after_prologue (file);
143718334Speter}
143818334Speter
143918334Speterstatic void
1440132727Skanprofile_after_prologue (FILE *file ATTRIBUTE_UNUSED)
144118334Speter{
144218334Speter#ifndef PROFILE_BEFORE_PROLOGUE
144390087Sobrien  if (current_function_profile)
144418334Speter    profile_function (file);
144518334Speter#endif /* not PROFILE_BEFORE_PROLOGUE */
144618334Speter}
144718334Speter
144818334Speterstatic void
1449132727Skanprofile_function (FILE *file ATTRIBUTE_UNUSED)
145018334Speter{
145174478Sobrien#ifndef NO_PROFILE_COUNTERS
1452132727Skan# define NO_PROFILE_COUNTERS	0
145374478Sobrien#endif
145450503Sobrien#if defined(ASM_OUTPUT_REG_PUSH)
145518334Speter  int sval = current_function_returns_struct;
1456132727Skan  rtx svrtx = targetm.calls.struct_value_rtx (TREE_TYPE (current_function_decl), 1);
145750503Sobrien#if defined(STATIC_CHAIN_INCOMING_REGNUM) || defined(STATIC_CHAIN_REGNUM)
1458169699Skan  int cxt = cfun->static_chain_decl != NULL;
145950503Sobrien#endif
146050503Sobrien#endif /* ASM_OUTPUT_REG_PUSH */
146118334Speter
1462132727Skan  if (! NO_PROFILE_COUNTERS)
1463132727Skan    {
1464132727Skan      int align = MIN (BIGGEST_ALIGNMENT, LONG_TYPE_SIZE);
1465169699Skan      switch_to_section (data_section);
1466132727Skan      ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));
1467169699Skan      targetm.asm_out.internal_label (file, "LP", current_function_funcdef_no);
1468132727Skan      assemble_integer (const0_rtx, LONG_TYPE_SIZE / BITS_PER_UNIT, align, 1);
1469132727Skan    }
147018334Speter
1471169699Skan  switch_to_section (current_function_section ());
147218334Speter
1473132727Skan#if defined(ASM_OUTPUT_REG_PUSH)
1474169699Skan  if (sval && svrtx != NULL_RTX && REG_P (svrtx))
1475132727Skan    ASM_OUTPUT_REG_PUSH (file, REGNO (svrtx));
147618334Speter#endif
147718334Speter
147850503Sobrien#if defined(STATIC_CHAIN_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
147918334Speter  if (cxt)
148018334Speter    ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_INCOMING_REGNUM);
148118334Speter#else
148250503Sobrien#if defined(STATIC_CHAIN_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
148318334Speter  if (cxt)
148450503Sobrien    {
148550503Sobrien      ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_REGNUM);
148650503Sobrien    }
148718334Speter#endif
148818334Speter#endif
148918334Speter
1490117404Skan  FUNCTION_PROFILER (file, current_function_funcdef_no);
149118334Speter
149250503Sobrien#if defined(STATIC_CHAIN_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
149318334Speter  if (cxt)
149418334Speter    ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_INCOMING_REGNUM);
149518334Speter#else
149650503Sobrien#if defined(STATIC_CHAIN_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
149718334Speter  if (cxt)
149850503Sobrien    {
149950503Sobrien      ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_REGNUM);
150050503Sobrien    }
150118334Speter#endif
150218334Speter#endif
150318334Speter
1504132727Skan#if defined(ASM_OUTPUT_REG_PUSH)
1505169699Skan  if (sval && svrtx != NULL_RTX && REG_P (svrtx))
1506132727Skan    ASM_OUTPUT_REG_POP (file, REGNO (svrtx));
150718334Speter#endif
150818334Speter}
150918334Speter
151018334Speter/* Output assembler code for the end of a function.
151118334Speter   For clarity, args are same as those of `final_start_function'
151218334Speter   even though not all of them are needed.  */
151318334Speter
151418334Spetervoid
1515132727Skanfinal_end_function (void)
151618334Speter{
151790087Sobrien  app_disable ();
151818334Speter
151990087Sobrien  (*debug_hooks->end_function) (high_function_linenum);
152018334Speter
152118334Speter  /* Finally, output the function epilogue:
152218334Speter     code to restore the stack frame and return to the caller.  */
1523169699Skan  targetm.asm_out.function_epilogue (asm_out_file, get_frame_size ());
152418334Speter
152590087Sobrien  /* And debug output.  */
1526117404Skan  (*debug_hooks->end_epilogue) (last_linenum, last_filename);
152790087Sobrien
152890087Sobrien#if defined (DWARF2_UNWIND_INFO)
152990087Sobrien  if (write_symbols != DWARF2_DEBUG && write_symbols != VMS_AND_DWARF2_DEBUG
153090087Sobrien      && dwarf2out_do_frame ())
1531117404Skan    dwarf2out_end_epilogue (last_linenum, last_filename);
153250503Sobrien#endif
153318334Speter}
153418334Speter
153518334Speter/* Output assembler code for some insns: all or part of a function.
1536169699Skan   For description of args, see `final_start_function', above.  */
153718334Speter
153818334Spetervoid
1539169699Skanfinal (rtx first, FILE *file, int optimize)
154018334Speter{
154190087Sobrien  rtx insn;
154250503Sobrien  int max_uid = 0;
1543132727Skan  int seen = 0;
154418334Speter
154518334Speter  last_ignored_compare = 0;
154618334Speter
1547132727Skan#ifdef SDB_DEBUGGING_INFO
1548132727Skan  /* When producing SDB debugging info, delete troublesome line number
154918334Speter     notes from inlined functions in other files as well as duplicate
155018334Speter     line number notes.  */
155118334Speter  if (write_symbols == SDB_DEBUG)
155218334Speter    {
155318334Speter      rtx last = 0;
155418334Speter      for (insn = first; insn; insn = NEXT_INSN (insn))
1555169699Skan	if (NOTE_P (insn) && NOTE_LINE_NUMBER (insn) > 0)
155618334Speter	  {
1557169699Skan	    if (last != 0
1558169699Skan#ifdef USE_MAPPED_LOCATION
1559169699Skan		&& NOTE_SOURCE_LOCATION (insn) == NOTE_SOURCE_LOCATION (last)
1560169699Skan#else
1561169699Skan		&& NOTE_LINE_NUMBER (insn) == NOTE_LINE_NUMBER (last)
1562169699Skan		&& NOTE_SOURCE_FILE (insn) == NOTE_SOURCE_FILE (last)
1563169699Skan#endif
1564169699Skan	      )
156518334Speter	      {
156690087Sobrien		delete_insn (insn);	/* Use delete_note.  */
156718334Speter		continue;
156818334Speter	      }
156918334Speter	    last = insn;
157018334Speter	  }
157118334Speter    }
157218334Speter#endif
157318334Speter
157418334Speter  for (insn = first; insn; insn = NEXT_INSN (insn))
157550503Sobrien    {
1576132727Skan      if (INSN_UID (insn) > max_uid)       /* Find largest UID.  */
157790087Sobrien	max_uid = INSN_UID (insn);
157852515Sobrien#ifdef HAVE_cc0
157952515Sobrien      /* If CC tracking across branches is enabled, record the insn which
158052515Sobrien	 jumps to each branch only reached from one place.  */
1581169699Skan      if (optimize && JUMP_P (insn))
158252515Sobrien	{
158352515Sobrien	  rtx lab = JUMP_LABEL (insn);
158452515Sobrien	  if (lab && LABEL_NUSES (lab) == 1)
158552515Sobrien	    {
158652515Sobrien	      LABEL_REFS (lab) = insn;
158752515Sobrien	    }
158852515Sobrien	}
158952515Sobrien#endif
159050503Sobrien    }
159118334Speter
159218334Speter  init_recog ();
159318334Speter
159418334Speter  CC_STATUS_INIT;
159518334Speter
159618334Speter  /* Output the insns.  */
159718334Speter  for (insn = NEXT_INSN (first); insn;)
159850503Sobrien    {
159950503Sobrien#ifdef HAVE_ATTR_length
160090087Sobrien      if ((unsigned) INSN_UID (insn) >= INSN_ADDRESSES_SIZE ())
160190087Sobrien	{
160290087Sobrien	  /* This can be triggered by bugs elsewhere in the compiler if
160390087Sobrien	     new insns are created after init_insn_lengths is called.  */
1604169699Skan	  gcc_assert (NOTE_P (insn));
1605169699Skan	  insn_current_address = -1;
160690087Sobrien	}
160790087Sobrien      else
160890087Sobrien	insn_current_address = INSN_ADDRESSES (INSN_UID (insn));
160990087Sobrien#endif /* HAVE_ATTR_length */
161090087Sobrien
1611169699Skan      insn = final_scan_insn (insn, file, optimize, 0, &seen);
161250503Sobrien    }
161390087Sobrien}
161490087Sobrien
161590087Sobrienconst char *
1616132727Skanget_insn_template (int code, rtx insn)
161790087Sobrien{
161890087Sobrien  switch (insn_data[code].output_format)
161990087Sobrien    {
162090087Sobrien    case INSN_OUTPUT_FORMAT_SINGLE:
1621132727Skan      return insn_data[code].output.single;
162290087Sobrien    case INSN_OUTPUT_FORMAT_MULTI:
1623132727Skan      return insn_data[code].output.multi[which_alternative];
162490087Sobrien    case INSN_OUTPUT_FORMAT_FUNCTION:
1625169699Skan      gcc_assert (insn);
1626132727Skan      return (*insn_data[code].output.function) (recog_data.operand, insn);
162750503Sobrien
162890087Sobrien    default:
1629169699Skan      gcc_unreachable ();
163090087Sobrien    }
163118334Speter}
163290087Sobrien
1633117404Skan/* Emit the appropriate declaration for an alternate-entry-point
1634117404Skan   symbol represented by INSN, to FILE.  INSN is a CODE_LABEL with
1635117404Skan   LABEL_KIND != LABEL_NORMAL.
1636117404Skan
1637117404Skan   The case fall-through in this function is intentional.  */
1638117404Skanstatic void
1639132727Skanoutput_alternate_entry_point (FILE *file, rtx insn)
1640117404Skan{
1641117404Skan  const char *name = LABEL_NAME (insn);
1642117404Skan
1643117404Skan  switch (LABEL_KIND (insn))
1644117404Skan    {
1645117404Skan    case LABEL_WEAK_ENTRY:
1646117404Skan#ifdef ASM_WEAKEN_LABEL
1647117404Skan      ASM_WEAKEN_LABEL (file, name);
1648117404Skan#endif
1649117404Skan    case LABEL_GLOBAL_ENTRY:
1650169699Skan      targetm.asm_out.globalize_label (file, name);
1651117404Skan    case LABEL_STATIC_ENTRY:
1652117404Skan#ifdef ASM_OUTPUT_TYPE_DIRECTIVE
1653117404Skan      ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function");
1654117404Skan#endif
1655117404Skan      ASM_OUTPUT_LABEL (file, name);
1656117404Skan      break;
1657117404Skan
1658117404Skan    case LABEL_NORMAL:
1659117404Skan    default:
1660169699Skan      gcc_unreachable ();
1661117404Skan    }
1662117404Skan}
1663117404Skan
166418334Speter/* The final scan for one insn, INSN.
166518334Speter   Args are same as in `final', except that INSN
166618334Speter   is the insn being scanned.
166718334Speter   Value returned is the next insn to be scanned.
166818334Speter
166918334Speter   NOPEEPHOLES is the flag to disallow peephole processing (currently
1670132727Skan   used for within delayed branch sequence output).
167118334Speter
1672132727Skan   SEEN is used to track the end of the prologue, for emitting
1673132727Skan   debug information.  We force the emission of a line note after
1674132727Skan   both NOTE_INSN_PROLOGUE_END and NOTE_INSN_FUNCTION_BEG, or
1675132727Skan   at the beginning of the second basic block, whichever comes
1676132727Skan   first.  */
1677132727Skan
167818334Speterrtx
1679132727Skanfinal_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
1680169699Skan		 int nopeepholes ATTRIBUTE_UNUSED, int *seen)
168118334Speter{
168250503Sobrien#ifdef HAVE_cc0
168350503Sobrien  rtx set;
168450503Sobrien#endif
1685169699Skan  rtx next;
168650503Sobrien
168718334Speter  insn_counter++;
168818334Speter
168918334Speter  /* Ignore deleted insns.  These can occur when we split insns (due to a
169018334Speter     template of "#") while not optimizing.  */
169118334Speter  if (INSN_DELETED_P (insn))
169218334Speter    return NEXT_INSN (insn);
169318334Speter
169418334Speter  switch (GET_CODE (insn))
169518334Speter    {
169618334Speter    case NOTE:
169790087Sobrien      switch (NOTE_LINE_NUMBER (insn))
169818334Speter	{
169990087Sobrien	case NOTE_INSN_DELETED:
170090087Sobrien	case NOTE_INSN_FUNCTION_END:
170190087Sobrien	case NOTE_INSN_REPEATED_LINE_NUMBER:
170290087Sobrien	case NOTE_INSN_EXPECTED_VALUE:
170318334Speter	  break;
170418334Speter
1705169699Skan	case NOTE_INSN_SWITCH_TEXT_SECTIONS:
1706169699Skan	  in_cold_section_p = !in_cold_section_p;
1707169699Skan	  (*debug_hooks->switch_text_section) ();
1708169699Skan	  switch_to_section (current_function_section ());
1709169699Skan	  break;
1710169699Skan
171190087Sobrien	case NOTE_INSN_BASIC_BLOCK:
1712169699Skan#ifdef TARGET_UNWIND_INFO
1713169699Skan	  targetm.asm_out.unwind_emit (asm_out_file, insn);
171450503Sobrien#endif
1715169699Skan
171690087Sobrien	  if (flag_debug_asm)
171790087Sobrien	    fprintf (asm_out_file, "\t%s basic block %d\n",
171890087Sobrien		     ASM_COMMENT_START, NOTE_BASIC_BLOCK (insn)->index);
1719132727Skan
1720132727Skan	  if ((*seen & (SEEN_EMITTED | SEEN_BB)) == SEEN_BB)
1721132727Skan	    {
1722132727Skan	      *seen |= SEEN_EMITTED;
1723169699Skan	      force_source_line = true;
1724132727Skan	    }
1725132727Skan	  else
1726132727Skan	    *seen |= SEEN_BB;
1727132727Skan
172850503Sobrien	  break;
172950503Sobrien
173090087Sobrien	case NOTE_INSN_EH_REGION_BEG:
173190087Sobrien	  ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LEHB",
173290087Sobrien				  NOTE_EH_HANDLER (insn));
173390087Sobrien	  break;
173490087Sobrien
173590087Sobrien	case NOTE_INSN_EH_REGION_END:
173690087Sobrien	  ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LEHE",
173790087Sobrien				  NOTE_EH_HANDLER (insn));
173890087Sobrien	  break;
173990087Sobrien
174090087Sobrien	case NOTE_INSN_PROLOGUE_END:
1741169699Skan	  targetm.asm_out.function_end_prologue (file);
174218334Speter	  profile_after_prologue (file);
1743132727Skan
1744132727Skan	  if ((*seen & (SEEN_EMITTED | SEEN_NOTE)) == SEEN_NOTE)
1745132727Skan	    {
1746132727Skan	      *seen |= SEEN_EMITTED;
1747169699Skan	      force_source_line = true;
1748132727Skan	    }
1749132727Skan	  else
1750132727Skan	    *seen |= SEEN_NOTE;
1751132727Skan
175218334Speter	  break;
175318334Speter
175490087Sobrien	case NOTE_INSN_EPILOGUE_BEG:
1755169699Skan	  targetm.asm_out.function_begin_epilogue (file);
175618334Speter	  break;
175718334Speter
175890087Sobrien	case NOTE_INSN_FUNCTION_BEG:
175990087Sobrien	  app_disable ();
1760117404Skan	  (*debug_hooks->end_prologue) (last_linenum, last_filename);
1761132727Skan
1762132727Skan	  if ((*seen & (SEEN_EMITTED | SEEN_NOTE)) == SEEN_NOTE)
1763132727Skan	    {
1764132727Skan	      *seen |= SEEN_EMITTED;
1765169699Skan	      force_source_line = true;
1766132727Skan	    }
1767132727Skan	  else
1768132727Skan	    *seen |= SEEN_NOTE;
1769132727Skan
177018334Speter	  break;
177190087Sobrien
177290087Sobrien	case NOTE_INSN_BLOCK_BEG:
177390087Sobrien	  if (debug_info_level == DINFO_LEVEL_NORMAL
177418334Speter	      || debug_info_level == DINFO_LEVEL_VERBOSE
177590087Sobrien	      || write_symbols == DWARF2_DEBUG
177690087Sobrien	      || write_symbols == VMS_AND_DWARF2_DEBUG
177790087Sobrien	      || write_symbols == VMS_DEBUG)
177890087Sobrien	    {
177990087Sobrien	      int n = BLOCK_NUMBER (NOTE_BLOCK (insn));
178018334Speter
178190087Sobrien	      app_disable ();
178290087Sobrien	      ++block_depth;
178390087Sobrien	      high_block_linenum = last_linenum;
178490087Sobrien
178590087Sobrien	      /* Output debugging info about the symbol-block beginning.  */
178690087Sobrien	      (*debug_hooks->begin_block) (last_linenum, n);
178790087Sobrien
178890087Sobrien	      /* Mark this block as output.  */
178990087Sobrien	      TREE_ASM_WRITTEN (NOTE_BLOCK (insn)) = 1;
179018334Speter	    }
179190087Sobrien	  break;
179218334Speter
179390087Sobrien	case NOTE_INSN_BLOCK_END:
179490087Sobrien	  if (debug_info_level == DINFO_LEVEL_NORMAL
179590087Sobrien	      || debug_info_level == DINFO_LEVEL_VERBOSE
179690087Sobrien	      || write_symbols == DWARF2_DEBUG
179790087Sobrien	      || write_symbols == VMS_AND_DWARF2_DEBUG
179890087Sobrien	      || write_symbols == VMS_DEBUG)
179990087Sobrien	    {
180090087Sobrien	      int n = BLOCK_NUMBER (NOTE_BLOCK (insn));
180118334Speter
180290087Sobrien	      app_disable ();
180318334Speter
180490087Sobrien	      /* End of a symbol-block.  */
180590087Sobrien	      --block_depth;
1806169699Skan	      gcc_assert (block_depth >= 0);
180718334Speter
180890087Sobrien	      (*debug_hooks->end_block) (high_block_linenum, n);
180990087Sobrien	    }
181090087Sobrien	  break;
181118334Speter
181290087Sobrien	case NOTE_INSN_DELETED_LABEL:
181390087Sobrien	  /* Emit the label.  We may have deleted the CODE_LABEL because
181490087Sobrien	     the label could be proved to be unreachable, though still
181590087Sobrien	     referenced (in the form of having its address taken.  */
181690087Sobrien	  ASM_OUTPUT_DEBUG_LABEL (file, "L", CODE_LABEL_NUMBER (insn));
181790087Sobrien	  break;
181818334Speter
1819169699Skan	case NOTE_INSN_VAR_LOCATION:
1820169699Skan	  (*debug_hooks->var_location) (insn);
1821169699Skan	  break;
1822169699Skan
182390087Sobrien	case 0:
182490087Sobrien	  break;
182518334Speter
182690087Sobrien	default:
1827169699Skan	  gcc_assert (NOTE_LINE_NUMBER (insn) > 0);
182890087Sobrien	  break;
182918334Speter	}
183018334Speter      break;
183118334Speter
183218334Speter    case BARRIER:
183390087Sobrien#if defined (DWARF2_UNWIND_INFO)
183490087Sobrien      if (dwarf2out_do_frame ())
1835169699Skan	dwarf2out_frame_debug (insn, false);
183618334Speter#endif
183718334Speter      break;
183818334Speter
183918334Speter    case CODE_LABEL:
184050503Sobrien      /* The target port might emit labels in the output function for
184150503Sobrien	 some insn, e.g. sh.c output_branchy_insn.  */
184250503Sobrien      if (CODE_LABEL_NUMBER (insn) <= max_labelno)
184350503Sobrien	{
184450503Sobrien	  int align = LABEL_TO_ALIGNMENT (insn);
184550503Sobrien#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
184650503Sobrien	  int max_skip = LABEL_TO_MAX_SKIP (insn);
184750503Sobrien#endif
184850503Sobrien
184950503Sobrien	  if (align && NEXT_INSN (insn))
185090087Sobrien	    {
185150503Sobrien#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
185290087Sobrien	      ASM_OUTPUT_MAX_SKIP_ALIGN (file, align, max_skip);
185350503Sobrien#else
1854117404Skan#ifdef ASM_OUTPUT_ALIGN_WITH_NOP
1855117404Skan              ASM_OUTPUT_ALIGN_WITH_NOP (file, align);
1856117404Skan#else
185790087Sobrien	      ASM_OUTPUT_ALIGN (file, align);
185850503Sobrien#endif
1859117404Skan#endif
186090087Sobrien	    }
186150503Sobrien	}
186252515Sobrien#ifdef HAVE_cc0
186318334Speter      CC_STATUS_INIT;
186452515Sobrien      /* If this label is reached from only one place, set the condition
186552515Sobrien	 codes from the instruction just before the branch.  */
186652515Sobrien
186752515Sobrien      /* Disabled because some insns set cc_status in the C output code
186852515Sobrien	 and NOTICE_UPDATE_CC alone can set incorrect status.  */
186952515Sobrien      if (0 /* optimize && LABEL_NUSES (insn) == 1*/)
187052515Sobrien	{
187152515Sobrien	  rtx jump = LABEL_REFS (insn);
187252515Sobrien	  rtx barrier = prev_nonnote_insn (insn);
187352515Sobrien	  rtx prev;
187452515Sobrien	  /* If the LABEL_REFS field of this label has been set to point
187552515Sobrien	     at a branch, the predecessor of the branch is a regular
187652515Sobrien	     insn, and that branch is the only way to reach this label,
187752515Sobrien	     set the condition codes based on the branch and its
187852515Sobrien	     predecessor.  */
1879169699Skan	  if (barrier && BARRIER_P (barrier)
1880169699Skan	      && jump && JUMP_P (jump)
188152515Sobrien	      && (prev = prev_nonnote_insn (jump))
1882169699Skan	      && NONJUMP_INSN_P (prev))
188352515Sobrien	    {
188452515Sobrien	      NOTICE_UPDATE_CC (PATTERN (prev), prev);
188552515Sobrien	      NOTICE_UPDATE_CC (PATTERN (jump), jump);
188652515Sobrien	    }
188752515Sobrien	}
188852515Sobrien#endif
188950503Sobrien
189090087Sobrien      if (LABEL_NAME (insn))
189190087Sobrien	(*debug_hooks->label) (insn);
189290087Sobrien
189318334Speter      if (app_on)
189418334Speter	{
189550503Sobrien	  fputs (ASM_APP_OFF, file);
189618334Speter	  app_on = 0;
189718334Speter	}
1898169699Skan
1899169699Skan      next = next_nonnote_insn (insn);
1900169699Skan      if (next != 0 && JUMP_P (next))
190118334Speter	{
1902169699Skan	  rtx nextbody = PATTERN (next);
190318334Speter
190418334Speter	  /* If this label is followed by a jump-table,
190518334Speter	     make sure we put the label in the read-only section.  Also
190618334Speter	     possibly write the label and jump table together.  */
190718334Speter
190818334Speter	  if (GET_CODE (nextbody) == ADDR_VEC
190918334Speter	      || GET_CODE (nextbody) == ADDR_DIFF_VEC)
191018334Speter	    {
191152515Sobrien#if defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC)
191252515Sobrien	      /* In this case, the case vector is being moved by the
191352515Sobrien		 target, so don't output the label at all.  Leave that
191452515Sobrien		 to the back end macros.  */
191552515Sobrien#else
191650503Sobrien	      if (! JUMP_TABLES_IN_TEXT_SECTION)
191750503Sobrien		{
191890087Sobrien		  int log_align;
191990087Sobrien
1920169699Skan		  switch_to_section (targetm.asm_out.function_rodata_section
1921169699Skan				     (current_function_decl));
192290087Sobrien
192390087Sobrien#ifdef ADDR_VEC_ALIGN
1924169699Skan		  log_align = ADDR_VEC_ALIGN (next);
192590087Sobrien#else
192690087Sobrien		  log_align = exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT);
192790087Sobrien#endif
192890087Sobrien		  ASM_OUTPUT_ALIGN (file, log_align);
192950503Sobrien		}
193050503Sobrien	      else
1931169699Skan		switch_to_section (current_function_section ());
193250503Sobrien
193318334Speter#ifdef ASM_OUTPUT_CASE_LABEL
193418334Speter	      ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn),
1935169699Skan				     next);
193618334Speter#else
1937169699Skan	      targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (insn));
193818334Speter#endif
193952515Sobrien#endif
194018334Speter	      break;
194118334Speter	    }
194218334Speter	}
1943117404Skan      if (LABEL_ALT_ENTRY_P (insn))
1944117404Skan	output_alternate_entry_point (file, insn);
194590087Sobrien      else
1946169699Skan	targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (insn));
194718334Speter      break;
194818334Speter
194918334Speter    default:
195018334Speter      {
195190087Sobrien	rtx body = PATTERN (insn);
195218334Speter	int insn_code_number;
195352515Sobrien	const char *template;
195418334Speter
1955169699Skan#ifdef HAVE_conditional_execution
1956169699Skan	/* Reset this early so it is correct for ASM statements.  */
1957169699Skan	current_insn_predicate = NULL_RTX;
1958169699Skan#endif
195918334Speter	/* An INSN, JUMP_INSN or CALL_INSN.
196018334Speter	   First check for special kinds that recog doesn't recognize.  */
196118334Speter
1962132727Skan	if (GET_CODE (body) == USE /* These are just declarations.  */
196318334Speter	    || GET_CODE (body) == CLOBBER)
196418334Speter	  break;
196518334Speter
196618334Speter#ifdef HAVE_cc0
1967169699Skan	{
1968169699Skan	  /* If there is a REG_CC_SETTER note on this insn, it means that
1969169699Skan	     the setting of the condition code was done in the delay slot
1970169699Skan	     of the insn that branched here.  So recover the cc status
1971169699Skan	     from the insn that set it.  */
197218334Speter
1973169699Skan	  rtx note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX);
1974169699Skan	  if (note)
1975169699Skan	    {
1976169699Skan	      NOTICE_UPDATE_CC (PATTERN (XEXP (note, 0)), XEXP (note, 0));
1977169699Skan	      cc_prev_status = cc_status;
1978169699Skan	    }
1979169699Skan	}
198018334Speter#endif
198118334Speter
198218334Speter	/* Detect insns that are really jump-tables
198318334Speter	   and output them as such.  */
198418334Speter
198518334Speter	if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC)
198618334Speter	  {
198752515Sobrien#if !(defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC))
198890087Sobrien	    int vlen, idx;
198952515Sobrien#endif
199018334Speter
1991169699Skan	    if (! JUMP_TABLES_IN_TEXT_SECTION)
1992169699Skan	      switch_to_section (targetm.asm_out.function_rodata_section
1993169699Skan				 (current_function_decl));
1994169699Skan	    else
1995169699Skan	      switch_to_section (current_function_section ());
199618334Speter
199718334Speter	    if (app_on)
199818334Speter	      {
199950503Sobrien		fputs (ASM_APP_OFF, file);
200018334Speter		app_on = 0;
200118334Speter	      }
200218334Speter
200352515Sobrien#if defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC)
200452515Sobrien	    if (GET_CODE (body) == ADDR_VEC)
200552515Sobrien	      {
200652515Sobrien#ifdef ASM_OUTPUT_ADDR_VEC
200752515Sobrien		ASM_OUTPUT_ADDR_VEC (PREV_INSN (insn), body);
200852515Sobrien#else
2009169699Skan		gcc_unreachable ();
201052515Sobrien#endif
201152515Sobrien	      }
201252515Sobrien	    else
201352515Sobrien	      {
201452515Sobrien#ifdef ASM_OUTPUT_ADDR_DIFF_VEC
201552515Sobrien		ASM_OUTPUT_ADDR_DIFF_VEC (PREV_INSN (insn), body);
201652515Sobrien#else
2017169699Skan		gcc_unreachable ();
201852515Sobrien#endif
201952515Sobrien	      }
202052515Sobrien#else
202118334Speter	    vlen = XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC);
202218334Speter	    for (idx = 0; idx < vlen; idx++)
202318334Speter	      {
202418334Speter		if (GET_CODE (body) == ADDR_VEC)
202518334Speter		  {
202618334Speter#ifdef ASM_OUTPUT_ADDR_VEC_ELT
202718334Speter		    ASM_OUTPUT_ADDR_VEC_ELT
202818334Speter		      (file, CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 0, idx), 0)));
202918334Speter#else
2030169699Skan		    gcc_unreachable ();
203118334Speter#endif
203218334Speter		  }
203318334Speter		else
203418334Speter		  {
203518334Speter#ifdef ASM_OUTPUT_ADDR_DIFF_ELT
203618334Speter		    ASM_OUTPUT_ADDR_DIFF_ELT
203718334Speter		      (file,
203850503Sobrien		       body,
203918334Speter		       CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 1, idx), 0)),
204018334Speter		       CODE_LABEL_NUMBER (XEXP (XEXP (body, 0), 0)));
204118334Speter#else
2042169699Skan		    gcc_unreachable ();
204318334Speter#endif
204418334Speter		  }
204518334Speter	      }
204618334Speter#ifdef ASM_OUTPUT_CASE_END
204718334Speter	    ASM_OUTPUT_CASE_END (file,
204818334Speter				 CODE_LABEL_NUMBER (PREV_INSN (insn)),
204918334Speter				 insn);
205018334Speter#endif
205152515Sobrien#endif
205218334Speter
2053169699Skan	    switch_to_section (current_function_section ());
205418334Speter
205518334Speter	    break;
205618334Speter	  }
2057132727Skan	/* Output this line note if it is the first or the last line
2058132727Skan	   note in a row.  */
2059132727Skan	if (notice_source_line (insn))
2060132727Skan	  {
2061132727Skan	    (*debug_hooks->source_line) (last_linenum, last_filename);
2062132727Skan	  }
206318334Speter
206418334Speter	if (GET_CODE (body) == ASM_INPUT)
206518334Speter	  {
206690087Sobrien	    const char *string = XSTR (body, 0);
206790087Sobrien
206818334Speter	    /* There's no telling what that did to the condition codes.  */
206918334Speter	    CC_STATUS_INIT;
207090087Sobrien
207190087Sobrien	    if (string[0])
207218334Speter	      {
207390087Sobrien		if (! app_on)
207490087Sobrien		  {
207590087Sobrien		    fputs (ASM_APP_ON, file);
207690087Sobrien		    app_on = 1;
207790087Sobrien		  }
207890087Sobrien		fprintf (asm_out_file, "\t%s\n", string);
207918334Speter	      }
208018334Speter	    break;
208118334Speter	  }
208218334Speter
208318334Speter	/* Detect `asm' construct with operands.  */
208418334Speter	if (asm_noperands (body) >= 0)
208518334Speter	  {
208650503Sobrien	    unsigned int noperands = asm_noperands (body);
2087132727Skan	    rtx *ops = alloca (noperands * sizeof (rtx));
208890087Sobrien	    const char *string;
208918334Speter
209018334Speter	    /* There's no telling what that did to the condition codes.  */
209118334Speter	    CC_STATUS_INIT;
209218334Speter
209318334Speter	    /* Get out the operand values.  */
209490087Sobrien	    string = decode_asm_operands (body, ops, NULL, NULL, NULL);
2095169699Skan	    /* Inhibit dieing on what would otherwise be compiler bugs.  */
209618334Speter	    insn_noperands = noperands;
209718334Speter	    this_is_asm_operands = insn;
209818334Speter
2099132727Skan#ifdef FINAL_PRESCAN_INSN
2100132727Skan	    FINAL_PRESCAN_INSN (insn, ops, insn_noperands);
2101132727Skan#endif
2102132727Skan
210318334Speter	    /* Output the insn using them.  */
210490087Sobrien	    if (string[0])
210590087Sobrien	      {
210690087Sobrien		if (! app_on)
210790087Sobrien		  {
210890087Sobrien		    fputs (ASM_APP_ON, file);
210990087Sobrien		    app_on = 1;
211090087Sobrien		  }
211190087Sobrien	        output_asm_insn (string, ops);
211290087Sobrien	      }
211390087Sobrien
211418334Speter	    this_is_asm_operands = 0;
211518334Speter	    break;
211618334Speter	  }
211718334Speter
2118169699Skan	if (app_on)
211918334Speter	  {
212050503Sobrien	    fputs (ASM_APP_OFF, file);
212118334Speter	    app_on = 0;
212218334Speter	  }
212318334Speter
212418334Speter	if (GET_CODE (body) == SEQUENCE)
212518334Speter	  {
212618334Speter	    /* A delayed-branch sequence */
212790087Sobrien	    int i;
212818334Speter
212918334Speter	    final_sequence = body;
213018334Speter
2131132727Skan	    /* Record the delay slots' frame information before the branch.
2132132727Skan	       This is needed for delayed calls: see execute_cfa_program().  */
2133132727Skan#if defined (DWARF2_UNWIND_INFO)
2134132727Skan	    if (dwarf2out_do_frame ())
2135132727Skan	      for (i = 1; i < XVECLEN (body, 0); i++)
2136169699Skan		dwarf2out_frame_debug (XVECEXP (body, 0, i), false);
2137132727Skan#endif
2138132727Skan
213918334Speter	    /* The first insn in this SEQUENCE might be a JUMP_INSN that will
214018334Speter	       force the restoration of a comparison that was previously
214118334Speter	       thought unnecessary.  If that happens, cancel this sequence
214218334Speter	       and cause that insn to be restored.  */
214318334Speter
2144169699Skan	    next = final_scan_insn (XVECEXP (body, 0, 0), file, 0, 1, seen);
214518334Speter	    if (next != XVECEXP (body, 0, 1))
214618334Speter	      {
214718334Speter		final_sequence = 0;
214818334Speter		return next;
214918334Speter	      }
215018334Speter
215118334Speter	    for (i = 1; i < XVECLEN (body, 0); i++)
215218334Speter	      {
215318334Speter		rtx insn = XVECEXP (body, 0, i);
215418334Speter		rtx next = NEXT_INSN (insn);
215518334Speter		/* We loop in case any instruction in a delay slot gets
215618334Speter		   split.  */
215718334Speter		do
2158169699Skan		  insn = final_scan_insn (insn, file, 0, 1, seen);
215918334Speter		while (insn != next);
216018334Speter	      }
216118334Speter#ifdef DBR_OUTPUT_SEQEND
216218334Speter	    DBR_OUTPUT_SEQEND (file);
216318334Speter#endif
216418334Speter	    final_sequence = 0;
216518334Speter
216618334Speter	    /* If the insn requiring the delay slot was a CALL_INSN, the
216718334Speter	       insns in the delay slot are actually executed before the
216818334Speter	       called function.  Hence we don't preserve any CC-setting
216918334Speter	       actions in these insns and the CC must be marked as being
217018334Speter	       clobbered by the function.  */
2171169699Skan	    if (CALL_P (XVECEXP (body, 0, 0)))
217250503Sobrien	      {
217350503Sobrien		CC_STATUS_INIT;
217450503Sobrien	      }
217518334Speter	    break;
217618334Speter	  }
217718334Speter
217818334Speter	/* We have a real machine instruction as rtl.  */
217918334Speter
218018334Speter	body = PATTERN (insn);
218118334Speter
218218334Speter#ifdef HAVE_cc0
218390087Sobrien	set = single_set (insn);
218450503Sobrien
218518334Speter	/* Check for redundant test and compare instructions
218618334Speter	   (when the condition codes are already set up as desired).
218718334Speter	   This is done only when optimizing; if not optimizing,
218818334Speter	   it should be possible for the user to alter a variable
218918334Speter	   with the debugger in between statements
219018334Speter	   and the next statement should reexamine the variable
219118334Speter	   to compute the condition codes.  */
219218334Speter
219350503Sobrien	if (optimize)
219418334Speter	  {
219550503Sobrien	    if (set
219650503Sobrien		&& GET_CODE (SET_DEST (set)) == CC0
219750503Sobrien		&& insn != last_ignored_compare)
219818334Speter	      {
219950503Sobrien		if (GET_CODE (SET_SRC (set)) == SUBREG)
220090087Sobrien		  SET_SRC (set) = alter_subreg (&SET_SRC (set));
220150503Sobrien		else if (GET_CODE (SET_SRC (set)) == COMPARE)
220218334Speter		  {
220350503Sobrien		    if (GET_CODE (XEXP (SET_SRC (set), 0)) == SUBREG)
220450503Sobrien		      XEXP (SET_SRC (set), 0)
220590087Sobrien			= alter_subreg (&XEXP (SET_SRC (set), 0));
220650503Sobrien		    if (GET_CODE (XEXP (SET_SRC (set), 1)) == SUBREG)
220750503Sobrien		      XEXP (SET_SRC (set), 1)
220890087Sobrien			= alter_subreg (&XEXP (SET_SRC (set), 1));
220918334Speter		  }
221050503Sobrien		if ((cc_status.value1 != 0
221150503Sobrien		     && rtx_equal_p (SET_SRC (set), cc_status.value1))
221250503Sobrien		    || (cc_status.value2 != 0
221350503Sobrien			&& rtx_equal_p (SET_SRC (set), cc_status.value2)))
221450503Sobrien		  {
221550503Sobrien		    /* Don't delete insn if it has an addressing side-effect.  */
221690087Sobrien		    if (! FIND_REG_INC_NOTE (insn, NULL_RTX)
221750503Sobrien			/* or if anything in it is volatile.  */
221850503Sobrien			&& ! volatile_refs_p (PATTERN (insn)))
221950503Sobrien		      {
222050503Sobrien			/* We don't really delete the insn; just ignore it.  */
222150503Sobrien			last_ignored_compare = insn;
222250503Sobrien			break;
222350503Sobrien		      }
222450503Sobrien		  }
222518334Speter	      }
222618334Speter	  }
222718334Speter#endif
222818334Speter
222918334Speter#ifdef HAVE_cc0
223018334Speter	/* If this is a conditional branch, maybe modify it
223118334Speter	   if the cc's are in a nonstandard state
223218334Speter	   so that it accomplishes the same thing that it would
223318334Speter	   do straightforwardly if the cc's were set up normally.  */
223418334Speter
223518334Speter	if (cc_status.flags != 0
2236169699Skan	    && JUMP_P (insn)
223718334Speter	    && GET_CODE (body) == SET
223818334Speter	    && SET_DEST (body) == pc_rtx
223918334Speter	    && GET_CODE (SET_SRC (body)) == IF_THEN_ELSE
2240169699Skan	    && COMPARISON_P (XEXP (SET_SRC (body), 0))
2241169699Skan	    && XEXP (XEXP (SET_SRC (body), 0), 0) == cc0_rtx)
224218334Speter	  {
224318334Speter	    /* This function may alter the contents of its argument
224418334Speter	       and clear some of the cc_status.flags bits.
224518334Speter	       It may also return 1 meaning condition now always true
224618334Speter	       or -1 meaning condition now always false
224718334Speter	       or 2 meaning condition nontrivial but altered.  */
224890087Sobrien	    int result = alter_cond (XEXP (SET_SRC (body), 0));
224918334Speter	    /* If condition now has fixed value, replace the IF_THEN_ELSE
225018334Speter	       with its then-operand or its else-operand.  */
225118334Speter	    if (result == 1)
225218334Speter	      SET_SRC (body) = XEXP (SET_SRC (body), 1);
225318334Speter	    if (result == -1)
225418334Speter	      SET_SRC (body) = XEXP (SET_SRC (body), 2);
225518334Speter
225618334Speter	    /* The jump is now either unconditional or a no-op.
225718334Speter	       If it has become a no-op, don't try to output it.
225818334Speter	       (It would not be recognized.)  */
225918334Speter	    if (SET_SRC (body) == pc_rtx)
226018334Speter	      {
226190087Sobrien	        delete_insn (insn);
226218334Speter		break;
226318334Speter	      }
226418334Speter	    else if (GET_CODE (SET_SRC (body)) == RETURN)
226518334Speter	      /* Replace (set (pc) (return)) with (return).  */
226618334Speter	      PATTERN (insn) = body = SET_SRC (body);
226718334Speter
226818334Speter	    /* Rerecognize the instruction if it has changed.  */
226918334Speter	    if (result != 0)
227018334Speter	      INSN_CODE (insn) = -1;
227118334Speter	  }
227218334Speter
227318334Speter	/* Make same adjustments to instructions that examine the
227450503Sobrien	   condition codes without jumping and instructions that
227550503Sobrien	   handle conditional moves (if this machine has either one).  */
227618334Speter
227718334Speter	if (cc_status.flags != 0
227850503Sobrien	    && set != 0)
227918334Speter	  {
228050503Sobrien	    rtx cond_rtx, then_rtx, else_rtx;
228190087Sobrien
2282169699Skan	    if (!JUMP_P (insn)
228350503Sobrien		&& GET_CODE (SET_SRC (set)) == IF_THEN_ELSE)
228418334Speter	      {
228550503Sobrien		cond_rtx = XEXP (SET_SRC (set), 0);
228650503Sobrien		then_rtx = XEXP (SET_SRC (set), 1);
228750503Sobrien		else_rtx = XEXP (SET_SRC (set), 2);
228850503Sobrien	      }
228950503Sobrien	    else
229050503Sobrien	      {
229150503Sobrien		cond_rtx = SET_SRC (set);
229250503Sobrien		then_rtx = const_true_rtx;
229350503Sobrien		else_rtx = const0_rtx;
229450503Sobrien	      }
229590087Sobrien
229650503Sobrien	    switch (GET_CODE (cond_rtx))
229750503Sobrien	      {
229818334Speter	      case GTU:
229918334Speter	      case GT:
230018334Speter	      case LTU:
230118334Speter	      case LT:
230218334Speter	      case GEU:
230318334Speter	      case GE:
230418334Speter	      case LEU:
230518334Speter	      case LE:
230618334Speter	      case EQ:
230718334Speter	      case NE:
230818334Speter		{
230990087Sobrien		  int result;
231050503Sobrien		  if (XEXP (cond_rtx, 0) != cc0_rtx)
231118334Speter		    break;
231250503Sobrien		  result = alter_cond (cond_rtx);
231318334Speter		  if (result == 1)
231450503Sobrien		    validate_change (insn, &SET_SRC (set), then_rtx, 0);
231518334Speter		  else if (result == -1)
231650503Sobrien		    validate_change (insn, &SET_SRC (set), else_rtx, 0);
231718334Speter		  else if (result == 2)
231818334Speter		    INSN_CODE (insn) = -1;
231950503Sobrien		  if (SET_DEST (set) == SET_SRC (set))
232090087Sobrien		    delete_insn (insn);
232118334Speter		}
232250503Sobrien		break;
232350503Sobrien
232450503Sobrien	      default:
232550503Sobrien		break;
232618334Speter	      }
232718334Speter	  }
232850503Sobrien
232918334Speter#endif
233018334Speter
233190087Sobrien#ifdef HAVE_peephole
233218334Speter	/* Do machine-specific peephole optimizations if desired.  */
233318334Speter
233418334Speter	if (optimize && !flag_no_peephole && !nopeepholes)
233518334Speter	  {
233618334Speter	    rtx next = peephole (insn);
233718334Speter	    /* When peepholing, if there were notes within the peephole,
233818334Speter	       emit them before the peephole.  */
233918334Speter	    if (next != 0 && next != NEXT_INSN (insn))
234018334Speter	      {
2341169699Skan		rtx note, prev = PREV_INSN (insn);
234218334Speter
234318334Speter		for (note = NEXT_INSN (insn); note != next;
234418334Speter		     note = NEXT_INSN (note))
2345169699Skan		  final_scan_insn (note, file, optimize, nopeepholes, seen);
234618334Speter
2347169699Skan		/* Put the notes in the proper position for a later
2348169699Skan		   rescan.  For example, the SH target can do this
2349169699Skan		   when generating a far jump in a delayed branch
2350169699Skan		   sequence.  */
235118334Speter		note = NEXT_INSN (insn);
235218334Speter		PREV_INSN (note) = prev;
235318334Speter		NEXT_INSN (prev) = note;
235418334Speter		NEXT_INSN (PREV_INSN (next)) = insn;
235518334Speter		PREV_INSN (insn) = PREV_INSN (next);
235618334Speter		NEXT_INSN (insn) = next;
235718334Speter		PREV_INSN (next) = insn;
235818334Speter	      }
235918334Speter
236018334Speter	    /* PEEPHOLE might have changed this.  */
236118334Speter	    body = PATTERN (insn);
236218334Speter	  }
236390087Sobrien#endif
236418334Speter
236518334Speter	/* Try to recognize the instruction.
236618334Speter	   If successful, verify that the operands satisfy the
236718334Speter	   constraints for the instruction.  Crash if they don't,
236818334Speter	   since `reload' should have changed them so that they do.  */
236918334Speter
237018334Speter	insn_code_number = recog_memoized (insn);
237152515Sobrien	cleanup_subreg_operands (insn);
237218334Speter
2373117404Skan	/* Dump the insn in the assembly for debugging.  */
2374117404Skan	if (flag_dump_rtl_in_asm)
2375117404Skan	  {
2376117404Skan	    print_rtx_head = ASM_COMMENT_START;
2377117404Skan	    print_rtl_single (asm_out_file, insn);
2378117404Skan	    print_rtx_head = "";
2379117404Skan	  }
238090087Sobrien
238190087Sobrien	if (! constrain_operands_cached (1))
238218334Speter	  fatal_insn_not_found (insn);
238318334Speter
238418334Speter	/* Some target machines need to prescan each insn before
238518334Speter	   it is output.  */
238618334Speter
238718334Speter#ifdef FINAL_PRESCAN_INSN
238890087Sobrien	FINAL_PRESCAN_INSN (insn, recog_data.operand, recog_data.n_operands);
238918334Speter#endif
239018334Speter
239190087Sobrien#ifdef HAVE_conditional_execution
239290087Sobrien	if (GET_CODE (PATTERN (insn)) == COND_EXEC)
239390087Sobrien	  current_insn_predicate = COND_EXEC_TEST (PATTERN (insn));
239490087Sobrien#endif
239590087Sobrien
239618334Speter#ifdef HAVE_cc0
239718334Speter	cc_prev_status = cc_status;
239818334Speter
239918334Speter	/* Update `cc_status' for this instruction.
240018334Speter	   The instruction's output routine may change it further.
240118334Speter	   If the output routine for a jump insn needs to depend
240218334Speter	   on the cc status, it should look at cc_prev_status.  */
240318334Speter
240418334Speter	NOTICE_UPDATE_CC (body, insn);
240518334Speter#endif
240618334Speter
240790087Sobrien	current_output_insn = debug_insn = insn;
240818334Speter
240990087Sobrien#if defined (DWARF2_UNWIND_INFO)
2410169699Skan	if (CALL_P (insn) && dwarf2out_do_frame ())
2411169699Skan	  dwarf2out_frame_debug (insn, false);
241250503Sobrien#endif
241350503Sobrien
241490087Sobrien	/* Find the proper template for this insn.  */
241590087Sobrien	template = get_insn_template (insn_code_number, insn);
241618334Speter
241790087Sobrien	/* If the C code returns 0, it means that it is a jump insn
241890087Sobrien	   which follows a deleted test insn, and that test insn
241990087Sobrien	   needs to be reinserted.  */
242018334Speter	if (template == 0)
242118334Speter	  {
242290087Sobrien	    rtx prev;
242318334Speter
2424169699Skan	    gcc_assert (prev_nonnote_insn (insn) == last_ignored_compare);
242590087Sobrien
242690087Sobrien	    /* We have already processed the notes between the setter and
242790087Sobrien	       the user.  Make sure we don't process them again, this is
242890087Sobrien	       particularly important if one of the notes is a block
242990087Sobrien	       scope note or an EH note.  */
243090087Sobrien	    for (prev = insn;
243190087Sobrien		 prev != last_ignored_compare;
243290087Sobrien		 prev = PREV_INSN (prev))
243318334Speter	      {
2434169699Skan		if (NOTE_P (prev))
243590087Sobrien		  delete_insn (prev);	/* Use delete_note.  */
243618334Speter	      }
243790087Sobrien
243890087Sobrien	    return prev;
243918334Speter	  }
244018334Speter
244118334Speter	/* If the template is the string "#", it means that this insn must
244218334Speter	   be split.  */
244318334Speter	if (template[0] == '#' && template[1] == '\0')
244418334Speter	  {
244518334Speter	    rtx new = try_split (body, insn, 0);
244618334Speter
244718334Speter	    /* If we didn't split the insn, go away.  */
244818334Speter	    if (new == insn && PATTERN (new) == body)
244990087Sobrien	      fatal_insn ("could not split insn", insn);
245090087Sobrien
245150503Sobrien#ifdef HAVE_ATTR_length
245250503Sobrien	    /* This instruction should have been split in shorten_branches,
245350503Sobrien	       to ensure that we would have valid length info for the
245450503Sobrien	       splitees.  */
2455169699Skan	    gcc_unreachable ();
245650503Sobrien#endif
245750503Sobrien
245818334Speter	    return new;
245918334Speter	  }
246090087Sobrien
2461169699Skan#ifdef TARGET_UNWIND_INFO
2462169699Skan	/* ??? This will put the directives in the wrong place if
2463169699Skan	   get_insn_template outputs assembly directly.  However calling it
2464169699Skan	   before get_insn_template breaks if the insns is split.  */
2465169699Skan	targetm.asm_out.unwind_emit (asm_out_file, insn);
2466169699Skan#endif
246718334Speter
246818334Speter	/* Output assembler code from the template.  */
246990087Sobrien	output_asm_insn (template, recog_data.operand);
247018334Speter
2471132727Skan	/* If necessary, report the effect that the instruction has on
2472132727Skan	   the unwind info.   We've already done this for delay slots
2473132727Skan	   and call instructions.  */
247450503Sobrien#if defined (DWARF2_UNWIND_INFO)
2475169699Skan	if (final_sequence == 0
2476132727Skan#if !defined (HAVE_prologue)
2477132727Skan	    && !ACCUMULATE_OUTGOING_ARGS
2478132727Skan#endif
247990087Sobrien	    && dwarf2out_do_frame ())
2480169699Skan	  dwarf2out_frame_debug (insn, true);
248150503Sobrien#endif
248250503Sobrien
248390087Sobrien	current_output_insn = debug_insn = 0;
248418334Speter      }
248518334Speter    }
248618334Speter  return NEXT_INSN (insn);
248718334Speter}
248818334Speter
2489169699Skan/* Return whether a source line note needs to be emitted before INSN.  */
249018334Speter
2491132727Skanstatic bool
2492132727Skannotice_source_line (rtx insn)
249318334Speter{
2494132727Skan  const char *filename = insn_file (insn);
2495132727Skan  int linenum = insn_line (insn);
249618334Speter
2497169699Skan  if (filename
2498169699Skan      && (force_source_line
2499169699Skan	  || filename != last_filename
2500169699Skan	  || last_linenum != linenum))
2501132727Skan    {
2502169699Skan      force_source_line = false;
2503132727Skan      last_filename = filename;
2504132727Skan      last_linenum = linenum;
2505132727Skan      high_block_linenum = MAX (last_linenum, high_block_linenum);
2506132727Skan      high_function_linenum = MAX (last_linenum, high_function_linenum);
2507132727Skan      return true;
2508132727Skan    }
2509132727Skan  return false;
251018334Speter}
251118334Speter
251252515Sobrien/* For each operand in INSN, simplify (subreg (reg)) so that it refers
251352515Sobrien   directly to the desired hard register.  */
251490087Sobrien
251552515Sobrienvoid
2516132727Skancleanup_subreg_operands (rtx insn)
251752515Sobrien{
251852515Sobrien  int i;
251990087Sobrien  extract_insn_cached (insn);
252090087Sobrien  for (i = 0; i < recog_data.n_operands; i++)
252152515Sobrien    {
2522132727Skan      /* The following test cannot use recog_data.operand when testing
252390087Sobrien	 for a SUBREG: the underlying object might have been changed
252490087Sobrien	 already if we are inside a match_operator expression that
252590087Sobrien	 matches the else clause.  Instead we test the underlying
252690087Sobrien	 expression directly.  */
252790087Sobrien      if (GET_CODE (*recog_data.operand_loc[i]) == SUBREG)
252890087Sobrien	recog_data.operand[i] = alter_subreg (recog_data.operand_loc[i]);
252990087Sobrien      else if (GET_CODE (recog_data.operand[i]) == PLUS
253090087Sobrien	       || GET_CODE (recog_data.operand[i]) == MULT
2531169699Skan	       || MEM_P (recog_data.operand[i]))
253290087Sobrien	recog_data.operand[i] = walk_alter_subreg (recog_data.operand_loc[i]);
253352515Sobrien    }
253452515Sobrien
253590087Sobrien  for (i = 0; i < recog_data.n_dups; i++)
253652515Sobrien    {
253790087Sobrien      if (GET_CODE (*recog_data.dup_loc[i]) == SUBREG)
253890087Sobrien	*recog_data.dup_loc[i] = alter_subreg (recog_data.dup_loc[i]);
253990087Sobrien      else if (GET_CODE (*recog_data.dup_loc[i]) == PLUS
254090087Sobrien	       || GET_CODE (*recog_data.dup_loc[i]) == MULT
2541169699Skan	       || MEM_P (*recog_data.dup_loc[i]))
254290087Sobrien	*recog_data.dup_loc[i] = walk_alter_subreg (recog_data.dup_loc[i]);
254352515Sobrien    }
254452515Sobrien}
254552515Sobrien
254618334Speter/* If X is a SUBREG, replace it with a REG or a MEM,
254718334Speter   based on the thing it is a subreg of.  */
254818334Speter
254918334Speterrtx
2550132727Skanalter_subreg (rtx *xp)
255118334Speter{
255290087Sobrien  rtx x = *xp;
255390087Sobrien  rtx y = SUBREG_REG (x);
255450503Sobrien
255590087Sobrien  /* simplify_subreg does not remove subreg from volatile references.
255690087Sobrien     We are required to.  */
2557169699Skan  if (MEM_P (y))
2558169699Skan    {
2559169699Skan      int offset = SUBREG_BYTE (x);
2560169699Skan
2561169699Skan      /* For paradoxical subregs on big-endian machines, SUBREG_BYTE
2562169699Skan	 contains 0 instead of the proper offset.  See simplify_subreg.  */
2563169699Skan      if (offset == 0
2564169699Skan	  && GET_MODE_SIZE (GET_MODE (y)) < GET_MODE_SIZE (GET_MODE (x)))
2565169699Skan        {
2566169699Skan          int difference = GET_MODE_SIZE (GET_MODE (y))
2567169699Skan			   - GET_MODE_SIZE (GET_MODE (x));
2568169699Skan          if (WORDS_BIG_ENDIAN)
2569169699Skan            offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
2570169699Skan          if (BYTES_BIG_ENDIAN)
2571169699Skan            offset += difference % UNITS_PER_WORD;
2572169699Skan        }
2573169699Skan
2574169699Skan      *xp = adjust_address (y, GET_MODE (x), offset);
2575169699Skan    }
257690087Sobrien  else
257718334Speter    {
257890087Sobrien      rtx new = simplify_subreg (GET_MODE (x), y, GET_MODE (y),
257990087Sobrien				 SUBREG_BYTE (x));
258050503Sobrien
258190087Sobrien      if (new != 0)
258290087Sobrien	*xp = new;
2583169699Skan      else if (REG_P (y))
258490087Sobrien	{
2585169699Skan	  /* Simplify_subreg can't handle some REG cases, but we have to.  */
2586169699Skan	  unsigned int regno = subreg_regno (x);
2587132727Skan	  *xp = gen_rtx_REG_offset (y, GET_MODE (x), regno, SUBREG_BYTE (x));
258890087Sobrien	}
258918334Speter    }
259018334Speter
259190087Sobrien  return *xp;
259218334Speter}
259318334Speter
259418334Speter/* Do alter_subreg on all the SUBREGs contained in X.  */
259518334Speter
259618334Speterstatic rtx
2597132727Skanwalk_alter_subreg (rtx *xp)
259818334Speter{
259990087Sobrien  rtx x = *xp;
260018334Speter  switch (GET_CODE (x))
260118334Speter    {
260218334Speter    case PLUS:
260318334Speter    case MULT:
2604169699Skan    case AND:
260590087Sobrien      XEXP (x, 0) = walk_alter_subreg (&XEXP (x, 0));
260690087Sobrien      XEXP (x, 1) = walk_alter_subreg (&XEXP (x, 1));
260718334Speter      break;
260818334Speter
260918334Speter    case MEM:
2610169699Skan    case ZERO_EXTEND:
261190087Sobrien      XEXP (x, 0) = walk_alter_subreg (&XEXP (x, 0));
261218334Speter      break;
261318334Speter
261418334Speter    case SUBREG:
261590087Sobrien      return alter_subreg (xp);
261690087Sobrien
261750503Sobrien    default:
261850503Sobrien      break;
261918334Speter    }
262018334Speter
262190087Sobrien  return *xp;
262218334Speter}
262318334Speter
262418334Speter#ifdef HAVE_cc0
262518334Speter
262618334Speter/* Given BODY, the body of a jump instruction, alter the jump condition
262718334Speter   as required by the bits that are set in cc_status.flags.
262818334Speter   Not all of the bits there can be handled at this level in all cases.
262918334Speter
263018334Speter   The value is normally 0.
263118334Speter   1 means that the condition has become always true.
263218334Speter   -1 means that the condition has become always false.
263318334Speter   2 means that COND has been altered.  */
263418334Speter
263518334Speterstatic int
2636132727Skanalter_cond (rtx cond)
263718334Speter{
263818334Speter  int value = 0;
263918334Speter
264018334Speter  if (cc_status.flags & CC_REVERSED)
264118334Speter    {
264218334Speter      value = 2;
264318334Speter      PUT_CODE (cond, swap_condition (GET_CODE (cond)));
264418334Speter    }
264518334Speter
264618334Speter  if (cc_status.flags & CC_INVERTED)
264718334Speter    {
264818334Speter      value = 2;
264918334Speter      PUT_CODE (cond, reverse_condition (GET_CODE (cond)));
265018334Speter    }
265118334Speter
265218334Speter  if (cc_status.flags & CC_NOT_POSITIVE)
265318334Speter    switch (GET_CODE (cond))
265418334Speter      {
265518334Speter      case LE:
265618334Speter      case LEU:
265718334Speter      case GEU:
265818334Speter	/* Jump becomes unconditional.  */
265918334Speter	return 1;
266018334Speter
266118334Speter      case GT:
266218334Speter      case GTU:
266318334Speter      case LTU:
266418334Speter	/* Jump becomes no-op.  */
266518334Speter	return -1;
266618334Speter
266718334Speter      case GE:
266818334Speter	PUT_CODE (cond, EQ);
266918334Speter	value = 2;
267018334Speter	break;
267118334Speter
267218334Speter      case LT:
267318334Speter	PUT_CODE (cond, NE);
267418334Speter	value = 2;
267518334Speter	break;
267690087Sobrien
267750503Sobrien      default:
267850503Sobrien	break;
267918334Speter      }
268018334Speter
268118334Speter  if (cc_status.flags & CC_NOT_NEGATIVE)
268218334Speter    switch (GET_CODE (cond))
268318334Speter      {
268418334Speter      case GE:
268518334Speter      case GEU:
268618334Speter	/* Jump becomes unconditional.  */
268718334Speter	return 1;
268818334Speter
268918334Speter      case LT:
269018334Speter      case LTU:
269118334Speter	/* Jump becomes no-op.  */
269218334Speter	return -1;
269318334Speter
269418334Speter      case LE:
269518334Speter      case LEU:
269618334Speter	PUT_CODE (cond, EQ);
269718334Speter	value = 2;
269818334Speter	break;
269918334Speter
270018334Speter      case GT:
270118334Speter      case GTU:
270218334Speter	PUT_CODE (cond, NE);
270318334Speter	value = 2;
270418334Speter	break;
270590087Sobrien
270650503Sobrien      default:
270750503Sobrien	break;
270818334Speter      }
270918334Speter
271018334Speter  if (cc_status.flags & CC_NO_OVERFLOW)
271118334Speter    switch (GET_CODE (cond))
271218334Speter      {
271318334Speter      case GEU:
271418334Speter	/* Jump becomes unconditional.  */
271518334Speter	return 1;
271618334Speter
271718334Speter      case LEU:
271818334Speter	PUT_CODE (cond, EQ);
271918334Speter	value = 2;
272018334Speter	break;
272118334Speter
272218334Speter      case GTU:
272318334Speter	PUT_CODE (cond, NE);
272418334Speter	value = 2;
272518334Speter	break;
272618334Speter
272718334Speter      case LTU:
272818334Speter	/* Jump becomes no-op.  */
272918334Speter	return -1;
273090087Sobrien
273150503Sobrien      default:
273250503Sobrien	break;
273318334Speter      }
273418334Speter
273518334Speter  if (cc_status.flags & (CC_Z_IN_NOT_N | CC_Z_IN_N))
273618334Speter    switch (GET_CODE (cond))
273718334Speter      {
273850503Sobrien      default:
2739169699Skan	gcc_unreachable ();
274018334Speter
274118334Speter      case NE:
274218334Speter	PUT_CODE (cond, cc_status.flags & CC_Z_IN_N ? GE : LT);
274318334Speter	value = 2;
274418334Speter	break;
274518334Speter
274618334Speter      case EQ:
274718334Speter	PUT_CODE (cond, cc_status.flags & CC_Z_IN_N ? LT : GE);
274818334Speter	value = 2;
274918334Speter	break;
275018334Speter      }
275118334Speter
275218334Speter  if (cc_status.flags & CC_NOT_SIGNED)
275318334Speter    /* The flags are valid if signed condition operators are converted
275418334Speter       to unsigned.  */
275518334Speter    switch (GET_CODE (cond))
275618334Speter      {
275718334Speter      case LE:
275818334Speter	PUT_CODE (cond, LEU);
275918334Speter	value = 2;
276018334Speter	break;
276118334Speter
276218334Speter      case LT:
276318334Speter	PUT_CODE (cond, LTU);
276418334Speter	value = 2;
276518334Speter	break;
276618334Speter
276718334Speter      case GT:
276818334Speter	PUT_CODE (cond, GTU);
276918334Speter	value = 2;
277018334Speter	break;
277118334Speter
277218334Speter      case GE:
277318334Speter	PUT_CODE (cond, GEU);
277418334Speter	value = 2;
277518334Speter	break;
277650503Sobrien
277750503Sobrien      default:
277850503Sobrien	break;
277918334Speter      }
278018334Speter
278118334Speter  return value;
278218334Speter}
278318334Speter#endif
278418334Speter
278518334Speter/* Report inconsistency between the assembler template and the operands.
278618334Speter   In an `asm', it's the user's fault; otherwise, the compiler's fault.  */
278718334Speter
278818334Spetervoid
2789169699Skanoutput_operand_lossage (const char *cmsgid, ...)
279018334Speter{
279196281Sobrien  char *fmt_string;
279296281Sobrien  char *new_message;
279396281Sobrien  const char *pfx_str;
2794132727Skan  va_list ap;
279596281Sobrien
2796169699Skan  va_start (ap, cmsgid);
2797132727Skan
2798169699Skan  pfx_str = this_is_asm_operands ? _("invalid 'asm': ") : "output_operand: ";
2799169699Skan  asprintf (&fmt_string, "%s%s", pfx_str, _(cmsgid));
280096281Sobrien  vasprintf (&new_message, fmt_string, ap);
2801117404Skan
280218334Speter  if (this_is_asm_operands)
280396281Sobrien    error_for_asm (this_is_asm_operands, "%s", new_message);
280418334Speter  else
280596281Sobrien    internal_error ("%s", new_message);
280696281Sobrien
280796281Sobrien  free (fmt_string);
280896281Sobrien  free (new_message);
2809132727Skan  va_end (ap);
281018334Speter}
281118334Speter
281218334Speter/* Output of assembler code from a template, and its subroutines.  */
281318334Speter
281490087Sobrien/* Annotate the assembly with a comment describing the pattern and
281590087Sobrien   alternative used.  */
281690087Sobrien
281790087Sobrienstatic void
2818132727Skanoutput_asm_name (void)
281990087Sobrien{
282090087Sobrien  if (debug_insn)
282190087Sobrien    {
282290087Sobrien      int num = INSN_CODE (debug_insn);
282390087Sobrien      fprintf (asm_out_file, "\t%s %d\t%s",
282490087Sobrien	       ASM_COMMENT_START, INSN_UID (debug_insn),
282590087Sobrien	       insn_data[num].name);
282690087Sobrien      if (insn_data[num].n_alternatives > 1)
282790087Sobrien	fprintf (asm_out_file, "/%d", which_alternative + 1);
282890087Sobrien#ifdef HAVE_ATTR_length
282990087Sobrien      fprintf (asm_out_file, "\t[length = %d]",
283090087Sobrien	       get_attr_length (debug_insn));
283190087Sobrien#endif
283290087Sobrien      /* Clear this so only the first assembler insn
283390087Sobrien	 of any rtl insn will get the special comment for -dp.  */
283490087Sobrien      debug_insn = 0;
283590087Sobrien    }
283690087Sobrien}
283790087Sobrien
283890087Sobrien/* If OP is a REG or MEM and we can find a MEM_EXPR corresponding to it
283990087Sobrien   or its address, return that expr .  Set *PADDRESSP to 1 if the expr
284090087Sobrien   corresponds to the address of the object and 0 if to the object.  */
284190087Sobrien
284290087Sobrienstatic tree
2843132727Skanget_mem_expr_from_op (rtx op, int *paddressp)
284490087Sobrien{
284590087Sobrien  tree expr;
284690087Sobrien  int inner_addressp;
284790087Sobrien
284890087Sobrien  *paddressp = 0;
284990087Sobrien
2850169699Skan  if (REG_P (op))
2851132727Skan    return REG_EXPR (op);
2852169699Skan  else if (!MEM_P (op))
285390087Sobrien    return 0;
285490087Sobrien
285590087Sobrien  if (MEM_EXPR (op) != 0)
285690087Sobrien    return MEM_EXPR (op);
285790087Sobrien
285890087Sobrien  /* Otherwise we have an address, so indicate it and look at the address.  */
285990087Sobrien  *paddressp = 1;
286090087Sobrien  op = XEXP (op, 0);
286190087Sobrien
286290087Sobrien  /* First check if we have a decl for the address, then look at the right side
286390087Sobrien     if it is a PLUS.  Otherwise, strip off arithmetic and keep looking.
286490087Sobrien     But don't allow the address to itself be indirect.  */
286590087Sobrien  if ((expr = get_mem_expr_from_op (op, &inner_addressp)) && ! inner_addressp)
286690087Sobrien    return expr;
286790087Sobrien  else if (GET_CODE (op) == PLUS
286890087Sobrien	   && (expr = get_mem_expr_from_op (XEXP (op, 1), &inner_addressp)))
286990087Sobrien    return expr;
287090087Sobrien
2871169699Skan  while (GET_RTX_CLASS (GET_CODE (op)) == RTX_UNARY
2872169699Skan	 || GET_RTX_CLASS (GET_CODE (op)) == RTX_BIN_ARITH)
287390087Sobrien    op = XEXP (op, 0);
287490087Sobrien
287590087Sobrien  expr = get_mem_expr_from_op (op, &inner_addressp);
287690087Sobrien  return inner_addressp ? 0 : expr;
287790087Sobrien}
287890087Sobrien
287990087Sobrien/* Output operand names for assembler instructions.  OPERANDS is the
288090087Sobrien   operand vector, OPORDER is the order to write the operands, and NOPS
288190087Sobrien   is the number of operands to write.  */
288290087Sobrien
288390087Sobrienstatic void
2884132727Skanoutput_asm_operand_names (rtx *operands, int *oporder, int nops)
288590087Sobrien{
288690087Sobrien  int wrote = 0;
288790087Sobrien  int i;
288890087Sobrien
288990087Sobrien  for (i = 0; i < nops; i++)
289090087Sobrien    {
289190087Sobrien      int addressp;
2892132727Skan      rtx op = operands[oporder[i]];
2893132727Skan      tree expr = get_mem_expr_from_op (op, &addressp);
289490087Sobrien
2895132727Skan      fprintf (asm_out_file, "%c%s",
2896132727Skan	       wrote ? ',' : '\t', wrote ? "" : ASM_COMMENT_START);
2897132727Skan      wrote = 1;
289890087Sobrien      if (expr)
289990087Sobrien	{
2900132727Skan	  fprintf (asm_out_file, "%s",
290190087Sobrien		   addressp ? "*" : "");
290290087Sobrien	  print_mem_expr (asm_out_file, expr);
290390087Sobrien	  wrote = 1;
290490087Sobrien	}
2905132727Skan      else if (REG_P (op) && ORIGINAL_REGNO (op)
2906132727Skan	       && ORIGINAL_REGNO (op) != REGNO (op))
2907132727Skan	fprintf (asm_out_file, " tmp%i", ORIGINAL_REGNO (op));
290890087Sobrien    }
290990087Sobrien}
291090087Sobrien
291118334Speter/* Output text from TEMPLATE to the assembler output file,
291218334Speter   obeying %-directions to substitute operands taken from
291318334Speter   the vector OPERANDS.
291418334Speter
291518334Speter   %N (for N a digit) means print operand N in usual manner.
291618334Speter   %lN means require operand N to be a CODE_LABEL or LABEL_REF
291718334Speter      and print the label name with no punctuation.
291818334Speter   %cN means require operand N to be a constant
291918334Speter      and print the constant expression with no punctuation.
292018334Speter   %aN means expect operand N to be a memory address
292118334Speter      (not a memory reference!) and print a reference
292218334Speter      to that address.
292318334Speter   %nN means expect operand N to be a constant
292418334Speter      and print a constant expression for minus the value
292518334Speter      of the operand, with no other punctuation.  */
292618334Speter
292718334Spetervoid
2928132727Skanoutput_asm_insn (const char *template, rtx *operands)
292918334Speter{
293090087Sobrien  const char *p;
293190087Sobrien  int c;
293290087Sobrien#ifdef ASSEMBLER_DIALECT
293390087Sobrien  int dialect = 0;
293490087Sobrien#endif
293590087Sobrien  int oporder[MAX_RECOG_OPERANDS];
293690087Sobrien  char opoutput[MAX_RECOG_OPERANDS];
293790087Sobrien  int ops = 0;
293818334Speter
293918334Speter  /* An insn may return a null string template
294018334Speter     in a case where no assembler code is needed.  */
294118334Speter  if (*template == 0)
294218334Speter    return;
294318334Speter
294490087Sobrien  memset (opoutput, 0, sizeof opoutput);
294518334Speter  p = template;
294618334Speter  putc ('\t', asm_out_file);
294718334Speter
294818334Speter#ifdef ASM_OUTPUT_OPCODE
294918334Speter  ASM_OUTPUT_OPCODE (asm_out_file, p);
295018334Speter#endif
295118334Speter
295250503Sobrien  while ((c = *p++))
295318334Speter    switch (c)
295418334Speter      {
295518334Speter      case '\n':
295690087Sobrien	if (flag_verbose_asm)
295790087Sobrien	  output_asm_operand_names (operands, oporder, ops);
295890087Sobrien	if (flag_print_asm_name)
295990087Sobrien	  output_asm_name ();
296090087Sobrien
296190087Sobrien	ops = 0;
296290087Sobrien	memset (opoutput, 0, sizeof opoutput);
296390087Sobrien
296418334Speter	putc (c, asm_out_file);
296518334Speter#ifdef ASM_OUTPUT_OPCODE
296618334Speter	while ((c = *p) == '\t')
296718334Speter	  {
296818334Speter	    putc (c, asm_out_file);
296918334Speter	    p++;
297018334Speter	  }
297118334Speter	ASM_OUTPUT_OPCODE (asm_out_file, p);
297218334Speter#endif
297318334Speter	break;
297418334Speter
297518334Speter#ifdef ASSEMBLER_DIALECT
297618334Speter      case '{':
297750503Sobrien	{
297890087Sobrien	  int i;
297990087Sobrien
298090087Sobrien	  if (dialect)
298190087Sobrien	    output_operand_lossage ("nested assembly dialect alternatives");
298290087Sobrien	  else
298390087Sobrien	    dialect = 1;
298490087Sobrien
298550503Sobrien	  /* If we want the first dialect, do nothing.  Otherwise, skip
298650503Sobrien	     DIALECT_NUMBER of strings ending with '|'.  */
298750503Sobrien	  for (i = 0; i < dialect_number; i++)
298850503Sobrien	    {
298990087Sobrien	      while (*p && *p != '}' && *p++ != '|')
299050503Sobrien		;
299190087Sobrien	      if (*p == '}')
299290087Sobrien		break;
299350503Sobrien	      if (*p == '|')
299450503Sobrien		p++;
299550503Sobrien	    }
299690087Sobrien
299790087Sobrien	  if (*p == '\0')
299890087Sobrien	    output_operand_lossage ("unterminated assembly dialect alternative");
299950503Sobrien	}
300018334Speter	break;
300118334Speter
300218334Speter      case '|':
300390087Sobrien	if (dialect)
300490087Sobrien	  {
300590087Sobrien	    /* Skip to close brace.  */
300690087Sobrien	    do
300790087Sobrien	      {
300890087Sobrien		if (*p == '\0')
300990087Sobrien		  {
301090087Sobrien		    output_operand_lossage ("unterminated assembly dialect alternative");
301190087Sobrien		    break;
301290087Sobrien		  }
301390087Sobrien	      }
301490087Sobrien	    while (*p++ != '}');
301590087Sobrien	    dialect = 0;
301690087Sobrien	  }
301790087Sobrien	else
301890087Sobrien	  putc (c, asm_out_file);
301918334Speter	break;
302018334Speter
302118334Speter      case '}':
302290087Sobrien	if (! dialect)
302390087Sobrien	  putc (c, asm_out_file);
302490087Sobrien	dialect = 0;
302518334Speter	break;
302618334Speter#endif
302718334Speter
302818334Speter      case '%':
302918334Speter	/* %% outputs a single %.  */
303018334Speter	if (*p == '%')
303118334Speter	  {
303218334Speter	    p++;
303318334Speter	    putc (c, asm_out_file);
303418334Speter	  }
303518334Speter	/* %= outputs a number which is unique to each insn in the entire
303618334Speter	   compilation.  This is useful for making local labels that are
303718334Speter	   referred to more than once in a given insn.  */
303818334Speter	else if (*p == '=')
303918334Speter	  {
304018334Speter	    p++;
304118334Speter	    fprintf (asm_out_file, "%d", insn_counter);
304218334Speter	  }
304318334Speter	/* % followed by a letter and some digits
304418334Speter	   outputs an operand in a special way depending on the letter.
304518334Speter	   Letters `acln' are implemented directly.
304618334Speter	   Other letters are passed to `output_operand' so that
304718334Speter	   the PRINT_OPERAND macro can define them.  */
304890087Sobrien	else if (ISALPHA (*p))
304918334Speter	  {
305018334Speter	    int letter = *p++;
3051169699Skan	    unsigned long opnum;
3052169699Skan	    char *endptr;
305318334Speter
3054169699Skan	    opnum = strtoul (p, &endptr, 10);
3055169699Skan
3056169699Skan	    if (endptr == p)
3057169699Skan	      output_operand_lossage ("operand number missing "
3058169699Skan				      "after %%-letter");
3059169699Skan	    else if (this_is_asm_operands && opnum >= insn_noperands)
306018334Speter	      output_operand_lossage ("operand number out of range");
306118334Speter	    else if (letter == 'l')
3062169699Skan	      output_asm_label (operands[opnum]);
306318334Speter	    else if (letter == 'a')
3064169699Skan	      output_address (operands[opnum]);
306518334Speter	    else if (letter == 'c')
306618334Speter	      {
3067169699Skan		if (CONSTANT_ADDRESS_P (operands[opnum]))
3068169699Skan		  output_addr_const (asm_out_file, operands[opnum]);
306918334Speter		else
3070169699Skan		  output_operand (operands[opnum], 'c');
307118334Speter	      }
307218334Speter	    else if (letter == 'n')
307318334Speter	      {
3074169699Skan		if (GET_CODE (operands[opnum]) == CONST_INT)
307550503Sobrien		  fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC,
3076169699Skan			   - INTVAL (operands[opnum]));
307718334Speter		else
307818334Speter		  {
307918334Speter		    putc ('-', asm_out_file);
3080169699Skan		    output_addr_const (asm_out_file, operands[opnum]);
308118334Speter		  }
308218334Speter	      }
308318334Speter	    else
3084169699Skan	      output_operand (operands[opnum], letter);
308590087Sobrien
3086169699Skan	    if (!opoutput[opnum])
3087169699Skan	      oporder[ops++] = opnum;
3088169699Skan	    opoutput[opnum] = 1;
308990087Sobrien
3090169699Skan	    p = endptr;
3091169699Skan	    c = *p;
309218334Speter	  }
309318334Speter	/* % followed by a digit outputs an operand the default way.  */
309490087Sobrien	else if (ISDIGIT (*p))
309518334Speter	  {
3096169699Skan	    unsigned long opnum;
3097169699Skan	    char *endptr;
3098169699Skan
3099169699Skan	    opnum = strtoul (p, &endptr, 10);
3100169699Skan	    if (this_is_asm_operands && opnum >= insn_noperands)
310118334Speter	      output_operand_lossage ("operand number out of range");
310218334Speter	    else
3103169699Skan	      output_operand (operands[opnum], 0);
310490087Sobrien
3105169699Skan	    if (!opoutput[opnum])
3106169699Skan	      oporder[ops++] = opnum;
3107169699Skan	    opoutput[opnum] = 1;
310890087Sobrien
3109169699Skan	    p = endptr;
3110169699Skan	    c = *p;
311118334Speter	  }
311218334Speter	/* % followed by punctuation: output something for that
311318334Speter	   punctuation character alone, with no operand.
311418334Speter	   The PRINT_OPERAND macro decides what is actually done.  */
311518334Speter#ifdef PRINT_OPERAND_PUNCT_VALID_P
311690087Sobrien	else if (PRINT_OPERAND_PUNCT_VALID_P ((unsigned char) *p))
311718334Speter	  output_operand (NULL_RTX, *p++);
311818334Speter#endif
311918334Speter	else
312018334Speter	  output_operand_lossage ("invalid %%-code");
312118334Speter	break;
312218334Speter
312318334Speter      default:
312418334Speter	putc (c, asm_out_file);
312518334Speter      }
312618334Speter
312790087Sobrien  /* Write out the variable names for operands, if we know them.  */
312890087Sobrien  if (flag_verbose_asm)
312990087Sobrien    output_asm_operand_names (operands, oporder, ops);
313090087Sobrien  if (flag_print_asm_name)
313190087Sobrien    output_asm_name ();
313218334Speter
313318334Speter  putc ('\n', asm_out_file);
313418334Speter}
313518334Speter
313618334Speter/* Output a LABEL_REF, or a bare CODE_LABEL, as an assembler symbol.  */
313718334Speter
313818334Spetervoid
3139132727Skanoutput_asm_label (rtx x)
314018334Speter{
314118334Speter  char buf[256];
314218334Speter
314318334Speter  if (GET_CODE (x) == LABEL_REF)
314490087Sobrien    x = XEXP (x, 0);
3145169699Skan  if (LABEL_P (x)
3146169699Skan      || (NOTE_P (x)
314790087Sobrien	  && NOTE_LINE_NUMBER (x) == NOTE_INSN_DELETED_LABEL))
314818334Speter    ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
314918334Speter  else
3150169699Skan    output_operand_lossage ("'%%l' operand isn't a label");
315118334Speter
315218334Speter  assemble_name (asm_out_file, buf);
315318334Speter}
315418334Speter
315518334Speter/* Print operand X using machine-dependent assembler syntax.
315618334Speter   The macro PRINT_OPERAND is defined just to control this function.
315718334Speter   CODE is a non-digit that preceded the operand-number in the % spec,
315818334Speter   such as 'z' if the spec was `%z3'.  CODE is 0 if there was no char
315918334Speter   between the % and the digits.
316018334Speter   When CODE is a non-letter, X is 0.
316118334Speter
316218334Speter   The meanings of the letters are machine-dependent and controlled
316318334Speter   by PRINT_OPERAND.  */
316418334Speter
316518334Speterstatic void
3166132727Skanoutput_operand (rtx x, int code ATTRIBUTE_UNUSED)
316718334Speter{
316818334Speter  if (x && GET_CODE (x) == SUBREG)
316990087Sobrien    x = alter_subreg (&x);
317018334Speter
3171169699Skan  /* X must not be a pseudo reg.  */
3172169699Skan  gcc_assert (!x || !REG_P (x) || REGNO (x) < FIRST_PSEUDO_REGISTER);
317318334Speter
317418334Speter  PRINT_OPERAND (asm_out_file, x, code);
317518334Speter}
317618334Speter
317718334Speter/* Print a memory reference operand for address X
317818334Speter   using machine-dependent assembler syntax.
317918334Speter   The macro PRINT_OPERAND_ADDRESS exists just to control this function.  */
318018334Speter
318118334Spetervoid
3182132727Skanoutput_address (rtx x)
318318334Speter{
318490087Sobrien  walk_alter_subreg (&x);
318518334Speter  PRINT_OPERAND_ADDRESS (asm_out_file, x);
318618334Speter}
318718334Speter
318818334Speter/* Print an integer constant expression in assembler syntax.
318918334Speter   Addition and subtraction are the only arithmetic
319018334Speter   that may appear in these expressions.  */
319118334Speter
319218334Spetervoid
3193132727Skanoutput_addr_const (FILE *file, rtx x)
319418334Speter{
319518334Speter  char buf[256];
319618334Speter
319718334Speter restart:
319818334Speter  switch (GET_CODE (x))
319918334Speter    {
320018334Speter    case PC:
320190087Sobrien      putc ('.', file);
320218334Speter      break;
320318334Speter
320418334Speter    case SYMBOL_REF:
3205169699Skan      if (SYMBOL_REF_DECL (x))
3206169699Skan	mark_decl_referenced (SYMBOL_REF_DECL (x));
320790087Sobrien#ifdef ASM_OUTPUT_SYMBOL_REF
320890087Sobrien      ASM_OUTPUT_SYMBOL_REF (file, x);
320990087Sobrien#else
321018334Speter      assemble_name (file, XSTR (x, 0));
321190087Sobrien#endif
321218334Speter      break;
321318334Speter
321418334Speter    case LABEL_REF:
321590087Sobrien      x = XEXP (x, 0);
321690087Sobrien      /* Fall through.  */
321718334Speter    case CODE_LABEL:
321818334Speter      ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
321990087Sobrien#ifdef ASM_OUTPUT_LABEL_REF
322090087Sobrien      ASM_OUTPUT_LABEL_REF (file, buf);
322190087Sobrien#else
322218334Speter      assemble_name (file, buf);
322390087Sobrien#endif
322418334Speter      break;
322518334Speter
322618334Speter    case CONST_INT:
322750503Sobrien      fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
322818334Speter      break;
322918334Speter
323018334Speter    case CONST:
323118334Speter      /* This used to output parentheses around the expression,
323218334Speter	 but that does not work on the 386 (either ATT or BSD assembler).  */
323318334Speter      output_addr_const (file, XEXP (x, 0));
323418334Speter      break;
323518334Speter
323618334Speter    case CONST_DOUBLE:
323718334Speter      if (GET_MODE (x) == VOIDmode)
323818334Speter	{
323918334Speter	  /* We can use %d if the number is one word and positive.  */
324018334Speter	  if (CONST_DOUBLE_HIGH (x))
324150503Sobrien	    fprintf (file, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
324218334Speter		     CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));
324390087Sobrien	  else if (CONST_DOUBLE_LOW (x) < 0)
324450503Sobrien	    fprintf (file, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_LOW (x));
324518334Speter	  else
324650503Sobrien	    fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (x));
324718334Speter	}
324818334Speter      else
324918334Speter	/* We can't handle floating point constants;
325018334Speter	   PRINT_OPERAND must handle them.  */
325118334Speter	output_operand_lossage ("floating constant misused");
325218334Speter      break;
325318334Speter
325418334Speter    case PLUS:
325518334Speter      /* Some assemblers need integer constants to appear last (eg masm).  */
325618334Speter      if (GET_CODE (XEXP (x, 0)) == CONST_INT)
325718334Speter	{
325818334Speter	  output_addr_const (file, XEXP (x, 1));
325918334Speter	  if (INTVAL (XEXP (x, 0)) >= 0)
326018334Speter	    fprintf (file, "+");
326118334Speter	  output_addr_const (file, XEXP (x, 0));
326218334Speter	}
326318334Speter      else
326418334Speter	{
326518334Speter	  output_addr_const (file, XEXP (x, 0));
326690087Sobrien	  if (GET_CODE (XEXP (x, 1)) != CONST_INT
326790087Sobrien	      || INTVAL (XEXP (x, 1)) >= 0)
326818334Speter	    fprintf (file, "+");
326918334Speter	  output_addr_const (file, XEXP (x, 1));
327018334Speter	}
327118334Speter      break;
327218334Speter
327318334Speter    case MINUS:
327418334Speter      /* Avoid outputting things like x-x or x+5-x,
327518334Speter	 since some assemblers can't handle that.  */
327618334Speter      x = simplify_subtraction (x);
327718334Speter      if (GET_CODE (x) != MINUS)
327818334Speter	goto restart;
327918334Speter
328018334Speter      output_addr_const (file, XEXP (x, 0));
328118334Speter      fprintf (file, "-");
328290087Sobrien      if ((GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) >= 0)
328390087Sobrien	  || GET_CODE (XEXP (x, 1)) == PC
328490087Sobrien	  || GET_CODE (XEXP (x, 1)) == SYMBOL_REF)
328590087Sobrien	output_addr_const (file, XEXP (x, 1));
328690087Sobrien      else
328718334Speter	{
328890087Sobrien	  fputs (targetm.asm_out.open_paren, file);
328918334Speter	  output_addr_const (file, XEXP (x, 1));
329090087Sobrien	  fputs (targetm.asm_out.close_paren, file);
329118334Speter	}
329218334Speter      break;
329318334Speter
329418334Speter    case ZERO_EXTEND:
329518334Speter    case SIGN_EXTEND:
329696281Sobrien    case SUBREG:
329718334Speter      output_addr_const (file, XEXP (x, 0));
329818334Speter      break;
329918334Speter
330018334Speter    default:
330190087Sobrien#ifdef OUTPUT_ADDR_CONST_EXTRA
330290087Sobrien      OUTPUT_ADDR_CONST_EXTRA (file, x, fail);
330390087Sobrien      break;
330490087Sobrien
330590087Sobrien    fail:
330690087Sobrien#endif
330718334Speter      output_operand_lossage ("invalid expression as operand");
330818334Speter    }
330918334Speter}
331018334Speter
331118334Speter/* A poor man's fprintf, with the added features of %I, %R, %L, and %U.
331218334Speter   %R prints the value of REGISTER_PREFIX.
331318334Speter   %L prints the value of LOCAL_LABEL_PREFIX.
331418334Speter   %U prints the value of USER_LABEL_PREFIX.
331518334Speter   %I prints the value of IMMEDIATE_PREFIX.
331618334Speter   %O runs ASM_OUTPUT_OPCODE to transform what follows in the string.
3317132727Skan   Also supported are %d, %i, %u, %x, %X, %o, %c, %s and %%.
331818334Speter
331918334Speter   We handle alternate assembler dialects here, just like output_asm_insn.  */
332018334Speter
332118334Spetervoid
3322132727Skanasm_fprintf (FILE *file, const char *p, ...)
332318334Speter{
332418334Speter  char buf[10];
332518334Speter  char *q, c;
3326132727Skan  va_list argptr;
332718334Speter
3328132727Skan  va_start (argptr, p);
332918334Speter
333018334Speter  buf[0] = '%';
333118334Speter
333250503Sobrien  while ((c = *p++))
333318334Speter    switch (c)
333418334Speter      {
333518334Speter#ifdef ASSEMBLER_DIALECT
333618334Speter      case '{':
333750503Sobrien	{
333850503Sobrien	  int i;
333918334Speter
334050503Sobrien	  /* If we want the first dialect, do nothing.  Otherwise, skip
334150503Sobrien	     DIALECT_NUMBER of strings ending with '|'.  */
334250503Sobrien	  for (i = 0; i < dialect_number; i++)
334350503Sobrien	    {
334450503Sobrien	      while (*p && *p++ != '|')
334550503Sobrien		;
334650503Sobrien
334750503Sobrien	      if (*p == '|')
334850503Sobrien		p++;
334990087Sobrien	    }
335050503Sobrien	}
335118334Speter	break;
335218334Speter
335318334Speter      case '|':
335418334Speter	/* Skip to close brace.  */
335518334Speter	while (*p && *p++ != '}')
335618334Speter	  ;
335718334Speter	break;
335818334Speter
335918334Speter      case '}':
336018334Speter	break;
336118334Speter#endif
336218334Speter
336318334Speter      case '%':
336418334Speter	c = *p++;
336518334Speter	q = &buf[1];
3366132727Skan	while (strchr ("-+ #0", c))
3367132727Skan	  {
3368132727Skan	    *q++ = c;
3369132727Skan	    c = *p++;
3370132727Skan	  }
337190087Sobrien	while (ISDIGIT (c) || c == '.')
337218334Speter	  {
337318334Speter	    *q++ = c;
337418334Speter	    c = *p++;
337518334Speter	  }
337618334Speter	switch (c)
337718334Speter	  {
337818334Speter	  case '%':
3379132727Skan	    putc ('%', file);
338018334Speter	    break;
338118334Speter
338218334Speter	  case 'd':  case 'i':  case 'u':
3383132727Skan	  case 'x':  case 'X':  case 'o':
3384132727Skan	  case 'c':
338518334Speter	    *q++ = c;
338618334Speter	    *q = 0;
338718334Speter	    fprintf (file, buf, va_arg (argptr, int));
338818334Speter	    break;
338918334Speter
339018334Speter	  case 'w':
3391132727Skan	    /* This is a prefix to the 'd', 'i', 'u', 'x', 'X', and
3392132727Skan	       'o' cases, but we do not check for those cases.  It
3393132727Skan	       means that the value is a HOST_WIDE_INT, which may be
3394132727Skan	       either `long' or `long long'.  */
3395132727Skan	    memcpy (q, HOST_WIDE_INT_PRINT, strlen (HOST_WIDE_INT_PRINT));
3396132727Skan	    q += strlen (HOST_WIDE_INT_PRINT);
339718334Speter	    *q++ = *p++;
339818334Speter	    *q = 0;
339918334Speter	    fprintf (file, buf, va_arg (argptr, HOST_WIDE_INT));
340018334Speter	    break;
340118334Speter
340218334Speter	  case 'l':
340318334Speter	    *q++ = c;
3404132727Skan#ifdef HAVE_LONG_LONG
3405132727Skan	    if (*p == 'l')
3406132727Skan	      {
3407132727Skan		*q++ = *p++;
3408132727Skan		*q++ = *p++;
3409132727Skan		*q = 0;
3410132727Skan		fprintf (file, buf, va_arg (argptr, long long));
3411132727Skan	      }
3412132727Skan	    else
3413132727Skan#endif
3414132727Skan	      {
3415132727Skan		*q++ = *p++;
3416132727Skan		*q = 0;
3417132727Skan		fprintf (file, buf, va_arg (argptr, long));
3418132727Skan	      }
341918334Speter
342018334Speter	    break;
342118334Speter
342218334Speter	  case 's':
342318334Speter	    *q++ = c;
342418334Speter	    *q = 0;
342518334Speter	    fprintf (file, buf, va_arg (argptr, char *));
342618334Speter	    break;
342718334Speter
342818334Speter	  case 'O':
342918334Speter#ifdef ASM_OUTPUT_OPCODE
343018334Speter	    ASM_OUTPUT_OPCODE (asm_out_file, p);
343118334Speter#endif
343218334Speter	    break;
343318334Speter
343418334Speter	  case 'R':
343518334Speter#ifdef REGISTER_PREFIX
343618334Speter	    fprintf (file, "%s", REGISTER_PREFIX);
343718334Speter#endif
343818334Speter	    break;
343918334Speter
344018334Speter	  case 'I':
344118334Speter#ifdef IMMEDIATE_PREFIX
344218334Speter	    fprintf (file, "%s", IMMEDIATE_PREFIX);
344318334Speter#endif
344418334Speter	    break;
344518334Speter
344618334Speter	  case 'L':
344718334Speter#ifdef LOCAL_LABEL_PREFIX
344818334Speter	    fprintf (file, "%s", LOCAL_LABEL_PREFIX);
344918334Speter#endif
345018334Speter	    break;
345118334Speter
345218334Speter	  case 'U':
345352515Sobrien	    fputs (user_label_prefix, file);
345418334Speter	    break;
345518334Speter
345690087Sobrien#ifdef ASM_FPRINTF_EXTENSIONS
3457132727Skan	    /* Uppercase letters are reserved for general use by asm_fprintf
345890087Sobrien	       and so are not available to target specific code.  In order to
345990087Sobrien	       prevent the ASM_FPRINTF_EXTENSIONS macro from using them then,
346090087Sobrien	       they are defined here.  As they get turned into real extensions
346190087Sobrien	       to asm_fprintf they should be removed from this list.  */
346290087Sobrien	  case 'A': case 'B': case 'C': case 'D': case 'E':
346390087Sobrien	  case 'F': case 'G': case 'H': case 'J': case 'K':
346490087Sobrien	  case 'M': case 'N': case 'P': case 'Q': case 'S':
346590087Sobrien	  case 'T': case 'V': case 'W': case 'Y': case 'Z':
346690087Sobrien	    break;
346790087Sobrien
346890087Sobrien	  ASM_FPRINTF_EXTENSIONS (file, argptr, p)
346990087Sobrien#endif
347018334Speter	  default:
3471169699Skan	    gcc_unreachable ();
347218334Speter	  }
347318334Speter	break;
347418334Speter
347518334Speter      default:
3476132727Skan	putc (c, file);
347718334Speter      }
3478132727Skan  va_end (argptr);
347918334Speter}
348018334Speter
348118334Speter/* Split up a CONST_DOUBLE or integer constant rtx
348218334Speter   into two rtx's for single words,
348318334Speter   storing in *FIRST the word that comes first in memory in the target
348418334Speter   and in *SECOND the other.  */
348518334Speter
348618334Spetervoid
3487132727Skansplit_double (rtx value, rtx *first, rtx *second)
348818334Speter{
348918334Speter  if (GET_CODE (value) == CONST_INT)
349018334Speter    {
349118334Speter      if (HOST_BITS_PER_WIDE_INT >= (2 * BITS_PER_WORD))
349218334Speter	{
349318334Speter	  /* In this case the CONST_INT holds both target words.
349450503Sobrien	     Extract the bits from it into two word-sized pieces.
349550503Sobrien	     Sign extend each half to HOST_WIDE_INT.  */
349690087Sobrien	  unsigned HOST_WIDE_INT low, high;
349790087Sobrien	  unsigned HOST_WIDE_INT mask, sign_bit, sign_extend;
349818334Speter
349990087Sobrien	  /* Set sign_bit to the most significant bit of a word.  */
350090087Sobrien	  sign_bit = 1;
350190087Sobrien	  sign_bit <<= BITS_PER_WORD - 1;
350290087Sobrien
350390087Sobrien	  /* Set mask so that all bits of the word are set.  We could
350490087Sobrien	     have used 1 << BITS_PER_WORD instead of basing the
350590087Sobrien	     calculation on sign_bit.  However, on machines where
350690087Sobrien	     HOST_BITS_PER_WIDE_INT == BITS_PER_WORD, it could cause a
350790087Sobrien	     compiler warning, even though the code would never be
350890087Sobrien	     executed.  */
350990087Sobrien	  mask = sign_bit << 1;
351090087Sobrien	  mask--;
351190087Sobrien
351290087Sobrien	  /* Set sign_extend as any remaining bits.  */
351390087Sobrien	  sign_extend = ~mask;
351490087Sobrien
351590087Sobrien	  /* Pick the lower word and sign-extend it.  */
351690087Sobrien	  low = INTVAL (value);
351790087Sobrien	  low &= mask;
351890087Sobrien	  if (low & sign_bit)
351990087Sobrien	    low |= sign_extend;
352090087Sobrien
352190087Sobrien	  /* Pick the higher word, shifted to the least significant
352290087Sobrien	     bits, and sign-extend it.  */
352390087Sobrien	  high = INTVAL (value);
352490087Sobrien	  high >>= BITS_PER_WORD - 1;
352590087Sobrien	  high >>= 1;
352690087Sobrien	  high &= mask;
352790087Sobrien	  if (high & sign_bit)
352890087Sobrien	    high |= sign_extend;
352990087Sobrien
353090087Sobrien	  /* Store the words in the target machine order.  */
353118334Speter	  if (WORDS_BIG_ENDIAN)
353218334Speter	    {
353390087Sobrien	      *first = GEN_INT (high);
353490087Sobrien	      *second = GEN_INT (low);
353518334Speter	    }
353618334Speter	  else
353718334Speter	    {
353890087Sobrien	      *first = GEN_INT (low);
353990087Sobrien	      *second = GEN_INT (high);
354018334Speter	    }
354118334Speter	}
354218334Speter      else
354318334Speter	{
354418334Speter	  /* The rule for using CONST_INT for a wider mode
354518334Speter	     is that we regard the value as signed.
354618334Speter	     So sign-extend it.  */
354718334Speter	  rtx high = (INTVAL (value) < 0 ? constm1_rtx : const0_rtx);
354818334Speter	  if (WORDS_BIG_ENDIAN)
354918334Speter	    {
355018334Speter	      *first = high;
355118334Speter	      *second = value;
355218334Speter	    }
355318334Speter	  else
355418334Speter	    {
355518334Speter	      *first = value;
355618334Speter	      *second = high;
355718334Speter	    }
355818334Speter	}
355918334Speter    }
356018334Speter  else if (GET_CODE (value) != CONST_DOUBLE)
356118334Speter    {
356218334Speter      if (WORDS_BIG_ENDIAN)
356318334Speter	{
356418334Speter	  *first = const0_rtx;
356518334Speter	  *second = value;
356618334Speter	}
356718334Speter      else
356818334Speter	{
356918334Speter	  *first = value;
357018334Speter	  *second = const0_rtx;
357118334Speter	}
357218334Speter    }
357318334Speter  else if (GET_MODE (value) == VOIDmode
357418334Speter	   /* This is the old way we did CONST_DOUBLE integers.  */
357518334Speter	   || GET_MODE_CLASS (GET_MODE (value)) == MODE_INT)
357618334Speter    {
357718334Speter      /* In an integer, the words are defined as most and least significant.
357818334Speter	 So order them by the target's convention.  */
357918334Speter      if (WORDS_BIG_ENDIAN)
358018334Speter	{
358118334Speter	  *first = GEN_INT (CONST_DOUBLE_HIGH (value));
358218334Speter	  *second = GEN_INT (CONST_DOUBLE_LOW (value));
358318334Speter	}
358418334Speter      else
358518334Speter	{
358618334Speter	  *first = GEN_INT (CONST_DOUBLE_LOW (value));
358718334Speter	  *second = GEN_INT (CONST_DOUBLE_HIGH (value));
358818334Speter	}
358918334Speter    }
359018334Speter  else
359118334Speter    {
359290087Sobrien      REAL_VALUE_TYPE r;
359390087Sobrien      long l[2];
359418334Speter      REAL_VALUE_FROM_CONST_DOUBLE (r, value);
359518334Speter
359618334Speter      /* Note, this converts the REAL_VALUE_TYPE to the target's
359718334Speter	 format, splits up the floating point double and outputs
359818334Speter	 exactly 32 bits of it into each of l[0] and l[1] --
359950503Sobrien	 not necessarily BITS_PER_WORD bits.  */
360018334Speter      REAL_VALUE_TO_TARGET_DOUBLE (r, l);
360118334Speter
360252515Sobrien      /* If 32 bits is an entire word for the target, but not for the host,
360352515Sobrien	 then sign-extend on the host so that the number will look the same
360452515Sobrien	 way on the host that it would on the target.  See for instance
360552515Sobrien	 simplify_unary_operation.  The #if is needed to avoid compiler
360652515Sobrien	 warnings.  */
360752515Sobrien
360852515Sobrien#if HOST_BITS_PER_LONG > 32
360952515Sobrien      if (BITS_PER_WORD < HOST_BITS_PER_LONG && BITS_PER_WORD == 32)
361052515Sobrien	{
361152515Sobrien	  if (l[0] & ((long) 1 << 31))
361252515Sobrien	    l[0] |= ((long) (-1) << 32);
361352515Sobrien	  if (l[1] & ((long) 1 << 31))
361452515Sobrien	    l[1] |= ((long) (-1) << 32);
361552515Sobrien	}
361652515Sobrien#endif
361752515Sobrien
3618169699Skan      *first = GEN_INT (l[0]);
3619169699Skan      *second = GEN_INT (l[1]);
362018334Speter    }
362118334Speter}
362218334Speter
362318334Speter/* Return nonzero if this function has no function calls.  */
362418334Speter
362518334Speterint
3626132727Skanleaf_function_p (void)
362718334Speter{
362818334Speter  rtx insn;
362990087Sobrien  rtx link;
363018334Speter
363190087Sobrien  if (current_function_profile || profile_arc_flag)
363218334Speter    return 0;
363318334Speter
363418334Speter  for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
363518334Speter    {
3636169699Skan      if (CALL_P (insn)
363790087Sobrien	  && ! SIBLING_CALL_P (insn))
363818334Speter	return 0;
3639169699Skan      if (NONJUMP_INSN_P (insn)
364018334Speter	  && GET_CODE (PATTERN (insn)) == SEQUENCE
3641169699Skan	  && CALL_P (XVECEXP (PATTERN (insn), 0, 0))
364290087Sobrien	  && ! SIBLING_CALL_P (XVECEXP (PATTERN (insn), 0, 0)))
364318334Speter	return 0;
364418334Speter    }
364590087Sobrien  for (link = current_function_epilogue_delay_list;
364690087Sobrien       link;
364790087Sobrien       link = XEXP (link, 1))
364818334Speter    {
364990087Sobrien      insn = XEXP (link, 0);
365090087Sobrien
3651169699Skan      if (CALL_P (insn)
365290087Sobrien	  && ! SIBLING_CALL_P (insn))
365318334Speter	return 0;
3654169699Skan      if (NONJUMP_INSN_P (insn)
365590087Sobrien	  && GET_CODE (PATTERN (insn)) == SEQUENCE
3656169699Skan	  && CALL_P (XVECEXP (PATTERN (insn), 0, 0))
365790087Sobrien	  && ! SIBLING_CALL_P (XVECEXP (PATTERN (insn), 0, 0)))
365818334Speter	return 0;
365918334Speter    }
366018334Speter
366118334Speter  return 1;
366218334Speter}
366318334Speter
3664117404Skan/* Return 1 if branch is a forward branch.
366590087Sobrien   Uses insn_shuid array, so it works only in the final pass.  May be used by
366690087Sobrien   output templates to customary add branch prediction hints.
366790087Sobrien */
366890087Sobrienint
3669132727Skanfinal_forward_branch_p (rtx insn)
367090087Sobrien{
367190087Sobrien  int insn_id, label_id;
3672169699Skan
3673169699Skan  gcc_assert (uid_shuid);
367490087Sobrien  insn_id = INSN_SHUID (insn);
367590087Sobrien  label_id = INSN_SHUID (JUMP_LABEL (insn));
367690087Sobrien  /* We've hit some insns that does not have id information available.  */
3677169699Skan  gcc_assert (insn_id && label_id);
367890087Sobrien  return insn_id < label_id;
367990087Sobrien}
368090087Sobrien
368118334Speter/* On some machines, a function with no call insns
368218334Speter   can run faster if it doesn't create its own register window.
368318334Speter   When output, the leaf function should use only the "output"
368418334Speter   registers.  Ordinarily, the function would be compiled to use
368518334Speter   the "input" registers to find its arguments; it is a candidate
368618334Speter   for leaf treatment if it uses only the "input" registers.
368718334Speter   Leaf function treatment means renumbering so the function
368818334Speter   uses the "output" registers instead.  */
368918334Speter
369018334Speter#ifdef LEAF_REGISTERS
369118334Speter
369218334Speter/* Return 1 if this function uses only the registers that can be
369318334Speter   safely renumbered.  */
369418334Speter
369518334Speterint
3696132727Skanonly_leaf_regs_used (void)
369718334Speter{
369818334Speter  int i;
3699132727Skan  const char *const permitted_reg_in_leaf_functions = LEAF_REGISTERS;
370018334Speter
370118334Speter  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
370250503Sobrien    if ((regs_ever_live[i] || global_regs[i])
370350503Sobrien	&& ! permitted_reg_in_leaf_functions[i])
370450503Sobrien      return 0;
370550503Sobrien
370650503Sobrien  if (current_function_uses_pic_offset_table
370750503Sobrien      && pic_offset_table_rtx != 0
3708169699Skan      && REG_P (pic_offset_table_rtx)
370950503Sobrien      && ! permitted_reg_in_leaf_functions[REGNO (pic_offset_table_rtx)])
371050503Sobrien    return 0;
371150503Sobrien
371218334Speter  return 1;
371318334Speter}
371418334Speter
371518334Speter/* Scan all instructions and renumber all registers into those
371618334Speter   available in leaf functions.  */
371718334Speter
371818334Speterstatic void
3719132727Skanleaf_renumber_regs (rtx first)
372018334Speter{
372118334Speter  rtx insn;
372218334Speter
372318334Speter  /* Renumber only the actual patterns.
372418334Speter     The reg-notes can contain frame pointer refs,
372518334Speter     and renumbering them could crash, and should not be needed.  */
372618334Speter  for (insn = first; insn; insn = NEXT_INSN (insn))
372790087Sobrien    if (INSN_P (insn))
372818334Speter      leaf_renumber_regs_insn (PATTERN (insn));
372990087Sobrien  for (insn = current_function_epilogue_delay_list;
373090087Sobrien       insn;
373190087Sobrien       insn = XEXP (insn, 1))
373290087Sobrien    if (INSN_P (XEXP (insn, 0)))
373318334Speter      leaf_renumber_regs_insn (PATTERN (XEXP (insn, 0)));
373418334Speter}
373518334Speter
373618334Speter/* Scan IN_RTX and its subexpressions, and renumber all regs into those
373718334Speter   available in leaf functions.  */
373818334Speter
373918334Spetervoid
3740132727Skanleaf_renumber_regs_insn (rtx in_rtx)
374118334Speter{
374290087Sobrien  int i, j;
374390087Sobrien  const char *format_ptr;
374418334Speter
374518334Speter  if (in_rtx == 0)
374618334Speter    return;
374718334Speter
374818334Speter  /* Renumber all input-registers into output-registers.
374918334Speter     renumbered_regs would be 1 for an output-register;
375018334Speter     they  */
375118334Speter
3752169699Skan  if (REG_P (in_rtx))
375318334Speter    {
375418334Speter      int newreg;
375518334Speter
375618334Speter      /* Don't renumber the same reg twice.  */
375718334Speter      if (in_rtx->used)
375818334Speter	return;
375918334Speter
376018334Speter      newreg = REGNO (in_rtx);
376118334Speter      /* Don't try to renumber pseudo regs.  It is possible for a pseudo reg
376218334Speter	 to reach here as part of a REG_NOTE.  */
376318334Speter      if (newreg >= FIRST_PSEUDO_REGISTER)
376418334Speter	{
376518334Speter	  in_rtx->used = 1;
376618334Speter	  return;
376718334Speter	}
376818334Speter      newreg = LEAF_REG_REMAP (newreg);
3769169699Skan      gcc_assert (newreg >= 0);
377018334Speter      regs_ever_live[REGNO (in_rtx)] = 0;
377118334Speter      regs_ever_live[newreg] = 1;
377218334Speter      REGNO (in_rtx) = newreg;
377318334Speter      in_rtx->used = 1;
377418334Speter    }
377518334Speter
377690087Sobrien  if (INSN_P (in_rtx))
377718334Speter    {
377818334Speter      /* Inside a SEQUENCE, we find insns.
377918334Speter	 Renumber just the patterns of these insns,
378018334Speter	 just as we do for the top-level insns.  */
378118334Speter      leaf_renumber_regs_insn (PATTERN (in_rtx));
378218334Speter      return;
378318334Speter    }
378418334Speter
378518334Speter  format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx));
378618334Speter
378718334Speter  for (i = 0; i < GET_RTX_LENGTH (GET_CODE (in_rtx)); i++)
378818334Speter    switch (*format_ptr++)
378918334Speter      {
379018334Speter      case 'e':
379118334Speter	leaf_renumber_regs_insn (XEXP (in_rtx, i));
379218334Speter	break;
379318334Speter
379418334Speter      case 'E':
379518334Speter	if (NULL != XVEC (in_rtx, i))
379618334Speter	  {
379718334Speter	    for (j = 0; j < XVECLEN (in_rtx, i); j++)
379818334Speter	      leaf_renumber_regs_insn (XVECEXP (in_rtx, i, j));
379918334Speter	  }
380018334Speter	break;
380118334Speter
380218334Speter      case 'S':
380318334Speter      case 's':
380418334Speter      case '0':
380518334Speter      case 'i':
380618334Speter      case 'w':
380718334Speter      case 'n':
380818334Speter      case 'u':
380918334Speter	break;
381018334Speter
381118334Speter      default:
3812169699Skan	gcc_unreachable ();
381318334Speter      }
381418334Speter}
381518334Speter#endif
3816132727Skan
3817132727Skan
3818132727Skan/* When -gused is used, emit debug info for only used symbols. But in
3819132727Skan   addition to the standard intercepted debug_hooks there are some direct
3820132727Skan   calls into this file, i.e., dbxout_symbol, dbxout_parms, and dbxout_reg_params.
3821132727Skan   Those routines may also be called from a higher level intercepted routine. So
3822132727Skan   to prevent recording data for an inner call to one of these for an intercept,
3823132727Skan   we maintain an intercept nesting counter (debug_nesting). We only save the
3824132727Skan   intercepted arguments if the nesting is 1.  */
3825132727Skanint debug_nesting = 0;
3826132727Skan
3827132727Skanstatic tree *symbol_queue;
3828132727Skanint symbol_queue_index = 0;
3829132727Skanstatic int symbol_queue_size = 0;
3830132727Skan
3831132727Skan/* Generate the symbols for any queued up type symbols we encountered
3832132727Skan   while generating the type info for some originally used symbol.
3833132727Skan   This might generate additional entries in the queue.  Only when
3834132727Skan   the nesting depth goes to 0 is this routine called.  */
3835132727Skan
3836132727Skanvoid
3837132727Skandebug_flush_symbol_queue (void)
3838132727Skan{
3839132727Skan  int i;
3840132727Skan
3841132727Skan  /* Make sure that additionally queued items are not flushed
3842132727Skan     prematurely.  */
3843132727Skan
3844132727Skan  ++debug_nesting;
3845132727Skan
3846132727Skan  for (i = 0; i < symbol_queue_index; ++i)
3847132727Skan    {
3848169699Skan      /* If we pushed queued symbols then such symbols must be
3849132727Skan         output no matter what anyone else says.  Specifically,
3850132727Skan         we need to make sure dbxout_symbol() thinks the symbol was
3851132727Skan         used and also we need to override TYPE_DECL_SUPPRESS_DEBUG
3852132727Skan         which may be set for outside reasons.  */
3853132727Skan      int saved_tree_used = TREE_USED (symbol_queue[i]);
3854132727Skan      int saved_suppress_debug = TYPE_DECL_SUPPRESS_DEBUG (symbol_queue[i]);
3855132727Skan      TREE_USED (symbol_queue[i]) = 1;
3856132727Skan      TYPE_DECL_SUPPRESS_DEBUG (symbol_queue[i]) = 0;
3857132727Skan
3858132727Skan#ifdef DBX_DEBUGGING_INFO
3859132727Skan      dbxout_symbol (symbol_queue[i], 0);
3860132727Skan#endif
3861132727Skan
3862132727Skan      TREE_USED (symbol_queue[i]) = saved_tree_used;
3863132727Skan      TYPE_DECL_SUPPRESS_DEBUG (symbol_queue[i]) = saved_suppress_debug;
3864132727Skan    }
3865132727Skan
3866132727Skan  symbol_queue_index = 0;
3867132727Skan  --debug_nesting;
3868132727Skan}
3869132727Skan
3870132727Skan/* Queue a type symbol needed as part of the definition of a decl
3871132727Skan   symbol.  These symbols are generated when debug_flush_symbol_queue()
3872132727Skan   is called.  */
3873132727Skan
3874132727Skanvoid
3875132727Skandebug_queue_symbol (tree decl)
3876132727Skan{
3877132727Skan  if (symbol_queue_index >= symbol_queue_size)
3878132727Skan    {
3879132727Skan      symbol_queue_size += 10;
3880132727Skan      symbol_queue = xrealloc (symbol_queue,
3881132727Skan			       symbol_queue_size * sizeof (tree));
3882132727Skan    }
3883132727Skan
3884132727Skan  symbol_queue[symbol_queue_index++] = decl;
3885132727Skan}
3886132727Skan
3887132727Skan/* Free symbol queue.  */
3888132727Skanvoid
3889132727Skandebug_free_queue (void)
3890132727Skan{
3891132727Skan  if (symbol_queue)
3892132727Skan    {
3893132727Skan      free (symbol_queue);
3894132727Skan      symbol_queue = NULL;
3895132727Skan      symbol_queue_size = 0;
3896132727Skan    }
3897132727Skan}
3898169699Skan
3899169699Skan/* Turn the RTL into assembly.  */
3900169699Skanstatic unsigned int
3901169699Skanrest_of_handle_final (void)
3902169699Skan{
3903169699Skan  rtx x;
3904169699Skan  const char *fnname;
3905169699Skan
3906169699Skan  /* Get the function's name, as described by its RTL.  This may be
3907169699Skan     different from the DECL_NAME name used in the source file.  */
3908169699Skan
3909169699Skan  x = DECL_RTL (current_function_decl);
3910169699Skan  gcc_assert (MEM_P (x));
3911169699Skan  x = XEXP (x, 0);
3912169699Skan  gcc_assert (GET_CODE (x) == SYMBOL_REF);
3913169699Skan  fnname = XSTR (x, 0);
3914169699Skan
3915169699Skan  assemble_start_function (current_function_decl, fnname);
3916169699Skan  final_start_function (get_insns (), asm_out_file, optimize);
3917169699Skan  final (get_insns (), asm_out_file, optimize);
3918169699Skan  final_end_function ();
3919169699Skan
3920169699Skan#ifdef TARGET_UNWIND_INFO
3921169699Skan  /* ??? The IA-64 ".handlerdata" directive must be issued before
3922169699Skan     the ".endp" directive that closes the procedure descriptor.  */
3923169699Skan  output_function_exception_table ();
3924169699Skan#endif
3925169699Skan
3926169699Skan  assemble_end_function (current_function_decl, fnname);
3927169699Skan
3928169699Skan#ifndef TARGET_UNWIND_INFO
3929169699Skan  /* Otherwise, it feels unclean to switch sections in the middle.  */
3930169699Skan  output_function_exception_table ();
3931169699Skan#endif
3932169699Skan
3933169699Skan  user_defined_section_attribute = false;
3934169699Skan
3935169699Skan  if (! quiet_flag)
3936169699Skan    fflush (asm_out_file);
3937169699Skan
3938169699Skan  /* Release all memory allocated by flow.  */
3939169699Skan  free_basic_block_vars ();
3940169699Skan
3941169699Skan  /* Write DBX symbols if requested.  */
3942169699Skan
3943169699Skan  /* Note that for those inline functions where we don't initially
3944169699Skan     know for certain that we will be generating an out-of-line copy,
3945169699Skan     the first invocation of this routine (rest_of_compilation) will
3946169699Skan     skip over this code by doing a `goto exit_rest_of_compilation;'.
3947169699Skan     Later on, wrapup_global_declarations will (indirectly) call
3948169699Skan     rest_of_compilation again for those inline functions that need
3949169699Skan     to have out-of-line copies generated.  During that call, we
3950169699Skan     *will* be routed past here.  */
3951169699Skan
3952169699Skan  timevar_push (TV_SYMOUT);
3953169699Skan  (*debug_hooks->function_decl) (current_function_decl);
3954169699Skan  timevar_pop (TV_SYMOUT);
3955169699Skan  return 0;
3956169699Skan}
3957169699Skan
3958169699Skanstruct tree_opt_pass pass_final =
3959169699Skan{
3960169699Skan  NULL,                                 /* name */
3961169699Skan  NULL,                                 /* gate */
3962169699Skan  rest_of_handle_final,                 /* execute */
3963169699Skan  NULL,                                 /* sub */
3964169699Skan  NULL,                                 /* next */
3965169699Skan  0,                                    /* static_pass_number */
3966169699Skan  TV_FINAL,                             /* tv_id */
3967169699Skan  0,                                    /* properties_required */
3968169699Skan  0,                                    /* properties_provided */
3969169699Skan  0,                                    /* properties_destroyed */
3970169699Skan  0,                                    /* todo_flags_start */
3971169699Skan  TODO_ggc_collect,                     /* todo_flags_finish */
3972169699Skan  0                                     /* letter */
3973169699Skan};
3974169699Skan
3975169699Skan
3976169699Skanstatic unsigned int
3977169699Skanrest_of_handle_shorten_branches (void)
3978169699Skan{
3979169699Skan  /* Shorten branches.  */
3980169699Skan  shorten_branches (get_insns ());
3981169699Skan  return 0;
3982169699Skan}
3983169699Skan
3984169699Skanstruct tree_opt_pass pass_shorten_branches =
3985169699Skan{
3986169699Skan  "shorten",                            /* name */
3987169699Skan  NULL,                                 /* gate */
3988169699Skan  rest_of_handle_shorten_branches,      /* execute */
3989169699Skan  NULL,                                 /* sub */
3990169699Skan  NULL,                                 /* next */
3991169699Skan  0,                                    /* static_pass_number */
3992169699Skan  TV_FINAL,                             /* tv_id */
3993169699Skan  0,                                    /* properties_required */
3994169699Skan  0,                                    /* properties_provided */
3995169699Skan  0,                                    /* properties_destroyed */
3996169699Skan  0,                                    /* todo_flags_start */
3997169699Skan  TODO_dump_func,                       /* todo_flags_finish */
3998169699Skan  0                                     /* letter */
3999169699Skan};
4000169699Skan
4001169699Skan
4002169699Skanstatic unsigned int
4003169699Skanrest_of_clean_state (void)
4004169699Skan{
4005169699Skan  rtx insn, next;
4006169699Skan
4007169699Skan  /* It is very important to decompose the RTL instruction chain here:
4008169699Skan     debug information keeps pointing into CODE_LABEL insns inside the function
4009169699Skan     body.  If these remain pointing to the other insns, we end up preserving
4010169699Skan     whole RTL chain and attached detailed debug info in memory.  */
4011169699Skan  for (insn = get_insns (); insn; insn = next)
4012169699Skan    {
4013169699Skan      next = NEXT_INSN (insn);
4014169699Skan      NEXT_INSN (insn) = NULL;
4015169699Skan      PREV_INSN (insn) = NULL;
4016169699Skan    }
4017169699Skan
4018169699Skan  /* In case the function was not output,
4019169699Skan     don't leave any temporary anonymous types
4020169699Skan     queued up for sdb output.  */
4021169699Skan#ifdef SDB_DEBUGGING_INFO
4022169699Skan  if (write_symbols == SDB_DEBUG)
4023169699Skan    sdbout_types (NULL_TREE);
4024169699Skan#endif
4025169699Skan
4026169699Skan  reload_completed = 0;
4027169699Skan  epilogue_completed = 0;
4028169699Skan  flow2_completed = 0;
4029169699Skan  no_new_pseudos = 0;
4030169699Skan#ifdef STACK_REGS
4031169699Skan  regstack_completed = 0;
4032169699Skan#endif
4033169699Skan
4034169699Skan  /* Clear out the insn_length contents now that they are no
4035169699Skan     longer valid.  */
4036169699Skan  init_insn_lengths ();
4037169699Skan
4038169699Skan  /* Show no temporary slots allocated.  */
4039169699Skan  init_temp_slots ();
4040169699Skan
4041169699Skan  free_basic_block_vars ();
4042169699Skan  free_bb_for_insn ();
4043169699Skan
4044169699Skan
4045169699Skan  if (targetm.binds_local_p (current_function_decl))
4046169699Skan    {
4047169699Skan      int pref = cfun->preferred_stack_boundary;
4048169699Skan      if (cfun->stack_alignment_needed > cfun->preferred_stack_boundary)
4049169699Skan        pref = cfun->stack_alignment_needed;
4050169699Skan      cgraph_rtl_info (current_function_decl)->preferred_incoming_stack_boundary
4051169699Skan        = pref;
4052169699Skan    }
4053169699Skan
4054169699Skan  /* Make sure volatile mem refs aren't considered valid operands for
4055169699Skan     arithmetic insns.  We must call this here if this is a nested inline
4056169699Skan     function, since the above code leaves us in the init_recog state,
4057169699Skan     and the function context push/pop code does not save/restore volatile_ok.
4058169699Skan
4059169699Skan     ??? Maybe it isn't necessary for expand_start_function to call this
4060169699Skan     anymore if we do it here?  */
4061169699Skan
4062169699Skan  init_recog_no_volatile ();
4063169699Skan
4064169699Skan  /* We're done with this function.  Free up memory if we can.  */
4065169699Skan  free_after_parsing (cfun);
4066169699Skan  free_after_compilation (cfun);
4067169699Skan  return 0;
4068169699Skan}
4069169699Skan
4070169699Skanstruct tree_opt_pass pass_clean_state =
4071169699Skan{
4072169699Skan  NULL,                                 /* name */
4073169699Skan  NULL,                                 /* gate */
4074169699Skan  rest_of_clean_state,                  /* execute */
4075169699Skan  NULL,                                 /* sub */
4076169699Skan  NULL,                                 /* next */
4077169699Skan  0,                                    /* static_pass_number */
4078169699Skan  TV_FINAL,                             /* tv_id */
4079169699Skan  0,                                    /* properties_required */
4080169699Skan  0,                                    /* properties_provided */
4081169699Skan  PROP_rtl,                             /* properties_destroyed */
4082169699Skan  0,                                    /* todo_flags_start */
4083169699Skan  0,                                    /* todo_flags_finish */
4084169699Skan  0                                     /* letter */
4085169699Skan};
4086169699Skan
4087