OSDN Git Service

Add setjmp/longjmp exception handling.
[pf3gnuchains/gcc-fork.git] / gcc / config / pa / pa.h
index 89697db..30a070b 100644 (file)
@@ -78,6 +78,10 @@ extern int target_flags;
 /* Allow unconditional jumps in the delay slots of call instructions.  */
 #define TARGET_JUMP_IN_DELAY (target_flags & 8)
 
+/* Optimize for space.  Currently this only turns on out of line
+   prologues and epilogues.  */
+#define TARGET_SPACE (target_flags & 16)
+
 /* Disable indexed addressing modes.  */
 
 #define TARGET_DISABLE_INDEXING (target_flags & 32)
@@ -105,6 +109,9 @@ extern int target_flags;
    in shared libraries on hpux10.  */
 #define TARGET_LONG_LOAD_STORE (target_flags & 512)
 
+/* Use a faster sequence for indirect calls.  */
+#define TARGET_FAST_INDIRECT_CALLS (target_flags & 1024)
+
 /* Macro to define tables used to set the flags.
    This is a list in braces of pairs in braces,
    each pair being { "NAME", VALUE }
@@ -119,9 +126,11 @@ extern int target_flags;
    {"disable-fpregs", 2},      \
    {"no-disable-fpregs", -2},  \
    {"no-space-regs", 4},       \
-   {"space-regs", -4},\
+   {"space-regs", -4},         \
    {"jump-in-delay", 8},       \
    {"no-jump-in-delay", -8},   \
+   {"space", 16},              \
+   {"no-space", -16},          \
    {"disable-indexing", 32},   \
    {"no-disable-indexing", -32},\
    {"portable-runtime", 64},   \
@@ -132,13 +141,19 @@ extern int target_flags;
    {"no-soft-float", -256},    \
    {"long-load-store", 512},   \
    {"no-long-load-store", -512},\
+   {"fast-indirect-calls", 1024},\
+   {"no-fast-indirect-calls", -1024},\
    {"linker-opt", 0},          \
-   { "", TARGET_DEFAULT}}
+   { "", TARGET_DEFAULT | TARGET_CPU_DEFAULT}}
 
 #ifndef TARGET_DEFAULT
 #define TARGET_DEFAULT 0x88            /* TARGET_GAS + TARGET_JUMP_IN_DELAY */
 #endif
 
