• Main Page
  • Modules
  • Data Types
  • Files

osprey/kg++fe/gnu/config/pa/pa.c

Go to the documentation of this file.
00001 /* Subroutines for insn-output.c for HPPA.
00002    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
00003    2002, 2003 Free Software Foundation, Inc.
00004    Contributed by Tim Moore (moore@cs.utah.edu), based on sparc.c
00005 
00006 This file is part of GNU CC.
00007 
00008 GNU CC is free software; you can redistribute it and/or modify
00009 it under the terms of the GNU General Public License as published by
00010 the Free Software Foundation; either version 2, or (at your option)
00011 any later version.
00012 
00013 GNU CC is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 GNU General Public License for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with GNU CC; see the file COPYING.  If not, write to
00020 the Free Software Foundation, 59 Temple Place - Suite 330,
00021 Boston, MA 02111-1307, USA.  */
00022 
00023 #include "config.h"
00024 #include "system.h"
00025 #include "rtl.h"
00026 #include "regs.h"
00027 #include "hard-reg-set.h"
00028 #include "real.h"
00029 #include "insn-config.h"
00030 #include "conditions.h"
00031 #include "output.h"
00032 #include "insn-attr.h"
00033 #include "flags.h"
00034 #include "tree.h"
00035 #include "expr.h"
00036 #include "optabs.h"
00037 #include "libfuncs.h"
00038 #include "reload.h"
00039 #include "c-tree.h"
00040 #include "integrate.h"
00041 #include "function.h"
00042 #include "obstack.h"
00043 #include "toplev.h"
00044 #include "ggc.h"
00045 #include "recog.h"
00046 #include "tm_p.h"
00047 #include "target.h"
00048 #include "target-def.h"
00049 
00050 #ifndef DO_FRAME_NOTES
00051 #ifdef INCOMING_RETURN_ADDR_RTX
00052 #define DO_FRAME_NOTES 1
00053 #else
00054 #define DO_FRAME_NOTES 0
00055 #endif
00056 #endif
00057 
00058 #if DO_FRAME_NOTES
00059 #define FRP(INSN) \
00060   do          \
00061     {         \
00062       rtx insn = INSN;      \
00063       RTX_FRAME_RELATED_P (insn) = 1; \
00064     }         \
00065   while (0)
00066 #else
00067 #define FRP(INSN) INSN
00068 #endif
00069 
00070 static inline rtx force_mode PARAMS ((enum machine_mode, rtx));
00071 static void pa_combine_instructions PARAMS ((rtx));
00072 static int pa_can_combine_p PARAMS ((rtx, rtx, rtx, int, rtx, rtx, rtx));
00073 static int forward_branch_p PARAMS ((rtx));
00074 static int shadd_constant_p PARAMS ((int));
00075 static void pa_add_gc_roots PARAMS ((void));
00076 static void mark_deferred_plabels PARAMS ((void *));
00077 static void compute_zdepwi_operands PARAMS ((unsigned HOST_WIDE_INT, unsigned *));
00078 static int compute_movstrsi_length PARAMS ((rtx));
00079 static bool pa_assemble_integer PARAMS ((rtx, unsigned int, int));
00080 static void remove_useless_addtr_insns PARAMS ((rtx, int));
00081 static void store_reg PARAMS ((int, int, int));
00082 static void load_reg PARAMS ((int, int, int));
00083 static void set_reg_plus_d PARAMS ((int, int, int));
00084 static rtx get_last_nonnote_insn PARAMS ((void));
00085 static void pa_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
00086 static int pa_adjust_cost PARAMS ((rtx, rtx, rtx, int));
00087 static int pa_adjust_priority PARAMS ((rtx, int));
00088 static int pa_issue_rate PARAMS ((void));
00089 
00090 /* Save the operands last given to a compare for use when we
00091    generate a scc or bcc insn.  */
00092 
00093 rtx hppa_compare_op0, hppa_compare_op1;
00094 enum cmp_type hppa_branch_type;
00095 
00096 /* Which cpu we are scheduling for.  */
00097 enum processor_type pa_cpu;
00098 
00099 /* String to hold which cpu we are scheduling for.  */
00100 const char *pa_cpu_string;
00101 
00102 /* Which architecture we are generating code for.  */
00103 enum architecture_type pa_arch;
00104 
00105 /* String to hold which architecture we are generating code for.  */
00106 const char *pa_arch_string;
00107 
00108 /* Counts for the number of callee-saved general and floating point
00109    registers which were saved by the current function's prologue.  */
00110 static int gr_saved, fr_saved;
00111 
00112 static rtx find_addr_reg PARAMS ((rtx));
00113 
00114 /* Keep track of the number of bytes we have output in the CODE subspaces
00115    during this compilation so we'll know when to emit inline long-calls.  */
00116 
00117 unsigned int total_code_bytes;
00118 
00119 /* Variables to handle plabels that we discover are necessary at assembly
00120    output time.  They are output after the current function.  */
00121 
00122 struct deferred_plabel
00123 {
00124   rtx internal_label;
00125   char *name;
00126 } *deferred_plabels = 0;
00127 int n_deferred_plabels = 0;
00128 
00129 /* Initialize the GCC target structure.  */
00130 
00131 #undef TARGET_ASM_ALIGNED_HI_OP
00132 #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
00133 #undef TARGET_ASM_ALIGNED_SI_OP
00134 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
00135 #undef TARGET_ASM_ALIGNED_DI_OP
00136 #define TARGET_ASM_ALIGNED_DI_OP "\t.dword\t"
00137 #undef TARGET_ASM_UNALIGNED_HI_OP
00138 #define TARGET_ASM_UNALIGNED_HI_OP TARGET_ASM_ALIGNED_HI_OP
00139 #undef TARGET_ASM_UNALIGNED_SI_OP
00140 #define TARGET_ASM_UNALIGNED_SI_OP TARGET_ASM_ALIGNED_SI_OP
00141 #undef TARGET_ASM_UNALIGNED_DI_OP
00142 #define TARGET_ASM_UNALIGNED_DI_OP TARGET_ASM_ALIGNED_DI_OP
00143 #undef TARGET_ASM_INTEGER
00144 #define TARGET_ASM_INTEGER pa_assemble_integer
00145 
00146 #undef TARGET_ASM_FUNCTION_PROLOGUE
00147 #define TARGET_ASM_FUNCTION_PROLOGUE pa_output_function_prologue
00148 #undef TARGET_ASM_FUNCTION_EPILOGUE
00149 #define TARGET_ASM_FUNCTION_EPILOGUE pa_output_function_epilogue
00150 
00151 #undef TARGET_SCHED_ADJUST_COST
00152 #define TARGET_SCHED_ADJUST_COST pa_adjust_cost
00153 #undef TARGET_SCHED_ADJUST_PRIORITY
00154 #define TARGET_SCHED_ADJUST_PRIORITY pa_adjust_priority
00155 #undef TARGET_SCHED_ISSUE_RATE
00156 #define TARGET_SCHED_ISSUE_RATE pa_issue_rate
00157 
00158 struct gcc_target targetm = TARGET_INITIALIZER;
00159 
00160 void
00161 override_options ()
00162 {
00163   /* Default to 7100LC scheduling.  */
00164   if (pa_cpu_string && ! strcmp (pa_cpu_string, "7100"))
00165     {
00166       pa_cpu_string = "7100";
00167       pa_cpu = PROCESSOR_7100;
00168     }
00169   else if (pa_cpu_string && ! strcmp (pa_cpu_string, "700"))
00170     {
00171       pa_cpu_string = "700";
00172       pa_cpu = PROCESSOR_700;
00173     }
00174   else if (pa_cpu_string == NULL
00175          || ! strcmp (pa_cpu_string, "7100LC"))
00176     {
00177       pa_cpu_string = "7100LC";
00178       pa_cpu = PROCESSOR_7100LC;
00179     }
00180   else if (pa_cpu_string && ! strcmp (pa_cpu_string, "7200"))
00181     {
00182       pa_cpu_string = "7200";
00183       pa_cpu = PROCESSOR_7200;
00184     }
00185   else if (pa_cpu_string && ! strcmp (pa_cpu_string, "8000"))
00186     {
00187       pa_cpu_string = "8000";
00188       pa_cpu = PROCESSOR_8000;
00189     }
00190   else
00191     {
00192       warning ("unknown -mschedule= option (%s).\nValid options are 700, 7100, 7100LC, 7200, and 8000\n", pa_cpu_string);
00193     }
00194 
00195   /* Set the instruction set architecture.  */
00196   if (pa_arch_string && ! strcmp (pa_arch_string, "1.0"))
00197     {
00198       pa_arch_string = "1.0";
00199       pa_arch = ARCHITECTURE_10;
00200       target_flags &= ~(MASK_PA_11 | MASK_PA_20);
00201     }
00202   else if (pa_arch_string && ! strcmp (pa_arch_string, "1.1"))
00203     {
00204       pa_arch_string = "1.1";
00205       pa_arch = ARCHITECTURE_11;
00206       target_flags &= ~MASK_PA_20;
00207       target_flags |= MASK_PA_11;
00208     }
00209   else if (pa_arch_string && ! strcmp (pa_arch_string, "2.0"))
00210     {
00211       pa_arch_string = "2.0";
00212       pa_arch = ARCHITECTURE_20;
00213       target_flags |= MASK_PA_11 | MASK_PA_20;
00214     }
00215   else if (pa_arch_string)
00216     {
00217       warning ("unknown -march= option (%s).\nValid options are 1.0, 1.1, and 2.0\n", pa_arch_string);
00218     }
00219 
00220   if (flag_pic && TARGET_PORTABLE_RUNTIME)
00221     {
00222       warning ("PIC code generation is not supported in the portable runtime model\n");
00223     }
00224 
00225   if (flag_pic && TARGET_FAST_INDIRECT_CALLS)
00226    {
00227       warning ("PIC code generation is not compatible with fast indirect calls\n");
00228    }
00229 
00230   if (! TARGET_GAS && write_symbols != NO_DEBUG)
00231     {
00232       warning ("-g is only supported when using GAS on this processor,");
00233       warning ("-g option disabled");
00234       write_symbols = NO_DEBUG;
00235     }
00236 
00237   /* We only support the "big PIC" model now.  And we always generate PIC
00238      code when in 64bit mode.  */
00239   if (flag_pic == 1 || TARGET_64BIT)
00240     flag_pic = 2;
00241 
00242   /* We can't guarantee that .dword is available for 32-bit targets.  */
00243   if (UNITS_PER_WORD == 4)
00244     targetm.asm_out.aligned_op.di = NULL;
00245 
00246   /* The unaligned ops are only available when using GAS.  */
00247   if (!TARGET_GAS)
00248     {
00249       targetm.asm_out.unaligned_op.hi = NULL;
00250       targetm.asm_out.unaligned_op.si = NULL;
00251       targetm.asm_out.unaligned_op.di = NULL;
00252     }
00253 
00254   /* Register global variables with the garbage collector.  */
00255   pa_add_gc_roots ();
00256 }
00257 
00258 /* Return non-zero only if OP is a register of mode MODE,
00259    or CONST0_RTX.  */
00260 int
00261 reg_or_0_operand (op, mode)
00262      rtx op;
00263      enum machine_mode mode;
00264 {
00265   return (op == CONST0_RTX (mode) || register_operand (op, mode));
00266 }
00267 
00268 /* Return non-zero if OP is suitable for use in a call to a named
00269    function.
00270 
00271    For 2.5 try to eliminate either call_operand_address or
00272    function_label_operand, they perform very similar functions.  */
00273 int
00274 call_operand_address (op, mode)
00275      rtx op;
00276      enum machine_mode mode ATTRIBUTE_UNUSED;
00277 {
00278   return (GET_MODE (op) == word_mode
00279     && CONSTANT_P (op) && ! TARGET_PORTABLE_RUNTIME);
00280 }
00281 
00282 /* Return 1 if X contains a symbolic expression.  We know these
00283    expressions will have one of a few well defined forms, so
00284    we need only check those forms.  */
00285 int
00286 symbolic_expression_p (x)
00287      register rtx x;
00288 {
00289 
00290   /* Strip off any HIGH.  */
00291   if (GET_CODE (x) == HIGH)
00292     x = XEXP (x, 0);
00293 
00294   return (symbolic_operand (x, VOIDmode));
00295 }
00296 
00297 int
00298 symbolic_operand (op, mode)
00299      register rtx op;
00300      enum machine_mode mode ATTRIBUTE_UNUSED;
00301 {
00302   switch (GET_CODE (op))
00303     {
00304     case SYMBOL_REF:
00305     case LABEL_REF:
00306       return 1;
00307     case CONST:
00308       op = XEXP (op, 0);
00309       return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
00310          || GET_CODE (XEXP (op, 0)) == LABEL_REF)
00311         && GET_CODE (XEXP (op, 1)) == CONST_INT);
00312     default:
00313       return 0;
00314     }
00315 }
00316 
00317 /* Return truth value of statement that OP is a symbolic memory
00318    operand of mode MODE.  */
00319 
00320 int
00321 symbolic_memory_operand (op, mode)
00322      rtx op;
00323      enum machine_mode mode ATTRIBUTE_UNUSED;
00324 {
00325   if (GET_CODE (op) == SUBREG)
00326     op = SUBREG_REG (op);
00327   if (GET_CODE (op) != MEM)
00328     return 0;
00329   op = XEXP (op, 0);
00330   return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST
00331     || GET_CODE (op) == HIGH || GET_CODE (op) == LABEL_REF);
00332 }
00333 
00334 /* Return 1 if the operand is either a register or a memory operand that is
00335    not symbolic.  */
00336 
00337 int
00338 reg_or_nonsymb_mem_operand (op, mode)
00339     register rtx op;
00340     enum machine_mode mode;
00341 {
00342   if (register_operand (op, mode))
00343     return 1;
00344 
00345   if (memory_operand (op, mode) && ! symbolic_memory_operand (op, mode))
00346     return 1;
00347 
00348   return 0;
00349 }
00350 
00351 /* Return 1 if the operand is either a register, zero, or a memory operand
00352    that is not symbolic.  */
00353 
00354 int
00355 reg_or_0_or_nonsymb_mem_operand (op, mode)
00356     register rtx op;
00357     enum machine_mode mode;
00358 {
00359   if (register_operand (op, mode))
00360     return 1;
00361 
00362   if (op == CONST0_RTX (mode))
00363     return 1;
00364 
00365   if (memory_operand (op, mode) && ! symbolic_memory_operand (op, mode))
00366     return 1;
00367 
00368   return 0;
00369 }
00370 
00371 /* Return 1 if the operand is a register operand or a non-symbolic memory
00372    operand after reload.  This predicate is used for branch patterns that
00373    internally handle register reloading.  We need to accept non-symbolic
00374    memory operands after reload to ensure that the pattern is still valid
00375    if reload didn't find a hard register for the operand.  */
00376 
00377 int
00378 reg_before_reload_operand (op, mode)
00379     register rtx op;
00380     enum machine_mode mode;
00381 {
00382   /* Don't accept a SUBREG since it will need a reload.  */
00383   if (GET_CODE (op) == SUBREG)
00384     return 0;
00385 
00386   if (register_operand (op, mode))
00387     return 1;
00388 
00389   if (reload_completed
00390       && memory_operand (op, mode)
00391       && ! symbolic_memory_operand (op, mode))
00392     return 1;
00393 
00394   return 0;
00395 }
00396 
00397 /* Accept any constant that can be moved in one instruction into a
00398    general register.  */
00399 int
00400 cint_ok_for_move (intval)
00401      HOST_WIDE_INT intval;
00402 {
00403   /* OK if ldo, ldil, or zdepi, can be used.  */
00404   return (CONST_OK_FOR_LETTER_P (intval, 'J')
00405     || CONST_OK_FOR_LETTER_P (intval, 'N')
00406     || CONST_OK_FOR_LETTER_P (intval, 'K'));
00407 }
00408 
00409 /* Accept anything that can be moved in one instruction into a general
00410    register.  */
00411 int
00412 move_operand (op, mode)
00413      rtx op;
00414      enum machine_mode mode;
00415 {
00416   if (register_operand (op, mode))
00417     return 1;
00418 
00419   if (GET_CODE (op) == CONSTANT_P_RTX)
00420     return 1;
00421 
00422   if (GET_CODE (op) == CONST_INT)
00423     return cint_ok_for_move (INTVAL (op));
00424 
00425   if (GET_CODE (op) == SUBREG)
00426     op = SUBREG_REG (op);
00427   if (GET_CODE (op) != MEM)
00428     return 0;
00429 
00430   op = XEXP (op, 0);
00431 
00432   /* We consider a LO_SUM DLT reference a move_operand now since it has
00433      been merged into the normal movsi/movdi patterns.  */
00434   if (GET_CODE (op) == LO_SUM
00435       && GET_CODE (XEXP (op, 0)) == REG
00436       && REG_OK_FOR_BASE_P (XEXP (op, 0))
00437       && GET_CODE (XEXP (op, 1)) == UNSPEC
00438       && GET_MODE (op) == Pmode)
00439     return 1;
00440 
00441   /* Since move_operand is only used for source operands, we can always
00442      allow scaled indexing!  */
00443   if (! TARGET_DISABLE_INDEXING
00444       && GET_CODE (op) == PLUS
00445       && ((GET_CODE (XEXP (op, 0)) == MULT
00446      && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
00447      && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT
00448      && INTVAL (XEXP (XEXP (op, 0), 1))
00449         == (HOST_WIDE_INT) GET_MODE_SIZE (mode)
00450      && GET_CODE (XEXP (op, 1)) == REG)
00451     || (GET_CODE (XEXP (op, 1)) == MULT
00452         &&GET_CODE (XEXP (XEXP (op, 1), 0)) == REG
00453         && GET_CODE (XEXP (XEXP (op, 1), 1)) == CONST_INT
00454         && INTVAL (XEXP (XEXP (op, 1), 1))
00455      == (HOST_WIDE_INT) GET_MODE_SIZE (mode)
00456         && GET_CODE (XEXP (op, 0)) == REG)))
00457     return 1;
00458 
00459   return memory_address_p (mode, op);
00460 }
00461 
00462 /* Accept REG and any CONST_INT that can be moved in one instruction into a
00463    general register.  */
00464 int
00465 reg_or_cint_move_operand (op, mode)
00466      rtx op;
00467      enum machine_mode mode;
00468 {
00469   if (register_operand (op, mode))
00470     return 1;
00471 
00472   if (GET_CODE (op) == CONST_INT)
00473     return cint_ok_for_move (INTVAL (op));
00474 
00475   return 0;
00476 }
00477 
00478 int
00479 pic_label_operand (op, mode)
00480      rtx op;
00481      enum machine_mode mode ATTRIBUTE_UNUSED;
00482 {
00483   if (!flag_pic)
00484     return 0;
00485 
00486   switch (GET_CODE (op))
00487     {
00488     case LABEL_REF:
00489       return 1;
00490     case CONST:
00491       op = XEXP (op, 0);
00492       return (GET_CODE (XEXP (op, 0)) == LABEL_REF
00493         && GET_CODE (XEXP (op, 1)) == CONST_INT);
00494     default:
00495       return 0;
00496     }
00497 }
00498 
00499 int
00500 fp_reg_operand (op, mode)
00501      rtx op;
00502      enum machine_mode mode ATTRIBUTE_UNUSED;
00503 {
00504   return reg_renumber && FP_REG_P (op);
00505 }
00506 
00507 
00508 
00509 /* Return truth value of whether OP can be used as an operand in a
00510    three operand arithmetic insn that accepts registers of mode MODE
00511    or 14-bit signed integers.  */
00512 int
00513 arith_operand (op, mode)
00514      rtx op;
00515      enum machine_mode mode;
00516 {
00517   return (register_operand (op, mode)
00518     || (GET_CODE (op) == CONST_INT && INT_14_BITS (op)));
00519 }
00520 
00521 /* Return truth value of whether OP can be used as an operand in a
00522    three operand arithmetic insn that accepts registers of mode MODE
00523    or 11-bit signed integers.  */
00524 int
00525 arith11_operand (op, mode)
00526      rtx op;
00527      enum machine_mode mode;
00528 {
00529   return (register_operand (op, mode)
00530     || (GET_CODE (op) == CONST_INT && INT_11_BITS (op)));
00531 }
00532 
00533 /* Return truth value of whether OP can be used as an operand in a
00534    adddi3 insn.  */
00535 int
00536 adddi3_operand (op, mode)
00537      rtx op;
00538      enum machine_mode mode;
00539 {
00540   return (register_operand (op, mode)
00541     || (GET_CODE (op) == CONST_INT
00542         && (TARGET_64BIT ? INT_14_BITS (op) : INT_11_BITS (op))));
00543 }
00544 
00545 /* A constant integer suitable for use in a PRE_MODIFY memory
00546    reference.  */
00547 int
00548 pre_cint_operand (op, mode)
00549      rtx op;
00550      enum machine_mode mode ATTRIBUTE_UNUSED;
00551 {
00552   return (GET_CODE (op) == CONST_INT
00553     && INTVAL (op) >= -0x2000 && INTVAL (op) < 0x10);
00554 }
00555 
00556 /* A constant integer suitable for use in a POST_MODIFY memory
00557    reference.  */
00558 int
00559 post_cint_operand (op, mode)
00560      rtx op;
00561      enum machine_mode mode ATTRIBUTE_UNUSED;
00562 {
00563   return (GET_CODE (op) == CONST_INT
00564     && INTVAL (op) < 0x2000 && INTVAL (op) >= -0x10);
00565 }
00566 
00567 int
00568 arith_double_operand (op, mode)
00569      rtx op;
00570      enum machine_mode mode;
00571 {
00572   return (register_operand (op, mode)
00573     || (GET_CODE (op) == CONST_DOUBLE
00574         && GET_MODE (op) == mode
00575         && VAL_14_BITS_P (CONST_DOUBLE_LOW (op))
00576         && ((CONST_DOUBLE_HIGH (op) >= 0)
00577       == ((CONST_DOUBLE_LOW (op) & 0x1000) == 0))));
00578 }
00579 
00580 /* Return truth value of whether OP is an integer which fits the
00581    range constraining immediate operands in three-address insns, or
00582    is an integer register.  */
00583 
00584 int
00585 ireg_or_int5_operand (op, mode)
00586      rtx op;
00587      enum machine_mode mode ATTRIBUTE_UNUSED;
00588 {
00589   return ((GET_CODE (op) == CONST_INT && INT_5_BITS (op))
00590     || (GET_CODE (op) == REG && REGNO (op) > 0 && REGNO (op) < 32));
00591 }
00592 
00593 /* Return nonzero if OP is an integer register, else return zero.  */
00594 int
00595 ireg_operand (op, mode)
00596      rtx op;
00597      enum machine_mode mode ATTRIBUTE_UNUSED;
00598 {
00599   return (GET_CODE (op) == REG && REGNO (op) > 0 && REGNO (op) < 32);
00600 }
00601 
00602 /* Return truth value of whether OP is an integer which fits the
00603    range constraining immediate operands in three-address insns.  */
00604 
00605 int
00606 int5_operand (op, mode)
00607      rtx op;
00608      enum machine_mode mode ATTRIBUTE_UNUSED;
00609 {
00610   return (GET_CODE (op) == CONST_INT && INT_5_BITS (op));
00611 }
00612 
00613 int
00614 uint5_operand (op, mode)
00615      rtx op;
00616      enum machine_mode mode ATTRIBUTE_UNUSED;
00617 {
00618   return (GET_CODE (op) == CONST_INT && INT_U5_BITS (op));
00619 }
00620 
00621 int
00622 int11_operand (op, mode)
00623      rtx op;
00624      enum machine_mode mode ATTRIBUTE_UNUSED;
00625 {
00626   return (GET_CODE (op) == CONST_INT && INT_11_BITS (op));
00627 }
00628 
00629 int
00630 uint32_operand (op, mode)
00631      rtx op;
00632      enum machine_mode mode ATTRIBUTE_UNUSED;
00633 {
00634 #if HOST_BITS_PER_WIDE_INT > 32
00635   /* All allowed constants will fit a CONST_INT.  */
00636   return (GET_CODE (op) == CONST_INT
00637     && (INTVAL (op) >= 0 && INTVAL (op) < (HOST_WIDE_INT) 1 << 32));
00638 #else
00639   return (GET_CODE (op) == CONST_INT
00640     || (GET_CODE (op) == CONST_DOUBLE
00641         && CONST_DOUBLE_HIGH (op) == 0));
00642 #endif
00643 }
00644 
00645 int
00646 arith5_operand (op, mode)
00647      rtx op;
00648      enum machine_mode mode;
00649 {
00650   return register_operand (op, mode) || int5_operand (op, mode);
00651 }
00652 
00653 /* True iff zdepi can be used to generate this CONST_INT.
00654    zdepi first sign extends a 5 bit signed number to a given field
00655    length, then places this field anywhere in a zero.  */
00656 int
00657 zdepi_cint_p (x)
00658      unsigned HOST_WIDE_INT x;
00659 {
00660   unsigned HOST_WIDE_INT lsb_mask, t;
00661 
00662   /* This might not be obvious, but it's at least fast.
00663      This function is critical; we don't have the time loops would take.  */
00664   lsb_mask = x & -x;
00665   t = ((x >> 4) + lsb_mask) & ~(lsb_mask - 1);
00666   /* Return true iff t is a power of two.  */
00667   return ((t & (t - 1)) == 0);
00668 }
00669 
00670 /* True iff depi or extru can be used to compute (reg & mask).
00671    Accept bit pattern like these:
00672    0....01....1
00673    1....10....0
00674    1..10..01..1  */
00675 int
00676 and_mask_p (mask)
00677      unsigned HOST_WIDE_INT mask;
00678 {
00679   mask = ~mask;
00680   mask += mask & -mask;
00681   return (mask & (mask - 1)) == 0;
00682 }
00683 
00684 /* True iff depi or extru can be used to compute (reg & OP).  */
00685 int
00686 and_operand (op, mode)
00687      rtx op;
00688      enum machine_mode mode;
00689 {
00690   return (register_operand (op, mode)
00691     || (GET_CODE (op) == CONST_INT && and_mask_p (INTVAL (op))));
00692 }
00693 
00694 /* True iff depi can be used to compute (reg | MASK).  */
00695 int
00696 ior_mask_p (mask)
00697      unsigned HOST_WIDE_INT mask;
00698 {
00699   mask += mask & -mask;
00700   return (mask & (mask - 1)) == 0;
00701 }
00702 
00703 /* True iff depi can be used to compute (reg | OP).  */
00704 int
00705 ior_operand (op, mode)
00706      rtx op;
00707      enum machine_mode mode ATTRIBUTE_UNUSED;
00708 {
00709   return (GET_CODE (op) == CONST_INT && ior_mask_p (INTVAL (op)));
00710 }
00711 
00712 int
00713 lhs_lshift_operand (op, mode)
00714      rtx op;
00715      enum machine_mode mode;
00716 {
00717   return register_operand (op, mode) || lhs_lshift_cint_operand (op, mode);
00718 }
00719 
00720 /* True iff OP is a CONST_INT of the forms 0...0xxxx or 0...01...1xxxx.
00721    Such values can be the left hand side x in (x << r), using the zvdepi
00722    instruction.  */
00723 int
00724 lhs_lshift_cint_operand (op, mode)
00725      rtx op;
00726      enum machine_mode mode ATTRIBUTE_UNUSED;
00727 {
00728   unsigned HOST_WIDE_INT x;
00729   if (GET_CODE (op) != CONST_INT)
00730     return 0;
00731   x = INTVAL (op) >> 4;
00732   return (x & (x + 1)) == 0;
00733 }
00734 
00735 int
00736 arith32_operand (op, mode)
00737      rtx op;
00738      enum machine_mode mode;
00739 {
00740   return register_operand (op, mode) || GET_CODE (op) == CONST_INT;
00741 }
00742 
00743 int
00744 pc_or_label_operand (op, mode)
00745      rtx op;
00746      enum machine_mode mode ATTRIBUTE_UNUSED;
00747 {
00748   return (GET_CODE (op) == PC || GET_CODE (op) == LABEL_REF);
00749 }
00750 
00751 /* Legitimize PIC addresses.  If the address is already
00752    position-independent, we return ORIG.  Newly generated
00753    position-independent addresses go to REG.  If we need more
00754    than one register, we lose.  */
00755 
00756 rtx
00757 legitimize_pic_address (orig, mode, reg)
00758      rtx orig, reg;
00759      enum machine_mode mode;
00760 {
00761   rtx pic_ref = orig;
00762 
00763   /* Labels need special handling.  */
00764   if (pic_label_operand (orig, mode))
00765     {
00766       /* We do not want to go through the movXX expanders here since that
00767    would create recursion.
00768 
00769    Nor do we really want to call a generator for a named pattern
00770    since that requires multiple patterns if we want to support
00771    multiple word sizes.
00772 
00773    So instead we just emit the raw set, which avoids the movXX
00774    expanders completely.  */
00775       emit_insn (gen_rtx_SET (VOIDmode, reg, orig));
00776       current_function_uses_pic_offset_table = 1;
00777       return reg;
00778     }
00779   if (GET_CODE (orig) == SYMBOL_REF)
00780     {
00781       if (reg == 0)
00782   abort ();
00783 
00784       emit_move_insn (reg,
00785           gen_rtx_PLUS (word_mode, pic_offset_table_rtx,
00786             gen_rtx_HIGH (word_mode, orig)));
00787       pic_ref
00788   = gen_rtx_MEM (Pmode,
00789            gen_rtx_LO_SUM (Pmode, reg,
00790                gen_rtx_UNSPEC (Pmode,
00791                    gen_rtvec (1, orig),
00792                    0)));
00793 
00794       current_function_uses_pic_offset_table = 1;
00795       RTX_UNCHANGING_P (pic_ref) = 1;
00796       emit_move_insn (reg, pic_ref);
00797       return reg;
00798     }
00799   else if (GET_CODE (orig) == CONST)
00800     {
00801       rtx base;
00802 
00803       if (GET_CODE (XEXP (orig, 0)) == PLUS
00804     && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
00805   return orig;
00806 
00807       if (reg == 0)
00808   abort ();
00809 
00810       if (GET_CODE (XEXP (orig, 0)) == PLUS)
00811   {
00812     base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
00813     orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
00814            base == reg ? 0 : reg);
00815   }
00816       else abort ();
00817       if (GET_CODE (orig) == CONST_INT)
00818   {
00819     if (INT_14_BITS (orig))
00820       return plus_constant (base, INTVAL (orig));
00821     orig = force_reg (Pmode, orig);
00822   }
00823       pic_ref = gen_rtx_PLUS (Pmode, base, orig);
00824       /* Likewise, should we set special REG_NOTEs here?  */
00825     }
00826   return pic_ref;
00827 }
00828 
00829 /* Try machine-dependent ways of modifying an illegitimate address
00830    to be legitimate.  If we find one, return the new, valid address.
00831    This macro is used in only one place: `memory_address' in explow.c.
00832 
00833    OLDX is the address as it was before break_out_memory_refs was called.
00834    In some cases it is useful to look at this to decide what needs to be done.
00835 
00836    MODE and WIN are passed so that this macro can use
00837    GO_IF_LEGITIMATE_ADDRESS.
00838 
00839    It is always safe for this macro to do nothing.  It exists to recognize
00840    opportunities to optimize the output.
00841 
00842    For the PA, transform:
00843 
00844   memory(X + <large int>)
00845 
00846    into:
00847 
00848   if (<large int> & mask) >= 16
00849     Y = (<large int> & ~mask) + mask + 1  Round up.
00850   else
00851     Y = (<large int> & ~mask)   Round down.
00852   Z = X + Y
00853   memory (Z + (<large int> - Y));
00854 
00855    This is for CSE to find several similar references, and only use one Z.
00856 
00857    X can either be a SYMBOL_REF or REG, but because combine can not
00858    perform a 4->2 combination we do nothing for SYMBOL_REF + D where
00859    D will not fit in 14 bits.
00860 
00861    MODE_FLOAT references allow displacements which fit in 5 bits, so use
00862    0x1f as the mask.
00863 
00864    MODE_INT references allow displacements which fit in 14 bits, so use
00865    0x3fff as the mask.
00866 
00867    This relies on the fact that most mode MODE_FLOAT references will use FP
00868    registers and most mode MODE_INT references will use integer registers.
00869    (In the rare case of an FP register used in an integer MODE, we depend
00870    on secondary reloads to clean things up.)
00871 
00872 
00873    It is also beneficial to handle (plus (mult (X) (Y)) (Z)) in a special
00874    manner if Y is 2, 4, or 8.  (allows more shadd insns and shifted indexed
00875    addressing modes to be used).
00876 
00877    Put X and Z into registers.  Then put the entire expression into
00878    a register.  */
00879 
00880 rtx
00881 hppa_legitimize_address (x, oldx, mode)
00882      rtx x, oldx ATTRIBUTE_UNUSED;
00883      enum machine_mode mode;
00884 {
00885   rtx orig = x;
00886 
00887   if (flag_pic)
00888     return legitimize_pic_address (x, mode, gen_reg_rtx (Pmode));
00889 
00890   /* Strip off CONST.  */
00891   if (GET_CODE (x) == CONST)
00892     x = XEXP (x, 0);
00893 
00894   /* Special case.  Get the SYMBOL_REF into a register and use indexing.
00895      That should always be safe.  */
00896   if (GET_CODE (x) == PLUS
00897       && GET_CODE (XEXP (x, 0)) == REG
00898       && GET_CODE (XEXP (x, 1)) == SYMBOL_REF)
00899     {
00900       rtx reg = force_reg (Pmode, XEXP (x, 1));
00901       return force_reg (Pmode, gen_rtx_PLUS (Pmode, reg, XEXP (x, 0)));
00902     }
00903 
00904   /* Note we must reject symbols which represent function addresses
00905      since the assembler/linker can't handle arithmetic on plabels.  */
00906   if (GET_CODE (x) == PLUS
00907       && GET_CODE (XEXP (x, 1)) == CONST_INT
00908       && ((GET_CODE (XEXP (x, 0)) == SYMBOL_REF
00909      && !FUNCTION_NAME_P (XSTR (XEXP (x, 0), 0)))
00910     || GET_CODE (XEXP (x, 0)) == REG))
00911     {
00912       rtx int_part, ptr_reg;
00913       int newoffset;
00914       int offset = INTVAL (XEXP (x, 1));
00915       int mask;
00916 
00917       mask = (GET_MODE_CLASS (mode) == MODE_FLOAT
00918         ? (TARGET_PA_20 ? 0x3fff : 0x1f) : 0x3fff);
00919 
00920       /* Choose which way to round the offset.  Round up if we
00921    are >= halfway to the next boundary.  */
00922       if ((offset & mask) >= ((mask + 1) / 2))
00923   newoffset = (offset & ~ mask) + mask + 1;
00924       else
00925   newoffset = (offset & ~ mask);
00926 
00927       /* If the newoffset will not fit in 14 bits (ldo), then
00928    handling this would take 4 or 5 instructions (2 to load
00929    the SYMBOL_REF + 1 or 2 to load the newoffset + 1 to
00930    add the new offset and the SYMBOL_REF.)  Combine can
00931    not handle 4->2 or 5->2 combinations, so do not create
00932    them.  */
00933       if (! VAL_14_BITS_P (newoffset)
00934     && GET_CODE (XEXP (x, 0)) == SYMBOL_REF)
00935   {
00936     rtx const_part = plus_constant (XEXP (x, 0), newoffset);
00937     rtx tmp_reg
00938       = force_reg (Pmode,
00939        gen_rtx_HIGH (Pmode, const_part));
00940     ptr_reg
00941       = force_reg (Pmode,
00942        gen_rtx_LO_SUM (Pmode,
00943            tmp_reg, const_part));
00944   }
00945       else
00946   {
00947     if (! VAL_14_BITS_P (newoffset))
00948       int_part = force_reg (Pmode, GEN_INT (newoffset));
00949     else
00950       int_part = GEN_INT (newoffset);
00951 
00952     ptr_reg = force_reg (Pmode,
00953              gen_rtx_PLUS (Pmode,
00954                force_reg (Pmode, XEXP (x, 0)),
00955                int_part));
00956   }
00957       return plus_constant (ptr_reg, offset - newoffset);
00958     }
00959 
00960   /* Handle (plus (mult (a) (shadd_constant)) (b)).  */
00961 
00962   if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == MULT
00963       && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
00964       && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1)))
00965       && (GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == 'o'
00966     || GET_CODE (XEXP (x, 1)) == SUBREG)
00967       && GET_CODE (XEXP (x, 1)) != CONST)
00968     {
00969       int val = INTVAL (XEXP (XEXP (x, 0), 1));
00970       rtx reg1, reg2;
00971 
00972       reg1 = XEXP (x, 1);
00973       if (GET_CODE (reg1) != REG)
00974   reg1 = force_reg (Pmode, force_operand (reg1, 0));
00975 
00976       reg2 = XEXP (XEXP (x, 0), 0);
00977       if (GET_CODE (reg2) != REG)
00978         reg2 = force_reg (Pmode, force_operand (reg2, 0));
00979 
00980       return force_reg (Pmode, gen_rtx_PLUS (Pmode,
00981                gen_rtx_MULT (Pmode,
00982                  reg2,
00983                  GEN_INT (val)),
00984                reg1));
00985     }
00986 
00987   /* Similarly for (plus (plus (mult (a) (shadd_constant)) (b)) (c)).
00988 
00989      Only do so for floating point modes since this is more speculative
00990      and we lose if it's an integer store.  */
00991   if (GET_CODE (x) == PLUS
00992       && GET_CODE (XEXP (x, 0)) == PLUS
00993       && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
00994       && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == CONST_INT
00995       && shadd_constant_p (INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1)))
00996       && (mode == SFmode || mode == DFmode))
00997     {
00998 
00999       /* First, try and figure out what to use as a base register.  */
01000       rtx reg1, reg2, base, idx, orig_base;
01001 
01002       reg1 = XEXP (XEXP (x, 0), 1);
01003       reg2 = XEXP (x, 1);
01004       base = NULL_RTX;
01005       idx = NULL_RTX;
01006 
01007       /* Make sure they're both regs.  If one was a SYMBOL_REF [+ const],
01008    then emit_move_sequence will turn on REG_POINTER so we'll know
01009    it's a base register below.  */
01010       if (GET_CODE (reg1) != REG)
01011   reg1 = force_reg (Pmode, force_operand (reg1, 0));
01012 
01013       if (GET_CODE (reg2) != REG)
01014   reg2 = force_reg (Pmode, force_operand (reg2, 0));
01015 
01016       /* Figure out what the base and index are.  */
01017 
01018       if (GET_CODE (reg1) == REG
01019     && REG_POINTER (reg1))
01020   {
01021     base = reg1;
01022     orig_base = XEXP (XEXP (x, 0), 1);
01023     idx = gen_rtx_PLUS (Pmode,
01024             gen_rtx_MULT (Pmode,
01025               XEXP (XEXP (XEXP (x, 0), 0), 0),
01026               XEXP (XEXP (XEXP (x, 0), 0), 1)),
01027             XEXP (x, 1));
01028   }
01029       else if (GET_CODE (reg2) == REG
01030          && REG_POINTER (reg2))
01031   {
01032     base = reg2;
01033     orig_base = XEXP (x, 1);
01034     idx = XEXP (x, 0);
01035   }
01036 
01037       if (base == 0)
01038   return orig;
01039 
01040       /* If the index adds a large constant, try to scale the
01041    constant so that it can be loaded with only one insn.  */
01042       if (GET_CODE (XEXP (idx, 1)) == CONST_INT
01043     && VAL_14_BITS_P (INTVAL (XEXP (idx, 1))
01044           / INTVAL (XEXP (XEXP (idx, 0), 1)))
01045     && INTVAL (XEXP (idx, 1)) % INTVAL (XEXP (XEXP (idx, 0), 1)) == 0)
01046   {
01047     /* Divide the CONST_INT by the scale factor, then add it to A.  */
01048     int val = INTVAL (XEXP (idx, 1));
01049 
01050     val /= INTVAL (XEXP (XEXP (idx, 0), 1));
01051     reg1 = XEXP (XEXP (idx, 0), 0);
01052     if (GET_CODE (reg1) != REG)
01053       reg1 = force_reg (Pmode, force_operand (reg1, 0));
01054 
01055     reg1 = force_reg (Pmode, gen_rtx_PLUS (Pmode, reg1, GEN_INT (val)));
01056 
01057     /* We can now generate a simple scaled indexed address.  */
01058     return
01059       force_reg
01060         (Pmode, gen_rtx_PLUS (Pmode,
01061             gen_rtx_MULT (Pmode, reg1,
01062               XEXP (XEXP (idx, 0), 1)),
01063             base));
01064   }
01065 
01066       /* If B + C is still a valid base register, then add them.  */
01067       if (GET_CODE (XEXP (idx, 1)) == CONST_INT
01068     && INTVAL (XEXP (idx, 1)) <= 4096
01069     && INTVAL (XEXP (idx, 1)) >= -4096)
01070   {
01071     int val = INTVAL (XEXP (XEXP (idx, 0), 1));
01072     rtx reg1, reg2;
01073 
01074     reg1 = force_reg (Pmode, gen_rtx_PLUS (Pmode, base, XEXP (idx, 1)));
01075 
01076     reg2 = XEXP (XEXP (idx, 0), 0);
01077     if (GET_CODE (reg2) != CONST_INT)
01078       reg2 = force_reg (Pmode, force_operand (reg2, 0));
01079 
01080     return force_reg (Pmode, gen_rtx_PLUS (Pmode,
01081              gen_rtx_MULT (Pmode,
01082                      reg2,
01083                      GEN_INT (val)),
01084              reg1));
01085   }
01086 
01087       /* Get the index into a register, then add the base + index and
01088    return a register holding the result.  */
01089 
01090       /* First get A into a register.  */
01091       reg1 = XEXP (XEXP (idx, 0), 0);
01092       if (GET_CODE (reg1) != REG)
01093   reg1 = force_reg (Pmode, force_operand (reg1, 0));
01094 
01095       /* And get B into a register.  */
01096       reg2 = XEXP (idx, 1);
01097       if (GET_CODE (reg2) != REG)
01098   reg2 = force_reg (Pmode, force_operand (reg2, 0));
01099 
01100       reg1 = force_reg (Pmode,
01101       gen_rtx_PLUS (Pmode,
01102               gen_rtx_MULT (Pmode, reg1,
01103                 XEXP (XEXP (idx, 0), 1)),
01104               reg2));
01105 
01106       /* Add the result to our base register and return.  */
01107       return force_reg (Pmode, gen_rtx_PLUS (Pmode, base, reg1));
01108 
01109     }
01110 
01111   /* Uh-oh.  We might have an address for x[n-100000].  This needs
01112      special handling to avoid creating an indexed memory address
01113      with x-100000 as the base.
01114 
01115      If the constant part is small enough, then it's still safe because
01116      there is a guard page at the beginning and end of the data segment.
01117 
01118      Scaled references are common enough that we want to try and rearrange the
01119      terms so that we can use indexing for these addresses too.  Only
01120      do the optimization for floatint point modes.  */
01121 
01122   if (GET_CODE (x) == PLUS
01123       && symbolic_expression_p (XEXP (x, 1)))
01124     {
01125       /* Ugly.  We modify things here so that the address offset specified
01126    by the index expression is computed first, then added to x to form
01127    the entire address.  */
01128 
01129       rtx regx1, regx2, regy1, regy2, y;
01130 
01131       /* Strip off any CONST.  */
01132       y = XEXP (x, 1);
01133       if (GET_CODE (y) == CONST)
01134   y = XEXP (y, 0);
01135 
01136       if (GET_CODE (y) == PLUS || GET_CODE (y) == MINUS)
01137   {
01138     /* See if this looks like
01139     (plus (mult (reg) (shadd_const))
01140           (const (plus (symbol_ref) (const_int))))
01141 
01142        Where const_int is small.  In that case the const
01143        expression is a valid pointer for indexing.
01144 
01145        If const_int is big, but can be divided evenly by shadd_const
01146        and added to (reg).  This allows more scaled indexed addresses.  */
01147     if (GET_CODE (XEXP (y, 0)) == SYMBOL_REF
01148         && GET_CODE (XEXP (x, 0)) == MULT
01149         && GET_CODE (XEXP (y, 1)) == CONST_INT
01150         && INTVAL (XEXP (y, 1)) >= -4096
01151         && INTVAL (XEXP (y, 1)) <= 4095
01152         && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
01153         && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1))))
01154       {
01155         int val = INTVAL (XEXP (XEXP (x, 0), 1));
01156         rtx reg1, reg2;
01157 
01158         reg1 = XEXP (x, 1);
01159         if (GET_CODE (reg1) != REG)
01160     reg1 = force_reg (Pmode, force_operand (reg1, 0));
01161 
01162         reg2 = XEXP (XEXP (x, 0), 0);
01163         if (GET_CODE (reg2) != REG)
01164           reg2 = force_reg (Pmode, force_operand (reg2, 0));
01165 
01166         return force_reg (Pmode,
01167         gen_rtx_PLUS (Pmode,
01168                 gen_rtx_MULT (Pmode,
01169                   reg2,
01170                   GEN_INT (val)),
01171                 reg1));
01172       }
01173     else if ((mode == DFmode || mode == SFmode)
01174        && GET_CODE (XEXP (y, 0)) == SYMBOL_REF
01175        && GET_CODE (XEXP (x, 0)) == MULT
01176        && GET_CODE (XEXP (y, 1)) == CONST_INT
01177        && INTVAL (XEXP (y, 1)) % INTVAL (XEXP (XEXP (x, 0), 1)) == 0
01178        && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
01179        && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1))))
01180       {
01181         regx1
01182     = force_reg (Pmode, GEN_INT (INTVAL (XEXP (y, 1))
01183                / INTVAL (XEXP (XEXP (x, 0), 1))));
01184         regx2 = XEXP (XEXP (x, 0), 0);
01185         if (GET_CODE (regx2) != REG)
01186     regx2 = force_reg (Pmode, force_operand (regx2, 0));
01187         regx2 = force_reg (Pmode, gen_rtx_fmt_ee (GET_CODE (y), Pmode,
01188               regx2, regx1));
01189         return
01190     force_reg (Pmode,
01191          gen_rtx_PLUS (Pmode,
01192            gen_rtx_MULT (Pmode, regx2,
01193                    XEXP (XEXP (x, 0), 1)),
01194            force_reg (Pmode, XEXP (y, 0))));
01195       }
01196     else if (GET_CODE (XEXP (y, 1)) == CONST_INT
01197        && INTVAL (XEXP (y, 1)) >= -4096
01198        && INTVAL (XEXP (y, 1)) <= 4095)
01199       {
01200         /* This is safe because of the guard page at the
01201      beginning and end of the data space.  Just
01202      return the original address.  */
01203         return orig;
01204       }
01205     else
01206       {
01207         /* Doesn't look like one we can optimize.  */
01208         regx1 = force_reg (Pmode, force_operand (XEXP (x, 0), 0));
01209         regy1 = force_reg (Pmode, force_operand (XEXP (y, 0), 0));
01210         regy2 = force_reg (Pmode, force_operand (XEXP (y, 1), 0));
01211         regx1 = force_reg (Pmode,
01212          gen_rtx_fmt_ee (GET_CODE (y), Pmode,
01213              regx1, regy2));
01214         return force_reg (Pmode, gen_rtx_PLUS (Pmode, regx1, regy1));
01215       }
01216   }
01217     }
01218 
01219   return orig;
01220 }
01221 
01222 /* For the HPPA, REG and REG+CONST is cost 0
01223    and addresses involving symbolic constants are cost 2.
01224 
01225    PIC addresses are very expensive.
01226 
01227    It is no coincidence that this has the same structure
01228    as GO_IF_LEGITIMATE_ADDRESS.  */
01229 int
01230 hppa_address_cost (X)
01231      rtx X;
01232 {
01233   if (GET_CODE (X) == PLUS)
01234       return 1;
01235   else if (GET_CODE (X) == LO_SUM)
01236     return 1;
01237   else if (GET_CODE (X) == HIGH)
01238     return 2;
01239   return 4;
01240 }
01241 
01242 /* Ensure mode of ORIG, a REG rtx, is MODE.  Returns either ORIG or a
01243    new rtx with the correct mode.  */
01244 static inline rtx
01245 force_mode (mode, orig)
01246      enum machine_mode mode;
01247      rtx orig;
01248 {
01249   if (mode == GET_MODE (orig))
01250     return orig;
01251 
01252   if (REGNO (orig) >= FIRST_PSEUDO_REGISTER)
01253     abort ();
01254 
01255   return gen_rtx_REG (mode, REGNO (orig));
01256 }
01257 
01258 /* Emit insns to move operands[1] into operands[0].
01259 
01260    Return 1 if we have written out everything that needs to be done to
01261    do the move.  Otherwise, return 0 and the caller will emit the move
01262    normally.
01263 
01264    Note SCRATCH_REG may not be in the proper mode depending on how it
01265    will be used.  This routine is resposible for creating a new copy
01266    of SCRATCH_REG in the proper mode.  */
01267 
01268 int
01269 emit_move_sequence (operands, mode, scratch_reg)
01270      rtx *operands;
01271      enum machine_mode mode;
01272      rtx scratch_reg;
01273 {
01274   register rtx operand0 = operands[0];
01275   register rtx operand1 = operands[1];
01276   register rtx tem;
01277 
01278   if (scratch_reg
01279       && reload_in_progress && GET_CODE (operand0) == REG
01280       && REGNO (operand0) >= FIRST_PSEUDO_REGISTER)
01281     operand0 = reg_equiv_mem[REGNO (operand0)];
01282   else if (scratch_reg
01283      && reload_in_progress && GET_CODE (operand0) == SUBREG
01284      && GET_CODE (SUBREG_REG (operand0)) == REG
01285      && REGNO (SUBREG_REG (operand0)) >= FIRST_PSEUDO_REGISTER)
01286     {
01287      /* We must not alter SUBREG_BYTE (operand0) since that would confuse
01288   the code which tracks sets/uses for delete_output_reload.  */
01289       rtx temp = gen_rtx_SUBREG (GET_MODE (operand0),
01290          reg_equiv_mem [REGNO (SUBREG_REG (operand0))],
01291          SUBREG_BYTE (operand0));
01292       operand0 = alter_subreg (&temp);
01293     }
01294 
01295   if (scratch_reg
01296       && reload_in_progress && GET_CODE (operand1) == REG
01297       && REGNO (operand1) >= FIRST_PSEUDO_REGISTER)
01298     operand1 = reg_equiv_mem[REGNO (operand1)];
01299   else if (scratch_reg
01300      && reload_in_progress && GET_CODE (operand1) == SUBREG
01301      && GET_CODE (SUBREG_REG (operand1)) == REG
01302      && REGNO (SUBREG_REG (operand1)) >= FIRST_PSEUDO_REGISTER)
01303     {
01304      /* We must not alter SUBREG_BYTE (operand0) since that would confuse
01305   the code which tracks sets/uses for delete_output_reload.  */
01306       rtx temp = gen_rtx_SUBREG (GET_MODE (operand1),
01307          reg_equiv_mem [REGNO (SUBREG_REG (operand1))],
01308          SUBREG_BYTE (operand1));
01309       operand1 = alter_subreg (&temp);
01310     }
01311 
01312   if (scratch_reg && reload_in_progress && GET_CODE (operand0) == MEM
01313       && ((tem = find_replacement (&XEXP (operand0, 0)))
01314     != XEXP (operand0, 0)))
01315     operand0 = gen_rtx_MEM (GET_MODE (operand0), tem);
01316   if (scratch_reg && reload_in_progress && GET_CODE (operand1) == MEM
01317       && ((tem = find_replacement (&XEXP (operand1, 0)))
01318     != XEXP (operand1, 0)))
01319     operand1 = gen_rtx_MEM (GET_MODE (operand1), tem);
01320 
01321   /* Handle secondary reloads for loads/stores of FP registers from
01322      REG+D addresses where D does not fit in 5 bits, including
01323      (subreg (mem (addr))) cases.  */
01324   if (fp_reg_operand (operand0, mode)
01325       && ((GET_CODE (operand1) == MEM
01326      && ! memory_address_p (DFmode, XEXP (operand1, 0)))
01327     || ((GET_CODE (operand1) == SUBREG
01328          && GET_CODE (XEXP (operand1, 0)) == MEM
01329          && !memory_address_p (DFmode, XEXP (XEXP (operand1, 0), 0)))))
01330       && scratch_reg)
01331     {
01332       if (GET_CODE (operand1) == SUBREG)
01333   operand1 = XEXP (operand1, 0);
01334 
01335       /* SCRATCH_REG will hold an address and maybe the actual data.  We want
01336    it in WORD_MODE regardless of what mode it was originally given
01337    to us.  */
01338       scratch_reg = force_mode (word_mode, scratch_reg);
01339 
01340       /* D might not fit in 14 bits either; for such cases load D into
01341    scratch reg.  */
01342       if (!memory_address_p (Pmode, XEXP (operand1, 0)))
01343   {
01344     emit_move_insn (scratch_reg, XEXP (XEXP (operand1, 0), 1));
01345     emit_move_insn (scratch_reg, gen_rtx_fmt_ee (GET_CODE (XEXP (operand1, 0)),
01346                    Pmode,
01347                    XEXP (XEXP (operand1, 0), 0),
01348                    scratch_reg));
01349   }
01350       else
01351   emit_move_insn (scratch_reg, XEXP (operand1, 0));
01352       emit_insn (gen_rtx_SET (VOIDmode, operand0,
01353             gen_rtx_MEM (mode, scratch_reg)));
01354       return 1;
01355     }
01356   else if (fp_reg_operand (operand1, mode)
01357      && ((GET_CODE (operand0) == MEM
01358     && ! memory_address_p (DFmode, XEXP (operand0, 0)))
01359          || ((GET_CODE (operand0) == SUBREG)
01360        && GET_CODE (XEXP (operand0, 0)) == MEM
01361        && !memory_address_p (DFmode, XEXP (XEXP (operand0, 0), 0))))
01362      && scratch_reg)
01363     {
01364       if (GET_CODE (operand0) == SUBREG)
01365   operand0 = XEXP (operand0, 0);
01366 
01367       /* SCRATCH_REG will hold an address and maybe the actual data.  We want
01368    it in WORD_MODE regardless of what mode it was originally given
01369    to us.  */
01370       scratch_reg = force_mode (word_mode, scratch_reg);
01371 
01372       /* D might not fit in 14 bits either; for such cases load D into
01373    scratch reg.  */
01374       if (!memory_address_p (Pmode, XEXP (operand0, 0)))
01375   {
01376     emit_move_insn (scratch_reg, XEXP (XEXP (operand0, 0), 1));
01377     emit_move_insn (scratch_reg, gen_rtx_fmt_ee (GET_CODE (XEXP (operand0,
01378                         0)),
01379                    Pmode,
01380                    XEXP (XEXP (operand0, 0),
01381                    0),
01382                    scratch_reg));
01383   }
01384       else
01385   emit_move_insn (scratch_reg, XEXP (operand0, 0));
01386       emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (mode, scratch_reg),
01387             operand1));
01388       return 1;
01389     }
01390   /* Handle secondary reloads for loads of FP registers from constant
01391      expressions by forcing the constant into memory.
01392 
01393      use scratch_reg to hold the address of the memory location.
01394 
01395      The proper fix is to change PREFERRED_RELOAD_CLASS to return
01396      NO_REGS when presented with a const_int and an register class
01397      containing only FP registers.  Doing so unfortunately creates
01398      more problems than it solves.   Fix this for 2.5.  */
01399   else if (fp_reg_operand (operand0, mode)
01400      && CONSTANT_P (operand1)
01401      && scratch_reg)
01402     {
01403       rtx xoperands[2];
01404 
01405       /* SCRATCH_REG will hold an address and maybe the actual data.  We want
01406    it in WORD_MODE regardless of what mode it was originally given
01407    to us.  */
01408       scratch_reg = force_mode (word_mode, scratch_reg);
01409 
01410       /* Force the constant into memory and put the address of the
01411    memory location into scratch_reg.  */
01412       xoperands[0] = scratch_reg;
01413       xoperands[1] = XEXP (force_const_mem (mode, operand1), 0);
01414       emit_move_sequence (xoperands, Pmode, 0);
01415 
01416       /* Now load the destination register.  */
01417       emit_insn (gen_rtx_SET (mode, operand0,
01418             gen_rtx_MEM (mode, scratch_reg)));
01419       return 1;
01420     }
01421   /* Handle secondary reloads for SAR.  These occur when trying to load
01422      the SAR from memory, FP register, or with a constant.  */
01423   else if (GET_CODE (operand0) == REG
01424      && REGNO (operand0) < FIRST_PSEUDO_REGISTER
01425      && REGNO_REG_CLASS (REGNO (operand0)) == SHIFT_REGS
01426      && (GET_CODE (operand1) == MEM
01427          || GET_CODE (operand1) == CONST_INT
01428          || (GET_CODE (operand1) == REG
01429        && FP_REG_CLASS_P (REGNO_REG_CLASS (REGNO (operand1)))))
01430      && scratch_reg)
01431     {
01432       /* D might not fit in 14 bits either; for such cases load D into
01433    scratch reg.  */
01434       if (GET_CODE (operand1) == MEM
01435     && !memory_address_p (Pmode, XEXP (operand1, 0)))
01436   {
01437     /* We are reloading the address into the scratch register, so we
01438        want to make sure the scratch register is a full register.  */
01439     scratch_reg = force_mode (word_mode, scratch_reg);
01440 
01441     emit_move_insn (scratch_reg, XEXP (XEXP (operand1, 0), 1));
01442     emit_move_insn (scratch_reg, gen_rtx_fmt_ee (GET_CODE (XEXP (operand1,
01443                         0)),
01444                    Pmode,
01445                    XEXP (XEXP (operand1, 0),
01446                    0),
01447                    scratch_reg));
01448 
01449     /* Now we are going to load the scratch register from memory,
01450        we want to load it in the same width as the original MEM,
01451        which must be the same as the width of the ultimate destination,
01452        OPERAND0.  */
01453     scratch_reg = force_mode (GET_MODE (operand0), scratch_reg);
01454 
01455     emit_move_insn (scratch_reg, gen_rtx_MEM (GET_MODE (operand0),
01456                 scratch_reg));
01457   }
01458       else
01459   {
01460     /* We want to load the scratch register using the same mode as
01461        the ultimate destination.  */
01462     scratch_reg = force_mode (GET_MODE (operand0), scratch_reg);
01463 
01464     emit_move_insn (scratch_reg, operand1);
01465   }
01466 
01467       /* And emit the insn to set the ultimate destination.  We know that
01468    the scratch register has the same mode as the destination at this
01469    point.  */
01470       emit_move_insn (operand0, scratch_reg);
01471       return 1;
01472     }
01473   /* Handle most common case: storing into a register.  */
01474   else if (register_operand (operand0, mode))
01475     {
01476       if (register_operand (operand1, mode)
01477     || (GET_CODE (operand1) == CONST_INT
01478         && cint_ok_for_move (INTVAL (operand1)))
01479     || (operand1 == CONST0_RTX (mode))
01480     || (GET_CODE (operand1) == HIGH
01481         && !symbolic_operand (XEXP (operand1, 0), VOIDmode))
01482     /* Only `general_operands' can come here, so MEM is ok.  */
01483     || GET_CODE (operand1) == MEM)
01484   {
01485     /* Run this case quickly.  */
01486     emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
01487     return 1;
01488   }
01489     }
01490   else if (GET_CODE (operand0) == MEM)
01491     {
01492       if (mode == DFmode && operand1 == CONST0_RTX (mode)
01493     && !(reload_in_progress || reload_completed))
01494   {
01495     rtx temp = gen_reg_rtx (DFmode);
01496 
01497     emit_insn (gen_rtx_SET (VOIDmode, temp, operand1));
01498     emit_insn (gen_rtx_SET (VOIDmode, operand0, temp));
01499     return 1;
01500   }
01501       if (register_operand (operand1, mode) || operand1 == CONST0_RTX (mode))
01502   {
01503     /* Run this case quickly.  */
01504     emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
01505     return 1;
01506   }
01507       if (! (reload_in_progress || reload_completed))
01508   {
01509     operands[0] = validize_mem (operand0);
01510     operands[1] = operand1 = force_reg (mode, operand1);
01511   }
01512     }
01513 
01514   /* Simplify the source if we need to.
01515      Note we do have to handle function labels here, even though we do
01516      not consider them legitimate constants.  Loop optimizations can
01517      call the emit_move_xxx with one as a source.  */
01518   if ((GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode))
01519       || function_label_operand (operand1, mode)
01520       || (GET_CODE (operand1) == HIGH
01521     && symbolic_operand (XEXP (operand1, 0), mode)))
01522     {
01523       int ishighonly = 0;
01524 
01525       if (GET_CODE (operand1) == HIGH)
01526   {
01527     ishighonly = 1;
01528     operand1 = XEXP (operand1, 0);
01529   }
01530       if (symbolic_operand (operand1, mode))
01531   {
01532     /* Argh.  The assembler and linker can't handle arithmetic
01533        involving plabels.
01534 
01535        So we force the plabel into memory, load operand0 from
01536        the memory location, then add in the constant part.  */
01537     if ((GET_CODE (operand1) == CONST
01538          && GET_CODE (XEXP (operand1, 0)) == PLUS
01539          && function_label_operand (XEXP (XEXP (operand1, 0), 0), Pmode))
01540         || function_label_operand (operand1, mode))
01541       {
01542         rtx temp, const_part;
01543 
01544         /* Figure out what (if any) scratch register to use.  */
01545         if (reload_in_progress || reload_completed)
01546     {
01547       scratch_reg = scratch_reg ? scratch_reg : operand0;
01548       /* SCRATCH_REG will hold an address and maybe the actual
01549          data.  We want it in WORD_MODE regardless of what mode it
01550          was originally given to us.  */
01551       scratch_reg = force_mode (word_mode, scratch_reg);
01552     }
01553         else if (flag_pic)
01554     scratch_reg = gen_reg_rtx (Pmode);
01555 
01556         if (GET_CODE (operand1) == CONST)
01557     {
01558       /* Save away the constant part of the expression.  */
01559       const_part = XEXP (XEXP (operand1, 0), 1);
01560       if (GET_CODE (const_part) != CONST_INT)
01561         abort ();
01562 
01563       /* Force the function label into memory.  */
01564       temp = force_const_mem (mode, XEXP (XEXP (operand1, 0), 0));
01565     }
01566         else
01567     {
01568       /* No constant part.  */
01569       const_part = NULL_RTX;
01570 
01571       /* Force the function label into memory.  */
01572       temp = force_const_mem (mode, operand1);
01573     }
01574 
01575 
01576         /* Get the address of the memory location.  PIC-ify it if
01577      necessary.  */
01578         temp = XEXP (temp, 0);
01579         if (flag_pic)
01580     temp = legitimize_pic_address (temp, mode, scratch_reg);
01581 
01582         /* Put the address of the memory location into our destination
01583      register.  */
01584         operands[1] = temp;
01585         emit_move_sequence (operands, mode, scratch_reg);
01586 
01587         /* Now load from the memory location into our destination
01588      register.  */
01589         operands[1] = gen_rtx_MEM (Pmode, operands[0]);
01590         emit_move_sequence (operands, mode, scratch_reg);
01591 
01592         /* And add back in the constant part.  */
01593         if (const_part != NULL_RTX)
01594     expand_inc (operand0, const_part);
01595 
01596         return 1;
01597       }
01598 
01599     if (flag_pic)
01600       {
01601         rtx temp;
01602 
01603         if (reload_in_progress || reload_completed)
01604     {
01605       temp = scratch_reg ? scratch_reg : operand0;
01606       /* TEMP will hold an address and maybe the actual
01607          data.  We want it in WORD_MODE regardless of what mode it
01608          was originally given to us.  */
01609       temp = force_mode (word_mode, temp);
01610     }
01611         else
01612     temp = gen_reg_rtx (Pmode);
01613 
01614         /* (const (plus (symbol) (const_int))) must be forced to
01615      memory during/after reload if the const_int will not fit
01616      in 14 bits.  */
01617         if (GET_CODE (operand1) == CONST
01618            && GET_CODE (XEXP (operand1, 0)) == PLUS
01619            && GET_CODE (XEXP (XEXP (operand1, 0), 1)) == CONST_INT
01620            && !INT_14_BITS (XEXP (XEXP (operand1, 0), 1))
01621            && (reload_completed || reload_in_progress)
01622            && flag_pic)
01623     {
01624       operands[1] = force_const_mem (mode, operand1);
01625       operands[1] = legitimize_pic_address (XEXP (operands[1], 0),
01626               mode, temp);
01627       emit_move_sequence (operands, mode, temp);
01628     }
01629         else
01630     {
01631       operands[1] = legitimize_pic_address (operand1, mode, temp);
01632       emit_insn (gen_rtx_SET (VOIDmode, operand0, operands[1]));
01633     }
01634       }
01635     /* On the HPPA, references to data space are supposed to use dp,
01636        register 27, but showing it in the RTL inhibits various cse
01637        and loop optimizations.  */
01638     else
01639       {
01640         rtx temp, set;
01641 
01642         if (reload_in_progress || reload_completed)
01643     {
01644       temp = scratch_reg ? scratch_reg : operand0;
01645       /* TEMP will hold an address and maybe the actual
01646          data.  We want it in WORD_MODE regardless of what mode it
01647          was originally given to us.  */
01648       temp = force_mode (word_mode, temp);
01649     }
01650         else
01651     temp = gen_reg_rtx (mode);
01652 
01653         /* Loading a SYMBOL_REF into a register makes that register
01654      safe to be used as the base in an indexed address.
01655 
01656      Don't mark hard registers though.  That loses.  */
01657         if (GET_CODE (operand0) == REG
01658       && REGNO (operand0) >= FIRST_PSEUDO_REGISTER)
01659     REG_POINTER (operand0) = 1;
01660         if (REGNO (temp) >= FIRST_PSEUDO_REGISTER)
01661     REG_POINTER (temp) = 1;
01662         if (ishighonly)
01663     set = gen_rtx_SET (mode, operand0, temp);
01664         else
01665     set = gen_rtx_SET (VOIDmode,
01666            operand0,
01667            gen_rtx_LO_SUM (mode, temp, operand1));
01668 
01669         emit_insn (gen_rtx_SET (VOIDmode,
01670               temp,
01671               gen_rtx_HIGH (mode, operand1)));
01672         emit_insn (set);
01673 
01674       }
01675     return 1;
01676   }
01677       else if (GET_CODE (operand1) != CONST_INT
01678          || ! cint_ok_for_move (INTVAL (operand1)))
01679   {
01680     rtx extend = NULL_RTX;
01681     rtx temp;
01682 
01683     if (TARGET_64BIT && GET_CODE (operand1) == CONST_INT
01684         && HOST_BITS_PER_WIDE_INT > 32
01685         && GET_MODE_BITSIZE (GET_MODE (operand0)) > 32)
01686       {
01687         HOST_WIDE_INT val = INTVAL (operand1);
01688         HOST_WIDE_INT nval;
01689 
01690         /* Extract the low order 32 bits of the value and sign extend.
01691      If the new value is the same as the original value, we can
01692      can use the original value as-is.  If the new value is
01693      different, we use it and insert the most-significant 32-bits
01694      of the original value into the final result.  */
01695         nval = ((val & (((HOST_WIDE_INT) 2 << 31) - 1))
01696           ^ ((HOST_WIDE_INT) 1 << 31)) - ((HOST_WIDE_INT) 1 << 31);
01697         if (val != nval)
01698     {
01699 #if HOST_BITS_PER_WIDE_INT > 32
01700       extend = GEN_INT (val >> 32);
01701 #endif
01702       operand1 = GEN_INT (nval);
01703     }
01704       }
01705 
01706     if (reload_in_progress || reload_completed)
01707       temp = operand0;
01708     else
01709       temp = gen_reg_rtx (mode);
01710 
01711     /* We don't directly split DImode constants on 32-bit targets
01712        because PLUS uses an 11-bit immediate and the insn sequence
01713        generated is not as efficient as the one using HIGH/LO_SUM.  */
01714     if (GET_CODE (operand1) == CONST_INT
01715         && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
01716       {
01717         /* Directly break constant into high and low parts.  This
01718      provides better optimization opportunities because various
01719      passes recognize constants split with PLUS but not LO_SUM.
01720      We use a 14-bit signed low part except when the addition
01721      of 0x4000 to the high part might change the sign of the
01722      high part.  */
01723         HOST_WIDE_INT value = INTVAL (operand1);
01724         HOST_WIDE_INT low = value & 0x3fff;
01725         HOST_WIDE_INT high = value & ~ 0x3fff;
01726 
01727         if (low >= 0x2000)
01728     {
01729       if (high == 0x7fffc000 || (mode == HImode && high == 0x4000))
01730         high += 0x2000;
01731       else
01732         high += 0x4000;
01733     }
01734 
01735         low = value - high;
01736 
01737         emit_insn (gen_rtx_SET (VOIDmode, temp, GEN_INT (high)));
01738         operands[1] = gen_rtx_PLUS (mode, temp, GEN_INT (low));
01739       }
01740     else
01741       {
01742         emit_insn (gen_rtx_SET (VOIDmode, temp,
01743               gen_rtx_HIGH (mode, operand1)));
01744         operands[1] = gen_rtx_LO_SUM (mode, temp, operand1);
01745       }
01746 
01747     emit_move_insn (operands[0], operands[1]);
01748 
01749     if (extend != NULL_RTX)
01750       emit_insn (gen_insv (operands[0], GEN_INT (32), const0_rtx,
01751          extend));
01752 
01753     return 1;
01754   }
01755     }
01756   /* Now have insn-emit do whatever it normally does.  */
01757   return 0;
01758 }
01759 
01760 /* Examine EXP and return nonzero if it contains an ADDR_EXPR (meaning
01761    it will need a link/runtime reloc).  */
01762 
01763 int
01764 reloc_needed (exp)
01765      tree exp;
01766 {
01767   int reloc = 0;
01768 
01769   switch (TREE_CODE (exp))
01770     {
01771     case ADDR_EXPR:
01772       return 1;
01773 
01774     case PLUS_EXPR:
01775     case MINUS_EXPR:
01776       reloc = reloc_needed (TREE_OPERAND (exp, 0));
01777       reloc |= reloc_needed (TREE_OPERAND (exp, 1));
01778       break;
01779 
01780     case NOP_EXPR:
01781     case CONVERT_EXPR:
01782     case NON_LVALUE_EXPR:
01783       reloc = reloc_needed (TREE_OPERAND (exp, 0));
01784       break;
01785 
01786     case CONSTRUCTOR:
01787       {
01788   register tree link;
01789   for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
01790     if (TREE_VALUE (link) != 0)
01791       reloc |= reloc_needed (TREE_VALUE (link));
01792       }
01793       break;
01794 
01795     case ERROR_MARK:
01796       break;
01797 
01798     default:
01799       break;
01800     }
01801   return reloc;
01802 }
01803 
01804 /* Does operand (which is a symbolic_operand) live in text space? If
01805    so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true.  */
01806 
01807 int
01808 read_only_operand (operand, mode)
01809      rtx operand;
01810      enum machine_mode mode ATTRIBUTE_UNUSED;
01811 {
01812   if (GET_CODE (operand) == CONST)
01813     operand = XEXP (XEXP (operand, 0), 0);
01814   if (flag_pic)
01815     {
01816       if (GET_CODE (operand) == SYMBOL_REF)
01817   return SYMBOL_REF_FLAG (operand) && !CONSTANT_POOL_ADDRESS_P (operand);
01818     }
01819   else
01820     {
01821       if (GET_CODE (operand) == SYMBOL_REF)
01822   return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand);
01823     }
01824   return 1;
01825 }
01826 
01827 
01828 /* Return the best assembler insn template
01829    for moving operands[1] into operands[0] as a fullword.   */
01830 const char *
01831 singlemove_string (operands)
01832      rtx *operands;
01833 {
01834   HOST_WIDE_INT intval;
01835 
01836   if (GET_CODE (operands[0]) == MEM)
01837     return "stw %r1,%0";
01838   if (GET_CODE (operands[1]) == MEM)
01839     return "ldw %1,%0";
01840   if (GET_CODE (operands[1]) == CONST_DOUBLE)
01841     {
01842       long i;
01843       REAL_VALUE_TYPE d;
01844 
01845       if (GET_MODE (operands[1]) != SFmode)
01846   abort ();
01847 
01848       /* Translate the CONST_DOUBLE to a CONST_INT with the same target
01849    bit pattern.  */
01850       REAL_VALUE_FROM_CONST_DOUBLE (d, operands[1]);
01851       REAL_VALUE_TO_TARGET_SINGLE (d, i);
01852 
01853       operands[1] = GEN_INT (i);
01854       /* Fall through to CONST_INT case.  */
01855     }
01856   if (GET_CODE (operands[1]) == CONST_INT)
01857     {
01858       intval = INTVAL (operands[1]);
01859 
01860       if (VAL_14_BITS_P (intval))
01861   return "ldi %1,%0";
01862       else if ((intval & 0x7ff) == 0)
01863   return "ldil L'%1,%0";
01864       else if (zdepi_cint_p (intval))
01865   return "{zdepi %Z1,%0|depwi,z %Z1,%0}";
01866       else
01867   return "ldil L'%1,%0\n\tldo R'%1(%0),%0";
01868     }
01869   return "copy %1,%0";
01870 }
01871 
01872 
01873 /* Compute position (in OP[1]) and width (in OP[2])
01874    useful for copying IMM to a register using the zdepi
01875    instructions.  Store the immediate value to insert in OP[0].  */
01876 static void
01877 compute_zdepwi_operands (imm, op)
01878      unsigned HOST_WIDE_INT imm;
01879      unsigned *op;
01880 {
01881   int lsb, len;
01882 
01883   /* Find the least significant set bit in IMM.  */
01884   for (lsb = 0; lsb < 32; lsb++)
01885     {
01886       if ((imm & 1) != 0)
01887         break;
01888       imm >>= 1;
01889     }
01890 
01891   /* Choose variants based on *sign* of the 5-bit field.  */
01892   if ((imm & 0x10) == 0)
01893     len = (lsb <= 28) ? 4 : 32 - lsb;
01894   else
01895     {
01896       /* Find the width of the bitstring in IMM.  */
01897       for (len = 5; len < 32; len++)
01898   {
01899     if ((imm & (1 << len)) == 0)
01900       break;
01901   }
01902 
01903       /* Sign extend IMM as a 5-bit value.  */
01904       imm = (imm & 0xf) - 0x10;
01905     }
01906 
01907   op[0] = imm;
01908   op[1] = 31 - lsb;
01909   op[2] = len;
01910 }
01911 
01912 /* Compute position (in OP[1]) and width (in OP[2])
01913    useful for copying IMM to a register using the depdi,z
01914    instructions.  Store the immediate value to insert in OP[0].  */
01915 void
01916 compute_zdepdi_operands (imm, op)
01917      unsigned HOST_WIDE_INT imm;
01918      unsigned *op;
01919 {
01920   HOST_WIDE_INT lsb, len;
01921 
01922   /* Find the least significant set bit in IMM.  */
01923   for (lsb = 0; lsb < HOST_BITS_PER_WIDE_INT; lsb++)
01924     {
01925       if ((imm & 1) != 0)
01926         break;
01927       imm >>= 1;
01928     }
01929 
01930   /* Choose variants based on *sign* of the 5-bit field.  */
01931   if ((imm & 0x10) == 0)
01932     len = ((lsb <= HOST_BITS_PER_WIDE_INT - 4)
01933      ? 4 : HOST_BITS_PER_WIDE_INT - lsb);
01934   else
01935     {
01936       /* Find the width of the bitstring in IMM.  */
01937       for (len = 5; len < HOST_BITS_PER_WIDE_INT; len++)
01938   {
01939     if ((imm & ((unsigned HOST_WIDE_INT) 1 << len)) == 0)
01940       break;
01941   }
01942 
01943       /* Sign extend IMM as a 5-bit value.  */
01944       imm = (imm & 0xf) - 0x10;
01945     }
01946 
01947   op[0] = imm;
01948   op[1] = 63 - lsb;
01949   op[2] = len;
01950 }
01951 
01952 /* Output assembler code to perform a doubleword move insn
01953    with operands OPERANDS.  */
01954 
01955 const char *
01956 output_move_double (operands)
01957      rtx *operands;
01958 {
01959   enum { REGOP, OFFSOP, MEMOP, CNSTOP, RNDOP } optype0, optype1;
01960   rtx latehalf[2];
01961   rtx addreg0 = 0, addreg1 = 0;
01962 
01963   /* First classify both operands.  */
01964 
01965   if (REG_P (operands[0]))
01966     optype0 = REGOP;
01967   else if (offsettable_memref_p (operands[0]))
01968     optype0 = OFFSOP;
01969   else if (GET_CODE (operands[0]) == MEM)
01970     optype0 = MEMOP;
01971   else
01972     optype0 = RNDOP;
01973 
01974   if (REG_P (operands[1]))
01975     optype1 = REGOP;
01976   else if (CONSTANT_P (operands[1]))
01977     optype1 = CNSTOP;
01978   else if (offsettable_memref_p (operands[1]))
01979     optype1 = OFFSOP;
01980   else if (GET_CODE (operands[1]) == MEM)
01981     optype1 = MEMOP;
01982   else
01983     optype1 = RNDOP;
01984 
01985   /* Check for the cases that the operand constraints are not
01986      supposed to allow to happen.  Abort if we get one,
01987      because generating code for these cases is painful.  */
01988 
01989   if (optype0 != REGOP && optype1 != REGOP)
01990     abort ();
01991 
01992    /* Handle auto decrementing and incrementing loads and stores
01993      specifically, since the structure of the function doesn't work
01994      for them without major modification.  Do it better when we learn
01995      this port about the general inc/dec addressing of PA.
01996      (This was written by tege.  Chide him if it doesn't work.)  */
01997 
01998   if (optype0 == MEMOP)
01999     {
02000       /* We have to output the address syntax ourselves, since print_operand
02001    doesn't deal with the addresses we want to use.  Fix this later.  */
02002 
02003       rtx addr = XEXP (operands[0], 0);
02004       if (GET_CODE (addr) == POST_INC || GET_CODE (addr) == POST_DEC)
02005   {
02006     rtx high_reg = gen_rtx_SUBREG (SImode, operands[1], 0);
02007 
02008     operands[0] = XEXP (addr, 0);
02009     if (GET_CODE (operands[1]) != REG || GET_CODE (operands[0]) != REG)
02010       abort ();
02011 
02012     if (!reg_overlap_mentioned_p (high_reg, addr))
02013       {
02014         /* No overlap between high target register and address
02015      register.  (We do this in a non-obvious way to
02016      save a register file writeback)  */
02017         if (GET_CODE (addr) == POST_INC)
02018     return "{stws|stw},ma %1,8(%0)\n\tstw %R1,-4(%0)";
02019         return "{stws|stw},ma %1,-8(%0)\n\tstw %R1,12(%0)";
02020       }
02021     else
02022       abort ();
02023   }
02024       else if (GET_CODE (addr) == PRE_INC || GET_CODE (addr) == PRE_DEC)
02025   {
02026     rtx high_reg = gen_rtx_SUBREG (SImode, operands[1], 0);
02027 
02028     operands[0] = XEXP (addr, 0);
02029     if (GET_CODE (operands[1]) != REG || GET_CODE (operands[0]) != REG)
02030       abort ();
02031 
02032     if (!reg_overlap_mentioned_p (high_reg, addr))
02033       {
02034         /* No overlap between high target register and address
02035      register.  (We do this in a non-obvious way to
02036      save a register file writeback)  */
02037         if (GET_CODE (addr) == PRE_INC)
02038     return "{stws|stw},mb %1,8(%0)\n\tstw %R1,4(%0)";
02039         return "{stws|stw},mb %1,-8(%0)\n\tstw %R1,4(%0)";
02040       }
02041     else
02042       abort ();
02043   }
02044     }
02045   if (optype1 == MEMOP)
02046     {
02047       /* We have to output the address syntax ourselves, since print_operand
02048    doesn't deal with the addresses we want to use.  Fix this later.  */
02049 
02050       rtx addr = XEXP (operands[1], 0);
02051       if (GET_CODE (addr) == POST_INC || GET_CODE (addr) == POST_DEC)
02052   {
02053     rtx high_reg = gen_rtx_SUBREG (SImode, operands[0], 0);
02054 
02055     operands[1] = XEXP (addr, 0);
02056     if (GET_CODE (operands[0]) != REG || GET_CODE (operands[1]) != REG)
02057       abort ();
02058 
02059     if (!reg_overlap_mentioned_p (high_reg, addr))
02060       {
02061         /* No overlap between high target register and address
02062      register.  (We do this in a non-obvious way to
02063      save a register file writeback)  */
02064         if (GET_CODE (addr) == POST_INC)
02065     return "{ldws|ldw},ma 8(%1),%0\n\tldw -4(%1),%R0";
02066         return "{ldws|ldw},ma -8(%1),%0\n\tldw 12(%1),%R0";
02067       }
02068     else
02069       {
02070         /* This is an undefined situation.  We should load into the
02071      address register *and* update that register.  Probably
02072      we don't need to handle this at all.  */
02073         if (GET_CODE (addr) == POST_INC)
02074     return "ldw 4(%1),%R0\n\t{ldws|ldw},ma 8(%1),%0";
02075         return "ldw 4(%1),%R0\n\t{ldws|ldw},ma -8(%1),%0";
02076       }
02077   }
02078       else if (GET_CODE (addr) == PRE_INC || GET_CODE (addr) == PRE_DEC)
02079   {
02080     rtx high_reg = gen_rtx_SUBREG (SImode, operands[0], 0);
02081 
02082     operands[1] = XEXP (addr, 0);
02083     if (GET_CODE (operands[0]) != REG || GET_CODE (operands[1]) != REG)
02084       abort ();
02085 
02086     if (!reg_overlap_mentioned_p (high_reg, addr))
02087       {
02088         /* No overlap between high target register and address
02089      register.  (We do this in a non-obvious way to
02090      save a register file writeback)  */
02091         if (GET_CODE (addr) == PRE_INC)
02092     return "{ldws|ldw},mb 8(%1),%0\n\tldw 4(%1),%R0";
02093         return "{ldws|ldw},mb -8(%1),%0\n\tldw 4(%1),%R0";
02094       }
02095     else
02096       {
02097         /* This is an undefined situation.  We should load into the
02098      address register *and* update that register.  Probably
02099      we don't need to handle this at all.  */
02100         if (GET_CODE (addr) == PRE_INC)
02101     return "ldw 12(%1),%R0\n\t{ldws|ldw},mb 8(%1),%0";
02102         return "ldw -4(%1),%R0\n\t{ldws|ldw},mb -8(%1),%0";
02103       }
02104   }
02105       else if (GET_CODE (addr) == PLUS
02106          && GET_CODE (XEXP (addr, 0)) == MULT)
02107   {
02108     rtx high_reg = gen_rtx_SUBREG (SImode, operands[0], 0);
02109 
02110     if (!reg_overlap_mentioned_p (high_reg, addr))
02111       {
02112         rtx xoperands[3];
02113 
02114         xoperands[0] = high_reg;
02115         xoperands[1] = XEXP (addr, 1);
02116         xoperands[2] = XEXP (XEXP (addr, 0), 0);
02117         xoperands[3] = XEXP (XEXP (addr, 0), 1);
02118         output_asm_insn ("{sh%O3addl %2,%1,%0|shladd,l %2,%O3,%1,%0}",
02119              xoperands);
02120         return "ldw 4(%0),%R0\n\tldw 0(%0),%0";
02121       }
02122     else
02123       {
02124         rtx xoperands[3];
02125 
02126         xoperands[0] = high_reg;
02127         xoperands[1] = XEXP (addr, 1);
02128         xoperands[2] = XEXP (XEXP (addr, 0), 0);
02129         xoperands[3] = XEXP (XEXP (addr, 0), 1);
02130         output_asm_insn ("{sh%O3addl %2,%1,%R0|shladd,l %2,%O3,%1,%R0}",
02131              xoperands);
02132         return "ldw 0(%R0),%0\n\tldw 4(%R0),%R0";
02133       }
02134   }
02135     }
02136 
02137   /* If an operand is an unoffsettable memory ref, find a register
02138      we can increment temporarily to make it refer to the second word.  */
02139 
02140   if (optype0 == MEMOP)
02141     addreg0 = find_addr_reg (XEXP (operands[0], 0));
02142 
02143   if (optype1 == MEMOP)
02144     addreg1 = find_addr_reg (XEXP (operands[1], 0));
02145 
02146   /* Ok, we can do one word at a time.
02147      Normally we do the low-numbered word first.
02148 
02149      In either case, set up in LATEHALF the operands to use
02150      for the high-numbered word and in some cases alter the
02151      operands in OPERANDS to be suitable for the low-numbered word.  */
02152 
02153   if (optype0 == REGOP)
02154     latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
02155   else if (optype0 == OFFSOP)
02156     latehalf[0] = adjust_address (operands[0], SImode, 4);
02157   else
02158     latehalf[0] = operands[0];
02159 
02160   if (optype1 == REGOP)
02161     latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
02162   else if (optype1 == OFFSOP)
02163     latehalf[1] = adjust_address (operands[1], SImode, 4);
02164   else if (optype1 == CNSTOP)
02165     split_double (operands[1], &operands[1], &latehalf[1]);
02166   else
02167     latehalf[1] = operands[1];
02168 
02169   /* If the first move would clobber the source of the second one,
02170      do them in the other order.
02171 
02172      This can happen in two cases:
02173 
02174   mem -> register where the first half of the destination register
02175   is the same register used in the memory's address.  Reload
02176   can create such insns.
02177 
02178   mem in this case will be either register indirect or register
02179   indirect plus a valid offset.
02180 
02181   register -> register move where REGNO(dst) == REGNO(src + 1)
02182   someone (Tim/Tege?) claimed this can happen for parameter loads.
02183 
02184      Handle mem -> register case first.  */
02185   if (optype0 == REGOP
02186       && (optype1 == MEMOP || optype1 == OFFSOP)
02187       && refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
02188           operands[1], 0))
02189     {
02190       /* Do the late half first.  */
02191       if (addreg1)
02192   output_asm_insn ("ldo 4(%0),%0", &addreg1);
02193       output_asm_insn (singlemove_string (latehalf), latehalf);
02194 
02195       /* Then clobber.  */
02196       if (addreg1)
02197   output_asm_insn ("ldo -4(%0),%0", &addreg1);
02198       return singlemove_string (operands);
02199     }
02200 
02201   /* Now handle register -> register case.  */
02202   if (optype0 == REGOP && optype1 == REGOP
02203       && REGNO (operands[0]) == REGNO (operands[1]) + 1)
02204     {
02205       output_asm_insn (singlemove_string (latehalf), latehalf);
02206       return singlemove_string (operands);
02207     }
02208 
02209   /* Normal case: do the two words, low-numbered first.  */
02210 
02211   output_asm_insn (singlemove_string (operands), operands);
02212 
02213   /* Make any unoffsettable addresses point at high-numbered word.  */
02214   if (addreg0)
02215     output_asm_insn ("ldo 4(%0),%0", &addreg0);
02216   if (addreg1)
02217     output_asm_insn ("ldo 4(%0),%0", &addreg1);
02218 
02219   /* Do that word.  */
02220   output_asm_insn (singlemove_string (latehalf), latehalf);
02221 
02222   /* Undo the adds we just did.  */
02223   if (addreg0)
02224     output_asm_insn ("ldo -4(%0),%0", &addreg0);
02225   if (addreg1)
02226     output_asm_insn ("ldo -4(%0),%0", &addreg1);
02227 
02228   return "";
02229 }
02230 
02231 const char *
02232 output_fp_move_double (operands)
02233      rtx *operands;
02234 {
02235   if (FP_REG_P (operands[0]))
02236     {
02237       if (FP_REG_P (operands[1])
02238     || operands[1] == CONST0_RTX (GET_MODE (operands[0])))
02239   output_asm_insn ("fcpy,dbl %f1,%0", operands);
02240       else
02241   output_asm_insn ("fldd%F1 %1,%0", operands);
02242     }
02243   else if (FP_REG_P (operands[1]))
02244     {
02245       output_asm_insn ("fstd%F0 %1,%0", operands);
02246     }
02247   else if (operands[1] == CONST0_RTX (GET_MODE (operands[0])))
02248     {
02249       if (GET_CODE (operands[0]) == REG)
02250   {
02251     rtx xoperands[2];
02252     xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
02253     xoperands[0] = operands[0];
02254     output_asm_insn ("copy %%r0,%0\n\tcopy %%r0,%1", xoperands);
02255   }
02256       /* This is a pain.  You have to be prepared to deal with an
02257    arbitrary address here including pre/post increment/decrement.
02258 
02259    so avoid this in the MD.  */
02260       else
02261   abort ();
02262     }
02263   else abort ();
02264   return "";
02265 }
02266 
02267 /* Return a REG that occurs in ADDR with coefficient 1.
02268    ADDR can be effectively incremented by incrementing REG.  */
02269 
02270 static rtx
02271 find_addr_reg (addr)
02272      rtx addr;
02273 {
02274   while (GET_CODE (addr) == PLUS)
02275     {
02276       if (GET_CODE (XEXP (addr, 0)) == REG)
02277   addr = XEXP (addr, 0);
02278       else if (GET_CODE (XEXP (addr, 1)) == REG)
02279   addr = XEXP (addr, 1);
02280       else if (CONSTANT_P (XEXP (addr, 0)))
02281   addr = XEXP (addr, 1);
02282       else if (CONSTANT_P (XEXP (addr, 1)))
02283   addr = XEXP (addr, 0);
02284       else
02285   abort ();
02286     }
02287   if (GET_CODE (addr) == REG)
02288     return addr;
02289   abort ();
02290 }
02291 
02292 /* Emit code to perform a block move.
02293 
02294    OPERANDS[0] is the destination pointer as a REG, clobbered.
02295    OPERANDS[1] is the source pointer as a REG, clobbered.
02296    OPERANDS[2] is a register for temporary storage.
02297    OPERANDS[4] is the size as a CONST_INT
02298    OPERANDS[3] is a register for temporary storage.
02299    OPERANDS[5] is the alignment safe to use, as a CONST_INT.
02300    OPERANDS[6] is another temporary register.   */
02301 
02302 const char *
02303 output_block_move (operands, size_is_constant)
02304      rtx *operands;
02305      int size_is_constant ATTRIBUTE_UNUSED;
02306 {
02307   int align = INTVAL (operands[5]);
02308   unsigned long n_bytes = INTVAL (operands[4]);
02309 
02310   /* We can't move more than four bytes at a time because the PA
02311      has no longer integer move insns.  (Could use fp mem ops?)  */
02312   if (align > 4)
02313     align = 4;
02314 
02315   /* Note that we know each loop below will execute at least twice
02316      (else we would have open-coded the copy).  */
02317   switch (align)
02318     {
02319       case 4:
02320   /* Pre-adjust the loop counter.  */
02321   operands[4] = GEN_INT (n_bytes - 8);
02322   output_asm_insn ("ldi %4,%2", operands);
02323 
02324   /* Copying loop.  */
02325   output_asm_insn ("{ldws|ldw},ma 4(%1),%3", operands);
02326   output_asm_insn ("{ldws|ldw},ma 4(%1),%6", operands);
02327   output_asm_insn ("{stws|stw},ma %3,4(%0)", operands);
02328   output_asm_insn ("addib,>= -8,%2,.-12", operands);
02329   output_asm_insn ("{stws|stw},ma %6,4(%0)", operands);
02330 
02331   /* Handle the residual.  There could be up to 7 bytes of
02332      residual to copy!  */
02333   if (n_bytes % 8 != 0)
02334     {
02335       operands[4] = GEN_INT (n_bytes % 4);
02336       if (n_bytes % 8 >= 4)
02337         output_asm_insn ("{ldws|ldw},ma 4(%1),%3", operands);
02338       if (n_bytes % 4 != 0)
02339         output_asm_insn ("ldw 0(%1),%6", operands);
02340       if (n_bytes % 8 >= 4)
02341         output_asm_insn ("{stws|stw},ma %3,4(%0)", operands);
02342       if (n_bytes % 4 != 0)
02343         output_asm_insn ("{stbys|stby},e %6,%4(%0)", operands);
02344     }
02345   return "";
02346 
02347       case 2:
02348   /* Pre-adjust the loop counter.  */
02349   operands[4] = GEN_INT (n_bytes - 4);
02350   output_asm_insn ("ldi %4,%2", operands);
02351 
02352   /* Copying loop.  */
02353   output_asm_insn ("{ldhs|ldh},ma 2(%1),%3", operands);
02354   output_asm_insn ("{ldhs|ldh},ma 2(%1),%6", operands);
02355   output_asm_insn ("{sths|sth},ma %3,2(%0)", operands);
02356   output_asm_insn ("addib,>= -4,%2,.-12", operands);
02357   output_asm_insn ("{sths|sth},ma %6,2(%0)", operands);
02358 
02359   /* Handle the residual.  */
02360   if (n_bytes % 4 != 0)
02361     {
02362       if (n_bytes % 4 >= 2)
02363         output_asm_insn ("{ldhs|ldh},ma 2(%1),%3", operands);
02364       if (n_bytes % 2 != 0)
02365         output_asm_insn ("ldb 0(%1),%6", operands);
02366       if (n_bytes % 4 >= 2)
02367         output_asm_insn ("{sths|sth},ma %3,2(%0)", operands);
02368       if (n_bytes % 2 != 0)
02369         output_asm_insn ("stb %6,0(%0)", operands);
02370     }
02371   return "";
02372 
02373       case 1:
02374   /* Pre-adjust the loop counter.  */
02375   operands[4] = GEN_INT (n_bytes - 2);
02376   output_asm_insn ("ldi %4,%2", operands);
02377 
02378   /* Copying loop.  */
02379   output_asm_insn ("{ldbs|ldb},ma 1(%1),%3", operands);
02380   output_asm_insn ("{ldbs|ldb},ma 1(%1),%6", operands);
02381   output_asm_insn ("{stbs|stb},ma %3,1(%0)", operands);
02382   output_asm_insn ("addib,>= -2,%2,.-12", operands);
02383   output_asm_insn ("{stbs|stb},ma %6,1(%0)", operands);
02384 
02385   /* Handle the residual.  */
02386   if (n_bytes % 2 != 0)
02387     {
02388       output_asm_insn ("ldb 0(%1),%3", operands);
02389       output_asm_insn ("stb %3,0(%0)", operands);
02390     }
02391   return "";
02392 
02393       default:
02394   abort ();
02395     }
02396 }
02397 
02398 /* Count the number of insns necessary to handle this block move.
02399 
02400    Basic structure is the same as emit_block_move, except that we
02401    count insns rather than emit them.  */
02402 
02403 static int
02404 compute_movstrsi_length (insn)
02405      rtx insn;
02406 {
02407   rtx pat = PATTERN (insn);
02408   unsigned int align = INTVAL (XEXP (XVECEXP (pat, 0, 7), 0));
02409   unsigned long n_bytes = INTVAL (XEXP (XVECEXP (pat, 0, 6), 0));
02410   unsigned int n_insns = 0;
02411 
02412   /* We can't move more than four bytes at a time because the PA
02413      has no longer integer move insns.  (Could use fp mem ops?)  */
02414   if (align > 4)
02415     align = 4;
02416 
02417   /* The basic copying loop.  */
02418   n_insns = 6;
02419 
02420   /* Residuals.  */
02421   if (n_bytes % (2 * align) != 0)
02422     {
02423       if ((n_bytes % (2 * align)) >= align)
02424   n_insns += 2;
02425 
02426       if ((n_bytes % align) != 0)
02427   n_insns += 2;
02428     }
02429 
02430   /* Lengths are expressed in bytes now; each insn is 4 bytes.  */
02431   return n_insns * 4;
02432 }
02433 
02434 
02435 const char *
02436 output_and (operands)
02437      rtx *operands;
02438 {
02439   if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) != 0)
02440     {
02441       unsigned HOST_WIDE_INT mask = INTVAL (operands[2]);
02442       int ls0, ls1, ms0, p, len;
02443 
02444       for (ls0 = 0; ls0 < 32; ls0++)
02445   if ((mask & (1 << ls0)) == 0)
02446     break;
02447 
02448       for (ls1 = ls0; ls1 < 32; ls1++)
02449   if ((mask & (1 << ls1)) != 0)
02450     break;
02451 
02452       for (ms0 = ls1; ms0 < 32; ms0++)
02453   if ((mask & (1 << ms0)) == 0)
02454     break;
02455 
02456       if (ms0 != 32)
02457   abort ();
02458 
02459       if (ls1 == 32)
02460   {
02461     len = ls0;
02462 
02463     if (len == 0)
02464       abort ();
02465 
02466     operands[2] = GEN_INT (len);
02467     return "{extru|extrw,u} %1,31,%2,%0";
02468   }
02469       else
02470   {
02471     /* We could use this `depi' for the case above as well, but `depi'
02472        requires one more register file access than an `extru'.  */
02473 
02474     p = 31 - ls0;
02475     len = ls1 - ls0;
02476 
02477     operands[2] = GEN_INT (p);
02478     operands[3] = GEN_INT (len);
02479     return "{depi|depwi} 0,%2,%3,%0";
02480   }
02481     }
02482   else
02483     return "and %1,%2,%0";
02484 }
02485 
02486 /* Return a string to perform a bitwise-and of operands[1] with operands[2]
02487    storing the result in operands[0].  */
02488 const char *
02489 output_64bit_and (operands)
02490      rtx *operands;
02491 {
02492   if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) != 0)
02493     {
02494       unsigned HOST_WIDE_INT mask = INTVAL (operands[2]);
02495       int ls0, ls1, ms0, p, len;
02496 
02497       for (ls0 = 0; ls0 < HOST_BITS_PER_WIDE_INT; ls0++)
02498   if ((mask & ((unsigned HOST_WIDE_INT) 1 << ls0)) == 0)
02499     break;
02500 
02501       for (ls1 = ls0; ls1 < HOST_BITS_PER_WIDE_INT; ls1++)
02502   if ((mask & ((unsigned HOST_WIDE_INT) 1 << ls1)) != 0)
02503     break;
02504 
02505       for (ms0 = ls1; ms0 < HOST_BITS_PER_WIDE_INT; ms0++)
02506   if ((mask & ((unsigned HOST_WIDE_INT) 1 << ms0)) == 0)
02507     break;
02508 
02509       if (ms0 != HOST_BITS_PER_WIDE_INT)
02510   abort ();
02511 
02512       if (ls1 == HOST_BITS_PER_WIDE_INT)
02513   {
02514     len = ls0;
02515 
02516     if (len == 0)
02517       abort ();
02518 
02519     operands[2] = GEN_INT (len);
02520     return "extrd,u %1,63,%2,%0";
02521   }
02522       else
02523   {
02524     /* We could use this `depi' for the case above as well, but `depi'
02525        requires one more register file access than an `extru'.  */
02526 
02527     p = 63 - ls0;
02528     len = ls1 - ls0;
02529 
02530     operands[2] = GEN_INT (p);
02531     operands[3] = GEN_INT (len);
02532     return "depdi 0,%2,%3,%0";
02533   }
02534     }
02535   else
02536     return "and %1,%2,%0";
02537 }
02538 
02539 const char *
02540 output_ior (operands)
02541      rtx *operands;
02542 {
02543   unsigned HOST_WIDE_INT mask = INTVAL (operands[2]);
02544   int bs0, bs1, p, len;
02545 
02546   if (INTVAL (operands[2]) == 0)
02547     return "copy %1,%0";
02548 
02549   for (bs0 = 0; bs0 < 32; bs0++)
02550     if ((mask & (1 << bs0)) != 0)
02551       break;
02552 
02553   for (bs1 = bs0; bs1 < 32; bs1++)
02554     if ((mask & (1 << bs1)) == 0)
02555       break;
02556 
02557   if (bs1 != 32 && ((unsigned HOST_WIDE_INT) 1 << bs1) <= mask)
02558     abort ();
02559 
02560   p = 31 - bs0;
02561   len = bs1 - bs0;
02562 
02563   operands[2] = GEN_INT (p);
02564   operands[3] = GEN_INT (len);
02565   return "{depi|depwi} -1,%2,%3,%0";
02566 }
02567 
02568 /* Return a string to perform a bitwise-and of operands[1] with operands[2]
02569    storing the result in operands[0].  */
02570 const char *
02571 output_64bit_ior (operands)
02572      rtx *operands;
02573 {
02574   unsigned HOST_WIDE_INT mask = INTVAL (operands[2]);
02575   int bs0, bs1, p, len;
02576 
02577   if (INTVAL (operands[2]) == 0)
02578     return "copy %1,%0";
02579 
02580   for (bs0 = 0; bs0 < HOST_BITS_PER_WIDE_INT; bs0++)
02581     if ((mask & ((unsigned HOST_WIDE_INT) 1 << bs0)) != 0)
02582       break;
02583 
02584   for (bs1 = bs0; bs1 < HOST_BITS_PER_WIDE_INT; bs1++)
02585     if ((mask & ((unsigned HOST_WIDE_INT) 1 << bs1)) == 0)
02586       break;
02587 
02588   if (bs1 != HOST_BITS_PER_WIDE_INT
02589       && ((unsigned HOST_WIDE_INT) 1 << bs1) <= mask)
02590     abort ();
02591 
02592   p = 63 - bs0;
02593   len = bs1 - bs0;
02594 
02595   operands[2] = GEN_INT (p);
02596   operands[3] = GEN_INT (len);
02597   return "depdi -1,%2,%3,%0";
02598 }
02599 
02600 /* Target hook for assembling integer objects.  This code handles
02601    aligned SI and DI integers specially, since function references must
02602    be preceded by P%.  */
02603 
02604 static bool
02605 pa_assemble_integer (x, size, aligned_p)
02606      rtx x;
02607      unsigned int size;
02608      int aligned_p;
02609 {
02610   if (size == UNITS_PER_WORD && aligned_p
02611       && function_label_operand (x, VOIDmode))
02612     {
02613       fputs (size == 8? "\t.dword\tP%" : "\t.word\tP%", asm_out_file);
02614       output_addr_const (asm_out_file, x);
02615       fputc ('\n', asm_out_file);
02616       return true;
02617     }
02618   return default_assemble_integer (x, size, aligned_p);
02619 }
02620 
02621 /* Output an ascii string.  */
02622 void
02623 output_ascii (file, p, size)
02624      FILE *file;
02625      const char *p;
02626      int size;
02627 {
02628   int i;
02629   int chars_output;
02630   unsigned char partial_output[16]; /* Max space 4 chars can occupy.   */
02631 
02632   /* The HP assembler can only take strings of 256 characters at one
02633      time.  This is a limitation on input line length, *not* the
02634      length of the string.  Sigh.  Even worse, it seems that the
02635      restriction is in number of input characters (see \xnn &
02636      \whatever).  So we have to do this very carefully.  */
02637 
02638   fputs ("\t.STRING \"", file);
02639 
02640   chars_output = 0;
02641   for (i = 0; i < size; i += 4)
02642     {
02643       int co = 0;
02644       int io = 0;
02645       for (io = 0, co = 0; io < MIN (4, size - i); io++)
02646   {
02647     register unsigned int c = (unsigned char) p[i + io];
02648 
02649     if (c == '\"' || c == '\\')
02650       partial_output[co++] = '\\';
02651     if (c >= ' ' && c < 0177)
02652       partial_output[co++] = c;
02653     else
02654       {
02655         unsigned int hexd;
02656         partial_output[co++] = '\\';
02657         partial_output[co++] = 'x';
02658         hexd =  c  / 16 - 0 + '0';
02659         if (hexd > '9')
02660     hexd -= '9' - 'a' + 1;
02661         partial_output[co++] = hexd;
02662         hexd =  c % 16 - 0 + '0';
02663         if (hexd > '9')
02664     hexd -= '9' - 'a' + 1;
02665         partial_output[co++] = hexd;
02666       }
02667   }
02668       if (chars_output + co > 243)
02669   {
02670     fputs ("\"\n\t.STRING \"", file);
02671     chars_output = 0;
02672   }
02673       fwrite (partial_output, 1, co, file);
02674       chars_output += co;
02675       co = 0;
02676     }
02677   fputs ("\"\n", file);
02678 }
02679 
02680 /* Try to rewrite floating point comparisons & branches to avoid
02681    useless add,tr insns.
02682 
02683    CHECK_NOTES is nonzero if we should examine REG_DEAD notes
02684    to see if FPCC is dead.  CHECK_NOTES is nonzero for the
02685    first attempt to remove useless add,tr insns.  It is zero
02686    for the second pass as reorg sometimes leaves bogus REG_DEAD
02687    notes lying around.
02688 
02689    When CHECK_NOTES is zero we can only eliminate add,tr insns
02690    when there's a 1:1 correspondence between fcmp and ftest/fbranch
02691    instructions.  */
02692 static void
02693 remove_useless_addtr_insns (insns, check_notes)
02694      rtx insns;
02695      int check_notes;
02696 {
02697   rtx insn;
02698   static int pass = 0;
02699 
02700   /* This is fairly cheap, so always run it when optimizing.  */
02701   if (optimize > 0)
02702     {
02703       int fcmp_count = 0;
02704       int fbranch_count = 0;
02705 
02706       /* Walk all the insns in this function looking for fcmp & fbranch
02707    instructions.  Keep track of how many of each we find.  */
02708       insns = get_insns ();
02709       for (insn = insns; insn; insn = next_insn (insn))
02710   {
02711     rtx tmp;
02712 
02713     /* Ignore anything that isn't an INSN or a JUMP_INSN.  */
02714     if (GET_CODE (insn) != INSN && GET_CODE (insn) != JUMP_INSN)
02715       continue;
02716 
02717     tmp = PATTERN (insn);
02718 
02719     /* It must be a set.  */
02720     if (GET_CODE (tmp) != SET)
02721       continue;
02722 
02723     /* If the destination is CCFP, then we've found an fcmp insn.  */
02724     tmp = SET_DEST (tmp);
02725     if (GET_CODE (tmp) == REG && REGNO (tmp) == 0)
02726       {
02727         fcmp_count++;
02728         continue;
02729       }
02730 
02731     tmp = PATTERN (insn);
02732     /* If this is an fbranch instruction, bump the fbranch counter.  */
02733     if (GET_CODE (tmp) == SET
02734         && SET_DEST (tmp) == pc_rtx
02735         && GET_CODE (SET_SRC (tmp)) == IF_THEN_ELSE
02736         && GET_CODE (XEXP (SET_SRC (tmp), 0)) == NE
02737         && GET_CODE (XEXP (XEXP (SET_SRC (tmp), 0), 0)) == REG
02738         && REGNO (XEXP (XEXP (SET_SRC (tmp), 0), 0)) == 0)
02739       {
02740         fbranch_count++;
02741         continue;
02742       }
02743   }
02744 
02745 
02746       /* Find all floating point compare + branch insns.  If possible,
02747    reverse the comparison & the branch to avoid add,tr insns.  */
02748       for (insn = insns; insn; insn = next_insn (insn))
02749   {
02750     rtx tmp, next;
02751 
02752     /* Ignore anything that isn't an INSN.  */
02753     if (GET_CODE (insn) != INSN)
02754       continue;
02755 
02756     tmp = PATTERN (insn);
02757 
02758     /* It must be a set.  */
02759     if (GET_CODE (tmp) != SET)
02760       continue;
02761 
02762     /* The destination must be CCFP, which is register zero.  */
02763     tmp = SET_DEST (tmp);
02764     if (GET_CODE (tmp) != REG || REGNO (tmp) != 0)
02765       continue;
02766 
02767     /* INSN should be a set of CCFP.
02768 
02769        See if the result of this insn is used in a reversed FP
02770        conditional branch.  If so, reverse our condition and
02771        the branch.  Doing so avoids useless add,tr insns.  */
02772     next = next_insn (insn);
02773     while (next)
02774       {
02775         /* Jumps, calls and labels stop our search.  */
02776         if (GET_CODE (next) == JUMP_INSN
02777       || GET_CODE (next) == CALL_INSN
02778       || GET_CODE (next) == CODE_LABEL)
02779     break;
02780 
02781         /* As does another fcmp insn.  */
02782         if (GET_CODE (next) == INSN
02783       && GET_CODE (PATTERN (next)) == SET
02784       && GET_CODE (SET_DEST (PATTERN (next))) == REG
02785       && REGNO (SET_DEST (PATTERN (next))) == 0)
02786     break;
02787 
02788         next = next_insn (next);
02789       }
02790 
02791     /* Is NEXT_INSN a branch?  */
02792     if (next
02793         && GET_CODE (next) == JUMP_INSN)
02794       {
02795         rtx pattern = PATTERN (next);
02796 
02797         /* If it a reversed fp conditional branch (eg uses add,tr)
02798      and CCFP dies, then reverse our conditional and the branch
02799      to avoid the add,tr.  */
02800         if (GET_CODE (pattern) == SET
02801       && SET_DEST (pattern) == pc_rtx
02802       && GET_CODE (SET_SRC (pattern)) == IF_THEN_ELSE
02803       && GET_CODE (XEXP (SET_SRC (pattern), 0)) == NE
02804       && GET_CODE (XEXP (XEXP (SET_SRC (pattern), 0), 0)) == REG
02805       && REGNO (XEXP (XEXP (SET_SRC (pattern), 0), 0)) == 0
02806       && GET_CODE (XEXP (SET_SRC (pattern), 1)) == PC
02807       && (fcmp_count == fbranch_count
02808           || (check_notes
02809         && find_regno_note (next, REG_DEAD, 0))))
02810     {
02811       /* Reverse the branch.  */
02812       tmp = XEXP (SET_SRC (pattern), 1);
02813       XEXP (SET_SRC (pattern), 1) = XEXP (SET_SRC (pattern), 2);
02814       XEXP (SET_SRC (pattern), 2) = tmp;
02815       INSN_CODE (next) = -1;
02816 
02817       /* Reverse our condition.  */
02818       tmp = PATTERN (insn);
02819       PUT_CODE (XEXP (tmp, 1),
02820           (reverse_condition_maybe_unordered
02821            (GET_CODE (XEXP (tmp, 1)))));
02822     }
02823       }
02824   }
02825     }
02826 
02827   pass = !pass;
02828 
02829 }
02830 
02831 /* You may have trouble believing this, but this is the 32 bit HP-PA
02832    stack layout.  Wow.
02833 
02834    Offset   Contents
02835 
02836    Variable arguments (optional; any number may be allocated)
02837 
02838    SP-(4*(N+9))   arg word N
02839     :       :
02840       SP-56   arg word 5
02841       SP-52   arg word 4
02842 
02843    Fixed arguments  (must be allocated; may remain unused)
02844 
02845       SP-48   arg word 3
02846       SP-44   arg word 2
02847       SP-40   arg word 1
02848       SP-36   arg word 0
02849 
02850    Frame Marker
02851 
02852       SP-32   External Data Pointer (DP)
02853       SP-28   External sr4
02854       SP-24   External/stub RP (RP')
02855       SP-20   Current RP
02856       SP-16   Static Link
02857       SP-12   Clean up
02858       SP-8    Calling Stub RP (RP'')
02859       SP-4    Previous SP
02860 
02861    Top of Frame
02862 
02863       SP-0    Stack Pointer (points to next available address)
02864 
02865 */
02866 
02867 /* This function saves registers as follows.  Registers marked with ' are
02868    this function's registers (as opposed to the previous function's).
02869    If a frame_pointer isn't needed, r4 is saved as a general register;
02870    the space for the frame pointer is still allocated, though, to keep
02871    things simple.
02872 
02873 
02874    Top of Frame
02875 
02876        SP (FP')   Previous FP
02877        SP + 4   Alignment filler (sigh)
02878        SP + 8   Space for locals reserved here.
02879        .
02880        .
02881        .
02882        SP + n   All call saved register used.
02883        .
02884        .
02885        .
02886        SP + o   All call saved fp registers used.
02887        .
02888        .
02889        .
02890        SP + p (SP') points to next available address.
02891 
02892 */
02893 
02894 /* Global variables set by output_function_prologue().  */
02895 /* Size of frame.  Need to know this to emit return insns from
02896    leaf procedures.  */
02897 static int actual_fsize;
02898 static int local_fsize, save_fregs;
02899 
02900 /* Emit RTL to store REG at the memory location specified by BASE+DISP.
02901    Handle case where DISP > 8k by using the add_high_const patterns.
02902 
02903    Note in DISP > 8k case, we will leave the high part of the address
02904    in %r1.  There is code in expand_hppa_{prologue,epilogue} that knows this.*/
02905 
02906 static void
02907 store_reg (reg, disp, base)
02908      int reg, disp, base;
02909 {
02910   rtx insn, dest, src, basereg;
02911 
02912   src = gen_rtx_REG (word_mode, reg);
02913   basereg = gen_rtx_REG (Pmode, base);
02914   if (VAL_14_BITS_P (disp))
02915     {
02916       dest = gen_rtx_MEM (word_mode, plus_constant (basereg, disp));
02917       insn = emit_move_insn (dest, src);
02918     }
02919   else
02920     {
02921       rtx delta = GEN_INT (disp);
02922       rtx high = gen_rtx_PLUS (Pmode, basereg, gen_rtx_HIGH (Pmode, delta));
02923       rtx tmpreg = gen_rtx_REG (Pmode, 1);
02924       emit_move_insn (tmpreg, high);
02925       dest = gen_rtx_MEM (word_mode, gen_rtx_LO_SUM (Pmode, tmpreg, delta));
02926       insn = emit_move_insn (dest, src);
02927       if (DO_FRAME_NOTES)
02928   {
02929     REG_NOTES (insn)
02930       = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
02931     gen_rtx_SET (VOIDmode,
02932            gen_rtx_MEM (word_mode,
02933             gen_rtx_PLUS (word_mode, basereg,
02934               delta)),
02935                              src),
02936                 REG_NOTES (insn));
02937   }
02938     }
02939 
02940   if (DO_FRAME_NOTES)
02941     RTX_FRAME_RELATED_P (insn) = 1;
02942 }
02943 
02944 /* Emit RTL to set REG to the value specified by BASE+DISP.
02945    Handle case where DISP > 8k by using the add_high_const patterns.
02946 
02947    Note in DISP > 8k case, we will leave the high part of the address
02948    in %r1.  There is code in expand_hppa_{prologue,epilogue} that knows this.*/
02949 
02950 static void
02951 set_reg_plus_d (reg, base, disp)
02952      int reg, base, disp;
02953 {
02954   rtx insn;
02955 
02956   if (VAL_14_BITS_P (disp))
02957     {
02958       insn = emit_move_insn (gen_rtx_REG (Pmode, reg),
02959            plus_constant (gen_rtx_REG (Pmode, base), disp));
02960     }
02961   else
02962     {
02963       rtx basereg = gen_rtx_REG (Pmode, base);
02964       rtx delta = GEN_INT (disp);
02965 
02966       emit_move_insn (gen_rtx_REG (Pmode, 1),
02967           gen_rtx_PLUS (Pmode, basereg,
02968             gen_rtx_HIGH (Pmode, delta)));
02969       insn = emit_move_insn (gen_rtx_REG (Pmode, reg),
02970            gen_rtx_LO_SUM (Pmode, gen_rtx_REG (Pmode, 1),
02971                delta));
02972     }
02973 
02974   if (DO_FRAME_NOTES && reg == STACK_POINTER_REGNUM)
02975     RTX_FRAME_RELATED_P (insn) = 1;
02976 }
02977 
02978 int
02979 compute_frame_size (size, fregs_live)
02980      int size;
02981      int *fregs_live;
02982 {
02983   int i, fsize;
02984 
02985   /* Space for frame pointer + filler. If any frame is allocated
02986      we need to add this in because of STARTING_FRAME_OFFSET.
02987 
02988      Similar code also appears in hppa_expand_prologue.  Change both
02989      of them at the same time.  */
02990   fsize = size + (size || frame_pointer_needed ? STARTING_FRAME_OFFSET : 0);
02991 
02992   /* Account for space used by the callee general register saves.  */
02993   for (i = 18; i >= 3; i--)
02994     if (regs_ever_live[i])
02995       fsize += UNITS_PER_WORD;
02996 
02997   /* Round the stack.  */
02998   fsize = (fsize + 7) & ~7;
02999 
03000   /* Account for space used by the callee floating point register saves.  */
03001   for (i = FP_SAVED_REG_LAST; i >= FP_SAVED_REG_FIRST; i -= FP_REG_STEP)
03002     if (regs_ever_live[i]
03003   || (! TARGET_64BIT && regs_ever_live[i + 1]))
03004       {
03005   if (fregs_live)
03006     *fregs_live = 1;
03007 
03008   /* We always save both halves of the FP register, so always
03009      increment the frame size by 8 bytes.  */
03010   fsize += 8;
03011       }
03012 
03013   /* The various ABIs include space for the outgoing parameters in the
03014      size of the current function's stack frame.  */
03015   fsize += current_function_outgoing_args_size;
03016 
03017   /* Allocate space for the fixed frame marker.  This space must be
03018      allocated for any function that makes calls or otherwise allocates
03019      stack space.  */
03020   if (!current_function_is_leaf || fsize)
03021     fsize += TARGET_64BIT ? 16 : 32;
03022 
03023   return (fsize + STACK_BOUNDARY - 1) & ~(STACK_BOUNDARY - 1);
03024 }
03025 
03026 /* Generate the assembly code for function entry.  FILE is a stdio
03027    stream to output the code to.  SIZE is an int: how many units of
03028    temporary storage to allocate.
03029 
03030    Refer to the array `regs_ever_live' to determine which registers to
03031    save; `regs_ever_live[I]' is nonzero if register number I is ever
03032    used in the function.  This function is responsible for knowing
03033    which registers should not be saved even if used.  */
03034 
03035 /* On HP-PA, move-double insns between fpu and cpu need an 8-byte block
03036    of memory.  If any fpu reg is used in the function, we allocate
03037    such a block here, at the bottom of the frame, just in case it's needed.
03038 
03039    If this function is a leaf procedure, then we may choose not
03040    to do a "save" insn.  The decision about whether or not
03041    to do this is made in regclass.c.  */
03042 
03043 void
03044 pa_output_function_prologue (file, size)
03045      FILE *file;
03046      HOST_WIDE_INT size ATTRIBUTE_UNUSED;
03047 {
03048   /* The function's label and associated .PROC must never be
03049      separated and must be output *after* any profiling declarations
03050      to avoid changing spaces/subspaces within a procedure.  */
03051   ASM_OUTPUT_LABEL (file, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));
03052   fputs ("\t.PROC\n", file);
03053 
03054   /* hppa_expand_prologue does the dirty work now.  We just need
03055      to output the assembler directives which denote the start
03056      of a function.  */
03057   fprintf (file, "\t.CALLINFO FRAME=%d", actual_fsize);
03058   if (regs_ever_live[2])
03059     fputs (",CALLS,SAVE_RP", file);
03060   else
03061     fputs (",NO_CALLS", file);
03062 
03063   if (frame_pointer_needed)
03064     fputs (",SAVE_SP", file);
03065 
03066   /* Pass on information about the number of callee register saves
03067      performed in the prologue.
03068 
03069      The compiler is supposed to pass the highest register number
03070      saved, the assembler then has to adjust that number before
03071      entering it into the unwind descriptor (to account for any
03072      caller saved registers with lower register numbers than the
03073      first callee saved register).  */
03074   if (gr_saved)
03075     fprintf (file, ",ENTRY_GR=%d", gr_saved + 2);
03076 
03077   if (fr_saved)
03078     fprintf (file, ",ENTRY_FR=%d", fr_saved + 11);
03079 
03080   fputs ("\n\t.ENTRY\n", file);
03081 
03082   remove_useless_addtr_insns (get_insns (), 0);
03083 }
03084 
03085 void
03086 hppa_expand_prologue ()
03087 {
03088   int size = get_frame_size ();
03089   int merge_sp_adjust_with_store = 0;
03090   int i, offset;
03091   rtx tmpreg, size_rtx;
03092 
03093   gr_saved = 0;
03094   fr_saved = 0;
03095   save_fregs = 0;
03096 
03097   /* Allocate space for frame pointer + filler. If any frame is allocated
03098      we need to add this in because of STARTING_FRAME_OFFSET.
03099 
03100      Similar code also appears in compute_frame_size.  Change both
03101      of them at the same time.  */
03102   local_fsize = size + (size || frame_pointer_needed
03103       ? STARTING_FRAME_OFFSET : 0);
03104 
03105   actual_fsize = compute_frame_size (size, &save_fregs);
03106 
03107   /* Compute a few things we will use often.  */
03108   tmpreg = gen_rtx_REG (word_mode, 1);
03109   size_rtx = GEN_INT (actual_fsize);
03110 
03111   /* Save RP first.  The calling conventions manual states RP will
03112      always be stored into the caller's frame at sp - 20 or sp - 16
03113      depending on which ABI is in use.  */
03114   if (regs_ever_live[2])
03115     store_reg (2, TARGET_64BIT ? -16 : -20, STACK_POINTER_REGNUM);
03116 
03117   /* Allocate the local frame and set up the frame pointer if needed.  */
03118   if (actual_fsize != 0)
03119     {
03120       if (frame_pointer_needed)
03121   {
03122     /* Copy the old frame pointer temporarily into %r1.  Set up the
03123        new stack pointer, then store away the saved old frame pointer
03124        into the stack at sp+actual_fsize and at the same time update
03125        the stack pointer by actual_fsize bytes.  Two versions, first
03126        handles small (<8k) frames.  The second handles large (>=8k)
03127        frames.  */
03128     emit_move_insn (tmpreg, frame_pointer_rtx);
03129     FRP (emit_move_insn (frame_pointer_rtx, stack_pointer_rtx));
03130     if (VAL_14_BITS_P (actual_fsize))
03131       {
03132         rtx insn = emit_insn (gen_post_store (stack_pointer_rtx, tmpreg,
03133                 size_rtx));
03134         if (DO_FRAME_NOTES)
03135     {
03136       rtvec vec;
03137       RTX_FRAME_RELATED_P (insn) = 1;
03138       vec = gen_rtvec (2,
03139            gen_rtx_SET (VOIDmode,
03140             gen_rtx_MEM (word_mode,
03141                    stack_pointer_rtx),
03142             frame_pointer_rtx),
03143            gen_rtx_SET (VOIDmode,
03144             stack_pointer_rtx,
03145             gen_rtx_PLUS (word_mode,
03146                     stack_pointer_rtx,
03147                     size_rtx)));
03148       REG_NOTES (insn)
03149         = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
03150            gen_rtx_SEQUENCE (VOIDmode, vec),
03151            REG_NOTES (insn));
03152     }
03153       }
03154     else
03155       {
03156         /* It is incorrect to store the saved frame pointer at *sp,
03157      then increment sp (writes beyond the current stack boundary).
03158 
03159      So instead use stwm to store at *sp and post-increment the
03160      stack pointer as an atomic operation.  Then increment sp to
03161      finish allocating the new frame.  */
03162         int adjust1 = 8192 - 64;
03163         int adjust2 = actual_fsize - adjust1;
03164         rtx delta = GEN_INT (adjust1);
03165         rtx insn = emit_insn (gen_post_store (stack_pointer_rtx, tmpreg,
03166                 delta));
03167         if (DO_FRAME_NOTES)
03168     {
03169       rtvec vec;
03170       RTX_FRAME_RELATED_P (insn) = 1;
03171       vec = gen_rtvec (2,
03172            gen_rtx_SET (VOIDmode,
03173             gen_rtx_MEM (word_mode,
03174                    stack_pointer_rtx),
03175             frame_pointer_rtx),
03176            gen_rtx_SET (VOIDmode,
03177             stack_pointer_rtx,
03178             gen_rtx_PLUS (word_mode,
03179                     stack_pointer_rtx,
03180                     delta)));
03181       REG_NOTES (insn)
03182         = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
03183            gen_rtx_SEQUENCE (VOIDmode, vec),
03184            REG_NOTES (insn));
03185     }
03186 
03187         set_reg_plus_d (STACK_POINTER_REGNUM, STACK_POINTER_REGNUM,
03188             adjust2);
03189       }
03190     /* Prevent register spills from being scheduled before the
03191        stack pointer is raised.  Necessary as we will be storing
03192        registers using the frame pointer as a base register, and
03193        we happen to set fp before raising sp.  */
03194     emit_insn (gen_blockage ());
03195   }
03196       /* no frame pointer needed.  */
03197       else
03198   {
03199     /* In some cases we can perform the first callee register save
03200        and allocating the stack frame at the same time.   If so, just
03201        make a note of it and defer allocating the frame until saving
03202        the callee registers.  */
03203     if (VAL_14_BITS_P (actual_fsize) && local_fsize == 0)
03204       merge_sp_adjust_with_store = 1;
03205     /* Can not optimize.  Adjust the stack frame by actual_fsize
03206        bytes.  */
03207     else
03208       set_reg_plus_d (STACK_POINTER_REGNUM, STACK_POINTER_REGNUM,
03209           actual_fsize);
03210   }
03211     }
03212 
03213   /* Normal register save.
03214 
03215      Do not save the frame pointer in the frame_pointer_needed case.  It
03216      was done earlier.  */
03217   if (frame_pointer_needed)
03218     {
03219       for (i = 18, offset = local_fsize; i >= 4; i--)
03220   if (regs_ever_live[i] && ! call_used_regs[i])
03221     {
03222       store_reg (i, offset, FRAME_POINTER_REGNUM);
03223       offset += UNITS_PER_WORD;
03224       gr_saved++;
03225     }
03226       /* Account for %r3 which is saved in a special place.  */
03227       gr_saved++;
03228     }
03229   /* No frame pointer needed.  */
03230   else
03231     {
03232       for (i = 18, offset = local_fsize - actual_fsize; i >= 3; i--)
03233         if (regs_ever_live[i] && ! call_used_regs[i])
03234     {
03235       /* If merge_sp_adjust_with_store is nonzero, then we can
03236          optimize the first GR save.  */
03237       if (merge_sp_adjust_with_store)
03238         {
03239     rtx delta = GEN_INT (-offset);
03240     merge_sp_adjust_with_store = 0;
03241           FRP (emit_insn (gen_post_store (stack_pointer_rtx,
03242             gen_rtx_REG (word_mode, i),
03243             delta)));
03244         }
03245       else
03246         store_reg (i, offset, STACK_POINTER_REGNUM);
03247       offset += UNITS_PER_WORD;
03248       gr_saved++;
03249     }
03250 
03251       /* If we wanted to merge the SP adjustment with a GR save, but we never
03252    did any GR saves, then just emit the adjustment here.  */
03253       if (merge_sp_adjust_with_store)
03254   set_reg_plus_d (STACK_POINTER_REGNUM, STACK_POINTER_REGNUM,
03255       actual_fsize);
03256     }
03257 
03258   /* The hppa calling conventions say that %r19, the pic offset
03259      register, is saved at sp - 32 (in this function's frame)
03260      when generating PIC code.  FIXME:  What is the correct thing
03261      to do for functions which make no calls and allocate no
03262      frame?  Do we need to allocate a frame, or can we just omit
03263      the save?   For now we'll just omit the save.  */
03264   if (flag_pic && actual_fsize != 0 && !TARGET_64BIT)
03265     store_reg (PIC_OFFSET_TABLE_REGNUM, -32, STACK_POINTER_REGNUM);
03266 
03267   /* Align pointer properly (doubleword boundary).  */
03268   offset = (offset + 7) & ~7;
03269 
03270   /* Floating point register store.  */
03271   if (save_fregs)
03272     {
03273       /* First get the frame or stack pointer to the start of the FP register
03274    save area.  */
03275       if (frame_pointer_needed)
03276   set_reg_plus_d (1, FRAME_POINTER_REGNUM, offset);
03277       else
03278   set_reg_plus_d (1, STACK_POINTER_REGNUM, offset);
03279 
03280       /* Now actually save the FP registers.  */
03281       for (i = FP_SAVED_REG_LAST; i >= FP_SAVED_REG_FIRST; i -= FP_REG_STEP)
03282   {
03283     if (regs_ever_live[i]
03284         || (! TARGET_64BIT && regs_ever_live[i + 1]))
03285       {
03286         rtx addr, insn, reg;
03287         addr = gen_rtx_MEM (DFmode, gen_rtx_POST_INC (DFmode, tmpreg));
03288         reg = gen_rtx_REG (DFmode, i);
03289         insn = emit_move_insn (addr, reg);
03290         if (DO_FRAME_NOTES)
03291     {
03292       RTX_FRAME_RELATED_P (insn) = 1;
03293       REG_NOTES (insn)
03294         = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
03295       gen_rtx_SET (VOIDmode,
03296         gen_rtx_MEM (DFmode,
03297                plus_constant (stack_pointer_rtx,
03298                   offset)),
03299         reg),
03300       REG_NOTES (insn));
03301     }
03302         offset += GET_MODE_SIZE (DFmode);
03303         fr_saved++;
03304       }
03305   }
03306     }
03307 }
03308 
03309 /* Emit RTL to load REG from the memory location specified by BASE+DISP.
03310    Handle case where DISP > 8k by using the add_high_const patterns.  */
03311 
03312 static void
03313 load_reg (reg, disp, base)
03314      int reg, disp, base;
03315 {
03316   rtx src, dest, basereg;
03317 
03318   dest = gen_rtx_REG (word_mode, reg);
03319   basereg = gen_rtx_REG (Pmode, base);
03320   if (VAL_14_BITS_P (disp))
03321     {
03322       src = gen_rtx_MEM (word_mode, plus_constant (basereg, disp));
03323       emit_move_insn (dest, src);
03324     }
03325   else
03326     {
03327       rtx delta = GEN_INT (disp);
03328       rtx high = gen_rtx_PLUS (Pmode, basereg, gen_rtx_HIGH (Pmode, delta));
03329       rtx tmpreg = gen_rtx_REG (Pmode, 1);
03330       emit_move_insn (tmpreg, high);
03331       src = gen_rtx_MEM (word_mode, gen_rtx_LO_SUM (Pmode, tmpreg, delta));
03332       emit_move_insn (dest, src);
03333     }
03334 }
03335 
03336 /* Return the last nonnote insn emitted in current sequence or current
03337    function.  This routine looks inside SEQUENCEs.  */
03338 
03339 static rtx
03340 get_last_nonnote_insn ()
03341 {
03342   rtx insn = get_last_insn ();
03343 
03344   while (insn)
03345     {
03346       insn = previous_insn (insn);
03347       if (insn == 0 || GET_CODE (insn) != NOTE)
03348   break;
03349     }
03350 
03351   return insn;
03352 }
03353 
03354 /* This function generates the assembly code for function exit.
03355    Args are as for output_function_prologue ().
03356 
03357    The function epilogue should not depend on the current stack
03358    pointer!  It should use the frame pointer only.  This is mandatory
03359    because of alloca; we also take advantage of it to omit stack
03360    adjustments before returning.  */
03361 
03362 static void
03363 pa_output_function_epilogue (file, size)
03364      FILE *file;
03365      HOST_WIDE_INT size ATTRIBUTE_UNUSED;
03366 {
03367   int last_address = 0;
03368   rtx insn = get_last_insn ();
03369 
03370   /* hppa_expand_epilogue does the dirty work now.  We just need
03371      to output the assembler directives which denote the end
03372      of a function.
03373 
03374      To make debuggers happy, emit a nop if the epilogue was completely
03375      eliminated due to a volatile call as the last insn in the
03376      current function.  That way the return address (in %r2) will
03377      always point to a valid instruction in the current function.  */
03378 
03379   /* Get the last real insn.  */
03380   if (GET_CODE (insn) == NOTE)
03381     insn = prev_real_insn (insn);
03382 
03383   /* If it is a sequence, then look inside.  */
03384   if (insn && GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
03385     insn = XVECEXP (PATTERN (insn), 0, 0);
03386 
03387   /* If insn is a CALL_INSN, then it must be a call to a volatile
03388      function (otherwise there would be epilogue insns).  */
03389   if (insn && GET_CODE (insn) == CALL_INSN)
03390     {
03391       fputs ("\tnop\n", file);
03392       last_address += 4;
03393     }
03394 
03395   fputs ("\t.EXIT\n\t.PROCEND\n", file);
03396 
03397   /* Finally, update the total number of code bytes output so far.  */
03398   if ((TARGET_PORTABLE_RUNTIME || !TARGET_GAS || !TARGET_SOM)
03399       && !flag_function_sections)
03400     {
03401       if (INSN_ADDRESSES_SET_P ())
03402   {
03403     unsigned long old_total = total_code_bytes;
03404 
03405     insn = get_last_nonnote_insn ();
03406     last_address += INSN_ADDRESSES (INSN_UID (insn));
03407     if (INSN_P (insn))
03408       last_address += insn_default_length (insn);
03409 
03410     total_code_bytes += last_address;
03411     total_code_bytes += FUNCTION_BOUNDARY / BITS_PER_UNIT;
03412 
03413     /* Be prepared to handle overflows.  */
03414     if (old_total > total_code_bytes)
03415       total_code_bytes = -1;
03416   }
03417       else
03418   total_code_bytes = -1;
03419     }
03420 }
03421 
03422 void
03423 hppa_expand_epilogue ()
03424 {
03425   rtx tmpreg;
03426   int offset, i;
03427   int merge_sp_adjust_with_load = 0;
03428   int ret_off = 0;
03429 
03430   /* We will use this often.  */
03431   tmpreg = gen_rtx_REG (word_mode, 1);
03432 
03433   /* Try to restore RP early to avoid load/use interlocks when
03434      RP gets used in the return (bv) instruction.  This appears to still
03435      be necessary even when we schedule the prologue and epilogue.  */
03436   if (regs_ever_live [2])
03437     {
03438       ret_off = TARGET_64BIT ? -16 : -20;
03439       if (frame_pointer_needed)
03440   {
03441     load_reg (2, ret_off, FRAME_POINTER_REGNUM);
03442     ret_off = 0;
03443   }
03444       else
03445   {
03446     /* No frame pointer, and stack is smaller than 8k.  */
03447     if (VAL_14_BITS_P (ret_off - actual_fsize))
03448       {
03449         load_reg (2, ret_off - actual_fsize, STACK_POINTER_REGNUM);
03450         ret_off = 0;
03451       }
03452   }
03453     }
03454 
03455   /* General register restores.  */
03456   if (frame_pointer_needed)
03457     {
03458       for (i = 18, offset = local_fsize; i >= 4; i--)
03459   if (regs_ever_live[i] && ! call_used_regs[i])
03460     {
03461       load_reg (i, offset, FRAME_POINTER_REGNUM);
03462       offset += UNITS_PER_WORD;
03463     }
03464     }
03465   else
03466     {
03467       for (i = 18, offset = local_fsize - actual_fsize; i >= 3; i--)
03468   {
03469     if (regs_ever_live[i] && ! call_used_regs[i])
03470       {
03471         /* Only for the first load.
03472            merge_sp_adjust_with_load holds the register load
03473            with which we will merge the sp adjustment.  */
03474         if (merge_sp_adjust_with_load == 0
03475       && local_fsize == 0
03476       && VAL_14_BITS_P (-actual_fsize))
03477           merge_sp_adjust_with_load = i;
03478         else
03479     load_reg (i, offset, STACK_POINTER_REGNUM);
03480         offset += UNITS_PER_WORD;
03481       }
03482   }
03483     }
03484 
03485   /* Align pointer properly (doubleword boundary).  */
03486   offset = (offset + 7) & ~7;
03487 
03488   /* FP register restores.  */
03489   if (save_fregs)
03490     {
03491       /* Adjust the register to index off of.  */
03492       if (frame_pointer_needed)
03493   set_reg_plus_d (1, FRAME_POINTER_REGNUM, offset);
03494       else
03495   set_reg_plus_d (1, STACK_POINTER_REGNUM, offset);
03496 
03497       /* Actually do the restores now.  */
03498       for (i = FP_SAVED_REG_LAST; i >= FP_SAVED_REG_FIRST; i -= FP_REG_STEP)
03499   if (regs_ever_live[i]
03500       || (! TARGET_64BIT && regs_ever_live[i + 1]))
03501     {
03502       rtx src = gen_rtx_MEM (DFmode, gen_rtx_POST_INC (DFmode, tmpreg));
03503       rtx dest = gen_rtx_REG (DFmode, i);
03504       emit_move_insn (dest, src);
03505     }
03506     }
03507 
03508   /* Emit a blockage insn here to keep these insns from being moved to
03509      an earlier spot in the epilogue, or into the main instruction stream.
03510 
03511      This is necessary as we must not cut the stack back before all the
03512      restores are finished.  */
03513   emit_insn (gen_blockage ());
03514 
03515   /* Reset stack pointer (and possibly frame pointer).  The stack
03516      pointer is initially set to fp + 64 to avoid a race condition.  */
03517   if (frame_pointer_needed)
03518     {
03519       rtx delta = GEN_INT (-64);
03520       rtx insn;
03521       set_reg_plus_d (STACK_POINTER_REGNUM, FRAME_POINTER_REGNUM, 64);
03522       insn = emit_insn (gen_pre_load (frame_pointer_rtx, stack_pointer_rtx,
03523               delta));
03524       if (DO_FRAME_NOTES)
03525   {
03526     RTX_FRAME_RELATED_P (insn) = 1;
03527     REG_NOTES (insn)
03528       = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
03529     gen_rtx_SET (VOIDmode, stack_pointer_rtx,
03530            gen_rtx_PLUS (word_mode, stack_pointer_rtx,
03531              delta)),
03532                 REG_NOTES (insn));
03533   }
03534     }
03535   /* If we were deferring a callee register restore, do it now.  */
03536   else if (merge_sp_adjust_with_load)
03537     {
03538       rtx delta = GEN_INT (-actual_fsize);
03539       rtx dest = gen_rtx_REG (word_mode, merge_sp_adjust_with_load);
03540       rtx insn = emit_insn (gen_pre_load (dest, stack_pointer_rtx, delta));
03541       if (DO_FRAME_NOTES)
03542   {
03543     RTX_FRAME_RELATED_P (insn) = 1;
03544     REG_NOTES (insn)
03545       = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
03546     gen_rtx_SET (VOIDmode, stack_pointer_rtx,
03547            gen_rtx_PLUS (word_mode, stack_pointer_rtx,
03548              delta)),
03549                 REG_NOTES (insn));
03550   }
03551     }
03552   else if (actual_fsize != 0)
03553     set_reg_plus_d (STACK_POINTER_REGNUM, STACK_POINTER_REGNUM, - actual_fsize);
03554 
03555   /* If we haven't restored %r2 yet (no frame pointer, and a stack
03556      frame greater than 8k), do so now.  */
03557   if (ret_off != 0)
03558     load_reg (2, ret_off, STACK_POINTER_REGNUM);
03559 }
03560 
03561 rtx
03562 hppa_pic_save_rtx ()
03563 {
03564   return get_hard_reg_initial_val (word_mode, PIC_OFFSET_TABLE_REGNUM);
03565 }
03566 
03567 void
03568 hppa_profile_hook (label_no)
03569      int label_no;
03570 {
03571   rtx begin_label_rtx, call_insn;
03572   char begin_label_name[16];
03573 
03574   ASM_GENERATE_INTERNAL_LABEL (begin_label_name, FUNC_BEGIN_PROLOG_LABEL,
03575              label_no);
03576   begin_label_rtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (begin_label_name));
03577 
03578   if (TARGET_64BIT)
03579     emit_move_insn (arg_pointer_rtx,
03580         gen_rtx_PLUS (word_mode, virtual_outgoing_args_rtx,
03581           GEN_INT (64)));
03582 
03583   emit_move_insn (gen_rtx_REG (word_mode, 26), gen_rtx_REG (word_mode, 2));
03584 
03585 #ifndef NO_PROFILE_COUNTERS
03586   {
03587     rtx count_label_rtx, addr, r24;
03588     char count_label_name[16];
03589 
03590     ASM_GENERATE_INTERNAL_LABEL (count_label_name, "LP", label_no);
03591     count_label_rtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (count_label_name));
03592 
03593     addr = force_reg (Pmode, count_label_rtx);
03594     r24 = gen_rtx_REG (Pmode, 24);
03595     emit_move_insn (r24, addr);
03596 
03597     /* %r25 is set from within the output pattern.  */
03598     call_insn =
03599       emit_call_insn (gen_call_profiler (gen_rtx_SYMBOL_REF (Pmode, "_mcount"),
03600            GEN_INT (TARGET_64BIT ? 24 : 12),
03601            begin_label_rtx));
03602 
03603     use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), r24);
03604   }
03605 #else
03606     /* %r25 is set from within the output pattern.  */
03607   call_insn =
03608     emit_call_insn (gen_call_profiler (gen_rtx_SYMBOL_REF (Pmode, "_mcount"),
03609                GEN_INT (TARGET_64BIT ? 16 : 8),
03610                begin_label_rtx));
03611 #endif
03612 
03613   /* Indicate the _mcount call cannot throw, nor will it execute a
03614      non-local goto.  */
03615   REG_NOTES (call_insn)
03616     = gen_rtx_EXPR_LIST (REG_EH_REGION, constm1_rtx, REG_NOTES (call_insn));
03617 
03618   if (flag_pic)
03619     {
03620       use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), pic_offset_table_rtx);
03621       if (TARGET_64BIT)
03622   use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), arg_pointer_rtx);
03623 
03624       emit_move_insn (pic_offset_table_rtx, hppa_pic_save_rtx ());
03625     }
03626 }
03627 
03628 /* Fetch the return address for the frame COUNT steps up from
03629    the current frame, after the prologue.  FRAMEADDR is the
03630    frame pointer of the COUNT frame.
03631 
03632    We want to ignore any export stub remnants here.  To handle this,
03633    we examine the code at the return address, and if it is an export
03634    stub, we return a memory rtx for the stub return address stored
03635    at frame-24.
03636 
03637    The value returned is used in two different ways:
03638 
03639   1. To find a function's caller.
03640 
03641   2. To change the return address for a function.
03642 
03643    This function handles most instances of case 1; however, it will
03644    fail if there are two levels of stubs to execute on the return
03645    path.  The only way I believe that can happen is if the return value
03646    needs a parameter relocation, which never happens for C code.
03647 
03648    This function handles most instances of case 2; however, it will
03649    fail if we did not originally have stub code on the return path
03650    but will need stub code on the new return path.  This can happen if
03651    the caller & callee are both in the main program, but the new
03652    return location is in a shared library.  */
03653 
03654 rtx
03655 return_addr_rtx (count, frameaddr)
03656      int count;
03657      rtx frameaddr;
03658 {
03659   rtx label;
03660   rtx rp;
03661   rtx saved_rp;
03662   rtx ins;
03663 
03664   if (count != 0)
03665     return NULL_RTX;
03666 
03667   rp = get_hard_reg_initial_val (Pmode, 2);
03668 
03669   if (TARGET_64BIT || TARGET_NO_SPACE_REGS)
03670     return rp;
03671 
03672   saved_rp = gen_reg_rtx (Pmode);
03673   emit_move_insn (saved_rp, rp);
03674 
03675   /* Get pointer to the instruction stream.  We have to mask out the
03676      privilege level from the two low order bits of the return address
03677      pointer here so that ins will point to the start of the first
03678      instruction that would have been executed if we returned.  */
03679   ins = copy_to_reg (gen_rtx_AND (Pmode, rp, MASK_RETURN_ADDR));
03680   label = gen_label_rtx ();
03681 
03682   /* Check the instruction stream at the normal return address for the
03683      export stub:
03684 
03685   0x4bc23fd1 | stub+8:   ldw -18(sr0,sp),rp
03686   0x004010a1 | stub+12:  ldsid (sr0,rp),r1
03687   0x00011820 | stub+16:  mtsp r1,sr0
03688   0xe0400002 | stub+20:  be,n 0(sr0,rp)
03689 
03690      If it is an export stub, than our return address is really in
03691      -24[frameaddr].  */
03692 
03693   emit_cmp_insn (gen_rtx_MEM (SImode, ins), GEN_INT (0x4bc23fd1), NE,
03694      NULL_RTX, SImode, 1);
03695   emit_jump_insn (gen_bne (label));
03696 
03697   emit_cmp_insn (gen_rtx_MEM (SImode, plus_constant (ins, 4)),
03698      GEN_INT (0x004010a1), NE, NULL_RTX, SImode, 1);
03699   emit_jump_insn (gen_bne (label));
03700 
03701   emit_cmp_insn (gen_rtx_MEM (SImode, plus_constant (ins, 8)),
03702      GEN_INT (0x00011820), NE, NULL_RTX, SImode, 1);
03703   emit_jump_insn (gen_bne (label));
03704 
03705   emit_cmp_insn (gen_rtx_MEM (SImode, plus_constant (ins, 12)),
03706      GEN_INT (0xe0400002), NE, NULL_RTX, SImode, 1);
03707 
03708   /* If there is no export stub then just use the value saved from
03709      the return pointer register.  */
03710 
03711   emit_jump_insn (gen_bne (label));
03712 
03713   /* Here we know that our return address points to an export
03714      stub.  We don't want to return the address of the export stub,
03715      but rather the return address of the export stub.  That return
03716      address is stored at -24[frameaddr].  */
03717 
03718   emit_move_insn (saved_rp,
03719       gen_rtx_MEM (Pmode,
03720              memory_address (Pmode,
03721                  plus_constant (frameaddr,
03722                     -24))));
03723 
03724   emit_label (label);
03725   return saved_rp;
03726 }
03727 
03728 /* This is only valid once reload has completed because it depends on
03729    knowing exactly how much (if any) frame there is and...
03730 
03731    It's only valid if there is no frame marker to de-allocate and...
03732 
03733    It's only valid if %r2 hasn't been saved into the caller's frame
03734    (we're not profiling and %r2 isn't live anywhere).  */
03735 int
03736 hppa_can_use_return_insn_p ()
03737 {
03738   return (reload_completed
03739     && (compute_frame_size (get_frame_size (), 0) ? 0 : 1)
03740     && ! regs_ever_live[2]
03741     && ! frame_pointer_needed);
03742 }
03743 
03744 void
03745 emit_bcond_fp (code, operand0)
03746      enum rtx_code code;
03747      rtx operand0;
03748 {
03749   emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
03750              gen_rtx_IF_THEN_ELSE (VOIDmode,
03751                  gen_rtx_fmt_ee (code,
03752                     VOIDmode,
03753                     gen_rtx_REG (CCFPmode, 0),
03754                     const0_rtx),
03755                  gen_rtx_LABEL_REF (VOIDmode, operand0),
03756                  pc_rtx)));
03757 
03758 }
03759 
03760 rtx
03761 gen_cmp_fp (code, operand0, operand1)
03762      enum rtx_code code;
03763      rtx operand0, operand1;
03764 {
03765   return gen_rtx_SET (VOIDmode, gen_rtx_REG (CCFPmode, 0),
03766           gen_rtx_fmt_ee (code, CCFPmode, operand0, operand1));
03767 }
03768 
03769 /* Adjust the cost of a scheduling dependency.  Return the new cost of
03770    a dependency LINK or INSN on DEP_INSN.  COST is the current cost.  */
03771 
03772 static int
03773 pa_adjust_cost (insn, link, dep_insn, cost)
03774      rtx insn;
03775      rtx link;
03776      rtx dep_insn;
03777      int cost;
03778 {
03779   enum attr_type attr_type;
03780 
03781   /* Don't adjust costs for a pa8000 chip.  */
03782   if (pa_cpu >= PROCESSOR_8000)
03783     return cost;
03784 
03785   if (! recog_memoized (insn))
03786     return 0;
03787 
03788   attr_type = get_attr_type (insn);
03789 
03790   if (REG_NOTE_KIND (link) == 0)
03791     {
03792       /* Data dependency; DEP_INSN writes a register that INSN reads some
03793    cycles later.  */
03794 
03795       if (attr_type == TYPE_FPSTORE)
03796   {
03797     rtx pat = PATTERN (insn);
03798     rtx dep_pat = PATTERN (dep_insn);
03799     if (GET_CODE (pat) == PARALLEL)
03800       {
03801         /* This happens for the fstXs,mb patterns.  */
03802         pat = XVECEXP (pat, 0, 0);
03803       }
03804     if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
03805       /* If this happens, we have to extend this to schedule
03806          optimally.  Return 0 for now.  */
03807     return 0;
03808 
03809     if (rtx_equal_p (SET_DEST (dep_pat), SET_SRC (pat)))
03810       {
03811         if (! recog_memoized (dep_insn))
03812     return 0;
03813         /* DEP_INSN is writing its result to the register
03814      being stored in the fpstore INSN.  */
03815         switch (get_attr_type (dep_insn))
03816     {
03817     case TYPE_FPLOAD:
03818       /* This cost 3 cycles, not 2 as the md says for the
03819          700 and 7100.  */
03820       return cost + 1;
03821 
03822     case TYPE_FPALU:
03823     case TYPE_FPMULSGL:
03824     case TYPE_FPMULDBL:
03825     case TYPE_FPDIVSGL:
03826     case TYPE_FPDIVDBL:
03827     case TYPE_FPSQRTSGL:
03828     case TYPE_FPSQRTDBL:
03829       /* In these important cases, we save one cycle compared to
03830          when flop instruction feed each other.  */
03831       return cost - 1;
03832 
03833     default:
03834       return cost;
03835     }
03836       }
03837   }
03838 
03839       /* For other data dependencies, the default cost specified in the
03840    md is correct.  */
03841       return cost;
03842     }
03843   else if (REG_NOTE_KIND (link) == REG_DEP_ANTI)
03844     {
03845       /* Anti dependency; DEP_INSN reads a register that INSN writes some
03846    cycles later.  */
03847 
03848       if (attr_type == TYPE_FPLOAD)
03849   {
03850     rtx pat = PATTERN (insn);
03851     rtx dep_pat = PATTERN (dep_insn);
03852     if (GET_CODE (pat) == PARALLEL)
03853       {
03854         /* This happens for the fldXs,mb patterns.  */
03855         pat = XVECEXP (pat, 0, 0);
03856       }
03857     if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
03858       /* If this happens, we have to extend this to schedule
03859          optimally.  Return 0 for now.  */
03860     return 0;
03861 
03862     if (reg_mentioned_p (SET_DEST (pat), SET_SRC (dep_pat)))
03863       {
03864         if (! recog_memoized (dep_insn))
03865     return 0;
03866         switch (get_attr_type (dep_insn))
03867     {
03868     case TYPE_FPALU:
03869     case TYPE_FPMULSGL:
03870     case TYPE_FPMULDBL:
03871     case TYPE_FPDIVSGL:
03872     case TYPE_FPDIVDBL:
03873     case TYPE_FPSQRTSGL:
03874     case TYPE_FPSQRTDBL:
03875       /* A fpload can't be issued until one cycle before a
03876          preceding arithmetic operation has finished if
03877          the target of the fpload is any of the sources
03878          (or destination) of the arithmetic operation.  */
03879       return cost - 1;
03880 
03881     default:
03882       return 0;
03883     }
03884       }
03885   }
03886       else if (attr_type == TYPE_FPALU)
03887   {
03888     rtx pat = PATTERN (insn);
03889     rtx dep_pat = PATTERN (dep_insn);
03890     if (GET_CODE (pat) == PARALLEL)
03891       {
03892         /* This happens for the fldXs,mb patterns.  */
03893         pat = XVECEXP (pat, 0, 0);
03894       }
03895     if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
03896       /* If this happens, we have to extend this to schedule
03897          optimally.  Return 0 for now.  */
03898     return 0;
03899 
03900     if (reg_mentioned_p (SET_DEST (pat), SET_SRC (dep_pat)))
03901       {
03902         if (! recog_memoized (dep_insn))
03903     return 0;
03904         switch (get_attr_type (dep_insn))
03905     {
03906     case TYPE_FPDIVSGL:
03907     case TYPE_FPDIVDBL:
03908     case TYPE_FPSQRTSGL:
03909     case TYPE_FPSQRTDBL:
03910       /* An ALU flop can't be issued until two cycles before a
03911          preceding divide or sqrt operation has finished if
03912          the target of the ALU flop is any of the sources
03913          (or destination) of the divide or sqrt operation.  */
03914       return cost - 2;
03915 
03916     default:
03917       return 0;
03918     }
03919       }
03920   }
03921 
03922       /* For other anti dependencies, the cost is 0.  */
03923       return 0;
03924     }
03925   else if (REG_NOTE_KIND (link) == REG_DEP_OUTPUT)
03926     {
03927       /* Output dependency; DEP_INSN writes a register that INSN writes some
03928    cycles later.  */
03929       if (attr_type == TYPE_FPLOAD)
03930   {
03931     rtx pat = PATTERN (insn);
03932     rtx dep_pat = PATTERN (dep_insn);
03933     if (GET_CODE (pat) == PARALLEL)
03934       {
03935         /* This happens for the fldXs,mb patterns.  */
03936         pat = XVECEXP (pat, 0, 0);
03937       }
03938     if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
03939       /* If this happens, we have to extend this to schedule
03940          optimally.  Return 0 for now.  */
03941     return 0;
03942 
03943     if (reg_mentioned_p (SET_DEST (pat), SET_DEST (dep_pat)))
03944       {
03945         if (! recog_memoized (dep_insn))
03946     return 0;
03947         switch (get_attr_type (dep_insn))
03948     {
03949     case TYPE_FPALU:
03950     case TYPE_FPMULSGL:
03951     case TYPE_FPMULDBL:
03952     case TYPE_FPDIVSGL:
03953     case TYPE_FPDIVDBL:
03954     case TYPE_FPSQRTSGL:
03955     case TYPE_FPSQRTDBL:
03956       /* A fpload can't be issued until one cycle before a
03957          preceding arithmetic operation has finished if
03958          the target of the fpload is the destination of the
03959          arithmetic operation.  */
03960       return cost - 1;
03961 
03962     default:
03963       return 0;
03964     }
03965       }
03966   }
03967       else if (attr_type == TYPE_FPALU)
03968   {
03969     rtx pat = PATTERN (insn);
03970     rtx dep_pat = PATTERN (dep_insn);
03971     if (GET_CODE (pat) == PARALLEL)
03972       {
03973         /* This happens for the fldXs,mb patterns.  */
03974         pat = XVECEXP (pat, 0, 0);
03975       }
03976     if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
03977       /* If this happens, we have to extend this to schedule
03978          optimally.  Return 0 for now.  */
03979     return 0;
03980 
03981     if (reg_mentioned_p (SET_DEST (pat), SET_DEST (dep_pat)))
03982       {
03983         if (! recog_memoized (dep_insn))
03984     return 0;
03985         switch (get_attr_type (dep_insn))
03986     {
03987     case TYPE_FPDIVSGL:
03988     case TYPE_FPDIVDBL:
03989     case TYPE_FPSQRTSGL:
03990     case TYPE_FPSQRTDBL:
03991       /* An ALU flop can't be issued until two cycles before a
03992          preceding divide or sqrt operation has finished if
03993          the target of the ALU flop is also the target of
03994          the divide or sqrt operation.  */
03995       return cost - 2;
03996 
03997     default:
03998       return 0;
03999     }
04000       }
04001   }
04002 
04003       /* For other output dependencies, the cost is 0.  */
04004       return 0;
04005     }
04006   else
04007     abort ();
04008 }
04009 
04010 /* Adjust scheduling priorities.  We use this to try and keep addil
04011    and the next use of %r1 close together.  */
04012 static int
04013 pa_adjust_priority (insn, priority)
04014      rtx insn;
04015      int priority;
04016 {
04017   rtx set = single_set (insn);
04018   rtx src, dest;
04019   if (set)
04020     {
04021       src = SET_SRC (set);
04022       dest = SET_DEST (set);
04023       if (GET_CODE (src) == LO_SUM
04024     && symbolic_operand (XEXP (src, 1), VOIDmode)
04025     && ! read_only_operand (XEXP (src, 1), VOIDmode))
04026   priority >>= 3;
04027 
04028       else if (GET_CODE (src) == MEM
04029          && GET_CODE (XEXP (src, 0)) == LO_SUM
04030          && symbolic_operand (XEXP (XEXP (src, 0), 1), VOIDmode)
04031          && ! read_only_operand (XEXP (XEXP (src, 0), 1), VOIDmode))
04032   priority >>= 1;
04033 
04034       else if (GET_CODE (dest) == MEM
04035          && GET_CODE (XEXP (dest, 0)) == LO_SUM
04036          && symbolic_operand (XEXP (XEXP (dest, 0), 1), VOIDmode)
04037          && ! read_only_operand (XEXP (XEXP (dest, 0), 1), VOIDmode))
04038   priority >>= 3;
04039     }
04040   return priority;
04041 }
04042 
04043 /* The 700 can only issue a single insn at a time.
04044    The 7XXX processors can issue two insns at a time.
04045    The 8000 can issue 4 insns at a time.  */
04046 static int
04047 pa_issue_rate ()
04048 {
04049   switch (pa_cpu)
04050     {
04051     case PROCESSOR_700:   return 1;
04052     case PROCESSOR_7100:  return 2;
04053     case PROCESSOR_7100LC:  return 2;
04054     case PROCESSOR_7200:  return 2;
04055     case PROCESSOR_8000:  return 4;
04056 
04057     default:
04058       abort ();
04059     }
04060 }
04061 
04062 
04063 
04064 /* Return any length adjustment needed by INSN which already has its length
04065    computed as LENGTH.   Return zero if no adjustment is necessary.
04066 
04067    For the PA: function calls, millicode calls, and backwards short
04068    conditional branches with unfilled delay slots need an adjustment by +1
04069    (to account for the NOP which will be inserted into the instruction stream).
04070 
04071    Also compute the length of an inline block move here as it is too
04072    complicated to express as a length attribute in pa.md.  */
04073 int
04074 pa_adjust_insn_length (insn, length)
04075     rtx insn;
04076     int length;
04077 {
04078   rtx pat = PATTERN (insn);
04079 
04080   /* Call insns which are *not* indirect and have unfilled delay slots.  */
04081   if (GET_CODE (insn) == CALL_INSN)
04082     {
04083 
04084       if (GET_CODE (XVECEXP (pat, 0, 0)) == CALL
04085     && GET_CODE (XEXP (XEXP (XVECEXP (pat, 0, 0), 0), 0)) == SYMBOL_REF)
04086   return 4;
04087       else if (GET_CODE (XVECEXP (pat, 0, 0)) == SET
04088          && GET_CODE (XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0), 0))
04089       == SYMBOL_REF)
04090   return 4;
04091       else
04092   return 0;
04093     }
04094   /* Jumps inside switch tables which have unfilled delay slots
04095      also need adjustment.  */
04096   else if (GET_CODE (insn) == JUMP_INSN
04097      && simplejump_p (insn)
04098      && GET_MODE (insn) == SImode)
04099     return 4;
04100   /* Millicode insn with an unfilled delay slot.  */
04101   else if (GET_CODE (insn) == INSN
04102      && GET_CODE (pat) != SEQUENCE
04103      && GET_CODE (pat) != USE
04104      && GET_CODE (pat) != CLOBBER
04105      && get_attr_type (insn) == TYPE_MILLI)
04106     return 4;
04107   /* Block move pattern.  */
04108   else if (GET_CODE (insn) == INSN
04109      && GET_CODE (pat) == PARALLEL
04110      && GET_CODE (XVECEXP (pat, 0, 0)) == SET
04111      && GET_CODE (XEXP (XVECEXP (pat, 0, 0), 0)) == MEM
04112      && GET_CODE (XEXP (XVECEXP (pat, 0, 0), 1)) == MEM
04113      && GET_MODE (XEXP (XVECEXP (pat, 0, 0), 0)) == BLKmode
04114      && GET_MODE (XEXP (XVECEXP (pat, 0, 0), 1)) == BLKmode)
04115     return compute_movstrsi_length (insn) - 4;
04116   /* Conditional branch with an unfilled delay slot.  */
04117   else if (GET_CODE (insn) == JUMP_INSN && ! simplejump_p (insn))
04118     {
04119       /* Adjust a short backwards conditional with an unfilled delay slot.  */
04120       if (GET_CODE (pat) == SET
04121     && length == 4
04122     && ! forward_branch_p (insn))
04123   return 4;
04124       else if (GET_CODE (pat) == PARALLEL
04125          && get_attr_type (insn) == TYPE_PARALLEL_BRANCH
04126          && length == 4)
04127   return 4;
04128       /* Adjust dbra insn with short backwards conditional branch with
04129    unfilled delay slot -- only for case where counter is in a
04130    general register register.  */
04131       else if (GET_CODE (pat) == PARALLEL
04132          && GET_CODE (XVECEXP (pat, 0, 1)) == SET
04133          && GET_CODE (XEXP (XVECEXP (pat, 0, 1), 0)) == REG
04134          && ! FP_REG_P (XEXP (XVECEXP (pat, 0, 1), 0))
04135          && length == 4
04136          && ! forward_branch_p (insn))
04137   return 4;
04138       else
04139   return 0;
04140     }
04141   return 0;
04142 }
04143 
04144 /* Print operand X (an rtx) in assembler syntax to file FILE.
04145    CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
04146    For `%' followed by punctuation, CODE is the punctuation and X is null.  */
04147 
04148 void
04149 print_operand (file, x, code)
04150      FILE *file;
04151      rtx x;
04152      int code;
04153 {
04154   switch (code)
04155     {
04156     case '#':
04157       /* Output a 'nop' if there's nothing for the delay slot.  */
04158       if (dbr_sequence_length () == 0)
04159   fputs ("\n\tnop", file);
04160       return;
04161     case '*':
04162       /* Output an nullification completer if there's nothing for the */
04163       /* delay slot or nullification is requested.  */
04164       if (dbr_sequence_length () == 0 ||
04165     (final_sequence &&
04166      INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))))
04167         fputs (",n", file);
04168       return;
04169     case 'R':
04170       /* Print out the second register name of a register pair.
04171    I.e., R (6) => 7.  */
04172       fputs (reg_names[REGNO (x) + 1], file);
04173       return;
04174     case 'r':
04175       /* A register or zero.  */
04176       if (x == const0_rtx
04177     || (x == CONST0_RTX (DFmode))
04178     || (x == CONST0_RTX (SFmode)))
04179   {
04180     fputs ("%r0", file);
04181     return;
04182   }
04183       else
04184   break;
04185     case 'f':
04186       /* A register or zero (floating point).  */
04187       if (x == const0_rtx
04188     || (x == CONST0_RTX (DFmode))
04189     || (x == CONST0_RTX (SFmode)))
04190   {
04191     fputs ("%fr0", file);
04192     return;
04193   }
04194       else
04195   break;
04196     case 'A':
04197       {
04198   rtx xoperands[2];
04199 
04200   xoperands[0] = XEXP (XEXP (x, 0), 0);
04201   xoperands[1] = XVECEXP (XEXP (XEXP (x, 0), 1), 0, 0);
04202   output_global_address (file, xoperands[1], 0);
04203         fprintf (file, "(%s)", reg_names [REGNO (xoperands[0])]);
04204   return;
04205       }
04206 
04207     case 'C':     /* Plain (C)ondition */
04208     case 'X':
04209       switch (GET_CODE (x))
04210   {
04211   case EQ:
04212     fputs ("=", file);  break;
04213   case NE:
04214     fputs ("<>", file);  break;
04215   case GT:
04216     fputs (">", file);  break;
04217   case GE:
04218     fputs (">=", file);  break;
04219   case GEU:
04220     fputs (">>=", file);  break;
04221   case GTU:
04222     fputs (">>", file);  break;
04223   case LT:
04224     fputs ("<", file);  break;
04225   case LE:
04226     fputs ("<=", file);  break;
04227   case LEU:
04228     fputs ("<<=", file);  break;
04229   case LTU:
04230     fputs ("<<", file);  break;
04231   default:
04232     abort ();
04233   }
04234       return;
04235     case 'N':     /* Condition, (N)egated */
04236       switch (GET_CODE (x))
04237   {
04238   case EQ:
04239     fputs ("<>", file);  break;
04240   case NE:
04241     fputs ("=", file);  break;
04242   case GT:
04243     fputs ("<=", file);  break;
04244   case GE:
04245     fputs ("<", file);  break;
04246   case GEU:
04247     fputs ("<<", file);  break;
04248   case GTU:
04249     fputs ("<<=", file);  break;
04250   case LT:
04251     fputs (">=", file);  break;
04252   case LE:
04253     fputs (">", file);  break;
04254   case LEU:
04255     fputs (">>", file);  break;
04256   case LTU:
04257     fputs (">>=", file);  break;
04258   default:
04259     abort ();
04260   }
04261       return;
04262     /* For floating point comparisons.  Note that the output
04263        predicates are the complement of the desired mode.  */
04264     case 'Y':
04265       switch (GET_CODE (x))
04266   {
04267   case EQ:
04268     fputs ("!=", file);  break;
04269   case NE:
04270     fputs ("=", file);  break;
04271   case GT:
04272     fputs ("!>", file);  break;
04273   case GE:
04274     fputs ("!>=", file);  break;
04275   case LT:
04276     fputs ("!<", file);  break;
04277   case LE:
04278     fputs ("!<=", file);  break;
04279   case LTGT:
04280     fputs ("!<>", file);  break;
04281   case UNLE:
04282     fputs (">", file);  break;
04283   case UNLT:
04284     fputs (">=", file);  break;
04285   case UNGE:
04286     fputs ("<", file);  break;
04287   case UNGT:
04288     fputs ("<=", file);  break;
04289   case UNEQ:
04290     fputs ("<>", file);  break;
04291   case UNORDERED:
04292     fputs ("<=>", file);  break;
04293   case ORDERED:
04294     fputs ("!<=>", file);  break;
04295   default:
04296     abort ();
04297   }
04298       return;
04299     case 'S':     /* Condition, operands are (S)wapped.  */
04300       switch (GET_CODE (x))
04301   {
04302   case EQ:
04303     fputs ("=", file);  break;
04304   case NE:
04305     fputs ("<>", file);  break;
04306   case GT:
04307     fputs ("<", file);  break;
04308   case GE:
04309     fputs ("<=", file);  break;
04310   case GEU:
04311     fputs ("<<=", file);  break;
04312   case GTU:
04313     fputs ("<<", file);  break;
04314   case LT:
04315     fputs (">", file);  break;
04316   case LE:
04317     fputs (">=", file);  break;
04318   case LEU:
04319     fputs (">>=", file);  break;
04320   case LTU:
04321     fputs (">>", file);  break;
04322   default:
04323     abort ();
04324   }
04325       return;
04326     case 'B':     /* Condition, (B)oth swapped and negate.  */
04327       switch (GET_CODE (x))
04328   {
04329   case EQ:
04330     fputs ("<>", file);  break;
04331   case NE:
04332     fputs ("=", file);  break;
04333   case GT:
04334     fputs (">=", file);  break;
04335   case GE:
04336     fputs (">", file);  break;
04337   case GEU:
04338     fputs (">>", file);  break;
04339   case GTU:
04340     fputs (">>=", file);  break;
04341   case LT:
04342     fputs ("<=", file);  break;
04343   case LE:
04344     fputs ("<", file);  break;
04345   case LEU:
04346     fputs ("<<", file);  break;
04347   case LTU:
04348     fputs ("<<=", file);  break;
04349   default:
04350     abort ();
04351   }
04352       return;
04353     case 'k':
04354       if (GET_CODE (x) == CONST_INT)
04355   {
04356     fprintf (file, HOST_WIDE_INT_PRINT_DEC, ~INTVAL (x));
04357     return;
04358   }
04359       abort ();
04360     case 'Q':
04361       if (GET_CODE (x) == CONST_INT)
04362   {
04363     fprintf (file, HOST_WIDE_INT_PRINT_DEC, 64 - (INTVAL (x) & 63));
04364     return;
04365   }
04366       abort ();
04367     case 'L':
04368       if (GET_CODE (x) == CONST_INT)
04369   {
04370     fprintf (file, HOST_WIDE_INT_PRINT_DEC, 32 - (INTVAL (x) & 31));
04371     return;
04372   }
04373       abort ();
04374     case 'O':
04375       if (GET_CODE (x) == CONST_INT && exact_log2 (INTVAL (x)) >= 0)
04376   {
04377     fprintf (file, "%d", exact_log2 (INTVAL (x)));
04378     return;
04379   }
04380       abort ();
04381     case 'p':
04382       if (GET_CODE (x) == CONST_INT)
04383   {
04384     fprintf (file, HOST_WIDE_INT_PRINT_DEC, 63 - (INTVAL (x) & 63));
04385     return;
04386   }
04387       abort ();
04388     case 'P':
04389       if (GET_CODE (x) == CONST_INT)
04390   {
04391     fprintf (file, HOST_WIDE_INT_PRINT_DEC, 31 - (INTVAL (x) & 31));
04392     return;
04393   }
04394       abort ();
04395     case 'I':
04396       if (GET_CODE (x) == CONST_INT)
04397   fputs ("i", file);
04398       return;
04399     case 'M':
04400     case 'F':
04401       switch (GET_CODE (XEXP (x, 0)))
04402   {
04403   case PRE_DEC:
04404   case PRE_INC:
04405     if (ASSEMBLER_DIALECT == 0)
04406       fputs ("s,mb", file);
04407     else
04408       fputs (",mb", file);
04409     break;
04410   case POST_DEC:
04411   case POST_INC:
04412     if (ASSEMBLER_DIALECT == 0)
04413       fputs ("s,ma", file);
04414     else
04415       fputs (",ma", file);
04416     break;
04417   case PLUS:
04418     if (GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
04419         || GET_CODE (XEXP (XEXP (x, 0), 1)) == MULT)
04420       {
04421         if (ASSEMBLER_DIALECT == 0)
04422     fputs ("x,s", file);
04423         else
04424     fputs (",s", file);
04425       }
04426     else if (code == 'F' && ASSEMBLER_DIALECT == 0)
04427       fputs ("s", file);
04428     break;
04429   default:
04430     if (code == 'F' && ASSEMBLER_DIALECT == 0)
04431       fputs ("s", file);
04432     break;
04433   }
04434       return;
04435     case 'G':
04436       output_global_address (file, x, 0);
04437       return;
04438     case 'H':
04439       output_global_address (file, x, 1);
04440       return;
04441     case 0:     /* Don't do anything special */
04442       break;
04443     case 'Z':
04444       {
04445   unsigned op[3];
04446   compute_zdepwi_operands (INTVAL (x), op);
04447   fprintf (file, "%d,%d,%d", op[0], op[1], op[2]);
04448   return;
04449       }
04450     case 'z':
04451       {
04452   unsigned op[3];
04453   compute_zdepdi_operands (INTVAL (x), op);
04454   fprintf (file, "%d,%d,%d", op[0], op[1], op[2]);
04455   return;
04456       }
04457     case 'c':
04458       /* We can get here from a .vtable_inherit due to our
04459    CONSTANT_ADDRESS_P rejecting perfectly good constant
04460    addresses.  */
04461       break;
04462     default:
04463       abort ();
04464     }
04465   if (GET_CODE (x) == REG)
04466     {
04467       fputs (reg_names [REGNO (x)], file);
04468       if (TARGET_64BIT && FP_REG_P (x) && GET_MODE_SIZE (GET_MODE (x)) <= 4)
04469   {
04470     fputs ("R", file);
04471     return;
04472   }
04473       if (FP_REG_P (x)
04474     && GET_MODE_SIZE (GET_MODE (x)) <= 4
04475     && (REGNO (x) & 1) == 0)
04476   fputs ("L", file);
04477     }
04478   else if (GET_CODE (x) == MEM)
04479     {
04480       int size = GET_MODE_SIZE (GET_MODE (x));
04481       rtx base = NULL_RTX;
04482       switch (GET_CODE (XEXP (x, 0)))
04483   {
04484   case PRE_DEC:
04485   case POST_DEC:
04486           base = XEXP (XEXP (x, 0), 0);
04487     fprintf (file, "-%d(%s)", size, reg_names [REGNO (base)]);
04488     break;
04489   case PRE_INC:
04490   case POST_INC:
04491           base = XEXP (XEXP (x, 0), 0);
04492     fprintf (file, "%d(%s)", size, reg_names [REGNO (base)]);
04493     break;
04494   default:
04495     if (GET_CODE (XEXP (x, 0)) == PLUS
04496         && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT)
04497       fprintf (file, "%s(%s)",
04498          reg_names [REGNO (XEXP (XEXP (XEXP (x, 0), 0), 0))],
04499          reg_names [REGNO (XEXP (XEXP (x, 0), 1))]);
04500     else if (GET_CODE (XEXP (x, 0)) == PLUS
04501        && GET_CODE (XEXP (XEXP (x, 0), 1)) == MULT)
04502       fprintf (file, "%s(%s)",
04503          reg_names [REGNO (XEXP (XEXP (XEXP (x, 0), 1), 0))],
04504          reg_names [REGNO (XEXP (XEXP (x, 0), 0))]);
04505     else
04506       output_address (XEXP (x, 0));
04507     break;
04508   }
04509     }
04510   else
04511     output_addr_const (file, x);
04512 }
04513 
04514 /* output a SYMBOL_REF or a CONST expression involving a SYMBOL_REF.  */
04515 
04516 void
04517 output_global_address (file, x, round_constant)
04518      FILE *file;
04519      rtx x;
04520      int round_constant;
04521 {
04522 
04523   /* Imagine  (high (const (plus ...))).  */
04524   if (GET_CODE (x) == HIGH)
04525     x = XEXP (x, 0);
04526 
04527   if (GET_CODE (x) == SYMBOL_REF && read_only_operand (x, VOIDmode))
04528     assemble_name (file, XSTR (x, 0));
04529   else if (GET_CODE (x) == SYMBOL_REF && !flag_pic)
04530     {
04531       assemble_name (file, XSTR (x, 0));
04532       fputs ("-$global$", file);
04533     }
04534   else if (GET_CODE (x) == CONST)
04535     {
04536       const char *sep = "";
04537       int offset = 0;   /* assembler wants -$global$ at end */
04538       rtx base = NULL_RTX;
04539 
04540       if (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF)
04541   {
04542     base = XEXP (XEXP (x, 0), 0);
04543     output_addr_const (file, base);
04544   }
04545       else if (GET_CODE (XEXP (XEXP (x, 0), 0)) == CONST_INT)
04546   offset = INTVAL (XEXP (XEXP (x, 0), 0));
04547       else abort ();
04548 
04549       if (GET_CODE (XEXP (XEXP (x, 0), 1)) == SYMBOL_REF)
04550   {
04551     base = XEXP (XEXP (x, 0), 1);
04552     output_addr_const (file, base);
04553   }
04554       else if (GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
04555   offset = INTVAL (XEXP (XEXP (x, 0), 1));
04556       else abort ();
04557 
04558       /* How bogus.  The compiler is apparently responsible for
04559    rounding the constant if it uses an LR field selector.
04560 
04561    The linker and/or assembler seem a better place since
04562    they have to do this kind of thing already.
04563 
04564    If we fail to do this, HP's optimizing linker may eliminate
04565    an addil, but not update the ldw/stw/ldo instruction that
04566    uses the result of the addil.  */
04567       if (round_constant)
04568   offset = ((offset + 0x1000) & ~0x1fff);
04569 
04570       if (GET_CODE (XEXP (x, 0)) == PLUS)
04571   {
04572     if (offset < 0)
04573       {
04574         offset = -offset;
04575         sep = "-";
04576       }
04577     else
04578       sep = "+";
04579   }
04580       else if (GET_CODE (XEXP (x, 0)) == MINUS
04581          && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF))
04582   sep = "-";
04583       else abort ();
04584 
04585       if (!read_only_operand (base, VOIDmode) && !flag_pic)
04586   fputs ("-$global$", file);
04587       if (offset)
04588   fprintf (file, "%s%d", sep, offset);
04589     }
04590   else
04591     output_addr_const (file, x);
04592 }
04593 
04594 void
04595 output_deferred_plabels (file)
04596      FILE *file;
04597 {
04598   int i;
04599   /* If we have deferred plabels, then we need to switch into the data
04600      section and align it to a 4 byte boundary before we output the
04601      deferred plabels.  */
04602   if (n_deferred_plabels)
04603     {
04604       data_section ();
04605       ASM_OUTPUT_ALIGN (file, 2);
04606     }
04607 
04608   /* Now output the deferred plabels.  */
04609   for (i = 0; i < n_deferred_plabels; i++)
04610     {
04611       ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (deferred_plabels[i].internal_label));
04612       assemble_integer (gen_rtx_SYMBOL_REF (Pmode, deferred_plabels[i].name),
04613       4, 32, 1);
04614     }
04615 }
04616 
04617 /* HP's millicode routines mean something special to the assembler.
04618    Keep track of which ones we have used.  */
04619 
04620 enum millicodes { remI, remU, divI, divU, mulI, mulU, end1000 };
04621 static void import_milli      PARAMS ((enum millicodes));
04622 static char imported[(int) end1000];
04623 static const char * const milli_names[] = {"remI", "remU", "divI", "divU", "mulI", "mulU"};
04624 static const char import_string[] = ".IMPORT $$....,MILLICODE";
04625 #define MILLI_START 10
04626 
04627 static void
04628 import_milli (code)
04629      enum millicodes code;
04630 {
04631   char str[sizeof (import_string)];
04632 
04633   if (!imported[(int) code])
04634     {
04635       imported[(int) code] = 1;
04636       strcpy (str, import_string);
04637       strncpy (str + MILLI_START, milli_names[(int) code], 4);
04638       output_asm_insn (str, 0);
04639     }
04640 }
04641 
04642 /* The register constraints have put the operands and return value in
04643    the proper registers.  */
04644 
04645 const char *
04646 output_mul_insn (unsignedp, insn)
04647      int unsignedp ATTRIBUTE_UNUSED;
04648      rtx insn;
04649 {
04650   import_milli (mulI);
04651   return output_millicode_call (insn, gen_rtx_SYMBOL_REF (Pmode, "$$mulI"));
04652 }
04653 
04654 /* Emit the rtl for doing a division by a constant.  */
04655 
04656 /* Do magic division millicodes exist for this value? */
04657 static const int magic_milli[]= {0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0,
04658          1, 1};
04659 
04660 /* We'll use an array to keep track of the magic millicodes and
04661    whether or not we've used them already. [n][0] is signed, [n][1] is
04662    unsigned.  */
04663 
04664 static int div_milli[16][2];
04665 
04666 int
04667 div_operand (op, mode)
04668      rtx op;
04669      enum machine_mode mode;
04670 {
04671   return (mode == SImode
04672     && ((GET_CODE (op) == REG && REGNO (op) == 25)
04673         || (GET_CODE (op) == CONST_INT && INTVAL (op) > 0
04674       && INTVAL (op) < 16 && magic_milli[INTVAL (op)])));
04675 }
04676 
04677 int
04678 emit_hpdiv_const (operands, unsignedp)
04679      rtx *operands;
04680      int unsignedp;
04681 {
04682   if (GET_CODE (operands[2]) == CONST_INT
04683       && INTVAL (operands[2]) > 0
04684       && INTVAL (operands[2]) < 16
04685       && magic_milli[INTVAL (operands[2])])
04686     {
04687       rtx ret = gen_rtx_REG (SImode, TARGET_64BIT ? 2 : 31);
04688 
04689       emit_move_insn (gen_rtx_REG (SImode, 26), operands[1]);
04690       emit
04691   (gen_rtx
04692    (PARALLEL, VOIDmode,
04693     gen_rtvec (6, gen_rtx_SET (VOIDmode, gen_rtx_REG (SImode, 29),
04694              gen_rtx_fmt_ee (unsignedp ? UDIV : DIV,
04695                  SImode,
04696                  gen_rtx_REG (SImode, 26),
04697                  operands[2])),
04698          gen_rtx_CLOBBER (VOIDmode, operands[4]),
04699          gen_rtx_CLOBBER (VOIDmode, operands[3]),
04700          gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, 26)),
04701          gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, 25)),
04702          gen_rtx_CLOBBER (VOIDmode, ret))));
04703       emit_move_insn (operands[0], gen_rtx_REG (SImode, 29));
04704       return 1;
04705     }
04706   return 0;
04707 }
04708 
04709 const char *
04710 output_div_insn (operands, unsignedp, insn)
04711      rtx *operands;
04712      int unsignedp;
04713      rtx insn;
04714 {
04715   int divisor;
04716 
04717   /* If the divisor is a constant, try to use one of the special
04718      opcodes .*/
04719   if (GET_CODE (operands[0]) == CONST_INT)
04720     {
04721       static char buf[100];
04722       divisor = INTVAL (operands[0]);
04723       if (!div_milli[divisor][unsignedp])
04724   {
04725     div_milli[divisor][unsignedp] = 1;
04726     if (unsignedp)
04727       output_asm_insn (".IMPORT $$divU_%0,MILLICODE", operands);
04728     else
04729       output_asm_insn (".IMPORT $$divI_%0,MILLICODE", operands);
04730   }
04731       if (unsignedp)
04732   {
04733     sprintf (buf, "$$divU_");
04734     sprintf (buf + 7, HOST_WIDE_INT_PRINT_DEC, INTVAL (operands[0]));
04735     return output_millicode_call (insn,
04736           gen_rtx_SYMBOL_REF (SImode, buf));
04737   }
04738       else
04739   {
04740     sprintf (buf, "$$divI_");
04741     sprintf (buf + 7, HOST_WIDE_INT_PRINT_DEC, INTVAL (operands[0]));
04742     return output_millicode_call (insn,
04743           gen_rtx_SYMBOL_REF (SImode, buf));
04744   }
04745     }
04746   /* Divisor isn't a special constant.  */
04747   else
04748     {
04749       if (unsignedp)
04750   {
04751     import_milli (divU);
04752     return output_millicode_call (insn,
04753           gen_rtx_SYMBOL_REF (SImode, "$$divU"));
04754   }
04755       else
04756   {
04757     import_milli (divI);
04758     return output_millicode_call (insn,
04759           gen_rtx_SYMBOL_REF (SImode, "$$divI"));
04760   }
04761     }
04762 }
04763 
04764 /* Output a $$rem millicode to do mod.  */
04765 
04766 const char *
04767 output_mod_insn (unsignedp, insn)
04768      int unsignedp;
04769      rtx insn;
04770 {
04771   if (unsignedp)
04772     {
04773       import_milli (remU);
04774       return output_millicode_call (insn,
04775             gen_rtx_SYMBOL_REF (SImode, "$$remU"));
04776     }
04777   else
04778     {
04779       import_milli (remI);
04780       return output_millicode_call (insn,
04781             gen_rtx_SYMBOL_REF (SImode, "$$remI"));
04782     }
04783 }
04784 
04785 void
04786 output_arg_descriptor (call_insn)
04787      rtx call_insn;
04788 {
04789   const char *arg_regs[4];
04790   enum machine_mode arg_mode;
04791   rtx link;
04792   int i, output_flag = 0;
04793   int regno;
04794 
04795   /* We neither need nor want argument location descriptors for the
04796      64bit runtime environment or the ELF32 environment.  */
04797   if (TARGET_64BIT || TARGET_ELF32)
04798     return;
04799 
04800   for (i = 0; i < 4; i++)
04801     arg_regs[i] = 0;
04802 
04803   /* Specify explicitly that no argument relocations should take place
04804      if using the portable runtime calling conventions.  */
04805   if (TARGET_PORTABLE_RUNTIME)
04806     {
04807       fputs ("\t.CALL ARGW0=NO,ARGW1=NO,ARGW2=NO,ARGW3=NO,RETVAL=NO\n",
04808        asm_out_file);
04809       return;
04810     }
04811 
04812   if (GET_CODE (call_insn) != CALL_INSN)
04813     abort ();
04814   for (link = CALL_INSN_FUNCTION_USAGE (call_insn); link; link = XEXP (link, 1))
04815     {
04816       rtx use = XEXP (link, 0);
04817 
04818       if (! (GET_CODE (use) == USE
04819        && GET_CODE (XEXP (use, 0)) == REG
04820        && FUNCTION_ARG_REGNO_P (REGNO (XEXP (use, 0)))))
04821   continue;
04822 
04823       arg_mode = GET_MODE (XEXP (use, 0));
04824       regno = REGNO (XEXP (use, 0));
04825       if (regno >= 23 && regno <= 26)
04826   {
04827     arg_regs[26 - regno] = "GR";
04828     if (arg_mode == DImode)
04829       arg_regs[25 - regno] = "GR";
04830   }
04831       else if (regno >= 32 && regno <= 39)
04832   {
04833     if (arg_mode == SFmode)
04834       arg_regs[(regno - 32) / 2] = "FR";
04835     else
04836       {
04837 #ifndef HP_FP_ARG_DESCRIPTOR_REVERSED
04838         arg_regs[(regno - 34) / 2] = "FR";
04839         arg_regs[(regno - 34) / 2 + 1] = "FU";
04840 #else
04841         arg_regs[(regno - 34) / 2] = "FU";
04842         arg_regs[(regno - 34) / 2 + 1] = "FR";
04843 #endif
04844       }
04845   }
04846     }
04847   fputs ("\t.CALL ", asm_out_file);
04848   for (i = 0; i < 4; i++)
04849     {
04850       if (arg_regs[i])
04851   {
04852     if (output_flag++)
04853       fputc (',', asm_out_file);
04854     fprintf (asm_out_file, "ARGW%d=%s", i, arg_regs[i]);
04855   }
04856     }
04857   fputc ('\n', asm_out_file);
04858 }
04859 
04860 /* Return the class of any secondary reload register that is needed to
04861    move IN into a register in class CLASS using mode MODE.
04862 
04863    Profiling has showed this routine and its descendants account for
04864    a significant amount of compile time (~7%).  So it has been
04865    optimized to reduce redundant computations and eliminate useless
04866    function calls.
04867 
04868    It might be worthwhile to try and make this a leaf function too.  */
04869 
04870 enum reg_class
04871 secondary_reload_class (class, mode, in)
04872      enum reg_class class;
04873      enum machine_mode mode;
04874      rtx in;
04875 {
04876   int regno, is_symbolic;
04877 
04878   /* Trying to load a constant into a FP register during PIC code
04879      generation will require %r1 as a scratch register.  */
04880   if (flag_pic
04881       && GET_MODE_CLASS (mode) == MODE_INT
04882       && FP_REG_CLASS_P (class)
04883       && (GET_CODE (in) == CONST_INT || GET_CODE (in) == CONST_DOUBLE))
04884     return R1_REGS;
04885 
04886   /* Profiling showed the PA port spends about 1.3% of its compilation
04887      time in true_regnum from calls inside secondary_reload_class.  */
04888 
04889   if (GET_CODE (in) == REG)
04890     {
04891       regno = REGNO (in);
04892       if (regno >= FIRST_PSEUDO_REGISTER)
04893   regno = true_regnum (in);
04894     }
04895   else if (GET_CODE (in) == SUBREG)
04896     regno = true_regnum (in);
04897   else
04898     regno = -1;
04899 
04900   /* If we have something like (mem (mem (...)), we can safely assume the
04901      inner MEM will end up in a general register after reloading, so there's
04902      no need for a secondary reload.  */
04903   if (GET_CODE (in) == MEM
04904       && GET_CODE (XEXP (in, 0)) == MEM)
04905     return NO_REGS;
04906 
04907   /* Handle out of range displacement for integer mode loads/stores of
04908      FP registers.  */
04909   if (((regno >= FIRST_PSEUDO_REGISTER || regno == -1)
04910        && GET_MODE_CLASS (mode) == MODE_INT
04911        && FP_REG_CLASS_P (class))
04912       || (class == SHIFT_REGS && (regno <= 0 || regno >= 32)))
04913     return GENERAL_REGS;
04914 
04915   /* A SAR<->FP register copy requires a secondary register (GPR) as
04916      well as secondary memory.  */
04917   if (regno >= 0 && regno < FIRST_PSEUDO_REGISTER
04918       && ((REGNO_REG_CLASS (regno) == SHIFT_REGS && FP_REG_CLASS_P (class))
04919     || (class == SHIFT_REGS && FP_REG_CLASS_P (REGNO_REG_CLASS (regno)))))
04920     return GENERAL_REGS;
04921 
04922   if (GET_CODE (in) == HIGH)
04923     in = XEXP (in, 0);
04924 
04925   /* Profiling has showed GCC spends about 2.6% of its compilation
04926      time in symbolic_operand from calls inside secondary_reload_class.
04927 
04928      We use an inline copy and only compute its return value once to avoid
04929      useless work.  */
04930   switch (GET_CODE (in))
04931     {
04932       rtx tmp;
04933 
04934       case SYMBOL_REF:
04935       case LABEL_REF:
04936         is_symbolic = 1;
04937         break;
04938       case CONST:
04939   tmp = XEXP (in, 0);
04940   is_symbolic = ((GET_CODE (XEXP (tmp, 0)) == SYMBOL_REF
04941       || GET_CODE (XEXP (tmp, 0)) == LABEL_REF)
04942            && GET_CODE (XEXP (tmp, 1)) == CONST_INT);
04943         break;
04944 
04945       default:
04946         is_symbolic = 0;
04947         break;
04948     }
04949 
04950   if (!flag_pic
04951       && is_symbolic
04952       && read_only_operand (in, VOIDmode))
04953     return NO_REGS;
04954 
04955   if (class != R1_REGS && is_symbolic)
04956     return R1_REGS;
04957 
04958   return NO_REGS;
04959 }
04960 
04961 enum direction
04962 function_arg_padding (mode, type)
04963      enum machine_mode mode;
04964      tree type;
04965 {
04966   int size;
04967 
04968   if (mode == BLKmode)
04969     {
04970       if (type && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
04971   size = int_size_in_bytes (type) * BITS_PER_UNIT;
04972       else
04973   return upward;    /* Don't know if this is right, but */
04974         /* same as old definition.  */
04975     }
04976   else
04977     size = GET_MODE_BITSIZE (mode);
04978   if (size < PARM_BOUNDARY)
04979     return downward;
04980   else if (size % PARM_BOUNDARY)
04981     return upward;
04982   else
04983     return none;
04984 }
04985 
04986 
04987 /* Do what is necessary for `va_start'.  We look at the current function
04988    to determine if stdargs or varargs is used and fill in an initial
04989    va_list.  A pointer to this constructor is returned.  */
04990 
04991 struct rtx_def *
04992 hppa_builtin_saveregs ()
04993 {
04994   rtx offset, dest;
04995   tree fntype = TREE_TYPE (current_function_decl);
04996   int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
04997        && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
04998            != void_type_node)))
04999     ? UNITS_PER_WORD : 0);
05000 
05001   if (argadj)
05002     offset = plus_constant (current_function_arg_offset_rtx, argadj);
05003   else
05004     offset = current_function_arg_offset_rtx;
05005 
05006   if (TARGET_64BIT)
05007     {
05008       int i, off;
05009 
05010       /* Adjust for varargs/stdarg differences.  */
05011       if (argadj)
05012   offset = plus_constant (current_function_arg_offset_rtx, -argadj);
05013       else
05014   offset = current_function_arg_offset_rtx;
05015 
05016       /* We need to save %r26 .. %r19 inclusive starting at offset -64
05017    from the incoming arg pointer and growing to larger addresses.  */
05018       for (i = 26, off = -64; i >= 19; i--, off += 8)
05019   emit_move_insn (gen_rtx_MEM (word_mode,
05020              plus_constant (arg_pointer_rtx, off)),
05021       gen_rtx_REG (word_mode, i));
05022 
05023       /* The incoming args pointer points just beyond the flushback area;
05024    normally this is not a serious concern.  However, when we are doing
05025    varargs/stdargs we want to make the arg pointer point to the start
05026    of the incoming argument area.  */
05027       emit_move_insn (virtual_incoming_args_rtx,
05028           plus_constant (arg_pointer_rtx, -64));
05029 
05030       /* Now return a pointer to the first anonymous argument.  */
05031       return copy_to_reg (expand_binop (Pmode, add_optab,
05032           virtual_incoming_args_rtx,
05033           offset, 0, 0, OPTAB_LIB_WIDEN));
05034     }
05035 
05036   /* Store general registers on the stack.  */
05037   dest = gen_rtx_MEM (BLKmode,
05038           plus_constant (current_function_internal_arg_pointer,
05039              -16));
05040   set_mem_alias_set (dest, get_varargs_alias_set ());
05041   set_mem_align (dest, BITS_PER_WORD);
05042   move_block_from_reg (23, dest, 4, 4 * UNITS_PER_WORD);
05043 
05044   /* move_block_from_reg will emit code to store the argument registers
05045      individually as scalar stores.
05046 
05047      However, other insns may later load from the same addresses for
05048      a structure load (passing a struct to a varargs routine).
05049 
05050      The alias code assumes that such aliasing can never happen, so we
05051      have to keep memory referencing insns from moving up beyond the
05052      last argument register store.  So we emit a blockage insn here.  */
05053   emit_insn (gen_blockage ());
05054 
05055   return copy_to_reg (expand_binop (Pmode, add_optab,
05056             current_function_internal_arg_pointer,
05057             offset, 0, 0, OPTAB_LIB_WIDEN));
05058 }
05059 
05060 void
05061 hppa_va_start (stdarg_p, valist, nextarg)
05062      int stdarg_p ATTRIBUTE_UNUSED;
05063      tree valist;
05064      rtx nextarg;
05065 {
05066   nextarg = expand_builtin_saveregs ();
05067   std_expand_builtin_va_start (1, valist, nextarg);
05068 }
05069 
05070 rtx
05071 hppa_va_arg (valist, type)
05072      tree valist, type;
05073 {
05074   HOST_WIDE_INT align, size, ofs;
05075   tree t, ptr, pptr;
05076 
05077   if (TARGET_64BIT)
05078     {
05079       /* Every argument in PA64 is passed by value (including large structs).
05080          Arguments with size greater than 8 must be aligned 0 MOD 16.  */
05081 
05082       size = int_size_in_bytes (type);
05083       if (size > UNITS_PER_WORD)
05084         {
05085           t = build (PLUS_EXPR, TREE_TYPE (valist), valist,
05086                      build_int_2 (2 * UNITS_PER_WORD - 1, 0));
05087           t = build (BIT_AND_EXPR, TREE_TYPE (t), t,
05088                      build_int_2 (-2 * UNITS_PER_WORD, -1));
05089           t = build (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
05090           TREE_SIDE_EFFECTS (t) = 1;
05091           expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
05092         }
05093       return std_expand_builtin_va_arg (valist, type);
05094     }
05095 
05096   /* Compute the rounded size of the type.  */
05097   align = PARM_BOUNDARY / BITS_PER_UNIT;
05098   size = int_size_in_bytes (type);
05099 
05100   ptr = build_pointer_type (type);
05101 
05102   /* "Large" types are passed by reference.  */
05103   if (size > 8)
05104     {
05105       t = build (PREDECREMENT_EXPR, TREE_TYPE (valist), valist,
05106      build_int_2 (POINTER_SIZE / BITS_PER_UNIT, 0));
05107       TREE_SIDE_EFFECTS (t) = 1;
05108 
05109       pptr = build_pointer_type (ptr);
05110       t = build1 (NOP_EXPR, pptr, t);
05111       TREE_SIDE_EFFECTS (t) = 1;
05112 
05113       t = build1 (INDIRECT_REF, ptr, t);
05114       TREE_SIDE_EFFECTS (t) = 1;
05115     }
05116   else
05117     {
05118       t = build (PLUS_EXPR, TREE_TYPE (valist), valist,
05119      build_int_2 (-size, -1));
05120 
05121       /* Copied from va-pa.h, but we probably don't need to align
05122    to word size, since we generate and preserve that invariant.  */
05123       t = build (BIT_AND_EXPR, TREE_TYPE (valist), t,
05124      build_int_2 ((size > 4 ? -8 : -4), -1));
05125 
05126       t = build (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
05127       TREE_SIDE_EFFECTS (t) = 1;
05128 
05129       ofs = (8 - size) % 4;
05130       if (ofs)
05131   {
05132     t = build (PLUS_EXPR, TREE_TYPE (valist), t, build_int_2 (ofs, 0));
05133     TREE_SIDE_EFFECTS (t) = 1;
05134   }
05135 
05136       t = build1 (NOP_EXPR, ptr, t);
05137       TREE_SIDE_EFFECTS (t) = 1;
05138     }
05139 
05140   /* Calculate!  */
05141   return expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
05142 }
05143 
05144 
05145 
05146 /* This routine handles all the normal conditional branch sequences we
05147    might need to generate.  It handles compare immediate vs compare
05148    register, nullification of delay slots, varying length branches,
05149    negated branches, and all combinations of the above.  It returns the
05150    output appropriate to emit the branch corresponding to all given
05151    parameters.  */
05152 
05153 const char *
05154 output_cbranch (operands, nullify, length, negated, insn)
05155   rtx *operands;
05156   int nullify, length, negated;
05157   rtx insn;
05158 {
05159   static char buf[100];
05160   int useskip = 0;
05161 
05162   /* A conditional branch to the following instruction (eg the delay slot) is
05163      asking for a disaster.  This can happen when not optimizing.
05164 
05165      In such cases it is safe to emit nothing.  */
05166 
05167   if (next_active_insn (JUMP_LABEL (insn)) == next_active_insn (insn))
05168     return "";
05169 
05170   /* If this is a long branch with its delay slot unfilled, set `nullify'
05171      as it can nullify the delay slot and save a nop.  */
05172   if (length == 8 && dbr_sequence_length () == 0)
05173     nullify = 1;
05174 
05175   /* If this is a short forward conditional branch which did not get
05176      its delay slot filled, the delay slot can still be nullified.  */
05177   if (! nullify && length == 4 && dbr_sequence_length () == 0)
05178     nullify = forward_branch_p (insn);
05179 
05180   /* A forward branch over a single nullified insn can be done with a
05181      comclr instruction.  This avoids a single cycle penalty due to
05182      mis-predicted branch if we fall through (branch not taken).  */
05183   if (length == 4
05184       && next_real_insn (insn) != 0
05185       && get_attr_length (next_real_insn (insn)) == 4
05186       && JUMP_LABEL (insn) == next_nonnote_insn (next_real_insn (insn))
05187       && nullify)
05188     useskip = 1;
05189 
05190   switch (length)
05191     {
05192       /* All short conditional branches except backwards with an unfilled
05193    delay slot.  */
05194       case 4:
05195   if (useskip)
05196     strcpy (buf, "{com%I2clr,|cmp%I2clr,}");
05197   else
05198     strcpy (buf, "{com%I2b,|cmp%I2b,}");
05199   if (GET_MODE (operands[1]) == DImode)
05200     strcat (buf, "*");
05201   if (negated)
05202     strcat (buf, "%B3");
05203   else
05204     strcat (buf, "%S3");
05205   if (useskip)
05206     strcat (buf, " %2,%r1,%%r0");
05207   else if (nullify)
05208     strcat (buf, ",n %2,%r1,%0");
05209   else
05210     strcat (buf, " %2,%r1,%0");
05211   break;
05212 
05213      /* All long conditionals.  Note an short backward branch with an
05214   unfilled delay slot is treated just like a long backward branch
05215   with an unfilled delay slot.  */
05216       case 8:
05217   /* Handle weird backwards branch with a filled delay slot
05218      with is nullified.  */
05219   if (dbr_sequence_length () != 0
05220       && ! forward_branch_p (insn)
05221       && nullify)
05222     {
05223       strcpy (buf, "{com%I2b,|cmp%I2b,}");
05224       if (GET_MODE (operands[1]) == DImode)
05225         strcat (buf, "*");
05226       if (negated)
05227         strcat (buf, "%S3");
05228       else
05229         strcat (buf, "%B3");
05230       strcat (buf, ",n %2,%r1,.+12\n\tb %0");
05231     }
05232   /* Handle short backwards branch with an unfilled delay slot.
05233      Using a comb;nop rather than comiclr;bl saves 1 cycle for both
05234      taken and untaken branches.  */
05235   else if (dbr_sequence_length () == 0
05236      && ! forward_branch_p (insn)
05237      && INSN_ADDRESSES_SET_P ()
05238      && VAL_14_BITS_P (INSN_ADDRESSES (INSN_UID (JUMP_LABEL (insn)))
05239             - INSN_ADDRESSES (INSN_UID (insn)) - 8))
05240     {
05241       strcpy (buf, "{com%I2b,|cmp%I2b,}");
05242       if (GET_MODE (operands[1]) == DImode)
05243         strcat (buf, "*");
05244       if (negated)
05245         strcat (buf, "%B3 %2,%r1,%0%#");
05246       else
05247         strcat (buf, "%S3 %2,%r1,%0%#");
05248     }
05249   else
05250     {
05251       strcpy (buf, "{com%I2clr,|cmp%I2clr,}");
05252       if (GET_MODE (operands[1]) == DImode)
05253         strcat (buf, "*");
05254       if (negated)
05255         strcat (buf, "%S3");
05256       else
05257         strcat (buf, "%B3");
05258       if (nullify)
05259         strcat (buf, " %2,%r1,%%r0\n\tb,n %0");
05260       else
05261         strcat (buf, " %2,%r1,%%r0\n\tb %0");
05262     }
05263   break;
05264 
05265       case 20:
05266   /* Very long branch.  Right now we only handle these when not
05267      optimizing.  See "jump" pattern in pa.md for details.  */
05268   if (optimize)
05269     abort ();
05270 
05271   /* Create a reversed conditional branch which branches around
05272      the following insns.  */
05273   if (negated)
05274     strcpy (buf, "{com%I2b,%S3,n %2,%r1,.+20|cmp%I2b,%S3,n %2,%r1,.+20}");
05275   else
05276     strcpy (buf, "{com%I2b,%B3,n %2,%r1,.+20|cmp%I2b,%B3,n %2,%r1,.+20}");
05277   if (GET_MODE (operands[1]) == DImode)
05278     {
05279       if (negated)
05280         strcpy (buf,
05281           "{com%I2b,*%S3,n %2,%r1,.+20|cmp%I2b,*%S3,n %2,%r1,.+20}");
05282       else
05283         strcpy (buf,
05284           "{com%I2b,*%B3,n %2,%r1,.+20|cmp%I2b,*%B3,n %2,%r1,.+20}");
05285     }
05286   output_asm_insn (buf, operands);
05287 
05288   /* Output an insn to save %r1.  */
05289   output_asm_insn ("stw %%r1,-16(%%r30)", operands);
05290 
05291   /* Now output a very long branch to the original target.  */
05292   output_asm_insn ("ldil L'%l0,%%r1\n\tbe R'%l0(%%sr4,%%r1)", operands);
05293 
05294   /* Now restore the value of %r1 in the delay slot.  We're not
05295      optimizing so we know nothing else can be in the delay slot.  */
05296   return "ldw -16(%%r30),%%r1";
05297 
05298       case 28:
05299   /* Very long branch when generating PIC code.  Right now we only
05300      handle these when not optimizing.  See "jump" pattern in pa.md
05301      for details.  */
05302   if (optimize)
05303     abort ();
05304 
05305   /* Create a reversed conditional branch which branches around
05306      the following insns.  */
05307   if (negated)
05308     strcpy (buf, "{com%I2b,%S3,n %2,%r1,.+28|cmp%I2b,%S3,n %2,%r1,.+28}");
05309   else
05310     strcpy (buf, "{com%I2b,%B3,n %2,%r1,.+28|cmp%I2b,%B3,n %2,%r1,.+28}");
05311   if (GET_MODE (operands[1]) == DImode)
05312     {
05313       if (negated)
05314         strcpy (buf, "{com%I2b,*%S3,n %2,%r1,.+28|cmp%I2b,*%S3,n %2,%r1,.+28}");
05315       else
05316         strcpy (buf, "{com%I2b,*%B3,n %2,%r1,.+28|cmp%I2b,*%B3,n %2,%r1,.+28}");
05317     }
05318   output_asm_insn (buf, operands);
05319 
05320   /* Output an insn to save %r1.  */
05321   output_asm_insn ("stw %%r1,-16(%%r30)", operands);
05322 
05323   /* Now output a very long PIC branch to the original target.  */
05324   {
05325     rtx xoperands[5];
05326 
05327     xoperands[0] = operands[0];
05328     xoperands[1] = operands[1];
05329     xoperands[2] = operands[2];
05330     xoperands[3] = operands[3];
05331     xoperands[4] = gen_label_rtx ();
05332 
05333     output_asm_insn ("{bl|b,l} .+8,%%r1\n\taddil L'%l0-%l4,%%r1",
05334          xoperands);
05335     ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
05336              CODE_LABEL_NUMBER (xoperands[4]));
05337     output_asm_insn ("ldo R'%l0-%l4(%%r1),%%r1\n\tbv %%r0(%%r1)",
05338          xoperands);
05339   }
05340 
05341   /* Now restore the value of %r1 in the delay slot.  We're not
05342      optimizing so we know nothing else can be in the delay slot.  */
05343   return "ldw -16(%%r30),%%r1";
05344 
05345       default:
05346   abort ();
05347     }
05348   return buf;
05349 }
05350 
05351 /* This routine handles all the branch-on-bit conditional branch sequences we
05352    might need to generate.  It handles nullification of delay slots,
05353    varying length branches, negated branches and all combinations of the
05354    above.  it returns the appropriate output template to emit the branch.  */
05355 
05356 const char *
05357 output_bb (operands, nullify, length, negated, insn, which)
05358   rtx *operands ATTRIBUTE_UNUSED;
05359   int nullify, length, negated;
05360   rtx insn;
05361   int which;
05362 {
05363   static char buf[100];
05364   int useskip = 0;
05365 
05366   /* A conditional branch to the following instruction (eg the delay slot) is
05367      asking for a disaster.  I do not think this can happen as this pattern
05368      is only used when optimizing; jump optimization should eliminate the
05369      jump.  But be prepared just in case.  */
05370 
05371   if (next_active_insn (JUMP_LABEL (insn)) == next_active_insn (insn))
05372     return "";
05373 
05374   /* If this is a long branch with its delay slot unfilled, set `nullify'
05375      as it can nullify the delay slot and save a nop.  */
05376   if (length == 8 && dbr_sequence_length () == 0)
05377     nullify = 1;
05378 
05379   /* If this is a short forward conditional branch which did not get
05380      its delay slot filled, the delay slot can still be nullified.  */
05381   if (! nullify && length == 4 && dbr_sequence_length () == 0)
05382     nullify = forward_branch_p (insn);
05383 
05384   /* A forward branch over a single nullified insn can be done with a
05385      extrs instruction.  This avoids a single cycle penalty due to
05386      mis-predicted branch if we fall through (branch not taken).  */
05387 
05388   if (length == 4
05389       && next_real_insn (insn) != 0
05390       && get_attr_length (next_real_insn (insn)) == 4
05391       && JUMP_LABEL (insn) == next_nonnote_insn (next_real_insn (insn))
05392       && nullify)
05393     useskip = 1;
05394 
05395   switch (length)
05396     {
05397 
05398       /* All short conditional branches except backwards with an unfilled
05399    delay slot.  */
05400       case 4:
05401   if (useskip)
05402     strcpy (buf, "{extrs,|extrw,s,}");
05403   else
05404     strcpy (buf, "bb,");
05405   if (useskip && GET_MODE (operands[0]) == DImode)
05406     strcpy (buf, "extrd,s,*");
05407   else if (GET_MODE (operands[0]) == DImode)
05408     strcpy (buf, "bb,*");
05409   if ((which == 0 && negated)
05410        || (which == 1 && ! negated))
05411     strcat (buf, ">=");
05412   else
05413     strcat (buf, "<");
05414   if (useskip)
05415     strcat (buf, " %0,%1,1,%%r0");
05416   else if (nullify && negated)
05417     strcat (buf, ",n %0,%1,%3");
05418   else if (nullify && ! negated)
05419     strcat (buf, ",n %0,%1,%2");
05420   else if (! nullify && negated)
05421     strcat (buf, "%0,%1,%3");
05422   else if (! nullify && ! negated)
05423     strcat (buf, " %0,%1,%2");
05424   break;
05425 
05426      /* All long conditionals.  Note an short backward branch with an
05427   unfilled delay slot is treated just like a long backward branch
05428   with an unfilled delay slot.  */
05429       case 8:
05430   /* Handle weird backwards branch with a filled delay slot
05431      with is nullified.  */
05432   if (dbr_sequence_length () != 0
05433       && ! forward_branch_p (insn)
05434       && nullify)
05435     {
05436       strcpy (buf, "bb,");
05437       if (GET_MODE (operands[0]) == DImode)
05438         strcat (buf, "*");
05439       if ((which == 0 && negated)
05440     || (which == 1 && ! negated))
05441         strcat (buf, "<");
05442       else
05443         strcat (buf, ">=");
05444       if (negated)
05445         strcat (buf, ",n %0,%1,.+12\n\tb %3");
05446       else
05447         strcat (buf, ",n %0,%1,.+12\n\tb %2");
05448     }
05449   /* Handle short backwards branch with an unfilled delay slot.
05450      Using a bb;nop rather than extrs;bl saves 1 cycle for both
05451      taken and untaken branches.  */
05452   else if (dbr_sequence_length () == 0
05453      && ! forward_branch_p (insn)
05454      && INSN_ADDRESSES_SET_P ()
05455      && VAL_14_BITS_P (INSN_ADDRESSES (INSN_UID (JUMP_LABEL (insn)))
05456             - INSN_ADDRESSES (INSN_UID (insn)) - 8))
05457     {
05458       strcpy (buf, "bb,");
05459       if (GET_MODE (operands[0]) == DImode)
05460         strcat (buf, "*");
05461       if ((which == 0 && negated)
05462     || (which == 1 && ! negated))
05463         strcat (buf, ">=");
05464       else
05465         strcat (buf, "<");
05466       if (negated)
05467         strcat (buf, " %0,%1,%3%#");
05468       else
05469         strcat (buf, " %0,%1,%2%#");
05470     }
05471   else
05472     {
05473       strcpy (buf, "{extrs,|extrw,s,}");
05474       if (GET_MODE (operands[0]) == DImode)
05475         strcpy (buf, "extrd,s,*");
05476       if ((which == 0 && negated)
05477     || (which == 1 && ! negated))
05478         strcat (buf, "<");
05479       else
05480         strcat (buf, ">=");
05481       if (nullify && negated)
05482         strcat (buf, " %0,%1,1,%%r0\n\tb,n %3");
05483       else if (nullify && ! negated)
05484         strcat (buf, " %0,%1,1,%%r0\n\tb,n %2");
05485       else if (negated)
05486         strcat (buf, " %0,%1,1,%%r0\n\tb %3");
05487       else
05488         strcat (buf, " %0,%1,1,%%r0\n\tb %2");
05489     }
05490   break;
05491 
05492       default:
05493   abort ();
05494     }
05495   return buf;
05496 }
05497 
05498 /* This routine handles all the branch-on-variable-bit conditional branch
05499    sequences we might need to generate.  It handles nullification of delay
05500    slots, varying length branches, negated branches and all combinations
05501    of the above.  it returns the appropriate output template to emit the
05502    branch.  */
05503 
05504 const char *
05505 output_bvb (operands, nullify, length, negated, insn, which)
05506   rtx *operands ATTRIBUTE_UNUSED;
05507   int nullify, length, negated;
05508   rtx insn;
05509   int which;
05510 {
05511   static char buf[100];
05512   int useskip = 0;
05513 
05514   /* A conditional branch to the following instruction (eg the delay slot) is
05515      asking for a disaster.  I do not think this can happen as this pattern
05516      is only used when optimizing; jump optimization should eliminate the
05517      jump.  But be prepared just in case.  */
05518 
05519   if (next_active_insn (JUMP_LABEL (insn)) == next_active_insn (insn))
05520     return "";
05521 
05522   /* If this is a long branch with its delay slot unfilled, set `nullify'
05523      as it can nullify the delay slot and save a nop.  */
05524   if (length == 8 && dbr_sequence_length () == 0)
05525     nullify = 1;
05526 
05527   /* If this is a short forward conditional branch which did not get
05528      its delay slot filled, the delay slot can still be nullified.  */
05529   if (! nullify && length == 4 && dbr_sequence_length () == 0)
05530     nullify = forward_branch_p (insn);
05531 
05532   /* A forward branch over a single nullified insn can be done with a
05533      extrs instruction.  This avoids a single cycle penalty due to
05534      mis-predicted branch if we fall through (branch not taken).  */
05535 
05536   if (length == 4
05537       && next_real_insn (insn) != 0
05538       && get_attr_length (next_real_insn (insn)) == 4
05539       && JUMP_LABEL (insn) == next_nonnote_insn (next_real_insn (insn))
05540       && nullify)
05541     useskip = 1;
05542 
05543   switch (length)
05544     {
05545 
05546       /* All short conditional branches except backwards with an unfilled
05547    delay slot.  */
05548       case 4:
05549   if (useskip)
05550     strcpy (buf, "{vextrs,|extrw,s,}");
05551   else
05552     strcpy (buf, "{bvb,|bb,}");
05553   if (useskip && GET_MODE (operands[0]) == DImode)
05554     strcpy (buf, "extrd,s,*}");
05555   else if (GET_MODE (operands[0]) == DImode)
05556     strcpy (buf, "bb,*");
05557   if ((which == 0 && negated)
05558        || (which == 1 && ! negated))
05559     strcat (buf, ">=");
05560   else
05561     strcat (buf, "<");
05562   if (useskip)
05563     strcat (buf, "{ %0,1,%%r0| %0,%%sar,1,%%r0}");
05564   else if (nullify && negated)
05565     strcat (buf, "{,n %0,%3|,n %0,%%sar,%3}");
05566   else if (nullify && ! negated)
05567     strcat (buf, "{,n %0,%2|,n %0,%%sar,%2}");
05568   else if (! nullify && negated)
05569     strcat (buf, "{%0,%3|%0,%%sar,%3}");
05570   else if (! nullify && ! negated)
05571     strcat (buf, "{ %0,%2| %0,%%sar,%2}");
05572   break;
05573 
05574      /* All long conditionals.  Note an short backward branch with an
05575   unfilled delay slot is treated just like a long backward branch
05576   with an unfilled delay slot.  */
05577       case 8:
05578   /* Handle weird backwards branch with a filled delay slot
05579      with is nullified.  */
05580   if (dbr_sequence_length () != 0
05581       && ! forward_branch_p (insn)
05582       && nullify)
05583     {
05584       strcpy (buf, "{bvb,|bb,}");
05585       if (GET_MODE (operands[0]) == DImode)
05586         strcat (buf, "*");
05587       if ((which == 0 && negated)
05588     || (which == 1 && ! negated))
05589         strcat (buf, "<");
05590       else
05591         strcat (buf, ">=");
05592       if (negated)
05593         strcat (buf, "{,n %0,.+12\n\tb %3|,n %0,%%sar,.+12\n\tb %3}");
05594       else
05595         strcat (buf, "{,n %0,.+12\n\tb %2|,n %0,%%sar,.+12\n\tb %2}");
05596     }
05597   /* Handle short backwards branch with an unfilled delay slot.
05598      Using a bb;nop rather than extrs;bl saves 1 cycle for both
05599      taken and untaken branches.  */
05600   else if (dbr_sequence_length () == 0
05601      && ! forward_branch_p (insn)
05602      && INSN_ADDRESSES_SET_P ()
05603      && VAL_14_BITS_P (INSN_ADDRESSES (INSN_UID (JUMP_LABEL (insn)))
05604             - INSN_ADDRESSES (INSN_UID (insn)) - 8))
05605     {
05606       strcpy (buf, "{bvb,|bb,}");
05607       if (GET_MODE (operands[0]) == DImode)
05608         strcat (buf, "*");
05609       if ((which == 0 && negated)
05610     || (which == 1 && ! negated))
05611         strcat (buf, ">=");
05612       else
05613         strcat (buf, "<");
05614       if (negated)
05615         strcat (buf, "{ %0,%3%#| %0,%%sar,%3%#}");
05616       else
05617         strcat (buf, "{ %0,%2%#| %0,%%sar,%2%#}");
05618     }
05619   else
05620     {
05621       strcpy (buf, "{vextrs,|extrw,s,}");
05622       if (GET_MODE (operands[0]) == DImode)
05623         strcpy (buf, "extrd,s,*");
05624       if ((which == 0 && negated)
05625     || (which == 1 && ! negated))
05626         strcat (buf, "<");
05627       else
05628         strcat (buf, ">=");
05629       if (nullify && negated)
05630         strcat (buf, "{ %0,1,%%r0\n\tb,n %3| %0,%%sar,1,%%r0\n\tb,n %3}");
05631       else if (nullify && ! negated)
05632         strcat (buf, "{ %0,1,%%r0\n\tb,n %2| %0,%%sar,1,%%r0\n\tb,n %2}");
05633       else if (negated)
05634         strcat (buf, "{ %0,1,%%r0\n\tb %3| %0,%%sar,1,%%r0\n\tb %3}");
05635       else
05636         strcat (buf, "{ %0,1,%%r0\n\tb %2| %0,%%sar,1,%%r0\n\tb %2}");
05637     }
05638   break;
05639 
05640       default:
05641   abort ();
05642     }
05643   return buf;
05644 }
05645 
05646 /* Return the output template for emitting a dbra type insn.
05647 
05648    Note it may perform some output operations on its own before
05649    returning the final output string.  */
05650 const char *
05651 output_dbra (operands, insn, which_alternative)
05652      rtx *operands;
05653      rtx insn;
05654      int which_alternative;
05655 {
05656 
05657   /* A conditional branch to the following instruction (eg the delay slot) is
05658      asking for a disaster.  Be prepared!  */
05659 
05660   if (next_active_insn (JUMP_LABEL (insn)) == next_active_insn (insn))
05661     {
05662       if (which_alternative == 0)
05663   return "ldo %1(%0),%0";
05664       else if (which_alternative == 1)
05665   {
05666     output_asm_insn ("{fstws|fstw} %0,-16(%%r30)", operands);
05667     output_asm_insn ("ldw -16(%%r30),%4", operands);
05668     output_asm_insn ("ldo %1(%4),%4\n\tstw %4,-16(%%r30)", operands);
05669     return "{fldws|fldw} -16(%%r30),%0";
05670   }
05671       else
05672   {
05673     output_asm_insn ("ldw %0,%4", operands);
05674     return "ldo %1(%4),%4\n\tstw %4,%0";
05675   }
05676     }
05677 
05678   if (which_alternative == 0)
05679     {
05680       int nullify = INSN_ANNULLED_BRANCH_P (insn);
05681       int length = get_attr_length (insn);
05682 
05683       /* If this is a long branch with its delay slot unfilled, set `nullify'
05684    as it can nullify the delay slot and save a nop.  */
05685       if (length == 8 && dbr_sequence_length () == 0)
05686   nullify = 1;
05687 
05688       /* If this is a short forward conditional branch which did not get
05689    its delay slot filled, the delay slot can still be nullified.  */
05690       if (! nullify && length == 4 && dbr_sequence_length () == 0)
05691   nullify = forward_branch_p (insn);
05692 
05693       /* Handle short versions first.  */
05694       if (length == 4 && nullify)
05695   return "addib,%C2,n %1,%0,%3";
05696       else if (length == 4 && ! nullify)
05697   return "addib,%C2 %1,%0,%3";
05698       else if (length == 8)
05699   {
05700     /* Handle weird backwards branch with a fulled delay slot
05701        which is nullified.  */
05702     if (dbr_sequence_length () != 0
05703         && ! forward_branch_p (insn)
05704         && nullify)
05705       return "addib,%N2,n %1,%0,.+12\n\tb %3";
05706     /* Handle short backwards branch with an unfilled delay slot.
05707        Using a addb;nop rather than addi;bl saves 1 cycle for both
05708        taken and untaken branches.  */
05709     else if (dbr_sequence_length () == 0
05710        && ! forward_branch_p (insn)
05711        && INSN_ADDRESSES_SET_P ()
05712        && VAL_14_BITS_P (INSN_ADDRESSES (INSN_UID (JUMP_LABEL (insn)))
05713               - INSN_ADDRESSES (INSN_UID (insn)) - 8))
05714         return "addib,%C2 %1,%0,%3%#";
05715 
05716     /* Handle normal cases.  */
05717     if (nullify)
05718       return "addi,%N2 %1,%0,%0\n\tb,n %3";
05719     else
05720       return "addi,%N2 %1,%0,%0\n\tb %3";
05721   }
05722       else
05723   abort ();
05724     }
05725   /* Deal with gross reload from FP register case.  */
05726   else if (which_alternative == 1)
05727     {
05728       /* Move loop counter from FP register to MEM then into a GR,
05729    increment the GR, store the GR into MEM, and finally reload
05730    the FP register from MEM from within the branch's delay slot.  */
05731       output_asm_insn ("{fstws|fstw} %0,-16(%%r30)\n\tldw -16(%%r30),%4",
05732            operands);
05733       output_asm_insn ("ldo %1(%4),%4\n\tstw %4,-16(%%r30)", operands);
05734       if (get_attr_length (insn) == 24)
05735   return "{comb|cmpb},%S2 %%r0,%4,%3\n\t{fldws|fldw} -16(%%r30),%0";
05736       else
05737   return "{comclr|cmpclr},%B2 %%r0,%4,%%r0\n\tb %3\n\t{fldws|fldw} -16(%%r30),%0";
05738     }
05739   /* Deal with gross reload from memory case.  */
05740   else
05741     {
05742       /* Reload loop counter from memory, the store back to memory
05743    happens in the branch's delay slot.   */
05744       output_asm_insn ("ldw %0,%4", operands);
05745       if (get_attr_length (insn) == 12)
05746   return "addib,%C2 %1,%4,%3\n\tstw %4,%0";
05747       else
05748   return "addi,%N2 %1,%4,%4\n\tb %3\n\tstw %4,%0";
05749     }
05750 }
05751 
05752 /* Return the output template for emitting a dbra type insn.
05753 
05754    Note it may perform some output operations on its own before
05755    returning the final output string.  */
05756 const char *
05757 output_movb (operands, insn, which_alternative, reverse_comparison)
05758      rtx *operands;
05759      rtx insn;
05760      int which_alternative;
05761      int reverse_comparison;
05762 {
05763 
05764   /* A conditional branch to the following instruction (eg the delay slot) is
05765      asking for a disaster.  Be prepared!  */
05766 
05767   if (next_active_insn (JUMP_LABEL (insn)) == next_active_insn (insn))
05768     {
05769       if (which_alternative == 0)
05770   return "copy %1,%0";
05771       else if (which_alternative == 1)
05772   {
05773     output_asm_insn ("stw %1,-16(%%r30)", operands);
05774     return "{fldws|fldw} -16(%%r30),%0";
05775   }
05776       else if (which_alternative == 2)
05777   return "stw %1,%0";
05778       else
05779   return "mtsar %r1";
05780     }
05781 
05782   /* Support the second variant.  */
05783   if (reverse_comparison)
05784     PUT_CODE (operands[2], reverse_condition (GET_CODE (operands[2])));
05785 
05786   if (which_alternative == 0)
05787     {
05788       int nullify = INSN_ANNULLED_BRANCH_P (insn);
05789       int length = get_attr_length (insn);
05790 
05791       /* If this is a long branch with its delay slot unfilled, set `nullify'
05792    as it can nullify the delay slot and save a nop.  */
05793       if (length == 8 && dbr_sequence_length () == 0)
05794   nullify = 1;
05795 
05796       /* If this is a short forward conditional branch which did not get
05797    its delay slot filled, the delay slot can still be nullified.  */
05798       if (! nullify && length == 4 && dbr_sequence_length () == 0)
05799   nullify = forward_branch_p (insn);
05800 
05801       /* Handle short versions first.  */
05802       if (length == 4 && nullify)
05803   return "movb,%C2,n %1,%0,%3";
05804       else if (length == 4 && ! nullify)
05805   return "movb,%C2 %1,%0,%3";
05806       else if (length == 8)
05807   {
05808     /* Handle weird backwards branch with a filled delay slot
05809        which is nullified.  */
05810     if (dbr_sequence_length () != 0
05811         && ! forward_branch_p (insn)
05812         && nullify)
05813       return "movb,%N2,n %1,%0,.+12\n\tb %3";
05814 
05815     /* Handle short backwards branch with an unfilled delay slot.
05816        Using a movb;nop rather than or;bl saves 1 cycle for both
05817        taken and untaken branches.  */
05818     else if (dbr_sequence_length () == 0
05819        && ! forward_branch_p (insn)
05820        && INSN_ADDRESSES_SET_P ()
05821        && VAL_14_BITS_P (INSN_ADDRESSES (INSN_UID (JUMP_LABEL (insn)))
05822               - INSN_ADDRESSES (INSN_UID (insn)) - 8))
05823       return "movb,%C2 %1,%0,%3%#";
05824     /* Handle normal cases.  */
05825     if (nullify)
05826       return "or,%N2 %1,%%r0,%0\n\tb,n %3";
05827     else
05828       return "or,%N2 %1,%%r0,%0\n\tb %3";
05829   }
05830       else
05831   abort ();
05832     }
05833   /* Deal with gross reload from FP register case.  */
05834   else if (which_alternative == 1)
05835     {
05836       /* Move loop counter from FP register to MEM then into a GR,
05837    increment the GR, store the GR into MEM, and finally reload
05838    the FP register from MEM from within the branch's delay slot.  */
05839       output_asm_insn ("stw %1,-16(%%r30)", operands);
05840       if (get_attr_length (insn) == 12)
05841   return "{comb|cmpb},%S2 %%r0,%1,%3\n\t{fldws|fldw} -16(%%r30),%0";
05842       else
05843   return "{comclr|cmpclr},%B2 %%r0,%1,%%r0\n\tb %3\n\t{fldws|fldw} -16(%%r30),%0";
05844     }
05845   /* Deal with gross reload from memory case.  */
05846   else if (which_alternative == 2)
05847     {
05848       /* Reload loop counter from memory, the store back to memory
05849    happens in the branch's delay slot.   */
05850       if (get_attr_length (insn) == 8)
05851   return "{comb|cmpb},%S2 %%r0,%1,%3\n\tstw %1,%0";
05852       else
05853   return "{comclr|cmpclr},%B2 %%r0,%1,%%r0\n\tb %3\n\tstw %1,%0";
05854     }
05855   /* Handle SAR as a destination.  */
05856   else
05857     {
05858       if (get_attr_length (insn) == 8)
05859   return "{comb|cmpb},%S2 %%r0,%1,%3\n\tmtsar %r1";
05860       else
05861   return "{comclr|cmpclr},%B2 %%r0,%1,%%r0\n\tbl %3\n\tmtsar %r1";
05862     }
05863 }
05864 
05865 
05866 /* INSN is a millicode call.  It may have an unconditional jump in its delay
05867    slot.
05868 
05869    CALL_DEST is the routine we are calling.  */
05870 
05871 const char *
05872 output_millicode_call (insn, call_dest)
05873   rtx insn;
05874   rtx call_dest;
05875 {
05876   int distance;
05877   rtx xoperands[4];
05878   rtx seq_insn;
05879 
05880   xoperands[3] = gen_rtx_REG (Pmode, TARGET_64BIT ? 2 : 31);
05881 
05882   /* Handle common case -- empty delay slot or no jump in the delay slot,
05883      and we're sure that the branch will reach the beginning of the $CODE$
05884      subspace.  The within reach form of the $$sh_func_adrs call has
05885      a length of 28 and attribute type of multi.  This length is the
05886      same as the maximum length of an out of reach PIC call to $$div.  */
05887   if ((dbr_sequence_length () == 0
05888        && (get_attr_length (insn) == 8
05889      || (get_attr_length (insn) == 28 
05890          && get_attr_type (insn) == TYPE_MULTI)))
05891       || (dbr_sequence_length () != 0
05892     && GET_CODE (NEXT_INSN (insn)) != JUMP_INSN
05893     && get_attr_length (insn) == 4))
05894     {
05895       xoperands[0] = call_dest;
05896       output_asm_insn ("{bl|b,l} %0,%3%#", xoperands);
05897       return "";
05898     }
05899 
05900   /* This call may not reach the beginning of the $CODE$ subspace.  */
05901   if (get_attr_length (insn) > 8)
05902     {
05903       int delay_insn_deleted = 0;
05904 
05905       /* We need to emit an inline long-call branch.  */
05906       if (dbr_sequence_length () != 0
05907     && GET_CODE (NEXT_INSN (insn)) != JUMP_INSN)
05908   {
05909     /* A non-jump insn in the delay slot.  By definition we can
05910        emit this insn before the call.  */
05911     final_scan_insn (NEXT_INSN (insn), asm_out_file, optimize, 0, 0);
05912 
05913     /* Now delete the delay insn.  */
05914     PUT_CODE (NEXT_INSN (insn), NOTE);
05915     NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED;
05916     NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0;
05917     delay_insn_deleted = 1;
05918   }
05919 
05920       /* PIC long millicode call sequence.  */
05921       if (flag_pic)
05922   {
05923     xoperands[0] = call_dest;
05924     xoperands[1] = gen_label_rtx ();
05925     /* Get our address + 8 into %r1.  */
05926     output_asm_insn ("{bl|b,l} .+8,%%r1", xoperands);
05927 
05928     /* Add %r1 to the offset of our target from the next insn.  */
05929     output_asm_insn ("addil L%%%0-%1,%%r1", xoperands);
05930     ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
05931              CODE_LABEL_NUMBER (xoperands[1]));
05932     output_asm_insn ("ldo R%%%0-%1(%%r1),%%r1", xoperands);
05933 
05934     /* Get the return address into %r31.  */
05935     output_asm_insn ("blr 0,%3", xoperands);
05936 
05937     /* Branch to our target which is in %r1.  */
05938     output_asm_insn ("bv,n %%r0(%%r1)", xoperands);
05939 
05940     /* Empty delay slot.  Note this insn gets fetched twice and
05941        executed once.  To be safe we use a nop.  */
05942     output_asm_insn ("nop", xoperands);
05943   }
05944       /* Pure portable runtime doesn't allow be/ble; we also don't have
05945    PIC support in the assembler/linker, so this sequence is needed.  */
05946       else if (TARGET_PORTABLE_RUNTIME)
05947   {
05948     xoperands[0] = call_dest;
05949     /* Get the address of our target into %r29.  */
05950     output_asm_insn ("ldil L%%%0,%%r29", xoperands);
05951     output_asm_insn ("ldo R%%%0(%%r29),%%r29", xoperands);
05952 
05953     /* Get our return address into %r31.  */
05954     output_asm_insn ("blr %%r0,%3", xoperands);
05955 
05956     /* Jump to our target address in %r29.  */
05957     output_asm_insn ("bv,n %%r0(%%r29)", xoperands);
05958 
05959     /* Empty delay slot.  Note this insn gets fetched twice and
05960        executed once.  To be safe we use a nop.  */
05961     output_asm_insn ("nop", xoperands);
05962   }
05963       /* If we're allowed to use be/ble instructions, then this is the
05964    best sequence to use for a long millicode call.  */
05965       else
05966   {
05967     xoperands[0] = call_dest;
05968     output_asm_insn ("ldil L%%%0,%3", xoperands);
05969     if (TARGET_PA_20)
05970       output_asm_insn ("be,l R%%%0(%%sr4,%3),%%sr0,%%r31", xoperands);
05971     else
05972       output_asm_insn ("ble R%%%0(%%sr4,%3)", xoperands);
05973     output_asm_insn ("nop", xoperands);
05974   }
05975 
05976       /* If we had a jump in the call's delay slot, output it now.  */
05977       if (dbr_sequence_length () != 0
05978     && !delay_insn_deleted)
05979   {
05980     xoperands[0] = XEXP (PATTERN (NEXT_INSN (insn)), 1);
05981     output_asm_insn ("b,n %0", xoperands);
05982 
05983     /* Now delete the delay insn.  */
05984     PUT_CODE (NEXT_INSN (insn), NOTE);
05985     NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED;
05986     NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0;
05987   }
05988       return "";
05989     }
05990 
05991   /* This call has an unconditional jump in its delay slot and the
05992      call is known to reach its target or the beginning of the current
05993      subspace.  */
05994 
05995   /* Use the containing sequence insn's address.  */
05996   seq_insn = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
05997 
05998   distance = INSN_ADDRESSES (INSN_UID (JUMP_LABEL (NEXT_INSN (insn))))
05999          - INSN_ADDRESSES (INSN_UID (seq_insn)) - 8;
06000 
06001   /* If the branch was too far away, emit a normal call followed
06002      by a nop, followed by the unconditional branch.
06003 
06004      If the branch is close, then adjust %r2 from within the
06005      call's delay slot.  */
06006 
06007   xoperands[0] = call_dest;
06008   xoperands[1] = XEXP (PATTERN (NEXT_INSN (insn)), 1);
06009   if (! VAL_14_BITS_P (distance))
06010     output_asm_insn ("{bl|b,l} %0,%3\n\tnop\n\tb,n %1", xoperands);
06011   else
06012     {
06013       xoperands[2] = gen_label_rtx ();
06014       output_asm_insn ("\n\t{bl|b,l} %0,%3\n\tldo %1-%2(%3),%3",
06015            xoperands);
06016       ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
06017          CODE_LABEL_NUMBER (xoperands[2]));
06018     }
06019 
06020   /* Delete the jump.  */
06021   PUT_CODE (NEXT_INSN (insn), NOTE);
06022   NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED;
06023   NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0;
06024   return "";
06025 }
06026 
06027 extern struct obstack permanent_obstack;
06028 
06029 /* INSN is either a function call.  It may have an unconditional jump
06030    in its delay slot.
06031 
06032    CALL_DEST is the routine we are calling.  */
06033 
06034 const char *
06035 output_call (insn, call_dest, sibcall)
06036   rtx insn;
06037   rtx call_dest;
06038   int sibcall;
06039 {
06040   int distance;
06041   rtx xoperands[4];
06042   rtx seq_insn;
06043 
06044   /* Handle common case -- empty delay slot or no jump in the delay slot,
06045      and we're sure that the branch will reach the beginning of the $CODE$
06046      subspace.  */
06047   if ((dbr_sequence_length () == 0
06048        && get_attr_length (insn) == 8)
06049       || (dbr_sequence_length () != 0
06050     && GET_CODE (NEXT_INSN (insn)) != JUMP_INSN
06051     && get_attr_length (insn) == 4))
06052     {
06053       xoperands[0] = call_dest;
06054       xoperands[1] = gen_rtx_REG (word_mode, sibcall ? 0 : 2);
06055       output_asm_insn ("{bl|b,l} %0,%1%#", xoperands);
06056       return "";
06057     }
06058 
06059   /* This call may not reach the beginning of the $CODE$ subspace.  */
06060   if (get_attr_length (insn) > 8)
06061     {
06062       int delay_insn_deleted = 0;
06063       rtx xoperands[2];
06064       rtx link;
06065 
06066       /* We need to emit an inline long-call branch.  Furthermore,
06067    because we're changing a named function call into an indirect
06068    function call well after the parameters have been set up, we
06069    need to make sure any FP args appear in both the integer
06070    and FP registers.  Also, we need move any delay slot insn
06071    out of the delay slot.  And finally, we can't rely on the linker
06072    being able to fix the call to $$dyncall!  -- Yuk!.  */
06073       if (dbr_sequence_length () != 0
06074     && GET_CODE (NEXT_INSN (insn)) != JUMP_INSN)
06075   {
06076     /* A non-jump insn in the delay slot.  By definition we can
06077        emit this insn before the call (and in fact before argument
06078        relocating.  */
06079     final_scan_insn (NEXT_INSN (insn), asm_out_file, optimize, 0, 0);
06080 
06081     /* Now delete the delay insn.  */
06082     PUT_CODE (NEXT_INSN (insn), NOTE);
06083     NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED;
06084     NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0;
06085     delay_insn_deleted = 1;
06086   }
06087 
06088       /* Now copy any FP arguments into integer registers.  */
06089       for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1))
06090   {
06091     int arg_mode, regno;
06092     rtx use = XEXP (link, 0);
06093     if (! (GET_CODE (use) == USE
06094      && GET_CODE (XEXP (use, 0)) == REG
06095      && FUNCTION_ARG_REGNO_P (REGNO (XEXP (use, 0)))))
06096       continue;
06097 
06098     arg_mode = GET_MODE (XEXP (use, 0));
06099     regno = REGNO (XEXP (use, 0));
06100     /* Is it a floating point register?  */
06101     if (regno >= 32 && regno <= 39)
06102       {
06103         /* Copy from the FP register into an integer register
06104      (via memory).  */
06105         if (arg_mode == SFmode)
06106     {
06107       xoperands[0] = XEXP (use, 0);
06108       xoperands[1] = gen_rtx_REG (SImode, 26 - (regno - 32) / 2);
06109       output_asm_insn ("{fstws|fstw} %0,-16(%%sr0,%%r30)",
06110             xoperands);
06111       output_asm_insn ("ldw -16(%%sr0,%%r30),%1", xoperands);
06112     }
06113         else
06114     {
06115       xoperands[0] = XEXP (use, 0);
06116       xoperands[1] = gen_rtx_REG (DImode, 25 - (regno - 34) / 2);
06117       output_asm_insn ("{fstds|fstd} %0,-16(%%sr0,%%r30)",
06118             xoperands);
06119       output_asm_insn ("ldw -12(%%sr0,%%r30),%R1", xoperands);
06120       output_asm_insn ("ldw -16(%%sr0,%%r30),%1", xoperands);
06121     }
06122       }
06123   }
06124 
06125       /* Don't have to worry about TARGET_PORTABLE_RUNTIME here since
06126    we don't have any direct calls in that case.  */
06127   {
06128     int i;
06129     const char *name = XSTR (call_dest, 0);
06130 
06131     /* See if we have already put this function on the list
06132        of deferred plabels.  This list is generally small,
06133        so a liner search is not too ugly.  If it proves too
06134        slow replace it with something faster.  */
06135     for (i = 0; i < n_deferred_plabels; i++)
06136       if (strcmp (name, deferred_plabels[i].name) == 0)
06137         break;
06138 
06139     /* If the deferred plabel list is empty, or this entry was
06140        not found on the list, create a new entry on the list.  */
06141     if (deferred_plabels == NULL || i == n_deferred_plabels)
06142       {
06143         const char *real_name;
06144 
06145         if (deferred_plabels == 0)
06146     deferred_plabels = (struct deferred_plabel *)
06147       xmalloc (1 * sizeof (struct deferred_plabel));
06148         else
06149     deferred_plabels = (struct deferred_plabel *)
06150       xrealloc (deferred_plabels,
06151           ((n_deferred_plabels + 1)
06152            * sizeof (struct deferred_plabel)));
06153 
06154         i = n_deferred_plabels++;
06155         deferred_plabels[i].internal_label = gen_label_rtx ();
06156         deferred_plabels[i].name = obstack_alloc (&permanent_obstack,
06157               strlen (name) + 1);
06158         strcpy (deferred_plabels[i].name, name);
06159 
06160         /* Gross.  We have just implicitly taken the address of this
06161      function, mark it as such.  */
06162         STRIP_NAME_ENCODING (real_name, name);
06163         TREE_SYMBOL_REFERENCED (get_identifier (real_name)) = 1;
06164       }
06165 
06166     /* We have to load the address of the function using a procedure
06167        label (plabel).  Inline plabels can lose for PIC and other
06168        cases, so avoid them by creating a 32bit plabel in the data
06169        segment.  */
06170     if (flag_pic)
06171       {
06172         xoperands[0] = deferred_plabels[i].internal_label;
06173         xoperands[1] = gen_label_rtx ();
06174 
06175         output_asm_insn ("addil LT%%%0,%%r19", xoperands);
06176         output_asm_insn ("ldw RT%%%0(%%r1),%%r22", xoperands);
06177         output_asm_insn ("ldw 0(%%r22),%%r22", xoperands);
06178 
06179         /* Get our address + 8 into %r1.  */
06180         output_asm_insn ("{bl|b,l} .+8,%%r1", xoperands);
06181 
06182         /* Add %r1 to the offset of dyncall from the next insn.  */
06183         if (TARGET_SOM || !TARGET_GAS)
06184     {
06185       output_asm_insn ("addil L%%$$dyncall-%1,%%r1", xoperands);
06186       ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
06187                CODE_LABEL_NUMBER (xoperands[1]));
06188       output_asm_insn ("ldo R%%$$dyncall-%1(%%r1),%%r1", xoperands);
06189     }
06190         else
06191     {
06192       output_asm_insn ("addil L%%$$dyncall-$PIC_pcrel$0+4,%%r1",
06193            xoperands);
06194       output_asm_insn ("ldo R%%$$dyncall-$PIC_pcrel$0+8(%%r1),%%r1",
06195            xoperands);
06196     }
06197 
06198         /* Get the return address into %r31.  */
06199         output_asm_insn ("blr %%r0,%%r31", xoperands);
06200 
06201         /* Branch to our target which is in %r1.  */
06202         output_asm_insn ("bv %%r0(%%r1)", xoperands);
06203 
06204         if (sibcall)
06205     {
06206       /* This call never returns, so we do not need to fix the
06207          return pointer.  */
06208       output_asm_insn ("nop", xoperands);
06209     }
06210         else
06211     {
06212       /* Copy the return address into %r2 also.  */
06213       output_asm_insn ("copy %%r31,%%r2", xoperands);
06214     }
06215       }
06216     else
06217       {
06218         xoperands[0] = deferred_plabels[i].internal_label;
06219 
06220         /* Get the address of our target into %r22.  */
06221         output_asm_insn ("addil LR%%%0-$global$,%%r27", xoperands);
06222         output_asm_insn ("ldw RR%%%0-$global$(%%r1),%%r22", xoperands);
06223 
06224         /* Get the high part of the  address of $dyncall into %r2, then
06225      add in the low part in the branch instruction.  */
06226         output_asm_insn ("ldil L%%$$dyncall,%%r2", xoperands);
06227         if (TARGET_PA_20)
06228     output_asm_insn ("be,l R%%$$dyncall(%%sr4,%%r2),%%sr0,%%r31",
06229          xoperands);
06230         else
06231     output_asm_insn ("ble R%%$$dyncall(%%sr4,%%r2)", xoperands);
06232 
06233         if (sibcall)
06234     {
06235       /* This call never returns, so we do not need to fix the
06236          return pointer.  */
06237       output_asm_insn ("nop", xoperands);
06238     }
06239         else
06240     {
06241       /* Copy the return address into %r2 also.  */
06242       output_asm_insn ("copy %%r31,%%r2", xoperands);
06243     }
06244       }
06245   }
06246 
06247       /* If we had a jump in the call's delay slot, output it now.  */
06248       if (dbr_sequence_length () != 0
06249     && !delay_insn_deleted)
06250   {
06251     xoperands[0] = XEXP (PATTERN (NEXT_INSN (insn)), 1);
06252     output_asm_insn ("b,n %0", xoperands);
06253 
06254     /* Now delete the delay insn.  */
06255     PUT_CODE (NEXT_INSN (insn), NOTE);
06256     NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED;
06257     NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0;
06258   }
06259       return "";
06260     }
06261 
06262   /* This call has an unconditional jump in its delay slot and the
06263      call is known to reach its target or the beginning of the current
06264      subspace.  */
06265 
06266   /* Use the containing sequence insn's address.  */
06267   seq_insn = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
06268 
06269   distance = INSN_ADDRESSES (INSN_UID (JUMP_LABEL (NEXT_INSN (insn))))
06270          - INSN_ADDRESSES (INSN_UID (seq_insn)) - 8;
06271 
06272   /* If the branch was too far away, emit a normal call followed
06273      by a nop, followed by the unconditional branch.
06274 
06275      If the branch is close, then adjust %r2 from within the
06276      call's delay slot.  */
06277 
06278   xoperands[0] = call_dest;
06279   xoperands[1] = XEXP (PATTERN (NEXT_INSN (insn)), 1);
06280   if (! VAL_14_BITS_P (distance))
06281     output_asm_insn ("{bl|b,l} %0,%%r2\n\tnop\n\tb,n %1", xoperands);
06282   else
06283     {
06284       xoperands[3] = gen_label_rtx ();
06285       output_asm_insn ("\n\t{bl|b,l} %0,%%r2\n\tldo %1-%3(%%r2),%%r2",
06286            xoperands);
06287       ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
06288          CODE_LABEL_NUMBER (xoperands[3]));
06289     }
06290 
06291   /* Delete the jump.  */
06292   PUT_CODE (NEXT_INSN (insn), NOTE);
06293   NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED;
06294   NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0;
06295   return "";
06296 }
06297 
06298 /* In HPUX 8.0's shared library scheme, special relocations are needed
06299    for function labels if they might be passed to a function
06300    in a shared library (because shared libraries don't live in code
06301    space), and special magic is needed to construct their address.  */
06302 
06303 void
06304 hppa_encode_label (sym)
06305      rtx sym;
06306 {
06307   const char *str = XSTR (sym, 0);
06308   int len = strlen (str) + 1;
06309   char *newstr, *p;
06310 
06311   p = newstr = alloca (len + 1);
06312   if (str[0] == '*')
06313     {
06314       str++;
06315       len--;
06316     }
06317   *p++ = '@';
06318   strcpy (p, str);
06319 
06320   XSTR (sym, 0) = ggc_alloc_string (newstr, len);
06321 }
06322 
06323 int
06324 function_label_operand (op, mode)
06325      rtx op;
06326      enum machine_mode mode ATTRIBUTE_UNUSED;
06327 {
06328   return GET_CODE (op) == SYMBOL_REF && FUNCTION_NAME_P (XSTR (op, 0));
06329 }
06330 
06331 /* Returns 1 if OP is a function label involved in a simple addition
06332    with a constant.  Used to keep certain patterns from matching
06333    during instruction combination.  */
06334 int
06335 is_function_label_plus_const (op)
06336      rtx op;
06337 {
06338   /* Strip off any CONST.  */
06339   if (GET_CODE (op) == CONST)
06340     op = XEXP (op, 0);
06341 
06342   return (GET_CODE (op) == PLUS
06343     && function_label_operand (XEXP (op, 0), Pmode)
06344     && GET_CODE (XEXP (op, 1)) == CONST_INT);
06345 }
06346 
06347 /* Returns 1 if the 6 operands specified in OPERANDS are suitable for
06348    use in fmpyadd instructions.  */
06349 int
06350 fmpyaddoperands (operands)
06351      rtx *operands;
06352 {
06353   enum machine_mode mode = GET_MODE (operands[0]);
06354 
06355   /* Must be a floating point mode.  */
06356   if (mode != SFmode && mode != DFmode)
06357     return 0;
06358 
06359   /* All modes must be the same.  */
06360   if (! (mode == GET_MODE (operands[1])
06361    && mode == GET_MODE (operands[2])
06362    && mode == GET_MODE (operands[3])
06363    && mode == GET_MODE (operands[4])
06364    && mode == GET_MODE (operands[5])))
06365     return 0;
06366 
06367   /* All operands must be registers.  */
06368   if (! (GET_CODE (operands[1]) == REG
06369    && GET_CODE (operands[2]) == REG
06370    && GET_CODE (operands[3]) == REG
06371    && GET_CODE (operands[4]) == REG
06372    && GET_CODE (operands[5]) == REG))
06373     return 0;
06374 
06375   /* Only 2 real operands to the addition.  One of the input operands must
06376      be the same as the output operand.  */
06377   if (! rtx_equal_p (operands[3], operands[4])
06378       && ! rtx_equal_p (operands[3], operands[5]))
06379     return 0;
06380 
06381   /* Inout operand of add can not conflict with any operands from multiply.  */
06382   if (rtx_equal_p (operands[3], operands[0])
06383      || rtx_equal_p (operands[3], operands[1])
06384      || rtx_equal_p (operands[3], operands[2]))
06385     return 0;
06386 
06387   /* multiply can not feed into addition operands.  */
06388   if (rtx_equal_p (operands[4], operands[0])
06389       || rtx_equal_p (operands[5], operands[0]))
06390     return 0;
06391 
06392   /* SFmode limits the registers to the upper 32 of the 32bit FP regs.  */
06393   if (mode == SFmode
06394       && (REGNO_REG_CLASS (REGNO (operands[0])) != FPUPPER_REGS
06395     || REGNO_REG_CLASS (REGNO (operands[1])) != FPUPPER_REGS
06396     || REGNO_REG_CLASS (REGNO (operands[2])) != FPUPPER_REGS
06397     || REGNO_REG_CLASS (REGNO (operands[3])) != FPUPPER_REGS
06398     || REGNO_REG_CLASS (REGNO (operands[4])) != FPUPPER_REGS
06399     || REGNO_REG_CLASS (REGNO (operands[5])) != FPUPPER_REGS))
06400     return 0;
06401 
06402   /* Passed.  Operands are suitable for fmpyadd.  */
06403   return 1;
06404 }
06405 
06406 /* Returns 1 if the 6 operands specified in OPERANDS are suitable for
06407    use in fmpysub instructions.  */
06408 int
06409 fmpysuboperands (operands)
06410      rtx *operands;
06411 {
06412   enum machine_mode mode = GET_MODE (operands[0]);
06413 
06414   /* Must be a floating point mode.  */
06415   if (mode != SFmode && mode != DFmode)
06416     return 0;
06417 
06418   /* All modes must be the same.  */
06419   if (! (mode == GET_MODE (operands[1])
06420    && mode == GET_MODE (operands[2])
06421    && mode == GET_MODE (operands[3])
06422    && mode == GET_MODE (operands[4])
06423    && mode == GET_MODE (operands[5])))
06424     return 0;
06425 
06426   /* All operands must be registers.  */
06427   if (! (GET_CODE (operands[1]) == REG
06428    && GET_CODE (operands[2]) == REG
06429    && GET_CODE (operands[3]) == REG
06430    && GET_CODE (operands[4]) == REG
06431    && GET_CODE (operands[5]) == REG))
06432     return 0;
06433 
06434   /* Only 2 real operands to the subtraction.  Subtraction is not a commutative
06435      operation, so operands[4] must be the same as operand[3].  */
06436   if (! rtx_equal_p (operands[3], operands[4]))
06437     return 0;
06438 
06439   /* multiply can not feed into subtraction.  */
06440   if (rtx_equal_p (operands[5], operands[0]))
06441     return 0;
06442 
06443   /* Inout operand of sub can not conflict with any operands from multiply.  */
06444   if (rtx_equal_p (operands[3], operands[0])
06445      || rtx_equal_p (operands[3], operands[1])
06446      || rtx_equal_p (operands[3], operands[2]))
06447     return 0;
06448 
06449   /* SFmode limits the registers to the upper 32 of the 32bit FP regs.  */
06450   if (mode == SFmode
06451       && (REGNO_REG_CLASS (REGNO (operands[0])) != FPUPPER_REGS
06452     || REGNO_REG_CLASS (REGNO (operands[1])) != FPUPPER_REGS
06453     || REGNO_REG_CLASS (REGNO (operands[2])) != FPUPPER_REGS
06454     || REGNO_REG_CLASS (REGNO (operands[3])) != FPUPPER_REGS
06455     || REGNO_REG_CLASS (REGNO (operands[4])) != FPUPPER_REGS
06456     || REGNO_REG_CLASS (REGNO (operands[5])) != FPUPPER_REGS))
06457     return 0;
06458 
06459   /* Passed.  Operands are suitable for fmpysub.  */
06460   return 1;
06461 }
06462 
06463 int
06464 plus_xor_ior_operator (op, mode)
06465      rtx op;
06466      enum machine_mode mode ATTRIBUTE_UNUSED;
06467 {
06468   return (GET_CODE (op) == PLUS || GET_CODE (op) == XOR
06469     || GET_CODE (op) == IOR);
06470 }
06471 
06472 /* Return 1 if the given constant is 2, 4, or 8.  These are the valid
06473    constants for shadd instructions.  */
06474 static int
06475 shadd_constant_p (val)
06476      int val;
06477 {
06478   if (val == 2 || val == 4 || val == 8)
06479     return 1;
06480   else
06481     return 0;
06482 }
06483 
06484 /* Return 1 if OP is a CONST_INT with the value 2, 4, or 8.  These are
06485    the valid constant for shadd instructions.  */
06486 int
06487 shadd_operand (op, mode)
06488      rtx op;
06489      enum machine_mode mode ATTRIBUTE_UNUSED;
06490 {
06491   return (GET_CODE (op) == CONST_INT && shadd_constant_p (INTVAL (op)));
06492 }
06493 
06494 /* Return 1 if OP is valid as a base register in a reg + reg address.  */
06495 
06496 int
06497 basereg_operand (op, mode)
06498      rtx op;
06499      enum machine_mode mode;
06500 {
06501   /* cse will create some unscaled indexed addresses, however; it
06502      generally isn't a win on the PA, so avoid creating unscaled
06503      indexed addresses until after cse is finished.  */
06504   if (!cse_not_expected)
06505     return 0;
06506 
06507   /* Allow any register when TARGET_NO_SPACE_REGS is in effect since
06508      we don't have to worry about the braindamaged implicit space
06509      register selection from the basereg.  */
06510   if (TARGET_NO_SPACE_REGS)
06511     return (GET_CODE (op) == REG);
06512 
06513   /* While it's always safe to index off the frame pointer, it's not
06514      always profitable, particularly when the frame pointer is being
06515      eliminated.  */
06516   if (! flag_omit_frame_pointer && op == frame_pointer_rtx)
06517     return 1;
06518 
06519   return (GET_CODE (op) == REG
06520           && REG_POINTER (op)
06521           && register_operand (op, mode));
06522 }
06523 
06524 /* Return 1 if this operand is anything other than a hard register.  */
06525 
06526 int
06527 non_hard_reg_operand (op, mode)
06528      rtx op;
06529      enum machine_mode mode ATTRIBUTE_UNUSED;
06530 {
06531   return ! (GET_CODE (op) == REG && REGNO (op) < FIRST_PSEUDO_REGISTER);
06532 }
06533 
06534 /* Return 1 if INSN branches forward.  Should be using insn_addresses
06535    to avoid walking through all the insns...  */
06536 static int
06537 forward_branch_p (insn)
06538      rtx insn;
06539 {
06540   rtx label = JUMP_LABEL (insn);
06541 
06542   while (insn)
06543     {
06544       if (insn == label)
06545   break;
06546       else
06547   insn = NEXT_INSN (insn);
06548     }
06549 
06550   return (insn == label);
06551 }
06552 
06553 /* Return 1 if OP is an equality comparison, else return 0.  */
06554 int
06555 eq_neq_comparison_operator (op, mode)
06556      rtx op;
06557      enum machine_mode mode ATTRIBUTE_UNUSED;
06558 {
06559   return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
06560 }
06561 
06562 /* Return 1 if OP is an operator suitable for use in a movb instruction.  */
06563 int
06564 movb_comparison_operator (op, mode)
06565      rtx op;
06566      enum machine_mode mode ATTRIBUTE_UNUSED;
06567 {
06568   return (GET_CODE (op) == EQ || GET_CODE (op) == NE
06569     || GET_CODE (op) == LT || GET_CODE (op) == GE);
06570 }
06571 
06572 /* Return 1 if INSN is in the delay slot of a call instruction.  */
06573 int
06574 jump_in_call_delay (insn)
06575      rtx insn;
06576 {
06577 
06578   if (GET_CODE (insn) != JUMP_INSN)
06579     return 0;
06580 
06581   if (PREV_INSN (insn)
06582       && PREV_INSN (PREV_INSN (insn))
06583       && GET_CODE (next_active_insn (PREV_INSN (PREV_INSN (insn)))) == INSN)
06584     {
06585       rtx test_insn = next_active_insn (PREV_INSN (PREV_INSN (insn)));
06586 
06587       return (GET_CODE (PATTERN (test_insn)) == SEQUENCE
06588         && XVECEXP (PATTERN (test_insn), 0, 1) == insn);
06589 
06590     }
06591   else
06592     return 0;
06593 }
06594 
06595 /* Output an unconditional move and branch insn.  */
06596 
06597 const char *
06598 output_parallel_movb (operands, length)
06599      rtx *operands;
06600      int length;
06601 {
06602   /* These are the cases in which we win.  */
06603   if (length == 4)
06604     return "mov%I1b,tr %1,%0,%2";
06605 
06606   /* None of these cases wins, but they don't lose either.  */
06607   if (dbr_sequence_length () == 0)
06608     {
06609       /* Nothing in the delay slot, fake it by putting the combined
06610    insn (the copy or add) in the delay slot of a bl.  */
06611       if (GET_CODE (operands[1]) == CONST_INT)
06612   return "b %2\n\tldi %1,%0";
06613       else
06614   return "b %2\n\tcopy %1,%0";
06615     }
06616   else
06617     {
06618       /* Something in the delay slot, but we've got a long branch.  */
06619       if (GET_CODE (operands[1]) == CONST_INT)
06620   return "ldi %1,%0\n\tb %2";
06621       else
06622   return "copy %1,%0\n\tb %2";
06623     }
06624 }
06625 
06626 /* Output an unconditional add and branch insn.  */
06627 
06628 const char *
06629 output_parallel_addb (operands, length)
06630      rtx *operands;
06631      int length;
06632 {
06633   /* To make life easy we want operand0 to be the shared input/output
06634      operand and operand1 to be the readonly operand.  */
06635   if (operands[0] == operands[1])
06636     operands[1] = operands[2];
06637 
06638   /* These are the cases in which we win.  */
06639   if (length == 4)
06640     return "add%I1b,tr %1,%0,%3";
06641 
06642   /* None of these cases win, but they don't lose either.  */
06643   if (dbr_sequence_length () == 0)
06644     {
06645       /* Nothing in the delay slot, fake it by putting the combined
06646    insn (the copy or add) in the delay slot of a bl.  */
06647       return "b %3\n\tadd%I1 %1,%0,%0";
06648     }
06649   else
06650     {
06651       /* Something in the delay slot, but we've got a long branch.  */
06652       return "add%I1 %1,%0,%0\n\tb %3";
06653     }
06654 }
06655 
06656 /* Return nonzero if INSN (a jump insn) immediately follows a call to
06657    a named function.  This is used to discourage creating parallel movb/addb
06658    insns since a jump which immediately follows a call can execute in the
06659    delay slot of the call.
06660 
06661    It is also used to avoid filling the delay slot of a jump which
06662    immediately follows a call since the jump can usually be eliminated
06663    completely by modifying RP in the delay slot of the call.  */
06664 
06665 int
06666 following_call (insn)
06667      rtx insn;
06668 {
06669   /* We do not parallel movb,addb or place jumps into call delay slots when
06670      optimizing for the PA8000.  */
06671   if (pa_cpu != PROCESSOR_8000)
06672     return 0;
06673 
06674   /* Find the previous real insn, skipping NOTEs.  */
06675   insn = PREV_INSN (insn);
06676   while (insn && GET_CODE (insn) == NOTE)
06677     insn = PREV_INSN (insn);
06678 
06679   /* Check for CALL_INSNs and millicode calls.  */
06680   if (insn
06681       && ((GET_CODE (insn) == CALL_INSN
06682      && get_attr_type (insn) != TYPE_DYNCALL)
06683     || (GET_CODE (insn) == INSN
06684         && GET_CODE (PATTERN (insn)) != SEQUENCE
06685         && GET_CODE (PATTERN (insn)) != USE
06686         && GET_CODE (PATTERN (insn)) != CLOBBER
06687         && get_attr_type (insn) == TYPE_MILLI)))
06688     return 1;
06689 
06690   return 0;
06691 }
06692 
06693 /* We use this hook to perform a PA specific optimization which is difficult
06694    to do in earlier passes.
06695 
06696    We want the delay slots of branches within jump tables to be filled.
06697    None of the compiler passes at the moment even has the notion that a
06698    PA jump table doesn't contain addresses, but instead contains actual
06699    instructions!
06700 
06701    Because we actually jump into the table, the addresses of each entry
06702    must stay constant in relation to the beginning of the table (which
06703    itself must stay constant relative to the instruction to jump into
06704    it).  I don't believe we can guarantee earlier passes of the compiler
06705    will adhere to those rules.
06706 
06707    So, late in the compilation process we find all the jump tables, and
06708    expand them into real code -- eg each entry in the jump table vector
06709    will get an appropriate label followed by a jump to the final target.
06710 
06711    Reorg and the final jump pass can then optimize these branches and
06712    fill their delay slots.  We end up with smaller, more efficient code.
06713 
06714    The jump instructions within the table are special; we must be able
06715    to identify them during assembly output (if the jumps don't get filled
06716    we need to emit a nop rather than nullifying the delay slot)).  We
06717    identify jumps in switch tables by marking the SET with DImode.
06718 
06719    We also surround the jump table itself with BEGIN_BRTAB and END_BRTAB
06720    insns.  This serves two purposes, first it prevents jump.c from
06721    noticing that the last N entries in the table jump to the instruction
06722    immediately after the table and deleting the jumps.  Second, those
06723    insns mark where we should emit .begin_brtab and .end_brtab directives
06724    when using GAS (allows for better link time optimizations).  */
06725 
06726 void
06727 pa_reorg (insns)
06728      rtx insns;
06729 {
06730   rtx insn;
06731 
06732   remove_useless_addtr_insns (insns, 1);
06733 
06734   if (pa_cpu < PROCESSOR_8000)
06735     pa_combine_instructions (get_insns ());
06736 
06737 
06738   /* This is fairly cheap, so always run it if optimizing.  */
06739   if (optimize > 0 && !TARGET_BIG_SWITCH)
06740     {
06741       /* Find and explode all ADDR_VEC or ADDR_DIFF_VEC insns.  */
06742       insns = get_insns ();
06743       for (insn = insns; insn; insn = NEXT_INSN (insn))
06744   {
06745     rtx pattern, tmp, location;
06746     unsigned int length, i;
06747 
06748     /* Find an ADDR_VEC or ADDR_DIFF_VEC insn to explode.  */
06749     if (GET_CODE (insn) != JUMP_INSN
06750         || (GET_CODE (PATTERN (insn)) != ADDR_VEC
06751       && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC))
06752       continue;
06753 
06754     /* Emit marker for the beginning of the branch table.  */
06755     emit_insn_before (gen_begin_brtab (), insn);
06756 
06757     pattern = PATTERN (insn);
06758     location = PREV_INSN (insn);
06759           length = XVECLEN (pattern, GET_CODE (pattern) == ADDR_DIFF_VEC);
06760 
06761     for (i = 0; i < length; i++)
06762       {
06763         /* Emit a label before each jump to keep jump.c from
06764      removing this code.  */
06765         tmp = gen_label_rtx ();
06766         LABEL_NUSES (tmp) = 1;
06767         emit_label_after (tmp, location);
06768         location = NEXT_INSN (location);
06769 
06770         if (GET_CODE (pattern) == ADDR_VEC)
06771     {
06772       /* Emit the jump itself.  */
06773       tmp = gen_jump (XEXP (XVECEXP (pattern, 0, i), 0));
06774       tmp = emit_jump_insn_after (tmp, location);
06775       JUMP_LABEL (tmp) = XEXP (XVECEXP (pattern, 0, i), 0);
06776       /* It is easy to rely on the branch table markers
06777          during assembly output to trigger the correct code
06778          for a switch table jump with an unfilled delay slot,
06779 
06780          However, that requires state and assumes that we look
06781          at insns in order.
06782 
06783          We can't make such assumptions when computing the length
06784          of instructions.  Ugh.  We could walk the insn chain to
06785          determine if this instruction is in a branch table, but
06786          that can get rather expensive, particularly during the
06787          branch shortening phase of the compiler.
06788 
06789          So instead we mark this jump as being special.  This is
06790          far from ideal and knows that no code after this will
06791          muck around with the mode of the JUMP_INSN itself.  */
06792       PUT_MODE (tmp, SImode);
06793       LABEL_NUSES (JUMP_LABEL (tmp))++;
06794       location = NEXT_INSN (location);
06795     }
06796         else
06797     {
06798       /* Emit the jump itself.  */
06799       tmp = gen_jump (XEXP (XVECEXP (pattern, 1, i), 0));
06800       tmp = emit_jump_insn_after (tmp, location);
06801       JUMP_LABEL (tmp) = XEXP (XVECEXP (pattern, 1, i), 0);
06802       /* It is easy to rely on the branch table markers
06803          during assembly output to trigger the correct code
06804          for a switch table jump with an unfilled delay slot,
06805 
06806          However, that requires state and assumes that we look
06807          at insns in order.
06808 
06809          We can't make such assumptions when computing the length
06810          of instructions.  Ugh.  We could walk the insn chain to
06811          determine if this instruction is in a branch table, but
06812          that can get rather expensive, particularly during the
06813          branch shortening phase of the compiler.
06814 
06815          So instead we mark this jump as being special.  This is
06816          far from ideal and knows that no code after this will
06817          muck around with the mode of the JUMP_INSN itself.  */
06818       PUT_MODE (tmp, SImode);
06819       LABEL_NUSES (JUMP_LABEL (tmp))++;
06820       location = NEXT_INSN (location);
06821     }
06822 
06823         /* Emit a BARRIER after the jump.  */
06824         emit_barrier_after (location);
06825         location = NEXT_INSN (location);
06826       }
06827 
06828     /* Emit marker for the end of the branch table.  */
06829     emit_insn_before (gen_end_brtab (), location);
06830     location = NEXT_INSN (location);
06831     emit_barrier_after (location);
06832 
06833     /* Delete the ADDR_VEC or ADDR_DIFF_VEC.  */
06834     delete_insn (insn);
06835   }
06836     }
06837   else
06838     {
06839       /* Sill need an end_brtab insn.  */
06840       insns = get_insns ();
06841       for (insn = insns; insn; insn = NEXT_INSN (insn))
06842   {
06843     /* Find an ADDR_VEC insn.  */
06844     if (GET_CODE (insn) != JUMP_INSN
06845         || (GET_CODE (PATTERN (insn)) != ADDR_VEC
06846       && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC))
06847       continue;
06848 
06849     /* Now generate markers for the beginning and end of the
06850        branch table.  */
06851     emit_insn_before (gen_begin_brtab (), insn);
06852     emit_insn_after (gen_end_brtab (), insn);
06853   }
06854     }
06855 }
06856 
06857 /* The PA has a number of odd instructions which can perform multiple
06858    tasks at once.  On first generation PA machines (PA1.0 and PA1.1)
06859    it may be profitable to combine two instructions into one instruction
06860    with two outputs.  It's not profitable PA2.0 machines because the
06861    two outputs would take two slots in the reorder buffers.
06862 
06863    This routine finds instructions which can be combined and combines
06864    them.  We only support some of the potential combinations, and we
06865    only try common ways to find suitable instructions.
06866 
06867       * addb can add two registers or a register and a small integer
06868       and jump to a nearby (+-8k) location.  Normally the jump to the
06869       nearby location is conditional on the result of the add, but by
06870       using the "true" condition we can make the jump unconditional.
06871       Thus addb can perform two independent operations in one insn.
06872 
06873       * movb is similar to addb in that it can perform a reg->reg
06874       or small immediate->reg copy and jump to a nearby (+-8k location).
06875 
06876       * fmpyadd and fmpysub can perform a FP multiply and either an
06877       FP add or FP sub if the operands of the multiply and add/sub are
06878       independent (there are other minor restrictions).  Note both
06879       the fmpy and fadd/fsub can in theory move to better spots according
06880       to data dependencies, but for now we require the fmpy stay at a
06881       fixed location.
06882 
06883       * Many of the memory operations can perform pre & post updates
06884       of index registers.  GCC's pre/post increment/decrement addressing
06885       is far too simple to take advantage of all the possibilities.  This
06886       pass may not be suitable since those insns may not be independent.
06887 
06888       * comclr can compare two ints or an int and a register, nullify
06889       the following instruction and zero some other register.  This
06890       is more difficult to use as it's harder to find an insn which
06891       will generate a comclr than finding something like an unconditional
06892       branch.  (conditional moves & long branches create comclr insns).
06893 
06894       * Most arithmetic operations can conditionally skip the next
06895       instruction.  They can be viewed as "perform this operation
06896       and conditionally jump to this nearby location" (where nearby
06897       is an insns away).  These are difficult to use due to the
06898       branch length restrictions.  */
06899 
06900 static void
06901 pa_combine_instructions (insns)
06902      rtx insns ATTRIBUTE_UNUSED;
06903 {
06904   rtx anchor, new;
06905 
06906   /* This can get expensive since the basic algorithm is on the
06907      order of O(n^2) (or worse).  Only do it for -O2 or higher
06908      levels of optimization.  */
06909   if (optimize < 2)
06910     return;
06911 
06912   /* Walk down the list of insns looking for "anchor" insns which
06913      may be combined with "floating" insns.  As the name implies,
06914      "anchor" instructions don't move, while "floating" insns may
06915      move around.  */
06916   new = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, NULL_RTX, NULL_RTX));
06917   new = make_insn_raw (new);
06918 
06919   for (anchor = get_insns (); anchor; anchor = NEXT_INSN (anchor))
06920     {
06921       enum attr_pa_combine_type anchor_attr;
06922       enum attr_pa_combine_type floater_attr;
06923 
06924       /* We only care about INSNs, JUMP_INSNs, and CALL_INSNs.
06925    Also ignore any special USE insns.  */
06926       if ((GET_CODE (anchor) != INSN
06927     && GET_CODE (anchor) != JUMP_INSN
06928     && GET_CODE (anchor) != CALL_INSN)
06929     || GET_CODE (PATTERN (anchor)) == USE
06930     || GET_CODE (PATTERN (anchor)) == CLOBBER
06931     || GET_CODE (PATTERN (anchor)) == ADDR_VEC
06932     || GET_CODE (PATTERN (anchor)) == ADDR_DIFF_VEC)
06933   continue;
06934 
06935       anchor_attr = get_attr_pa_combine_type (anchor);
06936       /* See if anchor is an insn suitable for combination.  */
06937       if (anchor_attr == PA_COMBINE_TYPE_FMPY
06938     || anchor_attr == PA_COMBINE_TYPE_FADDSUB
06939     || (anchor_attr == PA_COMBINE_TYPE_UNCOND_BRANCH
06940         && ! forward_branch_p (anchor)))
06941   {
06942     rtx floater;
06943 
06944     for (floater = PREV_INSN (anchor);
06945          floater;
06946          floater = PREV_INSN (floater))
06947       {
06948         if (GET_CODE (floater) == NOTE
06949       || (GET_CODE (floater) == INSN
06950           && (GET_CODE (PATTERN (floater)) == USE
06951         || GET_CODE (PATTERN (floater)) == CLOBBER)))
06952     continue;
06953 
06954         /* Anything except a regular INSN will stop our search.  */
06955         if (GET_CODE (floater) != INSN
06956       || GET_CODE (PATTERN (floater)) == ADDR_VEC
06957       || GET_CODE (PATTERN (floater)) == ADDR_DIFF_VEC)
06958     {
06959       floater = NULL_RTX;
06960       break;
06961     }
06962 
06963         /* See if FLOATER is suitable for combination with the
06964      anchor.  */
06965         floater_attr = get_attr_pa_combine_type (floater);
06966         if ((anchor_attr == PA_COMBINE_TYPE_FMPY
06967        && floater_attr == PA_COMBINE_TYPE_FADDSUB)
06968       || (anchor_attr == PA_COMBINE_TYPE_FADDSUB
06969           && floater_attr == PA_COMBINE_TYPE_FMPY))
06970     {
06971       /* If ANCHOR and FLOATER can be combined, then we're
06972          done with this pass.  */
06973       if (pa_can_combine_p (new, anchor, floater, 0,
06974           SET_DEST (PATTERN (floater)),
06975           XEXP (SET_SRC (PATTERN (floater)), 0),
06976           XEXP (SET_SRC (PATTERN (floater)), 1)))
06977         break;
06978     }
06979 
06980         else if (anchor_attr == PA_COMBINE_TYPE_UNCOND_BRANCH
06981            && floater_attr == PA_COMBINE_TYPE_ADDMOVE)
06982     {
06983       if (GET_CODE (SET_SRC (PATTERN (floater))) == PLUS)
06984         {
06985           if (pa_can_combine_p (new, anchor, floater, 0,
06986               SET_DEST (PATTERN (floater)),
06987           XEXP (SET_SRC (PATTERN (floater)), 0),
06988           XEXP (SET_SRC (PATTERN (floater)), 1)))
06989       break;
06990         }
06991       else
06992         {
06993           if (pa_can_combine_p (new, anchor, floater, 0,
06994               SET_DEST (PATTERN (floater)),
06995               SET_SRC (PATTERN (floater)),
06996               SET_SRC (PATTERN (floater))))
06997       break;
06998         }
06999     }
07000       }
07001 
07002     /* If we didn't find anything on the backwards scan try forwards.  */
07003     if (!floater
07004         && (anchor_attr == PA_COMBINE_TYPE_FMPY
07005       || anchor_attr == PA_COMBINE_TYPE_FADDSUB))
07006       {
07007         for (floater = anchor; floater; floater = NEXT_INSN (floater))
07008     {
07009       if (GET_CODE (floater) == NOTE
07010           || (GET_CODE (floater) == INSN
07011         && (GET_CODE (PATTERN (floater)) == USE
07012             || GET_CODE (PATTERN (floater)) == CLOBBER)))
07013 
07014         continue;
07015 
07016       /* Anything except a regular INSN will stop our search.  */
07017       if (GET_CODE (floater) != INSN
07018           || GET_CODE (PATTERN (floater)) == ADDR_VEC
07019           || GET_CODE (PATTERN (floater)) == ADDR_DIFF_VEC)
07020         {
07021           floater = NULL_RTX;
07022           break;
07023         }
07024 
07025       /* See if FLOATER is suitable for combination with the
07026          anchor.  */
07027       floater_attr = get_attr_pa_combine_type (floater);
07028       if ((anchor_attr == PA_COMBINE_TYPE_FMPY
07029            && floater_attr == PA_COMBINE_TYPE_FADDSUB)
07030           || (anchor_attr == PA_COMBINE_TYPE_FADDSUB
07031         && floater_attr == PA_COMBINE_TYPE_FMPY))
07032         {
07033           /* If ANCHOR and FLOATER can be combined, then we're
07034        done with this pass.  */
07035           if (pa_can_combine_p (new, anchor, floater, 1,
07036               SET_DEST (PATTERN (floater)),
07037               XEXP (SET_SRC (PATTERN (floater)),
07038               0),
07039               XEXP (SET_SRC (PATTERN (floater)),
07040               1)))
07041       break;
07042         }
07043     }
07044       }
07045 
07046     /* FLOATER will be nonzero if we found a suitable floating
07047        insn for combination with ANCHOR.  */
07048     if (floater
07049         && (anchor_attr == PA_COMBINE_TYPE_FADDSUB
07050       || anchor_attr == PA_COMBINE_TYPE_FMPY))
07051       {
07052         /* Emit the new instruction and delete the old anchor.  */
07053         emit_insn_before (gen_rtx_PARALLEL
07054         (VOIDmode,
07055          gen_rtvec (2, PATTERN (anchor),
07056               PATTERN (floater))),
07057         anchor);
07058 
07059         PUT_CODE (anchor, NOTE);
07060         NOTE_LINE_NUMBER (anchor) = NOTE_INSN_DELETED;
07061         NOTE_SOURCE_FILE (anchor) = 0;
07062 
07063         /* Emit a special USE insn for FLOATER, then delete
07064      the floating insn.  */
07065         emit_insn_before (gen_rtx_USE (VOIDmode, floater), floater);
07066         delete_insn (floater);
07067 
07068         continue;
07069       }
07070     else if (floater
07071        && anchor_attr == PA_COMBINE_TYPE_UNCOND_BRANCH)
07072       {
07073         rtx temp;
07074         /* Emit the new_jump instruction and delete the old anchor.  */
07075         temp
07076     = emit_jump_insn_before (gen_rtx_PARALLEL
07077            (VOIDmode,
07078             gen_rtvec (2, PATTERN (anchor),
07079                  PATTERN (floater))),
07080            anchor);
07081 
07082         JUMP_LABEL (temp) = JUMP_LABEL (anchor);
07083         PUT_CODE (anchor, NOTE);
07084         NOTE_LINE_NUMBER (anchor) = NOTE_INSN_DELETED;
07085         NOTE_SOURCE_FILE (anchor) = 0;
07086 
07087         /* Emit a special USE insn for FLOATER, then delete
07088      the floating insn.  */
07089         emit_insn_before (gen_rtx_USE (VOIDmode, floater), floater);
07090         delete_insn (floater);
07091         continue;
07092       }
07093   }
07094     }
07095 }
07096 
07097 static int
07098 pa_can_combine_p (new, anchor, floater, reversed, dest, src1, src2)
07099      rtx new, anchor, floater;
07100      int reversed;
07101      rtx dest, src1, src2;
07102 {
07103   int insn_code_number;
07104   rtx start, end;
07105 
07106   /* Create a PARALLEL with the patterns of ANCHOR and
07107      FLOATER, try to recognize it, then test constraints
07108      for the resulting pattern.
07109 
07110      If the pattern doesn't match or the constraints
07111      aren't met keep searching for a suitable floater
07112      insn.  */
07113   XVECEXP (PATTERN (new), 0, 0) = PATTERN (anchor);
07114   XVECEXP (PATTERN (new), 0, 1) = PATTERN (floater);
07115   INSN_CODE (new) = -1;
07116   insn_code_number = recog_memoized (new);
07117   if (insn_code_number < 0
07118       || (extract_insn (new), ! constrain_operands (1)))
07119     return 0;
07120 
07121   if (reversed)
07122     {
07123       start = anchor;
07124       end = floater;
07125     }
07126   else
07127     {
07128       start = floater;
07129       end = anchor;
07130     }
07131 
07132   /* There's up to three operands to consider.  One
07133      output and two inputs.
07134 
07135      The output must not be used between FLOATER & ANCHOR
07136      exclusive.  The inputs must not be set between
07137      FLOATER and ANCHOR exclusive.  */
07138 
07139   if (reg_used_between_p (dest, start, end))
07140     return 0;
07141 
07142   if (reg_set_between_p (src1, start, end))
07143     return 0;
07144 
07145   if (reg_set_between_p (src2, start, end))
07146     return 0;
07147 
07148   /* If we get here, then everything is good.  */
07149   return 1;
07150 }
07151 
07152 /* Return nonzero if references for INSN are delayed.
07153 
07154    Millicode insns are actually function calls with some special
07155    constraints on arguments and register usage.
07156 
07157    Millicode calls always expect their arguments in the integer argument
07158    registers, and always return their result in %r29 (ret1).  They
07159    are expected to clobber their arguments, %r1, %r29, and the return
07160    pointer which is %r31 on 32-bit and %r2 on 64-bit, and nothing else.
07161 
07162    This function tells reorg that the references to arguments and
07163    millicode calls do not appear to happen until after the millicode call.
07164    This allows reorg to put insns which set the argument registers into the
07165    delay slot of the millicode call -- thus they act more like traditional
07166    CALL_INSNs.
07167 
07168    Note we can not consider side effects of the insn to be delayed because
07169    the branch and link insn will clobber the return pointer.  If we happened
07170    to use the return pointer in the delay slot of the call, then we lose.
07171 
07172    get_attr_type will try to recognize the given insn, so make sure to
07173    filter out things it will not accept -- SEQUENCE, USE and CLOBBER insns
07174    in particular.  */
07175 int
07176 insn_refs_are_delayed (insn)
07177      rtx insn;
07178 {
07179   return ((GET_CODE (insn) == INSN
07180      && GET_CODE (PATTERN (insn)) != SEQUENCE
07181      && GET_CODE (PATTERN (insn)) != USE
07182      && GET_CODE (PATTERN (insn)) != CLOBBER
07183      && get_attr_type (insn) == TYPE_MILLI));
07184 }
07185 
07186 /* Return the location of a parameter that is passed in a register or NULL
07187    if the parameter has any component that is passed in memory.
07188 
07189    This is new code and will be pushed to into the net sources after
07190    further testing.
07191 
07192    ??? We might want to restructure this so that it looks more like other
07193    ports.  */
07194 rtx
07195 function_arg (cum, mode, type, named, incoming)
07196      CUMULATIVE_ARGS *cum;
07197      enum machine_mode mode;
07198      tree type;
07199      int named ATTRIBUTE_UNUSED;
07200      int incoming;
07201 {
07202   int max_arg_words = (TARGET_64BIT ? 8 : 4);
07203   int fpr_reg_base;
07204   int gpr_reg_base;
07205   rtx retval;
07206 
07207   if (! TARGET_64BIT)
07208     {
07209       /* If this arg would be passed partially or totally on the stack, then
07210          this routine should return zero.  FUNCTION_ARG_PARTIAL_NREGS will
07211          handle arguments which are split between regs and stack slots if
07212          the ABI mandates split arguments.  */
07213       if (cum->words + FUNCTION_ARG_SIZE (mode, type) > max_arg_words
07214           || mode == VOIDmode)
07215   return NULL_RTX;
07216     }
07217   else
07218     {
07219       int offset = 0;
07220       if (FUNCTION_ARG_SIZE (mode, type) > 1 && (cum->words & 1))
07221   offset = 1;
07222       if (cum->words + offset >= max_arg_words
07223     || mode == VOIDmode)
07224   return NULL_RTX;
07225     }
07226 
07227   /* The 32bit ABIs and the 64bit ABIs are rather different,
07228      particularly in their handling of FP registers.  We might
07229      be able to cleverly share code between them, but I'm not
07230      going to bother in the hope that splitting them up results
07231      in code that is more easily understood.
07232 
07233      The 64bit code probably is very wrong for structure passing.  */
07234   if (TARGET_64BIT)
07235     {
07236       /* Advance the base registers to their current locations.
07237 
07238          Remember, gprs grow towards smaller register numbers while
07239    fprs grow to higher register numbers.  Also remember FP regs
07240    are always 4 bytes wide, while the size of an integer register
07241    varies based on the size of the target word.  */
07242       gpr_reg_base = 26 - cum->words;
07243       fpr_reg_base = 32 + cum->words;
07244 
07245       /* If the argument is more than a word long, then we need to align
07246    the base registers.  Same caveats as above.  */
07247       if (FUNCTION_ARG_SIZE (mode, type) > 1)
07248   {
07249     if (mode != BLKmode)
07250       {
07251         /* First deal with alignment of the doubleword.  */
07252         gpr_reg_base -= (cum->words & 1);
07253 
07254         /* This seems backwards, but it is what HP specifies.  We need
07255            gpr_reg_base to point to the smaller numbered register of
07256