reg-stack.c revision 52284
118334Speter/* Register to Stack convert for GNU compiler.
252284Sobrien   Copyright (C) 1992, 93-98, 1999 Free Software Foundation, Inc.
318334Speter
418334SpeterThis file is part of GNU CC.
518334Speter
618334SpeterGNU CC is free software; you can redistribute it and/or modify
718334Speterit under the terms of the GNU General Public License as published by
818334Speterthe Free Software Foundation; either version 2, or (at your option)
918334Speterany later version.
1018334Speter
1118334SpeterGNU CC is distributed in the hope that it will be useful,
1218334Speterbut WITHOUT ANY WARRANTY; without even the implied warranty of
1318334SpeterMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1418334SpeterGNU General Public License for more details.
1518334Speter
1618334SpeterYou should have received a copy of the GNU General Public License
1718334Speteralong with GNU CC; see the file COPYING.  If not, write to
1818334Speterthe Free Software Foundation, 59 Temple Place - Suite 330,
1918334SpeterBoston, MA 02111-1307, USA.  */
2018334Speter
2118334Speter/* This pass converts stack-like registers from the "flat register
2218334Speter   file" model that gcc uses, to a stack convention that the 387 uses.
2318334Speter
2418334Speter   * The form of the input:
2518334Speter
2618334Speter   On input, the function consists of insn that have had their
2718334Speter   registers fully allocated to a set of "virtual" registers.  Note that
2818334Speter   the word "virtual" is used differently here than elsewhere in gcc: for
2918334Speter   each virtual stack reg, there is a hard reg, but the mapping between
3018334Speter   them is not known until this pass is run.  On output, hard register
3118334Speter   numbers have been substituted, and various pop and exchange insns have
3218334Speter   been emitted.  The hard register numbers and the virtual register
3318334Speter   numbers completely overlap - before this pass, all stack register
3418334Speter   numbers are virtual, and afterward they are all hard.
3518334Speter
3618334Speter   The virtual registers can be manipulated normally by gcc, and their
3718334Speter   semantics are the same as for normal registers.  After the hard
3818334Speter   register numbers are substituted, the semantics of an insn containing
3918334Speter   stack-like regs are not the same as for an insn with normal regs: for
4018334Speter   instance, it is not safe to delete an insn that appears to be a no-op
4118334Speter   move.  In general, no insn containing hard regs should be changed
4218334Speter   after this pass is done.
4318334Speter
4418334Speter   * The form of the output:
4518334Speter
4618334Speter   After this pass, hard register numbers represent the distance from
4718334Speter   the current top of stack to the desired register.  A reference to
4818334Speter   FIRST_STACK_REG references the top of stack, FIRST_STACK_REG + 1,
4918334Speter   represents the register just below that, and so forth.  Also, REG_DEAD
5018334Speter   notes indicate whether or not a stack register should be popped.
5118334Speter
5218334Speter   A "swap" insn looks like a parallel of two patterns, where each
5318334Speter   pattern is a SET: one sets A to B, the other B to A.
5418334Speter
5518334Speter   A "push" or "load" insn is a SET whose SET_DEST is FIRST_STACK_REG
5618334Speter   and whose SET_DEST is REG or MEM.  Any other SET_DEST, such as PLUS,
5718334Speter   will replace the existing stack top, not push a new value.
5818334Speter
5918334Speter   A store insn is a SET whose SET_DEST is FIRST_STACK_REG, and whose
6018334Speter   SET_SRC is REG or MEM.
6118334Speter
6218334Speter   The case where the SET_SRC and SET_DEST are both FIRST_STACK_REG
6318334Speter   appears ambiguous.  As a special case, the presence of a REG_DEAD note
6418334Speter   for FIRST_STACK_REG differentiates between a load insn and a pop.
6518334Speter
6618334Speter   If a REG_DEAD is present, the insn represents a "pop" that discards
6718334Speter   the top of the register stack.  If there is no REG_DEAD note, then the
6818334Speter   insn represents a "dup" or a push of the current top of stack onto the
6918334Speter   stack.
7018334Speter
7118334Speter   * Methodology:
7218334Speter
7318334Speter   Existing REG_DEAD and REG_UNUSED notes for stack registers are
7418334Speter   deleted and recreated from scratch.  REG_DEAD is never created for a
7518334Speter   SET_DEST, only REG_UNUSED.
7618334Speter
7718334Speter   * asm_operands:
7818334Speter
7918334Speter   There are several rules on the usage of stack-like regs in
8018334Speter   asm_operands insns.  These rules apply only to the operands that are
8118334Speter   stack-like regs:
8218334Speter
8318334Speter   1. Given a set of input regs that die in an asm_operands, it is
8418334Speter      necessary to know which are implicitly popped by the asm, and
8518334Speter      which must be explicitly popped by gcc.
8618334Speter
8718334Speter	An input reg that is implicitly popped by the asm must be
8818334Speter	explicitly clobbered, unless it is constrained to match an
8918334Speter	output operand.
9018334Speter
9118334Speter   2. For any input reg that is implicitly popped by an asm, it is
9218334Speter      necessary to know how to adjust the stack to compensate for the pop.
9318334Speter      If any non-popped input is closer to the top of the reg-stack than
9418334Speter      the implicitly popped reg, it would not be possible to know what the
9518334Speter      stack looked like - it's not clear how the rest of the stack "slides
9618334Speter      up".
9718334Speter
9818334Speter	All implicitly popped input regs must be closer to the top of
9918334Speter	the reg-stack than any input that is not implicitly popped.
10018334Speter
10118334Speter   3. It is possible that if an input dies in an insn, reload might
10218334Speter      use the input reg for an output reload.  Consider this example:
10318334Speter
10418334Speter		asm ("foo" : "=t" (a) : "f" (b));
10518334Speter
10618334Speter      This asm says that input B is not popped by the asm, and that
10718334Speter      the asm pushes a result onto the reg-stack, ie, the stack is one
10818334Speter      deeper after the asm than it was before.  But, it is possible that
10918334Speter      reload will think that it can use the same reg for both the input and
11018334Speter      the output, if input B dies in this insn.
11118334Speter
11218334Speter	If any input operand uses the "f" constraint, all output reg
11318334Speter	constraints must use the "&" earlyclobber.
11418334Speter
11518334Speter      The asm above would be written as
11618334Speter
11718334Speter		asm ("foo" : "=&t" (a) : "f" (b));
11818334Speter
11918334Speter   4. Some operands need to be in particular places on the stack.  All
12018334Speter      output operands fall in this category - there is no other way to
12118334Speter      know which regs the outputs appear in unless the user indicates
12218334Speter      this in the constraints.
12318334Speter
12418334Speter	Output operands must specifically indicate which reg an output
12518334Speter	appears in after an asm.  "=f" is not allowed: the operand
12618334Speter	constraints must select a class with a single reg.
12718334Speter
12818334Speter   5. Output operands may not be "inserted" between existing stack regs.
12918334Speter      Since no 387 opcode uses a read/write operand, all output operands
13018334Speter      are dead before the asm_operands, and are pushed by the asm_operands.
13118334Speter      It makes no sense to push anywhere but the top of the reg-stack.
13218334Speter
13318334Speter	Output operands must start at the top of the reg-stack: output
13418334Speter	operands may not "skip" a reg.
13518334Speter
13618334Speter   6. Some asm statements may need extra stack space for internal
13718334Speter      calculations.  This can be guaranteed by clobbering stack registers
13818334Speter      unrelated to the inputs and outputs.
13918334Speter
14018334Speter   Here are a couple of reasonable asms to want to write.  This asm
14118334Speter   takes one input, which is internally popped, and produces two outputs.
14218334Speter
14318334Speter	asm ("fsincos" : "=t" (cos), "=u" (sin) : "0" (inp));
14418334Speter
14518334Speter   This asm takes two inputs, which are popped by the fyl2xp1 opcode,
14618334Speter   and replaces them with one output.  The user must code the "st(1)"
14718334Speter   clobber for reg-stack.c to know that fyl2xp1 pops both inputs.
14818334Speter
14918334Speter	asm ("fyl2xp1" : "=t" (result) : "0" (x), "u" (y) : "st(1)");
15018334Speter
15118334Speter   */
15218334Speter
15318334Speter#include "config.h"
15450397Sobrien#include "system.h"
15518334Speter#include "tree.h"
15618334Speter#include "rtl.h"
15718334Speter#include "insn-config.h"
15818334Speter#include "regs.h"
15918334Speter#include "hard-reg-set.h"
16018334Speter#include "flags.h"
16150397Sobrien#include "insn-flags.h"
16252284Sobrien#include "recog.h"
16350397Sobrien#include "toplev.h"
16452284Sobrien#include "varray.h"
16518334Speter
16618334Speter#ifdef STACK_REGS
16718334Speter
16818334Speter#define REG_STACK_SIZE (LAST_STACK_REG - FIRST_STACK_REG + 1)
16918334Speter
17018334Speter/* This is the basic stack record.  TOP is an index into REG[] such
17118334Speter   that REG[TOP] is the top of stack.  If TOP is -1 the stack is empty.
17218334Speter
17318334Speter   If TOP is -2, REG[] is not yet initialized.  Stack initialization
17418334Speter   consists of placing each live reg in array `reg' and setting `top'
17518334Speter   appropriately.
17618334Speter
17718334Speter   REG_SET indicates which registers are live.  */
17818334Speter
17918334Spetertypedef struct stack_def
18018334Speter{
18118334Speter  int top;			/* index to top stack element */
18218334Speter  HARD_REG_SET reg_set;		/* set of live registers */
18318334Speter  char reg[REG_STACK_SIZE];	/* register - stack mapping */
18418334Speter} *stack;
18518334Speter
18618334Speter/* highest instruction uid */
18718334Speterstatic int max_uid = 0;
18818334Speter
18918334Speter/* Number of basic blocks in the current function.  */
19018334Speterstatic int blocks;
19118334Speter
19218334Speter/* Element N is first insn in basic block N.
19318334Speter   This info lasts until we finish compiling the function.  */
19418334Speterstatic rtx *block_begin;
19518334Speter
19618334Speter/* Element N is last insn in basic block N.
19718334Speter   This info lasts until we finish compiling the function.  */
19818334Speterstatic rtx *block_end;
19918334Speter
20018334Speter/* Element N is nonzero if control can drop into basic block N */
20118334Speterstatic char *block_drops_in;
20218334Speter
20318334Speter/* Element N says all about the stack at entry block N */
20418334Speterstatic stack block_stack_in;
20518334Speter
20618334Speter/* Element N says all about the stack life at the end of block N */
20718334Speterstatic HARD_REG_SET *block_out_reg_set;
20818334Speter
20918334Speter/* This is where the BLOCK_NUM values are really stored.  This is set
21018334Speter   up by find_blocks and used there and in life_analysis.  It can be used
21118334Speter   later, but only to look up an insn that is the head or tail of some
21218334Speter   block.  life_analysis and the stack register conversion process can
21350397Sobrien   add insns within a block.  */
21418334Speterstatic int *block_number;
21518334Speter
21652284Sobrien/* We use this array to cache info about insns, because otherwise we
21752284Sobrien   spend too much time in stack_regs_mentioned_p.
21852284Sobrien
21952284Sobrien   Indexed by insn UIDs.  A value of zero is uninitialized, one indicates
22052284Sobrien   the insn uses stack registers, two indicates the insn does not use
22152284Sobrien   stack registers.  */
22252284Sobrienstatic varray_type stack_regs_mentioned_data;
22352284Sobrien
22418334Speter/* This is the register file for all register after conversion */
22518334Speterstatic rtx
22618334Speter  FP_mode_reg[LAST_STACK_REG+1-FIRST_STACK_REG][(int) MAX_MACHINE_MODE];
22718334Speter
22818334Speter#define FP_MODE_REG(regno,mode)	\
22918334Speter  (FP_mode_reg[(regno)-FIRST_STACK_REG][(int)(mode)])
23018334Speter
23118334Speter/* Get the basic block number of an insn.  See note at block_number
23250397Sobrien   definition are validity of this information.  */
23318334Speter
23452284Sobrienstatic int BLOCK_NUM PROTO((rtx));
23518334Speter
23652284Sobrien#ifdef __GNUC__
23752284Sobrien__inline__
23852284Sobrien#endif
23952284Sobrienstatic int
24052284SobrienBLOCK_NUM(insn)
24152284Sobrien     rtx insn;
24252284Sobrien{
24352284Sobrien  int tmp = INSN_UID (insn);
24452284Sobrien  if (tmp > max_uid)
24552284Sobrien    abort ();
24652284Sobrien  tmp = block_number[tmp];
24752284Sobrien  if (tmp < 0)
24852284Sobrien    abort ();
24952284Sobrien  return tmp;
25052284Sobrien}
25152284Sobrien
25218334Speterextern rtx forced_labels;
25318334Speter
25418334Speter/* Forward declarations */
25518334Speter
25650397Sobrienstatic void mark_regs_pat		PROTO((rtx, HARD_REG_SET *));
25750397Sobrienstatic void straighten_stack		PROTO((rtx, stack));
25850397Sobrienstatic void pop_stack			PROTO((stack, int));
25950397Sobrienstatic void record_label_references	PROTO((rtx, rtx));
26050397Sobrienstatic rtx *get_true_reg		PROTO((rtx *));
26150397Sobrien
26252284Sobrienstatic void record_asm_reg_life		PROTO((rtx, stack));
26350397Sobrienstatic void record_reg_life_pat		PROTO((rtx, HARD_REG_SET *,
26450397Sobrien					       HARD_REG_SET *, int));
26552284Sobrienstatic int get_asm_operand_n_inputs	PROTO((rtx));
26650397Sobrienstatic void record_reg_life		PROTO((rtx, int, stack));
26750397Sobrienstatic void find_blocks			PROTO((rtx));
26850397Sobrienstatic rtx stack_result			PROTO((tree));
26950397Sobrienstatic void stack_reg_life_analysis	PROTO((rtx, HARD_REG_SET *));
27050397Sobrienstatic void replace_reg			PROTO((rtx *, int));
27150397Sobrienstatic void remove_regno_note		PROTO((rtx, enum reg_note, int));
27250397Sobrienstatic int get_hard_regnum		PROTO((stack, rtx));
27350397Sobrienstatic void delete_insn_for_stacker	PROTO((rtx));
27450397Sobrienstatic rtx emit_pop_insn		PROTO((rtx, stack, rtx, rtx (*) ()));
27550397Sobrienstatic void emit_swap_insn		PROTO((rtx, stack, rtx));
27650397Sobrienstatic void move_for_stack_reg		PROTO((rtx, stack, rtx));
27750397Sobrienstatic void swap_rtx_condition		PROTO((rtx));
27850397Sobrienstatic void compare_for_stack_reg	PROTO((rtx, stack, rtx));
27950397Sobrienstatic void subst_stack_regs_pat	PROTO((rtx, stack, rtx));
28052284Sobrienstatic void subst_asm_stack_regs	PROTO((rtx, stack));
28150397Sobrienstatic void subst_stack_regs		PROTO((rtx, stack));
28250397Sobrienstatic void change_stack		PROTO((rtx, stack, stack, rtx (*) ()));
28350397Sobrien
28450397Sobrienstatic void goto_block_pat		PROTO((rtx, stack, rtx));
28550397Sobrienstatic void convert_regs		PROTO((void));
28650397Sobrienstatic void print_blocks		PROTO((FILE *, rtx, rtx));
28750397Sobrienstatic void dump_stack_info		PROTO((FILE *));
28852284Sobrienstatic int check_stack_regs_mentioned	PROTO((rtx insn));
28918334Speter
29052284Sobrien/* Initialize stack_regs_mentioned_data for INSN (growing the virtual array
29152284Sobrien   if needed.  Return nonzero if INSN mentions stacked registers.  */
29252284Sobrien
29352284Sobrienstatic int
29452284Sobriencheck_stack_regs_mentioned (insn)
29552284Sobrien     rtx insn;
29652284Sobrien{
29752284Sobrien  unsigned int uid = INSN_UID (insn);
29852284Sobrien  if (uid >= VARRAY_SIZE (stack_regs_mentioned_data))
29952284Sobrien    /* Allocate some extra size to avoid too many reallocs, but
30052284Sobrien       do not grow exponentially.  */
30152284Sobrien    VARRAY_GROW (stack_regs_mentioned_data, uid + uid / 20);
30252284Sobrien  if (stack_regs_mentioned_p (PATTERN (insn)))
30352284Sobrien    {
30452284Sobrien      VARRAY_CHAR (stack_regs_mentioned_data, uid) = 1;
30552284Sobrien      return 1;
30652284Sobrien    }
30752284Sobrien  else
30852284Sobrien    VARRAY_CHAR (stack_regs_mentioned_data, uid) = 2;
30952284Sobrien  return 0;
31052284Sobrien}
31152284Sobrien
31252284Sobrien/* Return nonzero if INSN mentions stacked registers, else return
31352284Sobrien   zero.  */
31452284Sobrien
31552284Sobrienint
31652284Sobrienstack_regs_mentioned (insn)
31752284Sobrien     rtx insn;
31852284Sobrien{
31952284Sobrien  unsigned int uid;
32052284Sobrien  if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
32152284Sobrien    return 0;
32252284Sobrien  uid = INSN_UID (insn);
32352284Sobrien  if (uid >= VARRAY_SIZE (stack_regs_mentioned_data)
32452284Sobrien      || ! VARRAY_CHAR (stack_regs_mentioned_data, uid))
32552284Sobrien    return (check_stack_regs_mentioned (insn));
32652284Sobrien  return VARRAY_CHAR (stack_regs_mentioned_data, uid) == 1;
32752284Sobrien}
32852284Sobrien
32952284Sobrien
33018334Speter/* Mark all registers needed for this pattern.  */
33118334Speter
33218334Speterstatic void
33318334Spetermark_regs_pat (pat, set)
33418334Speter     rtx pat;
33518334Speter     HARD_REG_SET *set;
33618334Speter{
33718334Speter  enum machine_mode mode;
33818334Speter  register int regno;
33918334Speter  register int count;
34018334Speter
34118334Speter  if (GET_CODE (pat) == SUBREG)
34218334Speter   {
34318334Speter     mode = GET_MODE (pat);
34418334Speter     regno = SUBREG_WORD (pat);
34518334Speter     regno += REGNO (SUBREG_REG (pat));
34618334Speter   }
34718334Speter  else
34818334Speter     regno = REGNO (pat), mode = GET_MODE (pat);
34918334Speter
35018334Speter  for (count = HARD_REGNO_NREGS (regno, mode);
35118334Speter       count; count--, regno++)
35218334Speter     SET_HARD_REG_BIT (*set, regno);
35318334Speter}
35418334Speter
35518334Speter/* Reorganise the stack into ascending numbers,
35618334Speter   after this insn.  */
35718334Speter
35818334Speterstatic void
35918334Speterstraighten_stack (insn, regstack)
36018334Speter     rtx insn;
36118334Speter     stack regstack;
36218334Speter{
36318334Speter  struct stack_def temp_stack;
36418334Speter  int top;
36518334Speter
36650397Sobrien  /* If there is only a single register on the stack, then the stack is
36750397Sobrien     already in increasing order and no reorganization is needed.
36850397Sobrien
36950397Sobrien     Similarly if the stack is empty.  */
37050397Sobrien  if (regstack->top <= 0)
37150397Sobrien    return;
37250397Sobrien
37318334Speter  temp_stack.reg_set = regstack->reg_set;
37418334Speter
37518334Speter  for (top = temp_stack.top = regstack->top; top >= 0; top--)
37618334Speter     temp_stack.reg[top] = FIRST_STACK_REG + temp_stack.top - top;
37718334Speter
37818334Speter  change_stack (insn, regstack, &temp_stack, emit_insn_after);
37918334Speter}
38050397Sobrien
38150397Sobrien/* Pop a register from the stack */
38250397Sobrien
38350397Sobrienstatic void
38450397Sobrienpop_stack (regstack, regno)
38550397Sobrien     stack regstack;
38650397Sobrien     int   regno;
38750397Sobrien{
38850397Sobrien  int top = regstack->top;
38950397Sobrien
39050397Sobrien  CLEAR_HARD_REG_BIT (regstack->reg_set, regno);
39150397Sobrien  regstack->top--;
39250397Sobrien  /* If regno was not at the top of stack then adjust stack */
39350397Sobrien  if (regstack->reg [top] != regno)
39450397Sobrien    {
39550397Sobrien      int i;
39650397Sobrien      for (i = regstack->top; i >= 0; i--)
39750397Sobrien	if (regstack->reg [i] == regno)
39850397Sobrien	  {
39950397Sobrien	    int j;
40050397Sobrien	    for (j = i; j < top; j++)
40150397Sobrien	      regstack->reg [j] = regstack->reg [j + 1];
40250397Sobrien	    break;
40350397Sobrien	  }
40450397Sobrien    }
40550397Sobrien}
40618334Speter
40718334Speter/* Return non-zero if any stack register is mentioned somewhere within PAT.  */
40818334Speter
40918334Speterint
41018334Speterstack_regs_mentioned_p (pat)
41118334Speter     rtx pat;
41218334Speter{
41318334Speter  register char *fmt;
41418334Speter  register int i;
41518334Speter
41618334Speter  if (STACK_REG_P (pat))
41718334Speter    return 1;
41818334Speter
41918334Speter  fmt = GET_RTX_FORMAT (GET_CODE (pat));
42018334Speter  for (i = GET_RTX_LENGTH (GET_CODE (pat)) - 1; i >= 0; i--)
42118334Speter    {
42218334Speter      if (fmt[i] == 'E')
42318334Speter	{
42418334Speter	  register int j;
42518334Speter
42618334Speter	  for (j = XVECLEN (pat, i) - 1; j >= 0; j--)
42718334Speter	    if (stack_regs_mentioned_p (XVECEXP (pat, i, j)))
42818334Speter	      return 1;
42918334Speter	}
43018334Speter      else if (fmt[i] == 'e' && stack_regs_mentioned_p (XEXP (pat, i)))
43118334Speter	return 1;
43218334Speter    }
43318334Speter
43418334Speter  return 0;
43518334Speter}
43618334Speter
43718334Speter/* Convert register usage from "flat" register file usage to a "stack
43818334Speter   register file.  FIRST is the first insn in the function, FILE is the
43918334Speter   dump file, if used.
44018334Speter
44118334Speter   First compute the beginning and end of each basic block.  Do a
44218334Speter   register life analysis on the stack registers, recording the result
44318334Speter   for the head and tail of each basic block.  The convert each insn one
44418334Speter   by one.  Run a last jump_optimize() pass, if optimizing, to eliminate
44518334Speter   any cross-jumping created when the converter inserts pop insns.*/
44618334Speter
44718334Spetervoid
44818334Speterreg_to_stack (first, file)
44918334Speter     rtx first;
45018334Speter     FILE *file;
45118334Speter{
45218334Speter  register rtx insn;
45318334Speter  register int i;
45418334Speter  int stack_reg_seen = 0;
45518334Speter  enum machine_mode mode;
45618334Speter  HARD_REG_SET stackentry;
45718334Speter
45852284Sobrien  max_uid = get_max_uid ();
45952284Sobrien  VARRAY_CHAR_INIT (stack_regs_mentioned_data, max_uid + 1,
46052284Sobrien		    "stack_regs_mentioned cache");
46152284Sobrien
46218334Speter  CLEAR_HARD_REG_SET (stackentry);
46318334Speter
46418334Speter   {
46550397Sobrien     static int initialised;
46618334Speter     if (!initialised)
46718334Speter      {
46818334Speter#if 0
46918334Speter	initialised = 1;	/* This array can not have been previously
47018334Speter				   initialised, because the rtx's are
47118334Speter				   thrown away between compilations of
47218334Speter				   functions.  */
47318334Speter#endif
47418334Speter        for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
47518334Speter         {
47618334Speter           for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode;
47718334Speter               mode = GET_MODE_WIDER_MODE (mode))
47850397Sobrien              FP_MODE_REG (i, mode) = gen_rtx_REG (mode, i);
47918334Speter           for (mode = GET_CLASS_NARROWEST_MODE (MODE_COMPLEX_FLOAT); mode != VOIDmode;
48018334Speter               mode = GET_MODE_WIDER_MODE (mode))
48150397Sobrien              FP_MODE_REG (i, mode) = gen_rtx_REG (mode, i);
48218334Speter         }
48318334Speter      }
48418334Speter   }
48518334Speter
48618334Speter  /* Count the basic blocks.  Also find maximum insn uid.  */
48718334Speter  {
48818334Speter    register RTX_CODE prev_code = BARRIER;
48918334Speter    register RTX_CODE code;
49050397Sobrien    register int before_function_beg = 1;
49118334Speter
49218334Speter    max_uid = 0;
49318334Speter    blocks = 0;
49418334Speter    for (insn = first; insn; insn = NEXT_INSN (insn))
49518334Speter      {
49618334Speter	/* Note that this loop must select the same block boundaries
49718334Speter	   as code in find_blocks.  Also note that this code is not the
49818334Speter	   same as that used in flow.c.  */
49918334Speter
50018334Speter	if (INSN_UID (insn) > max_uid)
50118334Speter	  max_uid = INSN_UID (insn);
50218334Speter
50318334Speter	code = GET_CODE (insn);
50418334Speter
50518334Speter	if (code == CODE_LABEL
50618334Speter	    || (prev_code != INSN
50718334Speter		&& prev_code != CALL_INSN
50818334Speter		&& prev_code != CODE_LABEL
50918334Speter		&& GET_RTX_CLASS (code) == 'i'))
51018334Speter	  blocks++;
51118334Speter
51218334Speter	if (code == NOTE && NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG)
51318334Speter	   before_function_beg = 0;
51418334Speter
51518334Speter	/* Remember whether or not this insn mentions an FP regs.
51650397Sobrien	   Check JUMP_INSNs too, in case someone creates a funny PARALLEL.  */
51718334Speter
51818334Speter	if (GET_RTX_CLASS (code) == 'i'
51918334Speter	    && stack_regs_mentioned_p (PATTERN (insn)))
52018334Speter	  {
52118334Speter	    stack_reg_seen = 1;
52252284Sobrien	    VARRAY_CHAR (stack_regs_mentioned_data, INSN_UID (insn)) = 1;
52318334Speter
52418334Speter	    /* Note any register passing parameters.  */
52518334Speter
52618334Speter	    if (before_function_beg && code == INSN
52718334Speter	        && GET_CODE (PATTERN (insn)) == USE)
52850397Sobrien              record_reg_life_pat (PATTERN (insn), (HARD_REG_SET *) 0,
52918334Speter				   &stackentry, 1);
53018334Speter	  }
53118334Speter	else
53252284Sobrien	  VARRAY_CHAR (stack_regs_mentioned_data, INSN_UID (insn)) = 2;
53318334Speter
53418334Speter	if (code == CODE_LABEL)
53518334Speter	  LABEL_REFS (insn) = insn; /* delete old chain */
53618334Speter
53718334Speter	if (code != NOTE)
53818334Speter	  prev_code = code;
53918334Speter      }
54018334Speter  }
54118334Speter
54218334Speter  /* If no stack register reference exists in this insn, there isn't
54318334Speter     anything to convert.  */
54418334Speter
54518334Speter  if (! stack_reg_seen)
54652284Sobrien    {
54752284Sobrien      VARRAY_FREE (stack_regs_mentioned_data);
54852284Sobrien      return;
54952284Sobrien    }
55018334Speter
55150397Sobrien  /* If there are stack registers, there must be at least one block.  */
55218334Speter
55318334Speter  if (! blocks)
55418334Speter    abort ();
55518334Speter
55618334Speter  /* Allocate some tables that last till end of compiling this function
55750397Sobrien     and some needed only in find_blocks and life_analysis.  */
55818334Speter
55918334Speter  block_begin = (rtx *) alloca (blocks * sizeof (rtx));
56018334Speter  block_end = (rtx *) alloca (blocks * sizeof (rtx));
56118334Speter  block_drops_in = (char *) alloca (blocks);
56218334Speter
56318334Speter  block_stack_in = (stack) alloca (blocks * sizeof (struct stack_def));
56418334Speter  block_out_reg_set = (HARD_REG_SET *) alloca (blocks * sizeof (HARD_REG_SET));
56518334Speter  bzero ((char *) block_stack_in, blocks * sizeof (struct stack_def));
56618334Speter  bzero ((char *) block_out_reg_set, blocks * sizeof (HARD_REG_SET));
56718334Speter
56818334Speter  block_number = (int *) alloca ((max_uid + 1) * sizeof (int));
56952284Sobrien  memset (block_number, -1, (max_uid + 1) * sizeof (int));
57018334Speter
57118334Speter  find_blocks (first);
57218334Speter  stack_reg_life_analysis (first, &stackentry);
57318334Speter
57418334Speter  /* Dump the life analysis debug information before jump
57518334Speter     optimization, as that will destroy the LABEL_REFS we keep the
57650397Sobrien     information in.  */
57718334Speter
57818334Speter  if (file)
57918334Speter    dump_stack_info (file);
58018334Speter
58118334Speter  convert_regs ();
58218334Speter
58318334Speter  if (optimize)
58418334Speter    jump_optimize (first, 2, 0, 0);
58552284Sobrien
58652284Sobrien  VARRAY_FREE (stack_regs_mentioned_data);
58718334Speter}
58818334Speter
58918334Speter/* Check PAT, which is in INSN, for LABEL_REFs.  Add INSN to the
59018334Speter   label's chain of references, and note which insn contains each
59150397Sobrien   reference.  */
59218334Speter
59318334Speterstatic void
59418334Speterrecord_label_references (insn, pat)
59518334Speter     rtx insn, pat;
59618334Speter{
59718334Speter  register enum rtx_code code = GET_CODE (pat);
59818334Speter  register int i;
59918334Speter  register char *fmt;
60018334Speter
60118334Speter  if (code == LABEL_REF)
60218334Speter    {
60318334Speter      register rtx label = XEXP (pat, 0);
60418334Speter      register rtx ref;
60518334Speter
60618334Speter      if (GET_CODE (label) != CODE_LABEL)
60718334Speter	abort ();
60818334Speter
60950397Sobrien      /* If this is an undefined label, LABEL_REFS (label) contains
61050397Sobrien         garbage.  */
61150397Sobrien      if (INSN_UID (label) == 0)
61250397Sobrien	return;
61318334Speter
61450397Sobrien      /* Don't make a duplicate in the code_label's chain.  */
61550397Sobrien
61618334Speter      for (ref = LABEL_REFS (label);
61718334Speter	   ref && ref != label;
61818334Speter	   ref = LABEL_NEXTREF (ref))
61918334Speter	if (CONTAINING_INSN (ref) == insn)
62018334Speter	  return;
62118334Speter
62218334Speter      CONTAINING_INSN (pat) = insn;
62318334Speter      LABEL_NEXTREF (pat) = LABEL_REFS (label);
62418334Speter      LABEL_REFS (label) = pat;
62518334Speter
62618334Speter      return;
62718334Speter    }
62818334Speter
62918334Speter  fmt = GET_RTX_FORMAT (code);
63018334Speter  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
63118334Speter    {
63218334Speter      if (fmt[i] == 'e')
63318334Speter	record_label_references (insn, XEXP (pat, i));
63418334Speter      if (fmt[i] == 'E')
63518334Speter	{
63618334Speter	  register int j;
63718334Speter	  for (j = 0; j < XVECLEN (pat, i); j++)
63818334Speter	    record_label_references (insn, XVECEXP (pat, i, j));
63918334Speter	}
64018334Speter    }
64118334Speter}
64218334Speter
64318334Speter/* Return a pointer to the REG expression within PAT.  If PAT is not a
64418334Speter   REG, possible enclosed by a conversion rtx, return the inner part of
64550397Sobrien   PAT that stopped the search.  */
64618334Speter
64718334Speterstatic rtx *
64818334Speterget_true_reg (pat)
64918334Speter     rtx *pat;
65018334Speter{
65118334Speter  for (;;)
65218334Speter     switch (GET_CODE (*pat))
65318334Speter      {
65418334Speter	case SUBREG:
65518334Speter		/* eliminate FP subregister accesses in favour of the
65650397Sobrien		   actual FP register in use.  */
65718334Speter	 {
65818334Speter	   rtx subreg;
65918334Speter	   if (FP_REG_P (subreg = SUBREG_REG (*pat)))
66018334Speter	    {
66118334Speter	      *pat = FP_MODE_REG (REGNO (subreg) + SUBREG_WORD (*pat),
66218334Speter				  GET_MODE (subreg));
66318334Speter	default:
66418334Speter	      return pat;
66518334Speter	    }
66618334Speter	 }
66718334Speter	case FLOAT:
66818334Speter	case FIX:
66918334Speter	case FLOAT_EXTEND:
67018334Speter	   pat = & XEXP (*pat, 0);
67118334Speter      }
67218334Speter}
67318334Speter
67418334Speter/* Record the life info of each stack reg in INSN, updating REGSTACK.
67552284Sobrien   N_INPUTS is the number of inputs; N_OUTPUTS the outputs.
67618334Speter   OPERANDS is an array of all operands for the insn, and is assumed to
67718334Speter   contain all output operands, then all inputs operands.
67818334Speter
67918334Speter   There are many rules that an asm statement for stack-like regs must
68018334Speter   follow.  Those rules are explained at the top of this file: the rule
68150397Sobrien   numbers below refer to that explanation.  */
68218334Speter
68318334Speterstatic void
68452284Sobrienrecord_asm_reg_life (insn, regstack)
68518334Speter     rtx insn;
68618334Speter     stack regstack;
68718334Speter{
68818334Speter  int i;
68918334Speter  int n_clobbers;
69018334Speter  int malformed_asm = 0;
69118334Speter  rtx body = PATTERN (insn);
69218334Speter
69318334Speter  int reg_used_as_output[FIRST_PSEUDO_REGISTER];
69418334Speter  int implicitly_dies[FIRST_PSEUDO_REGISTER];
69552284Sobrien  int alt;
69618334Speter
69718334Speter  rtx *clobber_reg;
69852284Sobrien  int n_inputs, n_outputs;
69918334Speter
70018334Speter  /* Find out what the constraints require.  If no constraint
70118334Speter     alternative matches, this asm is malformed.  */
70252284Sobrien  extract_insn (insn);
70352284Sobrien  constrain_operands (1);
70452284Sobrien  alt = which_alternative;
70518334Speter
70652284Sobrien  preprocess_constraints ();
70752284Sobrien
70852284Sobrien  n_inputs = get_asm_operand_n_inputs (body);
70952284Sobrien  n_outputs = recog_n_operands - n_inputs;
71052284Sobrien
71152284Sobrien  if (alt < 0)
71252284Sobrien    {
71352284Sobrien      malformed_asm = 1;
71452284Sobrien      /* Avoid further trouble with this insn.  */
71552284Sobrien      PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
71652284Sobrien      VARRAY_CHAR (stack_regs_mentioned_data, INSN_UID (insn)) = 2;
71752284Sobrien      return;
71852284Sobrien    }
71952284Sobrien
72050397Sobrien  /* Strip SUBREGs here to make the following code simpler.  */
72152284Sobrien  for (i = 0; i < recog_n_operands; i++)
72252284Sobrien    if (GET_CODE (recog_operand[i]) == SUBREG
72352284Sobrien	&& GET_CODE (SUBREG_REG (recog_operand[i])) == REG)
72452284Sobrien      recog_operand[i] = SUBREG_REG (recog_operand[i]);
72518334Speter
72618334Speter  /* Set up CLOBBER_REG.  */
72718334Speter
72818334Speter  n_clobbers = 0;
72918334Speter
73018334Speter  if (GET_CODE (body) == PARALLEL)
73118334Speter    {
73252284Sobrien      clobber_reg = (rtx *) alloca (XVECLEN (body, 0) * sizeof (rtx));
73318334Speter
73418334Speter      for (i = 0; i < XVECLEN (body, 0); i++)
73518334Speter	if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER)
73618334Speter	  {
73718334Speter	    rtx clobber = XVECEXP (body, 0, i);
73818334Speter	    rtx reg = XEXP (clobber, 0);
73918334Speter
74018334Speter	    if (GET_CODE (reg) == SUBREG && GET_CODE (SUBREG_REG (reg)) == REG)
74118334Speter	      reg = SUBREG_REG (reg);
74218334Speter
74318334Speter	    if (STACK_REG_P (reg))
74418334Speter	      {
74518334Speter		clobber_reg[n_clobbers] = reg;
74618334Speter		n_clobbers++;
74718334Speter	      }
74818334Speter	  }
74918334Speter    }
75018334Speter
75118334Speter  /* Enforce rule #4: Output operands must specifically indicate which
75218334Speter     reg an output appears in after an asm.  "=f" is not allowed: the
75318334Speter     operand constraints must select a class with a single reg.
75418334Speter
75518334Speter     Also enforce rule #5: Output operands must start at the top of
75650397Sobrien     the reg-stack: output operands may not "skip" a reg.  */
75718334Speter
75818334Speter  bzero ((char *) reg_used_as_output, sizeof (reg_used_as_output));
75918334Speter  for (i = 0; i < n_outputs; i++)
76052284Sobrien    if (STACK_REG_P (recog_operand[i]))
76150397Sobrien      {
76252284Sobrien	if (reg_class_size[(int) recog_op_alt[i][alt].class] != 1)
76350397Sobrien	  {
76450397Sobrien	    error_for_asm (insn, "Output constraint %d must specify a single register", i);
76550397Sobrien	    malformed_asm = 1;
76650397Sobrien	  }
76750397Sobrien        else
76852284Sobrien	  reg_used_as_output[REGNO (recog_operand[i])] = 1;
76950397Sobrien      }
77018334Speter
77118334Speter
77218334Speter  /* Search for first non-popped reg.  */
77318334Speter  for (i = FIRST_STACK_REG; i < LAST_STACK_REG + 1; i++)
77418334Speter    if (! reg_used_as_output[i])
77518334Speter      break;
77618334Speter
77718334Speter  /* If there are any other popped regs, that's an error.  */
77818334Speter  for (; i < LAST_STACK_REG + 1; i++)
77918334Speter    if (reg_used_as_output[i])
78018334Speter      break;
78118334Speter
78218334Speter  if (i != LAST_STACK_REG + 1)
78318334Speter    {
78418334Speter      error_for_asm (insn, "Output regs must be grouped at top of stack");
78518334Speter      malformed_asm = 1;
78618334Speter    }
78718334Speter
78818334Speter  /* Enforce rule #2: All implicitly popped input regs must be closer
78918334Speter     to the top of the reg-stack than any input that is not implicitly
79050397Sobrien     popped.  */
79118334Speter
79218334Speter  bzero ((char *) implicitly_dies, sizeof (implicitly_dies));
79352284Sobrien  for (i = n_outputs; i < n_outputs + n_inputs; i++)
79452284Sobrien    if (STACK_REG_P (recog_operand[i]))
79518334Speter      {
79618334Speter	/* An input reg is implicitly popped if it is tied to an
79750397Sobrien	   output, or if there is a CLOBBER for it.  */
79818334Speter	int j;
79918334Speter
80018334Speter	for (j = 0; j < n_clobbers; j++)
80152284Sobrien	  if (operands_match_p (clobber_reg[j], recog_operand[i]))
80218334Speter	    break;
80318334Speter
80452284Sobrien	if (j < n_clobbers || recog_op_alt[i][alt].matches >= 0)
80552284Sobrien	  implicitly_dies[REGNO (recog_operand[i])] = 1;
80618334Speter      }
80718334Speter
80818334Speter  /* Search for first non-popped reg.  */
80918334Speter  for (i = FIRST_STACK_REG; i < LAST_STACK_REG + 1; i++)
81018334Speter    if (! implicitly_dies[i])
81118334Speter      break;
81218334Speter
81318334Speter  /* If there are any other popped regs, that's an error.  */
81418334Speter  for (; i < LAST_STACK_REG + 1; i++)
81518334Speter    if (implicitly_dies[i])
81618334Speter      break;
81718334Speter
81818334Speter  if (i != LAST_STACK_REG + 1)
81918334Speter    {
82018334Speter      error_for_asm (insn,
82118334Speter		     "Implicitly popped regs must be grouped at top of stack");
82218334Speter      malformed_asm = 1;
82318334Speter    }
82418334Speter
82518334Speter  /* Enfore rule #3: If any input operand uses the "f" constraint, all
82618334Speter     output constraints must use the "&" earlyclobber.
82718334Speter
82818334Speter     ???  Detect this more deterministically by having constraint_asm_operands
82950397Sobrien     record any earlyclobber.  */
83018334Speter
83152284Sobrien  for (i = n_outputs; i < n_outputs + n_inputs; i++)
83252284Sobrien    if (recog_op_alt[i][alt].matches == -1)
83318334Speter      {
83418334Speter	int j;
83518334Speter
83618334Speter	for (j = 0; j < n_outputs; j++)
83752284Sobrien	  if (operands_match_p (recog_operand[j], recog_operand[i]))
83818334Speter	    {
83918334Speter	      error_for_asm (insn,
84018334Speter			     "Output operand %d must use `&' constraint", j);
84118334Speter	      malformed_asm = 1;
84218334Speter	    }
84318334Speter      }
84418334Speter
84518334Speter  if (malformed_asm)
84618334Speter    {
84718334Speter      /* Avoid further trouble with this insn.  */
84850397Sobrien      PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
84952284Sobrien      VARRAY_CHAR (stack_regs_mentioned_data, INSN_UID (insn)) = 2;
85018334Speter      return;
85118334Speter    }
85218334Speter
85318334Speter  /* Process all outputs */
85418334Speter  for (i = 0; i < n_outputs; i++)
85518334Speter    {
85652284Sobrien      rtx op = recog_operand[i];
85718334Speter
85818334Speter      if (! STACK_REG_P (op))
85950397Sobrien	{
86050397Sobrien	  if (stack_regs_mentioned_p (op))
86150397Sobrien	    abort ();
86250397Sobrien	  else
86350397Sobrien	    continue;
86450397Sobrien	}
86518334Speter
86618334Speter      /* Each destination is dead before this insn.  If the
86718334Speter	 destination is not used after this insn, record this with
86818334Speter	 REG_UNUSED.  */
86918334Speter
87018334Speter      if (! TEST_HARD_REG_BIT (regstack->reg_set, REGNO (op)))
87150397Sobrien	REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_UNUSED, op,
87250397Sobrien					      REG_NOTES (insn));
87318334Speter
87418334Speter      CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (op));
87518334Speter    }
87618334Speter
87718334Speter  /* Process all inputs */
87852284Sobrien  for (i = n_outputs; i < n_outputs + n_inputs; i++)
87918334Speter    {
88052284Sobrien      rtx op = recog_operand[i];
88152284Sobrien      if (! STACK_REG_P (op))
88250397Sobrien	{
88352284Sobrien	  if (stack_regs_mentioned_p (op))
88450397Sobrien	    abort ();
88550397Sobrien	  else
88650397Sobrien	    continue;
88750397Sobrien	}
88818334Speter
88918334Speter      /* If an input is dead after the insn, record a death note.
89018334Speter	 But don't record a death note if there is already a death note,
89118334Speter	 or if the input is also an output.  */
89218334Speter
89352284Sobrien      if (! TEST_HARD_REG_BIT (regstack->reg_set, REGNO (op))
89452284Sobrien	  && recog_op_alt[i][alt].matches == -1
89552284Sobrien	  && find_regno_note (insn, REG_DEAD, REGNO (op)) == NULL_RTX)
89652284Sobrien	REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_DEAD, op, REG_NOTES (insn));
89718334Speter
89852284Sobrien      SET_HARD_REG_BIT (regstack->reg_set, REGNO (op));
89918334Speter    }
90018334Speter}
90118334Speter
90218334Speter/* Scan PAT, which is part of INSN, and record registers appearing in
90318334Speter   a SET_DEST in DEST, and other registers in SRC.
90418334Speter
90518334Speter   This function does not know about SET_DESTs that are both input and
90650397Sobrien   output (such as ZERO_EXTRACT) - this cannot happen on a 387.  */
90718334Speter
90818334Speterstatic void
90918334Speterrecord_reg_life_pat (pat, src, dest, douse)
91018334Speter     rtx pat;
91118334Speter     HARD_REG_SET *src, *dest;
91218334Speter     int douse;
91318334Speter{
91418334Speter  register char *fmt;
91518334Speter  register int i;
91618334Speter
91718334Speter  if (STACK_REG_P (pat)
91850397Sobrien      || (GET_CODE (pat) == SUBREG && STACK_REG_P (SUBREG_REG (pat))))
91918334Speter    {
92018334Speter      if (src)
92118334Speter	 mark_regs_pat (pat, src);
92218334Speter
92318334Speter      if (dest)
92418334Speter	 mark_regs_pat (pat, dest);
92518334Speter
92618334Speter      return;
92718334Speter    }
92818334Speter
92918334Speter  if (GET_CODE (pat) == SET)
93018334Speter    {
93118334Speter      record_reg_life_pat (XEXP (pat, 0), NULL_PTR, dest, 0);
93218334Speter      record_reg_life_pat (XEXP (pat, 1), src, NULL_PTR, 0);
93318334Speter      return;
93418334Speter    }
93518334Speter
93650397Sobrien  /* We don't need to consider either of these cases.  */
93750397Sobrien  if ((GET_CODE (pat) == USE && !douse) || GET_CODE (pat) == CLOBBER)
93818334Speter    return;
93918334Speter
94018334Speter  fmt = GET_RTX_FORMAT (GET_CODE (pat));
94118334Speter  for (i = GET_RTX_LENGTH (GET_CODE (pat)) - 1; i >= 0; i--)
94218334Speter    {
94318334Speter      if (fmt[i] == 'E')
94418334Speter	{
94518334Speter	  register int j;
94618334Speter
94718334Speter	  for (j = XVECLEN (pat, i) - 1; j >= 0; j--)
94818334Speter	    record_reg_life_pat (XVECEXP (pat, i, j), src, dest, 0);
94918334Speter	}
95018334Speter      else if (fmt[i] == 'e')
95118334Speter	record_reg_life_pat (XEXP (pat, i), src, dest, 0);
95218334Speter    }
95318334Speter}
95418334Speter
95518334Speter/* Calculate the number of inputs and outputs in BODY, an
95618334Speter   asm_operands.  N_OPERANDS is the total number of operands, and
95718334Speter   N_INPUTS and N_OUTPUTS are pointers to ints into which the results are
95850397Sobrien   placed.  */
95918334Speter
96052284Sobrienstatic int
96152284Sobrienget_asm_operand_n_inputs (body)
96218334Speter     rtx body;
96318334Speter{
96418334Speter  if (GET_CODE (body) == SET && GET_CODE (SET_SRC (body)) == ASM_OPERANDS)
96552284Sobrien    return ASM_OPERANDS_INPUT_LENGTH (SET_SRC (body));
96618334Speter
96718334Speter  else if (GET_CODE (body) == ASM_OPERANDS)
96852284Sobrien    return ASM_OPERANDS_INPUT_LENGTH (body);
96918334Speter
97018334Speter  else if (GET_CODE (body) == PARALLEL
97118334Speter	   && GET_CODE (XVECEXP (body, 0, 0)) == SET)
97252284Sobrien    return ASM_OPERANDS_INPUT_LENGTH (SET_SRC (XVECEXP (body, 0, 0)));
97318334Speter
97418334Speter  else if (GET_CODE (body) == PARALLEL
97518334Speter	   && GET_CODE (XVECEXP (body, 0, 0)) == ASM_OPERANDS)
97652284Sobrien    return ASM_OPERANDS_INPUT_LENGTH (XVECEXP (body, 0, 0));
97718334Speter
97852284Sobrien  abort ();
97918334Speter}
98018334Speter
98118334Speter/* Scan INSN, which is in BLOCK, and record the life & death of stack
98218334Speter   registers in REGSTACK.  This function is called to process insns from
98318334Speter   the last insn in a block to the first.  The actual scanning is done in
98418334Speter   record_reg_life_pat.
98518334Speter
98618334Speter   If a register is live after a CALL_INSN, but is not a value return
98718334Speter   register for that CALL_INSN, then code is emitted to initialize that
98818334Speter   register.  The block_end[] data is kept accurate.
98918334Speter
99018334Speter   Existing death and unset notes for stack registers are deleted
99150397Sobrien   before processing the insn.  */
99218334Speter
99318334Speterstatic void
99418334Speterrecord_reg_life (insn, block, regstack)
99518334Speter     rtx insn;
99618334Speter     int block;
99718334Speter     stack regstack;
99818334Speter{
99918334Speter  rtx note, *note_link;
100018334Speter  int n_operands;
100118334Speter
100218334Speter  if ((GET_CODE (insn) != INSN && GET_CODE (insn) != CALL_INSN)
100318334Speter      || INSN_DELETED_P (insn))
100418334Speter    return;
100518334Speter
100618334Speter  /* Strip death notes for stack regs from this insn */
100718334Speter
100818334Speter  note_link = &REG_NOTES(insn);
100918334Speter  for (note = *note_link; note; note = XEXP (note, 1))
101018334Speter    if (STACK_REG_P (XEXP (note, 0))
101118334Speter	&& (REG_NOTE_KIND (note) == REG_DEAD
101218334Speter	    || REG_NOTE_KIND (note) == REG_UNUSED))
101318334Speter      *note_link = XEXP (note, 1);
101418334Speter    else
101518334Speter      note_link = &XEXP (note, 1);
101618334Speter
101750397Sobrien  /* Process all patterns in the insn.  */
101818334Speter
101918334Speter  n_operands = asm_noperands (PATTERN (insn));
102018334Speter  if (n_operands >= 0)
102118334Speter    {
102252284Sobrien      record_asm_reg_life (insn, regstack);
102318334Speter      return;
102418334Speter    }
102518334Speter
102618334Speter    {
102718334Speter      HARD_REG_SET src, dest;
102818334Speter      int regno;
102918334Speter
103018334Speter      CLEAR_HARD_REG_SET (src);
103118334Speter      CLEAR_HARD_REG_SET (dest);
103218334Speter
103318334Speter      if (GET_CODE (insn) == CALL_INSN)
103418334Speter	 for (note = CALL_INSN_FUNCTION_USAGE (insn);
103518334Speter	      note;
103618334Speter	      note = XEXP (note, 1))
103718334Speter	   if (GET_CODE (XEXP (note, 0)) == USE)
103818334Speter	     record_reg_life_pat (SET_DEST (XEXP (note, 0)), &src, NULL_PTR, 0);
103918334Speter
104018334Speter      record_reg_life_pat (PATTERN (insn), &src, &dest, 0);
104118334Speter      for (regno = FIRST_STACK_REG; regno <= LAST_STACK_REG; regno++)
104218334Speter	if (! TEST_HARD_REG_BIT (regstack->reg_set, regno))
104318334Speter	  {
104418334Speter	    if (TEST_HARD_REG_BIT (src, regno)
104518334Speter		&& ! TEST_HARD_REG_BIT (dest, regno))
104650397Sobrien	      REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_DEAD,
104750397Sobrien						    FP_MODE_REG (regno, DFmode),
104850397Sobrien						    REG_NOTES (insn));
104918334Speter	    else if (TEST_HARD_REG_BIT (dest, regno))
105050397Sobrien	      REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_UNUSED,
105150397Sobrien						    FP_MODE_REG (regno, DFmode),
105250397Sobrien						    REG_NOTES (insn));
105318334Speter	  }
105418334Speter
105518334Speter      if (GET_CODE (insn) == CALL_INSN)
105618334Speter        {
105718334Speter	  int reg;
105818334Speter
105918334Speter          /* There might be a reg that is live after a function call.
106018334Speter             Initialize it to zero so that the program does not crash.  See
106150397Sobrien	     comment towards the end of stack_reg_life_analysis().  */
106218334Speter
106318334Speter          for (reg = FIRST_STACK_REG; reg <= LAST_STACK_REG; reg++)
106418334Speter	    if (! TEST_HARD_REG_BIT (dest, reg)
106518334Speter	        && TEST_HARD_REG_BIT (regstack->reg_set, reg))
106618334Speter	      {
106718334Speter	        rtx init, pat;
106818334Speter
106918334Speter	        /* The insn will use virtual register numbers, and so
107018334Speter	           convert_regs is expected to process these.  But BLOCK_NUM
107118334Speter	           cannot be used on these insns, because they do not appear in
107250397Sobrien	           block_number[].  */
107318334Speter
107450397Sobrien	        pat = gen_rtx_SET (VOIDmode, FP_MODE_REG (reg, DFmode),
107550397Sobrien				   CONST0_RTX (DFmode));
107618334Speter	        init = emit_insn_after (pat, insn);
107718334Speter
107818334Speter	        CLEAR_HARD_REG_BIT (regstack->reg_set, reg);
107918334Speter
108018334Speter	        /* If the CALL_INSN was the end of a block, move the
108150397Sobrien	           block_end to point to the new insn.  */
108218334Speter
108318334Speter	        if (block_end[block] == insn)
108418334Speter	          block_end[block] = init;
108518334Speter	      }
108618334Speter
108718334Speter	  /* Some regs do not survive a CALL */
108818334Speter          AND_COMPL_HARD_REG_SET (regstack->reg_set, call_used_reg_set);
108918334Speter	}
109018334Speter
109118334Speter      AND_COMPL_HARD_REG_SET (regstack->reg_set, dest);
109218334Speter      IOR_HARD_REG_SET (regstack->reg_set, src);
109318334Speter    }
109418334Speter}
109518334Speter
109618334Speter/* Find all basic blocks of the function, which starts with FIRST.
109750397Sobrien   For each JUMP_INSN, build the chain of LABEL_REFS on each CODE_LABEL.  */
109818334Speter
109918334Speterstatic void
110018334Speterfind_blocks (first)
110118334Speter     rtx first;
110218334Speter{
110318334Speter  register rtx insn;
110418334Speter  register int block;
110518334Speter  register RTX_CODE prev_code = BARRIER;
110618334Speter  register RTX_CODE code;
110718334Speter  rtx label_value_list = 0;
110818334Speter
110918334Speter  /* Record where all the blocks start and end.
111050397Sobrien     Record which basic blocks control can drop in to.  */
111118334Speter
111218334Speter  block = -1;
111318334Speter  for (insn = first; insn; insn = NEXT_INSN (insn))
111418334Speter    {
111518334Speter      /* Note that this loop must select the same block boundaries
111618334Speter	 as code in reg_to_stack, but that these are not the same
111718334Speter	 as those selected in flow.c.  */
111818334Speter
111918334Speter      code = GET_CODE (insn);
112018334Speter
112118334Speter      if (code == CODE_LABEL
112218334Speter	  || (prev_code != INSN
112318334Speter	      && prev_code != CALL_INSN
112418334Speter	      && prev_code != CODE_LABEL
112518334Speter	      && GET_RTX_CLASS (code) == 'i'))
112618334Speter	{
112718334Speter	  block_begin[++block] = insn;
112818334Speter	  block_end[block] = insn;
112918334Speter	  block_drops_in[block] = prev_code != BARRIER;
113018334Speter	}
113118334Speter      else if (GET_RTX_CLASS (code) == 'i')
113218334Speter	block_end[block] = insn;
113318334Speter
113418334Speter      if (GET_RTX_CLASS (code) == 'i')
113518334Speter	{
113618334Speter	  rtx note;
113718334Speter
113818334Speter	  /* Make a list of all labels referred to other than by jumps.  */
113918334Speter	  for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
114018334Speter	    if (REG_NOTE_KIND (note) == REG_LABEL)
114150397Sobrien	      label_value_list = gen_rtx_EXPR_LIST (VOIDmode, XEXP (note, 0),
114250397Sobrien						    label_value_list);
114318334Speter	}
114418334Speter
114518334Speter      block_number[INSN_UID (insn)] = block;
114618334Speter
114718334Speter      if (code != NOTE)
114818334Speter	prev_code = code;
114918334Speter    }
115018334Speter
115118334Speter  if (block + 1 != blocks)
115218334Speter    abort ();
115318334Speter
115418334Speter  /* generate all label references to the corresponding jump insn */
115518334Speter  for (block = 0; block < blocks; block++)
115618334Speter    {
115718334Speter      insn = block_end[block];
115818334Speter
115918334Speter      if (GET_CODE (insn) == JUMP_INSN)
116018334Speter	{
116118334Speter	  rtx pat = PATTERN (insn);
116218334Speter	  rtx x;
116318334Speter
116450397Sobrien	  if (computed_jump_p (insn))
116518334Speter	    {
116618334Speter	      for (x = label_value_list; x; x = XEXP (x, 1))
116718334Speter		record_label_references (insn,
116850397Sobrien					 gen_rtx_LABEL_REF (VOIDmode,
116950397Sobrien							    XEXP (x, 0)));
117018334Speter
117118334Speter	      for (x = forced_labels; x; x = XEXP (x, 1))
117218334Speter		record_label_references (insn,
117350397Sobrien					 gen_rtx_LABEL_REF (VOIDmode,
117450397Sobrien							    XEXP (x, 0)));
117518334Speter	    }
117618334Speter
117718334Speter	  record_label_references (insn, pat);
117818334Speter	}
117918334Speter    }
118018334Speter}
118118334Speter
118218334Speter/* If current function returns its result in an fp stack register,
118318334Speter   return the REG.  Otherwise, return 0.  */
118418334Speter
118518334Speterstatic rtx
118618334Speterstack_result (decl)
118718334Speter     tree decl;
118818334Speter{
118918334Speter  rtx result = DECL_RTL (DECL_RESULT (decl));
119018334Speter
119118334Speter  if (result != 0
119218334Speter      && ! (GET_CODE (result) == REG
119318334Speter	    && REGNO (result) < FIRST_PSEUDO_REGISTER))
119418334Speter    {
119518334Speter#ifdef FUNCTION_OUTGOING_VALUE
119618334Speter      result
119718334Speter        = FUNCTION_OUTGOING_VALUE (TREE_TYPE (DECL_RESULT (decl)), decl);
119818334Speter#else
119918334Speter      result = FUNCTION_VALUE (TREE_TYPE (DECL_RESULT (decl)), decl);
120018334Speter#endif
120118334Speter    }
120218334Speter
120318334Speter  return result != 0 && STACK_REG_P (result) ? result : 0;
120418334Speter}
120518334Speter
120618334Speter/* Determine the which registers are live at the start of each basic
120718334Speter   block of the function whose first insn is FIRST.
120818334Speter
120918334Speter   First, if the function returns a real_type, mark the function
121018334Speter   return type as live at each return point, as the RTL may not give any
121118334Speter   hint that the register is live.
121218334Speter
121318334Speter   Then, start with the last block and work back to the first block.
121418334Speter   Similarly, work backwards within each block, insn by insn, recording
121518334Speter   which regs are dead and which are used (and therefore live) in the
121618334Speter   hard reg set of block_stack_in[].
121718334Speter
121818334Speter   After processing each basic block, if there is a label at the start
121918334Speter   of the block, propagate the live registers to all jumps to this block.
122018334Speter
122118334Speter   As a special case, if there are regs live in this block, that are
122218334Speter   not live in a block containing a jump to this label, and the block
122318334Speter   containing the jump has already been processed, we must propagate this
122418334Speter   block's entry register life back to the block containing the jump, and
122518334Speter   restart life analysis from there.
122618334Speter
122718334Speter   In the worst case, this function may traverse the insns
122818334Speter   REG_STACK_SIZE times.  This is necessary, since a jump towards the end
122918334Speter   of the insns may not know that a reg is live at a target that is early
123018334Speter   in the insns.  So we back up and start over with the new reg live.
123118334Speter
123218334Speter   If there are registers that are live at the start of the function,
123318334Speter   insns are emitted to initialize these registers.  Something similar is
123450397Sobrien   done after CALL_INSNs in record_reg_life.  */
123518334Speter
123618334Speterstatic void
123718334Speterstack_reg_life_analysis (first, stackentry)
123818334Speter     rtx first;
123918334Speter     HARD_REG_SET *stackentry;
124018334Speter{
124118334Speter  int reg, block;
124218334Speter  struct stack_def regstack;
124318334Speter
124418334Speter   {
124518334Speter     rtx retvalue;
124618334Speter
124750397Sobrien     if ((retvalue = stack_result (current_function_decl)))
124818334Speter      {
124950397Sobrien        /* Find all RETURN insns and mark them.  */
125018334Speter
125118334Speter        for (block = blocks - 1; --block >= 0;)
125218334Speter	   if (GET_CODE (block_end[block]) == JUMP_INSN
125352284Sobrien	       && returnjump_p (block_end[block]))
125418334Speter	      mark_regs_pat (retvalue, block_out_reg_set+block);
125518334Speter
125618334Speter        /* Mark off the end of last block if we "fall off" the end of the
125750397Sobrien	   function into the epilogue.  */
125818334Speter
125918334Speter        if (GET_CODE (block_end[blocks-1]) != JUMP_INSN
126052284Sobrien	    || returnjump_p (block_end[blocks-1]))
126118334Speter	  mark_regs_pat (retvalue, block_out_reg_set+blocks-1);
126218334Speter      }
126318334Speter   }
126418334Speter
126518334Speter  /* now scan all blocks backward for stack register use */
126618334Speter
126718334Speter  block = blocks - 1;
126818334Speter  while (block >= 0)
126918334Speter    {
127018334Speter      register rtx insn, prev;
127118334Speter
127218334Speter      /* current register status at last instruction */
127318334Speter
127418334Speter      COPY_HARD_REG_SET (regstack.reg_set, block_out_reg_set[block]);
127518334Speter
127618334Speter      prev = block_end[block];
127718334Speter      do
127818334Speter	{
127918334Speter	  insn = prev;
128018334Speter	  prev = PREV_INSN (insn);
128118334Speter
128218334Speter	  /* If the insn is a CALL_INSN, we need to ensure that
128318334Speter	     everything dies.  But otherwise don't process unless there
128450397Sobrien	     are some stack regs present.  */
128518334Speter
128652284Sobrien	  if (stack_regs_mentioned (insn) || GET_CODE (insn) == CALL_INSN)
128718334Speter	    record_reg_life (insn, block, &regstack);
128818334Speter
128918334Speter	} while (insn != block_begin[block]);
129018334Speter
129118334Speter      /* Set the state at the start of the block.  Mark that no
129250397Sobrien	 register mapping information known yet.  */
129318334Speter
129418334Speter      COPY_HARD_REG_SET (block_stack_in[block].reg_set, regstack.reg_set);
129518334Speter      block_stack_in[block].top = -2;
129618334Speter
129718334Speter      /* If there is a label, propagate our register life to all jumps
129850397Sobrien	 to this label.  */
129918334Speter
130018334Speter      if (GET_CODE (insn) == CODE_LABEL)
130118334Speter	{
130218334Speter	  register rtx label;
130318334Speter	  int must_restart = 0;
130418334Speter
130518334Speter	  for (label = LABEL_REFS (insn); label != insn;
130618334Speter	       label = LABEL_NEXTREF (label))
130718334Speter	    {
130818334Speter	      int jump_block = BLOCK_NUM (CONTAINING_INSN (label));
130918334Speter
131018334Speter	      if (jump_block < block)
131118334Speter		IOR_HARD_REG_SET (block_out_reg_set[jump_block],
131218334Speter				  block_stack_in[block].reg_set);
131318334Speter	      else
131418334Speter		{
131518334Speter		  /* The block containing the jump has already been
131618334Speter		     processed.  If there are registers that were not known
131718334Speter		     to be live then, but are live now, we must back up
131818334Speter		     and restart life analysis from that point with the new
131950397Sobrien		     life information.  */
132018334Speter
132118334Speter		  GO_IF_HARD_REG_SUBSET (block_stack_in[block].reg_set,
132218334Speter					 block_out_reg_set[jump_block],
132318334Speter					 win);
132418334Speter
132518334Speter		  IOR_HARD_REG_SET (block_out_reg_set[jump_block],
132618334Speter				    block_stack_in[block].reg_set);
132718334Speter
132818334Speter		  block = jump_block;
132918334Speter		  must_restart = 1;
133050397Sobrien		  break;
133118334Speter
133218334Speter		win:
133318334Speter		  ;
133418334Speter		}
133518334Speter	    }
133618334Speter	  if (must_restart)
133718334Speter	    continue;
133818334Speter	}
133918334Speter
134018334Speter      if (block_drops_in[block])
134118334Speter	IOR_HARD_REG_SET (block_out_reg_set[block-1],
134218334Speter			  block_stack_in[block].reg_set);
134318334Speter
134418334Speter      block -= 1;
134518334Speter    }
134618334Speter
134718334Speter    /* If any reg is live at the start of the first block of a
134818334Speter       function, then we must guarantee that the reg holds some value by
134918334Speter       generating our own "load" of that register.  Otherwise a 387 would
135050397Sobrien       fault trying to access an empty register.  */
135118334Speter
135218334Speter  /* Load zero into each live register.  The fact that a register
135318334Speter     appears live at the function start necessarily implies an error
135418334Speter     in the user program: it means that (unless the offending code is *never*
135518334Speter     executed) this program is using uninitialised floating point
135618334Speter     variables.  In order to keep broken code like this happy, we initialise
135718334Speter     those variables with zero.
135818334Speter
135918334Speter     Note that we are inserting virtual register references here:
136018334Speter     these insns must be processed by convert_regs later.  Also, these
136150397Sobrien     insns will not be in block_number, so BLOCK_NUM() will fail for them.  */
136218334Speter
136318334Speter  for (reg = LAST_STACK_REG; reg >= FIRST_STACK_REG; reg--)
136418334Speter    if (TEST_HARD_REG_BIT (block_stack_in[0].reg_set, reg)
136518334Speter        && ! TEST_HARD_REG_BIT (*stackentry, reg))
136618334Speter      {
136718334Speter	rtx init_rtx;
136818334Speter
136950397Sobrien	init_rtx = gen_rtx_SET (VOIDmode, FP_MODE_REG(reg, DFmode),
137050397Sobrien				CONST0_RTX (DFmode));
137118334Speter	block_begin[0] = emit_insn_after (init_rtx, first);
137218334Speter
137318334Speter	CLEAR_HARD_REG_BIT (block_stack_in[0].reg_set, reg);
137418334Speter      }
137518334Speter}
137618334Speter
137718334Speter/*****************************************************************************
137818334Speter   This section deals with stack register substitution, and forms the second
137918334Speter   pass over the RTL.
138018334Speter *****************************************************************************/
138118334Speter
138218334Speter/* Replace REG, which is a pointer to a stack reg RTX, with an RTX for
138350397Sobrien   the desired hard REGNO.  */
138418334Speter
138518334Speterstatic void
138618334Speterreplace_reg (reg, regno)
138718334Speter     rtx *reg;
138818334Speter     int regno;
138918334Speter{
139018334Speter  if (regno < FIRST_STACK_REG || regno > LAST_STACK_REG
139118334Speter      || ! STACK_REG_P (*reg))
139218334Speter    abort ();
139318334Speter
139418334Speter  switch (GET_MODE_CLASS (GET_MODE (*reg)))
139518334Speter   {
139618334Speter     default: abort ();
139718334Speter     case MODE_FLOAT:
139818334Speter     case MODE_COMPLEX_FLOAT:;
139918334Speter   }
140018334Speter
140118334Speter  *reg = FP_MODE_REG (regno, GET_MODE (*reg));
140218334Speter}
140318334Speter
140418334Speter/* Remove a note of type NOTE, which must be found, for register
140550397Sobrien   number REGNO from INSN.  Remove only one such note.  */
140618334Speter
140718334Speterstatic void
140818334Speterremove_regno_note (insn, note, regno)
140918334Speter     rtx insn;
141018334Speter     enum reg_note note;
141118334Speter     int regno;
141218334Speter{
141318334Speter  register rtx *note_link, this;
141418334Speter
141518334Speter  note_link = &REG_NOTES(insn);
141618334Speter  for (this = *note_link; this; this = XEXP (this, 1))
141718334Speter    if (REG_NOTE_KIND (this) == note
141818334Speter	&& REG_P (XEXP (this, 0)) && REGNO (XEXP (this, 0)) == regno)
141918334Speter      {
142018334Speter	*note_link = XEXP (this, 1);
142118334Speter	return;
142218334Speter      }
142318334Speter    else
142418334Speter      note_link = &XEXP (this, 1);
142518334Speter
142618334Speter  abort ();
142718334Speter}
142818334Speter
142918334Speter/* Find the hard register number of virtual register REG in REGSTACK.
143018334Speter   The hard register number is relative to the top of the stack.  -1 is
143150397Sobrien   returned if the register is not found.  */
143218334Speter
143318334Speterstatic int
143418334Speterget_hard_regnum (regstack, reg)
143518334Speter     stack regstack;
143618334Speter     rtx reg;
143718334Speter{
143818334Speter  int i;
143918334Speter
144018334Speter  if (! STACK_REG_P (reg))
144118334Speter    abort ();
144218334Speter
144318334Speter  for (i = regstack->top; i >= 0; i--)
144418334Speter    if (regstack->reg[i] == REGNO (reg))
144518334Speter      break;
144618334Speter
144718334Speter  return i >= 0 ? (FIRST_STACK_REG + regstack->top - i) : -1;
144818334Speter}
144918334Speter
145018334Speter/* Delete INSN from the RTL.  Mark the insn, but don't remove it from
145118334Speter   the chain of insns.  Doing so could confuse block_begin and block_end
145250397Sobrien   if this were the only insn in the block.  */
145318334Speter
145418334Speterstatic void
145518334Speterdelete_insn_for_stacker (insn)
145618334Speter     rtx insn;
145718334Speter{
145852284Sobrien  int i;
145952284Sobrien
146052284Sobrien  /* Ensure that the side effects were clobbers when deleting a PARALLEL.  */
146152284Sobrien  if (GET_CODE (PATTERN (insn)) == PARALLEL)
146252284Sobrien    for (i = 1; i < XVECLEN (PATTERN (insn), 0); i++)
146352284Sobrien      if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) != CLOBBER)
146452284Sobrien	abort ();
146552284Sobrien
146618334Speter  PUT_CODE (insn, NOTE);
146718334Speter  NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
146818334Speter  NOTE_SOURCE_FILE (insn) = 0;
146918334Speter}
147018334Speter
147118334Speter/* Emit an insn to pop virtual register REG before or after INSN.
147218334Speter   REGSTACK is the stack state after INSN and is updated to reflect this
147352284Sobrien   pop.  WHEN is either emit_insn_before, emit_insn_after or NULL.
147452284Sobrien   in case WHEN is NULL we don't really emit the insn, just modify stack
147552284Sobrien   information.  Caller is expected to emit insn himself.
147652284Sobrien
147752284Sobrien   A pop insn is represented as a SET whose destination is the register to
147852284Sobrien   be popped and source is the top of stack.  A death note for the top of stack
147950397Sobrien   cases the movdf pattern to pop.  */
148018334Speter
148118334Speterstatic rtx
148218334Speteremit_pop_insn (insn, regstack, reg, when)
148318334Speter     rtx insn;
148418334Speter     stack regstack;
148518334Speter     rtx reg;
148618334Speter     rtx (*when)();
148718334Speter{
148818334Speter  rtx pop_insn, pop_rtx;
148918334Speter  int hard_regno;
149018334Speter
149118334Speter  hard_regno = get_hard_regnum (regstack, reg);
149218334Speter
149318334Speter  if (hard_regno < FIRST_STACK_REG)
149418334Speter    abort ();
149518334Speter
149652284Sobrien  if (when)
149752284Sobrien   {
149852284Sobrien     pop_rtx = gen_rtx_SET (VOIDmode, FP_MODE_REG (hard_regno, DFmode),
149952284Sobrien			    FP_MODE_REG (FIRST_STACK_REG, DFmode));
150018334Speter
150152284Sobrien     pop_insn = (*when) (pop_rtx, insn);
150218334Speter
150352284Sobrien     REG_NOTES (pop_insn) = gen_rtx_EXPR_LIST (REG_DEAD,
150452284Sobrien					       FP_MODE_REG (FIRST_STACK_REG,
150552284Sobrien							    DFmode),
150652284Sobrien					       REG_NOTES (pop_insn));
150752284Sobrien   }
150818334Speter
150918334Speter  regstack->reg[regstack->top - (hard_regno - FIRST_STACK_REG)]
151018334Speter    = regstack->reg[regstack->top];
151118334Speter  regstack->top -= 1;
151218334Speter  CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (reg));
151318334Speter
151418334Speter  return pop_insn;
151518334Speter}
151618334Speter
151718334Speter/* Emit an insn before or after INSN to swap virtual register REG with the
151818334Speter   top of stack.  WHEN should be `emit_insn_before' or `emit_insn_before'
151918334Speter   REGSTACK is the stack state before the swap, and is updated to reflect
152018334Speter   the swap.  A swap insn is represented as a PARALLEL of two patterns:
152118334Speter   each pattern moves one reg to the other.
152218334Speter
152350397Sobrien   If REG is already at the top of the stack, no insn is emitted.  */
152418334Speter
152518334Speterstatic void
152618334Speteremit_swap_insn (insn, regstack, reg)
152718334Speter     rtx insn;
152818334Speter     stack regstack;
152918334Speter     rtx reg;
153018334Speter{
153118334Speter  int hard_regno;
153218334Speter  rtx gen_swapdf();
153318334Speter  rtx swap_rtx, swap_insn;
153418334Speter  int tmp, other_reg;		/* swap regno temps */
153518334Speter  rtx i1;			/* the stack-reg insn prior to INSN */
153618334Speter  rtx i1set = NULL_RTX;		/* the SET rtx within I1 */
153718334Speter
153818334Speter  hard_regno = get_hard_regnum (regstack, reg);
153918334Speter
154018334Speter  if (hard_regno < FIRST_STACK_REG)
154118334Speter    abort ();
154218334Speter  if (hard_regno == FIRST_STACK_REG)
154318334Speter    return;
154418334Speter
154518334Speter  other_reg = regstack->top - (hard_regno - FIRST_STACK_REG);
154618334Speter
154718334Speter  tmp = regstack->reg[other_reg];
154818334Speter  regstack->reg[other_reg] = regstack->reg[regstack->top];
154918334Speter  regstack->reg[regstack->top] = tmp;
155018334Speter
155118334Speter  /* Find the previous insn involving stack regs, but don't go past
155218334Speter     any labels, calls or jumps.  */
155318334Speter  i1 = prev_nonnote_insn (insn);
155452284Sobrien  while (i1 && GET_CODE (i1) == INSN && !stack_regs_mentioned (i1))
155518334Speter    i1 = prev_nonnote_insn (i1);
155618334Speter
155718334Speter  if (i1)
155818334Speter    i1set = single_set (i1);
155918334Speter
156018334Speter  if (i1set)
156118334Speter    {
156218334Speter      rtx i1src = *get_true_reg (&SET_SRC (i1set));
156318334Speter      rtx i1dest = *get_true_reg (&SET_DEST (i1set));
156418334Speter
156518334Speter      /* If the previous register stack push was from the reg we are to
156650397Sobrien	 swap with, omit the swap.  */
156718334Speter
156818334Speter      if (GET_CODE (i1dest) == REG && REGNO (i1dest) == FIRST_STACK_REG
156918334Speter	  && GET_CODE (i1src) == REG && REGNO (i1src) == hard_regno - 1
157018334Speter	  && find_regno_note (i1, REG_DEAD, FIRST_STACK_REG) == NULL_RTX)
157118334Speter	return;
157218334Speter
157318334Speter      /* If the previous insn wrote to the reg we are to swap with,
157418334Speter	 omit the swap.  */
157518334Speter
157618334Speter      if (GET_CODE (i1dest) == REG && REGNO (i1dest) == hard_regno
157718334Speter	  && GET_CODE (i1src) == REG && REGNO (i1src) == FIRST_STACK_REG
157818334Speter	  && find_regno_note (i1, REG_DEAD, FIRST_STACK_REG) == NULL_RTX)
157918334Speter	return;
158018334Speter    }
158118334Speter
158218334Speter  if (GET_RTX_CLASS (GET_CODE (i1)) == 'i' && sets_cc0_p (PATTERN (i1)))
158318334Speter    {
158418334Speter      i1 = next_nonnote_insn (i1);
158518334Speter      if (i1 == insn)
158618334Speter	abort ();
158718334Speter    }
158818334Speter
158918334Speter  swap_rtx = gen_swapdf (FP_MODE_REG (hard_regno, DFmode),
159018334Speter			 FP_MODE_REG (FIRST_STACK_REG, DFmode));
159118334Speter  swap_insn = emit_insn_after (swap_rtx, i1);
159218334Speter}
159318334Speter
159418334Speter/* Handle a move to or from a stack register in PAT, which is in INSN.
159550397Sobrien   REGSTACK is the current stack.  */
159618334Speter
159718334Speterstatic void
159818334Spetermove_for_stack_reg (insn, regstack, pat)
159918334Speter     rtx insn;
160018334Speter     stack regstack;
160118334Speter     rtx pat;
160218334Speter{
160318334Speter  rtx *psrc =  get_true_reg (&SET_SRC (pat));
160418334Speter  rtx *pdest = get_true_reg (&SET_DEST (pat));
160518334Speter  rtx src, dest;
160618334Speter  rtx note;
160718334Speter
160818334Speter  src = *psrc; dest = *pdest;
160918334Speter
161018334Speter  if (STACK_REG_P (src) && STACK_REG_P (dest))
161118334Speter    {
161218334Speter      /* Write from one stack reg to another.  If SRC dies here, then
161350397Sobrien	 just change the register mapping and delete the insn.  */
161418334Speter
161518334Speter      note = find_regno_note (insn, REG_DEAD, REGNO (src));
161618334Speter      if (note)
161718334Speter	{
161818334Speter	  int i;
161918334Speter
162050397Sobrien	  /* If this is a no-op move, there must not be a REG_DEAD note.  */
162118334Speter	  if (REGNO (src) == REGNO (dest))
162218334Speter	    abort ();
162318334Speter
162418334Speter	  for (i = regstack->top; i >= 0; i--)
162518334Speter	    if (regstack->reg[i] == REGNO (src))
162618334Speter	      break;
162718334Speter
162850397Sobrien	  /* The source must be live, and the dest must be dead.  */
162918334Speter	  if (i < 0 || get_hard_regnum (regstack, dest) >= FIRST_STACK_REG)
163018334Speter	    abort ();
163118334Speter
163218334Speter	  /* It is possible that the dest is unused after this insn.
163350397Sobrien	     If so, just pop the src.  */
163418334Speter
163518334Speter	  if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))
163618334Speter	    {
163718334Speter	      emit_pop_insn (insn, regstack, src, emit_insn_after);
163818334Speter
163918334Speter	      delete_insn_for_stacker (insn);
164018334Speter	      return;
164118334Speter	    }
164218334Speter
164318334Speter	  regstack->reg[i] = REGNO (dest);
164418334Speter
164518334Speter	  SET_HARD_REG_BIT (regstack->reg_set, REGNO (dest));
164618334Speter	  CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (src));
164718334Speter
164818334Speter	  delete_insn_for_stacker (insn);
164918334Speter
165018334Speter	  return;
165118334Speter	}
165218334Speter
165350397Sobrien      /* The source reg does not die.  */
165418334Speter
165518334Speter      /* If this appears to be a no-op move, delete it, or else it
165618334Speter	 will confuse the machine description output patterns. But if
165718334Speter	 it is REG_UNUSED, we must pop the reg now, as per-insn processing
165850397Sobrien	 for REG_UNUSED will not work for deleted insns.  */
165918334Speter
166018334Speter      if (REGNO (src) == REGNO (dest))
166118334Speter	{
166218334Speter	  if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))
166318334Speter	    emit_pop_insn (insn, regstack, dest, emit_insn_after);
166418334Speter
166518334Speter	  delete_insn_for_stacker (insn);
166618334Speter	  return;
166718334Speter	}
166818334Speter
166918334Speter      /* The destination ought to be dead */
167018334Speter      if (get_hard_regnum (regstack, dest) >= FIRST_STACK_REG)
167118334Speter	abort ();
167218334Speter
167318334Speter      replace_reg (psrc, get_hard_regnum (regstack, src));
167418334Speter
167518334Speter      regstack->reg[++regstack->top] = REGNO (dest);
167618334Speter      SET_HARD_REG_BIT (regstack->reg_set, REGNO (dest));
167718334Speter      replace_reg (pdest, FIRST_STACK_REG);
167818334Speter    }
167918334Speter  else if (STACK_REG_P (src))
168018334Speter    {
168118334Speter      /* Save from a stack reg to MEM, or possibly integer reg.  Since
168218334Speter	 only top of stack may be saved, emit an exchange first if
168350397Sobrien	 needs be.  */
168418334Speter
168518334Speter      emit_swap_insn (insn, regstack, src);
168618334Speter
168718334Speter      note = find_regno_note (insn, REG_DEAD, REGNO (src));
168818334Speter      if (note)
168918334Speter	{
169018334Speter	  replace_reg (&XEXP (note, 0), FIRST_STACK_REG);
169118334Speter	  regstack->top--;
169218334Speter	  CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (src));
169318334Speter	}
169450397Sobrien      else if (GET_MODE (src) == XFmode && regstack->top < REG_STACK_SIZE - 1)
169518334Speter	{
169618334Speter	  /* A 387 cannot write an XFmode value to a MEM without
169718334Speter	     clobbering the source reg.  The output code can handle
169818334Speter	     this by reading back the value from the MEM.
169918334Speter	     But it is more efficient to use a temp register if one is
170018334Speter	     available.  Push the source value here if the register
170118334Speter	     stack is not full, and then write the value to memory via
170218334Speter	     a pop.  */
170318334Speter	  rtx push_rtx, push_insn;
170418334Speter	  rtx top_stack_reg = FP_MODE_REG (FIRST_STACK_REG, XFmode);
170518334Speter
170618334Speter	  push_rtx = gen_movxf (top_stack_reg, top_stack_reg);
170718334Speter	  push_insn = emit_insn_before (push_rtx, insn);
170850397Sobrien	  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_DEAD, top_stack_reg,
170950397Sobrien						REG_NOTES (insn));
171018334Speter	}
171118334Speter
171218334Speter      replace_reg (psrc, FIRST_STACK_REG);
171318334Speter    }
171418334Speter  else if (STACK_REG_P (dest))
171518334Speter    {
171618334Speter      /* Load from MEM, or possibly integer REG or constant, into the
171718334Speter	 stack regs.  The actual target is always the top of the
171818334Speter	 stack. The stack mapping is changed to reflect that DEST is
171918334Speter	 now at top of stack.  */
172018334Speter
172118334Speter      /* The destination ought to be dead */
172218334Speter      if (get_hard_regnum (regstack, dest) >= FIRST_STACK_REG)
172318334Speter	abort ();
172418334Speter
172518334Speter      if (regstack->top >= REG_STACK_SIZE)
172618334Speter	abort ();
172718334Speter
172818334Speter      regstack->reg[++regstack->top] = REGNO (dest);
172918334Speter      SET_HARD_REG_BIT (regstack->reg_set, REGNO (dest));
173018334Speter      replace_reg (pdest, FIRST_STACK_REG);
173118334Speter    }
173218334Speter  else
173318334Speter    abort ();
173418334Speter}
173518334Speter
173650397Sobrienstatic void
173718334Speterswap_rtx_condition (pat)
173818334Speter     rtx pat;
173918334Speter{
174018334Speter  register char *fmt;
174118334Speter  register int i;
174218334Speter
174318334Speter  if (GET_RTX_CLASS (GET_CODE (pat)) == '<')
174418334Speter    {
174518334Speter      PUT_CODE (pat, swap_condition (GET_CODE (pat)));
174618334Speter      return;
174718334Speter    }
174818334Speter
174918334Speter  fmt = GET_RTX_FORMAT (GET_CODE (pat));
175018334Speter  for (i = GET_RTX_LENGTH (GET_CODE (pat)) - 1; i >= 0; i--)
175118334Speter    {
175218334Speter      if (fmt[i] == 'E')
175318334Speter	{
175418334Speter	  register int j;
175518334Speter
175618334Speter	  for (j = XVECLEN (pat, i) - 1; j >= 0; j--)
175718334Speter	    swap_rtx_condition (XVECEXP (pat, i, j));
175818334Speter	}
175918334Speter      else if (fmt[i] == 'e')
176018334Speter	swap_rtx_condition (XEXP (pat, i));
176118334Speter    }
176218334Speter}
176318334Speter
176418334Speter/* Handle a comparison.  Special care needs to be taken to avoid
176518334Speter   causing comparisons that a 387 cannot do correctly, such as EQ.
176618334Speter
176752284Sobrien   Also, a fstp instruction may need to be emitted.  The 387 does have an
176818334Speter   `fcompp' insn that can pop two regs, but it is sometimes too expensive
176918334Speter   to do this - a `fcomp' followed by a `fstpl %st(0)' may be easier to
177052284Sobrien   set up.
177152284Sobrien
177252284Sobrien   We can not handle this by emiting fpop instruction after compare, because
177352284Sobrien   it appears between cc0 setter and user.  So we emit only
177452284Sobrien   REG_DEAD note and handle it as a special case in machine description.
177552284Sobrien
177652284Sobrien   This code used trick with delay_slot filling to emit pop insn after
177752284Sobrien   comparsion but it didn't worked because it caused confusion with cc_status
177852284Sobrien   in final pass. */
177918334Speter
178018334Speterstatic void
178118334Spetercompare_for_stack_reg (insn, regstack, pat)
178218334Speter     rtx insn;
178318334Speter     stack regstack;
178418334Speter     rtx pat;
178518334Speter{
178618334Speter  rtx *src1, *src2;
178718334Speter  rtx src1_note, src2_note;
178850397Sobrien  rtx cc0_user;
178950397Sobrien  int have_cmove;
179052284Sobrien  int hard_regno;
179118334Speter
179218334Speter  src1 = get_true_reg (&XEXP (SET_SRC (pat), 0));
179318334Speter  src2 = get_true_reg (&XEXP (SET_SRC (pat), 1));
179450397Sobrien  cc0_user = next_cc0_user (insn);
179518334Speter
179650397Sobrien  /* If the insn that uses cc0 is an FP-conditional move, then the destination
179750397Sobrien     must be the top of stack */
179850397Sobrien  if (GET_CODE (PATTERN (cc0_user)) == SET
179950397Sobrien      && SET_DEST (PATTERN (cc0_user)) != pc_rtx
180050397Sobrien      && GET_CODE (SET_SRC (PATTERN (cc0_user))) == IF_THEN_ELSE
180150397Sobrien      && (GET_MODE_CLASS (GET_MODE (SET_DEST (PATTERN (cc0_user))))
180250397Sobrien	  == MODE_FLOAT))
180350397Sobrien    {
180450397Sobrien      rtx *dest;
180550397Sobrien
180650397Sobrien      dest = get_true_reg (&SET_DEST (PATTERN (cc0_user)));
180750397Sobrien
180850397Sobrien      have_cmove = 1;
180950397Sobrien      if (get_hard_regnum (regstack, *dest) >= FIRST_STACK_REG
181050397Sobrien	  && REGNO (*dest) != regstack->reg[regstack->top])
181150397Sobrien	{
181250397Sobrien	  emit_swap_insn (insn, regstack, *dest);
181350397Sobrien	}
181450397Sobrien    }
181550397Sobrien  else
181650397Sobrien    have_cmove = 0;
181750397Sobrien
181818334Speter  /* ??? If fxch turns out to be cheaper than fstp, give priority to
181950397Sobrien     registers that die in this insn - move those to stack top first.  */
182018334Speter  if (! STACK_REG_P (*src1)
182118334Speter      || (STACK_REG_P (*src2)
182218334Speter	  && get_hard_regnum (regstack, *src2) == FIRST_STACK_REG))
182318334Speter    {
182418334Speter      rtx temp, next;
182518334Speter
182618334Speter      temp = XEXP (SET_SRC (pat), 0);
182718334Speter      XEXP (SET_SRC (pat), 0) = XEXP (SET_SRC (pat), 1);
182818334Speter      XEXP (SET_SRC (pat), 1) = temp;
182918334Speter
183018334Speter      src1 = get_true_reg (&XEXP (SET_SRC (pat), 0));
183118334Speter      src2 = get_true_reg (&XEXP (SET_SRC (pat), 1));
183218334Speter
183318334Speter      next = next_cc0_user (insn);
183418334Speter      if (next == NULL_RTX)
183518334Speter	abort ();
183618334Speter
183718334Speter      swap_rtx_condition (PATTERN (next));
183818334Speter      INSN_CODE (next) = -1;
183918334Speter      INSN_CODE (insn) = -1;
184018334Speter    }
184118334Speter
184250397Sobrien  /* We will fix any death note later.  */
184318334Speter
184418334Speter  src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
184518334Speter
184618334Speter  if (STACK_REG_P (*src2))
184718334Speter    src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2));
184818334Speter  else
184918334Speter    src2_note = NULL_RTX;
185018334Speter
185150397Sobrien  if (! have_cmove)
185250397Sobrien     emit_swap_insn (insn, regstack, *src1);
185318334Speter
185418334Speter  replace_reg (src1, FIRST_STACK_REG);
185518334Speter
185618334Speter  if (STACK_REG_P (*src2))
185752284Sobrien    {
185852284Sobrien      hard_regno = get_hard_regnum (regstack, *src2);
185952284Sobrien      replace_reg (src2, hard_regno);
186052284Sobrien    }
186118334Speter
186218334Speter  if (src1_note)
186318334Speter    {
186450397Sobrien      pop_stack (regstack, REGNO (XEXP (src1_note, 0)));
186518334Speter      replace_reg (&XEXP (src1_note, 0), FIRST_STACK_REG);
186618334Speter    }
186718334Speter
186818334Speter  /* If the second operand dies, handle that.  But if the operands are
186918334Speter     the same stack register, don't bother, because only one death is
187050397Sobrien     needed, and it was just handled.  */
187118334Speter
187218334Speter  if (src2_note
187318334Speter      && ! (STACK_REG_P (*src1) && STACK_REG_P (*src2)
187418334Speter	    && REGNO (*src1) == REGNO (*src2)))
187518334Speter    {
187618334Speter      /* As a special case, two regs may die in this insn if src2 is
187718334Speter	 next to top of stack and the top of stack also dies.  Since
187818334Speter	 we have already popped src1, "next to top of stack" is really
187950397Sobrien	 at top (FIRST_STACK_REG) now.  */
188018334Speter
188118334Speter      if (get_hard_regnum (regstack, XEXP (src2_note, 0)) == FIRST_STACK_REG
188218334Speter	  && src1_note)
188318334Speter	{
188450397Sobrien	  pop_stack (regstack, REGNO (XEXP (src2_note, 0)));
188518334Speter	  replace_reg (&XEXP (src2_note, 0), FIRST_STACK_REG + 1);
188618334Speter	}
188718334Speter      else
188818334Speter	{
188952284Sobrien	  /* Pop of second operand is handled using special REG_DEAD note
189052284Sobrien	     because we can't emit pop insn after cc0 setter.  */
189118334Speter
189252284Sobrien	  emit_pop_insn (insn, regstack, XEXP (src2_note, 0), NULL);
189352284Sobrien	  replace_reg (&XEXP (src2_note, 0), hard_regno);
189418334Speter	}
189518334Speter    }
189618334Speter}
189718334Speter
189818334Speter/* Substitute new registers in PAT, which is part of INSN.  REGSTACK
189950397Sobrien   is the current register layout.  */
190018334Speter
190118334Speterstatic void
190218334Spetersubst_stack_regs_pat (insn, regstack, pat)
190318334Speter     rtx insn;
190418334Speter     stack regstack;
190518334Speter     rtx pat;
190618334Speter{
190718334Speter  rtx *dest, *src;
190818334Speter  rtx *src1 = (rtx *) NULL_PTR, *src2;
190918334Speter  rtx src1_note, src2_note;
191018334Speter
191118334Speter  if (GET_CODE (pat) != SET)
191218334Speter    return;
191318334Speter
191418334Speter  dest = get_true_reg (&SET_DEST (pat));
191518334Speter  src  = get_true_reg (&SET_SRC (pat));
191618334Speter
191750397Sobrien  /* See if this is a `movM' pattern, and handle elsewhere if so.  */
191818334Speter
191918334Speter  if (*dest != cc0_rtx
192018334Speter      && (STACK_REG_P (*src)
192118334Speter	  || (STACK_REG_P (*dest)
192218334Speter	      && (GET_CODE (*src) == REG || GET_CODE (*src) == MEM
192318334Speter		  || GET_CODE (*src) == CONST_DOUBLE))))
192418334Speter    move_for_stack_reg (insn, regstack, pat);
192518334Speter  else
192618334Speter    switch (GET_CODE (SET_SRC (pat)))
192718334Speter      {
192818334Speter      case COMPARE:
192918334Speter	compare_for_stack_reg (insn, regstack, pat);
193018334Speter	break;
193118334Speter
193218334Speter      case CALL:
193318334Speter	 {
193418334Speter	   int count;
193518334Speter	   for (count = HARD_REGNO_NREGS (REGNO (*dest), GET_MODE (*dest));
193618334Speter              --count >= 0;)
193718334Speter	    {
193818334Speter	      regstack->reg[++regstack->top] = REGNO (*dest) + count;
193918334Speter	      SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest) + count);
194018334Speter	    }
194118334Speter	 }
194218334Speter	replace_reg (dest, FIRST_STACK_REG);
194318334Speter	break;
194418334Speter
194518334Speter      case REG:
194650397Sobrien	/* This is a `tstM2' case.  */
194718334Speter	if (*dest != cc0_rtx)
194818334Speter	  abort ();
194918334Speter
195018334Speter	src1 = src;
195118334Speter
195250397Sobrien	/* Fall through.  */
195318334Speter
195418334Speter      case FLOAT_TRUNCATE:
195518334Speter      case SQRT:
195618334Speter      case ABS:
195718334Speter      case NEG:
195818334Speter	/* These insns only operate on the top of the stack. DEST might
195918334Speter	   be cc0_rtx if we're processing a tstM pattern. Also, it's
196018334Speter	   possible that the tstM case results in a REG_DEAD note on the
196118334Speter	   source.  */
196218334Speter
196318334Speter	if (src1 == 0)
196418334Speter	  src1 = get_true_reg (&XEXP (SET_SRC (pat), 0));
196518334Speter
196618334Speter	emit_swap_insn (insn, regstack, *src1);
196718334Speter
196818334Speter	src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
196918334Speter
197018334Speter	if (STACK_REG_P (*dest))
197118334Speter	  replace_reg (dest, FIRST_STACK_REG);
197218334Speter
197318334Speter	if (src1_note)
197418334Speter	  {
197518334Speter	    replace_reg (&XEXP (src1_note, 0), FIRST_STACK_REG);
197618334Speter	    regstack->top--;
197718334Speter	    CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (*src1));
197818334Speter	  }
197918334Speter
198018334Speter	replace_reg (src1, FIRST_STACK_REG);
198118334Speter
198218334Speter	break;
198318334Speter
198418334Speter      case MINUS:
198518334Speter      case DIV:
198618334Speter	/* On i386, reversed forms of subM3 and divM3 exist for
198718334Speter	   MODE_FLOAT, so the same code that works for addM3 and mulM3
198850397Sobrien	   can be used.  */
198918334Speter      case MULT:
199018334Speter      case PLUS:
199118334Speter	/* These insns can accept the top of stack as a destination
199218334Speter	   from a stack reg or mem, or can use the top of stack as a
199318334Speter	   source and some other stack register (possibly top of stack)
199450397Sobrien	   as a destination.  */
199518334Speter
199618334Speter	src1 = get_true_reg (&XEXP (SET_SRC (pat), 0));
199718334Speter	src2 = get_true_reg (&XEXP (SET_SRC (pat), 1));
199818334Speter
199950397Sobrien	/* We will fix any death note later.  */
200018334Speter
200118334Speter	if (STACK_REG_P (*src1))
200218334Speter	  src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
200318334Speter	else
200418334Speter	  src1_note = NULL_RTX;
200518334Speter	if (STACK_REG_P (*src2))
200618334Speter	  src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2));
200718334Speter	else
200818334Speter	  src2_note = NULL_RTX;
200918334Speter
201018334Speter	/* If either operand is not a stack register, then the dest
201150397Sobrien	   must be top of stack.  */
201218334Speter
201318334Speter	if (! STACK_REG_P (*src1) || ! STACK_REG_P (*src2))
201418334Speter	  emit_swap_insn (insn, regstack, *dest);
201518334Speter	else
201618334Speter	  {
201718334Speter	    /* Both operands are REG.  If neither operand is already
201818334Speter	       at the top of stack, choose to make the one that is the dest
201918334Speter	       the new top of stack.  */
202018334Speter
202118334Speter	    int src1_hard_regnum, src2_hard_regnum;
202218334Speter
202318334Speter	    src1_hard_regnum = get_hard_regnum (regstack, *src1);
202418334Speter	    src2_hard_regnum = get_hard_regnum (regstack, *src2);
202518334Speter	    if (src1_hard_regnum == -1 || src2_hard_regnum == -1)
202618334Speter	      abort ();
202718334Speter
202818334Speter	    if (src1_hard_regnum != FIRST_STACK_REG
202918334Speter		&& src2_hard_regnum != FIRST_STACK_REG)
203018334Speter	      emit_swap_insn (insn, regstack, *dest);
203118334Speter	  }
203218334Speter
203318334Speter	if (STACK_REG_P (*src1))
203418334Speter	  replace_reg (src1, get_hard_regnum (regstack, *src1));
203518334Speter	if (STACK_REG_P (*src2))
203618334Speter	  replace_reg (src2, get_hard_regnum (regstack, *src2));
203718334Speter
203818334Speter	if (src1_note)
203918334Speter	  {
204018334Speter	    /* If the register that dies is at the top of stack, then
204118334Speter	       the destination is somewhere else - merely substitute it.
204218334Speter	       But if the reg that dies is not at top of stack, then
204318334Speter	       move the top of stack to the dead reg, as though we had
204450397Sobrien	       done the insn and then a store-with-pop.  */
204518334Speter
204618334Speter	    if (REGNO (XEXP (src1_note, 0)) == regstack->reg[regstack->top])
204718334Speter	      {
204818334Speter		SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));
204918334Speter		replace_reg (dest, get_hard_regnum (regstack, *dest));
205018334Speter	      }
205118334Speter	    else
205218334Speter	      {
205318334Speter		int regno = get_hard_regnum (regstack, XEXP (src1_note, 0));
205418334Speter
205518334Speter		SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));
205618334Speter		replace_reg (dest, regno);
205718334Speter
205818334Speter		regstack->reg[regstack->top - (regno - FIRST_STACK_REG)]
205918334Speter		  = regstack->reg[regstack->top];
206018334Speter	      }
206118334Speter
206218334Speter	    CLEAR_HARD_REG_BIT (regstack->reg_set,
206318334Speter				REGNO (XEXP (src1_note, 0)));
206418334Speter	    replace_reg (&XEXP (src1_note, 0), FIRST_STACK_REG);
206518334Speter	    regstack->top--;
206618334Speter	  }
206718334Speter	else if (src2_note)
206818334Speter	  {
206918334Speter	    if (REGNO (XEXP (src2_note, 0)) == regstack->reg[regstack->top])
207018334Speter	      {
207118334Speter		SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));
207218334Speter		replace_reg (dest, get_hard_regnum (regstack, *dest));
207318334Speter	      }
207418334Speter	    else
207518334Speter	      {
207618334Speter		int regno = get_hard_regnum (regstack, XEXP (src2_note, 0));
207718334Speter
207818334Speter		SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));
207918334Speter		replace_reg (dest, regno);
208018334Speter
208118334Speter		regstack->reg[regstack->top - (regno - FIRST_STACK_REG)]
208218334Speter		  = regstack->reg[regstack->top];
208318334Speter	      }
208418334Speter
208518334Speter	    CLEAR_HARD_REG_BIT (regstack->reg_set,
208618334Speter				REGNO (XEXP (src2_note, 0)));
208718334Speter	    replace_reg (&XEXP (src2_note, 0), FIRST_STACK_REG);
208818334Speter	    regstack->top--;
208918334Speter	  }
209018334Speter	else
209118334Speter	  {
209218334Speter	    SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));
209318334Speter	    replace_reg (dest, get_hard_regnum (regstack, *dest));
209418334Speter	  }
209518334Speter
209618334Speter	break;
209718334Speter
209818334Speter      case UNSPEC:
209918334Speter	switch (XINT (SET_SRC (pat), 1))
210018334Speter	  {
210118334Speter	  case 1: /* sin */
210218334Speter	  case 2: /* cos */
210318334Speter	    /* These insns only operate on the top of the stack.  */
210418334Speter
210518334Speter	    src1 = get_true_reg (&XVECEXP (SET_SRC (pat), 0, 0));
210618334Speter
210718334Speter	    emit_swap_insn (insn, regstack, *src1);
210818334Speter
210918334Speter	    src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
211018334Speter
211118334Speter	    if (STACK_REG_P (*dest))
211218334Speter	      replace_reg (dest, FIRST_STACK_REG);
211318334Speter
211418334Speter	    if (src1_note)
211518334Speter	      {
211618334Speter		replace_reg (&XEXP (src1_note, 0), FIRST_STACK_REG);
211718334Speter		regstack->top--;
211818334Speter		CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (*src1));
211918334Speter	      }
212018334Speter
212118334Speter	    replace_reg (src1, FIRST_STACK_REG);
212218334Speter
212318334Speter	    break;
212418334Speter
212518334Speter	  default:
212618334Speter	    abort ();
212718334Speter	  }
212818334Speter	break;
212918334Speter
213050397Sobrien      case IF_THEN_ELSE:
213150397Sobrien	/* dest has to be on stack. */
213250397Sobrien	if (get_hard_regnum (regstack, *dest) < FIRST_STACK_REG)
213350397Sobrien	  abort ();
213450397Sobrien
213550397Sobrien	/* This insn requires the top of stack to be the destination. */
213650397Sobrien
213750397Sobrien	/* If the comparison operator is an FP comparison operator,
213850397Sobrien	   it is handled correctly by compare_for_stack_reg () who
213950397Sobrien	   will move the destination to the top of stack. But if the
214050397Sobrien	   comparison operator is not an FP comparison operator, we
214150397Sobrien	   have to handle it here. */
214250397Sobrien	if (get_hard_regnum (regstack, *dest) >= FIRST_STACK_REG
214350397Sobrien	    && REGNO (*dest) != regstack->reg[regstack->top])
214450397Sobrien	  emit_swap_insn (insn, regstack, *dest);
214550397Sobrien
214650397Sobrien	src1 = get_true_reg (&XEXP (SET_SRC (pat), 1));
214750397Sobrien	src2 = get_true_reg (&XEXP (SET_SRC (pat), 2));
214850397Sobrien
214950397Sobrien	src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
215050397Sobrien	src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2));
215150397Sobrien
215250397Sobrien	{
215350397Sobrien	  rtx src_note [3];
215450397Sobrien	  int i;
215550397Sobrien
215650397Sobrien	  src_note[0] = 0;
215750397Sobrien	  src_note[1] = src1_note;
215850397Sobrien	  src_note[2] = src2_note;
215950397Sobrien
216050397Sobrien	  if (STACK_REG_P (*src1))
216150397Sobrien	    replace_reg (src1, get_hard_regnum (regstack, *src1));
216250397Sobrien	  if (STACK_REG_P (*src2))
216350397Sobrien	    replace_reg (src2, get_hard_regnum (regstack, *src2));
216450397Sobrien
216550397Sobrien	  for (i = 1; i <= 2; i++)
216650397Sobrien	    if (src_note [i])
216750397Sobrien	      {
216850397Sobrien		/* If the register that dies is not at the top of stack, then
216950397Sobrien		   move the top of stack to the dead reg */
217050397Sobrien		if (REGNO (XEXP (src_note[i], 0))
217150397Sobrien		    != regstack->reg[regstack->top])
217250397Sobrien		  {
217350397Sobrien		    remove_regno_note (insn, REG_DEAD,
217450397Sobrien				       REGNO (XEXP (src_note [i], 0)));
217550397Sobrien		    emit_pop_insn (insn, regstack, XEXP (src_note[i], 0),
217650397Sobrien				   emit_insn_after);
217750397Sobrien		  }
217850397Sobrien		else
217950397Sobrien		  {
218050397Sobrien		    CLEAR_HARD_REG_BIT (regstack->reg_set,
218150397Sobrien					REGNO (XEXP (src_note[i], 0)));
218250397Sobrien		    replace_reg (&XEXP (src_note[i], 0), FIRST_STACK_REG);
218350397Sobrien		    regstack->top--;
218450397Sobrien		  }
218550397Sobrien	      }
218650397Sobrien	}
218750397Sobrien
218850397Sobrien	/* Make dest the top of stack. */
218950397Sobrien	SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));
219050397Sobrien	replace_reg (dest, FIRST_STACK_REG);
219150397Sobrien
219250397Sobrien	break;
219350397Sobrien
219418334Speter      default:
219518334Speter	abort ();
219618334Speter      }
219718334Speter}
219818334Speter
219918334Speter/* Substitute hard regnums for any stack regs in INSN, which has
220018334Speter   N_INPUTS inputs and N_OUTPUTS outputs.  REGSTACK is the stack info
220152284Sobrien   before the insn, and is updated with changes made here.
220218334Speter
220318334Speter   There are several requirements and assumptions about the use of
220418334Speter   stack-like regs in asm statements.  These rules are enforced by
220518334Speter   record_asm_stack_regs; see comments there for details.  Any
220618334Speter   asm_operands left in the RTL at this point may be assume to meet the
220718334Speter   requirements, since record_asm_stack_regs removes any problem asm.  */
220818334Speter
220918334Speterstatic void
221052284Sobriensubst_asm_stack_regs (insn, regstack)
221118334Speter     rtx insn;
221218334Speter     stack regstack;
221318334Speter{
221418334Speter  rtx body = PATTERN (insn);
221552284Sobrien  int alt;
221618334Speter
221718334Speter  rtx *note_reg;		/* Array of note contents */
221818334Speter  rtx **note_loc;		/* Address of REG field of each note */
221918334Speter  enum reg_note *note_kind;	/* The type of each note */
222018334Speter
222118334Speter  rtx *clobber_reg;
222218334Speter  rtx **clobber_loc;
222318334Speter
222418334Speter  struct stack_def temp_stack;
222518334Speter  int n_notes;
222618334Speter  int n_clobbers;
222718334Speter  rtx note;
222818334Speter  int i;
222952284Sobrien  int n_inputs, n_outputs;
223018334Speter
223118334Speter  /* Find out what the constraints required.  If no constraint
223218334Speter     alternative matches, that is a compiler bug: we should have caught
223318334Speter     such an insn during the life analysis pass (and reload should have
223450397Sobrien     caught it regardless).  */
223552284Sobrien  extract_insn (insn);
223652284Sobrien  constrain_operands (1);
223752284Sobrien  alt = which_alternative;
223818334Speter
223952284Sobrien  preprocess_constraints ();
224052284Sobrien
224152284Sobrien  n_inputs = get_asm_operand_n_inputs (body);
224252284Sobrien  n_outputs = recog_n_operands - n_inputs;
224352284Sobrien
224452284Sobrien  if (alt < 0)
224518334Speter    abort ();
224618334Speter
224750397Sobrien  /* Strip SUBREGs here to make the following code simpler.  */
224852284Sobrien  for (i = 0; i < recog_n_operands; i++)
224952284Sobrien    if (GET_CODE (recog_operand[i]) == SUBREG
225052284Sobrien	&& GET_CODE (SUBREG_REG (recog_operand[i])) == REG)
225118334Speter      {
225252284Sobrien	recog_operand_loc[i] = & SUBREG_REG (recog_operand[i]);
225352284Sobrien	recog_operand[i] = SUBREG_REG (recog_operand[i]);
225418334Speter      }
225518334Speter
225618334Speter  /* Set up NOTE_REG, NOTE_LOC and NOTE_KIND.  */
225718334Speter
225818334Speter  for (i = 0, note = REG_NOTES (insn); note; note = XEXP (note, 1))
225918334Speter    i++;
226018334Speter
226118334Speter  note_reg = (rtx *) alloca (i * sizeof (rtx));
226218334Speter  note_loc = (rtx **) alloca (i * sizeof (rtx *));
226318334Speter  note_kind = (enum reg_note *) alloca (i * sizeof (enum reg_note));
226418334Speter
226518334Speter  n_notes = 0;
226618334Speter  for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
226718334Speter    {
226818334Speter      rtx reg = XEXP (note, 0);
226918334Speter      rtx *loc = & XEXP (note, 0);
227018334Speter
227118334Speter      if (GET_CODE (reg) == SUBREG && GET_CODE (SUBREG_REG (reg)) == REG)
227218334Speter	{
227318334Speter	  loc = & SUBREG_REG (reg);
227418334Speter	  reg = SUBREG_REG (reg);
227518334Speter	}
227618334Speter
227718334Speter      if (STACK_REG_P (reg)
227818334Speter	  && (REG_NOTE_KIND (note) == REG_DEAD
227918334Speter	      || REG_NOTE_KIND (note) == REG_UNUSED))
228018334Speter	{
228118334Speter	  note_reg[n_notes] = reg;
228218334Speter	  note_loc[n_notes] = loc;
228318334Speter	  note_kind[n_notes] = REG_NOTE_KIND (note);
228418334Speter	  n_notes++;
228518334Speter	}
228618334Speter    }
228718334Speter
228818334Speter  /* Set up CLOBBER_REG and CLOBBER_LOC.  */
228918334Speter
229018334Speter  n_clobbers = 0;
229118334Speter
229218334Speter  if (GET_CODE (body) == PARALLEL)
229318334Speter    {
229452284Sobrien      clobber_reg = (rtx *) alloca (XVECLEN (body, 0) * sizeof (rtx));
229552284Sobrien      clobber_loc = (rtx **) alloca (XVECLEN (body, 0) * sizeof (rtx *));
229618334Speter
229718334Speter      for (i = 0; i < XVECLEN (body, 0); i++)
229818334Speter	if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER)
229918334Speter	  {
230018334Speter	    rtx clobber = XVECEXP (body, 0, i);
230118334Speter	    rtx reg = XEXP (clobber, 0);
230218334Speter	    rtx *loc = & XEXP (clobber, 0);
230318334Speter
230418334Speter	    if (GET_CODE (reg) == SUBREG && GET_CODE (SUBREG_REG (reg)) == REG)
230518334Speter	      {
230618334Speter		loc = & SUBREG_REG (reg);
230718334Speter		reg = SUBREG_REG (reg);
230818334Speter	      }
230918334Speter
231018334Speter	    if (STACK_REG_P (reg))
231118334Speter	      {
231218334Speter		clobber_reg[n_clobbers] = reg;
231318334Speter		clobber_loc[n_clobbers] = loc;
231418334Speter		n_clobbers++;
231518334Speter	      }
231618334Speter	  }
231718334Speter    }
231818334Speter
231918334Speter  bcopy ((char *) regstack, (char *) &temp_stack, sizeof (temp_stack));
232018334Speter
232118334Speter  /* Put the input regs into the desired place in TEMP_STACK.  */
232218334Speter
232352284Sobrien  for (i = n_outputs; i < n_outputs + n_inputs; i++)
232452284Sobrien    if (STACK_REG_P (recog_operand[i])
232552284Sobrien	&& reg_class_subset_p (recog_op_alt[i][alt].class,
232652284Sobrien			       FLOAT_REGS)
232752284Sobrien	&& recog_op_alt[i][alt].class != FLOAT_REGS)
232818334Speter      {
232918334Speter	/* If an operand needs to be in a particular reg in
233018334Speter	   FLOAT_REGS, the constraint was either 't' or 'u'.  Since
233118334Speter	   these constraints are for single register classes, and reload
233218334Speter	   guaranteed that operand[i] is already in that class, we can
233352284Sobrien	   just use REGNO (recog_operand[i]) to know which actual reg this
233450397Sobrien	   operand needs to be in.  */
233518334Speter
233652284Sobrien	int regno = get_hard_regnum (&temp_stack, recog_operand[i]);
233718334Speter
233818334Speter	if (regno < 0)
233918334Speter	  abort ();
234018334Speter
234152284Sobrien	if (regno != REGNO (recog_operand[i]))
234218334Speter	  {
234352284Sobrien	    /* recog_operand[i] is not in the right place.  Find it
234418334Speter	       and swap it with whatever is already in I's place.
234552284Sobrien	       K is where recog_operand[i] is now.  J is where it should
234650397Sobrien	       be.  */
234718334Speter	    int j, k, temp;
234818334Speter
234918334Speter	    k = temp_stack.top - (regno - FIRST_STACK_REG);
235018334Speter	    j = (temp_stack.top
235152284Sobrien		 - (REGNO (recog_operand[i]) - FIRST_STACK_REG));
235218334Speter
235318334Speter	    temp = temp_stack.reg[k];
235418334Speter	    temp_stack.reg[k] = temp_stack.reg[j];
235518334Speter	    temp_stack.reg[j] = temp;
235618334Speter	  }
235718334Speter      }
235818334Speter
235918334Speter  /* emit insns before INSN to make sure the reg-stack is in the right
236018334Speter     order.  */
236118334Speter
236218334Speter  change_stack (insn, regstack, &temp_stack, emit_insn_before);
236318334Speter
236418334Speter  /* Make the needed input register substitutions.  Do death notes and
236550397Sobrien     clobbers too, because these are for inputs, not outputs.  */
236618334Speter
236752284Sobrien  for (i = n_outputs; i < n_outputs + n_inputs; i++)
236852284Sobrien    if (STACK_REG_P (recog_operand[i]))
236918334Speter      {
237052284Sobrien	int regnum = get_hard_regnum (regstack, recog_operand[i]);
237118334Speter
237218334Speter	if (regnum < 0)
237318334Speter	  abort ();
237418334Speter
237552284Sobrien	replace_reg (recog_operand_loc[i], regnum);
237618334Speter      }
237718334Speter
237818334Speter  for (i = 0; i < n_notes; i++)
237918334Speter    if (note_kind[i] == REG_DEAD)
238018334Speter      {
238118334Speter	int regnum = get_hard_regnum (regstack, note_reg[i]);
238218334Speter
238318334Speter	if (regnum < 0)
238418334Speter	  abort ();
238518334Speter
238618334Speter	replace_reg (note_loc[i], regnum);
238718334Speter      }
238818334Speter
238918334Speter  for (i = 0; i < n_clobbers; i++)
239018334Speter    {
239118334Speter      /* It's OK for a CLOBBER to reference a reg that is not live.
239218334Speter         Don't try to replace it in that case.  */
239318334Speter      int regnum = get_hard_regnum (regstack, clobber_reg[i]);
239418334Speter
239518334Speter      if (regnum >= 0)
239618334Speter	{
239718334Speter	  /* Sigh - clobbers always have QImode.  But replace_reg knows
239818334Speter	     that these regs can't be MODE_INT and will abort.  Just put
239918334Speter	     the right reg there without calling replace_reg.  */
240018334Speter
240118334Speter	  *clobber_loc[i] = FP_MODE_REG (regnum, DFmode);
240218334Speter	}
240318334Speter    }
240418334Speter
240550397Sobrien  /* Now remove from REGSTACK any inputs that the asm implicitly popped.  */
240618334Speter
240752284Sobrien  for (i = n_outputs; i < n_outputs + n_inputs; i++)
240852284Sobrien    if (STACK_REG_P (recog_operand[i]))
240918334Speter      {
241018334Speter	/* An input reg is implicitly popped if it is tied to an
241150397Sobrien	   output, or if there is a CLOBBER for it.  */
241218334Speter	int j;
241318334Speter
241418334Speter	for (j = 0; j < n_clobbers; j++)
241552284Sobrien	  if (operands_match_p (clobber_reg[j], recog_operand[i]))
241618334Speter	    break;
241718334Speter
241852284Sobrien	if (j < n_clobbers || recog_op_alt[i][alt].matches >= 0)
241918334Speter	  {
242052284Sobrien	    /* recog_operand[i] might not be at the top of stack.  But that's
242152284Sobrien	       OK, because all we need to do is pop the right number of regs
242218334Speter	       off of the top of the reg-stack.  record_asm_stack_regs
242318334Speter	       guaranteed that all implicitly popped regs were grouped
242418334Speter	       at the top of the reg-stack.  */
242518334Speter
242618334Speter	    CLEAR_HARD_REG_BIT (regstack->reg_set,
242718334Speter				regstack->reg[regstack->top]);
242818334Speter	    regstack->top--;
242918334Speter	  }
243018334Speter      }
243118334Speter
243218334Speter  /* Now add to REGSTACK any outputs that the asm implicitly pushed.
243318334Speter     Note that there isn't any need to substitute register numbers.
243450397Sobrien     ???  Explain why this is true.  */
243518334Speter
243618334Speter  for (i = LAST_STACK_REG; i >= FIRST_STACK_REG; i--)
243718334Speter    {
243818334Speter      /* See if there is an output for this hard reg.  */
243918334Speter      int j;
244018334Speter
244118334Speter      for (j = 0; j < n_outputs; j++)
244252284Sobrien	if (STACK_REG_P (recog_operand[j]) && REGNO (recog_operand[j]) == i)
244318334Speter	  {
244418334Speter	    regstack->reg[++regstack->top] = i;
244518334Speter	    SET_HARD_REG_BIT (regstack->reg_set, i);
244618334Speter	    break;
244718334Speter	  }
244818334Speter    }
244918334Speter
245018334Speter  /* Now emit a pop insn for any REG_UNUSED output, or any REG_DEAD
245118334Speter     input that the asm didn't implicitly pop.  If the asm didn't
245218334Speter     implicitly pop an input reg, that reg will still be live.
245318334Speter
245418334Speter     Note that we can't use find_regno_note here: the register numbers
245518334Speter     in the death notes have already been substituted.  */
245618334Speter
245718334Speter  for (i = 0; i < n_outputs; i++)
245852284Sobrien    if (STACK_REG_P (recog_operand[i]))
245918334Speter      {
246018334Speter	int j;
246118334Speter
246218334Speter	for (j = 0; j < n_notes; j++)
246352284Sobrien	  if (REGNO (recog_operand[i]) == REGNO (note_reg[j])
246418334Speter	      && note_kind[j] == REG_UNUSED)
246518334Speter	    {
246652284Sobrien	      insn = emit_pop_insn (insn, regstack, recog_operand[i],
246718334Speter				    emit_insn_after);
246818334Speter	      break;
246918334Speter	    }
247018334Speter      }
247118334Speter
247252284Sobrien  for (i = n_outputs; i < n_outputs + n_inputs; i++)
247352284Sobrien    if (STACK_REG_P (recog_operand[i]))
247418334Speter      {
247518334Speter	int j;
247618334Speter
247718334Speter	for (j = 0; j < n_notes; j++)
247852284Sobrien	  if (REGNO (recog_operand[i]) == REGNO (note_reg[j])
247918334Speter	      && note_kind[j] == REG_DEAD
248052284Sobrien	      && TEST_HARD_REG_BIT (regstack->reg_set,
248152284Sobrien				    REGNO (recog_operand[i])))
248218334Speter	    {
248352284Sobrien	      insn = emit_pop_insn (insn, regstack, recog_operand[i],
248418334Speter				    emit_insn_after);
248518334Speter	      break;
248618334Speter	    }
248718334Speter      }
248818334Speter}
248918334Speter
249018334Speter/* Substitute stack hard reg numbers for stack virtual registers in
249118334Speter   INSN.  Non-stack register numbers are not changed.  REGSTACK is the
249218334Speter   current stack content.  Insns may be emitted as needed to arrange the
249350397Sobrien   stack for the 387 based on the contents of the insn.  */
249418334Speter
249518334Speterstatic void
249618334Spetersubst_stack_regs (insn, regstack)
249718334Speter     rtx insn;
249818334Speter     stack regstack;
249918334Speter{
250018334Speter  register rtx *note_link, note;
250118334Speter  register int i;
250218334Speter
250318334Speter  if (GET_CODE (insn) == CALL_INSN)
250418334Speter   {
250518334Speter     int top = regstack->top;
250618334Speter
250718334Speter     /* If there are any floating point parameters to be passed in
250818334Speter	registers for this call, make sure they are in the right
250918334Speter	order.  */
251018334Speter
251118334Speter     if (top >= 0)
251218334Speter      {
251318334Speter	straighten_stack (PREV_INSN (insn), regstack);
251418334Speter
251518334Speter	/* Now mark the arguments as dead after the call.  */
251618334Speter
251718334Speter        while (regstack->top >= 0)
251818334Speter         {
251918334Speter           CLEAR_HARD_REG_BIT (regstack->reg_set, FIRST_STACK_REG + regstack->top);
252018334Speter	   regstack->top--;
252118334Speter         }
252218334Speter      }
252318334Speter   }
252418334Speter
252518334Speter  /* Do the actual substitution if any stack regs are mentioned.
252618334Speter     Since we only record whether entire insn mentions stack regs, and
252718334Speter     subst_stack_regs_pat only works for patterns that contain stack regs,
252818334Speter     we must check each pattern in a parallel here.  A call_value_pop could
252950397Sobrien     fail otherwise.  */
253018334Speter
253152284Sobrien  if (stack_regs_mentioned (insn))
253218334Speter    {
253352284Sobrien      int n_operands = asm_noperands (PATTERN (insn));
253418334Speter      if (n_operands >= 0)
253518334Speter	{
253618334Speter	  /* This insn is an `asm' with operands.  Decode the operands,
253718334Speter	     decide how many are inputs, and do register substitution.
253850397Sobrien	     Any REG_UNUSED notes will be handled by subst_asm_stack_regs.  */
253918334Speter
254052284Sobrien	  subst_asm_stack_regs (insn, regstack);
254118334Speter	  return;
254218334Speter	}
254318334Speter
254418334Speter      if (GET_CODE (PATTERN (insn)) == PARALLEL)
254518334Speter	for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
254618334Speter	  {
254718334Speter	    if (stack_regs_mentioned_p (XVECEXP (PATTERN (insn), 0, i)))
254852284Sobrien	      {
254952284Sobrien		subst_stack_regs_pat (insn, regstack,
255052284Sobrien				      XVECEXP (PATTERN (insn), 0, i));
255152284Sobrien
255252284Sobrien		/* subst_stack_regs_pat may have deleted a no-op insn.  */
255352284Sobrien		if (GET_CODE (insn) == NOTE)
255452284Sobrien		  break;
255552284Sobrien	      }
255618334Speter	  }
255718334Speter      else
255818334Speter	subst_stack_regs_pat (insn, regstack, PATTERN (insn));
255918334Speter    }
256018334Speter
256118334Speter  /* subst_stack_regs_pat may have deleted a no-op insn.  If so, any
256250397Sobrien     REG_UNUSED will already have been dealt with, so just return.  */
256318334Speter
256418334Speter  if (GET_CODE (insn) == NOTE)
256518334Speter    return;
256618334Speter
256718334Speter  /* If there is a REG_UNUSED note on a stack register on this insn,
256818334Speter     the indicated reg must be popped.  The REG_UNUSED note is removed,
256918334Speter     since the form of the newly emitted pop insn references the reg,
257050397Sobrien     making it no longer `unset'.  */
257118334Speter
257218334Speter  note_link = &REG_NOTES(insn);
257318334Speter  for (note = *note_link; note; note = XEXP (note, 1))
257418334Speter    if (REG_NOTE_KIND (note) == REG_UNUSED && STACK_REG_P (XEXP (note, 0)))
257518334Speter      {
257618334Speter	*note_link = XEXP (note, 1);
257718334Speter	insn = emit_pop_insn (insn, regstack, XEXP (note, 0), emit_insn_after);
257818334Speter      }
257918334Speter    else
258018334Speter      note_link = &XEXP (note, 1);
258118334Speter}
258218334Speter
258318334Speter/* Change the organization of the stack so that it fits a new basic
258418334Speter   block.  Some registers might have to be popped, but there can never be
258518334Speter   a register live in the new block that is not now live.
258618334Speter
258718334Speter   Insert any needed insns before or after INSN.  WHEN is emit_insn_before
258818334Speter   or emit_insn_after. OLD is the original stack layout, and NEW is
258918334Speter   the desired form.  OLD is updated to reflect the code emitted, ie, it
259018334Speter   will be the same as NEW upon return.
259118334Speter
259218334Speter   This function will not preserve block_end[].  But that information
259350397Sobrien   is no longer needed once this has executed.  */
259418334Speter
259518334Speterstatic void
259618334Speterchange_stack (insn, old, new, when)
259718334Speter     rtx insn;
259818334Speter     stack old;
259918334Speter     stack new;
260018334Speter     rtx (*when)();
260118334Speter{
260218334Speter  int reg;
260318334Speter
260418334Speter  /* We will be inserting new insns "backwards", by calling emit_insn_before.
260518334Speter     If we are to insert after INSN, find the next insn, and insert before
260618334Speter     it.  */
260718334Speter
260818334Speter  if (when == emit_insn_after)
260918334Speter    insn = NEXT_INSN (insn);
261018334Speter
261150397Sobrien  /* Pop any registers that are not needed in the new block.  */
261218334Speter
261318334Speter  for (reg = old->top; reg >= 0; reg--)
261418334Speter    if (! TEST_HARD_REG_BIT (new->reg_set, old->reg[reg]))
261518334Speter      emit_pop_insn (insn, old, FP_MODE_REG (old->reg[reg], DFmode),
261618334Speter		     emit_insn_before);
261718334Speter
261818334Speter  if (new->top == -2)
261918334Speter    {
262018334Speter      /* If the new block has never been processed, then it can inherit
262150397Sobrien	 the old stack order.  */
262218334Speter
262318334Speter      new->top = old->top;
262418334Speter      bcopy (old->reg, new->reg, sizeof (new->reg));
262518334Speter    }
262618334Speter  else
262718334Speter    {
262818334Speter      /* This block has been entered before, and we must match the
262950397Sobrien	 previously selected stack order.  */
263018334Speter
263118334Speter      /* By now, the only difference should be the order of the stack,
263250397Sobrien	 not their depth or liveliness.  */
263318334Speter
263418334Speter      GO_IF_HARD_REG_EQUAL (old->reg_set, new->reg_set, win);
263518334Speter
263618334Speter      abort ();
263718334Speter
263818334Speter    win:
263918334Speter
264018334Speter      if (old->top != new->top)
264118334Speter	abort ();
264218334Speter
264352284Sobrien      /* If the stack is not empty (new->top != -1), loop here emitting
264452284Sobrien	 swaps until the stack is correct.
264552284Sobrien
264652284Sobrien	 The worst case number of swaps emitted is N + 2, where N is the
264718334Speter	 depth of the stack.  In some cases, the reg at the top of
264818334Speter	 stack may be correct, but swapped anyway in order to fix
264918334Speter	 other regs.  But since we never swap any other reg away from
265050397Sobrien	 its correct slot, this algorithm will converge.  */
265118334Speter
265252284Sobrien      if (new->top != -1)
265352284Sobrien	do
265452284Sobrien	  {
265552284Sobrien	    /* Swap the reg at top of stack into the position it is
265652284Sobrien	       supposed to be in, until the correct top of stack appears.  */
265718334Speter
265852284Sobrien	    while (old->reg[old->top] != new->reg[new->top])
265952284Sobrien	      {
266052284Sobrien		for (reg = new->top; reg >= 0; reg--)
266152284Sobrien		  if (new->reg[reg] == old->reg[old->top])
266252284Sobrien		    break;
266318334Speter
266452284Sobrien		if (reg == -1)
266552284Sobrien		  abort ();
266618334Speter
266752284Sobrien		emit_swap_insn (insn, old,
266852284Sobrien				FP_MODE_REG (old->reg[reg], DFmode));
266952284Sobrien	      }
267018334Speter
267152284Sobrien	    /* See if any regs remain incorrect.  If so, bring an
267218334Speter	     incorrect reg to the top of stack, and let the while loop
267350397Sobrien	     above fix it.  */
267418334Speter
267552284Sobrien	    for (reg = new->top; reg >= 0; reg--)
267652284Sobrien	      if (new->reg[reg] != old->reg[reg])
267752284Sobrien		{
267852284Sobrien		  emit_swap_insn (insn, old,
267952284Sobrien				  FP_MODE_REG (old->reg[reg], DFmode));
268052284Sobrien		  break;
268152284Sobrien		}
268252284Sobrien	  } while (reg >= 0);
268318334Speter
268450397Sobrien      /* At this point there must be no differences.  */
268518334Speter
268618334Speter      for (reg = old->top; reg >= 0; reg--)
268718334Speter	if (old->reg[reg] != new->reg[reg])
268818334Speter	  abort ();
268918334Speter    }
269018334Speter}
269118334Speter
269218334Speter/* Check PAT, which points to RTL in INSN, for a LABEL_REF.  If it is
269318334Speter   found, ensure that a jump from INSN to the code_label to which the
269418334Speter   label_ref points ends up with the same stack as that at the
269518334Speter   code_label.  Do this by inserting insns just before the code_label to
269618334Speter   pop and rotate the stack until it is in the correct order.  REGSTACK
269718334Speter   is the order of the register stack in INSN.
269818334Speter
269918334Speter   Any code that is emitted here must not be later processed as part
270050397Sobrien   of any block, as it will already contain hard register numbers.  */
270118334Speter
270218334Speterstatic void
270318334Spetergoto_block_pat (insn, regstack, pat)
270418334Speter     rtx insn;
270518334Speter     stack regstack;
270618334Speter     rtx pat;
270718334Speter{
270818334Speter  rtx label;
270918334Speter  rtx new_jump, new_label, new_barrier;
271018334Speter  rtx *ref;
271118334Speter  stack label_stack;
271218334Speter  struct stack_def temp_stack;
271318334Speter  int reg;
271418334Speter
271518334Speter  switch (GET_CODE (pat))
271618334Speter   {
271718334Speter     case RETURN:
271818334Speter	straighten_stack (PREV_INSN (insn), regstack);
271918334Speter	return;
272018334Speter     default:
272118334Speter     {
272218334Speter      int i, j;
272318334Speter      char *fmt = GET_RTX_FORMAT (GET_CODE (pat));
272418334Speter
272518334Speter      for (i = GET_RTX_LENGTH (GET_CODE (pat)) - 1; i >= 0; i--)
272618334Speter	{
272718334Speter	  if (fmt[i] == 'e')
272818334Speter	    goto_block_pat (insn, regstack, XEXP (pat, i));
272918334Speter	  if (fmt[i] == 'E')
273018334Speter	    for (j = 0; j < XVECLEN (pat, i); j++)
273118334Speter	      goto_block_pat (insn, regstack, XVECEXP (pat, i, j));
273218334Speter	}
273318334Speter      return;
273418334Speter     }
273518334Speter     case LABEL_REF:;
273618334Speter   }
273718334Speter
273818334Speter  label = XEXP (pat, 0);
273918334Speter  if (GET_CODE (label) != CODE_LABEL)
274018334Speter    abort ();
274118334Speter
274250397Sobrien  /* First, see if in fact anything needs to be done to the stack at all.  */
274318334Speter  if (INSN_UID (label) <= 0)
274418334Speter    return;
274518334Speter
274618334Speter  label_stack = &block_stack_in[BLOCK_NUM (label)];
274718334Speter
274818334Speter  if (label_stack->top == -2)
274918334Speter    {
275018334Speter      /* If the target block hasn't had a stack order selected, then
275150397Sobrien	 we need merely ensure that no pops are needed.  */
275218334Speter
275318334Speter      for (reg = regstack->top; reg >= 0; reg--)
275418334Speter	if (! TEST_HARD_REG_BIT (label_stack->reg_set, regstack->reg[reg]))
275518334Speter	  break;
275618334Speter
275718334Speter      if (reg == -1)
275818334Speter	{
275950397Sobrien	  /* change_stack will not emit any code in this case.  */
276018334Speter
276118334Speter	  change_stack (label, regstack, label_stack, emit_insn_after);
276218334Speter	  return;
276318334Speter	}
276418334Speter    }
276518334Speter  else if (label_stack->top == regstack->top)
276618334Speter    {
276718334Speter      for (reg = label_stack->top; reg >= 0; reg--)
276818334Speter	if (label_stack->reg[reg] != regstack->reg[reg])
276918334Speter	  break;
277018334Speter
277118334Speter      if (reg == -1)
277218334Speter	return;
277318334Speter    }
277418334Speter
277518334Speter  /* At least one insn will need to be inserted before label.  Insert
277618334Speter     a jump around the code we are about to emit.  Emit a label for the new
277718334Speter     code, and point the original insn at this new label. We can't use
277818334Speter     redirect_jump here, because we're using fld[4] of the code labels as
277950397Sobrien     LABEL_REF chains, no NUSES counters.  */
278018334Speter
278118334Speter  new_jump = emit_jump_insn_before (gen_jump (label), label);
278218334Speter  record_label_references (new_jump, PATTERN (new_jump));
278318334Speter  JUMP_LABEL (new_jump) = label;
278418334Speter
278518334Speter  new_barrier = emit_barrier_after (new_jump);
278618334Speter
278718334Speter  new_label = gen_label_rtx ();
278818334Speter  emit_label_after (new_label, new_barrier);
278918334Speter  LABEL_REFS (new_label) = new_label;
279018334Speter
279118334Speter  /* The old label_ref will no longer point to the code_label if now uses,
279250397Sobrien     so strip the label_ref from the code_label's chain of references.  */
279318334Speter
279418334Speter  for (ref = &LABEL_REFS (label); *ref != label; ref = &LABEL_NEXTREF (*ref))
279518334Speter    if (*ref == pat)
279618334Speter      break;
279718334Speter
279818334Speter  if (*ref == label)
279918334Speter    abort ();
280018334Speter
280118334Speter  *ref = LABEL_NEXTREF (*ref);
280218334Speter
280318334Speter  XEXP (pat, 0) = new_label;
280418334Speter  record_label_references (insn, PATTERN (insn));
280518334Speter
280618334Speter  if (JUMP_LABEL (insn) == label)
280718334Speter    JUMP_LABEL (insn) = new_label;
280818334Speter
280950397Sobrien  /* Now emit the needed code.  */
281018334Speter
281118334Speter  temp_stack = *regstack;
281218334Speter
281318334Speter  change_stack (new_label, &temp_stack, label_stack, emit_insn_after);
281418334Speter}
281518334Speter
281618334Speter/* Traverse all basic blocks in a function, converting the register
281718334Speter   references in each insn from the "flat" register file that gcc uses, to
281850397Sobrien   the stack-like registers the 387 uses.  */
281918334Speter
282018334Speterstatic void
282118334Speterconvert_regs ()
282218334Speter{
282318334Speter  register int block, reg;
282418334Speter  register rtx insn, next;
282518334Speter  struct stack_def regstack;
282618334Speter
282718334Speter  for (block = 0; block < blocks; block++)
282818334Speter    {
282918334Speter      if (block_stack_in[block].top == -2)
283018334Speter	{
283118334Speter	  /* This block has not been previously encountered.  Choose a
283218334Speter	     default mapping for any stack regs live on entry */
283318334Speter
283418334Speter	  block_stack_in[block].top = -1;
283518334Speter
283618334Speter	  for (reg = LAST_STACK_REG; reg >= FIRST_STACK_REG; reg--)
283718334Speter	    if (TEST_HARD_REG_BIT (block_stack_in[block].reg_set, reg))
283818334Speter	      block_stack_in[block].reg[++block_stack_in[block].top] = reg;
283918334Speter	}
284018334Speter
284118334Speter      /* Process all insns in this block.  Keep track of `next' here,
284218334Speter	 so that we don't process any insns emitted while making
284350397Sobrien	 substitutions in INSN.  */
284418334Speter
284518334Speter      next = block_begin[block];
284618334Speter      regstack = block_stack_in[block];
284718334Speter      do
284818334Speter	{
284918334Speter	  insn = next;
285018334Speter	  next = NEXT_INSN (insn);
285118334Speter
285218334Speter	  /* Don't bother processing unless there is a stack reg
285318334Speter	     mentioned or if it's a CALL_INSN (register passing of
285450397Sobrien	     floating point values).  */
285518334Speter
285652284Sobrien	  if (stack_regs_mentioned (insn) || GET_CODE (insn) == CALL_INSN)
285718334Speter	    subst_stack_regs (insn, &regstack);
285818334Speter
285918334Speter	} while (insn != block_end[block]);
286050397Sobrien
286150397Sobrien      /* For all further actions, INSN needs to be the last insn in
286250397Sobrien         this basic block.  If subst_stack_regs inserted additional
286350397Sobrien         instructions after INSN, it is no longer the last one at
286450397Sobrien         this point.  */
286550397Sobrien      next = PREV_INSN (next);
286618334Speter
286750397Sobrien      /* If subst_stack_regs inserted something after a JUMP_INSN, that
286850397Sobrien         is almost certainly a bug.  */
286950397Sobrien      if (GET_CODE (insn) == JUMP_INSN && insn != next)
287050397Sobrien	abort ();
287150397Sobrien      insn = next;
287218334Speter
287350397Sobrien      /* Something failed if the stack life doesn't match.  */
287450397Sobrien
287518334Speter      GO_IF_HARD_REG_EQUAL (regstack.reg_set, block_out_reg_set[block], win);
287618334Speter
287718334Speter      abort ();
287818334Speter
287918334Speter    win:
288018334Speter
288118334Speter      /* Adjust the stack of this block on exit to match the stack of
288218334Speter	 the target block, or copy stack information into stack of
288318334Speter	 jump target if the target block's stack order hasn't been set
288450397Sobrien	 yet.  */
288518334Speter
288618334Speter      if (GET_CODE (insn) == JUMP_INSN)
288718334Speter	goto_block_pat (insn, &regstack, PATTERN (insn));
288818334Speter
288950397Sobrien      /* Likewise handle the case where we fall into the next block.  */
289018334Speter
289118334Speter      if ((block < blocks - 1) && block_drops_in[block+1])
289218334Speter	change_stack (insn, &regstack, &block_stack_in[block+1],
289318334Speter		      emit_insn_after);
289418334Speter    }
289518334Speter
289618334Speter  /* If the last basic block is the end of a loop, and that loop has
289718334Speter     regs live at its start, then the last basic block will have regs live
289850397Sobrien     at its end that need to be popped before the function returns.  */
289918334Speter
290018334Speter   {
290118334Speter     int value_reg_low, value_reg_high;
290218334Speter     value_reg_low = value_reg_high = -1;
290318334Speter      {
290418334Speter        rtx retvalue;
290550397Sobrien        if ((retvalue = stack_result (current_function_decl)))
290618334Speter	 {
290718334Speter	   value_reg_low = REGNO (retvalue);
290818334Speter	   value_reg_high = value_reg_low +
290918334Speter	    HARD_REGNO_NREGS (value_reg_low, GET_MODE (retvalue)) - 1;
291018334Speter	 }
291118334Speter
291218334Speter      }
291318334Speter     for (reg = regstack.top; reg >= 0; reg--)
291450397Sobrien        if (regstack.reg[reg] < value_reg_low
291550397Sobrien	    || regstack.reg[reg] > value_reg_high)
291618334Speter           insn = emit_pop_insn (insn, &regstack,
291718334Speter			    FP_MODE_REG (regstack.reg[reg], DFmode),
291818334Speter			    emit_insn_after);
291918334Speter   }
292018334Speter  straighten_stack (insn, &regstack);
292118334Speter}
292218334Speter
292318334Speter/* Check expression PAT, which is in INSN, for label references.  if
292450397Sobrien   one is found, print the block number of destination to FILE.  */
292518334Speter
292618334Speterstatic void
292718334Speterprint_blocks (file, insn, pat)
292818334Speter     FILE *file;
292918334Speter     rtx insn, pat;
293018334Speter{
293118334Speter  register RTX_CODE code = GET_CODE (pat);
293218334Speter  register int i;
293318334Speter  register char *fmt;
293418334Speter
293518334Speter  if (code == LABEL_REF)
293618334Speter    {
293718334Speter      register rtx label = XEXP (pat, 0);
293818334Speter
293918334Speter      if (GET_CODE (label) != CODE_LABEL)
294018334Speter	abort ();
294118334Speter
294218334Speter      fprintf (file, " %d", BLOCK_NUM (label));
294318334Speter
294418334Speter      return;
294518334Speter    }
294618334Speter
294718334Speter  fmt = GET_RTX_FORMAT (code);
294818334Speter  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
294918334Speter    {
295018334Speter      if (fmt[i] == 'e')
295118334Speter	print_blocks (file, insn, XEXP (pat, i));
295218334Speter      if (fmt[i] == 'E')
295318334Speter	{
295418334Speter	  register int j;
295518334Speter	  for (j = 0; j < XVECLEN (pat, i); j++)
295618334Speter	    print_blocks (file, insn, XVECEXP (pat, i, j));
295718334Speter	}
295818334Speter    }
295918334Speter}
296018334Speter
296118334Speter/* Write information about stack registers and stack blocks into FILE.
296218334Speter   This is part of making a debugging dump.  */
296350397Sobrien
296418334Speterstatic void
296518334Speterdump_stack_info (file)
296618334Speter     FILE *file;
296718334Speter{
296818334Speter  register int block;
296918334Speter
297018334Speter  fprintf (file, "\n%d stack blocks.\n", blocks);
297118334Speter  for (block = 0; block < blocks; block++)
297218334Speter    {
297318334Speter      register rtx head, jump, end;
297418334Speter      register int regno;
297518334Speter
297618334Speter      fprintf (file, "\nStack block %d: first insn %d, last %d.\n",
297718334Speter	       block, INSN_UID (block_begin[block]),
297818334Speter	       INSN_UID (block_end[block]));
297918334Speter
298018334Speter      head = block_begin[block];
298118334Speter
298218334Speter      fprintf (file, "Reached from blocks: ");
298318334Speter      if (GET_CODE (head) == CODE_LABEL)
298418334Speter	for (jump = LABEL_REFS (head);
298518334Speter	     jump != head;
298618334Speter	     jump = LABEL_NEXTREF (jump))
298718334Speter	  {
298818334Speter	    register int from_block = BLOCK_NUM (CONTAINING_INSN (jump));
298918334Speter	    fprintf (file, " %d", from_block);
299018334Speter	  }
299118334Speter      if (block_drops_in[block])
299218334Speter	fprintf (file, " previous");
299318334Speter
299418334Speter      fprintf (file, "\nlive stack registers on block entry: ");
299518334Speter      for (regno = FIRST_STACK_REG; regno <= LAST_STACK_REG; regno++)
299618334Speter	{
299718334Speter	  if (TEST_HARD_REG_BIT (block_stack_in[block].reg_set, regno))
299818334Speter	    fprintf (file, "%d ", regno);
299918334Speter	}
300018334Speter
300118334Speter      fprintf (file, "\nlive stack registers on block exit: ");
300218334Speter      for (regno = FIRST_STACK_REG; regno <= LAST_STACK_REG; regno++)
300318334Speter	{
300418334Speter	  if (TEST_HARD_REG_BIT (block_out_reg_set[block], regno))
300518334Speter	    fprintf (file, "%d ", regno);
300618334Speter	}
300718334Speter
300818334Speter      end = block_end[block];
300918334Speter
301018334Speter      fprintf (file, "\nJumps to blocks: ");
301118334Speter      if (GET_CODE (end) == JUMP_INSN)
301218334Speter	print_blocks (file, end, PATTERN (end));
301318334Speter
301418334Speter      if (block + 1 < blocks && block_drops_in[block+1])
301518334Speter	fprintf (file, " next");
301618334Speter      else if (block + 1 == blocks
301718334Speter	       || (GET_CODE (end) == JUMP_INSN
301818334Speter		   && GET_CODE (PATTERN (end)) == RETURN))
301918334Speter	fprintf (file, " return");
302018334Speter
302118334Speter      fprintf (file, "\n");
302218334Speter    }
302318334Speter}
302418334Speter#endif /* STACK_REGS */
3025