+#ifndef TARGET_CPU_DEFAULT
+#define TARGET_CPU_DEFAULT 0
+#endif
+
 #define TARGET_OPTIONS                 \
 {                                      \
   { "schedule=",       &pa_cpu_string }\
@@ -206,13 +221,13 @@ extern int target_flags;
 #define DBX_OUTPUT_MAIN_SOURCE_FILE_END(FILE, FILENAME) \
   text_section (); \
   if (!TARGET_PORTABLE_RUNTIME) \
-    fputs ("\t.NSUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY\n", FILE); \
+    fputs ("\t.SPACE $TEXT$\n\t.NSUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY\n", FILE); \
   else \
     fprintf (FILE, "%s\n", TEXT_SECTION_ASM_OP); \
   fprintf (FILE,                                                       \
           "\t.stabs \"\",%d,0,0,L$text_end0000\nL$text_end0000:\n", N_SO)
 
-#if (TARGET_DEFAULT & 1) == 0
+#if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & 1) == 0
 #define CPP_SPEC "%{msnake:-D__hp9000s700 -D_PA_RISC1_1}\
  %{mpa-risc-1-1:-D__hp9000s700 -D_PA_RISC1_1}\
  %{!ansi: -D_HPUX_SOURCE -D_HIUX_SOURCE}"
@@ -231,9 +246,6 @@ extern int target_flags;
 #define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}"
 #endif
 
-/* Allow $ in identifiers.  */
-#define DOLLARS_IN_IDENTIFIERS 2
-
 /* Make gcc agree with <machine/ansi.h> */
 
 #define SIZE_TYPE "unsigned int"
@@ -254,15 +266,48 @@ extern int target_flags;
 /* HPUX has a program 'chatr' to list the dependencies of dynamically
    linked executables and shared libraries.  */
 #define LDD_SUFFIX "chatr"
-/* look for lines like "dynamic   /usr/lib/X11R5/libX11.sl".  */
+/* Look for lines like "dynamic   /usr/lib/X11R5/libX11.sl"
+   or "static    /usr/lib/X11R5/libX11.sl". 
+
+   HPUX 10.20 also has lines like "static branch prediction ..."
+   so we filter that out explcitly.
+
+   We also try to bound our search for libraries with marker
+   lines.  What a pain.  */
 #define PARSE_LDD_OUTPUT(PTR)                                  \
 do {                                                           \
+  static int in_shlib_list = 0;                                        \
   while (*PTR == ' ') PTR++;                                   \
-  if (strncmp (PTR, "dynamic", sizeof ("dynamic") - 1) == 0)   \
+  if (strncmp (PTR, "shared library list:",                    \
+              sizeof ("shared library list:") - 1) == 0)       \
+    {                                                          \
+      PTR = 0;                                                 \
+      in_shlib_list = 1;                                       \
+    }                                                          \
+  else if (strncmp (PTR, "shared library binding:",            \
+                   sizeof ("shared library binding:") - 1) == 0)\
+    {                                                          \
+      PTR = 0;                                                 \
+      in_shlib_list = 0;                                       \
+    }                                                          \
+  else if (strncmp (PTR, "static branch prediction disabled",  \
+                   sizeof ("static branch prediction disabled") - 1) == 0)\
+    {                                                          \
+      PTR = 0;                                                 \
+      in_shlib_list = 0;                                       \
+    }                                                          \
+  else if (in_shlib_list                                       \
+          &&  strncmp (PTR, "dynamic", sizeof ("dynamic") - 1) == 0) \
     {                                                          \
       PTR += sizeof ("dynamic") - 1;                           \
       while (*p == ' ') PTR++;                                 \
     }                                                          \
+  else if (in_shlib_list                                       \
+          && strncmp (PTR, "static", sizeof ("static") - 1) == 0) \
+    {                                                          \
+      PTR += sizeof ("static") - 1;                            \
+      while (*p == ' ') PTR++;                                 \
+    }                                                          \
   else                                                         \
     PTR = 0;                                                   \
 } while (0)
@@ -554,9 +599,9 @@ do {                                                                \
 /* Base register for access to local variables of the function.  */
 #define FRAME_POINTER_REGNUM 3
 
-/* Value should be nonzero if functions must have frame pointers. */
-#define FRAME_POINTER_REQUIRED (current_function_calls_alloca)
-
+/* Value should be nonzero if functions must have frame pointers.  */
+#define FRAME_POINTER_REQUIRED \
+  (current_function_calls_alloca)
 
 /* C statement to store the difference between the frame pointer
    and the stack pointer values immediately after the function prologue.
@@ -587,7 +632,7 @@ do {                                                                \
 /* SOM ABI says that objects larger than 64 bits are returned in memory.  */
 #define DEFAULT_PCC_STRUCT_RETURN 0
 #define RETURN_IN_MEMORY(TYPE) \
-  (int_size_in_bytes (TYPE) > 8 || TREE_ADDRESSABLE (TYPE))
+  (int_size_in_bytes (TYPE) > 8)
 
 /* Register in which address to store a structure value
    is passed to a function.  */
@@ -857,7 +902,7 @@ enum reg_class { NO_REGS, R1_REGS, GENERAL_REGS, FP_REGS, GENERAL_OR_FP_REGS,
    if any, which holds the structure-value-address).
    Thus 4 or more means all following args should go on the stack.  */
 
-struct hppa_args {int words, nargs_prototype; };
+struct hppa_args {int words, nargs_prototype, indirect; };
 
 #define CUMULATIVE_ARGS struct hppa_args
 
@@ -865,8 +910,9 @@ struct hppa_args {int words, nargs_prototype; };
    for a call to a function whose data type is FNTYPE.
    For a library call, FNTYPE is 0.  */
 
-#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME) \
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \
   (CUM).words = 0,                                                     \
+  (CUM).indirect = INDIRECT,                                           \
   (CUM).nargs_prototype = (FNTYPE && TYPE_ARG_TYPES (FNTYPE)           \
                           ? (list_length (TYPE_ARG_TYPES (FNTYPE)) - 1 \
                              + (TYPE_MODE (TREE_TYPE (FNTYPE)) == BLKmode \
@@ -876,10 +922,11 @@ struct hppa_args {int words, nargs_prototype; };
 
 
 /* Similar, but when scanning the definition of a procedure.  We always
-   set NARGS_PROTOTYPE large so we never return an EXPR_LIST.  */
+   set NARGS_PROTOTYPE large so we never return a PARALLEL.  */
 
 #define INIT_CUMULATIVE_INCOMING_ARGS(CUM,FNTYPE,IGNORE) \
   (CUM).words = 0,                             \
+  (CUM).indirect = 0,                          \
   (CUM).nargs_prototype = 1000
 
 /* Figure out the size in words of the function argument. */
@@ -957,13 +1004,13 @@ struct hppa_args {int words, nargs_prototype; };
       || (CUM).nargs_prototype > 0)                                    \
       ? gen_rtx (REG, (MODE),                                          \
                 (FUNCTION_ARG_SIZE ((MODE), (TYPE)) > 1                \
-                 ? (((!current_call_is_indirect                        \
+                 ? (((!(CUM).indirect                                  \
                       || TARGET_PORTABLE_RUNTIME)                      \
                      && (MODE) == DFmode                               \
                      && ! TARGET_SOFT_FLOAT)                           \
                     ? ((CUM).words ? 38 : 34)                          \
                     : ((CUM).words ? 23 : 25))                         \
-                 : (((!current_call_is_indirect                        \
+                 : (((!(CUM).indirect                                  \
                       || TARGET_PORTABLE_RUNTIME)                      \
                      && (MODE) == SFmode                               \
                      && ! TARGET_SOFT_FLOAT)                           \
@@ -972,16 +1019,23 @@ struct hppa_args {int words, nargs_prototype; };
                                                              (TYPE))))))\
    /* We are calling a non-prototyped function with floating point     \
       arguments using the portable conventions.  */                    \
-   : gen_rtx (EXPR_LIST, VOIDmode,                                     \
-             gen_rtx (REG, (MODE),                                     \
-                      (FUNCTION_ARG_SIZE ((MODE), (TYPE)) > 1          \
-                       ? ((CUM).words ? 38 : 34)                       \
-                       : (32 + 2 * (CUM).words))),                     \
-             gen_rtx (REG, (MODE),                                     \
-                      (FUNCTION_ARG_SIZE ((MODE), (TYPE)) > 1          \
-                       ? ((CUM).words ? 23 : 25)                       \
-                       : (27 - (CUM).words - FUNCTION_ARG_SIZE ((MODE),\
-                                                                (TYPE)))))) \
+   : gen_rtx (PARALLEL, (MODE),                                                \
+             gen_rtvec                                                 \
+             (2,                                                       \
+              gen_rtx (EXPR_LIST, VOIDmode,                            \
+                       gen_rtx (REG, (MODE),                           \
+                                (FUNCTION_ARG_SIZE ((MODE), (TYPE)) > 1 \
+                                 ? ((CUM).words ? 38 : 34)             \
+                                 : (32 + 2 * (CUM).words))),           \
+                       const0_rtx),                                    \
+              gen_rtx (EXPR_LIST, VOIDmode,                            \
+                       gen_rtx (REG, (MODE),                           \
+                                (FUNCTION_ARG_SIZE ((MODE), (TYPE)) > 1 \
+                                 ? ((CUM).words ? 23 : 25)             \
+                                 : (27 - (CUM).words -                 \
+                                    FUNCTION_ARG_SIZE ((MODE),         \
+                                                       (TYPE))))),     \
+                       const0_rtx)))                                   \
   /* Pass this parameter in the stack.  */                             \
   : 0)
 
@@ -1025,6 +1079,18 @@ extern enum cmp_type hppa_branch_type;
        fprintf (FILE, ",ARGW%d=FR", (ARG1));} while (0)
 #endif
 
+#define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) \
+{ char *my_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (THUNK_FNDECL)); \
+  char *target_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (FUNCTION)); \
+  output_function_prologue (FILE, 0); \
+  if (VAL_14_BITS_P (DELTA)) \
+    fprintf (FILE, "\tb %s\n\tldo %d(%%r26),%%r26\n", target_name, DELTA); \
+  else \
+    fprintf (FILE, "\taddil L%%%d,%r26\n\tb %s\n\tldo R%%%d(%%r1),%%r26\n", \
+            DELTA, target_name, DELTA); \
+  fprintf (FILE, "\n\t.EXIT\n\t.PROCEND\n"); \
+}
+
 #define ASM_OUTPUT_FUNCTION_PREFIX(FILE, NAME) \
   {                                                                    \
     char *name;                                                                \
@@ -1085,7 +1151,7 @@ extern enum cmp_type hppa_branch_type;
                     /* Passing structs by invisible reference uses     \
                        one general register.  */                       \
                     if (arg_size > 2                                   \
-                        || TYPE_NEEDS_CONSTRUCTING (DECL_ARG_TYPE (parm)))\
+                        || TREE_ADDRESSABLE (DECL_ARG_TYPE (parm)))    \
                       arg_size = 1;                                    \
                     if (arg_size == 2 && i <= 2)                       \
                       {                                                \
@@ -1336,13 +1402,28 @@ extern struct rtx_def *hppa_builtin_saveregs ();
   ((C) == 'Q' ?                                                \
    (IS_RELOADING_PSEUDO_P (OP)                         \
     || (GET_CODE (OP) == MEM                           \
-       && memory_address_p (GET_MODE (OP), XEXP (OP, 0))\
-       && ! symbolic_memory_operand (OP, VOIDmode)))   \
+       && (memory_address_p (GET_MODE (OP), XEXP (OP, 0))\
+           || reload_in_progress)                      \
+       && ! symbolic_memory_operand (OP, VOIDmode)     \
+        && !(GET_CODE (XEXP (OP, 0)) == PLUS           \
+            && (GET_CODE (XEXP (XEXP (OP, 0), 0)) == MULT\
+                || GET_CODE (XEXP (XEXP (OP, 0), 1)) == MULT))))\
+   : ((C) == 'R' ?                                     \
+     (GET_CODE (OP) == MEM                             \
+      && GET_CODE (XEXP (OP, 0)) == PLUS               \
+      && (GET_CODE (XEXP (XEXP (OP, 0), 0)) == MULT    \
+         || GET_CODE (XEXP (XEXP (OP, 0), 1)) == MULT) \
+      && (move_operand (OP, GET_MODE (OP))             \
+         || memory_address_p (GET_MODE (OP), XEXP (OP, 0))\
+         || reload_in_progress))                       \
    : ((C) == 'T' ?                                     \
       (GET_CODE (OP) == MEM                            \
        /* Using DFmode forces only short displacements \
          to be recognized as valid in reg+d addresses.  */\
-       && memory_address_p (DFmode, XEXP (OP, 0))) : 0))
+       && memory_address_p (DFmode, XEXP (OP, 0))      \
+       && !(GET_CODE (XEXP (OP, 0)) == PLUS            \
+           && (GET_CODE (XEXP (XEXP (OP, 0), 0)) == MULT\
+               || GET_CODE (XEXP (XEXP (OP, 0), 1)) == MULT))) : 0)))
 
 /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
    and check its validity for a certain class.
