home *** CD-ROM | disk | FTP | other *** search
/ Education Sampler 1992 [NeXTSTEP] / Education_1992_Sampler.iso / NeXT / GnuSource / cplusplus-8 / config / out-i386.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-01-07  |  34.6 KB  |  1,416 lines

  1. /* Subroutines for insn-output.c for Intel 80386.
  2.    Copyright (C) 1988 Free Software Foundation, Inc.
  3.  
  4. This file is part of GNU CC.
  5.  
  6. GNU CC is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GNU CC is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU CC; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #ifndef FILE
  21. #include <stdio.h>
  22. #endif
  23.  
  24. #define FP_TOP (gen_rtx(REG, DFmode, FIRST_FLOAT_REG))
  25.  
  26. #define AT_SP(mode) (gen_rtx (MEM, (mode), stack_pointer_rtx))
  27. #define AT_BP(mode) (gen_rtx (MEM, (mode), frame_pointer_rtx))
  28.  
  29. #define RET return ""
  30.  
  31. /* #define RETCOM(X) fprintf (asm_out_file, "%sX fp_pop_level=%d\n", \
  32.                COMMENT_BEGIN, fp_pop_level); RET */
  33. #define RETCOM(X) return ""
  34.  
  35. #define POP_ONE_FP    \
  36.   { /* fp_pop_level--; */    \
  37.     fprintf (asm_out_file, "\tfstp %sst (0)\n", RP); }
  38.  
  39. extern FILE *asm_out_file;
  40. static char *singlemove_string ();
  41. static void output_movf ();
  42. static void replace_float_constant ();
  43. static int mentions_fp_top ();
  44. static int call_top_dead_p ();
  45. static int fp_top_dead_p1 ();
  46. static rtx via_memory ();
  47. static void output_asm_insn_double_reg_op ();
  48.  
  49. /* All output functions must increment or decrement this to indicate
  50.    the net number of pops or pushes which they perform.  Note that it won't
  51.    necessarily balance with the optimize running, since we might have
  52.    two different calls with the same pop shared by cross jumping.
  53.    However on optimize the reg dead heuristic seems to work.  */
  54.  
  55. int fp_pop_level = 0;
  56.  
  57. static char *hi_reg_name[] = HI_REGISTER_NAMES;
  58. static char *qi_reg_name[] = QI_REGISTER_NAMES;
  59.  
  60. /* for fabs, fch, .. where the argument operand[1] must first be moved to
  61.   constraints  "=fm" "0" */
  62.  
  63. #define FP_CALL1(op)  \
  64.   { if (FP_REG_P (operands[0]))        \
  65.       return op;            \
  66.     output_movf (FP_TOP, operands[1]);    \
  67.     output_asm_insn (op, operands);    \
  68.     /* fp_pop_level--; */        \
  69.     return "fstp%z0 %0"; }
  70.  
  71. /* handle case of call where op0/op1 is "=mf" and opn is "mrf"
  72.    eg. fadd */
  73. #define FP_CALL(op, rev, n)  \
  74.   return fp_call_internal (op, rev, n, operands, insn);
  75.  
  76. static char *
  77. fp_call_internal (op, rev, n, operands, insn)
  78.      char *op;
  79.      char *rev;
  80.      int n;
  81.      rtx *operands;
  82.      rtx insn;
  83. {
  84.   if (!FP_REG_P (operands[0]))
  85.     {
  86.       /* Here destination is in memory
  87.      and source is in the fp stack.  */
  88.       output_movf (FP_TOP, operands[0]);
  89.       output_asm_insn_double_reg_op (op, rev, insn);
  90.       return "fstp%z0 %0";
  91.     }
  92.  
  93.   if (FP_REG_P (operands[n]))
  94.     {
  95.       rtx temp = operands[1];
  96.       char *tem1 = op;
  97.       operands[1] = operands[n];
  98.       op = rev;
  99.       operands[n] = temp;
  100.       rev = tem1;
  101.     }
  102.  
  103.   if (REG_P (operands[n]))
  104.     {
  105.       rtx xops[2];
  106.       via_memory (operands[n]);
  107.       operands[n] = AT_SP (GET_MODE (operands[n]));
  108.       xops[0] = stack_pointer_rtx;
  109.       xops[1] = gen_rtx (CONST_INT, VOIDmode,
  110.              GET_MODE_SIZE (GET_MODE (operands[n])));
  111.       output_asm_insn (op, operands + n);
  112.       output_asm_insn (AS2 (add%L0,%1,%0), xops);
  113.     }
  114.   else
  115.     output_asm_insn (op, operands + n);
  116.  
  117.   if (FP_REG_P (operands[0]))
  118.     {
  119.       /* It turns out not to work to use top_dead_p because
  120.      the death notes are not accurate enough.
  121.      But this ought to work, because the only thing that can
  122.      live across basic blocks is reg 8, and these insns
  123.      never involve reg 8 directly.  */
  124.       if (fp_top_dead_p1 (insn))
  125.     POP_ONE_FP;
  126.     }
  127.  
  128.   RET;
  129. }
  130.  
  131. /* Output assembler code to perform insn OP
  132.    with two stack operands, and output on the stack.
  133.  
  134.    REV is the assembler insn that does the same thing but
  135.    effectively interchanges the meanings of the two arguments.
  136.  
  137.    Somewhat counterintuitively, the "first" operand was pushed last.
  138.  
  139.    The output replaces either the top-of-stack or both of the arguments,
  140.    depending on whether the other argument is wanted after this insn.  */
  141.  
  142. static void
  143. output_asm_insn_double_reg_op (op, rev, insn)
  144.      char *op;
  145.      char *rev;
  146.      rtx insn;
  147. {
  148.   fputc ('\t', asm_out_file);
  149.   if (top_dead_p (insn))
  150.     {
  151.       /* Here we want the "reversed" insn, fsubr or fdivr.
  152.      But there is an assembler bug in all 80386 assemblers
  153.      which exchanges the meanings of fsubr and fsub, and of fdivr and fdiv!
  154.      So use the "unreversed" opcode (which will assemble into
  155.      the "reversed" insn).  */
  156.       rev = op;
  157.  
  158.       while (*rev && *rev != '%')
  159.     fputc (*rev++, asm_out_file);
  160.       /* fp_pop_level--; */
  161.  
  162.       fprintf (asm_out_file, AS2 (p,%sst,%sst(1)), RP, RP);
  163.     }
  164.   else
  165.     {
  166.       while (*op && *op != '%')
  167.     fputc (*op++, asm_out_file);
  168.       fprintf (asm_out_file,AS2 ( ,%sst(1),%sst), RP, RP);
  169.     }
  170.   putc ('\n', asm_out_file);
  171. }
  172.  
  173. /* Moves X to memory location 8 below stack pointer
  174.    and returns an RTX for that memory location.
  175.    X should be a register, in DFmode or SFmode.  */
  176.  
  177. static rtx
  178. via_memory (x)
  179.      rtx x;
  180. {
  181.   if (!REG_P (x))
  182.     abort ();
  183.   if (GET_MODE (x) == DFmode)
  184.     {
  185.       rtx xops[1];
  186.       xops[0] = gen_rtx (REG, SImode, REGNO (x) + 1);
  187.       output_asm_insn ("push%L0 %0", xops);
  188.     }
  189.   output_asm_insn ("push%L0 %0", &x);
  190. }
  191.  
  192. /* Output an insn to copy the SFmode value in fp0 to OPERAND
  193.    without clobbering fp0.  */
  194.  
  195. void
  196. fp_store_sf (target)
  197.      rtx target;
  198. {
  199.   if (REG_P (target))
  200.     {
  201.       rtx xoperands[3];
  202.       xoperands[0] = stack_pointer_rtx;
  203.       xoperands[1] = AT_SP (Pmode);
  204.       xoperands[2] = gen_rtx (CONST_INT, VOIDmode, -4);
  205.       output_asm_insn (AS2 (add%L0,%2,%0), xoperands);
  206.       output_asm_insn ("fst%S0 %1", xoperands);
  207.       output_asm_insn ("pop%L0 %0", &target);
  208.     }
  209.   else if (GET_CODE (target) == MEM)
  210.     output_asm_insn ("fst%S0 %0", &target);
  211. }
  212.  
  213. /* Output an insn to pop an SF value from fp0 into TARGET.
  214.    This destroys the value of fp0.  */
  215.  
  216. void
  217. fp_pop_sf (target)
  218.      rtx target;
  219. {
  220.   if (REG_P (target))
  221.     {
  222.       rtx xoperands[3];
  223.       xoperands[0] = stack_pointer_rtx;
  224.       xoperands[1] = AT_SP (Pmode);
  225.       xoperands[2] = gen_rtx (CONST_INT, VOIDmode, -4);
  226.       output_asm_insn (AS2 (add%L0,%2,%0), xoperands);
  227.       output_asm_insn ("fstp%S0 %1", xoperands);
  228.       output_asm_insn ("pop%L0 %0", &target);
  229.       /* fp_pop_level--; */
  230.     }
  231.   else if (GET_CODE (target) == MEM)
  232.     {
  233.       /* fp_pop_level--; */
  234.       output_asm_insn ("fstp%S0 %0", &target);
  235.     }
  236.   else abort ();
  237. }
  238.  
  239. /* Copy the top of the fpu stack into TARGET, without popping.  */
  240.  
  241. void
  242. fp_store_df (target)
  243.      rtx target;
  244. {
  245.   if (REG_P (target))
  246.     {
  247.       rtx xoperands[4];
  248.       xoperands[0] = stack_pointer_rtx;
  249.       xoperands[1] = gen_rtx (REG, SImode, REGNO (target) + 1);
  250.       xoperands[2] = AT_SP (Pmode);
  251.       xoperands[3] = gen_rtx (CONST_INT, VOIDmode, -8);
  252.       output_asm_insn (AS2 (add%L0,%3,%0), xoperands);
  253.       output_asm_insn ("fst%Q0 %2", xoperands);
  254.       output_asm_insn ("pop%L0 %0", &target);
  255.       output_asm_insn ("pop%L0 %1", xoperands);
  256.     }
  257.   else if (GET_CODE (target) == MEM)
  258.     output_asm_insn ("fst%Q0 %0", &target);
  259. }
  260.  
  261. /* Copy the top of the fpu stack into TARGET, with popping.  */
  262.  
  263. void
  264. fp_pop_df (target)
  265.      rtx target;
  266. {
  267.   if (REG_P (target))
  268.     {
  269.       rtx xoperands[4];
  270.       xoperands[0] = stack_pointer_rtx;
  271.       xoperands[1] = gen_rtx (REG, SImode, REGNO (target) + 1);
  272.       xoperands[2] = AT_SP (Pmode);
  273.       xoperands[3] = gen_rtx (CONST_INT, VOIDmode, -8);
  274.       output_asm_insn (AS2 (add%L0,%3,%0), xoperands);
  275.       /* fp_pop_level--; */
  276.       output_asm_insn ("fstp%Q0 %2", xoperands);
  277.       output_asm_insn ("pop%L0 %0", &target);
  278.       output_asm_insn ("pop%L0 %1", xoperands);
  279.     }
  280.   else if (GET_CODE (target) == MEM)
  281.     {
  282.       /* fp_pop_level--; */
  283.       output_asm_insn ("fstp%z0 %0", &target);
  284.     }
  285. }
  286.  
  287. #if 0
  288. /* Pop the fp stack, convert value to integer and store in TARGET.
  289.    TARGET may be memory or register, and may have QI, HI or SImode.  */
  290.  
  291. void
  292. fp_pop_int (target)
  293.      rtx target;
  294. {
  295.   if (REG_P (target) || GET_MODE (target) != SImode)
  296.     {
  297.       rtx xxops[2];
  298.       xxops[0] = stack_pointer_rtx;
  299.       xxops[1] = gen_rtx (CONST_INT, VOIDmode, 4);
  300.       output_asm_insn (AS2 (sub%L0,%1,%0), xxops);
  301.       xxops[0] = AT_SP (Pmode);
  302.       /* fp_pop_level--; */
  303.       output_asm_insn ("fistp%L0 %0", xxops);
  304.       output_asm_insn ("pop%L0 %0", &target);
  305.     }
  306.   else if (GET_CODE (target) == MEM)
  307.     {
  308.       /* fp_pop_level--; */
  309.       output_asm_insn ("fistp%L0 %0", &target);
  310.     }
  311.   else abort ();
  312. }
  313. #endif
  314.  
  315. /* Push the SFmode value X onto the fpu stack.  */
  316.  
  317. void
  318. fp_push_sf (x)
  319.      rtx x;
  320. {
  321.   /* fp_pop_level++; */
  322.   if (REG_P (x))
  323.     {
  324.       rtx xoperands[2];
  325.       rtx xfops[3];
  326.       output_asm_insn ("push%L0 %0", &x);
  327.       xfops[0] = AT_SP (Pmode);
  328.       xfops[2] = gen_rtx (CONST_INT, VOIDmode, 4);
  329.       xfops[1] = stack_pointer_rtx;
  330.       output_asm_insn ("fld%S0 %0 \n\tadd%L0 %2,%1", xfops);
  331.     }
  332.   else
  333.     output_asm_insn ("fld%S0 %0", &x);
  334. }
  335.  
  336. /* Push the DFmode value X onto the fpu stack.  */
  337.  
  338. void
  339. fp_push_df (x)
  340.      rtx x;
  341. {
  342.   /* fp_pop_level++; */
  343.  
  344.   if (REG_P (x))
  345.     {
  346.       rtx xoperands[2];
  347.       rtx xfops[3];
  348.       xoperands[0] = x;
  349.       xoperands[1] = gen_rtx (REG, SImode, REGNO (x) + 1);
  350.       output_asm_insn ("push%L0 %1", xoperands);
  351.       output_asm_insn ("push%L0 %0", xoperands);
  352.       xfops[0] = AT_SP (Pmode);
  353.       xfops[2] = gen_rtx (CONST_INT, VOIDmode, 8);
  354.       xfops[1] = stack_pointer_rtx;
  355.       output_asm_insn ("fld%Q0 %0 \n\tadd%L0 %2,%1", xfops);
  356.     }
  357.   else if (GET_CODE (x) == MEM)
  358.     output_asm_insn ("fld%Q0 %0", &x);
  359. }
  360.  
  361. static char *output_move_const_single ();
  362.  
  363. static char *
  364. singlemove_string (operands)
  365.      rtx *operands;
  366. {
  367.   rtx x;
  368.   if (GET_CODE (operands[0]) == MEM
  369.       && GET_CODE (x = XEXP (operands[0], 0)) == PRE_DEC)
  370.     {
  371.       if (XEXP (x, 0) != stack_pointer_rtx)
  372.     abort ();
  373.       return "push%L0 %1";
  374.     }
  375.   else if (GET_CODE (operands[1]) == CONST_DOUBLE)
  376.     {
  377.       return output_move_const_single (operands);
  378.     }
  379.   else if (GET_CODE (operands[0]) == REG || GET_CODE (operands[1]) == REG)
  380.     return AS2 (mov%L0,%1,%0);
  381.   else if (CONSTANT_P (operands[1]))
  382.     return AS2 (mov%L0,%1,%0);
  383.   else
  384.     {
  385.       output_asm_insn ("push%L0 %1", operands);
  386.       return "pop%L0 %0";
  387.     }
  388. }
  389.  
  390. /* Return a REG that occurs in ADDR with coefficient 1.
  391.    ADDR can be effectively incremented by incrementing REG.  */
  392.  
  393. static rtx
  394. find_addr_reg (addr)
  395.      rtx addr;
  396. {
  397.   while (GET_CODE (addr) == PLUS)
  398.     {
  399.       if (GET_CODE (XEXP (addr, 0)) == REG)
  400.     addr = XEXP (addr, 0);
  401.       else if (GET_CODE (XEXP (addr, 1)) == REG)
  402.     addr = XEXP (addr, 1);
  403.       else if (CONSTANT_P (XEXP (addr, 0)))
  404.     addr = XEXP (addr, 1);
  405.       else if (CONSTANT_P (XEXP (addr, 1)))
  406.     addr = XEXP (addr, 0);
  407.       else
  408.     abort ();
  409.     }
  410.   if (GET_CODE (addr) == REG)
  411.     return addr;
  412.   abort ();
  413. }
  414.  
  415. /* Output an insn to add the constant N to the register X.  */
  416.  
  417. static void
  418. asm_add (n, x)
  419.      int n;
  420.      rtx x;
  421. {
  422.   rtx xops[2];
  423.   xops[1] = x;
  424.   if (n < 0)
  425.     {
  426.       xops[0] = gen_rtx (CONST_INT, VOIDmode, -n);
  427.       output_asm_insn (AS2 (sub%L0,%0,%1), xops);
  428.     }
  429.   else if (n > 0)
  430.     {
  431.       xops[0] = gen_rtx (CONST_INT, VOIDmode, n);
  432.       output_asm_insn (AS2 (add%L0,%0,%1), xops);
  433.     }
  434. }
  435.  
  436. /* Output assembler code to perform a doubleword move insn
  437.    with operands OPERANDS.  */
  438.  
  439. char *
  440. output_move_double (operands)
  441.      rtx *operands;
  442. {
  443.   enum {REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
  444.   rtx latehalf[2];
  445.   rtx addreg0 = 0, addreg1 = 0;
  446.  
  447.   /* First classify both operands.  */
  448.  
  449.   if (REG_P (operands[0]))
  450.     optype0 = REGOP;
  451.   else if (offsettable_memref_p (operands[0]))
  452.     optype0 = OFFSOP;
  453.   else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
  454.     optype0 = POPOP;
  455.   else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
  456.     optype0 = PUSHOP;
  457.   else if (GET_CODE (operands[0]) == MEM)
  458.     optype0 = MEMOP;
  459.   else
  460.     optype0 = RNDOP;
  461.  
  462.   if (REG_P (operands[1]))
  463.     optype1 = REGOP;
  464.   else if (CONSTANT_P (operands[1])
  465.        || GET_CODE (operands[1]) == CONST_DOUBLE)
  466.     optype1 = CNSTOP;
  467.   else if (offsettable_memref_p (operands[1]))
  468.     optype1 = OFFSOP;
  469.   else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
  470.     optype1 = POPOP;
  471.   else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
  472.     optype1 = PUSHOP;
  473.   else if (GET_CODE (operands[1]) == MEM)
  474.     optype1 = MEMOP;
  475.   else
  476.     optype1 = RNDOP;
  477.  
  478.   /* Check for the cases that the operand constraints are not
  479.      supposed to allow to happen.  Abort if we get one,
  480.      because generating code for these cases is painful.  */
  481.  
  482.   if (optype0 == RNDOP || optype1 == RNDOP)
  483.     abort ();
  484.  
  485.   /* If one operand is decrementing and one is incrementing
  486.      decrement the former register explicitly
  487.      and change that operand into ordinary indexing.  */
  488.  
  489.   if (optype0 == PUSHOP && optype1 == POPOP)
  490.     {
  491.       operands[0] = XEXP (XEXP (operands[0], 0), 0);
  492.       asm_add (-8, operands[0]);
  493.       operands[0] = gen_rtx (MEM, DImode, operands[0]);
  494.       optype0 = OFFSOP;
  495.     }
  496.   if (optype0 == POPOP && optype1 == PUSHOP)
  497.     {
  498.       operands[1] = XEXP (XEXP (operands[1], 0), 0);
  499.       asm_add (-8, operands[1]);
  500.       operands[1] = gen_rtx (MEM, DImode, operands[1]);
  501.       optype1 = OFFSOP;
  502.     }
  503.  
  504.   /* If an operand is an unoffsettable memory ref, find a register
  505.      we can increment temporarily to make it refer to the second word.  */
  506.  
  507.   if (optype0 == MEMOP)
  508.     addreg0 = find_addr_reg (XEXP (operands[0], 0));
  509.  
  510.   if (optype1 == MEMOP)
  511.     addreg1 = find_addr_reg (XEXP (operands[1], 0));
  512.  
  513.   /* Ok, we can do one word at a time.
  514.      Normally we do the low-numbered word first,
  515.      but if either operand is autodecrementing then we
  516.      do the high-numbered word first.
  517.  
  518.      In either case, set up in LATEHALF the operands to use
  519.      for the high-numbered word and in some cases alter the
  520.      operands in OPERANDS to be suitable for the low-numbered word.  */
  521.  
  522.   if (optype0 == REGOP)
  523.     latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
  524.   else if (optype0 == OFFSOP)
  525.     latehalf[0] = adj_offsettable_operand (operands[0], 4);
  526.   else
  527.     latehalf[0] = operands[0];
  528.  
  529.   if (optype1 == REGOP)
  530.     latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
  531.   else if (optype1 == OFFSOP)
  532.     latehalf[1] = adj_offsettable_operand (operands[1], 4);
  533.   else if (optype1 == CNSTOP)
  534.     {
  535.       if (CONSTANT_P (operands[1]))
  536.     latehalf[1] = const0_rtx;
  537.       else if (GET_CODE (operands[1]) == CONST_DOUBLE)
  538.     {
  539.       latehalf[1] = gen_rtx (CONST_INT, VOIDmode,
  540.                  CONST_DOUBLE_HIGH (operands[1]));
  541.       operands[1] = gen_rtx (CONST_INT, VOIDmode,
  542.                  CONST_DOUBLE_LOW (operands[1]));
  543.     }
  544.     }
  545.   else
  546.     latehalf[1] = operands[1];
  547.  
  548.   /* If insn is effectively movd N (sp),-(sp) then we will do the
  549.      high word first.  We should use the adjusted operand 1 (which is N+4 (sp))
  550.      for the low word as well, to compensate for the first decrement of sp.  */
  551.   if (optype0 == PUSHOP
  552.       && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
  553.       && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
  554.     operands[1] = latehalf[1];
  555.  
  556.   /* If one or both operands autodecrementing,
  557.      do the two words, high-numbered first.  */
  558.  
  559.   /* Likewise,  the first move would clobber the source of the second one,
  560.      do them in the other order.  This happens only for registers;
  561.      such overlap can't happen in memory unless the user explicitly
  562.      sets it up, and that is an undefined circumstance.  */
  563.  
  564.   if (optype0 == PUSHOP || optype1 == PUSHOP
  565.       || (optype0 == REGOP && optype1 == REGOP
  566.       && REGNO (operands[0]) == REGNO (latehalf[1])))
  567.     {
  568.       /* Make any unoffsettable addresses point at high-numbered word.  */
  569.       if (addreg0)
  570.     asm_add (4, addreg0);
  571.       if (addreg1)
  572.     asm_add (4, addreg1);
  573.  
  574.       /* Do that word.  */
  575.       output_asm_insn (singlemove_string (latehalf), latehalf);
  576.  
  577.       /* Undo the adds we just did.  */
  578.       if (addreg0)
  579.          asm_add (-4, addreg0);
  580.       if (addreg1)
  581.     asm_add (-4, addreg1);
  582.  
  583.       /* Do low-numbered word.  */
  584.       return singlemove_string (operands);
  585.     }
  586.  
  587.   /* Normal case: do the two words, low-numbered first.  */
  588.  
  589.   output_asm_insn (singlemove_string (operands), operands);
  590.  
  591.   /* Make any unoffsettable addresses point at high-numbered word.  */
  592.   if (addreg0)
  593.     asm_add (4, addreg0);
  594.   if (addreg1)
  595.     asm_add (4, addreg1);
  596.  
  597.   /* Do that word.  */
  598.   output_asm_insn (singlemove_string (latehalf), latehalf);
  599.  
  600.   /* Undo the adds we just did.  */
  601.   if (addreg0)
  602.     asm_add (-4, addreg0);
  603.   if (addreg1)
  604.     asm_add (-4, addreg1);
  605.  
  606.   return "";
  607. }
  608.  
  609. int
  610. standard_80387_constant_p (x)
  611.      rtx x;
  612. {
  613.   union { double d; int i[2];} u;
  614.   register double d;
  615.   u.i[0] = XINT (x, 0);
  616.   u.i[1] = XINT (x, 1);
  617.   d = u.d;
  618.  
  619.   if (d == 0)
  620.     return 1;
  621.   if (d == 1)
  622.     return 2;
  623.   /* Note that on the 80387, other constants, such as pi,
  624.      are much slower to load as standard constants
  625.      than to load from doubles in memory!  */
  626.  
  627.   return 0;
  628. }
  629.  
  630. static char *
  631. output_move_const_double (operands)
  632.      rtx *operands;
  633. {
  634.   if (FP_REG_P (operands[0]))
  635.     {
  636.       int conval = standard_80387_constant_p (operands[1]);
  637.  
  638.       /* fp_pop_level++; */
  639.       if (conval == 1)
  640.     return "fldz";
  641.       if (conval == 2)
  642.     return "fld1";
  643.       /* fp_pop_level--; */
  644.     }
  645.  
  646.   output_move_double (operands);
  647. }
  648.  
  649.  
  650. static char *
  651. output_move_const_single (operands)
  652.      rtx *operands;
  653. {
  654.   if (FP_REG_P (operands[0]))
  655.     {
  656.       int conval = standard_80387_constant_p (operands[1]);
  657.  
  658.       /* fp_pop_level++; */
  659.       if (conval == 1)
  660.     return "fldz";
  661.       if (conval == 2)
  662.     return "fld1";
  663.       /* fp_pop_level--; */
  664.     }
  665.   if (GET_CODE (operands[1]) == CONST_DOUBLE)
  666.     {
  667.       union { int i[2]; double d;} u1;
  668.       union { int i; float f;} u2;
  669.       u1.i[0] = CONST_DOUBLE_LOW (operands[1]);
  670.       u1.i[1] = CONST_DOUBLE_HIGH (operands[1]);
  671.       u2.f = u1.d;
  672.       operands[1] = gen_rtx (CONST_INT, VOIDmode, u2.i);
  673.     }
  674.   return singlemove_string (operands);
  675. }
  676.  
  677. /* Output an insn to move an SF value from FROM to TO.
  678.    The kinds of operands are not restricted
  679.    except that they may not both be in memory.  */
  680.  
  681. void
  682. output_movsf (to, from)
  683.      rtx from, to;
  684. {
  685.   rtx xops[2];
  686.   xops[0] = to;
  687.   xops[1] = from;
  688.   if (FP_REG_P (from) || FP_REG_P (to))
  689.     {
  690.       from = xops[1];
  691.     }
  692.  
  693.   if (FP_REG_P (from))
  694.     {
  695. #if 0
  696.     {
  697.       if (REGNO (from) != REGNO (to))
  698.         {
  699.           output_asm_insn ("fld%S0 %1 \n\tfstp%S0 %0", xops);
  700.         }
  701.     }
  702.       else
  703. #endif
  704.  
  705.       if (! FP_REG_P (to))
  706.     fp_pop_sf (to);
  707.     }
  708.   else if (FP_REG_P (to))
  709.     fp_push_sf (from);
  710.   else
  711.     output_asm_insn (singlemove_string (xops), xops);
  712. }
  713.  
  714. /* Output an insn to move a DF value from FROM to TO.
  715.    The kinds of operands are not restricted
  716.    except that they may not both be in memory.  */
  717.  
  718. void
  719. output_movdf (to, from)
  720.      rtx from, to;
  721. {
  722.   rtx xops[2];
  723.   xops[0] = to;
  724.   xops[1] = from;
  725.   if (FP_REG_P (from) || FP_REG_P (to))
  726.     {
  727.       from = xops[1];
  728.       to = xops[0];
  729.     }
  730.   if (FP_REG_P (from))
  731.     {
  732. #if 0
  733.     {
  734.       if (REGNO (from) != REGNO (to))
  735.         abort ();
  736. /*        output_asm_insn ("fld%Q0 %1 \n\t fstp%Q0 %0", xops);*/
  737.     }
  738.       else
  739.     {
  740. #endif
  741.       if (! FP_REG_P (to))
  742.     fp_pop_df (to);
  743.     }
  744.   else if (FP_REG_P (to))
  745.     fp_push_df (from);
  746.   else
  747.     output_asm_insn (output_move_double (xops), xops);
  748. }
  749.  
  750. /* does move of FROM to TO where the mode is the minimum of the
  751. two */
  752.  
  753. static void
  754. output_movf (to, from)
  755.      rtx to, from;
  756. {
  757.   if (GET_MODE (from) == SFmode || GET_MODE (to) == SFmode)
  758.     output_movsf (to, from);
  759.   else
  760.     output_movdf (to, from);
  761. }
  762.  
  763. /* Return the best assembler insn template
  764.    for moving operands[1] into operands[0] as a fullword.  */
  765.  
  766. void
  767. function_prologue (file, size)
  768.      FILE *file;
  769.      int size;
  770. {
  771.   register int regno;
  772.   int nregs, limit;
  773.   rtx xops[4];
  774.   extern int frame_pointer_needed;
  775.  
  776.   /* fp_pop_level = 0; */
  777.   xops[0] = stack_pointer_rtx;
  778.   xops[1] = frame_pointer_rtx;
  779.   xops[2] = gen_rtx (CONST_INT, VOIDmode, size);
  780.   if (frame_pointer_needed)
  781.     {
  782.       output_asm_insn ("push%L0 %1", xops);
  783.       output_asm_insn (AS2 (mov%L0,%0,%1), xops);
  784.       if (size)
  785.     output_asm_insn (AS2 (sub%L0,%2,%0), xops);
  786.     }
  787.  
  788.   /* Note If use enter it is NOT reversed args.
  789.      This one is not reversed from intel!!
  790.      I think enter is slower.  Also sdb doesn't like it.
  791.      But if you want it the code is:
  792.      {
  793.      xops[3] = const0_rtx;
  794.      output_asm_insn ("enter %2,%3", xops);
  795.      }
  796.      */
  797.   nregs = 0;
  798.   limit = (frame_pointer_needed ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
  799.   for (regno = limit - 1; regno >= 0; regno--)
  800.     if (regs_ever_live[regno] && ! call_used_regs[regno])
  801.       {
  802.     fprintf (file, "\tpush%s %se%s\n", L_SIZE, RP, hi_reg_name[regno]);
  803.       }
  804. }
  805.  
  806. void
  807. function_epilogue (file, size)
  808.      FILE *file;
  809.      int size;
  810. {
  811.   register int regno;
  812.   register int nregs, limit;
  813.   int assure_sp_pos;
  814.   int return_struct_adjust;
  815.   extern int frame_pointer_needed;
  816.   extern int current_function_pops_args;
  817.   extern int current_function_args_size;
  818.   extern int flag_pcc_struct_return;
  819.  
  820.   limit = (frame_pointer_needed ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
  821.   nregs = 0;
  822.  
  823.   return_struct_adjust =
  824.     (current_function_returns_struct
  825. #ifdef STRUCT_RETURN_CALLER_POP
  826.      && !flag_pcc_struct_return
  827. #endif
  828.      ? 4 : 0);
  829.  
  830.   for (regno = (limit -1); regno >= 0; regno--)
  831.     if (regs_ever_live[regno] && ! call_used_regs[regno])
  832.       nregs++;
  833.  
  834.   /* sp is often  unreliable so we must go off the frame pointer,
  835.    */
  836.  
  837.   if (nregs && frame_pointer_needed)
  838.     {
  839.       rtx xops[2];
  840.       xops[0] = adj_offsettable_operand (AT_BP (Pmode),
  841.                      -size -(nregs*(UNITS_PER_WORD)));
  842.       xops[1] = stack_pointer_rtx;
  843.       output_asm_insn (AS2 (lea%L0,%0,%1), xops);
  844.     }
  845.   for (regno = 0; regno < limit; regno++)
  846.     {
  847.       if (regs_ever_live[regno] && ! call_used_regs[regno])
  848.     {
  849.       fprintf (file, "\tpop%s ", L_SIZE);
  850.       fprintf (file, "%se%s\n", RP, hi_reg_name[regno]);
  851.     }
  852.     }
  853.  
  854.   if (frame_pointer_needed)
  855.     fprintf (file, "\tleave\n");
  856.   if (current_function_pops_args && current_function_args_size)
  857.     fprintf (file, "\tret %s%d\n", IP,
  858.          (current_function_args_size + return_struct_adjust));
  859.   else if (return_struct_adjust)
  860.     fprintf (file, "\tret %s%d\n", IP, return_struct_adjust);
  861.   else
  862.     fprintf (file, "\tret\n");
  863. }
  864.  
  865. int
  866. hard_regno_mode_ok (regno, mode)
  867.      int regno;
  868.      enum machine_mode mode;
  869. {
  870.   return
  871.     (regno < 2 ? 1
  872.      /* Used to reject floating modes here */
  873.      : regno < 4 ? 1
  874.      : regno >= 8 ? mode == DFmode || mode == SFmode
  875.      : mode != QImode);
  876. }
  877.  
  878. /* Print the name of a register based on its machine mode and number.
  879.    If CODE is 'w', pretend the mode is HImode.
  880.    If CODE is 'b', pretend the mode is QImode.
  881.    If CODE is 'k', pretend the mode is SImode.  */
  882.  
  883. #define PRINT_REG(X, CODE, FILE) \
  884.   do { fprintf (FILE, "%s", RP);            \
  885.        switch ((CODE == 'w' ? 2             \
  886.         : CODE == 'b' ? 1            \
  887.         : CODE == 'k' ? 4            \
  888.         : GET_MODE_SIZE (GET_MODE (X))))    \
  889.      {                        \
  890.      case 4:                    \
  891.      case 8:                    \
  892.        if (!FP_REG_P (X)) fputs ("e", FILE);    \
  893.      case 2:                    \
  894.        fputs (hi_reg_name[REGNO (X)], FILE);    \
  895.        break;                    \
  896.      case 1:                    \
  897.        fputs (qi_reg_name[REGNO (X)], FILE);    \
  898.        break;                    \
  899.      }                        \
  900.      } while (0)
  901.  
  902. /* Meaning of CODE:
  903.    f -- float insn (print a CONST_DOUBLE as a float rather than in hex).
  904.    L,W,B,Q,S -- print the opcode suffix for specified size of operand.
  905.    R -- print the prefix for register names.
  906.    z -- print the opcode suffix for the size of the current operand.
  907.    * -- print a star (in certain assembler syntax)
  908.    w -- print the operand as if it's a "word" (HImode) even if it isn't.
  909.    c -- don't print special prefixes before constant operands.
  910. */
  911.  
  912. void
  913. print_operand (file, x, code)
  914.      FILE *file;
  915.      rtx x;
  916.      int code;
  917. {
  918.   if (code)
  919.     {
  920.       switch (code)
  921.     {
  922.     case '*':
  923.       if (USE_STAR)
  924.         putc ('*', file);
  925.       return;
  926.  
  927.     case 'L':
  928.       PUT_OP_SIZE (code, 'l', file);
  929.       return;
  930.  
  931.     case 'W':
  932.       PUT_OP_SIZE (code, 'w', file);
  933.       return;
  934.  
  935.     case 'B':
  936.       PUT_OP_SIZE (code, 'b', file);
  937.       return;
  938.  
  939.     case 'Q':
  940.       PUT_OP_SIZE (code, 'l', file);
  941.       return;
  942.  
  943.     case 'S':
  944.       PUT_OP_SIZE (code, 's', file);
  945.       return;
  946.  
  947.     case 'R':
  948.       fprintf (file, "%s", RP);
  949.       return;
  950.  
  951.     case 'z':
  952.       /* this is the size of op from size of operand */
  953.       switch (GET_MODE_SIZE (GET_MODE (x)))
  954.         {
  955.         case 2:
  956.           PUT_OP_SIZE ('W', 'w', file);
  957.           return;
  958.         case 4:
  959.           if (GET_MODE (x) == SFmode)
  960.         {
  961.           PUT_OP_SIZE ('S', 's', file);
  962.           return;
  963.         }
  964.           else
  965.         PUT_OP_SIZE ('L', 'l', file);
  966.           return;
  967.         case 8:
  968.           if (!FP_REG_P (x)) PUT_OP_SIZE ('Q', 'l', file);
  969.           return;
  970.         case 1:
  971.           PUT_OP_SIZE ('B', 'b', file);
  972.           return;
  973.         }
  974.     }
  975.     }
  976.   if (GET_CODE (x) == REG)
  977.     {
  978.       PRINT_REG (x, code, file);
  979.     }
  980.   else if (GET_CODE (x) == MEM)
  981.     {
  982.       PRINT_PTR (x, file);
  983.       if (CONSTANT_ADDRESS_P (XEXP (x, 0)))
  984.     output_addr_const (file, XEXP (x, 0));
  985.       else
  986.     output_address (XEXP (x, 0));
  987.     }
  988.   else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode)
  989.     {
  990.       union { double d; int i[2]; } u;
  991.       union { float f; int i; } u1;
  992.       u.i[0] = CONST_DOUBLE_LOW (x);
  993.       u.i[1] = CONST_DOUBLE_HIGH (x);
  994.       u1.f = u.d;
  995.       if (code == 'f')
  996.         fprintf (file, "%.22e", u1.f);
  997.       else
  998.         {
  999.       PRINT_IMMED_PREFIX (file);
  1000.       fprintf (file, "0x%x", u1.i);
  1001.     }
  1002.     }
  1003.   else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode)
  1004.     {
  1005.       union { double d; int i[2]; } u;
  1006.       u.i[0] = CONST_DOUBLE_LOW (x);
  1007.       u.i[1] = CONST_DOUBLE_HIGH (x);
  1008.       fprintf (file, "%.22e", u.d);
  1009.     }
  1010.   else 
  1011.     {
  1012.       if (code != 'c')
  1013.     {
  1014.       if (GET_CODE (x) == CONST_INT)
  1015.         PRINT_IMMED_PREFIX (file);
  1016.       else if (GET_CODE (x) == CONST || GET_CODE (x) == SYMBOL_REF)
  1017.         PRINT_OFFSET_PREFIX (file);
  1018.     }
  1019.       output_addr_const (file, x);
  1020.     }
  1021. }
  1022.  
  1023. /* Print a memory operand whose address is ADDR.  */
  1024.  
  1025. void
  1026. print_operand_address (file, addr)
  1027.      FILE *file;
  1028.      register rtx addr;
  1029. {
  1030.   register rtx reg1, reg2, breg, ireg;
  1031.   rtx offset;
  1032.  
  1033.   switch (GET_CODE (addr))
  1034.     {
  1035.     case REG:
  1036.       ADDR_BEG (file);
  1037.       fprintf (file, "%se", RP);
  1038.       fputs (hi_reg_name[REGNO (addr)], file);
  1039.       ADDR_END (file);
  1040.       break;
  1041.  
  1042.     case PLUS:
  1043.       reg1 = 0;
  1044.       reg2 = 0;
  1045.       ireg = 0;
  1046.       breg = 0;
  1047.       offset = 0;
  1048.       if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
  1049.     {
  1050.       offset = XEXP (addr, 0);
  1051.       addr = XEXP (addr, 1);
  1052.     }
  1053.       else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
  1054.     {
  1055.       offset = XEXP (addr, 1);
  1056.       addr = XEXP (addr, 0);
  1057.     }
  1058.       if (GET_CODE (addr) != PLUS) ;
  1059.       else if (GET_CODE (XEXP (addr, 0)) == MULT)
  1060.     {
  1061.       reg1 = XEXP (addr, 0);
  1062.       addr = XEXP (addr, 1);
  1063.     }
  1064.       else if (GET_CODE (XEXP (addr, 1)) == MULT)
  1065.     {
  1066.       reg1 = XEXP (addr, 1);
  1067.       addr = XEXP (addr, 0);
  1068.     }
  1069.       else if (GET_CODE (XEXP (addr, 0)) == REG)
  1070.     {
  1071.       reg1 = XEXP (addr, 0);
  1072.       addr = XEXP (addr, 1);
  1073.     }
  1074.       else if (GET_CODE (XEXP (addr, 1)) == REG)
  1075.     {
  1076.       reg1 = XEXP (addr, 1);
  1077.       addr = XEXP (addr, 0);
  1078.     }
  1079.       if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
  1080.     {
  1081.       if (reg1 == 0) reg1 = addr;
  1082.       else reg2 = addr;
  1083.       addr = 0;
  1084.     }
  1085.       if (offset != 0)
  1086.     {
  1087.       if (addr != 0) abort ();
  1088.       addr = offset;
  1089.     }
  1090.       if ((reg1 && GET_CODE (reg1) == MULT)
  1091.       || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
  1092.     {
  1093.       breg = reg2;
  1094.       ireg = reg1;
  1095.     }
  1096.       else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
  1097.     {
  1098.       breg = reg1;
  1099.       ireg = reg2;
  1100.     }
  1101.  
  1102.       if (ireg != 0 || breg != 0)
  1103.     {
  1104.       int scale = 1;
  1105.  
  1106.       if (addr != 0)
  1107.         {
  1108.           if (GET_CODE (addr) == LABEL_REF)
  1109.         output_asm_label (addr);
  1110.           else
  1111.         output_addr_const (file, addr);
  1112.         }
  1113.  
  1114.         if (ireg != 0 && GET_CODE (ireg) == MULT)
  1115.         {
  1116.           scale = INTVAL (XEXP (ireg, 1));
  1117.           ireg = XEXP (ireg, 0);
  1118.         }
  1119.       /* output breg+ireg*scale */
  1120.       PRINT_B_I_S (breg, ireg, scale, file);
  1121.       break;
  1122.     }
  1123.  
  1124.     case MULT:
  1125.       {
  1126.     int scale;
  1127.     if (GET_CODE (XEXP (addr, 0)) == CONST_INT)
  1128.       {
  1129.         scale = INTVAL (XEXP (addr, 0));
  1130.         ireg = XEXP (addr, 1);
  1131.       }
  1132.     else
  1133.       {
  1134.         scale = INTVAL (XEXP (addr, 1));
  1135.         ireg = XEXP (addr, 0);
  1136.       }
  1137.     output_addr_const (file, const0_rtx);
  1138.     PRINT_B_I_S ((rtx) 0, ireg, scale, file);
  1139.       }
  1140.       break;
  1141.  
  1142.     default:
  1143.       if (GET_CODE (addr) == CONST_INT
  1144.       && INTVAL (addr) < 0x8000
  1145.       && INTVAL (addr) >= -0x8000)
  1146.     fprintf (file, "%d", INTVAL (addr));
  1147.       else
  1148.     output_addr_const (file, addr);
  1149.     }
  1150. }
  1151.  
  1152. /* Set the cc_status for the results of an insn whose pattern is EXP.
  1153.    On the 80386, we assume that only test and compare insns, as well
  1154.    as SI, HI, & DI mode ADD, SUB, NEG, AND, IOR, XOR, ASHIFT, LSHIFT,
  1155.    ASHIFTRT, and LSHIFTRT instructions set the condition codes usefully.
  1156.    Also, we assume that jumps and moves don't affect the condition codes.
  1157.    All else, clobbers the condition codes, by assumption.
  1158.  
  1159.    We assume that ALL add, minus, etc. instructions effect the condition
  1160.    codes.  This MUST be consistent with i386.md.  */
  1161.  
  1162. notice_update_cc (exp)
  1163.      rtx exp;
  1164. {
  1165.   if (GET_CODE (exp) == SET)
  1166.     {
  1167.       /* Jumps do not alter the cc's.  */
  1168.       if (SET_DEST (exp) == pc_rtx)
  1169.     return;
  1170.       /* Moving register or memory into a register:
  1171.      it doesn't alter the cc's, but it might invalidate
  1172.      the RTX's which we remember the cc's came from.
  1173.      (Note that moving a constant 0 or 1 MAY set the cc's).  */
  1174.       if (REG_P (SET_DEST (exp))
  1175.       && (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM))
  1176.     {
  1177.       if (cc_status.value1
  1178.           && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1))
  1179.         cc_status.value1 = 0;
  1180.       if (cc_status.value2
  1181.           && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2))
  1182.         cc_status.value2 = 0;
  1183.       return;
  1184.     }
  1185.       /* Moving register into memory doesn't alter the cc's.
  1186.      It may invalidate the RTX's which we remember the cc's came from.  */
  1187.       if (GET_CODE (SET_DEST (exp)) == MEM && REG_P (SET_SRC (exp)))
  1188.     {
  1189.       if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM)
  1190.         cc_status.value1 = 0;
  1191.       if (cc_status.value2 && GET_CODE (cc_status.value2) == MEM)
  1192.         cc_status.value2 = 0;
  1193.       return;
  1194.     }
  1195.       /* Function calls clobber the cc's.  */
  1196.       else if (GET_CODE (SET_SRC (exp)) == CALL)
  1197.     {
  1198.       CC_STATUS_INIT;
  1199.       return;
  1200.     }
  1201.       /* Tests and compares set the cc's in predictable ways.  */
  1202.       else if (SET_DEST (exp) == cc0_rtx)
  1203.     {
  1204.       CC_STATUS_INIT;
  1205.       cc_status.value1 = SET_SRC (exp);
  1206.       return;
  1207.     }
  1208.       /* Certain instructions effect the condition codes. */
  1209.       else if (GET_MODE (SET_SRC (exp)) == SImode
  1210.            || GET_MODE (SET_SRC (exp)) == HImode
  1211.            || GET_MODE (SET_SRC (exp)) == QImode)
  1212.     switch (GET_CODE (SET_SRC (exp)))
  1213.       {
  1214.       case ASHIFTRT: case LSHIFTRT:
  1215.       case ASHIFT: case LSHIFT:
  1216.         /* Shifts on the 386 don't set the condition codes if the
  1217.            shift count is zero. */
  1218.         if (GET_CODE (XEXP (SET_SRC (exp), 1)) != CONST_INT)
  1219.           {
  1220.         CC_STATUS_INIT;
  1221.         break;
  1222.           }
  1223.         /* We assume that the CONST_INT is non-zero (this rtx would
  1224.            have been deleted if it were zero. */
  1225.  
  1226.       case PLUS: case MINUS: case NEG:
  1227.       case AND: case IOR: case XOR:
  1228.         cc_status.flags = CC_NO_OVERFLOW;
  1229.         cc_status.value1 = SET_SRC (exp);
  1230.         cc_status.value2 = SET_DEST (exp);
  1231.         break;
  1232.  
  1233.       default:
  1234.         CC_STATUS_INIT;
  1235.       }
  1236.       else
  1237.     {
  1238.       CC_STATUS_INIT;
  1239.     }
  1240.     }
  1241.   else if (GET_CODE (exp) == PARALLEL
  1242.        && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
  1243.     {
  1244.       if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx)
  1245.     return;
  1246.       if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx)
  1247.     {
  1248.       CC_STATUS_INIT;
  1249.       cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0));
  1250.       return;
  1251.     }
  1252.       CC_STATUS_INIT;
  1253.     }
  1254.   else
  1255.     {
  1256.       CC_STATUS_INIT;
  1257.     }
  1258. }
  1259.  
  1260. /* Nonzero if the top of the fpu stack dies in this insn.  */
  1261.  
  1262. int
  1263. top_dead_p (insn)
  1264.      rtx insn;
  1265. {
  1266.   extern int optimize;
  1267.   if (optimize)
  1268.     return (find_regno_note (insn, REG_DEAD, FIRST_FLOAT_REG)
  1269.         || find_regno_note (insn, REG_DEAD, FIRST_FLOAT_REG + 1));
  1270.  
  1271.   if (GET_CODE (insn) == CALL_INSN)
  1272.     return call_top_dead_p (insn);
  1273.  
  1274.   return fp_top_dead_p1 (insn);
  1275. }
  1276.  
  1277. /* Following is used after a call_value insn
  1278.    if obey_regdecls there will not be the REG_DEAD notes
  1279.    to go by (there won't be any cross jumping to worry about
  1280.    either), and we depend on seeing if the FP_TOP is used
  1281.    in the next two insn's.  Otherwise we depend on the
  1282.    REG_DEAD notes.
  1283.    */
  1284.  
  1285. static int
  1286. call_top_dead_p (insn)
  1287.      rtx insn;
  1288. {
  1289.   int i;
  1290.   for (i = 0; i < 3; i++)
  1291.     {
  1292.       insn = NEXT_INSN (insn);
  1293.       if (insn == 0)
  1294.     return 1;
  1295.       if (GET_CODE (insn) == NOTE || GET_CODE (insn) == CODE_LABEL)
  1296.     continue;
  1297.       if (GET_CODE (insn) == BARRIER)
  1298.     abort ();
  1299.       if (GET_CODE (PATTERN (insn)) == SET
  1300.       && SET_DEST (PATTERN (insn)) != stack_pointer_rtx)
  1301.     return (!(mentions_fp_top (SET_SRC (PATTERN (insn)))));
  1302.       if (GET_CODE (PATTERN (insn)) == CALL)
  1303.     return 1;
  1304.       if (GET_CODE (PATTERN (insn)) == USE)
  1305.     return (! FP_REG_P (XEXP (PATTERN (insn), 0)));
  1306.     }
  1307.   return 1;
  1308. }
  1309.  
  1310. /* Return 1 if current val of fpu top-of-stack appears unused
  1311.    in rest of this basic block.  */
  1312.  
  1313. static int
  1314. fp_top_dead_p1 (insn)
  1315.      rtx insn;
  1316. {
  1317.   extern int optimize;
  1318.  
  1319.   int past_label = 0;
  1320.  
  1321.   for (insn = NEXT_INSN (insn); insn; insn = NEXT_INSN (insn))
  1322.     {
  1323.       switch (GET_CODE (insn))
  1324.     {
  1325.     case CALL_INSN:
  1326.       /* Function calls clobber this value, so it's dead.  */
  1327.       return 1;
  1328.  
  1329.     case JUMP_INSN:
  1330.       if (! optimize)
  1331.         /* Can't use JUMP_LABEL, but there's no cross-jumping either.  */
  1332.         return 1;
  1333.       if (JUMP_LABEL (insn) == 0)
  1334.         return 1;
  1335.       insn = JUMP_LABEL (insn);
  1336.     case CODE_LABEL:
  1337.       /* Go past one label or follow one jump in case of cross-jumping,
  1338.          which could insert such a label or jump into one basic block.  */
  1339.       if (! optimize)
  1340.         return 1;
  1341.       if (past_label)
  1342.         return 1;
  1343.       past_label = 1;
  1344.       break;
  1345.  
  1346.     case INSN:
  1347.       if (GET_CODE (PATTERN (insn)) == SET)
  1348.         {
  1349.           if ((mentions_fp_top (SET_SRC (PATTERN (insn)))))
  1350.         return 0;
  1351.           else if (FP_REG_P (SET_DEST (PATTERN (insn))))
  1352.         return 1;
  1353.         }
  1354.       else if (mentions_fp_top (PATTERN (insn)))
  1355.         return 0;
  1356.       break;
  1357.     }
  1358.     }
  1359.   return 1;
  1360. }
  1361.  
  1362. /* Return 1 if X involves an FPU register.  */
  1363.  
  1364. static int
  1365. mentions_fp_top (x)
  1366.      rtx x;
  1367. {
  1368.   register RTX_CODE code;
  1369.  
  1370.   code = GET_CODE (x);
  1371.   switch (code)
  1372.     {
  1373.     case LABEL_REF:
  1374.     case SYMBOL_REF:
  1375.     case CONST_INT:
  1376.     case CONST:
  1377.     case CC0:
  1378.     case PC:
  1379.     case CLOBBER:
  1380.     case MEM:
  1381.       return 0;
  1382.  
  1383.     case REG:
  1384.       return FP_REGNO_P (REGNO (x));
  1385.     }
  1386.  
  1387.   /* Recursively scan the operands of this expression.  */
  1388.   {
  1389.     register char *fmt = GET_RTX_FORMAT (code);
  1390.     register int i;
  1391.  
  1392.     for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
  1393.       {
  1394.     if (fmt[i] == 'e')
  1395.       {
  1396.         if (mentions_fp_top (XEXP (x, i)))
  1397.           return 1;
  1398.       }
  1399.     if (fmt[i] == 'E')
  1400.       {
  1401.         register int j;
  1402.         for (j = 0; j < XVECLEN (x, i); j++)
  1403.           if (mentions_fp_top (XVECEXP (x, i, j)))
  1404.         return 1;
  1405.       }
  1406.       }
  1407.   }
  1408.   return 0;
  1409. }
  1410.  
  1411. /* Some asm-dependent functions. */
  1412.  
  1413. #ifdef MASM
  1414. #include "masm386.c"
  1415. #endif
  1416.