home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 7 / FreshFishVol7.bin / bbs / gnu / gcc-2.3.3-src.lha / GNU / src / amiga / gcc-2.3.3 / config / pa.c < prev    next >
C/C++ Source or Header  |  1994-02-06  |  65KB  |  2,538 lines

  1. /* Subroutines for insn-output.c for HPPA.
  2.    Copyright (C) 1992 Free Software Foundation, Inc.
  3.    Contributed by Tim Moore (moore@cs.utah.edu), based on sparc.c
  4.  
  5. This file is part of GNU CC.
  6.  
  7. GNU CC is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2, or (at your option)
  10. any later version.
  11.  
  12. GNU CC is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with GNU CC; see the file COPYING.  If not, write to
  19. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21. #include <stdio.h>
  22. #include "config.h"
  23. #include "rtl.h"
  24. #include "regs.h"
  25. #include "hard-reg-set.h"
  26. #include "real.h"
  27. #include "insn-config.h"
  28. #include "conditions.h"
  29. #include "insn-flags.h"
  30. #include "output.h"
  31. #include "insn-attr.h"
  32. #include "flags.h"
  33. #include "tree.h"
  34. #include "c-tree.h"
  35. #include "expr.h"
  36. #include "obstack.h"
  37.  
  38. /* Save the operands last given to a compare for use when we
  39.    generate a scc or bcc insn.  */
  40.  
  41. rtx hppa_compare_op0, hppa_compare_op1;
  42. enum cmp_type hppa_branch_type;
  43.  
  44. /* Set by the FUNCTION_PROFILER macro. */
  45. int hp_profile_labelno;
  46.  
  47. /* Name of where we pretend to think the frame pointer points.
  48.    Normally, this is "4", but if we are in a leaf procedure,
  49.    this is "something(30)".  Will this work? */
  50. char *frame_base_name;
  51.  
  52. static rtx find_addr_reg ();
  53.  
  54. /* Return non-zero only if OP is a register of mode MODE,
  55.    or const0_rtx.  */
  56. int
  57. reg_or_0_operand (op, mode)
  58.      rtx op;
  59.      enum machine_mode mode;
  60. {
  61.   return (op == const0_rtx || register_operand (op, mode));
  62. }
  63.  
  64. int
  65. call_operand_address (op, mode)
  66.      rtx op;
  67.      enum machine_mode mode;
  68. {
  69.   return (REG_P (op) 
  70.       || (CONSTANT_P (op) && ! TARGET_LONG_CALLS));
  71. }
  72.  
  73. int
  74. symbolic_operand (op, mode)
  75.      register rtx op;
  76.      enum machine_mode mode;
  77. {
  78.   switch (GET_CODE (op))
  79.     {
  80.     case SYMBOL_REF:
  81.     case LABEL_REF:
  82.       return 1;
  83.     case CONST:
  84.       op = XEXP (op, 0);
  85.       return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
  86.            || GET_CODE (XEXP (op, 0)) == LABEL_REF)
  87.           && GET_CODE (XEXP (op, 1)) == CONST_INT);
  88.     default:
  89.       return 0;
  90.     }
  91. }
  92.  
  93. /* Return truth value of statement that OP is a symbolic memory
  94.    operand of mode MODE.  */
  95.  
  96. int
  97. symbolic_memory_operand (op, mode)
  98.      rtx op;
  99.      enum machine_mode mode;
  100. {
  101.   if (GET_CODE (op) == SUBREG)
  102.     op = SUBREG_REG (op);
  103.   if (GET_CODE (op) != MEM)
  104.     return 0;
  105.   op = XEXP (op, 0);
  106.   return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST
  107.       || GET_CODE (op) == HIGH || GET_CODE (op) == LABEL_REF);
  108. }
  109.  
  110. /* Return 1 if the operand is either a register or a memory operand that is
  111.    not symbolic.  */
  112.  
  113. int
  114. reg_or_nonsymb_mem_operand (op, mode)
  115.     register rtx op;
  116.     enum machine_mode mode;
  117. {
  118.   if (register_operand (op, mode))
  119.     return 1;
  120.  
  121.   if (memory_operand (op, mode) && ! symbolic_memory_operand (op, mode))
  122.     return 1;
  123.  
  124.   return 0;
  125. }
  126.  
  127. int
  128. move_operand (op, mode)
  129.      rtx op;
  130.      enum machine_mode mode;
  131. {
  132.   if (register_operand (op, mode))
  133.     return 1;
  134.  
  135.   if (op == CONST0_RTX (mode))
  136.     return 1;
  137.  
  138.   if (GET_MODE (op) != mode)
  139.     return 0;
  140.   if (GET_CODE (op) == SUBREG)
  141.     op = SUBREG_REG (op);
  142.   if (GET_CODE (op) != MEM)
  143.     return 0;
  144.  
  145.   op = XEXP (op, 0);
  146.   if (GET_CODE (op) == LO_SUM)
  147.     return (register_operand (XEXP (op, 0), Pmode)
  148.         && CONSTANT_P (XEXP (op, 1)));
  149.   return memory_address_p (mode, op);
  150. }
  151.  
  152. int
  153. pic_operand (op, mode)
  154.      rtx op;
  155.      enum machine_mode mode;
  156. {
  157.   return flag_pic && GET_CODE (op) == LABEL_REF;
  158. }
  159.  
  160. int
  161. short_memory_operand (op, mode)
  162.      rtx op;
  163.      enum machine_mode mode;
  164. {
  165.   if (GET_CODE (op) == MEM)
  166.     {
  167.       if (GET_CODE (XEXP (op, 0)) == REG)
  168.     return 1;
  169.       else if (GET_CODE (XEXP (op, 0)) == PLUS)
  170.     {
  171.       rtx op1 = XEXP (XEXP (op, 0), 0);
  172.       rtx op2 = XEXP (XEXP (op, 0), 1);
  173.  
  174.       if (GET_CODE (op1) == REG)
  175.         return (GET_CODE (op2) == CONST_INT && INT_5_BITS (op2));
  176.       else if (GET_CODE (op2) == REG)
  177.         return (GET_CODE (op1) == CONST_INT && INT_5_BITS (op1));
  178.     }
  179.     }
  180.   return 0;
  181. }
  182.  
  183. int
  184. register_or_short_operand (op, mode)
  185.      rtx op;
  186.      enum machine_mode mode;
  187. {
  188.   if (register_operand (op, mode))
  189.     return 1;
  190.   if (GET_CODE (op) == SUBREG)
  191.     op = SUBREG_REG (op);
  192.   return short_memory_operand (op, mode);
  193. }
  194.  
  195. int
  196. fp_reg_operand (op, mode)
  197.      rtx op;
  198.      enum machine_mode mode;
  199. {
  200.   return reg_renumber && FP_REG_P (op);
  201. }
  202.  
  203. int
  204. check_fp_mov (operands)
  205.      rtx *operands;
  206. {
  207.   enum machine_mode mode = GET_MODE (operands[0]);
  208.  
  209.   if (fp_reg_operand (operands[0], mode))
  210.     return (register_operand (operands[1], mode)
  211.         || short_memory_operand (operands[1], mode));
  212.   else if (fp_reg_operand (operands[1], mode))
  213.     return (register_operand (operands[0], mode)
  214.         || short_memory_operand (operands[0], mode));
  215.   else
  216.     return 1;
  217. }
  218.  
  219. extern int current_function_uses_pic_offset_table;
  220. extern rtx force_reg (), validize_mem ();
  221.  
  222. /* The rtx for the global offset table which is a special form
  223.    that *is* a position independent symbolic constant.  */
  224. rtx pic_pc_rtx;
  225.  
  226. /* Ensure that we are not using patterns that are not OK with PIC.  */
  227.  
  228. int
  229. check_pic (i)
  230.      int i;
  231. {
  232.   extern rtx recog_operand[];
  233.   switch (flag_pic)
  234.     {
  235.     case 1:
  236.       if (GET_CODE (recog_operand[i]) == SYMBOL_REF
  237.       || (GET_CODE (recog_operand[i]) == CONST
  238.           && ! rtx_equal_p (pic_pc_rtx, recog_operand[i])))
  239.     abort ();
  240.     case 2:
  241.     default:
  242.       return 1;
  243.     }
  244. }
  245.  
  246. /* Return truth value of whether OP is EQ or NE.  */
  247.  
  248. int
  249. eq_or_neq (op, mode)
  250.      rtx op;
  251.      enum machine_mode mode;
  252. {
  253.   return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
  254. }
  255.  
  256. /* Return truth value of whether OP can be used as an operand in a
  257.    three operand arithmetic insn that accepts registers of mode MODE
  258.    or 14-bit signed integers.  */
  259. int
  260. arith_operand (op, mode)
  261.      rtx op;
  262.      enum machine_mode mode;
  263. {
  264.   return (register_operand (op, mode)
  265.       || (GET_CODE (op) == CONST_INT && INT_14_BITS (op)));
  266. }
  267.  
  268. /* Return truth value of whether OP can be used as an operand in a
  269.    three operand arithmetic insn that accepts registers of mode MODE
  270.    or 11-bit signed integers.  */
  271. int
  272. arith11_operand (op, mode)
  273.      rtx op;
  274.      enum machine_mode mode;
  275. {
  276.   return (register_operand (op, mode)
  277.       || (GET_CODE (op) == CONST_INT && INT_11_BITS (op)));
  278. }
  279.  
  280. int
  281. arith_double_operand (op, mode)
  282.      rtx op;
  283.      enum machine_mode mode;
  284. {
  285.   return (register_operand (op, mode)
  286.       || (GET_CODE (op) == CONST_DOUBLE
  287.           && GET_MODE (op) == mode
  288.           && VAL_14_BITS_P (CONST_DOUBLE_LOW (op))
  289.           && (CONST_DOUBLE_HIGH (op) >= 0
  290.           == ((CONST_DOUBLE_LOW (op) & 0x1000) == 0))));
  291. }
  292.  
  293. /* Return truth value of whether OP is a integer which fits the
  294.    range constraining immediate operands in three-address insns.  */
  295.  
  296. int
  297. int5_operand (op, mode)
  298.      rtx op;
  299.      enum machine_mode mode;
  300. {
  301.   return (GET_CODE (op) == CONST_INT && INT_5_BITS (op));
  302. }
  303.  
  304. int
  305. uint5_operand (op, mode)
  306.      rtx op;
  307.      enum machine_mode mode;
  308. {
  309.   return (GET_CODE (op) == CONST_INT && INT_U5_BITS (op));
  310. }
  311.  
  312.   
  313. int
  314. int11_operand (op, mode)
  315.      rtx op;
  316.      enum machine_mode mode;
  317. {
  318.     return (GET_CODE (op) == CONST_INT && INT_11_BITS (op));
  319. }
  320.  
  321. int
  322. arith5_operand (op, mode)
  323.      rtx op;
  324.      enum machine_mode mode;
  325. {
  326.   return register_operand (op, mode) || int5_operand (op, mode);
  327. }
  328.  
  329. /* True iff zdepi can be used to generate this CONST_INT.  */
  330. int
  331. depi_cint_operand (op, mode)
  332.      rtx op;
  333.      enum machine_mode mode;
  334. {
  335.   unsigned x;
  336.   unsigned lbmask, t;
  337.  
  338.   if (GET_CODE (op) != CONST_INT)
  339.     return 0;
  340.  
  341.   /* This might not be obvious, but it's at least fast.
  342.      This function is critcal; we don't have the time loops would take.  */
  343.   x = INTVAL (op);
  344.   lbmask = x & -x;
  345.   t = ((x >> 4) + lbmask) & ~(lbmask - 1);
  346.   return ((t & (t - 1)) == 0);
  347. }
  348.  
  349. /* True iff depi or extru can be used to compute (reg & mask).  */
  350. int
  351. consec_zeros_p (mask)
  352.      unsigned mask;
  353. {
  354.   mask = ~mask;
  355.   mask += mask & -mask;
  356.   return (mask & (mask - 1)) == 0;
  357. }
  358.  
  359. /* True iff depi or extru can be used to compute (reg & OP).  */
  360. int
  361. and_operand (op, mode)
  362.      rtx op;
  363.      enum machine_mode mode;
  364. {
  365.   return (register_operand (op, mode)
  366.       || (GET_CODE (op) == CONST_INT && consec_zeros_p (INTVAL (op))));
  367. }
  368.  
  369. /* True iff depi can be used to compute (reg | MASK).  */
  370. int
  371. ior_mask_p (mask)
  372.      unsigned mask;
  373. {
  374.   mask += mask & -mask;
  375.   return (mask & (mask - 1)) == 0;
  376. }
  377.  
  378. /* True iff depi can be used to compute (reg | OP).  */
  379. int
  380. ior_operand (op, mode)
  381.      rtx op;
  382.      enum machine_mode mode;
  383. {
  384.   return (register_operand (op, mode)
  385.       || (GET_CODE (op) == CONST_INT && ior_mask_p (INTVAL (op))));
  386. }
  387.  
  388. int
  389. arith32_operand (op, mode)
  390.      rtx op;
  391.      enum machine_mode mode;
  392. {
  393.   return register_operand (op, mode) || GET_CODE (op) == CONST_INT;
  394. }
  395.  
  396. /* True iff OP can be the source of a move to a general register.  */
  397. int
  398. srcsi_operand (op, mode)
  399.      rtx op;
  400.      enum machine_mode mode;
  401. {
  402.   /* Not intended for other modes than SImode.  */
  403.   if (mode != SImode)
  404.     return 0;
  405.  
  406.   /* Accept any register or memory reference.  */
  407.   if (nonimmediate_operand (op, mode))
  408.     return 1;
  409.  
  410.   if (depi_cint_operand (op, mode))
  411.     return 1;
  412.  
  413.   /* OK if ldo or ldil can be used.  */
  414.   return (GET_CODE (op) == CONST_INT
  415.       && (INT_14_BITS (op) || (INTVAL (op) & 0x7ff) == 0));
  416. }
  417.  
  418.  
  419. /* Legitimize PIC addresses.  If the address is already
  420.    position-independent, we return ORIG.  Newly generated
  421.    position-independent addresses go to REG.  If we need more
  422.    than one register, we lose.  */
  423.  
  424. rtx
  425. legitimize_pic_address (orig, mode, reg)
  426.      rtx orig, reg;
  427.      enum machine_mode mode;
  428. {
  429.   rtx pic_ref = orig;
  430.  
  431.   if (GET_CODE (orig) == SYMBOL_REF)
  432.     {
  433.       if (reg == 0)
  434.     abort ();
  435.  
  436.       if (flag_pic == 2)
  437.     {
  438.       emit_insn (gen_rtx (SET, VOIDmode, reg,
  439.                   gen_rtx (HIGH, Pmode, orig)));
  440.       emit_insn (gen_rtx (SET, VOIDmode, reg,
  441.                   gen_rtx (LO_SUM, Pmode, reg, orig)));
  442.       orig = reg;
  443.     }
  444.       pic_ref = gen_rtx (MEM, Pmode,
  445.              gen_rtx (PLUS, Pmode,
  446.                   pic_offset_table_rtx, orig));
  447.       current_function_uses_pic_offset_table = 1;
  448.       RTX_UNCHANGING_P (pic_ref) = 1;
  449.       emit_move_insn (reg, pic_ref);
  450.       return reg;
  451.     }
  452.   else if (GET_CODE (orig) == CONST)
  453.     {
  454.       rtx base, offset;
  455.  
  456.       if (GET_CODE (XEXP (orig, 0)) == PLUS
  457.       && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
  458.     return orig;
  459.  
  460.       if (reg == 0)
  461.     abort ();
  462.  
  463.       if (GET_CODE (XEXP (orig, 0)) == PLUS)
  464.     {
  465.       base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
  466.       orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
  467.                      base == reg ? 0 : reg);
  468.     }
  469.       else abort ();
  470.       if (GET_CODE (orig) == CONST_INT)
  471.     {
  472.       if (SMALL_INT (orig))
  473.         return plus_constant_for_output (base, INTVAL (orig));
  474.       orig = force_reg (Pmode, orig);
  475.     }
  476.       pic_ref = gen_rtx (PLUS, Pmode, base, orig);
  477.       /* Likewise, should we set special REG_NOTEs here?  */
  478.     }
  479.   return pic_ref;
  480. }
  481.  
  482. /* Set up PIC-specific rtl.  This should not cause any insns
  483.    to be emitted.  */
  484.  
  485. void
  486. initialize_pic ()
  487. {
  488. }
  489.  
  490. /* Emit special PIC prologues and epilogues.  */
  491.  
  492. void
  493. finalize_pic ()
  494. {
  495.   /* Need to emit this whether or not we obey regdecls,
  496.      since setjmp/longjmp can cause life info to screw up.  */
  497.   emit_insn (gen_rtx (USE, VOIDmode, pic_offset_table_rtx));
  498. }
  499.  
  500. /* For the HPPA, REG and REG+CONST is cost 0
  501.    and addresses involving symbolic constants are cost 2.
  502.  
  503.    PIC addresses are very expensive.
  504.  
  505.    It is no coincidence that this has the same structure
  506.    as GO_IF_LEGITIMATE_ADDRESS.  */
  507. int
  508. hppa_address_cost (X)
  509.      rtx X;
  510. {
  511.   if (GET_CODE (X) == PLUS)
  512.       return 1;
  513.   else if (GET_CODE (X) == LO_SUM)
  514.     return 1;
  515.   else if (GET_CODE (X) == HIGH)
  516.     return 2;
  517.   return 4;
  518. }
  519.  
  520. /* Emit insns to move operands[1] into operands[0].
  521.  
  522.    Return 1 if we have written out everything that needs to be done to
  523.    do the move.  Otherwise, return 0 and the caller will emit the move
  524.    normally.  */
  525.  
  526. int
  527. emit_move_sequence (operands, mode, scratch_reg)
  528.      rtx *operands;
  529.      enum machine_mode mode;
  530.      rtx scratch_reg;
  531. {
  532.   register rtx operand0 = operands[0];
  533.   register rtx operand1 = operands[1];
  534.  
  535.   if (fp_reg_operand (operand0, mode)
  536.       && GET_CODE (operand1) == MEM
  537.       && !short_memory_operand  (operand1, mode)
  538.       && scratch_reg)
  539.     {
  540.       emit_move_insn (scratch_reg, XEXP (operand1 , 0));
  541.       emit_insn (gen_rtx (SET, VOIDmode, operand0, gen_rtx (MEM, mode,
  542.                                 scratch_reg)));
  543.       return 1;
  544.     }
  545.   else if (fp_reg_operand (operand1, mode)
  546.        && GET_CODE (operand0) == MEM
  547.        && !short_memory_operand  (operand0, mode)
  548.        && scratch_reg)
  549.     {
  550.       emit_move_insn (scratch_reg, XEXP (operand0 , 0));
  551.       emit_insn (gen_rtx (SET, VOIDmode, gen_rtx (MEM, mode,  scratch_reg),
  552.               operand1));
  553.       return 1;
  554.     }
  555.   /* Handle most common case: storing into a register.  */
  556.   else if (register_operand (operand0, mode))
  557.     {
  558.       if (register_operand (operand1, mode)
  559.       || (GET_CODE (operand1) == CONST_INT && SMALL_INT (operand1))
  560.       || (GET_CODE (operand1) == HIGH
  561.           && !symbolic_operand (XEXP (operand1, 0)))
  562.       /* Only `general_operands' can come here, so MEM is ok.  */
  563.       || GET_CODE (operand1) == MEM)
  564.     {
  565.       /* Run this case quickly.  */
  566.       emit_insn (gen_rtx (SET, VOIDmode, operand0, operand1));
  567.       return 1;
  568.     }
  569.     }
  570.   else if (GET_CODE (operand0) == MEM)
  571.     {
  572.       if (register_operand (operand1, mode) || operand1 == const0_rtx)
  573.     {
  574.       /* Run this case quickly.  */
  575.       emit_insn (gen_rtx (SET, VOIDmode, operand0, operand1));
  576.       return 1;
  577.     }
  578.       if (! reload_in_progress)
  579.     {
  580.       operands[0] = validize_mem (operand0);
  581.       operands[1] = operand1 = force_reg (mode, operand1);
  582.     }
  583.     }
  584.  
  585.   /* Simplify the source if we need to.  */
  586.   if (GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode))
  587.     {
  588.       if (symbolic_operand (operand1, mode))
  589.     {
  590.       if (flag_pic)
  591.         {
  592.           rtx temp = reload_in_progress ? operand0 : gen_reg_rtx (Pmode);
  593.           operands[1] = legitimize_pic_address (operand1, mode, temp);
  594.         }
  595.       /* On the HPPA, references to data space are supposed to */
  596.       /* use dp, register 27. */
  597.       else if (read_only_operand (operand1))
  598.         {
  599.           rtx set = gen_rtx (SET, VOIDmode,
  600.                   operand0,
  601.                   gen_rtx (LO_SUM, mode, operand0, operand1));
  602.                  
  603.           emit_insn (gen_rtx (SET, VOIDmode,
  604.                   operand0,
  605.                   gen_rtx (HIGH, mode, operand1)));
  606.           if (TARGET_SHARED_LIBS
  607.           && function_label_operand (operand1, mode))
  608.         {
  609.           rtx temp = reload_in_progress ? scratch_reg
  610.             : gen_reg_rtx (mode);
  611.           if (!temp)
  612.             abort ();
  613.           emit_insn (gen_rtx (PARALLEL, VOIDmode,
  614.                       gen_rtvec (2,
  615.                          set,
  616.                          gen_rtx (CLOBBER, VOIDmode,
  617.                               temp))));
  618.         }
  619.           else
  620.         emit_insn (set);
  621.           return 1;
  622.         }
  623.       else
  624.         {
  625.           /* If reload_in_progress, we can't use addil and r1; we */
  626.           /* have to use the more expensive ldil sequence. */
  627.           if (reload_in_progress)
  628.         {
  629.           emit_insn (gen_rtx (SET, VOIDmode,
  630.                       operand0,
  631.                       gen_rtx (HIGH, mode, operand1)));
  632.           emit_insn (gen_rtx (SET, VOIDmode,
  633.                       operand0,
  634.                       gen_rtx (PLUS, mode,
  635.                            operand0,
  636.                            gen_rtx (REG, mode, 27))));
  637.           emit_insn (gen_rtx (SET, VOIDmode,
  638.                       operand0,
  639.                       gen_rtx (LO_SUM, mode,
  640.                            operand0, operand1)));
  641.         }
  642.           else
  643.         {
  644.           rtx temp1, temp2 = gen_reg_rtx (mode);
  645.  
  646.           /* For 2.4 we could set RTX_UNCHANGING and add a 
  647.              REG_EQUAL note for the first insn.  This would 
  648.              allow the first insn to be moved out of loops.  */
  649.           temp1 = gen_rtx (HIGH, mode, operand1);
  650.           emit_insn (gen_rtx (SET, VOIDmode,
  651.                       temp2,
  652.                       gen_rtx (PLUS, mode,
  653.                            gen_rtx (REG, mode, 27),
  654.                            temp1)));
  655.           emit_insn (gen_rtx (SET, VOIDmode,
  656.                       operand0,
  657.                       gen_rtx (LO_SUM, mode,
  658.                            temp2, operand1)));
  659.         }
  660.           return 1;
  661.         }
  662.     }
  663.       else if (depi_cint_operand (operand1, VOIDmode))
  664.     return 0;
  665.       else if (GET_CODE (operand1) == CONST_INT
  666.            ? (! SMALL_INT (operand1)
  667.           && (INTVAL (operand1) & 0x7ff) != 0) : 1)
  668.     {
  669.       rtx temp = reload_in_progress ? operand0 : gen_reg_rtx (mode);
  670.       emit_insn (gen_rtx (SET, VOIDmode, temp,
  671.                   gen_rtx (HIGH, mode, operand1)));
  672.       operands[1] = gen_rtx (LO_SUM, mode, temp, operand1);
  673.     }
  674.     }
  675.   /* Now have insn-emit do whatever it normally does.  */
  676.   return 0;
  677. }
  678.  
  679. /* Does operand (which is a symbolic_operand) live in text space? If
  680.    so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true.*/
  681.  
  682. int
  683. read_only_operand (operand)
  684.      rtx operand;
  685. {
  686.   if (GET_CODE (operand) == CONST)
  687.     operand = XEXP (XEXP (operand, 0), 0);
  688.   if (GET_CODE (operand) == SYMBOL_REF)
  689.     return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand);
  690.   return 1;
  691. }
  692.      
  693.  
  694. /* Return the best assembler insn template
  695.    for moving operands[1] into operands[0] as a fullword.  */
  696.  
  697. char *
  698. singlemove_string (operands)
  699.      rtx *operands;
  700. {
  701.   if (GET_CODE (operands[0]) == MEM)
  702.     return "stw %r1,%0";
  703.   if (GET_CODE (operands[1]) == MEM)
  704.     return "ldw %1,%0";
  705.   if (GET_CODE (operands[1]) == CONST_INT)
  706.     if (INT_14_BITS (operands[1]))
  707.       return (INTVAL (operands[1]) == 0 ? "copy 0,%0" : "ldi %1,%0");
  708.     else
  709.       return "ldil L'%1,%0\n\tldo R'%1(%0),%0";
  710.   return "copy %1,%0";
  711. }
  712.  
  713.  
  714. /* Compute position (in OPERANDS[2]) and width (in OPERANDS[3])
  715.    useful for copying or or'ing IMM to a register using bit field
  716.    instructions.  Store the immediate value to insert in OPERANDS[1].  */
  717. void
  718. compute_xdepi_operands_from_integer (imm, operands)
  719.      unsigned imm;
  720.      rtx *operands;
  721. {
  722.   int lsb, len;
  723.  
  724.   /* Find the least significant set bit in IMM.  */
  725.   for (lsb = 0; lsb < 32; lsb++)
  726.     {
  727.       if ((imm & 1) != 0)
  728.         break;
  729.       imm >>= 1;
  730.     }
  731.  
  732.   /* Choose variants based on *sign* of the 5-bit field.  */
  733.   if ((imm & 0x10) == 0)
  734.     len = (lsb <= 28) ? 4 : 32 - lsb;
  735.   else
  736.     {
  737.       /* Find the width of the bitstring in IMM.  */
  738.       for (len = 5; len < 32; len++)
  739.     {
  740.       if ((imm & (1 << len)) == 0)
  741.         break;
  742.     }
  743.  
  744.       /* Sign extend IMM as a 5-bit value.  */
  745.       imm = (imm & 0xf) - 0x10;
  746.     }
  747.  
  748.   operands[1] = gen_rtx (CONST_INT, VOIDmode, imm);
  749.   operands[2] = gen_rtx (CONST_INT, VOIDmode, 31 - lsb);
  750.   operands[3] = gen_rtx (CONST_INT, VOIDmode, len);
  751. }
  752.  
  753. /* Output assembler code to perform a doubleword move insn
  754.    with operands OPERANDS.  */
  755.  
  756. char *
  757. output_move_double (operands)
  758.      rtx *operands;
  759. {
  760.   enum { REGOP, OFFSOP, MEMOP, CNSTOP, RNDOP } optype0, optype1;
  761.   rtx latehalf[2];
  762.   rtx addreg0 = 0, addreg1 = 0;
  763.  
  764.   /* First classify both operands.  */
  765.  
  766.   if (REG_P (operands[0]))
  767.     optype0 = REGOP;
  768.   else if (offsettable_memref_p (operands[0]))
  769.     optype0 = OFFSOP;
  770.   else if (GET_CODE (operands[0]) == MEM)
  771.     optype0 = MEMOP;
  772.   else
  773.     optype0 = RNDOP;
  774.  
  775.   if (REG_P (operands[1]))
  776.     optype1 = REGOP;
  777.   else if (CONSTANT_P (operands[1]))
  778.     optype1 = CNSTOP;
  779.   else if (offsettable_memref_p (operands[1]))
  780.     optype1 = OFFSOP;
  781.   else if (GET_CODE (operands[1]) == MEM)
  782.     optype1 = MEMOP;
  783.   else
  784.     optype1 = RNDOP;
  785.  
  786.   /* Check for the cases that the operand constraints are not
  787.      supposed to allow to happen.  Abort if we get one,
  788.      because generating code for these cases is painful.  */
  789.  
  790.   if (optype0 != REGOP && optype1 != REGOP)
  791.     abort ();
  792.  
  793.    /* Handle auto decrementing and incrementing loads and stores
  794.      specifically, since the structure of the function doesn't work
  795.      for them without major modification.  Do it better when we learn
  796.      this port about the general inc/dec addressing of PA.
  797.      (This was written by tege.  Chide him if it doesn't work.)  */
  798.  
  799.   if (optype0 == MEMOP)
  800.     {
  801.       /* We have to output the address syntax ourselves, since print_operand
  802.      doesn't deal with the addresses we want to use.  Fix this later.  */
  803.  
  804.       rtx addr = XEXP (operands[0], 0);
  805.       if (GET_CODE (addr) == POST_INC || GET_CODE (addr) == POST_DEC)
  806.     {
  807.       rtx high_reg = gen_rtx (SUBREG, SImode, operands[1], 0);
  808.  
  809.       operands[0] = XEXP (addr, 0);
  810.       if (GET_CODE (operands[1]) != REG || GET_CODE (operands[0]) != REG)
  811.         abort ();
  812.  
  813.       if (!reg_overlap_mentioned_p (high_reg, addr))
  814.         {
  815.           /* No overlap between high target register and address
  816.          register.  (We do this in a non-obvious way to
  817.          save a register file writeback)  */
  818.           if (GET_CODE (addr) == POST_INC)
  819.         return "stws,ma %1,8(0,%0)\n\tstw %R1,-4(0,%0)";
  820.           return "stws,ma %1,-8(0,%0)\n\tstw %R1,12(0,%0)";
  821.         }
  822.       else
  823.         abort();
  824.     }
  825.       else if (GET_CODE (addr) == PRE_INC || GET_CODE (addr) == PRE_DEC)
  826.     {
  827.       rtx high_reg = gen_rtx (SUBREG, SImode, operands[1], 0);
  828.  
  829.       operands[0] = XEXP (addr, 0);
  830.       if (GET_CODE (operands[1]) != REG || GET_CODE (operands[0]) != REG)
  831.         abort ();
  832.  
  833.       if (!reg_overlap_mentioned_p (high_reg, addr))
  834.         {
  835.           /* No overlap between high target register and address
  836.          register.  (We do this in a non-obvious way to
  837.          save a register file writeback)  */
  838.           if (GET_CODE (addr) == PRE_INC)
  839.         return "stws,mb %1,8(0,%0)\n\tstw %R1,4(0,%0)";
  840.           return "stws,mb %1,-8(0,%0)\n\tstw %R1,4(0,%0)";
  841.         }
  842.       else
  843.         abort();
  844.     }
  845.     }
  846.   if (optype1 == MEMOP)
  847.     {
  848.       /* We have to output the address syntax ourselves, since print_operand
  849.      doesn't deal with the addresses we want to use.  Fix this later.  */
  850.  
  851.       rtx addr = XEXP (operands[1], 0);
  852.       if (GET_CODE (addr) == POST_INC || GET_CODE (addr) == POST_DEC)
  853.     {
  854.       rtx high_reg = gen_rtx (SUBREG, SImode, operands[0], 0);
  855.  
  856.       operands[1] = XEXP (addr, 0);
  857.       if (GET_CODE (operands[0]) != REG || GET_CODE (operands[1]) != REG)
  858.         abort ();
  859.  
  860.       if (!reg_overlap_mentioned_p (high_reg, addr))
  861.         {
  862.           /* No overlap between high target register and address
  863.          register.  (We do this in a non-obvious way to
  864.          save a register file writeback)  */
  865.           if (GET_CODE (addr) == POST_INC)
  866.         return "ldws,ma 8(0,%1),%0\n\tldw -4(0,%1),%R0";
  867.           return "ldws,ma -8(0,%1),%0\n\tldw 12(0,%1),%R0";
  868.         }
  869.       else
  870.         {
  871.           /* This is an undefined situation.  We should load into the
  872.          address register *and* update that register.  Probably
  873.          we don't need to handle this at all.  */
  874.           if (GET_CODE (addr) == POST_INC)
  875.         return "ldw 4(0,%1),%R0\n\tldws,ma 8(0,%1),%0";
  876.           return "ldw 4(0,%1),%R0\n\tldws,ma -8(0,%1),%0";
  877.         }
  878.     }
  879.       else if (GET_CODE (addr) == PRE_INC || GET_CODE (addr) == PRE_DEC)
  880.     {
  881.       rtx high_reg = gen_rtx (SUBREG, SImode, operands[0], 0);
  882.  
  883.       operands[1] = XEXP (addr, 0);
  884.       if (GET_CODE (operands[0]) != REG || GET_CODE (operands[1]) != REG)
  885.         abort ();
  886.  
  887.       if (!reg_overlap_mentioned_p (high_reg, addr))
  888.         {
  889.           /* No overlap between high target register and address
  890.          register.  (We do this in a non-obvious way to
  891.          save a register file writeback)  */
  892.           if (GET_CODE (addr) == PRE_INC)
  893.         return "ldws,mb 8(0,%1),%0\n\tldw 4(0,%1),%R0";
  894.           return "ldws,mb -8(0,%1),%0\n\tldw 4(0,%1),%R0";
  895.         }
  896.       else
  897.         {
  898.           /* This is an undefined situation.  We should load into the
  899.          address register *and* update that register.  Probably
  900.          we don't need to handle this at all.  */
  901.           if (GET_CODE (addr) == PRE_INC)
  902.         return "ldw 12(0,%1),%R0\n\tldws,mb 8(0,%1),%0";
  903.           return "ldw -4(0,%1),%R0\n\tldws,mb -8(0,%1),%0";
  904.         }
  905.     }
  906.     }
  907.  
  908.   /* If an operand is an unoffsettable memory ref, find a register
  909.      we can increment temporarily to make it refer to the second word.  */
  910.  
  911.   if (optype0 == MEMOP)
  912.     addreg0 = find_addr_reg (XEXP (operands[0], 0));
  913.  
  914.   if (optype1 == MEMOP)
  915.     addreg1 = find_addr_reg (XEXP (operands[1], 0));
  916.  
  917.   /* Ok, we can do one word at a time.
  918.      Normally we do the low-numbered word first.
  919.  
  920.      In either case, set up in LATEHALF the operands to use
  921.      for the high-numbered word and in some cases alter the
  922.      operands in OPERANDS to be suitable for the low-numbered word.  */
  923.  
  924.   if (optype0 == REGOP)
  925.     latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
  926.   else if (optype0 == OFFSOP)
  927.     latehalf[0] = adj_offsettable_operand (operands[0], 4);
  928.   else
  929.     latehalf[0] = operands[0];
  930.  
  931.   if (optype1 == REGOP)
  932.     latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
  933.   else if (optype1 == OFFSOP)
  934.     latehalf[1] = adj_offsettable_operand (operands[1], 4);
  935.   else if (optype1 == CNSTOP)
  936.     split_double (operands[1], &operands[1], &latehalf[1]);
  937.   else
  938.     latehalf[1] = operands[1];
  939.  
  940.   /* If the first move would clobber the source of the second one,
  941.      do them in the other order.
  942.  
  943.      RMS says "This happens only for registers;
  944.      such overlap can't happen in memory unless the user explicitly
  945.      sets it up, and that is an undefined circumstance."
  946.  
  947.      but it happens on the HP-PA when loading parameter registers,
  948.      so I am going to define that circumstance, and make it work
  949.      as expected.  */
  950.  
  951.   if (optype0 == REGOP && (optype1 == MEMOP || optype1 == OFFSOP)
  952.        && reg_overlap_mentioned_p (operands[0], XEXP (operands[1], 0)))
  953.     {
  954.       /* XXX THIS PROBABLY DOESN'T WORK.  */
  955.       /* Do the late half first.  */
  956.       if (addreg1)
  957.     output_asm_insn ("ldo 4(%0),%0", &addreg1);
  958.       output_asm_insn (singlemove_string (latehalf), latehalf);
  959.       if (addreg1)
  960.     output_asm_insn ("ldo -4(%0),%0", &addreg1);
  961.       /* Then clobber.  */
  962.       return singlemove_string (operands);
  963.     }
  964.  
  965.   if (optype0 == REGOP && optype1 == REGOP
  966.       && REGNO (operands[0]) == REGNO (operands[1]) + 1)
  967.     {
  968.       output_asm_insn (singlemove_string (latehalf), latehalf);
  969.       return singlemove_string (operands);
  970.     }
  971.  
  972.   /* Normal case: do the two words, low-numbered first.  */
  973.  
  974.   output_asm_insn (singlemove_string (operands), operands);
  975.  
  976.   /* Make any unoffsettable addresses point at high-numbered word.  */
  977.   if (addreg0)
  978.     output_asm_insn ("ldo 4(%0),%0", &addreg0);
  979.   if (addreg1)
  980.     output_asm_insn ("ldo 4(%0),%0", &addreg1);
  981.  
  982.   /* Do that word.  */
  983.   output_asm_insn (singlemove_string (latehalf), latehalf);
  984.  
  985.   /* Undo the adds we just did.  */
  986.   if (addreg0)
  987.     output_asm_insn ("ldo -4(%0),%0", &addreg0);
  988.   if (addreg1)
  989.     output_asm_insn ("ldo -4(%0),%0", &addreg1);
  990.  
  991.   return "";
  992. }
  993.  
  994. char *
  995. output_fp_move_double (operands)
  996.      rtx *operands;
  997. {
  998.   if (FP_REG_P (operands[0]))
  999.     {
  1000.       if (FP_REG_P (operands[1]))
  1001.     output_asm_insn ("fcpy,dbl %1,%0", operands);
  1002.       else if (GET_CODE (operands[1]) == REG)
  1003.     {
  1004.       rtx xoperands[3];
  1005.       xoperands[0] = operands[0];
  1006.       xoperands[1] = operands[1];
  1007.       xoperands[2] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
  1008.       output_asm_insn
  1009.         ("stw %1,-16(0,30)\n\tstw %2,-12(0,30)\n\tfldds -16(0,30),%0",
  1010.                xoperands);
  1011.     }
  1012.       else 
  1013.     output_asm_insn ("fldds%F1 %1,%0", operands);
  1014.     }
  1015.   else if (FP_REG_P (operands[1]))
  1016.     {
  1017.       if (GET_CODE (operands[0]) == REG)
  1018.     {
  1019.       rtx xoperands[3];
  1020.       xoperands[2] = operands[1];
  1021.       xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
  1022.       xoperands[0] = operands[0];
  1023.       output_asm_insn
  1024.         ("fstds %2,-16(0,30)\n\tldw -12(0,30),%1\n\tldw -16(0,30),%0",
  1025.          xoperands);
  1026.     }
  1027.       else
  1028.     output_asm_insn ("fstds%F0 %1,%0", operands);
  1029.     }
  1030.   else abort ();
  1031.   return "";
  1032. }
  1033.  
  1034. /* Return a REG that occurs in ADDR with coefficient 1.
  1035.    ADDR can be effectively incremented by incrementing REG.  */
  1036.  
  1037. static rtx
  1038. find_addr_reg (addr)
  1039.      rtx addr;
  1040. {
  1041.   while (GET_CODE (addr) == PLUS)
  1042.     {
  1043.       if (GET_CODE (XEXP (addr, 0)) == REG)
  1044.     addr = XEXP (addr, 0);
  1045.       else if (GET_CODE (XEXP (addr, 1)) == REG)
  1046.     addr = XEXP (addr, 1);
  1047.       else if (CONSTANT_P (XEXP (addr, 0)))
  1048.     addr = XEXP (addr, 1);
  1049.       else if (CONSTANT_P (XEXP (addr, 1)))
  1050.     addr = XEXP (addr, 0);
  1051.       else
  1052.     abort ();
  1053.     }
  1054.   if (GET_CODE (addr) == REG)
  1055.     return addr;
  1056.   abort ();
  1057. }
  1058.  
  1059. /* Emit code to perform a block move.
  1060.  
  1061.    Restriction: If the length argument is non-constant, alignment
  1062.    must be 4.
  1063.  
  1064.    OPERANDS[0] is the destination pointer as a REG, clobbered.
  1065.    OPERANDS[1] is the source pointer as a REG, clobbered.
  1066.    if SIZE_IS_CONSTANT
  1067.      OPERANDS[2] is a register for temporary storage.
  1068.      OPERANDS[4] is the size as a CONST_INT
  1069.    else
  1070.      OPERANDS[2] is a REG which will contain the size, clobbered.
  1071.    OPERANDS[3] is a register for temporary storage.
  1072.    OPERANDS[5] is the alignment safe to use, as a CONST_INT.  */
  1073.  
  1074. char *
  1075. output_block_move (operands, size_is_constant)
  1076.      rtx *operands;
  1077.      int size_is_constant;
  1078. {
  1079.   int align = INTVAL (operands[5]);
  1080.   unsigned long n_bytes;
  1081.  
  1082.   /* We can't move more than four bytes at a time because the PA
  1083.      has no longer integer move insns.  (Could use fp mem ops?)  */
  1084.   if (align > 4)
  1085.     align = 4;
  1086.  
  1087.   if (size_is_constant)
  1088.     {
  1089.       unsigned long n_items;
  1090.       unsigned long offset;
  1091.       rtx temp;
  1092.  
  1093.       n_bytes = INTVAL (operands[4]);
  1094.       if (n_bytes == 0)
  1095.     return "";
  1096.  
  1097.       if (align >= 4)
  1098.     {
  1099.       /* Don't unroll too large blocks.  */
  1100.       if (n_bytes > 64)
  1101.         goto copy_with_loop;
  1102.  
  1103.       /* Read and store using two registers, and hide latency
  1104.          by deferring the stores until three instructions after
  1105.          the corresponding load.  The last load insn will read
  1106.          the entire word were the last bytes are, possibly past
  1107.          the end of the source block, but since loads are aligned,
  1108.          this is harmless.  */
  1109.  
  1110.       output_asm_insn ("ldws,ma 4(0,%1),%2", operands);
  1111.  
  1112.       for (offset = 4; offset < n_bytes; offset += 4)
  1113.         {
  1114.           output_asm_insn ("ldws,ma 4(0,%1),%3", operands);
  1115.           output_asm_insn ("stws,ma %2,4(0,%0)", operands);
  1116.  
  1117.           temp = operands[2];
  1118.           operands[2] = operands[3];
  1119.           operands[3] = temp;
  1120.         }
  1121.       if (n_bytes % 4 == 0)
  1122.         /* Store the last word.  */
  1123.         output_asm_insn ("stw %2,0(0,%0)", operands);
  1124.       else
  1125.         {
  1126.           /* Store the last, partial word.  */
  1127.           operands[4] = gen_rtx (CONST_INT, VOIDmode, n_bytes % 4);
  1128.           output_asm_insn ("stbys,e %2,%4(0,%0)", operands);
  1129.         }
  1130.       return "";
  1131.     }
  1132.  
  1133.       if (align >= 2 && n_bytes >= 2)
  1134.     {
  1135.       output_asm_insn ("ldhs,ma 2(0,%1),%2", operands);
  1136.  
  1137.       for (offset = 2; offset + 2 <= n_bytes; offset += 2)
  1138.         {
  1139.           output_asm_insn ("ldhs,ma 2(0,%1),%3", operands);
  1140.           output_asm_insn ("sths,ma %2,2(0,%0)", operands);
  1141.  
  1142.           temp = operands[2];
  1143.           operands[2] = operands[3];
  1144.           operands[3] = temp;
  1145.         }
  1146.       if (n_bytes % 2 != 0)
  1147.         output_asm_insn ("ldb 0(0,%1),%3", operands);
  1148.  
  1149.       output_asm_insn ("sths,ma %2,2(0,%0)", operands);
  1150.  
  1151.       if (n_bytes % 2 != 0)
  1152.         output_asm_insn ("stb %3,0(0,%0)", operands);
  1153.  
  1154.       return "";
  1155.     }
  1156.  
  1157.       output_asm_insn ("ldbs,ma 1(0,%1),%2", operands);
  1158.  
  1159.       for (offset = 1; offset + 1 <= n_bytes; offset += 1)
  1160.     {
  1161.       output_asm_insn ("ldbs,ma 1(0,%1),%3", operands);
  1162.       output_asm_insn ("stbs,ma %2,1(0,%0)", operands);
  1163.  
  1164.       temp = operands[2];
  1165.       operands[2] = operands[3];
  1166.       operands[3] = temp;
  1167.     }
  1168.       output_asm_insn ("stb %2,0(0,%0)", operands);
  1169.  
  1170.       return "";
  1171.     }
  1172.  
  1173.   if (align != 4)
  1174.     abort();
  1175.      
  1176.  copy_with_loop:
  1177.  
  1178.   if (size_is_constant)
  1179.     {
  1180.       /* Size is compile-time determined, and also not
  1181.      very small (such small cases are handled above).  */
  1182.       operands[4] = gen_rtx (CONST_INT, VOIDmode, n_bytes - 4);
  1183.       output_asm_insn ("ldo %4(0),%2", operands);
  1184.     }
  1185.   else
  1186.     {
  1187.       /* Decrement counter by 4, and if it becomes negative, jump past the
  1188.      word copying loop.  */
  1189.       output_asm_insn ("addib,<,n -4,%2,.+16", operands);
  1190.     }
  1191.  
  1192.   /* Copying loop.  Note that the first load is in the annulled delay slot
  1193.      of addib.  Is it OK on PA to have a load in a delay slot, i.e. is a
  1194.      possible page fault stopped in time?  */
  1195.   output_asm_insn ("ldws,ma 4(0,%1),%3", operands);
  1196.   output_asm_insn ("addib,>= -4,%2,.-4", operands);
  1197.   output_asm_insn ("stws,ma %3,4(0,%0)", operands);
  1198.  
  1199.   /* The counter is negative, >= -4.  The remaining number of bytes are
  1200.      determined by the two least significant bits.  */
  1201.  
  1202.   if (size_is_constant)
  1203.     {
  1204.       if (n_bytes % 4 != 0)
  1205.     {
  1206.       /* Read the entire word of the source block tail.  */
  1207.       output_asm_insn ("ldw 0(0,%1),%3", operands);
  1208.       operands[4] = gen_rtx (CONST_INT, VOIDmode, n_bytes % 4);
  1209.       output_asm_insn ("stbys,e %3,%4(0,%0)", operands);
  1210.     }
  1211.     }
  1212.   else
  1213.     {
  1214.       /* Add 4 to counter.  If it becomes zero, we're done.  */
  1215.       output_asm_insn ("addib,=,n 4,%2,.+16", operands);
  1216.  
  1217.       /* Read the entire word of the source block tail.  (Also this
  1218.      load is in an annulled delay slot.)  */
  1219.       output_asm_insn ("ldw 0(0,%1),%3", operands);
  1220.  
  1221.       /* Make %0 point at the first byte after the destination block.  */
  1222.       output_asm_insn ("add %2,%0,%0", operands);
  1223.       /* Store the leftmost bytes, up to, but not including, the address
  1224.      in %0.  */
  1225.       output_asm_insn ("stbys,e %3,0(0,%0)", operands);
  1226.     }
  1227.   return "";
  1228. }
  1229.  
  1230.  
  1231. char *
  1232. output_and (operands)
  1233.      rtx *operands;
  1234. {
  1235.   if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) != 0)
  1236.     {
  1237.       unsigned mask = INTVAL (operands[2]);
  1238.       int ls0, ls1, ms0, p, len;
  1239.  
  1240.       for (ls0 = 0; ls0 < 32; ls0++)
  1241.     if ((mask & (1 << ls0)) == 0)
  1242.       break;
  1243.  
  1244.       for (ls1 = ls0; ls1 < 32; ls1++)
  1245.     if ((mask & (1 << ls1)) != 0)
  1246.       break;
  1247.  
  1248.       for (ms0 = ls1; ms0 < 32; ms0++)
  1249.     if ((mask & (1 << ms0)) == 0)
  1250.       break;
  1251.  
  1252.       if (ms0 != 32)
  1253.     abort();
  1254.  
  1255.       if (ls1 == 32)
  1256.     {
  1257.       len = ls0;
  1258.  
  1259.       if (len == 0)
  1260.         abort ();
  1261.  
  1262.       operands[2] = gen_rtx (CONST_INT, VOIDmode, len);
  1263.       return "extru %1,31,%2,%0";
  1264.     }
  1265.       else
  1266.     {
  1267.       /* We could use this `depi' for the case above as well, but `depi'
  1268.          requires one more register file access than an `extru'.  */
  1269.  
  1270.       p = 31 - ls0;
  1271.       len = ls1 - ls0;
  1272.  
  1273.       operands[2] = gen_rtx (CONST_INT, VOIDmode, p);
  1274.       operands[3] = gen_rtx (CONST_INT, VOIDmode, len);
  1275.       return "depi 0,%2,%3,%0";
  1276.     }
  1277.     }
  1278.   else
  1279.     return "and %1,%2,%0";
  1280. }
  1281.  
  1282. char *
  1283. output_ior (operands)
  1284.      rtx *operands;
  1285. {
  1286.   if (GET_CODE (operands[2]) == CONST_INT)
  1287.     {
  1288.       unsigned mask = INTVAL (operands[2]);
  1289.       int bs0, bs1, bs2, p, len;
  1290.  
  1291.       if (INTVAL (operands[2]) == 0)
  1292.     return "copy %1,%0";
  1293.  
  1294.       for (bs0 = 0; bs0 < 32; bs0++)
  1295.     if ((mask & (1 << bs0)) != 0)
  1296.       break;
  1297.  
  1298.       for (bs1 = bs0; bs1 < 32; bs1++)
  1299.     if ((mask & (1 << bs1)) == 0)
  1300.       break;
  1301.  
  1302.       if (bs1 != 32 && ((unsigned) 1 << bs1) <= mask)
  1303.     abort();
  1304.  
  1305.       p = 31 - bs0;
  1306.       len = bs1 - bs0;
  1307.  
  1308.       operands[2] = gen_rtx (CONST_INT, VOIDmode, p);
  1309.       operands[3] = gen_rtx (CONST_INT, VOIDmode, len);
  1310.       return "depi -1,%2,%3,%0";
  1311.     }
  1312.   else
  1313.     return "or %1,%2,%0";
  1314. }
  1315.  
  1316. /* Output an ascii string.  */
  1317. output_ascii (file, p, size)
  1318.      FILE *file;
  1319.      unsigned char *p;
  1320.      int size;
  1321. {
  1322.   int i;
  1323.   int chars_output;
  1324.   unsigned char partial_output[16];    /* Max space 4 chars can occupy.   */
  1325.  
  1326.   /* The HP assembler can only take strings of 256 characters at one
  1327.      time.  This is a limitation on input line length, *not* the
  1328.      length of the string.  Sigh.  Even worse, it seems that the
  1329.      restriction is in number of input characters (see \xnn &
  1330.      \whatever).  So we have to do this very carefully.  */
  1331.  
  1332.   fprintf (file, "\t.STRING \"");
  1333.  
  1334.   chars_output = 0;
  1335.   for (i = 0; i < size; i += 4)
  1336.     {
  1337.       int co = 0;
  1338.       int io = 0;
  1339.       for (io = 0, co = 0; io < MIN (4, size - i); io++)
  1340.     {
  1341.       register unsigned int c = p[i + io];
  1342.  
  1343.       if (c == '\"' || c == '\\')
  1344.         partial_output[co++] = '\\';
  1345.       if (c >= ' ' && c < 0177)
  1346.         partial_output[co++] = c;
  1347.       else
  1348.         {
  1349.           unsigned int hexd;
  1350.           partial_output[co++] = '\\';
  1351.           partial_output[co++] = 'x';
  1352.           hexd =  c  / 16 - 0 + '0';
  1353.           if (hexd > '9')
  1354.         hexd -= '9' - 'a' + 1;
  1355.           partial_output[co++] = hexd;
  1356.           hexd =  c % 16 - 0 + '0';
  1357.           if (hexd > '9')
  1358.         hexd -= '9' - 'a' + 1;
  1359.           partial_output[co++] = hexd;
  1360.         }
  1361.     }
  1362.       if (chars_output + co > 243)
  1363.     {
  1364.       fprintf (file, "\"\n\t.STRING \"");
  1365.       chars_output = 0;
  1366.     }
  1367.       fwrite (partial_output, 1, co, file);
  1368.       chars_output += co;
  1369.       co = 0;
  1370.     }
  1371.   fprintf (file, "\"\n");
  1372. }
  1373.  
  1374. /* You may have trouble believing this, but this is the HP825 stack
  1375.    layout.  Wow.
  1376.  
  1377.    Offset        Contents
  1378.  
  1379.    Variable arguments    (optional; any number may be allocated)
  1380.  
  1381.    SP-(4*(N+9))        arg word N
  1382.        :            :
  1383.       SP-56        arg word 5
  1384.       SP-52        arg word 4
  1385.  
  1386.    Fixed arguments    (must be allocated; may remain unused)
  1387.  
  1388.       SP-48        arg word 3
  1389.       SP-44        arg word 2
  1390.       SP-40        arg word 1
  1391.       SP-36        arg word 0
  1392.  
  1393.    Frame Marker
  1394.  
  1395.       SP-32        External Data Pointer (DP)
  1396.       SP-28        External sr4
  1397.       SP-24        External/stub RP (RP')
  1398.       SP-20        Current RP
  1399.       SP-16        Static Link
  1400.       SP-12        Clean up
  1401.       SP-8        Calling Stub RP (RP'')
  1402.       SP-4        Previous SP
  1403.  
  1404.    Top of Frame
  1405.  
  1406.       SP-0        Stack Pointer (points to next available address)
  1407.  
  1408. */
  1409.  
  1410. /* This function saves registers as follows.  Registers marked with ' are
  1411.    this function's registers (as opposed to the previous function's).
  1412.    If a frame_pointer isn't needed, r4 is saved as a general register;
  1413.    the space for the frame pointer is still allocated, though, to keep
  1414.    things simple.
  1415.  
  1416.  
  1417.    Top of Frame
  1418.  
  1419.        SP (FP')        Previous FP
  1420.        SP + 4        Alignment filler (sigh)
  1421.        SP + 8        Space for locals reserved here.
  1422.        .
  1423.        .
  1424.        .
  1425.        SP + n        All call saved register used.
  1426.        .
  1427.        .
  1428.        .
  1429.        SP + o        All call saved fp registers used.
  1430.        .
  1431.        .
  1432.        .
  1433.        SP + p (SP')    points to next available address.
  1434.        
  1435. */
  1436.  
  1437. /* Helper functions */
  1438. void
  1439. print_stw (file, r, disp, base)
  1440.      FILE *file;
  1441.      int r, disp, base;
  1442. {
  1443.   if (VAL_14_BITS_P (disp))
  1444.     fprintf (file, "\tstw %d,%d(0,%d)\n", r, disp, base);
  1445.   else
  1446.     fprintf (file, "\taddil L'%d,%d\n\tstw %d,R'%d(0,1)\n", disp, base,
  1447.          r, disp);
  1448. }
  1449.  
  1450. void
  1451. print_ldw (file, r, disp, base)
  1452.      FILE *file;
  1453.      int r, disp, base;
  1454. {
  1455.   if (VAL_14_BITS_P (disp))
  1456.     fprintf (file, "\tldw %d(0,%d),%d\n", disp, base, r);
  1457.   else
  1458.     fprintf (file, "\taddil L'%d,%d\n\tldw R'%d(0,1),%d\n", disp, base,
  1459.          disp, r);
  1460. }
  1461.  
  1462. /* Global variables set by FUNCTION_PROLOGUE.  */
  1463. /* Size of frame.  Need to know this to emit return insns from
  1464.    leaf procedures.  */
  1465. int apparent_fsize;
  1466. int actual_fsize;
  1467. int local_fsize, save_fregs;
  1468.  
  1469. int
  1470. compute_frame_size (size, leaf_function, fregs_live)
  1471.      int size;
  1472.      int leaf_function;
  1473.      int *fregs_live;
  1474. {
  1475.   extern int current_function_outgoing_args_size;
  1476.   int i;
  1477.  
  1478.   /* 8 is space for frame pointer + filler */
  1479.   local_fsize = actual_fsize = size + 8;
  1480.  
  1481.   /* fp is stored in a special place. */
  1482.   for (i = 18; i >= 5; i--)
  1483.     if (regs_ever_live[i])
  1484.       actual_fsize += 4;
  1485.  
  1486.   if (regs_ever_live[3])
  1487.     actual_fsize += 4;
  1488.   actual_fsize = (actual_fsize + 7) & ~7;
  1489.  
  1490.   if (!TARGET_SNAKE)
  1491.     {
  1492.       for (i = 47; i >= 44; i--)
  1493.     if (regs_ever_live[i])
  1494.       {
  1495.         actual_fsize += 8;
  1496.         if (fregs_live)
  1497.           *fregs_live = 1;
  1498.       }
  1499.     }
  1500.   else
  1501.     {
  1502.       for (i = 90; i >= 72; i -= 2)
  1503.     if (regs_ever_live[i] || regs_ever_live[i + 1])
  1504.       {
  1505.         actual_fsize += 8;
  1506.         if (fregs_live)
  1507.           *fregs_live = 1;
  1508.       }
  1509.     }
  1510.   return actual_fsize + current_function_outgoing_args_size;
  1511. }
  1512.      
  1513. void
  1514. output_function_prologue (file, size, leaf_function)
  1515.      FILE *file;
  1516.      int size;
  1517.      int leaf_function;
  1518. {
  1519.   extern char call_used_regs[];
  1520.   extern int frame_pointer_needed;
  1521.   extern int current_function_returns_struct;
  1522.   int i, offset;
  1523.  
  1524.   save_fregs = 0;
  1525.   actual_fsize = compute_frame_size (size, leaf_function, &save_fregs) + 32;
  1526.   if (TARGET_SNAKE)
  1527.     actual_fsize = (actual_fsize + 63) & ~63;
  1528.  
  1529.   /* Let's not try to bullshit more than we need to here. */
  1530.   /* This might be right a lot of the time */
  1531.   fprintf (file, "\t.PROC\n\t.CALLINFO FRAME=%d", actual_fsize);
  1532.     if (regs_ever_live[2] || profile_flag)
  1533.       fprintf (file, ",CALLS,SAVE_RP\n");
  1534.     else
  1535.       fprintf (file, ",NO_CALLS\n");
  1536.   fprintf (file, "\t.ENTRY\n");
  1537.  
  1538.   /* Some registers have places to go in the current stack
  1539.      structure.  */
  1540.  
  1541.   if (regs_ever_live[2] || profile_flag)
  1542.     fprintf (file, "\tstw 2,-20(0,30)\n");
  1543.  
  1544.   /* Reserve space for local variables.  */
  1545.   if (frame_pointer_needed)
  1546.     {
  1547.       if (VAL_14_BITS_P (actual_fsize))
  1548.     fprintf (file, "\tcopy 4,1\n\tcopy 30,4\n\tstwm 1,%d(0,30)\n",
  1549.          actual_fsize);
  1550.       else
  1551.     {
  1552.       fprintf (file, "\tcopy 4,1\n\tcopy 30,4\n\tstw 1,0(0,4)\n");
  1553.       fprintf (file, "\taddil L'%d,30\n\tldo R'%d(1),30\n",
  1554.            actual_fsize, actual_fsize);
  1555.     }
  1556.     }
  1557.   else
  1558.     /* Used to be abort ();  */
  1559.     {
  1560.       if (VAL_14_BITS_P (actual_fsize))
  1561.     fprintf (file, "\tldo %d(30),30\n", actual_fsize);
  1562.       else
  1563.     fprintf (file, "\taddil L'%d,30\n\tldo R'%d(1),30\n",
  1564.          actual_fsize, actual_fsize);
  1565.     }
  1566.   /* The hppa calling conventions say that that %r19, the pic offset 
  1567.      register, is saved at sp - 32 (in this function's frame) */
  1568.   if (flag_pic)
  1569.     {
  1570.       fprintf (file, "\tstw %%r19,-32(%%r30)\n");
  1571.     }
  1572.   /* Instead of taking one argument, the counter label, as most normal
  1573.      mcounts do, _mcount appears to behave differently on the HPPA. It
  1574.      takes the return address of the caller, the address of this
  1575.      routine, and the address of the label. Also, it isn't magic, so
  1576.      argument registers have to be preserved. */
  1577.  
  1578.   if (profile_flag)
  1579.     {
  1580.       unsigned int pc_offset =
  1581.     (4 + (frame_pointer_needed
  1582.           ? (VAL_14_BITS_P (actual_fsize) ? 12 : 20)
  1583.           : (VAL_14_BITS_P (actual_fsize) ? 4 : 8)));
  1584.       int i, arg_offset;
  1585.       int basereg, offsetadj;
  1586.  
  1587.       /* When the function has a frame pointer, use that as the base 
  1588.      register for saving/restoring registers.  Else use the stack
  1589.      pointer.  Adjust the offset according to the frame size if this
  1590.      function does not have a frame pointer.  */
  1591.  
  1592.       basereg = frame_pointer_needed ? FRAME_POINTER_REGNUM
  1593.                      : STACK_POINTER_REGNUM;
  1594.       offsetadj = frame_pointer_needed ? 0 : actual_fsize;
  1595.  
  1596.       if (current_function_returns_struct)
  1597.     print_stw (file, STRUCT_VALUE_REGNUM, - 12 - offsetadj, basereg);
  1598.       for (i = 26, arg_offset = -36 - offsetadj; i >= 23; i--, arg_offset -= 4)
  1599.     if (regs_ever_live[i])
  1600.       {
  1601.         print_stw (file, i, arg_offset, basereg);
  1602.         /* It is possible for the arg_offset not to fit in 14 bits 
  1603.                when profiling a function without a frame pointer.  Deal
  1604.            with such cases.  */
  1605.         pc_offset += VAL_14_BITS_P (arg_offset) ? 4 : 8;
  1606.       }
  1607.       fprintf (file,
  1608.            "\tcopy %%r2,%%r26\n\taddil L'LP$%04d-$global$,%%r27\n\
  1609. \tldo R'LP$%04d-$global$(%%r1),%%r24\n\tbl _mcount,%%r2\n\
  1610. \tldo %d(%%r2),%%r25\n",
  1611.            hp_profile_labelno, hp_profile_labelno, -pc_offset - 12 - 8);
  1612.       for (i = 26, arg_offset = -36 - offsetadj; i >= 23; i--, arg_offset -= 4)
  1613.     if (regs_ever_live[i])
  1614.       print_ldw (file, i, arg_offset, basereg);
  1615.       if (current_function_returns_struct)
  1616.     print_ldw (file, STRUCT_VALUE_REGNUM, - 12 - offsetadj, basereg);
  1617.     }
  1618.  
  1619.   /* Normal register save. */
  1620.   if (frame_pointer_needed)
  1621.     {
  1622.       for (i = 18, offset = local_fsize; i >= 5; i--)
  1623.     if (regs_ever_live[i] && ! call_used_regs[i])
  1624.       {
  1625.         print_stw (file, i, offset, 4);  offset += 4;
  1626.       }
  1627.       if (regs_ever_live[3] && ! call_used_regs[3])
  1628.     {
  1629.       print_stw (file, 3, offset, 4);  offset += 4;
  1630.     }
  1631.     }
  1632.   else
  1633.     {
  1634.       for (i = 18, offset = local_fsize - actual_fsize; i >= 5; i--)
  1635.           if (regs_ever_live[i] && ! call_used_regs[i])
  1636.       {
  1637.         print_stw (file, i, offset, 30);  offset += 4;
  1638.       }
  1639.       if (regs_ever_live[3] && ! call_used_regs[3])
  1640.     {
  1641.       print_stw (file, 3, offset, 30);  offset += 4;
  1642.     }
  1643.     }
  1644.       
  1645.   /* Align pointer properly (doubleword boundary).  */
  1646.   offset = (offset + 7) & ~7;
  1647.  
  1648.   /* Floating point register store.  */
  1649.   if (save_fregs)
  1650.     if (frame_pointer_needed)
  1651.       {
  1652.     if (VAL_14_BITS_P (offset))
  1653.       fprintf (file, "\tldo %d(4),1\n", offset);
  1654.     else
  1655.       fprintf (file, "\taddil L'%d,4\n\tldo R'%d(1),1\n", offset, offset);
  1656.       }
  1657.     else
  1658.       {
  1659.     if (VAL_14_BITS_P (offset))
  1660.       fprintf (file, "\tldo %d(30),1\n", offset);
  1661.     else
  1662.       fprintf (file, "\taddil L'%d,30\n\tldo R'%d(1),1\n", offset, offset);
  1663.       }
  1664.   if (!TARGET_SNAKE)
  1665.     {
  1666.       for (i = 47; i >= 44; i--)
  1667.     {
  1668.       if (regs_ever_live[i])
  1669.         fprintf (file, "\tfstds,ma %s,8(0,1)\n", reg_names[i]);
  1670.     }
  1671.     }
  1672.   else
  1673.     {
  1674.       for (i = 90; i >= 72; i -= 2)
  1675.     if (regs_ever_live[i] || regs_ever_live[i + 1])
  1676.       {
  1677.         fprintf (file, "\tfstds,ma %s,8(0,1)\n", reg_names[i]);
  1678.       }
  1679.     }
  1680. }
  1681.  
  1682. void
  1683. output_function_epilogue (file, size, leaf_function)
  1684.      FILE *file;
  1685.      int size;
  1686.      int leaf_function;
  1687. {
  1688.   extern char call_used_regs[];
  1689.   extern int frame_pointer_needed;
  1690.   int  i, offset;
  1691.  
  1692.   if (frame_pointer_needed)
  1693.     {
  1694.       for (i = 18, offset = local_fsize; i >= 5; i--)
  1695.     if (regs_ever_live[i] && ! call_used_regs[i])
  1696.       {
  1697.         print_ldw (file, i, offset, 4);  offset += 4;
  1698.       }
  1699.       if (regs_ever_live[3] && ! call_used_regs[3])
  1700.     {
  1701.       print_ldw (file, 3, offset, 4);  offset += 4;      
  1702.     }
  1703.     }
  1704.   else
  1705.     {
  1706.       for (i = 18, offset = local_fsize - actual_fsize; i >= 5; i--)
  1707.           if (regs_ever_live[i] && ! call_used_regs[i])
  1708.       {
  1709.         print_ldw (file, i, offset, 30);  offset += 4;
  1710.       }
  1711.       if (regs_ever_live[3] && ! call_used_regs[3])
  1712.     {
  1713.       print_ldw (file, 3, offset, 30);  offset += 4;
  1714.     }
  1715.     }
  1716.       
  1717.   /* Align pointer properly (doubleword boundary).  */
  1718.   offset = (offset + 7) & ~7;
  1719.  
  1720.   /* Floating point register restore.  */
  1721.   if (save_fregs)
  1722.     if (frame_pointer_needed)
  1723.       {
  1724.     if (VAL_14_BITS_P (offset))
  1725.       fprintf (file, "\tldo %d(4),1\n", offset);
  1726.     else
  1727.       fprintf (file, "\taddil L'%d,4\n\tldo R'%d(1),1\n", offset, offset);
  1728.       }
  1729.     else
  1730.       {
  1731.     if (VAL_14_BITS_P (offset))
  1732.       fprintf (file, "\tldo %d(30),1\n", offset);
  1733.     else
  1734.       fprintf (file, "\taddil L'%d,30\n\tldo R'%d(1),1\n", offset, offset);
  1735.       }
  1736.   if (!TARGET_SNAKE)
  1737.     {
  1738.       for (i = 47; i >= 44; i--)
  1739.     {
  1740.       if (regs_ever_live[i])
  1741.         fprintf (file, "\tfldds,ma 8(0,1),%s\n", reg_names[i]);
  1742.     }
  1743.     }
  1744.   else
  1745.     {
  1746.       for (i = 90; i >= 72; i -= 2)
  1747.     if (regs_ever_live[i] || regs_ever_live[i + 1])
  1748.       {
  1749.         fprintf (file, "\tfldds,ma 8(0,1),%s\n", reg_names[i]);
  1750.       }
  1751.     }
  1752.   /* Reset stack pointer (and possibly frame pointer).  The stack */
  1753.   /* pointer is initially set to fp + 8 to avoid a race condition. */
  1754.   if (frame_pointer_needed)
  1755.     {
  1756.       fprintf (file, "\tldo 8(4),30\n");
  1757.       if (regs_ever_live[2] || profile_flag)
  1758.     fprintf (file, "\tldw -28(0,30),2\n");
  1759.       fprintf (file, "\tbv 0(2)\n\tldwm -8(30),4\n");
  1760.     }
  1761.   else if (actual_fsize)
  1762.     {
  1763.       if ((regs_ever_live[2] || profile_flag)
  1764.           && VAL_14_BITS_P (actual_fsize + 20))
  1765.     fprintf (file, "\tldw %d(30),2\n\tbv 0(2)\n\tldo %d(30),30\n",
  1766.          -(actual_fsize + 20), -actual_fsize);
  1767.       else if (regs_ever_live[2] || profile_flag)
  1768.     fprintf (file,
  1769.          "\taddil L'%d,30\n\tldw %d(1),2\n\tbv 0(2)\n\tldo R'%d(1),30\n",
  1770.          - actual_fsize,
  1771.          - (actual_fsize + 20 + ((-actual_fsize) & ~0x7ff)),
  1772.          /* - ((actual_fsize + 20) - (actual_fsize & ~0x7ff)), */
  1773.          - actual_fsize);
  1774.       else if (VAL_14_BITS_P (actual_fsize))
  1775.     fprintf (file, "\tbv 0(2)\n\tldo %d(30),30\n", - actual_fsize);
  1776.       else
  1777.     fprintf (file, "\taddil L'%d,30\n\tbv 0(2)\n\tldo R'%d(1),30\n");
  1778.     }
  1779.   else if (current_function_epilogue_delay_list)
  1780.     {
  1781.       fprintf (file, "\tbv 0(2)\n");
  1782.       final_scan_insn (XEXP (current_function_epilogue_delay_list, 0),
  1783.                file, write_symbols, 1, 0, 1);
  1784.     }
  1785.   else
  1786.     fprintf (file, "\tbv,n 0(2)\n");
  1787.   fprintf (file, "\t.EXIT\n\t.PROCEND\n");
  1788. }
  1789.  
  1790. rtx
  1791. gen_compare_reg (code, x, y)
  1792.      enum rtx_code code;
  1793.      rtx x, y;
  1794. {
  1795.   enum machine_mode mode = SELECT_CC_MODE (code, x, y);
  1796.   rtx cc_reg = gen_rtx (REG, mode, 0);
  1797.  
  1798.   emit_insn (gen_rtx (SET, VOIDmode, cc_reg,
  1799.               gen_rtx (COMPARE, mode, x, y)));
  1800.  
  1801.   return cc_reg;
  1802. }
  1803.  
  1804. /* Return nonzero if TRIAL can go into the function epilogue's
  1805.    delay slot.  SLOT is the slot we are trying to fill.  */
  1806.  
  1807. int
  1808. eligible_for_epilogue_delay (trial, slot)
  1809.      rtx trial;
  1810.      int slot;
  1811. {
  1812.   if (slot >= 1)
  1813.     return 0;
  1814.   if (GET_CODE (trial) != INSN
  1815.       || GET_CODE (PATTERN (trial)) != SET)
  1816.     return 0;
  1817.   if (get_attr_length (trial) != 1)
  1818.     return 0;
  1819.   return (leaf_function &&
  1820.       get_attr_in_branch_delay (trial) == IN_BRANCH_DELAY_TRUE);
  1821. }
  1822.  
  1823. rtx
  1824. gen_scond_fp (code, operand0)
  1825.      enum rtx_code code;
  1826.      rtx operand0;
  1827. {
  1828.   return gen_rtx (SET, VOIDmode, operand0,
  1829.           gen_rtx (code, CCFPmode,
  1830.                gen_rtx (REG, CCFPmode, 0), const0_rtx));
  1831. }
  1832.  
  1833. void
  1834. emit_bcond_fp (code, operand0)
  1835.      enum rtx_code code;
  1836.      rtx operand0;
  1837. {
  1838.   emit_jump_insn (gen_rtx (SET, VOIDmode, pc_rtx,
  1839.                gen_rtx (IF_THEN_ELSE, VOIDmode,
  1840.                     gen_rtx (code, VOIDmode, 
  1841.                          gen_rtx (REG, CCFPmode, 0),
  1842.                          const0_rtx),
  1843.                     gen_rtx (LABEL_REF, VOIDmode, operand0),
  1844.                     pc_rtx)));
  1845.  
  1846. }
  1847.  
  1848. rtx
  1849. gen_cmp_fp (code, operand0, operand1)
  1850.      enum rtx_code code;
  1851.      rtx operand0, operand1;
  1852. {
  1853.   return gen_rtx (SET, VOIDmode, gen_rtx (REG, CCFPmode, 0),
  1854.           gen_rtx (code, CCFPmode, operand0, operand1));
  1855. }
  1856.  
  1857.  
  1858. /* Print operand X (an rtx) in assembler syntax to file FILE.
  1859.    CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
  1860.    For `%' followed by punctuation, CODE is the punctuation and X is null.  */
  1861.  
  1862. void
  1863. print_operand (file, x, code)
  1864.      FILE *file;
  1865.      rtx x;
  1866.      int code;
  1867. {
  1868.   switch (code)
  1869.     {
  1870.     case '#':
  1871.       /* Output a 'nop' if there's nothing for the delay slot.  */
  1872.       if (dbr_sequence_length () == 0)
  1873.     fputs ("\n\tnop", file);
  1874.       return;
  1875.     case '*':
  1876.       /* Output an nullification completer if there's nothing for the */
  1877.       /* delay slot or nullification is requested.  */ 
  1878.       if (dbr_sequence_length () == 0 ||
  1879.       (final_sequence &&
  1880.        INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))))
  1881.         fputs (",n", file);
  1882.       return;
  1883.     case 'R':
  1884.       /* Print out the second register name of a register pair.
  1885.      I.e., R (6) => 7.  */
  1886.       fputs (reg_names[REGNO (x)+1], file);
  1887.       return;
  1888.     case 'r':
  1889.       /* A register or zero. */
  1890.       if (x == const0_rtx)
  1891.     {
  1892.       fputs ("0", file);
  1893.       return;
  1894.     }
  1895.       else
  1896.     break;
  1897.     case 'O':
  1898.       switch (GET_CODE (x))
  1899.     {
  1900.     case PLUS:
  1901.       fprintf (file, "add%s",
  1902.            GET_CODE (XEXP (x, 1)) == CONST_INT ? "i" : "");  break;
  1903.     case MINUS:
  1904.       fprintf (file, "sub%s",
  1905.            GET_CODE (XEXP (x, 0)) == CONST_INT ? "i" : "");  break;
  1906.     case AND:
  1907.       fprintf (file, "and%s",
  1908.            GET_CODE (XEXP (x, 1)) == NOT ? "cm" : "");  break;
  1909.     case IOR:
  1910.       fprintf (file, "or");  break;
  1911.     case XOR:
  1912.       fprintf (file, "xor");  break;
  1913.     case ASHIFT:
  1914.       fprintf (file, "sh%dadd", INTVAL (XEXP (x, 1)));  break;
  1915.       /* Too lazy to handle bitfield conditions yet.  */
  1916.     default:
  1917.       printf ("Can't grok '%c' operator:\n", code);
  1918.       debug_rtx (x);
  1919.       abort ();
  1920.     }
  1921.       return;
  1922.     case 'C':
  1923.     case 'X':
  1924.       switch (GET_CODE (x))
  1925.     {    
  1926.     case EQ:
  1927.       fprintf (file, "=");  break;
  1928.     case NE:
  1929.       if (code == 'C')
  1930.         fprintf (file, "<>");
  1931.       else
  1932.         fprintf (file, "!=");
  1933.       break;
  1934.     case GT:
  1935.       fprintf (file, ">");  break;
  1936.     case GE:
  1937.       fprintf (file, ">=");  break;
  1938.     case GEU:
  1939.       fprintf (file, ">>=");  break;
  1940.     case GTU:
  1941.       fprintf (file, ">>");  break;
  1942.     case LT:
  1943.       fprintf (file, "<");  break;
  1944.     case LE:
  1945.       fprintf (file, "<=");  break;
  1946.     case LEU:
  1947.       fprintf (file, "<<=");  break;
  1948.     case LTU:
  1949.       fprintf (file, "<<");  break;
  1950.     default:
  1951.       printf ("Can't grok '%c' operator:\n", code);
  1952.       debug_rtx (x);
  1953.       abort ();
  1954.     }
  1955.       return;
  1956.     case 'N':
  1957.     case 'Y':
  1958.       switch (GET_CODE (x))
  1959.     {
  1960.     case EQ:
  1961.       if (code == 'N')
  1962.         fprintf (file, "<>");
  1963.       else
  1964.         fprintf (file, "!=");
  1965.       break;
  1966.     case NE:
  1967.       fprintf (file, "=");  break;
  1968.     case GT:
  1969.       fprintf (file, "<=");  break;
  1970.     case GE:
  1971.       fprintf (file, "<");  break;
  1972.     case GEU:
  1973.       fprintf (file, "<<");  break;
  1974.     case GTU:
  1975.       fprintf (file, "<<=");  break;
  1976.     case LT:
  1977.       fprintf (file, ">=");  break;
  1978.     case LE:
  1979.       fprintf (file, ">");  break;
  1980.     case LEU:
  1981.       fprintf (file, ">>");  break;
  1982.     case LTU:
  1983.       fprintf (file, ">>=");  break;
  1984.     default:
  1985.       printf ("Can't grok '%c' operator:\n", code);
  1986.       debug_rtx (x);
  1987.       abort ();
  1988.     }
  1989.       return;
  1990.     case 'M':
  1991.       switch (GET_CODE (XEXP (x, 0)))
  1992.     {
  1993.     case PRE_DEC:
  1994.     case PRE_INC:
  1995.       fprintf (file, "s,mb");
  1996.       break;
  1997.     case POST_DEC:
  1998.     case POST_INC:
  1999.       fprintf (file, "s,ma");
  2000.       break;
  2001.     default:
  2002.       break;
  2003.     }
  2004.       return;
  2005.     case 'F':
  2006.       switch (GET_CODE (XEXP (x, 0)))
  2007.     {
  2008.     case PRE_DEC:
  2009.     case PRE_INC:
  2010.       fprintf (file, ",mb");
  2011.       break;
  2012.     case POST_DEC:
  2013.     case POST_INC:
  2014.       fprintf (file, ",ma");
  2015.       break;
  2016.     default:
  2017.       break;
  2018.     }
  2019.       return;
  2020.     case 'G':
  2021.       output_global_address (file, x);
  2022.       return;
  2023.     case 0:            /* Don't do anything special */
  2024.       break;
  2025.     default:
  2026.       abort ();
  2027.     }
  2028.   if (GET_CODE (x) == REG)
  2029.     fprintf (file, "%s", reg_names [REGNO (x)]);
  2030.   else if (GET_CODE (x) == MEM)
  2031.     {
  2032.       int size = GET_MODE_SIZE (GET_MODE (x));
  2033.       rtx base = XEXP (XEXP (x, 0), 0);
  2034.       switch (GET_CODE (XEXP (x, 0)))
  2035.     {
  2036.     case PRE_DEC:
  2037.     case POST_DEC:
  2038.       fprintf (file, "-%d(0,%s)", size, reg_names [REGNO (base)]);
  2039.       break;
  2040.     case PRE_INC:
  2041.     case POST_INC:
  2042.       fprintf (file, "%d(0,%s)", size, reg_names [REGNO (base)]);
  2043.       break;
  2044.     default:
  2045.       output_address (XEXP (x, 0));
  2046.       break;
  2047.     }
  2048.     }
  2049.   else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode)
  2050.     {
  2051.       union { double d; int i[2]; } u;
  2052.       union { float f; int i; } u1;
  2053.       u.i[0] = XINT (x, 0); u.i[1] = XINT (x, 1);
  2054.       u1.f = u.d;
  2055.       if (code == 'f')
  2056.     fprintf (file, "0r%.9g", u1.f);
  2057.       else
  2058.     fprintf (file, "0x%x", u1.i);
  2059.     }
  2060.   else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != DImode)
  2061.     {
  2062.       union { double d; int i[2]; } u;
  2063.       u.i[0] = XINT (x, 0); u.i[1] = XINT (x, 1);
  2064.       fprintf (file, "0r%.20g", u.d);
  2065.     }
  2066.   else
  2067.     output_addr_const (file, x);
  2068. }
  2069.  
  2070. /* output a SYMBOL_REF or a CONST expression involving a SYMBOL_REF. */
  2071.  
  2072. void
  2073. output_global_address (file, x)
  2074.      FILE *file;
  2075.      rtx x;
  2076. {
  2077.   if (GET_CODE (x) == SYMBOL_REF && read_only_operand (x))
  2078.     assemble_name (file, XSTR (x, 0));
  2079.   else if (GET_CODE (x) == SYMBOL_REF)
  2080.     {
  2081.       assemble_name (file, XSTR (x, 0));
  2082.       fprintf (file, "-$global$");
  2083.     }
  2084.   else if (GET_CODE (x) == CONST)
  2085.     {
  2086.       char *sep = "";
  2087.       int offset = 0;        /* assembler wants -$global$ at end */
  2088.       rtx base;
  2089.       
  2090.       if (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF)
  2091.     {
  2092.       base = XEXP (XEXP (x, 0), 0);
  2093.       output_addr_const (file, base);
  2094.     }
  2095.       else if (GET_CODE (XEXP (XEXP (x, 0), 0)) == CONST_INT)
  2096.     offset = INTVAL (XEXP (XEXP (x, 0), 0));
  2097.       else abort ();
  2098.  
  2099.       if (GET_CODE (XEXP (XEXP (x, 0), 1)) == SYMBOL_REF)
  2100.     {
  2101.       base = XEXP (XEXP (x, 0), 1);
  2102.       output_addr_const (file, base);
  2103.     }
  2104.       else if (GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
  2105.     offset = INTVAL (XEXP (XEXP (x, 0),1));
  2106.       else abort ();
  2107.  
  2108.       if (GET_CODE (XEXP (x, 0)) == PLUS)
  2109.     {
  2110.       if (offset < 0)
  2111.         {
  2112.           offset = -offset;
  2113.           sep = "-";
  2114.         }
  2115.       else
  2116.         sep = "+";
  2117.     }
  2118.       else if (GET_CODE (XEXP (x, 0)) == MINUS
  2119.            && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF))
  2120.     sep = "-";
  2121.       else abort ();
  2122.  
  2123.       if (!read_only_operand (base))
  2124.     fprintf (file, "-$global$");
  2125.       fprintf (file, "%s", sep);
  2126.       if (offset) fprintf (file,"%d", offset);
  2127.     }
  2128.   else
  2129.     output_addr_const (file, x);
  2130. }
  2131.  
  2132. /* MEM rtls here are never SYMBOL_REFs (I think), so fldws is safe. */
  2133.  
  2134. char *
  2135. output_floatsisf2 (operands)
  2136.      rtx *operands;
  2137. {
  2138.   if (GET_CODE (operands[1]) == MEM)
  2139.     return "fldws %1,%0\n\tfcnvxf,sgl,sgl %0,%0";
  2140.   else if (FP_REG_P (operands[1]))
  2141.     return "fcnvxf,sgl,sgl %1,%0";
  2142.   return "stwm %r1,4(0,30)\n\tfldws,mb -4(0,30),%0\n\tfcnvxf,sgl,sgl %0,%0";
  2143. }
  2144.  
  2145. char *
  2146. output_floatsidf2 (operands)
  2147.      rtx *operands;
  2148. {
  2149.   if (GET_CODE (operands[1]) == MEM)
  2150.     return "fldws %1,%0\n\tfcnvxf,sgl,dbl %0,%0";
  2151.   else if (FP_REG_P (operands[1]))
  2152.     return "fcnvxf,sgl,dbl %1,%0";
  2153.   return "stwm %r1,4(0,30)\n\tfldws,mb -4(0,30),%0\n\tfcnvxf,sgl,dbl %0,%0";
  2154. }
  2155.  
  2156. enum rtx_code
  2157. reverse_relop (code)
  2158.      enum rtx_code code;
  2159. {
  2160.   switch (code)
  2161.     {
  2162.     case GT:
  2163.       return LT;
  2164.     case LT:
  2165.       return GT;
  2166.     case GE:
  2167.       return LE;
  2168.     case LE:
  2169.       return GE;
  2170.     case LTU:
  2171.       return GTU;
  2172.     case GTU:
  2173.       return LTU;
  2174.     case GEU:
  2175.       return LEU;
  2176.     case LEU:
  2177.       return GEU;
  2178.     default:
  2179.       abort ();
  2180.     }
  2181. }
  2182.  
  2183. /* HP's millicode routines mean something special to the assembler.
  2184.    Keep track of which ones we have used.  */
  2185.  
  2186. enum millicodes { remI, remU, divI, divU, mulI, mulU, end1000 };
  2187. static char imported[(int)end1000];
  2188. static char *milli_names[] = {"remI", "remU", "divI", "divU", "mulI", "mulU"};
  2189. static char import_string[] = ".IMPORT $$....,MILLICODE";
  2190. #define MILLI_START 10
  2191.  
  2192. static int
  2193. import_milli (code)
  2194.      enum millicodes code;
  2195. {
  2196.   char str[sizeof (import_string)];
  2197.   
  2198.   if (!imported[(int)code])
  2199.     {
  2200.       imported[(int)code] = 1;
  2201.       strcpy (str, import_string);
  2202.       strncpy (str + MILLI_START, milli_names[(int)code], 4);
  2203.       output_asm_insn (str, 0);
  2204.     }
  2205. }
  2206.  
  2207. /* The register constraints have put the operands and return value in 
  2208.    the proper registers. */
  2209.  
  2210. char *
  2211. output_mul_insn (unsignedp)
  2212.      int unsignedp;
  2213. {
  2214.   if (unsignedp)
  2215.     {
  2216.       import_milli (mulU);
  2217.       return "bl $$mulU,31%#";
  2218.     }
  2219.   else
  2220.     {
  2221.       import_milli (mulI);
  2222.       return "bl $$mulI,31%#";
  2223.     }
  2224. }
  2225.  
  2226. /* If operands isn't NULL, then it's a CONST_INT with which we can do
  2227.    something */
  2228.  
  2229.  
  2230. /* Emit the rtl for doing a division by a constant. */
  2231.  
  2232.  /* Do magic division millicodes exist for this value? */
  2233.  
  2234. static int magic_milli[]= {0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0,
  2235.                  1, 1};
  2236.  
  2237. /* We'll use an array to keep track of the magic millicodes and 
  2238.    whether or not we've used them already. [n][0] is signed, [n][1] is
  2239.    unsigned. */
  2240.  
  2241.  
  2242. static int div_milli[16][2];
  2243.  
  2244. int
  2245. div_operand (op, mode)
  2246.      rtx op;
  2247.      enum machine_mode mode;
  2248. {
  2249.   return (mode == SImode
  2250.       && ((GET_CODE (op) == REG && REGNO (op) == 25)
  2251.           || (GET_CODE (op) == CONST_INT && INTVAL (op) > 0
  2252.           && INTVAL (op) < 16 && magic_milli[INTVAL (op)])));
  2253. }
  2254.  
  2255. int
  2256. emit_hpdiv_const (operands, unsignedp)
  2257.      rtx *operands;
  2258.      int unsignedp;
  2259. {
  2260.   if (GET_CODE (operands[2]) == CONST_INT
  2261.       && INTVAL (operands[2]) > 0
  2262.       && INTVAL (operands[2]) < 16
  2263.       && magic_milli[INTVAL (operands[2])])
  2264.     {
  2265.       emit_move_insn ( gen_rtx (REG, SImode, 26), operands[1]);
  2266.       emit
  2267.     (gen_rtx
  2268.      (PARALLEL, VOIDmode,
  2269.       gen_rtvec (5, gen_rtx (SET, VOIDmode, gen_rtx (REG, SImode, 29),
  2270.                  gen_rtx (unsignedp ? UDIV : DIV, SImode,
  2271.                       gen_rtx (REG, SImode, 26),
  2272.                       operands[2])),
  2273.              gen_rtx (CLOBBER, VOIDmode, gen_rtx (SCRATCH, SImode, 0)),
  2274.              gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 26)),
  2275.              gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 25)),
  2276.              gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 31)))));
  2277.       emit_move_insn (operands[0], gen_rtx (REG, SImode, 29));
  2278.       return 1;
  2279.     }
  2280.   return 0;
  2281. }
  2282.  
  2283. char *
  2284. output_div_insn (operands, unsignedp)
  2285.      rtx *operands;
  2286.      int unsignedp;
  2287. {
  2288.   int divisor;
  2289.   
  2290.   /* If the divisor is a constant, try to use one of the special 
  2291.      opcodes .*/
  2292.   if (GET_CODE (operands[0]) == CONST_INT)
  2293.     {
  2294.       divisor = INTVAL (operands[0]);
  2295.       if (!div_milli[divisor][unsignedp])
  2296.     {
  2297.       if (unsignedp)
  2298.         output_asm_insn (".IMPORT $$divU_%0,MILLICODE", operands);
  2299.       else
  2300.         output_asm_insn (".IMPORT $$divI_%0,MILLICODE", operands);
  2301.       div_milli[divisor][unsignedp] = 1;
  2302.     }
  2303.       if (unsignedp)
  2304.     return "bl $$divU_%0,31%#";
  2305.       return "bl $$divI_%0,31%#";
  2306.     }
  2307.   /* Divisor isn't a special constant. */
  2308.   else
  2309.     {
  2310.       if (unsignedp)
  2311.     {
  2312.       import_milli (divU);
  2313.       return "bl $$divU,31%#";
  2314.     }
  2315.       else
  2316.     {
  2317.       import_milli (divI);
  2318.       return "bl $$divI,31%#";
  2319.     }
  2320.     }
  2321. }
  2322.  
  2323. /* Output a $$rem millicode to do mod. */
  2324.  
  2325. char *
  2326. output_mod_insn (unsignedp)
  2327.      int unsignedp;
  2328. {
  2329.   if (unsignedp)
  2330.     {
  2331.       import_milli (remU);
  2332.       return "bl $$remU,31%#";
  2333.     }
  2334.   else
  2335.     {
  2336.       import_milli (remI);
  2337.       return "bl $$remI,31%#";
  2338.     }
  2339. }
  2340.  
  2341. void
  2342. output_arg_descriptor (insn)
  2343.      rtx insn;
  2344. {
  2345.   char *arg_regs[4];
  2346.   enum machine_mode arg_mode;
  2347.   rtx prev_insn;
  2348.   int i, output_flag = 0;
  2349.   int regno;
  2350.   
  2351.   for (i = 0; i < 4; i++)
  2352.     arg_regs[i] = 0;
  2353.  
  2354.   for (prev_insn = PREV_INSN (insn); GET_CODE (prev_insn) == INSN;
  2355.        prev_insn = PREV_INSN (prev_insn))
  2356.     {
  2357.       if (!(GET_CODE (PATTERN (prev_insn)) == USE &&
  2358.         GET_CODE (XEXP (PATTERN (prev_insn), 0)) == REG &&
  2359.         FUNCTION_ARG_REGNO_P (REGNO (XEXP (PATTERN (prev_insn), 0)))))
  2360.     break;
  2361.       arg_mode = GET_MODE (XEXP (PATTERN (prev_insn), 0));
  2362.       regno = REGNO (XEXP (PATTERN (prev_insn), 0));
  2363.       if (regno >= 23 && regno <= 26)
  2364.     {
  2365.       arg_regs[26 - regno] = "GR";
  2366.       if (arg_mode == DImode)
  2367.         arg_regs[25 - regno] = "GR";
  2368.     }
  2369.       else if (!TARGET_SNAKE)    /* fp args */
  2370.     {
  2371.       if (arg_mode == SFmode)
  2372.         arg_regs[regno - 36] = "FR";
  2373.       else
  2374.         {
  2375. #ifdef HP_FP_ARG_DESCRIPTOR_REVERSED
  2376.           arg_regs[regno - 37] = "FR";
  2377.           arg_regs[regno - 36] = "FU";
  2378. #else
  2379.           arg_regs[regno - 37] = "FU";
  2380.           arg_regs[regno - 36] = "FR";
  2381. #endif
  2382.         }
  2383.     }
  2384.       else
  2385.     {
  2386.       if (arg_mode == SFmode)
  2387.         arg_regs[(regno - 56) / 2] = "FR";
  2388.       else
  2389.         {
  2390. #ifdef HP_FP_ARG_DESCRIPTOR_REVERSED
  2391.           arg_regs[(regno - 58) / 2] = "FR";
  2392.           arg_regs[(regno - 58) / 2 + 1] = "FU";
  2393. #else
  2394.           arg_regs[(regno - 58) / 2] = "FU";
  2395.           arg_regs[(regno - 58) / 2 + 1] = "FR";
  2396. #endif
  2397.         }
  2398.     }
  2399.     }
  2400.   fputs ("\t.CALL ", asm_out_file);
  2401.   for (i = 0; i < 4; i++)
  2402.     {
  2403.       if (arg_regs[i])
  2404.     {
  2405.       if (output_flag++)
  2406.         fputc (',', asm_out_file);
  2407.       fprintf (asm_out_file, "ARGW%d=%s", i, arg_regs[i]);
  2408.     }
  2409.     }
  2410.   fputc ('\n', asm_out_file);
  2411. }
  2412.  
  2413. /* Memory loads/stores to/from the shift need to go through
  2414.    the general registers.  */
  2415.  
  2416. enum reg_class
  2417. secondary_reload_class (class, mode, in)
  2418.      enum reg_class class;
  2419.      enum machine_mode mode;
  2420.      rtx in;
  2421. {
  2422.   int regno = true_regnum (in);
  2423.  
  2424.   if ((TARGET_SHARED_LIBS && function_label_operand (in, mode))
  2425.       || ((regno >= FIRST_PSEUDO_REGISTER || regno == -1)
  2426.       && ((mode == QImode || mode == HImode || mode == SImode
  2427.            || mode == DImode) 
  2428.           && (class == FP_REGS || class == SNAKE_FP_REGS
  2429.           || class == HI_SNAKE_FP_REGS)))
  2430.       || (class == SHIFT_REGS && (regno <= 0 || regno >= 32)))
  2431.     return GENERAL_REGS;
  2432.  
  2433.   return NO_REGS;
  2434. }
  2435.  
  2436. enum direction
  2437. function_arg_padding (mode, type)
  2438.      enum machine_mode mode;
  2439.      tree type;
  2440. {
  2441.   int size;
  2442.  
  2443.   if (mode == BLKmode)
  2444.     {
  2445.       if (type && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
  2446.     size = int_size_in_bytes (type) * BITS_PER_UNIT;
  2447.       else
  2448.     return upward;        /* Don't know if this is right, but */
  2449.                 /* same as old definition. */
  2450.     }
  2451.   else
  2452.     size = GET_MODE_BITSIZE (mode);
  2453.   if (size < PARM_BOUNDARY)
  2454.     return downward;
  2455.   else if (size % PARM_BOUNDARY)
  2456.     return upward;
  2457.   else
  2458.     return none;
  2459. }
  2460.  
  2461.  
  2462. /* Do what is necessary for `va_start'.  The argument is ignored;
  2463.    We look at the current function to determine if stdargs or varargs
  2464.    is used and fill in an initial va_list.  A pointer to this constructor
  2465.    is returned.  */
  2466.  
  2467. struct rtx_def *
  2468. hppa_builtin_saveregs (arglist)
  2469.      tree arglist;
  2470. {
  2471.   rtx block, float_addr, offset, float_mem;
  2472.   tree fntype = TREE_TYPE (current_function_decl);
  2473.   int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
  2474.            && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
  2475.                != void_type_node)))
  2476.         ? UNITS_PER_WORD : 0);
  2477.  
  2478.   if (argadj)
  2479.     offset = plus_constant (current_function_arg_offset_rtx, argadj);
  2480.   else
  2481.     offset = current_function_arg_offset_rtx;
  2482.  
  2483.   /* Store general registers on the stack. */
  2484.   move_block_from_reg (23,
  2485.                gen_rtx (MEM, BLKmode,
  2486.                 plus_constant
  2487.                 (current_function_internal_arg_pointer, -16)),
  2488.                4); 
  2489.   return copy_to_reg (expand_binop (Pmode, add_optab,
  2490.                     current_function_internal_arg_pointer,
  2491.                     offset, 0, 0, OPTAB_LIB_WIDEN));
  2492. }
  2493.  
  2494. extern struct obstack *saveable_obstack;
  2495.  
  2496. /* In HPUX 8.0's shared library scheme, special relocations are needed
  2497.    for function labels if they might be passed to a function 
  2498.    in a shared library (because shared libraries don't live in code
  2499.    space), and special magic is needed to construct their address. */
  2500.  
  2501. void
  2502. hppa_encode_label (sym)
  2503.      rtx sym;
  2504. {
  2505.   char *str = XSTR (sym, 0);
  2506.   int len = strlen (str);
  2507.   char *newstr = obstack_alloc (saveable_obstack, len + 2) ;
  2508.  
  2509.   if (str[0] == '*')
  2510.     *newstr++ = *str++;
  2511.   strcpy (newstr + 1, str);
  2512.   *newstr = '@';
  2513.   XSTR (sym,0) = newstr;
  2514. }
  2515.   
  2516. int
  2517. function_label_operand  (op, mode)
  2518.      rtx op;
  2519.      enum machine_mode mode;
  2520. {
  2521.   return GET_CODE (op) == SYMBOL_REF && FUNCTION_NAME_P (XSTR (op, 0));
  2522. }
  2523.  
  2524. /* Return 1 if OP is suitable for the second add operand (the unshifed 
  2525.    operand) in an shadd instruction.   Allow CONST_INT to work around
  2526.    a reload bug.  */
  2527. int
  2528. shadd_operand (op, mode)
  2529.      rtx op;
  2530.      enum machine_mode mode;
  2531. {
  2532.   if (GET_CODE (op) == REG)
  2533.     return 1;
  2534.   if (GET_CODE (op) == CONST_INT)
  2535.     return 1;
  2536.   return 0;
  2537. }
  2538.