@@ -1437,6 +1518,15 @@ extern struct rtx_def *hppa_builtin_saveregs ();
                     || ((MODE) != SFmode && (MODE) != DFmode))) \
                || INT_5_BITS (index)))                 \
          goto ADDR;                                    \
+      if (! TARGET_SOFT_FLOAT                          \
+         && base                                       \
+         && (mode == SFmode || mode == DFmode)         \
+         && GET_CODE (index) == MULT                   \
+         && GET_CODE (XEXP (index, 0)) == REG          \
+         && REG_OK_FOR_BASE_P (XEXP (index, 0))        \
+         && GET_CODE (XEXP (index, 1)) == CONST_INT    \
+         && INTVAL (XEXP (index, 1)) == (mode == SFmode ? 4 : 8))\
+       goto ADDR;                                      \
     }                                                  \
   else if (GET_CODE (X) == LO_SUM                      \
           && GET_CODE (XEXP (X, 0)) == REG             \
@@ -1518,6 +1608,7 @@ extern struct rtx_def *hppa_legitimize_address ();
   (TREE_CODE (DECL) == FUNCTION_DECL                                   \
    || (TREE_CODE (DECL) == VAR_DECL                                    \
        && TREE_READONLY (DECL) && ! TREE_SIDE_EFFECTS (DECL)           \
+       && (! DECL_INITIAL (DECL) || ! reloc_needed (DECL_INITIAL (DECL))) \
        && !flag_pic)                                                   \
    || (*tree_code_type[(int) TREE_CODE (DECL)] == 'c'                  \
        && !(TREE_CODE (DECL) == STRING_CST && flag_writable_strings)))
@@ -1549,6 +1640,26 @@ while (0)
                             1 + (SYMBOL_NAME)[1] == '@'\
                             : (SYMBOL_NAME)[0] == '@'))
 
