/* 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)
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 }
{"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}, \
{"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 }\
#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}"
#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"
/* 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)
/* 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.
/* 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. */
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
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 \
/* 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. */
|| (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) \
(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)
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; \
/* 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) \
{ \
((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.
|| ((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 \
(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)))
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
{ \
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
{ 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);}
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 ();
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