+/* On hpux10, the linker will give an error if we have a reference
+   in the read-only data section to a symbol defined in a shared
+   library.  Therefore, expressions that might require a reloc can
+   not be placed in the read-only data section.  */
+#define SELECT_SECTION(EXP,RELOC) \
+  if (TREE_CODE (EXP) == VAR_DECL \
+      && TREE_READONLY (EXP) \
+      && !TREE_THIS_VOLATILE (EXP) \
+      && DECL_INITIAL (EXP) \
+      && (DECL_INITIAL (EXP) == error_mark_node \
+          || TREE_CONSTANT (DECL_INITIAL (EXP))) \
+      && !reloc) \
+    readonly_data_section (); \
+  else if (TREE_CODE_CLASS (TREE_CODE (EXP)) == 'c' \
+          && !(TREE_CODE (EXP) == STRING_CST && flag_writable_strings) \
+          && !reloc) \
+    readonly_data_section (); \
+  else \
+    data_section ();
+   
 /* Arghh.  This is used for stuff in the constant pool; this may include
    function addresses on the PA, which during PIC code generation must
    reside in the data space.  Unfortunately, there's no way to determine
@@ -1870,22 +1981,22 @@ do { fputs ("\t.SPACE $PRIVATE$\n\
     {                                                          \
       fputs ("\t.SPACE $TEXT$\n", FILE);                       \
       fprintf (FILE,                                           \
-              "\t.SUBSPA %s,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY,SORT=24\n", \
-              NAME);                                           \
+              "\t.SUBSPA %s%s%s,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY,SORT=24\n",\
+              TARGET_GAS ? "" : "$", NAME, TARGET_GAS ? "" : "$"); \
     }                                                          \
   else if (DECL && TREE_READONLY (DECL))                       \
     {                                                          \
       fputs ("\t.SPACE $TEXT$\n", FILE);                       \
       fprintf (FILE,                                           \
-              "\t.SUBSPA %s,QUAD=0,ALIGN=8,ACCESS=44,SORT=16\n", \
-              NAME);                                           \
+              "\t.SUBSPA %s%s%s,QUAD=0,ALIGN=8,ACCESS=44,SORT=16\n", \
+              TARGET_GAS ? "" : "$", NAME, TARGET_GAS ? "" : "$"); \
     }                                                          \
   else                                                         \
     {                                                          \
       fputs ("\t.SPACE $PRIVATE$\n", FILE);                    \
       fprintf (FILE,                                           \
               "\t.SUBSPA %s,QUAD=1,ALIGN=8,ACCESS=31,SORT=16\n", \
-              NAME);                                           \
+              TARGET_GAS ? "" : "$", NAME, TARGET_GAS ? "" : "$"); \
     }
 
 /* FIXME: HPUX ld generates incorrect GOT entries for "T" fixups
@@ -2057,10 +2168,7 @@ DTORS_SECTION_FUNCTION
 { fputs ("\t.word ", FILE);                    \
   if (function_label_operand (VALUE, VOIDmode) \
       && !TARGET_PORTABLE_RUNTIME)             \
-    fputs ("P%", FILE);                        \
-  if (in_section == in_named           \
-      && ! strcmp (".gcc_except_table", in_named_name))\
-    fputs ("P%", FILE);                        \
+    fputs ("P%", FILE);                                \
   output_addr_const (FILE, (VALUE));           \
   fputs ("\n", FILE);}
 
@@ -2234,6 +2342,8 @@ extern char *output_bb ();
 extern char *output_bvb ();
 extern char *output_dbra ();
 extern char *output_movb ();
+extern char *output_parallel_movb ();
+extern char *output_parallel_addb ();
 extern char *output_return ();
 extern char *output_call ();
 extern char *output_millicode_call ();
@@ -2247,18 +2357,37 @@ extern struct rtx_def *legitimize_pic_address ();
 extern struct rtx_def *gen_cmp_fp ();
 extern void hppa_encode_label ();
 
+/* Declare functions defined in pa.c and used in templates.  */
+
+extern struct rtx_def *return_addr_rtx ();
+
 /* We want __gcc_plt_call to appear in every program built by
    gcc, so we make a reference to it out of __main.
    We use the asm statement to fool the optimizer into not
    removing the dead (but important) initialization of
    REFERENCE.  */
 
-#define DO_GLOBAL_DTORS_BODY \
-do { \
-  extern void __gcc_plt_call (); \
-  void (*reference)() = &__gcc_plt_call; \
-  func_ptr *p; \
-  __asm__ ("" : : "r" (reference)); \
-  for (p = __DTOR_LIST__ + 1; *p; ) \
-    (*p++) (); \
+#define DO_GLOBAL_DTORS_BODY                   \
+do {                                           \
+  extern void __gcc_plt_call ();               \
+  void (*reference)() = &__gcc_plt_call;       \
+  func_ptr *p;                                 \
+  __asm__ ("" : : "r" (reference));            \
+  for (p = __DTOR_LIST__ + 1; *p; )            \
+    (*p++) ();                                 \
 } while (0)
+
+/* Find the return address associated with the frame given by
+   FRAMEADDR.  */
+#define RETURN_ADDR_RTX(COUNT, FRAMEADDR)                               \
+  (return_addr_rtx (COUNT, FRAMEADDR))
+
+/* Used to mask out junk bits from the return address, such as
+   processor state, interrupt status, condition codes and the like.  */
+#define MASK_RETURN_ADDR                                               \
+  /* The privilege level is in the two low order bits, mask em out     \
+     of the return address.  */                                                \
+  (GEN_INT (0xfffffffc))
+
+/* The number of Pmode words for the setjmp buffer.  */
+#define JMP_BUF_SIZE 50